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