cosq.c (81151B)
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 * COS Queue Management 8 * Purpose: API to set different cosq, priorities, and scheduler registers. 9 * Based on Draco/Draco 1.5 code 10 */ 11 12 #include <sal/core/libc.h> 13 #include <shared/bsl.h> 14 #include <soc/drv.h> 15 #include <soc/scache.h> 16 #include <soc/firebolt.h> 17 18 #include <bcm/error.h> 19 #include <bcm/cosq.h> 20 21 #include <bcm_int/esw/cosq.h> 22 #include <bcm_int/esw/mbcm.h> 23 #include <bcm_int/esw/firebolt.h> 24 25 #include <bcm_int/esw_dispatch.h> 26 27 #ifdef BCM_WARM_BOOT_SUPPORT 28 #include <bcm_int/esw/switch.h> 29 #endif /* BCM_WARM_BOOT_SUPPORT */ 30 31 /* 32 * MMU Configuration default settings. 33 * These can be overridden at runtime using config properties. 34 * Also see soc/esw/firebolt.c (soc_firebolt_mmu_init) for 35 * one-time XQ settings (HOLCOSPKTSETLIMIT) 36 */ 37 #define MMU_CELL_SIZE 128 /* not overrideable */ 38 #define MMU_FLOW_PERCENT 90 39 #define MMU_FLOW_FANIN 4 40 #define MMU_FLOW_PKTMIN 8 /* not overrideable */ 41 #define MMU_RED_DROP_PERCENT 60 42 #define MMU_YELLOW_DROP_PERCENT 80 43 #define MMU_STATIC_BYTES (1536 * 1) 44 #define MMU_STATIC_PERCENT 50 /* not used if STATIC_BYTES set */ 45 #define MMU_RESET_BYTES (1536 * 2) 46 #define MMU_RESET_MIN_PERCENT 50 /* not overrideable */ 47 #define MMU_OVERCOMMIT 1 /* non-stack dynamic cell overcommit */ 48 #define MMU_OVERCOMMIT_STACK 2 /* stack dynamic cell overcommit */ 49 50 #if defined(BCM_FIREBOLT_SUPPORT) 51 52 static int _num_cosq[SOC_MAX_NUM_DEVICES]; 53 54 #define FB_DRR_KBYTES (1) 55 #define FB_DRR_MBYTES (1024) 56 #define FB_DRR_WEIGHT_MAX 0xf 57 #define FB_WRR_WEIGHT_MAX 0xf 58 59 static int drr_weight_to_kbytes[FB_DRR_WEIGHT_MAX + 1] = { 60 /* Weight Kbytes */ 61 /* 0 */ 0 * FB_DRR_KBYTES, /* 0K bytes - pure priority scheduling */ 62 /* 1 */ 10 * FB_DRR_KBYTES, /* 10K bytes */ 63 /* 2 */ 20 * FB_DRR_KBYTES, /* 20K bytes */ 64 /* 3 */ 40 * FB_DRR_KBYTES, /* 40K bytes */ 65 /* 4 */ 80 * FB_DRR_KBYTES, /* 80K bytes */ 66 /* 5 */ 160 * FB_DRR_KBYTES, /* 160K bytes */ 67 /* 6 */ 320 * FB_DRR_KBYTES, /* 320K bytes */ 68 /* 7 */ 640 * FB_DRR_KBYTES, /* 640K bytes */ 69 /* 8 */ 1280 * FB_DRR_KBYTES, /* 1280K bytes */ 70 /* 9 */ 2560 * FB_DRR_KBYTES, /* 2560K bytes */ 71 /* 10 */ 5120 * FB_DRR_KBYTES, /* 5120K bytes */ 72 /* 11 */ 10 * FB_DRR_MBYTES, /* 10M bytes */ 73 /* 12 */ 20 * FB_DRR_MBYTES, /* 20M bytes */ 74 /* 13 */ 40 * FB_DRR_MBYTES, /* 40M bytes */ 75 /* 14 */ 80 * FB_DRR_MBYTES, /* 80M bytes */ 76 /* 15 */ 160 * FB_DRR_MBYTES /* 160M bytes */ 77 }; 78 79 #if defined(BCM_RAPTOR_SUPPORT) 80 81 #define BCM_MTU_QUANTA_ID_COUNT 4 82 83 static int MTU_Quanta[BCM_MTU_QUANTA_ID_COUNT] = { 84 2 * FB_DRR_KBYTES, /* Quanta of 2048 bytes */ 85 4 * FB_DRR_KBYTES, /* Quanta of 4096 bytes */ 86 8 * FB_DRR_KBYTES, /* Quanta of 8192 bytes */ 87 16 * FB_DRR_KBYTES /* Quanta of 16384 bytes */ 88 }; 89 90 #endif /* defined(BCM_RAPTOR_SUPPORT) */ 91 92 #if defined(BCM_FIREBOLT2_SUPPORT) 93 #define BCM_FB2_MTU_QUANTA_SMALL 2 94 #define BCM_FB2_MTU_QUANTA_LARGE 16 95 #define BCM_FB2_COS_WEIGHT_MAX 0xff 96 #define BCM_FB2_CNG_CELL_LIMIT_GRANULARITY 8 97 #define BCM_FB2_CNG_CELL_LIMIT_MAX 0x1ffc 98 #endif 99 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_RAPTOR_SUPPORT) 100 #define BCM_FB2_CNG_PKT_LIMIT_GRANULARITY 4 101 #endif 102 103 #undef FB_DRR_KBYTES 104 #undef FB_DRR_MBYTES 105 106 /* 107 * Convert the number of kbytes (1024 bytes) that can transmtted in one run 108 * to weight encoding as per table above 109 */ 110 static int 111 _bcm_fb_cos_drr_kbytes_to_weight(int kbytes) 112 { 113 int weight; 114 for (weight = 0; weight <= FB_DRR_WEIGHT_MAX; weight++) { 115 if (kbytes <= drr_weight_to_kbytes[weight]) { 116 break; 117 } 118 } 119 120 if (weight > FB_DRR_WEIGHT_MAX) { 121 weight = FB_DRR_WEIGHT_MAX; 122 } 123 124 return weight; 125 } 126 127 #if defined(BCM_RAPTOR_SUPPORT) || defined(BCM_FIREBOLT2_SUPPORT) 128 #define BCM_COS_WEIGHT_MAX 0x7f 129 130 static int 131 _bcm_cos_max_weight(const int weight[]) 132 { 133 int i, max_weight = 0; 134 135 /* find max weight */ 136 for (i = 0; i < 8; i++ ) { 137 if (max_weight < weight[i]) { 138 max_weight = weight[i]; 139 } 140 } 141 142 return max_weight; 143 } 144 #endif 145 146 #if defined(BCM_RAPTOR_SUPPORT) 147 /* 148 * Calculates the Quanta needed for COS according to its weight 149 */ 150 static int 151 _bcm_rp_cos_drr_weights_to_quanta(const int weight[]) 152 { 153 int i, max_weight = 0; 154 155 max_weight = _bcm_cos_max_weight(weight); 156 157 /* Search for the right quanta for max_wight*/ 158 for (i = 0; i < BCM_MTU_QUANTA_ID_COUNT; i++ ) { 159 if (max_weight <= MTU_Quanta[i] * BCM_COS_WEIGHT_MAX) { 160 return i; /* Right Quanta was found */ 161 } 162 } 163 164 return -1; /* In case of too big weight return negative value */ 165 } 166 167 /* 168 * Convert the number of kbytes (1024 bytes) that can transmtted in one run 169 * to weight encoding for Raptor 170 */ 171 static int 172 _bcm_rp_cos_drr_kbytes_to_weight(int kbytes, int MTUQuantaSel) 173 { 174 int cos_weight = 0; 175 int weight_found = FALSE, low_weight_boundary, hi_weight_boundary; 176 177 /* Search for right weight */ 178 low_weight_boundary = 1; 179 hi_weight_boundary = BCM_COS_WEIGHT_MAX; 180 181 /* Boundary conditions */ 182 if (kbytes >= hi_weight_boundary * MTU_Quanta[MTUQuantaSel]) { 183 cos_weight = hi_weight_boundary; 184 weight_found = TRUE; 185 } 186 if (kbytes <= low_weight_boundary * MTU_Quanta[MTUQuantaSel]) { 187 cos_weight = low_weight_boundary; 188 weight_found = TRUE; 189 } 190 191 while (!weight_found) { 192 cos_weight = (hi_weight_boundary + low_weight_boundary) / 2; 193 if (kbytes <= cos_weight * MTU_Quanta[MTUQuantaSel]) { 194 if (kbytes > ((cos_weight - 1) * MTU_Quanta[MTUQuantaSel])) { 195 weight_found = TRUE; 196 } else { 197 hi_weight_boundary = cos_weight; 198 } 199 } else { 200 if (kbytes <= ((cos_weight + 1) * MTU_Quanta[MTUQuantaSel])) { 201 cos_weight++; 202 weight_found = TRUE; 203 } else { 204 low_weight_boundary = cos_weight; 205 } 206 } 207 } /* Here weight should be found */ 208 209 return cos_weight; 210 } 211 212 /* 213 * Convert the encoded weights to number of kbytes that can transmtted 214 * in one run. 215 */ 216 static int 217 _bcm_rp_cos_drr_weight_to_kbytes(int weight, int MTUQuantaSel) 218 { 219 return (weight * MTU_Quanta[MTUQuantaSel]); 220 } 221 #endif /* defined(BCM_RAPTOR_SUPPORT) */ 222 223 /* 224 * Convert the encoded weights to number of kbytes that can transmtted 225 * in one run. 226 */ 227 static int 228 _bcm_fb_cos_drr_weight_to_kbytes(int weight) 229 { 230 assert(weight <= FB_DRR_WEIGHT_MAX); 231 232 return(drr_weight_to_kbytes[weight]); 233 } 234 235 #if defined(BCM_FIREBOLT2_SUPPORT) 236 /* 237 * Calculates the Quanta needed for COS according to its weight 238 */ 239 static int 240 _bcm_fb2_cos_drr_weights_to_quanta(const int weight[]) 241 { 242 int max_weight = 0; 243 244 max_weight = _bcm_cos_max_weight(weight); 245 246 /* Search for the right quanta for max_weight*/ 247 if (max_weight <= (BCM_FB2_MTU_QUANTA_SMALL * BCM_FB2_COS_WEIGHT_MAX)) { 248 return BCM_FB2_MTU_QUANTA_SMALL; 249 } else if (max_weight <= 250 (BCM_FB2_MTU_QUANTA_LARGE * BCM_FB2_COS_WEIGHT_MAX)) { 251 return BCM_FB2_MTU_QUANTA_LARGE; 252 } 253 254 return -1; /* In case of too big weight return negative value */ 255 } 256 257 /* 258 * Convert the number of kbytes (1024 bytes) that can transmtted in one run 259 * to weight encoding for Firebolt2 260 */ 261 static int 262 _bcm_fb2_cos_drr_kbytes_to_weight(int kbytes, int MTUQuanta) 263 { 264 int cos_weight = 0; 265 int weight_found = FALSE, low_weight_boundary, hi_weight_boundary; 266 267 /* Search for right weight */ 268 low_weight_boundary = 1; 269 hi_weight_boundary = BCM_FB2_COS_WEIGHT_MAX; 270 271 /* Boundary conditions */ 272 if (kbytes >= hi_weight_boundary * MTUQuanta) { 273 cos_weight = hi_weight_boundary; 274 weight_found = TRUE; 275 } 276 if (kbytes <= low_weight_boundary * MTUQuanta) { 277 cos_weight = low_weight_boundary; 278 weight_found = TRUE; 279 } 280 281 while (!weight_found) { 282 cos_weight = (hi_weight_boundary + low_weight_boundary) / 2; 283 if (kbytes <= cos_weight * MTUQuanta) { 284 if (kbytes > ((cos_weight - 1) * MTUQuanta)) { 285 weight_found = TRUE; 286 } else { 287 hi_weight_boundary = cos_weight; 288 } 289 } else { 290 if (kbytes <= ((cos_weight + 1) * MTUQuanta)) { 291 cos_weight++; 292 weight_found = TRUE; 293 } else { 294 low_weight_boundary = cos_weight; 295 } 296 } 297 } /* Here weight should be found */ 298 299 return cos_weight; 300 } 301 #endif /* defined(BCM_FIREBOLT2_SUPPORT) */ 302 303 304 #ifdef BCM_WARM_BOOT_SUPPORT 305 306 #define BCM_WB_VERSION_1_0 SOC_SCACHE_VERSION(1,0) 307 #define BCM_WB_DEFAULT_VERSION BCM_WB_VERSION_1_0 308 309 /* 310 * Function: 311 * bcm_fb_cosq_sync 312 * Purpose: 313 * Record COSQ module persistent info for Level 2 Warm Boot. 314 * Parameters: 315 * unit - Unit number. 316 * Returns: 317 * BCM_E_XXX 318 */ 319 int 320 bcm_fb_cosq_sync(int unit) 321 { 322 soc_scache_handle_t scache_handle; 323 uint8 *cosq_scache_ptr; 324 uint32 num_cosq; 325 326 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_COSQ, 0); 327 BCM_IF_ERROR_RETURN 328 (_bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 329 0, &cosq_scache_ptr, 330 BCM_WB_DEFAULT_VERSION, NULL)); 331 332 /* Number COSQ */ 333 num_cosq = _num_cosq[unit]; 334 sal_memcpy(cosq_scache_ptr, &num_cosq, sizeof(num_cosq)); 335 336 return BCM_E_NONE; 337 } 338 339 /* 340 * Function: 341 * _bcm_fb_cosq_reinit 342 * Purpose: 343 * Recover COSQ software state. 344 * Parameters: 345 * unit - Unit number. 346 * Returns: 347 * BCM_E_XXX 348 */ 349 STATIC int 350 _bcm_fb_cosq_reinit(int unit) 351 { 352 int rv; 353 soc_scache_handle_t scache_handle; 354 uint8 *cosq_scache_ptr; 355 uint32 num_cosq; 356 357 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_COSQ, 0); 358 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 359 0, &cosq_scache_ptr, 360 BCM_WB_DEFAULT_VERSION, NULL); 361 362 if (rv == BCM_E_NOT_FOUND) { 363 cosq_scache_ptr = NULL; 364 } else if (BCM_FAILURE(rv)) { 365 return rv; 366 } 367 368 if (cosq_scache_ptr != NULL) { 369 /* Number COSQ */ 370 sal_memcpy(&num_cosq, cosq_scache_ptr, sizeof(num_cosq)); 371 _num_cosq[unit] = num_cosq; 372 373 } else { 374 int cos; 375 uint32 val, csl; 376 377 /* Make best guess */ 378 if (soc_reg_field_valid(unit, LWMCOSCELLSETLIMITr, 379 CELLSETLIMITf)) { 380 for (cos = 0; cos < NUM_COS(unit); cos++) { 381 SOC_IF_ERROR_RETURN 382 (READ_LWMCOSCELLSETLIMITr(unit, REG_PORT_ANY, cos, &val)); 383 csl = soc_reg_field_get(unit, LWMCOSCELLSETLIMITr, 384 val, CELLSETLIMITf); 385 if (csl == 0) { 386 /* No more COSq info for this COS value, so we're done */ 387 break; 388 } 389 } 390 } else { 391 cos = _bcm_esw_cosq_config_property_get(unit); 392 } 393 394 _num_cosq[unit] = cos; 395 } 396 397 return BCM_E_NONE; 398 } 399 #endif /* BCM_WARM_BOOT_SUPPORT */ 400 401 /* 402 * Function: 403 * bcm_fb_cosq_init 404 * Purpose: 405 * Initialize (clear) all COS schedule/mapping state. 406 * Parameters: 407 * unit - StrataSwitch unit number. 408 * Returns: 409 * BCM_E_XXX 410 */ 411 412 int 413 bcm_fb_cosq_init(int unit) 414 { 415 int num_cos; 416 #ifdef BCM_WARM_BOOT_SUPPORT 417 int rv; 418 soc_scache_handle_t scache_handle; 419 uint32 cosq_scache_size; 420 uint8 *cosq_scache_ptr; 421 #endif /* BCM_WARM_BOOT_SUPPORT */ 422 423 #ifdef BCM_WARM_BOOT_SUPPORT 424 /* Warm boot level 2 cache size */ 425 cosq_scache_size = sizeof(uint32); /* Number COSQ */ 426 427 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_COSQ, 0); 428 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, 429 (0 == SOC_WARM_BOOT(unit)), 430 cosq_scache_size, &cosq_scache_ptr, 431 BCM_WB_DEFAULT_VERSION, NULL); 432 if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) { 433 return rv; 434 } 435 436 if (SOC_WARM_BOOT(unit)) { 437 return _bcm_fb_cosq_reinit(unit); 438 } 439 #endif /* BCM_WARM_BOOT_SUPPORT */ 440 441 num_cos = _bcm_esw_cosq_config_property_get(unit); 442 443 return bcm_fb_cosq_config_set(unit, num_cos); 444 } 445 446 /* 447 * MMU Programming for 56500 style memory managers. 448 * Includes 56100, 56300, 56200 devices. 449 * 450 * The MMU is always configured for dynamic mode. 451 * 452 * Per-port/per-cos limits are programmed in soc_firebolt_mmu_init 453 * based on the mmu_xq_weight config parameters. This has to happen 454 * one time during initialization. The remaining parameters can be 455 * updated multiple times after initialization. 456 * 457 * Default MMU xq (packet) controls allow for 8 queues to be used 458 * even less than 8 are currently configured. If less than 8 queues 459 * will ever be used then the remaining queues mmu_xq_weight_cosN 460 * values should be set to 0. A 4 queue configuration should set 461 * mmu_xq_weight_cosN=0 for N=4, 5, 6, 7. 462 * 463 * MMU Controls used here have defaults based on the defines at the 464 * top of this file. Each of those defaults can be overridden using 465 * config properties. 466 * 467 * mmu_flow_percent=90 percentage of per-port cells useable 468 * before flow control starts 469 * mmu_flow_fanin=4 number of simulteneous senders to each 470 * port for flow control purposes 471 * mmu_red_drop_percent=60 472 * mmu_yellow_drop_percent=80 percentage of per-port/per-cos packets 473 * used before red or yellow packets will 474 * be dropped 475 * mmu_static_bytes=1536 per-port/per-cos static reserved limit. 476 * Rounded up from bytes to next cell size. 477 * Remaining cells are put in dynamic pool. 478 * If 0, then mmu_static_percent is used. 479 * mmu_static_percent=50 Percentage of per-port/per-cos cells to 480 * use as static reserved limit. 481 * Remaining cells are put in dynamic pool. 482 * Only used if mmu_static_bytes is 0. 483 * mmu_reset_bytes=3072 (1536*2) 484 * offset from dynamic cell set limits for 485 * reset (enable) limits. 486 * Rounded up from bytes to next cell size. 487 * mmu_overcommit=1 non-stack port overcommit factor for 488 * dynamic pool 489 * mmu_overcommit_stack=2 stack port overcommit factor for 490 * dynamic pool. If 0, then use the 491 * mmu_overcommit value for stack ports 492 */ 493 494 STATIC int 495 _bcm_fb_cosq_config_set(int unit, int numq) 496 { 497 int ncells, nports, xq_per_port, cos; 498 int n, nreset, used_cells; 499 int scells, dcells; 500 soc_port_t port; 501 uint32 val, limit_red, limit_yel; 502 soc_mem_t xq_mem; 503 int mmu_flow_percent; 504 int mmu_flow_fanin; 505 int mmu_red_drop_percent; 506 int mmu_yellow_drop_percent; 507 int mmu_static_bytes; 508 int mmu_static_cells; 509 int mmu_static_percent; 510 int mmu_reset_bytes; 511 int mmu_reset_cells = 0; 512 int mmu_overcommit; 513 int mmu_overcommit_stack; 514 #if defined (BCM_HAWKEYE_SUPPORT) 515 int mmu_dyncellsetlimit = 0; 516 int mmu_xoff_pkt_threshold = 0; 517 int mmu_xoff_cell_threshold = 0; 518 int xq_per_cos = 0; 519 #endif /* BCM_HAWKEYE_SUPPORT */ 520 #if defined(BCM_RAPTOR_SUPPORT) || defined(BCM_HELIX_SUPPORT) || \ 521 defined(BCM_FELIX_SUPPORT) || defined(BCM_FIREBOLT2_SUPPORT) 522 int sreset; 523 #endif 524 525 /* Validate cosq num */ 526 if (numq < 1) { 527 return BCM_E_PARAM; 528 } 529 530 ncells = soc_mem_index_count(unit, MMU_CBPDATA0m); 531 #if defined (BCM_HAWKEYE_SUPPORT) 532 if(SOC_IS_HAWKEYE(unit)){ 533 nports = NUM_E_PORT(unit); 534 /* These special variables are for Hawkeye only. 535 Those values are retrieved from HAWKEYE MMU setting document*/ 536 mmu_dyncellsetlimit = 2400; 537 mmu_xoff_pkt_threshold = 12; 538 mmu_xoff_cell_threshold = 74; 539 xq_per_cos = 8; 540 } else 541 #endif /* BCM_HAWKEYE_SUPPORT */ 542 { 543 nports = NUM_ALL_PORT(unit); 544 } 545 546 /* get mmu control config values */ 547 mmu_flow_percent = soc_property_get(unit, 548 spn_MMU_FLOW_PERCENT, 549 MMU_FLOW_PERCENT); 550 mmu_flow_fanin = soc_property_get(unit, 551 spn_MMU_FLOW_FANIN, 552 MMU_FLOW_FANIN); 553 mmu_red_drop_percent = soc_property_get(unit, 554 spn_MMU_RED_DROP_PERCENT, 555 MMU_RED_DROP_PERCENT); 556 mmu_yellow_drop_percent = soc_property_get(unit, 557 spn_MMU_YELLOW_DROP_PERCENT, 558 MMU_YELLOW_DROP_PERCENT); 559 mmu_static_bytes = soc_property_get(unit, 560 spn_MMU_STATIC_BYTES, 561 MMU_STATIC_BYTES); 562 mmu_static_percent = soc_property_get(unit, 563 spn_MMU_STATIC_PERCENT, 564 MMU_STATIC_PERCENT); 565 mmu_reset_bytes = soc_property_get(unit, 566 spn_MMU_RESET_BYTES, 567 MMU_RESET_BYTES); 568 mmu_overcommit = soc_property_get(unit, 569 spn_MMU_OVERCOMMIT, 570 MMU_OVERCOMMIT); 571 mmu_overcommit_stack = soc_property_get(unit, 572 spn_MMU_OVERCOMMIT_STACK, 573 MMU_OVERCOMMIT_STACK); 574 575 /* sanity check config values */ 576 if (mmu_flow_percent <= 0 || mmu_flow_percent > 100) { 577 mmu_flow_percent = 100; 578 } 579 if (mmu_red_drop_percent <= 0 || mmu_red_drop_percent > 100) { 580 mmu_red_drop_percent = 100; 581 } 582 if (mmu_yellow_drop_percent <= 0 || mmu_yellow_drop_percent > 100) { 583 mmu_yellow_drop_percent = 100; 584 } 585 if (mmu_static_percent <= 0 || mmu_static_percent > 100) { 586 mmu_static_percent = MMU_STATIC_PERCENT; 587 } 588 if (mmu_overcommit <= 0) { 589 mmu_overcommit = 1; 590 } 591 if (mmu_overcommit_stack <= 0) { 592 mmu_overcommit_stack = mmu_overcommit; 593 } 594 mmu_static_cells = (mmu_static_bytes + MMU_CELL_SIZE - 1) / MMU_CELL_SIZE; 595 mmu_reset_cells = (mmu_reset_bytes + MMU_CELL_SIZE - 1) / MMU_CELL_SIZE; 596 597 /* calculate static limits first */ 598 if (mmu_static_cells > 0) { 599 scells = mmu_static_cells; 600 #if defined(BCM_RAPTOR_SUPPORT) || defined(BCM_HELIX_SUPPORT) || \ 601 defined(BCM_FELIX_SUPPORT) || defined(BCM_FIREBOLT2_SUPPORT) 602 sreset = scells; /* 100% */ 603 #endif 604 } else { 605 scells = (ncells / nports / numq) * mmu_static_percent / 100; 606 #if defined(BCM_RAPTOR_SUPPORT) || defined(BCM_HELIX_SUPPORT) || \ 607 defined(BCM_FELIX_SUPPORT) || defined(BCM_FIREBOLT2_SUPPORT) 608 sreset = scells * 75 / 100; /* 75% */ 609 #endif 610 } 611 used_cells = scells * numq * nports; 612 613 /* remaining cells are dynamic */ 614 n = ncells - used_cells; 615 if (n <= 0) { 616 n = 0; 617 } 618 dcells = n / nports; 619 nreset = n - mmu_reset_cells; 620 if (nreset < (n * MMU_RESET_MIN_PERCENT / 100)) { 621 nreset = n * MMU_RESET_MIN_PERCENT / 100; 622 } 623 if (nreset <= 0) { 624 nreset = 1; 625 } 626 627 /* device wide dynamic limits */ 628 if (SOC_IS_RAPTOR(unit) || SOC_IS_RAVEN(unit) || SOC_IS_HAWKEYE(unit)) { 629 #if defined(BCM_RAPTOR_SUPPORT) 630 SOC_IF_ERROR_RETURN(READ_TOTALDYNCELLSETLIMITr(unit, &val)); 631 soc_reg_field_set(unit, TOTALDYNCELLSETLIMITr, 632 &val, TOTALDYNCELLSETLIMITf, n); 633 SOC_IF_ERROR_RETURN(WRITE_TOTALDYNCELLSETLIMITr(unit, val)); 634 SOC_IF_ERROR_RETURN(READ_TOTALDYNCELLRESETLIMITr(unit, &val)); 635 soc_reg_field_set(unit, TOTALDYNCELLRESETLIMITr, 636 &val, TOTALDYNCELLRESETLIMITf, nreset); 637 SOC_IF_ERROR_RETURN(WRITE_TOTALDYNCELLRESETLIMITr(unit, val)); 638 #endif /* BCM_RAPTOR_SUPPORT*/ 639 } else if (SOC_IS_FIREBOLT2(unit)) { 640 #if defined(BCM_FIREBOLT2_SUPPORT) 641 SOC_IF_ERROR_RETURN(READ_TOTALDYNCELLLIMITr(unit, &val)); 642 soc_reg_field_set(unit, TOTALDYNCELLLIMITr, 643 &val, SETLIMITf, n); 644 SOC_IF_ERROR_RETURN(WRITE_TOTALDYNCELLLIMITr(unit, val)); 645 SOC_IF_ERROR_RETURN(READ_TOTALDYNCELLRESETLIMITr(unit, &val)); 646 soc_reg_field_set(unit, TOTALDYNCELLRESETLIMITr, 647 &val, RESETLIMITf, nreset); 648 SOC_IF_ERROR_RETURN(WRITE_TOTALDYNCELLRESETLIMITr(unit, val)); 649 650 /* red and yellow drop limits for total dynamic cells */ 651 limit_red = n * mmu_red_drop_percent / 100; 652 limit_yel = n * mmu_yellow_drop_percent / 100; 653 limit_red /= BCM_FB2_CNG_CELL_LIMIT_GRANULARITY; 654 limit_yel /= BCM_FB2_CNG_CELL_LIMIT_GRANULARITY; 655 656 val = 0; 657 soc_reg_field_set(unit, CNGTOTALDYNCELLLIMIT0r, 658 &val, CNGTOTALDYNCELLLIMITf, limit_red); 659 SOC_IF_ERROR_RETURN(WRITE_CNGTOTALDYNCELLLIMIT0r(unit, val)); 660 661 val = 0; 662 soc_reg_field_set(unit, CNGTOTALDYNCELLLIMIT1r, 663 &val, CNGTOTALDYNCELLLIMITf, limit_yel); 664 SOC_IF_ERROR_RETURN(WRITE_CNGTOTALDYNCELLLIMIT1r(unit, val)); 665 #endif /* BCM_FIREBOLT2_SUPPORT */ 666 } else { 667 SOC_IF_ERROR_RETURN(READ_TOTALDYNCELLLIMITr(unit, &val)); 668 soc_reg_field_set(unit, TOTALDYNCELLLIMITr, 669 &val, TOTALDYNCELLLIMITf, n); 670 #if defined(BCM_RAPTOR_SUPPORT) || defined(BCM_FELIX15_SUPPORT) || \ 671 defined(BCM_HELIX15_SUPPORT) 672 if (soc_reg_field_valid(unit, TOTALDYNCELLLIMITr, 673 TOTALDYNCELLRESETLIMITf)) { 674 soc_reg_field_set(unit, TOTALDYNCELLLIMITr, 675 &val, TOTALDYNCELLRESETLIMITf, nreset); 676 } 677 #endif /* RAPTOR || FELIX1.5 || HELIX1.5 */ 678 SOC_IF_ERROR_RETURN(WRITE_TOTALDYNCELLLIMITr(unit, val)); 679 } 680 681 /* per-port dynamic limits */ 682 PBMP_ALL_ITER(unit, port) { 683 if (IS_ST_PORT(unit, port)) { 684 n = dcells * mmu_overcommit_stack; 685 } else { 686 n = dcells * mmu_overcommit; 687 } 688 if (n >= ncells) { 689 n = ncells - 1; 690 } 691 692 #if defined (BCM_HAWKEYE_SUPPORT) 693 /* For Hawkeye, the value of field DYNCELLLIMIT of register DYNCELLLIMIT is 694 * min((ncells - used_cells) ,mmu_dyncellsetlimit). */ 695 if (SOC_IS_HAWKEYE(unit)) { 696 if((ncells - used_cells) > mmu_dyncellsetlimit) { 697 n = mmu_dyncellsetlimit; 698 } else { 699 n = ncells - used_cells; 700 } 701 } 702 #endif /* BCM_HAWKEYE_SUPPORT */ 703 704 nreset = n - mmu_reset_cells; 705 if (nreset < (n * MMU_RESET_MIN_PERCENT / 100)) { 706 nreset = n * MMU_RESET_MIN_PERCENT / 100; 707 } 708 if (nreset <= 0) { 709 nreset = 1; 710 } 711 712 SOC_IF_ERROR_RETURN(READ_DYNCELLLIMITr(unit, port, &val)); 713 if (soc_reg_field_valid(unit, DYNCELLLIMITr, DYNCELLLIMITf)) { 714 soc_reg_field_set(unit, DYNCELLLIMITr, &val, 715 DYNCELLLIMITf, n); 716 } 717 #if defined(BCM_RAPTOR_SUPPORT) || defined(BCM_HELIX_SUPPORT) || \ 718 defined(BCM_FELIX_SUPPORT) || defined(BCM_FIREBOLT2_SUPPORT) 719 if (soc_reg_field_valid(unit, DYNCELLLIMITr, DYNCELLSETLIMITf)) { 720 soc_reg_field_set(unit, DYNCELLLIMITr, &val, 721 DYNCELLSETLIMITf, n); 722 } 723 if (soc_reg_field_valid(unit, DYNCELLLIMITr, DYNCELLRESETLIMITf)) { 724 soc_reg_field_set(unit, DYNCELLLIMITr, &val, 725 DYNCELLRESETLIMITf, nreset); 726 } 727 #endif /* RAPTOR || HELIX || FELIX || FB2 */ 728 if (soc_reg_field_valid(unit, DYNCELLLIMITr, DYNCELLRESETLIMITSELf)) { 729 soc_reg_field_set(unit, DYNCELLLIMITr, &val, 730 DYNCELLRESETLIMITSELf, 0); /* 75% */ 731 } 732 733 SOC_IF_ERROR_RETURN(WRITE_DYNCELLLIMITr(unit, port, val)); 734 735 #if defined(BCM_FIREBOLT2_SUPPORT) 736 if (SOC_IS_FIREBOLT2(unit)) { 737 /* red and yellow drop limits for per-port dynamic cells */ 738 limit_red = n * mmu_red_drop_percent / 100; 739 limit_yel = n * mmu_yellow_drop_percent / 100; 740 limit_red /= BCM_FB2_CNG_CELL_LIMIT_GRANULARITY; 741 limit_yel /= BCM_FB2_CNG_CELL_LIMIT_GRANULARITY; 742 743 val = 0; 744 soc_reg_field_set(unit, CNGDYNCELLLIMIT0r, &val, 745 CNGDYNCELLLIMITf, limit_red); 746 SOC_IF_ERROR_RETURN(WRITE_CNGDYNCELLLIMIT0r(unit, port, val)); 747 748 val = 0; 749 soc_reg_field_set(unit, CNGDYNCELLLIMIT1r, &val, 750 CNGDYNCELLLIMITf, limit_yel); 751 SOC_IF_ERROR_RETURN(WRITE_CNGDYNCELLLIMIT1r(unit, port, val)); 752 } 753 #endif 754 755 /* 756 * Number of transactions allocated to each port, 757 * shared between that port's active cosqs. 758 */ 759 SOC_IF_ERROR_RETURN(soc_fb_xq_mem(unit, port, &xq_mem)); 760 xq_per_port = soc_mem_index_count(unit, xq_mem); 761 762 #if defined (BCM_HAWKEYE_SUPPORT) 763 if(SOC_IS_HAWKEYE(unit)) { 764 SOC_IF_ERROR_RETURN(WRITE_HOLCOS0MINXQCNTr(unit, port, xq_per_cos)); 765 SOC_IF_ERROR_RETURN(WRITE_HOLCOS1MINXQCNTr(unit, port, xq_per_cos)); 766 SOC_IF_ERROR_RETURN(WRITE_HOLCOS2MINXQCNTr(unit, port, xq_per_cos)); 767 SOC_IF_ERROR_RETURN(WRITE_HOLCOS3MINXQCNTr(unit, port, xq_per_cos)); 768 n = xq_per_port - (xq_per_cos * numq) -4 -5; 769 SOC_IF_ERROR_RETURN(WRITE_DYNXQCNTPORTr(unit, port, n)); 770 n = n + 8; 771 for (cos = 0; cos < NUM_COS(unit); cos++) { 772 SOC_IF_ERROR_RETURN 773 (WRITE_HOLCOSPKTSETLIMITr(unit, port, cos, n)); 774 SOC_IF_ERROR_RETURN 775 (WRITE_HOLCOSPKTRESETLIMITr(unit, port, cos, (n - 4))); 776 } 777 } 778 #endif /* BCM_HAWKEYE_SUPPORT */ 779 780 /* 781 * Divide weighted per-port packet limits into each cos. 782 * Initialize all COSQs, even the inactive ones. 783 */ 784 for (cos = 0; cos < NUM_COS(unit); cos++) { 785 /* set per-port static limits (calculated earlier) */ 786 SOC_IF_ERROR_RETURN 787 (READ_LWMCOSCELLSETLIMITr(unit, port, cos, &val)); 788 if (soc_reg_field_valid(unit, LWMCOSCELLSETLIMITr, 789 CELLSETLIMITf)) { 790 soc_reg_field_set(unit, LWMCOSCELLSETLIMITr, 791 &val, CELLSETLIMITf, 792 cos < numq ? scells : 0); 793 } 794 #if defined(BCM_RAPTOR_SUPPORT) || defined(BCM_HELIX_SUPPORT) || \ 795 defined(BCM_FELIX_SUPPORT) || defined(BCM_FIREBOLT2_SUPPORT) 796 if (soc_reg_field_valid(unit, LWMCOSCELLSETLIMITr, 797 CELLRESETLIMITf)) { 798 soc_reg_field_set(unit, LWMCOSCELLSETLIMITr, 799 &val, CELLRESETLIMITf, 800 cos < numq ? sreset : 0); 801 } 802 #endif /* RAPTOR || HELIX || FELIX || FB2 */ 803 SOC_IF_ERROR_RETURN 804 (WRITE_LWMCOSCELLSETLIMITr(unit, port, cos, val)); 805 806 807 /* set red and yellow drop limits */ 808 /* set as a percentage of the green drop (HOL) limit */ 809 810 SOC_IF_ERROR_RETURN 811 (READ_HOLCOSPKTSETLIMITr(unit, port, cos, &val)); 812 n = soc_reg_field_get(unit, HOLCOSPKTSETLIMITr, val, 813 PKTSETLIMITf); 814 815 /* Make sure numq will work with the cosq weighting. */ 816 if ((cos < numq) && (n == 4)) { 817 /* 818 * This means that this COSQ has been 819 * disabled due to XQ weighting, but 820 * has been selected as active. Config error. 821 */ 822 return BCM_E_PARAM; 823 } 824 825 /* per-queue packet red and yellow drop */ 826 if (cos < numq) { 827 limit_red = n * mmu_red_drop_percent / 100; 828 limit_yel = n * mmu_yellow_drop_percent / 100; 829 } else { 830 limit_red = xq_per_port - 1; /* Max limit (disabled) */ 831 limit_yel = xq_per_port - 1; /* Max limit (disabled) */ 832 } 833 834 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_RAPTOR_SUPPORT) 835 /* CNG limit for FB2 is set at 4 packet granularity */ 836 /* CNG limit for Raven and Hawkeye is set at packet granularity */ 837 if (SOC_IS_FIREBOLT2(unit)) { /* Granularity limitation */ 838 limit_red /= BCM_FB2_CNG_PKT_LIMIT_GRANULARITY; 839 limit_yel /= BCM_FB2_CNG_PKT_LIMIT_GRANULARITY; 840 } 841 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_RAPTOR_SUPPORT */ 842 843 val = 0; 844 soc_reg_field_set(unit, CNGCOSPKTLIMIT0r, &val, 845 CNGPKTSETLIMIT0f, limit_red); 846 SOC_IF_ERROR_RETURN(WRITE_CNGCOSPKTLIMIT0r(unit, port, cos, val)); 847 848 val = 0; 849 soc_reg_field_set(unit, CNGCOSPKTLIMIT1r, &val, 850 CNGPKTSETLIMIT1f, limit_yel); 851 SOC_IF_ERROR_RETURN(WRITE_CNGCOSPKTLIMIT1r(unit, port, cos, val)); 852 853 #if defined(BCM_FIREBOLT2_SUPPORT) 854 /* per-queue cell red and yellow drop */ 855 if (SOC_IS_FIREBOLT2(unit)) { 856 /* disabled (set to maximum) */ 857 limit_red = BCM_FB2_CNG_CELL_LIMIT_MAX; 858 limit_yel = BCM_FB2_CNG_CELL_LIMIT_MAX; 859 limit_red /= BCM_FB2_CNG_CELL_LIMIT_GRANULARITY; 860 limit_yel /= BCM_FB2_CNG_CELL_LIMIT_GRANULARITY; 861 862 val = 0; 863 soc_reg_field_set(unit, CNGCOSCELLLIMIT0r, &val, 864 CNGCELLSETLIMITf, limit_red); 865 SOC_IF_ERROR_RETURN 866 (WRITE_CNGCOSCELLLIMIT0r(unit, port, cos, val)); 867 868 val = 0; 869 soc_reg_field_set(unit, CNGCOSCELLLIMIT1r, &val, 870 CNGCELLSETLIMITf, limit_yel); 871 SOC_IF_ERROR_RETURN 872 (WRITE_CNGCOSCELLLIMIT1r(unit, port, cos, val)); 873 } 874 #endif 875 } 876 877 /* cell ingress back pressure */ 878 if (port == CMIC_PORT(unit)) { 879 n = ncells-1; 880 } else { 881 /* flow control cells (static + dynamic) */ 882 n = scells * mmu_flow_percent / 100; 883 n += dcells; 884 if (n < 0 || n >= ncells) { 885 n = ncells - 1; 886 } 887 } 888 889 SOC_IF_ERROR_RETURN(READ_IBPCELLSETLIMITr(unit, port, &val)); 890 #if defined (BCM_HAWKEYE_SUPPORT) 891 if(SOC_IS_HAWKEYE(unit)) { 892 n = mmu_xoff_cell_threshold; 893 soc_reg_field_set(unit, IBPCELLSETLIMITr, &val, 894 RESETLIMITSELf, 0); /* 75% */ 895 } 896 #endif /* BCM_HAWKEYE_SUPPORT */ 897 soc_reg_field_set(unit, IBPCELLSETLIMITr, &val, 898 CELLSETLIMITf, n); 899 SOC_IF_ERROR_RETURN(WRITE_IBPCELLSETLIMITr(unit, port, val)); 900 901 SOC_IF_ERROR_RETURN(READ_IBPDISCARDSETLIMITr(unit, port, &val)); 902 soc_reg_field_set(unit, IBPDISCARDSETLIMITr, &val, 903 DISCARDSETLIMITf, ncells-1); 904 SOC_IF_ERROR_RETURN(WRITE_IBPDISCARDSETLIMITr(unit, port, val)); 905 906 /* packet ingress back pressure */ 907 if (port == CMIC_PORT(unit) || mmu_flow_fanin <= 0) { 908 n = xq_per_port - 1; 909 } else { 910 n = xq_per_port / numq / mmu_flow_fanin; 911 if (n < MMU_FLOW_PKTMIN) { 912 n = MMU_FLOW_PKTMIN; 913 } 914 } 915 916 SOC_IF_ERROR_RETURN(READ_IBPPKTSETLIMITr(unit, port, &val)); 917 #if defined (BCM_HAWKEYE_SUPPORT) 918 if(SOC_IS_HAWKEYE(unit)) { 919 n=mmu_xoff_pkt_threshold; 920 } 921 #endif /* BCM_HAWKEYE_SUPPORT */ 922 soc_reg_field_set(unit, IBPPKTSETLIMITr, &val, 923 PKTSETLIMITf, n); 924 soc_reg_field_set(unit, IBPPKTSETLIMITr, &val, 925 RESETLIMITSELf, 0); /* 75% */ 926 SOC_IF_ERROR_RETURN(WRITE_IBPPKTSETLIMITr(unit, port, val)); 927 } 928 929 /* Overall MMU controls */ 930 SOC_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, &val)); 931 soc_reg_field_set(unit, MISCCONFIGr, &val, DYNAMIC_MEMORY_ENf, 1); 932 #if defined(BCM_FIREBOLT2_SUPPORT) 933 if (soc_reg_field_valid(unit, MISCCONFIGr, SOP_DROP_ONLY_POLICY_ENf)) { 934 soc_reg_field_set(unit, MISCCONFIGr, &val, SOP_DROP_ONLY_POLICY_ENf, 1); 935 } 936 #endif /* BCM_FIREBOLT2_SUPPORT */ 937 938 #if defined(BCM_RAPTOR_SUPPORT) || defined(BCM_FELIX15_SUPPORT) || \ 939 defined(BCM_HELIX15_SUPPORT) 940 if (soc_reg_field_valid(unit, MISCCONFIGr, HOL_CELL_SOP_DROP_ENf)) { 941 soc_reg_field_set(unit, MISCCONFIGr, &val, HOL_CELL_SOP_DROP_ENf, 1); 942 } 943 #endif /* BCM_RAPTOR_SUPPORT || BCM_FELIX15_SUPPORT || BCM_HELIX15_SUPPORT */ 944 945 SOC_IF_ERROR_RETURN(WRITE_MISCCONFIGr(unit, val)); 946 947 return BCM_E_NONE; 948 } 949 950 951 /* 952 * Function: 953 * bcm_fb_cosq_config_set 954 * Purpose: 955 * Set the number of COS queues 956 * Parameters: 957 * unit - Draco unit number. 958 * numq - number of COS queues (1-8). 959 * Returns: 960 * BCM_E_XXX 961 */ 962 963 int 964 bcm_fb_cosq_config_set(int unit, int numq) 965 { 966 int cos, prio, ratio, remain; 967 968 SOC_IF_ERROR_RETURN(_bcm_fb_cosq_config_set(unit, numq)); 969 970 /* Map the eight 802.1 priority levels to the active cosqs */ 971 ratio = 8 / numq; 972 remain = 8 % numq; 973 cos = 0; 974 for (prio = 0; prio < 8; prio++) { 975 BCM_IF_ERROR_RETURN 976 (bcm_fb_er_cosq_mapping_set(unit, -1, prio, cos)); 977 if ((prio + 1) == (((cos + 1) * ratio) + 978 ((remain < (numq - cos)) ? 0 : 979 (remain - (numq - cos) + 1)))) { 980 cos++; 981 } 982 } 983 984 #ifdef BCM_COSQ_HIGIG_MAP_DISABLE 985 SOC_IF_ERROR_RETURN(soc_cosq_stack_port_map_disable(unit)); 986 #endif 987 988 /* use identity mapping for CPU priority mapping */ 989 SOC_IF_ERROR_RETURN(soc_cpu_priority_mapping_init(unit)); 990 991 _num_cosq[unit] = numq; 992 993 #ifdef BCM_WARM_BOOT_SUPPORT 994 SOC_CONTROL_LOCK(unit); 995 SOC_CONTROL(unit)->scache_dirty = 1; 996 SOC_CONTROL_UNLOCK(unit); 997 #endif 998 999 return BCM_E_NONE; 1000 } 1001 1002 /* 1003 * Function: 1004 * bcm_fb_cosq_config_get 1005 * Purpose: 1006 * Get the number of cos queues 1007 * Parameters: 1008 * unit - StrataSwitch unit number. 1009 * numq - (Output) number of cosq 1010 * Returns: 1011 * BCM_E_XXX 1012 */ 1013 1014 int 1015 bcm_fb_cosq_config_get(int unit, int *numq) 1016 { 1017 if (_num_cosq[unit] == 0) { 1018 return BCM_E_INIT; 1019 } 1020 1021 if (numq != NULL) { 1022 *numq = _num_cosq[unit]; 1023 } 1024 1025 return (BCM_E_NONE); 1026 } 1027 1028 /* 1029 * Function: 1030 * bcm_fb_cosq_port_sched_set 1031 * Purpose: 1032 * Set up class-of-service policy and corresponding weights and delay 1033 * Parameters: 1034 * unit - StrataSwitch unit number. 1035 * pbm - port bitmap 1036 * mode - Scheduling mode, one of BCM_COSQ_xxx 1037 * weights - Weights for each COS queue 1038 * Only for BCM_COSQ_WEIGHTED_FAIR_ROUND_ROBIN mode. 1039 * For DRR Weight is specified in Kbytes 1040 * delay - This parameter is not used in 56504 1041 * Returns: 1042 * BCM_E_XXX 1043 */ 1044 1045 int 1046 bcm_fb_cosq_port_sched_set(int unit, bcm_pbmp_t pbm, 1047 int mode, const int weights[], int delay) 1048 { 1049 uint32 wrr; 1050 int port, t; 1051 uint32 cosarbsel; 1052 int mbits = 0; 1053 int i; 1054 int enc_weights[8]; 1055 #if defined (BCM_RAPTOR_SUPPORT) 1056 int MTUQuantaSel = 0; 1057 #endif 1058 #if defined (BCM_FIREBOLT2_SUPPORT) 1059 int MTUQuanta = 0; 1060 #endif 1061 1062 COMPILER_REFERENCE(delay); 1063 1064 switch (mode) { 1065 case BCM_COSQ_STRICT: 1066 mbits = 0; 1067 break; 1068 case BCM_COSQ_ROUND_ROBIN: 1069 mbits = 1; 1070 break; 1071 case BCM_COSQ_WEIGHTED_ROUND_ROBIN: 1072 mbits = 2; 1073 /* 1074 * All weight values must fit within 4 bits. 1075 * If weight is 0, this queue is run in strict mode, 1076 * others run in WRR mode. 1077 */ 1078 #if defined (BCM_HAWKEYE_SUPPORT) 1079 if(SOC_IS_HAWKEYE(unit)) { 1080 t = weights[0] | weights[1] | weights[2] | weights[3]; 1081 } else 1082 #endif /* BCM_HAWKEYE_SUPPORT*/ 1083 { 1084 t = weights[0] | weights[1] | weights[2] | weights[3] | 1085 weights[4] | weights[5] | weights[6] | weights[7]; 1086 } 1087 1088 #if defined (BCM_RAPTOR_SUPPORT) 1089 if ((SOC_IS_RAPTOR(unit) || SOC_IS_RAVEN(unit) || SOC_IS_HAWKEYE(unit))) { 1090 if ((t & ~0x7f) != 0) { 1091 return BCM_E_PARAM; 1092 } 1093 } else 1094 #endif 1095 #if defined (BCM_FIREBOLT2_SUPPORT) 1096 if (SOC_IS_FIREBOLT2(unit)) { 1097 if ((t & ~0xff) != 0) { 1098 return BCM_E_PARAM; 1099 } 1100 } else 1101 #endif 1102 if ((t & ~0xf) != 0) { 1103 return BCM_E_PARAM; 1104 } 1105 for(i = 0; i < NUM_COS(unit); i++) { 1106 enc_weights[i] = weights[i]; 1107 } 1108 break; 1109 case BCM_COSQ_DEFICIT_ROUND_ROBIN: 1110 mbits = 3; 1111 if (soc_feature(unit, soc_feature_linear_drr_weight)) { 1112 if (SOC_IS_RAPTOR(unit) || SOC_IS_RAVEN(unit) || 1113 SOC_IS_HAWKEYE(unit)) { 1114 #if defined (BCM_RAPTOR_SUPPORT) 1115 MTUQuantaSel = _bcm_rp_cos_drr_weights_to_quanta(weights); 1116 if (MTUQuantaSel < 0) { 1117 return BCM_E_PARAM; 1118 } 1119 for (i = 0; i < NUM_COS(unit); i++) { 1120 if (weights[i]) { 1121 enc_weights[i] = 1122 _bcm_rp_cos_drr_kbytes_to_weight(weights[i], 1123 MTUQuantaSel); 1124 } else { 1125 enc_weights[i] = weights[i]; 1126 } 1127 } 1128 #endif 1129 } else if (SOC_IS_FIREBOLT2(unit)) { 1130 #if defined (BCM_FIREBOLT2_SUPPORT) 1131 MTUQuanta = _bcm_fb2_cos_drr_weights_to_quanta(weights); 1132 if (MTUQuanta < 0) { 1133 return BCM_E_PARAM; 1134 } 1135 for (i = 0; i < 8; i++) { 1136 if (weights[i]) { 1137 enc_weights[i] = 1138 _bcm_fb2_cos_drr_kbytes_to_weight(weights[i], 1139 MTUQuanta); 1140 } else { 1141 enc_weights[i] = weights[i]; 1142 } 1143 1144 } 1145 #endif 1146 } 1147 } else { 1148 for(i = 0; i < 8; i++) { 1149 enc_weights[i] = _bcm_fb_cos_drr_kbytes_to_weight(weights[i]); 1150 } 1151 } 1152 1153 break; 1154 case BCM_COSQ_BOUNDED_DELAY: /* not supported in xgs */ 1155 default: 1156 return BCM_E_PARAM; 1157 } 1158 1159 PBMP_ITER(pbm, port) { 1160 cosarbsel = 0; 1161 soc_reg_field_set(unit, XQCOSARBSELr, &cosarbsel, COSARBf, mbits); 1162 if ((mode == BCM_COSQ_DEFICIT_ROUND_ROBIN) && 1163 (soc_feature(unit, soc_feature_linear_drr_weight))) { 1164 1165 if (SOC_IS_RAPTOR(unit) || SOC_IS_RAVEN(unit)) { 1166 #if defined (BCM_RAPTOR_SUPPORT) 1167 soc_reg_field_set(unit, XQCOSARBSELr, &cosarbsel, 1168 MTU_QUANTA_SELECTf, MTUQuantaSel); 1169 #endif 1170 } else if (SOC_IS_FIREBOLT2(unit)) { 1171 #if defined (BCM_FIREBOLT2_SUPPORT) 1172 soc_reg_field_set(unit, XQCOSARBSELr, &cosarbsel, 1173 MTU_QUANTAf, (MTUQuanta == 1174 BCM_FB2_MTU_QUANTA_LARGE) ? 1 : 0); 1175 #endif 1176 } 1177 } 1178 SOC_IF_ERROR_RETURN(WRITE_XQCOSARBSELr(unit, port, cosarbsel)); 1179 } 1180 1181 if ((mode == BCM_COSQ_WEIGHTED_ROUND_ROBIN) || 1182 (mode == BCM_COSQ_DEFICIT_ROUND_ROBIN)) { 1183 /* 1184 * Weighted Fair Queueing scheduling among vaild COSs 1185 */ 1186 PBMP_ITER(pbm, port) { 1187 #if defined (BCM_RAPTOR_SUPPORT) || defined (BCM_FIREBOLT2_SUPPORT) 1188 if (soc_feature(unit, soc_feature_linear_drr_weight)) { 1189 for (i = 0; i < NUM_COS(unit); i++) { 1190 SOC_IF_ERROR_RETURN(READ_WRRWEIGHT_COSr(unit, port, 1191 i, &wrr)); 1192 /* coverity[uninit_use_in_call : FALSE] */ 1193 soc_reg_field_set(unit, WRRWEIGHT_COSr, &wrr, 1194 WEIGHTf, enc_weights[i]); 1195 SOC_IF_ERROR_RETURN(WRITE_WRRWEIGHT_COSr(unit, port, 1196 i, wrr)); 1197 } 1198 } else 1199 #endif 1200 { /* Firebolt and Helix */ 1201 SOC_IF_ERROR_RETURN(READ_WRRWEIGHTSr(unit, port, &wrr)); 1202 soc_reg_field_set(unit, WRRWEIGHTSr, &wrr, 1203 COS0WEIGHTf, enc_weights[0]); 1204 soc_reg_field_set(unit, WRRWEIGHTSr, &wrr, 1205 COS1WEIGHTf, enc_weights[1]); 1206 soc_reg_field_set(unit, WRRWEIGHTSr, &wrr, 1207 COS2WEIGHTf, enc_weights[2]); 1208 soc_reg_field_set(unit, WRRWEIGHTSr, &wrr, 1209 COS3WEIGHTf, enc_weights[3]); 1210 soc_reg_field_set(unit, WRRWEIGHTSr, &wrr, 1211 COS4WEIGHTf, enc_weights[4]); 1212 soc_reg_field_set(unit, WRRWEIGHTSr, &wrr, 1213 COS5WEIGHTf, enc_weights[5]); 1214 soc_reg_field_set(unit, WRRWEIGHTSr, &wrr, 1215 COS6WEIGHTf, enc_weights[6]); 1216 soc_reg_field_set(unit, WRRWEIGHTSr, &wrr, 1217 COS7WEIGHTf, enc_weights[7]); 1218 SOC_IF_ERROR_RETURN(WRITE_WRRWEIGHTSr(unit, port, wrr)); 1219 } 1220 } 1221 } 1222 1223 return BCM_E_NONE; 1224 } 1225 1226 /* 1227 * Function: 1228 * bcm_fb_cosq_port_sched_get 1229 * Purpose: 1230 * Retrieve class-of-service policy and corresponding weights and delay 1231 * Parameters: 1232 * unit - StrataSwitch unit number. 1233 * pbm - port bitmap 1234 * mode - (output) Scheduling mode, one of BCM_COSQ_xxx 1235 * weights - (output) Weights for each COS queue 1236 * Only for BCM_COSQ_WEIGHTED_ROUND_ROBIN and 1237 * BCM_COSQ_DEFICIT_ROUND_ROBIN mode. 1238 * For DRR Weight is specified in Kbytes 1239 * delay - This parameter is not used in 56504 1240 * Returns: 1241 * BCM_E_XXX 1242 * Notes: 1243 * Actually just returns data for the first port in the bitmap 1244 */ 1245 1246 int 1247 bcm_fb_cosq_port_sched_get(int unit, bcm_pbmp_t pbm, 1248 int *mode, int weights[], int *delay) 1249 { 1250 uint32 cosarbsel, wrr; 1251 int mbits, port; 1252 #if defined (BCM_RAPTOR_SUPPORT) 1253 int MTUQuantaSel = -1; 1254 #endif 1255 #if defined (BCM_FIREBOLT2_SUPPORT) 1256 int MTUQuanta = -1; 1257 #endif 1258 1259 mbits = -1; 1260 PBMP_ITER(pbm, port) { 1261 SOC_IF_ERROR_RETURN(READ_XQCOSARBSELr(unit, port, &cosarbsel)); 1262 mbits = soc_reg_field_get(unit, XQCOSARBSELr, cosarbsel, COSARBf); 1263 if (soc_feature(unit, soc_feature_linear_drr_weight)) { 1264 if (SOC_IS_RAPTOR(unit) || SOC_IS_RAVEN(unit) || 1265 SOC_IS_HAWKEYE(unit)) { 1266 #if defined (BCM_RAPTOR_SUPPORT) 1267 MTUQuantaSel = 1268 soc_reg_field_get(unit, XQCOSARBSELr, cosarbsel, 1269 MTU_QUANTA_SELECTf); 1270 #endif 1271 } else if (SOC_IS_FIREBOLT2(unit)) { 1272 #if defined (BCM_FIREBOLT2_SUPPORT) 1273 MTUQuanta = soc_reg_field_get(unit, XQCOSARBSELr, 1274 cosarbsel, MTU_QUANTAf) ? 1275 BCM_FB2_MTU_QUANTA_LARGE : BCM_FB2_MTU_QUANTA_SMALL; 1276 #endif 1277 } 1278 } 1279 break; 1280 } 1281 1282 switch (mbits) { 1283 case 0: 1284 *mode = BCM_COSQ_STRICT; 1285 break; 1286 case 1: 1287 *mode = BCM_COSQ_ROUND_ROBIN; 1288 break; 1289 case 2: 1290 *mode = BCM_COSQ_WEIGHTED_ROUND_ROBIN; 1291 break; 1292 case 3: 1293 *mode = BCM_COSQ_DEFICIT_ROUND_ROBIN; 1294 break; 1295 default: 1296 return BCM_E_INTERNAL; 1297 } 1298 1299 if ((mbits == 2) || (mbits == 3)) { 1300 wrr = 0; 1301 #if defined (BCM_RAPTOR_SUPPORT) || defined (BCM_FIREBOLT2_SUPPORT) 1302 if (soc_feature(unit, soc_feature_linear_drr_weight)) { 1303 int i; 1304 1305 PBMP_ITER(pbm, port) { 1306 for (i = 0; i < NUM_COS(unit); i++) { 1307 SOC_IF_ERROR_RETURN(READ_WRRWEIGHT_COSr(unit, port, 1308 i, &wrr)); 1309 weights[i] = soc_reg_field_get(unit, WRRWEIGHT_COSr, 1310 wrr, WEIGHTf); 1311 } 1312 } 1313 } else 1314 #endif 1315 { 1316 PBMP_ITER(pbm, port) { 1317 SOC_IF_ERROR_RETURN(READ_WRRWEIGHTSr(unit, port, &wrr)); 1318 break; 1319 } 1320 weights[0] = soc_reg_field_get(unit, WRRWEIGHTSr, wrr, COS0WEIGHTf); 1321 weights[1] = soc_reg_field_get(unit, WRRWEIGHTSr, wrr, COS1WEIGHTf); 1322 weights[2] = soc_reg_field_get(unit, WRRWEIGHTSr, wrr, COS2WEIGHTf); 1323 weights[3] = soc_reg_field_get(unit, WRRWEIGHTSr, wrr, COS3WEIGHTf); 1324 weights[4] = soc_reg_field_get(unit, WRRWEIGHTSr, wrr, COS4WEIGHTf); 1325 weights[5] = soc_reg_field_get(unit, WRRWEIGHTSr, wrr, COS5WEIGHTf); 1326 weights[6] = soc_reg_field_get(unit, WRRWEIGHTSr, wrr, COS6WEIGHTf); 1327 weights[7] = soc_reg_field_get(unit, WRRWEIGHTSr, wrr, COS7WEIGHTf); 1328 } 1329 if (mbits == 3) { 1330 int i; 1331 for(i = 0; i < NUM_COS(unit); i++) { 1332 if (soc_feature(unit, soc_feature_linear_drr_weight)) { 1333 if (SOC_IS_RAPTOR(unit) || SOC_IS_RAVEN(unit) || 1334 SOC_IS_HAWKEYE(unit)) { 1335 #if defined (BCM_RAPTOR_SUPPORT) 1336 weights[i] = 1337 _bcm_rp_cos_drr_weight_to_kbytes(weights[i], 1338 MTUQuantaSel); 1339 #endif 1340 } else if (SOC_IS_FIREBOLT2(unit)) { 1341 #if defined (BCM_FIREBOLT2_SUPPORT) 1342 weights[i] *= MTUQuanta; 1343 #endif 1344 } 1345 } else { 1346 weights[i] = 1347 _bcm_fb_cos_drr_weight_to_kbytes(weights[i]); 1348 } 1349 } 1350 } 1351 } 1352 1353 if (delay) { 1354 *delay = 0; 1355 } 1356 return BCM_E_NONE; 1357 } 1358 1359 /* 1360 * Function: 1361 * bcm_fb_cosq_sched_weight_max_get 1362 * Purpose: 1363 * Retrieve maximum weights for given COS policy. 1364 * Parameters: 1365 * unit - StrataSwitch unit number. 1366 * mode - Scheduling mode, one of BCM_COSQ_xxx 1367 * weight_max - (output) Maximum weight for COS queue. 1368 * For DRR mode Weight is specified in Kbytes 1369 * 0 if mode is BCM_COSQ_STRICT. 1370 * 1 if mode is BCM_COSQ_ROUND_ROBIN. 1371 * -1 if not applicable to mode. 1372 * Returns: 1373 * BCM_E_XXX 1374 */ 1375 1376 int 1377 bcm_fb_cosq_sched_weight_max_get(int unit, int mode, int *weight_max) 1378 { 1379 switch (mode) { 1380 case BCM_COSQ_STRICT: 1381 *weight_max = BCM_COSQ_WEIGHT_STRICT; 1382 break; 1383 case BCM_COSQ_ROUND_ROBIN: 1384 *weight_max = BCM_COSQ_WEIGHT_MIN; 1385 break; 1386 case BCM_COSQ_WEIGHTED_ROUND_ROBIN: 1387 *weight_max = FB_WRR_WEIGHT_MAX; 1388 break; 1389 case BCM_COSQ_DEFICIT_ROUND_ROBIN: 1390 if (soc_feature(unit, soc_feature_linear_drr_weight)) { 1391 if (SOC_IS_RAPTOR(unit) || SOC_IS_RAVEN(unit) || 1392 SOC_IS_HAWKEYE(unit)) { 1393 #if defined (BCM_RAPTOR_SUPPORT) 1394 *weight_max = BCM_COS_WEIGHT_MAX * 1395 MTU_Quanta[BCM_MTU_QUANTA_ID_COUNT - 1]; 1396 #endif 1397 } else if (SOC_IS_FIREBOLT2(unit)) { 1398 #if defined (BCM_FIREBOLT2_SUPPORT) 1399 *weight_max = 1400 BCM_FB2_COS_WEIGHT_MAX * BCM_FB2_MTU_QUANTA_LARGE; 1401 #endif 1402 } 1403 } else { 1404 *weight_max = 1405 _bcm_fb_cos_drr_weight_to_kbytes(FB_DRR_WEIGHT_MAX); 1406 } 1407 break; 1408 default: 1409 *weight_max = BCM_COSQ_WEIGHT_UNLIMITED; 1410 return BCM_E_PARAM; 1411 } 1412 1413 return BCM_E_NONE; 1414 } 1415 1416 #define FB2_GRANULARITY_NUM 3 1417 #define FB_BW_GRANULARITY 64 1418 #define FB_BW_FIELD_MAX 0x3ffff 1419 1420 int 1421 bcm_fb_cosq_port_bandwidth_set(int unit, bcm_port_t port, 1422 bcm_cos_queue_t cosq, 1423 uint32 kbits_sec_min, 1424 uint32 kbits_sec_max, 1425 uint32 kbits_sec_burst, 1426 uint32 flags) 1427 { 1428 uint32 refresh_rate; 1429 uint32 regval; 1430 uint32 bucket_val, regindex; 1431 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_RAVEN_SUPPORT) 1432 int refresh_bitsize, bucket_bitsize; 1433 uint32 bucketsize, granularity = 3, meter_flags = 0; 1434 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_RAVEN_SUPPORT */ 1435 1436 if (soc_feature(unit,soc_feature_bucket_support)) { 1437 /* 1438 * To set the new Bandwidth settings, the procedure adopted is 1439 * a. reset MAXBUCKETCONFIG, MINBUCKETCONFIG, MAXBUCKET,MINBUCKET 1440 * b. update MAXBUCKETCONFIG and MINBUCKETCONFIG with new values passed 1441 * c. if MISCCONFIG.METERING_CLK_EN not set before, enable it. 1442 */ 1443 1444 #if defined (BCM_FIREBOLT2_SUPPORT) 1445 if (SOC_IS_FIREBOLT2(unit)) { 1446 BCM_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, ®val)); 1447 if (soc_reg_field_get(unit, MISCCONFIGr, 1448 regval, ITU_MODE_SELf)) { 1449 meter_flags |= _BCM_XGS_METER_FLAG_NON_LINEAR; 1450 } 1451 } 1452 #endif 1453 1454 BCM_IF_ERROR_RETURN(READ_MAXBUCKETCONFIGr(unit, port, cosq, ®val)); 1455 1456 /* Disable egress metering for this port */ 1457 soc_reg_field_set(unit, MAXBUCKETCONFIGr, ®val, MAX_REFRESHf, 0); 1458 soc_reg_field_set(unit, MAXBUCKETCONFIGr, ®val, MAX_THD_SELf, 0); 1459 BCM_IF_ERROR_RETURN(WRITE_MAXBUCKETCONFIGr(unit, port, cosq, regval)); 1460 1461 #if defined(BCM_HAWKEYE_SUPPORT) 1462 if (SOC_IS_HAWKEYE(unit)) { 1463 switch (cosq) { 1464 case 0: BCM_IF_ERROR_RETURN 1465 (WRITE_MINBUCKETCOS0CONFIGr(unit, port, 0)); 1466 break; 1467 case 1: BCM_IF_ERROR_RETURN 1468 (WRITE_MINBUCKETCOS1CONFIGr(unit, port, 0)); 1469 break; 1470 case 2: BCM_IF_ERROR_RETURN 1471 (WRITE_MINBUCKETCOS2CONFIGr(unit, port, 0)); 1472 break; 1473 case 3: BCM_IF_ERROR_RETURN 1474 (WRITE_MINBUCKETCOS3CONFIGr(unit, port, 0)); 1475 break; 1476 default: return BCM_E_PARAM; 1477 } 1478 } else 1479 #endif /* BCM_HAWKEYE_SUPPORT */ 1480 { 1481 BCM_IF_ERROR_RETURN(READ_MINBUCKETCONFIGr(unit, port, cosq, ®val)); 1482 soc_reg_field_set(unit, MINBUCKETCONFIGr, ®val, MIN_REFRESHf, 0); 1483 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_RAVEN_SUPPORT) 1484 if (SOC_IS_FIREBOLT2(unit) || SOC_IS_RAVEN(unit)) { 1485 soc_reg_field_set(unit, MINBUCKETCONFIGr, 1486 ®val, MIN_THD_SELf, 0); 1487 } else 1488 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_RAVEN_SUPPORT */ 1489 { 1490 soc_reg_field_set(unit, MINBUCKETCONFIGr, 1491 ®val, MIN_HI_THD_SELf, 0); 1492 soc_reg_field_set(unit, MINBUCKETCONFIGr, 1493 ®val, MIN_LO_THD_SELf, 0); 1494 } 1495 BCM_IF_ERROR_RETURN(WRITE_MINBUCKETCONFIGr(unit, port, cosq, regval)); 1496 } 1497 /*reset the MAXBUCKET register*/ 1498 bucket_val = 0; 1499 soc_reg_field_set(unit, MAXBUCKETr, &bucket_val, MAX_BUCKETf,0); 1500 soc_reg_field_set(unit, MAXBUCKETr, &bucket_val, IN_PROFILE_FLAGf,1); 1501 BCM_IF_ERROR_RETURN(WRITE_MAXBUCKETr(unit, port, cosq, bucket_val)); 1502 1503 /*reset the MINBUCKET register value*/ 1504 bucket_val = 0; 1505 soc_reg_field_set(unit, MINBUCKETr, &bucket_val, MIN_BUCKETf,0); 1506 soc_reg_field_set(unit, MINBUCKETr, &bucket_val, IN_PROFILE_FLAGf,0); 1507 BCM_IF_ERROR_RETURN(WRITE_MINBUCKETr(unit, port, cosq, bucket_val)); 1508 1509 regval = 0; 1510 #if defined(BCM_HAWKEYE_SUPPORT) 1511 if (SOC_IS_HAWKEYE(unit)) { 1512 switch (cosq) { 1513 case 0: regindex = MINBUCKETCOS0CONFIGr; break; 1514 case 1: regindex = MINBUCKETCOS1CONFIGr; break; 1515 case 2: regindex = MINBUCKETCOS2CONFIGr; break; 1516 case 3: regindex = MINBUCKETCOS3CONFIGr; break; 1517 default: return BCM_E_PARAM; 1518 } 1519 } else 1520 #endif /* BCM_HAWKEYE_SUPPORT */ 1521 { 1522 regindex = MINBUCKETCONFIGr; 1523 } 1524 1525 1526 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_RAVEN_SUPPORT) 1527 if (SOC_IS_FIREBOLT2(unit) || SOC_IS_RAVEN(unit) || 1528 SOC_IS_HAWKEYE(unit)) { 1529 refresh_bitsize = 1530 soc_reg_field_length(unit, regindex, MIN_REFRESHf); 1531 bucket_bitsize = 1532 soc_reg_field_length(unit, regindex, MIN_THD_SELf); 1533 1534 BCM_IF_ERROR_RETURN 1535 (_bcm_xgs_kbits_to_bucket_encoding(kbits_sec_min, 1536 kbits_sec_min, 1537 meter_flags, refresh_bitsize, bucket_bitsize, 1538 &refresh_rate, &bucketsize, &granularity)); 1539 1540 /* regval has MINBUCKETCONFIGr value */ 1541 soc_reg_field_set(unit, regindex, ®val, 1542 MIN_REFRESHf, refresh_rate); 1543 soc_reg_field_set(unit, regindex, 1544 ®val, MIN_THD_SELf, bucketsize); 1545 if (soc_reg_field_valid(unit, regindex, METER_GRANf)) { 1546 soc_reg_field_set(unit, regindex, ®val, 1547 METER_GRANf, granularity); 1548 } 1549 } else 1550 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_RAVEN_SUPPORT */ 1551 { 1552 /* Check kbits_sec_min upper limit prior to "granularization" */ 1553 if (kbits_sec_min > (0xFFFFFFFF - (FB_BW_GRANULARITY - 1)) ) { 1554 kbits_sec_min = (0xFFFFFFFF - (FB_BW_GRANULARITY - 1)); 1555 } 1556 1557 refresh_rate = 1558 (kbits_sec_min + (FB_BW_GRANULARITY - 1)) / 1559 FB_BW_GRANULARITY; 1560 if (refresh_rate > FB_BW_FIELD_MAX) { 1561 refresh_rate = FB_BW_FIELD_MAX; 1562 } 1563 1564 /* regval has MINBUCKETCONFIGr value */ 1565 soc_reg_field_set(unit, regindex, ®val, 1566 MIN_REFRESHf, refresh_rate); 1567 soc_reg_field_set(unit, regindex, 1568 ®val, MIN_HI_THD_SELf, 1569 _bcm_fb_kbits_to_bucketsize(kbits_sec_min)); 1570 soc_reg_field_set(unit, regindex, 1571 ®val, MIN_LO_THD_SELf, 1572 _bcm_fb_kbits_to_bucketsize(kbits_sec_min/2)); 1573 } 1574 #if defined(BCM_HAWKEYE_SUPPORT) 1575 if (SOC_IS_HAWKEYE(unit)) { 1576 switch (cosq) { 1577 case 0: BCM_IF_ERROR_RETURN 1578 (WRITE_MINBUCKETCOS0CONFIGr(unit, port, regval)); 1579 break; 1580 case 1: BCM_IF_ERROR_RETURN 1581 (WRITE_MINBUCKETCOS1CONFIGr(unit, port, regval)); 1582 break; 1583 case 2: BCM_IF_ERROR_RETURN 1584 (WRITE_MINBUCKETCOS2CONFIGr(unit, port, regval)); 1585 break; 1586 case 3: BCM_IF_ERROR_RETURN 1587 (WRITE_MINBUCKETCOS3CONFIGr(unit, port, regval)); 1588 break; 1589 default: return BCM_E_PARAM; 1590 } 1591 } else 1592 #endif /* BCM_HAWKEYE_SUPPORT */ 1593 { 1594 BCM_IF_ERROR_RETURN 1595 (WRITE_MINBUCKETCONFIGr(unit, port, cosq, regval)); 1596 } 1597 regval=0; 1598 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_RAVEN_SUPPORT) 1599 if (SOC_IS_FIREBOLT2(unit) || SOC_IS_RAVEN(unit) || 1600 SOC_IS_HAWKEYE(unit)) { 1601 refresh_bitsize = 1602 soc_reg_field_length(unit, MAXBUCKETCONFIGr, MAX_REFRESHf); 1603 bucket_bitsize = 1604 soc_reg_field_length(unit, MAXBUCKETCONFIGr, MAX_THD_SELf); 1605 1606 BCM_IF_ERROR_RETURN 1607 (_bcm_xgs_kbits_to_bucket_encoding(kbits_sec_max, 1608 kbits_sec_burst, 1609 meter_flags, refresh_bitsize, bucket_bitsize, 1610 &refresh_rate, &bucketsize, &granularity)); 1611 1612 /* regval has MAXBUCKETCONFIGr value */ 1613 soc_reg_field_set(unit, MAXBUCKETCONFIGr, ®val, 1614 MAX_REFRESHf, refresh_rate); 1615 soc_reg_field_set(unit, MAXBUCKETCONFIGr, 1616 ®val, MAX_THD_SELf, bucketsize); 1617 if (soc_reg_field_valid(unit, MAXBUCKETCONFIGr, METER_GRANf)) { 1618 soc_reg_field_set(unit, MAXBUCKETCONFIGr, 1619 ®val, METER_GRANf, granularity); 1620 } 1621 } else 1622 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_RAVEN_SUPPORT */ 1623 { 1624 /* Check kbits_sec_min upper limit prior to "granularization" */ 1625 if (kbits_sec_max > (0xFFFFFFFF - (FB_BW_GRANULARITY - 1)) ) { 1626 kbits_sec_max = (0xFFFFFFFF - (FB_BW_GRANULARITY - 1)); 1627 } 1628 1629 refresh_rate = 1630 (kbits_sec_max + (FB_BW_GRANULARITY - 1)) / 1631 FB_BW_GRANULARITY; 1632 if (refresh_rate > FB_BW_FIELD_MAX) { 1633 refresh_rate = FB_BW_FIELD_MAX; 1634 } 1635 1636 /* regval has MAXBUCKETCONFIGr value */ 1637 soc_reg_field_set(unit, MAXBUCKETCONFIGr, ®val, 1638 MAX_REFRESHf, refresh_rate); 1639 soc_reg_field_set(unit, MAXBUCKETCONFIGr, ®val, MAX_THD_SELf, 1640 _bcm_fb_kbits_to_bucketsize(kbits_sec_burst)); 1641 } 1642 BCM_IF_ERROR_RETURN 1643 (WRITE_MAXBUCKETCONFIGr(unit, port, cosq, regval)); 1644 1645 /* MISCCONFIG.METERING_CLK_EN is set by chip init */ 1646 1647 return BCM_E_NONE; 1648 } else { 1649 return BCM_E_UNAVAIL; 1650 } 1651 1652 } 1653 1654 int 1655 bcm_fb_cosq_port_bandwidth_get(int unit, bcm_port_t port, 1656 bcm_cos_queue_t cosq, 1657 uint32 *kbits_sec_min, 1658 uint32 *kbits_sec_max, 1659 uint32 *kbits_sec_burst, 1660 uint32 *flags) 1661 { 1662 uint32 regval, regindex, refresh_rate; 1663 uint32 bucketsize = 0; 1664 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_RAVEN_SUPPORT) 1665 uint32 kbits_burst, meter_flags = 0; 1666 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_RAVEN_SUPPORT */ 1667 1668 if (soc_feature(unit,soc_feature_bucket_support)){ 1669 1670 if (!kbits_sec_min || !kbits_sec_max || !flags) { 1671 return (BCM_E_PARAM); 1672 } 1673 1674 #if defined (BCM_FIREBOLT2_SUPPORT) 1675 if (SOC_IS_FIREBOLT2(unit)) { 1676 BCM_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, ®val)); 1677 if (soc_reg_field_get(unit, MISCCONFIGr, 1678 regval, ITU_MODE_SELf)) { 1679 meter_flags |= _BCM_XGS_METER_FLAG_NON_LINEAR; 1680 } 1681 } 1682 #endif 1683 1684 BCM_IF_ERROR_RETURN(READ_MAXBUCKETCONFIGr(unit, port, cosq, ®val)); 1685 refresh_rate = 1686 soc_reg_field_get(unit, MAXBUCKETCONFIGr, regval, MAX_REFRESHf); 1687 1688 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_RAVEN_SUPPORT) 1689 if (SOC_IS_FIREBOLT2(unit) || SOC_IS_RAVEN(unit) || 1690 SOC_IS_HAWKEYE(unit)) { 1691 bucketsize = 1692 soc_reg_field_get(unit, MAXBUCKETCONFIGr, 1693 regval, MAX_THD_SELf); 1694 BCM_IF_ERROR_RETURN 1695 (_bcm_xgs_bucket_encoding_to_kbits(refresh_rate, bucketsize, 1696 FB2_GRANULARITY_NUM, 1697 meter_flags, 1698 kbits_sec_max, 1699 kbits_sec_burst)); 1700 } else 1701 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_RAVEN_SUPPORT */ 1702 { 1703 bucketsize = 1704 soc_reg_field_get(unit, MAXBUCKETCONFIGr, 1705 regval, MAX_THD_SELf); 1706 /* Convert the REFRESH field to kbits/sec (1000 bits/sec). */ 1707 *kbits_sec_max = FB_BW_GRANULARITY * refresh_rate; 1708 *kbits_sec_burst = _bcm_fb_bucketsize_to_kbits(bucketsize); 1709 } 1710 1711 #if defined(BCM_HAWKEYE_SUPPORT) 1712 if (SOC_IS_HAWKEYE(unit)) { 1713 switch (cosq) { 1714 case 0: regindex = MINBUCKETCOS0CONFIGr; 1715 BCM_IF_ERROR_RETURN 1716 (READ_MINBUCKETCOS0CONFIGr(unit, port, ®val)); 1717 break; 1718 case 1: regindex = MINBUCKETCOS1CONFIGr; 1719 BCM_IF_ERROR_RETURN 1720 (READ_MINBUCKETCOS1CONFIGr(unit, port, ®val)); 1721 break; 1722 case 2: regindex = MINBUCKETCOS2CONFIGr; 1723 BCM_IF_ERROR_RETURN 1724 (READ_MINBUCKETCOS2CONFIGr(unit, port, ®val)); 1725 break; 1726 case 3: regindex = MINBUCKETCOS3CONFIGr; 1727 BCM_IF_ERROR_RETURN 1728 (READ_MINBUCKETCOS3CONFIGr(unit, port, ®val)); 1729 break; 1730 default: return BCM_E_PARAM; 1731 } 1732 } else 1733 #endif /* BCM_HAWKEYE_SUPPORT */ 1734 { 1735 regindex = MINBUCKETCONFIGr; 1736 BCM_IF_ERROR_RETURN(READ_MINBUCKETCONFIGr(unit, port, cosq, ®val)); 1737 } 1738 1739 refresh_rate = 1740 soc_reg_field_get(unit, regindex, regval, MIN_REFRESHf); 1741 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_RAVEN_SUPPORT) 1742 if (SOC_IS_FIREBOLT2(unit) || SOC_IS_RAVEN(unit) || 1743 SOC_IS_HAWKEYE(unit)) { 1744 BCM_IF_ERROR_RETURN 1745 (_bcm_xgs_bucket_encoding_to_kbits(refresh_rate, 0, 1746 FB2_GRANULARITY_NUM, 1747 meter_flags, 1748 kbits_sec_min, 1749 &kbits_burst)); 1750 } else 1751 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_RAVEN_SUPPORT */ 1752 { 1753 /* Convert the REFRESH field to kbits/sec (1000 bits/sec). */ 1754 *kbits_sec_min = FB_BW_GRANULARITY * refresh_rate; 1755 } 1756 1757 *flags = 0; 1758 1759 return BCM_E_NONE; 1760 } else { 1761 return BCM_E_UNAVAIL; 1762 } 1763 } 1764 1765 #if defined(BCM_RAVEN_SUPPORT) || defined(BCM_FIREBOLT2_SUPPORT) 1766 /* 1767 * Convert HW drop probability to percent value 1768 */ 1769 STATIC int 1770 _bcm_rv_hw_drop_prob_to_api_val[] = { 1771 1000, /* 0 */ 1772 125, /* 1 */ 1773 63, /* 2 */ 1774 31, /* 3 */ 1775 16, /* 4 */ 1776 8, /* 5 */ 1777 4, /* 6 */ 1778 2, /* 7 */ 1779 }; 1780 1781 STATIC int 1782 _bcm_rv_api_val_to_hw_drop_prob(int api_val) { 1783 int i; 1784 for (i = 7; i > 0 ; i--) { 1785 if (api_val <= _bcm_rv_hw_drop_prob_to_api_val[i]) { 1786 break; 1787 } 1788 } 1789 return i; 1790 } 1791 1792 STATIC soc_field_t 1793 _cosfld[] = { 1794 COS0THDMODEf, 1795 COS1THDMODEf, 1796 COS2THDMODEf, 1797 COS3THDMODEf, 1798 COS4THDMODEf, 1799 COS5THDMODEf, 1800 COS6THDMODEf, 1801 COS7THDMODEf, 1802 }; 1803 1804 STATIC int 1805 bcm_rv_cosq_discard_port_set(int unit, bcm_port_t port, 1806 bcm_cos_queue_t cosq, 1807 uint32 color, 1808 int drop_start, 1809 int drop_slope) 1810 { 1811 bcm_port_t local_port; 1812 bcm_pbmp_t pbmp; 1813 int i, cosq_start, num_cosq; 1814 uint32 min_thresh, n; 1815 uint32 rval, encoding; 1816 soc_reg_t reg; 1817 soc_field_t fld; 1818 1819 if (drop_start < 0 || drop_start > 100 || drop_slope > 0) { 1820 return BCM_E_PARAM; 1821 } 1822 1823 if (BCM_GPORT_IS_SET(port)) { 1824 BCM_IF_ERROR_RETURN(bcm_esw_port_local_get(unit, port, &local_port)); 1825 BCM_PBMP_PORT_SET(pbmp, local_port); 1826 } else { 1827 if (port == -1) { 1828 BCM_PBMP_ASSIGN(pbmp, PBMP_ALL(unit)); 1829 } else if (!SOC_PORT_VALID(unit, port)) { 1830 return BCM_E_PORT; 1831 } else { 1832 BCM_PBMP_PORT_SET(pbmp, port); 1833 } 1834 } 1835 1836 if (cosq < -1 || cosq >= _num_cosq[unit]) { 1837 return BCM_E_PARAM; 1838 } else if (cosq == -1) { 1839 cosq_start = 0; 1840 num_cosq = _num_cosq[unit]; 1841 } else { 1842 cosq_start = cosq; 1843 num_cosq = 1; 1844 } 1845 1846 BCM_PBMP_ITER(pbmp, local_port) { 1847 for (i = cosq_start; i < (cosq_start + num_cosq); i++) { 1848 /* Get the start point as a function of the HOL limit */ 1849 SOC_IF_ERROR_RETURN 1850 (READ_HOLCOSPKTSETLIMITr(unit, local_port, i, &rval)); 1851 n = soc_reg_field_get(unit, HOLCOSPKTSETLIMITr, rval, 1852 PKTSETLIMITf); 1853 min_thresh = drop_start * n / 100; 1854 1855 /* Set the drop rate depending on the color */ 1856 if (color == BCM_COSQ_DISCARD_COLOR_GREEN) { 1857 reg = CNG1COSDROPRATEr; 1858 } else { 1859 reg = CNG0COSDROPRATEr; 1860 } 1861 BCM_IF_ERROR_RETURN 1862 (soc_reg32_read(unit, soc_reg_addr 1863 (unit, reg, local_port, i), &rval)); 1864 encoding = _bcm_rv_api_val_to_hw_drop_prob(-1 * drop_slope); 1865 soc_reg_field_set(unit, reg, &rval, DROPRATEf, encoding); 1866 BCM_IF_ERROR_RETURN 1867 (soc_reg32_write(unit, soc_reg_addr 1868 (unit, reg, local_port, i), rval)); 1869 /* Enable simple RED for the (port, cos) pair */ 1870 BCM_IF_ERROR_RETURN 1871 (soc_reg_field32_modify(unit, SIMPLEREDCONFIGr, local_port, 1872 _cosfld[i], 1)); 1873 1874 /* Set the drop threshold depending on the color */ 1875 if (color == BCM_COSQ_DISCARD_COLOR_GREEN) { 1876 reg = CNGCOSPKTLIMIT1r; 1877 fld = CNGPKTSETLIMIT1f; 1878 } else { 1879 reg = CNGCOSPKTLIMIT0r; 1880 fld = CNGPKTSETLIMIT0f; 1881 } 1882 soc_reg_field_set(unit, reg, &rval, fld, min_thresh); 1883 BCM_IF_ERROR_RETURN 1884 (soc_reg32_write(unit, soc_reg_addr 1885 (unit, reg, local_port, i), rval)); 1886 } 1887 /* For Firebolt 2, also match the cell limits to the drop percentage. 1888 * Dynamic cell usage is enabled by default */ 1889 #if defined(BCM_FIREBOLT2_SUPPORT) 1890 if (SOC_IS_FIREBOLT2(unit)) { 1891 /* Fraction of per-port DYNCELLLIMIT */ 1892 BCM_IF_ERROR_RETURN(READ_DYNCELLLIMITr(unit, local_port, &rval)); 1893 n = soc_reg_field_get(unit, DYNCELLLIMITr, rval, DYNCELLSETLIMITf); 1894 min_thresh = drop_start * n / 100; 1895 /* Set the drop threshold depending on the color */ 1896 if (color == BCM_COSQ_DISCARD_COLOR_GREEN) { 1897 reg = CNGDYNCELLLIMIT1r; 1898 fld = CNGDYNCELLLIMITf; 1899 } else { 1900 reg = CNGDYNCELLLIMIT0r; 1901 fld = CNGDYNCELLLIMITf; 1902 } 1903 soc_reg_field_set(unit, reg, &rval, fld, min_thresh); 1904 BCM_IF_ERROR_RETURN 1905 (soc_reg32_write(unit, soc_reg_addr 1906 (unit, reg, local_port, 0), rval)); 1907 } 1908 #endif 1909 } 1910 return BCM_E_NONE; 1911 } 1912 1913 STATIC int 1914 bcm_rv_cosq_discard_port_get(int unit, bcm_port_t port, 1915 bcm_cos_queue_t cosq, 1916 uint32 color, 1917 int *drop_start, 1918 int *drop_slope) 1919 { 1920 bcm_port_t local_port; 1921 bcm_pbmp_t pbmp; 1922 uint32 rval, n; 1923 1924 if (drop_start == NULL || drop_slope == NULL) { 1925 return BCM_E_PARAM; 1926 } 1927 1928 if (BCM_GPORT_IS_SET(port)) { 1929 BCM_IF_ERROR_RETURN(bcm_esw_port_local_get(unit, port, &local_port)); 1930 BCM_PBMP_PORT_SET(pbmp, local_port); 1931 } else { 1932 if (port == -1) { 1933 BCM_PBMP_ASSIGN(pbmp, PBMP_PORT_ALL(unit)); 1934 } else if (!SOC_PORT_VALID(unit, port)) { 1935 return BCM_E_PORT; 1936 } else { 1937 BCM_PBMP_PORT_SET(pbmp, port); 1938 } 1939 } 1940 if (cosq < -1 || cosq >= _num_cosq[unit]) { 1941 return BCM_E_PARAM; 1942 } else if (cosq == -1) { 1943 cosq = 0; 1944 } 1945 1946 BCM_PBMP_ITER(pbmp, local_port) { 1947 /* Get the total HOL limit first */ 1948 BCM_IF_ERROR_RETURN 1949 (READ_HOLCOSPKTSETLIMITr(unit, local_port, cosq, &rval)); 1950 n = soc_reg_field_get(unit, HOLCOSPKTSETLIMITr, rval, PKTSETLIMITf); 1951 1952 /* Get the simple RED mode */ 1953 BCM_IF_ERROR_RETURN(READ_SIMPLEREDCONFIGr(unit, local_port, &rval)); 1954 if (soc_reg_field_get(unit, SIMPLEREDCONFIGr, rval, _cosfld[cosq])) { 1955 if (color == BCM_COSQ_DISCARD_COLOR_GREEN) { 1956 BCM_IF_ERROR_RETURN 1957 (READ_CNGCOSPKTLIMIT1r(unit, local_port, cosq, &rval)); 1958 *drop_start = soc_reg_field_get(unit, CNGCOSPKTLIMIT1r, rval, 1959 CNGPKTSETLIMIT1f) * 100 / n; 1960 BCM_IF_ERROR_RETURN 1961 (READ_CNG1COSDROPRATEr(unit, local_port, cosq, &rval)); 1962 *drop_slope = -1 * _bcm_rv_hw_drop_prob_to_api_val[rval]; 1963 } else { 1964 BCM_IF_ERROR_RETURN 1965 (READ_CNGCOSPKTLIMIT0r(unit, local_port, cosq, &rval)); 1966 *drop_start = soc_reg_field_get(unit, CNGCOSPKTLIMIT0r, rval, 1967 CNGPKTSETLIMIT0f) * 100 / n; 1968 BCM_IF_ERROR_RETURN 1969 (READ_CNG0COSDROPRATEr(unit, local_port, cosq, &rval)); 1970 *drop_slope = -1 * _bcm_rv_hw_drop_prob_to_api_val[rval]; 1971 } 1972 } 1973 break; 1974 } 1975 return BCM_E_NONE; 1976 } 1977 #endif 1978 1979 int 1980 bcm_fb_cosq_discard_set(int unit, uint32 flags) 1981 { 1982 return BCM_E_UNAVAIL; 1983 } 1984 1985 int 1986 bcm_fb_cosq_discard_get(int unit, uint32 *flags) 1987 { 1988 return BCM_E_UNAVAIL; 1989 } 1990 1991 int 1992 bcm_fb_cosq_discard_port_set(int unit, bcm_port_t port, 1993 bcm_cos_queue_t cosq, 1994 uint32 color, 1995 int drop_start, 1996 int drop_slope, 1997 int average_time) 1998 { 1999 int rv = BCM_E_UNAVAIL; 2000 #if defined(BCM_RAVEN_SUPPORT) || defined(BCM_FIREBOLT2_SUPPORT) 2001 if (SOC_IS_RAVEN(unit) || SOC_IS_FIREBOLT2(unit)) { 2002 rv = bcm_rv_cosq_discard_port_set(unit, port, cosq, color, 2003 drop_start, drop_slope); 2004 } 2005 #if defined(BCM_FIREBOLT2_SUPPORT) 2006 /* For Firebolt 2, also match the cell limits to the drop percentage. 2007 * Dynamic cell usage is enabled by default. */ 2008 if (BCM_SUCCESS(rv) && SOC_IS_FIREBOLT2(unit)) { 2009 uint32 min_thresh, n, rval; 2010 soc_reg_t reg; 2011 soc_field_t fld; 2012 /* Fraction of TOTALDYNCELLLIMIT */ 2013 BCM_IF_ERROR_RETURN(READ_TOTALDYNCELLLIMITr(unit, &rval)); 2014 n = soc_reg_field_get(unit, TOTALDYNCELLLIMITr, rval, SETLIMITf); 2015 min_thresh = drop_start * n / 100; 2016 /* Set the drop threshold depending on the color */ 2017 if (color == BCM_COSQ_DISCARD_COLOR_GREEN) { 2018 reg = CNGTOTALDYNCELLLIMIT1r; 2019 fld = CNGTOTALDYNCELLLIMITf; 2020 } else { 2021 reg = CNGTOTALDYNCELLLIMIT0r; 2022 fld = CNGTOTALDYNCELLLIMITf; 2023 } 2024 soc_reg_field_set(unit, reg, &rval, fld, min_thresh); 2025 BCM_IF_ERROR_RETURN 2026 (soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval)); 2027 } 2028 #endif 2029 #endif 2030 return rv; 2031 } 2032 2033 int 2034 bcm_fb_cosq_discard_port_get(int unit, bcm_port_t port, 2035 bcm_cos_queue_t cosq, 2036 uint32 color, 2037 int *drop_start, 2038 int *drop_slope, 2039 int *average_time) 2040 { 2041 int rv = BCM_E_UNAVAIL; 2042 #if defined(BCM_RAVEN_SUPPORT) || defined(BCM_FIREBOLT2_SUPPORT) 2043 if (SOC_IS_RAVEN(unit) || SOC_IS_FIREBOLT2(unit)) { 2044 rv = bcm_rv_cosq_discard_port_get(unit, port, cosq, color, 2045 drop_start, drop_slope); 2046 } 2047 #endif 2048 return rv; 2049 } 2050 2051 int 2052 bcm_fb_cosq_detach(int unit, int software_state_only) 2053 { 2054 return BCM_E_NONE; 2055 } 2056 #endif /* BCM_FIREBOLT_SUPPORT */ 2057 2058 /* 2059 * Function: 2060 * bcm_fb_er_cosq_mapping_set 2061 * Purpose: 2062 * Set which cosq a given priority should fall into 2063 * Parameters: 2064 * unit - StrataSwitch unit number. 2065 * priority - Priority value to map 2066 * cosq - COS queue to map to 2067 * Returns: 2068 * BCM_E_XXX 2069 */ 2070 2071 int 2072 bcm_fb_er_cosq_mapping_set(int unit, bcm_port_t port, 2073 bcm_cos_t priority, bcm_cos_queue_t cosq) 2074 { 2075 uint32 cval32, oval32; 2076 soc_field_t f; 2077 bcm_pbmp_t ports; 2078 2079 switch (priority) { 2080 case 0: f = COS0f; break; 2081 case 1: f = COS1f; break; 2082 case 2: f = COS2f; break; 2083 case 3: f = COS3f; break; 2084 case 4: f = COS4f; break; 2085 case 5: f = COS5f; break; 2086 case 6: f = COS6f; break; 2087 case 7: f = COS7f; break; 2088 default: return BCM_E_PARAM; 2089 } 2090 2091 if (cosq < 0 || cosq >= NUM_COS(unit)) { 2092 return (BCM_E_PARAM); 2093 } 2094 2095 if (port == -1) { /* all ports */ 2096 BCM_PBMP_ASSIGN(ports, PBMP_ALL(unit)); 2097 } else if (SOC_PORT_VALID(unit, port) && IS_ALL_PORT(unit, port)) { 2098 BCM_PBMP_CLEAR(ports); 2099 BCM_PBMP_PORT_ADD(ports, port); 2100 } else { 2101 return BCM_E_PORT; 2102 } 2103 2104 PBMP_ITER(ports, port) { 2105 SOC_IF_ERROR_RETURN(READ_COS_SELr(unit, port, &cval32)); 2106 oval32 = cval32; 2107 soc_reg_field_set(unit, COS_SELr, &cval32, f, cosq); 2108 if (cval32 != oval32) { 2109 SOC_IF_ERROR_RETURN(WRITE_COS_SELr(unit, port, cval32)); 2110 } 2111 if (port == CMIC_PORT(unit)) { 2112 SOC_IF_ERROR_RETURN(READ_CPU_COS_SELr(unit, &cval32)); 2113 oval32 = cval32; 2114 soc_reg_field_set(unit, CPU_COS_SELr, &cval32, f, cosq); 2115 if (cval32 != oval32) { 2116 SOC_IF_ERROR_RETURN(WRITE_CPU_COS_SELr(unit, cval32)); 2117 } 2118 } 2119 #ifndef BCM_COSQ_HIGIG_MAP_DISABLE 2120 if (IS_HG_PORT(unit, port) || port == CMIC_PORT(unit)) { 2121 SOC_IF_ERROR_RETURN(READ_ICOS_SELr(unit, port, &cval32)); 2122 oval32 = cval32; 2123 soc_reg_field_set(unit, ICOS_SELr, &cval32, f, cosq); 2124 if (cval32 != oval32) { 2125 SOC_IF_ERROR_RETURN(WRITE_ICOS_SELr(unit, port, cval32)); 2126 } 2127 } 2128 #endif 2129 } 2130 2131 return BCM_E_NONE; 2132 } 2133 2134 /* 2135 * Function: 2136 * bcm_fb_er_cosq_mapping_get 2137 * Purpose: 2138 * Determine which COS queue a given priority currently maps to. 2139 * Parameters: 2140 * unit - StrataSwitch unit number. 2141 * priority - Priority value 2142 * cosq - (Output) COS queue number 2143 * Returns: 2144 * BCM_E_XXX 2145 */ 2146 2147 int 2148 bcm_fb_er_cosq_mapping_get(int unit, bcm_port_t port, 2149 bcm_cos_t priority, bcm_cos_queue_t *cosq) 2150 { 2151 uint32 cval32; 2152 soc_field_t f; 2153 2154 switch (priority) { 2155 case 0: f = COS0f; break; 2156 case 1: f = COS1f; break; 2157 case 2: f = COS2f; break; 2158 case 3: f = COS3f; break; 2159 case 4: f = COS4f; break; 2160 case 5: f = COS5f; break; 2161 case 6: f = COS6f; break; 2162 case 7: f = COS7f; break; 2163 default: return BCM_E_PARAM; 2164 } 2165 2166 if (port == -1) { 2167 port = REG_PORT_ANY; 2168 } else if (!SOC_PORT_VALID(unit, port) || !IS_ALL_PORT(unit, port)) { 2169 return BCM_E_PORT; 2170 } 2171 2172 SOC_IF_ERROR_RETURN(READ_COS_SELr(unit, port, &cval32)); 2173 *cosq = soc_reg_field_get(unit, COS_SELr, cval32, f); 2174 2175 return BCM_E_NONE; 2176 } 2177 2178 #ifdef BCM_FIREBOLT2_SUPPORT 2179 2180 #define FB2_PKT_REFRESH_MAX 0xfffff 2181 #define FB2_PKT_THD_MAX 0xfff 2182 2183 STATIC int 2184 _bcm_fb2_cosq_port_packet_bandwidth_set(int unit, bcm_port_t port, 2185 bcm_cos_queue_t cosq, 2186 int pps, int burst) 2187 { 2188 uint32 regval; 2189 soc_reg_t maxbucket_config_reg, maxbucket_reg; 2190 soc_field_t refresh_f, thd_sel_f, bucket_f; 2191 2192 if (cosq < 0) { 2193 maxbucket_config_reg = PKTPORTMAXBUCKETCONFIGr; 2194 maxbucket_reg = PKTPORTMAXBUCKETr; 2195 refresh_f = PKT_PORT_MAX_REFRESHf; 2196 thd_sel_f = PKT_PORT_MAX_THD_SELf; 2197 bucket_f = PKT_PORT_MAX_BUCKETf; 2198 cosq = 0; 2199 } else { 2200 maxbucket_config_reg = PKTMAXBUCKETCONFIGr; 2201 maxbucket_reg = PKTMAXBUCKETr; 2202 refresh_f = PKT_MAX_REFRESHf; 2203 thd_sel_f = PKT_MAX_THD_SELf; 2204 bucket_f = PKT_MAX_BUCKETf; 2205 } 2206 2207 /* 2208 * To set the new Bandwidth settings, the procedure adopted is 2209 * a. reset MAXBUCKETCONFIG and MAXBUCKET 2210 * b. update MAXBUCKETCONFIG with new values passed 2211 * c. if MISCCONFIG.METERING_CLK_EN not set before, enable it. 2212 */ 2213 2214 /* Disable egress metering */ 2215 BCM_IF_ERROR_RETURN(soc_reg32_get(unit, maxbucket_config_reg, port, cosq, ®val)); 2216 soc_reg_field_set(unit, maxbucket_config_reg, ®val, refresh_f, 0); 2217 soc_reg_field_set(unit, maxbucket_config_reg, ®val, thd_sel_f, 0); 2218 BCM_IF_ERROR_RETURN(soc_reg32_set(unit, maxbucket_config_reg, port, cosq, regval)); 2219 2220 /* reset the MAXBUCKET register*/ 2221 BCM_IF_ERROR_RETURN(soc_reg32_get(unit, maxbucket_reg, port, cosq, ®val)); 2222 soc_reg_field_set(unit, maxbucket_reg, ®val, bucket_f, 0); 2223 soc_reg_field_set(unit, maxbucket_reg, ®val,IN_PROFILE_FLAGf, 0); 2224 BCM_IF_ERROR_RETURN(soc_reg32_set(unit, maxbucket_reg, port, cosq, regval)); 2225 2226 /* Check packets-per second upper limit */ 2227 if (pps > FB2_PKT_REFRESH_MAX) { 2228 pps = FB2_PKT_REFRESH_MAX; 2229 } 2230 2231 /* Check burst upper limit */ 2232 if (burst > FB2_PKT_THD_MAX) { 2233 burst = FB2_PKT_THD_MAX; 2234 } 2235 2236 BCM_IF_ERROR_RETURN(soc_reg32_get(unit, maxbucket_config_reg, port, cosq, ®val)); 2237 soc_reg_field_set(unit, maxbucket_config_reg, ®val, refresh_f, pps); 2238 soc_reg_field_set(unit, maxbucket_config_reg, ®val, thd_sel_f, burst); 2239 BCM_IF_ERROR_RETURN(soc_reg32_set(unit, maxbucket_config_reg, port, cosq, regval)); 2240 2241 /* MISCCONFIG.METERING_CLK_EN is set by chip init */ 2242 2243 return BCM_E_NONE; 2244 } 2245 2246 STATIC int 2247 _bcm_fb2_cosq_port_packet_bandwidth_get(int unit, bcm_port_t port, 2248 bcm_cos_queue_t cosq, 2249 int *pps, int *burst) 2250 { 2251 uint32 regval; 2252 soc_reg_t maxbucket_config_reg; 2253 soc_field_t refresh_f, thd_sel_f; 2254 2255 if (cosq < 0) { 2256 maxbucket_config_reg = PKTPORTMAXBUCKETCONFIGr; 2257 refresh_f = PKT_PORT_MAX_REFRESHf; 2258 thd_sel_f = PKT_PORT_MAX_THD_SELf; 2259 cosq = 0; 2260 } else { 2261 maxbucket_config_reg = PKTMAXBUCKETCONFIGr; 2262 refresh_f = PKT_MAX_REFRESHf; 2263 thd_sel_f = PKT_MAX_THD_SELf; 2264 } 2265 2266 /* Disable egress metering */ 2267 BCM_IF_ERROR_RETURN(soc_reg32_get(unit, maxbucket_config_reg, port, cosq, ®val)); 2268 *pps = soc_reg_field_get(unit, maxbucket_config_reg, regval, refresh_f); 2269 *burst = soc_reg_field_get(unit, maxbucket_config_reg, regval, thd_sel_f); 2270 2271 return BCM_E_NONE; 2272 } 2273 2274 int 2275 bcm_fb2_cosq_port_pps_set(int unit, bcm_port_t port, 2276 bcm_cos_queue_t cosq, int pps) 2277 { 2278 int temp_pps, burst; 2279 2280 if (!IS_CPU_PORT(unit, port)) { 2281 return BCM_E_PORT; 2282 } else if (cosq >= NUM_CPU_COSQ(unit)) { 2283 return BCM_E_PARAM; 2284 } 2285 2286 /* Get the current PPS and BURST settings */ 2287 BCM_IF_ERROR_RETURN 2288 (_bcm_fb2_cosq_port_packet_bandwidth_get(unit, port, cosq, 2289 &temp_pps, &burst)); 2290 2291 /* Replace the current PPS setting, keep BURST the same */ 2292 return _bcm_fb2_cosq_port_packet_bandwidth_set(unit, port, cosq, 2293 pps, burst); 2294 } 2295 2296 int 2297 bcm_fb2_cosq_port_pps_get(int unit, bcm_port_t port, 2298 bcm_cos_queue_t cosq, int *pps) 2299 { 2300 int burst; 2301 2302 if (!IS_CPU_PORT(unit, port)) { 2303 return BCM_E_PORT; 2304 } else if (cosq >= NUM_CPU_COSQ(unit)) { 2305 return BCM_E_PARAM; 2306 } 2307 2308 return _bcm_fb2_cosq_port_packet_bandwidth_get(unit, port, cosq, 2309 pps, &burst); 2310 } 2311 2312 int 2313 bcm_fb2_cosq_port_burst_set(int unit, bcm_port_t port, 2314 bcm_cos_queue_t cosq, int burst) 2315 { 2316 int pps, temp_burst; 2317 2318 if (!IS_CPU_PORT(unit, port)) { 2319 return BCM_E_PORT; 2320 } else if (cosq >= NUM_CPU_COSQ(unit)) { 2321 return BCM_E_PARAM; 2322 } 2323 2324 /* Get the current PPS and BURST settings */ 2325 BCM_IF_ERROR_RETURN 2326 (_bcm_fb2_cosq_port_packet_bandwidth_get(unit, port, cosq, 2327 &pps, &temp_burst)); 2328 2329 /* Replace the current BURST setting, keep PPS the same */ 2330 return _bcm_fb2_cosq_port_packet_bandwidth_set(unit, port, cosq, 2331 pps, burst); 2332 } 2333 2334 int 2335 bcm_fb2_cosq_port_burst_get(int unit, bcm_port_t port, 2336 bcm_cos_queue_t cosq, int *burst) 2337 { 2338 int pps; 2339 2340 if (!IS_CPU_PORT(unit, port)) { 2341 return BCM_E_PORT; 2342 } else if (cosq >= NUM_CPU_COSQ(unit)) { 2343 return BCM_E_PARAM; 2344 } 2345 2346 return _bcm_fb2_cosq_port_packet_bandwidth_get(unit, port, cosq, 2347 &pps, burst); 2348 } 2349 #endif /* BCM_FIREBOLT2_SUPPORT */ 2350 2351 2352 #ifndef BCM_SW_STATE_DUMP_DISABLE 2353 /* 2354 * Function: 2355 * bcm_fb_cosq_sw_dump 2356 * Purpose: 2357 * Displays COS Queue information maintained by software. 2358 * Parameters: 2359 * unit - Device unit number 2360 * Returns: 2361 * None 2362 */ 2363 void 2364 bcm_fb_cosq_sw_dump(int unit) 2365 { 2366 LOG_CLI((BSL_META_U(unit, 2367 "\nSW Information COSQ - Unit %d\n"), unit)); 2368 LOG_CLI((BSL_META_U(unit, 2369 " Number: %d\n"), _num_cosq[unit])); 2370 2371 return; 2372 } 2373 #endif /* BCM_SW_STATE_DUMP_DISABLE */