cosq.c (548510B)
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 <soc/defs.h> 14 #include <sal/core/libc.h> 15 16 #if defined(BCM_TOMAHAWK_SUPPORT) 17 #include <soc/drv.h> 18 #include <soc/scache.h> 19 #include <soc/scache_dictionary.h> 20 #include <soc/profile_mem.h> 21 #include <soc/debug.h> 22 #include <soc/tomahawk.h> 23 #include <soc/dma.h> 24 #include <soc/mmu_config.h> 25 #include <soc/uc.h> 26 #include <soc/shared/qcm.h> 27 28 29 #include <bcm/debug.h> 30 #include <bcm/error.h> 31 #include <bcm/cosq.h> 32 #include <bcm_int/esw/mbcm.h> 33 #include <bcm_int/esw/stack.h> 34 #include <bcm_int/esw/cosq.h> 35 #include <bcm_int/esw/virtual.h> 36 #include <bcm_int/esw/tomahawk.h> 37 #include <bcm_int/esw/ecn.h> 38 #include <bcm_int/esw/oob.h> 39 #if defined(INCLUDE_PSTATS) 40 #include <bcm_int/esw/pstats.h> 41 #endif /* INCLUDE_PSTATS */ 42 #if defined(BCM_TOMAHAWK2_SUPPORT) 43 #include <bcm_int/esw/tomahawk2.h> 44 #include <soc/tomahawk2.h> 45 #endif 46 #include <bcm_int/esw/pfc_deadlock.h> 47 #if defined (INCLUDE_TCB) && defined (BCM_TCB_SUPPORT) 48 #include <bcm_int/esw/tcb.h> 49 #endif 50 #include <bcm_int/esw_dispatch.h> 51 52 #include <bcm_int/bst.h> 53 54 #ifdef BCM_WARM_BOOT_SUPPORT 55 #include <bcm_int/esw/switch.h> 56 #endif /* BCM_WARM_BOOT_SUPPORT */ 57 #ifdef BCM_CMICM_SUPPORT 58 #include <soc/cmicm.h> 59 #endif 60 61 #define _BCM_TH_NUM_UCAST_QUEUE_PER_PORT 10 62 #define _BCM_TH_NUM_MCAST_QUEUE_PER_PORT 10 63 #define _BCM_TH_NUM_SCHEDULER_PER_PORT 10 64 #define _BCM_TH_NUM_CPU_MCAST_QUEUE 48 65 #define _BCM_TH_NUM_BUFFER_PER_PIPE 2 66 67 #define TH_WRED_CELL_FIELD_MAX 0xffff 68 69 #define _TH_NUM_PIPES 4 70 71 /* COS default value for TH is assumed to be 8 */ 72 #define BCM_TH_COS_DEFAULT 8 73 /* COS max value for TH is assumed to be 10 */ 74 #define BCM_TH_COS_MAX 10 75 76 /* TH supports 16 SAFC priority */ 77 #define _BCM_TH_NUM_SAFC_CLASS 16 78 79 /* TH supports 8 PFC priority */ 80 #define _BCM_TH_NUM_PFC_CLASS 8 81 82 #define _BCM_TH_NUM_TIME_DOMAIN 4 83 84 typedef struct _bcm_th_cosq_time_info_s { 85 uint32 ref_count; 86 } _bcm_th_cosq_time_info_t; 87 88 /* WRED can be enabled at per UC queue / port / service pool basis 89 MMU_WRED_AVG_QSIZE used entry: (330 + 132 + 4) = 466 90 329 ~ 0: Unicast Queue 91 461 ~ 330: Port Service Pool (port 0 to 32) 92 Address = 330 + {PORTID[5:0], SPID[1:0]} per PIPE 93 Each Port's service pool is addressed by Address[1:0] of this memory address. 94 465 ~ 462: Global Service Pool 95 462: Global Service Pool 0 96 463: Global Service Pool 1 97 464: Global Service Pool 2 98 465: Global Service Pool 3 99 */ 100 STATIC _bcm_th_cosq_time_info_t time_domain_info[BCM_MAX_NUM_UNITS][_BCM_TH_NUM_TIME_DOMAIN] = { 101 { 102 {466}, /* Default all entries are pointing to TIME_0 */ 103 {0}, 104 {0}, 105 {0} 106 } 107 }; 108 109 /* WRED resolution table */ 110 #define _BCM_TH_NUM_WRED_RESOLUTION_TABLE 4 111 STATIC uint32 _bcm_th_wred_resolution_tbl[_BCM_TH_NUM_WRED_RESOLUTION_TABLE] = { 112 1, 113 0, 114 0, 115 0, 116 }; 117 118 typedef struct _bcm_th_cosq_cpu_cosq_config_s { 119 /* All MC queues have DB[idx 0] and MCQE[idx 1] space */ 120 int q_min_limit[2]; 121 int q_shared_limit[2]; 122 uint8 q_limit_dynamic[2]; 123 uint8 q_limit_enable[2]; 124 uint8 q_color_limit_enable[2]; 125 uint8 enable; 126 } _bcm_th_cosq_cpu_cosq_config_t; 127 128 typedef struct _bcm_th_cosq_node_s { 129 bcm_gport_t gport; 130 int numq; 131 int level; 132 int hw_index; 133 int in_use; 134 bcm_gport_t parent_gport; 135 } _bcm_th_cosq_node_t; 136 137 typedef struct _bcm_th_cosq_port_info_s { 138 _bcm_th_cosq_node_t ucast[_BCM_TH_NUM_UCAST_QUEUE_PER_PORT]; 139 _bcm_th_cosq_node_t mcast[_BCM_TH_NUM_MCAST_QUEUE_PER_PORT]; 140 _bcm_th_cosq_node_t sched[_BCM_TH_NUM_SCHEDULER_PER_PORT]; 141 } _bcm_th_cosq_port_info_t; 142 143 typedef struct _bcm_th_cosq_cpu_port_info_s { 144 _bcm_th_cosq_node_t sched[_BCM_TH_NUM_SCHEDULER_PER_PORT]; 145 _bcm_th_cosq_node_t mcast[_BCM_TH_NUM_CPU_MCAST_QUEUE]; 146 } _bcm_th_cosq_cpu_port_info_t; 147 148 typedef struct _bcm_th_mmu_info_s { 149 int gport_tree_created; /* FALSE: No GPORT tree exists */ 150 _bcm_th_cosq_port_info_t *_bcm_th_port_info; 151 _bcm_th_cosq_cpu_port_info_t *_bcm_th_cpu_port_info; 152 int ing_shared_limit[_TH_XPES_PER_DEV]; 153 int egr_db_shared_limit[_TH_XPES_PER_DEV]; 154 int egr_qe_shared_limit[_TH_XPES_PER_DEV]; 155 } _bcm_th_mmu_info_t; 156 157 STATIC _bcm_th_mmu_info_t *_bcm_th_mmu_info[BCM_MAX_NUM_UNITS]; /* MMU info */ 158 STATIC _bcm_th_cosq_port_info_t *_bcm_th_cosq_port_info[BCM_MAX_NUM_UNITS]; 159 STATIC _bcm_th_cosq_cpu_port_info_t *_bcm_th_cosq_cpu_port_info[BCM_MAX_NUM_UNITS]; 160 STATIC soc_profile_mem_t *_bcm_th_cos_map_profile[BCM_MAX_NUM_UNITS]; 161 STATIC soc_profile_mem_t *_bcm_th_wred_profile[BCM_MAX_NUM_UNITS]; 162 STATIC soc_profile_reg_t *_bcm_th_prio2cos_profile[BCM_MAX_NUM_UNITS]; 163 STATIC soc_profile_mem_t *_bcm_th_ifp_cos_map_profile[BCM_MAX_NUM_UNITS]; 164 STATIC _bcm_th_cosq_cpu_cosq_config_t 165 *_bcm_th_cosq_cpu_cosq_config[BCM_MAX_NUM_UNITS][SOC_TH_NUM_CPU_QUEUES]; 166 167 typedef enum { 168 _BCM_TH_COSQ_TYPE_UCAST, 169 _BCM_TH_COSQ_TYPE_MCAST 170 } _bcm_th_cosq_type_t; 171 172 /* Number of COSQs configured for this unit */ 173 #define _TH_NUM_COS(unit) NUM_COS(unit) 174 175 #define _TH_PORT_NUM_COS(unit, port) \ 176 ((IS_CPU_PORT(unit, port)) ? NUM_CPU_COSQ(unit) : \ 177 (IS_LB_PORT(unit, port)) ? 10 : _TH_NUM_COS(unit)) 178 179 180 #define _BCM_TH_MMU_INFO(unit) _bcm_th_mmu_info[(unit)] 181 182 #ifdef BCM_WARM_BOOT_SUPPORT 183 #define BCM_WB_VERSION_1_0 SOC_SCACHE_VERSION(1,0) 184 #define BCM_WB_VERSION_1_1 SOC_SCACHE_VERSION(1,1) 185 #define BCM_WB_VERSION_1_2 SOC_SCACHE_VERSION(1,2) 186 #define BCM_WB_VERSION_1_3 SOC_SCACHE_VERSION(1,3) 187 #define BCM_WB_VERSION_1_4 SOC_SCACHE_VERSION(1,4) 188 #define BCM_WB_VERSION_1_5 SOC_SCACHE_VERSION(1,5) 189 #define BCM_WB_DEFAULT_VERSION BCM_WB_VERSION_1_5 190 191 192 STATIC int 193 _bcm_th_cosq_wb_alloc(int unit) 194 { 195 _bcm_th_mmu_info_t *mmu_info = NULL; 196 soc_scache_handle_t scache_handle; 197 uint8 *scache_ptr = NULL; 198 int rv, alloc_size = 0, max_size = 4096 * 3; 199 _bcm_th_cosq_cpu_port_info_t *cpu_port_info = NULL; 200 201 mmu_info = _bcm_th_mmu_info[unit]; 202 if (mmu_info == NULL) { 203 return BCM_E_INIT; 204 } 205 206 cpu_port_info = _bcm_th_cosq_cpu_port_info[unit]; 207 if (cpu_port_info == NULL) { 208 return BCM_E_INIT; 209 } 210 211 /* 212 * Sync _bcm_th_mmu_info[unit]->ing_shared_limit/ 213 * egr_db_shared_limit/egr_db_shared_limit 214 */ 215 alloc_size += 3 * sizeof(int); 216 217 /* 218 * Sync _bcm_th_cosq_cpu_port_info structure 219 */ 220 221 alloc_size += sizeof(_bcm_th_cosq_cpu_port_info_t); 222 223 /* 224 * Sync the ref_count of IFP_COS_MAPm/COS_MAPm 225 */ 226 alloc_size += (SOC_MEM_SIZE(unit, IFP_COS_MAPm) / _TH_MMU_NUM_INT_PRI) * 227 sizeof(uint16); 228 229 /* 230 * Added in BCM_WB_VERSION_1_1 231 * Sync _bcm_th_cosq_cpu_cosq_config_t structure for all CPU queues 232 */ 233 alloc_size += (SOC_TH_NUM_CPU_QUEUES * 234 sizeof(_bcm_th_cosq_cpu_cosq_config_t)); 235 236 /* 237 * Added in BCM_WB_VERSION_1_1 238 * Sync num_cos value 239 */ 240 alloc_size += sizeof(int); 241 242 /* 243 * Added in BCM_WB_VERSION_1_1 244 * Sync _bcm_pfc_deadlock_control_t structure 245 * Only for TH/TH+ 246 */ 247 if (SOC_IS_TOMAHAWK(unit) && 248 soc_feature(unit, soc_feature_pfc_deadlock)) { 249 alloc_size += sizeof(_bcm_pfc_deadlock_control_t); 250 } 251 252 /* 253 * Added TIME_DOMAIN ref count 254 */ 255 alloc_size += sizeof(_bcm_th_cosq_time_info_t); 256 257 #ifdef BCM_TOMAHAWK_SUPPORT 258 if (soc_feature(unit, soc_feature_ecn_wred)) { 259 uint32 scache_size = 0; 260 BCM_IF_ERROR_RETURN( 261 bcmi_xgs5_ecn_scache_size_get(unit, &scache_size)); 262 alloc_size += scache_size; 263 } 264 #endif 265 #if defined (BCM_TCB_SUPPORT) && defined (INCLUDE_TCB) 266 if (soc_feature(unit, soc_feature_tcb)){ 267 #ifdef BCM_TOMAHAWK2_SUPPORT 268 alloc_size += sizeof(uint16); 269 #endif 270 } 271 #else 272 alloc_size += sizeof(uint16); 273 #endif 274 275 /* 276 * Added in BCM_WB_VERSION_1_4 277 * Second around sync _bcm_pfc_deadlock_control_t structure 278 */ 279 if (soc_feature(unit, soc_feature_pfc_deadlock)) { 280 alloc_size += _bcm_pfc_deadlock_alloc_size(unit); 281 } 282 283 /* 284 * Added in BCM_WB_VERSION_1_5 285 * Sync _bcm_th_cosq_cpu_cosq_config_t structure for all CPU queues 286 */ 287 alloc_size += (_BCM_TH_NUM_WRED_RESOLUTION_TABLE * 288 sizeof(uint32)); 289 290 /* Reserving some space scache for future usecase (max_size) */ 291 if (alloc_size < max_size) { 292 alloc_size = max_size; 293 } else { 294 /* Required size more than max size allocated for Cosq */ 295 return BCM_E_INIT; 296 } 297 298 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_COSQ, 0); 299 300 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, TRUE, alloc_size, 301 &scache_ptr, BCM_WB_DEFAULT_VERSION, NULL); 302 303 if (rv == BCM_E_NOT_FOUND) { 304 rv = BCM_E_NONE; 305 } 306 307 return rv; 308 } 309 #endif /* BCM_WARM_BOOT_SUPPORT */ 310 311 /* 312 * index: degree, value: contangent(degree) * 100 313 * max value is 0xffff (16-bit) at 0 degree 314 * Same as TD2. 315 */ 316 STATIC int 317 _bcm_th_cotangent_lookup_table[] = 318 { 319 /* 0.. 5 */ 65535, 5728, 2863, 1908, 1430, 1143, 320 /* 6..11 */ 951, 814, 711, 631, 567, 514, 321 /* 12..17 */ 470, 433, 401, 373, 348, 327, 322 /* 18..23 */ 307, 290, 274, 260, 247, 235, 323 /* 24..29 */ 224, 214, 205, 196, 188, 180, 324 /* 30..35 */ 173, 166, 160, 153, 148, 142, 325 /* 36..41 */ 137, 132, 127, 123, 119, 115, 326 /* 42..47 */ 111, 107, 103, 100, 96, 93, 327 /* 48..53 */ 90, 86, 83, 80, 78, 75, 328 /* 54..59 */ 72, 70, 67, 64, 62, 60, 329 /* 60..65 */ 57, 55, 53, 50, 48, 46, 330 /* 66..71 */ 44, 42, 40, 38, 36, 34, 331 /* 72..77 */ 32, 30, 28, 26, 24, 23, 332 /* 78..83 */ 21, 19, 17, 15, 14, 12, 333 /* 84..89 */ 10, 8, 6, 5, 3, 1, 334 /* 90 */ 0 335 }; 336 337 /* 338 * Given a slope (angle in degrees) from 0 to 90, return the number of cells 339 * in the range from 0% drop probability to 100% drop probability. 340 * Same as TD2. 341 */ 342 STATIC int 343 _bcm_th_angle_to_cells(int angle) 344 { 345 return (_bcm_th_cotangent_lookup_table[angle]); 346 } 347 348 /* 349 * Given a number of packets in the range from 0% drop probability 350 * to 100% drop probability, return the slope (angle in degrees). 351 * Same as TD2. 352 */ 353 STATIC int 354 _bcm_th_cells_to_angle(int packets) 355 { 356 int angle; 357 358 for (angle = 90; angle >= 0 ; angle--) { 359 if (packets <= _bcm_th_cotangent_lookup_table[angle]) { 360 break; 361 } 362 } 363 return angle; 364 } 365 366 367 /* 368 * Convert HW drop probability to percent value 369 * Same as TD2. 370 */ 371 STATIC int 372 _bcm_th_hw_drop_prob_to_percent[] = { 373 0, /* 0 */ 374 1, /* 1 */ 375 2, /* 2 */ 376 3, /* 3 */ 377 4, /* 4 */ 378 5, /* 5 */ 379 6, /* 6 */ 380 7, /* 7 */ 381 8, /* 8 */ 382 9, /* 9 */ 383 10, /* 10 */ 384 25, /* 11 */ 385 50, /* 12 */ 386 75, /* 13 */ 387 100, /* 14 */ 388 -1 /* 15 */ 389 }; 390 391 STATIC int 392 _bcm_th_percent_to_drop_prob(int percent) 393 { 394 int i; 395 396 for (i = 14; i > 0 ; i--) { 397 if (percent >= _bcm_th_hw_drop_prob_to_percent[i]) { 398 break; 399 } 400 } 401 return i; 402 } 403 404 STATIC int 405 _bcm_th_drop_prob_to_percent(int drop_prob) { 406 return (_bcm_th_hw_drop_prob_to_percent[drop_prob]); 407 } 408 409 /* 410 * Function: 411 * _bcm_th_cosq_node_get 412 * Purpose: 413 * Get internal information of queue group or scheduler type GPORT 414 * Parameters: 415 * unit - (IN) unit number 416 * gport - (IN) queue group/scheduler GPORT identifier 417 * modid - (OUT) module identifier 418 * port - (OUT) port number 419 * id - (OUT) queue group or scheduler identifier 420 * node - (OUT) node structure for the specified GPORT 421 * Returns: 422 * BCM_E_XXX 423 */ 424 STATIC int 425 _bcm_th_cosq_node_get(int unit, bcm_gport_t gport, bcm_module_t *modid, 426 bcm_port_t *port, int *id, _bcm_th_cosq_node_t **node) 427 { 428 _bcm_th_cosq_port_info_t *port_info = NULL; 429 _bcm_th_cosq_cpu_port_info_t *cpu_port_info = NULL; 430 _bcm_th_cosq_node_t *node_base = NULL; 431 bcm_module_t modid_out; 432 bcm_port_t port_out; 433 uint32 encap_id; 434 int index; 435 436 if (_bcm_th_cosq_port_info[unit] == NULL) { 437 return BCM_E_INIT; 438 } 439 if (_bcm_th_cosq_cpu_port_info[unit] == NULL) { 440 return BCM_E_INIT; 441 } 442 443 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 444 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid_out)); 445 port_out = BCM_GPORT_UCAST_QUEUE_GROUP_SYSPORTID_GET(gport); 446 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 447 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid_out)); 448 port_out = BCM_GPORT_MCAST_QUEUE_GROUP_SYSPORTID_GET(gport); 449 } else if (BCM_GPORT_IS_SCHEDULER(gport)) { 450 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid_out)); 451 port_out = BCM_GPORT_SCHEDULER_GET(gport) & 0xff; 452 } else { 453 return BCM_E_PORT; 454 } 455 456 if (!SOC_PORT_VALID(unit, port_out)) { 457 return BCM_E_PORT; 458 } 459 if (IS_CPU_PORT(unit, port_out)) { 460 cpu_port_info = &_bcm_th_cosq_cpu_port_info[unit][port_out]; 461 } else { 462 port_info = &_bcm_th_cosq_port_info[unit][port_out]; 463 } 464 465 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 466 encap_id = BCM_GPORT_UCAST_QUEUE_GROUP_QID_GET(gport); 467 index = encap_id; 468 if (index >= _BCM_TH_NUM_UCAST_QUEUE_PER_PORT) { 469 return BCM_E_PORT; 470 } 471 node_base = port_info->ucast; 472 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 473 encap_id = BCM_GPORT_MCAST_QUEUE_GROUP_QID_GET(gport); 474 index = encap_id; 475 if (!IS_CPU_PORT(unit, port_out) && (index >= _BCM_TH_NUM_MCAST_QUEUE_PER_PORT)) { 476 return BCM_E_PORT; 477 } 478 if (IS_CPU_PORT(unit, port_out) && (index >= _BCM_TH_NUM_CPU_MCAST_QUEUE)) { 479 return BCM_E_PORT; 480 } 481 if (IS_CPU_PORT(unit, port_out)) { 482 node_base = cpu_port_info->mcast; 483 } else { 484 node_base = port_info->mcast; 485 } 486 } else { /* scheduler */ 487 encap_id = (BCM_GPORT_SCHEDULER_GET(gport) >> 16) & 0x3ff; 488 index = encap_id; 489 if (index >= _BCM_TH_NUM_SCHEDULER_PER_PORT) { 490 return BCM_E_PORT; 491 } 492 if (IS_CPU_PORT(unit, port_out)) { 493 node_base = cpu_port_info->sched; 494 } else { 495 node_base = port_info->sched; 496 } 497 } 498 499 if ((node_base == NULL) || 500 (node_base[index].numq == 0) || 501 (node_base[index].in_use == 0)) { 502 return BCM_E_NOT_FOUND; 503 } 504 505 if (modid != NULL) { 506 *modid = modid_out; 507 } 508 if (port != NULL) { 509 *port = port_out; 510 } 511 if (id != NULL) { 512 *id = encap_id; 513 } 514 if (node != NULL) { 515 *node = &node_base[index]; 516 } 517 518 return BCM_E_NONE; 519 } 520 521 /* 522 * Function: 523 * _bcm_th_cosq_localport_resolve 524 * Purpose: 525 * Resolve GPORT if it is a local port 526 * Parameters: 527 * unit - (IN) unit number 528 * gport - (IN) GPORT identifier 529 * local_port - (OUT) local port number 530 * Returns: 531 * BCM_E_XXX 532 */ 533 STATIC int 534 _bcm_th_cosq_localport_resolve(int unit, bcm_gport_t gport, 535 bcm_port_t *local_port) 536 { 537 bcm_module_t module; 538 bcm_port_t port; 539 bcm_trunk_t trunk; 540 int id, result, rv; 541 542 if (!BCM_GPORT_IS_SET(gport)) { 543 if (!SOC_PORT_VALID(unit, gport)) { 544 return BCM_E_PORT; 545 } 546 *local_port = gport; 547 return BCM_E_NONE; 548 } 549 550 rv = _bcm_esw_gport_resolve(unit, gport, &module, &port, &trunk, &id); 551 if (rv == BCM_E_PORT) { 552 /* returning E_PARAM when invalid gport is given as param */ 553 return BCM_E_PARAM; 554 } else if (BCM_FAILURE(rv)) { 555 return rv; 556 } 557 558 BCM_IF_ERROR_RETURN(_bcm_esw_modid_is_local(unit, module, &result)); 559 if (result == FALSE) { 560 return BCM_E_PARAM; 561 } 562 563 *local_port = port; 564 565 return BCM_E_NONE; 566 } 567 568 STATIC int 569 _bcm_th_cosq_egress_sp_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 570 int *p_pool_start, int *p_pool_end) 571 { 572 int local_port; 573 int pool; 574 575 if (cosq == BCM_COS_INVALID) { 576 if (p_pool_start && p_pool_end) { 577 *p_pool_start = 0; 578 *p_pool_end = 3; 579 return BCM_E_NONE; 580 } else { 581 return BCM_E_PARAM; 582 } 583 } 584 585 BCM_IF_ERROR_RETURN 586 (_bcm_th_cosq_index_resolve(unit, gport, cosq, 587 _BCM_TH_COSQ_INDEX_STYLE_EGR_POOL, 588 &local_port, &pool, NULL)); 589 590 if (p_pool_start) { 591 *p_pool_start = pool; 592 } 593 if (p_pool_end) { 594 *p_pool_end = pool; 595 } 596 return BCM_E_NONE; 597 } 598 599 STATIC int 600 _bcm_th_cosq_ingress_pg_get(int unit, bcm_gport_t gport, bcm_cos_queue_t pri, 601 int *p_pg_start, int *p_pg_end) 602 { 603 bcm_port_t local_port; 604 uint32 rval,pool; 605 soc_reg_t reg = INVALIDr; 606 static const soc_reg_t prigroup_reg[] = { 607 THDI_PORT_PRI_GRP0r, THDI_PORT_PRI_GRP1r 608 }; 609 static const soc_field_t prigroup_field[] = { 610 PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf, 611 PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf, 612 PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf, 613 PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf 614 }; 615 616 if (pri == BCM_COS_INVALID) { 617 *p_pg_start = 0; 618 *p_pg_end = 7; 619 return BCM_E_NONE; 620 } 621 622 BCM_IF_ERROR_RETURN 623 (_bcm_th_cosq_localport_resolve(unit, gport, &local_port)); 624 625 if (!SOC_PORT_VALID(unit, local_port)) { 626 return BCM_E_PORT; 627 } 628 629 if (pri >= _TH_MMU_NUM_INT_PRI) { 630 return BCM_E_PARAM; 631 } 632 /* get PG for port using Port+Cos */ 633 if (pri < (_TH_MMU_NUM_INT_PRI / 2)) { 634 reg = prigroup_reg[0]; 635 } else { 636 reg = prigroup_reg[1]; 637 } 638 639 SOC_IF_ERROR_RETURN 640 (soc_reg32_get(unit, reg, local_port, 0, &rval)); 641 pool = soc_reg_field_get(unit, reg, rval, prigroup_field[pri]); 642 643 if (p_pg_start) { 644 *p_pg_start = pool; 645 } 646 647 if (p_pg_end) { 648 *p_pg_end = pool; 649 } 650 651 return BCM_E_NONE; 652 } 653 654 655 /* 656 * This function is used to get shared pool 657 * for given Ingress [Port, Priority] 658 */ 659 STATIC int 660 _bcm_th_cosq_ingress_sp_get(int unit, bcm_gport_t gport, bcm_cos_t pri, 661 int *p_pool_start, int *p_pool_end) 662 { 663 int local_port; 664 uint32 rval, pool; 665 int pri_grp; 666 static const soc_field_t prigroup_spid_field[] = { 667 PG0_SPIDf, PG1_SPIDf, PG2_SPIDf, PG3_SPIDf, 668 PG4_SPIDf, PG5_SPIDf, PG6_SPIDf, PG7_SPIDf 669 }; 670 671 if (pri == BCM_COS_INVALID) { 672 if (p_pool_start && p_pool_end) { 673 *p_pool_start = 0; 674 *p_pool_end = 3; 675 return BCM_E_NONE; 676 } else { 677 return BCM_E_PARAM; 678 } 679 } 680 681 if ((pri < 0) || (pri >= _TH_MMU_NUM_INT_PRI)) { 682 /* Error. Input pri > Max Pri_Grp */ 683 return BCM_E_PARAM; 684 } 685 686 BCM_IF_ERROR_RETURN 687 (_bcm_th_cosq_ingress_pg_get(unit, gport, pri, &pri_grp, &pri_grp)); 688 689 BCM_IF_ERROR_RETURN 690 (_bcm_th_cosq_localport_resolve(unit, gport, &local_port)); 691 692 if (!SOC_PORT_VALID(unit, local_port)) { 693 return BCM_E_PORT; 694 } 695 696 if (pri_grp >= _TH_MMU_NUM_PG) { 697 return BCM_E_PARAM; 698 } 699 700 SOC_IF_ERROR_RETURN(READ_THDI_PORT_PG_SPIDr(unit, local_port, &rval)); 701 pool = soc_reg_field_get(unit, THDI_PORT_PG_SPIDr, rval, 702 prigroup_spid_field[pri_grp]); 703 704 if (p_pool_start) { 705 *p_pool_start = pool; 706 } 707 if (p_pool_end) { 708 *p_pool_end = pool; 709 } 710 return BCM_E_NONE; 711 } 712 713 /* 714 * This function is used to get shared pool 715 * for given Ingress [Port, Priority_group] 716 */ 717 STATIC int 718 _bcm_th_cosq_ingress_sp_get_by_pg(int unit, bcm_gport_t gport, bcm_cos_queue_t pri_grp, 719 int *p_pool_start, int *p_pool_end) 720 { 721 int local_port; 722 uint32 rval, pool; 723 static const soc_field_t prigroup_spid_field[] = { 724 PG0_SPIDf, PG1_SPIDf, PG2_SPIDf, PG3_SPIDf, 725 PG4_SPIDf, PG5_SPIDf, PG6_SPIDf, PG7_SPIDf 726 }; 727 728 if (pri_grp == BCM_COS_INVALID) { 729 if (p_pool_start && p_pool_end) { 730 *p_pool_start = 0; 731 *p_pool_end = 3; 732 return BCM_E_NONE; 733 } else { 734 return BCM_E_PARAM; 735 } 736 } 737 738 BCM_IF_ERROR_RETURN 739 (_bcm_th_cosq_localport_resolve(unit, gport, &local_port)); 740 741 if (!SOC_PORT_VALID(unit, local_port)) { 742 return BCM_E_PORT; 743 } 744 745 if (pri_grp >= _TH_MMU_NUM_PG) { 746 return BCM_E_PARAM; 747 } 748 749 SOC_IF_ERROR_RETURN(READ_THDI_PORT_PG_SPIDr(unit, local_port, &rval)); 750 pool = soc_reg_field_get(unit, THDI_PORT_PG_SPIDr, rval, 751 prigroup_spid_field[pri_grp]); 752 753 if (p_pool_start) { 754 *p_pool_start = pool; 755 } 756 if (p_pool_end) { 757 *p_pool_end = pool; 758 } 759 return BCM_E_NONE; 760 } 761 762 763 /* 764 * This function is used to get headroom pool 765 * for given Ingress [Port, Priority] 766 */ 767 STATIC int 768 _bcm_th_cosq_ingress_hdrm_pool_get(int unit, bcm_gport_t gport, 769 bcm_cos_t pri, 770 int *p_hdrm_pool_start, 771 int *p_hdrm_pool_end) 772 { 773 int local_port; 774 uint32 rval, hdrm_pool; 775 int pri_grp; 776 static const soc_field_t prigroup_hpid_field[] = { 777 PG0_HPIDf, PG1_HPIDf, PG2_HPIDf, PG3_HPIDf, 778 PG4_HPIDf, PG5_HPIDf, PG6_HPIDf, PG7_HPIDf 779 }; 780 781 if (pri == BCM_COS_INVALID) { 782 if (p_hdrm_pool_start && p_hdrm_pool_end) { 783 *p_hdrm_pool_start = 0; 784 *p_hdrm_pool_end = 3; 785 return BCM_E_NONE; 786 } else { 787 return BCM_E_PARAM; 788 } 789 } 790 791 if ((pri < 0) || (pri >= _TH_MMU_NUM_INT_PRI)) { 792 /* Error. Input pri > Max Pri_Grp */ 793 return BCM_E_PARAM; 794 } 795 796 BCM_IF_ERROR_RETURN 797 (_bcm_th_cosq_ingress_pg_get(unit, gport, pri, &pri_grp, &pri_grp)); 798 799 BCM_IF_ERROR_RETURN 800 (_bcm_th_cosq_localport_resolve(unit, gport, &local_port)); 801 802 if (!SOC_PORT_VALID(unit, local_port)) { 803 return BCM_E_PORT; 804 } 805 806 if (pri_grp >= _TH_MMU_NUM_PG) { 807 return BCM_E_PARAM; 808 } 809 810 SOC_IF_ERROR_RETURN(READ_THDI_HDRM_PORT_PG_HPIDr(unit, local_port, &rval)); 811 hdrm_pool = soc_reg_field_get(unit, THDI_HDRM_PORT_PG_HPIDr, rval, 812 prigroup_hpid_field[pri_grp]); 813 814 if (p_hdrm_pool_start) { 815 *p_hdrm_pool_start = hdrm_pool; 816 } 817 if (p_hdrm_pool_end) { 818 *p_hdrm_pool_end = hdrm_pool; 819 } 820 821 return BCM_E_NONE; 822 } 823 824 /* 825 * Function: 826 * _bcm_th_cosq_port_cos_resolve 827 * Purpose: 828 * Find UC/MC queue gport for a given logical port 829 * and cos value. 830 * Parameters: 831 * unit - (IN) unit number 832 * port - (IN) logical port 833 * cos - (IN) cos value 834 * style - (IN) index style 835 * (_BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE or 836 * _BCM_TH_COSQ_INDEX_STYLE_MCAST_QUEUE) 837 * gport - (OUT) Queue gport 838 * Returns: 839 * BCM_E_XXX 840 */ 841 int 842 _bcm_th_cosq_port_cos_resolve(int unit, bcm_port_t port, bcm_cos_t cos, 843 _bcm_th_cosq_index_style_t style, 844 bcm_gport_t *gport) 845 { 846 _bcm_th_cosq_port_info_t *port_info = NULL; 847 _bcm_th_cosq_cpu_port_info_t *cpu_port_info = NULL; 848 849 if (gport == NULL) { 850 return BCM_E_PARAM; 851 } 852 853 if (_bcm_th_cosq_port_info[unit] == NULL) { 854 return BCM_E_INIT; 855 } 856 if (_bcm_th_cosq_cpu_port_info[unit] == NULL) { 857 return BCM_E_INIT; 858 } 859 860 if ((IS_CPU_PORT(unit, port)) && 861 (style == _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE)) { 862 return BCM_E_PARAM; 863 } 864 865 if (cos < 0) { 866 return BCM_E_PARAM; 867 } 868 869 if (!SOC_PORT_VALID(unit, port)) { 870 return BCM_E_PORT; 871 } 872 873 if (_BCM_TH_MMU_INFO(unit)->gport_tree_created != TRUE) { 874 return BCM_E_INTERNAL; 875 } 876 877 if (IS_CPU_PORT(unit, port)) { 878 cpu_port_info = _bcm_th_cosq_cpu_port_info[unit]; 879 } else { 880 port_info = &_bcm_th_cosq_port_info[unit][port]; 881 } 882 883 if (style == _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE) { 884 if (cos >= _BCM_TH_NUM_UCAST_QUEUE_PER_PORT) { 885 return BCM_E_PARAM; 886 } 887 *gport = port_info->ucast[cos].gport; 888 } else if (style == _BCM_TH_COSQ_INDEX_STYLE_MCAST_QUEUE) { 889 if (IS_CPU_PORT(unit, port)) { 890 if (cos >= _BCM_TH_NUM_CPU_MCAST_QUEUE) { 891 return BCM_E_PARAM; 892 } 893 *gport = cpu_port_info->mcast[cos].gport; 894 } else { 895 if (cos >= _BCM_TH_NUM_MCAST_QUEUE_PER_PORT) { 896 return BCM_E_PARAM; 897 } 898 *gport = port_info->mcast[cos].gport; 899 } 900 } else { 901 return BCM_E_INTERNAL; 902 } 903 904 return BCM_E_NONE; 905 } 906 907 int 908 _bcm_th_cosq_port_resolve(int unit, bcm_gport_t gport, bcm_module_t *modid, 909 bcm_port_t *port, bcm_trunk_t *trunk_id, int *id, 910 int *qnum) 911 { 912 _bcm_th_cosq_node_t *node; 913 914 BCM_IF_ERROR_RETURN 915 (_bcm_th_cosq_node_get(unit, gport, modid, port, id, &node)); 916 *trunk_id = -1; 917 918 if (qnum) { 919 if (node->hw_index == -1) { 920 return BCM_E_PARAM; 921 } 922 *qnum = node->hw_index; 923 } 924 925 return BCM_E_NONE; 926 } 927 928 /* 929 * Function: 930 * _bcm_th_cosq_index_resolve 931 * Purpose: 932 * Find hardware index for the given port/cosq 933 * Parameters: 934 * unit - (IN) unit number 935 * port - (IN) port number or GPORT identifier 936 * cosq - (IN) COS queue number 937 * style - (IN) index style (_BCM_KA_COSQ_INDEX_STYLE_XXX) 938 * local_port - (OUT) local port number 939 * index - (OUT) result index 940 * count - (OUT) number of index 941 * Returns: 942 * BCM_E_XXX 943 */ 944 int 945 _bcm_th_cosq_index_resolve(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 946 _bcm_th_cosq_index_style_t style, 947 bcm_port_t *local_port, int *index, int *count) 948 { 949 bcm_port_t resolved_port; 950 soc_info_t *si; 951 int resolved_index = -1; 952 int id, startq, numq = 0; 953 int phy_port, pipe; 954 int uc_base = 0, mc_base = 0, cpu_mc_base = 0; /* Q base number */ 955 int mmu_port; /* global mmu port number */ 956 int local_mmu_port; /* local mmu port number - local to per pipe */ 957 _bcm_th_cosq_node_t *node; 958 uint32 entry0[SOC_MAX_MEM_WORDS]; 959 soc_mem_t mem; 960 961 si = &SOC_INFO(unit); 962 963 if (cosq < -1) { 964 return BCM_E_PARAM; 965 } else if (cosq == -1) { 966 startq = 0; 967 numq = NUM_COS(unit); 968 } else { 969 startq = cosq; 970 numq = 1; 971 } 972 973 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 974 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) || 975 BCM_GPORT_IS_SCHEDULER(port)) { 976 BCM_IF_ERROR_RETURN 977 (_bcm_th_cosq_node_get(unit, port, NULL, &resolved_port, &id, 978 &node)); 979 if (resolved_port < 0) { 980 return BCM_E_PORT; 981 } 982 } else { 983 BCM_IF_ERROR_RETURN 984 (_bcm_th_cosq_localport_resolve(unit, port, &resolved_port)); 985 if (resolved_port < 0) { 986 return BCM_E_PORT; 987 } 988 node = NULL; 989 numq = (IS_CPU_PORT(unit, resolved_port)) ? NUM_CPU_COSQ(unit) : NUM_COS(unit); 990 } 991 phy_port = si->port_l2p_mapping[resolved_port]; 992 mmu_port = si->port_p2m_mapping[phy_port]; 993 local_mmu_port = mmu_port & (SOC_TH_MMU_PORT_STRIDE - 1); 994 mc_base = si->port_cosq_base[resolved_port]; 995 uc_base = si->port_uc_cosq_base[resolved_port]; 996 997 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, resolved_port, &pipe)); 998 999 switch (style) { 1000 case _BCM_TH_COSQ_INDEX_STYLE_WRED_DEVICE: 1001 if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 1002 return BCM_E_PARAM; 1003 } 1004 if ((port == -1) || (cosq == -1)) { 1005 numq = _TH_MMU_NUM_POOL; /* 4 Global Service Pools */ 1006 resolved_index = 462; 1007 } else { 1008 BCM_IF_ERROR_RETURN 1009 (_bcm_th_cosq_egress_sp_get(unit, port, cosq, 1010 &resolved_index, 1011 NULL)); 1012 numq = 1; 1013 resolved_index += 462; 1014 } 1015 break; 1016 case _BCM_TH_COSQ_INDEX_STYLE_WRED_PORT: 1017 if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 1018 return BCM_E_PARAM; 1019 } 1020 resolved_index = 0; 1021 if (cosq != -1) { 1022 BCM_IF_ERROR_RETURN 1023 (_bcm_th_cosq_egress_sp_get(unit, port, cosq, 1024 &resolved_index, 1025 NULL)); 1026 } 1027 resolved_index += SOC_TH_NUM_UC_QUEUES_PER_PIPE + 1028 (local_mmu_port * 4); 1029 numq = (cosq == -1) ? 4: 1; 1030 break; 1031 case _BCM_TH_COSQ_INDEX_STYLE_WRED_QUEUE: 1032 if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 1033 return BCM_E_PARAM; 1034 } 1035 resolved_index = local_mmu_port * _BCM_TH_NUM_UCAST_QUEUE_PER_PORT; 1036 if (cosq != -1) { 1037 if (cosq >= NUM_COS(unit)) { 1038 return BCM_E_PARAM; 1039 } 1040 resolved_index += cosq; 1041 } 1042 numq = (cosq == -1) ? NUM_COS(unit): 1; 1043 break; 1044 case _BCM_TH_COSQ_INDEX_STYLE_EGR_POOL: 1045 if ((node != NULL) && (!BCM_GPORT_IS_MODPORT(port))) { 1046 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) { 1047 /* regular unicast queue */ 1048 resolved_index = (uc_base + (node->hw_index % 1049 _BCM_TH_NUM_UCAST_QUEUE_PER_PORT)); 1050 mem = MMU_THDU_Q_TO_QGRP_MAPm; 1051 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 1052 if (IS_CPU_PORT(unit, resolved_port)) { 1053 cpu_mc_base = si->port_cosq_base[CMIC_PORT(unit)]; 1054 resolved_index = cpu_mc_base + 1055 ((node->hw_index - cpu_mc_base) % 1056 _BCM_TH_NUM_CPU_MCAST_QUEUE); 1057 } else { 1058 resolved_index = (mc_base + (node->hw_index % 1059 _BCM_TH_NUM_MCAST_QUEUE_PER_PORT)); 1060 } 1061 mem = MMU_THDM_MCQE_QUEUE_CONFIGm; 1062 } else { /* scheduler */ 1063 return BCM_E_PARAM; 1064 } 1065 } else { /* node == NULL */ 1066 numq = si->port_num_cosq[resolved_port]; 1067 if (startq >= numq) { 1068 return BCM_E_PARAM; 1069 } 1070 resolved_index = (local_mmu_port * 1071 _BCM_TH_NUM_UCAST_QUEUE_PER_PORT) + startq; 1072 mem = MMU_THDU_Q_TO_QGRP_MAPm; 1073 } 1074 mem = SOC_MEM_UNIQUE_ACC(unit, mem)[pipe]; 1075 1076 SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, resolved_index, 1077 entry0)); 1078 resolved_index = soc_mem_field32_get(unit, mem, entry0, Q_SPIDf); 1079 break; 1080 case _BCM_TH_COSQ_INDEX_STYLE_COS: 1081 if (node) { 1082 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) { 1083 resolved_index = node->hw_index % 1084 _BCM_TH_NUM_UCAST_QUEUE_PER_PORT; 1085 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 1086 if (IS_CPU_PORT(unit, resolved_port)) { 1087 cpu_mc_base = si->port_cosq_base[CMIC_PORT(unit)]; 1088 resolved_index = (node->hw_index - cpu_mc_base) % 1089 NUM_CPU_COSQ(unit); 1090 } else { 1091 resolved_index = node->hw_index % 1092 _BCM_TH_NUM_MCAST_QUEUE_PER_PORT; 1093 } 1094 } else { 1095 resolved_index = node->hw_index % 1096 _BCM_TH_NUM_SCHEDULER_PER_PORT; 1097 } 1098 } else { 1099 resolved_index = startq; 1100 } 1101 break; 1102 case _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE: 1103 /* Return hw_index for given unicast queue gport */ 1104 if (node) { 1105 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) { 1106 resolved_index = (uc_base + (node->hw_index % 1107 _BCM_TH_NUM_UCAST_QUEUE_PER_PORT)); 1108 } else { 1109 return BCM_E_PARAM; 1110 } 1111 } else { 1112 if (startq >= numq) { 1113 return BCM_E_PARAM; 1114 } 1115 resolved_index = uc_base + startq; 1116 } 1117 break; 1118 case _BCM_TH_COSQ_INDEX_STYLE_MCAST_QUEUE: 1119 /* Return hw_index for given multicast queue gport */ 1120 if (node) { 1121 if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 1122 if (IS_CPU_PORT(unit, resolved_port)) { 1123 cpu_mc_base = si->port_cosq_base[CMIC_PORT(unit)]; 1124 resolved_index = cpu_mc_base + 1125 ((node->hw_index - cpu_mc_base) % 1126 _BCM_TH_NUM_CPU_MCAST_QUEUE); 1127 } else { 1128 resolved_index = (mc_base + (node->hw_index % 1129 _BCM_TH_NUM_MCAST_QUEUE_PER_PORT)); 1130 } 1131 } else { 1132 return BCM_E_PARAM; 1133 } 1134 } else { 1135 if (startq >= numq) { 1136 return BCM_E_PARAM; 1137 } 1138 resolved_index = mc_base + startq; 1139 } 1140 break; 1141 default: 1142 return BCM_E_PARAM; 1143 } 1144 1145 if (index) { 1146 *index = resolved_index; 1147 } 1148 if (local_port) { 1149 *local_port = resolved_port; 1150 } 1151 if (count) { 1152 *count = (cosq == -1) ? numq : 1; 1153 } 1154 1155 return BCM_E_NONE; 1156 } 1157 1158 STATIC int 1159 _bcm_th_cosq_cpu_port_info_dump(int unit) 1160 { 1161 _bcm_th_cosq_cpu_port_info_t *port_info; 1162 bcm_port_t port = 0; /* CPU Port */ 1163 _bcm_th_cosq_node_t *node; 1164 int index; 1165 soc_th_sched_mode_e sched_mode = 0; 1166 int weight = 0; 1167 char *sched_modes[] = {"X", "SP", "WRR", "WERR"}; 1168 1169 if (!SOC_PORT_VALID(unit, port)) { 1170 return BCM_E_PORT; 1171 } 1172 port_info = _bcm_th_cosq_cpu_port_info[unit]; 1173 1174 LOG_CLI((BSL_META_U(unit, 1175 "=== CPU PORT ===\n"))); 1176 1177 LOG_CLI((BSL_META_U(unit, 1178 "L0 Nodes\n"))); 1179 for (index = 0; index < _BCM_TH_NUM_SCHEDULER_PER_PORT; index++) { 1180 /* Node */ 1181 node = &port_info->sched[index]; 1182 1183 BCM_IF_ERROR_RETURN( 1184 soc_th_cosq_sched_mode_get(unit, port, node->level, index, 1185 &sched_mode, &weight, 0)); 1186 LOG_CLI((BSL_META_U(unit, 1187 " LO.%d: GPORT=0x%x MODE=%s WT=%d\n"), 1188 index, node->gport, 1189 sched_modes[sched_mode], weight)); 1190 } 1191 1192 LOG_CLI((BSL_META_U(unit, 1193 "\nMC Queues\n"))); 1194 for (index = 0; index < _BCM_TH_NUM_CPU_MCAST_QUEUE; index++) { 1195 int parent_id = 0; 1196 /* MC Queue */ 1197 node = &port_info->mcast[index]; 1198 BCM_IF_ERROR_RETURN( 1199 soc_th_cosq_sched_mode_get(unit, port, node->level, index, 1200 &sched_mode, &weight, 1)); 1201 BCM_IF_ERROR_RETURN( 1202 _bcm_th_cosq_node_get(unit, node->parent_gport, NULL, NULL, 1203 &parent_id, NULL)); 1204 LOG_CLI((BSL_META_U(unit, 1205 " MC.%d: GPORT=0x%x MODE=%s WT=%d" 1206 " PARENT=L0.%d\n"), 1207 index, node->gport, 1208 sched_modes[sched_mode], weight, 1209 parent_id)); 1210 } 1211 LOG_CLI((BSL_META_U(unit, 1212 "=========== \n"))); 1213 1214 return BCM_E_NONE; 1215 } 1216 1217 STATIC int 1218 _bcm_th_cosq_port_info_dump(int unit, bcm_port_t port) 1219 { 1220 _bcm_th_cosq_port_info_t *port_info; 1221 _bcm_th_cosq_node_t *node; 1222 int index, empty; 1223 soc_th_sched_mode_e sched_mode = 0; 1224 int weight = 0; 1225 char *sched_modes[] = {"X", "SP", "WRR", "WERR"}; 1226 1227 if (!SOC_PORT_VALID(unit, port)) { 1228 return BCM_E_PORT; 1229 } 1230 port_info = &_bcm_th_cosq_port_info[unit][port]; 1231 1232 empty = TRUE; 1233 for (index = 0; index < _BCM_TH_NUM_SCHEDULER_PER_PORT; index++) { 1234 if (port_info->sched[index].numq > 0) { 1235 empty = FALSE; 1236 break; 1237 } 1238 } 1239 if (empty) { 1240 for (index = 0; index < _BCM_TH_NUM_UCAST_QUEUE_PER_PORT; index++) { 1241 if (port_info->ucast[index].numq > 0) { 1242 empty = FALSE; 1243 break; 1244 } 1245 } 1246 } 1247 if (empty) { 1248 for (index = 0; index < _BCM_TH_NUM_MCAST_QUEUE_PER_PORT; index++) { 1249 if (port_info->mcast[index].numq > 0) { 1250 empty = FALSE; 1251 break; 1252 } 1253 } 1254 } 1255 1256 if (empty == TRUE) { 1257 return BCM_E_NOT_FOUND; 1258 } 1259 1260 LOG_CLI((BSL_META_U(unit, 1261 "=== PORT %d\n"), port)); 1262 1263 for (index = 0; index < _BCM_TH_NUM_SCHEDULER_PER_PORT; index++) { 1264 /* Node */ 1265 node = &port_info->sched[index]; 1266 1267 BCM_IF_ERROR_RETURN( 1268 soc_th_cosq_sched_mode_get(unit, port, node->level, index, 1269 &sched_mode, &weight, 0)); 1270 LOG_CLI((BSL_META_U(unit, 1271 "LO.%d: GPORT=0x%x MODE=%s WT=%d\n"), 1272 index, node->gport, 1273 sched_modes[sched_mode], weight)); 1274 1275 /* UC Queue */ 1276 node = &port_info->ucast[index % _BCM_TH_NUM_UCAST_QUEUE_PER_PORT]; 1277 BCM_IF_ERROR_RETURN( 1278 soc_th_cosq_sched_mode_get(unit, port, node->level, index, 1279 &sched_mode, &weight, 0)); 1280 LOG_CLI((BSL_META_U(unit, 1281 " UC.%d: GPORT=0x%x MODE=%s WT=%d\n"), 1282 index, node->gport, 1283 sched_modes[sched_mode], weight)); 1284 1285 /* MC Queue */ 1286 node = &port_info->mcast[index % _BCM_TH_NUM_MCAST_QUEUE_PER_PORT]; 1287 BCM_IF_ERROR_RETURN( 1288 soc_th_cosq_sched_mode_get(unit, port, node->level, index, 1289 &sched_mode, &weight, 1)); 1290 LOG_CLI((BSL_META_U(unit, 1291 " MC.%d: GPORT=0x%x MODE=%s WT=%d\n"), 1292 index, node->gport, 1293 sched_modes[sched_mode], weight)); 1294 } 1295 LOG_CLI((BSL_META_U(unit, 1296 "=========== \n"))); 1297 1298 return BCM_E_NONE; 1299 } 1300 1301 /* 1302 * Function: 1303 * bcm_th_cosq_gport_get 1304 * Purpose: 1305 * Get a cosq gport structure 1306 * Parameters: 1307 * unit - (IN) unit number 1308 * gport - (IN) GPORT identifier 1309 * port - (OUT) port number 1310 * numq - (OUT) number of COS queues 1311 * flags - (OUT) flags (BCM_COSQ_GPORT_XXX) 1312 * Returns: 1313 * BCM_E_XXX 1314 */ 1315 int 1316 bcm_th_cosq_gport_get(int unit, bcm_gport_t gport, bcm_gport_t *port, 1317 int *numq, uint32 *flags) 1318 { 1319 _bcm_th_cosq_node_t *node; 1320 bcm_port_t local_port; 1321 bcm_module_t modid; 1322 _bcm_gport_dest_t dest; 1323 1324 if (port == NULL || numq == NULL || flags == NULL) { 1325 return BCM_E_PARAM; 1326 } 1327 1328 LOG_INFO(BSL_LS_BCM_COSQ, 1329 (BSL_META_U(unit, 1330 "bcm_th_cosq_gport_get: unit=%d gport=0x%x\n"), 1331 unit, gport)); 1332 1333 if ((BCM_GPORT_IS_SCHEDULER(gport)) || 1334 BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 1335 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) || 1336 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport)) { 1337 BCM_IF_ERROR_RETURN 1338 (_bcm_th_cosq_node_get(unit, gport, NULL, &local_port, 1339 NULL, &node)); 1340 1341 *numq = node->numq; 1342 1343 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 1344 *flags = BCM_COSQ_GPORT_UCAST_QUEUE_GROUP; 1345 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 1346 *flags = BCM_COSQ_GPORT_MCAST_QUEUE_GROUP; 1347 } else if (BCM_GPORT_IS_SCHEDULER(gport)) { 1348 *flags = BCM_COSQ_GPORT_SCHEDULER; 1349 } else { 1350 *flags = 0; 1351 } 1352 } else { 1353 BCM_IF_ERROR_RETURN 1354 (_bcm_th_cosq_localport_resolve(unit, gport, &local_port)); 1355 *flags = 0; 1356 *numq = _BCM_TH_NUM_SCHEDULER_PER_PORT; 1357 } 1358 1359 if (SOC_USE_GPORT(unit)) { 1360 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid)); 1361 dest.gport_type = _SHR_GPORT_TYPE_MODPORT; 1362 dest.modid = modid; 1363 dest.port = local_port; 1364 BCM_IF_ERROR_RETURN(_bcm_esw_gport_construct(unit, &dest, port)); 1365 } else { 1366 *port = local_port; 1367 } 1368 1369 LOG_INFO(BSL_LS_BCM_COSQ, 1370 (BSL_META_U(unit, 1371 " port=0x%x numq=%d flags=0x%x\n"), 1372 *port, *numq, *flags)); 1373 1374 return BCM_E_NONE; 1375 } 1376 1377 int 1378 bcm_th_cosq_config_set(int unit, int numq) 1379 { 1380 port_cos_map_entry_t cos_map_entries[16]; 1381 void *entries[1]; 1382 uint32 index; 1383 int count; 1384 bcm_port_t port; 1385 int cos, prio, ref_count = -1; 1386 uint32 i; 1387 soc_mem_t mem = INVALIDm; 1388 1389 if (numq < 1 || numq > BCM_TH_COS_MAX) { 1390 return BCM_E_PARAM; 1391 } 1392 1393 index = 0; 1394 while (index < soc_mem_index_count(unit, PORT_COS_MAPm)) { 1395 BCM_IF_ERROR_RETURN(soc_profile_mem_ref_count_get(unit, 1396 _bcm_th_cos_map_profile[unit], 1397 index, &ref_count)); 1398 if (ref_count > 0) { 1399 while (ref_count) { 1400 if (!soc_profile_mem_delete(unit, 1401 _bcm_th_cos_map_profile[unit], index)) { 1402 ref_count -= 1; 1403 } 1404 } 1405 } 1406 index += 16; 1407 } 1408 1409 /* Distribute first 8 internal priority levels into the specified number 1410 * of cosq, map remaining internal priority levels to highest priority 1411 * cosq */ 1412 sal_memset(cos_map_entries, 0, sizeof(cos_map_entries)); 1413 entries[0] = &cos_map_entries; 1414 prio = 0; 1415 mem = PORT_COS_MAPm; 1416 1417 for (cos = 0; cos < numq; cos++) { 1418 for (i = 8 / numq + (cos < 8 % numq ? 1 : 0); i > 0; i--) { 1419 soc_mem_field32_set(unit, mem, &cos_map_entries[prio], 1420 UC_COS1f, cos); 1421 soc_mem_field32_set(unit, mem, &cos_map_entries[prio], 1422 MC_COS1f, cos); 1423 prio++; 1424 } 1425 } 1426 for (prio = 8; prio < 16; prio++) { 1427 /*TH may have up to 10 cosq.*/ 1428 if (prio < numq) { 1429 soc_mem_field32_set(unit, mem, &cos_map_entries[prio], UC_COS1f, 1430 prio); 1431 soc_mem_field32_set(unit, mem, &cos_map_entries[prio], MC_COS1f, 1432 prio); 1433 } else { 1434 soc_mem_field32_set(unit, mem, &cos_map_entries[prio], UC_COS1f, 1435 numq - 1); 1436 soc_mem_field32_set(unit, mem, &cos_map_entries[prio], MC_COS1f, 1437 numq - 1); 1438 } 1439 } 1440 1441 /* Map internal priority levels to CPU CoS queues */ 1442 BCM_IF_ERROR_RETURN(_bcm_esw_cpu_cosq_mapping_default_set(unit, numq)); 1443 1444 BCM_IF_ERROR_RETURN 1445 (soc_profile_mem_add(unit, _bcm_th_cos_map_profile[unit], entries, 16, 1446 &index)); 1447 count = 0; 1448 PBMP_ALL_ITER(unit, port) { 1449 BCM_IF_ERROR_RETURN 1450 (soc_mem_field32_modify(unit, COS_MAP_SELm, port, SELECTf, 1451 index / 16)); 1452 count++; 1453 } 1454 if (SOC_INFO(unit).cpu_hg_index != -1) { 1455 BCM_IF_ERROR_RETURN 1456 (soc_mem_field32_modify(unit, COS_MAP_SELm, 1457 SOC_INFO(unit).cpu_hg_index, SELECTf, 1458 index / 16)); 1459 count++; 1460 } 1461 for (i = 1; i < count; i++) { 1462 soc_profile_mem_reference(unit, _bcm_th_cos_map_profile[unit], index, 1463 0); 1464 } 1465 1466 _TH_NUM_COS(unit) = numq; 1467 1468 return BCM_E_NONE; 1469 } 1470 1471 /* 1472 * Function: 1473 * bcm_th_cosq_config_get 1474 * Purpose: 1475 * Get the number of cos queues 1476 * Parameters: 1477 * unit - unit number 1478 * numq - (Output) number of cosq 1479 * Returns: 1480 * BCM_E_XXX 1481 */ 1482 int 1483 bcm_th_cosq_config_get(int unit, int *numq) 1484 { 1485 if (numq != NULL) { 1486 *numq = _TH_NUM_COS(unit); 1487 } 1488 1489 return BCM_E_NONE; 1490 } 1491 1492 /* 1493 * Function: 1494 * _bcm_th_cosq_sched_set 1495 * Purpose: 1496 * Set scheduling mode 1497 * Parameters: 1498 * unit - (IN) unit number 1499 * port - (IN) port number or GPORT identifier 1500 * cosq - (IN) COS queue number 1501 * mode - (IN) scheduling mode (BCM_COSQ_XXX) 1502 * weight - (IN) weight 1503 * Returns: 1504 * BCM_E_XXX 1505 */ 1506 STATIC int 1507 _bcm_th_cosq_sched_set(int unit, bcm_port_t gport, bcm_cos_queue_t cosq, 1508 int mode, int weight) 1509 { 1510 soc_th_sched_mode_e sched_mode; 1511 bcm_port_t local_port; 1512 int lwts = 1, child_index=0, lvl = SOC_TH_NODE_LVL_L0, mc = 0; 1513 1514 if (cosq < 0) { 1515 if (cosq == -1) { 1516 /* caller needs to resolve the wild card value (-1) */ 1517 return BCM_E_INTERNAL; 1518 } else { /* reject all other negative value */ 1519 return BCM_E_PARAM; 1520 } 1521 } 1522 if ((weight < 0) || (weight > 127)) { 1523 return BCM_E_PARAM; 1524 } 1525 1526 switch(mode) { 1527 case BCM_COSQ_STRICT: 1528 sched_mode = SOC_TH_SCHED_MODE_STRICT; 1529 lwts = 0; 1530 break; 1531 case BCM_COSQ_ROUND_ROBIN: 1532 sched_mode = SOC_TH_SCHED_MODE_WRR; 1533 lwts = 1; 1534 break; 1535 case BCM_COSQ_WEIGHTED_ROUND_ROBIN: 1536 sched_mode = SOC_TH_SCHED_MODE_WRR; 1537 lwts = weight; 1538 break; 1539 case BCM_COSQ_DEFICIT_ROUND_ROBIN: 1540 sched_mode = SOC_TH_SCHED_MODE_WERR; 1541 lwts = weight; 1542 break; 1543 default: 1544 return BCM_E_PARAM; 1545 } 1546 1547 /* Weight = 0 corresponds to Strict Mode */ 1548 if (lwts == 0) { 1549 sched_mode = SOC_TH_SCHED_MODE_STRICT; 1550 } 1551 1552 child_index = cosq; 1553 BCM_IF_ERROR_RETURN 1554 (_bcm_th_cosq_localport_resolve(unit, gport, &local_port)); 1555 1556 if (BCM_GPORT_IS_SCHEDULER(gport)) { 1557 /* We need to set lvl = L0(schedular node) so that sched mode is set at it's parent */ 1558 lvl = SOC_TH_NODE_LVL_L0; 1559 } else if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 1560 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 1561 /* We need to set lvl = L1(UC/MC nodes) so that sched mode is set at it's parent */ 1562 lvl = SOC_TH_NODE_LVL_L1; 1563 mc = BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) ? 1 : 0; 1564 } else if (IS_CPU_PORT(unit, local_port)) { 1565 lvl = SOC_TH_NODE_LVL_L1; 1566 mc = 1; 1567 } 1568 BCM_IF_ERROR_RETURN(soc_th_cosq_sched_mode_set(unit, local_port, 1569 lvl, 1570 child_index, 1571 sched_mode, lwts, mc)); 1572 1573 return BCM_E_NONE; 1574 } 1575 1576 /* 1577 * Function: 1578 * _bcm_th_cosq_sched_get 1579 * Purpose: 1580 * Get scheduling mode setting 1581 * Parameters: 1582 * unit - (IN) unit number 1583 * port - (IN) port number or GPORT identifier 1584 * cosq - (IN) COS queue number 1585 * mode - (OUT) scheduling mode (BCM_COSQ_XXX) 1586 * weight - (OUT) weight 1587 * Returns: 1588 * BCM_E_XXX 1589 */ 1590 STATIC int 1591 _bcm_th_cosq_sched_get(int unit, bcm_port_t gport, bcm_cos_queue_t cosq, 1592 int *mode, int *weight) 1593 { 1594 soc_th_sched_mode_e sched_mode; 1595 bcm_port_t local_port; 1596 int lvl = SOC_TH_NODE_LVL_L0, mc = 0; 1597 1598 BCM_IF_ERROR_RETURN 1599 (_bcm_th_cosq_localport_resolve(unit, gport, &local_port)); 1600 if (BCM_GPORT_IS_SCHEDULER(gport)) { 1601 lvl = SOC_TH_NODE_LVL_L0; 1602 } else if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 1603 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 1604 lvl = SOC_TH_NODE_LVL_L1; 1605 mc = BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) ? 1 : 0; 1606 } else if (IS_CPU_PORT(unit, local_port)) { 1607 lvl = SOC_TH_NODE_LVL_L1; 1608 mc = 1; 1609 } 1610 BCM_IF_ERROR_RETURN( 1611 soc_th_cosq_sched_mode_get(unit, local_port, lvl, cosq, 1612 &sched_mode, weight, mc)); 1613 switch(sched_mode) { 1614 case SOC_TH_SCHED_MODE_STRICT: 1615 *mode = BCM_COSQ_STRICT; 1616 break; 1617 case SOC_TH_SCHED_MODE_WRR: 1618 *mode = BCM_COSQ_WEIGHTED_ROUND_ROBIN; 1619 break; 1620 case SOC_TH_SCHED_MODE_WERR: 1621 *mode = BCM_COSQ_DEFICIT_ROUND_ROBIN; 1622 break; 1623 default: 1624 return BCM_E_INTERNAL; 1625 break; 1626 } 1627 return BCM_E_NONE; 1628 } 1629 1630 /* 1631 * Function: 1632 * _bcm_th_cosq_bucket_set 1633 * Purpose: 1634 * Configure COS queue bandwidth control bucket 1635 * Parameters: 1636 * unit - (IN) unit number 1637 * gport - (IN) port number or GPORT identifier 1638 * cosq - (IN) COS queue number 1639 * min_quantum - (IN) kbps or packet/second 1640 * max_quantum - (IN) kbps or packet/second 1641 * burst_quantum - (IN) kbps or packet/second 1642 * flags - (IN) 1643 * Returns: 1644 * BCM_E_XXX 1645 * Notes: 1646 * If port is any form of local port, cosq is the hardware queue index. 1647 */ 1648 STATIC int 1649 _bcm_th_cosq_bucket_set(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 1650 uint32 min_quantum, uint32 max_quantum, 1651 uint32 kbits_burst_min, uint32 kbits_burst_max, 1652 uint32 flags) 1653 { 1654 _bcm_th_cosq_node_t *node = NULL; 1655 bcm_port_t local_port; 1656 uint32 rval, meter_flags; 1657 uint32 bucketsize_max, bucketsize_min; 1658 uint32 granularity_max, granularity_min; 1659 uint32 refresh_rate_max, refresh_rate_min; 1660 int refresh_bitsize = 0, bucket_bitsize = 0; 1661 int pipe, phy_port, mmu_port, index; 1662 soc_mem_t config_mem = INVALIDm; 1663 uint32 entry[SOC_MAX_MEM_WORDS]; 1664 soc_info_t *si; 1665 int cpu_mc_base = 0; 1666 1667 /* caller should resolve the cosq. */ 1668 if (cosq < 0) { 1669 if (cosq == -1) { 1670 /* caller needs to resolve the wild card value (-1) */ 1671 return BCM_E_INTERNAL; 1672 } else { /* reject all other negative value */ 1673 return BCM_E_PARAM; 1674 } 1675 } 1676 1677 BCM_IF_ERROR_RETURN 1678 (_bcm_th_cosq_localport_resolve(unit, gport, &local_port)); 1679 1680 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 1681 1682 si = &SOC_INFO(unit); 1683 phy_port = si->port_l2p_mapping[local_port]; 1684 mmu_port = si->port_p2m_mapping[phy_port]; 1685 1686 if (BCM_GPORT_IS_SET(gport) && 1687 ((BCM_GPORT_IS_SCHEDULER(gport)) || 1688 BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 1689 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) || 1690 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport))) { 1691 1692 BCM_IF_ERROR_RETURN 1693 (_bcm_th_cosq_node_get(unit, gport, NULL, 1694 NULL, NULL, &node)); 1695 } 1696 1697 if (node) { 1698 if (BCM_GPORT_IS_SCHEDULER(gport)) { 1699 if (node->level == SOC_TH_NODE_LVL_L0) { 1700 config_mem = MMU_MTRO_L0_MEMm; 1701 cosq = node->hw_index % _BCM_TH_NUM_SCHEDULER_PER_PORT; 1702 index = ((mmu_port & (SOC_TH_MMU_PORT_STRIDE - 1)) * 1703 _BCM_TH_NUM_SCHEDULER_PER_PORT) + cosq; 1704 } else { 1705 return BCM_E_PARAM; 1706 } 1707 } else if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 1708 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 1709 config_mem = MMU_MTRO_L1_MEMm; 1710 cosq = node->hw_index % si->port_num_cosq[local_port]; 1711 1712 if (IS_CPU_PORT(unit, local_port)) { 1713 /*Adjust mc cosq for cpu port*/ 1714 cpu_mc_base = si->port_cosq_base[CMIC_PORT(unit)]; 1715 cosq = (node->hw_index - cpu_mc_base) % 1716 _BCM_TH_NUM_CPU_MCAST_QUEUE; 1717 /* For CPU port's MC queue starting index: 660(L1 Memory) */ 1718 config_mem = MMU_MTRO_L1_MEMm; 1719 index = SOC_TH_MMU_CPU_MCQ_OFFSET + cosq; 1720 } else if (SOC_PBMP_MEMBER(si->management_pbm, local_port)) { 1721 config_mem = MMU_MTRO_L1_MEMm; 1722 index = (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) ? 1723 SOC_TH_MMU_MGMT_MCQ_OFFSET : SOC_TH_MMU_MGMT_UCQ_OFFSET) + cosq; 1724 } else { 1725 index = ((mmu_port & (SOC_TH_MMU_PORT_STRIDE - 1)) * 1726 _BCM_TH_NUM_SCHEDULER_PER_PORT) + cosq; 1727 if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 1728 index += SOC_TH_NUM_UC_QUEUES_PER_PIPE; 1729 } 1730 } 1731 } else { 1732 return BCM_E_PARAM; 1733 } 1734 } else { 1735 if ((cosq < 0) || (cosq >= si->port_num_cosq[local_port])) { 1736 return BCM_E_PARAM; 1737 } 1738 if (!IS_CPU_PORT(unit, local_port)) { 1739 index = ((mmu_port & (SOC_TH_MMU_PORT_STRIDE - 1)) * 1740 _BCM_TH_NUM_SCHEDULER_PER_PORT) + cosq; 1741 config_mem = MMU_MTRO_L0_MEMm; 1742 } else { 1743 /* For CPU port, refer L1 memory (logical queue, starting index 660) 1744 * directly */ 1745 config_mem = MMU_MTRO_L1_MEMm; 1746 index = (2 * SOC_TH_NUM_UC_QUEUES_PER_PIPE) + cosq; 1747 } 1748 } 1749 1750 /* 1751 * COVERITY 1752 * 1753 * This checker will not be True. 1754 * It is kept intentionally as a defensive check for future development. 1755 */ 1756 /* coverity[dead_error_line] */ 1757 if (config_mem == INVALIDm) { 1758 return BCM_E_PARAM; 1759 } 1760 config_mem = SOC_MEM_UNIQUE_ACC(unit, config_mem)[pipe]; 1761 1762 if (config_mem == INVALIDm) { 1763 return BCM_E_PARAM; 1764 } 1765 1766 meter_flags = flags & BCM_COSQ_BW_PACKET_MODE ? 1767 _BCM_TD_METER_FLAG_PACKET_MODE : 0; 1768 #ifdef BCM_TOMAHAWK2_SUPPORT 1769 if (soc_feature(unit, soc_feature_mmu_sed)) { 1770 BCM_IF_ERROR_RETURN(READ_MMU_SEDCFG_MISCCONFIGr(unit, &rval)); 1771 if (soc_reg_field_get(unit, MMU_SEDCFG_MISCCONFIGr, rval, ITU_MODE_SELf)) { 1772 meter_flags |= _BCM_TD_METER_FLAG_NON_LINEAR; 1773 } 1774 } else 1775 #endif 1776 { 1777 BCM_IF_ERROR_RETURN(READ_MMU_SCFG_MISCCONFIGr(unit, &rval)); 1778 if (soc_reg_field_get(unit, MMU_SCFG_MISCCONFIGr, rval, ITU_MODE_SELf)) { 1779 meter_flags |= _BCM_TD_METER_FLAG_NON_LINEAR; 1780 } 1781 } 1782 1783 refresh_bitsize = soc_mem_field_length(unit, config_mem, MAX_REFRESHf); 1784 bucket_bitsize = soc_mem_field_length(unit, config_mem, MAX_THD_SELf); 1785 1786 BCM_IF_ERROR_RETURN 1787 (_bcm_td_rate_to_bucket_encoding(unit, max_quantum, kbits_burst_max, 1788 meter_flags, refresh_bitsize, 1789 bucket_bitsize, &refresh_rate_max, 1790 &bucketsize_max, &granularity_max)); 1791 1792 BCM_IF_ERROR_RETURN 1793 (_bcm_td_rate_to_bucket_encoding(unit, min_quantum, kbits_burst_min, 1794 meter_flags, refresh_bitsize, 1795 bucket_bitsize, &refresh_rate_min, 1796 &bucketsize_min, &granularity_min)); 1797 1798 sal_memset(entry, 0, sizeof(uint32)*SOC_MAX_MEM_WORDS); 1799 1800 soc_mem_field32_set(unit, config_mem, &entry, MAX_METER_GRANf, granularity_max); 1801 soc_mem_field32_set(unit, config_mem, &entry, MAX_REFRESHf, refresh_rate_max); 1802 soc_mem_field32_set(unit, config_mem, &entry, MAX_THD_SELf, bucketsize_max); 1803 1804 soc_mem_field32_set(unit, config_mem, &entry, MIN_METER_GRANf, granularity_min); 1805 soc_mem_field32_set(unit, config_mem, &entry, MIN_REFRESHf, refresh_rate_min); 1806 soc_mem_field32_set(unit, config_mem, &entry, MIN_THD_SELf, bucketsize_min); 1807 1808 soc_mem_field32_set(unit, config_mem, &entry, SHAPER_CONTROLf, 1809 (flags & BCM_COSQ_BW_PACKET_MODE) ? 1 : 0); 1810 1811 BCM_IF_ERROR_RETURN 1812 (soc_mem_write(unit, config_mem, MEM_BLOCK_ALL, index, &entry)); 1813 1814 return BCM_E_NONE; 1815 } 1816 1817 /* 1818 * Function: 1819 * _bcm_th_cosq_bucket_get 1820 * Purpose: 1821 * Get COS queue bandwidth control bucket setting 1822 * Parameters: 1823 * unit - (IN) unit number 1824 * gport - (IN) port number or GPORT identifier 1825 * cosq - (IN) COS queue number 1826 * min_quantum - (OUT) kbps or packet/second 1827 * max_quantum - (OUT) kbps or packet/second 1828 * burst_quantum - (OUT) kbps or packet/second 1829 * flags - (IN) 1830 * Returns: 1831 * BCM_E_XXX 1832 * Notes: 1833 * If port is any form of local port, cosq is the hardware queue index. 1834 */ 1835 STATIC int 1836 _bcm_th_cosq_bucket_get(int unit, bcm_port_t gport, bcm_cos_queue_t cosq, 1837 uint32 *min_quantum, uint32 *max_quantum, 1838 uint32 *kbits_burst_min, uint32 *kbits_burst_max, 1839 uint32 *flags) 1840 { 1841 _bcm_th_cosq_node_t *node = NULL; 1842 bcm_port_t local_port; 1843 uint32 rval; 1844 uint32 refresh_rate, bucketsize, granularity, meter_flags; 1845 int pipe, phy_port, mmu_port, index; 1846 soc_mem_t config_mem = INVALIDm; 1847 uint32 entry[SOC_MAX_MEM_WORDS]; 1848 soc_info_t *si; 1849 int cpu_mc_base = 0; 1850 1851 if (cosq < 0) { 1852 if (cosq == -1) { 1853 /* caller needs to resolve the wild card value (-1) */ 1854 return BCM_E_INTERNAL; 1855 } else { /* reject all other negative value */ 1856 return BCM_E_PARAM; 1857 } 1858 } 1859 1860 BCM_IF_ERROR_RETURN 1861 (_bcm_th_cosq_localport_resolve(unit, gport, &local_port)); 1862 1863 si = &SOC_INFO(unit); 1864 phy_port = si->port_l2p_mapping[local_port]; 1865 mmu_port = si->port_p2m_mapping[phy_port]; 1866 pipe = si->port_pipe[local_port]; 1867 1868 if (BCM_GPORT_IS_SET(gport) && 1869 ((BCM_GPORT_IS_SCHEDULER(gport)) || 1870 BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 1871 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) || 1872 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport))) { 1873 1874 BCM_IF_ERROR_RETURN 1875 (_bcm_th_cosq_node_get(unit, gport, NULL, 1876 NULL, NULL, &node)); 1877 } 1878 1879 if (node) { 1880 if (BCM_GPORT_IS_SCHEDULER(gport)) { 1881 if (node->level == SOC_TH_NODE_LVL_L0) { 1882 config_mem = MMU_MTRO_L0_MEMm; 1883 cosq = node->hw_index % _BCM_TH_NUM_SCHEDULER_PER_PORT; 1884 index = ((mmu_port & (SOC_TH_MMU_PORT_STRIDE - 1)) * 1885 _BCM_TH_NUM_SCHEDULER_PER_PORT) + cosq; 1886 } else { 1887 return BCM_E_PARAM; 1888 } 1889 } else if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 1890 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 1891 config_mem = MMU_MTRO_L1_MEMm; 1892 cosq = node->hw_index % si->port_num_cosq[local_port]; 1893 1894 if (IS_CPU_PORT(unit, local_port)) { 1895 /*Adjust mc cosq for cpu port*/ 1896 cpu_mc_base = si->port_cosq_base[CMIC_PORT(unit)]; 1897 cosq = (node->hw_index - cpu_mc_base) % 1898 _BCM_TH_NUM_CPU_MCAST_QUEUE; 1899 /* For CPU port's MC queue starting index: 660(L1 Memory) */ 1900 config_mem = MMU_MTRO_L1_MEMm; 1901 index = SOC_TH_MMU_CPU_MCQ_OFFSET + cosq; 1902 } else if (SOC_PBMP_MEMBER(si->management_pbm, local_port)) { 1903 config_mem = MMU_MTRO_L1_MEMm; 1904 index = (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) ? 1905 SOC_TH_MMU_MGMT_MCQ_OFFSET : SOC_TH_MMU_MGMT_UCQ_OFFSET) + cosq; 1906 } else { 1907 index = ((mmu_port & (SOC_TH_MMU_PORT_STRIDE - 1)) * 1908 _BCM_TH_NUM_SCHEDULER_PER_PORT) + cosq; 1909 if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 1910 index += SOC_TH_NUM_UC_QUEUES_PER_PIPE; 1911 } 1912 } 1913 } else { 1914 return BCM_E_PARAM; 1915 } 1916 } else { 1917 if ((cosq < 0) || (cosq >= SOC_PORT_NUM_COSQ(unit, local_port))) { 1918 return BCM_E_PARAM; 1919 } 1920 if (!IS_CPU_PORT(unit, local_port)) { 1921 index = ((mmu_port & (SOC_TH_MMU_PORT_STRIDE - 1)) * 1922 _BCM_TH_NUM_SCHEDULER_PER_PORT) + cosq; 1923 config_mem = MMU_MTRO_L0_MEMm; 1924 } else { 1925 /* For CPU port, refer L1 memory (logical queue, starting index 660) 1926 * directly */ 1927 config_mem = MMU_MTRO_L1_MEMm; 1928 index = (2 * SOC_TH_NUM_UC_QUEUES_PER_PIPE) + cosq; 1929 } 1930 } 1931 1932 /* 1933 * COVERITY 1934 * 1935 * This checker will not be True. 1936 * It is kept intentionally as a defensive case for future development. 1937 */ 1938 /* coverity[dead_error_line] */ 1939 if (config_mem == INVALIDm) { 1940 return BCM_E_PARAM; 1941 } 1942 config_mem = SOC_MEM_UNIQUE_ACC(unit, config_mem)[pipe]; 1943 1944 if (config_mem == INVALIDm) { 1945 return BCM_E_PARAM; 1946 } 1947 1948 index = SOC_TH_MMU_PIPED_MEM_INDEX(unit, local_port, config_mem, index); 1949 1950 if (min_quantum == NULL || max_quantum == NULL || 1951 kbits_burst_max == NULL || kbits_burst_min == NULL) { 1952 return BCM_E_PARAM; 1953 } 1954 1955 BCM_IF_ERROR_RETURN 1956 (soc_mem_read(unit, config_mem, MEM_BLOCK_ALL, index, &entry)); 1957 1958 meter_flags = 0; 1959 *flags = 0; 1960 #ifdef BCM_TOMAHAWK2_SUPPORT 1961 if (soc_feature(unit, soc_feature_mmu_sed)) { 1962 BCM_IF_ERROR_RETURN(READ_MMU_SEDCFG_MISCCONFIGr(unit, &rval)); 1963 if (soc_reg_field_get(unit, MMU_SEDCFG_MISCCONFIGr, rval, ITU_MODE_SELf)) { 1964 meter_flags |= _BCM_TD_METER_FLAG_NON_LINEAR; 1965 } 1966 } else 1967 #endif 1968 { 1969 BCM_IF_ERROR_RETURN(READ_MMU_SCFG_MISCCONFIGr(unit, &rval)); 1970 if (soc_reg_field_get(unit, MMU_SCFG_MISCCONFIGr, rval, ITU_MODE_SELf)) { 1971 meter_flags |= _BCM_TD_METER_FLAG_NON_LINEAR; 1972 } 1973 } 1974 if (soc_mem_field32_get(unit, config_mem, &entry, SHAPER_CONTROLf)) { 1975 meter_flags |= _BCM_TD_METER_FLAG_PACKET_MODE; 1976 *flags |= BCM_COSQ_BW_PACKET_MODE; 1977 } 1978 1979 granularity = soc_mem_field32_get(unit, config_mem, &entry, MAX_METER_GRANf); 1980 refresh_rate = soc_mem_field32_get(unit, config_mem, &entry, MAX_REFRESHf); 1981 bucketsize = soc_mem_field32_get(unit, config_mem, &entry, MAX_THD_SELf); 1982 BCM_IF_ERROR_RETURN 1983 (_bcm_td_bucket_encoding_to_rate(unit, refresh_rate, bucketsize, 1984 granularity, meter_flags, 1985 max_quantum, kbits_burst_max)); 1986 1987 granularity = soc_mem_field32_get(unit, config_mem, &entry, MIN_METER_GRANf); 1988 refresh_rate = soc_mem_field32_get(unit, config_mem, &entry, MIN_REFRESHf); 1989 bucketsize = soc_mem_field32_get(unit, config_mem, &entry, MIN_THD_SELf); 1990 BCM_IF_ERROR_RETURN 1991 (_bcm_td_bucket_encoding_to_rate(unit, refresh_rate, bucketsize, 1992 granularity, meter_flags, 1993 min_quantum, kbits_burst_min)); 1994 return BCM_E_NONE; 1995 } 1996 1997 STATIC int 1998 _bcm_th_cosq_time_domain_get(int unit, int time_id, int *time_value) 1999 { 2000 uint32 time_domain_val; 2001 soc_reg_t time_domain_reg = TIME_DOMAINr; 2002 2003 if (time_id < 0 || time_id > _BCM_TH_NUM_TIME_DOMAIN - 1) { 2004 return SOC_E_PARAM; 2005 } 2006 2007 if (time_value == NULL) { 2008 return SOC_E_PARAM; 2009 } 2010 2011 BCM_IF_ERROR_RETURN( 2012 soc_reg32_get(unit, time_domain_reg, REG_PORT_ANY, time_id, &time_domain_val)); 2013 *time_value = soc_reg_field_get(unit, time_domain_reg, 2014 time_domain_val, TIME_DOMAIN_FIELDf); 2015 return SOC_E_NONE; 2016 } 2017 2018 STATIC int 2019 _bcm_th_cosq_time_domain_set(int unit, int time_value, int *time_id) 2020 { 2021 int id; 2022 uint32 time_domain_val; 2023 soc_reg_t time_domain_reg = TIME_DOMAINr; 2024 2025 if (time_value < 0 || time_value > 63) { 2026 return SOC_E_PARAM; 2027 } 2028 2029 for (id = 0; id < _BCM_TH_NUM_TIME_DOMAIN; id++) { 2030 BCM_IF_ERROR_RETURN( 2031 soc_reg32_get(unit, time_domain_reg, REG_PORT_ANY, id, &time_domain_val)); 2032 if (!time_domain_info[unit][id].ref_count) { 2033 soc_reg_field_set(unit, time_domain_reg, &time_domain_val, 2034 TIME_DOMAIN_FIELDf, time_value); 2035 time_domain_info[unit][id].ref_count++; 2036 break; 2037 } 2038 } 2039 2040 if (id == _BCM_TH_NUM_TIME_DOMAIN) {/* No field in TIME_DOMAINr is free,return ERR*/ 2041 return BCM_E_RESOURCE; 2042 } 2043 2044 if (time_id) { 2045 *time_id = id; 2046 } 2047 SOC_IF_ERROR_RETURN( 2048 soc_reg32_set(unit, time_domain_reg, REG_PORT_ANY, id, time_domain_val)); 2049 return SOC_E_NONE; 2050 } 2051 2052 /* 2053 * Function: 2054 * bcm_th_cosq_wred_resolution_id_create 2055 * Purpose: 2056 * Assign a unused entry. Default drop rules are WRED drop. 2057 * Parameters: 2058 * unit - (IN) unit number 2059 * index - (OUT) entry index 2060 * Returns: 2061 * BCM_E_XXX 2062 */ 2063 int 2064 bcm_th_cosq_wred_resolution_entry_create(int unit, int *index) 2065 { 2066 uint32 i, rval = 0; 2067 soc_reg_t reg = WRED_CONG_NOTIFICATION_RESOLUTION_TABLEr; 2068 2069 for (i = 0; i < _BCM_TH_NUM_WRED_RESOLUTION_TABLE; i ++) { 2070 if (_bcm_th_wred_resolution_tbl[i] == 0) { 2071 /* hw reset value */ 2072 soc_reg_field_set(unit, reg, &rval, MMU_CONGESTION_EXPERIENCEf, 0xAAA); 2073 BCM_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, i, rval)); 2074 _bcm_th_wred_resolution_tbl[i] ++; 2075 *index = i; 2076 return SOC_E_NONE; 2077 } 2078 } 2079 2080 return SOC_E_RESOURCE; 2081 } 2082 2083 /* 2084 * Function: 2085 * bcm_th_cosq_wred_resolution_id_destroy 2086 * Purpose: 2087 * Callback an entry and set its drop rules to WRED drop. 2088 * Parameters: 2089 * unit - (IN) unit number 2090 * index - (IN) entry index 2091 * Returns: 2092 * BCM_E_XXX 2093 */ 2094 int 2095 bcm_th_cosq_wred_resolution_entry_destroy(int unit, int index) 2096 { 2097 uint32 rval = 0; 2098 soc_reg_t reg = WRED_CONG_NOTIFICATION_RESOLUTION_TABLEr; 2099 2100 if ((index < 0) || (index >= _BCM_TH_NUM_WRED_RESOLUTION_TABLE)) { 2101 return SOC_E_PARAM; 2102 } 2103 2104 if (_bcm_th_wred_resolution_tbl[index] == 0) { 2105 return SOC_E_NOT_FOUND; 2106 } 2107 2108 /* hw reset value */ 2109 soc_reg_field_set(unit, reg, &rval, MMU_CONGESTION_EXPERIENCEf, 0xAAA); 2110 BCM_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, index, rval)); 2111 _bcm_th_wred_resolution_tbl[index] = 0; 2112 2113 return SOC_E_NONE; 2114 } 2115 2116 /* 2117 * Function: 2118 * bcm_th_cosq_wred_resolution_set 2119 * Purpose: 2120 * Set one rule of a resolution table entry 2121 * Parameters: 2122 * unit - (IN) unit number 2123 * index - (IN) entry index 2124 * rule - (IN) drop rule 2125 * Returns: 2126 * BCM_E_XXX 2127 * Notes: 2128 * One entry has 12 bits, equals to 6 rules 2129 */ 2130 int 2131 bcm_th_cosq_wred_resolution_set(int unit, int index, bcm_cosq_discard_rule_t *rule) 2132 { 2133 uint32 offset, sp, qmin; 2134 uint32 rval, fval, drop; 2135 soc_reg_t reg = WRED_CONG_NOTIFICATION_RESOLUTION_TABLEr; 2136 2137 if ((index < 0) || (index >= _BCM_TH_NUM_WRED_RESOLUTION_TABLE)) { 2138 return SOC_E_PARAM; 2139 } 2140 2141 if (_bcm_th_wred_resolution_tbl[index] == 0) { 2142 return BCM_E_NOT_FOUND; 2143 } 2144 2145 switch (rule->egress_pool_congestion_state) { 2146 case BCM_COSQ_DISCARD_CONGESTION_LOW: 2147 sp = 0; 2148 break; 2149 case BCM_COSQ_DISCARD_CONGESTION_MEDIUM: 2150 sp = 1; 2151 break; 2152 case BCM_COSQ_DISCARD_CONGESTION_HIGH: 2153 sp = 2; 2154 break; 2155 default: 2156 return SOC_E_PARAM; 2157 } 2158 2159 switch (rule->queue_min_congestion_state) { 2160 case BCM_COSQ_DISCARD_CONGESTION_LOW: 2161 qmin = 0; 2162 break; 2163 case BCM_COSQ_DISCARD_CONGESTION_HIGH: 2164 qmin = 1; 2165 break; 2166 default: 2167 return SOC_E_PARAM; 2168 } 2169 2170 switch (rule->action) { 2171 case BCM_COSQ_DISCARD_ACTION_WRED_DROP: 2172 drop = 0x2; 2173 break; 2174 case BCM_COSQ_DISCARD_ACTION_FORCE_DROP: 2175 drop = 0x3; 2176 break; 2177 case BCM_COSQ_DISCARD_ACTION_FORCE_NO_DROP: 2178 drop = 0x0; 2179 break; 2180 default: 2181 return SOC_E_PARAM; 2182 } 2183 2184 BCM_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, index, &rval)); 2185 fval = soc_reg_field_get(unit, reg, rval, MMU_CONGESTION_EXPERIENCEf); 2186 2187 offset = (sp * 2 + qmin) * 2; /* 2 bits per rule */ 2188 fval = (fval & (~(0x3 << offset))) | (drop << offset); 2189 2190 soc_reg_field_set(unit, reg, &rval, MMU_CONGESTION_EXPERIENCEf, fval); 2191 BCM_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, index, rval)); 2192 2193 return SOC_E_NONE; 2194 } 2195 2196 /* 2197 * Function: 2198 * bcm_th_cosq_wred_resolution_get 2199 * Purpose: 2200 * Get all rules of a resolution table entry 2201 * Parameters: 2202 * unit - (IN) unit number 2203 * index - (IN) entry index 2204 * max - (IN) rule array size 2205 * rule - (OUT) rule array 2206 * count - (OUT) actual rules count 2207 * Returns: 2208 * BCM_E_XXX 2209 * Notes: 2210 * One entry has 12 bits, equals to 6 rules 2211 */ 2212 int 2213 bcm_th_cosq_wred_resolution_get(int unit, int index, int max, 2214 bcm_cosq_discard_rule_t *rule, int *count) 2215 { 2216 uint32 offset, sp, qmin, i = 0; 2217 uint32 rval, fval, action; 2218 soc_reg_t reg = WRED_CONG_NOTIFICATION_RESOLUTION_TABLEr; 2219 uint32 sp_map[3] = { 2220 BCM_COSQ_DISCARD_CONGESTION_LOW, 2221 BCM_COSQ_DISCARD_CONGESTION_MEDIUM, 2222 BCM_COSQ_DISCARD_CONGESTION_HIGH, 2223 }; 2224 uint32 qmin_map[2] = { 2225 BCM_COSQ_DISCARD_CONGESTION_LOW, 2226 BCM_COSQ_DISCARD_CONGESTION_HIGH, 2227 }; 2228 uint32 action_map[4] = { 2229 BCM_COSQ_DISCARD_ACTION_FORCE_NO_DROP, 2230 -1, 2231 BCM_COSQ_DISCARD_ACTION_WRED_DROP, 2232 BCM_COSQ_DISCARD_ACTION_FORCE_DROP, 2233 }; 2234 2235 if ((!count) || 2236 (index < 0) || (index >= _BCM_TH_NUM_WRED_RESOLUTION_TABLE)) { 2237 return SOC_E_PARAM; 2238 } 2239 2240 *count = 3 * 2; 2241 2242 if (!rule) { 2243 return SOC_E_NONE; 2244 } 2245 2246 BCM_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, index, &rval)); 2247 fval = soc_reg_field_get(unit, reg, rval, MMU_CONGESTION_EXPERIENCEf); 2248 2249 for (sp = 0; sp < 3; sp ++) { 2250 for (qmin = 0; qmin < 2; qmin ++) { 2251 offset = (sp * 2 + qmin) * 2; /* 2 bits per rule */ 2252 action = (fval >> offset) & 0x3; 2253 if (i < max) { 2254 rule[i].egress_pool_congestion_state = sp_map[sp]; 2255 rule[i].queue_min_congestion_state = qmin_map[qmin]; 2256 rule[i].action = action_map[action]; 2257 i ++; 2258 } 2259 } 2260 } 2261 2262 return SOC_E_NONE; 2263 } 2264 2265 /* 2266 * Function: 2267 * _bcm_th_cosq_wred_set 2268 * Purpose: 2269 * Configure unicast queue WRED setting 2270 * Parameters: 2271 * unit - (IN) unit number 2272 * port - (IN) port number or GPORT identifier 2273 * cosq - (IN) COS queue number 2274 * flags - (IN) BCM_COSQ_DISCARD_XXX 2275 * min_thresh - (IN) Min Threshold 2276 * max_thresh - (IN) Max Threshold 2277 * drop_probablity - (IN) Probabilistic drop rate 2278 * gain - (IN) 2279 * ignore_enable_flags - (IN) 2280 * lflags - (IN) Config Flags 2281 * refresh_time - (IN) actual refresh time 2282 * Returns: 2283 * BCM_E_XXX 2284 * Notes: 2285 * If port is any form of local port, cosq is the hardware queue index. 2286 */ 2287 STATIC int 2288 _bcm_th_cosq_wred_set(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 2289 bcm_cosq_buffer_id_t buffer, 2290 uint32 flags, uint32 min_thresh, uint32 max_thresh, 2291 int drop_probability, int gain, int ignore_enable_flags, 2292 uint32 lflags, int refresh_time, uint32 resolution_id, 2293 uint32 use_queue_group) 2294 { 2295 /* Local Variables */ 2296 soc_mem_t wred_config_mem = INVALIDm; 2297 bcm_port_t local_port = -1; 2298 int index, i, start_index, end_index, count = 0; 2299 int end_offset, need_profile = 0, pipe, xpe, xpe_map, accessed = 0; 2300 uint32 profile_index, old_profile_index; 2301 uint32 wred_flags = 0; 2302 void *entries[9]; 2303 soc_mem_t mems[9]; 2304 static soc_mem_t wred_mems[9] = { 2305 MMU_WRED_DROP_CURVE_PROFILE_0m, MMU_WRED_DROP_CURVE_PROFILE_1m, 2306 MMU_WRED_DROP_CURVE_PROFILE_2m, MMU_WRED_DROP_CURVE_PROFILE_3m, 2307 MMU_WRED_DROP_CURVE_PROFILE_4m, MMU_WRED_DROP_CURVE_PROFILE_5m, 2308 MMU_WRED_DROP_CURVE_PROFILE_6m, MMU_WRED_DROP_CURVE_PROFILE_7m, 2309 MMU_WRED_DROP_CURVE_PROFILE_8m 2310 }; 2311 mmu_wred_drop_curve_profile_0_entry_t entry_tcp_green; 2312 mmu_wred_drop_curve_profile_1_entry_t entry_tcp_yellow; 2313 mmu_wred_drop_curve_profile_2_entry_t entry_tcp_red; 2314 mmu_wred_drop_curve_profile_3_entry_t entry_nontcp_green; 2315 mmu_wred_drop_curve_profile_4_entry_t entry_nontcp_yellow; 2316 mmu_wred_drop_curve_profile_5_entry_t entry_nontcp_red; 2317 mmu_wred_drop_curve_profile_6_entry_t entry_ecn_green; 2318 mmu_wred_drop_curve_profile_7_entry_t entry_ecn_yellow; 2319 mmu_wred_drop_curve_profile_8_entry_t entry_ecn_red; 2320 mmu_wred_config_entry_t entry; 2321 int rate = 0; 2322 int from_pipe, to_pipe; 2323 int time_id,time,old_time,current_time_sel; 2324 int rv = SOC_E_NONE, exists = 0; 2325 2326 if ((buffer != BCM_COSQ_BUFFER_ID_INVALID) && 2327 ((buffer < 0) || (buffer >= _TH_XPES_PER_DEV))) { 2328 return BCM_E_PARAM; 2329 } 2330 2331 wred_flags = flags | lflags; 2332 end_offset = 0; 2333 2334 /* Check Flags for WRED res level - Device-SP/Port-SP/Queues */ 2335 if ((wred_flags & BCM_COSQ_DISCARD_DEVICE) && (port == BCM_GPORT_INVALID)) { 2336 /* (Port == -1) For all Global SPs */ 2337 index = 462; 2338 count = _TH_MMU_NUM_POOL; 2339 /*For all pipe*/ 2340 from_pipe = 0; 2341 to_pipe = NUM_PIPE(unit) - 1; 2342 2343 } else { 2344 BCM_IF_ERROR_RETURN 2345 (_bcm_th_cosq_localport_resolve(unit, port, &local_port)); 2346 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 2347 from_pipe = to_pipe = pipe; 2348 2349 if (wred_flags & BCM_COSQ_DISCARD_DEVICE) { 2350 BCM_IF_ERROR_RETURN 2351 (_bcm_th_cosq_index_resolve(unit, port, cosq, 2352 _BCM_TH_COSQ_INDEX_STYLE_WRED_DEVICE, 2353 NULL, &index, &count)); 2354 /* (cosq == -1) For all Global SPs */ 2355 } else if (wred_flags & BCM_COSQ_DISCARD_PORT) { 2356 /* Port SP - Given or all SPs of the port */ 2357 BCM_IF_ERROR_RETURN 2358 (_bcm_th_cosq_index_resolve(unit, port, cosq, 2359 _BCM_TH_COSQ_INDEX_STYLE_WRED_PORT, 2360 NULL, &index, &count)); 2361 /* (cosq == -1) For all SPs of the given port */ 2362 } else { 2363 /* Per Queue WRED settings */ 2364 BCM_IF_ERROR_RETURN 2365 (_bcm_th_cosq_index_resolve(unit, port, cosq, 2366 _BCM_TH_COSQ_INDEX_STYLE_WRED_QUEUE, 2367 NULL, &index, &count)); 2368 /* (cosq == -1) For all Queues of the given port */ 2369 } 2370 } 2371 2372 2373 end_offset = (count > 0) ? (count - 1) : 0; 2374 2375 if (index < 0) { 2376 return BCM_E_PARAM; 2377 } 2378 if (refresh_time < 1) { 2379 return BCM_E_PARAM; 2380 } 2381 start_index = index; 2382 end_index = start_index + end_offset; 2383 2384 rate = _bcm_th_percent_to_drop_prob(drop_probability); 2385 2386 for (pipe = from_pipe; pipe <= to_pipe; pipe++ ) { 2387 /* Config MMU_WRED_CONFIGm for the respective resource */ 2388 wred_config_mem = MMU_WRED_CONFIGm; 2389 2390 for (i=0; i < 9; i++) { 2391 mems[i] = INVALIDm; 2392 } 2393 2394 if (wred_flags & (BCM_COSQ_DISCARD_COLOR_ALL | 2395 BCM_COSQ_DISCARD_TCP | 2396 BCM_COSQ_DISCARD_NONTCP | 2397 BCM_COSQ_DISCARD_ECT_MARKED | 2398 BCM_COSQ_DISCARD_RESPONSIVE_DROP | 2399 BCM_COSQ_DISCARD_NON_RESPONSIVE_DROP)) { 2400 need_profile = 1; 2401 2402 if (!(flags & (BCM_COSQ_DISCARD_COLOR_GREEN | 2403 BCM_COSQ_DISCARD_COLOR_YELLOW | 2404 BCM_COSQ_DISCARD_COLOR_RED))) { 2405 flags |= BCM_COSQ_DISCARD_COLOR_ALL; 2406 } 2407 2408 if (!(wred_flags & (BCM_COSQ_DISCARD_NONTCP | 2409 BCM_COSQ_DISCARD_NON_RESPONSIVE_DROP | 2410 BCM_COSQ_DISCARD_ECT_MARKED)) || 2411 ((wred_flags & BCM_COSQ_DISCARD_TCP) || 2412 (wred_flags & BCM_COSQ_DISCARD_RESPONSIVE_DROP))) { 2413 if (flags & BCM_COSQ_DISCARD_COLOR_GREEN) { 2414 mems[0] = wred_mems[0]; 2415 } 2416 if (flags & BCM_COSQ_DISCARD_COLOR_YELLOW) { 2417 mems[1] = wred_mems[1]; 2418 } 2419 if (flags & BCM_COSQ_DISCARD_COLOR_RED) { 2420 mems[2] = wred_mems[2]; 2421 } 2422 } 2423 if ((wred_flags & BCM_COSQ_DISCARD_NONTCP) || 2424 (wred_flags & BCM_COSQ_DISCARD_NON_RESPONSIVE_DROP)){ 2425 if (flags & BCM_COSQ_DISCARD_COLOR_GREEN) { 2426 mems[3] = wred_mems[3]; 2427 } 2428 if (flags & BCM_COSQ_DISCARD_COLOR_YELLOW) { 2429 mems[4] = wred_mems[4]; 2430 } 2431 if (flags & BCM_COSQ_DISCARD_COLOR_RED) { 2432 mems[5] = wred_mems[5]; 2433 } 2434 } 2435 if (wred_flags & BCM_COSQ_DISCARD_ECT_MARKED) { 2436 if (flags & BCM_COSQ_DISCARD_COLOR_GREEN) { 2437 mems[6] = wred_mems[6]; 2438 } 2439 if (flags & BCM_COSQ_DISCARD_COLOR_YELLOW) { 2440 mems[7] = wred_mems[7]; 2441 } 2442 if (flags & BCM_COSQ_DISCARD_COLOR_RED) { 2443 mems[8] = wred_mems[8]; 2444 } 2445 } 2446 } 2447 2448 entries[0] = &entry_tcp_green; 2449 entries[1] = &entry_tcp_yellow; 2450 entries[2] = &entry_tcp_red; 2451 entries[3] = &entry_nontcp_green; 2452 entries[4] = &entry_nontcp_yellow; 2453 entries[5] = &entry_nontcp_red; 2454 entries[6] = &entry_ecn_green; 2455 entries[7] = &entry_ecn_yellow; 2456 entries[8] = &entry_ecn_red; 2457 2458 if (buffer == BCM_COSQ_BUFFER_ID_INVALID) { 2459 xpe_map = SOC_INFO(unit).epipe_xpe_map[pipe]; 2460 } else if (port == BCM_GPORT_INVALID) { 2461 xpe_map = (1 << buffer) & SOC_INFO(unit).epipe_xpe_map[pipe]; 2462 } else { 2463 xpe_map = (1 << buffer); 2464 } 2465 2466 for (xpe = 0; xpe < NUM_XPE(unit); xpe ++) { 2467 if (!(xpe_map & (1 << xpe))) { 2468 continue; 2469 } 2470 2471 accessed = 1; 2472 for (index = start_index; index <= end_index; index++) { 2473 old_profile_index = 0xffffffff; 2474 BCM_IF_ERROR_RETURN 2475 (soc_tomahawk_xpe_mem_read(unit, wred_config_mem, xpe, pipe, 2476 MEM_BLOCK_ALL, index, &entry)); 2477 2478 if (need_profile) { 2479 old_profile_index = soc_mem_field32_get(unit, wred_config_mem, 2480 &entry, PROFILE_INDEXf); 2481 2482 BCM_IF_ERROR_RETURN 2483 (soc_profile_mem_get(unit, _bcm_th_wred_profile[unit], 2484 old_profile_index, 1, entries)); 2485 2486 for (i = 0; i < 9; i++) { 2487 if (mems[i] == INVALIDm) { 2488 continue; 2489 } 2490 soc_mem_field32_set(unit, wred_mems[i], entries[i], 2491 MIN_THDf, min_thresh); 2492 soc_mem_field32_set(unit, wred_mems[i], entries[i], 2493 MAX_THDf, max_thresh); 2494 soc_mem_field32_set(unit, wred_mems[i], entries[i], 2495 MAX_DROP_RATEf, rate); 2496 } 2497 BCM_IF_ERROR_RETURN 2498 (soc_profile_mem_add(unit, _bcm_th_wred_profile[unit], 2499 entries, 1, &profile_index)); 2500 soc_mem_field32_set(unit, wred_config_mem, &entry, PROFILE_INDEXf, profile_index); 2501 } 2502 2503 soc_mem_field32_set(unit, wred_config_mem, &entry, WEIGHTf, gain); 2504 /* Some APIs only modify profiles */ 2505 if (!ignore_enable_flags) { 2506 soc_mem_field32_set(unit, wred_config_mem, &entry, CAP_AVERAGEf, 2507 flags & BCM_COSQ_DISCARD_CAP_AVERAGE ? 1 : 0); 2508 soc_mem_field32_set(unit, wred_config_mem, &entry, WRED_ENf, 2509 flags & BCM_COSQ_DISCARD_ENABLE ? 1 : 0); 2510 soc_mem_field32_set(unit, wred_config_mem, &entry, LOGICAL_Q_TRACK_ENABLEf, 2511 flags & BCM_COSQ_DISCARD_ENABLE ? 1 : 0); 2512 soc_mem_field32_set(unit, wred_config_mem, &entry, ECN_MARKING_ENf, 2513 flags & BCM_COSQ_DISCARD_MARK_CONGESTION ? 1 : 0); 2514 } 2515 2516 current_time_sel = soc_mem_field32_get(unit, wred_config_mem, 2517 &entry, TIME_DOMAIN_SELf); 2518 time = refresh_time - 1; 2519 exists = 0; 2520 /* If the time value exist, update reference count only */ 2521 for (time_id = 0; time_id < _BCM_TH_NUM_TIME_DOMAIN; time_id++) { 2522 BCM_IF_ERROR_RETURN 2523 (_bcm_th_cosq_time_domain_get(unit, time_id, &old_time)); 2524 if (time == old_time) { 2525 /* Only set exist flag if this entry reference count already update, 2526 otherwise update reference count */ 2527 if(time_id != current_time_sel){ 2528 soc_mem_field32_set(unit, wred_config_mem, &entry, 2529 TIME_DOMAIN_SELf, time_id); 2530 time_domain_info[unit][time_id].ref_count++; 2531 time_domain_info[unit][current_time_sel].ref_count--; 2532 } 2533 exists = 1; 2534 break; 2535 } 2536 } 2537 2538 if(!exists){ 2539 rv = _bcm_th_cosq_time_domain_set(unit, time, &time_id); 2540 if(rv == SOC_E_NONE){ 2541 soc_mem_field32_set(unit, wred_config_mem, &entry, 2542 TIME_DOMAIN_SELf, time_id); 2543 time_domain_info[unit][current_time_sel].ref_count--; 2544 } else { 2545 return rv; 2546 } 2547 } 2548 2549 soc_mem_field32_set(unit, wred_config_mem, &entry, QG_ENf, 2550 use_queue_group ? 1 : 0); 2551 if (flags & BCM_COSQ_DISCARD_MARK_CONGESTION) { 2552 soc_mem_field32_set(unit, wred_config_mem, &entry, 2553 WRED_CONG_NOTIFICATION_RESOLUTION_TABLE_MARKING_INDEXf, 2554 resolution_id); 2555 } else { 2556 soc_mem_field32_set(unit, wred_config_mem, &entry, 2557 WRED_CONG_NOTIFICATION_RESOLUTION_TABLE_DROPPING_INDEXf, 2558 resolution_id); 2559 } 2560 2561 BCM_IF_ERROR_RETURN 2562 (soc_tomahawk_xpe_mem_write(unit, wred_config_mem, xpe, pipe, 2563 MEM_BLOCK_ALL, index, &entry)); 2564 2565 if (old_profile_index != 0xffffffff) { 2566 SOC_IF_ERROR_RETURN 2567 (soc_profile_mem_delete(unit, _bcm_th_wred_profile[unit], 2568 old_profile_index)); 2569 } 2570 2571 } 2572 } 2573 2574 } 2575 2576 /* pipe (port) and xpe (buffer) are not related */ 2577 if (!accessed) { 2578 return BCM_E_PARAM; 2579 } 2580 2581 return rv; 2582 } 2583 2584 /* 2585 * Function: 2586 * _bcm_th_cosq_wred_get 2587 * Purpose: 2588 * Configure unicast queue WRED setting 2589 * Parameters: 2590 * unit - (IN) unit number 2591 * port - (IN) port number or GPORT identifier 2592 * cosq - (IN) COS queue number 2593 * flags - (IN/OUT) BCM_COSQ_DISCARD_XXX 2594 * min_thresh - (OUT) Min Threshold 2595 * max_thresh - (OUT) Max Threshold 2596 * drop_probablity - (OUT) Probabilistic drop rate 2597 * gain - (OUT) 2598 * lflags - (IN) Config flags 2599 * refresh_time - (OUT) Time Domain 2600 * Returns: 2601 * BCM_E_XXX 2602 * Notes: 2603 * If port is any form of local port, cosq is the hardware queue index. 2604 */ 2605 STATIC int 2606 _bcm_th_cosq_wred_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 2607 bcm_cosq_buffer_id_t buffer, 2608 uint32 *flags, uint32 *min_thresh, uint32 *max_thresh, 2609 int *drop_probability, int *gain, uint32 lflags, 2610 int *refresh_time, uint32 *resolution_id, 2611 uint32 *use_queue_group) 2612 { 2613 soc_mem_t wred_config_mem = INVALIDm, mem = INVALIDm; 2614 bcm_port_t local_port = -1; 2615 mmu_wred_drop_curve_profile_0_entry_t entry_tcp_green; 2616 mmu_wred_drop_curve_profile_1_entry_t entry_tcp_yellow; 2617 mmu_wred_drop_curve_profile_2_entry_t entry_tcp_red; 2618 mmu_wred_drop_curve_profile_3_entry_t entry_nontcp_green; 2619 mmu_wred_drop_curve_profile_4_entry_t entry_nontcp_yellow; 2620 mmu_wred_drop_curve_profile_5_entry_t entry_nontcp_red; 2621 mmu_wred_drop_curve_profile_6_entry_t entry_ecn_green; 2622 mmu_wred_drop_curve_profile_7_entry_t entry_ecn_yellow; 2623 mmu_wred_drop_curve_profile_8_entry_t entry_ecn_red; 2624 void *entries[9]; 2625 void *entry_p; 2626 int index, profile_index; 2627 mmu_wred_config_entry_t entry; 2628 uint32 wred_flags = 0; 2629 int rate = 0, pipe = -1, xpe; 2630 int time_id, time; 2631 2632 if ((buffer != BCM_COSQ_BUFFER_ID_INVALID) && 2633 ((buffer < 0) || (buffer >= _TH_XPES_PER_DEV))) { 2634 return BCM_E_PARAM; 2635 } 2636 2637 if (flags) { 2638 wred_flags = *flags | lflags; 2639 } else { 2640 wred_flags = lflags; 2641 } 2642 2643 if ((wred_flags & BCM_COSQ_DISCARD_DEVICE) && (port == BCM_GPORT_INVALID)) { 2644 /* (Port == -1) For all Global SPs */ 2645 index = 462; 2646 pipe = 0; 2647 2648 } else { 2649 BCM_IF_ERROR_RETURN 2650 (_bcm_th_cosq_localport_resolve(unit, port, &local_port)); 2651 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 2652 2653 /* Check Flags for WRED res level - Device-SP/Port-SP/Queues */ 2654 if(wred_flags & BCM_COSQ_DISCARD_DEVICE) { 2655 BCM_IF_ERROR_RETURN 2656 (_bcm_th_cosq_index_resolve(unit, port, cosq, 2657 _BCM_TH_COSQ_INDEX_STYLE_WRED_DEVICE, 2658 NULL, &index, NULL)); 2659 } else if (wred_flags & BCM_COSQ_DISCARD_PORT) { 2660 /* Port SP - Given or all SPs of the port */ 2661 BCM_IF_ERROR_RETURN 2662 (_bcm_th_cosq_index_resolve(unit, port, cosq, 2663 _BCM_TH_COSQ_INDEX_STYLE_WRED_PORT, 2664 NULL, &index, NULL)); 2665 } else { 2666 /* Per Queue WRED settings */ 2667 BCM_IF_ERROR_RETURN 2668 (_bcm_th_cosq_index_resolve(unit, port, cosq, 2669 _BCM_TH_COSQ_INDEX_STYLE_WRED_QUEUE, 2670 NULL, &index, NULL)); 2671 } 2672 } 2673 2674 if ((index < 0) || (pipe == -1)) { 2675 return BCM_E_PARAM; 2676 } 2677 2678 if (buffer == BCM_COSQ_BUFFER_ID_INVALID) { 2679 xpe = -1; 2680 } else if (port == BCM_GPORT_INVALID) { 2681 xpe = buffer; 2682 pipe = -1; 2683 } else if (SOC_INFO(unit).epipe_xpe_map[pipe] & (1 << buffer)) { 2684 xpe = buffer; 2685 } else { 2686 return BCM_E_PARAM; 2687 } 2688 2689 wred_config_mem = MMU_WRED_CONFIGm; 2690 BCM_IF_ERROR_RETURN 2691 (soc_tomahawk_xpe_mem_read(unit, wred_config_mem, xpe, pipe, 2692 MEM_BLOCK_ALL, index, &entry)); 2693 2694 profile_index = soc_mem_field32_get(unit, wred_config_mem, 2695 &entry, PROFILE_INDEXf); 2696 2697 if (!(wred_flags & (BCM_COSQ_DISCARD_NONTCP | 2698 BCM_COSQ_DISCARD_NON_RESPONSIVE_DROP | 2699 BCM_COSQ_DISCARD_ECT_MARKED))) { 2700 /* By default we will assume 2701 BCM_COSQ_DISCARD_TCP */ 2702 if (wred_flags & BCM_COSQ_DISCARD_COLOR_YELLOW) { 2703 mem = MMU_WRED_DROP_CURVE_PROFILE_1m; 2704 entry_p = &entry_tcp_yellow; 2705 } else if (wred_flags & BCM_COSQ_DISCARD_COLOR_RED) { 2706 mem = MMU_WRED_DROP_CURVE_PROFILE_2m; 2707 entry_p = &entry_tcp_red; 2708 } else { 2709 /* By default we will assume 2710 BCM_COSQ_DISCARD_COLOR_GREEN */ 2711 mem = MMU_WRED_DROP_CURVE_PROFILE_0m; 2712 entry_p = &entry_tcp_green; 2713 } 2714 } else if ((wred_flags & BCM_COSQ_DISCARD_NONTCP) || 2715 (wred_flags & BCM_COSQ_DISCARD_NON_RESPONSIVE_DROP)) { 2716 if (wred_flags & BCM_COSQ_DISCARD_COLOR_YELLOW) { 2717 mem = MMU_WRED_DROP_CURVE_PROFILE_4m; 2718 entry_p = &entry_nontcp_yellow; 2719 } else if (wred_flags & BCM_COSQ_DISCARD_COLOR_RED) { 2720 mem = MMU_WRED_DROP_CURVE_PROFILE_5m; 2721 entry_p = &entry_nontcp_red; 2722 } else { 2723 /* By default we will assume 2724 BCM_COSQ_DISCARD_COLOR_GREEN */ 2725 mem = MMU_WRED_DROP_CURVE_PROFILE_3m; 2726 entry_p = &entry_nontcp_green; 2727 } 2728 } else { 2729 if (wred_flags & BCM_COSQ_DISCARD_COLOR_YELLOW) { 2730 mem = MMU_WRED_DROP_CURVE_PROFILE_7m; 2731 entry_p = &entry_ecn_yellow; 2732 } else if (wred_flags & BCM_COSQ_DISCARD_COLOR_RED) { 2733 mem = MMU_WRED_DROP_CURVE_PROFILE_8m; 2734 entry_p = &entry_ecn_red; 2735 } else { 2736 /* By default we will assume 2737 BCM_COSQ_DISCARD_COLOR_GREEN */ 2738 mem = MMU_WRED_DROP_CURVE_PROFILE_6m; 2739 entry_p = &entry_ecn_green; 2740 } 2741 } 2742 2743 entries[0] = &entry_tcp_green; 2744 entries[1] = &entry_tcp_yellow; 2745 entries[2] = &entry_tcp_red; 2746 entries[3] = &entry_nontcp_green; 2747 entries[4] = &entry_nontcp_yellow; 2748 entries[5] = &entry_nontcp_red; 2749 entries[6] = &entry_ecn_green; 2750 entries[7] = &entry_ecn_yellow; 2751 entries[8] = &entry_ecn_red; 2752 2753 BCM_IF_ERROR_RETURN 2754 (soc_profile_mem_get(unit, _bcm_th_wred_profile[unit], 2755 profile_index, 1, entries)); 2756 if (min_thresh != NULL) { 2757 *min_thresh = soc_mem_field32_get(unit, mem, entry_p, MIN_THDf); 2758 } 2759 if (max_thresh != NULL) { 2760 *max_thresh = soc_mem_field32_get(unit, mem, entry_p, MAX_THDf); 2761 } 2762 if (drop_probability != NULL) { 2763 rate = soc_mem_field32_get(unit, mem, entry_p, MAX_DROP_RATEf); 2764 *drop_probability = _bcm_th_drop_prob_to_percent(rate); 2765 } 2766 if (gain) { 2767 *gain = soc_mem_field32_get(unit, wred_config_mem, &entry, WEIGHTf); 2768 } 2769 2770 /* Get the Time Domain value */ 2771 if (refresh_time) { 2772 time_id = soc_mem_field32_get(unit, wred_config_mem, &entry, 2773 TIME_DOMAIN_SELf); 2774 BCM_IF_ERROR_RETURN 2775 (_bcm_th_cosq_time_domain_get(unit,time_id,&time)); 2776 *refresh_time = time + 1; 2777 } 2778 2779 /* Get flags */ 2780 if (flags) { 2781 *flags &= ~(BCM_COSQ_DISCARD_CAP_AVERAGE | BCM_COSQ_DISCARD_ENABLE | 2782 BCM_COSQ_DISCARD_MARK_CONGESTION); 2783 if (soc_mem_field32_get(unit, wred_config_mem, &entry, CAP_AVERAGEf)) { 2784 *flags |= BCM_COSQ_DISCARD_CAP_AVERAGE; 2785 } 2786 if (soc_mem_field32_get(unit, wred_config_mem, &entry, WRED_ENf)) { 2787 *flags |= BCM_COSQ_DISCARD_ENABLE; 2788 } 2789 if (soc_mem_field32_get(unit, wred_config_mem, &entry, ECN_MARKING_ENf)) { 2790 *flags |= BCM_COSQ_DISCARD_MARK_CONGESTION; 2791 } 2792 } 2793 2794 /* Get resolution table index */ 2795 if (resolution_id) { 2796 if (soc_mem_field32_get(unit, wred_config_mem, &entry, ECN_MARKING_ENf)) { 2797 *resolution_id = soc_mem_field32_get(unit, wred_config_mem, &entry, 2798 WRED_CONG_NOTIFICATION_RESOLUTION_TABLE_MARKING_INDEXf); 2799 } else { 2800 *resolution_id = soc_mem_field32_get(unit, wred_config_mem, &entry, 2801 WRED_CONG_NOTIFICATION_RESOLUTION_TABLE_DROPPING_INDEXf); 2802 } 2803 } 2804 2805 /* Get use_queue_group */ 2806 if (use_queue_group) { 2807 *use_queue_group = 2808 soc_mem_field32_get(unit, wred_config_mem, &entry, QG_ENf); 2809 } 2810 2811 return BCM_E_NONE; 2812 } 2813 2814 STATIC _bcm_bst_cb_ret_t 2815 _bcm_th_bst_index_resolve(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 2816 bcm_bst_stat_id_t bid, int *pipe, int *start_hw_index, 2817 int *end_hw_index, int *rcb_data, void **cb_data, int *bcm_rv) 2818 { 2819 int phy_port, mmu_port, local_port; 2820 int mmu_port_base = 0; 2821 _bcm_th_cosq_node_t *node = NULL; 2822 soc_info_t *si; 2823 uint32 rval = 0; 2824 int pool_idx; 2825 2826 *bcm_rv = _bcm_th_cosq_localport_resolve(unit, gport, &local_port); 2827 2828 if (BCM_E_NONE != (*bcm_rv)) { 2829 goto error; 2830 } 2831 2832 si = &SOC_INFO(unit); 2833 phy_port = si->port_l2p_mapping[local_port]; 2834 mmu_port = si->port_p2m_mapping[phy_port]; 2835 2836 *pipe = mmu_port / SOC_TH_MMU_PORT_STRIDE; 2837 2838 if (bid == bcmBstStatIdDevice) { 2839 *start_hw_index = *end_hw_index = 0; 2840 *bcm_rv = BCM_E_NONE; 2841 return _BCM_BST_RV_OK; 2842 } 2843 2844 if ((bid == bcmBstStatIdEgrPool) || (bid == bcmBstStatIdEgrMCastPool)) { 2845 if(_bcm_th_cosq_egress_sp_get(unit, gport, cosq, start_hw_index, 2846 end_hw_index)) { 2847 goto error; 2848 } 2849 return _BCM_BST_RV_OK; 2850 } else if (bid == bcmBstStatIdHeadroomPool) { 2851 /* ingress headroom pool */ 2852 if (_bcm_th_cosq_ingress_hdrm_pool_get(unit, gport, cosq, 2853 start_hw_index, end_hw_index)) { 2854 goto error; 2855 } 2856 return _BCM_BST_RV_OK; 2857 } else if (bid == bcmBstStatIdIngPool) { 2858 /* ingress pool */ 2859 if (_bcm_th_cosq_ingress_sp_get(unit, gport, cosq, 2860 start_hw_index, end_hw_index)) { 2861 goto error; 2862 } 2863 return _BCM_BST_RV_OK; 2864 } else if (bid == bcmBstStatIdRQEPool) { 2865 /* RQE pool */ 2866 if (cosq == BCM_COS_INVALID) { 2867 *start_hw_index = 0; 2868 *end_hw_index = _TH_MMU_NUM_POOL - 1; 2869 }else if ((cosq < 0) || (cosq >= _TH_MMU_NUM_RQE_QUEUES)) { 2870 return BCM_E_PARAM; 2871 } else { 2872 SOC_IF_ERROR_RETURN 2873 (READ_MMU_THDR_DB_CONFIG1_PRIQr(unit, cosq, &rval)); 2874 2875 pool_idx = soc_reg_field_get(unit, MMU_THDR_DB_CONFIG1_PRIQr, rval, 2876 SPIDf); 2877 *start_hw_index = *end_hw_index = pool_idx; 2878 } 2879 return _BCM_BST_RV_OK; 2880 } else if (bid == bcmBstStatIdRQEQueue) { 2881 /* RQE queue */ 2882 if (cosq == BCM_COS_INVALID) { 2883 *start_hw_index = 0; 2884 *end_hw_index = _TH_MMU_NUM_RQE_QUEUES - 1; 2885 }else if ((cosq < 0) || (cosq >= _TH_MMU_NUM_RQE_QUEUES)) { 2886 return BCM_E_PARAM; 2887 } else { 2888 *start_hw_index = *end_hw_index = cosq; 2889 } 2890 return _BCM_BST_RV_OK; 2891 } else if (bid == bcmBstStatIdUCQueueGroup) { 2892 /* unicast queue group */ 2893 mmu_port_base = SOC_TH_MMU_PORT_STRIDE * (*pipe); 2894 *start_hw_index = *end_hw_index = mmu_port - mmu_port_base; 2895 return _BCM_BST_RV_OK; 2896 } 2897 2898 if (bid == bcmBstStatIdPortPool) { 2899 /* ingress pool */ 2900 if (_bcm_th_cosq_ingress_sp_get(unit, gport, cosq, 2901 start_hw_index, end_hw_index)) { 2902 goto error; 2903 } 2904 *start_hw_index = ((mmu_port & (SOC_TH_MMU_PORT_STRIDE - 1)) * 4) + 2905 *start_hw_index; 2906 *end_hw_index = ((mmu_port & (SOC_TH_MMU_PORT_STRIDE - 1)) * 4) + 2907 *end_hw_index; 2908 } else if ((bid == bcmBstStatIdPriGroupShared) || 2909 (bid == bcmBstStatIdPriGroupHeadroom)) { 2910 /* ingress PG */ 2911 if (_bcm_th_cosq_ingress_pg_get(unit, gport, cosq, 2912 start_hw_index, end_hw_index)) { 2913 goto error; 2914 } 2915 *start_hw_index = ((mmu_port & (SOC_TH_MMU_PORT_STRIDE - 1)) * 8) + 2916 *start_hw_index; 2917 *end_hw_index = ((mmu_port & (SOC_TH_MMU_PORT_STRIDE - 1)) * 8) + 2918 *end_hw_index; 2919 } else if (bid == bcmBstStatIdEgrPortPoolSharedUcast || 2920 bid == bcmBstStatIdEgrPortPoolSharedMcast) { 2921 /* egress pool */ 2922 if (_bcm_th_cosq_egress_sp_get(unit, gport, cosq, 2923 start_hw_index, end_hw_index)) { 2924 goto error; 2925 } 2926 *start_hw_index = ((mmu_port & (SOC_TH_MMU_PORT_STRIDE - 1)) * 4) + 2927 *start_hw_index; 2928 *end_hw_index = ((mmu_port & (SOC_TH_MMU_PORT_STRIDE - 1)) * 4) + 2929 *end_hw_index; 2930 } else { 2931 if ((bid == bcmBstStatIdMcast) && IS_CPU_PORT(unit, local_port)) { 2932 *start_hw_index = cosq + _BCM_BST_TH_CPU_QUEUE_START; 2933 *end_hw_index = * start_hw_index; 2934 } else if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 2935 if (bid != bcmBstStatIdUcast) { 2936 goto error; 2937 } 2938 BCM_IF_ERROR_RETURN 2939 (_bcm_th_cosq_node_get(unit, gport, NULL, 2940 &local_port, NULL, &node)); 2941 if (!node) { 2942 goto error; 2943 } 2944 cosq = node->hw_index % _BCM_TH_NUM_UCAST_QUEUE_PER_PORT; 2945 *start_hw_index = ((mmu_port & (SOC_TH_MMU_PORT_STRIDE - 1)) * 2946 _BCM_TH_NUM_UCAST_QUEUE_PER_PORT) + cosq; 2947 *end_hw_index = *start_hw_index; 2948 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 2949 if (bid != bcmBstStatIdMcast) { 2950 goto error; 2951 } 2952 BCM_IF_ERROR_RETURN 2953 (_bcm_th_cosq_node_get(unit, gport, NULL, 2954 &local_port, NULL, &node)); 2955 if (!node) { 2956 goto error; 2957 } 2958 cosq = node->hw_index % _BCM_TH_NUM_MCAST_QUEUE_PER_PORT; 2959 *start_hw_index = ((mmu_port & (SOC_TH_MMU_PORT_STRIDE - 1)) * 2960 _BCM_TH_NUM_MCAST_QUEUE_PER_PORT) + cosq; 2961 *end_hw_index = *start_hw_index; 2962 } else { 2963 if (cosq < 0) { 2964 if (bid == bcmBstStatIdUcast) { 2965 if (IS_LB_PORT(unit, local_port)) { 2966 goto error; 2967 } 2968 *start_hw_index = (mmu_port & (SOC_TH_MMU_PORT_STRIDE - 1)) * 2969 _BCM_TH_NUM_UCAST_QUEUE_PER_PORT; 2970 *end_hw_index = *start_hw_index + 2971 _BCM_TH_NUM_UCAST_QUEUE_PER_PORT - 1; 2972 } else { 2973 *start_hw_index = (mmu_port & (SOC_TH_MMU_PORT_STRIDE - 1)) * 2974 _BCM_TH_NUM_MCAST_QUEUE_PER_PORT; 2975 *end_hw_index = *start_hw_index + 2976 _BCM_TH_NUM_MCAST_QUEUE_PER_PORT - 1; 2977 } 2978 } else if (cosq < _TH_PORT_NUM_COS(unit, local_port)) { 2979 if (bid == bcmBstStatIdUcast) { 2980 if (IS_LB_PORT(unit, local_port)) { 2981 goto error; 2982 } 2983 *start_hw_index = ((mmu_port & (SOC_TH_MMU_PORT_STRIDE - 1)) * 2984 _BCM_TH_NUM_UCAST_QUEUE_PER_PORT) + cosq; 2985 *end_hw_index = *start_hw_index; 2986 } else { 2987 *start_hw_index = ((mmu_port & (SOC_TH_MMU_PORT_STRIDE - 1)) * 2988 _BCM_TH_NUM_MCAST_QUEUE_PER_PORT) + cosq; 2989 *end_hw_index = *start_hw_index; 2990 } 2991 } else { 2992 goto error; 2993 } 2994 } 2995 } 2996 2997 *bcm_rv = BCM_E_NONE; 2998 return _BCM_BST_RV_OK; 2999 3000 error: 3001 *bcm_rv = BCM_E_PARAM; 3002 return _BCM_BST_RV_ERROR; 3003 } 3004 3005 STATIC int 3006 _bcm_th_cosq_bst_map_resource_to_gport_cos(int unit, 3007 bcm_bst_stat_id_t bid, int port, int index, bcm_gport_t *gport, 3008 bcm_cos_t *cosq) 3009 { 3010 soc_info_t *si = &SOC_INFO(unit); 3011 _bcm_bst_resource_info_t *pres = NULL; 3012 int phy_port = 0; 3013 int mmu_port = 0; 3014 int pipe = 0; 3015 int mmu_port_base = 0; 3016 int stats_per_inst = 1; 3017 int stats_per_pipe = 1; 3018 3019 if (bid >= bcmBstStatIdMaxCount) { 3020 LOG_INFO(BSL_LS_BCM_COSQ, 3021 (BSL_META_U(unit, 3022 "_bcm_th_cosq_bst_map_resource_to_gport_cos: unit=%d bid=0x%x\n"), 3023 unit, bid)); 3024 return BCM_E_NONE; 3025 } 3026 3027 pres = _BCM_BST_RESOURCE(unit, bid); 3028 stats_per_inst = (pres->num_stat_pp) / (pres->num_instance); 3029 index %= stats_per_inst; 3030 if (pres->flags & _BCM_BST_CMN_RES_F_PIPED) { 3031 stats_per_pipe = stats_per_inst / NUM_PIPE(unit); 3032 pipe = index / stats_per_pipe; 3033 index %= stats_per_pipe; 3034 mmu_port_base = SOC_TH_MMU_PORT_STRIDE * pipe; 3035 } 3036 3037 switch (bid) { 3038 case bcmBstStatIdDevice: 3039 *gport = -1; 3040 *cosq = BCM_COS_INVALID; 3041 break; 3042 3043 case bcmBstStatIdIngPool: 3044 case bcmBstStatIdEgrPool: 3045 case bcmBstStatIdEgrMCastPool: 3046 case bcmBstStatIdRQEPool: 3047 *gport = -1; 3048 *cosq = index % _TH_MMU_NUM_POOL; 3049 break; 3050 3051 case bcmBstStatIdRQEQueue: 3052 *gport = -1; 3053 *cosq = index % _TH_MMU_NUM_RQE_QUEUES; 3054 break; 3055 3056 case bcmBstStatIdUCQueueGroup: 3057 mmu_port= index; 3058 phy_port = si->port_m2p_mapping[mmu_port + mmu_port_base]; 3059 *gport = si->port_p2l_mapping[phy_port]; 3060 *cosq = -1; 3061 break; 3062 3063 case bcmBstStatIdPortPool: 3064 mmu_port= index/_TH_MMU_NUM_POOL; 3065 phy_port = si->port_m2p_mapping[mmu_port + mmu_port_base]; 3066 *gport = si->port_p2l_mapping[phy_port]; 3067 *cosq = index % _TH_MMU_NUM_POOL; 3068 break; 3069 3070 case bcmBstStatIdPriGroupHeadroom: 3071 case bcmBstStatIdPriGroupShared: 3072 mmu_port = index/_TH_MMU_NUM_PG; 3073 phy_port = si->port_m2p_mapping[mmu_port + mmu_port_base]; 3074 *gport = si->port_p2l_mapping[phy_port]; 3075 *cosq = index % _TH_MMU_NUM_PG; 3076 break; 3077 3078 case bcmBstStatIdUcast: 3079 case bcmBstStatIdMcast: 3080 if ((bid == bcmBstStatIdMcast) && _BCM_BST_TH_IS_CPU_QUEUE(index)) { 3081 *gport = 0; 3082 *cosq = index - _BCM_BST_TH_CPU_QUEUE_START; 3083 } else { 3084 mmu_port = index/10; 3085 phy_port = si->port_m2p_mapping[mmu_port + mmu_port_base]; 3086 *gport = si->port_p2l_mapping[phy_port]; 3087 *cosq = index % 10; 3088 } 3089 break; 3090 case bcmBstStatIdEgrPortPoolSharedUcast: 3091 case bcmBstStatIdEgrPortPoolSharedMcast: 3092 mmu_port = index/_TH_MMU_NUM_POOL; 3093 phy_port = si->port_m2p_mapping[mmu_port + mmu_port_base]; 3094 *gport = si->port_p2l_mapping[phy_port]; 3095 *cosq = index % _TH_MMU_NUM_POOL; 3096 break; 3097 default: 3098 break; 3099 } 3100 3101 return BCM_E_NONE; 3102 } 3103 3104 3105 int 3106 _bcm_th_cosq_pfc_class_resolve(bcm_switch_control_t sctype, int *type, 3107 int *class) 3108 { 3109 switch (sctype) { 3110 case bcmSwitchPFCClass7Queue: 3111 case bcmSwitchPFCClass6Queue: 3112 case bcmSwitchPFCClass5Queue: 3113 case bcmSwitchPFCClass4Queue: 3114 case bcmSwitchPFCClass3Queue: 3115 case bcmSwitchPFCClass2Queue: 3116 case bcmSwitchPFCClass1Queue: 3117 case bcmSwitchPFCClass0Queue: 3118 *type = _BCM_TH_COSQ_TYPE_UCAST; 3119 break; 3120 case bcmSwitchPFCClass7McastQueue: 3121 case bcmSwitchPFCClass6McastQueue: 3122 case bcmSwitchPFCClass5McastQueue: 3123 case bcmSwitchPFCClass4McastQueue: 3124 case bcmSwitchPFCClass3McastQueue: 3125 case bcmSwitchPFCClass2McastQueue: 3126 case bcmSwitchPFCClass1McastQueue: 3127 case bcmSwitchPFCClass0McastQueue: 3128 *type = _BCM_TH_COSQ_TYPE_MCAST; 3129 break; 3130 default: 3131 /* Unsupported Switch Control types should return E_UNAVAIL */ 3132 return BCM_E_UNAVAIL; 3133 } 3134 3135 switch (sctype) { 3136 case bcmSwitchPFCClass7Queue: 3137 case bcmSwitchPFCClass7McastQueue: 3138 *class = 7; 3139 break; 3140 case bcmSwitchPFCClass6Queue: 3141 case bcmSwitchPFCClass6McastQueue: 3142 *class = 6; 3143 break; 3144 case bcmSwitchPFCClass5Queue: 3145 case bcmSwitchPFCClass5McastQueue: 3146 *class = 5; 3147 break; 3148 case bcmSwitchPFCClass4Queue: 3149 case bcmSwitchPFCClass4McastQueue: 3150 *class = 4; 3151 break; 3152 case bcmSwitchPFCClass3Queue: 3153 case bcmSwitchPFCClass3McastQueue: 3154 *class = 3; 3155 break; 3156 case bcmSwitchPFCClass2Queue: 3157 case bcmSwitchPFCClass2McastQueue: 3158 *class = 2; 3159 break; 3160 case bcmSwitchPFCClass1Queue: 3161 case bcmSwitchPFCClass1McastQueue: 3162 *class = 1; 3163 break; 3164 case bcmSwitchPFCClass0Queue: 3165 case bcmSwitchPFCClass0McastQueue: 3166 *class = 0; 3167 break; 3168 /* 3169 * COVERITY 3170 * 3171 * This default is unreachable but needed for some compiler. 3172 */ 3173 /* coverity[dead_error_begin] */ 3174 default: 3175 return BCM_E_INTERNAL; 3176 } 3177 return BCM_E_NONE; 3178 } 3179 3180 /* Function to Set Default Scheduler Configuration for all the ports */ 3181 STATIC int 3182 _bcm_th_cosq_sched_default_config(int unit) 3183 { 3184 _bcm_th_cosq_port_info_t *port_info = NULL; 3185 _bcm_th_cosq_cpu_port_info_t *cpu_port_info = NULL; 3186 bcm_port_t port; 3187 int default_mode = BCM_COSQ_WEIGHTED_ROUND_ROBIN, default_weight = 1; 3188 int i; 3189 3190 port = 0; 3191 cpu_port_info = &_bcm_th_cosq_cpu_port_info[unit][port]; 3192 for (i = 0; i < _BCM_TH_NUM_SCHEDULER_PER_PORT; i++) { 3193 BCM_IF_ERROR_RETURN 3194 (bcm_th_cosq_gport_sched_set(unit, cpu_port_info->sched[i].gport, 3195 -1, default_mode, default_weight)); 3196 } 3197 for (i = 0; i < _BCM_TH_NUM_CPU_MCAST_QUEUE; i++) { 3198 BCM_IF_ERROR_RETURN 3199 (bcm_th_cosq_gport_sched_set(unit, cpu_port_info->mcast[i].gport, 3200 -1, default_mode, default_weight)); 3201 } 3202 3203 PBMP_ALL_ITER(unit, port) { 3204 if (IS_CPU_PORT(unit, port) || IS_LB_PORT(unit, port)) { 3205 continue; 3206 } else { 3207 port_info = &_bcm_th_cosq_port_info[unit][port]; 3208 } 3209 for (i = 0; i < _BCM_TH_NUM_SCHEDULER_PER_PORT; i++) { 3210 BCM_IF_ERROR_RETURN 3211 (bcm_th_cosq_gport_sched_set(unit, port_info->sched[i].gport, 3212 -1, default_mode, default_weight)); 3213 } 3214 for (i = 0; i < _BCM_TH_NUM_UCAST_QUEUE_PER_PORT; i++) { 3215 BCM_IF_ERROR_RETURN 3216 (bcm_th_cosq_gport_sched_set(unit, port_info->ucast[i].gport, 3217 -1, default_mode, default_weight)); 3218 } 3219 for (i = 0; i < _BCM_TH_NUM_MCAST_QUEUE_PER_PORT; i++) { 3220 BCM_IF_ERROR_RETURN 3221 (bcm_th_cosq_gport_sched_set(unit, port_info->mcast[i].gport, 3222 -1, default_mode, default_weight)); 3223 } 3224 } 3225 return BCM_E_NONE; 3226 } 3227 3228 STATIC int 3229 _bcm_th_cosq_gport_default_config(int unit) 3230 { 3231 BCM_IF_ERROR_RETURN 3232 (_bcm_th_cosq_sched_default_config(unit)); 3233 3234 return BCM_E_NONE; 3235 } 3236 3237 STATIC int 3238 _bcm_th_cosq_cpu_tree_create(int unit, bcm_gport_t *sched_gport) 3239 { 3240 bcm_gport_t cpu_mc_gport[_BCM_TH_NUM_CPU_MCAST_QUEUE]; 3241 int id, cmc, pci_cmc = SOC_PCI_CMC(unit); 3242 int ch_l0_map[SOC_CMCS_NUM_MAX]; 3243 3244 if (SOC_CMCS_NUM(unit) > SOC_CMCS_NUM_MAX) { 3245 return BCM_E_INIT; 3246 } 3247 3248 for (cmc = 0; cmc < SOC_CMCS_NUM(unit); cmc++) { 3249 if (cmc == pci_cmc) { 3250 ch_l0_map[cmc] = 0; 3251 } else if (cmc == SOC_ARM_CMC(unit, 0)) { 3252 ch_l0_map[cmc] = 7; 3253 } else if (cmc == SOC_ARM_CMC(unit, 1)) { 3254 ch_l0_map[cmc] = 8; 3255 } else { 3256 return BCM_E_PARAM; 3257 } 3258 } 3259 3260 /* Adding MC queues and attaching them to Schedular nodes */ 3261 for (id = 0; id < _BCM_TH_NUM_CPU_MCAST_QUEUE; id++) { 3262 cmc = (id < NUM_CPU_ARM_COSQ(unit, pci_cmc)) ? pci_cmc : 3263 (id < (NUM_CPU_ARM_COSQ(unit, pci_cmc) + 3264 NUM_CPU_ARM_COSQ(unit, 1))) ? SOC_ARM_CMC(unit, 0) : 3265 SOC_ARM_CMC(unit, 1); 3266 BCM_IF_ERROR_RETURN 3267 (bcm_th_cosq_gport_add(unit, 0, 1, 3268 BCM_COSQ_GPORT_MCAST_QUEUE_GROUP, 3269 &cpu_mc_gport[id])); 3270 BCM_IF_ERROR_RETURN 3271 (bcm_th_cosq_gport_attach(unit, cpu_mc_gport[id], 3272 sched_gport[ch_l0_map[cmc]], id)); 3273 } 3274 return BCM_E_NONE; 3275 } 3276 3277 /* 3278 * Function: 3279 * _bcm_th_cosq_gport_tree_create 3280 * Purpose: 3281 * During cosq init create the default cosq gport tree. 3282 * Schedualar (L0) nodes are created and attach to physical ports. 3283 * UC and MC queues are added and attached to each L0 nodes. 3284 * Parameters: 3285 * unit - (IN) unit number. 3286 * port - (IN) port number 3287 * Returns: 3288 * BCM_E_XXX 3289 */ 3290 STATIC int 3291 _bcm_th_cosq_gport_tree_create(int unit, bcm_port_t port) 3292 { 3293 int id; 3294 bcm_gport_t sched_gport[_BCM_TH_NUM_SCHEDULER_PER_PORT]; 3295 bcm_gport_t uc_gport[_BCM_TH_NUM_UCAST_QUEUE_PER_PORT]; 3296 bcm_gport_t mc_gport[_BCM_TH_NUM_MCAST_QUEUE_PER_PORT]; 3297 int numq = 0; 3298 3299 if (IS_CPU_PORT(unit, port)) { 3300 numq = 48; 3301 } else { 3302 numq = 2; 3303 } 3304 /* Adding L0 (schedular) nodes and attaching them to front panel and cpu port */ 3305 for (id = 0; id < _BCM_TH_NUM_SCHEDULER_PER_PORT; id++) { 3306 BCM_IF_ERROR_RETURN 3307 (bcm_th_cosq_gport_add(unit, port, numq, BCM_COSQ_GPORT_SCHEDULER, 3308 &sched_gport[id])); 3309 BCM_IF_ERROR_RETURN 3310 (bcm_th_cosq_gport_attach(unit, sched_gport[id], port, id)); 3311 } 3312 3313 numq = 1; 3314 if (IS_CPU_PORT(unit, port)) { 3315 BCM_IF_ERROR_RETURN 3316 (_bcm_th_cosq_cpu_tree_create(unit, sched_gport)); 3317 } else { 3318 /* Adding UC queues and attaching them to Schedular nodes */ 3319 for (id = 0; id < _BCM_TH_NUM_UCAST_QUEUE_PER_PORT; id++) { 3320 BCM_IF_ERROR_RETURN 3321 (bcm_th_cosq_gport_add(unit, port, numq, 3322 BCM_COSQ_GPORT_UCAST_QUEUE_GROUP, 3323 &uc_gport[id])); 3324 BCM_IF_ERROR_RETURN 3325 (bcm_th_cosq_gport_attach(unit, uc_gport[id], 3326 sched_gport[id], id)); 3327 } 3328 3329 /* Adding MC queues and attaching them to Schedular nodes */ 3330 for (id = 0; id < _BCM_TH_NUM_MCAST_QUEUE_PER_PORT; id++) { 3331 BCM_IF_ERROR_RETURN 3332 (bcm_th_cosq_gport_add(unit, port, numq, 3333 BCM_COSQ_GPORT_MCAST_QUEUE_GROUP, 3334 &mc_gport[id])); 3335 BCM_IF_ERROR_RETURN 3336 (bcm_th_cosq_gport_attach(unit, mc_gport[id], 3337 sched_gport[id], id)); 3338 } 3339 } 3340 3341 return SOC_E_NONE; 3342 } 3343 3344 /* 3345 * Function: 3346 * bcm_th_ecn_init 3347 * Purpose: 3348 * Initialize (clear) all ECN memories/registers 3349 * Parameters: 3350 * unit - unit number 3351 * Returns: 3352 * BCM_E_XXX 3353 */ 3354 STATIC int 3355 _bcm_th_ecn_init(int unit) 3356 { 3357 egr_ip_to_int_cn_mapping_entry_t entry_egr_ip_int_cn; 3358 int count, i; 3359 uint32 fld_val; 3360 3361 BCM_IF_ERROR_RETURN(_bcm_esw_ecn_init(unit)); 3362 3363 /* Perform additional Tomahawk specific ECN initialization */ 3364 /* EGR_IP_TO_INT_CN_MAPPING is identical to IP_TO_INT_CN_MAPPING table 3365 */ 3366 if (!SOC_WARM_BOOT(unit)) { 3367 count = soc_mem_index_count(unit, EGR_IP_TO_INT_CN_MAPPINGm); 3368 for (i = 0; i < count; i++) { 3369 sal_memset(&entry_egr_ip_int_cn, 0, sizeof(entry_egr_ip_int_cn)); 3370 switch (i) { 3371 case 0: 3372 fld_val = _BCM_ECN_INT_CN_NON_RESPONSIVE_DROP; 3373 break; 3374 case 1: 3375 fld_val = _BCM_ECN_INT_CN_RESPONSIVE_DROP; 3376 break; 3377 case 6: 3378 case 7: 3379 fld_val = _BCM_ECN_INT_CN_CONGESTION_MARK_ECN; 3380 break; 3381 default: 3382 fld_val = _BCM_ECN_INT_CN_NON_CONGESTION_MARK_ECN; 3383 break; 3384 } 3385 soc_mem_field32_set(unit, EGR_IP_TO_INT_CN_MAPPINGm, 3386 &entry_egr_ip_int_cn, INT_CNf, fld_val); 3387 SOC_IF_ERROR_RETURN 3388 (soc_mem_write(unit, EGR_IP_TO_INT_CN_MAPPINGm, MEM_BLOCK_ALL, 3389 i, (void *)&entry_egr_ip_int_cn)); 3390 } 3391 } 3392 return BCM_E_NONE; 3393 } 3394 3395 /* 3396 * Function: 3397 * _bcm_th_rqe_q_init 3398 * Purpose: 3399 * Initialize RQE registers 3400 * Parameters: 3401 * unit - unit number 3402 * Returns: 3403 * BCM_E_XXX 3404 */ 3405 STATIC int 3406 _bcm_th_rqe_q_init(int unit) 3407 { 3408 uint32 rval; 3409 3410 rval = 0; 3411 SOC_IF_ERROR_RETURN(READ_CPU_LO_RQE_Q_NUMr(unit, &rval)); 3412 soc_reg_field_set(unit, CPU_LO_RQE_Q_NUMr, &rval, RQE_Q_NUMf, 8); 3413 SOC_IF_ERROR_RETURN(WRITE_CPU_LO_RQE_Q_NUMr(unit, rval)); 3414 3415 rval = 0; 3416 SOC_IF_ERROR_RETURN(READ_CPU_HI_RQE_Q_NUMr(unit, &rval)); 3417 soc_reg_field_set(unit, CPU_HI_RQE_Q_NUMr, &rval, RQE_Q_NUMf, 9); 3418 SOC_IF_ERROR_RETURN(WRITE_CPU_HI_RQE_Q_NUMr(unit, rval)); 3419 3420 return BCM_E_NONE; 3421 } 3422 3423 /* 3424 * Function: 3425 * _bcm_th_cosq_cleanup 3426 * Purpose: 3427 * Clean resource in case of error during Cosq Init 3428 * Parameters: 3429 * unit - unit number 3430 * Returns: 3431 * No return value 3432 */ 3433 STATIC void 3434 _bcm_th_cosq_cleanup(int unit) 3435 { 3436 if (_bcm_th_cosq_port_info[unit] != NULL) { 3437 sal_free(_bcm_th_cosq_port_info[unit]); 3438 _bcm_th_cosq_port_info[unit] = NULL; 3439 } 3440 3441 if (_bcm_th_cosq_cpu_port_info[unit] != NULL) { 3442 sal_free(_bcm_th_cosq_cpu_port_info[unit]); 3443 _bcm_th_cosq_cpu_port_info[unit] = NULL; 3444 } 3445 3446 if (_bcm_th_mmu_info[unit] != NULL) { 3447 sal_free(_bcm_th_mmu_info[unit]); 3448 _bcm_th_mmu_info[unit] = NULL; 3449 } 3450 3451 if (_bcm_th_cos_map_profile[unit] != NULL) { 3452 soc_profile_mem_destroy(unit, _bcm_th_cos_map_profile[unit]); 3453 sal_free(_bcm_th_cos_map_profile[unit]); 3454 _bcm_th_cos_map_profile[unit] = NULL; 3455 } 3456 3457 if (_bcm_th_ifp_cos_map_profile[unit] != NULL) { 3458 soc_profile_mem_destroy(unit, _bcm_th_ifp_cos_map_profile[unit]); 3459 sal_free(_bcm_th_ifp_cos_map_profile[unit]); 3460 _bcm_th_ifp_cos_map_profile[unit] = NULL; 3461 } 3462 3463 if (_bcm_th_wred_profile[unit] != NULL) { 3464 soc_profile_mem_destroy(unit, _bcm_th_wred_profile[unit]); 3465 sal_free(_bcm_th_wred_profile[unit]); 3466 _bcm_th_wred_profile[unit] = NULL; 3467 } 3468 3469 if (_bcm_th_prio2cos_profile[unit] != NULL) { 3470 soc_profile_reg_destroy(unit, _bcm_th_prio2cos_profile[unit]); 3471 sal_free(_bcm_th_prio2cos_profile[unit]); 3472 _bcm_th_prio2cos_profile[unit] = NULL; 3473 } 3474 3475 #if defined(INCLUDE_PSTATS) 3476 if (_BCM_PSTATS_UNIT_DRIVER(unit) != NULL) { 3477 _bcm_pstats_deinit(unit); 3478 } 3479 #endif /* INCLUDE_PSTATS */ 3480 3481 #if defined (INCLUDE_TCB) && defined (BCM_TCB_SUPPORT) 3482 #ifdef BCM_TOMAHAWK2_SUPPORT 3483 _bcm_th2_cosq_tcb_deinit(unit); 3484 #endif 3485 #endif 3486 3487 (void)_bcm_bst_detach(unit); 3488 3489 #if defined(BCM_TOMAHAWK_SUPPORT) && defined(INCLUDE_L3) 3490 bcmi_ecn_map_clean_up(unit); 3491 #endif 3492 3493 if (soc_feature(unit, soc_feature_pfc_deadlock)) { 3494 (void)_bcm_pfc_deadlock_deinit(unit); 3495 } 3496 return; 3497 } 3498 3499 /* 3500 * Function: 3501 * bcm_th_cosq_detach 3502 * Purpose: 3503 * Discard all COS schedule/mapping state. 3504 * Parameters: 3505 * unit - unit number 3506 * Returns: 3507 * BCM_E_XXX 3508 */ 3509 int 3510 bcm_th_cosq_detach(int unit, int software_state_only) 3511 { 3512 _bcm_th_cosq_cleanup(unit); 3513 return BCM_E_NONE; 3514 } 3515 3516 /* 3517 * Function: 3518 * bcm_th_cosq_init 3519 * Purpose: 3520 * Initialize (clear) all COS schedule/mapping state. 3521 * Parameters: 3522 * unit - unit number 3523 * Returns: 3524 * BCM_E_XXX 3525 */ 3526 int 3527 bcm_th_cosq_init(int unit) 3528 { 3529 int i, numq, alloc_size, pipe = -1, xpe = -1; 3530 soc_mem_t mem = INVALIDm; 3531 bcm_port_t port; 3532 soc_reg_t reg; 3533 static soc_mem_t wred_mems[9] = { 3534 MMU_WRED_DROP_CURVE_PROFILE_0m, MMU_WRED_DROP_CURVE_PROFILE_1m, 3535 MMU_WRED_DROP_CURVE_PROFILE_2m, MMU_WRED_DROP_CURVE_PROFILE_3m, 3536 MMU_WRED_DROP_CURVE_PROFILE_4m, MMU_WRED_DROP_CURVE_PROFILE_5m, 3537 MMU_WRED_DROP_CURVE_PROFILE_6m, MMU_WRED_DROP_CURVE_PROFILE_7m, 3538 MMU_WRED_DROP_CURVE_PROFILE_8m 3539 }; 3540 int entry_words[9]; 3541 mmu_wred_drop_curve_profile_0_entry_t entry_tcp_green; 3542 mmu_wred_drop_curve_profile_1_entry_t entry_tcp_yellow; 3543 mmu_wred_drop_curve_profile_2_entry_t entry_tcp_red; 3544 mmu_wred_drop_curve_profile_3_entry_t entry_nontcp_green; 3545 mmu_wred_drop_curve_profile_4_entry_t entry_nontcp_yellow; 3546 mmu_wred_drop_curve_profile_5_entry_t entry_nontcp_red; 3547 mmu_wred_drop_curve_profile_6_entry_t entry_ecn_green; 3548 mmu_wred_drop_curve_profile_7_entry_t entry_ecn_yellow; 3549 mmu_wred_drop_curve_profile_8_entry_t entry_ecn_red; 3550 void *entries[9]; 3551 int ii, wred_prof_count; 3552 soc_mem_t wred_config_mem = INVALIDm; 3553 uint64 rval64s[16], *prval64s[1]; 3554 uint32 rval, profile_index; 3555 _bcm_bst_device_handlers_t bst_callbks; 3556 _bcm_th_cosq_cpu_cosq_config_t *cpu_cosq_config_p = NULL; 3557 int rv = BCM_E_NONE; 3558 soc_info_t *si = &SOC_INFO(unit); 3559 3560 if (!SOC_WARM_BOOT(unit)) { 3561 _bcm_th_cosq_cleanup(unit); 3562 } 3563 3564 numq = soc_property_get(unit, spn_BCM_NUM_COS, BCM_TH_COS_DEFAULT); 3565 3566 if (numq < 1) { 3567 numq = 1; 3568 } else if (numq > BCM_TH_COS_MAX) { 3569 numq = BCM_TH_COS_MAX; 3570 } 3571 3572 /* Create Port Information structure */ 3573 alloc_size = sizeof(_bcm_th_cosq_port_info_t) * 136; 3574 if (_bcm_th_cosq_port_info[unit] == NULL) { 3575 _bcm_th_cosq_port_info[unit] = 3576 sal_alloc(alloc_size, "_bcm_th_cosq_port_info"); 3577 if (_bcm_th_cosq_port_info[unit] == NULL) { 3578 return BCM_E_MEMORY; 3579 } 3580 } 3581 sal_memset(_bcm_th_cosq_port_info[unit], 0, alloc_size); 3582 3583 /* Create CPU Port Information structure */ 3584 alloc_size = sizeof(_bcm_th_cosq_cpu_port_info_t); 3585 if (_bcm_th_cosq_cpu_port_info[unit] == NULL) { 3586 _bcm_th_cosq_cpu_port_info[unit] = 3587 sal_alloc(alloc_size, "_bcm_th_cosq_cpu_port_info"); 3588 if (_bcm_th_cosq_cpu_port_info[unit] == NULL) { 3589 _bcm_th_cosq_cleanup(unit); 3590 return BCM_E_MEMORY; 3591 } 3592 } 3593 sal_memset(_bcm_th_cosq_cpu_port_info[unit], 0, alloc_size); 3594 3595 /* Create MMU Port Information structure */ 3596 alloc_size = sizeof(_bcm_th_mmu_info_t); 3597 if (_bcm_th_mmu_info[unit] == NULL) { 3598 _bcm_th_mmu_info[unit] = 3599 sal_alloc(alloc_size, "_bcm_th_mmu_info"); 3600 if (_bcm_th_mmu_info[unit] == NULL) { 3601 _bcm_th_cosq_cleanup(unit); 3602 return BCM_E_MEMORY; 3603 } 3604 } 3605 sal_memset(_bcm_th_mmu_info[unit], 0, alloc_size); 3606 _BCM_TH_MMU_INFO(unit)->_bcm_th_port_info = 3607 _bcm_th_cosq_port_info[unit]; 3608 _BCM_TH_MMU_INFO(unit)->_bcm_th_cpu_port_info = 3609 _bcm_th_cosq_cpu_port_info[unit]; 3610 3611 /* Create profile for PORT_COS_MAP table */ 3612 if (_bcm_th_cos_map_profile[unit] == NULL) { 3613 _bcm_th_cos_map_profile[unit] = sal_alloc(sizeof(soc_profile_mem_t), 3614 "COS_MAP Profile Mem"); 3615 if (_bcm_th_cos_map_profile[unit] == NULL) { 3616 _bcm_th_cosq_cleanup(unit); 3617 return BCM_E_MEMORY; 3618 } 3619 soc_profile_mem_t_init(_bcm_th_cos_map_profile[unit]); 3620 } 3621 mem = PORT_COS_MAPm; 3622 entry_words[0] = sizeof(port_cos_map_entry_t) / sizeof(uint32); 3623 3624 rv = soc_profile_mem_create(unit, &mem, entry_words, 1, 3625 _bcm_th_cos_map_profile[unit]); 3626 if (rv != SOC_E_NONE) { 3627 _bcm_th_cosq_cleanup(unit); 3628 return rv; 3629 } 3630 3631 /* Create profile for IFP_COS_MAP table */ 3632 if (_bcm_th_ifp_cos_map_profile[unit] == NULL) { 3633 _bcm_th_ifp_cos_map_profile[unit] 3634 = sal_alloc(sizeof(soc_profile_mem_t), "IFP_COS_MAP Profile Mem"); 3635 if (_bcm_th_ifp_cos_map_profile[unit] == NULL) { 3636 _bcm_th_cosq_cleanup(unit); 3637 return BCM_E_MEMORY; 3638 } 3639 soc_profile_mem_t_init(_bcm_th_ifp_cos_map_profile[unit]); 3640 } 3641 mem = IFP_COS_MAPm; 3642 entry_words[0] = sizeof(ifp_cos_map_entry_t) / sizeof(uint32); 3643 3644 rv = soc_profile_mem_create(unit, &mem, entry_words, 1, 3645 _bcm_th_ifp_cos_map_profile[unit]); 3646 if (rv != SOC_E_NONE) { 3647 _bcm_th_cosq_cleanup(unit); 3648 return rv; 3649 } 3650 3651 /* Create profile for MMU_WRED_DROP_CURVE_PROFILE_x tables */ 3652 if (_bcm_th_wred_profile[unit] == NULL) { 3653 _bcm_th_wred_profile[unit] = 3654 sal_alloc(sizeof(soc_profile_mem_t), "WRED Profile Mem"); 3655 if (_bcm_th_wred_profile[unit] == NULL) { 3656 _bcm_th_cosq_cleanup(unit); 3657 return BCM_E_MEMORY; 3658 } 3659 soc_profile_mem_t_init(_bcm_th_wred_profile[unit]); 3660 } 3661 3662 3663 entry_words[0] = 3664 sizeof(mmu_wred_drop_curve_profile_0_entry_t) / sizeof(uint32); 3665 entry_words[1] = 3666 sizeof(mmu_wred_drop_curve_profile_1_entry_t) / sizeof(uint32); 3667 entry_words[2] = 3668 sizeof(mmu_wred_drop_curve_profile_2_entry_t) / sizeof(uint32); 3669 entry_words[3] = 3670 sizeof(mmu_wred_drop_curve_profile_3_entry_t) / sizeof(uint32); 3671 entry_words[4] = 3672 sizeof(mmu_wred_drop_curve_profile_4_entry_t) / sizeof(uint32); 3673 entry_words[5] = 3674 sizeof(mmu_wred_drop_curve_profile_5_entry_t) / sizeof(uint32); 3675 entry_words[6] = 3676 sizeof(mmu_wred_drop_curve_profile_6_entry_t) / sizeof(uint32); 3677 entry_words[7] = 3678 sizeof(mmu_wred_drop_curve_profile_7_entry_t) / sizeof(uint32); 3679 entry_words[8] = 3680 sizeof(mmu_wred_drop_curve_profile_8_entry_t) / sizeof(uint32); 3681 3682 rv = soc_profile_mem_create(unit, wred_mems, entry_words, 9, 3683 _bcm_th_wred_profile[unit]); 3684 if (rv != SOC_E_NONE) { 3685 _bcm_th_cosq_cleanup(unit); 3686 return rv; 3687 } 3688 3689 /* Create profile for PRIO2COS_PROFILE register */ 3690 if (_bcm_th_prio2cos_profile[unit] == NULL) { 3691 _bcm_th_prio2cos_profile[unit] = 3692 sal_alloc(sizeof(soc_profile_reg_t), "PRIO2COS_PROFILE Profile Reg"); 3693 if (_bcm_th_prio2cos_profile[unit] == NULL) { 3694 _bcm_th_cosq_cleanup(unit); 3695 return BCM_E_MEMORY; 3696 } 3697 soc_profile_reg_t_init(_bcm_th_prio2cos_profile[unit]); 3698 } 3699 reg = PRIO2COS_PROFILEr; 3700 rv = soc_profile_reg_create(unit, ®, 1, _bcm_th_prio2cos_profile[unit]); 3701 if (rv != SOC_E_NONE) { 3702 _bcm_th_cosq_cleanup(unit); 3703 return rv; 3704 } 3705 3706 if (_bcm_th_cosq_cpu_cosq_config[unit][0] == NULL) { 3707 cpu_cosq_config_p = sal_alloc( 3708 SOC_TH_NUM_CPU_QUEUES * sizeof(_bcm_th_cosq_cpu_cosq_config_t), 3709 "CPU Cosq Config"); 3710 if (cpu_cosq_config_p == NULL) { 3711 _bcm_th_cosq_cleanup(unit); 3712 return BCM_E_MEMORY; 3713 } 3714 if (NUM_CPU_COSQ(unit) > SOC_TH_NUM_CPU_QUEUES) { 3715 /* Invalid CPU Queues */ 3716 if (cpu_cosq_config_p != NULL) { 3717 sal_free(cpu_cosq_config_p); 3718 cpu_cosq_config_p = NULL; 3719 } 3720 _bcm_th_cosq_cleanup(unit); 3721 return BCM_E_INIT; 3722 } 3723 for (i = 0; i < NUM_CPU_COSQ(unit); i++) { 3724 _bcm_th_cosq_cpu_cosq_config[unit][i] = cpu_cosq_config_p + i; 3725 } 3726 } 3727 3728 /* Assign default init values for RQE queue number */ 3729 rv = _bcm_th_rqe_q_init(unit); 3730 if (rv != BCM_E_NONE) { 3731 if (cpu_cosq_config_p != NULL) { 3732 sal_free(cpu_cosq_config_p); 3733 cpu_cosq_config_p = NULL; 3734 } 3735 _bcm_th_cosq_cleanup(unit); 3736 return rv; 3737 } 3738 3739 /* Requires ECN init to program the default Responsive/Non-responsive 3740 * settings in Hardware 3741 */ 3742 if(soc_feature(unit, soc_feature_ecn_wred)) { 3743 rv = _bcm_th_ecn_init(unit); 3744 if (rv != BCM_E_NONE) { 3745 if (cpu_cosq_config_p != NULL) { 3746 sal_free(cpu_cosq_config_p); 3747 cpu_cosq_config_p = NULL; 3748 } 3749 _bcm_th_cosq_cleanup(unit); 3750 return rv; 3751 } 3752 } 3753 3754 #if defined(INCLUDE_PSTATS) 3755 if (soc_feature(unit, soc_feature_pstats)) { 3756 rv = _bcm_pstats_init(unit); 3757 if (rv != BCM_E_NONE) { 3758 if (cpu_cosq_config_p != NULL) { 3759 sal_free(cpu_cosq_config_p); 3760 cpu_cosq_config_p = NULL; 3761 } 3762 _bcm_th_cosq_cleanup(unit); 3763 return rv; 3764 } 3765 } 3766 #endif /* INCLUDE_PSTATS */ 3767 3768 rv = _bcm_oob_init(unit); 3769 if (rv != BCM_E_NONE) { 3770 if (cpu_cosq_config_p != NULL) { 3771 sal_free(cpu_cosq_config_p); 3772 cpu_cosq_config_p = NULL; 3773 } 3774 _bcm_th_cosq_cleanup(unit); 3775 return rv; 3776 } 3777 3778 3779 #if defined (INCLUDE_TCB) && defined (BCM_TCB_SUPPORT) 3780 if(soc_feature(unit, soc_feature_tcb)) { 3781 #ifdef BCM_TOMAHAWK2_SUPPORT 3782 rv = bcm_th2_cosq_tcb_init(unit); 3783 #endif 3784 } 3785 if (rv != BCM_E_NONE) { 3786 if (cpu_cosq_config_p != NULL) { 3787 sal_free(cpu_cosq_config_p); 3788 cpu_cosq_config_p = NULL; 3789 } 3790 _bcm_th_cosq_cleanup(unit); 3791 return rv; 3792 } 3793 #endif 3794 3795 #ifdef BCM_WARM_BOOT_SUPPORT 3796 if (SOC_WARM_BOOT(unit)) { 3797 rv = bcm_th_cosq_reinit(unit); 3798 if (rv != BCM_E_NONE) { 3799 if (cpu_cosq_config_p != NULL) { 3800 sal_free(cpu_cosq_config_p); 3801 cpu_cosq_config_p = NULL; 3802 } 3803 _bcm_th_cosq_cleanup(unit); 3804 } 3805 /* 3806 * COVERITY 3807 * 3808 * This checker will not be True. 3809 * cpu_cosq_config_p pointer is assigned to 3810 * _bcm_th_cosq_cpu_cosq_config global data 3811 * structure. 3812 */ 3813 /* coverity[resource_leak] */ 3814 return rv; 3815 } else { 3816 rv = _bcm_th_cosq_wb_alloc(unit); 3817 if (rv != BCM_E_NONE) { 3818 if (cpu_cosq_config_p != NULL) { 3819 sal_free(cpu_cosq_config_p); 3820 cpu_cosq_config_p = NULL; 3821 } 3822 _bcm_th_cosq_cleanup(unit); 3823 return rv; 3824 } 3825 } 3826 #endif /* BCM_WARM_BOOT_SUPPORT */ 3827 3828 /* Assign default init values for CPU info */ 3829 for (i = 0; i < NUM_CPU_COSQ(unit); i++) { 3830 if (_bcm_th_cosq_cpu_cosq_config[unit][i] == NULL) { 3831 if (cpu_cosq_config_p != NULL) { 3832 sal_free(cpu_cosq_config_p); 3833 cpu_cosq_config_p = NULL; 3834 } 3835 _bcm_th_cosq_cleanup(unit); 3836 return BCM_E_MEMORY; 3837 } 3838 sal_memset(_bcm_th_cosq_cpu_cosq_config[unit][i], 0, 3839 sizeof(_bcm_th_cosq_cpu_cosq_config_t)); 3840 _bcm_th_cosq_cpu_cosq_config[unit][i]->enable = 1; 3841 } 3842 3843 /* Add default entries for PORT_COS_MAP memory profile */ 3844 rv = bcm_th_cosq_config_set(unit, numq); 3845 if (rv != BCM_E_NONE) { 3846 if (cpu_cosq_config_p != NULL) { 3847 sal_free(cpu_cosq_config_p); 3848 cpu_cosq_config_p = NULL; 3849 } 3850 _bcm_th_cosq_cleanup(unit); 3851 return rv; 3852 } 3853 3854 for (pipe = 0; pipe < NUM_PIPE(unit); pipe++) { 3855 for (xpe = 0; xpe < NUM_XPE(unit); xpe++) { 3856 if (si->epipe_xpe_map[pipe] & (1 << xpe)) { 3857 mem = SOC_MEM_UNIQUE_ACC_XPE_PIPE(unit, MMU_WRED_CONFIGm, 3858 xpe, pipe); 3859 rv = soc_mem_clear(unit, mem, COPYNO_ALL, 1); 3860 if (rv != SOC_E_NONE) { 3861 if (cpu_cosq_config_p != NULL) { 3862 sal_free(cpu_cosq_config_p); 3863 cpu_cosq_config_p = NULL; 3864 } 3865 _bcm_th_cosq_cleanup(unit); 3866 return rv; 3867 } 3868 } 3869 } 3870 } 3871 3872 /* Add default entries for MMU_WRED_DROP_CURVE_PROFILE_x memory profile */ 3873 sal_memset(&entry_tcp_green, 0, sizeof(entry_tcp_green)); 3874 sal_memset(&entry_tcp_yellow,0, sizeof(entry_tcp_yellow)); 3875 sal_memset(&entry_tcp_red, 0, sizeof(entry_tcp_red)); 3876 sal_memset(&entry_nontcp_green, 0, sizeof(entry_nontcp_green)); 3877 sal_memset(&entry_nontcp_yellow, 0, sizeof(entry_nontcp_yellow)); 3878 sal_memset(&entry_nontcp_red, 0, sizeof(entry_nontcp_red)); 3879 sal_memset(&entry_ecn_green, 0, sizeof(entry_ecn_green)); 3880 sal_memset(&entry_ecn_yellow,0, sizeof(entry_ecn_yellow)); 3881 sal_memset(&entry_ecn_red, 0, sizeof(entry_ecn_red)); 3882 entries[0] = &entry_tcp_green; 3883 entries[1] = &entry_tcp_yellow; 3884 entries[2] = &entry_tcp_red; 3885 entries[3] = &entry_nontcp_green; 3886 entries[4] = &entry_nontcp_yellow; 3887 entries[5] = &entry_nontcp_red; 3888 entries[6] = &entry_ecn_green; 3889 entries[7] = &entry_ecn_yellow; 3890 entries[8] = &entry_ecn_red; 3891 3892 for (ii = 0; ii < 9; ii++) { 3893 soc_mem_field32_set(unit, wred_mems[ii], entries[ii], 3894 MIN_THDf, 0xffff); 3895 soc_mem_field32_set(unit, wred_mems[ii], entries[ii], 3896 MAX_THDf, 0xffff); 3897 } 3898 profile_index = 0xffffffff; 3899 wred_config_mem = SOC_MEM_UNIQUE_ACC(unit, MMU_WRED_CONFIGm)[0]; 3900 wred_prof_count = soc_mem_index_count(unit, wred_config_mem); 3901 3902 /* In TH Profile table duplicate across all pipes all (related) xpes. 3903 * Ref count needs to be updated too */ 3904 wred_prof_count *= (2 * NUM_PIPE(unit)); 3905 while(wred_prof_count) { 3906 if (profile_index == 0xffffffff) { 3907 rv = soc_profile_mem_add(unit, _bcm_th_wred_profile[unit], 3908 entries, 1, &profile_index); 3909 } else { 3910 rv = soc_profile_mem_reference(unit, _bcm_th_wred_profile[unit], 3911 profile_index, 0); 3912 } 3913 if (rv != SOC_E_NONE) { 3914 if (cpu_cosq_config_p != NULL) { 3915 sal_free(cpu_cosq_config_p); 3916 cpu_cosq_config_p = NULL; 3917 } 3918 _bcm_th_cosq_cleanup(unit); 3919 return rv; 3920 } 3921 wred_prof_count -= 1; 3922 } 3923 3924 for (i = 0; i < _BCM_TH_NUM_WRED_RESOLUTION_TABLE; i++) { 3925 if (i == 0) { 3926 _bcm_th_wred_resolution_tbl[i] = 1; 3927 } else { 3928 _bcm_th_wred_resolution_tbl[i] = 0; 3929 } 3930 } 3931 3932 3933 /* Add default entries for PRIO2COS_PROFILE register profile */ 3934 sal_memset(rval64s, 0, sizeof(rval64s)); 3935 prval64s[0] = rval64s; 3936 profile_index = 0xffffffff; 3937 PBMP_PORT_ITER(unit, port) { 3938 if (profile_index == 0xffffffff) { 3939 rv = soc_profile_reg_add(unit, _bcm_th_prio2cos_profile[unit], 3940 prval64s, 16, &profile_index); 3941 } else { 3942 rv = soc_profile_reg_reference(unit, _bcm_th_prio2cos_profile[unit], 3943 profile_index, 0); 3944 } 3945 if (rv == SOC_E_NONE) { 3946 rv = soc_reg32_get(unit, PORT_LLFC_CFGr, port, 0, &rval); 3947 soc_reg_field_set(unit, PORT_LLFC_CFGr, &rval, PROFILE_INDEXf, 3948 profile_index/16); 3949 rv = soc_reg32_set(unit, PORT_LLFC_CFGr, port, 0, rval); 3950 } 3951 if (rv != SOC_E_NONE) { 3952 if (cpu_cosq_config_p != NULL) { 3953 sal_free(cpu_cosq_config_p); 3954 cpu_cosq_config_p = NULL; 3955 } 3956 _bcm_th_cosq_cleanup(unit); 3957 return rv; 3958 } 3959 } 3960 3961 _BCM_TH_MMU_INFO(unit)->gport_tree_created = FALSE; 3962 PBMP_ALL_ITER(unit, port) { 3963 if (IS_LB_PORT(unit, port)) { 3964 continue; 3965 } 3966 rv = _bcm_th_cosq_gport_tree_create(unit, port); 3967 if (rv != BCM_E_NONE) { 3968 if (cpu_cosq_config_p != NULL) { 3969 sal_free(cpu_cosq_config_p); 3970 cpu_cosq_config_p = NULL; 3971 } 3972 _bcm_th_cosq_cleanup(unit); 3973 return rv; 3974 } 3975 } 3976 _BCM_TH_MMU_INFO(unit)->gport_tree_created = TRUE; 3977 3978 rv = _bcm_th_cosq_gport_default_config(unit); 3979 if (rv != BCM_E_NONE) { 3980 if (cpu_cosq_config_p != NULL) { 3981 sal_free(cpu_cosq_config_p); 3982 cpu_cosq_config_p = NULL; 3983 } 3984 _bcm_th_cosq_cleanup(unit); 3985 return rv; 3986 } 3987 3988 sal_memset(&bst_callbks, 0, sizeof(_bcm_bst_device_handlers_t)); 3989 bst_callbks.resolve_index = &_bcm_th_bst_index_resolve; 3990 bst_callbks.reverse_resolve_index = 3991 &_bcm_th_cosq_bst_map_resource_to_gport_cos; 3992 rv = _bcm_bst_attach(unit, &bst_callbks); 3993 if (rv != BCM_E_NONE) { 3994 if (cpu_cosq_config_p != NULL) { 3995 sal_free(cpu_cosq_config_p); 3996 cpu_cosq_config_p = NULL; 3997 } 3998 _bcm_th_cosq_cleanup(unit); 3999 return rv; 4000 } 4001 4002 if (soc_feature(unit, soc_feature_pfc_deadlock)) { 4003 rv = _bcm_pfc_deadlock_init(unit); 4004 if (rv != BCM_E_NONE) { 4005 if (cpu_cosq_config_p != NULL) { 4006 sal_free(cpu_cosq_config_p); 4007 cpu_cosq_config_p = NULL; 4008 } 4009 _bcm_th_cosq_cleanup(unit); 4010 return rv; 4011 } 4012 } 4013 4014 rv = soc_th_mmu_get_shared_size(unit, 4015 _BCM_TH_MMU_INFO(unit)->ing_shared_limit, 4016 _BCM_TH_MMU_INFO(unit)->egr_db_shared_limit, 4017 _BCM_TH_MMU_INFO(unit)->egr_qe_shared_limit); 4018 if (rv != SOC_E_NONE) { 4019 if (cpu_cosq_config_p != NULL) { 4020 sal_free(cpu_cosq_config_p); 4021 cpu_cosq_config_p = NULL; 4022 } 4023 _bcm_th_cosq_cleanup(unit); 4024 return rv; 4025 } 4026 4027 /* reset time_domain ref_count so that entries can be added upon 4028 * rc */ 4029 time_domain_info[unit][0].ref_count = 466; 4030 time_domain_info[unit][1].ref_count = 0; 4031 time_domain_info[unit][2].ref_count = 0; 4032 time_domain_info[unit][3].ref_count = 0; 4033 return BCM_E_NONE; 4034 } 4035 4036 /* 4037 * Function: 4038 * bcm_th_cosq_port_sched_set 4039 * Purpose: 4040 * Set up class-of-service policy and corresponding weights and delay 4041 * Parameters: 4042 * unit - (IN) unit number 4043 * pbm - (IN) port bitmap 4044 * mode - (IN) Scheduling mode (BCM_COSQ_xxx) 4045 * weights - (IN) Weights for each COS queue 4046 * delay - This parameter is not used 4047 * Returns: 4048 * BCM_E_XXX 4049 */ 4050 int 4051 bcm_th_cosq_port_sched_set(int unit, bcm_pbmp_t pbm, 4052 int mode, const int *weights, int delay) 4053 { 4054 bcm_port_t port; 4055 int num_weights, i; 4056 4057 BCM_PBMP_ITER(pbm, port) { 4058 num_weights = _TH_NUM_COS(unit); 4059 for (i = 0; i < num_weights; i++) { 4060 BCM_IF_ERROR_RETURN 4061 (_bcm_th_cosq_sched_set(unit, port, i, mode, weights[i])); 4062 } 4063 } 4064 4065 return BCM_E_NONE; 4066 } 4067 4068 /* 4069 * Function: 4070 * bcm_th_cosq_port_sched_get 4071 * Purpose: 4072 * Retrieve class-of-service policy and corresponding weights and delay 4073 * Parameters: 4074 * unit - (IN) unit number 4075 * pbm - (IN) port bitmap 4076 * mode - (OUT) Scheduling mode (BCM_COSQ_XXX) 4077 * weights - (OUT) Weights for each COS queue 4078 * delay - This parameter is not used 4079 * Returns: 4080 * BCM_E_XXX 4081 */ 4082 int 4083 bcm_th_cosq_port_sched_get(int unit, bcm_pbmp_t pbm, 4084 int *mode, int *weights, int *delay) 4085 { 4086 bcm_port_t port; 4087 int i, num_weights; 4088 4089 BCM_PBMP_ITER(pbm, port) { 4090 if (IS_CPU_PORT(unit, port) && SOC_PBMP_NEQ(pbm, PBMP_CMIC(unit))) { 4091 continue; 4092 } 4093 num_weights = _TH_NUM_COS(unit); 4094 for (i = 0; i < num_weights; i++) { 4095 BCM_IF_ERROR_RETURN( 4096 _bcm_th_cosq_sched_get(unit, port, i, mode, &weights[i])); 4097 } 4098 } 4099 4100 return BCM_E_NONE; 4101 } 4102 4103 /* 4104 * Function: 4105 * bcm_th_cosq_sched_weight_max_get 4106 * Purpose: 4107 * Retrieve maximum weights for given COS policy 4108 * Parameters: 4109 * unit - (IN) unit number 4110 * mode - (IN) Scheduling mode (BCM_COSQ_xxx) 4111 * weight_max - (OUT) Maximum weight for COS queue. 4112 * Returns: 4113 * BCM_E_XXX 4114 */ 4115 int 4116 bcm_th_cosq_sched_weight_max_get(int unit, int mode, int *weight_max) 4117 { 4118 switch (mode) { 4119 case BCM_COSQ_STRICT: 4120 *weight_max = BCM_COSQ_WEIGHT_STRICT; 4121 break; 4122 case BCM_COSQ_ROUND_ROBIN: 4123 case BCM_COSQ_WEIGHTED_ROUND_ROBIN: 4124 case BCM_COSQ_DEFICIT_ROUND_ROBIN: 4125 /* In TH the maximum weight will be 127 */ 4126 *weight_max = 4127 (1 << soc_mem_field_length(unit, Q_SCHED_L0_WEIGHT_MEMm, 4128 WEIGHTf)) - 1; 4129 break; 4130 default: 4131 return BCM_E_PARAM; 4132 } 4133 4134 return BCM_E_NONE; 4135 } 4136 4137 /* 4138 * Function: 4139 * bcm_th_cosq_port_bandwidth_set 4140 * Purpose: 4141 * Configure COS queue bandwidth control 4142 * Parameters: 4143 * unit - (IN) unit number 4144 * port - (IN) port number or GPORT identifier 4145 * cosq - (IN) COS queue number 4146 * min_quantum - (IN) 4147 * max_quantum - (IN) 4148 * burst_quantum - (IN) 4149 * flags - (IN) 4150 * Returns: 4151 * BCM_E_XXX 4152 * Notes: 4153 * If port is any form of local port, cosq is the hardware queue index. 4154 */ 4155 int 4156 bcm_th_cosq_port_bandwidth_set(int unit, bcm_port_t port, 4157 bcm_cos_queue_t cosq, 4158 uint32 min_quantum, uint32 max_quantum, 4159 uint32 burst_quantum, uint32 flags) 4160 { 4161 uint32 burst_min, burst_max; 4162 4163 if (cosq < 0) { 4164 return BCM_E_PARAM; 4165 } 4166 4167 if (BCM_GPORT_IS_SET(port) && 4168 ((BCM_GPORT_IS_SCHEDULER(port)) || 4169 BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 4170 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) || 4171 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port))) { 4172 return BCM_E_UNAVAIL; 4173 } 4174 4175 burst_min = (min_quantum > 0) ? 4176 _bcm_td_default_burst_size(unit, port, min_quantum) : 0; 4177 4178 burst_max = (max_quantum > 0) ? 4179 _bcm_td_default_burst_size(unit, port, max_quantum) : 0; 4180 4181 return _bcm_th_cosq_bucket_set(unit, port, cosq, min_quantum, max_quantum, 4182 burst_min, burst_max, flags); 4183 } 4184 4185 /* 4186 * Function: 4187 * bcm_th_cosq_port_bandwidth_get 4188 * Purpose: 4189 * Get COS queue bandwidth control configuration 4190 * Parameters: 4191 * unit - (IN) unit number 4192 * port - (IN) port number or GPORT identifier 4193 * cosq - (IN) COS queue number 4194 * min_quantum - (OUT) 4195 * max_quantum - (OUT) 4196 * burst_quantum - (OUT) 4197 * flags - (OUT) 4198 * Returns: 4199 * BCM_E_XXX 4200 * Notes: 4201 * If port is any form of local port, cosq is the hardware queue index. 4202 */ 4203 int 4204 bcm_th_cosq_port_bandwidth_get(int unit, bcm_port_t port, 4205 bcm_cos_queue_t cosq, 4206 uint32 *min_quantum, uint32 *max_quantum, 4207 uint32 *burst_quantum, uint32 *flags) 4208 { 4209 uint32 kbit_burst_min; 4210 4211 if (cosq < -1) { 4212 return BCM_E_PARAM; 4213 } 4214 4215 if (BCM_GPORT_IS_SET(port) && 4216 ((BCM_GPORT_IS_SCHEDULER(port)) || 4217 BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 4218 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) || 4219 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port))) { 4220 return BCM_E_UNAVAIL; 4221 } 4222 4223 BCM_IF_ERROR_RETURN(_bcm_th_cosq_bucket_get(unit, port, cosq, 4224 min_quantum, max_quantum, &kbit_burst_min, 4225 burst_quantum, flags)); 4226 return BCM_E_NONE; 4227 } 4228 4229 int 4230 bcm_th_cosq_port_pps_set(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 4231 int pps) 4232 { 4233 uint32 min, max, burst, burst_min, flags; 4234 bcm_port_t local_port = port; 4235 4236 if (!IS_CPU_PORT(unit, port)) { 4237 return BCM_E_PORT; 4238 } else if (cosq < 0 || cosq >= NUM_CPU_COSQ(unit)) { 4239 return BCM_E_PARAM; 4240 } 4241 4242 if (BCM_GPORT_IS_SET(port) && 4243 ((BCM_GPORT_IS_SCHEDULER(port)) || 4244 BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 4245 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) || 4246 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port))) { 4247 return BCM_E_UNAVAIL; 4248 } 4249 4250 BCM_IF_ERROR_RETURN 4251 (_bcm_th_cosq_bucket_get(unit, port, cosq, &min, &max, &burst_min, 4252 &burst, &flags)); 4253 min = pps; 4254 burst_min = (min > 0) ? 4255 _bcm_td_default_burst_size(unit, local_port, min) : 0; 4256 burst = burst_min; 4257 4258 return _bcm_th_cosq_bucket_set(unit, port, cosq, min, pps, burst_min, 4259 burst, flags | BCM_COSQ_BW_PACKET_MODE); 4260 } 4261 4262 int 4263 bcm_th_cosq_port_pps_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 4264 int *pps) 4265 { 4266 uint32 min, max, burst, flags; 4267 4268 if (!IS_CPU_PORT(unit, port)) { 4269 return BCM_E_PORT; 4270 } else if (cosq < 0 || cosq >= NUM_CPU_COSQ(unit)) { 4271 return BCM_E_PARAM; 4272 } 4273 4274 if (BCM_GPORT_IS_SET(port) && 4275 ((BCM_GPORT_IS_SCHEDULER(port)) || 4276 BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 4277 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) || 4278 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port))) { 4279 return BCM_E_UNAVAIL; 4280 } 4281 4282 BCM_IF_ERROR_RETURN 4283 (_bcm_th_cosq_bucket_get(unit, port, cosq, &min, &max, &burst, &burst, 4284 &flags)); 4285 *pps = max; 4286 4287 return BCM_E_NONE; 4288 } 4289 4290 int 4291 bcm_th_cosq_port_burst_set(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 4292 int burst) 4293 { 4294 uint32 min, max, cur_burst, flags; 4295 4296 if (!IS_CPU_PORT(unit, port)) { 4297 return BCM_E_PORT; 4298 } else if (cosq < 0 || cosq >= NUM_CPU_COSQ(unit)) { 4299 return BCM_E_PARAM; 4300 } 4301 4302 if (BCM_GPORT_IS_SET(port) && 4303 ((BCM_GPORT_IS_SCHEDULER(port)) || 4304 BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 4305 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) || 4306 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port))) { 4307 return BCM_E_UNAVAIL; 4308 } 4309 4310 BCM_IF_ERROR_RETURN 4311 (_bcm_th_cosq_bucket_get(unit, port, cosq, &min, &max, &cur_burst, 4312 &cur_burst, &flags)); 4313 4314 /* Replace the current BURST setting, keep PPS the same */ 4315 4316 return _bcm_th_cosq_bucket_set(unit, port, cosq, min, max, burst, burst, 4317 flags | BCM_COSQ_BW_PACKET_MODE); 4318 return BCM_E_NONE; 4319 } 4320 4321 int 4322 bcm_th_cosq_port_burst_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 4323 int *burst) 4324 { 4325 uint32 min, max, cur_burst, cur_burst_min, flags; 4326 4327 if (!IS_CPU_PORT(unit, port)) { 4328 return BCM_E_PORT; 4329 } else if (cosq < 0 || cosq >= NUM_CPU_COSQ(unit)) { 4330 return BCM_E_PARAM; 4331 } 4332 4333 if (BCM_GPORT_IS_SET(port) && 4334 ((BCM_GPORT_IS_SCHEDULER(port)) || 4335 BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 4336 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) || 4337 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port))) { 4338 return BCM_E_PARAM; 4339 } 4340 4341 BCM_IF_ERROR_RETURN 4342 (_bcm_th_cosq_bucket_get(unit, port, cosq, &min, &max, 4343 &cur_burst_min, &cur_burst, &flags)); 4344 *burst = cur_burst; 4345 return BCM_E_NONE; 4346 } 4347 4348 /* 4349 * Function: 4350 * bcm_th_cosq_gport_traverse 4351 * Purpose: 4352 * Walks through the valid COSQ GPORTs and calls 4353 * the user supplied callback function for each entry. 4354 * Parameters: 4355 * unit - (IN) unit number 4356 * trav_fn - (IN) Callback function. 4357 * user_data - (IN) User data to be passed to callback function 4358 * Returns: 4359 * BCM_E_NONE - Success. 4360 * BCM_E_XXX 4361 */ 4362 int 4363 bcm_th_cosq_gport_traverse(int unit, bcm_cosq_gport_traverse_cb cb, 4364 void *user_data) 4365 { 4366 _bcm_th_cosq_port_info_t *port_info = NULL; 4367 _bcm_th_cosq_cpu_port_info_t *cpu_port_info = NULL; 4368 bcm_module_t my_modid, modid_out; 4369 bcm_port_t port, port_out, local_port; 4370 bcm_gport_t gport; 4371 int id, rv = SOC_E_NONE; 4372 4373 if (_bcm_th_cosq_port_info[unit] == NULL) { 4374 return BCM_E_INIT; 4375 } 4376 if (_bcm_th_cosq_cpu_port_info[unit] == NULL) { 4377 return BCM_E_INIT; 4378 } 4379 4380 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_modid)); 4381 PBMP_ALL_ITER(unit, port) { 4382 BCM_IF_ERROR_RETURN 4383 (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, 4384 my_modid, port, &modid_out, &port_out)); 4385 BCM_GPORT_MODPORT_SET(gport, modid_out, port_out); 4386 4387 BCM_IF_ERROR_RETURN 4388 (_bcm_th_cosq_localport_resolve(unit, port, &local_port)); 4389 4390 if (IS_CPU_PORT(unit, local_port)) { 4391 cpu_port_info = &_bcm_th_cosq_cpu_port_info[unit][local_port]; 4392 } else { 4393 port_info = &_bcm_th_cosq_port_info[unit][local_port]; 4394 } 4395 if (!IS_CPU_PORT(unit, local_port)) { 4396 for (id = 0; id < _BCM_TH_NUM_UCAST_QUEUE_PER_PORT; id++) { 4397 if (port_info->ucast[id].numq == 0) { 4398 continue; 4399 } 4400 rv = cb(unit, gport, port_info->ucast[id].numq, 4401 BCM_COSQ_GPORT_UCAST_QUEUE_GROUP, 4402 port_info->ucast[id].gport, user_data); 4403 #ifdef BCM_CB_ABORT_ON_ERR 4404 if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) { 4405 return rv; 4406 } 4407 #else 4408 /* 4409 * If CB_ABORT_ON_ERR is not defined don't return error 4410 * and continue. 4411 */ 4412 rv = BCM_E_NONE; 4413 #endif 4414 } 4415 } 4416 if (IS_CPU_PORT(unit, local_port)) { 4417 for (id = 0; id < _BCM_TH_NUM_CPU_MCAST_QUEUE; id++) { 4418 if (cpu_port_info->mcast[id].numq == 0) { 4419 continue; 4420 } 4421 rv = cb(unit, gport, cpu_port_info->mcast[id].numq, 4422 BCM_COSQ_GPORT_MCAST_QUEUE_GROUP, 4423 cpu_port_info->mcast[id].gport, user_data); 4424 #ifdef BCM_CB_ABORT_ON_ERR 4425 if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) { 4426 return rv; 4427 } 4428 #else 4429 /* 4430 * If CB_ABORT_ON_ERR is not defined don't return error 4431 * and continue. 4432 */ 4433 rv = BCM_E_NONE; 4434 #endif 4435 } 4436 } else { 4437 for (id = 0; id < _BCM_TH_NUM_MCAST_QUEUE_PER_PORT; id++) { 4438 if (port_info->mcast[id].numq == 0) { 4439 continue; 4440 } 4441 rv = cb(unit, gport, port_info->mcast[id].numq, 4442 BCM_COSQ_GPORT_MCAST_QUEUE_GROUP, 4443 port_info->mcast[id].gport, user_data); 4444 #ifdef BCM_CB_ABORT_ON_ERR 4445 if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) { 4446 return rv; 4447 } 4448 #else 4449 /* 4450 * If CB_ABORT_ON_ERR is not defined don't return error 4451 * and continue. 4452 */ 4453 rv = BCM_E_NONE; 4454 #endif 4455 } 4456 } 4457 for (id = 0; id < _BCM_TH_NUM_SCHEDULER_PER_PORT; id++) { 4458 if (IS_CPU_PORT(unit, local_port)) { 4459 if (cpu_port_info->sched[id].numq == 0) { 4460 continue; 4461 } 4462 rv = cb(unit, gport, cpu_port_info->sched[id].numq, 4463 BCM_COSQ_GPORT_SCHEDULER, 4464 cpu_port_info->sched[id].gport, user_data); 4465 } else { 4466 if (port_info->sched[id].numq == 0) { 4467 continue; 4468 } 4469 rv = cb(unit, gport, port_info->sched[id].numq, 4470 BCM_COSQ_GPORT_SCHEDULER, 4471 port_info->sched[id].gport, user_data); 4472 } 4473 #ifdef BCM_CB_ABORT_ON_ERR 4474 if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) { 4475 return rv; 4476 } 4477 #else 4478 /* 4479 * If CB_ABORT_ON_ERR is not defined don't return error 4480 * and continue. 4481 */ 4482 rv = BCM_E_NONE; 4483 #endif 4484 } 4485 } 4486 return rv; 4487 } 4488 4489 /* 4490 * Function: 4491 * bcm_cosq_gport_traverse_by_port 4492 * Purpose: 4493 * Walks through the valid COSQ GPORTs belong to a port and calls 4494 * the user supplied callback function for each entry. 4495 * Parameters: 4496 * unit - (IN) unit number 4497 * port - (IN) port number or GPORT identifier 4498 * trav_fn - (IN) Callback function. 4499 * user_data - (IN) User data to be passed to callback function 4500 * Returns: 4501 * BCM_E_NONE - Success. 4502 * BCM_E_XXX 4503 */ 4504 int 4505 bcm_th_cosq_gport_traverse_by_port(int unit, bcm_gport_t port, 4506 bcm_cosq_gport_traverse_cb cb, 4507 void *user_data) 4508 { 4509 _bcm_th_cosq_port_info_t *port_info = NULL; 4510 _bcm_th_cosq_cpu_port_info_t *cpu_port_info = NULL; 4511 bcm_module_t my_modid, modid_out; 4512 bcm_port_t port_out, local_port; 4513 bcm_gport_t gport; 4514 int id, rv = SOC_E_NONE; 4515 4516 if (_bcm_th_cosq_port_info[unit] == NULL) { 4517 return BCM_E_INIT; 4518 } 4519 if (_bcm_th_cosq_cpu_port_info[unit] == NULL) { 4520 return BCM_E_INIT; 4521 } 4522 4523 if (BCM_GPORT_IS_SET(port) && 4524 (!BCM_GPORT_IS_LOCAL(port) && 4525 !BCM_GPORT_IS_DEVPORT(port) && 4526 !BCM_GPORT_IS_MODPORT(port))) { 4527 LOG_ERROR(BSL_LS_BCM_COSQ, (BSL_META_U(unit, 4528 "Invalid gport type\n"))); 4529 return BCM_E_PARAM; 4530 } 4531 4532 BCM_IF_ERROR_RETURN 4533 (_bcm_th_cosq_localport_resolve(unit, port, &local_port)); 4534 4535 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_modid)); 4536 4537 BCM_IF_ERROR_RETURN 4538 (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, 4539 my_modid, port, &modid_out, &port_out)); 4540 BCM_GPORT_MODPORT_SET(gport, modid_out, port_out); 4541 4542 if (IS_CPU_PORT(unit, local_port)) { 4543 cpu_port_info = &_bcm_th_cosq_cpu_port_info[unit][local_port]; 4544 } else { 4545 port_info = &_bcm_th_cosq_port_info[unit][local_port]; 4546 } 4547 if (!IS_CPU_PORT(unit, local_port)) { 4548 for (id = 0; id < _BCM_TH_NUM_UCAST_QUEUE_PER_PORT; id++) { 4549 if (port_info->ucast[id].numq == 0) { 4550 continue; 4551 } 4552 rv = cb(unit, gport, port_info->ucast[id].numq, 4553 BCM_COSQ_GPORT_UCAST_QUEUE_GROUP, 4554 port_info->ucast[id].gport, user_data); 4555 #ifdef BCM_CB_ABORT_ON_ERR 4556 if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) { 4557 return rv; 4558 } 4559 #else 4560 /* 4561 * If CB_ABORT_ON_ERR is not defined don't return error 4562 * and continue. 4563 */ 4564 rv = BCM_E_NONE; 4565 #endif 4566 } 4567 } 4568 if (IS_CPU_PORT(unit, local_port)) { 4569 for (id = 0; id < _BCM_TH_NUM_CPU_MCAST_QUEUE; id++) { 4570 if (cpu_port_info->mcast[id].numq == 0) { 4571 continue; 4572 } 4573 rv = cb(unit, gport, cpu_port_info->mcast[id].numq, 4574 BCM_COSQ_GPORT_MCAST_QUEUE_GROUP, 4575 cpu_port_info->mcast[id].gport, user_data); 4576 #ifdef BCM_CB_ABORT_ON_ERR 4577 if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) { 4578 return rv; 4579 } 4580 #else 4581 /* 4582 * If CB_ABORT_ON_ERR is not defined don't return error 4583 * and continue. 4584 */ 4585 rv = BCM_E_NONE; 4586 #endif 4587 } 4588 } else { 4589 for (id = 0; id < _BCM_TH_NUM_MCAST_QUEUE_PER_PORT; id++) { 4590 if (port_info->mcast[id].numq == 0) { 4591 continue; 4592 } 4593 rv = cb(unit, gport, port_info->mcast[id].numq, 4594 BCM_COSQ_GPORT_MCAST_QUEUE_GROUP, 4595 port_info->mcast[id].gport, user_data); 4596 #ifdef BCM_CB_ABORT_ON_ERR 4597 if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) { 4598 return rv; 4599 } 4600 #else 4601 /* 4602 * If CB_ABORT_ON_ERR is not defined don't return error 4603 * and continue. 4604 */ 4605 rv = BCM_E_NONE; 4606 #endif 4607 } 4608 } 4609 for (id = 0; id < _BCM_TH_NUM_SCHEDULER_PER_PORT; id++) { 4610 if (IS_CPU_PORT(unit, local_port)) { 4611 if (cpu_port_info->sched[id].numq == 0) { 4612 continue; 4613 } 4614 rv = cb(unit, gport, cpu_port_info->sched[id].numq, 4615 BCM_COSQ_GPORT_SCHEDULER, 4616 cpu_port_info->sched[id].gport, user_data); 4617 } else { 4618 if (port_info->sched[id].numq == 0) { 4619 continue; 4620 } 4621 rv = cb(unit, gport, port_info->sched[id].numq, 4622 BCM_COSQ_GPORT_SCHEDULER, 4623 port_info->sched[id].gport, user_data); 4624 } 4625 #ifdef BCM_CB_ABORT_ON_ERR 4626 if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) { 4627 return rv; 4628 } 4629 #else 4630 /* 4631 * If CB_ABORT_ON_ERR is not defined don't return error 4632 * and continue. 4633 */ 4634 rv = BCM_E_NONE; 4635 #endif 4636 } 4637 4638 return rv; 4639 } 4640 4641 4642 /* 4643 * Function: 4644 * bcm_th_cosq_gport_sched_get 4645 * Purpose: 4646 * Get COS queue schedular setting 4647 * Parameters: 4648 * unit - (IN) unit number 4649 * gport - (IN) GPORT identifier 4650 * cosq - (IN) COS queue to get, -1 for any queue 4651 * mode - (OUT) Scheduling mode (BCM_COSQ_XXX) 4652 * weights - (OUT) Weights for queue 4653 * Returns: 4654 * BCM_E_XXX 4655 */ 4656 int 4657 bcm_th_cosq_gport_sched_get(int unit, bcm_gport_t gport, 4658 bcm_cos_queue_t cosq, int *mode, int *weight) 4659 { 4660 _bcm_th_cosq_node_t *node = NULL; 4661 int local_port = -1, cpu_mc_base = 0; 4662 soc_info_t *si = &SOC_INFO(unit); 4663 4664 if (BCM_GPORT_IS_SET(gport)) { 4665 if ((BCM_GPORT_IS_SCHEDULER(gport)) || 4666 BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 4667 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 4668 4669 BCM_IF_ERROR_RETURN 4670 (_bcm_th_cosq_node_get(unit, gport, NULL, &local_port, NULL, &node)); 4671 4672 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 4673 /* For Non-CPU and non-LB ports, num UC queues are 10 */ 4674 cosq = node->hw_index % si->port_num_cosq[local_port]; 4675 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 4676 /* For Non-CPU ports, num MC queues are 10 4677 * For CPU ports, num MC queues are 48 4678 */ 4679 if (IS_CPU_PORT(unit, local_port)) { 4680 cpu_mc_base = si->port_cosq_base[CMIC_PORT(unit)]; 4681 cosq = (node->hw_index - cpu_mc_base) % 4682 _BCM_TH_NUM_CPU_MCAST_QUEUE; 4683 } else { 4684 cosq = node->hw_index % si->port_num_cosq[local_port]; 4685 } 4686 } else { 4687 /* For all ports, total scheduler nodes(L0) are 10 */ 4688 cosq = node->hw_index % _BCM_TH_NUM_SCHEDULER_PER_PORT; 4689 } 4690 BCM_IF_ERROR_RETURN( 4691 _bcm_th_cosq_sched_get(unit, gport, cosq, mode, weight)); 4692 return BCM_E_NONE; 4693 } else { 4694 BCM_IF_ERROR_RETURN(_bcm_th_cosq_localport_resolve(unit, gport, 4695 &local_port)); 4696 4697 if ((cosq < 0) || (cosq >= SOC_PORT_NUM_COSQ(unit, local_port))) { 4698 return BCM_E_PARAM; 4699 } 4700 4701 BCM_IF_ERROR_RETURN( 4702 _bcm_th_cosq_sched_get(unit, local_port, cosq, mode, weight)); 4703 return BCM_E_NONE; 4704 } 4705 } else { 4706 return BCM_E_PORT; 4707 } 4708 4709 return BCM_E_NOT_FOUND; 4710 } 4711 4712 /* 4713 * Function: 4714 * bcm_th_cosq_gport_sched_set 4715 * Purpose: 4716 * Set up class-of-service policy and corresponding weights and delay 4717 * Parameters: 4718 * unit - (IN) unit number 4719 * gport - (IN) GPORT ID 4720 * cosq - (IN) COS queue to configure 4721 * mode - (IN) Scheduling mode (BCM_COSQ_xxx) 4722 * weight - (IN) Weight for COS queue 4723 * Returns: 4724 * BCM_E_XXX 4725 */ 4726 int 4727 bcm_th_cosq_gport_sched_set(int unit, bcm_gport_t gport, 4728 bcm_cos_queue_t cosq, int mode, int weight) 4729 { 4730 _bcm_th_cosq_node_t *node = NULL; 4731 soc_info_t *si = &SOC_INFO(unit); 4732 int local_port = -1, cpu_mc_base = 0; 4733 4734 if (BCM_GPORT_IS_SET(gport)) { 4735 if (BCM_GPORT_IS_SCHEDULER(gport) || 4736 BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 4737 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 4738 4739 BCM_IF_ERROR_RETURN 4740 (_bcm_th_cosq_node_get(unit, gport, NULL, &local_port, 4741 NULL, &node)); 4742 4743 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 4744 /* For Non-CPU and non-LB ports, num UC queues are 10 */ 4745 cosq = node->hw_index % si->port_num_cosq[local_port]; 4746 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 4747 /* For Non-CPU ports, num MC queues are 10 4748 * For CPU ports, num MC queues are 48 4749 */ 4750 if (IS_CPU_PORT(unit, local_port)) { 4751 cpu_mc_base = si->port_cosq_base[CMIC_PORT(unit)]; 4752 cosq = (node->hw_index - cpu_mc_base) % 4753 _BCM_TH_NUM_CPU_MCAST_QUEUE; 4754 } else { 4755 cosq = node->hw_index % si->port_num_cosq[local_port]; 4756 } 4757 } else { 4758 /* For all ports, total scheduler nodes(L0) are 10 */ 4759 cosq = node->hw_index % _BCM_TH_NUM_SCHEDULER_PER_PORT; 4760 } 4761 BCM_IF_ERROR_RETURN 4762 (_bcm_th_cosq_sched_set(unit, gport, cosq, mode, weight)); 4763 return BCM_E_NONE; 4764 } else { 4765 BCM_IF_ERROR_RETURN(_bcm_th_cosq_localport_resolve(unit, gport, 4766 &local_port)); 4767 4768 if ((cosq < 0) || (cosq >= SOC_PORT_NUM_COSQ(unit, local_port))) { 4769 return BCM_E_PARAM; 4770 } 4771 4772 BCM_IF_ERROR_RETURN 4773 (_bcm_th_cosq_sched_set(unit, local_port, cosq, mode, weight)); 4774 return BCM_E_NONE; 4775 } 4776 } else { 4777 return BCM_E_PORT; 4778 } 4779 4780 return BCM_E_NOT_FOUND; 4781 } 4782 4783 /* 4784 * Function: 4785 * bcm_th_cosq_gport_bandwidth_set 4786 * Purpose: 4787 * Configure COS queue bandwidth control 4788 * Parameters: 4789 * unit - (IN) unit number 4790 * gport - (IN) GPORT identifier 4791 * cosq - (IN) COS queue to configure, -1 for all COS queues 4792 * kbits_sec_min - (IN) minimum bandwidth, kbits/sec 4793 * kbits_sec_max - (IN) maximum bandwidth, kbits/sec 4794 * flags - (IN) BCM_COSQ_BW_* 4795 * Returns: 4796 * BCM_E_XXX 4797 */ 4798 int 4799 bcm_th_cosq_gport_bandwidth_set(int unit, bcm_gport_t gport, 4800 bcm_cos_queue_t cosq, uint32 kbits_sec_min, 4801 uint32 kbits_sec_max, uint32 flags) 4802 { 4803 int i, start_cos=0, end_cos=0, local_port; 4804 _bcm_th_cosq_node_t *node = NULL; 4805 uint32 burst_min, burst_max; 4806 4807 BCM_IF_ERROR_RETURN(_bcm_th_cosq_localport_resolve(unit, gport, 4808 &local_port)); 4809 if (BCM_GPORT_IS_SET(gport)) { 4810 if ((BCM_GPORT_IS_SCHEDULER(gport)) || 4811 BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 4812 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 4813 BCM_IF_ERROR_RETURN 4814 (_bcm_th_cosq_node_get(unit, gport, NULL, 4815 NULL, NULL, &node)); 4816 if (node != NULL) { 4817 start_cos = end_cos = node->hw_index; 4818 } else { 4819 cosq = 0; 4820 } 4821 } else { 4822 if (cosq < 0) { 4823 return BCM_E_PARAM; 4824 } 4825 start_cos = end_cos = cosq; 4826 } 4827 } else { 4828 if (cosq < 0) { 4829 return BCM_E_PARAM; 4830 } 4831 start_cos = end_cos = cosq; 4832 } 4833 4834 burst_min = (kbits_sec_min > 0) ? 4835 _bcm_td_default_burst_size(unit, local_port, kbits_sec_min) : 0; 4836 4837 burst_max = (kbits_sec_max > 0) ? 4838 _bcm_td_default_burst_size(unit, local_port, kbits_sec_max) : 0; 4839 4840 for (i = start_cos; i <= end_cos; i++) { 4841 BCM_IF_ERROR_RETURN 4842 (_bcm_th_cosq_bucket_set(unit, gport, i, kbits_sec_min, 4843 kbits_sec_max, burst_min, burst_max, flags)); 4844 } 4845 return BCM_E_NONE; 4846 } 4847 4848 /* 4849 * Function: 4850 * bcm_th_cosq_gport_bandwidth_get 4851 * Purpose: 4852 * Get COS queue bandwidth control configuration 4853 * Parameters: 4854 * unit - (IN) unit number 4855 * gport - (IN) GPORT identifier 4856 * cosq - (IN) COS queue to get, -1 for any COS queue 4857 * kbits_sec_min - (OUT) minimum bandwidth, kbits/sec 4858 * kbits_sec_max - (OUT) maximum bandwidth, kbits/sec 4859 * flags - (OUT) BCM_COSQ_BW_* 4860 * Returns: 4861 * BCM_E_XXX 4862 */ 4863 int 4864 bcm_th_cosq_gport_bandwidth_get(int unit, bcm_gport_t gport, 4865 bcm_cos_queue_t cosq, uint32 *kbits_sec_min, 4866 uint32 *kbits_sec_max, uint32 *flags) 4867 { 4868 uint32 kbits_sec_burst; 4869 4870 BCM_IF_ERROR_RETURN 4871 (_bcm_th_cosq_bucket_get(unit, gport, cosq, 4872 kbits_sec_min, kbits_sec_max, 4873 &kbits_sec_burst, &kbits_sec_burst, flags)); 4874 return BCM_E_NONE; 4875 } 4876 4877 /* 4878 * Function: 4879 * bcm_th_cosq_gport_bandwidth_burst_set 4880 * Purpose: 4881 * Configure COS queue bandwidth burst setting 4882 * Parameters: 4883 * unit - (IN) unit number 4884 * gport - (IN) GPORT identifier 4885 * cosq - (IN) COS queue to configure, -1 for all COS queues 4886 * kbits_burst - (IN) maximum burst, kbits 4887 * Returns: 4888 * BCM_E_XXX 4889 */ 4890 int 4891 bcm_th_cosq_gport_bandwidth_burst_set(int unit, bcm_gport_t gport, 4892 bcm_cos_queue_t cosq, 4893 uint32 kbits_burst_min, 4894 uint32 kbits_burst_max) 4895 { 4896 int i, start_cos=0, end_cos=0; 4897 uint32 kbits_sec_min, kbits_sec_max, kbits_sec_burst, flags; 4898 bcm_port_t local_port; 4899 4900 BCM_IF_ERROR_RETURN 4901 (_bcm_th_cosq_localport_resolve(unit, gport, &local_port)); 4902 4903 start_cos = end_cos = cosq; 4904 4905 if (cosq == BCM_COS_INVALID) { 4906 start_cos = 0; 4907 end_cos = (IS_CPU_PORT(unit, local_port)) ? 4908 NUM_CPU_COSQ(unit) - 1 : SOC_PORT_NUM_COSQ(unit, local_port) 4909 - 1; 4910 } 4911 4912 if (BCM_GPORT_IS_SET(gport)) { 4913 if ((BCM_GPORT_IS_SCHEDULER(gport)) || 4914 BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 4915 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 4916 start_cos = end_cos = 0; 4917 } 4918 } 4919 4920 for (i = start_cos; i <= end_cos; i++) { 4921 BCM_IF_ERROR_RETURN 4922 (_bcm_th_cosq_bucket_get(unit, gport, i, &kbits_sec_min, 4923 &kbits_sec_max, &kbits_sec_burst, 4924 &kbits_sec_burst, &flags)); 4925 BCM_IF_ERROR_RETURN 4926 (_bcm_th_cosq_bucket_set(unit, gport, i, kbits_sec_min, 4927 kbits_sec_max, kbits_burst_min, 4928 kbits_burst_max, flags)); 4929 } 4930 return BCM_E_NONE; 4931 } 4932 4933 /* 4934 * Function: 4935 * bcm_th_cosq_gport_bandwidth_burst_get 4936 * Purpose: 4937 * Get COS queue bandwidth burst setting 4938 * Parameters: 4939 * unit - (IN) unit number 4940 * gport - (IN) GPORT identifier 4941 * cosq - (IN) COS queue to get, -1 for Queue 0 4942 * kbits_burst - (OUT) maximum burst, kbits 4943 * Returns: 4944 * BCM_E_XXX 4945 */ 4946 int 4947 bcm_th_cosq_gport_bandwidth_burst_get(int unit, bcm_gport_t gport, 4948 bcm_cos_queue_t cosq, 4949 uint32 *kbits_burst_min, 4950 uint32 *kbits_burst_max) 4951 { 4952 uint32 kbits_sec_min, kbits_sec_max, flags; 4953 4954 if (cosq < -1) { 4955 return BCM_E_PARAM; 4956 } 4957 4958 BCM_IF_ERROR_RETURN 4959 (_bcm_th_cosq_bucket_get(unit, gport, cosq == -1 ? 0 : cosq, 4960 &kbits_sec_min, &kbits_sec_max, kbits_burst_min, 4961 kbits_burst_max, &flags)); 4962 4963 return BCM_E_NONE; 4964 } 4965 4966 int 4967 bcm_th_cosq_discard_set(int unit, uint32 flags) 4968 { 4969 bcm_port_t port; 4970 4971 if (_bcm_th_cosq_port_info[unit] == NULL) { 4972 return BCM_E_INIT; 4973 } 4974 4975 if (flags & ~(BCM_COSQ_DISCARD_DEVICE | 4976 BCM_COSQ_DISCARD_NONTCP | 4977 BCM_COSQ_DISCARD_COLOR_ALL | 4978 BCM_COSQ_DISCARD_PORT | 4979 BCM_COSQ_DISCARD_TCP | 4980 BCM_COSQ_DISCARD_COLOR_GREEN | 4981 BCM_COSQ_DISCARD_COLOR_YELLOW | 4982 BCM_COSQ_DISCARD_COLOR_RED | 4983 BCM_COSQ_DISCARD_CAP_AVERAGE | 4984 BCM_COSQ_DISCARD_ENABLE | 4985 BCM_COSQ_DISCARD_MARK_CONGESTION)) { 4986 return BCM_E_PARAM; 4987 } 4988 4989 flags &= ~(BCM_COSQ_DISCARD_NONTCP | BCM_COSQ_DISCARD_COLOR_ALL); 4990 4991 PBMP_PORT_ITER(unit, port) { 4992 BCM_IF_ERROR_RETURN 4993 (_bcm_th_cosq_wred_set(unit, port, 0, BCM_COSQ_BUFFER_ID_INVALID, 4994 flags, 0, 0, 0, 0, 4995 FALSE, BCM_COSQ_DISCARD_PORT, 1, 0, 0)); 4996 } 4997 4998 return BCM_E_NONE; 4999 } 5000 5001 int 5002 bcm_th_cosq_discard_get(int unit, uint32 *flags) 5003 { 5004 bcm_port_t port; 5005 5006 PBMP_PORT_ITER(unit, port) { 5007 *flags = 0; 5008 /* use setting from hardware cosq index 0 of the first port */ 5009 return _bcm_th_cosq_wred_get(unit, port, 0, BCM_COSQ_BUFFER_ID_INVALID, 5010 flags, NULL, NULL, NULL, 5011 NULL, BCM_COSQ_DISCARD_PORT, NULL, NULL, 5012 NULL); 5013 } 5014 5015 return BCM_E_NOT_FOUND; 5016 } 5017 5018 /* 5019 * Function: 5020 * bcm_th_cosq_discard_port_set 5021 * Purpose: 5022 * Configure port WRED setting 5023 * Parameters: 5024 * unit - (IN) unit number 5025 * port - (IN) port number or GPORT identifier 5026 * cosq - (IN) COS queue number 5027 * color - (IN) 5028 * drop_start - (IN) 5029 * drop_slot - (IN) 5030 * average_time - (IN) 5031 * Returns: 5032 * BCM_E_XXX 5033 * Notes: 5034 * If port is any form of local port, cosq is the hardware queue index. 5035 * Same as TD2 except for Reg changes. 5036 */ 5037 int 5038 bcm_th_cosq_discard_port_set(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 5039 uint32 color, int drop_start, int drop_slope, 5040 int average_time) 5041 { 5042 bcm_port_t local_port; 5043 bcm_pbmp_t pbmp; 5044 int gain; 5045 uint32 min_thresh, max_thresh, shared_limit, xpe_map; 5046 uint32 bits, flags = 0; 5047 int numq, i; 5048 5049 if (drop_start < 0 || drop_start > 100 || 5050 drop_slope < 0 || drop_slope > 90) { 5051 return BCM_E_PARAM; 5052 } 5053 5054 /* 5055 * average queue size is reculated every 1us, the formula is 5056 * avg_qsize(t + 1) = 5057 * avg_qsize(t) + (cur_qsize - avg_qsize(t)) / (2 ** gain) 5058 * gain = log2(average_time) 5059 */ 5060 bits = average_time & 0xffff; 5061 if (bits != 0) { 5062 bits |= bits >> 1; 5063 bits |= bits >> 2; 5064 bits |= bits >> 4; 5065 bits |= bits >> 8; 5066 gain = _shr_popcount(bits) - 1; 5067 } else { 5068 gain = 0; 5069 } 5070 5071 /* 5072 * per-port cell limit may be disabled. 5073 * per-port per-cos cell limit may be set to use dynamic method. 5074 * therefore drop_start percentage is based on per-device total shared 5075 * cells. 5076 */ 5077 xpe_map = SOC_INFO(unit).ipipe_xpe_map[0]|SOC_INFO(unit).ipipe_xpe_map[1]; 5078 _TH_ARRAY_MIN(_BCM_TH_MMU_INFO(unit)->egr_db_shared_limit, NUM_XPE(unit), 5079 xpe_map, shared_limit); 5080 min_thresh = ((drop_start * shared_limit) + (100 - 1)) / 100; 5081 5082 /* Calculate the max threshold. For a given slope (angle in 5083 * degrees), determine how many packets are in the range from 5084 * 0% drop probability to 100% drop probability. Add that 5085 * number to the min_treshold to the the max_threshold. 5086 */ 5087 max_thresh = min_thresh + _bcm_th_angle_to_cells(drop_slope); 5088 if (max_thresh > TH_WRED_CELL_FIELD_MAX) { 5089 max_thresh = TH_WRED_CELL_FIELD_MAX; 5090 } 5091 5092 if (BCM_GPORT_IS_SET(port)) { 5093 numq = 1; 5094 for (i = 0; i < numq; i++) { 5095 BCM_IF_ERROR_RETURN 5096 (_bcm_th_cosq_wred_set(unit, port, cosq + i, 5097 BCM_COSQ_BUFFER_ID_INVALID, color, 5098 min_thresh, max_thresh, 100, gain, 5099 TRUE, flags, 1, 0, 0)); 5100 } 5101 } else { 5102 if (port == -1) { 5103 BCM_PBMP_ASSIGN(pbmp, PBMP_PORT_ALL(unit)); 5104 } else if (!SOC_PORT_VALID(unit, port)) { 5105 return BCM_E_PORT; 5106 } else { 5107 BCM_PBMP_PORT_SET(pbmp, port); 5108 } 5109 5110 BCM_PBMP_ITER(pbmp, local_port) { 5111 numq = 1; 5112 for (i = 0; i < numq; i++) { 5113 BCM_IF_ERROR_RETURN 5114 (_bcm_th_cosq_wred_set(unit, local_port, cosq + i, 5115 BCM_COSQ_BUFFER_ID_INVALID, color, 5116 min_thresh, max_thresh, 100, gain, 5117 TRUE, 0, 1, 0, 0)); 5118 } 5119 } 5120 } 5121 5122 return BCM_E_NONE; 5123 } 5124 5125 /* 5126 * Function: 5127 * bcm_th_cosq_discard_port_get 5128 * Purpose: 5129 * Get port WRED setting 5130 * Parameters: 5131 * unit - (IN) unit number 5132 * port - (IN) port number or GPORT identifier 5133 * cosq - (IN) COS queue number 5134 * color - (OUT) 5135 * drop_start - (OUT) 5136 * drop_slot - (OUT) 5137 * average_time - (OUT) 5138 * Returns: 5139 * BCM_E_XXX 5140 * Notes: 5141 * If port is any form of local port, cosq is the hardware queue index. 5142 * Same as TD2 except for Reg changes. 5143 */ 5144 int 5145 bcm_th_cosq_discard_port_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 5146 uint32 color, int *drop_start, int *drop_slope, 5147 int *average_time) 5148 { 5149 bcm_port_t local_port; 5150 bcm_pbmp_t pbmp; 5151 int gain, drop_prob; 5152 uint32 min_thresh, max_thresh, shared_limit, xpe_map; 5153 int refresh_time = 0; 5154 5155 if (drop_start == NULL || drop_slope == NULL || average_time == NULL) { 5156 return BCM_E_PARAM; 5157 } 5158 5159 if (BCM_GPORT_IS_SET(port)) { 5160 local_port = port; 5161 } else { 5162 if (port == -1) { 5163 BCM_PBMP_ASSIGN(pbmp, PBMP_PORT_ALL(unit)); 5164 } else if (!SOC_PORT_VALID(unit, port)) { 5165 return BCM_E_PORT; 5166 } else { 5167 BCM_PBMP_PORT_SET(pbmp, port); 5168 } 5169 BCM_PBMP_ITER(pbmp, local_port) { 5170 break; 5171 } 5172 } 5173 5174 BCM_IF_ERROR_RETURN 5175 (_bcm_th_cosq_wred_get(unit, local_port, cosq == -1 ? 0 : cosq, 5176 BCM_COSQ_BUFFER_ID_INVALID, 5177 &color, &min_thresh, &max_thresh, &drop_prob, 5178 &gain, 0, &refresh_time, NULL, NULL)); 5179 5180 /* 5181 * average queue size is reculated every 8us, the formula is 5182 * avg_qsize(t + 1) = 5183 * avg_qsize(t) + (cur_qsize - avg_qsize(t)) / (2 ** gain) 5184 */ 5185 *average_time = (1 << gain); 5186 5187 xpe_map = SOC_INFO(unit).ipipe_xpe_map[0]|SOC_INFO(unit).ipipe_xpe_map[1]; 5188 _TH_ARRAY_MIN(_BCM_TH_MMU_INFO(unit)->egr_db_shared_limit, NUM_XPE(unit), 5189 xpe_map, shared_limit); 5190 5191 if (min_thresh > shared_limit) { 5192 min_thresh = shared_limit; 5193 } 5194 5195 if (max_thresh > shared_limit) { 5196 max_thresh = shared_limit; 5197 } 5198 5199 *drop_start = min_thresh * 100 / shared_limit; 5200 5201 /* Calculate the slope using the min and max threshold. 5202 * The angle is calculated knowing drop probability at min 5203 * threshold is 0% and drop probability at max threshold is 100%. 5204 */ 5205 *drop_slope = _bcm_th_cells_to_angle(max_thresh - min_thresh); 5206 5207 return BCM_E_NONE; 5208 } 5209 5210 /* 5211 * Function: 5212 * bcm_th_cosq_gport_discard_set 5213 * Purpose: 5214 * Configure port WRED setting 5215 * Parameters: 5216 * unit - (IN) unit number 5217 * port - (IN) GPORT identifier 5218 * cosq - (IN) COS queue to configure, -1 for all COS queues 5219 * buffer - (IN) XPE ID 5220 * discard - (IN) discard settings 5221 * Returns: 5222 * BCM_E_XXX 5223 */ 5224 int 5225 bcm_th_cosq_gport_discard_set(int unit, bcm_gport_t gport, 5226 bcm_cos_queue_t cosq, 5227 bcm_cosq_buffer_id_t buffer, 5228 bcm_cosq_gport_discard_t *discard) 5229 { 5230 int numq, i; 5231 uint32 min_thresh, max_thresh, flags = 0; 5232 int cell_size, cell_field_max; 5233 bcm_port_t local_port = -1; 5234 5235 /* Time Domain */ 5236 /* the reasonable range of refresh_time is from 1 to 64 */ 5237 if (discard == NULL || 5238 discard->gain < 0 || discard->gain > 15 || 5239 discard->drop_probability < 0 || discard->drop_probability > 100 || 5240 discard->profile_id > 3 || 5241 discard->refresh_time <= 0 || discard->refresh_time > 64) { 5242 return BCM_E_PARAM; 5243 } 5244 5245 if (discard == NULL || 5246 discard->gain < 0 || discard->gain > 15 || 5247 discard->drop_probability < 0 || discard->drop_probability > 100 || 5248 (discard->min_thresh > discard->max_thresh) || 5249 (discard->min_thresh < 0)) { 5250 return BCM_E_PARAM; 5251 } 5252 5253 cell_size = _TH_MMU_BYTES_PER_CELL; 5254 cell_field_max = 0xffff; 5255 5256 min_thresh = discard->min_thresh; 5257 max_thresh = discard->max_thresh; 5258 if (discard->flags & BCM_COSQ_DISCARD_BYTES) { 5259 /* Convert bytes to cells */ 5260 min_thresh += (cell_size - 1); 5261 min_thresh /= cell_size; 5262 5263 max_thresh += (cell_size - 1); 5264 max_thresh /= cell_size; 5265 5266 if ((min_thresh > cell_field_max) || 5267 (max_thresh > cell_field_max)) { 5268 return BCM_E_PARAM; 5269 } 5270 } else if (discard->flags & BCM_COSQ_DISCARD_PACKETS) { 5271 /* Packet mode not supported */ 5272 return BCM_E_PARAM; 5273 } else { 5274 /* Lower layer function will update thresh when these flags are 5275 * configured, this interface only allow such opration when 5276 * BCM_COSQ_DISCARD_BYTES is also configured. 5277 */ 5278 if (discard->flags & (BCM_COSQ_DISCARD_COLOR_ALL | 5279 BCM_COSQ_DISCARD_TCP | 5280 BCM_COSQ_DISCARD_NONTCP | 5281 BCM_COSQ_DISCARD_ECT_MARKED | 5282 BCM_COSQ_DISCARD_RESPONSIVE_DROP | 5283 BCM_COSQ_DISCARD_NON_RESPONSIVE_DROP)) { 5284 return BCM_E_PARAM; 5285 } 5286 } 5287 5288 if (gport != BCM_GPORT_INVALID) { 5289 BCM_IF_ERROR_RETURN 5290 (_bcm_th_cosq_localport_resolve(unit, gport, &local_port)); 5291 if (IS_CPU_PORT(unit,local_port) || IS_LB_PORT(unit,local_port)) { 5292 return BCM_E_PORT; 5293 } 5294 if ((cosq < -1) || (cosq >= SOC_PORT_NUM_COSQ(unit, local_port))) { 5295 return BCM_E_PARAM; 5296 } 5297 } 5298 5299 numq = 1; 5300 5301 for (i = 0; i < numq; i++) { 5302 BCM_IF_ERROR_RETURN 5303 (_bcm_th_cosq_wred_set(unit, gport, cosq + i, buffer, 5304 discard->flags, min_thresh, max_thresh, 5305 discard->drop_probability, discard->gain, 5306 FALSE, flags, discard->refresh_time, 5307 discard->profile_id, discard->use_queue_group)); 5308 } 5309 5310 return BCM_E_NONE; 5311 } 5312 5313 /* 5314 * Function: 5315 * bcm_th_cosq_gport_discard_get 5316 * Purpose: 5317 * Get port WRED setting 5318 * Parameters: 5319 * unit - (IN) unit number 5320 * port - (IN) GPORT identifier 5321 * cosq - (IN) COS queue to get, -1 for any queue 5322 * buffer - (IN) XPE ID 5323 * discard - (OUT) discard settings 5324 * Returns: 5325 * BCM_E_XXX 5326 */ 5327 int 5328 bcm_th_cosq_gport_discard_get(int unit, bcm_gport_t gport, 5329 bcm_cos_queue_t cosq, 5330 bcm_cosq_buffer_id_t buffer, 5331 bcm_cosq_gport_discard_t *discard) 5332 { 5333 uint32 min_thresh, max_thresh; 5334 bcm_port_t local_port = -1; 5335 5336 if (discard == NULL) { 5337 return BCM_E_PARAM; 5338 } 5339 5340 if (discard->flags & BCM_COSQ_DISCARD_PACKETS) { 5341 /* Packet mode not supported */ 5342 return BCM_E_PARAM; 5343 } 5344 5345 if (gport != BCM_GPORT_INVALID) { 5346 BCM_IF_ERROR_RETURN 5347 (_bcm_th_cosq_localport_resolve(unit, gport, &local_port)); 5348 if (IS_CPU_PORT(unit,local_port) || IS_LB_PORT(unit,local_port)) { 5349 return BCM_E_PORT; 5350 } 5351 if ((cosq < -1) || (cosq >= SOC_PORT_NUM_COSQ(unit, local_port))) { 5352 return BCM_E_PARAM; 5353 } 5354 } 5355 5356 BCM_IF_ERROR_RETURN 5357 (_bcm_th_cosq_wred_get(unit, gport, cosq == -1 ? 0 : cosq, buffer, 5358 &discard->flags, &min_thresh, &max_thresh, 5359 &discard->drop_probability, &discard->gain, 5360 0, &discard->refresh_time, 5361 &discard->profile_id, &discard->use_queue_group)); 5362 5363 /* Convert number of cells to number of bytes */ 5364 discard->min_thresh = min_thresh * _TH_MMU_BYTES_PER_CELL; 5365 discard->max_thresh = max_thresh * _TH_MMU_BYTES_PER_CELL; 5366 5367 return BCM_E_NONE; 5368 } 5369 5370 int 5371 bcm_th_pfc_deadlock_ignore_pfc_xoff_gen(int unit, int priority, 5372 bcm_port_t port, uint32 *rval32) 5373 { 5374 uint32 profile_index, fc_class; 5375 uint32 rval, uc_cos_bmp; 5376 uint64 rval64[16], *rval64s[1]; 5377 static const soc_reg_t port_fc_reg = PORT_LLFC_CFGr; 5378 5379 rval64s[0] = rval64; 5380 BCM_IF_ERROR_RETURN 5381 (soc_reg32_get(unit, port_fc_reg, port, 0, &rval)); 5382 profile_index = soc_reg_field_get(unit, port_fc_reg, rval, PROFILE_INDEXf) * 16; 5383 5384 BCM_IF_ERROR_RETURN 5385 (soc_profile_reg_get(unit, _bcm_th_prio2cos_profile[unit], 5386 profile_index, 16, rval64s)); 5387 5388 for (fc_class = 0; fc_class < _BCM_TH_NUM_PFC_CLASS; ++fc_class ) { 5389 5390 uc_cos_bmp = soc_reg64_field32_get(unit, PRIO2COS_PROFILEr, rval64[fc_class], 5391 UC_COS_BMPf); 5392 if (uc_cos_bmp & (1 << priority)) { 5393 *rval32 = uc_cos_bmp; 5394 return BCM_E_NONE; 5395 } 5396 } 5397 5398 return BCM_E_NOT_FOUND; 5399 } 5400 5401 STATIC int 5402 _bcm_th_pfc_deadlock_hw_cos_index_get(int unit, bcm_cos_t priority, 5403 int *hw_cos_index) 5404 { 5405 int i, cos_val; 5406 uint32 rval = 0; 5407 _bcm_pfc_deadlock_control_t *pfc_deadlock_control = NULL; 5408 _bcm_pfc_hw_resorces_t *hw_res = NULL; 5409 5410 pfc_deadlock_control = _BCM_UNIT_PFC_DEADLOCK_CONTROL(unit); 5411 hw_res = &pfc_deadlock_control->hw_regs_fields; 5412 5413 SOC_IF_ERROR_RETURN( 5414 soc_reg32_get(unit, hw_res->chip_config[0], REG_PORT_ANY, 0, &rval)); 5415 5416 for (i = 0; i < pfc_deadlock_control->pfc_deadlock_cos_max; i++) { 5417 cos_val = soc_reg_field_get(unit, hw_res->chip_config[0], rval, 5418 hw_res->cos_field[i]); 5419 if ((cos_val == priority) && 5420 (pfc_deadlock_control->hw_cos_idx_inuse[i] == TRUE)) { 5421 *hw_cos_index = i; 5422 return BCM_E_NONE; 5423 } 5424 } 5425 return BCM_E_NOT_FOUND; 5426 } 5427 5428 /* Routine to begin recovery when a Port is deaclared to be in Deadlock by 5429 * Hardware 5430 */ 5431 int 5432 bcm_th_pfc_deadlock_recovery_start(int unit, bcm_port_t port, int priority) 5433 { 5434 soc_info_t *si; 5435 uint32 rval, setval, uc_cos_bmp = 0; 5436 int rv, phy_port, pipe, local_mmu_port, mmu_port, cos = 0; 5437 uint64 rval64, temp_rval64, temp_mask64, temp_en64; 5438 _bcm_pfc_deadlock_control_t *pfc_deadlock_control = NULL; 5439 _bcm_pfc_deadlock_config_t *pfc_deadlock_pri_config = NULL; 5440 _bcm_pfc_hw_resorces_t *hw_res = NULL; 5441 5442 bcm_port_t local_port = -1; 5443 5444 BCM_IF_ERROR_RETURN 5445 (_bcm_th_cosq_localport_resolve(unit, port, &local_port)); 5446 5447 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 5448 5449 si = &SOC_INFO(unit); 5450 phy_port = si->port_l2p_mapping[local_port]; 5451 mmu_port = si->port_p2m_mapping[phy_port]; 5452 local_mmu_port = mmu_port & (SOC_TH_MMU_PORT_STRIDE - 1); 5453 5454 pfc_deadlock_control = _BCM_UNIT_PFC_DEADLOCK_CONTROL(unit); 5455 if (pfc_deadlock_control == NULL) { 5456 return BCM_E_INIT; 5457 } 5458 hw_res = &pfc_deadlock_control->hw_regs_fields; 5459 5460 pfc_deadlock_pri_config = _BCM_PFC_DEADLOCK_CONFIG(unit, priority); 5461 if (pfc_deadlock_pri_config->priority != priority) { 5462 return BCM_E_NOT_FOUND; 5463 } 5464 5465 COMPILER_64_ZERO(temp_en64); 5466 COMPILER_64_ZERO(temp_mask64); 5467 COMPILER_64_ZERO(temp_rval64); 5468 5469 if (local_port >= MAX_PORT(unit)) { 5470 return BCM_E_PARAM; /* Process for valid ports */ 5471 } 5472 if (local_mmu_port < 32) { 5473 COMPILER_64_SET(temp_rval64, 0, (1 << local_mmu_port)); 5474 } else { 5475 COMPILER_64_SET(temp_rval64, (1 << (local_mmu_port - 32)), 0); 5476 } 5477 COMPILER_64_OR(temp_mask64, temp_rval64); 5478 COMPILER_64_OR(temp_en64, temp_rval64); 5479 5480 LOG_INFO(BSL_LS_BCM_COSQ, 5481 (BSL_META_U(unit, 5482 "PFC Deadlock Detected: Cos %d port=%d\n"), 5483 priority, local_port)); 5484 5485 rv = _bcm_th_pfc_deadlock_hw_cos_index_get(unit, priority, &cos); 5486 if (!BCM_SUCCESS(rv)) { 5487 return BCM_E_FAIL; 5488 } 5489 /* 2.a: Mask the Intr DD_TIMER_MASK_A|_B by setting 1 (pbmp) */ 5490 COMPILER_64_ZERO(rval64); 5491 5492 SOC_IF_ERROR_RETURN( 5493 soc_reg_get(unit, hw_res->timer_mask[cos], pipe, 5494 0, &rval64)); 5495 5496 COMPILER_64_OR(rval64, temp_mask64); 5497 SOC_IF_ERROR_RETURN( 5498 soc_reg_set(unit, hw_res->timer_mask[cos], pipe, 5499 0, rval64)); 5500 5501 /* 2.b: Turn timer off DD_TIMER_ENABLE_A|_B by setting 0 (pbmp) */ 5502 COMPILER_64_ZERO(rval64); 5503 5504 SOC_IF_ERROR_RETURN( 5505 soc_reg_get(unit, hw_res->timer_en[cos], pipe, 5506 0, &rval64)); 5507 5508 COMPILER_64_NOT(temp_en64); 5509 COMPILER_64_AND(rval64, temp_en64); 5510 SOC_IF_ERROR_RETURN( 5511 soc_reg_set(unit, hw_res->timer_en[cos], pipe, 5512 0, rval64)); 5513 5514 /* 2.c: For that port, set ignore_pfc_xoff = 1 (per port reg) */ 5515 setval = 0; 5516 SOC_IF_ERROR_RETURN( 5517 soc_reg32_get(unit, hw_res->port_config, local_port, 0, &setval)); 5518 priority = pfc_deadlock_control->pfc_cos2pri[cos]; 5519 5520 rval = bcm_th_pfc_deadlock_ignore_pfc_xoff_gen(unit, priority, 5521 local_port, &uc_cos_bmp); 5522 if(rval != BCM_E_NONE) { 5523 rval = 0; 5524 rval |= (1 << priority); 5525 } else { 5526 rval = 0; 5527 rval |= uc_cos_bmp; 5528 } 5529 setval |= rval; 5530 5531 SOC_IF_ERROR_RETURN( 5532 soc_reg32_set(unit, hw_res->port_config, local_port, 0, setval)); 5533 5534 return BCM_E_NONE; 5535 } 5536 5537 5538 /* Routine to Reset the recovery state of a port and config the port back in 5539 * original state 5540 */ 5541 int 5542 bcm_th_pfc_deadlock_recovery_exit(int unit, bcm_port_t port, int priority) 5543 { 5544 soc_info_t *si; 5545 int rv, phy_port, mmu_port, local_mmu_port, pipe, cos = 0; 5546 _bcm_pfc_deadlock_control_t *pfc_deadlock_control = NULL; 5547 _bcm_pfc_deadlock_config_t *pfc_deadlock_pri_config = NULL; 5548 uint64 rval64, temp_rval64, temp_mask64, temp_en64; 5549 uint32 rval, setval, uc_cos_bmp; 5550 _bcm_pfc_hw_resorces_t *hw_res = NULL; 5551 bcm_port_t local_port = -1; 5552 5553 si = &SOC_INFO(unit); 5554 pfc_deadlock_control = _BCM_UNIT_PFC_DEADLOCK_CONTROL(unit); 5555 if (pfc_deadlock_control == NULL) { 5556 return BCM_E_INIT; 5557 } 5558 hw_res = &pfc_deadlock_control->hw_regs_fields; 5559 5560 pfc_deadlock_pri_config = _BCM_PFC_DEADLOCK_CONFIG(unit, priority); 5561 if (pfc_deadlock_pri_config->priority != priority) { 5562 return BCM_E_NOT_FOUND; 5563 } 5564 5565 BCM_IF_ERROR_RETURN 5566 (_bcm_th_cosq_localport_resolve(unit, port, &local_port)); 5567 5568 if (local_port >= MAX_PORT(unit)) { 5569 return BCM_E_PARAM; /* Process for valid ports */ 5570 } 5571 phy_port = si->port_l2p_mapping[local_port]; 5572 mmu_port = si->port_p2m_mapping[phy_port]; 5573 local_mmu_port = mmu_port & (SOC_TH_MMU_PORT_STRIDE - 1); 5574 5575 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 5576 5577 COMPILER_64_ZERO(temp_en64); 5578 COMPILER_64_ZERO(temp_mask64); 5579 COMPILER_64_ZERO(temp_rval64); 5580 5581 if (local_mmu_port < 32) { 5582 COMPILER_64_SET(temp_rval64, 0, (1 << local_mmu_port)); 5583 } else { 5584 COMPILER_64_SET(temp_rval64, (1 << (local_mmu_port - 32)), 0); 5585 } 5586 COMPILER_64_OR(temp_mask64, temp_rval64); 5587 COMPILER_64_OR(temp_en64, temp_rval64); 5588 5589 rv = _bcm_th_pfc_deadlock_hw_cos_index_get(unit, priority, &cos); 5590 if (!BCM_SUCCESS(rv)) { 5591 return BCM_E_FAIL; 5592 } 5593 LOG_INFO(BSL_LS_BCM_COSQ, 5594 (BSL_META_U(unit, 5595 "PFC Deadlock Recovery ends: Prio %d port=%d\n"), 5596 priority, port)); 5597 5598 5599 /* 3.a: For that port, set ignore_pfc_xoff = 0 (per port reg) */ 5600 setval = 0; 5601 SOC_IF_ERROR_RETURN( 5602 soc_reg32_get(unit, hw_res->port_config, local_port, 0, &setval)); 5603 5604 rval = bcm_th_pfc_deadlock_ignore_pfc_xoff_gen(unit, priority, 5605 local_port, &uc_cos_bmp); 5606 if(rval != BCM_E_NONE) { 5607 setval &= ~(1 << priority); 5608 } else { 5609 setval &= ~uc_cos_bmp; 5610 } 5611 SOC_IF_ERROR_RETURN( 5612 soc_reg32_set(unit, hw_res->port_config, local_port, 0, setval)); 5613 5614 /* 3.b: Mask the Intr DD_TIMER_MASK_A|_B by setting 0 (pbmp) */ 5615 COMPILER_64_ZERO(rval64); 5616 5617 SOC_IF_ERROR_RETURN( 5618 soc_reg_get(unit, hw_res->timer_mask[cos], pipe, 5619 0, &rval64)); 5620 5621 COMPILER_64_NOT(temp_mask64); 5622 COMPILER_64_AND(rval64, temp_mask64); 5623 SOC_IF_ERROR_RETURN( 5624 soc_reg_set(unit, hw_res->timer_mask[cos], pipe, 0, rval64)); 5625 5626 /* 3.c: Turn timer on DD_TIMER_ENABLE_A|_B by setting 1 (pbmp) */ 5627 if (BCM_PBMP_MEMBER(pfc_deadlock_pri_config->enabled_ports, 5628 local_port)) { 5629 COMPILER_64_ZERO(rval64); 5630 5631 SOC_IF_ERROR_RETURN( 5632 soc_reg_get(unit, hw_res->timer_en[cos], pipe, 5633 0, &rval64)); 5634 5635 COMPILER_64_OR(rval64, temp_en64); 5636 SOC_IF_ERROR_RETURN( 5637 soc_reg_set(unit, hw_res->timer_en[cos], pipe, 0, rval64)); 5638 } 5639 5640 return BCM_E_NONE; 5641 } 5642 5643 /* Flow control APIs */ 5644 5645 /* 5646 * Function: 5647 * _bcm_th_cosq_port_fc_get 5648 * Purpose: 5649 * Get the UC|MC gport values associated with 5650 * the given PFC/SAFC class. 5651 * Parameters: 5652 * unit - (IN) unit number 5653 * port - (IN) port number 5654 * fc_class - (IN) PFC/SAFC internal priority class 5655 * gport_list - (OUT) UC|MC gport list 5656 * gport_count - (OUT) gport count 5657 * Returns: 5658 * BCM_E_XXX 5659 */ 5660 STATIC int 5661 _bcm_th_cosq_port_fc_get(int unit, bcm_gport_t local_port, 5662 int fc_class, bcm_gport_t *gport_list, 5663 int *gport_count) 5664 { 5665 int hw_cosq, count = 0; 5666 uint32 profile_index; 5667 uint32 rval, uc_cos_bmp, mc_cos_bmp; 5668 uint64 rval64[16], *rval64s[1]; 5669 static const soc_reg_t port_fc_reg = PORT_LLFC_CFGr; 5670 5671 if ((gport_list == NULL) || (gport_count == NULL)) { 5672 return BCM_E_PARAM; 5673 } 5674 5675 rval64s[0] = rval64; 5676 BCM_IF_ERROR_RETURN 5677 (soc_reg32_get(unit, port_fc_reg, local_port, 0, &rval)); 5678 profile_index = soc_reg_field_get(unit, port_fc_reg, rval, PROFILE_INDEXf) * 16; 5679 5680 BCM_IF_ERROR_RETURN 5681 (soc_profile_reg_get(unit, _bcm_th_prio2cos_profile[unit], 5682 profile_index, 16, rval64s)); 5683 5684 uc_cos_bmp = soc_reg64_field32_get(unit, PRIO2COS_PROFILEr, rval64[fc_class], 5685 UC_COS_BMPf); 5686 mc_cos_bmp = soc_reg64_field32_get(unit, PRIO2COS_PROFILEr, rval64[fc_class], 5687 MC_COS_BMPf); 5688 5689 for (hw_cosq = 0; hw_cosq < _BCM_TH_NUM_UCAST_QUEUE_PER_PORT; hw_cosq++) { 5690 if (!(uc_cos_bmp & (1 << hw_cosq))) { 5691 continue; 5692 } 5693 BCM_IF_ERROR_RETURN 5694 (_bcm_th_cosq_port_cos_resolve(unit, local_port, hw_cosq, 5695 _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE, 5696 &gport_list[count++])); 5697 } 5698 5699 for (hw_cosq = 0; hw_cosq < _BCM_TH_NUM_MCAST_QUEUE_PER_PORT; hw_cosq++) { 5700 if (!(mc_cos_bmp & (1 << hw_cosq))) { 5701 continue; 5702 } 5703 BCM_IF_ERROR_RETURN 5704 (_bcm_th_cosq_port_cos_resolve(unit, local_port, hw_cosq, 5705 _BCM_TH_COSQ_INDEX_STYLE_MCAST_QUEUE, 5706 &gport_list[count++])); 5707 } 5708 5709 if (count == 0) { 5710 return BCM_E_NOT_FOUND; 5711 } 5712 5713 *gport_count = count; 5714 5715 return BCM_E_NONE; 5716 } 5717 5718 /* 5719 * Function: 5720 * _bcm_th_cosq_port_fc_profile_set 5721 * Purpose: 5722 * Set PFC/SAFC Prio 2 Cos Map and set the profile index for the Port 5723 * Parameters: 5724 * unit - (IN) unit number 5725 * port - (IN) GPORT identifier 5726 * fc_class - (IN) Input Class 5727 * uc_cos_bmp - (IN) UC Cos bitmap array 5728 * mc_cos_bmp - (IN) MC Cos bitmap array 5729 * num_class - (IN) Number of input class 5730 * Returns: 5731 * BCM_E_XXX 5732 */ 5733 STATIC int 5734 _bcm_th_cosq_port_fc_profile_set(int unit, bcm_port_t local_port, 5735 int *fc_class, uint32 *uc_cos_bmp, uint32 *mc_cos_bmp, 5736 int num_class) 5737 { 5738 uint32 profile_index, old_profile_index; 5739 uint32 rval; 5740 uint64 rval64[16], *rval64s[1]; 5741 static const soc_reg_t port_fc_reg = PORT_LLFC_CFGr; 5742 int entry, cur_class; 5743 uint32 cur_uc_bmp, cur_mc_bmp; 5744 5745 if ((fc_class == NULL) || 5746 (uc_cos_bmp == NULL) || 5747 (mc_cos_bmp == NULL)) { 5748 return BCM_E_PARAM; 5749 } 5750 5751 rval64s[0] = rval64; 5752 BCM_IF_ERROR_RETURN 5753 (soc_reg32_get(unit, port_fc_reg, local_port, 0, &rval)); 5754 5755 old_profile_index = soc_reg_field_get(unit, port_fc_reg, rval, PROFILE_INDEXf) * 16; 5756 5757 BCM_IF_ERROR_RETURN 5758 (soc_profile_reg_get(unit, _bcm_th_prio2cos_profile[unit], 5759 old_profile_index, 16, rval64s)); 5760 5761 for (entry = 0; entry < num_class; entry++) { 5762 cur_class = fc_class[entry]; 5763 cur_uc_bmp = uc_cos_bmp[entry]; 5764 cur_mc_bmp = mc_cos_bmp[entry]; 5765 soc_reg64_field32_set(unit, PRIO2COS_PROFILEr, &rval64[cur_class], 5766 UC_COS_BMPf, cur_uc_bmp); 5767 soc_reg64_field32_set(unit, PRIO2COS_PROFILEr, &rval64[cur_class], 5768 MC_COS_BMPf, cur_mc_bmp); 5769 5770 } 5771 5772 BCM_IF_ERROR_RETURN 5773 (soc_profile_reg_add(unit, _bcm_th_prio2cos_profile[unit], rval64s, 5774 16, &profile_index)); 5775 5776 soc_reg_field_set(unit, port_fc_reg, &rval, PROFILE_INDEXf, 5777 profile_index / 16); 5778 5779 BCM_IF_ERROR_RETURN 5780 (soc_profile_reg_delete(unit, _bcm_th_prio2cos_profile[unit], 5781 old_profile_index)); 5782 5783 BCM_IF_ERROR_RETURN 5784 (soc_reg32_set(unit, port_fc_reg, local_port, 0, rval)); 5785 5786 return BCM_E_NONE; 5787 } 5788 5789 /* 5790 * Function: 5791 * _bcm_th_fc_status_map_gport 5792 * Purpose: 5793 * Set mapping in PFC/SAFC for gport, and update 5794 * uc_cos_bmp/mc_cos_bmp with gport cosq. 5795 * Parameters: 5796 * unit - (IN) unit number 5797 * port - (IN) port number 5798 * gport - (IN) gport to be mapped 5799 * uc_cos_map - (OUT) unicast hw_cosq of gport 5800 * mc_cos_map - (OUT) multicast hw_cosq of gport 5801 * Returns: 5802 * BCM_E_XXX 5803 */ 5804 STATIC int 5805 _bcm_th_fc_status_map_gport(int unit, bcm_port_t port, 5806 bcm_gport_t gport, uint32 *uc_cos_bmp, uint32 *mc_cos_bmp) 5807 { 5808 _bcm_th_cosq_node_t *node = NULL; 5809 bcm_port_t local_port = -1; 5810 bcm_cos_queue_t cosq = -1; 5811 5812 BCM_IF_ERROR_RETURN 5813 (_bcm_th_cosq_node_get(unit, gport, NULL, &local_port, NULL, 5814 &node)); 5815 5816 if (node == NULL) { 5817 return BCM_E_PARAM; 5818 } 5819 5820 if (local_port < 0) { 5821 return BCM_E_PARAM; 5822 } 5823 5824 if (local_port != port) { 5825 return BCM_E_PARAM; 5826 } 5827 5828 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 5829 cosq = node->hw_index % 5830 _BCM_TH_NUM_UCAST_QUEUE_PER_PORT; 5831 *uc_cos_bmp |= 1 << cosq; 5832 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 5833 cosq = node->hw_index % 5834 _BCM_TH_NUM_MCAST_QUEUE_PER_PORT; 5835 *mc_cos_bmp |= 1 << cosq; 5836 } 5837 5838 return BCM_E_NONE; 5839 } 5840 5841 /* 5842 * Function: 5843 * bcm_th_cosq_port_pfc_op 5844 * Purpose: 5845 * Set PFC Prio 2 Cos Map and set the profile index for the Port 5846 * Parameters: 5847 * unit - (IN) unit number 5848 * port - (IN) GPORT identifier 5849 * sctype - (IN) Input Class 5850 * op - (IN) Operation to be performed (ADD|SET|CLEAR) 5851 * gport - (IN) Gport/Cos array 5852 * gport_ct - (IN) Count of values in the array 5853 * Returns: 5854 * BCM_E_XXX 5855 */ 5856 int 5857 bcm_th_cosq_port_pfc_op(int unit, bcm_port_t port, 5858 bcm_switch_control_t sctype, _bcm_cosq_op_t op, 5859 bcm_gport_t *gport, int gport_count) 5860 { 5861 bcm_port_t local_port; 5862 int type = -1, class = -1, index, hw_cosq, hw_cosq1; 5863 uint32 profile_index, old_profile_index; 5864 uint32 rval, fval, cos_bmp; 5865 uint64 rval64[16], *rval64s[1]; 5866 _bcm_th_cosq_node_t *node; 5867 static const soc_reg_t port_fc_reg = PORT_LLFC_CFGr; 5868 soc_field_t field = INVALIDf; 5869 soc_info_t *si = &SOC_INFO(unit); 5870 int rv = SOC_E_NONE; 5871 5872 if (gport_count < 0) { 5873 return BCM_E_PARAM; 5874 } 5875 5876 BCM_IF_ERROR_RETURN 5877 (_bcm_th_cosq_localport_resolve(unit, port, &local_port)); 5878 5879 BCM_IF_ERROR_RETURN(_bcm_th_cosq_pfc_class_resolve(sctype, &type, &class)); 5880 5881 cos_bmp = 0; 5882 5883 if (type == _BCM_TH_COSQ_TYPE_MCAST) { 5884 field = MC_COS_BMPf; 5885 } else { 5886 field = UC_COS_BMPf; 5887 } 5888 5889 for (index = 0; index < gport_count; index++) { 5890 hw_cosq = hw_cosq1 = -1; 5891 if (BCM_GPORT_IS_SET(gport[index]) && 5892 ((BCM_GPORT_IS_SCHEDULER(gport[index])) || 5893 BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport[index]) || 5894 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport[index]))) { 5895 BCM_IF_ERROR_RETURN 5896 (_bcm_th_cosq_node_get(unit, gport[index], NULL, 5897 NULL, NULL, &node)); 5898 if (BCM_GPORT_IS_SCHEDULER(gport[index])) { 5899 hw_cosq = node->hw_index % _BCM_TH_NUM_SCHEDULER_PER_PORT; 5900 } else if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport[index])) { 5901 if (type != _BCM_TH_COSQ_TYPE_UCAST) { 5902 return BCM_E_PARAM; 5903 } 5904 hw_cosq = node->hw_index % si->port_num_cosq[local_port]; 5905 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport[index])) { 5906 if (type != _BCM_TH_COSQ_TYPE_MCAST) { 5907 return BCM_E_PARAM; 5908 } 5909 hw_cosq = node->hw_index % si->port_num_cosq[local_port]; 5910 } 5911 } else { 5912 /* Find hardware index for given local_port, cosq */ 5913 hw_cosq = gport[index] % 10; 5914 } 5915 cos_bmp |= 1 << hw_cosq; 5916 } 5917 5918 rval64s[0] = rval64; 5919 BCM_IF_ERROR_RETURN(soc_reg32_get(unit, port_fc_reg, local_port, 0, &rval)); 5920 5921 if (op == _BCM_COSQ_OP_CLEAR || cos_bmp != 0) { 5922 old_profile_index = soc_reg_field_get(unit, port_fc_reg, rval, PROFILE_INDEXf) * 16; 5923 5924 BCM_IF_ERROR_RETURN 5925 (soc_profile_reg_get(unit, _bcm_th_prio2cos_profile[unit], 5926 old_profile_index, 16, rval64s)); 5927 if (op == _BCM_COSQ_OP_SET) { 5928 soc_reg64_field32_set(unit, PRIO2COS_PROFILEr, &rval64[class], 5929 field, cos_bmp); 5930 } else if (op == _BCM_COSQ_OP_CLEAR || cos_bmp != 0) { 5931 fval = soc_reg64_field32_get(unit, PRIO2COS_PROFILEr, rval64[class], 5932 field); 5933 if (op == _BCM_COSQ_OP_ADD) { 5934 fval |= cos_bmp; 5935 } else { /* _BCM_COSQ_OP_DELETE */ 5936 fval = 0; 5937 } 5938 soc_reg64_field32_set(unit, PRIO2COS_PROFILEr, &rval64[class], 5939 field, fval); 5940 } 5941 BCM_IF_ERROR_RETURN 5942 (soc_profile_reg_delete(unit, _bcm_th_prio2cos_profile[unit], 5943 old_profile_index)); 5944 rv = soc_profile_reg_add(unit, _bcm_th_prio2cos_profile[unit], rval64s, 5945 16, &profile_index); 5946 if (rv != BCM_E_NONE) { 5947 SOC_IF_ERROR_RETURN 5948 (soc_profile_reg_reference(unit, _bcm_th_prio2cos_profile[unit], 5949 old_profile_index, 16)); 5950 return rv; 5951 } 5952 soc_reg_field_set(unit, port_fc_reg, &rval, PROFILE_INDEXf, 5953 profile_index / 16); 5954 } 5955 BCM_IF_ERROR_RETURN(soc_reg32_set(unit, port_fc_reg, local_port, 0, rval)); 5956 5957 return BCM_E_NONE; 5958 } 5959 5960 /* 5961 * Function: 5962 * bcm_th_cosq_port_pfc_get 5963 * Purpose: 5964 * Get PFC Prio2Cos Map for a given Traffic Class 5965 * Parameters: 5966 * unit - (IN) unit number 5967 * port - (IN) GPORT identifier 5968 * sctype - (IN) Input Traffic Class 5969 * gport - (OUT) Gport/Cos array 5970 * gport_ct - (IN) Input Count of gport required 5971 * actual_gport_ct - (OUT) Actual Count of gport/cos in the array 5972 * Returns: 5973 * BCM_E_XXX 5974 */ 5975 int 5976 bcm_th_cosq_port_pfc_get(int unit, bcm_port_t port, 5977 bcm_switch_control_t sctype, 5978 bcm_gport_t *gport, int gport_count, 5979 int *actual_gport_count) 5980 { 5981 bcm_port_t local_port; 5982 int type = 0, class = -1, hw_cosq, count = 0; 5983 uint32 profile_index; 5984 uint32 rval, cos_bmp; 5985 uint64 rval64[16], *rval64s[1]; 5986 static const soc_reg_t port_fc_reg = PORT_LLFC_CFGr; 5987 soc_field_t field = INVALIDf; 5988 5989 if (gport == NULL || gport_count <= 0 || actual_gport_count == NULL) { 5990 return BCM_E_PARAM; 5991 } 5992 5993 BCM_IF_ERROR_RETURN 5994 (_bcm_th_cosq_localport_resolve(unit, port, &local_port)); 5995 5996 BCM_IF_ERROR_RETURN(_bcm_th_cosq_pfc_class_resolve(sctype, &type, &class)); 5997 5998 rval64s[0] = rval64; 5999 BCM_IF_ERROR_RETURN(soc_reg32_get(unit, port_fc_reg, local_port, 0, &rval)); 6000 profile_index = soc_reg_field_get(unit, port_fc_reg, rval, PROFILE_INDEXf) * 16; 6001 6002 if (type == _BCM_TH_COSQ_TYPE_MCAST) { 6003 field = MC_COS_BMPf; 6004 } else { 6005 field = UC_COS_BMPf; 6006 } 6007 6008 BCM_IF_ERROR_RETURN 6009 (soc_profile_reg_get(unit, _bcm_th_prio2cos_profile[unit], 6010 profile_index, 16, rval64s)); 6011 6012 cos_bmp = soc_reg64_field32_get(unit, PRIO2COS_PROFILEr, rval64[class], 6013 field); 6014 for (hw_cosq = 0; hw_cosq < 10; hw_cosq++) { 6015 if (!(cos_bmp & (1 << hw_cosq))) { 6016 continue; 6017 } 6018 gport[count++] = hw_cosq; 6019 6020 if (count == gport_count) { 6021 break; 6022 } 6023 } 6024 if (count == 0) { 6025 return BCM_E_NOT_FOUND; 6026 } 6027 *actual_gport_count = count; 6028 6029 return BCM_E_NONE; 6030 } 6031 6032 /* 6033 * Function: 6034 * bcm_th_cosq_pfc_class_mapping_set 6035 * Purpose: 6036 * Set PFC mapping for port. 6037 * PFC class is mapped to cosq or scheduler node gports. 6038 * Parameters: 6039 * unit - (IN) unit number 6040 * port - (IN) port number 6041 * array_count - (IN) count of mapping 6042 * mapping_array - (IN) mappings 6043 * Returns: 6044 * BCM_E_XXX 6045 */ 6046 int 6047 bcm_th_cosq_pfc_class_mapping_set(int unit, bcm_gport_t port, 6048 int array_count, 6049 bcm_cosq_pfc_class_mapping_t *mapping_array) 6050 { 6051 int index, count; 6052 int cur_class = 0; 6053 int pfc_class[_BCM_TH_NUM_PFC_CLASS]; 6054 bcm_gport_t cur_gport = 0; 6055 uint32 uc_cos_bmp[_BCM_TH_NUM_PFC_CLASS] = {0}; 6056 uint32 mc_cos_bmp[_BCM_TH_NUM_PFC_CLASS] = {0}; 6057 bcm_port_t local_port = -1; 6058 6059 BCM_IF_ERROR_RETURN 6060 (_bcm_th_cosq_localport_resolve(unit, port, &local_port)); 6061 6062 if (local_port < 0) { 6063 return BCM_E_PORT; 6064 } 6065 6066 if (IS_CPU_PORT(unit, local_port)) { 6067 return BCM_E_PORT; 6068 } 6069 6070 if ((array_count < 0) || (array_count > _BCM_TH_NUM_PFC_CLASS)) { 6071 return BCM_E_PARAM; 6072 } 6073 6074 if (mapping_array == NULL) { 6075 return BCM_E_PARAM; 6076 } 6077 6078 for (count = 0; count < array_count; count++) { 6079 cur_class = mapping_array[count].class_id; 6080 if ((cur_class < 0) || (cur_class >= _BCM_TH_NUM_PFC_CLASS)) { 6081 return BCM_E_PARAM; 6082 } else { 6083 uc_cos_bmp[cur_class] = 0; 6084 mc_cos_bmp[cur_class] = 0; 6085 } 6086 6087 for (index = 0; index < BCM_COSQ_PFC_GPORT_COUNT; index++) { 6088 cur_gport = mapping_array[count].gport_list[index]; 6089 if (cur_gport == BCM_GPORT_INVALID) { 6090 break; 6091 } 6092 6093 if ((BCM_GPORT_IS_UCAST_QUEUE_GROUP(cur_gport)) || 6094 (BCM_GPORT_IS_MCAST_QUEUE_GROUP(cur_gport))) { 6095 BCM_IF_ERROR_RETURN 6096 (_bcm_th_fc_status_map_gport(unit, local_port, cur_gport, 6097 &uc_cos_bmp[cur_class], 6098 &mc_cos_bmp[cur_class])); 6099 } else { 6100 return BCM_E_PARAM; 6101 } 6102 } 6103 } 6104 6105 for (index = 0; index < _BCM_TH_NUM_PFC_CLASS; index++) { 6106 pfc_class[index] = index; 6107 } 6108 BCM_IF_ERROR_RETURN 6109 (_bcm_th_cosq_port_fc_profile_set(unit, local_port, pfc_class, 6110 uc_cos_bmp, mc_cos_bmp, 6111 _BCM_TH_NUM_PFC_CLASS)); 6112 6113 return BCM_E_NONE; 6114 } 6115 6116 /* 6117 * Function: 6118 * bcm_th_cosq_pfc_class_mapping_get 6119 * Purpose: 6120 * Get PFC mapping for port. 6121 * Retrieves cosq or scheduler node gports 6122 * associated to PFC classes. 6123 * Parameters: 6124 * unit - (IN) unit number 6125 * port - (IN) port number 6126 * array_max - (IN) max retrieve count 6127 * mapping_array - (OUT) mappings 6128 * array_count - (OUT) retrieved mapping count 6129 * Returns: 6130 * BCM_E_XXX 6131 */ 6132 int 6133 bcm_th_cosq_pfc_class_mapping_get(int unit, bcm_gport_t port, 6134 int array_max, 6135 bcm_cosq_pfc_class_mapping_t *mapping_array, 6136 int *array_count) 6137 { 6138 int rv = 0; 6139 int cur_class = 0; 6140 int actual_gport_count, class_count = 0; 6141 bcm_port_t local_port = -1; 6142 6143 BCM_IF_ERROR_RETURN 6144 (_bcm_th_cosq_localport_resolve(unit, port, &local_port)); 6145 6146 if (local_port < 0) { 6147 return BCM_E_PORT; 6148 } 6149 6150 if (IS_CPU_PORT(unit, local_port)) { 6151 return BCM_E_PORT; 6152 } 6153 6154 if (((mapping_array == NULL) && (array_max > 0)) || 6155 ((mapping_array != NULL) && (array_max <= 0)) || 6156 (array_count == NULL)) { 6157 return BCM_E_PARAM; 6158 } 6159 6160 if (array_max <= 0) { 6161 *array_count = _BCM_TH_NUM_PFC_CLASS; 6162 return BCM_E_NONE; 6163 } 6164 6165 for (cur_class = 0; cur_class < _BCM_TH_NUM_PFC_CLASS; cur_class++) { 6166 actual_gport_count = 0; 6167 rv = _bcm_th_cosq_port_fc_get(unit, local_port, cur_class, 6168 mapping_array[class_count].gport_list, 6169 &actual_gport_count); 6170 6171 if (rv == BCM_E_NONE) { 6172 mapping_array[class_count].class_id = cur_class; 6173 if (actual_gport_count < BCM_COSQ_PFC_GPORT_COUNT) { 6174 mapping_array[class_count].gport_list[actual_gport_count] = 6175 BCM_GPORT_INVALID; 6176 } 6177 class_count++; 6178 } else if (rv != BCM_E_NOT_FOUND) { 6179 return rv; 6180 } 6181 6182 if (class_count == array_max) { 6183 break; 6184 } 6185 } 6186 6187 *array_count = class_count; 6188 if (class_count == 0) { 6189 return BCM_E_NOT_FOUND; 6190 } 6191 6192 return BCM_E_NONE; 6193 } 6194 6195 6196 /* 6197 * Function: 6198 * bcm_th_port_priority_group_mapping_set 6199 * Purpose: 6200 * Assign a Priority Group for the input priority. 6201 * Parameters: 6202 * unit - (IN) device id. 6203 * gport - (IN) generic port. 6204 * prio - (IN) input priority. 6205 * priority_group - (IN) PG ID that the input priority mapped to. 6206 * Returns: 6207 * BCM_E_XXX 6208 */ 6209 int 6210 bcm_th_port_priority_group_mapping_set(int unit, bcm_gport_t gport, 6211 int prio, int priority_group) 6212 { 6213 bcm_port_t port; 6214 uint32 value; 6215 int field_count; 6216 soc_field_t fields_0[]={PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf, 6217 PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf}; 6218 soc_field_t fields_1[]={PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf, 6219 PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf}; 6220 6221 if (!soc_feature(unit, soc_feature_priority_flow_control)) { 6222 return BCM_E_UNAVAIL; 6223 } 6224 /* PFC : 0-7, SAFC : 0-15. Taking the larger range for comparison */ 6225 if ((prio < TH_SAFC_INPUT_PRIORITY_MIN) || 6226 (prio > TH_SAFC_INPUT_PRIORITY_MAX)) { 6227 return BCM_E_PARAM; 6228 } 6229 6230 if ((priority_group < TH_PRIOROTY_GROUP_ID_MIN) || 6231 (priority_group > TH_PRIOROTY_GROUP_ID_MAX)) { 6232 return BCM_E_PARAM; 6233 } 6234 6235 BCM_IF_ERROR_RETURN(_bcm_th_cosq_localport_resolve(unit, gport, &port)); 6236 if (!SOC_PORT_VALID(unit, port)) { 6237 return BCM_E_PORT; 6238 } 6239 field_count = COUNTOF(fields_0); 6240 if (prio < field_count) { 6241 /* input priority 0~7 */ 6242 BCM_IF_ERROR_RETURN(READ_THDI_PORT_PRI_GRP0r(unit, port, &value)); 6243 soc_reg_field_set(unit, THDI_PORT_PRI_GRP0r, &value, 6244 fields_0[prio], priority_group); 6245 BCM_IF_ERROR_RETURN(WRITE_THDI_PORT_PRI_GRP0r(unit, port, value)); 6246 } else { 6247 /* input priority 8~15 */ 6248 BCM_IF_ERROR_RETURN(READ_THDI_PORT_PRI_GRP1r(unit, port, &value)); 6249 soc_reg_field_set(unit, THDI_PORT_PRI_GRP1r, &value, 6250 fields_1[prio - field_count], priority_group); 6251 BCM_IF_ERROR_RETURN(WRITE_THDI_PORT_PRI_GRP1r(unit, port, value)); 6252 } 6253 6254 return BCM_E_NONE; 6255 } 6256 6257 /* 6258 * Function: 6259 * bcm_th_port_priority_group_mapping_get 6260 * Purpose: 6261 * Get the assigned Priority Group ID of the input priority. 6262 * Parameters: 6263 * unit - (IN) device id. 6264 * gport - (IN) generic port. 6265 * prio - (IN) input priority. 6266 * priority_group - (OUT) PG ID that the input priority mapped to. 6267 * Returns: 6268 * BCM_E_XXX 6269 */ 6270 int 6271 bcm_th_port_priority_group_mapping_get(int unit, bcm_gport_t gport, 6272 int prio, int *priority_group) 6273 { 6274 bcm_port_t port; 6275 uint32 value; 6276 int field_count; 6277 soc_field_t fields_0[]={PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf, 6278 PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf}; 6279 soc_field_t fields_1[]={PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf, 6280 PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf}; 6281 6282 if (!soc_feature(unit, soc_feature_priority_flow_control)) { 6283 return BCM_E_UNAVAIL; 6284 } 6285 if (priority_group == NULL) { 6286 return BCM_E_PARAM; 6287 } 6288 /* PFC : 0-7, SAFC : 0-15. Taking the larger range for comparison */ 6289 if ((prio < TH_SAFC_INPUT_PRIORITY_MIN) || 6290 (prio > TH_SAFC_INPUT_PRIORITY_MAX)) { 6291 return BCM_E_PARAM; 6292 } 6293 6294 BCM_IF_ERROR_RETURN(_bcm_th_cosq_localport_resolve(unit, gport, &port)); 6295 if (!SOC_PORT_VALID(unit, port)) { 6296 return BCM_E_PORT; 6297 } 6298 field_count = COUNTOF(fields_0); 6299 if (prio < field_count) { 6300 /* input priority 0~7 */ 6301 BCM_IF_ERROR_RETURN(READ_THDI_PORT_PRI_GRP0r(unit, port, &value)); 6302 *priority_group = soc_reg_field_get(unit, THDI_PORT_PRI_GRP0r, 6303 value, fields_0[prio]); 6304 } else { 6305 /* input priority 8~15 */ 6306 BCM_IF_ERROR_RETURN(READ_THDI_PORT_PRI_GRP1r(unit, port, &value)); 6307 *priority_group = soc_reg_field_get(unit, THDI_PORT_PRI_GRP1r, 6308 value, 6309 fields_1[prio - field_count]); 6310 } 6311 6312 return BCM_E_NONE; 6313 } 6314 6315 /* 6316 * Function: 6317 * bcm_th_port_priority_group_config_set 6318 * Purpose: 6319 * Set the port priority group configuration. 6320 * Parameters: 6321 * unit - (IN) device id. 6322 * gport - (IN) generic port. 6323 * priority_group - (IN) priority group id. 6324 * prigrp_config - (IN) structure describes port PG configuration. 6325 * Returns: 6326 * BCM_E_XXX 6327 */ 6328 int 6329 bcm_th_port_priority_group_config_set(int unit, bcm_gport_t gport, 6330 int priority_group, bcm_port_priority_group_config_t *prigrp_config) 6331 { 6332 bcm_port_t port; 6333 uint32 rval, pri_bmp; 6334 6335 if (!soc_feature(unit, soc_feature_priority_flow_control)) { 6336 return BCM_E_UNAVAIL; 6337 } 6338 if ((priority_group < TH_PRIOROTY_GROUP_ID_MIN) || 6339 (priority_group > TH_PRIOROTY_GROUP_ID_MAX)) { 6340 return BCM_E_PARAM; 6341 } 6342 if (prigrp_config == NULL) { 6343 return BCM_E_PARAM; 6344 } 6345 if (prigrp_config->shared_pool_xoff_enable || 6346 prigrp_config->shared_pool_discard_enable || 6347 prigrp_config->priority_enable_vector_mask) { 6348 return BCM_E_UNAVAIL; 6349 } 6350 BCM_IF_ERROR_RETURN(_bcm_th_cosq_localport_resolve(unit, gport, &port)); 6351 if (!SOC_PORT_VALID(unit, port)) { 6352 return BCM_E_PORT; 6353 } 6354 6355 SOC_IF_ERROR_RETURN(READ_THDI_INPUT_PORT_XON_ENABLESr(unit, port, &rval)); 6356 pri_bmp = soc_reg_field_get(unit, THDI_INPUT_PORT_XON_ENABLESr, rval, 6357 PORT_PRI_XON_ENABLEf); 6358 6359 if (prigrp_config->pfc_transmit_enable) { 6360 pri_bmp |= (1 << priority_group); 6361 } else { 6362 pri_bmp &= ~(1 << priority_group); 6363 } 6364 /* To cover higher 8 PFC classes that have no corresponding PG. */ 6365 if ((pri_bmp & 0xff) == 0) { 6366 pri_bmp = 0; 6367 } 6368 6369 soc_reg_field_set(unit, THDI_INPUT_PORT_XON_ENABLESr, &rval, 6370 PORT_PRI_XON_ENABLEf, pri_bmp); 6371 BCM_IF_ERROR_RETURN(WRITE_THDI_INPUT_PORT_XON_ENABLESr(unit, port, rval)); 6372 6373 return BCM_E_NONE; 6374 } 6375 6376 /* 6377 * Function: 6378 * bcm_th_port_priority_group_config_get 6379 * Purpose: 6380 * Get the port priority group configuration. 6381 * Parameters: 6382 * unit - (IN) device id. 6383 * gport - (IN) generic port. 6384 * priority_group - (IN) priority group id. 6385 * prigrp_config - (OUT) structure describes port PG configuration. 6386 * Returns: 6387 * BCM_E_XXX 6388 */ 6389 int 6390 bcm_th_port_priority_group_config_get(int unit, bcm_gport_t gport, 6391 int priority_group, bcm_port_priority_group_config_t *prigrp_config) 6392 { 6393 bcm_port_t port; 6394 uint32 rval, pri_bmp; 6395 6396 if (!soc_feature(unit, soc_feature_priority_flow_control)) { 6397 return BCM_E_UNAVAIL; 6398 } 6399 if ((priority_group < TH_PRIOROTY_GROUP_ID_MIN) || 6400 (priority_group > TH_PRIOROTY_GROUP_ID_MAX)) { 6401 return BCM_E_PARAM; 6402 } 6403 if (prigrp_config == NULL) { 6404 return BCM_E_PARAM; 6405 } 6406 6407 BCM_IF_ERROR_RETURN(_bcm_th_cosq_localport_resolve(unit, gport, &port)); 6408 if (!SOC_PORT_VALID(unit, port)) { 6409 return BCM_E_PORT; 6410 } 6411 6412 SOC_IF_ERROR_RETURN(READ_THDI_INPUT_PORT_XON_ENABLESr(unit, port, &rval)); 6413 pri_bmp = soc_reg_field_get(unit, THDI_INPUT_PORT_XON_ENABLESr, rval, 6414 PORT_PRI_XON_ENABLEf); 6415 if (pri_bmp & (1U << priority_group)) { 6416 prigrp_config->pfc_transmit_enable = 1; 6417 } else { 6418 prigrp_config->pfc_transmit_enable = 0; 6419 } 6420 6421 return BCM_E_NONE; 6422 } 6423 6424 /* 6425 * Function: 6426 * bcm_th_cosq_gport_add 6427 * Purpose: 6428 * Create a cosq gport structure 6429 * Parameters: 6430 * unit - (IN) unit number 6431 * port - (IN) port number 6432 * numq - (IN) number of COS queues 6433 * flags - (IN) flags (BCM_COSQ_GPORT_XXX) 6434 * gport - (OUT) GPORT identifier 6435 * Returns: 6436 * BCM_E_XXX 6437 */ 6438 int 6439 bcm_th_cosq_gport_add(int unit, bcm_gport_t port, int numq, uint32 flags, 6440 bcm_gport_t *gport) 6441 { 6442 _bcm_th_cosq_port_info_t *port_info = NULL; 6443 _bcm_th_cosq_cpu_port_info_t *cpu_port_info = NULL; 6444 _bcm_th_cosq_node_t *node; 6445 uint32 sched_encap; 6446 bcm_port_t local_port; 6447 int id; 6448 6449 LOG_INFO(BSL_LS_BCM_COSQ, 6450 (BSL_META_U(unit, 6451 "bcm_th_cosq_gport_add: unit=%d port=0x%x " 6452 "numq=%d flags=0x%x\n"), 6453 unit, port, numq, flags)); 6454 6455 if (gport == NULL) { 6456 return BCM_E_PARAM; 6457 } 6458 6459 if (_bcm_th_cosq_port_info[unit] == NULL) { 6460 return BCM_E_INIT; 6461 } 6462 6463 if (_bcm_th_cosq_cpu_port_info[unit] == NULL) { 6464 return BCM_E_INIT; 6465 } 6466 6467 BCM_IF_ERROR_RETURN 6468 (_bcm_th_cosq_localport_resolve(unit, port, &local_port)); 6469 6470 if (local_port < 0 || IS_LB_PORT(unit, local_port)) { 6471 return BCM_E_PORT; 6472 } 6473 6474 if (IS_CPU_PORT(unit, local_port)) { 6475 cpu_port_info = &_bcm_th_cosq_cpu_port_info[unit][local_port]; 6476 } else { 6477 port_info = &_bcm_th_cosq_port_info[unit][local_port]; 6478 } 6479 switch (flags) { 6480 case BCM_COSQ_GPORT_UCAST_QUEUE_GROUP: 6481 if (IS_CPU_PORT(unit, local_port)) { 6482 return BCM_E_PARAM; 6483 } 6484 if (numq != 1) { 6485 return BCM_E_PARAM; 6486 } 6487 for (id = 0; id < _BCM_TH_NUM_UCAST_QUEUE_PER_PORT; id++) { 6488 if ((port_info->ucast[id].numq == 0) || 6489 (port_info->ucast[id].in_use == 0)) { 6490 break; 6491 } 6492 } 6493 if (id == _BCM_TH_NUM_UCAST_QUEUE_PER_PORT) { 6494 return BCM_E_RESOURCE; 6495 } 6496 BCM_GPORT_UCAST_QUEUE_GROUP_SYSQID_SET(*gport, local_port, id); 6497 node = &port_info->ucast[id]; 6498 node->level = SOC_TH_NODE_LVL_L1; 6499 break; 6500 case BCM_COSQ_GPORT_MCAST_QUEUE_GROUP: 6501 if (numq != 1) { 6502 return BCM_E_PARAM; 6503 } 6504 if (IS_CPU_PORT(unit, local_port)) { 6505 for (id = 0; id < _BCM_TH_NUM_CPU_MCAST_QUEUE; id++) { 6506 if ((cpu_port_info->mcast[id].numq == 0) || 6507 (cpu_port_info->mcast[id].in_use == 0)) { 6508 break; 6509 } 6510 } 6511 if (id == _BCM_TH_NUM_CPU_MCAST_QUEUE) { 6512 return BCM_E_RESOURCE; 6513 } 6514 } else { 6515 for (id = 0; id < _BCM_TH_NUM_MCAST_QUEUE_PER_PORT; id++) { 6516 if ((port_info->mcast[id].numq == 0) || 6517 (port_info->mcast[id].in_use == 0)) { 6518 break; 6519 } 6520 } 6521 if (id == _BCM_TH_NUM_MCAST_QUEUE_PER_PORT) { 6522 return BCM_E_RESOURCE; 6523 } 6524 } 6525 BCM_GPORT_MCAST_QUEUE_GROUP_SYSQID_SET(*gport, local_port, id); 6526 if (IS_CPU_PORT(unit, local_port)) { 6527 node = &cpu_port_info->mcast[id]; 6528 } else { 6529 node = &port_info->mcast[id]; 6530 } 6531 node->level = SOC_TH_NODE_LVL_L1; 6532 break; 6533 case BCM_COSQ_GPORT_SCHEDULER: 6534 case 0: 6535 if (numq <= 0) { 6536 return BCM_E_PARAM; 6537 } 6538 for (id = 0; id < _BCM_TH_NUM_SCHEDULER_PER_PORT; id++) { 6539 if (IS_CPU_PORT(unit, local_port)) { 6540 if (cpu_port_info->sched[id].numq == 0) { 6541 break; 6542 } 6543 } else { 6544 if (port_info->sched[id].numq == 0) { 6545 break; 6546 } 6547 } 6548 } 6549 if (id == _BCM_TH_NUM_SCHEDULER_PER_PORT) { 6550 return BCM_E_RESOURCE; 6551 } 6552 6553 sched_encap = (id << 16) | local_port; 6554 BCM_GPORT_SCHEDULER_SET(*gport, sched_encap); 6555 if (IS_CPU_PORT(unit, local_port)) { 6556 node = &cpu_port_info->sched[id]; 6557 } else { 6558 node = &port_info->sched[id]; 6559 } 6560 node->level = SOC_TH_NODE_LVL_L0; 6561 break; 6562 default: 6563 return BCM_E_UNAVAIL; 6564 } 6565 6566 node->gport = *gport; 6567 node->numq = numq; 6568 node->in_use = 1; 6569 6570 LOG_INFO(BSL_LS_BCM_COSQ, 6571 (BSL_META_U(unit, 6572 " gport=0x%x\n"), 6573 *gport)); 6574 6575 return BCM_E_NONE; 6576 } 6577 6578 STATIC int 6579 _bcm_th_cosq_rx_queue_channel_set(int unit, 6580 bcm_cos_queue_t parent_cos, 6581 bcm_cos_queue_t queue_id, 6582 int enable) 6583 { 6584 #if defined(BCM_CMICM_SUPPORT) || defined(BCM_CMICX_SUPPORT) 6585 6586 if(soc_feature(unit, soc_feature_cmicm) || 6587 soc_feature(unit, soc_feature_cmicx)) { 6588 int pci_cmc = SOC_PCI_CMC(unit); 6589 int chan_id = -1; 6590 int start_chan_id = 0; 6591 uint32 chan_off; 6592 uint32 reg_addr, reg_val; 6593 uint32 ix; 6594 6595 if (parent_cos == 0) { 6596 chan_id = 1; 6597 } else if (parent_cos == 1) { 6598 chan_id = 2; 6599 } else if (parent_cos == 2) { 6600 chan_id = 3; 6601 } else if (parent_cos == 3) { 6602 chan_id = 0; 6603 } else { 6604 return BCM_E_PARAM; 6605 } 6606 6607 if (!SHR_BITGET(CPU_ARM_QUEUE_BITMAP(unit, pci_cmc), queue_id)) { 6608 return BCM_E_PARAM; 6609 } 6610 6611 for (ix = start_chan_id; ix < (start_chan_id + BCM_RX_CHANNELS); ix++) { 6612 chan_off = ix % BCM_RX_CHANNELS; 6613 soc_dma_cos_ctrl_reg_addr_get(unit, pci_cmc, chan_off, 6614 queue_id, ®_addr); 6615 reg_val = soc_pci_read(unit, reg_addr); 6616 6617 if (enable == 1) { 6618 if (ix == (uint32)chan_id) { 6619 reg_val |= ((uint32)1 << (queue_id % 32)); 6620 } else { 6621 /* Clear all other channels */ 6622 reg_val &= ~((uint32)1 << (queue_id % 32)); 6623 } 6624 } else { 6625 if (ix == (uint32)chan_id) { 6626 reg_val &= ~((uint32)1 << (queue_id % 32)); 6627 } 6628 } 6629 /* Incoporate the reserved queues (if any on this device) 6630 * into the CMIC programming, */ 6631 reg_val |= 6632 CPU_ARM_RSVD_QUEUE_BITMAP(unit, pci_cmc)[queue_id / 32]; 6633 soc_pci_write(unit, reg_addr, reg_val); 6634 } 6635 } 6636 #endif 6637 return BCM_E_NONE; 6638 } 6639 6640 /* 6641 * This function does two things: 6642 * 1. Tests whether the corresponding COS_BMP bit is set or not. 6643 * 2. Tests whether the queue corresponding to given cos is 6644 * mapped to correct L0 or not. 6645 * 6646 * L0.0 is associated with CMC0 CH1(Rx) (pci) 6647 * L0.1 is associated with CMC0 CH2(Rx) (pci) 6648 * L0.2 is associated with CMC0 CH3(Rx) (pci) 6649 * L0.3 is associated with CMC0 CH0(Rx) (pci) 6650 * L0.7 is associated with CMC1 CH1(Rx) (uC0) 6651 * L0.8 is associated with CMC2 CH1(Rx) (uC1) 6652 * L0.9 is reserved 6653 */ 6654 int 6655 bcm_th_rx_queue_channel_set_test(int unit, 6656 bcm_cos_queue_t queue_id, 6657 bcm_rx_chan_t chan_id) 6658 { 6659 #if defined(BCM_CMICM_SUPPORT) || defined(BCM_CMICX_SUPPORT) 6660 if(soc_feature(unit, soc_feature_cmicm) || 6661 soc_feature(unit, soc_feature_cmicx)) { 6662 int pci_cmc = SOC_PCI_CMC(unit); 6663 uint32 reg_val; 6664 uint32 bit; 6665 _bcm_th_cosq_cpu_port_info_t *cpu_port_info = NULL; 6666 bcm_gport_t cpu_l0_gport = -1; 6667 bcm_gport_t parent_gport = -1; 6668 6669 if ((chan_id < 0) || (chan_id >= BCM_RX_CHANNELS)) { 6670 /* Return error for non- pci_cmc channels */ 6671 return BCM_E_PARAM; 6672 } 6673 6674 if (_bcm_th_cosq_cpu_port_info[unit] == NULL) { 6675 return BCM_E_INIT; 6676 } 6677 6678 cpu_port_info = _bcm_th_cosq_cpu_port_info[unit]; 6679 6680 if (chan_id == 0) { 6681 /* l0.3 gport */ 6682 cpu_l0_gport = cpu_port_info->sched[3].gport; 6683 } else if (chan_id == 1) { 6684 /* l0.0 gport */ 6685 cpu_l0_gport = cpu_port_info->sched[0].gport; 6686 } else if (chan_id == 2) { 6687 /* l0.1 gport */ 6688 cpu_l0_gport = cpu_port_info->sched[1].gport; 6689 } else if (chan_id == 3) { 6690 /* l0.2 gport */ 6691 cpu_l0_gport = cpu_port_info->sched[2].gport; 6692 } 6693 6694 if (queue_id < 0) { /* All COS Queues */ 6695 for (queue_id = 0; queue_id < NUM_CPU_COSQ(unit); queue_id++) { 6696 soc_dma_cos_ctrl_queue_get(unit, pci_cmc, chan_id, 6697 queue_id, ®_val); 6698 6699 bit = 1 << (queue_id % 32); 6700 if (reg_val & bit) { 6701 /* find the parent gport of this queue 6702 if parent gport is not equal to l0 gport 6703 for this channel return error */ 6704 parent_gport = cpu_port_info->mcast[queue_id].parent_gport; 6705 if (parent_gport != cpu_l0_gport) { 6706 return BCM_E_PARAM; 6707 } 6708 } 6709 } 6710 } else { 6711 soc_dma_cos_ctrl_queue_get(unit, pci_cmc, chan_id, 6712 queue_id, ®_val); 6713 bit = 1 << (queue_id % 32); 6714 if (reg_val & bit) { 6715 /* find the parent gport of this queue 6716 if parent gport is not equal to l0 gport 6717 for this channel return error */ 6718 parent_gport = cpu_port_info->mcast[queue_id].parent_gport; 6719 if (parent_gport != cpu_l0_gport) { 6720 return BCM_E_PARAM; 6721 } 6722 } else { 6723 return BCM_E_PARAM; 6724 } 6725 } 6726 } 6727 #endif 6728 return BCM_E_NONE; 6729 } 6730 6731 #ifdef BCM_WARM_BOOT_SUPPORT 6732 STATIC int 6733 _bcm_cosq_rx_queue_channel_reinit(int unit) 6734 { 6735 _bcm_th_cosq_cpu_port_info_t *cpu_port_info = NULL; 6736 int idx; 6737 /* 6738 * L0.0 is associated with CMC0 CH1(Rx) (pci) 6739 * L0.1 is associated with CMC0 CH2(Rx) (pci) 6740 * L0.2 is associated with CMC0 CH3(Rx) (pci) 6741 * L0.3 is associated with CMC0 CH0(Rx) (pci) 6742 */ 6743 bcm_gport_t sched_gport[4]; 6744 bcm_cos_queue_t parent_cos; 6745 6746 cpu_port_info = _bcm_th_cosq_cpu_port_info[unit]; 6747 if (cpu_port_info == NULL) { 6748 return BCM_E_INIT; 6749 } 6750 6751 for (idx = 0; idx < 4; idx++) { 6752 sched_gport[idx] = cpu_port_info->sched[idx].gport; 6753 } 6754 6755 for (idx = 0; idx < _BCM_TH_NUM_CPU_MCAST_QUEUE; idx++) { 6756 parent_cos = -1; 6757 if (cpu_port_info->mcast[idx].parent_gport == sched_gport[0]) { 6758 parent_cos = 0; 6759 } else if (cpu_port_info->mcast[idx].parent_gport == sched_gport[1]) { 6760 parent_cos = 1; 6761 } else if (cpu_port_info->mcast[idx].parent_gport == sched_gport[2]) { 6762 parent_cos = 2; 6763 } else if (cpu_port_info->mcast[idx].parent_gport == sched_gport[3]) { 6764 parent_cos = 3; 6765 } 6766 if ((parent_cos >= 0) && (parent_cos < 4)) { 6767 BCM_IF_ERROR_RETURN 6768 (_bcm_th_cosq_rx_queue_channel_set(unit, parent_cos, idx, 1)); 6769 } 6770 } 6771 return BCM_E_NONE; 6772 } 6773 #endif 6774 6775 /* Function to attach any of the 48 L1 MC Queue to one of the 10 L0 nodes 6776 */ 6777 STATIC int 6778 bcm_th_cosq_cpu_gport_attach(int unit, bcm_gport_t input_gport, 6779 bcm_gport_t parent_gport, bcm_cos_queue_t cosq) 6780 { 6781 bcm_port_t parent_port, input_port; 6782 _bcm_th_cosq_node_t *input_node = NULL, *parent_node = NULL; 6783 int phy_port, mmu_port; 6784 int input_cos = 0, parent_cos = 0; 6785 int cpu_sched_base = 0, cpu_mc_base = 0; 6786 soc_info_t *si = &SOC_INFO(unit); 6787 6788 /* Post Default tree created, expected Input Gport is of MC Gport 6789 * and expected Parent Gport is new L0 Parent 6790 */ 6791 if (_BCM_TH_MMU_INFO(unit)->gport_tree_created == FALSE) { 6792 if (((BCM_GPORT_IS_MCAST_QUEUE_GROUP(input_gport)) && 6793 (!BCM_GPORT_IS_SCHEDULER(parent_gport))) || 6794 (!(BCM_GPORT_IS_MCAST_QUEUE_GROUP(input_gport)) && 6795 (!BCM_GPORT_IS_SCHEDULER(input_gport)))) { 6796 return BCM_E_PARAM; 6797 } 6798 } else if ((!BCM_GPORT_IS_SCHEDULER(parent_gport)) || 6799 (!BCM_GPORT_IS_MCAST_QUEUE_GROUP(input_gport))) { 6800 return BCM_E_PARAM; 6801 } 6802 BCM_IF_ERROR_RETURN 6803 (_bcm_th_cosq_node_get(unit, input_gport, NULL, &input_port, NULL, 6804 &input_node)); 6805 if (BCM_GPORT_IS_SCHEDULER(parent_gport)) { 6806 BCM_IF_ERROR_RETURN 6807 (_bcm_th_cosq_node_get(unit, parent_gport, NULL, &parent_port, NULL, 6808 &parent_node)); 6809 } else { 6810 BCM_IF_ERROR_RETURN 6811 (_bcm_th_cosq_localport_resolve(unit, parent_gport, &parent_port)); 6812 parent_node = NULL; 6813 } 6814 6815 if (!IS_CPU_PORT(unit, parent_port)) { 6816 return BCM_E_PARAM; 6817 } 6818 6819 /* Return BCM_E_EXISTS when queue to be attached is 6820 already attached to the given gport */ 6821 if ((_BCM_TH_MMU_INFO(unit)->gport_tree_created == TRUE) && 6822 (input_node->parent_gport == parent_gport)) { 6823 return BCM_E_EXISTS; 6824 } 6825 6826 phy_port = si->port_l2p_mapping[input_port]; 6827 mmu_port = si->port_p2m_mapping[phy_port]; 6828 cpu_sched_base = mmu_port * _BCM_TH_NUM_SCHEDULER_PER_PORT; 6829 input_cos = cosq % _BCM_TH_NUM_CPU_MCAST_QUEUE; 6830 input_node->parent_gport = parent_port; 6831 6832 if (BCM_GPORT_IS_SCHEDULER(parent_gport)) { 6833 cpu_mc_base = si->port_cosq_base[CMIC_PORT(unit)]; 6834 parent_cos = (parent_node->hw_index - cpu_sched_base) % 6835 _BCM_TH_NUM_CPU_MCAST_QUEUE; 6836 SOC_IF_ERROR_RETURN 6837 (soc_th_cosq_cpu_parent_set(unit, input_cos, SOC_TH_NODE_LVL_L1, 6838 parent_cos)); 6839 if ((parent_cos >= 0) && (parent_cos < 4)) { 6840 BCM_IF_ERROR_RETURN 6841 (_bcm_th_cosq_rx_queue_channel_set(unit, parent_cos, input_cos, 1)); 6842 } 6843 input_node->parent_gport = parent_node->gport; 6844 if (_BCM_TH_MMU_INFO(unit)->gport_tree_created == FALSE) { 6845 input_node->hw_index = cpu_mc_base + input_cos; 6846 } 6847 } else { 6848 input_node->hw_index = cpu_sched_base + input_cos; 6849 } 6850 6851 return BCM_E_NONE; 6852 } 6853 6854 /* Function to detach any of the 48 L1 MC Queue from its parent 10 L0 nodes 6855 * Post detach, L1 MC queue is attached to Parent L0.9 node 6856 */ 6857 STATIC int 6858 bcm_th_cosq_cpu_gport_detach(int unit, bcm_gport_t input_gport, 6859 bcm_gport_t parent_gport, bcm_cos_queue_t cosq) 6860 { 6861 bcm_port_t parent_port, input_port; 6862 _bcm_th_cosq_node_t *input_node = NULL, *parent_node = NULL; 6863 int phy_port, mmu_port; 6864 int input_cos = 0, parent_cos = 0, config_cos = 0; 6865 int cpu_mc_base = 0, cpu_sched_base = 0; 6866 soc_info_t *si = &SOC_INFO(unit); 6867 6868 /* Post Default tree created, expected Input Gport is of MC Gport 6869 * and expected Parent Gport is new L0 Parent 6870 */ 6871 if ((!BCM_GPORT_IS_SCHEDULER(parent_gport)) || 6872 (!BCM_GPORT_IS_MCAST_QUEUE_GROUP(input_gport))) { 6873 return BCM_E_PARAM; 6874 } 6875 BCM_IF_ERROR_RETURN 6876 (_bcm_th_cosq_node_get(unit, input_gport, NULL, &input_port, NULL, 6877 &input_node)); 6878 BCM_IF_ERROR_RETURN 6879 (_bcm_th_cosq_node_get(unit, parent_gport, NULL, &parent_port, NULL, 6880 &parent_node)); 6881 6882 if (!IS_CPU_PORT(unit, parent_port)) { 6883 return BCM_E_PARAM; 6884 } 6885 6886 /* Return BCM_E_PARAM when queue to be detached is 6887 not attached to the given gport */ 6888 if (input_node->parent_gport != parent_gport) { 6889 return BCM_E_PARAM; 6890 } 6891 6892 phy_port = si->port_l2p_mapping[input_port]; 6893 mmu_port = si->port_p2m_mapping[phy_port]; 6894 cpu_sched_base = mmu_port * _BCM_TH_NUM_SCHEDULER_PER_PORT; 6895 parent_cos = (parent_node->hw_index - cpu_sched_base) % 6896 _BCM_TH_NUM_CPU_MCAST_QUEUE; 6897 cpu_mc_base = si->port_cosq_base[CMIC_PORT(unit)]; 6898 input_cos = (input_node->hw_index - cpu_mc_base) % 6899 _BCM_TH_NUM_CPU_MCAST_QUEUE; 6900 6901 /* Reset parent to L0.9 */ 6902 SOC_IF_ERROR_RETURN 6903 (soc_th_cosq_cpu_parent_get(unit, input_cos, SOC_TH_NODE_LVL_L1, 6904 &config_cos)); 6905 if (config_cos != parent_cos) { 6906 /* Error when detaching from wrong Parent (L0 level) */ 6907 return BCM_E_PARAM; 6908 } 6909 6910 /* 6911 * L0.0 is associated with CMC0 CH1(Rx) 6912 * L0.1 is associated with CMC0 CH2(Rx) 6913 * L0.2 is associated with CMC0 CH3(Rx) 6914 * L0.3 is associated with CMC0 CH0(Rx) 6915 */ 6916 if ((parent_cos >= 0) && (parent_cos < 4)) { 6917 BCM_IF_ERROR_RETURN 6918 (_bcm_th_cosq_rx_queue_channel_set(unit, parent_cos, input_cos, 0)); 6919 } 6920 6921 /* Reset parent to L0.9 */ 6922 SOC_IF_ERROR_RETURN 6923 (soc_th_cosq_cpu_parent_set(unit, input_cos, SOC_TH_NODE_LVL_L1, 6924 _BCM_TH_NUM_SCHEDULER_PER_PORT - 1)); 6925 input_node->parent_gport = 6926 _BCM_TH_MMU_INFO(unit)->_bcm_th_cpu_port_info-> 6927 sched[_BCM_TH_NUM_SCHEDULER_PER_PORT -1].gport; 6928 6929 return BCM_E_NONE; 6930 } 6931 6932 /* 6933 * Function: 6934 * bcm_th_cosq_gport_attach 6935 * Purpose: 6936 * Attach sched_port to the specified index (cosq) of input_port 6937 * Parameters: 6938 * unit - (IN) unit number 6939 * input_gport - (IN) GPORT id, that will attach to parent gport 6940 * parent_gport - (IN) Parent Gport to which current gport will be attached 6941 * cosq - (IN) COS queue to attach to (-1 for first available cosq) 6942 * Returns: 6943 * BCM_E_XXX 6944 */ 6945 int 6946 bcm_th_cosq_gport_attach(int unit, bcm_gport_t input_gport, 6947 bcm_gport_t parent_gport, bcm_cos_queue_t cosq) 6948 { 6949 _bcm_th_cosq_node_t *input_node = NULL, *parent_node = NULL; 6950 bcm_port_t input_port, parent_port; 6951 int phy_port, mmu_port; 6952 int input_hw_index = -1, parent_hw_index = -1; 6953 soc_info_t *si = &SOC_INFO(unit); 6954 6955 LOG_INFO(BSL_LS_BCM_COSQ, 6956 (BSL_META_U(unit, 6957 "bcm_th_cosq_gport_attach: unit=%d parent_gport=0x%x " 6958 "input_gport=0x%x cosq=%d\n"), 6959 unit, parent_gport, input_gport, cosq)); 6960 6961 if (!(BCM_GPORT_IS_SCHEDULER(input_gport) || 6962 BCM_GPORT_IS_UCAST_QUEUE_GROUP(input_gport) || 6963 BCM_GPORT_IS_MCAST_QUEUE_GROUP(input_gport))) { 6964 return BCM_E_PARAM; 6965 } 6966 6967 BCM_IF_ERROR_RETURN 6968 (_bcm_th_cosq_node_get(unit, input_gport, NULL, &input_port, NULL, 6969 &input_node)); 6970 6971 if (!input_node) { 6972 return BCM_E_PARAM; 6973 } 6974 if (input_port < 0) { 6975 return BCM_E_PORT; 6976 } 6977 6978 if (IS_CPU_PORT(unit, input_port)) { 6979 return bcm_th_cosq_cpu_gport_attach(unit, input_gport, 6980 parent_gport, cosq); 6981 } else if (_BCM_TH_MMU_INFO(unit)->gport_tree_created == TRUE) { 6982 return BCM_E_PARAM; 6983 } 6984 6985 phy_port = si->port_l2p_mapping[input_port]; 6986 mmu_port = si->port_p2m_mapping[phy_port]; 6987 6988 if (BCM_GPORT_IS_SCHEDULER(parent_gport)) { 6989 BCM_IF_ERROR_RETURN 6990 (_bcm_th_cosq_node_get(unit, parent_gport, NULL, &parent_port, NULL, 6991 &parent_node)); 6992 } else { 6993 BCM_IF_ERROR_RETURN 6994 (_bcm_th_cosq_localport_resolve(unit, parent_gport, &parent_port)); 6995 parent_node = NULL; 6996 } 6997 6998 if (input_port != parent_port) { 6999 return BCM_E_PARAM; 7000 } 7001 7002 /* TH - Scheduler heirarchy is fixed. Hence check for wrong config. */ 7003 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(input_gport)) { 7004 input_node->hw_index = (mmu_port * _BCM_TH_NUM_UCAST_QUEUE_PER_PORT) + 7005 cosq; 7006 input_hw_index = input_node->hw_index % 7007 _BCM_TH_NUM_UCAST_QUEUE_PER_PORT; 7008 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(input_gport)) { 7009 input_node->hw_index = (mmu_port * _BCM_TH_NUM_MCAST_QUEUE_PER_PORT) + 7010 cosq; 7011 input_hw_index = input_node->hw_index % 7012 _BCM_TH_NUM_MCAST_QUEUE_PER_PORT; 7013 } else { 7014 input_node->hw_index = (mmu_port * _BCM_TH_NUM_SCHEDULER_PER_PORT) + 7015 cosq; 7016 input_hw_index = input_node->hw_index % 7017 _BCM_TH_NUM_SCHEDULER_PER_PORT; 7018 } 7019 7020 if (parent_node) { 7021 parent_hw_index = parent_node->hw_index % 7022 _BCM_TH_NUM_SCHEDULER_PER_PORT; 7023 if (input_hw_index != parent_hw_index) { 7024 return BCM_E_PARAM; 7025 } 7026 } 7027 7028 if (BCM_GPORT_IS_SCHEDULER(input_gport)) { 7029 BCM_IF_ERROR_RETURN 7030 (bcm_esw_port_gport_get(unit, input_port, 7031 &(input_node->parent_gport))); 7032 } else if ((BCM_GPORT_IS_UCAST_QUEUE_GROUP(input_gport)) || 7033 (BCM_GPORT_IS_MCAST_QUEUE_GROUP(input_gport))) { 7034 input_node->parent_gport = parent_gport; 7035 } 7036 7037 return BCM_E_NONE; 7038 } 7039 7040 /* 7041 * Function: 7042 * bcm_th_cosq_gport_detach 7043 * Purpose: 7044 * Detach sched_port from the specified index (cosq) of input_port 7045 * Parameters: 7046 * unit - (IN) unit number 7047 * input_port - (IN) scheduler GPORT identifier 7048 * parent_port - (IN) GPORT to detach from 7049 * cosq - (IN) COS queue to detach from 7050 * Returns: 7051 * BCM_E_XXX 7052 */ 7053 int 7054 bcm_th_cosq_gport_detach(int unit, bcm_gport_t input_gport, 7055 bcm_gport_t parent_gport, bcm_cos_queue_t cosq) 7056 { 7057 _bcm_th_cosq_node_t *input_node = NULL, *parent_node = NULL; 7058 bcm_port_t input_port, parent_port; 7059 int input_hw_index = -1, parent_hw_index = -1; 7060 7061 LOG_INFO(BSL_LS_BCM_COSQ, 7062 (BSL_META_U(unit, 7063 "bcm_th_cosq_gport_detach: unit=%d input_gport=0x%x " 7064 "parent_gport=0x%x cosq=%d\n"), 7065 unit, input_gport, parent_gport, cosq)); 7066 7067 if (!(BCM_GPORT_IS_SCHEDULER(input_gport) || 7068 BCM_GPORT_IS_UCAST_QUEUE_GROUP(input_gport) || 7069 BCM_GPORT_IS_MCAST_QUEUE_GROUP(input_gport))) { 7070 return BCM_E_PARAM; 7071 } 7072 7073 BCM_IF_ERROR_RETURN 7074 (_bcm_th_cosq_node_get(unit, input_gport, NULL, &input_port, NULL, 7075 &input_node)); 7076 7077 if (!input_node) { 7078 return BCM_E_PARAM; 7079 } 7080 7081 if (_BCM_TH_MMU_INFO(unit)->gport_tree_created == TRUE) { 7082 if (IS_CPU_PORT(unit, input_port)) { 7083 return bcm_th_cosq_cpu_gport_detach(unit, input_gport, 7084 parent_gport, cosq); 7085 } else { 7086 return BCM_E_PARAM; 7087 } 7088 } 7089 7090 if (BCM_GPORT_IS_SCHEDULER(parent_gport)) { 7091 BCM_IF_ERROR_RETURN 7092 (_bcm_th_cosq_node_get(unit, parent_gport, NULL, &parent_port, NULL, 7093 &parent_node)); 7094 } else { 7095 BCM_IF_ERROR_RETURN 7096 (_bcm_th_cosq_localport_resolve(unit, parent_gport, &parent_port)); 7097 parent_node = NULL; 7098 } 7099 7100 if (input_port != parent_port) { 7101 return BCM_E_PARAM; 7102 } 7103 7104 /* TH - Scheduler heirarchy is fixed. Hence check for wrong config. */ 7105 if (parent_node) { 7106 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(input_gport)) { 7107 input_hw_index = input_node->hw_index % 7108 _BCM_TH_NUM_UCAST_QUEUE_PER_PORT; 7109 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(input_gport)) { 7110 input_hw_index = input_node->hw_index % 7111 _BCM_TH_NUM_MCAST_QUEUE_PER_PORT; 7112 } else { 7113 input_hw_index = input_node->hw_index % 7114 _BCM_TH_NUM_SCHEDULER_PER_PORT; 7115 } 7116 7117 parent_hw_index = parent_node->hw_index % _BCM_TH_NUM_SCHEDULER_PER_PORT; 7118 7119 if (input_hw_index != parent_hw_index) { 7120 return BCM_E_PARAM; 7121 } 7122 } 7123 7124 return BCM_E_NONE; 7125 } 7126 7127 /* 7128 * Function: 7129 * bcm_th_cosq_gport_attach_get 7130 * Purpose: 7131 * Get attached status of a scheduler port 7132 * Parameters: 7133 * unit - (IN) unit number 7134 * sched_port - (IN) scheduler GPORT identifier 7135 * input_port - (OUT) GPORT to attach to 7136 * cosq - (OUT) COS queue to attached to 7137 * Returns: 7138 * BCM_E_XXX 7139 * Notes: 7140 */ 7141 int 7142 bcm_th_cosq_gport_attach_get(int unit, bcm_gport_t sched_gport, 7143 bcm_gport_t *input_gport, bcm_cos_queue_t *cosq) 7144 { 7145 _bcm_th_cosq_node_t *node = NULL; 7146 int numq = -1, cpu_mc_base = 0; 7147 bcm_port_t local_port = -1; 7148 soc_info_t *si = &SOC_INFO(unit); 7149 7150 if (!(BCM_GPORT_IS_SET(sched_gport) || 7151 BCM_GPORT_IS_SCHEDULER(sched_gport) || 7152 BCM_GPORT_IS_UCAST_QUEUE_GROUP(sched_gport) || 7153 BCM_GPORT_IS_MCAST_QUEUE_GROUP(sched_gport))) { 7154 return BCM_E_PARAM; 7155 } 7156 7157 BCM_IF_ERROR_RETURN 7158 (_bcm_th_cosq_node_get(unit, sched_gport, NULL, &local_port, NULL, 7159 &node)); 7160 if (node == NULL) { 7161 return BCM_E_PARAM; 7162 } 7163 7164 if (local_port < 0) { 7165 return BCM_E_PARAM; 7166 } 7167 7168 if (BCM_GPORT_IS_SCHEDULER(sched_gport)) { 7169 *cosq = node->hw_index % _BCM_TH_NUM_SCHEDULER_PER_PORT; 7170 } else if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(sched_gport)) { 7171 *cosq = node->hw_index % _BCM_TH_NUM_UCAST_QUEUE_PER_PORT; 7172 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(sched_gport)) { 7173 if (IS_CPU_PORT(unit, local_port)) { 7174 cpu_mc_base = si->port_cosq_base[CMIC_PORT(unit)]; 7175 numq = _BCM_TH_NUM_CPU_MCAST_QUEUE; 7176 *cosq = (node->hw_index - cpu_mc_base) % numq; 7177 } else { 7178 numq = _BCM_TH_NUM_MCAST_QUEUE_PER_PORT; 7179 *cosq = node->hw_index % numq; 7180 } 7181 } else { 7182 return BCM_E_PARAM; 7183 } 7184 *input_gport = node->parent_gport; 7185 7186 return BCM_E_NONE; 7187 } 7188 7189 /* 7190 * Function: 7191 * bcm_th_cosq_gport_child_get 7192 * Purpose: 7193 * Get the child node GPORT atatched to N-th index (cosq) 7194 * of the scheduler GPORT. 7195 * Parameters: 7196 * unit - (IN) Unit number. 7197 * in_gport - (IN) Scheduler GPORT ID. 7198 * cosq - (IN) COS queue attached to. 7199 * out_gport - (OUT) child GPORT ID. 7200 * Returns: 7201 * BCM_E_XXX 7202 * Notes: 7203 */ 7204 int 7205 bcm_th_cosq_gport_child_get(int unit, bcm_gport_t in_gport, 7206 bcm_cos_queue_t cosq, 7207 bcm_gport_t *out_gport) 7208 { 7209 _bcm_th_cosq_node_t *tmp_node = NULL; 7210 bcm_port_t local_port = -1; 7211 _bcm_th_cosq_cpu_port_info_t *port_info = NULL; 7212 int index = -1, cpu_mc_base = 0; 7213 soc_info_t *si = &SOC_INFO(unit); 7214 7215 if (out_gport == NULL) { 7216 return BCM_E_PARAM; 7217 } 7218 7219 BCM_IF_ERROR_RETURN 7220 (_bcm_th_cosq_localport_resolve(unit, in_gport, &local_port)); 7221 7222 if (!SOC_PORT_VALID(unit, local_port)) { 7223 return BCM_E_PORT; 7224 } 7225 7226 /* This API is only implemented to CPU ports because 7227 for all other ports we have fixed hierarchy */ 7228 if (!IS_CPU_PORT(unit, local_port)) { 7229 return BCM_E_PARAM; 7230 } 7231 7232 if ((cosq < 0) || (cosq >= NUM_CPU_COSQ(unit))) { 7233 return BCM_E_PARAM; 7234 } 7235 7236 if (_bcm_th_cosq_cpu_port_info[unit] == NULL) { 7237 return BCM_E_INIT; 7238 } 7239 7240 port_info = _bcm_th_cosq_cpu_port_info[unit]; 7241 cpu_mc_base = si->port_cosq_base[CMIC_PORT(unit)]; 7242 7243 if (BCM_GPORT_IS_SCHEDULER(in_gport)) { 7244 for (index = 0; index < _BCM_TH_NUM_CPU_MCAST_QUEUE; index++) { 7245 if (port_info->mcast[index].parent_gport == in_gport) { 7246 if (cosq == ((port_info->mcast[index].hw_index - cpu_mc_base) % 7247 _BCM_TH_NUM_CPU_MCAST_QUEUE)) { 7248 tmp_node = &port_info->mcast[index]; 7249 break; 7250 } 7251 } 7252 } 7253 } else { 7254 return BCM_E_PARAM; 7255 } 7256 7257 if (tmp_node == NULL) { 7258 return BCM_E_NOT_FOUND; 7259 } 7260 7261 *out_gport = tmp_node->gport; 7262 7263 return BCM_E_NONE; 7264 } 7265 7266 #ifdef DEAD_CODE 7267 /* 7268 * Function: 7269 * bcm_th_cosq_gport_delete 7270 * Purpose: 7271 * Destroy a cosq gport structure 7272 * Parameters: 7273 * unit - (IN) unit number 7274 * gport - (IN) GPORT identifier 7275 * Returns: 7276 * BCM_E_XXX 7277 */ 7278 int 7279 bcm_th_cosq_gport_delete(int unit, bcm_gport_t gport) 7280 { 7281 _bcm_th_cosq_node_t *node = NULL; 7282 _bcm_th_cosq_port_info_t *port_info = NULL; 7283 int local_port, i; 7284 7285 LOG_INFO(BSL_LS_BCM_COSQ, 7286 (BSL_META_U(unit, 7287 "bcm_th_cosq_gport_delete: unit=%d gport=0x%x\n"), 7288 unit, gport)); 7289 7290 if (_bcm_th_cosq_port_info[unit] == NULL) { 7291 return BCM_E_INIT; 7292 } 7293 7294 7295 if (gport == -2) { 7296 bcm_th_cosq_sw_dump(unit); 7297 } 7298 7299 if (BCM_GPORT_IS_SCHEDULER(gport) || 7300 BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 7301 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 7302 BCM_IF_ERROR_RETURN 7303 (_bcm_th_cosq_node_get(unit, gport, NULL, NULL, NULL, &node)); 7304 7305 if (node->in_use == 0) { 7306 return BCM_E_UNAVAIL; 7307 } 7308 } 7309 7310 BCM_IF_ERROR_RETURN 7311 (_bcm_th_cosq_localport_resolve(unit, gport, &local_port)); 7312 7313 if (!SOC_PORT_VALID(unit, local_port)) { 7314 return BCM_E_PORT; 7315 } 7316 port_info = &_bcm_th_cosq_port_info[unit][local_port]; 7317 7318 for (i = 0; i < _BCM_TH_NUM_SCHEDULER_PER_PORT; i++) { 7319 port_info->sched[i].in_use = 0; 7320 port_info->sched[i].numq = 0; 7321 } 7322 for (i = 0; i < _BCM_TH_NUM_UCAST_QUEUE_PER_PORT; i++) { 7323 port_info->ucast[i].in_use = 0; 7324 port_info->ucast[i].numq = 0; 7325 } 7326 for (i = 0; i < _BCM_TH_NUM_MCAST_QUEUE_PER_PORT; i++) { 7327 port_info->mcast[i].in_use = 0; 7328 port_info->mcast[i].numq = 0; 7329 } 7330 return BCM_E_NONE; 7331 } 7332 #endif 7333 7334 /* 7335 * Function: 7336 * _bcm_th_cosq_mapping_set 7337 * Purpose: 7338 * Set COS queue for the specified priority of an ingress port 7339 * Parameters: 7340 * unit - (IN) unit number 7341 * ing_port - (IN) ingress port 7342 * gport - (IN) queue group GPORT identifier 7343 * priority - (IN) priority value to map 7344 * flags - (IN) BCM_COSQ_GPORT_XXX_QUEUE_GROUP 7345 * gport - (IN) queue group GPORT identifier 7346 * cosq - (IN) COS queue number 7347 * Returns: 7348 * BCM_E_XXX 7349 */ 7350 STATIC int 7351 _bcm_th_cosq_mapping_set(int unit, bcm_port_t ing_port, bcm_cos_t priority, 7352 uint32 flags, bcm_gport_t gport, bcm_cos_queue_t cosq) 7353 { 7354 bcm_port_t local_port, out_port; 7355 bcm_cos_queue_t hw_cosq; 7356 int rv, idx; 7357 soc_field_t field[2] = {INVALIDf, INVALIDf}; /* [0]:UC, [1]:MC cos */ 7358 void *entries[1]; 7359 cos_map_sel_entry_t cos_map_sel_entry; 7360 port_cos_map_entry_t cos_map_entries[_TH_MMU_NUM_INT_PRI]; 7361 uint32 old_index, new_index; 7362 7363 BCM_IF_ERROR_RETURN 7364 (_bcm_th_cosq_localport_resolve(unit, ing_port, &local_port)); 7365 7366 if (gport != -1) { 7367 BCM_IF_ERROR_RETURN(_bcm_th_cosq_localport_resolve(unit, gport, 7368 &out_port)); 7369 } 7370 7371 switch (flags) { 7372 case BCM_COSQ_GPORT_UCAST_QUEUE_GROUP: 7373 if (gport == -1) { 7374 hw_cosq = cosq; 7375 } else { 7376 if (!BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 7377 return BCM_E_PARAM; 7378 } 7379 BCM_IF_ERROR_RETURN 7380 (_bcm_th_cosq_index_resolve 7381 (unit, gport, cosq, _BCM_TH_COSQ_INDEX_STYLE_COS, 7382 NULL, &hw_cosq, NULL)); 7383 } 7384 hw_cosq %= _BCM_TH_NUM_UCAST_QUEUE_PER_PORT; 7385 field[0] = UC_COS1f; 7386 break; 7387 case BCM_COSQ_GPORT_MCAST_QUEUE_GROUP: 7388 if (gport == -1) { 7389 hw_cosq = cosq; 7390 } else { 7391 if (!BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 7392 return BCM_E_PARAM; 7393 } 7394 BCM_IF_ERROR_RETURN 7395 (_bcm_th_cosq_index_resolve 7396 (unit, gport, cosq, _BCM_TH_COSQ_INDEX_STYLE_COS, 7397 NULL, &hw_cosq, NULL)); 7398 } 7399 hw_cosq %= _BCM_TH_NUM_MCAST_QUEUE_PER_PORT; 7400 field[0] = MC_COS1f; 7401 break; 7402 case (BCM_COSQ_GPORT_UCAST_QUEUE_GROUP | 7403 BCM_COSQ_GPORT_MCAST_QUEUE_GROUP): 7404 if (gport == -1) { 7405 hw_cosq = cosq; 7406 } else { 7407 return BCM_E_PARAM; 7408 } 7409 hw_cosq %= _BCM_TH_NUM_SCHEDULER_PER_PORT; 7410 field[0] = UC_COS1f; 7411 field[1] = MC_COS1f; 7412 break; 7413 default: 7414 return BCM_E_PARAM; 7415 } 7416 7417 entries[0] = &cos_map_entries; 7418 7419 BCM_IF_ERROR_RETURN 7420 (READ_COS_MAP_SELm(unit, MEM_BLOCK_ANY, local_port, 7421 &cos_map_sel_entry)); 7422 old_index = soc_mem_field32_get(unit, COS_MAP_SELm, &cos_map_sel_entry, 7423 SELECTf); 7424 old_index *= _TH_MMU_NUM_INT_PRI; 7425 7426 BCM_IF_ERROR_RETURN 7427 (soc_profile_mem_get(unit, _bcm_th_cos_map_profile[unit], 7428 old_index, _TH_MMU_NUM_INT_PRI, entries)); 7429 7430 for (idx = 0; idx < 2; idx++) { 7431 if (field[idx] != INVALIDf) { 7432 soc_mem_field32_set(unit, PORT_COS_MAPm, 7433 &cos_map_entries[priority], 7434 field[idx], hw_cosq); 7435 } 7436 } 7437 7438 soc_mem_lock(unit, PORT_COS_MAPm); 7439 7440 rv = soc_profile_mem_delete(unit, _bcm_th_cos_map_profile[unit], 7441 old_index); 7442 if (BCM_FAILURE(rv)) { 7443 soc_mem_unlock(unit, PORT_COS_MAPm); 7444 return rv; 7445 } 7446 7447 rv = soc_profile_mem_add(unit, _bcm_th_cos_map_profile[unit], entries, 7448 _TH_MMU_NUM_INT_PRI, &new_index); 7449 7450 soc_mem_unlock(unit, PORT_COS_MAPm); 7451 7452 if (BCM_FAILURE(rv)) { 7453 return rv; 7454 } 7455 7456 soc_mem_field32_set(unit, COS_MAP_SELm, &cos_map_sel_entry, SELECTf, 7457 new_index / _TH_MMU_NUM_INT_PRI); 7458 BCM_IF_ERROR_RETURN 7459 (WRITE_COS_MAP_SELm(unit, MEM_BLOCK_ANY, local_port, 7460 &cos_map_sel_entry)); 7461 #ifndef BCM_COSQ_HIGIG_MAP_DISABLE 7462 if (IS_CPU_PORT(unit, local_port)) { 7463 BCM_IF_ERROR_RETURN 7464 (soc_mem_field32_modify(unit, COS_MAP_SELm, 7465 SOC_INFO(unit).cpu_hg_index, SELECTf, 7466 new_index / _TH_MMU_NUM_INT_PRI)); 7467 } 7468 #endif /* BCM_COSQ_HIGIG_MAP_DISABLE */ 7469 7470 return BCM_E_NONE; 7471 } 7472 7473 /* 7474 * Function: 7475 * bcm_th_cosq_mapping_set 7476 * Purpose: 7477 * Set which cosq a given priority should fall into 7478 * Parameters: 7479 * unit - (IN) unit number 7480 * gport - (IN) queue group GPORT identifier 7481 * priority - (IN) priority value to map 7482 * cosq - (IN) COS queue to map to 7483 * Returns: 7484 * BCM_E_XXX 7485 */ 7486 7487 int 7488 bcm_th_cosq_mapping_set(int unit, bcm_port_t port, bcm_cos_t priority, 7489 bcm_cos_queue_t cosq) 7490 { 7491 bcm_pbmp_t pbmp; 7492 bcm_port_t local_port; 7493 7494 BCM_PBMP_CLEAR(pbmp); 7495 7496 if ((priority < 0) || (priority >= _TH_MMU_NUM_INT_PRI)) { 7497 return BCM_E_PARAM; 7498 } 7499 7500 if (cosq < 0) { 7501 return BCM_E_PARAM; 7502 } 7503 7504 if (port == -1) { 7505 /* port value of -1 will cause the cosq mapping set for 7506 all types of local ports except Loopback ports. 7507 So we do the sanity check of cos value with Default Number 7508 of COS */ 7509 if (cosq >= _TH_NUM_COS(unit)) { 7510 return BCM_E_PARAM; 7511 } 7512 BCM_PBMP_ASSIGN(pbmp, PBMP_ALL(unit)); 7513 } else { 7514 if (BCM_GPORT_IS_SET(port)) { 7515 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 7516 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) || 7517 BCM_GPORT_IS_SCHEDULER(port)) { 7518 return BCM_E_PARAM; 7519 } else if (BCM_GPORT_IS_LOCAL(port)) { 7520 local_port = BCM_GPORT_LOCAL_GET(port); 7521 } else if (BCM_GPORT_IS_MODPORT(port)) { 7522 BCM_IF_ERROR_RETURN( 7523 bcm_esw_port_local_get(unit, port, &local_port)); 7524 } else { 7525 return BCM_E_PARAM; 7526 } 7527 } else { 7528 local_port = port; 7529 } 7530 7531 if (!SOC_PORT_VALID(unit, local_port)) { 7532 return BCM_E_PORT; 7533 } 7534 7535 BCM_PBMP_PORT_ADD(pbmp, local_port); 7536 if (cosq >= _TH_PORT_NUM_COS(unit, local_port)) { 7537 return BCM_E_PARAM; 7538 } 7539 } 7540 7541 PBMP_ITER(pbmp, local_port) { 7542 if (IS_LB_PORT(unit, local_port)) { 7543 continue; 7544 } 7545 7546 /* If no ETS/gport, map the int prio symmetrically for ucast and 7547 * mcast */ 7548 BCM_IF_ERROR_RETURN 7549 (_bcm_th_cosq_mapping_set(unit, local_port, 7550 priority, 7551 BCM_COSQ_GPORT_UCAST_QUEUE_GROUP | 7552 BCM_COSQ_GPORT_MCAST_QUEUE_GROUP, 7553 -1, cosq)); 7554 } 7555 7556 return BCM_E_NONE; 7557 } 7558 7559 int 7560 bcm_th_cosq_gport_mapping_set(int unit, bcm_port_t ing_port, 7561 bcm_cos_t int_pri, uint32 flags, 7562 bcm_gport_t gport, bcm_cos_queue_t cosq) 7563 { 7564 bcm_port_t local_port; 7565 7566 if ((int_pri < 0) || (int_pri >= _TH_MMU_NUM_INT_PRI)) { 7567 return BCM_E_PARAM; 7568 } 7569 7570 BCM_IF_ERROR_RETURN(_bcm_th_cosq_localport_resolve(unit, ing_port, 7571 &local_port)); 7572 7573 if ((cosq < 0) || (cosq >= _TH_PORT_NUM_COS(unit, local_port))) { 7574 return BCM_E_PARAM; 7575 } 7576 7577 return _bcm_th_cosq_mapping_set(unit, ing_port, int_pri, flags, gport, 7578 cosq); 7579 } 7580 7581 /* Routine to perform Inverse mapping for given Queue port back to Port/Priority 7582 * which was defined by default or through cosq_mapping_set functions 7583 */ 7584 int 7585 _bcm_th_cosq_inv_mapping_get(int unit, bcm_gport_t gport, 7586 bcm_cos_queue_t cosq, 7587 uint32 flags, bcm_port_t *ing_port, 7588 bcm_cos_t *priority) 7589 { 7590 bcm_port_t local_port; 7591 cos_map_sel_entry_t cos_map_sel_entry; 7592 void *entries[1]; 7593 int num_queue = 1, index, ii; 7594 bcm_cos_queue_t in_cosq = BCM_COS_INVALID, pri_cosq = BCM_COS_INVALID; 7595 bcm_module_t modid; 7596 soc_field_t cos_field = INVALIDf; 7597 port_cos_map_entry_t cos_map_entries[_TH_MMU_NUM_INT_PRI]; 7598 7599 if ((flags != BCM_COSQ_GPORT_UCAST_QUEUE_GROUP) && 7600 (flags != BCM_COSQ_GPORT_MCAST_QUEUE_GROUP)) { 7601 return BCM_E_PARAM; 7602 } 7603 7604 if ((ing_port == NULL) || (priority == NULL)) { 7605 return BCM_E_PARAM; 7606 } 7607 7608 if (BCM_GPORT_IS_SET(gport)) { 7609 if (!(BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) && 7610 !(BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport))) { 7611 return BCM_E_PARAM; 7612 } 7613 BCM_IF_ERROR_RETURN 7614 (_bcm_th_cosq_node_get(unit, gport, &modid, &local_port, 7615 &in_cosq, NULL)); 7616 } else { 7617 BCM_IF_ERROR_RETURN 7618 (_bcm_th_cosq_localport_resolve(unit, gport, &local_port)); 7619 in_cosq = cosq; 7620 } 7621 7622 if ((cosq < -1) || (cosq >= _TH_PORT_NUM_COS(unit, local_port))) { 7623 return BCM_E_PARAM; 7624 } 7625 7626 if ((IS_CPU_PORT(unit, local_port)) || (IS_LB_PORT(unit, local_port))) { 7627 return BCM_E_PARAM; 7628 } 7629 7630 *ing_port = local_port; 7631 7632 if (flags == BCM_COSQ_GPORT_MCAST_QUEUE_GROUP) { 7633 cos_field = MC_COS1f; 7634 num_queue = _BCM_TH_NUM_MCAST_QUEUE_PER_PORT; 7635 } else { 7636 cos_field = COSf; 7637 num_queue = _BCM_TH_NUM_UCAST_QUEUE_PER_PORT; 7638 } 7639 7640 if (in_cosq == BCM_COS_INVALID) { 7641 return BCM_E_PARAM; 7642 } else { 7643 in_cosq %= num_queue; 7644 } 7645 7646 entries[0] = &cos_map_entries; 7647 BCM_IF_ERROR_RETURN 7648 (READ_COS_MAP_SELm(unit, MEM_BLOCK_ANY, local_port, 7649 &cos_map_sel_entry)); 7650 index = soc_mem_field32_get(unit, COS_MAP_SELm, &cos_map_sel_entry, 7651 SELECTf); 7652 index *= _TH_MMU_NUM_INT_PRI; 7653 7654 BCM_IF_ERROR_RETURN 7655 (soc_profile_mem_get(unit, _bcm_th_cos_map_profile[unit], 7656 index, _TH_MMU_NUM_INT_PRI, entries)); 7657 7658 for (ii = 0; ii < _TH_MMU_NUM_INT_PRI; ii++) { 7659 pri_cosq = soc_mem_field32_get(unit, PORT_COS_MAPm, 7660 &cos_map_entries[ii], cos_field); 7661 if (pri_cosq == in_cosq) { 7662 /* Required Cosq found. Break as the index is the priority */ 7663 *priority = ii; 7664 break; 7665 } 7666 } 7667 7668 if (ii == _TH_MMU_NUM_INT_PRI) { 7669 /* Mapping cannot be found */ 7670 return BCM_E_NOT_FOUND; 7671 } 7672 7673 return BCM_E_NONE; 7674 } 7675 7676 /* 7677 * Function: 7678 * bcm_th_cosq_mapping_get 7679 * Purpose: 7680 * Determine which COS queue a given priority currently maps to. 7681 * Parameters: 7682 * unit - (IN) unit number 7683 * gport - (IN) queue group GPORT identifier 7684 * priority - (IN) priority value to map 7685 * cosq - (OUT) COS queue to map to 7686 * Returns: 7687 * BCM_E_XXX 7688 */ 7689 int 7690 _bcm_th_cosq_mapping_get(int unit, bcm_port_t ing_port, bcm_cos_t priority, 7691 uint32 flags, bcm_gport_t *gport, 7692 bcm_cos_queue_t *cosq) 7693 { 7694 bcm_port_t local_port; 7695 cos_map_sel_entry_t cos_map_sel_entry; 7696 _bcm_th_cosq_port_info_t *port_info = NULL; 7697 _bcm_th_cosq_cpu_port_info_t *cpu_port_info = NULL; 7698 _bcm_th_cosq_node_t *node; 7699 int ii, index, cosq_base = 0; 7700 void *entry_p; 7701 bcm_cos_queue_t hw_cosq = BCM_COS_INVALID, node_cosq = BCM_COS_INVALID; 7702 int numq = -1; 7703 soc_info_t *si = &SOC_INFO(unit); 7704 7705 if ((flags != BCM_COSQ_GPORT_UCAST_QUEUE_GROUP) && 7706 (flags != BCM_COSQ_GPORT_MCAST_QUEUE_GROUP)) { 7707 return BCM_E_PARAM; 7708 } 7709 7710 BCM_IF_ERROR_RETURN 7711 (_bcm_th_cosq_localport_resolve(unit, ing_port, &local_port)); 7712 7713 if (gport) { 7714 *gport = BCM_GPORT_INVALID; 7715 } 7716 7717 *cosq = BCM_COS_INVALID; 7718 7719 BCM_IF_ERROR_RETURN 7720 (READ_COS_MAP_SELm(unit, MEM_BLOCK_ANY, local_port, 7721 &cos_map_sel_entry)); 7722 index = soc_mem_field32_get(unit, COS_MAP_SELm, &cos_map_sel_entry, 7723 SELECTf); 7724 index *= _TH_MMU_NUM_INT_PRI; 7725 7726 entry_p = SOC_PROFILE_MEM_ENTRY(unit, _bcm_th_cos_map_profile[unit], 7727 port_cos_map_entry_t *, 7728 index + priority); 7729 if (IS_CPU_PORT(unit, local_port)) { 7730 cpu_port_info = &_bcm_th_cosq_cpu_port_info[unit][local_port]; 7731 } else { 7732 port_info = &_bcm_th_cosq_port_info[unit][local_port]; 7733 } 7734 7735 switch (flags) { 7736 case BCM_COSQ_GPORT_UCAST_QUEUE_GROUP: 7737 hw_cosq = soc_mem_field32_get(unit, PORT_COS_MAPm, entry_p, 7738 UC_COS1f); 7739 if ((IS_CPU_PORT(unit, local_port) == FALSE) && (gport)) { 7740 for (ii = 0; ii < _BCM_TH_NUM_UCAST_QUEUE_PER_PORT; ii++) { 7741 node = &port_info->ucast[ii]; 7742 if (node == NULL) { 7743 return BCM_E_NOT_FOUND; 7744 } 7745 node_cosq = (node->hw_index % 7746 _BCM_TH_NUM_UCAST_QUEUE_PER_PORT); 7747 if (node && (node_cosq == hw_cosq)) { 7748 *gport = node->gport; 7749 *cosq = hw_cosq; 7750 break; 7751 } 7752 } 7753 } else { 7754 *cosq = hw_cosq; 7755 } 7756 break; 7757 case BCM_COSQ_GPORT_MCAST_QUEUE_GROUP: 7758 hw_cosq = soc_mem_field32_get(unit, PORT_COS_MAPm, entry_p, 7759 MC_COS1f); 7760 if (gport) { 7761 if (IS_CPU_PORT(unit, local_port)) { 7762 numq = _BCM_TH_NUM_CPU_MCAST_QUEUE; 7763 cosq_base = si->port_cosq_base[CMIC_PORT(unit)]; 7764 } else { 7765 numq = _BCM_TH_NUM_MCAST_QUEUE_PER_PORT; 7766 cosq_base = 0; 7767 } 7768 for (ii = 0; ii < numq; ii++) { 7769 if (IS_CPU_PORT(unit, local_port)) { 7770 node = &cpu_port_info->mcast[ii]; 7771 } else { 7772 node = &port_info->mcast[ii]; 7773 } 7774 if (!node) { 7775 return BCM_E_NOT_FOUND; 7776 } 7777 node_cosq = ((node->hw_index - cosq_base) % numq); 7778 if (node_cosq == hw_cosq) { 7779 *gport = node->gport; 7780 *cosq = hw_cosq; 7781 break; 7782 } 7783 } 7784 } else { 7785 *cosq = hw_cosq; 7786 } 7787 break; 7788 /* 7789 * COVERITY 7790 * 7791 * This default is unreachable. It is kept intentionally 7792 * as a defensive default for future development. 7793 */ 7794 /* coverity[dead_error_begin] */ 7795 default: 7796 return BCM_E_PARAM; 7797 } 7798 if (((gport && 7799 (*gport == BCM_GPORT_INVALID) && (*cosq == BCM_COS_INVALID))) || 7800 (*cosq == BCM_COS_INVALID)) { 7801 return BCM_E_NOT_FOUND; 7802 } 7803 7804 return BCM_E_NONE; 7805 } 7806 7807 /* 7808 * Function: 7809 * bcm_th_cosq_mapping_get 7810 * Purpose: 7811 * Determine which COS queue a given priority currently maps to. 7812 * Parameters: 7813 * unit - (IN) unit number 7814 * gport - (IN) queue group GPORT identifier 7815 * priority - (IN) priority value to map 7816 * cosq - (OUT) COS queue to map to 7817 * Returns: 7818 * BCM_E_XXX 7819 */ 7820 int 7821 bcm_th_cosq_mapping_get(int unit, bcm_port_t port, bcm_cos_t priority, 7822 bcm_cos_queue_t *cosq) 7823 { 7824 bcm_port_t local_port; 7825 bcm_pbmp_t pbmp; 7826 7827 if ((priority < 0) || (priority >= _TH_MMU_NUM_INT_PRI)) { 7828 return BCM_E_PARAM; 7829 } 7830 7831 BCM_PBMP_CLEAR(pbmp); 7832 7833 if (port == -1) { 7834 BCM_PBMP_ASSIGN(pbmp, PBMP_ALL(unit)); 7835 } else { 7836 if (BCM_GPORT_IS_SET(port)) { 7837 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 7838 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) || 7839 BCM_GPORT_IS_SCHEDULER(port)) { 7840 return BCM_E_PARAM; 7841 } else if (BCM_GPORT_IS_LOCAL(port)) { 7842 local_port = BCM_GPORT_LOCAL_GET(port); 7843 } else if (BCM_GPORT_IS_MODPORT(port)) { 7844 BCM_IF_ERROR_RETURN 7845 (bcm_esw_port_local_get(unit, port, &local_port)); 7846 } else { 7847 return BCM_E_PARAM; 7848 } 7849 } else { 7850 local_port = port; 7851 } 7852 7853 if (!SOC_PORT_VALID(unit, local_port)) { 7854 return BCM_E_PORT; 7855 } 7856 7857 BCM_PBMP_PORT_ADD(pbmp, local_port); 7858 } 7859 7860 PBMP_ITER(pbmp, local_port) { 7861 if (IS_LB_PORT(unit, local_port)) { 7862 continue; 7863 } 7864 7865 BCM_IF_ERROR_RETURN(_bcm_th_cosq_mapping_get(unit, local_port, 7866 priority, BCM_COSQ_GPORT_UCAST_QUEUE_GROUP, NULL, cosq)); 7867 break; 7868 } 7869 return BCM_E_NONE; 7870 } 7871 7872 int 7873 bcm_th_cosq_gport_mapping_get(int unit, bcm_port_t ing_port, 7874 bcm_cos_t int_pri, uint32 flags, 7875 bcm_gport_t *gport, bcm_cos_queue_t *cosq) 7876 { 7877 if (gport == NULL || cosq == NULL) { 7878 return BCM_E_PARAM; 7879 } 7880 7881 if ((int_pri < 0) || (int_pri >= _TH_MMU_NUM_INT_PRI)) { 7882 return BCM_E_PARAM; 7883 } 7884 7885 return _bcm_th_cosq_mapping_get(unit, ing_port, int_pri, flags, gport, 7886 cosq); 7887 } 7888 7889 7890 /* 7891 * Function: 7892 * bcm_th_cosq_field_classifier_get 7893 * Purpose: 7894 * Get classifier type information. 7895 * Parameters: 7896 * unit - (IN) Unit number. 7897 * classifier_id - (IN) Classifier ID 7898 * classifier - (OUT) Classifier info 7899 * Returns: 7900 * BCM_E_xxx 7901 */ 7902 int 7903 bcm_th_cosq_field_classifier_get( 7904 int unit, 7905 int classifier_id, 7906 bcm_cosq_classifier_t *classifier) 7907 { 7908 if (classifier == NULL) { 7909 return BCM_E_PARAM; 7910 } 7911 sal_memset(classifier, 0, sizeof(bcm_cosq_classifier_t)); 7912 7913 if (_BCM_COSQ_CLASSIFIER_IS_FIELD(classifier_id)) { 7914 classifier->flags |= BCM_COSQ_CLASSIFIER_FIELD; 7915 } 7916 7917 return BCM_E_NONE; 7918 } 7919 7920 /* 7921 * Function: 7922 * bcm_th_cosq_field_classifier_id_create 7923 * Purpose: 7924 * Create a cosq classifier. 7925 * Parameters: 7926 * unit - (IN) Unit number. 7927 * classifier - (IN) Classifier attributes 7928 * classifier_id - (OUT) Classifier ID 7929 * Returns: 7930 * BCM_E_xxx 7931 */ 7932 int 7933 bcm_th_cosq_field_classifier_id_create( 7934 int unit, 7935 bcm_cosq_classifier_t *classifier, 7936 int *classifier_id) 7937 { 7938 int rv; 7939 int ref_count = 0; 7940 int ent_per_set = _TH_MMU_NUM_INT_PRI; 7941 int i; 7942 7943 if (NULL == classifier || NULL == classifier_id) { 7944 return BCM_E_PARAM; 7945 } 7946 7947 for (i = 0; i < SOC_MEM_SIZE(unit, IFP_COS_MAPm); i += ent_per_set) { 7948 rv = soc_profile_mem_ref_count_get( 7949 unit, _bcm_th_ifp_cos_map_profile[unit], i, &ref_count); 7950 if (SOC_FAILURE(rv)) { 7951 return rv; 7952 } 7953 if (0 == ref_count) { 7954 break; 7955 } 7956 } 7957 7958 if (i >= SOC_MEM_SIZE(unit, IFP_COS_MAPm) && ref_count != 0) { 7959 *classifier_id = 0; 7960 return BCM_E_RESOURCE; 7961 } 7962 7963 _BCM_COSQ_CLASSIFIER_FIELD_SET(*classifier_id, (i / ent_per_set)); 7964 7965 return BCM_E_NONE; 7966 } 7967 7968 /* 7969 * Function: 7970 * bcm_th_cosq_field_classifier_map_set 7971 * Purpose: 7972 * Set internal priority to ingress field processor CoS queue 7973 * override mapping. 7974 * Parameters: 7975 * unit - (IN) Unit number. 7976 * classifier_id - (IN) Classifier ID 7977 * count - (IN) Number of elements in priority_array and 7978 * cosq_array. 7979 * priority_array - (IN) Array of internal priorities 7980 * cosq_array - (IN) Array of COS queues 7981 * Returns: 7982 * BCM_E_xxx 7983 * Notes: 7984 * Supported count value is [0-16] and 48 7985 * When count = [0-16] 7986 * Array Index [15-0] : Maps Prio[15-0] to UC, MC 7987 * and RQE cos[15-0] 7988 * When count = 48 7989 * Prio Array Index Map 7990 * Array Index [15-0] : Maps Prio[15-0] to UC cos[15-0] 7991 * Array Index [31-16] : Maps Prio[15-0] to MC cos[15-0] 7992 * Array Index [47-32] : Maps Prio[15-0] to RQE cos[15-0] 7993 */ 7994 int 7995 bcm_th_cosq_field_classifier_map_set( 7996 int unit, 7997 int classifier_id, 7998 int count, 7999 bcm_cos_t *priority_array, 8000 bcm_cos_queue_t *cosq_array) 8001 { 8002 int rv; 8003 int i; 8004 int max_entries = _TH_MMU_NUM_INT_PRI; 8005 uint32 index, new_index; 8006 void *entries[1]; 8007 ifp_cos_map_entry_t ent_buf[_TH_MMU_NUM_INT_PRI]; 8008 soc_field_t field = -1; 8009 8010 /* Input parameter check. */ 8011 if (!_BCM_COSQ_CLASSIFIER_IS_FIELD(classifier_id)) { 8012 return BCM_E_PARAM; 8013 } 8014 8015 if (NULL == priority_array || NULL == cosq_array) { 8016 return BCM_E_PARAM; 8017 } 8018 8019 if ((count > max_entries) && (count != (max_entries * 3))) { 8020 return BCM_E_PARAM; 8021 } 8022 8023 sal_memset(ent_buf, 0, sizeof(ifp_cos_map_entry_t) * max_entries); 8024 entries[0] = ent_buf; 8025 8026 if (count != (max_entries * 3)) { 8027 for (i = 0; i < count; i++) { 8028 if (priority_array[i] < max_entries) { 8029 /* When count != max_entries * 3 8030 We program the same mapping for all three 8031 fields UC/MC/RQE queues. 8032 Hence cos_array[i] cannot have value more than 8033 equal to 10 */ 8034 if ((cosq_array[i] < 0) || 8035 (cosq_array[i] >= _BCM_TH_NUM_UCAST_QUEUE_PER_PORT)) { 8036 return BCM_E_PARAM; 8037 } 8038 soc_mem_field32_set(unit, IFP_COS_MAPm, &ent_buf[priority_array[i]], 8039 IFP_MC_COSf, cosq_array[i]); 8040 soc_mem_field32_set(unit, IFP_COS_MAPm, &ent_buf[priority_array[i]], 8041 IFP_UC_COSf, cosq_array[i]); 8042 soc_mem_field32_set(unit, IFP_COS_MAPm, &ent_buf[priority_array[i]], 8043 IFP_RQE_Q_NUMf, cosq_array[i]); 8044 } 8045 } 8046 } else { 8047 for (i = 0; i < count; i++) { 8048 if (priority_array[i] < max_entries) { 8049 if (i < max_entries) { 8050 /* Number of UCAST queue per port = 10 */ 8051 if ((cosq_array[i] < 0) || 8052 (cosq_array[i] >= _BCM_TH_NUM_UCAST_QUEUE_PER_PORT)) { 8053 return BCM_E_PARAM; 8054 } 8055 field = IFP_UC_COSf; 8056 } else if (i < (max_entries * 2)) { 8057 /* Number of MCAST queue per port = 10 */ 8058 if ((cosq_array[i] < 0) || 8059 (cosq_array[i] >= _BCM_TH_NUM_MCAST_QUEUE_PER_PORT)) { 8060 return BCM_E_PARAM; 8061 } 8062 field = IFP_MC_COSf; 8063 } else { 8064 /* Number of RQE queue per unit = 11 */ 8065 if ((cosq_array[i] < 0) || 8066 (cosq_array[i] >= _TH_MMU_NUM_RQE_QUEUES)) { 8067 return BCM_E_PARAM; 8068 } 8069 field = IFP_RQE_Q_NUMf; 8070 } 8071 soc_mem_field32_set(unit, IFP_COS_MAPm, &ent_buf[priority_array[i]], 8072 field, cosq_array[i]); 8073 } 8074 } 8075 } 8076 8077 index = _BCM_COSQ_CLASSIFIER_FIELD_GET(classifier_id); 8078 8079 rv = soc_profile_mem_delete(unit, _bcm_th_ifp_cos_map_profile[unit], 8080 index * max_entries); 8081 8082 /* If rv = SOC_E_NONE means that there exists a 8083 * mapping for given classifier_id which is now 8084 * successfully deleted and we can overwrite. 8085 * rv = SOC_E_NOT_FOUND means there was no mapping 8086 * for given classifier_id and we can create a new mapping 8087 * Otherwise there is something else wrong and we return 8088 * the error value returned by soc_profile_mem_delete() 8089 */ 8090 if ((rv != SOC_E_NONE) && (rv != SOC_E_NOT_FOUND)) { 8091 return rv; 8092 } 8093 8094 SOC_IF_ERROR_RETURN 8095 (soc_profile_mem_add(unit, _bcm_th_ifp_cos_map_profile[unit], 8096 entries, max_entries, &new_index)); 8097 8098 /* If we get (index == new_index / max_entries) means we have 8099 * a successful mapping operation. 8100 * But if they are not equal which means there already exists 8101 * a similar mapping associated with other classifier_id hence 8102 * we return BCM_E_EXISTS. 8103 */ 8104 8105 if (index != (new_index / max_entries)) { 8106 SOC_IF_ERROR_RETURN 8107 (soc_profile_mem_delete(unit, _bcm_th_ifp_cos_map_profile[unit], 8108 new_index)); 8109 return BCM_E_EXISTS; 8110 } 8111 8112 return BCM_E_NONE; 8113 } 8114 8115 /* 8116 * Function: 8117 * bcm_th_cosq_field_classifier_map_get 8118 * Purpose: 8119 * Get internal priority to ingress field processor CoS queue 8120 * override mapping information. 8121 * Parameters: 8122 * unit - (IN) Unit number. 8123 * classifier_id - (IN) Classifier ID 8124 * array_max - (IN) Size of priority_array and cosq_array 8125 * priority_array - (IN) Array of internal priorities 8126 * cosq_array - (OUT) Array of COS queues 8127 * array_count - (OUT) Size of cosq_array 8128 * Returns: 8129 * BCM_E_xxx 8130 * Notes: 8131 * Supported array_max = [0-16] and 48 8132 * When array_max = [0-16] 8133 * Array Index [15-0] : Maps Prio[15-0] to UC cos[15-0] 8134 * When array_max = 48 8135 * Prio Array Index Map 8136 * Array Index [15-0] : Maps Prio[15-0] to UC cos[15-0] 8137 * Array Index [31-16] : Maps Prio[15-0] to MC cos[15-0] 8138 * Array Index [47-32] : Maps Prio[15-0] to RQE cos[15-0] 8139 */ 8140 int 8141 bcm_th_cosq_field_classifier_map_get( 8142 int unit, 8143 int classifier_id, 8144 int array_max, 8145 bcm_cos_t *priority_array, 8146 bcm_cos_queue_t *cosq_array, 8147 int *array_count) 8148 { 8149 int rv; 8150 int i; 8151 int ent_per_set = _TH_MMU_NUM_INT_PRI; 8152 uint32 index; 8153 void *entries[1]; 8154 ifp_cos_map_entry_t ent_buf[_TH_MMU_NUM_INT_PRI]; 8155 soc_field_t field = -1; 8156 8157 /* Input parameter check. */ 8158 if (NULL == priority_array || NULL == cosq_array || NULL == array_count) { 8159 return BCM_E_PARAM; 8160 } 8161 8162 sal_memset(ent_buf, 0, sizeof(ifp_cos_map_entry_t) * ent_per_set); 8163 entries[0] = ent_buf; 8164 8165 /* Get profile table entry set base index. */ 8166 index = _BCM_COSQ_CLASSIFIER_FIELD_GET(classifier_id); 8167 8168 /* Read out entries from profile table into allocated buffer. */ 8169 rv = soc_profile_mem_get(unit, _bcm_th_ifp_cos_map_profile[unit], 8170 index * ent_per_set, ent_per_set, entries); 8171 if (SOC_FAILURE(rv)) { 8172 return rv; 8173 } 8174 8175 if (array_max <= ent_per_set) { 8176 *array_count = array_max; 8177 } else if ((array_max > ent_per_set) && (array_max < (ent_per_set * 3))) { 8178 return BCM_E_PARAM; 8179 } else { 8180 *array_count = ent_per_set * 3; 8181 } 8182 /* Copy values into API OUT parameters. */ 8183 for (i = 0; i < *array_count; i++) { 8184 if (priority_array[i % 16] >= _TH_MMU_NUM_INT_PRI) { 8185 return BCM_E_PARAM; 8186 } 8187 if (i < ent_per_set) { 8188 field = IFP_UC_COSf; 8189 } else if (i < (ent_per_set * 2)) { 8190 field = IFP_MC_COSf; 8191 } else { 8192 field = IFP_RQE_Q_NUMf; 8193 } 8194 cosq_array[i] = soc_mem_field32_get(unit, IFP_COS_MAPm, 8195 &ent_buf[priority_array[i]], 8196 field); 8197 } 8198 8199 return BCM_E_NONE; 8200 } 8201 8202 /* 8203 * Function: 8204 * bcm_th_cosq_field_classifier_map_clear 8205 * Purpose: 8206 * Delete an internal priority to ingress field processor CoS queue 8207 * override mapping profile set. 8208 * Parameters: 8209 * unit - (IN) Unit number. 8210 * classifier_id - (IN) Classifier ID 8211 * Returns: 8212 * BCM_E_xxx 8213 */ 8214 int 8215 bcm_th_cosq_field_classifier_map_clear(int unit, int classifier_id) 8216 { 8217 int ent_per_set = _TH_MMU_NUM_INT_PRI; 8218 uint32 index; 8219 8220 /* Get profile table entry set base index. */ 8221 index = _BCM_COSQ_CLASSIFIER_FIELD_GET(classifier_id); 8222 8223 /* Delete the profile entries set. */ 8224 SOC_IF_ERROR_RETURN 8225 (soc_profile_mem_delete(unit, 8226 _bcm_th_ifp_cos_map_profile[unit], 8227 index * ent_per_set)); 8228 return BCM_E_NONE; 8229 } 8230 8231 /* 8232 * Function: 8233 * bcm_th_cosq_field_classifier_id_destroy 8234 * Purpose: 8235 * Free resource associated with this field classifier id. 8236 * Parameters: 8237 * unit - (IN) Unit number. 8238 * classifier_id - (IN) Classifier ID 8239 * Returns: 8240 * BCM_E_xxx 8241 */ 8242 int 8243 bcm_th_cosq_field_classifier_id_destroy(int unit, int classifier_id) 8244 { 8245 return BCM_E_NONE; 8246 } 8247 8248 STATIC int 8249 _bcm_th_cosq_egr_queue_set(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 8250 bcm_cosq_control_t type, int arg) 8251 { 8252 bcm_port_t local_port; 8253 int pipe, startq; 8254 uint32 max_val; 8255 uint32 max_val2; 8256 uint32 entry[SOC_MAX_MEM_WORDS]; 8257 uint32 entry2[SOC_MAX_MEM_WORDS]; 8258 soc_mem_t mem = INVALIDm, mem2 = INVALIDm; 8259 soc_field_t fld_limit = INVALIDf; 8260 int granularity = 1; 8261 int from_cos, to_cos, ci; 8262 int egr_db_shd_size[_TH_XPES_PER_DEV], egr_qe_shd_size[_TH_XPES_PER_DEV]; 8263 int cur_val; 8264 int limit; 8265 int disable_queuing = 0; 8266 int uc_qlimit_enable = 0, mc_qlimit_enable = 0; 8267 8268 if (arg < 0) { 8269 return BCM_E_PARAM; 8270 } 8271 8272 arg = (arg + _TH_MMU_BYTES_PER_CELL - 1) / _TH_MMU_BYTES_PER_CELL; 8273 8274 if ((type == bcmCosqControlEgressUCQueueMinLimitBytes) || 8275 (type == bcmCosqControlEgressUCQueueSharedLimitBytes)) { 8276 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 8277 BCM_IF_ERROR_RETURN 8278 (_bcm_th_cosq_index_resolve(unit, gport, cosq, 8279 _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE, 8280 &local_port, &startq, NULL)); 8281 SOC_IF_ERROR_RETURN 8282 (soc_port_pipe_get(unit, local_port, &pipe)); 8283 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 8284 return BCM_E_PARAM; 8285 } 8286 else { 8287 if (cosq == BCM_COS_INVALID) { 8288 from_cos = to_cos = 0; 8289 } else { 8290 from_cos = to_cos = cosq; 8291 } 8292 8293 BCM_IF_ERROR_RETURN 8294 (_bcm_th_cosq_localport_resolve(unit, gport, &local_port)); 8295 if (local_port < 0) { 8296 return BCM_E_PORT; 8297 } 8298 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 8299 for (ci = from_cos; ci <= to_cos; ci++) { 8300 BCM_IF_ERROR_RETURN 8301 (_bcm_th_cosq_index_resolve 8302 (unit, local_port, ci, _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE, 8303 NULL, &startq, NULL)); 8304 } 8305 } 8306 mem = SOC_MEM_UNIQUE_ACC(unit, MMU_THDU_CONFIG_QUEUEm)[pipe]; 8307 mem2 = SOC_MEM_UNIQUE_ACC(unit, MMU_THDU_Q_TO_QGRP_MAPm)[pipe]; 8308 } else if ((type == bcmCosqControlEgressMCQueueMinLimitBytes) || 8309 (type == bcmCosqControlEgressMCQueueSharedLimitBytes)) { 8310 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 8311 return BCM_E_PARAM; 8312 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 8313 BCM_IF_ERROR_RETURN 8314 (_bcm_th_cosq_index_resolve(unit, gport, cosq, 8315 _BCM_TH_COSQ_INDEX_STYLE_MCAST_QUEUE, 8316 &local_port, &startq, NULL)); 8317 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 8318 } 8319 else { 8320 if (cosq == BCM_COS_INVALID) { 8321 from_cos = to_cos = 0; 8322 } else { 8323 from_cos = to_cos = cosq; 8324 } 8325 8326 BCM_IF_ERROR_RETURN 8327 (_bcm_th_cosq_localport_resolve(unit, gport, &local_port)); 8328 if (local_port < 0) { 8329 return BCM_E_PORT; 8330 } 8331 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 8332 for (ci = from_cos; ci <= to_cos; ci++) { 8333 BCM_IF_ERROR_RETURN 8334 (_bcm_th_cosq_index_resolve 8335 (unit, local_port, ci, _BCM_TH_COSQ_INDEX_STYLE_MCAST_QUEUE, 8336 NULL, &startq, NULL)); 8337 } 8338 } 8339 mem = SOC_MEM_UNIQUE_ACC(unit, MMU_THDM_DB_QUEUE_CONFIGm)[pipe]; 8340 mem2 = SOC_MEM_UNIQUE_ACC(unit, MMU_THDM_MCQE_QUEUE_CONFIGm)[pipe]; 8341 } else { 8342 return BCM_E_PARAM; 8343 } 8344 8345 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 8346 if (mem2 != INVALIDm) { 8347 BCM_IF_ERROR_RETURN 8348 (soc_mem_read(unit, mem2, MEM_BLOCK_ALL, startq, entry2)); 8349 } 8350 8351 switch (type) { 8352 case bcmCosqControlEgressUCQueueSharedLimitBytes: 8353 fld_limit = Q_SHARED_LIMIT_CELLf; 8354 8355 uc_qlimit_enable = 1; 8356 8357 /* Set MMU_THDU_XPIPE_Q_TO_QGRP_MAP.DISABLE_QUEUING to 1 when both MIN 8358 * and SHARED LIMIT are 0. Set it to 0 when either MIN or SHARED LIMIT 8359 * is non-zero. 8360 */ 8361 limit = soc_mem_field32_get(unit, mem, entry, Q_MIN_LIMIT_CELLf); 8362 if (arg == 0 && limit == 0) { 8363 disable_queuing = 1; 8364 } else if (arg != 0 || limit != 0) { 8365 disable_queuing = 0; 8366 } 8367 granularity = 1; 8368 break; 8369 case bcmCosqControlEgressMCQueueSharedLimitBytes: 8370 fld_limit = Q_SHARED_LIMITf; 8371 mc_qlimit_enable = 1; 8372 granularity = 1; 8373 break; 8374 case bcmCosqControlEgressUCQueueMinLimitBytes: 8375 fld_limit = Q_MIN_LIMIT_CELLf; 8376 8377 /* Set MMU_THDU_Q_TO_QGRP_MAP.DISABLE_QUEUING to 1 when both MIN 8378 * and SHARED LIMIT are 0. Set it to 0 when either MIN or 8379 * SHARED LIMIT is non-zero 8380 */ 8381 limit = soc_mem_field32_get(unit, mem, entry, Q_SHARED_LIMIT_CELLf); 8382 if (arg == 0 && limit == 0) { 8383 disable_queuing = 1; 8384 } else if (arg != 0 || limit != 0) { 8385 disable_queuing = 0; 8386 } 8387 8388 granularity = 1; 8389 break; 8390 case bcmCosqControlEgressMCQueueMinLimitBytes: 8391 fld_limit = Q_MIN_LIMITf; 8392 granularity = 1; 8393 break; 8394 default: 8395 return BCM_E_UNAVAIL; 8396 } 8397 8398 /* Check for min/max values */ 8399 max_val = (1 << soc_mem_field_length(unit, mem, fld_limit)) - 1; 8400 if ((arg < 0) || ((arg/granularity) > max_val)) { 8401 return BCM_E_PARAM; 8402 } 8403 8404 /* guarantee limits need adjust shared limits */ 8405 if ((type == bcmCosqControlEgressUCQueueMinLimitBytes) || 8406 (type == bcmCosqControlEgressMCQueueMinLimitBytes)) { 8407 int xpe, xpe_map; 8408 int delta[_TH_XPES_PER_DEV] = {0}, update; 8409 int *egr_shd_size; 8410 8411 8412 cur_val = soc_mem_field32_get(unit, mem, entry, fld_limit); 8413 sal_memcpy(egr_db_shd_size, _BCM_TH_MMU_INFO(unit)->egr_db_shared_limit, 8414 sizeof(egr_db_shd_size)); 8415 sal_memcpy(egr_qe_shd_size, _BCM_TH_MMU_INFO(unit)->egr_qe_shared_limit, 8416 sizeof(egr_qe_shd_size)); 8417 8418 egr_shd_size = egr_db_shd_size; 8419 8420 /* adjustment delta */ 8421 xpe_map = SOC_INFO(unit).epipe_xpe_map[pipe]; 8422 for (xpe = 0; xpe < NUM_XPE(unit); xpe ++) { 8423 if (xpe_map & (1 << xpe)) { 8424 delta[xpe] = ((arg / granularity) - cur_val) * granularity; 8425 } 8426 } 8427 8428 /* shared limits to be decreased */ 8429 for (xpe = 0, update = 0; xpe < NUM_XPE(unit); xpe ++) { 8430 if ((xpe_map & (1 << xpe)) && (delta[xpe] > 0)) { 8431 /* no space to decrease shared limit */ 8432 if (delta[xpe] > egr_shd_size[xpe]) { 8433 return BCM_E_PARAM; 8434 } 8435 egr_shd_size[xpe] -= delta[xpe]; 8436 update = 1; 8437 } 8438 } 8439 if (update) { 8440 BCM_IF_ERROR_RETURN 8441 (soc_th_mmu_config_res_limits_update(unit, 2 /* egr */, 8442 NULL, egr_db_shd_size, egr_qe_shd_size, 1)); 8443 } 8444 8445 /* set new guarantee */ 8446 /* the hw value may be changed by soc_th_mmu_config_res_limits_update 8447 * so read the register again in order to keep consistent */ 8448 BCM_IF_ERROR_RETURN 8449 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 8450 soc_mem_field32_set(unit, mem, entry, fld_limit, (arg/granularity)); 8451 /* coverity[negative_returns] */ 8452 BCM_IF_ERROR_RETURN 8453 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 8454 8455 /* shared limits to be increased */ 8456 for (xpe = 0, update = 0; xpe < NUM_XPE(unit); xpe ++) { 8457 if ((xpe_map & (1 << xpe)) && (delta[xpe] < 0)) { 8458 egr_shd_size[xpe] -= delta[xpe]; 8459 update = 1; 8460 } 8461 } 8462 if (update) { 8463 BCM_IF_ERROR_RETURN 8464 (soc_th_mmu_config_res_limits_update(unit, 2 /* egr */, 8465 NULL, egr_db_shd_size, egr_qe_shd_size, 0)); 8466 } 8467 8468 sal_memcpy(_BCM_TH_MMU_INFO(unit)->egr_db_shared_limit, egr_db_shd_size, 8469 sizeof(egr_db_shd_size)); 8470 sal_memcpy(_BCM_TH_MMU_INFO(unit)->egr_qe_shared_limit, egr_qe_shd_size, 8471 sizeof(egr_qe_shd_size)); 8472 } else { 8473 if (type == bcmCosqControlEgressMCQueueSharedLimitBytes) { 8474 uint32 value = arg/granularity; 8475 max_val2 = (1 << soc_mem_field_length(unit, mem2, fld_limit)) - 1; 8476 if (value > max_val2) { 8477 value = max_val2; 8478 } 8479 soc_mem_field32_set(unit, mem2, entry2, fld_limit, value); 8480 BCM_IF_ERROR_RETURN 8481 (soc_mem_write(unit, mem2, MEM_BLOCK_ALL, startq, entry2)); 8482 } 8483 soc_mem_field32_set(unit, mem, entry, fld_limit, (arg/granularity)); 8484 BCM_IF_ERROR_RETURN 8485 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 8486 } 8487 8488 /* limit enable */ 8489 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 8490 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem2, MEM_BLOCK_ALL, startq, entry2)); 8491 8492 if ((type == bcmCosqControlEgressUCQueueMinLimitBytes) || 8493 (type == bcmCosqControlEgressUCQueueSharedLimitBytes)) { 8494 soc_mem_field32_set(unit, mem2, entry2, DISABLE_QUEUINGf, disable_queuing); 8495 } 8496 8497 if (mc_qlimit_enable) { 8498 soc_mem_field32_set(unit, mem, entry, Q_LIMIT_ENABLEf, 1); 8499 soc_mem_field32_set(unit, mem2, entry2, Q_LIMIT_ENABLEf, 1); 8500 } 8501 8502 if (uc_qlimit_enable) { 8503 soc_mem_field32_set(unit, mem2, entry2, Q_LIMIT_ENABLEf, 1); 8504 } 8505 8506 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 8507 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem2, MEM_BLOCK_ALL, startq, entry2)); 8508 8509 return BCM_E_NONE; 8510 } 8511 8512 STATIC int 8513 _bcm_th_cosq_egr_queue_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 8514 bcm_cosq_control_t type, int *arg) 8515 { 8516 bcm_port_t local_port; 8517 int pipe, startq; 8518 uint32 entry[SOC_MAX_MEM_WORDS]; 8519 soc_mem_t mem = INVALIDm; 8520 soc_field_t fld_limit = INVALIDf; 8521 int granularity = 1; 8522 int from_cos, to_cos, ci; 8523 8524 if (!arg) { 8525 return BCM_E_PARAM; 8526 } 8527 8528 if ((type == bcmCosqControlEgressUCQueueMinLimitBytes) || 8529 (type == bcmCosqControlEgressUCQueueSharedLimitBytes)) { 8530 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 8531 BCM_IF_ERROR_RETURN 8532 (_bcm_th_cosq_index_resolve(unit, gport, cosq, 8533 _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE, 8534 &local_port, &startq, NULL)); 8535 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 8536 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 8537 return BCM_E_PARAM; 8538 } 8539 else { 8540 if (cosq == BCM_COS_INVALID) { 8541 from_cos = to_cos = 0; 8542 } else { 8543 from_cos = to_cos = cosq; 8544 } 8545 8546 BCM_IF_ERROR_RETURN 8547 (_bcm_th_cosq_localport_resolve(unit, gport, &local_port)); 8548 if (local_port < 0) { 8549 return BCM_E_PORT; 8550 } 8551 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 8552 for (ci = from_cos; ci <= to_cos; ci++) { 8553 BCM_IF_ERROR_RETURN 8554 (_bcm_th_cosq_index_resolve 8555 (unit, local_port, ci, _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE, 8556 NULL, &startq, NULL)); 8557 } 8558 } 8559 mem = SOC_MEM_UNIQUE_ACC(unit, MMU_THDU_CONFIG_QUEUEm)[pipe]; 8560 } else if ((type == bcmCosqControlEgressMCQueueMinLimitBytes) || 8561 (type == bcmCosqControlEgressMCQueueSharedLimitBytes)) { 8562 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 8563 return BCM_E_PARAM; 8564 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 8565 BCM_IF_ERROR_RETURN 8566 (_bcm_th_cosq_index_resolve(unit, gport, cosq, 8567 _BCM_TH_COSQ_INDEX_STYLE_MCAST_QUEUE, 8568 &local_port, &startq, NULL)); 8569 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 8570 } 8571 else { 8572 if (cosq == BCM_COS_INVALID) { 8573 from_cos = to_cos = 0; 8574 } else { 8575 from_cos = to_cos = cosq; 8576 } 8577 8578 BCM_IF_ERROR_RETURN 8579 (_bcm_th_cosq_localport_resolve(unit, gport, &local_port)); 8580 if (local_port < 0) { 8581 return BCM_E_PORT; 8582 } 8583 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 8584 for (ci = from_cos; ci <= to_cos; ci++) { 8585 BCM_IF_ERROR_RETURN 8586 (_bcm_th_cosq_index_resolve 8587 (unit, local_port, ci, _BCM_TH_COSQ_INDEX_STYLE_MCAST_QUEUE, 8588 NULL, &startq, NULL)); 8589 } 8590 } 8591 mem = SOC_MEM_UNIQUE_ACC(unit, MMU_THDM_DB_QUEUE_CONFIGm)[pipe]; 8592 } else { 8593 return BCM_E_PARAM; 8594 } 8595 8596 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, 8597 startq, entry)); 8598 8599 switch (type) { 8600 case bcmCosqControlEgressUCQueueSharedLimitBytes: 8601 fld_limit = Q_SHARED_LIMIT_CELLf; 8602 granularity = 1; 8603 break; 8604 case bcmCosqControlEgressMCQueueSharedLimitBytes: 8605 fld_limit = Q_SHARED_LIMITf; 8606 granularity = 1; 8607 break; 8608 case bcmCosqControlEgressUCQueueMinLimitBytes: 8609 fld_limit = Q_MIN_LIMIT_CELLf; 8610 granularity = 1; 8611 break; 8612 case bcmCosqControlEgressMCQueueMinLimitBytes: 8613 fld_limit = Q_MIN_LIMITf; 8614 granularity = 1; 8615 break; 8616 default: 8617 return BCM_E_UNAVAIL; 8618 } 8619 *arg = soc_mem_field32_get(unit, mem, entry, fld_limit); 8620 *arg = (*arg) * granularity * _TH_MMU_BYTES_PER_CELL; 8621 return BCM_E_NONE; 8622 } 8623 8624 /* 8625 * This function is used to get ingress pipe, shared pool id 8626 * priority group and headroom pool id for a given [Port, Prio] 8627 */ 8628 STATIC int 8629 _bcm_th_cosq_ing_pool_pg_pipe_get(int unit, bcm_gport_t gport, 8630 bcm_cos_t prio, int *pipe, 8631 int *sp, int *pg, int *hdrm_pool) 8632 { 8633 bcm_port_t local_port; 8634 8635 if (pipe) { 8636 BCM_IF_ERROR_RETURN 8637 (_bcm_th_cosq_localport_resolve(unit, gport, &local_port)); 8638 if (local_port < 0) { 8639 return BCM_E_PORT; 8640 } 8641 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, pipe)); 8642 } 8643 8644 if (pg) { 8645 BCM_IF_ERROR_RETURN 8646 (_bcm_th_cosq_ingress_pg_get(unit, gport, prio, pg, 8647 NULL )); 8648 8649 if ((*pg < 0) || (*pg >= _TH_MMU_NUM_PG)) { 8650 return BCM_E_PARAM; 8651 } 8652 } 8653 8654 if (sp) { 8655 BCM_IF_ERROR_RETURN( 8656 _bcm_th_cosq_ingress_sp_get(unit, gport, prio, sp, 8657 NULL)); 8658 8659 if ((*sp < 0) || (*sp >= _TH_MMU_NUM_POOL)) { 8660 return BCM_E_PARAM; 8661 } 8662 } 8663 8664 if (hdrm_pool) { 8665 BCM_IF_ERROR_RETURN( 8666 _bcm_th_cosq_ingress_hdrm_pool_get(unit, gport, 8667 prio, hdrm_pool, 8668 NULL)); 8669 8670 if ((*hdrm_pool < 0) || (*hdrm_pool >= _TH_MMU_NUM_POOL)) { 8671 return BCM_E_PARAM; 8672 } 8673 } 8674 8675 return BCM_E_NONE; 8676 } 8677 8678 8679 /* 8680 * This function is used to get the 8681 * Min and Max value of ingress PG or SP 8682 */ 8683 STATIC int 8684 _bcm_th_cosq_ing_res_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 8685 bcm_cosq_control_t type, int *arg) 8686 { 8687 bcm_port_t local_port; 8688 int midx; 8689 uint32 entry[SOC_MAX_MEM_WORDS]; 8690 soc_mem_t mem = INVALIDm, base_mem = INVALIDm; 8691 soc_field_t fld_limit = INVALIDf; 8692 int pipe, port_pg; 8693 int pool, granularity = 1; 8694 8695 if ((cosq < 0) || (cosq >= _TH_MMU_NUM_INT_PRI)) { 8696 /* Error. Input pri > Max Pri_Grp */ 8697 return BCM_E_PARAM; 8698 } 8699 8700 if (arg == NULL) { 8701 return BCM_E_PARAM; 8702 } 8703 8704 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 8705 BCM_GPORT_IS_SCHEDULER(gport) || 8706 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 8707 return BCM_E_PARAM; 8708 } 8709 8710 BCM_IF_ERROR_RETURN 8711 (_bcm_th_cosq_localport_resolve(unit, gport, &local_port)); 8712 if (!SOC_PORT_VALID(unit, local_port)) { 8713 return BCM_E_PORT; 8714 } 8715 8716 BCM_IF_ERROR_RETURN 8717 (_bcm_th_cosq_ing_pool_pg_pipe_get(unit, gport, cosq, 8718 &pipe, &pool, &port_pg, 8719 NULL)); 8720 8721 if ((type == bcmCosqControlIngressPortPGSharedLimitBytes) || 8722 (type == bcmCosqControlIngressPortPGMinLimitBytes) || 8723 (type == bcmCosqControlIngressPortPGHeadroomLimitBytes)|| 8724 (type == bcmCosqControlIngressPortPGResetFloorBytes) || 8725 (type == bcmCosqControlIngressPortPGResetOffsetBytes)) { 8726 base_mem = THDI_PORT_PG_CONFIGm; 8727 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 8728 /* get index for Port-PG */ 8729 midx = SOC_TH_MMU_PIPED_MEM_INDEX(unit, local_port, base_mem, port_pg); 8730 } else if ((type == bcmCosqControlIngressPortPoolMaxLimitBytes) || 8731 (type == bcmCosqControlIngressPortPoolMinLimitBytes) || 8732 (type == bcmCosqControlIngressPortPoolResumeLimitBytes)) { 8733 base_mem = THDI_PORT_SP_CONFIGm; 8734 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 8735 /* get index for Port-SP */ 8736 midx = SOC_TH_MMU_PIPED_MEM_INDEX(unit, local_port, base_mem, pool); 8737 } else { 8738 return BCM_E_UNAVAIL; 8739 } 8740 8741 if (midx < 0) { 8742 return BCM_E_PARAM; 8743 } 8744 8745 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, entry)); 8746 8747 switch (type) { 8748 case bcmCosqControlIngressPortPGSharedLimitBytes: 8749 fld_limit = PG_SHARED_LIMITf; 8750 granularity = 1; 8751 break; 8752 case bcmCosqControlIngressPortPoolMaxLimitBytes: 8753 fld_limit = PORT_SP_MAX_LIMITf; 8754 granularity = 1; 8755 break; 8756 case bcmCosqControlIngressPortPGMinLimitBytes: 8757 fld_limit = PG_MIN_LIMITf; 8758 granularity = 1; 8759 break; 8760 case bcmCosqControlIngressPortPoolMinLimitBytes: 8761 fld_limit = PORT_SP_MIN_LIMITf; 8762 granularity = 1; 8763 break; 8764 case bcmCosqControlIngressPortPGHeadroomLimitBytes: 8765 fld_limit = PG_HDRM_LIMITf; 8766 granularity = 1; 8767 break; 8768 case bcmCosqControlIngressPortPGResetFloorBytes: 8769 fld_limit = PG_RESET_FLOORf; 8770 granularity = 1; 8771 break; 8772 case bcmCosqControlIngressPortPGResetOffsetBytes: 8773 fld_limit = PG_RESET_OFFSETf; 8774 granularity = 1; 8775 break; 8776 case bcmCosqControlIngressPortPoolResumeLimitBytes: 8777 fld_limit = PORT_SP_RESUME_LIMITf; 8778 granularity = 1; 8779 break; 8780 /* coverity[dead_error_begin] */ 8781 default: 8782 return BCM_E_UNAVAIL; 8783 } 8784 8785 *arg = soc_mem_field32_get(unit, mem, entry, fld_limit); 8786 *arg = (*arg) * granularity * _TH_MMU_BYTES_PER_CELL; 8787 8788 return BCM_E_NONE; 8789 } 8790 8791 8792 STATIC int 8793 _bcm_th_cosq_ing_res_set(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 8794 bcm_cosq_control_t type, int arg) 8795 { 8796 bcm_port_t local_port; 8797 int midx; 8798 uint32 max_val, regval = 0; 8799 uint32 entry[SOC_MAX_MEM_WORDS]; 8800 soc_mem_t mem = INVALIDm, base_mem = INVALIDm; 8801 soc_field_t fld_limit = INVALIDf; 8802 int pipe, port_pg; 8803 int pool, granularity = 1; 8804 int ing_shd_size[_TH_XPES_PER_DEV], cur_val; 8805 int cur_hdrm; 8806 soc_reg_t reg; 8807 8808 if ((cosq < 0) || (cosq >= _TH_MMU_NUM_INT_PRI)) { 8809 /* Error. Input pri > Max Pri_Grp */ 8810 return BCM_E_PARAM; 8811 } 8812 8813 if (arg < 0) { 8814 return BCM_E_PARAM; 8815 } 8816 8817 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 8818 BCM_GPORT_IS_SCHEDULER(gport) || 8819 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 8820 return BCM_E_PARAM; 8821 } 8822 8823 arg = (arg + _TH_MMU_BYTES_PER_CELL - 1) / _TH_MMU_BYTES_PER_CELL; 8824 BCM_IF_ERROR_RETURN 8825 (_bcm_th_cosq_localport_resolve(unit, gport, &local_port)); 8826 if (!SOC_PORT_VALID(unit, local_port)) { 8827 return BCM_E_PORT; 8828 } 8829 8830 BCM_IF_ERROR_RETURN 8831 (_bcm_th_cosq_ing_pool_pg_pipe_get(unit, gport, cosq, 8832 &pipe, &pool, &port_pg, 8833 NULL)); 8834 8835 if ((type == bcmCosqControlIngressPortPGSharedLimitBytes) || 8836 (type == bcmCosqControlIngressPortPGMinLimitBytes) || 8837 (type == bcmCosqControlIngressPortPGHeadroomLimitBytes)|| 8838 (type == bcmCosqControlIngressPortPGResetFloorBytes) || 8839 (type == bcmCosqControlIngressPortPGResetOffsetBytes)) { 8840 base_mem = THDI_PORT_PG_CONFIGm; 8841 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 8842 /* get index for Port-PG */ 8843 midx = SOC_TH_MMU_PIPED_MEM_INDEX(unit, local_port, base_mem, port_pg); 8844 } else if ((type == bcmCosqControlIngressPortPoolMaxLimitBytes) || 8845 (type == bcmCosqControlIngressPortPoolMinLimitBytes) || 8846 (type == bcmCosqControlIngressPortPoolResumeLimitBytes)) { 8847 base_mem = THDI_PORT_SP_CONFIGm; 8848 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 8849 /* get index for Port-SP */ 8850 midx = SOC_TH_MMU_PIPED_MEM_INDEX(unit, local_port, base_mem, pool); 8851 } else { 8852 return BCM_E_UNAVAIL; 8853 } 8854 8855 if (midx < 0) { 8856 return BCM_E_PARAM; 8857 } 8858 8859 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, entry)); 8860 8861 switch (type) { 8862 case bcmCosqControlIngressPortPGSharedLimitBytes: 8863 fld_limit = PG_SHARED_LIMITf; 8864 granularity = 1; 8865 break; 8866 case bcmCosqControlIngressPortPoolMaxLimitBytes: 8867 fld_limit = PORT_SP_MAX_LIMITf; 8868 granularity = 1; 8869 break; 8870 case bcmCosqControlIngressPortPGMinLimitBytes: 8871 fld_limit = PG_MIN_LIMITf; 8872 granularity = 1; 8873 break; 8874 case bcmCosqControlIngressPortPoolMinLimitBytes: 8875 fld_limit = PORT_SP_MIN_LIMITf; 8876 granularity = 1; 8877 break; 8878 case bcmCosqControlIngressPortPGHeadroomLimitBytes: 8879 fld_limit = PG_HDRM_LIMITf; 8880 granularity = 1; 8881 break; 8882 case bcmCosqControlIngressPortPGResetFloorBytes: 8883 fld_limit = PG_RESET_FLOORf; 8884 granularity = 1; 8885 break; 8886 case bcmCosqControlIngressPortPGResetOffsetBytes: 8887 fld_limit = PG_RESET_OFFSETf; 8888 granularity = 1; 8889 break; 8890 case bcmCosqControlIngressPortPoolResumeLimitBytes: 8891 fld_limit = PORT_SP_RESUME_LIMITf; 8892 granularity = 1; 8893 break; 8894 /* coverity[dead_error_begin] */ 8895 default: 8896 return BCM_E_UNAVAIL; 8897 } 8898 8899 /* Check for min/max values */ 8900 max_val = (1 << soc_mem_field_length(unit, mem, fld_limit)) - 1; 8901 if ((arg < 0) || ((arg/granularity) > max_val)) { 8902 return BCM_E_PARAM; 8903 } 8904 8905 /* guarantee limits need adjust shared limits */ 8906 if ((type == bcmCosqControlIngressPortPGMinLimitBytes) || 8907 (type == bcmCosqControlIngressPortPGHeadroomLimitBytes)) { 8908 int xpe, xpe_map; 8909 int delta[_TH_XPES_PER_DEV] = {0}, update; 8910 8911 cur_val = soc_mem_field32_get(unit, mem, entry, fld_limit); 8912 sal_memcpy(ing_shd_size, _BCM_TH_MMU_INFO(unit)->ing_shared_limit, 8913 sizeof(ing_shd_size)); 8914 8915 /* adjustment delta */ 8916 xpe_map = SOC_INFO(unit).ipipe_xpe_map[pipe]; 8917 for (xpe = 0; xpe < NUM_XPE(unit); xpe ++) { 8918 if (xpe_map & (1 << xpe)) { 8919 delta[xpe] = ((arg / granularity) - cur_val) * granularity; 8920 } 8921 } 8922 8923 /* shared limits to be decreased */ 8924 for (xpe = 0, update = 0; xpe < NUM_XPE(unit); xpe ++) { 8925 if ((xpe_map & (1 << xpe)) && (delta[xpe] > 0)) { 8926 /* no space to decrease shared limit */ 8927 if (delta[xpe] > ing_shd_size[xpe]) { 8928 return BCM_E_PARAM; 8929 } 8930 ing_shd_size[xpe] -= delta[xpe]; 8931 update = 1; 8932 } 8933 } 8934 if (update) { 8935 BCM_IF_ERROR_RETURN 8936 (soc_th_mmu_config_res_limits_update(unit, 1 /* ing */, 8937 ing_shd_size, NULL, NULL, 1)); 8938 } 8939 8940 /* set new guarantee */ 8941 /* the hw value may be changed by soc_th_mmu_config_res_limits_update 8942 * so read the register again in order to keep consistent */ 8943 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, entry)); 8944 soc_mem_field32_set(unit, mem, entry, fld_limit, (arg/granularity)); 8945 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, midx, entry)); 8946 8947 /* shared limits to be increased */ 8948 for (xpe = 0, update = 0; xpe < NUM_XPE(unit); xpe ++) { 8949 if ((xpe_map & (1 << xpe)) && (delta[xpe] < 0)) { 8950 ing_shd_size[xpe] -= delta[xpe]; 8951 update = 1; 8952 } 8953 } 8954 if (update) { 8955 BCM_IF_ERROR_RETURN 8956 (soc_th_mmu_config_res_limits_update(unit, 1 /* ing */, 8957 ing_shd_size, NULL, NULL, 0)); 8958 } 8959 8960 sal_memcpy(_BCM_TH_MMU_INFO(unit)->ing_shared_limit, ing_shd_size, 8961 sizeof(ing_shd_size)); 8962 8963 if (type == bcmCosqControlIngressPortPGHeadroomLimitBytes) { 8964 reg = THDI_HDRM_BUFFER_CELL_LIMIT_HPr; 8965 for (xpe = 0; xpe < NUM_XPE(unit); xpe++) { 8966 if (xpe_map & ( 1 << xpe)) { 8967 BCM_IF_ERROR_RETURN( 8968 soc_tomahawk_xpe_reg32_get(unit, reg, xpe, -1, pool, ®val)); 8969 cur_hdrm = soc_reg_field_get(unit, reg, regval, LIMITf); 8970 cur_hdrm += delta[xpe]; 8971 if (cur_hdrm < 0 ){ 8972 return BCM_E_PARAM; 8973 } 8974 regval = 0; 8975 soc_reg_field_set(unit, reg, ®val, LIMITf, cur_hdrm); 8976 BCM_IF_ERROR_RETURN( 8977 soc_tomahawk_xpe_reg32_set(unit, reg, xpe, -1, pool, regval)); 8978 } 8979 } 8980 } 8981 } else { 8982 soc_mem_field32_set(unit, mem, entry, fld_limit, (arg/granularity)); 8983 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, midx, entry)); 8984 } 8985 8986 return BCM_E_NONE; 8987 } 8988 8989 /* 8990 * This function is used to get the 8991 * enable status of ingress PG or SP 8992 */ 8993 STATIC int 8994 _bcm_th_cosq_ing_res_enable_get(int unit, bcm_gport_t gport, 8995 bcm_cos_queue_t cosq, bcm_cosq_control_t type, 8996 int *arg) 8997 { 8998 bcm_port_t local_port; 8999 int midx; 9000 uint32 entry[SOC_MAX_MEM_WORDS]; 9001 soc_mem_t mem = INVALIDm, base_mem = INVALIDm; 9002 soc_field_t fld_en = INVALIDf; 9003 int pipe, port_pg; 9004 9005 if ((cosq < 0) || (cosq >= _TH_MMU_NUM_INT_PRI)) { 9006 /* Error. Input pri > Max Pri_Grp */ 9007 return BCM_E_PARAM; 9008 } 9009 9010 if (arg == NULL) { 9011 return BCM_E_PARAM; 9012 } 9013 9014 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 9015 BCM_GPORT_IS_SCHEDULER(gport) || 9016 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 9017 return BCM_E_PARAM; 9018 } 9019 9020 BCM_IF_ERROR_RETURN 9021 (_bcm_th_cosq_localport_resolve(unit, gport, &local_port)); 9022 if (!SOC_PORT_VALID(unit, local_port)) { 9023 return BCM_E_PORT; 9024 } 9025 9026 BCM_IF_ERROR_RETURN 9027 (_bcm_th_cosq_ing_pool_pg_pipe_get(unit, gport, cosq, 9028 &pipe, NULL, &port_pg, 9029 NULL)); 9030 9031 if (type == bcmCosqControlIngressPortPGGlobalHeadroomEnable) { 9032 base_mem = THDI_PORT_PG_CONFIGm; 9033 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 9034 /* get index for Port-PG */ 9035 midx = SOC_TH_MMU_PIPED_MEM_INDEX(unit, local_port, base_mem, port_pg); 9036 } else { 9037 return BCM_E_UNAVAIL; 9038 } 9039 9040 if (midx < 0) { 9041 return BCM_E_PARAM; 9042 } 9043 9044 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, entry)); 9045 9046 switch (type) { 9047 case bcmCosqControlIngressPortPGGlobalHeadroomEnable: 9048 fld_en = PG_GBL_HDRM_ENf; 9049 break; 9050 /* coverity[dead_error_begin] */ 9051 default: 9052 return BCM_E_UNAVAIL; 9053 } 9054 9055 *arg = soc_mem_field32_get(unit, mem, entry, fld_en); 9056 9057 return BCM_E_NONE; 9058 } 9059 9060 STATIC int 9061 _bcm_th_cosq_ing_res_enable_set(int unit, bcm_gport_t gport, 9062 bcm_cos_queue_t cosq, bcm_cosq_control_t type, 9063 int arg) 9064 { 9065 bcm_port_t local_port; 9066 int midx; 9067 uint32 max_val; 9068 uint32 entry[SOC_MAX_MEM_WORDS]; 9069 soc_mem_t mem = INVALIDm, base_mem = INVALIDm; 9070 soc_field_t fld_en = INVALIDf; 9071 int pipe, port_pg; 9072 9073 if ((cosq < 0) || (cosq >= _TH_MMU_NUM_INT_PRI)) { 9074 /* Error. Input pri > Max Pri_Grp */ 9075 return BCM_E_PARAM; 9076 } 9077 9078 if (arg < 0) { 9079 return BCM_E_PARAM; 9080 } 9081 9082 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 9083 BCM_GPORT_IS_SCHEDULER(gport) || 9084 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 9085 return BCM_E_PARAM; 9086 } 9087 9088 BCM_IF_ERROR_RETURN 9089 (_bcm_th_cosq_localport_resolve(unit, gport, &local_port)); 9090 if (!SOC_PORT_VALID(unit, local_port)) { 9091 return BCM_E_PORT; 9092 } 9093 9094 BCM_IF_ERROR_RETURN 9095 (_bcm_th_cosq_ing_pool_pg_pipe_get(unit, gport, cosq, 9096 &pipe, NULL, &port_pg, 9097 NULL)); 9098 9099 if (type == bcmCosqControlIngressPortPGGlobalHeadroomEnable) { 9100 base_mem = THDI_PORT_PG_CONFIGm; 9101 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 9102 /* get index for Port-PG */ 9103 midx = SOC_TH_MMU_PIPED_MEM_INDEX(unit, local_port, base_mem, port_pg); 9104 } else { 9105 return BCM_E_UNAVAIL; 9106 } 9107 9108 if (midx < 0) { 9109 return BCM_E_PARAM; 9110 } 9111 9112 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, entry)); 9113 9114 switch (type) { 9115 case bcmCosqControlIngressPortPGGlobalHeadroomEnable: 9116 fld_en = PG_GBL_HDRM_ENf; 9117 break; 9118 /* coverity[dead_error_begin] */ 9119 default: 9120 return BCM_E_UNAVAIL; 9121 } 9122 9123 /* Check for min/max values */ 9124 max_val = (1 << soc_mem_field_length(unit, mem, fld_en)) - 1; 9125 if ((arg < 0) || (arg > max_val)) { 9126 return BCM_E_PARAM; 9127 } 9128 9129 if (type == bcmCosqControlIngressPortPGGlobalHeadroomEnable) { 9130 soc_mem_field32_set(unit, mem, entry, fld_en, arg ? 1 : 0); 9131 /* coverity[negative_returns] */ 9132 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, midx, entry)); 9133 } 9134 9135 return BCM_E_NONE; 9136 } 9137 9138 /* 9139 * This function is used to set headroom pool 9140 * or shared pool for given Ingress [Port, Priority] 9141 */ 9142 STATIC int 9143 _bcm_th_cosq_ing_pool_set(int unit, bcm_gport_t gport, bcm_cos_t pri, 9144 bcm_cosq_control_t type, int arg) 9145 { 9146 int local_port; 9147 uint32 rval; 9148 int pri_grp; 9149 static const soc_field_t prigroup_spid_field[] = { 9150 PG0_SPIDf, PG1_SPIDf, PG2_SPIDf, PG3_SPIDf, 9151 PG4_SPIDf, PG5_SPIDf, PG6_SPIDf, PG7_SPIDf 9152 }; 9153 static const soc_field_t prigroup_hpid_field[] = { 9154 PG0_HPIDf, PG1_HPIDf, PG2_HPIDf, PG3_HPIDf, 9155 PG4_HPIDf, PG5_HPIDf, PG6_HPIDf, PG7_HPIDf 9156 }; 9157 9158 if((arg < 0) || (arg >= _TH_MMU_NUM_POOL)) { 9159 return BCM_E_PARAM; 9160 } 9161 9162 if ((pri < 0) || (pri >= _TH_MMU_NUM_INT_PRI)) { 9163 /* Error. Input pri > Max Pri_Grp */ 9164 return BCM_E_PARAM; 9165 } 9166 9167 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 9168 BCM_GPORT_IS_SCHEDULER(gport) || 9169 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 9170 return BCM_E_PARAM; 9171 } 9172 9173 BCM_IF_ERROR_RETURN 9174 (_bcm_th_cosq_localport_resolve(unit, gport, &local_port)); 9175 9176 if (!SOC_PORT_VALID(unit, local_port)) { 9177 return BCM_E_PORT; 9178 } 9179 9180 BCM_IF_ERROR_RETURN 9181 (_bcm_th_cosq_ingress_pg_get(unit, gport, pri, &pri_grp, &pri_grp)); 9182 9183 /* coverity fix : pri_grp can take value from 0 to 7 */ 9184 if ((pri_grp < 0) || (pri_grp >= _TH_MMU_NUM_PG)) { 9185 return BCM_E_PARAM; 9186 } 9187 9188 if (type == bcmCosqControlIngressPool) { 9189 SOC_IF_ERROR_RETURN(READ_THDI_PORT_PG_SPIDr(unit, local_port, &rval)); 9190 soc_reg_field_set(unit, THDI_PORT_PG_SPIDr, &rval, 9191 prigroup_spid_field[pri_grp],arg); 9192 BCM_IF_ERROR_RETURN(WRITE_THDI_PORT_PG_SPIDr(unit, local_port, rval)); 9193 } else if (type == bcmCosqControlIngressHeadroomPool) { 9194 SOC_IF_ERROR_RETURN(READ_THDI_HDRM_PORT_PG_HPIDr(unit, local_port, &rval)); 9195 soc_reg_field_set(unit, THDI_HDRM_PORT_PG_HPIDr, &rval, 9196 prigroup_hpid_field[pri_grp], arg); 9197 BCM_IF_ERROR_RETURN(WRITE_THDI_HDRM_PORT_PG_HPIDr(unit, local_port, rval)); 9198 } else { 9199 return BCM_E_PARAM; 9200 } 9201 return BCM_E_NONE; 9202 } 9203 9204 STATIC int 9205 _bcm_th_cosq_ing_pool_get(int unit, bcm_gport_t gport, 9206 bcm_cos_t pri, 9207 bcm_cosq_control_t type, int *arg) 9208 { 9209 int pool_start_idx = 0, pool_end_idx = 0; 9210 9211 if (arg == NULL) { 9212 return BCM_E_PARAM; 9213 } 9214 9215 if ((pri < 0) || (pri >= _TH_MMU_NUM_INT_PRI)) { 9216 /* Error. Input pri > Max Pri_Grp */ 9217 return BCM_E_PARAM; 9218 } 9219 9220 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 9221 BCM_GPORT_IS_SCHEDULER(gport) || 9222 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 9223 return BCM_E_PARAM; 9224 } 9225 9226 if (type == bcmCosqControlIngressPool) { 9227 BCM_IF_ERROR_RETURN( 9228 _bcm_th_cosq_ingress_sp_get(unit, gport, pri, 9229 &pool_start_idx, 9230 &pool_end_idx)); 9231 } else if (type == bcmCosqControlIngressHeadroomPool) { 9232 BCM_IF_ERROR_RETURN( 9233 _bcm_th_cosq_ingress_hdrm_pool_get(unit, gport, pri, 9234 &pool_start_idx, 9235 &pool_end_idx)); 9236 } else { 9237 return BCM_E_PARAM; 9238 } 9239 *arg = pool_start_idx; 9240 return BCM_E_NONE; 9241 } 9242 9243 STATIC int 9244 _bcm_th_cosq_egr_pool_set(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 9245 bcm_cosq_buffer_id_t buffer, 9246 bcm_cosq_control_t type, int arg) 9247 { 9248 bcm_port_t local_port; 9249 int startq, pool, midx; 9250 uint32 max_val; 9251 uint32 entry[SOC_MAX_MEM_WORDS]; 9252 uint32 entry2[SOC_MAX_MEM_WORDS]; 9253 soc_mem_t base_mem = INVALIDm, base_mem2 = INVALIDm; 9254 soc_mem_t mem = INVALIDm, mem2 = INVALIDm; 9255 soc_field_t fld_limit = INVALIDf; 9256 int granularity = 1, pipe; 9257 9258 if (arg < 0) { 9259 return BCM_E_PARAM; 9260 } 9261 9262 BCM_IF_ERROR_RETURN 9263 (_bcm_th_cosq_index_resolve(unit, gport, cosq, 9264 _BCM_TH_COSQ_INDEX_STYLE_EGR_POOL, 9265 &local_port, &pool, NULL)); 9266 9267 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 9268 9269 base_mem = MMU_THDM_DB_PORTSP_CONFIGm; 9270 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 9271 9272 if (type == bcmCosqControlEgressPoolLimitEnable) { 9273 midx = SOC_TH_MMU_PIPED_MEM_INDEX(unit, local_port, base_mem, pool); 9274 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, 9275 midx, entry)); 9276 9277 soc_mem_field32_set(unit, mem, entry, SHARED_LIMIT_ENABLEf, !!arg); 9278 9279 return soc_mem_write(unit, mem, MEM_BLOCK_ALL, midx, entry); 9280 } 9281 if (type == bcmCosqControlEgressPool || type == bcmCosqControlUCEgressPool || 9282 type == bcmCosqControlMCEgressPool) { 9283 if((arg < 0) || (arg >= _TH_MMU_NUM_POOL)) { 9284 return BCM_E_PARAM; 9285 } 9286 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 9287 if (type != bcmCosqControlEgressPool) { 9288 return BCM_E_PARAM; 9289 } 9290 /* regular unicast queue */ 9291 BCM_IF_ERROR_RETURN 9292 (_bcm_th_cosq_index_resolve(unit, gport, cosq, 9293 _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE, 9294 &local_port, &startq, NULL)); 9295 base_mem = MMU_THDU_Q_TO_QGRP_MAPm; 9296 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 9297 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 9298 if (type != bcmCosqControlEgressPool) { 9299 return BCM_E_PARAM; 9300 } 9301 BCM_IF_ERROR_RETURN 9302 (_bcm_th_cosq_index_resolve(unit, gport, cosq, 9303 _BCM_TH_COSQ_INDEX_STYLE_MCAST_QUEUE, 9304 &local_port, &startq, NULL)); 9305 base_mem = MMU_THDM_MCQE_QUEUE_CONFIGm; 9306 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 9307 base_mem2 = MMU_THDM_DB_QUEUE_CONFIGm; 9308 mem2 = SOC_MEM_UNIQUE_ACC(unit, base_mem2)[pipe]; 9309 } else { /* local port */ 9310 if (type == bcmCosqControlUCEgressPool) { 9311 BCM_IF_ERROR_RETURN 9312 (_bcm_th_cosq_index_resolve(unit, gport, cosq, 9313 _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE, 9314 &local_port, &startq, NULL)); 9315 base_mem = MMU_THDU_Q_TO_QGRP_MAPm; 9316 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 9317 } else { 9318 BCM_IF_ERROR_RETURN 9319 (_bcm_th_cosq_index_resolve(unit, gport, cosq, 9320 _BCM_TH_COSQ_INDEX_STYLE_MCAST_QUEUE, 9321 &local_port, &startq, NULL)); 9322 base_mem = MMU_THDM_MCQE_QUEUE_CONFIGm; 9323 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 9324 base_mem2 = MMU_THDM_DB_QUEUE_CONFIGm; 9325 mem2 = SOC_MEM_UNIQUE_ACC(unit, base_mem2)[pipe]; 9326 } 9327 } 9328 9329 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 9330 soc_mem_field32_set(unit, mem, entry, Q_SPIDf, arg); 9331 9332 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 9333 if (mem2 != INVALIDm) { 9334 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem2, MEM_BLOCK_ALL, startq, entry2)); 9335 soc_mem_field32_set(unit, mem2, entry2, Q_SPIDf, arg); 9336 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem2, MEM_BLOCK_ALL, startq, entry2)); 9337 } 9338 return BCM_E_NONE; 9339 } 9340 9341 arg = (arg + _TH_MMU_BYTES_PER_CELL - 1) / _TH_MMU_BYTES_PER_CELL; 9342 9343 /* per service pool settings */ 9344 if (type == bcmCosqControlEgressPoolSharedLimitBytes || 9345 type == bcmCosqControlEgressPoolResumeLimitBytes || 9346 type == bcmCosqControlEgressPoolYellowSharedLimitBytes || 9347 type == bcmCosqControlEgressPoolYellowResumeLimitBytes || 9348 type == bcmCosqControlEgressPoolRedSharedLimitBytes || 9349 type == bcmCosqControlEgressPoolRedResumeLimitBytes || 9350 type == bcmCosqControlEgressPoolHighCongestionLimitBytes || 9351 type == bcmCosqControlEgressPoolLowCongestionLimitBytes) { 9352 int xpe, xpe_map; 9353 uint32 rval; 9354 soc_reg_t reg; 9355 soc_reg_t wred_cng_lmt[4] = { 9356 WRED_POOL_INST_CONG_LIMIT_0r, 9357 WRED_POOL_INST_CONG_LIMIT_1r, 9358 WRED_POOL_INST_CONG_LIMIT_2r, 9359 WRED_POOL_INST_CONG_LIMIT_3r, 9360 }; 9361 9362 switch (type) { 9363 case bcmCosqControlEgressPoolSharedLimitBytes: 9364 reg = MMU_THDM_DB_POOL_SHARED_LIMITr; 9365 fld_limit = SHARED_LIMITf; 9366 granularity = 1; 9367 break; 9368 case bcmCosqControlEgressPoolResumeLimitBytes: 9369 reg = MMU_THDM_DB_POOL_RESUME_LIMITr; 9370 fld_limit = RESUME_LIMITf; 9371 granularity = 8; 9372 break; 9373 case bcmCosqControlEgressPoolYellowSharedLimitBytes: 9374 reg = MMU_THDM_DB_POOL_YELLOW_SHARED_LIMITr; 9375 fld_limit = YELLOW_SHARED_LIMITf; 9376 granularity = 8; 9377 break; 9378 case bcmCosqControlEgressPoolYellowResumeLimitBytes: 9379 reg = MMU_THDM_DB_POOL_YELLOW_RESUME_LIMITr; 9380 fld_limit = YELLOW_RESUME_LIMITf; 9381 granularity = 8; 9382 break; 9383 case bcmCosqControlEgressPoolRedSharedLimitBytes: 9384 reg = MMU_THDM_DB_POOL_RED_SHARED_LIMITr; 9385 fld_limit = RED_SHARED_LIMITf; 9386 granularity = 8; 9387 break; 9388 case bcmCosqControlEgressPoolRedResumeLimitBytes: 9389 reg = MMU_THDM_DB_POOL_RED_RESUME_LIMITr; 9390 fld_limit = RED_RESUME_LIMITf; 9391 granularity = 8; 9392 break; 9393 case bcmCosqControlEgressPoolHighCongestionLimitBytes: 9394 reg = wred_cng_lmt[pool]; 9395 fld_limit = POOL_HI_CONG_LIMITf; 9396 pool = -1; 9397 granularity = 1; 9398 break; 9399 case bcmCosqControlEgressPoolLowCongestionLimitBytes: 9400 reg = wred_cng_lmt[pool]; 9401 fld_limit = POOL_LOW_CONG_LIMITf; 9402 pool = -1; 9403 granularity = 1; 9404 break; 9405 /* coverity[dead_error_begin] */ 9406 default: 9407 return BCM_E_UNAVAIL; 9408 } 9409 9410 /* These regs are chip unique, buffer = -1 writes on all 4 xpes. 9411 No need to do pipe-xpe checking */ 9412 xpe_map = SOC_INFO(unit).ipipe_xpe_map[0] | 9413 SOC_INFO(unit).ipipe_xpe_map[1]; 9414 if (buffer == BCM_COSQ_BUFFER_ID_INVALID) { 9415 xpe = -1; 9416 } else if (xpe_map & (1 << buffer)) { 9417 xpe = buffer; 9418 } else { 9419 return BCM_E_PARAM; 9420 } 9421 9422 SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_get 9423 (unit, reg, xpe, -1, pool, &rval)); 9424 9425 /* Check for min/max values */ 9426 max_val = (1 << soc_reg_field_length(unit, reg, fld_limit)) - 1; 9427 if ((arg < 0) || ((arg/granularity) > max_val)) { 9428 return BCM_E_PARAM; 9429 } else { 9430 soc_reg_field_set(unit, reg, &rval, fld_limit, (arg/granularity)); 9431 } 9432 9433 SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_set 9434 (unit, reg, xpe, -1, pool, rval)); 9435 9436 return BCM_E_NONE; 9437 } 9438 9439 /* per port settings */ 9440 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 9441 BCM_IF_ERROR_RETURN 9442 (_bcm_th_cosq_index_resolve(unit, gport, cosq, 9443 _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE, 9444 &local_port, &startq, NULL)); 9445 base_mem = MMU_THDU_CONFIG_QUEUEm; 9446 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 9447 base_mem2 = MMU_THDU_Q_TO_QGRP_MAPm; 9448 mem2 = SOC_MEM_UNIQUE_ACC(unit, base_mem2)[pipe]; 9449 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 9450 BCM_IF_ERROR_RETURN 9451 (_bcm_th_cosq_index_resolve(unit, gport, cosq, 9452 _BCM_TH_COSQ_INDEX_STYLE_MCAST_QUEUE, 9453 &local_port, &startq, NULL)); 9454 base_mem = MMU_THDM_DB_QUEUE_CONFIGm; 9455 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 9456 } else { 9457 if (soc_property_get(unit, spn_PORT_UC_MC_ACCOUNTING_COMBINE, 0) == 0) { 9458 /* Need to have the UC_MC_Combine config enabled */ 9459 return BCM_E_PARAM; 9460 } 9461 base_mem = MMU_THDM_DB_PORTSP_CONFIGm; 9462 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 9463 startq = SOC_TH_MMU_PIPED_MEM_INDEX(unit, local_port, base_mem, pool); 9464 } 9465 9466 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 9467 9468 if (mem2 != INVALIDm) { 9469 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem2, MEM_BLOCK_ALL, startq, entry2)); 9470 } 9471 9472 switch (type) { 9473 case bcmCosqControlEgressPoolLimitBytes: 9474 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 9475 fld_limit = Q_SHARED_LIMIT_CELLf; 9476 9477 if (mem2 != INVALIDm) { 9478 soc_mem_field32_set(unit, mem2, entry2, Q_LIMIT_ENABLEf, 1); 9479 } 9480 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 9481 fld_limit = Q_SHARED_LIMITf; 9482 soc_mem_field32_set(unit, mem, entry, Q_LIMIT_ENABLEf, 1); 9483 } else { 9484 fld_limit = SHARED_LIMITf; 9485 soc_mem_field32_set(unit, mem, entry, SHARED_LIMIT_ENABLEf, 1); 9486 } 9487 granularity = 1; 9488 break; 9489 case bcmCosqControlEgressPoolYellowLimitBytes: 9490 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 9491 fld_limit = LIMIT_YELLOW_CELLf; 9492 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 9493 fld_limit = YELLOW_SHARED_LIMITf; 9494 } else { 9495 fld_limit = YELLOW_SHARED_LIMITf; 9496 } 9497 granularity = 8; 9498 break; 9499 case bcmCosqControlEgressPoolRedLimitBytes: 9500 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 9501 fld_limit = LIMIT_RED_CELLf; 9502 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 9503 fld_limit = RED_SHARED_LIMITf; 9504 } else { 9505 fld_limit = RED_SHARED_LIMITf; 9506 } 9507 granularity = 8; 9508 break; 9509 default: 9510 return BCM_E_UNAVAIL; 9511 } 9512 9513 /* Check for min/max values */ 9514 max_val = (1 << soc_mem_field_length(unit, mem, fld_limit)) - 1; 9515 if ((arg < 0) || ((arg/granularity) > max_val)) { 9516 return BCM_E_PARAM; 9517 } else { 9518 soc_mem_field32_set(unit, mem, entry, fld_limit, (arg/granularity)); 9519 } 9520 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 9521 9522 if (mem2 != INVALIDm) { 9523 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem2, MEM_BLOCK_ALL, startq, entry2)); 9524 } 9525 return BCM_E_NONE; 9526 } 9527 9528 STATIC int 9529 _bcm_th_cosq_egr_pool_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 9530 bcm_cosq_buffer_id_t buffer, 9531 bcm_cosq_control_t type, int *arg) 9532 { 9533 bcm_port_t local_port; 9534 int startq, pool, midx, pipe; 9535 uint32 entry[SOC_MAX_MEM_WORDS]; 9536 soc_mem_t mem, base_mem; 9537 int granularity = 1; 9538 9539 if (!arg) { 9540 return BCM_E_PARAM; 9541 } 9542 9543 BCM_IF_ERROR_RETURN 9544 (_bcm_th_cosq_index_resolve(unit, gport, cosq, 9545 _BCM_TH_COSQ_INDEX_STYLE_EGR_POOL, 9546 &local_port, &pool, NULL)); 9547 9548 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 9549 9550 if (type == bcmCosqControlEgressPool || type == bcmCosqControlUCEgressPool || 9551 type == bcmCosqControlMCEgressPool) { 9552 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 9553 if (type != bcmCosqControlEgressPool) { 9554 return BCM_E_PARAM; 9555 } 9556 /* regular unicast queue */ 9557 BCM_IF_ERROR_RETURN 9558 (_bcm_th_cosq_index_resolve(unit, gport, cosq, 9559 _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE, 9560 &local_port, &startq, NULL)); 9561 base_mem = MMU_THDU_Q_TO_QGRP_MAPm; 9562 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 9563 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 9564 if (type != bcmCosqControlEgressPool) { 9565 return BCM_E_PARAM; 9566 } 9567 BCM_IF_ERROR_RETURN 9568 (_bcm_th_cosq_index_resolve(unit, gport, cosq, 9569 _BCM_TH_COSQ_INDEX_STYLE_MCAST_QUEUE, 9570 &local_port, &startq, NULL)); 9571 base_mem = MMU_THDM_MCQE_QUEUE_CONFIGm; 9572 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 9573 } else { /* local port */ 9574 if (type == bcmCosqControlUCEgressPool) { 9575 BCM_IF_ERROR_RETURN 9576 (_bcm_th_cosq_index_resolve(unit, gport, cosq, 9577 _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE, 9578 &local_port, &startq, NULL)); 9579 base_mem = MMU_THDU_Q_TO_QGRP_MAPm; 9580 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 9581 } else { 9582 BCM_IF_ERROR_RETURN 9583 (_bcm_th_cosq_index_resolve(unit, gport, cosq, 9584 _BCM_TH_COSQ_INDEX_STYLE_MCAST_QUEUE, 9585 &local_port, &startq, NULL)); 9586 base_mem = MMU_THDM_MCQE_QUEUE_CONFIGm; 9587 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 9588 } 9589 } 9590 9591 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 9592 *arg = soc_mem_field32_get(unit, mem, entry, Q_SPIDf); 9593 return BCM_E_NONE; 9594 } 9595 9596 /* per service pool settings */ 9597 if (type == bcmCosqControlEgressPoolSharedLimitBytes || 9598 type == bcmCosqControlEgressPoolResumeLimitBytes || 9599 type == bcmCosqControlEgressPoolYellowSharedLimitBytes || 9600 type == bcmCosqControlEgressPoolYellowResumeLimitBytes || 9601 type == bcmCosqControlEgressPoolRedSharedLimitBytes || 9602 type == bcmCosqControlEgressPoolRedResumeLimitBytes || 9603 type == bcmCosqControlEgressPoolHighCongestionLimitBytes || 9604 type == bcmCosqControlEgressPoolLowCongestionLimitBytes) { 9605 int xpe, xpe_map; 9606 uint32 rval; 9607 soc_reg_t reg; 9608 soc_reg_t wred_cng_lmt[4] = { 9609 WRED_POOL_INST_CONG_LIMIT_0r, 9610 WRED_POOL_INST_CONG_LIMIT_1r, 9611 WRED_POOL_INST_CONG_LIMIT_2r, 9612 WRED_POOL_INST_CONG_LIMIT_3r, 9613 }; 9614 soc_field_t fld_limit = INVALIDf; 9615 9616 switch (type) { 9617 case bcmCosqControlEgressPoolSharedLimitBytes: 9618 reg = MMU_THDM_DB_POOL_SHARED_LIMITr; 9619 fld_limit = SHARED_LIMITf; 9620 granularity = 1; 9621 break; 9622 case bcmCosqControlEgressPoolResumeLimitBytes: 9623 reg = MMU_THDM_DB_POOL_RESUME_LIMITr; 9624 fld_limit = RESUME_LIMITf; 9625 granularity = 8; 9626 break; 9627 case bcmCosqControlEgressPoolYellowSharedLimitBytes: 9628 reg = MMU_THDM_DB_POOL_YELLOW_SHARED_LIMITr; 9629 fld_limit = YELLOW_SHARED_LIMITf; 9630 granularity = 8; 9631 break; 9632 case bcmCosqControlEgressPoolYellowResumeLimitBytes: 9633 reg = MMU_THDM_DB_POOL_YELLOW_RESUME_LIMITr; 9634 fld_limit = YELLOW_RESUME_LIMITf; 9635 granularity = 8; 9636 break; 9637 case bcmCosqControlEgressPoolRedSharedLimitBytes: 9638 reg = MMU_THDM_DB_POOL_RED_SHARED_LIMITr; 9639 fld_limit = RED_SHARED_LIMITf; 9640 granularity = 8; 9641 break; 9642 case bcmCosqControlEgressPoolRedResumeLimitBytes: 9643 reg = MMU_THDM_DB_POOL_RED_RESUME_LIMITr; 9644 fld_limit = RED_RESUME_LIMITf; 9645 granularity = 8; 9646 break; 9647 case bcmCosqControlEgressPoolHighCongestionLimitBytes: 9648 reg = wred_cng_lmt[pool]; 9649 fld_limit = POOL_HI_CONG_LIMITf; 9650 pool = -1; 9651 granularity = 1; 9652 break; 9653 case bcmCosqControlEgressPoolLowCongestionLimitBytes: 9654 reg = wred_cng_lmt[pool]; 9655 fld_limit = POOL_LOW_CONG_LIMITf; 9656 pool = -1; 9657 granularity = 1; 9658 break; 9659 /* coverity[dead_error_begin] */ 9660 default: 9661 return BCM_E_UNAVAIL; 9662 } 9663 9664 /* These regs are chip unique, buffer = -1 writes on all 4 xpes. 9665 No need to do pipe-xpe checking */ 9666 xpe_map = SOC_INFO(unit).ipipe_xpe_map[0] | 9667 SOC_INFO(unit).ipipe_xpe_map[1]; 9668 if (buffer == BCM_COSQ_BUFFER_ID_INVALID) { 9669 xpe_map = SOC_INFO(unit).epipe_xpe_map[pipe]; 9670 /*find the first valid xpe*/ 9671 for (xpe = 0; xpe < NUM_XPE(unit); xpe++) { 9672 if ((xpe_map & (1 << xpe))) { 9673 break; 9674 } 9675 } 9676 if(xpe == NUM_XPE(unit)) { 9677 return BCM_E_INTERNAL; 9678 } 9679 } else if (xpe_map & (1 << buffer)) { 9680 xpe = buffer; 9681 } else { 9682 return BCM_E_PARAM; 9683 } 9684 9685 SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_get 9686 (unit, reg, xpe, -1, pool, &rval)); 9687 9688 *arg = soc_reg_field_get(unit, reg, rval, fld_limit); 9689 *arg = (*arg) * granularity * _TH_MMU_BYTES_PER_CELL; 9690 9691 return BCM_E_NONE; 9692 } 9693 9694 base_mem = MMU_THDM_DB_PORTSP_CONFIGm; 9695 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 9696 9697 if (type == bcmCosqControlEgressPoolLimitEnable) { 9698 midx = SOC_TH_MMU_PIPED_MEM_INDEX(unit, local_port, base_mem, pool); 9699 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, 9700 midx, entry)); 9701 9702 *arg = soc_mem_field32_get(unit, mem, entry, SHARED_LIMIT_ENABLEf); 9703 return BCM_E_NONE; 9704 } 9705 9706 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 9707 BCM_IF_ERROR_RETURN 9708 (_bcm_th_cosq_index_resolve(unit, gport, cosq, 9709 _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE, 9710 &local_port, &startq, NULL)); 9711 base_mem = MMU_THDU_CONFIG_QUEUEm; 9712 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 9713 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 9714 BCM_IF_ERROR_RETURN 9715 (_bcm_th_cosq_index_resolve(unit, gport, cosq, 9716 _BCM_TH_COSQ_INDEX_STYLE_MCAST_QUEUE, 9717 &local_port, &startq, NULL)); 9718 9719 base_mem = MMU_THDM_DB_QUEUE_CONFIGm; 9720 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 9721 } else { 9722 if (soc_property_get(unit, spn_PORT_UC_MC_ACCOUNTING_COMBINE, 0) == 0) { 9723 /* Need to have the UC_MC_Combine config enabled */ 9724 return BCM_E_PARAM; 9725 } 9726 base_mem = MMU_THDM_DB_PORTSP_CONFIGm; 9727 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 9728 startq = SOC_TH_MMU_PIPED_MEM_INDEX(unit, local_port, base_mem, pool); 9729 } 9730 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, 9731 startq, entry)); 9732 9733 switch (type) { 9734 case bcmCosqControlEgressPoolLimitBytes: 9735 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 9736 *arg = soc_mem_field32_get(unit, mem, entry, Q_SHARED_LIMIT_CELLf); 9737 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 9738 *arg = soc_mem_field32_get(unit, mem, entry, Q_SHARED_LIMITf); 9739 } else { 9740 *arg = soc_mem_field32_get(unit, mem, entry, SHARED_LIMITf); 9741 } 9742 granularity = 1; 9743 break; 9744 case bcmCosqControlEgressPoolYellowLimitBytes: 9745 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 9746 *arg = soc_mem_field32_get(unit, mem, entry, LIMIT_YELLOW_CELLf); 9747 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 9748 *arg = soc_mem_field32_get(unit, mem, entry, YELLOW_SHARED_LIMITf); 9749 } else { 9750 *arg = soc_mem_field32_get(unit, mem, entry, YELLOW_SHARED_LIMITf); 9751 } 9752 granularity = 8; 9753 break; 9754 case bcmCosqControlEgressPoolRedLimitBytes: 9755 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 9756 *arg = soc_mem_field32_get(unit, mem, entry, LIMIT_RED_CELLf); 9757 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 9758 *arg = soc_mem_field32_get(unit, mem, entry, RED_SHARED_LIMITf); 9759 } else { 9760 *arg = soc_mem_field32_get(unit, mem, entry, RED_SHARED_LIMITf); 9761 } 9762 granularity = 8; 9763 break; 9764 default: 9765 return BCM_E_UNAVAIL; 9766 } 9767 *arg = (*arg) * granularity * _TH_MMU_BYTES_PER_CELL; 9768 return BCM_E_NONE; 9769 } 9770 9771 STATIC int 9772 _bcm_th_cosq_egr_port_pool_set(int unit, bcm_gport_t gport, 9773 bcm_cos_queue_t cosq, 9774 bcm_cosq_control_t type, int arg) 9775 { 9776 bcm_port_t local_port; 9777 uint32 max_val; 9778 uint32 entry[SOC_MAX_MEM_WORDS]; 9779 soc_mem_t mem = INVALIDm, base_mem = INVALIDm; 9780 soc_field_t fld_limit = INVALIDf; 9781 int granularity = 1; 9782 int pool, midx, pipe; 9783 9784 if (arg < 0) { 9785 return BCM_E_PARAM; 9786 } 9787 9788 BCM_IF_ERROR_RETURN 9789 (_bcm_th_cosq_index_resolve(unit, gport, cosq, 9790 _BCM_TH_COSQ_INDEX_STYLE_EGR_POOL, 9791 &local_port, &pool, NULL)); 9792 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 9793 9794 if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 9795 base_mem = MMU_THDM_DB_PORTSP_CONFIGm; 9796 } else { 9797 if ((type == bcmCosqControlEgressPortPoolRedResumeBytes) || 9798 (type == bcmCosqControlEgressPortPoolYellowResumeBytes) || 9799 (type == bcmCosqControlEgressPortPoolSharedResumeBytes)) { 9800 base_mem = MMU_THDU_RESUME_PORTm; 9801 } else { 9802 base_mem = MMU_THDU_CONFIG_PORTm; 9803 } 9804 } 9805 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 9806 midx = SOC_TH_MMU_PIPED_MEM_INDEX(unit, local_port, base_mem, pool); 9807 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, entry)); 9808 9809 switch (type) { 9810 case bcmCosqControlEgressPortPoolYellowLimitBytes: 9811 if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 9812 fld_limit = YELLOW_SHARED_LIMITf; 9813 } else { 9814 fld_limit = YELLOW_LIMITf; 9815 } 9816 granularity = 8; 9817 break; 9818 case bcmCosqControlEgressPortPoolRedLimitBytes: 9819 if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 9820 fld_limit = RED_SHARED_LIMITf; 9821 } else { 9822 fld_limit = RED_LIMITf; 9823 } 9824 granularity = 8; 9825 break; 9826 case bcmCosqControlEgressPortPoolSharedLimitBytes: 9827 fld_limit = SHARED_LIMITf; 9828 granularity = 8; 9829 break; 9830 case bcmCosqControlEgressPortPoolRedResumeBytes: 9831 fld_limit = RED_RESUMEf; 9832 granularity = 8; 9833 break; 9834 case bcmCosqControlEgressPortPoolYellowResumeBytes: 9835 fld_limit = YELLOW_RESUMEf; 9836 granularity = 8; 9837 break; 9838 case bcmCosqControlEgressPortPoolSharedResumeBytes: 9839 fld_limit = SHARED_RESUMEf; 9840 granularity = 8; 9841 break; 9842 default: 9843 return BCM_E_UNAVAIL; 9844 } 9845 9846 arg = (arg + _TH_MMU_BYTES_PER_CELL - 1) / _TH_MMU_BYTES_PER_CELL; 9847 9848 /* Check for min/max values */ 9849 max_val = (1 << soc_mem_field_length(unit, mem, fld_limit)) - 1; 9850 if ((arg < 0) || ((arg/granularity) > max_val)) { 9851 return BCM_E_PARAM; 9852 } else { 9853 soc_mem_field32_set(unit, mem, entry, fld_limit, (arg/granularity)); 9854 } 9855 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, midx, entry)); 9856 9857 return BCM_E_NONE; 9858 } 9859 9860 STATIC int 9861 _bcm_th_cosq_egr_port_pool_get(int unit, bcm_gport_t gport, 9862 bcm_cos_queue_t cosq, 9863 bcm_cosq_control_t type, int *arg) 9864 { 9865 bcm_port_t local_port; 9866 uint32 entry[SOC_MAX_MEM_WORDS]; 9867 soc_mem_t mem = INVALIDm, base_mem = INVALIDm; 9868 int granularity = 1; 9869 int pool, midx, pipe; 9870 9871 if (!arg) { 9872 return BCM_E_PARAM; 9873 } 9874 9875 BCM_IF_ERROR_RETURN 9876 (_bcm_th_cosq_index_resolve(unit, gport, cosq, 9877 _BCM_TH_COSQ_INDEX_STYLE_EGR_POOL, 9878 &local_port, &pool, NULL)); 9879 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 9880 9881 if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 9882 base_mem = MMU_THDM_DB_PORTSP_CONFIGm; 9883 } else { 9884 if ((type == bcmCosqControlEgressPortPoolRedResumeBytes) || 9885 (type == bcmCosqControlEgressPortPoolYellowResumeBytes) || 9886 (type == bcmCosqControlEgressPortPoolSharedResumeBytes)) { 9887 base_mem = MMU_THDU_RESUME_PORTm; 9888 } else { 9889 base_mem = MMU_THDU_CONFIG_PORTm; 9890 } 9891 } 9892 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 9893 midx = SOC_TH_MMU_PIPED_MEM_INDEX(unit, local_port, base_mem, pool); 9894 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, entry)); 9895 9896 switch (type) { 9897 case bcmCosqControlEgressPortPoolYellowLimitBytes: 9898 if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 9899 *arg = soc_mem_field32_get(unit, mem, entry, YELLOW_SHARED_LIMITf); 9900 } else { 9901 *arg = soc_mem_field32_get(unit, mem, entry, YELLOW_LIMITf); 9902 } 9903 granularity = 8; 9904 break; 9905 case bcmCosqControlEgressPortPoolRedLimitBytes: 9906 if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 9907 *arg = soc_mem_field32_get(unit, mem, entry, RED_SHARED_LIMITf); 9908 } else { 9909 *arg = soc_mem_field32_get(unit, mem, entry, RED_LIMITf); 9910 } 9911 granularity = 8; 9912 break; 9913 case bcmCosqControlEgressPortPoolSharedLimitBytes: 9914 *arg = soc_mem_field32_get(unit, mem, entry, SHARED_LIMITf); 9915 granularity = 8; 9916 break; 9917 case bcmCosqControlEgressPortPoolRedResumeBytes: 9918 *arg = soc_mem_field32_get(unit, mem, entry, RED_RESUMEf); 9919 granularity = 8; 9920 break; 9921 case bcmCosqControlEgressPortPoolYellowResumeBytes: 9922 *arg = soc_mem_field32_get(unit, mem, entry, YELLOW_RESUMEf); 9923 granularity = 8; 9924 break; 9925 case bcmCosqControlEgressPortPoolSharedResumeBytes: 9926 *arg = soc_mem_field32_get(unit, mem, entry, YELLOW_RESUMEf); 9927 granularity = 8; 9928 break; 9929 default: 9930 return BCM_E_UNAVAIL; 9931 } 9932 9933 *arg = (*arg) * granularity * _TH_MMU_BYTES_PER_CELL; 9934 return BCM_E_NONE; 9935 } 9936 9937 STATIC int 9938 _bcm_th_cosq_dynamic_thresh_enable_get(int unit, 9939 bcm_gport_t gport, bcm_cos_queue_t cosq, 9940 bcm_cosq_control_t type, int *arg) 9941 { 9942 bcm_port_t local_port; 9943 int startq, pipe, from_cos, to_cos, ci, midx, port_pg; 9944 uint32 rval; 9945 uint32 entry[SOC_MAX_MEM_WORDS]; 9946 soc_mem_t mem = INVALIDm, base_mem = INVALIDm; 9947 soc_reg_t reg = INVALIDr; 9948 static const soc_reg_t prigroup_reg[] = { 9949 THDI_PORT_PRI_GRP0r, THDI_PORT_PRI_GRP1r 9950 }; 9951 static const soc_field_t prigroup_field[] = { 9952 PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf, 9953 PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf, 9954 PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf, 9955 PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf 9956 }; 9957 9958 if (!arg) { 9959 return BCM_E_PARAM; 9960 } 9961 9962 if (type == bcmCosqControlIngressPortPGSharedDynamicEnable) { 9963 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 9964 BCM_GPORT_IS_SCHEDULER(gport) || 9965 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 9966 return BCM_E_PARAM; 9967 } 9968 BCM_IF_ERROR_RETURN 9969 (_bcm_th_cosq_localport_resolve(unit, gport, &local_port)); 9970 if (local_port < 0) { 9971 return BCM_E_PORT; 9972 } 9973 if ((cosq < 0) || (cosq >= 16)) { 9974 return BCM_E_PARAM; 9975 } 9976 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 9977 9978 if ((cosq < 0) || (cosq >= _TH_MMU_NUM_INT_PRI)) { 9979 /* Error. Input pri > Max Pri_Grp */ 9980 /* coverity[dead_error_line] */ 9981 return BCM_E_PARAM; 9982 } 9983 9984 /* get PG for port using Port+Cos */ 9985 if (cosq < _TH_MMU_NUM_PG) { 9986 reg = prigroup_reg[0]; 9987 } else { 9988 reg = prigroup_reg[1]; 9989 } 9990 9991 SOC_IF_ERROR_RETURN 9992 (soc_reg32_get(unit, reg, local_port, 0, &rval)); 9993 port_pg = soc_reg_field_get(unit, reg, rval, prigroup_field[cosq]); 9994 base_mem = THDI_PORT_PG_CONFIGm; 9995 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 9996 /* get index for Port-PG */ 9997 midx = SOC_TH_MMU_PIPED_MEM_INDEX(unit, local_port, base_mem, port_pg); 9998 9999 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, 10000 midx, entry)); 10001 *arg = soc_mem_field32_get(unit, mem, entry, PG_SHARED_DYNAMICf); 10002 10003 } else if (type == bcmCosqControlEgressUCSharedDynamicEnable) { 10004 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 10005 BCM_IF_ERROR_RETURN 10006 (_bcm_th_cosq_index_resolve(unit, gport, cosq, 10007 _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE, 10008 &local_port, &startq, NULL)); 10009 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 10010 return BCM_E_PARAM; 10011 } else { 10012 if (cosq == BCM_COS_INVALID) { 10013 from_cos = to_cos = 0; 10014 } else { 10015 from_cos = to_cos = cosq; 10016 } 10017 10018 BCM_IF_ERROR_RETURN 10019 (_bcm_th_cosq_localport_resolve(unit, gport, &local_port)); 10020 if (local_port < 0) { 10021 return BCM_E_PORT; 10022 } 10023 for (ci = from_cos; ci <= to_cos; ci++) { 10024 BCM_IF_ERROR_RETURN 10025 (_bcm_th_cosq_index_resolve(unit, local_port, ci, 10026 _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE, 10027 NULL, &startq, NULL)); 10028 } 10029 } 10030 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 10031 base_mem = MMU_THDU_CONFIG_QUEUEm; 10032 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 10033 10034 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, 10035 startq, entry)); 10036 *arg = soc_mem_field32_get(unit, mem, entry, Q_LIMIT_DYNAMIC_CELLf); 10037 } else if (type == bcmCosqControlEgressMCSharedDynamicEnable) { 10038 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 10039 return BCM_E_PARAM; 10040 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 10041 BCM_IF_ERROR_RETURN 10042 (_bcm_th_cosq_index_resolve(unit, gport, cosq, 10043 _BCM_TH_COSQ_INDEX_STYLE_MCAST_QUEUE, 10044 &local_port, &startq, NULL)); 10045 } 10046 else { 10047 if (cosq == BCM_COS_INVALID) { 10048 from_cos = to_cos = 0; 10049 } else { 10050 from_cos = to_cos = cosq; 10051 } 10052 10053 BCM_IF_ERROR_RETURN 10054 (_bcm_th_cosq_localport_resolve(unit, gport, &local_port)); 10055 if (local_port < 0) { 10056 return BCM_E_PORT; 10057 } 10058 for (ci = from_cos; ci <= to_cos; ci++) { 10059 BCM_IF_ERROR_RETURN 10060 (_bcm_th_cosq_index_resolve(unit, local_port, ci, 10061 _BCM_TH_COSQ_INDEX_STYLE_MCAST_QUEUE, 10062 NULL, &startq, NULL)); 10063 } 10064 } 10065 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 10066 base_mem = MMU_THDM_DB_QUEUE_CONFIGm; 10067 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 10068 10069 BCM_IF_ERROR_RETURN 10070 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 10071 *arg = soc_mem_field32_get(unit, mem, entry, Q_LIMIT_DYNAMICf); 10072 } else { 10073 return BCM_E_PARAM; 10074 } 10075 10076 return BCM_E_NONE; 10077 } 10078 10079 STATIC int 10080 _bcm_th_cosq_alpha_set(int unit, 10081 bcm_gport_t gport, bcm_cos_queue_t cosq, 10082 bcm_cosq_control_drop_limit_alpha_value_t arg) 10083 { 10084 bcm_port_t local_port; 10085 int startq, midx, pipe; 10086 uint32 rval; 10087 uint32 entry[SOC_MAX_MEM_WORDS]; 10088 uint32 entry2[SOC_MAX_MEM_WORDS]; 10089 soc_mem_t base_mem = INVALIDm, base_mem2 = INVALIDm; 10090 soc_mem_t mem = INVALIDm, mem2 = INVALIDm; 10091 int alpha, dynamic_thresh_mode, port_pg; 10092 soc_reg_t reg = INVALIDr; 10093 static const soc_reg_t prigroup_reg[] = { 10094 THDI_PORT_PRI_GRP0r, THDI_PORT_PRI_GRP1r 10095 }; 10096 static const soc_field_t prigroup_field[] = { 10097 PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf, 10098 PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf, 10099 PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf, 10100 PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf 10101 }; 10102 int phy_port, mmu_port, local_mmu_port; 10103 10104 soc_info_t *si; 10105 si = &SOC_INFO(unit); 10106 10107 switch(arg) { 10108 case bcmCosqControlDropLimitAlpha_1_128: 10109 alpha = SOC_TH_COSQ_DROP_LIMIT_ALPHA_1_128; 10110 break; 10111 case bcmCosqControlDropLimitAlpha_1_64: 10112 alpha = SOC_TH_COSQ_DROP_LIMIT_ALPHA_1_64; 10113 break; 10114 case bcmCosqControlDropLimitAlpha_1_32: 10115 alpha = SOC_TH_COSQ_DROP_LIMIT_ALPHA_1_32; 10116 break; 10117 case bcmCosqControlDropLimitAlpha_1_16: 10118 alpha = SOC_TH_COSQ_DROP_LIMIT_ALPHA_1_16; 10119 break; 10120 case bcmCosqControlDropLimitAlpha_1_8: 10121 alpha = SOC_TH_COSQ_DROP_LIMIT_ALPHA_1_8; 10122 break; 10123 case bcmCosqControlDropLimitAlpha_1_4: 10124 alpha = SOC_TH_COSQ_DROP_LIMIT_ALPHA_1_4; 10125 break; 10126 case bcmCosqControlDropLimitAlpha_1_2: 10127 alpha = SOC_TH_COSQ_DROP_LIMIT_ALPHA_1_2; 10128 break; 10129 case bcmCosqControlDropLimitAlpha_1: 10130 alpha = SOC_TH_COSQ_DROP_LIMIT_ALPHA_1; 10131 break; 10132 case bcmCosqControlDropLimitAlpha_2: 10133 alpha = SOC_TH_COSQ_DROP_LIMIT_ALPHA_2; 10134 break; 10135 case bcmCosqControlDropLimitAlpha_4: 10136 alpha = SOC_TH_COSQ_DROP_LIMIT_ALPHA_4; 10137 break; 10138 case bcmCosqControlDropLimitAlpha_8: 10139 alpha = SOC_TH_COSQ_DROP_LIMIT_ALPHA_8; 10140 break; 10141 default: 10142 return BCM_E_PARAM; 10143 } 10144 10145 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 10146 BCM_IF_ERROR_RETURN 10147 (_bcm_th_cosq_dynamic_thresh_enable_get(unit, gport, cosq, 10148 bcmCosqControlEgressUCSharedDynamicEnable, 10149 &dynamic_thresh_mode)); 10150 if (!dynamic_thresh_mode){ 10151 return BCM_E_CONFIG; 10152 } 10153 10154 BCM_IF_ERROR_RETURN 10155 (_bcm_th_cosq_index_resolve(unit, gport, cosq, 10156 _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE, 10157 &local_port, &startq, NULL)); 10158 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 10159 10160 base_mem = MMU_THDU_CONFIG_QUEUEm; 10161 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 10162 10163 BCM_IF_ERROR_RETURN 10164 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 10165 soc_mem_field32_set(unit, mem, entry, 10166 Q_SHARED_ALPHA_CELLf, alpha); 10167 SOC_IF_ERROR_RETURN 10168 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 10169 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 10170 BCM_IF_ERROR_RETURN 10171 (_bcm_th_cosq_dynamic_thresh_enable_get(unit, gport, cosq, 10172 bcmCosqControlEgressMCSharedDynamicEnable, 10173 &dynamic_thresh_mode)); 10174 if (!dynamic_thresh_mode){ 10175 return BCM_E_CONFIG; 10176 } 10177 10178 BCM_IF_ERROR_RETURN 10179 (_bcm_th_cosq_index_resolve(unit, gport, cosq, 10180 _BCM_TH_COSQ_INDEX_STYLE_MCAST_QUEUE, 10181 &local_port, &startq, NULL)); 10182 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 10183 10184 base_mem = MMU_THDM_DB_QUEUE_CONFIGm; 10185 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 10186 10187 base_mem2 = MMU_THDM_MCQE_QUEUE_CONFIGm; 10188 mem2 = SOC_MEM_UNIQUE_ACC(unit, base_mem2)[pipe]; 10189 10190 BCM_IF_ERROR_RETURN 10191 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 10192 soc_mem_field32_set(unit, mem, entry, Q_SHARED_ALPHAf, alpha); 10193 SOC_IF_ERROR_RETURN 10194 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 10195 10196 BCM_IF_ERROR_RETURN 10197 (soc_mem_read(unit, mem2, MEM_BLOCK_ALL, startq, entry2)); 10198 soc_mem_field32_set(unit, mem2, entry2, Q_SHARED_ALPHAf, alpha); 10199 SOC_IF_ERROR_RETURN 10200 (soc_mem_write(unit, mem2, MEM_BLOCK_ALL, startq, entry2)); 10201 } else if (BCM_GPORT_IS_LOCAL(gport)) { 10202 /*Set the alpha for Qgroup associated with the gport*/ 10203 BCM_IF_ERROR_RETURN 10204 (_bcm_th_cosq_dynamic_thresh_enable_get(unit, gport, cosq, 10205 bcmCosqControlEgressUCQueueGroupSharedDynamicEnable, 10206 &dynamic_thresh_mode)); 10207 if (!dynamic_thresh_mode){ 10208 return BCM_E_CONFIG; 10209 } 10210 10211 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 10212 10213 phy_port = si->port_l2p_mapping[local_port]; 10214 mmu_port = si->port_p2m_mapping[phy_port]; 10215 local_mmu_port = mmu_port & (SOC_TH_MMU_PORT_STRIDE - 1); 10216 10217 base_mem = MMU_THDU_CONFIG_QGROUPm; 10218 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 10219 10220 BCM_IF_ERROR_RETURN 10221 (soc_mem_read(unit, mem, MEM_BLOCK_ALL,local_mmu_port , entry)); 10222 soc_mem_field32_set(unit, mem, entry, 10223 Q_SHARED_ALPHA_CELLf, alpha); 10224 SOC_IF_ERROR_RETURN 10225 (soc_mem_write(unit, mem, MEM_BLOCK_ALL,local_mmu_port , entry)); 10226 } else { 10227 BCM_IF_ERROR_RETURN 10228 (_bcm_th_cosq_dynamic_thresh_enable_get(unit, gport, cosq, 10229 bcmCosqControlIngressPortPGSharedDynamicEnable, 10230 &dynamic_thresh_mode)); 10231 if (!dynamic_thresh_mode){ 10232 return BCM_E_CONFIG; 10233 } 10234 10235 BCM_IF_ERROR_RETURN 10236 (_bcm_th_cosq_localport_resolve(unit, gport, &local_port)); 10237 if (local_port < 0) { 10238 return BCM_E_PORT; 10239 } 10240 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 10241 10242 if ((cosq < 0) || (cosq >= _TH_MMU_NUM_INT_PRI)) { 10243 /* Error. Input pri > Max Pri_Grp */ 10244 return BCM_E_PARAM; 10245 } 10246 10247 /* get PG for port using Port+Cos */ 10248 if (cosq < _TH_MMU_NUM_PG) { 10249 reg = prigroup_reg[0]; 10250 } else { 10251 reg = prigroup_reg[1]; 10252 } 10253 10254 SOC_IF_ERROR_RETURN 10255 (soc_reg32_get(unit, reg, local_port, 0, &rval)); 10256 port_pg = soc_reg_field_get(unit, reg, rval, prigroup_field[cosq]); 10257 base_mem = THDI_PORT_PG_CONFIGm; 10258 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 10259 /* get index for Port-PG */ 10260 midx = SOC_TH_MMU_PIPED_MEM_INDEX(unit, local_port, base_mem, port_pg); 10261 BCM_IF_ERROR_RETURN 10262 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, entry)); 10263 soc_mem_field32_set(unit, mem, entry, PG_SHARED_LIMITf, alpha); 10264 SOC_IF_ERROR_RETURN 10265 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, midx, entry)); 10266 } 10267 10268 return BCM_E_NONE; 10269 } 10270 10271 10272 STATIC int 10273 _bcm_th_cosq_alpha_get(int unit, 10274 bcm_gport_t gport, bcm_cos_queue_t cosq, 10275 bcm_cosq_control_drop_limit_alpha_value_t *arg) 10276 { 10277 bcm_port_t local_port; 10278 int startq, midx, pipe; 10279 uint32 rval; 10280 uint32 entry[SOC_MAX_MEM_WORDS]; 10281 soc_mem_t mem = INVALIDm, base_mem = INVALIDm; 10282 int alpha, dynamic_thresh_mode, port_pg; 10283 soc_reg_t reg = INVALIDr; 10284 static const soc_reg_t prigroup_reg[] = { 10285 THDI_PORT_PRI_GRP0r, THDI_PORT_PRI_GRP1r 10286 }; 10287 static const soc_field_t prigroup_field[] = { 10288 PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf, 10289 PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf, 10290 PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf, 10291 PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf 10292 }; 10293 10294 if (!arg) { 10295 return BCM_E_PARAM; 10296 } 10297 10298 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 10299 BCM_IF_ERROR_RETURN 10300 (_bcm_th_cosq_dynamic_thresh_enable_get(unit, gport, cosq, 10301 bcmCosqControlEgressUCSharedDynamicEnable, 10302 &dynamic_thresh_mode)); 10303 if (!dynamic_thresh_mode){ 10304 return BCM_E_CONFIG; 10305 } 10306 10307 BCM_IF_ERROR_RETURN 10308 (_bcm_th_cosq_index_resolve(unit, gport, cosq, 10309 _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE, 10310 &local_port, &startq, NULL)); 10311 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 10312 10313 base_mem = MMU_THDU_CONFIG_QUEUEm; 10314 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 10315 10316 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, 10317 startq, entry)); 10318 alpha = soc_mem_field32_get(unit, mem, entry, Q_SHARED_ALPHA_CELLf); 10319 10320 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 10321 BCM_IF_ERROR_RETURN 10322 (_bcm_th_cosq_dynamic_thresh_enable_get(unit, gport, cosq, 10323 bcmCosqControlEgressMCSharedDynamicEnable, 10324 &dynamic_thresh_mode)); 10325 if (!dynamic_thresh_mode){ 10326 return BCM_E_CONFIG; 10327 } 10328 10329 BCM_IF_ERROR_RETURN 10330 (_bcm_th_cosq_index_resolve(unit, gport, cosq, 10331 _BCM_TH_COSQ_INDEX_STYLE_MCAST_QUEUE, 10332 &local_port, &startq, NULL)); 10333 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 10334 10335 base_mem = MMU_THDM_DB_QUEUE_CONFIGm; 10336 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 10337 BCM_IF_ERROR_RETURN 10338 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 10339 alpha = soc_mem_field32_get(unit, mem, entry, Q_SHARED_ALPHAf); 10340 10341 } else { 10342 BCM_IF_ERROR_RETURN 10343 (_bcm_th_cosq_dynamic_thresh_enable_get(unit, gport, cosq, 10344 bcmCosqControlIngressPortPGSharedDynamicEnable, 10345 &dynamic_thresh_mode)); 10346 if (!dynamic_thresh_mode){ 10347 return BCM_E_CONFIG; 10348 } 10349 10350 BCM_IF_ERROR_RETURN 10351 (_bcm_th_cosq_localport_resolve(unit, gport, &local_port)); 10352 if (local_port < 0) { 10353 return BCM_E_PORT; 10354 } 10355 10356 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 10357 10358 if ((cosq < 0) || (cosq >= _TH_MMU_NUM_INT_PRI)) { 10359 /* Error. Input pri > Max Pri_Grp */ 10360 return BCM_E_PARAM; 10361 } 10362 10363 /* get PG for port using Port+Cos */ 10364 if (cosq < _TH_MMU_NUM_PG) { 10365 reg = prigroup_reg[0]; 10366 } else { 10367 reg = prigroup_reg[1]; 10368 } 10369 10370 SOC_IF_ERROR_RETURN 10371 (soc_reg32_get(unit, reg, local_port, 0, &rval)); 10372 port_pg = soc_reg_field_get(unit, reg, rval, prigroup_field[cosq]); 10373 10374 base_mem = THDI_PORT_PG_CONFIGm; 10375 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 10376 /* get index for Port-PG */ 10377 midx = SOC_TH_MMU_PIPED_MEM_INDEX(unit, local_port, base_mem, port_pg); 10378 10379 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, 10380 midx, entry)); 10381 alpha = soc_mem_field32_get(unit, mem, entry, PG_SHARED_LIMITf); 10382 10383 } 10384 10385 switch(alpha) { 10386 case SOC_TH_COSQ_DROP_LIMIT_ALPHA_1_128: 10387 *arg = bcmCosqControlDropLimitAlpha_1_128; 10388 break; 10389 case SOC_TH_COSQ_DROP_LIMIT_ALPHA_1_64: 10390 *arg = bcmCosqControlDropLimitAlpha_1_64; 10391 break; 10392 case SOC_TH_COSQ_DROP_LIMIT_ALPHA_1_32: 10393 *arg = bcmCosqControlDropLimitAlpha_1_32; 10394 break; 10395 case SOC_TH_COSQ_DROP_LIMIT_ALPHA_1_16: 10396 *arg = bcmCosqControlDropLimitAlpha_1_16; 10397 break; 10398 case SOC_TH_COSQ_DROP_LIMIT_ALPHA_1_8: 10399 *arg = bcmCosqControlDropLimitAlpha_1_8; 10400 break; 10401 case SOC_TH_COSQ_DROP_LIMIT_ALPHA_1_4: 10402 *arg = bcmCosqControlDropLimitAlpha_1_4; 10403 break; 10404 case SOC_TH_COSQ_DROP_LIMIT_ALPHA_1_2: 10405 *arg = bcmCosqControlDropLimitAlpha_1_2; 10406 break; 10407 case SOC_TH_COSQ_DROP_LIMIT_ALPHA_1: 10408 *arg = bcmCosqControlDropLimitAlpha_1; 10409 break; 10410 case SOC_TH_COSQ_DROP_LIMIT_ALPHA_2: 10411 *arg = bcmCosqControlDropLimitAlpha_2; 10412 break; 10413 case SOC_TH_COSQ_DROP_LIMIT_ALPHA_4: 10414 *arg = bcmCosqControlDropLimitAlpha_4; 10415 break; 10416 case SOC_TH_COSQ_DROP_LIMIT_ALPHA_8: 10417 *arg = bcmCosqControlDropLimitAlpha_8; 10418 break; 10419 default: 10420 return BCM_E_PARAM; 10421 } 10422 10423 return BCM_E_NONE; 10424 } 10425 10426 STATIC int 10427 _bcm_th_cosq_dynamic_thresh_enable_set(int unit, 10428 bcm_gport_t gport, bcm_cos_queue_t cosq, 10429 bcm_cosq_control_t type, int arg) 10430 { 10431 bcm_port_t local_port; 10432 int startq, pipe; 10433 int from_cos, to_cos, ci; 10434 int midx; 10435 uint32 rval; 10436 uint32 entry[SOC_MAX_MEM_WORDS]; 10437 uint32 entry2[SOC_MAX_MEM_WORDS]; 10438 soc_mem_t base_mem = INVALIDm, base_mem2 = INVALIDm; 10439 soc_mem_t mem = INVALIDm, mem2 = INVALIDm; 10440 soc_reg_t reg = INVALIDr; 10441 int port_pg; 10442 static const soc_reg_t prigroup_reg[] = { 10443 THDI_PORT_PRI_GRP0r, THDI_PORT_PRI_GRP1r 10444 }; 10445 static const soc_field_t prigroup_field[] = { 10446 PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf, 10447 PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf, 10448 PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf, 10449 PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf 10450 }; 10451 10452 if (type == bcmCosqControlIngressPortPGSharedDynamicEnable) { 10453 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 10454 BCM_GPORT_IS_SCHEDULER(gport) || 10455 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 10456 return BCM_E_PARAM; 10457 } 10458 BCM_IF_ERROR_RETURN 10459 (_bcm_th_cosq_localport_resolve(unit, gport, &local_port)); 10460 if (local_port < 0) { 10461 return BCM_E_PORT; 10462 } 10463 if ((cosq < 0) || (cosq >= 16)) { 10464 return BCM_E_PARAM; 10465 } 10466 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 10467 10468 if ((cosq < 0) || (cosq >= _TH_MMU_NUM_INT_PRI)) { 10469 /* Error. Input pri > Max Pri_Grp */ 10470 /* coverity[dead_error_line] */ 10471 return BCM_E_PARAM; 10472 } 10473 10474 /* get PG for port using Port+Cos */ 10475 if (cosq < _TH_MMU_NUM_PG) { 10476 reg = prigroup_reg[0]; 10477 } else { 10478 reg = prigroup_reg[1]; 10479 } 10480 10481 SOC_IF_ERROR_RETURN 10482 (soc_reg32_get(unit, reg, local_port, 0, &rval)); 10483 port_pg = soc_reg_field_get(unit, reg, rval, prigroup_field[cosq]); 10484 base_mem = THDI_PORT_PG_CONFIGm; 10485 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 10486 /* get index for Port-PG */ 10487 midx = SOC_TH_MMU_PIPED_MEM_INDEX(unit, local_port, base_mem, port_pg); 10488 BCM_IF_ERROR_RETURN 10489 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, entry)); 10490 soc_mem_field32_set(unit, mem, entry, 10491 PG_SHARED_DYNAMICf, arg ? 1 : 0); 10492 if(arg) { 10493 /* Set default alpha value*/ 10494 soc_mem_field32_set(unit, mem, entry, PG_SHARED_LIMITf, 10495 SOC_TH_COSQ_DROP_LIMIT_ALPHA_1_128); 10496 } 10497 SOC_IF_ERROR_RETURN 10498 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, midx, entry)); 10499 } else if (type == bcmCosqControlEgressUCSharedDynamicEnable) { 10500 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 10501 BCM_IF_ERROR_RETURN 10502 (_bcm_th_cosq_index_resolve(unit, gport, cosq, 10503 _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE, 10504 &local_port, &startq, NULL)); 10505 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 10506 return BCM_E_PARAM; 10507 } else { 10508 if (cosq == BCM_COS_INVALID) { 10509 from_cos = to_cos = 0; 10510 } else { 10511 from_cos = to_cos = cosq; 10512 } 10513 10514 BCM_IF_ERROR_RETURN 10515 (_bcm_th_cosq_localport_resolve(unit, gport, &local_port)); 10516 if (local_port < 0) { 10517 return BCM_E_PORT; 10518 } 10519 for (ci = from_cos; ci <= to_cos; ci++) { 10520 BCM_IF_ERROR_RETURN 10521 (_bcm_th_cosq_index_resolve(unit, local_port, ci, 10522 _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE, 10523 NULL, &startq, NULL)); 10524 10525 } 10526 } 10527 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 10528 base_mem = MMU_THDU_CONFIG_QUEUEm; 10529 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 10530 10531 BCM_IF_ERROR_RETURN 10532 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 10533 soc_mem_field32_set(unit, mem, entry, 10534 Q_LIMIT_DYNAMIC_CELLf, arg ? 1 : 0); 10535 if(arg) { 10536 /* Set default alpha value*/ 10537 soc_mem_field32_set(unit, mem, entry, Q_SHARED_ALPHA_CELLf, 10538 SOC_TH_COSQ_DROP_LIMIT_ALPHA_1_128); 10539 } 10540 SOC_IF_ERROR_RETURN 10541 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 10542 } else if (type == bcmCosqControlEgressMCSharedDynamicEnable) { 10543 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 10544 return BCM_E_PARAM; 10545 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 10546 BCM_IF_ERROR_RETURN 10547 (_bcm_th_cosq_index_resolve(unit, gport, cosq, 10548 _BCM_TH_COSQ_INDEX_STYLE_MCAST_QUEUE, 10549 &local_port, &startq, NULL)); 10550 } 10551 else { 10552 if (cosq == BCM_COS_INVALID) { 10553 from_cos = to_cos = 0; 10554 } else { 10555 from_cos = to_cos = cosq; 10556 } 10557 10558 BCM_IF_ERROR_RETURN 10559 (_bcm_th_cosq_localport_resolve(unit, gport, &local_port)); 10560 if (local_port < 0) { 10561 return BCM_E_PORT; 10562 } 10563 for (ci = from_cos; ci <= to_cos; ci++) { 10564 BCM_IF_ERROR_RETURN 10565 (_bcm_th_cosq_index_resolve(unit, local_port, ci, 10566 _BCM_TH_COSQ_INDEX_STYLE_MCAST_QUEUE, 10567 NULL, &startq, NULL)); 10568 10569 } 10570 } 10571 10572 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 10573 base_mem = MMU_THDM_DB_QUEUE_CONFIGm; 10574 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 10575 10576 base_mem2 = MMU_THDM_MCQE_QUEUE_CONFIGm; 10577 mem2 = SOC_MEM_UNIQUE_ACC(unit, base_mem2)[pipe]; 10578 10579 BCM_IF_ERROR_RETURN 10580 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 10581 soc_mem_field32_set(unit, mem, entry, Q_LIMIT_DYNAMICf, arg ? 1 : 0); 10582 if(arg) { 10583 /* Set default alpha value*/ 10584 soc_mem_field32_set(unit, mem, entry, Q_SHARED_ALPHAf, 10585 SOC_TH_COSQ_DROP_LIMIT_ALPHA_1_128); 10586 } 10587 SOC_IF_ERROR_RETURN 10588 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 10589 10590 BCM_IF_ERROR_RETURN 10591 (soc_mem_read(unit, mem2, MEM_BLOCK_ALL, startq, entry2)); 10592 soc_mem_field32_set(unit, mem2, entry2, Q_LIMIT_DYNAMICf, arg ? 1 : 0); 10593 if(arg) { 10594 /* Set default alpha value*/ 10595 soc_mem_field32_set(unit, mem2, entry2, Q_SHARED_ALPHAf, 10596 SOC_TH_COSQ_DROP_LIMIT_ALPHA_1_128); 10597 } 10598 SOC_IF_ERROR_RETURN 10599 (soc_mem_write(unit, mem2, MEM_BLOCK_ALL, startq, entry2)); 10600 10601 } else { 10602 return BCM_E_PARAM; 10603 } 10604 10605 return BCM_E_NONE; 10606 } 10607 /* 10608 * Function: _bcm_th_cosq_egr_queue_color_limit_set 10609 * Purpose: Set Red and Yellow color limit per queue 10610 * IF color mode dynamic: limit should be between 0-7 10611 * 0: 100% of green threshold 10612 * 1: 12.5% of green threshold 10613 * 2: 25% of green threshold 10614 * 3: 37.5% of green threshold 10615 * 4: 50% of green threshold 10616 * 5: 67.5% of green threshold 10617 * 6: 75% of green threshold 10618 * 7: 87.5% of green threshold 10619 * If color mode static: Limit is number of bytes 10620 */ 10621 10622 STATIC int 10623 _bcm_th_cosq_egr_queue_color_limit_set(int unit, bcm_gport_t gport, 10624 bcm_cos_queue_t cosq, 10625 bcm_cosq_control_t type, 10626 int arg) 10627 { 10628 bcm_port_t local_port; 10629 int startq, pipe; 10630 uint32 entry[SOC_MAX_MEM_WORDS]; 10631 soc_mem_t mem = INVALIDm; 10632 soc_field_t fld_limit = INVALIDf; 10633 int color_mode, granularity, max_val; 10634 10635 if (arg < 0) { 10636 return BCM_E_PARAM; 10637 } 10638 granularity = 8; 10639 10640 if ((type == bcmCosqControlEgressUCQueueRedLimit) || 10641 (type == bcmCosqControlEgressUCQueueYellowLimit)) { 10642 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 10643 BCM_IF_ERROR_RETURN 10644 (_bcm_th_cosq_index_resolve(unit, gport, cosq, 10645 _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE, 10646 &local_port, &startq, NULL)); 10647 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 10648 return BCM_E_PARAM; 10649 } else { 10650 if (cosq < 0) { 10651 return BCM_E_PARAM; 10652 } 10653 BCM_IF_ERROR_RETURN 10654 (_bcm_th_cosq_localport_resolve(unit, gport, &local_port)); 10655 if (local_port < 0) { 10656 return BCM_E_PORT; 10657 } 10658 BCM_IF_ERROR_RETURN 10659 (_bcm_th_cosq_index_resolve 10660 (unit, local_port, cosq, _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE, 10661 NULL, &startq, NULL)); 10662 } 10663 if (type == bcmCosqControlEgressUCQueueRedLimit) { 10664 fld_limit = LIMIT_RED_CELLf; 10665 } else { 10666 fld_limit = LIMIT_YELLOW_CELLf; 10667 } 10668 BCM_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 10669 mem = SOC_MEM_UNIQUE_ACC(unit, MMU_THDU_CONFIG_QUEUEm)[pipe]; 10670 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 10671 color_mode = soc_mem_field32_get(unit, mem, entry, Q_COLOR_LIMIT_DYNAMIC_CELLf); 10672 10673 if (color_mode == 1) { /* Dynamic color limit */ 10674 if (arg > 7) { /* Legal values are 0 - 7 */ 10675 return BCM_E_PARAM; 10676 } else { 10677 soc_mem_field32_set(unit, mem, entry, fld_limit, arg); 10678 } 10679 } else { /* Static color limit */ 10680 arg = (arg + _TH_MMU_BYTES_PER_CELL - 1) / _TH_MMU_BYTES_PER_CELL; 10681 10682 /* Check for min/max values */ 10683 max_val = (1 << soc_mem_field_length(unit, mem, fld_limit)) - 1; 10684 if ((arg < 0) || ((arg/granularity) > max_val)) { 10685 return BCM_E_PARAM; 10686 } else { 10687 soc_mem_field32_set(unit, mem, entry, fld_limit, (arg/granularity)); 10688 } 10689 } 10690 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 10691 } else if ((type == bcmCosqControlEgressMCQueueRedLimit) || 10692 (type == bcmCosqControlEgressMCQueueYellowLimit)) { 10693 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 10694 return BCM_E_PARAM; 10695 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 10696 BCM_IF_ERROR_RETURN 10697 (_bcm_th_cosq_index_resolve(unit, gport, cosq, 10698 _BCM_TH_COSQ_INDEX_STYLE_MCAST_QUEUE, 10699 &local_port, &startq, NULL)); 10700 } else { 10701 if (cosq < 0) { 10702 return BCM_E_PARAM; 10703 } 10704 BCM_IF_ERROR_RETURN 10705 (_bcm_th_cosq_localport_resolve(unit, gport, &local_port)); 10706 if (local_port < 0) { 10707 return BCM_E_PORT; 10708 } 10709 BCM_IF_ERROR_RETURN 10710 (_bcm_th_cosq_index_resolve(unit, local_port, cosq, 10711 _BCM_TH_COSQ_INDEX_STYLE_MCAST_QUEUE, 10712 NULL, &startq, NULL)); 10713 } 10714 10715 if (type == bcmCosqControlEgressMCQueueRedLimit) { 10716 fld_limit = RED_SHARED_LIMITf; 10717 } else { 10718 fld_limit = YELLOW_SHARED_LIMITf; 10719 } 10720 BCM_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 10721 mem = SOC_MEM_UNIQUE_ACC(unit, MMU_THDM_DB_QUEUE_CONFIGm)[pipe]; 10722 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 10723 color_mode = soc_mem_field32_get(unit, mem, entry, Q_COLOR_LIMIT_DYNAMICf); 10724 10725 if (color_mode == 1) { /* Dynamic color limit */ 10726 if (arg > 7) { /* Legal values are 0 - 7 */ 10727 return BCM_E_PARAM; 10728 } else { 10729 soc_mem_field32_set(unit, mem, entry, fld_limit, arg); 10730 } 10731 } else { /* Static color limit */ 10732 arg = (arg + _TH_MMU_BYTES_PER_CELL - 1) / _TH_MMU_BYTES_PER_CELL; 10733 10734 /* Check for min/max values */ 10735 max_val = (1 << soc_mem_field_length(unit, mem, fld_limit)) - 1; 10736 if ((arg < 0) || ((arg/granularity) > max_val)) { 10737 return BCM_E_PARAM; 10738 } else { 10739 soc_mem_field32_set(unit, mem, entry, fld_limit, (arg/granularity)); 10740 } 10741 } 10742 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 10743 10744 } else { 10745 return BCM_E_PARAM; 10746 } 10747 10748 return BCM_E_NONE; 10749 } 10750 10751 /* 10752 * Function: _bcm_th_cosq_egr_queue_color_limit_get 10753 * Purpose: Get Red and Yellow color limit per queue 10754 * Return value: IF color mode dynamic: limit should be between 0-7 10755 * 0: 100% of green threshold 10756 * 1: 12.5% of green threshold 10757 * 2: 25% of green threshold 10758 * 3: 37.5% of green threshold 10759 * 4: 50% of green threshold 10760 * 5: 67.5% of green threshold 10761 * 6: 75% of green threshold 10762 * 7: 87.5% of green threshold 10763 * If color mode static: Limit is number of bytes 10764 */ 10765 10766 STATIC int 10767 _bcm_th_cosq_egr_queue_color_limit_get(int unit, bcm_gport_t gport, 10768 bcm_cos_queue_t cosq, 10769 bcm_cosq_control_t type, 10770 int* arg) 10771 { 10772 bcm_port_t local_port; 10773 int startq, pipe; 10774 uint32 entry[SOC_MAX_MEM_WORDS]; 10775 soc_mem_t mem = INVALIDm; 10776 soc_field_t fld_limit = INVALIDf; 10777 int color_mode, granularity; 10778 10779 if (arg == NULL) { 10780 return BCM_E_PARAM; 10781 } 10782 10783 granularity = 8; 10784 10785 if ((type == bcmCosqControlEgressUCQueueRedLimit) || 10786 (type == bcmCosqControlEgressUCQueueYellowLimit)) { 10787 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 10788 BCM_IF_ERROR_RETURN 10789 (_bcm_th_cosq_index_resolve(unit, gport, cosq, 10790 _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE, 10791 &local_port, &startq, NULL)); 10792 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 10793 return BCM_E_PARAM; 10794 } else { 10795 if (cosq < 0) { 10796 return BCM_E_PARAM; 10797 } 10798 BCM_IF_ERROR_RETURN 10799 (_bcm_th_cosq_localport_resolve(unit, gport, &local_port)); 10800 if (local_port < 0) { 10801 return BCM_E_PORT; 10802 } 10803 BCM_IF_ERROR_RETURN 10804 (_bcm_th_cosq_index_resolve 10805 (unit, local_port, cosq, _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE, 10806 NULL, &startq, NULL)); 10807 } 10808 10809 if (type == bcmCosqControlEgressUCQueueRedLimit) { 10810 fld_limit = LIMIT_RED_CELLf; 10811 } else { 10812 fld_limit = LIMIT_YELLOW_CELLf; 10813 } 10814 BCM_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 10815 mem = SOC_MEM_UNIQUE_ACC(unit, MMU_THDU_CONFIG_QUEUEm)[pipe]; 10816 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 10817 color_mode = soc_mem_field32_get(unit, mem, entry, Q_COLOR_LIMIT_DYNAMIC_CELLf); 10818 10819 if (color_mode == 1) { /* Dynamic color limit */ 10820 *arg = soc_mem_field32_get(unit, mem, entry, fld_limit); 10821 } else { /* Static color limit */ 10822 *arg = soc_mem_field32_get(unit, mem, entry, fld_limit); 10823 *arg = (*arg) * granularity * _TH_MMU_BYTES_PER_CELL; 10824 } 10825 } else if ((type == bcmCosqControlEgressMCQueueRedLimit) || 10826 (type == bcmCosqControlEgressMCQueueYellowLimit)) { 10827 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 10828 return BCM_E_PARAM; 10829 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 10830 BCM_IF_ERROR_RETURN 10831 (_bcm_th_cosq_index_resolve(unit, gport, cosq, 10832 _BCM_TH_COSQ_INDEX_STYLE_MCAST_QUEUE, 10833 &local_port, &startq, NULL)); 10834 } else { 10835 if (cosq < 0) { 10836 return BCM_E_PARAM; 10837 } 10838 BCM_IF_ERROR_RETURN 10839 (_bcm_th_cosq_localport_resolve(unit, gport, &local_port)); 10840 if (local_port < 0) { 10841 return BCM_E_PORT; 10842 } 10843 BCM_IF_ERROR_RETURN 10844 (_bcm_th_cosq_index_resolve(unit, local_port, cosq, 10845 _BCM_TH_COSQ_INDEX_STYLE_MCAST_QUEUE, 10846 NULL, &startq, NULL)); 10847 } 10848 10849 if (type == bcmCosqControlEgressMCQueueRedLimit) { 10850 fld_limit = RED_SHARED_LIMITf; 10851 } else { 10852 fld_limit = YELLOW_SHARED_LIMITf; 10853 } 10854 BCM_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 10855 mem = SOC_MEM_UNIQUE_ACC(unit, MMU_THDM_DB_QUEUE_CONFIGm)[pipe]; 10856 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 10857 color_mode = soc_mem_field32_get(unit, mem, entry, Q_COLOR_LIMIT_DYNAMICf); 10858 10859 if (color_mode == 1) { /* Dynamic color limit */ 10860 *arg = soc_mem_field32_get(unit, mem, entry, fld_limit); 10861 } else { /* Static color limit */ 10862 *arg = soc_mem_field32_get(unit, mem, entry, fld_limit); 10863 *arg = (*arg) * granularity * _TH_MMU_BYTES_PER_CELL; 10864 } 10865 10866 } else { 10867 return BCM_E_PARAM; 10868 } 10869 10870 return BCM_E_NONE; 10871 } 10872 10873 10874 /* 10875 * Function: _bcm_th_cosq_egr_queue_color_limit_mode_set 10876 * Purpose: Set color limit mode per queue to static (0) or 10877 * dynamic (1) 10878 */ 10879 10880 STATIC int 10881 _bcm_th_cosq_egr_queue_color_limit_mode_set(int unit, bcm_gport_t gport, 10882 bcm_cos_queue_t cosq, 10883 bcm_cosq_control_t type, 10884 int arg) 10885 { 10886 bcm_port_t local_port; 10887 int startq, pipe; 10888 uint32 entry[SOC_MAX_MEM_WORDS]; 10889 soc_mem_t mem = INVALIDm; 10890 int enable; 10891 10892 if (arg < 0) { 10893 return BCM_E_PARAM; 10894 } 10895 10896 arg = arg ? 1 : 0; 10897 10898 if (type == bcmCosqControlEgressUCQueueColorLimitDynamicEnable) { 10899 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 10900 BCM_IF_ERROR_RETURN 10901 (_bcm_th_cosq_index_resolve(unit, gport, cosq, 10902 _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE, 10903 &local_port, &startq, NULL)); 10904 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 10905 return BCM_E_PARAM; 10906 } else { 10907 if (cosq < 0) { 10908 return BCM_E_PARAM; 10909 } 10910 BCM_IF_ERROR_RETURN 10911 (_bcm_th_cosq_localport_resolve(unit, gport, &local_port)); 10912 if (local_port < 0) { 10913 return BCM_E_PORT; 10914 } 10915 BCM_IF_ERROR_RETURN 10916 (_bcm_th_cosq_index_resolve 10917 (unit, local_port, cosq, _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE, 10918 NULL, &startq, NULL)); 10919 } 10920 BCM_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 10921 mem = SOC_MEM_UNIQUE_ACC(unit, MMU_THDU_CONFIG_QUEUEm)[pipe]; 10922 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 10923 enable = soc_mem_field32_get(unit, mem, entry, Q_COLOR_LIMIT_DYNAMIC_CELLf); 10924 if (enable != arg) { 10925 soc_mem_field32_set(unit, mem, entry, Q_COLOR_LIMIT_DYNAMIC_CELLf, arg); 10926 /* Reset the Red and Yellow limits when color limit mode is changed */ 10927 soc_mem_field32_set(unit, mem, entry, LIMIT_RED_CELLf, 0); 10928 soc_mem_field32_set(unit, mem, entry, LIMIT_YELLOW_CELLf, 0); 10929 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 10930 } 10931 } else if (type == bcmCosqControlEgressMCQueueColorLimitDynamicEnable) { 10932 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 10933 return BCM_E_PARAM; 10934 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 10935 BCM_IF_ERROR_RETURN 10936 (_bcm_th_cosq_index_resolve(unit, gport, cosq, 10937 _BCM_TH_COSQ_INDEX_STYLE_MCAST_QUEUE, 10938 &local_port, &startq, NULL)); 10939 } else { 10940 if (cosq < 0) { 10941 return BCM_E_PARAM; 10942 } 10943 BCM_IF_ERROR_RETURN 10944 (_bcm_th_cosq_localport_resolve(unit, gport, &local_port)); 10945 if (local_port < 0) { 10946 return BCM_E_PORT; 10947 } 10948 BCM_IF_ERROR_RETURN 10949 (_bcm_th_cosq_index_resolve(unit, local_port, cosq, 10950 _BCM_TH_COSQ_INDEX_STYLE_MCAST_QUEUE, 10951 NULL, &startq, NULL)); 10952 } 10953 BCM_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 10954 mem = SOC_MEM_UNIQUE_ACC(unit, MMU_THDM_DB_QUEUE_CONFIGm)[pipe]; 10955 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 10956 enable = soc_mem_field32_get(unit, mem, entry, Q_COLOR_LIMIT_DYNAMICf); 10957 if (enable != arg) { 10958 soc_mem_field32_set(unit, mem, entry, Q_COLOR_LIMIT_DYNAMICf, arg); 10959 /* Reset the Red and Yellow limits when color limit mode is changed */ 10960 soc_mem_field32_set(unit, mem, entry, RED_SHARED_LIMITf, 0); 10961 soc_mem_field32_set(unit, mem, entry, YELLOW_SHARED_LIMITf, 0); 10962 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 10963 } 10964 } else { 10965 return BCM_E_PARAM; 10966 } 10967 10968 return BCM_E_NONE; 10969 } 10970 10971 /* 10972 * Function: _bcm_th_cosq_egr_queue_color_limit_mode_get 10973 * Purpose: Get color limit mode per queue. 10974 * Returns: 0 (static) or 1 (dynamic) 10975 */ 10976 STATIC int 10977 _bcm_th_cosq_egr_queue_color_limit_mode_get(int unit, bcm_gport_t gport, 10978 bcm_cos_queue_t cosq, 10979 bcm_cosq_control_t type, 10980 int* arg) 10981 { 10982 bcm_port_t local_port; 10983 int startq, pipe; 10984 uint32 entry[SOC_MAX_MEM_WORDS]; 10985 soc_mem_t mem = INVALIDm; 10986 10987 if (arg == NULL) { 10988 return BCM_E_PARAM; 10989 } 10990 10991 if (type == bcmCosqControlEgressUCQueueColorLimitDynamicEnable) { 10992 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 10993 BCM_IF_ERROR_RETURN 10994 (_bcm_th_cosq_index_resolve(unit, gport, cosq, 10995 _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE, 10996 &local_port, &startq, NULL)); 10997 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 10998 return BCM_E_PARAM; 10999 } else { 11000 if (cosq < 0) { 11001 return BCM_E_PARAM; 11002 } 11003 BCM_IF_ERROR_RETURN 11004 (_bcm_th_cosq_localport_resolve(unit, gport, &local_port)); 11005 if (local_port < 0) { 11006 return BCM_E_PORT; 11007 } 11008 BCM_IF_ERROR_RETURN 11009 (_bcm_th_cosq_index_resolve 11010 (unit, local_port, cosq, _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE, 11011 NULL, &startq, NULL)); 11012 } 11013 BCM_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 11014 mem = SOC_MEM_UNIQUE_ACC(unit, MMU_THDU_CONFIG_QUEUEm)[pipe]; 11015 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 11016 *arg = soc_mem_field32_get(unit, mem, entry, Q_COLOR_LIMIT_DYNAMIC_CELLf); 11017 } else if (type == bcmCosqControlEgressMCQueueColorLimitDynamicEnable) { 11018 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 11019 return BCM_E_PARAM; 11020 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 11021 BCM_IF_ERROR_RETURN 11022 (_bcm_th_cosq_index_resolve(unit, gport, cosq, 11023 _BCM_TH_COSQ_INDEX_STYLE_MCAST_QUEUE, 11024 &local_port, &startq, NULL)); 11025 } else { 11026 if (cosq < 0) { 11027 return BCM_E_PARAM; 11028 } 11029 BCM_IF_ERROR_RETURN 11030 (_bcm_th_cosq_localport_resolve(unit, gport, &local_port)); 11031 if (local_port < 0) { 11032 return BCM_E_PORT; 11033 } 11034 BCM_IF_ERROR_RETURN 11035 (_bcm_th_cosq_index_resolve(unit, local_port, cosq, 11036 _BCM_TH_COSQ_INDEX_STYLE_MCAST_QUEUE, 11037 NULL, &startq, NULL)); 11038 } 11039 BCM_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 11040 mem = SOC_MEM_UNIQUE_ACC(unit, MMU_THDM_DB_QUEUE_CONFIGm)[pipe]; 11041 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 11042 *arg = soc_mem_field32_get(unit, mem, entry, Q_COLOR_LIMIT_DYNAMICf); 11043 } else { 11044 return BCM_E_PARAM; 11045 } 11046 11047 return BCM_E_NONE; 11048 } 11049 11050 11051 STATIC int 11052 _bcm_th_cosq_egr_queue_limit_enable_set(int unit, bcm_gport_t gport, 11053 bcm_cos_queue_t cosq, 11054 bcm_cosq_control_t type, 11055 int arg) 11056 { 11057 bcm_port_t local_port; 11058 int startq, pipe; 11059 uint32 entry[SOC_MAX_MEM_WORDS]; 11060 soc_mem_t mem = INVALIDm, base_mem = INVALIDm; 11061 soc_field_t fld_name = INVALIDf; 11062 int enable; 11063 11064 if (arg < 0) { 11065 return BCM_E_PARAM; 11066 } 11067 11068 arg = arg ? 1 : 0; 11069 11070 if ((type == bcmCosqControlEgressUCQueueLimitEnable) || 11071 (type == bcmCosqControlEgressUCQueueColorLimitEnable)) { 11072 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 11073 BCM_IF_ERROR_RETURN 11074 (_bcm_th_cosq_index_resolve(unit, gport, cosq, 11075 _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE, 11076 &local_port, &startq, NULL)); 11077 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 11078 return BCM_E_PARAM; 11079 } else { 11080 if (cosq < 0) { 11081 return BCM_E_PARAM; 11082 } 11083 BCM_IF_ERROR_RETURN 11084 (_bcm_th_cosq_localport_resolve(unit, gport, &local_port)); 11085 if (local_port < 0) { 11086 return BCM_E_PORT; 11087 } 11088 BCM_IF_ERROR_RETURN 11089 (_bcm_th_cosq_index_resolve 11090 (unit, local_port, cosq, _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE, 11091 NULL, &startq, NULL)); 11092 } 11093 11094 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 11095 11096 base_mem = MMU_THDU_Q_TO_QGRP_MAPm; 11097 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 11098 if (type == bcmCosqControlEgressUCQueueLimitEnable) { 11099 fld_name = Q_LIMIT_ENABLEf; 11100 } else if (type == bcmCosqControlEgressUCQueueColorLimitEnable) { 11101 fld_name = Q_COLOR_ENABLE_CELLf; 11102 } 11103 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 11104 enable = soc_mem_field32_get(unit, mem, entry, fld_name); 11105 if (enable != arg) { 11106 soc_mem_field32_set(unit, mem, entry, fld_name, arg); 11107 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 11108 } 11109 } else if (type == bcmCosqControlEgressMCQueueLimitEnable) { 11110 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 11111 return BCM_E_PARAM; 11112 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 11113 BCM_IF_ERROR_RETURN 11114 (_bcm_th_cosq_index_resolve(unit, gport, cosq, 11115 _BCM_TH_COSQ_INDEX_STYLE_MCAST_QUEUE, 11116 &local_port, &startq, NULL)); 11117 } else { 11118 if (cosq < 0) { 11119 return BCM_E_PARAM; 11120 } 11121 BCM_IF_ERROR_RETURN 11122 (_bcm_th_cosq_localport_resolve(unit, gport, &local_port)); 11123 if (local_port < 0) { 11124 return BCM_E_PORT; 11125 } 11126 BCM_IF_ERROR_RETURN 11127 (_bcm_th_cosq_index_resolve(unit, local_port, cosq, 11128 _BCM_TH_COSQ_INDEX_STYLE_MCAST_QUEUE, 11129 NULL, &startq, NULL)); 11130 } 11131 11132 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 11133 11134 base_mem = MMU_THDM_MCQE_QUEUE_CONFIGm; 11135 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 11136 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 11137 enable = soc_mem_field32_get(unit, mem, entry, Q_LIMIT_ENABLEf); 11138 if (enable != arg) { 11139 soc_mem_field32_set(unit, mem, entry, Q_LIMIT_ENABLEf, arg); 11140 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 11141 } 11142 11143 base_mem = MMU_THDM_DB_QUEUE_CONFIGm; 11144 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 11145 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 11146 enable = soc_mem_field32_get(unit, mem, entry, Q_LIMIT_ENABLEf); 11147 if (enable != arg) { 11148 soc_mem_field32_set(unit, mem, entry, Q_LIMIT_ENABLEf, arg); 11149 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 11150 } 11151 } else if (type == bcmCosqControlEgressMCQueueColorLimitEnable) { 11152 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 11153 return BCM_E_PARAM; 11154 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 11155 BCM_IF_ERROR_RETURN 11156 (_bcm_th_cosq_index_resolve(unit, gport, cosq, 11157 _BCM_TH_COSQ_INDEX_STYLE_MCAST_QUEUE, 11158 &local_port, &startq, NULL)); 11159 } else { 11160 if (cosq < 0) { 11161 return BCM_E_PARAM; 11162 } 11163 BCM_IF_ERROR_RETURN 11164 (_bcm_th_cosq_localport_resolve(unit, gport, &local_port)); 11165 if (local_port < 0) { 11166 return BCM_E_PORT; 11167 } 11168 BCM_IF_ERROR_RETURN 11169 (_bcm_th_cosq_index_resolve(unit, local_port, cosq, 11170 _BCM_TH_COSQ_INDEX_STYLE_MCAST_QUEUE, 11171 NULL, &startq, NULL)); 11172 } 11173 11174 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 11175 11176 base_mem = MMU_THDM_MCQE_QUEUE_CONFIGm; 11177 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 11178 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 11179 enable = soc_mem_field32_get(unit, mem, entry, Q_COLOR_LIMIT_ENABLEf); 11180 if (enable != arg) { 11181 soc_mem_field32_set(unit, mem, entry, Q_COLOR_LIMIT_ENABLEf, arg); 11182 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 11183 } 11184 11185 base_mem = MMU_THDM_DB_QUEUE_CONFIGm; 11186 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 11187 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 11188 enable = soc_mem_field32_get(unit, mem, entry, Q_COLOR_LIMIT_ENABLEf); 11189 if (enable != arg) { 11190 soc_mem_field32_set(unit, mem, entry, Q_COLOR_LIMIT_ENABLEf, arg); 11191 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 11192 } 11193 } else { 11194 return BCM_E_PARAM; 11195 } 11196 11197 return BCM_E_NONE; 11198 } 11199 11200 STATIC int 11201 _bcm_th_cosq_egr_queue_limit_enable_get(int unit, bcm_gport_t gport, 11202 bcm_cos_queue_t cosq, 11203 bcm_cosq_control_t type, 11204 int *arg) 11205 { 11206 bcm_port_t local_port; 11207 int startq, pipe; 11208 uint32 entry[SOC_MAX_MEM_WORDS]; 11209 soc_mem_t mem = INVALIDm, base_mem = INVALIDm; 11210 soc_field_t field_name = INVALIDf; 11211 11212 if ((type == bcmCosqControlEgressUCQueueLimitEnable) || 11213 (type == bcmCosqControlEgressUCQueueColorLimitEnable)) { 11214 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 11215 BCM_IF_ERROR_RETURN 11216 (_bcm_th_cosq_index_resolve(unit, gport, cosq, 11217 _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE, 11218 &local_port, &startq, NULL)); 11219 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 11220 return BCM_E_PARAM; 11221 } else { 11222 if (cosq < 0) { 11223 return BCM_E_PARAM; 11224 } 11225 BCM_IF_ERROR_RETURN 11226 (_bcm_th_cosq_localport_resolve(unit, gport, &local_port)); 11227 if (local_port < 0) { 11228 return BCM_E_PORT; 11229 } 11230 BCM_IF_ERROR_RETURN 11231 (_bcm_th_cosq_index_resolve 11232 (unit, local_port, cosq, _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE, 11233 NULL, &startq, NULL)); 11234 } 11235 11236 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 11237 11238 base_mem = MMU_THDU_Q_TO_QGRP_MAPm; 11239 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 11240 if (type == bcmCosqControlEgressUCQueueLimitEnable) { 11241 field_name = Q_LIMIT_ENABLEf; 11242 } else if (type == bcmCosqControlEgressUCQueueColorLimitEnable) { 11243 field_name = Q_COLOR_ENABLE_CELLf; 11244 } 11245 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 11246 *arg = soc_mem_field32_get(unit, mem, entry, field_name); 11247 } else if ((type == bcmCosqControlEgressMCQueueLimitEnable) || 11248 (type == bcmCosqControlEgressMCQueueColorLimitEnable)) { 11249 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 11250 return BCM_E_PARAM; 11251 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 11252 BCM_IF_ERROR_RETURN 11253 (_bcm_th_cosq_index_resolve(unit, gport, cosq, 11254 _BCM_TH_COSQ_INDEX_STYLE_MCAST_QUEUE, 11255 &local_port, &startq, NULL)); 11256 } else { 11257 if (cosq < 0) { 11258 return BCM_E_PARAM; 11259 } 11260 BCM_IF_ERROR_RETURN 11261 (_bcm_th_cosq_localport_resolve(unit, gport, &local_port)); 11262 if (local_port < 0) { 11263 return BCM_E_PORT; 11264 } 11265 BCM_IF_ERROR_RETURN 11266 (_bcm_th_cosq_index_resolve(unit, local_port, cosq, 11267 _BCM_TH_COSQ_INDEX_STYLE_MCAST_QUEUE, 11268 NULL, &startq, NULL)); 11269 } 11270 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 11271 11272 base_mem = MMU_THDM_MCQE_QUEUE_CONFIGm; 11273 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 11274 11275 if (type == bcmCosqControlEgressMCQueueLimitEnable) { 11276 base_mem = MMU_THDM_MCQE_QUEUE_CONFIGm; 11277 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 11278 field_name = Q_LIMIT_ENABLEf; 11279 } else if (type == bcmCosqControlEgressMCQueueColorLimitEnable) { 11280 base_mem = MMU_THDM_DB_QUEUE_CONFIGm; 11281 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 11282 field_name = Q_COLOR_LIMIT_ENABLEf; 11283 } 11284 11285 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 11286 *arg = soc_mem_field32_get(unit, mem, entry, field_name); 11287 } else { 11288 return BCM_E_PARAM; 11289 } 11290 return BCM_E_NONE; 11291 } 11292 11293 /* 11294 * This function is used to get ingress pool 11295 * limit given Ingress [Port, Priority] 11296 */ 11297 STATIC int 11298 _bcm_th_cosq_ing_res_limit_get(int unit, bcm_gport_t gport, bcm_cos_t cosq, 11299 bcm_cosq_buffer_id_t buffer, 11300 bcm_cosq_control_t type, int *arg) 11301 { 11302 uint32 rval = 0x0; 11303 int pool; 11304 int local_port, pipe, layer, xpe; 11305 soc_reg_t reg = INVALIDr; 11306 soc_field_t fld_limit = INVALIDf; 11307 11308 if (arg == NULL) { 11309 return BCM_E_PARAM; 11310 } 11311 11312 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 11313 BCM_GPORT_IS_SCHEDULER(gport) || 11314 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 11315 return BCM_E_PARAM; 11316 } 11317 11318 BCM_IF_ERROR_RETURN 11319 (_bcm_th_cosq_localport_resolve(unit, gport, &local_port)); 11320 11321 if (!SOC_PORT_VALID(unit, local_port)) { 11322 return BCM_E_PORT; 11323 } 11324 11325 if (type == bcmCosqControlIngressPoolLimitBytes || 11326 type == bcmCosqControlIngressPoolResetOffsetLimitBytes) { 11327 BCM_IF_ERROR_RETURN 11328 (_bcm_th_cosq_ing_pool_get(unit, gport, cosq, 11329 bcmCosqControlIngressPool, 11330 &pool)); 11331 if (type == bcmCosqControlIngressPoolLimitBytes) { 11332 reg = THDI_BUFFER_CELL_LIMIT_SPr; 11333 fld_limit = LIMITf; 11334 } else { /* bcmCosqControlIngressPoolResetOffsetLimitBytes */ 11335 reg = THDI_CELL_RESET_LIMIT_OFFSET_SPr; 11336 fld_limit = OFFSETf; 11337 } 11338 } else if (type == bcmCosqControlIngressHeadroomPoolLimitBytes) { 11339 BCM_IF_ERROR_RETURN 11340 (_bcm_th_cosq_ing_pool_get(unit, gport, cosq, 11341 bcmCosqControlIngressHeadroomPool, 11342 &pool)); 11343 reg = THDI_HDRM_BUFFER_CELL_LIMIT_HPr; 11344 fld_limit = LIMITf; 11345 } else if (type == bcmCosqControlIngressPublicPoolLimitBytes) { 11346 pool = -1; 11347 reg = THDI_BUFFER_CELL_LIMIT_PUBLIC_POOLr; 11348 fld_limit = LIMITf; 11349 } else { 11350 return BCM_E_PARAM; 11351 } 11352 11353 SOC_IF_ERROR_RETURN( 11354 soc_port_pipe_get(unit, local_port, &pipe)); 11355 SOC_IF_ERROR_RETURN( 11356 soc_tomahawk_mmu_layer_get(unit, pipe, &layer)); 11357 11358 if (buffer == BCM_COSQ_BUFFER_ID_INVALID) { 11359 xpe = -1; 11360 } else if (SOC_INFO(unit).ipipe_xpe_map[pipe] & (1 << buffer)) { 11361 xpe = buffer; 11362 } else { 11363 return BCM_E_PARAM; 11364 } 11365 11366 SOC_IF_ERROR_RETURN( 11367 soc_tomahawk_xpe_reg32_get(unit,reg, 11368 xpe, layer, pool, &rval)); 11369 *arg = soc_reg_field_get(unit, reg, rval, fld_limit); 11370 11371 *arg *= _TH_MMU_BYTES_PER_CELL; 11372 11373 return BCM_E_NONE; 11374 } 11375 11376 /* 11377 * This function is used to set ingress pool 11378 * limit given Ingress [Port, Priority] 11379 */ 11380 STATIC int 11381 _bcm_th_cosq_ing_res_limit_set(int unit, bcm_gport_t gport, bcm_cos_t cosq, 11382 bcm_cosq_buffer_id_t buffer, 11383 bcm_cosq_control_t type, int arg) 11384 { 11385 uint32 rval = 0x0; 11386 int pool; 11387 int local_port, pipe, layer, xpe; 11388 soc_reg_t reg = INVALIDr; 11389 soc_field_t fld_limit = INVALIDf; 11390 int max_value; 11391 int pool_limit = 0; 11392 int headroom_limit = 0; 11393 int public_limit = 0; 11394 int total_limit = 0; 11395 int mmu_total_cells = 0; 11396 11397 if (arg < 0) { 11398 return BCM_E_PARAM; 11399 } 11400 11401 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 11402 BCM_GPORT_IS_SCHEDULER(gport) || 11403 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 11404 return BCM_E_PARAM; 11405 } 11406 BCM_IF_ERROR_RETURN 11407 (_bcm_th_cosq_localport_resolve(unit, gport, &local_port)); 11408 11409 if (!SOC_PORT_VALID(unit, local_port)) { 11410 return BCM_E_PORT; 11411 } 11412 11413 BCM_IF_ERROR_RETURN(_bcm_th_cosq_ing_res_limit_get( 11414 unit, gport, cosq, buffer, 11415 bcmCosqControlIngressPoolLimitBytes, &pool_limit)); 11416 BCM_IF_ERROR_RETURN(_bcm_th_cosq_ing_res_limit_get( 11417 unit, gport, cosq, buffer, 11418 bcmCosqControlIngressHeadroomPoolLimitBytes, &headroom_limit)); 11419 BCM_IF_ERROR_RETURN(_bcm_th_cosq_ing_res_limit_get( 11420 unit, gport, cosq, buffer, 11421 bcmCosqControlIngressPublicPoolLimitBytes, &public_limit)); 11422 11423 if (type == bcmCosqControlIngressPoolLimitBytes || 11424 type == bcmCosqControlIngressPoolResetOffsetLimitBytes) { 11425 BCM_IF_ERROR_RETURN 11426 (_bcm_th_cosq_ing_pool_get(unit, gport, cosq, 11427 bcmCosqControlIngressPool, 11428 &pool)); 11429 if (type == bcmCosqControlIngressPoolLimitBytes) { 11430 reg = THDI_BUFFER_CELL_LIMIT_SPr; 11431 fld_limit = LIMITf; 11432 total_limit = arg + headroom_limit + public_limit; 11433 } else { /* bcmCosqControlIngressPoolResetOffsetLimitBytes */ 11434 reg = THDI_CELL_RESET_LIMIT_OFFSET_SPr; 11435 fld_limit = OFFSETf; 11436 } 11437 #ifdef BCM_TOMAHAWK2_SUPPORT 11438 if (SOC_IS_TOMAHAWK2(unit)) { 11439 max_value = _TH2_THDI_BUFFER_CELL_LIMIT_SP_MAX; 11440 } else 11441 #endif 11442 #ifdef BCM_TOMAHAWKPLUS_SUPPORT 11443 if (SOC_IS_TOMAHAWKPLUS(unit)) { 11444 max_value = _THP_THDI_BUFFER_CELL_LIMIT_SP_MAX; 11445 } else 11446 #endif 11447 { 11448 max_value = _TH_THDI_BUFFER_CELL_LIMIT_SP_MAX; 11449 } 11450 } else if (type == bcmCosqControlIngressHeadroomPoolLimitBytes) { 11451 BCM_IF_ERROR_RETURN 11452 (_bcm_th_cosq_ing_pool_get(unit, gport, cosq, 11453 bcmCosqControlIngressHeadroomPool, 11454 &pool)); 11455 reg = THDI_HDRM_BUFFER_CELL_LIMIT_HPr; 11456 fld_limit = LIMITf; 11457 total_limit = arg + pool_limit + public_limit; 11458 #ifdef BCM_TOMAHAWK2_SUPPORT 11459 if (SOC_IS_TOMAHAWK2(unit)) { 11460 max_value = _TH2_THDI_HDRM_BUFFER_CELL_LIMIT_HP_MAX; 11461 } else 11462 #endif 11463 #ifdef BCM_TOMAHAWKPLUS_SUPPORT 11464 if (SOC_IS_TOMAHAWKPLUS(unit)) { 11465 max_value = _THP_THDI_HDRM_BUFFER_CELL_LIMIT_HP_MAX; 11466 } else 11467 #endif 11468 { 11469 max_value = _TH_THDI_HDRM_BUFFER_CELL_LIMIT_HP_MAX; 11470 } 11471 } else if (type == bcmCosqControlIngressPublicPoolLimitBytes) { 11472 reg = THDI_BUFFER_CELL_LIMIT_PUBLIC_POOLr; 11473 fld_limit = LIMITf; 11474 total_limit = arg + pool_limit + headroom_limit; 11475 #ifdef BCM_TOMAHAWK2_SUPPORT 11476 if (SOC_IS_TOMAHAWK2(unit)) { 11477 max_value = _TH2_THDI_BUFFER_CELL_LIMIT_SP_MAX; 11478 } else 11479 #endif 11480 #ifdef BCM_TOMAHAWKPLUS_SUPPORT 11481 if (SOC_IS_TOMAHAWKPLUS(unit)) { 11482 max_value = _THP_THDI_BUFFER_CELL_LIMIT_SP_MAX; 11483 } else 11484 #endif 11485 { 11486 max_value = _TH_THDI_BUFFER_CELL_LIMIT_SP_MAX; 11487 } 11488 } else { 11489 return BCM_E_PARAM; 11490 } 11491 11492 arg = (arg + _TH_MMU_BYTES_PER_CELL - 1) / _TH_MMU_BYTES_PER_CELL; 11493 if (arg > max_value) { 11494 LOG_WARN(BSL_LS_BCM_COSQ, 11495 (BSL_META_U(unit, "Warning: Request of %d bytes exceeds maximum of %d bytes\n"), 11496 arg * _TH_MMU_BYTES_PER_CELL, 11497 max_value * _TH_MMU_BYTES_PER_CELL)); 11498 return BCM_E_PARAM; 11499 } 11500 total_limit = (total_limit + _TH_MMU_BYTES_PER_CELL - 1) / _TH_MMU_BYTES_PER_CELL; 11501 #ifdef BCM_TOMAHAWK2_SUPPORT 11502 if (SOC_IS_TOMAHAWK2(unit)) { 11503 mmu_total_cells = _TH2_MMU_TOTAL_CELLS_PER_XPE; 11504 } else 11505 #endif 11506 #ifdef BCM_TOMAHAWKPLUS_SUPPORT 11507 if (SOC_IS_TOMAHAWKPLUS(unit)) { 11508 mmu_total_cells = _THP_MMU_TOTAL_CELLS_PER_XPE; 11509 } else 11510 #endif 11511 { 11512 mmu_total_cells = _TH_MMU_TOTAL_CELLS_PER_XPE; 11513 } 11514 if (total_limit > mmu_total_cells) { 11515 LOG_WARN(BSL_LS_BCM_COSQ, 11516 (BSL_META_U(unit, "Warning: Total allocation of %d bytes exceeds maximum of %d bytes\n"), 11517 total_limit * _TH_MMU_BYTES_PER_CELL, 11518 mmu_total_cells * _TH_MMU_BYTES_PER_CELL)); 11519 return BCM_E_PARAM; 11520 } 11521 11522 soc_reg_field_set(unit, reg, &rval, fld_limit, arg); 11523 SOC_IF_ERROR_RETURN( 11524 soc_port_pipe_get(unit, local_port, &pipe)); 11525 SOC_IF_ERROR_RETURN( 11526 soc_tomahawk_mmu_layer_get(unit, pipe, &layer)); 11527 11528 if (buffer == BCM_COSQ_BUFFER_ID_INVALID) { 11529 xpe = -1; 11530 } else if (SOC_INFO(unit).ipipe_xpe_map[pipe] & (1 << buffer)) { 11531 xpe = buffer; 11532 } else { 11533 return BCM_E_PARAM; 11534 } 11535 11536 SOC_IF_ERROR_RETURN( 11537 soc_tomahawk_xpe_reg32_set(unit, reg, 11538 xpe, layer, pool, rval)); 11539 11540 if (type == bcmCosqControlIngressPoolLimitBytes) { 11541 int xpe_map = 0; 11542 if (xpe == -1) { 11543 xpe_map = SOC_INFO(unit).ipipe_xpe_map[pipe]; 11544 } else { 11545 xpe_map = 1 << xpe; 11546 } 11547 for (xpe = 0; xpe < NUM_XPE(unit); xpe++) { 11548 if (xpe_map & (1 << xpe)) { 11549 _BCM_TH_MMU_INFO(unit)->ing_shared_limit[xpe] = arg; 11550 } 11551 } 11552 } 11553 return BCM_E_NONE; 11554 } 11555 11556 /* 11557 * This function is used to set enables 11558 * for Qgroup Min and Shared Limits for a given Egress Unicast Queue 11559 */ 11560 STATIC int 11561 _bcm_th_cosq_qgroup_limit_enables_set(int unit, bcm_gport_t gport, 11562 bcm_cos_t cosq, bcm_cosq_control_t type, 11563 int arg) 11564 { 11565 bcm_port_t local_port; 11566 int startq=0, pipe=0, count=1, lc=0, to_cos=0; 11567 uint32 entry[SOC_MAX_MEM_WORDS], entry2[SOC_MAX_MEM_WORDS]; 11568 soc_mem_t mem = INVALIDm, base_mem = INVALIDm; 11569 int enable; 11570 int valid; 11571 soc_field_t field = INVALIDf; 11572 soc_field_t field2 = INVALIDf; 11573 int new_shared_limit_cell, egr_qe_shd_size[_TH_XPES_PER_DEV], egr_db_shd_size[_TH_XPES_PER_DEV]; 11574 int rv; 11575 int xpe, temp_val, pipe2=-1; 11576 uint32 pipe_map; 11577 soc_info_t *si=&SOC_INFO(unit); 11578 11579 if (arg < 0) { 11580 return BCM_E_PARAM; 11581 } 11582 arg = arg ? 1 : 0; 11583 11584 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 11585 BCM_IF_ERROR_RETURN 11586 (_bcm_th_cosq_index_resolve(unit, gport, cosq, 11587 _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE, 11588 &local_port, &startq, NULL)); 11589 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 11590 return BCM_E_PARAM; 11591 } else { 11592 if (cosq < -1) { 11593 return BCM_E_PARAM; 11594 } 11595 BCM_IF_ERROR_RETURN 11596 (_bcm_th_cosq_localport_resolve(unit, gport, &local_port)); 11597 if (local_port < 0) { 11598 return BCM_E_PORT; 11599 } 11600 BCM_IF_ERROR_RETURN 11601 (_bcm_th_cosq_index_resolve 11602 (unit, local_port, cosq, _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE, 11603 NULL, &startq, &count)); 11604 } 11605 11606 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 11607 base_mem = MMU_THDU_Q_TO_QGRP_MAPm; 11608 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 11609 if (type == bcmCosqControlEgressUCQueueGroupSharedLimitEnable) { 11610 field = QGROUP_LIMIT_ENABLEf; 11611 field2 = QGROUP_VALIDf; 11612 } else if (type == bcmCosqControlEgressUCQueueGroupMinEnable) { 11613 field = USE_QGROUP_MINf; 11614 field2 = QGROUP_VALIDf; 11615 } else { 11616 return BCM_E_PARAM; 11617 } 11618 11619 to_cos = startq + count; 11620 for (lc = startq; lc < to_cos; lc++) { 11621 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, 11622 lc, entry)); 11623 enable = soc_mem_field32_get(unit, mem, entry, field); 11624 if (enable != arg) { 11625 soc_mem_field32_set(unit, mem, entry, field, arg); 11626 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, 11627 lc, entry)); 11628 } 11629 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, 11630 lc, entry2)); 11631 valid = soc_mem_field32_get(unit, mem, entry2, field2); 11632 if (valid != 1) { 11633 soc_mem_field32_set(unit, mem, entry2, field2, 1); 11634 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, 11635 lc, entry2)); 11636 } 11637 } 11638 11639 /*If qgroup min limit enable is being set, 11640 *buffer shared limits need to be recalculated 11641 */ 11642 if (type == bcmCosqControlEgressUCQueueGroupMinEnable) { 11643 sal_memcpy(egr_db_shd_size, _BCM_TH_MMU_INFO(unit)->egr_db_shared_limit, 11644 sizeof(egr_db_shd_size)); 11645 sal_memcpy(egr_qe_shd_size, _BCM_TH_MMU_INFO(unit)->egr_qe_shared_limit, 11646 sizeof(egr_qe_shd_size)); 11647 /*Calculate the new value of shared limit*/ 11648 soc_th_recalc_new_egress_shared_limit(unit, pipe, 11649 &new_shared_limit_cell); 11650 /*Getting the two egress pipes with the new value of shared limit*/ 11651 for (xpe = 0; xpe < NUM_XPE(unit); xpe++) { 11652 pipe_map = si->xpe_epipe_map[xpe]; 11653 if (pipe_map & (1 << pipe)) { 11654 count = 0; 11655 while(pipe_map) { 11656 temp_val = (pipe_map >> 1); 11657 if ((temp_val != 0) && (count != pipe)) { 11658 pipe2=count; 11659 break; 11660 } 11661 count++; 11662 } 11663 } 11664 } 11665 /*Assign new value to both xpes for the egress pipe*/ 11666 egr_db_shd_size[pipe] = new_shared_limit_cell; 11667 if (pipe2!=-1) { 11668 egr_db_shd_size[pipe2] = new_shared_limit_cell; 11669 } 11670 /*Passing the modified values to the funtion to re-adjust shared limits*/ 11671 rv = soc_th_mmu_config_res_limits_update(unit, 2 /* egr */, NULL, 11672 egr_db_shd_size, 11673 egr_qe_shd_size, 1); 11674 if (rv < 0) { 11675 return rv; 11676 } 11677 sal_memcpy( _BCM_TH_MMU_INFO(unit)->egr_db_shared_limit,egr_db_shd_size, 11678 sizeof(egr_db_shd_size)); 11679 } 11680 return BCM_E_NONE; 11681 } 11682 11683 /* 11684 * This function is used to get enables 11685 * for Qgroup Min and Shared Limits for a given Egress Unicast Queue 11686 */ 11687 STATIC int 11688 _bcm_th_cosq_qgroup_limit_enables_get(int unit, bcm_gport_t gport, 11689 bcm_cos_queue_t cosq, 11690 bcm_cosq_control_t type, 11691 int *arg) 11692 { 11693 bcm_port_t local_port; 11694 int startq, pipe; 11695 uint32 entry[SOC_MAX_MEM_WORDS]; 11696 soc_mem_t mem = INVALIDm, base_mem = INVALIDm; 11697 soc_field_t field = INVALIDf; 11698 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 11699 BCM_IF_ERROR_RETURN 11700 (_bcm_th_cosq_index_resolve(unit, gport, cosq, 11701 _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE, 11702 &local_port, &startq, NULL)); 11703 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 11704 return BCM_E_PARAM; 11705 } else { 11706 if (cosq < 0) { 11707 return BCM_E_PARAM; 11708 } 11709 BCM_IF_ERROR_RETURN 11710 (_bcm_th_cosq_localport_resolve(unit, gport, &local_port)); 11711 if (local_port < 0) { 11712 return BCM_E_PORT; 11713 } 11714 BCM_IF_ERROR_RETURN 11715 (_bcm_th_cosq_index_resolve 11716 (unit, local_port, cosq, _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE, 11717 NULL, &startq, NULL)); 11718 } 11719 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 11720 base_mem = MMU_THDU_Q_TO_QGRP_MAPm; 11721 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 11722 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 11723 if (type == bcmCosqControlEgressUCQueueGroupMinEnable) { 11724 field = USE_QGROUP_MINf; 11725 } else if (type == bcmCosqControlEgressUCQueueGroupSharedLimitEnable) { 11726 field = QGROUP_LIMIT_ENABLEf; 11727 } else { 11728 return BCM_E_PARAM; 11729 } 11730 *arg = soc_mem_field32_get(unit, mem, entry, field); 11731 return BCM_E_NONE; 11732 } 11733 11734 /* 11735 * This function is used to set limits 11736 * for Qgroup Min and Shared Limits for a given Egress Unicast Queue 11737 */ 11738 STATIC int 11739 _bcm_th_cosq_qgroup_limit_set(int unit, bcm_gport_t gport, bcm_cos_t cosq, 11740 bcm_cosq_control_t type, int arg) 11741 { 11742 bcm_port_t local_port; 11743 int phy_port, pipe; 11744 uint32 entry[SOC_MAX_MEM_WORDS]; 11745 soc_mem_t mem = INVALIDm, base_mem = INVALIDm; 11746 soc_field_t field = INVALIDf; 11747 int mmu_port; /* global mmu port number */ 11748 int local_mmu_port; /* local mmu port number - local to per pipe */ 11749 soc_info_t *si; 11750 int granularity; 11751 int egr_db_shd_size[_TH_XPES_PER_DEV], egr_qe_shd_size[_TH_XPES_PER_DEV], cur_val; 11752 int rv, xpe; 11753 int delta[_TH_XPES_PER_DEV] = {0}; 11754 int max_val; 11755 uint32 xpe_map; 11756 si = &SOC_INFO(unit); 11757 11758 if (cosq < 0) { 11759 return BCM_E_PARAM; 11760 } 11761 BCM_IF_ERROR_RETURN 11762 (_bcm_th_cosq_localport_resolve(unit, gport, &local_port)); 11763 if (local_port < 0) { 11764 return BCM_E_PORT; 11765 } 11766 11767 if (type == bcmCosqControlEgressUCQueueGroupMinLimitBytes || 11768 type == bcmCosqControlEgressUCQueueGroupSharedLimitBytes) { 11769 arg = (arg + _TH_MMU_BYTES_PER_CELL - 1) / _TH_MMU_BYTES_PER_CELL; 11770 } 11771 11772 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 11773 phy_port = si->port_l2p_mapping[local_port]; 11774 mmu_port = si->port_p2m_mapping[phy_port]; 11775 local_mmu_port = mmu_port & (SOC_TH_MMU_PORT_STRIDE - 1); 11776 base_mem = MMU_THDU_CONFIG_QGROUPm; 11777 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 11778 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, local_mmu_port, 11779 entry)); 11780 11781 if (type == bcmCosqControlEgressUCQueueGroupMinLimitBytes) { 11782 field = Q_MIN_LIMIT_CELLf; 11783 granularity =1; 11784 /* Recalculate Shared Values if Min Changed */ 11785 sal_memcpy(egr_db_shd_size, _BCM_TH_MMU_INFO(unit)->egr_db_shared_limit, 11786 sizeof(egr_db_shd_size)); 11787 sal_memcpy(egr_qe_shd_size, _BCM_TH_MMU_INFO(unit)->egr_qe_shared_limit, 11788 sizeof(egr_qe_shd_size)); 11789 11790 cur_val = soc_mem_field32_get(unit, mem, entry, field); 11791 /* adjustment delta */ 11792 xpe_map = SOC_INFO(unit).epipe_xpe_map[pipe]; 11793 for (xpe = 0; xpe < NUM_XPE(unit); xpe ++) { 11794 if (xpe_map & (1 << xpe)) { 11795 delta[xpe] = ((arg / granularity) - cur_val) * granularity; 11796 } 11797 } 11798 /* shared limits to be increased/decreased */ 11799 for (xpe = 0; xpe < NUM_XPE(unit); xpe ++) { 11800 if ((xpe_map & (1 << xpe)) && (delta[xpe] > 0)) { 11801 /* no space to decrease shared limit */ 11802 if (delta[xpe] > egr_db_shd_size[xpe]) { 11803 return BCM_E_PARAM; 11804 } 11805 egr_db_shd_size[xpe] -= delta[xpe]; 11806 } 11807 if ((xpe_map & (1 << xpe)) && (delta[xpe] < 0)) { 11808 egr_db_shd_size[xpe] -= delta[xpe]; 11809 } 11810 } 11811 11812 rv = soc_th_mmu_config_res_limits_update(unit, 2 /* egr */, NULL, 11813 egr_db_shd_size , 11814 egr_qe_shd_size, 1); 11815 if (rv < 0) { 11816 return rv; 11817 } 11818 11819 sal_memcpy(_BCM_TH_MMU_INFO(unit)->egr_db_shared_limit,egr_db_shd_size, 11820 sizeof(egr_db_shd_size)); 11821 } else if (type == bcmCosqControlEgressUCQueueGroupSharedLimitBytes) { 11822 field = Q_SHARED_LIMIT_CELLf; 11823 granularity = 1; 11824 } else if (type == bcmCosqControlEgressUCQueueGroupSharedDynamicEnable) { 11825 field = Q_LIMIT_DYNAMIC_CELLf; 11826 granularity = 1; 11827 } else { 11828 return BCM_E_PARAM; 11829 } 11830 11831 /* Check for min/max values */ 11832 max_val = (1 << soc_mem_field_length(unit, mem, field)) - 1; 11833 if ((arg < 0) || ((arg/granularity) > max_val)) { 11834 return BCM_E_PARAM; 11835 } else { 11836 soc_mem_field32_set(unit, mem, entry, field, (arg/granularity)); 11837 } 11838 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, local_mmu_port, 11839 entry)); 11840 return BCM_E_NONE; 11841 } 11842 11843 /* 11844 * This function is used to get limits 11845 * for Qgroup Min and Shared Limits for a given Egress Unicast Queue 11846 */ 11847 11848 STATIC int 11849 _bcm_th_cosq_qgroup_limit_get(int unit, bcm_gport_t gport, bcm_cos_t cosq, 11850 bcm_cosq_control_t type, int *arg) 11851 { 11852 bcm_port_t local_port; 11853 int phy_port, pipe; 11854 uint32 entry[SOC_MAX_MEM_WORDS]; 11855 soc_mem_t mem = INVALIDm, base_mem = INVALIDm ; 11856 soc_field_t field = INVALIDf; 11857 int mmu_port; /* global mmu port number */ 11858 int local_mmu_port; /* local mmu port number - local to per pipe */ 11859 soc_info_t *si; 11860 si = &SOC_INFO(unit); 11861 if (cosq < 0) { 11862 return BCM_E_PARAM; 11863 } 11864 BCM_IF_ERROR_RETURN 11865 (_bcm_th_cosq_localport_resolve(unit, gport, &local_port)); 11866 if (local_port < 0) { 11867 return BCM_E_PORT; 11868 } 11869 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 11870 phy_port = si->port_l2p_mapping[local_port]; 11871 mmu_port = si->port_p2m_mapping[phy_port]; 11872 local_mmu_port = mmu_port & (SOC_TH_MMU_PORT_STRIDE - 1); 11873 base_mem = MMU_THDU_CONFIG_QGROUPm; 11874 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 11875 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, local_mmu_port, 11876 entry)); 11877 if (type == bcmCosqControlEgressUCQueueGroupMinLimitBytes) { 11878 field = Q_MIN_LIMIT_CELLf; 11879 } else if (type == bcmCosqControlEgressUCQueueGroupSharedLimitBytes) { 11880 field = Q_SHARED_LIMIT_CELLf; 11881 } else if (type == bcmCosqControlEgressUCQueueGroupSharedDynamicEnable) { 11882 field = Q_LIMIT_DYNAMIC_CELLf; 11883 } else { 11884 return BCM_E_PARAM; 11885 } 11886 *arg = soc_mem_field32_get(unit, mem, entry, field); 11887 if (type == bcmCosqControlEgressUCQueueGroupMinLimitBytes || 11888 type == bcmCosqControlEgressUCQueueGroupSharedLimitBytes) { 11889 *arg = (*arg) * _TH_MMU_BYTES_PER_CELL; 11890 } 11891 return BCM_E_NONE; 11892 } 11893 11894 int 11895 bcm_th_cosq_priority_mapping_get_all(int unit, bcm_gport_t gport, int index, 11896 bcm_cosq_priority_mapping_t type, 11897 int pri_max, int *pri_array, 11898 int *pri_count) 11899 { 11900 bcm_port_t port; 11901 int i, pg, sp, count = 0; 11902 11903 BCM_IF_ERROR_RETURN(_bcm_th_cosq_localport_resolve(unit, gport, &port)); 11904 if (!SOC_PORT_VALID(unit, port)) { 11905 return BCM_E_PORT; 11906 } 11907 11908 switch (type) { 11909 case bcmCosqPriorityGroup: 11910 if ((index < TH_PRIOROTY_GROUP_ID_MIN) || 11911 (index > TH_PRIOROTY_GROUP_ID_MAX)) { 11912 return BCM_E_PARAM; 11913 } 11914 for (i = 0; i < 16; i++) { 11915 BCM_IF_ERROR_RETURN 11916 (bcm_th_port_priority_group_mapping_get(unit, gport, 11917 i, &pg)); 11918 if (pg == index) { 11919 if (pri_max != 0 && pri_array != NULL) { 11920 if (count < pri_max) { 11921 pri_array[count] = i; 11922 } 11923 } 11924 count++; 11925 } 11926 } 11927 break; 11928 case bcmCosqIngressPool: 11929 if ((index < 0) || (index >= _TH_MMU_NUM_POOL)) { 11930 return BCM_E_PARAM; 11931 } 11932 for (i = 0; i < 16; i++) { 11933 BCM_IF_ERROR_RETURN 11934 (_bcm_th_cosq_ing_pool_get(unit, gport, i, 11935 bcmCosqControlIngressPool, 11936 &sp)); 11937 if (sp == index) { 11938 if (pri_max != 0 && pri_array != NULL) { 11939 if (count < pri_max) { 11940 pri_array[count] = i; 11941 } 11942 } 11943 count++; 11944 } 11945 } 11946 break; 11947 default: 11948 return BCM_E_UNAVAIL; 11949 } 11950 11951 if ((count < pri_max) && (pri_array != NULL)) { 11952 for (i = count; i < pri_max; i++) { 11953 pri_array[i] = -1; 11954 } 11955 *pri_count = count; 11956 } else if (pri_max == 0) { 11957 *pri_count = count; 11958 } else { 11959 *pri_count = pri_max; 11960 } 11961 return BCM_E_NONE; 11962 } 11963 11964 /* 11965 * Function: 11966 * bcm_th_cosq_control_set 11967 * Purpose: 11968 * Set specified feature configuration 11969 * 11970 * Parameters: 11971 * unit - (IN) Unit number. 11972 * port - (IN) GPORT ID. 11973 * cosq - (IN) COS queue. 11974 * buffer-(IN) XPE ID 11975 * type - (IN) feature 11976 * arg - (IN) feature value 11977 * Returns: 11978 * BCM_E_XXX 11979 * Notes: 11980 */ 11981 int 11982 bcm_th_cosq_control_set(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 11983 bcm_cosq_buffer_id_t buffer, 11984 bcm_cosq_control_t type, int arg) 11985 { 11986 uint32 kbits_burst_min, kbits_burst_max; 11987 uint32 kbits_burst; 11988 11989 kbits_burst_min = 0; 11990 kbits_burst_max = 0; 11991 11992 COMPILER_REFERENCE(kbits_burst_min); 11993 COMPILER_REFERENCE(kbits_burst_max); 11994 11995 switch (type) { 11996 case bcmCosqControlBandwidthBurstMax: 11997 kbits_burst = arg & 0x7fffffff; /* Convert to uint32 */ 11998 BCM_IF_ERROR_RETURN 11999 (bcm_th_cosq_gport_bandwidth_burst_get(unit, gport, cosq, 12000 &kbits_burst_min, 12001 &kbits_burst_max)); 12002 return bcm_th_cosq_gport_bandwidth_burst_set(unit, gport, cosq, 12003 kbits_burst_min, 12004 kbits_burst); 12005 case bcmCosqControlBandwidthBurstMin: 12006 kbits_burst = arg & 0x7fffffff; /* Convert to uint32 */ 12007 BCM_IF_ERROR_RETURN 12008 (bcm_th_cosq_gport_bandwidth_burst_get(unit, gport, cosq, 12009 &kbits_burst_min, 12010 &kbits_burst_max)); 12011 return bcm_th_cosq_gport_bandwidth_burst_set(unit, gport, cosq, 12012 kbits_burst, 12013 kbits_burst_max); 12014 case bcmCosqControlEgressPool: 12015 case bcmCosqControlEgressPoolLimitBytes: 12016 case bcmCosqControlEgressPoolYellowLimitBytes: 12017 case bcmCosqControlEgressPoolRedLimitBytes: 12018 case bcmCosqControlEgressPoolLimitEnable: 12019 case bcmCosqControlUCEgressPool: 12020 case bcmCosqControlMCEgressPool: 12021 case bcmCosqControlEgressPoolSharedLimitBytes: 12022 case bcmCosqControlEgressPoolResumeLimitBytes: 12023 case bcmCosqControlEgressPoolYellowSharedLimitBytes: 12024 case bcmCosqControlEgressPoolYellowResumeLimitBytes: 12025 case bcmCosqControlEgressPoolRedSharedLimitBytes: 12026 case bcmCosqControlEgressPoolRedResumeLimitBytes: 12027 case bcmCosqControlEgressPoolHighCongestionLimitBytes: 12028 case bcmCosqControlEgressPoolLowCongestionLimitBytes: 12029 return _bcm_th_cosq_egr_pool_set(unit, gport, cosq, buffer, type, arg); 12030 case bcmCosqControlEgressUCQueueSharedLimitBytes: 12031 case bcmCosqControlEgressMCQueueSharedLimitBytes: 12032 case bcmCosqControlEgressUCQueueMinLimitBytes: 12033 case bcmCosqControlEgressMCQueueMinLimitBytes: 12034 return _bcm_th_cosq_egr_queue_set(unit, gport, cosq, type, arg); 12035 case bcmCosqControlIngressPortPGSharedLimitBytes: 12036 case bcmCosqControlIngressPortPGMinLimitBytes: 12037 case bcmCosqControlIngressPortPoolMaxLimitBytes: 12038 case bcmCosqControlIngressPortPoolMinLimitBytes: 12039 case bcmCosqControlIngressPortPGHeadroomLimitBytes: 12040 case bcmCosqControlIngressPortPGResetFloorBytes: 12041 case bcmCosqControlIngressPortPGResetOffsetBytes: 12042 case bcmCosqControlIngressPortPoolResumeLimitBytes: 12043 return _bcm_th_cosq_ing_res_set(unit, gport, cosq, type, arg); 12044 case bcmCosqControlIngressPortPGGlobalHeadroomEnable: 12045 return _bcm_th_cosq_ing_res_enable_set(unit, gport, cosq, type, arg); 12046 case bcmCosqControlIngressPool: 12047 case bcmCosqControlIngressHeadroomPool: 12048 return _bcm_th_cosq_ing_pool_set(unit, gport, cosq, type, arg); 12049 case bcmCosqControlDropLimitAlpha: 12050 return _bcm_th_cosq_alpha_set(unit, gport, cosq, 12051 (bcm_cosq_control_drop_limit_alpha_value_t)arg); 12052 case bcmCosqControlIngressPortPGSharedDynamicEnable: 12053 case bcmCosqControlEgressUCSharedDynamicEnable: 12054 case bcmCosqControlEgressMCSharedDynamicEnable: 12055 return _bcm_th_cosq_dynamic_thresh_enable_set(unit, gport, cosq, 12056 type, arg); 12057 case bcmCosqControlEgressPortPoolYellowLimitBytes: 12058 case bcmCosqControlEgressPortPoolRedLimitBytes: 12059 case bcmCosqControlEgressPortPoolSharedLimitBytes: 12060 case bcmCosqControlEgressPortPoolRedResumeBytes: 12061 case bcmCosqControlEgressPortPoolYellowResumeBytes: 12062 case bcmCosqControlEgressPortPoolSharedResumeBytes: 12063 return _bcm_th_cosq_egr_port_pool_set(unit, gport, cosq, type, arg); 12064 case bcmCosqControlEgressUCQueueLimitEnable: 12065 case bcmCosqControlEgressMCQueueLimitEnable: 12066 case bcmCosqControlEgressMCQueueColorLimitEnable: 12067 case bcmCosqControlEgressUCQueueColorLimitEnable: 12068 return _bcm_th_cosq_egr_queue_limit_enable_set(unit, gport, cosq, 12069 type, arg); 12070 case bcmCosqControlIngressPoolLimitBytes: 12071 case bcmCosqControlIngressPoolResetOffsetLimitBytes: 12072 case bcmCosqControlIngressHeadroomPoolLimitBytes: 12073 case bcmCosqControlIngressPublicPoolLimitBytes: 12074 return _bcm_th_cosq_ing_res_limit_set(unit, gport, cosq, buffer, type, arg); 12075 case bcmCosqControlEgressUCQueueGroupMinEnable: 12076 case bcmCosqControlEgressUCQueueGroupSharedLimitEnable: 12077 return _bcm_th_cosq_qgroup_limit_enables_set(unit, gport, cosq, 12078 type, arg); 12079 case bcmCosqControlEgressUCQueueGroupMinLimitBytes: 12080 case bcmCosqControlEgressUCQueueGroupSharedLimitBytes: 12081 case bcmCosqControlEgressUCQueueGroupSharedDynamicEnable: 12082 return _bcm_th_cosq_qgroup_limit_set(unit, gport, cosq, type, arg); 12083 case bcmCosqControlEgressUCQueueColorLimitDynamicEnable: 12084 case bcmCosqControlEgressMCQueueColorLimitDynamicEnable: 12085 return _bcm_th_cosq_egr_queue_color_limit_mode_set(unit, gport, cosq, 12086 type, arg); 12087 case bcmCosqControlEgressUCQueueRedLimit: 12088 case bcmCosqControlEgressUCQueueYellowLimit: 12089 case bcmCosqControlEgressMCQueueRedLimit: 12090 case bcmCosqControlEgressMCQueueYellowLimit: 12091 return _bcm_th_cosq_egr_queue_color_limit_set(unit, gport, cosq, type, arg); 12092 12093 default: 12094 break; 12095 } 12096 return BCM_E_UNAVAIL; 12097 } 12098 12099 /* 12100 * Function: 12101 * bcm_th_cosq_control_get 12102 * Purpose: 12103 * Get specified feature configuration 12104 * 12105 * Parameters: 12106 * unit - (IN) Unit number. 12107 * port - (IN) GPORT ID. 12108 * cosq - (IN) COS queue. 12109 * buffer-(IN) XPE ID 12110 * type - (IN) feature 12111 * arg - (OUT) feature value 12112 * Returns: 12113 * BCM_E_XXX 12114 * Notes: 12115 */ 12116 int 12117 bcm_th_cosq_control_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 12118 bcm_cosq_buffer_id_t buffer, 12119 bcm_cosq_control_t type, int *arg) 12120 { 12121 uint32 kburst_tmp, kbits_burst; 12122 12123 switch (type) { 12124 case bcmCosqControlBandwidthBurstMax: 12125 BCM_IF_ERROR_RETURN 12126 (bcm_th_cosq_gport_bandwidth_burst_get(unit, gport, cosq, 12127 &kburst_tmp, 12128 &kbits_burst)); 12129 *arg = kbits_burst & 0x7fffffff; /* Convert to int */ 12130 return BCM_E_NONE; 12131 12132 case bcmCosqControlBandwidthBurstMin: 12133 return bcm_th_cosq_gport_bandwidth_burst_get(unit, gport, cosq, 12134 (uint32*)arg, 12135 &kburst_tmp); 12136 case bcmCosqControlEgressPool: 12137 case bcmCosqControlEgressPoolLimitBytes: 12138 case bcmCosqControlEgressPoolYellowLimitBytes: 12139 case bcmCosqControlEgressPoolRedLimitBytes: 12140 case bcmCosqControlEgressPoolLimitEnable: 12141 case bcmCosqControlUCEgressPool: 12142 case bcmCosqControlMCEgressPool: 12143 case bcmCosqControlEgressPoolSharedLimitBytes: 12144 case bcmCosqControlEgressPoolResumeLimitBytes: 12145 case bcmCosqControlEgressPoolYellowSharedLimitBytes: 12146 case bcmCosqControlEgressPoolYellowResumeLimitBytes: 12147 case bcmCosqControlEgressPoolRedSharedLimitBytes: 12148 case bcmCosqControlEgressPoolRedResumeLimitBytes: 12149 case bcmCosqControlEgressPoolHighCongestionLimitBytes: 12150 case bcmCosqControlEgressPoolLowCongestionLimitBytes: 12151 return _bcm_th_cosq_egr_pool_get(unit, gport, cosq, buffer, type, arg); 12152 case bcmCosqControlEgressUCQueueSharedLimitBytes: 12153 case bcmCosqControlEgressMCQueueSharedLimitBytes: 12154 case bcmCosqControlEgressUCQueueMinLimitBytes: 12155 case bcmCosqControlEgressMCQueueMinLimitBytes: 12156 return _bcm_th_cosq_egr_queue_get(unit, gport, cosq, type, arg); 12157 case bcmCosqControlIngressPortPGSharedLimitBytes: 12158 case bcmCosqControlIngressPortPGMinLimitBytes: 12159 case bcmCosqControlIngressPortPoolMaxLimitBytes: 12160 case bcmCosqControlIngressPortPoolMinLimitBytes: 12161 case bcmCosqControlIngressPortPGHeadroomLimitBytes: 12162 case bcmCosqControlIngressPortPGResetFloorBytes: 12163 case bcmCosqControlIngressPortPGResetOffsetBytes: 12164 case bcmCosqControlIngressPortPoolResumeLimitBytes: 12165 return _bcm_th_cosq_ing_res_get(unit, gport, cosq, type, arg); 12166 case bcmCosqControlIngressPortPGGlobalHeadroomEnable: 12167 return _bcm_th_cosq_ing_res_enable_get(unit, gport, cosq, type, arg); 12168 case bcmCosqControlIngressPool: 12169 case bcmCosqControlIngressHeadroomPool: 12170 return _bcm_th_cosq_ing_pool_get(unit, gport, cosq, type, arg); 12171 case bcmCosqControlDropLimitAlpha: 12172 return _bcm_th_cosq_alpha_get(unit, gport, cosq, 12173 (bcm_cosq_control_drop_limit_alpha_value_t *)arg); 12174 case bcmCosqControlIngressPortPGSharedDynamicEnable: 12175 case bcmCosqControlEgressUCSharedDynamicEnable: 12176 case bcmCosqControlEgressMCSharedDynamicEnable: 12177 return _bcm_th_cosq_dynamic_thresh_enable_get(unit, gport, cosq, 12178 type, arg); 12179 case bcmCosqControlEgressPortPoolYellowLimitBytes: 12180 case bcmCosqControlEgressPortPoolRedLimitBytes: 12181 case bcmCosqControlEgressPortPoolSharedLimitBytes: 12182 case bcmCosqControlEgressPortPoolRedResumeBytes: 12183 case bcmCosqControlEgressPortPoolYellowResumeBytes: 12184 case bcmCosqControlEgressPortPoolSharedResumeBytes: 12185 return _bcm_th_cosq_egr_port_pool_get(unit, gport, cosq, type, arg); 12186 case bcmCosqControlEgressUCQueueLimitEnable: 12187 case bcmCosqControlEgressMCQueueLimitEnable: 12188 case bcmCosqControlEgressMCQueueColorLimitEnable: 12189 case bcmCosqControlEgressUCQueueColorLimitEnable: 12190 return _bcm_th_cosq_egr_queue_limit_enable_get(unit, gport, cosq, 12191 type, arg); 12192 case bcmCosqControlIngressPoolLimitBytes: 12193 case bcmCosqControlIngressPoolResetOffsetLimitBytes: 12194 case bcmCosqControlIngressHeadroomPoolLimitBytes: 12195 case bcmCosqControlIngressPublicPoolLimitBytes: 12196 return _bcm_th_cosq_ing_res_limit_get(unit, gport, cosq, buffer, type, arg); 12197 case bcmCosqControlEgressUCQueueGroupMinEnable: 12198 case bcmCosqControlEgressUCQueueGroupSharedLimitEnable: 12199 return _bcm_th_cosq_qgroup_limit_enables_get(unit, gport, cosq, 12200 type, arg); 12201 case bcmCosqControlEgressUCQueueGroupMinLimitBytes: 12202 case bcmCosqControlEgressUCQueueGroupSharedLimitBytes: 12203 case bcmCosqControlEgressUCQueueGroupSharedDynamicEnable: 12204 return _bcm_th_cosq_qgroup_limit_get(unit, gport, cosq, type, arg); 12205 case bcmCosqControlEgressUCQueueColorLimitDynamicEnable: 12206 case bcmCosqControlEgressMCQueueColorLimitDynamicEnable: 12207 return _bcm_th_cosq_egr_queue_color_limit_mode_get(unit, gport, cosq, 12208 type, arg); 12209 case bcmCosqControlEgressUCQueueRedLimit: 12210 case bcmCosqControlEgressUCQueueYellowLimit: 12211 case bcmCosqControlEgressMCQueueRedLimit: 12212 case bcmCosqControlEgressMCQueueYellowLimit: 12213 return _bcm_th_cosq_egr_queue_color_limit_get(unit, gport, cosq, type, arg); 12214 12215 default: 12216 break; 12217 } 12218 return BCM_E_UNAVAIL; 12219 } 12220 12221 STATIC int 12222 _bcm_th_cosq_obmhighwatermark_set(int unit, bcm_port_t port, uint64 value) 12223 { 12224 int pipe, obm_id, obm_max, lane; 12225 soc_reg_t reg; 12226 uint64 rval64; 12227 soc_info_t *si; 12228 soc_reg_t obm_high_watermark_reg[] = { 12229 IDB_OBM0_MAX_USAGEr, IDB_OBM1_MAX_USAGEr, 12230 IDB_OBM2_MAX_USAGEr, IDB_OBM3_MAX_USAGEr, 12231 IDB_OBM4_MAX_USAGEr, IDB_OBM5_MAX_USAGEr, 12232 IDB_OBM6_MAX_USAGEr, IDB_OBM7_MAX_USAGEr, 12233 #ifdef BCM_TOMAHAWK2_SUPPORT 12234 IDB_OBM8_MAX_USAGEr, IDB_OBM9_MAX_USAGEr, 12235 IDB_OBM10_MAX_USAGEr, IDB_OBM11_MAX_USAGEr, 12236 IDB_OBM12_MAX_USAGEr, IDB_OBM13_MAX_USAGEr, 12237 IDB_OBM14_MAX_USAGEr, IDB_OBM15_MAX_USAGEr, 12238 #endif 12239 }; 12240 12241 soc_field_t obm_high_watermark_fields[] = { 12242 PORT0_MAX_USAGEf, PORT1_MAX_USAGEf, 12243 PORT2_MAX_USAGEf, PORT3_MAX_USAGEf 12244 }; 12245 12246 SOC_IF_ERROR_RETURN 12247 (soc_tomahawk_port_obm_info_get(unit, port, &obm_id, &lane)); 12248 #ifdef BCM_TOMAHAWK2_SUPPORT 12249 obm_max = SOC_IS_TOMAHAWK2(unit) ? _TH2_PBLKS_PER_PIPE : _TH_PBLKS_PER_PIPE; 12250 #else 12251 obm_max = _TH_PBLKS_PER_PIPE; 12252 #endif 12253 if (obm_id >= obm_max || (lane < 0 || lane >= _TH_PORTS_PER_PBLK)) { 12254 return BCM_E_PARAM; 12255 } 12256 if(!COMPILER_64_IS_ZERO(value)) { 12257 return BCM_E_PARAM; 12258 } 12259 si = &SOC_INFO(unit); 12260 pipe = si->port_pipe[port]; 12261 12262 reg = SOC_REG_UNIQUE_ACC(unit, obm_high_watermark_reg[obm_id])[pipe]; 12263 COMPILER_64_ZERO(rval64); 12264 BCM_IF_ERROR_RETURN 12265 (soc_reg64_get(unit, reg, REG_PORT_ANY, 0, &rval64)); 12266 12267 soc_reg64_field32_set(unit, reg, &rval64, obm_high_watermark_fields[lane], 0); 12268 BCM_IF_ERROR_RETURN 12269 (soc_reg64_set(unit, reg, REG_PORT_ANY, 0, rval64)); 12270 return BCM_E_NONE; 12271 } 12272 12273 STATIC int 12274 _bcm_th_cosq_obmhighwatermark_get(int unit, bcm_port_t port, uint64 *value) 12275 { 12276 int pipe, obm_id, obm_max, lane, gran; 12277 soc_reg_t reg; 12278 uint64 rval64; 12279 soc_info_t *si; 12280 soc_reg_t obm_high_watermark_reg[] = { 12281 IDB_OBM0_MAX_USAGEr, IDB_OBM1_MAX_USAGEr, 12282 IDB_OBM2_MAX_USAGEr, IDB_OBM3_MAX_USAGEr, 12283 IDB_OBM4_MAX_USAGEr, IDB_OBM5_MAX_USAGEr, 12284 IDB_OBM6_MAX_USAGEr, IDB_OBM7_MAX_USAGEr, 12285 #ifdef BCM_TOMAHAWK2_SUPPORT 12286 IDB_OBM8_MAX_USAGEr, IDB_OBM9_MAX_USAGEr, 12287 IDB_OBM10_MAX_USAGEr, IDB_OBM11_MAX_USAGEr, 12288 IDB_OBM12_MAX_USAGEr, IDB_OBM13_MAX_USAGEr, 12289 IDB_OBM14_MAX_USAGEr, IDB_OBM15_MAX_USAGEr, 12290 #endif 12291 }; 12292 12293 soc_field_t obm_high_watermark_fields[] = { 12294 PORT0_MAX_USAGEf, PORT1_MAX_USAGEf, 12295 PORT2_MAX_USAGEf, PORT3_MAX_USAGEf 12296 }; 12297 12298 SOC_IF_ERROR_RETURN 12299 (soc_tomahawk_port_obm_info_get(unit, port, &obm_id, &lane)); 12300 #ifdef BCM_TOMAHAWK2_SUPPORT 12301 obm_max = SOC_IS_TOMAHAWK2(unit) ? _TH2_PBLKS_PER_PIPE : _TH_PBLKS_PER_PIPE; 12302 #else 12303 obm_max = _TH_PBLKS_PER_PIPE; 12304 #endif 12305 if (obm_id >= obm_max || (lane < 0 || lane >= _TH_PORTS_PER_PBLK)) { 12306 return BCM_E_PARAM; 12307 } 12308 si = &SOC_INFO(unit); 12309 pipe = si->port_pipe[port]; 12310 12311 reg = SOC_REG_UNIQUE_ACC(unit, obm_high_watermark_reg[obm_id])[pipe]; 12312 COMPILER_64_ZERO(rval64); 12313 BCM_IF_ERROR_RETURN 12314 (soc_reg64_get(unit, reg, REG_PORT_ANY, 0, &rval64)); 12315 12316 *value = soc_reg64_field_get(unit, reg, rval64, obm_high_watermark_fields[lane]); 12317 gran = SOC_IS_TOMAHAWK2(unit) ? 16 : 48; 12318 COMPILER_64_UMUL_32(*value, gran); 12319 12320 return BCM_E_NONE; 12321 } 12322 12323 STATIC int 12324 _bcm_th_cosq_obm_buf_use_cnt_set(int unit, bcm_port_t port, uint64 value) 12325 { 12326 int pipe, obm_id, obm_max, lane; 12327 soc_reg_t reg; 12328 soc_field_t fld; 12329 uint64 rval64; 12330 soc_info_t *si; 12331 soc_reg_t obm_usage_reg[] = { 12332 IDB_OBM0_USAGEr, IDB_OBM1_USAGEr, 12333 IDB_OBM2_USAGEr, IDB_OBM3_USAGEr, 12334 IDB_OBM4_USAGEr, IDB_OBM5_USAGEr, 12335 IDB_OBM6_USAGEr, IDB_OBM7_USAGEr, 12336 #ifdef BCM_TOMAHAWK2_SUPPORT 12337 IDB_OBM8_USAGEr, IDB_OBM9_USAGEr, 12338 IDB_OBM10_USAGEr, IDB_OBM11_USAGEr, 12339 IDB_OBM12_USAGEr, IDB_OBM13_USAGEr, 12340 IDB_OBM14_USAGEr, IDB_OBM15_USAGEr, 12341 #endif 12342 }; 12343 12344 SOC_IF_ERROR_RETURN 12345 (soc_tomahawk_port_obm_info_get(unit, port, &obm_id, &lane)); 12346 #ifdef BCM_TOMAHAWK2_SUPPORT 12347 obm_max = SOC_IS_TOMAHAWK2(unit) ? _TH2_PBLKS_PER_PIPE : _TH_PBLKS_PER_PIPE; 12348 #else 12349 obm_max = _TH_PBLKS_PER_PIPE; 12350 #endif 12351 if (obm_id >= obm_max || (lane < 0 || lane >= _TH_PORTS_PER_PBLK)) { 12352 return BCM_E_PARAM; 12353 } 12354 if(!COMPILER_64_IS_ZERO(value)) { 12355 return BCM_E_PARAM; 12356 } 12357 si = &SOC_INFO(unit); 12358 pipe = si->port_pipe[port]; 12359 12360 reg = SOC_REG_UNIQUE_ACC(unit, obm_usage_reg[obm_id])[pipe]; 12361 fld = si->mmu_lossless ? LOSSLESS0_COUNTf : LOSSY_COUNTf; 12362 COMPILER_64_ZERO(rval64); 12363 BCM_IF_ERROR_RETURN 12364 (soc_reg64_get(unit, reg, REG_PORT_ANY, lane, &rval64)); 12365 12366 soc_reg64_field_set(unit, reg, &rval64, fld, value); 12367 BCM_IF_ERROR_RETURN 12368 (soc_reg64_set(unit, reg, REG_PORT_ANY, lane, rval64)); 12369 return BCM_E_NONE; 12370 } 12371 12372 STATIC int 12373 _bcm_th_cosq_obm_buf_use_cnt_get(int unit, bcm_port_t port, uint64 *value) 12374 { 12375 int pipe, obm_id, obm_max, lane, gran; 12376 soc_reg_t reg; 12377 soc_field_t fld; 12378 uint64 rval64; 12379 soc_info_t *si; 12380 soc_reg_t obm_usage_reg[] = { 12381 IDB_OBM0_USAGEr, IDB_OBM1_USAGEr, 12382 IDB_OBM2_USAGEr, IDB_OBM3_USAGEr, 12383 IDB_OBM4_USAGEr, IDB_OBM5_USAGEr, 12384 IDB_OBM6_USAGEr, IDB_OBM7_USAGEr, 12385 #ifdef BCM_TOMAHAWK2_SUPPORT 12386 IDB_OBM8_USAGEr, IDB_OBM9_USAGEr, 12387 IDB_OBM10_USAGEr, IDB_OBM11_USAGEr, 12388 IDB_OBM12_USAGEr, IDB_OBM13_USAGEr, 12389 IDB_OBM14_USAGEr, IDB_OBM15_USAGEr, 12390 #endif 12391 }; 12392 12393 SOC_IF_ERROR_RETURN 12394 (soc_tomahawk_port_obm_info_get(unit, port, &obm_id, &lane)); 12395 #ifdef BCM_TOMAHAWK2_SUPPORT 12396 obm_max = SOC_IS_TOMAHAWK2(unit) ? _TH2_PBLKS_PER_PIPE : _TH_PBLKS_PER_PIPE; 12397 #else 12398 obm_max = _TH_PBLKS_PER_PIPE; 12399 #endif 12400 if (obm_id >= obm_max || (lane < 0 || lane >= _TH_PORTS_PER_PBLK)) { 12401 return BCM_E_PARAM; 12402 } 12403 si = &SOC_INFO(unit); 12404 pipe = si->port_pipe[port]; 12405 12406 reg = SOC_REG_UNIQUE_ACC(unit, obm_usage_reg[obm_id])[pipe]; 12407 fld = si->mmu_lossless ? LOSSLESS0_COUNTf : LOSSY_COUNTf; 12408 COMPILER_64_ZERO(rval64); 12409 BCM_IF_ERROR_RETURN 12410 (soc_reg64_get(unit, reg, REG_PORT_ANY, lane, &rval64)); 12411 12412 *value = soc_reg64_field_get(unit, reg, rval64, fld); 12413 gran = SOC_IS_TOMAHAWK2(unit) ? 16 : 48; 12414 COMPILER_64_UMUL_32(*value, gran); 12415 12416 return BCM_E_NONE; 12417 } 12418 12419 int 12420 bcm_th_cosq_stat_set(int unit, bcm_gport_t port, bcm_cos_queue_t cosq, 12421 bcm_cosq_stat_t stat, uint64 value) 12422 { 12423 soc_ctr_control_info_t ctrl_info; 12424 soc_reg_t ctr_reg, ctr_reg_uc, ctr_reg_mc; 12425 _bcm_th_cosq_index_style_t style = _BCM_TH_COSQ_INDEX_STYLE_COUNT; 12426 int startq = 0, ci, from_cos, to_cos; 12427 bcm_port_t local_port = -1; 12428 12429 ctrl_info.instance = -1; 12430 ctrl_info.instance_type = SOC_CTR_INSTANCE_TYPE_XPE; 12431 12432 BCM_IF_ERROR_RETURN 12433 (_bcm_th_cosq_localport_resolve(unit, port, &local_port)); 12434 if ((cosq < -1) || (cosq >= _TH_PORT_NUM_COS(unit, local_port))) { 12435 return BCM_E_PARAM; 12436 } 12437 12438 switch (stat) { 12439 case bcmCosqStatDroppedPackets: 12440 case bcmCosqStatDroppedBytes: 12441 case bcmCosqStatOutPackets: 12442 case bcmCosqStatOutBytes: 12443 case bcmCosqStatUCOutPackets: 12444 case bcmCosqStatUCOutBytes: 12445 case bcmCosqStatMCOutPackets: 12446 case bcmCosqStatMCOutBytes: 12447 case bcmCosqStatDiscardUCDroppedPackets: 12448 style = _BCM_TH_COSQ_INDEX_STYLE_COS; 12449 if (stat == bcmCosqStatDroppedBytes) { 12450 ctr_reg_uc = SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE_UC; 12451 ctr_reg_mc = SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE; 12452 } else if (stat == bcmCosqStatDroppedPackets) { 12453 ctr_reg_uc = SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_UC; 12454 ctr_reg_mc = SOC_COUNTER_NON_DMA_COSQ_DROP_PKT; 12455 } else if (stat == bcmCosqStatUCOutBytes) { 12456 if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 12457 return BCM_E_PARAM; 12458 } 12459 ctr_reg_uc = SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE_UC; 12460 ctr_reg_mc = INVALIDr; 12461 ctrl_info.instance_type = SOC_CTR_INSTANCE_TYPE_PORT; 12462 } else if (stat == bcmCosqStatUCOutPackets) { 12463 if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 12464 return BCM_E_PARAM; 12465 } 12466 ctr_reg_uc = SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT_UC; 12467 ctr_reg_mc = INVALIDr; 12468 ctrl_info.instance_type = SOC_CTR_INSTANCE_TYPE_PORT; 12469 } else if (stat == bcmCosqStatMCOutBytes) { 12470 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) { 12471 return BCM_E_PARAM; 12472 } 12473 ctr_reg_uc = INVALIDr; 12474 ctr_reg_mc = SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE; 12475 ctrl_info.instance_type = SOC_CTR_INSTANCE_TYPE_PORT; 12476 } else if (stat == bcmCosqStatMCOutPackets) { 12477 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) { 12478 return BCM_E_PARAM; 12479 } 12480 ctr_reg_uc = INVALIDr; 12481 ctr_reg_mc = SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT; 12482 ctrl_info.instance_type = SOC_CTR_INSTANCE_TYPE_PORT; 12483 } else if (stat == bcmCosqStatOutBytes) { 12484 ctr_reg_uc = SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE_UC; 12485 ctr_reg_mc = SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE; 12486 ctrl_info.instance_type = SOC_CTR_INSTANCE_TYPE_PORT; 12487 } else if (stat == bcmCosqStatDiscardUCDroppedPackets) { 12488 if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) || 12489 BCM_GPORT_IS_SCHEDULER(port)) { 12490 return BCM_E_PARAM; 12491 } 12492 ctr_reg_uc = SOC_COUNTER_NON_DMA_COSQ_DROP_WRED_PKT; 12493 ctr_reg_mc = INVALIDr; 12494 } else { /* (stat == bcmCosqStatOutPackets) */ 12495 ctr_reg_uc = SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT_UC; 12496 ctr_reg_mc = SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT; 12497 ctrl_info.instance_type = SOC_CTR_INSTANCE_TYPE_PORT; 12498 } 12499 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) { 12500 if (ctr_reg_uc != INVALIDr) { 12501 BCM_IF_ERROR_RETURN 12502 (_bcm_th_cosq_index_resolve 12503 (unit, port, cosq, style, &local_port, &startq, NULL)); 12504 12505 ctrl_info.instance = local_port; 12506 BCM_IF_ERROR_RETURN 12507 (soc_counter_generic_set(unit, ctr_reg_uc, ctrl_info, 0, 12508 startq, value)); 12509 } 12510 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 12511 if (ctr_reg_mc != INVALIDr) { 12512 BCM_IF_ERROR_RETURN 12513 (_bcm_th_cosq_index_resolve 12514 (unit, port, cosq, style, &local_port, &startq, NULL)); 12515 12516 ctrl_info.instance = local_port; 12517 BCM_IF_ERROR_RETURN 12518 (soc_counter_generic_set(unit, ctr_reg_mc, ctrl_info, 0, 12519 startq, value)); 12520 } 12521 } else { 12522 if (BCM_GPORT_IS_SCHEDULER(port)) { 12523 BCM_IF_ERROR_RETURN 12524 (_bcm_th_cosq_index_resolve 12525 (unit, port, cosq, style, &local_port, &startq, NULL)); 12526 from_cos = to_cos = startq; 12527 } else { 12528 BCM_IF_ERROR_RETURN 12529 (_bcm_th_cosq_localport_resolve(unit, port, 12530 &local_port)); 12531 12532 if (cosq == BCM_COS_INVALID) { 12533 /* if (cosq == -1) set value for the first cosq */ 12534 cosq = 0; 12535 } 12536 from_cos = to_cos = cosq; 12537 } 12538 ctrl_info.instance = local_port; 12539 for (ci = from_cos; ci <= to_cos; ci++) { 12540 12541 if (!IS_CPU_PORT(unit, local_port)) { 12542 if (ctr_reg_uc != INVALIDr) { 12543 /* Get UC values if NOT CPU port */ 12544 BCM_IF_ERROR_RETURN 12545 (soc_counter_generic_set(unit, ctr_reg_uc, 12546 ctrl_info, 0, 12547 ci, value)); 12548 } 12549 } 12550 12551 if (ctr_reg_mc != INVALIDr) { 12552 BCM_IF_ERROR_RETURN 12553 (soc_counter_generic_set(unit, ctr_reg_mc, 12554 ctrl_info, 0, ci, value)); 12555 } 12556 } 12557 } 12558 break; 12559 case bcmCosqStatYellowCongestionDroppedPackets: 12560 case bcmCosqStatRedCongestionDroppedPackets: 12561 case bcmCosqStatGreenDiscardDroppedPackets: 12562 case bcmCosqStatYellowDiscardDroppedPackets: 12563 case bcmCosqStatRedDiscardDroppedPackets: 12564 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 12565 BCM_GPORT_IS_SCHEDULER(port) || 12566 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 12567 return BCM_E_PARAM; 12568 } 12569 if (cosq != BCM_COS_INVALID) { 12570 return BCM_E_UNAVAIL; 12571 } 12572 if (stat == bcmCosqStatYellowCongestionDroppedPackets) { 12573 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_PKT_YELLOW; 12574 } else if (stat == bcmCosqStatRedCongestionDroppedPackets) { 12575 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_PKT_RED; 12576 } else if (stat == bcmCosqStatYellowDiscardDroppedPackets) { 12577 ctr_reg = SOC_COUNTER_NON_DMA_PORT_WRED_PKT_YELLOW; 12578 } else if (stat == bcmCosqStatRedDiscardDroppedPackets) { 12579 ctr_reg = SOC_COUNTER_NON_DMA_PORT_WRED_PKT_RED; 12580 } else { 12581 ctr_reg = SOC_COUNTER_NON_DMA_PORT_WRED_PKT_GREEN; 12582 } 12583 BCM_IF_ERROR_RETURN 12584 (_bcm_th_cosq_localport_resolve(unit, port, &local_port)); 12585 12586 ctrl_info.instance = local_port; 12587 BCM_IF_ERROR_RETURN 12588 (soc_counter_generic_set(unit, ctr_reg, ctrl_info, 0, 12589 startq, value)); 12590 break; 12591 case bcmCosqStatHighPriDroppedPackets: 12592 case bcmCosqStatOBMLossyHighPriDroppedPackets: 12593 case bcmCosqStatLowPriDroppedPackets: 12594 case bcmCosqStatOBMLossyLowPriDroppedPackets: 12595 case bcmCosqStatHighPriDroppedBytes: 12596 case bcmCosqStatOBMLossyHighPriDroppedBytes: 12597 case bcmCosqStatLowPriDroppedBytes: 12598 case bcmCosqStatOBMLossyLowPriDroppedBytes: 12599 case bcmCosqStatOBMLossless0DroppedPackets: 12600 case bcmCosqStatOBMLossless1DroppedPackets: 12601 case bcmCosqStatOBMLossless0DroppedBytes: 12602 case bcmCosqStatOBMLossless1DroppedBytes: 12603 case bcmCosqStatOBMFlowControlEvents: 12604 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 12605 BCM_GPORT_IS_SCHEDULER(port) || 12606 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 12607 return BCM_E_PARAM; 12608 } 12609 if ((stat == bcmCosqStatHighPriDroppedPackets) || 12610 (stat == bcmCosqStatOBMLossyHighPriDroppedPackets)) { 12611 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM_LOSSY_HI; 12612 } else if ((stat == bcmCosqStatLowPriDroppedPackets) || 12613 (stat == bcmCosqStatOBMLossyLowPriDroppedPackets)) { 12614 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM_LOSSY_LO; 12615 } else if ((stat == bcmCosqStatHighPriDroppedBytes) || 12616 (stat == bcmCosqStatOBMLossyHighPriDroppedBytes)) { 12617 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM_LOSSY_HI; 12618 } else if ((stat == bcmCosqStatLowPriDroppedBytes) || 12619 (stat == bcmCosqStatOBMLossyLowPriDroppedBytes)) { 12620 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM_LOSSY_LO; 12621 } else if (stat == bcmCosqStatOBMLossless0DroppedPackets) { 12622 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM_LOSSLESS0; 12623 } else if (stat == bcmCosqStatOBMLossless1DroppedPackets) { 12624 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM_LOSSLESS1; 12625 } else if (stat == bcmCosqStatOBMLossless0DroppedBytes) { 12626 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM_LOSSLESS0; 12627 } else if (stat == bcmCosqStatOBMLossless1DroppedBytes) { 12628 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM_LOSSLESS1; 12629 } else { /* (stat == bcmCosqStatOBMFlowControlEvents) */ 12630 ctr_reg = SOC_COUNTER_NON_DMA_PORT_OBM_FC_EVENTS; 12631 } 12632 ctrl_info.instance_type = SOC_CTR_INSTANCE_TYPE_PORT; 12633 ctrl_info.instance = local_port; 12634 BCM_IF_ERROR_RETURN 12635 (soc_counter_generic_set(unit, ctr_reg, ctrl_info, 0, 12636 0, value)); 12637 break; 12638 case bcmCosqStatOBMHighWatermark: 12639 case bcmCosqStatOBMBufferBytes: 12640 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 12641 BCM_GPORT_IS_SCHEDULER(port) || 12642 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 12643 return BCM_E_PARAM; 12644 } 12645 if (stat == bcmCosqStatOBMHighWatermark) { 12646 BCM_IF_ERROR_RETURN 12647 (_bcm_th_cosq_obmhighwatermark_set(unit, local_port, value)); 12648 } else { 12649 BCM_IF_ERROR_RETURN 12650 (_bcm_th_cosq_obm_buf_use_cnt_set(unit, local_port, value)); 12651 } 12652 break; 12653 default: 12654 return BCM_E_PARAM; 12655 } 12656 12657 return BCM_E_NONE; 12658 } 12659 12660 int 12661 bcm_th_cosq_stat_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 12662 bcm_cosq_stat_t stat, int sync_mode, uint64 *value) 12663 { 12664 soc_ctr_control_info_t ctrl_info; 12665 soc_reg_t ctr_reg, ctr_reg_uc, ctr_reg_mc; 12666 _bcm_th_cosq_index_style_t style = _BCM_TH_COSQ_INDEX_STYLE_COUNT; 12667 uint64 sum, value64; 12668 int startq = 0, ci, from_cos, to_cos, i, start_hw_index, end_hw_index; 12669 bcm_port_t local_port = -1; 12670 int sync = sync_mode ? SOC_COUNTER_SYNC_ENABLE : 0; 12671 soc_info_t *si = &SOC_INFO(unit); 12672 soc_mem_t mem = INVALIDm; 12673 soc_mem_t base_mem; 12674 uint32 entry[SOC_MAX_MEM_WORDS]; 12675 uint32 sum32; 12676 int pipe, xpe, factor = 1; 12677 int pool, mem_idx; 12678 uint32 value32, rval, valid; 12679 soc_field_t field = INVALIDf; 12680 soc_reg_t reg = INVALIDr; 12681 soc_reg_t base_reg = INVALIDr; 12682 12683 BCM_IF_ERROR_RETURN 12684 (_bcm_th_cosq_localport_resolve(unit, port, &local_port)); 12685 ctrl_info.instance = -1; 12686 ctrl_info.instance_type = SOC_CTR_INSTANCE_TYPE_XPE; 12687 12688 switch (stat) { 12689 case bcmCosqStatDroppedPackets: 12690 case bcmCosqStatDroppedBytes: 12691 case bcmCosqStatOutPackets: 12692 case bcmCosqStatOutBytes: 12693 case bcmCosqStatUCOutPackets: 12694 case bcmCosqStatUCOutBytes: 12695 case bcmCosqStatMCOutPackets: 12696 case bcmCosqStatMCOutBytes: 12697 case bcmCosqStatEgressMCQueueBytesPeak: 12698 case bcmCosqStatEgressUCQueueBytesPeak: 12699 case bcmCosqStatDiscardUCDroppedPackets: 12700 if ((cosq < -1) || (cosq >= _TH_PORT_NUM_COS(unit, local_port))) { 12701 return BCM_E_PARAM; 12702 } 12703 style = _BCM_TH_COSQ_INDEX_STYLE_COS; 12704 if (stat == bcmCosqStatEgressMCQueueBytesPeak) { 12705 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 12706 BCM_GPORT_IS_SCHEDULER(port)) { 12707 return BCM_E_PARAM; 12708 } 12709 ctr_reg_uc = INVALIDr; 12710 ctr_reg_mc = SOC_COUNTER_NON_DMA_QUEUE_PEAK; 12711 factor = _TH_MMU_BYTES_PER_CELL; 12712 } else if (stat == bcmCosqStatEgressUCQueueBytesPeak) { 12713 if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) || 12714 BCM_GPORT_IS_SCHEDULER(port)) { 12715 return BCM_E_PARAM; 12716 } 12717 if (!BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) { 12718 BCM_IF_ERROR_RETURN 12719 (_bcm_th_cosq_localport_resolve(unit, port, 12720 &local_port)); 12721 if (IS_CPU_PORT(unit, local_port)) { 12722 return BCM_E_PARAM; 12723 } 12724 } 12725 ctr_reg_uc = SOC_COUNTER_NON_DMA_UC_QUEUE_PEAK; 12726 ctr_reg_mc = INVALIDr; 12727 factor = _TH_MMU_BYTES_PER_CELL; 12728 } else if (stat == bcmCosqStatDroppedBytes) { 12729 ctr_reg_uc = SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE_UC; 12730 ctr_reg_mc = SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE; 12731 } else if (stat == bcmCosqStatDroppedPackets) { 12732 ctr_reg_uc = SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_UC; 12733 ctr_reg_mc = SOC_COUNTER_NON_DMA_COSQ_DROP_PKT; 12734 } else if (stat == bcmCosqStatUCOutBytes) { 12735 if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 12736 return BCM_E_PARAM; 12737 } 12738 ctr_reg_uc = SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE_UC; 12739 ctr_reg_mc = INVALIDr; 12740 ctrl_info.instance_type = SOC_CTR_INSTANCE_TYPE_PORT; 12741 } else if (stat == bcmCosqStatUCOutPackets) { 12742 if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 12743 return BCM_E_PARAM; 12744 } 12745 ctr_reg_uc = SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT_UC; 12746 ctr_reg_mc = INVALIDr; 12747 ctrl_info.instance_type = SOC_CTR_INSTANCE_TYPE_PORT; 12748 } else if (stat == bcmCosqStatMCOutBytes) { 12749 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) { 12750 return BCM_E_PARAM; 12751 } 12752 ctr_reg_uc = INVALIDr; 12753 ctr_reg_mc = SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE; 12754 ctrl_info.instance_type = SOC_CTR_INSTANCE_TYPE_PORT; 12755 } else if (stat == bcmCosqStatMCOutPackets) { 12756 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) { 12757 return BCM_E_PARAM; 12758 } 12759 ctr_reg_uc = INVALIDr; 12760 ctr_reg_mc = SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT; 12761 ctrl_info.instance_type = SOC_CTR_INSTANCE_TYPE_PORT; 12762 } else if (stat == bcmCosqStatOutBytes) { 12763 ctr_reg_uc = SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE_UC; 12764 ctr_reg_mc = SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE; 12765 ctrl_info.instance_type = SOC_CTR_INSTANCE_TYPE_PORT; 12766 } else if (stat == bcmCosqStatDiscardUCDroppedPackets) { 12767 if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) || 12768 BCM_GPORT_IS_SCHEDULER(port)) { 12769 return BCM_E_PARAM; 12770 } 12771 ctr_reg_uc = SOC_COUNTER_NON_DMA_COSQ_DROP_WRED_PKT; 12772 ctr_reg_mc = INVALIDr; 12773 } else { /* (stat == bcmCosqStatOutPackets) */ 12774 ctr_reg_uc = SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT_UC; 12775 ctr_reg_mc = SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT; 12776 ctrl_info.instance_type = SOC_CTR_INSTANCE_TYPE_PORT; 12777 } 12778 12779 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) { 12780 if (ctr_reg_uc != INVALIDr) { 12781 BCM_IF_ERROR_RETURN 12782 (_bcm_th_cosq_index_resolve 12783 (unit, port, cosq, style, &local_port, &startq, NULL)); 12784 12785 ctrl_info.instance = local_port; 12786 BCM_IF_ERROR_RETURN 12787 (soc_counter_generic_get(unit, ctr_reg_uc, ctrl_info, 12788 sync, startq, value)); 12789 } 12790 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 12791 if (ctr_reg_mc != INVALIDr) { 12792 BCM_IF_ERROR_RETURN 12793 (_bcm_th_cosq_index_resolve 12794 (unit, port, cosq, style, &local_port, &startq, NULL)); 12795 ctrl_info.instance = local_port; 12796 BCM_IF_ERROR_RETURN 12797 (soc_counter_generic_get(unit, ctr_reg_mc, ctrl_info, 12798 sync, startq, value)); 12799 } 12800 } else { 12801 COMPILER_64_ZERO(sum); 12802 if (BCM_GPORT_IS_SCHEDULER(port)) { 12803 BCM_IF_ERROR_RETURN 12804 (_bcm_th_cosq_index_resolve 12805 (unit, port, cosq, style, &local_port, &startq, NULL)); 12806 from_cos = to_cos = startq; 12807 } else { 12808 BCM_IF_ERROR_RETURN 12809 (_bcm_th_cosq_localport_resolve(unit, port, 12810 &local_port)); 12811 12812 if (cosq == BCM_COS_INVALID) { 12813 from_cos = 0; 12814 to_cos = (IS_CPU_PORT(unit, local_port)) ? 12815 NUM_CPU_COSQ(unit) - 1 : _TH_NUM_COS(unit) 12816 - 1; 12817 } else { 12818 from_cos = to_cos = cosq; 12819 } 12820 } 12821 ctrl_info.instance = local_port; 12822 for (ci = from_cos; ci <= to_cos; ci++) { 12823 12824 if (!IS_CPU_PORT(unit, local_port)) { 12825 /* Get UC values if NOT CPU port */ 12826 if (ctr_reg_uc != INVALIDr) { 12827 BCM_IF_ERROR_RETURN 12828 (soc_counter_generic_get(unit, ctr_reg_uc, 12829 ctrl_info, 12830 sync, ci, &value64)); 12831 COMPILER_64_ADD_64(sum, value64); 12832 } 12833 } 12834 12835 if (ctr_reg_mc != INVALIDr) { 12836 BCM_IF_ERROR_RETURN 12837 (soc_counter_generic_get(unit, ctr_reg_mc, 12838 ctrl_info, 12839 sync, ci, &value64)); 12840 COMPILER_64_ADD_64(sum, value64); 12841 } 12842 } 12843 COMPILER_64_COPY(*value, sum); 12844 COMPILER_64_UMUL_32(*value, factor); 12845 } 12846 break; 12847 case bcmCosqStatYellowCongestionDroppedPackets: 12848 case bcmCosqStatRedCongestionDroppedPackets: 12849 case bcmCosqStatGreenDiscardDroppedPackets: 12850 case bcmCosqStatYellowDiscardDroppedPackets: 12851 case bcmCosqStatRedDiscardDroppedPackets: 12852 if ((cosq < -1) || (cosq >= _TH_PORT_NUM_COS(unit, local_port))) { 12853 return BCM_E_PARAM; 12854 } 12855 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 12856 BCM_GPORT_IS_SCHEDULER(port) || 12857 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 12858 return BCM_E_PARAM; 12859 } 12860 if (cosq != BCM_COS_INVALID) { 12861 return BCM_E_UNAVAIL; 12862 } 12863 if (stat == bcmCosqStatYellowCongestionDroppedPackets) { 12864 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_PKT_YELLOW; 12865 } else if (stat == bcmCosqStatRedCongestionDroppedPackets) { 12866 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_PKT_RED; 12867 } else if (stat == bcmCosqStatYellowDiscardDroppedPackets) { 12868 ctr_reg = SOC_COUNTER_NON_DMA_PORT_WRED_PKT_YELLOW; 12869 } else if (stat == bcmCosqStatRedDiscardDroppedPackets) { 12870 ctr_reg = SOC_COUNTER_NON_DMA_PORT_WRED_PKT_RED; 12871 } else { /* (stat == bcmCosqStatGreenDiscardDroppedPackets) */ 12872 ctr_reg = SOC_COUNTER_NON_DMA_PORT_WRED_PKT_GREEN; 12873 } 12874 BCM_IF_ERROR_RETURN 12875 (_bcm_th_cosq_localport_resolve(unit, port, &local_port)); 12876 12877 ctrl_info.instance = local_port; 12878 BCM_IF_ERROR_RETURN 12879 (soc_counter_generic_get(unit, ctr_reg, ctrl_info, 12880 sync, startq, value)); 12881 break; 12882 case bcmCosqStatIngressPortPGMinBytesPeak: 12883 case bcmCosqStatIngressPortPGMinBytesCurrent: 12884 case bcmCosqStatIngressPortPGSharedBytesPeak: 12885 case bcmCosqStatIngressPortPGSharedBytesCurrent: 12886 case bcmCosqStatIngressPortPGHeadroomBytesPeak: 12887 case bcmCosqStatIngressPortPGHeadroomBytesCurrent: 12888 if ( cosq < -1 ) { 12889 return BCM_E_PARAM; 12890 } 12891 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 12892 BCM_GPORT_IS_SCHEDULER(port) || 12893 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 12894 return BCM_E_PARAM; 12895 } 12896 COMPILER_64_ZERO(sum); 12897 if (stat == bcmCosqStatIngressPortPGMinBytesPeak) { 12898 ctr_reg = SOC_COUNTER_NON_DMA_PG_MIN_PEAK; 12899 } else if (stat == bcmCosqStatIngressPortPGMinBytesCurrent) { 12900 ctr_reg = SOC_COUNTER_NON_DMA_PG_MIN_CURRENT; 12901 } else if (stat == bcmCosqStatIngressPortPGSharedBytesPeak) { 12902 ctr_reg = SOC_COUNTER_NON_DMA_PG_SHARED_PEAK; 12903 } else if (stat == bcmCosqStatIngressPortPGSharedBytesCurrent) { 12904 ctr_reg = SOC_COUNTER_NON_DMA_PG_SHARED_CURRENT; 12905 } else if (stat == bcmCosqStatIngressPortPGHeadroomBytesPeak) { 12906 ctr_reg = SOC_COUNTER_NON_DMA_PG_HDRM_PEAK; 12907 } else { 12908 /* (stat == bcmCosqStatIngressPortPGHeadroomBytesCurrent) */ 12909 ctr_reg = SOC_COUNTER_NON_DMA_PG_HDRM_CURRENT; 12910 } 12911 BCM_IF_ERROR_RETURN 12912 (_bcm_th_cosq_localport_resolve(unit, port, &local_port)); 12913 BCM_IF_ERROR_RETURN 12914 (_bcm_th_cosq_ingress_pg_get(unit, port, cosq, 12915 &start_hw_index, &end_hw_index)); 12916 12917 for (i = start_hw_index; i <= end_hw_index; i++) { 12918 ctrl_info.instance = local_port; 12919 BCM_IF_ERROR_RETURN 12920 (soc_counter_generic_get(unit, ctr_reg, ctrl_info, 12921 sync, i, &value64)); 12922 COMPILER_64_ADD_64(sum, value64); 12923 } 12924 12925 COMPILER_64_UMUL_32(sum, _TH_MMU_BYTES_PER_CELL); 12926 *value = sum; 12927 break; 12928 case bcmCosqStatIngressPortPoolSharedBytesPeak: 12929 if ( cosq < -1 ) { 12930 return BCM_E_PARAM; 12931 } 12932 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 12933 BCM_GPORT_IS_SCHEDULER(port) || 12934 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 12935 return BCM_E_PARAM; 12936 } 12937 COMPILER_64_ZERO(sum); 12938 BCM_IF_ERROR_RETURN 12939 (_bcm_th_cosq_ingress_sp_get_by_pg(unit, port, cosq, 12940 &start_hw_index, &end_hw_index)); 12941 12942 BCM_IF_ERROR_RETURN( 12943 _bcm_th_cosq_localport_resolve(unit, port, &local_port)); 12944 12945 ctrl_info.instance_type = SOC_CTR_INSTANCE_TYPE_XPE; 12946 ctrl_info.instance = local_port; 12947 ctr_reg = SOC_COUNTER_NON_DMA_POOL_PEAK; 12948 12949 for (i = start_hw_index; i <= end_hw_index; i++) { 12950 BCM_IF_ERROR_RETURN 12951 (soc_counter_generic_get(unit, ctr_reg, ctrl_info, 12952 sync, i, &value64)); 12953 COMPILER_64_ADD_64(sum, value64); 12954 } 12955 12956 COMPILER_64_UMUL_32(sum, _TH_MMU_BYTES_PER_CELL); 12957 *value = sum; 12958 break; 12959 case bcmCosqStatIngressPortPoolSharedBytesCurrent: 12960 if ( cosq < -1 ) { 12961 return BCM_E_PARAM; 12962 } 12963 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 12964 BCM_GPORT_IS_SCHEDULER(port) || 12965 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 12966 return BCM_E_PARAM; 12967 } 12968 BCM_IF_ERROR_RETURN 12969 (_bcm_th_cosq_ingress_sp_get_by_pg(unit, port, cosq, 12970 &start_hw_index, &end_hw_index)); 12971 BCM_IF_ERROR_RETURN( 12972 _bcm_th_cosq_localport_resolve(unit, port, &local_port)); 12973 12974 ctrl_info.instance_type = SOC_CTR_INSTANCE_TYPE_XPE; 12975 ctrl_info.instance = local_port; 12976 ctr_reg = SOC_COUNTER_NON_DMA_POOL_CURRENT; 12977 12978 COMPILER_64_ZERO(sum); 12979 for (i = start_hw_index; i <= end_hw_index; i++) { 12980 BCM_IF_ERROR_RETURN 12981 (soc_counter_generic_get(unit, ctr_reg, ctrl_info, 12982 sync, i, &value64)); 12983 COMPILER_64_ADD_64(sum, value64); 12984 } 12985 12986 COMPILER_64_UMUL_32(sum, _TH_MMU_BYTES_PER_CELL); 12987 *value = sum; 12988 break; 12989 case bcmCosqStatHighPriDroppedPackets: 12990 case bcmCosqStatOBMLossyHighPriDroppedPackets: 12991 case bcmCosqStatLowPriDroppedPackets: 12992 case bcmCosqStatOBMLossyLowPriDroppedPackets: 12993 case bcmCosqStatHighPriDroppedBytes: 12994 case bcmCosqStatOBMLossyHighPriDroppedBytes: 12995 case bcmCosqStatLowPriDroppedBytes: 12996 case bcmCosqStatOBMLossyLowPriDroppedBytes: 12997 case bcmCosqStatOBMLossless0DroppedPackets: 12998 case bcmCosqStatOBMLossless1DroppedPackets: 12999 case bcmCosqStatOBMLossless0DroppedBytes: 13000 case bcmCosqStatOBMLossless1DroppedBytes: 13001 case bcmCosqStatOBMFlowControlEvents: 13002 if ((cosq < -1) || (cosq >= _TH_PORT_NUM_COS(unit, local_port))) { 13003 return BCM_E_PARAM; 13004 } 13005 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 13006 BCM_GPORT_IS_SCHEDULER(port) || 13007 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 13008 return BCM_E_PARAM; 13009 } 13010 if ((stat == bcmCosqStatHighPriDroppedPackets) || 13011 (stat == bcmCosqStatOBMLossyHighPriDroppedPackets)) { 13012 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM_LOSSY_HI; 13013 } else if ((stat == bcmCosqStatLowPriDroppedPackets) || 13014 (stat == bcmCosqStatOBMLossyLowPriDroppedPackets)) { 13015 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM_LOSSY_LO; 13016 } else if ((stat == bcmCosqStatHighPriDroppedBytes) || 13017 (stat == bcmCosqStatOBMLossyHighPriDroppedBytes)) { 13018 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM_LOSSY_HI; 13019 } else if ((stat == bcmCosqStatLowPriDroppedBytes) || 13020 (stat == bcmCosqStatOBMLossyLowPriDroppedBytes)) { 13021 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM_LOSSY_LO; 13022 } else if (stat == bcmCosqStatOBMLossless0DroppedPackets) { 13023 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM_LOSSLESS0; 13024 } else if (stat == bcmCosqStatOBMLossless1DroppedPackets) { 13025 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM_LOSSLESS1; 13026 } else if (stat == bcmCosqStatOBMLossless0DroppedBytes) { 13027 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM_LOSSLESS0; 13028 } else if (stat == bcmCosqStatOBMLossless1DroppedBytes) { 13029 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM_LOSSLESS1; 13030 } else { /* (stat == bcmCosqStatOBMFlowControlEvents) */ 13031 ctr_reg = SOC_COUNTER_NON_DMA_PORT_OBM_FC_EVENTS; 13032 } 13033 ctrl_info.instance_type = SOC_CTR_INSTANCE_TYPE_PORT; 13034 ctrl_info.instance = local_port; 13035 BCM_IF_ERROR_RETURN 13036 (soc_counter_generic_get(unit, ctr_reg, ctrl_info, 0, 13037 0, value)); 13038 break; 13039 case bcmCosqStatOBMHighWatermark: 13040 case bcmCosqStatOBMBufferBytes: 13041 if ((cosq < -1) || (cosq >= _TH_PORT_NUM_COS(unit, local_port))) { 13042 return BCM_E_PARAM; 13043 } 13044 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 13045 BCM_GPORT_IS_SCHEDULER(port) || 13046 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 13047 return BCM_E_PARAM; 13048 } 13049 if (stat == bcmCosqStatOBMHighWatermark) { 13050 BCM_IF_ERROR_RETURN 13051 (_bcm_th_cosq_obmhighwatermark_get(unit, local_port, value)); 13052 } else { 13053 BCM_IF_ERROR_RETURN 13054 (_bcm_th_cosq_obm_buf_use_cnt_get(unit, local_port, value)); 13055 } 13056 break; 13057 case bcmCosqStatEgressUCQueueMinBytesCurrent: 13058 case bcmCosqStatEgressUCQueueBytesCurrent: 13059 if (local_port < 0 || local_port >= SOC_MAX_NUM_PORTS) { 13060 return BCM_E_PORT; 13061 } 13062 if (stat == bcmCosqStatEgressUCQueueMinBytesCurrent) { 13063 field = MIN_COUNTf; 13064 } else if (stat == bcmCosqStatEgressUCQueueBytesCurrent) { 13065 field = SHARED_COUNTf; 13066 } 13067 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) { 13068 BCM_IF_ERROR_RETURN 13069 (_bcm_th_cosq_index_resolve(unit, port, cosq, 13070 _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE, 13071 NULL, &start_hw_index, NULL)); 13072 pipe = si->port_pipe[local_port]; 13073 COMPILER_64_ZERO(sum); 13074 sum32 = 0; 13075 for (xpe = 0; xpe < NUM_XPE(unit); xpe++) { 13076 base_mem = MMU_THDU_COUNTER_QUEUEm; 13077 /* Get XPE/PIPE view from base mem */ 13078 mem = SOC_MEM_UNIQUE_ACC_XPE_PIPE(unit, base_mem, xpe, pipe); 13079 if (mem == INVALIDm) { 13080 continue; 13081 } 13082 SOC_IF_ERROR_RETURN 13083 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, start_hw_index, &entry)); 13084 sum32 += soc_mem_field32_get(unit, mem, entry, field); 13085 } 13086 COMPILER_64_ADD_32(sum, sum32); 13087 COMPILER_64_UMUL_32(sum, _TH_MMU_BYTES_PER_CELL); 13088 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 13089 return BCM_E_PARAM; 13090 } else { 13091 if (IS_CPU_PORT(unit, local_port)) { 13092 return BCM_E_PARAM; 13093 } 13094 13095 pipe = si->port_pipe[local_port]; 13096 COMPILER_64_ZERO(sum); 13097 sum32 =0; 13098 13099 if (cosq == BCM_COS_INVALID) { 13100 from_cos = 0; 13101 to_cos = NUM_COS(unit) - 1; 13102 } else { 13103 from_cos = to_cos = cosq; 13104 } 13105 13106 for (xpe = 0; xpe < NUM_XPE(unit); xpe++) { 13107 base_mem = MMU_THDU_COUNTER_QUEUEm; 13108 /* Get XPE/PIPE view from base mem */ 13109 mem = SOC_MEM_UNIQUE_ACC_XPE_PIPE(unit, base_mem, xpe, pipe); 13110 if (mem == INVALIDm) { 13111 continue; 13112 } 13113 for (ci = from_cos; ci <= to_cos; ci++) { 13114 BCM_IF_ERROR_RETURN 13115 (_bcm_th_cosq_index_resolve(unit, local_port, ci, 13116 _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE, 13117 NULL, &start_hw_index, NULL)); 13118 SOC_IF_ERROR_RETURN 13119 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, start_hw_index, &entry)); 13120 sum32 += soc_mem_field32_get(unit, mem, entry, field); 13121 } 13122 } 13123 COMPILER_64_ADD_32(sum, sum32); 13124 COMPILER_64_UMUL_32(sum, _TH_MMU_BYTES_PER_CELL); 13125 } 13126 *value = sum; 13127 break; 13128 13129 case bcmCosqStatEgressUCQueuePortBytesCurrent: 13130 BCM_IF_ERROR_RETURN 13131 (_bcm_th_cosq_index_resolve(unit, port, cosq, 13132 _BCM_TH_COSQ_INDEX_STYLE_EGR_POOL, 13133 &local_port, &pool, NULL)); 13134 value32 = 0; 13135 base_mem = MMU_THDU_COUNTER_PORTm; 13136 BCM_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 13137 for (xpe = 0; xpe < NUM_XPE(unit); xpe++) { 13138 if (!(si->epipe_xpe_map[pipe] & (1 << xpe))) { 13139 continue; 13140 } 13141 mem = SOC_MEM_UNIQUE_ACC_XPE_PIPE(unit, base_mem, xpe, pipe); 13142 if (mem == INVALIDm) { 13143 continue; 13144 } 13145 mem_idx = SOC_TH_MMU_PIPED_MEM_INDEX(unit, 13146 local_port, base_mem, pool); 13147 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, 13148 mem_idx, entry)); 13149 value32 += soc_mem_field32_get(unit, mem, entry, SHARED_COUNTf); 13150 } 13151 13152 COMPILER_64_ADD_32(*value, value32); 13153 COMPILER_64_UMUL_32(*value, _TH_MMU_BYTES_PER_CELL); 13154 break; 13155 13156 case bcmCosqStatEgressPortPoolTotalBytesCurrent: 13157 if (cosq != BCM_COS_INVALID) { 13158 return BCM_E_UNAVAIL; 13159 } 13160 if (!SOC_REG_IS_VALID(unit, MMU_THDM_DB_PORT_TOTAL_COUNTr)) { 13161 return BCM_E_UNAVAIL; 13162 } 13163 BCM_IF_ERROR_RETURN 13164 (_bcm_th_cosq_localport_resolve(unit, port, &local_port)); 13165 value32 = 0; 13166 base_reg = MMU_THDM_DB_PORT_TOTAL_COUNTr; 13167 BCM_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 13168 for (xpe = 0; xpe < NUM_XPE(unit); xpe++) { 13169 if (!(si->epipe_xpe_map[pipe] & (1 << xpe))) { 13170 continue; 13171 } 13172 reg = SOC_REG_UNIQUE_ACC(unit, base_reg)[xpe]; 13173 if (reg == INVALIDr) { 13174 continue; 13175 } 13176 BCM_IF_ERROR_RETURN 13177 (soc_reg32_get(unit, reg, local_port, 0, &rval)); 13178 value32 += soc_reg_field_get(unit, reg, rval, COUNTf); 13179 } 13180 13181 COMPILER_64_ADD_32(*value, value32); 13182 COMPILER_64_UMUL_32(*value, _TH_MMU_BYTES_PER_CELL); 13183 break; 13184 13185 case bcmCosqStatEgressPortPoolSharedBytesCurrent: 13186 if (!SOC_REG_IS_VALID(unit, MMU_THDM_DB_PORTSP_SHARED_COUNTr)) { 13187 return BCM_E_UNAVAIL; 13188 } 13189 BCM_IF_ERROR_RETURN 13190 (_bcm_th_cosq_index_resolve(unit, port, cosq, 13191 _BCM_TH_COSQ_INDEX_STYLE_EGR_POOL, 13192 &local_port, &pool, NULL)); 13193 value32 = 0; 13194 base_reg = MMU_THDM_DB_PORTSP_SHARED_COUNTr; 13195 BCM_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 13196 for (xpe = 0; xpe < NUM_XPE(unit); xpe++) { 13197 if (!(si->epipe_xpe_map[pipe] & (1 << xpe))) { 13198 continue; 13199 } 13200 reg = SOC_REG_UNIQUE_ACC(unit, base_reg)[xpe]; 13201 if (reg == INVALIDr) { 13202 continue; 13203 } 13204 BCM_IF_ERROR_RETURN 13205 (soc_reg32_get(unit, reg, local_port, pool, &rval)); 13206 value32 += soc_reg_field_get(unit, reg, rval, COUNTf); 13207 } 13208 13209 COMPILER_64_ADD_32(*value, value32); 13210 COMPILER_64_UMUL_32(*value, _TH_MMU_BYTES_PER_CELL); 13211 break; 13212 13213 case bcmCosqStatEgressMCQueueMinBytesCurrent: 13214 case bcmCosqStatEgressMCQueueBytesCurrent: 13215 if (stat == bcmCosqStatEgressMCQueueMinBytesCurrent) { 13216 field = MIN_COUNTf; 13217 } else if (stat == bcmCosqStatEgressMCQueueBytesCurrent) { 13218 field = SHARED_COUNTf; 13219 } 13220 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) { 13221 return BCM_E_PARAM; 13222 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 13223 BCM_IF_ERROR_RETURN 13224 (_bcm_th_cosq_index_resolve(unit, port, cosq, 13225 _BCM_TH_COSQ_INDEX_STYLE_MCAST_QUEUE, 13226 &local_port, &startq, NULL)); 13227 value32 = 0; 13228 base_mem = MMU_THDM_DB_QUEUE_COUNTm; 13229 BCM_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 13230 for (xpe = 0; xpe < NUM_XPE(unit); xpe++) { 13231 if (!(si->epipe_xpe_map[pipe] & (1 << xpe))) { 13232 continue; 13233 } 13234 mem = SOC_MEM_UNIQUE_ACC_XPE_PIPE(unit, base_mem, xpe, pipe); 13235 if (mem == INVALIDm) { 13236 continue; 13237 } 13238 mem_idx = SOC_TH_MMU_PIPED_MEM_INDEX(unit, 13239 local_port, base_mem, pool); 13240 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, 13241 mem_idx, entry)); 13242 value32 += soc_mem_field32_get(unit, mem, entry, field); 13243 } 13244 13245 COMPILER_64_ADD_32(*value, value32); 13246 COMPILER_64_UMUL_32(*value, _TH_MMU_BYTES_PER_CELL); 13247 } else { 13248 BCM_IF_ERROR_RETURN(_bcm_th_cosq_localport_resolve(unit, port, 13249 &local_port)); 13250 COMPILER_64_ZERO(sum); 13251 sum32 =0; 13252 if (cosq == BCM_COS_INVALID) { 13253 from_cos = 0; 13254 to_cos = (IS_CPU_PORT(unit, local_port)) ? 13255 NUM_CPU_COSQ(unit) - 1 : _TH_NUM_COS(unit) - 1; 13256 } else { 13257 from_cos = to_cos = cosq; 13258 } 13259 13260 if (local_port < 0) { 13261 return BCM_E_PORT; 13262 } 13263 13264 sum32 = 0; 13265 base_mem = MMU_THDM_DB_QUEUE_COUNTm; 13266 BCM_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 13267 for (xpe = 0; xpe < NUM_XPE(unit); xpe++) { 13268 if (!(si->epipe_xpe_map[pipe] & (1 << xpe))) { 13269 continue; 13270 } 13271 mem = SOC_MEM_UNIQUE_ACC_XPE_PIPE(unit, base_mem, xpe, pipe); 13272 if (mem == INVALIDm) { 13273 continue; 13274 } 13275 for (ci = from_cos; ci <= to_cos; ci++) { 13276 BCM_IF_ERROR_RETURN 13277 (_bcm_th_cosq_index_resolve 13278 (unit, local_port, ci, _BCM_TH_COSQ_INDEX_STYLE_MCAST_QUEUE, 13279 NULL, &startq, NULL)); 13280 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, 13281 startq, entry)); 13282 sum32 += soc_mem_field32_get(unit, mem, entry, field); 13283 } 13284 } 13285 13286 COMPILER_64_ADD_32(sum, sum32); 13287 COMPILER_64_UMUL_32(sum, _TH_MMU_BYTES_PER_CELL); 13288 *value = sum; 13289 } 13290 break; 13291 13292 case bcmCosqStatEgressQgroupMinBytesCurrent: 13293 case bcmCosqStatEgressQgroupBytesCurrent: 13294 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) { 13295 BCM_IF_ERROR_RETURN 13296 (_bcm_th_cosq_index_resolve(unit, port, cosq, 13297 _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE, 13298 &local_port, &startq, NULL)); 13299 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 13300 return BCM_E_PARAM; 13301 } else { 13302 BCM_IF_ERROR_RETURN 13303 (_bcm_th_cosq_localport_resolve(unit, port, &local_port)); 13304 if (local_port < 0) { 13305 return BCM_E_PORT; 13306 } 13307 BCM_IF_ERROR_RETURN 13308 (_bcm_th_cosq_index_resolve(unit, local_port, cosq, 13309 _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE, 13310 NULL, &startq, NULL)); 13311 } 13312 13313 value32 = 0; 13314 BCM_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 13315 for (xpe = 0; xpe < NUM_XPE(unit); xpe++) { 13316 if (!(si->epipe_xpe_map[pipe] & (1 << xpe))) { 13317 continue; 13318 } 13319 base_mem = MMU_THDU_Q_TO_QGRP_MAPm; 13320 mem = SOC_MEM_UNIQUE_ACC_PIPE(unit, base_mem, pipe); 13321 if (mem == INVALIDm) { 13322 continue; 13323 } 13324 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 13325 valid = soc_mem_field32_get(unit, mem, entry, QGROUP_VALIDf); 13326 if (!valid) { 13327 LOG_INFO(BSL_LS_BCM_COSQ, 13328 (BSL_META_U(unit, 13329 "UCQ doesn't associate with a queue group!\n"))); 13330 return BCM_E_UNAVAIL; 13331 } 13332 base_mem = MMU_THDU_COUNTER_QGROUPm; 13333 BCM_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 13334 mem = SOC_MEM_UNIQUE_ACC_XPE_PIPE(unit, base_mem, xpe, pipe); 13335 if (stat == bcmCosqStatEgressQgroupMinBytesCurrent) { 13336 field = MIN_COUNTf; 13337 } else if (stat == bcmCosqStatEgressQgroupBytesCurrent) { 13338 field = SHARED_COUNTf; 13339 } 13340 13341 mem_idx = si->port_p2m_mapping[si->port_l2p_mapping[local_port]]; 13342 mem_idx &= (SOC_TH_MMU_PORT_STRIDE - 1); 13343 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, mem_idx, entry)); 13344 value32 += soc_mem_field32_get(unit, mem, entry, field); 13345 } 13346 13347 COMPILER_64_ADD_32(*value, value32); 13348 COMPILER_64_UMUL_32(*value, _TH_MMU_BYTES_PER_CELL); 13349 break; 13350 13351 default: 13352 return BCM_E_PARAM; 13353 } 13354 13355 return BCM_E_NONE; 13356 } 13357 13358 13359 /* 13360 * Function: 13361 * bcm_th_cosq_bst_profile_set 13362 * Purpose: 13363 * Set the BST profile of a given BST stat id. 13364 * Parameters: 13365 * unit - (IN) unit number 13366 * gport - (IN) gport of the port 13367 * cosq - (IN) COS queue 13368 * bid - (IN) BST statistics ID 13369 * profile - (IN) profile for given BST ID 13370 * Returns: 13371 * BCM_E_XXX 13372 */ 13373 int 13374 bcm_th_cosq_bst_profile_set(int unit, 13375 bcm_gport_t gport, 13376 bcm_cos_queue_t cosq, 13377 bcm_bst_stat_id_t bid, 13378 bcm_cosq_bst_profile_t *profile) 13379 { 13380 if (bid == bcmBstStatIdHeadroomPool) { 13381 /* Do not have BST profile to set */ 13382 return BCM_E_PARAM; 13383 } else { 13384 return _bcm_bst_cmn_profile_set 13385 (unit, gport, cosq, BCM_BST_DUP_XPE, bid, profile); 13386 } 13387 } 13388 13389 /* 13390 * Function: 13391 * bcm_th_cosq_bst_profile_get 13392 * Purpose: 13393 * Get the BST profile of a given BST stat id. 13394 * Parameters: 13395 * unit - (IN) unit number 13396 * gport - (IN) gport of the port 13397 * cosq - (IN) COS queue 13398 * bid - (IN) BST statistics ID 13399 * profile - (OUT) profile retrieved for given BST ID 13400 * Returns: 13401 * BCM_E_XXX 13402 */ 13403 int 13404 bcm_th_cosq_bst_profile_get(int unit, 13405 bcm_gport_t gport, 13406 bcm_cos_queue_t cosq, 13407 bcm_bst_stat_id_t bid, 13408 bcm_cosq_bst_profile_t *profile) 13409 { 13410 if (bid == bcmBstStatIdHeadroomPool) { 13411 /* Do not have BST profile to get */ 13412 return BCM_E_PARAM; 13413 } else { 13414 return _bcm_bst_cmn_profile_get 13415 (unit, gport, cosq, BCM_BST_DUP_XPE, bid, profile); 13416 } 13417 } 13418 13419 /* 13420 * Function: 13421 * bcm_th_cosq_bst_multi_profile_set 13422 * Purpose: 13423 * Set the BST profiles of a given BST stat id, per XPE. 13424 * Parameters: 13425 * unit - (IN) unit number 13426 * gport - (IN) gport of the port 13427 * cosq - (IN) COS queue 13428 * bid - (IN) BST statistics ID 13429 * size - (IN) size of the profile array 13430 * profile - (IN) profile array for given BST ID, index with XPE 13431 * Returns: 13432 * BCM_E_XXX 13433 */ 13434 int 13435 bcm_th_cosq_bst_multi_profile_set(int unit, 13436 bcm_gport_t gport, 13437 bcm_cos_queue_t cosq, 13438 bcm_bst_stat_id_t bid, 13439 int array_size, 13440 bcm_cosq_bst_profile_t *profile_array) 13441 { 13442 int cnt; 13443 bcm_cosq_bst_profile_t profile[_TH_XPES_PER_DEV]; 13444 13445 if ((!profile_array) || (array_size <=0)) { 13446 return BCM_E_PARAM; 13447 } 13448 if (bid == bcmBstStatIdHeadroomPool) { 13449 /* Do not have BST profile to set */ 13450 return BCM_E_PARAM; 13451 } 13452 if ((bid == bcmBstStatIdDevice) 13453 || (bid == bcmBstStatIdUcast) 13454 || (bid == bcmBstStatIdEgrPortPoolSharedUcast)) { 13455 return BCM_E_UNAVAIL; 13456 } 13457 13458 cnt = NUM_XPE(unit); 13459 if (array_size < cnt) { 13460 cnt = array_size; 13461 } 13462 sal_memset(profile, 0, sizeof(profile)); 13463 sal_memcpy(profile, profile_array, cnt*sizeof(bcm_cosq_bst_profile_t)); 13464 13465 return _bcm_bst_cmn_profile_set 13466 (unit, gport, cosq, BCM_BST_MLT_XPE, bid, profile); 13467 } 13468 13469 /* 13470 * Function: 13471 * bcm_th_cosq_bst_multi_profile_get 13472 * Purpose: 13473 * Get the BST profiles of a given BST stat id, per XPE. 13474 * Parameters: 13475 * unit - (IN) unit number 13476 * gport - (IN) gport of the port 13477 * cosq - (IN) COS queue 13478 * bid - (IN) BST statistics ID 13479 * size - (IN) max size of the profile array 13480 * profile - (OUT) profile array retrieved for given BST ID, index with XPE 13481 * count - (OUT) actual size of the profile array 13482 * Returns: 13483 * BCM_E_XXX 13484 */ 13485 int 13486 bcm_th_cosq_bst_multi_profile_get(int unit, 13487 bcm_gport_t gport, 13488 bcm_cos_queue_t cosq, 13489 bcm_bst_stat_id_t bid, 13490 int array_size, 13491 bcm_cosq_bst_profile_t *profile_array, 13492 int *count) 13493 { 13494 int cnt; 13495 bcm_cosq_bst_profile_t profile[_TH_XPES_PER_DEV]; 13496 13497 if (bid == bcmBstStatIdHeadroomPool) { 13498 /* Do not have BST profile to get */ 13499 return BCM_E_PARAM; 13500 } 13501 if ((bid == bcmBstStatIdDevice) 13502 || (bid == bcmBstStatIdUcast) 13503 || (bid == bcmBstStatIdEgrPortPoolSharedUcast)) { 13504 return BCM_E_UNAVAIL; 13505 } 13506 13507 cnt = NUM_XPE(unit); 13508 if ((array_size > 0) && (array_size < cnt)) { 13509 cnt = array_size; 13510 } 13511 if (count) { 13512 *count = cnt; 13513 } 13514 13515 if ((array_size == 0) && (!profile_array)) { 13516 return BCM_E_NONE; 13517 } else if ((array_size > 0) && (profile_array)) { 13518 sal_memset(profile, 0, sizeof(profile)); 13519 BCM_IF_ERROR_RETURN(_bcm_bst_cmn_profile_get 13520 (unit, gport, cosq, BCM_BST_MLT_XPE, bid, profile)); 13521 sal_memcpy(profile_array, profile, cnt*sizeof(bcm_cosq_bst_profile_t)); 13522 return BCM_E_NONE; 13523 } else { 13524 return BCM_E_PARAM; 13525 } 13526 } 13527 13528 /* 13529 * Function: 13530 * bcm_th_cosq_bst_stat_get 13531 * Purpose: 13532 * Get the statistics of a given BST stat id. 13533 * Parameters: 13534 * unit - (IN) unit number 13535 * gport - (IN) gport of the port 13536 * cosq - (IN) COS queue 13537 * buffer - (IN) Buffer ID 13538 * bid - (IN) BST statistics ID 13539 * options - (IN) Clear-on-read or not 13540 * pvalues - (OUT) values retrieved for given BST ID 13541 * Returns: 13542 * BCM_E_XXX 13543 */ 13544 int 13545 bcm_th_cosq_bst_stat_get(int unit, 13546 bcm_gport_t gport, 13547 bcm_cos_queue_t cosq, 13548 bcm_cosq_buffer_id_t buffer, 13549 bcm_bst_stat_id_t bid, 13550 uint32 options, 13551 uint64 *pvalue) 13552 { 13553 if (bid == bcmBstStatIdHeadroomPool) { 13554 return _bcm_th_cosq_bst_hdrm_stat_get 13555 (unit, gport, cosq, buffer, options, pvalue); 13556 } else { 13557 return _bcm_bst_cmn_stat_get(unit, gport, cosq, buffer, bid, options, pvalue); 13558 } 13559 } 13560 13561 /* 13562 * Function: 13563 * bcm_th_cosq_bst_stat_multi_get 13564 * Purpose: 13565 * Get the statistics of a given BST stat id. 13566 * Parameters: 13567 * unit - (IN) unit number 13568 * gport - (IN) gport of the port 13569 * cosq - (IN) COS queue 13570 * options - (IN) Clear-on-read or not 13571 * max_values - (IN) max value in id_list. 13572 * id_list - (IN) IDs to retrieve. 13573 * pvalues - (OUT) values retrieved for id_list 13574 * Returns: 13575 * BCM_E_XXX 13576 */ 13577 int 13578 bcm_th_cosq_bst_stat_multi_get(int unit, 13579 bcm_gport_t gport, 13580 bcm_cos_queue_t cosq, 13581 uint32 options, 13582 int max_values, 13583 bcm_bst_stat_id_t *id_list, 13584 uint64 *pvalues) 13585 { 13586 int i; 13587 13588 for (i = 0; i < max_values; i++) { 13589 if (id_list[i] == bcmBstStatIdHeadroomPool) { 13590 BCM_IF_ERROR_RETURN 13591 (_bcm_th_cosq_bst_hdrm_stat_get(unit, gport, cosq, 13592 BCM_COSQ_BUFFER_ID_INVALID, options, &pvalues[i])); 13593 } else { 13594 BCM_IF_ERROR_RETURN(_bcm_bst_cmn_stat_get(unit, gport, cosq, 13595 -1, id_list[i], options, &pvalues[i])); 13596 } 13597 } 13598 return BCM_E_NONE; 13599 } 13600 13601 /* 13602 * Function: 13603 * bcm_th_cosq_bst_stat_clear 13604 * Purpose: 13605 * Clear the statistics from both hardware and 13606 * software for a given BST stat id. 13607 * Parameters: 13608 * unit - (IN) unit number 13609 * gport - (IN) gport of the port 13610 * cosq - (IN) COS queue 13611 * buffer - (IN) Buffer ID 13612 * bid - (IN) BST statistics ID 13613 * Returns: 13614 * BCM_E_XXX 13615 */ 13616 13617 int bcm_th_cosq_bst_stat_clear(int unit, bcm_gport_t gport, 13618 bcm_cos_queue_t cosq, bcm_cosq_buffer_id_t buffer, 13619 bcm_bst_stat_id_t bid) 13620 { 13621 if (bid == bcmBstStatIdHeadroomPool) { 13622 return _bcm_th_bst_hdrm_stat_clear(unit, gport, cosq, buffer); 13623 } else { 13624 return _bcm_bst_cmn_stat_clear(unit, gport, cosq, bid); 13625 } 13626 } 13627 13628 int bcm_th_cosq_bst_stat_sync(int unit, bcm_bst_stat_id_t bid) 13629 { 13630 return _bcm_bst_cmn_stat_sync(unit, bid); 13631 } 13632 13633 /* 13634 * Function: 13635 * _bcm_th_port_enqueue_set 13636 * Purpose: 13637 * Set the enqueue state of the port 13638 * Parameters: 13639 * unit - (IN) unit number 13640 * gport - (IN) gport of the port 13641 * enable - (IN) TRUE to enable 13642 * FALSE to disable 13643 * Returns: 13644 * BCM_E_XXX 13645 */ 13646 13647 int 13648 _bcm_th_port_enqueue_set(int unit, bcm_port_t gport, int enable) 13649 { 13650 int rv = BCM_E_NONE; 13651 pbmp_t mask; 13652 bcm_port_t port; 13653 uint64 ctrl; 13654 13655 BCM_IF_ERROR_RETURN( 13656 _bcm_esw_port_gport_validate(unit, gport, &port)); 13657 13658 PORT_LOCK(unit); 13659 SOC_IF_ERROR_RETURN(READ_CLMAC_CTRLr(unit, port, &ctrl)); 13660 13661 /* Don't disable TX since it stops egress and hangs if CPU sends */ 13662 soc_reg64_field32_set(unit, CLMAC_CTRLr, &ctrl, TX_ENf, 1); 13663 soc_reg64_field32_set(unit, CLMAC_CTRLr, &ctrl, RX_ENf, enable ? 1 : 0); 13664 13665 if (enable) { 13666 /* Deassert SOFT_RESET */ 13667 soc_reg64_field32_set(unit, CLMAC_CTRLr, &ctrl, SOFT_RESETf, 0); 13668 /* Deassert EGR_XLPORT_BUFFER_SFT_RESET */ 13669 rv = soc_tomahawk_edb_buf_reset(unit, port, 0); 13670 if (BCM_FAILURE(rv)) { 13671 PORT_UNLOCK(unit); 13672 return (rv); 13673 } 13674 /* Release Ingress buffers from reset */ 13675 rv = soc_tomahawk_idb_buf_reset(unit, port, 0); 13676 if (BCM_FAILURE(rv)) { 13677 PORT_UNLOCK(unit); 13678 return (rv); 13679 } 13680 13681 rv = WRITE_CLMAC_CTRLr(unit, port, ctrl); 13682 if (BCM_FAILURE(rv)) { 13683 PORT_UNLOCK(unit); 13684 return (rv); 13685 } 13686 13687 #ifdef BCM_TOMAHAWKPLUS_SUPPORT 13688 /* Special handling for new mac version for TH+. Internally MAC 13689 * loopback looks for rising edge on MAC loopback configuration 13690 * to enter loopback state. 13691 */ 13692 if (SOC_IS_TOMAHAWKPLUS(unit)) { 13693 uint32 ctrl_32; 13694 COMPILER_64_TO_32_LO(ctrl_32, ctrl); 13695 if (ctrl_32 & 0x4) { 13696 /* Do only if loopback bit is intented to be set */ 13697 soc_reg_field32_modify(unit, CLMAC_CTRLr, port, LOCAL_LPBKf, 0); 13698 sal_usleep(10); 13699 /* Wait 10usec as suggested by MAC designer */ 13700 soc_reg_field32_modify(unit, CLMAC_CTRLr, port, LOCAL_LPBKf, 1); 13701 } 13702 } 13703 #endif /* BCM_TOMAHAWKPLUS_SUPPORT */ 13704 13705 soc_link_mask2_get(unit, &mask); 13706 SOC_PBMP_PORT_ADD(mask, port); 13707 rv = soc_link_mask2_set(unit, mask); 13708 if (BCM_FAILURE(rv)) { 13709 PORT_UNLOCK(unit); 13710 return (rv); 13711 } 13712 13713 } else { 13714 /* Disable MAC RX */ 13715 rv = WRITE_CLMAC_CTRLr(unit, port, ctrl); 13716 if (BCM_FAILURE(rv)) { 13717 PORT_UNLOCK(unit); 13718 return (rv); 13719 } 13720 soc_link_mask2_get(unit, &mask); 13721 SOC_PBMP_PORT_REMOVE(mask, port); 13722 rv = soc_link_mask2_set(unit, mask); 13723 if (BCM_FAILURE(rv)) { 13724 PORT_UNLOCK(unit); 13725 return (rv); 13726 } 13727 /* Delay to ensure EOP is received at Ingress */ 13728 sal_udelay(1000); 13729 13730 /* Reset Ingress buffers */ 13731 rv = soc_tomahawk_idb_buf_reset(unit, port, 1); 13732 if (BCM_FAILURE(rv)) { 13733 PORT_UNLOCK(unit); 13734 return (rv); 13735 } 13736 /* Reset egress_buffer */ 13737 rv = soc_tomahawk_edb_buf_reset(unit, port, 1); 13738 if (BCM_FAILURE(rv)) { 13739 PORT_UNLOCK(unit); 13740 return (rv); 13741 } 13742 /* Put port into SOFT_RESET */ 13743 soc_reg64_field32_set(unit, CLMAC_CTRLr, &ctrl, SOFT_RESETf, 1); 13744 rv = WRITE_CLMAC_CTRLr(unit, port, ctrl); 13745 if (BCM_FAILURE(rv)) { 13746 PORT_UNLOCK(unit); 13747 return (rv); 13748 } 13749 13750 } 13751 13752 PORT_UNLOCK(unit); 13753 return BCM_E_NONE; 13754 13755 } 13756 13757 /* 13758 * Function: 13759 * _bcm_th_port_enqueue_get 13760 * Purpose: 13761 * Getting the enqueing state of the port 13762 * Parameters: 13763 * unit - (IN) unit number 13764 * gport - (IN) gport of the port 13765 * enable - (IN) TRUE to enable 13766 * FALSE to disable 13767 * Returns: 13768 * BCM_E_XXX 13769 */ 13770 13771 int 13772 _bcm_th_port_enqueue_get(int unit, bcm_port_t gport, 13773 int *enable) 13774 { 13775 return BCM_E_UNAVAIL; 13776 } 13777 13778 /* 13779 * Function: 13780 * bcm_th_cosq_safc_class_mapping_set 13781 * Purpose: 13782 * Set SAFC mapping for port. 13783 * SAFC class is mapped to cosq or scheduler node gports. 13784 * Parameters: 13785 * unit - (IN) unit number 13786 * port - (IN) port number 13787 * array_count - (IN) count of mapping 13788 * mapping_array - (IN) mappings 13789 * Returns: 13790 * BCM_E_XXX 13791 */ 13792 int 13793 bcm_th_cosq_safc_class_mapping_set(int unit, bcm_gport_t port, 13794 int array_count, 13795 bcm_cosq_safc_class_mapping_t *mapping_array) 13796 { 13797 int index, count; 13798 int cur_class = 0; 13799 int safc_class[_BCM_TH_NUM_SAFC_CLASS]; 13800 bcm_gport_t cur_gport = 0; 13801 uint32 uc_cos_bmp[_BCM_TH_NUM_SAFC_CLASS] = {0}; 13802 uint32 mc_cos_bmp[_BCM_TH_NUM_SAFC_CLASS] = {0}; 13803 bcm_port_t local_port = -1; 13804 13805 BCM_IF_ERROR_RETURN 13806 (_bcm_th_cosq_localport_resolve(unit, port, &local_port)); 13807 13808 if (local_port < 0) { 13809 return BCM_E_PORT; 13810 } 13811 13812 if (IS_CPU_PORT(unit, local_port)) { 13813 return BCM_E_PARAM; 13814 } 13815 13816 if ((array_count < 0) || (array_count > _BCM_TH_NUM_SAFC_CLASS)) { 13817 return BCM_E_PARAM; 13818 } 13819 13820 if (mapping_array == NULL) { 13821 return BCM_E_PARAM; 13822 } 13823 13824 for (count = 0; count < array_count; count++) { 13825 cur_class = mapping_array[count].class_id; 13826 if ((cur_class < 0) || (cur_class >= _BCM_TH_NUM_SAFC_CLASS)) { 13827 return BCM_E_PARAM; 13828 } else { 13829 uc_cos_bmp[cur_class] = 0; 13830 mc_cos_bmp[cur_class] = 0; 13831 } 13832 13833 for (index = 0; index < BCM_COSQ_SAFC_GPORT_COUNT; index++) { 13834 cur_gport = mapping_array[count].gport_list[index]; 13835 if (cur_gport == BCM_GPORT_INVALID) { 13836 break; 13837 } 13838 13839 if ((BCM_GPORT_IS_UCAST_QUEUE_GROUP(cur_gport)) || 13840 (BCM_GPORT_IS_MCAST_QUEUE_GROUP(cur_gport))) { 13841 BCM_IF_ERROR_RETURN 13842 (_bcm_th_fc_status_map_gport(unit, local_port, cur_gport, 13843 &uc_cos_bmp[cur_class], 13844 &mc_cos_bmp[cur_class])); 13845 } else { 13846 return BCM_E_PARAM; 13847 } 13848 } 13849 } 13850 13851 for (index = 0; index < _BCM_TH_NUM_SAFC_CLASS; index++) { 13852 safc_class[index] = index; 13853 } 13854 BCM_IF_ERROR_RETURN 13855 (_bcm_th_cosq_port_fc_profile_set(unit, local_port, safc_class, 13856 uc_cos_bmp, mc_cos_bmp, 13857 _BCM_TH_NUM_SAFC_CLASS)); 13858 13859 return BCM_E_NONE; 13860 } 13861 13862 /* 13863 * Function: 13864 * bcm_th_cosq_safc_class_mapping_get 13865 * Purpose: 13866 * Get SAFC mapping for port. 13867 * Retrieves cosq or scheduler node gports 13868 * associated to SAFC classes. 13869 * Parameters: 13870 * unit - (IN) unit number 13871 * port - (IN) port number 13872 * array_max - (IN) max retrieve count 13873 * mapping_array - (OUT) mappings 13874 * array_count - (OUT) retrieved mapping count 13875 * Returns: 13876 * BCM_E_XXX 13877 */ 13878 int 13879 bcm_th_cosq_safc_class_mapping_get(int unit, bcm_gport_t port, 13880 int array_max, 13881 bcm_cosq_safc_class_mapping_t *mapping_array, 13882 int *array_count) 13883 { 13884 int rv = 0; 13885 int cur_class = 0; 13886 int actual_gport_count, class_count = 0; 13887 bcm_port_t local_port = -1; 13888 13889 BCM_IF_ERROR_RETURN 13890 (_bcm_th_cosq_localport_resolve(unit, port, &local_port)); 13891 13892 if (local_port < 0) { 13893 return BCM_E_PORT; 13894 } 13895 13896 if (IS_CPU_PORT(unit, local_port)) { 13897 return BCM_E_PARAM; 13898 } 13899 13900 if (((mapping_array == NULL) && (array_max > 0)) || 13901 ((mapping_array != NULL) && (array_max <= 0)) || 13902 (array_count == NULL)) { 13903 return BCM_E_PARAM; 13904 } 13905 13906 if (array_max <= 0) { 13907 *array_count = _BCM_TH_NUM_SAFC_CLASS; 13908 return BCM_E_NONE; 13909 } 13910 13911 for (cur_class = 0; cur_class < _BCM_TH_NUM_SAFC_CLASS; cur_class++) { 13912 actual_gport_count = 0; 13913 rv = _bcm_th_cosq_port_fc_get(unit, local_port, cur_class, 13914 mapping_array[class_count].gport_list, 13915 &actual_gport_count); 13916 13917 if (rv == BCM_E_NONE) { 13918 mapping_array[class_count].class_id = cur_class; 13919 if (actual_gport_count < BCM_COSQ_SAFC_GPORT_COUNT) { 13920 mapping_array[class_count].gport_list[actual_gport_count] = 13921 BCM_GPORT_INVALID; 13922 } 13923 class_count++; 13924 } else if (rv != BCM_E_NOT_FOUND) { 13925 return rv; 13926 } 13927 13928 if (class_count == array_max) { 13929 break; 13930 } 13931 } 13932 13933 *array_count = class_count; 13934 if (class_count == 0) { 13935 return BCM_E_NOT_FOUND; 13936 } 13937 13938 return BCM_E_NONE; 13939 } 13940 13941 /* 13942 * Function: 13943 * bcm_th_cosq_cpu_cosq_enable_set 13944 * Purpose: 13945 * To enable/disable Rx of packets on the specified CPU cosq. 13946 * Parameters: 13947 * unit - (IN) Unit number. 13948 * cosq - (IN) CPU Cosq ID 13949 * enable - (IN) Enable/Disable 13950 * Returns: 13951 * BCM_E_xxx 13952 */ 13953 int 13954 bcm_th_cosq_cpu_cosq_enable_set(int unit, bcm_cos_queue_t cosq, int enable) 13955 { 13956 uint32 entry[SOC_MAX_MEM_WORDS]; 13957 int i, index, enable_status; 13958 _bcm_th_cosq_cpu_cosq_config_t *cpu_cosq_config; 13959 soc_info_t *si; 13960 soc_mem_t thdm_mem[] = { 13961 MMU_THDM_DB_QUEUE_CONFIG_PIPE0m, 13962 MMU_THDM_MCQE_QUEUE_CONFIG_PIPE0m 13963 }; 13964 13965 si = &SOC_INFO(unit); 13966 13967 if ((cosq < 0) || (cosq >= NUM_CPU_COSQ(unit))) { 13968 return BCM_E_PARAM; 13969 } 13970 13971 cpu_cosq_config = _bcm_th_cosq_cpu_cosq_config[unit][cosq]; 13972 13973 if (!cpu_cosq_config) { 13974 return BCM_E_INTERNAL; 13975 } 13976 if (enable) { 13977 enable = 1; 13978 } 13979 13980 BCM_IF_ERROR_RETURN(bcm_th_cosq_cpu_cosq_enable_get(unit, cosq, 13981 &enable_status)); 13982 if (enable == enable_status) { 13983 return BCM_E_NONE; 13984 } 13985 13986 /* CPU Port (0) - MC cosq's range from 330 - 378. */ 13987 index = si->port_cosq_base[CMIC_PORT(unit)] + cosq; 13988 13989 /* To set DB and QE entries */ 13990 for (i = 0; i < 2; i++) { 13991 BCM_IF_ERROR_RETURN 13992 (soc_mem_read(unit, thdm_mem[i], MEM_BLOCK_ALL, index, &entry)); 13993 13994 /* When enabled, restore the Min and Shared from the cached value */ 13995 if (!enable) { 13996 cpu_cosq_config->q_min_limit[i] = soc_mem_field32_get(unit, 13997 thdm_mem[i], 13998 &entry, 13999 Q_MIN_LIMITf); 14000 cpu_cosq_config->q_shared_limit[i] = soc_mem_field32_get(unit, 14001 thdm_mem[i], 14002 &entry, 14003 Q_SHARED_LIMITf); 14004 cpu_cosq_config->q_limit_dynamic[i] = soc_mem_field32_get(unit, 14005 thdm_mem[i], 14006 &entry, 14007 Q_LIMIT_DYNAMICf); 14008 cpu_cosq_config->q_limit_enable[i] = soc_mem_field32_get(unit, 14009 thdm_mem[i], 14010 &entry, 14011 Q_LIMIT_ENABLEf); 14012 cpu_cosq_config->q_color_limit_enable[i] = soc_mem_field32_get(unit, 14013 thdm_mem[i], 14014 &entry, 14015 Q_COLOR_LIMIT_ENABLEf); 14016 } 14017 soc_mem_field32_set(unit, thdm_mem[i], &entry, Q_LIMIT_DYNAMICf, 14018 enable ? cpu_cosq_config->q_limit_dynamic[i] : 0); 14019 soc_mem_field32_set(unit, thdm_mem[i], &entry, Q_LIMIT_ENABLEf, 14020 enable ? cpu_cosq_config->q_limit_enable[i] : 1); 14021 soc_mem_field32_set(unit, thdm_mem[i], &entry, Q_COLOR_LIMIT_ENABLEf, 14022 enable ? cpu_cosq_config->q_color_limit_enable[i] : 1); 14023 soc_mem_field32_set(unit, thdm_mem[i], &entry, Q_MIN_LIMITf, 14024 enable ? cpu_cosq_config->q_min_limit[i] : 0); 14025 soc_mem_field32_set(unit, thdm_mem[i], &entry, Q_SHARED_LIMITf, 14026 enable ? cpu_cosq_config->q_shared_limit[i] : 0); 14027 cpu_cosq_config->enable = enable; 14028 BCM_IF_ERROR_RETURN( 14029 soc_mem_write(unit, thdm_mem[i], MEM_BLOCK_ALL, index, &entry)); 14030 } 14031 14032 return BCM_E_NONE; 14033 } 14034 14035 /* 14036 * Function: 14037 * bcm_th_cosq_cpu_cosq_enable_get 14038 * Purpose: 14039 * To get enable/disable status on Rx of packets on the specified CPU cosq. 14040 * Parameters: 14041 * unit - (IN) Unit number. 14042 * cosq - (IN) CPU Cosq ID 14043 * enable - (OUT) Enable/Disable 14044 * Returns: 14045 * BCM_E_xxx 14046 */ 14047 int 14048 bcm_th_cosq_cpu_cosq_enable_get(int unit, bcm_cos_queue_t cosq, int *enable) 14049 { 14050 _bcm_th_cosq_cpu_cosq_config_t *cpu_cosq; 14051 soc_info_t *si; 14052 int index, hw_enable; 14053 uint32 entry[SOC_MAX_MEM_WORDS]; 14054 soc_field_t min_limit, shared_limit, limit_enable, dynamic_enable; 14055 soc_mem_t thdm_mem = MMU_THDM_DB_QUEUE_CONFIG_PIPE0m; 14056 14057 si = &SOC_INFO(unit); 14058 14059 if ((cosq < 0) || (cosq >= NUM_CPU_COSQ(unit))) { 14060 return BCM_E_PARAM; 14061 } 14062 14063 cpu_cosq = _bcm_th_cosq_cpu_cosq_config[unit][cosq]; 14064 if (!cpu_cosq) { 14065 return BCM_E_INTERNAL; 14066 } 14067 14068 /* CPU Port (0) - MC cosq's range from 330 - 378. */ 14069 index = si->port_cosq_base[CMIC_PORT(unit)] + cosq; 14070 hw_enable = 1; 14071 14072 /* Sync up software record with hardware status. */ 14073 BCM_IF_ERROR_RETURN(soc_mem_read(unit, thdm_mem, MEM_BLOCK_ALL, 14074 index, &entry)); 14075 min_limit = soc_mem_field32_get(unit, thdm_mem, &entry, 14076 Q_MIN_LIMITf); 14077 shared_limit = soc_mem_field32_get(unit, thdm_mem, &entry, 14078 Q_SHARED_LIMITf); 14079 limit_enable = soc_mem_field32_get(unit, thdm_mem, &entry, 14080 Q_LIMIT_ENABLEf); 14081 dynamic_enable = soc_mem_field32_get(unit, thdm_mem, &entry, 14082 Q_LIMIT_DYNAMICf); 14083 if ((limit_enable != 0) && (dynamic_enable == 0) && 14084 (min_limit == 0) && (shared_limit == 0)) { 14085 hw_enable = 0; 14086 } 14087 cpu_cosq->enable = hw_enable; 14088 14089 *enable = cpu_cosq->enable; 14090 return BCM_E_NONE; 14091 } 14092 14093 /* 14094 * Function: 14095 * bcm_th2_cosq_buffer_id_multi_get 14096 * Purpose: 14097 * Get mutliple buffer ids associated with a specified port. 14098 * Parameters: 14099 * unit - (IN) BCM device number. 14100 * gport - (IN) Port 14101 * cosq - (IN) Reserved field 14102 * direction - (IN) Specify ingress or egress direction 14103 * array_max - (IN) number of entries to be retrieved 14104 * buf_id_array - (OUT) Buffer id array 14105 * array_count - (OUT) Actural buffer id count in buf_id_array 14106 * Returns: 14107 * BCM_E_XXX 14108 */ 14109 int 14110 bcm_th_cosq_buffer_id_multi_get(int unit, bcm_gport_t gport, 14111 bcm_cos_queue_t cosq, bcm_cosq_dir_t direction, 14112 int array_max, bcm_cosq_buffer_id_t *buf_id_array, 14113 int *array_count) 14114 { 14115 uint8 ipipe2buf[4][2] = {{0, 1}, {2, 3}, {2, 3}, {0, 1}}; 14116 uint8 epipe2buf[4][2] = {{0, 2}, {0, 2}, {1, 3}, {1, 3}}; 14117 14118 bcm_port_t local_port; 14119 int pipe, i; 14120 14121 if ((direction < bcmCosqIngress) || 14122 (direction >= bcmCosqDirectionMaxCount)) { 14123 return BCM_E_PARAM; 14124 } 14125 14126 if (!BCM_GPORT_IS_SET(gport)) { 14127 local_port = gport; 14128 } else if (BCM_GPORT_IS_LOCAL(gport)) { 14129 local_port = BCM_GPORT_LOCAL_GET(gport); 14130 } else if (BCM_GPORT_IS_MODPORT(gport)) { 14131 BCM_IF_ERROR_RETURN(bcm_esw_port_local_get(unit, gport, &local_port)); 14132 } else if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 14133 int idx; 14134 BCM_IF_ERROR_RETURN(_bcm_th_cosq_index_resolve(unit, gport, cosq, 14135 _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE, &local_port, &idx, NULL)); 14136 } else { 14137 return BCM_E_PARAM; 14138 } 14139 14140 if (!SOC_PORT_VALID(unit, local_port)) { 14141 return BCM_E_PORT; 14142 } 14143 14144 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 14145 14146 if (array_max > _BCM_TH_NUM_BUFFER_PER_PIPE) { 14147 *array_count = _BCM_TH_NUM_BUFFER_PER_PIPE; 14148 } else if (array_max >= 0){ 14149 *array_count = array_max; 14150 } else { 14151 return BCM_E_PARAM; 14152 } 14153 14154 for (i = 0; i < *array_count; i++) { 14155 if (bcmCosqIngress == direction) { 14156 buf_id_array[i] = ipipe2buf[pipe][i]; 14157 } else { 14158 buf_id_array[i] = epipe2buf[pipe][i]; 14159 } 14160 } 14161 for (i = *array_count; i < array_max; i++) { 14162 buf_id_array[i] = BCM_COSQ_INVALID_BUF_ID; 14163 } 14164 14165 return BCM_E_NONE; 14166 } 14167 14168 14169 14170 #ifdef BCM_WARM_BOOT_SUPPORT 14171 int 14172 bcm_th_cosq_reinit(int unit) 14173 { 14174 soc_scache_handle_t scache_handle; 14175 uint8 *scache_ptr = NULL; 14176 int *int_scache_ptr = NULL; 14177 uint16 *u16_scache_ptr = NULL; 14178 uint32 *u32_scache_ptr = NULL; 14179 _bcm_th_mmu_info_t *mmu_info = NULL; 14180 _bcm_th_cosq_cpu_port_info_t *cpu_port_info = NULL; 14181 int alloc_size = 0, i, j, pipe = -1, xpe, scache_sz; 14182 soc_profile_mem_t *profile_mem; 14183 soc_mem_t wred_config_mem = INVALIDm; 14184 int index, profile_index, resolution_index; 14185 int stable_size, rv, num, set_index; 14186 mmu_wred_config_entry_t qentry; 14187 uint32 entry[SOC_MAX_MEM_WORDS]; 14188 bcm_port_t port; 14189 static const soc_reg_t port_fc_reg = PORT_LLFC_CFGr; 14190 uint32 rval; 14191 _bcm_bst_device_handlers_t bst_callbks; 14192 _bcm_th_cosq_cpu_cosq_config_t *cpu_cosq_config_p; 14193 _bcm_pfc_deadlock_control_t *pfc_deadlock_control = NULL; 14194 uint16 recovered_ver = 0; 14195 int index_min, index_max; 14196 int additional_scache_sz = 0; 14197 uint32 qcm_app_status[2], host_mem_size; 14198 uint32 *host_mem_add; 14199 14200 SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size)); 14201 if ((stable_size == 0) || (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit))) { 14202 /* COSQ warmboot requires extended scache support i.e. level2 warmboot*/ 14203 return BCM_E_NONE; 14204 } 14205 14206 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_COSQ, 0); 14207 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 0, &scache_ptr, 14208 BCM_WB_DEFAULT_VERSION, &recovered_ver); 14209 if (BCM_FAILURE(rv)) { 14210 return rv; 14211 } 14212 14213 mmu_info = _bcm_th_mmu_info[unit]; 14214 14215 if (mmu_info == NULL) { 14216 return BCM_E_INIT; 14217 } 14218 14219 cpu_port_info = _bcm_th_cosq_cpu_port_info[unit]; 14220 if (cpu_port_info == NULL) { 14221 return BCM_E_INIT; 14222 } 14223 14224 /* Update mmu_info shared limit parameters */ 14225 int_scache_ptr = (int *) scache_ptr; 14226 /* shared limits are now recovered from hw */ 14227 int_scache_ptr += 3; 14228 BCM_IF_ERROR_RETURN( 14229 soc_th_mmu_get_shared_size(unit, 14230 mmu_info->ing_shared_limit, 14231 mmu_info->egr_db_shared_limit, 14232 mmu_info->egr_qe_shared_limit)); 14233 14234 alloc_size = sizeof(_bcm_th_cosq_cpu_port_info_t); 14235 scache_ptr = (uint8*) int_scache_ptr; 14236 sal_memcpy(cpu_port_info, scache_ptr, alloc_size); 14237 14238 /* Restore the Queue to Channel Mapping */ 14239 if (recovered_ver <= BCM_WB_VERSION_1_1) { 14240 BCM_IF_ERROR_RETURN 14241 (_bcm_cosq_rx_queue_channel_reinit(unit)); 14242 } 14243 14244 scache_ptr += alloc_size; 14245 14246 /* Update IFP_COS_MAP memory profile reference counter */ 14247 profile_mem = _bcm_th_ifp_cos_map_profile[unit]; 14248 num = SOC_MEM_SIZE(unit, IFP_COS_MAPm) / _TH_MMU_NUM_INT_PRI; 14249 u16_scache_ptr = (uint16 *)scache_ptr; 14250 for (i = 0; i < num; i++) { 14251 for (j = 0; j < *u16_scache_ptr; j++) { 14252 SOC_IF_ERROR_RETURN( 14253 soc_profile_mem_reference(unit, profile_mem, 14254 i * _TH_MMU_NUM_INT_PRI, 14255 _TH_MMU_NUM_INT_PRI)); 14256 } 14257 u16_scache_ptr++; 14258 } 14259 14260 /* Recover CPU queue config information from scache */ 14261 if (recovered_ver >= BCM_WB_VERSION_1_1) { 14262 cpu_cosq_config_p = _bcm_th_cosq_cpu_cosq_config[unit][0]; 14263 if (cpu_cosq_config_p == NULL) { 14264 return BCM_E_INIT; 14265 } 14266 alloc_size = (SOC_TH_NUM_CPU_QUEUES * 14267 sizeof(_bcm_th_cosq_cpu_cosq_config_t)); 14268 scache_ptr = (uint8*) u16_scache_ptr; 14269 sal_memcpy(cpu_cosq_config_p, scache_ptr, alloc_size); 14270 scache_ptr += alloc_size; 14271 } 14272 14273 /* Retriving num_cos value */ 14274 if (recovered_ver >= BCM_WB_VERSION_1_1) { 14275 int_scache_ptr = (int *) scache_ptr; 14276 _TH_NUM_COS(unit) = *int_scache_ptr++; 14277 scache_ptr = (uint8*) int_scache_ptr; 14278 } 14279 14280 /* Update PRIO2COS_PROFILE register profile reference counter */ 14281 PBMP_PORT_ITER(unit, port) { 14282 BCM_IF_ERROR_RETURN 14283 (soc_reg32_get(unit, port_fc_reg, port, 0, &rval)); 14284 profile_index = soc_reg_field_get(unit, port_fc_reg, rval, PROFILE_INDEXf) * 16; 14285 SOC_IF_ERROR_RETURN 14286 (soc_profile_reg_reference(unit, _bcm_th_prio2cos_profile[unit], 14287 profile_index, 16)); 14288 } 14289 14290 /* Update PORT_COS_MAP memory profile reference counter */ 14291 profile_mem = _bcm_th_cos_map_profile[unit]; 14292 PBMP_ALL_ITER(unit, port) { 14293 SOC_IF_ERROR_RETURN 14294 (soc_mem_read(unit, COS_MAP_SELm, MEM_BLOCK_ALL, port, &entry)); 14295 set_index = soc_mem_field32_get(unit, COS_MAP_SELm, &entry, SELECTf); 14296 SOC_IF_ERROR_RETURN 14297 (soc_profile_mem_reference(unit, profile_mem, set_index * 16, 16)); 14298 } 14299 if (SOC_INFO(unit).cpu_hg_index != -1) { 14300 SOC_IF_ERROR_RETURN(soc_mem_read(unit, COS_MAP_SELm, MEM_BLOCK_ALL, 14301 SOC_INFO(unit).cpu_hg_index, &entry)); 14302 set_index = soc_mem_field32_get(unit, COS_MAP_SELm, &entry, SELECTf); 14303 SOC_IF_ERROR_RETURN 14304 (soc_profile_mem_reference(unit, profile_mem, set_index * 16, 16)); 14305 } 14306 14307 index_min = soc_mem_index_min(unit, SOC_MEM_UNIQUE_ACC_XPE_PIPE(unit, 14308 MMU_WRED_CONFIGm, 0, 0)); 14309 index_max = soc_mem_index_max(unit, SOC_MEM_UNIQUE_ACC_XPE_PIPE(unit, 14310 MMU_WRED_CONFIGm, 0, 0)); 14311 14312 wred_config_mem = MMU_WRED_CONFIGm; 14313 for (pipe = 0; pipe < NUM_PIPE(unit); pipe++) { 14314 for (xpe = 0; xpe < NUM_XPE(unit); xpe++) { 14315 if (SOC_INFO(unit).epipe_xpe_map[pipe] & (1 << xpe)) { 14316 for (index = index_min; index < index_max; index++) { 14317 BCM_IF_ERROR_RETURN 14318 (soc_tomahawk_xpe_mem_read(unit, wred_config_mem, 14319 xpe, pipe, MEM_BLOCK_ALL, index, &qentry)); 14320 profile_index = soc_mem_field32_get(unit, wred_config_mem, 14321 &qentry, PROFILE_INDEXf); 14322 BCM_IF_ERROR_RETURN(soc_profile_mem_reference 14323 (unit, _bcm_th_wred_profile[unit], profile_index, 1)); 14324 14325 if (soc_mem_field32_get(unit, wred_config_mem, &qentry, 14326 ECN_MARKING_ENf)) { 14327 resolution_index = soc_mem_field32_get( 14328 unit, wred_config_mem, &qentry, 14329 WRED_CONG_NOTIFICATION_RESOLUTION_TABLE_MARKING_INDEXf); 14330 } else { 14331 resolution_index = soc_mem_field32_get( 14332 unit, wred_config_mem, &qentry, 14333 WRED_CONG_NOTIFICATION_RESOLUTION_TABLE_DROPPING_INDEXf); 14334 } 14335 _bcm_th_wred_resolution_tbl[resolution_index] = 1; 14336 } 14337 } 14338 } 14339 } 14340 14341 /* Create gport tree */ 14342 _BCM_TH_MMU_INFO(unit)->gport_tree_created = FALSE; 14343 PBMP_ALL_ITER(unit, port) { 14344 if (IS_LB_PORT(unit, port) || IS_CPU_PORT(unit, port)) { 14345 continue; 14346 } 14347 BCM_IF_ERROR_RETURN 14348 (_bcm_th_cosq_gport_tree_create(unit, port)); 14349 } 14350 _BCM_TH_MMU_INFO(unit)->gport_tree_created = TRUE; 14351 14352 /* BST reinit */ 14353 sal_memset(&bst_callbks, 0, sizeof(_bcm_bst_device_handlers_t)); 14354 bst_callbks.resolve_index = &_bcm_th_bst_index_resolve; 14355 bst_callbks.reverse_resolve_index = NULL; 14356 BCM_IF_ERROR_RETURN(_bcm_bst_attach(unit, &bst_callbks)); 14357 #if defined (BCM_TCB_SUPPORT) && defined (INCLUDE_TCB) 14358 if (soc_feature(unit, soc_feature_tcb)){ 14359 #ifdef BCM_TOMAHAWK2_SUPPORT 14360 BCM_IF_ERROR_RETURN(bcm_th2_cosq_tcb_reinit(unit)); 14361 #endif 14362 } 14363 #endif 14364 /* PFC Deadlock recovery should be initialize 14365 irrespective of scache version to handle 14366 upgrades */ 14367 if (soc_feature(unit, soc_feature_pfc_deadlock)) { 14368 BCM_IF_ERROR_RETURN(_bcm_pfc_deadlock_init(unit)); 14369 } 14370 14371 /* Recover PFC Deadlock recovery information from scache */ 14372 if (SOC_IS_TOMAHAWK(unit) && 14373 soc_feature(unit, soc_feature_pfc_deadlock)) { 14374 if (recovered_ver >= BCM_WB_VERSION_1_1) { 14375 pfc_deadlock_control = _BCM_UNIT_PFC_DEADLOCK_CONTROL(unit); 14376 if (pfc_deadlock_control == NULL) { 14377 return BCM_E_INIT; 14378 } 14379 alloc_size = sizeof(_bcm_pfc_deadlock_control_t); 14380 if (recovered_ver >= BCM_WB_VERSION_1_4) { 14381 scache_sz = soc_scache_dictionary_entry_get(unit, 14382 "_bcm_pfc_deadlock_control_t", 14383 alloc_size); 14384 scache_ptr += scache_sz; 14385 additional_scache_sz += alloc_size - scache_sz; 14386 } else { 14387 sal_memcpy(pfc_deadlock_control, scache_ptr, alloc_size); 14388 scache_ptr += alloc_size; 14389 /* Re-set the Hardware Registers/Memory info */ 14390 BCM_IF_ERROR_RETURN(_bcm_th_pfc_deadlock_init(unit)); 14391 BCM_IF_ERROR_RETURN(_bcm_pfc_deadlock_recovery_reset(unit)); 14392 pfc_deadlock_control->cosq_inv_mapping_get = _bcm_th_cosq_inv_mapping_get; 14393 } 14394 } else { 14395 additional_scache_sz += sizeof(_bcm_pfc_deadlock_control_t); 14396 } 14397 } 14398 /* Recovery TIME_DOMAINr count reference */ 14399 if (recovered_ver >= BCM_WB_VERSION_1_2) { 14400 int ii; 14401 for (ii = 0; ii < _BCM_TH_NUM_TIME_DOMAIN; ii++) { 14402 alloc_size = sizeof(uint32); 14403 sal_memcpy(&time_domain_info[unit][ii].ref_count, scache_ptr, alloc_size); 14404 scache_ptr += alloc_size; 14405 } 14406 } else { 14407 additional_scache_sz += _BCM_TH_NUM_TIME_DOMAIN * sizeof(uint32); 14408 } 14409 14410 #ifdef BCM_TOMAHAWK_SUPPORT 14411 if (soc_feature(unit, soc_feature_ecn_wred)) { 14412 if (recovered_ver >= BCM_WB_VERSION_1_3) { 14413 BCM_IF_ERROR_RETURN(bcmi_xgs5_ecn_reinit(unit, &scache_ptr)); 14414 } else { 14415 uint32 mpls_ecn_map_size = 0; 14416 BCM_IF_ERROR_RETURN( 14417 bcmi_xgs5_ecn_scache_size_get(unit, &mpls_ecn_map_size)); 14418 additional_scache_sz += mpls_ecn_map_size; 14419 } 14420 } 14421 #endif 14422 14423 #if defined (BCM_TCB_SUPPORT) && defined (INCLUDE_TCB) 14424 if (soc_feature(unit, soc_feature_tcb)){ 14425 #ifdef BCM_TOMAHAWK2_SUPPORT 14426 if (recovered_ver >= BCM_WB_VERSION_1_4) { 14427 _bcm_cosq_tcb_unit_ctrl_t *tcb_unit_info; 14428 tcb_unit_info = TCB_UNIT_CONTROL(unit); 14429 TCB_INIT(unit); 14430 14431 alloc_size = sizeof(uint16); 14432 sal_memcpy(&tcb_unit_info->tcb_config_init_bmp, scache_ptr, alloc_size); 14433 scache_ptr += alloc_size; 14434 } else { 14435 additional_scache_sz += sizeof(uint16); 14436 } 14437 #endif 14438 } 14439 #else 14440 if (recovered_ver >= BCM_WB_VERSION_1_4) { 14441 scache_ptr += sizeof(uint16); 14442 } else { 14443 additional_scache_sz += sizeof(uint16); 14444 } 14445 #endif 14446 14447 if (soc_feature(unit, soc_feature_pfc_deadlock)) { 14448 pfc_deadlock_control = _BCM_UNIT_PFC_DEADLOCK_CONTROL(unit); 14449 if (pfc_deadlock_control == NULL) { 14450 return BCM_E_INIT; 14451 } 14452 if (recovered_ver >= BCM_WB_VERSION_1_4) { 14453 int priority = 0; 14454 for (i = 0; i < pfc_deadlock_control->pfc_deadlock_cos_max; i++) { 14455 sal_memcpy(&pfc_deadlock_control->pfc_cos2pri[i], 14456 scache_ptr, sizeof(int)); 14457 scache_ptr += sizeof(int); 14458 priority = pfc_deadlock_control->pfc_cos2pri[i]; 14459 if ((priority >= 0) && (priority < _TH_MMU_NUM_INT_PRI)) { 14460 pfc_deadlock_control->hw_cos_idx_inuse[i] = TRUE; 14461 pfc_deadlock_control->pfc_pri2cos[priority] = i; 14462 } 14463 } 14464 sal_memcpy(&pfc_deadlock_control->cb_interval, 14465 scache_ptr, sizeof(uint32)); 14466 scache_ptr += sizeof(uint32); 14467 BCM_IF_ERROR_RETURN(_bcm_pfc_deadlock_reinit(unit)); 14468 BCM_IF_ERROR_RETURN(_bcm_pfc_deadlock_recovery_reset(unit)); 14469 pfc_deadlock_control->cosq_inv_mapping_get = _bcm_th_cosq_inv_mapping_get; 14470 } else { 14471 for (i = 0; i < pfc_deadlock_control->pfc_deadlock_cos_max; i++) { 14472 additional_scache_sz += sizeof(int); 14473 } 14474 additional_scache_sz += sizeof(uint32); 14475 } 14476 } 14477 14478 /* Retriving _bcm_th_wred_resolution_tbl value */ 14479 if (recovered_ver >= BCM_WB_VERSION_1_5) { 14480 u32_scache_ptr = (uint32 *) scache_ptr; 14481 for (i = 0; i < _BCM_TH_NUM_WRED_RESOLUTION_TABLE; i++) { 14482 _bcm_th_wred_resolution_tbl[i] = *u32_scache_ptr++; 14483 } 14484 } else { 14485 additional_scache_sz += (_BCM_TH_NUM_WRED_RESOLUTION_TABLE * 14486 sizeof(uint32));; 14487 } 14488 14489 14490 /* realloc scache_handle resource*/ 14491 if (additional_scache_sz != 0) { 14492 rv = soc_scache_realloc(unit, scache_handle, additional_scache_sz); 14493 if (SOC_FAILURE(rv)) { 14494 return rv; 14495 } 14496 } 14497 14498 qcm_app_status[0] = soc_uc_mem_read(unit, (SRAM_BASEADDR(unit) + sram_offset(app_status))); 14499 qcm_app_status[1] = soc_uc_mem_read(unit, (SRAM_BASEADDR(unit) + sram_offset(app_status) + 4)); 14500 14501 /* Validation check whether core 0 R5 is loaded with QCM app srec file 14502 * ASCII of word QCM_(SHR_QCM_APP_STATUS_1) and _APP(SHR_QCM_APP_STATUS_2) 14503 */ 14504 if ((qcm_app_status[0] == SHR_QCM_APP_STATUS_1) && 14505 (qcm_app_status[1] == SHR_QCM_APP_STATUS_2)) { 14506 host_mem_size = soc_uc_mem_read(unit, (SRAM_BASEADDR(unit) + sram_offset(host_buf_size))); 14507 if (host_mem_size >= SHR_QCM_MEM_MIN_SIZE) { 14508 bcm_th_cosq_burst_monitor_dma_config_set(unit, host_mem_size, &host_mem_add); 14509 } 14510 } 14511 14512 return BCM_E_NONE; 14513 } 14514 14515 int 14516 bcm_th_cosq_sync(int unit) 14517 { 14518 soc_scache_handle_t scache_handle; 14519 uint8 *scache_ptr; 14520 uint32 *u32_scache_ptr; 14521 uint16 *u16_scache_ptr; 14522 int *int_scache_ptr; 14523 _bcm_th_mmu_info_t *mmu_info = NULL; 14524 _bcm_th_cosq_cpu_port_info_t *cpu_port_info = NULL; 14525 int size = 0, ii; 14526 int ing_shared_limit_min, egr_db_shared_limit_min, egr_qe_shared_limit_min; 14527 int xpe_map; 14528 int rv = BCM_E_NONE, ref_count; 14529 _bcm_th_cosq_cpu_cosq_config_t **cpu_cosq_config_p; 14530 _bcm_pfc_deadlock_control_t *pfc_deadlock_control = NULL; 14531 uint32 qcm_app_status[2], qcm_host_status; 14532 14533 mmu_info = _bcm_th_mmu_info[unit]; 14534 if (mmu_info == NULL) { 14535 return BCM_E_INIT; 14536 } 14537 14538 cpu_port_info = _bcm_th_cosq_cpu_port_info[unit]; 14539 if (cpu_port_info == NULL) { 14540 return BCM_E_INIT; 14541 } 14542 14543 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_COSQ, 0); 14544 BCM_IF_ERROR_RETURN 14545 (_bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 0, 14546 &scache_ptr, BCM_WB_DEFAULT_VERSION, NULL)); 14547 14548 /* Cache minimal ing_shared_limit/egr_db_shared_limit/egr_qe_shared_limit */ 14549 xpe_map = SOC_INFO(unit).ipipe_xpe_map[0]|SOC_INFO(unit).ipipe_xpe_map[1]; 14550 _TH_ARRAY_MIN(mmu_info->ing_shared_limit, NUM_XPE(unit), xpe_map, 14551 ing_shared_limit_min); 14552 _TH_ARRAY_MIN(mmu_info->egr_db_shared_limit, NUM_XPE(unit), xpe_map, 14553 egr_db_shared_limit_min); 14554 _TH_ARRAY_MIN(mmu_info->egr_qe_shared_limit, NUM_XPE(unit), xpe_map, 14555 egr_qe_shared_limit_min); 14556 u32_scache_ptr = (uint32*) scache_ptr; 14557 *u32_scache_ptr++ = ing_shared_limit_min; 14558 *u32_scache_ptr++ = egr_db_shared_limit_min; 14559 *u32_scache_ptr++ = egr_qe_shared_limit_min / 4; /* to keep consistence with old version */ 14560 14561 /* Cache _bcm_th_cosq_cpu_port_info_t structure */ 14562 size = sizeof(_bcm_th_cosq_cpu_port_info_t); 14563 scache_ptr = (uint8*)u32_scache_ptr; 14564 sal_memcpy(scache_ptr, cpu_port_info, size); 14565 scache_ptr += size/sizeof(uint8); 14566 14567 /* Cache _bcm_th_ifp_cos_map_profile reference count */ 14568 u16_scache_ptr = (uint16 *)scache_ptr; 14569 for (ii = 0; 14570 ii < (SOC_MEM_SIZE(unit, IFP_COS_MAPm) / _TH_MMU_NUM_INT_PRI); 14571 ii++) { 14572 rv = soc_profile_mem_ref_count_get(unit, 14573 _bcm_th_ifp_cos_map_profile[unit], 14574 ii * _TH_MMU_NUM_INT_PRI, 14575 &ref_count); 14576 if (!(rv == SOC_E_NOT_FOUND || rv == SOC_E_NONE)) { 14577 return rv; 14578 } 14579 *u16_scache_ptr++ = (uint16)(ref_count & 0xffff); 14580 } 14581 14582 /* Sync CPU Queue info */ 14583 cpu_cosq_config_p = _bcm_th_cosq_cpu_cosq_config[unit]; 14584 size = (SOC_TH_NUM_CPU_QUEUES * sizeof(_bcm_th_cosq_cpu_cosq_config_t)); 14585 scache_ptr = (uint8*) u16_scache_ptr; 14586 sal_memcpy(scache_ptr, *cpu_cosq_config_p, size); 14587 scache_ptr += (size / sizeof(uint8)); 14588 14589 /* Sync num_cos value */ 14590 int_scache_ptr = (int*) scache_ptr; 14591 *int_scache_ptr++ = _TH_NUM_COS(unit); 14592 scache_ptr = (uint8 *)int_scache_ptr; 14593 14594 /* Sync PFC Deadlock Control info */ 14595 if (SOC_IS_TOMAHAWK(unit) && 14596 soc_feature(unit, soc_feature_pfc_deadlock)) { 14597 pfc_deadlock_control = _BCM_UNIT_PFC_DEADLOCK_CONTROL(unit); 14598 if (pfc_deadlock_control == NULL) { 14599 return BCM_E_INIT; 14600 } 14601 size = sizeof(_bcm_pfc_deadlock_control_t); 14602 sal_memcpy(scache_ptr, pfc_deadlock_control, size); 14603 scache_ptr += (size / sizeof(uint8)); 14604 SOC_IF_ERROR_RETURN 14605 (soc_scache_dictionary_entry_set(unit, 14606 "_bcm_pfc_deadlock_control_t", 14607 size)); 14608 } 14609 /* Sync TIME_DOMAINr field and count reference */ 14610 u32_scache_ptr = (uint32*) scache_ptr; 14611 size = sizeof(uint32); 14612 for (ii = 0; ii < _BCM_TH_NUM_TIME_DOMAIN; ii++) { 14613 sal_memcpy(u32_scache_ptr, &time_domain_info[unit][ii].ref_count, size); 14614 u32_scache_ptr++; 14615 } 14616 14617 scache_ptr = (uint8*)u32_scache_ptr; 14618 #ifdef BCM_TOMAHAWK_SUPPORT 14619 if (soc_feature(unit, soc_feature_ecn_wred)) { 14620 BCM_IF_ERROR_RETURN(bcmi_xgs5_ecn_sync(unit, &scache_ptr)); 14621 } 14622 #endif 14623 #if defined (BCM_TCB_SUPPORT) && defined (INCLUDE_TCB) 14624 if (soc_feature(unit, soc_feature_tcb)){ 14625 #ifdef BCM_TOMAHAWK2_SUPPORT 14626 _bcm_cosq_tcb_unit_ctrl_t *tcb_unit_info; 14627 tcb_unit_info = TCB_UNIT_CONTROL(unit); 14628 TCB_INIT(unit); 14629 14630 u16_scache_ptr = (uint16*) scache_ptr; 14631 size = sizeof(uint16); 14632 sal_memcpy(u16_scache_ptr, &tcb_unit_info->tcb_config_init_bmp, size); 14633 u16_scache_ptr ++; 14634 scache_ptr = (uint8*)u16_scache_ptr; 14635 #endif 14636 } 14637 #else 14638 u16_scache_ptr = (uint16*) scache_ptr; 14639 u16_scache_ptr ++; 14640 scache_ptr = (uint8*)u16_scache_ptr; 14641 #endif 14642 14643 /* Second around to sync PFC Deadlock Control info */ 14644 if (soc_feature(unit, soc_feature_pfc_deadlock)) { 14645 pfc_deadlock_control = _BCM_UNIT_PFC_DEADLOCK_CONTROL(unit); 14646 if (pfc_deadlock_control == NULL) { 14647 return BCM_E_INIT; 14648 } 14649 for (ii = 0; ii < pfc_deadlock_control->pfc_deadlock_cos_max; ii++) { 14650 sal_memcpy(scache_ptr, &pfc_deadlock_control->pfc_cos2pri[ii], 14651 sizeof(int)); 14652 scache_ptr += sizeof(int); 14653 } 14654 sal_memcpy(scache_ptr, &pfc_deadlock_control->cb_interval, 14655 sizeof(uint32)); 14656 scache_ptr += sizeof(uint32); 14657 } 14658 14659 u32_scache_ptr = (uint32*) scache_ptr; 14660 14661 for (ii = 0; ii < _BCM_TH_NUM_WRED_RESOLUTION_TABLE; ii++) { 14662 *u32_scache_ptr++ = _bcm_th_wred_resolution_tbl[ii]; 14663 } 14664 14665 scache_ptr = (uint8 *)u32_scache_ptr; 14666 14667 qcm_app_status[0] = soc_uc_mem_read(unit, (SRAM_BASEADDR(unit) + sram_offset(app_status))); 14668 qcm_app_status[1] = soc_uc_mem_read(unit, (SRAM_BASEADDR(unit) + sram_offset(app_status) + 4)); 14669 14670 /* Validation check whether core 0 R5 is loaded with QCM app srec file 14671 * ASCII of word QCM_(SHR_QCM_APP_STATUS_1) and _APP(SHR_QCM_APP_STATUS_2) 14672 */ 14673 if ((qcm_app_status[0] == SHR_QCM_APP_STATUS_1) && 14674 (qcm_app_status[1] == SHR_QCM_APP_STATUS_2)) { 14675 14676 qcm_host_status = soc_uc_mem_read(unit, (SRAM_BASEADDR(unit) + sram_offset(host_status))); 14677 if (qcm_host_status & SHR_QCM_INIT_STATUS_BIT) { 14678 bcm_th_cosq_burst_monitor_dma_config_reset(unit); 14679 } 14680 } 14681 14682 return BCM_E_NONE; 14683 } 14684 14685 #endif /* BCM_WARM_BOOT_SUPPORT */ 14686 14687 /* 14688 * Function: 14689 * bcm_th_cosq_sw_dump 14690 * Purpose: 14691 * Displays COS Queue information maintained by software. 14692 * Parameters: 14693 * unit - Device unit number 14694 * Returns: 14695 * None 14696 */ 14697 void 14698 bcm_th_cosq_sw_dump(int unit) 14699 { 14700 bcm_port_t port; 14701 int ii; 14702 LOG_CLI((BSL_META_U(unit, 14703 "\nSW Information COSQ - Unit %d\n"), unit)); 14704 PBMP_ALL_ITER(unit, port) { 14705 if (IS_CPU_PORT(unit, port)) { 14706 (void)_bcm_th_cosq_cpu_port_info_dump(unit); 14707 } 14708 (void)_bcm_th_cosq_port_info_dump(unit, port); 14709 } 14710 for (ii = 0; ii < _BCM_TH_NUM_TIME_DOMAIN; ii++) { 14711 LOG_CLI((BSL_META_U(unit, 14712 "\nTIME_DOMAIN[%d] - refcnt %d\n"), ii, 14713 time_domain_info[unit][ii].ref_count)); 14714 } 14715 14716 #ifndef BCM_SW_STATE_DUMP_DISABLE 14717 #if defined (INCLUDE_TCB) && defined (BCM_TCB_SUPPORT) 14718 if(soc_feature(unit, soc_feature_tcb)) { 14719 #ifdef BCM_TOMAHAWK2_SUPPORT 14720 (void)bcm_th2_cosq_tcb_sw_dump(unit); 14721 #endif 14722 } 14723 #endif 14724 #endif /* BCM_SW_STATE_DUMP_DISABLE */ 14725 14726 return; 14727 } 14728 14729 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT) 14730 /* 14731 * Function: 14732 * bcm_th_cosq_port_attach 14733 * Purpose: 14734 * Initialize Cosq for newly added port 14735 * Parameters: 14736 * unit - (IN) Unit number. 14737 * port - (IN) Logical port. 14738 * Returns: 14739 * SOC_E_XXX 14740 */ 14741 int 14742 bcm_th_cosq_port_attach(int unit, bcm_port_t port) 14743 { 14744 _bcm_th_cosq_port_info_t *port_info = NULL; 14745 int default_mode = BCM_COSQ_WEIGHTED_ROUND_ROBIN, default_weight = 1; 14746 int i; 14747 uint64 rval64s[16], *prval64s[1]; 14748 uint32 rval, profile_index; 14749 14750 if (IS_CPU_PORT(unit, port) || IS_LB_PORT(unit, port) || 14751 IS_MANAGEMENT_PORT(unit, port)) { 14752 return BCM_E_PARAM; 14753 } 14754 14755 /* Increase the reference of defalt PRIO2COS_PROFILE */ 14756 sal_memset(rval64s, 0, sizeof(rval64s)); 14757 prval64s[0] = rval64s; 14758 BCM_IF_ERROR_RETURN 14759 (soc_profile_reg_add(unit, _bcm_th_prio2cos_profile[unit], 14760 prval64s, 16, &profile_index)); 14761 /* update PORT_LLFC_CFG as default profile might not be 0 */ 14762 BCM_IF_ERROR_RETURN(soc_reg32_get(unit, PORT_LLFC_CFGr, port, 0, &rval)); 14763 soc_reg_field_set(unit, PORT_LLFC_CFGr, &rval, PROFILE_INDEXf, profile_index/16); 14764 BCM_IF_ERROR_RETURN(soc_reg32_set(unit, PORT_LLFC_CFGr, port, 0, rval)); 14765 14766 /* Increase the reference of default COS_MAP_PROFILE */ 14767 BCM_IF_ERROR_RETURN 14768 (soc_mem_field32_modify(unit, COS_MAP_SELm, port, SELECTf, 0)); 14769 BCM_IF_ERROR_RETURN 14770 (soc_profile_mem_reference(unit, _bcm_th_cos_map_profile[unit], 0, 0)); 14771 14772 /* Create gport tree */ 14773 _BCM_TH_MMU_INFO(unit)->gport_tree_created = FALSE; 14774 BCM_IF_ERROR_RETURN(_bcm_th_cosq_gport_tree_create(unit, port)); 14775 _BCM_TH_MMU_INFO(unit)->gport_tree_created = TRUE; 14776 14777 /* Set Default Scheduler Configuration on the ports */ 14778 port_info = &_bcm_th_cosq_port_info[unit][port]; 14779 for (i = 0; i < _BCM_TH_NUM_SCHEDULER_PER_PORT; i++) { 14780 BCM_IF_ERROR_RETURN 14781 (bcm_th_cosq_gport_sched_set(unit, port_info->sched[i].gport, 14782 -1, default_mode, default_weight)); 14783 } 14784 for (i = 0; i < _BCM_TH_NUM_UCAST_QUEUE_PER_PORT; i++) { 14785 BCM_IF_ERROR_RETURN 14786 (bcm_th_cosq_gport_sched_set(unit, port_info->ucast[i].gport, 14787 -1, default_mode, default_weight)); 14788 } 14789 for (i = 0; i < _BCM_TH_NUM_MCAST_QUEUE_PER_PORT; i++) { 14790 BCM_IF_ERROR_RETURN 14791 (bcm_th_cosq_gport_sched_set(unit, port_info->mcast[i].gport, 14792 -1, default_mode, default_weight)); 14793 } 14794 14795 #if defined(BCM_TOMAHAWK2_SUPPORT) 14796 /* Update shared limit of new ports in case the shared limit has been 14797 * adjusted by bcm_cosq_control_set() API */ 14798 BCM_IF_ERROR_RETURN 14799 (soc_th2_mmu_config_shared_buf_set_hw_port(unit, port, 14800 _BCM_TH_MMU_INFO(unit)->ing_shared_limit, 14801 _BCM_TH_MMU_INFO(unit)->egr_db_shared_limit, 14802 _BCM_TH_MMU_INFO(unit)->egr_qe_shared_limit)); 14803 #endif 14804 return BCM_E_NONE; 14805 } 14806 14807 #if defined(BCM_TOMAHAWK2_SUPPORT) 14808 /* 14809 * Function: 14810 * _bcm_th2_cosq_port_guarantee_reset 14811 * Purpose: 14812 * Reset the guarantee of priority group, uc queue, mc queue to the default 14813 * Parameters: 14814 * unit - (IN) Unit number. 14815 * port - (IN) Logical port. 14816 * Returns: 14817 * BCM_E_XXX 14818 */ 14819 STATIC int 14820 _bcm_th2_cosq_port_guarantee_reset(int unit, bcm_port_t port) 14821 { 14822 soc_info_t *si = &SOC_INFO(unit); 14823 _soc_mmu_device_info_t devcfg; 14824 int lossless, override, default_mtu_cells, idx, numq; 14825 int pg_guarantee, uc_guarantee, mc_guarantee; 14826 14827 lossless = soc_property_get(unit, spn_MMU_LOSSLESS, 0); 14828 override = soc_property_get(unit, spn_MMU_CONFIG_OVERRIDE, 1); 14829 14830 _soc_th2_mmu_init_dev_config(unit, &devcfg, lossless); 14831 default_mtu_cells = _MMU_CFG_MMU_BYTES_TO_CELLS(devcfg.default_mtu_size + 14832 devcfg.mmu_hdr_byte, 14833 devcfg.mmu_cell_size); 14834 14835 /* priority group */ 14836 for (idx = 0; idx < _TH_MMU_NUM_PG; idx++) { 14837 pg_guarantee = 0; 14838 if (idx == 7 && lossless) { 14839 pg_guarantee = default_mtu_cells; 14840 } 14841 if (!override) { 14842 _soc_mmu_cfg_property_get_cells 14843 (unit, port, spn_PRIGROUP, idx, spn_GUARANTEE, FALSE, 14844 &pg_guarantee, devcfg.mmu_cell_size, 14845 _MMU_DEFAULT_THRES_TYPE); 14846 pg_guarantee *= devcfg.mmu_cell_size; 14847 } 14848 BCM_IF_ERROR_RETURN 14849 (_bcm_th_cosq_ing_res_set(unit, port, idx, 14850 bcmCosqControlIngressPortPGMinLimitBytes, 14851 pg_guarantee)); 14852 } 14853 14854 /* UC */ 14855 numq = MIN(si->port_num_uc_cosq[port], NUM_COS(unit)); 14856 for (idx = 0; idx < numq; idx++) { 14857 uc_guarantee = 0; 14858 if (!override) { 14859 _soc_mmu_cfg_property_get_cells 14860 (unit, port, spn_QUEUE, idx, spn_GUARANTEE, FALSE, 14861 &uc_guarantee, devcfg.mmu_cell_size, 14862 _MMU_DEFAULT_THRES_TYPE); 14863 uc_guarantee *= devcfg.mmu_cell_size; 14864 } 14865 BCM_IF_ERROR_RETURN 14866 (_bcm_th_cosq_egr_queue_set(unit, port, idx, 14867 bcmCosqControlEgressUCQueueMinLimitBytes, 14868 uc_guarantee)); 14869 } 14870 14871 /* MC */ 14872 numq = MIN(si->port_num_cosq[port], NUM_COS(unit)); 14873 for (idx = 0; idx < numq; idx++) { 14874 mc_guarantee = 0; 14875 if (!override) { 14876 _soc_mmu_cfg_property_get_cells 14877 (unit, port, spn_MQUEUE, idx, spn_GUARANTEE, FALSE, 14878 &mc_guarantee, devcfg.mmu_cell_size, 14879 _MMU_DEFAULT_THRES_TYPE); 14880 mc_guarantee *= devcfg.mmu_cell_size; 14881 } 14882 BCM_IF_ERROR_RETURN 14883 (_bcm_th_cosq_egr_queue_set(unit, port, idx, 14884 bcmCosqControlEgressMCQueueMinLimitBytes, 14885 mc_guarantee)); 14886 } 14887 14888 return BCM_E_NONE; 14889 } 14890 #endif 14891 14892 /* 14893 * Function: 14894 * bcm_th_cosq_port_detach 14895 * Purpose: 14896 * Clear cosq configuration of port 14897 * Parameters: 14898 * unit - (IN) Unit number. 14899 * port - (IN) Logical port. 14900 * Returns: 14901 * SOC_E_XXX 14902 */ 14903 int 14904 bcm_th_cosq_port_detach(int unit, bcm_port_t port) 14905 { 14906 soc_info_t *si = &SOC_INFO(unit); 14907 _bcm_th_cosq_port_info_t *port_info = NULL; 14908 uint32 rval, profile_index; 14909 uint32 entry[SOC_MAX_MEM_WORDS]; 14910 14911 if (IS_CPU_PORT(unit, port) || IS_LB_PORT(unit, port) || 14912 IS_MANAGEMENT_PORT(unit, port)) { 14913 return BCM_E_PARAM; 14914 } 14915 14916 #if defined(BCM_TOMAHAWK2_SUPPORT) 14917 /* When update guarantee of PG/UC/MC via API, the shared limit is adjusted 14918 * accordingly. So MUST reset the gurarntee to the default value before 14919 * deleting the port to recover the shared limit. */ 14920 BCM_IF_ERROR_RETURN 14921 (_bcm_th2_cosq_port_guarantee_reset(unit, port)); 14922 #endif 14923 14924 /* Destroy cosq gport tree on port */ 14925 port_info = &_bcm_th_cosq_port_info[unit][port]; 14926 sal_memset(port_info, 0, sizeof(_bcm_th_cosq_port_info_t)); 14927 14928 /* Decrease the reference of defalt PRIO2COS_PROFILE */ 14929 BCM_IF_ERROR_RETURN(soc_reg32_get(unit, PORT_LLFC_CFGr, port, 0, &rval)); 14930 profile_index = 14931 soc_reg_field_get(unit, PORT_LLFC_CFGr, rval, PROFILE_INDEXf) * 16; 14932 BCM_IF_ERROR_RETURN 14933 (soc_profile_reg_delete(unit, _bcm_th_prio2cos_profile[unit], 14934 profile_index)); 14935 14936 /* Decrease the reference of COS_MAP_PROFILE */ 14937 SOC_IF_ERROR_RETURN 14938 (soc_mem_read(unit, COS_MAP_SELm, MEM_BLOCK_ALL, port, &entry)); 14939 profile_index = soc_mem_field32_get(unit, COS_MAP_SELm, &entry, SELECTf); 14940 SOC_IF_ERROR_RETURN 14941 (soc_profile_mem_delete(unit, _bcm_th_cos_map_profile[unit], 14942 profile_index * 16)); 14943 14944 /* Clear cosq */ 14945 si->port_num_cosq[port] = 0; 14946 si->port_cosq_base[port] = 0; 14947 si->port_num_uc_cosq[port] = 0; 14948 si->port_uc_cosq_base[port] = 0; 14949 si->port_num_ext_cosq[port] = 0; 14950 14951 return BCM_E_NONE; 14952 } 14953 #endif /* BCM_TOMAHAWK2_SUPPORT BCM_TRIDENT3_SUPPORT */ 14954 14955 int bcm_th_cosq_burst_monitor_dma_config_reset(int unit) 14956 { 14957 uint32 qcm_app_status[2], qcm_host_status, qcm_uc_status, time_count; 14958 uint32 *read_addr_ptr, read_addr; 14959 14960 qcm_app_status[0] = soc_uc_mem_read(unit, (SRAM_BASEADDR(unit) + sram_offset(app_status))); 14961 qcm_app_status[1] = soc_uc_mem_read(unit, (SRAM_BASEADDR(unit) + sram_offset(app_status) + 4)); 14962 14963 /* Validation check whether core 0 R5 is loaded with CM app srec file 14964 * ASCII of word QCM_(SHR_QCM_APP_STATUS_1) and _APP(SHR_QCM_APP_STATUS_2) 14965 */ 14966 if ((qcm_app_status[0] != SHR_QCM_APP_STATUS_1) || 14967 (qcm_app_status[1] != SHR_QCM_APP_STATUS_2)) { 14968 LOG_ERROR(BSL_LS_BCM_COSQ, (BSL_META_U(unit, 14969 "load CM APP srec file to core 0\n"))); 14970 return BCM_E_UNAVAIL; 14971 } 14972 14973 qcm_host_status = soc_uc_mem_read(unit, (SRAM_BASEADDR(unit) + sram_offset(host_status))); 14974 if (!(qcm_host_status & SHR_QCM_INIT_STATUS_BIT)) { 14975 LOG_ERROR(BSL_LS_BCM_COSQ, (BSL_META_U(unit, 14976 "shared memory not allocated yet\n"))); 14977 return BCM_E_INIT; 14978 } 14979 read_addr = soc_uc_mem_read(unit, (SRAM_BASEADDR(unit) + sram_offset(host_buf_start_addr))); 14980 read_addr_ptr = (uint32 *)soc_cm_p2l(unit, read_addr); 14981 14982 qcm_host_status = (qcm_host_status & (~SHR_QCM_INIT_STATUS_BIT)); 14983 soc_uc_mem_write(unit, (SRAM_BASEADDR(unit) + sram_offset(host_status)), (uint32)qcm_host_status); 14984 14985 time_count = 0; 14986 while (1) { 14987 qcm_uc_status = soc_uc_mem_read(unit, (SRAM_BASEADDR(unit) + sram_offset(uc_status))); 14988 qcm_uc_status = qcm_uc_status & SHR_QCM_INIT_STATUS_BIT; 14989 if (!qcm_uc_status) { 14990 break; 14991 } 14992 ++time_count; 14993 if ((time_count * QCM_UC_STATUS_TIMEOUT) > QCM_UC_MSG_TIMEOUT) { 14994 LOG_ERROR(BSL_LS_BCM_COSQ, (BSL_META_U(unit, 14995 "CM APP R5 core 0 does not responded\n"))); 14996 return BCM_E_TIMEOUT; 14997 } 14998 sal_usleep(QCM_UC_STATUS_TIMEOUT); 14999 } 15000 soc_cm_sfree(unit, read_addr_ptr); 15001 15002 return BCM_E_NONE; 15003 } 15004 15005 int bcm_th_cosq_burst_monitor_dma_config_set(int unit, 15006 uint32 host_mem_size, 15007 uint32 **host_mem_add) 15008 { 15009 uint32 qcm_app_status[2], qcm_host_status, qcm_uc_status, shared_mem_size, share_mem_add, endianess; 15010 int time_count, rv; 15011 15012 qcm_app_status[0] = soc_uc_mem_read(unit, (SRAM_BASEADDR(unit) + sram_offset(app_status))); 15013 qcm_app_status[1] = soc_uc_mem_read(unit, (SRAM_BASEADDR(unit) + sram_offset(app_status) + 4)); 15014 15015 /* Validation check whether core 0 R5 is loaded with QCM app srec file 15016 * ASCII of word QCM_(SHR_QCM_APP_STATUS_1) and _APP(SHR_QCM_APP_STATUS_2) 15017 */ 15018 if ((qcm_app_status[0] != SHR_QCM_APP_STATUS_1) || 15019 (qcm_app_status[1] != SHR_QCM_APP_STATUS_2)) { 15020 LOG_ERROR(BSL_LS_BCM_COSQ, (BSL_META_U(unit, 15021 "load QCM app srec file to core 0\n"))); 15022 return BCM_E_UNAVAIL; 15023 } 15024 15025 qcm_host_status = soc_uc_mem_read(unit, (SRAM_BASEADDR(unit) + sram_offset(host_status))); 15026 if (qcm_host_status & SHR_QCM_INIT_STATUS_BIT) { 15027 if (host_mem_size == 0) { 15028 rv = bcm_th_cosq_burst_monitor_dma_config_reset(unit); 15029 *host_mem_add = NULL; 15030 soc_uc_mem_write(unit, (SRAM_BASEADDR(unit) + sram_offset(host_buf_start_addr)), (uint32)0); 15031 soc_uc_mem_write(unit, (SRAM_BASEADDR(unit) + sram_offset(host_buf_size)), (uint32)0); 15032 return rv; 15033 } else { 15034 LOG_ERROR(BSL_LS_BCM_COSQ, (BSL_META_U(unit, 15035 "already configured\n"))); 15036 return BCM_E_PARAM; 15037 } 15038 } 15039 15040 qcm_host_status = qcm_host_status | SHR_QCM_INIT_STATUS_BIT; 15041 shared_mem_size = (uint32)sizeof(struct bcm_cosq_burst_output_s); 15042 shared_mem_size = host_mem_size - (host_mem_size % shared_mem_size); 15043 15044 if (shared_mem_size < SHR_QCM_MEM_MIN_SIZE) { 15045 LOG_ERROR(BSL_LS_BCM_COSQ, (BSL_META_U(unit, 15046 "except's minimum shared memory size : %x\n"), 15047 SHR_QCM_MEM_MIN_SIZE)); 15048 return BCM_E_PARAM; 15049 } 15050 15051 /* Ensure QCM app host memory is not NULL */ 15052 *host_mem_add = (uint32 *) soc_cm_salloc(unit, host_mem_size, "Host buffer"); 15053 if (*host_mem_add == NULL) { 15054 LOG_ERROR(BSL_LS_BCM_COSQ, (BSL_META_U(unit, 15055 "host memory address NULL\n"))); 15056 return BCM_E_PARAM; 15057 } 15058 15059 sal_memset(*host_mem_add, 0, host_mem_size); 15060 share_mem_add = (uint32)soc_cm_l2p(unit, *host_mem_add); 15061 15062 soc_uc_mem_write(unit, (SRAM_BASEADDR(unit) + sram_offset(host_buf_start_addr)), (uint32)share_mem_add); 15063 soc_uc_mem_write(unit, (SRAM_BASEADDR(unit) + sram_offset(host_buf_size)), (uint32)shared_mem_size); 15064 15065 soc_uc_mem_write(unit, (SRAM_BASEADDR(unit) + sram_offset(drop_table_index)), 15066 (uint32)soc_mem_base(unit, MMU_CTR_UC_DROP_MEM_XPE0_PIPE0m)); 15067 soc_uc_mem_write(unit, (SRAM_BASEADDR(unit) + sram_offset(drop_table_index) + 4), 15068 (uint32)soc_mem_base(unit, MMU_CTR_UC_DROP_MEM_XPE0_PIPE1m)); 15069 soc_uc_mem_write(unit, (SRAM_BASEADDR(unit) + sram_offset(drop_table_index) + 8), 15070 (uint32)soc_mem_base(unit, MMU_CTR_UC_DROP_MEM_XPE1_PIPE2m)); 15071 soc_uc_mem_write(unit, (SRAM_BASEADDR(unit) + sram_offset(drop_table_index) + 12), 15072 (uint32)soc_mem_base(unit, MMU_CTR_UC_DROP_MEM_XPE1_PIPE3m)); 15073 15074 soc_uc_mem_write(unit, (SRAM_BASEADDR(unit) + sram_offset(egr_table_index)), 15075 (uint32)soc_mem_base(unit, EGR_PERQ_XMT_COUNTERSm)); 15076 15077 soc_uc_mem_write(unit, (SRAM_BASEADDR(unit) + sram_offset(queues_per_pipe)), 15078 (uint32)SOC_TH_MMU_GP_UCQ_NUM); 15079 soc_uc_mem_write(unit, (SRAM_BASEADDR(unit) + sram_offset(queues_per_port)), 15080 (uint32)_BCM_TH_NUM_UCAST_QUEUE_PER_PORT); 15081 soc_uc_mem_write(unit, (SRAM_BASEADDR(unit) + sram_offset(ports_per_pipe)), 15082 (uint32)_TH_MMU_PORTS_PER_PIPE); 15083 soc_uc_mem_write(unit, (SRAM_BASEADDR(unit) + sram_offset(num_pipes)), 15084 (uint32)_TH_NUM_PIPES); 15085 soc_uc_mem_write(unit, (SRAM_BASEADDR(unit) + sram_offset(num_xpe_per_pipe)), 15086 (uint32)_BCM_TH_NUM_BUFFER_PER_PIPE); 15087 15088 soc_uc_mem_write(unit, (SRAM_BASEADDR(unit) + sram_offset(host_status)), (uint32)qcm_host_status); 15089 15090 time_count = 0; 15091 while (1) { 15092 qcm_uc_status = soc_uc_mem_read(unit, (SRAM_BASEADDR(unit) + sram_offset(uc_status))); 15093 qcm_uc_status = qcm_uc_status & SHR_QCM_INIT_STATUS_BIT; 15094 if (qcm_host_status == qcm_uc_status) { 15095 break; 15096 } 15097 ++time_count; 15098 if ((time_count * QCM_UC_STATUS_TIMEOUT) > QCM_UC_MSG_TIMEOUT) { 15099 LOG_ERROR(BSL_LS_BCM_COSQ, (BSL_META_U(unit, 15100 "QCM app R5 core 0 does not responded\n"))); 15101 return BCM_E_TIMEOUT; 15102 } 15103 sal_usleep(QCM_UC_STATUS_TIMEOUT); 15104 } 15105 if (*host_mem_add[0] == 0x1000000) { 15106 endianess = 1; 15107 } else { 15108 endianess = 0; 15109 } 15110 soc_uc_mem_write(unit, (SRAM_BASEADDR(unit) + sram_offset(endianess)), (uint32)endianess); 15111 15112 return BCM_E_NONE; 15113 } 15114 15115 int bcm_th_cosq_burst_monitor_dma_config_get(int unit, 15116 uint32 *host_mem_size, 15117 uint32 **host_mem_add) 15118 { 15119 uint32 qcm_app_status[2], qcm_host_status; 15120 uint32 host_addr; 15121 15122 qcm_app_status[0] = soc_uc_mem_read(unit, (SRAM_BASEADDR(unit) + sram_offset(app_status))); 15123 qcm_app_status[1] = soc_uc_mem_read(unit, (SRAM_BASEADDR(unit) + sram_offset(app_status) + 4)); 15124 15125 /* Validation check whether core 0 R5 is loaded with CM app srec file 15126 * ASCII of word QCM_(SHR_QCM_APP_STATUS_1) and _APP(SHR_QCM_APP_STATUS_2) 15127 */ 15128 if ((qcm_app_status[0] != SHR_QCM_APP_STATUS_1) || (qcm_app_status[1] != SHR_QCM_APP_STATUS_2)) { 15129 LOG_ERROR(BSL_LS_BCM_COSQ, (BSL_META_U(unit, 15130 "load CM APP srec file to core 0\n"))); 15131 return BCM_E_UNAVAIL; 15132 } 15133 15134 qcm_host_status = soc_uc_mem_read(unit, (SRAM_BASEADDR(unit) + sram_offset(host_status))); 15135 if (!(qcm_host_status & SHR_QCM_INIT_STATUS_BIT)) { 15136 LOG_ERROR(BSL_LS_BCM_COSQ, (BSL_META_U(unit, 15137 "shared memory not allocated yet\n"))); 15138 return BCM_E_INIT; 15139 } 15140 host_addr = soc_uc_mem_read(unit, (SRAM_BASEADDR(unit) + sram_offset(host_buf_start_addr))); 15141 *host_mem_size = soc_uc_mem_read(unit, (SRAM_BASEADDR(unit) + sram_offset(host_buf_size))); 15142 15143 *host_mem_add = (uint32 *)soc_cm_p2l(unit, host_addr); 15144 15145 return BCM_E_NONE; 15146 } 15147 15148 STATIC 15149 void bcm_th_cosq_burst_linked_list_clean(int unit, qcm_gport_port_queue_map_t *head) 15150 { 15151 qcm_gport_port_queue_map_t *temp, *newnode; 15152 temp = head; 15153 while(temp) { 15154 newnode = temp; 15155 temp = temp->next; 15156 soc_cm_sfree(unit, newnode); 15157 } 15158 } 15159 15160 15161 int bcm_th_cosq_burst_monitor_set(int unit, int num_gports, 15162 bcm_gport_t *gport_list) 15163 { 15164 uint32 qcm_app_status[2], qcm_host_status, qcm_uc_status; 15165 qcm_gport_port_queue_map_t *head, *newnode, *temp; 15166 int phy_port, pipe, mmu_port, local_mmu_port, i, index, time_count, rv = BCM_E_NONE; 15167 _bcm_th_cosq_node_t *node; 15168 bcm_port_t local_port; 15169 soc_info_t *si; 15170 15171 qcm_app_status[0] = soc_uc_mem_read(unit, (SRAM_BASEADDR(unit) + sram_offset(app_status))); 15172 qcm_app_status[1] = soc_uc_mem_read(unit, (SRAM_BASEADDR(unit) + sram_offset(app_status) + 4)); 15173 15174 /* Validation check whether core 0 R5 is loaded with QCM app srec file 15175 * ASCII of word QCM_(SHR_QCM_APP_STATUS_1) and _APP(SHR_QCM_APP_STATUS_2) 15176 */ 15177 if ((qcm_app_status[0] != SHR_QCM_APP_STATUS_1) || 15178 (qcm_app_status[1] != SHR_QCM_APP_STATUS_2)) { 15179 LOG_ERROR(BSL_LS_BCM_COSQ, (BSL_META_U(unit, 15180 "load QCM app srec file to core 0\n"))); 15181 return BCM_E_UNAVAIL; 15182 } 15183 15184 qcm_host_status = soc_uc_mem_read(unit, (SRAM_BASEADDR(unit) + sram_offset(host_status))); 15185 if (!(qcm_host_status & SHR_QCM_INIT_STATUS_BIT)) { 15186 LOG_ERROR(BSL_LS_BCM_COSQ, (BSL_META_U(unit, 15187 "set shared memory\n"))); 15188 return BCM_E_INIT; 15189 } 15190 15191 if (gport_list == NULL) { 15192 LOG_ERROR(BSL_LS_BCM_COSQ, (BSL_META_U(unit, 15193 "gport parameter NULL\n"))); 15194 return BCM_E_PARAM; 15195 } 15196 15197 if (num_gports > SHR_QCM_MAX_GPORT_MONITOR) { 15198 LOG_ERROR(BSL_LS_BCM_COSQ, (BSL_META_U(unit, 15199 "Maximum number of entries :%d\n"), 15200 SHR_QCM_MAX_GPORT_MONITOR)); 15201 return BCM_E_PARAM; 15202 } 15203 15204 head = (qcm_gport_port_queue_map_t *)0; 15205 qcm_host_status = qcm_host_status ^ SHR_QCM_CONFIG_STATUS_BIT; 15206 si = &SOC_INFO(unit); 15207 15208 for (i = 0; i < num_gports; i++) { 15209 if (!(BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport_list[i]))) { 15210 bcm_th_cosq_burst_linked_list_clean(unit, head); 15211 LOG_ERROR(BSL_LS_BCM_COSQ, (BSL_META_U(unit, 15212 "%x gport is non unicast queue type" 15213 "Only uincast type gport are alone monitored\n"), 15214 gport_list[i])); 15215 return BCM_E_PARAM; 15216 } 15217 newnode = (qcm_gport_port_queue_map_t *) soc_cm_salloc(unit, 15218 sizeof(struct qcm_gport_port_queue_map_s), 15219 "microburst temp linked list"); 15220 15221 if (newnode == NULL) { 15222 bcm_th_cosq_burst_linked_list_clean(unit, head); 15223 LOG_ERROR(BSL_LS_BCM_COSQ, (BSL_META_U(unit, 15224 "Failed to create local memory\n"))); 15225 return BCM_E_MEMORY; 15226 } 15227 sal_memset(newnode, 0, sizeof(struct qcm_gport_port_queue_map_s)); 15228 newnode->next=(qcm_gport_port_queue_map_t *)0; 15229 15230 rv = _bcm_th_cosq_node_get(unit, gport_list[i], NULL, &local_port, 15231 NULL, &node); 15232 15233 if ((BCM_E_NONE != rv) || (local_port < 0)) { 15234 bcm_th_cosq_burst_linked_list_clean(unit, head); 15235 LOG_ERROR(BSL_LS_BCM_COSQ, (BSL_META_U(unit, 15236 "gport %x with wrong local port value\n"), 15237 gport_list[i])); 15238 return rv; 15239 } 15240 15241 rv = soc_port_pipe_get(unit, local_port, &pipe); 15242 if (BCM_E_NONE != rv) { 15243 bcm_th_cosq_burst_linked_list_clean(unit, head); 15244 LOG_ERROR(BSL_LS_BCM_COSQ, (BSL_META_U(unit, 15245 "gport %x with wrong pipe\n"), 15246 gport_list[i])); 15247 return rv; 15248 } 15249 15250 newnode->queue_num = node->hw_index % _BCM_TH_NUM_UCAST_QUEUE_PER_PORT; 15251 if (newnode->queue_num >= _BCM_TH_NUM_UCAST_QUEUE_PER_PORT) { 15252 bcm_th_cosq_burst_linked_list_clean(unit, head); 15253 LOG_ERROR(BSL_LS_BCM_COSQ, (BSL_META_U(unit, 15254 "gport %x with wrong queue number\n"), 15255 gport_list[i])); 15256 return BCM_E_PORT; 15257 } 15258 phy_port = si->port_l2p_mapping[local_port]; 15259 mmu_port = si->port_p2m_mapping[phy_port]; 15260 local_mmu_port = mmu_port & (SOC_TH_MMU_PORT_STRIDE - 1); 15261 newnode->pipe_num = pipe; 15262 newnode->gport = gport_list[i]; 15263 newnode->port_num = local_mmu_port; 15264 newnode->global_num = (newnode->pipe_num * SOC_TH_MMU_GP_UCQ_NUM) + 15265 (local_mmu_port * _BCM_TH_NUM_UCAST_QUEUE_PER_PORT) + 15266 newnode->queue_num; 15267 15268 if (head == NULL || (head)->global_num >= newnode->global_num) { 15269 newnode->next = head; 15270 head = newnode; 15271 } else { 15272 temp = head; 15273 while ((temp->next != NULL) && 15274 (temp->next->global_num < newnode->global_num)) { 15275 temp = temp->next; 15276 } 15277 newnode->next = temp->next; 15278 temp->next = newnode; 15279 } 15280 } 15281 15282 soc_uc_mem_write(unit, (SRAM_BASEADDR(unit) + sram_offset(total_num_gports)), (uint32)num_gports); 15283 temp = head; 15284 index = 0; 15285 while(temp) { 15286 uint32 port_pipe_queue_num = (((temp->port_num & 0xFFFF) << 16) | 15287 ((temp->pipe_num & 0xF) << 12) | 15288 (temp->queue_num & 0xFFF)); 15289 soc_uc_mem_write(unit, (SRAM_BASEADDR(unit) + sram_offset(port_pipe_queue) + (index * 4)), (uint32)temp->gport); 15290 soc_uc_mem_write(unit, (SRAM_BASEADDR(unit) + sram_offset(port_pipe_queue) + ((index + 1) * 4)), (uint32)port_pipe_queue_num); 15291 newnode = temp; 15292 temp = temp->next; 15293 soc_cm_sfree(unit, newnode); 15294 index = index + 2; 15295 } 15296 soc_uc_mem_write(unit, (SRAM_BASEADDR(unit) + sram_offset(host_status)), (uint32)qcm_host_status); 15297 qcm_host_status = qcm_host_status & SHR_QCM_CONFIG_STATUS_BIT; 15298 15299 time_count = 0; 15300 while (1) { 15301 qcm_uc_status = soc_uc_mem_read(unit, (SRAM_BASEADDR(unit) + sram_offset(uc_status))); 15302 qcm_uc_status = qcm_uc_status & SHR_QCM_CONFIG_STATUS_BIT; 15303 if (qcm_host_status == qcm_uc_status) { 15304 break; 15305 } 15306 ++time_count; 15307 if ((time_count * QCM_UC_STATUS_TIMEOUT) > QCM_UC_MSG_TIMEOUT) { 15308 LOG_ERROR(BSL_LS_BCM_COSQ, (BSL_META_U(unit, 15309 "QCM app R5 core 0 does not responded\n"))); 15310 return BCM_E_TIMEOUT; 15311 } 15312 sal_usleep(QCM_UC_STATUS_TIMEOUT); 15313 } 15314 qcm_uc_status = soc_uc_mem_read(unit, (SRAM_BASEADDR(unit) + sram_offset(uc_status))); 15315 15316 return (qcm_uc_status >> SHR_QCM_INIT_STATUS_BIT); 15317 } 15318 15319 int bcm_th_cosq_burst_monitor_get(int unit, int max_gports, 15320 bcm_gport_t *gport_list, int *num_gports) 15321 { 15322 uint32 qcm_app_status[2], qcm_host_status, i, entries_transfer; 15323 15324 qcm_app_status[0] = soc_uc_mem_read(unit, (SRAM_BASEADDR(unit) + sram_offset(app_status))); 15325 qcm_app_status[1] = soc_uc_mem_read(unit, (SRAM_BASEADDR(unit) + sram_offset(app_status) + 4)); 15326 15327 /* Validation check whether core 0 R5 is loaded with QCM app srec file 15328 * ASCII of word QCM_(SHR_QCM_APP_STATUS_1) and _APP(SHR_QCM_APP_STATUS_2) 15329 */ 15330 if ((qcm_app_status[0] != SHR_QCM_APP_STATUS_1) || 15331 (qcm_app_status[1] != SHR_QCM_APP_STATUS_2)) { 15332 LOG_ERROR(BSL_LS_BCM_COSQ, (BSL_META_U(unit, 15333 "load QCM app srec file to core 0\n"))); 15334 return BCM_E_UNAVAIL; 15335 } 15336 15337 qcm_host_status = soc_uc_mem_read(unit, (SRAM_BASEADDR(unit) + sram_offset(host_status))); 15338 if (!(qcm_host_status & SHR_QCM_INIT_STATUS_BIT)) { 15339 LOG_ERROR(BSL_LS_BCM_COSQ, (BSL_META_U(unit, 15340 "set shared memory\n"))); 15341 return BCM_E_INIT; 15342 } 15343 15344 if (gport_list == NULL) { 15345 LOG_ERROR(BSL_LS_BCM_COSQ, (BSL_META_U(unit, 15346 "gport parameter NULL\n"))); 15347 return BCM_E_PARAM; 15348 } 15349 15350 *num_gports = soc_uc_mem_read(unit, (SRAM_BASEADDR(unit) + (sram_offset(total_num_gports)))); 15351 15352 if (!max_gports) { 15353 return BCM_E_NONE; 15354 } else if (*num_gports > max_gports) { 15355 entries_transfer = max_gports; 15356 } else { 15357 entries_transfer = *num_gports; 15358 } 15359 15360 sal_memset(gport_list, 0, (sizeof(bcm_gport_t) * max_gports)); 15361 15362 for (i = 0; i < entries_transfer; i++) { 15363 gport_list[i] = soc_uc_mem_read(unit, (SRAM_BASEADDR(unit) + (sram_offset(port_pipe_queue)) + (i * 2 * 4))); 15364 } 15365 15366 return BCM_E_NONE; 15367 15368 } 15369 #endif /* BCM_TOMAHAWK_SUPPORT */