cosq.c (349301B)
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 */ 10 11 #include <shared/bsl.h> 12 13 #include <sal/core/libc.h> 14 #include <soc/defs.h> 15 #if defined(BCM_KATANA_SUPPORT) 16 #include <soc/drv.h> 17 #include <soc/scache.h> 18 #include <soc/katana.h> 19 #include <soc/macutil.h> 20 #include <soc/profile_mem.h> 21 #ifdef BCM_CMICM_SUPPORT 22 #include <soc/cmicm.h> 23 #endif 24 #include <bcm/error.h> 25 #include <bcm/cosq.h> 26 #include <bcm_int/esw/mbcm.h> 27 #include <bcm_int/esw/firebolt.h> 28 #include <bcm_int/esw/katana.h> 29 #include <bcm_int/esw/stack.h> 30 #include <bcm_int/esw/cosq.h> 31 #include <bcm_int/esw/multicast.h> 32 33 #include <bcm_int/esw_dispatch.h> 34 35 #include <bcm/types.h> 36 37 #ifdef BCM_WARM_BOOT_SUPPORT 38 #include <bcm_int/esw/switch.h> 39 #endif /* BCM_WARM_BOOT_SUPPORT */ 40 41 #if defined(BCM_KATANA_SUPPORT) 42 #include <soc/katana2.h> 43 #endif 44 45 #define _BCM_COSQ_PARENT_BMAP_SET(bmap, bit) \ 46 if (bmap != NULL) { \ 47 SHR_BITSET(bmap, bit); \ 48 } 49 50 #define _BCM_COSQ_PARENT_BMAP_CLR(bmap, bit) \ 51 if (bmap != NULL) { \ 52 SHR_BITCLR(bmap, bit); \ 53 } 54 55 #define _BCM_KT_IS_UC_QUEUE(mmu_info,qid) \ 56 (((qid) < mmu_info->num_base_queues) ? 1 : 0) 57 58 59 #define KT_CELL_FIELD_MAX 0x3ffff 60 61 #define KT_QUEUE_FLUSH_BURST_MANTISSA 124 62 #define KT_QUEUE_FLUSH_BURST_EXP 14 63 #define KT_QUEUE_FLUSH_CYCLE_SEL 0 64 65 /* Sum of all of max bandwidth configured on all children 66 * nodes should be less than or equal to the parent node's 67 * max bandwidth. Hence using 90% of parent's node BW and dividing 68 * it by the num of children nodes when configuring the children nodes 69 * shpaer config. 70 */ 71 #define KT_COSQ_SHAPER_PERC 90 72 73 /* MMU cell size in bytes */ 74 #define _BCM_KT_COSQ_CELLSIZE 192 75 #define _BCM_KT_COSQ_EXT_CELLSIZE 768 76 77 #define _BCM_KT_NUM_UCAST_QUEUE_GROUP 8 78 #define _BCM_KT_NUM_VLAN_UCAST_QUEUE_GROUP 16 79 80 /* ==========Separate file for KT2 is surely required now ===== */ 81 /* For KT: #define _BCM_KT_NUM_PORT_SCHEDULERS 36 */ 82 /* For KT2: #define _BCM_KT_NUM_PORT_SCHEDULERS 42 */ 83 /* ============================================================ */ 84 #define _BCM_KT_NUM_PORT_SCHEDULERS 42 85 #define _BCM_KT_NUM_L0_SCHEDULER 256 86 #define _BCM_KT_NUM_L1_SCHEDULER 1024 87 #define _BCM_KT_NUM_L2_QUEUES 4096 88 #define _BCM_KT_NUM_TOTAL_SCHEDULERS (_BCM_KT_NUM_PORT_SCHEDULERS + \ 89 _BCM_KT_NUM_L0_SCHEDULER + \ 90 _BCM_KT_NUM_L1_SCHEDULER) 91 92 #define _BCM_KT_COSQ_LIST_NODE_INIT(list, node) \ 93 list[node].in_use = FALSE; \ 94 list[node].wrr_in_use = 0; \ 95 list[node].gport = -1; \ 96 list[node].base_index = -1; \ 97 list[node].numq = 0; \ 98 list[node].hw_index = -1; \ 99 list[node].level = -1; \ 100 list[node].cosq_attached_to = -1; \ 101 list[node].num_child = 0; \ 102 list[node].first_child = 4095; \ 103 list[node].cosq_map = NULL; \ 104 list[node].parent = NULL; \ 105 list[node].sibling = NULL; \ 106 list[node].child = NULL; 107 108 #define _BCM_KT_COSQ_NODE_INIT(node) \ 109 node->in_use = FALSE; \ 110 node->wrr_in_use = 0; \ 111 node->gport = -1; \ 112 node->base_index = -1; \ 113 node->numq = 0; \ 114 node->hw_index = -1; \ 115 node->level = -1; \ 116 node->cosq_attached_to = -1; \ 117 node->num_child = 0; \ 118 node->first_child = 4095; \ 119 node->cosq_map = NULL; \ 120 node->parent = NULL; \ 121 node->sibling = NULL; \ 122 node->child = NULL; 123 124 typedef enum { 125 _BCM_KT_COSQ_STATE_NO_CHANGE, 126 _BCM_KT_COSQ_STATE_DISABLE, 127 _BCM_KT_COSQ_STATE_ENABLE, 128 _BCM_KT_COSQ_STATE_SPRI_TO_WRR, 129 _BCM_KT_COSQ_STATE_WRR_TO_SPRI, 130 _BCM_KT_COSQ_STATE_MAX 131 }_bcm_kt_cosq_state_t; 132 133 typedef struct _bcm_kt_cosq_list_s { 134 int count; 135 SHR_BITDCL *bits; 136 }_bcm_kt_cosq_list_t; 137 138 typedef struct _bcm_kt_cosq_port_info { 139 int q_offset; 140 int q_limit; 141 }_bcm_kt_cosq_port_info_t; 142 143 typedef struct _bcm_kt_mmu_info_s { 144 int num_base_queues; /* Number of classical queues */ 145 int num_ext_queues; /* Number of extended queues */ 146 int num_sub_queues; /* Number of subscriber queues */ 147 int base_sub_queue; /* Base Subscriber queue */ 148 int qset_size; /* subscriber queue set size */ 149 uint32 num_queues; /* total number of queues */ 150 uint32 num_nodes; /* max number of sched nodes */ 151 uint32 max_nodes[_BCM_KT_COSQ_NODE_LEVEL_MAX]; /* max nodes in each level */ 152 bcm_gport_t *l1_gport_pair; /* L1 gport mapping for dynamic update */ 153 _bcm_kt_cosq_port_info_t *port; /* port information */ 154 _bcm_kt_cosq_list_t ext_qlist; /* list of extended queues */ 155 _bcm_kt_cosq_list_t sub_qlist; /* list of subscriber queues */ 156 _bcm_kt_cosq_list_t sched_list; /* list of sched nodes */ 157 _bcm_kt_cosq_list_t l0_sched_list; /* list of l0 sched nodes */ 158 _bcm_kt_cosq_list_t l1_sched_list; /* list of l1 sched nodes */ 159 _bcm_kt_cosq_list_t l2_base_qlist; /* list of l2 base queue index list */ 160 _bcm_kt_cosq_list_t l2_ext_qlist; /* list of l2 base queue index list */ 161 _bcm_kt_cosq_list_t l2_sub_qlist; /* list of l2 subscriber queue index list */ 162 163 _bcm_kt_cosq_node_t sched_node[_BCM_KT_NUM_TOTAL_SCHEDULERS]; /* sched nodes */ 164 _bcm_kt_cosq_node_t queue_node[_BCM_KT_NUM_L2_QUEUES]; /* queue nodes */ 165 uint32 intf_ref_cnt[BCM_MULTICAST_PORT_MAX]; /* Interface reference count 166 for queues */ 167 }_bcm_kt_mmu_info_t; 168 169 STATIC _bcm_kt_mmu_info_t *_bcm_kt_mmu_info[BCM_MAX_NUM_UNITS]; /* MMU info */ 170 171 STATIC soc_profile_mem_t *_bcm_kt_cos_map_profile[BCM_MAX_NUM_UNITS]; 172 STATIC soc_profile_mem_t *_bcm_kt_wred_profile[BCM_MAX_NUM_UNITS]; 173 174 STATIC int 175 _bcm_kt_cosq_child_node_at_input(_bcm_kt_cosq_node_t *node, int cosq, 176 _bcm_kt_cosq_node_t **child_node); 177 /* Number of COSQs configured for this device */ 178 STATIC int _bcm_kt_num_cosq[SOC_MAX_NUM_DEVICES]; 179 180 extern sal_mutex_t cosq_sync_lock[SOC_MAX_NUM_DEVICES]; 181 182 /* 183 * Function: 184 * _bcm_kt_cosq_localport_resolve 185 * Purpose: 186 * Resolve GRPOT if it is a local port 187 * Parameters: 188 * unit - (IN) unit number 189 * gport - (IN) GPORT identifier 190 * local_port - (OUT) local port number 191 * Returns: 192 * BCM_E_XXX 193 */ 194 STATIC int 195 _bcm_kt_cosq_localport_resolve(int unit, bcm_gport_t gport, 196 bcm_port_t *local_port) 197 { 198 bcm_module_t module; 199 bcm_port_t port; 200 bcm_trunk_t trunk; 201 int id, result; 202 203 if (!BCM_GPORT_IS_SET(gport)) { 204 /* Below SOC check is used for time-being for KT2 */ 205 if (SOC_IS_KATANA(unit)) { 206 if (!SOC_PORT_VALID(unit, gport)) { 207 return BCM_E_PORT; 208 } 209 } 210 *local_port = gport; 211 return BCM_E_NONE; 212 } else if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 213 BCM_GPORT_IS_SCHEDULER(gport) || 214 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport)) { 215 return BCM_E_PORT; 216 } 217 218 BCM_IF_ERROR_RETURN 219 (_bcm_esw_gport_resolve(unit, gport, &module, &port, &trunk, &id)); 220 221 BCM_IF_ERROR_RETURN(_bcm_esw_modid_is_local(unit, module, &result)); 222 if (result == FALSE) { 223 return BCM_E_PORT; 224 } 225 226 *local_port = port; 227 228 return BCM_E_NONE; 229 } 230 231 /* 232 * Function: 233 * _bcm_kt_node_index_get 234 * Purpose: 235 * Allocate free index from the given list 236 * Parameters: 237 * unit - (IN) unit number 238 * list - (IN) bit list 239 * start - (IN) start index 240 * end - (IN) end index 241 * qset - (IN) size of queue set 242 * range - (IN) range bits 243 * id - (OUT) start index 244 * Returns: 245 * BCM_E_XXX 246 */ 247 STATIC int 248 _bcm_kt_node_index_get(int unit, SHR_BITDCL *list, int start, int end, 249 int qset, int range, int *id) 250 { 251 int i, j, inc; 252 _bcm_kt_mmu_info_t *mmu_info; 253 254 if (_bcm_kt_mmu_info[unit] == NULL) { 255 return BCM_E_INIT; 256 } 257 mmu_info = _bcm_kt_mmu_info[unit]; 258 259 *id = -1; 260 261 if (range != qset) { 262 inc = 1; 263 for (i = start; i < end; i = (i + inc)) { 264 inc = 1; 265 for (j = i; j < (i + range); j++, inc++) { 266 if (SHR_BITGET(list, j) != 0) { 267 break; 268 } 269 } 270 271 if (j == (i + range) && (mmu_info->intf_ref_cnt[i] == 0)) { 272 *id = i; 273 return BCM_E_NONE; 274 } 275 } 276 if (i == end) { 277 return BCM_E_RESOURCE; 278 } 279 } 280 281 for (i = start; i < end; i = i + range) { 282 for (j = i; j < (i + range); j++) { 283 if (SHR_BITGET(list, j) != 0) { 284 break; 285 } 286 } 287 288 if (j == (i + range) && (mmu_info->intf_ref_cnt[i] == 0)) { 289 *id = i; 290 return BCM_E_NONE; 291 } 292 } 293 294 if (i == end) { 295 return BCM_E_RESOURCE; 296 } 297 298 return BCM_E_NONE; 299 } 300 301 /* 302 * Function: 303 * _bcm_kt_node_index_set 304 * Purpose: 305 * Mark indices as allocated 306 * Parameters: 307 * list - (IN) bit list 308 * start - (IN) start index 309 * range - (IN) range bits 310 * Returns: 311 * BCM_E_XXX 312 */ 313 STATIC int 314 _bcm_kt_node_index_set(_bcm_kt_cosq_list_t *list, int start, int range) 315 { 316 list->count += range; 317 SHR_BITSET_RANGE(list->bits, start, range); 318 319 return BCM_E_NONE; 320 } 321 322 /* 323 * Function: 324 * _bcm_kt_node_index_clear 325 * Purpose: 326 * Mark indices as free 327 * Parameters: 328 * list - (IN) bit list 329 * start - (IN) start index 330 * range - (IN) range bits 331 * Returns: 332 * BCM_E_XXX 333 */ 334 STATIC int 335 _bcm_kt_node_index_clear(_bcm_kt_cosq_list_t *list, int start, int range) 336 { 337 list->count -= range; 338 SHR_BITCLR_RANGE(list->bits, start, range); 339 340 return BCM_E_NONE; 341 } 342 343 /* 344 * Function: 345 * _bcm_kt_cosq_map_index_get 346 * Purpose: 347 * Allocate free index from the given list 348 * Parameters: 349 * list - (IN) bit list 350 * start - (IN) start index 351 * end - (IN) end index 352 * id - (OUT) start index 353 * Returns: 354 * BCM_E_XXX 355 */ 356 STATIC int 357 _bcm_kt_cosq_map_index_get(SHR_BITDCL *list, int start, int end, int *id) 358 { 359 int i; 360 361 for (i = start; i < end; i++) { 362 if (SHR_BITGET(list, i) != 0) { 363 continue; 364 } 365 *id = i; 366 return BCM_E_NONE; 367 } 368 369 return BCM_E_RESOURCE; 370 } 371 372 /* 373 * Function: 374 * _bcm_kt_cosq_map_index_set 375 * Purpose: 376 * Mark indices as allocated 377 * Parameters: 378 * list - (IN) bit list 379 * start - (IN) start index 380 * range - (IN) range bits 381 * Returns: 382 * BCM_E_XXX 383 */ 384 STATIC int 385 _bcm_kt_cosq_map_index_set(SHR_BITDCL *list, int start, int range) 386 { 387 SHR_BITSET_RANGE(list, start, range); 388 return BCM_E_NONE; 389 } 390 391 /* 392 * Function: 393 * _bcm_kt_cosq_map_index_clear 394 * Purpose: 395 * Mark indices as free 396 * Parameters: 397 * list - (IN) bit list 398 * start - (IN) start index 399 * range - (IN) range bits 400 * Returns: 401 * BCM_E_XXX 402 */ 403 STATIC int 404 _bcm_kt_cosq_map_index_clear(SHR_BITDCL *list, int start, int range) 405 { 406 SHR_BITCLR_RANGE(list, start, range); 407 return BCM_E_NONE; 408 } 409 410 /* 411 * Function: 412 * _bcm_kt_cosq_map_index_is_set 413 * Purpose: 414 * Check index is allocated 415 * Parameters: 416 * list - (IN) bit list 417 * index - (IN) index 418 * Returns: 419 * BCM_E_XXX 420 */ 421 STATIC int 422 _bcm_kt_cosq_map_index_is_set(SHR_BITDCL *list, int index) 423 { 424 if (SHR_BITGET(list, index) != 0) { 425 return TRUE; 426 } 427 428 return FALSE; 429 } 430 431 STATIC int 432 _bcm_kt_cosq_max_nodes_get(int unit, _bcm_kt_cosq_node_level_t level, 433 int *id) 434 { 435 _bcm_kt_mmu_info_t *mmu_info; 436 437 if (level < _BCM_KT_COSQ_NODE_LEVEL_ROOT || 438 level >= _BCM_KT_COSQ_NODE_LEVEL_MAX) { 439 return BCM_E_PARAM; 440 } 441 mmu_info = _bcm_kt_mmu_info[unit]; 442 *id = mmu_info->max_nodes[level]; 443 444 return BCM_E_NONE; 445 } 446 447 /* 448 * Function: 449 * _bcm_kt_cosq_alloc_clear 450 * Purpose: 451 * Allocate cosq memory and clear 452 * Parameters: 453 * size - (IN) size of memory required 454 * description- (IN) description about the structure 455 * Returns: 456 * BCM_E_XXX 457 */ 458 STATIC void * 459 _bcm_kt_cosq_alloc_clear(unsigned int size, char *description) 460 { 461 void *block_p; 462 463 block_p = sal_alloc(size, description); 464 465 if (block_p != NULL) { 466 sal_memset(block_p, 0, size); 467 } 468 469 return block_p; 470 } 471 472 /* 473 * Function: 474 * _bcm_kt_cosq_free_memory 475 * Purpose: 476 * Free memory allocated for mmu info members 477 * Parameters: 478 * mmu_info_p - (IN) MMU info pointer 479 * Returns: 480 * BCM_E_XXX 481 */ 482 STATIC void 483 _bcm_kt_cosq_free_memory(_bcm_kt_mmu_info_t *mmu_info_p) 484 { 485 sal_free(mmu_info_p->port); 486 sal_free(mmu_info_p->l1_gport_pair); 487 sal_free(mmu_info_p->ext_qlist.bits); 488 sal_free(mmu_info_p->sched_list.bits); 489 sal_free(mmu_info_p->l0_sched_list.bits); 490 sal_free(mmu_info_p->l1_sched_list.bits); 491 sal_free(mmu_info_p->l2_base_qlist.bits); 492 sal_free(mmu_info_p->l2_ext_qlist.bits); 493 494 if (mmu_info_p->sub_qlist.bits != NULL) { 495 sal_free(mmu_info_p->sub_qlist.bits); 496 } 497 if (mmu_info_p->l2_sub_qlist.bits != NULL) { 498 sal_free(mmu_info_p->l2_sub_qlist.bits); 499 } 500 } 501 502 /* 503 * Function: 504 * _bcm_kt_cosq_node_get 505 * Purpose: 506 * Get internal information of queue group or scheduler type GPORT 507 * Parameters: 508 * unit - (IN) unit number 509 * gport - (IN) queue group/scheduler GPORT identifier 510 * modid - (OUT) module identifier 511 * port - (OUT) port number 512 * id - (OUT) queue group or scheduler identifier 513 * node - (OUT) node structure for the specified GPORT 514 * Returns: 515 * BCM_E_XXX 516 */ 517 STATIC int 518 _bcm_kt_cosq_node_get(int unit, bcm_gport_t gport, bcm_module_t *modid, 519 bcm_port_t *port, int *id, _bcm_kt_cosq_node_t **node) 520 { 521 soc_info_t *si; 522 _bcm_kt_mmu_info_t *mmu_info; 523 _bcm_kt_cosq_node_t *node_base; 524 bcm_module_t modid_out = 0; 525 bcm_port_t port_out = 0; 526 uint32 encap_id = 0; 527 int index; 528 529 si = &SOC_INFO(unit); 530 531 if (_bcm_kt_mmu_info[unit] == NULL) { 532 return BCM_E_INIT; 533 } 534 535 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 536 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid_out)); 537 port_out = BCM_GPORT_UCAST_QUEUE_GROUP_SYSPORTID_GET(gport); 538 } else if (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport)) { 539 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid_out)); 540 port_out = BCM_GPORT_UCAST_SUBSCRIBER_QUEUE_GROUP_SYSPORTID_GET(gport); 541 } else if (BCM_GPORT_IS_SCHEDULER(gport)) { 542 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid_out)); 543 port_out = BCM_GPORT_SCHEDULER_GET(gport) & 0xff; 544 } else if (BCM_GPORT_IS_LOCAL(gport)) { 545 encap_id = BCM_GPORT_LOCAL_GET(gport); 546 port_out = encap_id; 547 } else if (BCM_GPORT_IS_MODPORT(gport)) { 548 /* get the local_port */ 549 BCM_IF_ERROR_RETURN( 550 _bcm_kt_cosq_localport_resolve(unit, gport, &port_out)); 551 encap_id = port_out; 552 } else { 553 return BCM_E_PORT; 554 } 555 556 /* Below SOC check is used for time-being for KT2 */ 557 if (SOC_IS_KATANA(unit)) { 558 if (!SOC_PORT_VALID(unit, port_out)) { 559 return BCM_E_PORT; 560 } 561 } 562 563 mmu_info = _bcm_kt_mmu_info[unit]; 564 565 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 566 encap_id = BCM_GPORT_UCAST_QUEUE_GROUP_QID_GET(gport); 567 index = encap_id; 568 if (index < mmu_info->num_base_queues) { 569 node_base = mmu_info->queue_node; 570 } else { 571 if (si->port_num_ext_cosq[port_out] == 0) { 572 return BCM_E_PORT; 573 } 574 node_base = mmu_info->queue_node; 575 } 576 } else if (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport)) { 577 encap_id = BCM_GPORT_UCAST_SUBSCRIBER_QUEUE_GROUP_QID_GET(gport); 578 index = encap_id; 579 if (mmu_info->num_sub_queues > 0) { 580 index += mmu_info->base_sub_queue; 581 } else { 582 index += mmu_info->num_base_queues; 583 } 584 node_base = mmu_info->queue_node; 585 } 586 else { 587 if (BCM_GPORT_IS_SCHEDULER(gport)) { 588 /* scheduler */ 589 encap_id = (BCM_GPORT_SCHEDULER_GET(gport) >> 8) & 0x7ff; 590 if (encap_id == 0) { 591 encap_id = (BCM_GPORT_SCHEDULER_GET(gport) & 0xff); 592 } 593 } 594 index = encap_id; 595 if (index >= _BCM_KT_NUM_TOTAL_SCHEDULERS) { 596 return BCM_E_PORT; 597 } 598 node_base = mmu_info->sched_node; 599 } 600 601 if (!(BCM_GPORT_IS_LOCAL(gport) || BCM_GPORT_IS_MODPORT(gport)) && 602 node_base[index].numq == 0) { 603 return BCM_E_NOT_FOUND; 604 } 605 606 if (modid != NULL) { 607 *modid = modid_out; 608 } 609 if (port != NULL) { 610 *port = port_out; 611 } 612 if (id != NULL) { 613 *id = encap_id; 614 } 615 if (node != NULL) { 616 *node = &node_base[index]; 617 } 618 619 return BCM_E_NONE; 620 } 621 622 int 623 _bcm_kt_cosq_port_resolve(int unit, bcm_gport_t gport, bcm_module_t *modid, 624 bcm_port_t *port, bcm_trunk_t *trunk_id, int *id, 625 int *qnum) 626 { 627 _bcm_kt_cosq_node_t *node; 628 629 BCM_IF_ERROR_RETURN 630 (_bcm_kt_cosq_node_get(unit, gport, modid, port, NULL, &node)); 631 *trunk_id = -1; 632 633 if (qnum) { 634 if (node->hw_index == -1) { 635 return BCM_E_PARAM; 636 } 637 *qnum = node->hw_index; 638 } 639 640 return BCM_E_NONE; 641 } 642 643 /* 644 * Function: 645 * _bcm_kt_cosq_gport_traverse 646 * Purpose: 647 * Walks through the valid COSQ GPORTs and calls 648 * the user supplied callback function for each entry. 649 * Parameters: 650 * unit - (IN) unit number 651 * gport - (IN) 652 * cb - (IN) Callback function. 653 * user_data - (IN) User data to be passed to callback function 654 * Returns: 655 * BCM_E_NONE - Success. 656 * BCM_E_XXX 657 */ 658 int 659 _bcm_kt_cosq_gport_traverse(int unit, bcm_gport_t gport, 660 bcm_cosq_gport_traverse_cb cb, 661 void *user_data) 662 { 663 _bcm_kt_cosq_node_t *node; 664 uint32 flags = BCM_COSQ_GPORT_SCHEDULER; 665 int rv = BCM_E_NONE; 666 667 BCM_IF_ERROR_RETURN 668 (_bcm_kt_cosq_node_get(unit, gport, NULL, NULL, NULL, &node)); 669 670 if (node != NULL) { 671 if (node->level == _BCM_KT_COSQ_NODE_LEVEL_L2) { 672 flags = BCM_GPORT_IS_UCAST_QUEUE_GROUP(node->gport) ? 673 BCM_COSQ_GPORT_UCAST_QUEUE_GROUP : 674 BCM_COSQ_GPORT_SUBSCRIBER; 675 } 676 rv = cb(unit, gport, node->numq, flags, 677 node->gport, user_data); 678 if (BCM_FAILURE(rv)) { 679 #ifdef BCM_CB_ABORT_ON_ERR 680 if (SOC_CB_ABORT_ON_ERR(unit)) { 681 return rv; 682 } 683 #endif 684 } 685 } else { 686 return BCM_E_NONE; 687 } 688 689 if (node->sibling != NULL) { 690 _bcm_kt_cosq_gport_traverse(unit, node->sibling->gport, cb, user_data); 691 } 692 693 if (node->child != NULL) { 694 _bcm_kt_cosq_gport_traverse(unit, node->child->gport, cb, user_data); 695 } 696 697 return BCM_E_NONE; 698 } 699 700 /* 701 * Function: 702 * _bcm_kt_cosq_index_resolve 703 * Purpose: 704 * Find hardware index for the given port/cosq 705 * Parameters: 706 * unit - (IN) unit number 707 * port - (IN) port number or GPORT identifier 708 * cosq - (IN) COS queue number 709 * style - (IN) index style (_BCM_KA_COSQ_INDEX_STYLE_XXX) 710 * local_port - (OUT) local port number 711 * index - (OUT) result index 712 * count - (OUT) number of index 713 * Returns: 714 * BCM_E_XXX 715 */ 716 int 717 _bcm_kt_cosq_index_resolve(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 718 _bcm_kt_cosq_index_style_t style, 719 bcm_port_t *local_port, int *index, int *count) 720 { 721 _bcm_kt_cosq_node_t *node, *cur_node; 722 bcm_port_t resolved_port; 723 int resolved_index; 724 int id, startq, numq = 0; 725 _bcm_kt_mmu_info_t *mmu_info; 726 727 if (cosq < -1) { 728 return BCM_E_PARAM; 729 } else if (cosq == -1) { 730 startq = 0; 731 } else { 732 startq = cosq; 733 } 734 735 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 736 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port) || 737 BCM_GPORT_IS_SCHEDULER(port)) { 738 BCM_IF_ERROR_RETURN 739 (_bcm_kt_cosq_node_get(unit, port, NULL, &resolved_port, &id, 740 &node)); 741 if ((node->cosq_attached_to < 0) || (node->hw_index == -1)) { 742 /* Not resolved yet */ 743 return BCM_E_NOT_FOUND; 744 } 745 if (BCM_GPORT_IS_SCHEDULER(port) && 746 (style != _BCM_KT_COSQ_INDEX_STYLE_BUCKET)) { 747 numq = node->numq; 748 if (startq >= numq) { 749 return BCM_E_PARAM; 750 } 751 } 752 else { 753 numq=node->numq; 754 } 755 } else { 756 /* optionally validate port */ 757 BCM_IF_ERROR_RETURN 758 (_bcm_kt_cosq_localport_resolve(unit, port, &resolved_port)); 759 if (resolved_port < 0) { 760 return BCM_E_PORT; 761 } 762 node = NULL; 763 numq = 0; 764 } 765 766 switch (style) { 767 case _BCM_KT_COSQ_INDEX_STYLE_BUCKET: 768 if (node != NULL) { 769 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 770 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port)) { 771 resolved_index = node->hw_index; 772 } else if (BCM_GPORT_IS_SCHEDULER(port)) { 773 if (node->level > _BCM_KT_COSQ_NODE_LEVEL_L1) { 774 return BCM_E_PARAM; 775 } 776 resolved_index = node->hw_index; 777 } else { 778 return BCM_E_PARAM; 779 } 780 } else { /* node == NULL */ 781 mmu_info = _bcm_kt_mmu_info[unit]; 782 numq = mmu_info->port[resolved_port].q_limit - 783 mmu_info->port[resolved_port].q_offset; 784 785 if (cosq >= numq) { 786 return BCM_E_PARAM; 787 } 788 resolved_index = mmu_info->port[resolved_port].q_offset + startq; 789 } 790 break; 791 792 case _BCM_KT_COSQ_INDEX_STYLE_WRED: 793 if (node != NULL) { 794 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 795 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port)) { 796 resolved_index = node->hw_index; 797 } else if (BCM_GPORT_IS_SCHEDULER(port)) { 798 if (node->level != _BCM_KT_COSQ_NODE_LEVEL_L1) { 799 return BCM_E_PARAM; 800 } 801 resolved_index = node->hw_index; 802 } else { 803 return BCM_E_PARAM; 804 } 805 } else { /* node == NULL */ 806 mmu_info = _bcm_kt_mmu_info[unit]; 807 numq = mmu_info->port[resolved_port].q_limit - 808 mmu_info->port[resolved_port].q_offset; 809 810 if (cosq >= numq) { 811 return BCM_E_PARAM; 812 } 813 resolved_index = mmu_info->port[resolved_port].q_offset + startq; 814 } 815 break; 816 817 case _BCM_KT_COSQ_INDEX_STYLE_SCHEDULER: 818 if (node != NULL) { 819 if (BCM_GPORT_IS_SCHEDULER(port)) { 820 for (cur_node = node->child; cur_node != NULL; 821 cur_node = cur_node->sibling) { 822 if (cur_node->cosq_attached_to == startq) { 823 break; 824 } 825 } 826 827 if (cur_node == NULL) { 828 /* this cosq is not yet attached */ 829 return BCM_E_INTERNAL; 830 } 831 832 if (node->numq <= 8) { 833 resolved_index = node->base_index + startq; 834 } else { 835 resolved_index = cur_node->hw_index; 836 } 837 } else { /* unicast queue group or multicast queue group */ 838 return BCM_E_PARAM; 839 } 840 } else { /* node == NULL */ 841 mmu_info = _bcm_kt_mmu_info[unit]; 842 numq = mmu_info->port[resolved_port].q_limit - 843 mmu_info->port[resolved_port].q_offset; 844 845 if (cosq >= numq) { 846 return BCM_E_PARAM; 847 } 848 resolved_index = mmu_info->port[resolved_port].q_offset + startq; 849 } 850 break; 851 case _BCM_KT_COSQ_INDEX_STYLE_UCAST_QUEUE: 852 mmu_info = _bcm_kt_mmu_info[unit]; 853 if (node != NULL) { 854 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 855 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port)) { 856 resolved_index = node->hw_index; 857 } else if (BCM_GPORT_IS_SCHEDULER(port)) { 858 if (node->level != _BCM_KT_COSQ_NODE_LEVEL_L1) { 859 return BCM_E_PARAM; 860 } 861 resolved_index = node->base_index; 862 } else { 863 return BCM_E_PARAM; 864 } 865 866 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) { 867 resolved_index -= mmu_info->port[resolved_port].q_offset; 868 } 869 } else { /* node == NULL */ 870 mmu_info = _bcm_kt_mmu_info[unit]; 871 numq = mmu_info->port[resolved_port].q_limit - 872 mmu_info->port[resolved_port].q_offset; 873 874 if (startq >= numq) { 875 return BCM_E_PARAM; 876 } 877 resolved_index = startq; 878 } 879 break; 880 case _BCM_KT_COSQ_INDEX_STYLE_QUEUE_REPLICATION: 881 mmu_info = _bcm_kt_mmu_info[unit]; 882 if (node != NULL) { 883 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 884 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port)) { 885 resolved_index = node->hw_index; 886 } else { 887 return BCM_E_PARAM; 888 } 889 890 } else { /* node == NULL */ 891 mmu_info = _bcm_kt_mmu_info[unit]; 892 numq = mmu_info->port[resolved_port].q_limit - 893 mmu_info->port[resolved_port].q_offset; 894 895 if (startq >= numq) { 896 return BCM_E_PARAM; 897 } 898 resolved_index = startq + mmu_info->port 899 [resolved_port].q_offset; 900 } 901 break; 902 default: 903 return BCM_E_INTERNAL; 904 } 905 906 if (local_port != NULL) { 907 *local_port = resolved_port; 908 } 909 if (index != NULL) { 910 *index = resolved_index; 911 } 912 if (count != NULL) { 913 *count = (cosq == -1) ? numq : 1; 914 } 915 916 return BCM_E_NONE; 917 } 918 919 int 920 bcm_kt_sw_hw_queue(int unit, int *queue_array) 921 { 922 _bcm_kt_mmu_info_t *mmu_info; 923 int index = 0; 924 mmu_info = _bcm_kt_mmu_info[unit]; 925 926 for (index = 0; index < mmu_info->num_queues; index++){ 927 if (mmu_info->queue_node[index].hw_index == *queue_array){ 928 *queue_array = index; 929 return BCM_E_NONE; 930 } 931 } 932 index = -1; 933 return BCM_E_PARAM; 934 } 935 936 int 937 bcm_kt_is_uc_queue(int unit,int queue_id,int *is_ucq) 938 { 939 _bcm_kt_mmu_info_t *mmu_info; 940 mmu_info = _bcm_kt_mmu_info[unit]; 941 942 if(_BCM_KT_IS_UC_QUEUE(mmu_info, queue_id)) 943 { 944 *is_ucq = TRUE; 945 } 946 else 947 { 948 *is_ucq = FALSE ; 949 } 950 return BCM_E_NONE; 951 } 952 /* 953 * Function: 954 * _bcm_kt_cosq_node_resolve 955 * Purpose: 956 * Resolve queue number in the specified scheduler tree and its subtree 957 * Parameters: 958 * unit - (IN) unit number 959 * node - (IN) node structure for the specified scheduler node 960 * cosq - (IN) COS queue to attach to 961 * Returns: 962 * BCM_E_XXX 963 */ 964 STATIC int 965 _bcm_kt_cosq_node_resolve(int unit, _bcm_kt_cosq_node_t *node, 966 bcm_cos_queue_t cosq) 967 { 968 _bcm_kt_cosq_node_t *parent; 969 _bcm_kt_mmu_info_t *mmu_info; 970 _bcm_kt_cosq_list_t *list; 971 bcm_port_t local_port; 972 int alloc_size; 973 int numq, id = 0; 974 int offset, limit; 975 976 parent = node->parent; 977 if (parent == NULL) { 978 /* Not attached, should never happen */ 979 return BCM_E_NOT_FOUND; 980 } 981 982 if (parent->numq == 0 || parent->numq < -1) { 983 return BCM_E_PARAM; 984 } 985 986 if (parent->cosq_map == NULL) { 987 alloc_size = SHR_BITALLOCSIZE(parent->numq); 988 parent->cosq_map = _bcm_kt_cosq_alloc_clear(alloc_size, 989 "cosq_map"); 990 if (parent->cosq_map == NULL) { 991 return BCM_E_MEMORY; 992 } 993 } 994 995 if (cosq < 0) { 996 BCM_IF_ERROR_RETURN 997 (_bcm_kt_cosq_map_index_get(parent->cosq_map, 998 0, parent->numq, &id)); 999 BCM_IF_ERROR_RETURN 1000 (_bcm_kt_cosq_map_index_set(parent->cosq_map, id, 1)); 1001 node->cosq_attached_to = id; 1002 } else { 1003 if (_bcm_kt_cosq_map_index_is_set(parent->cosq_map, 1004 cosq) == TRUE) { 1005 return BCM_E_EXISTS; 1006 } 1007 BCM_IF_ERROR_RETURN 1008 (_bcm_kt_cosq_map_index_set(parent->cosq_map,cosq, 1)); 1009 node->cosq_attached_to = cosq; 1010 } 1011 1012 mmu_info = _bcm_kt_mmu_info[unit]; 1013 numq = (parent->numq > 8) ? 8 : parent->numq; 1014 1015 switch (parent->level) { 1016 case _BCM_KT_COSQ_NODE_LEVEL_ROOT: 1017 list = &mmu_info->l0_sched_list; 1018 if (parent->base_index < 0) { 1019 BCM_IF_ERROR_RETURN 1020 (_bcm_kt_node_index_get(unit, list->bits, 0, mmu_info->max_nodes[node->level], 1021 mmu_info->qset_size, numq, &id)); 1022 _bcm_kt_node_index_set(list, id, numq); 1023 parent->base_index = id; 1024 1025 } else if (node->cosq_attached_to >= 8) { 1026 BCM_IF_ERROR_RETURN 1027 (_bcm_kt_node_index_get(unit, list->bits, 0, mmu_info->max_nodes[node->level], 1028 mmu_info->qset_size, 1, &id)); 1029 _bcm_kt_node_index_set(list, id, 1); 1030 1031 } 1032 break; 1033 1034 case _BCM_KT_COSQ_NODE_LEVEL_L0: 1035 list = &mmu_info->l1_sched_list; 1036 if (parent->base_index < 0) { 1037 BCM_IF_ERROR_RETURN 1038 (_bcm_kt_node_index_get(unit, list->bits, 0, mmu_info->max_nodes[node->level], 1039 mmu_info->qset_size, numq, &id)); 1040 _bcm_kt_node_index_set(list, id, numq); 1041 parent->base_index = id; 1042 } else if (node->cosq_attached_to >= 8) { 1043 BCM_IF_ERROR_RETURN 1044 (_bcm_kt_node_index_get(unit, list->bits, 0, mmu_info->max_nodes[node->level], 1045 mmu_info->qset_size, 1, &id)); 1046 _bcm_kt_node_index_set(list, id, 1); 1047 1048 } 1049 break; 1050 1051 case _BCM_KT_COSQ_NODE_LEVEL_L1: 1052 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(node->gport)) { 1053 list = &mmu_info->l2_base_qlist; 1054 local_port = BCM_GPORT_UCAST_QUEUE_GROUP_SYSPORTID_GET(node->gport); 1055 offset = mmu_info->port[local_port].q_offset; 1056 limit = mmu_info->port[local_port].q_limit; 1057 } else if (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(node->gport)) { 1058 local_port = BCM_GPORT_UCAST_SUBSCRIBER_QUEUE_GROUP_SYSPORTID_GET 1059 (node->gport); 1060 offset = 0; 1061 if (mmu_info->num_sub_queues > 0) { 1062 list = &mmu_info->l2_sub_qlist; 1063 limit = mmu_info->num_sub_queues; 1064 } else { 1065 list = &mmu_info->l2_ext_qlist; 1066 limit = mmu_info->num_ext_queues; 1067 } 1068 } else { 1069 list = &mmu_info->l2_ext_qlist; 1070 offset = 0; 1071 limit = mmu_info->num_ext_queues; 1072 } 1073 if (node->cosq_attached_to >= 8) { 1074 numq = 1; 1075 } 1076 1077 if (node->hw_index < 0) { 1078 if ((BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(node->gport)) && 1079 (parent->base_index < 0) && 1080 (node->cosq_attached_to < 8)) { 1081 BCM_IF_ERROR_RETURN 1082 (_bcm_kt_node_index_get(unit, list->bits, offset, limit, 1083 mmu_info->qset_size, numq, &id)); 1084 1085 _bcm_kt_node_index_set(list, id, numq); 1086 if (mmu_info->num_sub_queues > 0) { 1087 parent->base_index = id + mmu_info->base_sub_queue ; 1088 } else { 1089 parent->base_index = id + mmu_info->num_base_queues ; 1090 } 1091 node->base_index = parent->base_index; 1092 } else if((parent->base_index < 0) && (node->cosq_attached_to < 8)) { 1093 BCM_IF_ERROR_RETURN 1094 (_bcm_kt_node_index_get(unit, list->bits, offset, limit, 1095 mmu_info->qset_size, numq, &id)); 1096 _bcm_kt_node_index_set(list, id, numq); 1097 parent->base_index = (BCM_GPORT_IS_UCAST_QUEUE_GROUP(node->gport)) ? id : 1098 (id + mmu_info->num_base_queues); 1099 node->base_index = parent->base_index; 1100 } else if (node->cosq_attached_to >= 8) { 1101 BCM_IF_ERROR_RETURN 1102 (_bcm_kt_node_index_get(unit, list->bits, offset, limit, 1103 mmu_info->qset_size, numq, &id)); 1104 _bcm_kt_node_index_set(list, id, numq); 1105 } 1106 if (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(node->gport)) { 1107 if (mmu_info->num_sub_queues > 0) { 1108 id += mmu_info->base_sub_queue ; 1109 } else { 1110 id += mmu_info->num_base_queues; 1111 } 1112 } else { 1113 id += (BCM_GPORT_IS_UCAST_QUEUE_GROUP(node->gport)) ? 1114 0 : mmu_info->num_base_queues; 1115 } 1116 } else { 1117 if (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(node->gport)) { 1118 /* Input 0 should be atttached 1119 * first to get the correct base 1120 */ 1121 if (node->cosq_attached_to < 8) { 1122 if ((BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(node->gport)) && 1123 parent->base_index < 0) { 1124 parent->base_index = node->hw_index; 1125 } 1126 } 1127 } 1128 } 1129 break; 1130 1131 case _BCM_KT_COSQ_NODE_LEVEL_L2: 1132 /* passthru */ 1133 default: 1134 return BCM_E_PARAM; 1135 1136 } 1137 1138 if (parent->numq <= 8) { 1139 if (parent->level <= _BCM_KT_COSQ_NODE_LEVEL_L1) { 1140 if (node->hw_index < 0) { 1141 node->hw_index = parent->base_index + node->cosq_attached_to; 1142 } 1143 } 1144 1145 parent->num_child++; 1146 /* get the lowest cosq as a first child */ 1147 if (node->hw_index < parent->first_child) { 1148 parent->first_child = node->hw_index; 1149 } 1150 } else { 1151 if (parent->level <= _BCM_KT_COSQ_NODE_LEVEL_L1) { 1152 if (node->hw_index < 0) { 1153 node->hw_index = (node->cosq_attached_to < 8) ? 1154 (parent->base_index + node->cosq_attached_to) : id; 1155 } 1156 if (node->cosq_attached_to >= 8) { 1157 node->wrr_in_use = 1; 1158 } 1159 } 1160 parent->num_child++; 1161 } 1162 1163 return BCM_E_NONE; 1164 } 1165 1166 /* 1167 * Function: 1168 * _bcm_kt_cosq_node_unresolve 1169 * Purpose: 1170 * Unresolve queue number in the specified scheduler tree and its subtree 1171 * Parameters: 1172 * unit - (IN) unit number 1173 * node - (IN) node structure for the specified scheduler node 1174 * cosq - (IN) COS queue to attach to 1175 * Returns: 1176 * BCM_E_XXX 1177 */ 1178 STATIC int 1179 _bcm_kt_cosq_node_unresolve(int unit, _bcm_kt_cosq_node_t *node, bcm_cos_queue_t cosq) 1180 { 1181 _bcm_kt_cosq_node_t *cur_node, *parent; 1182 _bcm_kt_mmu_info_t *mmu_info; 1183 _bcm_kt_cosq_list_t *list; 1184 uint32 map; 1185 int min_index; 1186 int id, offset, numq; 1187 int min_flag = 0; 1188 1189 if (node->cosq_attached_to < 0) { 1190 /* Has been unresolved already */ 1191 return BCM_E_NONE; 1192 } 1193 1194 parent = node->parent; 1195 1196 if (parent->numq == 0 || parent->numq < -1) { 1197 return BCM_E_PARAM; 1198 } 1199 1200 if (parent->numq <= 8) { 1201 /* find the current cosq_attached_to usage */ 1202 map = 0; 1203 if (parent->first_child == node->hw_index && node->wrr_in_use == 0) { 1204 min_flag = 1; 1205 min_index = (node->level == _BCM_KT_COSQ_NODE_LEVEL_L2) ? 4095 : 1206 ((node->level == _BCM_KT_COSQ_NODE_LEVEL_L1) ? 1023 : 255); 1207 } else { 1208 min_index = parent->first_child; 1209 } 1210 1211 for (cur_node = parent->child; cur_node != NULL; 1212 cur_node = cur_node->sibling) { 1213 if (cur_node->cosq_attached_to >= 0) { 1214 map |= 1 << cur_node->cosq_attached_to; 1215 /* dont update the min node is not this node */ 1216 if (min_flag && cur_node->hw_index != node->hw_index) { 1217 if (cur_node->hw_index < min_index) { 1218 min_index = cur_node->hw_index; 1219 } 1220 } 1221 } 1222 } 1223 1224 if (!(map & (1 << node->cosq_attached_to))) { 1225 return BCM_E_PARAM; 1226 } 1227 1228 BCM_IF_ERROR_RETURN 1229 (_bcm_kt_cosq_map_index_clear(parent->cosq_map, 1230 node->cosq_attached_to, 1)); 1231 parent->first_child = min_index; 1232 1233 } else { 1234 1235 /* check whether the entry is available */ 1236 for (cur_node = parent->child; cur_node != NULL; 1237 cur_node = cur_node->sibling) { 1238 if (cur_node->gport == node->gport) { 1239 break; 1240 } 1241 } 1242 1243 if (cur_node == NULL) { 1244 return BCM_E_PARAM; 1245 } 1246 BCM_IF_ERROR_RETURN 1247 (_bcm_kt_cosq_map_index_clear(parent->cosq_map, 1248 cur_node->cosq_attached_to, 1)); 1249 } 1250 1251 mmu_info = _bcm_kt_mmu_info[unit]; 1252 numq = (parent->numq > 8) ? 8 : parent->numq; 1253 1254 switch (parent->level) { 1255 case _BCM_KT_COSQ_NODE_LEVEL_ROOT: 1256 list = &mmu_info->l0_sched_list; 1257 parent->num_child--; 1258 if (parent->num_child >= 0) { 1259 if (node->cosq_attached_to >= 8) { 1260 _bcm_kt_node_index_clear(list, node->hw_index, 1); 1261 } 1262 if (parent->num_child == 0 && 1263 parent->base_index >= 0) { 1264 /* release contiguous queue ids */ 1265 _bcm_kt_node_index_clear(list, parent->base_index, numq); 1266 parent->base_index = -1; 1267 } 1268 } 1269 break; 1270 1271 case _BCM_KT_COSQ_NODE_LEVEL_L0: 1272 list = &mmu_info->l1_sched_list; 1273 parent->num_child--; 1274 if (parent->num_child >= 0) { 1275 if (node->cosq_attached_to >= 8) { 1276 _bcm_kt_node_index_clear(list, node->hw_index, 1); 1277 } 1278 if (parent->num_child == 0 && 1279 parent->base_index >= 0) { 1280 /* release contiguous queue ids */ 1281 _bcm_kt_node_index_clear(list, parent->base_index, numq); 1282 parent->base_index = -1; 1283 } 1284 } 1285 break; 1286 1287 case _BCM_KT_COSQ_NODE_LEVEL_L1: 1288 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(node->gport)) { 1289 list = &mmu_info->l2_base_qlist; 1290 offset = 0; 1291 } else if (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(node->gport) 1292 && (mmu_info->num_sub_queues > 0)) { 1293 list = &mmu_info->l2_sub_qlist; 1294 offset = mmu_info->base_sub_queue; 1295 } else { 1296 list = &mmu_info->l2_ext_qlist; 1297 offset = mmu_info->num_base_queues; 1298 } 1299 parent->num_child--; 1300 id = node->hw_index - offset; 1301 if (parent->num_child >= 0) { 1302 if (node->cosq_attached_to >= 8) { 1303 _bcm_kt_node_index_clear(list, id, 1); 1304 } 1305 if (parent->num_child == 0 && 1306 parent->base_index >= 0) { 1307 /* release contiguous queue ids */ 1308 id = parent->base_index - offset; 1309 _bcm_kt_node_index_clear(list, id, numq); 1310 parent->base_index = -1; 1311 } 1312 } 1313 break; 1314 1315 case _BCM_KT_COSQ_NODE_LEVEL_L2: 1316 /* passthru */ 1317 default: 1318 return BCM_E_PARAM; 1319 1320 } 1321 1322 return BCM_E_NONE; 1323 } 1324 1325 STATIC int 1326 _bcm_kt_cosq_valid_werr_node(int unit, _bcm_kt_cosq_node_t *node, 1327 int cosq, int spri) 1328 { 1329 _bcm_kt_cosq_node_t *cur_node; 1330 uint8 spri_vector = 0; 1331 uint8 mask, mask_lower, mask_upper; 1332 1333 if (cosq >= 8) { 1334 return 1; 1335 } 1336 for (cur_node = node->child; cur_node != NULL; 1337 cur_node = cur_node->sibling) { 1338 if ((cur_node->cosq_attached_to < 8) && (cur_node->wrr_in_use == 0)) { 1339 spri_vector |= (1 << cur_node->cosq_attached_to); 1340 } 1341 } 1342 mask_lower = ~(0xFF << cosq); 1343 mask_upper = 0xFF << (cosq + 1); 1344 1345 if ((spri_vector & mask_lower) && (spri_vector & mask_upper)) { 1346 /* if queues are not contiguous return invalid */ 1347 return 0; 1348 } 1349 1350 if (((spri_vector & mask_lower) == 0) && ((spri_vector & mask_upper) != 0)) { 1351 mask = spri_vector & mask_upper; 1352 if ((spri == 0) || (mask & (1 << (cosq + 1)))) { 1353 /* check the next queue also in spri if cosq is spri */ 1354 return 1; 1355 } 1356 } else if (((spri_vector & mask_lower) != 0) && ((spri_vector & mask_upper) == 0)) { 1357 mask = spri_vector & mask_lower; 1358 if ((spri == 0) || (mask & (1 << (cosq - 1)))) { 1359 /* check previous queue also in spri if cosq is spri */ 1360 return 1; 1361 } 1362 } else { 1363 /* this is the first queue */ 1364 return 1; 1365 } 1366 1367 return 0; 1368 } 1369 1370 STATIC int 1371 _bcm_kt_cosq_dynamic_bw_update(int unit, soc_mem_t config_mem, 1372 int index, int hw_index, 1373 lls_l2_shaper_config_lower_entry_t l2_shaper_entry) 1374 { 1375 soc_mem_t bucket_mem; 1376 lls_l2_shaper_bucket_lower_entry_t l2_bucket_max_entry; 1377 lls_l2_shaper_config_lower_entry_t l2_temp_entry; 1378 uint32 i; 1379 int rv = BCM_E_NONE; 1380 static const soc_field_t rate_exp_fields[] = { 1381 C_MAX_REF_RATE_EXP_0f, C_MAX_REF_RATE_EXP_1f, 1382 C_MAX_REF_RATE_EXP_2f, C_MAX_REF_RATE_EXP_3f 1383 }; 1384 static const soc_field_t rate_mant_fields[] = { 1385 C_MAX_REF_RATE_MANT_0f, C_MAX_REF_RATE_MANT_1f, 1386 C_MAX_REF_RATE_MANT_2f, C_MAX_REF_RATE_MANT_3f 1387 }; 1388 static const soc_field_t not_active_fields[] = { 1389 NOT_ACTIVE_IN_LLS_0f, NOT_ACTIVE_IN_LLS_1f, 1390 NOT_ACTIVE_IN_LLS_2f, NOT_ACTIVE_IN_LLS_3f 1391 }; 1392 1393 /* Change L2 max shaper configuration back to original setting. */ 1394 bucket_mem = (config_mem == LLS_L2_SHAPER_CONFIG_LOWERm) ? 1395 LLS_L2_SHAPER_BUCKET_LOWERm : 1396 LLS_L2_SHAPER_BUCKET_UPPERm; 1397 sal_memset(&l2_bucket_max_entry, 0, sizeof(lls_l2_shaper_bucket_lower_entry_t)); 1398 sal_memcpy(&l2_temp_entry, &l2_shaper_entry, 1399 sizeof(lls_l2_shaper_config_lower_entry_t)); 1400 for (i = 0; i < 4; i++) { 1401 soc_mem_field32_set(unit, config_mem, &l2_temp_entry, 1402 rate_exp_fields[i], 0); 1403 soc_mem_field32_set(unit, config_mem, &l2_temp_entry, 1404 rate_mant_fields[i], 0); 1405 soc_mem_field32_set(unit, bucket_mem, &l2_bucket_max_entry, 1406 not_active_fields[i], 1); 1407 } 1408 SOC_EGRESS_METERING_LOCK(unit); 1409 rv = soc_mem_write(unit, config_mem, MEM_BLOCK_ALL, 1410 index/8, &l2_temp_entry); 1411 if (rv < 0) { 1412 SOC_EGRESS_METERING_UNLOCK(unit); 1413 return rv; 1414 } 1415 1416 rv = soc_mem_write(unit, bucket_mem, MEM_BLOCK_ALL, 1417 index/8, &l2_bucket_max_entry); 1418 if (rv < 0) { 1419 SOC_EGRESS_METERING_UNLOCK(unit); 1420 return rv; 1421 } 1422 1423 rv = soc_mem_write(unit, config_mem, MEM_BLOCK_ALL, 1424 index/8, &l2_shaper_entry); 1425 SOC_EGRESS_METERING_UNLOCK(unit); 1426 return rv; 1427 } 1428 STATIC int 1429 _bcm_kt_cosq_inject_max_shaper_update(int unit,_bcm_kt_cosq_node_t *node) 1430 { 1431 1432 _bcm_kt_cosq_node_t *parentl0_node = NULL; 1433 _bcm_kt_cosq_node_t *cur_node = NULL; 1434 uint32 rval = 0; 1435 if((!node) || !(node->parent) || 1436 (node->level != _BCM_KT_COSQ_NODE_LEVEL_L2)) 1437 { 1438 return BCM_E_INTERNAL; 1439 } 1440 parentl0_node = node->parent->parent; 1441 for(cur_node = parentl0_node->child ;cur_node;cur_node=cur_node->sibling) { 1442 if(cur_node->child){ 1443 /* Inject max shaper enqueue. */ 1444 SOC_IF_ERROR_RETURN(READ_LLS_DEBUG_INJECT_ACTIVATIONr(unit, &rval)); 1445 soc_reg_field_set(unit, LLS_DEBUG_INJECT_ACTIVATIONr, &rval, INJECTf, 1); 1446 soc_reg_field_set(unit, LLS_DEBUG_INJECT_ACTIVATIONr, &rval, ENTITY_TYPEf, 1); 1447 soc_reg_field_set(unit, LLS_DEBUG_INJECT_ACTIVATIONr, &rval, ENTITY_LEVELf, 3); 1448 soc_reg_field_set(unit, LLS_DEBUG_INJECT_ACTIVATIONr, &rval, ENTITY_IDENTIFIERf, 1449 cur_node->child->hw_index); 1450 SOC_IF_ERROR_RETURN(WRITE_LLS_DEBUG_INJECT_ACTIVATIONr(unit, rval)); 1451 } 1452 } 1453 return BCM_E_NONE; 1454 } 1455 1456 1457 STATIC int 1458 _bcm_kt_cosq_dynamic_sched_update(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 1459 int mode, _bcm_kt_cosq_node_t *node) 1460 { 1461 soc_timeout_t timeout; 1462 uint32 timeout_val; 1463 lls_l2_child_state1_entry_t l2_child_state; 1464 lls_l1_parent_state_entry_t l1_parent_state; 1465 lls_l2_shaper_config_lower_entry_t l2_shaper_entry_upper; 1466 lls_l2_shaper_config_lower_entry_t l2_shaper_entry_lower; 1467 lls_l2_shaper_config_lower_entry_t l2_temp_entry_upper; 1468 lls_l2_shaper_config_lower_entry_t l2_temp_entry_lower; 1469 lls_l2_shaper_config_lower_entry_t *entry; 1470 uint32 wrr0_not_empty, wrr1_not_empty; 1471 uint32 poll_active = 1; 1472 int parent_id, old_l1_index; 1473 bcm_gport_t remap_gport; 1474 _bcm_kt_mmu_info_t *mmu_info; 1475 _bcm_kt_cosq_node_t *prev_node, *l1_node; 1476 uint32 spare, min_list, ef_list; 1477 bcm_port_t local_port; 1478 int index; 1479 int num_cos = 0; 1480 int cos = 0; 1481 int rv = BCM_E_NONE; 1482 soc_mem_t config_mem, config_mem1, config_mem2; 1483 static const soc_field_t rate_exp_fields[] = { 1484 C_MAX_REF_RATE_EXP_0f, C_MAX_REF_RATE_EXP_1f, 1485 C_MAX_REF_RATE_EXP_2f, C_MAX_REF_RATE_EXP_3f 1486 }; 1487 static const soc_field_t rate_mant_fields[] = { 1488 C_MAX_REF_RATE_MANT_0f, C_MAX_REF_RATE_MANT_1f, 1489 C_MAX_REF_RATE_MANT_2f, C_MAX_REF_RATE_MANT_3f 1490 }; 1491 static const soc_field_t burst_exp_fields[] = { 1492 C_MAX_THLD_EXP_0f, C_MAX_THLD_EXP_1f, 1493 C_MAX_THLD_EXP_2f, C_MAX_THLD_EXP_3f 1494 }; 1495 1496 if (node == NULL) { 1497 return BCM_E_INTERNAL; 1498 } 1499 bcm_kt_cosq_config_get(unit,&num_cos); 1500 /* Change the max shaper configuration for the queue to minimum threshold (64B) and 1501 * minimum rate (2kbps) 1502 */ 1503 BCM_IF_ERROR_RETURN 1504 (_bcm_kt_cosq_index_resolve(unit, port, cosq, 1505 _BCM_KT_COSQ_INDEX_STYLE_BUCKET, 1506 &local_port, &index, NULL)); 1507 SOC_EGRESS_METERING_LOCK(unit); 1508 config_mem1 = LLS_L2_SHAPER_CONFIG_LOWERm; 1509 config_mem2 = LLS_L2_SHAPER_CONFIG_UPPERm; 1510 rv = soc_mem_read(unit, config_mem1, MEM_BLOCK_ALL, 1511 index/8, &l2_shaper_entry_lower); 1512 if ( rv < 0 ){ 1513 SOC_EGRESS_METERING_UNLOCK(unit); 1514 return rv; 1515 } 1516 rv = soc_mem_read(unit, config_mem2, MEM_BLOCK_ALL, 1517 index/8, &l2_shaper_entry_upper); 1518 if ( rv < 0 ){ 1519 SOC_EGRESS_METERING_UNLOCK(unit); 1520 return rv; 1521 } 1522 sal_memcpy(&l2_temp_entry_lower, &l2_shaper_entry_lower, 1523 sizeof(lls_l2_shaper_config_lower_entry_t)); 1524 sal_memcpy(&l2_temp_entry_upper, &l2_shaper_entry_upper, 1525 sizeof(lls_l2_shaper_config_lower_entry_t)); 1526 for(cos = 0; cos<num_cos; cos++) { 1527 config_mem = ((cos < 4) ? LLS_L2_SHAPER_CONFIG_LOWERm : 1528 LLS_L2_SHAPER_CONFIG_UPPERm); 1529 entry = ((cos < 4) ? (&l2_temp_entry_lower) : (&l2_temp_entry_upper)); 1530 soc_mem_field32_set(unit, config_mem, entry, 1531 rate_exp_fields[cos % 4], 0); 1532 soc_mem_field32_set(unit, config_mem, entry , 1533 rate_mant_fields[cos % 4], 1); 1534 soc_mem_field32_set(unit, config_mem, entry, 1535 burst_exp_fields[cos % 4], 5); 1536 } 1537 1538 rv = soc_mem_write(unit, config_mem1, MEM_BLOCK_ALL, 1539 index/8, &l2_temp_entry_lower); 1540 if ( rv < 0 ){ 1541 SOC_EGRESS_METERING_UNLOCK(unit); 1542 return rv; 1543 } 1544 rv = soc_mem_write(unit, config_mem2, MEM_BLOCK_ALL, 1545 index/8, &l2_temp_entry_upper); 1546 if ( rv < 0 ){ 1547 SOC_EGRESS_METERING_UNLOCK(unit); 1548 return rv; 1549 } 1550 SOC_EGRESS_METERING_UNLOCK(unit); 1551 /* Poll L2 child state until observe node is not active within the scheduler hierarchy.*/ 1552 timeout_val = soc_property_get(unit, spn_MMU_QUEUE_FLUSH_TIMEOUT, 20000); 1553 soc_timeout_init(&timeout, timeout_val, 0); 1554 1555 while (poll_active) { 1556 SOC_IF_ERROR_RETURN 1557 (READ_LLS_L2_CHILD_STATE1m(unit, MEM_BLOCK_ALL, node->hw_index, 1558 &l2_child_state)); 1559 if (SOC_MEM_FIELD_VALID(unit, LLS_L2_CHILD_STATE1m, SPAREf)) { 1560 soc_mem_field_get(unit, LLS_L2_CHILD_STATE1m, (uint32 *)&l2_child_state, 1561 SPAREf, &spare); 1562 } else { 1563 soc_mem_field_get(unit, LLS_L2_CHILD_STATE1m, (uint32 *)&l2_child_state, 1564 C_ON_WERR_LISTf, &spare); 1565 } 1566 soc_mem_field_get(unit, LLS_L2_CHILD_STATE1m, (uint32 *)&l2_child_state, 1567 C_ON_MIN_LIST_0f, &min_list); 1568 soc_mem_field_get(unit, LLS_L2_CHILD_STATE1m, (uint32 *)&l2_child_state, 1569 C_ON_EF_LIST_0f, &ef_list); 1570 if (!spare && !min_list && !ef_list) { 1571 poll_active = 0; 1572 } 1573 if (soc_timeout_check(&timeout)) { 1574 BCM_IF_ERROR_RETURN 1575 (_bcm_kt_cosq_dynamic_bw_update(unit, config_mem1, index, node->hw_index, 1576 l2_shaper_entry_lower)); 1577 BCM_IF_ERROR_RETURN 1578 (_bcm_kt_cosq_dynamic_bw_update(unit, config_mem1, index, node->hw_index, 1579 l2_shaper_entry_upper)); 1580 BCM_IF_ERROR_RETURN 1581 (_bcm_kt_cosq_inject_max_shaper_update(unit,node)); 1582 1583 LOG_ERROR(BSL_LS_BCM_COMMON, 1584 (BSL_META_U(unit, 1585 "ERROR: Queue %d L2 child state timeout: spare %d min_list %d ef_list %d\n"), 1586 node->hw_index, spare, min_list, ef_list)); 1587 return BCM_E_TIMEOUT; 1588 } 1589 } 1590 1591 /* Change L2 parent to point to new L1 */ 1592 mmu_info = _bcm_kt_mmu_info[unit]; 1593 if (node->parent == NULL) { 1594 return BCM_E_INTERNAL; 1595 } 1596 parent_id = (BCM_GPORT_SCHEDULER_GET(node->parent->gport) >> 8) & 0x7ff; 1597 remap_gport = mmu_info->l1_gport_pair[parent_id]; 1598 1599 BCM_IF_ERROR_RETURN 1600 (_bcm_kt_cosq_node_get(unit, node->parent->gport, NULL, NULL, NULL, 1601 &l1_node)); 1602 old_l1_index = l1_node->hw_index; 1603 1604 /* unresolve the node - delete this node from parent's child list */ 1605 BCM_IF_ERROR_RETURN 1606 (_bcm_kt_cosq_node_unresolve(unit, node, 0)); 1607 1608 /* now remove from the sw tree */ 1609 if (node->parent != NULL) { 1610 if (node->parent->child == node) { 1611 node->parent->child = node->sibling; 1612 } else { 1613 prev_node = node->parent->child; 1614 while (prev_node != NULL && prev_node->sibling != node) { 1615 prev_node = prev_node->sibling; 1616 } 1617 if (prev_node == NULL) { 1618 return BCM_E_INTERNAL; 1619 } 1620 prev_node->sibling = node->sibling; 1621 } 1622 node->parent = NULL; 1623 node->sibling = NULL; 1624 node->hw_index = -1; 1625 node->wrr_in_use = 0; 1626 node->cosq_attached_to = -1; 1627 } 1628 1629 node->wrr_in_use = (mode != BCM_COSQ_STRICT) ? 1 : 0; 1630 BCM_IF_ERROR_RETURN 1631 (bcm_kt_cosq_gport_attach(unit, node->gport, remap_gport, 0)); 1632 1633 /* Read L2 child state to check L2 is not active in the scheduler. */ 1634 SOC_IF_ERROR_RETURN 1635 (READ_LLS_L2_CHILD_STATE1m(unit, MEM_BLOCK_ALL, node->hw_index, 1636 &l2_child_state)); 1637 if (SOC_MEM_FIELD_VALID(unit, LLS_L2_CHILD_STATE1m, SPAREf)) { 1638 soc_mem_field_get(unit, LLS_L2_CHILD_STATE1m, (uint32 *)&l2_child_state, 1639 SPAREf, &spare); 1640 } else { 1641 soc_mem_field_get(unit, LLS_L2_CHILD_STATE1m, (uint32 *)&l2_child_state, 1642 C_ON_WERR_LISTf, &spare); 1643 } 1644 1645 /* if(spare == 1) check whether L2 is on old L1. */ 1646 if (spare == 1) { 1647 SOC_IF_ERROR_RETURN 1648 (READ_LLS_L1_PARENT_STATEm(unit, MEM_BLOCK_ALL, old_l1_index, 1649 &l1_parent_state)); 1650 soc_mem_field_get(unit, LLS_L1_PARENT_STATEm, (uint32 *)&l1_parent_state, 1651 P_WRR_0_NOT_EMPTYf, &wrr0_not_empty); 1652 soc_mem_field_get(unit, LLS_L1_PARENT_STATEm, (uint32 *)&l1_parent_state, 1653 P_WRR_1_NOT_EMPTYf, &wrr1_not_empty); 1654 if (wrr0_not_empty || wrr1_not_empty) { 1655 timeout_val = soc_property_get(unit, spn_MMU_QUEUE_FLUSH_TIMEOUT, 20000); 1656 soc_timeout_init(&timeout, timeout_val, 0); 1657 1658 poll_active = 1; 1659 while (poll_active) { 1660 SOC_IF_ERROR_RETURN 1661 (READ_LLS_L2_CHILD_STATE1m(unit, MEM_BLOCK_ALL, node->hw_index, 1662 &l2_child_state)); 1663 if (SOC_MEM_FIELD_VALID(unit, LLS_L2_CHILD_STATE1m, SPAREf)) { 1664 soc_mem_field_get(unit, LLS_L2_CHILD_STATE1m, (uint32 *)&l2_child_state, 1665 SPAREf, &spare); 1666 } else { 1667 soc_mem_field_get(unit, LLS_L2_CHILD_STATE1m, (uint32 *)&l2_child_state, 1668 C_ON_WERR_LISTf, &spare); 1669 } 1670 soc_mem_field_get(unit, LLS_L2_CHILD_STATE1m, (uint32 *)&l2_child_state, 1671 C_ON_MIN_LIST_0f, &min_list); 1672 soc_mem_field_get(unit, LLS_L2_CHILD_STATE1m, (uint32 *)&l2_child_state, 1673 C_ON_EF_LIST_0f, &ef_list); 1674 if (!spare && !min_list && !ef_list) { 1675 poll_active = 0; 1676 } 1677 if (soc_timeout_check(&timeout)) { 1678 (_bcm_kt_cosq_dynamic_bw_update(unit, config_mem1, index, node->hw_index, 1679 l2_shaper_entry_lower)); 1680 BCM_IF_ERROR_RETURN 1681 (_bcm_kt_cosq_dynamic_bw_update(unit, config_mem2, index, node->hw_index, 1682 l2_shaper_entry_upper)); 1683 BCM_IF_ERROR_RETURN 1684 (_bcm_kt_cosq_inject_max_shaper_update(unit,node)); 1685 1686 LOG_ERROR(BSL_LS_BCM_COMMON, 1687 (BSL_META_U(unit, 1688 "ERROR: Queue %d old L1 index %d wrr0/1_not_empty %d %d\n"), 1689 node->hw_index, old_l1_index, wrr0_not_empty, 1690 wrr1_not_empty)); 1691 LOG_ERROR(BSL_LS_BCM_COMMON, 1692 (BSL_META_U(unit, 1693 "spare %d min_list %d ef_list %d\n"), 1694 spare, min_list, 1695 ef_list)); 1696 return BCM_E_TIMEOUT; 1697 } 1698 } 1699 } 1700 } 1701 BCM_IF_ERROR_RETURN 1702 (_bcm_kt_cosq_dynamic_bw_update(unit, config_mem1, index, node->hw_index, 1703 l2_shaper_entry_lower)); 1704 BCM_IF_ERROR_RETURN 1705 (_bcm_kt_cosq_dynamic_bw_update(unit, config_mem2, index, node->hw_index, 1706 l2_shaper_entry_upper)); 1707 BCM_IF_ERROR_RETURN 1708 (_bcm_kt_cosq_inject_max_shaper_update(unit,node)); 1709 1710 return rv; 1711 } 1712 1713 /* 1714 * Function: 1715 * _bcm_kt_cosq_valid_dynamic_request 1716 * Purpose: 1717 * Validate the new dynamic request 1718 * Parameters: 1719 * unit - (IN) unit number 1720 * port - (IN) port 1721 * level - (IN) scheduler level 1722 * node_id - (IN) node index 1723 * parent_id - (IN) parent index 1724 * rval - (IN) dynamic reg value 1725 * Returns: 1726 * BCM_E_XXX 1727 */ 1728 1729 STATIC int 1730 _bcm_kt_cosq_valid_dynamic_request(int unit, bcm_port_t port, int node_level, 1731 int node_id, int parent_id, uint32 rval) 1732 { 1733 soc_reg_t dyn_reg = LLS_SP_WERR_DYN_CHANGE_0Ar; 1734 lls_l0_parent_entry_t l0_parent; 1735 lls_l1_parent_entry_t l1_parent; 1736 bcm_port_t req_port, req_parent; 1737 1738 /* dont allow more than one req per parent */ 1739 req_parent = soc_reg_field_get(unit, dyn_reg, rval, PARENT_IDf); 1740 if ((node_level == soc_reg_field_get(unit, dyn_reg, rval, NODE_LEVELf)) && 1741 (parent_id == req_parent)) { 1742 return FALSE; 1743 } 1744 1745 switch (node_level) { 1746 case _BCM_KT_COSQ_NODE_LEVEL_L0: 1747 req_port = parent_id; 1748 break; 1749 case _BCM_KT_COSQ_NODE_LEVEL_L1: 1750 SOC_IF_ERROR_RETURN 1751 (READ_LLS_L0_PARENTm(unit, MEM_BLOCK_ALL, req_parent, 1752 &l0_parent)); 1753 req_port = soc_mem_field32_get(unit, LLS_L0_PARENTm, &l0_parent, 1754 C_PARENTf); 1755 break; 1756 case _BCM_KT_COSQ_NODE_LEVEL_L2: 1757 SOC_IF_ERROR_RETURN 1758 (READ_LLS_L1_PARENTm(unit, MEM_BLOCK_ALL, req_parent, 1759 &l1_parent)); 1760 req_port = soc_mem_field32_get(unit, LLS_L1_PARENTm, &l1_parent, 1761 C_PARENTf); 1762 SOC_IF_ERROR_RETURN 1763 (READ_LLS_L0_PARENTm(unit, MEM_BLOCK_ALL, req_port, 1764 &l0_parent)); 1765 req_port = soc_mem_field32_get(unit, LLS_L0_PARENTm, &l0_parent, 1766 C_PARENTf); 1767 break; 1768 default: 1769 return FALSE; 1770 } 1771 1772 /* dont allow more than one req per port */ 1773 if (port == req_port) { 1774 return FALSE; 1775 } 1776 return TRUE; 1777 } 1778 1779 /* 1780 * Function: 1781 * _bcm_kt_cosq_dynamic_sp_werr_change 1782 * Purpose: 1783 * Set LLS dynamic scheduler registers based on level and hw index 1784 * Parameters: 1785 * unit - (IN) unit number 1786 * level - (IN) scheduler level 1787 * node_id - (IN) node index 1788 * parent_id - (IN) parent index 1789 * config - (IN) config details 1790 * Returns: 1791 * BCM_E_XXX 1792 */ 1793 STATIC int 1794 _bcm_kt_cosq_dynamic_sp_werr_change(int unit, bcm_port_t port, int node_level, 1795 int node_id, int parent_id, uint32 config, 1796 _bcm_kt_cosq_state_t state) 1797 { 1798 soc_timeout_t timeout; 1799 uint32 timeout_val, rval; 1800 int i, in_use; 1801 soc_reg_t dyn_reg_a, dyn_reg_b; 1802 lls_l0_xoff_entry_t l0_xoff; 1803 soc_reg_t dyn_change_a[] = 1804 { 1805 LLS_SP_WERR_DYN_CHANGE_0Ar, 1806 LLS_SP_WERR_DYN_CHANGE_1Ar, 1807 LLS_SP_WERR_DYN_CHANGE_2Ar, 1808 LLS_SP_WERR_DYN_CHANGE_3Ar 1809 }; 1810 soc_reg_t dyn_change_b[] = 1811 { 1812 LLS_SP_WERR_DYN_CHANGE_0Br, 1813 LLS_SP_WERR_DYN_CHANGE_1Br, 1814 LLS_SP_WERR_DYN_CHANGE_2Br, 1815 LLS_SP_WERR_DYN_CHANGE_3Br 1816 }; 1817 1818 /* Get one of the free register to place the request */ 1819 for (i = 0; i < 4; i++) { 1820 dyn_reg_a = dyn_change_a[i]; 1821 dyn_reg_b = dyn_change_b[i]; 1822 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, dyn_reg_a, REG_PORT_ANY, 1823 0, &rval)); 1824 if (SAL_BOOT_SIMULATION) { 1825 break; 1826 } 1827 1828 if (soc_reg_field_get(unit, dyn_reg_a, rval, IN_USEf) == 0) { 1829 break; 1830 } else { 1831 /* verify any other req pending from this port or same parent */ 1832 if (_bcm_kt_cosq_valid_dynamic_request(unit, port, node_level, 1833 node_id, parent_id, rval) == FALSE) { 1834 return BCM_E_UNAVAIL; 1835 } 1836 } 1837 } 1838 1839 if (i == 4) { 1840 /* None of the registers are available */ 1841 return BCM_E_UNAVAIL; 1842 } 1843 1844 rval = 0; 1845 soc_reg_field_set(unit, dyn_reg_a, &rval, NODE_LEVELf, node_level); 1846 soc_reg_field_set(unit, dyn_reg_a, &rval, NODE_IDf, node_id); 1847 soc_reg_field_set(unit, dyn_reg_a, &rval, PARENT_IDf, parent_id); 1848 soc_reg_field_set(unit, dyn_reg_a, &rval, IN_USEf, 1); 1849 1850 /* Write DYN_CHANGE_XB register first */ 1851 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, dyn_reg_b, REG_PORT_ANY, 1852 0, config)); 1853 /* Write DYN_CHANGE_XA register next. this triggers the request */ 1854 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, dyn_reg_a, REG_PORT_ANY, 1855 0, rval)); 1856 if (SAL_BOOT_SIMULATION) { 1857 return BCM_E_NONE; 1858 } 1859 1860 in_use = 1; 1861 timeout_val = soc_property_get(unit, spn_MMU_QUEUE_FLUSH_TIMEOUT, 1862 _BCM_COSQ_QUEUE_FLUSH_TIMEOUT_DEFAULT); 1863 soc_timeout_init(&timeout, timeout_val, 0); 1864 1865 while (in_use) { 1866 SOC_IF_ERROR_RETURN 1867 (soc_reg32_get(unit, dyn_reg_a, REG_PORT_ANY, 0, &rval)); 1868 in_use = soc_reg_field_get(unit, dyn_reg_a, rval, IN_USEf); 1869 if (in_use && soc_timeout_check(&timeout)) { 1870 LOG_ERROR(BSL_LS_BCM_COMMON, 1871 (BSL_META_U(unit, 1872 "ERROR: dynamic sp <-> werr change operation failed \n"))); 1873 LOG_ERROR(BSL_LS_BCM_COMMON, 1874 (BSL_META_U(unit, 1875 " node_level %d node_id %d parent_id %d \n"), 1876 node_level, node_id, parent_id)); 1877 soc_reg_field_set(unit, dyn_reg_a, &rval, IN_USEf, 0); 1878 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, dyn_reg_a, REG_PORT_ANY, 1879 0, rval)); 1880 return BCM_E_TIMEOUT; 1881 } 1882 } 1883 1884 if (node_level == _BCM_KT_COSQ_NODE_LEVEL_L1 && 1885 state == _BCM_KT_COSQ_STATE_WRR_TO_SPRI) { 1886 sal_memset(&l0_xoff, 0, sizeof(lls_l0_xoff_entry_t)); 1887 soc_mem_field32_set(unit, LLS_L0_XOFFm, &l0_xoff, C_XOFFf, 1888 (1 << (parent_id & 0xf))); 1889 SOC_IF_ERROR_RETURN 1890 (WRITE_LLS_L0_XOFFm(unit, MEM_BLOCK_ALL, ((parent_id >> 4) & 0xf), 1891 &l0_xoff)); 1892 /* Add single lls register read delay */ 1893 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, dyn_reg_a, REG_PORT_ANY, 1894 0, &rval)); 1895 soc_mem_field32_set(unit, LLS_L0_XOFFm, &l0_xoff, C_XOFFf, 0); 1896 SOC_IF_ERROR_RETURN 1897 (WRITE_LLS_L0_XOFFm(unit, MEM_BLOCK_ALL, ((parent_id >> 4) & 0xf), 1898 &l0_xoff)); 1899 SOC_IF_ERROR_RETURN(READ_LLS_DEBUG_INJECT_ACTIVATIONr(unit, &rval)); 1900 soc_reg_field_set(unit, LLS_DEBUG_INJECT_ACTIVATIONr, &rval, 1901 INJECTf, 1); 1902 soc_reg_field_set(unit, LLS_DEBUG_INJECT_ACTIVATIONr, &rval, 1903 ENTITY_TYPEf, 2); 1904 soc_reg_field_set(unit, LLS_DEBUG_INJECT_ACTIVATIONr, &rval, 1905 ENTITY_LEVELf, 1); 1906 soc_reg_field_set(unit, LLS_DEBUG_INJECT_ACTIVATIONr, &rval, 1907 ENTITY_IDENTIFIERf, parent_id); 1908 SOC_IF_ERROR_RETURN(WRITE_LLS_DEBUG_INJECT_ACTIVATIONr(unit, rval)); 1909 } 1910 1911 return BCM_E_NONE; 1912 } 1913 1914 STATIC int 1915 _bcm_kt_cosq_shaper_value_get(int unit, int port, int max_speed, 1916 uint32 lvl, int *node_count, 1917 uint32 *exp, uint32 *mant) 1918 { 1919 int speed; 1920 int rv; 1921 int l0_speed = 0, l1_speed = 0; 1922 1923 if (NULL == exp || NULL == mant) { 1924 return BCM_E_PARAM; 1925 } 1926 1927 speed = max_speed * 1000; 1928 1929 1930 if (lvl == _SOC_KT_COSQ_NODE_LEVEL_L0) { 1931 speed = (( KT_COSQ_SHAPER_PERC * speed) / 100); 1932 if (node_count[_SOC_KT_COSQ_NODE_LEVEL_L1]) { 1933 speed /= node_count[_SOC_KT_COSQ_NODE_LEVEL_L1]; 1934 } 1935 } else if (lvl == _SOC_KT_COSQ_NODE_LEVEL_L1) { 1936 l0_speed = (( KT_COSQ_SHAPER_PERC * speed) / 100); 1937 if(node_count[_SOC_KT_COSQ_NODE_LEVEL_L1]) { 1938 l0_speed /= node_count[_SOC_KT_COSQ_NODE_LEVEL_L0]; 1939 } 1940 speed = (( KT_COSQ_SHAPER_PERC * l0_speed) / 100); 1941 if (node_count[_SOC_KT_COSQ_NODE_LEVEL_L1]) { 1942 speed /= node_count[_SOC_KT_COSQ_NODE_LEVEL_L1]; 1943 } 1944 } else if (lvl == _SOC_KT_COSQ_NODE_LEVEL_L2) { 1945 l0_speed = (( KT_COSQ_SHAPER_PERC * speed) / 100); 1946 if (node_count[_SOC_KT_COSQ_NODE_LEVEL_L0]) { 1947 l0_speed /= node_count[_SOC_KT_COSQ_NODE_LEVEL_L0]; 1948 } 1949 l1_speed = (( KT_COSQ_SHAPER_PERC * l0_speed) / 100); 1950 if (node_count[_SOC_KT_COSQ_NODE_LEVEL_L1]) { 1951 l1_speed /= node_count[_SOC_KT_COSQ_NODE_LEVEL_L1]; 1952 } 1953 speed = (( KT_COSQ_SHAPER_PERC * l1_speed) / 100); 1954 if (node_count[_SOC_KT_COSQ_NODE_LEVEL_L2]) { 1955 speed /= node_count[_SOC_KT_COSQ_NODE_LEVEL_L2]; 1956 } 1957 } else { 1958 speed = (( KT_COSQ_SHAPER_PERC * speed) / 100); 1959 } 1960 1961 rv = soc_katana_get_shaper_rate_info(unit, speed, mant, exp); 1962 if (BCM_FAILURE(rv)) { 1963 return(rv); 1964 } 1965 return BCM_E_NONE; 1966 } 1967 1968 STATIC int 1969 _bcm_kt_cosq_sched_bucket_set(int unit, int port, 1970 int index, uint32 level, int *node_count, int max_speed) 1971 { 1972 uint32 idx = 0; 1973 uint32 i = 0; 1974 lls_port_shaper_config_c_entry_t port_entry; 1975 lls_l0_shaper_config_c_entry_t l0_entry; 1976 lls_l1_shaper_config_c_entry_t l1_entry; 1977 lls_l2_shaper_config_lower_entry_t l2_entry; 1978 uint32 exp = 0, mant = 0; 1979 soc_mem_t config_mem[2]; 1980 static const soc_field_t rate_exp_fields[] = { 1981 C_MAX_REF_RATE_EXP_0f, C_MAX_REF_RATE_EXP_1f, 1982 C_MAX_REF_RATE_EXP_2f, C_MAX_REF_RATE_EXP_3f, 1983 C_MIN_REF_RATE_EXP_0f, C_MIN_REF_RATE_EXP_1f, 1984 C_MIN_REF_RATE_EXP_2f, C_MIN_REF_RATE_EXP_3f 1985 }; 1986 static const soc_field_t rate_mant_fields[] = { 1987 C_MAX_REF_RATE_MANT_0f, C_MAX_REF_RATE_MANT_1f, 1988 C_MAX_REF_RATE_MANT_2f, C_MAX_REF_RATE_MANT_3f, 1989 C_MIN_REF_RATE_MANT_0f, C_MIN_REF_RATE_MANT_1f, 1990 C_MIN_REF_RATE_MANT_2f, C_MIN_REF_RATE_MANT_3f 1991 }; 1992 static const soc_field_t burst_exp_fields[] = { 1993 C_MAX_THLD_EXP_0f, C_MAX_THLD_EXP_1f, 1994 C_MAX_THLD_EXP_2f, C_MAX_THLD_EXP_3f, 1995 C_MIN_THLD_EXP_0f, C_MIN_THLD_EXP_1f, 1996 C_MIN_THLD_EXP_2f, C_MIN_THLD_EXP_3f 1997 }; 1998 static const soc_field_t burst_mant_fields[] = { 1999 C_MAX_THLD_MANT_0f, C_MAX_THLD_MANT_1f, 2000 C_MAX_THLD_MANT_2f, C_MAX_THLD_MANT_3f, 2001 C_MIN_THLD_MANT_0f, C_MIN_THLD_MANT_1f, 2002 C_MIN_THLD_MANT_2f, C_MIN_THLD_MANT_3f 2003 }; 2004 static const soc_field_t cycle_sel_fields[] = { 2005 C_MAX_CYCLE_SEL_0f, C_MAX_CYCLE_SEL_1f, 2006 C_MAX_CYCLE_SEL_2f, C_MAX_CYCLE_SEL_3f, 2007 C_MIN_CYCLE_SEL_0f, C_MIN_CYCLE_SEL_1f, 2008 C_MIN_CYCLE_SEL_2f, C_MIN_CYCLE_SEL_3f 2009 }; 2010 2011 soc_field_t rate_exp_f[] = { 2012 C_MAX_REF_RATE_EXPf, C_MIN_REF_RATE_EXPf 2013 }; 2014 soc_field_t rate_mant_f[] = { 2015 C_MAX_REF_RATE_MANTf, C_MIN_REF_RATE_MANTf 2016 }; 2017 soc_field_t burst_exp_f[] = { 2018 C_MAX_THLD_EXPf, C_MIN_THLD_EXPf 2019 }; 2020 soc_field_t burst_mant_f[] = { 2021 C_MAX_THLD_MANTf, C_MIN_THLD_MANTf 2022 }; 2023 soc_field_t cycle_sel_f[] = { 2024 C_MAX_CYCLE_SELf, C_MIN_CYCLE_SELf 2025 }; 2026 2027 2028 SOC_IF_ERROR_RETURN 2029 (_bcm_kt_cosq_shaper_value_get(unit, port, max_speed, level, node_count, &exp, &mant)); 2030 switch (level) { 2031 case _SOC_KT_COSQ_NODE_LEVEL_ROOT: 2032 config_mem[0] = LLS_PORT_SHAPER_CONFIG_Cm; 2033 2034 sal_memset(&port_entry, 0, 2035 sizeof(lls_port_shaper_config_c_entry_t)); 2036 SOC_IF_ERROR_RETURN 2037 (soc_mem_read(unit, config_mem[0], MEM_BLOCK_ALL, 2038 index, &port_entry)); 2039 soc_mem_field32_set(unit, config_mem[0], &port_entry, 2040 rate_exp_f[0], exp); 2041 soc_mem_field32_set(unit, config_mem[0], &port_entry, 2042 rate_mant_f[0], mant); 2043 soc_mem_field32_set(unit, config_mem[0], &port_entry, 2044 burst_exp_f[0], KT_QUEUE_FLUSH_BURST_EXP); 2045 soc_mem_field32_set(unit, config_mem[0], &port_entry, 2046 burst_mant_f[0], KT_QUEUE_FLUSH_BURST_MANTISSA); 2047 soc_mem_field32_set(unit, config_mem[0], &port_entry, 2048 cycle_sel_f[0], KT_QUEUE_FLUSH_CYCLE_SEL); 2049 SOC_IF_ERROR_RETURN 2050 (soc_mem_write(unit, config_mem[0], 2051 MEM_BLOCK_ALL, index, &port_entry)); 2052 break; 2053 case _SOC_KT_COSQ_NODE_LEVEL_L0: 2054 config_mem[0] = LLS_L0_SHAPER_CONFIG_Cm; 2055 config_mem[1] = LLS_L0_MIN_CONFIG_Cm; 2056 2057 for (i = 0; i < 2; i++) { 2058 sal_memset(&l0_entry, 0, 2059 sizeof(lls_l0_shaper_config_c_entry_t)); 2060 SOC_IF_ERROR_RETURN 2061 (soc_mem_read(unit, config_mem[i], MEM_BLOCK_ALL, 2062 index, &l0_entry)); 2063 soc_mem_field32_set(unit, config_mem[i], &l0_entry, 2064 rate_exp_f[i], exp); 2065 soc_mem_field32_set(unit, config_mem[i], &l0_entry, 2066 rate_mant_f[i], mant); 2067 soc_mem_field32_set(unit, config_mem[i], &l0_entry, 2068 burst_exp_f[i], KT_QUEUE_FLUSH_BURST_EXP); 2069 soc_mem_field32_set(unit, config_mem[i], &l0_entry, 2070 burst_mant_f[i], KT_QUEUE_FLUSH_BURST_MANTISSA); 2071 soc_mem_field32_set(unit, config_mem[i], &l0_entry, 2072 cycle_sel_f[i], KT_QUEUE_FLUSH_CYCLE_SEL); 2073 SOC_IF_ERROR_RETURN 2074 (soc_mem_write(unit, config_mem[i], 2075 MEM_BLOCK_ALL, index, &l0_entry)); 2076 } 2077 break; 2078 case _SOC_KT_COSQ_NODE_LEVEL_L1: 2079 config_mem[0] = LLS_L1_SHAPER_CONFIG_Cm; 2080 config_mem[1] = LLS_L1_MIN_CONFIG_Cm; 2081 2082 for (i = 0; i < 2; i++) { 2083 sal_memset(&l1_entry, 0, 2084 sizeof(lls_l1_shaper_config_c_entry_t)); 2085 idx = (i * 4) + (index % 4); 2086 SOC_IF_ERROR_RETURN 2087 (soc_mem_read(unit, config_mem[i], MEM_BLOCK_ALL, 2088 index/4, &l1_entry)); 2089 soc_mem_field32_set(unit, config_mem[i], &l1_entry, 2090 rate_exp_fields[idx], exp); 2091 soc_mem_field32_set(unit, config_mem[i], &l1_entry, 2092 rate_mant_fields[idx], mant); 2093 soc_mem_field32_set(unit, config_mem[i], &l1_entry, 2094 burst_exp_fields[idx], KT_QUEUE_FLUSH_BURST_EXP); 2095 soc_mem_field32_set(unit, config_mem[i], &l1_entry, 2096 burst_mant_fields[idx], KT_QUEUE_FLUSH_BURST_MANTISSA); 2097 soc_mem_field32_set(unit, config_mem[i], &l1_entry, 2098 cycle_sel_fields[idx], KT_QUEUE_FLUSH_CYCLE_SEL); 2099 SOC_IF_ERROR_RETURN 2100 (soc_mem_write(unit, config_mem[i], 2101 MEM_BLOCK_ALL, index/4, &l1_entry)); 2102 } 2103 break; 2104 case _SOC_KT_COSQ_NODE_LEVEL_L2: 2105 if ((index % 8) < 4) { 2106 config_mem[0] = LLS_L2_SHAPER_CONFIG_LOWERm; 2107 config_mem[1] = LLS_L2_MIN_CONFIG_LOWER_Cm; 2108 } else { 2109 config_mem[0] = LLS_L2_SHAPER_CONFIG_UPPERm; 2110 config_mem[1] = LLS_L2_MIN_CONFIG_UPPER_Cm; 2111 } 2112 2113 for ( i = 0; i < 2; i++) { 2114 idx = (i * 4) + (index % 4); 2115 2116 sal_memset(&l2_entry, 0, 2117 sizeof(lls_l2_shaper_config_lower_entry_t)); 2118 SOC_IF_ERROR_RETURN 2119 (soc_mem_read(unit, config_mem[i], MEM_BLOCK_ALL, 2120 index/8, &l2_entry)); 2121 soc_mem_field32_set(unit, config_mem[i], &l2_entry, 2122 rate_exp_fields[idx], exp); 2123 soc_mem_field32_set(unit, config_mem[i], &l2_entry, 2124 rate_mant_fields[idx], mant); 2125 soc_mem_field32_set(unit, config_mem[i], &l2_entry, 2126 burst_exp_fields[idx], KT_QUEUE_FLUSH_BURST_EXP ); 2127 soc_mem_field32_set(unit, config_mem[i], &l2_entry, 2128 burst_mant_fields[idx], KT_QUEUE_FLUSH_BURST_MANTISSA ); 2129 soc_mem_field32_set(unit, config_mem[i], &l2_entry, 2130 cycle_sel_fields[idx], KT_QUEUE_FLUSH_CYCLE_SEL); 2131 SOC_IF_ERROR_RETURN 2132 (soc_mem_write(unit, config_mem[i], 2133 MEM_BLOCK_ALL, index/8, &l2_entry)); 2134 } 2135 break; 2136 default: 2137 return SOC_E_NONE; 2138 2139 } 2140 2141 return SOC_E_NONE; 2142 } 2143 2144 2145 STATIC int 2146 _bcm_kt_egress_metering_freeze(int unit, soc_port_t port, void **setting) 2147 { 2148 int rv = BCM_E_NONE; 2149 soc_mem_t mem; 2150 uint32 *bmap, *bmap_list[5]; 2151 int word_count, wdc[5], blk_size=0; 2152 int lvl, j, index, word, bit, index_count, count; 2153 int idx, upper_flag = 0; 2154 int prev_idx, prev_upper_flag; 2155 int node_count[4], speed = 0; 2156 mem_entry_t *buffer; 2157 soc_info_t *si; 2158 static const soc_mem_t cfg_mems[][2] = { 2159 { LLS_PORT_SHAPER_CONFIG_Cm, INVALIDm }, 2160 { LLS_L0_SHAPER_CONFIG_Cm, LLS_L0_MIN_CONFIG_Cm }, 2161 { LLS_L1_SHAPER_CONFIG_Cm, LLS_L1_MIN_CONFIG_Cm }, 2162 { LLS_L2_SHAPER_CONFIG_LOWERm, LLS_L2_MIN_CONFIG_LOWER_Cm }, 2163 { LLS_L2_SHAPER_CONFIG_UPPERm, LLS_L2_MIN_CONFIG_UPPER_Cm }, 2164 }; 2165 2166 SOC_EGRESS_METERING_LOCK(unit); 2167 2168 si = &SOC_INFO(unit); 2169 bmap_list[1] = SOC_CONTROL(unit)->port_lls_l0_bmap[port]; 2170 bmap_list[2] = SOC_CONTROL(unit)->port_lls_l1_bmap[port]; 2171 bmap_list[3] = SOC_CONTROL(unit)->port_lls_l2_bmap[port]; 2172 count = 0; /* One entry for port level */ 2173 2174 for (lvl = _BCM_KT_COSQ_NODE_LEVEL_L0; 2175 lvl < _BCM_KT_COSQ_NODE_LEVEL_MAX; lvl++) { 2176 node_count[lvl] = 0; 2177 } 2178 2179 if (IS_LB_PORT(unit, port) || IS_CPU_PORT(unit, port)) { 2180 speed = si->port_speed_max[port]; 2181 } else { 2182 rv = bcm_esw_port_speed_get(unit, port, &speed); 2183 if (BCM_FAILURE(rv)) { 2184 goto _ka_freeze_abort; 2185 } 2186 if (speed == 0) { 2187 rv = bcm_esw_port_speed_max(unit, port, &speed); 2188 if (BCM_FAILURE(rv)) { 2189 goto _ka_freeze_abort; 2190 } 2191 } 2192 } 2193 2194 for (lvl = _BCM_KT_COSQ_NODE_LEVEL_L0; 2195 lvl < _BCM_KT_COSQ_NODE_LEVEL_MAX; lvl++) { 2196 bmap = bmap_list[lvl]; 2197 mem = cfg_mems[lvl][0]; 2198 index_count = soc_mem_index_count(unit, mem); 2199 /* 2200 * Allocation done using LLS_LX_PARENT 2201 * reading also done using same memories 2202 */ 2203 if (lvl == _BCM_KT_COSQ_NODE_LEVEL_L0) { 2204 index_count = soc_mem_index_count(unit, LLS_L0_PARENTm); 2205 } else if (lvl == _BCM_KT_COSQ_NODE_LEVEL_L1) { 2206 index_count = soc_mem_index_count(unit, LLS_L1_PARENTm); 2207 } else if (lvl == _BCM_KT_COSQ_NODE_LEVEL_L2) { 2208 index_count = soc_mem_index_count(unit, LLS_L2_PARENTm); 2209 } 2210 wdc[lvl] = _SHR_BITDCLSIZE(index_count); 2211 word_count = wdc[lvl]; 2212 for (word = 0; word < word_count; word++) { 2213 if (bmap[word] != 0) { 2214 if (lvl == _BCM_KT_COSQ_NODE_LEVEL_L0) { 2215 node_count[_BCM_KT_COSQ_NODE_LEVEL_L0] += _shr_popcount(bmap[word]); 2216 } else if (lvl == _BCM_KT_COSQ_NODE_LEVEL_L1) { 2217 node_count[_BCM_KT_COSQ_NODE_LEVEL_L1] += _shr_popcount(bmap[word]); 2218 } else if (lvl == _BCM_KT_COSQ_NODE_LEVEL_L2) { 2219 node_count[_BCM_KT_COSQ_NODE_LEVEL_L2] += _shr_popcount(bmap[word]); 2220 } 2221 } 2222 } 2223 } 2224 2225 for (lvl = _BCM_KT_COSQ_NODE_LEVEL_L0; 2226 lvl < _BCM_KT_COSQ_NODE_LEVEL_MAX; lvl++) { 2227 count += node_count[lvl]; 2228 } 2229 count = (count * 8) + 1; 2230 node_count[_BCM_KT_COSQ_NODE_LEVEL_ROOT] = 1; 2231 2232 buffer = sal_alloc((count + 1) * sizeof(mem_entry_t), 2233 "shaper buffer"); 2234 2235 if (buffer == NULL) { 2236 rv = BCM_E_MEMORY; 2237 goto _ka_freeze_abort; 2238 } 2239 2240 count = 0; 2241 /* port */ 2242 mem = LLS_PORT_SHAPER_CONFIG_Cm; 2243 index = port & 0x3f; 2244 /* Save the entry */ 2245 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, index, 2246 &buffer[count].entry); 2247 2248 if (BCM_FAILURE(rv)) { 2249 sal_free(buffer); 2250 goto _ka_freeze_abort; 2251 } 2252 buffer[count].mem = mem; 2253 buffer[count].index = index; 2254 count++; 2255 /* Set the threshold for the port to max shaper rate */ 2256 rv = _bcm_kt_cosq_sched_bucket_set(unit, port, index, 2257 _SOC_KT_COSQ_NODE_LEVEL_ROOT, node_count, speed); 2258 if (BCM_FAILURE(rv)) { 2259 sal_free(buffer); 2260 goto _ka_freeze_abort; 2261 } 2262 2263 /* L0, L1, L2 meter */ 2264 for (lvl = _BCM_KT_COSQ_NODE_LEVEL_L0; 2265 lvl < _BCM_KT_COSQ_NODE_LEVEL_MAX; lvl++) { 2266 idx = upper_flag = 0; 2267 prev_idx = prev_upper_flag = -1; 2268 blk_size = (lvl == _BCM_KT_COSQ_NODE_LEVEL_L2) ? 8: 2269 ((lvl == _BCM_KT_COSQ_NODE_LEVEL_L1)? 4:1); 2270 bmap = bmap_list[lvl]; 2271 word_count = wdc[lvl]; 2272 for (word = 0; word < word_count; word++) { 2273 if (bmap[word] == 0) { 2274 continue; 2275 } 2276 for (bit = 0; bit < SHR_BITWID; bit++) { 2277 if (!(bmap[word] & (1 << bit))) { 2278 continue; 2279 } 2280 index = word * SHR_BITWID + bit; 2281 idx = index / blk_size; 2282 for (j = 0; j < 2; j++) { 2283 mem = cfg_mems[lvl][j]; 2284 if (lvl == _BCM_KT_COSQ_NODE_LEVEL_L2) { 2285 if ((index % 8) >= 4) { 2286 mem = cfg_mems[lvl][j]; 2287 upper_flag = 1; 2288 } else { 2289 upper_flag = 0; 2290 } 2291 } 2292 2293 /* Store the Threshold MIN/MAX table entries only 2294 * once per table index as for the 2295 * next consecutive L1/L2 indices falling on 2296 * to the same table index need not be stored 2297 */ 2298 if ((prev_idx != idx) || 2299 ((lvl == _BCM_KT_COSQ_NODE_LEVEL_L2) && (prev_upper_flag != upper_flag))) { 2300 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, idx, 2301 &buffer[count].entry); 2302 if (BCM_FAILURE(rv)) { 2303 sal_free(buffer); 2304 goto _ka_freeze_abort; 2305 } 2306 buffer[count].mem = mem; 2307 buffer[count].index = idx; 2308 count++; 2309 } 2310 2311 if (lvl == _BCM_KT_COSQ_NODE_LEVEL_L2){ 2312 rv = _bcm_kt_cosq_sched_bucket_set(unit, port, 2313 index, lvl, node_count, speed); 2314 } else if ((lvl != _BCM_KT_COSQ_NODE_LEVEL_L2) && (j == 1)) { 2315 rv = _bcm_kt_cosq_sched_bucket_set(unit, port, 2316 index, lvl, node_count, speed); 2317 } 2318 if (BCM_FAILURE(rv)) { 2319 sal_free(buffer); 2320 goto _ka_freeze_abort; 2321 } 2322 }/*END of for j */ 2323 prev_idx = idx; 2324 prev_upper_flag = upper_flag; 2325 } /* END of the valid bit */ 2326 } /* END of the word */ 2327 } /* END of lvl */ 2328 2329 buffer[count].mem = INVALIDm; 2330 *setting = buffer; 2331 _ka_freeze_abort: 2332 return rv; 2333 } 2334 2335 STATIC int 2336 _bcm_kt_egress_metering_thaw(int unit, soc_port_t port, void *setting) 2337 { 2338 int rv; 2339 int index; 2340 mem_entry_t *buffer; 2341 if (setting == NULL) { 2342 SOC_EGRESS_METERING_UNLOCK(unit); 2343 return SOC_E_NONE; 2344 } 2345 rv = SOC_E_NONE; 2346 2347 buffer = setting; 2348 for (index = 0; buffer[index].mem != INVALIDm ;index++) { 2349 rv = soc_mem_write(unit, buffer[index].mem, MEM_BLOCK_ANY, 2350 buffer[index].index, &buffer[index].entry); 2351 if (BCM_FAILURE(rv)) { 2352 break; 2353 } 2354 } 2355 sal_free(setting); 2356 SOC_EGRESS_METERING_UNLOCK(unit); 2357 return rv; 2358 } 2359 2360 /* 2361 * Function: 2362 * _bcm_kt_cosq_sched_config_set 2363 * Purpose: 2364 * Set LLS scheduler registers based on GPORT 2365 * Parameters: 2366 * unit - (IN) unit number 2367 * gport - (IN) queue group/scheduler GPORT identifier 2368 * state - (IN) sched state change 2369 * Returns: 2370 * BCM_E_XXX 2371 */ 2372 STATIC int 2373 _bcm_kt_cosq_sched_config_set(int unit, bcm_gport_t gport, 2374 _bcm_kt_cosq_state_t state) 2375 { 2376 _bcm_kt_mmu_info_t *mmu_info; 2377 _bcm_kt_cosq_node_t *node, *parent; 2378 mmu_rqe_queue_op_node_map_entry_t rqe_op_node; 2379 mmu_wred_queue_op_node_map_entry_t wred_op_node; 2380 lls_l2_child_state1_entry_t l2_child_state; 2381 uint32 entry_c[SOC_MAX_MEM_WORDS]; 2382 uint32 entry_p[SOC_MAX_MEM_WORDS]; 2383 int port, start_spri = 0; 2384 int flush_active = 0; 2385 int update_spri_vector = 0; 2386 uint8 spri_vector = 0; 2387 int parent_index; 2388 uint8 vec_3_0, vec_7_4; 2389 uint32 rval = 0, timeout_val; 2390 int retval_temp = 0; 2391 uint32 spare, min_list, ef_list, not_empty; 2392 soc_timeout_t timeout; 2393 soc_mem_t config_mem, parent_mem; 2394 uint32 *bmap = NULL; 2395 soc_mem_t mem_c[] = { 2396 LLS_PORT_CONFIGm, 2397 LLS_L0_CONFIGm, 2398 LLS_L1_CONFIGm 2399 }; 2400 soc_mem_t mem_p[] = { 2401 LLS_L0_PARENTm, 2402 LLS_L1_PARENTm, 2403 LLS_L2_PARENTm 2404 }; 2405 2406 void *setting = NULL; 2407 BCM_IF_ERROR_RETURN 2408 (_bcm_kt_cosq_node_get(unit, gport, NULL, &port, NULL, 2409 &node)); 2410 parent = node->parent; 2411 2412 if (node->cosq_attached_to < 0 || (node->cosq_attached_to < 8 && 2413 parent->base_index < 0)) { 2414 return BCM_E_PARAM; 2415 } 2416 2417 config_mem = mem_c[parent->level]; 2418 if ((node->cosq_attached_to < 8) && (parent->hw_index != -1)) { 2419 start_spri = parent->base_index; 2420 spri_vector = 1 << (node->hw_index - start_spri); 2421 update_spri_vector = 1; 2422 2423 sal_memset(entry_c, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS); 2424 SOC_IF_ERROR_RETURN 2425 (soc_mem_read(unit, config_mem, MEM_BLOCK_ALL, parent->hw_index, 2426 &entry_c)); 2427 vec_3_0 = soc_mem_field32_get(unit, config_mem, &entry_c, 2428 P_NUM_SPRIf); 2429 vec_7_4 = soc_mem_field32_get(unit, config_mem, &entry_c, 2430 P_VECT_SPRI_7_4f); 2431 if (state == _BCM_KT_COSQ_STATE_ENABLE || 2432 state == _BCM_KT_COSQ_STATE_WRR_TO_SPRI) { 2433 vec_3_0 |= (spri_vector & 0xF); 2434 vec_7_4 |= (spri_vector >> 4); 2435 } else if (state == _BCM_KT_COSQ_STATE_DISABLE || 2436 state == _BCM_KT_COSQ_STATE_SPRI_TO_WRR) { 2437 vec_3_0 &= ~(spri_vector & 0xF); 2438 vec_7_4 &= ~(spri_vector >> 4); 2439 } 2440 2441 /* update LLS_CONFIG with the updated vector */ 2442 soc_mem_field32_set(unit, config_mem, &entry_c, P_START_SPRIf, 2443 start_spri); 2444 soc_mem_field32_set(unit, config_mem, &entry_c, P_NUM_SPRIf, 2445 vec_3_0); 2446 soc_mem_field32_set(unit, config_mem, &entry_c, P_VECT_SPRI_7_4f, 2447 vec_7_4); 2448 } 2449 2450 parent_mem = mem_p[parent->level]; 2451 sal_memset(entry_p, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS); 2452 sal_memset(&rqe_op_node, 0, sizeof(mmu_rqe_queue_op_node_map_entry_t)); 2453 sal_memset(&wred_op_node, 0, sizeof(mmu_wred_queue_op_node_map_entry_t)); 2454 2455 if (parent->level == _BCM_KT_COSQ_NODE_LEVEL_ROOT) { 2456 bmap = SOC_CONTROL(unit)->port_lls_l0_bmap[port]; 2457 } else if (parent->level == _BCM_KT_COSQ_NODE_LEVEL_L0) { 2458 bmap = SOC_CONTROL(unit)->port_lls_l1_bmap[port]; 2459 } else if (parent->level == _BCM_KT_COSQ_NODE_LEVEL_L1) { 2460 bmap = SOC_CONTROL(unit)->port_lls_l2_bmap[port]; 2461 } 2462 switch (state) { 2463 case _BCM_KT_COSQ_STATE_ENABLE: 2464 if ((parent_mem == LLS_L0_PARENTm) && 2465 SOC_MEM_FIELD_VALID(unit, LLS_L0_PARENTm, C_TYPEf)) { 2466 soc_mem_field32_set(unit, parent_mem, &entry_p, C_TYPEf, 1); 2467 } 2468 soc_mem_field32_set(unit, parent_mem, &entry_p, C_PARENTf, parent->hw_index); 2469 SOC_IF_ERROR_RETURN 2470 (soc_mem_write(unit, parent_mem, MEM_BLOCK_ANY, node->hw_index, &entry_p)); 2471 if (update_spri_vector) { 2472 SOC_IF_ERROR_RETURN 2473 (soc_mem_write(unit, config_mem, MEM_BLOCK_ANY, parent->hw_index, 2474 &entry_c)); 2475 } 2476 2477 if (parent->level == _BCM_KT_COSQ_NODE_LEVEL_L1) { 2478 /* Read the entry from the RQE map in order to preserve the E_TYPE field */ 2479 SOC_IF_ERROR_RETURN 2480 (READ_MMU_RQE_QUEUE_OP_NODE_MAPm(unit, MEM_BLOCK_ALL, node->hw_index, 2481 &rqe_op_node)); 2482 soc_mem_field32_set(unit, MMU_RQE_QUEUE_OP_NODE_MAPm, &rqe_op_node, 2483 OP_NODEf, parent->hw_index); 2484 soc_mem_field32_set(unit, MMU_WRED_QUEUE_OP_NODE_MAPm, &wred_op_node, 2485 OP_NODEf, parent->hw_index); 2486 SOC_IF_ERROR_RETURN 2487 (WRITE_MMU_RQE_QUEUE_OP_NODE_MAPm(unit, MEM_BLOCK_ALL, node->hw_index, 2488 &rqe_op_node)); 2489 SOC_IF_ERROR_RETURN 2490 (WRITE_MMU_WRED_QUEUE_OP_NODE_MAPm(unit, MEM_BLOCK_ALL, node->hw_index, 2491 &wred_op_node)); 2492 _soc_kt_cosq_end_port_flush(unit,node->hw_index); 2493 } 2494 _BCM_COSQ_PARENT_BMAP_SET(bmap, node->hw_index); 2495 break; 2496 case _BCM_KT_COSQ_STATE_DISABLE: 2497 mmu_info = _bcm_kt_mmu_info[unit]; 2498 if (parent->level == _BCM_KT_COSQ_NODE_LEVEL_ROOT) { 2499 parent_index = (1 << soc_mem_field_length(unit, parent_mem, C_PARENTf)) - 1; 2500 } else { 2501 parent_index = mmu_info->max_nodes[parent->level] - 1; 2502 } 2503 soc_mem_field32_set(unit, parent_mem, &entry_p, C_PARENTf, parent_index); 2504 2505 if (parent->level == _BCM_KT_COSQ_NODE_LEVEL_L1) { 2506 /* flush the queue */ 2507 if (!(SAL_BOOT_SIMULATION)) { 2508 BCM_IF_ERROR_RETURN(READ_TOQ_QUEUE_FLUSH0r(unit, &rval)); 2509 flush_active = soc_reg_field_get(unit, TOQ_QUEUE_FLUSH0r, rval, 2510 Q_FLUSH_ACTIVEf); 2511 if (flush_active == 1) { 2512 /* some other queue is in flush state, return failure */ 2513 LOG_ERROR(BSL_LS_BCM_COMMON, 2514 (BSL_META_U(unit, 2515 "ERROR: Queue %d is already in flush state \n"), 2516 (soc_reg_field_get(unit, TOQ_QUEUE_FLUSH0r, rval, 2517 Q_FLUSH_ID0f)))); 2518 return BCM_E_BUSY; 2519 } 2520 2521 soc_reg_field_set(unit, TOQ_QUEUE_FLUSH0r, &rval, Q_FLUSH_ID0f, 2522 node->hw_index); 2523 soc_reg_field_set(unit, TOQ_QUEUE_FLUSH0r, &rval, Q_FLUSH_NUMf, 1); 2524 soc_reg_field_set(unit, TOQ_QUEUE_FLUSH0r, &rval, Q_FLUSH_ACTIVEf, 1); 2525 soc_reg_field_set(unit, TOQ_QUEUE_FLUSH0r, &rval, 2526 Q_FLUSH_EXTERNALf, 2527 (IS_EXT_MEM_PORT(unit, port) ? 1: 0)); 2528 BCM_IF_ERROR_RETURN(WRITE_TOQ_QUEUE_FLUSH0r(unit, rval)); 2529 flush_active = 1; 2530 timeout_val = soc_property_get(unit, spn_MMU_QUEUE_FLUSH_TIMEOUT, 20000); 2531 soc_timeout_init(&timeout, timeout_val, 0); 2532 2533 while (flush_active) { 2534 BCM_IF_ERROR_RETURN(READ_TOQ_QUEUE_FLUSH0r(unit, &rval)); 2535 flush_active = soc_reg_field_get(unit, TOQ_QUEUE_FLUSH0r, rval, 2536 Q_FLUSH_ACTIVEf); 2537 if (soc_timeout_check(&timeout)) { 2538 LOG_ERROR(BSL_LS_BCM_COMMON, 2539 (BSL_META_U(unit, 2540 "ERROR: Queue %d flush operation failed \n"), 2541 node->hw_index)); 2542 return (BCM_E_TIMEOUT); 2543 } 2544 } 2545 } 2546 SOC_IF_ERROR_RETURN 2547 (READ_LLS_L2_CHILD_STATE1m(unit, MEM_BLOCK_ALL, 2548 node->hw_index, 2549 &l2_child_state)); 2550 if (SOC_MEM_FIELD_VALID(unit, LLS_L2_CHILD_STATE1m, SPAREf)) { 2551 soc_mem_field_get(unit, LLS_L2_CHILD_STATE1m, 2552 (uint32 *)&l2_child_state, SPAREf, 2553 &spare); 2554 } else { 2555 soc_mem_field_get(unit, LLS_L2_CHILD_STATE1m, 2556 (uint32 *)&l2_child_state, C_ON_WERR_LISTf, 2557 &spare); 2558 } 2559 soc_mem_field_get(unit, LLS_L2_CHILD_STATE1m, 2560 (uint32 *)&l2_child_state, 2561 C_ON_MIN_LIST_0f, &min_list); 2562 soc_mem_field_get(unit, LLS_L2_CHILD_STATE1m, 2563 (uint32 *)&l2_child_state, 2564 C_ON_EF_LIST_0f, &ef_list); 2565 soc_mem_field_get(unit, LLS_L2_CHILD_STATE1m, 2566 (uint32 *)&l2_child_state, 2567 C_NOT_EMPTY_0f, ¬_empty); 2568 /* check LLS_L2_CHILD_STATE[7:4] == 4'b0000 to confirm 2569 * that the node is empty */ 2570 if (spare || min_list || ef_list || not_empty) { 2571 return BCM_E_BUSY; 2572 } 2573 SOC_IF_ERROR_RETURN 2574 (READ_LLS_L2_CHILD_STATE1m(unit, MEM_BLOCK_ALL, 2575 node->hw_index, 2576 &l2_child_state)); 2577 if (SOC_MEM_FIELD_VALID(unit, LLS_L2_CHILD_STATE1m, SPAREf)) { 2578 soc_mem_field_get(unit, LLS_L2_CHILD_STATE1m, 2579 (uint32 *)&l2_child_state, SPAREf, 2580 &spare); 2581 } else { 2582 soc_mem_field_get(unit, LLS_L2_CHILD_STATE1m, 2583 (uint32 *)&l2_child_state, C_ON_WERR_LISTf, 2584 &spare); 2585 } 2586 soc_mem_field_get(unit, LLS_L2_CHILD_STATE1m, 2587 (uint32 *)&l2_child_state, 2588 C_ON_MIN_LIST_0f, &min_list); 2589 soc_mem_field_get(unit, LLS_L2_CHILD_STATE1m, 2590 (uint32 *)&l2_child_state, 2591 C_ON_EF_LIST_0f, &ef_list); 2592 soc_mem_field_get(unit, LLS_L2_CHILD_STATE1m, 2593 (uint32 *)&l2_child_state, 2594 C_NOT_EMPTY_0f, ¬_empty); 2595 /* check LLS_L2_CHILD_STATE[7:4] == 4'b0000 to confirm 2596 * that the node is empty */ 2597 if (spare || min_list || ef_list || not_empty) { 2598 return BCM_E_BUSY; 2599 } 2600 SOC_IF_ERROR_RETURN 2601 (READ_MMU_RQE_QUEUE_OP_NODE_MAPm(unit, MEM_BLOCK_ALL, node->hw_index, 2602 &rqe_op_node)); 2603 soc_mem_field32_set(unit, MMU_RQE_QUEUE_OP_NODE_MAPm, &rqe_op_node, 2604 OP_NODEf, parent_index); 2605 soc_mem_field32_set(unit, MMU_WRED_QUEUE_OP_NODE_MAPm, &wred_op_node, 2606 OP_NODEf, parent_index); 2607 SOC_IF_ERROR_RETURN 2608 (soc_mem_write(unit, parent_mem, MEM_BLOCK_ANY, node->hw_index, &entry_p)); 2609 SOC_IF_ERROR_RETURN 2610 (WRITE_MMU_RQE_QUEUE_OP_NODE_MAPm(unit, MEM_BLOCK_ALL, node->hw_index, 2611 &rqe_op_node)); 2612 SOC_IF_ERROR_RETURN 2613 (WRITE_MMU_WRED_QUEUE_OP_NODE_MAPm(unit, MEM_BLOCK_ALL, node->hw_index, 2614 &wred_op_node)); 2615 } else { 2616 SOC_IF_ERROR_RETURN 2617 (soc_mem_write(unit, parent_mem, MEM_BLOCK_ANY, node->hw_index, &entry_p)); 2618 } 2619 if (update_spri_vector) { 2620 SOC_IF_ERROR_RETURN 2621 (soc_mem_write(unit, config_mem, MEM_BLOCK_ANY, parent->hw_index, 2622 &entry_c)); 2623 } 2624 _BCM_COSQ_PARENT_BMAP_CLR(bmap, node->hw_index); 2625 break; 2626 case _BCM_KT_COSQ_STATE_WRR_TO_SPRI: 2627 case _BCM_KT_COSQ_STATE_SPRI_TO_WRR: 2628 if (update_spri_vector) { 2629 SOC_IF_ERROR_RETURN(_bcm_kt_egress_metering_freeze(unit, 2630 port, &setting)); 2631 retval_temp = _bcm_kt_cosq_dynamic_sp_werr_change(unit, port, node->level, 2632 node->hw_index, parent->hw_index, entry_c[0], state); 2633 SOC_IF_ERROR_RETURN(_bcm_kt_egress_metering_thaw(unit, port, setting)); 2634 if (BCM_FAILURE(retval_temp)) { 2635 return retval_temp; 2636 } 2637 } 2638 break; 2639 default: 2640 break; 2641 } 2642 2643 return BCM_E_NONE; 2644 } 2645 2646 /* 2647 * Function: 2648 * _bcm_kt_cosq_sched_node_set 2649 * Purpose: 2650 * Set LLS scheduler registers based on GPORT 2651 * Parameters: 2652 * unit - (IN) unit number 2653 * gport - (IN) queue group/scheduler GPORT identifier 2654 * Returns: 2655 * BCM_E_XXX 2656 */ 2657 STATIC int 2658 _bcm_kt_cosq_sched_node_set(int unit, bcm_gport_t gport, 2659 _bcm_kt_cosq_state_t state) 2660 { 2661 _bcm_kt_cosq_node_t *node, *parent; 2662 _bcm_kt_cosq_node_t *cur_node; 2663 lls_port_config_entry_t port_cfg; 2664 lls_l0_parent_entry_t l0_parent; 2665 lls_l0_config_entry_t l0_cfg; 2666 lls_l1_config_entry_t l1_cfg; 2667 lls_l1_parent_entry_t l1_parent; 2668 lls_l2_parent_entry_t l2_parent; 2669 mmu_rqe_queue_op_node_map_entry_t rqe_op_node; 2670 mmu_wred_queue_op_node_map_entry_t wred_op_node; 2671 uint32 num_pri = 0, wrr_use = 0, start_pri = 0; 2672 int port; 2673 uint32 rval = 0; 2674 int spri_nodes =0; 2675 int set_wrr = 0; 2676 int update_mem = 0; 2677 int flush_active = 0; 2678 int min_index; 2679 soc_timeout_t timeout; 2680 uint32 timeout_val; 2681 uint32 *bmap = NULL; 2682 2683 if (soc_feature(unit, soc_feature_vector_based_spri)) { 2684 return _bcm_kt_cosq_sched_config_set(unit, gport, state); 2685 } 2686 2687 /* parent ->level == root 2688 * config LLS_PORT_CONFIG, LLS_L0_PARENT points to port. 2689 2690 * parent->level == L0 2691 * config LLS_L0_CONFIG and LLS_L1_PARENT points to L0 queue 2692 2693 * parent->level == L1 2694 * config LLS_L1_CONFIG and LLS_L2_PARENT points to L1 queue 2695 */ 2696 2697 BCM_IF_ERROR_RETURN 2698 (_bcm_kt_cosq_node_get(unit, gport, NULL, &port, NULL, 2699 &node)); 2700 2701 /* read lls_config[level], if num_pri and num_child is diffent reprogram 2702 * write lls_parent[level with node->parent->hw_index indexed on node_hw_index 2703 */ 2704 2705 parent = node->parent; 2706 2707 min_index = (node->level == _BCM_KT_COSQ_NODE_LEVEL_L2) ? 4095 : 2708 ((node->level == _BCM_KT_COSQ_NODE_LEVEL_L1) ? 1023 : 255); 2709 2710 if (parent->numq <= 8) { 2711 for (cur_node = parent->child; cur_node != NULL; 2712 cur_node = cur_node->sibling) { 2713 if (cur_node->wrr_in_use == 0) { 2714 spri_nodes++; 2715 if (cur_node->hw_index < min_index) { 2716 min_index = cur_node->hw_index; 2717 } 2718 } else { 2719 set_wrr = 1; 2720 } 2721 } 2722 if (spri_nodes == 1 && state == _BCM_KT_COSQ_STATE_DISABLE) { 2723 /* this is the last spri node which gets deleted */ 2724 spri_nodes = 0; 2725 min_index = (node->level == _BCM_KT_COSQ_NODE_LEVEL_L2) ? 4095 : 2726 ((node->level == _BCM_KT_COSQ_NODE_LEVEL_L1) ? 1023 : 255); 2727 } 2728 2729 parent->first_child = min_index; 2730 } 2731 2732 if (parent->level == _BCM_KT_COSQ_NODE_LEVEL_ROOT) { 2733 bmap = SOC_CONTROL(unit)->port_lls_l0_bmap[port]; 2734 SOC_IF_ERROR_RETURN 2735 (READ_LLS_PORT_CONFIGm(unit, MEM_BLOCK_ALL, parent->hw_index, &port_cfg)); 2736 2737 wrr_use = soc_mem_field32_get(unit, LLS_PORT_CONFIGm, &port_cfg, P_WRR_IN_USEf); 2738 num_pri = soc_mem_field32_get(unit, LLS_PORT_CONFIGm, &port_cfg, P_NUM_SPRIf); 2739 start_pri = soc_mem_field32_get(unit, LLS_PORT_CONFIGm, &port_cfg, P_START_SPRIf); 2740 2741 if (wrr_use != set_wrr) { 2742 soc_mem_field32_set(unit, LLS_PORT_CONFIGm, &port_cfg, P_WRR_IN_USEf, set_wrr); 2743 update_mem = 1; 2744 } 2745 if (num_pri != spri_nodes) { 2746 soc_mem_field32_set(unit, LLS_PORT_CONFIGm, &port_cfg, P_NUM_SPRIf, spri_nodes); 2747 update_mem = 1; 2748 } 2749 if (start_pri != min_index) { 2750 soc_mem_field32_set(unit, LLS_PORT_CONFIGm, &port_cfg, P_START_SPRIf, min_index); 2751 update_mem = 1; 2752 } 2753 2754 if (update_mem == 1) { 2755 SOC_IF_ERROR_RETURN 2756 (WRITE_LLS_PORT_CONFIGm(unit, MEM_BLOCK_ALL, parent->hw_index, &port_cfg)); 2757 } 2758 2759 sal_memset(&l0_parent, 0, sizeof(lls_l0_parent_entry_t)); 2760 if (state == _BCM_KT_COSQ_STATE_ENABLE) { 2761 soc_mem_field32_set(unit, LLS_L0_PARENTm, &l0_parent, C_PARENTf, parent->hw_index); 2762 SOC_IF_ERROR_RETURN 2763 (WRITE_LLS_L0_PARENTm(unit, MEM_BLOCK_ALL, node->hw_index, &l0_parent)); 2764 _BCM_COSQ_PARENT_BMAP_SET(bmap, node->hw_index); 2765 } 2766 if (state == _BCM_KT_COSQ_STATE_DISABLE) { 2767 soc_mem_field32_set(unit, LLS_L0_PARENTm, &l0_parent, C_PARENTf, 0x3f); 2768 SOC_IF_ERROR_RETURN 2769 (WRITE_LLS_L0_PARENTm(unit, MEM_BLOCK_ALL, node->hw_index, &l0_parent)); 2770 _BCM_COSQ_PARENT_BMAP_CLR(bmap, node->hw_index); 2771 } 2772 } else if (parent->level == _BCM_KT_COSQ_NODE_LEVEL_L0) { 2773 bmap = SOC_CONTROL(unit)->port_lls_l1_bmap[port]; 2774 SOC_IF_ERROR_RETURN 2775 (READ_LLS_L0_CONFIGm(unit, MEM_BLOCK_ALL, parent->hw_index, &l0_cfg)); 2776 2777 wrr_use = soc_mem_field32_get(unit, LLS_L0_CONFIGm, &l0_cfg, P_WRR_IN_USEf); 2778 num_pri = soc_mem_field32_get(unit, LLS_L0_CONFIGm, &l0_cfg, P_NUM_SPRIf); 2779 start_pri = soc_mem_field32_get(unit, LLS_L0_CONFIGm, &l0_cfg, P_START_SPRIf); 2780 2781 if (wrr_use != set_wrr) { 2782 soc_mem_field32_set(unit, LLS_L0_CONFIGm, &l0_cfg, P_WRR_IN_USEf, set_wrr); 2783 update_mem = 1; 2784 } 2785 if (num_pri != spri_nodes) { 2786 soc_mem_field32_set(unit, LLS_L0_CONFIGm, &l0_cfg, P_NUM_SPRIf, spri_nodes); 2787 update_mem = 1; 2788 } 2789 if (start_pri != min_index) { 2790 soc_mem_field32_set(unit, LLS_L0_CONFIGm, &l0_cfg, P_START_SPRIf, min_index); 2791 update_mem = 1; 2792 } 2793 2794 if (update_mem == 1) { 2795 SOC_IF_ERROR_RETURN 2796 (WRITE_LLS_L0_CONFIGm(unit, MEM_BLOCK_ALL, parent->hw_index, &l0_cfg)); 2797 } 2798 2799 sal_memset(&l1_parent, 0, sizeof(lls_l1_parent_entry_t)); 2800 if (state == _BCM_KT_COSQ_STATE_ENABLE) { 2801 soc_mem_field32_set(unit, LLS_L1_PARENTm, &l1_parent, C_PARENTf, parent->hw_index); 2802 SOC_IF_ERROR_RETURN 2803 (WRITE_LLS_L1_PARENTm(unit, MEM_BLOCK_ALL, node->hw_index, &l1_parent)); 2804 _BCM_COSQ_PARENT_BMAP_SET(bmap, node->hw_index); 2805 } 2806 if (state == _BCM_KT_COSQ_STATE_DISABLE) { 2807 soc_mem_field32_set(unit, LLS_L1_PARENTm, &l1_parent, C_PARENTf, 0xff); 2808 SOC_IF_ERROR_RETURN 2809 (WRITE_LLS_L1_PARENTm(unit, MEM_BLOCK_ALL, node->hw_index, &l1_parent)); 2810 _BCM_COSQ_PARENT_BMAP_CLR(bmap, node->hw_index); 2811 } 2812 } else if (parent->level == _BCM_KT_COSQ_NODE_LEVEL_L1) { 2813 bmap = SOC_CONTROL(unit)->port_lls_l2_bmap[port]; 2814 if (soc_feature(unit, soc_feature_dynamic_sched_update)) { 2815 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 2816 set_wrr = 0; 2817 spri_nodes = 0; 2818 min_index = 0; 2819 } 2820 } else { 2821 SOC_IF_ERROR_RETURN 2822 (READ_LLS_L1_CONFIGm(unit, MEM_BLOCK_ALL, parent->hw_index, &l1_cfg)); 2823 num_pri = soc_mem_field32_get(unit, LLS_L1_CONFIGm, &l1_cfg, P_NUM_SPRIf); 2824 wrr_use = soc_mem_field32_get(unit, LLS_L1_CONFIGm, &l1_cfg, P_WRR_IN_USEf); 2825 if (SOC_IS_KATANA2(unit)) { 2826 /* Changed in the latest QT Regfile. MMU Implementor to revisit / reconfirm */ 2827 start_pri = soc_mem_field32_get(unit, LLS_L1_CONFIGm, &l1_cfg, P_START_UC_SPRIf); 2828 } else { 2829 start_pri = soc_mem_field32_get(unit, LLS_L1_CONFIGm, &l1_cfg, P_START_SPRIf); 2830 } 2831 } 2832 2833 if (wrr_use != set_wrr) { 2834 soc_mem_field32_set(unit, LLS_L1_CONFIGm, &l1_cfg, P_WRR_IN_USEf, set_wrr); 2835 update_mem = 1; 2836 } 2837 if (num_pri != spri_nodes) { 2838 soc_mem_field32_set(unit, LLS_L1_CONFIGm, &l1_cfg, P_NUM_SPRIf, spri_nodes); 2839 update_mem = 1; 2840 } 2841 if (start_pri != min_index) { 2842 if (SOC_IS_KATANA2(unit)) { 2843 soc_mem_field32_set(unit, LLS_L1_CONFIGm, &l1_cfg, P_START_UC_SPRIf, min_index); 2844 } else { 2845 soc_mem_field32_set(unit, LLS_L1_CONFIGm, &l1_cfg, P_START_SPRIf, min_index); 2846 } 2847 update_mem = 1; 2848 } 2849 if (state != _BCM_KT_COSQ_STATE_DISABLE && update_mem == 1) { 2850 SOC_IF_ERROR_RETURN 2851 (WRITE_LLS_L1_CONFIGm(unit, MEM_BLOCK_ALL, parent->hw_index, &l1_cfg)); 2852 } 2853 2854 sal_memset(&l2_parent, 0, sizeof(lls_l2_parent_entry_t)); 2855 sal_memset(&rqe_op_node, 0, sizeof(mmu_rqe_queue_op_node_map_entry_t)); 2856 sal_memset(&wred_op_node, 0, sizeof(mmu_wred_queue_op_node_map_entry_t)); 2857 2858 if (state == _BCM_KT_COSQ_STATE_ENABLE) { 2859 soc_mem_field32_set(unit, LLS_L2_PARENTm, &l2_parent, 2860 C_PARENTf, parent->hw_index); 2861 SOC_IF_ERROR_RETURN 2862 (WRITE_LLS_L2_PARENTm(unit, MEM_BLOCK_ALL, node->hw_index, 2863 &l2_parent)); 2864 /* Read the entry from the RQE map in order to preserve the E_TYPE field */ 2865 SOC_IF_ERROR_RETURN 2866 (READ_MMU_RQE_QUEUE_OP_NODE_MAPm(unit, MEM_BLOCK_ALL, node->hw_index, 2867 &rqe_op_node)); 2868 soc_mem_field32_set(unit, MMU_RQE_QUEUE_OP_NODE_MAPm, &rqe_op_node, 2869 OP_NODEf, parent->hw_index); 2870 soc_mem_field32_set(unit, MMU_WRED_QUEUE_OP_NODE_MAPm, &wred_op_node, 2871 OP_NODEf, parent->hw_index); 2872 SOC_IF_ERROR_RETURN 2873 (WRITE_MMU_RQE_QUEUE_OP_NODE_MAPm(unit, MEM_BLOCK_ALL, node->hw_index, 2874 &rqe_op_node)); 2875 SOC_IF_ERROR_RETURN 2876 (WRITE_MMU_WRED_QUEUE_OP_NODE_MAPm(unit, MEM_BLOCK_ALL, node->hw_index, 2877 &wred_op_node)); 2878 _soc_kt_cosq_end_port_flush(unit,node->hw_index); 2879 _BCM_COSQ_PARENT_BMAP_SET(bmap, node->hw_index); 2880 } else if (state == _BCM_KT_COSQ_STATE_DISABLE) { 2881 /* deletion case , flush the queue */ 2882 BCM_IF_ERROR_RETURN(READ_TOQ_QUEUE_FLUSH0r(unit, &rval)); 2883 flush_active = soc_reg_field_get(unit, TOQ_QUEUE_FLUSH0r, rval, 2884 Q_FLUSH_ACTIVEf); 2885 if (flush_active == 1) { 2886 /* some other queue is in flush state, return failure */ 2887 LOG_ERROR(BSL_LS_BCM_COMMON, 2888 (BSL_META_U(unit, 2889 "ERROR: Queue %d is already in flush state \n"), 2890 (soc_reg_field_get(unit, TOQ_QUEUE_FLUSH0r, rval, 2891 Q_FLUSH_ID0f)))); 2892 return BCM_E_BUSY; 2893 } 2894 2895 if (!(SAL_BOOT_SIMULATION)) { 2896 soc_reg_field_set(unit, TOQ_QUEUE_FLUSH0r, &rval, Q_FLUSH_ID0f, 2897 node->hw_index); 2898 soc_reg_field_set(unit, TOQ_QUEUE_FLUSH0r, &rval, Q_FLUSH_NUMf, 1); 2899 soc_reg_field_set(unit, TOQ_QUEUE_FLUSH0r, &rval, Q_FLUSH_ACTIVEf, 1); 2900 soc_reg_field_set(unit, TOQ_QUEUE_FLUSH0r, &rval, 2901 Q_FLUSH_EXTERNALf, 2902 (IS_EXT_MEM_PORT(unit, port) ? 1: 0)); 2903 2904 BCM_IF_ERROR_RETURN(WRITE_TOQ_QUEUE_FLUSH0r(unit, rval)); 2905 } 2906 flush_active = 1; 2907 timeout_val = soc_property_get(unit, spn_MMU_QUEUE_FLUSH_TIMEOUT, 20000); 2908 soc_timeout_init(&timeout, timeout_val, 0); 2909 2910 while (flush_active) { 2911 BCM_IF_ERROR_RETURN(READ_TOQ_QUEUE_FLUSH0r(unit, &rval)); 2912 flush_active = soc_reg_field_get(unit, TOQ_QUEUE_FLUSH0r, rval, 2913 Q_FLUSH_ACTIVEf); 2914 if (soc_timeout_check(&timeout)) { 2915 LOG_ERROR(BSL_LS_BCM_COMMON, 2916 (BSL_META_U(unit, 2917 "ERROR: Queue %d flush operation failed \n"), 2918 node->hw_index)); 2919 return (BCM_E_TIMEOUT); 2920 } 2921 } 2922 2923 soc_mem_field32_set(unit, LLS_L2_PARENTm, &l2_parent, 2924 C_PARENTf, 0x3ff); 2925 soc_mem_field32_set(unit, MMU_RQE_QUEUE_OP_NODE_MAPm, &rqe_op_node, 2926 OP_NODEf, 0x3ff); 2927 soc_mem_field32_set(unit, MMU_WRED_QUEUE_OP_NODE_MAPm, &wred_op_node, 2928 OP_NODEf, 0x3ff); 2929 SOC_IF_ERROR_RETURN 2930 (WRITE_LLS_L2_PARENTm(unit, MEM_BLOCK_ALL, node->hw_index, 2931 &l2_parent)); 2932 SOC_IF_ERROR_RETURN 2933 (WRITE_MMU_RQE_QUEUE_OP_NODE_MAPm(unit, MEM_BLOCK_ALL, node->hw_index, 2934 &rqe_op_node)); 2935 SOC_IF_ERROR_RETURN 2936 (WRITE_MMU_WRED_QUEUE_OP_NODE_MAPm(unit, MEM_BLOCK_ALL, node->hw_index, 2937 &wred_op_node)); 2938 if (update_mem == 1) { 2939 SOC_IF_ERROR_RETURN 2940 (WRITE_LLS_L1_CONFIGm(unit, MEM_BLOCK_ALL, parent->hw_index, &l1_cfg)); 2941 } 2942 _BCM_COSQ_PARENT_BMAP_CLR(bmap, node->hw_index); 2943 } 2944 } else { 2945 return BCM_E_PARAM; 2946 } 2947 2948 return BCM_E_NONE; 2949 } 2950 2951 /* 2952 * Function: 2953 * _bcm_kt_cosq_sched_set 2954 * Purpose: 2955 * Set scheduling mode 2956 * Parameters: 2957 * unit - (IN) unit number 2958 * port - (IN) port number or GPORT identifier 2959 * cosq - (IN) COS queue number 2960 * mode - (IN) scheduling mode (BCM_COSQ_XXX) 2961 * num_weights - (IN) number of entries in weights array 2962 * weights - (IN) weights array 2963 * Returns: 2964 * BCM_E_XXX 2965 */ 2966 STATIC int 2967 _bcm_kt_cosq_sched_set(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 2968 int mode, int num_weights, const int weights[]) 2969 { 2970 _bcm_kt_mmu_info_t *mmu_info; 2971 _bcm_kt_cosq_node_t *node, *cur_node, *l0_node; 2972 bcm_port_t local_port; 2973 int index; 2974 int i; 2975 int max_weight; 2976 lls_l0_child_weight_cfg_cnt_entry_t l0_weight_cfg; 2977 lls_l1_child_weight_cfg_cnt_entry_t l1_weight_cfg; 2978 lls_l2_child_weight_cfg_cnt_entry_t l2_weight_cfg; 2979 lls_l2_parent_entry_t l2_parent; 2980 _bcm_kt_cosq_state_t state = _BCM_KT_COSQ_STATE_NO_CHANGE; 2981 int parent_id; 2982 bcm_gport_t remap_gport; 2983 int numq; 2984 uint32 fval; 2985 uint32 entry[SOC_MAX_MEM_WORDS]; 2986 soc_mem_t mem; 2987 int rv; 2988 2989 if (cosq < 0) { 2990 if (cosq == -1) { 2991 /* caller needs to resolve the wild card value */ 2992 return BCM_E_INTERNAL; 2993 } else { 2994 /* reject all other negative value */ 2995 return BCM_E_PARAM; 2996 } 2997 } 2998 2999 /* Validate weight values */ 3000 if (mode == BCM_COSQ_ROUND_ROBIN || 3001 mode == BCM_COSQ_WEIGHTED_ROUND_ROBIN || 3002 mode == BCM_COSQ_DEFICIT_ROUND_ROBIN || 3003 mode == BCM_COSQ_STRICT) { 3004 max_weight = 3005 (1 << soc_mem_field_length(unit, LLS_L0_CHILD_WEIGHT_CFG_CNTm, C_WEIGHTf)) - 1; 3006 for (i = 0; i < num_weights; i++) { 3007 if (weights[i] < 0 || weights[i] > max_weight) { 3008 return BCM_E_PARAM; 3009 } 3010 } 3011 } else { 3012 return BCM_E_PARAM; 3013 } 3014 3015 /* To support legacy device compatibility to configure STRICT 3016 mode if weight is "0". 3017 */ 3018 if ((num_weights == 1) && (weights[0] == BCM_COSQ_WEIGHT_STRICT)) { 3019 mode = BCM_COSQ_STRICT; 3020 } 3021 3022 mmu_info = _bcm_kt_mmu_info[unit]; 3023 3024 if (BCM_GPORT_IS_SCHEDULER(port)) { /* ETS style scheduler */ 3025 BCM_IF_ERROR_RETURN 3026 (_bcm_kt_cosq_node_get(unit, port, NULL, &local_port, NULL, 3027 &node)); 3028 }else { 3029 BCM_IF_ERROR_RETURN 3030 (_bcm_kt_cosq_localport_resolve(unit, port, &local_port)); 3031 3032 node = &mmu_info->sched_node[local_port]; 3033 3034 if (node->gport < 0) { 3035 return BCM_E_PARAM; 3036 } 3037 3038 if ((l0_node = node->child) == NULL) { 3039 return BCM_E_PARAM; 3040 } 3041 if (!soc_feature(unit, soc_feature_dynamic_sched_update)) { 3042 if ((node = l0_node->child) == NULL) { 3043 return BCM_E_PARAM; 3044 } 3045 } else { 3046 node = l0_node; 3047 } 3048 if (IS_CPU_PORT(unit, local_port)) { 3049 /* 3050 * In case when number of cpu queues are not multiples of 8 3051 * there is chance last siblings gets numq < 8, 3052 * which may result in failure , So node is moved to the 3053 * first sibling, which guarantee to have numq = 8 3054 */ 3055 for (cur_node = l0_node; cur_node->sibling != NULL; 3056 cur_node = cur_node->sibling) { 3057 if (cur_node->numq == 5) { 3058 break; 3059 } 3060 } 3061 for (cur_node = cur_node->child; cur_node->sibling != NULL; 3062 cur_node = cur_node->sibling); 3063 node = cur_node; 3064 } 3065 3066 } 3067 3068 if ((mode != BCM_COSQ_STRICT) && 3069 (node->numq > 0 && (cosq + num_weights) > node->numq)) { 3070 return BCM_E_PARAM; 3071 } 3072 3073 3074 if (node->cosq_attached_to < 0) { /* Not resolved yet */ 3075 return BCM_E_NOT_FOUND; 3076 } 3077 3078 if (!soc_feature(unit, soc_feature_dynamic_sched_update) || 3079 BCM_GPORT_IS_SCHEDULER(port)) { 3080 for (cur_node = node->child; cur_node != NULL; 3081 cur_node = cur_node->sibling) { 3082 if (cur_node->cosq_attached_to == cosq) { 3083 break; 3084 } 3085 } 3086 } else { 3087 numq = soc_property_get(unit, spn_BCM_NUM_COS, BCM_COS_DEFAULT); 3088 for (cur_node = node->child; cur_node != NULL; 3089 cur_node = cur_node->sibling) { 3090 if (cur_node->child != NULL && (cur_node->cosq_attached_to == cosq || 3091 cur_node->cosq_attached_to == (cosq + numq))) { 3092 break; 3093 } 3094 } 3095 3096 if (cur_node != NULL) { 3097 cur_node = cur_node->child; 3098 } 3099 } 3100 3101 if (cur_node == NULL) { 3102 /* this cosq is not yet attached */ 3103 return BCM_E_INTERNAL; 3104 } 3105 3106 if (cur_node->wrr_in_use == 1 && mode == BCM_COSQ_STRICT) { 3107 if (cur_node->cosq_attached_to >= 8) { 3108 return BCM_E_PARAM; 3109 } 3110 if (!soc_feature(unit, soc_feature_dynamic_sched_update) && 3111 !soc_feature(unit, soc_feature_vector_based_spri) && 3112 _bcm_kt_cosq_valid_werr_node(unit, node, cur_node->cosq_attached_to, 1) == 0) 3113 { 3114 return BCM_E_PARAM; 3115 } 3116 state = _BCM_KT_COSQ_STATE_WRR_TO_SPRI; 3117 } 3118 3119 if (cur_node->wrr_in_use == 0 && mode != BCM_COSQ_STRICT) { 3120 if (!soc_feature(unit, soc_feature_dynamic_sched_update) && 3121 !soc_feature(unit, soc_feature_vector_based_spri) && 3122 _bcm_kt_cosq_valid_werr_node(unit, node, cur_node->cosq_attached_to, 0) == 0) 3123 { 3124 return BCM_E_PARAM; 3125 } 3126 state = _BCM_KT_COSQ_STATE_SPRI_TO_WRR; 3127 } 3128 3129 if (state == _BCM_KT_COSQ_STATE_SPRI_TO_WRR && 3130 cur_node->level == _BCM_KT_COSQ_NODE_LEVEL_L2) { 3131 SOC_IF_ERROR_RETURN 3132 (READ_LLS_L2_PARENTm(unit, MEM_BLOCK_ALL, cur_node->hw_index, 3133 &l2_parent)); 3134 if (soc_mem_field32_get(unit, LLS_L2_PARENTm, 3135 &l2_parent, C_EFf) == 1) { 3136 return BCM_E_PARAM; 3137 } 3138 } 3139 3140 if (soc_feature(unit, soc_feature_dynamic_sched_update) && 3141 !BCM_GPORT_IS_SCHEDULER(port)) { 3142 if (state == _BCM_KT_COSQ_STATE_WRR_TO_SPRI || 3143 state == _BCM_KT_COSQ_STATE_SPRI_TO_WRR) { 3144 parent_id = (BCM_GPORT_SCHEDULER_GET(cur_node->parent->gport) >> 8) & 0x7ff; 3145 remap_gport = mmu_info->l1_gport_pair[parent_id]; 3146 BCM_IF_ERROR_RETURN 3147 (_bcm_kt_cosq_dynamic_sched_update(unit, port, cosq, mode, cur_node)); 3148 BCM_IF_ERROR_RETURN 3149 (_bcm_kt_cosq_node_get(unit, remap_gport, NULL, &local_port, NULL, 3150 &node)); 3151 } else { 3152 BCM_IF_ERROR_RETURN 3153 (_bcm_kt_cosq_node_get(unit, cur_node->parent->gport, 3154 NULL, &local_port, NULL, 3155 &node)); 3156 } 3157 port = node->parent->gport; 3158 cosq = node->cosq_attached_to; 3159 BCM_IF_ERROR_RETURN 3160 (_bcm_kt_cosq_node_get(unit, port, NULL, &local_port, NULL, 3161 &node)); 3162 } else { 3163 cur_node->wrr_in_use = (mode != BCM_COSQ_STRICT) ? 1 : 0; 3164 rv = _bcm_kt_cosq_sched_node_set(unit, cur_node->gport, state); 3165 if (BCM_FAILURE(rv)) { 3166 if (state == _BCM_KT_COSQ_STATE_SPRI_TO_WRR) { 3167 cur_node->wrr_in_use = 0; 3168 } else if (state == _BCM_KT_COSQ_STATE_WRR_TO_SPRI) { 3169 cur_node->wrr_in_use = 1; 3170 } 3171 } 3172 } 3173 3174 if (mode != BCM_COSQ_STRICT) { 3175 mem = LLS_PORT_CONFIGm; 3176 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, 3177 local_port, &entry)); 3178 fval = ((mode == BCM_COSQ_WEIGHTED_ROUND_ROBIN) || 3179 (mode == BCM_COSQ_ROUND_ROBIN)) ? 1 : 0; 3180 if (soc_mem_field32_get(unit, mem, entry, 3181 PACKET_MODE_WRR_ACCOUNTING_ENABLEf) != fval) { 3182 soc_mem_field32_set(unit, mem, entry, 3183 PACKET_MODE_WRR_ACCOUNTING_ENABLEf, fval); 3184 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ANY, 3185 local_port, &entry)); 3186 } 3187 } 3188 3189 switch (node->level) { 3190 case _BCM_KT_COSQ_NODE_LEVEL_ROOT: /* port scheduler */ 3191 for (i = 0; i < num_weights; i++) { 3192 BCM_IF_ERROR_RETURN 3193 (_bcm_kt_cosq_index_resolve(unit, port, cosq + i, 3194 _BCM_KT_COSQ_INDEX_STYLE_SCHEDULER, 3195 NULL, &index, NULL)); 3196 SOC_IF_ERROR_RETURN 3197 (READ_LLS_L0_CHILD_WEIGHT_CFG_CNTm(unit, MEM_BLOCK_ALL, index, &l0_weight_cfg)); 3198 soc_mem_field32_set(unit, LLS_L0_CHILD_WEIGHT_CFG_CNTm, (uint32 *)&l0_weight_cfg, 3199 C_WEIGHTf, (mode == BCM_COSQ_ROUND_ROBIN) ? 1: weights[i]); 3200 soc_mem_field32_set(unit, LLS_L0_CHILD_WEIGHT_CFG_CNTm, (uint32 *)&l0_weight_cfg, 3201 C_WEIGHT_SURPLUS_COUNTf, 0); 3202 soc_mem_field32_set(unit, LLS_L0_CHILD_WEIGHT_CFG_CNTm, (uint32 *)&l0_weight_cfg, 3203 C_WEIGHT_COUNTf, 0); 3204 SOC_IF_ERROR_RETURN 3205 (WRITE_LLS_L0_CHILD_WEIGHT_CFG_CNTm(unit, MEM_BLOCK_ALL, index, &l0_weight_cfg)); 3206 3207 } 3208 break; 3209 3210 case _BCM_KT_COSQ_NODE_LEVEL_L0: /* L0 scheduler */ 3211 for (i = 0; i < num_weights; i++) { 3212 BCM_IF_ERROR_RETURN 3213 (_bcm_kt_cosq_index_resolve(unit, port, cosq + i, 3214 _BCM_KT_COSQ_INDEX_STYLE_SCHEDULER, 3215 NULL, &index, NULL)); 3216 SOC_IF_ERROR_RETURN 3217 (READ_LLS_L1_CHILD_WEIGHT_CFG_CNTm(unit, MEM_BLOCK_ALL, index, &l1_weight_cfg)); 3218 soc_mem_field32_set(unit, LLS_L1_CHILD_WEIGHT_CFG_CNTm, (uint32 *)&l1_weight_cfg, 3219 C_WEIGHTf, (mode == BCM_COSQ_ROUND_ROBIN) ? 1: weights[i]); 3220 soc_mem_field32_set(unit, LLS_L1_CHILD_WEIGHT_CFG_CNTm, (uint32 *)&l1_weight_cfg, 3221 C_WEIGHT_SURPLUS_COUNTf, 0); 3222 soc_mem_field32_set(unit, LLS_L1_CHILD_WEIGHT_CFG_CNTm, (uint32 *)&l1_weight_cfg, 3223 C_WEIGHT_COUNTf, 0); 3224 SOC_IF_ERROR_RETURN 3225 (WRITE_LLS_L1_CHILD_WEIGHT_CFG_CNTm(unit, MEM_BLOCK_ALL, index, &l1_weight_cfg)); 3226 3227 } 3228 break; 3229 3230 case _BCM_KT_COSQ_NODE_LEVEL_L1: /* L1 scheduler */ 3231 for (i = 0; i < num_weights; i++) { 3232 BCM_IF_ERROR_RETURN 3233 (_bcm_kt_cosq_index_resolve(unit, port, cosq + i, 3234 _BCM_KT_COSQ_INDEX_STYLE_SCHEDULER, 3235 NULL, &index, NULL)); 3236 SOC_IF_ERROR_RETURN 3237 (READ_LLS_L2_CHILD_WEIGHT_CFG_CNTm(unit, MEM_BLOCK_ALL, index, &l2_weight_cfg)); 3238 soc_mem_field32_set(unit, LLS_L2_CHILD_WEIGHT_CFG_CNTm, (uint32 *)&l2_weight_cfg, 3239 C_WEIGHTf, (mode == BCM_COSQ_ROUND_ROBIN) ? 1: weights[i]); 3240 soc_mem_field32_set(unit, LLS_L2_CHILD_WEIGHT_CFG_CNTm, (uint32 *)&l2_weight_cfg, 3241 C_WEIGHT_SURPLUS_COUNTf, 0); 3242 soc_mem_field32_set(unit, LLS_L2_CHILD_WEIGHT_CFG_CNTm, (uint32 *)&l2_weight_cfg, 3243 C_WEIGHT_COUNTf, 0); 3244 SOC_IF_ERROR_RETURN 3245 (WRITE_LLS_L2_CHILD_WEIGHT_CFG_CNTm(unit, MEM_BLOCK_ALL, index, &l2_weight_cfg)); 3246 3247 } 3248 break; 3249 3250 default: 3251 return BCM_E_INTERNAL; 3252 } 3253 3254 return BCM_E_NONE; 3255 } 3256 3257 /* 3258 * Function: 3259 * _bcm_kt_cosq_sched_get 3260 * Purpose: 3261 * Get scheduling mode setting 3262 * Parameters: 3263 * unit - (IN) unit number 3264 * port - (IN) port number or GPORT identifier 3265 * cosq - (IN) COS queue number 3266 * mode - (OUT) scheduling mode (BCM_COSQ_XXX) 3267 * num_weights - (IN) number of entries in weights array 3268 * weights - (OUT) weights array 3269 * Returns: 3270 * BCM_E_XXX 3271 */ 3272 STATIC int 3273 _bcm_kt_cosq_sched_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 3274 int *mode, int num_weights, int weights[]) 3275 { 3276 _bcm_kt_mmu_info_t *mmu_info; 3277 _bcm_kt_cosq_node_t *node, *l0_node = NULL; 3278 _bcm_kt_cosq_node_t *cur_node; 3279 bcm_port_t local_port; 3280 int index; 3281 int i; 3282 lls_l0_child_weight_cfg_cnt_entry_t l0_weight_cfg; 3283 lls_l1_child_weight_cfg_cnt_entry_t l1_weight_cfg; 3284 lls_l2_child_weight_cfg_cnt_entry_t l2_weight_cfg; 3285 int numq; 3286 soc_mem_t mem; 3287 uint32 entry[SOC_MAX_MEM_WORDS]; 3288 3289 if (cosq < 0) { 3290 if (cosq == -1) { 3291 /* caller needs to resolve the wild card value */ 3292 return BCM_E_INTERNAL; 3293 } else { 3294 /* reject all other negative value */ 3295 return BCM_E_PARAM; 3296 } 3297 } 3298 3299 if (BCM_GPORT_IS_SCHEDULER(port)) { /* ETS style scheduler */ 3300 BCM_IF_ERROR_RETURN 3301 (_bcm_kt_cosq_node_get(unit, port, NULL, &local_port, NULL, 3302 &node)); 3303 } else { 3304 BCM_IF_ERROR_RETURN 3305 (_bcm_kt_cosq_localport_resolve(unit, port, &local_port)); 3306 mmu_info = _bcm_kt_mmu_info[unit]; 3307 3308 node = &mmu_info->sched_node[local_port]; 3309 3310 if (node->gport < 0) { 3311 return BCM_E_PARAM; 3312 } 3313 3314 if ((l0_node = node->child) == NULL) { 3315 return BCM_E_PARAM; 3316 } 3317 if (!soc_feature(unit, soc_feature_dynamic_sched_update)) { 3318 if ((node = l0_node->child) == NULL) { 3319 return BCM_E_PARAM; 3320 } 3321 } else { 3322 node = l0_node; 3323 } 3324 if (IS_CPU_PORT(unit, local_port)) { 3325 /* 3326 * In case when number of cpu queues are not multiples of 8 3327 * there is chance last siblings gets numq < 8, 3328 * which may result in failure , So node is moved to the 3329 * first sibling, which guarantee to have numq = 8 3330 */ 3331 for (cur_node = l0_node; cur_node->sibling != NULL; 3332 cur_node = cur_node->sibling) { 3333 /* After warm boot first sibling will have numq = 4 3334 * check for the parent node in which all childs will have the numq = 8 3335 * so we wont see failure 3336 */ 3337 if (cur_node->numq == 5) { 3338 break; 3339 } 3340 } 3341 for (cur_node = cur_node->child; cur_node->sibling != NULL; 3342 cur_node = cur_node->sibling); 3343 node = cur_node; 3344 } 3345 } 3346 3347 if (node->numq > 0 && (cosq + num_weights) > node->numq) { 3348 return BCM_E_PARAM; 3349 } 3350 3351 if (node->cosq_attached_to < 0) { /* Not resolved yet */ 3352 return BCM_E_NOT_FOUND; 3353 } 3354 3355 if (!soc_feature(unit, soc_feature_dynamic_sched_update)) { 3356 for (cur_node = node->child; cur_node != NULL; 3357 cur_node = cur_node->sibling) { 3358 if (cur_node->cosq_attached_to == cosq) { 3359 break; 3360 } 3361 } 3362 } else { 3363 numq = soc_property_get(unit, spn_BCM_NUM_COS, BCM_COS_DEFAULT); 3364 for (cur_node = node->child; cur_node != NULL; 3365 cur_node = cur_node->sibling) { 3366 if (cur_node->child != NULL && (cur_node->cosq_attached_to == cosq || 3367 cur_node->cosq_attached_to == (cosq + numq))) { 3368 break; 3369 } 3370 } 3371 3372 if (cur_node != NULL) { 3373 port = l0_node->gport; 3374 cosq = cur_node->cosq_attached_to; 3375 } 3376 } 3377 3378 switch (node->level) { 3379 case _BCM_KT_COSQ_NODE_LEVEL_ROOT: /* port scheduler */ 3380 for (i = 0; i < num_weights; i++) { 3381 BCM_IF_ERROR_RETURN 3382 (_bcm_kt_cosq_index_resolve(unit, port, cosq + i, 3383 _BCM_KT_COSQ_INDEX_STYLE_SCHEDULER, 3384 NULL, &index, NULL)); 3385 SOC_IF_ERROR_RETURN 3386 (READ_LLS_L0_CHILD_WEIGHT_CFG_CNTm(unit, MEM_BLOCK_ALL, index, &l0_weight_cfg)); 3387 weights[i] = soc_mem_field32_get(unit, LLS_L0_CHILD_WEIGHT_CFG_CNTm, (uint32 *)&l0_weight_cfg, C_WEIGHTf); 3388 } 3389 break; 3390 3391 case _BCM_KT_COSQ_NODE_LEVEL_L0: /* L0 scheduler */ 3392 for (i = 0; i < num_weights; i++) { 3393 BCM_IF_ERROR_RETURN 3394 (_bcm_kt_cosq_index_resolve(unit, port, cosq + i, 3395 _BCM_KT_COSQ_INDEX_STYLE_SCHEDULER, 3396 NULL, &index, NULL)); 3397 SOC_IF_ERROR_RETURN 3398 (READ_LLS_L1_CHILD_WEIGHT_CFG_CNTm(unit, MEM_BLOCK_ALL, index, &l1_weight_cfg)); 3399 weights[i] = soc_mem_field32_get(unit, LLS_L1_CHILD_WEIGHT_CFG_CNTm, (uint32 *)&l1_weight_cfg, C_WEIGHTf); 3400 3401 } 3402 break; 3403 3404 case _BCM_KT_COSQ_NODE_LEVEL_L1: /* L1 scheduler */ 3405 for (i = 0; i < num_weights; i++) { 3406 BCM_IF_ERROR_RETURN 3407 (_bcm_kt_cosq_index_resolve(unit, port, cosq + i, 3408 _BCM_KT_COSQ_INDEX_STYLE_SCHEDULER, 3409 NULL, &index, NULL)); 3410 SOC_IF_ERROR_RETURN 3411 (READ_LLS_L2_CHILD_WEIGHT_CFG_CNTm(unit, MEM_BLOCK_ALL, index, &l2_weight_cfg)); 3412 weights[i] = soc_mem_field32_get(unit, LLS_L2_CHILD_WEIGHT_CFG_CNTm, (uint32 *)&l2_weight_cfg, C_WEIGHTf); 3413 3414 } 3415 break; 3416 3417 default: 3418 return BCM_E_INTERNAL; 3419 } 3420 3421 if (cur_node->wrr_in_use == 0) { 3422 *mode = BCM_COSQ_STRICT; 3423 } else { 3424 mem = LLS_PORT_CONFIGm; 3425 BCM_IF_ERROR_RETURN( 3426 soc_mem_read(unit, mem, MEM_BLOCK_ALL, local_port, &entry)); 3427 if (soc_mem_field32_get(unit, mem, entry, 3428 PACKET_MODE_WRR_ACCOUNTING_ENABLEf)) { 3429 *mode = BCM_COSQ_WEIGHTED_ROUND_ROBIN; 3430 } else { 3431 *mode = BCM_COSQ_DEFICIT_ROUND_ROBIN; 3432 } 3433 3434 } 3435 3436 return BCM_E_NONE; 3437 } 3438 3439 /* 3440 * Function: 3441 * _bcm_kt_cosq_port_sched_set 3442 * Purpose: 3443 * Set scheduling mode setting for a port 3444 * Parameters: 3445 * unit - (IN) unit number 3446 * port - (IN) port number or GPORT identifier 3447 * cosq - (IN) COS queue number 3448 * mode - (IN) scheduling mode (BCM_COSQ_XXX) 3449 * num_weights - (IN) number of entries in weights array 3450 * weights - (IN) weights array 3451 * Returns: 3452 * BCM_E_XXX 3453 */ 3454 STATIC int 3455 _bcm_kt_cosq_port_sched_set(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 3456 int mode, int num_weights, int *weights) 3457 { 3458 int i; 3459 3460 for (i = 0; i < num_weights; i++) { 3461 BCM_IF_ERROR_RETURN 3462 (_bcm_kt_cosq_sched_set(unit, port, (cosq + i), mode, 1, &weights[i])); 3463 3464 } 3465 3466 return BCM_E_NONE; 3467 } 3468 3469 /* 3470 * Function: 3471 * _bcm_kt_cosq_port_sched_get 3472 * Purpose: 3473 * Set scheduling mode setting for a port 3474 * Parameters: 3475 * unit - (IN) unit number 3476 * port - (IN) port number or GPORT identifier 3477 * cosq - (IN) COS queue number 3478 * mode - (OUT) scheduling mode (BCM_COSQ_XXX) 3479 * num_weights - (IN) number of entries in weights array 3480 * weights - (OUT) weights array 3481 * Returns: 3482 * BCM_E_XXX 3483 */ 3484 STATIC int 3485 _bcm_kt_cosq_port_sched_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 3486 int *mode, int num_weights, int *weights) 3487 { 3488 int i; 3489 3490 for (i = 0; i < num_weights; i++) { 3491 BCM_IF_ERROR_RETURN 3492 (_bcm_kt_cosq_sched_get(unit, port, (cosq + i), mode, 1, &weights[i])); 3493 3494 } 3495 3496 return BCM_E_NONE; 3497 } 3498 3499 /* 3500 * Function: 3501 * _bcm_kt_cosq_mapping_set_regular 3502 * Purpose: 3503 * Determine which COS queue a given priority currently maps to. 3504 * Parameters: 3505 * unit - (IN) unit number 3506 * gport - (IN) queue group GPORT identifier 3507 * priority - (IN) priority value to map 3508 * cosq - (IN) COS queue to map to 3509 * Returns: 3510 * BCM_E_XXX 3511 */ 3512 STATIC int 3513 _bcm_kt_cosq_mapping_set_regular(int unit, bcm_port_t gport, bcm_cos_t priority, 3514 bcm_cos_queue_t cosq) 3515 { 3516 _bcm_kt_mmu_info_t *mmu_info; 3517 bcm_port_t port; 3518 int numq; 3519 bcm_cos_queue_t hw_cosq; 3520 soc_field_t field = COSf; 3521 cos_map_sel_entry_t cos_map_sel_entry; 3522 port_cos_map_entry_t cos_map_entries[16]; 3523 void *entries[1]; 3524 uint32 old_index, new_index; 3525 int rv; 3526 #ifndef BCM_COSQ_HIGIG_MAP_DISABLE 3527 int cpu_hg_index = 0; 3528 #endif 3529 3530 if (priority < 0 || priority >= 16) { 3531 return BCM_E_PARAM; 3532 } 3533 3534 hw_cosq = cosq; 3535 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 3536 BCM_IF_ERROR_RETURN 3537 (_bcm_kt_cosq_index_resolve 3538 (unit, gport, cosq, _BCM_KT_COSQ_INDEX_STYLE_UCAST_QUEUE, 3539 &port, &hw_cosq, NULL)); 3540 } else { 3541 if (BCM_GPORT_IS_SET(gport)) { 3542 BCM_IF_ERROR_RETURN( 3543 bcm_esw_port_local_get(unit, gport, &port)); 3544 } else { 3545 port = gport; 3546 } 3547 3548 if (!SOC_PORT_VALID(unit, port) || !IS_ALL_PORT(unit, port)) { 3549 return BCM_E_PORT; 3550 } 3551 } 3552 3553 mmu_info = _bcm_kt_mmu_info[unit]; 3554 numq = mmu_info->port[port].q_limit - 3555 mmu_info->port[port].q_offset; 3556 3557 if (cosq >= numq) { 3558 return BCM_E_PARAM; 3559 } 3560 3561 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 3562 field = (numq <= 8) ? COSf : HG_COSf; 3563 } 3564 3565 entries[0] = &cos_map_entries; 3566 3567 BCM_IF_ERROR_RETURN 3568 (READ_COS_MAP_SELm(unit, MEM_BLOCK_ANY, port, &cos_map_sel_entry)); 3569 old_index = soc_mem_field32_get(unit, COS_MAP_SELm, &cos_map_sel_entry, 3570 SELECTf); 3571 old_index *= 16; 3572 3573 BCM_IF_ERROR_RETURN 3574 (soc_profile_mem_get(unit, _bcm_kt_cos_map_profile[unit], 3575 old_index, 16, entries)); 3576 soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[priority], field, 3577 hw_cosq); 3578 3579 soc_mem_lock(unit, PORT_COS_MAPm); 3580 3581 rv = soc_profile_mem_delete(unit, _bcm_kt_cos_map_profile[unit], 3582 old_index); 3583 #ifndef BCM_COSQ_HIGIG_MAP_DISABLE 3584 if (BCM_SUCCESS(rv) && IS_CPU_PORT(unit, port)) { 3585 rv = soc_profile_mem_delete(unit, _bcm_kt_cos_map_profile[unit], 3586 old_index); 3587 } 3588 #endif /* BCM_COSQ_HIGIG_MAP_DISABLE */ 3589 if (BCM_FAILURE(rv)) { 3590 soc_mem_unlock(unit, PORT_COS_MAPm); 3591 return rv; 3592 } 3593 3594 rv = soc_profile_mem_add(unit, _bcm_kt_cos_map_profile[unit], entries, 3595 16, &new_index); 3596 #ifndef BCM_COSQ_HIGIG_MAP_DISABLE 3597 if (BCM_SUCCESS(rv) && IS_CPU_PORT(unit, port)) { 3598 rv = soc_profile_mem_reference(unit, _bcm_kt_cos_map_profile[unit], 3599 new_index, 16); 3600 } 3601 #endif /* BCM_COSQ_HIGIG_MAP_DISABLE */ 3602 3603 if (rv == SOC_E_RESOURCE) { 3604 (void)soc_profile_mem_reference(unit, _bcm_kt_cos_map_profile[unit], 3605 old_index, 16); 3606 #ifndef BCM_COSQ_HIGIG_MAP_DISABLE 3607 if (IS_CPU_PORT(unit, port)) { 3608 (void)soc_profile_mem_reference(unit, 3609 _bcm_kt_cos_map_profile[unit], 3610 old_index, 16); 3611 } 3612 #endif /* BCM_COSQ_HIGIG_MAP_DISABLE */ 3613 } 3614 3615 soc_mem_unlock(unit, PORT_COS_MAPm); 3616 3617 if (BCM_FAILURE(rv)) { 3618 return rv; 3619 } 3620 3621 soc_mem_field32_set(unit, COS_MAP_SELm, &cos_map_sel_entry, SELECTf, 3622 new_index / 16); 3623 BCM_IF_ERROR_RETURN 3624 (WRITE_COS_MAP_SELm(unit, MEM_BLOCK_ANY, port, &cos_map_sel_entry)); 3625 3626 #ifndef BCM_COSQ_HIGIG_MAP_DISABLE 3627 if (IS_CPU_PORT(unit, port)) { 3628 cpu_hg_index = SOC_IS_KATANA2(unit) ? 3629 SOC_INFO(unit).cpu_hg_pp_port_index : 3630 SOC_INFO(unit).cpu_hg_index; 3631 BCM_IF_ERROR_RETURN 3632 (soc_mem_field32_modify(unit, COS_MAP_SELm, 3633 cpu_hg_index, SELECTf, 3634 new_index / 16)); 3635 } 3636 #endif /* BCM_COSQ_HIGIG_MAP_DISABLE */ 3637 3638 return BCM_E_NONE; 3639 } 3640 3641 /* 3642 * Function: 3643 * _bcm_kt_cosq_bucket_set 3644 * Purpose: 3645 * Configure COS queue bandwidth control bucket 3646 * Parameters: 3647 * unit - (IN) unit number 3648 * port - (IN) port number or GPORT identifier 3649 * cosq - (IN) COS queue number 3650 * min_quantum - (IN) kbps or packet/second 3651 * max_quantum - (IN) kbps or packet/second 3652 * burst_quantum - (IN) kbps or packet/second 3653 * flags - (IN) 3654 * Returns: 3655 * BCM_E_XXX 3656 * Notes: 3657 * If port is any form of local port, cosq is the hardware queue index. 3658 */ 3659 STATIC int 3660 _bcm_kt_cosq_bucket_set(int unit, bcm_gport_t port, bcm_cos_queue_t cosq, 3661 uint32 min_quantum, uint32 max_quantum, 3662 uint32 burst_min_quantum, uint32 burst_max_quantum, 3663 uint32 flags) 3664 { 3665 int rv; 3666 _bcm_kt_cosq_node_t *node; 3667 bcm_port_t local_port; 3668 int index; 3669 soc_mem_t config_mem[2]; 3670 soc_mem_t bucket_mem; 3671 lls_port_shaper_config_c_entry_t port_entry; 3672 lls_port_shaper_config_c_entry_t port_null_entry; 3673 lls_port_shaper_bucket_c_entry_t port_bucket_entry; 3674 lls_l0_shaper_config_c_entry_t l0_entry; 3675 lls_l1_shaper_config_c_entry_t l1_entry; 3676 lls_l2_shaper_config_lower_entry_t l2_entry; 3677 lls_l0_min_config_c_entry_t l0_null_entry; 3678 lls_l0_min_bucket_c_entry_t l0_bucket_entry; 3679 lls_l1_min_config_c_entry_t l1_null_entry; 3680 lls_l1_min_bucket_c_entry_t l1_bucket_entry; 3681 lls_l2_min_config_lower_c_entry_t l2_null_entry; 3682 lls_l2_min_bucket_lower_c_entry_t l2_bucket_entry; 3683 lls_l2_shaper_config_lower_entry_t l2_null_max_entry; 3684 lls_l2_shaper_bucket_lower_entry_t l2_bucket_max_entry; 3685 uint32 rate_exp[2], rate_mantissa[2]; 3686 uint32 burst_exp[2], burst_mantissa[2]; 3687 uint32 cycle_sel[2]; 3688 uint32 burst_min, burst_max; 3689 int i, idx; 3690 int level = _BCM_KT_COSQ_NODE_LEVEL_L2; 3691 soc_field_t rate_exp_f[] = { 3692 C_MAX_REF_RATE_EXPf, C_MIN_REF_RATE_EXPf 3693 }; 3694 soc_field_t rate_mant_f[] = { 3695 C_MAX_REF_RATE_MANTf, C_MIN_REF_RATE_MANTf 3696 }; 3697 soc_field_t burst_exp_f[] = { 3698 C_MAX_THLD_EXPf, C_MIN_THLD_EXPf 3699 }; 3700 soc_field_t burst_mant_f[] = { 3701 C_MAX_THLD_MANTf, C_MIN_THLD_MANTf 3702 }; 3703 soc_field_t cycle_sel_f[] = { 3704 C_MAX_CYCLE_SELf, C_MIN_CYCLE_SELf 3705 }; 3706 static const soc_field_t rate_exp_fields[] = { 3707 C_MAX_REF_RATE_EXP_0f, C_MAX_REF_RATE_EXP_1f, 3708 C_MAX_REF_RATE_EXP_2f, C_MAX_REF_RATE_EXP_3f, 3709 C_MIN_REF_RATE_EXP_0f, C_MIN_REF_RATE_EXP_1f, 3710 C_MIN_REF_RATE_EXP_2f, C_MIN_REF_RATE_EXP_3f 3711 }; 3712 static const soc_field_t rate_mant_fields[] = { 3713 C_MAX_REF_RATE_MANT_0f, C_MAX_REF_RATE_MANT_1f, 3714 C_MAX_REF_RATE_MANT_2f, C_MAX_REF_RATE_MANT_3f, 3715 C_MIN_REF_RATE_MANT_0f, C_MIN_REF_RATE_MANT_1f, 3716 C_MIN_REF_RATE_MANT_2f, C_MIN_REF_RATE_MANT_3f 3717 }; 3718 static const soc_field_t burst_exp_fields[] = { 3719 C_MAX_THLD_EXP_0f, C_MAX_THLD_EXP_1f, 3720 C_MAX_THLD_EXP_2f, C_MAX_THLD_EXP_3f, 3721 C_MIN_THLD_EXP_0f, C_MIN_THLD_EXP_1f, 3722 C_MIN_THLD_EXP_2f, C_MIN_THLD_EXP_3f 3723 }; 3724 static const soc_field_t burst_mant_fields[] = { 3725 C_MAX_THLD_MANT_0f, C_MAX_THLD_MANT_1f, 3726 C_MAX_THLD_MANT_2f, C_MAX_THLD_MANT_3f, 3727 C_MIN_THLD_MANT_0f, C_MIN_THLD_MANT_1f, 3728 C_MIN_THLD_MANT_2f, C_MIN_THLD_MANT_3f 3729 }; 3730 soc_field_t cycle_sel_fields[] = { 3731 C_MAX_CYCLE_SEL_0f, C_MAX_CYCLE_SEL_1f, 3732 C_MAX_CYCLE_SEL_2f, C_MAX_CYCLE_SEL_3f, 3733 C_MIN_CYCLE_SEL_0f, C_MIN_CYCLE_SEL_1f, 3734 C_MIN_CYCLE_SEL_2f, C_MIN_CYCLE_SEL_3f 3735 }; 3736 3737 if (cosq < 0) { 3738 if (cosq == -1) { 3739 /* caller needs to resolve the wild card value (-1) */ 3740 return BCM_E_INTERNAL; 3741 } else { /* reject all other negative value */ 3742 return BCM_E_PARAM; 3743 } 3744 } 3745 3746 3747 BCM_IF_ERROR_RETURN 3748 (_bcm_kt_cosq_index_resolve(unit, port, cosq, 3749 _BCM_KT_COSQ_INDEX_STYLE_BUCKET, 3750 &local_port, &index, NULL)); 3751 3752 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 3753 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port) || 3754 BCM_GPORT_IS_SCHEDULER(port)) { 3755 BCM_IF_ERROR_RETURN 3756 (_bcm_kt_cosq_node_get(unit, port, NULL, NULL, NULL, &node)); 3757 level = node->level; 3758 if ((level== _BCM_KT_COSQ_NODE_LEVEL_ROOT) && 3759 (min_quantum > 0)) { 3760 /* min shaper is not supported */ 3761 return BCM_E_PARAM; 3762 } 3763 } 3764 3765 /* compute exp and mantissa and program the registers */ 3766 rv = soc_katana_get_shaper_rate_info(unit, max_quantum, 3767 &rate_mantissa[0], &rate_exp[0]); 3768 if (BCM_FAILURE(rv)) { 3769 return(rv); 3770 } 3771 3772 rv = soc_katana_get_shaper_rate_info(unit, min_quantum, 3773 &rate_mantissa[1], &rate_exp[1]); 3774 if (BCM_FAILURE(rv)) { 3775 return(rv); 3776 } 3777 3778 burst_max = burst_max_quantum; 3779 burst_min = burst_min_quantum; 3780 rv = soc_katana_get_shaper_burst_info(unit, burst_max, &burst_mantissa[0], 3781 &burst_exp[0], flags); 3782 if (BCM_FAILURE(rv)) { 3783 return(rv); 3784 } 3785 3786 rv = soc_katana_get_shaper_burst_info(unit, burst_min, &burst_mantissa[1], 3787 &burst_exp[1], flags); 3788 if (BCM_FAILURE(rv)) { 3789 return(rv); 3790 } 3791 3792 if (!(flags & _BCM_XGS_METER_FLAG_NON_BURST_CORRECTION)) { 3793 /* set recommended burst settings */ 3794 for (i = 0; i < 2; i++) { 3795 if (rate_exp[i] != 0) { 3796 if (rate_exp[i] < 10) { 3797 burst_exp[i] = 5; 3798 burst_mantissa[i] = 0; 3799 } else { 3800 burst_exp[i] = rate_exp[i] - 4; 3801 burst_mantissa[i] = (rate_mantissa[i] >> 3); 3802 } 3803 } 3804 } 3805 /* set recommended refresh rate/cycle_sel settings */ 3806 for (i = 0; i < 2; i++) { 3807 if (rate_exp[i] > 4) { 3808 cycle_sel[i] = 0; 3809 } else if (rate_exp[i] > 1) { 3810 cycle_sel[i] = 5 - rate_exp[i]; 3811 } else { 3812 cycle_sel[i] = 4; 3813 } 3814 } 3815 } else { 3816 for (i = 0; i < 2; i++) { 3817 if ((burst_exp[i] >= 14) && (burst_mantissa[i] >= 124)) { 3818 /* maximum supported is 2064384 byte */ 3819 burst_exp[i] = 14; 3820 burst_mantissa[i] = 124; 3821 } 3822 rv = soc_katana_compute_refresh_rate(unit, rate_exp[i], 3823 rate_mantissa[i], burst_exp[i], 3824 burst_mantissa[i], &cycle_sel[i]); 3825 if (BCM_FAILURE(rv)) { 3826 return(rv); 3827 } 3828 } 3829 } 3830 3831 if (soc_feature(unit, soc_feature_dynamic_shaper_update) && 3832 (level > _BCM_KT_COSQ_NODE_LEVEL_L0)) { 3833 /* set cycle_sel = 0 for L1 and L2 in A0 */ 3834 for (i = 0; i < 2; i++) { 3835 cycle_sel[i] = 0; 3836 } 3837 } 3838 3839 SOC_EGRESS_METERING_LOCK(unit); 3840 switch (level) { 3841 case _BCM_KT_COSQ_NODE_LEVEL_ROOT: 3842 config_mem[0] = LLS_PORT_SHAPER_CONFIG_Cm; 3843 sal_memset(&port_null_entry, 0, sizeof(lls_port_shaper_config_c_entry_t)); 3844 sal_memset(&port_bucket_entry, 0, sizeof(lls_port_shaper_bucket_c_entry_t)); 3845 3846 rv = soc_mem_read(unit, config_mem[0], MEM_BLOCK_ALL, 3847 index, &port_entry); 3848 if (BCM_FAILURE(rv)) { 3849 SOC_EGRESS_METERING_UNLOCK(unit); 3850 return(rv); 3851 } 3852 soc_mem_field32_set(unit, config_mem[0], &port_entry, 3853 rate_exp_f[0], rate_exp[0]); 3854 soc_mem_field32_set(unit, config_mem[0], &port_entry, 3855 rate_mant_f[0], rate_mantissa[0]); 3856 soc_mem_field32_set(unit, config_mem[0], &port_entry, 3857 burst_exp_f[0], burst_exp[0]); 3858 soc_mem_field32_set(unit, config_mem[0], &port_entry, 3859 burst_mant_f[0], burst_mantissa[0]); 3860 soc_mem_field32_set(unit, config_mem[0], &port_entry, 3861 cycle_sel_f[0], cycle_sel[0]); 3862 if (soc_feature(unit, soc_feature_dynamic_shaper_update)) { 3863 bucket_mem = LLS_PORT_SHAPER_BUCKET_Cm; 3864 rv = soc_mem_write(unit, config_mem[0], 3865 MEM_BLOCK_ALL, index, &port_null_entry); 3866 if (BCM_FAILURE(rv)) { 3867 SOC_EGRESS_METERING_UNLOCK(unit); 3868 return(rv); 3869 } 3870 soc_mem_field32_set(unit, bucket_mem, &port_bucket_entry, 3871 NOT_ACTIVE_IN_LLSf, 1); 3872 rv = soc_mem_write(unit, bucket_mem, 3873 MEM_BLOCK_ALL, index, &port_bucket_entry); 3874 if (BCM_FAILURE(rv)) { 3875 SOC_EGRESS_METERING_UNLOCK(unit); 3876 return(rv); 3877 } 3878 } 3879 rv = soc_mem_write(unit, config_mem[0], 3880 MEM_BLOCK_ALL, index, &port_entry); 3881 if (BCM_FAILURE(rv)) { 3882 SOC_EGRESS_METERING_UNLOCK(unit); 3883 return(rv); 3884 } 3885 break; 3886 3887 case _BCM_KT_COSQ_NODE_LEVEL_L0: 3888 config_mem[0] = LLS_L0_SHAPER_CONFIG_Cm; 3889 config_mem[1] = LLS_L0_MIN_CONFIG_Cm; 3890 sal_memset(&l0_null_entry, 0, sizeof(lls_l0_min_config_c_entry_t)); 3891 sal_memset(&l0_bucket_entry, 0, sizeof(lls_l0_min_bucket_c_entry_t)); 3892 3893 for (i = 0; i < 2; i++) { 3894 rv = soc_mem_read(unit, config_mem[i], MEM_BLOCK_ALL, 3895 index, &l0_entry); 3896 if (BCM_FAILURE(rv)) { 3897 SOC_EGRESS_METERING_UNLOCK(unit); 3898 return(rv); 3899 } 3900 soc_mem_field32_set(unit, config_mem[i], &l0_entry, 3901 rate_exp_f[i], rate_exp[i]); 3902 soc_mem_field32_set(unit, config_mem[i], &l0_entry, 3903 rate_mant_f[i], rate_mantissa[i]); 3904 soc_mem_field32_set(unit, config_mem[i], &l0_entry, 3905 burst_exp_f[i], burst_exp[i]); 3906 soc_mem_field32_set(unit, config_mem[i], &l0_entry, 3907 burst_mant_f[i], burst_mantissa[i]); 3908 soc_mem_field32_set(unit, config_mem[i], &l0_entry, 3909 cycle_sel_f[i], cycle_sel[i]); 3910 if (soc_feature(unit, soc_feature_dynamic_shaper_update)) { 3911 bucket_mem = (config_mem[i] == LLS_L0_MIN_CONFIG_Cm) ? 3912 LLS_L0_MIN_BUCKET_Cm : 3913 LLS_L0_SHAPER_BUCKET_Cm; 3914 rv = soc_mem_write(unit, config_mem[i], 3915 MEM_BLOCK_ALL, index, &l0_null_entry); 3916 if (BCM_FAILURE(rv)) { 3917 SOC_EGRESS_METERING_UNLOCK(unit); 3918 return(rv); 3919 } 3920 soc_mem_field32_set(unit, bucket_mem, &l0_bucket_entry, 3921 NOT_ACTIVE_IN_LLSf, 1); 3922 rv = soc_mem_write(unit, bucket_mem, 3923 MEM_BLOCK_ALL, index, &l0_bucket_entry); 3924 if (BCM_FAILURE(rv)) { 3925 SOC_EGRESS_METERING_UNLOCK(unit); 3926 return(rv); 3927 } 3928 } 3929 rv = soc_mem_write(unit, config_mem[i], 3930 MEM_BLOCK_ALL, index, &l0_entry); 3931 if (BCM_FAILURE(rv)) { 3932 SOC_EGRESS_METERING_UNLOCK(unit); 3933 return(rv); 3934 } 3935 } 3936 break; 3937 3938 case _BCM_KT_COSQ_NODE_LEVEL_L1: 3939 config_mem[0] = LLS_L1_SHAPER_CONFIG_Cm; 3940 config_mem[1] = LLS_L1_MIN_CONFIG_Cm; 3941 sal_memset(&l1_null_entry, 0, sizeof(lls_l1_min_config_c_entry_t)); 3942 sal_memset(&l1_bucket_entry, 0, sizeof(lls_l1_min_bucket_c_entry_t)); 3943 3944 for (i = 0; i < 2; i++) { 3945 idx = (i * 4) + (index % 4); 3946 rv = soc_mem_read(unit, config_mem[i], MEM_BLOCK_ALL, 3947 index/4, &l1_entry); 3948 if (BCM_FAILURE(rv)) { 3949 SOC_EGRESS_METERING_UNLOCK(unit); 3950 return(rv); 3951 } 3952 soc_mem_field32_set(unit, config_mem[i], &l1_entry, 3953 rate_exp_fields[idx], rate_exp[i]); 3954 soc_mem_field32_set(unit, config_mem[i], &l1_entry, 3955 rate_mant_fields[idx], rate_mantissa[i]); 3956 soc_mem_field32_set(unit, config_mem[i], &l1_entry, 3957 burst_exp_fields[idx], burst_exp[i]); 3958 soc_mem_field32_set(unit, config_mem[i], &l1_entry, 3959 burst_mant_fields[idx], burst_mantissa[i]); 3960 soc_mem_field32_set(unit, config_mem[i], &l1_entry, 3961 cycle_sel_fields[idx], cycle_sel[i]); 3962 if (soc_feature(unit, soc_feature_dynamic_shaper_update)) { 3963 bucket_mem = (config_mem[i] == LLS_L1_MIN_CONFIG_Cm) ? 3964 LLS_L1_MIN_BUCKET_Cm : 3965 LLS_L1_SHAPER_BUCKET_Cm; 3966 rv = soc_mem_write(unit, config_mem[i], 3967 MEM_BLOCK_ALL, index/4, &l1_null_entry); 3968 if (BCM_FAILURE(rv)) { 3969 SOC_EGRESS_METERING_UNLOCK(unit); 3970 return(rv); 3971 } 3972 soc_mem_field32_set(unit, bucket_mem, &l1_bucket_entry, 3973 NOT_ACTIVE_IN_LLS_0f, 1); 3974 soc_mem_field32_set(unit, bucket_mem, &l1_bucket_entry, 3975 NOT_ACTIVE_IN_LLS_1f, 1); 3976 soc_mem_field32_set(unit, bucket_mem, &l1_bucket_entry, 3977 NOT_ACTIVE_IN_LLS_2f, 1); 3978 soc_mem_field32_set(unit, bucket_mem, &l1_bucket_entry, 3979 NOT_ACTIVE_IN_LLS_3f, 1); 3980 rv = soc_mem_write(unit, bucket_mem, 3981 MEM_BLOCK_ALL, index/4, &l1_bucket_entry); 3982 if (BCM_FAILURE(rv)) { 3983 SOC_EGRESS_METERING_UNLOCK(unit); 3984 return(rv); 3985 } 3986 } 3987 3988 rv = soc_mem_write(unit, config_mem[i], 3989 MEM_BLOCK_ALL, index/4, &l1_entry); 3990 if (BCM_FAILURE(rv)) { 3991 SOC_EGRESS_METERING_UNLOCK(unit); 3992 return(rv); 3993 } 3994 } 3995 break; 3996 3997 case _BCM_KT_COSQ_NODE_LEVEL_L2: 3998 if ((index % 8) < 4) { 3999 config_mem[0] = LLS_L2_SHAPER_CONFIG_LOWERm; 4000 config_mem[1] = LLS_L2_MIN_CONFIG_LOWER_Cm; 4001 } else { 4002 config_mem[0] = LLS_L2_SHAPER_CONFIG_UPPERm; 4003 config_mem[1] = LLS_L2_MIN_CONFIG_UPPER_Cm; 4004 } 4005 sal_memset(&l2_null_entry, 0, sizeof(lls_l2_min_config_lower_c_entry_t)); 4006 sal_memset(&l2_bucket_entry, 0, sizeof(lls_l2_min_bucket_lower_c_entry_t)); 4007 sal_memset(&l2_null_max_entry, 0, sizeof(lls_l2_shaper_config_lower_entry_t)); 4008 sal_memset(&l2_bucket_max_entry, 0, sizeof(lls_l2_shaper_bucket_lower_entry_t)); 4009 4010 for (i = 0; i < 2; i++) { 4011 idx = (i * 4) + (index % 4); 4012 rv = soc_mem_read(unit, config_mem[i], MEM_BLOCK_ALL, 4013 index/8, &l2_entry); 4014 if (BCM_FAILURE(rv)) { 4015 SOC_EGRESS_METERING_UNLOCK(unit); 4016 return(rv); 4017 } 4018 soc_mem_field32_set(unit, config_mem[i], &l2_entry, 4019 rate_exp_fields[idx], rate_exp[i]); 4020 soc_mem_field32_set(unit, config_mem[i], &l2_entry, 4021 rate_mant_fields[idx], rate_mantissa[i]); 4022 soc_mem_field32_set(unit, config_mem[i], &l2_entry, 4023 burst_exp_fields[idx], burst_exp[i]); 4024 soc_mem_field32_set(unit, config_mem[i], &l2_entry, 4025 burst_mant_fields[idx], burst_mantissa[i]); 4026 soc_mem_field32_set(unit, config_mem[i], &l2_entry, 4027 cycle_sel_fields[idx], cycle_sel[i]); 4028 if (soc_feature(unit, soc_feature_dynamic_shaper_update) && 4029 (config_mem[i] == LLS_L2_MIN_CONFIG_LOWER_Cm || 4030 config_mem[i] == LLS_L2_MIN_CONFIG_UPPER_Cm)) { 4031 bucket_mem = (config_mem[i] == LLS_L2_MIN_CONFIG_LOWER_Cm) ? 4032 LLS_L2_MIN_BUCKET_LOWER_Cm : 4033 LLS_L2_MIN_BUCKET_UPPER_Cm; 4034 rv = soc_mem_write(unit, config_mem[i], 4035 MEM_BLOCK_ALL, index/8, &l2_null_entry); 4036 if (BCM_FAILURE(rv)) { 4037 SOC_EGRESS_METERING_UNLOCK(unit); 4038 return(rv); 4039 } 4040 soc_mem_field32_set(unit, bucket_mem, &l2_bucket_entry, 4041 NOT_ACTIVE_IN_LLS_0f, 1); 4042 soc_mem_field32_set(unit, bucket_mem, &l2_bucket_entry, 4043 NOT_ACTIVE_IN_LLS_1f, 1); 4044 soc_mem_field32_set(unit, bucket_mem, &l2_bucket_entry, 4045 NOT_ACTIVE_IN_LLS_2f, 1); 4046 soc_mem_field32_set(unit, bucket_mem, &l2_bucket_entry, 4047 NOT_ACTIVE_IN_LLS_3f, 1); 4048 rv = soc_mem_write(unit, bucket_mem, 4049 MEM_BLOCK_ALL, index/8, &l2_bucket_entry); 4050 if (BCM_FAILURE(rv)) { 4051 SOC_EGRESS_METERING_UNLOCK(unit); 4052 return(rv); 4053 } 4054 } 4055 if (soc_feature(unit, soc_feature_dynamic_shaper_update) && 4056 (config_mem[i] == LLS_L2_SHAPER_CONFIG_LOWERm || 4057 config_mem[i] == LLS_L2_SHAPER_CONFIG_UPPERm)) { 4058 bucket_mem = (config_mem[i] == LLS_L2_SHAPER_CONFIG_LOWERm) ? 4059 LLS_L2_SHAPER_BUCKET_LOWERm : 4060 LLS_L2_SHAPER_BUCKET_UPPERm; 4061 rv = soc_mem_write(unit, config_mem[i], 4062 MEM_BLOCK_ALL, index/8, &l2_null_max_entry); 4063 if (BCM_FAILURE(rv)) { 4064 SOC_EGRESS_METERING_UNLOCK(unit); 4065 return(rv); 4066 } 4067 soc_mem_field32_set(unit, bucket_mem, &l2_bucket_max_entry, 4068 NOT_ACTIVE_IN_LLS_0f, 1); 4069 soc_mem_field32_set(unit, bucket_mem, &l2_bucket_max_entry, 4070 NOT_ACTIVE_IN_LLS_1f, 1); 4071 soc_mem_field32_set(unit, bucket_mem, &l2_bucket_max_entry, 4072 NOT_ACTIVE_IN_LLS_2f, 1); 4073 soc_mem_field32_set(unit, bucket_mem, &l2_bucket_max_entry, 4074 NOT_ACTIVE_IN_LLS_3f, 1); 4075 rv = soc_mem_write(unit, bucket_mem, 4076 MEM_BLOCK_ALL, index/8, &l2_bucket_max_entry); 4077 if (BCM_FAILURE(rv)) { 4078 SOC_EGRESS_METERING_UNLOCK(unit); 4079 return(rv); 4080 } 4081 } 4082 rv = soc_mem_write(unit, config_mem[i], 4083 MEM_BLOCK_ALL, index/8, &l2_entry); 4084 if (BCM_FAILURE(rv)) { 4085 SOC_EGRESS_METERING_UNLOCK(unit); 4086 return(rv); 4087 } 4088 } 4089 break; 4090 4091 default: 4092 SOC_EGRESS_METERING_UNLOCK(unit); 4093 return BCM_E_PARAM; 4094 } 4095 4096 SOC_EGRESS_METERING_UNLOCK(unit); 4097 return BCM_E_NONE; 4098 } 4099 4100 /* 4101 * Function: 4102 * _bcm_kt_cosq_bucket_get 4103 * Purpose: 4104 * Get COS queue bandwidth control bucket setting 4105 * Parameters: 4106 * unit - (IN) unit number 4107 * port - (IN) port number or GPORT identifier 4108 * cosq - (IN) COS queue number 4109 * min_quantum - (OUT) kbps or packet/second 4110 * max_quantum - (OUT) kbps or packet/second 4111 * burst_quantum - (OUT) kbps or packet/second 4112 * flags - (IN) 4113 * Returns: 4114 * BCM_E_XXX 4115 * Notes: 4116 * If port is any form of local port, cosq is the hardware queue index. 4117 */ 4118 STATIC int 4119 _bcm_kt_cosq_bucket_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 4120 uint32 *min_quantum, uint32 *max_quantum, 4121 uint32 *burst_min_quantum, uint32 *burst_max_quantum, 4122 uint32 flags) 4123 { 4124 int rv; 4125 _bcm_kt_cosq_node_t *node; 4126 bcm_port_t local_port; 4127 int index; 4128 soc_mem_t config_mem[2]; 4129 lls_port_shaper_config_c_entry_t port_entry; 4130 lls_l0_shaper_config_c_entry_t l0_entry; 4131 lls_l1_shaper_config_c_entry_t l1_entry; 4132 lls_l2_shaper_config_lower_entry_t l2_entry; 4133 uint32 rate_exp[2], rate_mantissa[2]; 4134 uint32 burst_exp[2], burst_mantissa[2]; 4135 int i, idx; 4136 int level = _BCM_KT_COSQ_NODE_LEVEL_L2; 4137 soc_field_t rate_exp_f[] = { 4138 C_MAX_REF_RATE_EXPf, C_MIN_REF_RATE_EXPf 4139 }; 4140 soc_field_t rate_mant_f[] = { 4141 C_MAX_REF_RATE_MANTf, C_MIN_REF_RATE_MANTf 4142 }; 4143 soc_field_t burst_exp_f[] = { 4144 C_MAX_THLD_EXPf, C_MIN_THLD_EXPf 4145 }; 4146 soc_field_t burst_mant_f[] = { 4147 C_MAX_THLD_MANTf, C_MIN_THLD_MANTf 4148 }; 4149 static const soc_field_t rate_exp_fields[] = { 4150 C_MAX_REF_RATE_EXP_0f, C_MAX_REF_RATE_EXP_1f, 4151 C_MAX_REF_RATE_EXP_2f, C_MAX_REF_RATE_EXP_3f, 4152 C_MIN_REF_RATE_EXP_0f, C_MIN_REF_RATE_EXP_1f, 4153 C_MIN_REF_RATE_EXP_2f, C_MIN_REF_RATE_EXP_3f 4154 }; 4155 static const soc_field_t rate_mant_fields[] = { 4156 C_MAX_REF_RATE_MANT_0f, C_MAX_REF_RATE_MANT_1f, 4157 C_MAX_REF_RATE_MANT_2f, C_MAX_REF_RATE_MANT_3f, 4158 C_MIN_REF_RATE_MANT_0f, C_MIN_REF_RATE_MANT_1f, 4159 C_MIN_REF_RATE_MANT_2f, C_MIN_REF_RATE_MANT_3f 4160 }; 4161 static const soc_field_t burst_exp_fields[] = { 4162 C_MAX_THLD_EXP_0f, C_MAX_THLD_EXP_1f, 4163 C_MAX_THLD_EXP_2f, C_MAX_THLD_EXP_3f, 4164 C_MIN_THLD_EXP_0f, C_MIN_THLD_EXP_1f, 4165 C_MIN_THLD_EXP_2f, C_MIN_THLD_EXP_3f 4166 }; 4167 static const soc_field_t burst_mant_fields[] = { 4168 C_MAX_THLD_MANT_0f, C_MAX_THLD_MANT_1f, 4169 C_MAX_THLD_MANT_2f, C_MAX_THLD_MANT_3f, 4170 C_MIN_THLD_MANT_0f, C_MIN_THLD_MANT_1f, 4171 C_MIN_THLD_MANT_2f, C_MIN_THLD_MANT_3f 4172 }; 4173 4174 if (cosq < 0) { 4175 if (cosq == -1) { 4176 /* caller needs to resolve the wild card value (-1) */ 4177 return BCM_E_INTERNAL; 4178 } else { /* reject all other negative value */ 4179 return BCM_E_PARAM; 4180 } 4181 } 4182 4183 if (min_quantum == NULL || max_quantum == NULL || 4184 burst_min_quantum == NULL || burst_max_quantum == NULL) { 4185 return BCM_E_PARAM; 4186 } 4187 4188 BCM_IF_ERROR_RETURN 4189 (_bcm_kt_cosq_index_resolve(unit, port, cosq, 4190 _BCM_KT_COSQ_INDEX_STYLE_BUCKET, 4191 &local_port, &index, NULL)); 4192 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 4193 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port) || 4194 BCM_GPORT_IS_SCHEDULER(port)) { 4195 BCM_IF_ERROR_RETURN 4196 (_bcm_kt_cosq_node_get(unit, port, NULL, NULL, NULL, &node)); 4197 level = node->level; 4198 } 4199 4200 SOC_EGRESS_METERING_LOCK(unit); 4201 switch (level) { 4202 case _BCM_KT_COSQ_NODE_LEVEL_ROOT: 4203 config_mem[0] = LLS_PORT_SHAPER_CONFIG_Cm; 4204 rv = soc_mem_read(unit, config_mem[0], MEM_BLOCK_ALL, 4205 index, &port_entry); 4206 if (BCM_FAILURE(rv)) { 4207 SOC_EGRESS_METERING_UNLOCK(unit); 4208 return(rv); 4209 } 4210 rate_exp[0] = soc_mem_field32_get(unit, config_mem[0], &port_entry, 4211 rate_exp_f[0]); 4212 rate_mantissa[0] = soc_mem_field32_get(unit, config_mem[0], &port_entry, 4213 rate_mant_f[0]); 4214 rate_exp[1] = rate_exp[0]; 4215 rate_mantissa[1] = rate_mantissa[0]; 4216 burst_exp[0] = soc_mem_field32_get(unit, config_mem[0], &port_entry, 4217 burst_exp_f[0]); 4218 burst_mantissa[0] = soc_mem_field32_get(unit, config_mem[0], &port_entry, 4219 burst_mant_f[0]); 4220 burst_exp[1] = burst_exp[0]; 4221 burst_mantissa[1] = burst_mantissa[0]; 4222 break; 4223 4224 case _BCM_KT_COSQ_NODE_LEVEL_L0: 4225 config_mem[0] = LLS_L0_SHAPER_CONFIG_Cm; 4226 config_mem[1] = LLS_L0_MIN_CONFIG_Cm; 4227 4228 for (i = 0; i < 2; i++) { 4229 rv = soc_mem_read(unit, config_mem[i], MEM_BLOCK_ALL, 4230 index, &l0_entry); 4231 if (BCM_FAILURE(rv)) { 4232 SOC_EGRESS_METERING_UNLOCK(unit); 4233 return(rv); 4234 } 4235 rate_exp[i] = soc_mem_field32_get(unit, config_mem[i], &l0_entry, 4236 rate_exp_f[i]); 4237 rate_mantissa[i] = soc_mem_field32_get(unit, config_mem[i], &l0_entry, 4238 rate_mant_f[i]); 4239 burst_exp[i] = soc_mem_field32_get(unit, config_mem[i], &l0_entry, 4240 burst_exp_f[i]); 4241 burst_mantissa[i] = soc_mem_field32_get(unit, config_mem[i], &l0_entry, 4242 burst_mant_f[i]); 4243 } 4244 break; 4245 4246 case _BCM_KT_COSQ_NODE_LEVEL_L1: 4247 config_mem[0] = LLS_L1_SHAPER_CONFIG_Cm; 4248 config_mem[1] = LLS_L1_MIN_CONFIG_Cm; 4249 4250 for (i = 0; i < 2; i++) { 4251 idx = (i * 4) + (index % 4); 4252 rv = soc_mem_read(unit, config_mem[i], MEM_BLOCK_ALL, 4253 index/4, &l1_entry); 4254 if (BCM_FAILURE(rv)) { 4255 SOC_EGRESS_METERING_UNLOCK(unit); 4256 return(rv); 4257 } 4258 rate_exp[i] = soc_mem_field32_get(unit, config_mem[i], &l1_entry, 4259 rate_exp_fields[idx]); 4260 rate_mantissa[i] = soc_mem_field32_get(unit, config_mem[i], &l1_entry, 4261 rate_mant_fields[idx]); 4262 burst_exp[i] = soc_mem_field32_get(unit, config_mem[i], &l1_entry, 4263 burst_exp_fields[idx]); 4264 burst_mantissa[i] = soc_mem_field32_get(unit, config_mem[i], &l1_entry, 4265 burst_mant_fields[idx]); 4266 } 4267 break; 4268 4269 case _BCM_KT_COSQ_NODE_LEVEL_L2: 4270 if ((index % 8) < 4) { 4271 config_mem[0] = LLS_L2_SHAPER_CONFIG_LOWERm; 4272 config_mem[1] = LLS_L2_MIN_CONFIG_LOWER_Cm; 4273 } else { 4274 config_mem[0] = LLS_L2_SHAPER_CONFIG_UPPERm; 4275 config_mem[1] = LLS_L2_MIN_CONFIG_UPPER_Cm; 4276 } 4277 4278 for (i = 0; i < 2; i++) { 4279 idx = (i * 4) + (index % 4); 4280 rv = soc_mem_read(unit, config_mem[i], MEM_BLOCK_ALL, 4281 index/8, &l2_entry); 4282 if (BCM_FAILURE(rv)) { 4283 SOC_EGRESS_METERING_UNLOCK(unit); 4284 return(rv); 4285 } 4286 rate_exp[i] = soc_mem_field32_get(unit, config_mem[i], &l2_entry, 4287 rate_exp_fields[idx]); 4288 rate_mantissa[i] = soc_mem_field32_get(unit, config_mem[i], &l2_entry, 4289 rate_mant_fields[idx]); 4290 burst_exp[i] = soc_mem_field32_get(unit, config_mem[i], &l2_entry, 4291 burst_exp_fields[idx]); 4292 burst_mantissa[i] = soc_mem_field32_get(unit, config_mem[i], &l2_entry, 4293 burst_mant_fields[idx]); 4294 } 4295 break; 4296 4297 default: 4298 SOC_EGRESS_METERING_UNLOCK(unit); 4299 return BCM_E_PARAM; 4300 } 4301 4302 SOC_EGRESS_METERING_UNLOCK(unit); 4303 /* convert exp and mantissa to bps */ 4304 rv = soc_katana_compute_shaper_rate(unit, rate_mantissa[0], rate_exp[0], 4305 max_quantum); 4306 if (BCM_FAILURE(rv)) { 4307 return(rv); 4308 } 4309 4310 rv = soc_katana_compute_shaper_rate(unit, rate_mantissa[1], rate_exp[1], 4311 min_quantum); 4312 if (BCM_FAILURE(rv)) { 4313 return(rv); 4314 } 4315 4316 /* Reset min shaping rate for port */ 4317 if(level == _BCM_KT_COSQ_NODE_LEVEL_ROOT) { 4318 *min_quantum = 0; 4319 } 4320 4321 rv = soc_katana_compute_shaper_burst(unit, burst_mantissa[0], burst_exp[0], 4322 burst_max_quantum); 4323 if (BCM_FAILURE(rv)) { 4324 return(rv); 4325 } 4326 4327 rv = soc_katana_compute_shaper_burst(unit, burst_mantissa[1], burst_exp[1], 4328 burst_min_quantum); 4329 if (BCM_FAILURE(rv)) { 4330 return(rv); 4331 } 4332 4333 return BCM_E_NONE; 4334 } 4335 4336 STATIC int 4337 _bcm_kt_cosq_dynamic_bucket_set(int unit, bcm_gport_t port, bcm_cos_queue_t cosq, 4338 uint32 min_quantum, uint32 max_quantum, 4339 uint32 burst_min_quantum, uint32 burst_max_quantum, 4340 uint32 flags) 4341 { 4342 _bcm_kt_mmu_info_t *mmu_info; 4343 _bcm_kt_cosq_node_t *node, *cur_node, *l0_node; 4344 bcm_port_t local_port; 4345 int numq; 4346 4347 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 4348 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port) || 4349 BCM_GPORT_IS_SCHEDULER(port)) { 4350 BCM_IF_ERROR_RETURN 4351 (_bcm_kt_cosq_bucket_set(unit, port, cosq, min_quantum, 4352 max_quantum, burst_min_quantum, 4353 burst_max_quantum, flags)); 4354 } else { 4355 BCM_IF_ERROR_RETURN 4356 (_bcm_kt_cosq_localport_resolve(unit, port, &local_port)); 4357 mmu_info = _bcm_kt_mmu_info[unit]; 4358 4359 node = &mmu_info->sched_node[local_port]; 4360 4361 if (node->gport < 0) { 4362 return BCM_E_PARAM; 4363 } 4364 4365 if ((l0_node = node->child) == NULL) { 4366 return BCM_E_PARAM; 4367 } 4368 BCM_IF_ERROR_RETURN 4369 (_bcm_kt_cosq_bucket_set(unit, port, cosq, 0, 4370 max_quantum, 0, 4371 burst_max_quantum, flags)); 4372 4373 numq = soc_property_get(unit, spn_BCM_NUM_COS, BCM_COS_DEFAULT); 4374 for (cur_node = l0_node->child; cur_node != NULL; 4375 cur_node = cur_node->sibling) { 4376 if (cur_node->cosq_attached_to == cosq || 4377 cur_node->cosq_attached_to == (cosq + numq)) { 4378 BCM_IF_ERROR_RETURN 4379 (_bcm_kt_cosq_bucket_set(unit, cur_node->gport, 0, 4380 min_quantum, 4381 0, burst_min_quantum, 4382 0, flags)); 4383 continue; 4384 } 4385 } 4386 4387 } 4388 4389 return BCM_E_NONE; 4390 } 4391 4392 STATIC int 4393 _bcm_kt_cosq_dynamic_bucket_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 4394 uint32 *min_quantum, uint32 *max_quantum, 4395 uint32 *burst_min_quantum, uint32 *burst_max_quantum, 4396 uint32 flags) 4397 { 4398 _bcm_kt_mmu_info_t *mmu_info; 4399 _bcm_kt_cosq_node_t *node, *cur_node, *l0_node; 4400 bcm_port_t local_port; 4401 int numq; 4402 uint32 temp_val; 4403 4404 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 4405 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port) || 4406 BCM_GPORT_IS_SCHEDULER(port)) { 4407 BCM_IF_ERROR_RETURN 4408 (_bcm_kt_cosq_bucket_get(unit, port, cosq, 4409 min_quantum, max_quantum, 4410 burst_min_quantum, burst_max_quantum, 4411 flags)); 4412 } else { 4413 BCM_IF_ERROR_RETURN 4414 (_bcm_kt_cosq_localport_resolve(unit, port, &local_port)); 4415 mmu_info = _bcm_kt_mmu_info[unit]; 4416 4417 node = &mmu_info->sched_node[local_port]; 4418 4419 if (node->gport < 0) { 4420 return BCM_E_PARAM; 4421 } 4422 4423 if ((l0_node = node->child) == NULL) { 4424 return BCM_E_PARAM; 4425 } 4426 4427 BCM_IF_ERROR_RETURN 4428 (_bcm_kt_cosq_bucket_get(unit, port, cosq, &temp_val, 4429 max_quantum, &temp_val, 4430 burst_max_quantum, flags)); 4431 4432 numq = soc_property_get(unit, spn_BCM_NUM_COS, BCM_COS_DEFAULT); 4433 for (cur_node = l0_node->child; cur_node != NULL; 4434 cur_node = cur_node->sibling) { 4435 if (cur_node->child != NULL && (cur_node->cosq_attached_to == cosq || 4436 cur_node->cosq_attached_to == (cosq + numq))) { 4437 BCM_IF_ERROR_RETURN 4438 (_bcm_kt_cosq_bucket_get(unit, cur_node->gport, 0, 4439 min_quantum, 4440 &temp_val, burst_min_quantum, 4441 &temp_val, flags)); 4442 break; 4443 } 4444 } 4445 4446 } 4447 4448 return BCM_E_NONE; 4449 } 4450 4451 /* 4452 * Convert HW drop probability to percent value 4453 */ 4454 STATIC int 4455 _bcm_kt_hw_drop_prob_to_percent[] = { 4456 0, /* 0 */ 4457 1, /* 1 */ 4458 2, /* 2 */ 4459 3, /* 3 */ 4460 4, /* 4 */ 4461 5, /* 5 */ 4462 6, /* 6 */ 4463 7, /* 7 */ 4464 8, /* 8 */ 4465 9, /* 9 */ 4466 10, /* 10 */ 4467 25, /* 11 */ 4468 50, /* 12 */ 4469 75, /* 13 */ 4470 100, /* 14 */ 4471 -1 /* 15 */ 4472 }; 4473 4474 STATIC int 4475 _bcm_kt_percent_to_drop_prob(int percent) 4476 { 4477 int i; 4478 4479 for (i = 14; i > 0 ; i--) { 4480 if (percent >= _bcm_kt_hw_drop_prob_to_percent[i]) { 4481 break; 4482 } 4483 } 4484 return i; 4485 } 4486 4487 STATIC int 4488 _bcm_kt_drop_prob_to_percent(int drop_prob) { 4489 return (_bcm_kt_hw_drop_prob_to_percent[drop_prob]); 4490 } 4491 4492 /* 4493 * Function: 4494 * _bcm_kt_cosq_wred_set 4495 * Purpose: 4496 * Configure unicast queue WRED setting 4497 * Parameters: 4498 * unit - (IN) unit number 4499 * port - (IN) port number or GPORT identifier 4500 * cosq - (IN) COS queue number 4501 * flags - (IN) BCM_COSQ_DISCARD_XXX 4502 * min_thresh - (IN) 4503 * max_thresh - (IN) 4504 * drop_probablity - (IN) 4505 * gain - (IN) 4506 * ignore_enable_flags - (IN) 4507 * Returns: 4508 * BCM_E_XXX 4509 * Notes: 4510 * If port is any form of local port, cosq is the hardware queue index. 4511 */ 4512 STATIC int 4513 _bcm_kt_cosq_wred_set(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 4514 uint32 flags, uint32 min_thresh, uint32 max_thresh, 4515 int drop_probability, int gain, int ignore_enable_flags) 4516 { 4517 soc_reg_t reg = 0; 4518 soc_field_t field; 4519 uint32 rval = 0; 4520 bcm_port_t local_port; 4521 int index; 4522 uint32 profile_index, old_profile_index, partner_index; 4523 mmu_wred_drop_curve_profile_0_entry_t entry_tcp_green; 4524 mmu_wred_drop_curve_profile_1_entry_t entry_tcp_yellow; 4525 mmu_wred_drop_curve_profile_2_entry_t entry_tcp_red; 4526 mmu_wred_drop_curve_profile_3_entry_t entry_nontcp_green; 4527 mmu_wred_drop_curve_profile_4_entry_t entry_nontcp_yellow; 4528 mmu_wred_drop_curve_profile_5_entry_t entry_nontcp_red; 4529 void *entries[6]; 4530 soc_mem_t mems[6]; 4531 _bcm_kt_cosq_node_t *node; 4532 soc_mem_t wred_mem = MMU_WRED_QUEUE_CONFIG_BUFFERm; 4533 soc_mem_t partner_mem = MMU_WRED_QUEUE_CONFIG_QENTRYm; 4534 mmu_wred_queue_config_buffer_entry_t qentry, entry; 4535 int rate, i; 4536 int wred_enabled = 0; 4537 int ext_mem_port_count = 0; 4538 4539 reg = WRED_CONFIGr; 4540 if (flags & BCM_COSQ_DISCARD_DEVICE) { 4541 /* For port -1 , set global wred discard profile for all ports */ 4542 if ((port == -1) || (flags & BCM_COSQ_DISCARD_PACKETS)) { 4543 reg = GLOBAL_WRED_CONFIG_QENTRYr; 4544 field = WRED_ENABLEf; 4545 local_port = 0; 4546 index = 0; /* mmu init code uses service pool 0 only */ 4547 } else { 4548 return BCM_E_PARAM; 4549 } 4550 } else { 4551 if (cosq == -1) { 4552 return BCM_E_PARAM; 4553 } 4554 BCM_IF_ERROR_RETURN 4555 (_bcm_kt_cosq_index_resolve(unit, port, cosq, 4556 _BCM_KT_COSQ_INDEX_STYLE_WRED, 4557 &local_port, &index, NULL)); 4558 /* WRED doesn't work on CPU/LB Ports */ 4559 if (IS_LB_PORT(unit, local_port) || IS_CPU_PORT(unit, local_port)) { 4560 return BCM_E_PORT; 4561 } 4562 4563 if (flags & BCM_COSQ_DISCARD_PACKETS) { 4564 wred_mem = MMU_WRED_QUEUE_CONFIG_QENTRYm; 4565 partner_mem = MMU_WRED_QUEUE_CONFIG_BUFFERm; 4566 } 4567 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 4568 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port) || 4569 BCM_GPORT_IS_SCHEDULER(port)) { 4570 BCM_IF_ERROR_RETURN 4571 (_bcm_kt_cosq_node_get(unit, port, NULL, &local_port, NULL, 4572 &node)); 4573 4574 if (node->level == _BCM_KT_COSQ_NODE_LEVEL_L1) { 4575 wred_mem = (flags & BCM_COSQ_DISCARD_PACKETS) ? 4576 MMU_WRED_OPN_CONFIG_QENTRYm : 4577 MMU_WRED_OPN_CONFIG_BUFFERm; 4578 partner_mem = (flags & BCM_COSQ_DISCARD_PACKETS) ? 4579 MMU_WRED_OPN_CONFIG_BUFFERm : 4580 MMU_WRED_OPN_CONFIG_QENTRYm; 4581 } 4582 } 4583 field = WRED_ENf; 4584 } 4585 4586 old_profile_index = 0xffffffff; 4587 profile_index = 0xffffffff; 4588 if (reg == GLOBAL_WRED_CONFIG_QENTRYr) { 4589 BCM_IF_ERROR_RETURN(soc_reg32_get(unit, reg, local_port, index, &rval)); 4590 } else { 4591 SOC_IF_ERROR_RETURN 4592 (soc_mem_read(unit, wred_mem, MEM_BLOCK_ALL, 4593 index, &qentry)); 4594 } 4595 if (flags & (BCM_COSQ_DISCARD_NONTCP | BCM_COSQ_DISCARD_COLOR_ALL)) { 4596 if (reg == GLOBAL_WRED_CONFIG_QENTRYr) { 4597 old_profile_index = soc_reg_field_get(unit, reg, rval, PROFILE_INDEXf); 4598 } else { 4599 old_profile_index = soc_mem_field32_get(unit, wred_mem, 4600 &qentry, PROFILE_INDEXf); 4601 } 4602 entries[0] = &entry_tcp_green; 4603 entries[1] = &entry_tcp_yellow; 4604 entries[2] = &entry_tcp_red; 4605 entries[3] = &entry_nontcp_green; 4606 entries[4] = &entry_nontcp_yellow; 4607 entries[5] = &entry_nontcp_red; 4608 BCM_IF_ERROR_RETURN 4609 (soc_profile_mem_get(unit, _bcm_kt_wred_profile[unit], 4610 old_profile_index, 1, entries)); 4611 for (i = 0; i < 6; i++) { 4612 mems[i] = INVALIDm; 4613 } 4614 if (!(flags & BCM_COSQ_DISCARD_NONTCP)) { 4615 if (flags & BCM_COSQ_DISCARD_COLOR_GREEN) { 4616 mems[0] = MMU_WRED_DROP_CURVE_PROFILE_0m; 4617 } 4618 if (flags & BCM_COSQ_DISCARD_COLOR_YELLOW) { 4619 mems[1] = MMU_WRED_DROP_CURVE_PROFILE_1m; 4620 } 4621 if (flags & BCM_COSQ_DISCARD_COLOR_RED) { 4622 mems[2] = MMU_WRED_DROP_CURVE_PROFILE_2m; 4623 } 4624 } else if (!(flags & (BCM_COSQ_DISCARD_COLOR_GREEN | 4625 BCM_COSQ_DISCARD_COLOR_YELLOW | 4626 BCM_COSQ_DISCARD_COLOR_RED))) { 4627 mems[3] = MMU_WRED_DROP_CURVE_PROFILE_3m; 4628 mems[4] = MMU_WRED_DROP_CURVE_PROFILE_4m; 4629 mems[5] = MMU_WRED_DROP_CURVE_PROFILE_5m; 4630 4631 } else { 4632 if (flags & BCM_COSQ_DISCARD_COLOR_GREEN) { 4633 mems[3] = MMU_WRED_DROP_CURVE_PROFILE_3m; 4634 } 4635 if (flags & BCM_COSQ_DISCARD_COLOR_YELLOW) { 4636 mems[4] = MMU_WRED_DROP_CURVE_PROFILE_4m; 4637 } 4638 if (flags & BCM_COSQ_DISCARD_COLOR_RED) { 4639 mems[5] = MMU_WRED_DROP_CURVE_PROFILE_5m; 4640 } 4641 } 4642 rate = _bcm_kt_percent_to_drop_prob(drop_probability); 4643 for (i = 0; i < 6; i++) { 4644 if (mems[i] == INVALIDm) { 4645 continue; 4646 } 4647 soc_mem_field32_set(unit, mems[i], entries[i], MIN_THDf, 4648 min_thresh); 4649 soc_mem_field32_set(unit, mems[i], entries[i], MAX_THDf, 4650 max_thresh); 4651 soc_mem_field32_set(unit, mems[i], entries[i], MAX_DROP_RATEf, 4652 rate); 4653 } 4654 BCM_IF_ERROR_RETURN 4655 (soc_profile_mem_add(unit, _bcm_kt_wred_profile[unit], entries, 1, 4656 &profile_index)); 4657 if (reg == GLOBAL_WRED_CONFIG_QENTRYr) { 4658 soc_reg_field_set(unit, reg, &rval, PROFILE_INDEXf, profile_index); 4659 soc_reg_field_set(unit, reg, &rval, WEIGHTf, gain); 4660 } else { 4661 soc_mem_field32_set(unit, wred_mem, &qentry, PROFILE_INDEXf, profile_index); 4662 soc_mem_field32_set(unit, wred_mem, &qentry, WEIGHTf, gain); 4663 } 4664 } 4665 4666 /* Some APIs only modify profiles */ 4667 if (!ignore_enable_flags) { 4668 if ( reg == GLOBAL_WRED_CONFIG_QENTRYr) { 4669 soc_reg_field_set(unit, reg, &rval, CAP_AVERAGEf, 4670 flags & BCM_COSQ_DISCARD_CAP_AVERAGE ? 1 : 0); 4671 soc_reg_field_set(unit, reg, &rval, field, 4672 flags & BCM_COSQ_DISCARD_ENABLE ? 1 : 0); 4673 } else { 4674 soc_mem_field32_set(unit, wred_mem, &qentry, CAP_AVERAGEf, 4675 flags & BCM_COSQ_DISCARD_CAP_AVERAGE ? 1 : 0); 4676 soc_mem_field32_set(unit, wred_mem, &qentry, field, 4677 flags & BCM_COSQ_DISCARD_ENABLE ? 1 : 0); 4678 if (wred_mem == MMU_WRED_QUEUE_CONFIG_BUFFERm || 4679 wred_mem == MMU_WRED_QUEUE_CONFIG_QENTRYm) { 4680 /* ECN marking is applicable only for queues */ 4681 soc_mem_field32_set(unit, wred_mem, &qentry, ECN_MARKING_ENf, 4682 flags & BCM_COSQ_DISCARD_MARK_CONGESTION ? 4683 1 : 0); 4684 if (wred_mem == MMU_WRED_QUEUE_CONFIG_QENTRYm) { 4685 /* ECN marking needs to be enabled in BUFFER entry */ 4686 SOC_IF_ERROR_RETURN 4687 (soc_mem_read(unit, MMU_WRED_QUEUE_CONFIG_BUFFERm, 4688 MEM_BLOCK_ALL, index, &entry)); 4689 soc_mem_field32_set(unit, MMU_WRED_QUEUE_CONFIG_BUFFERm, 4690 &entry, ECN_MARKING_ENf, 4691 flags & BCM_COSQ_DISCARD_MARK_CONGESTION ? 4692 1 : 0); 4693 SOC_IF_ERROR_RETURN 4694 (soc_mem_write(unit, MMU_WRED_QUEUE_CONFIG_BUFFERm, 4695 MEM_BLOCK_ALL, index, &entry)); 4696 } 4697 } 4698 } 4699 } 4700 4701 partner_index = 0xffffffff; 4702 if (reg == GLOBAL_WRED_CONFIG_QENTRYr) { 4703 BCM_IF_ERROR_RETURN(soc_reg32_set(unit, reg, local_port, index, rval)); 4704 4705 /* update interna/external buffer entries based on port configuration */ 4706 BCM_IF_ERROR_RETURN(soc_reg32_get(unit, GLOBAL_WRED_CONFIG_BUFFERIr, 4707 local_port, index, &rval)); 4708 soc_reg_field_set(unit, GLOBAL_WRED_CONFIG_BUFFERIr, &rval, field, 4709 flags & BCM_COSQ_DISCARD_ENABLE ? 1 : 0); 4710 soc_reg_field_set(unit, GLOBAL_WRED_CONFIG_BUFFERIr, &rval, 4711 PROFILE_INDEXf, 0); 4712 BCM_IF_ERROR_RETURN(soc_reg32_set(unit, GLOBAL_WRED_CONFIG_BUFFERIr, 4713 local_port, index, rval)); 4714 BCM_PBMP_COUNT(PBMP_EXT_MEM (unit), ext_mem_port_count); 4715 if (ext_mem_port_count > 0) { 4716 BCM_IF_ERROR_RETURN(soc_reg32_get(unit, GLOBAL_WRED_CONFIG_BUFFEREr, 4717 local_port, index, &rval)); 4718 soc_reg_field_set(unit, GLOBAL_WRED_CONFIG_BUFFEREr, &rval, field, 4719 flags & BCM_COSQ_DISCARD_ENABLE ? 1 : 0); 4720 soc_reg_field_set(unit, GLOBAL_WRED_CONFIG_BUFFEREr, &rval, 4721 PROFILE_INDEXf, 0); 4722 BCM_IF_ERROR_RETURN(soc_reg32_set(unit, GLOBAL_WRED_CONFIG_BUFFEREr, 4723 local_port, index, rval)); 4724 } 4725 } else { 4726 SOC_IF_ERROR_RETURN 4727 (soc_mem_write(unit, wred_mem, MEM_BLOCK_ALL, 4728 index, &qentry)); 4729 SOC_IF_ERROR_RETURN 4730 (soc_mem_read(unit, partner_mem, MEM_BLOCK_ALL, 4731 index, &qentry)); 4732 wred_enabled = soc_mem_field32_get(unit, partner_mem, 4733 &qentry, WRED_ENf); 4734 4735 /* if buffer/qentry_mem WRED enabled, make sure the partner_mem (qentry/buffer_mem) 4736 * also WRED enabled. 4737 * if buffer/qentry_mem WRED disabled, make sure the partner_mem (qentry/buffer_mem) 4738 * also WRED disabled. 4739 */ 4740 if (((flags & BCM_COSQ_DISCARD_ENABLE) && (wred_enabled == 0)) || 4741 (!(flags & BCM_COSQ_DISCARD_ENABLE) && (wred_enabled == 1))) { 4742 partner_index = soc_mem_field32_get(unit, partner_mem, 4743 &qentry, PROFILE_INDEXf); 4744 soc_mem_field32_set(unit, partner_mem, &qentry, PROFILE_INDEXf, 0); 4745 soc_mem_field32_set(unit, partner_mem, &qentry, WRED_ENf, 4746 flags & BCM_COSQ_DISCARD_ENABLE ? 1 : 0); 4747 SOC_IF_ERROR_RETURN 4748 (soc_mem_write(unit, partner_mem, MEM_BLOCK_ALL, 4749 index, &qentry)); 4750 } 4751 } 4752 4753 /* Replacing old profiles with new global profiles when wred discard 4754 profile is set for all ports */ 4755 4756 if ((port == -1) && (flags & BCM_COSQ_DISCARD_DEVICE) && 4757 (profile_index != 0xffffffff)) { 4758 for (i = 1; i < SOC_REG_NUMELS(unit, reg); i++) { 4759 BCM_IF_ERROR_RETURN(soc_profile_mem_add(unit, 4760 _bcm_kt_wred_profile[unit], entries, 1, 4761 &profile_index)); 4762 BCM_IF_ERROR_RETURN(soc_reg32_set(unit, reg, local_port, i, rval)); 4763 } 4764 } 4765 4766 if (old_profile_index != 0xffffffff && old_profile_index > 0) { 4767 BCM_IF_ERROR_RETURN 4768 (soc_profile_mem_delete(unit, _bcm_kt_wred_profile[unit], 4769 old_profile_index)); 4770 if((port==-1) && (flags & BCM_COSQ_DISCARD_DEVICE)) { 4771 for(i = 1; i < SOC_REG_NUMELS(unit, reg); i++) { 4772 BCM_IF_ERROR_RETURN(soc_profile_mem_delete(unit, 4773 _bcm_kt_wred_profile[unit], 4774 old_profile_index)); 4775 } 4776 } 4777 } 4778 4779 if (partner_index != 0xffffffff && partner_index > 0) { 4780 BCM_IF_ERROR_RETURN 4781 (soc_profile_mem_delete(unit, _bcm_kt_wred_profile[unit], 4782 partner_index)); 4783 } 4784 4785 return BCM_E_NONE; 4786 } 4787 4788 /* 4789 * Function: 4790 * _bcm_kt_cosq_wred_get 4791 * Purpose: 4792 * Get unicast queue WRED setting 4793 * Parameters: 4794 * unit - (IN) unit number 4795 * port - (IN) port number or GPORT identifier 4796 * cosq - (IN) COS queue number 4797 * flags - (IN/OUT) BCM_COSQ_DISCARD_XXX 4798 * min_thresh - (OUT) 4799 * max_thresh - (OUT) 4800 * drop_probablity - (OUT) 4801 * gain - (OUT) 4802 * Returns: 4803 * BCM_E_XXX 4804 * Notes: 4805 * If port is any form of local port, cosq is the hardware queue index. 4806 */ 4807 STATIC int 4808 _bcm_kt_cosq_wred_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 4809 uint32 *flags, uint32 *min_thresh, uint32 *max_thresh, 4810 int *drop_probability, int *gain) 4811 { 4812 soc_reg_t reg = 0; 4813 soc_field_t field; 4814 uint32 rval; 4815 bcm_port_t local_port; 4816 int index, profile_index; 4817 mmu_wred_drop_curve_profile_0_entry_t entry_tcp_green; 4818 mmu_wred_drop_curve_profile_1_entry_t entry_tcp_yellow; 4819 mmu_wred_drop_curve_profile_2_entry_t entry_tcp_red; 4820 mmu_wred_drop_curve_profile_3_entry_t entry_nontcp_green; 4821 mmu_wred_drop_curve_profile_4_entry_t entry_nontcp_yellow; 4822 mmu_wred_drop_curve_profile_5_entry_t entry_nontcp_red; 4823 void *entries[6]; 4824 void *entry_p; 4825 soc_mem_t mem; 4826 _bcm_kt_cosq_node_t *node; 4827 soc_mem_t wred_mem = MMU_WRED_QUEUE_CONFIG_BUFFERm; 4828 mmu_wred_queue_config_buffer_entry_t qentry; 4829 int rate; 4830 4831 if (*flags & BCM_COSQ_DISCARD_DEVICE) { 4832 if ((port == -1) || (*flags & BCM_COSQ_DISCARD_PACKETS)) { 4833 reg = GLOBAL_WRED_CONFIG_QENTRYr; 4834 field = WRED_ENABLEf; 4835 local_port = 0; 4836 index = 0; /* mmu init code uses service pool 0 only */ 4837 wred_mem = 0; 4838 } else { 4839 return BCM_E_PARAM; 4840 } 4841 } else { 4842 if (cosq == -1) { 4843 return BCM_E_PARAM; 4844 } 4845 BCM_IF_ERROR_RETURN 4846 (_bcm_kt_cosq_index_resolve(unit, port, cosq, 4847 _BCM_KT_COSQ_INDEX_STYLE_WRED, 4848 &local_port, &index, NULL)); 4849 /* WRED doesn't work on CPU/LB Ports */ 4850 if (IS_LB_PORT(unit, local_port) || IS_CPU_PORT(unit, local_port)) { 4851 return BCM_E_PORT; 4852 } 4853 if (*flags & BCM_COSQ_DISCARD_PACKETS) { 4854 wred_mem = MMU_WRED_QUEUE_CONFIG_QENTRYm; 4855 } 4856 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 4857 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port) || 4858 BCM_GPORT_IS_SCHEDULER(port)) { 4859 BCM_IF_ERROR_RETURN 4860 (_bcm_kt_cosq_node_get(unit, port, NULL, &local_port, NULL, 4861 &node)); 4862 if (node->level == _BCM_KT_COSQ_NODE_LEVEL_L1) { 4863 wred_mem = (*flags & BCM_COSQ_DISCARD_PACKETS) ? 4864 MMU_WRED_OPN_CONFIG_QENTRYm : 4865 MMU_WRED_OPN_CONFIG_BUFFERm; 4866 } 4867 } 4868 4869 field = WRED_ENf; 4870 } 4871 4872 if (reg == GLOBAL_WRED_CONFIG_QENTRYr) { 4873 BCM_IF_ERROR_RETURN(soc_reg32_get(unit, reg, local_port, index, &rval)); 4874 profile_index = soc_reg_field_get(unit, reg, rval, PROFILE_INDEXf); 4875 } else { 4876 SOC_IF_ERROR_RETURN 4877 (soc_mem_read(unit, wred_mem, MEM_BLOCK_ALL, 4878 index, &qentry)); 4879 profile_index = soc_mem_field32_get(unit, wred_mem, 4880 &qentry, PROFILE_INDEXf); 4881 } 4882 4883 if (!(*flags & BCM_COSQ_DISCARD_NONTCP)) { 4884 if (*flags & BCM_COSQ_DISCARD_COLOR_GREEN) { 4885 mem = MMU_WRED_DROP_CURVE_PROFILE_0m; 4886 entry_p = &entry_tcp_green; 4887 } else if (*flags & BCM_COSQ_DISCARD_COLOR_YELLOW) { 4888 mem = MMU_WRED_DROP_CURVE_PROFILE_1m; 4889 entry_p = &entry_tcp_yellow; 4890 } else if (*flags & BCM_COSQ_DISCARD_COLOR_RED) { 4891 mem = MMU_WRED_DROP_CURVE_PROFILE_2m; 4892 entry_p = &entry_tcp_red; 4893 } else { 4894 mem = MMU_WRED_DROP_CURVE_PROFILE_0m; 4895 entry_p = &entry_tcp_green; 4896 } 4897 } else { 4898 if (*flags & BCM_COSQ_DISCARD_COLOR_GREEN) { 4899 mem = MMU_WRED_DROP_CURVE_PROFILE_3m; 4900 entry_p = &entry_nontcp_green; 4901 } else if (*flags & BCM_COSQ_DISCARD_COLOR_YELLOW) { 4902 mem = MMU_WRED_DROP_CURVE_PROFILE_4m; 4903 entry_p = &entry_nontcp_yellow; 4904 } else if (*flags & BCM_COSQ_DISCARD_COLOR_RED) { 4905 mem = MMU_WRED_DROP_CURVE_PROFILE_5m; 4906 entry_p = &entry_nontcp_red; 4907 } else { 4908 mem = MMU_WRED_DROP_CURVE_PROFILE_3m; 4909 entry_p = &entry_nontcp_green; 4910 } 4911 } 4912 entries[0] = &entry_tcp_green; 4913 entries[1] = &entry_tcp_yellow; 4914 entries[2] = &entry_tcp_red; 4915 entries[3] = &entry_nontcp_green; 4916 entries[4] = &entry_nontcp_yellow; 4917 entries[5] = &entry_nontcp_red; 4918 BCM_IF_ERROR_RETURN 4919 (soc_profile_mem_get(unit, _bcm_kt_wred_profile[unit], 4920 profile_index, 1, entries)); 4921 if (min_thresh != NULL) { 4922 *min_thresh = soc_mem_field32_get(unit, mem, entry_p, MIN_THDf); 4923 } 4924 if (max_thresh != NULL) { 4925 *max_thresh = soc_mem_field32_get(unit, mem, entry_p, MAX_THDf); 4926 } 4927 if (drop_probability != NULL) { 4928 rate = soc_mem_field32_get(unit, mem, entry_p, MAX_DROP_RATEf); 4929 *drop_probability = _bcm_kt_drop_prob_to_percent(rate); 4930 } 4931 4932 if (gain != NULL && reg == GLOBAL_WRED_CONFIG_QENTRYr) { 4933 *gain = soc_reg_field_get(unit, reg, rval, WEIGHTf); 4934 } 4935 if (gain != NULL && wred_mem != 0) { 4936 *gain = soc_mem_field32_get(unit, wred_mem, &qentry, WEIGHTf); 4937 } 4938 4939 *flags &= ~(BCM_COSQ_DISCARD_CAP_AVERAGE | BCM_COSQ_DISCARD_ENABLE); 4940 if ((reg == GLOBAL_WRED_CONFIG_QENTRYr) && 4941 soc_reg_field_get(unit, reg, rval, CAP_AVERAGEf)) { 4942 *flags |= BCM_COSQ_DISCARD_CAP_AVERAGE; 4943 } 4944 if ((wred_mem != 0) && 4945 soc_mem_field32_get(unit, wred_mem, &qentry, CAP_AVERAGEf)) { 4946 *flags |= BCM_COSQ_DISCARD_CAP_AVERAGE; 4947 } 4948 4949 if ((reg == GLOBAL_WRED_CONFIG_QENTRYr) && 4950 soc_reg_field_get(unit, reg, rval, field)) { 4951 *flags |= BCM_COSQ_DISCARD_ENABLE; 4952 } 4953 if ((wred_mem != 0) && 4954 soc_mem_field32_get(unit, wred_mem, &qentry, field)) { 4955 *flags |= BCM_COSQ_DISCARD_ENABLE; 4956 } 4957 4958 if (wred_mem == MMU_WRED_QUEUE_CONFIG_BUFFERm || 4959 wred_mem == MMU_WRED_QUEUE_CONFIG_QENTRYm) { 4960 if (soc_mem_field32_get(unit, wred_mem, &qentry, ECN_MARKING_ENf)) { 4961 *flags |= BCM_COSQ_DISCARD_MARK_CONGESTION; 4962 } 4963 } 4964 4965 return BCM_E_NONE; 4966 } 4967 4968 STATIC int 4969 _bcm_kt_cosq_dynamic_hierarchy_create(int unit, bcm_gport_t port, int numq) 4970 { 4971 bcm_gport_t port_sched, l0_sched, l1_sched[16]; 4972 bcm_gport_t queue; 4973 int i, encap_id; 4974 _bcm_kt_mmu_info_t *mmu_info; 4975 4976 BCM_IF_ERROR_RETURN 4977 (bcm_kt_cosq_gport_add(unit, port, 1, 0, &port_sched)); 4978 4979 /* coverity[uninit_use_in_call] */ 4980 BCM_IF_ERROR_RETURN 4981 (bcm_kt_cosq_gport_add(unit, port, 16, BCM_COSQ_GPORT_SCHEDULER, 4982 &l0_sched)); 4983 BCM_IF_ERROR_RETURN 4984 (bcm_kt_cosq_gport_attach(unit, l0_sched, port_sched, 0)); 4985 4986 for (i = 0; i < (2 * numq); i++) { 4987 BCM_IF_ERROR_RETURN 4988 (bcm_kt_cosq_gport_add(unit, port, 1, BCM_COSQ_GPORT_SCHEDULER, 4989 &l1_sched[i])); 4990 BCM_IF_ERROR_RETURN 4991 (bcm_kt_cosq_gport_attach(unit, l1_sched[i], l0_sched, i)); 4992 } 4993 4994 mmu_info = _bcm_kt_mmu_info[unit]; 4995 4996 for (i = 0; i < numq; i++) { 4997 BCM_IF_ERROR_RETURN 4998 (bcm_kt_cosq_gport_add(unit, port, 1, 4999 BCM_COSQ_GPORT_UCAST_QUEUE_GROUP, &queue)); 5000 BCM_IF_ERROR_RETURN 5001 (bcm_kt_cosq_gport_attach(unit, queue, l1_sched[i], 0)); 5002 encap_id = (BCM_GPORT_SCHEDULER_GET(l1_sched[i]) >> 8) & 0x7ff; 5003 mmu_info->l1_gport_pair[encap_id] = l1_sched[i + numq]; 5004 encap_id = (BCM_GPORT_SCHEDULER_GET(l1_sched[i + numq]) >> 8) & 0x7ff; 5005 mmu_info->l1_gport_pair[encap_id] = l1_sched[i]; 5006 } 5007 5008 return 0; 5009 } 5010 5011 STATIC int 5012 _bcm_kt_cosq_gport_delete_all(int unit, bcm_gport_t gport, int *rv) 5013 { 5014 _bcm_kt_cosq_node_t *node; 5015 _bcm_kt_mmu_info_t *mmu_info; 5016 int encap_id; 5017 int local_port; 5018 5019 BCM_IF_ERROR_RETURN 5020 (_bcm_kt_cosq_node_get(unit, gport, NULL, NULL, NULL, &node)); 5021 5022 if (node->child != NULL) { 5023 _bcm_kt_cosq_gport_delete_all(unit, node->child->gport, rv); 5024 BCM_IF_ERROR_RETURN(*rv); 5025 } 5026 5027 if (node->sibling != NULL) { 5028 _bcm_kt_cosq_gport_delete_all(unit, node->sibling->gport, rv); 5029 BCM_IF_ERROR_RETURN(*rv); 5030 } 5031 5032 if (node->level != _BCM_KT_COSQ_NODE_LEVEL_ROOT && node->cosq_attached_to >= 0) { 5033 *rv = bcm_kt_cosq_gport_detach(unit, node->gport, node->parent->gport, 5034 node->cosq_attached_to); 5035 BCM_IF_ERROR_RETURN(*rv); 5036 } 5037 5038 mmu_info = _bcm_kt_mmu_info[unit]; 5039 5040 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { /* unicast queue group */ 5041 encap_id = BCM_GPORT_UCAST_QUEUE_GROUP_QID_GET(gport); 5042 } else if (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport)) { 5043 /* subscriber queue group */ 5044 encap_id = BCM_GPORT_UCAST_SUBSCRIBER_QUEUE_GROUP_QID_GET(gport); 5045 if (mmu_info->num_sub_queues > 0) { 5046 _bcm_kt_node_index_clear(&mmu_info->sub_qlist, 5047 encap_id , 1); 5048 } else { 5049 5050 _bcm_kt_node_index_clear(&mmu_info->ext_qlist, 5051 encap_id, 1); 5052 } 5053 } else { 5054 if (BCM_GPORT_IS_SCHEDULER(gport)) { 5055 /* scheduler node */ 5056 encap_id = (BCM_GPORT_SCHEDULER_GET(gport) >> 8) & 0x7ff; 5057 5058 if (encap_id == 0) { 5059 encap_id = (BCM_GPORT_SCHEDULER_GET(gport) & 0xff); 5060 } 5061 } else if ((BCM_GPORT_IS_LOCAL(gport)) || (BCM_GPORT_IS_MODPORT(gport))) { 5062 BCM_IF_ERROR_RETURN 5063 (_bcm_kt_cosq_localport_resolve(unit, gport, &local_port)); 5064 if (local_port < 0) { 5065 return BCM_E_PORT; 5066 } 5067 encap_id = local_port; 5068 } else { 5069 return BCM_E_PARAM; 5070 } 5071 5072 _bcm_kt_node_index_clear(&mmu_info->sched_list, encap_id, 1); 5073 5074 } 5075 5076 if (node->cosq_map != NULL) { 5077 sal_free(node->cosq_map); 5078 } 5079 5080 _BCM_KT_COSQ_NODE_INIT(node); 5081 5082 return BCM_E_NONE; 5083 } 5084 5085 /* 5086 * Function: 5087 * _bcm_kt_intf_ref_cnt_increment 5088 * Purpose: 5089 * Increase interface reference count for queue id 5090 * Parameters: 5091 * unit - (IN) unit number 5092 * queue_id - (IN) HW queue id 5093 * count - (IN) Interface count 5094 * Returns: 5095 * BCM_E_XXX 5096 */ 5097 5098 int 5099 _bcm_kt_intf_ref_cnt_increment(int unit, uint32 queue_id, int count) 5100 { 5101 _bcm_kt_mmu_info_t *mmu_info; 5102 5103 if (_bcm_kt_mmu_info[unit] == NULL) { 5104 return BCM_E_INIT; 5105 } 5106 5107 mmu_info = _bcm_kt_mmu_info[unit]; 5108 mmu_info->intf_ref_cnt[queue_id] = mmu_info->intf_ref_cnt[queue_id] 5109 + count; 5110 return BCM_E_NONE; 5111 } 5112 5113 /* 5114 * Function: 5115 * _bcm_kt_intf_ref_cnt_decrement 5116 * Purpose: 5117 * Decrease interface reference count for queue id 5118 * Parameters: 5119 * unit - (IN) unit number 5120 * queue_id - (IN) HW queue id 5121 * count - (IN) Interface count 5122 * Returns: 5123 * BCM_E_XXX 5124 */ 5125 5126 int 5127 _bcm_kt_intf_ref_cnt_decrement(int unit, uint32 queue_id, int count) 5128 { 5129 _bcm_kt_mmu_info_t *mmu_info; 5130 5131 if (_bcm_kt_mmu_info[unit] == NULL) { 5132 return BCM_E_INIT; 5133 } 5134 5135 mmu_info = _bcm_kt_mmu_info[unit]; 5136 if (mmu_info->intf_ref_cnt[queue_id] > 0) { 5137 mmu_info->intf_ref_cnt[queue_id] = mmu_info->intf_ref_cnt[queue_id] 5138 - count; 5139 } else { 5140 return BCM_E_PARAM; 5141 } 5142 return BCM_E_NONE; 5143 } 5144 5145 /* 5146 * Function: 5147 * bcm_kt_cosq_gport_add 5148 * Purpose: 5149 * Create a cosq gport structure 5150 * Parameters: 5151 * unit - (IN) unit number 5152 * port - (IN) port number 5153 * numq - (IN) number of COS queues 5154 * flags - (IN) flags (BCM_COSQ_GPORT_XXX) 5155 * gport - (OUT) GPORT identifier 5156 * Returns: 5157 * BCM_E_XXX 5158 */ 5159 int 5160 bcm_kt_cosq_gport_add(int unit, bcm_gport_t port, int numq, uint32 flags, 5161 bcm_gport_t *gport) 5162 { 5163 soc_info_t *si; 5164 _bcm_kt_mmu_info_t *mmu_info; 5165 _bcm_kt_cosq_port_info_t *port_info; 5166 _bcm_kt_cosq_node_t *node = NULL; 5167 bcm_port_t local_port; 5168 int id, max_nodes; 5169 uint32 sched_encap; 5170 _bcm_kt_cosq_list_t *list; 5171 int max_queues; 5172 5173 LOG_INFO(BSL_LS_BCM_COSQ, 5174 (BSL_META_U(unit, 5175 "bcm_kt_cosq_gport_add: unit=%d port=0x%x numq=%d flags=0x%x\n"), 5176 unit, port, numq, flags)); 5177 5178 if (gport == NULL) { 5179 return BCM_E_PARAM; 5180 } 5181 5182 si = &SOC_INFO(unit); 5183 5184 if (_bcm_kt_mmu_info[unit] == NULL) { 5185 return BCM_E_INIT; 5186 } 5187 5188 BCM_IF_ERROR_RETURN 5189 (_bcm_kt_cosq_localport_resolve(unit, port, &local_port)); 5190 5191 if (local_port < 0) { 5192 return BCM_E_PORT; 5193 } 5194 5195 mmu_info = _bcm_kt_mmu_info[unit]; 5196 switch (flags) { 5197 case BCM_COSQ_GPORT_UCAST_QUEUE_GROUP: 5198 case BCM_COSQ_GPORT_VLAN_UCAST_QUEUE_GROUP: 5199 if (numq != 1) { 5200 return BCM_E_PARAM; 5201 } 5202 5203 if ((flags == BCM_COSQ_GPORT_VLAN_UCAST_QUEUE_GROUP) && 5204 (si->port_num_ext_cosq[local_port] == 0)) { 5205 return BCM_E_PARAM; 5206 } 5207 5208 port_info = &mmu_info->port[local_port]; 5209 5210 for (id = port_info->q_offset; id < port_info->q_limit; id++) { 5211 if (mmu_info->queue_node[id].numq == 0) { 5212 break; 5213 } 5214 } 5215 5216 if (id == port_info->q_limit) { 5217 return BCM_E_RESOURCE; 5218 } 5219 5220 BCM_GPORT_UCAST_QUEUE_GROUP_SYSQID_SET(*gport, local_port, id); 5221 node = &mmu_info->queue_node[id]; 5222 node->gport = *gport; 5223 node->numq = numq; 5224 break; 5225 5226 case BCM_COSQ_GPORT_SUBSCRIBER: 5227 if (numq != 1) { 5228 return BCM_E_PARAM; 5229 } 5230 /* chcek for pre allocated subscriber queues */ 5231 if (mmu_info->num_sub_queues == 0) { 5232 list = &mmu_info->ext_qlist; 5233 max_queues = mmu_info->num_ext_queues; 5234 } else { 5235 list = &mmu_info->sub_qlist; 5236 max_queues = mmu_info->num_sub_queues; 5237 } 5238 BCM_IF_ERROR_RETURN 5239 (_bcm_kt_node_index_get(unit, list->bits, 0, max_queues, 5240 mmu_info->qset_size, 1, &id)); 5241 _bcm_kt_node_index_set(list, id, 1); 5242 BCM_GPORT_UCAST_SUBSCRIBER_QUEUE_GROUP_SYSQID_SET(*gport, 5243 local_port, id); 5244 if (mmu_info->num_sub_queues == 0) { 5245 id += mmu_info->num_base_queues; 5246 } else { 5247 id += mmu_info->base_sub_queue; 5248 } 5249 node = &mmu_info->queue_node[id]; 5250 node->gport = *gport; 5251 node->numq = numq; 5252 break; 5253 5254 case (BCM_COSQ_GPORT_WITH_ID | BCM_COSQ_GPORT_SUBSCRIBER): 5255 if (numq != 1) { 5256 return BCM_E_PARAM; 5257 } 5258 5259 if (BCM_GPORT_UCAST_SUBSCRIBER_QUEUE_GROUP_SYSPORTID_GET(*gport) 5260 != local_port) { 5261 return BCM_E_PARAM; 5262 } 5263 5264 id = BCM_GPORT_UCAST_SUBSCRIBER_QUEUE_GROUP_QID_GET(*gport); 5265 if ((id >= mmu_info->num_sub_queues) || 5266 (mmu_info->num_sub_queues == 0) || 5267 (mmu_info->intf_ref_cnt[id] != 0)) { 5268 return BCM_E_PARAM; 5269 } 5270 max_queues = mmu_info->num_sub_queues; 5271 5272 node = &mmu_info->queue_node[id + mmu_info->base_sub_queue]; 5273 if(node->numq != 0) { 5274 return BCM_E_EXISTS; 5275 } 5276 _bcm_kt_node_index_set(&mmu_info->sub_qlist, id, 1); 5277 _bcm_kt_node_index_set(&mmu_info->l2_sub_qlist, id, 1); 5278 5279 id += mmu_info->base_sub_queue; 5280 node->hw_index = id; 5281 node->gport = *gport; 5282 node->numq = numq; 5283 node->level = _BCM_KT_COSQ_NODE_LEVEL_L2; 5284 node->type = _BCM_KT_NODE_SUBSCRIBER_GPORT_ID; 5285 break; 5286 5287 case BCM_COSQ_GPORT_SCHEDULER: 5288 /* passthru */ 5289 case 0: 5290 /* 5291 * Can not validate actual number of cosq until attach time. 5292 * Maximum number of input is 8 for SP or WRR node 5293 * expect -1 if number of inputs are unknown at this stage(WRR only) 5294 */ 5295 if (numq == 0 || numq < -1) { 5296 return BCM_E_PARAM; 5297 } 5298 5299 if (flags == BCM_COSQ_GPORT_SCHEDULER) { 5300 BCM_IF_ERROR_RETURN 5301 (_bcm_kt_cosq_max_nodes_get(unit, _BCM_KT_COSQ_NODE_LEVEL_L2, 5302 &max_nodes)); 5303 } else { 5304 BCM_IF_ERROR_RETURN 5305 (_bcm_kt_cosq_max_nodes_get(unit, _BCM_KT_COSQ_NODE_LEVEL_L0, 5306 &max_nodes)); 5307 } 5308 if (numq > max_nodes) { 5309 return BCM_E_PARAM; 5310 } 5311 5312 if ( flags == 0) { 5313 /* this is a port level scheduler */ 5314 id = local_port; 5315 5316 if ( id < 0 || id >= _BCM_KT_NUM_PORT_SCHEDULERS) { 5317 return BCM_E_PARAM; 5318 } 5319 5320 _bcm_kt_node_index_set(&mmu_info->sched_list, id, 1); 5321 node = &mmu_info->sched_node[id]; 5322 sched_encap = (id << 8) | local_port; 5323 BCM_GPORT_SCHEDULER_SET(*gport, sched_encap); 5324 node->gport = *gport; 5325 node->level = _BCM_KT_COSQ_NODE_LEVEL_ROOT; 5326 node->hw_index = id; 5327 node->numq = numq; 5328 node->cosq_attached_to = 0; 5329 } else { 5330 /* allocate from sched_list, index will start from 36, 5331 * 0-35 is used for port(root) schedulers. */ 5332 BCM_IF_ERROR_RETURN 5333 (_bcm_kt_node_index_get(unit, mmu_info->sched_list.bits, 5334 _BCM_KT_NUM_PORT_SCHEDULERS, 5335 mmu_info->num_nodes, 1, 1, &id)); 5336 _bcm_kt_node_index_set(&mmu_info->sched_list, id, 1); 5337 node = &mmu_info->sched_node[id]; 5338 sched_encap = (id << 8) | local_port; 5339 BCM_GPORT_SCHEDULER_SET(*gport, sched_encap); 5340 node->gport = *gport; 5341 node->numq = numq; 5342 node->cosq_attached_to = -1; 5343 } 5344 break; 5345 5346 case BCM_COSQ_GPORT_WITH_ID: 5347 if (BCM_GPORT_IS_SCHEDULER(*gport)) { 5348 if (numq == 0 || numq < -1 || numq > 8) { 5349 return BCM_E_PARAM; 5350 } 5351 id = BCM_GPORT_SCHEDULER_GET(*gport); 5352 5353 if (id != local_port) { 5354 return BCM_E_PARAM; 5355 } 5356 5357 /* allow only port level scheduler with id */ 5358 if ( id < 0 || id >= _BCM_KT_NUM_PORT_SCHEDULERS) { 5359 return BCM_E_PARAM; 5360 } 5361 5362 _bcm_kt_node_index_set(&mmu_info->sched_list, id, 1); 5363 node = &mmu_info->sched_node[id]; 5364 node->gport = *gport; 5365 node->level = _BCM_KT_COSQ_NODE_LEVEL_ROOT; 5366 node->hw_index = id; 5367 node->numq = numq; 5368 node->cosq_attached_to = 0; 5369 } else if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(*gport)) { 5370 if (numq != 1) { 5371 return BCM_E_PARAM; 5372 } 5373 5374 if (BCM_GPORT_UCAST_QUEUE_GROUP_SYSPORTID_GET(*gport) != local_port) { 5375 return BCM_E_PARAM; 5376 } 5377 5378 id = BCM_GPORT_UCAST_QUEUE_GROUP_QID_GET(*gport); 5379 port_info = &mmu_info->port[local_port]; 5380 /* allow only base queues */ 5381 if (id < port_info->q_offset || id >= port_info->q_limit) { 5382 return BCM_E_PARAM; 5383 } 5384 5385 list = &mmu_info->l2_base_qlist; 5386 if (SHR_BITGET(list->bits, id) != 0) { 5387 return BCM_E_RESOURCE; 5388 } 5389 5390 node = &mmu_info->queue_node[id]; 5391 if (node->numq != 0) { 5392 return BCM_E_EXISTS; 5393 } 5394 5395 _bcm_kt_node_index_set(&mmu_info->l2_base_qlist, id, 1); 5396 node->hw_index = id; 5397 node->gport = *gport; 5398 node->numq = numq; 5399 } else { 5400 return BCM_E_PARAM; 5401 } 5402 break; 5403 5404 default: 5405 return BCM_E_PARAM; 5406 } 5407 5408 LOG_INFO(BSL_LS_BCM_COSQ, 5409 (BSL_META_U(unit, 5410 " gport=0x%x\n"), 5411 *gport)); 5412 5413 return BCM_E_NONE; 5414 } 5415 5416 /* 5417 * Function: 5418 * bcm_kt_cosq_gport_delete 5419 * Purpose: 5420 * Destroy a cosq gport structure 5421 * Parameters: 5422 * unit - (IN) unit number 5423 * gport - (IN) GPORT identifier 5424 * Returns: 5425 * BCM_E_XXX 5426 */ 5427 int 5428 bcm_kt_cosq_gport_delete(int unit, bcm_gport_t gport) 5429 { 5430 _bcm_kt_cosq_node_t *node; 5431 _bcm_kt_mmu_info_t *mmu_info; 5432 int encap_id; 5433 int rv = BCM_E_NONE; 5434 _bcm_kt_cosq_list_t *list; 5435 5436 LOG_INFO(BSL_LS_BCM_COSQ, 5437 (BSL_META_U(unit, 5438 "bcm_kt_cosq_gport_delete: unit=%d gport=0x%x\n"), 5439 unit, gport)); 5440 5441 if (_bcm_kt_mmu_info[unit] == NULL) { 5442 return BCM_E_INIT; 5443 } 5444 mmu_info = _bcm_kt_mmu_info[unit]; 5445 5446 BCM_IF_ERROR_RETURN 5447 (_bcm_kt_cosq_node_get(unit, gport, NULL, NULL, NULL, &node)); 5448 5449 if (node->gport < 0) { 5450 return BCM_E_NOT_FOUND; 5451 } 5452 5453 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 5454 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport)) { 5455 if (node->cosq_attached_to >= 0) { 5456 BCM_IF_ERROR_RETURN 5457 (bcm_kt_cosq_gport_detach(unit, gport, node->parent->gport, 5458 node->cosq_attached_to)); 5459 } 5460 if (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport)) { 5461 encap_id = BCM_GPORT_UCAST_SUBSCRIBER_QUEUE_GROUP_QID_GET(gport); 5462 if (mmu_info->num_sub_queues == 0) { 5463 list = &mmu_info->ext_qlist; 5464 } else { 5465 list = &mmu_info->sub_qlist; 5466 } 5467 _bcm_kt_node_index_clear(list, encap_id, 1); 5468 } 5469 _BCM_KT_COSQ_NODE_INIT(node); 5470 } else { 5471 BCM_IF_ERROR_RETURN 5472 (_bcm_kt_cosq_gport_delete_all(unit, gport, &rv)); 5473 } 5474 5475 return rv; 5476 } 5477 5478 /* 5479 * Function: 5480 * bcm_kt_cosq_gport_get 5481 * Purpose: 5482 * Get a cosq gport structure 5483 * Parameters: 5484 * unit - (IN) unit number 5485 * gport - (IN) GPORT identifier 5486 * port - (OUT) port number 5487 * numq - (OUT) number of COS queues 5488 * flags - (OUT) flags (BCM_COSQ_GPORT_XXX) 5489 * Returns: 5490 * BCM_E_XXX 5491 */ 5492 int 5493 bcm_kt_cosq_gport_get(int unit, bcm_gport_t gport, bcm_gport_t *port, 5494 int *numq, uint32 *flags) 5495 { 5496 _bcm_kt_cosq_node_t *node; 5497 bcm_module_t modid; 5498 bcm_port_t local_port; 5499 int id; 5500 _bcm_gport_dest_t dest; 5501 5502 if (port == NULL || numq == NULL || flags == NULL) { 5503 return BCM_E_PARAM; 5504 } 5505 5506 LOG_INFO(BSL_LS_BCM_COSQ, 5507 (BSL_META_U(unit, 5508 "bcm_kt_cosq_gport_get: unit=%d gport=0x%x\n"), 5509 unit, gport)); 5510 5511 BCM_IF_ERROR_RETURN 5512 (_bcm_kt_cosq_node_get(unit, gport, NULL, &local_port, &id, &node)); 5513 5514 if (SOC_USE_GPORT(unit)) { 5515 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid)); 5516 dest.gport_type = _SHR_GPORT_TYPE_MODPORT; 5517 dest.modid = modid; 5518 dest.port = local_port; 5519 BCM_IF_ERROR_RETURN(_bcm_esw_gport_construct(unit, &dest, port)); 5520 } else { 5521 *port = local_port; 5522 } 5523 5524 *numq = node->numq; 5525 5526 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 5527 *flags = BCM_COSQ_GPORT_UCAST_QUEUE_GROUP; 5528 5529 } else if (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport)) { 5530 *flags = BCM_COSQ_GPORT_SUBSCRIBER; 5531 } else if (BCM_GPORT_IS_SCHEDULER(gport)) { 5532 *flags = BCM_COSQ_GPORT_SCHEDULER; 5533 } else { 5534 *flags = 0; 5535 } 5536 5537 LOG_INFO(BSL_LS_BCM_COSQ, 5538 (BSL_META_U(unit, 5539 " port=0x%x numq=%d flags=0x%x\n"), 5540 *port, *numq, *flags)); 5541 5542 return BCM_E_NONE; 5543 } 5544 5545 /* 5546 * Function: 5547 * bcm_kt_cosq_gport_traverse 5548 * Purpose: 5549 * Walks through the valid COSQ GPORTs and calls 5550 * the user supplied callback function for each entry. 5551 * Parameters: 5552 * unit - (IN) unit number 5553 * trav_fn - (IN) Callback function. 5554 * user_data - (IN) User data to be passed to callback function 5555 * Returns: 5556 * BCM_E_NONE - Success. 5557 * BCM_E_XXX 5558 */ 5559 int 5560 bcm_kt_cosq_gport_traverse(int unit, bcm_cosq_gport_traverse_cb cb, 5561 void *user_data) 5562 { 5563 _bcm_kt_cosq_node_t *port_info; 5564 _bcm_kt_mmu_info_t *mmu_info; 5565 bcm_port_t local_port; 5566 bcm_port_t port; 5567 5568 if (_bcm_kt_mmu_info[unit] == NULL) { 5569 return BCM_E_INIT; 5570 } 5571 mmu_info = _bcm_kt_mmu_info[unit]; 5572 5573 PBMP_ALL_ITER(unit, port) { 5574 BCM_IF_ERROR_RETURN 5575 (_bcm_kt_cosq_localport_resolve(unit, port, &local_port)); 5576 5577 if (local_port < 0) { 5578 return BCM_E_PORT; 5579 } 5580 /* root node */ 5581 port_info = &mmu_info->sched_node[local_port]; 5582 5583 if (port_info->gport >= 0) { 5584 _bcm_kt_cosq_gport_traverse(unit, port_info->gport, cb, user_data); 5585 } 5586 } 5587 5588 return BCM_E_NONE; 5589 } 5590 5591 /* 5592 * Function: 5593 * bcm_kt_cosq_mapping_set 5594 * Purpose: 5595 * Determine which COS queue a given priority currently maps to. 5596 * Parameters: 5597 * unit - (IN) unit number 5598 * gport - (IN) queue group GPORT identifier 5599 * priority - (IN) priority value to map 5600 * cosq - (IN) COS queue to map to 5601 * Returns: 5602 * BCM_E_XXX 5603 */ 5604 int 5605 bcm_kt_cosq_mapping_set(int unit, bcm_port_t gport, bcm_cos_t priority, 5606 bcm_cos_queue_t cosq) 5607 { 5608 bcm_pbmp_t ports; 5609 bcm_port_t local_port; 5610 5611 if (gport == -1) { /* all ports */ 5612 BCM_PBMP_ASSIGN(ports, PBMP_ALL(unit)); 5613 } else { 5614 return _bcm_kt_cosq_mapping_set_regular(unit, gport, priority, cosq); 5615 } 5616 5617 PBMP_ITER(ports, local_port) { 5618 BCM_IF_ERROR_RETURN 5619 (_bcm_kt_cosq_mapping_set_regular(unit, local_port, priority, cosq)); 5620 5621 } 5622 5623 return BCM_E_NONE; 5624 } 5625 5626 5627 /* 5628 * Function: 5629 * bcm_kt_cosq_mapping_get 5630 * Purpose: 5631 * Determine which COS queue a given priority currently maps to. 5632 * Parameters: 5633 * unit - (IN) unit number 5634 * gport - (IN) queue group GPORT identifier 5635 * priority - (IN) priority value to map 5636 * cosq - (OUT) COS queue to map to 5637 * Returns: 5638 * BCM_E_XXX 5639 */ 5640 int 5641 bcm_kt_cosq_mapping_get(int unit, bcm_port_t gport, bcm_cos_t priority, 5642 bcm_cos_queue_t *cosq) 5643 { 5644 _bcm_kt_mmu_info_t *mmu_info; 5645 bcm_port_t port; 5646 int numq; 5647 bcm_cos_queue_t hw_cosq; 5648 soc_field_t field = COSf; 5649 int index; 5650 cos_map_sel_entry_t cos_map_sel_entry; 5651 void *entry_p; 5652 bcm_pbmp_t ports; 5653 5654 if (priority < 0 || priority >= 16) { 5655 return BCM_E_PARAM; 5656 } 5657 5658 if (gport == -1) { 5659 BCM_PBMP_ASSIGN(ports, PBMP_ALL(unit)); 5660 PBMP_ITER(ports, port) { 5661 BCM_IF_ERROR_RETURN 5662 (READ_COS_MAP_SELm(unit, MEM_BLOCK_ANY, port, &cos_map_sel_entry)); 5663 index = soc_mem_field32_get(unit, COS_MAP_SELm, &cos_map_sel_entry, 5664 SELECTf); 5665 index *= 16; 5666 5667 entry_p = SOC_PROFILE_MEM_ENTRY(unit, _bcm_kt_cos_map_profile[unit], 5668 port_cos_map_entry_t *, 5669 index + priority); 5670 *cosq = soc_mem_field32_get(unit, PORT_COS_MAPm, entry_p, field); 5671 5672 return BCM_E_NONE; 5673 } 5674 } 5675 5676 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 5677 BCM_IF_ERROR_RETURN 5678 (_bcm_kt_cosq_index_resolve 5679 (unit, gport, -1, _BCM_KT_COSQ_INDEX_STYLE_UCAST_QUEUE, 5680 &port, NULL, NULL)); 5681 } else { 5682 if (BCM_GPORT_IS_SET(gport)) { 5683 BCM_IF_ERROR_RETURN( 5684 bcm_esw_port_local_get(unit, gport, &port)); 5685 } else { 5686 port = gport; 5687 } 5688 5689 if (!SOC_PORT_VALID(unit, port) || !IS_ALL_PORT(unit, port)) { 5690 return BCM_E_PORT; 5691 } 5692 } 5693 5694 mmu_info = _bcm_kt_mmu_info[unit]; 5695 numq = mmu_info->port[port].q_limit - 5696 mmu_info->port[port].q_offset; 5697 5698 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 5699 field = (numq <= 8) ? COSf : HG_COSf; 5700 } 5701 5702 BCM_IF_ERROR_RETURN 5703 (READ_COS_MAP_SELm(unit, MEM_BLOCK_ANY, port, &cos_map_sel_entry)); 5704 index = soc_mem_field32_get(unit, COS_MAP_SELm, &cos_map_sel_entry, 5705 SELECTf); 5706 index *= 16; 5707 5708 entry_p = SOC_PROFILE_MEM_ENTRY(unit, _bcm_kt_cos_map_profile[unit], 5709 port_cos_map_entry_t *, 5710 index + priority); 5711 hw_cosq = soc_mem_field32_get(unit, PORT_COS_MAPm, entry_p, field); 5712 5713 if (hw_cosq >= numq) { 5714 return BCM_E_NOT_FOUND; 5715 } 5716 *cosq = hw_cosq; 5717 5718 return BCM_E_NONE; 5719 } 5720 5721 /* 5722 * Function: 5723 * bcm_kt_cosq_port_sched_set 5724 * Purpose: 5725 * Set up class-of-service policy and corresponding weights and delay 5726 * Parameters: 5727 * unit - (IN) unit number 5728 * pbm - (IN) port bitmap 5729 * mode - (IN) Scheduling mode (BCM_COSQ_xxx) 5730 * weights - (IN) Weights for each COS queue 5731 * delay - This parameter is not used 5732 * Returns: 5733 * BCM_E_XXX 5734 * Notes: 5735 * For non-ETS style scheduler (CPU port) only. 5736 */ 5737 int 5738 bcm_kt_cosq_port_sched_set(int unit, bcm_pbmp_t pbm, 5739 int mode, const int *weights, int delay) 5740 { 5741 bcm_port_t port; 5742 int num_cos; 5743 int num_weights; 5744 5745 num_cos = soc_property_get(unit, spn_BCM_NUM_COS, BCM_COS_DEFAULT); 5746 5747 BCM_PBMP_ITER(pbm, port) { 5748 num_weights = IS_CPU_PORT(unit, port) ? BCM_COS_COUNT : num_cos; 5749 5750 BCM_IF_ERROR_RETURN 5751 (_bcm_kt_cosq_port_sched_set(unit, port, 0, mode, num_weights, 5752 (int *)weights)); 5753 } 5754 5755 return BCM_E_NONE; 5756 } 5757 5758 /* 5759 * Function: 5760 * bcm_kt_cosq_port_sched_get 5761 * Purpose: 5762 * Retrieve class-of-service policy and corresponding weights and delay 5763 * Parameters: 5764 * unit - (IN) unit number 5765 * pbm - (IN) port bitmap 5766 * mode - (OUT) Scheduling mode (BCM_COSQ_XXX) 5767 * weights - (OUT) Weights for each COS queue 5768 * delay - This parameter is not used 5769 * Returns: 5770 * BCM_E_XXX 5771 * Notes: 5772 * For non-ETS style scheduler (CPU port) only. 5773 */ 5774 int 5775 bcm_kt_cosq_port_sched_get(int unit, bcm_pbmp_t pbm, 5776 int *mode, int *weights, int *delay) 5777 { 5778 bcm_port_t port; 5779 int num_cos; 5780 int num_weights; 5781 5782 num_cos = soc_property_get(unit, spn_BCM_NUM_COS, BCM_COS_DEFAULT); 5783 5784 BCM_PBMP_ITER(pbm, port) { 5785 num_weights = IS_CPU_PORT(unit, port) ? BCM_COS_COUNT : num_cos; 5786 5787 BCM_IF_ERROR_RETURN 5788 (_bcm_kt_cosq_port_sched_get(unit, port, 0, mode, num_weights, 5789 weights)); 5790 } 5791 5792 return BCM_E_NONE; 5793 } 5794 5795 /* 5796 * Function: 5797 * bcm_kt_cosq_sched_weight_max_get 5798 * Purpose: 5799 * Retrieve maximum weights for given COS policy 5800 * Parameters: 5801 * unit - (IN) unit number 5802 * mode - (IN) Scheduling mode (BCM_COSQ_xxx) 5803 * weight_max - (OUT) Maximum weight for COS queue. 5804 * Returns: 5805 * BCM_E_XXX 5806 */ 5807 int 5808 bcm_kt_cosq_sched_weight_max_get(int unit, int mode, int *weight_max) 5809 { 5810 switch (mode) { 5811 case BCM_COSQ_STRICT: 5812 *weight_max = BCM_COSQ_WEIGHT_STRICT; 5813 break; 5814 case BCM_COSQ_ROUND_ROBIN: 5815 *weight_max = BCM_COSQ_WEIGHT_MIN; 5816 break; 5817 case BCM_COSQ_WEIGHTED_ROUND_ROBIN: 5818 case BCM_COSQ_DEFICIT_ROUND_ROBIN: 5819 *weight_max = 5820 (1 << soc_mem_field_length(unit, LLS_L0_CHILD_WEIGHT_CFG_CNTm, C_WEIGHTf)) - 1; 5821 break; 5822 default: 5823 return BCM_E_PARAM; 5824 } 5825 5826 return BCM_E_NONE; 5827 } 5828 5829 /* 5830 * Function: 5831 * bcm_kt_cosq_bandwidth_set 5832 * Purpose: 5833 * Configure COS queue bandwidth control 5834 * Parameters: 5835 * unit - (IN) unit number 5836 * port - (IN) port number or GPORT identifier 5837 * cosq - (IN) COS queue number 5838 * min_quantum - (IN) 5839 * max_quantum - (IN) 5840 * burst_quantum - (IN) 5841 * flags - (IN) 5842 * Returns: 5843 * BCM_E_XXX 5844 * Notes: 5845 * If port is any form of local port, cosq is the hardware queue index. 5846 */ 5847 int 5848 bcm_kt_cosq_port_bandwidth_set(int unit, bcm_port_t port, 5849 bcm_cos_queue_t cosq, 5850 uint32 min_quantum, uint32 max_quantum, 5851 uint32 burst_quantum, uint32 flags) 5852 { 5853 if (cosq < 0) { 5854 return BCM_E_PARAM; 5855 } 5856 5857 return _bcm_kt_cosq_bucket_set(unit, port, cosq, min_quantum, 5858 max_quantum, min_quantum, 5859 burst_quantum, flags); 5860 } 5861 5862 /* 5863 * Function: 5864 * bcm_kt_cosq_bandwidth_get 5865 * Purpose: 5866 * Get COS queue bandwidth control configuration 5867 * Parameters: 5868 * unit - (IN) unit number 5869 * port - (IN) port number or GPORT identifier 5870 * cosq - (IN) COS queue number 5871 * min_quantum - (OUT) 5872 * max_quantum - (OUT) 5873 * burst_quantum - (OUT) 5874 * flags - (OUT) 5875 * Returns: 5876 * BCM_E_XXX 5877 * Notes: 5878 * If port is any form of local port, cosq is the hardware queue index. 5879 */ 5880 int 5881 bcm_kt_cosq_port_bandwidth_get(int unit, bcm_port_t port, 5882 bcm_cos_queue_t cosq, 5883 uint32 *min_quantum, uint32 *max_quantum, 5884 uint32 *burst_quantum, uint32 *flags) 5885 { 5886 5887 if (cosq < 0) { 5888 return BCM_E_PARAM; 5889 } 5890 5891 BCM_IF_ERROR_RETURN(_bcm_kt_cosq_bucket_get(unit, port, cosq, min_quantum, 5892 max_quantum, burst_quantum, 5893 burst_quantum, *flags)); 5894 *flags = 0; 5895 5896 return BCM_E_NONE; 5897 } 5898 5899 int 5900 bcm_kt_cosq_port_pps_set(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 5901 int pps) 5902 { 5903 uint32 min, max, burst_min, burst_max; 5904 5905 if (!IS_CPU_PORT(unit, port)) { 5906 return BCM_E_PORT; 5907 } else if (cosq < 0 || cosq >= NUM_CPU_COSQ(unit)) { 5908 return BCM_E_PARAM; 5909 } 5910 5911 BCM_IF_ERROR_RETURN 5912 (_bcm_kt_cosq_bucket_get(unit, port, cosq, &min, &max, &burst_min, 5913 &burst_max, _BCM_XGS_METER_FLAG_PACKET_MODE)); 5914 5915 return _bcm_kt_cosq_bucket_set(unit, port, cosq, min, pps, burst_min, 5916 burst_max, _BCM_XGS_METER_FLAG_PACKET_MODE); 5917 } 5918 5919 int 5920 bcm_kt_cosq_port_pps_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 5921 int *pps) 5922 { 5923 uint32 min, max, burst_min, burst_max; 5924 5925 if (!IS_CPU_PORT(unit, port)) { 5926 return BCM_E_PORT; 5927 } else if (cosq < 0 || cosq >= NUM_CPU_COSQ(unit)) { 5928 return BCM_E_PARAM; 5929 } 5930 5931 BCM_IF_ERROR_RETURN 5932 (_bcm_kt_cosq_bucket_get(unit, port, cosq, &min, &max, &burst_min, 5933 &burst_max, _BCM_XGS_METER_FLAG_PACKET_MODE)); 5934 *pps = max; 5935 5936 return BCM_E_NONE; 5937 } 5938 5939 int 5940 bcm_kt_cosq_port_burst_set(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 5941 int burst) 5942 { 5943 uint32 min, max, cur_burst_min, cur_burst_max; 5944 5945 if (!IS_CPU_PORT(unit, port)) { 5946 return BCM_E_PORT; 5947 } else if (cosq < 0 || cosq >= NUM_CPU_COSQ(unit)) { 5948 return BCM_E_PARAM; 5949 } 5950 5951 /* Get the current PPS and BURST settings */ 5952 BCM_IF_ERROR_RETURN 5953 (_bcm_kt_cosq_bucket_get(unit, port, cosq, &min, &max, &cur_burst_min, 5954 &cur_burst_max, _BCM_XGS_METER_FLAG_PACKET_MODE)); 5955 5956 /* Replace the current BURST setting, keep PPS the same */ 5957 return _bcm_kt_cosq_bucket_set(unit, port, cosq, min, max, cur_burst_min, burst, 5958 _BCM_XGS_METER_FLAG_PACKET_MODE); 5959 } 5960 5961 int 5962 bcm_kt_cosq_port_burst_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 5963 int *burst) 5964 { 5965 uint32 min, max, cur_burst_min, cur_burst_max; 5966 5967 if (!IS_CPU_PORT(unit, port)) { 5968 return BCM_E_PORT; 5969 } else if (cosq < 0 || cosq >= NUM_CPU_COSQ(unit)) { 5970 return BCM_E_PARAM; 5971 } 5972 5973 BCM_IF_ERROR_RETURN 5974 (_bcm_kt_cosq_bucket_get(unit, port, cosq, &min, &max, &cur_burst_min, 5975 &cur_burst_max, _BCM_XGS_METER_FLAG_PACKET_MODE)); 5976 *burst = cur_burst_max; 5977 5978 return BCM_E_NONE; 5979 } 5980 5981 /* 5982 * Function: 5983 * bcm_kt_cosq_gport_sched_set 5984 * Purpose: 5985 * Configure COS queue scheduler setting 5986 * Parameters: 5987 * unit - (IN) unit number 5988 * gport - (IN) GPORT identifier 5989 * cosq - (IN) COS queue to configure, -1 for all COS queues 5990 * mode - (IN) Scheduling mode, one of BCM_COSQ_xxx 5991 * weight - (IN) queue weight 5992 * Returns: 5993 * BCM_E_XXX 5994 */ 5995 int 5996 bcm_kt_cosq_gport_sched_set(int unit, bcm_gport_t gport, 5997 bcm_cos_queue_t cosq, int mode, int weight) 5998 { 5999 int rv, numq, i, count; 6000 6001 if (cosq == -1) { 6002 BCM_IF_ERROR_RETURN 6003 (_bcm_kt_cosq_index_resolve(unit, gport, cosq, 6004 _BCM_KT_COSQ_INDEX_STYLE_SCHEDULER, 6005 NULL, NULL, &numq)); 6006 cosq = 0; 6007 } else { 6008 numq = 1; 6009 } 6010 6011 count = 0; 6012 for (i = 0; i < numq; i++) { 6013 rv = _bcm_kt_cosq_sched_set(unit, gport, cosq + i, mode, 1, &weight); 6014 if (rv == BCM_E_NOT_FOUND) { 6015 continue; 6016 } else if (BCM_FAILURE(rv)) { 6017 return rv; 6018 } else { 6019 count++; 6020 } 6021 } 6022 6023 return count > 0 ? BCM_E_NONE : BCM_E_NOT_FOUND; 6024 } 6025 6026 /* 6027 * Function: 6028 * bcm_kt_cosq_gport_sched_get 6029 * Purpose: 6030 * Get COS queue scheduler setting 6031 * Parameters: 6032 * unit - (IN) unit number 6033 * gport - (IN) GPORT identifier 6034 * cosq - (IN) COS queue to get, -1 for any queue 6035 * mode - (OUT) Scheduling mode, one of BCM_COSQ_xxx 6036 * weight - (OUT) queue weight 6037 * Returns: 6038 * BCM_E_XXX 6039 */ 6040 int 6041 bcm_kt_cosq_gport_sched_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 6042 int *mode, int *weight) 6043 { 6044 int rv, numq, i; 6045 6046 if (cosq == -1) { 6047 BCM_IF_ERROR_RETURN 6048 (_bcm_kt_cosq_index_resolve(unit, gport, cosq, 6049 _BCM_KT_COSQ_INDEX_STYLE_SCHEDULER, 6050 NULL, NULL, &numq)); 6051 cosq = 0; 6052 } else { 6053 numq = 1; 6054 } 6055 6056 for (i = 0; i < numq; i++) { 6057 rv = _bcm_kt_cosq_sched_get(unit, gport, cosq + i, mode, 1, weight); 6058 if (rv == BCM_E_NOT_FOUND) { 6059 continue; 6060 } else { 6061 return rv; 6062 } 6063 } 6064 6065 return BCM_E_NOT_FOUND; 6066 } 6067 6068 /* 6069 * Function: 6070 * bcm_kt_cosq_gport_bandwidth_set 6071 * Purpose: 6072 * Configure COS queue bandwidth control 6073 * Parameters: 6074 * unit - (IN) unit number 6075 * gport - (IN) GPORT identifier 6076 * cosq - (IN) COS queue to configure, -1 for all COS queues 6077 * kbits_sec_min - (IN) minimum bandwidth, kbits/sec 6078 * kbits_sec_max - (IN) maximum bandwidth, kbits/sec 6079 * flags - (IN) BCM_COSQ_BW_* 6080 * Returns: 6081 * BCM_E_XXX 6082 */ 6083 int 6084 bcm_kt_cosq_gport_bandwidth_set(int unit, bcm_gport_t gport, 6085 bcm_cos_queue_t cosq, uint32 kbits_sec_min, 6086 uint32 kbits_sec_max, uint32 flags) 6087 { 6088 int numq, i; 6089 6090 if (cosq == -1) { 6091 BCM_IF_ERROR_RETURN 6092 (_bcm_kt_cosq_index_resolve(unit, gport, cosq, 6093 _BCM_KT_COSQ_INDEX_STYLE_BUCKET, 6094 NULL, NULL, &numq)); 6095 cosq = 0; 6096 } else { 6097 numq = 1; 6098 } 6099 6100 for (i = 0; i < numq; i++) { 6101 if (!soc_feature(unit, soc_feature_dynamic_sched_update)) { 6102 BCM_IF_ERROR_RETURN 6103 (_bcm_kt_cosq_bucket_set(unit, gport, cosq + i, kbits_sec_min, 6104 kbits_sec_max, kbits_sec_min, 6105 kbits_sec_max, flags)); 6106 } else { 6107 BCM_IF_ERROR_RETURN 6108 (_bcm_kt_cosq_dynamic_bucket_set(unit, gport, cosq + i, 6109 kbits_sec_min, 6110 kbits_sec_max, kbits_sec_min, 6111 kbits_sec_max, flags)); 6112 } 6113 } 6114 6115 return BCM_E_NONE; 6116 } 6117 6118 /* 6119 * Function: 6120 * bcm_kt_cosq_gport_bandwidth_get 6121 * Purpose: 6122 * Get COS queue bandwidth control configuration 6123 * Parameters: 6124 * unit - (IN) unit number 6125 * gport - (IN) GPORT identifier 6126 * cosq - (IN) COS queue to get, -1 for any COS queue 6127 * kbits_sec_min - (OUT) minimum bandwidth, kbits/sec 6128 * kbits_sec_max - (OUT) maximum bandwidth, kbits/sec 6129 * flags - (OUT) BCM_COSQ_BW_* 6130 * Returns: 6131 * BCM_E_XXX 6132 */ 6133 int 6134 bcm_kt_cosq_gport_bandwidth_get(int unit, bcm_gport_t gport, 6135 bcm_cos_queue_t cosq, uint32 *kbits_sec_min, 6136 uint32 *kbits_sec_max, uint32 *flags) 6137 { 6138 uint32 burst_min, burst_max; 6139 6140 if (!soc_feature(unit, soc_feature_dynamic_sched_update)) { 6141 BCM_IF_ERROR_RETURN 6142 (_bcm_kt_cosq_bucket_get(unit, gport, cosq == -1 ? 0 : cosq, 6143 kbits_sec_min, kbits_sec_max, 6144 &burst_min, &burst_max, *flags)); 6145 } else { 6146 BCM_IF_ERROR_RETURN 6147 (_bcm_kt_cosq_dynamic_bucket_get(unit, gport, cosq == -1 ? 0 : cosq, 6148 kbits_sec_min, kbits_sec_max, 6149 &burst_min, &burst_max, *flags)); 6150 } 6151 6152 *flags = 0; 6153 6154 return BCM_E_NONE; 6155 } 6156 6157 /* 6158 * Function: 6159 * bcm_kt_cosq_gport_child_node_bandwidth_set 6160 * Purpose: 6161 * Configure COS queue bandwidth control 6162 * Parameters: 6163 * unit - (IN) unit number 6164 * gport - (IN) GPORT identifier 6165 * cosq - (IN) COS queue to configure, -1 for all COS queues 6166 * kbits_sec_min - (IN) minimum bandwidth, kbits/sec 6167 * kbits_sec_max - (IN) maximum bandwidth, kbits/sec 6168 * flags - (IN) BCM_COSQ_BW_* 6169 * Returns: 6170 * BCM_E_XXX 6171 */ 6172 int 6173 bcm_kt_cosq_gport_child_node_bandwidth_set(int unit, 6174 bcm_gport_t gport, bcm_cos_queue_t cosq, 6175 uint32 kbits_sec_min, uint32 kbits_sec_max, 6176 uint32 flags) 6177 { 6178 _bcm_kt_cosq_node_t *node = NULL; 6179 _bcm_kt_cosq_node_t *cur_node = NULL; 6180 bcm_gport_t cur_gport; 6181 int start_cos; 6182 int end_cos; 6183 int numq, i; 6184 uint32 temp_kbits_sec_min = 0; 6185 uint32 temp_kbits_sec_max = 0; 6186 uint32 kbits_sec_burst_min = 0; 6187 uint32 kbits_sec_burst_max = 0; 6188 6189 cur_gport = gport; 6190 if (cosq == -1) { 6191 BCM_IF_ERROR_RETURN 6192 (_bcm_kt_cosq_index_resolve(unit, gport, cosq, 6193 _BCM_KT_COSQ_INDEX_STYLE_BUCKET, 6194 NULL, NULL, &numq)); 6195 start_cos = 0; 6196 end_cos = numq - 1; 6197 6198 } else { 6199 start_cos = end_cos = cosq; 6200 } 6201 6202 if ((BCM_GPORT_IS_SET(gport)) && 6203 (BCM_GPORT_IS_SCHEDULER(gport))) { 6204 BCM_IF_ERROR_RETURN 6205 (_bcm_kt_cosq_node_get(unit, gport, NULL, NULL, NULL, &node)); 6206 } 6207 6208 if (node) { 6209 /* For Port gport, L0, L1 scheduler nodes */ 6210 if (cosq >= node->numq) { 6211 return BCM_E_PARAM; 6212 } 6213 for (i = 0, cur_node = node->child; cur_node; 6214 cur_node = cur_node->sibling, i++) { 6215 6216 /* get the child node at cosq */ 6217 if ((cosq != -1) && (cur_node->cosq_attached_to != cosq)) { 6218 continue; 6219 } 6220 cur_gport = cur_node->gport; 6221 BCM_IF_ERROR_RETURN 6222 (_bcm_kt_cosq_bucket_get(unit, cur_gport, 6223 cur_node->cosq_attached_to, 6224 &temp_kbits_sec_min, 6225 &temp_kbits_sec_max, 6226 &kbits_sec_burst_min, 6227 &kbits_sec_burst_max, 0)); 6228 if (kbits_sec_burst_min || kbits_sec_burst_max) { 6229 flags = _BCM_XGS_METER_FLAG_NON_BURST_CORRECTION; 6230 } 6231 BCM_IF_ERROR_RETURN 6232 (_bcm_kt_cosq_bucket_set(unit, cur_gport, 6233 cur_node->cosq_attached_to, kbits_sec_min, 6234 kbits_sec_max, kbits_sec_burst_min, 6235 kbits_sec_burst_max, flags)); 6236 } 6237 } else { 6238 /* For Port and L2 queues */ 6239 for (i = start_cos; i <= end_cos; i++) { 6240 BCM_IF_ERROR_RETURN 6241 (_bcm_kt_cosq_bucket_get(unit, cur_gport, i, 6242 &temp_kbits_sec_min, 6243 &temp_kbits_sec_max, 6244 &kbits_sec_burst_min, 6245 &kbits_sec_burst_max, 0)); 6246 6247 if (kbits_sec_burst_min || kbits_sec_burst_max) { 6248 flags = _BCM_XGS_METER_FLAG_NON_BURST_CORRECTION; 6249 } 6250 BCM_IF_ERROR_RETURN 6251 (_bcm_kt_cosq_bucket_set(unit, cur_gport, 6252 i, kbits_sec_min, 6253 kbits_sec_max, 6254 kbits_sec_burst_min, 6255 kbits_sec_burst_max, flags)); 6256 } 6257 } 6258 6259 return BCM_E_NONE; 6260 } 6261 6262 /* 6263 * Function: 6264 * bcm_kt_cosq_gport_child_node_bandwidth_get 6265 * Purpose: 6266 * Get COS queue bandwidth control configuration 6267 * Parameters: 6268 * unit - (IN) unit number 6269 * gport - (IN) GPORT identifier 6270 * cosq - (IN) COS queue to get, -1 for any COS queue 6271 * kbits_sec_min - (OUT) minimum bandwidth, kbits/sec 6272 * kbits_sec_max - (OUT) maximum bandwidth, kbits/sec 6273 * flags - (OUT) BCM_COSQ_BW_* 6274 * Returns: 6275 * BCM_E_XXX 6276 */ 6277 int 6278 bcm_kt_cosq_gport_child_node_bandwidth_get(int unit, bcm_gport_t gport, 6279 bcm_cos_queue_t cosq, uint32 *kbits_sec_min, 6280 uint32 *kbits_sec_max, uint32 *flags) 6281 { 6282 uint32 burst_min, burst_max; 6283 _bcm_kt_cosq_node_t *node = NULL; 6284 _bcm_kt_cosq_node_t *cur_node = NULL; 6285 bcm_gport_t cur_gport; 6286 int i; 6287 6288 i = (cosq == -1) ? 0 : cosq; 6289 cur_gport = gport; 6290 if ((BCM_GPORT_IS_SET(gport)) && 6291 (BCM_GPORT_IS_SCHEDULER(gport))) { 6292 /* get the child node at cosq*/ 6293 BCM_IF_ERROR_RETURN 6294 (_bcm_kt_cosq_node_get(unit, gport, NULL, NULL, NULL, &node)); 6295 if (node != NULL) { 6296 if (cosq >= node->numq) { 6297 return BCM_E_PARAM; 6298 } 6299 /* resolve the child attached to input cosq */ 6300 BCM_IF_ERROR_RETURN( 6301 _bcm_kt_cosq_child_node_at_input(node, i, &cur_node)); 6302 cur_gport = cur_node->gport; 6303 6304 } else { 6305 return BCM_E_PARAM; 6306 } 6307 } 6308 BCM_IF_ERROR_RETURN 6309 (_bcm_kt_cosq_bucket_get(unit, cur_gport, i, 6310 kbits_sec_min, kbits_sec_max, 6311 &burst_min, &burst_max, *flags)); 6312 *flags = 0; 6313 return BCM_E_NONE; 6314 } 6315 6316 /* 6317 * Function: 6318 * bcm_kt_cosq_gport_bandwidth_burst_set 6319 * Purpose: 6320 * Configure COS queue bandwidth burst setting 6321 * Parameters: 6322 * unit - (IN) unit number 6323 * gport - (IN) GPORT identifier 6324 * cosq - (IN) COS queue to configure, -1 for all COS queues 6325 * kbits_burst - (IN) maximum burst, kbits 6326 * Returns: 6327 * BCM_E_XXX 6328 */ 6329 int 6330 bcm_kt_cosq_gport_bandwidth_burst_set(int unit, bcm_gport_t gport, 6331 bcm_cos_queue_t cosq, 6332 uint32 kbits_burst_min, 6333 uint32 kbits_burst_max) 6334 { 6335 int numq, i; 6336 uint32 kbits_sec_min, kbits_sec_max; 6337 uint32 kbits_sec_burst_min, kbits_sec_burst_max; 6338 6339 if (cosq == -1) { 6340 BCM_IF_ERROR_RETURN 6341 (_bcm_kt_cosq_index_resolve(unit, gport, cosq, 6342 _BCM_KT_COSQ_INDEX_STYLE_BUCKET, 6343 NULL, NULL, &numq)); 6344 cosq = 0; 6345 } else { 6346 numq = 1; 6347 } 6348 6349 for (i = 0; i < numq; i++) { 6350 BCM_IF_ERROR_RETURN 6351 (_bcm_kt_cosq_bucket_get(unit, gport, cosq + i, &kbits_sec_min, 6352 &kbits_sec_max, &kbits_sec_burst_min, 6353 &kbits_sec_burst_max, 0)); 6354 BCM_IF_ERROR_RETURN 6355 (_bcm_kt_cosq_bucket_set(unit, gport, cosq + i, kbits_sec_min, 6356 kbits_sec_max, kbits_burst_min, 6357 kbits_burst_max, 6358 _BCM_XGS_METER_FLAG_NON_BURST_CORRECTION)); 6359 } 6360 6361 return BCM_E_NONE; 6362 } 6363 6364 /* 6365 * Function: 6366 * bcm_kt_cosq_gport_bandwidth_burst_get 6367 * Purpose: 6368 * Get COS queue bandwidth burst setting 6369 * Parameters: 6370 * unit - (IN) unit number 6371 * gport - (IN) GPORT identifier 6372 * cosq - (IN) COS queue to get, -1 for any queue 6373 * kbits_burst - (OUT) maximum burst, kbits 6374 * Returns: 6375 * BCM_E_XXX 6376 */ 6377 int 6378 bcm_kt_cosq_gport_bandwidth_burst_get(int unit, bcm_gport_t gport, 6379 bcm_cos_queue_t cosq, 6380 uint32 *kbits_burst_min, 6381 uint32 *kbits_burst_max) 6382 { 6383 uint32 kbits_sec_min, kbits_sec_max; 6384 6385 BCM_IF_ERROR_RETURN 6386 (_bcm_kt_cosq_bucket_get(unit, gport, cosq == -1 ? 0 : cosq, 6387 &kbits_sec_min, &kbits_sec_max, 6388 kbits_burst_min, kbits_burst_max, 0)); 6389 6390 return BCM_E_NONE; 6391 } 6392 6393 /* 6394 * Function: 6395 * bcm_kt_cosq_gport_discard_set 6396 * Purpose: 6397 * Configure gport WRED setting 6398 * Parameters: 6399 * unit - (IN) unit number 6400 * port - (IN) GPORT identifier 6401 * cosq - (IN) COS queue to configure, -1 for all COS queues 6402 * discard - (IN) discard settings 6403 * Returns: 6404 * BCM_E_XXX 6405 */ 6406 int 6407 bcm_kt_cosq_gport_discard_set(int unit, bcm_gport_t gport, 6408 bcm_cos_queue_t cosq, 6409 bcm_cosq_gport_discard_t *discard) 6410 { 6411 int numq, i; 6412 uint32 min_thresh, max_thresh; 6413 int cell_size, cell_field_max; 6414 bcm_port_t local_port; 6415 6416 if (discard == NULL || 6417 discard->gain < 0 || discard->gain > 15 || 6418 discard->drop_probability < 0 || discard->drop_probability > 100) { 6419 return BCM_E_PARAM; 6420 } 6421 6422 if (cosq < -1) { 6423 return BCM_E_PARAM; 6424 } 6425 6426 cell_size = _BCM_KT_COSQ_CELLSIZE; 6427 if (gport != -1) { 6428 6429 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 6430 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport) || 6431 BCM_GPORT_IS_SCHEDULER(gport)) { 6432 BCM_IF_ERROR_RETURN 6433 (_bcm_kt_cosq_node_get(unit, gport, NULL, &local_port,NULL, 6434 NULL)); 6435 } else { 6436 BCM_IF_ERROR_RETURN 6437 (_bcm_kt_cosq_localport_resolve(unit, gport, &local_port)); 6438 } 6439 if (IS_EXT_MEM_PORT(unit, local_port)) { 6440 cell_size = _BCM_KT_COSQ_EXT_CELLSIZE; 6441 } 6442 } 6443 6444 6445 cell_field_max = KT_CELL_FIELD_MAX; 6446 6447 min_thresh = discard->min_thresh; 6448 max_thresh = discard->max_thresh; 6449 if (discard->flags & BCM_COSQ_DISCARD_BYTES) { 6450 /* Convert bytes to cells */ 6451 min_thresh += (cell_size - 1); 6452 min_thresh /= cell_size; 6453 6454 max_thresh += (cell_size - 1); 6455 max_thresh /= cell_size; 6456 6457 if ((min_thresh > cell_field_max) || 6458 (max_thresh > cell_field_max)) { 6459 return BCM_E_PARAM; 6460 } 6461 } else { /* BCM_COSQ_DISCARD_PACKETS */ 6462 if ((min_thresh > KT_CELL_FIELD_MAX) || 6463 (max_thresh > KT_CELL_FIELD_MAX)) { 6464 return BCM_E_PARAM; 6465 } 6466 } 6467 6468 if (cosq == -1) { 6469 BCM_IF_ERROR_RETURN 6470 (_bcm_kt_cosq_index_resolve(unit, gport, cosq, 6471 _BCM_KT_COSQ_INDEX_STYLE_WRED, 6472 NULL, NULL, &numq)); 6473 cosq = 0; 6474 } else { 6475 numq = 1; 6476 } 6477 6478 for (i = 0; i < numq; i++) { 6479 BCM_IF_ERROR_RETURN 6480 (_bcm_kt_cosq_wred_set(unit, gport, cosq + i, discard->flags, 6481 min_thresh, max_thresh, 6482 discard->drop_probability, discard->gain, 6483 FALSE)); 6484 } 6485 6486 return BCM_E_NONE; 6487 } 6488 6489 /* 6490 * Function: 6491 * bcm_kt_cosq_gport_discard_get 6492 * Purpose: 6493 * Get port WRED setting 6494 * Parameters: 6495 * unit - (IN) unit number 6496 * port - (IN) GPORT identifier 6497 * cosq - (IN) COS queue to get, -1 for any queue 6498 * discard - (OUT) discard settings 6499 * Returns: 6500 * BCM_E_XXX 6501 */ 6502 int 6503 bcm_kt_cosq_gport_discard_get(int unit, bcm_gport_t gport, 6504 bcm_cos_queue_t cosq, 6505 bcm_cosq_gport_discard_t *discard) 6506 { 6507 uint32 min_thresh, max_thresh; 6508 int cell_size; 6509 bcm_port_t local_port; 6510 6511 if (discard == NULL) { 6512 return BCM_E_PARAM; 6513 } 6514 6515 if (cosq < -1) { 6516 return BCM_E_PARAM; 6517 } 6518 6519 BCM_IF_ERROR_RETURN 6520 (_bcm_kt_cosq_wred_get(unit, gport, cosq == -1 ? 0 : cosq, 6521 &discard->flags, &min_thresh, &max_thresh, 6522 &discard->drop_probability, &discard->gain)); 6523 6524 cell_size = _BCM_KT_COSQ_CELLSIZE; 6525 if (gport != -1) { 6526 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 6527 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport) || 6528 BCM_GPORT_IS_SCHEDULER(gport)) { 6529 BCM_IF_ERROR_RETURN 6530 (_bcm_kt_cosq_node_get(unit, gport, NULL, &local_port,NULL, 6531 NULL)); 6532 } else { 6533 6534 BCM_IF_ERROR_RETURN 6535 (_bcm_kt_cosq_localport_resolve(unit, gport, &local_port)); 6536 } 6537 if (IS_EXT_MEM_PORT(unit, local_port)) { 6538 cell_size = _BCM_KT_COSQ_EXT_CELLSIZE; 6539 } 6540 } 6541 /* Convert number of cells to number of bytes */ 6542 if (discard->flags & BCM_COSQ_DISCARD_BYTES) { 6543 discard->min_thresh = min_thresh * cell_size; 6544 discard->max_thresh = max_thresh * cell_size; 6545 } else { 6546 discard->min_thresh = min_thresh; 6547 discard->max_thresh = max_thresh; 6548 } 6549 6550 return BCM_E_NONE; 6551 } 6552 6553 /* 6554 * Function: 6555 * bcm_kt_cosq_discard_set 6556 * Purpose: 6557 * Get port WRED setting 6558 * Parameters: 6559 * unit - (IN) unit number 6560 * flags - (IN) flags 6561 * Returns: 6562 * BCM_E_XXX 6563 */ 6564 int 6565 bcm_kt_cosq_discard_set(int unit, uint32 flags) 6566 { 6567 bcm_port_t port; 6568 bcm_cos_queue_t cosq; 6569 int numq; 6570 6571 if (flags & ~(BCM_COSQ_DISCARD_DEVICE | 6572 BCM_COSQ_DISCARD_NONTCP | 6573 BCM_COSQ_DISCARD_COLOR_ALL | 6574 BCM_COSQ_DISCARD_PACKETS | 6575 BCM_COSQ_DISCARD_CAP_AVERAGE | 6576 BCM_COSQ_DISCARD_ENABLE | 6577 BCM_COSQ_DISCARD_MARK_CONGESTION)) { 6578 return BCM_E_PARAM; 6579 } 6580 6581 flags &= ~(BCM_COSQ_DISCARD_NONTCP | BCM_COSQ_DISCARD_COLOR_ALL); 6582 6583 PBMP_PORT_ITER(unit, port) { 6584 BCM_IF_ERROR_RETURN 6585 (_bcm_kt_cosq_index_resolve(unit, port, -1, 6586 _BCM_KT_COSQ_INDEX_STYLE_WRED, NULL, 6587 NULL, &numq)); 6588 for (cosq = 0; cosq < numq; cosq++) { 6589 BCM_IF_ERROR_RETURN 6590 (_bcm_kt_cosq_wred_set(unit, port, cosq, flags, 0, 0, 0, 0, 6591 FALSE)); 6592 } 6593 } 6594 6595 return BCM_E_NONE; 6596 6597 } 6598 6599 /* 6600 * Function: 6601 * bcm_kt_cosq_discard_get 6602 * Purpose: 6603 * Get port WRED setting 6604 * Parameters: 6605 * unit - (IN) unit number 6606 * flags - (OUT) flags 6607 * Returns: 6608 * BCM_E_XXX 6609 */ 6610 int 6611 bcm_kt_cosq_discard_get(int unit, uint32 *flags) 6612 { 6613 bcm_port_t port; 6614 6615 PBMP_PORT_ITER(unit, port) { 6616 *flags = 0; 6617 /* use setting from hardware cosq index 0 of the first port */ 6618 return _bcm_kt_cosq_wred_get(unit, port, 0, flags, NULL, NULL, NULL, 6619 NULL); 6620 } 6621 6622 return BCM_E_NOT_FOUND; 6623 6624 } 6625 6626 /* 6627 * Function: 6628 * bcm_kt_cosq_discard_port_set 6629 * Purpose: 6630 * Configure port WRED setting 6631 * Parameters: 6632 * unit - (IN) unit number 6633 * port - (IN) port number or GPORT identifier 6634 * cosq - (IN) COS queue number 6635 * color - (IN) 6636 * drop_start - (IN) 6637 * drop_slot - (IN) 6638 * average_time - (IN) 6639 * Returns: 6640 * BCM_E_XXX 6641 * Notes: 6642 * If port is any form of local port, cosq is the hardware queue index. 6643 */ 6644 int 6645 bcm_kt_cosq_discard_port_set(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 6646 uint32 color, int drop_start, int drop_slope, 6647 int average_time) 6648 { 6649 return SOC_E_UNAVAIL; 6650 } 6651 6652 /* 6653 * Function: 6654 * bcm_kt_cosq_discard_port_get 6655 * Purpose: 6656 * Get port WRED setting 6657 * Parameters: 6658 * unit - (IN) unit number 6659 * port - (IN) port number or GPORT identifier 6660 * cosq - (IN) COS queue number 6661 * color - (OUT) 6662 * drop_start - (OUT) 6663 * drop_slot - (OUT) 6664 * average_time - (OUT) 6665 * Returns: 6666 * BCM_E_XXX 6667 * Notes: 6668 * If port is any form of local port, cosq is the hardware queue index. 6669 */ 6670 int 6671 bcm_kt_cosq_discard_port_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 6672 uint32 color, int *drop_start, int *drop_slope, 6673 int *average_time) 6674 { 6675 return SOC_E_UNAVAIL; 6676 } 6677 6678 int 6679 bcm_kt_cosq_stat_set(int unit, bcm_gport_t port, bcm_cos_queue_t cosq, 6680 bcm_cosq_stat_t stat, uint64 value) 6681 { 6682 bcm_port_t local_port; 6683 int startq, numq, i; 6684 _bcm_kt_mmu_info_t *mmu_info; 6685 soc_counter_non_dma_id_t dma_id; 6686 _bcm_kt_cosq_node_t *node = NULL; 6687 _bcm_kt_cosq_node_t *child_node = NULL; 6688 int first_child = 1; 6689 uint64 value64; 6690 uint64 zero; 6691 6692 BCM_IF_ERROR_RETURN 6693 (_bcm_kt_cosq_index_resolve 6694 (unit, port, cosq, _BCM_KT_COSQ_INDEX_STYLE_UCAST_QUEUE, 6695 &local_port, &startq, &numq)); 6696 6697 mmu_info = _bcm_kt_mmu_info[unit]; 6698 if (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port) || 6699 startq >= mmu_info->num_base_queues) { 6700 /* pass port as queue number */ 6701 local_port = startq; 6702 startq = 0; 6703 } 6704 6705 switch (stat) { 6706 case bcmCosqStatDroppedPackets: 6707 dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_PKT; 6708 break; 6709 case bcmCosqStatDroppedBytes: 6710 dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE; 6711 break; 6712 case bcmCosqStatRedCongestionDroppedPackets: 6713 dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_RED; 6714 break; 6715 case bcmCosqStatOutPackets: 6716 dma_id = SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT; 6717 break; 6718 case bcmCosqStatOutBytes: 6719 dma_id = SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE; 6720 break; 6721 default: 6722 return BCM_E_PARAM; 6723 } 6724 6725 if (!BCM_GPORT_IS_SCHEDULER(port)) { 6726 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 6727 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port) || 6728 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) || 6729 BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(port) || 6730 (cosq != BCM_COS_INVALID)) { 6731 BCM_IF_ERROR_RETURN 6732 (soc_counter_set(unit, local_port, dma_id, startq, value)); 6733 } else { 6734 numq = soc_property_get(unit, spn_BCM_NUM_COS, BCM_COS_DEFAULT); 6735 if (numq < 1) { 6736 numq = 1; 6737 } else if (numq > 8) { 6738 numq = 8; 6739 } 6740 for (i = 0; i < numq; i++) { 6741 COMPILER_64_ZERO(zero); 6742 SOC_IF_ERROR_RETURN 6743 (soc_counter_set(unit, local_port, dma_id, i, i == 0 ? value : zero)); 6744 } 6745 } 6746 } else { 6747 BCM_IF_ERROR_RETURN 6748 (_bcm_kt_cosq_node_get(unit, port, 0, 6749 &local_port, NULL, &node)); 6750 if (cosq == -1) { 6751 for (i = 0; i < node->numq; i++) { 6752 if ((_bcm_kt_cosq_child_node_at_input(node, i, &child_node)) 6753 == BCM_E_NOT_FOUND) { 6754 continue; 6755 } 6756 port = child_node->gport; 6757 BCM_IF_ERROR_RETURN 6758 (_bcm_kt_cosq_index_resolve 6759 (unit, port, 0, _BCM_KT_COSQ_INDEX_STYLE_UCAST_QUEUE, 6760 &local_port, &startq, &numq)); 6761 6762 if (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port) || 6763 startq >= mmu_info->num_base_queues) { 6764 /* pass port as queue number */ 6765 local_port = startq; 6766 startq = 0; 6767 } 6768 if (first_child) { 6769 /* 6770 *According to api guide only first child should be set with given value 6771 *all other are set to 0 6772 */ 6773 BCM_IF_ERROR_RETURN 6774 (soc_counter_set(unit, local_port, dma_id, 6775 startq , value)); 6776 first_child = 0; 6777 } 6778 else { 6779 COMPILER_64_ZERO(value64); 6780 BCM_IF_ERROR_RETURN 6781 (soc_counter_set(unit, local_port, dma_id, 6782 startq , value64)); 6783 } 6784 } 6785 } 6786 else { 6787 if ((_bcm_kt_cosq_child_node_at_input(node, cosq, &child_node)) 6788 == BCM_E_NOT_FOUND) { 6789 return BCM_E_NOT_FOUND; 6790 } 6791 port = child_node->gport; 6792 BCM_IF_ERROR_RETURN 6793 (_bcm_kt_cosq_index_resolve 6794 (unit, port, 0, _BCM_KT_COSQ_INDEX_STYLE_UCAST_QUEUE, 6795 &local_port, &startq, &numq)); 6796 6797 if (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port) || 6798 startq >= mmu_info->num_base_queues) { 6799 /* pass port as queue number */ 6800 local_port = startq; 6801 startq = 0; 6802 } 6803 BCM_IF_ERROR_RETURN 6804 (soc_counter_set(unit, local_port, dma_id, 6805 startq , value)); 6806 6807 } 6808 } 6809 6810 return BCM_E_NONE; 6811 } 6812 6813 int 6814 bcm_kt_cosq_stat_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 6815 bcm_cosq_stat_t stat, int sync_mode, uint64 *value) 6816 { 6817 bcm_port_t local_port; 6818 int startq, numq, i; 6819 uint64 sum, value64; 6820 _bcm_kt_mmu_info_t *mmu_info; 6821 soc_counter_non_dma_id_t dma_id; 6822 _bcm_kt_cosq_node_t *node = NULL; 6823 _bcm_kt_cosq_node_t *child_node = NULL; 6824 int (*counter_get) (int , soc_port_t , soc_reg_t , int , uint64 *); 6825 6826 if (value == NULL) { 6827 return BCM_E_PARAM; 6828 } 6829 6830 /* 6831 * if sync-mode is set, update the software cached counter value, 6832 * with the hardware count and then retrieve the count. 6833 * else return the software cache counter value. 6834 */ 6835 counter_get = (sync_mode == 1)? soc_counter_sync_get: soc_counter_get; 6836 6837 6838 BCM_IF_ERROR_RETURN 6839 (_bcm_kt_cosq_index_resolve 6840 (unit, port, cosq, _BCM_KT_COSQ_INDEX_STYLE_UCAST_QUEUE, 6841 &local_port, &startq, &numq)); 6842 6843 mmu_info = _bcm_kt_mmu_info[unit]; 6844 if (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port) || 6845 startq >= mmu_info->num_base_queues) { 6846 /* pass port as queue number */ 6847 local_port = startq; 6848 startq = 0; 6849 } 6850 6851 switch (stat) { 6852 case bcmCosqStatDroppedPackets: 6853 dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_PKT; 6854 break; 6855 case bcmCosqStatDroppedBytes: 6856 dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE; 6857 break; 6858 case bcmCosqStatRedCongestionDroppedPackets: 6859 dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_RED; 6860 break; 6861 case bcmCosqStatOutPackets: 6862 dma_id = SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT; 6863 break; 6864 case bcmCosqStatOutBytes: 6865 dma_id = SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE; 6866 break; 6867 default: 6868 return BCM_E_PARAM; 6869 } 6870 6871 if (!BCM_GPORT_IS_SCHEDULER(port)) { 6872 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 6873 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port) || 6874 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) || 6875 BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(port) || 6876 (cosq != BCM_COS_INVALID)) { 6877 BCM_IF_ERROR_RETURN 6878 (counter_get(unit, local_port, dma_id, startq, value)); 6879 } else { 6880 numq = soc_property_get(unit, spn_BCM_NUM_COS, BCM_COS_DEFAULT); 6881 if (numq < 1) { 6882 numq = 1; 6883 } else if (numq > 8) { 6884 numq = 8; 6885 } 6886 COMPILER_64_ZERO(sum); 6887 COMPILER_64_ZERO(value64); 6888 for (i = 0; i < numq; i++) { 6889 BCM_IF_ERROR_RETURN 6890 (counter_get(unit, local_port, dma_id, i, &value64)); 6891 COMPILER_64_ADD_64(sum, value64); 6892 } 6893 *value = sum; 6894 } 6895 } else { 6896 BCM_IF_ERROR_RETURN 6897 (_bcm_kt_cosq_node_get(unit, port, 0, 6898 &local_port, NULL, &node)); 6899 COMPILER_64_ZERO(sum); 6900 if (cosq ==-1) { 6901 for (i = 0; i < node->numq; i++) { 6902 if ((_bcm_kt_cosq_child_node_at_input(node, i, &child_node)) 6903 == BCM_E_NOT_FOUND) { 6904 continue; 6905 } 6906 port = child_node->gport; 6907 6908 BCM_IF_ERROR_RETURN 6909 (_bcm_kt_cosq_index_resolve 6910 (unit, port, 0, _BCM_KT_COSQ_INDEX_STYLE_UCAST_QUEUE, 6911 &local_port, &startq, &numq)); 6912 6913 if (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port) || 6914 startq >= mmu_info->num_base_queues) { 6915 /* pass port as queue number */ 6916 local_port = startq; 6917 startq = 0; 6918 } 6919 BCM_IF_ERROR_RETURN 6920 (counter_get(unit, local_port, dma_id, 6921 startq , &value64)); 6922 COMPILER_64_ADD_64(sum, value64); 6923 6924 } 6925 } 6926 else { 6927 if ((_bcm_kt_cosq_child_node_at_input(node, cosq, &child_node)) 6928 == BCM_E_NOT_FOUND) { 6929 return BCM_E_NOT_FOUND; 6930 } 6931 port = child_node->gport; 6932 6933 BCM_IF_ERROR_RETURN 6934 (_bcm_kt_cosq_index_resolve 6935 (unit, port, 0, _BCM_KT_COSQ_INDEX_STYLE_UCAST_QUEUE, 6936 &local_port, &startq, &numq)); 6937 6938 if (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port) || 6939 startq >= mmu_info->num_base_queues) { 6940 /* pass port as queue number */ 6941 local_port = startq; 6942 startq = 0; 6943 } 6944 BCM_IF_ERROR_RETURN 6945 (counter_get(unit, local_port, dma_id, 6946 startq , &value64)); 6947 COMPILER_64_ADD_64(sum, value64); 6948 } 6949 6950 *value = sum; 6951 } 6952 6953 return BCM_E_NONE; 6954 } 6955 6956 int 6957 bcm_kt_cosq_gport_stat_set(int unit, bcm_gport_t port, bcm_cos_queue_t cosq, 6958 bcm_cosq_gport_stats_t stat, uint64 value) 6959 { 6960 bcm_port_t local_port; 6961 int startq, numq, i; 6962 uint64 value64; 6963 _bcm_kt_mmu_info_t *mmu_info; 6964 soc_counter_non_dma_id_t dma_id; 6965 6966 if (BCM_GPORT_IS_SCHEDULER(port) && cosq != BCM_COS_INVALID) { 6967 return BCM_E_PARAM; 6968 } 6969 6970 BCM_IF_ERROR_RETURN 6971 (_bcm_kt_cosq_index_resolve 6972 (unit, port, cosq, _BCM_KT_COSQ_INDEX_STYLE_UCAST_QUEUE, 6973 &local_port, &startq, &numq)); 6974 6975 mmu_info = _bcm_kt_mmu_info[unit]; 6976 if (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port) || 6977 startq >= mmu_info->num_base_queues) { 6978 /* pass port as queue number */ 6979 local_port = startq; 6980 startq = 0; 6981 } 6982 6983 switch (stat) { 6984 case bcmCosqGportGreenAcceptedPkts: 6985 dma_id = SOC_COUNTER_NON_DMA_COSQ_ACCEPT_PKT_GREEN; 6986 break; 6987 case bcmCosqGportGreenAcceptedBytes: 6988 dma_id = SOC_COUNTER_NON_DMA_COSQ_ACCEPT_BYTE_GREEN; 6989 break; 6990 case bcmCosqGportYellowAcceptedPkts: 6991 dma_id = SOC_COUNTER_NON_DMA_COSQ_ACCEPT_PKT_YELLOW; 6992 break; 6993 case bcmCosqGportYellowAcceptedBytes: 6994 dma_id = SOC_COUNTER_NON_DMA_COSQ_ACCEPT_BYTE_YELLOW; 6995 break; 6996 case bcmCosqGportRedAcceptedPkts: 6997 dma_id = SOC_COUNTER_NON_DMA_COSQ_ACCEPT_PKT_RED; 6998 break; 6999 case bcmCosqGportRedAcceptedBytes: 7000 dma_id = SOC_COUNTER_NON_DMA_COSQ_ACCEPT_BYTE_RED; 7001 break; 7002 case bcmCosqGportReceivedPkts: 7003 dma_id = SOC_COUNTER_NON_DMA_COSQ_ACCEPT_PKT; 7004 break; 7005 case bcmCosqGportReceivedBytes: 7006 dma_id = SOC_COUNTER_NON_DMA_COSQ_ACCEPT_BYTE; 7007 break; 7008 case bcmCosqGportGreenDroppedPkts: 7009 dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_GREEN; 7010 break; 7011 case bcmCosqGportGreenDroppedBytes: 7012 dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE_GREEN; 7013 break; 7014 case bcmCosqGportYellowDroppedPkts: 7015 dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_YELLOW; 7016 break; 7017 case bcmCosqGportYellowDroppedBytes: 7018 dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE_YELLOW; 7019 break; 7020 case bcmCosqGportRedDroppedPkts: 7021 dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_RED; 7022 break; 7023 case bcmCosqGportRedDroppedBytes: 7024 dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE_RED; 7025 break; 7026 case bcmCosqGportDroppedPkts: 7027 dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_PKT; 7028 break; 7029 case bcmCosqGportDroppedBytes: 7030 dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE; 7031 break; 7032 case bcmCosqGportOutPkts: 7033 dma_id = SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT; 7034 break; 7035 case bcmCosqGportOutBytes: 7036 dma_id = SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE; 7037 break; 7038 default: 7039 return BCM_E_PARAM; 7040 } 7041 7042 if (!BCM_GPORT_IS_SCHEDULER(port)) { 7043 BCM_IF_ERROR_RETURN 7044 (soc_counter_set(unit, local_port, dma_id, startq, value)); 7045 } else { 7046 COMPILER_64_ZERO(value64); 7047 for (i = 0; i < numq; i++) { 7048 BCM_IF_ERROR_RETURN 7049 (soc_counter_set(unit, local_port, dma_id, startq + i, 7050 value64)); 7051 } 7052 } 7053 7054 return BCM_E_NONE; 7055 } 7056 7057 int 7058 bcm_kt_cosq_gport_stat_get(int unit, int sync_mode, bcm_port_t port, 7059 bcm_cos_queue_t cosq, bcm_cosq_gport_stats_t stat, 7060 uint64 *value) 7061 { 7062 bcm_port_t local_port; 7063 int startq, numq, i; 7064 uint64 sum, value64; 7065 _bcm_kt_mmu_info_t *mmu_info; 7066 soc_counter_non_dma_id_t dma_id; 7067 int (*counter_get) (int , soc_port_t , soc_reg_t , int , uint64 *); 7068 7069 if (value == NULL) { 7070 return BCM_E_PARAM; 7071 } 7072 7073 if (BCM_GPORT_IS_SCHEDULER(port) && cosq != BCM_COS_INVALID) { 7074 return BCM_E_PARAM; 7075 } 7076 7077 BCM_IF_ERROR_RETURN 7078 (_bcm_kt_cosq_index_resolve 7079 (unit, port, cosq, _BCM_KT_COSQ_INDEX_STYLE_UCAST_QUEUE, 7080 &local_port, &startq, &numq)); 7081 7082 mmu_info = _bcm_kt_mmu_info[unit]; 7083 if (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port) || 7084 startq >= mmu_info->num_base_queues) { 7085 /* pass port as queue number */ 7086 local_port = startq; 7087 startq = 0; 7088 } 7089 7090 switch (stat) { 7091 case bcmCosqGportGreenAcceptedPkts: 7092 dma_id = SOC_COUNTER_NON_DMA_COSQ_ACCEPT_PKT_GREEN; 7093 break; 7094 case bcmCosqGportGreenAcceptedBytes: 7095 dma_id = SOC_COUNTER_NON_DMA_COSQ_ACCEPT_BYTE_GREEN; 7096 break; 7097 case bcmCosqGportYellowAcceptedPkts: 7098 dma_id = SOC_COUNTER_NON_DMA_COSQ_ACCEPT_PKT_YELLOW; 7099 break; 7100 case bcmCosqGportYellowAcceptedBytes: 7101 dma_id = SOC_COUNTER_NON_DMA_COSQ_ACCEPT_BYTE_YELLOW; 7102 break; 7103 case bcmCosqGportRedAcceptedPkts: 7104 dma_id = SOC_COUNTER_NON_DMA_COSQ_ACCEPT_PKT_RED; 7105 break; 7106 case bcmCosqGportRedAcceptedBytes: 7107 dma_id = SOC_COUNTER_NON_DMA_COSQ_ACCEPT_BYTE_RED; 7108 break; 7109 case bcmCosqGportReceivedPkts: 7110 dma_id = SOC_COUNTER_NON_DMA_COSQ_ACCEPT_PKT; 7111 break; 7112 case bcmCosqGportReceivedBytes: 7113 dma_id = SOC_COUNTER_NON_DMA_COSQ_ACCEPT_BYTE; 7114 break; 7115 case bcmCosqGportGreenDroppedPkts: 7116 dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_GREEN; 7117 break; 7118 case bcmCosqGportGreenDroppedBytes: 7119 dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE_GREEN; 7120 break; 7121 case bcmCosqGportYellowDroppedPkts: 7122 dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_YELLOW; 7123 break; 7124 case bcmCosqGportYellowDroppedBytes: 7125 dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE_YELLOW; 7126 break; 7127 case bcmCosqGportRedDroppedPkts: 7128 dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_RED; 7129 break; 7130 case bcmCosqGportRedDroppedBytes: 7131 dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE_RED; 7132 break; 7133 case bcmCosqGportDroppedPkts: 7134 dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_PKT; 7135 break; 7136 case bcmCosqGportDroppedBytes: 7137 dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE; 7138 break; 7139 case bcmCosqGportOutPkts: 7140 dma_id = SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT; 7141 break; 7142 case bcmCosqGportOutBytes: 7143 dma_id = SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE; 7144 break; 7145 default: 7146 return BCM_E_PARAM; 7147 } 7148 7149 /* if sync-mode is set, update the software cached counter value, 7150 * with the hardware count and then retrieve the count. 7151 * else return the software cache counter value. 7152 */ 7153 counter_get = (sync_mode == 1)? soc_counter_sync_get: soc_counter_get; 7154 7155 if (!BCM_GPORT_IS_SCHEDULER(port)) { 7156 BCM_IF_ERROR_RETURN 7157 (counter_get(unit, local_port, dma_id, startq, value)); 7158 } else { 7159 COMPILER_64_ZERO(sum); 7160 for (i = 0; i < numq; i++) { 7161 BCM_IF_ERROR_RETURN 7162 (counter_get(unit, local_port, dma_id, startq + i, &value64)); 7163 COMPILER_64_ADD_64(sum, value64); 7164 } 7165 *value = sum; 7166 } 7167 7168 return BCM_E_NONE; 7169 } 7170 7171 int bcm_kt_cosq_port_get(int unit, int queue_id, bcm_port_t *port) 7172 { 7173 _bcm_kt_mmu_info_t *mmu_info; 7174 lls_l0_parent_entry_t l0_parent; 7175 lls_l1_parent_entry_t l1_parent; 7176 lls_l2_parent_entry_t l2_parent; 7177 int index; 7178 7179 if (_bcm_kt_mmu_info[unit] == NULL) { 7180 return BCM_E_INIT; 7181 } 7182 7183 mmu_info = _bcm_kt_mmu_info[unit]; 7184 7185 if (queue_id >= mmu_info->num_queues) { 7186 return BCM_E_PARAM; 7187 } 7188 7189 SOC_IF_ERROR_RETURN 7190 (READ_LLS_L2_PARENTm(unit, MEM_BLOCK_ALL, queue_id, &l2_parent)); 7191 index = soc_mem_field32_get(unit, LLS_L2_PARENTm, &l2_parent, C_PARENTf); 7192 7193 SOC_IF_ERROR_RETURN 7194 (READ_LLS_L1_PARENTm(unit, MEM_BLOCK_ALL, index, &l1_parent)); 7195 index = soc_mem_field32_get(unit, LLS_L1_PARENTm, &l1_parent, C_PARENTf); 7196 7197 SOC_IF_ERROR_RETURN 7198 (READ_LLS_L0_PARENTm(unit, MEM_BLOCK_ALL, index, &l0_parent)); 7199 7200 *port = soc_mem_field32_get(unit, LLS_L0_PARENTm, &l0_parent, C_PARENTf);; 7201 7202 return BCM_E_NONE; 7203 } 7204 7205 #ifdef BCM_WARM_BOOT_SUPPORT 7206 7207 #define BCM_WB_VERSION_1_0 SOC_SCACHE_VERSION(1,0) 7208 #define BCM_WB_VERSION_1_1 SOC_SCACHE_VERSION(1,1) 7209 #define BCM_WB_VERSION_1_2 SOC_SCACHE_VERSION(1,2) 7210 #define BCM_WB_DEFAULT_VERSION BCM_WB_VERSION_1_2 7211 7212 #define _BCM_KT_COSQ_WB_END_NODE_VALUE 0xffffffff 7213 7214 #define _BCM_KT_COSQ_WB_NODE_COSQ_MASK 0x3f /* LW-1 [5:0] */ 7215 #define _BCM_KT_COSQ_WB_NODE_COSQ_SHIFT 0 7216 #define _BCM_KT_COSQ_WB_NODE_NUMQ_MASK 0x3f /* LW-1 [11:6] */ 7217 #define _BCM_KT_COSQ_WB_NODE_NUMQ_SHIFT 6 7218 #define _BCM_KT_COSQ_WB_NODE_HW_INDEX_MASK 0xfff /* LW-1 [23:12] */ 7219 #define _BCM_KT_COSQ_WB_NODE_HW_INDEX_SHIFT 12 7220 #define _BCM_KT_COSQ_WB_NODE_LEVEL_MASK 0x3 /* LW-1 [25:24 */ 7221 #define _BCM_KT_COSQ_WB_NODE_LEVEL_SHIFT 24 7222 #define _BCM_KT_COSQ_WB_NODE_WRR_MASK 0x1 /* LW-1 [27] */ 7223 #define _BCM_KT_COSQ_WB_NODE_WRR_SHIFT 27 7224 7225 #define _BCM_KT_COSQ_WB_NUM_COS_MASK 0xf /* [3:0] */ 7226 #define _BCM_KT_COSQ_WB_NUM_COS_SHIFT 0 7227 7228 #define SET_FIELD(_field, _value) \ 7229 (((_value) & _BCM_KT_COSQ_WB_## _field## _MASK) << \ 7230 _BCM_KT_COSQ_WB_## _field## _SHIFT) 7231 #define GET_FIELD(_field, _byte) \ 7232 (((_byte) >> _BCM_KT_COSQ_WB_## _field## _SHIFT) & \ 7233 _BCM_KT_COSQ_WB_## _field## _MASK) 7234 7235 STATIC int 7236 _bcm_kt_cosq_wb_alloc(int unit) 7237 { 7238 soc_scache_handle_t scache_handle; 7239 uint8 *scache_ptr; 7240 _bcm_kt_mmu_info_t *mmu_info; 7241 int rv, alloc_size; 7242 7243 mmu_info = _bcm_kt_mmu_info[unit]; 7244 7245 alloc_size = 0; 7246 alloc_size += sizeof(mmu_info->num_base_queues); 7247 alloc_size += sizeof(mmu_info->num_ext_queues); 7248 alloc_size += sizeof(mmu_info->qset_size); 7249 alloc_size += sizeof(mmu_info->num_queues); 7250 alloc_size += sizeof(mmu_info->num_nodes); 7251 alloc_size += sizeof(mmu_info->max_nodes); 7252 alloc_size += (_BCM_KT_NUM_TOTAL_SCHEDULERS * sizeof(uint32) * 3); 7253 alloc_size += (_BCM_KT_NUM_L2_QUEUES * sizeof(uint32) * 2); 7254 alloc_size += sizeof(uint32); 7255 /* Storing NUM_COS */ 7256 alloc_size += sizeof(uint8); 7257 /* Storing interface reference count for all queues */ 7258 alloc_size += (BCM_MULTICAST_PORT_MAX * sizeof(uint32)); 7259 7260 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_COSQ, 0); 7261 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, TRUE, alloc_size, 7262 &scache_ptr, BCM_WB_DEFAULT_VERSION, NULL); 7263 if (rv == BCM_E_NOT_FOUND) { 7264 rv = BCM_E_NONE; 7265 } 7266 7267 return rv; 7268 } 7269 7270 /* 7271 * This funtion encodes the 1 byte of the common data to be written in to 7272 * scache.Currently only last 4 bits of the byte are used for storing 7273 * num cos value rest can be used if necessary later. 7274 */ 7275 STATIC void 7276 _bcm_kt_cosq_wb_encode_data(int unit, uint8 *scache_ptr) 7277 { 7278 uint8 data = 0; 7279 int numq = 0; 7280 bcm_kt_cosq_config_get(unit, &numq); 7281 data = SET_FIELD(NUM_COS, numq); 7282 *scache_ptr = data; 7283 } 7284 7285 STATIC uint32 7286 _bcm_kt_cosq_wb_encode_node(int unit, _bcm_kt_cosq_node_t *node) 7287 { 7288 uint32 data = 0; 7289 7290 data = SET_FIELD(NODE_COSQ, node->cosq_attached_to); 7291 data |= SET_FIELD(NODE_NUMQ, node->numq); 7292 data |= SET_FIELD(NODE_LEVEL, node->level); 7293 data |= SET_FIELD(NODE_HW_INDEX, node->hw_index); 7294 data |= SET_FIELD(NODE_WRR, node->wrr_in_use); 7295 7296 return data; 7297 } 7298 7299 int 7300 bcm_kt_cosq_sync(int unit) 7301 { 7302 soc_scache_handle_t scache_handle; 7303 uint8 *scache_ptr, *ptr; 7304 _bcm_kt_mmu_info_t *mmu_info; 7305 _bcm_kt_cosq_node_t *port_node, *l0_node, *l1_node, *l2_node; 7306 bcm_port_t port; 7307 int i; 7308 uint32 node_data; 7309 7310 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_COSQ, 0); 7311 BCM_IF_ERROR_RETURN 7312 (_bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 0, 7313 &scache_ptr, BCM_WB_DEFAULT_VERSION, NULL)); 7314 7315 if (_bcm_kt_mmu_info[unit] == NULL) { 7316 return BCM_E_INIT; 7317 } 7318 7319 mmu_info = _bcm_kt_mmu_info[unit]; 7320 7321 ptr = scache_ptr; 7322 7323 *(((uint32 *)ptr)) = mmu_info->num_base_queues; 7324 ptr += sizeof(uint32); 7325 7326 *(((uint32 *)ptr)) = mmu_info->num_ext_queues; 7327 ptr += sizeof(uint32); 7328 7329 *(((uint32 *)ptr)) = mmu_info->qset_size; 7330 ptr += sizeof(uint32); 7331 7332 *(((uint32 *)ptr)) = mmu_info->num_queues; 7333 ptr += sizeof(uint32); 7334 7335 *(((uint32 *)ptr)) = mmu_info->num_nodes; 7336 ptr += sizeof(uint32); 7337 7338 for (i = 0; i < _BCM_KT_COSQ_NODE_LEVEL_MAX; i++) { 7339 *(((uint32 *)ptr)) = mmu_info->max_nodes[i]; 7340 ptr += sizeof(uint32); 7341 } 7342 7343 PBMP_ALL_ITER(unit, port) { 7344 port_node = &mmu_info->sched_node[port]; 7345 7346 if (port_node->cosq_attached_to < 0) { 7347 continue; 7348 } 7349 7350 if (port_node->child != NULL) { 7351 *(((uint32 *)ptr)) = port_node->gport; 7352 ptr += sizeof(uint32); 7353 7354 node_data = _bcm_kt_cosq_wb_encode_node(unit, port_node); 7355 *(((uint32 *)ptr)) = node_data; 7356 ptr += sizeof(uint32); 7357 7358 *(((uint32 *)ptr)) = port_node->base_index; 7359 ptr += sizeof(uint32); 7360 } 7361 7362 for (l0_node = port_node->child; l0_node != NULL; 7363 l0_node = l0_node->sibling) { 7364 *(((uint32 *)ptr)) = l0_node->gport; 7365 ptr += sizeof(uint32); 7366 7367 node_data = _bcm_kt_cosq_wb_encode_node(unit, l0_node); 7368 *(((uint32 *)ptr)) = node_data; 7369 ptr += sizeof(uint32); 7370 7371 *(((uint32 *)ptr)) = l0_node->base_index; 7372 ptr += sizeof(uint32); 7373 7374 for (l1_node = l0_node->child; l1_node != NULL; 7375 l1_node = l1_node->sibling) { 7376 *(((uint32 *)ptr)) = l1_node->gport; 7377 ptr += sizeof(uint32); 7378 7379 node_data = _bcm_kt_cosq_wb_encode_node(unit, l1_node); 7380 *(((uint32 *)ptr)) = node_data; 7381 ptr += sizeof(uint32); 7382 7383 *(((uint32 *)ptr)) = l1_node->base_index; 7384 ptr += sizeof(uint32); 7385 7386 for (l2_node = l1_node->child; l2_node != NULL; 7387 l2_node = l2_node->sibling) { 7388 *(((uint32 *)ptr)) = l2_node->gport; 7389 ptr += sizeof(uint32); 7390 7391 node_data = _bcm_kt_cosq_wb_encode_node(unit, l2_node); 7392 *(((uint32 *)ptr)) = node_data; 7393 ptr += sizeof(uint32); 7394 7395 } 7396 } 7397 7398 } 7399 7400 } 7401 7402 *(((uint32 *)ptr)) = _BCM_KT_COSQ_WB_END_NODE_VALUE; 7403 ptr += sizeof(uint32); 7404 7405 /* add NUM_COS to the scache */ 7406 _bcm_kt_cosq_wb_encode_data(unit, (uint8 *)ptr); 7407 ptr += sizeof(uint8); 7408 7409 /* copy interface reference count values for all queues into scache ptr */ 7410 sal_memcpy(ptr, mmu_info->intf_ref_cnt, 7411 (sizeof(uint32) * BCM_MULTICAST_PORT_MAX)); 7412 ptr += (sizeof(uint32) * BCM_MULTICAST_PORT_MAX); 7413 7414 return BCM_E_NONE; 7415 } 7416 /* 7417 * Function: 7418 * _bcm_kt_cosq_map_alloc_set 7419 * Purpose: 7420 * Allocate the cosq_map bitmap and 7421 * restore 7422 * Parameters: 7423 * node - (IN) cosq_node 7424 * Returns: 7425 * BCM_E_XXX 7426 */ 7427 STATIC int 7428 _bcm_kt_cosq_map_alloc_set(_bcm_kt_cosq_node_t *node) 7429 { 7430 _bcm_kt_cosq_node_t *child; 7431 int alloc_size; 7432 if (node->cosq_map == NULL) { 7433 alloc_size = SHR_BITALLOCSIZE(node->numq); 7434 node->cosq_map = _bcm_kt_cosq_alloc_clear(alloc_size, 7435 "cosq_map"); 7436 if (node->cosq_map == NULL) { 7437 return BCM_E_MEMORY; 7438 } 7439 } 7440 child = node->child; 7441 while (child != NULL) { 7442 BCM_IF_ERROR_RETURN 7443 (_bcm_kt_cosq_map_index_set(node->cosq_map, 7444 child->cosq_attached_to, 1)); 7445 child = child->sibling; 7446 } 7447 7448 return BCM_E_NONE; 7449 } 7450 7451 /* 7452 * Function: 7453 * _bcm_kt_cosq_map_recover_next_level_node 7454 * Purpose: 7455 * Used to recover cos_map for S0,S1,L0,L1 levels 7456 * Parameters: 7457 * node - (IN) cosq_node 7458 * Returns: 7459 * BCM_E_XXX 7460 */ 7461 7462 7463 STATIC int 7464 _bcm_kt_cosq_map_recover_next_level_node(_bcm_kt_cosq_node_t *node) 7465 { 7466 if (!node) { 7467 return BCM_E_NONE; 7468 } 7469 if (node->level == _BCM_KT_COSQ_NODE_LEVEL_L2) { 7470 return BCM_E_NONE; 7471 } 7472 BCM_IF_ERROR_RETURN(_bcm_kt_cosq_map_alloc_set(node)); 7473 BCM_IF_ERROR_RETURN(_bcm_kt_cosq_map_recover_next_level_node(node->sibling)); 7474 BCM_IF_ERROR_RETURN(_bcm_kt_cosq_map_recover_next_level_node(node->child)); 7475 return BCM_E_NONE; 7476 } 7477 7478 STATIC int 7479 _bcm_set_gport_pair(int unit,_bcm_kt_cosq_node_t *node) 7480 { 7481 7482 _bcm_kt_cosq_node_t *parent = NULL; 7483 _bcm_kt_cosq_node_t *curnode = NULL; 7484 _bcm_kt_mmu_info_t *mmu_info = NULL; 7485 int cosq = 0; 7486 int paircosq = 0; 7487 int numcos = 0; 7488 uint32 encap_id; 7489 7490 BCM_IF_ERROR_RETURN( 7491 bcm_kt_cosq_config_get(unit, &numcos)); 7492 parent = node->parent; 7493 if(!parent) 7494 { 7495 return BCM_E_INTERNAL; 7496 } 7497 cosq = node->cosq_attached_to; 7498 paircosq = (cosq + numcos) % (numcos * 2); 7499 mmu_info = _bcm_kt_mmu_info[unit]; 7500 7501 for(curnode = parent->child; curnode; curnode = curnode->sibling) 7502 { 7503 if (curnode->cosq_attached_to == paircosq) { 7504 encap_id = (BCM_GPORT_SCHEDULER_GET(node->gport) >> 8) & 0x7ff; 7505 mmu_info->l1_gport_pair[encap_id] = curnode->gport; 7506 break; 7507 } 7508 } 7509 return BCM_E_NONE; 7510 } 7511 int 7512 bcm_kt_cosq_reinit(int unit) 7513 { 7514 soc_scache_handle_t scache_handle; 7515 uint8 *scache_ptr, *ptr; 7516 _bcm_kt_cosq_node_t *port_info; 7517 _bcm_kt_mmu_info_t *mmu_info; 7518 _bcm_kt_cosq_node_t *port_node = NULL; 7519 _bcm_kt_cosq_node_t *queue_node = NULL; 7520 _bcm_kt_cosq_node_t *node = NULL; 7521 _bcm_kt_cosq_node_t *l0_node = NULL; 7522 _bcm_kt_cosq_node_t *l1_node = NULL; 7523 _bcm_kt_cosq_node_t *l2_node = NULL; 7524 _bcm_kt_cosq_node_t *curnode = NULL; 7525 _bcm_kt_cosq_node_t *l0node = NULL; 7526 int rv, stable_size = 0; 7527 bcm_port_t port = 0; 7528 bcm_gport_t gport; 7529 int i, index, numq; 7530 uint32 node_data; 7531 uint32 encap_id; 7532 int set_index, cosq; 7533 uint32 entry[SOC_MAX_MEM_WORDS]; 7534 soc_profile_mem_t *profile_mem; 7535 _bcm_kt_cosq_list_t *list; 7536 soc_mem_t mem; 7537 mmu_wred_queue_config_buffer_entry_t qentry; 7538 mmu_wred_queue_config_qentry_entry_t qentry1; 7539 int cpu_hg_index = 0; 7540 uint8 data; 7541 int num_cos = 0; 7542 uint16 recovered_ver = 0; 7543 int additional_scache_size = 0; 7544 uint32 *l0_bmap = NULL; 7545 uint32 *l1_bmap = NULL; 7546 uint32 *l2_bmap = NULL; 7547 7548 7549 SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size)); 7550 if ((stable_size == 0) || (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit))) { 7551 /* COSQ warmboot requires extended scache support i.e. level2 warmboot*/ 7552 return BCM_E_NONE; 7553 } 7554 7555 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_COSQ, 0); 7556 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 0, &scache_ptr, 7557 BCM_WB_DEFAULT_VERSION, &recovered_ver); 7558 if (BCM_FAILURE(rv)) { 7559 return rv; 7560 } 7561 7562 if (_bcm_kt_mmu_info[unit] == NULL) { 7563 return BCM_E_INIT; 7564 } 7565 7566 mmu_info = _bcm_kt_mmu_info[unit]; 7567 7568 ptr = scache_ptr; 7569 7570 mmu_info->num_base_queues = *(((uint32 *)ptr)); 7571 ptr += sizeof(uint32); 7572 7573 mmu_info->num_ext_queues = *(((uint32 *)ptr)); 7574 ptr += sizeof(uint32); 7575 7576 mmu_info->qset_size = *(((uint32 *)ptr)); 7577 ptr += sizeof(uint32); 7578 7579 mmu_info->num_queues = *(((uint32 *)ptr)); 7580 ptr += sizeof(uint32); 7581 7582 mmu_info->num_nodes = *(((uint32 *)ptr)); 7583 ptr += sizeof(uint32); 7584 7585 for (i = 0; i < _BCM_KT_COSQ_NODE_LEVEL_MAX; i++) { 7586 mmu_info->max_nodes[i] = *(((uint32 *)ptr)); 7587 ptr += sizeof(uint32); 7588 } 7589 7590 while (*(((uint32 *)ptr)) != _BCM_KT_COSQ_WB_END_NODE_VALUE) { 7591 gport = *(((uint32 *)ptr)); 7592 ptr += sizeof(uint32); 7593 node_data = *(((uint32 *)ptr)); 7594 ptr += sizeof(uint32); 7595 7596 if (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport)) { 7597 list = &mmu_info->ext_qlist; 7598 encap_id = BCM_GPORT_UCAST_SUBSCRIBER_QUEUE_GROUP_QID_GET(gport); 7599 node = &mmu_info->queue_node[encap_id]; 7600 encap_id -= mmu_info->num_base_queues; 7601 _bcm_kt_node_index_set(list, encap_id, 1); 7602 } else if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 7603 encap_id = BCM_GPORT_UCAST_QUEUE_GROUP_QID_GET(gport); 7604 node = &mmu_info->queue_node[encap_id]; 7605 } else { 7606 encap_id = (BCM_GPORT_SCHEDULER_GET(gport) >> 8) & 0x7ff; 7607 if (encap_id == 0) { 7608 encap_id = (BCM_GPORT_SCHEDULER_GET(gport) & 0xff); 7609 } 7610 list = &mmu_info->sched_list; 7611 _bcm_kt_node_index_set(list, encap_id, 1); 7612 node = &mmu_info->sched_node[encap_id]; 7613 node->first_child = 4095; 7614 node->base_index = *(((uint32 *)ptr)); 7615 ptr += sizeof(uint32); 7616 } 7617 7618 node->gport = gport; 7619 node->numq = GET_FIELD(NODE_NUMQ, node_data); 7620 node->cosq_attached_to = GET_FIELD(NODE_COSQ, node_data); 7621 node->level = GET_FIELD(NODE_LEVEL, node_data); 7622 node->hw_index = GET_FIELD(NODE_HW_INDEX, node_data); 7623 node->wrr_in_use = GET_FIELD(NODE_WRR, node_data); 7624 7625 switch (node->level) { 7626 case _BCM_KT_COSQ_NODE_LEVEL_ROOT: 7627 port_node = node; 7628 port_node->parent = NULL; 7629 port_node->sibling = NULL; 7630 port_node->child = NULL; 7631 break; 7632 7633 case _BCM_KT_COSQ_NODE_LEVEL_L0: 7634 l0_node = node; 7635 list = &mmu_info->l0_sched_list; 7636 7637 if (port_node != NULL) { 7638 l0_node->parent = port_node; 7639 l0_node->sibling = port_node->child; 7640 7641 port_node->child = l0_node; 7642 port_node->num_child++; 7643 7644 if (port_node->numq > 0) { 7645 if (l0_node->hw_index < port_node->first_child) { 7646 port_node->first_child = l0_node->hw_index; 7647 } 7648 if (port_node->num_child == 1) { 7649 _bcm_kt_node_index_set(list, port_node->base_index, port_node->numq); 7650 } 7651 } else { 7652 _bcm_kt_node_index_set(list, l0_node->hw_index, 1); 7653 } 7654 } 7655 break; 7656 7657 case _BCM_KT_COSQ_NODE_LEVEL_L1: 7658 l1_node = node; 7659 list = &mmu_info->l1_sched_list; 7660 if (l0_node != NULL) { 7661 l1_node->parent = l0_node; 7662 l1_node->sibling = l0_node->child; 7663 7664 l0_node->child = l1_node; 7665 l0_node->num_child++; 7666 7667 if (l0_node->numq > 0) { 7668 if (l1_node->hw_index < l0_node->first_child) { 7669 l0_node->first_child = l1_node->hw_index; 7670 } 7671 if (l0_node->num_child == 1) { 7672 _bcm_kt_node_index_set(list, l0_node->base_index, l0_node->numq); 7673 } 7674 } else { 7675 _bcm_kt_node_index_set(list, l1_node->hw_index, 1); 7676 } 7677 } 7678 break; 7679 7680 case _BCM_KT_COSQ_NODE_LEVEL_L2: 7681 queue_node = node; 7682 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 7683 list = &mmu_info->l2_base_qlist; 7684 } else { 7685 list = &mmu_info->l2_ext_qlist; 7686 } 7687 if (l1_node != NULL) { 7688 queue_node->parent = l1_node; 7689 queue_node->sibling = l1_node->child; 7690 queue_node->hw_index = GET_FIELD(NODE_HW_INDEX, node_data); 7691 l1_node->child = queue_node; 7692 l1_node->num_child++; 7693 7694 if (l1_node->numq > 0) { 7695 if (queue_node->hw_index < l1_node->first_child) { 7696 l1_node->first_child = queue_node->hw_index; 7697 } 7698 if (l1_node->num_child == 1) { 7699 _bcm_kt_node_index_set(list, l1_node->base_index, l1_node->numq); 7700 } 7701 } else { 7702 _bcm_kt_node_index_set(list, queue_node->hw_index, 1); 7703 } 7704 } 7705 break; 7706 7707 default: 7708 break; 7709 } 7710 } 7711 7712 /* Update PORT_COS_MAP memory profile reference counter */ 7713 profile_mem = _bcm_kt_cos_map_profile[unit]; 7714 PBMP_ALL_ITER(unit, port) { 7715 SOC_IF_ERROR_RETURN 7716 (soc_mem_read(unit, COS_MAP_SELm, MEM_BLOCK_ALL, port, &entry)); 7717 set_index = soc_mem_field32_get(unit, COS_MAP_SELm, &entry, SELECTf); 7718 SOC_IF_ERROR_RETURN 7719 (soc_profile_mem_reference(unit, profile_mem, set_index * 16, 16)); 7720 } 7721 7722 cpu_hg_index = SOC_IS_KATANA2(unit) ? 7723 SOC_INFO(unit).cpu_hg_pp_port_index : 7724 SOC_INFO(unit).cpu_hg_index; 7725 if (cpu_hg_index != -1) { 7726 SOC_IF_ERROR_RETURN(soc_mem_read(unit, COS_MAP_SELm, MEM_BLOCK_ALL, 7727 cpu_hg_index, &entry)); 7728 set_index = soc_mem_field32_get(unit, COS_MAP_SELm, &entry, SELECTf); 7729 SOC_IF_ERROR_RETURN 7730 (soc_profile_mem_reference(unit, profile_mem, set_index, 1)); 7731 } 7732 7733 /* Update MMU_WRED_DROP_CURVE_PROFILE_x memory profile reference counter */ 7734 profile_mem = _bcm_kt_wred_profile[unit]; 7735 PBMP_PORT_ITER(unit, port) { 7736 /* 7737 * Wred data can be in two tables depending on packet based or byte bases 7738 * we scan both and update the software profile 7739 */ 7740 BCM_IF_ERROR_RETURN 7741 (_bcm_kt_cosq_index_resolve(unit, port, -1, 7742 _BCM_KT_COSQ_INDEX_STYLE_WRED, NULL, 7743 NULL, &numq)); 7744 for (cosq = 0; cosq < numq; cosq++) { 7745 BCM_IF_ERROR_RETURN 7746 (_bcm_kt_cosq_index_resolve(unit, port, cosq, 7747 _BCM_KT_COSQ_INDEX_STYLE_WRED, 7748 NULL, &index, NULL)); 7749 /* scan byte based wred table */ 7750 mem = MMU_WRED_QUEUE_CONFIG_BUFFERm; 7751 SOC_IF_ERROR_RETURN 7752 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, index, &qentry)); 7753 set_index = soc_mem_field32_get(unit, mem, &qentry, PROFILE_INDEXf); 7754 SOC_IF_ERROR_RETURN 7755 (soc_profile_mem_reference(unit, profile_mem, set_index, 1)); 7756 7757 /* scan packet based wred table */ 7758 mem = MMU_WRED_QUEUE_CONFIG_QENTRYm; 7759 set_index = 0; 7760 memset(&qentry1, 0, sizeof(mmu_wred_queue_config_qentry_entry_t)); 7761 7762 SOC_IF_ERROR_RETURN 7763 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, index, &qentry1)); 7764 set_index = soc_mem_field32_get(unit, mem, &qentry1, PROFILE_INDEXf); 7765 SOC_IF_ERROR_RETURN 7766 (soc_profile_mem_reference(unit, profile_mem, set_index, 1)); 7767 } 7768 } 7769 /* Restoring the cosq_map */ 7770 PBMP_ALL_ITER(unit, port) { 7771 /* root node */ 7772 port_info = &mmu_info->sched_node[port]; 7773 node = NULL; 7774 if (port_info->gport >= 0) { 7775 BCM_IF_ERROR_RETURN( 7776 _bcm_kt_cosq_node_get(unit, port_info->gport, 7777 NULL, NULL, NULL, &node)); 7778 if (node != NULL) { 7779 BCM_IF_ERROR_RETURN( 7780 _bcm_kt_cosq_map_recover_next_level_node(node)); 7781 } 7782 } 7783 } 7784 /* 7785 * The following will recover the L1 gport pair 7786 * if the dynamic sched update feature is enabled 7787 */ 7788 if (soc_feature(unit, soc_feature_dynamic_sched_update)) 7789 { 7790 PBMP_ALL_ITER(unit, port) { 7791 port_info = &mmu_info->sched_node[port]; 7792 if (port_info->gport >= 0) { 7793 BCM_IF_ERROR_RETURN( 7794 _bcm_kt_cosq_node_get(unit, port_info->gport, 7795 NULL, NULL, NULL, &node)); 7796 if (node->child) { 7797 l0node = node->child; 7798 /*The curnode is always L1 here*/ 7799 for (curnode = l0node->child; curnode; 7800 curnode = curnode->sibling ) { 7801 _bcm_set_gport_pair(unit, curnode); 7802 } 7803 } 7804 } 7805 } 7806 } 7807 /* Recover NUM_COS */ 7808 if (recovered_ver >= BCM_WB_VERSION_1_1) { 7809 ptr += sizeof(uint32); 7810 data = *((uint8 *) ptr); 7811 num_cos = GET_FIELD(NUM_COS, data); 7812 if (_bcm_kt_num_cosq[unit] == 0) { 7813 return BCM_E_INIT; 7814 } 7815 _bcm_kt_num_cosq[unit] = num_cos; 7816 } else { 7817 additional_scache_size += sizeof(uint8); 7818 } 7819 7820 if (recovered_ver >= BCM_WB_VERSION_1_2) { 7821 ptr += sizeof(uint8); 7822 /* Update interface reference count values for all queues */ 7823 sal_memcpy(mmu_info->intf_ref_cnt, ptr, 7824 (sizeof(uint32) * BCM_MULTICAST_PORT_MAX)); 7825 ptr += (sizeof(uint32) * BCM_MULTICAST_PORT_MAX); 7826 } else { 7827 /* Extra memory to store interface ref count of queues */ 7828 additional_scache_size += (sizeof(uint32) * BCM_MULTICAST_PORT_MAX); 7829 } 7830 7831 if (additional_scache_size > 0) { 7832 BCM_IF_ERROR_RETURN( 7833 soc_scache_realloc(unit, scache_handle, additional_scache_size)); 7834 } 7835 7836 for (port = CMIC_PORT(unit); port < (LB_PORT(unit)+1); port++) { 7837 l0_bmap = SOC_CONTROL(unit)->port_lls_l0_bmap[port]; 7838 l1_bmap = SOC_CONTROL(unit)->port_lls_l1_bmap[port]; 7839 l2_bmap = SOC_CONTROL(unit)->port_lls_l2_bmap[port]; 7840 port_node = &mmu_info->sched_node[port]; 7841 7842 if (port_node->cosq_attached_to < 0) { 7843 continue; 7844 } 7845 7846 7847 for (l0_node = port_node->child; l0_node != NULL; 7848 l0_node = l0_node->sibling) { 7849 _BCM_COSQ_PARENT_BMAP_SET(l0_bmap, l0_node->hw_index); 7850 for (l1_node = l0_node->child; l1_node != NULL; 7851 l1_node = l1_node->sibling) { 7852 _BCM_COSQ_PARENT_BMAP_SET(l1_bmap, l1_node->hw_index); 7853 for (l2_node = l1_node->child; l2_node != NULL; 7854 l2_node = l2_node->sibling) { 7855 _BCM_COSQ_PARENT_BMAP_SET(l2_bmap, l2_node->hw_index); 7856 } 7857 } 7858 } 7859 } 7860 7861 7862 return BCM_E_NONE; 7863 } 7864 7865 #endif /* BCM_WARM_BOOT_SUPPORT */ 7866 7867 /* 7868 * Function: 7869 * bcm_kt_cosq_init 7870 * Purpose: 7871 * Initialize (clear) all COS schedule/mapping state. 7872 * Parameters: 7873 * unit - unit number 7874 * Returns: 7875 * BCM_E_XXX 7876 */ 7877 int 7878 bcm_kt_cosq_init(int unit) 7879 { 7880 soc_info_t *si; 7881 STATIC int _kt_max_cosq = -1; 7882 int cosq, numq, alloc_size; 7883 bcm_port_t port; 7884 soc_reg_t mem; 7885 STATIC soc_mem_t wred_mems[6] = { 7886 MMU_WRED_DROP_CURVE_PROFILE_0m, MMU_WRED_DROP_CURVE_PROFILE_1m, 7887 MMU_WRED_DROP_CURVE_PROFILE_2m, MMU_WRED_DROP_CURVE_PROFILE_3m, 7888 MMU_WRED_DROP_CURVE_PROFILE_4m, MMU_WRED_DROP_CURVE_PROFILE_5m 7889 }; 7890 int entry_words[6]; 7891 mmu_wred_drop_curve_profile_0_entry_t entry_tcp_green; 7892 mmu_wred_drop_curve_profile_1_entry_t entry_tcp_yellow; 7893 mmu_wred_drop_curve_profile_2_entry_t entry_tcp_red; 7894 mmu_wred_drop_curve_profile_3_entry_t entry_nontcp_green; 7895 mmu_wred_drop_curve_profile_4_entry_t entry_nontcp_yellow; 7896 mmu_wred_drop_curve_profile_5_entry_t entry_nontcp_red; 7897 void *entries[6]; 7898 uint32 profile_index, rval; 7899 _bcm_kt_mmu_info_t *mmu_info_p; 7900 int i, cmc; 7901 bcm_gport_t port_sched, l0_sched, l1_sched, queue; 7902 uint32 max_threshold, min_threshold; 7903 int num_queues, num_inputs; 7904 int num_base_queues = 0; 7905 7906 if (_kt_max_cosq < 0) { 7907 _kt_max_cosq = NUM_COS(unit); 7908 NUM_COS(unit) = 8; 7909 } 7910 7911 if (!SOC_WARM_BOOT(unit)) { /* Cold Boot */ 7912 BCM_IF_ERROR_RETURN (bcm_kt_cosq_detach(unit, 0)); 7913 } 7914 7915 numq = soc_property_get(unit, spn_BCM_NUM_COS, BCM_COS_DEFAULT); 7916 7917 if (numq < 1) { 7918 numq = 1; 7919 } else if (numq > 8) { 7920 numq = 8; 7921 } 7922 7923 /* Create profile for PORT_COS_MAP table */ 7924 if (_bcm_kt_cos_map_profile[unit] == NULL) { 7925 _bcm_kt_cos_map_profile[unit] = sal_alloc(sizeof(soc_profile_mem_t), 7926 "COS_MAP Profile Mem"); 7927 if (_bcm_kt_cos_map_profile[unit] == NULL) { 7928 return BCM_E_MEMORY; 7929 } 7930 soc_profile_mem_t_init(_bcm_kt_cos_map_profile[unit]); 7931 } 7932 mem = PORT_COS_MAPm; 7933 entry_words[0] = sizeof(port_cos_map_entry_t) / sizeof(uint32); 7934 BCM_IF_ERROR_RETURN(soc_profile_mem_create(unit, &mem, entry_words, 1, 7935 _bcm_kt_cos_map_profile[unit])); 7936 7937 /* Create profile for MMU_WRED_DROP_CURVE_PROFILE_x tables */ 7938 if (_bcm_kt_wred_profile[unit] == NULL) { 7939 _bcm_kt_wred_profile[unit] = sal_alloc(sizeof(soc_profile_mem_t), 7940 "WRED Profile Mem"); 7941 if (_bcm_kt_wred_profile[unit] == NULL) { 7942 return BCM_E_MEMORY; 7943 } 7944 soc_profile_mem_t_init(_bcm_kt_wred_profile[unit]); 7945 } 7946 entry_words[0] = 7947 sizeof(mmu_wred_drop_curve_profile_0_entry_t) / sizeof(uint32); 7948 entry_words[1] = 7949 sizeof(mmu_wred_drop_curve_profile_1_entry_t) / sizeof(uint32); 7950 entry_words[2] = 7951 sizeof(mmu_wred_drop_curve_profile_2_entry_t) / sizeof(uint32); 7952 entry_words[3] = 7953 sizeof(mmu_wred_drop_curve_profile_3_entry_t) / sizeof(uint32); 7954 entry_words[4] = 7955 sizeof(mmu_wred_drop_curve_profile_4_entry_t) / sizeof(uint32); 7956 entry_words[5] = 7957 sizeof(mmu_wred_drop_curve_profile_5_entry_t) / sizeof(uint32); 7958 BCM_IF_ERROR_RETURN(soc_profile_mem_create(unit, wred_mems, entry_words, 6, 7959 _bcm_kt_wred_profile[unit])); 7960 7961 alloc_size = sizeof(_bcm_kt_mmu_info_t) * 1; 7962 if (_bcm_kt_mmu_info[unit] == NULL) { 7963 _bcm_kt_mmu_info[unit] = 7964 sal_alloc(alloc_size, "_bcm_kt_mmu_info"); 7965 7966 if (_bcm_kt_mmu_info[unit] == NULL) { 7967 return BCM_E_MEMORY; 7968 } 7969 } else { 7970 _bcm_kt_cosq_free_memory(_bcm_kt_mmu_info[unit]); 7971 } 7972 7973 sal_memset(_bcm_kt_mmu_info[unit], 0, alloc_size); 7974 7975 mmu_info_p = _bcm_kt_mmu_info[unit]; 7976 if (soc_feature(unit, soc_feature_ddr3)) { 7977 mmu_info_p->num_queues = soc_mem_index_count(unit, LLS_L2_PARENTm); 7978 } else { 7979 /* restrict to maximum 1K queues */ 7980 mmu_info_p->num_queues = 1024; 7981 } 7982 7983 mmu_info_p->max_nodes[_BCM_KT_COSQ_NODE_LEVEL_ROOT] = soc_mem_index_count(unit, LLS_PORT_CONFIGm); 7984 mmu_info_p->max_nodes[_BCM_KT_COSQ_NODE_LEVEL_L0] = soc_mem_index_count(unit, LLS_L0_CONFIGm); 7985 mmu_info_p->max_nodes[_BCM_KT_COSQ_NODE_LEVEL_L1] = soc_mem_index_count(unit, LLS_L1_CONFIGm); 7986 mmu_info_p->max_nodes[_BCM_KT_COSQ_NODE_LEVEL_L2] = mmu_info_p->num_queues; 7987 7988 mmu_info_p->num_nodes = 0; 7989 7990 if (!soc_feature(unit, soc_feature_ddr3)) { 7991 mmu_info_p->max_nodes[_BCM_KT_COSQ_NODE_LEVEL_L0] /= 2; /* 512 */ 7992 mmu_info_p->max_nodes[_BCM_KT_COSQ_NODE_LEVEL_L1] /= 2; /* 128 */ 7993 } 7994 7995 for (i=0; i<_BCM_KT_COSQ_NODE_LEVEL_L2; i++) { 7996 mmu_info_p->num_nodes += mmu_info_p->max_nodes[i]; 7997 } 7998 7999 mmu_info_p->port = _bcm_kt_cosq_alloc_clear((_BCM_KT_NUM_PORT_SCHEDULERS * 8000 sizeof(_bcm_kt_cosq_port_info_t)), 8001 "port_info"); 8002 if (mmu_info_p->port == NULL) { 8003 _bcm_kt_cosq_free_memory(mmu_info_p); 8004 return BCM_E_MEMORY; 8005 } 8006 8007 si = &SOC_INFO(unit); 8008 8009 for (port=0;port < (si->lb_port+1);port++) { 8010 if (!SOC_PBMP_MEMBER((PBMP_ALL(unit)), port)) { 8011 if (SOC_IS_KATANA(unit)) { 8012 continue; 8013 } 8014 } 8015 mmu_info_p->port[port].q_offset = si->port_cosq_base[port]; 8016 mmu_info_p->port[port].q_limit = si->port_cosq_base[port] + 8017 si->port_num_uc_cosq[port]; 8018 8019 SOC_IF_ERROR_RETURN(READ_ING_COS_MODEr(unit, port, &rval)); 8020 soc_reg_field_set(unit, ING_COS_MODEr, &rval, BASE_QUEUE_NUMf, 8021 mmu_info_p->port[port].q_offset); 8022 if (IS_HG_PORT(unit, port)) { 8023 soc_reg_field_set(unit, ING_COS_MODEr, &rval, COS_MODEf, 2); 8024 } 8025 SOC_IF_ERROR_RETURN(WRITE_ING_COS_MODEr(unit, port, rval)); 8026 8027 if (SOC_IS_KATANA(unit)) { 8028 SOC_IF_ERROR_RETURN(READ_RQE_PORT_CONFIGr(unit, port, &rval)); 8029 soc_reg_field_set(unit, RQE_PORT_CONFIGr, &rval, BASE_QUEUEf, 8030 mmu_info_p->port[port].q_offset); 8031 if (IS_EXT_MEM_PORT(unit, port)) { 8032 soc_reg_field_set(unit, RQE_PORT_CONFIGr, &rval, BUFF_TYPEf, 1); 8033 } 8034 if (IS_HG_PORT(unit, port)) { 8035 soc_reg_field_set(unit, RQE_PORT_CONFIGr, &rval, COS_MODEf, 2); 8036 } 8037 SOC_IF_ERROR_RETURN(WRITE_RQE_PORT_CONFIGr(unit, port, rval)); 8038 8039 rval = 0; 8040 soc_reg_field_set(unit, OP_E2ECC_PORT_CONFIGr, &rval, BASE_QUEUEf, 8041 mmu_info_p->port[port].q_offset); 8042 if (IS_EXT_MEM_PORT(unit, port)) { 8043 soc_reg_field_set(unit, OP_E2ECC_PORT_CONFIGr, &rval, 8044 BUFF_TYPEf, 1); 8045 } 8046 SOC_IF_ERROR_RETURN(WRITE_OP_E2ECC_PORT_CONFIGr(unit, port, rval)); 8047 } 8048 8049 #if defined (BCM_KATANA2_SUPPORT) 8050 if (SOC_IS_KATANA2(unit)) { 8051 SOC_IF_ERROR_RETURN(READ_RQE_PP_PORT_CONFIGr(unit, port, &rval)); 8052 soc_reg_field_set(unit, RQE_PP_PORT_CONFIGr, &rval, BASE_QUEUEf, 8053 mmu_info_p->port[port].q_offset); 8054 if (IS_EXT_MEM_PORT(unit, port)) { 8055 soc_reg_field_set(unit, RQE_PP_PORT_CONFIGr, 8056 &rval, BUFF_TYPEf, 1); 8057 } 8058 if (IS_HG_PORT(unit, port)) { 8059 soc_reg_field_set(unit, RQE_PP_PORT_CONFIGr, 8060 &rval, COS_MODEf, 2); 8061 } 8062 SOC_IF_ERROR_RETURN(WRITE_RQE_PP_PORT_CONFIGr(unit, port, rval)); 8063 8064 for (i = mmu_info_p->port[port].q_offset; 8065 i <= (mmu_info_p->port[port].q_offset + 8066 mmu_info_p->port[port].q_limit); i++) { 8067 SOC_IF_ERROR_RETURN (soc_mem_field32_modify(unit, 8068 EGR_QUEUE_TO_PP_PORT_MAPm, i, PP_PORTf,port)); 8069 } 8070 } 8071 #endif 8072 num_base_queues = mmu_info_p->port[port].q_limit; 8073 } 8074 8075 mmu_info_p->num_base_queues = soc_property_get(unit, spn_MMU_MAX_CLASSIC_QUEUES, 8076 num_base_queues); 8077 mmu_info_p->num_ext_queues = mmu_info_p->num_queues - mmu_info_p->num_base_queues; 8078 mmu_info_p->qset_size = soc_property_get(unit, spn_MMU_SUBSCRIBER_NUM_COS_LEVEL, 1); 8079 8080 /* Config variable defining 8081 * the number of pre reserved subscriber queues 8082 * spn_MMU_NUM_SUBSCRIBER_QUEUES 8083 */ 8084 mmu_info_p->num_sub_queues = soc_property_get(unit, 8085 spn_MMU_NUM_SUBSCRIBER_QUEUES, 8086 0); 8087 mmu_info_p->l1_gport_pair = _bcm_kt_cosq_alloc_clear((mmu_info_p->num_nodes * 8088 sizeof(bcm_gport_t)), 8089 "l1_pair_info"); 8090 if (mmu_info_p->l1_gport_pair == NULL) { 8091 _bcm_kt_cosq_free_memory(mmu_info_p); 8092 return BCM_E_MEMORY; 8093 } 8094 8095 mmu_info_p->ext_qlist.bits = _bcm_kt_cosq_alloc_clear(SHR_BITALLOCSIZE(mmu_info_p->num_ext_queues), 8096 "ext_qlist"); 8097 if (mmu_info_p->ext_qlist.bits == NULL) { 8098 _bcm_kt_cosq_free_memory(mmu_info_p); 8099 return BCM_E_MEMORY; 8100 } 8101 8102 mmu_info_p->sched_list.bits = _bcm_kt_cosq_alloc_clear(SHR_BITALLOCSIZE(mmu_info_p->num_nodes), 8103 "sched_list"); 8104 if (mmu_info_p->sched_list.bits == NULL) { 8105 _bcm_kt_cosq_free_memory(mmu_info_p); 8106 return BCM_E_MEMORY; 8107 } 8108 8109 mmu_info_p->l0_sched_list.bits = _bcm_kt_cosq_alloc_clear(SHR_BITALLOCSIZE 8110 (mmu_info_p->max_nodes[_BCM_KT_COSQ_NODE_LEVEL_L0]), 8111 "l0_sched_list"); 8112 if (mmu_info_p->l0_sched_list.bits == NULL) { 8113 _bcm_kt_cosq_free_memory(mmu_info_p); 8114 return BCM_E_MEMORY; 8115 } 8116 8117 mmu_info_p->l1_sched_list.bits = _bcm_kt_cosq_alloc_clear(SHR_BITALLOCSIZE 8118 (mmu_info_p->max_nodes[_BCM_KT_COSQ_NODE_LEVEL_L1]), 8119 "l1_sched_list"); 8120 if (mmu_info_p->l1_sched_list.bits == NULL) { 8121 _bcm_kt_cosq_free_memory(mmu_info_p); 8122 return BCM_E_MEMORY; 8123 } 8124 8125 mmu_info_p->l2_base_qlist.bits = _bcm_kt_cosq_alloc_clear(SHR_BITALLOCSIZE(mmu_info_p->num_base_queues), 8126 "l2_base_qlist"); 8127 if (mmu_info_p->l2_base_qlist.bits == NULL) { 8128 _bcm_kt_cosq_free_memory(mmu_info_p); 8129 return BCM_E_MEMORY; 8130 } 8131 8132 mmu_info_p->l2_ext_qlist.bits = _bcm_kt_cosq_alloc_clear(SHR_BITALLOCSIZE(mmu_info_p->num_ext_queues), 8133 "l2_ext_qlist"); 8134 if (mmu_info_p->l2_ext_qlist.bits == NULL) { 8135 _bcm_kt_cosq_free_memory(mmu_info_p); 8136 return BCM_E_MEMORY; 8137 } 8138 8139 for (i = 0; i < _BCM_KT_NUM_TOTAL_SCHEDULERS; i++) { 8140 _BCM_KT_COSQ_LIST_NODE_INIT(mmu_info_p->sched_node, i); 8141 } 8142 8143 for (i = 0; i < _BCM_KT_NUM_L2_QUEUES; i++) { 8144 _BCM_KT_COSQ_LIST_NODE_INIT(mmu_info_p->queue_node, i); 8145 } 8146 8147 /* reserve last entry of L0 and L1 nodes */ 8148 BCM_IF_ERROR_RETURN 8149 (_bcm_kt_node_index_set(&mmu_info_p->l0_sched_list, 8150 (mmu_info_p->max_nodes[_BCM_KT_COSQ_NODE_LEVEL_L0] - 1), 1)); 8151 BCM_IF_ERROR_RETURN 8152 (_bcm_kt_node_index_set(&mmu_info_p->l1_sched_list, 8153 (mmu_info_p->max_nodes[_BCM_KT_COSQ_NODE_LEVEL_L1] - 1), 1)); 8154 8155 if (mmu_info_p->num_sub_queues) { 8156 mmu_info_p->base_sub_queue = mmu_info_p->num_base_queues; 8157 mmu_info_p->sub_qlist.bits = _bcm_kt_cosq_alloc_clear( 8158 SHR_BITALLOCSIZE(mmu_info_p->num_sub_queues), 8159 "sub_qlist"); 8160 if (mmu_info_p->sub_qlist.bits == NULL) { 8161 _bcm_kt_cosq_free_memory(mmu_info_p); 8162 return BCM_E_MEMORY; 8163 } 8164 8165 mmu_info_p->l2_sub_qlist.bits = _bcm_kt_cosq_alloc_clear( 8166 SHR_BITALLOCSIZE 8167 (mmu_info_p->num_sub_queues), 8168 "l2_sub_qlist"); 8169 8170 if (mmu_info_p->l2_sub_qlist.bits == NULL) { 8171 _bcm_kt_cosq_free_memory(mmu_info_p); 8172 return BCM_E_MEMORY; 8173 } 8174 8175 BCM_IF_ERROR_RETURN 8176 (_bcm_kt_node_index_set(&mmu_info_p->l2_ext_qlist, 8177 mmu_info_p->base_sub_queue, 8178 mmu_info_p->num_sub_queues)); 8179 BCM_IF_ERROR_RETURN 8180 (_bcm_kt_node_index_set(&mmu_info_p->ext_qlist, 8181 mmu_info_p->base_sub_queue, 8182 mmu_info_p->num_sub_queues)); 8183 8184 } else { 8185 mmu_info_p->base_sub_queue = 0; 8186 } 8187 8188 8189 if (!SOC_WARM_BOOT(unit)) { /* Cold Boot */ 8190 8191 for (port=0;port < (si->lb_port+1);port++) { 8192 if (!SOC_PBMP_MEMBER((PBMP_ALL(unit)), port)) { 8193 if (SOC_IS_KATANA(unit)) { 8194 continue; 8195 } 8196 } 8197 if (IS_CPU_PORT(unit, port)) { 8198 BCM_IF_ERROR_RETURN 8199 (bcm_kt_cosq_gport_add(unit, port, SOC_CMCS_NUM(unit), 8200 0, &port_sched)); 8201 for (cmc = 0; cmc < SOC_CMCS_NUM(unit); cmc++) { 8202 if (NUM_CPU_ARM_COSQ(unit, cmc) == 0) { 8203 continue; 8204 } 8205 cosq = (NUM_CPU_ARM_COSQ(unit, cmc) + 7) / 8; 8206 /* coverity[uninit_use_in_call] */ 8207 BCM_IF_ERROR_RETURN 8208 (bcm_kt_cosq_gport_add(unit, port, cosq, 8209 BCM_COSQ_GPORT_SCHEDULER, &l0_sched)); 8210 BCM_IF_ERROR_RETURN 8211 (bcm_kt_cosq_gport_attach(unit, l0_sched, port_sched, cmc)); 8212 cosq = 0; 8213 num_queues = NUM_CPU_ARM_COSQ(unit, cmc); 8214 for (i = 0; i < NUM_CPU_ARM_COSQ(unit, cmc); i++) { 8215 if (i % 8 == 0) { 8216 num_inputs = (num_queues >= 8) ? 8 : num_queues; 8217 BCM_IF_ERROR_RETURN 8218 (bcm_kt_cosq_gport_add(unit, port, num_inputs, 8219 BCM_COSQ_GPORT_SCHEDULER, &l1_sched)); 8220 BCM_IF_ERROR_RETURN 8221 (bcm_kt_cosq_gport_attach(unit, l1_sched, l0_sched, cosq)); 8222 cosq++; 8223 num_queues -= num_inputs; 8224 } 8225 BCM_IF_ERROR_RETURN 8226 (bcm_kt_cosq_gport_add(unit, port, 1, 8227 BCM_COSQ_GPORT_UCAST_QUEUE_GROUP, &queue)); 8228 BCM_IF_ERROR_RETURN 8229 (bcm_kt_cosq_gport_attach(unit, queue, l1_sched, (i % 8))); 8230 8231 } 8232 } 8233 } else { 8234 if (!soc_feature(unit, soc_feature_dynamic_sched_update)) { 8235 BCM_IF_ERROR_RETURN 8236 (bcm_kt_cosq_gport_add(unit, port, 1, 0, &port_sched)); 8237 /* coverity[uninit_use_in_call] */ 8238 BCM_IF_ERROR_RETURN 8239 (bcm_kt_cosq_gport_add(unit, port, 1, BCM_COSQ_GPORT_SCHEDULER, 8240 &l0_sched)); 8241 BCM_IF_ERROR_RETURN 8242 (bcm_kt_cosq_gport_attach(unit, l0_sched, port_sched, 0)); 8243 BCM_IF_ERROR_RETURN 8244 (bcm_kt_cosq_gport_add(unit, port, numq, BCM_COSQ_GPORT_SCHEDULER, 8245 &l1_sched)); 8246 BCM_IF_ERROR_RETURN 8247 (bcm_kt_cosq_gport_attach(unit, l1_sched, l0_sched, 0)); 8248 for (cosq = 0; cosq < numq; cosq++) { 8249 BCM_IF_ERROR_RETURN 8250 (bcm_kt_cosq_gport_add(unit, port, 1, 8251 BCM_COSQ_GPORT_UCAST_QUEUE_GROUP, &queue)); 8252 BCM_IF_ERROR_RETURN 8253 (bcm_kt_cosq_gport_attach(unit, queue, l1_sched, cosq)); 8254 8255 } 8256 } else { 8257 BCM_IF_ERROR_RETURN 8258 (_bcm_kt_cosq_dynamic_hierarchy_create(unit, port, numq)); 8259 } 8260 } 8261 } 8262 8263 } 8264 8265 if (!cosq_sync_lock[unit]) { 8266 cosq_sync_lock[unit] = sal_mutex_create("KT cosq sync lock"); 8267 if (cosq_sync_lock[unit] == NULL) { 8268 return BCM_E_MEMORY; 8269 } 8270 } 8271 8272 /* Add default entries for PORT_COS_MAP memory profile */ 8273 BCM_IF_ERROR_RETURN(bcm_kt_cosq_config_set(unit, numq)); 8274 8275 #ifdef BCM_WARM_BOOT_SUPPORT 8276 if (SOC_WARM_BOOT(unit)) { 8277 return bcm_kt_cosq_reinit(unit); 8278 } else { 8279 BCM_IF_ERROR_RETURN(_bcm_kt_cosq_wb_alloc(unit)); 8280 } 8281 #endif /* BCM_WARM_BOOT_SUPPORT */ 8282 8283 8284 sal_memset(&entry_tcp_green, 0, sizeof(entry_tcp_green)); 8285 sal_memset(&entry_tcp_yellow, 0, sizeof(entry_tcp_yellow)); 8286 sal_memset(&entry_tcp_red, 0, sizeof(entry_tcp_red)); 8287 sal_memset(&entry_nontcp_green, 0, sizeof(entry_nontcp_green)); 8288 sal_memset(&entry_nontcp_yellow, 0, sizeof(entry_nontcp_yellow)); 8289 sal_memset(&entry_nontcp_red, 0, sizeof(entry_nontcp_red)); 8290 entries[0] = &entry_tcp_green; 8291 entries[1] = &entry_tcp_yellow; 8292 entries[2] = &entry_tcp_red; 8293 entries[3] = &entry_nontcp_green; 8294 entries[4] = &entry_nontcp_yellow; 8295 entries[5] = &entry_nontcp_red; 8296 max_threshold = (1 << soc_mem_field_length(unit, MMU_WRED_DROP_CURVE_PROFILE_0m, 8297 MAX_THDf)) - 1; 8298 min_threshold = (1 << soc_mem_field_length(unit, MMU_WRED_DROP_CURVE_PROFILE_0m, 8299 MIN_THDf)) - 1; 8300 for (i = 0; i < 6; i++) { 8301 soc_mem_field32_set(unit, wred_mems[i], entries[i], MIN_THDf, 8302 max_threshold); 8303 soc_mem_field32_set(unit, wred_mems[i], entries[i], MAX_THDf, 8304 min_threshold); 8305 } 8306 profile_index = 0xffffffff; 8307 for (port=0;port < (si->lb_port+1);port++) { 8308 if (!SOC_PBMP_MEMBER((PBMP_ALL(unit)), port)) { 8309 if (SOC_IS_KATANA(unit)) { 8310 continue; 8311 } 8312 } 8313 BCM_IF_ERROR_RETURN 8314 (_bcm_kt_cosq_index_resolve(unit, port, -1, 8315 _BCM_KT_COSQ_INDEX_STYLE_WRED, NULL, 8316 NULL, &numq)); 8317 for (cosq = 0; cosq < numq; cosq++) { 8318 if (profile_index == 0xffffffff) { 8319 BCM_IF_ERROR_RETURN 8320 (soc_profile_mem_add(unit, _bcm_kt_wred_profile[unit], 8321 entries, 1, &profile_index)); 8322 } else { 8323 BCM_IF_ERROR_RETURN 8324 (soc_profile_mem_reference(unit, 8325 _bcm_kt_wred_profile[unit], 8326 profile_index, 0)); 8327 } 8328 } 8329 } 8330 /* 8331 * Set all CPU queues to disable enqueue. Enqueue will be enabled when 8332 * RX DMA is enabled. This is to prevent packets from getting wedged in 8333 * the CMIC when they don't have a means of egressing from the CMIC. 8334 */ 8335 if (!(SAL_BOOT_SIMULATION) && !SOC_IS_RCPU_ONLY(unit)) { 8336 for (i = 0; i < NUM_CPU_COSQ(unit); i++) { 8337 rval = 0; 8338 soc_reg_field_set(unit, TOQ_QUEUE_FLUSH0r, &rval, Q_FLUSH_ID0f, i); 8339 soc_reg_field_set(unit, TOQ_QUEUE_FLUSH0r, &rval, Q_FLUSH_NUMf, 1); 8340 if (SOC_PBMP_MEMBER (PBMP_EXT_MEM (unit), CMIC_PORT(unit))) { 8341 soc_reg_field_set(unit, TOQ_QUEUE_FLUSH0r, &rval, Q_FLUSH_EXTERNALf, 1); 8342 } 8343 soc_reg_field_set(unit, 8344 TOQ_QUEUE_FLUSH0r, &rval, Q_FLUSH_ACTIVEf, 1); 8345 SOC_IF_ERROR_RETURN(WRITE_TOQ_QUEUE_FLUSH0r(unit, rval)); 8346 while (rval) { 8347 SOC_IF_ERROR_RETURN(READ_TOQ_QUEUE_FLUSH0r(unit, &rval)); 8348 rval = soc_reg_field_get(unit, 8349 TOQ_QUEUE_FLUSH0r, rval, Q_FLUSH_ACTIVEf); 8350 } 8351 rval = 0; 8352 soc_reg_field_set(unit, TOQ_ERRORr, &rval, FLUSH_COMPLETEf, 1); /* w1tc */ 8353 SOC_IF_ERROR_RETURN(WRITE_TOQ_ERRORr(unit, rval)); 8354 } 8355 } 8356 return BCM_E_NONE; 8357 } 8358 8359 /* 8360 * Function: 8361 * bcm_kt_cosq_detach 8362 * Purpose: 8363 * Discard all COS schedule/mapping state. 8364 * Parameters: 8365 * unit - unit number 8366 * Returns: 8367 * BCM_E_XXX 8368 */ 8369 int 8370 bcm_kt_cosq_detach(int unit, int software_state_only) 8371 { 8372 if (cosq_sync_lock[unit]) { 8373 sal_mutex_destroy(cosq_sync_lock[unit]); 8374 cosq_sync_lock[unit] = NULL; 8375 } 8376 8377 return BCM_E_NONE; 8378 } 8379 8380 /* 8381 * Function: 8382 * bcm_kt_cosq_config_set 8383 * Purpose: 8384 * Set the number of COS queues 8385 * Parameters: 8386 * unit - unit number 8387 * numq - number of COS queues (1-8). 8388 * Returns: 8389 * BCM_E_XXX 8390 */ 8391 int 8392 bcm_kt_cosq_config_set(int unit, int numq) 8393 { 8394 port_cos_map_entry_t cos_map_entries[16]; 8395 void *entries[1], *hg_entries[1]; 8396 uint32 index, hg_index; 8397 int count, hg_count; 8398 bcm_port_t port; 8399 int cos, prio; 8400 uint32 i; 8401 int cpu_hg_index = 0, ref_count; 8402 #ifdef BCM_COSQ_HIGIG_MAP_DISABLE 8403 port_cos_map_entry_t hg_cos_map_entries[16]; 8404 #endif 8405 8406 if (numq < 1 || numq > 8) { 8407 return BCM_E_PARAM; 8408 } 8409 8410 /* clear out old profiles. */ 8411 index = 0; 8412 while (index < soc_mem_index_count(unit, PORT_COS_MAPm)) { 8413 BCM_IF_ERROR_RETURN(soc_profile_mem_ref_count_get(unit, 8414 _bcm_kt_cos_map_profile[unit], 8415 index, &ref_count)); 8416 if (ref_count > 0) { 8417 while (ref_count) { 8418 BCM_IF_ERROR_RETURN(soc_profile_mem_delete(unit, 8419 _bcm_kt_cos_map_profile[unit], index)); 8420 ref_count -= 1; 8421 } 8422 } 8423 index += 16; 8424 } 8425 8426 /* Distribute first 8 internal priority levels into the specified number 8427 * of cosq, map remaining internal priority levels to highest priority 8428 * cosq */ 8429 sal_memset(cos_map_entries, 0, sizeof(cos_map_entries)); 8430 entries[0] = &cos_map_entries; 8431 hg_entries[0] = &cos_map_entries; 8432 prio = 0; 8433 for (cos = 0; cos < numq; cos++) { 8434 for (i = 8 / numq + (cos < 8 % numq ? 1 : 0); i > 0; i--) { 8435 soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio], 8436 COSf, cos); 8437 prio++; 8438 } 8439 } 8440 for (prio = 8; prio < 16; prio++) { 8441 soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio], COSf, 8442 numq - 1); 8443 } 8444 8445 /* Map internal priority levels to CPU CoS queues */ 8446 BCM_IF_ERROR_RETURN(_bcm_esw_cpu_cosq_mapping_default_set(unit, numq)); 8447 8448 #ifdef BCM_COSQ_HIGIG_MAP_DISABLE 8449 /* Use identical mapping for Higig port */ 8450 sal_memset(hg_cos_map_entries, 0, sizeof(hg_cos_map_entries)); 8451 hg_entries[0] = &hg_cos_map_entries; 8452 prio = 0; 8453 for (prio = 0; prio < 8; prio++) { 8454 soc_mem_field32_set(unit, PORT_COS_MAPm, &hg_cos_map_entries[prio], 8455 COSf, prio); 8456 } 8457 for (prio = 8; prio < 16; prio++) { 8458 soc_mem_field32_set(unit, PORT_COS_MAPm, &hg_cos_map_entries[prio], 8459 COSf, 7); 8460 } 8461 8462 #endif /* BCM_COSQ_HIGIG_MAP_DISABLE */ 8463 8464 BCM_IF_ERROR_RETURN 8465 (soc_profile_mem_add(unit, _bcm_kt_cos_map_profile[unit], entries, 16, 8466 &index)); 8467 BCM_IF_ERROR_RETURN 8468 (soc_profile_mem_add(unit, _bcm_kt_cos_map_profile[unit], hg_entries, 8469 16, &hg_index)); 8470 count = 0; 8471 hg_count = 0; 8472 PBMP_ALL_ITER(unit, port) { 8473 if (IS_HG_PORT(unit, port)) { 8474 BCM_IF_ERROR_RETURN 8475 (soc_mem_field32_modify(unit, COS_MAP_SELm, port, SELECTf, 8476 hg_index / 16)); 8477 hg_count++; 8478 } else { 8479 BCM_IF_ERROR_RETURN 8480 (soc_mem_field32_modify(unit, COS_MAP_SELm, port, SELECTf, 8481 index / 16)); 8482 count++; 8483 } 8484 } 8485 8486 cpu_hg_index = SOC_IS_KATANA2(unit) ? 8487 SOC_INFO(unit).cpu_hg_pp_port_index : 8488 SOC_INFO(unit).cpu_hg_index; 8489 if (cpu_hg_index != -1) { 8490 BCM_IF_ERROR_RETURN 8491 (soc_mem_field32_modify(unit, COS_MAP_SELm, 8492 cpu_hg_index, SELECTf, 8493 hg_index / 16)); 8494 hg_count++; 8495 } 8496 8497 8498 for (i = 1; i < count; i++) { 8499 soc_profile_mem_reference(unit, _bcm_kt_cos_map_profile[unit], index, 8500 0); 8501 } 8502 for (i = 1; i < hg_count; i++) { 8503 soc_profile_mem_reference(unit, _bcm_kt_cos_map_profile[unit], 8504 hg_index, 0); 8505 } 8506 8507 _bcm_kt_num_cosq[unit] = numq; 8508 8509 return BCM_E_NONE; 8510 } 8511 8512 8513 /* 8514 * Function: 8515 * bcm_kt_cosq_config_get 8516 * Purpose: 8517 * Get the number of cos queues 8518 * Parameters: 8519 * unit - unit number 8520 * numq - (Output) number of cosq 8521 * Returns: 8522 * BCM_E_XXX 8523 */ 8524 int 8525 bcm_kt_cosq_config_get(int unit, int *numq) 8526 { 8527 if (_bcm_kt_num_cosq[unit] == 0) { 8528 return BCM_E_INIT; 8529 } 8530 8531 if (numq != NULL) { 8532 *numq = _bcm_kt_num_cosq[unit]; 8533 } 8534 8535 return BCM_E_NONE; 8536 } 8537 8538 /* 8539 * Function: 8540 * bcm_kt_cosq_gport_attach 8541 * Purpose: 8542 * Attach sched_port to the specified index (cosq) of input_port 8543 * Parameters: 8544 * unit - (IN) unit number 8545 * sched_port - (IN) scheduler GPORT identifier 8546 * input_port - (IN) GPORT to attach to 8547 * cosq - (IN) COS queue to attach to (-1 for first available cosq) 8548 * Returns: 8549 * BCM_E_XXX 8550 */ 8551 int 8552 bcm_kt_cosq_gport_attach(int unit, bcm_gport_t sched_gport, 8553 bcm_gport_t input_gport, bcm_cos_queue_t cosq) 8554 { 8555 _bcm_kt_cosq_node_t *sched_node, *input_node, *temp_parent, *temp_sibling; 8556 bcm_port_t sched_port, input_port, local_port; 8557 int rv, max_nodes; 8558 int status = 0; 8559 8560 if (_bcm_kt_mmu_info[unit] == NULL) { 8561 return BCM_E_INIT; 8562 } 8563 8564 if ((BCM_GPORT_IS_UCAST_QUEUE_GROUP(input_gport)) || 8565 (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(input_gport))) { 8566 return BCM_E_PORT; 8567 } 8568 8569 if(!(BCM_GPORT_IS_UCAST_QUEUE_GROUP(sched_gport) || 8570 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(sched_gport) || 8571 BCM_GPORT_IS_SCHEDULER(sched_gport))) { 8572 return BCM_E_PORT; 8573 } 8574 8575 if (cosq < -1) { 8576 return BCM_E_PARAM; 8577 } 8578 8579 BCM_IF_ERROR_RETURN 8580 (_bcm_kt_cosq_node_get(unit, sched_gport, NULL, &sched_port, NULL, 8581 &sched_node)); 8582 8583 if (sched_node->cosq_attached_to >= 0) { 8584 /* Has already attached */ 8585 return BCM_E_EXISTS; 8586 } 8587 8588 if (BCM_GPORT_IS_SCHEDULER(input_gport) || 8589 BCM_GPORT_IS_LOCAL(input_gport) || 8590 BCM_GPORT_IS_MODPORT(input_gport)) { 8591 BCM_IF_ERROR_RETURN 8592 (_bcm_kt_cosq_node_get(unit, input_gport, NULL, &input_port, NULL, 8593 &input_node)); 8594 } else { 8595 BCM_IF_ERROR_RETURN 8596 (_bcm_kt_cosq_localport_resolve(unit, input_gport, &input_port)); 8597 input_node = NULL; 8598 } 8599 8600 if (sched_port != input_port) { 8601 return BCM_E_PORT; 8602 } 8603 8604 /* Identify the levels of schedulers 8605 * input_port == phy_port && sched_gport == scheduler => sched_gport = L0 8606 * input_port == schduler && sched_gport == scheduler => input_port = L0 and sched_port = L1 8607 * input_port == scheduler && sched_port == queue_group => input_port = L1 and sched_port = L2 8608 */ 8609 if (input_node != NULL) { 8610 if (!BCM_GPORT_IS_SCHEDULER(input_gport)) { 8611 if (input_node->numq == 0) { 8612 local_port = (BCM_GPORT_IS_LOCAL(input_gport)) ? 8613 BCM_GPORT_LOCAL_GET(input_gport) : 8614 BCM_GPORT_MODPORT_PORT_GET(input_gport); 8615 input_node->gport = input_gport; 8616 input_node->hw_index = local_port; 8617 input_node->level = _BCM_KT_COSQ_NODE_LEVEL_ROOT; 8618 input_node->cosq_attached_to = 0; 8619 input_node->numq = 4; /* Assign max of 4 L0 nodes */ 8620 input_node->base_index = -1; 8621 } 8622 8623 if (!BCM_GPORT_IS_SCHEDULER(sched_gport)) { 8624 return BCM_E_PARAM; 8625 } 8626 8627 sched_node->level = _BCM_KT_COSQ_NODE_LEVEL_L0; 8628 } else { 8629 if (input_node->level == _BCM_KT_COSQ_NODE_LEVEL_ROOT) { 8630 /* Don't allow non-scheduler node (queues) to be attached to port */ 8631 if (!BCM_GPORT_IS_SCHEDULER(sched_gport)) { 8632 return BCM_E_PARAM; 8633 } 8634 sched_node->level = _BCM_KT_COSQ_NODE_LEVEL_L0; 8635 BCM_IF_ERROR_RETURN 8636 (_bcm_kt_cosq_max_nodes_get(unit, sched_node->level, &max_nodes)); 8637 if (input_node->numq == -1) { 8638 input_node->numq = max_nodes; 8639 } else { 8640 if (input_node->numq > max_nodes) { 8641 return BCM_E_PARAM; 8642 } 8643 } 8644 } 8645 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(sched_gport) || 8646 BCM_GPORT_IS_MCAST_QUEUE_GROUP(sched_gport) || 8647 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(sched_gport) || 8648 BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(sched_gport)) { 8649 if (!BCM_GPORT_IS_SCHEDULER(input_gport)) { 8650 return BCM_E_PARAM; 8651 } 8652 if (input_node->level != _BCM_KT_COSQ_NODE_LEVEL_L1) { 8653 return BCM_E_PARAM; 8654 } 8655 } 8656 8657 if ((input_node->level == -1)) { 8658 input_node->level = (BCM_GPORT_IS_SCHEDULER(sched_gport)) ? 8659 _BCM_KT_COSQ_NODE_LEVEL_L0 : _BCM_KT_COSQ_NODE_LEVEL_L1; 8660 } 8661 8662 if (sched_node->level == -1) { 8663 sched_node->level = (BCM_GPORT_IS_UCAST_QUEUE_GROUP(sched_gport) || 8664 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(sched_gport)) ? 8665 _BCM_KT_COSQ_NODE_LEVEL_L2 : _BCM_KT_COSQ_NODE_LEVEL_L1; 8666 BCM_IF_ERROR_RETURN 8667 (_bcm_kt_cosq_max_nodes_get(unit, sched_node->level, &max_nodes)); 8668 if (input_node->numq == -1) { 8669 input_node->numq = max_nodes; 8670 } else { 8671 if (input_node->numq > max_nodes) { 8672 return BCM_E_PARAM; 8673 } 8674 } 8675 } 8676 } 8677 8678 if (input_node->cosq_attached_to < 0) { 8679 /* Only allow to attach to a node that has already attached */ 8680 return BCM_E_PARAM; 8681 } 8682 if (cosq < -1 || (input_node->numq != -1 && cosq >= input_node->numq)) { 8683 return BCM_E_PARAM; 8684 } 8685 } 8686 8687 if (BCM_GPORT_IS_SCHEDULER(input_gport) || BCM_GPORT_IS_LOCAL(input_gport) || 8688 BCM_GPORT_IS_MODPORT(input_gport)) { 8689 if (input_node->cosq_attached_to < 0) { 8690 /* dont allow to attach to a node that has already attached */ 8691 return BCM_E_PARAM; 8692 } 8693 temp_parent = sched_node->parent; 8694 temp_sibling = sched_node->sibling; 8695 8696 sched_node->parent = input_node; 8697 sched_node->sibling = input_node->child; 8698 input_node->child = sched_node; 8699 /* resolve the nodes */ 8700 rv = _bcm_kt_cosq_node_resolve(unit, sched_node, cosq); 8701 if (BCM_FAILURE(rv)) { 8702 input_node->child = sched_node->sibling; 8703 sched_node->parent = temp_parent; 8704 sched_node->sibling = temp_sibling; 8705 sched_node->cosq_attached_to = -1; 8706 return rv; 8707 } 8708 /* Protect LLS hierachy change as 8709 * port flush on link flap might be effected 8710 * when there is changed in the LLS hierarchy 8711 */ 8712 SOC_LLS_SCHEDULER_LOCK(unit); 8713 soc_kt_port_flush_state_get(unit, input_port, &status); 8714 if (status) { 8715 LOG_ERROR(BSL_LS_BCM_COSQ, 8716 (BSL_META_U(unit, 8717 "Unit %d Port %d is in flush state, Cannot change LLS hierarchy." 8718 "\n Attach of Cosq hw_cosq=%d failed.\n"), 8719 unit, input_port, sched_node->cosq_attached_to)); 8720 input_node->child = sched_node->sibling; 8721 SOC_LLS_SCHEDULER_UNLOCK(unit); 8722 return BCM_E_RESOURCE; 8723 } 8724 rv = _bcm_kt_cosq_sched_node_set(unit, sched_gport, 8725 _BCM_KT_COSQ_STATE_ENABLE); 8726 SOC_LLS_SCHEDULER_UNLOCK(unit); 8727 if (BCM_FAILURE(rv)) { 8728 return rv; 8729 } 8730 LOG_INFO(BSL_LS_BCM_COSQ, 8731 (BSL_META_U(unit, 8732 " hw_cosq=%d\n"), 8733 sched_node->cosq_attached_to)); 8734 } else { 8735 return BCM_E_PORT; 8736 } 8737 8738 return BCM_E_NONE; 8739 } 8740 8741 /* 8742 * Function: 8743 * bcm_kt_cosq_gport_detach 8744 * Purpose: 8745 * Detach sched_port to the specified index (cosq) of input_port 8746 * Parameters: 8747 * unit - (IN) unit number 8748 * sched_port - (IN) scheduler GPORT identifier 8749 * input_port - (IN) GPORT to attach to 8750 * cosq - (IN) COS queue to attach to (-1 for first available cosq) 8751 * Returns: 8752 * BCM_E_XXX 8753 */ 8754 int 8755 bcm_kt_cosq_gport_detach(int unit, bcm_gport_t sched_gport, 8756 bcm_gport_t input_gport, bcm_cos_queue_t cosq) 8757 { 8758 _bcm_kt_cosq_node_t *sched_node, *input_node, *prev_node; 8759 bcm_port_t sched_port, input_port; 8760 int rv; 8761 int status = 0; 8762 8763 if (_bcm_kt_mmu_info[unit] == NULL) { 8764 return BCM_E_INIT; 8765 } 8766 8767 if ((BCM_GPORT_IS_UCAST_QUEUE_GROUP(input_gport)) || 8768 (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(input_gport))) { 8769 return BCM_E_PORT; 8770 } 8771 8772 BCM_IF_ERROR_RETURN 8773 (_bcm_kt_cosq_node_get(unit, sched_gport, NULL, &sched_port, NULL, 8774 &sched_node)); 8775 8776 if (sched_node->cosq_attached_to < 0) { 8777 /* Not attached yet */ 8778 return BCM_E_PORT; 8779 } 8780 8781 if (input_gport != BCM_GPORT_INVALID) { 8782 8783 if (BCM_GPORT_IS_SCHEDULER(input_gport) || 8784 BCM_GPORT_IS_LOCAL(input_gport) || 8785 BCM_GPORT_IS_MODPORT(input_gport)) { 8786 BCM_IF_ERROR_RETURN 8787 (_bcm_kt_cosq_node_get(unit, input_gport, NULL, &input_port, NULL, 8788 &input_node)); 8789 8790 } 8791 else { 8792 8793 if (!(BCM_GPORT_IS_SCHEDULER(sched_gport) || 8794 BCM_GPORT_IS_UCAST_QUEUE_GROUP(sched_gport) || 8795 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(sched_gport))) { 8796 return BCM_E_PARAM; 8797 } 8798 else { 8799 BCM_IF_ERROR_RETURN 8800 (_bcm_kt_cosq_localport_resolve(unit, input_gport, 8801 &input_port)); 8802 input_node = NULL; 8803 } 8804 } 8805 } 8806 8807 if (sched_port != input_port) { 8808 return BCM_E_PORT; 8809 } 8810 8811 if (sched_node->parent != input_node) { 8812 return BCM_E_PORT; 8813 } 8814 8815 if (cosq < -1 || (input_node->numq != -1 && cosq >= input_node->numq)) { 8816 return BCM_E_PARAM; 8817 } 8818 8819 if (cosq != -1) { 8820 if (sched_node->cosq_attached_to != cosq) { 8821 return BCM_E_PARAM; 8822 } 8823 } 8824 /* Update the hw accordingly 8825 * Protect LLS hierachy change as 8826 * port flush on link flap might be effected 8827 * when there is a change in the LLS hierarchy 8828 */ 8829 SOC_LLS_SCHEDULER_LOCK(unit); 8830 soc_kt_port_flush_state_get(unit, input_port, &status); 8831 if (status) { 8832 LOG_ERROR(BSL_LS_BCM_COSQ, 8833 (BSL_META_U(unit, 8834 " Unit %d Port %d is in flush state, Cannot change LLS hierarchy." 8835 "\n Detach of Cosq hw_cosq=%d failed.\n"), 8836 unit, input_port, sched_node->cosq_attached_to)); 8837 SOC_LLS_SCHEDULER_UNLOCK(unit); 8838 return BCM_E_RESOURCE; 8839 } 8840 8841 rv = _bcm_kt_cosq_sched_node_set(unit, sched_gport, 8842 _BCM_KT_COSQ_STATE_DISABLE); 8843 SOC_LLS_SCHEDULER_UNLOCK(unit); 8844 if (BCM_FAILURE(rv)) { 8845 return rv; 8846 } 8847 /* unresolve the node - delete this node from parent's child list */ 8848 BCM_IF_ERROR_RETURN 8849 (_bcm_kt_cosq_node_unresolve(unit, sched_node, cosq)); 8850 8851 /* now remove from the sw tree */ 8852 if (sched_node->parent != NULL) { 8853 if (sched_node->parent->child == sched_node) { 8854 sched_node->parent->child = sched_node->sibling; 8855 } else { 8856 prev_node = sched_node->parent->child; 8857 while (prev_node != NULL && prev_node->sibling != sched_node) { 8858 prev_node = prev_node->sibling; 8859 } 8860 if (prev_node == NULL) { 8861 return BCM_E_INTERNAL; 8862 } 8863 prev_node->sibling = sched_node->sibling; 8864 } 8865 sched_node->parent = NULL; 8866 sched_node->sibling = NULL; 8867 sched_node->wrr_in_use = 0; 8868 sched_node->cosq_attached_to = -1; 8869 if (sched_node->type != 8870 _BCM_KT_NODE_SUBSCRIBER_GPORT_ID) { 8871 sched_node->hw_index = -1; 8872 } 8873 } 8874 8875 LOG_INFO(BSL_LS_BCM_COSQ, 8876 (BSL_META_U(unit, 8877 " hw_cosq=%d\n"), 8878 sched_node->cosq_attached_to)); 8879 8880 return BCM_E_NONE; 8881 } 8882 8883 /* 8884 * Function: 8885 * bcm_kt_cosq_gport_attach_get 8886 * Purpose: 8887 * Get attached status of a scheduler port 8888 * Parameters: 8889 * unit - (IN) unit number 8890 * sched_port - (IN) scheduler GPORT identifier 8891 * input_port - (OUT) GPORT to attach to 8892 * cosq - (OUT) COS queue to attached to 8893 * Returns: 8894 * BCM_E_XXX 8895 * Notes: 8896 */ 8897 int 8898 bcm_kt_cosq_gport_attach_get(int unit, bcm_gport_t sched_gport, 8899 bcm_gport_t *input_gport, bcm_cos_queue_t *cosq) 8900 { 8901 _bcm_kt_cosq_node_t *sched_node; 8902 bcm_module_t modid, modid_out; 8903 bcm_port_t port, port_out; 8904 8905 if (input_gport == NULL || cosq == NULL) { 8906 return BCM_E_PARAM; 8907 } 8908 8909 BCM_IF_ERROR_RETURN 8910 (_bcm_kt_cosq_node_get(unit, sched_gport, &modid, &port, NULL, 8911 &sched_node)); 8912 8913 if (sched_node->level == _BCM_KT_COSQ_NODE_LEVEL_ROOT) { 8914 return BCM_E_PARAM; 8915 } 8916 8917 if (sched_node->cosq_attached_to < 0) { 8918 /* Not attached yet */ 8919 return BCM_E_NOT_FOUND; 8920 } 8921 8922 if (sched_node->parent != NULL) { 8923 *input_gport = sched_node->parent->gport; 8924 } else { /* sched_node is in L2 level */ 8925 BCM_IF_ERROR_RETURN 8926 (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, modid, port, 8927 &modid_out, &port_out)); 8928 BCM_GPORT_MODPORT_SET(*input_gport, modid_out, port_out); 8929 } 8930 *cosq = sched_node->cosq_attached_to; 8931 8932 return BCM_E_NONE; 8933 } 8934 8935 STATIC int 8936 _bcm_kt_cosq_ef_update_war(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 8937 int hw_index, lls_l2_parent_entry_t *entry) 8938 { 8939 lls_l1_config_entry_t l1_config; 8940 uint32 min_bw, max_bw, min_burst, max_burst, flags = 0; 8941 int parent_index, spri_vector; 8942 uint32 start_pri, vec_3_0 =0, vec_7_4 = 0; 8943 uint32 rval = 0, bit_offset; 8944 8945 LOG_INFO(BSL_LS_BCM_COSQ, 8946 (BSL_META_U(unit, 8947 "_bcm_kt_cosq_ef_update_war:unit=%d gport=0x%x cosq=%d idx=%d\n"), 8948 unit, gport, cosq, hw_index)); 8949 8950 BCM_IF_ERROR_RETURN 8951 (_bcm_kt_cosq_bucket_get(unit, gport, cosq, &min_bw, &max_bw, 8952 &min_burst, &max_burst, flags)); 8953 8954 if ((min_bw == 0) && (max_bw == 0)) { 8955 SOC_IF_ERROR_RETURN 8956 (soc_mem_write(unit, LLS_L2_PARENTm, MEM_BLOCK_ALL, 8957 hw_index, entry)); 8958 } else { 8959 parent_index = soc_mem_field32_get(unit, LLS_L2_PARENTm, entry, 8960 C_PARENTf); 8961 SOC_IF_ERROR_RETURN 8962 (soc_mem_read(unit, LLS_L1_CONFIGm, MEM_BLOCK_ALL, parent_index, 8963 &l1_config)); 8964 if (SOC_IS_KATANA2(unit)) { 8965 start_pri = soc_mem_field32_get(unit, LLS_L1_CONFIGm, &l1_config, 8966 P_START_UC_SPRIf); 8967 } else { 8968 start_pri = soc_mem_field32_get(unit, LLS_L1_CONFIGm, &l1_config, 8969 P_START_SPRIf); 8970 } 8971 vec_3_0 = soc_mem_field32_get(unit, LLS_L1_CONFIGm, &l1_config, 8972 P_NUM_SPRIf); 8973 vec_7_4 = soc_mem_field32_get(unit, LLS_L1_CONFIGm, &l1_config, 8974 P_VECT_SPRI_7_4f); 8975 spri_vector = vec_3_0 | (vec_7_4 << 4); 8976 bit_offset = hw_index - start_pri; 8977 if (bit_offset >= 8) { 8978 return BCM_E_PARAM; 8979 } 8980 LOG_INFO(BSL_LS_BCM_COSQ, 8981 (BSL_META_U(unit, 8982 "parent=%d spri_vector=0x%x bit_offset=%d\n"), 8983 parent_index, spri_vector, bit_offset)); 8984 spri_vector &= ~(1 << bit_offset); 8985 soc_mem_field32_set(unit, LLS_L1_CONFIGm, &l1_config, P_NUM_SPRIf, 8986 (spri_vector & 0xF)); 8987 soc_mem_field32_set(unit, LLS_L1_CONFIGm, &l1_config, P_VECT_SPRI_7_4f, 8988 ((spri_vector >> 4) & 0xF)); 8989 BCM_IF_ERROR_RETURN 8990 (_bcm_kt_cosq_bucket_set(unit, gport, cosq, 0, 0, 8991 min_burst, max_burst, flags)); 8992 SOC_IF_ERROR_RETURN 8993 (soc_mem_write(unit, LLS_L2_PARENTm, MEM_BLOCK_ALL, 8994 hw_index, entry)); 8995 SOC_IF_ERROR_RETURN 8996 (soc_mem_write(unit, LLS_L1_CONFIGm, MEM_BLOCK_ALL, 8997 parent_index, &l1_config)); 8998 8999 soc_reg_field_set(unit, LLS_DEBUG_INJECT_ACTIVATIONr, &rval, 9000 INJECTf, 1); 9001 /* 0 = enqueue event,1 = shaper event,2 = xon event,3 = xoff event */ 9002 soc_reg_field_set(unit, LLS_DEBUG_INJECT_ACTIVATIONr, &rval, 9003 ENTITY_TYPEf, 1); 9004 /* 0 = port, 1 = level 0, 2 = level 1, 3 = level 2 */ 9005 soc_reg_field_set(unit, LLS_DEBUG_INJECT_ACTIVATIONr, &rval, 9006 ENTITY_LEVELf, 3); 9007 soc_reg_field_set(unit, LLS_DEBUG_INJECT_ACTIVATIONr, &rval, 9008 ENTITY_IDENTIFIERf, hw_index); 9009 SOC_IF_ERROR_RETURN(WRITE_LLS_DEBUG_INJECT_ACTIVATIONr(unit, rval)); 9010 spri_vector |= (1 << bit_offset); 9011 soc_mem_field32_set(unit, LLS_L1_CONFIGm, &l1_config, P_NUM_SPRIf, 9012 (spri_vector & 0xF)); 9013 soc_mem_field32_set(unit, LLS_L1_CONFIGm, &l1_config, P_VECT_SPRI_7_4f, 9014 ((spri_vector >> 4) & 0xF)); 9015 SOC_IF_ERROR_RETURN 9016 (soc_mem_write(unit, LLS_L1_CONFIGm, MEM_BLOCK_ALL, 9017 parent_index, &l1_config)); 9018 BCM_IF_ERROR_RETURN 9019 (_bcm_kt_cosq_bucket_set(unit, gport, cosq, min_bw, max_bw, 9020 min_burst, max_burst, flags)); 9021 } 9022 9023 return BCM_E_NONE; 9024 } 9025 9026 STATIC int 9027 _bcm_kt_cosq_valid_ef_node(int unit, lls_l1_config_entry_t *entry, 9028 int hw_index) 9029 { 9030 lls_l2_parent_entry_t l2_parent; 9031 int index, start_pri, spri_vector, num_spri, vec_7_4; 9032 uint32 bit_offset; 9033 int i; 9034 9035 if (SOC_IS_KATANA2(unit)) { 9036 start_pri = soc_mem_field32_get(unit, LLS_L1_CONFIGm, entry, 9037 P_START_UC_SPRIf); 9038 } else { 9039 start_pri = soc_mem_field32_get(unit, LLS_L1_CONFIGm, entry, 9040 P_START_SPRIf); 9041 } 9042 num_spri = soc_mem_field32_get(unit, LLS_L1_CONFIGm, entry, 9043 P_NUM_SPRIf); 9044 if (soc_feature(unit, soc_feature_vector_based_spri)) { 9045 vec_7_4 = soc_mem_field32_get(unit, LLS_L1_CONFIGm, entry, 9046 P_VECT_SPRI_7_4f); 9047 spri_vector = num_spri | (vec_7_4 << 4); 9048 bit_offset = hw_index - start_pri; 9049 if (bit_offset >= 8) { 9050 return BCM_E_PARAM; 9051 } 9052 if (!(spri_vector & (1 << bit_offset))) { 9053 /* werr node cannot be EF */ 9054 return BCM_E_PARAM; 9055 } 9056 for (i = 0; i < 8; i++) { 9057 if (spri_vector & (1 << i)) { 9058 index = start_pri + i; 9059 SOC_IF_ERROR_RETURN 9060 (soc_mem_read(unit, LLS_L2_PARENTm, MEM_BLOCK_ALL, 9061 index, &l2_parent)); 9062 if (soc_mem_field32_get(unit, LLS_L2_PARENTm, 9063 &l2_parent, C_EFf) == 1) { 9064 /* maximum of 1 EF node is supported */ 9065 return FALSE; 9066 } 9067 } 9068 } 9069 } else { 9070 if ((hw_index < start_pri) || (hw_index >= (start_pri + num_spri))) { 9071 /* werr node cannot be EF */ 9072 return BCM_E_PARAM; 9073 } 9074 for (i = start_pri; i < (start_pri + num_spri); i++) { 9075 SOC_IF_ERROR_RETURN 9076 (soc_mem_read(unit, LLS_L2_PARENTm, MEM_BLOCK_ALL, 9077 i, &l2_parent)); 9078 if (soc_mem_field32_get(unit, LLS_L2_PARENTm, 9079 &l2_parent, C_EFf) == 1) { 9080 /* maximum of 1 EF node is supported */ 9081 return FALSE; 9082 } 9083 } 9084 } 9085 9086 return TRUE; 9087 } 9088 9089 STATIC int 9090 _bcm_kt_cosq_ef_op_at_index(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 9091 int hw_index, _bcm_cosq_op_t op, int *ef_val) 9092 { 9093 lls_l2_parent_entry_t entry; 9094 lls_l1_parent_entry_t l1_entry; 9095 lls_l1_config_entry_t l1_config; 9096 lls_l0_config_entry_t l0_config; 9097 uint32 current_ef = 0, set_ef = 0; 9098 uint32 index; 9099 9100 SOC_IF_ERROR_RETURN 9101 (soc_mem_read(unit, LLS_L2_PARENTm, MEM_BLOCK_ALL, hw_index, &entry)); 9102 9103 if (op == _BCM_COSQ_OP_GET) { 9104 *ef_val = soc_mem_field32_get(unit, LLS_L2_PARENTm, &entry, C_EFf); 9105 } else { 9106 current_ef = soc_mem_field32_get(unit, LLS_L2_PARENTm, &entry, C_EFf); 9107 set_ef = (*ef_val != 0) ? 1 : 0; 9108 soc_mem_field32_set(unit, LLS_L2_PARENTm, &entry, C_EFf, set_ef); 9109 if ((current_ef == 0) && (set_ef == 1)) { 9110 index = soc_mem_field32_get(unit, LLS_L2_PARENTm, &entry, 9111 C_PARENTf); 9112 SOC_IF_ERROR_RETURN 9113 (soc_mem_read(unit, LLS_L1_CONFIGm, MEM_BLOCK_ALL, 9114 index, &l1_config)); 9115 if (_bcm_kt_cosq_valid_ef_node(unit, &l1_config, 9116 hw_index) != TRUE) { 9117 return BCM_E_PARAM; 9118 } 9119 soc_mem_field32_set(unit, LLS_L1_CONFIGm, &l1_config, 9120 P_CFG_EF_PROPAGATEf, set_ef); 9121 SOC_IF_ERROR_RETURN 9122 (soc_mem_write(unit, LLS_L1_CONFIGm, MEM_BLOCK_ALL, 9123 index, &l1_config)); 9124 SOC_IF_ERROR_RETURN 9125 (soc_mem_read(unit, LLS_L1_PARENTm, MEM_BLOCK_ALL, 9126 index, &l1_entry)); 9127 index = soc_mem_field32_get(unit, LLS_L1_PARENTm, &l1_entry, 9128 C_PARENTf); 9129 SOC_IF_ERROR_RETURN 9130 (soc_mem_read(unit, LLS_L0_CONFIGm, MEM_BLOCK_ALL, 9131 index, &l0_config)); 9132 soc_mem_field32_set(unit, LLS_L0_CONFIGm, &l0_config, 9133 P_CFG_EF_PROPAGATEf, set_ef); 9134 SOC_IF_ERROR_RETURN 9135 (soc_mem_write(unit, LLS_L0_CONFIGm, MEM_BLOCK_ALL, 9136 index, &l0_config)); 9137 SOC_IF_ERROR_RETURN 9138 (soc_mem_write(unit, LLS_L2_PARENTm, MEM_BLOCK_ALL, 9139 hw_index, &entry)); 9140 } else if ((current_ef == 1) && (set_ef == 0)) { 9141 if (soc_feature(unit, soc_feature_vector_based_spri)) { 9142 return _bcm_kt_cosq_ef_update_war(unit, gport, cosq, 9143 hw_index, &entry); 9144 } 9145 SOC_IF_ERROR_RETURN 9146 (soc_mem_write(unit, LLS_L2_PARENTm, MEM_BLOCK_ALL, 9147 hw_index, &entry)); 9148 } else { 9149 return BCM_E_NONE; 9150 } 9151 } 9152 9153 return BCM_E_NONE; 9154 } 9155 9156 STATIC int 9157 _bcm_kt_cosq_ef_op(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, int *arg, 9158 _bcm_cosq_op_t op) 9159 { 9160 bcm_port_t local_port; 9161 int index, numq, from_cos, to_cos, ci; 9162 9163 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 9164 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport)) { 9165 BCM_IF_ERROR_RETURN 9166 (_bcm_kt_cosq_index_resolve 9167 (unit, gport, cosq, _BCM_KT_COSQ_INDEX_STYLE_BUCKET, 9168 &local_port, &index, NULL)); 9169 return _bcm_kt_cosq_ef_op_at_index(unit, gport, cosq, 9170 index, op, arg); 9171 } else if (BCM_GPORT_IS_SCHEDULER(gport)) { 9172 return BCM_E_PARAM; 9173 } else { 9174 BCM_IF_ERROR_RETURN 9175 (_bcm_kt_cosq_index_resolve 9176 (unit, gport, cosq, _BCM_KT_COSQ_INDEX_STYLE_BUCKET, 9177 &local_port, &index, &numq)); 9178 if (cosq == BCM_COS_INVALID) { 9179 /* Maximum 1 spri can be EF enabled */ 9180 from_cos = to_cos = 0; 9181 } else { 9182 from_cos = to_cos = cosq; 9183 } 9184 for (ci = from_cos; ci <= to_cos; ci++) { 9185 BCM_IF_ERROR_RETURN 9186 (_bcm_kt_cosq_index_resolve 9187 (unit, gport, ci, _BCM_KT_COSQ_INDEX_STYLE_BUCKET, 9188 &local_port, &index, NULL)); 9189 9190 BCM_IF_ERROR_RETURN(_bcm_kt_cosq_ef_op_at_index(unit, 9191 gport, ci, index, op, arg)); 9192 if (op == _BCM_COSQ_OP_GET) { 9193 return BCM_E_NONE; 9194 } 9195 } 9196 } 9197 return BCM_E_NONE; 9198 } 9199 9200 STATIC int 9201 _bcm_kt_cosq_port_qnum_get(int unit, bcm_gport_t gport, 9202 bcm_cos_queue_t cosq, bcm_cosq_control_t type, int *arg) 9203 { 9204 bcm_port_t local_port; 9205 if (!arg) { 9206 return BCM_E_PARAM; 9207 } 9208 9209 if (!BCM_COSQ_QUEUE_VALID(unit, cosq)) { 9210 return BCM_E_PARAM; 9211 } 9212 9213 BCM_IF_ERROR_RETURN 9214 (_bcm_kt_cosq_localport_resolve(unit, gport, &local_port)); 9215 if (local_port < 0) { 9216 return BCM_E_PORT; 9217 } 9218 9219 if (type == bcmCosqControlPortQueueUcast) { 9220 *arg = SOC_INFO(unit).port_uc_cosq_base[local_port] + cosq; 9221 } else { 9222 *arg = SOC_INFO(unit).port_cosq_base[local_port] + cosq; 9223 } 9224 9225 return BCM_E_NONE; 9226 } 9227 9228 int 9229 bcm_kt_cosq_control_set(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 9230 bcm_cosq_control_t type, int arg) 9231 { 9232 LOG_INFO(BSL_LS_BCM_COSQ, 9233 (BSL_META_U(unit, 9234 "bcm_kt_cosq_control_set: unit=%d gport=0x%x cosq=%d \ 9235 type=%d arg=%d\n"), 9236 unit, gport, cosq, type, arg)); 9237 switch (type) { 9238 case bcmCosqControlEfPropagation: 9239 return _bcm_kt_cosq_ef_op(unit, gport, cosq, &arg, _BCM_COSQ_OP_SET); 9240 default: 9241 break; 9242 } 9243 9244 return BCM_E_UNAVAIL; 9245 } 9246 9247 int 9248 bcm_kt_cosq_control_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 9249 bcm_cosq_control_t type, int *arg) 9250 { 9251 LOG_INFO(BSL_LS_BCM_COSQ, 9252 (BSL_META_U(unit, 9253 "bcm_kt_cosq_control_get: unit=%d gport=0x%x cosq=%d type=%d\n"), 9254 unit, gport, cosq, type)); 9255 switch (type) { 9256 case bcmCosqControlEfPropagation: 9257 return _bcm_kt_cosq_ef_op(unit, gport, cosq, arg, _BCM_COSQ_OP_GET); 9258 case bcmCosqControlPortQueueUcast: 9259 case bcmCosqControlPortQueueMcast: 9260 return _bcm_kt_cosq_port_qnum_get(unit, gport, cosq, type, arg); 9261 default: 9262 break; 9263 } 9264 9265 return BCM_E_UNAVAIL; 9266 } 9267 9268 int 9269 bcm_kt_cosq_drop_status_enable_set(int unit, bcm_port_t port, int enable) 9270 { 9271 uint32 rval; 9272 9273 BCM_IF_ERROR_RETURN(READ_OP_E2ECC_PORT_CONFIGr(unit, port, &rval)); 9274 soc_reg_field_set(unit, OP_E2ECC_PORT_CONFIGr, &rval, 9275 COS_MASKf, enable ? 0xFF : 0x0); 9276 soc_reg_field_set(unit, OP_E2ECC_PORT_CONFIGr, &rval, 9277 E2ECC_RPT_ENf, enable ? 1 : 0); 9278 BCM_IF_ERROR_RETURN(WRITE_OP_E2ECC_PORT_CONFIGr(unit, port, rval)); 9279 9280 9281 BCM_IF_ERROR_RETURN(READ_OP_THR_CONFIGr(unit, &rval)); 9282 soc_reg_field_set(unit, OP_THR_CONFIGr, &rval, EARLY_E2E_SELECTf, 9283 enable ? 1 : 0); 9284 BCM_IF_ERROR_RETURN(WRITE_OP_THR_CONFIGr(unit, rval)); 9285 9286 return BCM_E_NONE; 9287 } 9288 9289 STATIC int 9290 _bcm_kt_dump_config(int unit, bcm_port_t port, 9291 _bcm_kt_cosq_node_t *node) 9292 { 9293 int num_spri, first_child; 9294 uint32 spmap; 9295 soc_kt_sched_mode_e sched_mode = SOC_KT_SCHED_MODE_UNKNOWN; 9296 int wt = 0; 9297 char *lvl_name[] = { "Root", "L0", "L1", "L2" }; 9298 char *sched_modes[] = {"X", "SP", "WRR", "WDRR"}; 9299 int sp_vec = soc_feature(unit, soc_feature_vector_based_spri); 9300 9301 9302 /* get sched config */ 9303 if (node->level != _BCM_KT_COSQ_NODE_LEVEL_L2) { 9304 SOC_IF_ERROR_RETURN( 9305 soc_kt_sched_get_node_config(unit, port, node->level, 9306 node->hw_index, &num_spri, 9307 &first_child, &spmap)); 9308 } 9309 sched_mode = 0; 9310 if (node->level != _BCM_KT_COSQ_NODE_LEVEL_ROOT) { 9311 SOC_IF_ERROR_RETURN( 9312 soc_kt_cosq_get_sched_mode(unit, port, node->level, node->hw_index, 9313 &sched_mode, &wt)); 9314 } 9315 switch (node->level) { 9316 case _BCM_KT_COSQ_NODE_LEVEL_ROOT: 9317 case _BCM_KT_COSQ_NODE_LEVEL_L0: 9318 case _BCM_KT_COSQ_NODE_LEVEL_L1: 9319 if (sp_vec) { 9320 LOG_CLI((BSL_META_U(unit, 9321 " %s.%d : INDEX=%d NUM_SPRI=%d FC=%d SPMAP=0x%08x MODE=%s Wt=%d\n"), 9322 lvl_name[node->level], node->cosq_attached_to, 9323 node->hw_index, num_spri, first_child, 9324 spmap, sched_modes[sched_mode], wt)); 9325 } else { 9326 LOG_CLI((BSL_META_U(unit, 9327 " %s.%d : INDEX=%d NUM_SPRI=%d FC=%d MODE=%s Wt=%d\n"), 9328 lvl_name[node->level], node->cosq_attached_to, 9329 node->hw_index, num_spri, first_child, 9330 sched_modes[sched_mode], wt)); 9331 } 9332 break; 9333 case _BCM_KT_COSQ_NODE_LEVEL_L2: 9334 LOG_CLI((BSL_META_U(unit, 9335 " L2.%d INDEX=%d Mode=%s WEIGHT=%d\n"), 9336 node->cosq_attached_to, node->hw_index, 9337 sched_modes[sched_mode], wt)); 9338 break; 9339 default: 9340 return BCM_E_INTERNAL; 9341 9342 } 9343 return BCM_E_NONE; 9344 } 9345 9346 STATIC int 9347 _bcm_kt_cosq_child_node_at_input(_bcm_kt_cosq_node_t *node, int cosq, 9348 _bcm_kt_cosq_node_t **child_node) 9349 { 9350 _bcm_kt_cosq_node_t *cur_node; 9351 9352 for (cur_node = node->child; cur_node; cur_node = cur_node->sibling) { 9353 if (cur_node->cosq_attached_to == cosq) { 9354 break; 9355 } 9356 } 9357 if (!cur_node) { 9358 return BCM_E_NOT_FOUND; 9359 } 9360 9361 *child_node = cur_node; 9362 9363 return BCM_E_NONE; 9364 } 9365 9366 STATIC int 9367 _bcm_kt_dump_sched(int unit, bcm_port_t port, bcm_gport_t gport) 9368 { 9369 _bcm_kt_cosq_node_t *node; 9370 _bcm_kt_cosq_node_t *cur_node; 9371 int i = 0; 9372 int start_cos = 0; 9373 int end_cos = 0; 9374 9375 BCM_IF_ERROR_RETURN 9376 (_bcm_kt_cosq_node_get(unit, gport, NULL, NULL, NULL, &node)); 9377 9378 if (node != NULL) { 9379 if (node->level == _BCM_KT_COSQ_NODE_LEVEL_L2) { 9380 return BCM_E_INTERNAL; 9381 } 9382 9383 start_cos = 0; 9384 end_cos = node->numq; 9385 _bcm_kt_dump_config(unit, port, node); 9386 9387 for (i = start_cos; i < end_cos; i++) 9388 { 9389 if(_bcm_kt_cosq_child_node_at_input(node, i, &cur_node) 9390 == BCM_E_NOT_FOUND) { 9391 continue; 9392 } 9393 if (cur_node->level == _BCM_KT_COSQ_NODE_LEVEL_L2) { 9394 BCM_IF_ERROR_RETURN 9395 (_bcm_kt_dump_config(unit, port, cur_node)); 9396 } else { 9397 BCM_IF_ERROR_RETURN 9398 (_bcm_kt_dump_sched(unit, port, cur_node->gport)); 9399 } 9400 } 9401 } 9402 return BCM_E_NONE; 9403 9404 } 9405 9406 STATIC int 9407 _bcm_kt_dump_port_lls(int unit, bcm_port_t port) 9408 { 9409 _bcm_kt_cosq_node_t *port_info; 9410 _bcm_kt_mmu_info_t *mmu_info; 9411 bcm_port_t port_out; 9412 9413 if (_bcm_kt_mmu_info[unit] == NULL) { 9414 return BCM_E_INIT; 9415 } 9416 mmu_info = _bcm_kt_mmu_info[unit]; 9417 9418 BCM_IF_ERROR_RETURN 9419 (_bcm_kt_cosq_localport_resolve(unit, port, &port_out)); 9420 9421 /* root node */ 9422 port_info = &mmu_info->sched_node[port_out]; 9423 9424 if (port_info->gport >= 0) { 9425 _bcm_kt_dump_sched(unit, port, port_info->gport); 9426 } 9427 return BCM_E_NONE; 9428 } 9429 9430 int bcm_kt_dump_port_lls(int unit, bcm_port_t port) 9431 { 9432 9433 LOG_CLI((BSL_META_U(unit, 9434 "-------%s (LLS)------\n"), SOC_PORT_NAME(unit, (port)))); 9435 _bcm_kt_dump_port_lls(unit, port); 9436 return SOC_E_NONE; 9437 } 9438 9439 int 9440 bcm_kt_cosq_subscriber_qid_set(int unit, 9441 bcm_gport_t *gport, 9442 int queue_id) 9443 { 9444 _bcm_kt_mmu_info_t *mmu_info; 9445 mmu_info = _bcm_kt_mmu_info[unit]; 9446 if (mmu_info == NULL) { 9447 return BCM_E_INIT; 9448 } 9449 if (queue_id >= mmu_info->num_base_queues) { 9450 queue_id -= mmu_info->num_base_queues; 9451 } 9452 BCM_GPORT_UCAST_SUBSCRIBER_QUEUE_GROUP_QID_SET 9453 (*gport,queue_id); 9454 return SOC_E_NONE; 9455 } 9456 9457 9458 #ifndef BCM_SW_STATE_DUMP_DISABLE 9459 9460 STATIC int 9461 _bcm_kt_cosq_port_info_dump(int unit, bcm_port_t port) 9462 { 9463 _bcm_kt_mmu_info_t *mmu_info; 9464 _bcm_kt_cosq_node_t *port_node = NULL; 9465 _bcm_kt_cosq_node_t *queue_node = NULL; 9466 _bcm_kt_cosq_node_t *l0_node = NULL; 9467 _bcm_kt_cosq_node_t *l1_node = NULL; 9468 9469 if (!SOC_PORT_VALID(unit, port)) { 9470 return BCM_E_PORT; 9471 } 9472 9473 mmu_info = _bcm_kt_mmu_info[unit]; 9474 9475 /* get the root node */ 9476 port_node = &mmu_info->sched_node[port]; 9477 9478 if (port_node && port_node->cosq_attached_to < 0) { 9479 return BCM_E_NONE; 9480 } 9481 9482 LOG_CLI((BSL_META_U(unit, 9483 "=== port %d\n"), port)); 9484 LOG_CLI((BSL_META_U(unit, 9485 "base = %d numq = %d hw_index = %d level = %d cosq_attach = %d \n"), 9486 port_node->base_index, port_node->numq, port_node->hw_index, 9487 port_node->level, port_node->cosq_attached_to)); 9488 LOG_CLI((BSL_META_U(unit, 9489 "num_child = %d first_child = %d \n"), port_node->num_child, 9490 port_node->first_child)); 9491 if (port_node->parent != NULL) { 9492 LOG_CLI((BSL_META_U(unit, 9493 " parent gport = 0x%08x\n"), port_node->parent->gport)); 9494 } 9495 if (port_node->sibling != NULL) { 9496 LOG_CLI((BSL_META_U(unit, 9497 " sibling gport = 0x%08x\n"), port_node->sibling->gport)); 9498 } 9499 if (port_node->child != NULL) { 9500 LOG_CLI((BSL_META_U(unit, 9501 " child gport = 0x%08x\n"), port_node->child->gport)); 9502 } 9503 9504 for (l0_node = port_node->child; l0_node != NULL; 9505 l0_node = l0_node->sibling) { 9506 9507 if (l0_node->cosq_attached_to < 0) { 9508 return BCM_E_NONE; 9509 } 9510 LOG_CLI((BSL_META_U(unit, 9511 "=== L0 gport 0x%08x\n"), l0_node->gport)); 9512 LOG_CLI((BSL_META_U(unit, 9513 "base = %d numq = %d hw_index = %d level = %d cosq_attach = %d \n"), 9514 l0_node->base_index, l0_node->numq, l0_node->hw_index, 9515 l0_node->level, l0_node->cosq_attached_to)); 9516 LOG_CLI((BSL_META_U(unit, 9517 "num_child = %d first_child = %d \n"), l0_node->num_child, 9518 l0_node->first_child)); 9519 if (l0_node->parent != NULL) { 9520 LOG_CLI((BSL_META_U(unit, 9521 " parent gport = 0x%08x\n"), l0_node->parent->gport)); 9522 } 9523 if (l0_node->sibling != NULL) { 9524 LOG_CLI((BSL_META_U(unit, 9525 " sibling gport = 0x%08x\n"), l0_node->sibling->gport)); 9526 } 9527 if (l0_node->child != NULL) { 9528 LOG_CLI((BSL_META_U(unit, 9529 " child gport = 0x%08x\n"), l0_node->child->gport)); 9530 } 9531 9532 for (l1_node = l0_node->child; l1_node != NULL; 9533 l1_node = l1_node->sibling) { 9534 if (l1_node->cosq_attached_to < 0) { 9535 return BCM_E_NONE; 9536 } 9537 LOG_CLI((BSL_META_U(unit, 9538 "=== L1 gport 0x%08x\n"), l1_node->gport)); 9539 LOG_CLI((BSL_META_U(unit, 9540 "base = %d numq = %d hw_index = %d level = %d cosq_attach = %d \n"), 9541 l1_node->base_index, l1_node->numq, l1_node->hw_index, 9542 l1_node->level, l1_node->cosq_attached_to)); 9543 LOG_CLI((BSL_META_U(unit, 9544 "num_child = %d first_child = %d \n"), l1_node->num_child, 9545 l1_node->first_child)); 9546 if (l1_node->parent != NULL) { 9547 LOG_CLI((BSL_META_U(unit, 9548 " parent gport = 0x%08x\n"), l1_node->parent->gport)); 9549 } 9550 if (l1_node->sibling != NULL) { 9551 LOG_CLI((BSL_META_U(unit, 9552 " sibling gport = 0x%08x\n"), l1_node->sibling->gport)); 9553 } 9554 if (l1_node->child != NULL) { 9555 LOG_CLI((BSL_META_U(unit, 9556 " child gport = 0x%08x\n"), l1_node->child->gport)); 9557 } 9558 9559 for (queue_node = l1_node->child; queue_node != NULL; 9560 queue_node = queue_node->sibling) { 9561 if (queue_node->cosq_attached_to < 0) { 9562 return BCM_E_NONE; 9563 } 9564 LOG_CLI((BSL_META_U(unit, 9565 "=== L2 gport 0x%08x\n"), queue_node->gport)); 9566 LOG_CLI((BSL_META_U(unit, 9567 "base = %d numq = %d hw_index = %d level = %d cosq_attach = %d \n"), 9568 queue_node->base_index, queue_node->numq, queue_node->hw_index, 9569 queue_node->level, queue_node->cosq_attached_to)); 9570 LOG_CLI((BSL_META_U(unit, 9571 "num_child = %d first_child = %d \n"), queue_node->num_child, 9572 queue_node->first_child)); 9573 if (queue_node->parent != NULL) { 9574 LOG_CLI((BSL_META_U(unit, 9575 " parent gport = 0x%08x\n"), queue_node->parent->gport)); 9576 } 9577 if (queue_node->sibling != NULL) { 9578 LOG_CLI((BSL_META_U(unit, 9579 " sibling gport = 0x%08x\n"), queue_node->sibling->gport)); 9580 } 9581 if (queue_node->child != NULL) { 9582 LOG_CLI((BSL_META_U(unit, 9583 " child gport = 0x%08x\n"), queue_node->child->gport)); 9584 } 9585 } 9586 9587 } 9588 } 9589 9590 return BCM_E_NONE; 9591 } 9592 9593 /* 9594 * Function: 9595 * bcm_kt_cosq_sw_dump 9596 * Purpose: 9597 * Displays COS Queue information maintained by software. 9598 * Parameters: 9599 * unit - Device unit number 9600 * Returns: 9601 * None 9602 */ 9603 void 9604 bcm_kt_cosq_sw_dump(int unit) 9605 { 9606 _bcm_kt_mmu_info_t *mmu_info; 9607 bcm_port_t port; 9608 9609 mmu_info = _bcm_kt_mmu_info[unit]; 9610 9611 LOG_CLI((BSL_META_U(unit, 9612 "\nSW Information COSQ - Unit %d\n"), unit)); 9613 9614 PBMP_ALL_ITER(unit, port) { 9615 (void)_bcm_kt_cosq_port_info_dump(unit, port); 9616 } 9617 9618 LOG_CLI((BSL_META_U(unit, 9619 "ext_qlist = %d \n"), mmu_info->ext_qlist.count)); 9620 LOG_CLI((BSL_META_U(unit, 9621 "sched_list = %d \n"), mmu_info->sched_list.count)); 9622 LOG_CLI((BSL_META_U(unit, 9623 "l0_sched_list = %d \n"), mmu_info->l0_sched_list.count)); 9624 LOG_CLI((BSL_META_U(unit, 9625 "l1_sched_list = %d \n"), mmu_info->l1_sched_list.count)); 9626 LOG_CLI((BSL_META_U(unit, 9627 "l2_base_qlist = %d \n"), mmu_info->l2_base_qlist.count)); 9628 LOG_CLI((BSL_META_U(unit, 9629 "l2_ext_qlist = %d \n"), mmu_info->l2_ext_qlist.count)); 9630 9631 return; 9632 } 9633 #endif /* BCM_SW_STATE_DUMP_DISABLE */ 9634 9635 #else /* BCM_KATANA_SUPPORT */ 9636 int _kt_cosq_not_empty; 9637 #endif /* BCM_KATANA_SUPPORT */