cosq.c (493967B)
1 2 /* 3 * 4 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 5 * 6 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 7 * 8 * COS Queue Management 9 * Purpose: API to set different cosq, priorities, and scheduler registers. 10 */ 11 12 #include <shared/bsl.h> 13 14 #include <soc/defs.h> 15 #include <sal/core/libc.h> 16 17 #if defined(BCM_TRIDENT3_SUPPORT) 18 #include <soc/drv.h> 19 #include <soc/scache.h> 20 #include <soc/profile_mem.h> 21 #include <soc/debug.h> 22 #include <soc/helix5.h> 23 24 #include <bcm/debug.h> 25 #include <bcm/error.h> 26 #include <bcm/cosq.h> 27 #include <bcm_int/esw/mbcm.h> 28 #include <bcm_int/esw/stack.h> 29 #include <bcm_int/esw/cosq.h> 30 #include <bcm_int/esw/virtual.h> 31 #include <bcm_int/esw/helix5.h> 32 #include <bcm_int/esw/trident.h> 33 #include <bcm_int/esw_dispatch.h> 34 #include <bcm_int/esw/ecn.h> 35 #include <bcm_int/bst.h> 36 #include <bcm_int/esw/pfc_deadlock.h> 37 38 #if defined(INCLUDE_PSTATS) 39 #include <bcm_int/esw/pstats.h> 40 #endif /* INCLUDE_PSTATS */ 41 42 43 #if defined (INCLUDE_TCB) && defined (BCM_TCB_SUPPORT) 44 #include <bcm_int/esw/tcb.h> 45 #endif 46 47 #if defined(BCM_TOMAHAWK2_SUPPORT) 48 #include <bcm_int/esw/tomahawk2.h> 49 #include <soc/tomahawk2.h> 50 #endif 51 #ifdef BCM_WARM_BOOT_SUPPORT 52 #include <bcm_int/esw/switch.h> 53 #endif /* BCM_WARM_BOOT_SUPPORT */ 54 55 /* COS default value for HX5 is assumed to be 8 */ 56 #define _BCM_HX5_COS_DEFAULT 8 57 #define _HX5_NUM_COS_MAP_ENTRY 16 58 #define _HX5_WIRELESS_COS_MAP_BASE 64 59 /* Number of Class of Service Supported */ 60 #define _BCM_HX5_NUM_COS(unit) NUM_COS(unit) 61 62 #define HX5_WRED_CELL_FIELD_MAX 0x3ffff 63 #define HX5_WRED_PROFILE_NUM 9 64 65 /* Number of logical Ports */ 66 #define _BCM_HX5_NUM_PORTS 72 67 /* Number of HG/stacking/uplink Ports */ 68 #define _BCM_HX5_NUM_ST_PORTS 16 69 70 /* HX5 supports 8 PFC priorities */ 71 #define _BCM_HX5_NUM_PFC_CLASS 8 72 73 /* Base l3 queue number for down link port */ 74 #define _HX5_BASE_L3QUEUE 416 75 /* Base l2 queue number for down link port */ 76 #define _HX5_BASE_L2QUEUE 416 77 /* Base l1 queue number for down link port */ 78 #define _HX5_BASE_L1QUEUE 64 79 /* Base l0 queue number for down link port */ 80 #define _HX5_BASE_L0QUEUE 48 81 82 #define _HX5_ST_NUML0_NODES 3 83 #define _HX5_ST_NUML1_NODES 4 84 #define _HX5_ST_NUML2_NODES 26 85 86 #define _HX5_NUML0_NODES 1 87 #define _HX5_NUML1_NODES 2 88 #define _HX5_NUML2_NODES 16 89 90 #define _HX5_CPU_LO_NODE_BASE 103 91 #define _HX5_CPU_L1_NODE_BASE 173 92 #define _HX5_CPU_L2_NODE_BASE 1290 93 94 #define _HX5_CPU_NUML0_NODES 1 95 #define _HX5_CPU_NUML1_NODES 1 96 #define _HX5_CPU_NUML2_NODES 10 97 98 #define _BCM_HX5_NUM_SAFC_CLASS 16 99 100 /* Number of COSQs configured for this unit */ 101 #define BCM_HX5_NUM_COS(unit) NUM_COS(unit) 102 103 #define _HX5_IS_ST_PORT(unit, mmu_port) \ 104 ((mmu_port < 16) ? 1 : 0) 105 106 107 108 #define _HX5_PORT_INDEX_GET(unit, mmu_port, index) \ 109 do { \ 110 if (_HX5_IS_ST_PORT(unit, mmu_port)) { \ 111 index = mmu_port; \ 112 } else { \ 113 index = mmu_port - _BCM_HX5_NUM_ST_PORTS; \ 114 } \ 115 } while (0) 116 117 118 119 #define _HX5_PORT_NUM_COS(unit, port) \ 120 ((IS_CPU_PORT(unit, port)) ? NUM_CPU_COSQ(unit) : \ 121 (IS_LB_PORT(unit, port)) ? 10 : BCM_HX5_NUM_COS(unit)) 122 123 #define _BCM_HX5_NUM_TIME_DOMAIN 4 124 125 /* Here cosq is < SOC_HX5_NUM_SCHEDULER_PER_ST_PORT */ 126 #define HX5_ST_SCHED_LEVEL_GET(unit, cosq) \ 127 ((cosq < 3) ? SOC_HX5_NODE_LVL_L0 : (cosq >= 3 && cosq < 7) ? SOC_HX5_NODE_LVL_L1 : SOC_HX5_NODE_LVL_L2) 128 129 /* Here cosq is < SOC_HX5_NUM_SCHEDULER_PER_PORT */ 130 #define HX5_SCHED_LEVEL_GET(unit, cosq) \ 131 ((cosq < 1) ? SOC_HX5_NODE_LVL_L0 : (cosq >= 1 && cosq < 3) ? SOC_HX5_NODE_LVL_L1 : SOC_HX5_NODE_LVL_L2) 132 133 #define HX5_CPU_SCHED_LEVEL_GET(unit, cosq) \ 134 ((cosq < 1) ? SOC_HX5_NODE_LVL_L0 : (cosq == 1) ? SOC_HX5_NODE_LVL_L1 : SOC_HX5_NODE_LVL_L2) 135 136 #define _BCM_HX5_NUM_TIME_DOMAIN 4 137 138 typedef struct _bcm_hx5_cosq_time_info_s { 139 uint32 ref_count; 140 } _bcm_hx5_cosq_time_info_t; 141 142 STATIC _bcm_hx5_cosq_time_info_t hx5_time_domain_info[BCM_MAX_NUM_UNITS][_BCM_HX5_NUM_TIME_DOMAIN]; 143 /* WRED resolution table */ 144 #define _BCM_HX5_NUM_WRED_RESOLUTION_TABLE 4 145 STATIC uint32 _bcm_hx5_wred_resolution_tbl[_BCM_HX5_NUM_WRED_RESOLUTION_TABLE] = { 146 1, 147 0, 148 0, 149 0, 150 }; 151 152 153 typedef struct _bcm_hx5_cosq_cpu_cosq_config_s { 154 /* All MC queues have DB[idx 0] and MCQE[idx 1] space */ 155 int q_min_limit[2]; 156 int q_shared_limit[2]; 157 uint8 q_limit_dynamic[2]; 158 uint8 q_limit_enable[2]; 159 uint8 q_color_limit_enable[2]; 160 uint8 enable; 161 } _bcm_hx5_cosq_cpu_cosq_config_t; 162 163 typedef struct _bcm_hx5_cosq_node_s { 164 bcm_gport_t gport; 165 int numq; 166 int level; 167 int hw_index; 168 int in_use; 169 bcm_gport_t parent_gport; 170 } _bcm_hx5_cosq_node_t; 171 172 173 typedef struct _bcm_hx5_cosq_st_port_info_s { 174 _bcm_hx5_cosq_node_t ucast[SOC_HX5_NUM_UCAST_QUEUE_PER_ST_PORT]; 175 _bcm_hx5_cosq_node_t mcast[SOC_HX5_NUM_MCAST_QUEUE_PER_ST_PORT]; 176 _bcm_hx5_cosq_node_t sched[SOC_HX5_NUM_SCHEDULER_PER_ST_PORT]; 177 } _bcm_hx5_cosq_st_port_info_t; 178 179 typedef struct _bcm_hx5_cosq_port_info_s { 180 _bcm_hx5_cosq_node_t ucast[SOC_HX5_NUM_UCAST_QUEUE_PER_PORT]; 181 _bcm_hx5_cosq_node_t mcast[SOC_HX5_NUM_MCAST_QUEUE_PER_PORT]; 182 _bcm_hx5_cosq_node_t sched[SOC_HX5_NUM_SCHEDULER_PER_PORT]; 183 } _bcm_hx5_cosq_port_info_t; 184 185 typedef struct _bcm_hx5_cosq_cpu_port_info_s { 186 _bcm_hx5_cosq_node_t sched[SOC_HX5_NUM_SCHEDULER_PER_CPU_PORT]; 187 _bcm_hx5_cosq_node_t mcast[SOC_HX5_NUM_CPU_QUEUES]; 188 } _bcm_hx5_cosq_cpu_port_info_t; 189 190 typedef struct _bcm_hx5_mmu_info_s { 191 _bcm_hx5_cosq_port_info_t *_bcm_hx5_port_info; 192 _bcm_hx5_cosq_cpu_port_info_t *_bcm_hx5_cpu_port_info; 193 _bcm_hx5_cosq_st_port_info_t *_bcm_hx5_st_port_info; 194 int gport_tree_created; /* FALSE: No GPORT tree exists */ 195 } _bcm_hx5_mmu_info_t; 196 197 STATIC _bcm_hx5_mmu_info_t *_bcm_hx5_mmu_info[BCM_MAX_NUM_UNITS]; /* MMU info */ 198 STATIC _bcm_hx5_cosq_port_info_t *_bcm_hx5_cosq_port_info[BCM_MAX_NUM_UNITS]; 199 STATIC _bcm_hx5_cosq_st_port_info_t *_bcm_hx5_cosq_st_port_info[BCM_MAX_NUM_UNITS]; 200 STATIC _bcm_hx5_cosq_cpu_port_info_t *_bcm_hx5_cosq_cpu_port_info[BCM_MAX_NUM_UNITS]; 201 STATIC _bcm_hx5_cosq_cpu_cosq_config_t 202 *_bcm_hx5_cosq_cpu_cosq_config[BCM_MAX_NUM_UNITS][SOC_HX5_NUM_CPU_QUEUES]; 203 204 STATIC soc_profile_mem_t *_bcm_hx5_ifp_cos_map_profile[BCM_MAX_NUM_UNITS]; 205 206 typedef enum { 207 _BCM_HX5_COSQ_TYPE_UCAST, 208 _BCM_HX5_COSQ_TYPE_MCAST 209 } _bcm_hx5_cosq_type_t; 210 211 /* Memory Profiles */ 212 STATIC soc_profile_mem_t *_bcm_hx5_cos_map_profile[BCM_MAX_NUM_UNITS]; 213 STATIC soc_profile_mem_t *_bcm_hx5_wred_profile[BCM_MAX_NUM_UNITS]; 214 STATIC soc_profile_reg_t *_bcm_hx5_prio2cos_profile[BCM_MAX_NUM_UNITS]; 215 216 #define _BCM_HX5_MMU_INFO(unit) _bcm_hx5_mmu_info[(unit)] 217 218 #define _BCM_HX5_CPU_COS_MAPS_RSVD 9 219 #define _BCM_HX5_INT_PRI_8_15_MASK 0x8 220 #define _BCM_HX5_INT_PRI_0_7_MASK 0xf 221 222 /* 223 * index: degree, value: contangent(degree) * 100 224 * max value is 0xffff (16-bit) at 0 degree 225 * Same as TD2. 226 */ 227 STATIC int 228 _bcm_hx5_cotangent_lookup_table[] = 229 { 230 /* 0.. 5 */ 65535, 5728, 2863, 1908, 1430, 1143, 231 /* 6..11 */ 951, 814, 711, 631, 567, 514, 232 /* 12..17 */ 470, 433, 401, 373, 348, 327, 233 /* 18..23 */ 307, 290, 274, 260, 247, 235, 234 /* 24..29 */ 224, 214, 205, 196, 188, 180, 235 /* 30..35 */ 173, 166, 160, 153, 148, 142, 236 /* 36..41 */ 137, 132, 127, 123, 119, 115, 237 /* 42..47 */ 111, 107, 103, 100, 96, 93, 238 /* 48..53 */ 90, 86, 83, 80, 78, 75, 239 /* 54..59 */ 72, 70, 67, 64, 62, 60, 240 /* 60..65 */ 57, 55, 53, 50, 48, 46, 241 /* 66..71 */ 44, 42, 40, 38, 36, 34, 242 /* 72..77 */ 32, 30, 28, 26, 24, 23, 243 /* 78..83 */ 21, 19, 17, 15, 14, 12, 244 /* 84..89 */ 10, 8, 6, 5, 3, 1, 245 /* 90 */ 0 246 }; 247 248 /* 249 * Function: 250 * _bcm_hx5_ecn_init 251 * Purpose: 252 * Initialize (clear) all ECN memories/registers 253 * Parameters: 254 * unit - unit number 255 * Returns: 256 * BCM_E_XXX 257 */ 258 STATIC int 259 _bcm_hx5_ecn_init(int unit) 260 { 261 egr_tunnel_ecn_encap_entry_t egr_tunnel_ecn_encap; 262 int count, i; 263 uint32 fld_val; 264 265 BCM_IF_ERROR_RETURN(_bcm_esw_ecn_init(unit)); 266 267 if (!SOC_WARM_BOOT(unit)) { 268 count = soc_mem_index_count(unit, EGR_TUNNEL_ECN_ENCAPm); 269 for (i = 0; i < count; i++) { 270 sal_memset(&egr_tunnel_ecn_encap, 0, sizeof(egr_tunnel_ecn_encap)); 271 switch (i%4) { 272 case 0: 273 fld_val = _BCM_ECN_INT_CN_RESPONSIVE_DROP; 274 break; 275 case 1: 276 fld_val = _BCM_ECN_INT_CN_NON_RESPONSIVE_DROP; 277 break; 278 case 2: 279 fld_val = _BCM_ECN_INT_CN_NON_CONGESTION_MARK_ECN; 280 break; 281 case 3: 282 fld_val = _BCM_ECN_INT_CN_CONGESTION_MARK_ECN; 283 break; 284 /* 285 * COVERITY 286 * 287 *This default is unreachable. It is kept intentionally 288 *as a defensive default for future development. 289 */ 290 /* coverity[dead_error_begin] */ 291 default: 292 fld_val = _BCM_ECN_INT_CN_NON_CONGESTION_MARK_ECN; 293 break; 294 } 295 soc_mem_field32_set(unit, EGR_TUNNEL_ECN_ENCAPm, 296 &egr_tunnel_ecn_encap, OUTER_ECNf, fld_val); 297 SOC_IF_ERROR_RETURN 298 (soc_mem_write(unit, EGR_TUNNEL_ECN_ENCAPm, MEM_BLOCK_ALL, 299 i, (void *)&egr_tunnel_ecn_encap)); 300 } 301 } 302 return BCM_E_NONE; 303 } 304 /* 305 * Given a slope (angle in degrees) from 0 to 90, return the number of cells 306 * in the range from 0% drop probability to 100% drop probability. 307 * Same as TD2. 308 */ 309 STATIC int 310 _bcm_hx5_angle_to_cells(int angle) 311 { 312 return (_bcm_hx5_cotangent_lookup_table[angle]); 313 } 314 315 /* 316 * Given a number of packets in the range from 0% drop probability 317 * to 100% drop probability, return the slope (angle in degrees). 318 * Same as TD2. 319 */ 320 STATIC int 321 _bcm_hx5_cells_to_angle(int packets) 322 { 323 int angle; 324 325 for (angle = 90; angle >= 0 ; angle--) { 326 if (packets <= _bcm_hx5_cotangent_lookup_table[angle]) { 327 break; 328 } 329 } 330 return angle; 331 } 332 333 334 /* 335 * Convert HW drop probability to percent value 336 * Same as TD2. 337 */ 338 STATIC int 339 _bcm_hx5_hw_drop_prob_to_percent[] = { 340 0, /* 0 */ 341 1, /* 1 */ 342 2, /* 2 */ 343 3, /* 3 */ 344 4, /* 4 */ 345 5, /* 5 */ 346 6, /* 6 */ 347 7, /* 7 */ 348 8, /* 8 */ 349 9, /* 9 */ 350 10, /* 10 */ 351 25, /* 11 */ 352 50, /* 12 */ 353 75, /* 13 */ 354 100, /* 14 */ 355 -1 /* 15 */ 356 }; 357 358 STATIC int 359 _bcm_hx5_percent_to_drop_prob(int percent) 360 { 361 int i; 362 363 for (i = 14; i > 0 ; i--) { 364 if (percent >= _bcm_hx5_hw_drop_prob_to_percent[i]) { 365 break; 366 } 367 } 368 return i; 369 } 370 371 STATIC int 372 _bcm_hx5_drop_prob_to_percent(int drop_prob) { 373 return (_bcm_hx5_hw_drop_prob_to_percent[drop_prob]); 374 } 375 376 377 STATIC int 378 _bcm_hx5_cosq_bucket_set(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 379 uint32 min_quantum, uint32 max_quantum, 380 uint32 kbits_burst_min, uint32 kbits_burst_max, 381 uint32 flags); 382 STATIC int 383 _bcm_hx5_cosq_bucket_get(int unit, bcm_port_t gport, bcm_cos_queue_t cosq, 384 uint32 *min_quantum, uint32 *max_quantum, 385 uint32 *kbits_burst_min, uint32 *kbits_burst_max, 386 uint32 *flags); 387 388 389 /* 390 * Function: 391 * _bcm_hx5_cosq_node_get 392 * Purpose: 393 * Get internal information of queue group or scheduler type GPORT 394 * Parameters: 395 * unit - (IN) unit number 396 * gport - (IN) queue group/scheduler GPORT identifier 397 * modid - (OUT) module identifier 398 * port - (OUT) port number 399 * id - (OUT) queue group or scheduler identifier 400 * node - (OUT) node structure for the specified GPORT 401 * Returns: 402 * BCM_E_XXX 403 */ 404 int 405 _bcm_hx5_cosq_node_get(int unit, bcm_gport_t gport, bcm_module_t *modid, 406 bcm_port_t *port, int *id, _bcm_hx5_cosq_node_t **node) 407 { 408 _bcm_hx5_cosq_port_info_t *port_info = NULL; 409 _bcm_hx5_cosq_st_port_info_t *stport_info = NULL; 410 _bcm_hx5_cosq_cpu_port_info_t *cpu_port_info = NULL; 411 _bcm_hx5_cosq_node_t *node_base = NULL; 412 bcm_module_t modid_out; 413 bcm_port_t port_out; 414 int index, port_index; 415 int num_sched_port = 0; 416 int phy_port, mmu_port; 417 soc_info_t *si = &SOC_INFO(unit); 418 419 if (_bcm_hx5_cosq_port_info[unit] == NULL) { 420 return BCM_E_INIT; 421 } 422 423 if (_bcm_hx5_cosq_st_port_info[unit] == NULL) { 424 return BCM_E_INIT; 425 } 426 427 if (_bcm_hx5_cosq_cpu_port_info[unit] == NULL) { 428 return BCM_E_INIT; 429 } 430 431 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid_out)); 432 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 433 port_out = BCM_GPORT_UCAST_QUEUE_GROUP_SYSPORTID_GET(gport); 434 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 435 port_out = BCM_GPORT_MCAST_QUEUE_GROUP_SYSPORTID_GET(gport); 436 } else if (BCM_GPORT_IS_SCHEDULER(gport)) { 437 port_out = BCM_GPORT_SCHEDULER_GET(gport) & 0xff; 438 } else { 439 return BCM_E_PORT; 440 } 441 442 if (!SOC_PORT_VALID(unit, port_out) || IS_LB_PORT(unit, port_out) ) { 443 return BCM_E_PORT; 444 } 445 446 phy_port = si->port_l2p_mapping[port_out]; 447 mmu_port = si->port_p2m_mapping[phy_port]; 448 _HX5_PORT_INDEX_GET(unit, mmu_port, port_index); 449 450 if (IS_CPU_PORT(unit, port_out)) { 451 cpu_port_info = _bcm_hx5_cosq_cpu_port_info[unit]; 452 num_sched_port = SOC_HX5_NUM_SCHEDULER_PER_CPU_PORT; 453 } else if(_HX5_IS_ST_PORT(unit, mmu_port)){ 454 stport_info = &_bcm_hx5_cosq_st_port_info[unit][port_index]; 455 num_sched_port = SOC_HX5_NUM_SCHEDULER_PER_ST_PORT; 456 } else { 457 port_info = &_bcm_hx5_cosq_port_info[unit][port_index]; 458 num_sched_port = SOC_HX5_NUM_SCHEDULER_PER_PORT; 459 } 460 461 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 462 index = BCM_GPORT_UCAST_QUEUE_GROUP_QID_GET(gport); 463 node_base = (_HX5_IS_ST_PORT(unit, mmu_port)) ? stport_info->ucast : port_info->ucast; 464 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 465 index = BCM_GPORT_MCAST_QUEUE_GROUP_QID_GET(gport); 466 if (IS_CPU_PORT(unit, port_out)) { 467 node_base = cpu_port_info->mcast; 468 } else { 469 node_base = (_HX5_IS_ST_PORT(unit, mmu_port)) ? stport_info->mcast : port_info->mcast; 470 } 471 } else { 472 index = (BCM_GPORT_SCHEDULER_GET(gport) >> 16) & 0x3ff; 473 if (index >= num_sched_port) { 474 return BCM_E_PORT; 475 } 476 if (IS_CPU_PORT(unit, port_out)) { 477 node_base = cpu_port_info->sched; 478 } else { 479 node_base = (_HX5_IS_ST_PORT(unit, mmu_port)) ? stport_info->sched : port_info->sched; 480 } 481 } 482 483 if ((node_base == NULL) || 484 (node_base[index].numq == 0) || 485 (node_base[index].in_use == 0)) { 486 return BCM_E_NOT_FOUND; 487 } 488 489 if (modid != NULL) { 490 *modid = modid_out; 491 } 492 if (port != NULL) { 493 *port = port_out; 494 } 495 if (id != NULL) { 496 *id = index; 497 } 498 if (node != NULL) { 499 *node = &node_base[index]; 500 } 501 502 return BCM_E_NONE; 503 504 } 505 506 507 /* 508 * Function: 509 * _bcm_hx5_cosq_port_resolve 510 * Purpose: 511 * Resolve following COS queue related GPORT 512 * BCM_GPORT_TYPE_UCAST_QUEUE_GROUP 513 * BCM_GPORT_TYPE_MCAST_QUEUE_GROUP 514 * BCM_GPORT_TYPE SCHEDULER 515 * Parameters: 516 * unit - (IN) unit number 517 * gport - (IN) GPORT identifier 518 * modid - (OUT) module identifier 519 * port - (OUT) port number 520 * trunk_id - (OUT) trunk identifier 521 * id - (OUT) queue group or scheduler identifier 522 * qnum - (OUT) hw_index for given queue gport 523 * Returns: 524 * BCM_E_XXX 525 */ 526 int 527 _bcm_hx5_cosq_port_resolve(int unit, bcm_gport_t gport, bcm_module_t *modid, 528 bcm_port_t *port, bcm_trunk_t *trunk_id, int *id, 529 int *qnum) 530 { 531 _bcm_hx5_cosq_node_t *node; 532 533 BCM_IF_ERROR_RETURN 534 (_bcm_hx5_cosq_node_get(unit, gport, modid, port, id, &node)); 535 *trunk_id = -1; 536 537 if (qnum) { 538 if (node->hw_index == -1) { 539 return BCM_E_PARAM; 540 } 541 *qnum = node->hw_index; 542 } 543 544 return BCM_E_NONE; 545 } 546 547 /* 548 * Function: 549 * _bcm_hx5_cosq_localport_resolve 550 * Purpose: 551 * Resolve GPORT if it is a local port 552 * Parameters: 553 * unit - (IN) unit number 554 * gport - (IN) GPORT identifier 555 * local_port - (OUT) local port number 556 * Returns: 557 * BCM_E_XXX 558 */ 559 STATIC int 560 _bcm_hx5_cosq_localport_resolve(int unit, bcm_gport_t gport, 561 bcm_port_t *local_port) 562 { 563 bcm_module_t module; 564 bcm_port_t port; 565 bcm_trunk_t trunk; 566 int id, result, rv; 567 568 if (!BCM_GPORT_IS_SET(gport)) { 569 if (!SOC_PORT_VALID(unit, gport)) { 570 return BCM_E_PORT; 571 } 572 *local_port = gport; 573 return BCM_E_NONE; 574 } 575 576 rv = _bcm_esw_gport_resolve(unit, gport, &module, &port, &trunk, &id); 577 if (rv == BCM_E_PORT) { 578 /* returning E_PARAM when invalid gport is given as param */ 579 return BCM_E_PARAM; 580 } else if (BCM_FAILURE(rv)) { 581 return rv; 582 } 583 584 BCM_IF_ERROR_RETURN 585 (_bcm_esw_modid_is_local(unit, module, &result)); 586 if (result == FALSE) { 587 return BCM_E_PARAM; 588 } 589 590 *local_port = port; 591 592 return BCM_E_NONE; 593 } 594 595 596 /* 597 * Function: 598 * _bcm_hx5_cosq_cleanup 599 * Purpose: 600 * Clean resource in case of error during Cosq Init 601 * Parameters: 602 * unit - (IN) unit number 603 * Returns: 604 * No return value 605 */ 606 STATIC void 607 _bcm_hx5_cosq_cleanup(int unit) 608 { 609 if (_bcm_hx5_cosq_port_info[unit] != NULL) { 610 sal_free(_bcm_hx5_cosq_port_info[unit]); 611 _bcm_hx5_cosq_port_info[unit] = NULL; 612 } 613 614 if (_bcm_hx5_cosq_st_port_info[unit] != NULL) { 615 sal_free(_bcm_hx5_cosq_st_port_info[unit]); 616 _bcm_hx5_cosq_st_port_info[unit] = NULL; 617 } 618 619 if (_bcm_hx5_cosq_cpu_port_info[unit] != NULL) { 620 sal_free(_bcm_hx5_cosq_cpu_port_info[unit]); 621 _bcm_hx5_cosq_cpu_port_info[unit] = NULL; 622 } 623 624 if (_bcm_hx5_mmu_info[unit] != NULL) { 625 sal_free(_bcm_hx5_mmu_info[unit]); 626 _bcm_hx5_mmu_info[unit] = NULL; 627 } 628 629 if (_bcm_hx5_wred_profile[unit] != NULL) { 630 (void)soc_profile_mem_destroy(unit, _bcm_hx5_wred_profile[unit]); 631 sal_free(_bcm_hx5_wred_profile[unit]); 632 _bcm_hx5_wred_profile[unit] = NULL; 633 } 634 635 /* Cleanup profile for PRIO2COS_PROFILE register */ 636 if (_bcm_hx5_prio2cos_profile[unit] != NULL) { 637 (void)soc_profile_reg_destroy(unit, _bcm_hx5_prio2cos_profile[unit]); 638 sal_free(_bcm_hx5_prio2cos_profile[unit]); 639 _bcm_hx5_prio2cos_profile[unit] = NULL; 640 } 641 642 if (_bcm_hx5_ifp_cos_map_profile[unit] != NULL) { 643 (void)soc_profile_mem_destroy(unit, _bcm_hx5_ifp_cos_map_profile[unit]); 644 sal_free(_bcm_hx5_ifp_cos_map_profile[unit]); 645 _bcm_hx5_ifp_cos_map_profile[unit] = NULL; 646 } 647 #if defined (INCLUDE_TCB) && defined (BCM_TCB_SUPPORT) 648 if (soc_feature(unit, soc_feature_tcb)) { 649 _bcm_hx5_cosq_tcb_deinit(unit); 650 } 651 #endif /* INCLUDE_TCB && BCM_TCB_SUPPORT */ 652 } 653 654 /* 655 * Function: 656 * _bcm_hx5_cosq_node_hw_index_get 657 * Purpose: 658 * Get cosq node hardware index 659 * Parameters: 660 * unit - (IN) unit number 661 * gport - (IN) GPORT identifier 662 * cosq - (OUT) COS queue number 663 * Returns: 664 * BCM_E_XXX 665 */ 666 STATIC int 667 _bcm_hx5_cosq_node_hw_index_get(int unit, bcm_gport_t gport, 668 bcm_cos_queue_t *cosq) 669 { 670 _bcm_hx5_cosq_node_t *node = NULL; 671 int local_port = -1; 672 int phy_port, mmu_port; 673 int num_uc, num_mc; 674 675 soc_info_t *si = &SOC_INFO(unit); 676 677 BCM_IF_ERROR_RETURN 678 (_bcm_hx5_cosq_node_get(unit, gport, NULL, &local_port, NULL, 679 &node)); 680 681 phy_port = si->port_l2p_mapping[local_port]; 682 mmu_port = si->port_p2m_mapping[phy_port]; 683 684 if(IS_CPU_PORT(unit, local_port)){ 685 num_uc = 0; 686 num_mc = SOC_HX5_NUM_CPU_QUEUES; 687 }else { 688 if(_HX5_IS_ST_PORT(unit, mmu_port)) { 689 num_uc = SOC_HX5_NUM_UCAST_QUEUE_PER_ST_PORT; 690 num_mc = SOC_HX5_NUM_MCAST_QUEUE_PER_ST_PORT; 691 }else { 692 num_uc = SOC_HX5_NUM_UCAST_QUEUE_PER_PORT; 693 num_mc = SOC_HX5_NUM_MCAST_QUEUE_PER_PORT; 694 } 695 } 696 697 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 698 if(_HX5_IS_ST_PORT(unit, mmu_port)){ 699 *cosq = node->hw_index - (mmu_port * num_uc); 700 } else { 701 *cosq = node->hw_index - (_HX5_BASE_L3QUEUE + 702 ((mmu_port - _BCM_HX5_NUM_ST_PORTS) * num_uc)); 703 } 704 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 705 if(IS_CPU_PORT(unit, local_port)){ 706 *cosq = node->hw_index - _HX5_CPU_L2_NODE_BASE; 707 } else if(_HX5_IS_ST_PORT(unit, mmu_port)){ 708 *cosq = node->hw_index - (mmu_port * num_mc); 709 } else { 710 *cosq = node->hw_index - (_HX5_BASE_L3QUEUE + 711 ((mmu_port - _BCM_HX5_NUM_ST_PORTS) * num_mc)); 712 } 713 } else { 714 switch(node->level) { 715 case SOC_HX5_NODE_LVL_L0: 716 if(IS_CPU_PORT(unit, local_port)){ 717 *cosq = node->hw_index - _HX5_CPU_LO_NODE_BASE; 718 } else if(_HX5_IS_ST_PORT(unit, mmu_port)){ 719 *cosq = node->hw_index - (mmu_port * _HX5_ST_NUML0_NODES); 720 } else { 721 *cosq = node->hw_index - (_HX5_BASE_L0QUEUE + 722 ((mmu_port - _BCM_HX5_NUM_ST_PORTS) * _HX5_NUML0_NODES)); 723 } 724 break; 725 case SOC_HX5_NODE_LVL_L1: 726 if(IS_CPU_PORT(unit, local_port)){ 727 *cosq = node->hw_index - _HX5_CPU_L1_NODE_BASE; 728 } else if(_HX5_IS_ST_PORT(unit, mmu_port)){ 729 *cosq = node->hw_index - (mmu_port * _HX5_ST_NUML1_NODES); 730 } else { 731 *cosq = node->hw_index - (_HX5_BASE_L1QUEUE + 732 ((mmu_port - _BCM_HX5_NUM_ST_PORTS) * _HX5_NUML1_NODES)); 733 } 734 break; 735 case SOC_HX5_NODE_LVL_L2: 736 if(IS_CPU_PORT(unit, local_port)){ 737 *cosq = node->hw_index - _HX5_CPU_L2_NODE_BASE; 738 } else if(_HX5_IS_ST_PORT(unit, mmu_port)){ 739 *cosq = node->hw_index - (mmu_port * _HX5_ST_NUML2_NODES); 740 } else { 741 *cosq = node->hw_index - (_HX5_BASE_L2QUEUE + 742 ((mmu_port - _BCM_HX5_NUM_ST_PORTS) * _HX5_NUML2_NODES)); 743 } 744 break; 745 default: 746 return BCM_E_PARAM; 747 } 748 749 } 750 751 return BCM_E_NONE; 752 } 753 754 755 /* 756 * Function: 757 * bcm_hx5_cosq_gport_get 758 * Purpose: 759 * Get a cosq gport structure 760 * Parameters: 761 * unit - (IN) unit number 762 * gport - (IN) GPORT identifier 763 * port - (OUT) port number 764 * numq - (OUT) number of COS queues 765 * flags - (OUT) flags (BCM_COSQ_GPORT_XXX) 766 * Returns: 767 * BCM_E_XXX 768 */ 769 int 770 bcm_hx5_cosq_gport_get(int unit, bcm_gport_t gport, bcm_gport_t *port, 771 int *numq, uint32 *flags) 772 { 773 _bcm_hx5_cosq_node_t *node; 774 bcm_port_t local_port; 775 bcm_module_t modid; 776 _bcm_gport_dest_t dest; 777 int phy_port, mmu_port; 778 soc_info_t *si = &SOC_INFO(unit); 779 780 if (port == NULL || numq == NULL || flags == NULL) { 781 return BCM_E_PARAM; 782 } 783 784 LOG_INFO(BSL_LS_BCM_COSQ, 785 (BSL_META_U(unit, 786 "bcm_hx5_cosq_gport_get: unit=%d gport=0x%x\n"), 787 unit, gport)); 788 789 if ((BCM_GPORT_IS_SCHEDULER(gport)) || 790 BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 791 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) || 792 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport)) { 793 BCM_IF_ERROR_RETURN 794 (_bcm_hx5_cosq_node_get(unit, gport, NULL, &local_port, NULL, 795 &node)); 796 797 *numq = node->numq; 798 799 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 800 *flags = BCM_COSQ_GPORT_UCAST_QUEUE_GROUP; 801 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 802 *flags = BCM_COSQ_GPORT_MCAST_QUEUE_GROUP; 803 } else if (BCM_GPORT_IS_SCHEDULER(gport)) { 804 *flags = BCM_COSQ_GPORT_SCHEDULER; 805 } else { 806 *flags = 0; 807 } 808 } else { 809 BCM_IF_ERROR_RETURN 810 (_bcm_hx5_cosq_localport_resolve(unit, gport, &local_port)); 811 *flags = 0; 812 phy_port = si->port_l2p_mapping[local_port]; 813 mmu_port = si->port_p2m_mapping[phy_port]; 814 *numq = (_HX5_IS_ST_PORT(unit, mmu_port)) ? SOC_HX5_NUM_SCHEDULER_PER_ST_PORT : 815 SOC_HX5_NUM_SCHEDULER_PER_PORT; 816 } 817 818 if (SOC_USE_GPORT(unit)) { 819 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid)); 820 dest.gport_type = _SHR_GPORT_TYPE_MODPORT; 821 dest.modid = modid; 822 dest.port = local_port; 823 BCM_IF_ERROR_RETURN(_bcm_esw_gport_construct(unit, &dest, port)); 824 } else { 825 *port = local_port; 826 } 827 828 LOG_INFO(BSL_LS_BCM_COSQ, 829 (BSL_META_U(unit, 830 " port=0x%x numq=%d flags=0x%x\n"), 831 *port, *numq, *flags)); 832 833 return BCM_E_NONE; 834 } 835 836 /* 837 * Function: 838 * _bcm_hx5_cosq_gport_add 839 * Purpose: 840 * Create a cosq gport structure 841 * Parameters: 842 * unit - (IN) unit number 843 * port - (IN) port number 844 * numq - (IN) number of COS queues 845 * flags - (IN) flags (BCM_COSQ_GPORT_XXX) 846 * gport - (OUT) GPORT identifier 847 * Returns: 848 * BCM_E_XXX 849 */ 850 STATIC int 851 _bcm_hx5_cosq_gport_add(int unit, bcm_gport_t port, int numq, uint32 flags, 852 bcm_gport_t *gport) 853 { 854 _bcm_hx5_cosq_port_info_t *port_info = NULL; 855 _bcm_hx5_cosq_st_port_info_t *stport_info = NULL; 856 _bcm_hx5_cosq_cpu_port_info_t *cpu_port_info = NULL; 857 _bcm_hx5_cosq_node_t *node = NULL; 858 int phy_port, mmu_port; 859 bcm_port_t local_port; 860 uint32 sched_encap; 861 int id; 862 int num_uc, num_mc, num_sc, index; 863 864 soc_info_t *si = &SOC_INFO(unit); 865 866 LOG_INFO(BSL_LS_BCM_COSQ, 867 (BSL_META_U(unit, 868 "_bcm_hx5_cosq_gport_add: unit=%d port=0x%x " 869 "numq=%d flags=0x%x\n"), unit, port, numq, flags)); 870 871 if (gport == NULL) { 872 return BCM_E_PARAM; 873 } 874 875 if (_bcm_hx5_cosq_port_info[unit] == NULL) { 876 return BCM_E_INIT; 877 } 878 879 if (_bcm_hx5_cosq_st_port_info[unit] == NULL) { 880 return BCM_E_INIT; 881 } 882 883 if (_bcm_hx5_cosq_cpu_port_info[unit] == NULL) { 884 return BCM_E_INIT; 885 } 886 887 BCM_IF_ERROR_RETURN 888 (_bcm_hx5_cosq_localport_resolve(unit, port, &local_port)); 889 890 if (local_port < 0 || IS_LB_PORT(unit, local_port)) { 891 return BCM_E_PORT; 892 } 893 894 phy_port = si->port_l2p_mapping[local_port]; 895 mmu_port = si->port_p2m_mapping[phy_port]; 896 _HX5_PORT_INDEX_GET(unit, mmu_port, index); 897 if (IS_CPU_PORT(unit, local_port)) { 898 cpu_port_info = _bcm_hx5_cosq_cpu_port_info[unit]; 899 num_uc = 0; 900 num_mc = SOC_HX5_NUM_CPU_QUEUES; 901 num_sc = SOC_HX5_NUM_SCHEDULER_PER_CPU_PORT; 902 } else if(_HX5_IS_ST_PORT(unit, mmu_port)) { 903 stport_info = &_bcm_hx5_cosq_st_port_info[unit][index]; 904 num_uc = SOC_HX5_NUM_UCAST_QUEUE_PER_ST_PORT; 905 num_mc = SOC_HX5_NUM_MCAST_QUEUE_PER_ST_PORT; 906 num_sc = SOC_HX5_NUM_SCHEDULER_PER_ST_PORT; 907 } else { 908 port_info = &_bcm_hx5_cosq_port_info[unit][index]; 909 num_uc = SOC_HX5_NUM_UCAST_QUEUE_PER_PORT; 910 num_mc = SOC_HX5_NUM_UCAST_QUEUE_PER_PORT; 911 num_sc = SOC_HX5_NUM_SCHEDULER_PER_PORT; 912 } 913 914 switch (flags) { 915 case BCM_COSQ_GPORT_UCAST_QUEUE_GROUP: 916 if (IS_CPU_PORT(unit, local_port)) { 917 return BCM_E_PARAM; 918 } 919 if (numq != 1) { 920 return BCM_E_PARAM; 921 } 922 for (id = 0; id < num_uc; id++) { 923 if(_HX5_IS_ST_PORT(unit, mmu_port)) { 924 if ((stport_info->ucast[id].numq == 0) || 925 (stport_info->ucast[id].in_use == 0)) { 926 break; 927 } 928 } else { 929 if ((port_info->ucast[id].numq == 0) || 930 (port_info->ucast[id].in_use == 0)) { 931 break; 932 } 933 } 934 } 935 if (id == num_uc) { 936 return BCM_E_RESOURCE; 937 } 938 BCM_GPORT_UCAST_QUEUE_GROUP_SYSQID_SET(*gport, local_port, id); 939 if (_HX5_IS_ST_PORT(unit, mmu_port)){ 940 node = &stport_info->ucast[id]; 941 } else { 942 node = &port_info->ucast[id]; 943 } 944 node->level = SOC_HX5_NODE_LVL_L3; 945 break; 946 case BCM_COSQ_GPORT_MCAST_QUEUE_GROUP: 947 if (numq != 1) { 948 return BCM_E_PARAM; 949 } 950 if (IS_CPU_PORT(unit, local_port)) { 951 for (id = 0; id < SOC_HX5_NUM_CPU_QUEUES; id++) { 952 if ((cpu_port_info->mcast[id].numq == 0) || 953 (cpu_port_info->mcast[id].in_use == 0)) { 954 break; 955 } 956 } 957 if (id == SOC_HX5_NUM_CPU_QUEUES) { 958 return BCM_E_RESOURCE; 959 } 960 } else { 961 for (id = 0; id < num_mc; id++) { 962 if(_HX5_IS_ST_PORT(unit, mmu_port)) { 963 if ((stport_info->mcast[id].numq == 0) || 964 (stport_info->mcast[id].in_use == 0)) { 965 break; 966 } 967 } else { 968 if ((port_info->mcast[id].numq == 0) || 969 (port_info->mcast[id].in_use == 0)) { 970 break; 971 } 972 } 973 } 974 if (id == num_mc) { 975 return BCM_E_RESOURCE; 976 } 977 } 978 BCM_GPORT_MCAST_QUEUE_GROUP_SYSQID_SET(*gport, local_port, id); 979 if (IS_CPU_PORT(unit, local_port)) { 980 node = &cpu_port_info->mcast[id]; 981 } else if ( _HX5_IS_ST_PORT(unit, mmu_port)){ 982 node = &stport_info->mcast[id]; 983 } else { 984 node = &port_info->mcast[id]; 985 } 986 node->level = SOC_HX5_NODE_LVL_L3; 987 break; 988 case BCM_COSQ_GPORT_SCHEDULER: 989 case 0: 990 if (numq <= 0) { 991 return BCM_E_PARAM; 992 } 993 if (IS_CPU_PORT(unit, local_port)) { 994 for (id = 0; id < SOC_HX5_NUM_SCHEDULER_PER_CPU_PORT; id++) { 995 if (cpu_port_info->sched[id].numq == 0) { 996 break; 997 } 998 if (id == num_sc) { 999 return BCM_E_RESOURCE; 1000 } 1001 } 1002 if (id == SOC_HX5_NUM_SCHEDULER_PER_CPU_PORT) { 1003 return BCM_E_RESOURCE; 1004 } 1005 1006 sched_encap = (id << 16) | local_port; 1007 BCM_GPORT_SCHEDULER_SET(*gport, sched_encap); 1008 node = &cpu_port_info->sched[id]; 1009 node->level = SOC_HX5_NODE_LVL_L0; 1010 } 1011 1012 if (_HX5_IS_ST_PORT(unit, mmu_port) && !IS_CPU_PORT(unit, local_port)){ 1013 for (id = 0; id < SOC_HX5_NUM_SCHEDULER_PER_ST_PORT; id++) { 1014 if (stport_info->sched[id].numq == 0) { 1015 break; 1016 } 1017 } 1018 if (id == SOC_HX5_NUM_SCHEDULER_PER_ST_PORT) { 1019 return BCM_E_RESOURCE; 1020 } 1021 sched_encap = (id << 16) | local_port; 1022 BCM_GPORT_SCHEDULER_SET(*gport, sched_encap); 1023 node = &stport_info->sched[id]; 1024 node->level = SOC_HX5_NODE_LVL_L0; 1025 } 1026 1027 if (!_HX5_IS_ST_PORT(unit, mmu_port) && !IS_CPU_PORT(unit, local_port)){ 1028 for (id = 0; id < SOC_HX5_NUM_SCHEDULER_PER_PORT; id++) { 1029 if (port_info->sched[id].numq == 0) { 1030 break; 1031 } 1032 } 1033 if (id == SOC_HX5_NUM_SCHEDULER_PER_PORT) { 1034 return BCM_E_RESOURCE; 1035 } 1036 sched_encap = (id << 16) | local_port; 1037 BCM_GPORT_SCHEDULER_SET(*gport, sched_encap); 1038 node = &port_info->sched[id]; 1039 node->level = SOC_HX5_NODE_LVL_L0; 1040 } 1041 break; 1042 default: 1043 return BCM_E_PARAM; 1044 } 1045 1046 node->gport = *gport; 1047 node->numq = numq; 1048 node->in_use = 1; 1049 1050 LOG_INFO(BSL_LS_BCM_COSQ, 1051 (BSL_META_U(unit,"gport=0x%x\n"), *gport)); 1052 1053 return BCM_E_NONE; 1054 } 1055 1056 /* 1057 * This function does two things: 1058 * 1. Tests whether the corresponding COS_BMP bit is set or not. 1059 * 2. Tests whether the queue corresponding to given cos is 1060 * mapped to correct L2 or not. 1061 * 1062 * L2.0 is associated with CMC0 CH1(Rx) (pci) 1063 * L2.1 is associated with CMC0 CH2(Rx) (pci) 1064 * L2.2 is associated with CMC0 CH3(Rx) (pci) 1065 * L2.3 is associated with CMC0 CH4(Rx) (pci) 1066 * L2.4 is associated with CMC0 CH5(Rx) (pci) 1067 * L2.5 is associated with CMC0 CH6(Rx) (pci) 1068 * L2.6 is associated with CMC0 CH7(Rx) (pci) 1069 * L2.7 is associated with CMC1 CHx(Rx) (uc0) 1070 * L2.8 is associated with CMC1 CHx(Rx) (uC1) 1071 * L2.9 is reserved 1072 */ 1073 int 1074 bcm_hx5_rx_queue_channel_set_test(int unit, bcm_cos_queue_t queue_id, 1075 bcm_rx_chan_t chan_id) 1076 { 1077 #if defined(BCM_CMICX_SUPPORT) 1078 if (soc_feature(unit, soc_feature_cmicx)) { 1079 int pci_cmc = SOC_PCI_CMC(unit); 1080 uint32 reg_val; 1081 uint32 bit; 1082 uint32 max_rx_channels = 0; 1083 int index; 1084 _bcm_hx5_cosq_cpu_port_info_t *cpu_port_info = NULL; 1085 bcm_gport_t cpu_l2_gport = -1; 1086 bcm_gport_t parent_gport = -1; 1087 1088 soc_dma_max_rx_channels_get(unit, &max_rx_channels); 1089 1090 if ((chan_id <= 0) || (chan_id >= max_rx_channels)) { 1091 return BCM_E_PARAM; 1092 } 1093 1094 if (_bcm_hx5_cosq_cpu_port_info[unit] == NULL) { 1095 return BCM_E_INIT; 1096 } 1097 1098 cpu_port_info = _bcm_hx5_cosq_cpu_port_info[unit]; 1099 1100 if ((chan_id > 0) && (chan_id < 8 )) { 1101 index = chan_id + 2; 1102 cpu_l2_gport = cpu_port_info->sched[index - 1].gport; 1103 } 1104 1105 if (queue_id < 0) { /* All COS Queues */ 1106 for (queue_id = 0; queue_id < NUM_CPU_COSQ(unit); queue_id++) { 1107 soc_dma_cos_ctrl_queue_get(unit, pci_cmc, chan_id, queue_id, 1108 ®_val); 1109 1110 bit = 1 << (queue_id % 32); 1111 if (reg_val & bit) { 1112 /* find the parent gport of this queue if parent gport is 1113 * not equal to l0 gport for this channel return error */ 1114 parent_gport = cpu_port_info->mcast[queue_id].parent_gport; 1115 if (parent_gport != cpu_l2_gport) { 1116 return BCM_E_PARAM; 1117 } 1118 } 1119 } 1120 } else { 1121 soc_dma_cos_ctrl_queue_get(unit, pci_cmc, chan_id, queue_id, 1122 ®_val); 1123 bit = 1 << (queue_id % 32); 1124 if (reg_val & bit) { 1125 /* find the parent gport of this queue if parent gport is not 1126 * equal to l0 gport for this channel return error */ 1127 parent_gport = cpu_port_info->mcast[queue_id].parent_gport; 1128 if (parent_gport != cpu_l2_gport) { 1129 return BCM_E_PARAM; 1130 } 1131 } else { 1132 return BCM_E_PARAM; 1133 } 1134 } 1135 } 1136 #endif /* BCM_CMICX_SUPPORT */ 1137 1138 return BCM_E_NONE; 1139 } 1140 1141 /* 1142 * Function: 1143 * _bcm_hx5_cpu_cosq_mapping_default_set 1144 * Purpose: 1145 * Map 16 internal priorities to CPU COS queues using CPU_COS_MAPm 1146 * Default cpu_cos_maps should have lower priorities than user created 1147 * maps 1148 * Parameters: 1149 * unit - (IN) Unit number. 1150 * numq - (IN) number of COS queues (0-7). 1151 * Returns: 1152 * BCM_E_XXX 1153 */ 1154 STATIC int 1155 _bcm_hx5_cpu_cosq_mapping_default_set(int unit, int numq) 1156 { 1157 int cos = 0, prio = 0, index = 0, i = 0; 1158 cpu_cos_map_entry_t cpu_cos_map_entry; 1159 1160 /* Nothing to do on devices with no CPU_COS_MAP memory */ 1161 if (!SOC_MEM_IS_VALID(unit, CPU_COS_MAPm)) { 1162 return BCM_E_NONE; 1163 } 1164 1165 /* Map internal priorities 0 ~ 7 to appropriate CPU CoS queue */ 1166 sal_memset(&cpu_cos_map_entry, 0, sizeof(cpu_cos_map_entry_t)); 1167 soc_mem_field32_set(unit, CPU_COS_MAPm, &cpu_cos_map_entry, VALIDf, 3); 1168 soc_mem_field32_set(unit, CPU_COS_MAPm, &cpu_cos_map_entry, 1169 INT_PRI_MASKf, _BCM_HX5_INT_PRI_0_7_MASK); 1170 1171 index = (soc_mem_index_count(unit, CPU_COS_MAPm) - _BCM_HX5_CPU_COS_MAPS_RSVD); 1172 for (cos = 0; cos < numq; cos++) { 1173 for (i = 8 / numq + (cos < 8 % numq ? 1 : 0); i > 0; i--) { 1174 soc_mem_field32_set(unit, CPU_COS_MAPm, &cpu_cos_map_entry, 1175 INT_PRI_KEYf, prio); 1176 soc_mem_field32_set(unit, CPU_COS_MAPm, &cpu_cos_map_entry, COSf, cos); 1177 SOC_IF_ERROR_RETURN(WRITE_CPU_COS_MAPm(unit, MEM_BLOCK_ALL, index, 1178 &cpu_cos_map_entry)); 1179 prio++; 1180 index++; 1181 } 1182 } 1183 1184 /* Map internal priorities 8 ~ 15 to (numq - 1) CPU CoS queue */ 1185 soc_mem_field32_set(unit, CPU_COS_MAPm, &cpu_cos_map_entry, 1186 INT_PRI_KEYf, 0x8); 1187 soc_mem_field32_set(unit, CPU_COS_MAPm, &cpu_cos_map_entry, 1188 INT_PRI_MASKf, _BCM_HX5_INT_PRI_8_15_MASK); 1189 soc_mem_field32_set(unit, CPU_COS_MAPm, &cpu_cos_map_entry, COSf, numq - 1); 1190 SOC_IF_ERROR_RETURN(WRITE_CPU_COS_MAPm(unit, MEM_BLOCK_ALL, index, 1191 &cpu_cos_map_entry)); 1192 1193 return BCM_E_NONE; 1194 } 1195 1196 /* 1197 * Function: 1198 * bcm_hx5_wireless_cos_map_update 1199 * Purpose: 1200 * Set the number of classes of service supported 1201 * Parameters: 1202 * unit - (IN) unit number 1203 * index - (IN) index of newly added profile 1204 * Returns: 1205 * BCM_E_XXX 1206 */ 1207 int bcm_hx5_wireless_cos_map_update(int unit, int numq) 1208 { 1209 uint32 *cos_map_entries; 1210 soc_mem_t mem; 1211 int rv = SOC_E_NONE, cos, prio = 0, index = 0; 1212 uint32 uc_cos = 0, mc_cos = 0, hg_cos = 0; 1213 1214 mem = PORT_COS_MAPm; 1215 cos_map_entries = soc_cm_salloc(unit, (sizeof(port_cos_map_entry_t) * 16), 1216 "HX5 Cos map update"); 1217 for (index = 0; index < 4; index++) { 1218 prio = 0; 1219 sal_memset(cos_map_entries, 0, (sizeof(port_cos_map_entry_t) * 16)); 1220 rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY, index * _HX5_NUM_COS_MAP_ENTRY, 1221 (index * _HX5_NUM_COS_MAP_ENTRY) + (_HX5_NUM_COS_MAP_ENTRY - 1), 1222 (void *)cos_map_entries); 1223 if (BCM_FAILURE(rv)) { 1224 soc_cm_sfree(unit, cos_map_entries); 1225 return rv; 1226 } 1227 for (cos = 0; cos < numq; cos++) { 1228 uc_cos = mc_cos = hg_cos = 0; 1229 uc_cos = soc_mem_field32_get(unit, mem, &cos_map_entries[prio], UC_COS1f); 1230 mc_cos = soc_mem_field32_get(unit, mem, &cos_map_entries[prio], MC_COS1f); 1231 hg_cos = soc_mem_field32_get(unit, mem, &cos_map_entries[prio], HG_COSf); 1232 soc_mem_field32_set(unit, mem, &cos_map_entries[prio], UC_COS1f, uc_cos + _BCM_HX5_COS_DEFAULT); 1233 soc_mem_field32_set(unit, mem, &cos_map_entries[prio], MC_COS1f, mc_cos + _BCM_HX5_COS_DEFAULT); 1234 if(!hg_cos || (hg_cos < _BCM_HX5_COS_DEFAULT)) { 1235 soc_mem_field32_set(unit, mem, &cos_map_entries[prio], HG_COSf, hg_cos + _HX5_NUM_COS_MAP_ENTRY); 1236 } 1237 prio++; 1238 } 1239 1240 for (prio = 8; prio < 16; prio++) { 1241 soc_mem_field32_set(unit, mem, &cos_map_entries[prio], UC_COS1f, 1242 uc_cos + _BCM_HX5_COS_DEFAULT); 1243 soc_mem_field32_set(unit, mem, &cos_map_entries[prio], MC_COS1f, 1244 mc_cos + _BCM_HX5_COS_DEFAULT); 1245 if(!hg_cos || (hg_cos < _BCM_HX5_COS_DEFAULT)) { 1246 soc_mem_field32_set(unit, mem, &cos_map_entries[prio], HG_COSf, 1247 hg_cos + _HX5_NUM_COS_MAP_ENTRY); 1248 } 1249 } 1250 1251 rv = soc_mem_write_range(unit, mem, MEM_BLOCK_ANY, (index * _HX5_NUM_COS_MAP_ENTRY) + 1252 _HX5_WIRELESS_COS_MAP_BASE, (index * _HX5_NUM_COS_MAP_ENTRY) + 1253 (_HX5_WIRELESS_COS_MAP_BASE + _HX5_NUM_COS_MAP_ENTRY - 1), 1254 (void *)cos_map_entries); 1255 1256 } 1257 soc_cm_sfree(unit, cos_map_entries); 1258 return rv; 1259 1260 } 1261 1262 /* 1263 * Function: 1264 * bcm_hx5_cosq_config_set 1265 * Purpose: 1266 * Set the number of classes of service supported 1267 * Parameters: 1268 * unit - (IN) unit number 1269 * numq - (IN) number of classes of service 1270 * Returns: 1271 * BCM_E_XXX 1272 */ 1273 int 1274 bcm_hx5_cosq_config_set(int unit, int numq) 1275 { 1276 port_cos_map_entry_t cos_map_entries[16]; 1277 void *entries[1]; 1278 uint32 index; 1279 int count = 0; 1280 bcm_port_t port; 1281 int cos, prio = 0, ref_count = -1; 1282 uint32 i; 1283 soc_mem_t mem = PORT_COS_MAPm; 1284 1285 if (numq < 1 || numq > _BCM_HX5_COS_DEFAULT) { 1286 return BCM_E_PARAM; 1287 } 1288 1289 index = 0; 1290 while (index < (soc_mem_index_count(unit, mem) / 2)) { 1291 BCM_IF_ERROR_RETURN(soc_profile_mem_ref_count_get(unit, 1292 _bcm_hx5_cos_map_profile[unit], 1293 index, &ref_count)); 1294 if (ref_count > 0) { 1295 while (ref_count) { 1296 if (!soc_profile_mem_delete(unit, 1297 _bcm_hx5_cos_map_profile[unit], index)) { 1298 ref_count -= 1; 1299 } 1300 } 1301 } 1302 index += 16; 1303 } 1304 1305 /* 1306 * Distribute first 8 internal priority levels into the specified number 1307 * of cosq, map remaining internal priority levels to highest priority 1308 * cosq 1309 */ 1310 sal_memset(cos_map_entries, 0, sizeof(cos_map_entries)); 1311 entries[0] = &cos_map_entries; 1312 1313 for (cos = 0; cos < numq; cos++) { 1314 for (i = 8 / numq + (cos < 8 % numq ? 1 : 0); i > 0; i--) { 1315 soc_mem_field32_set(unit, mem, &cos_map_entries[prio], 1316 UC_COS1f, cos); 1317 soc_mem_field32_set(unit, mem, &cos_map_entries[prio], 1318 MC_COS1f, cos); 1319 soc_mem_field32_set(unit, mem, &cos_map_entries[prio], 1320 HG_COSf, _HX5_NUM_COS_MAP_ENTRY + cos); 1321 prio++; 1322 } 1323 } 1324 for (prio = 8; prio < 16; prio++) { 1325 soc_mem_field32_set(unit, mem, &cos_map_entries[prio], UC_COS1f, 1326 numq - 1); 1327 soc_mem_field32_set(unit, mem, &cos_map_entries[prio], MC_COS1f, 1328 numq - 1); 1329 soc_mem_field32_set(unit, mem, &cos_map_entries[prio], HG_COSf, 1330 _HX5_NUM_COS_MAP_ENTRY + (numq - 1)); 1331 } 1332 1333 /* Map internal priority levels to CPU CoS queues */ 1334 BCM_IF_ERROR_RETURN(_bcm_hx5_cpu_cosq_mapping_default_set(unit, numq)); 1335 1336 SOC_IF_ERROR_RETURN 1337 (soc_profile_mem_add(unit, _bcm_hx5_cos_map_profile[unit], entries, 16, 1338 &index)); 1339 BCM_IF_ERROR_RETURN(bcm_hx5_wireless_cos_map_update(unit, numq)); 1340 PBMP_ALL_ITER(unit, port) { 1341 SOC_IF_ERROR_RETURN 1342 (soc_mem_field32_modify(unit, COS_MAP_SELm, port, SELECTf, 1343 index / 16)); 1344 count++; 1345 } 1346 if (SOC_INFO(unit).cpu_hg_index != -1) { 1347 SOC_IF_ERROR_RETURN 1348 (soc_mem_field32_modify(unit, COS_MAP_SELm, 1349 SOC_INFO(unit).cpu_hg_index, SELECTf, 1350 index / 16)); 1351 count++; 1352 } 1353 for (i = 1; i < count; i++) { 1354 soc_profile_mem_reference(unit, _bcm_hx5_cos_map_profile[unit], index, 0); 1355 } 1356 1357 _BCM_HX5_NUM_COS(unit) = numq; 1358 1359 return BCM_E_NONE; 1360 } 1361 1362 int bcm_hx5_hgcos_mode_get(int unit, bcm_port_t port, int *mode) 1363 { 1364 uint32 regval = 0; 1365 SOC_IF_ERROR_RETURN(READ_UC_HG_QUEUE_MODEr(unit, port, ®val)); 1366 *mode = soc_reg_field_get(unit, UC_HG_QUEUE_MODEr, regval, QUEUE_MODEf); 1367 1368 return BCM_E_NONE; 1369 } 1370 1371 1372 /* 1373 * Function: 1374 * bcm_hx5_cosq_config_get 1375 * Purpose: 1376 * Get the number of Classes of Service 1377 * Parameters: 1378 * unit - (IN) unit number 1379 * numq - (OUT) Number of Classes of Service 1380 * Returns: 1381 * BCM_E_XXX 1382 */ 1383 int 1384 bcm_hx5_cosq_config_get(int unit, int *numq) 1385 { 1386 if (numq != NULL) { 1387 *numq = _BCM_HX5_NUM_COS(unit); 1388 } 1389 1390 return BCM_E_NONE; 1391 1392 } 1393 1394 1395 /* 1396 * CMIC CMC Channel to Queue mapping. 1397 */ 1398 STATIC int 1399 _bcm_hx5_cosq_rx_queue_channel_set(int unit, bcm_cos_queue_t parent_cos, 1400 bcm_cos_queue_t queue_id, int enable) 1401 { 1402 #if defined(BCM_CMICX_SUPPORT) 1403 if soc_feature(unit, soc_feature_cmicx) { 1404 int pci_cmc = SOC_PCI_CMC(unit); 1405 int chan_id = -1; 1406 int start_chan_id = 0; 1407 uint32 chan_off; 1408 uint32 reg_addr, reg_val; 1409 uint32 ix; 1410 uint32 max_rx_channels = 0; 1411 1412 if ((parent_cos >= 0) && (parent_cos <= 6)) { 1413 chan_id = parent_cos + 1; 1414 } else { 1415 return BCM_E_PARAM; 1416 } 1417 1418 if (!SHR_BITGET(CPU_ARM_QUEUE_BITMAP(unit, pci_cmc), queue_id)) { 1419 return BCM_E_PARAM; 1420 } 1421 1422 soc_dma_max_rx_channels_get(unit, &max_rx_channels); 1423 1424 for (ix = start_chan_id; ix < (start_chan_id + max_rx_channels); ix++) { 1425 chan_off = ix % max_rx_channels; 1426 soc_dma_cos_ctrl_reg_addr_get(unit, pci_cmc, chan_off, queue_id, 1427 ®_addr); 1428 reg_val = soc_pci_read(unit, reg_addr); 1429 1430 if (enable == 1) { 1431 if (ix == (uint32)chan_id) { 1432 reg_val |= ((uint32)1 << (queue_id % 32)); 1433 } else { 1434 /* Clear all other channels */ 1435 reg_val &= ~((uint32)1 << (queue_id % 32)); 1436 } 1437 } else { 1438 if (ix == (uint32)chan_id) { 1439 reg_val &= ~((uint32)1 << (queue_id % 32)); 1440 } 1441 } 1442 /* Incoporate the reserved queues (if any on this device) 1443 * into the CMIC programming, */ 1444 reg_val |= 1445 CPU_ARM_RSVD_QUEUE_BITMAP(unit, pci_cmc)[queue_id / 32]; 1446 soc_pci_write(unit, reg_addr, reg_val); 1447 } 1448 } 1449 #endif /* BCM_CMICX_SUPPORT */ 1450 1451 return BCM_E_NONE; 1452 } 1453 1454 1455 1456 1457 /* 1458 * Function: 1459 * _bcm_hx5_cosq_cpu_parent_set 1460 * Purpose: 1461 * Set Parent(L2) for a given L3 queue of the CPU port. 1462 * Only child @ L3 level is supported. Because only L3 level queues can be 1463 * attached to different parent (L2.0-L2.9) of the CPU port. 1464 * Parameters: 1465 * unit - (IN) unit number 1466 * child_index - (IN) Child node index 1467 * child_level - (IN) Child node level 1468 * parent_index - (IN) Parent node index 1469 * Returns: 1470 * BCM_E_XXX 1471 */ 1472 STATIC int 1473 _bcm_hx5_cosq_cpu_parent_set(int unit, int child_index, int child_level, 1474 int parent_index) 1475 { 1476 soc_reg_t reg = Q_SCHED_CPU_L3_MC_QUEUE_L2_MAPPINGr; 1477 uint32 rval = 0; 1478 1479 if (child_level != SOC_HX5_NODE_LVL_L3) { 1480 return BCM_E_PARAM; 1481 } 1482 1483 /* Set the L3 queue's parent to the given L2 node */ 1484 SOC_IF_ERROR_RETURN 1485 (soc_reg32_get(unit, reg, 0, child_index, &rval)); 1486 soc_reg_field_set(unit, reg, &rval, SELECTf, parent_index); 1487 SOC_IF_ERROR_RETURN 1488 (soc_reg32_set(unit, reg, 0, child_index, rval)); 1489 1490 return BCM_E_NONE; 1491 } 1492 1493 1494 /* 1495 * Function: 1496 * _bcm_hx5_cosq_cpu_parent_get 1497 * Purpose: 1498 * Get Parent(L2) for a given L3 queue of the CPU port. 1499 * Only child @ L3 level is supported. Because only L3 level queues can be 1500 * attached to different parent (L2.0-L2.9) of the CPU port. 1501 * Parameters: 1502 * unit - (IN) unit number 1503 * child_index - (IN) Child node index 1504 * child_level - (IN) Child node level 1505 * parent_index - (OUT) Parent node index 1506 * Returns: 1507 * BCM_E_XXX 1508 */ 1509 STATIC int 1510 _bcm_hx5_cosq_cpu_parent_get(int unit, int child_index, int child_level, 1511 int *parent_index) 1512 { 1513 soc_reg_t reg = Q_SCHED_CPU_L3_MC_QUEUE_L2_MAPPINGr; 1514 uint32 rval = 0; 1515 1516 if (child_level != SOC_HX5_NODE_LVL_L3) { 1517 return BCM_E_PARAM; 1518 } 1519 1520 /* Set the L3 queue's parent to the given L2 node */ 1521 SOC_IF_ERROR_RETURN 1522 (soc_reg32_get(unit, reg, 0, child_index, &rval)); 1523 *parent_index = soc_reg_field_get(unit, reg, rval, SELECTf); 1524 1525 return BCM_E_NONE; 1526 } 1527 1528 1529 /* 1530 * Function: 1531 * _bcm_hx5_cosq_cpu_gport_attach 1532 * Purpose: 1533 * Attach any of the L3 MC Queue to one of the L2 nodes 1534 * Parameters: 1535 * unit - (IN) unit number 1536 * input_gport - (IN) GPORT id, that will attach to parent gport 1537 * parent_gport - (IN) Parent Gport to which current gport will be attached 1538 * cosq - (IN) COS queue to attach to (-1 for first available cosq) 1539 * Returns: 1540 * BCM_E_XXX 1541 */ 1542 STATIC int 1543 _bcm_hx5_cosq_cpu_gport_attach(int unit, bcm_gport_t input_gport, 1544 bcm_gport_t parent_gport, bcm_cos_queue_t cosq) 1545 { 1546 1547 _bcm_hx5_cosq_node_t *input_node = NULL; 1548 _bcm_hx5_cosq_node_t *parent_node = NULL; 1549 bcm_port_t input_port, parent_port; 1550 int parent_cos = 0; 1551 1552 LOG_INFO(BSL_LS_BCM_COSQ, 1553 (BSL_META_U(unit, 1554 "bcm_hx5_cosq_gport_attach: unit=%d parent_gport=0x%x " 1555 "input_gport=0x%x cosq=%d\n"), unit, parent_gport, 1556 input_gport, cosq)); 1557 1558 if (_BCM_HX5_MMU_INFO(unit)->gport_tree_created == FALSE) { 1559 if (((BCM_GPORT_IS_MCAST_QUEUE_GROUP(input_gport)) && 1560 (!BCM_GPORT_IS_SCHEDULER(parent_gport))) || 1561 (!(BCM_GPORT_IS_MCAST_QUEUE_GROUP(input_gport)) && 1562 (!BCM_GPORT_IS_SCHEDULER(input_gport)))) { 1563 return BCM_E_PARAM; 1564 } 1565 } else if ((!BCM_GPORT_IS_SCHEDULER(parent_gport)) || 1566 (!BCM_GPORT_IS_MCAST_QUEUE_GROUP(input_gport))) { 1567 return BCM_E_PARAM; 1568 } 1569 1570 BCM_IF_ERROR_RETURN 1571 (_bcm_hx5_cosq_node_get(unit, input_gport, NULL, &input_port, NULL, 1572 &input_node)); 1573 1574 if (!input_node) { 1575 return BCM_E_PARAM; 1576 } 1577 if (input_port < 0) { 1578 return BCM_E_PORT; 1579 } 1580 1581 if (BCM_GPORT_IS_SCHEDULER(parent_gport)) { 1582 BCM_IF_ERROR_RETURN 1583 (_bcm_hx5_cosq_node_get(unit, parent_gport, NULL, &parent_port, NULL, 1584 &parent_node)); 1585 } else { 1586 BCM_IF_ERROR_RETURN 1587 (_bcm_hx5_cosq_localport_resolve(unit, parent_gport, &parent_port)); 1588 parent_node = NULL; 1589 } 1590 1591 if (!IS_CPU_PORT(unit, parent_port)) { 1592 return BCM_E_PARAM; 1593 } 1594 1595 /* Return BCM_E_EXISTS when queue to be attached is 1596 * already attached to the given gport 1597 */ 1598 if ((_BCM_HX5_MMU_INFO(unit)->gport_tree_created == TRUE) && 1599 (input_node->parent_gport == parent_gport)) { 1600 return BCM_E_EXISTS; 1601 } 1602 1603 1604 if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(input_gport)) { 1605 input_node->hw_index = SOC_HX5_CPU_MCQ_BASE + cosq; 1606 } else { 1607 input_node->level = HX5_CPU_SCHED_LEVEL_GET(unit, cosq); 1608 switch(input_node->level) { 1609 case SOC_HX5_NODE_LVL_L0: 1610 input_node->hw_index = _HX5_CPU_LO_NODE_BASE; 1611 break; 1612 case SOC_HX5_NODE_LVL_L1: 1613 input_node->hw_index = _HX5_CPU_L1_NODE_BASE; 1614 break; 1615 case SOC_HX5_NODE_LVL_L2: 1616 input_node->hw_index = _HX5_CPU_L2_NODE_BASE + (cosq - (_HX5_CPU_NUML0_NODES + _HX5_CPU_NUML1_NODES)); 1617 break; 1618 default: 1619 return BCM_E_PARAM; 1620 } 1621 } 1622 1623 if (BCM_GPORT_IS_SCHEDULER(parent_gport)) { 1624 if(parent_node->level == SOC_HX5_NODE_LVL_L2) { 1625 parent_cos = parent_node->hw_index - _HX5_CPU_L2_NODE_BASE; 1626 BCM_IF_ERROR_RETURN 1627 (_bcm_hx5_cosq_cpu_parent_set(unit, cosq, SOC_HX5_NODE_LVL_L3, 1628 parent_cos)); 1629 /* 1630 * L2.0 is associated with CMC0 CH1(Rx) 1631 * L2.1 is associated with CMC0 CH2(Rx) 1632 * L2.2 is associated with CMC0 CH3(Rx) 1633 * L2.3 is associated with CMC0 CH4(Rx) 1634 * L2.4 is associated with CMC0 CH5(Rx) 1635 * L2.5 is associated with CMC0 CH6(Rx) 1636 * L2.6 is associated with CMC0 CH7(Rx) 1637 */ 1638 if ((parent_cos >= 0) && (parent_cos < 7)) { 1639 BCM_IF_ERROR_RETURN 1640 (_bcm_hx5_cosq_rx_queue_channel_set(unit, parent_cos, cosq, 1)); 1641 } 1642 } 1643 } 1644 1645 if (BCM_GPORT_IS_SCHEDULER(input_gport)) { 1646 if(input_node->level == SOC_HX5_NODE_LVL_L0) { 1647 BCM_IF_ERROR_RETURN 1648 (bcm_esw_port_gport_get(unit, input_port, 1649 &(input_node->parent_gport))); 1650 } else { 1651 input_node->parent_gport = parent_gport; 1652 } 1653 }else if(BCM_GPORT_IS_MCAST_QUEUE_GROUP(input_gport)){ 1654 input_node->parent_gport = parent_gport; 1655 } 1656 1657 1658 return BCM_E_NONE; 1659 } 1660 1661 1662 1663 /* 1664 * Function: 1665 * _bcm_hx5_cosq_port_cos_resolve 1666 * Purpose: 1667 * Find UC/MC queue gport for a given logical port 1668 * and cos value. 1669 * Parameters: 1670 * unit - (IN) unit number 1671 * port - (IN) logical port 1672 * cos - (IN) cos value 1673 * style - (IN) index style 1674 * (_BCM_HX5_COSQ_INDEX_STYLE_UCAST_QUEUE or 1675 * _BCM_HX5_COSQ_INDEX_STYLE_MCAST_QUEUE) 1676 * gport - (OUT) Queue gport 1677 * Returns: 1678 * BCM_E_XXX 1679 */ 1680 int 1681 _bcm_hx5_cosq_port_cos_resolve(int unit, bcm_port_t port, bcm_cos_t cos, 1682 _bcm_hx5_cosq_index_style_t style, 1683 bcm_gport_t *gport) 1684 { 1685 _bcm_hx5_cosq_port_info_t *port_info = NULL; 1686 _bcm_hx5_cosq_st_port_info_t *stport_info = NULL; 1687 _bcm_hx5_cosq_cpu_port_info_t *cpu_port_info = NULL; 1688 int phy_port, mmu_port, port_index; 1689 1690 soc_info_t *si = &SOC_INFO(unit); 1691 1692 if (gport == NULL) { 1693 return BCM_E_PARAM; 1694 } 1695 1696 if (_bcm_hx5_cosq_port_info[unit] == NULL) { 1697 return BCM_E_INIT; 1698 } 1699 1700 if (_bcm_hx5_cosq_st_port_info[unit] == NULL) { 1701 return BCM_E_INIT; 1702 } 1703 if (_bcm_hx5_cosq_cpu_port_info[unit] == NULL) { 1704 return BCM_E_INIT; 1705 } 1706 1707 if ((IS_CPU_PORT(unit, port)) && 1708 (style == _BCM_HX5_COSQ_INDEX_STYLE_UCAST_QUEUE)) { 1709 return BCM_E_PARAM; 1710 } 1711 1712 if (cos < 0) { 1713 return BCM_E_PARAM; 1714 } 1715 1716 if (!SOC_PORT_VALID(unit, port)) { 1717 return BCM_E_PORT; 1718 } 1719 1720 if (_BCM_HX5_MMU_INFO(unit)->gport_tree_created != TRUE) { 1721 return BCM_E_INTERNAL; 1722 } 1723 1724 phy_port = si->port_l2p_mapping[port]; 1725 mmu_port = si->port_p2m_mapping[phy_port]; 1726 _HX5_PORT_INDEX_GET(unit, mmu_port, port_index); 1727 1728 1729 if (IS_CPU_PORT(unit, port)) { 1730 cpu_port_info = _bcm_hx5_cosq_cpu_port_info[unit]; 1731 if (style == _BCM_HX5_COSQ_INDEX_STYLE_MCAST_QUEUE) { 1732 if (cos >= SOC_HX5_NUM_CPU_QUEUES) { 1733 return BCM_E_PARAM; 1734 } 1735 *gport = cpu_port_info->mcast[cos].gport; 1736 } else { 1737 return BCM_E_INTERNAL; 1738 } 1739 } else if(_HX5_IS_ST_PORT(unit, mmu_port)){ 1740 stport_info = &_bcm_hx5_cosq_st_port_info[unit][port_index]; 1741 if (style == _BCM_HX5_COSQ_INDEX_STYLE_UCAST_QUEUE) { 1742 if (cos >= SOC_HX5_NUM_UCAST_QUEUE_PER_ST_PORT) { 1743 return BCM_E_PARAM; 1744 } 1745 *gport = stport_info->ucast[cos].gport; 1746 } else if (style == _BCM_HX5_COSQ_INDEX_STYLE_MCAST_QUEUE) { 1747 if (cos >= SOC_HX5_NUM_MCAST_QUEUE_PER_ST_PORT) { 1748 return BCM_E_PARAM; 1749 } 1750 *gport = stport_info->mcast[cos].gport; 1751 } else { 1752 return BCM_E_INTERNAL; 1753 } 1754 } else { 1755 port_info = &_bcm_hx5_cosq_port_info[unit][port_index]; 1756 if (style == _BCM_HX5_COSQ_INDEX_STYLE_UCAST_QUEUE) { 1757 if (cos >= SOC_HX5_NUM_UCAST_QUEUE_PER_PORT) { 1758 return BCM_E_PARAM; 1759 } 1760 *gport = port_info->ucast[cos].gport; 1761 } else if (style == _BCM_HX5_COSQ_INDEX_STYLE_MCAST_QUEUE) { 1762 if (cos >= SOC_HX5_NUM_MCAST_QUEUE_PER_PORT) { 1763 return BCM_E_PARAM; 1764 } 1765 *gport = port_info->mcast[cos].gport; 1766 } else { 1767 return BCM_E_INTERNAL; 1768 } 1769 } 1770 1771 return BCM_E_NONE; 1772 } 1773 1774 /* 1775 * Function: 1776 * bcm_hx5_cosq_gport_attach 1777 * Purpose: 1778 * Attach sched_port to the specified index (cosq) of input_port 1779 * Parameters: 1780 * unit - (IN) unit number 1781 * input_port - (IN) GPORT id, that will attach to parent gport 1782 * parent_gport - (IN) Parent Gport to which current gport will be attached 1783 * cosq - (IN) COS queue to attach to (-1 for first available cosq) 1784 * Returns: 1785 * BCM_E_XXX 1786 */ 1787 int 1788 bcm_hx5_cosq_gport_attach(int unit, bcm_gport_t input_gport, 1789 bcm_gport_t parent_gport, bcm_cos_queue_t cosq) 1790 { 1791 _bcm_hx5_cosq_node_t *input_node = NULL; 1792 _bcm_hx5_cosq_node_t *parent_node = NULL; 1793 bcm_port_t input_port, parent_port; 1794 int phy_port, mmu_port; 1795 soc_info_t *si = &SOC_INFO(unit); 1796 1797 LOG_INFO(BSL_LS_BCM_COSQ, 1798 (BSL_META_U(unit, 1799 "bcm_hx5_cosq_gport_attach: unit=%d parent_gport=0x%x " 1800 "input_gport=0x%x cosq=%d\n"), unit, parent_gport, 1801 input_gport, cosq)); 1802 1803 if (!(BCM_GPORT_IS_SCHEDULER(input_gport) || 1804 BCM_GPORT_IS_UCAST_QUEUE_GROUP(input_gport) || 1805 BCM_GPORT_IS_MCAST_QUEUE_GROUP(input_gport))) { 1806 return BCM_E_PARAM; 1807 } 1808 1809 BCM_IF_ERROR_RETURN 1810 (_bcm_hx5_cosq_node_get(unit, input_gport, NULL, &input_port, NULL, 1811 &input_node)); 1812 1813 if (!input_node) { 1814 return BCM_E_PARAM; 1815 } 1816 if (input_port < 0) { 1817 return BCM_E_PORT; 1818 } 1819 1820 if (IS_CPU_PORT(unit, input_port)) { 1821 return _bcm_hx5_cosq_cpu_gport_attach(unit, input_gport, parent_gport, 1822 cosq); 1823 } else if (_BCM_HX5_MMU_INFO(unit)->gport_tree_created == TRUE) { 1824 return BCM_E_PARAM; 1825 } 1826 1827 phy_port = si->port_l2p_mapping[input_port]; 1828 mmu_port = si->port_p2m_mapping[phy_port]; 1829 1830 if (BCM_GPORT_IS_SCHEDULER(parent_gport)) { 1831 BCM_IF_ERROR_RETURN 1832 (_bcm_hx5_cosq_node_get(unit, parent_gport, NULL, &parent_port, NULL, 1833 &parent_node)); 1834 } else { 1835 BCM_IF_ERROR_RETURN 1836 (_bcm_hx5_cosq_localport_resolve(unit, parent_gport, &parent_port)); 1837 parent_node = NULL; 1838 } 1839 1840 if (input_port != parent_port) { 1841 return BCM_E_PARAM; 1842 } 1843 1844 phy_port = si->port_l2p_mapping[parent_port]; 1845 mmu_port = si->port_p2m_mapping[phy_port]; 1846 1847 if(_HX5_IS_ST_PORT(unit, mmu_port)) { 1848 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(input_gport)) { 1849 input_node->hw_index = (mmu_port * SOC_HX5_NUM_UCAST_QUEUE_PER_ST_PORT) + cosq; 1850 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(input_gport)) { 1851 input_node->hw_index = (mmu_port * SOC_HX5_NUM_MCAST_QUEUE_PER_ST_PORT) + cosq; 1852 } else { 1853 input_node->level = HX5_ST_SCHED_LEVEL_GET(unit, cosq); 1854 switch(input_node->level) { 1855 case SOC_HX5_NODE_LVL_L0: 1856 input_node->hw_index = (mmu_port * _HX5_ST_NUML0_NODES) + cosq; 1857 break; 1858 case SOC_HX5_NODE_LVL_L1: 1859 input_node->hw_index = (mmu_port * _HX5_ST_NUML1_NODES) + (cosq - _HX5_ST_NUML0_NODES); 1860 break; 1861 case SOC_HX5_NODE_LVL_L2: 1862 input_node->hw_index = (mmu_port * _HX5_ST_NUML2_NODES) + 1863 (cosq - (_HX5_ST_NUML1_NODES + _HX5_ST_NUML0_NODES)); 1864 break; 1865 default: 1866 return BCM_E_PARAM; 1867 } 1868 } 1869 }else { 1870 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(input_gport)) { 1871 input_node->hw_index = _HX5_BASE_L3QUEUE + ((mmu_port - _BCM_HX5_NUM_ST_PORTS) * 1872 SOC_HX5_NUM_UCAST_QUEUE_PER_PORT) + cosq; 1873 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(input_gport)) { 1874 input_node->hw_index = _HX5_BASE_L3QUEUE + ((mmu_port - _BCM_HX5_NUM_ST_PORTS) * 1875 SOC_HX5_NUM_MCAST_QUEUE_PER_PORT) + cosq; 1876 } else { 1877 input_node->level = HX5_SCHED_LEVEL_GET(unit, cosq); 1878 switch(input_node->level) { 1879 case SOC_HX5_NODE_LVL_L0: 1880 input_node->hw_index = _HX5_BASE_L0QUEUE + ((mmu_port - _BCM_HX5_NUM_ST_PORTS) * 1881 _HX5_NUML0_NODES) + cosq; 1882 break; 1883 case SOC_HX5_NODE_LVL_L1: 1884 input_node->hw_index = _HX5_BASE_L1QUEUE + ((mmu_port - _BCM_HX5_NUM_ST_PORTS) * 1885 _HX5_NUML1_NODES) + (cosq - _HX5_NUML0_NODES); 1886 break; 1887 case SOC_HX5_NODE_LVL_L2: 1888 input_node->hw_index = _HX5_BASE_L2QUEUE + ((mmu_port - _BCM_HX5_NUM_ST_PORTS) * 1889 _HX5_NUML2_NODES) + (cosq - (_HX5_NUML1_NODES + _HX5_NUML0_NODES)); 1890 break; 1891 default: 1892 return BCM_E_PARAM; 1893 } 1894 } 1895 } 1896 1897 if (BCM_GPORT_IS_SCHEDULER(input_gport)) { 1898 if(input_node->level == SOC_HX5_NODE_LVL_L0) { 1899 BCM_IF_ERROR_RETURN 1900 (bcm_esw_port_gport_get(unit, input_port, 1901 &(input_node->parent_gport))); 1902 } else { 1903 input_node->parent_gport = parent_gport; 1904 } 1905 } else if ((BCM_GPORT_IS_UCAST_QUEUE_GROUP(input_gport)) || 1906 (BCM_GPORT_IS_MCAST_QUEUE_GROUP(input_gport))) { 1907 input_node->parent_gport = parent_gport; 1908 } 1909 1910 return BCM_E_NONE; 1911 } 1912 1913 1914 /* 1915 * Function: 1916 * _bcm_hx5_cosq_cpu_gport_detach 1917 * Purpose: 1918 * Detach any of the L3 MC Queue from its parent L2 nodes. 1919 * Post detach, L3 MC queue is attached to Parent L2.9 node 1920 * Parameters: 1921 * unit - (IN) unit number 1922 * input_port - (IN) scheduler GPORT identifier 1923 * parent_port - (IN) GPORT to detach from 1924 * cosq - (IN) COS queue to detach from 1925 * Returns: 1926 * BCM_E_XXX 1927 */ 1928 STATIC int 1929 _bcm_hx5_cosq_cpu_gport_detach(int unit, bcm_gport_t input_gport, 1930 bcm_gport_t parent_gport, bcm_cos_queue_t cosq) 1931 { 1932 bcm_port_t parent_port, input_port; 1933 _bcm_hx5_cosq_node_t *input_node = NULL, *parent_node = NULL; 1934 int input_cos = 0, parent_cos = 0, config_cos = 0; 1935 int index = 0; 1936 1937 /* Post Default tree created, expected Input 1938 * Gport is of MC Gport 1939 * and expected Parent Gport is new L0 1940 * Parent 1941 */ 1942 if ((!BCM_GPORT_IS_SCHEDULER(parent_gport)) || 1943 (!BCM_GPORT_IS_MCAST_QUEUE_GROUP(input_gport))) { 1944 return BCM_E_PARAM; 1945 } 1946 1947 BCM_IF_ERROR_RETURN 1948 (_bcm_hx5_cosq_node_get(unit, input_gport, NULL, &input_port, NULL, 1949 &input_node)); 1950 BCM_IF_ERROR_RETURN 1951 (_bcm_hx5_cosq_node_get(unit, parent_gport, NULL, &parent_port, NULL, 1952 &parent_node)); 1953 1954 if (!IS_CPU_PORT(unit, parent_port)) { 1955 return BCM_E_PARAM; 1956 } 1957 1958 /* Return BCM_E_PARAM when queue to be detached is 1959 not attached to the given gport */ 1960 if (input_node->parent_gport != parent_gport) { 1961 return BCM_E_PARAM; 1962 } 1963 1964 if (BCM_GPORT_IS_SCHEDULER(parent_gport)) { 1965 switch(parent_node->level) { 1966 case SOC_HX5_NODE_LVL_L0: 1967 parent_cos = parent_node->hw_index - _HX5_CPU_LO_NODE_BASE; 1968 break; 1969 case SOC_HX5_NODE_LVL_L1: 1970 parent_cos = parent_node->hw_index - _HX5_CPU_L1_NODE_BASE; 1971 break; 1972 case SOC_HX5_NODE_LVL_L2: 1973 parent_cos = parent_node->hw_index - _HX5_CPU_L2_NODE_BASE; 1974 break; 1975 default: 1976 return BCM_E_PARAM; 1977 } 1978 } 1979 1980 input_cos = cosq % SOC_HX5_NUM_CPU_QUEUES; 1981 1982 if(parent_node->level == SOC_HX5_NODE_LVL_L2) { 1983 BCM_IF_ERROR_RETURN 1984 (_bcm_hx5_cosq_cpu_parent_get(unit, input_cos, SOC_HX5_NODE_LVL_L3, 1985 &config_cos)); 1986 if (config_cos != parent_cos) { 1987 /* Error when detaching from wrong Parent (L0 level) */ 1988 return BCM_E_PARAM; 1989 } 1990 1991 /* 1992 * L2.0 is associated with CMC0 CH1(Rx) 1993 * L2.1 is associated with CMC0 CH2(Rx) 1994 * L2.2 is associated with CMC0 CH3(Rx) 1995 * L2.3 is associated with CMC0 CH4(Rx) 1996 * L2.4 is associated with CMC0 CH5(Rx) 1997 * L2.5 is associated with CMC0 CH6(Rx) 1998 * L2.6 is associated with CMC0 CH7(Rx) 1999 */ 2000 if ((parent_cos >= 0) && (parent_cos < 7)) { 2001 BCM_IF_ERROR_RETURN 2002 (_bcm_hx5_cosq_rx_queue_channel_set(unit, parent_cos, input_cos, 2003 0)); 2004 } 2005 2006 /* Reset parent to L0.9 */ 2007 index = _HX5_CPU_NUML2_NODES; 2008 BCM_IF_ERROR_RETURN 2009 (_bcm_hx5_cosq_cpu_parent_set(unit, input_cos, SOC_HX5_NODE_LVL_L3, index - 1)); 2010 index += 2; 2011 input_node->parent_gport = _BCM_HX5_MMU_INFO(unit)->_bcm_hx5_cpu_port_info-> 2012 sched[index - 1].gport; 2013 } 2014 return BCM_E_NONE; 2015 } 2016 2017 2018 2019 2020 2021 /* 2022 * Function: 2023 * bcm_hx5_cosq_gport_detach 2024 * Purpose: 2025 * Detach sched_port from the specified index (cosq) of input_port 2026 * Parameters: 2027 * unit - (IN) unit number 2028 * input_port - (IN) scheduler GPORT identifier 2029 * parent_port - (IN) GPORT to detach from 2030 * cosq - (IN) COS queue to detach from 2031 * Returns: 2032 * BCM_E_XXX 2033 */ 2034 int 2035 bcm_hx5_cosq_gport_detach(int unit, bcm_gport_t input_gport, 2036 bcm_gport_t parent_gport, bcm_cos_queue_t cosq) 2037 { 2038 _bcm_hx5_cosq_node_t *input_node = NULL, *parent_node = NULL; 2039 bcm_port_t input_port, parent_port; 2040 int input_hw_index = -1, parent_hw_index = -1; 2041 int num_uc, num_mc, num_sc; 2042 int phy_port, mmu_port; 2043 2044 soc_info_t *si = &SOC_INFO(unit); 2045 LOG_INFO(BSL_LS_BCM_COSQ, 2046 (BSL_META_U(unit, 2047 "bcm_hx5_cosq_gport_detach: unit=%d input_gport=0x%x " 2048 "parent_gport=0x%x cosq=%d\n"), 2049 unit, input_gport, parent_gport, cosq)); 2050 2051 if (!(BCM_GPORT_IS_SCHEDULER(input_gport) || 2052 BCM_GPORT_IS_UCAST_QUEUE_GROUP(input_gport) || 2053 BCM_GPORT_IS_MCAST_QUEUE_GROUP(input_gport))) { 2054 return BCM_E_PARAM; 2055 } 2056 2057 BCM_IF_ERROR_RETURN 2058 (_bcm_hx5_cosq_node_get(unit, input_gport, NULL, &input_port, NULL, 2059 &input_node)); 2060 2061 if (!input_node) { 2062 return BCM_E_PARAM; 2063 } 2064 2065 if (_BCM_HX5_MMU_INFO(unit)->gport_tree_created == TRUE) { 2066 if (IS_CPU_PORT(unit, input_port)) { 2067 return _bcm_hx5_cosq_cpu_gport_detach(unit, input_gport, parent_gport, cosq); 2068 } else { 2069 return BCM_E_PARAM; 2070 } 2071 } 2072 2073 phy_port = si->port_l2p_mapping[input_port]; 2074 mmu_port = si->port_p2m_mapping[phy_port]; 2075 2076 if(_HX5_IS_ST_PORT(unit, mmu_port)) { 2077 num_uc = SOC_HX5_NUM_UCAST_QUEUE_PER_ST_PORT; 2078 num_mc = SOC_HX5_NUM_MCAST_QUEUE_PER_ST_PORT; 2079 num_sc = SOC_HX5_NUM_SCHEDULER_PER_ST_PORT; 2080 }else { 2081 num_uc = SOC_HX5_NUM_UCAST_QUEUE_PER_PORT; 2082 num_mc = SOC_HX5_NUM_MCAST_QUEUE_PER_PORT; 2083 num_sc = SOC_HX5_NUM_SCHEDULER_PER_PORT; 2084 } 2085 2086 if (BCM_GPORT_IS_SCHEDULER(parent_gport)) { 2087 BCM_IF_ERROR_RETURN 2088 (_bcm_hx5_cosq_node_get(unit, parent_gport, NULL, &parent_port, NULL, 2089 &parent_node)); 2090 } else { 2091 BCM_IF_ERROR_RETURN 2092 (_bcm_hx5_cosq_localport_resolve(unit, parent_gport, &parent_port)); 2093 parent_node = NULL; 2094 } 2095 2096 if (input_port != parent_port) { 2097 return BCM_E_PARAM; 2098 } 2099 2100 /* HX5 scheduler heirarchy is fixed. Hence check for wrong config. */ 2101 if (parent_node) { 2102 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(input_gport)) { 2103 input_hw_index = input_node->hw_index % num_uc; 2104 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(input_gport)) { 2105 input_hw_index = input_node->hw_index % num_mc; 2106 } else { 2107 input_hw_index = input_node->hw_index % num_sc; 2108 } 2109 2110 if (parent_node->level == SOC_HX5_NODE_LVL_L2) { 2111 parent_hw_index = parent_node->hw_index % num_sc; 2112 2113 if (input_hw_index != parent_hw_index) { 2114 return BCM_E_PARAM; 2115 } 2116 } 2117 } 2118 2119 return BCM_E_NONE; 2120 } 2121 2122 /* 2123 * Function: 2124 * bcm_hx5_cosq_gport_attach_get 2125 * Purpose: 2126 * Get attached status of a scheduler port 2127 * Parameters: 2128 * unit - (IN) unit number 2129 * sched_port - (IN) scheduler GPORT identifier 2130 * input_port - (OUT) GPORT to attach to 2131 * cosq - (OUT) COS queue to attached to 2132 * Returns: 2133 * BCM_E_XXX 2134 */ 2135 int 2136 bcm_hx5_cosq_gport_attach_get(int unit, bcm_gport_t sched_gport, 2137 bcm_gport_t *input_gport, bcm_cos_queue_t *cosq) 2138 { 2139 _bcm_hx5_cosq_node_t *node = NULL; 2140 bcm_port_t local_port = -1; 2141 int phy_port, mmu_port; 2142 int num_uc, num_mc; 2143 2144 soc_info_t *si = &SOC_INFO(unit); 2145 2146 if (!(BCM_GPORT_IS_SET(sched_gport) || 2147 BCM_GPORT_IS_SCHEDULER(sched_gport) || 2148 BCM_GPORT_IS_UCAST_QUEUE_GROUP(sched_gport) || 2149 BCM_GPORT_IS_MCAST_QUEUE_GROUP(sched_gport))) { 2150 return BCM_E_PARAM; 2151 } 2152 2153 BCM_IF_ERROR_RETURN 2154 (_bcm_hx5_cosq_node_get(unit, sched_gport, NULL, &local_port, NULL, 2155 &node)); 2156 2157 if (node == NULL) { 2158 return BCM_E_PARAM; 2159 } 2160 2161 if (local_port < 0) { 2162 return BCM_E_PARAM; 2163 } 2164 2165 phy_port = si->port_l2p_mapping[local_port]; 2166 mmu_port = si->port_p2m_mapping[phy_port]; 2167 2168 if(IS_CPU_PORT(unit, local_port)){ 2169 num_uc = 0; 2170 num_mc = SOC_HX5_NUM_CPU_QUEUES; 2171 }else { 2172 if(_HX5_IS_ST_PORT(unit, mmu_port)) { 2173 num_uc = SOC_HX5_NUM_UCAST_QUEUE_PER_ST_PORT; 2174 num_mc = SOC_HX5_NUM_MCAST_QUEUE_PER_ST_PORT; 2175 }else { 2176 num_uc = SOC_HX5_NUM_UCAST_QUEUE_PER_PORT; 2177 num_mc = SOC_HX5_NUM_MCAST_QUEUE_PER_PORT; 2178 } 2179 } 2180 2181 2182 if (BCM_GPORT_IS_SCHEDULER(sched_gport)) { 2183 switch(node->level) { 2184 case SOC_HX5_NODE_LVL_L0: 2185 if(IS_CPU_PORT(unit, local_port)){ 2186 *cosq = node->hw_index - _HX5_CPU_LO_NODE_BASE; 2187 } else if(_HX5_IS_ST_PORT(unit, mmu_port)){ 2188 *cosq = node->hw_index - (mmu_port * _HX5_ST_NUML0_NODES); 2189 } else { 2190 *cosq = node->hw_index - (_HX5_BASE_L0QUEUE + ((mmu_port - _BCM_HX5_NUM_ST_PORTS) * _HX5_NUML0_NODES)); 2191 } 2192 break; 2193 case SOC_HX5_NODE_LVL_L1: 2194 if(IS_CPU_PORT(unit, local_port)){ 2195 *cosq = node->hw_index - _HX5_CPU_L1_NODE_BASE; 2196 } else if(_HX5_IS_ST_PORT(unit, mmu_port)){ 2197 *cosq = node->hw_index - (mmu_port * _HX5_ST_NUML1_NODES); 2198 } else { 2199 *cosq = node->hw_index - (_HX5_BASE_L1QUEUE + ((mmu_port - _BCM_HX5_NUM_ST_PORTS) * _HX5_NUML1_NODES)); 2200 } 2201 break; 2202 case SOC_HX5_NODE_LVL_L2: 2203 if(IS_CPU_PORT(unit, local_port)){ 2204 *cosq = node->hw_index - _HX5_CPU_L2_NODE_BASE; 2205 } else if(_HX5_IS_ST_PORT(unit, mmu_port)){ 2206 *cosq = node->hw_index - (mmu_port * _HX5_ST_NUML2_NODES); 2207 } else { 2208 *cosq = node->hw_index - (_HX5_BASE_L2QUEUE + ((mmu_port - _BCM_HX5_NUM_ST_PORTS) * _HX5_NUML2_NODES)); 2209 } 2210 break; 2211 default: 2212 return BCM_E_PARAM; 2213 } 2214 } else if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(sched_gport)) { 2215 if(_HX5_IS_ST_PORT(unit, mmu_port)){ 2216 *cosq = node->hw_index - (mmu_port * num_uc); 2217 } else { 2218 *cosq = node->hw_index - (_HX5_BASE_L3QUEUE + ((mmu_port - _BCM_HX5_NUM_ST_PORTS)* num_uc)); 2219 } 2220 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(sched_gport)) { 2221 if(IS_CPU_PORT(unit, local_port)){ 2222 *cosq = node->hw_index - _HX5_CPU_L2_NODE_BASE; 2223 } else if(_HX5_IS_ST_PORT(unit, mmu_port)){ 2224 *cosq = node->hw_index - (mmu_port * num_mc); 2225 } else { 2226 *cosq = node->hw_index - (_HX5_BASE_L3QUEUE + ((mmu_port - _BCM_HX5_NUM_ST_PORTS) * num_mc)); 2227 } 2228 } else { 2229 return BCM_E_PARAM; 2230 } 2231 2232 *input_gport = node->parent_gport; 2233 return BCM_E_NONE; 2234 } 2235 2236 /* 2237 * Function: 2238 * bcm_hx5_cosq_gport_traverse 2239 * Purpose: 2240 * Walks through the valid COSQ GPORTs and calls 2241 * the user supplied callback function for each entry. 2242 * Parameters: 2243 * unit - (IN) unit number 2244 * trav_fn - (IN) Callback function. 2245 * user_data - (IN) User data to be passed to callback function 2246 * Returns: 2247 * BCM_E_NONE - Success. 2248 * BCM_E_XXX 2249 */ 2250 int 2251 bcm_hx5_cosq_gport_traverse(int unit, bcm_cosq_gport_traverse_cb cb, 2252 void *user_data) 2253 { 2254 _bcm_hx5_cosq_port_info_t *port_info = NULL; 2255 _bcm_hx5_cosq_st_port_info_t *stport_info = NULL; 2256 _bcm_hx5_cosq_cpu_port_info_t *cpu_port_info = NULL; 2257 bcm_module_t my_modid, modid_out; 2258 bcm_port_t port, port_out, local_port; 2259 bcm_gport_t gport; 2260 int id, rv = SOC_E_NONE; 2261 int phy_port, mmu_port, index; 2262 2263 soc_info_t *si = &SOC_INFO(unit); 2264 2265 if (_bcm_hx5_cosq_port_info[unit] == NULL) { 2266 return BCM_E_INIT; 2267 } 2268 if (_bcm_hx5_cosq_st_port_info[unit] == NULL) { 2269 return BCM_E_INIT; 2270 } 2271 if (_bcm_hx5_cosq_cpu_port_info[unit] == NULL) { 2272 return BCM_E_INIT; 2273 } 2274 2275 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_modid)); 2276 PBMP_ALL_ITER(unit, port) { 2277 BCM_IF_ERROR_RETURN 2278 (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, my_modid, port, 2279 &modid_out, &port_out)); 2280 BCM_GPORT_MODPORT_SET(gport, modid_out, port_out); 2281 2282 BCM_IF_ERROR_RETURN 2283 (_bcm_hx5_cosq_localport_resolve(unit, port, &local_port)); 2284 2285 phy_port = si->port_l2p_mapping[local_port]; 2286 mmu_port = si->port_p2m_mapping[phy_port]; 2287 _HX5_PORT_INDEX_GET(unit, mmu_port, index); 2288 if (IS_CPU_PORT(unit, local_port)) { 2289 cpu_port_info = _bcm_hx5_cosq_cpu_port_info[unit]; 2290 } else { 2291 if(_HX5_IS_ST_PORT(unit, mmu_port)) { 2292 stport_info = &_bcm_hx5_cosq_st_port_info[unit][index]; 2293 }else { 2294 port_info = &_bcm_hx5_cosq_port_info[unit][index]; 2295 } 2296 } 2297 2298 if (!IS_CPU_PORT(unit, local_port) && !_HX5_IS_ST_PORT(unit, mmu_port)) { 2299 for (id = 0; id < SOC_HX5_NUM_UCAST_QUEUE_PER_PORT; id++) { 2300 if (port_info->ucast[id].numq == 0) { 2301 continue; 2302 } 2303 rv = cb(unit, gport, port_info->ucast[id].numq, 2304 BCM_COSQ_GPORT_UCAST_QUEUE_GROUP, 2305 port_info->ucast[id].gport, user_data); 2306 } 2307 #ifdef BCM_CB_ABORT_ON_ERR 2308 if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) { 2309 return rv; 2310 } 2311 #else 2312 rv = BCM_E_NONE; 2313 #endif 2314 } 2315 2316 if (!IS_CPU_PORT(unit, local_port) && _HX5_IS_ST_PORT(unit, mmu_port)) { 2317 for (id = 0; id < SOC_HX5_NUM_UCAST_QUEUE_PER_ST_PORT; id++) { 2318 if (stport_info->ucast[id].numq == 0) { 2319 continue; 2320 } 2321 rv = cb(unit, gport, stport_info->ucast[id].numq, 2322 BCM_COSQ_GPORT_UCAST_QUEUE_GROUP, 2323 stport_info->ucast[id].gport, user_data); 2324 } 2325 #ifdef BCM_CB_ABORT_ON_ERR 2326 if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) { 2327 return rv; 2328 } 2329 #else 2330 rv = BCM_E_NONE; 2331 #endif 2332 } 2333 2334 if (IS_CPU_PORT(unit, local_port)) { 2335 for (id = 0; id < SOC_HX5_NUM_CPU_QUEUES; id++) { 2336 if (cpu_port_info->mcast[id].numq == 0) { 2337 continue; 2338 } 2339 rv = cb(unit, gport, cpu_port_info->mcast[id].numq, 2340 BCM_COSQ_GPORT_MCAST_QUEUE_GROUP, 2341 cpu_port_info->mcast[id].gport, user_data); 2342 #ifdef BCM_CB_ABORT_ON_ERR 2343 if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) { 2344 return rv; 2345 } 2346 #else 2347 rv = BCM_E_NONE; 2348 #endif 2349 } 2350 } 2351 2352 if (!IS_CPU_PORT(unit, local_port) && !_HX5_IS_ST_PORT(unit, mmu_port)) { 2353 for (id = 0; id < SOC_HX5_NUM_MCAST_QUEUE_PER_PORT; id++) { 2354 if (port_info->mcast[id].numq == 0) { 2355 continue; 2356 } 2357 rv = cb(unit, gport, port_info->mcast[id].numq, 2358 BCM_COSQ_GPORT_MCAST_QUEUE_GROUP, 2359 port_info->mcast[id].gport, user_data); 2360 } 2361 #ifdef BCM_CB_ABORT_ON_ERR 2362 if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) { 2363 return rv; 2364 } 2365 #else 2366 rv = BCM_E_NONE; 2367 #endif 2368 } 2369 2370 2371 if (!IS_CPU_PORT(unit, local_port) && _HX5_IS_ST_PORT(unit, mmu_port)) { 2372 for (id = 0; id < SOC_HX5_NUM_MCAST_QUEUE_PER_ST_PORT; id++) { 2373 if (stport_info->mcast[id].numq == 0) { 2374 continue; 2375 } 2376 rv = cb(unit, gport, stport_info->mcast[id].numq, 2377 BCM_COSQ_GPORT_MCAST_QUEUE_GROUP, 2378 stport_info->mcast[id].gport, user_data); 2379 } 2380 #ifdef BCM_CB_ABORT_ON_ERR 2381 if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) { 2382 return rv; 2383 } 2384 #else 2385 rv = BCM_E_NONE; 2386 #endif 2387 } 2388 2389 2390 if (IS_CPU_PORT(unit, local_port)) { 2391 for (id = 0; id < SOC_HX5_NUM_SCHEDULER_PER_CPU_PORT; id++) { 2392 if (cpu_port_info->sched[id].numq == 0) { 2393 continue; 2394 } 2395 rv = cb(unit, gport, cpu_port_info->sched[id].numq, 2396 BCM_COSQ_GPORT_SCHEDULER, 2397 cpu_port_info->sched[id].gport, user_data); 2398 #ifdef BCM_CB_ABORT_ON_ERR 2399 if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) { 2400 return rv; 2401 } 2402 #else 2403 rv = BCM_E_NONE; 2404 #endif 2405 } 2406 } 2407 2408 if (!IS_CPU_PORT(unit, local_port) && !_HX5_IS_ST_PORT(unit, mmu_port)) { 2409 for (id = 0; id < SOC_HX5_NUM_SCHEDULER_PER_PORT; id++) { 2410 if (port_info->sched[id].numq == 0) { 2411 continue; 2412 } 2413 rv = cb(unit, gport, port_info->sched[id].numq, 2414 BCM_COSQ_GPORT_SCHEDULER, 2415 port_info->sched[id].gport, user_data); 2416 } 2417 #ifdef BCM_CB_ABORT_ON_ERR 2418 if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) { 2419 return rv; 2420 } 2421 #else 2422 rv = BCM_E_NONE; 2423 #endif 2424 } 2425 2426 2427 if (!IS_CPU_PORT(unit, local_port) && _HX5_IS_ST_PORT(unit, mmu_port)) { 2428 for (id = 0; id < SOC_HX5_NUM_SCHEDULER_PER_ST_PORT; id++) { 2429 if (stport_info->sched[id].numq == 0) { 2430 continue; 2431 } 2432 rv = cb(unit, gport, stport_info->sched[id].numq, 2433 BCM_COSQ_GPORT_SCHEDULER, 2434 stport_info->sched[id].gport, user_data); 2435 } 2436 #ifdef BCM_CB_ABORT_ON_ERR 2437 if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) { 2438 return rv; 2439 } 2440 #else 2441 rv = BCM_E_NONE; 2442 #endif 2443 } 2444 2445 } 2446 return rv; 2447 } 2448 2449 STATIC void 2450 _bcm_hx5_gport_numq_get(int unit, int id, int *numq) 2451 { 2452 switch(id) { 2453 case 1: 2454 case 2: 2455 *numq = 1; 2456 break; 2457 case 3: 2458 case 4: 2459 case 5: 2460 *numq = 8; 2461 break; 2462 default: 2463 case 6: 2464 *numq = 2; 2465 break; 2466 } 2467 } 2468 /* 2469 * Function: 2470 * _bcm_hx5_cosq_st_gport_tree_create 2471 * Purpose: 2472 * During cosq init create the default cosq gport tree. 2473 * Schedualar (L0) nodes are created and attach to physical ports. 2474 * UC and MC queues are added and attached to each L0 nodes. 2475 * Parameters: 2476 * unit - (IN) unit number. 2477 * port - (IN) port number 2478 * Returns: 2479 * BCM_E_XXX 2480 */ 2481 STATIC int 2482 _bcm_hx5_cosq_st_gport_tree_create(int unit, bcm_port_t port) 2483 { 2484 int id, sc_id; 2485 bcm_gport_t sched_gport[SOC_HX5_NUM_SCHEDULER_PER_ST_PORT]; 2486 bcm_gport_t uc_gport[SOC_HX5_NUM_UCAST_QUEUE_PER_ST_PORT]; 2487 bcm_gport_t mc_gport[SOC_HX5_NUM_MCAST_QUEUE_PER_ST_PORT]; 2488 int numq = 1; 2489 2490 /*Creating all L0,L1 and L2 scheduler nodes */ 2491 for (id = 0; id < SOC_HX5_NUM_SCHEDULER_PER_ST_PORT; id++) { 2492 _bcm_hx5_gport_numq_get(unit, id, &numq); 2493 BCM_IF_ERROR_RETURN 2494 (_bcm_hx5_cosq_gport_add(unit, port, numq, BCM_COSQ_GPORT_SCHEDULER, 2495 &sched_gport[id])); 2496 } 2497 2498 /* Attaching L0 schedular node to front panel port */ 2499 for (sc_id = 0; sc_id < 3; sc_id++) { 2500 BCM_IF_ERROR_RETURN 2501 (bcm_hx5_cosq_gport_attach(unit, sched_gport[sc_id], port, sc_id)); 2502 } 2503 /* Attaching L1 schedular nodes to l0 Schedular nodes */ 2504 for (sc_id = 3; sc_id < 7; sc_id++) { 2505 if (sc_id == 3) { 2506 BCM_IF_ERROR_RETURN 2507 (bcm_hx5_cosq_gport_attach(unit, sched_gport[sc_id], 2508 sched_gport[0], sc_id)); 2509 } else if (sc_id > 3 && sc_id < 6) { 2510 BCM_IF_ERROR_RETURN 2511 (bcm_hx5_cosq_gport_attach(unit, sched_gport[sc_id], 2512 sched_gport[1], sc_id)); 2513 } else { 2514 BCM_IF_ERROR_RETURN 2515 (bcm_hx5_cosq_gport_attach(unit, sched_gport[sc_id], 2516 sched_gport[2], sc_id)); 2517 } 2518 } 2519 2520 /* Aattaching L2 schedular nodes to l1 Schedular nodes */ 2521 for (sc_id = 7; sc_id < SOC_HX5_NUM_SCHEDULER_PER_ST_PORT; sc_id++) { 2522 if (sc_id < 15) { 2523 BCM_IF_ERROR_RETURN 2524 (bcm_hx5_cosq_gport_attach(unit, sched_gport[sc_id], 2525 sched_gport[3], sc_id)); 2526 } else if((sc_id >= 15) && (sc_id < 23)) { 2527 BCM_IF_ERROR_RETURN 2528 (bcm_hx5_cosq_gport_attach(unit, sched_gport[sc_id], 2529 sched_gport[4], sc_id)); 2530 } else if((sc_id >= 23 ) && (sc_id < 31)) { 2531 BCM_IF_ERROR_RETURN 2532 (bcm_hx5_cosq_gport_attach(unit, sched_gport[sc_id], 2533 sched_gport[5], sc_id)); 2534 } else { 2535 BCM_IF_ERROR_RETURN 2536 (bcm_hx5_cosq_gport_attach(unit, sched_gport[sc_id], 2537 sched_gport[6], sc_id)); 2538 } 2539 } 2540 numq = 1; 2541 /* Creating and attaching l3 uc and l2 mc queues to l2 Schedular nodes */ 2542 for (id = 0, sc_id = 7; id < SOC_HX5_NUM_MCAST_QUEUE_PER_ST_PORT && 2543 sc_id < SOC_HX5_NUM_SCHEDULER_PER_ST_PORT; id++, sc_id++) { 2544 BCM_IF_ERROR_RETURN 2545 (_bcm_hx5_cosq_gport_add(unit, port, numq, 2546 BCM_COSQ_GPORT_UCAST_QUEUE_GROUP, 2547 &uc_gport[id])); 2548 BCM_IF_ERROR_RETURN 2549 (bcm_hx5_cosq_gport_attach(unit, uc_gport[id], 2550 sched_gport[sc_id], id)); 2551 2552 BCM_IF_ERROR_RETURN 2553 (_bcm_hx5_cosq_gport_add(unit, port, numq, 2554 BCM_COSQ_GPORT_MCAST_QUEUE_GROUP, 2555 &mc_gport[id])); 2556 BCM_IF_ERROR_RETURN 2557 (bcm_hx5_cosq_gport_attach(unit, mc_gport[id], 2558 sched_gport[sc_id], id)); 2559 } 2560 return BCM_E_NONE; 2561 } 2562 2563 /* 2564 * Function: 2565 * bcm_hx5_cosq_sched_weight_max_get 2566 * Purpose: 2567 * Retrieve maximum weights for given COS policy 2568 * Parameters: 2569 * unit - (IN) unit number 2570 * mode - (IN) Scheduling mode (BCM_COSQ_xxx) 2571 * weight_max - (OUT) Maximum weight for COS queue. 2572 * Returns: 2573 * BCM_E_XXX 2574 */ 2575 int 2576 bcm_hx5_cosq_sched_weight_max_get(int unit, int mode, int *weight_max) 2577 { 2578 switch (mode) { 2579 case BCM_COSQ_STRICT: 2580 *weight_max = BCM_COSQ_WEIGHT_STRICT; 2581 break; 2582 case BCM_COSQ_ROUND_ROBIN: 2583 case BCM_COSQ_WEIGHTED_ROUND_ROBIN: 2584 case BCM_COSQ_DEFICIT_ROUND_ROBIN: 2585 /* In hx5, weights can be [1, 127] */ 2586 *weight_max = 2587 (1 << soc_mem_field_length(unit, Q_SCHED_L0_WEIGHT_MEMm, 2588 WEIGHTf)) - 1; 2589 break; 2590 default: 2591 return BCM_E_PARAM; 2592 } 2593 2594 return BCM_E_NONE; 2595 } 2596 2597 2598 /* 2599 * Function: 2600 * _bcm_hx5_sched_weight_setget 2601 * Purpose: 2602 * Get/Set weights for given COS policy 2603 * Parameters: 2604 * unit - (IN) unit number 2605 * port - (IN) port number 2606 * level - (IN) node level 2607 * index - (IN) COS queue number 2608 * weights - (OUT) Weights for COS queue. 2609 * mc - (IN) Multicast queue group 2610 * setget - (IN) Set/get flag 2611 * Returns: 2612 * BCM_E_XXX 2613 */ 2614 STATIC int 2615 _bcm_hx5_sched_weight_setget(int unit, int port, int level, int index, 2616 int *weight, int mc, int setget) 2617 { 2618 soc_info_t *si; 2619 soc_mem_t mem = INVALIDm; 2620 uint32 entry[SOC_MAX_MEM_WORDS]; 2621 int pipe; 2622 int phy_port, mmu_port; 2623 2624 si = &SOC_INFO(unit); 2625 pipe = si->port_pipe[port]; 2626 phy_port = si->port_l2p_mapping[port]; 2627 mmu_port = si->port_p2m_mapping[phy_port]; 2628 2629 switch(level) { 2630 case SOC_HX5_NODE_LVL_L0: 2631 mem = Q_SCHED_L0_WEIGHT_MEMm; 2632 if(IS_CPU_PORT(unit, port)) { 2633 index = _HX5_CPU_LO_NODE_BASE; 2634 } else if(_HX5_IS_ST_PORT(unit, mmu_port)){ 2635 index += (mmu_port * _HX5_ST_NUML0_NODES); 2636 } else { 2637 index += _HX5_BASE_L0QUEUE + ((mmu_port - _BCM_HX5_NUM_ST_PORTS) * _HX5_NUML0_NODES); 2638 } 2639 break; 2640 2641 case SOC_HX5_NODE_LVL_L1: 2642 mem = Q_SCHED_L1_WEIGHT_MEMm; 2643 if(IS_CPU_PORT(unit, port)) { 2644 index = _HX5_CPU_L1_NODE_BASE; 2645 } else if(_HX5_IS_ST_PORT(unit, mmu_port)){ 2646 index += (mmu_port * _HX5_ST_NUML1_NODES); 2647 } else { 2648 index += _HX5_BASE_L1QUEUE + ((mmu_port - _BCM_HX5_NUM_ST_PORTS) * _HX5_NUML1_NODES); 2649 } 2650 break; 2651 2652 case SOC_HX5_NODE_LVL_L2: 2653 mem = Q_SCHED_L2_WEIGHT_MEMm; 2654 if(IS_CPU_PORT(unit, port)) { 2655 index = _HX5_CPU_L2_NODE_BASE; 2656 } else if(_HX5_IS_ST_PORT(unit, mmu_port)){ 2657 index += (mmu_port * _HX5_ST_NUML2_NODES); 2658 } else { 2659 index += _HX5_BASE_L2QUEUE + ((mmu_port - _BCM_HX5_NUM_ST_PORTS) * _HX5_NUML2_NODES); 2660 } 2661 break; 2662 2663 case SOC_HX5_NODE_LVL_L3: 2664 mem = Q_SCHED_L3_WEIGHT_MEMm; 2665 if(IS_CPU_PORT(unit, port)) { 2666 index += _HX5_CPU_L2_NODE_BASE; 2667 } else if(_HX5_IS_ST_PORT(unit, mmu_port)){ 2668 index += (mmu_port * SOC_HX5_NUM_UCAST_QUEUE_PER_ST_PORT); 2669 } else { 2670 index += ((mmu_port - _BCM_HX5_NUM_ST_PORTS) * SOC_HX5_NUM_UCAST_QUEUE_PER_PORT); 2671 } 2672 if(mc == 1) { 2673 index += SOC_HX5_NUM_UC_QUEUES_PER_PIPE; 2674 } 2675 break; 2676 default: 2677 return BCM_E_PARAM; 2678 } 2679 2680 mem = SOC_MEM_UNIQUE_ACC(unit, mem)[pipe]; 2681 SOC_IF_ERROR_RETURN 2682 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, index, &entry)); 2683 2684 if (setget == 1) { 2685 soc_mem_field32_set(unit, mem, &entry, WEIGHTf, *weight); 2686 SOC_IF_ERROR_RETURN 2687 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, index, &entry)); 2688 } else { 2689 *weight = soc_mem_field32_get(unit, mem, &entry, WEIGHTf); 2690 } 2691 2692 return BCM_E_NONE; 2693 } 2694 2695 2696 2697 2698 /* 2699 * Function: 2700 * _bcm_hx5_cosq_sched_mode_setget 2701 * Purpose: 2702 * Get/Set scheduling mode 2703 * Parameters: 2704 * unit - (IN) Unit number 2705 * port - (IN) Port number 2706 * level - (IN) Node level 2707 * index - (IN) COS queue number 2708 * mode - (IN/OUT) Scheduling mode (BCM_COSQ_xxx) 2709 * weights - (IN/OUT) Weights for COS queue. 2710 * mc - (IN) Multicast queue group 2711 * setget - (IN) Set/get flag 2712 * Returns: 2713 * BCM_E_XXX 2714 */ 2715 STATIC int 2716 _bcm_hx5_cosq_sched_mode_setget(int unit, bcm_port_t port, int level, int index, 2717 soc_hx5_sched_mode_e *mode, int *weight, int mc, 2718 int setget) 2719 { 2720 soc_reg_t reg; 2721 uint32 fval = 0, rval, wrr_mask; 2722 uint64 rval64; 2723 int parent_index = 0; 2724 int mmu_port, phy_port; 2725 2726 soc_info_t *si = &SOC_INFO(unit); 2727 phy_port = si->port_l2p_mapping[port]; 2728 mmu_port = si->port_p2m_mapping[phy_port]; 2729 2730 if (setget == 1) { 2731 LOG_INFO(BSL_LS_SOC_COSQ, 2732 (BSL_META_U(unit, 2733 "Port:%d L%s%d config : index=%d MODE=%d WT=%d\n"), 2734 port, (level == 0) ? "r" : "", level - 1, index, *mode, 2735 *weight)); 2736 } 2737 2738 2739 2740 /* Selection between SP and WxRR is based on weight property. */ 2741 BCM_IF_ERROR_RETURN 2742 (_bcm_hx5_sched_weight_setget(unit, port, level, index, weight, mc, 2743 setget)); 2744 2745 if ((level == SOC_HX5_NODE_LVL_L1 || level == SOC_HX5_NODE_LVL_L2) && (IS_CPU_PORT(unit, port))) { 2746 return BCM_E_NONE; 2747 } 2748 2749 switch(level) { 2750 case SOC_HX5_NODE_LVL_L0: 2751 reg = IS_CPU_PORT(unit, port) ? Q_SCHED_CPU_PORT_CONFIGr : Q_SCHED_PORT_CONFIGr; 2752 index = 0; 2753 break; 2754 2755 case SOC_HX5_NODE_LVL_L1: 2756 if(_HX5_IS_ST_PORT(unit, mmu_port)) { 2757 reg = Q_SCHED_L0_NODE_CONFIG_HIQr; 2758 index = (index == 0) ? 0 : (index > 0 && index < 3) ? 1 : 2; 2759 } else { 2760 reg = Q_SCHED_L0_NODE_CONFIGr; 2761 index = 0; 2762 } 2763 break; 2764 2765 case SOC_HX5_NODE_LVL_L2: 2766 if(_HX5_IS_ST_PORT(unit, mmu_port)) { 2767 reg = Q_SCHED_L1_NODE_CONFIG_HIQr; 2768 if( index >= 0 && index < 8 ) { 2769 index = 0; 2770 } else if (index >= 8 && index < 16 ){ 2771 index = 1; 2772 } else if (index >= 16 && index < 24 ){ 2773 index = 2; 2774 } else { 2775 index = 3; 2776 } 2777 } else { 2778 reg = Q_SCHED_L1_NODE_CONFIGr; 2779 index = (index >= 0 && index < 8) ? 0 : 1; 2780 } 2781 break; 2782 2783 case SOC_HX5_NODE_LVL_L3: 2784 if (IS_CPU_PORT(unit, port)) { 2785 reg = Q_SCHED_CPU_L2_NODE_CONFIGr; 2786 SOC_IF_ERROR_RETURN 2787 (_bcm_hx5_cosq_cpu_parent_get(unit, index, SOC_HX5_NODE_LVL_L3, 2788 &parent_index)); 2789 index = parent_index; 2790 } else if(_HX5_IS_ST_PORT(unit, mmu_port)) { 2791 reg = Q_SCHED_L2_NODE_CONFIG_HIQ_SPLIT0r; 2792 } else { 2793 reg = Q_SCHED_L2_NODE_CONFIG_NORMQr; 2794 } 2795 break; 2796 default: 2797 return BCM_E_PARAM; 2798 2799 } 2800 2801 if (SOC_REG_IS_64(unit, reg)) { 2802 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, port, 0, &rval64)); 2803 wrr_mask = soc_reg64_field32_get(unit, reg, rval64, ENABLE_WRRf); 2804 } else { 2805 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, port, 0, &rval)); 2806 wrr_mask = soc_reg_field_get(unit, reg, rval, ENABLE_WRRf); 2807 } 2808 2809 if (setget == 1) { 2810 if (*mode == SOC_HX5_SCHED_MODE_WRR) { 2811 fval = 1; 2812 } else if (*mode == SOC_HX5_SCHED_MODE_WERR) { 2813 fval = 0; 2814 } else { 2815 return BCM_E_NONE; 2816 } 2817 2818 wrr_mask &= ~(1 << index); 2819 wrr_mask |= (fval << index); 2820 if (SOC_REG_IS_64(unit, reg)) { 2821 soc_reg64_field32_set(unit, reg, &rval64, ENABLE_WRRf, wrr_mask); 2822 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, port, 0, rval64)); 2823 }else { 2824 soc_reg_field_set(unit, reg, &rval, ENABLE_WRRf, wrr_mask); 2825 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, port, 0, rval)); 2826 } 2827 } else { 2828 if (*weight == 0) { 2829 *mode = SOC_HX5_SCHED_MODE_STRICT; 2830 } else if (wrr_mask & (1 << index)) { 2831 *mode = SOC_HX5_SCHED_MODE_WRR; 2832 } else { 2833 *mode = SOC_HX5_SCHED_MODE_WERR; 2834 } 2835 } 2836 2837 return BCM_E_NONE; 2838 } 2839 2840 2841 /* 2842 * Function: 2843 * _bcm_hx5_cosq_sched_get 2844 * Purpose: 2845 * Get scheduling mode setting 2846 * Parameters: 2847 * unit - (IN) unit number 2848 * gport - (IN) GPORT identifier 2849 * cosq - (IN) COS queue number 2850 * mode - (OUT) Scheduling mode (BCM_COSQ_xxx) 2851 * weights - (OUT) Weights for COS queue. 2852 * Returns: 2853 * BCM_E_XXX 2854 */ 2855 STATIC int 2856 _bcm_hx5_cosq_sched_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 2857 int *mode, int *weight) 2858 { 2859 soc_hx5_sched_mode_e sched_mode; 2860 bcm_port_t local_port; 2861 _bcm_hx5_cosq_node_t *node = NULL; 2862 int lvl = SOC_HX5_NODE_LVL_L2, mc = 0; 2863 2864 2865 if (BCM_GPORT_IS_SET(gport)) { 2866 BCM_IF_ERROR_RETURN 2867 (_bcm_hx5_cosq_node_get(unit, gport, NULL, &local_port, NULL, 2868 &node)); 2869 lvl = node->level; 2870 }else { 2871 BCM_IF_ERROR_RETURN 2872 (_bcm_hx5_cosq_localport_resolve(unit, gport, &local_port)); 2873 2874 } 2875 2876 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 2877 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 2878 mc = BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) ? 1 : 0; 2879 } else if (IS_CPU_PORT(unit, local_port)) { 2880 mc = 1; 2881 lvl = SOC_HX5_NODE_LVL_L3; 2882 } 2883 2884 BCM_IF_ERROR_RETURN 2885 (_bcm_hx5_cosq_sched_mode_setget(unit, local_port, lvl, cosq, 2886 &sched_mode, weight, mc, 0)); 2887 2888 switch(sched_mode) { 2889 case SOC_HX5_SCHED_MODE_STRICT: 2890 *mode = BCM_COSQ_STRICT; 2891 break; 2892 2893 case SOC_HX5_SCHED_MODE_WRR: 2894 *mode = BCM_COSQ_WEIGHTED_ROUND_ROBIN; 2895 break; 2896 2897 case SOC_HX5_SCHED_MODE_WERR: 2898 *mode = BCM_COSQ_DEFICIT_ROUND_ROBIN; 2899 break; 2900 2901 default: 2902 return BCM_E_INTERNAL; 2903 } 2904 2905 return BCM_E_NONE; 2906 } 2907 2908 /* 2909 * Function: 2910 * bcm_hx5_cosq_gport_sched_get 2911 * Purpose: 2912 * Get COS queue schedular setting 2913 * Parameters: 2914 * unit - (IN) unit number 2915 * gport - (IN) GPORT identifier 2916 * cosq - (IN) COS queue to get, -1 for any queue 2917 * mode - (OUT) Scheduling mode (BCM_COSQ_xxx) 2918 * weights - (OUT) Weights for COS queue. 2919 * Returns: 2920 * BCM_E_XXX 2921 */ 2922 int 2923 bcm_hx5_cosq_gport_sched_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 2924 int *mode, int *weight) 2925 { 2926 int local_port = -1; 2927 soc_info_t *si = &SOC_INFO(unit); 2928 2929 if (BCM_GPORT_IS_SET(gport)) { 2930 if ((BCM_GPORT_IS_SCHEDULER(gport)) || 2931 BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 2932 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 2933 2934 BCM_IF_ERROR_RETURN 2935 (_bcm_hx5_cosq_node_hw_index_get(unit, gport, &cosq)); 2936 2937 BCM_IF_ERROR_RETURN 2938 (_bcm_hx5_cosq_sched_get(unit, gport, cosq, mode, weight)); 2939 return BCM_E_NONE; 2940 } else { 2941 BCM_IF_ERROR_RETURN 2942 (_bcm_hx5_cosq_localport_resolve(unit, gport, &local_port)); 2943 2944 if ((cosq < 0) || (cosq >= si->port_num_cosq[local_port])) { 2945 return BCM_E_PARAM; 2946 } 2947 2948 BCM_IF_ERROR_RETURN 2949 (_bcm_hx5_cosq_sched_get(unit, local_port, cosq, mode, weight)); 2950 return BCM_E_NONE; 2951 } 2952 } else { 2953 return BCM_E_PORT; 2954 } 2955 2956 return BCM_E_NOT_FOUND; 2957 } 2958 2959 2960 /* 2961 * Function: 2962 * bcm_hx5_cosq_port_sched_get 2963 * Purpose: 2964 * Retrieve class-of-service policy and corresponding weights and delay 2965 * Parameters: 2966 * unit - (IN) unit number 2967 * pbm - (IN) port bitmap 2968 * mode - (OUT) Scheduling mode (BCM_COSQ_xxx) 2969 * weights - (OUT) Weights for each COS queue. 2970 * delay - This parameter is not used 2971 * Returns: 2972 * BCM_E_XXX 2973 */ 2974 int 2975 bcm_hx5_cosq_port_sched_get(int unit, bcm_pbmp_t pbm, int *mode, int *weights, 2976 int *delay) 2977 { 2978 bcm_port_t port; 2979 int num_weights, i; 2980 2981 BCM_PBMP_ITER(pbm, port) { 2982 if (IS_CPU_PORT(unit, port) && SOC_PBMP_NEQ(pbm, PBMP_CMIC(unit))) { 2983 continue; 2984 } 2985 num_weights = _BCM_HX5_NUM_COS(unit); 2986 for (i = 0; i < num_weights; i++) { 2987 BCM_IF_ERROR_RETURN( 2988 _bcm_hx5_cosq_sched_get(unit, port, i, mode, &weights[i])); 2989 } 2990 } 2991 2992 return BCM_E_NONE; 2993 } 2994 2995 2996 2997 2998 /* 2999 * Function: 3000 * _bcm_hx5_cosq_sched_set 3001 * Purpose: 3002 * Set scheduling mode 3003 * Parameters: 3004 * unit - (IN) unit number 3005 * gport - (IN) GPORT identifier 3006 * cosq - (IN) COS queue number 3007 * mode - (IN) Scheduling mode (BCM_COSQ_xxx) 3008 * weights - (IN) Weight for COS queue. 3009 * Returns: 3010 * BCM_E_XXX 3011 */ 3012 STATIC int 3013 _bcm_hx5_cosq_sched_set(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 3014 int mode, int weight) 3015 { 3016 soc_hx5_sched_mode_e sched_mode; 3017 _bcm_hx5_cosq_node_t *node = NULL; 3018 bcm_port_t local_port; 3019 int lwts = 1, child_index=0, lvl = SOC_HX5_NODE_LVL_L2, mc = 0; 3020 3021 if (cosq < 0) { 3022 if (cosq == -1) { 3023 /* caller needs to resolve the wild card value (-1) */ 3024 return BCM_E_INTERNAL; 3025 } else { 3026 return BCM_E_PARAM; 3027 } 3028 } 3029 3030 if ((weight < 0) || (weight > 127)) { 3031 return BCM_E_PARAM; 3032 } 3033 3034 switch(mode) { 3035 case BCM_COSQ_STRICT: 3036 sched_mode = SOC_HX5_SCHED_MODE_STRICT; 3037 lwts = 0; 3038 break; 3039 case BCM_COSQ_ROUND_ROBIN: 3040 sched_mode = SOC_HX5_SCHED_MODE_WRR; 3041 lwts = 1; 3042 break; 3043 case BCM_COSQ_WEIGHTED_ROUND_ROBIN: 3044 sched_mode = SOC_HX5_SCHED_MODE_WRR; 3045 lwts = weight; 3046 break; 3047 case BCM_COSQ_DEFICIT_ROUND_ROBIN: 3048 sched_mode = SOC_HX5_SCHED_MODE_WERR; 3049 lwts = weight; 3050 break; 3051 default: 3052 return BCM_E_PARAM; 3053 } 3054 3055 /* Weight = 0 corresponds to Strict Mode */ 3056 if (lwts == 0) { 3057 sched_mode = SOC_HX5_SCHED_MODE_STRICT; 3058 } 3059 3060 if(BCM_GPORT_IS_SET(gport)) { 3061 BCM_IF_ERROR_RETURN 3062 (_bcm_hx5_cosq_node_get(unit, gport, NULL, &local_port, NULL, 3063 &node)); 3064 lvl = node->level; 3065 } else { 3066 BCM_IF_ERROR_RETURN(_bcm_hx5_cosq_localport_resolve(unit, gport, 3067 &local_port)); 3068 3069 } 3070 3071 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 3072 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 3073 mc = BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) ? 1 : 0; 3074 } else if (IS_CPU_PORT(unit, local_port)) { 3075 mc = 1; 3076 lvl = SOC_HX5_NODE_LVL_L3; 3077 } 3078 3079 child_index = cosq; 3080 BCM_IF_ERROR_RETURN(_bcm_hx5_cosq_sched_mode_setget(unit, local_port, lvl, 3081 child_index, &sched_mode, &lwts, mc, 1)); 3082 3083 return BCM_E_NONE; 3084 } 3085 3086 3087 3088 3089 3090 /* 3091 * Function: 3092 * bcm_hx5_cosq_gport_sched_set 3093 * Purpose: 3094 * Set up class-of-service policy and corresponding weights 3095 * Parameters: 3096 * unit - (IN) unit number 3097 * gport - (IN) GPORT identifier 3098 * cosq - (IN) COS queue to get 3099 * mode - (IN) Scheduling mode (BCM_COSQ_xxx) 3100 * weight - (IN) Weight for COS queue. 3101 * Returns: 3102 * BCM_E_XXX 3103 */ 3104 int 3105 bcm_hx5_cosq_gport_sched_set(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 3106 int mode, int weight) 3107 { 3108 soc_info_t *si = &SOC_INFO(unit); 3109 int local_port = -1; 3110 3111 if (BCM_GPORT_IS_SET(gport)) { 3112 if (BCM_GPORT_IS_SCHEDULER(gport) || 3113 BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 3114 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 3115 3116 BCM_IF_ERROR_RETURN 3117 (_bcm_hx5_cosq_node_hw_index_get(unit, gport, &cosq)); 3118 3119 BCM_IF_ERROR_RETURN 3120 (_bcm_hx5_cosq_sched_set(unit, gport, cosq, mode, weight)); 3121 return BCM_E_NONE; 3122 3123 } else { 3124 BCM_IF_ERROR_RETURN(_bcm_hx5_cosq_localport_resolve(unit, gport, 3125 &local_port)); 3126 3127 if ((cosq < 0) || (cosq >= si->port_num_cosq[local_port])) { 3128 return BCM_E_PARAM; 3129 } 3130 3131 BCM_IF_ERROR_RETURN 3132 (_bcm_hx5_cosq_sched_set(unit, local_port, cosq, mode, weight)); 3133 return BCM_E_NONE; 3134 } 3135 } else { 3136 return BCM_E_PORT; 3137 } 3138 3139 return BCM_E_NOT_FOUND; 3140 } 3141 3142 /* 3143 * Function: 3144 * bcm_hx5_cosq_port_sched_set 3145 * Purpose: 3146 * Set up class-of-service policy and corresponding weights and delay 3147 * Parameters: 3148 * unit - (IN) unit number 3149 * pbm - (IN) port bitmap 3150 * mode - (IN) Scheduling mode (BCM_COSQ_xxx) 3151 * weight - (IN) Weight for each COS queue. 3152 * delay - This parameter is not used 3153 * Returns: 3154 * BCM_E_XXX 3155 */ 3156 int 3157 bcm_hx5_cosq_port_sched_set(int unit, bcm_pbmp_t pbm, int mode, const int 3158 *weights, int delay) 3159 { 3160 bcm_port_t port; 3161 int num_weights, i = 0; 3162 int phy_port, mmu_port; 3163 3164 soc_info_t *si = &SOC_INFO(unit); 3165 3166 BCM_PBMP_ITER(pbm, port) { 3167 num_weights = _BCM_HX5_NUM_COS(unit); 3168 phy_port = si->port_l2p_mapping[port]; 3169 mmu_port = si->port_p2m_mapping[phy_port]; 3170 for (i = 0; i < num_weights; i++) { 3171 BCM_IF_ERROR_RETURN 3172 (_bcm_hx5_cosq_sched_set(unit, port, i, mode, weights[i])); 3173 3174 if(!IS_CPU_PORT(unit, port)) { 3175 BCM_IF_ERROR_RETURN 3176 (_bcm_hx5_cosq_sched_set(unit, port, i + 8, mode, weights[i])); 3177 3178 if (_HX5_IS_ST_PORT(unit, mmu_port)) { 3179 BCM_IF_ERROR_RETURN 3180 (_bcm_hx5_cosq_sched_set(unit, port, i + 16, mode, weights[i])); 3181 } 3182 } 3183 } 3184 } 3185 3186 return BCM_E_NONE; 3187 } 3188 3189 3190 /* 3191 * Function: 3192 * _bcm_hx5_cosq_sched_config_port 3193 * Purpose: 3194 * Set scheduler Configuration for the specified port 3195 * Parameters: 3196 * unit - (IN) unit number. 3197 * port - (IN) port number. 3198 * Returns: 3199 * BCM_E_XXX 3200 */ 3201 STATIC int 3202 _bcm_hx5_cosq_sched_config_port(int unit, int port, int mode, int weight) 3203 { 3204 _bcm_hx5_cosq_port_info_t *port_info = NULL; 3205 _bcm_hx5_cosq_st_port_info_t *stport_info = NULL; 3206 int phy_port, mmu_port, i, index; 3207 3208 soc_info_t *si = &SOC_INFO(unit); 3209 phy_port = si->port_l2p_mapping[port]; 3210 mmu_port = si->port_p2m_mapping[phy_port]; 3211 _HX5_PORT_INDEX_GET(unit, mmu_port, index); 3212 3213 if (_HX5_IS_ST_PORT(unit, mmu_port)) { 3214 stport_info = &_bcm_hx5_cosq_st_port_info[unit][index]; 3215 3216 for (i = 0; i < SOC_HX5_NUM_SCHEDULER_PER_ST_PORT; i++) { 3217 BCM_IF_ERROR_RETURN 3218 (bcm_hx5_cosq_gport_sched_set(unit, stport_info->sched[i].gport, 3219 -1, mode, weight)); 3220 } 3221 for (i = 0; i < SOC_HX5_NUM_UCAST_QUEUE_PER_ST_PORT; i++) { 3222 BCM_IF_ERROR_RETURN 3223 (bcm_hx5_cosq_gport_sched_set(unit, stport_info->ucast[i].gport, 3224 -1, mode, weight)); 3225 } 3226 for (i = 0; i < SOC_HX5_NUM_MCAST_QUEUE_PER_ST_PORT; i++) { 3227 BCM_IF_ERROR_RETURN 3228 (bcm_hx5_cosq_gport_sched_set(unit, stport_info->mcast[i].gport, 3229 -1, mode, weight)); 3230 } 3231 } else { 3232 port_info = &_bcm_hx5_cosq_port_info[unit][index]; 3233 3234 for (i = 0; i < SOC_HX5_NUM_SCHEDULER_PER_PORT; i++) { 3235 BCM_IF_ERROR_RETURN 3236 (bcm_hx5_cosq_gport_sched_set(unit, port_info->sched[i].gport, 3237 -1, mode, weight)); 3238 } 3239 for (i = 0; i < SOC_HX5_NUM_UCAST_QUEUE_PER_PORT; i++) { 3240 BCM_IF_ERROR_RETURN 3241 (bcm_hx5_cosq_gport_sched_set(unit, port_info->ucast[i].gport, 3242 -1, mode, weight)); 3243 } 3244 for (i = 0; i < SOC_HX5_NUM_MCAST_QUEUE_PER_PORT; i++) { 3245 BCM_IF_ERROR_RETURN 3246 (bcm_hx5_cosq_gport_sched_set(unit, port_info->mcast[i].gport, 3247 -1, mode, weight)); 3248 } 3249 } 3250 3251 return BCM_E_NONE; 3252 } 3253 3254 /* 3255 * Function: 3256 * _bcm_hx5_cosq_sched_default_config 3257 * Purpose: 3258 * Set Default Scheduler Configuration for all the ports 3259 * Parameters: 3260 * unit - (IN) unit number. 3261 * Returns: 3262 * BCM_E_XXX 3263 */ 3264 STATIC int 3265 _bcm_hx5_cosq_sched_default_config(int unit) 3266 { 3267 _bcm_hx5_cosq_cpu_port_info_t *cpu_port_info = NULL; 3268 bcm_port_t port; 3269 int default_mode = BCM_COSQ_WEIGHTED_ROUND_ROBIN, default_weight = 1; 3270 int i; 3271 3272 port = 0; 3273 cpu_port_info = &_bcm_hx5_cosq_cpu_port_info[unit][port]; 3274 for (i = 0; i < SOC_HX5_NUM_SCHEDULER_PER_CPU_PORT; i++) { 3275 BCM_IF_ERROR_RETURN 3276 (bcm_hx5_cosq_gport_sched_set(unit, cpu_port_info->sched[i].gport, 3277 -1, default_mode, default_weight)); 3278 } 3279 for (i = 0; i < SOC_HX5_NUM_CPU_QUEUES; i++) { 3280 BCM_IF_ERROR_RETURN 3281 (bcm_hx5_cosq_gport_sched_set(unit, cpu_port_info->mcast[i].gport, 3282 -1, default_mode, default_weight)); 3283 } 3284 3285 PBMP_ALL_ITER(unit, port) { 3286 if (IS_CPU_PORT(unit, port) || IS_LB_PORT(unit, port) || IS_FAE_PORT(unit, port)) { 3287 continue; 3288 } 3289 BCM_IF_ERROR_RETURN 3290 (_bcm_hx5_cosq_sched_config_port(unit, port, default_mode, 3291 default_weight)); 3292 } 3293 3294 return BCM_E_NONE; 3295 } 3296 3297 3298 3299 3300 3301 STATIC int 3302 _bcm_hx5_cosq_gport_default_config(int unit) 3303 { 3304 BCM_IF_ERROR_RETURN 3305 (_bcm_hx5_cosq_sched_default_config(unit)); 3306 3307 return BCM_E_NONE; 3308 } 3309 3310 3311 /**************** 3312 * BST Support 3313 */ 3314 3315 3316 STATIC int 3317 _bcm_hx5_cosq_egress_sp_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 3318 int *p_pool_start, int *p_pool_end) 3319 { 3320 int local_port; 3321 int pool; 3322 3323 if (cosq == BCM_COS_INVALID) { 3324 if (p_pool_start && p_pool_end) { 3325 *p_pool_start = 0; 3326 *p_pool_end = 3; 3327 return BCM_E_NONE; 3328 } else { 3329 return BCM_E_PARAM; 3330 } 3331 } 3332 3333 BCM_IF_ERROR_RETURN 3334 (_bcm_hx5_cosq_index_resolve(unit, gport, cosq, 3335 _BCM_HX5_COSQ_INDEX_STYLE_EGR_POOL, 3336 &local_port, &pool, NULL)); 3337 3338 if (p_pool_start) { 3339 *p_pool_start = pool; 3340 } 3341 if (p_pool_end) { 3342 *p_pool_end = pool; 3343 } 3344 return BCM_E_NONE; 3345 } 3346 /* 3347 * Function: 3348 * _bcm_hx5_cosq_index_resolve 3349 * Purpose: 3350 * Find hardware index for the given port/cosq 3351 * Parameters: 3352 * unit - (IN) unit number 3353 * port - (IN) port number or GPORT identifier 3354 * cosq - (IN) COS queue number 3355 * style - (IN) index style (_BCM_KA_COSQ_INDEX_STYLE_XXX) 3356 * local_port - (OUT) local port number 3357 * index - (OUT) result index 3358 * count - (OUT) number of index 3359 * Returns: 3360 * BCM_E_XXX 3361 */ 3362 int 3363 _bcm_hx5_cosq_index_resolve(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 3364 _bcm_hx5_cosq_index_style_t style, 3365 bcm_port_t *local_port, int *index, int *count) 3366 { 3367 bcm_port_t resolved_port; 3368 soc_info_t *si; 3369 int resolved_index = -1; 3370 int id, startq, numq = 0; 3371 int pipe; 3372 int uc_base = 0, mc_base = 0, cpu_mc_base; /* Q base number */ 3373 int mmu_port, phy_port; 3374 3375 _bcm_hx5_cosq_node_t *node; 3376 uint32 entry0[SOC_MAX_MEM_WORDS]; 3377 soc_mem_t mem; 3378 3379 si = &SOC_INFO(unit); 3380 3381 if (cosq < -1) { 3382 return BCM_E_PARAM; 3383 } else if (cosq == -1) { 3384 startq = 0; 3385 numq = NUM_COS(unit); 3386 } else { 3387 startq = cosq; 3388 numq = 1; 3389 } 3390 3391 3392 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 3393 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) || 3394 BCM_GPORT_IS_SCHEDULER(port)) { 3395 BCM_IF_ERROR_RETURN 3396 (_bcm_hx5_cosq_node_get(unit, port, NULL, &resolved_port, &id, 3397 &node)); 3398 if (resolved_port < 0) { 3399 return BCM_E_PORT; 3400 } 3401 } else { 3402 BCM_IF_ERROR_RETURN 3403 (_bcm_hx5_cosq_localport_resolve(unit, port, &resolved_port)); 3404 if (resolved_port < 0) { 3405 return BCM_E_PORT; 3406 } 3407 node = NULL; 3408 numq = (IS_CPU_PORT(unit, resolved_port)) ? NUM_CPU_COSQ(unit) : NUM_COS(unit); 3409 } 3410 phy_port = si->port_l2p_mapping[resolved_port]; 3411 mmu_port = si->port_p2m_mapping[phy_port]; 3412 mc_base = si->port_cosq_base[resolved_port]; 3413 uc_base = si->port_uc_cosq_base[resolved_port]; 3414 3415 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, resolved_port, &pipe)); 3416 3417 switch (style) { 3418 case _BCM_HX5_COSQ_INDEX_STYLE_WRED_DEVICE: 3419 if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 3420 return BCM_E_PARAM; 3421 } 3422 if ((port == -1) || (cosq == -1)) { 3423 numq = _HX5_MMU_NUM_POOL; /* 4 Global Service Pools */ 3424 resolved_index = _HX5_WRED_PER_PIPE_GLOBAL_SP_BASE; 3425 } else { 3426 BCM_IF_ERROR_RETURN 3427 (_bcm_hx5_cosq_egress_sp_get(unit, port, cosq, 3428 &resolved_index, 3429 NULL)); 3430 numq = 1; 3431 resolved_index += _HX5_WRED_PER_PIPE_GLOBAL_SP_BASE; 3432 } 3433 break; 3434 3435 case _BCM_HX5_COSQ_INDEX_STYLE_WRED_PORT: 3436 if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 3437 return BCM_E_PARAM; 3438 } 3439 resolved_index = 0; 3440 if (cosq != -1) { 3441 BCM_IF_ERROR_RETURN 3442 (_bcm_hx5_cosq_egress_sp_get(unit, port, cosq, 3443 &resolved_index, 3444 NULL)); 3445 } 3446 resolved_index += _HX5_WRED_PER_PIPE_PORT_SP_BASE + 3447 (mmu_port * 4); 3448 numq = (cosq == -1) ? 4: 1; 3449 break; 3450 3451 case _BCM_HX5_COSQ_INDEX_STYLE_WRED_QUEUE: 3452 if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 3453 return BCM_E_PARAM; 3454 } 3455 if (node) { 3456 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) { 3457 resolved_index = node->hw_index; 3458 } else { 3459 return BCM_E_PARAM; 3460 } 3461 } else { 3462 resolved_index = uc_base; 3463 if (cosq != -1) { 3464 numq = si->port_num_cosq[resolved_port]; 3465 if (cosq >= numq) { 3466 return BCM_E_PARAM; 3467 } 3468 resolved_index += cosq; 3469 } 3470 numq = (cosq == -1) ? NUM_COS(unit): 1; 3471 } 3472 break; 3473 3474 case _BCM_HX5_COSQ_INDEX_STYLE_EGR_POOL: 3475 if ((node != NULL) && (!BCM_GPORT_IS_MODPORT(port))) { 3476 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) { 3477 /* regular unicast queue */ 3478 resolved_index = node->hw_index ; 3479 mem = MMU_THDU_Q_TO_QGRP_MAPm; 3480 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 3481 resolved_index = node->hw_index ; 3482 mem = MMU_THDM_MCQE_QUEUE_CONFIGm; 3483 } else { /* scheduler */ 3484 return BCM_E_PARAM; 3485 } 3486 } else { /* node == NULL */ 3487 /* PGA check this else part for uc index based on port type 3488 icaluclation */ 3489 numq = si->port_num_cosq[resolved_port]; 3490 if (startq >= numq) { 3491 return BCM_E_PARAM; 3492 } 3493 resolved_index = uc_base + startq; 3494 mem = MMU_THDU_Q_TO_QGRP_MAPm; 3495 } 3496 mem = SOC_MEM_UNIQUE_ACC(unit, mem)[pipe]; 3497 3498 SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, resolved_index, 3499 entry0)); 3500 resolved_index = soc_mem_field32_get(unit, mem, entry0, Q_SPIDf); 3501 break; 3502 3503 case _BCM_HX5_COSQ_INDEX_STYLE_UCAST_QUEUE: 3504 /* Return hw_index for given unicast queue gport */ 3505 if (node) { 3506 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) { 3507 resolved_index = node->hw_index; 3508 } else { 3509 return BCM_E_PARAM; 3510 } 3511 } else { 3512 numq = si->port_num_cosq[resolved_port]; 3513 if ((startq >= numq) || (IS_LB_PORT(unit, resolved_port))) { 3514 return BCM_E_PARAM; 3515 } 3516 resolved_index = uc_base + startq; 3517 } 3518 break; 3519 case _BCM_HX5_COSQ_INDEX_STYLE_MCAST_QUEUE: 3520 /* Return hw_index for given multicast queue gport */ 3521 if (node) { 3522 if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 3523 resolved_index = node->hw_index; 3524 } else { 3525 return BCM_E_PARAM; 3526 } 3527 } else { 3528 if (startq >= numq) { 3529 return BCM_E_PARAM; 3530 } 3531 resolved_index = mc_base + startq; 3532 } 3533 break; 3534 case _BCM_HX5_COSQ_INDEX_STYLE_COS: 3535 if (node) { 3536 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) { 3537 resolved_index = node->hw_index; 3538 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 3539 if (IS_CPU_PORT(unit, resolved_port)) { 3540 cpu_mc_base = si->port_cosq_base[CMIC_PORT(unit)]; 3541 resolved_index = (node->hw_index - cpu_mc_base) % 3542 NUM_CPU_COSQ(unit); 3543 } else { 3544 resolved_index = node->hw_index; 3545 } 3546 } else { 3547 resolved_index = node->hw_index; 3548 } 3549 } else { 3550 resolved_index = startq; 3551 } 3552 break; 3553 default: 3554 return BCM_E_PARAM; 3555 } 3556 3557 if (index) { 3558 *index = resolved_index; 3559 } 3560 if (local_port) { 3561 *local_port = resolved_port; 3562 } 3563 if (count) { 3564 *count = (cosq == -1) ? numq : 1; 3565 } 3566 3567 return BCM_E_NONE; 3568 } 3569 3570 STATIC int 3571 _bcm_hx5_cosq_bst_map_resource_to_gport_cos(int unit, 3572 bcm_bst_stat_id_t bid, int port, int index, bcm_gport_t *gport, 3573 bcm_cos_t *cosq) 3574 { 3575 soc_info_t *si = &SOC_INFO(unit); 3576 _bcm_bst_resource_info_t *pres = NULL; 3577 int phy_port = 0; 3578 int mmu_port = 0; 3579 int stats_per_inst = 1; 3580 int stats_per_pipe = 1; 3581 3582 if (bid >= bcmBstStatIdMaxCount) { 3583 LOG_INFO(BSL_LS_BCM_COSQ, 3584 (BSL_META_U(unit, 3585 "_bcm_th_cosq_bst_map_resource_to_gport_cos: unit=%d bid=0x%x\n"), 3586 unit, bid)); 3587 return BCM_E_NONE; 3588 } 3589 3590 pres = _BCM_BST_RESOURCE(unit, bid); 3591 stats_per_inst = (pres->num_stat_pp) / (pres->num_instance); 3592 index %= stats_per_inst; 3593 if (pres->flags & _BCM_BST_CMN_RES_F_PIPED) { 3594 stats_per_pipe = stats_per_inst / NUM_PIPE(unit); 3595 index %= stats_per_pipe; 3596 } 3597 3598 switch (bid) { 3599 case bcmBstStatIdDevice: 3600 *gport = -1; 3601 *cosq = BCM_COS_INVALID; 3602 break; 3603 3604 case bcmBstStatIdIngPool: 3605 case bcmBstStatIdEgrPool: 3606 case bcmBstStatIdEgrMCastPool: 3607 case bcmBstStatIdRQEPool: 3608 *gport = -1; 3609 *cosq = index % _HX5_MMU_NUM_POOL; 3610 break; 3611 3612 case bcmBstStatIdRQEQueue: 3613 *gport = -1; 3614 *cosq = index % _HX5_MMU_NUM_RQE_QUEUES; 3615 break; 3616 3617 case bcmBstStatIdUCQueueGroup: 3618 mmu_port = index; 3619 phy_port = si->port_m2p_mapping[mmu_port]; 3620 *gport = si->port_p2l_mapping[phy_port]; 3621 *cosq = -1; 3622 break; 3623 3624 case bcmBstStatIdPortPool: 3625 mmu_port= index/_HX5_MMU_NUM_POOL; 3626 phy_port = si->port_m2p_mapping[mmu_port]; 3627 *gport = si->port_p2l_mapping[phy_port]; 3628 *cosq = index % _HX5_MMU_NUM_POOL; 3629 break; 3630 3631 case bcmBstStatIdPriGroupHeadroom: 3632 case bcmBstStatIdPriGroupShared: 3633 mmu_port = index/_HX5_MMU_NUM_PG; 3634 phy_port = si->port_m2p_mapping[mmu_port]; 3635 *gport = si->port_p2l_mapping[phy_port]; 3636 *cosq = index % _HX5_MMU_NUM_PG; 3637 break; 3638 3639 case bcmBstStatIdUcast: 3640 case bcmBstStatIdMcast: 3641 if (index < SOC_HX5_DOWNLINK_PORTQ_BASE) { 3642 mmu_port = index / 26; 3643 } else { 3644 mmu_port = ((index - SOC_HX5_DOWNLINK_PORTQ_BASE) / 16) + 16; 3645 } 3646 if ((bid == bcmBstStatIdMcast) && 3647 (index >= si->port_cosq_base[CMIC_PORT(unit)])) { 3648 *gport = CMIC_PORT(unit); 3649 *cosq = index - si->port_cosq_base[CMIC_PORT(unit)]; 3650 } else { 3651 phy_port = si->port_m2p_mapping[mmu_port]; 3652 *gport = si->port_p2l_mapping[phy_port]; 3653 *cosq = index - si->port_uc_cosq_base[*gport]; 3654 } 3655 break; 3656 case bcmBstStatIdEgrPortPoolSharedUcast: 3657 case bcmBstStatIdEgrPortPoolSharedMcast: 3658 mmu_port = index/_HX5_MMU_NUM_POOL; 3659 phy_port = si->port_m2p_mapping[mmu_port]; 3660 *gport = si->port_p2l_mapping[phy_port]; 3661 *cosq = index % _HX5_MMU_NUM_POOL; 3662 break; 3663 default: 3664 break; 3665 } 3666 3667 return BCM_E_NONE; 3668 } 3669 3670 3671 int 3672 _bcm_hx5_cosq_pfc_class_resolve(bcm_switch_control_t sctype, int *type, 3673 int *class) 3674 { 3675 switch (sctype) { 3676 case bcmSwitchPFCClass7Queue: 3677 case bcmSwitchPFCClass6Queue: 3678 case bcmSwitchPFCClass5Queue: 3679 case bcmSwitchPFCClass4Queue: 3680 case bcmSwitchPFCClass3Queue: 3681 case bcmSwitchPFCClass2Queue: 3682 case bcmSwitchPFCClass1Queue: 3683 case bcmSwitchPFCClass0Queue: 3684 *type = _BCM_HX5_COSQ_TYPE_UCAST; 3685 break; 3686 case bcmSwitchPFCClass7McastQueue: 3687 case bcmSwitchPFCClass6McastQueue: 3688 case bcmSwitchPFCClass5McastQueue: 3689 case bcmSwitchPFCClass4McastQueue: 3690 case bcmSwitchPFCClass3McastQueue: 3691 case bcmSwitchPFCClass2McastQueue: 3692 case bcmSwitchPFCClass1McastQueue: 3693 case bcmSwitchPFCClass0McastQueue: 3694 *type = _BCM_HX5_COSQ_TYPE_MCAST; 3695 break; 3696 default: 3697 /* Unsupported Switch Control types should return E_UNAVAIL */ 3698 return BCM_E_UNAVAIL; 3699 } 3700 3701 switch (sctype) { 3702 case bcmSwitchPFCClass7Queue: 3703 case bcmSwitchPFCClass7McastQueue: 3704 *class = 7; 3705 break; 3706 case bcmSwitchPFCClass6Queue: 3707 case bcmSwitchPFCClass6McastQueue: 3708 *class = 6; 3709 break; 3710 case bcmSwitchPFCClass5Queue: 3711 case bcmSwitchPFCClass5McastQueue: 3712 *class = 5; 3713 break; 3714 case bcmSwitchPFCClass4Queue: 3715 case bcmSwitchPFCClass4McastQueue: 3716 *class = 4; 3717 break; 3718 case bcmSwitchPFCClass3Queue: 3719 case bcmSwitchPFCClass3McastQueue: 3720 *class = 3; 3721 break; 3722 case bcmSwitchPFCClass2Queue: 3723 case bcmSwitchPFCClass2McastQueue: 3724 *class = 2; 3725 break; 3726 case bcmSwitchPFCClass1Queue: 3727 case bcmSwitchPFCClass1McastQueue: 3728 *class = 1; 3729 break; 3730 case bcmSwitchPFCClass0Queue: 3731 case bcmSwitchPFCClass0McastQueue: 3732 *class = 0; 3733 break; 3734 /* 3735 * COVERITY 3736 * 3737 * This default is unreachable but needed for some compiler. 3738 */ 3739 /* coverity[dead_error_begin] */ 3740 default: 3741 return BCM_E_INTERNAL; 3742 } 3743 return BCM_E_NONE; 3744 } 3745 3746 3747 3748 STATIC int 3749 _bcm_hx5_cosq_ingress_pg_get(int unit, bcm_gport_t gport, bcm_cos_queue_t pri, 3750 int *p_pg_start, int *p_pg_end) 3751 { 3752 bcm_port_t local_port; 3753 uint32 rval,pool; 3754 soc_reg_t reg = INVALIDr; 3755 static const soc_reg_t prigroup_reg[] = { 3756 THDI_PORT_PRI_GRP0r, THDI_PORT_PRI_GRP1r 3757 }; 3758 static const soc_field_t prigroup_field[] = { 3759 PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf, 3760 PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf, 3761 PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf, 3762 PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf 3763 }; 3764 3765 if (pri == BCM_COS_INVALID) { 3766 *p_pg_start = 0; 3767 *p_pg_end = 7; 3768 return BCM_E_NONE; 3769 } 3770 3771 BCM_IF_ERROR_RETURN 3772 (_bcm_hx5_cosq_localport_resolve(unit, gport, &local_port)); 3773 3774 if (!SOC_PORT_VALID(unit, local_port)) { 3775 return BCM_E_PORT; 3776 } 3777 3778 if (pri >= _HX5_MMU_NUM_INT_PRI) { 3779 return BCM_E_PARAM; 3780 } 3781 /* get PG for port using Port+Cos */ 3782 if (pri < (_HX5_MMU_NUM_INT_PRI / 2)) { 3783 reg = prigroup_reg[0]; 3784 } else { 3785 reg = prigroup_reg[1]; 3786 } 3787 3788 SOC_IF_ERROR_RETURN 3789 (soc_reg32_get(unit, reg, local_port, 0, &rval)); 3790 pool = soc_reg_field_get(unit, reg, rval, prigroup_field[pri]); 3791 3792 if (p_pg_start) { 3793 *p_pg_start = pool; 3794 } 3795 3796 if (p_pg_end) { 3797 *p_pg_end = pool; 3798 } 3799 3800 return BCM_E_NONE; 3801 } 3802 3803 3804 /* 3805 * This function is used to get shared pool 3806 * for given Ingress [Port, Priority] 3807 */ 3808 STATIC int 3809 _bcm_hx5_cosq_ingress_sp_get(int unit, bcm_gport_t gport, bcm_cos_t pri, 3810 int *p_pool_start, int *p_pool_end) 3811 { 3812 int local_port; 3813 uint32 rval, pool; 3814 int pri_grp; 3815 static const soc_field_t prigroup_spid_field[] = { 3816 PG0_SPIDf, PG1_SPIDf, PG2_SPIDf, PG3_SPIDf, 3817 PG4_SPIDf, PG5_SPIDf, PG6_SPIDf, PG7_SPIDf 3818 }; 3819 3820 if (pri == BCM_COS_INVALID) { 3821 if (p_pool_start && p_pool_end) { 3822 *p_pool_start = 0; 3823 *p_pool_end = 3; 3824 return BCM_E_NONE; 3825 } else { 3826 return BCM_E_PARAM; 3827 } 3828 } 3829 3830 if ((pri < 0) || (pri >= _HX5_MMU_NUM_INT_PRI)) { 3831 /* Error. Input pri > Max Pri_Grp */ 3832 return BCM_E_PARAM; 3833 } 3834 3835 BCM_IF_ERROR_RETURN 3836 (_bcm_hx5_cosq_ingress_pg_get(unit, gport, pri, &pri_grp, &pri_grp)); 3837 3838 BCM_IF_ERROR_RETURN 3839 (_bcm_hx5_cosq_localport_resolve(unit, gport, &local_port)); 3840 3841 if (!SOC_PORT_VALID(unit, local_port)) { 3842 return BCM_E_PORT; 3843 } 3844 3845 if (pri_grp >= _HX5_MMU_NUM_PG) { 3846 return BCM_E_PARAM; 3847 } 3848 3849 SOC_IF_ERROR_RETURN(READ_THDI_PORT_PG_SPIDr(unit, local_port, &rval)); 3850 pool = soc_reg_field_get(unit, THDI_PORT_PG_SPIDr, rval, 3851 prigroup_spid_field[pri_grp]); 3852 3853 if (p_pool_start) { 3854 *p_pool_start = pool; 3855 } 3856 if (p_pool_end) { 3857 *p_pool_end = pool; 3858 } 3859 return BCM_E_NONE; 3860 } 3861 3862 /* 3863 * This function is used to get shared pool 3864 * for given Ingress [Port, Priority_group] 3865 */ 3866 STATIC int 3867 _bcm_hx5_cosq_ingress_sp_get_by_pg(int unit, bcm_gport_t gport, bcm_cos_queue_t pri_grp, 3868 int *p_pool_start, int *p_pool_end) 3869 { 3870 int local_port; 3871 uint32 rval, pool; 3872 static const soc_field_t prigroup_spid_field[] = { 3873 PG0_SPIDf, PG1_SPIDf, PG2_SPIDf, PG3_SPIDf, 3874 PG4_SPIDf, PG5_SPIDf, PG6_SPIDf, PG7_SPIDf 3875 }; 3876 3877 if (pri_grp == BCM_COS_INVALID) { 3878 if (p_pool_start && p_pool_end) { 3879 *p_pool_start = 0; 3880 *p_pool_end = 3; 3881 return BCM_E_NONE; 3882 } else { 3883 return BCM_E_PARAM; 3884 } 3885 } 3886 3887 BCM_IF_ERROR_RETURN 3888 (_bcm_hx5_cosq_localport_resolve(unit, gport, &local_port)); 3889 3890 if (!SOC_PORT_VALID(unit, local_port)) { 3891 return BCM_E_PORT; 3892 } 3893 3894 if (pri_grp >= _HX5_MMU_NUM_PG) { 3895 return BCM_E_PARAM; 3896 } 3897 3898 SOC_IF_ERROR_RETURN(READ_THDI_PORT_PG_SPIDr(unit, local_port, &rval)); 3899 pool = soc_reg_field_get(unit, THDI_PORT_PG_SPIDr, rval, 3900 prigroup_spid_field[pri_grp]); 3901 3902 if (p_pool_start) { 3903 *p_pool_start = pool; 3904 } 3905 if (p_pool_end) { 3906 *p_pool_end = pool; 3907 } 3908 return BCM_E_NONE; 3909 } 3910 3911 /* 3912 * This function is used to get headroom pool 3913 * for given Ingress [Port, Priority] 3914 */ 3915 STATIC int 3916 _bcm_hx5_cosq_ingress_hdrm_pool_get(int unit, bcm_gport_t gport, 3917 bcm_cos_t pri, 3918 int *p_hdrm_pool_start, 3919 int *p_hdrm_pool_end) 3920 { 3921 int local_port; 3922 uint32 rval, hdrm_pool; 3923 int pri_grp; 3924 static const soc_field_t prigroup_hpid_field[] = { 3925 PG0_HPIDf, PG1_HPIDf, PG2_HPIDf, PG3_HPIDf, 3926 PG4_HPIDf, PG5_HPIDf, PG6_HPIDf, PG7_HPIDf 3927 }; 3928 3929 if (pri == BCM_COS_INVALID) { 3930 if (p_hdrm_pool_start && p_hdrm_pool_end) { 3931 *p_hdrm_pool_start = 0; 3932 *p_hdrm_pool_end = 3; 3933 return BCM_E_NONE; 3934 } else { 3935 return BCM_E_PARAM; 3936 } 3937 } 3938 3939 if ((pri < 0) || (pri >= _HX5_MMU_NUM_INT_PRI)) { 3940 /* Error. Input pri > Max Pri_Grp */ 3941 return BCM_E_PARAM; 3942 } 3943 3944 BCM_IF_ERROR_RETURN 3945 (_bcm_hx5_cosq_ingress_pg_get(unit, gport, pri, &pri_grp, &pri_grp)); 3946 3947 BCM_IF_ERROR_RETURN 3948 (_bcm_hx5_cosq_localport_resolve(unit, gport, &local_port)); 3949 3950 if (!SOC_PORT_VALID(unit, local_port)) { 3951 return BCM_E_PORT; 3952 } 3953 3954 if (pri_grp >= _HX5_MMU_NUM_PG) { 3955 return BCM_E_PARAM; 3956 } 3957 3958 SOC_IF_ERROR_RETURN(READ_THDI_HDRM_PORT_PG_HPIDr(unit, local_port, &rval)); 3959 hdrm_pool = soc_reg_field_get(unit, THDI_HDRM_PORT_PG_HPIDr, rval, 3960 prigroup_hpid_field[pri_grp]); 3961 3962 if (p_hdrm_pool_start) { 3963 *p_hdrm_pool_start = hdrm_pool; 3964 } 3965 if (p_hdrm_pool_end) { 3966 *p_hdrm_pool_end = hdrm_pool; 3967 } 3968 3969 return BCM_E_NONE; 3970 } 3971 3972 3973 /* 3974 * This function is used to set headroom pool 3975 * or shared pool for given Ingress [Port, Priority] 3976 */ 3977 STATIC int 3978 _bcm_hx5_cosq_ing_pool_set(int unit, bcm_gport_t gport, bcm_cos_t pri, 3979 bcm_cosq_control_t type, int arg) 3980 { 3981 int local_port; 3982 uint32 rval; 3983 int pri_grp; 3984 static const soc_field_t prigroup_spid_field[] = { 3985 PG0_SPIDf, PG1_SPIDf, PG2_SPIDf, PG3_SPIDf, 3986 PG4_SPIDf, PG5_SPIDf, PG6_SPIDf, PG7_SPIDf 3987 }; 3988 static const soc_field_t prigroup_hpid_field[] = { 3989 PG0_HPIDf, PG1_HPIDf, PG2_HPIDf, PG3_HPIDf, 3990 PG4_HPIDf, PG5_HPIDf, PG6_HPIDf, PG7_HPIDf 3991 }; 3992 pri = pri % 8; 3993 3994 if((arg < 0) || (arg >= _HX5_MMU_NUM_POOL)) { 3995 return BCM_E_PARAM; 3996 } 3997 3998 if ((pri < 0) || (pri >= _HX5_MMU_NUM_INT_PRI)) { 3999 /* Error. Input pri > Max Pri_Grp */ 4000 return BCM_E_PARAM; 4001 } 4002 4003 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 4004 BCM_GPORT_IS_SCHEDULER(gport) || 4005 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 4006 return BCM_E_PARAM; 4007 } 4008 4009 BCM_IF_ERROR_RETURN 4010 (_bcm_hx5_cosq_localport_resolve(unit, gport, &local_port)); 4011 4012 if (!SOC_PORT_VALID(unit, local_port)) { 4013 return BCM_E_PORT; 4014 } 4015 4016 BCM_IF_ERROR_RETURN 4017 (_bcm_hx5_cosq_ingress_pg_get(unit, gport, pri, &pri_grp, &pri_grp)); 4018 4019 /* coverity fix : pri_grp can take value from 0 to 7 */ 4020 if ((pri_grp < 0) || (pri_grp >= _HX5_MMU_NUM_PG)) { 4021 return BCM_E_PARAM; 4022 } 4023 4024 if (type == bcmCosqControlIngressPool) { 4025 SOC_IF_ERROR_RETURN(READ_THDI_PORT_PG_SPIDr(unit, local_port, &rval)); 4026 soc_reg_field_set(unit, THDI_PORT_PG_SPIDr, &rval, 4027 prigroup_spid_field[pri_grp],arg); 4028 BCM_IF_ERROR_RETURN(WRITE_THDI_PORT_PG_SPIDr(unit, local_port, rval)); 4029 } else if (type == bcmCosqControlIngressHeadroomPool) { 4030 SOC_IF_ERROR_RETURN(READ_THDI_HDRM_PORT_PG_HPIDr(unit, local_port, &rval)); 4031 soc_reg_field_set(unit, THDI_HDRM_PORT_PG_HPIDr, &rval, 4032 prigroup_hpid_field[pri_grp], arg); 4033 BCM_IF_ERROR_RETURN(WRITE_THDI_HDRM_PORT_PG_HPIDr(unit, local_port, rval)); 4034 } else { 4035 return BCM_E_PARAM; 4036 } 4037 return BCM_E_NONE; 4038 } 4039 4040 STATIC int 4041 _bcm_hx5_cosq_ing_pool_get(int unit, bcm_gport_t gport, 4042 bcm_cos_t pri, 4043 bcm_cosq_control_t type, int *arg) 4044 { 4045 int pool_start_idx = 0, pool_end_idx = 0; 4046 pri = pri % 8; 4047 4048 if (arg == NULL) { 4049 return BCM_E_PARAM; 4050 } 4051 4052 if ((pri < 0) || (pri >= _HX5_MMU_NUM_INT_PRI)) { 4053 /* Error. Input pri > Max Pri_Grp */ 4054 return BCM_E_PARAM; 4055 } 4056 4057 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 4058 BCM_GPORT_IS_SCHEDULER(gport) || 4059 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 4060 return BCM_E_PARAM; 4061 } 4062 4063 if (type == bcmCosqControlIngressPool) { 4064 BCM_IF_ERROR_RETURN( 4065 _bcm_hx5_cosq_ingress_sp_get(unit, gport, pri, 4066 &pool_start_idx, 4067 &pool_end_idx)); 4068 } else if (type == bcmCosqControlIngressHeadroomPool) { 4069 BCM_IF_ERROR_RETURN( 4070 _bcm_hx5_cosq_ingress_hdrm_pool_get(unit, gport, pri, 4071 &pool_start_idx, 4072 &pool_end_idx)); 4073 } else { 4074 return BCM_E_PARAM; 4075 } 4076 *arg = pool_start_idx; 4077 return BCM_E_NONE; 4078 } 4079 4080 4081 STATIC _bcm_bst_cb_ret_t 4082 _bcm_hx5_bst_index_resolve(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 4083 bcm_bst_stat_id_t bid, int *pipe, int *start_hw_index, 4084 int *end_hw_index, int *rcb_data, void **cb_data, int *bcm_rv) 4085 { 4086 int phy_port, mmu_port, local_port; 4087 int mmu_port_base = 0; 4088 int pool_idx = 0; 4089 uint32 rval = 0; 4090 _bcm_hx5_cosq_node_t *node = NULL; 4091 soc_info_t *si; 4092 4093 *bcm_rv = _bcm_hx5_cosq_localport_resolve(unit, gport, &local_port); 4094 4095 if (BCM_E_NONE != (*bcm_rv)) { 4096 goto error; 4097 } 4098 4099 si = &SOC_INFO(unit); 4100 phy_port = si->port_l2p_mapping[local_port]; 4101 mmu_port = si->port_p2m_mapping[phy_port]; 4102 4103 *pipe = mmu_port / SOC_HX5_MMU_PORT_STRIDE; 4104 4105 if (bid == bcmBstStatIdDevice) { 4106 *start_hw_index = *end_hw_index = 0; 4107 *bcm_rv = BCM_E_NONE; 4108 return _BCM_BST_RV_OK; 4109 } 4110 4111 if ((bid == bcmBstStatIdEgrPool) || (bid == bcmBstStatIdEgrMCastPool)) { 4112 if(_bcm_hx5_cosq_egress_sp_get(unit, gport, cosq, start_hw_index, 4113 end_hw_index)) { 4114 goto error; 4115 } 4116 return _BCM_BST_RV_OK; 4117 } else if (bid == bcmBstStatIdHeadroomPool) { 4118 cosq = cosq % 8; 4119 /* ingress headroom pool */ 4120 if (_bcm_hx5_cosq_ingress_hdrm_pool_get(unit, gport, cosq, 4121 start_hw_index, end_hw_index)) { 4122 goto error; 4123 } 4124 return _BCM_BST_RV_OK; 4125 } else if (bid == bcmBstStatIdIngPool) { 4126 cosq = cosq % 8; 4127 /* ingress pool */ 4128 if (_bcm_hx5_cosq_ingress_sp_get(unit, gport, cosq, 4129 start_hw_index, end_hw_index)) { 4130 goto error; 4131 } 4132 return _BCM_BST_RV_OK; 4133 } else if (bid == bcmBstStatIdRQEPool) { 4134 /* RQE pool */ 4135 if (cosq == BCM_COS_INVALID) { 4136 *start_hw_index = 0; 4137 *end_hw_index = _HX5_MMU_NUM_POOL - 1; 4138 } else if ((cosq < 0) || (cosq >= _HX5_MMU_NUM_POOL)) { 4139 return BCM_E_PARAM; 4140 } else { 4141 SOC_IF_ERROR_RETURN 4142 (READ_MMU_THDR_DB_CONFIG1_PRIQr(unit, cosq, &rval)); 4143 4144 pool_idx = soc_reg_field_get(unit, MMU_THDR_DB_CONFIG1_PRIQr, rval, 4145 SPIDf); 4146 *start_hw_index = *end_hw_index = pool_idx; 4147 } 4148 return _BCM_BST_RV_OK; 4149 } else if (bid == bcmBstStatIdRQEQueue) { 4150 /* RQE queue */ 4151 if (cosq == BCM_COS_INVALID) { 4152 *start_hw_index = 0; 4153 *end_hw_index = _HX5_MMU_NUM_RQE_QUEUES - 1; 4154 } else if ((cosq < 0) || (cosq >= _HX5_MMU_NUM_RQE_QUEUES)) { 4155 return BCM_E_PARAM; 4156 } else { 4157 *start_hw_index = *end_hw_index = cosq; 4158 } 4159 return _BCM_BST_RV_OK; 4160 } else if (bid == bcmBstStatIdUCQueueGroup) { 4161 /* unicast queue group */ 4162 mmu_port_base = SOC_HX5_MMU_PORT_STRIDE * (*pipe); 4163 *start_hw_index = *end_hw_index = mmu_port - mmu_port_base; 4164 return _BCM_BST_RV_OK; 4165 } 4166 4167 4168 if (bid == bcmBstStatIdPortPool) { 4169 cosq = cosq % 8; 4170 /* ingress pool */ 4171 if (_bcm_hx5_cosq_ingress_sp_get(unit, gport, cosq, 4172 start_hw_index, end_hw_index)) { 4173 goto error; 4174 } 4175 *start_hw_index = ((mmu_port & SOC_HX5_MMU_PORT_STRIDE) * 4) + 4176 *start_hw_index; 4177 *end_hw_index = ((mmu_port & SOC_HX5_MMU_PORT_STRIDE) * 4) + 4178 *end_hw_index; 4179 } else if ((bid == bcmBstStatIdPriGroupShared) || 4180 (bid == bcmBstStatIdPriGroupHeadroom)) { 4181 cosq = cosq % 8; 4182 /* ingress PG */ 4183 if (_bcm_hx5_cosq_ingress_pg_get(unit, gport, cosq, 4184 start_hw_index, end_hw_index)) { 4185 goto error; 4186 } 4187 *start_hw_index = ((mmu_port & SOC_HX5_MMU_PORT_STRIDE) * 8) + 4188 *start_hw_index; 4189 *end_hw_index = ((mmu_port & SOC_HX5_MMU_PORT_STRIDE) * 8) + 4190 *end_hw_index; 4191 } else if (bid == bcmBstStatIdEgrPortPoolSharedUcast || 4192 bid == bcmBstStatIdEgrPortPoolSharedMcast) { 4193 /* egress pool */ 4194 if (_bcm_hx5_cosq_egress_sp_get(unit, gport, cosq, 4195 start_hw_index, end_hw_index)) { 4196 goto error; 4197 } 4198 *start_hw_index = ((mmu_port & SOC_HX5_MMU_PORT_STRIDE) * 4) + 4199 *start_hw_index; 4200 *end_hw_index = ((mmu_port & SOC_HX5_MMU_PORT_STRIDE) * 4) + 4201 *end_hw_index; 4202 } else { 4203 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 4204 if (bid != bcmBstStatIdUcast) { 4205 goto error; 4206 } 4207 BCM_IF_ERROR_RETURN 4208 (_bcm_hx5_cosq_node_get(unit, gport, NULL, 4209 &local_port, NULL, &node)); 4210 if (!node) { 4211 goto error; 4212 } 4213 *start_hw_index = node->hw_index; 4214 *end_hw_index = *start_hw_index; 4215 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 4216 if (bid != bcmBstStatIdMcast) { 4217 goto error; 4218 } 4219 BCM_IF_ERROR_RETURN 4220 (_bcm_hx5_cosq_node_get(unit, gport, NULL, 4221 &local_port, NULL, &node)); 4222 if (!node) { 4223 goto error; 4224 } 4225 if (IS_CPU_PORT(unit, local_port)) { 4226 *start_hw_index = si->port_cosq_base[CMIC_PORT(unit)] + cosq; 4227 } else { 4228 *start_hw_index = node->hw_index; 4229 } 4230 *end_hw_index = *start_hw_index; 4231 } else { 4232 if (cosq < 0) { 4233 if (bid == bcmBstStatIdUcast) { 4234 if (IS_LB_PORT(unit, local_port)) { 4235 goto error; 4236 } 4237 *start_hw_index = si->port_uc_cosq_base[local_port]; 4238 *end_hw_index = *start_hw_index + 4239 si->port_num_uc_cosq[local_port] - 1; 4240 } else { 4241 if (IS_CPU_PORT(unit, local_port)) { 4242 *start_hw_index = si->port_cosq_base[CMIC_PORT(unit)]; 4243 *end_hw_index = *start_hw_index + 4244 SOC_HX5_NUM_CPU_QUEUES - 1; 4245 } else { 4246 *start_hw_index = si->port_cosq_base[local_port]; 4247 *end_hw_index = *start_hw_index + 4248 si->port_num_cosq[local_port] - 1; 4249 } 4250 } 4251 } else { 4252 if (bid == bcmBstStatIdUcast) { 4253 if (IS_LB_PORT(unit, local_port)) { 4254 goto error; 4255 } 4256 *start_hw_index = si->port_num_uc_cosq[local_port] + cosq; 4257 *end_hw_index = *start_hw_index; 4258 } else { 4259 if (IS_CPU_PORT(unit, local_port)) { 4260 *start_hw_index = si->port_cosq_base[CMIC_PORT(unit)] + cosq; 4261 } else { 4262 *start_hw_index = si->port_num_cosq[local_port] + cosq; 4263 } 4264 *end_hw_index = *start_hw_index; 4265 } 4266 } 4267 } 4268 } 4269 4270 *bcm_rv = BCM_E_NONE; 4271 return _BCM_BST_RV_OK; 4272 4273 error: 4274 *bcm_rv = BCM_E_PARAM; 4275 return _BCM_BST_RV_ERROR; 4276 } 4277 4278 /* 4279 * Function: 4280 * _bcm_hx5_cosq_bucket_get 4281 * Purpose: 4282 * Get COS queue bandwidth control bucket setting 4283 * Parameters: 4284 * unit - (IN) unit number 4285 * gport - (IN) port number or GPORT identifier 4286 * cosq - (IN) COS queue number 4287 * min_quantum - (OUT) kbps or packet/second 4288 * max_quantum - (OUT) kbps or packet/second 4289 * burst_quantum - (OUT) kbps or packet/second 4290 * flags - (IN) BCM_COSQ_BW_XXX 4291 * Returns: 4292 * BCM_E_XXX 4293 * Notes: 4294 * If port is any form of local port, cosq is the hardware queue index. 4295 */ 4296 STATIC int 4297 _bcm_hx5_cosq_bucket_get(int unit, bcm_port_t gport, bcm_cos_queue_t cosq, 4298 uint32 *min_quantum, uint32 *max_quantum, 4299 uint32 *kbits_burst_min, uint32 *kbits_burst_max, 4300 uint32 *flags) 4301 { 4302 _bcm_hx5_cosq_node_t *node = NULL; 4303 bcm_port_t local_port; 4304 uint32 rval; 4305 uint32 refresh_rate, bucketsize, granularity, meter_flags; 4306 int pipe = -1, phy_port, mmu_port, index = 0; 4307 4308 soc_mem_t config_mem = INVALIDm; 4309 uint32 entry[SOC_MAX_MEM_WORDS]; 4310 soc_info_t *si; 4311 4312 if (cosq < 0) { 4313 if (cosq == -1) { 4314 /* caller needs to resolve the wild card value (-1) */ 4315 return BCM_E_INTERNAL; 4316 } else { /* reject all other negative value */ 4317 return BCM_E_PARAM; 4318 } 4319 } 4320 4321 BCM_IF_ERROR_RETURN 4322 (_bcm_hx5_cosq_localport_resolve(unit, gport, &local_port)); 4323 4324 si = &SOC_INFO(unit); 4325 phy_port = si->port_l2p_mapping[local_port]; 4326 mmu_port = si->port_p2m_mapping[phy_port]; 4327 pipe = si->port_pipe[local_port]; 4328 4329 if (BCM_GPORT_IS_SET(gport) && 4330 ((BCM_GPORT_IS_SCHEDULER(gport)) || 4331 BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 4332 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport))) { 4333 4334 BCM_IF_ERROR_RETURN 4335 (_bcm_hx5_cosq_node_get(unit, gport, NULL, NULL, NULL, &node)); 4336 } 4337 4338 if (node) { 4339 if (BCM_GPORT_IS_SCHEDULER(gport)) { 4340 if (node->level == SOC_HX5_NODE_LVL_L0) { 4341 config_mem = SOC_MEM_UNIQUE_ACC(unit, MMU_MTRO_L0_MEMm)[pipe]; 4342 index = node->hw_index; 4343 } else if(node->level == SOC_HX5_NODE_LVL_L1) { 4344 config_mem = SOC_MEM_UNIQUE_ACC(unit, MMU_MTRO_L1_MEMm)[pipe]; 4345 index = node->hw_index; 4346 } else if(node->level == SOC_HX5_NODE_LVL_L2) { 4347 config_mem = SOC_MEM_UNIQUE_ACC(unit, MMU_MTRO_L2_MEMm)[pipe]; 4348 index = node->hw_index; 4349 } else { 4350 return BCM_E_PARAM; 4351 } 4352 } else if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 4353 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 4354 config_mem = SOC_MEM_UNIQUE_ACC(unit, MMU_MTRO_L3_MEMm)[pipe]; 4355 4356 if (IS_CPU_PORT(unit, local_port)) { 4357 cosq = node->hw_index - SOC_HX5_CPU_MCQ_BASE; 4358 /* For CPU port's MC queue starting index: 2570 */ 4359 index = _BCM_HX5_MMU_L3_MC_CPU_QBASE + cosq; 4360 } else if (IS_LB_PORT(unit, local_port)) { 4361 cosq = node->hw_index - SOC_HX5_LB_MCQ_BASE; 4362 index = _BCM_HX5_MMU_L3_MC_LB_QBASE + cosq; 4363 } else { 4364 index = node->hw_index; 4365 if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 4366 index = node->hw_index + SOC_HX5_NUM_UC_QUEUES_PER_PIPE; 4367 } 4368 } 4369 } else { 4370 return BCM_E_PARAM; 4371 } 4372 } else { 4373 if ((cosq < 0) || (cosq >= si->port_num_cosq[local_port])) { 4374 return BCM_E_PARAM; 4375 } 4376 if (IS_CPU_PORT(unit, local_port)) { 4377 /* For CPU port, refer L3 memory (logical queue, starting index 2570) 4378 * directly */ 4379 config_mem = SOC_MEM_UNIQUE_ACC(unit, MMU_MTRO_L3_MEMm)[pipe]; 4380 index = _BCM_HX5_MMU_L3_MC_CPU_QBASE + cosq; 4381 } else if (IS_LB_PORT(unit, local_port)) { 4382 config_mem = SOC_MEM_UNIQUE_ACC(unit, MMU_MTRO_L3_MEMm)[pipe]; 4383 index = _BCM_HX5_MMU_L3_MC_LB_QBASE + cosq; 4384 } else { 4385 if (_HX5_IS_ST_PORT(unit, mmu_port)) { 4386 index = (mmu_port * SOC_HX5_NUM_UCAST_QUEUE_PER_ST_PORT) + cosq; 4387 } else { 4388 index = SOC_HX5_DOWNLINK_PORTQ_BASE + ((mmu_port - 16) * SOC_HX5_NUM_UCAST_QUEUE_PER_PORT) + cosq; 4389 } 4390 config_mem = SOC_MEM_UNIQUE_ACC(unit, MMU_MTRO_L2_MEMm)[pipe]; 4391 } 4392 } 4393 4394 /* 4395 * COVERITY 4396 * 4397 * This checker will not be True. 4398 * It is kept intentionally as a defensive case for future development. 4399 */ 4400 /* coverity[dead_error_line] */ 4401 if (config_mem == INVALIDm) { 4402 return BCM_E_PARAM; 4403 } 4404 4405 if (min_quantum == NULL || max_quantum == NULL || 4406 kbits_burst_max == NULL || kbits_burst_min == NULL) { 4407 return BCM_E_PARAM; 4408 } 4409 4410 BCM_IF_ERROR_RETURN 4411 (soc_mem_read(unit, config_mem, MEM_BLOCK_ALL, index, &entry)); 4412 4413 meter_flags = 0; 4414 *flags = 0; 4415 BCM_IF_ERROR_RETURN(READ_MMU_SEDCFG_MISCCONFIGr(unit, &rval)); 4416 if (soc_reg_field_get(unit, MMU_SEDCFG_MISCCONFIGr, rval, ITU_MODE_SELf)) { 4417 meter_flags |= _BCM_TD_METER_FLAG_NON_LINEAR; 4418 } 4419 if (soc_mem_field32_get(unit, config_mem, &entry, SHAPER_CONTROLf)) { 4420 meter_flags |= _BCM_TD_METER_FLAG_PACKET_MODE; 4421 *flags |= BCM_COSQ_BW_PACKET_MODE; 4422 } 4423 4424 granularity = soc_mem_field32_get(unit, config_mem, &entry, MAX_METER_GRANf); 4425 refresh_rate = soc_mem_field32_get(unit, config_mem, &entry, MAX_REFRESHf); 4426 bucketsize = soc_mem_field32_get(unit, config_mem, &entry, MAX_THD_SELf); 4427 BCM_IF_ERROR_RETURN 4428 (_bcm_td_bucket_encoding_to_rate(unit, refresh_rate, bucketsize, 4429 granularity, meter_flags, 4430 max_quantum, kbits_burst_max)); 4431 4432 granularity = soc_mem_field32_get(unit, config_mem, &entry, MIN_METER_GRANf); 4433 refresh_rate = soc_mem_field32_get(unit, config_mem, &entry, MIN_REFRESHf); 4434 bucketsize = soc_mem_field32_get(unit, config_mem, &entry, MIN_THD_SELf); 4435 BCM_IF_ERROR_RETURN 4436 (_bcm_td_bucket_encoding_to_rate(unit, refresh_rate, bucketsize, 4437 granularity, meter_flags, 4438 min_quantum, kbits_burst_min)); 4439 return BCM_E_NONE; 4440 } 4441 4442 /* 4443 * Function: 4444 * _bcm_hx5_cosq_bucket_set 4445 * Purpose: 4446 * Configure COS queue bandwidth control bucket 4447 * Parameters: 4448 * unit - (IN) unit number 4449 * gport - (IN) port number or GPORT identifier 4450 * cosq - (IN) COS queue number 4451 * min_quantum - (IN) kbps or packet/second 4452 * max_quantum - (IN) kbps or packet/second 4453 * burst_quantum - (IN) kbps or packet/second 4454 * flags - (IN) BCM_COSQ_BW_XXX 4455 * Returns: 4456 * BCM_E_XXX 4457 * Notes: 4458 * If port is any form of local port, cosq is the hardware queue index. 4459 */ 4460 STATIC int 4461 _bcm_hx5_cosq_bucket_set(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 4462 uint32 min_quantum, uint32 max_quantum, 4463 uint32 kbits_burst_min, uint32 kbits_burst_max, 4464 uint32 flags) 4465 { 4466 _bcm_hx5_cosq_node_t *node = NULL; 4467 bcm_port_t local_port; 4468 uint32 rval, meter_flags; 4469 uint32 bucketsize_max, bucketsize_min; 4470 uint32 granularity_max, granularity_min; 4471 uint32 refresh_rate_max, refresh_rate_min; 4472 int refresh_bitsize = 0, bucket_bitsize = 0; 4473 int pipe, phy_port, mmu_port, index = 0; 4474 soc_mem_t config_mem = INVALIDm; 4475 uint32 entry[SOC_MAX_MEM_WORDS]; 4476 soc_info_t *si; 4477 4478 /* caller should resolve the cosq. */ 4479 if (cosq < 0) { 4480 if (cosq == -1) { 4481 /* caller needs to resolve the wild card value (-1) */ 4482 return BCM_E_INTERNAL; 4483 } else { /* reject all other negative value */ 4484 return BCM_E_PARAM; 4485 } 4486 } 4487 4488 BCM_IF_ERROR_RETURN 4489 (_bcm_hx5_cosq_localport_resolve(unit, gport, &local_port)); 4490 4491 si = &SOC_INFO(unit); 4492 phy_port = si->port_l2p_mapping[local_port]; 4493 mmu_port = si->port_p2m_mapping[phy_port]; 4494 pipe = si->port_pipe[local_port]; 4495 4496 if (BCM_GPORT_IS_SET(gport) && 4497 ((BCM_GPORT_IS_SCHEDULER(gport)) || 4498 BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 4499 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport))) { 4500 4501 BCM_IF_ERROR_RETURN 4502 (_bcm_hx5_cosq_node_get(unit, gport, NULL, NULL, NULL, &node)); 4503 } 4504 4505 if (node) { 4506 if (BCM_GPORT_IS_SCHEDULER(gport)) { 4507 if (node->level == SOC_HX5_NODE_LVL_L0) { 4508 config_mem = SOC_MEM_UNIQUE_ACC(unit, MMU_MTRO_L0_MEMm)[pipe]; 4509 index = node->hw_index; 4510 } else if(node->level == SOC_HX5_NODE_LVL_L1) { 4511 config_mem = SOC_MEM_UNIQUE_ACC(unit, MMU_MTRO_L1_MEMm)[pipe]; 4512 index = node->hw_index; 4513 } else if(node->level == SOC_HX5_NODE_LVL_L2) { 4514 config_mem = SOC_MEM_UNIQUE_ACC(unit, MMU_MTRO_L2_MEMm)[pipe]; 4515 index = node->hw_index; 4516 } else { 4517 return BCM_E_PARAM; 4518 } 4519 } else if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 4520 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 4521 config_mem = SOC_MEM_UNIQUE_ACC(unit, MMU_MTRO_L3_MEMm)[pipe]; 4522 if (IS_CPU_PORT(unit, local_port)) { 4523 /* For CPU port, refer L3 memory (logical queue, starting index 2570) 4524 * directly */ 4525 index = _BCM_HX5_MMU_L3_MC_CPU_QBASE + cosq; 4526 } else if (IS_LB_PORT(unit, local_port)) { 4527 index = _BCM_HX5_MMU_L3_MC_LB_QBASE + cosq; 4528 } else { 4529 index = node->hw_index; 4530 if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 4531 index = node->hw_index + SOC_HX5_NUM_UC_QUEUES_PER_PIPE; 4532 } 4533 } 4534 } else { 4535 return BCM_E_PARAM; 4536 } 4537 } else { 4538 if ((cosq < 0) || (cosq >= si->port_num_cosq[local_port])) { 4539 return BCM_E_PARAM; 4540 } 4541 if (IS_CPU_PORT(unit, local_port)) { 4542 /* For CPU port, refer L1 memory (logical queue, starting index 1300) 4543 * directly */ 4544 config_mem = SOC_MEM_UNIQUE_ACC(unit, MMU_MTRO_L3_MEMm)[pipe]; 4545 index = _BCM_HX5_MMU_L3_MC_CPU_QBASE + cosq; 4546 } else if (IS_LB_PORT(unit, local_port)) { 4547 config_mem = SOC_MEM_UNIQUE_ACC(unit, MMU_MTRO_L3_MEMm)[pipe]; 4548 index = _BCM_HX5_MMU_L3_MC_LB_QBASE + cosq; 4549 } else { 4550 if (_HX5_IS_ST_PORT(unit, mmu_port)) { 4551 index = (mmu_port * SOC_HX5_NUM_UCAST_QUEUE_PER_ST_PORT) + cosq; 4552 } else { 4553 index = SOC_HX5_DOWNLINK_PORTQ_BASE + ((mmu_port - 16) * SOC_HX5_NUM_UCAST_QUEUE_PER_PORT) + cosq; 4554 } 4555 config_mem = SOC_MEM_UNIQUE_ACC(unit, MMU_MTRO_L2_MEMm)[pipe]; 4556 } 4557 } 4558 4559 /* 4560 * COVERITY 4561 * 4562 * This checker will not be True. 4563 * It is kept intentionally as a defensive check for future development. 4564 */ 4565 /* coverity[dead_error_line] */ 4566 if (config_mem == INVALIDm) { 4567 return BCM_E_PARAM; 4568 } 4569 4570 meter_flags = flags & BCM_COSQ_BW_PACKET_MODE ? 4571 _BCM_TD_METER_FLAG_PACKET_MODE : 0; 4572 BCM_IF_ERROR_RETURN(READ_MMU_SEDCFG_MISCCONFIGr(unit, &rval)); 4573 4574 if (soc_reg_field_get(unit, MMU_SEDCFG_MISCCONFIGr, rval, ITU_MODE_SELf)) { 4575 meter_flags |= _BCM_TD_METER_FLAG_NON_LINEAR; 4576 } 4577 4578 refresh_bitsize = soc_mem_field_length(unit, config_mem, MAX_REFRESHf); 4579 bucket_bitsize = soc_mem_field_length(unit, config_mem, MAX_THD_SELf); 4580 4581 BCM_IF_ERROR_RETURN 4582 (_bcm_td_rate_to_bucket_encoding(unit, max_quantum, kbits_burst_max, 4583 meter_flags, refresh_bitsize, 4584 bucket_bitsize, &refresh_rate_max, 4585 &bucketsize_max, &granularity_max)); 4586 4587 BCM_IF_ERROR_RETURN 4588 (_bcm_td_rate_to_bucket_encoding(unit, min_quantum, kbits_burst_min, 4589 meter_flags, refresh_bitsize, 4590 bucket_bitsize, &refresh_rate_min, 4591 &bucketsize_min, &granularity_min)); 4592 4593 sal_memset(entry, 0, sizeof(uint32)*SOC_MAX_MEM_WORDS); 4594 4595 soc_mem_field32_set(unit, config_mem, &entry, MAX_METER_GRANf, granularity_max); 4596 soc_mem_field32_set(unit, config_mem, &entry, MAX_REFRESHf, refresh_rate_max); 4597 soc_mem_field32_set(unit, config_mem, &entry, MAX_THD_SELf, bucketsize_max); 4598 4599 soc_mem_field32_set(unit, config_mem, &entry, MIN_METER_GRANf, granularity_min); 4600 soc_mem_field32_set(unit, config_mem, &entry, MIN_REFRESHf, refresh_rate_min); 4601 soc_mem_field32_set(unit, config_mem, &entry, MIN_THD_SELf, bucketsize_min); 4602 4603 soc_mem_field32_set(unit, config_mem, &entry, SHAPER_CONTROLf, 4604 (flags & BCM_COSQ_BW_PACKET_MODE) ? 1 : 0); 4605 4606 BCM_IF_ERROR_RETURN 4607 (soc_mem_write(unit, config_mem, MEM_BLOCK_ALL, index, &entry)); 4608 4609 return BCM_E_NONE; 4610 } 4611 4612 /* 4613 * Function: 4614 * bcm_hx5_cosq_gport_bandwidth_burst_set 4615 * Purpose: 4616 * Configure COS queue bandwidth burst setting 4617 * Parameters: 4618 * unit - (IN) unit number 4619 * gport - (IN) GPORT identifier 4620 * cosq - (IN) COS queue to configure, -1 for all COS queues 4621 * kbits_burst - (IN) maximum burst, kbits 4622 * Returns: 4623 * BCM_E_XXX 4624 */ 4625 int 4626 bcm_hx5_cosq_gport_bandwidth_burst_set(int unit, 4627 bcm_gport_t gport, 4628 bcm_cos_queue_t cosq, 4629 uint32 kbits_burst_min, 4630 uint32 kbits_burst_max) 4631 { 4632 int i, start_cos=0, end_cos=0; 4633 uint32 kbits_sec_min, kbits_sec_max, kbits_sec_burst, flags; 4634 bcm_port_t local_port; 4635 int phy_port, mmu_port; 4636 4637 4638 soc_info_t *si = &SOC_INFO(unit); 4639 4640 BCM_IF_ERROR_RETURN 4641 (_bcm_hx5_cosq_localport_resolve(unit, gport, &local_port)); 4642 4643 phy_port = si->port_l2p_mapping[local_port]; 4644 mmu_port = si->port_p2m_mapping[phy_port]; 4645 start_cos = end_cos = cosq; 4646 4647 if (cosq == BCM_COS_INVALID) { 4648 start_cos = 0; 4649 if (IS_CPU_PORT(unit, local_port)) { 4650 end_cos = NUM_CPU_COSQ(unit); 4651 } else if(_HX5_IS_ST_PORT(unit, mmu_port)) { 4652 end_cos = SOC_HX5_NUM_UCAST_QUEUE_PER_ST_PORT; 4653 } else { 4654 end_cos = SOC_HX5_NUM_UCAST_QUEUE_PER_PORT; 4655 } 4656 } 4657 4658 if (BCM_GPORT_IS_SET(gport)) { 4659 if ((BCM_GPORT_IS_SCHEDULER(gport)) || 4660 BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 4661 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 4662 start_cos = end_cos = 0; 4663 } 4664 } 4665 4666 for (i = start_cos; i <= end_cos; i++) { 4667 BCM_IF_ERROR_RETURN 4668 (_bcm_hx5_cosq_bucket_get(unit, gport, i, &kbits_sec_min, 4669 &kbits_sec_max, &kbits_sec_burst, 4670 &kbits_sec_burst, &flags)); 4671 BCM_IF_ERROR_RETURN 4672 (_bcm_hx5_cosq_bucket_set(unit, gport, i, kbits_sec_min, 4673 kbits_sec_max, kbits_burst_min, 4674 kbits_burst_max, flags)); 4675 } 4676 return BCM_E_NONE; 4677 } 4678 4679 /* 4680 * Function: 4681 * bcm_hx5_cosq_gport_bandwidth_burst_get 4682 * Purpose: 4683 * Get COS queue bandwidth burst setting 4684 * Parameters: 4685 * unit - (IN) unit number 4686 * gport - (IN) GPORT identifier 4687 * cosq - (IN) COS queue to get, -1 for Queue 0 4688 * kbits_burst - (OUT) maximum burst, kbits 4689 * Returns: 4690 * BCM_E_XXX 4691 */ 4692 int 4693 bcm_hx5_cosq_gport_bandwidth_burst_get(int unit, 4694 bcm_gport_t gport, 4695 bcm_cos_queue_t cosq, 4696 uint32 *kbits_burst_min, 4697 uint32 *kbits_burst_max) 4698 { 4699 uint32 kbits_sec_min, kbits_sec_max, flags; 4700 4701 if (cosq < -1) { 4702 return BCM_E_PARAM; 4703 } 4704 4705 BCM_IF_ERROR_RETURN 4706 (_bcm_hx5_cosq_bucket_get(unit, gport, cosq == -1 ? 0 : cosq, 4707 &kbits_sec_min, &kbits_sec_max, kbits_burst_min, 4708 kbits_burst_max, &flags)); 4709 4710 return BCM_E_NONE; 4711 } 4712 4713 /* 4714 * Function: 4715 * _bcm_hx5_cosq_mapping_set 4716 * Purpose: 4717 * Set COS queue for the specified priority of an ingress port 4718 * Parameters: 4719 * unit - (IN) unit number 4720 * ing_port - (IN) ingress port 4721 * priority - (IN) priority value to map 4722 * flags - (IN) BCM_COSQ_GPORT_XXX_QUEUE_GROUP 4723 * gport - (IN) queue group GPORT identifier 4724 * cosq - (IN) COS queue number 4725 * Returns: 4726 * BCM_E_XXX 4727 */ 4728 STATIC int 4729 _bcm_hx5_cosq_mapping_set(int unit, bcm_port_t ing_port, bcm_cos_t priority, 4730 uint32 flags, bcm_gport_t gport, bcm_cos_queue_t cosq) 4731 { 4732 bcm_port_t local_port, out_port; 4733 bcm_cos_queue_t hw_cosq; 4734 int rv, idx, numq; 4735 int port; 4736 soc_field_t field[3] = {INVALIDf, INVALIDf, INVALIDf}; /* [0]:UC, [1]:MC cos */ 4737 int value[3] = {0, 0, 0}; 4738 void *entries[1]; 4739 cos_map_sel_entry_t cos_map_sel_entry; 4740 port_cos_map_entry_t cos_map_entries[_HX5_MMU_NUM_INT_PRI]; 4741 uint32 old_index, new_index; 4742 soc_info_t *si; 4743 4744 BCM_IF_ERROR_RETURN 4745 (_bcm_hx5_cosq_localport_resolve(unit, ing_port, &local_port)); 4746 4747 si = &SOC_INFO(unit); 4748 4749 if (gport != -1) { 4750 BCM_IF_ERROR_RETURN(_bcm_hx5_cosq_localport_resolve(unit, gport, 4751 &out_port)); 4752 } 4753 4754 switch(flags) { 4755 case BCM_COSQ_GPORT_UCAST_QUEUE_GROUP: 4756 if (gport == -1) { 4757 hw_cosq = cosq; 4758 } else { 4759 if (!BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 4760 return BCM_E_PARAM; 4761 } 4762 BCM_IF_ERROR_RETURN 4763 (_bcm_hx5_cosq_index_resolve(unit, gport, cosq, 4764 _BCM_HX5_COSQ_INDEX_STYLE_COS, &port, &hw_cosq, NULL)); 4765 if (!IS_CPU_PORT(unit, port)) { 4766 hw_cosq = hw_cosq - si->port_uc_cosq_base[port]; 4767 } 4768 } 4769 hw_cosq = hw_cosq % 8; 4770 field[0] = UC_COS1f; 4771 field[1] = HG_COSf; 4772 value[0] = hw_cosq; 4773 value[1] = hw_cosq + 8; 4774 break; 4775 case BCM_COSQ_GPORT_MCAST_QUEUE_GROUP: 4776 if (gport == -1) { 4777 hw_cosq = cosq; 4778 } else { 4779 if (!BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 4780 return BCM_E_PARAM; 4781 } 4782 BCM_IF_ERROR_RETURN 4783 (_bcm_hx5_cosq_index_resolve(unit, gport, cosq, 4784 _BCM_HX5_COSQ_INDEX_STYLE_COS, &port, &hw_cosq, NULL)); 4785 if (!IS_CPU_PORT(unit, port)) { 4786 hw_cosq = hw_cosq - si->port_cosq_base[port]; 4787 } 4788 } 4789 hw_cosq = hw_cosq % 8; 4790 field[0] = MC_COS1f; 4791 field[1] = HG_COSf; 4792 value[0] = hw_cosq; 4793 value[1] = hw_cosq + 8; 4794 break; 4795 case (BCM_COSQ_GPORT_UCAST_QUEUE_GROUP | 4796 BCM_COSQ_GPORT_MCAST_QUEUE_GROUP): 4797 if (gport == -1) { 4798 hw_cosq = cosq; 4799 } else { 4800 return BCM_E_PARAM; 4801 } 4802 hw_cosq = hw_cosq % 8; 4803 field[0] = UC_COS1f; 4804 field[1] = MC_COS1f; 4805 field[2] = HG_COSf; 4806 value[0] = hw_cosq; 4807 value[1] = hw_cosq; 4808 value[2] = hw_cosq + 8; 4809 break; 4810 default: 4811 return BCM_E_PARAM; 4812 } 4813 4814 numq = _BCM_HX5_NUM_COS(unit); 4815 entries[0] = &cos_map_entries; 4816 BCM_IF_ERROR_RETURN 4817 (READ_COS_MAP_SELm(unit, MEM_BLOCK_ANY, local_port, 4818 &cos_map_sel_entry)); 4819 old_index = soc_mem_field32_get(unit, COS_MAP_SELm, &cos_map_sel_entry, 4820 SELECTf); 4821 old_index *= _HX5_MMU_NUM_INT_PRI; 4822 4823 BCM_IF_ERROR_RETURN 4824 (soc_profile_mem_get(unit, _bcm_hx5_cos_map_profile[unit], old_index, 4825 _HX5_MMU_NUM_INT_PRI, entries)); 4826 4827 for (idx = 0; idx < 3; idx++) { 4828 if (field[idx] != INVALIDf) { 4829 soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[priority], 4830 field[idx], value[idx]); 4831 } 4832 } 4833 4834 soc_mem_lock(unit, PORT_COS_MAPm); 4835 rv = soc_profile_mem_delete(unit, _bcm_hx5_cos_map_profile[unit], 4836 old_index); 4837 if (BCM_FAILURE(rv)) { 4838 soc_mem_unlock(unit, PORT_COS_MAPm); 4839 return rv; 4840 } 4841 4842 rv = soc_profile_mem_add(unit, _bcm_hx5_cos_map_profile[unit], entries, 4843 _HX5_MMU_NUM_INT_PRI, &new_index); 4844 4845 if (BCM_FAILURE(rv)) { 4846 soc_mem_unlock(unit, PORT_COS_MAPm); 4847 return rv; 4848 } 4849 4850 soc_mem_field32_set(unit, COS_MAP_SELm, &cos_map_sel_entry, SELECTf, 4851 new_index / _HX5_MMU_NUM_INT_PRI); 4852 BCM_IF_ERROR_RETURN 4853 (WRITE_COS_MAP_SELm(unit, MEM_BLOCK_ANY, local_port, 4854 &cos_map_sel_entry)); 4855 4856 #ifndef BCM_COSQ_HIGIG_MAP_DISABLE 4857 if (IS_CPU_PORT(unit, local_port)) { 4858 BCM_IF_ERROR_RETURN 4859 (soc_mem_field32_modify(unit, COS_MAP_SELm, 4860 SOC_INFO(unit).cpu_hg_index, SELECTf, 4861 new_index / _HX5_MMU_NUM_INT_PRI)); 4862 } 4863 #endif /* BCM_COSQ_HIGIG_MAP_DISABLE */ 4864 4865 /* update the wireless part of the cos_map table */ 4866 rv = bcm_hx5_wireless_cos_map_update(unit, numq); 4867 4868 if (rv < 0) { 4869 return rv; 4870 } 4871 return BCM_E_NONE; 4872 } 4873 4874 /* 4875 * Function: 4876 * _bcm_hx5_cosq_mapping_get 4877 * Purpose: 4878 * Determine which COS queue a given priority currently maps to. 4879 * Parameters: 4880 * unit - (IN) unit number 4881 * ing_port - (IN) ingress port 4882 * priority - (IN) priority value to map 4883 * flags - (IN) BCM_COSQ_GPORT_XXX_QUEUE_GROUP 4884 * gport - (IN) queue group GPORT identifier 4885 * cosq - (OUT) COS queue number 4886 * Returns: 4887 * BCM_E_XXX 4888 */ 4889 STATIC int 4890 _bcm_hx5_cosq_mapping_get(int unit, bcm_port_t ing_port, bcm_cos_t priority, 4891 uint32 flags, bcm_gport_t *gport, 4892 bcm_cos_queue_t *cosq) 4893 { 4894 bcm_port_t local_port; 4895 cos_map_sel_entry_t cos_map_sel_entry; 4896 _bcm_hx5_cosq_port_info_t *port_info = NULL; 4897 _bcm_hx5_cosq_st_port_info_t *stport_info = NULL; 4898 _bcm_hx5_cosq_cpu_port_info_t *cpu_port_info = NULL; 4899 _bcm_hx5_cosq_node_t *node; 4900 int ii, index; 4901 void *entry_p; 4902 bcm_cos_queue_t hw_cosq = BCM_COS_INVALID, node_cosq = BCM_COS_INVALID; 4903 int numq = -1; 4904 int phy_port, mmu_port, port_index; 4905 4906 4907 soc_info_t *si = &SOC_INFO(unit); 4908 4909 if ((flags != BCM_COSQ_GPORT_UCAST_QUEUE_GROUP) && 4910 (flags != BCM_COSQ_GPORT_MCAST_QUEUE_GROUP)) { 4911 return BCM_E_PARAM; 4912 } 4913 4914 BCM_IF_ERROR_RETURN 4915 (_bcm_hx5_cosq_localport_resolve(unit, ing_port, &local_port)); 4916 4917 phy_port = si->port_l2p_mapping[local_port]; 4918 mmu_port = si->port_p2m_mapping[phy_port]; 4919 4920 if (gport) { 4921 *gport = BCM_GPORT_INVALID; 4922 } 4923 4924 *cosq = BCM_COS_INVALID; 4925 4926 BCM_IF_ERROR_RETURN 4927 (READ_COS_MAP_SELm(unit, MEM_BLOCK_ANY, local_port, 4928 &cos_map_sel_entry)); 4929 index = soc_mem_field32_get(unit, COS_MAP_SELm, &cos_map_sel_entry, 4930 SELECTf); 4931 index *= _HX5_MMU_NUM_INT_PRI; 4932 4933 entry_p = SOC_PROFILE_MEM_ENTRY(unit, _bcm_hx5_cos_map_profile[unit], 4934 port_cos_map_entry_t *, index + priority); 4935 4936 if (IS_CPU_PORT(unit, local_port)) { 4937 cpu_port_info = &_bcm_hx5_cosq_cpu_port_info[unit][local_port]; 4938 numq = SOC_HX5_NUM_CPU_QUEUES; 4939 } else { 4940 _HX5_PORT_INDEX_GET(unit, mmu_port, port_index); 4941 if (_HX5_IS_ST_PORT(unit, mmu_port)) { 4942 stport_info = &_bcm_hx5_cosq_st_port_info[unit][port_index]; 4943 numq = SOC_HX5_NUM_UCAST_QUEUE_PER_ST_PORT; 4944 } else { 4945 port_info = &_bcm_hx5_cosq_port_info[unit][port_index]; 4946 numq = SOC_HX5_NUM_UCAST_QUEUE_PER_PORT; 4947 } 4948 } 4949 4950 switch (flags) { 4951 case BCM_COSQ_GPORT_UCAST_QUEUE_GROUP: 4952 hw_cosq = soc_mem_field32_get(unit, PORT_COS_MAPm, entry_p, 4953 UC_COS1f); 4954 if ((IS_CPU_PORT(unit, local_port) == FALSE) && (gport)) { 4955 for (ii = 0; ii < numq; ii++) { 4956 if (_HX5_IS_ST_PORT(unit, mmu_port)) { 4957 node = &stport_info->ucast[ii]; 4958 } else { 4959 node = &port_info->ucast[ii]; 4960 } 4961 if (node == NULL) { 4962 return BCM_E_NOT_FOUND; 4963 } 4964 node_cosq = node->hw_index - si->port_uc_cosq_base[local_port]; 4965 if (node && (node_cosq == hw_cosq)) { 4966 *gport = node->gport; 4967 *cosq = hw_cosq % 8; 4968 break; 4969 } 4970 } 4971 } else { 4972 *cosq = hw_cosq; 4973 } 4974 break; 4975 case BCM_COSQ_GPORT_MCAST_QUEUE_GROUP: 4976 hw_cosq = soc_mem_field32_get(unit, PORT_COS_MAPm, entry_p, 4977 MC_COS1f); 4978 if (gport) { 4979 for (ii = 0; ii < numq; ii++) { 4980 if (IS_CPU_PORT(unit, local_port)) { 4981 node = &cpu_port_info->mcast[ii]; 4982 } else { 4983 if (_HX5_IS_ST_PORT(unit, mmu_port)) { 4984 node = &stport_info->mcast[ii]; 4985 } else { 4986 node = &port_info->mcast[ii]; 4987 } 4988 } 4989 if (!node) { 4990 return BCM_E_NOT_FOUND; 4991 } 4992 if (IS_CPU_PORT(unit, local_port)) { 4993 node_cosq = node->hw_index - _HX5_CPU_L2_NODE_BASE; 4994 } else { 4995 node_cosq = node->hw_index - si->port_cosq_base[local_port]; 4996 } 4997 if (node_cosq == hw_cosq) { 4998 *gport = node->gport; 4999 *cosq = hw_cosq % 8; 5000 break; 5001 } 5002 } 5003 } else { 5004 *cosq = hw_cosq; 5005 } 5006 break; 5007 /* 5008 * COVERITY 5009 * 5010 *This default is unreachable. It is kept intentionally 5011 *as a defensive default for future development. 5012 */ 5013 /* coverity[dead_error_begin] */ 5014 default: 5015 return BCM_E_PARAM; 5016 } 5017 5018 if (((gport && 5019 (*gport == BCM_GPORT_INVALID) && (*cosq == BCM_COS_INVALID))) || 5020 (*cosq == BCM_COS_INVALID)) { 5021 return BCM_E_NOT_FOUND; 5022 } 5023 5024 return BCM_E_NONE; 5025 } 5026 5027 /* 5028 * Function: 5029 * bcm_hx5_cosq_mapping_set 5030 * Purpose: 5031 * Set which cosq a given priority should fall into 5032 * Parameters: 5033 * unit - (IN) unit number 5034 * gport - (IN) queue group GPORT identifier 5035 * priority - (IN) priority value to map 5036 * cosq - (INT) COS queue number 5037 * Returns: 5038 * BCM_E_XXX 5039 */ 5040 int 5041 bcm_hx5_cosq_mapping_set(int unit, bcm_port_t port, bcm_cos_t priority, 5042 bcm_cos_queue_t cosq) 5043 { 5044 bcm_pbmp_t pbmp; 5045 bcm_port_t local_port; 5046 int rv = BCM_E_NONE, numq; 5047 5048 BCM_PBMP_CLEAR(pbmp); 5049 5050 if ((priority < 0) || (priority >= _HX5_MMU_NUM_INT_PRI)) { 5051 return BCM_E_PARAM; 5052 } 5053 5054 if (cosq < 0) { 5055 return BCM_E_PARAM; 5056 } 5057 5058 if (port == -1) { 5059 /* port value of -1 will cause the cosq mapping set for 5060 * * all types of local ports except Loopback ports. 5061 * * So we do the sanity check of cos value with Default Number 5062 * * of COS 5063 */ 5064 if (cosq >= _BCM_HX5_NUM_COS(unit)) { 5065 return BCM_E_PARAM; 5066 } 5067 BCM_PBMP_ASSIGN(pbmp, PBMP_ALL(unit)); 5068 } else { 5069 if (BCM_GPORT_IS_SET(port)) { 5070 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 5071 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) || 5072 BCM_GPORT_IS_SCHEDULER(port)) { 5073 return BCM_E_PARAM; 5074 } else if (BCM_GPORT_IS_LOCAL(port)) { 5075 local_port = BCM_GPORT_LOCAL_GET(port); 5076 } else if (BCM_GPORT_IS_MODPORT(port)) { 5077 BCM_IF_ERROR_RETURN 5078 (bcm_esw_port_local_get(unit, port, &local_port)); 5079 } else { 5080 return BCM_E_PARAM; 5081 } 5082 } else { 5083 local_port = port; 5084 } 5085 5086 if (!SOC_PORT_VALID(unit, local_port)) { 5087 return BCM_E_PORT; 5088 } 5089 5090 BCM_PBMP_PORT_ADD(pbmp, local_port); 5091 if (cosq >= _HX5_PORT_NUM_COS(unit, local_port)) { 5092 return BCM_E_PARAM; 5093 } 5094 } 5095 5096 numq = _BCM_HX5_NUM_COS(unit); 5097 PBMP_ITER(pbmp, local_port) { 5098 if (IS_LB_PORT(unit, local_port)) { 5099 continue; 5100 } 5101 5102 /* If no ETS/gport, map the int prio symmetrically for ucast and 5103 * * mcast */ 5104 BCM_IF_ERROR_RETURN 5105 (_bcm_hx5_cosq_mapping_set(unit, local_port, priority, 5106 BCM_COSQ_GPORT_UCAST_QUEUE_GROUP | 5107 BCM_COSQ_GPORT_MCAST_QUEUE_GROUP, 5108 -1, cosq)); 5109 } 5110 5111 rv = bcm_hx5_wireless_cos_map_update(unit, numq); 5112 5113 if (rv < 0) { 5114 return rv; 5115 } 5116 5117 return BCM_E_NONE; 5118 } 5119 5120 /* 5121 * Function: 5122 * bcm_hx5_cosq_gport_mapping_set 5123 * Purpose: 5124 * Set COS queue for the specified priority of an ingress port 5125 * Parameters: 5126 * unit - (IN) unit number 5127 * ing_port - (IN) ingress port 5128 * int_pri - (IN) priority value to map 5129 * flags - (IN) BCM_COSQ_GPORT_XXX_QUEUE_GROUP 5130 * gport - (IN) queue group GPORT identifier 5131 * cosq - (IN) COS queue number 5132 * Returns: 5133 * BCM_E_XXX 5134 */ 5135 int 5136 bcm_hx5_cosq_gport_mapping_set(int unit, bcm_port_t ing_port, bcm_cos_t int_pri, 5137 uint32 flags, bcm_gport_t gport, 5138 bcm_cos_queue_t cosq) 5139 { 5140 bcm_port_t local_port; 5141 5142 if ((int_pri < 0) || (int_pri >= _HX5_MMU_NUM_INT_PRI)) { 5143 return BCM_E_PARAM; 5144 } 5145 5146 BCM_IF_ERROR_RETURN(_bcm_hx5_cosq_localport_resolve(unit, ing_port, 5147 &local_port)); 5148 5149 if ((cosq < 0) || (cosq >= _HX5_PORT_NUM_COS(unit, local_port))) { 5150 return BCM_E_PARAM; 5151 } 5152 5153 return _bcm_hx5_cosq_mapping_set(unit, ing_port, int_pri, flags, gport, 5154 cosq); 5155 } 5156 5157 /* 5158 * Function: 5159 * bcm_hx5_cosq_mapping_get 5160 * Purpose: 5161 * Determine which COS queue a given priority currently maps to. 5162 * Parameters: 5163 * unit - (IN) unit number 5164 * gport - (IN) queue group GPORT identifier 5165 * priority - (IN) priority value to map 5166 * cosq - (OUT) COS queue number 5167 * Returns: 5168 * BCM_E_XXX 5169 */ 5170 int 5171 bcm_hx5_cosq_mapping_get(int unit, bcm_port_t port, bcm_cos_t priority, 5172 bcm_cos_queue_t *cosq) 5173 { 5174 bcm_port_t local_port; 5175 bcm_pbmp_t pbmp; 5176 5177 BCM_PBMP_CLEAR(pbmp); 5178 5179 if ((priority < 0) || (priority >= _HX5_MMU_NUM_INT_PRI)) { 5180 return BCM_E_PARAM; 5181 } 5182 5183 if (port == -1) { 5184 BCM_PBMP_ASSIGN(pbmp, PBMP_ALL(unit)); 5185 } else { 5186 if (BCM_GPORT_IS_SET(port)) { 5187 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 5188 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) || 5189 BCM_GPORT_IS_SCHEDULER(port)) { 5190 return BCM_E_PARAM; 5191 } else if (BCM_GPORT_IS_LOCAL(port)) { 5192 local_port = BCM_GPORT_LOCAL_GET(port); 5193 } else if (BCM_GPORT_IS_MODPORT(port)) { 5194 BCM_IF_ERROR_RETURN 5195 (bcm_esw_port_local_get(unit, port, &local_port)); 5196 } else { 5197 return BCM_E_PARAM; 5198 } 5199 } else { 5200 local_port = port; 5201 } 5202 5203 if (!SOC_PORT_VALID(unit, local_port)) { 5204 return BCM_E_PORT; 5205 } 5206 5207 BCM_PBMP_PORT_ADD(pbmp, local_port); 5208 } 5209 5210 PBMP_ITER(pbmp, local_port) { 5211 if (IS_LB_PORT(unit, local_port)) { 5212 continue; 5213 } 5214 5215 BCM_IF_ERROR_RETURN 5216 (_bcm_hx5_cosq_mapping_get(unit, local_port, priority, 5217 BCM_COSQ_GPORT_UCAST_QUEUE_GROUP, NULL, 5218 cosq)); 5219 break; 5220 } 5221 5222 return BCM_E_NONE; 5223 5224 } 5225 5226 /* 5227 * Function: 5228 * _bcm_hx5_cosq_gport_mapping_get 5229 * Purpose: 5230 * Determine which COS queue a given priority currently maps to. 5231 * Parameters: 5232 * unit - (IN) unit number 5233 * ing_port - (IN) ingress port 5234 * int_pri - (IN) priority value to map 5235 * flags - (IN) BCM_COSQ_GPORT_XXX_QUEUE_GROUP 5236 * gport - (IN) queue group GPORT identifier 5237 * cosq - (OUT) COS queue number 5238 * Returns: 5239 * BCM_E_XXX 5240 */ 5241 int 5242 bcm_hx5_cosq_gport_mapping_get(int unit, bcm_port_t ing_port, bcm_cos_t int_pri, 5243 uint32 flags, bcm_gport_t *gport, 5244 bcm_cos_queue_t *cosq) 5245 { 5246 if (gport == NULL || cosq == NULL) { 5247 return BCM_E_PARAM; 5248 } 5249 5250 if ((int_pri < 0) || (int_pri >= _HX5_MMU_NUM_INT_PRI)) { 5251 return BCM_E_PARAM; 5252 } 5253 5254 return _bcm_hx5_cosq_mapping_get(unit, ing_port, int_pri, flags, gport, 5255 cosq); 5256 } 5257 5258 5259 STATIC int 5260 _bcm_hx5_cosq_egr_pool_set(int unit, bcm_gport_t gport, 5261 bcm_cos_queue_t cosq, bcm_cosq_control_t type, int arg) 5262 { 5263 bcm_port_t local_port; 5264 int startq, pool, midx; 5265 uint32 max_val; 5266 uint32 entry[SOC_MAX_MEM_WORDS]; 5267 uint32 entry2[SOC_MAX_MEM_WORDS]; 5268 soc_mem_t base_mem = INVALIDm, base_mem2 = INVALIDm; 5269 soc_mem_t mem = INVALIDm, mem2 = INVALIDm; 5270 soc_field_t fld_limit = INVALIDf; 5271 int granularity = 1, pipe; 5272 5273 if (arg < 0) { 5274 return BCM_E_PARAM; 5275 } 5276 5277 BCM_IF_ERROR_RETURN 5278 (_bcm_hx5_cosq_index_resolve(unit, gport, cosq, 5279 _BCM_HX5_COSQ_INDEX_STYLE_EGR_POOL, 5280 &local_port, &pool, NULL)); 5281 5282 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 5283 5284 base_mem = MMU_THDM_DB_PORTSP_CONFIGm; 5285 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 5286 5287 if (type == bcmCosqControlEgressPoolLimitEnable) { 5288 midx = SOC_TD3_MMU_PIPED_MEM_INDEX(unit, local_port, base_mem, pool); 5289 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, 5290 midx, entry)); 5291 5292 soc_mem_field32_set(unit, mem, entry, SHARED_LIMIT_ENABLEf, !!arg); 5293 5294 return soc_mem_write(unit, mem, MEM_BLOCK_ALL, midx, entry); 5295 } 5296 if (type == bcmCosqControlEgressPool || type == bcmCosqControlUCEgressPool || 5297 type == bcmCosqControlMCEgressPool) { 5298 if((arg < 0) || (arg >= _HX5_MMU_NUM_POOL)) { 5299 return BCM_E_PARAM; 5300 } 5301 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 5302 if (type != bcmCosqControlEgressPool) { 5303 return BCM_E_PARAM; 5304 } 5305 /* regular unicast queue */ 5306 BCM_IF_ERROR_RETURN 5307 (_bcm_hx5_cosq_index_resolve(unit, gport, cosq, 5308 _BCM_HX5_COSQ_INDEX_STYLE_UCAST_QUEUE, 5309 &local_port, &startq, NULL)); 5310 base_mem = MMU_THDU_Q_TO_QGRP_MAPm; 5311 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 5312 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 5313 if (type != bcmCosqControlEgressPool) { 5314 return BCM_E_PARAM; 5315 } 5316 BCM_IF_ERROR_RETURN 5317 (_bcm_hx5_cosq_index_resolve(unit, gport, cosq, 5318 _BCM_HX5_COSQ_INDEX_STYLE_MCAST_QUEUE, 5319 &local_port, &startq, NULL)); 5320 base_mem = MMU_THDM_MCQE_QUEUE_CONFIGm; 5321 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 5322 base_mem2 = MMU_THDM_DB_QUEUE_CONFIGm; 5323 mem2 = SOC_MEM_UNIQUE_ACC(unit, base_mem2)[pipe]; 5324 } else { /* local port */ 5325 if (type == bcmCosqControlUCEgressPool) { 5326 BCM_IF_ERROR_RETURN 5327 (_bcm_hx5_cosq_index_resolve(unit, gport, cosq, 5328 _BCM_HX5_COSQ_INDEX_STYLE_UCAST_QUEUE, 5329 &local_port, &startq, NULL)); 5330 base_mem = MMU_THDU_Q_TO_QGRP_MAPm; 5331 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 5332 } else { 5333 BCM_IF_ERROR_RETURN 5334 (_bcm_hx5_cosq_index_resolve(unit, gport, cosq, 5335 _BCM_HX5_COSQ_INDEX_STYLE_MCAST_QUEUE, 5336 &local_port, &startq, NULL)); 5337 base_mem = MMU_THDM_MCQE_QUEUE_CONFIGm; 5338 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 5339 base_mem2 = MMU_THDM_DB_QUEUE_CONFIGm; 5340 mem2 = SOC_MEM_UNIQUE_ACC(unit, base_mem2)[pipe]; 5341 } 5342 } 5343 5344 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 5345 soc_mem_field32_set(unit, mem, entry, Q_SPIDf, arg); 5346 5347 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 5348 if (mem2 != INVALIDm) { 5349 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem2, MEM_BLOCK_ALL, startq, entry2)); 5350 soc_mem_field32_set(unit, mem2, entry2, Q_SPIDf, arg); 5351 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem2, MEM_BLOCK_ALL, startq, entry2)); 5352 } 5353 return BCM_E_NONE; 5354 } 5355 5356 arg = (arg + _HX5_MMU_BYTES_PER_CELL - 1) / _HX5_MMU_BYTES_PER_CELL; 5357 5358 /* per service pool settings */ 5359 if (type == bcmCosqControlEgressPoolSharedLimitBytes || 5360 type == bcmCosqControlEgressPoolResumeLimitBytes || 5361 type == bcmCosqControlEgressPoolYellowSharedLimitBytes || 5362 type == bcmCosqControlEgressPoolYellowResumeLimitBytes || 5363 type == bcmCosqControlEgressPoolRedSharedLimitBytes || 5364 type == bcmCosqControlEgressPoolRedResumeLimitBytes) { 5365 uint32 rval; 5366 soc_reg_t reg; 5367 switch (type) { 5368 case bcmCosqControlEgressPoolSharedLimitBytes: 5369 reg = MMU_THDM_DB_POOL_SHARED_LIMITr; 5370 fld_limit = SHARED_LIMITf; 5371 granularity = 1; 5372 break; 5373 case bcmCosqControlEgressPoolResumeLimitBytes: 5374 reg = MMU_THDM_DB_POOL_RESUME_LIMITr; 5375 fld_limit = RESUME_LIMITf; 5376 granularity = 8; 5377 break; 5378 case bcmCosqControlEgressPoolYellowSharedLimitBytes: 5379 reg = MMU_THDM_DB_POOL_YELLOW_SHARED_LIMITr; 5380 fld_limit = YELLOW_SHARED_LIMITf; 5381 granularity = 8; 5382 break; 5383 case bcmCosqControlEgressPoolYellowResumeLimitBytes: 5384 reg = MMU_THDM_DB_POOL_YELLOW_RESUME_LIMITr; 5385 fld_limit = YELLOW_RESUME_LIMITf; 5386 granularity = 8; 5387 break; 5388 case bcmCosqControlEgressPoolRedSharedLimitBytes: 5389 reg = MMU_THDM_DB_POOL_RED_SHARED_LIMITr; 5390 fld_limit = RED_SHARED_LIMITf; 5391 granularity = 8; 5392 break; 5393 case bcmCosqControlEgressPoolRedResumeLimitBytes: 5394 reg = MMU_THDM_DB_POOL_RED_RESUME_LIMITr; 5395 fld_limit = RED_RESUME_LIMITf; 5396 granularity = 8; 5397 break; 5398 /* coverity[dead_error_begin] */ 5399 default: 5400 return BCM_E_UNAVAIL; 5401 } 5402 5403 BCM_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, pool, &rval)); 5404 5405 /* Check for min/max values */ 5406 max_val = (1 << soc_reg_field_length(unit, reg, fld_limit)) - 1; 5407 if ((arg < 0) || ((arg/granularity) > max_val)) { 5408 return BCM_E_PARAM; 5409 } else { 5410 soc_reg_field_set(unit, reg, &rval, fld_limit, (arg/granularity)); 5411 } 5412 5413 BCM_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, pool, rval)); 5414 5415 return BCM_E_NONE; 5416 } 5417 5418 if (type == bcmCosqControlEgressPoolHighCongestionLimitBytes || 5419 type == bcmCosqControlEgressPoolLowCongestionLimitBytes) { 5420 uint64 rval64; 5421 soc_reg_t reg64; 5422 soc_reg_t wred_cng_lmt[4] = { 5423 WRED_POOL_INST_CONG_LIMIT_0r, 5424 WRED_POOL_INST_CONG_LIMIT_1r, 5425 WRED_POOL_INST_CONG_LIMIT_2r, 5426 WRED_POOL_INST_CONG_LIMIT_3r, 5427 }; 5428 5429 switch (type) { 5430 case bcmCosqControlEgressPoolHighCongestionLimitBytes: 5431 reg64 = wred_cng_lmt[pool]; 5432 fld_limit = POOL_HI_CONG_LIMITf; 5433 pool = -1; 5434 granularity = 1; 5435 break; 5436 case bcmCosqControlEgressPoolLowCongestionLimitBytes: 5437 reg64 = wred_cng_lmt[pool]; 5438 fld_limit = POOL_LOW_CONG_LIMITf; 5439 pool = -1; 5440 granularity = 1; 5441 break; 5442 /* coverity[dead_error_begin] */ 5443 default: 5444 return BCM_E_UNAVAIL; 5445 } 5446 5447 BCM_IF_ERROR_RETURN(soc_reg64_get(unit, reg64, REG_PORT_ANY, pool, &rval64)); 5448 5449 /* Check for min/max values */ 5450 max_val = (1 << soc_reg_field_length(unit, reg64, fld_limit)) - 1; 5451 if ((arg < 0) || ((arg/granularity) > max_val)) { 5452 return BCM_E_PARAM; 5453 } else { 5454 soc_reg64_field32_set(unit, reg64, &rval64, fld_limit, (arg/granularity)); 5455 } 5456 5457 BCM_IF_ERROR_RETURN(soc_reg64_set(unit, reg64, REG_PORT_ANY, pool, rval64)); 5458 5459 return BCM_E_NONE; 5460 } 5461 5462 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 5463 BCM_IF_ERROR_RETURN 5464 (_bcm_hx5_cosq_index_resolve(unit, gport, cosq, 5465 _BCM_HX5_COSQ_INDEX_STYLE_UCAST_QUEUE, 5466 &local_port, &startq, NULL)); 5467 base_mem = MMU_THDU_CONFIG_QUEUEm; 5468 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 5469 base_mem2 = MMU_THDU_Q_TO_QGRP_MAPm; 5470 mem2 = SOC_MEM_UNIQUE_ACC(unit, base_mem2)[pipe]; 5471 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 5472 BCM_IF_ERROR_RETURN 5473 (_bcm_hx5_cosq_index_resolve(unit, gport, cosq, 5474 _BCM_HX5_COSQ_INDEX_STYLE_MCAST_QUEUE, 5475 &local_port, &startq, NULL)); 5476 base_mem = MMU_THDM_DB_QUEUE_CONFIGm; 5477 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 5478 } else { 5479 if (soc_property_get(unit, spn_PORT_UC_MC_ACCOUNTING_COMBINE, 0) == 0) { 5480 /* Need to have the UC_MC_Combine config enabled */ 5481 return BCM_E_PARAM; 5482 } 5483 base_mem = MMU_THDM_DB_PORTSP_CONFIGm; 5484 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 5485 startq = SOC_TD3_MMU_PIPED_MEM_INDEX(unit, local_port, base_mem, pool); 5486 } 5487 5488 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 5489 5490 if (mem2 != INVALIDm) { 5491 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem2, MEM_BLOCK_ALL, startq, entry2)); 5492 } 5493 5494 switch (type) { 5495 case bcmCosqControlEgressPoolLimitBytes: 5496 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 5497 fld_limit = Q_SHARED_LIMIT_CELLf; 5498 5499 if (mem2 != INVALIDm) { 5500 soc_mem_field32_set(unit, mem2, entry2, Q_LIMIT_ENABLEf, 1); 5501 } 5502 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 5503 fld_limit = Q_SHARED_LIMITf; 5504 soc_mem_field32_set(unit, mem, entry, Q_LIMIT_ENABLEf, 1); 5505 } else { 5506 fld_limit = SHARED_LIMITf; 5507 soc_mem_field32_set(unit, mem, entry, SHARED_LIMIT_ENABLEf, 1); 5508 } 5509 granularity = 1; 5510 break; 5511 case bcmCosqControlEgressPoolYellowLimitBytes: 5512 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 5513 fld_limit = LIMIT_YELLOW_CELLf; 5514 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 5515 fld_limit = YELLOW_SHARED_LIMITf; 5516 } else { 5517 fld_limit = YELLOW_SHARED_LIMITf; 5518 } 5519 granularity = 8; 5520 break; 5521 case bcmCosqControlEgressPoolRedLimitBytes: 5522 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 5523 fld_limit = LIMIT_RED_CELLf; 5524 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 5525 fld_limit = RED_SHARED_LIMITf; 5526 } else { 5527 fld_limit = RED_SHARED_LIMITf; 5528 } 5529 granularity = 8; 5530 break; 5531 default: 5532 return BCM_E_UNAVAIL; 5533 } 5534 5535 /* Check for min/max values */ 5536 max_val = (1 << soc_mem_field_length(unit, mem, fld_limit)) - 1; 5537 if ((arg < 0) || ((arg/granularity) > max_val)) { 5538 return BCM_E_PARAM; 5539 } else { 5540 soc_mem_field32_set(unit, mem, entry, fld_limit, (arg/granularity)); 5541 } 5542 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 5543 5544 if (mem2 != INVALIDm) { 5545 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem2, MEM_BLOCK_ALL, startq, entry2)); 5546 } 5547 return BCM_E_NONE; 5548 } 5549 5550 STATIC int 5551 _bcm_hx5_cosq_egr_pool_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 5552 bcm_cosq_control_t type, int *arg) 5553 { 5554 bcm_port_t local_port; 5555 int startq, pool, midx, pipe; 5556 uint32 entry[SOC_MAX_MEM_WORDS]; 5557 soc_mem_t mem, base_mem; 5558 int granularity = 1; 5559 5560 if (!arg) { 5561 return BCM_E_PARAM; 5562 } 5563 5564 BCM_IF_ERROR_RETURN 5565 (_bcm_hx5_cosq_index_resolve(unit, gport, cosq, 5566 _BCM_HX5_COSQ_INDEX_STYLE_EGR_POOL, 5567 &local_port, &pool, NULL)); 5568 5569 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 5570 5571 if (type == bcmCosqControlEgressPool || type == bcmCosqControlUCEgressPool || 5572 type == bcmCosqControlMCEgressPool) { 5573 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 5574 if (type != bcmCosqControlEgressPool) { 5575 return BCM_E_PARAM; 5576 } 5577 /* regular unicast queue */ 5578 BCM_IF_ERROR_RETURN 5579 (_bcm_hx5_cosq_index_resolve(unit, gport, cosq, 5580 _BCM_HX5_COSQ_INDEX_STYLE_UCAST_QUEUE, 5581 &local_port, &startq, NULL)); 5582 base_mem = MMU_THDU_Q_TO_QGRP_MAPm; 5583 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 5584 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 5585 if (type != bcmCosqControlEgressPool) { 5586 return BCM_E_PARAM; 5587 } 5588 BCM_IF_ERROR_RETURN 5589 (_bcm_hx5_cosq_index_resolve(unit, gport, cosq, 5590 _BCM_HX5_COSQ_INDEX_STYLE_MCAST_QUEUE, 5591 &local_port, &startq, NULL)); 5592 base_mem = MMU_THDM_MCQE_QUEUE_CONFIGm; 5593 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 5594 } else { /* local port */ 5595 if (type == bcmCosqControlUCEgressPool) { 5596 BCM_IF_ERROR_RETURN 5597 (_bcm_hx5_cosq_index_resolve(unit, gport, cosq, 5598 _BCM_HX5_COSQ_INDEX_STYLE_UCAST_QUEUE, 5599 &local_port, &startq, NULL)); 5600 base_mem = MMU_THDU_Q_TO_QGRP_MAPm; 5601 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 5602 } else { 5603 BCM_IF_ERROR_RETURN 5604 (_bcm_hx5_cosq_index_resolve(unit, gport, cosq, 5605 _BCM_HX5_COSQ_INDEX_STYLE_MCAST_QUEUE, 5606 &local_port, &startq, NULL)); 5607 base_mem = MMU_THDM_MCQE_QUEUE_CONFIGm; 5608 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 5609 } 5610 } 5611 5612 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 5613 *arg = soc_mem_field32_get(unit, mem, entry, Q_SPIDf); 5614 return BCM_E_NONE; 5615 } 5616 5617 /* per service pool settings */ 5618 if (type == bcmCosqControlEgressPoolSharedLimitBytes || 5619 type == bcmCosqControlEgressPoolResumeLimitBytes || 5620 type == bcmCosqControlEgressPoolYellowSharedLimitBytes || 5621 type == bcmCosqControlEgressPoolYellowResumeLimitBytes || 5622 type == bcmCosqControlEgressPoolRedSharedLimitBytes || 5623 type == bcmCosqControlEgressPoolRedResumeLimitBytes) { 5624 uint32 rval; 5625 soc_reg_t reg; 5626 soc_field_t fld_limit = INVALIDf; 5627 switch (type) { 5628 case bcmCosqControlEgressPoolSharedLimitBytes: 5629 reg = MMU_THDM_DB_POOL_SHARED_LIMITr; 5630 fld_limit = SHARED_LIMITf; 5631 granularity = 1; 5632 break; 5633 case bcmCosqControlEgressPoolResumeLimitBytes: 5634 reg = MMU_THDM_DB_POOL_RESUME_LIMITr; 5635 fld_limit = RESUME_LIMITf; 5636 granularity = 8; 5637 break; 5638 case bcmCosqControlEgressPoolYellowSharedLimitBytes: 5639 reg = MMU_THDM_DB_POOL_YELLOW_SHARED_LIMITr; 5640 fld_limit = YELLOW_SHARED_LIMITf; 5641 granularity = 8; 5642 break; 5643 case bcmCosqControlEgressPoolYellowResumeLimitBytes: 5644 reg = MMU_THDM_DB_POOL_YELLOW_RESUME_LIMITr; 5645 fld_limit = YELLOW_RESUME_LIMITf; 5646 granularity = 8; 5647 break; 5648 case bcmCosqControlEgressPoolRedSharedLimitBytes: 5649 reg = MMU_THDM_DB_POOL_RED_SHARED_LIMITr; 5650 fld_limit = RED_SHARED_LIMITf; 5651 granularity = 8; 5652 break; 5653 case bcmCosqControlEgressPoolRedResumeLimitBytes: 5654 reg = MMU_THDM_DB_POOL_RED_RESUME_LIMITr; 5655 fld_limit = RED_RESUME_LIMITf; 5656 granularity = 8; 5657 break; 5658 /* coverity[dead_error_begin] */ 5659 default: 5660 return BCM_E_UNAVAIL; 5661 } 5662 5663 BCM_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, pool, &rval)); 5664 5665 *arg = soc_reg_field_get(unit, reg, rval, fld_limit); 5666 *arg = (*arg) * granularity * _HX5_MMU_BYTES_PER_CELL; 5667 5668 return BCM_E_NONE; 5669 } 5670 5671 if (type == bcmCosqControlEgressPoolHighCongestionLimitBytes || 5672 type == bcmCosqControlEgressPoolLowCongestionLimitBytes) { 5673 uint64 rval64; 5674 soc_reg_t reg64; 5675 soc_reg_t wred_cng_lmt[4] = { 5676 WRED_POOL_INST_CONG_LIMIT_0r, 5677 WRED_POOL_INST_CONG_LIMIT_1r, 5678 WRED_POOL_INST_CONG_LIMIT_2r, 5679 WRED_POOL_INST_CONG_LIMIT_3r, 5680 }; 5681 soc_field_t fld_limit = INVALIDf; 5682 5683 switch (type) { 5684 case bcmCosqControlEgressPoolHighCongestionLimitBytes: 5685 reg64 = wred_cng_lmt[pool]; 5686 fld_limit = POOL_HI_CONG_LIMITf; 5687 pool = -1; 5688 granularity = 1; 5689 break; 5690 case bcmCosqControlEgressPoolLowCongestionLimitBytes: 5691 reg64 = wred_cng_lmt[pool]; 5692 fld_limit = POOL_LOW_CONG_LIMITf; 5693 pool = -1; 5694 granularity = 1; 5695 break; 5696 /* coverity[dead_error_begin] */ 5697 default: 5698 return BCM_E_UNAVAIL; 5699 } 5700 5701 BCM_IF_ERROR_RETURN(soc_reg64_get(unit, reg64, REG_PORT_ANY, pool, &rval64)); 5702 5703 *arg = soc_reg64_field32_get(unit, reg64, rval64, fld_limit); 5704 *arg = (*arg) * granularity * _HX5_MMU_BYTES_PER_CELL; 5705 5706 return BCM_E_NONE; 5707 } 5708 5709 base_mem = MMU_THDM_DB_PORTSP_CONFIGm; 5710 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 5711 5712 if (type == bcmCosqControlEgressPoolLimitEnable) { 5713 midx = SOC_TD3_MMU_PIPED_MEM_INDEX(unit, local_port, base_mem, pool); 5714 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, 5715 midx, entry)); 5716 5717 *arg = soc_mem_field32_get(unit, mem, entry, SHARED_LIMIT_ENABLEf); 5718 return BCM_E_NONE; 5719 } 5720 5721 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 5722 BCM_IF_ERROR_RETURN 5723 (_bcm_hx5_cosq_index_resolve(unit, gport, cosq, 5724 _BCM_HX5_COSQ_INDEX_STYLE_UCAST_QUEUE, 5725 &local_port, &startq, NULL)); 5726 base_mem = MMU_THDU_CONFIG_QUEUEm; 5727 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 5728 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 5729 BCM_IF_ERROR_RETURN 5730 (_bcm_hx5_cosq_index_resolve(unit, gport, cosq, 5731 _BCM_HX5_COSQ_INDEX_STYLE_MCAST_QUEUE, 5732 &local_port, &startq, NULL)); 5733 5734 base_mem = MMU_THDM_DB_QUEUE_CONFIGm; 5735 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 5736 } else { 5737 if (soc_property_get(unit, spn_PORT_UC_MC_ACCOUNTING_COMBINE, 0) == 0) { 5738 /* Need to have the UC_MC_Combine config enabled */ 5739 return BCM_E_PARAM; 5740 } 5741 base_mem = MMU_THDM_DB_PORTSP_CONFIGm; 5742 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 5743 startq = SOC_TD3_MMU_PIPED_MEM_INDEX(unit, local_port, base_mem, pool); 5744 } 5745 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, 5746 startq, entry)); 5747 5748 switch (type) { 5749 case bcmCosqControlEgressPoolLimitBytes: 5750 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 5751 *arg = soc_mem_field32_get(unit, mem, entry, Q_SHARED_LIMIT_CELLf); 5752 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 5753 *arg = soc_mem_field32_get(unit, mem, entry, Q_SHARED_LIMITf); 5754 } else { 5755 *arg = soc_mem_field32_get(unit, mem, entry, SHARED_LIMITf); 5756 } 5757 granularity = 1; 5758 break; 5759 case bcmCosqControlEgressPoolYellowLimitBytes: 5760 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 5761 *arg = soc_mem_field32_get(unit, mem, entry, LIMIT_YELLOW_CELLf); 5762 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 5763 *arg = soc_mem_field32_get(unit, mem, entry, YELLOW_SHARED_LIMITf); 5764 } else { 5765 *arg = soc_mem_field32_get(unit, mem, entry, YELLOW_SHARED_LIMITf); 5766 } 5767 granularity = 8; 5768 break; 5769 case bcmCosqControlEgressPoolRedLimitBytes: 5770 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 5771 *arg = soc_mem_field32_get(unit, mem, entry, LIMIT_RED_CELLf); 5772 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 5773 *arg = soc_mem_field32_get(unit, mem, entry, RED_SHARED_LIMITf); 5774 } else { 5775 *arg = soc_mem_field32_get(unit, mem, entry, RED_SHARED_LIMITf); 5776 } 5777 granularity = 8; 5778 break; 5779 default: 5780 return BCM_E_UNAVAIL; 5781 } 5782 *arg = (*arg) * granularity * _HX5_MMU_BYTES_PER_CELL; 5783 return BCM_E_NONE; 5784 } 5785 5786 STATIC int 5787 _bcm_hx5_cosq_egr_queue_set(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 5788 bcm_cosq_control_t type, int arg) 5789 { 5790 bcm_port_t local_port; 5791 int pipe, startq; 5792 uint32 max_val, rval; 5793 uint32 entry[SOC_MAX_MEM_WORDS]; 5794 uint32 entry2[SOC_MAX_MEM_WORDS]; 5795 soc_mem_t mem = INVALIDm, mem2 = INVALIDm; 5796 soc_field_t fld_limit = INVALIDf; 5797 int granularity = 1; 5798 int from_cos, to_cos, ci; 5799 int egr_db_shd_size, egr_qe_shd_size, cur_val, post_update; 5800 int limit; 5801 int disable_queuing = 0; 5802 int uc_qlimit_enable = 0, mc_qlimit_enable = 0; 5803 5804 if (arg < 0) { 5805 return BCM_E_PARAM; 5806 } 5807 5808 arg = (arg + _HX5_MMU_BYTES_PER_CELL - 1) / _HX5_MMU_BYTES_PER_CELL; 5809 5810 if ((type == bcmCosqControlEgressUCQueueMinLimitBytes) || 5811 (type == bcmCosqControlEgressUCQueueSharedLimitBytes)) { 5812 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 5813 BCM_IF_ERROR_RETURN 5814 (_bcm_hx5_cosq_index_resolve(unit, gport, cosq, 5815 _BCM_HX5_COSQ_INDEX_STYLE_UCAST_QUEUE, 5816 &local_port, &startq, NULL)); 5817 SOC_IF_ERROR_RETURN 5818 (soc_port_pipe_get(unit, local_port, &pipe)); 5819 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 5820 return BCM_E_PARAM; 5821 } 5822 else { 5823 if (cosq == BCM_COS_INVALID) { 5824 from_cos = to_cos = 0; 5825 } else { 5826 from_cos = to_cos = cosq; 5827 } 5828 5829 BCM_IF_ERROR_RETURN 5830 (_bcm_hx5_cosq_localport_resolve(unit, gport, &local_port)); 5831 if (local_port < 0) { 5832 return BCM_E_PORT; 5833 } 5834 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 5835 for (ci = from_cos; ci <= to_cos; ci++) { 5836 BCM_IF_ERROR_RETURN 5837 (_bcm_hx5_cosq_index_resolve 5838 (unit, local_port, ci, _BCM_HX5_COSQ_INDEX_STYLE_UCAST_QUEUE, 5839 NULL, &startq, NULL)); 5840 } 5841 } 5842 mem = SOC_MEM_UNIQUE_ACC(unit, MMU_THDU_CONFIG_QUEUEm)[pipe]; 5843 mem2 = SOC_MEM_UNIQUE_ACC(unit, MMU_THDU_Q_TO_QGRP_MAPm)[pipe]; 5844 } else if ((type == bcmCosqControlEgressMCQueueMinLimitBytes) || 5845 (type == bcmCosqControlEgressMCQueueSharedLimitBytes)) { 5846 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 5847 return BCM_E_PARAM; 5848 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 5849 BCM_IF_ERROR_RETURN 5850 (_bcm_hx5_cosq_index_resolve(unit, gport, cosq, 5851 _BCM_HX5_COSQ_INDEX_STYLE_MCAST_QUEUE, 5852 &local_port, &startq, NULL)); 5853 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 5854 } 5855 else { 5856 if (cosq == BCM_COS_INVALID) { 5857 from_cos = to_cos = 0; 5858 } else { 5859 from_cos = to_cos = cosq; 5860 } 5861 5862 BCM_IF_ERROR_RETURN 5863 (_bcm_hx5_cosq_localport_resolve(unit, gport, &local_port)); 5864 if (local_port < 0) { 5865 return BCM_E_PORT; 5866 } 5867 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 5868 for (ci = from_cos; ci <= to_cos; ci++) { 5869 BCM_IF_ERROR_RETURN 5870 (_bcm_hx5_cosq_index_resolve 5871 (unit, local_port, ci, _BCM_HX5_COSQ_INDEX_STYLE_MCAST_QUEUE, 5872 NULL, &startq, NULL)); 5873 } 5874 } 5875 mem = SOC_MEM_UNIQUE_ACC(unit, MMU_THDM_DB_QUEUE_CONFIGm)[pipe]; 5876 mem2 = SOC_MEM_UNIQUE_ACC(unit, MMU_THDM_MCQE_QUEUE_CONFIGm)[pipe]; 5877 } else { 5878 return BCM_E_PARAM; 5879 } 5880 5881 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 5882 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem2, MEM_BLOCK_ALL, startq, entry2)); 5883 5884 switch (type) { 5885 case bcmCosqControlEgressUCQueueSharedLimitBytes: 5886 fld_limit = Q_SHARED_LIMIT_CELLf; 5887 uc_qlimit_enable = 1; 5888 5889 /* Set MMU_THDU_XPIPE_Q_TO_QGRP_MAP.DISABLE_QUEUING to 1 when both MIN 5890 * and SHARED LIMIT are 0. Set it to 0 when either MIN or SHARED LIMIT 5891 * is non-zero. 5892 */ 5893 limit = soc_mem_field32_get(unit, mem, entry, Q_MIN_LIMIT_CELLf); 5894 if (arg == 0 && limit == 0) { 5895 disable_queuing = 1; 5896 } else if (arg != 0 || limit != 0) { 5897 disable_queuing = 0; 5898 } 5899 granularity = 1; 5900 break; 5901 case bcmCosqControlEgressMCQueueSharedLimitBytes: 5902 fld_limit = Q_SHARED_LIMITf; 5903 mc_qlimit_enable = 1; 5904 granularity = 1; 5905 break; 5906 case bcmCosqControlEgressUCQueueMinLimitBytes: 5907 fld_limit = Q_MIN_LIMIT_CELLf; 5908 5909 /* Set MMU_THDU_Q_TO_QGRP_MAP.DISABLE_QUEUING to 1 when both MIN 5910 * and SHARED LIMIT are 0. Set it to 0 when either MIN or 5911 * SHARED LIMIT is non-zero 5912 */ 5913 limit = soc_mem_field32_get(unit, mem, entry, Q_SHARED_LIMIT_CELLf); 5914 if (arg == 0 && limit == 0) { 5915 disable_queuing = 1; 5916 } else if (arg != 0 || limit != 0) { 5917 disable_queuing = 0; 5918 } 5919 5920 granularity = 1; 5921 break; 5922 case bcmCosqControlEgressMCQueueMinLimitBytes: 5923 fld_limit = Q_MIN_LIMITf; 5924 granularity = 1; 5925 break; 5926 default: 5927 return BCM_E_UNAVAIL; 5928 } 5929 5930 /* Recalculate Shared Values if Min Changed */ 5931 /* THDO - DB */ 5932 rval = 0; 5933 SOC_IF_ERROR_RETURN 5934 (READ_MMU_THDM_DB_POOL_SHARED_LIMITr(unit, 0, &rval)); 5935 egr_db_shd_size = soc_reg_field_get(unit, MMU_THDM_DB_POOL_SHARED_LIMITr, 5936 rval, SHARED_LIMITf); 5937 5938 /* THDO - QE */ 5939 rval = 0; 5940 SOC_IF_ERROR_RETURN 5941 (READ_MMU_THDM_MCQE_POOL_SHARED_LIMITr(unit, 0, &rval)); 5942 egr_qe_shd_size = soc_reg_field_get(unit, MMU_THDM_MCQE_POOL_SHARED_LIMITr, 5943 rval, SHARED_LIMITf); 5944 cur_val = soc_mem_field32_get(unit, mem, entry, fld_limit); 5945 5946 if ((arg / granularity) > cur_val) { 5947 /* New Min Val > Cur Min Val 5948 * So reduce the Shared values first and then 5949 * Increase the Min Value for given resource 5950 */ 5951 post_update = 0; 5952 } else if ((arg / granularity) < cur_val) { 5953 /* New Min Val < Cur Min Val 5954 * So reduce the Min values first and then 5955 * Increase Shared values everywhere 5956 */ 5957 post_update = 1; 5958 } else { 5959 return BCM_E_NONE; 5960 } 5961 5962 if (!post_update && 5963 ((type == bcmCosqControlEgressUCQueueMinLimitBytes) || 5964 (type == bcmCosqControlEgressMCQueueMinLimitBytes))) { 5965 int delta = 0; /* In Cells */ 5966 delta = ((arg / granularity) - cur_val) * granularity; 5967 if (delta > egr_db_shd_size) { 5968 return BCM_E_PARAM; 5969 } 5970 SOC_IF_ERROR_RETURN( 5971 soc_hx5_mmu_config_shared_buf_recalc(unit, 2 /* egr */, -1, 5972 egr_db_shd_size - delta, 5973 egr_qe_shd_size, 1)); 5974 } 5975 5976 5977 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 5978 if (mem2 != INVALIDm) { 5979 BCM_IF_ERROR_RETURN 5980 (soc_mem_read(unit, mem2, MEM_BLOCK_ALL, startq, entry2)); 5981 } 5982 /* Check for min/max values */ 5983 max_val = (1 << soc_mem_field_length(unit, mem, fld_limit)) - 1; 5984 if ((arg < 0) || ((arg/granularity) > max_val)) { 5985 return BCM_E_PARAM; 5986 } else { 5987 soc_mem_field32_set(unit, mem, entry, fld_limit, (arg/granularity)); 5988 } 5989 5990 if ((type == bcmCosqControlEgressUCQueueMinLimitBytes) || 5991 (type == bcmCosqControlEgressUCQueueSharedLimitBytes)) { 5992 soc_mem_field32_set(unit, mem2, entry2, DISABLE_QUEUINGf, 5993 disable_queuing); 5994 } 5995 5996 if (mc_qlimit_enable) { 5997 soc_mem_field32_set(unit, mem, entry, Q_LIMIT_ENABLEf, 1); 5998 soc_mem_field32_set(unit, mem2, entry2, Q_LIMIT_ENABLEf, 1); 5999 } 6000 6001 if (uc_qlimit_enable) { 6002 soc_mem_field32_set(unit, mem2, entry2, Q_LIMIT_ENABLEf, 1); 6003 } 6004 6005 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 6006 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem2, MEM_BLOCK_ALL, startq, 6007 entry2)); 6008 6009 if (post_update && 6010 ((type == bcmCosqControlEgressUCQueueMinLimitBytes) || 6011 (type == bcmCosqControlEgressMCQueueMinLimitBytes))) { 6012 int delta = 0; 6013 delta = (cur_val - (arg / granularity)) * granularity; 6014 6015 SOC_IF_ERROR_RETURN( 6016 soc_hx5_mmu_config_shared_buf_recalc(unit, 2 /* egr */, -1, 6017 egr_db_shd_size + delta, 6018 egr_qe_shd_size, 0)); 6019 } 6020 6021 return BCM_E_NONE; 6022 } 6023 6024 6025 STATIC int 6026 _bcm_hx5_cosq_egr_queue_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 6027 bcm_cosq_control_t type, int *arg) 6028 { 6029 bcm_port_t local_port; 6030 int pipe, startq; 6031 uint32 entry[SOC_MAX_MEM_WORDS]; 6032 soc_mem_t mem = INVALIDm; 6033 soc_field_t fld_limit = INVALIDf; 6034 int granularity = 1; 6035 int from_cos, to_cos, ci; 6036 6037 if (!arg) { 6038 return BCM_E_PARAM; 6039 } 6040 6041 if ((type == bcmCosqControlEgressUCQueueMinLimitBytes) || 6042 (type == bcmCosqControlEgressUCQueueSharedLimitBytes)) { 6043 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 6044 BCM_IF_ERROR_RETURN 6045 (_bcm_hx5_cosq_index_resolve(unit, gport, cosq, 6046 _BCM_HX5_COSQ_INDEX_STYLE_UCAST_QUEUE, 6047 &local_port, &startq, NULL)); 6048 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 6049 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 6050 return BCM_E_PARAM; 6051 } 6052 else { 6053 if (cosq == BCM_COS_INVALID) { 6054 from_cos = to_cos = 0; 6055 } else { 6056 from_cos = to_cos = cosq; 6057 } 6058 6059 BCM_IF_ERROR_RETURN 6060 (_bcm_hx5_cosq_localport_resolve(unit, gport, &local_port)); 6061 if (local_port < 0) { 6062 return BCM_E_PORT; 6063 } 6064 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 6065 for (ci = from_cos; ci <= to_cos; ci++) { 6066 BCM_IF_ERROR_RETURN 6067 (_bcm_hx5_cosq_index_resolve 6068 (unit, local_port, ci, _BCM_HX5_COSQ_INDEX_STYLE_UCAST_QUEUE, 6069 NULL, &startq, NULL)); 6070 } 6071 } 6072 mem = SOC_MEM_UNIQUE_ACC(unit, MMU_THDU_CONFIG_QUEUEm)[pipe]; 6073 } else if ((type == bcmCosqControlEgressMCQueueMinLimitBytes) || 6074 (type == bcmCosqControlEgressMCQueueSharedLimitBytes)) { 6075 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 6076 return BCM_E_PARAM; 6077 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 6078 BCM_IF_ERROR_RETURN 6079 (_bcm_hx5_cosq_index_resolve(unit, gport, cosq, 6080 _BCM_HX5_COSQ_INDEX_STYLE_MCAST_QUEUE, 6081 &local_port, &startq, NULL)); 6082 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 6083 } 6084 else { 6085 if (cosq == BCM_COS_INVALID) { 6086 from_cos = to_cos = 0; 6087 } else { 6088 from_cos = to_cos = cosq; 6089 } 6090 6091 BCM_IF_ERROR_RETURN 6092 (_bcm_hx5_cosq_localport_resolve(unit, gport, &local_port)); 6093 if (local_port < 0) { 6094 return BCM_E_PORT; 6095 } 6096 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 6097 for (ci = from_cos; ci <= to_cos; ci++) { 6098 BCM_IF_ERROR_RETURN 6099 (_bcm_hx5_cosq_index_resolve 6100 (unit, local_port, ci, _BCM_HX5_COSQ_INDEX_STYLE_MCAST_QUEUE, 6101 NULL, &startq, NULL)); 6102 } 6103 } 6104 mem = SOC_MEM_UNIQUE_ACC(unit, MMU_THDM_DB_QUEUE_CONFIGm)[pipe]; 6105 } else { 6106 return BCM_E_PARAM; 6107 } 6108 6109 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, 6110 startq, entry)); 6111 6112 switch (type) { 6113 case bcmCosqControlEgressUCQueueSharedLimitBytes: 6114 fld_limit = Q_SHARED_LIMIT_CELLf; 6115 granularity = 1; 6116 break; 6117 case bcmCosqControlEgressMCQueueSharedLimitBytes: 6118 fld_limit = Q_SHARED_LIMITf; 6119 granularity = 1; 6120 break; 6121 case bcmCosqControlEgressUCQueueMinLimitBytes: 6122 fld_limit = Q_MIN_LIMIT_CELLf; 6123 granularity = 1; 6124 break; 6125 case bcmCosqControlEgressMCQueueMinLimitBytes: 6126 fld_limit = Q_MIN_LIMITf; 6127 granularity = 1; 6128 break; 6129 default: 6130 return BCM_E_UNAVAIL; 6131 } 6132 *arg = soc_mem_field32_get(unit, mem, entry, fld_limit); 6133 *arg = (*arg) * granularity * _HX5_MMU_BYTES_PER_CELL; 6134 return BCM_E_NONE; 6135 } 6136 6137 STATIC int 6138 _bcm_hx5_cosq_egr_queue_limit_enable_set(int unit, bcm_gport_t gport, 6139 bcm_cos_queue_t cosq, 6140 bcm_cosq_control_t type, 6141 int arg) 6142 { 6143 bcm_port_t local_port; 6144 int startq, pipe; 6145 uint32 entry[SOC_MAX_MEM_WORDS]; 6146 soc_mem_t mem = INVALIDm, base_mem = INVALIDm; 6147 int enable; 6148 6149 if (arg < 0) { 6150 return BCM_E_PARAM; 6151 } 6152 6153 arg = arg ? 1 : 0; 6154 6155 if (type == bcmCosqControlEgressUCQueueLimitEnable) { 6156 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 6157 BCM_IF_ERROR_RETURN 6158 (_bcm_hx5_cosq_index_resolve(unit, gport, cosq, 6159 _BCM_HX5_COSQ_INDEX_STYLE_UCAST_QUEUE, 6160 &local_port, &startq, NULL)); 6161 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 6162 return BCM_E_PARAM; 6163 } else { 6164 if (cosq < 0) { 6165 return BCM_E_PARAM; 6166 } 6167 BCM_IF_ERROR_RETURN 6168 (_bcm_hx5_cosq_localport_resolve(unit, gport, &local_port)); 6169 if (local_port < 0) { 6170 return BCM_E_PORT; 6171 } 6172 BCM_IF_ERROR_RETURN 6173 (_bcm_hx5_cosq_index_resolve 6174 (unit, local_port, cosq, _BCM_HX5_COSQ_INDEX_STYLE_UCAST_QUEUE, 6175 NULL, &startq, NULL)); 6176 } 6177 6178 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 6179 6180 base_mem = MMU_THDU_Q_TO_QGRP_MAPm; 6181 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 6182 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 6183 enable = soc_mem_field32_get(unit, mem, entry, Q_LIMIT_ENABLEf); 6184 if (enable != arg) { 6185 soc_mem_field32_set(unit, mem, entry, Q_LIMIT_ENABLEf, arg); 6186 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 6187 } 6188 } else if (type == bcmCosqControlEgressMCQueueLimitEnable) { 6189 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 6190 return BCM_E_PARAM; 6191 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 6192 BCM_IF_ERROR_RETURN 6193 (_bcm_hx5_cosq_index_resolve(unit, gport, cosq, 6194 _BCM_HX5_COSQ_INDEX_STYLE_MCAST_QUEUE, 6195 &local_port, &startq, NULL)); 6196 } else { 6197 if (cosq < 0) { 6198 return BCM_E_PARAM; 6199 } 6200 BCM_IF_ERROR_RETURN 6201 (_bcm_hx5_cosq_localport_resolve(unit, gport, &local_port)); 6202 if (local_port < 0) { 6203 return BCM_E_PORT; 6204 } 6205 BCM_IF_ERROR_RETURN 6206 (_bcm_hx5_cosq_index_resolve(unit, local_port, cosq, 6207 _BCM_HX5_COSQ_INDEX_STYLE_MCAST_QUEUE, 6208 NULL, &startq, NULL)); 6209 } 6210 6211 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 6212 6213 base_mem = MMU_THDM_MCQE_QUEUE_CONFIGm; 6214 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 6215 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 6216 enable = soc_mem_field32_get(unit, mem, entry, Q_LIMIT_ENABLEf); 6217 if (enable != arg) { 6218 soc_mem_field32_set(unit, mem, entry, Q_LIMIT_ENABLEf, arg); 6219 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 6220 } 6221 6222 base_mem = MMU_THDM_DB_QUEUE_CONFIGm; 6223 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 6224 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 6225 enable = soc_mem_field32_get(unit, mem, entry, Q_LIMIT_ENABLEf); 6226 if (enable != arg) { 6227 soc_mem_field32_set(unit, mem, entry, Q_LIMIT_ENABLEf, arg); 6228 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 6229 } 6230 } else { 6231 return BCM_E_PARAM; 6232 } 6233 6234 return BCM_E_NONE; 6235 } 6236 6237 STATIC int 6238 _bcm_hx5_cosq_egr_queue_limit_enable_get(int unit, bcm_gport_t gport, 6239 bcm_cos_queue_t cosq, 6240 bcm_cosq_control_t type, 6241 int *arg) 6242 { 6243 bcm_port_t local_port; 6244 int startq, pipe; 6245 uint32 entry[SOC_MAX_MEM_WORDS]; 6246 soc_mem_t mem = INVALIDm, base_mem = INVALIDm; 6247 6248 if (type == bcmCosqControlEgressUCQueueLimitEnable) { 6249 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 6250 BCM_IF_ERROR_RETURN 6251 (_bcm_hx5_cosq_index_resolve(unit, gport, cosq, 6252 _BCM_HX5_COSQ_INDEX_STYLE_UCAST_QUEUE, 6253 &local_port, &startq, NULL)); 6254 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 6255 return BCM_E_PARAM; 6256 } else { 6257 if (cosq < 0) { 6258 return BCM_E_PARAM; 6259 } 6260 BCM_IF_ERROR_RETURN 6261 (_bcm_hx5_cosq_localport_resolve(unit, gport, &local_port)); 6262 if (local_port < 0) { 6263 return BCM_E_PORT; 6264 } 6265 BCM_IF_ERROR_RETURN 6266 (_bcm_hx5_cosq_index_resolve 6267 (unit, local_port, cosq, _BCM_HX5_COSQ_INDEX_STYLE_UCAST_QUEUE, 6268 NULL, &startq, NULL)); 6269 } 6270 6271 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 6272 6273 base_mem = MMU_THDU_Q_TO_QGRP_MAPm; 6274 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 6275 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 6276 *arg = soc_mem_field32_get(unit, mem, entry, Q_LIMIT_ENABLEf); 6277 } else if (type == bcmCosqControlEgressMCQueueLimitEnable) { 6278 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 6279 return BCM_E_PARAM; 6280 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 6281 BCM_IF_ERROR_RETURN 6282 (_bcm_hx5_cosq_index_resolve(unit, gport, cosq, 6283 _BCM_HX5_COSQ_INDEX_STYLE_MCAST_QUEUE, 6284 &local_port, &startq, NULL)); 6285 } else { 6286 if (cosq < 0) { 6287 return BCM_E_PARAM; 6288 } 6289 BCM_IF_ERROR_RETURN 6290 (_bcm_hx5_cosq_localport_resolve(unit, gport, &local_port)); 6291 if (local_port < 0) { 6292 return BCM_E_PORT; 6293 } 6294 BCM_IF_ERROR_RETURN 6295 (_bcm_hx5_cosq_index_resolve(unit, local_port, cosq, 6296 _BCM_HX5_COSQ_INDEX_STYLE_MCAST_QUEUE, 6297 NULL, &startq, NULL)); 6298 } 6299 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 6300 6301 base_mem = MMU_THDM_MCQE_QUEUE_CONFIGm; 6302 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 6303 6304 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 6305 *arg = soc_mem_field32_get(unit, mem, entry, Q_LIMIT_ENABLEf); 6306 } else { 6307 return BCM_E_PARAM; 6308 } 6309 return BCM_E_NONE; 6310 } 6311 6312 STATIC int 6313 _bcm_hx5_cosq_egr_port_pool_set(int unit, bcm_gport_t gport, 6314 bcm_cos_queue_t cosq, 6315 bcm_cosq_control_t type, int arg) 6316 { 6317 bcm_port_t local_port; 6318 uint32 max_val; 6319 uint32 entry[SOC_MAX_MEM_WORDS]; 6320 soc_mem_t mem = INVALIDm, base_mem = INVALIDm; 6321 soc_field_t fld_limit = INVALIDf; 6322 int granularity = 1; 6323 int pool, midx, pipe; 6324 6325 if (arg < 0) { 6326 return BCM_E_PARAM; 6327 } 6328 6329 BCM_IF_ERROR_RETURN 6330 (_bcm_hx5_cosq_index_resolve(unit, gport, cosq, 6331 _BCM_HX5_COSQ_INDEX_STYLE_EGR_POOL, 6332 &local_port, &pool, NULL)); 6333 6334 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 6335 6336 if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) || IS_CPU_PORT(unit, local_port)) { 6337 base_mem = MMU_THDM_DB_PORTSP_CONFIGm; 6338 } else { 6339 base_mem = MMU_THDU_CONFIG_PORTm; 6340 } 6341 6342 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 6343 midx = SOC_TD3_MMU_PIPED_MEM_INDEX(unit, local_port, base_mem, pool); 6344 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, entry)); 6345 6346 switch (type) { 6347 case bcmCosqControlEgressPortPoolYellowLimitBytes: 6348 if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) || IS_CPU_PORT(unit, local_port)) { 6349 fld_limit = YELLOW_SHARED_LIMITf; 6350 } else { 6351 fld_limit = YELLOW_LIMITf; 6352 } 6353 granularity = 8; 6354 break; 6355 case bcmCosqControlEgressPortPoolRedLimitBytes: 6356 if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) || IS_CPU_PORT(unit, local_port)) { 6357 fld_limit = RED_SHARED_LIMITf; 6358 } else { 6359 fld_limit = RED_LIMITf; 6360 } 6361 granularity = 8; 6362 break; 6363 default: 6364 return BCM_E_UNAVAIL; 6365 } 6366 6367 arg = (arg + _HX5_MMU_BYTES_PER_CELL - 1) / _HX5_MMU_BYTES_PER_CELL; 6368 6369 /* Check for min/max values */ 6370 max_val = (1 << soc_mem_field_length(unit, mem, fld_limit)) - 1; 6371 if ((arg < 0) || ((arg/granularity) > max_val)) { 6372 return BCM_E_PARAM; 6373 } else { 6374 soc_mem_field32_set(unit, mem, entry, fld_limit, (arg/granularity)); 6375 } 6376 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, midx, entry)); 6377 6378 return BCM_E_NONE; 6379 } 6380 6381 STATIC int 6382 _bcm_hx5_cosq_egr_port_pool_get(int unit, bcm_gport_t gport, 6383 bcm_cos_queue_t cosq, 6384 bcm_cosq_control_t type, int *arg) 6385 { 6386 bcm_port_t local_port; 6387 uint32 entry[SOC_MAX_MEM_WORDS]; 6388 soc_mem_t mem = INVALIDm, base_mem = INVALIDm; 6389 int granularity = 1; 6390 int pool, midx, pipe; 6391 6392 if (!arg) { 6393 return BCM_E_PARAM; 6394 } 6395 6396 BCM_IF_ERROR_RETURN 6397 (_bcm_hx5_cosq_index_resolve(unit, gport, cosq, 6398 _BCM_HX5_COSQ_INDEX_STYLE_EGR_POOL, 6399 &local_port, &pool, NULL)); 6400 6401 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 6402 6403 if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) || IS_CPU_PORT(unit, local_port)) { 6404 base_mem = MMU_THDM_DB_PORTSP_CONFIGm; 6405 } else { 6406 base_mem = MMU_THDU_CONFIG_PORTm; 6407 } 6408 6409 6410 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 6411 midx = SOC_TD3_MMU_PIPED_MEM_INDEX(unit, local_port, base_mem, pool); 6412 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, entry)); 6413 6414 switch (type) { 6415 case bcmCosqControlEgressPortPoolYellowLimitBytes: 6416 if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) || IS_CPU_PORT(unit, local_port)) { 6417 *arg = soc_mem_field32_get(unit, mem, entry, 6418 YELLOW_SHARED_LIMITf); 6419 } else { 6420 *arg = soc_mem_field32_get(unit, mem, entry, YELLOW_LIMITf); 6421 } 6422 granularity = 8; 6423 break; 6424 case bcmCosqControlEgressPortPoolRedLimitBytes: 6425 if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) || IS_CPU_PORT(unit, local_port)) { 6426 *arg = soc_mem_field32_get(unit, mem, entry, RED_SHARED_LIMITf); 6427 } else { 6428 *arg = soc_mem_field32_get(unit, mem, entry, RED_LIMITf); 6429 } 6430 granularity = 8; 6431 break; 6432 default: 6433 return BCM_E_UNAVAIL; 6434 } 6435 6436 *arg = (*arg) * granularity * _HX5_MMU_BYTES_PER_CELL; 6437 return BCM_E_NONE; 6438 } 6439 6440 /* 6441 * This function is used to get the 6442 * Min and Max value of ingress PG or SP 6443 */ 6444 STATIC int 6445 _bcm_hx5_cosq_ing_res_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 6446 bcm_cosq_control_t type, int *arg) 6447 { 6448 bcm_port_t local_port; 6449 int midx; 6450 uint32 entry[SOC_MAX_MEM_WORDS]; 6451 soc_mem_t mem = INVALIDm, base_mem = INVALIDm; 6452 soc_field_t fld_limit = INVALIDf; 6453 int pipe, port_pg; 6454 int pool, granularity = 1; 6455 6456 if ((cosq < 0) || (cosq >= _HX5_MMU_NUM_INT_PRI)) { 6457 /* Error. Input pri > Max Pri_Grp */ 6458 return BCM_E_PARAM; 6459 } 6460 6461 if (arg == NULL) { 6462 return BCM_E_PARAM; 6463 } 6464 6465 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 6466 BCM_GPORT_IS_SCHEDULER(gport) || 6467 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 6468 return BCM_E_PARAM; 6469 } 6470 6471 BCM_IF_ERROR_RETURN 6472 (_bcm_hx5_cosq_localport_resolve(unit, gport, &local_port)); 6473 if (local_port < 0) { 6474 return BCM_E_PORT; 6475 } 6476 6477 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 6478 BCM_IF_ERROR_RETURN 6479 (_bcm_hx5_cosq_ingress_pg_get(unit, gport, cosq, &port_pg, NULL)); 6480 BCM_IF_ERROR_RETURN 6481 (_bcm_hx5_cosq_ingress_sp_get(unit, gport, cosq, &pool, NULL)); 6482 6483 if ((type == bcmCosqControlIngressPortPGSharedLimitBytes) || 6484 (type == bcmCosqControlIngressPortPGMinLimitBytes) || 6485 (type == bcmCosqControlIngressPortPGHeadroomLimitBytes) || 6486 (type == bcmCosqControlIngressPortPGResetFloorBytes)) { 6487 base_mem = THDI_PORT_PG_CONFIGm; 6488 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 6489 /* get index for Port-PG */ 6490 midx = SOC_TD3_MMU_PIPED_MEM_INDEX(unit, local_port, base_mem, port_pg); 6491 } else if ((type == bcmCosqControlIngressPortPoolMaxLimitBytes) || 6492 (type == bcmCosqControlIngressPortPoolMinLimitBytes)) { 6493 base_mem = THDI_PORT_SP_CONFIGm; 6494 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 6495 /* get index for Port-SP */ 6496 midx = SOC_TD3_MMU_PIPED_MEM_INDEX(unit, local_port, base_mem, pool); 6497 } else { 6498 return BCM_E_UNAVAIL; 6499 } 6500 6501 if (midx < 0) { 6502 return BCM_E_PARAM; 6503 } 6504 6505 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, entry)); 6506 6507 switch (type) { 6508 case bcmCosqControlIngressPortPGSharedLimitBytes: 6509 fld_limit = PG_SHARED_LIMITf; 6510 granularity = 1; 6511 break; 6512 case bcmCosqControlIngressPortPoolMaxLimitBytes: 6513 fld_limit = PORT_SP_MAX_LIMITf; 6514 granularity = 1; 6515 break; 6516 case bcmCosqControlIngressPortPGMinLimitBytes: 6517 fld_limit = PG_MIN_LIMITf; 6518 granularity = 1; 6519 break; 6520 case bcmCosqControlIngressPortPoolMinLimitBytes: 6521 fld_limit = PORT_SP_MIN_LIMITf; 6522 granularity = 1; 6523 break; 6524 case bcmCosqControlIngressPortPGHeadroomLimitBytes: 6525 fld_limit = PG_HDRM_LIMITf; 6526 granularity = 1; 6527 break; 6528 case bcmCosqControlIngressPortPGResetFloorBytes: 6529 fld_limit = PG_RESET_FLOORf; 6530 granularity = 1; 6531 break; 6532 /* coverity[dead_error_begin] */ 6533 default: 6534 return BCM_E_UNAVAIL; 6535 } 6536 6537 *arg = soc_mem_field32_get(unit, mem, entry, fld_limit); 6538 *arg = (*arg) * granularity * _HX5_MMU_BYTES_PER_CELL; 6539 6540 return BCM_E_NONE; 6541 } 6542 6543 STATIC int 6544 _bcm_hx5_cosq_ing_res_set(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 6545 bcm_cosq_control_t type, int arg) 6546 { 6547 bcm_port_t local_port; 6548 int midx; 6549 uint32 max_val; 6550 uint32 entry[SOC_MAX_MEM_WORDS]; 6551 soc_mem_t mem = INVALIDm, base_mem = INVALIDm; 6552 soc_field_t fld_limit = INVALIDf; 6553 int pipe, port_pg; 6554 int pool, granularity = 1; 6555 int ing_shd_size, cur_val; 6556 6557 if ((cosq < 0) || (cosq >= _HX5_MMU_NUM_INT_PRI)) { 6558 /* Error. Input pri > Max Pri_Grp */ 6559 return BCM_E_PARAM; 6560 } 6561 6562 if (arg < 0) { 6563 return BCM_E_PARAM; 6564 } 6565 6566 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 6567 BCM_GPORT_IS_SCHEDULER(gport) || 6568 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 6569 return BCM_E_PARAM; 6570 } 6571 6572 arg = (arg + _HX5_MMU_BYTES_PER_CELL - 1) / _HX5_MMU_BYTES_PER_CELL; 6573 BCM_IF_ERROR_RETURN 6574 (_bcm_hx5_cosq_localport_resolve(unit, gport, &local_port)); 6575 if (local_port < 0) { 6576 return BCM_E_PORT; 6577 } 6578 6579 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 6580 BCM_IF_ERROR_RETURN 6581 (_bcm_hx5_cosq_ingress_pg_get(unit, gport, cosq, &port_pg, NULL)); 6582 BCM_IF_ERROR_RETURN 6583 (_bcm_hx5_cosq_ingress_sp_get(unit, gport, cosq, &pool, NULL)); 6584 6585 if ((type == bcmCosqControlIngressPortPGSharedLimitBytes) || 6586 (type == bcmCosqControlIngressPortPGMinLimitBytes) || 6587 (type == bcmCosqControlIngressPortPGHeadroomLimitBytes) || 6588 (type == bcmCosqControlIngressPortPGResetFloorBytes)) { 6589 base_mem = THDI_PORT_PG_CONFIGm; 6590 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 6591 /* get index for Port-PG */ 6592 midx = SOC_TD3_MMU_PIPED_MEM_INDEX(unit, local_port, base_mem, port_pg); 6593 } else if ((type == bcmCosqControlIngressPortPoolMaxLimitBytes) || 6594 (type == bcmCosqControlIngressPortPoolMinLimitBytes)) { 6595 base_mem = THDI_PORT_SP_CONFIGm; 6596 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 6597 /* get index for Port-SP */ 6598 midx = SOC_TD3_MMU_PIPED_MEM_INDEX(unit, local_port, base_mem, pool); 6599 } else { 6600 return BCM_E_UNAVAIL; 6601 } 6602 6603 if (midx < 0) { 6604 return BCM_E_PARAM; 6605 } 6606 6607 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, entry)); 6608 6609 switch (type) { 6610 case bcmCosqControlIngressPortPGSharedLimitBytes: 6611 fld_limit = PG_SHARED_LIMITf; 6612 granularity = 1; 6613 break; 6614 case bcmCosqControlIngressPortPoolMaxLimitBytes: 6615 fld_limit = PORT_SP_MAX_LIMITf; 6616 granularity = 1; 6617 break; 6618 case bcmCosqControlIngressPortPGMinLimitBytes: 6619 fld_limit = PG_MIN_LIMITf; 6620 granularity = 1; 6621 break; 6622 case bcmCosqControlIngressPortPoolMinLimitBytes: 6623 fld_limit = PORT_SP_MIN_LIMITf; 6624 granularity = 1; 6625 break; 6626 case bcmCosqControlIngressPortPGHeadroomLimitBytes: 6627 fld_limit = PG_HDRM_LIMITf; 6628 granularity = 1; 6629 break; 6630 case bcmCosqControlIngressPortPGResetFloorBytes: 6631 fld_limit = PG_RESET_FLOORf; 6632 granularity = 1; 6633 break; 6634 /* coverity[dead_error_begin] */ 6635 default: 6636 return BCM_E_UNAVAIL; 6637 } 6638 6639 /* Recalculate Shared Values if Min Changed */ 6640 cur_val = soc_mem_field32_get(unit, mem, entry, fld_limit); 6641 6642 if((arg / granularity) == cur_val) { 6643 return BCM_E_NONE; 6644 } 6645 6646 if (type == bcmCosqControlIngressPortPGMinLimitBytes) { 6647 int delta = 0; /* In Cells */ 6648 uint32 rval = 0; 6649 /* Read THDI shared size from Service pool 0 */ 6650 SOC_IF_ERROR_RETURN 6651 (READ_THDI_BUFFER_CELL_LIMIT_SPr(unit, 0, &rval)); 6652 ing_shd_size = soc_reg_field_get(unit, THDI_BUFFER_CELL_LIMIT_SPr, 6653 rval, LIMITf); 6654 if ((arg / granularity) > cur_val) { 6655 /* New Min Val > Cur Min Val 6656 * So reduce the Shared values first and then 6657 * Increase the Min Value for given resource */ 6658 delta = ((arg / granularity) - cur_val) * granularity; 6659 if (delta > ing_shd_size) { 6660 return BCM_E_PARAM; 6661 } 6662 6663 SOC_IF_ERROR_RETURN( 6664 soc_hx5_mmu_config_shared_buf_recalc(unit, 1 /* ing */, 6665 ing_shd_size - delta, 6666 -1, -1, 1)); 6667 6668 /* the value may be changed by soc_hx5_mmu_config_res_limits_update 6669 * so read the register again in order to keep consistent */ 6670 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, entry)); 6671 } 6672 6673 /* Check for min/max values */ 6674 max_val = (1 << soc_mem_field_length(unit, mem, fld_limit)) - 1; 6675 if ((arg < 0) || ((arg/granularity) > max_val)) { 6676 return BCM_E_PARAM; 6677 } 6678 6679 soc_mem_field32_set(unit, mem, entry, fld_limit, (arg/granularity)); 6680 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, midx, entry)); 6681 6682 if ((arg / granularity) < cur_val) { 6683 /* New Min Val < Cur Min Val 6684 * So reduce the Min values first and then 6685 * Increase Shared values everywhere */ 6686 delta = (cur_val - (arg / granularity)) * granularity; 6687 if (delta > ing_shd_size) { 6688 return BCM_E_PARAM; 6689 } 6690 SOC_IF_ERROR_RETURN( 6691 soc_hx5_mmu_config_shared_buf_recalc(unit, 1 /* ing */, 6692 ing_shd_size + delta, 6693 -1, -1, 0)); 6694 } 6695 } else { 6696 /* Check for min/max values */ 6697 max_val = (1 << soc_mem_field_length(unit, mem, fld_limit)) - 1; 6698 if ((arg < 0) || ((arg/granularity) > max_val)) { 6699 return BCM_E_PARAM; 6700 } 6701 soc_mem_field32_set(unit, mem, entry, fld_limit, (arg/granularity)); 6702 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, midx, entry)); 6703 } 6704 6705 return BCM_E_NONE; 6706 } 6707 6708 /* 6709 * This function is used to get ingress pool 6710 * limit given Ingress [Port, Priority] 6711 */ 6712 STATIC int 6713 _bcm_hx5_cosq_ing_res_limit_get(int unit, bcm_gport_t gport, bcm_cos_t cosq, 6714 bcm_cosq_control_t type, int *arg) 6715 { 6716 uint32 rval = 0x0; 6717 int pool; 6718 int local_port; 6719 soc_reg_t reg = INVALIDr; 6720 6721 if (arg == NULL) { 6722 return BCM_E_PARAM; 6723 } 6724 6725 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 6726 BCM_GPORT_IS_SCHEDULER(gport) || 6727 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 6728 return BCM_E_PARAM; 6729 } 6730 6731 BCM_IF_ERROR_RETURN 6732 (_bcm_hx5_cosq_localport_resolve(unit, gport, &local_port)); 6733 6734 if (!SOC_PORT_VALID(unit, local_port)) { 6735 return BCM_E_PORT; 6736 } 6737 6738 if (type == bcmCosqControlIngressPoolLimitBytes) { 6739 BCM_IF_ERROR_RETURN 6740 (_bcm_hx5_cosq_ing_pool_get(unit, gport, cosq, 6741 bcmCosqControlIngressPool, 6742 &pool)); 6743 reg = THDI_BUFFER_CELL_LIMIT_SPr; 6744 } else if (type == bcmCosqControlIngressHeadroomPoolLimitBytes) { 6745 BCM_IF_ERROR_RETURN 6746 (_bcm_hx5_cosq_ing_pool_get(unit, gport, cosq, 6747 bcmCosqControlIngressHeadroomPool, 6748 &pool)); 6749 reg = THDI_HDRM_BUFFER_CELL_LIMIT_HPr; 6750 } else { 6751 return BCM_E_PARAM; 6752 } 6753 6754 SOC_IF_ERROR_RETURN( 6755 soc_trident3_xpe_reg32_get(unit,reg, 6756 -1, 0, pool, &rval)); 6757 *arg = soc_reg_field_get(unit, reg, rval, LIMITf); 6758 6759 *arg *= _HX5_MMU_BYTES_PER_CELL; 6760 6761 return BCM_E_NONE; 6762 } 6763 6764 /* 6765 * This function is used to set ingress pool 6766 * limit given Ingress [Port, Priority] 6767 */ 6768 STATIC int 6769 _bcm_hx5_cosq_ing_res_limit_set(int unit, bcm_gport_t gport, bcm_cos_t cosq, 6770 bcm_cosq_control_t type, int arg) 6771 { 6772 uint32 rval = 0x0; 6773 int pool; 6774 int local_port; 6775 soc_reg_t reg = INVALIDr; 6776 6777 if (arg < 0) { 6778 return BCM_E_PARAM; 6779 } 6780 6781 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 6782 BCM_GPORT_IS_SCHEDULER(gport) || 6783 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 6784 return BCM_E_PARAM; 6785 } 6786 BCM_IF_ERROR_RETURN 6787 (_bcm_hx5_cosq_localport_resolve(unit, gport, &local_port)); 6788 6789 if (!SOC_PORT_VALID(unit, local_port)) { 6790 return BCM_E_PORT; 6791 } 6792 6793 arg = (arg + _HX5_MMU_BYTES_PER_CELL - 1) / _HX5_MMU_BYTES_PER_CELL; 6794 6795 if (type == bcmCosqControlIngressPoolLimitBytes) { 6796 BCM_IF_ERROR_RETURN 6797 (_bcm_hx5_cosq_ing_pool_get(unit, gport, cosq, 6798 bcmCosqControlIngressPool, 6799 &pool)); 6800 reg = THDI_BUFFER_CELL_LIMIT_SPr; 6801 } else if (type == bcmCosqControlIngressHeadroomPoolLimitBytes) { 6802 BCM_IF_ERROR_RETURN 6803 (_bcm_hx5_cosq_ing_pool_get(unit, gport, cosq, 6804 bcmCosqControlIngressHeadroomPool, 6805 &pool)); 6806 reg = THDI_HDRM_BUFFER_CELL_LIMIT_HPr; 6807 } else { 6808 return BCM_E_PARAM; 6809 } 6810 6811 soc_reg_field_set(unit, reg, &rval, LIMITf, arg); 6812 SOC_IF_ERROR_RETURN( 6813 soc_trident3_xpe_reg32_set(unit, reg, 6814 -1, 0, pool, rval)); 6815 6816 return BCM_E_NONE; 6817 } 6818 6819 STATIC int 6820 _bcm_hx5_cosq_dynamic_thresh_enable_set(int unit, 6821 bcm_gport_t gport, bcm_cos_queue_t cosq, 6822 bcm_cosq_control_t type, int arg) 6823 { 6824 bcm_port_t local_port; 6825 int startq, pipe; 6826 int from_cos, to_cos, ci; 6827 int midx; 6828 uint32 rval; 6829 uint32 entry[SOC_MAX_MEM_WORDS]; 6830 uint32 entry2[SOC_MAX_MEM_WORDS]; 6831 soc_mem_t base_mem = INVALIDm, base_mem2 = INVALIDm; 6832 soc_mem_t mem = INVALIDm, mem2 = INVALIDm; 6833 soc_reg_t reg = INVALIDr; 6834 int port_pg; 6835 static const soc_reg_t prigroup_reg[] = { 6836 THDI_PORT_PRI_GRP0r, THDI_PORT_PRI_GRP1r 6837 }; 6838 static const soc_field_t prigroup_field[] = { 6839 PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf, 6840 PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf, 6841 PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf, 6842 PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf 6843 }; 6844 6845 if (type == bcmCosqControlIngressPortPGSharedDynamicEnable) { 6846 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 6847 BCM_GPORT_IS_SCHEDULER(gport) || 6848 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 6849 return BCM_E_PARAM; 6850 } 6851 BCM_IF_ERROR_RETURN 6852 (_bcm_hx5_cosq_localport_resolve(unit, gport, &local_port)); 6853 if (local_port < 0) { 6854 return BCM_E_PORT; 6855 } 6856 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 6857 6858 if ((cosq < 0) || (cosq >= _HX5_MMU_NUM_INT_PRI)) { 6859 /* Error. Input pri > Max Pri_Grp */ 6860 return BCM_E_PARAM; 6861 } 6862 6863 /* get PG for port using Port+Cos */ 6864 if (cosq < _HX5_MMU_NUM_PG) { 6865 reg = prigroup_reg[0]; 6866 } else { 6867 reg = prigroup_reg[1]; 6868 } 6869 6870 SOC_IF_ERROR_RETURN 6871 (soc_reg32_get(unit, reg, local_port, 0, &rval)); 6872 port_pg = soc_reg_field_get(unit, reg, rval, prigroup_field[cosq]); 6873 base_mem = THDI_PORT_PG_CONFIGm; 6874 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 6875 /* get index for Port-PG */ 6876 midx = SOC_TD3_MMU_PIPED_MEM_INDEX(unit, local_port, base_mem, port_pg); 6877 BCM_IF_ERROR_RETURN 6878 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, entry)); 6879 soc_mem_field32_set(unit, mem, entry, 6880 PG_SHARED_DYNAMICf, arg ? 1 : 0); 6881 /* Set default alpha value*/ 6882 if (arg) { 6883 soc_mem_field32_set(unit, mem, entry, PG_SHARED_LIMITf, 6884 SOC_HX5_COSQ_DROP_LIMIT_ALPHA_1_128); 6885 } 6886 SOC_IF_ERROR_RETURN 6887 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, midx, entry)); 6888 } else if (type == bcmCosqControlEgressUCSharedDynamicEnable) { 6889 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 6890 BCM_IF_ERROR_RETURN 6891 (_bcm_hx5_cosq_index_resolve(unit, gport, cosq, 6892 _BCM_HX5_COSQ_INDEX_STYLE_UCAST_QUEUE, 6893 &local_port, &startq, NULL)); 6894 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 6895 return BCM_E_PARAM; 6896 } else { 6897 if (cosq == BCM_COS_INVALID) { 6898 from_cos = to_cos = 0; 6899 } else { 6900 from_cos = to_cos = cosq; 6901 } 6902 6903 BCM_IF_ERROR_RETURN 6904 (_bcm_hx5_cosq_localport_resolve(unit, gport, &local_port)); 6905 if (local_port < 0) { 6906 return BCM_E_PORT; 6907 } 6908 for (ci = from_cos; ci <= to_cos; ci++) { 6909 BCM_IF_ERROR_RETURN 6910 (_bcm_hx5_cosq_index_resolve(unit, local_port, ci, 6911 _BCM_HX5_COSQ_INDEX_STYLE_UCAST_QUEUE, 6912 NULL, &startq, NULL)); 6913 6914 } 6915 } 6916 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 6917 base_mem = MMU_THDU_CONFIG_QUEUEm; 6918 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 6919 6920 BCM_IF_ERROR_RETURN 6921 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 6922 soc_mem_field32_set(unit, mem, entry, 6923 Q_LIMIT_DYNAMIC_CELLf, arg ? 1 : 0); 6924 /* Set default alpha value*/ 6925 if (arg) { 6926 soc_mem_field32_set(unit, mem, entry, Q_SHARED_ALPHA_CELLf, 6927 SOC_HX5_COSQ_DROP_LIMIT_ALPHA_1_128); 6928 } 6929 SOC_IF_ERROR_RETURN 6930 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 6931 } else if (type == bcmCosqControlEgressMCSharedDynamicEnable) { 6932 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 6933 return BCM_E_PARAM; 6934 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 6935 BCM_IF_ERROR_RETURN 6936 (_bcm_hx5_cosq_index_resolve(unit, gport, cosq, 6937 _BCM_HX5_COSQ_INDEX_STYLE_MCAST_QUEUE, 6938 &local_port, &startq, NULL)); 6939 } 6940 else { 6941 if (cosq == BCM_COS_INVALID) { 6942 from_cos = to_cos = 0; 6943 } else { 6944 from_cos = to_cos = cosq; 6945 } 6946 6947 BCM_IF_ERROR_RETURN 6948 (_bcm_hx5_cosq_localport_resolve(unit, gport, &local_port)); 6949 if (local_port < 0) { 6950 return BCM_E_PORT; 6951 } 6952 for (ci = from_cos; ci <= to_cos; ci++) { 6953 BCM_IF_ERROR_RETURN 6954 (_bcm_hx5_cosq_index_resolve(unit, local_port, ci, 6955 _BCM_HX5_COSQ_INDEX_STYLE_MCAST_QUEUE, 6956 NULL, &startq, NULL)); 6957 6958 } 6959 } 6960 6961 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 6962 base_mem = MMU_THDM_DB_QUEUE_CONFIGm; 6963 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 6964 6965 base_mem2 = MMU_THDM_MCQE_QUEUE_CONFIGm; 6966 mem2 = SOC_MEM_UNIQUE_ACC(unit, base_mem2)[pipe]; 6967 6968 BCM_IF_ERROR_RETURN 6969 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 6970 soc_mem_field32_set(unit, mem, entry, Q_LIMIT_DYNAMICf, arg ? 1 : 0); 6971 /* Set default alpha value*/ 6972 if (arg) { 6973 soc_mem_field32_set(unit, mem, entry, Q_SHARED_ALPHAf, 6974 SOC_HX5_COSQ_DROP_LIMIT_ALPHA_1_128); 6975 } 6976 SOC_IF_ERROR_RETURN 6977 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 6978 6979 BCM_IF_ERROR_RETURN 6980 (soc_mem_read(unit, mem2, MEM_BLOCK_ALL, startq, entry2)); 6981 soc_mem_field32_set(unit, mem2, entry2, Q_LIMIT_DYNAMICf, arg ? 1 : 0); 6982 /* Set default alpha value*/ 6983 if (arg) { 6984 soc_mem_field32_set(unit, mem2, entry2, Q_SHARED_ALPHAf, 6985 SOC_HX5_COSQ_DROP_LIMIT_ALPHA_1_128); 6986 } 6987 SOC_IF_ERROR_RETURN 6988 (soc_mem_write(unit, mem2, MEM_BLOCK_ALL, startq, entry2)); 6989 6990 } else { 6991 return BCM_E_PARAM; 6992 } 6993 6994 return BCM_E_NONE; 6995 } 6996 6997 STATIC int 6998 _bcm_hx5_cosq_dynamic_thresh_enable_get(int unit, 6999 bcm_gport_t gport, bcm_cos_queue_t cosq, 7000 bcm_cosq_control_t type, int *arg) 7001 { 7002 bcm_port_t local_port; 7003 int startq, pipe, from_cos, to_cos, ci, midx, port_pg; 7004 uint32 rval; 7005 uint32 entry[SOC_MAX_MEM_WORDS]; 7006 soc_mem_t mem = INVALIDm, base_mem = INVALIDm; 7007 soc_reg_t reg = INVALIDr; 7008 static const soc_reg_t prigroup_reg[] = { 7009 THDI_PORT_PRI_GRP0r, THDI_PORT_PRI_GRP1r 7010 }; 7011 static const soc_field_t prigroup_field[] = { 7012 PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf, 7013 PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf, 7014 PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf, 7015 PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf 7016 }; 7017 7018 if (!arg) { 7019 return BCM_E_PARAM; 7020 } 7021 7022 if (type == bcmCosqControlIngressPortPGSharedDynamicEnable) { 7023 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 7024 BCM_GPORT_IS_SCHEDULER(gport) || 7025 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 7026 return BCM_E_PARAM; 7027 } 7028 BCM_IF_ERROR_RETURN 7029 (_bcm_hx5_cosq_localport_resolve(unit, gport, &local_port)); 7030 if (local_port < 0) { 7031 return BCM_E_PORT; 7032 } 7033 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 7034 7035 if ((cosq < 0) || (cosq >= _HX5_MMU_NUM_INT_PRI)) { 7036 /* Error. Input pri > Max Pri_Grp */ 7037 return BCM_E_PARAM; 7038 } 7039 /* get PG for port using Port+Cos */ 7040 if (cosq < _HX5_MMU_NUM_PG) { 7041 reg = prigroup_reg[0]; 7042 } else { 7043 reg = prigroup_reg[1]; 7044 } 7045 7046 SOC_IF_ERROR_RETURN 7047 (soc_reg32_get(unit, reg, local_port, 0, &rval)); 7048 port_pg = soc_reg_field_get(unit, reg, rval, prigroup_field[cosq]); 7049 base_mem = THDI_PORT_PG_CONFIGm; 7050 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 7051 /* get index for Port-PG */ 7052 midx = SOC_TD3_MMU_PIPED_MEM_INDEX(unit, local_port, base_mem, port_pg); 7053 7054 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, 7055 midx, entry)); 7056 *arg = soc_mem_field32_get(unit, mem, entry, PG_SHARED_DYNAMICf); 7057 7058 } else if (type == bcmCosqControlEgressUCSharedDynamicEnable) { 7059 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 7060 BCM_IF_ERROR_RETURN 7061 (_bcm_hx5_cosq_index_resolve(unit, gport, cosq, 7062 _BCM_HX5_COSQ_INDEX_STYLE_UCAST_QUEUE, 7063 &local_port, &startq, NULL)); 7064 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 7065 return BCM_E_PARAM; 7066 } else { 7067 if (cosq == BCM_COS_INVALID) { 7068 from_cos = to_cos = 0; 7069 } else { 7070 from_cos = to_cos = cosq; 7071 } 7072 7073 BCM_IF_ERROR_RETURN 7074 (_bcm_hx5_cosq_localport_resolve(unit, gport, &local_port)); 7075 if (local_port < 0) { 7076 return BCM_E_PORT; 7077 } 7078 for (ci = from_cos; ci <= to_cos; ci++) { 7079 BCM_IF_ERROR_RETURN 7080 (_bcm_hx5_cosq_index_resolve(unit, local_port, ci, 7081 _BCM_HX5_COSQ_INDEX_STYLE_UCAST_QUEUE, 7082 NULL, &startq, NULL)); 7083 } 7084 } 7085 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 7086 base_mem = MMU_THDU_CONFIG_QUEUEm; 7087 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 7088 7089 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, 7090 startq, entry)); 7091 *arg = soc_mem_field32_get(unit, mem, entry, Q_LIMIT_DYNAMIC_CELLf); 7092 } else if (type == bcmCosqControlEgressMCSharedDynamicEnable) { 7093 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 7094 return BCM_E_PARAM; 7095 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 7096 BCM_IF_ERROR_RETURN 7097 (_bcm_hx5_cosq_index_resolve(unit, gport, cosq, 7098 _BCM_HX5_COSQ_INDEX_STYLE_MCAST_QUEUE, 7099 &local_port, &startq, NULL)); 7100 } 7101 else { 7102 if (cosq == BCM_COS_INVALID) { 7103 from_cos = to_cos = 0; 7104 } else { 7105 from_cos = to_cos = cosq; 7106 } 7107 7108 BCM_IF_ERROR_RETURN 7109 (_bcm_hx5_cosq_localport_resolve(unit, gport, &local_port)); 7110 if (local_port < 0) { 7111 return BCM_E_PORT; 7112 } 7113 for (ci = from_cos; ci <= to_cos; ci++) { 7114 BCM_IF_ERROR_RETURN 7115 (_bcm_hx5_cosq_index_resolve(unit, local_port, ci, 7116 _BCM_HX5_COSQ_INDEX_STYLE_MCAST_QUEUE, 7117 NULL, &startq, NULL)); 7118 } 7119 } 7120 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 7121 base_mem = MMU_THDM_DB_QUEUE_CONFIGm; 7122 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 7123 7124 BCM_IF_ERROR_RETURN 7125 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 7126 *arg = soc_mem_field32_get(unit, mem, entry, Q_LIMIT_DYNAMICf); 7127 } else { 7128 return BCM_E_PARAM; 7129 } 7130 7131 return BCM_E_NONE; 7132 } 7133 7134 STATIC int 7135 _bcm_hx5_cosq_alpha_set(int unit, 7136 bcm_gport_t gport, bcm_cos_queue_t cosq, 7137 bcm_cosq_control_drop_limit_alpha_value_t arg) 7138 { 7139 bcm_port_t local_port; 7140 int startq, midx, pipe; 7141 uint32 rval; 7142 uint32 entry[SOC_MAX_MEM_WORDS]; 7143 uint32 entry2[SOC_MAX_MEM_WORDS]; 7144 soc_mem_t base_mem = INVALIDm, base_mem2 = INVALIDm; 7145 soc_mem_t mem = INVALIDm, mem2 = INVALIDm; 7146 int alpha, dynamic_thresh_mode, port_pg; 7147 soc_reg_t reg = INVALIDr; 7148 static const soc_reg_t prigroup_reg[] = { 7149 THDI_PORT_PRI_GRP0r, THDI_PORT_PRI_GRP1r 7150 }; 7151 static const soc_field_t prigroup_field[] = { 7152 PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf, 7153 PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf, 7154 PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf, 7155 PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf 7156 }; 7157 7158 switch(arg) { 7159 case bcmCosqControlDropLimitAlpha_1_128: 7160 alpha = SOC_HX5_COSQ_DROP_LIMIT_ALPHA_1_128; 7161 break; 7162 case bcmCosqControlDropLimitAlpha_1_64: 7163 alpha = SOC_HX5_COSQ_DROP_LIMIT_ALPHA_1_64; 7164 break; 7165 case bcmCosqControlDropLimitAlpha_1_32: 7166 alpha = SOC_HX5_COSQ_DROP_LIMIT_ALPHA_1_32; 7167 break; 7168 case bcmCosqControlDropLimitAlpha_1_16: 7169 alpha = SOC_HX5_COSQ_DROP_LIMIT_ALPHA_1_16; 7170 break; 7171 case bcmCosqControlDropLimitAlpha_1_8: 7172 alpha = SOC_HX5_COSQ_DROP_LIMIT_ALPHA_1_8; 7173 break; 7174 case bcmCosqControlDropLimitAlpha_1_4: 7175 alpha = SOC_HX5_COSQ_DROP_LIMIT_ALPHA_1_4; 7176 break; 7177 case bcmCosqControlDropLimitAlpha_1_2: 7178 alpha = SOC_HX5_COSQ_DROP_LIMIT_ALPHA_1_2; 7179 break; 7180 case bcmCosqControlDropLimitAlpha_1: 7181 alpha = SOC_HX5_COSQ_DROP_LIMIT_ALPHA_1; 7182 break; 7183 case bcmCosqControlDropLimitAlpha_2: 7184 alpha = SOC_HX5_COSQ_DROP_LIMIT_ALPHA_2; 7185 break; 7186 case bcmCosqControlDropLimitAlpha_4: 7187 alpha = SOC_HX5_COSQ_DROP_LIMIT_ALPHA_4; 7188 break; 7189 case bcmCosqControlDropLimitAlpha_8: 7190 alpha = SOC_HX5_COSQ_DROP_LIMIT_ALPHA_8; 7191 break; 7192 default: 7193 return BCM_E_PARAM; 7194 } 7195 7196 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 7197 BCM_IF_ERROR_RETURN 7198 (_bcm_hx5_cosq_dynamic_thresh_enable_get(unit, gport, cosq, 7199 bcmCosqControlEgressUCSharedDynamicEnable, 7200 &dynamic_thresh_mode)); 7201 if (!dynamic_thresh_mode){ 7202 return BCM_E_CONFIG; 7203 } 7204 7205 BCM_IF_ERROR_RETURN 7206 (_bcm_hx5_cosq_index_resolve(unit, gport, cosq, 7207 _BCM_HX5_COSQ_INDEX_STYLE_UCAST_QUEUE, 7208 &local_port, &startq, NULL)); 7209 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 7210 7211 base_mem = MMU_THDU_CONFIG_QUEUEm; 7212 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 7213 7214 BCM_IF_ERROR_RETURN 7215 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 7216 soc_mem_field32_set(unit, mem, entry, 7217 Q_SHARED_ALPHA_CELLf, alpha); 7218 SOC_IF_ERROR_RETURN 7219 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 7220 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 7221 BCM_IF_ERROR_RETURN 7222 (_bcm_hx5_cosq_dynamic_thresh_enable_get(unit, gport, cosq, 7223 bcmCosqControlEgressMCSharedDynamicEnable, 7224 &dynamic_thresh_mode)); 7225 if (!dynamic_thresh_mode){ 7226 return BCM_E_CONFIG; 7227 } 7228 7229 BCM_IF_ERROR_RETURN 7230 (_bcm_hx5_cosq_index_resolve(unit, gport, cosq, 7231 _BCM_HX5_COSQ_INDEX_STYLE_MCAST_QUEUE, 7232 &local_port, &startq, NULL)); 7233 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 7234 7235 base_mem = MMU_THDM_DB_QUEUE_CONFIGm; 7236 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 7237 7238 base_mem2 = MMU_THDM_MCQE_QUEUE_CONFIGm; 7239 mem2 = SOC_MEM_UNIQUE_ACC(unit, base_mem2)[pipe]; 7240 7241 BCM_IF_ERROR_RETURN 7242 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 7243 soc_mem_field32_set(unit, mem, entry, Q_SHARED_ALPHAf, alpha); 7244 SOC_IF_ERROR_RETURN 7245 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 7246 7247 BCM_IF_ERROR_RETURN 7248 (soc_mem_read(unit, mem2, MEM_BLOCK_ALL, startq, entry2)); 7249 soc_mem_field32_set(unit, mem2, entry2, Q_SHARED_ALPHAf, alpha); 7250 SOC_IF_ERROR_RETURN 7251 (soc_mem_write(unit, mem2, MEM_BLOCK_ALL, startq, entry2)); 7252 } else { 7253 BCM_IF_ERROR_RETURN 7254 (_bcm_hx5_cosq_dynamic_thresh_enable_get(unit, gport, cosq, 7255 bcmCosqControlIngressPortPGSharedDynamicEnable, 7256 &dynamic_thresh_mode)); 7257 if (!dynamic_thresh_mode){ 7258 return BCM_E_CONFIG; 7259 } 7260 7261 BCM_IF_ERROR_RETURN 7262 (_bcm_hx5_cosq_localport_resolve(unit, gport, &local_port)); 7263 if (local_port < 0) { 7264 return BCM_E_PORT; 7265 } 7266 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 7267 7268 if ((cosq < 0) || (cosq >= _HX5_MMU_NUM_INT_PRI)) { 7269 /* Error. Input pri > Max Pri_Grp */ 7270 return BCM_E_PARAM; 7271 } 7272 /* get PG for port using Port+Cos */ 7273 if (cosq < _HX5_MMU_NUM_PG) { 7274 reg = prigroup_reg[0]; 7275 } else { 7276 reg = prigroup_reg[1]; 7277 } 7278 7279 SOC_IF_ERROR_RETURN 7280 (soc_reg32_get(unit, reg, local_port, 0, &rval)); 7281 port_pg = soc_reg_field_get(unit, reg, rval, prigroup_field[cosq]); 7282 base_mem = THDI_PORT_PG_CONFIGm; 7283 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 7284 /* get index for Port-PG */ 7285 midx = SOC_TD3_MMU_PIPED_MEM_INDEX(unit, local_port, base_mem, port_pg); 7286 BCM_IF_ERROR_RETURN 7287 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, entry)); 7288 soc_mem_field32_set(unit, mem, entry, PG_SHARED_LIMITf, alpha); 7289 SOC_IF_ERROR_RETURN 7290 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, midx, entry)); 7291 } 7292 7293 return BCM_E_NONE; 7294 } 7295 7296 7297 STATIC int 7298 _bcm_hx5_cosq_alpha_get(int unit, 7299 bcm_gport_t gport, bcm_cos_queue_t cosq, 7300 bcm_cosq_control_drop_limit_alpha_value_t *arg) 7301 { 7302 bcm_port_t local_port; 7303 int startq, midx, pipe; 7304 uint32 rval; 7305 uint32 entry[SOC_MAX_MEM_WORDS]; 7306 soc_mem_t mem = INVALIDm, base_mem = INVALIDm; 7307 int alpha, dynamic_thresh_mode, port_pg; 7308 soc_reg_t reg = INVALIDr; 7309 static const soc_reg_t prigroup_reg[] = { 7310 THDI_PORT_PRI_GRP0r, THDI_PORT_PRI_GRP1r 7311 }; 7312 static const soc_field_t prigroup_field[] = { 7313 PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf, 7314 PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf, 7315 PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf, 7316 PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf 7317 }; 7318 7319 if (!arg) { 7320 return BCM_E_PARAM; 7321 } 7322 7323 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 7324 BCM_IF_ERROR_RETURN 7325 (_bcm_hx5_cosq_dynamic_thresh_enable_get(unit, gport, cosq, 7326 bcmCosqControlEgressUCSharedDynamicEnable, 7327 &dynamic_thresh_mode)); 7328 if (!dynamic_thresh_mode){ 7329 return BCM_E_CONFIG; 7330 } 7331 7332 BCM_IF_ERROR_RETURN 7333 (_bcm_hx5_cosq_index_resolve(unit, gport, cosq, 7334 _BCM_HX5_COSQ_INDEX_STYLE_UCAST_QUEUE, 7335 &local_port, &startq, NULL)); 7336 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 7337 7338 base_mem = MMU_THDU_CONFIG_QUEUEm; 7339 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 7340 7341 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, 7342 startq, entry)); 7343 alpha = soc_mem_field32_get(unit, mem, entry, Q_SHARED_ALPHA_CELLf); 7344 7345 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 7346 BCM_IF_ERROR_RETURN 7347 (_bcm_hx5_cosq_dynamic_thresh_enable_get(unit, gport, cosq, 7348 bcmCosqControlEgressMCSharedDynamicEnable, 7349 &dynamic_thresh_mode)); 7350 if (!dynamic_thresh_mode){ 7351 return BCM_E_CONFIG; 7352 } 7353 7354 BCM_IF_ERROR_RETURN 7355 (_bcm_hx5_cosq_index_resolve(unit, gport, cosq, 7356 _BCM_HX5_COSQ_INDEX_STYLE_MCAST_QUEUE, 7357 &local_port, &startq, NULL)); 7358 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 7359 7360 base_mem = MMU_THDM_DB_QUEUE_CONFIGm; 7361 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 7362 BCM_IF_ERROR_RETURN 7363 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 7364 alpha = soc_mem_field32_get(unit, mem, entry, Q_SHARED_ALPHAf); 7365 7366 } else { 7367 BCM_IF_ERROR_RETURN 7368 (_bcm_hx5_cosq_dynamic_thresh_enable_get(unit, gport, cosq, 7369 bcmCosqControlIngressPortPGSharedDynamicEnable, 7370 &dynamic_thresh_mode)); 7371 if (!dynamic_thresh_mode){ 7372 return BCM_E_CONFIG; 7373 } 7374 7375 BCM_IF_ERROR_RETURN 7376 (_bcm_hx5_cosq_localport_resolve(unit, gport, &local_port)); 7377 if (local_port < 0) { 7378 return BCM_E_PORT; 7379 } 7380 7381 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 7382 7383 if ((cosq < 0) || (cosq >= _HX5_MMU_NUM_INT_PRI)) { 7384 /* Error. Input pri > Max Pri_Grp */ 7385 return BCM_E_PARAM; 7386 } 7387 /* get PG for port using Port+Cos */ 7388 if (cosq < _HX5_MMU_NUM_PG) { 7389 reg = prigroup_reg[0]; 7390 } else { 7391 reg = prigroup_reg[1]; 7392 } 7393 7394 SOC_IF_ERROR_RETURN 7395 (soc_reg32_get(unit, reg, local_port, 0, &rval)); 7396 port_pg = soc_reg_field_get(unit, reg, rval, prigroup_field[cosq]); 7397 7398 base_mem = THDI_PORT_PG_CONFIGm; 7399 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 7400 /* get index for Port-PG */ 7401 midx = SOC_TD3_MMU_PIPED_MEM_INDEX(unit, local_port, base_mem, port_pg); 7402 7403 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, 7404 midx, entry)); 7405 alpha = soc_mem_field32_get(unit, mem, entry, PG_SHARED_LIMITf); 7406 7407 } 7408 7409 switch(alpha) { 7410 case SOC_HX5_COSQ_DROP_LIMIT_ALPHA_1_128: 7411 *arg = bcmCosqControlDropLimitAlpha_1_128; 7412 break; 7413 case SOC_HX5_COSQ_DROP_LIMIT_ALPHA_1_64: 7414 *arg = bcmCosqControlDropLimitAlpha_1_64; 7415 break; 7416 case SOC_HX5_COSQ_DROP_LIMIT_ALPHA_1_32: 7417 *arg = bcmCosqControlDropLimitAlpha_1_32; 7418 break; 7419 case SOC_HX5_COSQ_DROP_LIMIT_ALPHA_1_16: 7420 *arg = bcmCosqControlDropLimitAlpha_1_16; 7421 break; 7422 case SOC_HX5_COSQ_DROP_LIMIT_ALPHA_1_8: 7423 *arg = bcmCosqControlDropLimitAlpha_1_8; 7424 break; 7425 case SOC_HX5_COSQ_DROP_LIMIT_ALPHA_1_4: 7426 *arg = bcmCosqControlDropLimitAlpha_1_4; 7427 break; 7428 case SOC_HX5_COSQ_DROP_LIMIT_ALPHA_1_2: 7429 *arg = bcmCosqControlDropLimitAlpha_1_2; 7430 break; 7431 case SOC_HX5_COSQ_DROP_LIMIT_ALPHA_1: 7432 *arg = bcmCosqControlDropLimitAlpha_1; 7433 break; 7434 case SOC_HX5_COSQ_DROP_LIMIT_ALPHA_2: 7435 *arg = bcmCosqControlDropLimitAlpha_2; 7436 break; 7437 case SOC_HX5_COSQ_DROP_LIMIT_ALPHA_4: 7438 *arg = bcmCosqControlDropLimitAlpha_4; 7439 break; 7440 case SOC_HX5_COSQ_DROP_LIMIT_ALPHA_8: 7441 *arg = bcmCosqControlDropLimitAlpha_8; 7442 break; 7443 default: 7444 return BCM_E_PARAM; 7445 } 7446 7447 return BCM_E_NONE; 7448 } 7449 7450 STATIC int 7451 _bcm_hx5_cosq_time_domain_get(int unit, int time_id, int *time_value) 7452 { 7453 uint32 time_domain_val; 7454 soc_reg_t time_domain_reg = TIME_DOMAINr; 7455 7456 if (time_id < 0 || time_id > _BCM_HX5_NUM_TIME_DOMAIN - 1) { 7457 return SOC_E_PARAM; 7458 } 7459 7460 if (time_value == NULL) { 7461 return SOC_E_PARAM; 7462 } 7463 7464 BCM_IF_ERROR_RETURN( 7465 soc_reg32_get(unit, time_domain_reg, REG_PORT_ANY, time_id, &time_domain_val)); 7466 *time_value = soc_reg_field_get(unit, time_domain_reg, 7467 time_domain_val, TIME_DOMAIN_FIELDf); 7468 return SOC_E_NONE; 7469 } 7470 7471 STATIC int 7472 _bcm_hx5_cosq_time_domain_set(int unit, int time_value, int *time_id) 7473 { 7474 int id; 7475 uint32 time_domain_val; 7476 soc_reg_t time_domain_reg = TIME_DOMAINr; 7477 7478 if (time_value < 0 || time_value > 63) { 7479 return SOC_E_PARAM; 7480 } 7481 7482 for (id = 0; id < _BCM_HX5_NUM_TIME_DOMAIN; id++) { 7483 BCM_IF_ERROR_RETURN( 7484 soc_reg32_get(unit, time_domain_reg, REG_PORT_ANY, id, &time_domain_val)); 7485 if (!hx5_time_domain_info[unit][id].ref_count) { 7486 soc_reg_field_set(unit, time_domain_reg, &time_domain_val, 7487 TIME_DOMAIN_FIELDf, time_value); 7488 hx5_time_domain_info[unit][id].ref_count++; 7489 break; 7490 } 7491 } 7492 7493 if (id == _BCM_HX5_NUM_TIME_DOMAIN) { 7494 return BCM_E_RESOURCE; 7495 } 7496 7497 if (time_id) { 7498 *time_id = id; 7499 } 7500 SOC_IF_ERROR_RETURN( 7501 soc_reg32_set(unit, time_domain_reg, REG_PORT_ANY, id, time_domain_val)); 7502 return SOC_E_NONE; 7503 } 7504 7505 /* 7506 * Function: 7507 * bcm_hx5_cosq_wred_resolution_entry_create 7508 * Purpose: 7509 * Assign a unused entry. Default drop rules are WRED drop. 7510 * Parameters: 7511 * unit - (IN) unit number 7512 * index - (OUT) entry index 7513 * Returns: 7514 * BCM_E_XXX 7515 */ 7516 int 7517 bcm_hx5_cosq_wred_resolution_entry_create(int unit, int *index) 7518 { 7519 uint32 i, rval = 0; 7520 soc_reg_t reg = WRED_CONG_NOTIFICATION_RESOLUTION_TABLEr; 7521 7522 for (i = 0; i < _BCM_HX5_NUM_WRED_RESOLUTION_TABLE; i++) { 7523 if (_bcm_hx5_wred_resolution_tbl[i] == 0) { 7524 /* hw reset value */ 7525 soc_reg_field_set(unit, reg, &rval, MMU_CONGESTION_EXPERIENCEf, 0xAAA); 7526 BCM_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, i, rval)); 7527 _bcm_hx5_wred_resolution_tbl[i]++; 7528 *index = i; 7529 return BCM_E_NONE; 7530 } 7531 } 7532 7533 return BCM_E_RESOURCE; 7534 } 7535 7536 /* 7537 * Function: 7538 * bcm_hx5_cosq_wred_resolution_entry_destroy 7539 * Purpose: 7540 * Callback an entry and set its drop rules to WRED drop. 7541 * Parameters: 7542 * unit - (IN) unit number 7543 * index - (IN) entry index 7544 * Returns: 7545 * BCM_E_XXX 7546 */ 7547 int 7548 bcm_hx5_cosq_wred_resolution_entry_destroy(int unit, int index) 7549 { 7550 uint32 rval = 0; 7551 soc_reg_t reg = WRED_CONG_NOTIFICATION_RESOLUTION_TABLEr; 7552 7553 if ((index < 0) || (index >= _BCM_HX5_NUM_WRED_RESOLUTION_TABLE)) { 7554 return BCM_E_PARAM; 7555 } 7556 7557 if (_bcm_hx5_wred_resolution_tbl[index] == 0) { 7558 return BCM_E_NOT_FOUND; 7559 } 7560 7561 /* hw reset value */ 7562 soc_reg_field_set(unit, reg, &rval, MMU_CONGESTION_EXPERIENCEf, 0xAAA); 7563 BCM_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, index, rval)); 7564 _bcm_hx5_wred_resolution_tbl[index] = 0; 7565 7566 return BCM_E_NONE; 7567 } 7568 7569 /* 7570 * Function: 7571 * bcm_hx5_cosq_wred_resolution_set 7572 * Purpose: 7573 * Set one rule of a resolution table entry 7574 * Parameters: 7575 * unit - (IN) unit number 7576 * index - (IN) entry index 7577 * rule - (IN) drop rule 7578 * Returns: 7579 * BCM_E_XXX 7580 * Notes: 7581 * One entry has 12 bits, equals to 6 rules 7582 */ 7583 int 7584 bcm_hx5_cosq_wred_resolution_set(int unit, int index, bcm_cosq_discard_rule_t *rule) 7585 { 7586 uint32 offset, sp, qmin; 7587 uint32 rval, fval, drop; 7588 soc_reg_t reg = WRED_CONG_NOTIFICATION_RESOLUTION_TABLEr; 7589 7590 if ((index < 0) || (index >= _BCM_HX5_NUM_WRED_RESOLUTION_TABLE)) { 7591 return BCM_E_PARAM; 7592 } 7593 7594 if (_bcm_hx5_wred_resolution_tbl[index] == 0) { 7595 return BCM_E_NOT_FOUND; 7596 } 7597 7598 switch (rule->egress_pool_congestion_state) { 7599 case BCM_COSQ_DISCARD_CONGESTION_LOW: 7600 sp = 0; 7601 break; 7602 case BCM_COSQ_DISCARD_CONGESTION_MEDIUM: 7603 sp = 1; 7604 break; 7605 case BCM_COSQ_DISCARD_CONGESTION_HIGH: 7606 sp = 2; 7607 break; 7608 default: 7609 return BCM_E_PARAM; 7610 } 7611 7612 switch (rule->queue_min_congestion_state) { 7613 case BCM_COSQ_DISCARD_CONGESTION_LOW: 7614 qmin = 0; 7615 break; 7616 case BCM_COSQ_DISCARD_CONGESTION_HIGH: 7617 qmin = 1; 7618 break; 7619 default: 7620 return BCM_E_PARAM; 7621 } 7622 7623 switch (rule->action) { 7624 case BCM_COSQ_DISCARD_ACTION_WRED_DROP: 7625 drop = 0x2; 7626 break; 7627 case BCM_COSQ_DISCARD_ACTION_FORCE_DROP: 7628 drop = 0x3; 7629 break; 7630 case BCM_COSQ_DISCARD_ACTION_FORCE_NO_DROP: 7631 drop = 0x0; 7632 break; 7633 default: 7634 return BCM_E_PARAM; 7635 } 7636 7637 BCM_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, index, &rval)); 7638 fval = soc_reg_field_get(unit, reg, rval, MMU_CONGESTION_EXPERIENCEf); 7639 7640 offset = (sp * 2 + qmin) * 2; /* 2 bits per rule */ 7641 fval = (fval & (~(0x3 << offset))) | (drop << offset); 7642 7643 soc_reg_field_set(unit, reg, &rval, MMU_CONGESTION_EXPERIENCEf, fval); 7644 BCM_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, index, rval)); 7645 7646 return BCM_E_NONE; 7647 } 7648 7649 /* 7650 * Function: 7651 * bcm_hx5_cosq_wred_resolution_get 7652 * Purpose: 7653 * Get all rules of a resolution table entry 7654 * Parameters: 7655 * unit - (IN) unit number 7656 * index - (IN) entry index 7657 * max - (IN) rule array size 7658 * rule - (OUT) rule array 7659 * count - (OUT) actual rules count 7660 * Returns: 7661 * BCM_E_XXX 7662 * Notes: 7663 * One entry has 12 bits, equals to 6 rules 7664 */ 7665 int 7666 bcm_hx5_cosq_wred_resolution_get(int unit, int index, int max, 7667 bcm_cosq_discard_rule_t *rule, int *count) 7668 { 7669 uint32 offset, sp, qmin, i = 0; 7670 uint32 rval, fval, action; 7671 soc_reg_t reg = WRED_CONG_NOTIFICATION_RESOLUTION_TABLEr; 7672 uint32 sp_map[3] = { 7673 BCM_COSQ_DISCARD_CONGESTION_LOW, 7674 BCM_COSQ_DISCARD_CONGESTION_MEDIUM, 7675 BCM_COSQ_DISCARD_CONGESTION_HIGH, 7676 }; 7677 uint32 qmin_map[2] = { 7678 BCM_COSQ_DISCARD_CONGESTION_LOW, 7679 BCM_COSQ_DISCARD_CONGESTION_HIGH, 7680 }; 7681 uint32 action_map[4] = { 7682 BCM_COSQ_DISCARD_ACTION_FORCE_NO_DROP, 7683 -1, 7684 BCM_COSQ_DISCARD_ACTION_WRED_DROP, 7685 BCM_COSQ_DISCARD_ACTION_FORCE_DROP, 7686 }; 7687 7688 if ((!count) || 7689 (index < 0) || (index >= _BCM_HX5_NUM_WRED_RESOLUTION_TABLE)) { 7690 return BCM_E_PARAM; 7691 } 7692 7693 *count = 3 * 2; 7694 7695 if (!rule) { 7696 return BCM_E_NONE; 7697 } 7698 7699 BCM_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, index, &rval)); 7700 fval = soc_reg_field_get(unit, reg, rval, MMU_CONGESTION_EXPERIENCEf); 7701 7702 for (sp = 0; sp < 3; sp ++) { 7703 for (qmin = 0; qmin < 2; qmin++) { 7704 offset = (sp * 2 + qmin) * 2; /* 2 bits per rule */ 7705 action = (fval >> offset) & 0x3; 7706 if (i < max) { 7707 rule[i].egress_pool_congestion_state = sp_map[sp]; 7708 rule[i].queue_min_congestion_state = qmin_map[qmin]; 7709 rule[i].action = action_map[action]; 7710 i++; 7711 } 7712 } 7713 } 7714 7715 return BCM_E_NONE; 7716 } 7717 7718 STATIC int 7719 _bcm_hx5_cosq_wred_set(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 7720 uint32 flags, uint32 min_thresh, uint32 max_thresh, 7721 int drop_probability, int gain, int ignore_enable_flags, 7722 uint32 lflags, int refresh_time, uint32 resolution_id, 7723 uint32 use_queue_group) 7724 { 7725 /* Local Variables */ 7726 soc_mem_t wred_config_mem = INVALIDm; 7727 bcm_port_t local_port = -1; 7728 int index, i, start_index, end_index, count = 0; 7729 int end_offset, need_profile = 0, pipe; 7730 uint32 profile_index, old_profile_index; 7731 uint32 wred_flags = 0; 7732 void *entries[9]; 7733 soc_mem_t mems[9]; 7734 static soc_mem_t wred_mems[9] = { 7735 MMU_WRED_DROP_CURVE_PROFILE_0m, MMU_WRED_DROP_CURVE_PROFILE_1m, 7736 MMU_WRED_DROP_CURVE_PROFILE_2m, MMU_WRED_DROP_CURVE_PROFILE_3m, 7737 MMU_WRED_DROP_CURVE_PROFILE_4m, MMU_WRED_DROP_CURVE_PROFILE_5m, 7738 MMU_WRED_DROP_CURVE_PROFILE_6m, MMU_WRED_DROP_CURVE_PROFILE_7m, 7739 MMU_WRED_DROP_CURVE_PROFILE_8m 7740 }; 7741 mmu_wred_drop_curve_profile_0_entry_t entry_tcp_green; 7742 mmu_wred_drop_curve_profile_1_entry_t entry_tcp_yellow; 7743 mmu_wred_drop_curve_profile_2_entry_t entry_tcp_red; 7744 mmu_wred_drop_curve_profile_3_entry_t entry_nontcp_green; 7745 mmu_wred_drop_curve_profile_4_entry_t entry_nontcp_yellow; 7746 mmu_wred_drop_curve_profile_5_entry_t entry_nontcp_red; 7747 mmu_wred_drop_curve_profile_6_entry_t entry_ecn_green; 7748 mmu_wred_drop_curve_profile_7_entry_t entry_ecn_yellow; 7749 mmu_wred_drop_curve_profile_8_entry_t entry_ecn_red; 7750 mmu_wred_config_entry_t entry; 7751 int rate = 0; 7752 int from_pipe, to_pipe; 7753 int time_id,time,old_time,current_time_sel; 7754 int rv = SOC_E_NONE, exists = 0; 7755 7756 wred_flags = flags | lflags; 7757 end_offset = 0; 7758 7759 /* Check Flags for WRED res level - Device-SP/Port-SP/Queues */ 7760 if ((wred_flags & BCM_COSQ_DISCARD_DEVICE) && (port == BCM_GPORT_INVALID)) { 7761 /* (Port == -1) For all Global SPs */ 7762 index = _HX5_WRED_PER_PIPE_GLOBAL_SP_BASE; 7763 count = _HX5_MMU_NUM_POOL; 7764 /*For all pipe*/ 7765 from_pipe = 0; 7766 to_pipe = NUM_PIPE(unit) - 1; 7767 7768 } else { 7769 BCM_IF_ERROR_RETURN 7770 (_bcm_hx5_cosq_localport_resolve(unit, port, &local_port)); 7771 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 7772 from_pipe = to_pipe = pipe; 7773 7774 if (wred_flags & BCM_COSQ_DISCARD_DEVICE) { 7775 BCM_IF_ERROR_RETURN 7776 (_bcm_hx5_cosq_index_resolve(unit, port, cosq, 7777 _BCM_HX5_COSQ_INDEX_STYLE_WRED_DEVICE, 7778 NULL, &index, &count)); 7779 /* (cosq == -1) For all Global SPs */ 7780 } else if (wred_flags & BCM_COSQ_DISCARD_PORT) { 7781 /* Port SP - Given or all SPs of the port */ 7782 BCM_IF_ERROR_RETURN 7783 (_bcm_hx5_cosq_index_resolve(unit, port, cosq, 7784 _BCM_HX5_COSQ_INDEX_STYLE_WRED_PORT, 7785 NULL, &index, &count)); 7786 /* (cosq == -1) For all SPs of the given port */ 7787 } else { 7788 /* Per Queue WRED settings */ 7789 BCM_IF_ERROR_RETURN 7790 (_bcm_hx5_cosq_index_resolve(unit, port, cosq, 7791 _BCM_HX5_COSQ_INDEX_STYLE_WRED_QUEUE, 7792 NULL, &index, &count)); 7793 /* (cosq == -1) For all Queues of the given port */ 7794 } 7795 } 7796 7797 7798 end_offset = (count > 0) ? (count - 1) : 0; 7799 7800 if (index < 0) { 7801 return BCM_E_PARAM; 7802 } 7803 7804 if (refresh_time < 1) { 7805 return BCM_E_PARAM; 7806 } 7807 7808 start_index = index; 7809 end_index = start_index + end_offset; 7810 7811 rate = _bcm_hx5_percent_to_drop_prob(drop_probability); 7812 7813 for (pipe = from_pipe; pipe <= to_pipe; pipe++ ) { 7814 /* Config MMU_WRED_CONFIGm for the respective resource */ 7815 wred_config_mem = MMU_WRED_CONFIGm; 7816 wred_config_mem = SOC_MEM_UNIQUE_ACC(unit, wred_config_mem)[pipe]; 7817 if (wred_config_mem == INVALIDm) { 7818 return BCM_E_PARAM; 7819 } 7820 7821 for (i=0; i < 9; i++) { 7822 mems[i] = INVALIDm; 7823 } 7824 7825 if (wred_flags & (BCM_COSQ_DISCARD_COLOR_ALL | 7826 BCM_COSQ_DISCARD_TCP | 7827 BCM_COSQ_DISCARD_NONTCP | 7828 BCM_COSQ_DISCARD_ECT_MARKED | 7829 BCM_COSQ_DISCARD_RESPONSIVE_DROP | 7830 BCM_COSQ_DISCARD_NON_RESPONSIVE_DROP)) { 7831 need_profile = 1; 7832 7833 if (!(flags & (BCM_COSQ_DISCARD_COLOR_GREEN | 7834 BCM_COSQ_DISCARD_COLOR_YELLOW | 7835 BCM_COSQ_DISCARD_COLOR_RED))) { 7836 flags |= BCM_COSQ_DISCARD_COLOR_ALL; 7837 } 7838 7839 if (!(wred_flags & (BCM_COSQ_DISCARD_NONTCP | 7840 BCM_COSQ_DISCARD_NON_RESPONSIVE_DROP | 7841 BCM_COSQ_DISCARD_ECT_MARKED)) || 7842 ((wred_flags & BCM_COSQ_DISCARD_TCP) || 7843 (wred_flags & BCM_COSQ_DISCARD_RESPONSIVE_DROP))) { 7844 if (flags & BCM_COSQ_DISCARD_COLOR_GREEN) { 7845 mems[0] = wred_mems[0]; 7846 } 7847 if (flags & BCM_COSQ_DISCARD_COLOR_YELLOW) { 7848 mems[1] = wred_mems[1]; 7849 } 7850 if (flags & BCM_COSQ_DISCARD_COLOR_RED) { 7851 mems[2] = wred_mems[2]; 7852 } 7853 } 7854 if ((wred_flags & BCM_COSQ_DISCARD_NONTCP) || 7855 (wred_flags & BCM_COSQ_DISCARD_NON_RESPONSIVE_DROP)){ 7856 if (flags & BCM_COSQ_DISCARD_COLOR_GREEN) { 7857 mems[3] = wred_mems[3]; 7858 } 7859 if (flags & BCM_COSQ_DISCARD_COLOR_YELLOW) { 7860 mems[4] = wred_mems[4]; 7861 } 7862 if (flags & BCM_COSQ_DISCARD_COLOR_RED) { 7863 mems[5] = wred_mems[5]; 7864 } 7865 } 7866 if (wred_flags & BCM_COSQ_DISCARD_ECT_MARKED) { 7867 if (flags & BCM_COSQ_DISCARD_COLOR_GREEN) { 7868 mems[6] = wred_mems[6]; 7869 } 7870 if (flags & BCM_COSQ_DISCARD_COLOR_YELLOW) { 7871 mems[7] = wred_mems[7]; 7872 } 7873 if (flags & BCM_COSQ_DISCARD_COLOR_RED) { 7874 mems[8] = wred_mems[8]; 7875 } 7876 } 7877 } 7878 7879 entries[0] = &entry_tcp_green; 7880 entries[1] = &entry_tcp_yellow; 7881 entries[2] = &entry_tcp_red; 7882 entries[3] = &entry_nontcp_green; 7883 entries[4] = &entry_nontcp_yellow; 7884 entries[5] = &entry_nontcp_red; 7885 entries[6] = &entry_ecn_green; 7886 entries[7] = &entry_ecn_yellow; 7887 entries[8] = &entry_ecn_red; 7888 7889 for (index = start_index; index <= end_index; index++) { 7890 old_profile_index = 0xffffffff; 7891 BCM_IF_ERROR_RETURN 7892 (soc_mem_read(unit, wred_config_mem, MEM_BLOCK_ALL, index, &entry)); 7893 7894 if (need_profile) { 7895 old_profile_index = soc_mem_field32_get(unit, wred_config_mem, 7896 &entry, PROFILE_INDEXf); 7897 7898 BCM_IF_ERROR_RETURN 7899 (soc_profile_mem_get(unit, _bcm_hx5_wred_profile[unit], 7900 old_profile_index, 1, entries)); 7901 7902 for (i = 0; i < HX5_WRED_PROFILE_NUM; i++) { 7903 if (mems[i] == INVALIDm) { 7904 continue; 7905 } 7906 soc_mem_field32_set(unit, wred_mems[i], entries[i], 7907 MIN_THDf, min_thresh); 7908 soc_mem_field32_set(unit, wred_mems[i], entries[i], 7909 MAX_THDf, max_thresh); 7910 soc_mem_field32_set(unit, wred_mems[i], entries[i], 7911 MAX_DROP_RATEf, rate); 7912 } 7913 BCM_IF_ERROR_RETURN 7914 (soc_profile_mem_add(unit, _bcm_hx5_wred_profile[unit], 7915 entries, 1, &profile_index)); 7916 soc_mem_field32_set(unit, wred_config_mem, &entry, PROFILE_INDEXf, profile_index); 7917 } 7918 soc_mem_field32_set(unit, wred_config_mem, &entry, WEIGHTf, gain); 7919 7920 /* Some APIs only modify profiles */ 7921 if (!ignore_enable_flags) { 7922 soc_mem_field32_set(unit, wred_config_mem, &entry, CAP_AVERAGEf, 7923 flags & BCM_COSQ_DISCARD_CAP_AVERAGE ? 1 : 0); 7924 soc_mem_field32_set(unit, wred_config_mem, &entry, WRED_ENf, 7925 flags & BCM_COSQ_DISCARD_ENABLE ? 1 : 0); 7926 soc_mem_field32_set(unit, wred_config_mem, &entry, ECN_MARKING_ENf, 7927 flags & BCM_COSQ_DISCARD_MARK_CONGESTION ? 1 : 0); 7928 } 7929 7930 current_time_sel = soc_mem_field32_get(unit, wred_config_mem, 7931 &entry, TIME_DOMAIN_SELf); 7932 time = refresh_time - 1; 7933 exists = 0; 7934 /* If the time value exist, update reference count only */ 7935 for (time_id = 0; time_id < _BCM_HX5_NUM_TIME_DOMAIN; time_id++) { 7936 BCM_IF_ERROR_RETURN 7937 (_bcm_hx5_cosq_time_domain_get(unit, time_id, &old_time)); 7938 if (time == old_time) { 7939 /* Only set exist flag if this entry reference count already update, 7940 otherwise update reference count */ 7941 if(time_id != current_time_sel){ 7942 soc_mem_field32_set(unit, wred_config_mem, &entry, 7943 TIME_DOMAIN_SELf, time_id); 7944 hx5_time_domain_info[unit][time_id].ref_count++; 7945 hx5_time_domain_info[unit][current_time_sel].ref_count--; 7946 } 7947 exists = 1; 7948 break; 7949 } 7950 } 7951 7952 if(!exists){ 7953 rv = _bcm_hx5_cosq_time_domain_set(unit, time, &time_id); 7954 if(rv == SOC_E_NONE){ 7955 soc_mem_field32_set(unit, wred_config_mem, &entry, 7956 TIME_DOMAIN_SELf, time_id); 7957 hx5_time_domain_info[unit][current_time_sel].ref_count--; 7958 } else { 7959 return rv; 7960 } 7961 } 7962 7963 soc_mem_field32_set(unit, wred_config_mem, &entry, QG_ENf, 7964 use_queue_group ? 1 : 0); 7965 if (flags & BCM_COSQ_DISCARD_MARK_CONGESTION) { 7966 soc_mem_field32_set(unit, wred_config_mem, &entry, 7967 WRED_CONG_NOTIFICATION_RESOLUTION_TABLE_MARKING_INDEXf, 7968 resolution_id); 7969 } else { 7970 soc_mem_field32_set(unit, wred_config_mem, &entry, 7971 WRED_CONG_NOTIFICATION_RESOLUTION_TABLE_DROPPING_INDEXf, 7972 resolution_id); 7973 } 7974 7975 7976 BCM_IF_ERROR_RETURN( 7977 soc_mem_write(unit, wred_config_mem, MEM_BLOCK_ALL, index, &entry)); 7978 7979 if (old_profile_index != 0xffffffff) { 7980 SOC_IF_ERROR_RETURN 7981 (soc_profile_mem_delete(unit, _bcm_hx5_wred_profile[unit], 7982 old_profile_index)); 7983 } 7984 7985 } 7986 7987 } 7988 7989 /* Check Flags for WRED profile based on Color */ 7990 return BCM_E_NONE; 7991 } 7992 7993 /* 7994 * Function: 7995 * _bcm_hx5_cosq_wred_get 7996 * Purpose: 7997 * Configure unicast queue WRED setting 7998 * Parameters: 7999 * unit - (IN) unit number 8000 * port - (IN) port number or GPORT identifier 8001 * cosq - (IN) COS queue number 8002 * flags - (IN/OUT) BCM_COSQ_DISCARD_XXX 8003 * min_thresh - (OUT) Min Threshold 8004 * max_thresh - (OUT) Max Threshold 8005 * drop_probablity - (OUT) Probabilistic drop rate 8006 * gain - (OUT) 8007 * lflags - (IN) Config flags 8008 * refresh_time - (OUT) Time Domain 8009 * resolution_id - (OUT) Resolution index 8010 * use_queue_group - (OUT) Queue group status is used 8011 * Returns: 8012 * BCM_E_XXX 8013 * Notes: 8014 * If port is any form of local port, cosq is the hardware queue index. 8015 */ 8016 STATIC int 8017 _bcm_hx5_cosq_wred_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 8018 uint32 *flags, uint32 *min_thresh, uint32 *max_thresh, 8019 int *drop_probability, int *gain, uint32 lflags, 8020 int *refresh_time, uint32 *resolution_id, 8021 uint32 *use_queue_group) 8022 { 8023 soc_mem_t wred_config_mem = INVALIDm, mem = INVALIDm; 8024 bcm_port_t local_port = -1; 8025 mmu_wred_drop_curve_profile_0_entry_t entry_tcp_green; 8026 mmu_wred_drop_curve_profile_1_entry_t entry_tcp_yellow; 8027 mmu_wred_drop_curve_profile_2_entry_t entry_tcp_red; 8028 mmu_wred_drop_curve_profile_3_entry_t entry_nontcp_green; 8029 mmu_wred_drop_curve_profile_4_entry_t entry_nontcp_yellow; 8030 mmu_wred_drop_curve_profile_5_entry_t entry_nontcp_red; 8031 mmu_wred_drop_curve_profile_6_entry_t entry_ecn_green; 8032 mmu_wred_drop_curve_profile_7_entry_t entry_ecn_yellow; 8033 mmu_wred_drop_curve_profile_8_entry_t entry_ecn_red; 8034 void *entries[9]; 8035 void *entry_p; 8036 int index, profile_index; 8037 mmu_wred_config_entry_t entry; 8038 uint32 wred_flags = 0; 8039 int rate = 0, pipe = -1; 8040 int time_id, time; 8041 8042 if (flags) { 8043 wred_flags = *flags | lflags; 8044 } else { 8045 wred_flags = lflags; 8046 } 8047 8048 if ((wred_flags & BCM_COSQ_DISCARD_DEVICE) && (port == BCM_GPORT_INVALID)) { 8049 /* (Port == -1) For all Global SPs */ 8050 index = _HX5_WRED_PER_PIPE_GLOBAL_SP_BASE; 8051 pipe = 0; 8052 8053 } else { 8054 BCM_IF_ERROR_RETURN 8055 (_bcm_hx5_cosq_localport_resolve(unit, port, &local_port)); 8056 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 8057 8058 /* Check Flags for WRED res level - Device-SP/Port-SP/Queues */ 8059 if(wred_flags & BCM_COSQ_DISCARD_DEVICE) { 8060 BCM_IF_ERROR_RETURN 8061 (_bcm_hx5_cosq_index_resolve(unit, port, cosq, 8062 _BCM_HX5_COSQ_INDEX_STYLE_WRED_DEVICE, 8063 NULL, &index, NULL)); 8064 } else if (wred_flags & BCM_COSQ_DISCARD_PORT) { 8065 /* Port SP - Given or all SPs of the port */ 8066 BCM_IF_ERROR_RETURN 8067 (_bcm_hx5_cosq_index_resolve(unit, port, cosq, 8068 _BCM_HX5_COSQ_INDEX_STYLE_WRED_PORT, 8069 NULL, &index, NULL)); 8070 } else { 8071 /* Per Queue WRED settings */ 8072 BCM_IF_ERROR_RETURN 8073 (_bcm_hx5_cosq_index_resolve(unit, port, cosq, 8074 _BCM_HX5_COSQ_INDEX_STYLE_WRED_QUEUE, 8075 NULL, &index, NULL)); 8076 } 8077 } 8078 8079 if ((index < 0) || (pipe == -1)) { 8080 return BCM_E_PARAM; 8081 } 8082 8083 wred_config_mem = MMU_WRED_CONFIGm; 8084 wred_config_mem = SOC_MEM_UNIQUE_ACC(unit, wred_config_mem)[pipe]; 8085 if (wred_config_mem == INVALIDm) { 8086 return BCM_E_PARAM; 8087 } 8088 8089 BCM_IF_ERROR_RETURN 8090 (soc_mem_read(unit, wred_config_mem, MEM_BLOCK_ALL, index, &entry)); 8091 profile_index = soc_mem_field32_get(unit, wred_config_mem, 8092 &entry, PROFILE_INDEXf); 8093 8094 if (!(wred_flags & (BCM_COSQ_DISCARD_NONTCP | 8095 BCM_COSQ_DISCARD_NON_RESPONSIVE_DROP | 8096 BCM_COSQ_DISCARD_ECT_MARKED))) { 8097 /* By default we will assume 8098 BCM_COSQ_DISCARD_TCP */ 8099 if (wred_flags & BCM_COSQ_DISCARD_COLOR_YELLOW) { 8100 mem = MMU_WRED_DROP_CURVE_PROFILE_1m; 8101 entry_p = &entry_tcp_yellow; 8102 } else if (wred_flags & BCM_COSQ_DISCARD_COLOR_RED) { 8103 mem = MMU_WRED_DROP_CURVE_PROFILE_2m; 8104 entry_p = &entry_tcp_red; 8105 } else { 8106 /* By default we will assume 8107 BCM_COSQ_DISCARD_COLOR_GREEN */ 8108 mem = MMU_WRED_DROP_CURVE_PROFILE_0m; 8109 entry_p = &entry_tcp_green; 8110 } 8111 } else if ((wred_flags & BCM_COSQ_DISCARD_NONTCP) || 8112 (wred_flags & BCM_COSQ_DISCARD_NON_RESPONSIVE_DROP)) { 8113 if (wred_flags & BCM_COSQ_DISCARD_COLOR_YELLOW) { 8114 mem = MMU_WRED_DROP_CURVE_PROFILE_4m; 8115 entry_p = &entry_nontcp_yellow; 8116 } else if (wred_flags & BCM_COSQ_DISCARD_COLOR_RED) { 8117 mem = MMU_WRED_DROP_CURVE_PROFILE_5m; 8118 entry_p = &entry_nontcp_red; 8119 } else { 8120 /* By default we will assume 8121 BCM_COSQ_DISCARD_COLOR_GREEN */ 8122 mem = MMU_WRED_DROP_CURVE_PROFILE_3m; 8123 entry_p = &entry_nontcp_green; 8124 } 8125 } else { 8126 if (wred_flags & BCM_COSQ_DISCARD_COLOR_YELLOW) { 8127 mem = MMU_WRED_DROP_CURVE_PROFILE_7m; 8128 entry_p = &entry_ecn_yellow; 8129 } else if (wred_flags & BCM_COSQ_DISCARD_COLOR_RED) { 8130 mem = MMU_WRED_DROP_CURVE_PROFILE_8m; 8131 entry_p = &entry_ecn_red; 8132 } else { 8133 /* By default we will assume 8134 BCM_COSQ_DISCARD_COLOR_GREEN */ 8135 mem = MMU_WRED_DROP_CURVE_PROFILE_6m; 8136 entry_p = &entry_ecn_green; 8137 } 8138 } 8139 8140 entries[0] = &entry_tcp_green; 8141 entries[1] = &entry_tcp_yellow; 8142 entries[2] = &entry_tcp_red; 8143 entries[3] = &entry_nontcp_green; 8144 entries[4] = &entry_nontcp_yellow; 8145 entries[5] = &entry_nontcp_red; 8146 entries[6] = &entry_ecn_green; 8147 entries[7] = &entry_ecn_yellow; 8148 entries[8] = &entry_ecn_red; 8149 8150 BCM_IF_ERROR_RETURN 8151 (soc_profile_mem_get(unit, _bcm_hx5_wred_profile[unit], 8152 profile_index, 1, entries)); 8153 if (min_thresh != NULL) { 8154 *min_thresh = soc_mem_field32_get(unit, mem, entry_p, MIN_THDf); 8155 } 8156 if (max_thresh != NULL) { 8157 *max_thresh = soc_mem_field32_get(unit, mem, entry_p, MAX_THDf); 8158 } 8159 if (drop_probability != NULL) { 8160 rate = soc_mem_field32_get(unit, mem, entry_p, MAX_DROP_RATEf); 8161 *drop_probability = _bcm_hx5_drop_prob_to_percent(rate); 8162 } 8163 if (gain) { 8164 *gain = soc_mem_field32_get(unit, wred_config_mem, &entry, WEIGHTf); 8165 } 8166 8167 if (refresh_time) { 8168 time_id = soc_mem_field32_get(unit, wred_config_mem, &entry, 8169 TIME_DOMAIN_SELf); 8170 BCM_IF_ERROR_RETURN 8171 (_bcm_hx5_cosq_time_domain_get(unit,time_id,&time)); 8172 *refresh_time = time + 1; 8173 } 8174 8175 /* Get flags */ 8176 if (flags) { 8177 if (soc_mem_field32_get(unit, wred_config_mem, &entry, CAP_AVERAGEf)) { 8178 *flags |= BCM_COSQ_DISCARD_CAP_AVERAGE; 8179 } 8180 if (soc_mem_field32_get(unit, wred_config_mem, &entry, WRED_ENf)) { 8181 *flags |= BCM_COSQ_DISCARD_ENABLE; 8182 } 8183 if (soc_mem_field32_get(unit, wred_config_mem, &entry, ECN_MARKING_ENf)) { 8184 *flags |= BCM_COSQ_DISCARD_MARK_CONGESTION; 8185 } 8186 } 8187 8188 /* Get resolution table index */ 8189 if (resolution_id) { 8190 if (soc_mem_field32_get(unit, wred_config_mem, &entry, ECN_MARKING_ENf)) { 8191 *resolution_id = soc_mem_field32_get(unit, wred_config_mem, &entry, 8192 WRED_CONG_NOTIFICATION_RESOLUTION_TABLE_MARKING_INDEXf); 8193 } else { 8194 *resolution_id = soc_mem_field32_get(unit, wred_config_mem, &entry, 8195 WRED_CONG_NOTIFICATION_RESOLUTION_TABLE_DROPPING_INDEXf); 8196 } 8197 } 8198 8199 /* Get use_queue_group */ 8200 if (use_queue_group) { 8201 *use_queue_group = 8202 soc_mem_field32_get(unit, wred_config_mem, &entry, QG_ENf); 8203 } 8204 8205 return BCM_E_NONE; 8206 } 8207 8208 8209 int 8210 bcm_hx5_cosq_discard_set(int unit, uint32 flags) 8211 { 8212 bcm_port_t port; 8213 8214 if (_bcm_hx5_cosq_port_info[unit] == NULL) { 8215 return BCM_E_INIT; 8216 } 8217 8218 if (flags & ~(BCM_COSQ_DISCARD_DEVICE | 8219 BCM_COSQ_DISCARD_NONTCP | 8220 BCM_COSQ_DISCARD_COLOR_ALL | 8221 BCM_COSQ_DISCARD_PORT | 8222 BCM_COSQ_DISCARD_TCP | 8223 BCM_COSQ_DISCARD_COLOR_GREEN | 8224 BCM_COSQ_DISCARD_COLOR_YELLOW | 8225 BCM_COSQ_DISCARD_COLOR_RED | 8226 BCM_COSQ_DISCARD_CAP_AVERAGE | 8227 BCM_COSQ_DISCARD_ENABLE | 8228 BCM_COSQ_DISCARD_MARK_CONGESTION)) { 8229 return BCM_E_PARAM; 8230 } 8231 8232 flags &= ~(BCM_COSQ_DISCARD_NONTCP | BCM_COSQ_DISCARD_COLOR_ALL); 8233 8234 PBMP_PORT_ITER(unit, port) { 8235 BCM_IF_ERROR_RETURN 8236 (_bcm_hx5_cosq_wred_set(unit, port, 0, flags, 0, 0, 0, 0, 8237 FALSE, BCM_COSQ_DISCARD_PORT, 0x1, 0, 0)); 8238 } 8239 8240 return BCM_E_NONE; 8241 } 8242 8243 int 8244 bcm_hx5_cosq_discard_get(int unit, uint32 *flags) 8245 { 8246 bcm_port_t port; 8247 8248 PBMP_PORT_ITER(unit, port) { 8249 *flags = 0; 8250 /* use setting from hardware cosq index 0 of the first port */ 8251 return _bcm_hx5_cosq_wred_get(unit, port, 0, flags, NULL, NULL, NULL, 8252 NULL, BCM_COSQ_DISCARD_PORT, NULL, NULL, 8253 NULL); 8254 } 8255 8256 return BCM_E_NOT_FOUND; 8257 } 8258 8259 /* 8260 * Function: 8261 * bcm_hx5_cosq_discard_port_set 8262 * Purpose: 8263 * Configure port WRED setting 8264 * Parameters: 8265 * unit - (IN) unit number 8266 * port - (IN) port number or GPORT identifier 8267 * cosq - (IN) COS queue number 8268 * color - (IN) 8269 * drop_start - (IN) 8270 * drop_slot - (IN) 8271 * average_time - (IN) 8272 * Returns: 8273 * BCM_E_XXX 8274 * Notes: 8275 * If port is any form of local port, cosq is the hardware queue index. 8276 * Same as TD2 except for Reg changes. 8277 */ 8278 int 8279 bcm_hx5_cosq_discard_port_set(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 8280 uint32 color, int drop_start, int drop_slope, 8281 int average_time) 8282 { 8283 bcm_port_t local_port; 8284 bcm_pbmp_t pbmp; 8285 int gain; 8286 uint32 min_thresh, max_thresh, shared_limit; 8287 uint32 rval, bits, flags = 0; 8288 int numq, i; 8289 8290 if (drop_start < 0 || drop_start > 100 || 8291 drop_slope < 0 || drop_slope > 90) { 8292 return BCM_E_PARAM; 8293 } 8294 8295 /* 8296 * average queue size is reculated every 8us, the formula is 8297 * avg_qsize(t + 1) = 8298 * avg_qsize(t) + (cur_qsize - avg_qsize(t)) / (2 ** gain) 8299 * gain = log2(average_time / 8) 8300 */ 8301 bits = (average_time / 8) & 0xffff; 8302 if (bits != 0) { 8303 bits |= bits >> 1; 8304 bits |= bits >> 2; 8305 bits |= bits >> 4; 8306 bits |= bits >> 8; 8307 gain = _shr_popcount(bits) - 1; 8308 } else { 8309 gain = 0; 8310 } 8311 8312 /* 8313 * per-port cell limit may be disabled. 8314 * per-port per-cos cell limit may be set to use dynamic method. 8315 * therefore drop_start percentage is based on per-device total shared 8316 * cells. 8317 */ 8318 BCM_IF_ERROR_RETURN(READ_MMU_THDM_DB_POOL_SHARED_LIMITr(unit, 0, &rval)); 8319 shared_limit = soc_reg_field_get(unit, MMU_THDM_DB_POOL_SHARED_LIMITr, 8320 rval, SHARED_LIMITf); 8321 min_thresh = ((drop_start * shared_limit) + (100 - 1)) / 100; 8322 8323 /* Calculate the max threshold. For a given slope (angle in 8324 * degrees), determine how many packets are in the range from 8325 * 0% drop probability to 100% drop probability. Add that 8326 * number to the min_treshold to the the max_threshold. 8327 */ 8328 max_thresh = min_thresh + _bcm_hx5_angle_to_cells(drop_slope); 8329 if (max_thresh > HX5_WRED_CELL_FIELD_MAX) { 8330 max_thresh = HX5_WRED_CELL_FIELD_MAX; 8331 } 8332 8333 if (BCM_GPORT_IS_SET(port)) { 8334 numq = 1; 8335 for (i = 0; i < numq; i++) { 8336 BCM_IF_ERROR_RETURN 8337 (_bcm_hx5_cosq_wred_set(unit, port, cosq + i, color, 8338 min_thresh, max_thresh, 100, gain, 8339 TRUE, flags, 0x1, 0, 0)); 8340 } 8341 } else { 8342 if (port == -1) { 8343 BCM_PBMP_ASSIGN(pbmp, PBMP_PORT_ALL(unit)); 8344 } else if (!SOC_PORT_VALID(unit, port)) { 8345 return BCM_E_PORT; 8346 } else { 8347 BCM_PBMP_PORT_SET(pbmp, port); 8348 } 8349 8350 BCM_PBMP_ITER(pbmp, local_port) { 8351 numq = 1; 8352 for (i = 0; i < numq; i++) { 8353 BCM_IF_ERROR_RETURN 8354 (_bcm_hx5_cosq_wred_set(unit, local_port, cosq + i, 8355 color, min_thresh, max_thresh, 100, 8356 gain, TRUE, 0, 0x1, 0, 0)); 8357 } 8358 } 8359 } 8360 8361 return BCM_E_NONE; 8362 } 8363 8364 /* 8365 * Function: 8366 * bcm_hx5_cosq_discard_port_get 8367 * Purpose: 8368 * Get port WRED setting 8369 * Parameters: 8370 * unit - (IN) unit number 8371 * port - (IN) port number or GPORT identifier 8372 * cosq - (IN) COS queue number 8373 * color - (OUT) 8374 * drop_start - (OUT) 8375 * drop_slot - (OUT) 8376 * average_time - (OUT) 8377 * Returns: 8378 * BCM_E_XXX 8379 * Notes: 8380 * If port is any form of local port, cosq is the hardware queue index. 8381 * Same as TD2 except for Reg changes. 8382 */ 8383 int 8384 bcm_hx5_cosq_discard_port_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 8385 uint32 color, int *drop_start, int *drop_slope, 8386 int *average_time) 8387 { 8388 bcm_port_t local_port; 8389 bcm_pbmp_t pbmp; 8390 int gain, drop_prob; 8391 uint32 min_thresh, max_thresh, shared_limit; 8392 uint32 rval; 8393 8394 if (drop_start == NULL || drop_slope == NULL || average_time == NULL) { 8395 return BCM_E_PARAM; 8396 } 8397 8398 if (BCM_GPORT_IS_SET(port)) { 8399 local_port = port; 8400 } else { 8401 if (port == -1) { 8402 BCM_PBMP_ASSIGN(pbmp, PBMP_PORT_ALL(unit)); 8403 } else if (!SOC_PORT_VALID(unit, port)) { 8404 return BCM_E_PORT; 8405 } else { 8406 BCM_PBMP_PORT_SET(pbmp, port); 8407 } 8408 BCM_PBMP_ITER(pbmp, local_port) { 8409 break; 8410 } 8411 } 8412 8413 BCM_IF_ERROR_RETURN 8414 (_bcm_hx5_cosq_wred_get(unit, local_port, cosq == -1 ? 0 : cosq, 8415 &color, &min_thresh, &max_thresh, &drop_prob, 8416 &gain, 0, NULL, NULL, NULL)); 8417 8418 /* 8419 * average queue size is reculated every 8us, the formula is 8420 * avg_qsize(t + 1) = 8421 * avg_qsize(t) + (cur_qsize - avg_qsize(t)) / (2 ** gain) 8422 */ 8423 *average_time = (1 << gain) * 8; 8424 8425 BCM_IF_ERROR_RETURN(READ_MMU_THDM_DB_POOL_SHARED_LIMITr(unit, 0, &rval)); 8426 shared_limit = soc_reg_field_get(unit, MMU_THDM_DB_POOL_SHARED_LIMITr, 8427 rval, SHARED_LIMITf); 8428 if (min_thresh > shared_limit) { 8429 min_thresh = shared_limit; 8430 } 8431 8432 if (max_thresh > shared_limit) { 8433 max_thresh = shared_limit; 8434 } 8435 8436 *drop_start = min_thresh * 100 / shared_limit; 8437 8438 /* Calculate the slope using the min and max threshold. 8439 * The angle is calculated knowing drop probability at min 8440 * threshold is 0% and drop probability at max threshold is 100%. 8441 */ 8442 *drop_slope = _bcm_hx5_cells_to_angle(max_thresh - min_thresh); 8443 8444 return BCM_E_NONE; 8445 } 8446 8447 /* 8448 * Function: 8449 * bcm_hx5_cosq_gport_discard_set 8450 * Purpose: 8451 * Configure port WRED setting 8452 * Parameters: 8453 * unit - (IN) unit number 8454 * port - (IN) GPORT identifier 8455 * cosq - (IN) COS queue to configure, -1 for all COS queues 8456 * discard - (IN) discard settings 8457 * Returns: 8458 * BCM_E_XXX 8459 */ 8460 int 8461 bcm_hx5_cosq_gport_discard_set(int unit, bcm_gport_t gport, 8462 bcm_cos_queue_t cosq, 8463 bcm_cosq_gport_discard_t *discard) 8464 { 8465 int numq, i; 8466 uint32 min_thresh, max_thresh, flags = 0; 8467 int cell_size, cell_field_max; 8468 bcm_port_t local_port = -1; 8469 8470 /* the reasonable range of refresh_time is from 1 to 64 */ 8471 if (discard == NULL || 8472 discard->gain < 0 || discard->gain > 15 || 8473 discard->drop_probability < 0 || discard->drop_probability > 100 || 8474 discard->refresh_time <= 0 || discard->refresh_time > 64 || 8475 discard->profile_id > 3) { 8476 return BCM_E_PARAM; 8477 } 8478 8479 if (discard == NULL || 8480 discard->gain < 0 || discard->gain > 15 || 8481 discard->drop_probability < 0 || discard->drop_probability > 100) { 8482 return BCM_E_PARAM; 8483 } 8484 8485 cell_size = _HX5_MMU_BYTES_PER_CELL; 8486 cell_field_max = HX5_WRED_CELL_FIELD_MAX; 8487 8488 min_thresh = discard->min_thresh; 8489 max_thresh = discard->max_thresh; 8490 if (discard->flags & BCM_COSQ_DISCARD_BYTES) { 8491 /* Convert bytes to cells */ 8492 min_thresh += (cell_size - 1); 8493 min_thresh /= cell_size; 8494 8495 max_thresh += (cell_size - 1); 8496 max_thresh /= cell_size; 8497 8498 if ((min_thresh > cell_field_max) || 8499 (max_thresh > cell_field_max)) { 8500 return BCM_E_PARAM; 8501 } 8502 } else if (discard->flags & BCM_COSQ_DISCARD_PACKETS) { 8503 /* Packet mode not supported */ 8504 return BCM_E_PARAM; 8505 } else { 8506 /* Lower layer function will update thresh when these flags are 8507 * configured, this interface only allow such opration when 8508 * BCM_COSQ_DISCARD_BYTES is also configured. 8509 */ 8510 if (discard->flags & (BCM_COSQ_DISCARD_COLOR_ALL | 8511 BCM_COSQ_DISCARD_TCP | 8512 BCM_COSQ_DISCARD_NONTCP | 8513 BCM_COSQ_DISCARD_ECT_MARKED | 8514 BCM_COSQ_DISCARD_RESPONSIVE_DROP | 8515 BCM_COSQ_DISCARD_NON_RESPONSIVE_DROP)) { 8516 return BCM_E_PARAM; 8517 } 8518 } 8519 8520 if (gport != BCM_GPORT_INVALID) { 8521 BCM_IF_ERROR_RETURN 8522 (_bcm_hx5_cosq_localport_resolve(unit, gport, &local_port)); 8523 if (IS_CPU_PORT(unit,local_port) || IS_LB_PORT(unit,local_port)) { 8524 return BCM_E_PORT; 8525 } 8526 if ((cosq < -1) || (cosq >= SOC_PORT_NUM_COSQ(unit, local_port))) { 8527 return BCM_E_PARAM; 8528 } 8529 } 8530 8531 numq = 1; 8532 8533 for (i = 0; i < numq; i++) { 8534 BCM_IF_ERROR_RETURN 8535 (_bcm_hx5_cosq_wred_set(unit, gport, cosq + i, discard->flags, 8536 min_thresh, max_thresh, 8537 discard->drop_probability, discard->gain, 8538 FALSE, flags, discard->refresh_time, 8539 discard->profile_id, discard->use_queue_group)); 8540 } 8541 8542 return BCM_E_NONE; 8543 } 8544 8545 /* 8546 * Function: 8547 * bcm_hx5_cosq_gport_discard_get 8548 * Purpose: 8549 * Get port WRED setting 8550 * Parameters: 8551 * unit - (IN) unit number 8552 * port - (IN) GPORT identifier 8553 * cosq - (IN) COS queue to get, -1 for any queue 8554 * discard - (OUT) discard settings 8555 * Returns: 8556 * BCM_E_XXX 8557 */ 8558 int 8559 bcm_hx5_cosq_gport_discard_get(int unit, bcm_gport_t gport, 8560 bcm_cos_queue_t cosq, 8561 bcm_cosq_gport_discard_t *discard) 8562 { 8563 uint32 min_thresh, max_thresh; 8564 bcm_port_t local_port = -1; 8565 8566 if (discard == NULL) { 8567 return BCM_E_PARAM; 8568 } 8569 8570 if (gport != BCM_GPORT_INVALID) { 8571 BCM_IF_ERROR_RETURN 8572 (_bcm_hx5_cosq_localport_resolve(unit, gport, &local_port)); 8573 if (IS_CPU_PORT(unit,local_port) || IS_LB_PORT(unit,local_port)) { 8574 return BCM_E_PORT; 8575 } 8576 if ((cosq < -1) || (cosq >= SOC_PORT_NUM_COSQ(unit, local_port))) { 8577 return BCM_E_PARAM; 8578 } 8579 } 8580 8581 BCM_IF_ERROR_RETURN 8582 (_bcm_hx5_cosq_wred_get(unit, gport, cosq == -1 ? 0 : cosq, 8583 &discard->flags, &min_thresh, &max_thresh, 8584 &discard->drop_probability, &discard->gain, 8585 0, &discard->refresh_time, 8586 &discard->profile_id, &discard->use_queue_group)); 8587 8588 /* Convert number of cells to number of bytes */ 8589 discard->min_thresh = min_thresh * _HX5_MMU_BYTES_PER_CELL; 8590 discard->max_thresh = max_thresh * _HX5_MMU_BYTES_PER_CELL; 8591 8592 return BCM_E_NONE; 8593 } 8594 8595 8596 /* 8597 * Function: 8598 * _bcm_hx5_cosq_qgroup_limit_enables_set 8599 * Purpose: 8600 * set enables for Qgroup Min and Shared Limits 8601 * Parameters: 8602 * unit - (IN) Unit number. 8603 * port - (IN) GPORT ID. 8604 * cosq - (IN) COS queue. 8605 * type - (IN) feature 8606 * arg - (IN) feature value 8607 * Returns: 8608 * BCM_E_XXX 8609 * Notes: 8610 */ 8611 STATIC int 8612 _bcm_hx5_cosq_qgroup_limit_enables_set(int unit, bcm_gport_t gport, 8613 bcm_cos_t cosq, 8614 bcm_cosq_control_t type, 8615 int arg) 8616 { 8617 bcm_port_t local_port = 0; 8618 int startq = 0, pipe = 0, count = 1, lc = 0, to_cos = 0; 8619 uint32 entry[SOC_MAX_MEM_WORDS]; 8620 uint32 entry2[SOC_MAX_MEM_WORDS]; 8621 soc_mem_t mem = INVALIDm; 8622 soc_mem_t base_mem = INVALIDm; 8623 int enable = 0; 8624 int valid = 0; 8625 soc_field_t field = INVALIDf; 8626 soc_field_t field2 = INVALIDf; 8627 8628 if (arg < 0) { 8629 return BCM_E_PARAM; 8630 } 8631 arg = arg ? 1 : 0; 8632 8633 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 8634 BCM_IF_ERROR_RETURN(_bcm_hx5_cosq_index_resolve(unit, gport, cosq, 8635 _BCM_HX5_COSQ_INDEX_STYLE_UCAST_QUEUE, &local_port, &startq, NULL)); 8636 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 8637 return BCM_E_PARAM; 8638 } else { 8639 if (cosq < -1) { 8640 return BCM_E_PARAM; 8641 } 8642 BCM_IF_ERROR_RETURN 8643 (_bcm_hx5_cosq_localport_resolve(unit, gport, &local_port)); 8644 if (local_port < 0) { 8645 return BCM_E_PORT; 8646 } 8647 BCM_IF_ERROR_RETURN(_bcm_hx5_cosq_index_resolve(unit, local_port, cosq, 8648 _BCM_HX5_COSQ_INDEX_STYLE_UCAST_QUEUE, NULL, &startq, &count)); 8649 } 8650 8651 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 8652 base_mem = MMU_THDU_Q_TO_QGRP_MAPm; 8653 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 8654 if (type == bcmCosqControlEgressUCQueueGroupSharedLimitEnable) { 8655 field = QGROUP_LIMIT_ENABLEf; 8656 field2 = QGROUP_VALIDf; 8657 } else if (type == bcmCosqControlEgressUCQueueGroupMinEnable) { 8658 field = USE_QGROUP_MINf; 8659 field2 = QGROUP_VALIDf; 8660 } else { 8661 return BCM_E_PARAM; 8662 } 8663 8664 to_cos = startq + count; 8665 for (lc = startq; lc < to_cos; lc++) { 8666 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, lc, entry)); 8667 enable = soc_mem_field32_get(unit, mem, entry, field); 8668 if (enable != arg) { 8669 soc_mem_field32_set(unit, mem, entry, field, arg); 8670 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, lc, entry)); 8671 } 8672 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, lc, entry2)); 8673 valid = soc_mem_field32_get(unit, mem, entry2, field2); 8674 if (valid != 1) { 8675 soc_mem_field32_set(unit, mem, entry2, field2, 1); 8676 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, lc, entry2)); 8677 } 8678 } 8679 8680 return BCM_E_NONE; 8681 } 8682 8683 /* 8684 * Function: 8685 * _bcm_hx5_cosq_qgroup_limit_enables_get 8686 * Purpose: 8687 * get enables for Qgroup Min and Shared Limits 8688 * Parameters: 8689 * unit - (IN) Unit number. 8690 * port - (IN) GPORT ID. 8691 * cosq - (IN) COS queue. 8692 * type - (IN) feature 8693 * arg - (OUT) feature value 8694 * Returns: 8695 * BCM_E_XXX 8696 * Notes: 8697 */ 8698 8699 STATIC int 8700 _bcm_hx5_cosq_qgroup_limit_enables_get(int unit, bcm_gport_t gport, 8701 bcm_cos_queue_t cosq, 8702 bcm_cosq_control_t type, 8703 int *arg) 8704 { 8705 int startq, pipe; 8706 bcm_port_t local_port; 8707 uint32 entry[SOC_MAX_MEM_WORDS]; 8708 soc_mem_t mem = INVALIDm; 8709 soc_mem_t base_mem = INVALIDm; 8710 soc_field_t field = INVALIDf; 8711 8712 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 8713 BCM_IF_ERROR_RETURN(_bcm_hx5_cosq_index_resolve(unit, gport, cosq, 8714 _BCM_HX5_COSQ_INDEX_STYLE_UCAST_QUEUE, &local_port, &startq, NULL)); 8715 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 8716 return BCM_E_PARAM; 8717 } else { 8718 if (cosq < 0) { 8719 return BCM_E_PARAM; 8720 } 8721 BCM_IF_ERROR_RETURN 8722 (_bcm_hx5_cosq_localport_resolve(unit, gport, &local_port)); 8723 if (local_port < 0) { 8724 return BCM_E_PORT; 8725 } 8726 BCM_IF_ERROR_RETURN(_bcm_hx5_cosq_index_resolve(unit, local_port, cosq, 8727 _BCM_HX5_COSQ_INDEX_STYLE_UCAST_QUEUE, NULL, &startq, NULL)); 8728 } 8729 8730 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 8731 base_mem = MMU_THDU_Q_TO_QGRP_MAPm; 8732 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 8733 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 8734 8735 if (type == bcmCosqControlEgressUCQueueGroupSharedLimitEnable) { 8736 field = QGROUP_LIMIT_ENABLEf; 8737 } else if (type == bcmCosqControlEgressUCQueueGroupMinEnable) { 8738 field = USE_QGROUP_MINf; 8739 } else { 8740 return BCM_E_PARAM; 8741 } 8742 8743 *arg = soc_mem_field32_get(unit, mem, entry, field); 8744 return BCM_E_NONE; 8745 } 8746 8747 /* 8748 *Function: 8749 * _bcm_hx5_cosq_qgroup_limit_set 8750 *Purpose: 8751 * set limits for Qgroup Min and Shared Limits 8752 *Parameters: 8753 * unit - (IN) Unit number. 8754 * port - (IN) GPORT ID. 8755 * cosq - (IN) COS queue. 8756 * type - (IN) feature 8757 * arg - (IN) feature value 8758 * Returns: 8759 * BCM_E_XXX 8760 * Notes: 8761 */ 8762 8763 STATIC int 8764 _bcm_hx5_cosq_qgroup_limit_set(int unit, bcm_gport_t gport, bcm_cos_t cosq, 8765 bcm_cosq_control_t type, int arg) 8766 { 8767 int pipe; 8768 int phy_port; 8769 int mmu_port; 8770 bcm_port_t local_port; 8771 soc_mem_t mem = INVALIDm; 8772 soc_mem_t base_mem = INVALIDm; 8773 soc_field_t field = INVALIDf; 8774 int granularity; 8775 int egr_db_shd_size; 8776 int egr_qe_shd_size; 8777 int cur_val; 8778 int max_val; 8779 int delta; 8780 uint32 rval; 8781 uint32 entry[SOC_MAX_MEM_WORDS]; 8782 soc_info_t *si = &SOC_INFO(unit); 8783 8784 if (cosq < 0) { 8785 return BCM_E_PARAM; 8786 } 8787 8788 if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 8789 return BCM_E_PARAM; 8790 } 8791 BCM_IF_ERROR_RETURN( 8792 _bcm_hx5_cosq_localport_resolve(unit, gport, &local_port)); 8793 if (local_port < 0) { 8794 return BCM_E_PORT; 8795 } 8796 8797 if (type == bcmCosqControlEgressUCQueueGroupMinLimitBytes || 8798 type == bcmCosqControlEgressUCQueueGroupSharedLimitBytes) { 8799 arg = (arg + _HX5_MMU_BYTES_PER_CELL - 1) / _HX5_MMU_BYTES_PER_CELL; 8800 } 8801 8802 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 8803 phy_port = si->port_l2p_mapping[local_port]; 8804 mmu_port = si->port_p2m_mapping[phy_port]; 8805 base_mem = MMU_THDU_CONFIG_QGROUPm; 8806 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 8807 BCM_IF_ERROR_RETURN(soc_mem_read( 8808 unit, mem, MEM_BLOCK_ALL, mmu_port, entry)); 8809 8810 if (type == bcmCosqControlEgressUCQueueGroupMinLimitBytes) { 8811 field = Q_MIN_LIMIT_CELLf; 8812 granularity = 1; 8813 8814 rval = 0; 8815 SOC_IF_ERROR_RETURN( 8816 READ_MMU_THDM_DB_POOL_SHARED_LIMITr(unit, 0, &rval)); 8817 egr_db_shd_size = soc_reg_field_get( 8818 unit, MMU_THDM_DB_POOL_SHARED_LIMITr, rval, SHARED_LIMITf); 8819 8820 rval = 0; 8821 SOC_IF_ERROR_RETURN( 8822 READ_MMU_THDM_MCQE_POOL_SHARED_LIMITr(unit, 0, &rval)); 8823 egr_qe_shd_size = soc_reg_field_get( 8824 unit, MMU_THDM_MCQE_POOL_SHARED_LIMITr, rval, SHARED_LIMITf); 8825 8826 cur_val = soc_mem_field32_get(unit, mem, entry, field); 8827 delta = ((arg / granularity) - cur_val) * granularity; 8828 if (delta > egr_db_shd_size) { 8829 return BCM_E_PARAM; 8830 } 8831 8832 SOC_IF_ERROR_RETURN(soc_hx5_mmu_config_shared_buf_recalc( 8833 unit, 2, -1, egr_db_shd_size - delta, egr_qe_shd_size, 1)); 8834 } else if (type == bcmCosqControlEgressUCQueueGroupSharedLimitBytes) { 8835 field = Q_SHARED_LIMIT_CELLf; 8836 granularity = 1; 8837 } else if (type == bcmCosqControlEgressUCQueueGroupSharedDynamicEnable) { 8838 field = Q_LIMIT_DYNAMIC_CELLf; 8839 granularity = 1; 8840 } else { 8841 return BCM_E_PARAM; 8842 } 8843 8844 max_val = (1 << soc_mem_field_length(unit, mem, field)) - 1; 8845 if ((arg < 0) || ((arg / granularity) > max_val)) { 8846 return BCM_E_PARAM; 8847 } 8848 8849 soc_mem_field32_set(unit, mem, entry, field, (arg / granularity)); 8850 BCM_IF_ERROR_RETURN(soc_mem_write( 8851 unit, mem, MEM_BLOCK_ALL, mmu_port, entry)); 8852 return BCM_E_NONE; 8853 } 8854 8855 8856 /* 8857 * Function: 8858 * _bcm_hx5_cosq_qgroup_limit_get 8859 * Purpose: 8860 * get limits for Qgroup Min and Shared Limits 8861 * Parameters: 8862 * unit - (IN) Unit number. 8863 * port - (IN) GPORT ID. 8864 * cosq - (IN) COS queue. 8865 * type - (IN) feature 8866 * arg - (OUT) feature value 8867 * Returns: 8868 * BCM_E_XXX 8869 * Notes: 8870 */ 8871 8872 STATIC int 8873 _bcm_hx5_cosq_qgroup_limit_get(int unit, bcm_gport_t gport, bcm_cos_t cosq, 8874 bcm_cosq_control_t type, int *arg) { 8875 int pipe; 8876 int phy_port; 8877 int mmu_port; 8878 bcm_port_t local_port; 8879 soc_mem_t mem = INVALIDm; 8880 soc_mem_t base_mem = INVALIDm; 8881 soc_field_t field = INVALIDf; 8882 uint32 entry[SOC_MAX_MEM_WORDS]; 8883 soc_info_t *si = &SOC_INFO(unit); 8884 8885 if (cosq < 0) { 8886 return BCM_E_PARAM; 8887 } 8888 8889 if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 8890 return BCM_E_PARAM; 8891 } 8892 BCM_IF_ERROR_RETURN( 8893 _bcm_hx5_cosq_localport_resolve(unit, gport, &local_port)); 8894 if (local_port < 0) { 8895 return BCM_E_PORT; 8896 } 8897 8898 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, & pipe)); 8899 phy_port = si->port_l2p_mapping[local_port]; 8900 mmu_port = si->port_p2m_mapping[phy_port]; 8901 base_mem = MMU_THDU_CONFIG_QGROUPm; 8902 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 8903 BCM_IF_ERROR_RETURN( 8904 soc_mem_read(unit, mem, MEM_BLOCK_ALL, mmu_port, entry)); 8905 8906 if (type == bcmCosqControlEgressUCQueueGroupMinLimitBytes) { 8907 field = Q_MIN_LIMIT_CELLf; 8908 } else if (type == bcmCosqControlEgressUCQueueGroupSharedLimitBytes) { 8909 field = Q_SHARED_LIMIT_CELLf; 8910 } else if (type == bcmCosqControlEgressUCQueueGroupSharedDynamicEnable) { 8911 field = Q_LIMIT_DYNAMIC_CELLf; 8912 } else { 8913 return BCM_E_PARAM; 8914 } 8915 8916 *arg = soc_mem_field32_get(unit, mem, entry, field); 8917 if (type == bcmCosqControlEgressUCQueueGroupMinLimitBytes || 8918 type == bcmCosqControlEgressUCQueueGroupSharedLimitBytes) { 8919 *arg = (*arg) * _HX5_MMU_BYTES_PER_CELL; 8920 } 8921 return BCM_E_NONE; 8922 } 8923 8924 /* 8925 *Function: 8926 * _bcm_hx5_cosq_qgroup_alpha_set 8927 * Purpose: 8928 * set alpha for qgroup 8929 * Parameters: 8930 * unit - (IN) Unit number. 8931 * port - (IN) GPORT ID. 8932 * cosq - (IN) COS queue. 8933 * arg - (IN) feature value 8934 * Returns: 8935 * BCM_E_XXX 8936 * Notes: 8937 */ 8938 STATIC int 8939 _bcm_hx5_cosq_qgroup_alpha_set(int unit, bcm_gport_t gport, 8940 bcm_cos_queue_t cosq, 8941 bcm_cosq_control_drop_limit_alpha_value_t arg) 8942 { 8943 int alpha; 8944 int pipe; 8945 int phy_port; 8946 int mmu_port; 8947 bcm_port_t local_port; 8948 soc_mem_t mem = INVALIDm; 8949 soc_mem_t base_mem = INVALIDm; 8950 uint32 entry[SOC_MAX_MEM_WORDS]; 8951 soc_info_t *si = &SOC_INFO(unit); 8952 8953 if (cosq < 0) { 8954 return BCM_E_PARAM; 8955 } 8956 8957 if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 8958 return BCM_E_PARAM; 8959 } 8960 8961 BCM_IF_ERROR_RETURN( 8962 _bcm_hx5_cosq_localport_resolve(unit, gport, &local_port)); 8963 if (local_port < 0) { 8964 return BCM_E_PORT; 8965 } 8966 8967 switch(arg) { 8968 case bcmCosqControlDropLimitAlpha_1_128: 8969 alpha = SOC_HX5_COSQ_DROP_LIMIT_ALPHA_1_128; 8970 break; 8971 case bcmCosqControlDropLimitAlpha_1_64: 8972 alpha = SOC_HX5_COSQ_DROP_LIMIT_ALPHA_1_64; 8973 break; 8974 case bcmCosqControlDropLimitAlpha_1_32: 8975 alpha = SOC_HX5_COSQ_DROP_LIMIT_ALPHA_1_32; 8976 break; 8977 case bcmCosqControlDropLimitAlpha_1_16: 8978 alpha = SOC_HX5_COSQ_DROP_LIMIT_ALPHA_1_16; 8979 break; 8980 case bcmCosqControlDropLimitAlpha_1_8: 8981 alpha = SOC_HX5_COSQ_DROP_LIMIT_ALPHA_1_8; 8982 break; 8983 case bcmCosqControlDropLimitAlpha_1_4: 8984 alpha = SOC_HX5_COSQ_DROP_LIMIT_ALPHA_1_4; 8985 break; 8986 case bcmCosqControlDropLimitAlpha_1_2: 8987 alpha = SOC_HX5_COSQ_DROP_LIMIT_ALPHA_1_2; 8988 break; 8989 case bcmCosqControlDropLimitAlpha_1: 8990 alpha = SOC_HX5_COSQ_DROP_LIMIT_ALPHA_1; 8991 break; 8992 case bcmCosqControlDropLimitAlpha_2: 8993 alpha = SOC_HX5_COSQ_DROP_LIMIT_ALPHA_2; 8994 break; 8995 case bcmCosqControlDropLimitAlpha_4: 8996 alpha = SOC_HX5_COSQ_DROP_LIMIT_ALPHA_4; 8997 break; 8998 case bcmCosqControlDropLimitAlpha_8: 8999 alpha = SOC_HX5_COSQ_DROP_LIMIT_ALPHA_8; 9000 break; 9001 default: 9002 return BCM_E_PARAM; 9003 } 9004 9005 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 9006 phy_port = si->port_l2p_mapping[local_port]; 9007 mmu_port = si->port_p2m_mapping[phy_port]; 9008 base_mem = MMU_THDU_CONFIG_QGROUPm; 9009 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 9010 BCM_IF_ERROR_RETURN(soc_mem_read( 9011 unit, mem, MEM_BLOCK_ALL, mmu_port, entry)); 9012 9013 soc_mem_field32_set(unit, mem, entry, Q_SHARED_ALPHA_CELLf, alpha); 9014 BCM_IF_ERROR_RETURN(soc_mem_write( 9015 unit, mem, MEM_BLOCK_ALL, mmu_port, entry)); 9016 return BCM_E_NONE; 9017 } 9018 9019 /* 9020 * Function: 9021 * _bcm_hx5_cosq_qgroup_alpha_get 9022 * Purpose: 9023 * get alpha for qgroup 9024 * Parameters: 9025 * unit - (IN) Unit number. 9026 * port - (IN) GPORT ID. 9027 * cosq - (IN) COS queue. 9028 * arg - (OUT) feature value 9029 * Returns: 9030 * BCM_E_XXX 9031 * Notes: 9032 */ 9033 9034 STATIC int 9035 _bcm_hx5_cosq_qgroup_alpha_get(int unit, bcm_gport_t gport, 9036 bcm_cos_queue_t cosq, 9037 bcm_cosq_control_drop_limit_alpha_value_t *arg) 9038 { 9039 int alpha; 9040 int pipe; 9041 int phy_port; 9042 int mmu_port; 9043 bcm_port_t local_port; 9044 soc_mem_t mem = INVALIDm; 9045 soc_mem_t base_mem = INVALIDm; 9046 uint32 entry[SOC_MAX_MEM_WORDS]; 9047 soc_info_t *si = &SOC_INFO(unit); 9048 9049 if (cosq < 0) { 9050 return BCM_E_PARAM; 9051 } 9052 9053 if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 9054 return BCM_E_PARAM; 9055 } 9056 9057 BCM_IF_ERROR_RETURN( 9058 _bcm_hx5_cosq_localport_resolve(unit, gport, &local_port)); 9059 if (local_port < 0) { 9060 return BCM_E_PORT; 9061 } 9062 9063 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); 9064 phy_port = si->port_l2p_mapping[local_port]; 9065 mmu_port = si->port_p2m_mapping[phy_port]; 9066 base_mem = MMU_THDU_CONFIG_QGROUPm; 9067 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 9068 BCM_IF_ERROR_RETURN(soc_mem_read( 9069 unit, mem, MEM_BLOCK_ALL, mmu_port, entry)); 9070 alpha = soc_mem_field32_get(unit, mem, entry, Q_SHARED_ALPHA_CELLf); 9071 9072 switch(alpha) { 9073 case SOC_HX5_COSQ_DROP_LIMIT_ALPHA_1_128: 9074 *arg = bcmCosqControlDropLimitAlpha_1_128; 9075 break; 9076 case SOC_HX5_COSQ_DROP_LIMIT_ALPHA_1_64: 9077 *arg = bcmCosqControlDropLimitAlpha_1_64; 9078 break; 9079 case SOC_HX5_COSQ_DROP_LIMIT_ALPHA_1_32: 9080 *arg = bcmCosqControlDropLimitAlpha_1_32; 9081 break; 9082 case SOC_HX5_COSQ_DROP_LIMIT_ALPHA_1_16: 9083 *arg = bcmCosqControlDropLimitAlpha_1_16; 9084 break; 9085 case SOC_HX5_COSQ_DROP_LIMIT_ALPHA_1_8: 9086 *arg = bcmCosqControlDropLimitAlpha_1_8; 9087 break; 9088 case SOC_HX5_COSQ_DROP_LIMIT_ALPHA_1_4: 9089 *arg = bcmCosqControlDropLimitAlpha_1_4; 9090 break; 9091 case SOC_HX5_COSQ_DROP_LIMIT_ALPHA_1_2: 9092 *arg = bcmCosqControlDropLimitAlpha_1_2; 9093 break; 9094 case SOC_HX5_COSQ_DROP_LIMIT_ALPHA_1: 9095 *arg = bcmCosqControlDropLimitAlpha_1; 9096 break; 9097 case SOC_HX5_COSQ_DROP_LIMIT_ALPHA_2: 9098 *arg = bcmCosqControlDropLimitAlpha_2; 9099 break; 9100 case SOC_HX5_COSQ_DROP_LIMIT_ALPHA_4: 9101 *arg = bcmCosqControlDropLimitAlpha_4; 9102 break; 9103 case SOC_HX5_COSQ_DROP_LIMIT_ALPHA_8: 9104 *arg = bcmCosqControlDropLimitAlpha_8; 9105 break; 9106 default: 9107 return BCM_E_PARAM; 9108 } 9109 9110 return BCM_E_NONE; 9111 } 9112 9113 9114 /* 9115 * Function: 9116 * bcm_hx5_cosq_control_set 9117 * Purpose: 9118 * Set specified feature configuration 9119 * 9120 * Parameters: 9121 * unit - (IN) Unit number. 9122 * port - (IN) GPORT ID. 9123 * cosq - (IN) COS queue. 9124 * type - (IN) feature 9125 * arg - (IN) feature value 9126 * Returns: 9127 * BCM_E_XXX 9128 * Notes: 9129 */ 9130 int 9131 bcm_hx5_cosq_control_set(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 9132 bcm_cosq_control_t type, int arg) 9133 { 9134 uint32 kbits_burst_min, kbits_burst_max; 9135 uint32 kbits_burst; 9136 9137 kbits_burst_min = 0; 9138 kbits_burst_max = 0; 9139 9140 COMPILER_REFERENCE(kbits_burst_min); 9141 COMPILER_REFERENCE(kbits_burst_max); 9142 9143 switch (type) { 9144 case bcmCosqControlBandwidthBurstMax: 9145 kbits_burst = arg & 0x7fffffff; /* Convert to uint32 */ 9146 BCM_IF_ERROR_RETURN 9147 (bcm_hx5_cosq_gport_bandwidth_burst_get(unit, gport, cosq, 9148 &kbits_burst_min, 9149 &kbits_burst_max)); 9150 return bcm_hx5_cosq_gport_bandwidth_burst_set(unit, gport, cosq, 9151 kbits_burst_min, 9152 kbits_burst); 9153 case bcmCosqControlBandwidthBurstMin: 9154 kbits_burst = arg & 0x7fffffff; /* Convert to uint32 */ 9155 BCM_IF_ERROR_RETURN 9156 (bcm_hx5_cosq_gport_bandwidth_burst_get(unit, gport, cosq, 9157 &kbits_burst_min, 9158 &kbits_burst_max)); 9159 return bcm_hx5_cosq_gport_bandwidth_burst_set(unit, gport, cosq, 9160 kbits_burst, 9161 kbits_burst_max); 9162 case bcmCosqControlEgressPool: 9163 case bcmCosqControlEgressPoolLimitBytes: 9164 case bcmCosqControlEgressPoolYellowLimitBytes: 9165 case bcmCosqControlEgressPoolRedLimitBytes: 9166 case bcmCosqControlEgressPoolLimitEnable: 9167 case bcmCosqControlUCEgressPool: 9168 case bcmCosqControlMCEgressPool: 9169 case bcmCosqControlEgressPoolSharedLimitBytes: 9170 case bcmCosqControlEgressPoolResumeLimitBytes: 9171 case bcmCosqControlEgressPoolYellowSharedLimitBytes: 9172 case bcmCosqControlEgressPoolYellowResumeLimitBytes: 9173 case bcmCosqControlEgressPoolRedSharedLimitBytes: 9174 case bcmCosqControlEgressPoolRedResumeLimitBytes: 9175 case bcmCosqControlEgressPoolHighCongestionLimitBytes: 9176 case bcmCosqControlEgressPoolLowCongestionLimitBytes: 9177 return _bcm_hx5_cosq_egr_pool_set(unit, gport, cosq, type, arg); 9178 case bcmCosqControlEgressUCQueueSharedLimitBytes: 9179 case bcmCosqControlEgressMCQueueSharedLimitBytes: 9180 case bcmCosqControlEgressUCQueueMinLimitBytes: 9181 case bcmCosqControlEgressMCQueueMinLimitBytes: 9182 return _bcm_hx5_cosq_egr_queue_set(unit, gport, cosq, type, arg); 9183 case bcmCosqControlIngressPortPGSharedLimitBytes: 9184 case bcmCosqControlIngressPortPGMinLimitBytes: 9185 case bcmCosqControlIngressPortPoolMaxLimitBytes: 9186 case bcmCosqControlIngressPortPoolMinLimitBytes: 9187 case bcmCosqControlIngressPortPGHeadroomLimitBytes: 9188 case bcmCosqControlIngressPortPGResetFloorBytes: 9189 return _bcm_hx5_cosq_ing_res_set(unit, gport, cosq, type, arg); 9190 case bcmCosqControlIngressPool: 9191 case bcmCosqControlIngressHeadroomPool: 9192 return _bcm_hx5_cosq_ing_pool_set(unit, gport, cosq, type, arg); 9193 case bcmCosqControlDropLimitAlpha: 9194 return _bcm_hx5_cosq_alpha_set(unit, gport, cosq, 9195 (bcm_cosq_control_drop_limit_alpha_value_t)arg); 9196 case bcmCosqControlIngressPortPGSharedDynamicEnable: 9197 case bcmCosqControlEgressUCSharedDynamicEnable: 9198 case bcmCosqControlEgressMCSharedDynamicEnable: 9199 return _bcm_hx5_cosq_dynamic_thresh_enable_set(unit, gport, cosq, 9200 type, arg); 9201 case bcmCosqControlEgressPortPoolYellowLimitBytes: 9202 case bcmCosqControlEgressPortPoolRedLimitBytes: 9203 return _bcm_hx5_cosq_egr_port_pool_set(unit, gport, cosq, type, arg); 9204 case bcmCosqControlEgressUCQueueLimitEnable: 9205 case bcmCosqControlEgressMCQueueLimitEnable: 9206 return _bcm_hx5_cosq_egr_queue_limit_enable_set(unit, gport, cosq, 9207 type, arg); 9208 case bcmCosqControlIngressPoolLimitBytes: 9209 case bcmCosqControlIngressHeadroomPoolLimitBytes: 9210 return _bcm_hx5_cosq_ing_res_limit_set(unit, gport, cosq, type, arg); 9211 case bcmCosqControlEgressUCQueueGroupMinEnable: 9212 case bcmCosqControlEgressUCQueueGroupSharedLimitEnable: 9213 return _bcm_hx5_cosq_qgroup_limit_enables_set( 9214 unit, gport, cosq, type, arg); 9215 case bcmCosqControlEgressUCQueueGroupMinLimitBytes: 9216 case bcmCosqControlEgressUCQueueGroupSharedLimitBytes: 9217 case bcmCosqControlEgressUCQueueGroupSharedDynamicEnable: 9218 return _bcm_hx5_cosq_qgroup_limit_set(unit, gport, cosq, type, arg); 9219 case bcmCosqControlEgressUCQueueGroupDropLimitAlpha: 9220 return _bcm_hx5_cosq_qgroup_alpha_set(unit, gport, cosq, 9221 (bcm_cosq_control_drop_limit_alpha_value_t)arg); 9222 9223 default: 9224 break; 9225 } 9226 return BCM_E_UNAVAIL; 9227 } 9228 9229 /* 9230 * Function: 9231 * bcm_hx5_cosq_control_get 9232 * Purpose: 9233 * Get specified feature configuration 9234 * 9235 * Parameters: 9236 * unit - (IN) Unit number. 9237 * port - (IN) GPORT ID. 9238 * cosq - (IN) COS queue. 9239 * type - (IN) feature 9240 * arg - (OUT) feature value 9241 * Returns: 9242 * BCM_E_XXX 9243 * Notes: 9244 */ 9245 int 9246 bcm_hx5_cosq_control_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 9247 bcm_cosq_control_t type, int *arg) 9248 { 9249 uint32 kburst_tmp, kbits_burst; 9250 9251 switch (type) { 9252 case bcmCosqControlBandwidthBurstMax: 9253 BCM_IF_ERROR_RETURN 9254 (bcm_hx5_cosq_gport_bandwidth_burst_get(unit, gport, cosq, 9255 &kburst_tmp, 9256 &kbits_burst)); 9257 *arg = kbits_burst & 0x7fffffff; /* Convert to int */ 9258 return BCM_E_NONE; 9259 9260 case bcmCosqControlBandwidthBurstMin: 9261 return bcm_hx5_cosq_gport_bandwidth_burst_get(unit, gport, cosq, 9262 (uint32*)arg, 9263 &kburst_tmp); 9264 case bcmCosqControlEgressPool: 9265 case bcmCosqControlEgressPoolLimitBytes: 9266 case bcmCosqControlEgressPoolYellowLimitBytes: 9267 case bcmCosqControlEgressPoolRedLimitBytes: 9268 case bcmCosqControlEgressPoolLimitEnable: 9269 case bcmCosqControlUCEgressPool: 9270 case bcmCosqControlMCEgressPool: 9271 case bcmCosqControlEgressPoolSharedLimitBytes: 9272 case bcmCosqControlEgressPoolResumeLimitBytes: 9273 case bcmCosqControlEgressPoolYellowSharedLimitBytes: 9274 case bcmCosqControlEgressPoolYellowResumeLimitBytes: 9275 case bcmCosqControlEgressPoolRedSharedLimitBytes: 9276 case bcmCosqControlEgressPoolRedResumeLimitBytes: 9277 case bcmCosqControlEgressPoolHighCongestionLimitBytes: 9278 case bcmCosqControlEgressPoolLowCongestionLimitBytes: 9279 return _bcm_hx5_cosq_egr_pool_get(unit, gport, cosq, type, arg); 9280 case bcmCosqControlEgressUCQueueSharedLimitBytes: 9281 case bcmCosqControlEgressMCQueueSharedLimitBytes: 9282 case bcmCosqControlEgressUCQueueMinLimitBytes: 9283 case bcmCosqControlEgressMCQueueMinLimitBytes: 9284 return _bcm_hx5_cosq_egr_queue_get(unit, gport, cosq, type, arg); 9285 case bcmCosqControlIngressPortPGSharedLimitBytes: 9286 case bcmCosqControlIngressPortPGMinLimitBytes: 9287 case bcmCosqControlIngressPortPoolMaxLimitBytes: 9288 case bcmCosqControlIngressPortPoolMinLimitBytes: 9289 case bcmCosqControlIngressPortPGHeadroomLimitBytes: 9290 case bcmCosqControlIngressPortPGResetFloorBytes: 9291 return _bcm_hx5_cosq_ing_res_get(unit, gport, cosq, type, arg); 9292 case bcmCosqControlIngressPool: 9293 case bcmCosqControlIngressHeadroomPool: 9294 return _bcm_hx5_cosq_ing_pool_get(unit, gport, cosq, type, arg); 9295 case bcmCosqControlDropLimitAlpha: 9296 return _bcm_hx5_cosq_alpha_get(unit, gport, cosq, 9297 (bcm_cosq_control_drop_limit_alpha_value_t *)arg); 9298 case bcmCosqControlIngressPortPGSharedDynamicEnable: 9299 case bcmCosqControlEgressUCSharedDynamicEnable: 9300 case bcmCosqControlEgressMCSharedDynamicEnable: 9301 return _bcm_hx5_cosq_dynamic_thresh_enable_get(unit, gport, cosq, 9302 type, arg); 9303 case bcmCosqControlEgressPortPoolYellowLimitBytes: 9304 case bcmCosqControlEgressPortPoolRedLimitBytes: 9305 return _bcm_hx5_cosq_egr_port_pool_get(unit, gport, cosq, type, arg); 9306 case bcmCosqControlEgressUCQueueLimitEnable: 9307 case bcmCosqControlEgressMCQueueLimitEnable: 9308 return _bcm_hx5_cosq_egr_queue_limit_enable_get(unit, gport, cosq, 9309 type, arg); 9310 case bcmCosqControlIngressPoolLimitBytes: 9311 case bcmCosqControlIngressHeadroomPoolLimitBytes: 9312 return _bcm_hx5_cosq_ing_res_limit_get(unit, gport, cosq, type, arg); 9313 case bcmCosqControlEgressUCQueueGroupMinEnable: 9314 case bcmCosqControlEgressUCQueueGroupSharedLimitEnable: 9315 return _bcm_hx5_cosq_qgroup_limit_enables_get( 9316 unit, gport, cosq, type, arg); 9317 case bcmCosqControlEgressUCQueueGroupMinLimitBytes: 9318 case bcmCosqControlEgressUCQueueGroupSharedLimitBytes: 9319 case bcmCosqControlEgressUCQueueGroupSharedDynamicEnable: 9320 return _bcm_hx5_cosq_qgroup_limit_get(unit, gport, cosq, type, arg); 9321 case bcmCosqControlEgressUCQueueGroupDropLimitAlpha: 9322 return _bcm_hx5_cosq_qgroup_alpha_get(unit, gport, cosq, 9323 (bcm_cosq_control_drop_limit_alpha_value_t*)arg); 9324 default: 9325 break; 9326 } 9327 return BCM_E_UNAVAIL; 9328 } 9329 /* 9330 * Function: 9331 * bcm_hx5_cosq_gport_bandwidth_get 9332 * Purpose: 9333 * Get COS queue bandwidth control configuration 9334 * Parameters: 9335 * unit - (IN) unit number 9336 * gport - (IN) GPORT identifier 9337 * cosq - (IN) COS queue number 9338 * kbits_sec_min - (OUT) minimum bandwidth, kbits/sec 9339 * kbits_sec_max - (OUT) maximum bandwidth, kbits/sec 9340 * flags - (OUT) BCM_COSQ_BW_XXX 9341 * Returns: 9342 * BCM_E_XXX 9343 */ 9344 int 9345 bcm_hx5_cosq_gport_bandwidth_get(int unit, bcm_gport_t gport, 9346 bcm_cos_queue_t cosq, uint32 *kbits_sec_min, 9347 uint32 *kbits_sec_max, uint32 *flags) 9348 { 9349 uint32 kbits_sec_burst; 9350 9351 BCM_IF_ERROR_RETURN 9352 (_bcm_hx5_cosq_bucket_get(unit, gport, cosq, kbits_sec_min, 9353 kbits_sec_max, &kbits_sec_burst, 9354 &kbits_sec_burst, flags)); 9355 9356 return BCM_E_NONE; 9357 } 9358 9359 /* 9360 * Function: 9361 * bcm_hx5_cosq_gport_bandwidth_set 9362 * Purpose: 9363 * Configure COS queue bandwidth control 9364 * Parameters: 9365 * unit - (IN) unit number 9366 * gport - (IN) GPORT identifier 9367 * cosq - (IN) COS queue number 9368 * kbits_sec_min - (IN) minimum bandwidth, kbits/sec 9369 * kbits_sec_max - (IN) maximum bandwidth, kbits/sec 9370 * flags - (IN) BCM_COSQ_BW_XXX 9371 * Returns: 9372 * BCM_E_XXX 9373 */ 9374 int 9375 bcm_hx5_cosq_gport_bandwidth_set(int unit, bcm_gport_t gport, 9376 bcm_cos_queue_t cosq, uint32 kbits_sec_min, 9377 uint32 kbits_sec_max, uint32 flags) 9378 { 9379 int i = 0, local_port; 9380 _bcm_hx5_cosq_node_t *node = NULL; 9381 uint32 burst_min, burst_max; 9382 9383 BCM_IF_ERROR_RETURN(_bcm_hx5_cosq_localport_resolve(unit, gport, 9384 &local_port)); 9385 9386 if (BCM_GPORT_IS_SET(gport)) { 9387 if ((BCM_GPORT_IS_SCHEDULER(gport)) || 9388 BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 9389 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 9390 BCM_IF_ERROR_RETURN 9391 (_bcm_hx5_cosq_node_get(unit, gport, NULL, NULL, NULL, &node)); 9392 9393 if (node != NULL) { 9394 i = node->hw_index; 9395 } else { 9396 cosq = 0; 9397 } 9398 } else { 9399 if (cosq < 0) { 9400 return BCM_E_PARAM; 9401 } 9402 i = cosq; 9403 } 9404 } else { 9405 if (cosq < 0) { 9406 return BCM_E_PARAM; 9407 } 9408 i = cosq; 9409 } 9410 9411 burst_min = (kbits_sec_min > 0) ? 9412 _bcm_td_default_burst_size(unit, local_port, kbits_sec_min) : 0; 9413 9414 burst_max = (kbits_sec_max > 0) ? 9415 _bcm_td_default_burst_size(unit, local_port, kbits_sec_max) : 0; 9416 9417 BCM_IF_ERROR_RETURN 9418 (_bcm_hx5_cosq_bucket_set(unit, gport, i, kbits_sec_min, 9419 kbits_sec_max, burst_min, burst_max, 9420 flags)); 9421 9422 return BCM_E_NONE; 9423 } 9424 9425 /* 9426 * Function: 9427 * bcm_hx5_cosq_port_bandwidth_set 9428 * Purpose: 9429 * Configure COS queue bandwidth control 9430 * Parameters: 9431 * unit - (IN) unit number 9432 * port - (IN) port number 9433 * cosq - (IN) COS queue number 9434 * min_quantum - (IN) minimum bandwidth, kbits/sec 9435 * max_quantum - (IN) maximum bandwidth, kbits/sec 9436 * burst_quantum - (IN) burst size, kbits/sec 9437 * flags - (IN) BCM_COSQ_BW_XXX 9438 * Returns: 9439 * BCM_E_XXX 9440 */ 9441 int 9442 bcm_hx5_cosq_port_bandwidth_set(int unit, bcm_port_t port, 9443 bcm_cos_queue_t cosq, uint32 min_quantum, 9444 uint32 max_quantum, uint32 burst_quantum, 9445 uint32 flags) 9446 { 9447 uint32 burst_min, burst_max; 9448 9449 if (cosq < 0) { 9450 return BCM_E_PARAM; 9451 } 9452 9453 if (BCM_GPORT_IS_SET(port)) { 9454 if ((BCM_GPORT_IS_SCHEDULER(port)) || 9455 BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 9456 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) || 9457 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port)) { 9458 return BCM_E_UNAVAIL; 9459 } 9460 } 9461 9462 burst_min = (min_quantum > 0) ? 9463 _bcm_td_default_burst_size(unit, port, min_quantum) : 0; 9464 9465 burst_max = (max_quantum > 0) ? 9466 _bcm_td_default_burst_size(unit, port, max_quantum) : 0; 9467 9468 BCM_IF_ERROR_RETURN 9469 (_bcm_hx5_cosq_bucket_set(unit, port, cosq, min_quantum, 9470 max_quantum, burst_min, burst_max, 9471 flags)); 9472 9473 return BCM_E_NONE; 9474 } 9475 9476 /* 9477 * Function: 9478 * bcm_hx5_cosq_port_bandwidth_get 9479 * Purpose: 9480 * Get COS queue bandwidth control configuration 9481 * Parameters: 9482 * unit - (IN) unit number 9483 * port - (IN) port number 9484 * cosq - (IN) COS queue number 9485 * min_quantum - (OUT) minimum bandwidth, kbits/sec 9486 * max_quantum - (OUT) maximum bandwidth, kbits/sec 9487 * burst_quantum - (OUT) burst size, kbits/sec 9488 * flags - (OUT) BCM_COSQ_BW_XXX 9489 * Returns: 9490 * BCM_E_XXX 9491 */ 9492 int 9493 bcm_hx5_cosq_port_bandwidth_get(int unit, bcm_port_t port, 9494 bcm_cos_queue_t cosq, uint32 *min_quantum, 9495 uint32 *max_quantum, uint32 *burst_quantum, 9496 uint32 *flags) 9497 { 9498 uint32 kbits_burst_min; 9499 9500 if (cosq < -1) { 9501 return BCM_E_PARAM; 9502 } 9503 9504 if (BCM_GPORT_IS_SET(port) && 9505 ((BCM_GPORT_IS_SCHEDULER(port)) || 9506 BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 9507 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) || 9508 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port))) { 9509 return BCM_E_UNAVAIL; 9510 } 9511 9512 BCM_IF_ERROR_RETURN 9513 (_bcm_hx5_cosq_bucket_get(unit, port, cosq, min_quantum, 9514 max_quantum, &kbits_burst_min, 9515 burst_quantum, flags)); 9516 9517 return BCM_E_NONE; 9518 } 9519 9520 9521 /* 9522 * Function: 9523 * bcm_hx5_cosq_port_pps_set 9524 * Purpose: 9525 * Set the RX per-Cos rate limiting value 9526 * Parameters: 9527 * unit - (IN) unit number 9528 * port - (IN) queue group GPORT identifier 9529 * cosq - (IN) CoS to configure 9530 * pps - (IN) Rate in packets/second 9531 * Returns: 9532 * BCM_E_XXX 9533 */ 9534 int 9535 bcm_hx5_cosq_port_pps_set(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 9536 int pps) 9537 { 9538 uint32 min, max, burst, burst_min, flags; 9539 bcm_port_t local_port = port; 9540 9541 if (!IS_CPU_PORT(unit, port)) { 9542 return BCM_E_PORT; 9543 } else if (cosq < 0 || cosq >= NUM_CPU_COSQ(unit)) { 9544 return BCM_E_PARAM; 9545 } 9546 9547 if (BCM_GPORT_IS_SET(port) && 9548 ((BCM_GPORT_IS_SCHEDULER(port)) || 9549 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port))) { 9550 return BCM_E_UNAVAIL; 9551 } 9552 9553 BCM_IF_ERROR_RETURN 9554 (_bcm_hx5_cosq_bucket_get(unit, port, cosq, &min, &max, &burst_min, 9555 &burst, &flags)); 9556 9557 min = pps; 9558 burst_min = (min > 0) ? 9559 _bcm_td_default_burst_size(unit, local_port, min) : 0; 9560 burst = burst_min; 9561 9562 return _bcm_hx5_cosq_bucket_set(unit, port, cosq, min, pps, burst_min, 9563 burst, flags | BCM_COSQ_BW_PACKET_MODE); 9564 } 9565 9566 /* 9567 * Function: 9568 * bcm_hx5_cosq_port_pps_get 9569 * Purpose: 9570 * Get the RX per-Cos rate limiting value 9571 * Parameters: 9572 * unit - (IN) unit number 9573 * port - (IN) queue group GPORT identifier 9574 * cosq - (IN) COS queue number 9575 * pps - (OUT) Rate in packets/second 9576 * Returns: 9577 * BCM_E_XXX 9578 */ 9579 int 9580 bcm_hx5_cosq_port_pps_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 9581 int *pps) 9582 { 9583 uint32 min, max, burst, flags; 9584 9585 if (!IS_CPU_PORT(unit, port)) { 9586 return BCM_E_PORT; 9587 } else if (cosq < 0 || cosq >= NUM_CPU_COSQ(unit)) { 9588 return BCM_E_PARAM; 9589 } 9590 9591 if (BCM_GPORT_IS_SET(port) && 9592 ((BCM_GPORT_IS_SCHEDULER(port)) || 9593 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port))) { 9594 return BCM_E_UNAVAIL; 9595 } 9596 9597 BCM_IF_ERROR_RETURN 9598 (_bcm_hx5_cosq_bucket_get(unit, port, cosq, &min, &max, &burst, &burst, 9599 &flags)); 9600 9601 *pps = max; 9602 9603 return BCM_E_NONE; 9604 } 9605 9606 /* 9607 * Function: 9608 * bcm_hx5_cosq_port_burst_set 9609 * Purpose: 9610 * Set the per-Cos burst setting 9611 * Parameters: 9612 * unit - (IN) unit number 9613 * port - (IN) queue group GPORT identifier 9614 * cosq - (IN) CoS to configure 9615 * burst - (IN) Burst rate for the system in packets 9616 * Returns: 9617 * BCM_E_XXX 9618 */ 9619 int 9620 bcm_hx5_cosq_port_burst_set(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 9621 int burst) 9622 { 9623 uint32 min, max, cur_burst, flags; 9624 9625 if (!IS_CPU_PORT(unit, port)) { 9626 return BCM_E_PORT; 9627 } else if (cosq < 0 || cosq >= NUM_CPU_COSQ(unit)) { 9628 return BCM_E_PARAM; 9629 } 9630 9631 if (BCM_GPORT_IS_SET(port) && 9632 ((BCM_GPORT_IS_SCHEDULER(port)) || 9633 BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 9634 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) || 9635 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port))) { 9636 return BCM_E_UNAVAIL; 9637 } 9638 9639 BCM_IF_ERROR_RETURN 9640 (_bcm_hx5_cosq_bucket_get(unit, port, cosq, &min, &max, &cur_burst, 9641 &cur_burst, &flags)); 9642 9643 /* Replace the current BURST setting, keep PPS the same */ 9644 return _bcm_hx5_cosq_bucket_set(unit, port, cosq, min, max, burst, burst, 9645 flags | BCM_COSQ_BW_PACKET_MODE); 9646 } 9647 9648 /* 9649 * Function: 9650 * bcm_hx5_cosq_port_burst_set 9651 * Purpose: 9652 * Get the per-Cos burst setting 9653 * Parameters: 9654 * unit - (IN) unit number 9655 * port - (IN) queue group GPORT identifier 9656 * cosq - (IN) CoS queue number 9657 * burst - (OUT) Burst rate for the system in packets 9658 * Returns: 9659 * BCM_E_XXX 9660 */ 9661 int 9662 bcm_hx5_cosq_port_burst_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 9663 int *burst) 9664 { 9665 uint32 min, max, cur_burst, cur_burst_min, flags; 9666 9667 if (!IS_CPU_PORT(unit, port)) { 9668 return BCM_E_PORT; 9669 } else if (cosq < 0 || cosq >= NUM_CPU_COSQ(unit)) { 9670 return BCM_E_PARAM; 9671 } 9672 9673 if (BCM_GPORT_IS_SET(port) && 9674 ((BCM_GPORT_IS_SCHEDULER(port)) || 9675 BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 9676 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) || 9677 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port))) { 9678 return BCM_E_UNAVAIL; 9679 } 9680 9681 BCM_IF_ERROR_RETURN 9682 (_bcm_hx5_cosq_bucket_get(unit, port, cosq, &min, &max, 9683 &cur_burst_min, &cur_burst, &flags)); 9684 9685 *burst = cur_burst; 9686 9687 return BCM_E_NONE; 9688 } 9689 9690 STATIC int 9691 _bcm_hx5_cosq_obmhighwatermark_set(int unit, bcm_port_t port, uint64 value) 9692 { 9693 int pipe, obm_id, lane; 9694 soc_reg_t reg; 9695 uint64 rval64; 9696 soc_info_t *si; 9697 soc_reg_t obm_high_watermark_reg[] = { 9698 /* PM4x10Q */ 9699 IDB_OBM0_Q_MAX_USAGEr, IDB_OBM1_Q_MAX_USAGEr, IDB_OBM2_Q_MAX_USAGEr, 9700 /* PM4x10 */ 9701 IDB_OBM0_MAX_USAGEr, IDB_OBM1_MAX_USAGEr, IDB_OBM2_MAX_USAGEr, IDB_OBM3_MAX_USAGEr, 9702 /* PM4x25 */ 9703 IDB_OBM0_48_MAX_USAGEr, IDB_OBM1_48_MAX_USAGEr, IDB_OBM2_48_MAX_USAGEr, 9704 }; 9705 9706 9707 soc_field_t obm_high_watermark_fields[] = { 9708 PORT0_MAX_USAGEf, PORT1_MAX_USAGEf, 9709 PORT2_MAX_USAGEf, PORT3_MAX_USAGEf 9710 }; 9711 9712 SOC_IF_ERROR_RETURN 9713 (soc_helix5_port_obm_info_get(unit, port, &obm_id, &lane)); 9714 if (obm_id >= _HX5_OBMS_PER_PIPE || 9715 (lane < 0 || lane >= _HX5_PORTS_PER_PBLK)) { 9716 return BCM_E_PARAM; 9717 } 9718 if(!COMPILER_64_IS_ZERO(value)) { 9719 return BCM_E_PARAM; 9720 } 9721 si = &SOC_INFO(unit); 9722 pipe = si->port_pipe[port]; 9723 9724 reg = SOC_REG_UNIQUE_ACC(unit, obm_high_watermark_reg[obm_id])[pipe]; 9725 COMPILER_64_ZERO(rval64); 9726 BCM_IF_ERROR_RETURN 9727 (soc_reg64_get(unit, reg, REG_PORT_ANY, 0, &rval64)); 9728 9729 soc_reg64_field32_set(unit, reg, &rval64, obm_high_watermark_fields[lane], 0); 9730 BCM_IF_ERROR_RETURN 9731 (soc_reg64_set(unit, reg, REG_PORT_ANY, 0, rval64)); 9732 return BCM_E_NONE; 9733 } 9734 9735 STATIC int 9736 _bcm_hx5_cosq_obmhighwatermark_get(int unit, bcm_port_t port, uint64 *value) 9737 { 9738 int pipe, obm_id, lane; 9739 soc_reg_t reg; 9740 uint64 rval64; 9741 soc_info_t *si; 9742 soc_reg_t obm_high_watermark_reg[] = { 9743 /* PM4x10Q */ 9744 IDB_OBM0_Q_MAX_USAGEr, IDB_OBM1_Q_MAX_USAGEr, IDB_OBM2_Q_MAX_USAGEr, 9745 /* PM4x10 */ 9746 IDB_OBM0_MAX_USAGEr, IDB_OBM1_MAX_USAGEr, IDB_OBM2_MAX_USAGEr, IDB_OBM3_MAX_USAGEr, 9747 /* PM4x25 */ 9748 IDB_OBM0_48_MAX_USAGEr, IDB_OBM1_48_MAX_USAGEr, IDB_OBM2_48_MAX_USAGEr, 9749 }; 9750 9751 soc_field_t obm_high_watermark_fields[] = { 9752 PORT0_MAX_USAGEf, PORT1_MAX_USAGEf, 9753 PORT2_MAX_USAGEf, PORT3_MAX_USAGEf 9754 }; 9755 9756 SOC_IF_ERROR_RETURN 9757 (soc_helix5_port_obm_info_get(unit, port, &obm_id, &lane)); 9758 if (obm_id >= _HX5_OBMS_PER_PIPE || 9759 (lane < 0 || lane >= _HX5_PORTS_PER_PBLK)) { 9760 return BCM_E_PARAM; 9761 } 9762 si = &SOC_INFO(unit); 9763 pipe = si->port_pipe[port]; 9764 9765 reg = SOC_REG_UNIQUE_ACC(unit, obm_high_watermark_reg[obm_id])[pipe]; 9766 COMPILER_64_ZERO(rval64); 9767 BCM_IF_ERROR_RETURN 9768 (soc_reg64_get(unit, reg, REG_PORT_ANY, 0, &rval64)); 9769 9770 *value = soc_reg64_field_get(unit, reg, rval64, obm_high_watermark_fields[lane]); 9771 COMPILER_64_UMUL_32(*value, 16); /* 16B cell granularity. */ 9772 9773 return BCM_E_NONE; 9774 } 9775 9776 STATIC int 9777 _bcm_hx5_cosq_obm_buf_use_cnt_set(int unit, bcm_port_t port, uint64 value) 9778 { 9779 int pipe, obm_id, lane; 9780 soc_reg_t reg; 9781 soc_field_t fld; 9782 uint64 rval64; 9783 soc_info_t *si; 9784 soc_reg_t obm_usage_reg[] = { 9785 /* PM4x10Q */ 9786 IDB_OBM0_Q_USAGEr, IDB_OBM1_Q_USAGEr, IDB_OBM2_Q_USAGEr, 9787 /* PM4x10 */ 9788 IDB_OBM0_USAGEr, IDB_OBM1_USAGEr, IDB_OBM2_USAGEr, IDB_OBM3_USAGEr, 9789 /* PM4x25 */ 9790 IDB_OBM0_48_USAGEr, IDB_OBM1_48_USAGEr, IDB_OBM2_48_USAGEr, 9791 }; 9792 9793 SOC_IF_ERROR_RETURN 9794 (soc_helix5_port_obm_info_get(unit, port, &obm_id, &lane)); 9795 if (obm_id >= _HX5_OBMS_PER_PIPE || (lane < 0 || lane >= _HX5_PORTS_PER_PBLK)) { 9796 return BCM_E_PARAM; 9797 } 9798 if(!COMPILER_64_IS_ZERO(value)) { 9799 return BCM_E_PARAM; 9800 } 9801 si = &SOC_INFO(unit); 9802 pipe = si->port_pipe[port]; 9803 9804 reg = SOC_REG_UNIQUE_ACC(unit, obm_usage_reg[obm_id])[pipe]; 9805 fld = si->mmu_lossless ? LOSSLESS0_COUNTf : LOSSY_COUNTf; 9806 COMPILER_64_ZERO(rval64); 9807 BCM_IF_ERROR_RETURN 9808 (soc_reg64_get(unit, reg, REG_PORT_ANY, lane, &rval64)); 9809 9810 soc_reg64_field_set(unit, reg, &rval64, fld, value); 9811 BCM_IF_ERROR_RETURN 9812 (soc_reg64_set(unit, reg, REG_PORT_ANY, lane, rval64)); 9813 return BCM_E_NONE; 9814 } 9815 9816 STATIC int 9817 _bcm_hx5_cosq_obm_buf_use_cnt_get(int unit, bcm_port_t port, uint64 *value) 9818 { 9819 int pipe, obm_id, lane; 9820 soc_reg_t reg; 9821 soc_field_t fld; 9822 uint64 rval64; 9823 soc_info_t *si; 9824 soc_reg_t obm_usage_reg[] = { 9825 /* PM4x10Q */ 9826 IDB_OBM0_Q_USAGEr, IDB_OBM1_Q_USAGEr, IDB_OBM2_Q_USAGEr, 9827 /* PM4x10 */ 9828 IDB_OBM0_USAGEr, IDB_OBM1_USAGEr, IDB_OBM2_USAGEr, IDB_OBM3_USAGEr, 9829 /* PM4x25 */ 9830 IDB_OBM0_48_USAGEr, IDB_OBM1_48_USAGEr, IDB_OBM2_48_USAGEr, 9831 }; 9832 9833 SOC_IF_ERROR_RETURN 9834 (soc_helix5_port_obm_info_get(unit, port, &obm_id, &lane)); 9835 if (obm_id >= _HX5_OBMS_PER_PIPE || (lane < 0 || lane >= _HX5_PORTS_PER_PBLK)) { 9836 return BCM_E_PARAM; 9837 } 9838 si = &SOC_INFO(unit); 9839 pipe = si->port_pipe[port]; 9840 9841 reg = SOC_REG_UNIQUE_ACC(unit, obm_usage_reg[obm_id])[pipe]; 9842 fld = si->mmu_lossless ? LOSSLESS0_COUNTf : LOSSY_COUNTf; 9843 COMPILER_64_ZERO(rval64); 9844 BCM_IF_ERROR_RETURN 9845 (soc_reg64_get(unit, reg, REG_PORT_ANY, lane, &rval64)); 9846 9847 *value = soc_reg64_field_get(unit, reg, rval64, fld); 9848 COMPILER_64_UMUL_32(*value, 16); /* 16B cell granularity. */ 9849 9850 return BCM_E_NONE; 9851 } 9852 9853 /* 9854 * Function: 9855 * bcm_hx5_cosq_stat_set 9856 * Purpose: 9857 * Set MMU statistics on a per port per cosq basis. 9858 * Parameters: 9859 * unit - (IN) Unit number. 9860 * port - (IN) GPORT ID 9861 * cosq - (IN) COS queue. 9862 * stat - (IN) Statistic to be set. 9863 * value - (IN) Statistic value to be set. 9864 * Returns: 9865 * BCM_E_xxx 9866 * Notes: 9867 */ 9868 int 9869 bcm_hx5_cosq_stat_set(int unit, bcm_gport_t port, bcm_cos_queue_t cosq, 9870 bcm_cosq_stat_t stat, uint64 value) 9871 { 9872 soc_ctr_control_info_t ctrl_info; 9873 soc_reg_t ctr_reg, ctr_reg_uc, ctr_reg_mc; 9874 _bcm_hx5_cosq_index_style_t style = _BCM_HX5_COSQ_INDEX_STYLE_COUNT; 9875 int startq = 0, ci, from_cos, to_cos; 9876 bcm_port_t local_port = -1; 9877 soc_info_t *si = &SOC_INFO(unit); 9878 9879 ctrl_info.instance = -1; 9880 ctrl_info.instance_type = SOC_CTR_INSTANCE_TYPE_XPE; 9881 9882 BCM_IF_ERROR_RETURN 9883 (_bcm_hx5_cosq_localport_resolve(unit, port, &local_port)); 9884 if ((cosq < -1) || (cosq >= si->port_num_cosq[local_port])) { 9885 return BCM_E_PARAM; 9886 } 9887 9888 switch (stat) { 9889 case bcmCosqStatDroppedPackets: 9890 case bcmCosqStatDroppedBytes: 9891 case bcmCosqStatOutPackets: 9892 case bcmCosqStatOutBytes: 9893 style = _BCM_HX5_COSQ_INDEX_STYLE_COS; 9894 if (stat == bcmCosqStatDroppedBytes) { 9895 ctr_reg_uc = SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE_UC; 9896 ctr_reg_mc = SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE; 9897 } else if (stat == bcmCosqStatDroppedPackets) { 9898 ctr_reg_uc = SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_UC; 9899 ctr_reg_mc = SOC_COUNTER_NON_DMA_COSQ_DROP_PKT; 9900 } else if (stat == bcmCosqStatOutBytes) { 9901 ctr_reg_uc = SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE_UC; 9902 ctr_reg_mc = SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE; 9903 ctrl_info.instance_type = SOC_CTR_INSTANCE_TYPE_PORT; 9904 } else { /* (stat == bcmCosqStatOutPackets) */ 9905 ctr_reg_uc = SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT_UC; 9906 ctr_reg_mc = SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT; 9907 ctrl_info.instance_type = SOC_CTR_INSTANCE_TYPE_PORT; 9908 } 9909 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) { 9910 if (ctr_reg_uc != INVALIDr) { 9911 BCM_IF_ERROR_RETURN 9912 (_bcm_hx5_cosq_index_resolve 9913 (unit, port, cosq, style, &local_port, &startq, NULL)); 9914 9915 ctrl_info.instance = local_port; 9916 startq = startq - si->port_uc_cosq_base[local_port]; 9917 BCM_IF_ERROR_RETURN 9918 (soc_counter_generic_set(unit, ctr_reg_uc, ctrl_info, 0, 9919 startq, value)); 9920 } 9921 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 9922 if (ctr_reg_mc != INVALIDr) { 9923 BCM_IF_ERROR_RETURN 9924 (_bcm_hx5_cosq_index_resolve 9925 (unit, port, cosq, style, &local_port, &startq, NULL)); 9926 9927 ctrl_info.instance = local_port; 9928 startq = startq - si->port_cosq_base[local_port]; 9929 BCM_IF_ERROR_RETURN 9930 (soc_counter_generic_set(unit, ctr_reg_mc, ctrl_info, 0, 9931 startq, value)); 9932 } 9933 } else { 9934 if (BCM_GPORT_IS_SCHEDULER(port)) { 9935 BCM_IF_ERROR_RETURN 9936 (_bcm_hx5_cosq_index_resolve 9937 (unit, port, cosq, style, &local_port, &startq, NULL)); 9938 from_cos = to_cos = startq; 9939 } else { 9940 BCM_IF_ERROR_RETURN 9941 (_bcm_hx5_cosq_localport_resolve(unit, port, 9942 &local_port)); 9943 9944 if (cosq == BCM_COS_INVALID) { 9945 /* if (cosq == -1) set value for the first cosq */ 9946 cosq = 0; 9947 } 9948 from_cos = to_cos = cosq; 9949 } 9950 ctrl_info.instance = local_port; 9951 for (ci = from_cos; ci <= to_cos; ci++) { 9952 if (!IS_CPU_PORT(unit, local_port)) { 9953 if (ctr_reg_uc != INVALIDr) { 9954 /* Set UC values if NOT CPU port */ 9955 BCM_IF_ERROR_RETURN 9956 (soc_counter_generic_set(unit, ctr_reg_uc, 9957 ctrl_info, 0, 9958 ci, value)); 9959 } 9960 } 9961 9962 if (ctr_reg_mc != INVALIDr) { 9963 BCM_IF_ERROR_RETURN 9964 (soc_counter_generic_set(unit, ctr_reg_mc, 9965 ctrl_info, 0, ci, value)); 9966 } 9967 } 9968 } 9969 break; 9970 case bcmCosqStatYellowCongestionDroppedPackets: 9971 case bcmCosqStatRedCongestionDroppedPackets: 9972 case bcmCosqStatGreenDiscardDroppedPackets: 9973 case bcmCosqStatYellowDiscardDroppedPackets: 9974 case bcmCosqStatRedDiscardDroppedPackets: 9975 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 9976 BCM_GPORT_IS_SCHEDULER(port) || 9977 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 9978 return BCM_E_PARAM; 9979 } 9980 if (cosq != BCM_COS_INVALID) { 9981 return BCM_E_UNAVAIL; 9982 } 9983 if (stat == bcmCosqStatYellowCongestionDroppedPackets) { 9984 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_PKT_YELLOW; 9985 } else if (stat == bcmCosqStatRedCongestionDroppedPackets) { 9986 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_PKT_RED; 9987 } else if (stat == bcmCosqStatYellowDiscardDroppedPackets) { 9988 ctr_reg = SOC_COUNTER_NON_DMA_PORT_WRED_PKT_YELLOW; 9989 } else if (stat == bcmCosqStatRedDiscardDroppedPackets) { 9990 ctr_reg = SOC_COUNTER_NON_DMA_PORT_WRED_PKT_RED; 9991 } else { 9992 ctr_reg = SOC_COUNTER_NON_DMA_PORT_WRED_PKT_GREEN; 9993 } 9994 BCM_IF_ERROR_RETURN 9995 (_bcm_hx5_cosq_localport_resolve(unit, port, &local_port)); 9996 9997 ctrl_info.instance = local_port; 9998 BCM_IF_ERROR_RETURN 9999 (soc_counter_generic_set(unit, ctr_reg, ctrl_info, 0, 10000 startq, value)); 10001 break; 10002 case bcmCosqStatHighPriDroppedPackets: 10003 case bcmCosqStatOBMLossyHighPriDroppedPackets: 10004 case bcmCosqStatLowPriDroppedPackets: 10005 case bcmCosqStatOBMLossyLowPriDroppedPackets: 10006 case bcmCosqStatHighPriDroppedBytes: 10007 case bcmCosqStatOBMLossyHighPriDroppedBytes: 10008 case bcmCosqStatLowPriDroppedBytes: 10009 case bcmCosqStatOBMLossyLowPriDroppedBytes: 10010 case bcmCosqStatOBMLossless0DroppedPackets: 10011 case bcmCosqStatOBMLossless1DroppedPackets: 10012 case bcmCosqStatOBMLossless0DroppedBytes: 10013 case bcmCosqStatOBMLossless1DroppedBytes: 10014 case bcmCosqStatOBMFlowControlEvents: 10015 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 10016 BCM_GPORT_IS_SCHEDULER(port) || 10017 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 10018 return BCM_E_PARAM; 10019 } 10020 if ((stat == bcmCosqStatHighPriDroppedPackets) || 10021 (stat == bcmCosqStatOBMLossyHighPriDroppedPackets)) { 10022 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM_LOSSY_HI; 10023 } else if ((stat == bcmCosqStatLowPriDroppedPackets) || 10024 (stat == bcmCosqStatOBMLossyLowPriDroppedPackets)) { 10025 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM_LOSSY_LO; 10026 } else if ((stat == bcmCosqStatHighPriDroppedBytes) || 10027 (stat == bcmCosqStatOBMLossyHighPriDroppedBytes)) { 10028 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM_LOSSY_HI; 10029 } else if ((stat == bcmCosqStatLowPriDroppedBytes) || 10030 (stat == bcmCosqStatOBMLossyLowPriDroppedBytes)) { 10031 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM_LOSSY_LO; 10032 } else if (stat == bcmCosqStatOBMLossless0DroppedPackets) { 10033 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM_LOSSLESS0; 10034 } else if (stat == bcmCosqStatOBMLossless1DroppedPackets) { 10035 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM_LOSSLESS1; 10036 } else if (stat == bcmCosqStatOBMLossless0DroppedBytes) { 10037 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM_LOSSLESS0; 10038 } else if (stat == bcmCosqStatOBMLossless1DroppedBytes) { 10039 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM_LOSSLESS1; 10040 } else { /* (stat == bcmCosqStatOBMFlowControlEvents) */ 10041 ctr_reg = SOC_COUNTER_NON_DMA_PORT_OBM_FC_EVENTS; 10042 } 10043 ctrl_info.instance_type = SOC_CTR_INSTANCE_TYPE_PORT; 10044 ctrl_info.instance = local_port; 10045 BCM_IF_ERROR_RETURN 10046 (soc_counter_generic_set(unit, ctr_reg, ctrl_info, 0, 10047 0, value)); 10048 break; 10049 case bcmCosqStatOBMHighWatermark: 10050 case bcmCosqStatOBMBufferBytes: 10051 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 10052 BCM_GPORT_IS_SCHEDULER(port) || 10053 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 10054 return BCM_E_PARAM; 10055 } 10056 if (stat == bcmCosqStatOBMHighWatermark) { 10057 BCM_IF_ERROR_RETURN 10058 (_bcm_hx5_cosq_obmhighwatermark_set(unit, local_port, value)); 10059 } else { /* stat == bcmCosqStatOBMBufferBytes */ 10060 BCM_IF_ERROR_RETURN 10061 (_bcm_hx5_cosq_obm_buf_use_cnt_set(unit, local_port, value)); 10062 } 10063 break; 10064 default: 10065 return BCM_E_PARAM; 10066 } 10067 10068 return BCM_E_NONE; 10069 } 10070 10071 /* 10072 * Function: 10073 * bcm_hx5_cosq_stat_get 10074 * Purpose: 10075 * Get MMU statistics on a per port per cosq basis. 10076 * Parameters: 10077 * unit - (IN) Unit number. 10078 * port - (IN) GPORT ID. 10079 * cosq - (IN) COS queue. 10080 * stat - (IN) Statistic to be retrieved. 10081 * sync_mode - (IN) whether to sync before read. 10082 * value - (OUT) Returned statistic value. 10083 * Returns: 10084 * BCM_E_xxx 10085 * Notes: 10086 */ 10087 int 10088 bcm_hx5_cosq_stat_get(int unit, bcm_gport_t port, bcm_cos_queue_t cosq, 10089 bcm_cosq_stat_t stat, int sync_mode, uint64 *value) 10090 { 10091 soc_ctr_control_info_t ctrl_info; 10092 soc_reg_t ctr_reg, ctr_reg_uc, ctr_reg_mc; 10093 _bcm_hx5_cosq_index_style_t style = _BCM_HX5_COSQ_INDEX_STYLE_COUNT; 10094 uint64 sum, value64; 10095 int startq = 0, ci, from_cos, to_cos, i, start_hw_index, end_hw_index; 10096 bcm_port_t local_port = -1; 10097 int sync = sync_mode ? SOC_COUNTER_SYNC_ENABLE : 0; 10098 soc_info_t *si = &SOC_INFO(unit); 10099 10100 BCM_IF_ERROR_RETURN 10101 (_bcm_hx5_cosq_localport_resolve(unit, port, &local_port)); 10102 ctrl_info.instance = -1; 10103 ctrl_info.instance_type = SOC_CTR_INSTANCE_TYPE_XPE; 10104 10105 switch (stat) { 10106 case bcmCosqStatDroppedPackets: 10107 case bcmCosqStatDroppedBytes: 10108 case bcmCosqStatOutPackets: 10109 case bcmCosqStatOutBytes: 10110 case bcmCosqStatEgressMCQueueBytesPeak: 10111 case bcmCosqStatEgressMCQueueBytesCurrent: 10112 case bcmCosqStatEgressUCQueueBytesPeak: 10113 case bcmCosqStatEgressUCQueueBytesCurrent: 10114 if ((cosq < -1) || (cosq >= si->port_num_cosq[local_port])) { 10115 return BCM_E_PARAM; 10116 } 10117 style = _BCM_HX5_COSQ_INDEX_STYLE_COS; 10118 if (stat == bcmCosqStatEgressMCQueueBytesPeak) { 10119 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 10120 BCM_GPORT_IS_SCHEDULER(port)) { 10121 return BCM_E_PARAM; 10122 } 10123 ctr_reg_uc = INVALIDr; 10124 ctr_reg_mc = SOC_COUNTER_NON_DMA_QUEUE_PEAK; 10125 } else if (stat == bcmCosqStatEgressMCQueueBytesCurrent) { 10126 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 10127 BCM_GPORT_IS_SCHEDULER(port)) { 10128 return BCM_E_PARAM; 10129 } 10130 ctr_reg_uc = INVALIDr; 10131 ctr_reg_mc = SOC_COUNTER_NON_DMA_QUEUE_CURRENT; 10132 } else if (stat == bcmCosqStatEgressUCQueueBytesPeak) { 10133 if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) || 10134 BCM_GPORT_IS_SCHEDULER(port)) { 10135 return BCM_E_PARAM; 10136 } 10137 if (!BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) { 10138 BCM_IF_ERROR_RETURN 10139 (_bcm_hx5_cosq_localport_resolve(unit, port, 10140 &local_port)); 10141 if (IS_CPU_PORT(unit, local_port)) 10142 { 10143 return BCM_E_PARAM; 10144 } 10145 } 10146 ctr_reg_uc = SOC_COUNTER_NON_DMA_UC_QUEUE_PEAK; 10147 ctr_reg_mc = INVALIDr; 10148 } else if (stat == bcmCosqStatEgressUCQueueBytesCurrent) { 10149 if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) || 10150 BCM_GPORT_IS_SCHEDULER(port)) { 10151 return BCM_E_PARAM; 10152 } 10153 if (!BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) { 10154 BCM_IF_ERROR_RETURN 10155 (_bcm_hx5_cosq_localport_resolve(unit, port, 10156 &local_port)); 10157 if (IS_CPU_PORT(unit, local_port)) 10158 { 10159 return BCM_E_PARAM; 10160 } 10161 } 10162 ctr_reg_uc = SOC_COUNTER_NON_DMA_UC_QUEUE_CURRENT; 10163 ctr_reg_mc = INVALIDr; 10164 } else if (stat == bcmCosqStatDroppedBytes) { 10165 ctr_reg_uc = SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE_UC; 10166 ctr_reg_mc = SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE; 10167 } else if (stat == bcmCosqStatDroppedPackets) { 10168 ctr_reg_uc = SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_UC; 10169 ctr_reg_mc = SOC_COUNTER_NON_DMA_COSQ_DROP_PKT; 10170 } else if (stat == bcmCosqStatOutBytes) { 10171 ctr_reg_uc = SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE_UC; 10172 ctr_reg_mc = SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE; 10173 ctrl_info.instance_type = SOC_CTR_INSTANCE_TYPE_PORT; 10174 } else { /* (stat == bcmCosqStatOutPackets) */ 10175 ctr_reg_uc = SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT_UC; 10176 ctr_reg_mc = SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT; 10177 ctrl_info.instance_type = SOC_CTR_INSTANCE_TYPE_PORT; 10178 } 10179 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) { 10180 if (ctr_reg_uc != INVALIDr) { 10181 BCM_IF_ERROR_RETURN 10182 (_bcm_hx5_cosq_index_resolve 10183 (unit, port, cosq, style, &local_port, &startq, NULL)); 10184 10185 startq = startq - si->port_uc_cosq_base[local_port]; 10186 ctrl_info.instance = local_port; 10187 BCM_IF_ERROR_RETURN 10188 (soc_counter_generic_get(unit, ctr_reg_uc, ctrl_info, 10189 sync, startq, value)); 10190 } 10191 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 10192 if (ctr_reg_mc != INVALIDr) { 10193 BCM_IF_ERROR_RETURN 10194 (_bcm_hx5_cosq_index_resolve 10195 (unit, port, cosq, style, &local_port, &startq, NULL)); 10196 ctrl_info.instance = local_port; 10197 startq = startq - si->port_cosq_base[local_port]; 10198 BCM_IF_ERROR_RETURN 10199 (soc_counter_generic_get(unit, ctr_reg_mc, ctrl_info, 10200 sync, startq, value)); 10201 } 10202 } else { 10203 if (BCM_GPORT_IS_SCHEDULER(port)) { 10204 BCM_IF_ERROR_RETURN 10205 (_bcm_hx5_cosq_index_resolve 10206 (unit, port, cosq, style, &local_port, &startq, NULL)); 10207 from_cos = to_cos = startq; 10208 } else { 10209 BCM_IF_ERROR_RETURN 10210 (_bcm_hx5_cosq_localport_resolve(unit, port, 10211 &local_port)); 10212 10213 if (cosq == BCM_COS_INVALID) { 10214 from_cos = 0; 10215 to_cos = (IS_CPU_PORT(unit, local_port)) ? \ 10216 NUM_CPU_COSQ(unit) - 1 : _BCM_HX5_NUM_COS(unit) - 1; 10217 } else { 10218 from_cos = to_cos = cosq; 10219 } 10220 } 10221 COMPILER_64_ZERO(sum); 10222 ctrl_info.instance = local_port; 10223 for (ci = from_cos; ci <= to_cos; ci++) { 10224 10225 if (!IS_CPU_PORT(unit, local_port)) { 10226 /* Get UC values if NOT CPU port */ 10227 if (ctr_reg_uc != INVALIDr) { 10228 BCM_IF_ERROR_RETURN 10229 (soc_counter_generic_get(unit, ctr_reg_uc, 10230 ctrl_info, 10231 sync, ci, &value64)); 10232 COMPILER_64_ADD_64(sum, value64); 10233 } 10234 } 10235 10236 if (ctr_reg_mc != INVALIDr) { 10237 BCM_IF_ERROR_RETURN 10238 (soc_counter_generic_get(unit, ctr_reg_mc, 10239 ctrl_info, 10240 sync, ci, &value64)); 10241 COMPILER_64_ADD_64(sum, value64); 10242 } 10243 } 10244 *value = sum; 10245 } 10246 break; 10247 case bcmCosqStatYellowCongestionDroppedPackets: 10248 case bcmCosqStatRedCongestionDroppedPackets: 10249 case bcmCosqStatGreenDiscardDroppedPackets: 10250 case bcmCosqStatYellowDiscardDroppedPackets: 10251 case bcmCosqStatRedDiscardDroppedPackets: 10252 if ((cosq < -1) || (cosq >= si->port_num_cosq[local_port])) { 10253 return BCM_E_PARAM; 10254 } 10255 10256 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 10257 BCM_GPORT_IS_SCHEDULER(port) || 10258 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 10259 return BCM_E_PARAM; 10260 } 10261 if (cosq != BCM_COS_INVALID) { 10262 return BCM_E_UNAVAIL; 10263 } 10264 if (stat == bcmCosqStatYellowCongestionDroppedPackets) { 10265 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_PKT_YELLOW; 10266 } else if (stat == bcmCosqStatRedCongestionDroppedPackets) { 10267 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_PKT_RED; 10268 } else if (stat == bcmCosqStatYellowDiscardDroppedPackets) { 10269 ctr_reg = SOC_COUNTER_NON_DMA_PORT_WRED_PKT_YELLOW; 10270 } else if (stat == bcmCosqStatRedDiscardDroppedPackets) { 10271 ctr_reg = SOC_COUNTER_NON_DMA_PORT_WRED_PKT_RED; 10272 } else { /* (stat == bcmCosqStatGreenDiscardDroppedPackets) */ 10273 ctr_reg = SOC_COUNTER_NON_DMA_PORT_WRED_PKT_GREEN; 10274 } 10275 BCM_IF_ERROR_RETURN 10276 (_bcm_hx5_cosq_localport_resolve(unit, port, &local_port)); 10277 10278 ctrl_info.instance = local_port; 10279 BCM_IF_ERROR_RETURN 10280 (soc_counter_generic_get(unit, ctr_reg, ctrl_info, 10281 sync, startq, value)); 10282 break; 10283 case bcmCosqStatIngressPortPGMinBytesPeak: 10284 case bcmCosqStatIngressPortPGMinBytesCurrent: 10285 case bcmCosqStatIngressPortPGSharedBytesPeak: 10286 case bcmCosqStatIngressPortPGSharedBytesCurrent: 10287 case bcmCosqStatIngressPortPGHeadroomBytesPeak: 10288 case bcmCosqStatIngressPortPGHeadroomBytesCurrent: 10289 if (cosq < -1) { 10290 return BCM_E_PARAM; 10291 } 10292 10293 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 10294 BCM_GPORT_IS_SCHEDULER(port) || 10295 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 10296 return BCM_E_PARAM; 10297 } 10298 if (stat == bcmCosqStatIngressPortPGMinBytesPeak) { 10299 ctr_reg = SOC_COUNTER_NON_DMA_PG_MIN_PEAK; 10300 } else if (stat == bcmCosqStatIngressPortPGMinBytesCurrent) { 10301 ctr_reg = SOC_COUNTER_NON_DMA_PG_MIN_CURRENT; 10302 } else if (stat == bcmCosqStatIngressPortPGSharedBytesPeak) { 10303 ctr_reg = SOC_COUNTER_NON_DMA_PG_SHARED_PEAK; 10304 } else if (stat == bcmCosqStatIngressPortPGSharedBytesCurrent) { 10305 ctr_reg = SOC_COUNTER_NON_DMA_PG_SHARED_CURRENT; 10306 } else if (stat == bcmCosqStatIngressPortPGHeadroomBytesPeak) { 10307 ctr_reg = SOC_COUNTER_NON_DMA_PG_HDRM_PEAK; 10308 } else { 10309 /* (stat == bcmCosqStatIngressPortPGHeadroomBytesCurrent) */ 10310 ctr_reg = SOC_COUNTER_NON_DMA_PG_HDRM_CURRENT; 10311 } 10312 BCM_IF_ERROR_RETURN 10313 (_bcm_hx5_cosq_localport_resolve(unit, port, &local_port)); 10314 BCM_IF_ERROR_RETURN 10315 (_bcm_hx5_cosq_ingress_pg_get(unit, port, cosq, 10316 &start_hw_index, &end_hw_index)); 10317 10318 COMPILER_64_ZERO(sum); 10319 for (i = start_hw_index; i <= end_hw_index; i++) { 10320 ctrl_info.instance = local_port; 10321 BCM_IF_ERROR_RETURN 10322 (soc_counter_generic_get(unit, ctr_reg, ctrl_info, 10323 sync, i, &value64)); 10324 COMPILER_64_ADD_64(sum, value64); 10325 } 10326 10327 COMPILER_64_UMUL_32(sum, _HX5_MMU_BYTES_PER_CELL); 10328 *value = sum; 10329 break; 10330 case bcmCosqStatIngressPortPoolSharedBytesPeak: 10331 if (cosq < -1) { 10332 return BCM_E_PARAM; 10333 } 10334 10335 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 10336 BCM_GPORT_IS_SCHEDULER(port) || 10337 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 10338 return BCM_E_PARAM; 10339 } 10340 BCM_IF_ERROR_RETURN 10341 (_bcm_hx5_cosq_ingress_sp_get_by_pg(unit, port, cosq, 10342 &start_hw_index, &end_hw_index)); 10343 10344 BCM_IF_ERROR_RETURN( 10345 _bcm_hx5_cosq_localport_resolve(unit, port, &local_port)); 10346 10347 ctrl_info.instance_type = SOC_CTR_INSTANCE_TYPE_XPE; 10348 ctrl_info.instance = local_port; 10349 ctr_reg = SOC_COUNTER_NON_DMA_POOL_PEAK; 10350 10351 COMPILER_64_ZERO(sum); 10352 for (i = start_hw_index; i <= end_hw_index; i++) { 10353 BCM_IF_ERROR_RETURN 10354 (soc_counter_generic_get(unit, ctr_reg, ctrl_info, 10355 sync, i, &value64)); 10356 COMPILER_64_ADD_64(sum, value64); 10357 } 10358 10359 COMPILER_64_UMUL_32(sum, _HX5_MMU_BYTES_PER_CELL); 10360 *value = sum; 10361 break; 10362 case bcmCosqStatIngressPortPoolSharedBytesCurrent: 10363 if (cosq < -1) { 10364 return BCM_E_PARAM; 10365 } 10366 10367 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 10368 BCM_GPORT_IS_SCHEDULER(port) || 10369 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 10370 return BCM_E_PARAM; 10371 } 10372 BCM_IF_ERROR_RETURN 10373 (_bcm_hx5_cosq_ingress_sp_get_by_pg(unit, port, cosq, 10374 &start_hw_index, &end_hw_index)); 10375 BCM_IF_ERROR_RETURN( 10376 _bcm_hx5_cosq_localport_resolve(unit, port, &local_port)); 10377 10378 ctrl_info.instance_type = SOC_CTR_INSTANCE_TYPE_XPE; 10379 ctrl_info.instance = local_port; 10380 ctr_reg = SOC_COUNTER_NON_DMA_POOL_CURRENT; 10381 10382 COMPILER_64_ZERO(sum); 10383 for (i = start_hw_index; i <= end_hw_index; i++) { 10384 BCM_IF_ERROR_RETURN 10385 (soc_counter_generic_get(unit, ctr_reg, ctrl_info, 10386 sync, i, &value64)); 10387 COMPILER_64_ADD_64(sum, value64); 10388 } 10389 10390 COMPILER_64_UMUL_32(sum, _HX5_MMU_BYTES_PER_CELL); 10391 *value = sum; 10392 break; 10393 case bcmCosqStatHighPriDroppedPackets: 10394 case bcmCosqStatOBMLossyHighPriDroppedPackets: 10395 case bcmCosqStatLowPriDroppedPackets: 10396 case bcmCosqStatOBMLossyLowPriDroppedPackets: 10397 case bcmCosqStatHighPriDroppedBytes: 10398 case bcmCosqStatOBMLossyHighPriDroppedBytes: 10399 case bcmCosqStatLowPriDroppedBytes: 10400 case bcmCosqStatOBMLossyLowPriDroppedBytes: 10401 case bcmCosqStatOBMLossless0DroppedPackets: 10402 case bcmCosqStatOBMLossless1DroppedPackets: 10403 case bcmCosqStatOBMLossless0DroppedBytes: 10404 case bcmCosqStatOBMLossless1DroppedBytes: 10405 case bcmCosqStatOBMFlowControlEvents: 10406 if ((cosq < -1) || (cosq >= si->port_num_cosq[local_port])) { 10407 return BCM_E_PARAM; 10408 } 10409 10410 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 10411 BCM_GPORT_IS_SCHEDULER(port) || 10412 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 10413 return BCM_E_PARAM; 10414 } 10415 if ((stat == bcmCosqStatHighPriDroppedPackets) || 10416 (stat == bcmCosqStatOBMLossyHighPriDroppedPackets)) { 10417 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM_LOSSY_HI; 10418 } else if ((stat == bcmCosqStatLowPriDroppedPackets) || 10419 (stat == bcmCosqStatOBMLossyLowPriDroppedPackets)) { 10420 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM_LOSSY_LO; 10421 } else if ((stat == bcmCosqStatHighPriDroppedBytes) || 10422 (stat == bcmCosqStatOBMLossyHighPriDroppedBytes)) { 10423 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM_LOSSY_HI; 10424 } else if ((stat == bcmCosqStatLowPriDroppedBytes) || 10425 (stat == bcmCosqStatOBMLossyLowPriDroppedBytes)) { 10426 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM_LOSSY_LO; 10427 } else if (stat == bcmCosqStatOBMLossless0DroppedPackets) { 10428 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM_LOSSLESS0; 10429 } else if (stat == bcmCosqStatOBMLossless1DroppedPackets) { 10430 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM_LOSSLESS1; 10431 } else if (stat == bcmCosqStatOBMLossless0DroppedBytes) { 10432 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM_LOSSLESS0; 10433 } else if (stat == bcmCosqStatOBMLossless1DroppedBytes) { 10434 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM_LOSSLESS1; 10435 } else { /* (stat == bcmCosqStatOBMFlowControlEvents) */ 10436 ctr_reg = SOC_COUNTER_NON_DMA_PORT_OBM_FC_EVENTS; 10437 } 10438 ctrl_info.instance_type = SOC_CTR_INSTANCE_TYPE_PORT; 10439 ctrl_info.instance = local_port; 10440 BCM_IF_ERROR_RETURN 10441 (soc_counter_generic_get(unit, ctr_reg, ctrl_info, 0, 10442 0, value)); 10443 break; 10444 case bcmCosqStatOBMHighWatermark: 10445 case bcmCosqStatOBMBufferBytes: 10446 if ((cosq < -1) || (cosq >= si->port_num_cosq[local_port])) { 10447 return BCM_E_PARAM; 10448 } 10449 10450 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 10451 BCM_GPORT_IS_SCHEDULER(port) || 10452 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 10453 return BCM_E_PARAM; 10454 } 10455 if (stat == bcmCosqStatOBMHighWatermark) { 10456 BCM_IF_ERROR_RETURN 10457 (_bcm_hx5_cosq_obmhighwatermark_get(unit, local_port, value)); 10458 } else { /* stat == bcmCosqStatOBMBufferBytes */ 10459 BCM_IF_ERROR_RETURN 10460 (_bcm_hx5_cosq_obm_buf_use_cnt_get(unit, local_port, value)); 10461 } 10462 break; 10463 default: 10464 return BCM_E_PARAM; 10465 } 10466 10467 return BCM_E_NONE; 10468 } 10469 10470 10471 STATIC int 10472 _bcm_hx5_cosq_cpu_tree_create(int unit, bcm_port_t port) 10473 { 10474 int id, sc_id; 10475 bcm_gport_t sched_gport[SOC_HX5_NUM_SCHEDULER_PER_CPU_PORT]; 10476 bcm_gport_t cpu_mc_gport[SOC_HX5_NUM_CPU_QUEUES]; 10477 int numq = 1; 10478 10479 /*Creating all L0,L1 and L2 scheduler nodes for cpu port */ 10480 for (id = 0; id < SOC_HX5_NUM_SCHEDULER_PER_CPU_PORT; id++) { 10481 if (id == 1) { 10482 numq = 10; 10483 } else if (id >= 2 && id <= 11) { 10484 numq = 48; 10485 } 10486 10487 BCM_IF_ERROR_RETURN 10488 (_bcm_hx5_cosq_gport_add(unit, port, numq, 10489 BCM_COSQ_GPORT_SCHEDULER, 10490 &sched_gport[id])); 10491 } 10492 10493 /* Attaching L0 schedular node to front panel port */ 10494 BCM_IF_ERROR_RETURN 10495 (bcm_hx5_cosq_gport_attach(unit, sched_gport[0], port, 0)); 10496 10497 /* Attaching L1 schedular node to L0 schedular node */ 10498 BCM_IF_ERROR_RETURN 10499 (bcm_hx5_cosq_gport_attach(unit, sched_gport[1], sched_gport[0], 1)); 10500 10501 /* Attaching L2 schedular node to L1 schedular node */ 10502 for (sc_id = 2; sc_id < SOC_HX5_NUM_SCHEDULER_PER_CPU_PORT; sc_id++) { 10503 BCM_IF_ERROR_RETURN 10504 (bcm_hx5_cosq_gport_attach(unit, sched_gport[sc_id], sched_gport[1], sc_id)); 10505 } 10506 10507 numq = 1; 10508 for (id = 0; id < SOC_HX5_NUM_CPU_QUEUES; id++) { 10509 BCM_IF_ERROR_RETURN 10510 (_bcm_hx5_cosq_gport_add(unit, port, numq, 10511 BCM_COSQ_GPORT_MCAST_QUEUE_GROUP, 10512 &cpu_mc_gport[id])); 10513 /* Attach all the 48 CPU MC queues to L2.0 node */ 10514 BCM_IF_ERROR_RETURN 10515 (bcm_hx5_cosq_gport_attach(unit, cpu_mc_gport[id], 10516 sched_gport[2], id)); 10517 } 10518 10519 return BCM_E_NONE; 10520 10521 10522 } 10523 10524 /* 10525 * Function: 10526 * bcm_hx5_cosq_gport_child_get 10527 * Purpose: 10528 * Get the child node GPORT atatched to N-th index (cosq) 10529 * of the scheduler GPORT. 10530 * Parameters: 10531 * unit - (IN) Unit number. 10532 * in_gport - (IN) Scheduler GPORT ID. 10533 * cosq - (IN) COS queue attached to. 10534 * out_gport - (OUT) Child GPORT ID. 10535 * Returns: 10536 * BCM_E_XXX 10537 */ 10538 10539 int 10540 bcm_hx5_cosq_gport_child_get(int unit, bcm_gport_t in_gport, 10541 bcm_cos_queue_t cosq, bcm_gport_t *out_gport) 10542 { 10543 _bcm_hx5_cosq_node_t *tmp_node = NULL; 10544 bcm_port_t local_port = -1; 10545 _bcm_hx5_cosq_cpu_port_info_t *port_info = NULL; 10546 int index = -1, cpu_mc_base = 0; 10547 soc_info_t *si = &SOC_INFO(unit); 10548 10549 if (out_gport == NULL) { 10550 return BCM_E_PARAM; 10551 } 10552 10553 BCM_IF_ERROR_RETURN 10554 (_bcm_hx5_cosq_localport_resolve(unit, in_gport, &local_port)); 10555 10556 if (!SOC_PORT_VALID(unit, local_port)) { 10557 return BCM_E_PORT; 10558 } 10559 10560 /* This API is only supported for CPU ports because 10561 * for all other ports we have fixed hierarchy */ 10562 if (!IS_CPU_PORT(unit, local_port)) { 10563 return BCM_E_PARAM; 10564 } 10565 10566 if ((cosq < 0) || (cosq >= NUM_CPU_COSQ(unit))) { 10567 return BCM_E_PARAM; 10568 } 10569 10570 if (_bcm_hx5_cosq_cpu_port_info[unit] == NULL) { 10571 return BCM_E_INIT; 10572 } 10573 10574 port_info = _bcm_hx5_cosq_cpu_port_info[unit]; 10575 cpu_mc_base = si->port_cosq_base[CMIC_PORT(unit)]; 10576 10577 if (BCM_GPORT_IS_SCHEDULER(in_gport)) { 10578 for (index = 0; index < SOC_HX5_NUM_CPU_QUEUES; index++) { 10579 if (port_info->mcast[index].parent_gport == in_gport) { 10580 if (cosq == ((port_info->mcast[index].hw_index - cpu_mc_base) % 10581 SOC_HX5_NUM_CPU_QUEUES)) { 10582 tmp_node = &port_info->mcast[index]; 10583 break; 10584 } 10585 } 10586 } 10587 } else { 10588 return BCM_E_PARAM; 10589 } 10590 10591 if (tmp_node == NULL) { 10592 return BCM_E_NOT_FOUND; 10593 } 10594 10595 *out_gport = tmp_node->gport; 10596 10597 return BCM_E_NONE; 10598 } 10599 10600 /* 10601 * Function: 10602 * _bcm_hx5_cosq_gport_tree_create 10603 * Purpose: 10604 * During cosq init create the default cosq gport tree. 10605 * Schedualar (L0) nodes are created and attach to physical ports. 10606 * UC and MC queues are added and attached to each L0 nodes. 10607 * Parameters: 10608 * unit - (IN) unit number. 10609 * port - (IN) port number 10610 * Returns: 10611 * BCM_E_XXX 10612 */ 10613 STATIC int 10614 _bcm_hx5_cosq_gport_tree_create(int unit, bcm_port_t port) 10615 { 10616 int id, sc_id; 10617 bcm_gport_t sched_gport[SOC_HX5_NUM_SCHEDULER_PER_PORT]; 10618 bcm_gport_t uc_gport[SOC_HX5_NUM_UCAST_QUEUE_PER_PORT]; 10619 bcm_gport_t mc_gport[SOC_HX5_NUM_MCAST_QUEUE_PER_PORT]; 10620 int numq = 1; 10621 10622 /*Creating all L0,L1 and L2 scheduler nodes */ 10623 for (id = 0; id < SOC_HX5_NUM_SCHEDULER_PER_PORT; id++) { 10624 if (id == 0 || id >= 3) { 10625 numq = 2; 10626 } else if(id > 0 && id < 3) { 10627 numq = 8; 10628 } 10629 BCM_IF_ERROR_RETURN 10630 (_bcm_hx5_cosq_gport_add(unit, port, numq, 10631 BCM_COSQ_GPORT_SCHEDULER, 10632 &sched_gport[id])); 10633 } 10634 10635 /* Attaching L0 schedular node to front panel port */ 10636 BCM_IF_ERROR_RETURN 10637 (bcm_hx5_cosq_gport_attach(unit, sched_gport[0], port, 0)); 10638 10639 /* Attaching L1 schedular nodes to L0 schedular node */ 10640 for(sc_id = 1; sc_id < 3; sc_id++){ 10641 BCM_IF_ERROR_RETURN 10642 (bcm_hx5_cosq_gport_attach(unit, sched_gport[sc_id], sched_gport[0], sc_id)); 10643 } 10644 /* Attaching L2 schedular nodes to L1 schedular node */ 10645 for(sc_id = 3; sc_id < SOC_HX5_NUM_SCHEDULER_PER_PORT; sc_id++){ 10646 BCM_IF_ERROR_RETURN 10647 (bcm_hx5_cosq_gport_attach(unit, sched_gport[sc_id], (sc_id < 11) ? sched_gport[1] : sched_gport[2], sc_id)); 10648 } 10649 numq = 1; 10650 /* Creating and attaching l3 uc and l2 mc queues to l2 Schedular nodes */ 10651 for (id = 0, sc_id = 3; id < SOC_HX5_NUM_UCAST_QUEUE_PER_PORT && 10652 sc_id < SOC_HX5_NUM_SCHEDULER_PER_PORT; id++, sc_id++) { 10653 BCM_IF_ERROR_RETURN 10654 (_bcm_hx5_cosq_gport_add(unit, port, numq, 10655 BCM_COSQ_GPORT_UCAST_QUEUE_GROUP, 10656 &uc_gport[id])); 10657 BCM_IF_ERROR_RETURN 10658 (bcm_hx5_cosq_gport_attach(unit, uc_gport[id], 10659 sched_gport[sc_id], id)); 10660 BCM_IF_ERROR_RETURN 10661 (_bcm_hx5_cosq_gport_add(unit, port, numq, 10662 BCM_COSQ_GPORT_MCAST_QUEUE_GROUP, 10663 &mc_gport[id])); 10664 BCM_IF_ERROR_RETURN 10665 (bcm_hx5_cosq_gport_attach(unit, mc_gport[id], 10666 sched_gport[sc_id], id)); 10667 } 10668 return BCM_E_NONE; 10669 } 10670 10671 /* 10672 * Function: 10673 * bcm_hx5_cosq_port_pfc_op 10674 * Purpose: 10675 * Set PFC Prio 2 Cos Map and set the profile index for the Port 10676 * Parameters: 10677 * unit - (IN) unit number 10678 * port - (IN) GPORT identifier 10679 * sctype - (IN) Input Class 10680 * op - (IN) Operation to be performed (ADD|SET|CLEAR) 10681 * gport - (IN) Gport/Cos array 10682 * gport_ct - (IN) Count of values in the array 10683 * Returns: 10684 * BCM_E_XXX 10685 */ 10686 int 10687 bcm_hx5_cosq_port_pfc_op(int unit, bcm_port_t port, 10688 bcm_switch_control_t sctype, _bcm_cosq_op_t op, 10689 bcm_gport_t *gport, int gport_count) 10690 { 10691 bcm_port_t local_port; 10692 int type = -1, class = -1, index, hw_cosq; 10693 uint32 profile_index, old_profile_index; 10694 uint32 rval, fval, cos_bmp; 10695 uint64 rval64[16], *rval64s[1]; 10696 _bcm_hx5_cosq_node_t *node; 10697 static const soc_reg_t port_fc_reg = PORT_LLFC_CFGr; 10698 soc_field_t field = INVALIDf; 10699 soc_info_t *si = &SOC_INFO(unit); 10700 int rv = SOC_E_NONE; 10701 10702 if (gport_count < 0) { 10703 return BCM_E_PARAM; 10704 } 10705 10706 BCM_IF_ERROR_RETURN 10707 (_bcm_hx5_cosq_localport_resolve(unit, port, &local_port)); 10708 if (IS_CPU_PORT(unit, local_port)) { 10709 return BCM_E_PARAM; 10710 } 10711 10712 BCM_IF_ERROR_RETURN(_bcm_hx5_cosq_pfc_class_resolve(sctype, &type, &class)); 10713 10714 cos_bmp = 0; 10715 10716 if (type == _BCM_HX5_COSQ_TYPE_MCAST) { 10717 field = MC_COS_BMPf; 10718 } else { 10719 field = UC_COS_BMPf; 10720 } 10721 10722 for (index = 0; index < gport_count; index++) { 10723 hw_cosq = -1; 10724 if (BCM_GPORT_IS_SET(gport[index]) && 10725 ((BCM_GPORT_IS_SCHEDULER(gport[index])) || 10726 BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport[index]) || 10727 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport[index]))) { 10728 BCM_IF_ERROR_RETURN 10729 (_bcm_hx5_cosq_node_get(unit, gport[index], NULL, 10730 NULL, NULL, &node)); 10731 if (BCM_GPORT_IS_SCHEDULER(gport[index])) { 10732 hw_cosq = node->hw_index % SOC_HX5_NUM_SCHEDULER_PER_PORT; 10733 } else if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport[index])) { 10734 if (type != _BCM_HX5_COSQ_TYPE_UCAST) { 10735 return BCM_E_PARAM; 10736 } 10737 hw_cosq = node->hw_index - si->port_uc_cosq_base[local_port]; 10738 10739 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport[index])) { 10740 if (type != _BCM_HX5_COSQ_TYPE_MCAST) { 10741 return BCM_E_PARAM; 10742 } 10743 hw_cosq = node->hw_index - si->port_cosq_base[local_port];; 10744 } 10745 } else { 10746 /* Find hardware index for given local_port, cosq */ 10747 hw_cosq = gport[index] % si->port_num_cosq[local_port]; 10748 } 10749 cos_bmp |= (1 << hw_cosq); 10750 } 10751 10752 rval64s[0] = rval64; 10753 BCM_IF_ERROR_RETURN(soc_reg32_get(unit, port_fc_reg, local_port, 0, &rval)); 10754 10755 if (op == _BCM_COSQ_OP_CLEAR || cos_bmp != 0) { 10756 old_profile_index = 16 * soc_reg_field_get(unit, port_fc_reg, rval, 10757 PROFILE_INDEXf); 10758 10759 BCM_IF_ERROR_RETURN 10760 (soc_profile_reg_get(unit, _bcm_hx5_prio2cos_profile[unit], 10761 old_profile_index, 16, rval64s)); 10762 if (op == _BCM_COSQ_OP_SET) { 10763 soc_reg64_field32_set(unit, PRIO2COS_PROFILE_64r, &rval64[class], 10764 field, cos_bmp); 10765 } else if (op == _BCM_COSQ_OP_CLEAR || cos_bmp != 0) { 10766 fval = soc_reg64_field32_get(unit, PRIO2COS_PROFILE_64r, rval64[class], 10767 field); 10768 if (op == _BCM_COSQ_OP_ADD) { 10769 fval |= cos_bmp; 10770 } else { /* _BCM_COSQ_OP_CLEAR */ 10771 fval = 0; 10772 } 10773 soc_reg64_field32_set(unit, PRIO2COS_PROFILE_64r, &rval64[class], 10774 field, fval); 10775 } 10776 BCM_IF_ERROR_RETURN 10777 (soc_profile_reg_delete(unit, _bcm_hx5_prio2cos_profile[unit], 10778 old_profile_index)); 10779 rv = soc_profile_reg_add(unit, _bcm_hx5_prio2cos_profile[unit], rval64s, 10780 16, &profile_index); 10781 if (rv != BCM_E_NONE) { 10782 SOC_IF_ERROR_RETURN 10783 (soc_profile_reg_reference(unit, _bcm_hx5_prio2cos_profile[unit], 10784 old_profile_index, 16)); 10785 return rv; 10786 } 10787 soc_reg_field_set(unit, port_fc_reg, &rval, PROFILE_INDEXf, 10788 profile_index / 16); 10789 } 10790 BCM_IF_ERROR_RETURN(soc_reg32_set(unit, port_fc_reg, local_port, 0, rval)); 10791 return BCM_E_NONE; 10792 } 10793 10794 /* 10795 * Function: 10796 * bcm_hx5_cosq_port_pfc_get 10797 * Purpose: 10798 * Get PFC Prio2Cos Map for a given Traffic Class 10799 * Parameters: 10800 * unit - (IN) unit number 10801 * port - (IN) GPORT identifier 10802 * sctype - (IN) Input Traffic Class 10803 * gport - (OUT) Gport/Cos array 10804 * gport_ct - (IN) Input Count of gport required 10805 * actual_gport_ct - (OUT) Actual Count of gport/cos in the array 10806 * Returns: 10807 * BCM_E_XXX 10808 */ 10809 int 10810 bcm_hx5_cosq_port_pfc_get(int unit, bcm_port_t port, 10811 bcm_switch_control_t sctype, 10812 bcm_gport_t *gport, int gport_count, 10813 int *actual_gport_count) 10814 { 10815 bcm_port_t local_port; 10816 int type = 0, class = -1, hw_cosq, count = 0; 10817 int port_index; 10818 uint32 profile_index; 10819 uint32 rval, cos_bmp; 10820 uint64 rval64[16], *rval64s[1]; 10821 static const soc_reg_t port_fc_reg = PORT_LLFC_CFGr; 10822 soc_field_t field = INVALIDf; 10823 _bcm_hx5_cosq_node_t *port_node = NULL; 10824 int phy_port, mmu_port; 10825 soc_info_t *si = &SOC_INFO(unit); 10826 10827 if (gport == NULL || gport_count <= 0 || actual_gport_count == NULL) { 10828 return BCM_E_PARAM; 10829 } 10830 10831 BCM_IF_ERROR_RETURN 10832 (_bcm_hx5_cosq_localport_resolve(unit, port, &local_port)); 10833 if (IS_CPU_PORT(unit, local_port)) { 10834 return BCM_E_PARAM; 10835 } 10836 10837 BCM_IF_ERROR_RETURN(_bcm_hx5_cosq_pfc_class_resolve(sctype, &type, &class)); 10838 10839 phy_port = si->port_l2p_mapping[local_port]; 10840 mmu_port = si->port_p2m_mapping[phy_port]; 10841 _HX5_PORT_INDEX_GET(unit, mmu_port, port_index); 10842 10843 rval64s[0] = rval64; 10844 BCM_IF_ERROR_RETURN(soc_reg32_get(unit, port_fc_reg, local_port, 0, &rval)); 10845 profile_index = 16 * soc_reg_field_get(unit, port_fc_reg, rval, 10846 PROFILE_INDEXf); 10847 10848 if (type == _BCM_HX5_COSQ_TYPE_MCAST) { 10849 field = MC_COS_BMPf; 10850 port_node = _HX5_IS_ST_PORT(unit, mmu_port) ? 10851 _bcm_hx5_cosq_st_port_info[unit][port_index].mcast : 10852 _bcm_hx5_cosq_port_info[unit][port_index].mcast; 10853 } else { 10854 field = UC_COS_BMPf; 10855 port_node = _HX5_IS_ST_PORT(unit, mmu_port) ? 10856 _bcm_hx5_cosq_st_port_info[unit][port_index].ucast : 10857 _bcm_hx5_cosq_port_info[unit][port_index].ucast; 10858 } 10859 10860 BCM_IF_ERROR_RETURN 10861 (soc_profile_reg_get(unit, _bcm_hx5_prio2cos_profile[unit], 10862 profile_index, 16, rval64s)); 10863 10864 cos_bmp = soc_reg64_field32_get(unit, PRIO2COS_PROFILE_64r, rval64[class], 10865 field); 10866 for (hw_cosq = 0; hw_cosq < si->port_num_cosq[local_port]; hw_cosq++) { 10867 if (!(cos_bmp & (1 << hw_cosq))) { 10868 continue; 10869 } 10870 gport[count++] = port_node[hw_cosq].gport; 10871 10872 if (count == gport_count) { 10873 break; 10874 } 10875 } 10876 if (count == 0) { 10877 return BCM_E_NOT_FOUND; 10878 } 10879 *actual_gport_count = count; 10880 10881 return BCM_E_NONE; 10882 } 10883 10884 /* 10885 * Function: 10886 * _bcm_hx5_cosq_port_fc_get 10887 * Purpose: 10888 * Get the UC|MC gport values associated with 10889 * the given PFC/SAFC class. 10890 * Parameters: 10891 * unit - (IN) unit number 10892 * port - (IN) port number 10893 * fc_class - (IN) PFC/SAFC internal priority class 10894 * gport_list - (OUT) UC|MC gport list 10895 * gport_count - (OUT) gport count 10896 * Returns: 10897 * BCM_E_XXX 10898 */ 10899 STATIC int 10900 _bcm_hx5_cosq_port_fc_get(int unit, bcm_gport_t local_port, 10901 int fc_class, bcm_gport_t *gport_list, 10902 int *gport_count) 10903 { 10904 int hw_cosq, count = 0; 10905 uint32 profile_index; 10906 uint32 rval, uc_cos_bmp, mc_cos_bmp; 10907 uint64 rval64[16], *rval64s[1]; 10908 static const soc_reg_t port_fc_reg = PORT_LLFC_CFGr; 10909 soc_info_t *si = &SOC_INFO(unit); 10910 10911 if ((gport_list == NULL) || (gport_count == NULL)) { 10912 return BCM_E_PARAM; 10913 } 10914 10915 rval64s[0] = rval64; 10916 BCM_IF_ERROR_RETURN 10917 (soc_reg32_get(unit, port_fc_reg, local_port, 0, &rval)); 10918 profile_index = 16 * soc_reg_field_get(unit, port_fc_reg, rval, 10919 PROFILE_INDEXf); 10920 10921 BCM_IF_ERROR_RETURN 10922 (soc_profile_reg_get(unit, _bcm_hx5_prio2cos_profile[unit], 10923 profile_index, 16, rval64s)); 10924 10925 uc_cos_bmp = soc_reg64_field32_get(unit, PRIO2COS_PROFILE_64r, rval64[fc_class], 10926 UC_COS_BMPf); 10927 mc_cos_bmp = soc_reg64_field32_get(unit, PRIO2COS_PROFILE_64r, rval64[fc_class], 10928 MC_COS_BMPf); 10929 10930 for (hw_cosq = 0; hw_cosq < si->port_num_uc_cosq[local_port]; hw_cosq++) { 10931 if (!(uc_cos_bmp & (1 << hw_cosq))) { 10932 continue; 10933 } 10934 BCM_IF_ERROR_RETURN 10935 (_bcm_hx5_cosq_port_cos_resolve(unit, local_port, hw_cosq, 10936 _BCM_HX5_COSQ_INDEX_STYLE_UCAST_QUEUE, 10937 &gport_list[count++])); 10938 } 10939 10940 for (hw_cosq = 0; hw_cosq < si->port_num_cosq[local_port]; hw_cosq++) { 10941 if (!(mc_cos_bmp & (1 << hw_cosq))) { 10942 continue; 10943 } 10944 BCM_IF_ERROR_RETURN 10945 (_bcm_hx5_cosq_port_cos_resolve(unit, local_port, hw_cosq, 10946 _BCM_HX5_COSQ_INDEX_STYLE_MCAST_QUEUE, 10947 &gport_list[count++])); 10948 } 10949 10950 if (count == 0) { 10951 return BCM_E_NOT_FOUND; 10952 } 10953 *gport_count = count; 10954 10955 return BCM_E_NONE; 10956 } 10957 10958 /* 10959 * Function: 10960 * _bcm_hx5_cosq_port_fc_profile_set 10961 * Purpose: 10962 * Set PFC/SAFC Prio 2 Cos Map and set the profile index for the Port 10963 * Parameters: 10964 * unit - (IN) unit number 10965 * port - (IN) GPORT identifier 10966 * fc_class - (IN) Input Class 10967 * uc_cos_bmp - (IN) UC Cos bitmap array 10968 * mc_cos_bmp - (IN) MC Cos bitmap array 10969 * num_class - (IN) Number of input class 10970 * Returns: 10971 * BCM_E_XXX 10972 */ 10973 STATIC int 10974 _bcm_hx5_cosq_port_fc_profile_set(int unit, bcm_port_t local_port, 10975 int *fc_class, uint32 *uc_cos_bmp, uint32 *mc_cos_bmp, 10976 int num_class) 10977 { 10978 uint32 profile_index, old_profile_index; 10979 uint32 rval; 10980 uint64 rval64[16], *rval64s[1]; 10981 static const soc_reg_t port_fc_reg = PORT_LLFC_CFGr; 10982 int entry, cur_class; 10983 uint32 cur_uc_bmp, cur_mc_bmp; 10984 10985 if ((fc_class == NULL) || 10986 (uc_cos_bmp == NULL) || 10987 (mc_cos_bmp == NULL)) { 10988 return BCM_E_PARAM; 10989 } 10990 10991 rval64s[0] = rval64; 10992 BCM_IF_ERROR_RETURN 10993 (soc_reg32_get(unit, port_fc_reg, local_port, 0, &rval)); 10994 10995 old_profile_index = 16 * soc_reg_field_get(unit, port_fc_reg, rval, 10996 PROFILE_INDEXf); 10997 10998 BCM_IF_ERROR_RETURN 10999 (soc_profile_reg_get(unit, _bcm_hx5_prio2cos_profile[unit], 11000 old_profile_index, 16, rval64s)); 11001 11002 for (entry = 0; entry < num_class; entry++) { 11003 cur_class = fc_class[entry]; 11004 cur_uc_bmp = uc_cos_bmp[entry]; 11005 cur_mc_bmp = mc_cos_bmp[entry]; 11006 soc_reg64_field32_set(unit, PRIO2COS_PROFILE_64r, &rval64[cur_class], 11007 UC_COS_BMPf, cur_uc_bmp); 11008 soc_reg64_field32_set(unit, PRIO2COS_PROFILE_64r, &rval64[cur_class], 11009 MC_COS_BMPf, cur_mc_bmp); 11010 11011 } 11012 11013 BCM_IF_ERROR_RETURN 11014 (soc_profile_reg_add(unit, _bcm_hx5_prio2cos_profile[unit], rval64s, 11015 16, &profile_index)); 11016 11017 soc_reg_field_set(unit, port_fc_reg, &rval, PROFILE_INDEXf, 11018 profile_index / 16); 11019 11020 BCM_IF_ERROR_RETURN 11021 (soc_profile_reg_delete(unit, _bcm_hx5_prio2cos_profile[unit], 11022 old_profile_index)); 11023 11024 BCM_IF_ERROR_RETURN 11025 (soc_reg32_set(unit, port_fc_reg, local_port, 0, rval)); 11026 11027 return BCM_E_NONE; 11028 } 11029 11030 /* 11031 * Function: 11032 * _bcm_hx5_fc_status_map_gport 11033 * Purpose: 11034 * Set mapping in PFC/SAFC for gport, and update 11035 * uc_cos_bmp/mc_cos_bmp with gport cosq. 11036 * Parameters: 11037 * unit - (IN) unit number 11038 * port - (IN) port number 11039 * gport - (IN) gport to be mapped 11040 * uc_cos_map - (OUT) unicast hw_cosq of gport 11041 * mc_cos_map - (OUT) multicast hw_cosq of gport 11042 * Returns: 11043 * BCM_E_XXX 11044 */ 11045 STATIC int 11046 _bcm_hx5_fc_status_map_gport(int unit, bcm_port_t port, 11047 bcm_gport_t gport, uint32 *uc_cos_bmp, uint32 *mc_cos_bmp) 11048 { 11049 _bcm_hx5_cosq_node_t *node = NULL; 11050 bcm_port_t local_port = -1; 11051 bcm_cos_queue_t cosq = -1; 11052 soc_info_t *si = &SOC_INFO(unit); 11053 11054 BCM_IF_ERROR_RETURN 11055 (_bcm_hx5_cosq_node_get(unit, gport, NULL, &local_port, NULL, &node)); 11056 11057 if (node == NULL) { 11058 return BCM_E_PARAM; 11059 } 11060 if (local_port < 0) { 11061 return BCM_E_PARAM; 11062 } 11063 if (local_port != port) { 11064 return BCM_E_PARAM; 11065 } 11066 11067 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 11068 cosq = node->hw_index - si->port_uc_cosq_base[local_port]; 11069 *uc_cos_bmp |= 1 << cosq; 11070 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 11071 cosq = node->hw_index - si->port_cosq_base[local_port]; 11072 *mc_cos_bmp |= 1 << cosq; 11073 } 11074 11075 return BCM_E_NONE; 11076 } 11077 11078 /* 11079 * Function: 11080 * _bcm_hx5_pfc_class_mapping_check 11081 * Purpose: 11082 * Validate param of bcm_cosq_pfc_class_mapping_t. 11083 * Parameters: 11084 * unit - (IN) unit number 11085 * port - (IN) port number 11086 * array_count - (IN) count of mapping array 11087 * mapping_array - (IN) mapping array list 11088 * Returns: 11089 * BCM_E_XXX 11090 */ 11091 STATIC int 11092 _bcm_hx5_pfc_class_mapping_check(int unit, 11093 bcm_gport_t port, 11094 int array_count, 11095 bcm_cosq_pfc_class_mapping_t *mapping_array) 11096 { 11097 int count, index, cur_class; 11098 bcm_port_t local_port = -1, resolved_port; 11099 bcm_gport_t cur_gport = 0; 11100 11101 if (mapping_array == NULL) { 11102 return BCM_E_PARAM; 11103 } 11104 11105 BCM_IF_ERROR_RETURN 11106 (_bcm_hx5_cosq_localport_resolve(unit, port, &local_port)); 11107 if (local_port < 0) { 11108 return BCM_E_PORT; 11109 } 11110 if (IS_CPU_PORT(unit, local_port)) { 11111 return BCM_E_PARAM; 11112 } 11113 11114 for (count = 0; count < array_count; count++) { 11115 cur_class = mapping_array[count].class_id; 11116 if ((cur_class < 0) || (cur_class >= _BCM_HX5_NUM_PFC_CLASS)) { 11117 return BCM_E_PARAM; 11118 } 11119 11120 for (index = 0; index < BCM_COSQ_PFC_GPORT_COUNT; index++) { 11121 cur_gport = mapping_array[count].gport_list[index]; 11122 if (cur_gport == BCM_GPORT_INVALID) { 11123 break; 11124 } 11125 if (BCM_GPORT_IS_SET(cur_gport)) { 11126 if (!((BCM_GPORT_IS_UCAST_QUEUE_GROUP(cur_gport)) || 11127 (BCM_GPORT_IS_MCAST_QUEUE_GROUP(cur_gport)))) { 11128 return BCM_E_PARAM; 11129 } 11130 BCM_IF_ERROR_RETURN(_bcm_hx5_cosq_node_get(unit, cur_gport, 11131 NULL, &resolved_port, NULL, NULL)); 11132 if (resolved_port != local_port) { 11133 return BCM_E_PARAM; 11134 } 11135 } else { 11136 return BCM_E_PARAM; 11137 } 11138 } 11139 } 11140 11141 return BCM_E_NONE; 11142 } 11143 11144 /* 11145 * Function: 11146 * bcm_hx5_cosq_pfc_class_mapping_set 11147 * Purpose: 11148 * Set PFC mapping for port. 11149 * PFC class is mapped to cosq or scheduler node gports. 11150 * Parameters: 11151 * unit - (IN) unit number 11152 * port - (IN) port number 11153 * array_count - (IN) count of mapping 11154 * mapping_array - (IN) mappings 11155 * Returns: 11156 * BCM_E_XXX 11157 */ 11158 int 11159 bcm_hx5_cosq_pfc_class_mapping_set(int unit, bcm_gport_t port, 11160 int array_count, 11161 bcm_cosq_pfc_class_mapping_t *mapping_array) 11162 { 11163 int index, count; 11164 int cur_class = 0; 11165 int pfc_class[_BCM_HX5_NUM_PFC_CLASS]; 11166 bcm_gport_t cur_gport = 0; 11167 uint32 uc_cos_bmp[_BCM_HX5_NUM_PFC_CLASS] = {0}; 11168 uint32 mc_cos_bmp[_BCM_HX5_NUM_PFC_CLASS] = {0}; 11169 bcm_port_t local_port = -1; 11170 11171 if ((array_count < 0) || (array_count > _BCM_HX5_NUM_PFC_CLASS)) { 11172 return BCM_E_PARAM; 11173 } 11174 if (mapping_array == NULL) { 11175 return BCM_E_PARAM; 11176 } 11177 BCM_IF_ERROR_RETURN 11178 (_bcm_hx5_pfc_class_mapping_check(unit, port, 11179 array_count, mapping_array)); 11180 11181 BCM_IF_ERROR_RETURN 11182 (_bcm_hx5_cosq_localport_resolve(unit, port, &local_port)); 11183 11184 for (count = 0; count < array_count; count++) { 11185 cur_class = mapping_array[count].class_id; 11186 uc_cos_bmp[cur_class] = 0; 11187 mc_cos_bmp[cur_class] = 0; 11188 11189 for (index = 0; index < BCM_COSQ_PFC_GPORT_COUNT; index++) { 11190 cur_gport = mapping_array[count].gport_list[index]; 11191 if (cur_gport == BCM_GPORT_INVALID) { 11192 break; 11193 } 11194 11195 BCM_IF_ERROR_RETURN 11196 (_bcm_hx5_fc_status_map_gport(unit, local_port, cur_gport, 11197 &uc_cos_bmp[cur_class], 11198 &mc_cos_bmp[cur_class])); 11199 } 11200 } 11201 11202 for (index = 0; index < _BCM_HX5_NUM_PFC_CLASS; index++) { 11203 pfc_class[index] = index; 11204 } 11205 BCM_IF_ERROR_RETURN 11206 (_bcm_hx5_cosq_port_fc_profile_set(unit, local_port, pfc_class, 11207 uc_cos_bmp, mc_cos_bmp, 11208 _BCM_HX5_NUM_PFC_CLASS)); 11209 11210 return BCM_E_NONE; 11211 } 11212 11213 /* 11214 * Function: 11215 * bcm_hx5_cosq_pfc_class_mapping_get 11216 * Purpose: 11217 * Get PFC mapping for port. 11218 * Retrieves cosq or scheduler node gports 11219 * associated to PFC classes. 11220 * Parameters: 11221 * unit - (IN) unit number 11222 * port - (IN) port number 11223 * array_max - (IN) max retrieve count 11224 * mapping_array - (OUT) mappings 11225 * array_count - (OUT) retrieved mapping count 11226 * Returns: 11227 * BCM_E_XXX 11228 */ 11229 int 11230 bcm_hx5_cosq_pfc_class_mapping_get(int unit, bcm_gport_t port, 11231 int array_max, 11232 bcm_cosq_pfc_class_mapping_t *mapping_array, 11233 int *array_count) 11234 { 11235 int rv = 0; 11236 int cur_class = 0; 11237 int actual_gport_count, class_count = 0; 11238 bcm_port_t local_port = -1; 11239 11240 BCM_IF_ERROR_RETURN 11241 (_bcm_hx5_cosq_localport_resolve(unit, port, &local_port)); 11242 11243 if (local_port < 0) { 11244 return BCM_E_PORT; 11245 } 11246 if (IS_CPU_PORT(unit, local_port)) { 11247 return BCM_E_PARAM; 11248 } 11249 if (((mapping_array == NULL) && (array_max > 0)) || 11250 ((mapping_array != NULL) && (array_max <= 0)) || 11251 (array_count == NULL)) { 11252 return BCM_E_PARAM; 11253 } 11254 if (array_max <= 0) { 11255 *array_count = _BCM_HX5_NUM_PFC_CLASS; 11256 return BCM_E_NONE; 11257 } 11258 11259 for (cur_class = 0; cur_class < _BCM_HX5_NUM_PFC_CLASS; cur_class++) { 11260 actual_gport_count = 0; 11261 rv = _bcm_hx5_cosq_port_fc_get(unit, local_port, cur_class, 11262 mapping_array[class_count].gport_list, 11263 &actual_gport_count); 11264 11265 if (rv == BCM_E_NONE) { 11266 mapping_array[class_count].class_id = cur_class; 11267 if (actual_gport_count < BCM_COSQ_PFC_GPORT_COUNT) { 11268 mapping_array[class_count].gport_list[actual_gport_count] = 11269 BCM_GPORT_INVALID; 11270 } 11271 class_count++; 11272 } else if (rv != BCM_E_NOT_FOUND) { 11273 return rv; 11274 } 11275 11276 if ((class_count == array_max) && (array_max > 0)) { 11277 break; 11278 } 11279 } 11280 11281 *array_count = class_count; 11282 if (class_count == 0) { 11283 return BCM_E_NOT_FOUND; 11284 } 11285 11286 return BCM_E_NONE; 11287 } 11288 11289 /* 11290 * Function: 11291 * bcm_hx5_cosq_safc_class_mapping_set 11292 * Purpose: 11293 * Set SAFC mapping for port. 11294 * SAFC class is mapped to cosq or scheduler node gports. 11295 * Parameters: 11296 * unit - (IN) unit number 11297 * port - (IN) port number 11298 * array_count - (IN) count of mapping 11299 * mapping_array - (IN) mappings 11300 * Returns: 11301 * BCM_E_XXX 11302 */ 11303 int 11304 bcm_hx5_cosq_safc_class_mapping_set(int unit, bcm_gport_t port, int array_count, 11305 bcm_cosq_safc_class_mapping_t *mapping_array) 11306 { 11307 int index, count; 11308 int cur_class = 0; 11309 int safc_class[_BCM_HX5_NUM_SAFC_CLASS]; 11310 bcm_gport_t cur_gport = 0; 11311 uint32 uc_cos_bmp[_BCM_HX5_NUM_SAFC_CLASS] = {0}; 11312 uint32 mc_cos_bmp[_BCM_HX5_NUM_SAFC_CLASS] = {0}; 11313 bcm_port_t local_port = -1; 11314 11315 BCM_IF_ERROR_RETURN 11316 (_bcm_hx5_cosq_localport_resolve(unit, port, &local_port)); 11317 11318 if (local_port < 0) { 11319 return BCM_E_PORT; 11320 } 11321 11322 if (IS_CPU_PORT(unit, local_port)) { 11323 return BCM_E_PARAM; 11324 } 11325 11326 if ((array_count < 0) || (array_count > _BCM_HX5_NUM_SAFC_CLASS)) { 11327 return BCM_E_PARAM; 11328 } 11329 11330 if (mapping_array == NULL) { 11331 return BCM_E_PARAM; 11332 } 11333 11334 for (count = 0; count < array_count; count++) { 11335 cur_class = mapping_array[count].class_id; 11336 if ((cur_class < 0) || (cur_class >= _BCM_HX5_NUM_SAFC_CLASS)) { 11337 return BCM_E_PARAM; 11338 } else { 11339 uc_cos_bmp[cur_class] = 0; 11340 mc_cos_bmp[cur_class] = 0; 11341 } 11342 11343 for (index = 0; index < BCM_COSQ_SAFC_GPORT_COUNT; index++) { 11344 cur_gport = mapping_array[count].gport_list[index]; 11345 if (cur_gport == BCM_GPORT_INVALID) { 11346 break; 11347 } 11348 11349 if ((BCM_GPORT_IS_UCAST_QUEUE_GROUP(cur_gport)) || 11350 (BCM_GPORT_IS_MCAST_QUEUE_GROUP(cur_gport))) { 11351 BCM_IF_ERROR_RETURN 11352 (_bcm_hx5_fc_status_map_gport(unit, local_port, cur_gport, 11353 &uc_cos_bmp[cur_class], 11354 &mc_cos_bmp[cur_class])); 11355 } else { 11356 return BCM_E_PARAM; 11357 } 11358 } 11359 } 11360 11361 for (index = 0; index < _BCM_HX5_NUM_SAFC_CLASS; index++) { 11362 safc_class[index] = index; 11363 } 11364 11365 BCM_IF_ERROR_RETURN 11366 (_bcm_hx5_cosq_port_fc_profile_set(unit, local_port, safc_class, 11367 uc_cos_bmp, mc_cos_bmp, 11368 _BCM_HX5_NUM_SAFC_CLASS)); 11369 11370 return BCM_E_NONE; 11371 } 11372 11373 /* 11374 * Function: 11375 * bcm_hx5_cosq_safc_class_mapping_get 11376 * Purpose: 11377 * Get SAFC mapping for port. 11378 * Retrieves cosq or scheduler node gports associated to SAFC classes. 11379 * Parameters: 11380 * unit - (IN) unit number 11381 * port - (IN) port number 11382 * array_max - (IN) max retrieve count 11383 * mapping_array - (OUT) mappings 11384 * array_count - (OUT) retrieved mapping count 11385 * Returns: 11386 * BCM_E_XXX 11387 */ 11388 int 11389 bcm_hx5_cosq_safc_class_mapping_get(int unit, bcm_gport_t port, int array_max, 11390 bcm_cosq_safc_class_mapping_t *mapping_array, 11391 int *array_count) 11392 { 11393 int rv = 0; 11394 int cur_class = 0; 11395 int actual_gport_count, class_count = 0; 11396 bcm_port_t local_port = -1; 11397 11398 BCM_IF_ERROR_RETURN 11399 (_bcm_hx5_cosq_localport_resolve(unit, port, &local_port)); 11400 11401 if (local_port < 0) { 11402 return BCM_E_PORT; 11403 } 11404 11405 if (IS_CPU_PORT(unit, local_port)) { 11406 return BCM_E_PARAM; 11407 } 11408 11409 if (((mapping_array == NULL) && (array_max > 0)) || 11410 ((mapping_array != NULL) && (array_max <= 0)) || 11411 (array_count == NULL)) { 11412 return BCM_E_PARAM; 11413 } 11414 11415 if (array_max <= 0) { 11416 *array_count = _BCM_HX5_NUM_SAFC_CLASS; 11417 return BCM_E_NONE; 11418 } 11419 11420 for (cur_class = 0; cur_class < _BCM_HX5_NUM_SAFC_CLASS; cur_class++) { 11421 actual_gport_count = 0; 11422 rv = _bcm_hx5_cosq_port_fc_get(unit, local_port, cur_class, 11423 mapping_array[class_count].gport_list, 11424 &actual_gport_count); 11425 11426 if (rv == BCM_E_NONE) { 11427 mapping_array[class_count].class_id = cur_class; 11428 if (actual_gport_count < BCM_COSQ_SAFC_GPORT_COUNT) { 11429 mapping_array[class_count].gport_list[actual_gport_count] = 11430 BCM_GPORT_INVALID; 11431 } 11432 class_count++; 11433 } else if (rv != BCM_E_NOT_FOUND) { 11434 return rv; 11435 } 11436 11437 if (class_count == array_max) { 11438 break; 11439 } 11440 } 11441 11442 *array_count = class_count; 11443 if (class_count == 0) { 11444 return BCM_E_NOT_FOUND; 11445 } 11446 11447 return BCM_E_NONE; 11448 } 11449 /* 11450 * Function: 11451 * bcm_hx5_cosq_buffer_id_multi_get 11452 * Purpose: 11453 * Get mutliple buffer ids associated with a specified port. 11454 * Parameters: 11455 * unit - (IN) BCM device number. 11456 * gport - (IN) Port 11457 * cosq - (IN) Reserved field 11458 * direction - (IN) Specify ingress or egress direction 11459 * array_max - (IN) number of entries to be retrieved 11460 * buf_id_array - (OUT) Buffer id array 11461 * array_count - (OUT) Actural buffer id count in buf_id_array 11462 * Returns: 11463 * BCM_E_XXX 11464 */ 11465 int 11466 bcm_hx5_cosq_buffer_id_multi_get(int unit, bcm_gport_t gport, 11467 bcm_cos_queue_t cosq, bcm_cosq_dir_t direction, 11468 int array_max, bcm_cosq_buffer_id_t *buf_id_array, 11469 int *array_count) 11470 { 11471 bcm_port_t local_port; 11472 int i; 11473 11474 if ((direction < bcmCosqIngress) || 11475 (direction >= bcmCosqDirectionMaxCount)) { 11476 return BCM_E_PARAM; 11477 } 11478 11479 if (!BCM_GPORT_IS_SET(gport)) { 11480 local_port = gport; 11481 } else if (BCM_GPORT_IS_LOCAL(gport)) { 11482 local_port = BCM_GPORT_LOCAL_GET(gport); 11483 } else if (BCM_GPORT_IS_MODPORT(gport)) { 11484 BCM_IF_ERROR_RETURN(bcm_esw_port_local_get(unit, gport, &local_port)); 11485 } else if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 11486 int idx; 11487 BCM_IF_ERROR_RETURN(_bcm_hx5_cosq_index_resolve(unit, gport, cosq, 11488 _BCM_HX5_COSQ_INDEX_STYLE_UCAST_QUEUE, &local_port, &idx, NULL)); 11489 } else { 11490 return BCM_E_PARAM; 11491 } 11492 11493 if (!SOC_PORT_VALID(unit, local_port)) { 11494 return BCM_E_PORT; 11495 } 11496 11497 if (array_max >= 1) { 11498 *array_count = 1; 11499 } else if (array_max == 0){ 11500 *array_count = array_max; 11501 } else { 11502 return BCM_E_PARAM; 11503 } 11504 11505 for (i = 0; i < *array_count; i++) { 11506 buf_id_array[i] = 0; 11507 } 11508 11509 for (i = *array_count; i < array_max; i++) { 11510 buf_id_array[i] = BCM_COSQ_INVALID_BUF_ID; 11511 } 11512 11513 return BCM_E_NONE; 11514 } 11515 11516 #ifdef BCM_WARM_BOOT_SUPPORT 11517 #define BCM_WB_VERSION_1_0 SOC_SCACHE_VERSION(1,0) 11518 #define BCM_WB_DEFAULT_VERSION BCM_WB_VERSION_1_0 11519 STATIC int 11520 _bcm_hx5_cosq_wb_alloc(int unit) 11521 { 11522 soc_scache_handle_t scache_handle; 11523 uint8 *scache_ptr = NULL; 11524 int rv, alloc_size = 0, max_size = (4096 * 7); 11525 _bcm_hx5_cosq_cpu_port_info_t *cpu_port_info = NULL; 11526 11527 /* 11528 * Sync _bcm_hx5_cosq_cpu_port_info structure 11529 */ 11530 cpu_port_info = _bcm_hx5_cosq_cpu_port_info[unit]; 11531 if (cpu_port_info == NULL) { 11532 return BCM_E_INIT; 11533 } 11534 alloc_size += sizeof(_bcm_hx5_cosq_cpu_port_info_t); 11535 11536 /* 11537 * Sync the ref_count of IFP_COS_MAPm/COS_MAPm 11538 */ 11539 alloc_size += (SOC_MEM_SIZE(unit, IFP_COS_MAPm) / _HX5_MMU_NUM_INT_PRI) * 11540 sizeof(uint16); 11541 11542 /* 11543 * Sync _bcm_hx5_cosq_cpu_cosq_config_t structure for all CPU queues 11544 */ 11545 alloc_size += (SOC_HX5_NUM_CPU_QUEUES * 11546 sizeof(_bcm_hx5_cosq_cpu_cosq_config_t)); 11547 11548 /* 11549 * Sync num_cos value 11550 */ 11551 alloc_size += sizeof(int); 11552 11553 /* 11554 * Sync _soc_td3_mmu_traffic_ctrl_t 11555 */ 11556 BCM_IF_ERROR_RETURN(soc_td3_mmu_traffic_ctrl_size(unit, &alloc_size)); 11557 11558 /* 11559 * Sync _bcm_pfc_deadlock_control_t structure 11560 */ 11561 if (soc_feature(unit, soc_feature_pfc_deadlock)) { 11562 alloc_size += sizeof(_bcm_hx5_pfc_deadlock_control_t); 11563 } 11564 11565 /* 11566 * Sync _bcm_hx5_cosq_cpu_cosq_config_t structure for all CPU queues 11567 */ 11568 alloc_size += (_BCM_HX5_NUM_WRED_RESOLUTION_TABLE * 11569 sizeof(uint32)); 11570 11571 if (soc_feature(unit, soc_feature_mpls_ecn)) { 11572 uint32 scache_size = 0; 11573 BCM_IF_ERROR_RETURN( 11574 bcmi_xgs5_ecn_scache_size_get(unit, &scache_size)); 11575 alloc_size += scache_size; 11576 } 11577 11578 #if defined (BCM_TCB_SUPPORT) && defined (INCLUDE_TCB) 11579 if (soc_feature(unit, soc_feature_tcb)) { 11580 alloc_size += sizeof(uint16); 11581 } 11582 #else 11583 alloc_size += sizeof(uint16); 11584 #endif 11585 11586 /* Reserving some space scache for future usecase (max_size) */ 11587 if (alloc_size < max_size) { 11588 alloc_size = max_size; 11589 } else { 11590 /* Required size more than max size allocated for Cosq */ 11591 return BCM_E_INIT; 11592 } 11593 11594 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_COSQ, 0); 11595 11596 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, TRUE, alloc_size, 11597 &scache_ptr, BCM_WB_DEFAULT_VERSION, NULL); 11598 11599 if (rv == BCM_E_NOT_FOUND) { 11600 rv = BCM_E_NONE; 11601 } 11602 11603 return rv; 11604 } 11605 11606 int 11607 bcm_hx5_cosq_reinit(int unit) 11608 { 11609 soc_scache_handle_t scache_handle; 11610 uint8 *scache_ptr = NULL; 11611 int *int_scache_ptr = NULL; 11612 uint16 *u16_scache_ptr = NULL; 11613 uint32 *u32_scache_ptr = NULL; 11614 _bcm_hx5_cosq_cpu_port_info_t *cpu_port_info = NULL; 11615 int alloc_size = 0, pipe = -1, i, j; 11616 soc_profile_mem_t *profile_mem; 11617 soc_mem_t wred_config_mem = INVALIDm; 11618 int index, profile_index, resolution_index; 11619 int stable_size, rv, set_index, num; 11620 mmu_wred_config_entry_t qentry; 11621 uint32 entry[SOC_MAX_MEM_WORDS]; 11622 int phy_port, mmu_port; 11623 bcm_port_t port; 11624 static const soc_reg_t port_fc_reg = PORT_LLFC_CFGr; 11625 uint32 rval; 11626 _bcm_bst_device_handlers_t bst_callbks; 11627 _bcm_hx5_cosq_cpu_cosq_config_t *cpu_cosq_config_p; 11628 uint16 recovered_ver = 0; 11629 int index_min, index_max; 11630 _bcm_hx5_pfc_deadlock_control_t *pfc_deadlock_control = NULL; 11631 soc_info_t *si = &SOC_INFO(unit); 11632 11633 11634 SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size)); 11635 if ((stable_size == 0) || (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit))) { 11636 /* COSQ warmboot requires extended scache support i.e. level2 warmboot*/ 11637 return BCM_E_NONE; 11638 } 11639 11640 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_COSQ, 0); 11641 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 0, &scache_ptr, 11642 BCM_WB_DEFAULT_VERSION, &recovered_ver); 11643 if (BCM_FAILURE(rv)) { 11644 return rv; 11645 } 11646 11647 /* Restore _bcm_hx5_cosq_cpu_port_info structure */ 11648 cpu_port_info = _bcm_hx5_cosq_cpu_port_info[unit]; 11649 if (cpu_port_info == NULL) { 11650 return BCM_E_INIT; 11651 } 11652 alloc_size = sizeof(_bcm_hx5_cosq_cpu_port_info_t); 11653 sal_memcpy(cpu_port_info, scache_ptr, alloc_size); 11654 scache_ptr += alloc_size; 11655 11656 /* Update IFP_COS_MAP memory profile reference counter */ 11657 profile_mem = _bcm_hx5_ifp_cos_map_profile[unit]; 11658 num = SOC_MEM_SIZE(unit, IFP_COS_MAPm) / _HX5_MMU_NUM_INT_PRI; 11659 u16_scache_ptr = (uint16 *)scache_ptr; 11660 for (i = 0; i < num; i++) { 11661 for (j = 0; j < *u16_scache_ptr; j++) { 11662 SOC_IF_ERROR_RETURN( 11663 soc_profile_mem_reference(unit, profile_mem, 11664 i * _HX5_MMU_NUM_INT_PRI, 11665 _HX5_MMU_NUM_INT_PRI)); 11666 } 11667 u16_scache_ptr++; 11668 } 11669 scache_ptr = (uint8*)u16_scache_ptr; 11670 11671 /* Recover CPU queue config information from scache */ 11672 cpu_cosq_config_p = _bcm_hx5_cosq_cpu_cosq_config[unit][0]; 11673 if (cpu_cosq_config_p == NULL) { 11674 return BCM_E_INIT; 11675 } 11676 alloc_size = (SOC_HX5_NUM_CPU_QUEUES * 11677 sizeof(_bcm_hx5_cosq_cpu_cosq_config_t)); 11678 sal_memcpy(cpu_cosq_config_p, scache_ptr, alloc_size); 11679 scache_ptr += alloc_size; 11680 11681 /* Retriving num_cos value */ 11682 int_scache_ptr = (int *) scache_ptr; 11683 _BCM_HX5_NUM_COS(unit) = *int_scache_ptr++; 11684 scache_ptr = (uint8*) int_scache_ptr; 11685 11686 /* Update PRIO2COS_PROFILE register profile reference counter */ 11687 PBMP_PORT_ITER(unit, port) { 11688 BCM_IF_ERROR_RETURN 11689 (soc_reg32_get(unit, port_fc_reg, port, 0, &rval)); 11690 profile_index = 16 * soc_reg_field_get(unit, port_fc_reg, rval, 11691 PROFILE_INDEXf); 11692 SOC_IF_ERROR_RETURN 11693 (soc_profile_reg_reference(unit, _bcm_hx5_prio2cos_profile[unit], 11694 profile_index, 16)); 11695 } 11696 11697 /* Update PORT_COS_MAP memory profile reference counter */ 11698 profile_mem = _bcm_hx5_cos_map_profile[unit]; 11699 PBMP_ALL_ITER(unit, port) { 11700 SOC_IF_ERROR_RETURN 11701 (soc_mem_read(unit, COS_MAP_SELm, MEM_BLOCK_ALL, port, &entry)); 11702 set_index = soc_mem_field32_get(unit, COS_MAP_SELm, &entry, SELECTf); 11703 SOC_IF_ERROR_RETURN 11704 (soc_profile_mem_reference(unit, profile_mem, set_index * 16, 16)); 11705 } 11706 if (SOC_INFO(unit).cpu_hg_index != -1) { 11707 SOC_IF_ERROR_RETURN(soc_mem_read(unit, COS_MAP_SELm, MEM_BLOCK_ALL, 11708 SOC_INFO(unit).cpu_hg_index, &entry)); 11709 set_index = soc_mem_field32_get(unit, COS_MAP_SELm, &entry, SELECTf); 11710 SOC_IF_ERROR_RETURN 11711 (soc_profile_mem_reference(unit, profile_mem, set_index * 16, 16)); 11712 } 11713 11714 /* Update MMU_WRED_DROP_CURVE_PROFILE memory profile reference counter */ 11715 for (pipe = 0; pipe < NUM_PIPE(unit); pipe++) { 11716 wred_config_mem = SOC_MEM_UNIQUE_ACC(unit, MMU_WRED_CONFIGm)[pipe]; 11717 if (wred_config_mem == INVALIDm) { 11718 return BCM_E_PARAM; 11719 } 11720 index_min = soc_mem_index_min(unit, wred_config_mem); 11721 index_max = soc_mem_index_max(unit, wred_config_mem); 11722 for (index = index_min; index < index_max; index++) { 11723 BCM_IF_ERROR_RETURN 11724 (soc_mem_read(unit, wred_config_mem, 11725 MEM_BLOCK_ALL, index, &qentry)); 11726 profile_index = soc_mem_field32_get(unit, wred_config_mem, 11727 &qentry, PROFILE_INDEXf); 11728 BCM_IF_ERROR_RETURN 11729 (soc_profile_mem_reference(unit, _bcm_hx5_wred_profile[unit], 11730 profile_index, 1)); 11731 11732 if (soc_mem_field32_get(unit, wred_config_mem, &qentry, 11733 ECN_MARKING_ENf)) { 11734 resolution_index = soc_mem_field32_get( 11735 unit, wred_config_mem, &qentry, 11736 WRED_CONG_NOTIFICATION_RESOLUTION_TABLE_MARKING_INDEXf); 11737 } else { 11738 resolution_index = soc_mem_field32_get( 11739 unit, wred_config_mem, &qentry, 11740 WRED_CONG_NOTIFICATION_RESOLUTION_TABLE_DROPPING_INDEXf); 11741 } 11742 _bcm_hx5_wred_resolution_tbl[resolution_index] = 1; 11743 } 11744 } 11745 11746 /* Create gport tree */ 11747 _BCM_HX5_MMU_INFO(unit)->gport_tree_created = FALSE; 11748 PBMP_ALL_ITER(unit, port) { 11749 phy_port = si->port_l2p_mapping[port]; 11750 mmu_port = si->port_p2m_mapping[phy_port]; 11751 if (IS_LB_PORT(unit, port) || IS_CPU_PORT(unit, port) 11752 || IS_FAE_PORT(unit, port)) { 11753 continue; 11754 } 11755 if (_HX5_IS_ST_PORT(unit, mmu_port)) { 11756 BCM_IF_ERROR_RETURN 11757 (_bcm_hx5_cosq_st_gport_tree_create(unit, port)); 11758 } else { 11759 BCM_IF_ERROR_RETURN 11760 (_bcm_hx5_cosq_gport_tree_create(unit, port)); 11761 } 11762 } 11763 _BCM_HX5_MMU_INFO(unit)->gport_tree_created = TRUE; 11764 11765 /* BST reinit */ 11766 sal_memset(&bst_callbks, 0, sizeof(_bcm_bst_device_handlers_t)); 11767 bst_callbks.resolve_index = &_bcm_hx5_bst_index_resolve; 11768 bst_callbks.reverse_resolve_index = NULL; 11769 BCM_IF_ERROR_RETURN(_bcm_bst_attach(unit, &bst_callbks)); 11770 11771 /* Recover _soc_td3_mmu_traffic_ctrl_t */ 11772 BCM_IF_ERROR_RETURN(soc_td3_mmu_traffic_ctrl_wb_restore(unit, &scache_ptr)); 11773 11774 11775 /* PFC Deadlock recovery should be initialized 11776 irrespective of scache version to handle 11777 upgrades */ 11778 if (soc_feature(unit, soc_feature_pfc_deadlock)) { 11779 BCM_IF_ERROR_RETURN(_bcm_pfc_deadlock_init(unit)); 11780 } 11781 11782 /* Recover PFC Deadlock recovery information from scache */ 11783 if (soc_feature(unit, soc_feature_pfc_deadlock)) { 11784 pfc_deadlock_control = _BCM_HX5_UNIT_PFC_DEADLOCK_CONTROL(unit); 11785 if (pfc_deadlock_control == NULL) { 11786 return BCM_E_INIT; 11787 } 11788 alloc_size = sizeof(_bcm_hx5_pfc_deadlock_control_t); 11789 sal_memcpy(pfc_deadlock_control, scache_ptr, alloc_size); 11790 scache_ptr += alloc_size; 11791 /* Re-set the Hardware Registers/Memory info */ 11792 BCM_IF_ERROR_RETURN(_bcm_hx5_pfc_deadlock_hw_res_init(unit)); 11793 BCM_IF_ERROR_RETURN(_bcm_hx5_pfc_deadlock_reinit(unit)); 11794 BCM_IF_ERROR_RETURN(_bcm_hx5_pfc_deadlock_recovery_reset(unit)); 11795 pfc_deadlock_control->cosq_inv_mapping_get = _bcm_hx5_cosq_inv_mapping_get; 11796 } 11797 11798 #if defined (BCM_TCB_SUPPORT) && defined (INCLUDE_TCB) 11799 if (soc_feature(unit, soc_feature_tcb)){ 11800 _bcm_cosq_tcb_unit_ctrl_t *tcb_unit_info; 11801 BCM_IF_ERROR_RETURN(bcm_hx5_cosq_tcb_reinit(unit)); 11802 11803 tcb_unit_info = TCB_UNIT_CONTROL(unit); 11804 TCB_INIT(unit); 11805 11806 alloc_size = sizeof(uint16); 11807 sal_memcpy(&tcb_unit_info->tcb_config_init_bmp, scache_ptr, alloc_size); 11808 scache_ptr += alloc_size; 11809 } 11810 #else 11811 scache_ptr += sizeof(uint16); 11812 #endif 11813 11814 /* Retriving _bcm_hx5_wred_resolution_tbl value */ 11815 u32_scache_ptr = (uint32 *) scache_ptr; 11816 for (i = 0; i < _BCM_HX5_NUM_WRED_RESOLUTION_TABLE; i++) { 11817 _bcm_hx5_wred_resolution_tbl[i] = *u32_scache_ptr++; 11818 } 11819 11820 return BCM_E_NONE; 11821 } 11822 11823 int 11824 bcm_hx5_cosq_sync(int unit) 11825 { 11826 soc_scache_handle_t scache_handle; 11827 uint8 *scache_ptr; 11828 int *int_scache_ptr; 11829 _bcm_hx5_cosq_cpu_port_info_t *cpu_port_info = NULL; 11830 int size = 0; 11831 _bcm_hx5_cosq_cpu_cosq_config_t **cpu_cosq_config_p; 11832 int ii; 11833 int rv = BCM_E_NONE, ref_count; 11834 uint16 *u16_scache_ptr; 11835 uint32 *u32_scache_ptr; 11836 _bcm_hx5_pfc_deadlock_control_t *pfc_deadlock_control = NULL; 11837 11838 cpu_port_info = _bcm_hx5_cosq_cpu_port_info[unit]; 11839 if (cpu_port_info == NULL) { 11840 return BCM_E_INIT; 11841 } 11842 11843 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_COSQ, 0); 11844 BCM_IF_ERROR_RETURN 11845 (_bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 0, 11846 &scache_ptr, BCM_WB_DEFAULT_VERSION, NULL)); 11847 11848 /* Cache _bcm_hx5_cosq_cpu_port_info_t structure */ 11849 size = sizeof(_bcm_hx5_cosq_cpu_port_info_t); 11850 sal_memcpy(scache_ptr, cpu_port_info, size); 11851 scache_ptr += size/sizeof(uint8); 11852 11853 /* Cache _bcm_hx5_ifp_cos_map_profile reference count */ 11854 u16_scache_ptr = (uint16 *)scache_ptr; 11855 for (ii = 0; 11856 ii < (SOC_MEM_SIZE(unit, IFP_COS_MAPm) / _HX5_MMU_NUM_INT_PRI); 11857 ii++) { 11858 rv = soc_profile_mem_ref_count_get(unit, 11859 _bcm_hx5_ifp_cos_map_profile[unit], 11860 ii * _HX5_MMU_NUM_INT_PRI, 11861 &ref_count); 11862 if (!(rv == SOC_E_NOT_FOUND || rv == SOC_E_NONE)) { 11863 return rv; 11864 } 11865 *u16_scache_ptr++ = (uint16)(ref_count & 0xffff); 11866 } 11867 scache_ptr = (uint8*) u16_scache_ptr; 11868 11869 /* Sync CPU Queue info */ 11870 cpu_cosq_config_p = _bcm_hx5_cosq_cpu_cosq_config[unit]; 11871 size = (SOC_HX5_NUM_CPU_QUEUES * sizeof(_bcm_hx5_cosq_cpu_cosq_config_t)); 11872 sal_memcpy(scache_ptr, *cpu_cosq_config_p, size); 11873 scache_ptr += (size / sizeof(uint8)); 11874 11875 /* Sync num_cos value */ 11876 int_scache_ptr = (int*) scache_ptr; 11877 *int_scache_ptr++ = _BCM_HX5_NUM_COS(unit); 11878 scache_ptr = (uint8 *)int_scache_ptr; 11879 11880 /* Sync _soc_td3_mmu_traffic_ctrl_t */ 11881 BCM_IF_ERROR_RETURN(soc_td3_mmu_traffic_ctrl_wb_sync(unit, &scache_ptr)); 11882 11883 11884 /* Sync PFC Deadlock Control info */ 11885 if (soc_feature(unit, soc_feature_pfc_deadlock)) { 11886 pfc_deadlock_control = _BCM_HX5_UNIT_PFC_DEADLOCK_CONTROL(unit); 11887 if (pfc_deadlock_control == NULL) { 11888 return BCM_E_INIT; 11889 } 11890 size = sizeof(_bcm_hx5_pfc_deadlock_control_t); 11891 sal_memcpy(scache_ptr, pfc_deadlock_control, size); 11892 scache_ptr += (size / sizeof(uint8)); 11893 } 11894 11895 11896 #if defined (BCM_TCB_SUPPORT) && defined (INCLUDE_TCB) 11897 if (soc_feature(unit, soc_feature_tcb)){ 11898 _bcm_cosq_tcb_unit_ctrl_t *tcb_unit_info; 11899 tcb_unit_info = TCB_UNIT_CONTROL(unit); 11900 TCB_INIT(unit); 11901 11902 u16_scache_ptr = (uint16*) scache_ptr; 11903 size = sizeof(uint16); 11904 sal_memcpy(u16_scache_ptr, &tcb_unit_info->tcb_config_init_bmp, size); 11905 u16_scache_ptr ++; 11906 } 11907 #else 11908 u16_scache_ptr = (uint16*) scache_ptr; 11909 u16_scache_ptr ++; 11910 #endif 11911 u32_scache_ptr = (uint32*) u16_scache_ptr; 11912 11913 for (ii = 0; ii < _BCM_HX5_NUM_WRED_RESOLUTION_TABLE; ii++) { 11914 *u32_scache_ptr++ = _bcm_hx5_wred_resolution_tbl[ii]; 11915 } 11916 11917 scache_ptr = (uint8 *)u32_scache_ptr; 11918 11919 return BCM_E_NONE; 11920 } 11921 #endif 11922 11923 11924 /* 11925 * Function: 11926 * bcm_hx5_cosq_init 11927 * Purpose: 11928 * Initialize (clear) all COS schedule/mapping state. 11929 * Parameters: 11930 * unit - (IN) unit number 11931 * Returns: 11932 * BCM_E_XXX 11933 */ 11934 int 11935 bcm_hx5_cosq_init(int unit) 11936 { 11937 int i, alloc_size = 0, numq = 0, pipe = -1; 11938 int rv = BCM_E_NONE; 11939 soc_mem_t mem = INVALIDm; 11940 soc_reg_t reg = INVALIDr; 11941 int entry_words[9]; 11942 int phy_port, mmu_port; 11943 int min_index, max_index; 11944 bcm_port_t port; 11945 uint64 rval64s[16], *prval64s[1]; 11946 _bcm_hx5_cosq_cpu_cosq_config_t *cpu_cosq_config_p = NULL; 11947 soc_mem_t wred_config_mem = INVALIDm; 11948 _bcm_bst_device_handlers_t bst_callbks; 11949 soc_info_t *si = &SOC_INFO(unit); 11950 11951 static soc_mem_t wred_mems[9] = { 11952 MMU_WRED_DROP_CURVE_PROFILE_0m, MMU_WRED_DROP_CURVE_PROFILE_1m, 11953 MMU_WRED_DROP_CURVE_PROFILE_2m, MMU_WRED_DROP_CURVE_PROFILE_3m, 11954 MMU_WRED_DROP_CURVE_PROFILE_4m, MMU_WRED_DROP_CURVE_PROFILE_5m, 11955 MMU_WRED_DROP_CURVE_PROFILE_6m, MMU_WRED_DROP_CURVE_PROFILE_7m, 11956 MMU_WRED_DROP_CURVE_PROFILE_8m 11957 }; 11958 11959 mmu_wred_drop_curve_profile_0_entry_t entry_tcp_green; 11960 mmu_wred_drop_curve_profile_1_entry_t entry_tcp_yellow; 11961 mmu_wred_drop_curve_profile_2_entry_t entry_tcp_red; 11962 mmu_wred_drop_curve_profile_3_entry_t entry_nontcp_green; 11963 mmu_wred_drop_curve_profile_4_entry_t entry_nontcp_yellow; 11964 mmu_wred_drop_curve_profile_5_entry_t entry_nontcp_red; 11965 mmu_wred_drop_curve_profile_6_entry_t entry_ecn_green; 11966 mmu_wred_drop_curve_profile_7_entry_t entry_ecn_yellow; 11967 mmu_wred_drop_curve_profile_8_entry_t entry_ecn_red; 11968 void *entries[9]; 11969 uint32 profile_index; 11970 int ii, wred_prof_count; 11971 11972 numq = soc_property_get(unit, spn_BCM_NUM_COS, _BCM_HX5_COS_DEFAULT); 11973 if (numq < 1) { 11974 numq = 1; 11975 } else if (numq > _BCM_HX5_COS_DEFAULT) { 11976 numq = _BCM_HX5_COS_DEFAULT; 11977 } 11978 11979 /* Create Port Information structure */ 11980 alloc_size = sizeof(_bcm_hx5_cosq_port_info_t) * (_BCM_HX5_NUM_PORTS); 11981 if (_bcm_hx5_cosq_port_info[unit] == NULL) { 11982 _bcm_hx5_cosq_port_info[unit] = 11983 sal_alloc(alloc_size, "_bcm_hx5_cosq_port_info"); 11984 if (_bcm_hx5_cosq_port_info[unit] == NULL) { 11985 return BCM_E_MEMORY; 11986 } 11987 } 11988 sal_memset(_bcm_hx5_cosq_port_info[unit], 0, alloc_size); 11989 11990 /* Create HG Port Information structure */ 11991 alloc_size = sizeof(_bcm_hx5_cosq_st_port_info_t) * (_BCM_HX5_NUM_ST_PORTS); 11992 if (_bcm_hx5_cosq_st_port_info[unit] == NULL) { 11993 _bcm_hx5_cosq_st_port_info[unit] = 11994 sal_alloc(alloc_size, "_bcm_hx5_cosq_st_port_info"); 11995 if (_bcm_hx5_cosq_st_port_info[unit] == NULL) { 11996 return BCM_E_MEMORY; 11997 } 11998 } 11999 sal_memset(_bcm_hx5_cosq_st_port_info[unit], 0, alloc_size); 12000 12001 /* Create CPU Port Information structure */ 12002 alloc_size = sizeof(_bcm_hx5_cosq_cpu_port_info_t); 12003 if (_bcm_hx5_cosq_cpu_port_info[unit] == NULL) { 12004 _bcm_hx5_cosq_cpu_port_info[unit] = 12005 sal_alloc(alloc_size, "_bcm_hx5_cosq_cpu_port_info"); 12006 if (_bcm_hx5_cosq_cpu_port_info[unit] == NULL) { 12007 _bcm_hx5_cosq_cleanup(unit); 12008 return BCM_E_MEMORY; 12009 } 12010 } 12011 sal_memset(_bcm_hx5_cosq_cpu_port_info[unit], 0, alloc_size); 12012 12013 /* Create MMU Port Information structure */ 12014 alloc_size = sizeof(_bcm_hx5_mmu_info_t); 12015 if (_bcm_hx5_mmu_info[unit] == NULL) { 12016 _bcm_hx5_mmu_info[unit] = 12017 sal_alloc(alloc_size, "_bcm_hx5_mmu_info"); 12018 if (_bcm_hx5_mmu_info[unit] == NULL) { 12019 _bcm_hx5_cosq_cleanup(unit); 12020 return BCM_E_MEMORY; 12021 } 12022 } 12023 sal_memset(_bcm_hx5_mmu_info[unit], 0, alloc_size); 12024 _BCM_HX5_MMU_INFO(unit)->_bcm_hx5_port_info = 12025 _bcm_hx5_cosq_port_info[unit]; 12026 _BCM_HX5_MMU_INFO(unit)->_bcm_hx5_cpu_port_info = 12027 _bcm_hx5_cosq_cpu_port_info[unit]; 12028 _BCM_HX5_MMU_INFO(unit)->_bcm_hx5_st_port_info = 12029 _bcm_hx5_cosq_st_port_info[unit]; 12030 12031 /* Create profile for PORT_COS_MAP table */ 12032 if (_bcm_hx5_cos_map_profile[unit] == NULL) { 12033 _bcm_hx5_cos_map_profile[unit] = sal_alloc(sizeof(soc_profile_mem_t), 12034 "COS_MAP Profile Mem"); 12035 if (_bcm_hx5_cos_map_profile[unit] == NULL) { 12036 _bcm_hx5_cosq_cleanup(unit); 12037 return BCM_E_MEMORY; 12038 } 12039 soc_profile_mem_t_init(_bcm_hx5_cos_map_profile[unit]); 12040 } 12041 mem = PORT_COS_MAPm; 12042 min_index = soc_mem_index_min(unit, PORT_COS_MAPm); 12043 max_index = soc_mem_index_max(unit, PORT_COS_MAPm) / 2; 12044 entry_words[0] = sizeof(port_cos_map_entry_t) / sizeof(uint32); 12045 12046 /* create an cos_map profile with max index of 64, 12047 * because cos_map_sel being an 2 bit we can able to 12048 * maintain up to 4 profiles. 12049 */ 12050 rv = soc_profile_mem_index_create(unit, &mem, entry_words, 12051 &min_index, &max_index, NULL, 1, 12052 _bcm_hx5_cos_map_profile[unit]); 12053 if (rv != SOC_E_NONE) { 12054 _bcm_hx5_cosq_cleanup(unit); 12055 return rv; 12056 } 12057 12058 /* Create profile for IFP_COS_MAP table */ 12059 if (_bcm_hx5_ifp_cos_map_profile[unit] == NULL) { 12060 _bcm_hx5_ifp_cos_map_profile[unit] 12061 = sal_alloc(sizeof(soc_profile_mem_t), "IFP_COS_MAP Profile Mem"); 12062 if (_bcm_hx5_ifp_cos_map_profile[unit] == NULL) { 12063 _bcm_hx5_cosq_cleanup(unit); 12064 return BCM_E_MEMORY; 12065 } 12066 soc_profile_mem_t_init(_bcm_hx5_ifp_cos_map_profile[unit]); 12067 } 12068 mem = IFP_COS_MAPm; 12069 entry_words[0] = sizeof(ifp_cos_map_entry_t) / sizeof(uint32); 12070 12071 rv = soc_profile_mem_create(unit, &mem, entry_words, 1, 12072 _bcm_hx5_ifp_cos_map_profile[unit]); 12073 if (rv != SOC_E_NONE) { 12074 _bcm_hx5_cosq_cleanup(unit); 12075 return rv; 12076 } 12077 12078 /* Create profile for MMU_WRED_DROP_CURVE_PROFILE_x tables */ 12079 if (_bcm_hx5_wred_profile[unit] == NULL) { 12080 _bcm_hx5_wred_profile[unit] = 12081 sal_alloc(sizeof(soc_profile_mem_t), "WRED Profile Mem"); 12082 if (_bcm_hx5_wred_profile[unit] == NULL) { 12083 _bcm_hx5_cosq_cleanup(unit); 12084 return BCM_E_MEMORY; 12085 } 12086 soc_profile_mem_t_init(_bcm_hx5_wred_profile[unit]); 12087 } 12088 12089 entry_words[0] = 12090 sizeof(mmu_wred_drop_curve_profile_0_entry_t) / sizeof(uint32); 12091 entry_words[1] = 12092 sizeof(mmu_wred_drop_curve_profile_1_entry_t) / sizeof(uint32); 12093 entry_words[2] = 12094 sizeof(mmu_wred_drop_curve_profile_2_entry_t) / sizeof(uint32); 12095 entry_words[3] = 12096 sizeof(mmu_wred_drop_curve_profile_3_entry_t) / sizeof(uint32); 12097 entry_words[4] = 12098 sizeof(mmu_wred_drop_curve_profile_4_entry_t) / sizeof(uint32); 12099 entry_words[5] = 12100 sizeof(mmu_wred_drop_curve_profile_5_entry_t) / sizeof(uint32); 12101 entry_words[6] = 12102 sizeof(mmu_wred_drop_curve_profile_6_entry_t) / sizeof(uint32); 12103 entry_words[7] = 12104 sizeof(mmu_wred_drop_curve_profile_7_entry_t) / sizeof(uint32); 12105 entry_words[8] = 12106 sizeof(mmu_wred_drop_curve_profile_8_entry_t) / sizeof(uint32); 12107 12108 rv = soc_profile_mem_create(unit, wred_mems, entry_words, 9, 12109 _bcm_hx5_wred_profile[unit]); 12110 if (rv != SOC_E_NONE) { 12111 _bcm_hx5_cosq_cleanup(unit); 12112 return rv; 12113 } 12114 12115 /* Create profile for PRIO2COS_PROFILE register */ 12116 if (_bcm_hx5_prio2cos_profile[unit] == NULL) { 12117 _bcm_hx5_prio2cos_profile[unit] = 12118 sal_alloc(sizeof(soc_profile_reg_t), "PRIO2COS_PROFILE Profile Reg"); 12119 if (_bcm_hx5_prio2cos_profile[unit] == NULL) { 12120 _bcm_hx5_cosq_cleanup(unit); 12121 return BCM_E_MEMORY; 12122 } 12123 soc_profile_reg_t_init(_bcm_hx5_prio2cos_profile[unit]); 12124 } 12125 reg = PRIO2COS_PROFILE_64r; 12126 rv = soc_profile_reg_create(unit, ®, 1, _bcm_hx5_prio2cos_profile[unit]); 12127 if (rv != SOC_E_NONE) { 12128 _bcm_hx5_cosq_cleanup(unit); 12129 return rv; 12130 } 12131 12132 if (_bcm_hx5_cosq_cpu_cosq_config[unit][0] == NULL) { 12133 cpu_cosq_config_p = sal_alloc(SOC_HX5_NUM_CPU_QUEUES * 12134 sizeof(_bcm_hx5_cosq_cpu_cosq_config_t), "CPU Cosq Config"); 12135 if (cpu_cosq_config_p == NULL) { 12136 _bcm_hx5_cosq_cleanup(unit); 12137 return BCM_E_MEMORY; 12138 } 12139 if (NUM_CPU_COSQ(unit) > SOC_HX5_NUM_CPU_QUEUES) { 12140 /* Invalid CPU Queues */ 12141 if (cpu_cosq_config_p != NULL) { 12142 sal_free(cpu_cosq_config_p); 12143 cpu_cosq_config_p = NULL; 12144 } 12145 _bcm_hx5_cosq_cleanup(unit); 12146 return BCM_E_INIT; 12147 } 12148 for (i = 0; i < NUM_CPU_COSQ(unit); i++) { 12149 _bcm_hx5_cosq_cpu_cosq_config[unit][i] = cpu_cosq_config_p + i; 12150 } 12151 } 12152 12153 if (soc_feature(unit, soc_feature_helix5_ecn)) { 12154 rv = _bcm_hx5_ecn_init(unit); 12155 if (rv != BCM_E_NONE) { 12156 if (cpu_cosq_config_p != NULL) { 12157 sal_free(cpu_cosq_config_p); 12158 cpu_cosq_config_p = NULL; 12159 } 12160 _bcm_hx5_cosq_cleanup(unit); 12161 return rv; 12162 } 12163 } 12164 12165 #if defined(INCLUDE_PSTATS) 12166 if (soc_feature(unit, soc_feature_pstats)) { 12167 rv = _bcm_pstats_init(unit); 12168 if (rv != BCM_E_NONE) { 12169 if (cpu_cosq_config_p != NULL) { 12170 sal_free(cpu_cosq_config_p); 12171 cpu_cosq_config_p = NULL; 12172 } 12173 _bcm_hx5_cosq_cleanup(unit); 12174 return rv; 12175 } 12176 } 12177 #endif /* INCLUDE_PSTATS */ 12178 12179 #if defined (INCLUDE_TCB) && defined (BCM_TCB_SUPPORT) 12180 if (soc_feature(unit, soc_feature_tcb)) { 12181 rv = bcm_hx5_cosq_tcb_init(unit); 12182 } 12183 if (rv != SOC_E_NONE) { 12184 if (cpu_cosq_config_p != NULL) { 12185 sal_free(cpu_cosq_config_p); 12186 cpu_cosq_config_p = NULL; 12187 } 12188 _bcm_hx5_cosq_cleanup(unit); 12189 return rv; 12190 } 12191 #endif 12192 12193 #ifdef BCM_WARM_BOOT_SUPPORT 12194 if (SOC_WARM_BOOT(unit)) { 12195 rv = bcm_hx5_cosq_reinit(unit); 12196 if (rv != BCM_E_NONE) { 12197 if (cpu_cosq_config_p != NULL) { 12198 sal_free(cpu_cosq_config_p); 12199 cpu_cosq_config_p = NULL; 12200 } 12201 _bcm_hx5_cosq_cleanup(unit); 12202 } 12203 /* 12204 * COVERITY 12205 * 12206 * This checker will not be True. 12207 * cpu_cosq_config_p pointer is assigned to 12208 * _bcm_hx5_cosq_cpu_cosq_config global data 12209 * structure. 12210 */ 12211 /* coverity[resource_leak] */ 12212 return rv; 12213 } else { 12214 rv = _bcm_hx5_cosq_wb_alloc(unit); 12215 if (rv != BCM_E_NONE) { 12216 if (cpu_cosq_config_p != NULL) { 12217 sal_free(cpu_cosq_config_p); 12218 cpu_cosq_config_p = NULL; 12219 } 12220 _bcm_hx5_cosq_cleanup(unit); 12221 return rv; 12222 } 12223 } 12224 #endif /* BCM_WARM_BOOT_SUPPORT */ 12225 12226 /* Assign default init values for CPU info */ 12227 for (i = 0; i < NUM_CPU_COSQ(unit); i++) { 12228 if (_bcm_hx5_cosq_cpu_cosq_config[unit][i] == NULL) { 12229 if (cpu_cosq_config_p != NULL) { 12230 sal_free(cpu_cosq_config_p); 12231 cpu_cosq_config_p = NULL; 12232 } 12233 _bcm_hx5_cosq_cleanup(unit); 12234 return BCM_E_MEMORY; 12235 } 12236 sal_memset(_bcm_hx5_cosq_cpu_cosq_config[unit][i], 0, 12237 sizeof(_bcm_hx5_cosq_cpu_cosq_config_t)); 12238 _bcm_hx5_cosq_cpu_cosq_config[unit][i]->enable = 1; 12239 } 12240 12241 /* Add default entries for PORT_COS_MAP memory profile */ 12242 rv = bcm_hx5_cosq_config_set(unit, numq); 12243 if (rv != BCM_E_NONE) { 12244 if (cpu_cosq_config_p != NULL) { 12245 sal_free(cpu_cosq_config_p); 12246 cpu_cosq_config_p = NULL; 12247 } 12248 _bcm_hx5_cosq_cleanup(unit); 12249 return rv; 12250 } 12251 12252 for (pipe = 0; pipe < NUM_PIPE(unit); pipe++) { 12253 /* Clear the WRED memories pointing to WRED profiles */ 12254 mem = SOC_MEM_UNIQUE_ACC(unit, MMU_WRED_CONFIGm)[pipe]; 12255 rv = soc_mem_clear(unit, mem, COPYNO_ALL, 1); 12256 if (rv != SOC_E_NONE) { 12257 if (cpu_cosq_config_p != NULL) { 12258 sal_free(cpu_cosq_config_p); 12259 cpu_cosq_config_p = NULL; 12260 } 12261 _bcm_hx5_cosq_cleanup(unit); 12262 return rv; 12263 } 12264 } 12265 12266 /* Add default entries for MMU_WRED_DROP_CURVE_PROFILE_x memory profile */ 12267 sal_memset(&entry_tcp_green, 0, sizeof(entry_tcp_green)); 12268 sal_memset(&entry_tcp_yellow,0, sizeof(entry_tcp_yellow)); 12269 sal_memset(&entry_tcp_red, 0, sizeof(entry_tcp_red)); 12270 sal_memset(&entry_nontcp_green, 0, sizeof(entry_nontcp_green)); 12271 sal_memset(&entry_nontcp_yellow, 0, sizeof(entry_nontcp_yellow)); 12272 sal_memset(&entry_nontcp_red, 0, sizeof(entry_nontcp_red)); 12273 sal_memset(&entry_ecn_green, 0, sizeof(entry_ecn_green)); 12274 sal_memset(&entry_ecn_yellow,0, sizeof(entry_ecn_yellow)); 12275 sal_memset(&entry_ecn_red, 0, sizeof(entry_ecn_red)); 12276 entries[0] = &entry_tcp_green; 12277 entries[1] = &entry_tcp_yellow; 12278 entries[2] = &entry_tcp_red; 12279 entries[3] = &entry_nontcp_green; 12280 entries[4] = &entry_nontcp_yellow; 12281 entries[5] = &entry_nontcp_red; 12282 entries[6] = &entry_ecn_green; 12283 entries[7] = &entry_ecn_yellow; 12284 entries[8] = &entry_ecn_red; 12285 12286 for (ii = 0; ii < HX5_WRED_PROFILE_NUM; ii++) { 12287 soc_mem_field32_set(unit, wred_mems[ii], entries[ii], 12288 MIN_THDf, 0xffff); 12289 soc_mem_field32_set(unit, wred_mems[ii], entries[ii], 12290 MAX_THDf, 0xffff); 12291 } 12292 profile_index = 0xffffffff; 12293 wred_config_mem = SOC_MEM_UNIQUE_ACC(unit, MMU_WRED_CONFIGm)[0]; 12294 wred_prof_count = soc_mem_index_count(unit, wred_config_mem); 12295 12296 /* In HX5 Profile table duplicate across all pipes. 12297 * Ref count needs to be updated too */ 12298 wred_prof_count *= NUM_PIPE(unit); 12299 while(wred_prof_count) { 12300 if (profile_index == 0xffffffff) { 12301 rv = soc_profile_mem_add(unit, _bcm_hx5_wred_profile[unit], 12302 entries, 1, &profile_index); 12303 } else { 12304 rv = soc_profile_mem_reference(unit, _bcm_hx5_wred_profile[unit], 12305 profile_index, 0); 12306 } 12307 if (rv != SOC_E_NONE) { 12308 if (cpu_cosq_config_p != NULL) { 12309 sal_free(cpu_cosq_config_p); 12310 cpu_cosq_config_p = NULL; 12311 } 12312 _bcm_hx5_cosq_cleanup(unit); 12313 return rv; 12314 } 12315 wred_prof_count -= 1; 12316 } 12317 12318 /* Add default entries for PRIO2COS_PROFILE register profile */ 12319 sal_memset(rval64s, 0, sizeof(rval64s)); 12320 prval64s[0] = rval64s; 12321 profile_index = 0xffffffff; 12322 PBMP_ALL_ITER(unit, port) { 12323 if (IS_CPU_PORT(unit, port) || IS_FAE_PORT(unit, port)) { 12324 continue; 12325 } 12326 if (profile_index == 0xffffffff) { 12327 rv = soc_profile_reg_add(unit, _bcm_hx5_prio2cos_profile[unit], 12328 prval64s, 16, &profile_index); 12329 } else { 12330 rv = soc_profile_reg_reference(unit, _bcm_hx5_prio2cos_profile[unit], 12331 profile_index, 0); 12332 } 12333 if (rv != SOC_E_NONE) { 12334 if (cpu_cosq_config_p != NULL) { 12335 sal_free(cpu_cosq_config_p); 12336 cpu_cosq_config_p = NULL; 12337 } 12338 _bcm_hx5_cosq_cleanup(unit); 12339 return rv; 12340 } 12341 } 12342 12343 /* Create default gport tree */ 12344 _BCM_HX5_MMU_INFO(unit)->gport_tree_created = FALSE; 12345 PBMP_ALL_ITER(unit, port) { 12346 phy_port = si->port_l2p_mapping[port]; 12347 mmu_port = si->port_p2m_mapping[phy_port]; 12348 if (IS_LB_PORT(unit, port) || 12349 IS_FAE_PORT(unit, port) ) { 12350 continue; 12351 } 12352 if(IS_CPU_PORT(unit, port)){ 12353 rv = _bcm_hx5_cosq_cpu_tree_create(unit, port); 12354 if (rv != BCM_E_NONE) { 12355 if (cpu_cosq_config_p != NULL) { 12356 sal_free(cpu_cosq_config_p); 12357 cpu_cosq_config_p = NULL; 12358 } 12359 _bcm_hx5_cosq_cleanup(unit); 12360 return rv; 12361 } 12362 }else if (_HX5_IS_ST_PORT(unit, mmu_port)) { 12363 rv = _bcm_hx5_cosq_st_gport_tree_create(unit, port); 12364 if (rv != BCM_E_NONE) { 12365 if (cpu_cosq_config_p != NULL) { 12366 sal_free(cpu_cosq_config_p); 12367 cpu_cosq_config_p = NULL; 12368 } 12369 _bcm_hx5_cosq_cleanup(unit); 12370 return rv; 12371 } 12372 } else { 12373 rv = _bcm_hx5_cosq_gport_tree_create(unit, port); 12374 if (rv != BCM_E_NONE) { 12375 if (cpu_cosq_config_p != NULL) { 12376 sal_free(cpu_cosq_config_p); 12377 cpu_cosq_config_p = NULL; 12378 } 12379 _bcm_hx5_cosq_cleanup(unit); 12380 return rv; 12381 } 12382 } 12383 } 12384 _BCM_HX5_MMU_INFO(unit)->gport_tree_created = TRUE; 12385 12386 rv = _bcm_hx5_cosq_gport_default_config(unit); 12387 if (rv != BCM_E_NONE) { 12388 if (cpu_cosq_config_p != NULL) { 12389 sal_free(cpu_cosq_config_p); 12390 cpu_cosq_config_p = NULL; 12391 } 12392 _bcm_hx5_cosq_cleanup(unit); 12393 return rv; 12394 } 12395 12396 /* BST INIT */ 12397 sal_memset(&bst_callbks, 0, sizeof(_bcm_bst_device_handlers_t)); 12398 bst_callbks.resolve_index = &_bcm_hx5_bst_index_resolve; 12399 bst_callbks.reverse_resolve_index = &_bcm_hx5_cosq_bst_map_resource_to_gport_cos; 12400 rv = _bcm_bst_attach(unit, &bst_callbks); 12401 if (rv != BCM_E_NONE) { 12402 if (cpu_cosq_config_p != NULL) { 12403 sal_free(cpu_cosq_config_p); 12404 cpu_cosq_config_p = NULL; 12405 } 12406 _bcm_hx5_cosq_cleanup(unit); 12407 return rv; 12408 } 12409 12410 if (soc_feature(unit, soc_feature_pfc_deadlock)) { 12411 rv = _bcm_pfc_deadlock_init(unit); 12412 if (rv != BCM_E_NONE) { 12413 if (cpu_cosq_config_p != NULL) { 12414 sal_free(cpu_cosq_config_p); 12415 cpu_cosq_config_p = NULL; 12416 } 12417 _bcm_hx5_cosq_cleanup(unit); 12418 return rv; 12419 } 12420 } 12421 sal_memset(hx5_time_domain_info, 0x0, sizeof(hx5_time_domain_info)); 12422 for (pipe = 0; pipe < NUM_PIPE(unit); pipe++) { 12423 mmu_wred_config_entry_t entry; 12424 uint32 time_id = 0; 12425 uint32 wred_mem_count = 0; 12426 12427 wred_config_mem = SOC_MEM_UNIQUE_ACC(unit, MMU_WRED_CONFIGm)[pipe]; 12428 wred_mem_count = soc_mem_index_count(unit, wred_config_mem); 12429 if (INVALIDm != wred_config_mem) { 12430 for (i = 0; i< wred_mem_count; i++){ 12431 BCM_IF_ERROR_RETURN 12432 (soc_mem_read(unit, wred_config_mem, MEM_BLOCK_ALL, i, 12433 &entry)); 12434 time_id = soc_mem_field32_get(unit, wred_config_mem, &entry, 12435 TIME_DOMAIN_SELf); 12436 if(time_id < _BCM_HX5_NUM_TIME_DOMAIN) { 12437 hx5_time_domain_info[unit][time_id].ref_count ++; 12438 } 12439 } 12440 } 12441 } 12442 12443 for (i = 0; i < _BCM_HX5_NUM_WRED_RESOLUTION_TABLE; i++) { 12444 if (i == 0) { 12445 _bcm_hx5_wred_resolution_tbl[i] = 1; 12446 } else { 12447 _bcm_hx5_wred_resolution_tbl[i] = 0; 12448 } 12449 } 12450 12451 12452 12453 12454 return BCM_E_NONE; 12455 } 12456 12457 /* 12458 * Function: 12459 * bcm_hx5_cosq_port_attach 12460 * Purpose: 12461 * Initialize Cosq for newly added port 12462 * Parameters: 12463 * unit - (IN) unit number 12464 * port - (IN) Logical port. 12465 * Returns: 12466 * BCM_E_XXX 12467 */ 12468 int 12469 bcm_hx5_cosq_port_attach(int unit, bcm_port_t port) 12470 { 12471 int default_mode = BCM_COSQ_WEIGHTED_ROUND_ROBIN, default_weight = 1; 12472 uint64 rval64s[16], *prval64s[1]; 12473 uint32 profile_index; 12474 int phy_port, mmu_port; 12475 soc_info_t *si = &SOC_INFO(unit); 12476 12477 12478 if (IS_CPU_PORT(unit, port) || IS_LB_PORT(unit, port) || 12479 IS_MANAGEMENT_PORT(unit, port)) { 12480 return BCM_E_PARAM; 12481 } 12482 12483 phy_port = si->port_l2p_mapping[port]; 12484 mmu_port = si->port_p2m_mapping[phy_port]; 12485 /* Increase the reference of default PRIO2COS_PROFILE */ 12486 sal_memset(rval64s, 0, sizeof(rval64s)); 12487 prval64s[0] = rval64s; 12488 BCM_IF_ERROR_RETURN 12489 (soc_profile_reg_add(unit, _bcm_hx5_prio2cos_profile[unit], 12490 prval64s, 16, &profile_index)); 12491 12492 /* Create gport tree */ 12493 _BCM_HX5_MMU_INFO(unit)->gport_tree_created = FALSE; 12494 if (_HX5_IS_ST_PORT(unit, mmu_port)) { 12495 BCM_IF_ERROR_RETURN(_bcm_hx5_cosq_st_gport_tree_create(unit, port)); 12496 } else { 12497 BCM_IF_ERROR_RETURN(_bcm_hx5_cosq_gport_tree_create(unit, port)); 12498 } 12499 _BCM_HX5_MMU_INFO(unit)->gport_tree_created = TRUE; 12500 12501 /* Set Default Scheduler Configuration on the ports */ 12502 BCM_IF_ERROR_RETURN 12503 (_bcm_hx5_cosq_sched_config_port(unit, port, default_mode, 12504 default_weight)); 12505 12506 return BCM_E_NONE; 12507 } 12508 12509 /* 12510 * Function: 12511 * bcm_hx5_cosq_port_detach 12512 * Purpose: 12513 * Clear cosq configuration of port 12514 * Parameters: 12515 * unit - (IN) unit number 12516 * port - (IN) Logical port. 12517 * Returns: 12518 * BCM_E_XXX 12519 */ 12520 int 12521 bcm_hx5_cosq_port_detach(int unit, bcm_port_t port) 12522 { 12523 _bcm_hx5_cosq_port_info_t *port_info = NULL; 12524 _bcm_hx5_cosq_st_port_info_t *stport_info = NULL; 12525 int phy_port, mmu_port, index; 12526 uint32 rval, profile_index; 12527 12528 soc_info_t *si = &SOC_INFO(unit); 12529 12530 if (IS_CPU_PORT(unit, port) || IS_LB_PORT(unit, port) || 12531 IS_MANAGEMENT_PORT(unit, port)) { 12532 return BCM_E_PARAM; 12533 } 12534 12535 phy_port = si->port_l2p_mapping[port]; 12536 mmu_port = si->port_p2m_mapping[phy_port]; 12537 _HX5_PORT_INDEX_GET(unit, mmu_port, index); 12538 12539 /* Destroy cosq gport tree on port */ 12540 if (_HX5_IS_ST_PORT(unit, mmu_port)) { 12541 stport_info = &_bcm_hx5_cosq_st_port_info[unit][index]; 12542 sal_memset(stport_info, 0, sizeof(_bcm_hx5_cosq_st_port_info_t)); 12543 } else { 12544 port_info = &_bcm_hx5_cosq_port_info[unit][index]; 12545 sal_memset(port_info, 0, sizeof(_bcm_hx5_cosq_port_info_t)); 12546 } 12547 12548 /* Decrease the reference of defalt PRIO2COS_PROFILE */ 12549 BCM_IF_ERROR_RETURN(soc_reg32_get(unit, PORT_LLFC_CFGr, port, 0, &rval)); 12550 profile_index = soc_reg_field_get(unit, PORT_LLFC_CFGr, rval, 12551 PROFILE_INDEXf) * 16; 12552 BCM_IF_ERROR_RETURN 12553 (soc_profile_reg_delete(unit, _bcm_hx5_prio2cos_profile[unit], 12554 profile_index)); 12555 12556 /* Clear cosq */ 12557 si->port_num_cosq[port] = 0; 12558 si->port_cosq_base[port] = 0; 12559 si->port_num_uc_cosq[port] = 0; 12560 si->port_uc_cosq_base[port] = 0; 12561 si->port_num_ext_cosq[port] = 0; 12562 12563 return BCM_E_NONE; 12564 } 12565 12566 /* 12567 * Function: 12568 * _bcm_hx5_port_enqueue_set 12569 * Purpose: 12570 * Enable or Disable enqueing packets to the port 12571 * Parameters: 12572 * unit - (IN) unit number 12573 * gport - (IN) gport of the port 12574 * enable - (IN) TRUE to enable 12575 * FALSE to disable 12576 * Returns: 12577 * BCM_E_XXX 12578 */ 12579 12580 int 12581 _bcm_hx5_port_enqueue_set(int unit, bcm_port_t gport, int enable) 12582 { 12583 bcm_port_t local_port = -1; 12584 12585 BCM_IF_ERROR_RETURN 12586 (_bcm_hx5_cosq_localport_resolve(unit, gport, &local_port)); 12587 12588 SOC_IF_ERROR_RETURN( 12589 soc_td3_port_mmu_tx_enable_set(unit, local_port, enable)); 12590 SOC_IF_ERROR_RETURN( 12591 soc_td3_port_mmu_rx_enable_set(unit, local_port, enable)); 12592 12593 return BCM_E_NONE; 12594 } 12595 12596 /* 12597 * Function: 12598 * _bcm_hx5_port_enqueue_get 12599 * Purpose: 12600 * Get the enqueing state of the port 12601 * Parameters: 12602 * unit - (IN) unit number 12603 * gport - (IN) gport of the port 12604 * enable - (IN) TRUE for both rx and tx are enable 12605 * FALSE for rx/tx is disable 12606 * Returns: 12607 * BCM_E_XXX 12608 */ 12609 12610 int 12611 _bcm_hx5_port_enqueue_get(int unit, bcm_port_t gport, 12612 int *enable) 12613 { 12614 bcm_port_t local_port = -1; 12615 int rx_enable = 0, tx_enable = 0; 12616 12617 if (enable == NULL) { 12618 return BCM_E_INTERNAL; 12619 } 12620 12621 BCM_IF_ERROR_RETURN( 12622 _bcm_hx5_cosq_localport_resolve(unit, gport, &local_port)); 12623 12624 SOC_IF_ERROR_RETURN( 12625 soc_td3_port_mmu_tx_enable_get(unit, local_port, &tx_enable)); 12626 SOC_IF_ERROR_RETURN( 12627 soc_td3_port_mmu_rx_enable_get(unit, local_port, &rx_enable)); 12628 12629 if (rx_enable && tx_enable) { 12630 *enable = TRUE; 12631 } else { 12632 *enable = FALSE; 12633 } 12634 12635 return BCM_E_NONE; 12636 } 12637 /* 12638 * Function: 12639 * bcm_hx5_cosq_cpu_cosq_enable_get 12640 * Purpose: 12641 * To get enable/disable status on Rx of packets on the specified CPU cosq. 12642 * Parameters: 12643 * unit - (IN) unit number 12644 * cosq - (IN) CPU Cosq ID 12645 * enable - (IN) Enable/Disable 12646 * Returns: 12647 * BCM_E_XXX 12648 */ 12649 int 12650 bcm_hx5_cosq_cpu_cosq_enable_get(int unit, bcm_cos_queue_t cosq, int *enable) 12651 { 12652 uint32 entry[SOC_MAX_MEM_WORDS]; 12653 int index, hw_enable; 12654 _bcm_hx5_cosq_cpu_cosq_config_t *cpu_cosq; 12655 soc_info_t *si; 12656 soc_mem_t thdm_mem = MMU_THDM_DB_QUEUE_CONFIG_PIPE0m; 12657 soc_field_t min_limit, shared_limit, limit_enable, dynamic_enable; 12658 12659 si = &SOC_INFO(unit); 12660 12661 if ((cosq < 0) || (cosq >= NUM_CPU_COSQ(unit))) { 12662 return BCM_E_PARAM; 12663 } 12664 12665 cpu_cosq = _bcm_hx5_cosq_cpu_cosq_config[unit][cosq]; 12666 12667 if (!cpu_cosq) { 12668 return BCM_E_INTERNAL; 12669 } 12670 12671 /* CPU Port (0) - MC cosq's range from 1290 - 1337. */ 12672 index = si->port_cosq_base[CMIC_PORT(unit)] + cosq; 12673 hw_enable = 1; 12674 12675 /* Sync up software record with hardware status. */ 12676 BCM_IF_ERROR_RETURN(soc_mem_read(unit, thdm_mem, MEM_BLOCK_ALL, index, 12677 &entry)); 12678 min_limit = soc_mem_field32_get(unit, thdm_mem, &entry, Q_MIN_LIMITf); 12679 shared_limit = soc_mem_field32_get(unit, thdm_mem, &entry, Q_SHARED_LIMITf); 12680 limit_enable = soc_mem_field32_get(unit, thdm_mem, &entry, Q_LIMIT_ENABLEf); 12681 dynamic_enable = soc_mem_field32_get(unit, thdm_mem, &entry, Q_LIMIT_DYNAMICf); 12682 12683 if ((limit_enable != 0) && (dynamic_enable == 0) && 12684 (min_limit == 0) && (shared_limit == 0)) { 12685 hw_enable = 0; 12686 } 12687 cpu_cosq->enable = hw_enable; 12688 12689 *enable = cpu_cosq->enable; 12690 return BCM_E_NONE; 12691 12692 return BCM_E_NONE; 12693 } 12694 /* 12695 * Function: 12696 * bcm_hx5_cosq_cpu_cosq_enable_set 12697 * Purpose: 12698 * To enable/disable Rx of packets on the specified CPU cosq. 12699 * Parameters: 12700 * unit - (IN) unit number 12701 * cosq - (IN) CPU Cosq ID 12702 * enable - (IN) Enable/Disable 12703 * Returns: 12704 * BCM_E_XXX 12705 */ 12706 int 12707 bcm_hx5_cosq_cpu_cosq_enable_set(int unit, bcm_cos_queue_t cosq, int enable) 12708 { 12709 uint32 entry[SOC_MAX_MEM_WORDS]; 12710 int i, index, enable_status; 12711 _bcm_hx5_cosq_cpu_cosq_config_t *cpu_cosq_config; 12712 soc_info_t *si; 12713 soc_mem_t thdm_mem[] = { 12714 MMU_THDM_DB_QUEUE_CONFIG_PIPE0m, 12715 MMU_THDM_MCQE_QUEUE_CONFIG_PIPE0m 12716 }; 12717 12718 si = &SOC_INFO(unit); 12719 12720 if ((cosq < 0) || (cosq >= NUM_CPU_COSQ(unit))) { 12721 return BCM_E_PARAM; 12722 } 12723 12724 cpu_cosq_config = _bcm_hx5_cosq_cpu_cosq_config[unit][cosq]; 12725 12726 if (!cpu_cosq_config) { 12727 return BCM_E_INTERNAL; 12728 } 12729 12730 BCM_IF_ERROR_RETURN(bcm_hx5_cosq_cpu_cosq_enable_get(unit, cosq, 12731 &enable_status)); 12732 if (enable == enable_status) { 12733 return BCM_E_NONE; 12734 } 12735 12736 /* CPU Port (0) - MC cosq's range from 1290 - 1337. */ 12737 index = si->port_cosq_base[CMIC_PORT(unit)] + cosq; 12738 12739 /* To set DB and QE entries */ 12740 for (i = 0; i < 2; i++) { 12741 BCM_IF_ERROR_RETURN 12742 (soc_mem_read(unit, thdm_mem[i], MEM_BLOCK_ALL, index, &entry)); 12743 12744 /* When enabled, restore the Min and Shared from the cached value */ 12745 if (!enable) { 12746 cpu_cosq_config->q_min_limit[i] = soc_mem_field32_get(unit, 12747 thdm_mem[i], &entry, 12748 Q_MIN_LIMITf); 12749 cpu_cosq_config->q_shared_limit[i] = soc_mem_field32_get(unit, 12750 thdm_mem[i], &entry, 12751 Q_SHARED_LIMITf); 12752 cpu_cosq_config->q_limit_dynamic[i] = soc_mem_field32_get(unit, 12753 thdm_mem[i], &entry, 12754 Q_LIMIT_DYNAMICf); 12755 cpu_cosq_config->q_limit_enable[i] = soc_mem_field32_get(unit, 12756 thdm_mem[i], &entry, 12757 Q_LIMIT_ENABLEf); 12758 cpu_cosq_config->q_color_limit_enable[i] = soc_mem_field32_get(unit, 12759 thdm_mem[i], &entry, 12760 Q_COLOR_LIMIT_ENABLEf); 12761 } 12762 soc_mem_field32_set(unit, thdm_mem[i], &entry, Q_LIMIT_DYNAMICf, 12763 enable ? cpu_cosq_config->q_limit_dynamic[i] : 0); 12764 soc_mem_field32_set(unit, thdm_mem[i], &entry, Q_LIMIT_ENABLEf, 12765 enable ? cpu_cosq_config->q_limit_enable[i] : 1); 12766 soc_mem_field32_set(unit, thdm_mem[i], &entry, Q_COLOR_LIMIT_ENABLEf, 12767 enable ? cpu_cosq_config->q_color_limit_enable[i] :1); 12768 soc_mem_field32_set(unit, thdm_mem[i], &entry, Q_MIN_LIMITf, 12769 enable ? cpu_cosq_config->q_min_limit[i] : 0); 12770 soc_mem_field32_set(unit, thdm_mem[i], &entry, Q_SHARED_LIMITf, 12771 enable ? cpu_cosq_config->q_shared_limit[i] : 0); 12772 cpu_cosq_config->enable = enable; 12773 BCM_IF_ERROR_RETURN 12774 (soc_mem_write(unit, thdm_mem[i], MEM_BLOCK_ALL, index, &entry)); 12775 } 12776 12777 return BCM_E_NONE; 12778 } 12779 12780 /* 12781 * Function: 12782 * bcm_hx5_cosq_field_classifier_get 12783 * Purpose: 12784 * Get classifier type information. 12785 * Parameters: 12786 * unit - (IN) unit number 12787 * classifier_id - (IN) Classifier ID 12788 * classifier - (OUT) Classifier info 12789 * Returns: 12790 * BCM_E_XXX 12791 */ 12792 int 12793 bcm_hx5_cosq_field_classifier_get(int unit, int classifier_id, 12794 bcm_cosq_classifier_t *classifier) 12795 { 12796 if (classifier == NULL) { 12797 return BCM_E_PARAM; 12798 } 12799 sal_memset(classifier, 0, sizeof(bcm_cosq_classifier_t)); 12800 12801 if (_BCM_COSQ_CLASSIFIER_IS_FIELD(classifier_id)) { 12802 classifier->flags |= BCM_COSQ_CLASSIFIER_FIELD; 12803 } 12804 12805 return BCM_E_NONE; 12806 } 12807 12808 /* 12809 * Function: 12810 * bcm_hx5_cosq_field_classifier_id_create 12811 * Purpose: 12812 * Create a cosq classifier. 12813 * Parameters: 12814 * unit - (IN) unit number 12815 * classifier - (IN) Classifier attributes 12816 * classifier_id - (OUT) Classifier ID 12817 * Returns: 12818 * BCM_E_XXX 12819 */ 12820 int 12821 bcm_hx5_cosq_field_classifier_id_create(int unit, bcm_cosq_classifier_t 12822 *classifier, int *classifier_id) 12823 { 12824 int rv; 12825 int ref_count = 0; 12826 int ent_per_set = _HX5_MMU_NUM_INT_PRI; 12827 int i; 12828 12829 if (NULL == classifier || NULL == classifier_id) { 12830 return BCM_E_PARAM; 12831 } 12832 12833 for (i = 0; i < SOC_MEM_SIZE(unit, IFP_COS_MAPm); i += ent_per_set) { 12834 rv = soc_profile_mem_ref_count_get( 12835 unit, _bcm_hx5_ifp_cos_map_profile[unit], i, &ref_count); 12836 if (SOC_FAILURE(rv)) { 12837 return rv; 12838 } 12839 if (0 == ref_count) { 12840 break; 12841 } 12842 } 12843 12844 if (i >= SOC_MEM_SIZE(unit, IFP_COS_MAPm) && ref_count != 0) { 12845 *classifier_id = 0; 12846 return BCM_E_RESOURCE; 12847 } 12848 12849 _BCM_COSQ_CLASSIFIER_FIELD_SET(*classifier_id, (i / ent_per_set)); 12850 12851 return BCM_E_NONE; 12852 } 12853 12854 /* 12855 * Function: 12856 * bcm_hx5_cosq_field_classifier_id_destroy 12857 * Purpose: 12858 * Free resource associated with this field classifier id. 12859 * Parameters: 12860 * unit - (IN) Unit number. 12861 * classifier_id - (IN) Classifier ID 12862 * Returns: 12863 * BCM_E_xxx 12864 */ 12865 int 12866 bcm_hx5_cosq_field_classifier_id_destroy(int unit, int classifier_id) 12867 { 12868 return BCM_E_NONE; 12869 } 12870 12871 /* 12872 * Function: 12873 * bcm_hx5_cosq_field_classifier_map_set 12874 * Purpose: 12875 * Set internal priority to ingress field processor CoS queue override 12876 * mapping. 12877 * Parameters: 12878 * unit - (IN) unit number 12879 * classifier_id - (OUT) Classifier ID 12880 * count - (IN) Number of elements in priority_array and cosq_array 12881 * priority_array - (IN) Array of internal priorities 12882 * cosq_array - (IN) Array of COS queues 12883 * Returns: 12884 * BCM_E_XXX 12885 * Notes: 12886 * Supported count value is [0-16] and 48 12887 * When count = [0-16] 12888 * Array Index [15-0] : Maps Prio[15-0] to UC, MC, HG and RQE cos[15-0] 12889 * When count = 48 12890 * Prio Array Index Map 12891 * Array Index [15-0] : Maps Prio[15-0] to UC and HG cos[15-0] 12892 * Array Index [31-16] : Maps Prio[15-0] to MC and HG cos[15-0] 12893 * Array Index [47-32] : Maps Prio[15-0] to RQE cos[15-0] 12894 */ 12895 int 12896 bcm_hx5_cosq_field_classifier_map_set(int unit, int classifier_id, int count, 12897 bcm_cos_t *priority_array, bcm_cos_queue_t *cosq_array) 12898 { 12899 int rv; 12900 int i; 12901 int max_entries = _HX5_MMU_NUM_INT_PRI; 12902 uint32 index, new_index; 12903 void *entries[1]; 12904 ifp_cos_map_entry_t ent_buf[_HX5_MMU_NUM_INT_PRI]; 12905 soc_field_t field = -1; 12906 soc_field_t field1 = -1; 12907 12908 /* Input parameter check. */ 12909 if (!_BCM_COSQ_CLASSIFIER_IS_FIELD(classifier_id)) { 12910 return BCM_E_PARAM; 12911 } 12912 12913 if (NULL == priority_array || NULL == cosq_array) { 12914 return BCM_E_PARAM; 12915 } 12916 12917 if ((count > max_entries) && (count != (max_entries * 3))) { 12918 return BCM_E_PARAM; 12919 } 12920 12921 sal_memset(ent_buf, 0, sizeof(ifp_cos_map_entry_t) * max_entries); 12922 entries[0] = ent_buf; 12923 12924 if (count != (max_entries * 3)) { 12925 for (i = 0; i < count; i++) { 12926 if (priority_array[i] < max_entries) { 12927 /* When count != max_entries * 3 12928 We program the same mapping for all three 12929 fields UC/MC/RQE/HG queues. 12930 Hence cos_array[i] cannot have value more than 12931 equal to 26 */ 12932 if ((cosq_array[i] < 0) || 12933 (cosq_array[i] >= SOC_HX5_NUM_UCAST_QUEUE_PER_ST_PORT)) { 12934 return BCM_E_PARAM; 12935 } 12936 soc_mem_field32_set(unit, IFP_COS_MAPm, &ent_buf[priority_array[i]], 12937 IFP_MC_COSf, cosq_array[i]); 12938 soc_mem_field32_set(unit, IFP_COS_MAPm, &ent_buf[priority_array[i]], 12939 IFP_UC_COSf, cosq_array[i]); 12940 soc_mem_field32_set(unit, IFP_COS_MAPm, &ent_buf[priority_array[i]], 12941 IFP_HG_COSf, cosq_array[i]); 12942 soc_mem_field32_set(unit, IFP_COS_MAPm, &ent_buf[priority_array[i]], 12943 IFP_RQE_Q_NUMf, 12944 (cosq_array[i] > _HX5_MMU_NUM_RQE_QUEUES) ? _HX5_MMU_NUM_RQE_QUEUES : cosq_array[i]); 12945 } 12946 } 12947 } else { 12948 for (i = 0; i < count; i++) { 12949 field = field1 = -1; 12950 if (priority_array[i] < max_entries) { 12951 if (i < max_entries) { 12952 /* Number of UCAST queue per port = 26 */ 12953 if ((cosq_array[i] < 0) || 12954 (cosq_array[i] >= SOC_HX5_NUM_UCAST_QUEUE_PER_ST_PORT)) { 12955 return BCM_E_PARAM; 12956 } 12957 field = IFP_UC_COSf; 12958 field1 = IFP_HG_COSf; 12959 } else if (i < (max_entries * 2)) { 12960 /* Number of MCAST queue per port = 26 */ 12961 if ((cosq_array[i] < 0) || 12962 (cosq_array[i] >= SOC_HX5_NUM_MCAST_QUEUE_PER_ST_PORT)) { 12963 return BCM_E_PARAM; 12964 } 12965 field = IFP_MC_COSf; 12966 field1 = IFP_HG_COSf; 12967 } else { 12968 if ((cosq_array[i] < 0) || 12969 (cosq_array[i] >= SOC_HX5_NUM_MCAST_QUEUE_PER_ST_PORT)) { 12970 return BCM_E_PARAM; 12971 } 12972 /* Number of RQE queue per unit = 11 */ 12973 if (cosq_array[i] > _HX5_MMU_NUM_RQE_QUEUES) { 12974 cosq_array[i] = _HX5_MMU_NUM_RQE_QUEUES; 12975 } 12976 field = IFP_RQE_Q_NUMf; 12977 } 12978 soc_mem_field32_set(unit, IFP_COS_MAPm, &ent_buf[priority_array[i]], 12979 field, cosq_array[i]); 12980 if (field1 != -1) { 12981 soc_mem_field32_set(unit, IFP_COS_MAPm, &ent_buf[priority_array[i]], 12982 field1, cosq_array[i]); 12983 } 12984 } 12985 } 12986 } 12987 12988 index = _BCM_COSQ_CLASSIFIER_FIELD_GET(classifier_id); 12989 12990 rv = soc_profile_mem_delete(unit, _bcm_hx5_ifp_cos_map_profile[unit], 12991 index * max_entries); 12992 12993 /* If rv = SOC_E_NONE means that there exists a 12994 * mapping for given classifier_id which is now 12995 * successfully deleted and we can overwrite. 12996 * rv = SOC_E_NOT_FOUND means there was no mapping 12997 * for given classifier_id and we can create a new mapping 12998 * Otherwise there is something else wrong and we return 12999 * the error value returned by soc_profile_mem_delete() 13000 */ 13001 if ((rv != SOC_E_NONE) && (rv != SOC_E_NOT_FOUND)) { 13002 return rv; 13003 } 13004 13005 SOC_IF_ERROR_RETURN 13006 (soc_profile_mem_add(unit, _bcm_hx5_ifp_cos_map_profile[unit], 13007 entries, max_entries, &new_index)); 13008 13009 /* If we get (index == new_index / max_entries) means we have 13010 * a successful mapping operation. 13011 * But if they are not equal which means there already exists 13012 * a similar mapping associated with other classifier_id hence 13013 * we return BCM_E_EXISTS. 13014 */ 13015 13016 if (index != (new_index / max_entries)) { 13017 SOC_IF_ERROR_RETURN 13018 (soc_profile_mem_delete(unit, _bcm_hx5_ifp_cos_map_profile[unit], 13019 new_index)); 13020 return BCM_E_EXISTS; 13021 } 13022 13023 return BCM_E_NONE; 13024 } 13025 13026 /* 13027 * Function: 13028 * bcm_hx5_cosq_field_classifier_map_get 13029 * Purpose: 13030 * Get internal priority to ingress field processor CoS queue 13031 * override mapping information. 13032 * Parameters: 13033 * unit - (IN) Unit number. 13034 * classifier_id - (IN) Classifier ID 13035 * array_max - (IN) Size of priority_array and cosq_array 13036 * priority_array - (IN) Array of internal priorities 13037 * cosq_array - (OUT) Array of COS queues 13038 * array_count - (OUT) Size of cosq_array 13039 * Returns: 13040 * BCM_E_xxx 13041 * Notes: 13042 * Supported array_max = [0-16] and 48 13043 * When array_max = [0-16] 13044 * Array Index [15-0] : Maps Prio[15-0] to UC cos[15-0] 13045 * When array_max = 48 13046 * Prio Array Index Map 13047 * Array Index [15-0] : Maps Prio[15-0] to UC cos[15-0] 13048 * Array Index [31-16] : Maps Prio[15-0] to MC cos[15-0] 13049 * Array Index [47-32] : Maps Prio[15-0] to RQE cos[15-0] 13050 */ 13051 int 13052 bcm_hx5_cosq_field_classifier_map_get(int unit, int classifier_id, int array_max, 13053 bcm_cos_t *priority_array, bcm_cos_queue_t *cosq_array, int *array_count) 13054 { 13055 int rv; 13056 int i; 13057 int ent_per_set = _HX5_MMU_NUM_INT_PRI; 13058 uint32 index; 13059 void *entries[1]; 13060 ifp_cos_map_entry_t ent_buf[_HX5_MMU_NUM_INT_PRI]; 13061 soc_field_t field = -1; 13062 13063 /* Input parameter check. */ 13064 if (NULL == priority_array || NULL == cosq_array || NULL == array_count) { 13065 return BCM_E_PARAM; 13066 } 13067 13068 sal_memset(ent_buf, 0, sizeof(ifp_cos_map_entry_t) * ent_per_set); 13069 entries[0] = ent_buf; 13070 13071 /* Get profile table entry set base index. */ 13072 index = _BCM_COSQ_CLASSIFIER_FIELD_GET(classifier_id); 13073 13074 /* Read out entries from profile table into allocated buffer. */ 13075 rv = soc_profile_mem_get(unit, _bcm_hx5_ifp_cos_map_profile[unit], 13076 index * ent_per_set, ent_per_set, entries); 13077 if (SOC_FAILURE(rv)) { 13078 return rv; 13079 } 13080 13081 if (array_max <= ent_per_set) { 13082 *array_count = array_max; 13083 } else if ((array_max > ent_per_set) && (array_max < (ent_per_set * 3))) { 13084 return BCM_E_PARAM; 13085 } else { 13086 *array_count = ent_per_set * 3; 13087 } 13088 /* Copy values into API OUT parameters. */ 13089 for (i = 0; i < *array_count; i++) { 13090 if (priority_array[i % 16] >= _HX5_MMU_NUM_INT_PRI) { 13091 return BCM_E_PARAM; 13092 } 13093 if (i < ent_per_set) { 13094 field = IFP_UC_COSf; 13095 } else if (i < (ent_per_set * 2)) { 13096 field = IFP_MC_COSf; 13097 } else { 13098 field = IFP_RQE_Q_NUMf; 13099 } 13100 cosq_array[i] = soc_mem_field32_get(unit, IFP_COS_MAPm, 13101 &ent_buf[priority_array[i]], 13102 field); 13103 } 13104 13105 return BCM_E_NONE; 13106 } 13107 13108 /* 13109 * Function: 13110 * bcm_hx5_cosq_field_classifier_map_clear 13111 * Purpose: 13112 * Delete an internal priority to ingress field processor CoS queue 13113 * override mapping profile set. 13114 * Parameters: 13115 * unit - (IN) Unit number. 13116 * classifier_id - (IN) Classifier ID 13117 * Returns: 13118 * BCM_E_xxx 13119 */ 13120 int 13121 bcm_hx5_cosq_field_classifier_map_clear(int unit, int classifier_id) 13122 { 13123 int ent_per_set = _HX5_MMU_NUM_INT_PRI; 13124 uint32 index; 13125 13126 /* Get profile table entry set base index. */ 13127 index = _BCM_COSQ_CLASSIFIER_FIELD_GET(classifier_id); 13128 13129 /* Delete the profile entries set. */ 13130 SOC_IF_ERROR_RETURN 13131 (soc_profile_mem_delete(unit, 13132 _bcm_hx5_ifp_cos_map_profile[unit], 13133 index * ent_per_set)); 13134 return BCM_E_NONE; 13135 } 13136 13137 STATIC int 13138 _bcm_hx5_cosq_cpu_port_info_dump(int unit) 13139 { 13140 _bcm_hx5_cosq_cpu_port_info_t *port_info; 13141 bcm_port_t port = 0; /* CPU Port */ 13142 _bcm_hx5_cosq_node_t *node; 13143 int index, new_index; 13144 soc_hx5_sched_mode_e sched_mode = 0; 13145 int weight = 0; 13146 13147 char *sched_modes[] = {"X", "SP", "WRR", "WERR"}; 13148 13149 if (!SOC_PORT_VALID(unit, port)) { 13150 return BCM_E_PORT; 13151 } 13152 port_info = _bcm_hx5_cosq_cpu_port_info[unit]; 13153 if (port_info == NULL) { 13154 return BCM_E_INIT; 13155 } 13156 13157 LOG_CLI((BSL_META_U(unit, 13158 "=== CPU PORT ===\n"))); 13159 13160 LOG_CLI((BSL_META_U(unit, 13161 "Nodes\n"))); 13162 for (index = 0; index < SOC_HX5_NUM_SCHEDULER_PER_CPU_PORT; index++) { 13163 /* Node */ 13164 node = &port_info->sched[index]; 13165 BCM_IF_ERROR_RETURN( 13166 _bcm_hx5_cosq_sched_mode_setget(unit, port, node->level, index, 13167 &sched_mode, &weight, 0, 0)); 13168 new_index = (index >= 2) ? index - 2 : index; 13169 LOG_CLI((BSL_META_U(unit, 13170 "L%d.%d: GPORT=0x%x HW_INDEX=%d MODE=%s WT=%d\n"), 13171 node->level - 1, new_index, node->gport, node->hw_index, 13172 sched_modes[sched_mode], weight)); 13173 } 13174 13175 LOG_CLI((BSL_META_U(unit, 13176 "\nMC Queues\n"))); 13177 for (index = 0; index < SOC_HX5_NUM_CPU_QUEUES; index++) { 13178 int parent_id = 0; 13179 /* MC Queue */ 13180 node = &port_info->mcast[index]; 13181 BCM_IF_ERROR_RETURN( 13182 _bcm_hx5_cosq_sched_mode_setget(unit, port, node->level, index, 13183 &sched_mode, &weight, 1, 0)); 13184 BCM_IF_ERROR_RETURN( 13185 _bcm_hx5_cosq_node_get(unit, node->parent_gport, NULL, NULL, 13186 &parent_id, NULL)); 13187 LOG_CLI((BSL_META_U(unit, 13188 " MC.%d: GPORT=0x%x HW_INDEX=%d MODE=%s WT=%d" 13189 " PARENT=%d\n"), 13190 index, node->gport, node->hw_index, 13191 sched_modes[sched_mode], weight, 13192 parent_id)); 13193 } 13194 LOG_CLI((BSL_META_U(unit, 13195 "=========== \n"))); 13196 13197 return BCM_E_NONE; 13198 } 13199 13200 STATIC int 13201 _bcm_hx5_cosq_st_port_info_dump(int unit, bcm_port_t port) 13202 { 13203 _bcm_hx5_cosq_st_port_info_t *port_info; 13204 _bcm_hx5_cosq_node_t *node; 13205 int index, empty, port_index; 13206 int l1index = 0, l2index = 0, l3index = 0; 13207 int l1_max = 0, l2_max = 0, l3_max = 0; 13208 soc_hx5_sched_mode_e sched_mode = 0; 13209 int weight = 0; 13210 char *sched_modes[] = {"X", "SP", "WRR", "WERR"}; 13211 int phy_port, mmu_port; 13212 soc_info_t *si = &SOC_INFO(unit); 13213 13214 13215 phy_port = si->port_l2p_mapping[port]; 13216 mmu_port = si->port_p2m_mapping[phy_port]; 13217 _HX5_PORT_INDEX_GET(unit, mmu_port, port_index); 13218 13219 if (!SOC_PORT_VALID(unit, port)) { 13220 return BCM_E_PORT; 13221 } 13222 port_info = &_bcm_hx5_cosq_st_port_info[unit][port_index]; 13223 13224 empty = TRUE; 13225 for (index = 0; index < SOC_HX5_NUM_SCHEDULER_PER_ST_PORT; index++) { 13226 if (port_info->sched[index].numq > 0) { 13227 empty = FALSE; 13228 break; 13229 } 13230 } 13231 if (empty) { 13232 for (index = 0; index < SOC_HX5_NUM_UCAST_QUEUE_PER_ST_PORT; index++) { 13233 if (port_info->ucast[index].numq > 0) { 13234 empty = FALSE; 13235 break; 13236 } 13237 } 13238 } 13239 if (empty) { 13240 for (index = 0; index < SOC_HX5_NUM_MCAST_QUEUE_PER_ST_PORT; index++) { 13241 if (port_info->mcast[index].numq > 0) { 13242 empty = FALSE; 13243 break; 13244 } 13245 } 13246 } 13247 13248 if (empty == TRUE) { 13249 return BCM_E_NOT_FOUND; 13250 } 13251 13252 LOG_CLI((BSL_META_U(unit, 13253 "=== PORT %d\n"), port)); 13254 13255 for (index = 0; index < 3; index++) { 13256 /* Node */ 13257 node = &port_info->sched[index]; 13258 13259 BCM_IF_ERROR_RETURN( 13260 _bcm_hx5_cosq_sched_mode_setget(unit, port, node->level, index, 13261 &sched_mode, &weight, 0, 0)); 13262 LOG_CLI((BSL_META_U(unit, 13263 "L0.%d: GPORT=0x%x HW_INDEX=%d MODE=%s WT=%d\n"), 13264 index, node->gport, node->hw_index, 13265 sched_modes[sched_mode], weight)); 13266 13267 if (index == 0) { 13268 l1index = 3; 13269 l1_max = 4; 13270 } else if(index == 1) { 13271 l1index = 5; 13272 l1_max = 5; 13273 } else { 13274 l1index = 6; 13275 l1_max = 6; 13276 } 13277 for(; l1index <= l1_max; l1index++) { 13278 node = &port_info->sched[l1index]; 13279 BCM_IF_ERROR_RETURN( 13280 _bcm_hx5_cosq_sched_mode_setget(unit, port, node->level, l1index, 13281 &sched_mode, &weight, 0, 0)); 13282 LOG_CLI((BSL_META_U(unit, 13283 " L1.%d: GPORT=0x%x HW_INDEX=%d MODE=%s WT=%d\n"), 13284 l1index - 3, node->gport, node->hw_index, 13285 sched_modes[sched_mode], weight)); 13286 13287 if (index == 0) { 13288 if (l1index == 3) { 13289 l2index = 7; 13290 l2_max = l2index + 8; 13291 l3index = 8; 13292 l3_max = l3index + 8; 13293 } else if(l1index == 4) { 13294 l2index = 15; 13295 l2_max = l2index + 8; 13296 l3index = 16; 13297 l3_max = l3index + 8; 13298 } 13299 } else if (index == 1) { 13300 l2index = 23; 13301 l2_max = l2index + 8; 13302 l3index = 16; 13303 l3_max = l3index + 8; 13304 } else { 13305 l2index = 31; 13306 l2_max = l2index + 2; 13307 l3index = 24; 13308 l3_max = l3index + 2; 13309 } 13310 13311 13312 for (; l2index < l2_max && l3index < l3_max; l2index++, l3index++) { 13313 node = &port_info->sched[l2index]; 13314 BCM_IF_ERROR_RETURN( 13315 _bcm_hx5_cosq_sched_mode_setget(unit, port, node->level, l2index, 13316 &sched_mode, &weight, 0, 0)); 13317 LOG_CLI((BSL_META_U(unit, 13318 " L2.%d: GPORT=0x%x HW_INDEX=%d MODE=%s WT=%d\n"), 13319 l2index - 7, node->gport, node->hw_index, 13320 sched_modes[sched_mode], weight)); 13321 13322 /* UC Queue */ 13323 node = &port_info->ucast[l3index]; 13324 BCM_IF_ERROR_RETURN( 13325 _bcm_hx5_cosq_sched_mode_setget(unit, port, node->level, l3index, 13326 &sched_mode, &weight, 0, 0)); 13327 LOG_CLI((BSL_META_U(unit, 13328 " UC.%d: GPORT=0x%x HW_INDEX=%d MODE=%s WT=%d\n"), 13329 l3index, node->gport, node->hw_index, 13330 sched_modes[sched_mode], weight)); 13331 13332 /* MC Queue */ 13333 node = &port_info->mcast[l3index]; 13334 BCM_IF_ERROR_RETURN( 13335 _bcm_hx5_cosq_sched_mode_setget(unit, port, node->level, l3index, 13336 &sched_mode, &weight, 1, 0)); 13337 LOG_CLI((BSL_META_U(unit, 13338 " MC.%d: GPORT=0x%x HW_INDEX=%d MODE=%s WT=%d\n"), 13339 l3index, node->gport, node->hw_index, 13340 sched_modes[sched_mode], weight)); 13341 } 13342 } 13343 } 13344 LOG_CLI((BSL_META_U(unit, 13345 "=========== \n"))); 13346 13347 return BCM_E_NONE; 13348 } 13349 13350 STATIC int 13351 _bcm_hx5_cosq_port_info_dump(int unit, bcm_port_t port) 13352 { 13353 _bcm_hx5_cosq_port_info_t *port_info; 13354 _bcm_hx5_cosq_node_t *node; 13355 int index = 0, empty; 13356 int l1index, l2index, l3index; 13357 soc_hx5_sched_mode_e sched_mode = 0; 13358 int weight = 0, port_index; 13359 char *sched_modes[] = {"X", "SP", "WRR", "WERR"}; 13360 int phy_port, mmu_port; 13361 soc_info_t *si = &SOC_INFO(unit); 13362 13363 13364 phy_port = si->port_l2p_mapping[port]; 13365 mmu_port = si->port_p2m_mapping[phy_port]; 13366 _HX5_PORT_INDEX_GET(unit, mmu_port, port_index); 13367 13368 if (!SOC_PORT_VALID(unit, port)) { 13369 return BCM_E_PORT; 13370 } 13371 port_info = &_bcm_hx5_cosq_port_info[unit][port_index]; 13372 13373 empty = TRUE; 13374 for (index = 0; index < SOC_HX5_NUM_SCHEDULER_PER_PORT; index++) { 13375 if (port_info->sched[index].numq > 0) { 13376 empty = FALSE; 13377 break; 13378 } 13379 } 13380 if (empty) { 13381 for (index = 0; index < SOC_HX5_NUM_UCAST_QUEUE_PER_PORT; index++) { 13382 if (port_info->ucast[index].numq > 0) { 13383 empty = FALSE; 13384 break; 13385 } 13386 } 13387 } 13388 if (empty) { 13389 for (index = 0; index < SOC_HX5_NUM_MCAST_QUEUE_PER_PORT; index++) { 13390 if (port_info->mcast[index].numq > 0) { 13391 empty = FALSE; 13392 break; 13393 } 13394 } 13395 } 13396 13397 if (empty == TRUE) { 13398 return BCM_E_NOT_FOUND; 13399 } 13400 13401 LOG_CLI((BSL_META_U(unit, 13402 "=== PORT %d\n"), port)); 13403 13404 node = &port_info->sched[index]; 13405 13406 BCM_IF_ERROR_RETURN( 13407 _bcm_hx5_cosq_sched_mode_setget(unit, port, node->level, index, 13408 &sched_mode, &weight, 0, 0)); 13409 LOG_CLI((BSL_META_U(unit, 13410 "L0.%d: GPORT=0x%x HW_INDEX=%d MODE=%s WT=%d\n"), 13411 index, node->gport, node->hw_index, 13412 sched_modes[sched_mode], weight)); 13413 13414 for (l1index = 1; l1index < 3; l1index++) { 13415 /* Node */ 13416 node = &port_info->sched[l1index]; 13417 13418 BCM_IF_ERROR_RETURN( 13419 _bcm_hx5_cosq_sched_mode_setget(unit, port, node->level, l1index, 13420 &sched_mode, &weight, 0, 0)); 13421 LOG_CLI((BSL_META_U(unit, 13422 " L1.%d: GPORT=0x%x HW_INDEX=%d MODE=%s WT=%d\n"), 13423 l1index - 1, node->gport, node->hw_index, 13424 sched_modes[sched_mode], weight)); 13425 13426 l2index = ((l1index - 1) * 8) + 3; 13427 l3index = ((l1index - 1) * 8); 13428 13429 for (; l2index < ((l1index - 1) * 8) + 11 && l3index < ((l1index - 1) * 8) + 8; l2index++, l3index++) { 13430 node = &port_info->sched[l2index]; 13431 13432 BCM_IF_ERROR_RETURN( 13433 _bcm_hx5_cosq_sched_mode_setget(unit, port, node->level, l2index, 13434 &sched_mode, &weight, 0, 0)); 13435 LOG_CLI((BSL_META_U(unit, 13436 " L2.%d: GPORT=0x%x HW_INDEX=%d MODE=%s WT=%d\n"), 13437 l2index - 3, node->gport, node->hw_index, 13438 sched_modes[sched_mode], weight)); 13439 13440 /* UC Queue */ 13441 node = &port_info->ucast[l3index]; 13442 BCM_IF_ERROR_RETURN( 13443 _bcm_hx5_cosq_sched_mode_setget(unit, port, node->level, l3index, 13444 &sched_mode, &weight, 0, 0)); 13445 LOG_CLI((BSL_META_U(unit, 13446 " UC.%d: GPORT=0x%x HW_INDEX=%d MODE=%s WT=%d\n"), 13447 l3index, node->gport, node->hw_index, 13448 sched_modes[sched_mode], weight)); 13449 13450 /* MC Queue */ 13451 node = &port_info->mcast[l3index]; 13452 BCM_IF_ERROR_RETURN( 13453 _bcm_hx5_cosq_sched_mode_setget(unit, port, node->level, l3index, 13454 &sched_mode, &weight, 1, 0)); 13455 LOG_CLI((BSL_META_U(unit, 13456 " MC.%d: GPORT=0x%x HW_INDEX=%d MODE=%s WT=%d\n"), 13457 l3index, node->gport, node->hw_index, 13458 sched_modes[sched_mode], weight)); 13459 } 13460 } 13461 LOG_CLI((BSL_META_U(unit, 13462 "=========== \n"))); 13463 13464 return BCM_E_NONE; 13465 } 13466 13467 int 13468 bcm_hx5_dump_port_hsp(int unit, int port) 13469 { 13470 int phy_port, mmu_port; 13471 soc_info_t *si = &SOC_INFO(unit); 13472 LOG_CLI((BSL_META_U(unit, 13473 "\nSW Information COSQ - Unit %d\n"), unit)); 13474 if (!IS_FAE_PORT(unit, port) && !IS_LB_PORT(unit, port)) { 13475 phy_port = si->port_l2p_mapping[port]; 13476 mmu_port = si->port_p2m_mapping[phy_port]; 13477 if (IS_CPU_PORT(unit, port)) { 13478 (void)_bcm_hx5_cosq_cpu_port_info_dump(unit); 13479 } 13480 if(_HX5_IS_ST_PORT(unit, mmu_port)) { 13481 (void)_bcm_hx5_cosq_st_port_info_dump(unit, port); 13482 } else { 13483 (void)_bcm_hx5_cosq_port_info_dump(unit, port); 13484 } 13485 } 13486 return BCM_E_NONE; 13487 } 13488 /* 13489 * Function: 13490 * bcm_hx5_cosq_sw_dump 13491 * Purpose: 13492 * Displays COS Queue information maintained by software. 13493 * Parameters: 13494 * unit - Device unit number 13495 * Returns: 13496 * None 13497 */ 13498 void 13499 bcm_hx5_cosq_sw_dump(int unit) 13500 { 13501 bcm_port_t port; 13502 int phy_port, mmu_port; 13503 soc_info_t *si = &SOC_INFO(unit); 13504 LOG_CLI((BSL_META_U(unit, 13505 "\nSW Information COSQ - Unit %d\n"), unit)); 13506 13507 PBMP_ALL_ITER(unit, port) { 13508 phy_port = si->port_l2p_mapping[port]; 13509 mmu_port = si->port_p2m_mapping[phy_port]; 13510 if (IS_CPU_PORT(unit, port)) { 13511 (void)_bcm_hx5_cosq_cpu_port_info_dump(unit); 13512 } 13513 if(_HX5_IS_ST_PORT(unit, mmu_port)) { 13514 (void)_bcm_hx5_cosq_st_port_info_dump(unit, port); 13515 } else { 13516 (void)_bcm_hx5_cosq_port_info_dump(unit, port); 13517 } 13518 } 13519 return; 13520 } 13521 13522 int 13523 bcm_hx5_hgcos_select_port_control_set(int unit, bcm_port_t port, 13524 bcm_port_control_t type, int value) 13525 { 13526 soc_info_t *si; 13527 int phy_port, mmu_port; 13528 uint64 rval64, rval64_tmp, rval64_reset_tmp; 13529 uint32 rval; 13530 soc_reg_t reg = UC_HG_QUEUE_MODEr; 13531 soc_field_t field = QUEUE_MODEf; 13532 soc_reg_t reg1 = COS_MODE_SPLIT0r; 13533 si = &SOC_INFO(unit); 13534 phy_port = si->port_l2p_mapping[port]; 13535 mmu_port = si->port_p2m_mapping[phy_port]; 13536 13537 if ((value < 0) || (value > 1)) { 13538 return BCM_E_PARAM; 13539 } 13540 COMPILER_64_ZERO(rval64); 13541 COMPILER_64_ZERO(rval64_tmp); 13542 COMPILER_64_ZERO(rval64_reset_tmp); 13543 13544 if (IS_CPU_PORT(unit, port) || IS_LB_PORT(unit, port) || 13545 IS_FAE_PORT(unit, port) || !_HX5_IS_ST_PORT(unit, mmu_port)) { 13546 return BCM_E_PARAM; 13547 } 13548 BCM_IF_ERROR_RETURN 13549 (soc_reg32_get(unit, reg, port, 0, &rval)); 13550 13551 soc_reg_field_set(unit, reg, &rval, field, value); 13552 13553 BCM_IF_ERROR_RETURN 13554 (soc_reg32_set(unit, reg, port, 0, rval)); 13555 13556 SOC_IF_ERROR_RETURN 13557 (soc_trident3_xpe_reg_get(unit, reg1, -1, si->port_pipe[port], 13558 0, &rval64)); 13559 COMPILER_64_SET(rval64_tmp, 0, (2 << (mmu_port * 2))); 13560 COMPILER_64_SET(rval64_reset_tmp, 0, (3 << (mmu_port * 2))); 13561 13562 if (value) { 13563 COMPILER_64_OR(rval64, rval64_tmp); 13564 } else { 13565 COMPILER_64_NOT(rval64_reset_tmp); 13566 COMPILER_64_AND(rval64, rval64_reset_tmp); 13567 13568 } 13569 SOC_IF_ERROR_RETURN 13570 (soc_trident3_xpe_reg_set(unit, reg1, -1, si->port_pipe[port], 13571 0, rval64)); 13572 return BCM_E_NONE; 13573 } 13574 13575 int 13576 bcm_hx5_hgcos_select_port_control_get(int unit, bcm_port_t port, 13577 bcm_port_control_t type, int *value) 13578 { 13579 soc_info_t *si; 13580 int phy_port, mmu_port; 13581 uint32 rval; 13582 soc_reg_t reg = UC_HG_QUEUE_MODEr; 13583 soc_field_t field = QUEUE_MODEf; 13584 si = &SOC_INFO(unit); 13585 phy_port = si->port_l2p_mapping[port]; 13586 mmu_port = si->port_p2m_mapping[phy_port]; 13587 13588 if (IS_CPU_PORT(unit, port) || IS_LB_PORT(unit, port) || 13589 IS_FAE_PORT(unit, port) || !_HX5_IS_ST_PORT(unit, mmu_port)) { 13590 return BCM_E_PARAM; 13591 } 13592 13593 BCM_IF_ERROR_RETURN 13594 (soc_reg32_get(unit, reg, port, 0, &rval)); 13595 13596 *value = soc_reg_field_get(unit, reg, rval, field); 13597 13598 return BCM_E_NONE; 13599 } 13600 13601 int 13602 bcm_hx5_cosq_gport_info_get(int unit, bcm_gport_t gport, 13603 bcm_cosq_gport_level_info_t *info) 13604 { 13605 13606 int phy_port, mmu_port, local_port; 13607 _bcm_hx5_cosq_node_t *node = NULL; 13608 soc_info_t *si; 13609 13610 if( NULL == info ) { 13611 return BCM_E_PARAM; 13612 } 13613 13614 if (!BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) && 13615 !BCM_GPORT_IS_SCHEDULER(gport) && 13616 !BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 13617 return BCM_E_PARAM; 13618 } 13619 13620 BCM_IF_ERROR_RETURN 13621 (_bcm_hx5_cosq_node_get(unit, gport, NULL, 13622 &local_port, NULL, &node)); 13623 13624 si = &SOC_INFO(unit); 13625 phy_port = si->port_l2p_mapping[local_port]; 13626 mmu_port = si->port_p2m_mapping[phy_port]; 13627 13628 info->parent_port_type = (mmu_port < 16) ? BCM_COSQ_UPLINK_GPORT : BCM_COSQ_DOWNLINK_GPORT; 13629 info->level = node->level; 13630 13631 return BCM_E_NONE; 13632 } 13633 /* Routine to perform Inverse mapping for given Queue port back to Port/Priority 13634 * which was defined by default or through cosq_mapping_set functions 13635 */ 13636 int 13637 _bcm_hx5_cosq_inv_mapping_get(int unit, bcm_gport_t gport, 13638 bcm_cos_queue_t cosq, 13639 uint32 flags, bcm_port_t *ing_port, 13640 bcm_cos_t *priority) 13641 { 13642 bcm_port_t local_port; 13643 cos_map_sel_entry_t cos_map_sel_entry; 13644 void *entries[1]; 13645 int index, ii; 13646 bcm_cos_queue_t in_cosq = BCM_COS_INVALID, pri_cosq = BCM_COS_INVALID; 13647 bcm_module_t modid; 13648 soc_field_t cos_field = INVALIDf; 13649 port_cos_map_entry_t cos_map_entries[_HX5_MMU_NUM_INT_PRI]; 13650 13651 if ((flags != BCM_COSQ_GPORT_UCAST_QUEUE_GROUP) && 13652 (flags != BCM_COSQ_GPORT_MCAST_QUEUE_GROUP)) { 13653 return BCM_E_PARAM; 13654 } 13655 13656 if ((ing_port == NULL) || (priority == NULL)) { 13657 return BCM_E_PARAM; 13658 } 13659 13660 if (BCM_GPORT_IS_SET(gport)) { 13661 if (!(BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) && 13662 !(BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport))) { 13663 return BCM_E_PARAM; 13664 } 13665 BCM_IF_ERROR_RETURN 13666 (_bcm_hx5_cosq_node_get(unit, gport, &modid, &local_port, 13667 &in_cosq, NULL)); 13668 } else { 13669 BCM_IF_ERROR_RETURN 13670 (_bcm_hx5_cosq_localport_resolve(unit, gport, &local_port)); 13671 in_cosq = cosq; 13672 } 13673 13674 if ((cosq < -1) || (cosq >= _HX5_PORT_NUM_COS(unit, local_port))) { 13675 return BCM_E_PARAM; 13676 } 13677 13678 if ((IS_CPU_PORT(unit, local_port)) || (IS_LB_PORT(unit, local_port))) { 13679 return BCM_E_PARAM; 13680 } 13681 13682 *ing_port = local_port; 13683 13684 if (flags == BCM_COSQ_GPORT_MCAST_QUEUE_GROUP) { 13685 cos_field = MC_COS1f; 13686 } else { 13687 cos_field = UC_COS1f; 13688 } 13689 13690 if (in_cosq == BCM_COS_INVALID) { 13691 return BCM_E_PARAM; 13692 } else { 13693 in_cosq %= _BCM_HX5_NUM_PFC_CLASS; 13694 } 13695 13696 entries[0] = &cos_map_entries; 13697 BCM_IF_ERROR_RETURN 13698 (READ_COS_MAP_SELm(unit, MEM_BLOCK_ANY, local_port, 13699 &cos_map_sel_entry)); 13700 index = soc_mem_field32_get(unit, COS_MAP_SELm, &cos_map_sel_entry, 13701 SELECTf); 13702 index *= _HX5_MMU_NUM_INT_PRI; 13703 13704 BCM_IF_ERROR_RETURN 13705 (soc_profile_mem_get(unit, _bcm_hx5_cos_map_profile[unit], 13706 index, _HX5_MMU_NUM_INT_PRI, entries)); 13707 13708 for (ii = 0; ii < _HX5_MMU_NUM_INT_PRI; ii++) { 13709 pri_cosq = soc_mem_field32_get(unit, PORT_COS_MAPm, 13710 &cos_map_entries[ii], cos_field); 13711 if (pri_cosq == in_cosq) { 13712 /* Required Cosq found. Break as the index is the priority */ 13713 *priority = ii; 13714 break; 13715 } 13716 } 13717 13718 if (ii == _HX5_MMU_NUM_INT_PRI) { 13719 /* Mapping cannot be found */ 13720 return BCM_E_NOT_FOUND; 13721 } 13722 13723 return BCM_E_NONE; 13724 } 13725 13726 int 13727 bcm_hx5_pfc_deadlock_queue_info_get(int unit, bcm_gport_t gport, 13728 bcm_port_t *mmu_port, bcm_port_t *local_port, int *type, int *split) 13729 { 13730 soc_info_t *si; 13731 int pport = 0, mport = 0, lport = 0, in_cosq = 0; 13732 bcm_module_t modid; 13733 si = &SOC_INFO(unit); 13734 13735 if ((mmu_port == NULL) || (split == NULL) || (local_port == NULL) || (type == NULL)) { 13736 return BCM_E_PARAM; 13737 } 13738 13739 if (BCM_GPORT_IS_SET(gport)) { 13740 if (!(BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) && 13741 !(BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport))) { 13742 return BCM_E_PARAM; 13743 } 13744 BCM_IF_ERROR_RETURN 13745 (_bcm_hx5_cosq_node_get(unit, gport, &modid, &lport, 13746 &in_cosq, NULL)); 13747 } 13748 pport = si->port_l2p_mapping[lport]; 13749 mport = si->port_p2m_mapping[pport]; 13750 13751 *split = (mport > 15) ? 0 : 1; 13752 *mmu_port = mport; 13753 *local_port = lport; 13754 *type = (in_cosq < 8) ? 0 : (in_cosq >= 8 && in_cosq < 16) ? 1 : 2; 13755 13756 return BCM_E_NONE; 13757 } 13758 13759 int 13760 bcm_hx5_pfc_deadlock_ignore_pfc_xoff_gen(int unit, int priority, 13761 bcm_port_t port, uint32 *rval32) 13762 { 13763 uint32 profile_index, fc_class; 13764 uint32 rval, uc_cos_bmp; 13765 uint64 rval64[16], *rval64s[1]; 13766 static const soc_reg_t port_fc_reg = PORT_LLFC_CFGr; 13767 13768 rval64s[0] = rval64; 13769 BCM_IF_ERROR_RETURN 13770 (soc_reg32_get(unit, port_fc_reg, port, 0, &rval)); 13771 profile_index = soc_reg_field_get(unit, port_fc_reg, rval, PROFILE_INDEXf) * 16; 13772 13773 BCM_IF_ERROR_RETURN 13774 (soc_profile_reg_get(unit, _bcm_hx5_prio2cos_profile[unit], 13775 profile_index, 16, rval64s)); 13776 13777 for (fc_class = 0; fc_class < _BCM_HX5_NUM_PFC_CLASS; ++fc_class ) { 13778 13779 uc_cos_bmp = soc_reg64_field32_get(unit, PRIO2COS_PROFILE_64r, rval64[fc_class], 13780 UC_COS_BMPf); 13781 if (uc_cos_bmp & (1 << priority)) { 13782 *rval32 = uc_cos_bmp; 13783 return BCM_E_NONE; 13784 } 13785 } 13786 13787 return BCM_E_NOT_FOUND; 13788 } 13789 13790 /* 13791 * Function: 13792 * bcm_hx5_pfc_deadlock_recovery_start 13793 * Purpose: 13794 * Begin recovery when a Port is deaclared to be in Deadlock by Hardware 13795 * Parameters: 13796 * unit - unit number 13797 * port - port number 13798 * priority - priority 13799 * Returns: 13800 * BCM_E_XXX 13801 */ 13802 int 13803 bcm_hx5_pfc_deadlock_recovery_start(int unit, bcm_port_t port, int priority) 13804 { 13805 int pipe, split, pos, cos = 0, index; 13806 uint32 rval = 0, uc_cos_bmp = 0; 13807 uint64 rval64, temp_mask64, temp_en64; 13808 _bcm_hx5_pfc_hw_resorces_t *hw_res = NULL; 13809 _bcm_hx5_pfc_deadlock_control_t *pfc_deadlock_control = NULL; 13810 13811 if ((priority < 0) || (priority >= HX5_PFC_DEADLOCK_MAX_COS)) { 13812 return BCM_E_PARAM; 13813 } 13814 13815 BCM_IF_ERROR_RETURN( 13816 _bcm_hx5_cosq_localport_resolve(unit, port, &port)); 13817 if (port >= MAX_PORT(unit)) { 13818 return BCM_E_PARAM; 13819 } 13820 13821 pfc_deadlock_control = _BCM_HX5_UNIT_PFC_DEADLOCK_CONTROL(unit); 13822 hw_res = &pfc_deadlock_control->hw_regs_fields; 13823 SOC_IF_ERROR_RETURN( 13824 soc_td3_mmu_bmp_reg_pos_get(unit, port, &pipe, &split, &pos)); 13825 13826 BCM_IF_ERROR_RETURN( 13827 _bcm_hx5_pfc_reg_index_get(unit, port, NULL, &index)); 13828 13829 COMPILER_64_ZERO(temp_en64); 13830 COMPILER_64_ZERO(temp_mask64); 13831 13832 if (pos < 32) { 13833 COMPILER_64_SET(temp_mask64, 0, (1 << pos)); 13834 } else { 13835 COMPILER_64_SET(temp_mask64, (1 << (pos - 32)), 0); 13836 } 13837 13838 COMPILER_64_OR(temp_en64, temp_mask64); 13839 13840 BCM_IF_ERROR_RETURN( 13841 _bcm_hx5_pfc_deadlock_hw_cos_index_get(unit, priority, &cos)); 13842 13843 /* Mask the Intr DD_TIMER_MASK by setting 1 (pbmp) */ 13844 COMPILER_64_ZERO(rval64); 13845 SOC_IF_ERROR_RETURN( 13846 soc_trident3_xpe_reg_get(unit, hw_res->timer_mask[split], -1, pipe, 13847 cos, &rval64)); 13848 COMPILER_64_OR(rval64, temp_mask64); 13849 SOC_IF_ERROR_RETURN( 13850 soc_trident3_xpe_reg_set(unit, hw_res->timer_mask[split], -1, pipe, 13851 cos, rval64)); 13852 13853 SOC_IF_ERROR_RETURN( 13854 soc_reg32_get(unit, hw_res->port_config[index], port, 0, &rval)); 13855 priority = pfc_deadlock_control->pfc_cos2pri[cos]; 13856 13857 rval = _bcm_pfc_deadlock_ignore_pfc_xoff_gen(unit, priority, port, 13858 &uc_cos_bmp); 13859 if (rval != BCM_E_NONE) { 13860 rval = 0; 13861 rval |= (1 << priority); 13862 } else { 13863 rval = 0; 13864 rval |= uc_cos_bmp; 13865 } 13866 13867 SOC_IF_ERROR_RETURN( 13868 soc_reg32_set(unit, hw_res->port_config[index], port, 0, rval)); 13869 13870 return BCM_E_NONE; 13871 } 13872 13873 /* 13874 * Function: 13875 * bcm_hx5_pfc_deadlock_recovery_exit 13876 * Purpose: 13877 * Reset recovery state of a port and config port back in original state 13878 * Parameters: 13879 * unit - unit number 13880 * port - port number 13881 * priority - priority 13882 * Returns: 13883 * BCM_E_XXX 13884 */ 13885 int 13886 bcm_hx5_pfc_deadlock_recovery_exit(int unit, bcm_port_t port, int priority) 13887 { 13888 int pipe, split, pos, cos = 0, index; 13889 uint32 rval = 0, uc_cos_bmp = 0; 13890 uint64 rval64, temp_mask64, temp_en64; 13891 _bcm_hx5_pfc_hw_resorces_t *hw_res = NULL; 13892 _bcm_hx5_pfc_deadlock_control_t *pfc_deadlock_control = NULL; 13893 13894 if ((priority < 0) || (priority >= HX5_PFC_DEADLOCK_MAX_COS)) { 13895 return BCM_E_PARAM; 13896 } 13897 13898 BCM_IF_ERROR_RETURN( 13899 _bcm_hx5_cosq_localport_resolve(unit, port, &port)); 13900 if (port >= MAX_PORT(unit)) { 13901 return BCM_E_PARAM; 13902 } 13903 13904 pfc_deadlock_control = _BCM_HX5_UNIT_PFC_DEADLOCK_CONTROL(unit); 13905 hw_res = &pfc_deadlock_control->hw_regs_fields; 13906 SOC_IF_ERROR_RETURN( 13907 soc_td3_mmu_bmp_reg_pos_get(unit, port, &pipe, &split, &pos)); 13908 13909 COMPILER_64_ZERO(temp_en64); 13910 COMPILER_64_ZERO(temp_mask64); 13911 13912 if (pos < 32) { 13913 COMPILER_64_SET(temp_mask64, 0, (1 << pos)); 13914 } else { 13915 COMPILER_64_SET(temp_mask64, (1 << (pos - 32)), 0); 13916 } 13917 13918 COMPILER_64_OR(temp_en64, temp_mask64); 13919 13920 BCM_IF_ERROR_RETURN( 13921 _bcm_hx5_pfc_deadlock_hw_cos_index_get(unit, priority, &cos)); 13922 13923 BCM_IF_ERROR_RETURN( 13924 _bcm_hx5_pfc_reg_index_get(unit, port, NULL, &index)); 13925 /* For that port, set ignore_pfc_xoff = 0 (per port reg) */ 13926 SOC_IF_ERROR_RETURN( 13927 soc_reg32_get(unit, hw_res->port_config[index], port, 0, &rval)); 13928 13929 rval = _bcm_pfc_deadlock_ignore_pfc_xoff_gen(unit, priority, port, 13930 &uc_cos_bmp); 13931 if (rval != BCM_E_NONE) { 13932 rval = 0; 13933 rval &= ~(1 << priority); 13934 } else { 13935 rval = 0; 13936 rval &= ~uc_cos_bmp; 13937 } 13938 13939 SOC_IF_ERROR_RETURN( 13940 soc_reg32_set(unit, hw_res->port_config[index], port, 0, rval)); 13941 13942 /* Mask the Intr DD_TIMER_MASK by setting 0 (pbmp) */ 13943 COMPILER_64_ZERO(rval64); 13944 SOC_IF_ERROR_RETURN( 13945 soc_trident3_xpe_reg_get(unit, hw_res->timer_mask[split], -1, pipe, 13946 cos, &rval64)); 13947 COMPILER_64_NOT(temp_mask64); 13948 COMPILER_64_AND(rval64, temp_mask64); 13949 SOC_IF_ERROR_RETURN( 13950 soc_trident3_xpe_reg_set(unit, hw_res->timer_mask[split], -1, pipe, 13951 cos, rval64)); 13952 13953 /* Turn timer on DD_TIMER_ENABLE by setting 1 (pbmp) */ 13954 COMPILER_64_ZERO(rval64); 13955 SOC_IF_ERROR_RETURN( 13956 soc_trident3_xpe_reg_get(unit, hw_res->timer_en[split], -1, pipe, 13957 cos, &rval64)); 13958 COMPILER_64_OR(rval64, temp_en64); 13959 SOC_IF_ERROR_RETURN( 13960 soc_trident3_xpe_reg_set(unit, hw_res->timer_en[split], -1, pipe, 13961 cos, rval64)); 13962 13963 return BCM_E_NONE; 13964 } 13965 13966 13967 13968 /* Function: 13969 * bcmi_hx5_port_cosmap_update 13970 * Purpose: 13971 * called during flexport during port attach/detach 13972 * to update the cos_map profile for the port 13973 * Parameters: 13974 * unit - unit number 13975 * port - port number 13976 * enable - add/delete 13977 * Returns: 13978 * BCM_E_XXX 13979 */ 13980 13981 int 13982 bcmi_hx5_port_cosmap_update(int unit, pbmp_t pbm, int enable) 13983 { 13984 port_cos_map_entry_t cos_map_entries[16]; 13985 cos_map_sel_entry_t cos_map_sel_entry; 13986 void *entries[1]; 13987 uint32 index, old_index; 13988 bcm_port_t port; 13989 int cos, prio, numq, rv; 13990 soc_mem_t mem = PORT_COS_MAPm; 13991 uint32 i; 13992 13993 numq = _BCM_HX5_NUM_COS(unit); 13994 13995 SOC_PBMP_ITER(pbm, port) { 13996 prio = 0; 13997 sal_memset(cos_map_entries, 0, sizeof(cos_map_entries)); 13998 entries[0] = &cos_map_entries; 13999 14000 if (enable) { 14001 /* 14002 * Distribute first 8 internal priority levels into the specified number 14003 * of cosq, map remaining internal priority levels to highest priority 14004 * cosq 14005 */ 14006 sal_memset(cos_map_entries, 0, sizeof(cos_map_entries)); 14007 entries[0] = &cos_map_entries; 14008 14009 for (cos = 0; cos < numq; cos++) { 14010 for (i = 8 / numq + (cos < 8 % numq ? 1 : 0); i > 0; i--) { 14011 soc_mem_field32_set(unit, mem, &cos_map_entries[prio], 14012 UC_COS1f, cos); 14013 soc_mem_field32_set(unit, mem, &cos_map_entries[prio], 14014 MC_COS1f, cos); 14015 soc_mem_field32_set(unit, mem, &cos_map_entries[prio], 14016 HG_COSf, _HX5_NUM_COS_MAP_ENTRY + cos); 14017 prio++; 14018 } 14019 } 14020 for (prio = 8; prio < 16; prio++) { 14021 soc_mem_field32_set(unit, mem, &cos_map_entries[prio], UC_COS1f, 14022 numq - 1); 14023 soc_mem_field32_set(unit, mem, &cos_map_entries[prio], MC_COS1f, 14024 numq - 1); 14025 soc_mem_field32_set(unit, mem, &cos_map_entries[prio], HG_COSf, 14026 _HX5_NUM_COS_MAP_ENTRY + (numq - 1)); 14027 } 14028 14029 SOC_IF_ERROR_RETURN 14030 (soc_profile_mem_add(unit, _bcm_hx5_cos_map_profile[unit], entries, 16, 14031 &index)); 14032 BCM_IF_ERROR_RETURN(bcm_hx5_wireless_cos_map_update(unit, numq)); 14033 BCM_IF_ERROR_RETURN 14034 (soc_mem_field32_modify(unit, COS_MAP_SELm, port, SELECTf, 14035 index / 16)); 14036 14037 } else { 14038 BCM_IF_ERROR_RETURN 14039 (READ_COS_MAP_SELm(unit, MEM_BLOCK_ANY, port, &cos_map_sel_entry)); 14040 old_index = soc_mem_field32_get(unit, COS_MAP_SELm, &cos_map_sel_entry, 14041 SELECTf); 14042 old_index *= 16; 14043 14044 rv = soc_profile_mem_delete(unit, _bcm_hx5_cos_map_profile[unit], 14045 old_index); 14046 14047 if (BCM_FAILURE(rv)) { 14048 return rv; 14049 } 14050 } 14051 } 14052 return BCM_E_NONE; 14053 } 14054 14055 /* 14056 * Function: 14057 * bcm_cosq_gport_traverse_by_port 14058 * Purpose: 14059 * Walks through the valid COSQ GPORTs belong to a port and calls 14060 * the user supplied callback function for each entry. 14061 * Parameters: 14062 * unit - (IN) unit number 14063 * port - (IN) port number or GPORT identifier 14064 * trav_fn - (IN) Callback function. 14065 * user_data - (IN) User data to be passed to callback function 14066 * Returns: 14067 * BCM_E_NONE - Success. 14068 * BCM_E_XXX 14069 */ 14070 14071 int 14072 bcm_hx5_cosq_gport_traverse_by_port(int unit, bcm_gport_t port, 14073 bcm_cosq_gport_traverse_cb cb, 14074 void *user_data) 14075 { 14076 _bcm_hx5_cosq_port_info_t *port_info = NULL; 14077 _bcm_hx5_cosq_st_port_info_t *stport_info = NULL; 14078 _bcm_hx5_cosq_cpu_port_info_t *cpu_port_info = NULL; 14079 bcm_module_t my_modid, modid_out; 14080 bcm_port_t port_out, local_port; 14081 bcm_gport_t gport; 14082 int id, rv = SOC_E_NONE; 14083 int phy_port, mmu_port, index; 14084 14085 soc_info_t *si = &SOC_INFO(unit); 14086 14087 if (_bcm_hx5_cosq_port_info[unit] == NULL) { 14088 return BCM_E_INIT; 14089 } 14090 if (_bcm_hx5_cosq_st_port_info[unit] == NULL) { 14091 return BCM_E_INIT; 14092 } 14093 if (_bcm_hx5_cosq_cpu_port_info[unit] == NULL) { 14094 return BCM_E_INIT; 14095 } 14096 14097 if (BCM_GPORT_IS_SET(port) && 14098 (!BCM_GPORT_IS_LOCAL(port) && 14099 !BCM_GPORT_IS_DEVPORT(port) && 14100 !BCM_GPORT_IS_MODPORT(port))) { 14101 LOG_ERROR(BSL_LS_BCM_COSQ, (BSL_META_U(unit, 14102 "Invalid gport type\n"))); 14103 return BCM_E_PARAM; 14104 } 14105 14106 BCM_IF_ERROR_RETURN 14107 (_bcm_hx5_cosq_localport_resolve(unit, port, &local_port)); 14108 14109 14110 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_modid)); 14111 BCM_IF_ERROR_RETURN 14112 (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, my_modid, port, 14113 &modid_out, &port_out)); 14114 BCM_GPORT_MODPORT_SET(gport, modid_out, port_out); 14115 14116 phy_port = si->port_l2p_mapping[local_port]; 14117 mmu_port = si->port_p2m_mapping[phy_port]; 14118 _HX5_PORT_INDEX_GET(unit, mmu_port, index); 14119 if (IS_CPU_PORT(unit, local_port)) { 14120 cpu_port_info = _bcm_hx5_cosq_cpu_port_info[unit]; 14121 } else { 14122 if(_HX5_IS_ST_PORT(unit, mmu_port)) { 14123 stport_info = &_bcm_hx5_cosq_st_port_info[unit][index]; 14124 }else { 14125 port_info = &_bcm_hx5_cosq_port_info[unit][index]; 14126 } 14127 } 14128 14129 if (!IS_CPU_PORT(unit, local_port) && !_HX5_IS_ST_PORT(unit, mmu_port)) { 14130 for (id = 0; id < SOC_HX5_NUM_UCAST_QUEUE_PER_PORT; id++) { 14131 if (port_info->ucast[id].numq == 0) { 14132 continue; 14133 } 14134 rv = cb(unit, gport, port_info->ucast[id].numq, 14135 BCM_COSQ_GPORT_UCAST_QUEUE_GROUP, 14136 port_info->ucast[id].gport, user_data); 14137 } 14138 #ifdef BCM_CB_ABORT_ON_ERR 14139 if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) { 14140 return rv; 14141 } 14142 #else 14143 rv = BCM_E_NONE; 14144 #endif 14145 } 14146 14147 if (!IS_CPU_PORT(unit, local_port) && _HX5_IS_ST_PORT(unit, mmu_port)) { 14148 for (id = 0; id < SOC_HX5_NUM_UCAST_QUEUE_PER_ST_PORT; id++) { 14149 if (stport_info->ucast[id].numq == 0) { 14150 continue; 14151 } 14152 rv = cb(unit, gport, stport_info->ucast[id].numq, 14153 BCM_COSQ_GPORT_UCAST_QUEUE_GROUP, 14154 stport_info->ucast[id].gport, user_data); 14155 } 14156 #ifdef BCM_CB_ABORT_ON_ERR 14157 if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) { 14158 return rv; 14159 } 14160 #else 14161 rv = BCM_E_NONE; 14162 #endif 14163 } 14164 14165 if (IS_CPU_PORT(unit, local_port)) { 14166 for (id = 0; id < SOC_HX5_NUM_CPU_QUEUES; id++) { 14167 if (cpu_port_info->mcast[id].numq == 0) { 14168 continue; 14169 } 14170 rv = cb(unit, gport, cpu_port_info->mcast[id].numq, 14171 BCM_COSQ_GPORT_MCAST_QUEUE_GROUP, 14172 cpu_port_info->mcast[id].gport, user_data); 14173 #ifdef BCM_CB_ABORT_ON_ERR 14174 if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) { 14175 return rv; 14176 } 14177 #else 14178 rv = BCM_E_NONE; 14179 #endif 14180 } 14181 } 14182 14183 if (!IS_CPU_PORT(unit, local_port) && !_HX5_IS_ST_PORT(unit, mmu_port)) { 14184 for (id = 0; id < SOC_HX5_NUM_MCAST_QUEUE_PER_PORT; id++) { 14185 if (port_info->mcast[id].numq == 0) { 14186 continue; 14187 } 14188 rv = cb(unit, gport, port_info->mcast[id].numq, 14189 BCM_COSQ_GPORT_MCAST_QUEUE_GROUP, 14190 port_info->mcast[id].gport, user_data); 14191 } 14192 #ifdef BCM_CB_ABORT_ON_ERR 14193 if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) { 14194 return rv; 14195 } 14196 #else 14197 rv = BCM_E_NONE; 14198 #endif 14199 } 14200 14201 14202 if (!IS_CPU_PORT(unit, local_port) && _HX5_IS_ST_PORT(unit, mmu_port)) { 14203 for (id = 0; id < SOC_HX5_NUM_MCAST_QUEUE_PER_ST_PORT; id++) { 14204 if (stport_info->mcast[id].numq == 0) { 14205 continue; 14206 } 14207 rv = cb(unit, gport, stport_info->mcast[id].numq, 14208 BCM_COSQ_GPORT_MCAST_QUEUE_GROUP, 14209 stport_info->mcast[id].gport, user_data); 14210 } 14211 #ifdef BCM_CB_ABORT_ON_ERR 14212 if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) { 14213 return rv; 14214 } 14215 #else 14216 rv = BCM_E_NONE; 14217 #endif 14218 } 14219 14220 14221 if (IS_CPU_PORT(unit, local_port)) { 14222 for (id = 0; id < SOC_HX5_NUM_SCHEDULER_PER_CPU_PORT; id++) { 14223 if (cpu_port_info->sched[id].numq == 0) { 14224 continue; 14225 } 14226 rv = cb(unit, gport, cpu_port_info->sched[id].numq, 14227 BCM_COSQ_GPORT_SCHEDULER, 14228 cpu_port_info->sched[id].gport, user_data); 14229 #ifdef BCM_CB_ABORT_ON_ERR 14230 if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) { 14231 return rv; 14232 } 14233 #else 14234 rv = BCM_E_NONE; 14235 #endif 14236 } 14237 } 14238 14239 if (!IS_CPU_PORT(unit, local_port) && !_HX5_IS_ST_PORT(unit, mmu_port)) { 14240 for (id = 0; id < SOC_HX5_NUM_SCHEDULER_PER_PORT; id++) { 14241 if (port_info->sched[id].numq == 0) { 14242 continue; 14243 } 14244 rv = cb(unit, gport, port_info->sched[id].numq, 14245 BCM_COSQ_GPORT_SCHEDULER, 14246 port_info->sched[id].gport, user_data); 14247 } 14248 #ifdef BCM_CB_ABORT_ON_ERR 14249 if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) { 14250 return rv; 14251 } 14252 #else 14253 rv = BCM_E_NONE; 14254 #endif 14255 } 14256 14257 14258 if (!IS_CPU_PORT(unit, local_port) && _HX5_IS_ST_PORT(unit, mmu_port)) { 14259 for (id = 0; id < SOC_HX5_NUM_SCHEDULER_PER_ST_PORT; id++) { 14260 if (stport_info->sched[id].numq == 0) { 14261 continue; 14262 } 14263 rv = cb(unit, gport, stport_info->sched[id].numq, 14264 BCM_COSQ_GPORT_SCHEDULER, 14265 stport_info->sched[id].gport, user_data); 14266 } 14267 #ifdef BCM_CB_ABORT_ON_ERR 14268 if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) { 14269 return rv; 14270 } 14271 #else 14272 rv = BCM_E_NONE; 14273 #endif 14274 } 14275 14276 return rv; 14277 14278 } 14279 #endif /* BCM_HELIX5_SUPPORT */