cosq.c (748605B)
1 2 /* 3 * 4 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 5 * 6 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 7 * 8 * COS Queue Management 9 * Purpose: API to set different cosq, priorities, and scheduler registers. 10 */ 11 #include <shared/bsl.h> 12 #include <soc/defs.h> 13 #include <sal/core/libc.h> 14 #if defined(BCM_TRIDENT2_SUPPORT) 15 #include <soc/drv.h> 16 #include <soc/scache.h> 17 #include <soc/profile_mem.h> 18 #include <soc/l3x.h> 19 #include <soc/macutil.h> 20 21 #include <soc/esw/portctrl.h> 22 #include <soc/trident2.h> 23 #include <soc/td2_td2p.h> 24 25 #include <bcm/error.h> 26 #include <bcm/cosq.h> 27 #include <bcm_int/esw/mbcm.h> 28 #include <bcm_int/esw/stack.h> 29 #include <bcm_int/esw/cosq.h> 30 #include <bcm_int/esw/rx.h> 31 #include <bcm_int/esw/virtual.h> 32 #include <bcm_int/esw/trident2.h> 33 #include <bcm_int/esw/trident2plus.h> 34 #include <bcm_int/esw/subport.h> 35 #include <bcm_int/esw/xgs5.h> 36 #include <bcm_int/esw/trx.h> 37 38 #include <bcm_int/esw_dispatch.h> 39 40 #include <bcm_int/bst.h> 41 42 #ifdef BCM_WARM_BOOT_SUPPORT 43 #include <bcm_int/esw/switch.h> 44 #endif /* BCM_WARM_BOOT_SUPPORT */ 45 46 #define TD2_CELL_FIELD_MAX 0x1ffff 47 48 /* MMU cell size in bytes */ 49 #define _BCM_TD2_BYTES_PER_CELL 208 /* bytes */ 50 #define _BCM_TD2_BYTES_TO_CELLS(_byte_) \ 51 (((_byte_) + _BCM_TD2_BYTES_PER_CELL - 1) / _BCM_TD2_BYTES_PER_CELL) 52 53 #define _BCM_TD2_NUM_PORT_SCHEDULERS 106 54 #define _BCM_TD2_NUM_L0_SCHEDULER_PER_PIPE 265 55 #define _BCM_TD2_NUM_L0_SCHEDULER _BCM_TD2_NUM_L0_SCHEDULER_PER_PIPE * 2 56 #define _BCM_TD2_NUM_L1_SCHEDULER_PER_PIPE (1024 - 4) /* Reserved for default val */ 57 #define _BCM_TD2_NUM_L1_SCHEDULER _BCM_TD2_NUM_L1_SCHEDULER_PER_PIPE * 2 58 #define _BCM_TD2_NUM_L2_UC_LEAVES_PER_PIPE (1480 - 4) /* Reserved for default val */ 59 #define _BCM_TD2_NUM_L2_UC_LEAVES _BCM_TD2_NUM_L2_UC_LEAVES_PER_PIPE * 2 60 #define _BCM_TD2_NUM_L2_MC_LEAVES_PER_PIPE 568 61 #define _BCM_TD2_NUM_L2_MC_LEAVES _BCM_TD2_NUM_L2_MC_LEAVES_PER_PIPE * 2 62 #define _BCM_TD2_NUM_L2_LEAVES_PER_PIPE (_BCM_TD2_NUM_L2_MC_LEAVES_PER_PIPE + \ 63 _BCM_TD2_NUM_L2_UC_LEAVES_PER_PIPE) 64 #define _BCM_TD2_NUM_L2_LEAVES _BCM_TD2_NUM_L2_LEAVES_PER_PIPE * 2 65 #define _BCM_TD2_NUM_TOTAL_SCHEDULERS (_BCM_TD2_NUM_PORT_SCHEDULERS + \ 66 _BCM_TD2_NUM_L0_SCHEDULER + \ 67 _BCM_TD2_NUM_L1_SCHEDULER) 68 #define _TD2_SPM_ENTRIES_PER_SET 128 69 #define _TD2_SCM_ENTRIES_PER_SET 16 70 /* ENDPOINT_COS_MAPm */ 71 #define _TD2_EPCM_ENTRIES_PER_SET 16 72 /* All CPU leaves are MC and belong to X Pipe only. Ranges from 520-567.*/ 73 #define _BCM_TD2_NUM_L2_CPU_LEAVES 48 74 75 #define _TD2_NUM_COS NUM_COS 76 #define _TD2_NUM_INTERNAL_PRI 16 77 78 /* TD2 supports eight PFC priority */ 79 #define _BCM_TD2_NUM_PFC_CLASS 8 80 81 #define _BCM_TD2_COSQ_LIST_NODE_INIT(list, node) \ 82 list[node].in_use = FALSE; \ 83 list[node].gport = -1; \ 84 list[node].base_index = -1; \ 85 list[node].numq = 0; \ 86 list[node].base_size = 0; \ 87 list[node].numq_expandable = 0; \ 88 list[node].hw_index = -1; \ 89 list[node].level = -1; \ 90 list[node].attached_to_input = -1; \ 91 list[node].hw_cosq = 0; \ 92 list[node].node_align_value = 1; \ 93 list[node].remote_modid = -1; \ 94 list[node].remote_port = -1; \ 95 BCM_PBMP_CLEAR(list[node].fabric_pbmp); \ 96 list[node].local_port = -1; \ 97 list[node].parent = NULL; \ 98 list[node].sibling = NULL; \ 99 list[node].child = NULL; 100 101 #define _BCM_TD2_COSQ_NODE_INIT(node) \ 102 node->in_use = FALSE; \ 103 node->gport = -1; \ 104 node->base_index = -1; \ 105 node->numq = 0; \ 106 node->base_size = 0; \ 107 node->numq_expandable = 0; \ 108 node->hw_index = -1; \ 109 node->level = -1; \ 110 node->attached_to_input = -1; \ 111 node->hw_cosq = 0; \ 112 node->node_align_value = 1; \ 113 node->remote_modid = -1; \ 114 node->remote_port = -1; \ 115 BCM_PBMP_CLEAR(node->fabric_pbmp); \ 116 node->local_port = -1; \ 117 node->parent = NULL; \ 118 node->sibling = NULL; \ 119 node->child = NULL; 120 121 typedef enum { 122 _BCM_TD2_COSQ_FC_PAUSE = 0, 123 _BCM_TD2_COSQ_FC_PFC, 124 _BCM_TD2_COSQ_FC_VOQFC, 125 _BCM_TD2_COSQ_FC_E2ECC 126 } _bcm_td2_fc_type_t; 127 128 typedef enum { 129 _BCM_TD2_NODE_UNKNOWN = 0, 130 _BCM_TD2_NODE_UCAST, 131 _BCM_TD2_NODE_MCAST, 132 _BCM_TD2_NODE_VOQ, 133 _BCM_TD2_NODE_VLAN_UCAST, 134 _BCM_TD2_NODE_VM_UCAST, 135 _BCM_TD2_NODE_SERVICE_UCAST, 136 _BCM_TD2_NODE_SCHEDULER 137 } _bcm_td2_node_type_e; 138 139 typedef struct _bcm_td2_cosq_node_s { 140 struct _bcm_td2_cosq_node_s *parent; 141 struct _bcm_td2_cosq_node_s *sibling; 142 struct _bcm_td2_cosq_node_s *child; 143 bcm_gport_t gport; 144 int in_use; 145 int base_index; 146 uint16 numq_expandable; 147 uint16 base_size; 148 int numq; 149 int hw_index; 150 soc_td2_node_lvl_e level; 151 _bcm_td2_node_type_e type; 152 int attached_to_input; 153 int hw_cosq; 154 int node_align_value; 155 156 /* DPVOQ specific information */ 157 bcm_port_t local_port; 158 bcm_module_t remote_modid; 159 bcm_port_t remote_port; 160 bcm_pbmp_t fabric_pbmp; 161 }_bcm_td2_cosq_node_t; 162 163 typedef struct _bcm_td2_cosq_list_s { 164 int count; 165 SHR_BITDCL *bits; 166 }_bcm_td2_cosq_list_t; 167 168 #define _BCM_TD2_HSP_PORT_MAX_L0 5 169 #define _BCM_TD2_HSP_PORT_MAX_L1 10 170 #define _BCM_TD2_HSP_PORT_MAX_L2 2 171 #define _BCM_TD2_HSP_PORT_MAX_COS 8 172 173 #define _BCM_TD2_MAX_PORT 106 174 175 #define _BCM_TD2_ROOT_SCHED_INDEX(u,mmu_port) \ 176 ((mmu_port >= 64) ? (mmu_port - 64) : (mmu_port)) 177 178 #define _BCM_TD2_HSP_L0_INDEX(u,mmu_port,cosq) \ 179 ((((mmu_port >= 64) ? (mmu_port - 64) : (mmu_port)) * _BCM_TD2_HSP_PORT_MAX_L0) +\ 180 (cosq)) 181 182 #define _BCM_TD2_HSP_L1_INDEX(u,mmu_port,cosq) \ 183 ((((mmu_port >= 64) ? (mmu_port - 64) : (mmu_port)) * _BCM_TD2_HSP_PORT_MAX_L1) +\ 184 (cosq)) 185 186 187 typedef struct _bcm_td2_pipe_resources_s { 188 int num_base_queues; /* Number of classical queues */ 189 190 _bcm_td2_cosq_list_t ext_qlist; /* list of extended queues */ 191 _bcm_td2_cosq_list_t l0_sched_list; /* list of l0 sched nodes */ 192 _bcm_td2_cosq_list_t l1_sched_list; /* list of l1 sched nodes */ 193 194 _bcm_td2_cosq_node_t *p_queue_node; 195 _bcm_td2_cosq_node_t *p_mc_queue_node; 196 } _bcm_td2_pipe_resources_t; 197 198 typedef struct _bcm_td2_cosq_port_info_s { 199 int mc_base; 200 int mc_limit; 201 int uc_base; 202 int uc_limit; 203 int eq_base; 204 int eq_limit; 205 _bcm_td2_pipe_resources_t *resources; 206 } _bcm_td2_cosq_port_info_t; 207 208 typedef struct _bcm_td2_cosq_cpu_cosq_config_s { 209 /* All MC queues have DB and MCQE space */ 210 int enable; 211 int q_min_limit[2]; 212 int q_shared_limit[2]; 213 uint8 q_limit_dynamic[2]; 214 uint8 q_limit_enable[2]; 215 } _bcm_td2_cosq_cpu_cosq_config_t; 216 217 #define _TD2_XPIPE 0 218 #define _TD2_YPIPE 1 219 #define _TD2_NUM_PIPES 2 220 221 #define _BCM_TD2_PORT_TO_PIPE(u, p) \ 222 (SOC_PBMP_MEMBER(SOC_INFO(unit).xpipe_pbm, (p)) ? _TD2_XPIPE : _TD2_YPIPE) 223 224 typedef struct _bcm_td2_mmu_info_s { 225 226 _bcm_td2_cosq_node_t sched_node[_BCM_TD2_NUM_TOTAL_SCHEDULERS]; /* sched nodes */ 227 _bcm_td2_cosq_node_t queue_node[_BCM_TD2_NUM_L2_UC_LEAVES]; /* queue nodes */ 228 _bcm_td2_cosq_node_t mc_queue_node[_BCM_TD2_NUM_L2_MC_LEAVES]; /* queue nodes */ 229 _bcm_td2_cosq_port_info_t port_info[_BCM_TD2_MAX_PORT]; 230 231 _bcm_td2_pipe_resources_t pipe_resources[_TD2_NUM_PIPES]; 232 233 int ets_mode; 234 int curr_shared_limit; 235 int curr_merger_index; 236 }_bcm_td2_mmu_info_t; 237 238 /* Node hardware index alignment. */ 239 #define _BCM_TD2_START_INDEX_ALIGN_DEFAULT 1 240 #define _BCM_TD2_START_INDEX_ALIGN_PFC 4 241 242 #define _TD2_NUM_TIME_DOMAIN 4 243 244 typedef struct _bcm_td2_cosq_time_info_s { 245 soc_field_t field; 246 uint32 ref_count; 247 } _bcm_td2_cosq_time_info_t; 248 249 /* WRED can be enabled at per UC queue / queue group/ port / service pool basis 250 MMU_WRED_AVG_QSIZE_X/Y_PIPE used entry:2 * (1480 + 128 + 208 + 4) = 3640 251 1479 ~ 0: Unicast Queue 252 1487 ~ 1480: Not used. 253 1615 ~ 1488: Queue Group per PIPE 254 1823 ~ 1616: Port Service Pool (Port 0 to 52) 255 1839 ~ 1824: Not used. 256 1843 ~ 1840: Global Service Pool 257 */ 258 STATIC _bcm_td2_cosq_time_info_t time_domain[_TD2_NUM_TIME_DOMAIN] = { 259 {TIME_0f, 3640}, /* Default all entries are pointing to TIME_0 */ 260 {TIME_1f, 0}, 261 {TIME_2f, 0}, 262 {TIME_3f, 0} 263 }; 264 265 #define _TD2_NUM_SERVICE_POOL 4 266 267 #define _BCM_TD2_PRESOURCES(mi, p) (&(mi)->pipe_resources[(p)]) 268 269 STATIC _bcm_td2_mmu_info_t *_bcm_td2_mmu_info[BCM_MAX_NUM_UNITS]; /* MMU info */ 270 271 STATIC soc_profile_mem_t *_bcm_td2_wred_profile[_TD2_NUM_PIPES][BCM_MAX_NUM_UNITS]; 272 STATIC soc_profile_mem_t *_bcm_td2_cos_map_profile[BCM_MAX_NUM_UNITS]; 273 STATIC soc_profile_mem_t *_bcm_td2_sample_int_profile[BCM_MAX_NUM_UNITS]; 274 STATIC soc_profile_reg_t *_bcm_td2_feedback_profile[BCM_MAX_NUM_UNITS]; 275 STATIC soc_profile_reg_t *_bcm_td2_llfc_profile[BCM_MAX_NUM_UNITS]; 276 STATIC soc_profile_mem_t *_bcm_td2_voq_port_map_profile[BCM_MAX_NUM_UNITS]; 277 static soc_profile_mem_t *_bcm_td2_ifp_cos_map_profile[BCM_MAX_NUM_UNITS]; 278 STATIC soc_profile_mem_t *_bcm_td2_service_port_map_profile[BCM_MAX_NUM_UNITS]; 279 STATIC soc_profile_mem_t *_bcm_td2_service_cos_map_profile[BCM_MAX_NUM_UNITS]; 280 281 STATIC _bcm_td2_cosq_cpu_cosq_config_t *_bcm_td2_cosq_cpu_cosq_config[BCM_MAX_NUM_UNITS][_BCM_TD2_NUM_L2_CPU_LEAVES]; 282 283 STATIC int bcm_td2p_cosq_rx_chan_l0_map[BCM_RX_CHANNELS] = 284 {-1, 259, 260, 261}; 285 STATIC int bcm_td2p_cmic_to_mmu_cosmask_map[_TD2PLUS_COSQ_NUM_CPU_L0_NODES] = 286 {58, 59, 60, 61, 62, 63}; 287 288 STATIC int 289 _bcm_td2_node_index_set(_bcm_td2_cosq_list_t *list, int start, int range); 290 291 STATIC int _bcm_td2_voq_next_base_node_get(int unit, bcm_port_t port, 292 int modid, 293 _bcm_td2_cosq_node_t **base_node); 294 STATIC int 295 _bcm_td2_cosq_mapping_set(int unit, bcm_port_t ing_port, bcm_cos_t priority, 296 uint32 flags, bcm_gport_t gport, bcm_cos_queue_t cosq); 297 STATIC int 298 _bcm_td2_cosq_set_scheduler_states(int unit, bcm_port_t port, int busy); 299 300 typedef enum { 301 _BCM_TD2_COSQ_TYPE_UCAST, 302 _BCM_TD2_COSQ_TYPE_MCAST, 303 _BCM_TD2_COSQ_TYPE_EXT_UCAST 304 } _bcm_td2_cosq_type_t; 305 306 #define IS_TD2_HSP_PORT(u,p) \ 307 ((_soc_trident2_port_sched_type_get((u),(p)) == SOC_TD2_SCHED_HSP) ? 1 : 0) 308 309 typedef struct _bcm_td2_endpoint_s { 310 uint32 flags; /* BCM_COSQ_CLASSIFIER_xxx flags */ 311 bcm_vlan_t vlan; /* VLAN */ 312 bcm_mac_t mac; /* MAC address */ 313 bcm_vrf_t vrf; /* Virtual Router Instance */ 314 bcm_ip_t ip_addr; /* IPv4 address */ 315 bcm_ip6_t ip6_addr; /* IPv6 address */ 316 bcm_gport_t gport; /* GPORT ID */ 317 bcm_if_t egress_if; /* Egress object */ 318 } _bcm_td2_endpoint_t; 319 320 typedef struct _bcm_td2_endpoint_queuing_info_s { 321 int num_endpoint; /* Number of endpoints */ 322 _bcm_td2_endpoint_t **ptr_array; /* Array of pointers to endpoints */ 323 soc_profile_mem_t *cos_map_profile; /* Internal priority to CoS queue 324 mapping profile */ 325 } _bcm_td2_endpoint_queuing_info_t; 326 327 STATIC int 328 _bcm_td2_cosq_egress_sp_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 329 int *p_pool_start, int *p_pool_end); 330 331 STATIC _bcm_td2_endpoint_queuing_info_t *_bcm_td2_endpoint_queuing_info[BCM_MAX_NUM_UNITS]; 332 333 STATIC int 334 _bcm_td2_cosq_dynamic_thresh_enable_get(int unit, 335 bcm_gport_t gport, bcm_cos_queue_t cosq, 336 bcm_cosq_control_t type, int *arg); 337 338 STATIC int 339 _bcm_td2_cosq_node_get(int unit, bcm_gport_t gport, 340 bcm_cos_queue_t cosq,bcm_module_t *modid, bcm_port_t *port, 341 int *id, _bcm_td2_cosq_node_t **node); 342 343 STATIC int 344 _bcm_td2_cosq_sched_parent_child_set(int unit, int port, int level, 345 int sched_index, int child_index, 346 soc_td2_sched_mode_e sched_mode, 347 int weight, _bcm_td2_cosq_node_t *node); 348 349 #define _BCM_TD2_NUM_ENDPOINT(unit) \ 350 (_bcm_td2_endpoint_queuing_info[unit]->num_endpoint) 351 352 #define _BCM_TD2_ENDPOINT(unit, id) \ 353 (_bcm_td2_endpoint_queuing_info[unit]->ptr_array[id]) 354 355 #define _BCM_TD2_ENDPOINT_IS_USED(unit, id) \ 356 (_bcm_td2_endpoint_queuing_info[unit]->ptr_array[id] != NULL) 357 358 #define _BCM_TD2_ENDPOINT_COS_MAP_PROFILE(unit) \ 359 (_bcm_td2_endpoint_queuing_info[unit]->cos_map_profile) 360 361 #ifdef BCM_WARM_BOOT_SUPPORT 362 363 #define BCM_WB_VERSION_1_0 SOC_SCACHE_VERSION(1,0) 364 #define BCM_WB_VERSION_1_1 SOC_SCACHE_VERSION(1,1) 365 #define BCM_WB_VERSION_1_2 SOC_SCACHE_VERSION(1,2) 366 #define BCM_WB_VERSION_1_3 SOC_SCACHE_VERSION(1,3) 367 #define BCM_WB_VERSION_1_4 SOC_SCACHE_VERSION(1,4) 368 #define BCM_WB_VERSION_1_5 SOC_SCACHE_VERSION(1,5) 369 #define BCM_WB_VERSION_1_6 SOC_SCACHE_VERSION(1,6) 370 #define BCM_WB_VERSION_1_7 SOC_SCACHE_VERSION(1,7) 371 372 #define BCM_WB_DEFAULT_VERSION BCM_WB_VERSION_1_7 373 374 STATIC int 375 _bcm_td2_cosq_wb_alloc(int unit) 376 { 377 _bcm_td2_mmu_info_t *mmu_info; 378 soc_scache_handle_t scache_handle; 379 uint8 *scache_ptr; 380 int rv, alloc_size, node_list_sizes[3], ii, jj; 381 uint32 shadow_size = 0; 382 383 mmu_info = _bcm_td2_mmu_info[unit]; 384 385 if (!mmu_info) { 386 return BCM_E_INIT; 387 } 388 if ((SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit))) { 389 /* COSQ warmboot requires extended scache support i.e. level2 warmboot*/ 390 return BCM_E_NONE; 391 } 392 393 node_list_sizes[0] = _BCM_TD2_NUM_L2_UC_LEAVES; 394 node_list_sizes[1] = _BCM_TD2_NUM_L2_MC_LEAVES; 395 node_list_sizes[2] = _BCM_TD2_NUM_TOTAL_SCHEDULERS; 396 397 alloc_size = 0; 398 for(ii = 0; ii < 3; ii++) { 399 alloc_size += sizeof(uint32); 400 for(jj = 0; jj < node_list_sizes[ii]; jj++) { 401 alloc_size += 4 * sizeof(uint32); 402 } 403 } 404 405 /* Size of TIME_DOMAINr field and count reference */ 406 alloc_size += _TD2_NUM_TIME_DOMAIN * sizeof(_bcm_td2_cosq_time_info_t); 407 408 soc_trident2_fc_map_shadow_size_get(unit, &shadow_size); 409 alloc_size += shadow_size; 410 411 /* added in BCM_WB_VERSION_1_1 412 * to sync _bcm_td2_mmu_info[unit]->hw_cosq/attached_to_input/ 413 * type/numq_expandable/numq/base_index/base_size 414 */ 415 for (ii = 0; ii < 3; ii++) { 416 for (jj = 0; jj < node_list_sizes[ii]; jj++) { 417 alloc_size += 2 * sizeof(uint32); 418 } 419 } 420 421 /* added in BCM_WB_VERSION_1_1 422 * to sync _bcm_td2_mmu_info[unit]->ets_mode/curr_shared_limit 423 */ 424 alloc_size += 2 * sizeof(int); 425 426 /* added in BCM_WB_VERSION_1_2 427 * to sync the reference count of IFP_COS_MAPm 428 */ 429 alloc_size += (SOC_MEM_SIZE(unit,IFP_COS_MAPm) / _TD2_NUM_INTERNAL_PRI) * 430 sizeof(uint16); 431 432 alloc_size += sizeof(uint16) * SOC_MEM_SIZE(unit, SERVICE_COS_MAPm) / 433 _TD2_SCM_ENTRIES_PER_SET; 434 alloc_size += sizeof(uint16) * SOC_MEM_SIZE(unit, SERVICE_PORT_MAPm) / 435 _TD2_SPM_ENTRIES_PER_SET; 436 437 BCM_IF_ERROR_RETURN(soc_td2_mmu_traffic_ctrl_size(unit, &alloc_size)); 438 439 /* 440 * Added in BCM_WB_VERSION_1_5 441 * Sync num_cos value 442 */ 443 alloc_size += sizeof(int); 444 445 /* 446 * Added in BCM_WB_VERSION_1_6 447 * to sync _bcm_td2_mmu_info[unit]->curr_merger_index/node->fabric_pbmp 448 */ 449 alloc_size += sizeof(int); /* to sync sizeof(bcm_pbmp_t) */ 450 for(ii = 0; ii < 3; ii++) { 451 alloc_size += (node_list_sizes[ii] * sizeof(bcm_pbmp_t)); 452 } 453 alloc_size += sizeof(int); 454 455 /* 456 * Added in BCM_WB_VERSION_1_7 457 * to sync _bcm_td2_endpoint_queuing_info[unit]->ptr_array[id] 458 */ 459 if (soc_feature(unit, soc_feature_endpoint_queuing)) { 460 alloc_size += ((_BCM_TD2_NUM_ENDPOINT(unit) - 1) * 461 (sizeof(uint32) + sizeof(bcm_vrf_t) + sizeof(bcm_ip6_t))); 462 alloc_size += sizeof(uint16) * SOC_MEM_SIZE(unit, ENDPOINT_COS_MAPm) / 463 _TD2_EPCM_ENTRIES_PER_SET; 464 } 465 466 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_COSQ, 0); 467 468 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, TRUE, alloc_size, 469 &scache_ptr, BCM_WB_DEFAULT_VERSION, NULL); 470 if (rv == BCM_E_NOT_FOUND) { 471 rv = BCM_E_NONE; 472 } 473 474 return rv; 475 } 476 477 #define _BCM_TD2_WB_NTYPE_UCAST 0 478 #define _BCM_TD2_WB_NTYPE_MCAST 1 479 #define _BCM_TD2_WB_NTYPE_SCHED 2 480 481 #define _BCM_TD2_WB_SET_NODE_W1(ntype,nid,sz,parentid,pipe) \ 482 (((ntype & 3)) | \ 483 (((sz) & 7) << 2) | \ 484 (((nid) & 0x1fff) << 5) | \ 485 (((parentid) & 0xfff) << 18) | ((pipe) & 1) << 31) 486 487 #define _BCM_TD2_WB_GET_NODE_ID_W1(w1) (((w1) >> 5) & 0x1fff) 488 489 #define _BCM_TD2_WB_GET_NODE_TYPE_W1(w1) ((w1) & 3) 490 491 #define _BCM_TD2_WB_GET_NODE_SIZE_W1(w1) (((w1) >> 2) & 7) 492 493 #define _BCM_TD2_WB_GET_NODE_PARENT_W1(w1) (((w1) >> 18) & 0xfff) 494 495 #define _BCM_TD2_WB_GET_PIPE_W1(w1) (((w1) >> 31) & 1) 496 497 /* 12 bit hw index, 11 bit sibling, 3 bit hw cosq */ 498 /* Encoding node_align_value in 1 bit 0->1, 1->4 */ 499 #define _BCM_TD2_WB_SET_NODE_W2(hwindex,hwcosq,cosq,lvl,align) \ 500 ((((hwindex) & 0x1fff)) | (((hwcosq) & 0xf) << 13) | \ 501 (((cosq) & 0xf) << 17) | (((lvl) & 0x7) << 21) | \ 502 (((align) & 0x1) << 24)) 503 504 #define _BCM_TD2_WB_GET_NODE_HW_INDEX_W2(w1) ((w1) & 0x1fff) 505 506 #define _BCM_TD2_WB_GET_NODE_HW_COSQ_W2(w1) (((w1) >> 13) & 0xf) 507 508 #define _BCM_TD2_WB_GET_NODE_COSQATTT_W2(w1) (((w1) >> 17) & 0xf) 509 510 #define _BCM_TD2_WB_GET_NODE_LEVEL_W2(w1) (((w1) >> 21) & 0x7) 511 512 #define _BCM_TD2_WB_GET_ALIGN_W2(w1) (((w1) >> 24) & 0x1) 513 514 #define _BCM_TD2_WB_SET_NODE_W3(gport) (gport) 515 516 #define _BCM_TD2_WB_SET_NODE_W4(remote_modid,remote_port,voq_cosq) \ 517 ((((remote_modid) & 0x1ff)) | \ 518 (((remote_port) & 0x1ff) << 9) | \ 519 (((voq_cosq) & 0xf) << 18)) 520 521 #define _BCM_TD2_WB_GET_NODE_DEST_MODID_W4(w1) ((w1) & 0x1ff) 522 523 #define _BCM_TD2_WB_GET_NODE_DEST_PORT_W4(w1) (((w1) >> 9) & 0x1ff) 524 525 #define _BCM_TD2_WB_GET_NODE_VOQ_COSQ_W4(w1) (((w1) >> 18) & 0xf) 526 527 #define _BCM_TD2_WB_SET_NODE_W5(expand,type,cosq,hw_cosq) \ 528 (((expand) & 0x7) | (((type) & 0x1f) << 3) | \ 529 (((cosq) & 0xfff) << 8) | (((hw_cosq) & 0xfff) << 20)) 530 531 #define _BCM_TD2_WB_GET_EXPAND_W5(w1) ((w1) & 0x7) 532 533 #define _BCM_TD2_WB_TYPE_W5(w1) (((w1) >> 3) & 0x1f) 534 535 #define _BCM_TD2_WB_COSQ_W5(w1) (((w1) >> 8) & 0xfff) 536 537 #define _BCM_TD2_WB_HW_COSQ_W5(w1) (((w1) >> 20) & 0xfff) 538 539 #define _BCM_TD2_WB_SET_NODE_W6(base_size,base_index,numq) \ 540 (((base_size) & 0x3ff) | (((base_index) & 0x7ff) << 10) | \ 541 (((numq) & 0x7ff) << 21)) 542 543 #define _BCM_TD2_WB_GET_BASE_SIZE_W6(w1) ((w1) & 0x3ff) 544 545 #define _BCM_TD2_WB_GET_BASE_INDEX_W6(w1) (((w1) >> 10) & 0x7ff) 546 547 #define _BCM_TD2_WB_GET_NUMQ_W6(w1) (((w1) >> 21) & 0x7ff) 548 549 550 #define _BCM_TD2_NODE_ID(np,np0) (np - np0) 551 552 /* 553 * Function: 554 * bcm_td2_cosq_endpoint_recover 555 * Purpose: 556 * Recover endpoint info from scache. 557 * Parameters: 558 * unit - (IN) StrataSwitch unit # 559 * scache_ptr - (IN/OUT) Scache pointer 560 * Returns: 561 * BCM_E_xxx 562 */ 563 STATIC int 564 bcm_td2_cosq_endpoint_recover(int unit, uint8 **scache_ptr) 565 { 566 int entry_size; 567 int flags; 568 int ii; 569 int profile_num; 570 soc_profile_mem_t *profile_mem; 571 uint16 *u16_scache_ptr; 572 int ref_count; 573 574 entry_size = sizeof(uint32) + sizeof(bcm_vrf_t) + sizeof(bcm_ip6_t); 575 /* entry 0 was reserved and is not synced. */ 576 for (ii = 1; ii < _BCM_TD2_NUM_ENDPOINT(unit); ii++) { 577 sal_memcpy(&flags, (*scache_ptr), sizeof(uint32)); 578 579 if ((flags & BCM_COSQ_CLASSIFIER_L2) || 580 (flags & BCM_COSQ_CLASSIFIER_L3) || 581 (flags & BCM_COSQ_CLASSIFIER_GPORT) || 582 (flags & BCM_COSQ_CLASSIFIER_L3_EGRESS)) { 583 _BCM_TD2_ENDPOINT(unit, ii) = sal_alloc( 584 sizeof(_bcm_td2_endpoint_t), "Endpoint Info"); 585 if (_BCM_TD2_ENDPOINT(unit, ii) == NULL) { 586 return BCM_E_MEMORY; 587 } 588 sal_memset(_BCM_TD2_ENDPOINT(unit, ii), 0, 589 sizeof(_bcm_td2_endpoint_t)); 590 _BCM_TD2_ENDPOINT(unit, ii)->flags = flags; 591 if (flags & BCM_COSQ_CLASSIFIER_L2) { 592 (*scache_ptr) += sizeof(uint32); 593 sal_memcpy(&(_BCM_TD2_ENDPOINT(unit, ii)->vlan), 594 (*scache_ptr), sizeof(bcm_vlan_t)); 595 (*scache_ptr) += sizeof(bcm_vlan_t); 596 sal_memcpy(_BCM_TD2_ENDPOINT(unit, ii)->mac, (*scache_ptr), 597 sizeof(bcm_mac_t)); 598 (*scache_ptr) += (entry_size - sizeof(uint32) - 599 sizeof(bcm_vlan_t)); 600 } else if (flags & BCM_COSQ_CLASSIFIER_L3) { 601 (*scache_ptr) += sizeof(uint32); 602 sal_memcpy(&(_BCM_TD2_ENDPOINT(unit, ii)->vrf), 603 (*scache_ptr), sizeof(bcm_vrf_t)); 604 (*scache_ptr) += sizeof(bcm_vrf_t); 605 if (flags & BCM_COSQ_CLASSIFIER_IP6) { 606 sal_memcpy(_BCM_TD2_ENDPOINT(unit, ii)->ip6_addr, (*scache_ptr), 607 sizeof(bcm_ip6_t)); 608 } else { 609 sal_memcpy(&(_BCM_TD2_ENDPOINT(unit, ii)->ip_addr), (*scache_ptr), 610 sizeof(bcm_ip_t)); 611 } 612 (*scache_ptr) += (entry_size - sizeof(uint32) - 613 sizeof(bcm_vrf_t)); 614 } else if (flags & BCM_COSQ_CLASSIFIER_L3_EGRESS) { 615 (*scache_ptr) += sizeof(uint32); 616 sal_memcpy(&(_BCM_TD2_ENDPOINT(unit, ii)->egress_if), 617 (*scache_ptr), sizeof(bcm_if_t)); 618 (*scache_ptr) += (entry_size - sizeof(uint32)); 619 } else { 620 (*scache_ptr) += sizeof(uint32); 621 sal_memcpy(&(_BCM_TD2_ENDPOINT(unit, ii)->gport), 622 (*scache_ptr), sizeof(bcm_gport_t)); 623 (*scache_ptr) += (entry_size - sizeof(uint32)); 624 } 625 } else { 626 (*scache_ptr) += entry_size; 627 } 628 } 629 630 profile_mem = _BCM_TD2_ENDPOINT_COS_MAP_PROFILE(unit); 631 profile_num = SOC_MEM_SIZE(unit, ENDPOINT_COS_MAPm) / _TD2_EPCM_ENTRIES_PER_SET; 632 u16_scache_ptr = (uint16 *)(*scache_ptr); 633 634 for (ii = 0; ii < profile_num; ii++) { 635 for (ref_count = 0; ref_count < *u16_scache_ptr; ref_count++) { 636 SOC_IF_ERROR_RETURN( 637 soc_profile_mem_reference(unit, profile_mem, 638 ii * _TD2_EPCM_ENTRIES_PER_SET, 639 _TD2_EPCM_ENTRIES_PER_SET)); 640 } 641 u16_scache_ptr++; 642 } 643 644 *scache_ptr = (uint8 *)(u16_scache_ptr); 645 646 return BCM_E_NONE; 647 } 648 649 int 650 bcm_td2_cosq_reinit(int unit) 651 { 652 soc_scache_handle_t scache_handle; 653 uint8 *scache_ptr; 654 uint32 *u32_scache_ptr, *u32_base_ptr, *u32_base_ptr_1, wval, fval; 655 uint16 *u16_scache_ptr = NULL; 656 _bcm_td2_cosq_node_t *node; 657 bcm_port_t port; 658 int rv, ii, jj, set_index; 659 _bcm_td2_cosq_node_t *nodes[3]; 660 int xnode_id, stable_size, node_size, count, pipe, profile_index; 661 _bcm_td2_mmu_info_t *mmu_info; 662 uint32 entry[SOC_MAX_MEM_WORDS]; 663 soc_profile_mem_t *profile_mem; 664 _bcm_td2_pipe_resources_t *res; 665 soc_mem_t mem; 666 mmu_wred_config_entry_t qentry; 667 int alloc_size; 668 int incr_size = 0; 669 uint16 recovered_ver = 0; 670 int node_list_sizes[3]; 671 int index=0; 672 bcm_pbmp_t all_pbmp; 673 soc_profile_reg_t *profile_reg; 674 soc_info_t *si; 675 bcm_port_t phy_port, mmu_port; 676 soc_reg_t reg; 677 uint32 tmp32, scache_pbmp_size, pbmp_restore_size; 678 uint64 rval, index_map; 679 static const soc_reg_t llfc_cfgr[] = { 680 PORT_PFC_CFG0r, PORT_PFC_CFG1r, PORT_PFC_CFG2r, PORT_PFC_CFG3r 681 }; 682 int num; 683 _bcm_td2_cosq_time_info_t tmp_timedomain; 684 uint8 *u8_scache_ptr = NULL; 685 686 si = &SOC_INFO(unit); 687 688 SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size)); 689 if ((stable_size == 0) || (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit))) { 690 /* COSQ warmboot requires extended scache support i.e. level2 warmboot*/ 691 return BCM_E_NONE; 692 } 693 694 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_COSQ, 0); 695 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 0, &scache_ptr, 696 BCM_WB_DEFAULT_VERSION, &recovered_ver); 697 if (BCM_FAILURE(rv)) { 698 return rv; 699 } 700 701 mmu_info = _bcm_td2_mmu_info[unit]; 702 703 if (!mmu_info) { 704 return BCM_E_INIT; 705 } 706 707 u32_scache_ptr = (uint32*) scache_ptr; 708 709 nodes[0] = &mmu_info->queue_node[0]; 710 nodes[1] = &mmu_info->mc_queue_node[0]; 711 nodes[2] = &mmu_info->sched_node[0]; 712 713 u32_base_ptr = u32_scache_ptr; 714 u32_base_ptr_1 = u32_scache_ptr; 715 for(ii = 0; ii < 3; ii++) { 716 count = *u32_scache_ptr; 717 u32_scache_ptr++; 718 for(jj = 0; jj < count; jj++) { 719 wval = *u32_scache_ptr; 720 u32_scache_ptr++; 721 xnode_id = _BCM_TD2_WB_GET_NODE_ID_W1(wval); 722 node = nodes[ii] + xnode_id; 723 node->in_use = TRUE; 724 node->numq = 1; 725 node_size = _BCM_TD2_WB_GET_NODE_SIZE_W1(wval); 726 fval = _BCM_TD2_WB_GET_NODE_PARENT_W1(wval); 727 if (fval & 0x800) { 728 } else { 729 node->parent = &mmu_info->sched_node[fval]; 730 if (node->parent->child) { 731 node->sibling = node->parent->child; 732 } 733 node->parent->child = node; 734 } 735 736 pipe = _BCM_TD2_WB_GET_PIPE_W1(wval); 737 res = _BCM_TD2_PRESOURCES(mmu_info, pipe); 738 739 wval = *u32_scache_ptr; 740 u32_scache_ptr++; 741 742 fval = _BCM_TD2_WB_GET_NODE_HW_INDEX_W2(wval); 743 if (fval & 0x1000) { 744 node->hw_index = -1; 745 } else { 746 node->hw_index = fval; 747 } 748 749 fval = _BCM_TD2_WB_GET_NODE_HW_COSQ_W2(wval); 750 if (fval & 8) { 751 node->hw_cosq = -1; 752 } else { 753 node->hw_cosq = fval; 754 } 755 756 fval = _BCM_TD2_WB_GET_NODE_COSQATTT_W2(wval); 757 if (fval & 8) { 758 node->attached_to_input = -1; 759 } else { 760 node->attached_to_input = fval; 761 } 762 763 node->level = _BCM_TD2_WB_GET_NODE_LEVEL_W2(wval); 764 765 node->node_align_value = (_BCM_TD2_WB_GET_ALIGN_W2(wval) ? \ 766 _BCM_TD2_START_INDEX_ALIGN_PFC : \ 767 _BCM_TD2_START_INDEX_ALIGN_DEFAULT); 768 769 wval = *u32_scache_ptr; 770 u32_scache_ptr++; 771 node->gport = wval; 772 /* 773 * Not checking the return value intentionally 774 * to take care of warmboot case. 775 */ 776 /* coverity[unchecked_value] */ 777 /* coverity[check_return] */ 778 _bcm_td2_cosq_node_get(unit, node->gport, 0, NULL, 779 &node->local_port, NULL, NULL); 780 781 if (node->hw_index != -1) { 782 if (node->level == SOC_TD2_NODE_LVL_L0) { 783 _bcm_td2_node_index_set(&res->l0_sched_list, 784 node->hw_index, 1); 785 } else if (node->level == SOC_TD2_NODE_LVL_L1) { 786 _bcm_td2_node_index_set(&res->l1_sched_list, 787 node->hw_index, 1); 788 } else if (node->level == SOC_TD2_NODE_LVL_L2) { 789 _bcm_td2_node_index_set(&res->ext_qlist, 790 node->hw_index, 1); 791 } 792 } 793 794 if (node_size > 3) { 795 wval = *u32_scache_ptr; 796 u32_scache_ptr++; 797 798 fval = _BCM_TD2_WB_GET_NODE_DEST_MODID_W4(wval); 799 if (fval & 0x100) { 800 node->remote_modid = -1; 801 } else { 802 node->remote_modid = fval; 803 } 804 805 fval = _BCM_TD2_WB_GET_NODE_DEST_PORT_W4(wval); 806 if (fval & 0x100) { 807 node->remote_port = -1; 808 } else { 809 node->remote_port = fval; 810 } 811 812 fval = _BCM_TD2_WB_GET_NODE_VOQ_COSQ_W4(wval); 813 if (fval & 0xf) { 814 node->hw_cosq = -1; 815 } else { 816 node->hw_cosq = fval; 817 } 818 } 819 } 820 } 821 822 /* Recovery TIME_DOMAINr field and count reference 823 * Do not overwrite time_domian[i].field data, 824 * TIME_0/1/2/3f(file value) itself can be changed during version update 825 * Just update time_domain[i].ref_count */ 826 for (ii = 0; ii < _TD2_NUM_TIME_DOMAIN; ii++) { 827 sal_memset(&tmp_timedomain, 0, sizeof(tmp_timedomain)); 828 alloc_size = sizeof(_bcm_td2_cosq_time_info_t); 829 sal_memcpy(&tmp_timedomain, u32_scache_ptr, alloc_size); 830 time_domain[ii].ref_count = tmp_timedomain.ref_count; 831 u32_scache_ptr += alloc_size / sizeof(uint32); 832 } 833 soc_trident2_fc_map_shadow_load(unit, &u32_scache_ptr); 834 835 node_list_sizes[0] = _BCM_TD2_NUM_L2_UC_LEAVES; 836 node_list_sizes[1] = _BCM_TD2_NUM_L2_MC_LEAVES; 837 node_list_sizes[2] = _BCM_TD2_NUM_TOTAL_SCHEDULERS; 838 /* 1.In the vesion before BCM_WB_VERSION_1_1, the node->attached_to_input/ 839 * hw_cosq/numq were synced/recovered incorrectly(The range of them were 840 * incorrect). 841 * 2.The node->base_inde/base_size/_bcm_td2_mmu_info[unit]->ets_mode/ 842 * curr_shared_limit were not synced/recovered in the version before 843 * BCM_WB_VERSION_1_1. 844 */ 845 if (recovered_ver >= BCM_WB_VERSION_1_1) { 846 for (ii = 0; ii < 3; ii++) { 847 count = *u32_base_ptr++; 848 for (jj = 0; jj < count; jj++) { 849 wval = *u32_base_ptr++; 850 xnode_id = _BCM_TD2_WB_GET_NODE_ID_W1(wval); 851 node = nodes[ii] + xnode_id; 852 node_size = _BCM_TD2_WB_GET_NODE_SIZE_W1(wval); 853 854 wval = *u32_scache_ptr++; 855 node->numq_expandable = _BCM_TD2_WB_GET_EXPAND_W5(wval); 856 node->type = _BCM_TD2_WB_TYPE_W5(wval); 857 858 fval = _BCM_TD2_WB_COSQ_W5(wval); 859 if (fval & 0x800) { 860 node->attached_to_input = -1; 861 } else { 862 node->attached_to_input = fval; 863 } 864 865 fval = _BCM_TD2_WB_HW_COSQ_W5(wval); 866 if (fval & 0x800) { 867 node->hw_cosq = -1; 868 } else { 869 node->hw_cosq = fval; 870 } 871 872 wval = *u32_scache_ptr++; 873 node->base_size = _BCM_TD2_WB_GET_BASE_SIZE_W6(wval); 874 fval = _BCM_TD2_WB_GET_NUMQ_W6(wval); 875 if (fval & 0x600) { 876 node->numq = -1; 877 } else { 878 node->numq = fval; 879 } 880 fval = _BCM_TD2_WB_GET_BASE_INDEX_W6(wval); 881 if (fval & 0x400) { 882 node->base_index = -1; 883 } else { 884 node->base_index = fval; 885 } 886 887 u32_base_ptr += 2; 888 if (node_size > 3) { 889 u32_base_ptr++; 890 } 891 } 892 } 893 894 mmu_info->ets_mode = *u32_scache_ptr++; 895 mmu_info->curr_shared_limit = *u32_scache_ptr++; 896 } else { 897 /* added in BCM_WB_VERSION_1_1 898 * to sync _bcm_td2_mmu_info[unit]->hw_cosq/attached_to_input/ 899 * type/numq_expandable/numq/base_index/base_size 900 */ 901 for (ii = 0; ii < 3; ii++) { 902 for (jj = 0; jj < node_list_sizes[ii]; jj++) { 903 incr_size += 2 * sizeof(uint32); 904 } 905 } 906 907 /* added in BCM_WB_VERSION_1_1 908 * to sync _bcm_td2_mmu_info[unit]->ets_mode/curr_shared_limit 909 */ 910 incr_size += 2 * sizeof(int); 911 } 912 913 if (recovered_ver >= BCM_WB_VERSION_1_2) { 914 /* Update IFP_COS_MAP memory profile reference counter */ 915 profile_mem = _bcm_td2_ifp_cos_map_profile[unit]; 916 num = SOC_MEM_SIZE(unit,IFP_COS_MAPm) / _TD2_NUM_INTERNAL_PRI; 917 u16_scache_ptr = (uint16 *)u32_scache_ptr; 918 for (ii = 0; ii < num; ii++) { 919 for (jj = 0; jj < *u16_scache_ptr; jj++) { 920 SOC_IF_ERROR_RETURN( 921 soc_profile_mem_reference(unit, profile_mem, 922 ii * _TD2_NUM_INTERNAL_PRI, 923 _TD2_NUM_INTERNAL_PRI)); 924 } 925 u16_scache_ptr++; 926 } 927 } else { 928 incr_size += 929 (SOC_MEM_SIZE(unit,IFP_COS_MAPm) / _TD2_NUM_INTERNAL_PRI) * 930 sizeof(uint16); 931 } 932 933 if (recovered_ver >= BCM_WB_VERSION_1_3) { 934 profile_mem = _bcm_td2_service_cos_map_profile[unit]; 935 num = SOC_MEM_SIZE(unit, SERVICE_COS_MAPm) / _TD2_SCM_ENTRIES_PER_SET; 936 for (ii = 0; ii < num; ii++) { 937 for (jj = 0; jj < *u16_scache_ptr; jj++) { 938 SOC_IF_ERROR_RETURN( 939 soc_profile_mem_reference(unit, profile_mem, 940 ii * _TD2_SCM_ENTRIES_PER_SET, 941 _TD2_SCM_ENTRIES_PER_SET)); 942 } 943 u16_scache_ptr++; 944 } 945 946 profile_mem = _bcm_td2_service_port_map_profile[unit]; 947 num = SOC_MEM_SIZE(unit, SERVICE_PORT_MAPm) / _TD2_SPM_ENTRIES_PER_SET; 948 for (ii = 0; ii < num; ii++) { 949 for (jj = 0; jj < *u16_scache_ptr; jj++) { 950 SOC_IF_ERROR_RETURN( 951 soc_profile_mem_reference(unit, profile_mem, 952 ii * _TD2_SPM_ENTRIES_PER_SET, 953 _TD2_SPM_ENTRIES_PER_SET)); 954 } 955 u16_scache_ptr++; 956 } 957 } else { 958 incr_size += sizeof(uint16) * SOC_MEM_SIZE(unit, SERVICE_COS_MAPm) / 959 _TD2_SCM_ENTRIES_PER_SET; 960 incr_size += sizeof(uint16) * SOC_MEM_SIZE(unit, SERVICE_PORT_MAPm) / 961 _TD2_SPM_ENTRIES_PER_SET; 962 } 963 964 if (recovered_ver >= BCM_WB_VERSION_1_4) { 965 u8_scache_ptr = (uint8 *)u16_scache_ptr; 966 BCM_IF_ERROR_RETURN(soc_td2_mmu_traffic_ctrl_wb_restore(unit, &u8_scache_ptr)); 967 } else { 968 BCM_IF_ERROR_RETURN(soc_td2_mmu_traffic_ctrl_size(unit, &incr_size)); 969 } 970 971 /* Retriving num_cos value */ 972 if (recovered_ver >= BCM_WB_VERSION_1_5) { 973 u32_scache_ptr = (uint32 *) u8_scache_ptr; 974 NUM_COS(unit) = *u32_scache_ptr++; 975 } else { 976 incr_size += sizeof(int); 977 } 978 979 /* Retriving node->fabric_pbmp & mmu_info->curr_merger_index value */ 980 if (recovered_ver >= BCM_WB_VERSION_1_6) { 981 scache_pbmp_size = *u32_scache_ptr++; 982 u8_scache_ptr = (uint8 *)u32_scache_ptr; 983 pbmp_restore_size = (scache_pbmp_size < sizeof(bcm_pbmp_t))? \ 984 scache_pbmp_size : sizeof(bcm_pbmp_t); 985 for (ii = 0; ii < 3; ii++) { 986 count = *u32_base_ptr_1++; 987 for (jj = 0; jj < count; jj++) { 988 wval = *u32_base_ptr_1++; 989 xnode_id = _BCM_TD2_WB_GET_NODE_ID_W1(wval); 990 node = nodes[ii] + xnode_id; 991 node_size = _BCM_TD2_WB_GET_NODE_SIZE_W1(wval); 992 993 sal_memcpy(&node->fabric_pbmp, u8_scache_ptr, 994 pbmp_restore_size); 995 u8_scache_ptr += scache_pbmp_size; 996 997 u32_base_ptr_1 += 2; 998 if (node_size > 3) { 999 u32_base_ptr_1++; 1000 } 1001 } 1002 } 1003 u32_scache_ptr = (uint32 *)u8_scache_ptr; 1004 mmu_info->curr_merger_index = *u32_scache_ptr++; 1005 } else { 1006 incr_size += sizeof(int); 1007 for(ii = 0; ii < 3; ii++) { 1008 incr_size += (node_list_sizes[ii] * sizeof(bcm_pbmp_t)); 1009 } 1010 incr_size += sizeof(int); 1011 } 1012 1013 /* BCM_WB_VERSION_1_7 Sync endpoint info. 1014 * In order to save scache, each entry size is fixed. 1015 * entry_size = sizeof(uint32)+ sizeof(bcm_vrf_t) + sizeof(bcm_ip6_t). 1016 * entry 0 was reserved and is not synced. 1017 */ 1018 if (recovered_ver >= BCM_WB_VERSION_1_7) { 1019 if (soc_feature(unit, soc_feature_endpoint_queuing)) { 1020 u8_scache_ptr = (uint8 *)u32_scache_ptr; 1021 BCM_IF_ERROR_RETURN( 1022 bcm_td2_cosq_endpoint_recover(unit, &u8_scache_ptr)); 1023 } 1024 } else { 1025 if (soc_feature(unit, soc_feature_endpoint_queuing)) { 1026 incr_size += ((_BCM_TD2_NUM_ENDPOINT(unit) - 1) * 1027 (sizeof(uint32) + sizeof(bcm_vrf_t) + sizeof(bcm_ip6_t))); 1028 incr_size += sizeof(uint16) * SOC_MEM_SIZE(unit, ENDPOINT_COS_MAPm) / 1029 _TD2_EPCM_ENTRIES_PER_SET; 1030 } 1031 } 1032 1033 if (incr_size > 0) { 1034 BCM_IF_ERROR_RETURN( 1035 soc_scache_realloc(unit, scache_handle, incr_size)); 1036 } 1037 1038 /* Update reference counts for DSCP_TABLE profile*/ 1039 BCM_PBMP_CLEAR(all_pbmp); 1040 BCM_PBMP_ASSIGN(all_pbmp, PBMP_ALL(unit)); 1041 1042 PBMP_ITER(all_pbmp, port) { 1043 if (IS_LB_PORT(unit, port)) { 1044 /* Loopback port base starts from 64 */ 1045 continue; 1046 } 1047 SOC_IF_ERROR_RETURN(soc_mem_read(unit, PORT_TABm, MEM_BLOCK_ALL, 1048 port, &entry)); 1049 index = soc_mem_field32_get(unit, PORT_TABm, &entry, TRUST_DSCP_PTRf); 1050 1051 SOC_IF_ERROR_RETURN(_bcm_dscp_table_entry_reference(unit, index * 64, 1052 64)); 1053 } 1054 1055 /* Update PORT_COS_MAP memory profile reference counter */ 1056 profile_mem = _bcm_td2_cos_map_profile[unit]; 1057 PBMP_ALL_ITER(unit, port) { 1058 if (IS_LB_PORT(unit, port)) { 1059 continue; 1060 } 1061 SOC_IF_ERROR_RETURN 1062 (soc_mem_read(unit, COS_MAP_SELm, MEM_BLOCK_ALL, port, &entry)); 1063 set_index = soc_mem_field32_get(unit, COS_MAP_SELm, &entry, SELECTf); 1064 SOC_IF_ERROR_RETURN 1065 (soc_profile_mem_reference(unit, profile_mem, set_index * 16, 16)); 1066 } 1067 if (SOC_INFO(unit).cpu_hg_index != -1) { 1068 SOC_IF_ERROR_RETURN(soc_mem_read(unit, COS_MAP_SELm, MEM_BLOCK_ALL, 1069 SOC_INFO(unit).cpu_hg_index, &entry)); 1070 set_index = soc_mem_field32_get(unit, COS_MAP_SELm, &entry, SELECTf); 1071 SOC_IF_ERROR_RETURN 1072 (soc_profile_mem_reference(unit, profile_mem, set_index * 16, 16)); 1073 } 1074 1075 for (pipe = 0; pipe < 2; pipe++) { 1076 mem = (pipe == _TD2_XPIPE) ? 1077 MMU_WRED_CONFIG_X_PIPEm : MMU_WRED_CONFIG_Y_PIPEm; 1078 for (ii = soc_mem_index_min(unit, mem); 1079 ii <= soc_mem_index_max(unit, mem); ii++) { 1080 BCM_IF_ERROR_RETURN( 1081 soc_mem_read(unit, mem, MEM_BLOCK_ALL, ii, &qentry)); 1082 1083 profile_index = soc_mem_field32_get(unit, mem, &qentry, PROFILE_INDEXf); 1084 1085 BCM_IF_ERROR_RETURN 1086 (soc_profile_mem_reference(unit, _bcm_td2_wred_profile[pipe][unit], 1087 profile_index, 1)); 1088 } 1089 } 1090 1091 /* Update PRIO2COS_LLFC register profile reference counter */ 1092 profile_reg = _bcm_td2_llfc_profile[unit]; 1093 PBMP_PORT_ITER(unit, port) { 1094 phy_port = si->port_l2p_mapping[port]; 1095 mmu_port = si->port_p2m_mapping[phy_port]; 1096 if (mmu_port == -1) { 1097 continue; 1098 } 1099 reg = llfc_cfgr[mmu_port/32]; 1100 BCM_IF_ERROR_RETURN(soc_reg64_get(unit, reg, 0, 0, &rval)); 1101 1102 index_map = soc_reg64_field_get(unit, reg, rval, PROFILE_INDEXf); 1103 COMPILER_64_SHR(index_map, ((mmu_port % 32) * 2)); 1104 COMPILER_64_TO_32_LO(tmp32, index_map); 1105 set_index = (tmp32 & 3); 1106 SOC_IF_ERROR_RETURN 1107 (soc_profile_reg_reference(unit, profile_reg, set_index * 16, 16)); 1108 } 1109 1110 return BCM_E_NONE; 1111 } 1112 1113 /* 1114 * Function: 1115 * bcm_td2_cosq_endpoint_sync 1116 * Purpose: 1117 * Sync endpoint info to scache. 1118 * Parameters: 1119 * unit - (IN) StrataSwitch unit # 1120 * scache_ptr - (IN/OUT) Scache pointer 1121 * Returns: 1122 * BCM_E_xxx 1123 */ 1124 STATIC int 1125 bcm_td2_cosq_endpoint_sync(int unit, uint8 **scache_ptr) 1126 { 1127 uint32 endpoint_flags, entry_size; 1128 int ii; 1129 int profile_num; 1130 soc_profile_mem_t *profile_mem; 1131 uint16 *u16_scache_ptr; 1132 int ref_count; 1133 int rv = BCM_E_NONE; 1134 1135 /* entry 0 was reserved and is not synced. */ 1136 entry_size = sizeof(uint32)+ sizeof(bcm_vrf_t) + sizeof(bcm_ip6_t); 1137 for (ii = 1; ii < _BCM_TD2_NUM_ENDPOINT(unit); ii++) { 1138 if (_BCM_TD2_ENDPOINT_IS_USED(unit, ii)) { 1139 endpoint_flags = _BCM_TD2_ENDPOINT(unit, ii)->flags; 1140 if (endpoint_flags & BCM_COSQ_CLASSIFIER_L2) { 1141 sal_memcpy((*scache_ptr), &endpoint_flags, sizeof(uint32)); 1142 (*scache_ptr) += sizeof(uint32); 1143 sal_memcpy((*scache_ptr), &(_BCM_TD2_ENDPOINT(unit, ii)->vlan), 1144 sizeof(bcm_vlan_t)); 1145 (*scache_ptr) += sizeof(bcm_vlan_t); 1146 sal_memcpy((*scache_ptr), _BCM_TD2_ENDPOINT(unit, ii)->mac, 1147 sizeof(bcm_mac_t)); 1148 (*scache_ptr) += (entry_size - sizeof(uint32) - sizeof(bcm_vlan_t)); 1149 } else if (endpoint_flags & BCM_COSQ_CLASSIFIER_L3) { 1150 sal_memcpy((*scache_ptr), &endpoint_flags, sizeof(uint32)); 1151 (*scache_ptr) += sizeof(uint32); 1152 sal_memcpy((*scache_ptr), &(_BCM_TD2_ENDPOINT(unit, ii)->vrf), 1153 sizeof(bcm_vrf_t)); 1154 (*scache_ptr) += sizeof(bcm_vrf_t); 1155 if (endpoint_flags & BCM_COSQ_CLASSIFIER_IP6) { 1156 sal_memcpy((*scache_ptr), 1157 _BCM_TD2_ENDPOINT(unit, ii)->ip6_addr, 1158 sizeof(bcm_ip6_t)); 1159 } else { 1160 sal_memcpy((*scache_ptr), 1161 &(_BCM_TD2_ENDPOINT(unit, ii)->ip_addr), 1162 sizeof(bcm_ip_t)); 1163 } 1164 (*scache_ptr) += (entry_size - sizeof(uint32) - sizeof(bcm_vrf_t)); 1165 } else if (endpoint_flags & BCM_COSQ_CLASSIFIER_GPORT) { 1166 sal_memcpy((*scache_ptr), &endpoint_flags, sizeof(uint32)); 1167 (*scache_ptr) += sizeof(uint32); 1168 sal_memcpy((*scache_ptr), &(_BCM_TD2_ENDPOINT(unit, ii)->gport), 1169 sizeof(bcm_gport_t)); 1170 (*scache_ptr) += (entry_size - sizeof(uint32)); 1171 } else if (endpoint_flags & BCM_COSQ_CLASSIFIER_L3_EGRESS) { 1172 sal_memcpy((*scache_ptr), &endpoint_flags, sizeof(uint32)); 1173 (*scache_ptr) += sizeof(uint32); 1174 sal_memcpy((*scache_ptr), &(_BCM_TD2_ENDPOINT(unit, ii)->egress_if), 1175 sizeof(bcm_if_t)); 1176 (*scache_ptr) += (entry_size - sizeof(uint32)); 1177 } else { 1178 return BCM_E_INTERNAL; 1179 } 1180 } else { 1181 sal_memset((*scache_ptr), 0, entry_size); 1182 (*scache_ptr) += entry_size; 1183 } 1184 } 1185 1186 u16_scache_ptr = (uint16 *)(*scache_ptr); 1187 1188 profile_num = SOC_MEM_SIZE(unit, ENDPOINT_COS_MAPm) / 1189 _TD2_EPCM_ENTRIES_PER_SET; 1190 profile_mem = _BCM_TD2_ENDPOINT_COS_MAP_PROFILE(unit); 1191 for (ii = 0; ii < profile_num; ii++) { 1192 ref_count = 0; 1193 rv = soc_profile_mem_ref_count_get( 1194 unit, profile_mem, ii * _TD2_EPCM_ENTRIES_PER_SET, &ref_count); 1195 if (!(rv == SOC_E_NOT_FOUND || rv == SOC_E_NONE)) { 1196 return rv; 1197 } 1198 *u16_scache_ptr++ = (uint16)(ref_count & 0xffff); 1199 } 1200 *scache_ptr = (uint8 *)u16_scache_ptr; 1201 1202 return BCM_E_NONE; 1203 } 1204 1205 int 1206 bcm_td2_cosq_sync(int unit) 1207 { 1208 soc_scache_handle_t scache_handle; 1209 uint8 *scache_ptr, *u8_scache_ptr; 1210 uint32 *u32_scache_ptr; 1211 uint16 *u16_scache_ptr; 1212 _bcm_td2_cosq_node_t *node; 1213 int node_list_sizes[3], ii, jj, cosq; 1214 _bcm_td2_cosq_node_t *nodes[3]; 1215 int xnode_id, node_size, count, pipe; 1216 uint32 *psize; 1217 _bcm_td2_mmu_info_t *mmu_info; 1218 int alloc_size; 1219 int rv = BCM_E_NONE; 1220 int ref_count; 1221 int profile_num; 1222 soc_profile_mem_t *profile_mem; 1223 1224 mmu_info = _bcm_td2_mmu_info[unit]; 1225 1226 if (!mmu_info) { 1227 return BCM_E_INIT; 1228 } 1229 if ((SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit))) { 1230 /* COSQ warmboot requires extended scache support i.e. level2 warmboot*/ 1231 return BCM_E_NONE; 1232 } 1233 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_COSQ, 0); 1234 BCM_IF_ERROR_RETURN 1235 (_bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 0, 1236 &scache_ptr, BCM_WB_DEFAULT_VERSION, NULL)); 1237 1238 u32_scache_ptr = (uint32*) scache_ptr; 1239 1240 nodes[0] = &mmu_info->queue_node[0]; 1241 node_list_sizes[0] = _BCM_TD2_NUM_L2_UC_LEAVES; 1242 nodes[1] = &mmu_info->mc_queue_node[0]; 1243 node_list_sizes[1] = _BCM_TD2_NUM_L2_MC_LEAVES; 1244 nodes[2] = &mmu_info->sched_node[0]; 1245 node_list_sizes[2] = _BCM_TD2_NUM_TOTAL_SCHEDULERS; 1246 1247 for(ii = 0; ii < 3; ii++) { 1248 psize = u32_scache_ptr++; 1249 for(count = 0, jj = 0; jj < node_list_sizes[ii]; jj++) { 1250 node = nodes[ii] + jj; 1251 if (node->in_use == FALSE) { 1252 continue; 1253 } 1254 count += 1; 1255 node_size = 3; 1256 if ((node->remote_modid != -1) || (node->remote_port != -1) || 1257 (node->hw_cosq != -1)) { 1258 node_size += 1; 1259 } 1260 1261 if (node->parent == NULL) { 1262 xnode_id = 0x800; 1263 } else { 1264 xnode_id = _BCM_TD2_NODE_ID(node->parent, mmu_info->sched_node); 1265 } 1266 1267 pipe = _BCM_TD2_PORT_TO_PIPE(unit, node->local_port); 1268 1269 *u32_scache_ptr++ = _BCM_TD2_WB_SET_NODE_W1(ii, jj, node_size, xnode_id, pipe); 1270 cosq = ((node->attached_to_input == -1) ? 0x8 : node->attached_to_input); 1271 1272 *u32_scache_ptr++ = _BCM_TD2_WB_SET_NODE_W2( 1273 (node->hw_index == -1) ? 0x1000 : node->hw_index, 1274 ((node->hw_cosq == -1) ? 8 : node->hw_cosq), cosq, node->level, 1275 ((node->node_align_value == _BCM_TD2_START_INDEX_ALIGN_PFC) ? 1 : 0)); 1276 1277 *u32_scache_ptr++ = _BCM_TD2_WB_SET_NODE_W3(node->gport); 1278 1279 if ((node->remote_modid != -1) || (node->remote_port != -1) || 1280 (node->hw_cosq != -1)) { 1281 node_size += 1; 1282 *u32_scache_ptr++ = _BCM_TD2_WB_SET_NODE_W4( 1283 (node->remote_modid == -1) ? 0x100 : node->remote_modid, 1284 (node->remote_port == -1) ? 0x100 : node->remote_port, 1285 (node->hw_cosq == -1) ? 0x8 : node->hw_cosq); 1286 } 1287 } 1288 *psize = count; 1289 } 1290 1291 /* Sync TIME_DOMAINr field and count reference */ 1292 alloc_size = _TD2_NUM_TIME_DOMAIN * sizeof(_bcm_td2_cosq_time_info_t); 1293 sal_memcpy(u32_scache_ptr, &time_domain[0], alloc_size); 1294 u32_scache_ptr += alloc_size / sizeof(uint32); 1295 soc_trident2_fc_map_shadow_sync(unit, &u32_scache_ptr); 1296 1297 for (ii = 0; ii < 3; ii++) { 1298 for (count = 0, jj = 0; jj < node_list_sizes[ii]; jj++) { 1299 node = nodes[ii] + jj; 1300 if (node->in_use == FALSE) { 1301 continue; 1302 } 1303 1304 *u32_scache_ptr++ = _BCM_TD2_WB_SET_NODE_W5( 1305 (node->numq_expandable), (node->type), 1306 ((node->attached_to_input == -1) ? 0x800 : 1307 node->attached_to_input), 1308 ((node->hw_cosq == -1) ? 0x800 : node->hw_cosq)); 1309 1310 *u32_scache_ptr++ = _BCM_TD2_WB_SET_NODE_W6( 1311 (node->base_size), 1312 ((node->base_index == -1 ) ? 0x400 : node->base_index), 1313 ((node->numq == -1 ) ? 0x600 : node->numq)); 1314 } 1315 } 1316 1317 *u32_scache_ptr++ = mmu_info->ets_mode; 1318 *u32_scache_ptr++ = mmu_info->curr_shared_limit; 1319 1320 u16_scache_ptr = (uint16 *)u32_scache_ptr; 1321 for (ii = 0; 1322 ii < (SOC_MEM_SIZE(unit, IFP_COS_MAPm) / _TD2_NUM_INTERNAL_PRI); 1323 ii++) { 1324 rv = soc_profile_mem_ref_count_get(unit, 1325 _bcm_td2_ifp_cos_map_profile[unit], 1326 ii * _TD2_NUM_INTERNAL_PRI, 1327 &ref_count); 1328 if (!(rv == SOC_E_NOT_FOUND || rv == SOC_E_NONE)) { 1329 return rv; 1330 } 1331 *u16_scache_ptr++ = (uint16)(ref_count & 0xffff); 1332 } 1333 1334 profile_num = SOC_MEM_SIZE(unit, SERVICE_COS_MAPm) / 1335 _TD2_SCM_ENTRIES_PER_SET; 1336 profile_mem = _bcm_td2_service_cos_map_profile[unit]; 1337 for (ii = 0; ii < profile_num; ii++) { 1338 ref_count = 0; 1339 rv = soc_profile_mem_ref_count_get( 1340 unit, profile_mem, ii * _TD2_SCM_ENTRIES_PER_SET, &ref_count); 1341 if (!(rv == SOC_E_NOT_FOUND || rv == SOC_E_NONE)) { 1342 return rv; 1343 } 1344 *u16_scache_ptr++ = (uint16)(ref_count & 0xffff); 1345 } 1346 1347 profile_num = SOC_MEM_SIZE(unit, SERVICE_PORT_MAPm) / 1348 _TD2_SPM_ENTRIES_PER_SET; 1349 profile_mem = _bcm_td2_service_port_map_profile[unit]; 1350 for (ii = 0; ii < profile_num; ii++) { 1351 ref_count = 0; 1352 rv = soc_profile_mem_ref_count_get( 1353 unit, profile_mem, ii * _TD2_SPM_ENTRIES_PER_SET, &ref_count); 1354 if (!(rv == SOC_E_NOT_FOUND || rv == SOC_E_NONE)) { 1355 return rv; 1356 } 1357 *u16_scache_ptr++ = (uint16)(ref_count & 0xffff); 1358 } 1359 1360 scache_ptr = (uint8 *)u16_scache_ptr; 1361 1362 BCM_IF_ERROR_RETURN(soc_td2_mmu_traffic_ctrl_wb_sync(unit, &scache_ptr)); 1363 1364 u32_scache_ptr = (uint32 *) scache_ptr; 1365 *u32_scache_ptr++ = NUM_COS(unit); 1366 scache_ptr = (uint8*)u32_scache_ptr; 1367 1368 /* BCM_WB_VERSION_1_6: Sync DMVOQ fabric parameter & curr_merger_index. */ 1369 *u32_scache_ptr++ = sizeof(bcm_pbmp_t); 1370 u8_scache_ptr = (uint8 *)u32_scache_ptr; 1371 for (ii = 0; ii < 3; ii++) { 1372 for (count = 0, jj = 0; jj < node_list_sizes[ii]; jj++) { 1373 node = nodes[ii] + jj; 1374 if (node->in_use == FALSE) { 1375 continue; 1376 } 1377 sal_memcpy(u8_scache_ptr, &node->fabric_pbmp, sizeof(bcm_pbmp_t)); 1378 u8_scache_ptr += sizeof(bcm_pbmp_t); 1379 } 1380 } 1381 u32_scache_ptr = (uint32 *)u8_scache_ptr; 1382 *u32_scache_ptr++ = mmu_info->curr_merger_index; 1383 1384 /* BCM_WB_VERSION_1_7 Sync endpoint info. 1385 * In order to save scache, each entry size is fixed. 1386 * entry_size = sizeof(uint32)+ sizeof(bcm_vrf_t) + sizeof(bcm_ip6_t). 1387 * entry 0 was reserved and is not synced. 1388 */ 1389 if (soc_feature(unit, soc_feature_endpoint_queuing)) { 1390 u8_scache_ptr = (uint8 *)u32_scache_ptr; 1391 BCM_IF_ERROR_RETURN( 1392 bcm_td2_cosq_endpoint_sync(unit, &u8_scache_ptr)); 1393 } 1394 1395 return BCM_E_NONE; 1396 } 1397 1398 #endif /* BCM_WARM_BOOT_SUPPORT */ 1399 1400 #ifndef BCM_SW_STATE_DUMP_DISABLE 1401 STATIC char* 1402 _bcm_td2_cosq_node_lvl_str(soc_td2_node_lvl_e lvl) 1403 { 1404 switch(lvl) { 1405 case SOC_TD2_NODE_LVL_ROOT: 1406 return "Root"; 1407 break; 1408 case SOC_TD2_NODE_LVL_L0: 1409 return " L0"; 1410 break; 1411 case SOC_TD2_NODE_LVL_L1: 1412 return " L1"; 1413 break; 1414 case SOC_TD2_NODE_LVL_L2: 1415 return " Q"; 1416 break; 1417 case SOC_TD2_NODE_LVL_MAX: 1418 break; 1419 } 1420 return ""; 1421 } 1422 1423 STATIC void 1424 _bcm_td2_cosq_dump_node(_bcm_td2_cosq_node_t *node, int loff) 1425 { 1426 LOG_CLI((BSL_META("%s.%d index=%d cosq=%d gport=0x%08x numq=%d\n"), 1427 _bcm_td2_cosq_node_lvl_str(node->level), 1428 loff, 1429 node->hw_index, 1430 node->attached_to_input, 1431 node->gport, 1432 node->numq)); 1433 1434 if (node->child) { 1435 _bcm_td2_cosq_dump_node(node->child, 0); 1436 } 1437 1438 if (node->sibling) { 1439 _bcm_td2_cosq_dump_node(node->sibling, loff+1); 1440 } 1441 } 1442 1443 STATIC void 1444 _bcm_td2_cosq_port_sw_dump(int unit, bcm_port_t port) 1445 { 1446 _bcm_td2_mmu_info_t *mmu_info; 1447 int phy_port, mmu_port; 1448 soc_info_t *si; 1449 bcm_port_t local_port; 1450 int rv; 1451 _bcm_td2_cosq_node_t *node = NULL; 1452 1453 si = &SOC_INFO(unit); 1454 mmu_info = _bcm_td2_mmu_info[unit]; 1455 1456 phy_port = si->port_l2p_mapping[port]; 1457 1458 if (phy_port == -1) { 1459 return; 1460 } 1461 1462 mmu_port = si->port_p2m_mapping[phy_port]; 1463 1464 if (mmu_port == -1) { 1465 return; 1466 } 1467 1468 rv = _bcm_td2_cosq_localport_resolve(unit, port, &local_port); 1469 if (BCM_FAILURE(rv) || (local_port < 0)) { 1470 return; 1471 } 1472 node = &mmu_info->sched_node[local_port]; 1473 1474 if (node == NULL) { 1475 return; 1476 } 1477 1478 LOG_CLI((BSL_META("Logical Port: %d, Physical Port: %d\n"), 1479 port, 1480 phy_port)); 1481 1482 _bcm_td2_cosq_dump_node(node, 0); 1483 1484 return; 1485 } 1486 #endif /* BCM_SW_STATE_DUMP_DISABLEP */ 1487 1488 /* 1489 * Function: 1490 * bcm_td2_cosq_sw_dump 1491 * Purpose: 1492 * Displays COS Queue information maintained by software. 1493 * Parameters: 1494 * unit - Device unit number 1495 * Returns: 1496 * None 1497 */ 1498 void 1499 bcm_td2_cosq_sw_dump(int unit) 1500 { 1501 #ifndef BCM_SW_STATE_DUMP_DISABLE 1502 bcm_port_t port; 1503 1504 PBMP_ALL_ITER(unit, port) { 1505 _bcm_td2_cosq_port_sw_dump(unit, port); 1506 } 1507 #endif 1508 return; 1509 } 1510 1511 /* 1512 * Function: 1513 * _bcm_td2_cosq_localport_resolve 1514 * Purpose: 1515 * Resolve GRPOT if it is a local port 1516 * Parameters: 1517 * unit - (IN) unit number 1518 * gport - (IN) GPORT identifier 1519 * local_port - (OUT) local port number 1520 * Returns: 1521 * BCM_E_XXX 1522 */ 1523 int 1524 _bcm_td2_cosq_localport_resolve(int unit, bcm_gport_t gport, 1525 bcm_port_t *local_port) 1526 { 1527 bcm_module_t module; 1528 bcm_port_t port; 1529 bcm_trunk_t trunk; 1530 int id, result; 1531 1532 if (!BCM_GPORT_IS_SET(gport)) { 1533 if (!SOC_PORT_VALID(unit, gport)) { 1534 return BCM_E_PORT; 1535 } 1536 *local_port = gport; 1537 return BCM_E_NONE; 1538 } 1539 1540 BCM_IF_ERROR_RETURN 1541 (_bcm_esw_gport_resolve(unit, gport, &module, &port, &trunk, &id)); 1542 1543 BCM_IF_ERROR_RETURN(_bcm_esw_modid_is_local(unit, module, &result)); 1544 if (result == FALSE) { 1545 return BCM_E_PARAM; 1546 } 1547 1548 *local_port = port; 1549 1550 return BCM_E_NONE; 1551 } 1552 1553 STATIC int 1554 _bcm_td2_cosq_port_has_ets(int unit, bcm_port_t port) 1555 { 1556 _bcm_td2_mmu_info_t *mmu_info = _bcm_td2_mmu_info[unit]; 1557 return mmu_info->ets_mode; 1558 } 1559 1560 /* 1561 * Function: 1562 * _bcm_td2_node_index_get 1563 * Purpose: 1564 * Allocate free index from the given list 1565 * Parameters: 1566 * list - (IN) bit list 1567 * start - (IN) start index 1568 * end - (IN) end index 1569 * qset - (IN) size of queue set 1570 * range - (IN) range bits 1571 * id - (OUT) start index 1572 * Returns: 1573 * BCM_E_XXX 1574 */ 1575 STATIC int 1576 _bcm_td2_node_index_get(SHR_BITDCL *list, int start, int end, 1577 int count, int align, int *id) 1578 { 1579 int i, j, range_empty; 1580 1581 *id = -1; 1582 1583 if ((align <= 0) || (count == 0)) { 1584 return BCM_E_PARAM; 1585 } 1586 1587 if (start & (align - 1)) { 1588 start = (start + align - 1) & ~(align - 1); 1589 } 1590 1591 end = end - align + 1; 1592 1593 for (i = start; i < end; i += align) { 1594 range_empty = 1; 1595 if ((i + count) <= end){ 1596 for (j = i; j < (i + count); j++) { 1597 if (SHR_BITGET(list, j) != 0) { 1598 range_empty = 0; 1599 break; 1600 } 1601 } 1602 1603 if (range_empty) { 1604 *id = i; 1605 return BCM_E_NONE; 1606 } 1607 } else { 1608 return BCM_E_RESOURCE; 1609 } 1610 } 1611 return BCM_E_RESOURCE; 1612 } 1613 1614 /* 1615 * Function: 1616 * _bcm_td2_node_index_set 1617 * Purpose: 1618 * Mark indices as allocated 1619 * Parameters: 1620 * list - (IN) bit list 1621 * start - (IN) start index 1622 * range - (IN) range bits 1623 * Returns: 1624 * BCM_E_XXX 1625 */ 1626 STATIC int 1627 _bcm_td2_node_index_set(_bcm_td2_cosq_list_t *list, int start, int range) 1628 { 1629 if (range == 0) { 1630 return BCM_E_NONE; 1631 } 1632 if ((start < 0) || 1633 (range < 0) || 1634 ((start + range) > list->count)) { 1635 return BCM_E_INTERNAL; 1636 } 1637 SHR_BITSET_RANGE(list->bits, start, range); 1638 1639 return BCM_E_NONE; 1640 } 1641 1642 /* 1643 * Function: 1644 * _bcm_td2_node_index_clear 1645 * Purpose: 1646 * Mark indices as free 1647 * Parameters: 1648 * list - (IN) bit list 1649 * start - (IN) start index 1650 * range - (IN) range bits 1651 * Returns: 1652 * BCM_E_XXX 1653 */ 1654 STATIC int 1655 _bcm_td2_node_index_clear(_bcm_td2_cosq_list_t *list, int start, int range) 1656 { 1657 if (range == 0) { 1658 return BCM_E_NONE; 1659 } 1660 if ((start < 0) || 1661 (range < 0) || 1662 ((start + range) > list->count)) { 1663 return BCM_E_INTERNAL; 1664 } 1665 SHR_BITCLR_RANGE(list->bits, start, range); 1666 1667 return BCM_E_NONE; 1668 } 1669 1670 /* 1671 * Function: 1672 * _bcm_td2_cosq_alloc_clear 1673 * Purpose: 1674 * Allocate cosq memory and clear 1675 * Parameters: 1676 * size - (IN) size of memory required 1677 * description- (IN) description about the structure 1678 * Returns: 1679 * BCM_E_XXX 1680 */ 1681 STATIC void * 1682 _bcm_td2_cosq_alloc_clear(void *cp, unsigned int size, char *description) 1683 { 1684 void *block_p; 1685 1686 block_p = (cp) ? cp : sal_alloc(size, description); 1687 1688 if (block_p != NULL) { 1689 sal_memset(block_p, 0, size); 1690 } 1691 1692 return block_p; 1693 } 1694 1695 /* 1696 * Function: 1697 * _bcm_td2_cosq_free_memory 1698 * Purpose: 1699 * Free memory allocated for mmu info members 1700 * Parameters: 1701 * mmu_info - (IN) MMU info pointer 1702 * Returns: 1703 * BCM_E_XXX 1704 */ 1705 STATIC void 1706 _bcm_td2_cosq_free_memory(_bcm_td2_mmu_info_t *mmu_info_p) 1707 { 1708 int pipe; 1709 _bcm_td2_pipe_resources_t *res; 1710 1711 if (mmu_info_p == NULL) { 1712 return; 1713 } 1714 for (pipe = _TD2_XPIPE; pipe <= _TD2_YPIPE; pipe++) { 1715 res = _BCM_TD2_PRESOURCES(mmu_info_p, pipe); 1716 if (res->ext_qlist.bits != NULL) { 1717 sal_free(res->ext_qlist.bits); 1718 res->ext_qlist.bits = NULL; 1719 } 1720 if (res->l0_sched_list.bits != NULL) { 1721 sal_free(res->l0_sched_list.bits); 1722 res->l0_sched_list.bits = NULL; 1723 } 1724 if (res->l1_sched_list.bits != NULL) { 1725 sal_free(res->l1_sched_list.bits); 1726 res->l1_sched_list.bits = NULL; 1727 } 1728 } 1729 } 1730 1731 /* 1732 * Function: 1733 * _bcm_td2_cosq_node_get 1734 * Purpose: 1735 * Get internal information of queue group or scheduler type GPORT 1736 * Parameters: 1737 * unit - (IN) unit number 1738 * gport - (IN) queue group/scheduler GPORT identifier 1739 * modid - (OUT) module identifier 1740 * port - (OUT) port number 1741 * id - (OUT) queue group or scheduler identifier 1742 * node - (OUT) node structure for the specified GPORT 1743 * Returns: 1744 * BCM_E_XXX 1745 */ 1746 STATIC int 1747 _bcm_td2_cosq_node_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 1748 bcm_module_t *modid, bcm_port_t *port, 1749 int *id, _bcm_td2_cosq_node_t **node) 1750 { 1751 _bcm_td2_mmu_info_t *mmu_info; 1752 _bcm_td2_cosq_node_t *node_base = NULL; 1753 bcm_module_t modid_out = 0; 1754 bcm_port_t port_out = 0; 1755 uint32 encap_id = -1; 1756 int index; 1757 1758 if ((mmu_info = _bcm_td2_mmu_info[unit]) == NULL) { 1759 return BCM_E_INIT; 1760 } 1761 1762 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 1763 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid_out)); 1764 port_out = BCM_GPORT_UCAST_QUEUE_GROUP_SYSPORTID_GET(gport); 1765 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 1766 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid_out)); 1767 port_out = BCM_GPORT_MCAST_QUEUE_GROUP_SYSPORTID_GET(gport); 1768 } else if (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport)) { 1769 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid_out)); 1770 port_out = (gport >> 16) & 0xff; 1771 } else if (BCM_GPORT_IS_SCHEDULER(gport)) { 1772 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid_out)); 1773 port_out = BCM_GPORT_SCHEDULER_GET(gport) & 0xff; 1774 } else if (BCM_GPORT_IS_LOCAL(gport)) { 1775 encap_id = BCM_GPORT_LOCAL_GET(gport); 1776 port_out = encap_id; 1777 } else if (BCM_GPORT_IS_MODPORT(gport)) { 1778 modid_out = SOC_GPORT_MODPORT_MODID_GET(gport); 1779 port_out = SOC_GPORT_MODPORT_PORT_GET(gport); 1780 encap_id = port_out; 1781 } else { 1782 return BCM_E_PORT; 1783 } 1784 1785 if (!SOC_PORT_VALID(unit, port_out)) { 1786 return BCM_E_PORT; 1787 } 1788 1789 if (port != NULL) { 1790 *port = port_out; 1791 } 1792 1793 if (!_bcm_td2_cosq_port_has_ets(unit, port_out)) { 1794 return BCM_E_NOT_FOUND; 1795 } 1796 1797 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 1798 encap_id = BCM_GPORT_UCAST_QUEUE_GROUP_QID_GET(gport); 1799 index = encap_id; 1800 node_base = mmu_info->queue_node; 1801 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 1802 encap_id = BCM_GPORT_MCAST_QUEUE_GROUP_QID_GET(gport); 1803 index = encap_id; 1804 node_base = mmu_info->mc_queue_node; 1805 } else if (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport)) { 1806 encap_id = BCM_GPORT_UCAST_SUBSCRIBER_QUEUE_GROUP_QID_GET(gport); 1807 index = encap_id; 1808 node_base = mmu_info->queue_node; 1809 } else if (BCM_GPORT_IS_SCHEDULER(gport)) { 1810 encap_id = (BCM_GPORT_SCHEDULER_GET(gport) >> 8) & 0x3fff; 1811 index = encap_id; 1812 node_base = mmu_info->sched_node; 1813 } else { 1814 index = encap_id; 1815 node_base = mmu_info->sched_node; 1816 } 1817 1818 if (index < 0) { 1819 return BCM_E_NOT_FOUND; 1820 } 1821 1822 if (node_base[index].numq == 0) { 1823 return BCM_E_NOT_FOUND; 1824 } 1825 1826 if (modid != NULL) { 1827 *modid = modid_out; 1828 } 1829 if (id != NULL) { 1830 *id = encap_id; 1831 } 1832 if (node != NULL) { 1833 *node = &node_base[index]; 1834 if (*node) { 1835 _bcm_td2_cosq_node_t *tmp_node; 1836 tmp_node = *node; 1837 if (tmp_node->type == _BCM_TD2_NODE_SERVICE_UCAST) { 1838 *node = &node_base[index + cosq]; 1839 if (id != NULL) { 1840 *id = tmp_node->hw_index; 1841 } 1842 } 1843 } 1844 1845 } 1846 1847 return BCM_E_NONE; 1848 } 1849 1850 int 1851 _bcm_td2_cosq_port_resolve(int unit, bcm_gport_t gport, bcm_module_t *modid, 1852 bcm_port_t *port, bcm_trunk_t *trunk_id, int *id, 1853 int *qnum) 1854 { 1855 _bcm_td2_cosq_node_t *node; 1856 1857 BCM_IF_ERROR_RETURN 1858 (_bcm_td2_cosq_node_get(unit, gport, 0, modid, port, id, &node)); 1859 *trunk_id = -1; 1860 1861 if (qnum) { 1862 if (node->hw_index == -1) { 1863 return BCM_E_PARAM; 1864 } 1865 *qnum = node->hw_index; 1866 } 1867 1868 return BCM_E_NONE; 1869 } 1870 1871 /* 1872 * Function: 1873 * _bcm_td2_cosq_gport_traverse 1874 * Purpose: 1875 * Walks through the valid COSQ GPORTs and calls 1876 * the user supplied callback function for each entry. 1877 * Parameters: 1878 * unit - (IN) unit number 1879 * gport - (IN) 1880 * cb - (IN) Callback function. 1881 * user_data - (IN) User data to be passed to callback function 1882 * Returns: 1883 * BCM_E_NONE - Success. 1884 * BCM_E_XXX 1885 */ 1886 int 1887 _bcm_td2_cosq_gport_traverse(int unit, bcm_gport_t gport, 1888 bcm_cosq_gport_traverse_cb cb, 1889 void *user_data) 1890 { 1891 _bcm_td2_cosq_node_t *node; 1892 uint32 flags = BCM_COSQ_GPORT_SCHEDULER; 1893 int rv = BCM_E_NONE; 1894 1895 BCM_IF_ERROR_RETURN 1896 (_bcm_td2_cosq_node_get(unit, gport, 0, NULL, NULL, NULL, &node)); 1897 1898 if (node != NULL) { 1899 if (node->level == SOC_TD2_NODE_LVL_L2) { 1900 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(node->gport)) { 1901 flags = BCM_COSQ_GPORT_UCAST_QUEUE_GROUP; 1902 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(node->gport)) { 1903 flags = BCM_COSQ_GPORT_MCAST_QUEUE_GROUP; 1904 } 1905 } else { 1906 flags = BCM_COSQ_GPORT_SCHEDULER; 1907 if (node->node_align_value == _BCM_TD2_START_INDEX_ALIGN_PFC) { 1908 flags |= BCM_COSQ_GPORT_SCHEDULER_PFC_ALIGN; 1909 } 1910 } 1911 rv = cb(unit, gport, node->numq, flags, 1912 node->gport, user_data); 1913 if (BCM_FAILURE(rv)) { 1914 #ifdef BCM_CB_ABORT_ON_ERR 1915 if (SOC_CB_ABORT_ON_ERR(unit)) { 1916 return rv; 1917 } 1918 #endif 1919 } 1920 } else { 1921 return BCM_E_NONE; 1922 } 1923 1924 if (node->sibling != NULL) { 1925 _bcm_td2_cosq_gport_traverse(unit, node->sibling->gport, cb, user_data); 1926 } 1927 1928 if (node->child != NULL) { 1929 _bcm_td2_cosq_gport_traverse(unit, node->child->gport, cb, user_data); 1930 } 1931 1932 return BCM_E_NONE; 1933 } 1934 1935 STATIC int 1936 _bcm_td2_cosq_child_node_at_input(_bcm_td2_cosq_node_t *node, int cosq, 1937 _bcm_td2_cosq_node_t **child_node) 1938 { 1939 _bcm_td2_cosq_node_t *cur_node; 1940 1941 for (cur_node = node->child; cur_node; cur_node = cur_node->sibling) { 1942 if (cur_node->attached_to_input == cosq) { 1943 break; 1944 } 1945 } 1946 if (!cur_node) { 1947 return BCM_E_NOT_FOUND; 1948 } 1949 1950 *child_node = cur_node; 1951 1952 return BCM_E_NONE; 1953 } 1954 1955 STATIC int 1956 _bcm_td2_cosq_l2_gport(int unit, int port, int cosq, 1957 _bcm_td2_node_type_e type, bcm_gport_t *gport, 1958 _bcm_td2_cosq_node_t **p_node) 1959 { 1960 int i, max; 1961 _bcm_td2_cosq_node_t *node, *fnode; 1962 _bcm_td2_mmu_info_t *mmu_info; 1963 _bcm_td2_cosq_port_info_t *port_info; 1964 _bcm_td2_pipe_resources_t *res; 1965 1966 mmu_info = _bcm_td2_mmu_info[unit]; 1967 port_info = &mmu_info->port_info[port]; 1968 res = port_info->resources; 1969 1970 max = 0; 1971 if ((type == _BCM_TD2_NODE_UCAST) || (type == _BCM_TD2_NODE_VOQ) || 1972 (type == _BCM_TD2_NODE_VLAN_UCAST) || (type == _BCM_TD2_NODE_VM_UCAST) || 1973 (type == _BCM_TD2_NODE_SERVICE_UCAST)) { 1974 max = _BCM_TD2_NUM_L2_UC_LEAVES; 1975 fnode = &res->p_queue_node[0]; 1976 } else if (type == _BCM_TD2_NODE_MCAST) { 1977 max = _BCM_TD2_NUM_L2_MC_LEAVES; 1978 fnode = &res->p_mc_queue_node[0]; 1979 } else { 1980 return BCM_E_PARAM; 1981 } 1982 1983 for (i = 0; i < max; i++) { 1984 node = fnode + i; 1985 if (node->in_use && (node->local_port == port) && 1986 (node->type == type) && (node->hw_cosq == cosq)) { 1987 if (gport) { 1988 *gport = node->gport; 1989 } 1990 if (p_node) { 1991 *p_node = node; 1992 } 1993 return BCM_E_NONE; 1994 } 1995 } 1996 return BCM_E_NOT_FOUND; 1997 } 1998 1999 /* 2000 * Function: 2001 * _bcm_td2_cosq_index_resolve 2002 * Purpose: 2003 * Find hardware index for the given port/cosq 2004 * Parameters: 2005 * unit - (IN) unit number 2006 * port - (IN) port number or GPORT identifier 2007 * cosq - (IN) COS queue number 2008 * style - (IN) index style (_BCM_KA_COSQ_INDEX_STYLE_XXX) 2009 * local_port - (OUT) local port number 2010 * index - (OUT) result index 2011 * count - (OUT) number of index 2012 * Returns: 2013 * BCM_E_XXX 2014 */ 2015 int 2016 _bcm_td2_cosq_index_resolve(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 2017 _bcm_td2_cosq_index_style_t style, 2018 bcm_port_t *local_port, int *index, int *count) 2019 { 2020 _bcm_td2_cosq_node_t *node, *cur_node; 2021 bcm_port_t resolved_port; 2022 int resolved_index = -1; 2023 int id, startq, numq; 2024 soc_info_t *si; 2025 int phy_port, mmu_port, mmu_port_pipe_off; 2026 uint32 entry0[SOC_MAX_MEM_WORDS]; 2027 soc_mem_t mem; 2028 2029 si = &SOC_INFO(unit); 2030 2031 if (cosq < -1) { 2032 return BCM_E_PARAM; 2033 } else if (cosq == -1) { 2034 startq = 0; 2035 numq = NUM_COS(unit); 2036 } else { 2037 startq = cosq; 2038 numq = 1; 2039 } 2040 2041 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 2042 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) || 2043 BCM_GPORT_IS_SCHEDULER(port)) { 2044 BCM_IF_ERROR_RETURN 2045 (_bcm_td2_cosq_node_get(unit, port, cosq, NULL, &resolved_port, &id, 2046 &node)); 2047 if (node->attached_to_input < 0) { /* Not resolved yet */ 2048 return BCM_E_NOT_FOUND; 2049 } 2050 numq = (node->numq != -1) ? node->numq : 64; 2051 } else { 2052 /* optionally validate port */ 2053 BCM_IF_ERROR_RETURN 2054 (_bcm_td2_cosq_localport_resolve(unit, port, &resolved_port)); 2055 if (resolved_port < 0) { 2056 return BCM_E_PORT; 2057 } 2058 node = NULL; 2059 numq = (IS_CPU_PORT(unit, resolved_port)) ? NUM_CPU_COSQ(unit) : NUM_COS(unit); 2060 } 2061 2062 if (startq >= numq) { 2063 return BCM_E_PARAM; 2064 } 2065 2066 phy_port = si->port_l2p_mapping[resolved_port]; 2067 mmu_port = si->port_p2m_mapping[phy_port]; 2068 mmu_port_pipe_off = (mmu_port >= 64) ? mmu_port - 64 : mmu_port; 2069 2070 if ((node == NULL) && (BCM_GPORT_IS_MODPORT(port)) && 2071 (_bcm_td2_cosq_port_has_ets(unit, resolved_port))) { 2072 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_node_get(unit, port, 0, 2073 NULL, NULL, NULL, &node)); 2074 } 2075 2076 switch (style) { 2077 case _BCM_TD2_COSQ_INDEX_STYLE_BUCKET: 2078 if (node != NULL) { 2079 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) { 2080 resolved_index = node->hw_index; 2081 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 2082 resolved_index = node->hw_index; 2083 } else if (BCM_GPORT_IS_SCHEDULER(port) || BCM_GPORT_IS_MODPORT(port)) { 2084 /* resolve the child attached to input cosq */ 2085 BCM_IF_ERROR_RETURN( 2086 _bcm_td2_cosq_child_node_at_input(node, startq, &cur_node)); 2087 resolved_index = cur_node->hw_index; 2088 } else { 2089 return BCM_E_PARAM; 2090 } 2091 } else { /* node == NULL */ 2092 if (_bcm_td2_cosq_port_has_ets(unit, resolved_port)) { 2093 LOG_ERROR(BSL_LS_BCM_COSQ, 2094 (BSL_META_U(unit, "Not a GPORT type port in ETS mode.\n"))); 2095 return BCM_E_PARAM; 2096 } 2097 if (IS_CPU_PORT(unit, resolved_port)) { 2098 resolved_index = SOC_INFO(unit).port_cosq_base[resolved_port] + 2099 startq; 2100 resolved_index = soc_td2_l2_hw_index(unit, resolved_index, 0); 2101 } else { 2102 BCM_IF_ERROR_RETURN(soc_td2_sched_hw_index_get(unit, 2103 resolved_port, SOC_TD2_NODE_LVL_L1, 2104 startq, &resolved_index)); 2105 } 2106 } 2107 break; 2108 2109 case _BCM_TD2_COSQ_INDEX_STYLE_QCN: 2110 if (node != NULL) { 2111 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) { 2112 resolved_index = node->hw_index; 2113 } else { 2114 return BCM_E_PARAM; 2115 } 2116 } else { /* node == NULL */ 2117 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_port_has_ets(unit, resolved_port)); 2118 if (IS_CPU_PORT(unit, resolved_port)) { 2119 return BCM_E_PARAM; 2120 } else { 2121 resolved_index = soc_td2_l2_hw_index(unit, 2122 si->port_uc_cosq_base[resolved_port] + startq, 1); 2123 } 2124 } 2125 break; 2126 2127 case _BCM_TD2_COSQ_INDEX_STYLE_WRED: 2128 if (node != NULL) { 2129 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) { 2130 resolved_index = node->hw_index + startq; 2131 } else if (BCM_GPORT_IS_SCHEDULER(port)) { 2132 BCM_IF_ERROR_RETURN( 2133 _bcm_td2_cosq_child_node_at_input(node, startq, &cur_node)); 2134 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(cur_node->gport)) { 2135 resolved_index = cur_node->hw_index; 2136 } else { 2137 return BCM_E_PARAM; 2138 } 2139 } else if (BCM_GPORT_IS_MODPORT(port)) { 2140 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_l2_gport(unit, node->local_port, 2141 startq, _BCM_TD2_NODE_UCAST, NULL, &cur_node)); 2142 resolved_index = cur_node->hw_index; 2143 } else { 2144 return BCM_E_PARAM; 2145 } 2146 } else { /* node == NULL */ 2147 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_port_has_ets(unit, resolved_port)); 2148 resolved_index = soc_td2_l2_hw_index(unit, 2149 si->port_uc_cosq_base[resolved_port] + startq, 1); 2150 numq = 1; 2151 } 2152 break; 2153 2154 case _BCM_TD2_COSQ_INDEX_STYLE_WRED_PORT: 2155 resolved_index = 1616 + (mmu_port_pipe_off*4); 2156 numq = 4; 2157 break; 2158 2159 case _BCM_TD2_COSQ_INDEX_STYLE_WRED_POOL: 2160 if ((node != NULL) && (!BCM_GPORT_IS_MODPORT(port))) { 2161 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) { 2162 /* regular unicast queue */ 2163 resolved_index = soc_td2_l2_hw_index(unit, node->hw_index + startq, 1); 2164 } else { 2165 return BCM_E_PARAM; 2166 } 2167 } else { /* node == NULL */ 2168 numq = si->port_num_uc_cosq[resolved_port]; 2169 if (startq >= numq) { 2170 return BCM_E_PARAM; 2171 } 2172 resolved_index = soc_td2_l2_hw_index(unit, 2173 si->port_uc_cosq_base[resolved_port] + startq, 1); 2174 } 2175 mem = SOC_TD2_PMEM(unit, resolved_port, 2176 MMU_THDU_XPIPE_Q_TO_QGRP_MAPm, MMU_THDU_YPIPE_Q_TO_QGRP_MAPm); 2177 SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, resolved_index, 2178 entry0)); 2179 2180 resolved_index = soc_mem_field32_get(unit, mem, entry0, Q_SPIDf); 2181 2182 break; 2183 2184 case _BCM_TD2_COSQ_INDEX_STYLE_SCHEDULER: 2185 if (node != NULL) { 2186 if (!BCM_GPORT_IS_SCHEDULER(port)) { 2187 return BCM_E_PARAM; 2188 } 2189 BCM_IF_ERROR_RETURN( 2190 _bcm_td2_cosq_child_node_at_input(node, startq, &cur_node)); 2191 resolved_index = cur_node->hw_index; 2192 } else { /* node == NULL */ 2193 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_port_has_ets(unit, resolved_port)); 2194 if (IS_CPU_PORT(unit, resolved_port)) { 2195 resolved_index = soc_td2_l2_hw_index(unit, 2196 si->port_cosq_base[resolved_port] + startq, 0); 2197 } else { 2198 BCM_IF_ERROR_RETURN(soc_td2_sched_hw_index_get(unit, 2199 resolved_port, SOC_TD2_NODE_LVL_L1, startq, 2200 &resolved_index)); 2201 } 2202 } 2203 break; 2204 2205 case _BCM_TD2_COSQ_INDEX_STYLE_COS: 2206 if (node) { 2207 if ((BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) || 2208 (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port))) { 2209 resolved_index = node->hw_cosq; 2210 } else if (BCM_GPORT_IS_SCHEDULER(port)) { 2211 BCM_IF_ERROR_RETURN( 2212 _bcm_td2_cosq_child_node_at_input(node, startq, &cur_node)); 2213 if (BCM_GPORT_IS_SCHEDULER(cur_node->gport)) { 2214 return BCM_E_PARAM; 2215 } 2216 resolved_index = cur_node->hw_cosq; 2217 } 2218 } else { 2219 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_port_has_ets(unit, resolved_port)); 2220 resolved_index = startq; 2221 } 2222 break; 2223 2224 case _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE: 2225 case _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE_GROUP: 2226 if (IS_CPU_PORT(unit, resolved_port) || 2227 IS_LB_PORT(unit, resolved_port)) { 2228 return BCM_E_PARAM; 2229 } 2230 if (node) { 2231 resolved_index = node->hw_index + startq; 2232 numq = 1; 2233 } else { 2234 /* Not support -1 for queue group index resolving, as group may not consecutive */ 2235 if ((cosq == -1) && 2236 (style == _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE_GROUP)) { 2237 return BCM_E_PARAM; 2238 } 2239 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_port_has_ets(unit, resolved_port)); 2240 numq = 1; 2241 resolved_index = soc_td2_l2_hw_index(unit, 2242 si->port_uc_cosq_base[resolved_port] + startq, 1); 2243 } 2244 if (style == _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE_GROUP) { 2245 mem = SOC_TD2_PMEM(unit, resolved_port, MMU_THDU_XPIPE_Q_TO_QGRP_MAPm, 2246 MMU_THDU_YPIPE_Q_TO_QGRP_MAPm); 2247 SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, 2248 resolved_index, entry0)); 2249 if (soc_mem_field32_get(unit, mem, entry0, QGROUP_VALIDf)) { 2250 resolved_index = soc_mem_field32_get(unit, mem, entry0, QGROUPf); 2251 } else { 2252 return BCM_E_NOT_FOUND; 2253 } 2254 } 2255 break; 2256 2257 case _BCM_TD2_COSQ_INDEX_STYLE_MCAST_QUEUE: 2258 if (node) { 2259 resolved_index = node->hw_index + startq; 2260 numq = 1; 2261 } else { 2262 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_port_has_ets(unit, resolved_port)); 2263 numq = 1; 2264 resolved_index = soc_td2_l2_hw_index(unit, 2265 si->port_cosq_base[resolved_port] + startq, 0); 2266 } 2267 break; 2268 2269 case _BCM_TD2_COSQ_INDEX_STYLE_EGR_POOL: 2270 if ((node != NULL) && (!BCM_GPORT_IS_MODPORT(port))) { 2271 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) { 2272 /* regular unicast queue */ 2273 resolved_index = soc_td2_l2_hw_index(unit, node->hw_index + startq, 1); 2274 mem = SOC_TD2_PMEM(unit, resolved_port, 2275 MMU_THDU_XPIPE_Q_TO_QGRP_MAPm, MMU_THDU_YPIPE_Q_TO_QGRP_MAPm); 2276 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 2277 resolved_index = soc_td2_l2_hw_index(unit, 2278 si->port_cosq_base[resolved_port] + startq, 0) - 1480; 2279 mem = SOC_TD2_PMEM(unit, resolved_port, 2280 MMU_THDM_MCQE_QUEUE_CONFIG_0m, MMU_THDM_MCQE_QUEUE_CONFIG_1m); 2281 } else { /* scheduler */ 2282 return BCM_E_PARAM; 2283 } 2284 } else { /* node == NULL */ 2285 numq = si->port_num_cosq[resolved_port]; 2286 if (startq >= numq) { 2287 return BCM_E_PARAM; 2288 } 2289 resolved_index = soc_td2_l2_hw_index(unit, 2290 si->port_cosq_base[resolved_port] + startq, 0) - 1480; 2291 mem = SOC_TD2_PMEM(unit, resolved_port, 2292 MMU_THDM_MCQE_QUEUE_CONFIG_0m, MMU_THDM_MCQE_QUEUE_CONFIG_1m); 2293 } 2294 2295 SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, resolved_index, 2296 entry0)); 2297 2298 resolved_index = soc_mem_field32_get(unit, mem, entry0, Q_SPIDf); 2299 2300 break; 2301 2302 case _BCM_TD2_COSQ_INDEX_STYLE_UC_EGR_POOL: 2303 if (IS_CPU_PORT(unit, resolved_port) || 2304 IS_LB_PORT(unit, resolved_port)) { 2305 return BCM_E_PARAM; 2306 } 2307 2308 numq = si->port_num_uc_cosq[resolved_port]; 2309 if (startq >= numq) { 2310 return BCM_E_PARAM; 2311 } 2312 2313 resolved_index = soc_td2_l2_hw_index(unit, 2314 si->port_uc_cosq_base[resolved_port] + startq, 1); 2315 mem = SOC_TD2_PMEM(unit, resolved_port, 2316 MMU_THDU_XPIPE_Q_TO_QGRP_MAPm, MMU_THDU_YPIPE_Q_TO_QGRP_MAPm); 2317 2318 SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, resolved_index, 2319 entry0)); 2320 2321 resolved_index = soc_mem_field32_get(unit, mem, entry0, Q_SPIDf); 2322 break; 2323 2324 case _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_UCAST: 2325 if (node) { 2326 resolved_index = node->hw_index + startq; 2327 resolved_index -= soc_td2_l2_hw_index(unit, 2328 si->port_uc_cosq_base[resolved_port], 1); 2329 numq = 1; 2330 } else { 2331 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_port_has_ets(unit, resolved_port)); 2332 numq = 1; 2333 resolved_index = startq; 2334 } 2335 break; 2336 2337 case _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_MCAST: 2338 if (node) { 2339 resolved_index = node->hw_index + startq; 2340 resolved_index -= soc_td2_l2_hw_index(unit, 2341 si->port_cosq_base[resolved_port], 0); 2342 numq = 1; 2343 } else { 2344 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_port_has_ets(unit, resolved_port)); 2345 numq = 1; 2346 resolved_index = startq; 2347 } 2348 break; 2349 2350 default: 2351 return BCM_E_INTERNAL; 2352 } 2353 2354 if (local_port != NULL) { 2355 *local_port = resolved_port; 2356 } 2357 if (index != NULL) { 2358 *index = resolved_index; 2359 } 2360 if (count != NULL) { 2361 *count = (cosq == -1) ? numq : 1; 2362 } 2363 2364 return BCM_E_NONE; 2365 } 2366 2367 STATIC int _bcm_td2_cosq_min_child_index(_bcm_td2_cosq_node_t *child, int lvl, int uc) 2368 { 2369 int min_index = -1; 2370 2371 if ((lvl == SOC_TD2_NODE_LVL_L2) && (uc)) { 2372 while (child) { 2373 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(child->gport)) { 2374 if (min_index == -1) { 2375 min_index = child->hw_index; 2376 } 2377 2378 if (child->hw_index < min_index) { 2379 min_index = child->hw_index; 2380 } 2381 } 2382 child = child->sibling; 2383 } 2384 } else if ((lvl == SOC_TD2_NODE_LVL_L2) && (!uc)) { 2385 while (child) { 2386 if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(child->gport)) { 2387 if (min_index == -1) { 2388 min_index = child->hw_index; 2389 } 2390 2391 if (child->hw_index < min_index) { 2392 min_index = child->hw_index; 2393 } 2394 } 2395 child = child->sibling; 2396 } 2397 } else { 2398 while (child) { 2399 if (min_index == -1) { 2400 min_index = child->hw_index; 2401 } 2402 2403 if (child->hw_index < min_index) { 2404 min_index = child->hw_index; 2405 } 2406 child = child->sibling; 2407 } 2408 } 2409 2410 return min_index; 2411 } 2412 2413 STATIC int 2414 _bcm_td2_child_state_check(int unit, bcm_port_t gport, 2415 bcm_cos_queue_t cosq, int ets_mode) 2416 { 2417 _bcm_td2_cosq_node_t *node, *child_node = NULL; 2418 bcm_port_t local_port; 2419 int level, sch_index, empty = 0; 2420 int rv = BCM_E_NONE; 2421 soc_timeout_t timeout; 2422 uint32 timeout_val; 2423 uint32 entry[SOC_MAX_MEM_WORDS]; 2424 soc_mem_t mem = INVALIDm; 2425 static const soc_mem_t memx[] = { 2426 INVALIDm, 2427 ES_PIPE0_LLS_L0_CHILD_STATE1m, 2428 ES_PIPE0_LLS_L1_CHILD_STATE1m, 2429 ES_PIPE0_LLS_L2_CHILD_STATE1m 2430 }; 2431 static const soc_mem_t memy[] = { 2432 INVALIDm, 2433 ES_PIPE1_LLS_L0_CHILD_STATE1m, 2434 ES_PIPE1_LLS_L1_CHILD_STATE1m, 2435 ES_PIPE1_LLS_L2_CHILD_STATE1m 2436 }; 2437 2438 /* Timeout val = Static for now. Need to quantify the max wait time */ 2439 timeout_val = 2000000; 2440 2441 BCM_IF_ERROR_RETURN 2442 (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port)); 2443 2444 if (ets_mode & (!IS_TD2_HSP_PORT(unit, local_port))) { 2445 BCM_IF_ERROR_RETURN 2446 (_bcm_td2_cosq_node_get(unit, gport, 0, NULL, 2447 &local_port, NULL, &node)); 2448 2449 /* Get the Child node for the Given Gport */ 2450 rv = _bcm_td2_cosq_child_node_at_input(node, cosq, &child_node); 2451 2452 if ((!child_node) || (rv == BCM_E_NOT_FOUND)) { 2453 /* No Child present */ 2454 return BCM_E_NONE; 2455 } 2456 2457 BCM_IF_ERROR_RETURN 2458 (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port)); 2459 2460 level = child_node->level; 2461 sch_index = child_node->hw_index; 2462 2463 /* Child State Check is NOT necessary for Non-L0/L1/L2 levels */ 2464 if ((level < SOC_TD2_NODE_LVL_L0) || (level > SOC_TD2_NODE_LVL_L2)) { 2465 /* Sanity for Node's level should be done in the caller */ 2466 return BCM_E_NONE; 2467 } 2468 2469 mem = SOC_TD2_PMEM(unit, local_port, memx[level], memy[level]); 2470 2471 if (mem == INVALIDm) { 2472 return BCM_E_INTERNAL; 2473 } 2474 2475 soc_timeout_init(&timeout, timeout_val, 0); 2476 2477 for(;;) { 2478 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, 2479 sch_index, entry)); 2480 empty = 0; 2481 if (soc_timeout_check(&timeout)) { 2482 LOG_ERROR(BSL_LS_BCM_COMMON, 2483 (BSL_META_U(unit, 2484 "ERROR: Timeout during Child lists Not zero\n"))); 2485 return BCM_E_BUSY; 2486 } 2487 empty += soc_mem_field32_get(unit, mem, &entry, C_ON_ACTIVE_LISTf); 2488 empty += soc_mem_field32_get(unit, mem, &entry, C_ON_MIN_LISTf); 2489 empty += soc_mem_field32_get(unit, mem, &entry, C_NOT_EMPTYf); 2490 2491 if (!empty) { 2492 break; 2493 } 2494 } 2495 } else { 2496 /* TBD: Need to implement for Non-ETS mode */ 2497 return BCM_E_NONE; 2498 } 2499 2500 return BCM_E_NONE; 2501 } 2502 2503 2504 STATIC int 2505 _bcm_td2_cosq_node_queue_state_check(int unit, 2506 _bcm_td2_cosq_node_t *node, int ets_mode) 2507 { 2508 int cosq = 0; 2509 2510 if (node == NULL) { 2511 return BCM_E_PARAM; 2512 } 2513 2514 for (cosq = 0; cosq < node->numq; cosq++) { 2515 BCM_IF_ERROR_RETURN 2516 (_bcm_td2_child_state_check(unit, node->gport, 2517 cosq, ets_mode)); 2518 } 2519 2520 if ((node->level <= SOC_TD2_NODE_LVL_L1) && 2521 (node->child != NULL)) { 2522 BCM_IF_ERROR_RETURN 2523 (_bcm_td2_cosq_node_queue_state_check(unit, 2524 node->child,ets_mode)); 2525 } 2526 2527 if (node->sibling != NULL) { 2528 2529 BCM_IF_ERROR_RETURN 2530 (_bcm_td2_cosq_node_queue_state_check(unit, 2531 node->sibling,ets_mode)); 2532 } 2533 2534 return BCM_E_NONE; 2535 } 2536 2537 int 2538 _bcm_td2_cosq_port_queue_state_check(int unit, bcm_port_t gport) 2539 { 2540 bcm_port_t local_port; 2541 int ets_mode; 2542 _bcm_td2_cosq_node_t *node; 2543 2544 BCM_IF_ERROR_RETURN 2545 (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port)); 2546 ets_mode = _bcm_td2_cosq_port_has_ets(unit, local_port); 2547 if (!ets_mode) { 2548 return BCM_E_NONE; 2549 } 2550 2551 BCM_IF_ERROR_RETURN 2552 (bcm_esw_port_gport_get(unit, local_port, 2553 &gport)); 2554 2555 BCM_IF_ERROR_RETURN 2556 (_bcm_td2_cosq_node_get(unit, gport, 0, NULL, 2557 NULL, NULL, &node)); 2558 2559 BCM_IF_ERROR_RETURN 2560 (_bcm_td2_cosq_node_queue_state_check(unit, 2561 node,ets_mode)); 2562 return BCM_E_NONE; 2563 } 2564 2565 /* 2566 * Function: 2567 * _bcm_td2_dynamic_sched_update_begin 2568 * Purpose: 2569 * Set settings to enable Dynamic Sched update. 2570 * Parameters: 2571 * unit - (IN) unit number 2572 * port - (IN) Port 2573 * Returns: 2574 * BCM_E_XXX 2575 */ 2576 STATIC int 2577 _bcm_td2_dynamic_sched_update_begin(int unit, bcm_port_t gport, 2578 bcm_cos_queue_t cosq) 2579 { 2580 int ets_mode = 0; 2581 int rv = BCM_E_NONE; 2582 bcm_port_t local_port; 2583 2584 if (SAL_BOOT_SIMULATION) { 2585 return BCM_E_NONE; 2586 } 2587 2588 BCM_IF_ERROR_RETURN 2589 (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port)); 2590 2591 SOC_IF_ERROR_RETURN( 2592 soc_td2_port_traffic_egr_enable_set(unit, local_port, 0)); 2593 2594 /* CPU port and loopback port need no cell drain to happen */ 2595 if (!IS_CPU_PORT(unit, local_port) && !IS_LB_PORT(unit, local_port)) { 2596 /* Drain the cells assoiciated to the port */ 2597 _bcm_td2_port_drain_cells(unit, local_port); 2598 } 2599 2600 ets_mode = _bcm_td2_cosq_port_has_ets(unit, local_port); 2601 /* Poll Child state to verify if Child is still in Parent list */ 2602 rv = _bcm_td2_child_state_check(unit, gport, cosq, ets_mode); 2603 if (rv != BCM_E_NONE) { 2604 /* Logging the Error. Not stopping the flow for now. */ 2605 LOG_ERROR(BSL_LS_BCM_COMMON, 2606 (BSL_META_U(unit, 2607 "ERROR: During Child State Check(rv %d)\n"), 2608 rv)); 2609 } 2610 return BCM_E_NONE; 2611 } 2612 2613 STATIC int 2614 _bcm_td2_dynamic_sched_reset_thd(int unit, bcm_port_t gport, 2615 bcm_cos_queue_t cosq, int ets_mode) 2616 { 2617 _bcm_td2_cosq_node_t *node, *child_node = NULL; 2618 bcm_port_t local_port; 2619 int level, sch_index; 2620 int rv = BCM_E_NONE; 2621 uint32 entry[SOC_MAX_MEM_WORDS]; 2622 soc_mem_t mem = INVALIDm; 2623 static const soc_mem_t memx[] = { 2624 INVALIDm, 2625 MMU_MTRO_L0_MEM_0m, 2626 MMU_MTRO_L1_MEM_0m, 2627 MMU_MTRO_L2_MEM_0m 2628 }; 2629 static const soc_mem_t memy[] = { 2630 INVALIDm, 2631 MMU_MTRO_L0_MEM_1m, 2632 MMU_MTRO_L1_MEM_1m, 2633 MMU_MTRO_L2_MEM_1m 2634 }; 2635 2636 BCM_IF_ERROR_RETURN 2637 (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port)); 2638 2639 if (ets_mode & (!IS_TD2_HSP_PORT(unit, local_port))) { 2640 uint32 min_thd = 0; 2641 uint32 max_thd = 0; 2642 2643 BCM_IF_ERROR_RETURN 2644 (_bcm_td2_cosq_node_get(unit, gport, 0, NULL, 2645 &local_port, NULL, &node)); 2646 2647 /* Get the Child node for the Given Gport */ 2648 rv = _bcm_td2_cosq_child_node_at_input(node, cosq, &child_node); 2649 2650 if ((!child_node) || (rv == BCM_E_NOT_FOUND)) { 2651 /* No Child present */ 2652 return BCM_E_INTERNAL; 2653 } 2654 2655 BCM_IF_ERROR_RETURN 2656 (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port)); 2657 2658 level = child_node->level; 2659 sch_index = child_node->hw_index; 2660 2661 /* Child State Check is NOT necessary for Non-L0/L1/L2 levels */ 2662 if ((level < SOC_TD2_NODE_LVL_L0) || (level > SOC_TD2_NODE_LVL_L2)) { 2663 /* Sanity for Node's level should be done in the caller */ 2664 return BCM_E_NONE; 2665 } 2666 2667 mem = SOC_TD2_PMEM(unit, local_port, memx[level], memy[level]); 2668 2669 if (mem == INVALIDm) { 2670 return BCM_E_INTERNAL; 2671 } 2672 2673 SOC_EGRESS_METERING_LOCK(unit); 2674 rv = soc_mem_read(unit, mem, MEM_BLOCK_ALL, 2675 sch_index, entry); 2676 if (rv != BCM_E_NONE) { 2677 SOC_EGRESS_METERING_UNLOCK(unit); 2678 return rv; 2679 } 2680 min_thd = soc_mem_field32_get(unit, mem, &entry, MIN_THD_SELf); 2681 max_thd = soc_mem_field32_get(unit, mem, &entry, MAX_THD_SELf); 2682 2683 if (min_thd || max_thd) { 2684 /* Set Min_Thd of the node to 0 in MTRO_CONFIG_xxx_MEM */ 2685 soc_mem_field32_set(unit, mem, entry, MIN_THD_SELf, 0); 2686 soc_mem_field32_set(unit, mem, entry, MAX_THD_SELf, 0); 2687 rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, 2688 sch_index, entry); 2689 if (rv != BCM_E_NONE) { 2690 SOC_EGRESS_METERING_UNLOCK(unit); 2691 return rv; 2692 } 2693 2694 /* A uSec delay */ 2695 sal_usleep(1); 2696 /* Reset MIN_THD value back to original one. 2697 * This step is to activate the MIN_THD to LLS. 2698 */ 2699 soc_mem_field32_set(unit, mem, entry, MIN_THD_SELf, min_thd); 2700 soc_mem_field32_set(unit, mem, entry, MAX_THD_SELf, max_thd); 2701 rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, 2702 sch_index, entry); 2703 if (rv != BCM_E_NONE) { 2704 SOC_EGRESS_METERING_UNLOCK(unit); 2705 return rv; 2706 } 2707 } 2708 SOC_EGRESS_METERING_UNLOCK(unit); 2709 } else { 2710 /* TBD: Need to implement for Non-ETS mode */ 2711 return BCM_E_NONE; 2712 } 2713 2714 return BCM_E_NONE; 2715 } 2716 2717 /* 2718 * Function: 2719 * _bcm_td2_dynamic_sched_update_end 2720 * Purpose: 2721 * Reset settings back to original state after Dynamic Sched update is complete. 2722 * Parameters: 2723 * unit - (IN) unit number 2724 * port - (IN) Port 2725 * Returns: 2726 * BCM_E_XXX 2727 */ 2728 STATIC int 2729 _bcm_td2_dynamic_sched_update_end(int unit, bcm_port_t gport, 2730 bcm_cos_queue_t cosq) 2731 { 2732 int ets_mode = 0; 2733 bcm_port_t local_port; 2734 int rv = BCM_E_NONE; 2735 2736 if (SAL_BOOT_SIMULATION) { 2737 return BCM_E_NONE; 2738 } 2739 2740 BCM_IF_ERROR_RETURN 2741 (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port)); 2742 2743 ets_mode = _bcm_td2_cosq_port_has_ets(unit, local_port); 2744 /* Reset MIN_THD for the respective Node/Queue */ 2745 rv = _bcm_td2_dynamic_sched_reset_thd(unit, gport, cosq, ets_mode); 2746 if (rv != BCM_E_NONE) { 2747 /* Logging the Error. Not stopping the flow for now. */ 2748 LOG_ERROR(BSL_LS_BCM_COMMON, 2749 (BSL_META_U(unit, 2750 "ERROR: During Reset MIN_THD process(rv %d)\n"), 2751 rv)); 2752 } 2753 2754 SOC_IF_ERROR_RETURN( 2755 soc_td2_port_traffic_egr_enable_set(unit, local_port, 1)); 2756 2757 return BCM_E_NONE; 2758 2759 } 2760 2761 STATIC int 2762 _bcm_td2_attach_node_in_hw(int unit, _bcm_td2_cosq_node_t *node) 2763 { 2764 int local_port, fc = 0, fmc = 0; 2765 _bcm_td2_cosq_node_t *child_node; 2766 int num_spri = 0, first_sp_child = 0, first_sp_mc_child = 0; 2767 uint32 ucmap = 0, spmap = 0; 2768 soc_trident2_sched_type_t sched_type; 2769 2770 local_port = node->local_port; 2771 2772 if (node->level == SOC_TD2_NODE_LVL_ROOT) { 2773 return 0; 2774 } else if (node->level == SOC_TD2_NODE_LVL_L2) { 2775 fc = _bcm_td2_cosq_min_child_index(node->parent->child, SOC_TD2_NODE_LVL_L2, 1); 2776 if (fc < 0) { 2777 fc = 0; 2778 } 2779 fmc = _bcm_td2_cosq_min_child_index(node->parent->child, SOC_TD2_NODE_LVL_L2, 0); 2780 if (fmc < 0) { 2781 fmc = 1480; 2782 } 2783 } else { 2784 fc = _bcm_td2_cosq_min_child_index(node->parent->child, node->level, 0); 2785 fmc = 0; 2786 } 2787 2788 /* If node is scheduler, reset the scheduler and attach it to the parent.*/ 2789 BCM_IF_ERROR_RETURN( 2790 soc_td2_cosq_set_sched_parent(unit, local_port, node->level, 2791 node->hw_index, node->parent->hw_index)); 2792 2793 sched_type = _soc_trident2_port_sched_type_get(unit, local_port); 2794 2795 if (sched_type == SOC_TD2_SCHED_LLS) { 2796 /* Get num_spri and ucmap config from parent node. */ 2797 BCM_IF_ERROR_RETURN( 2798 soc_td2_cosq_get_sched_child_config(unit, local_port, 2799 node->parent->level, 2800 node->parent->hw_index, 2801 &num_spri, &first_sp_child, 2802 &first_sp_mc_child, &ucmap, 2803 &spmap)); 2804 2805 /* 2806 * If there is no SP child under a schedule node, fc of this node will 2807 * be set to the index of min child. 2808 * Else, fc of this node will be set to the index of first SP child. 2809 */ 2810 if (num_spri == 0) { 2811 if (fc != first_sp_child && fc == node->hw_index) { 2812 first_sp_child = fc; 2813 } 2814 2815 if (node->level == SOC_TD2_NODE_LVL_L2 && fmc != first_sp_mc_child 2816 && fmc == node->hw_index) { 2817 first_sp_mc_child = fmc; 2818 } 2819 } 2820 2821 /* Retain the num_spri only if the current node is NOT the first_sp_child */ 2822 if (first_sp_child == node->hw_index || 2823 first_sp_mc_child == node->hw_index) { 2824 num_spri = 0; 2825 ucmap = 0; 2826 } 2827 2828 /* set the node by default in WRR mode with wt=1 */ 2829 BCM_IF_ERROR_RETURN(soc_td2_cosq_set_sched_config(unit, 2830 local_port, node->parent->level, 2831 node->parent->hw_index, node->hw_index, 2832 num_spri, first_sp_child, first_sp_mc_child, ucmap, 2833 0, SOC_TD2_SCHED_MODE_WRR, 1)); 2834 } 2835 2836 2837 if (node->child) { 2838 child_node = node->child; 2839 while (child_node) { 2840 BCM_IF_ERROR_RETURN(_bcm_td2_attach_node_in_hw(unit, child_node)); 2841 child_node = child_node->sibling; 2842 } 2843 } 2844 2845 return BCM_E_NONE; 2846 } 2847 2848 STATIC int 2849 _bcm_td2_cosq_hsp_port_count_per_pipe_get(int unit, int pipe) 2850 { 2851 bcm_port_t port; 2852 int count = 0; 2853 #ifdef BCM_TRIDENT2PLUS_SUPPORT 2854 if(SOC_IS_TD2P_TT2P(unit)) { 2855 BCM_IF_ERROR_RETURN( 2856 soc_td2p_num_hsp_reserved_per_pipe(unit, pipe, &count)); 2857 } else 2858 #endif 2859 { 2860 PBMP_ALL_ITER(unit, port) { 2861 if (IS_TD2_HSP_PORT(unit, port) && 2862 pipe == _BCM_TD2_PORT_TO_PIPE(unit, port)) { 2863 count++; 2864 } 2865 } 2866 } 2867 return count; 2868 } 2869 2870 /* 2871 * Function: 2872 * _bcm_td2_cosq_node_resolve 2873 * Purpose: 2874 * Resolve queue number in the specified scheduler tree and its subtree 2875 * Parameters: 2876 * unit - (IN) unit number 2877 * node - (IN) node structure for the specified scheduler node 2878 * cosq - (IN) COS queue to attach to 2879 * Returns: 2880 * BCM_E_XXX 2881 */ 2882 STATIC int 2883 _bcm_td2_cosq_node_resolve(int unit, _bcm_td2_cosq_node_t *node, 2884 bcm_cos_queue_t cosq) 2885 { 2886 _bcm_td2_cosq_node_t *cur_node, *parent; 2887 _bcm_td2_cosq_port_info_t *port_info; 2888 _bcm_td2_pipe_resources_t * res; 2889 _bcm_td2_mmu_info_t *mmu_info; 2890 _bcm_td2_cosq_list_t *list; 2891 int numq, id, ii, rv, max_cosq = -1; 2892 int valid_index_lo, valid_index_hi; 2893 bcm_port_t port; 2894 int phy_port, mmu_port; 2895 int pipe; 2896 int old_base_index = -1; 2897 int old_base_size = -1; 2898 /* An array was used to find first free slot in L0/L1/L2 table 2899 So choose the one of the longest length of the three table */ 2900 SHR_BIT_DCL_CLR_NAME(map, 1480); 2901 2902 if ((parent = node->parent) == NULL) { 2903 /* Not attached, should never happen */ 2904 return BCM_E_NOT_FOUND; 2905 } 2906 2907 if (parent->numq == 0 || parent->numq < -1) { 2908 return BCM_E_PARAM; 2909 } 2910 2911 port = node->local_port; 2912 2913 if (parent->numq != -1) { 2914 /* find the current attached_to_input usage */ 2915 for (cur_node = parent->child; cur_node != NULL; 2916 cur_node = cur_node->sibling) { 2917 if (cur_node->attached_to_input >= 0) { 2918 SHR_BITSET(map, cur_node->attached_to_input); 2919 } 2920 } 2921 2922 if (cosq < 0) { 2923 for (ii = 0; ii < parent->numq; ii++) { 2924 if (!SHR_BITGET(map, ii)) { 2925 node->attached_to_input = ii; 2926 cosq = ii; 2927 break; 2928 } 2929 } 2930 if (ii == parent->numq) { 2931 return BCM_E_PARAM; 2932 } 2933 } else { 2934 if (SHR_BITGET(map, cosq)) { 2935 return BCM_E_EXISTS; 2936 } 2937 node->attached_to_input = cosq; 2938 } 2939 } else if (parent->numq == -1) { 2940 for (cur_node = parent->child; cur_node != NULL; 2941 cur_node = cur_node->sibling) { 2942 if (cur_node->attached_to_input >= 0) { 2943 SHR_BITSET(map, cur_node->attached_to_input); 2944 max_cosq = (cur_node->attached_to_input > max_cosq)? \ 2945 cur_node->attached_to_input : max_cosq; 2946 } 2947 } 2948 if (cosq >= 0) { 2949 if (SHR_BITGET(map, cosq)) { 2950 return BCM_E_EXISTS; 2951 } 2952 } else { 2953 /* Attach anywhere. find first free slot */ 2954 for (ii = 0; ii < 1480; ii++) { 2955 if (!SHR_BITGET(map, ii)) { 2956 cosq = ii; 2957 break; 2958 } 2959 } 2960 if (cosq < 0) { /* No available slot. */ 2961 return BCM_E_FULL; 2962 } 2963 } 2964 node->attached_to_input = cosq; 2965 max_cosq = (node->attached_to_input > max_cosq)? \ 2966 node->attached_to_input : max_cosq; 2967 } 2968 2969 mmu_info = _bcm_td2_mmu_info[unit]; 2970 port_info = &mmu_info->port_info[port]; 2971 res = port_info->resources; 2972 numq = (parent->numq == -1) ? (max_cosq + 1) : parent->numq; 2973 phy_port = SOC_INFO(unit).port_l2p_mapping[port]; 2974 mmu_port = SOC_INFO(unit).port_p2m_mapping[phy_port]; 2975 pipe = _BCM_TD2_PORT_TO_PIPE(unit, port); 2976 2977 switch (parent->level) { 2978 case SOC_TD2_NODE_LVL_ROOT: 2979 list = &res->l0_sched_list; 2980 if ((parent->numq == -1) && parent->base_index >= 0 && 2981 parent->base_size != numq) { 2982 old_base_index = parent->base_index; 2983 old_base_size = parent->base_size; 2984 _bcm_td2_node_index_clear(list, parent->base_index, 2985 parent->base_size); 2986 parent->base_index = -1; 2987 } 2988 2989 if (parent->base_index < 0) { 2990 if (IS_CPU_PORT(unit, port)) { 2991 valid_index_lo = (SOC_IS_TD2P_TT2P(unit)?259:261); 2992 valid_index_hi = _BCM_TD2_NUM_L0_SCHEDULER_PER_PIPE; 2993 } else if (IS_TD2_HSP_PORT(unit, port)) { 2994 valid_index_lo = _BCM_TD2_HSP_L0_INDEX(unit, mmu_port, 0); 2995 valid_index_hi = _BCM_TD2_HSP_L0_INDEX(unit, (mmu_port + 1), 2996 0); 2997 } else { 2998 valid_index_lo = _bcm_td2_cosq_hsp_port_count_per_pipe_get(unit, pipe) * 2999 _BCM_TD2_HSP_PORT_MAX_L0; 3000 /* upper 4 L0 nodes reserverd for cpu */ 3001 valid_index_hi = (SOC_IS_TD2P_TT2P(unit)?259:261); 3002 } 3003 3004 if (IS_CPU_PORT(unit, port) || 3005 IS_TD2_HSP_PORT(unit, port)) { 3006 rv = _bcm_td2_node_index_get(list->bits, valid_index_lo, 3007 valid_index_hi, numq, 1, &id); 3008 } else { 3009 rv = _bcm_td2_node_index_get(list->bits, valid_index_lo, 3010 valid_index_hi, numq, 3011 node->node_align_value, &id); 3012 } 3013 if (rv) { 3014 parent->base_index = old_base_index; 3015 _bcm_td2_node_index_set(list, old_base_index, 3016 old_base_size); 3017 return rv; 3018 } 3019 3020 _bcm_td2_node_index_set(list, id, numq); 3021 parent->base_index = id; 3022 node->hw_index = parent->base_index + node->attached_to_input; 3023 parent->base_size = numq; 3024 if (parent->base_index != old_base_index){ 3025 for (id = old_base_index; 3026 id < old_base_index + old_base_size; 3027 id++) { 3028 BCM_IF_ERROR_RETURN(soc_td2_cosq_set_sched_parent(unit, 3029 port, node->level, id, 3030 _soc_td2_invalid_parent_index(unit, node->level))); 3031 } 3032 } 3033 for (cur_node = parent->child; cur_node; 3034 cur_node = cur_node->sibling) { 3035 if (cur_node->attached_to_input >= 0) { 3036 cur_node->hw_index = parent->base_index + 3037 cur_node->attached_to_input; 3038 BCM_IF_ERROR_RETURN( 3039 _bcm_td2_attach_node_in_hw(unit, cur_node)); 3040 } 3041 } 3042 } else { 3043 node->hw_index = parent->base_index + node->attached_to_input; 3044 } 3045 node->hw_cosq = node->attached_to_input; 3046 3047 break; 3048 3049 case SOC_TD2_NODE_LVL_L0: 3050 list = &res->l1_sched_list; 3051 if (IS_TD2_HSP_PORT(unit, port)) { 3052 if (node->attached_to_input >= _BCM_TD2_HSP_PORT_MAX_L1) { 3053 return BCM_E_PARAM; 3054 } 3055 3056 if ((parent->hw_index % _BCM_TD2_HSP_PORT_MAX_L0) == 0) { 3057 /* L0.0 could only be attached by MC nodes */ 3058 if (node->type == _BCM_TD2_NODE_MCAST) { 3059 uint32 rval = 0; 3060 uint32 mc_group_mode = 0; 3061 SOC_IF_ERROR_RETURN( 3062 READ_HSP_SCHED_PORT_CONFIGr(unit, port, &rval)); 3063 mc_group_mode = soc_reg_field_get( 3064 unit, HSP_SCHED_PORT_CONFIGr, 3065 rval, MC_GROUP_MODEf); 3066 /* check mc group mode and the node offset */ 3067 if ((!mc_group_mode) || 3068 ((node->hw_index % _BCM_TD2_HSP_PORT_MAX_L1) >= 3069 _BCM_TD2_HSP_PORT_MAX_COS)) { 3070 return BCM_E_PARAM; 3071 } 3072 break; 3073 } else { 3074 return BCM_E_PARAM; 3075 } 3076 } 3077 3078 BCM_IF_ERROR_RETURN(_bcm_td2_node_index_get(list->bits, 3079 _BCM_TD2_HSP_PORT_MAX_L1 * (mmu_port & 0x3f), 3080 (_BCM_TD2_HSP_PORT_MAX_L1) * ((mmu_port & 0x3f) + 1), 3081 1, 1, &id)); 3082 if (parent->base_index == -1) { 3083 parent->base_index = id; 3084 } 3085 node->hw_index = id; 3086 3087 if ((node->hw_index % _BCM_TD2_HSP_PORT_MAX_L1) >= 8) { 3088 if ((parent->hw_index % _BCM_TD2_HSP_PORT_MAX_L0) != 4) { 3089 return BCM_E_PARAM; 3090 } 3091 } else { 3092 if ((parent->hw_index % _BCM_TD2_HSP_PORT_MAX_L0) == 4) { 3093 return BCM_E_PARAM; 3094 } 3095 } 3096 _bcm_td2_node_index_set(list, id, 1); 3097 } else { 3098 /* Delete current COSQs if numq needs to be expanded. */ 3099 if ((parent->base_index >= 0) && 3100 (parent->numq == -1) && (cosq == max_cosq)) { 3101 old_base_index = parent->base_index; 3102 old_base_size = parent->base_size; 3103 _bcm_td2_node_index_clear(list, parent->base_index, 3104 parent->base_size); 3105 parent->base_index = -1; 3106 } 3107 if (parent->base_index < 0) { 3108 rv = _bcm_td2_node_index_get(list->bits, 3109 _BCM_TD2_HSP_PORT_MAX_L1 * _bcm_td2_cosq_hsp_port_count_per_pipe_get(unit, pipe), 3110 _BCM_TD2_NUM_L1_SCHEDULER_PER_PIPE, 3111 numq, node->node_align_value, &id); 3112 if (rv) { 3113 _bcm_td2_node_index_set(list, old_base_index, 3114 old_base_size); 3115 return rv; 3116 } 3117 _bcm_td2_node_index_set(list, id, numq); 3118 parent->base_size = numq; 3119 parent->base_index = id; 3120 node->hw_index = parent->base_index + node->attached_to_input; 3121 if (parent->base_index != old_base_index){ 3122 for (id = old_base_index; 3123 id < old_base_index + old_base_size; 3124 id++) { 3125 BCM_IF_ERROR_RETURN(soc_td2_cosq_set_sched_parent(unit, 3126 port, node->level, id, 3127 _soc_td2_invalid_parent_index(unit, node->level))); 3128 } 3129 } 3130 for (cur_node = parent->child; cur_node; 3131 cur_node = cur_node->sibling) { 3132 if (cur_node->attached_to_input >= 0) { 3133 cur_node->hw_index = parent->base_index + 3134 cur_node->attached_to_input; 3135 BCM_IF_ERROR_RETURN( 3136 _bcm_td2_attach_node_in_hw(unit, cur_node)); 3137 } 3138 } 3139 } else { 3140 node->hw_index = parent->base_index + node->attached_to_input; 3141 } 3142 } 3143 node->hw_cosq = node->attached_to_input; 3144 3145 break; 3146 3147 case SOC_TD2_NODE_LVL_L1: 3148 if (IS_TD2_HSP_PORT(unit, port)) { 3149 uint32 rval = 0; 3150 uint32 mc_group_mode = 0; 3151 SOC_IF_ERROR_RETURN( 3152 READ_HSP_SCHED_PORT_CONFIGr(unit, port, &rval)); 3153 mc_group_mode = soc_reg_field_get(unit, HSP_SCHED_PORT_CONFIGr, 3154 rval, MC_GROUP_MODEf); 3155 if (mc_group_mode && 3156 ((node->hw_index % _BCM_TD2_HSP_PORT_MAX_L1) < 3157 _BCM_TD2_HSP_PORT_MAX_COS)) { 3158 if (node->attached_to_input >= 1) { 3159 return BCM_E_PARAM; 3160 } 3161 if (node->type == _BCM_TD2_NODE_MCAST) { 3162 return BCM_E_PARAM; 3163 } 3164 } else { 3165 if (node->attached_to_input >= _BCM_TD2_HSP_PORT_MAX_L2) { 3166 return BCM_E_PARAM; 3167 } 3168 if ((node->sibling) && 3169 (node->type == node->sibling->type)) { 3170 return BCM_E_PARAM; 3171 } 3172 } 3173 } 3174 if ((node->hw_index == -1) && 3175 (node->type != _BCM_TD2_NODE_VOQ)) { 3176 return BCM_E_PARAM; 3177 } else if (node->type == _BCM_TD2_NODE_VOQ) { 3178 if (parent->base_index < 0) { 3179 BCM_IF_ERROR_RETURN( 3180 _bcm_td2_node_index_get(res->ext_qlist.bits, 3181 res->num_base_queues, 3182 _BCM_TD2_NUM_L2_UC_LEAVES_PER_PIPE , 3183 _TD2_NUM_COS(unit), 3184 _TD2_NUM_COS(unit), &id)); 3185 /* The following logic is to make sure the id is always 3186 * multiple of 8 3187 */ 3188 while ( id % 8 != 0) { 3189 id = ((id + 8) & 0xfffffff8); 3190 if (id > _BCM_TD2_NUM_L2_UC_LEAVES_PER_PIPE ) { 3191 return BCM_E_RESOURCE; 3192 } 3193 BCM_IF_ERROR_RETURN( 3194 _bcm_td2_node_index_get(res->ext_qlist.bits, id, 3195 _BCM_TD2_NUM_L2_UC_LEAVES_PER_PIPE, 3196 NUM_COS(unit), 3197 NUM_COS(unit), &id)); 3198 } 3199 _bcm_td2_node_index_set(&res->ext_qlist, id, 3200 _TD2_NUM_COS(unit)); 3201 parent->base_index = id ; 3202 node->hw_index = parent->base_index; 3203 node->hw_cosq = node->hw_index % NUM_COS(unit); 3204 } else { 3205 node->hw_index = parent->base_index + 3206 node->attached_to_input; 3207 node->hw_cosq = node->hw_index % NUM_COS(unit); 3208 } 3209 } 3210 break; 3211 3212 case SOC_TD2_NODE_LVL_L2: 3213 /* passthru */ 3214 default: 3215 return BCM_E_PARAM; 3216 3217 } 3218 3219 BCM_IF_ERROR_RETURN(_bcm_td2_attach_node_in_hw(unit, node)); 3220 return BCM_E_NONE; 3221 } 3222 3223 STATIC int 3224 _bcm_td2_detach_node_in_hw(int unit, _bcm_td2_cosq_node_t *node) 3225 { 3226 int local_port; 3227 3228 local_port = node->local_port; 3229 3230 if (!IS_TD2_HSP_PORT(unit, local_port)) { 3231 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_sched_parent_child_set(unit, 3232 local_port, node->parent->level, 3233 node->parent->hw_index, node->hw_index, 3234 SOC_TD2_SCHED_MODE_WRR, 1, node)); 3235 } 3236 3237 return BCM_E_NONE; 3238 } 3239 3240 /* 3241 * Function: 3242 * _bcm_td2_cosq_node_unresolve 3243 * Purpose: 3244 * Unresolve queue number in the specified scheduler tree and its subtree 3245 * Parameters: 3246 * unit - (IN) unit number 3247 * node - (IN) node structure for the specified scheduler node 3248 * cosq - (IN) COS queue to attach to 3249 * Returns: 3250 * BCM_E_XXX 3251 */ 3252 STATIC int 3253 _bcm_td2_cosq_node_unresolve(int unit, _bcm_td2_cosq_node_t *node, 3254 bcm_cos_queue_t cosq) 3255 { 3256 _bcm_td2_cosq_node_t *parent; 3257 _bcm_td2_mmu_info_t *mmu_info; 3258 _bcm_td2_pipe_resources_t * res; 3259 _bcm_td2_cosq_port_info_t *port_info; 3260 _bcm_td2_cosq_list_t *list; 3261 int numq = 1, port; 3262 3263 if (node->attached_to_input < 0) { 3264 /* Has been unresolved already */ 3265 return BCM_E_NONE; 3266 } 3267 3268 parent = node->parent; 3269 3270 if (!parent) { 3271 return BCM_E_PARAM; 3272 } 3273 3274 mmu_info = _bcm_td2_mmu_info[unit]; 3275 3276 BCM_IF_ERROR_RETURN 3277 (_bcm_td2_cosq_node_get(unit, node->gport, 0, NULL, &port, NULL, NULL)); 3278 3279 port_info = &mmu_info->port_info[port]; 3280 res = port_info->resources; 3281 3282 list = NULL; 3283 3284 switch (parent->level) { 3285 case SOC_TD2_NODE_LVL_ROOT: 3286 break; 3287 3288 case SOC_TD2_NODE_LVL_L0: 3289 if (IS_TD2_HSP_PORT(unit, port) && 3290 (node->type != _BCM_TD2_NODE_MCAST)) { /* L0.0 of HSP port. */ 3291 list = &res->l1_sched_list; 3292 } 3293 break; 3294 3295 case SOC_TD2_NODE_LVL_L1: 3296 break; 3297 3298 case SOC_TD2_NODE_LVL_L2: 3299 /* passthru */ 3300 default: 3301 return BCM_E_PARAM; 3302 3303 } 3304 3305 BCM_IF_ERROR_RETURN(_bcm_td2_detach_node_in_hw(unit, node)); 3306 3307 if (list) { 3308 _bcm_td2_node_index_clear(list, node->hw_index, numq); 3309 } 3310 node->attached_to_input = -1; 3311 3312 return BCM_E_NONE; 3313 } 3314 3315 typedef struct _bcm_td2p_lls_info_s { 3316 int child_lvl; /* level of the node */ 3317 int child_hw_index; /* hw index of the node */ 3318 int node_count[SOC_TD2_NODE_LVL_MAX]; /* total number of nodes in the lls */ 3319 int count[SOC_TD2_NODE_LVL_MAX]; /* number of nodes in each level */ 3320 int offset[SOC_TD2_NODE_LVL_MAX]; /* index of the starting node at each level */ 3321 3322 int kbit_max; /* max speed for the node */ 3323 int kbit_min; /* min speed for the node */ 3324 uint32 *mtro_entries; /* entries to maintain mmu mtro level mem */ 3325 int mtro_restore; /*indicate available data in mtro_entries*/ 3326 } _bcm_td2p_lls_info_t; 3327 3328 /* 3329 * Function: 3330 * _bcm_td2_lls_node_count 3331 * Purpose: 3332 * This function counts the number of nodes at a particular level 3333 * Parameters: 3334 * unit - (IN) unit number 3335 * port - (IN) local port number 3336 * level - (IN) level of the node in LLS 3337 * hw_index - (IN) h/w index of the node 3338 * cookie - (IN) state of the LLS structure 3339 */ 3340 STATIC int _bcm_td2_lls_node_count(int unit, int port, int level, 3341 int hw_index, void *cookie) 3342 { 3343 _bcm_td2p_lls_info_t *i_lls_tree = (_bcm_td2p_lls_info_t *) cookie; 3344 i_lls_tree->node_count[level] += 1; 3345 return 0; 3346 } 3347 3348 /* 3349 * Function: 3350 * _bcm_td2_lls_shapers_init 3351 * Purpose: 3352 * This function reset MTRO shapers so that each node can only schedule upto 3353 * the max rate. 3354 * Parameters: 3355 * unit - (IN) unit number 3356 */ 3357 STATIC int 3358 _bcm_td2_lls_shapers_init(int unit) 3359 { 3360 uint8 *mbuf = NULL; 3361 int table, alloc_size, rv = SOC_E_NONE; 3362 soc_mem_t config_mem; 3363 static const soc_mem_t mem[] = { 3364 MMU_MTRO_L0_MEM_0m, 3365 MMU_MTRO_L1_MEM_0m, 3366 MMU_MTRO_L2_MEM_0m, 3367 MMU_MTRO_L0_MEM_1m, 3368 MMU_MTRO_L1_MEM_1m, 3369 MMU_MTRO_L2_MEM_1m 3370 }; 3371 3372 for (table = 0; table < COUNTOF(mem); table++) { 3373 config_mem = mem[table]; 3374 alloc_size = SOC_MEM_TABLE_BYTES(unit, config_mem); 3375 mbuf = soc_cm_salloc(unit, alloc_size, "MMU_MTRO entries"); 3376 if (NULL == mbuf) { 3377 return BCM_E_MEMORY; 3378 } 3379 sal_memset(mbuf, 0, alloc_size); 3380 rv = soc_mem_write_range(unit, config_mem, MEM_BLOCK_ANY, 3381 soc_mem_index_min(unit, config_mem), 3382 soc_mem_index_max(unit, config_mem), 3383 mbuf); 3384 soc_cm_sfree(unit, mbuf); 3385 mbuf = NULL; 3386 if (SOC_FAILURE(rv)) { 3387 return rv; 3388 } 3389 } 3390 3391 return BCM_E_NONE; 3392 } 3393 3394 /* 3395 * Function: 3396 * _bcm_td2_lls_shapers_remove 3397 * Purpose: 3398 * This function removes shapers on the nodes by setting them 3399 * to the max rate and setting min to 0 so that each node can only schedule upto 3400 * the max rate. It also calculates the leaky bucket parameters based on 3401 * the kbit max 3402 * Parameters: 3403 * unit - (IN) unit number 3404 * port - (IN) local port number 3405 * level - (IN) level of the node in LLS 3406 * hw_index - (IN) h/w index of the node 3407 * cookie - (IN) state of the LLS structure 3408 */ 3409 STATIC int _bcm_td2_lls_shapers_remove(int unit, int port, int level, 3410 int hw_index, void *cookie) 3411 { 3412 _bcm_td2p_lls_info_t *i_lls_tree = (_bcm_td2p_lls_info_t *) cookie; 3413 soc_mem_t config_mem; 3414 uint32 *p_entry; 3415 uint32 entry[SOC_MAX_MEM_WORDS]; 3416 int index, kbit_max, kbit_min; 3417 uint32 meter_flags; 3418 uint32 bucketsize_max, granularity_max, refresh_rate_max, 3419 refresh_bitsize = 0, bucket_bitsize = 0; 3420 3421 static const soc_mem_t memx[] = { 3422 INVALIDm, 3423 MMU_MTRO_L0_MEM_0m, 3424 MMU_MTRO_L1_MEM_0m, 3425 MMU_MTRO_L2_MEM_0m 3426 }; 3427 3428 static const soc_mem_t memy[] = { 3429 INVALIDm, 3430 MMU_MTRO_L0_MEM_1m, 3431 MMU_MTRO_L1_MEM_1m, 3432 MMU_MTRO_L2_MEM_1m 3433 }; 3434 3435 if (level == SOC_TD2_NODE_LVL_MAX) { 3436 return SOC_E_PARAM; 3437 } 3438 3439 if (i_lls_tree->child_lvl != level) { 3440 return BCM_E_NONE; 3441 } 3442 3443 config_mem = SOC_TD2_PMEM(unit, port, memx[level], memy[level]); 3444 3445 if (config_mem == INVALIDm) { 3446 return BCM_E_PARAM; 3447 } 3448 3449 index = i_lls_tree->offset[level] + i_lls_tree->count[level]; 3450 p_entry = &i_lls_tree->mtro_entries[index * SOC_MAX_MEM_WORDS]; 3451 3452 if (*p_entry == 0) { 3453 SOC_IF_ERROR_RETURN(soc_mem_read(unit, config_mem, MEM_BLOCK_ALL, hw_index, 3454 p_entry)); 3455 i_lls_tree->mtro_restore = TRUE; 3456 } 3457 3458 sal_memset(entry, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS); 3459 3460 3461 meter_flags = 0; 3462 3463 refresh_bitsize = soc_mem_field_length(unit, config_mem, MAX_REFRESHf); 3464 bucket_bitsize = soc_mem_field_length(unit, config_mem, MAX_THD_SELf); 3465 3466 /* Setting the max metering configuration */ 3467 kbit_max = i_lls_tree->kbit_max; 3468 BCM_IF_ERROR_RETURN 3469 (_bcm_td_rate_to_bucket_encoding(unit, kbit_max, kbit_max, 3470 meter_flags, refresh_bitsize, 3471 bucket_bitsize, &refresh_rate_max, 3472 &bucketsize_max, &granularity_max)); 3473 3474 soc_mem_field32_set(unit, config_mem, entry, MAX_METER_GRANf, 3475 granularity_max); 3476 soc_mem_field32_set(unit, config_mem, entry, MAX_REFRESHf, 3477 refresh_rate_max); 3478 soc_mem_field32_set(unit, config_mem, entry, MAX_THD_SELf, 3479 bucketsize_max); 3480 3481 3482 /* Setting the min metering configuration */ 3483 kbit_min = i_lls_tree->kbit_min; 3484 BCM_IF_ERROR_RETURN 3485 (_bcm_td_rate_to_bucket_encoding(unit, kbit_min, kbit_min, 3486 meter_flags, refresh_bitsize, 3487 bucket_bitsize, &refresh_rate_max, 3488 &bucketsize_max, &granularity_max)); 3489 3490 soc_mem_field32_set(unit, config_mem, entry, MIN_METER_GRANf, 3491 granularity_max); 3492 soc_mem_field32_set(unit, config_mem, entry, MIN_REFRESHf, 3493 refresh_rate_max); 3494 soc_mem_field32_set(unit, config_mem, entry, MIN_THD_SELf, 3495 bucketsize_max); 3496 3497 BCM_IF_ERROR_RETURN 3498 (soc_mem_write(unit, config_mem, MEM_BLOCK_ALL, hw_index, entry)); 3499 3500 sal_usleep(100); 3501 i_lls_tree->count[level] += 1; 3502 return 0; 3503 } 3504 3505 /* 3506 * Function: 3507 * _bcm_td2_lls_shapers_restore 3508 * Purpose: 3509 * This function restores the shapers on the nodes 3510 * Parameters: 3511 * unit - (IN) unit number 3512 * port - (IN) local port number 3513 * level - (IN) level of the node in LLS 3514 * hw_index - (IN) h/w index of the node 3515 * cookie - (IN) state of the LLS structure 3516 */ 3517 STATIC int _bcm_td2_lls_shapers_restore(int unit, int port, int level, 3518 int hw_index, void *cookie) 3519 { 3520 _bcm_td2p_lls_info_t *i_lls_tree = (_bcm_td2p_lls_info_t *) cookie; 3521 soc_mem_t config_mem; 3522 uint32 *p_entry; 3523 int index; 3524 uint32 entry[SOC_MAX_MEM_WORDS]; 3525 3526 static const soc_mem_t memx[] = { 3527 INVALIDm, 3528 MMU_MTRO_L0_MEM_0m, 3529 MMU_MTRO_L1_MEM_0m, 3530 MMU_MTRO_L2_MEM_0m 3531 }; 3532 3533 static const soc_mem_t memy[] = { 3534 INVALIDm, 3535 MMU_MTRO_L0_MEM_1m, 3536 MMU_MTRO_L1_MEM_1m, 3537 MMU_MTRO_L2_MEM_1m 3538 }; 3539 3540 if (level == SOC_TD2_NODE_LVL_MAX) { 3541 return SOC_E_PARAM; 3542 } 3543 3544 config_mem = SOC_TD2_PMEM(unit, port, memx[level], memy[level]); 3545 3546 if (i_lls_tree->child_lvl != level) { 3547 return BCM_E_NONE; 3548 } 3549 3550 if (config_mem == INVALIDm) { 3551 return BCM_E_PARAM; 3552 } 3553 3554 3555 sal_memset(entry, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS); 3556 3557 soc_mem_field32_set(unit, config_mem, entry, MIN_REFRESHf, 3558 500); 3559 soc_mem_field32_set(unit, config_mem, entry, MIN_THD_SELf, 3560 3); 3561 3562 SOC_IF_ERROR_RETURN 3563 (soc_mem_write(unit, config_mem, MEM_BLOCK_ALL, hw_index, entry)); 3564 3565 sal_usleep(100); 3566 3567 index = i_lls_tree->offset[level] + i_lls_tree->count[level]; 3568 if (i_lls_tree->mtro_entries != NULL) { 3569 p_entry = &i_lls_tree->mtro_entries[index * SOC_MAX_MEM_WORDS]; 3570 3571 if (i_lls_tree->mtro_restore == TRUE) { 3572 SOC_IF_ERROR_RETURN(soc_mem_write(unit, config_mem, MEM_BLOCK_ALL, 3573 hw_index, p_entry)); 3574 } 3575 } 3576 i_lls_tree->count[level] += 1; 3577 3578 return 0; 3579 } 3580 3581 /* 3582 * Function: 3583 * _bcm_td2_num_ones 3584 * Purpose: 3585 * This function calculates the numbers of 1s in the binary format 3586 * of the number 3587 * Parameters: 3588 * m - (IN) number 3589 * Returns: 3590 * The number of 1s in the binary format of the number 3591 */ 3592 STATIC uint32 3593 _bcm_td2_num_ones(uint32 m) 3594 { 3595 uint32 i = 0; 3596 3597 while (m) { 3598 m &= m - 1; 3599 i += 1; 3600 } 3601 return i; 3602 } 3603 3604 /* 3605 * Function: 3606 * _bcm_td2plus_compute_lls_config 3607 * Purpose: 3608 * This function computes the LLS configuration at each level 3609 * Parameters: 3610 * unit - (IN) unit number 3611 * port - (IN) local port number 3612 * level - (IN) level of the node in LLS 3613 * first_sp_child - (OUT) first sp child 3614 * first_sp_mc_child - (OUT) first so multicast child 3615 * ucmap - (OUT) unicast node map 3616 * spmap - (OUT) SPRI node map 3617 * child_index - (IN) index of the child node 3618 * cur_mode - (IN) current schedling mode of the node 3619 * mode - (IN) new scheduling mode of the node 3620 * max_children - (IN) maximum number of children in the level 3621 * Returns: 3622 * BCM_E_XXX 3623 */ 3624 STATIC int 3625 _bcm_td2plus_compute_lls_config (int unit, int port, int level, 3626 int *first_sp_child, 3627 int *first_sp_mc_child, 3628 int *num_spri, 3629 uint32 *ucmap, 3630 uint32 *spmap, 3631 int child_index, 3632 soc_td2_sched_mode_e cur_mode, 3633 soc_td2_sched_mode_e mode, 3634 int max_children) 3635 { 3636 uint32 ucm = 0, mcm = 0, cur_spmap, cur_num_spri, lucmap = 0; 3637 int ii, *pfc, uc, mc, fc, oc, *use_fc; 3638 3639 cur_num_spri = _bcm_td2_num_ones(*spmap); 3640 cur_spmap = *spmap; 3641 3642 if (level == SOC_TD2_NODE_LVL_L1) { 3643 if (IS_CPU_PORT(unit, port)) { 3644 use_fc = first_sp_mc_child; 3645 } else { 3646 use_fc = (child_index >= 1480) ? first_sp_mc_child : first_sp_child; 3647 } 3648 } else { 3649 use_fc = first_sp_child; 3650 } 3651 3652 if (cur_num_spri == 0) { 3653 *ucmap = 0; 3654 *spmap = 0; 3655 } 3656 3657 if (mode == SOC_TD2_SCHED_MODE_STRICT) { 3658 if (child_index > *use_fc) { 3659 if ((child_index - *use_fc) >= max_children && cur_num_spri > 0) { 3660 return BCM_E_UNAVAIL; 3661 } 3662 } else if (child_index < *use_fc) { 3663 return BCM_E_UNAVAIL; 3664 } 3665 } 3666 3667 if (level == SOC_TD2_NODE_LVL_L1) { 3668 for (mcm = 0, mc = 0, ucm = 0, uc = 0, ii = 0; ii < 8; ii++) { 3669 if (*ucmap & (1 << ii)) { 3670 mcm |= (cur_spmap & (1 << ii)) ? (1 << mc) : 0; 3671 mc += 1; 3672 } else { 3673 ucm |= (cur_spmap & (1 << ii)) ? (1 << uc) : 0; 3674 uc += 1; 3675 } 3676 } 3677 3678 if (child_index < 1480) { 3679 fc = *first_sp_child; 3680 oc = _bcm_td2_num_ones(ucm); 3681 BCM_IF_ERROR_RETURN(_bcm_td2plus_compute_lls_config(unit, port, 3682 level - 1, &fc, NULL, &oc, &lucmap, &ucm, child_index, 3683 cur_mode, mode, 8)); 3684 } else { 3685 fc = *first_sp_mc_child; 3686 oc = _bcm_td2_num_ones(mcm); 3687 BCM_IF_ERROR_RETURN(_bcm_td2plus_compute_lls_config(unit, port, 3688 level - 1, &fc, NULL, &oc, &lucmap, &mcm, 3689 child_index, cur_mode, mode, 8)); 3690 } 3691 3692 cur_spmap = 0; 3693 *ucmap = 0; 3694 for (fc = 0, ii = 0; ii < 8; ii++) { 3695 if (ucm) { 3696 cur_spmap |= (ucm & (1 << ii)) ? 1 << fc : 0; 3697 fc += 1; 3698 ucm &= ~(1 << ii); 3699 } 3700 3701 if (mcm) { 3702 cur_spmap |= (mcm & (1 << ii)) ? 1 << fc : 0; 3703 *ucmap |= 1 << fc; 3704 fc += 1; 3705 mcm &= ~(1 << ii); 3706 } 3707 3708 if (fc > max_children) { 3709 return BCM_E_PARAM; 3710 } 3711 3712 if ((mcm == 0) && (ucm == 0)) { 3713 break; 3714 } 3715 } 3716 3717 } else { 3718 pfc = first_sp_child; 3719 if (mode == SOC_TD2_SCHED_MODE_STRICT) { 3720 if (*pfc > child_index) { 3721 cur_spmap <<= (*pfc - child_index); 3722 cur_spmap |= 1; 3723 *pfc = child_index; 3724 *num_spri += 1; 3725 } else { 3726 if (((1 << (child_index - *pfc)) & cur_spmap) == 0) { 3727 cur_spmap |= 1 << (child_index - *pfc); 3728 *num_spri += 1; 3729 } 3730 } 3731 } else { 3732 if (1 << (child_index - *pfc) & cur_spmap) { 3733 cur_spmap &= ~(1 << (child_index - *pfc)); 3734 *num_spri -= 1; 3735 } 3736 } 3737 } 3738 3739 *num_spri = _bcm_td2_num_ones(cur_spmap); 3740 3741 *spmap = cur_spmap; 3742 3743 return BCM_E_NONE; 3744 } 3745 3746 /* 3747 * Function: 3748 * _bcm_td2_compute_lls_config 3749 * Purpose: 3750 * This function computes the LLS configuration at each level 3751 * Parameters: 3752 * unit - (IN) unit number 3753 * port - (IN) local port number 3754 * level - (IN) level of the node in LLS 3755 * first_sp_child - (OUT) first sp child 3756 * first_sp_mc_child - (OUT) first so multicast child 3757 * ucmap - (OUT) unicast node map 3758 * spmap - (OUT) SPRI node map 3759 * child_index - (IN) index of the child node 3760 * cur_mode - (IN) current schedling mode of the node 3761 * mode - (IN) new scheduling mode of the node 3762 * max_children - (IN) maximum number of children in the level 3763 * Returns: 3764 * BCM_E_XXX 3765 */ 3766 STATIC int 3767 _bcm_td2_compute_lls_config(int unit, int port, int level, 3768 int *first_sp_child, 3769 int *first_sp_mc_child, 3770 int *num_spri, 3771 uint32 *ucmap, 3772 uint32 *spmap, 3773 int child_index, 3774 soc_td2_sched_mode_e cur_mode, 3775 soc_td2_sched_mode_e mode) 3776 { 3777 if (!soc_feature(unit, soc_feature_vector_based_spri)) { 3778 return BCM_E_UNAVAIL; 3779 } 3780 3781 if (((cur_mode != SOC_TD2_SCHED_MODE_STRICT) && 3782 (mode != SOC_TD2_SCHED_MODE_STRICT)) || 3783 ((cur_mode == SOC_TD2_SCHED_MODE_STRICT) && 3784 (mode == SOC_TD2_SCHED_MODE_STRICT))) { 3785 return BCM_E_NONE; 3786 } 3787 3788 return _bcm_td2plus_compute_lls_config(unit, port, level, first_sp_child, 3789 first_sp_mc_child, num_spri, 3790 ucmap, spmap, child_index, 3791 cur_mode, mode, 8); 3792 } 3793 3794 STATIC int 3795 _bcm_td2_cosq_traverse_lls_tree(int unit, int port, _bcm_td2_cosq_node_t *node, 3796 _soc_td2_lls_traverse_cb cb, void *cookie) 3797 { 3798 if (node->child) { 3799 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_traverse_lls_tree(unit, port, 3800 node->child, 3801 cb, cookie)); 3802 } 3803 3804 if (node->sibling) { 3805 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_traverse_lls_tree(unit, port, 3806 node->sibling, cb, cookie)); 3807 } 3808 3809 if (node->level != SOC_TD2_NODE_LVL_ROOT) { 3810 BCM_IF_ERROR_RETURN(cb(unit, port, node->level, node->hw_index, cookie)); 3811 } 3812 3813 return BCM_E_NONE; 3814 } 3815 3816 /* 3817 * Function: 3818 * _bcm_td2_adjust_lls_bw 3819 * Purpose: 3820 * This function adjusts the bandwidth at the level in which the node is 3821 * being switched so that each node gets sufficient bandwidth to do the 3822 * switchover. 3823 * Parameters: 3824 * unit - (IN) unit number 3825 * port - (IN) local port number 3826 * node - (IN) cosq node structure 3827 * child_lvl - (IN) level of the child node 3828 * child_hw_index - (IN) h/w index of the child node 3829 * start - (IN) flag 3830 * i_lls_tree - (OUT) LLS info 3831 * Returns: 3832 * BCM_E_XXX 3833 */ 3834 STATIC int 3835 _bcm_td2_adjust_lls_bw(int unit, bcm_port_t port, _bcm_td2_cosq_node_t *node, 3836 int child_lvl, int child_hw_index, int start, 3837 _bcm_td2p_lls_info_t *i_lls_tree) 3838 { 3839 int rv = BCM_E_NONE, count, mem_size, ii, speed, jj; 3840 soc_info_t *si; 3841 3842 if (!soc_feature(unit, soc_feature_vector_based_spri)) { 3843 return BCM_E_NONE; 3844 } 3845 3846 if (start) { 3847 3848 sal_memset(i_lls_tree, 0, sizeof(_bcm_td2p_lls_info_t)); 3849 i_lls_tree->child_lvl = child_lvl; 3850 i_lls_tree->child_hw_index = child_hw_index; 3851 3852 if (node) { 3853 3854 /* get to top node */ 3855 while(node->parent) { node = node->parent; } 3856 3857 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_traverse_lls_tree(unit, port, 3858 node,_bcm_td2_lls_node_count, i_lls_tree)); 3859 } else { 3860 BCM_IF_ERROR_RETURN(soc_td2_port_lls_traverse(unit, port, 3861 _bcm_td2_lls_node_count, i_lls_tree)); 3862 } 3863 3864 for (count = 0, ii = 0; ii < SOC_TD2_NODE_LVL_MAX; ii++) { 3865 count += i_lls_tree->node_count[ii]; 3866 for (jj = ii - 1; jj >= 0; jj--) { 3867 i_lls_tree->offset[ii] += i_lls_tree->node_count[jj]; 3868 } 3869 } 3870 3871 if (count == 0) { 3872 return BCM_E_INIT; 3873 } 3874 3875 mem_size = sizeof(uint32)*SOC_MAX_MEM_WORDS*count; 3876 i_lls_tree->mtro_entries = sal_alloc(mem_size, "lls_war_buf"); 3877 3878 if (port != CMIC_PORT(unit)) { 3879 rv = soc_esw_portctrl_speed_get(unit, port, &speed); 3880 if (rv == BCM_E_UNAVAIL) { 3881 si = &SOC_INFO(unit); 3882 speed = si->port_speed_max[port]; 3883 } 3884 } else { 3885 speed = 10000; 3886 } 3887 i_lls_tree->kbit_min = 0; 3888 i_lls_tree->kbit_max = ((speed)/10)/i_lls_tree->node_count[child_lvl]; 3889 3890 for (count = 0, ii = 0; ii < SOC_TD2_NODE_LVL_MAX; ii++) { 3891 i_lls_tree->count[ii] = 0; 3892 } 3893 3894 sal_memset(i_lls_tree->mtro_entries, 0, mem_size); 3895 i_lls_tree->mtro_restore = FALSE; 3896 3897 if (node) { 3898 3899 /* get to top node */ 3900 while(node->parent) { node = node->parent; } 3901 3902 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_traverse_lls_tree(unit, port, node, 3903 _bcm_td2_lls_shapers_remove, i_lls_tree)); 3904 } else { 3905 BCM_IF_ERROR_RETURN(soc_td2_port_lls_traverse(unit, port, 3906 _bcm_td2_lls_shapers_remove, i_lls_tree)); 3907 } 3908 } else { 3909 for (count = 0, ii = 0; ii < SOC_TD2_NODE_LVL_MAX; ii++) { 3910 i_lls_tree->count[ii] = 0; 3911 } 3912 3913 if (node) { 3914 /* get to top node */ 3915 while(node->parent) { node = node->parent; } 3916 3917 rv = _bcm_td2_cosq_traverse_lls_tree(unit, port, node, 3918 _bcm_td2_lls_shapers_restore, i_lls_tree); 3919 } else { 3920 rv = soc_td2_port_lls_traverse(unit, port, 3921 _bcm_td2_lls_shapers_restore, i_lls_tree); 3922 } 3923 3924 if (i_lls_tree->mtro_entries) { 3925 sal_free(i_lls_tree->mtro_entries); 3926 i_lls_tree->mtro_entries = NULL; 3927 } 3928 } 3929 3930 return rv; 3931 } 3932 3933 /* 3934 * Function: 3935 * _bcm_td2_port_enqueue_set 3936 * Purpose: 3937 * Enable or Disable the enqueing the packets to the port 3938 * Parameters: 3939 * unit - (IN) unit number 3940 * gport - (IN) gport of the port 3941 * enable - (IN) TRUE to enable 3942 * FALSE to disable 3943 * Returns: 3944 * BCM_E_XXX 3945 */ 3946 3947 int 3948 _bcm_td2_port_enqueue_set(int unit, bcm_port_t gport, int enable) 3949 { 3950 bcm_port_t local_port; 3951 3952 BCM_IF_ERROR_RETURN 3953 (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port)); 3954 3955 SOC_IF_ERROR_RETURN( 3956 soc_td2_port_mmu_tx_enable_set(unit, local_port, enable)); 3957 SOC_IF_ERROR_RETURN( 3958 soc_td2_mmu_rx_enable_set(unit, local_port, enable)); 3959 3960 return BCM_E_NONE; 3961 } 3962 /* 3963 * Function: 3964 * _bcm_td2_port_enqueue_get 3965 * Purpose: 3966 * Getting the enqueing state of the port 3967 * Parameters: 3968 * unit - (IN) unit number 3969 * gport - (IN) gport of the port 3970 * enable - (IN) TRUE to enable 3971 * FALSE to disable 3972 * Returns: 3973 * BCM_E_XXX 3974 */ 3975 3976 int 3977 _bcm_td2_port_enqueue_get(int unit, bcm_port_t gport, 3978 int *enable) 3979 { 3980 uint64 rval64; 3981 int mmu_port, phy_port, i; 3982 int rv = BCM_E_NONE; 3983 bcm_port_t local_port; 3984 soc_info_t *si; 3985 soc_reg_t reg_tmp; 3986 soc_reg_t reg[3][2] = { 3987 { 3988 THDU_OUTPUT_PORT_RX_ENABLE0_64r, 3989 THDU_OUTPUT_PORT_RX_ENABLE1_64r 3990 }, 3991 { 3992 MMU_THDM_DB_PORTSP_RX_ENABLE0_64r, 3993 MMU_THDM_DB_PORTSP_RX_ENABLE1_64r 3994 }, 3995 { 3996 MMU_THDM_MCQE_PORTSP_RX_ENABLE0_64r, 3997 MMU_THDM_MCQE_PORTSP_RX_ENABLE1_64r 3998 } 3999 }; 4000 int max_reg = 3; 4001 4002 BCM_IF_ERROR_RETURN 4003 (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port)); 4004 4005 si = &SOC_INFO(unit); 4006 4007 phy_port = si->port_l2p_mapping[local_port]; 4008 mmu_port = si->port_p2m_mapping[phy_port]; 4009 4010 COMPILER_64_ZERO(rval64); 4011 4012 /* Disable enqueue to the port */ 4013 for (i = 0; i < max_reg; i++) { 4014 reg_tmp = SOC_TD2_PREG(unit, local_port, reg[i][0], reg[i][1]); 4015 4016 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg_tmp, REG_PORT_ANY, 0, &rval64)); 4017 4018 mmu_port &= 0x3f; 4019 if (COMPILER_64_BITTEST(rval64 , mmu_port)) { 4020 *enable = TRUE; 4021 } else { 4022 *enable = FALSE; 4023 } 4024 } 4025 return rv; 4026 } 4027 4028 /* 4029 * Function: 4030 * bcm_td2_lb_lls_init 4031 * Purpose: 4032 * Construct cosq hierarchy for Loopback port in ETS mode 4033 * Parameters: 4034 * unit - (IN) unit number 4035 * Returns: 4036 * BCM_E_XXX 4037 */ 4038 STATIC int 4039 bcm_td2_lb_lls_init(int unit) 4040 { 4041 soc_port_t local_port; 4042 _bcm_td2_mmu_info_t *mmu_info; 4043 _bcm_td2_cosq_node_t *node = NULL; 4044 _bcm_td2_cosq_port_info_t *port_info; 4045 _bcm_td2_pipe_resources_t *res; 4046 bcm_gport_t gport, gport_l0, gport_l1[9], gport_l2[9]; 4047 int phy_port, mmu_port; 4048 uint32 sched_encap; 4049 int id, pipe, cos; 4050 int l1_node_cnt = 9; 4051 int l2_node_cnt = 9; /* 8 MCQs + 1 QCN queue */ 4052 4053 mmu_info = _bcm_td2_mmu_info[unit]; 4054 if(mmu_info == NULL) { 4055 return BCM_E_INIT; 4056 } 4057 4058 /* coverity[illegal_address: FALSE] */ 4059 SOC_PBMP_ITER(PBMP_LB(unit), local_port) { 4060 if (local_port >= _BCM_TD2_MAX_PORT) { 4061 return BCM_E_INTERNAL; 4062 } 4063 port_info = &mmu_info->port_info[local_port]; 4064 pipe = _BCM_TD2_PORT_TO_PIPE(unit, local_port); 4065 res = _BCM_TD2_PRESOURCES(mmu_info, pipe); 4066 4067 /* Root node*/ 4068 node = &mmu_info->sched_node[local_port]; 4069 sched_encap = (local_port << 8) | local_port; 4070 BCM_GPORT_SCHEDULER_SET(gport, sched_encap); 4071 node->gport = gport; 4072 node->level = SOC_TD2_NODE_LVL_ROOT; 4073 node->type = _BCM_TD2_NODE_SCHEDULER; 4074 phy_port = SOC_INFO(unit).port_l2p_mapping[local_port]; 4075 mmu_port = SOC_INFO(unit).port_p2m_mapping[phy_port]; 4076 node->hw_index = mmu_port % 64; 4077 node->numq = 1; 4078 node->local_port = local_port; 4079 node->in_use = TRUE; 4080 node->attached_to_input = 0; 4081 4082 /* L0.0 node */ 4083 node = NULL; 4084 for (id = _BCM_TD2_NUM_PORT_SCHEDULERS; 4085 id < _BCM_TD2_NUM_TOTAL_SCHEDULERS; id++) { 4086 if (mmu_info->sched_node[id].in_use == FALSE) { 4087 node = &mmu_info->sched_node[id]; 4088 node->in_use = TRUE; 4089 break; 4090 } 4091 } 4092 if (!node) { 4093 return BCM_E_RESOURCE; 4094 } 4095 4096 node = &mmu_info->sched_node[id]; 4097 sched_encap = (id << 8) | local_port; 4098 BCM_GPORT_SCHEDULER_SET(gport_l0, sched_encap); 4099 node->gport = gport_l0; 4100 node->numq = l1_node_cnt; 4101 node->local_port = local_port; 4102 node->type = _BCM_TD2_NODE_SCHEDULER; 4103 node->attached_to_input = -1; 4104 4105 /* Attach to Root node */ 4106 BCM_IF_ERROR_RETURN 4107 (bcm_td2_cosq_gport_attach(unit, gport_l0, gport, 0)); 4108 4109 /* L1.0 ~ L1.8 node */ 4110 for (cos = 0; cos < l1_node_cnt; cos++) { 4111 node = NULL; 4112 for (id = _BCM_TD2_NUM_PORT_SCHEDULERS; 4113 id < _BCM_TD2_NUM_TOTAL_SCHEDULERS; id++) { 4114 if (mmu_info->sched_node[id].in_use == FALSE) { 4115 node = &mmu_info->sched_node[id]; 4116 node->in_use = TRUE; 4117 break; 4118 } 4119 } 4120 if (!node) { 4121 return BCM_E_RESOURCE; 4122 } 4123 4124 node = &mmu_info->sched_node[id]; 4125 sched_encap = (id << 8) | local_port; 4126 BCM_GPORT_SCHEDULER_SET(gport_l1[cos], sched_encap); 4127 node->gport = gport_l1[cos]; 4128 node->numq = 1; 4129 node->local_port = local_port; 4130 node->type = _BCM_TD2_NODE_SCHEDULER; 4131 node->attached_to_input = -1; 4132 4133 /* Attach to L0 node */ 4134 BCM_IF_ERROR_RETURN 4135 (bcm_td2_cosq_gport_attach(unit, gport_l1[cos], gport_l0, cos)); 4136 } 4137 4138 /* L2 mc queue & QCN queue */ 4139 for (cos = 0; cos < l2_node_cnt; cos++) { 4140 for (id = port_info->mc_base; id < port_info->mc_limit; id++) { 4141 if (res->p_mc_queue_node[id].numq == 0) { 4142 break; 4143 } 4144 } 4145 4146 if (id == port_info->mc_limit) { 4147 return BCM_E_RESOURCE; 4148 } 4149 4150 /* set index bits */ 4151 BCM_GPORT_MCAST_QUEUE_GROUP_SYSQID_SET(gport_l2[cos], local_port, id); 4152 node = &res->p_mc_queue_node[id]; 4153 node->gport = gport_l2[cos]; 4154 node->numq = 1; 4155 node->level = SOC_TD2_NODE_LVL_L2; 4156 node->type = _BCM_TD2_NODE_MCAST; 4157 node->hw_cosq = id - port_info->mc_base; 4158 node->hw_index = soc_td2_l2_hw_index(unit, id, 0); 4159 node->local_port = local_port; 4160 node->remote_modid = -1; 4161 node->remote_port = -1; 4162 node->in_use = TRUE; 4163 4164 /* Attach to L1 node */ 4165 BCM_IF_ERROR_RETURN 4166 (bcm_td2_cosq_gport_attach(unit, gport_l2[cos], 4167 gport_l1[cos], 0)); 4168 } 4169 4170 } 4171 4172 return BCM_E_NONE; 4173 } 4174 /* 4175 * Function: 4176 * bcm_td2_cosq_hw_idx_get 4177 * Purpose: 4178 * Get cosq hardware index 4179 * Returns: 4180 * BCM_E_XXX 4181 */ 4182 4183 int 4184 _bcm_td2_cosq_hw_idx_get(int unit, int max_count, bcm_gport_t *port, int *hw_idx, int* count) 4185 { 4186 _bcm_td2_mmu_info_t *mmu_info; 4187 _bcm_td2_pipe_resources_t *res; 4188 int pipe = 0, qmax, qmin, id, i = 0; 4189 if (port == NULL || hw_idx == NULL || count == NULL) { 4190 return BCM_E_PARAM; 4191 } 4192 4193 mmu_info = _bcm_td2_mmu_info[unit]; 4194 for (pipe = 0; pipe < 2; pipe++) { 4195 res = _BCM_TD2_PRESOURCES(mmu_info, pipe); 4196 qmax = (pipe + 1) * _BCM_TD2_NUM_L2_UC_LEAVES_PER_PIPE; 4197 qmin = res->num_base_queues + 4198 (pipe * _BCM_TD2_NUM_L2_UC_LEAVES_PER_PIPE); 4199 for (id = qmin; id < qmax; id++) { 4200 if (res->p_queue_node[id].numq == 0 || 4201 res->p_queue_node[id].level != SOC_TD2_NODE_LVL_L2) { 4202 continue; 4203 } 4204 if (i >= max_count) { 4205 return BCM_E_CONFIG; 4206 } 4207 /*for Y pipe, uc queue starts at hw_idx 2048*/ 4208 hw_idx[i] = res->p_queue_node[id].hw_index + pipe * 2048; 4209 port[i] = res->p_queue_node[id].local_port; 4210 i++; 4211 } 4212 } 4213 *count = i; 4214 return BCM_E_NONE; 4215 } 4216 4217 /* 4218 * Function: 4219 * bcm_td2_cosq_gport_add 4220 * Purpose: 4221 * Create a cosq gport structure 4222 * Parameters: 4223 * unit - (IN) unit number 4224 * port - (IN) port number 4225 * numq - (IN) number of COS queues 4226 * flags - (IN) flags (BCM_COSQ_GPORT_XXX) 4227 * gport - (OUT) GPORT identifier 4228 * Returns: 4229 * BCM_E_XXX 4230 */ 4231 int 4232 bcm_td2_cosq_gport_add(int unit, bcm_gport_t port, int numq, uint32 flags, 4233 bcm_gport_t *gport) 4234 { 4235 _bcm_td2_mmu_info_t *mmu_info; 4236 _bcm_td2_cosq_node_t *node = NULL; 4237 _bcm_td2_cosq_port_info_t *port_info; 4238 uint32 sched_encap; 4239 _bcm_td2_pipe_resources_t *res; 4240 int phy_port, mmu_port, local_port; 4241 int id, ii, q_base, pipe, qmin, qmax; 4242 bcm_gport_t tmp_gport; 4243 4244 LOG_INFO(BSL_LS_BCM_COSQ, 4245 (BSL_META_U(unit, 4246 "bcm_td2_cosq_gport_add: unit=%d port=0x%x numq=%d flags=0x%x\n"), 4247 unit, port, numq, flags)); 4248 4249 if (!soc_feature(unit, soc_feature_ets)) { 4250 return BCM_E_UNAVAIL; 4251 } 4252 4253 if (gport == NULL) { 4254 return BCM_E_PARAM; 4255 } 4256 4257 if (_bcm_td2_mmu_info[unit] == NULL) { 4258 return BCM_E_INIT; 4259 } 4260 4261 BCM_IF_ERROR_RETURN 4262 (_bcm_td2_cosq_localport_resolve(unit, port, &local_port)); 4263 4264 if (local_port < 0) { 4265 return BCM_E_PORT; 4266 } 4267 4268 /* Check Alignment request is not for unsupported type */ 4269 if (flags & BCM_COSQ_GPORT_SCHEDULER_PFC_ALIGN) { 4270 if (!(flags == (BCM_COSQ_GPORT_SCHEDULER | 4271 BCM_COSQ_GPORT_SCHEDULER_PFC_ALIGN))) { 4272 return BCM_E_PARAM; 4273 } 4274 } 4275 4276 mmu_info = _bcm_td2_mmu_info[unit]; 4277 4278 port_info = &mmu_info->port_info[local_port]; 4279 pipe = _BCM_TD2_PORT_TO_PIPE(unit, local_port); 4280 res = _BCM_TD2_PRESOURCES(mmu_info, pipe); 4281 4282 if (!mmu_info->ets_mode) { 4283 4284 /* cleanup the default lls setup */ 4285 SOC_IF_ERROR_RETURN(soc_td2_lls_reset(unit)); 4286 4287 mmu_info->ets_mode = 1; 4288 4289 BCM_IF_ERROR_RETURN(bcm_td2_lb_lls_init(unit)); 4290 } 4291 4292 switch (flags) { 4293 case BCM_COSQ_GPORT_UCAST_QUEUE_GROUP: 4294 if (numq != 1) { 4295 return BCM_E_PARAM; 4296 } 4297 4298 if (IS_CPU_PORT(unit, local_port)) { 4299 return BCM_E_PARAM; 4300 } 4301 4302 for (id = port_info->uc_base; id < port_info->uc_limit; id++) { 4303 if (res->p_queue_node[id].numq == 0) { 4304 break; 4305 } 4306 } 4307 4308 qmax = (pipe + 1) * _BCM_TD2_NUM_L2_UC_LEAVES_PER_PIPE; 4309 if (id == port_info->uc_limit) { 4310 if (IS_TD2_HSP_PORT(unit, local_port)) { 4311 return BCM_E_RESOURCE; 4312 } 4313 qmin = res->num_base_queues + 4314 (pipe * _BCM_TD2_NUM_L2_UC_LEAVES_PER_PIPE); 4315 for (id = qmin; id < qmax; id++) { 4316 if (res->p_queue_node[id].numq == 0) { 4317 break; 4318 } 4319 } 4320 } 4321 4322 if (id == qmax) { 4323 return BCM_E_RESOURCE; 4324 } 4325 4326 BCM_GPORT_UCAST_QUEUE_GROUP_SYSQID_SET(*gport, local_port, id); 4327 node = &res->p_queue_node[id]; 4328 node->gport = *gport; 4329 node->numq = numq; 4330 node->level = SOC_TD2_NODE_LVL_L2; 4331 node->hw_cosq = id - port_info->uc_base; 4332 node->hw_index = soc_td2_l2_hw_index(unit, id, 1); 4333 node->local_port = local_port; 4334 node->remote_modid = -1; 4335 node->remote_port = -1; 4336 node->type = _BCM_TD2_NODE_UCAST; 4337 node->in_use = TRUE; 4338 break; 4339 4340 case BCM_COSQ_GPORT_SUBSCRIBER: 4341 case BCM_COSQ_GPORT_VIRTUAL_PORT: 4342 case BCM_COSQ_GPORT_VLAN_UCAST_QUEUE_GROUP: 4343 if (IS_TD2_HSP_PORT(unit, local_port)) { 4344 return BCM_E_PARAM; 4345 } 4346 /* Service Queueing are outside default queues. Hence NO alignment 4347 * required. 4348 */ 4349 BCM_IF_ERROR_RETURN( 4350 _bcm_td2_node_index_get(res->ext_qlist.bits, res->num_base_queues, 4351 _BCM_TD2_NUM_L2_UC_LEAVES_PER_PIPE, numq, 4352 1, &q_base)); 4353 4354 _bcm_td2_node_index_set(&res->ext_qlist, q_base, numq); 4355 qmin = res->num_base_queues + (pipe * _BCM_TD2_NUM_L2_UC_LEAVES_PER_PIPE); 4356 qmax = (pipe + 1) * _BCM_TD2_NUM_L2_UC_LEAVES_PER_PIPE; 4357 4358 for (ii = 0, id = qmin; id < qmax; id++) { 4359 if (res->p_queue_node[id].numq > 0) { 4360 ii = 0; 4361 } else { 4362 ii += 1; 4363 4364 if (ii == numq) { 4365 break; 4366 } 4367 } 4368 } 4369 4370 if (ii != numq) { 4371 return BCM_E_RESOURCE; 4372 } 4373 4374 id = id - (numq - 1); 4375 4376 for (ii = 0; ii < numq; ii++, id++) { 4377 BCM_GPORT_UCAST_QUEUE_GROUP_SYSQID_SET(tmp_gport, local_port, id); 4378 node= &res->p_queue_node[id]; 4379 node->gport = tmp_gport; 4380 node->numq = numq - ii; 4381 node->level = SOC_TD2_NODE_LVL_L2; 4382 node->type = (flags == BCM_COSQ_GPORT_VIRTUAL_PORT) ? 4383 _BCM_TD2_NODE_VM_UCAST : _BCM_TD2_NODE_SERVICE_UCAST; 4384 node->hw_index = q_base + ii; 4385 /* by default assign the cosq on order of order of alocation, 4386 * can be overriddedn by cos_mapping_set */ 4387 node->hw_cosq = ii; 4388 node->local_port = local_port; 4389 node->remote_modid = -1; 4390 node->remote_port = -1; 4391 node->in_use = TRUE; 4392 4393 if (ii == 0) { 4394 *gport = tmp_gport; 4395 } 4396 } 4397 break; 4398 4399 case BCM_COSQ_GPORT_DESTMOD_UCAST_QUEUE_GROUP: 4400 if (numq != 1) { 4401 return BCM_E_PARAM; 4402 } 4403 4404 if (!IS_HG_PORT(unit, local_port)) { 4405 return BCM_E_PORT; 4406 } 4407 4408 qmin = res->num_base_queues + (pipe * _BCM_TD2_NUM_L2_UC_LEAVES_PER_PIPE); 4409 qmax = (pipe + 1) * _BCM_TD2_NUM_L2_UC_LEAVES_PER_PIPE; 4410 for (id = qmin; id < qmax; id++) { 4411 if (res->p_queue_node[id].numq == 0) { 4412 break; 4413 } 4414 } 4415 4416 if (id >= qmax) { 4417 return BCM_E_RESOURCE; 4418 } 4419 4420 BCM_GPORT_UCAST_QUEUE_GROUP_SYSQID_SET(*gport, local_port, id); 4421 node = &res->p_queue_node[id]; 4422 node->gport = *gport; 4423 node->numq = numq; 4424 node->level = SOC_TD2_NODE_LVL_L2; 4425 node->type = _BCM_TD2_NODE_VOQ; 4426 node->hw_index = -1; 4427 /* by default assign the cosq on order of order of alocation, 4428 * can be overriddedn by cos_mapping_set */ 4429 node->hw_cosq = -1; 4430 node->local_port = local_port; 4431 node->remote_modid = -1; 4432 node->remote_port = -1; 4433 node->in_use = TRUE; 4434 break; 4435 4436 case BCM_COSQ_GPORT_MCAST_QUEUE_GROUP: 4437 if (numq != 1) { 4438 return BCM_E_PARAM; 4439 } 4440 4441 for (id = port_info->mc_base; id < port_info->mc_limit; id++) { 4442 if (res->p_mc_queue_node[id].numq == 0) { 4443 break; 4444 } 4445 } 4446 4447 if (id == port_info->mc_limit) { 4448 return BCM_E_RESOURCE; 4449 } 4450 4451 /* set index bits */ 4452 BCM_GPORT_MCAST_QUEUE_GROUP_SYSQID_SET(*gport, local_port, id); 4453 node = &res->p_mc_queue_node[id]; 4454 node->gport = *gport; 4455 node->numq = numq; 4456 node->level = SOC_TD2_NODE_LVL_L2; 4457 node->type = _BCM_TD2_NODE_MCAST; 4458 node->hw_cosq = id - port_info->mc_base; 4459 node->hw_index = soc_td2_l2_hw_index(unit, id, 0); 4460 node->local_port = local_port; 4461 node->remote_modid = -1; 4462 node->remote_port = -1; 4463 node->in_use = TRUE; 4464 break; 4465 4466 case BCM_COSQ_GPORT_SCHEDULER: 4467 case BCM_COSQ_GPORT_SCHEDULER | BCM_COSQ_GPORT_SCHEDULER_PFC_ALIGN: 4468 if (numq < -1) { 4469 return BCM_E_PARAM; 4470 } 4471 for (id = _BCM_TD2_NUM_PORT_SCHEDULERS; 4472 id < _BCM_TD2_NUM_TOTAL_SCHEDULERS; id++) { 4473 if (mmu_info->sched_node[id].in_use == FALSE) { 4474 node = &mmu_info->sched_node[id]; 4475 node->in_use = TRUE; 4476 break; 4477 } 4478 } 4479 if (!node) { 4480 return BCM_E_RESOURCE; 4481 } 4482 4483 node = &mmu_info->sched_node[id]; 4484 sched_encap = (id << 8) | local_port; 4485 BCM_GPORT_SCHEDULER_SET(*gport, sched_encap); 4486 node->gport = *gport; 4487 node->numq = numq; 4488 node->local_port = local_port; 4489 node->type = _BCM_TD2_NODE_SCHEDULER; 4490 node->attached_to_input = -1; 4491 if (flags & BCM_COSQ_GPORT_SCHEDULER_PFC_ALIGN) { 4492 node->node_align_value = _BCM_TD2_START_INDEX_ALIGN_PFC; 4493 } else { 4494 node->node_align_value = _BCM_TD2_START_INDEX_ALIGN_DEFAULT; 4495 } 4496 break; 4497 4498 case BCM_COSQ_GPORT_WITH_ID: 4499 case 0: 4500 if (numq < -1) { 4501 return BCM_E_PARAM; 4502 } 4503 4504 /* this is a port level scheduler */ 4505 id = local_port; 4506 4507 if ( id < 0 || id >= _BCM_TD2_NUM_PORT_SCHEDULERS) { 4508 return BCM_E_PARAM; 4509 } 4510 4511 if (numq >= _BCM_TD2_NUM_L0_SCHEDULER_PER_PIPE) { 4512 return BCM_E_RESOURCE; 4513 } 4514 4515 node = &mmu_info->sched_node[id]; 4516 sched_encap = (id << 8) | local_port; 4517 BCM_GPORT_SCHEDULER_SET(*gport, sched_encap); 4518 node->gport = *gport; 4519 node->level = SOC_TD2_NODE_LVL_ROOT; 4520 node->type = _BCM_TD2_NODE_SCHEDULER; 4521 phy_port = SOC_INFO(unit).port_l2p_mapping[local_port]; 4522 mmu_port = SOC_INFO(unit).port_p2m_mapping[phy_port]; 4523 node->hw_index = mmu_port % 64; 4524 4525 if (IS_TD2_HSP_PORT(unit, local_port)) { 4526 /* free any schedulers in use by legacy setup */ 4527 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_set_scheduler_states(unit, local_port, 0)); 4528 BCM_IF_ERROR_RETURN(soc_td2_lls_port_uninit(unit, local_port)); 4529 } 4530 4531 if (IS_TD2_HSP_PORT(unit, local_port)) { 4532 node->numq = _BCM_TD2_HSP_PORT_MAX_L0; 4533 } else { 4534 node->numq = numq; 4535 } 4536 node->local_port = local_port; 4537 node->in_use = TRUE; 4538 node->attached_to_input = 0; 4539 break; 4540 4541 default: 4542 return BCM_E_PARAM; 4543 } 4544 4545 LOG_INFO(BSL_LS_BCM_COSQ, 4546 (BSL_META_U(unit, 4547 " gport=0x%x\n"), 4548 *gport)); 4549 4550 return BCM_E_NONE; 4551 } 4552 4553 /* 4554 * Function: 4555 * bcm_td2_cosq_gport_detach 4556 * Purpose: 4557 * Detach sched_port from the specified index (cosq) of input_port 4558 * Parameters: 4559 * unit - (IN) unit number 4560 * sched_port - (IN) scheduler GPORT identifier 4561 * input_port - (IN) GPORT to detach from 4562 * cosq - (IN) COS queue to detach from 4563 * Returns: 4564 * BCM_E_XXX 4565 */ 4566 int 4567 bcm_td2_cosq_gport_detach(int unit, bcm_gport_t sched_gport, 4568 bcm_gport_t input_gport, bcm_cos_queue_t cosq) 4569 { 4570 _bcm_td2_cosq_node_t *sched_node, *input_node = NULL, *prev_node; 4571 bcm_port_t sched_port, input_port = -1; 4572 _bcm_td2_cosq_node_t *parent; 4573 _bcm_td2_cosq_list_t *list; 4574 _bcm_td2_mmu_info_t *mmu_info; 4575 _bcm_td2_pipe_resources_t * res; 4576 _bcm_td2_cosq_port_info_t *port_info; 4577 int start = 0, end = 0, q_base, hw_index; 4578 4579 if (_bcm_td2_mmu_info[unit] == NULL) { 4580 return BCM_E_INIT; 4581 } 4582 4583 if ((BCM_GPORT_IS_UCAST_QUEUE_GROUP(input_gport)) || 4584 (BCM_GPORT_IS_MCAST_QUEUE_GROUP(input_gport))) { 4585 return BCM_E_PARAM; 4586 } 4587 4588 BCM_IF_ERROR_RETURN 4589 (_bcm_td2_cosq_node_get(unit, sched_gport, 0, NULL, &sched_port, NULL, 4590 &sched_node)); 4591 4592 if (sched_node->attached_to_input < 0) { 4593 /* Not attached yet */ 4594 return BCM_E_PORT; 4595 } 4596 4597 if (input_gport != BCM_GPORT_INVALID) { 4598 if (BCM_GPORT_IS_SCHEDULER(input_gport) || 4599 BCM_GPORT_IS_MODPORT(input_gport) || 4600 BCM_GPORT_IS_LOCAL(input_gport)) { 4601 BCM_IF_ERROR_RETURN 4602 (_bcm_td2_cosq_node_get(unit, input_gport, 0, NULL, 4603 &input_port, NULL, &input_node)); 4604 } else { 4605 if (!(BCM_GPORT_IS_SCHEDULER(sched_gport) || 4606 BCM_GPORT_IS_UCAST_QUEUE_GROUP(sched_gport) || 4607 BCM_GPORT_IS_MCAST_QUEUE_GROUP(sched_gport))) { 4608 return BCM_E_PARAM; 4609 } 4610 else { 4611 BCM_IF_ERROR_RETURN 4612 (_bcm_td2_cosq_localport_resolve(unit, input_gport, 4613 &input_port)); 4614 input_node = NULL; 4615 } 4616 } 4617 } 4618 4619 if (input_port == -1) { 4620 return BCM_E_PORT; 4621 } 4622 4623 mmu_info = _bcm_td2_mmu_info[unit]; 4624 port_info = &mmu_info->port_info[input_port]; 4625 res = port_info->resources; 4626 4627 if (sched_port != input_port) { 4628 return BCM_E_PORT; 4629 } 4630 4631 if (sched_node->parent != input_node) { 4632 return BCM_E_PORT; 4633 } 4634 4635 if ((cosq < -1) || 4636 (input_node && (input_node->numq != -1) && (cosq >= input_node->numq))) { 4637 return BCM_E_PARAM; 4638 } 4639 4640 if (cosq != -1) { 4641 if (sched_node->attached_to_input != cosq) { 4642 return BCM_E_PARAM; 4643 } 4644 } 4645 4646 if (sched_node->type == _BCM_TD2_NODE_SERVICE_UCAST) { 4647 end = sched_node->numq; 4648 } else { 4649 end = 1; 4650 } 4651 4652 for (start = 0; start < end; start++) { 4653 /* unresolve the node - delete this node from parent's child list */ 4654 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_node_unresolve(unit, sched_node, cosq)); 4655 4656 BCM_IF_ERROR_RETURN( 4657 soc_td2_cosq_set_sched_parent(unit, input_port, 4658 sched_node->level, sched_node->hw_index, 4659 _soc_td2_invalid_parent_index(unit, sched_node->level))); 4660 4661 /* now remove from the sw tree */ 4662 if (sched_node->parent != NULL) { 4663 parent = sched_node->parent; 4664 if (sched_node->parent->child == sched_node) { 4665 sched_node->parent->child = sched_node->sibling; 4666 } else { 4667 prev_node = sched_node->parent->child; 4668 while (prev_node != NULL && prev_node->sibling != sched_node) { 4669 prev_node = prev_node->sibling; 4670 } 4671 if (prev_node == NULL) { 4672 return BCM_E_INTERNAL; 4673 } 4674 prev_node->sibling = sched_node->sibling; 4675 } 4676 sched_node->parent = NULL; 4677 sched_node->sibling = NULL; 4678 sched_node->attached_to_input = -1; 4679 if (0 == start) { 4680 hw_index = sched_node->hw_index; 4681 q_base = hw_index; 4682 if ((sched_node->type == _BCM_TD2_NODE_VM_UCAST) || 4683 (sched_node->type == _BCM_TD2_NODE_SERVICE_UCAST)) { 4684 BCM_IF_ERROR_RETURN( 4685 _bcm_td2_node_index_clear(&res->ext_qlist, 4686 q_base, sched_node->numq)); 4687 } 4688 } 4689 4690 if (parent->child == NULL) { 4691 list = NULL; 4692 switch (parent->level) { 4693 case SOC_TD2_NODE_LVL_ROOT: 4694 list = &res->l0_sched_list; 4695 sched_node->hw_index = -1; 4696 break; 4697 case SOC_TD2_NODE_LVL_L0: 4698 list = &res->l1_sched_list; 4699 sched_node->hw_index = -1; 4700 break; 4701 case SOC_TD2_NODE_LVL_L1: 4702 if (sched_node->type == _BCM_TD2_NODE_VOQ) { 4703 list = &res->ext_qlist; 4704 } 4705 break; 4706 default: 4707 break; 4708 } 4709 4710 if (list) { 4711 BCM_IF_ERROR_RETURN(_bcm_td2_node_index_clear(list, 4712 parent->base_index, parent->base_size)); 4713 parent->base_index = -1; 4714 parent->base_size = 0; 4715 } 4716 } 4717 } 4718 if ((sched_node->type == _BCM_TD2_NODE_SERVICE_UCAST) && 4719 ((start + 1) < end)){ 4720 BCM_IF_ERROR_RETURN 4721 (_bcm_td2_cosq_node_get(unit, sched_gport, start + 1, NULL, 4722 &sched_port, NULL, &sched_node)); 4723 if (!sched_node) { 4724 return BCM_E_NOT_FOUND; 4725 } 4726 } 4727 } 4728 4729 LOG_INFO(BSL_LS_BCM_COSQ, 4730 (BSL_META_U(unit, 4731 " hw_cosq=%d\n"), 4732 sched_node->attached_to_input)); 4733 4734 return BCM_E_NONE; 4735 } 4736 4737 STATIC int 4738 _bcm_td2_cosq_gport_delete_all(int unit, bcm_gport_t gport) 4739 { 4740 _bcm_td2_cosq_node_t *node, *tnode, *base_node; 4741 int ii, local_port, phy_port, mmu_port, hw_index; 4742 _bcm_td2_mmu_info_t *mmu_info; 4743 soc_info_t *si; 4744 4745 LOG_INFO(BSL_LS_BCM_COSQ, 4746 (BSL_META_U(unit, 4747 "bcm_td2_cosq_gport_delete_all: unit=%d gport=0x%x\n"), 4748 unit, gport)); 4749 4750 node = NULL; 4751 base_node= NULL; 4752 4753 if (!soc_feature(unit, soc_feature_ets)) { 4754 return BCM_E_UNAVAIL; 4755 } 4756 4757 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 4758 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) || 4759 BCM_GPORT_IS_SCHEDULER(gport)) { 4760 BCM_IF_ERROR_RETURN 4761 (_bcm_td2_cosq_node_get(unit, gport, 0, NULL, &local_port, NULL, &node)); 4762 } else { 4763 local_port = (BCM_GPORT_IS_LOCAL(gport)) ? 4764 BCM_GPORT_LOCAL_GET(gport) : BCM_GPORT_MODPORT_PORT_GET(gport); 4765 4766 if (!SOC_PORT_VALID(unit, local_port)) { 4767 return BCM_E_PORT; 4768 } 4769 4770 mmu_info = _bcm_td2_mmu_info[unit]; 4771 si = &SOC_INFO(unit); 4772 phy_port = si->port_l2p_mapping[local_port]; 4773 mmu_port = si->port_p2m_mapping[phy_port]; 4774 hw_index = _BCM_TD2_ROOT_SCHED_INDEX(unit, mmu_port); 4775 4776 for (ii = 0; ii < _BCM_TD2_NUM_TOTAL_SCHEDULERS; ii++) { 4777 tnode = &mmu_info->sched_node[ii]; 4778 if (tnode->in_use == FALSE) { 4779 continue; 4780 } 4781 if ((tnode->level == SOC_TD2_NODE_LVL_ROOT) && 4782 (tnode->hw_index == hw_index) && 4783 (tnode->local_port == local_port)) { 4784 /* check both mmu_port(unique only within a pipe) 4785 and local_port(unique witin system) to get the 4786 correct node */ 4787 node = tnode; 4788 break; 4789 } 4790 } 4791 if (node == NULL) { 4792 return BCM_E_NONE; 4793 } 4794 } 4795 4796 if (node->child != NULL) { 4797 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_gport_delete_all(unit, node->child->gport)); 4798 } 4799 4800 if (node->sibling != NULL) { 4801 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_gport_delete_all(unit, node->sibling->gport)); 4802 } 4803 4804 if (node->level != SOC_TD2_NODE_LVL_ROOT && node->attached_to_input >= 0) { 4805 BCM_IF_ERROR_RETURN 4806 (bcm_td2_cosq_gport_detach(unit, node->gport, 4807 node->parent->gport, node->attached_to_input)); 4808 } 4809 if ((node->type == _BCM_TD2_NODE_VOQ) && 4810 (node->remote_modid > 0)) { 4811 _bcm_td2_voq_next_base_node_get (unit, local_port, 4812 node->remote_modid, &base_node); 4813 if (base_node != NULL) { 4814 BCM_PBMP_ASSIGN(base_node->fabric_pbmp, 4815 node->fabric_pbmp); 4816 } 4817 } 4818 4819 _BCM_TD2_COSQ_NODE_INIT(node); 4820 return BCM_E_NONE; 4821 } 4822 4823 /* 4824 * Function: 4825 * bcm_td2_cosq_gport_delete 4826 * Purpose: 4827 * Destroy a cosq gport structure 4828 * Parameters: 4829 * unit - (IN) unit number 4830 * gport - (IN) GPORT identifier 4831 * Returns: 4832 * BCM_E_XXX 4833 */ 4834 int 4835 bcm_td2_cosq_gport_delete(int unit, bcm_gport_t gport) 4836 { 4837 _bcm_td2_cosq_node_t *node, *tnode, *base_node; 4838 int ii, local_port, phy_port, mmu_port, hw_index; 4839 _bcm_td2_mmu_info_t *mmu_info; 4840 soc_info_t *si; 4841 4842 LOG_INFO(BSL_LS_BCM_COSQ, 4843 (BSL_META_U(unit, 4844 "bcm_td2_cosq_gport_delete: unit=%d gport=0x%x\n"), 4845 unit, gport)); 4846 4847 node = NULL; 4848 base_node= NULL; 4849 4850 if (!soc_feature(unit, soc_feature_ets)) { 4851 return BCM_E_UNAVAIL; 4852 } 4853 4854 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 4855 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) || 4856 BCM_GPORT_IS_SCHEDULER(gport)) { 4857 BCM_IF_ERROR_RETURN 4858 (_bcm_td2_cosq_node_get(unit, gport, 0, NULL, &local_port, NULL, &node)); 4859 } else { 4860 local_port = (BCM_GPORT_IS_LOCAL(gport)) ? 4861 BCM_GPORT_LOCAL_GET(gport) : BCM_GPORT_MODPORT_PORT_GET(gport); 4862 4863 if (!SOC_PORT_VALID(unit, local_port)) { 4864 return BCM_E_PORT; 4865 } 4866 4867 mmu_info = _bcm_td2_mmu_info[unit]; 4868 si = &SOC_INFO(unit); 4869 phy_port = si->port_l2p_mapping[local_port]; 4870 mmu_port = si->port_p2m_mapping[phy_port]; 4871 hw_index = _BCM_TD2_ROOT_SCHED_INDEX(unit, mmu_port); 4872 4873 for (ii = 0; ii < _BCM_TD2_NUM_TOTAL_SCHEDULERS; ii++) { 4874 tnode = &mmu_info->sched_node[ii]; 4875 if (tnode->in_use == FALSE) { 4876 continue; 4877 } 4878 if ((tnode->level == SOC_TD2_NODE_LVL_ROOT) && 4879 (tnode->hw_index == hw_index) && 4880 (tnode->local_port == local_port)) { 4881 /* check both mmu_port(unique only within a pipe) 4882 and local_port(unique witin system) to get the 4883 correct node */ 4884 node = tnode; 4885 break; 4886 } 4887 } 4888 if (node == NULL) { 4889 return BCM_E_NONE; 4890 } 4891 } 4892 4893 if (node->child != NULL) { 4894 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_gport_delete_all(unit, node->child->gport)); 4895 } 4896 4897 if (node->level != SOC_TD2_NODE_LVL_ROOT && node->attached_to_input >= 0) { 4898 BCM_IF_ERROR_RETURN 4899 (bcm_td2_cosq_gport_detach(unit, node->gport, 4900 node->parent->gport, node->attached_to_input)); 4901 } 4902 if ((node->type == _BCM_TD2_NODE_VOQ) && 4903 (node->remote_modid > 0)) { 4904 _bcm_td2_voq_next_base_node_get (unit, local_port, 4905 node->remote_modid, &base_node); 4906 if (base_node != NULL) { 4907 BCM_PBMP_ASSIGN(base_node->fabric_pbmp, 4908 node->fabric_pbmp); 4909 } 4910 } 4911 4912 _BCM_TD2_COSQ_NODE_INIT(node); 4913 return BCM_E_NONE; 4914 } 4915 4916 /* 4917 * Function: 4918 * bcm_td2_cosq_gport_get 4919 * Purpose: 4920 * Get a cosq gport structure 4921 * Parameters: 4922 * unit - (IN) unit number 4923 * gport - (IN) GPORT identifier 4924 * port - (OUT) port number 4925 * numq - (OUT) number of COS queues 4926 * flags - (OUT) flags (BCM_COSQ_GPORT_XXX) 4927 * Returns: 4928 * BCM_E_XXX 4929 */ 4930 int 4931 bcm_td2_cosq_gport_get(int unit, bcm_gport_t gport, bcm_gport_t *port, 4932 int *numq, uint32 *flags) 4933 { 4934 _bcm_td2_cosq_node_t *node; 4935 bcm_module_t modid; 4936 bcm_port_t local_port; 4937 int id; 4938 _bcm_gport_dest_t dest; 4939 4940 if (port == NULL || numq == NULL || flags == NULL) { 4941 return BCM_E_PARAM; 4942 } 4943 4944 LOG_INFO(BSL_LS_BCM_COSQ, 4945 (BSL_META_U(unit, 4946 "bcm_td2_cosq_gport_get: unit=%d gport=0x%x\n"), 4947 unit, gport)); 4948 4949 BCM_IF_ERROR_RETURN 4950 (_bcm_td2_cosq_node_get(unit, gport, 0, NULL, &local_port, &id, &node)); 4951 4952 if (SOC_USE_GPORT(unit)) { 4953 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid)); 4954 dest.gport_type = _SHR_GPORT_TYPE_MODPORT; 4955 dest.modid = modid; 4956 dest.port = local_port; 4957 BCM_IF_ERROR_RETURN(_bcm_esw_gport_construct(unit, &dest, port)); 4958 } else { 4959 *port = local_port; 4960 } 4961 4962 *numq = node->numq; 4963 4964 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 4965 if (node->type == _BCM_TD2_NODE_SERVICE_UCAST) { 4966 *flags = BCM_COSQ_GPORT_VLAN_UCAST_QUEUE_GROUP; 4967 } else if (node->type == _BCM_TD2_NODE_VM_UCAST) { 4968 *flags = BCM_COSQ_GPORT_VIRTUAL_PORT; 4969 } else if (node->type == _BCM_TD2_NODE_VOQ) { 4970 *flags = BCM_COSQ_GPORT_DESTMOD_UCAST_QUEUE_GROUP; 4971 } else { 4972 *flags = BCM_COSQ_GPORT_UCAST_QUEUE_GROUP; 4973 } 4974 } else if (BCM_GPORT_IS_SCHEDULER(gport)) { 4975 *flags = BCM_COSQ_GPORT_SCHEDULER; 4976 if (node->node_align_value == _BCM_TD2_START_INDEX_ALIGN_PFC) { 4977 *flags |= BCM_COSQ_GPORT_SCHEDULER_PFC_ALIGN; 4978 } 4979 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 4980 *flags = BCM_COSQ_GPORT_MCAST_QUEUE_GROUP; 4981 } else { 4982 *flags = 0; 4983 } 4984 4985 LOG_INFO(BSL_LS_BCM_COSQ, 4986 (BSL_META_U(unit, 4987 " port=0x%x numq=%d flags=0x%x\n"), 4988 *port, *numq, *flags)); 4989 4990 return BCM_E_NONE; 4991 } 4992 4993 /* 4994 * Function: 4995 * bcm_td2_cosq_gport_traverse 4996 * Purpose: 4997 * Walks through the valid COSQ GPORTs and calls 4998 * the user supplied callback function for each entry. 4999 * Parameters: 5000 * unit - (IN) unit number 5001 * trav_fn - (IN) Callback function. 5002 * user_data - (IN) User data to be passed to callback function 5003 * Returns: 5004 * BCM_E_NONE - Success. 5005 * BCM_E_XXX 5006 */ 5007 int 5008 bcm_td2_cosq_gport_traverse(int unit, bcm_cosq_gport_traverse_cb cb, 5009 void *user_data) 5010 { 5011 _bcm_td2_cosq_node_t *port_info; 5012 _bcm_td2_mmu_info_t *mmu_info; 5013 bcm_module_t my_modid, modid_out; 5014 bcm_port_t port, port_out; 5015 5016 if (_bcm_td2_mmu_info[unit] == NULL) { 5017 return BCM_E_INIT; 5018 } 5019 mmu_info = _bcm_td2_mmu_info[unit]; 5020 5021 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_modid)); 5022 PBMP_ALL_ITER(unit, port) { 5023 BCM_IF_ERROR_RETURN 5024 (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, 5025 my_modid, port, &modid_out, &port_out)); 5026 5027 /* root node */ 5028 port_info = &mmu_info->sched_node[port_out]; 5029 5030 if (port_info->gport >= 0) { 5031 _bcm_td2_cosq_gport_traverse(unit, port_info->gport, cb, user_data); 5032 } 5033 } 5034 5035 return BCM_E_NONE; 5036 } 5037 5038 /* 5039 * Function: 5040 * bcm_td2_cosq_gport_attach 5041 * Purpose: 5042 * Attach sched_port to the specified index (cosq) of input_port 5043 * Parameters: 5044 * unit - (IN) unit number 5045 * sched_port - (IN) scheduler GPORT identifier 5046 * input_port - (IN) GPORT to attach to 5047 * cosq - (IN) COS queue to attach to (-1 for first available cosq) 5048 * Returns: 5049 * BCM_E_XXX 5050 */ 5051 int 5052 bcm_td2_cosq_gport_attach(int unit, bcm_gport_t gport, 5053 bcm_gport_t to_gport, 5054 bcm_cos_queue_t to_cosq) 5055 { 5056 _bcm_td2_mmu_info_t *mmu_info; 5057 _bcm_td2_cosq_node_t *node, *to_node; 5058 bcm_port_t port, to_port, local_port, mmu_port; 5059 int rv, tmp; 5060 5061 if ((mmu_info = _bcm_td2_mmu_info[unit]) == NULL) { 5062 return BCM_E_INIT; 5063 } 5064 5065 if ((BCM_GPORT_IS_UCAST_QUEUE_GROUP(to_gport)) || 5066 (BCM_GPORT_IS_MCAST_QUEUE_GROUP(to_gport)) || 5067 (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(to_gport))) { 5068 return BCM_E_PARAM; 5069 } 5070 5071 if(!(BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 5072 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) || 5073 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport) || 5074 BCM_GPORT_IS_SCHEDULER(gport))) { 5075 return BCM_E_PORT; 5076 } 5077 5078 BCM_IF_ERROR_RETURN 5079 (_bcm_td2_cosq_node_get(unit, gport, 0, NULL, &port, NULL, &node)); 5080 5081 if (node->attached_to_input >= 0) { 5082 /* Has already attached */ 5083 return BCM_E_EXISTS; 5084 } 5085 tmp = node->attached_to_input; 5086 5087 if (BCM_GPORT_IS_SCHEDULER(to_gport)) { 5088 5089 BCM_IF_ERROR_RETURN 5090 (_bcm_td2_cosq_node_get(unit, to_gport, 0, NULL, &to_port, NULL, 5091 &to_node)); 5092 5093 } else { 5094 5095 BCM_IF_ERROR_RETURN 5096 (_bcm_td2_cosq_localport_resolve(unit, to_gport, &to_port)); 5097 5098 to_node = &mmu_info->sched_node[to_port]; 5099 } 5100 5101 if (port != to_port) { 5102 return BCM_E_PORT; 5103 } 5104 5105 mmu_port = SOC_TD2_MMU_PORT(unit, port); 5106 5107 /* Identify the levels of schedulers 5108 * to_port == phy_port && gport == scheduler => gport = L0 5109 * to_port == schduler && gport == scheduler => to_port = L0 and port = L1 5110 * to_port == scheduler && port == queue_group => to_port = L1 and port = L2 5111 */ 5112 if (to_node != NULL) { 5113 if (((to_node->level == SOC_TD2_NODE_LVL_ROOT) && (to_cosq >= 265)) || 5114 ((to_node->level == SOC_TD2_NODE_LVL_L0) && (to_cosq >= 1024)) || 5115 ((to_node->level == SOC_TD2_NODE_LVL_L1) && (to_cosq >= 1480))) { 5116 return BCM_E_RESOURCE; 5117 } 5118 5119 if (!BCM_GPORT_IS_SCHEDULER(to_gport)) { 5120 if ((to_node->numq == 0) || (to_node->numq_expandable)) { 5121 local_port = (BCM_GPORT_IS_LOCAL(to_gport)) ? 5122 BCM_GPORT_LOCAL_GET(to_gport) : 5123 BCM_GPORT_MODPORT_PORT_GET(to_gport); 5124 5125 if (!SOC_PORT_VALID(unit, local_port)) { 5126 return BCM_E_PORT; 5127 } 5128 to_node->in_use = TRUE; 5129 to_node->local_port = port; 5130 if (IS_TD2_HSP_PORT(unit, local_port)) { 5131 to_node->base_index = _BCM_TD2_HSP_L0_INDEX(unit, mmu_port, 0); 5132 to_node->numq = _BCM_TD2_HSP_PORT_MAX_L0; 5133 } else { 5134 to_node->gport = to_gport; 5135 to_node->hw_index = _BCM_TD2_ROOT_SCHED_INDEX(unit, mmu_port); 5136 to_node->level = SOC_TD2_NODE_LVL_ROOT; 5137 to_node->attached_to_input = 0; 5138 to_node->numq_expandable = 1; 5139 if (to_cosq == -1) { 5140 to_node->numq += 1; 5141 } else { 5142 if (to_cosq >= to_node->numq) { 5143 to_node->numq = to_cosq + 1; 5144 } 5145 } 5146 } 5147 } 5148 5149 if (!BCM_GPORT_IS_SCHEDULER(gport)) { 5150 5151 return BCM_E_PARAM; 5152 } 5153 5154 node->level = SOC_TD2_NODE_LVL_L0; 5155 } else { 5156 if (to_node->level == SOC_TD2_NODE_LVL_ROOT) { 5157 node->level = SOC_TD2_NODE_LVL_L0; 5158 } 5159 5160 if ((to_node->level == -1)) { 5161 to_node->level = (BCM_GPORT_IS_SCHEDULER(gport)) ? 5162 SOC_TD2_NODE_LVL_L0 : SOC_TD2_NODE_LVL_L1; 5163 } 5164 5165 if (node->level == -1) { 5166 node->level = 5167 (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 5168 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) || 5169 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport)) ? 5170 SOC_TD2_NODE_LVL_L2 : SOC_TD2_NODE_LVL_L1; 5171 } 5172 } 5173 } else { 5174 return BCM_E_NOT_FOUND; 5175 } 5176 5177 if ((to_cosq < -1) || ((to_node->numq != -1) && (to_cosq >= to_node->numq))) { 5178 5179 return BCM_E_PARAM; 5180 } 5181 5182 if (BCM_GPORT_IS_SCHEDULER(to_gport) || BCM_GPORT_IS_LOCAL(to_gport) || 5183 BCM_GPORT_IS_MODPORT(to_gport)) { 5184 int start = 0, end = 0; 5185 if (to_node->attached_to_input < 0) { 5186 /* dont allow to attach to a node that has already attached */ 5187 5188 return BCM_E_PARAM; 5189 } 5190 5191 if (node->type == _BCM_TD2_NODE_SERVICE_UCAST) { 5192 end = node->numq; 5193 } else { 5194 end = 1; 5195 } 5196 5197 for (start = 0; start < end; start++) { 5198 node->parent = to_node; 5199 node->sibling = to_node->child; 5200 to_node->child = node; 5201 /* resolve the nodes */ 5202 rv = _bcm_td2_cosq_node_resolve(unit, node, to_cosq + start); 5203 if (BCM_FAILURE(rv)) { 5204 to_node->child = node->sibling; 5205 node->parent = NULL; 5206 node->attached_to_input = tmp; 5207 return rv; 5208 } 5209 LOG_INFO(BSL_LS_BCM_COSQ, 5210 (BSL_META_U(unit, 5211 " hw_cosq=%d\n"), 5212 node->attached_to_input)); 5213 5214 if ((node->type == _BCM_TD2_NODE_SERVICE_UCAST) && 5215 ((start + 1) < end)){ 5216 5217 BCM_IF_ERROR_RETURN 5218 (_bcm_td2_cosq_node_get(unit, gport, start + 1, NULL, 5219 &port, NULL, &node)); 5220 5221 if (!node) { 5222 return BCM_E_NOT_FOUND; 5223 } 5224 } 5225 } 5226 5227 } else { 5228 return BCM_E_PORT; 5229 } 5230 5231 return BCM_E_NONE; 5232 } 5233 5234 /* 5235 * Function: 5236 * bcm_td2_cosq_gport_attach_get 5237 * Purpose: 5238 * Get attached status of a scheduler port 5239 * Parameters: 5240 * unit - (IN) unit number 5241 * sched_port - (IN) scheduler GPORT identifier 5242 * input_port - (OUT) GPORT to attach to 5243 * cosq - (OUT) COS queue to attached to 5244 * Returns: 5245 * BCM_E_XXX 5246 * Notes: 5247 */ 5248 int 5249 bcm_td2_cosq_gport_attach_get(int unit, bcm_gport_t sched_gport, 5250 bcm_gport_t *input_gport, bcm_cos_queue_t *cosq) 5251 { 5252 _bcm_td2_cosq_node_t *sched_node; 5253 bcm_module_t modid, modid_out; 5254 bcm_port_t port, port_out; 5255 5256 if (input_gport == NULL || cosq == NULL) { 5257 return BCM_E_PARAM; 5258 } 5259 5260 BCM_IF_ERROR_RETURN 5261 (_bcm_td2_cosq_node_get(unit, sched_gport, 0, &modid, &port, NULL, 5262 &sched_node)); 5263 5264 if (sched_node->attached_to_input < 0) { 5265 /* Not attached yet */ 5266 return BCM_E_NOT_FOUND; 5267 } 5268 5269 if (sched_node->parent != NULL) { /* sched_node is not an S1 scheduler */ 5270 *input_gport = sched_node->parent->gport; 5271 } else { /* sched_node is an S1 scheduler */ 5272 BCM_IF_ERROR_RETURN 5273 (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, modid, port, 5274 &modid_out, &port_out)); 5275 BCM_GPORT_MODPORT_SET(*input_gport, modid_out, port_out); 5276 } 5277 *cosq = sched_node->attached_to_input; 5278 5279 return BCM_E_NONE; 5280 } 5281 5282 /* 5283 * Function: 5284 * bcm_td2_cosq_gport_child_get 5285 * Purpose: 5286 * Get the child node GPORT atatched to N-th index (cosq) 5287 * of the scheduler GPORT. 5288 * Parameters: 5289 * unit - (IN) Unit number. 5290 * in_gport - (IN) Scheduler GPORT ID. 5291 * cosq - (IN) COS queue attached to. 5292 * out_gport - (OUT) child GPORT ID. 5293 * Returns: 5294 * BCM_E_XXX 5295 * Notes: 5296 */ 5297 int 5298 bcm_td2_cosq_gport_child_get(int unit, bcm_gport_t in_gport, 5299 bcm_cos_queue_t cosq, 5300 bcm_gport_t *out_gport) 5301 { 5302 _bcm_td2_cosq_node_t *in_node = NULL; 5303 _bcm_td2_cosq_node_t *cur_node = NULL; 5304 _bcm_td2_cosq_node_t *tmp_node = NULL; 5305 bcm_module_t modid; 5306 bcm_port_t port; 5307 5308 if (out_gport == NULL) { 5309 return BCM_E_PARAM; 5310 } 5311 5312 /* get the child of the input gport node 5313 * at an index of cosq 5314 */ 5315 5316 if ((cosq < 0) || ( cosq >= 64)) { 5317 return BCM_E_PARAM; 5318 } 5319 5320 BCM_IF_ERROR_RETURN 5321 (_bcm_td2_cosq_node_get(unit, in_gport, 0, &modid, &port, NULL, 5322 &in_node)); 5323 if ((in_node->child == NULL) && (in_node->level == SOC_TD2_NODE_LVL_L2)) { 5324 return BCM_E_PARAM; 5325 } 5326 5327 for (cur_node = in_node->child; cur_node != NULL; 5328 cur_node = cur_node->sibling) { 5329 if (cur_node->attached_to_input == cosq) { 5330 tmp_node = cur_node; 5331 break; 5332 } 5333 } 5334 if (tmp_node == NULL) { 5335 return BCM_E_NOT_FOUND; 5336 } 5337 *out_gport = tmp_node->gport; 5338 5339 return BCM_E_NONE; 5340 } 5341 5342 /* 5343 * Convert HW drop probability to percent value 5344 */ 5345 STATIC int 5346 _bcm_td2_hw_drop_prob_to_percent[] = { 5347 0, /* 0 */ 5348 1, /* 1 */ 5349 2, /* 2 */ 5350 3, /* 3 */ 5351 4, /* 4 */ 5352 5, /* 5 */ 5353 6, /* 6 */ 5354 7, /* 7 */ 5355 8, /* 8 */ 5356 9, /* 9 */ 5357 10, /* 10 */ 5358 25, /* 11 */ 5359 50, /* 12 */ 5360 75, /* 13 */ 5361 100, /* 14 */ 5362 -1 /* 15 */ 5363 }; 5364 5365 STATIC int 5366 _bcm_td2_percent_to_drop_prob(int percent) 5367 { 5368 int i; 5369 5370 for (i = 14; i > 0 ; i--) { 5371 if (percent >= _bcm_td2_hw_drop_prob_to_percent[i]) { 5372 break; 5373 } 5374 } 5375 return i; 5376 } 5377 5378 STATIC int 5379 _bcm_td2_drop_prob_to_percent(int drop_prob) { 5380 return (_bcm_td2_hw_drop_prob_to_percent[drop_prob]); 5381 } 5382 5383 /* 5384 * index: degree, value: contangent(degree) * 100 5385 * max value is 0xffff (16-bit) at 0 degree 5386 */ 5387 STATIC int 5388 _bcm_td2_cotangent_lookup_table[] = 5389 { 5390 /* 0.. 5 */ 65535, 5728, 2863, 1908, 1430, 1143, 5391 /* 6..11 */ 951, 814, 711, 631, 567, 514, 5392 /* 12..17 */ 470, 433, 401, 373, 348, 327, 5393 /* 18..23 */ 307, 290, 274, 260, 247, 235, 5394 /* 24..29 */ 224, 214, 205, 196, 188, 180, 5395 /* 30..35 */ 173, 166, 160, 153, 148, 142, 5396 /* 36..41 */ 137, 132, 127, 123, 119, 115, 5397 /* 42..47 */ 111, 107, 103, 100, 96, 93, 5398 /* 48..53 */ 90, 86, 83, 80, 78, 75, 5399 /* 54..59 */ 72, 70, 67, 64, 62, 60, 5400 /* 60..65 */ 57, 55, 53, 50, 48, 46, 5401 /* 66..71 */ 44, 42, 40, 38, 36, 34, 5402 /* 72..77 */ 32, 30, 28, 26, 24, 23, 5403 /* 78..83 */ 21, 19, 17, 15, 14, 12, 5404 /* 84..89 */ 10, 8, 6, 5, 3, 1, 5405 /* 90 */ 0 5406 }; 5407 5408 /* 5409 * Given a slope (angle in degrees) from 0 to 90, return the number of cells 5410 * in the range from 0% drop probability to 100% drop probability. 5411 */ 5412 STATIC int 5413 _bcm_td2_angle_to_cells(int angle) 5414 { 5415 return (_bcm_td2_cotangent_lookup_table[angle]); 5416 } 5417 5418 /* 5419 * Given a number of packets in the range from 0% drop probability 5420 * to 100% drop probability, return the slope (angle in degrees). 5421 */ 5422 STATIC int 5423 _bcm_td2_cells_to_angle(int packets) 5424 { 5425 int angle; 5426 5427 for (angle = 90; angle >= 0 ; angle--) { 5428 if (packets <= _bcm_td2_cotangent_lookup_table[angle]) { 5429 break; 5430 } 5431 } 5432 return angle; 5433 } 5434 5435 /* 5436 * Function: 5437 * _bcm_td2_cosq_bucket_set 5438 * Purpose: 5439 * Configure COS queue bandwidth control bucket 5440 * Parameters: 5441 * unit - (IN) unit number 5442 * port - (IN) port number or GPORT identifier 5443 * cosq - (IN) COS queue number 5444 * min_quantum - (IN) kbps or packet/second 5445 * max_quantum - (IN) kbps or packet/second 5446 * burst_quantum - (IN) kbps or packet/second 5447 * flags - (IN) 5448 * Returns: 5449 * BCM_E_XXX 5450 * Notes: 5451 * If port is any form of local port, cosq is the hardware queue index. 5452 */ 5453 STATIC int 5454 _bcm_td2_cosq_bucket_set(int unit, bcm_gport_t port, bcm_cos_queue_t cosq, 5455 uint32 min_quantum, uint32 max_quantum, 5456 uint32 kbits_burst_min, uint32 kbits_burst_max, 5457 uint32 flags) 5458 { 5459 _bcm_td2_cosq_node_t *node = NULL; 5460 int rv = BCM_E_NONE; 5461 bcm_port_t local_port; 5462 int index; 5463 uint32 rval; 5464 uint32 meter_flags; 5465 uint32 bucketsize_max, bucketsize_min; 5466 uint32 granularity_max, granularity_min; 5467 uint32 refresh_rate_max, refresh_rate_min; 5468 int refresh_bitsize = 0, bucket_bitsize = 0; 5469 soc_mem_t config_mem = INVALIDm; 5470 uint32 entry[SOC_MAX_MEM_WORDS]; 5471 5472 /* caller should resolve the cosq. */ 5473 if (cosq < 0) { 5474 if (cosq == -1) { 5475 /* caller needs to resolve the wild card value (-1) */ 5476 return BCM_E_INTERNAL; 5477 } else { /* reject all other negative value */ 5478 return BCM_E_PARAM; 5479 } 5480 } 5481 5482 BCM_IF_ERROR_RETURN 5483 (_bcm_td2_cosq_index_resolve(unit, port, cosq, 5484 _BCM_TD2_COSQ_INDEX_STYLE_BUCKET, 5485 &local_port, &index, NULL)); 5486 5487 if (BCM_GPORT_IS_SET(port) && 5488 ((BCM_GPORT_IS_SCHEDULER(port)) || 5489 BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 5490 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) || 5491 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port))) { 5492 5493 BCM_IF_ERROR_RETURN 5494 (_bcm_td2_cosq_node_get(unit, port, cosq, NULL, 5495 NULL, NULL, &node)); 5496 } 5497 5498 if (node) { 5499 if (BCM_GPORT_IS_SCHEDULER(port)) { 5500 if (node->level == SOC_TD2_NODE_LVL_ROOT) { 5501 config_mem = SOC_TD2_PMEM(unit, local_port, 5502 MMU_MTRO_L0_MEM_0m, MMU_MTRO_L0_MEM_1m); 5503 } else if (node->level == SOC_TD2_NODE_LVL_L0) { 5504 uint32 mc_group_mode = 0; 5505 if (IS_TD2_HSP_PORT(unit, local_port)) { 5506 SOC_IF_ERROR_RETURN( 5507 READ_HSP_SCHED_PORT_CONFIGr(unit, 5508 local_port, &rval)); 5509 mc_group_mode = soc_reg_field_get(unit, 5510 HSP_SCHED_PORT_CONFIGr, 5511 rval, MC_GROUP_MODEf); 5512 } 5513 if (mc_group_mode) { 5514 config_mem = SOC_TD2_PMEM(unit, local_port, 5515 MMU_MTRO_L2_MEM_0m, 5516 MMU_MTRO_L2_MEM_1m); 5517 } else { 5518 config_mem = SOC_TD2_PMEM(unit, local_port, 5519 MMU_MTRO_L1_MEM_0m, 5520 MMU_MTRO_L1_MEM_1m); 5521 } 5522 } else if (node->level == SOC_TD2_NODE_LVL_L1) { 5523 config_mem = SOC_TD2_PMEM(unit, local_port, 5524 MMU_MTRO_L2_MEM_0m, MMU_MTRO_L2_MEM_1m); 5525 } else { 5526 return BCM_E_PARAM; 5527 } 5528 } else if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 5529 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 5530 config_mem = SOC_TD2_PMEM(unit, local_port, 5531 MMU_MTRO_L2_MEM_0m, MMU_MTRO_L2_MEM_1m); 5532 } else { 5533 return BCM_E_PARAM; 5534 } 5535 } else { 5536 if (IS_CPU_PORT(unit, local_port)) { 5537 config_mem = SOC_TD2_PMEM(unit, local_port, 5538 MMU_MTRO_L2_MEM_0m, MMU_MTRO_L2_MEM_1m); 5539 } else { 5540 config_mem = SOC_TD2_PMEM(unit, local_port, 5541 MMU_MTRO_L1_MEM_0m, MMU_MTRO_L1_MEM_1m); 5542 } 5543 } 5544 5545 5546 meter_flags = flags & BCM_COSQ_BW_PACKET_MODE ? 5547 _BCM_TD_METER_FLAG_PACKET_MODE : 0; 5548 BCM_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, &rval)); 5549 if (soc_reg_field_get(unit, MISCCONFIGr, rval, ITU_MODE_SELf)) { 5550 meter_flags |= _BCM_TD_METER_FLAG_NON_LINEAR; 5551 } 5552 5553 refresh_bitsize = soc_mem_field_length(unit, config_mem, MAX_REFRESHf); 5554 bucket_bitsize = soc_mem_field_length(unit, config_mem, MAX_THD_SELf); 5555 5556 BCM_IF_ERROR_RETURN 5557 (_bcm_td_rate_to_bucket_encoding(unit, max_quantum, kbits_burst_max, 5558 meter_flags, refresh_bitsize, 5559 bucket_bitsize, &refresh_rate_max, 5560 &bucketsize_max, &granularity_max)); 5561 5562 BCM_IF_ERROR_RETURN 5563 (_bcm_td_rate_to_bucket_encoding(unit, min_quantum, kbits_burst_min, 5564 meter_flags, refresh_bitsize, 5565 bucket_bitsize, &refresh_rate_min, 5566 &bucketsize_min, &granularity_min)); 5567 5568 sal_memset(entry, 0, sizeof(uint32)*SOC_MAX_MEM_WORDS); 5569 soc_mem_field32_set(unit, config_mem, &entry, MAX_METER_GRANf, granularity_max); 5570 soc_mem_field32_set(unit, config_mem, &entry, MAX_REFRESHf, refresh_rate_max); 5571 soc_mem_field32_set(unit, config_mem, &entry, MAX_THD_SELf, bucketsize_max); 5572 5573 soc_mem_field32_set(unit, config_mem, &entry, MIN_METER_GRANf, granularity_min); 5574 soc_mem_field32_set(unit, config_mem, &entry, MIN_REFRESHf, refresh_rate_min); 5575 soc_mem_field32_set(unit, config_mem, &entry, MIN_THD_SELf, bucketsize_min); 5576 5577 soc_mem_field32_set(unit, config_mem, &entry, SHAPER_CONTROLf, 5578 (flags & BCM_COSQ_BW_PACKET_MODE) ? 1 : 0); 5579 soc_mem_field32_set(unit, config_mem, &entry, EAV_ENABLEf, 5580 (flags & BCM_COSQ_BW_EAV_MODE) ? 1 : 0); 5581 5582 SOC_EGRESS_METERING_LOCK(unit); 5583 rv = soc_mem_write(unit, config_mem, MEM_BLOCK_ALL, index, &entry); 5584 SOC_EGRESS_METERING_UNLOCK(unit); 5585 5586 return rv; 5587 } 5588 5589 /* 5590 * Function: 5591 * _bcm_td2_cosq_bucket_get 5592 * Purpose: 5593 * Get COS queue bandwidth control bucket setting 5594 * Parameters: 5595 * unit - (IN) unit number 5596 * port - (IN) port number or GPORT identifier 5597 * cosq - (IN) COS queue number 5598 * min_quantum - (OUT) kbps or packet/second 5599 * max_quantum - (OUT) kbps or packet/second 5600 * burst_quantum - (OUT) kbps or packet/second 5601 * flags - (IN) 5602 * Returns: 5603 * BCM_E_XXX 5604 * Notes: 5605 * If port is any form of local port, cosq is the hardware queue index. 5606 */ 5607 STATIC int 5608 _bcm_td2_cosq_bucket_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 5609 uint32 *min_quantum, uint32 *max_quantum, 5610 uint32 *kbits_burst_min, uint32 *kbits_burst_max, 5611 uint32 *flags) 5612 { 5613 _bcm_td2_cosq_node_t *node = NULL; 5614 int rv = BCM_E_NONE; 5615 bcm_port_t local_port; 5616 int index; 5617 uint32 rval; 5618 uint32 refresh_rate, bucketsize, granularity, meter_flags; 5619 soc_mem_t config_mem = INVALIDm; 5620 uint32 entry[SOC_MAX_MEM_WORDS]; 5621 5622 if (cosq < 0) { 5623 if (cosq == -1) { 5624 /* caller needs to resolve the wild card value (-1) */ 5625 return BCM_E_INTERNAL; 5626 } else { /* reject all other negative value */ 5627 return BCM_E_PARAM; 5628 } 5629 } 5630 5631 BCM_IF_ERROR_RETURN 5632 (_bcm_td2_cosq_index_resolve(unit, port, cosq, 5633 _BCM_TD2_COSQ_INDEX_STYLE_BUCKET, 5634 &local_port, &index, NULL)); 5635 5636 if (BCM_GPORT_IS_SET(port) && 5637 ((BCM_GPORT_IS_SCHEDULER(port)) || 5638 BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 5639 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) || 5640 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port))) { 5641 5642 BCM_IF_ERROR_RETURN 5643 (_bcm_td2_cosq_node_get(unit, port, cosq, NULL, 5644 &local_port, NULL, &node)); 5645 } 5646 5647 if (node) { 5648 if (BCM_GPORT_IS_SCHEDULER(port)) { 5649 if (node->level == SOC_TD2_NODE_LVL_ROOT) { 5650 config_mem = SOC_TD2_PMEM(unit, local_port, 5651 MMU_MTRO_L0_MEM_0m, MMU_MTRO_L0_MEM_1m); 5652 } else if (node->level == SOC_TD2_NODE_LVL_L0) { 5653 uint32 mc_group_mode = 0; 5654 if (IS_TD2_HSP_PORT(unit, local_port)) { 5655 SOC_IF_ERROR_RETURN( 5656 READ_HSP_SCHED_PORT_CONFIGr(unit, 5657 local_port, &rval)); 5658 mc_group_mode = soc_reg_field_get(unit, 5659 HSP_SCHED_PORT_CONFIGr, 5660 rval, MC_GROUP_MODEf); 5661 } 5662 if (mc_group_mode) { 5663 config_mem = SOC_TD2_PMEM(unit, local_port, 5664 MMU_MTRO_L2_MEM_0m, 5665 MMU_MTRO_L2_MEM_1m); 5666 } else { 5667 config_mem = SOC_TD2_PMEM(unit, local_port, 5668 MMU_MTRO_L1_MEM_0m, 5669 MMU_MTRO_L1_MEM_1m); 5670 } 5671 } else if (node->level == SOC_TD2_NODE_LVL_L1) { 5672 config_mem = SOC_TD2_PMEM(unit, local_port, 5673 MMU_MTRO_L2_MEM_0m, MMU_MTRO_L2_MEM_1m); 5674 } else { 5675 return BCM_E_PARAM; 5676 } 5677 } else if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 5678 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 5679 config_mem = SOC_TD2_PMEM(unit, local_port, 5680 MMU_MTRO_L2_MEM_0m, MMU_MTRO_L2_MEM_1m); 5681 } else { 5682 return BCM_E_PARAM; 5683 } 5684 } else { 5685 if (IS_CPU_PORT(unit, local_port)) { 5686 config_mem = SOC_TD2_PMEM(unit, local_port, 5687 MMU_MTRO_L2_MEM_0m, MMU_MTRO_L2_MEM_1m); 5688 } else { 5689 config_mem = SOC_TD2_PMEM(unit, local_port, 5690 MMU_MTRO_L1_MEM_0m, MMU_MTRO_L1_MEM_1m); 5691 } 5692 } 5693 5694 if (min_quantum == NULL || max_quantum == NULL || 5695 kbits_burst_max == NULL || kbits_burst_min == NULL) { 5696 return BCM_E_PARAM; 5697 } 5698 5699 SOC_EGRESS_METERING_LOCK(unit); 5700 rv = soc_mem_read(unit, config_mem, MEM_BLOCK_ALL, index, &entry); 5701 SOC_EGRESS_METERING_UNLOCK(unit); 5702 if (rv != BCM_E_NONE) { 5703 return rv; 5704 } 5705 5706 meter_flags = 0; 5707 *flags = 0; 5708 BCM_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, &rval)); 5709 if (soc_reg_field_get(unit, MISCCONFIGr, rval, ITU_MODE_SELf)) { 5710 meter_flags |= _BCM_TD_METER_FLAG_NON_LINEAR; 5711 } 5712 if (soc_mem_field32_get(unit, config_mem, &entry, SHAPER_CONTROLf)) { 5713 meter_flags |= _BCM_TD_METER_FLAG_PACKET_MODE; 5714 *flags |= BCM_COSQ_BW_PACKET_MODE; 5715 } 5716 if (soc_mem_field32_get(unit, config_mem, &entry, EAV_ENABLEf)) { 5717 *flags |= BCM_COSQ_BW_EAV_MODE; 5718 } 5719 5720 granularity = soc_mem_field32_get(unit, config_mem, &entry, MAX_METER_GRANf); 5721 refresh_rate = soc_mem_field32_get(unit, config_mem, &entry, MAX_REFRESHf); 5722 bucketsize = soc_mem_field32_get(unit, config_mem, &entry, MAX_THD_SELf); 5723 BCM_IF_ERROR_RETURN 5724 (_bcm_td_bucket_encoding_to_rate(unit, refresh_rate, bucketsize, 5725 granularity, meter_flags, 5726 max_quantum, kbits_burst_max)); 5727 5728 granularity = soc_mem_field32_get(unit, config_mem, &entry, MIN_METER_GRANf); 5729 refresh_rate = soc_mem_field32_get(unit, config_mem, &entry, MIN_REFRESHf); 5730 bucketsize = soc_mem_field32_get(unit, config_mem, &entry, MIN_THD_SELf); 5731 BCM_IF_ERROR_RETURN 5732 (_bcm_td_bucket_encoding_to_rate(unit, refresh_rate, bucketsize, 5733 granularity, meter_flags, 5734 min_quantum, kbits_burst_min)); 5735 return BCM_E_NONE; 5736 } 5737 5738 5739 5740 STATIC int 5741 _bcm_td2_cosq_time_domain_get(int unit, int time_id, int *time_value) 5742 { 5743 uint32 rval; 5744 5745 if (time_id < 0 || time_id > _TD2_NUM_TIME_DOMAIN - 1) { 5746 return SOC_E_PARAM; 5747 } 5748 5749 if (time_value == NULL) { 5750 return SOC_E_PARAM; 5751 } 5752 5753 rval = 0; 5754 SOC_IF_ERROR_RETURN(READ_TIME_DOMAINr(unit, &rval)); 5755 *time_value = soc_reg_field_get(unit, TIME_DOMAINr, rval, 5756 time_domain[time_id].field); 5757 5758 return SOC_E_NONE; 5759 } 5760 5761 5762 5763 5764 STATIC int 5765 _bcm_td2_cosq_time_domain_set(int unit, int time_value, int *time_id) 5766 { 5767 uint32 rval; 5768 int rv = SOC_E_NONE; 5769 int id; 5770 5771 if (time_value < 0 || time_value > 63) { 5772 return SOC_E_PARAM; 5773 } 5774 5775 rval = 0; 5776 SOC_IF_ERROR_RETURN(READ_TIME_DOMAINr(unit, &rval)); 5777 for (id = 0; id < _TD2_NUM_TIME_DOMAIN; id++) {/* Find a unset field from TIME_0 to TIME_3 */ 5778 if (!time_domain[id].ref_count) { 5779 soc_reg_field_set(unit, TIME_DOMAINr, &rval, time_domain[id].field, 5780 time_value); 5781 time_domain[id].ref_count++; 5782 break; 5783 } 5784 } 5785 5786 if(id == _TD2_NUM_TIME_DOMAIN){/* No field in TIME_DOMAINr is free,return ERR*/ 5787 rv = BCM_E_RESOURCE; 5788 } 5789 5790 if(time_id){ 5791 *time_id = id; 5792 } 5793 5794 SOC_IF_ERROR_RETURN(WRITE_TIME_DOMAINr(unit, rval)); 5795 return rv; 5796 } 5797 5798 STATIC int 5799 _bcm_td2_cosq_wred_index_resolve(int unit, bcm_port_t port, 5800 bcm_cos_queue_t cosq, uint32 flags, uint32 lflags, 5801 bcm_port_t *local_port, int *index_start, int *index_end, 5802 int *port_id, int *pool_id) 5803 { 5804 int index; 5805 int to_index = -1; 5806 int start_pool_idx; 5807 soc_info_t *si; 5808 int phy_port, mmu_port = 0; 5809 int service_pool = 0; 5810 bcm_port_t local_p = -1; 5811 5812 if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 5813 return BCM_E_PARAM; 5814 } 5815 5816 if((lflags & BCM_COSQ_DISCARD_DEVICE) || (flags & BCM_COSQ_DISCARD_DEVICE)) { 5817 if ((port == -1) || (cosq == -1)) { 5818 index = 1840; 5819 to_index = index + 3; 5820 } else { 5821 BCM_IF_ERROR_RETURN 5822 (_bcm_td2_cosq_index_resolve(unit, port, cosq, 5823 _BCM_TD2_COSQ_INDEX_STYLE_WRED_POOL, 5824 NULL, &start_pool_idx, NULL)); 5825 index = to_index = 1840 + start_pool_idx; 5826 } 5827 } else { 5828 if((lflags & BCM_COSQ_DISCARD_PORT) || (flags & BCM_COSQ_DISCARD_PORT)) { 5829 if (port == -1) { 5830 return BCM_E_PARAM; 5831 } 5832 BCM_IF_ERROR_RETURN 5833 (_bcm_td2_cosq_index_resolve(unit, port, cosq, 5834 _BCM_TD2_COSQ_INDEX_STYLE_WRED_PORT, 5835 &local_p, &index, NULL)); 5836 if (cosq != -1) { 5837 BCM_IF_ERROR_RETURN 5838 (_bcm_td2_cosq_index_resolve(unit, port, cosq, 5839 _BCM_TD2_COSQ_INDEX_STYLE_WRED_POOL, 5840 NULL, &start_pool_idx, NULL)); 5841 index = to_index = index + start_pool_idx; 5842 } else { 5843 to_index = index + 3; 5844 } 5845 } else { 5846 BCM_IF_ERROR_RETURN 5847 (_bcm_td2_cosq_index_resolve(unit, port, cosq == -1 ? 0:cosq, 5848 _BCM_TD2_COSQ_INDEX_STYLE_WRED, 5849 &local_p, &index, NULL)); 5850 5851 si = &SOC_INFO(unit); 5852 phy_port = si->port_l2p_mapping[local_p]; 5853 mmu_port = si->port_p2m_mapping[phy_port]; 5854 mmu_port = (mmu_port >= 64) ? (mmu_port - 64) : (mmu_port); 5855 5856 BCM_IF_ERROR_RETURN 5857 (_bcm_td2_cosq_index_resolve(unit, port, cosq == -1 ? 0:cosq, 5858 _BCM_TD2_COSQ_INDEX_STYLE_WRED_POOL, 5859 NULL, &start_pool_idx, NULL)); 5860 service_pool = start_pool_idx; 5861 5862 if (cosq == -1) { 5863 to_index = index + NUM_COS(unit) - 1; 5864 } else { 5865 to_index = index; 5866 } 5867 } 5868 } 5869 5870 if (index < 0) { 5871 return BCM_E_PARAM; 5872 } 5873 5874 if (local_port != NULL) { 5875 *local_port = local_p; 5876 } 5877 if (index_start != NULL) { 5878 *index_start = index; 5879 } 5880 if (index_end != NULL) { 5881 *index_end = to_index; 5882 } 5883 if (port_id != NULL) { 5884 *port_id = mmu_port; 5885 } 5886 if (pool_id != NULL) { 5887 *pool_id = service_pool; 5888 } 5889 5890 return BCM_E_NONE; 5891 } 5892 5893 /* 5894 * Function: 5895 * _bcm_td2_cosq_wred_set 5896 * Purpose: 5897 * Configure unicast queue WRED setting 5898 * Parameters: 5899 * unit - (IN) unit number 5900 * port - (IN) port number or GPORT identifier 5901 * cosq - (IN) COS queue number 5902 * flags - (IN) BCM_COSQ_DISCARD_XXX 5903 * min_thresh - (IN) 5904 * max_thresh - (IN) 5905 * drop_probablity - (IN) 5906 * gain - (IN) 5907 * ignore_enable_flags - (IN) 5908 * Returns: 5909 * BCM_E_XXX 5910 * Notes: 5911 * If port is any form of local port, cosq is the hardware queue index. 5912 */ 5913 STATIC int 5914 _bcm_td2_cosq_wred_set(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 5915 uint32 flags, uint32 min_thresh, uint32 max_thresh, 5916 int drop_probability, int gain, int ignore_enable_flags, 5917 uint32 lflags,int refresh_time) 5918 { 5919 soc_mem_t wred_mem; 5920 bcm_port_t local_port = -1; 5921 int index; 5922 uint32 profile_index, old_profile_index; 5923 mmu_wred_drop_curve_profile_0_entry_t entry_tcp_green; 5924 mmu_wred_drop_curve_profile_1_entry_t entry_tcp_yellow; 5925 mmu_wred_drop_curve_profile_2_entry_t entry_tcp_red; 5926 mmu_wred_drop_curve_profile_3_entry_t entry_nontcp_green; 5927 mmu_wred_drop_curve_profile_4_entry_t entry_nontcp_yellow; 5928 mmu_wred_drop_curve_profile_5_entry_t entry_nontcp_red; 5929 mmu_wred_config_entry_t qentry; 5930 void *entries[6]; 5931 soc_mem_t mems[6]; 5932 int rate, i, pipe, fpipe, tpipe, jj, to_index = -1, exists = 0; 5933 int time_id,time,old_time,current_time_sel; 5934 int port_id = 0; 5935 int pool_id = 0; 5936 int rv = SOC_E_NONE; 5937 static soc_mem_t wred_mems[2][6] = { 5938 { 5939 MMU_WRED_DROP_CURVE_PROFILE_0_X_PIPEm, 5940 MMU_WRED_DROP_CURVE_PROFILE_1_X_PIPEm, 5941 MMU_WRED_DROP_CURVE_PROFILE_2_X_PIPEm, 5942 MMU_WRED_DROP_CURVE_PROFILE_3_X_PIPEm, 5943 MMU_WRED_DROP_CURVE_PROFILE_4_X_PIPEm, 5944 MMU_WRED_DROP_CURVE_PROFILE_5_X_PIPEm 5945 }, 5946 { 5947 MMU_WRED_DROP_CURVE_PROFILE_0_Y_PIPEm, 5948 MMU_WRED_DROP_CURVE_PROFILE_1_Y_PIPEm, 5949 MMU_WRED_DROP_CURVE_PROFILE_2_Y_PIPEm, 5950 MMU_WRED_DROP_CURVE_PROFILE_3_Y_PIPEm, 5951 MMU_WRED_DROP_CURVE_PROFILE_4_Y_PIPEm, 5952 MMU_WRED_DROP_CURVE_PROFILE_5_Y_PIPEm 5953 } 5954 }; 5955 5956 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_wred_index_resolve(unit, port, cosq, 5957 flags, lflags, &local_port, &index, &to_index, 5958 &port_id, &pool_id)); 5959 5960 if (local_port >= 0) { 5961 fpipe = tpipe = _BCM_TD2_PORT_TO_PIPE(unit, local_port); 5962 } else { 5963 fpipe = _TD2_XPIPE; 5964 tpipe = _TD2_YPIPE; 5965 } 5966 5967 /* WRED doesn't work on CPU/LB Ports */ 5968 if (IS_LB_PORT(unit, local_port) || IS_CPU_PORT(unit, local_port)) { 5969 return BCM_E_PORT; 5970 } 5971 5972 for (pipe = fpipe; pipe <= tpipe; pipe++) { 5973 for(jj = index; jj <= to_index; jj++) { 5974 wred_mem = (pipe == _TD2_XPIPE) ? 5975 MMU_WRED_CONFIG_X_PIPEm : MMU_WRED_CONFIG_Y_PIPEm; 5976 5977 BCM_IF_ERROR_RETURN 5978 (soc_mem_read(unit, wred_mem, MEM_BLOCK_ALL, jj, &qentry)); 5979 5980 old_profile_index = 0xffffffff; 5981 if (flags & (BCM_COSQ_DISCARD_NONTCP | BCM_COSQ_DISCARD_COLOR_ALL | 5982 BCM_COSQ_DISCARD_TCP)) { 5983 old_profile_index = soc_mem_field32_get(unit, wred_mem, 5984 &qentry, PROFILE_INDEXf); 5985 entries[0] = &entry_tcp_green; 5986 entries[1] = &entry_tcp_yellow; 5987 entries[2] = &entry_tcp_red; 5988 entries[3] = &entry_nontcp_green; 5989 entries[4] = &entry_nontcp_yellow; 5990 entries[5] = &entry_nontcp_red; 5991 BCM_IF_ERROR_RETURN 5992 (soc_profile_mem_get(unit, _bcm_td2_wred_profile[pipe][unit], 5993 old_profile_index, 1, entries)); 5994 5995 for (i = 0; i < 6; i++) { 5996 mems[i] = INVALIDm; 5997 } 5998 if (!(flags & (BCM_COSQ_DISCARD_COLOR_GREEN | 5999 BCM_COSQ_DISCARD_COLOR_YELLOW | 6000 BCM_COSQ_DISCARD_COLOR_RED))) { 6001 flags |= BCM_COSQ_DISCARD_COLOR_ALL; 6002 } 6003 if (!(flags & BCM_COSQ_DISCARD_NONTCP) || (flags & BCM_COSQ_DISCARD_TCP)) { 6004 if (flags & BCM_COSQ_DISCARD_COLOR_GREEN) { 6005 mems[0] = (pipe == _TD2_XPIPE) ? 6006 MMU_WRED_DROP_CURVE_PROFILE_0_X_PIPEm : 6007 MMU_WRED_DROP_CURVE_PROFILE_0_Y_PIPEm; 6008 } 6009 if (flags & BCM_COSQ_DISCARD_COLOR_YELLOW) { 6010 mems[1] = (pipe == _TD2_XPIPE) ? 6011 MMU_WRED_DROP_CURVE_PROFILE_1_X_PIPEm : 6012 MMU_WRED_DROP_CURVE_PROFILE_1_Y_PIPEm; 6013 } 6014 if (flags & BCM_COSQ_DISCARD_COLOR_RED) { 6015 mems[2] = (pipe == _TD2_XPIPE) ? 6016 MMU_WRED_DROP_CURVE_PROFILE_2_X_PIPEm : 6017 MMU_WRED_DROP_CURVE_PROFILE_2_Y_PIPEm; 6018 } 6019 } 6020 if (flags & BCM_COSQ_DISCARD_NONTCP) { 6021 if (flags & BCM_COSQ_DISCARD_COLOR_GREEN) { 6022 mems[3] = (pipe == _TD2_XPIPE) ? 6023 MMU_WRED_DROP_CURVE_PROFILE_3_X_PIPEm : 6024 MMU_WRED_DROP_CURVE_PROFILE_3_Y_PIPEm; 6025 } 6026 if (flags & BCM_COSQ_DISCARD_COLOR_YELLOW) { 6027 mems[4] = (pipe == _TD2_XPIPE) ? 6028 MMU_WRED_DROP_CURVE_PROFILE_4_X_PIPEm : 6029 MMU_WRED_DROP_CURVE_PROFILE_4_Y_PIPEm; 6030 } 6031 if (flags & BCM_COSQ_DISCARD_COLOR_RED) { 6032 mems[5] = (pipe == _TD2_XPIPE) ? 6033 MMU_WRED_DROP_CURVE_PROFILE_5_X_PIPEm : 6034 MMU_WRED_DROP_CURVE_PROFILE_5_Y_PIPEm; 6035 } 6036 } 6037 rate = _bcm_td2_percent_to_drop_prob(drop_probability); 6038 for (i = 0; i < 6; i++) { 6039 exists = 0; 6040 if ((soc_mem_field32_get(unit, wred_mems[pipe][i], entries[i], 6041 MIN_THDf) != 0x1ffff) && (mems[i] == INVALIDm)) { 6042 mems[i] = wred_mems[pipe][i]; 6043 exists = 1; 6044 } else { 6045 soc_mem_field32_set(unit, wred_mems[pipe][i], entries[i], 6046 MIN_THDf, (mems[i] == INVALIDm) ? 0x1ffff : min_thresh); 6047 } 6048 6049 if ((soc_mem_field32_get(unit, wred_mems[pipe][i], entries[i], 6050 MAX_THDf) != 0x1ffff) && ((mems[i] == INVALIDm) || exists)) { 6051 mems[i] = wred_mems[pipe][i]; 6052 exists = 1; 6053 } else { 6054 soc_mem_field32_set(unit, wred_mems[pipe][i], entries[i], 6055 MAX_THDf, (mems[i] == INVALIDm) ? 0x1ffff :max_thresh); 6056 } 6057 6058 if (!exists) { 6059 soc_mem_field32_set(unit, wred_mems[pipe][i], entries[i], 6060 MAX_DROP_RATEf, (mems[i] == INVALIDm) ? 0 : rate); 6061 } 6062 } 6063 6064 BCM_IF_ERROR_RETURN 6065 (soc_profile_mem_add(unit, _bcm_td2_wred_profile[pipe][unit], 6066 entries, 1, &profile_index)); 6067 soc_mem_field32_set(unit, wred_mem, &qentry, PROFILE_INDEXf, profile_index); 6068 soc_mem_field32_set(unit, wred_mem, &qentry, WEIGHTf, gain); 6069 } 6070 6071 /* Some APIs only modify profiles */ 6072 if (!ignore_enable_flags) { 6073 soc_mem_field32_set(unit, wred_mem, &qentry, CAP_AVERAGEf, 6074 flags & BCM_COSQ_DISCARD_CAP_AVERAGE ? 1 : 0); 6075 soc_mem_field32_set(unit, wred_mem, &qentry, WRED_ENf, 6076 flags & BCM_COSQ_DISCARD_ENABLE ? 1 : 0); 6077 soc_mem_field32_set(unit, wred_mem, &qentry, ECN_MARKING_ENf, 6078 flags & BCM_COSQ_DISCARD_MARK_CONGESTION ? 1 : 0); 6079 soc_mem_field32_set(unit, wred_mem, &qentry, PORTIDf, 6080 port_id ? port_id : 0); 6081 soc_mem_field32_set(unit, wred_mem, &qentry, SPIDf, 6082 pool_id ? pool_id : 0); 6083 } 6084 6085 current_time_sel = soc_mem_field32_get(unit, wred_mem, &qentry, TIME_DOMAIN_SELf); 6086 time = (refresh_time + 7) / 8 - 1; /* Round it up to avoid negative value */ 6087 exists = 0; 6088 /* If the time value exist, update reference count only */ 6089 for (time_id = 0; time_id < _TD2_NUM_TIME_DOMAIN; time_id++) { 6090 BCM_IF_ERROR_RETURN 6091 (_bcm_td2_cosq_time_domain_get(unit, time_id, &old_time)); 6092 if (time == old_time) { 6093 /* Only set exist flag if this entry reference count already update, 6094 otherwise update reference count */ 6095 if(time_id != current_time_sel){ 6096 soc_mem_field32_set(unit, wred_mem, &qentry, TIME_DOMAIN_SELf, 6097 time_id); 6098 time_domain[time_id].ref_count++; 6099 time_domain[current_time_sel].ref_count--; 6100 } 6101 exists = 1; 6102 break; 6103 } 6104 } 6105 6106 if(!exists){ 6107 rv = _bcm_td2_cosq_time_domain_set(unit, time, &time_id); 6108 if(rv == SOC_E_NONE){ 6109 soc_mem_field32_set(unit, wred_mem, &qentry, TIME_DOMAIN_SELf, 6110 time_id); 6111 time_domain[current_time_sel].ref_count--; 6112 } else { 6113 return rv; 6114 } 6115 } 6116 6117 BCM_IF_ERROR_RETURN( 6118 soc_mem_write(unit, wred_mem, MEM_BLOCK_ALL, jj, &qentry)); 6119 6120 if (old_profile_index != 0xffffffff) { 6121 SOC_IF_ERROR_RETURN 6122 (soc_profile_mem_delete(unit, _bcm_td2_wred_profile[pipe][unit], 6123 old_profile_index)); 6124 } 6125 } 6126 } 6127 6128 return rv; 6129 } 6130 6131 /* 6132 * Function: 6133 * _bcm_td2_cosq_wred_get 6134 * Purpose: 6135 * Get unicast queue WRED setting 6136 * Parameters: 6137 * unit - (IN) unit number 6138 * port - (IN) port number or GPORT identifier 6139 * cosq - (IN) COS queue number 6140 * flags - (IN/OUT) BCM_COSQ_DISCARD_XXX 6141 * min_thresh - (OUT) 6142 * max_thresh - (OUT) 6143 * drop_probablity - (OUT) 6144 * gain - (OUT) 6145 * Returns: 6146 * BCM_E_XXX 6147 * Notes: 6148 * If port is any form of local port, cosq is the hardware queue index. 6149 */ 6150 STATIC int 6151 _bcm_td2_cosq_wred_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 6152 uint32 *flags, uint32 *min_thresh, uint32 *max_thresh, 6153 int *drop_probability, int *gain, uint32 lflags,int *refresh_time) 6154 { 6155 bcm_port_t local_port = -1; 6156 int index, profile_index; 6157 mmu_wred_drop_curve_profile_0_entry_t entry_tcp_green; 6158 mmu_wred_drop_curve_profile_1_entry_t entry_tcp_yellow; 6159 mmu_wred_drop_curve_profile_2_entry_t entry_tcp_red; 6160 mmu_wred_drop_curve_profile_3_entry_t entry_nontcp_green; 6161 mmu_wred_drop_curve_profile_4_entry_t entry_nontcp_yellow; 6162 mmu_wred_drop_curve_profile_5_entry_t entry_nontcp_red; 6163 void *entries[6]; 6164 void *entry_p; 6165 soc_mem_t mem; 6166 soc_mem_t wred_mem = 0; 6167 mmu_wred_config_entry_t qentry; 6168 int rate, pipe,time_id,time; 6169 6170 6171 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_wred_index_resolve(unit, port, cosq, 6172 *flags, lflags, &local_port, &index, NULL, NULL, NULL)); 6173 6174 if (local_port < 0) { 6175 /* 6176 * local_port is -1, when flag is BCM_COSQ_DISCARD_DEVICE and port = -1 6177 * global config is set in both X_PIPE and Y_PIPE, since there are identical 6178 * just read the config of X PIPE should be sufficient 6179 */ 6180 pipe = _TD2_XPIPE; 6181 } else { 6182 pipe = _BCM_TD2_PORT_TO_PIPE(unit, local_port); 6183 } 6184 6185 /* WRED doesn't work on CPU/LB Ports */ 6186 if (IS_LB_PORT(unit, local_port) || IS_CPU_PORT(unit, local_port)) { 6187 return BCM_E_PORT; 6188 } 6189 6190 wred_mem = (pipe == _TD2_XPIPE) ? MMU_WRED_CONFIG_X_PIPEm : MMU_WRED_CONFIG_Y_PIPEm; 6191 6192 BCM_IF_ERROR_RETURN 6193 (soc_mem_read(unit, wred_mem, MEM_BLOCK_ALL, index, &qentry)); 6194 profile_index = soc_mem_field32_get(unit, wred_mem, 6195 &qentry, PROFILE_INDEXf); 6196 6197 if (!(*flags & BCM_COSQ_DISCARD_NONTCP)) { 6198 if (*flags & BCM_COSQ_DISCARD_COLOR_GREEN) { 6199 mem = (pipe == _TD2_XPIPE) ? MMU_WRED_DROP_CURVE_PROFILE_0_X_PIPEm : 6200 MMU_WRED_DROP_CURVE_PROFILE_0_Y_PIPEm; 6201 entry_p = &entry_tcp_green; 6202 } else if (*flags & BCM_COSQ_DISCARD_COLOR_YELLOW) { 6203 mem = (pipe == _TD2_XPIPE) ? MMU_WRED_DROP_CURVE_PROFILE_1_X_PIPEm : 6204 MMU_WRED_DROP_CURVE_PROFILE_1_Y_PIPEm; 6205 entry_p = &entry_tcp_yellow; 6206 } else if (*flags & BCM_COSQ_DISCARD_COLOR_RED) { 6207 mem = (pipe == _TD2_XPIPE) ? MMU_WRED_DROP_CURVE_PROFILE_2_X_PIPEm : 6208 MMU_WRED_DROP_CURVE_PROFILE_2_Y_PIPEm; 6209 entry_p = &entry_tcp_red; 6210 } else { 6211 mem = (pipe == _TD2_XPIPE) ? MMU_WRED_DROP_CURVE_PROFILE_0_X_PIPEm : 6212 MMU_WRED_DROP_CURVE_PROFILE_0_Y_PIPEm; 6213 entry_p = &entry_tcp_green; 6214 } 6215 } else { 6216 if (*flags & BCM_COSQ_DISCARD_COLOR_GREEN) { 6217 mem = (pipe == _TD2_XPIPE) ? MMU_WRED_DROP_CURVE_PROFILE_3_X_PIPEm : 6218 MMU_WRED_DROP_CURVE_PROFILE_3_Y_PIPEm; 6219 entry_p = &entry_nontcp_green; 6220 } else if (*flags & BCM_COSQ_DISCARD_COLOR_YELLOW) { 6221 mem = (pipe == _TD2_XPIPE) ? MMU_WRED_DROP_CURVE_PROFILE_4_X_PIPEm : 6222 MMU_WRED_DROP_CURVE_PROFILE_4_Y_PIPEm; 6223 entry_p = &entry_nontcp_yellow; 6224 } else if (*flags & BCM_COSQ_DISCARD_COLOR_RED) { 6225 mem = (pipe == _TD2_XPIPE) ? MMU_WRED_DROP_CURVE_PROFILE_5_X_PIPEm : 6226 MMU_WRED_DROP_CURVE_PROFILE_5_Y_PIPEm; 6227 entry_p = &entry_nontcp_red; 6228 } else { 6229 mem = (pipe == _TD2_XPIPE) ? MMU_WRED_DROP_CURVE_PROFILE_3_X_PIPEm : 6230 MMU_WRED_DROP_CURVE_PROFILE_3_Y_PIPEm; 6231 entry_p = &entry_nontcp_green; 6232 } 6233 } 6234 6235 entries[0] = &entry_tcp_green; 6236 entries[1] = &entry_tcp_yellow; 6237 entries[2] = &entry_tcp_red; 6238 entries[3] = &entry_nontcp_green; 6239 entries[4] = &entry_nontcp_yellow; 6240 entries[5] = &entry_nontcp_red; 6241 BCM_IF_ERROR_RETURN 6242 (soc_profile_mem_get(unit, _bcm_td2_wred_profile[pipe][unit], 6243 profile_index, 1, entries)); 6244 if (min_thresh != NULL) { 6245 *min_thresh = soc_mem_field32_get(unit, mem, entry_p, MIN_THDf); 6246 } 6247 if (max_thresh != NULL) { 6248 *max_thresh = soc_mem_field32_get(unit, mem, entry_p, MAX_THDf); 6249 } 6250 if (drop_probability != NULL) { 6251 rate = soc_mem_field32_get(unit, mem, entry_p, MAX_DROP_RATEf); 6252 *drop_probability = _bcm_td2_drop_prob_to_percent(rate); 6253 } 6254 6255 if (gain) { 6256 *gain = soc_mem_field32_get(unit, wred_mem, &qentry, WEIGHTf); 6257 } 6258 6259 if (refresh_time) { 6260 time_id = soc_mem_field32_get(unit, wred_mem, &qentry, TIME_DOMAIN_SELf); 6261 BCM_IF_ERROR_RETURN 6262 (_bcm_td2_cosq_time_domain_get(unit,time_id,&time)); 6263 *refresh_time = (time + 1) * 8; 6264 } 6265 6266 *flags &= ~(BCM_COSQ_DISCARD_CAP_AVERAGE | BCM_COSQ_DISCARD_ENABLE); 6267 if (soc_mem_field32_get(unit, wred_mem, &qentry, CAP_AVERAGEf)) { 6268 *flags |= BCM_COSQ_DISCARD_CAP_AVERAGE; 6269 } 6270 if (soc_mem_field32_get(unit, wred_mem, &qentry, WRED_ENf)) { 6271 *flags |= BCM_COSQ_DISCARD_ENABLE; 6272 } 6273 if (soc_mem_field32_get(unit, wred_mem, &qentry, ECN_MARKING_ENf)) { 6274 *flags |= BCM_COSQ_DISCARD_MARK_CONGESTION; 6275 } 6276 return BCM_E_NONE; 6277 } 6278 6279 STATIC int 6280 _bcm_td2_decode_sp_masks(int num_sp, uint32 ucmap, uint32 *umap, int *numuc, 6281 uint32 *mmap, int *nummc) 6282 { 6283 int i, uindex, mindex; 6284 uint32 tmp_umap = 0, tmp_mmap = 0; 6285 6286 mindex = uindex = 0; 6287 6288 for (i = 0; i < num_sp; i++) { 6289 if (ucmap & (1 << i)) { 6290 /* MC */ 6291 tmp_mmap |= 1 << mindex; 6292 mindex += 1; 6293 } else { 6294 /* UC */ 6295 tmp_umap |= 1 << uindex; 6296 uindex += 1; 6297 } 6298 } 6299 6300 if (numuc) { 6301 *numuc = uindex; 6302 } 6303 6304 if (umap) { 6305 *umap = tmp_umap; 6306 } 6307 6308 if (mmap) { 6309 *mmap = tmp_mmap; 6310 } 6311 6312 if (nummc) { 6313 *nummc = mindex; 6314 } 6315 6316 return 0; 6317 } 6318 6319 STATIC int 6320 _bcm_td2_sched_check_constraints(int unit, int level, 6321 int *first_sp_child, 6322 int *first_sp_mc_child, 6323 int *num_spri, 6324 uint32 *ucmap, 6325 int child_index, 6326 soc_td2_sched_mode_e cur_mode, 6327 soc_td2_sched_mode_e mode) 6328 { 6329 int cur_first_child; 6330 int cur_num_spri; 6331 int cur_ucmap; 6332 int diff; 6333 6334 uint32 umap = 0, mmap = 0; 6335 int numuc = 0, nummc = 0; 6336 uint32 pnumn = 0; 6337 6338 if (((cur_mode != SOC_TD2_SCHED_MODE_STRICT) && 6339 (mode != SOC_TD2_SCHED_MODE_STRICT)) || 6340 ((cur_mode == SOC_TD2_SCHED_MODE_STRICT) && 6341 (mode == SOC_TD2_SCHED_MODE_STRICT))) { 6342 return BCM_E_NONE; 6343 } 6344 6345 cur_num_spri = *num_spri; 6346 cur_ucmap = *ucmap; 6347 6348 if (level == SOC_TD2_NODE_LVL_L1) { 6349 _bcm_td2_decode_sp_masks(cur_num_spri, cur_ucmap, &umap, 6350 &numuc, &mmap, &nummc); 6351 if (child_index < 1480) { 6352 /* UC */ 6353 pnumn = numuc; 6354 cur_num_spri = numuc; 6355 cur_first_child = *first_sp_child; 6356 } else { 6357 /* MC */ 6358 pnumn = nummc; 6359 cur_num_spri = nummc; 6360 cur_first_child = *first_sp_mc_child; 6361 } 6362 } else { 6363 pnumn = cur_num_spri; 6364 cur_first_child = *first_sp_child; 6365 } 6366 6367 if (cur_mode == SOC_TD2_SCHED_MODE_STRICT) { 6368 if ((child_index == cur_first_child) && (pnumn > 1)) { 6369 /* First SP node changed. Hence increment first_sp to next node */ 6370 if (level == SOC_TD2_NODE_LVL_L1) { 6371 if (child_index < 1480) { 6372 *first_sp_child = *first_sp_child + 1; 6373 } else { 6374 *first_sp_mc_child = *first_sp_mc_child + 1; 6375 } 6376 } else { 6377 *first_sp_child = *first_sp_child + 1; 6378 } 6379 } else if (child_index != (cur_first_child + pnumn - 1)) { 6380 /* this node is not in the middle of SP nodes */ 6381 return BCM_E_UNAVAIL; 6382 } 6383 6384 cur_num_spri -= 1; 6385 pnumn -= 1; 6386 6387 if (level == SOC_TD2_NODE_LVL_L1) { 6388 if (child_index < 1480) { 6389 *num_spri = pnumn + nummc; 6390 } else { 6391 *num_spri = pnumn + numuc; 6392 *ucmap >>= 1; 6393 } 6394 } else { 6395 *num_spri = cur_num_spri; 6396 *ucmap = cur_num_spri ? (1 << cur_num_spri) -1 : 0; 6397 } 6398 if (*num_spri == 0) { 6399 *ucmap = 0; 6400 } 6401 } else { 6402 if (cur_num_spri) { 6403 if (cur_num_spri >= 8) { 6404 return BCM_E_PARAM; 6405 } else { 6406 /* adding new sp */ 6407 if (child_index >= cur_first_child) { 6408 diff = child_index - cur_first_child; 6409 if (diff != cur_num_spri) { 6410 return BCM_E_UNAVAIL; 6411 } 6412 } else { 6413 /* Setting of SP node prior to the current first SP child, 6414 * need to make sure SP nodes are contiguous. 6415 */ 6416 if ((child_index + 1) != cur_first_child) { 6417 return BCM_E_UNAVAIL; 6418 } 6419 if (level == SOC_TD2_NODE_LVL_L1) { 6420 if (child_index < 1480) { 6421 *first_sp_child = child_index; 6422 } else { 6423 *first_sp_mc_child = child_index; 6424 } 6425 } else { 6426 *first_sp_child = child_index; 6427 } 6428 } 6429 6430 if (level == SOC_TD2_NODE_LVL_L1) { 6431 if (child_index < 1480) { 6432 pnumn += 1; 6433 *num_spri = pnumn + nummc; 6434 } else { 6435 pnumn += 1; 6436 *num_spri = pnumn + numuc; 6437 *ucmap = ((*ucmap ) << 1) + 1; 6438 } 6439 } else { 6440 pnumn += 1; 6441 *num_spri = pnumn; 6442 *ucmap = (1 << pnumn) - 1; 6443 } 6444 } 6445 } else { 6446 *num_spri = 1; 6447 *ucmap = 1; 6448 if (level == SOC_TD2_NODE_LVL_L1) { 6449 if (child_index < 1480) { 6450 *first_sp_child = child_index; 6451 *ucmap = 0; 6452 } else { 6453 *first_sp_mc_child = child_index; 6454 } 6455 } else { 6456 *first_sp_child = child_index; 6457 } 6458 } 6459 } 6460 return BCM_E_NONE; 6461 } 6462 6463 STATIC int 6464 _bcm_td2_cosq_sched_parent_child_set(int unit, int port, int level, 6465 int sched_index, int child_index, 6466 soc_td2_sched_mode_e sched_mode, 6467 int weight, _bcm_td2_cosq_node_t *child_node) 6468 { 6469 int wt, num_spri, first_sp_child, first_sp_mc_child; 6470 uint32 ucmap = 0, spmap = 0; 6471 soc_td2_sched_mode_e cur_sched_mode; 6472 _bcm_td2p_lls_info_t lls_tree_info; 6473 int rv; 6474 6475 BCM_IF_ERROR_RETURN(soc_td2_cosq_get_sched_config(unit, port, level, 6476 sched_index, child_index, &num_spri, &first_sp_child, 6477 &first_sp_mc_child, &ucmap, &spmap, &cur_sched_mode, 6478 &wt)); 6479 /* If the dynamic switchover feature is enabled, then compute the LLS 6480 configuration and adjust the bandwidth at the level such that each 6481 node has sufficient bandwidth to perform the switchover. Also set 6482 the new scheduler config based on the request */ 6483 if (soc_feature(unit, soc_feature_vector_based_spri)) { 6484 6485 if ((rv = _bcm_td2_compute_lls_config(unit, port, level, &first_sp_child, 6486 &first_sp_mc_child, &num_spri, 6487 &ucmap, &spmap, child_index, 6488 cur_sched_mode, sched_mode))) { 6489 return rv; 6490 } 6491 6492 if (cur_sched_mode != sched_mode) { 6493 SOC_EGRESS_METERING_LOCK(unit); 6494 if ((rv = _bcm_td2_adjust_lls_bw(unit, port, child_node, 6495 level + 1, child_index, 1, &lls_tree_info))){ 6496 goto restore; 6497 } 6498 } 6499 6500 if ((rv = soc_td2_cosq_set_sched_config(unit, port, level, 6501 sched_index, child_index, 6502 num_spri, first_sp_child, 6503 first_sp_mc_child, ucmap, 6504 spmap, sched_mode, weight))){ 6505 goto restore; 6506 } 6507 6508 if (cur_sched_mode != sched_mode) { 6509 goto restore; 6510 } 6511 6512 } else { 6513 if (_bcm_td2_sched_check_constraints(unit, level, &first_sp_child, 6514 &first_sp_mc_child, &num_spri, &ucmap, 6515 child_index, cur_sched_mode, sched_mode)) { 6516 return BCM_E_UNAVAIL; 6517 } 6518 6519 BCM_IF_ERROR_RETURN(soc_td2_cosq_set_sched_config(unit, port, level, 6520 sched_index, child_index, num_spri, first_sp_child, 6521 first_sp_mc_child, ucmap, spmap, sched_mode, weight)); 6522 6523 } 6524 6525 return BCM_E_NONE; 6526 6527 /* If there is an error during the switchover process, then restore the 6528 bandwidth to the previous state */ 6529 restore: 6530 if (cur_sched_mode != sched_mode) { 6531 rv = _bcm_td2_adjust_lls_bw(unit, port, child_node, 6532 level + 1, 6533 child_index, 6534 0, &lls_tree_info); 6535 SOC_EGRESS_METERING_UNLOCK(unit); 6536 } 6537 return rv; 6538 6539 } 6540 6541 /* 6542 * Function: 6543 * _bcm_td2_cosq_sched_get 6544 * Purpose: 6545 * Get scheduling mode setting 6546 * Parameters: 6547 * unit - (IN) unit number 6548 * port - (IN) port number or GPORT identifier 6549 * cosq - (IN) COS queue number 6550 * mode - (OUT) scheduling mode (BCM_COSQ_XXX) 6551 * num_weights - (IN) number of entries in weights array 6552 * weights - (OUT) weights array 6553 * Returns: 6554 * BCM_E_XXX 6555 */ 6556 STATIC int 6557 _bcm_td2_cosq_sched_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 6558 int *mode, int *weight) 6559 { 6560 _bcm_td2_cosq_node_t *node, *child_node; 6561 bcm_port_t local_port; 6562 int sch_index, lvl = SOC_TD2_NODE_LVL_L1, numq; 6563 soc_td2_sched_mode_e sched_mode; 6564 _bcm_td2_mmu_info_t *mmu_info; 6565 6566 if ((mmu_info = _bcm_td2_mmu_info[unit]) == NULL) { 6567 return BCM_E_INIT; 6568 } 6569 6570 if (cosq < 0) { 6571 if (cosq == -1) { 6572 /* caller needs to resolve the wild card value (-1) */ 6573 return BCM_E_INTERNAL; 6574 } else { /* reject all other negative value */ 6575 return BCM_E_PARAM; 6576 } 6577 } 6578 6579 BCM_IF_ERROR_RETURN 6580 (_bcm_td2_cosq_localport_resolve(unit, port, &local_port)); 6581 6582 if (_bcm_td2_cosq_port_has_ets(unit, local_port) && BCM_GPORT_IS_SET(port)) { 6583 BCM_IF_ERROR_RETURN 6584 (_bcm_td2_cosq_node_get(unit, port, 0, NULL, &local_port, NULL, &node)); 6585 sch_index = node->hw_index; 6586 numq = node->numq; 6587 if ((numq != -1) && (cosq >= numq)) { 6588 return BCM_E_PARAM; 6589 } 6590 6591 BCM_IF_ERROR_RETURN( 6592 _bcm_td2_cosq_child_node_at_input(node, cosq, &child_node)); 6593 lvl = child_node->level; 6594 sch_index = child_node->hw_index; 6595 } else { 6596 numq = (IS_CPU_PORT(unit, local_port)) ? SOC_INFO(unit).num_cpu_cosq : NUM_COS(unit); 6597 6598 if (cosq >= numq) { 6599 return BCM_E_PARAM; 6600 } 6601 6602 lvl = (IS_CPU_PORT(unit, local_port)) ? 6603 SOC_TD2_NODE_LVL_L2 : SOC_TD2_NODE_LVL_L1; 6604 6605 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_index_resolve(unit, local_port, cosq, 6606 _BCM_TD2_COSQ_INDEX_STYLE_SCHEDULER, NULL, &sch_index, NULL)); 6607 6608 } 6609 6610 BCM_IF_ERROR_RETURN( 6611 soc_td2_cosq_get_sched_mode(unit, local_port, lvl, sch_index, 6612 &sched_mode, weight)); 6613 6614 switch(sched_mode) { 6615 case SOC_TD2_SCHED_MODE_STRICT: 6616 *mode = BCM_COSQ_STRICT; 6617 break; 6618 case SOC_TD2_SCHED_MODE_WRR: 6619 *mode = BCM_COSQ_WEIGHTED_ROUND_ROBIN; 6620 break; 6621 case SOC_TD2_SCHED_MODE_WDRR: 6622 *mode = BCM_COSQ_DEFICIT_ROUND_ROBIN; 6623 break; 6624 default: 6625 return BCM_E_INTERNAL; 6626 break; 6627 } 6628 return BCM_E_NONE; 6629 } 6630 6631 6632 /* 6633 * Function: 6634 * _bcm_td2_cosq_sched_set 6635 * Purpose: 6636 * Set scheduling mode 6637 * Parameters: 6638 * unit - (IN) unit number 6639 * port - (IN) port number or GPORT identifier 6640 * cosq - (IN) COS queue number 6641 * mode - (IN) scheduling mode (BCM_COSQ_XXX) 6642 * num_weights - (IN) number of entries in weights array 6643 * weights - (IN) weights array 6644 * Returns: 6645 * BCM_E_XXX 6646 */ 6647 STATIC int 6648 _bcm_td2_cosq_sched_set(int unit, bcm_port_t gport, bcm_cos_queue_t cosq, 6649 int mode, int weight) 6650 { 6651 _bcm_td2_cosq_node_t *node = NULL, *child_node; 6652 bcm_port_t local_port; 6653 int sch_index, lvl = SOC_TD2_NODE_LVL_L0, cpu_l0_index; 6654 int numq, lwts = 1, child_index, cpu_l1_index, roff = 0; 6655 soc_td2_sched_mode_e sched_mode; 6656 int rv = BCM_E_NONE; 6657 int cur_mode, cur_weight, new_mode; 6658 /* 1 - indicates dynamic change allowed without emptying the queue. */ 6659 int dynamic_change = 0; 6660 void *setting = NULL; 6661 6662 if (cosq < 0) { 6663 if (cosq == -1) { 6664 /* caller needs to resolve the wild card value (-1) */ 6665 return BCM_E_INTERNAL; 6666 } else { /* reject all other negative value */ 6667 return BCM_E_PARAM; 6668 } 6669 } 6670 6671 if ((weight < 0) || (weight > 127)) { 6672 return BCM_E_PARAM; 6673 } 6674 6675 switch(mode) { 6676 case BCM_COSQ_STRICT: 6677 sched_mode = SOC_TD2_SCHED_MODE_STRICT; 6678 lwts = 0; 6679 break; 6680 case BCM_COSQ_ROUND_ROBIN: 6681 sched_mode = SOC_TD2_SCHED_MODE_WRR; 6682 lwts = 1; 6683 break; 6684 case BCM_COSQ_WEIGHTED_ROUND_ROBIN: 6685 sched_mode = SOC_TD2_SCHED_MODE_WRR; 6686 lwts = weight; 6687 break; 6688 case BCM_COSQ_DEFICIT_ROUND_ROBIN: 6689 sched_mode = SOC_TD2_SCHED_MODE_WDRR; 6690 lwts = weight; 6691 break; 6692 default: 6693 return BCM_E_PARAM; 6694 } 6695 6696 if ( lwts == 0) { 6697 sched_mode = SOC_TD2_SCHED_MODE_STRICT; 6698 } 6699 6700 BCM_IF_ERROR_RETURN 6701 (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port)); 6702 6703 BCM_IF_ERROR_RETURN 6704 (_bcm_td2_cosq_sched_get(unit, gport, cosq, &cur_mode, &cur_weight)); 6705 6706 new_mode = (weight == 0) ? BCM_COSQ_STRICT : mode; 6707 6708 /*The weight for both WDRR and WRR schemes can be changed dynamically.*/ 6709 if ((cur_mode == new_mode) && 6710 (new_mode != BCM_COSQ_STRICT)){ 6711 dynamic_change = 1; 6712 } else { 6713 dynamic_change = 0; 6714 } 6715 6716 if (!dynamic_change) { 6717 /* don't apply it for TD2+ if dynamic scheduling feature is enabled*/ 6718 if (!soc_feature(unit, soc_feature_vector_based_spri)) { 6719 BCM_IF_ERROR_RETURN 6720 (_bcm_td2_dynamic_sched_update_begin(unit, gport, cosq)); 6721 } 6722 6723 } 6724 6725 if (_bcm_td2_cosq_port_has_ets(unit, local_port)) { 6726 rv = _bcm_td2_cosq_node_get(unit, gport, 0, NULL, &local_port, NULL, &node); 6727 if (BCM_SUCCESS(rv)) { 6728 numq = node->numq; 6729 /* HSP/LLS - child node at cosq index of parent gport 6730 * is resloved to set it's schedule mode and weight 6731 */ 6732 rv = _bcm_td2_cosq_child_node_at_input(node, cosq, &child_node); 6733 if (BCM_SUCCESS(rv)) { 6734 child_index = child_node->hw_index; 6735 if (IS_TD2_HSP_PORT(unit, local_port)) { 6736 rv = soc_td2_cosq_set_sched_mode(unit, local_port, 6737 child_node->level, child_node->hw_index, sched_mode, lwts); 6738 } else { 6739 BCM_IF_ERROR_RETURN(_soc_egress_metering_freeze(unit, 6740 local_port, &setting)); 6741 rv = _bcm_td2_cosq_sched_parent_child_set(unit, 6742 local_port, node->level, node->hw_index, 6743 child_node->hw_index, sched_mode, lwts, child_node); 6744 BCM_IF_ERROR_RETURN(_soc_egress_metering_thaw(unit, 6745 local_port, setting)); 6746 } 6747 } 6748 } 6749 } else { 6750 numq = (IS_CPU_PORT(unit, local_port)) ? SOC_INFO(unit).num_cpu_cosq : NUM_COS(unit); 6751 6752 if (cosq >= numq) { 6753 rv = BCM_E_PARAM; 6754 } 6755 6756 if (BCM_SUCCESS(rv)) { 6757 if (IS_CPU_PORT(unit, local_port)) { 6758 lvl = SOC_TD2_NODE_LVL_L1; 6759 roff = cosq/8; 6760 } else if (IS_TD2_HSP_PORT(unit, local_port)) { 6761 lvl = SOC_TD2_NODE_LVL_L0; 6762 roff = 1; 6763 } else { 6764 lvl = SOC_TD2_NODE_LVL_L0; 6765 } 6766 6767 rv = soc_td2_sched_hw_index_get(unit, local_port, 6768 lvl, roff, &sch_index); 6769 } 6770 if (BCM_SUCCESS(rv)) { 6771 rv = _bcm_td2_cosq_index_resolve(unit, local_port, cosq, 6772 _BCM_TD2_COSQ_INDEX_STYLE_SCHEDULER, NULL, &child_index, NULL); 6773 } 6774 6775 if (BCM_SUCCESS(rv)) { 6776 if (IS_TD2_HSP_PORT(unit, local_port)) { 6777 rv = soc_td2_cosq_set_sched_mode(unit, local_port, 6778 SOC_TD2_NODE_LVL_L1, 6779 child_index, 6780 sched_mode, lwts); 6781 } else { 6782 if (IS_CPU_PORT(unit, local_port)) { 6783 /* set the L0.0 index as parent, L0.(cosq/8) as child in 6784 * schduling mode */ 6785 rv = soc_td2_sched_hw_index_get(unit, local_port, 6786 SOC_TD2_NODE_LVL_L0, 0, &cpu_l0_index); 6787 if (BCM_SUCCESS(rv)) { 6788 rv = soc_td2_sched_hw_index_get(unit, local_port, 6789 SOC_TD2_NODE_LVL_L1, cosq/8, &cpu_l1_index); 6790 } 6791 if (BCM_SUCCESS(rv)) { 6792 BCM_IF_ERROR_RETURN(_soc_egress_metering_freeze(unit, 6793 local_port, &setting)); 6794 rv = _bcm_td2_cosq_sched_parent_child_set(unit, 6795 local_port, SOC_TD2_NODE_LVL_L0, cpu_l0_index, 6796 cpu_l1_index, sched_mode, 1, NULL); 6797 BCM_IF_ERROR_RETURN(_soc_egress_metering_thaw(unit, 6798 local_port, setting)); 6799 } 6800 } 6801 if (BCM_SUCCESS(rv)) { 6802 BCM_IF_ERROR_RETURN(_soc_egress_metering_freeze(unit, 6803 local_port, &setting)); 6804 rv = _bcm_td2_cosq_sched_parent_child_set(unit, local_port, 6805 lvl, sch_index, child_index, sched_mode, lwts, NULL); 6806 BCM_IF_ERROR_RETURN(_soc_egress_metering_thaw(unit, 6807 local_port, setting)); 6808 } 6809 } 6810 } 6811 } 6812 6813 if (!dynamic_change) { 6814 /* don't apply it for TD2+ if dynamic scheduling feature is enabled*/ 6815 if (!soc_feature(unit, soc_feature_vector_based_spri)) { 6816 BCM_IF_ERROR_RETURN 6817 (_bcm_td2_dynamic_sched_update_end(unit, gport, cosq)); 6818 } 6819 } 6820 6821 return rv; 6822 } 6823 6824 6825 /* 6826 * Function: 6827 * bcm_td2_cosq_detach 6828 * Purpose: 6829 * Discard all COS schedule/mapping state. 6830 * Parameters: 6831 * unit - unit number 6832 * Returns: 6833 * BCM_E_XXX 6834 */ 6835 int 6836 bcm_td2_cosq_detach(int unit, int software_state_only) 6837 { 6838 int i, pipe; 6839 soc_info_t *si; 6840 6841 si = &SOC_INFO(unit); 6842 6843 (void) _bcm_bst_detach(unit); 6844 6845 if (NULL != _bcm_td2_endpoint_queuing_info[unit]) { 6846 if (NULL != _bcm_td2_endpoint_queuing_info[unit]->ptr_array) { 6847 for (i = 0; i < _BCM_TD2_NUM_ENDPOINT(unit); i++) { 6848 if (_BCM_TD2_ENDPOINT_IS_USED(unit, i)) { 6849 sal_free(_BCM_TD2_ENDPOINT(unit, i)); 6850 _BCM_TD2_ENDPOINT(unit, i) = NULL; 6851 } 6852 } 6853 sal_free(_bcm_td2_endpoint_queuing_info[unit]->ptr_array); 6854 _bcm_td2_endpoint_queuing_info[unit]->ptr_array = NULL; 6855 } 6856 if (NULL != _bcm_td2_endpoint_queuing_info[unit]->cos_map_profile) { 6857 (void) soc_profile_mem_destroy(unit, 6858 _bcm_td2_endpoint_queuing_info[unit]->cos_map_profile); 6859 sal_free(_bcm_td2_endpoint_queuing_info[unit]->cos_map_profile); 6860 _bcm_td2_endpoint_queuing_info[unit]->cos_map_profile = NULL; 6861 } 6862 sal_free(_bcm_td2_endpoint_queuing_info[unit]); 6863 _bcm_td2_endpoint_queuing_info[unit] = NULL; 6864 } 6865 6866 /* Cleanup profile for PORT_COS_MAP table */ 6867 if (_bcm_td2_cos_map_profile[unit] != NULL) { 6868 SOC_IF_ERROR_RETURN(soc_profile_mem_destroy(unit, 6869 _bcm_td2_cos_map_profile[unit])); 6870 sal_free(_bcm_td2_cos_map_profile[unit]); 6871 _bcm_td2_cos_map_profile[unit] = NULL; 6872 } 6873 6874 /* Cleanup profile for IFP_COS_MAP table. */ 6875 if (_bcm_td2_ifp_cos_map_profile[unit] != NULL) { 6876 SOC_IF_ERROR_RETURN(soc_profile_mem_destroy(unit, 6877 _bcm_td2_ifp_cos_map_profile[unit])); 6878 sal_free(_bcm_td2_ifp_cos_map_profile[unit]); 6879 _bcm_td2_ifp_cos_map_profile[unit] = NULL; 6880 } 6881 6882 /* Cleanup profile for SERVICE_COS_MAP table */ 6883 if (_bcm_td2_service_cos_map_profile[unit] != NULL) { 6884 SOC_IF_ERROR_RETURN(soc_profile_mem_destroy(unit, 6885 _bcm_td2_service_cos_map_profile[unit])); 6886 sal_free(_bcm_td2_service_cos_map_profile[unit]); 6887 _bcm_td2_service_cos_map_profile[unit] = NULL; 6888 } 6889 6890 /* Cleanup profile for SERVICE_PORT_MAP table */ 6891 if (_bcm_td2_service_port_map_profile[unit] != NULL) { 6892 SOC_IF_ERROR_RETURN(soc_profile_mem_destroy(unit, 6893 _bcm_td2_service_port_map_profile[unit])); 6894 sal_free(_bcm_td2_service_port_map_profile[unit]); 6895 _bcm_td2_service_port_map_profile[unit] = NULL; 6896 } 6897 6898 /* Cleanup profile for MMU_QCN_SITB table */ 6899 if (_bcm_td2_sample_int_profile[unit] != NULL) { 6900 SOC_IF_ERROR_RETURN(soc_profile_mem_destroy(unit, 6901 _bcm_td2_sample_int_profile[unit])); 6902 sal_free(_bcm_td2_sample_int_profile[unit]); 6903 _bcm_td2_sample_int_profile[unit] = NULL; 6904 } 6905 6906 /* Cleanup profile for MMU_QCN_CPQ_SEQ register */ 6907 if (_bcm_td2_feedback_profile[unit] != NULL) { 6908 SOC_IF_ERROR_RETURN(soc_profile_reg_destroy(unit, 6909 _bcm_td2_feedback_profile[unit])); 6910 sal_free(_bcm_td2_feedback_profile[unit]); 6911 _bcm_td2_feedback_profile[unit] = NULL; 6912 } 6913 6914 /* Cleanup profile for PRIO2COS_LLFC register */ 6915 if (_bcm_td2_llfc_profile[unit] != NULL) { 6916 SOC_IF_ERROR_RETURN(soc_profile_reg_destroy(unit, 6917 _bcm_td2_llfc_profile[unit])); 6918 sal_free(_bcm_td2_llfc_profile[unit]); 6919 _bcm_td2_llfc_profile[unit] = NULL; 6920 } 6921 6922 /* Cleanup profile for VOQ_MOD_MAP table */ 6923 if (_bcm_td2_voq_port_map_profile[unit] != NULL) { 6924 SOC_IF_ERROR_RETURN(soc_profile_mem_destroy(unit, 6925 _bcm_td2_voq_port_map_profile[unit])); 6926 sal_free(_bcm_td2_voq_port_map_profile[unit]); 6927 _bcm_td2_voq_port_map_profile[unit] = NULL; 6928 } 6929 6930 for (pipe = _TD2_XPIPE; pipe <= _TD2_YPIPE; pipe++) { 6931 /* Cleanup profile for MMU_WRED_DROP_CURVE_PROFILE_x/y tables */ 6932 if (_bcm_td2_wred_profile[pipe][unit] != NULL) { 6933 SOC_IF_ERROR_RETURN(soc_profile_mem_destroy(unit, 6934 _bcm_td2_wred_profile[pipe][unit])); 6935 sal_free(_bcm_td2_wred_profile[pipe][unit]); 6936 _bcm_td2_wred_profile[pipe][unit] = NULL; 6937 } 6938 } 6939 6940 for (i = 0; i < si->num_cpu_cosq; i++) { 6941 if (_bcm_td2_cosq_cpu_cosq_config[unit][i] != NULL) { 6942 sal_free(_bcm_td2_cosq_cpu_cosq_config[unit][i]); 6943 _bcm_td2_cosq_cpu_cosq_config[unit][i] = NULL; 6944 } 6945 } 6946 6947 if (_bcm_td2_mmu_info[unit] != NULL) { 6948 _bcm_td2_cosq_free_memory(_bcm_td2_mmu_info[unit]); 6949 sal_free(_bcm_td2_mmu_info[unit]); 6950 _bcm_td2_mmu_info[unit] = NULL; 6951 } 6952 6953 soc_trident2_fc_map_shadow_free(unit); 6954 return BCM_E_NONE; 6955 } 6956 6957 /* 6958 * Function: 6959 * bcm_td2_cosq_config_set 6960 * Purpose: 6961 * Set the number of COS queues 6962 * Parameters: 6963 * unit - unit number 6964 * numq - number of COS queues (1-8). 6965 * Returns: 6966 * BCM_E_XXX 6967 */ 6968 int 6969 bcm_td2_cosq_config_set(int unit, int numq) 6970 { 6971 port_cos_map_entry_t cos_map_entries[16]; 6972 port_cos_map_entry_t hg_cos_map_entries[16]; 6973 void *entries[1], *hg_entries[1]; 6974 uint32 index, hg_index; 6975 int count, hg_count; 6976 bcm_port_t port; 6977 int cos, prio; 6978 uint32 i; 6979 voq_cos_map_entry_t voq_cos_map; 6980 int ref_count; 6981 int cpu_hg_index = 0; 6982 6983 if (numq < 1 || numq > 8) { 6984 return BCM_E_PARAM; 6985 } 6986 6987 /* clear out old profiles. */ 6988 index = 0; 6989 while (index < soc_mem_index_count(unit, PORT_COS_MAPm)) { 6990 BCM_IF_ERROR_RETURN(soc_profile_mem_ref_count_get(unit, 6991 _bcm_td2_cos_map_profile[unit], 6992 index, &ref_count)); 6993 if (ref_count > 0) { 6994 while (ref_count) { 6995 BCM_IF_ERROR_RETURN(soc_profile_mem_delete(unit, 6996 _bcm_td2_cos_map_profile[unit], index)); 6997 ref_count -= 1; 6998 } 6999 } 7000 index += 16; 7001 } 7002 7003 /* Distribute first 8 internal priority levels into the specified number 7004 * of cosq, map remaining internal priority levels to highest priority 7005 * cosq */ 7006 sal_memset(cos_map_entries, 0, sizeof(cos_map_entries)); 7007 entries[0] = &cos_map_entries; 7008 hg_entries[0] = &hg_cos_map_entries; 7009 prio = 0; 7010 for (cos = 0; cos < numq; cos++) { 7011 for (i = 8 / numq + (cos < 8 % numq ? 1 : 0); i > 0; i--) { 7012 soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio], 7013 UC_COS1f, cos); 7014 soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio], 7015 MC_COS1f, cos); 7016 soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio], 7017 HG_COSf, cos); 7018 soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio], 7019 RQE_Q_NUMf, cos); 7020 prio++; 7021 } 7022 } 7023 for (prio = 8; prio < 16; prio++) { 7024 soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio], 7025 UC_COS1f, numq - 1); 7026 soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio], 7027 MC_COS1f, numq - 1); 7028 soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio], 7029 HG_COSf, numq - 1); 7030 soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio], 7031 RQE_Q_NUMf, numq - 1); 7032 } 7033 7034 /* Map internal priority levels to CPU CoS queues */ 7035 BCM_IF_ERROR_RETURN(_bcm_esw_cpu_cosq_mapping_default_set(unit, numq)); 7036 7037 #ifdef BCM_COSQ_HIGIG_MAP_DISABLE 7038 /* Use identical mapping for Higig port */ 7039 sal_memset(hg_cos_map_entries, 0, sizeof(hg_cos_map_entries)); 7040 prio = 0; 7041 for (prio = 0; prio < 8; prio++) { 7042 soc_mem_field32_set(unit, PORT_COS_MAPm, &hg_cos_map_entries[prio], 7043 UC_COS1f, prio); 7044 soc_mem_field32_set(unit, PORT_COS_MAPm, &hg_cos_map_entries[prio], 7045 MC_COS1f, prio); 7046 soc_mem_field32_set(unit, PORT_COS_MAPm, &hg_cos_map_entries[prio], 7047 RQE_Q_NUMf, prio); 7048 } 7049 for (prio = 8; prio < 13; prio++) { 7050 soc_mem_field32_set(unit, PORT_COS_MAPm, &hg_cos_map_entries[prio], 7051 UC_COS1f, 7); 7052 soc_mem_field32_set(unit, PORT_COS_MAPm, &hg_cos_map_entries[prio], 7053 MC_COS1f, 7); 7054 soc_mem_field32_set(unit, PORT_COS_MAPm, &hg_cos_map_entries[prio], 7055 RQE_Q_NUMf, 7); 7056 } 7057 #else /* BCM_COSQ_HIGIG_MAP_DISABLE */ 7058 sal_memcpy(hg_cos_map_entries, cos_map_entries, sizeof(cos_map_entries)); 7059 #endif /* !BCM_COSQ_HIGIG_MAP_DISABLE */ 7060 7061 BCM_IF_ERROR_RETURN 7062 (soc_profile_mem_add(unit, _bcm_td2_cos_map_profile[unit], 7063 entries, 16, &index)); 7064 soc_mem_field32_set(unit, PORT_COS_MAPm, &hg_cos_map_entries[14], 7065 HG_COSf, 8); 7066 soc_mem_field32_set(unit, PORT_COS_MAPm, &hg_cos_map_entries[15], 7067 HG_COSf, 9); 7068 7069 BCM_IF_ERROR_RETURN 7070 (soc_profile_mem_add(unit, _bcm_td2_cos_map_profile[unit], 7071 hg_entries, 16, &hg_index)); 7072 count = 0; 7073 hg_count = 0; 7074 PBMP_ALL_ITER(unit, port) { 7075 if (IS_LB_PORT(unit, port)) { 7076 continue; 7077 } 7078 7079 if (IS_HG_PORT(unit, port)) { 7080 BCM_IF_ERROR_RETURN 7081 (soc_mem_field32_modify(unit, COS_MAP_SELm, port, SELECTf, 7082 hg_index / 16)); 7083 hg_count++; 7084 } else { 7085 BCM_IF_ERROR_RETURN 7086 (soc_mem_field32_modify(unit, COS_MAP_SELm, port, SELECTf, 7087 index / 16)); 7088 count++; 7089 } 7090 } 7091 cpu_hg_index = SOC_INFO(unit).cpu_hg_index; 7092 if (cpu_hg_index != -1) { 7093 BCM_IF_ERROR_RETURN 7094 (soc_mem_field32_modify(unit, COS_MAP_SELm, 7095 cpu_hg_index, SELECTf, index / 16)); 7096 count++; 7097 } 7098 7099 for (i = 1; i < count; i++) { 7100 soc_profile_mem_reference(unit, _bcm_td2_cos_map_profile[unit], index, 0); 7101 } 7102 for (i = 1; i < hg_count; i++) { 7103 soc_profile_mem_reference(unit, _bcm_td2_cos_map_profile[unit], 7104 hg_index, 0); 7105 } 7106 /* Delete the default higig cos map profile for the non-higig system */ 7107 if (hg_count == 0) { 7108 BCM_IF_ERROR_RETURN( 7109 soc_profile_mem_delete(unit, _bcm_td2_cos_map_profile[unit], 7110 hg_index)); 7111 } 7112 7113 sal_memset(&voq_cos_map, 0, sizeof(voq_cos_map)); 7114 for (cos = 0; cos < numq; cos++) { 7115 for (i = 8 / numq + (i < 8 % numq ? 1 : 0); i > 0; i--) { 7116 soc_mem_field32_set(unit, VOQ_COS_MAPm, &voq_cos_map, VOQ_COS_OFFSETf, cos); 7117 BCM_IF_ERROR_RETURN( 7118 soc_mem_write(unit, VOQ_COS_MAPm, MEM_BLOCK_ANY, cos, 7119 &voq_cos_map)); 7120 prio++; 7121 } 7122 } 7123 for (prio = 8; prio < 16; prio++) { 7124 soc_mem_field32_set(unit, VOQ_COS_MAPm, &voq_cos_map, VOQ_COS_OFFSETf, numq - 1); 7125 BCM_IF_ERROR_RETURN( 7126 soc_mem_write(unit, VOQ_COS_MAPm, MEM_BLOCK_ANY, prio, 7127 &voq_cos_map)); 7128 } 7129 7130 _TD2_NUM_COS(unit) = numq; 7131 7132 return BCM_E_NONE; 7133 } 7134 7135 #ifdef BCM_TRIDENT2PLUS_SUPPORT 7136 /* 7137 * Function: 7138 * bcm_td2p_port_cosq_config_set 7139 * Purpose: 7140 * called during flexport during port attach/detach 7141 * to update the cos_map profile for the port 7142 * Parameters: 7143 * unit - unit number 7144 * port - port number 7145 * enable - add/delete 7146 * Returns: 7147 * BCM_E_XXX 7148 */ 7149 int 7150 bcm_td2p_port_cosq_config_set(int unit, bcm_port_t port, int enable) 7151 { 7152 port_cos_map_entry_t cos_map_entries[16]; 7153 port_cos_map_entry_t hg_cos_map_entries[16]; 7154 cos_map_sel_entry_t cos_map_sel_entry; 7155 void *entries[1], *hg_entries[1]; 7156 uint32 index, old_index, hg_index; 7157 int cos, prio, numq, rv; 7158 uint32 i; 7159 7160 numq = _TD2_NUM_COS(unit); 7161 7162 sal_memset(cos_map_entries, 0, sizeof(cos_map_entries)); 7163 entries[0] = &cos_map_entries; 7164 hg_entries[0] = &hg_cos_map_entries; 7165 prio = 0; 7166 if (enable) { 7167 for (cos = 0; cos < numq; cos++) { 7168 for (i = 8 / numq + (cos < 8 % numq ? 1 : 0); i > 0; i--) { 7169 soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio], 7170 UC_COS1f, cos); 7171 soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio], 7172 MC_COS1f, cos); 7173 soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio], 7174 HG_COSf, cos); 7175 soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio], 7176 RQE_Q_NUMf, cos); 7177 prio++; 7178 } 7179 } 7180 for (prio = 8; prio < 16; prio++) { 7181 soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio], 7182 UC_COS1f, numq - 1); 7183 soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio], 7184 MC_COS1f, numq - 1); 7185 soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio], 7186 HG_COSf, numq - 1); 7187 soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio], 7188 RQE_Q_NUMf, numq - 1); 7189 } 7190 7191 7192 #ifdef BCM_COSQ_HIGIG_MAP_DISABLE 7193 /* Use identical mapping for Higig port */ 7194 sal_memset(hg_cos_map_entries, 0, sizeof(hg_cos_map_entries)); 7195 prio = 0; 7196 for (prio = 0; prio < 8; prio++) { 7197 soc_mem_field32_set(unit, PORT_COS_MAPm, &hg_cos_map_entries[prio], 7198 UC_COS1f, prio); 7199 soc_mem_field32_set(unit, PORT_COS_MAPm, &hg_cos_map_entries[prio], 7200 MC_COS1f, prio); 7201 soc_mem_field32_set(unit, PORT_COS_MAPm, &hg_cos_map_entries[prio], 7202 RQE_Q_NUMf, prio); 7203 } 7204 for (prio = 8; prio < 13; prio++) { 7205 soc_mem_field32_set(unit, PORT_COS_MAPm, &hg_cos_map_entries[prio], 7206 UC_COS1f, 7); 7207 soc_mem_field32_set(unit, PORT_COS_MAPm, &hg_cos_map_entries[prio], 7208 MC_COS1f, 7); 7209 soc_mem_field32_set(unit, PORT_COS_MAPm, &hg_cos_map_entries[prio], 7210 RQE_Q_NUMf, 7); 7211 } 7212 #else /* BCM_COSQ_HIGIG_MAP_DISABLE */ 7213 sal_memcpy(hg_cos_map_entries, cos_map_entries, sizeof(cos_map_entries)); 7214 #endif /* !BCM_COSQ_HIGIG_MAP_DISABLE */ 7215 soc_mem_field32_set(unit, PORT_COS_MAPm, &hg_cos_map_entries[14], 7216 HG_COSf, 8); 7217 soc_mem_field32_set(unit, PORT_COS_MAPm, &hg_cos_map_entries[15], 7218 HG_COSf, 9); 7219 7220 if (IS_HG_PORT(unit, port)) { 7221 soc_mem_lock(unit, PORT_COS_MAPm); 7222 7223 rv = soc_profile_mem_add(unit, _bcm_td2_cos_map_profile[unit], 7224 hg_entries, 16, &hg_index); 7225 7226 soc_mem_unlock(unit, PORT_COS_MAPm); 7227 if (BCM_FAILURE(rv)) { 7228 return rv; 7229 } 7230 BCM_IF_ERROR_RETURN 7231 (soc_mem_field32_modify(unit, COS_MAP_SELm, port, SELECTf, 7232 hg_index / 16)); 7233 } else { 7234 soc_mem_lock(unit, PORT_COS_MAPm); 7235 7236 rv = soc_profile_mem_add(unit, _bcm_td2_cos_map_profile[unit], 7237 entries, 16, &index); 7238 7239 soc_mem_unlock(unit, PORT_COS_MAPm); 7240 if (BCM_FAILURE(rv)) { 7241 return rv; 7242 } 7243 BCM_IF_ERROR_RETURN 7244 (soc_mem_field32_modify(unit, COS_MAP_SELm, port, SELECTf, 7245 index / 16)); 7246 } 7247 7248 } else { 7249 BCM_IF_ERROR_RETURN 7250 (READ_COS_MAP_SELm(unit, MEM_BLOCK_ANY, port, 7251 &cos_map_sel_entry)); 7252 old_index = soc_mem_field32_get(unit, COS_MAP_SELm, &cos_map_sel_entry, 7253 SELECTf); 7254 old_index *= 16; 7255 7256 soc_mem_lock(unit, PORT_COS_MAPm); 7257 7258 rv = soc_profile_mem_delete(unit, _bcm_td2_cos_map_profile[unit], 7259 old_index); 7260 7261 soc_mem_unlock(unit, PORT_COS_MAPm); 7262 if (BCM_FAILURE(rv)) { 7263 return rv; 7264 } 7265 } 7266 return BCM_E_NONE; 7267 } 7268 #endif 7269 7270 STATIC int 7271 _bcm_td2_cosq_egress_sp_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 7272 int *p_pool_start, int *p_pool_end) 7273 { 7274 int local_port; 7275 int pool; 7276 if (cosq == BCM_COS_INVALID) { 7277 *p_pool_start = 0; 7278 *p_pool_end = 3; 7279 return BCM_E_NONE; 7280 } 7281 7282 BCM_IF_ERROR_RETURN 7283 (_bcm_td2_cosq_index_resolve(unit, gport, cosq, 7284 _BCM_TD2_COSQ_INDEX_STYLE_EGR_POOL, 7285 &local_port, &pool, NULL)); 7286 7287 *p_pool_start = *p_pool_end = pool; 7288 return BCM_E_NONE; 7289 } 7290 7291 STATIC int 7292 _bcm_td2_cosq_ingress_sp_get(int unit, bcm_gport_t gport, bcm_cos_queue_t pri_grp, 7293 int *p_pool_start, int *p_pool_end) 7294 { 7295 int local_port; 7296 uint32 rval, pool; 7297 static const soc_field_t prigroup_spid_field[] = { 7298 PG0_SPIDf, PG1_SPIDf, PG2_SPIDf, PG3_SPIDf, 7299 PG4_SPIDf, PG5_SPIDf, PG6_SPIDf, PG7_SPIDf 7300 }; 7301 7302 if (pri_grp == BCM_COS_INVALID) { 7303 *p_pool_start = 0; 7304 *p_pool_end = 3; 7305 return BCM_E_NONE; 7306 } 7307 7308 BCM_IF_ERROR_RETURN 7309 (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port)); 7310 7311 if (!SOC_PORT_VALID(unit, local_port)) { 7312 return BCM_E_PORT; 7313 } 7314 7315 if ((pri_grp < 0) || (pri_grp >= 8)) { 7316 return BCM_E_PARAM; 7317 } 7318 7319 SOC_IF_ERROR_RETURN(READ_THDI_PORT_PG_SPIDr(unit, local_port, &rval)); 7320 pool = soc_reg_field_get(unit, THDI_PORT_PG_SPIDr, rval, 7321 prigroup_spid_field[pri_grp]); 7322 7323 *p_pool_start = *p_pool_end = pool; 7324 return BCM_E_NONE; 7325 } 7326 7327 STATIC int 7328 _bcm_td2_cosq_ingress_pg_get(int unit, bcm_gport_t gport, bcm_cos_queue_t pri, 7329 int *p_pg_start, int *p_pg_end) 7330 { 7331 bcm_port_t local_port; 7332 uint32 rval,pool; 7333 soc_reg_t reg = INVALIDr; 7334 static const soc_reg_t prigroup_reg[] = { 7335 THDI_PORT_PRI_GRP0r, THDI_PORT_PRI_GRP1r 7336 }; 7337 static const soc_field_t prigroup_field[] = { 7338 PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf, 7339 PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf, 7340 PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf, 7341 PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf 7342 }; 7343 7344 if (pri == BCM_COS_INVALID) { 7345 *p_pg_start = 0; 7346 *p_pg_end = 7; 7347 return BCM_E_NONE; 7348 } 7349 7350 BCM_IF_ERROR_RETURN 7351 (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port)); 7352 7353 if (!SOC_PORT_VALID(unit, local_port)) { 7354 return BCM_E_PORT; 7355 } 7356 7357 if (pri > 15) { 7358 return BCM_E_PARAM; 7359 } 7360 /* get PG for port using Port+Cos */ 7361 if (pri < 8) { 7362 reg = prigroup_reg[0]; 7363 } else { 7364 reg = prigroup_reg[1]; 7365 } 7366 7367 SOC_IF_ERROR_RETURN 7368 (soc_reg32_get(unit, reg, local_port, 0, &rval)); 7369 pool = soc_reg_field_get(unit, reg, rval, prigroup_field[pri]); 7370 7371 *p_pg_start = *p_pg_end = pool; 7372 return BCM_E_NONE; 7373 } 7374 7375 7376 STATIC _bcm_bst_cb_ret_t 7377 _bcm_td2_bst_index_resolve(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 7378 bcm_bst_stat_id_t bid, int *pipe, int *start_hw_index, 7379 int *end_hw_index, int *rcb_data, void **cb_data, int *bcm_rv) 7380 { 7381 int phy_port, mmu_port, local_port; 7382 _bcm_td2_cosq_node_t *node = NULL; 7383 soc_info_t *si; 7384 uint32 rval = 0; 7385 int pool_idx; 7386 7387 *bcm_rv = BCM_E_NONE; 7388 7389 #define _BST_IF_ERROR_GOTO_EXIT(op) \ 7390 do { int __rv__; if ((__rv__ = (op)) < 0) { goto error_exit; } } while(0) 7391 7392 _BST_IF_ERROR_GOTO_EXIT 7393 (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port)); 7394 7395 si = &SOC_INFO(unit); 7396 phy_port = si->port_l2p_mapping[local_port]; 7397 mmu_port = si->port_p2m_mapping[phy_port]; 7398 7399 *pipe = (mmu_port < 64) ? 0 : 1; 7400 7401 if (bid == bcmBstStatIdDevice) { 7402 *start_hw_index = *end_hw_index = 0; 7403 *bcm_rv = BCM_E_NONE; 7404 return _BCM_BST_RV_OK; 7405 } 7406 7407 if (bid == bcmBstStatIdEgrPool) { 7408 /* Egress Unicast Pool */ 7409 if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 7410 goto error_exit; 7411 } 7412 _BST_IF_ERROR_GOTO_EXIT(_bcm_td2_cosq_egress_sp_get(unit, gport, cosq, 7413 start_hw_index, end_hw_index)); 7414 return _BCM_BST_RV_OK; 7415 } else if (bid == bcmBstStatIdEgrMCastPool) { 7416 /* Egress Multicast Pool */ 7417 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 7418 goto error_exit; 7419 } 7420 _BST_IF_ERROR_GOTO_EXIT(_bcm_td2_cosq_egress_sp_get(unit, gport, cosq, 7421 start_hw_index, end_hw_index)); 7422 return _BCM_BST_RV_OK; 7423 } else if (bid == bcmBstStatIdIngPool) { 7424 /* ingress pool */ 7425 _BST_IF_ERROR_GOTO_EXIT(_bcm_td2_cosq_ingress_sp_get(unit, gport, cosq, 7426 start_hw_index, end_hw_index)); 7427 return _BCM_BST_RV_OK; 7428 } else if (bid == bcmBstStatIdRQEPool) { 7429 /* RQE pool */ 7430 if (cosq == BCM_COS_INVALID) { 7431 *start_hw_index = 0; 7432 *end_hw_index = _TD2_MMU_NUM_POOL - 1; 7433 }else if ((cosq < 0) || (cosq >= _TD2_MMU_NUM_RQE_QUEUES)) { 7434 return BCM_E_PARAM; 7435 } else { 7436 SOC_IF_ERROR_RETURN 7437 (READ_MMU_THDR_DB_CONFIG1_PRIQr(unit, cosq, &rval)); 7438 7439 pool_idx = soc_reg_field_get(unit, MMU_THDR_DB_CONFIG1_PRIQr, rval, 7440 SPIDf); 7441 *start_hw_index = *end_hw_index = pool_idx; 7442 } 7443 return _BCM_BST_RV_OK; 7444 } else if (bid == bcmBstStatIdRQEQueue) { 7445 /* RQE queue */ 7446 if (cosq == BCM_COS_INVALID) { 7447 *start_hw_index = 0; 7448 *end_hw_index = _TD2_MMU_NUM_RQE_QUEUES - 1; 7449 }else if ((cosq < 0) || (cosq >= _TD2_MMU_NUM_RQE_QUEUES)) { 7450 return BCM_E_PARAM; 7451 } else { 7452 *start_hw_index = *end_hw_index = cosq; 7453 } 7454 return _BCM_BST_RV_OK; 7455 } else if (bid == bcmBstStatIdUCQueueGroup) { 7456 /* unicast queue group */ 7457 _BST_IF_ERROR_GOTO_EXIT(_bcm_td2_cosq_index_resolve(unit, 7458 gport, cosq, _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE_GROUP, 7459 NULL, start_hw_index, NULL)); 7460 *end_hw_index = *start_hw_index; 7461 return _BCM_BST_RV_OK; 7462 } 7463 7464 if (bid == bcmBstStatIdPortPool) { 7465 /* ingress pool */ 7466 _BST_IF_ERROR_GOTO_EXIT( 7467 _bcm_td2_cosq_ingress_sp_get(unit, gport, cosq, 7468 start_hw_index, end_hw_index)); 7469 *start_hw_index = ((mmu_port & 0x3f) * 4) + *start_hw_index; 7470 *end_hw_index = ((mmu_port & 0x3f) * 4) + *end_hw_index; 7471 } else if ((bid == bcmBstStatIdPriGroupShared) || 7472 (bid == bcmBstStatIdPriGroupHeadroom)) { 7473 /* ingress pool */ 7474 _BST_IF_ERROR_GOTO_EXIT( 7475 _bcm_td2_cosq_ingress_pg_get(unit, gport, cosq, 7476 start_hw_index, end_hw_index)); 7477 *start_hw_index = ((mmu_port & 0x3f) * 8) + *start_hw_index; 7478 *end_hw_index = ((mmu_port & 0x3f) * 8) + *end_hw_index; 7479 } else if (bid == bcmBstStatIdEgrPortPoolSharedUcast || 7480 bid == bcmBstStatIdEgrPortPoolSharedMcast) { 7481 /* egress pool */ 7482 _BST_IF_ERROR_GOTO_EXIT( 7483 _bcm_td2_cosq_egress_sp_get(unit, gport, cosq, 7484 start_hw_index, end_hw_index)); 7485 *start_hw_index = ((mmu_port & 0x3f) * 4) + *start_hw_index; 7486 *end_hw_index = ((mmu_port & 0x3f) * 4) + *end_hw_index; 7487 } else { 7488 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 7489 if (bid != bcmBstStatIdUcast) { 7490 goto error_exit; 7491 } 7492 _BST_IF_ERROR_GOTO_EXIT 7493 (_bcm_td2_cosq_node_get(unit, gport, 0, NULL, 7494 &local_port, NULL, &node)); 7495 if (!node) { 7496 goto error_exit; 7497 } 7498 *start_hw_index = *end_hw_index = node->hw_index; 7499 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 7500 if (bid != bcmBstStatIdMcast) { 7501 goto error_exit; 7502 } 7503 _BST_IF_ERROR_GOTO_EXIT 7504 (_bcm_td2_cosq_node_get(unit, gport, 0, NULL, 7505 &local_port, NULL, &node)); 7506 if (!node) { 7507 goto error_exit; 7508 } 7509 *start_hw_index = *end_hw_index = node->hw_index - 1480; 7510 } else { 7511 _BST_IF_ERROR_GOTO_EXIT(_bcm_td2_cosq_port_has_ets(unit, local_port)); 7512 7513 if (cosq < 0) { 7514 if (bid == bcmBstStatIdUcast) { 7515 _BST_IF_ERROR_GOTO_EXIT(_bcm_td2_cosq_index_resolve(unit, 7516 local_port, 0, _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE, 7517 NULL, start_hw_index, NULL)); 7518 7519 _BST_IF_ERROR_GOTO_EXIT(_bcm_td2_cosq_index_resolve(unit, 7520 local_port, NUM_COS(unit) - 1, 7521 _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE, 7522 NULL, end_hw_index, NULL)); 7523 7524 } else { 7525 _BST_IF_ERROR_GOTO_EXIT(_bcm_td2_cosq_index_resolve(unit, 7526 local_port, 0, _BCM_TD2_COSQ_INDEX_STYLE_MCAST_QUEUE, 7527 NULL, start_hw_index, NULL)); 7528 *start_hw_index -= 1480; 7529 7530 _BST_IF_ERROR_GOTO_EXIT(_bcm_td2_cosq_index_resolve(unit, 7531 local_port, NUM_COS(unit) - 1, 7532 _BCM_TD2_COSQ_INDEX_STYLE_MCAST_QUEUE, 7533 NULL, end_hw_index, NULL)); 7534 *end_hw_index -= 1480; 7535 } 7536 } else { 7537 if (bid == bcmBstStatIdUcast) { 7538 _BST_IF_ERROR_GOTO_EXIT(_bcm_td2_cosq_index_resolve(unit, 7539 local_port, cosq, _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE, 7540 NULL, start_hw_index, NULL)); 7541 *end_hw_index = *start_hw_index; 7542 } else { 7543 _BST_IF_ERROR_GOTO_EXIT(_bcm_td2_cosq_index_resolve(unit, 7544 local_port, cosq, _BCM_TD2_COSQ_INDEX_STYLE_MCAST_QUEUE, 7545 NULL, start_hw_index, NULL)); 7546 *start_hw_index -= 1480; 7547 *end_hw_index = *start_hw_index; 7548 } 7549 } /* if (cosq < 0) */ 7550 } /* if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { */ 7551 } /* if (bid == bcmBstStatIdPortPool) { */ 7552 7553 *bcm_rv = BCM_E_NONE; 7554 return _BCM_BST_RV_OK; 7555 7556 error_exit: 7557 *bcm_rv = BCM_E_PARAM; 7558 return _BCM_BST_RV_ERROR; 7559 } 7560 7561 STATIC int 7562 _bcm_td2_cosq_set_scheduler_states(int unit, bcm_port_t port, int busy) 7563 { 7564 int lvl, lvl_offset, hw_index, rv; 7565 _bcm_td2_mmu_info_t *mmu_info; 7566 _bcm_td2_pipe_resources_t *res; 7567 _bcm_td2_cosq_list_t *list; 7568 7569 mmu_info = _bcm_td2_mmu_info[unit]; 7570 res = _BCM_TD2_PRESOURCES(mmu_info, _BCM_TD2_PORT_TO_PIPE(unit, port)); 7571 7572 for (lvl = SOC_TD2_NODE_LVL_L0; lvl <= SOC_TD2_NODE_LVL_L1; lvl++) { 7573 lvl_offset = 0; 7574 7575 list = NULL; 7576 if (lvl == SOC_TD2_NODE_LVL_L0) { 7577 list = &res->l0_sched_list; 7578 } else if (lvl == SOC_TD2_NODE_LVL_L1) { 7579 list = &res->l1_sched_list; 7580 } 7581 7582 if (!list) { 7583 continue; 7584 } 7585 while ((rv = soc_td2_sched_hw_index_get(unit, port, lvl, 7586 lvl_offset, &hw_index)) == SOC_E_NONE) { 7587 if (busy) { 7588 _bcm_td2_node_index_set(list, hw_index, 1); 7589 } else { 7590 _bcm_td2_node_index_clear(list, hw_index, 1); 7591 } 7592 lvl_offset += 1; 7593 } 7594 } 7595 return BCM_E_NONE; 7596 } 7597 7598 STATIC int 7599 _bcm_td2_cosq_bst_map_resource_to_gport_cos(int unit, bcm_bst_stat_id_t bid, int port, 7600 int index, bcm_gport_t *gport, bcm_cos_t *cosq) 7601 { 7602 soc_info_t *si; 7603 _bcm_td2_cosq_node_t *node; 7604 _bcm_td2_mmu_info_t *mmu_info; 7605 _bcm_td2_pipe_resources_t *pres; 7606 int ii, pipe; 7607 int phy_port, mmu_port, hw_index; 7608 _bcm_bst_resource_info_t *resInfo; 7609 int pipe_offset = 0; 7610 7611 if (port == -2) { 7612 pipe = _TD2_YPIPE; 7613 } else { 7614 pipe = _TD2_XPIPE; 7615 } 7616 7617 resInfo = _BCM_BST_RESOURCE(unit, bid); 7618 pipe_offset = (resInfo->index_max / NUM_PIPE(unit)) * pipe; 7619 mmu_info = _bcm_td2_mmu_info[unit]; 7620 pres = _BCM_TD2_PRESOURCES(mmu_info, pipe); 7621 si = &SOC_INFO(unit); 7622 7623 switch (bid) { 7624 case bcmBstStatIdDevice: 7625 *gport = -1; 7626 *cosq = BCM_COS_INVALID; 7627 break; 7628 7629 case bcmBstStatIdIngPool: 7630 case bcmBstStatIdEgrPool: 7631 case bcmBstStatIdEgrMCastPool: 7632 case bcmBstStatIdRQEPool: 7633 *gport = -1; 7634 *cosq = index; 7635 break; 7636 7637 case bcmBstStatIdRQEQueue: 7638 *gport = -1; 7639 *cosq = index % _TD2_MMU_NUM_RQE_QUEUES; 7640 break; 7641 7642 case bcmBstStatIdUCQueueGroup: 7643 *gport = index; 7644 *cosq = -1; 7645 break; 7646 7647 case bcmBstStatIdPortPool: 7648 case bcmBstStatIdEgrPortPoolSharedUcast: 7649 case bcmBstStatIdEgrPortPoolSharedMcast: 7650 mmu_port= (index - pipe_offset)/4; 7651 if (pipe == _TD2_YPIPE) { 7652 mmu_port = mmu_port + 64; 7653 } 7654 phy_port = si->port_m2p_mapping[mmu_port]; 7655 *gport = si->port_p2l_mapping[phy_port]; 7656 *cosq = index % 4; 7657 break; 7658 7659 case bcmBstStatIdPriGroupHeadroom: 7660 case bcmBstStatIdPriGroupShared: 7661 mmu_port= (index - pipe_offset)/8; 7662 if (pipe == _TD2_YPIPE) { 7663 mmu_port = mmu_port + 64; 7664 } 7665 phy_port = si->port_m2p_mapping[mmu_port]; 7666 *gport = si->port_p2l_mapping[phy_port]; 7667 *cosq = index % 8; 7668 break; 7669 7670 case bcmBstStatIdMcast: 7671 pipe = _TD2_XPIPE; 7672 if (index >= 568) { 7673 pipe = _TD2_YPIPE; 7674 } 7675 hw_index = soc_td2_l2_hw_index(unit, index, 0); 7676 7677 if (mmu_info->ets_mode) { 7678 for (ii = 0; ii < _BCM_TD2_NUM_L2_MC_LEAVES; ii++) { 7679 node = &pres->p_mc_queue_node[ii]; 7680 if (node->in_use == TRUE) { 7681 phy_port = si->port_l2p_mapping[node->local_port]; 7682 mmu_port = si->port_p2m_mapping[phy_port]; 7683 7684 if (((pipe == _TD2_YPIPE) && mmu_port < 64) || 7685 ((pipe == _TD2_XPIPE) && mmu_port > 64)) { 7686 continue; 7687 } 7688 7689 if (node->hw_index == hw_index) { 7690 *gport = node->gport; 7691 *cosq = 0; 7692 break; 7693 } 7694 } 7695 } 7696 } else { 7697 int port_mc_base = 0; 7698 int port_num_mc = 0; 7699 PBMP_ALL_ITER(unit, port) { 7700 phy_port = si->port_l2p_mapping[port]; 7701 mmu_port = si->port_p2m_mapping[phy_port]; 7702 7703 if (((pipe == _TD2_YPIPE) && mmu_port < 64) || 7704 ((pipe == _TD2_XPIPE) && mmu_port > 64)) { 7705 continue; 7706 } 7707 if (IS_LB_PORT(unit, port)) { 7708 continue; 7709 } 7710 7711 port_num_mc = si->port_num_cosq[port]; 7712 port_mc_base = si->port_cosq_base[port]; 7713 7714 if ((index >= port_mc_base) && 7715 (index < port_mc_base + port_num_mc)) { 7716 *gport = port; 7717 *cosq = index - port_mc_base; 7718 break; 7719 } 7720 } 7721 } 7722 break; 7723 7724 case bcmBstStatIdUcast: 7725 pipe = _TD2_XPIPE; 7726 if (index >= 1480) { 7727 pipe = _TD2_YPIPE; 7728 } 7729 hw_index = soc_td2_l2_hw_index(unit, index, 1); 7730 7731 if (mmu_info->ets_mode) { 7732 for (ii = 0; ii < _BCM_TD2_NUM_L2_UC_LEAVES; ii++) { 7733 node = &pres->p_queue_node[ii]; 7734 if (node->in_use == TRUE) { 7735 phy_port = si->port_l2p_mapping[node->local_port]; 7736 mmu_port = si->port_p2m_mapping[phy_port]; 7737 7738 if (((pipe == _TD2_YPIPE) && mmu_port < 64) || 7739 ((pipe == _TD2_XPIPE) && mmu_port > 64)) { 7740 continue; 7741 } 7742 7743 if (node->hw_index == hw_index) { 7744 *gport = node->gport; 7745 *cosq = 0; 7746 break; 7747 } 7748 } 7749 } 7750 } else { 7751 int port_uc_base = 0; 7752 int port_num_uc = 0; 7753 PBMP_ALL_ITER(unit, port) { 7754 phy_port = si->port_l2p_mapping[port]; 7755 mmu_port = si->port_p2m_mapping[phy_port]; 7756 7757 if (((pipe == _TD2_YPIPE) && mmu_port < 64) || 7758 ((pipe == _TD2_XPIPE) && mmu_port > 64)) { 7759 continue; 7760 } 7761 if (IS_LB_PORT(unit, port)) { 7762 continue; 7763 } 7764 7765 port_num_uc = si->port_num_uc_cosq[port]; 7766 port_uc_base = si->port_uc_cosq_base[port]; 7767 7768 if ((index >= port_uc_base) && 7769 (index < port_uc_base + port_num_uc)) { 7770 *gport = port; 7771 *cosq = index - port_uc_base; 7772 break; 7773 } 7774 } 7775 } 7776 break; 7777 default: 7778 break; 7779 } 7780 7781 return BCM_E_NONE; 7782 } 7783 #ifdef BCM_TRIDENT2PLUS_SUPPORT 7784 /* 7785 * Function: 7786 * _bcm_td2p_update_base_queue_num 7787 * Purpose: 7788 * After flexing, update the base queue numbers in the _bcm_td2_mmu_info_t 7789 * structure and update the associated registers between base 7790 * queues and logical ports. 7791 * Parameters: 7792 * unit - (IN) unit number 7793 * nport - (IN) number of entries in flexport_data 7794 * ports - (IN) contains the ports for what new 7795 * ports are being added via flexport 7796 * and need queues updated so we only touch those. 7797 * Returns: 7798 * BCM_E_XXX 7799 */ 7800 STATIC int 7801 _bcm_td2p_update_base_queue_num(int unit, int nport, int * ports) 7802 { 7803 uint64 rval64; 7804 int qnum, pipe, i; 7805 soc_info_t *si; 7806 bcm_port_t port; 7807 _bcm_td2_mmu_info_t *mmu_info; 7808 #ifdef BCM_TRIDENT2PLUS_SUPPORT 7809 int phy_port, mmu_port; 7810 #endif 7811 7812 si = &SOC_INFO(unit); 7813 7814 COMPILER_64_ZERO(rval64); 7815 7816 /* This info needs to be updated when flexport occurs. 7817 Set this information based upon bcm_td2_cosq_init.*/ 7818 mmu_info = _bcm_td2_mmu_info[unit]; 7819 mmu_info->pipe_resources[_TD2_XPIPE].num_base_queues = 0; 7820 mmu_info->pipe_resources[_TD2_YPIPE].num_base_queues = 0; 7821 7822 /* assign queues to ports */ 7823 PBMP_ALL_ITER(unit, port) { 7824 if (IS_CPU_PORT(unit, port) || IS_LB_PORT(unit, port)) { 7825 continue; 7826 } 7827 pipe = _BCM_TD2_PORT_TO_PIPE(unit, port); 7828 mmu_info->port_info[port].resources = &mmu_info->pipe_resources[pipe]; 7829 #ifdef BCM_TRIDENT2PLUS_SUPPORT 7830 /* This needs to be done for Trident 2+ since queues are no longer 7831 based upon a running number but are instead indexed by MMU Port 7832 number. Example: If MMU port 0 and 1 are using VBS, they'll only 7833 use queues 0-9 and 10-19. If MMU port 2 is LLS, it will start 7834 at queue 24 rather than 20. We need to add this total to 7835 port_num_uc_cosq so that the device won't think it has overrun 7836 its queues. */ 7837 if (SOC_IS_TD2P_TT2P(unit)) { 7838 phy_port = si->port_l2p_mapping[port]; 7839 mmu_port = si->port_p2m_mapping[phy_port]; 7840 7841 /* Make sure num_base_queues accounts for not only the port's 7842 base queue, but all the queues assigned to it as well */ 7843 if (mmu_info->port_info[port].resources->num_base_queues < 7844 ((mmu_port%64) + 1) * si->port_num_uc_cosq[port]) { 7845 mmu_info->port_info[port].resources->num_base_queues = 7846 ((mmu_port%64) + 1) * si->port_num_uc_cosq[port]; 7847 } 7848 } else 7849 #endif 7850 { 7851 mmu_info->port_info[port].resources->num_base_queues += 7852 si->port_num_uc_cosq[port]; 7853 } 7854 7855 /* iterate through the newly flexed ports and only update those. */ 7856 for (i = 0; i < nport; i++) { 7857 if (port == ports[i]) { 7858 break; 7859 } 7860 } 7861 if (i != nport) { 7862 mmu_info->port_info[port].mc_base = si->port_cosq_base[port]; 7863 mmu_info->port_info[port].mc_limit = si->port_cosq_base[port] + 7864 si->port_num_cosq[port]; 7865 7866 mmu_info->port_info[port].uc_base = si->port_uc_cosq_base[port]; 7867 mmu_info->port_info[port].uc_limit = si->port_uc_cosq_base[port] + 7868 si->port_num_uc_cosq[port]; 7869 7870 if (!SOC_WARM_BOOT(unit)) { 7871 COMPILER_64_ZERO(rval64); 7872 qnum = soc_td2_logical_qnum_hw_qnum(unit, port, 7873 si->port_uc_cosq_base[port], 1); 7874 soc_reg64_field32_set(unit, ING_COS_MODE_64r, 7875 &rval64, BASE_QUEUE_NUM_0f, qnum); 7876 soc_reg64_field32_set(unit, ING_COS_MODE_64r, 7877 &rval64, BASE_QUEUE_NUM_1f, qnum); 7878 BCM_IF_ERROR_RETURN(soc_reg_set(unit, ING_COS_MODE_64r, port, 0, rval64)); 7879 } 7880 } 7881 } 7882 7883 return BCM_E_NONE; 7884 } 7885 7886 /* 7887 * Function: 7888 * _bcm_td2p_set_flexport_port_q_cb 7889 * Purpose: 7890 * Set the callback for updating the logical port to queue association. 7891 * Parameters: 7892 * unit - unit number 7893 * Returns: 7894 * BCM_E_XXX 7895 */ 7896 7897 STATIC int 7898 _bcm_td2p_set_flexport_port_q_cb(int unit) 7899 { 7900 BCM_IF_ERROR_RETURN( 7901 soc_td2p_set_flexport_port_q_callback(unit, 7902 _bcm_td2p_update_base_queue_num)); 7903 return BCM_E_NONE; 7904 } 7905 7906 /* 7907 * Function: 7908 * _bcm_td2p_set_ets_mode_q_cb 7909 * Purpose: 7910 * Set the callback for checking ets mode 7911 * Parameters: 7912 * unit - unit number 7913 * Returns: 7914 * BCM_E_XXX 7915 */ 7916 7917 STATIC int 7918 _bcm_td2p_set_ets_mode_q_cb(int unit) 7919 { 7920 BCM_IF_ERROR_RETURN( 7921 soc_td2p_set_ets_mode_q_callback(unit, 7922 _bcm_td2_cosq_port_has_ets)); 7923 return BCM_E_NONE; 7924 } 7925 #endif 7926 7927 /* 7928 * Function: 7929 * bcm_td2_cosq_init 7930 * Purpose: 7931 * Initialize (clear) all COS schedule/mapping state. 7932 * Parameters: 7933 * unit - unit number 7934 * Returns: 7935 * BCM_E_XXX 7936 */ 7937 int 7938 bcm_td2_cosq_init(int unit) 7939 { 7940 int numq, alloc_size, phy_port, mmu_port, ii, index; 7941 soc_info_t *si; 7942 bcm_port_t port; 7943 soc_reg_t mem; 7944 soc_reg_t reg; 7945 static soc_mem_t wred_mems[2][6] = { 7946 { 7947 MMU_WRED_DROP_CURVE_PROFILE_0_X_PIPEm, 7948 MMU_WRED_DROP_CURVE_PROFILE_1_X_PIPEm, 7949 MMU_WRED_DROP_CURVE_PROFILE_2_X_PIPEm, 7950 MMU_WRED_DROP_CURVE_PROFILE_3_X_PIPEm, 7951 MMU_WRED_DROP_CURVE_PROFILE_4_X_PIPEm, 7952 MMU_WRED_DROP_CURVE_PROFILE_5_X_PIPEm 7953 }, 7954 { 7955 MMU_WRED_DROP_CURVE_PROFILE_0_Y_PIPEm, 7956 MMU_WRED_DROP_CURVE_PROFILE_1_Y_PIPEm, 7957 MMU_WRED_DROP_CURVE_PROFILE_2_Y_PIPEm, 7958 MMU_WRED_DROP_CURVE_PROFILE_3_Y_PIPEm, 7959 MMU_WRED_DROP_CURVE_PROFILE_4_Y_PIPEm, 7960 MMU_WRED_DROP_CURVE_PROFILE_5_Y_PIPEm 7961 } 7962 }; 7963 7964 int entry_words[6], pipe; 7965 mmu_wred_drop_curve_profile_0_entry_t entry_tcp_green; 7966 mmu_wred_drop_curve_profile_1_entry_t entry_tcp_yellow; 7967 mmu_wred_drop_curve_profile_2_entry_t entry_tcp_red; 7968 mmu_wred_drop_curve_profile_3_entry_t entry_nontcp_green; 7969 mmu_wred_drop_curve_profile_4_entry_t entry_nontcp_yellow; 7970 mmu_wred_drop_curve_profile_5_entry_t entry_nontcp_red; 7971 void *entries[6]; 7972 uint32 profile_index; 7973 _bcm_td2_mmu_info_t *mmu_info; 7974 int i, qnum, wred_prof_count, endpoint_num; 7975 _bcm_bst_device_handlers_t bst_callbks; 7976 _bcm_td2_pipe_resources_t *pres; 7977 uint64 rval64; 7978 _bcm_td2_cosq_list_t *list = NULL; 7979 7980 if (!SOC_WARM_BOOT(unit)) { /* Cold Boot */ 7981 BCM_IF_ERROR_RETURN (bcm_td2_cosq_detach(unit, 0)); 7982 } 7983 7984 si = &SOC_INFO(unit); 7985 7986 numq = soc_property_get(unit, spn_BCM_NUM_COS, BCM_COS_DEFAULT); 7987 7988 if (numq < 1) { 7989 numq = 1; 7990 } else if (numq > 8) { 7991 numq = 8; 7992 } 7993 7994 NUM_COS(unit) = numq; 7995 soc_trident2_fc_map_shadow_create(unit); 7996 7997 7998 /* Create profile for PORT_COS_MAP table */ 7999 if (_bcm_td2_cos_map_profile[unit] == NULL) { 8000 _bcm_td2_cos_map_profile[unit] = sal_alloc(sizeof(soc_profile_mem_t), 8001 "COS_MAP Profile Mem"); 8002 if (_bcm_td2_cos_map_profile[unit] == NULL) { 8003 return BCM_E_MEMORY; 8004 } 8005 soc_profile_mem_t_init(_bcm_td2_cos_map_profile[unit]); 8006 } 8007 mem = PORT_COS_MAPm; 8008 entry_words[0] = sizeof(port_cos_map_entry_t) / sizeof(uint32); 8009 BCM_IF_ERROR_RETURN(soc_profile_mem_create(unit, &mem, entry_words, 1, 8010 _bcm_td2_cos_map_profile[unit])); 8011 8012 /* Create profile for IFP_COS_MAP table. */ 8013 if (_bcm_td2_ifp_cos_map_profile[unit] == NULL) { 8014 _bcm_td2_ifp_cos_map_profile[unit] 8015 = sal_alloc(sizeof(soc_profile_mem_t), "IFP_COS_MAP Profile Mem"); 8016 if (_bcm_td2_ifp_cos_map_profile[unit] == NULL) { 8017 return BCM_E_MEMORY; 8018 } 8019 soc_profile_mem_t_init(_bcm_td2_ifp_cos_map_profile[unit]); 8020 } 8021 mem = IFP_COS_MAPm; 8022 entry_words[0] = sizeof(ifp_cos_map_entry_t) / sizeof(uint32); 8023 SOC_IF_ERROR_RETURN 8024 (soc_profile_mem_create(unit, &mem, entry_words, 1, 8025 _bcm_td2_ifp_cos_map_profile[unit])); 8026 8027 /* Create profile for SERVICE_COS_MAP table */ 8028 if (_bcm_td2_service_cos_map_profile[unit] == NULL) { 8029 alloc_size = sizeof(soc_profile_mem_t); 8030 _bcm_td2_service_cos_map_profile[unit] = sal_alloc(alloc_size, 8031 "SERVICE_COS_MAP"); 8032 if (_bcm_td2_service_cos_map_profile[unit] == NULL) { 8033 return BCM_E_MEMORY; 8034 } 8035 soc_profile_mem_t_init(_bcm_td2_service_cos_map_profile[unit]); 8036 } 8037 mem = SERVICE_COS_MAPm; 8038 entry_words[0] = sizeof(service_cos_map_entry_t) / sizeof(uint32); 8039 SOC_IF_ERROR_RETURN( 8040 soc_profile_mem_create(unit, &mem, entry_words, 1, 8041 _bcm_td2_service_cos_map_profile[unit])); 8042 8043 /* Create profile for SERVICE_PORT_MAP table */ 8044 if (_bcm_td2_service_port_map_profile[unit] == NULL) { 8045 alloc_size = sizeof(soc_profile_mem_t); 8046 _bcm_td2_service_port_map_profile[unit] = sal_alloc(alloc_size, 8047 "SERVICE_PORT_MAP"); 8048 if (_bcm_td2_service_port_map_profile[unit] == NULL) { 8049 return BCM_E_MEMORY; 8050 } 8051 soc_profile_mem_t_init(_bcm_td2_service_port_map_profile[unit]); 8052 } 8053 8054 mem = SERVICE_PORT_MAPm; 8055 entry_words[0] = sizeof(service_port_map_entry_t) / sizeof(uint32); 8056 SOC_IF_ERROR_RETURN( 8057 soc_profile_mem_create(unit, &mem, entry_words, 1, 8058 _bcm_td2_service_port_map_profile[unit])); 8059 8060 /* Create profile for MMU_QCN_SITB table */ 8061 if (_bcm_td2_sample_int_profile[unit] == NULL) { 8062 _bcm_td2_sample_int_profile[unit] = 8063 sal_alloc(sizeof(soc_profile_mem_t), "QCN sample Int Profile Mem"); 8064 if (_bcm_td2_sample_int_profile[unit] == NULL) { 8065 return BCM_E_MEMORY; 8066 } 8067 soc_profile_mem_t_init(_bcm_td2_sample_int_profile[unit]); 8068 } 8069 mem = MMU_QCN_SITBm; 8070 entry_words[0] = sizeof(mmu_qcn_sitb_entry_t) / sizeof(uint32); 8071 BCM_IF_ERROR_RETURN 8072 (soc_profile_mem_create(unit, &mem, entry_words, 1, 8073 _bcm_td2_sample_int_profile[unit])); 8074 8075 /* Create profile for MMU_QCN_CPQ_SEQ register */ 8076 if (_bcm_td2_feedback_profile[unit] == NULL) { 8077 _bcm_td2_feedback_profile[unit] = 8078 sal_alloc(sizeof(soc_profile_reg_t), "QCN Feedback Profile Reg"); 8079 if (_bcm_td2_feedback_profile[unit] == NULL) { 8080 return BCM_E_MEMORY; 8081 } 8082 soc_profile_reg_t_init(_bcm_td2_feedback_profile[unit]); 8083 } 8084 reg = MMU_QCN_CPQ_SEQr; 8085 BCM_IF_ERROR_RETURN 8086 (soc_profile_reg_create(unit, ®, 1, 8087 _bcm_td2_feedback_profile[unit])); 8088 8089 /* Create profile for PRIO2COS_LLFC register */ 8090 if (_bcm_td2_llfc_profile[unit] == NULL) { 8091 _bcm_td2_llfc_profile[unit] = 8092 sal_alloc(sizeof(soc_profile_reg_t), "PRIO2COS_LLFC Profile Reg"); 8093 if (_bcm_td2_llfc_profile[unit] == NULL) { 8094 return BCM_E_MEMORY; 8095 } 8096 soc_profile_reg_t_init(_bcm_td2_llfc_profile[unit]); 8097 } 8098 reg = PRIO2COS_PROFILEr; 8099 BCM_IF_ERROR_RETURN 8100 (soc_profile_reg_create(unit, ®, 1, _bcm_td2_llfc_profile[unit])); 8101 8102 /* Create profile for VOQ_MOD_MAP table */ 8103 if (_bcm_td2_voq_port_map_profile[unit] == NULL) { 8104 _bcm_td2_voq_port_map_profile[unit] = sal_alloc(sizeof(soc_profile_mem_t), 8105 "VOQ_PORT_MAP Profile Mem"); 8106 if (_bcm_td2_voq_port_map_profile[unit] == NULL) { 8107 return BCM_E_MEMORY; 8108 } 8109 soc_profile_mem_t_init(_bcm_td2_voq_port_map_profile[unit]); 8110 } 8111 mem = VOQ_PORT_MAPm; 8112 entry_words[0] = sizeof(voq_port_map_entry_t) / sizeof(uint32); 8113 BCM_IF_ERROR_RETURN(soc_profile_mem_create(unit, &mem, entry_words, 1, 8114 _bcm_td2_voq_port_map_profile[unit])); 8115 8116 for (pipe = _TD2_XPIPE; pipe <= _TD2_YPIPE; pipe++) { 8117 /* Create profile for MMU_WRED_DROP_CURVE_PROFILE_x tables */ 8118 if (_bcm_td2_wred_profile[pipe][unit] == NULL) { 8119 _bcm_td2_wred_profile[pipe][unit] = 8120 sal_alloc(sizeof(soc_profile_mem_t), "WRED Profile Mem"); 8121 if (_bcm_td2_wred_profile[pipe][unit] == NULL) { 8122 return BCM_E_MEMORY; 8123 } 8124 soc_profile_mem_t_init(_bcm_td2_wred_profile[pipe][unit]); 8125 } 8126 8127 entry_words[0] = 8128 sizeof(mmu_wred_drop_curve_profile_0_entry_t) / sizeof(uint32); 8129 entry_words[1] = 8130 sizeof(mmu_wred_drop_curve_profile_1_entry_t) / sizeof(uint32); 8131 entry_words[2] = 8132 sizeof(mmu_wred_drop_curve_profile_2_entry_t) / sizeof(uint32); 8133 entry_words[3] = 8134 sizeof(mmu_wred_drop_curve_profile_3_entry_t) / sizeof(uint32); 8135 entry_words[4] = 8136 sizeof(mmu_wred_drop_curve_profile_4_entry_t) / sizeof(uint32); 8137 entry_words[5] = 8138 sizeof(mmu_wred_drop_curve_profile_5_entry_t) / sizeof(uint32); 8139 BCM_IF_ERROR_RETURN 8140 (soc_profile_mem_create(unit, wred_mems[pipe], entry_words, 6, 8141 _bcm_td2_wred_profile[pipe][unit])); 8142 } 8143 8144 alloc_size = sizeof(_bcm_td2_mmu_info_t) * 1; 8145 if (_bcm_td2_mmu_info[unit] == NULL) { 8146 _bcm_td2_mmu_info[unit] = 8147 sal_alloc(alloc_size, "_bcm_td2_mmu_info"); 8148 8149 if (_bcm_td2_mmu_info[unit] == NULL) { 8150 return BCM_E_MEMORY; 8151 } 8152 8153 sal_memset(_bcm_td2_mmu_info[unit], 0, alloc_size); 8154 } 8155 8156 mmu_info = _bcm_td2_mmu_info[unit]; 8157 mmu_info->ets_mode = 0; 8158 mmu_info->pipe_resources[_TD2_XPIPE].num_base_queues = 0; 8159 mmu_info->pipe_resources[_TD2_YPIPE].num_base_queues = 0; 8160 8161 /* assign queues to ports */ 8162 PBMP_ALL_ITER(unit, port) { 8163 pipe = _BCM_TD2_PORT_TO_PIPE(unit, port); 8164 mmu_info->port_info[port].resources = &mmu_info->pipe_resources[pipe]; 8165 mmu_info->port_info[port].mc_base = si->port_cosq_base[port]; 8166 mmu_info->port_info[port].mc_limit = si->port_cosq_base[port] + 8167 si->port_num_cosq[port]; 8168 8169 mmu_info->port_info[port].uc_base = si->port_uc_cosq_base[port]; 8170 mmu_info->port_info[port].uc_limit = si->port_uc_cosq_base[port] + 8171 si->port_num_uc_cosq[port]; 8172 #ifdef BCM_TRIDENT2PLUS_SUPPORT 8173 /* This needs to be done for Trident 2+ since queues are no longer 8174 based upon a running number but are instead indexed by MMU Port 8175 number. Example: If MMU port 0 and 1 are using VBS, they'll only 8176 use queues 0-9 and 10-19. If MMU port 2 is LLS, it will start 8177 at queue 24 rather than 20. We need to add this total to 8178 port_num_uc_cosq so that the device won't think it has overrun 8179 its queues. */ 8180 if (SOC_IS_TD2P_TT2P(unit)) { 8181 phy_port = si->port_l2p_mapping[port]; 8182 mmu_port = si->port_p2m_mapping[phy_port]; 8183 8184 if (mmu_info->port_info[port].resources->num_base_queues < 8185 (mmu_port%64) * si->port_num_uc_cosq[port]) { 8186 mmu_info->port_info[port].resources->num_base_queues = 8187 (mmu_port%64) * si->port_num_uc_cosq[port]; 8188 } 8189 8190 mmu_info->port_info[port].resources->num_base_queues += 8191 si->port_num_uc_cosq[port]; 8192 } else 8193 #endif 8194 { 8195 mmu_info->port_info[port].resources->num_base_queues += 8196 si->port_num_uc_cosq[port]; 8197 } 8198 if (!SOC_WARM_BOOT(unit)) { 8199 COMPILER_64_ZERO(rval64); 8200 qnum = soc_td2_logical_qnum_hw_qnum(unit, port, 8201 si->port_uc_cosq_base[port], 1); 8202 soc_reg64_field32_set(unit, ING_COS_MODE_64r, 8203 &rval64, BASE_QUEUE_NUM_0f, qnum); 8204 soc_reg64_field32_set(unit, ING_COS_MODE_64r, 8205 &rval64, BASE_QUEUE_NUM_1f, qnum); 8206 BCM_IF_ERROR_RETURN(soc_reg_set(unit, ING_COS_MODE_64r, port, 0, rval64)); 8207 } 8208 } 8209 #ifdef BCM_TRIDENT2PLUS_SUPPORT 8210 if (SOC_IS_TD2P_TT2P(unit)) { 8211 BCM_IF_ERROR_RETURN(_bcm_td2p_set_flexport_port_q_cb(unit)); 8212 BCM_IF_ERROR_RETURN(_bcm_td2p_set_ets_mode_q_cb(unit)); 8213 } 8214 #endif 8215 8216 for (i = 0; i < si->num_cpu_cosq; i++) { 8217 if (_bcm_td2_cosq_cpu_cosq_config[unit][i] == NULL) { 8218 _bcm_td2_cosq_cpu_cosq_config[unit][i] = 8219 sal_alloc(sizeof(_bcm_td2_cosq_cpu_cosq_config_t), "CPU Cosq Config"); 8220 8221 if (_bcm_td2_cosq_cpu_cosq_config[unit][i] == NULL) { 8222 return BCM_E_MEMORY; 8223 } 8224 sal_memset(_bcm_td2_cosq_cpu_cosq_config[unit][i], 0, 8225 sizeof(_bcm_td2_cosq_cpu_cosq_config_t)); 8226 _bcm_td2_cosq_cpu_cosq_config[unit][i]->enable = 1; 8227 } 8228 } 8229 8230 if (soc_feature(unit, soc_feature_endpoint_queuing)) { 8231 if (_bcm_td2_endpoint_queuing_info[unit] == NULL) { 8232 _bcm_td2_endpoint_queuing_info[unit] = 8233 sal_alloc(sizeof(_bcm_td2_endpoint_queuing_info_t), 8234 "Endpoint Queuing Info"); 8235 if (_bcm_td2_endpoint_queuing_info[unit] == NULL) { 8236 return BCM_E_MEMORY; 8237 } 8238 } 8239 sal_memset(_bcm_td2_endpoint_queuing_info[unit], 0, 8240 sizeof(_bcm_td2_endpoint_queuing_info_t)); 8241 8242 /* The maximum number of endpoints is limited to 2^14, 8243 * since the endpoint ID field is limited to 14 bits in 8244 * Higig2 header. 8245 */ 8246 endpoint_num = (1U << 14); 8247 _bcm_td2_endpoint_queuing_info[unit]->ptr_array = sal_alloc( 8248 endpoint_num * sizeof(_bcm_td2_endpoint_t *), 8249 "Endpoint Pointer Array"); 8250 if (_bcm_td2_endpoint_queuing_info[unit]->ptr_array == NULL) { 8251 return BCM_E_MEMORY; 8252 } 8253 sal_memset(_bcm_td2_endpoint_queuing_info[unit]->ptr_array, 0, 8254 endpoint_num * sizeof(_bcm_td2_endpoint_t *)); 8255 _BCM_TD2_NUM_ENDPOINT(unit) = endpoint_num; 8256 /* Reserve endpoint 0 */ 8257 _bcm_td2_endpoint_queuing_info[unit]->ptr_array[0] = 8258 sal_alloc(sizeof(_bcm_td2_endpoint_t), "Endpoint Info"); 8259 if (_bcm_td2_endpoint_queuing_info[unit]->ptr_array[0] == NULL) { 8260 return BCM_E_MEMORY; 8261 } 8262 8263 sal_memset(_bcm_td2_endpoint_queuing_info[unit]->ptr_array[0], 0, 8264 sizeof(_bcm_td2_endpoint_t)); 8265 8266 _bcm_td2_endpoint_queuing_info[unit]->cos_map_profile = sal_alloc( 8267 sizeof(soc_profile_mem_t), "Priority to CoS Map Profile"); 8268 if (_bcm_td2_endpoint_queuing_info[unit]->cos_map_profile == NULL) { 8269 return BCM_E_MEMORY; 8270 } 8271 soc_profile_mem_t_init 8272 (_bcm_td2_endpoint_queuing_info[unit]->cos_map_profile); 8273 mem = ENDPOINT_COS_MAPm; 8274 entry_words[0] = sizeof(endpoint_cos_map_entry_t) / sizeof(uint32); 8275 SOC_IF_ERROR_RETURN(soc_profile_mem_create(unit, &mem, entry_words, 1, 8276 _bcm_td2_endpoint_queuing_info[unit]->cos_map_profile)); 8277 } 8278 8279 for (pipe = _TD2_XPIPE; pipe <= _TD2_YPIPE; pipe++) { 8280 pres = _BCM_TD2_PRESOURCES(mmu_info, pipe); 8281 pres->p_queue_node = &mmu_info->queue_node[0]; 8282 pres->p_mc_queue_node = &mmu_info->mc_queue_node[0]; 8283 pres->ext_qlist.count = _BCM_TD2_NUM_L2_UC_LEAVES_PER_PIPE; 8284 pres->ext_qlist.bits = _bcm_td2_cosq_alloc_clear( 8285 pres->ext_qlist.bits, 8286 SHR_BITALLOCSIZE(pres->ext_qlist.count), 8287 "ext_qlist"); 8288 if (pres->ext_qlist.bits == NULL) { 8289 _bcm_td2_cosq_free_memory(mmu_info); 8290 return BCM_E_MEMORY; 8291 } 8292 8293 pres->l0_sched_list.count = 8294 soc_mem_index_count(unit, ES_PIPE0_LLS_L0_PARENTm); 8295 pres->l0_sched_list.bits = _bcm_td2_cosq_alloc_clear( 8296 pres->l0_sched_list.bits, 8297 SHR_BITALLOCSIZE(pres->l0_sched_list.count), 8298 "l0_sched_list"); 8299 if (pres->l0_sched_list.bits == NULL) { 8300 _bcm_td2_cosq_free_memory(mmu_info); 8301 return BCM_E_MEMORY; 8302 } 8303 8304 pres->l1_sched_list.count = 8305 soc_mem_index_count(unit, ES_PIPE0_LLS_L1_PARENTm); 8306 pres->l1_sched_list.bits = _bcm_td2_cosq_alloc_clear( 8307 pres->l1_sched_list.bits, 8308 SHR_BITALLOCSIZE(pres->l1_sched_list.count), 8309 "l1_sched_list"); 8310 if (pres->l1_sched_list.bits == NULL) { 8311 _bcm_td2_cosq_free_memory(mmu_info); 8312 return BCM_E_MEMORY; 8313 } 8314 } 8315 8316 for (i = 0; i < _BCM_TD2_NUM_TOTAL_SCHEDULERS; i++) { 8317 _BCM_TD2_COSQ_LIST_NODE_INIT(mmu_info->sched_node, i); 8318 } 8319 8320 for (i = 0; i < _BCM_TD2_NUM_L2_UC_LEAVES; i++) { 8321 _BCM_TD2_COSQ_LIST_NODE_INIT(mmu_info->queue_node, i); 8322 } 8323 8324 for (i = 0; i < _BCM_TD2_NUM_L2_MC_LEAVES; i++) { 8325 _BCM_TD2_COSQ_LIST_NODE_INIT(mmu_info->mc_queue_node, i); 8326 } 8327 8328 for (pipe = _TD2_XPIPE; pipe <= _TD2_YPIPE; pipe++) { 8329 pres = _BCM_TD2_PRESOURCES(mmu_info, pipe); 8330 for (i = SOC_TD2_NODE_LVL_L1; i <= SOC_TD2_NODE_LVL_L2; i++) { 8331 index = _soc_td2_invalid_parent_index(unit, i); 8332 if (i == SOC_TD2_NODE_LVL_L1) { 8333 list = &pres->l0_sched_list; 8334 } else if (i == SOC_TD2_NODE_LVL_L2) { 8335 list = &pres->l1_sched_list; 8336 } else { 8337 continue; 8338 } 8339 if (index >= 0) { 8340 _bcm_td2_node_index_set(list, index, 1); 8341 } 8342 } 8343 } 8344 8345 /* reserve the resources for HSP ports */ 8346 PBMP_ALL_ITER(unit, port) { 8347 if (IS_TD2_HSP_PORT(unit, port)) { 8348 phy_port = si->port_l2p_mapping[port]; 8349 mmu_port = si->port_p2m_mapping[phy_port]; 8350 8351 pres = _BCM_TD2_PRESOURCES(mmu_info, (mmu_port >= 64) ? 1 : 0); 8352 _bcm_td2_node_index_set(&pres->l0_sched_list, (mmu_port & 0x3f)*5, 5); 8353 _bcm_td2_node_index_set(&pres->l1_sched_list, (mmu_port & 0x3f)*10, 10); 8354 } 8355 } 8356 8357 sal_memset(&bst_callbks, 0, sizeof(_bcm_bst_device_handlers_t)); 8358 bst_callbks.resolve_index = &_bcm_td2_bst_index_resolve; 8359 bst_callbks.reverse_resolve_index = &_bcm_td2_cosq_bst_map_resource_to_gport_cos; 8360 BCM_IF_ERROR_RETURN(_bcm_bst_attach(unit, &bst_callbks)); 8361 8362 #ifdef BCM_WARM_BOOT_SUPPORT 8363 if (SOC_WARM_BOOT(unit)) { 8364 return bcm_td2_cosq_reinit(unit); 8365 } else { 8366 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_wb_alloc(unit)); 8367 } 8368 #endif /* BCM_WARM_BOOT_SUPPORT */ 8369 8370 /* Add default entries for PORT_COS_MAP memory profile */ 8371 BCM_IF_ERROR_RETURN(bcm_td2_cosq_config_set(unit, numq)); 8372 8373 for (pipe = _TD2_XPIPE; pipe <= _TD2_YPIPE; pipe++) { 8374 /* Add default entries for MMU_WRED_DROP_CURVE_PROFILE_x memory profile */ 8375 sal_memset(&entry_tcp_green, 0, sizeof(entry_tcp_green)); 8376 sal_memset(&entry_tcp_yellow,0, sizeof(entry_tcp_yellow)); 8377 sal_memset(&entry_tcp_red, 0, sizeof(entry_tcp_red)); 8378 sal_memset(&entry_nontcp_green, 0, sizeof(entry_nontcp_green)); 8379 sal_memset(&entry_nontcp_yellow, 0, sizeof(entry_nontcp_yellow)); 8380 sal_memset(&entry_nontcp_red, 0, sizeof(entry_nontcp_red)); 8381 entries[0] = &entry_tcp_green; 8382 entries[1] = &entry_tcp_yellow; 8383 entries[2] = &entry_tcp_red; 8384 entries[3] = &entry_nontcp_green; 8385 entries[4] = &entry_nontcp_yellow; 8386 entries[5] = &entry_nontcp_red; 8387 for (ii = 0; ii < 6; ii++) { 8388 soc_mem_field32_set(unit, wred_mems[pipe][ii], entries[ii], 8389 MIN_THDf, 0x1ffff); 8390 soc_mem_field32_set(unit, wred_mems[pipe][ii], entries[ii], 8391 MAX_THDf, 0x1ffff); 8392 } 8393 profile_index = 0xffffffff; 8394 wred_prof_count = soc_mem_index_count(unit, MMU_WRED_CONFIG_X_PIPEm); 8395 while(wred_prof_count) { 8396 if (profile_index == 0xffffffff) { 8397 BCM_IF_ERROR_RETURN 8398 (soc_profile_mem_add(unit, 8399 _bcm_td2_wred_profile[pipe][unit], 8400 entries, 1, &profile_index)); 8401 } else { 8402 BCM_IF_ERROR_RETURN 8403 (soc_profile_mem_reference(unit, 8404 _bcm_td2_wred_profile[pipe][unit], 8405 profile_index, 0)); 8406 } 8407 wred_prof_count -= 1; 8408 } 8409 } 8410 8411 /* Add default entries for PRIO2COS_PROFILE register profile */ 8412 PBMP_PORT_ITER(unit, port) { 8413 BCM_IF_ERROR_RETURN 8414 (bcm_td2_cosq_default_llfc_profile_attach(unit, port)); 8415 } 8416 8417 if (!mmu_info->curr_shared_limit) { 8418 BCM_IF_ERROR_RETURN(soc_td2_mmu_get_shared_size(unit, 8419 &mmu_info->curr_shared_limit)); 8420 } 8421 /* Starting the curr_merger_index from 2, 8422 * since 0 is configured in all the FC_MAP_TBL2 by default, 8423 * so it might effect the traffic of other queues 8424 */ 8425 mmu_info->curr_merger_index = 2; 8426 /* Reset shapers. */ 8427 BCM_IF_ERROR_RETURN(_bcm_td2_lls_shapers_init(unit)); 8428 8429 /* reset time_domain ref_count so that entries can be added upon 8430 * rc */ 8431 time_domain[0].ref_count = 3640; 8432 time_domain[1].ref_count = 0; 8433 time_domain[2].ref_count = 0; 8434 time_domain[3].ref_count = 0; 8435 8436 return BCM_E_NONE; 8437 } 8438 8439 8440 /* 8441 * Function: 8442 * bcm_td2_cosq_config_get 8443 * Purpose: 8444 * Get the number of cos queues 8445 * Parameters: 8446 * unit - unit number 8447 * numq - (Output) number of cosq 8448 * Returns: 8449 * BCM_E_XXX 8450 */ 8451 int 8452 bcm_td2_cosq_config_get(int unit, int *numq) 8453 { 8454 if (numq != NULL) { 8455 *numq = _TD2_NUM_COS(unit); 8456 } 8457 8458 return BCM_E_NONE; 8459 } 8460 8461 /* 8462 * Function: 8463 * _bcm_td2_cosq_mapping_set 8464 * Purpose: 8465 * Set COS queue for the specified priority of an ingress port 8466 * Parameters: 8467 * unit - (IN) unit number 8468 * ing_port - (IN) ingress port 8469 * gport - (IN) queue group GPORT identifier 8470 * priority - (IN) priority value to map 8471 * flags - (IN) BCM_COSQ_GPORT_XXX_QUEUE_GROUP 8472 * gport - (IN) queue group GPORT identifier 8473 * cosq - (IN) COS queue number 8474 * Returns: 8475 * BCM_E_XXX 8476 */ 8477 STATIC int 8478 _bcm_td2_cosq_mapping_set(int unit, bcm_port_t ing_port, bcm_cos_t priority, 8479 uint32 flags, bcm_gport_t gport, bcm_cos_queue_t cosq) 8480 { 8481 bcm_port_t local_port, outport = -1; 8482 bcm_cos_queue_t hw_cosq; 8483 soc_field_t field = INVALIDf, field2 = INVALIDf, field3 = INVALIDf; 8484 cos_map_sel_entry_t cos_map_sel_entry; 8485 port_cos_map_entry_t cos_map_entries[16]; 8486 void *entries[1]; 8487 uint32 old_index, new_index; 8488 voq_cos_map_entry_t voq_cos_map; 8489 _bcm_td2_cosq_node_t *node; 8490 _bcm_td2_mmu_info_t *mmu_info; 8491 _bcm_td2_pipe_resources_t *res = NULL; 8492 int rv, pipe = -1; 8493 int valid = 0; 8494 8495 if (priority < 0 || priority >= 16) { 8496 return BCM_E_PARAM; 8497 } 8498 8499 BCM_IF_ERROR_RETURN 8500 (_bcm_td2_cosq_localport_resolve(unit, ing_port, &local_port)); 8501 8502 if (gport != -1) { 8503 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_localport_resolve(unit, gport, &outport)); 8504 mmu_info = _bcm_td2_mmu_info[unit]; 8505 pipe = _BCM_TD2_PORT_TO_PIPE(unit, outport); 8506 res = _BCM_TD2_PRESOURCES(mmu_info, pipe); 8507 } 8508 8509 switch (flags) { 8510 case BCM_COSQ_GPORT_UCAST_QUEUE_GROUP: 8511 if (gport == -1) { 8512 hw_cosq = cosq; 8513 } else { 8514 if (!BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 8515 return BCM_E_PARAM; 8516 } 8517 BCM_IF_ERROR_RETURN 8518 (_bcm_td2_cosq_index_resolve 8519 (unit, gport, cosq, _BCM_TD2_COSQ_INDEX_STYLE_COS, 8520 NULL, &hw_cosq, NULL)); 8521 8522 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 8523 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_node_get(unit, gport, cosq, NULL, 8524 NULL, NULL, &node)); 8525 if (node->hw_index >= (res->num_base_queues + 8526 (pipe * _BCM_TD2_NUM_L2_UC_LEAVES_PER_PIPE))) { 8527 return BCM_E_PARAM; 8528 } 8529 } 8530 } 8531 if ((outport != -1) && (IS_HG_PORT(unit, outport))) { 8532 field = HG_COSf; 8533 } else { 8534 field = UC_COS1f; 8535 } 8536 break; 8537 case BCM_COSQ_GPORT_MCAST_QUEUE_GROUP: 8538 if (gport == -1) { 8539 hw_cosq = cosq; 8540 } else { 8541 if (!BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 8542 return BCM_E_PARAM; 8543 } 8544 BCM_IF_ERROR_RETURN 8545 (_bcm_td2_cosq_index_resolve 8546 (unit, gport, cosq, _BCM_TD2_COSQ_INDEX_STYLE_COS, 8547 NULL, &hw_cosq, NULL)); 8548 } 8549 field = MC_COS1f; 8550 field2 = RQE_Q_NUMf; 8551 break; 8552 case BCM_COSQ_GPORT_UCAST_QUEUE_GROUP | BCM_COSQ_GPORT_MCAST_QUEUE_GROUP: 8553 if (gport == -1) { 8554 hw_cosq = cosq; 8555 } else { 8556 return BCM_E_PARAM; 8557 } 8558 field = UC_COS1f; 8559 field2 = MC_COS1f; 8560 field3 = RQE_Q_NUMf; 8561 break; 8562 case BCM_COSQ_GPORT_DESTMOD_UCAST_QUEUE_GROUP: 8563 if (gport == -1) { 8564 hw_cosq = cosq; 8565 } else { 8566 BCM_IF_ERROR_RETURN 8567 (_bcm_td2_cosq_index_resolve 8568 (unit, gport, cosq, _BCM_TD2_COSQ_INDEX_STYLE_COS, 8569 NULL, &hw_cosq, NULL)); 8570 } 8571 8572 BCM_IF_ERROR_RETURN( 8573 READ_VOQ_COS_MAPm(unit, MEM_BLOCK_ALL, priority, &voq_cos_map)); 8574 valid = soc_mem_field32_get(unit, VOQ_COS_MAPm, &voq_cos_map, 8575 VOQ_COS_USE_MODf); 8576 8577 /* Setting the VOQ_PORT_BASE_SELECT, 8578 so that BASE_QUEUE_NUM_1 is used for queue 8579 calculation */ 8580 8581 soc_mem_field32_set(unit, VOQ_COS_MAPm, 8582 &voq_cos_map, VOQ_PORT_BASE_SELECTf, 1); 8583 soc_mem_field32_set(unit, VOQ_COS_MAPm, 8584 &voq_cos_map, VOQ_COS_USE_MODf, 1); 8585 8586 if (valid && (soc_mem_field32_get(unit, VOQ_COS_MAPm, &voq_cos_map, 8587 VOQ_COS_OFFSETf) != hw_cosq)) { 8588 soc_mem_field32_set(unit, VOQ_COS_MAPm, 8589 &voq_cos_map, VOQ_COS_OFFSETf, hw_cosq); 8590 } 8591 BCM_IF_ERROR_RETURN( 8592 soc_mem_write(unit, VOQ_COS_MAPm, MEM_BLOCK_ANY, priority, 8593 &voq_cos_map)); 8594 return BCM_E_NONE; 8595 break; 8596 default: 8597 return BCM_E_PARAM; 8598 } 8599 8600 entries[0] = &cos_map_entries; 8601 8602 if (hw_cosq < 0 || hw_cosq >= 16) { 8603 return BCM_E_PARAM; 8604 } 8605 8606 BCM_IF_ERROR_RETURN 8607 (READ_COS_MAP_SELm(unit, MEM_BLOCK_ANY, local_port, 8608 &cos_map_sel_entry)); 8609 old_index = soc_mem_field32_get(unit, COS_MAP_SELm, &cos_map_sel_entry, 8610 SELECTf); 8611 old_index *= 16; 8612 8613 BCM_IF_ERROR_RETURN 8614 (soc_profile_mem_get(unit, _bcm_td2_cos_map_profile[unit], 8615 old_index, 16, entries)); 8616 soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[priority], field, 8617 hw_cosq); 8618 if (field2 != INVALIDf) { 8619 soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[priority], 8620 field2,hw_cosq); 8621 } 8622 if (field3 != INVALIDf) { 8623 soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[priority], 8624 field3,hw_cosq); 8625 } 8626 8627 soc_mem_lock(unit, PORT_COS_MAPm); 8628 8629 rv = soc_profile_mem_delete(unit, _bcm_td2_cos_map_profile[unit], 8630 old_index); 8631 if (BCM_FAILURE(rv)) { 8632 soc_mem_unlock(unit, PORT_COS_MAPm); 8633 return rv; 8634 } 8635 8636 rv = soc_profile_mem_add(unit, _bcm_td2_cos_map_profile[unit], entries, 8637 16, &new_index); 8638 8639 soc_mem_unlock(unit, PORT_COS_MAPm); 8640 8641 if (BCM_FAILURE(rv)) { 8642 return rv; 8643 } 8644 8645 soc_mem_field32_set(unit, COS_MAP_SELm, &cos_map_sel_entry, SELECTf, 8646 new_index / 16); 8647 BCM_IF_ERROR_RETURN 8648 (WRITE_COS_MAP_SELm(unit, MEM_BLOCK_ANY, local_port, 8649 &cos_map_sel_entry)); 8650 8651 #ifndef BCM_COSQ_HIGIG_MAP_DISABLE 8652 if (IS_CPU_PORT(unit, local_port)) { 8653 BCM_IF_ERROR_RETURN 8654 (soc_mem_field32_modify(unit, COS_MAP_SELm, 8655 SOC_INFO(unit).cpu_hg_index, SELECTf, 8656 new_index / 16)); 8657 } 8658 #endif /* BCM_COSQ_HIGIG_MAP_DISABLE */ 8659 8660 return BCM_E_NONE; 8661 } 8662 8663 /* 8664 * Function: 8665 * bcm_td2_cosq_mapping_set 8666 * Purpose: 8667 * Set which cosq a given priority should fall into 8668 * Parameters: 8669 * unit - (IN) unit number 8670 * gport - (IN) queue group GPORT identifier 8671 * priority - (IN) priority value to map 8672 * cosq - (IN) COS queue to map to 8673 * Returns: 8674 * BCM_E_XXX 8675 */ 8676 8677 int 8678 bcm_td2_cosq_mapping_set(int unit, bcm_port_t port, bcm_cos_t priority, 8679 bcm_cos_queue_t cosq) 8680 { 8681 bcm_pbmp_t pbmp; 8682 bcm_port_t local_port; 8683 8684 BCM_PBMP_CLEAR(pbmp); 8685 8686 if (port == -1) { 8687 BCM_PBMP_ASSIGN(pbmp, PBMP_ALL(unit)); 8688 } else { 8689 if (BCM_GPORT_IS_SET(port)) { 8690 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 8691 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) || 8692 BCM_GPORT_IS_SCHEDULER(port)) { 8693 return BCM_E_PARAM; 8694 } else if (BCM_GPORT_IS_LOCAL(port)) { 8695 local_port = BCM_GPORT_LOCAL_GET(port); 8696 } else if (BCM_GPORT_IS_MODPORT(port)) { 8697 BCM_IF_ERROR_RETURN( 8698 bcm_esw_port_local_get(unit, port, &local_port)); 8699 } else { 8700 return BCM_E_PARAM; 8701 } 8702 } else { 8703 local_port = port; 8704 } 8705 8706 if (!SOC_PORT_VALID(unit, local_port)) { 8707 return BCM_E_PORT; 8708 } 8709 8710 BCM_PBMP_PORT_ADD(pbmp, local_port); 8711 } 8712 8713 PBMP_ITER(pbmp, local_port) { 8714 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_port_has_ets(unit, local_port)); 8715 } 8716 8717 if ((cosq < 0) || (cosq >= _TD2_NUM_COS(unit))) { 8718 return BCM_E_PARAM; 8719 } 8720 8721 PBMP_ITER(pbmp, local_port) { 8722 if (IS_LB_PORT(unit, local_port)) { 8723 continue; 8724 } 8725 8726 /* If no ETS/gport, map the int prio symmetrically for ucast and 8727 * mcast */ 8728 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_mapping_set(unit, local_port, 8729 priority, 8730 BCM_COSQ_GPORT_UCAST_QUEUE_GROUP | 8731 BCM_COSQ_GPORT_MCAST_QUEUE_GROUP, 8732 -1, cosq)); 8733 } 8734 8735 return BCM_E_NONE; 8736 } 8737 8738 /* 8739 * Function: 8740 * bcm_td2_cosq_mapping_get 8741 * Purpose: 8742 * Determine which COS queue a given priority currently maps to. 8743 * Parameters: 8744 * unit - (IN) unit number 8745 * gport - (IN) queue group GPORT identifier 8746 * priority - (IN) priority value to map 8747 * cosq - (OUT) COS queue to map to 8748 * Returns: 8749 * BCM_E_XXX 8750 */ 8751 int 8752 _bcm_td2_cosq_mapping_get(int unit, bcm_port_t ing_port, bcm_cos_t priority, 8753 uint32 flags, bcm_gport_t *gport, 8754 bcm_cos_queue_t *cosq) 8755 { 8756 _bcm_td2_mmu_info_t *mmu_info; 8757 _bcm_td2_pipe_resources_t *res; 8758 _bcm_td2_cosq_port_info_t *port_info; 8759 _bcm_td2_cosq_node_t *node; 8760 bcm_port_t local_port; 8761 bcm_cos_queue_t hw_cosq = BCM_COS_INVALID; 8762 int index, ii; 8763 cos_map_sel_entry_t cos_map_sel_entry; 8764 voq_cos_map_entry_t voq_cos_map; 8765 void *entry_p; 8766 int ets_mode; 8767 8768 if (priority < 0 || priority >= 16) { 8769 return BCM_E_PARAM; 8770 } 8771 8772 if (flags != BCM_COSQ_GPORT_UCAST_QUEUE_GROUP && 8773 flags != BCM_COSQ_GPORT_MCAST_QUEUE_GROUP && 8774 flags != BCM_COSQ_GPORT_DESTMOD_UCAST_QUEUE_GROUP) { 8775 return BCM_E_PARAM; 8776 } 8777 8778 BCM_IF_ERROR_RETURN 8779 (_bcm_td2_cosq_localport_resolve(unit, ing_port, &local_port)); 8780 8781 if (gport) { 8782 *gport = BCM_GPORT_INVALID; 8783 } 8784 8785 *cosq = BCM_COS_INVALID; 8786 8787 if (local_port == CMIC_PORT(unit)) { 8788 /* CPU has two indices: 8789 * index_0 for Eth packet and index_106 for HiGig packet. 8790 * Getting cos mapping from index_106 instead of index_0, 8791 * although they are identical. Because previous version only write 8792 * index_106. Keep this for warmboot backward compatability. 8793 */ 8794 BCM_IF_ERROR_RETURN 8795 (READ_COS_MAP_SELm(unit, MEM_BLOCK_ANY, SOC_INFO(unit).cpu_hg_index, 8796 &cos_map_sel_entry)); 8797 } else { 8798 BCM_IF_ERROR_RETURN 8799 (READ_COS_MAP_SELm(unit, MEM_BLOCK_ANY, local_port, 8800 &cos_map_sel_entry)); 8801 } 8802 index = soc_mem_field32_get(unit, COS_MAP_SELm, &cos_map_sel_entry, 8803 SELECTf); 8804 index *= 16; 8805 8806 entry_p = SOC_PROFILE_MEM_ENTRY(unit, _bcm_td2_cos_map_profile[unit], 8807 port_cos_map_entry_t *, 8808 index + priority); 8809 8810 mmu_info = _bcm_td2_mmu_info[unit]; 8811 port_info = &mmu_info->port_info[local_port]; 8812 res = _BCM_TD2_PRESOURCES(mmu_info, _BCM_TD2_PORT_TO_PIPE(unit, local_port)); 8813 ets_mode = _bcm_td2_cosq_port_has_ets(unit, local_port); 8814 8815 switch (flags) { 8816 case BCM_COSQ_GPORT_UCAST_QUEUE_GROUP: 8817 hw_cosq = soc_mem_field32_get(unit, PORT_COS_MAPm, entry_p, UC_COS1f); 8818 if ((IS_CPU_PORT(unit, local_port) == FALSE) && gport && ets_mode) { 8819 for (ii = port_info->uc_base; ii < port_info->uc_limit; ii++) { 8820 node = &mmu_info->queue_node[ii]; 8821 if (node->numq > 0 && node->hw_cosq == hw_cosq) { 8822 *gport = node->gport; 8823 *cosq = 0; 8824 break; 8825 } 8826 } 8827 if (ii == port_info->uc_limit) { 8828 return BCM_E_NOT_FOUND; 8829 } 8830 } 8831 break; 8832 case BCM_COSQ_GPORT_MCAST_QUEUE_GROUP: 8833 hw_cosq = soc_mem_field32_get(unit, PORT_COS_MAPm, entry_p, MC_COS1f); 8834 if (gport && ets_mode) { 8835 for (ii = port_info->mc_base; ii < port_info->mc_limit; ii++) { 8836 node = &mmu_info->mc_queue_node[ii]; 8837 if (node->numq > 0 && node->hw_cosq == hw_cosq) { 8838 *gport = node->gport; 8839 *cosq = 0; 8840 break; 8841 } 8842 } 8843 if (ii == port_info->mc_limit) { 8844 return BCM_E_NOT_FOUND; 8845 } 8846 } 8847 break; 8848 8849 case BCM_COSQ_GPORT_DESTMOD_UCAST_QUEUE_GROUP: 8850 BCM_IF_ERROR_RETURN( 8851 READ_VOQ_COS_MAPm(unit, MEM_BLOCK_ALL, priority, &voq_cos_map)); 8852 hw_cosq = soc_mem_field32_get(unit, VOQ_COS_MAPm, 8853 &voq_cos_map, VOQ_COS_OFFSETf); 8854 if (gport && ets_mode) { 8855 for (ii = res->num_base_queues; ii < _BCM_TD2_NUM_L2_UC_LEAVES; ii++) { 8856 node = &mmu_info->queue_node[ii]; 8857 8858 if (node->numq > 0 && node->hw_cosq == hw_cosq) { 8859 *gport = node->gport; 8860 break; 8861 } 8862 } 8863 if (ii == _BCM_TD2_NUM_L2_UC_LEAVES) { 8864 return BCM_E_NOT_FOUND; 8865 } 8866 } 8867 break; 8868 } 8869 8870 *cosq = hw_cosq; 8871 8872 if (((gport && 8873 (*gport == BCM_GPORT_INVALID) && (*cosq == BCM_COS_INVALID))) || 8874 (*cosq == BCM_COS_INVALID)) { 8875 return BCM_E_NOT_FOUND; 8876 } 8877 8878 return BCM_E_NONE; 8879 } 8880 8881 int 8882 bcm_td2_cosq_mapping_get(int unit, bcm_port_t port, bcm_cos_t priority, 8883 bcm_cos_queue_t *cosq) 8884 { 8885 bcm_port_t local_port; 8886 bcm_pbmp_t pbmp; 8887 8888 BCM_PBMP_CLEAR(pbmp); 8889 8890 if (port == -1) { 8891 BCM_PBMP_ASSIGN(pbmp, PBMP_ALL(unit)); 8892 } else { 8893 if (BCM_GPORT_IS_SET(port)) { 8894 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 8895 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) || 8896 BCM_GPORT_IS_SCHEDULER(port)) { 8897 return BCM_E_PARAM; 8898 } else if (BCM_GPORT_IS_LOCAL(port)) { 8899 local_port = BCM_GPORT_LOCAL_GET(port); 8900 } else if (BCM_GPORT_IS_MODPORT(port)) { 8901 BCM_IF_ERROR_RETURN( 8902 bcm_esw_port_local_get(unit, port, &local_port)); 8903 } else { 8904 return BCM_E_PARAM; 8905 } 8906 } else { 8907 local_port = port; 8908 } 8909 8910 if (!SOC_PORT_VALID(unit, local_port)) { 8911 return BCM_E_PORT; 8912 } 8913 8914 BCM_PBMP_PORT_ADD(pbmp, local_port); 8915 } 8916 8917 PBMP_ITER(pbmp, local_port) { 8918 if (IS_LB_PORT(unit, local_port)) { 8919 continue; 8920 } 8921 8922 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_mapping_get(unit, local_port, 8923 priority, BCM_COSQ_GPORT_UCAST_QUEUE_GROUP, NULL, cosq)); 8924 break; 8925 } 8926 return BCM_E_NONE; 8927 } 8928 8929 int 8930 bcm_td2_cosq_gport_mapping_set(int unit, bcm_port_t ing_port, 8931 bcm_cos_t int_pri, uint32 flags, 8932 bcm_gport_t gport, bcm_cos_queue_t cosq) 8933 { 8934 return _bcm_td2_cosq_mapping_set(unit, ing_port, int_pri, flags, gport, 8935 cosq); 8936 } 8937 8938 int 8939 bcm_td2_cosq_gport_mapping_get(int unit, bcm_port_t ing_port, 8940 bcm_cos_t int_pri, uint32 flags, 8941 bcm_gport_t *gport, bcm_cos_queue_t *cosq) 8942 { 8943 if (gport == NULL || cosq == NULL) { 8944 return BCM_E_PARAM; 8945 } 8946 8947 return _bcm_td2_cosq_mapping_get(unit, ing_port, int_pri, flags, gport, 8948 cosq); 8949 } 8950 8951 /* 8952 * Function: 8953 * bcm_td2_cosq_port_sched_set 8954 * Purpose: 8955 * Set up class-of-service policy and corresponding weights and delay 8956 * Parameters: 8957 * unit - (IN) unit number 8958 * pbm - (IN) port bitmap 8959 * mode - (IN) Scheduling mode (BCM_COSQ_xxx) 8960 * weights - (IN) Weights for each COS queue 8961 * delay - This parameter is not used 8962 * Returns: 8963 * BCM_E_XXX 8964 */ 8965 int 8966 bcm_td2_cosq_port_sched_set(int unit, bcm_pbmp_t pbm, 8967 int mode, const int *weights, int delay) 8968 { 8969 bcm_port_t port; 8970 int num_weights, i; 8971 int cur_mode, cur_weight; 8972 int reset_mode = BCM_COSQ_WEIGHTED_ROUND_ROBIN; 8973 8974 num_weights = _TD2_NUM_COS(unit); 8975 BCM_PBMP_ITER(pbm, port) { 8976 /*WRR mode is a property per port, 8977 * so just get cosq=0 schedule mode*/ 8978 BCM_IF_ERROR_RETURN 8979 (_bcm_td2_cosq_sched_get(unit, port, 0, 8980 &cur_mode, &cur_weight)); 8981 if (cur_mode == BCM_COSQ_STRICT) { 8982 reset_mode = BCM_COSQ_WEIGHTED_ROUND_ROBIN; 8983 } else { 8984 reset_mode = cur_mode; 8985 } 8986 8987 /* Schedule mode switch need base on default wrr mode */ 8988 for (i = 0; i < num_weights; i++) { 8989 BCM_IF_ERROR_RETURN 8990 (_bcm_td2_cosq_sched_set(unit, port, i, 8991 reset_mode, 1)); 8992 } 8993 8994 for (i = 0; i < num_weights; i++) { 8995 BCM_IF_ERROR_RETURN 8996 (_bcm_td2_cosq_sched_set(unit, port, i, mode, weights[i])); 8997 8998 } 8999 } 9000 9001 return BCM_E_NONE; 9002 } 9003 9004 /* 9005 * Function: 9006 * bcm_td2_cosq_port_sched_get 9007 * Purpose: 9008 * Retrieve class-of-service policy and corresponding weights and delay 9009 * Parameters: 9010 * unit - (IN) unit number 9011 * pbm - (IN) port bitmap 9012 * mode - (OUT) Scheduling mode (BCM_COSQ_XXX) 9013 * weights - (OUT) Weights for each COS queue 9014 * delay - This parameter is not used 9015 * Returns: 9016 * BCM_E_XXX 9017 */ 9018 int 9019 bcm_td2_cosq_port_sched_get(int unit, bcm_pbmp_t pbm, 9020 int *mode, int *weights, int *delay) 9021 { 9022 bcm_port_t port; 9023 int i, num_weights; 9024 9025 BCM_PBMP_ITER(pbm, port) { 9026 /* coverity[illegal_address : FALSE] */ 9027 if (IS_CPU_PORT(unit, port) && SOC_PBMP_NEQ(pbm, PBMP_CMIC(unit))) { 9028 continue; 9029 } 9030 num_weights = _TD2_NUM_COS(unit); 9031 for (i = 0; i < num_weights; i++) { 9032 BCM_IF_ERROR_RETURN( 9033 _bcm_td2_cosq_sched_get(unit, port, i, mode, &weights[i])); 9034 } 9035 } 9036 9037 return BCM_E_NONE; 9038 } 9039 9040 /* 9041 * Function: 9042 * bcm_td2_cosq_sched_weight_max_get 9043 * Purpose: 9044 * Retrieve maximum weights for given COS policy 9045 * Parameters: 9046 * unit - (IN) unit number 9047 * mode - (IN) Scheduling mode (BCM_COSQ_xxx) 9048 * weight_max - (OUT) Maximum weight for COS queue. 9049 * Returns: 9050 * BCM_E_XXX 9051 */ 9052 int 9053 bcm_td2_cosq_sched_weight_max_get(int unit, int mode, int *weight_max) 9054 { 9055 switch (mode) { 9056 case BCM_COSQ_STRICT: 9057 *weight_max = BCM_COSQ_WEIGHT_STRICT; 9058 break; 9059 case BCM_COSQ_ROUND_ROBIN: 9060 case BCM_COSQ_WEIGHTED_ROUND_ROBIN: 9061 case BCM_COSQ_DEFICIT_ROUND_ROBIN: 9062 /* TD2 - weights can be calculated based on LLS/HSP based 9063 * scheduling type associated to the port, in either case 9064 * the maximum weight can be 127 9065 */ 9066 *weight_max = 9067 (1 << soc_reg_field_length(unit, HSP_SCHED_L0_NODE_WEIGHTr, 9068 WEIGHTf)) - 1; 9069 break; 9070 default: 9071 return BCM_E_PARAM; 9072 } 9073 9074 return BCM_E_NONE; 9075 } 9076 9077 /* 9078 * Function: 9079 * bcm_td2_cosq_bandwidth_set 9080 * Purpose: 9081 * Configure COS queue bandwidth control 9082 * Parameters: 9083 * unit - (IN) unit number 9084 * port - (IN) port number or GPORT identifier 9085 * cosq - (IN) COS queue number 9086 * min_quantum - (IN) 9087 * max_quantum - (IN) 9088 * burst_quantum - (IN) 9089 * flags - (IN) 9090 * Returns: 9091 * BCM_E_XXX 9092 * Notes: 9093 * If port is any form of local port, cosq is the hardware queue index. 9094 */ 9095 int 9096 bcm_td2_cosq_port_bandwidth_set(int unit, bcm_port_t port, 9097 bcm_cos_queue_t cosq, 9098 uint32 min_quantum, uint32 max_quantum, 9099 uint32 burst_quantum, uint32 flags) 9100 { 9101 uint32 burst_min, burst_max; 9102 9103 if (cosq < 0) { 9104 return BCM_E_PARAM; 9105 } 9106 9107 burst_min = (min_quantum > 0) ? 9108 _bcm_td_default_burst_size(unit, port, min_quantum) : 0; 9109 9110 burst_max = (max_quantum > 0) ? 9111 _bcm_td_default_burst_size(unit, port, max_quantum) : 0; 9112 9113 return _bcm_td2_cosq_bucket_set(unit, port, cosq, min_quantum, max_quantum, 9114 burst_min, burst_max, flags); 9115 } 9116 9117 /* 9118 * Function: 9119 * bcm_td2_cosq_bandwidth_get 9120 * Purpose: 9121 * Get COS queue bandwidth control configuration 9122 * Parameters: 9123 * unit - (IN) unit number 9124 * port - (IN) port number or GPORT identifier 9125 * cosq - (IN) COS queue number 9126 * min_quantum - (OUT) 9127 * max_quantum - (OUT) 9128 * burst_quantum - (OUT) 9129 * flags - (OUT) 9130 * Returns: 9131 * BCM_E_XXX 9132 * Notes: 9133 * If port is any form of local port, cosq is the hardware queue index. 9134 */ 9135 int 9136 bcm_td2_cosq_port_bandwidth_get(int unit, bcm_port_t port, 9137 bcm_cos_queue_t cosq, 9138 uint32 *min_quantum, uint32 *max_quantum, 9139 uint32 *burst_quantum, uint32 *flags) 9140 { 9141 uint32 kbit_burst_min; 9142 9143 if (cosq < -1) { 9144 return BCM_E_PARAM; 9145 } 9146 9147 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_bucket_get(unit, port, cosq, 9148 min_quantum, max_quantum, &kbit_burst_min, 9149 burst_quantum, flags)); 9150 return BCM_E_NONE; 9151 } 9152 9153 int 9154 bcm_td2_cosq_port_pps_set(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 9155 int pps) 9156 { 9157 uint32 min, max, burst, burst_min, flags; 9158 bcm_port_t local_port = port; 9159 9160 if (!IS_CPU_PORT(unit, port)) { 9161 return BCM_E_PORT; 9162 } else if (cosq < 0 || cosq >= NUM_CPU_COSQ(unit)) { 9163 return BCM_E_PARAM; 9164 } 9165 9166 if (_bcm_td2_cosq_port_has_ets(unit, port)) { 9167 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_l2_gport(unit, port, cosq, 9168 _BCM_TD2_NODE_MCAST, &port, NULL)); 9169 cosq = 0; 9170 } 9171 9172 BCM_IF_ERROR_RETURN 9173 (_bcm_td2_cosq_bucket_get(unit, port, cosq, &min, &max, &burst_min, 9174 &burst, &flags)); 9175 9176 min = pps; 9177 burst_min = (min > 0) ? 9178 _bcm_td_default_burst_size(unit, local_port, min) : 0; 9179 burst = burst_min; 9180 9181 return _bcm_td2_cosq_bucket_set(unit, port, cosq, min, pps, burst_min, burst, 9182 flags | BCM_COSQ_BW_PACKET_MODE); 9183 } 9184 9185 int 9186 bcm_td2_cosq_port_pps_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 9187 int *pps) 9188 { 9189 uint32 min, max, burst, flags; 9190 9191 if (!IS_CPU_PORT(unit, port)) { 9192 return BCM_E_PORT; 9193 } else if (cosq < 0 || cosq >= NUM_CPU_COSQ(unit)) { 9194 return BCM_E_PARAM; 9195 } 9196 9197 if (_bcm_td2_cosq_port_has_ets(unit, port)) { 9198 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_l2_gport(unit, port, cosq, 9199 _BCM_TD2_NODE_MCAST, &port, NULL)); 9200 cosq = 0; 9201 } 9202 9203 BCM_IF_ERROR_RETURN 9204 (_bcm_td2_cosq_bucket_get(unit, port, cosq, &min, &max, &burst, &burst, 9205 &flags)); 9206 *pps = max; 9207 9208 return BCM_E_NONE; 9209 } 9210 9211 int 9212 bcm_td2_cosq_port_burst_set(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 9213 int burst) 9214 { 9215 uint32 min, max, cur_burst, flags; 9216 9217 if (!IS_CPU_PORT(unit, port)) { 9218 return BCM_E_PORT; 9219 } else if (cosq < 0 || cosq >= NUM_CPU_COSQ(unit)) { 9220 return BCM_E_PARAM; 9221 } 9222 9223 if (_bcm_td2_cosq_port_has_ets(unit, port)) { 9224 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_l2_gport(unit, port, cosq, 9225 _BCM_TD2_NODE_MCAST, &port, NULL)); 9226 cosq = 0; 9227 } 9228 9229 BCM_IF_ERROR_RETURN 9230 (_bcm_td2_cosq_bucket_get(unit, port, cosq, &min, &max, &cur_burst, 9231 &cur_burst, &flags)); 9232 9233 /* Replace the current BURST setting, keep PPS the same */ 9234 return _bcm_td2_cosq_bucket_set(unit, port, cosq, min, max, burst, burst, 9235 flags | BCM_COSQ_BW_PACKET_MODE); 9236 } 9237 9238 int 9239 bcm_td2_cosq_port_burst_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 9240 int *burst) 9241 { 9242 uint32 min, max, cur_burst, cur_burst_min, flags; 9243 9244 if (!IS_CPU_PORT(unit, port)) { 9245 return BCM_E_PORT; 9246 } else if (cosq < 0 || cosq >= NUM_CPU_COSQ(unit)) { 9247 return BCM_E_PARAM; 9248 } 9249 9250 if (_bcm_td2_cosq_port_has_ets(unit, port)) { 9251 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_l2_gport(unit, port, cosq, 9252 _BCM_TD2_NODE_MCAST, &port, NULL)); 9253 cosq = 0; 9254 } 9255 9256 BCM_IF_ERROR_RETURN 9257 (_bcm_td2_cosq_bucket_get(unit, port, cosq, &min, &max, 9258 &cur_burst_min, &cur_burst, &flags)); 9259 *burst = cur_burst; 9260 9261 return BCM_E_NONE; 9262 } 9263 9264 int 9265 bcm_td2_cosq_discard_set(int unit, uint32 flags) 9266 { 9267 bcm_port_t port; 9268 _bcm_td2_mmu_info_t *mmu_info; 9269 9270 if ((mmu_info = _bcm_td2_mmu_info[unit]) == NULL) { 9271 return BCM_E_INIT; 9272 } 9273 9274 if (flags & ~(BCM_COSQ_DISCARD_TCP | 9275 BCM_COSQ_DISCARD_NONTCP | 9276 BCM_COSQ_DISCARD_COLOR_ALL | 9277 BCM_COSQ_DISCARD_COLOR_GREEN | 9278 BCM_COSQ_DISCARD_COLOR_YELLOW | 9279 BCM_COSQ_DISCARD_COLOR_RED | 9280 BCM_COSQ_DISCARD_CAP_AVERAGE | 9281 BCM_COSQ_DISCARD_ENABLE | 9282 BCM_COSQ_DISCARD_MARK_CONGESTION)) { 9283 return BCM_E_PARAM; 9284 } 9285 9286 flags &= ~(BCM_COSQ_DISCARD_NONTCP | BCM_COSQ_DISCARD_COLOR_ALL); 9287 9288 PBMP_PORT_ITER(unit, port) { 9289 BCM_IF_ERROR_RETURN 9290 (_bcm_td2_cosq_wred_set(unit, port, 0, flags, 0, 0, 0, 0, 9291 FALSE, BCM_COSQ_DISCARD_PORT,8)); 9292 } 9293 9294 return BCM_E_NONE; 9295 } 9296 9297 int 9298 bcm_td2_cosq_discard_get(int unit, uint32 *flags) 9299 { 9300 bcm_port_t port; 9301 9302 PBMP_PORT_ITER(unit, port) { 9303 *flags = 0; 9304 /* use setting from hardware cosq index 0 of the first port */ 9305 return _bcm_td2_cosq_wred_get(unit, port, 0, flags, NULL, NULL, NULL, 9306 NULL, BCM_COSQ_DISCARD_PORT,NULL); 9307 } 9308 9309 return BCM_E_NOT_FOUND; 9310 } 9311 9312 /* 9313 * Function: 9314 * bcm_td2_cosq_discard_port_set 9315 * Purpose: 9316 * Configure port WRED setting 9317 * Parameters: 9318 * unit - (IN) unit number 9319 * port - (IN) port number or GPORT identifier 9320 * cosq - (IN) COS queue number 9321 * color - (IN) 9322 * drop_start - (IN) 9323 * drop_slot - (IN) 9324 * average_time - (IN) 9325 * Returns: 9326 * BCM_E_XXX 9327 * Notes: 9328 * If port is any form of local port, cosq is the hardware queue index. 9329 */ 9330 int 9331 bcm_td2_cosq_discard_port_set(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 9332 uint32 color, int drop_start, int drop_slope, 9333 int average_time) 9334 { 9335 bcm_port_t local_port; 9336 bcm_pbmp_t pbmp; 9337 int gain; 9338 uint32 min_thresh, max_thresh, shared_limit; 9339 uint32 rval, bits, flags = 0; 9340 int numq, i; 9341 9342 if (drop_start < 0 || drop_start > 100 || 9343 drop_slope < 0 || drop_slope > 90) { 9344 return BCM_E_PARAM; 9345 } 9346 9347 /* 9348 * average queue size is reculated every 8us, the formula is 9349 * avg_qsize(t + 1) = 9350 * avg_qsize(t) + (cur_qsize - avg_qsize(t)) / (2 ** gain) 9351 * gain = log2(average_time / 8) 9352 */ 9353 bits = (average_time / 8) & 0xffff; 9354 if (bits != 0) { 9355 bits |= bits >> 1; 9356 bits |= bits >> 2; 9357 bits |= bits >> 4; 9358 bits |= bits >> 8; 9359 gain = _shr_popcount(bits) - 1; 9360 } else { 9361 gain = 0; 9362 } 9363 9364 /* 9365 * per-port cell limit may be disabled. 9366 * per-port per-cos cell limit may be set to use dynamic method. 9367 * therefore drop_start percentage is based on per-device total shared 9368 * cells. 9369 */ 9370 BCM_IF_ERROR_RETURN(READ_MMU_THDM_DB_POOL_SHARED_LIMITr(unit, 0, &rval)); 9371 shared_limit = soc_reg_field_get(unit, MMU_THDM_DB_POOL_SHARED_LIMITr, 9372 rval, SHARED_LIMITf); 9373 min_thresh = ((drop_start * shared_limit) + (100 - 1)) / 100; 9374 9375 /* Calculate the max threshold. For a given slope (angle in 9376 * degrees), determine how many packets are in the range from 9377 * 0% drop probability to 100% drop probability. Add that 9378 * number to the min_treshold to the the max_threshold. 9379 */ 9380 max_thresh = min_thresh + _bcm_td2_angle_to_cells(drop_slope); 9381 if (max_thresh > TD2_CELL_FIELD_MAX) { 9382 max_thresh = TD2_CELL_FIELD_MAX; 9383 } 9384 9385 if (BCM_GPORT_IS_SET(port)) { 9386 numq = 1; 9387 for (i = 0; i < numq; i++) { 9388 BCM_IF_ERROR_RETURN 9389 (_bcm_td2_cosq_wred_set(unit, port, cosq + i, color, 9390 min_thresh, max_thresh, 100, gain, 9391 TRUE, flags,8)); 9392 } 9393 } else { 9394 if (port == -1) { 9395 BCM_PBMP_ASSIGN(pbmp, PBMP_PORT_ALL(unit)); 9396 } else if (!SOC_PORT_VALID(unit, port)) { 9397 return BCM_E_PORT; 9398 } else { 9399 BCM_PBMP_PORT_SET(pbmp, port); 9400 } 9401 9402 BCM_PBMP_ITER(pbmp, local_port) { 9403 numq = 1; 9404 for (i = 0; i < numq; i++) { 9405 BCM_IF_ERROR_RETURN 9406 (_bcm_td2_cosq_wred_set(unit, local_port, cosq + i, 9407 color, min_thresh, max_thresh, 100, 9408 gain, TRUE, 0,8)); 9409 } 9410 } 9411 } 9412 9413 return BCM_E_NONE; 9414 } 9415 9416 /* 9417 * Function: 9418 * bcm_td2_cosq_discard_port_get 9419 * Purpose: 9420 * Get port WRED setting 9421 * Parameters: 9422 * unit - (IN) unit number 9423 * port - (IN) port number or GPORT identifier 9424 * cosq - (IN) COS queue number 9425 * color - (OUT) 9426 * drop_start - (OUT) 9427 * drop_slot - (OUT) 9428 * average_time - (OUT) 9429 * Returns: 9430 * BCM_E_XXX 9431 * Notes: 9432 * If port is any form of local port, cosq is the hardware queue index. 9433 */ 9434 int 9435 bcm_td2_cosq_discard_port_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 9436 uint32 color, int *drop_start, int *drop_slope, 9437 int *average_time) 9438 { 9439 bcm_port_t local_port; 9440 bcm_pbmp_t pbmp; 9441 int gain, drop_prob; 9442 int refresh_time = 0; 9443 uint32 min_thresh, max_thresh, shared_limit; 9444 uint32 rval; 9445 9446 if (drop_start == NULL || drop_slope == NULL || average_time == NULL) { 9447 return BCM_E_PARAM; 9448 } 9449 9450 if (BCM_GPORT_IS_SET(port)) { 9451 local_port = port; 9452 } else { 9453 if (port == -1) { 9454 BCM_PBMP_ASSIGN(pbmp, PBMP_PORT_ALL(unit)); 9455 } else if (!SOC_PORT_VALID(unit, port)) { 9456 return BCM_E_PORT; 9457 } else { 9458 BCM_PBMP_PORT_SET(pbmp, port); 9459 } 9460 BCM_PBMP_ITER(pbmp, local_port) { 9461 break; 9462 } 9463 } 9464 9465 BCM_IF_ERROR_RETURN 9466 (_bcm_td2_cosq_wred_get(unit, local_port, cosq == -1 ? 0 : cosq, 9467 &color, &min_thresh, &max_thresh, &drop_prob, 9468 &gain, 0, &refresh_time)); 9469 9470 /* 9471 * average queue size is reculated every 8us, the formula is 9472 * avg_qsize(t + 1) = 9473 * avg_qsize(t) + (cur_qsize - avg_qsize(t)) / (2 ** gain) 9474 */ 9475 *average_time = (1 << gain) * refresh_time; 9476 9477 BCM_IF_ERROR_RETURN(READ_MMU_THDM_DB_POOL_SHARED_LIMITr(unit, 0, &rval)); 9478 shared_limit = soc_reg_field_get(unit, MMU_THDM_DB_POOL_SHARED_LIMITr, 9479 rval, SHARED_LIMITf); 9480 if (min_thresh > shared_limit) { 9481 min_thresh = shared_limit; 9482 } 9483 9484 if (max_thresh > shared_limit) { 9485 max_thresh = shared_limit; 9486 } 9487 9488 *drop_start = min_thresh * 100 / shared_limit; 9489 9490 /* Calculate the slope using the min and max threshold. 9491 * The angle is calculated knowing drop probability at min 9492 * threshold is 0% and drop probability at max threshold is 100%. 9493 */ 9494 *drop_slope = _bcm_td2_cells_to_angle(max_thresh - min_thresh); 9495 9496 return BCM_E_NONE; 9497 } 9498 9499 STATIC int 9500 _bcm_td2_distribute_u64(uint64 value, uint64 *l, uint64 *r) 9501 { 9502 uint64 tmp, tmp1; 9503 9504 tmp = value; 9505 COMPILER_64_SHR(tmp, 1); 9506 *l = tmp; 9507 9508 COMPILER_64_SET(tmp1, 0, 1); 9509 COMPILER_64_AND(tmp1, value); 9510 COMPILER_64_ADD_64(tmp1, tmp); 9511 *r = tmp1; 9512 return 0; 9513 } 9514 9515 STATIC int 9516 _port_l2c_mapping(int unit, bcm_port_t port, bcm_cosq_stat_t stat, int *xlp_port) 9517 { 9518 soc_info_t *si; 9519 soc_port_t phy_port; 9520 int i, xlp_blk, xlp_bindex = -1, pgw_blk, pgw_bindex = -1; 9521 9522 si = &SOC_INFO(unit); 9523 9524 phy_port = si->port_l2p_mapping[port]; 9525 for (i = 0; i < SOC_DRIVER(unit)->port_num_blktype; i++) { 9526 xlp_blk = SOC_PORT_IDX_BLOCK(unit, phy_port, i); 9527 xlp_bindex = SOC_PORT_IDX_BINDEX(unit, phy_port, i); 9528 if (SOC_BLOCK_INFO(unit, xlp_blk).type == SOC_BLK_XLPORT) { 9529 break; 9530 } 9531 } 9532 for (i = 0; i < SOC_DRIVER(unit)->port_num_blktype; i++) { 9533 pgw_blk = SOC_PORT_IDX_BLOCK(unit, phy_port, i); 9534 pgw_bindex = SOC_PORT_IDX_BINDEX(unit, phy_port, i); 9535 if (SOC_BLOCK_INFO(unit, pgw_blk).type == SOC_BLK_PGW_CL) { 9536 break; 9537 } 9538 } 9539 *xlp_port = xlp_bindex; 9540 9541 if(stat == bcmCosqStatHighPriDroppedPackets){ 9542 switch (pgw_bindex % 16) { 9543 case 0: 9544 case 1: 9545 case 2: 9546 case 3: 9547 return SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM0_HIGH_PRI; 9548 case 4: 9549 case 5: 9550 case 6: 9551 case 7: 9552 return SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM1_HIGH_PRI; 9553 case 8: 9554 case 9: 9555 case 10: 9556 case 11: 9557 return SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM2_HIGH_PRI; 9558 case 12: 9559 case 13: 9560 case 14: 9561 case 15: 9562 return SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM3_HIGH_PRI; 9563 default: 9564 return SOC_E_INTERNAL; 9565 } 9566 } 9567 9568 if(stat == bcmCosqStatLowPriDroppedPackets){ 9569 switch (pgw_bindex % 16) { 9570 case 0: 9571 case 1: 9572 case 2: 9573 case 3: 9574 return SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM0_LOW_PRI; 9575 case 4: 9576 case 5: 9577 case 6: 9578 case 7: 9579 return SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM1_LOW_PRI; 9580 case 8: 9581 case 9: 9582 case 10: 9583 case 11: 9584 return SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM2_LOW_PRI; 9585 case 12: 9586 case 13: 9587 case 14: 9588 case 15: 9589 return SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM3_LOW_PRI; 9590 default: 9591 return SOC_E_INTERNAL; 9592 } 9593 } 9594 9595 if(stat == bcmCosqStatHighPriDroppedBytes){ 9596 switch (pgw_bindex % 16) { 9597 case 0: 9598 case 1: 9599 case 2: 9600 case 3: 9601 return SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM0_HIGH_PRI; 9602 case 4: 9603 case 5: 9604 case 6: 9605 case 7: 9606 return SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM1_HIGH_PRI; 9607 case 8: 9608 case 9: 9609 case 10: 9610 case 11: 9611 return SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM2_HIGH_PRI; 9612 case 12: 9613 case 13: 9614 case 14: 9615 case 15: 9616 return SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM3_HIGH_PRI; 9617 default: 9618 return SOC_E_INTERNAL; 9619 } 9620 } 9621 9622 if(stat == bcmCosqStatLowPriDroppedBytes){ 9623 switch (pgw_bindex % 16) { 9624 case 0: 9625 case 1: 9626 case 2: 9627 case 3: 9628 return SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM0_LOW_PRI; 9629 case 4: 9630 case 5: 9631 case 6: 9632 case 7: 9633 return SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM1_LOW_PRI; 9634 case 8: 9635 case 9: 9636 case 10: 9637 case 11: 9638 return SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM2_LOW_PRI; 9639 case 12: 9640 case 13: 9641 case 14: 9642 case 15: 9643 return SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM3_LOW_PRI; 9644 default: 9645 return SOC_E_INTERNAL; 9646 } 9647 } 9648 9649 return SOC_E_INTERNAL; 9650 } 9651 9652 int 9653 bcm_td2_cosq_stat_set(int unit, bcm_gport_t port, bcm_cos_queue_t cosq, 9654 bcm_cosq_stat_t stat, uint64 value) 9655 { 9656 _bcm_td2_cosq_node_t *node; 9657 bcm_port_t local_port; 9658 int startq, numq, i, from_cos, to_cos, ci; 9659 uint64 l, r; 9660 soc_counter_non_dma_id_t id; 9661 int xlp_port; 9662 9663 if (cosq < -1) { 9664 return BCM_E_PARAM; 9665 } 9666 _bcm_td2_distribute_u64(value, &l, &r); 9667 9668 switch (stat) { 9669 case bcmCosqStatDroppedPackets: 9670 if (BCM_GPORT_IS_SCHEDULER(port)) { 9671 BCM_IF_ERROR_RETURN 9672 (_bcm_td2_cosq_node_get(unit, port, 0, NULL, 9673 &local_port, NULL, &node)); 9674 BCM_IF_ERROR_RETURN( 9675 _bcm_td2_cosq_child_node_at_input(node, cosq, &node)); 9676 port = node->gport; 9677 } 9678 9679 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) { 9680 BCM_IF_ERROR_RETURN 9681 (_bcm_td2_cosq_node_get(unit, port, 0, NULL, 9682 &local_port, NULL, &node)); 9683 if ((node->type == _BCM_TD2_NODE_VM_UCAST) || 9684 (node->type == _BCM_TD2_NODE_SERVICE_UCAST)) { 9685 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9686 BCM_IF_ERROR_RETURN 9687 (soc_counter_set(unit, local_port, 9688 SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_EXT, node->hw_index, 9689 value)); 9690 } else { 9691 BCM_IF_ERROR_RETURN 9692 (_bcm_td2_cosq_index_resolve 9693 (unit, port, cosq, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_UCAST, 9694 &local_port, &startq, NULL)); 9695 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9696 BCM_IF_ERROR_RETURN 9697 (soc_counter_set(unit, local_port, 9698 SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_UC, startq, 9699 value)); 9700 } 9701 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 9702 BCM_IF_ERROR_RETURN 9703 (_bcm_td2_cosq_index_resolve 9704 (unit, port, cosq, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_MCAST, 9705 &local_port, &startq, NULL)); 9706 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9707 BCM_IF_ERROR_RETURN 9708 (soc_counter_set(unit, local_port, 9709 SOC_COUNTER_NON_DMA_COSQ_DROP_PKT, startq, 9710 value)); 9711 } else { 9712 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_localport_resolve(unit, port, &local_port)); 9713 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_port_has_ets(unit, local_port)); 9714 if (cosq == BCM_COS_INVALID) { 9715 from_cos = to_cos = 0; 9716 } else { 9717 from_cos = to_cos = cosq; 9718 } 9719 for (ci = from_cos; ci <= to_cos; ci++) { 9720 if (!IS_CPU_PORT(unit, local_port)) { 9721 BCM_IF_ERROR_RETURN 9722 (_bcm_td2_cosq_index_resolve 9723 (unit, port, ci, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_UCAST, 9724 &local_port, &startq, &numq)); 9725 for (i = 0; i < numq; i++) { 9726 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9727 BCM_IF_ERROR_RETURN 9728 (soc_counter_set(unit, local_port, 9729 SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_UC, 9730 startq + i, l)); 9731 } 9732 } 9733 BCM_IF_ERROR_RETURN 9734 (_bcm_td2_cosq_index_resolve 9735 (unit, port, ci, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_MCAST, 9736 &local_port, &startq, &numq)); 9737 for (i = 0; i < numq; i++) { 9738 BCM_IF_ERROR_RETURN 9739 (soc_counter_set(unit, local_port, 9740 SOC_COUNTER_NON_DMA_COSQ_DROP_PKT, 9741 startq + i , r)); 9742 } 9743 } 9744 } 9745 break; 9746 case bcmCosqStatDroppedBytes: 9747 if (BCM_GPORT_IS_SCHEDULER(port)) { 9748 BCM_IF_ERROR_RETURN 9749 (_bcm_td2_cosq_node_get(unit, port, 0, NULL, 9750 &local_port, NULL, &node)); 9751 BCM_IF_ERROR_RETURN( 9752 _bcm_td2_cosq_child_node_at_input(node, cosq, &node)); 9753 port = node->gport; 9754 } 9755 9756 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) { 9757 BCM_IF_ERROR_RETURN 9758 (_bcm_td2_cosq_node_get(unit, port, 0, NULL, 9759 &local_port, NULL, &node)); 9760 if ((node->type == _BCM_TD2_NODE_VM_UCAST) || 9761 (node->type == _BCM_TD2_NODE_SERVICE_UCAST)) { 9762 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9763 BCM_IF_ERROR_RETURN 9764 (soc_counter_set(unit, local_port, 9765 SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE_EXT, node->hw_index, 9766 value)); 9767 } else { 9768 BCM_IF_ERROR_RETURN 9769 (_bcm_td2_cosq_index_resolve 9770 (unit, port, cosq, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_UCAST, 9771 &local_port, &startq, NULL)); 9772 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9773 BCM_IF_ERROR_RETURN 9774 (soc_counter_set(unit, local_port, 9775 SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE_UC, startq, 9776 value)); 9777 } 9778 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 9779 BCM_IF_ERROR_RETURN 9780 (_bcm_td2_cosq_index_resolve 9781 (unit, port, cosq, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_MCAST, 9782 &local_port, &startq, NULL)); 9783 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9784 BCM_IF_ERROR_RETURN 9785 (soc_counter_set(unit, local_port, 9786 SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE, startq , value)); 9787 } else { 9788 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_localport_resolve(unit, port, &local_port)); 9789 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_port_has_ets(unit, local_port)); 9790 if (cosq == BCM_COS_INVALID) { 9791 from_cos = to_cos = 0; 9792 } else { 9793 from_cos = to_cos = cosq; 9794 } 9795 for (ci = from_cos; ci <= to_cos; ci++) { 9796 if (!IS_CPU_PORT(unit, local_port)) { 9797 BCM_IF_ERROR_RETURN 9798 (_bcm_td2_cosq_index_resolve 9799 (unit, port, ci, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_UCAST, 9800 &local_port, &startq, &numq)); 9801 for (i = 0; i < numq; i++) { 9802 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9803 BCM_IF_ERROR_RETURN 9804 (soc_counter_set(unit, local_port, 9805 SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE_UC, 9806 startq + i, l)); 9807 } 9808 } 9809 BCM_IF_ERROR_RETURN 9810 (_bcm_td2_cosq_index_resolve 9811 (unit, port, ci, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_MCAST, 9812 &local_port, &startq, &numq)); 9813 for (i = 0; i < numq; i++) { 9814 BCM_IF_ERROR_RETURN 9815 (soc_counter_set(unit, local_port, 9816 SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE, 9817 startq + i , r)); 9818 } 9819 } 9820 } 9821 break; 9822 case bcmCosqStatYellowCongestionDroppedPackets: 9823 if (cosq != BCM_COS_INVALID) { 9824 return BCM_E_UNAVAIL; 9825 } 9826 BCM_IF_ERROR_RETURN 9827 (_bcm_td2_cosq_localport_resolve(unit, port, &local_port)); 9828 BCM_IF_ERROR_RETURN 9829 (soc_counter_set(unit, local_port, 9830 SOC_COUNTER_NON_DMA_PORT_DROP_PKT_YELLOW, 0, 9831 value)); 9832 break; 9833 case bcmCosqStatRedCongestionDroppedPackets: 9834 if (cosq != BCM_COS_INVALID) { 9835 return BCM_E_UNAVAIL; 9836 } 9837 BCM_IF_ERROR_RETURN 9838 (_bcm_td2_cosq_localport_resolve(unit, port, &local_port)); 9839 BCM_IF_ERROR_RETURN 9840 (soc_counter_set(unit, local_port, 9841 SOC_COUNTER_NON_DMA_PORT_DROP_PKT_RED, 0, 9842 value)); 9843 break; 9844 case bcmCosqStatGreenDiscardDroppedPackets: 9845 if (cosq != BCM_COS_INVALID) { 9846 return BCM_E_UNAVAIL; 9847 } 9848 BCM_IF_ERROR_RETURN 9849 (_bcm_td2_cosq_localport_resolve(unit, port, &local_port)); 9850 BCM_IF_ERROR_RETURN 9851 (soc_counter_set(unit, local_port, 9852 SOC_COUNTER_NON_DMA_PORT_WRED_PKT_GREEN, 0, 9853 value)); 9854 break; 9855 case bcmCosqStatYellowDiscardDroppedPackets: 9856 if (cosq != BCM_COS_INVALID) { 9857 return BCM_E_UNAVAIL; 9858 } 9859 BCM_IF_ERROR_RETURN 9860 (_bcm_td2_cosq_localport_resolve(unit, port, &local_port)); 9861 BCM_IF_ERROR_RETURN 9862 (soc_counter_set(unit, local_port, 9863 SOC_COUNTER_NON_DMA_PORT_WRED_PKT_YELLOW, 0, 9864 value)); 9865 break; 9866 case bcmCosqStatRedDiscardDroppedPackets: 9867 if (cosq != BCM_COS_INVALID) { 9868 return BCM_E_UNAVAIL; 9869 } 9870 BCM_IF_ERROR_RETURN 9871 (_bcm_td2_cosq_localport_resolve(unit, port, &local_port)); 9872 BCM_IF_ERROR_RETURN 9873 (soc_counter_set(unit, local_port, 9874 SOC_COUNTER_NON_DMA_PORT_WRED_PKT_RED, 0, value)); 9875 break; 9876 case bcmCosqStatOutPackets: 9877 if (BCM_GPORT_IS_SCHEDULER(port)) { 9878 BCM_IF_ERROR_RETURN 9879 (_bcm_td2_cosq_node_get(unit, port, 0, NULL, 9880 &local_port, NULL, &node)); 9881 BCM_IF_ERROR_RETURN( 9882 _bcm_td2_cosq_child_node_at_input(node, cosq, &node)); 9883 port = node->gport; 9884 } 9885 9886 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) { 9887 BCM_IF_ERROR_RETURN 9888 (_bcm_td2_cosq_node_get(unit, port, 0, NULL, 9889 &local_port, NULL, &node)); 9890 if ((node->type == _BCM_TD2_NODE_VM_UCAST) || 9891 (node->type == _BCM_TD2_NODE_SERVICE_UCAST)) { 9892 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9893 BCM_IF_ERROR_RETURN 9894 (soc_counter_set(unit, local_port, 9895 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT_EXT, node->hw_index, 9896 value)); 9897 } else { 9898 BCM_IF_ERROR_RETURN 9899 (_bcm_td2_cosq_index_resolve 9900 (unit, port, cosq, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_UCAST, 9901 &local_port, &startq, NULL)); 9902 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9903 BCM_IF_ERROR_RETURN 9904 (soc_counter_set(unit, local_port, 9905 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT_UC, startq, 9906 value)); 9907 } 9908 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 9909 BCM_IF_ERROR_RETURN 9910 (_bcm_td2_cosq_index_resolve 9911 (unit, port, cosq, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_MCAST, 9912 &local_port, &startq, NULL)); 9913 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9914 BCM_IF_ERROR_RETURN 9915 (soc_counter_set(unit, local_port, 9916 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT, startq, 9917 value)); 9918 } else { 9919 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_localport_resolve(unit, port, &local_port)); 9920 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_port_has_ets(unit, local_port)); 9921 if (cosq == BCM_COS_INVALID) { 9922 from_cos = to_cos = 0; 9923 } else { 9924 from_cos = to_cos = cosq; 9925 } 9926 for (ci = from_cos; ci <= to_cos; ci++) { 9927 if (!IS_CPU_PORT(unit, local_port)) { 9928 BCM_IF_ERROR_RETURN 9929 (_bcm_td2_cosq_index_resolve 9930 (unit, port, ci, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_UCAST, 9931 &local_port, &startq, &numq)); 9932 for (i = 0; i < numq; i++) { 9933 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9934 BCM_IF_ERROR_RETURN 9935 (soc_counter_set(unit, local_port, 9936 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT_UC, 9937 startq + i, l)); 9938 } 9939 } 9940 BCM_IF_ERROR_RETURN 9941 (_bcm_td2_cosq_index_resolve 9942 (unit, port, ci, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_MCAST, 9943 &local_port, &startq, &numq)); 9944 for (i = 0; i < numq; i++) { 9945 BCM_IF_ERROR_RETURN 9946 (soc_counter_set(unit, local_port, 9947 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT, 9948 startq + i, r)); 9949 } 9950 } 9951 } 9952 break; 9953 case bcmCosqStatOutBytes: 9954 if (BCM_GPORT_IS_SCHEDULER(port)) { 9955 BCM_IF_ERROR_RETURN 9956 (_bcm_td2_cosq_node_get(unit, port, 0, NULL, 9957 &local_port, NULL, &node)); 9958 BCM_IF_ERROR_RETURN( 9959 _bcm_td2_cosq_child_node_at_input(node, cosq, &node)); 9960 port = node->gport; 9961 } 9962 9963 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) { 9964 BCM_IF_ERROR_RETURN 9965 (_bcm_td2_cosq_node_get(unit, port, 0, NULL, 9966 &local_port, NULL, &node)); 9967 if ((node->type == _BCM_TD2_NODE_VM_UCAST) || 9968 (node->type == _BCM_TD2_NODE_SERVICE_UCAST)) { 9969 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9970 BCM_IF_ERROR_RETURN 9971 (soc_counter_set(unit, local_port, 9972 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE_EXT, node->hw_index, 9973 value)); 9974 } else { 9975 BCM_IF_ERROR_RETURN 9976 (_bcm_td2_cosq_index_resolve 9977 (unit, port, cosq, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_UCAST, 9978 &local_port, &startq, NULL)); 9979 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9980 BCM_IF_ERROR_RETURN 9981 (soc_counter_set(unit, local_port, 9982 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE_UC, startq, 9983 value)); 9984 } 9985 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 9986 BCM_IF_ERROR_RETURN 9987 (_bcm_td2_cosq_index_resolve 9988 (unit, port, cosq, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_MCAST, 9989 &local_port, &startq, NULL)); 9990 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9991 BCM_IF_ERROR_RETURN 9992 (soc_counter_set(unit, local_port, 9993 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE, startq, 9994 value)); 9995 } else { 9996 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_localport_resolve(unit, port, &local_port)); 9997 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_port_has_ets(unit, local_port)); 9998 if (cosq == BCM_COS_INVALID) { 9999 from_cos = to_cos = 0; 10000 } else { 10001 from_cos = to_cos = cosq; 10002 } 10003 for (ci = from_cos; ci <= to_cos; ci++) { 10004 if (!IS_CPU_PORT(unit, local_port)) { 10005 BCM_IF_ERROR_RETURN 10006 (_bcm_td2_cosq_index_resolve 10007 (unit, port, ci, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_UCAST, 10008 &local_port, &startq, &numq)); 10009 for (i = 0; i < numq; i++) { 10010 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10011 BCM_IF_ERROR_RETURN 10012 (soc_counter_set(unit, local_port, 10013 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE_UC, 10014 startq + i, l)); 10015 } 10016 } 10017 BCM_IF_ERROR_RETURN 10018 (_bcm_td2_cosq_index_resolve 10019 (unit, port, ci, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_MCAST, 10020 &local_port, &startq, &numq)); 10021 for (i = 0; i < numq; i++) { 10022 BCM_IF_ERROR_RETURN 10023 (soc_counter_set(unit, local_port, 10024 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE, 10025 startq + i, r)); 10026 } 10027 } 10028 } 10029 break; 10030 case bcmCosqStatUCOutPackets: 10031 case bcmCosqStatUCOutBytes: 10032 if (BCM_GPORT_IS_SCHEDULER(port)) { 10033 BCM_IF_ERROR_RETURN 10034 (_bcm_td2_cosq_node_get(unit, port, 0, NULL, 10035 &local_port, NULL, &node)); 10036 BCM_IF_ERROR_RETURN( 10037 _bcm_td2_cosq_child_node_at_input(node, cosq, &node)); 10038 port = node->gport; 10039 } 10040 10041 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) { 10042 soc_reg_t ctr_reg_uc; 10043 BCM_IF_ERROR_RETURN 10044 (_bcm_td2_cosq_node_get(unit, port, 0, NULL, 10045 &local_port, NULL, &node)); 10046 if ((node->type == _BCM_TD2_NODE_VM_UCAST) || 10047 (node->type == _BCM_TD2_NODE_SERVICE_UCAST)) { 10048 ctr_reg_uc = (stat == bcmCosqStatUCOutPackets) ? 10049 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT_EXT : 10050 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE_EXT; 10051 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10052 BCM_IF_ERROR_RETURN 10053 (soc_counter_set(unit, local_port, ctr_reg_uc, node->hw_index, value)); 10054 } else { 10055 ctr_reg_uc = (stat == bcmCosqStatUCOutPackets) ? 10056 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT_UC : 10057 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE_UC; 10058 BCM_IF_ERROR_RETURN 10059 (_bcm_td2_cosq_index_resolve 10060 (unit, port, cosq, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_UCAST, 10061 &local_port, &startq, NULL)); 10062 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10063 BCM_IF_ERROR_RETURN 10064 (soc_counter_set(unit, local_port, ctr_reg_uc, startq, value)); 10065 } 10066 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 10067 return BCM_E_PARAM; 10068 } else { 10069 soc_reg_t ctr_reg_uc; 10070 ctr_reg_uc = (stat == bcmCosqStatUCOutPackets) ? 10071 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT_UC : 10072 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE_UC; 10073 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_localport_resolve(unit, port, &local_port)); 10074 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_port_has_ets(unit, local_port)); 10075 if (cosq == BCM_COS_INVALID) { 10076 from_cos = to_cos = 0; 10077 } else { 10078 from_cos = to_cos = cosq; 10079 } 10080 for (ci = from_cos; ci <= to_cos; ci++) { 10081 if (!IS_CPU_PORT(unit, local_port)) { 10082 BCM_IF_ERROR_RETURN 10083 (_bcm_td2_cosq_index_resolve 10084 (unit, port, ci, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_UCAST, 10085 &local_port, &startq, &numq)); 10086 for (i = 0; i < numq; i++) { 10087 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10088 BCM_IF_ERROR_RETURN 10089 (soc_counter_set(unit, local_port, ctr_reg_uc, startq + i, value)); 10090 } 10091 } 10092 } 10093 } 10094 break; 10095 case bcmCosqStatMCOutPackets: 10096 case bcmCosqStatMCOutBytes: 10097 if (BCM_GPORT_IS_SCHEDULER(port)) { 10098 BCM_IF_ERROR_RETURN 10099 (_bcm_td2_cosq_node_get(unit, port, 0, NULL, 10100 &local_port, NULL, &node)); 10101 BCM_IF_ERROR_RETURN( 10102 _bcm_td2_cosq_child_node_at_input(node, cosq, &node)); 10103 port = node->gport; 10104 } 10105 10106 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) { 10107 return BCM_E_PARAM; 10108 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 10109 soc_reg_t ctr_reg_mc = (stat == bcmCosqStatMCOutPackets) ? 10110 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT : 10111 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE; 10112 BCM_IF_ERROR_RETURN 10113 (_bcm_td2_cosq_index_resolve 10114 (unit, port, cosq, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_MCAST, 10115 &local_port, &startq, NULL)); 10116 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10117 BCM_IF_ERROR_RETURN 10118 (soc_counter_set(unit, local_port, ctr_reg_mc, startq, value)); 10119 } else { 10120 soc_reg_t ctr_reg_mc = (stat == bcmCosqStatMCOutPackets) ? 10121 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT : 10122 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE; 10123 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_localport_resolve(unit, port, &local_port)); 10124 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_port_has_ets(unit, local_port)); 10125 if (cosq == BCM_COS_INVALID) { 10126 from_cos = to_cos = 0; 10127 } else { 10128 from_cos = to_cos = cosq; 10129 } 10130 for (ci = from_cos; ci <= to_cos; ci++) { 10131 BCM_IF_ERROR_RETURN 10132 (_bcm_td2_cosq_index_resolve 10133 (unit, port, ci, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_MCAST, 10134 &local_port, &startq, &numq)); 10135 for (i = 0; i < numq; i++) { 10136 BCM_IF_ERROR_RETURN 10137 (soc_counter_set(unit, local_port, ctr_reg_mc, startq + i, value)); 10138 } 10139 } 10140 } 10141 break; 10142 case bcmCosqStatIeee8021CnCpTransmittedCnms: 10143 BCM_IF_ERROR_RETURN 10144 (_bcm_td2_cosq_index_resolve 10145 (unit, port, cosq, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_UCAST, 10146 &local_port, &startq, NULL)); 10147 BCM_IF_ERROR_RETURN 10148 (soc_counter_set(unit, local_port, 10149 SOC_COUNTER_NON_DMA_MMU_QCN_CNM, startq, value)); 10150 break; 10151 case bcmCosqStatHighPriDroppedPackets: 10152 if (cosq != BCM_COS_INVALID) { 10153 return BCM_E_UNAVAIL; 10154 } 10155 BCM_IF_ERROR_RETURN 10156 (_bcm_td2_cosq_localport_resolve(unit, port, &local_port)); 10157 BCM_IF_ERROR_RETURN 10158 (id = _port_l2c_mapping(unit,local_port,bcmCosqStatHighPriDroppedPackets,&xlp_port)); 10159 BCM_IF_ERROR_RETURN 10160 (soc_counter_set(unit, local_port, id, xlp_port, value)); 10161 break; 10162 case bcmCosqStatLowPriDroppedPackets: 10163 if (cosq != BCM_COS_INVALID) { 10164 return BCM_E_UNAVAIL; 10165 } 10166 10167 BCM_IF_ERROR_RETURN 10168 (_bcm_td2_cosq_localport_resolve(unit, port, &local_port)); 10169 BCM_IF_ERROR_RETURN 10170 (id = _port_l2c_mapping(unit,local_port,bcmCosqStatLowPriDroppedPackets,&xlp_port)); 10171 BCM_IF_ERROR_RETURN 10172 (soc_counter_set(unit, local_port, id, xlp_port, value)); 10173 break; 10174 case bcmCosqStatHighPriDroppedBytes: 10175 if (cosq != BCM_COS_INVALID) { 10176 return BCM_E_UNAVAIL; 10177 } 10178 10179 BCM_IF_ERROR_RETURN 10180 (_bcm_td2_cosq_localport_resolve(unit, port, &local_port)); 10181 BCM_IF_ERROR_RETURN 10182 (id = _port_l2c_mapping(unit,local_port,bcmCosqStatHighPriDroppedBytes,&xlp_port)); 10183 BCM_IF_ERROR_RETURN 10184 (soc_counter_set(unit, local_port, id, xlp_port, value)); 10185 break; 10186 case bcmCosqStatLowPriDroppedBytes: 10187 if (cosq != BCM_COS_INVALID) { 10188 return BCM_E_UNAVAIL; 10189 } 10190 10191 BCM_IF_ERROR_RETURN 10192 (_bcm_td2_cosq_localport_resolve(unit, port, &local_port)); 10193 BCM_IF_ERROR_RETURN 10194 (id = _port_l2c_mapping(unit,local_port,bcmCosqStatLowPriDroppedBytes,&xlp_port)); 10195 BCM_IF_ERROR_RETURN 10196 (soc_counter_set(unit, local_port, id, xlp_port, value)); 10197 break; 10198 default: 10199 return BCM_E_PARAM; 10200 } 10201 10202 return BCM_E_NONE; 10203 } 10204 10205 int 10206 bcm_td2_cosq_stat_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 10207 bcm_cosq_stat_t stat, int sync_mode, uint64 *value) 10208 { 10209 _bcm_td2_cosq_node_t *node; 10210 bcm_port_t local_port; 10211 int startq, numq, i, from_cos, to_cos, ci, start_hw_index, end_hw_index; 10212 uint64 sum, value64; 10213 uint32 sum32, value32; 10214 soc_counter_non_dma_id_t id; 10215 int xlp_port; 10216 int (*counter_get) (int , soc_port_t , soc_reg_t , int , uint64 *); 10217 int pool, midx, valid; 10218 uint32 entry[SOC_MAX_MEM_WORDS], rval; 10219 soc_mem_t mem = INVALIDm; 10220 soc_field_t field = INVALIDf; 10221 10222 if ((value == NULL) || (cosq < -1)) { 10223 return BCM_E_PARAM; 10224 } 10225 10226 /* 10227 * if sync-mode is set, update the software cached counter value, 10228 * with the hardware count and then retrieve the count. 10229 * else return the software cache counter value. 10230 */ 10231 counter_get = (sync_mode == 1)? soc_counter_sync_get: soc_counter_get; 10232 COMPILER_64_ZERO(*value); 10233 value32 = 0; 10234 10235 switch (stat) { 10236 case bcmCosqStatDroppedPackets: 10237 if (BCM_GPORT_IS_SCHEDULER(port)) { 10238 BCM_IF_ERROR_RETURN 10239 (_bcm_td2_cosq_node_get(unit, port, 0, NULL, 10240 &local_port, NULL, &node)); 10241 BCM_IF_ERROR_RETURN( 10242 _bcm_td2_cosq_child_node_at_input(node, cosq, &node)); 10243 port = node->gport; 10244 } 10245 10246 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) { 10247 BCM_IF_ERROR_RETURN 10248 (_bcm_td2_cosq_node_get(unit, port, 0, NULL, 10249 &local_port, NULL, &node)); 10250 if ((node->type == _BCM_TD2_NODE_VM_UCAST) || 10251 (node->type == _BCM_TD2_NODE_SERVICE_UCAST)) { 10252 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10253 BCM_IF_ERROR_RETURN 10254 (counter_get(unit, local_port, 10255 SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_EXT, node->hw_index, 10256 value)); 10257 } else { 10258 BCM_IF_ERROR_RETURN 10259 (_bcm_td2_cosq_index_resolve 10260 (unit, port, cosq, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_UCAST, 10261 &local_port, &startq, NULL)); 10262 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10263 BCM_IF_ERROR_RETURN 10264 (counter_get(unit, local_port, 10265 SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_UC, startq, 10266 value)); 10267 } 10268 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 10269 BCM_IF_ERROR_RETURN 10270 (_bcm_td2_cosq_index_resolve 10271 (unit, port, cosq, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_MCAST, 10272 &local_port, &startq, NULL)); 10273 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10274 BCM_IF_ERROR_RETURN 10275 (counter_get(unit, local_port, 10276 SOC_COUNTER_NON_DMA_COSQ_DROP_PKT, startq, value)); 10277 } else { 10278 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_localport_resolve(unit, port, &local_port)); 10279 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_port_has_ets(unit, local_port)); 10280 COMPILER_64_ZERO(sum); 10281 if (cosq == BCM_COS_INVALID) { 10282 from_cos = 0; 10283 to_cos = (IS_CPU_PORT(unit, local_port)) ? 10284 NUM_CPU_COSQ(unit) - 1 : _TD2_NUM_COS(unit) - 1; 10285 } else { 10286 from_cos = to_cos = cosq; 10287 } 10288 for (ci = from_cos; ci <= to_cos; ci++) { 10289 if (!IS_CPU_PORT(unit, local_port)) { 10290 BCM_IF_ERROR_RETURN 10291 (_bcm_td2_cosq_index_resolve 10292 (unit, port, ci, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_UCAST, 10293 &local_port, &startq, &numq)); 10294 for (i = 0; i < numq; i++) { 10295 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10296 BCM_IF_ERROR_RETURN 10297 (counter_get(unit, local_port, 10298 SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_UC, 10299 startq + i, &value64)); 10300 COMPILER_64_ADD_64(sum, value64); 10301 } 10302 } 10303 BCM_IF_ERROR_RETURN 10304 (_bcm_td2_cosq_index_resolve 10305 (unit, port, ci, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_MCAST, 10306 &local_port, &startq, &numq)); 10307 10308 for (i = 0; i < numq; i++) { 10309 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10310 BCM_IF_ERROR_RETURN 10311 (counter_get(unit, local_port, 10312 SOC_COUNTER_NON_DMA_COSQ_DROP_PKT, 10313 startq + i, &value64)); 10314 COMPILER_64_ADD_64(sum, value64); 10315 } 10316 } 10317 *value = sum; 10318 } 10319 break; 10320 case bcmCosqStatDroppedBytes: 10321 if (BCM_GPORT_IS_SCHEDULER(port)) { 10322 BCM_IF_ERROR_RETURN 10323 (_bcm_td2_cosq_node_get(unit, port, 0, NULL, 10324 &local_port, NULL, &node)); 10325 BCM_IF_ERROR_RETURN( 10326 _bcm_td2_cosq_child_node_at_input(node, cosq, &node)); 10327 port = node->gport; 10328 } 10329 10330 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) { 10331 BCM_IF_ERROR_RETURN 10332 (_bcm_td2_cosq_node_get(unit, port, 0, NULL, 10333 &local_port, NULL, &node)); 10334 if ((node->type == _BCM_TD2_NODE_VM_UCAST) || 10335 (node->type == _BCM_TD2_NODE_SERVICE_UCAST)) { 10336 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10337 BCM_IF_ERROR_RETURN 10338 (counter_get(unit, local_port, 10339 SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE_EXT, node->hw_index, 10340 value)); 10341 } else { 10342 BCM_IF_ERROR_RETURN 10343 (_bcm_td2_cosq_index_resolve 10344 (unit, port, cosq, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_UCAST, 10345 &local_port, &startq, NULL)); 10346 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10347 BCM_IF_ERROR_RETURN 10348 (counter_get(unit, local_port, 10349 SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE_UC, startq, 10350 value)); 10351 } 10352 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 10353 BCM_IF_ERROR_RETURN 10354 (_bcm_td2_cosq_index_resolve 10355 (unit, port, cosq, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_MCAST, 10356 &local_port, &startq, NULL)); 10357 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10358 BCM_IF_ERROR_RETURN 10359 (counter_get(unit, local_port, 10360 SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE, startq, value)); 10361 } else { 10362 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_localport_resolve(unit, port, &local_port)); 10363 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_port_has_ets(unit, local_port)); 10364 COMPILER_64_ZERO(sum); 10365 if (cosq == BCM_COS_INVALID) { 10366 from_cos = 0; 10367 to_cos = (IS_CPU_PORT(unit, local_port)) ? 10368 NUM_CPU_COSQ(unit) - 1 : _TD2_NUM_COS(unit) - 1; 10369 } else { 10370 from_cos = to_cos = cosq; 10371 } 10372 for (ci = from_cos; ci <= to_cos; ci++) { 10373 if (!IS_CPU_PORT(unit, local_port)) { 10374 BCM_IF_ERROR_RETURN 10375 (_bcm_td2_cosq_index_resolve 10376 (unit, port, ci, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_UCAST, 10377 &local_port, &startq, &numq)); 10378 for (i = 0; i < numq; i++) { 10379 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10380 BCM_IF_ERROR_RETURN 10381 (counter_get(unit, local_port, 10382 SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE_UC, 10383 startq + i, &value64)); 10384 COMPILER_64_ADD_64(sum, value64); 10385 } 10386 } 10387 BCM_IF_ERROR_RETURN 10388 (_bcm_td2_cosq_index_resolve 10389 (unit, port, ci, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_MCAST, 10390 &local_port, &startq, &numq)); 10391 for (i = 0; i < numq; i++) { 10392 BCM_IF_ERROR_RETURN 10393 (counter_get(unit, local_port, 10394 SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE, 10395 startq + i, &value64)); 10396 COMPILER_64_ADD_64(sum, value64); 10397 } 10398 } 10399 *value = sum; 10400 } 10401 break; 10402 case bcmCosqStatYellowCongestionDroppedPackets: 10403 if (cosq != BCM_COS_INVALID) { 10404 return BCM_E_UNAVAIL; 10405 } 10406 BCM_IF_ERROR_RETURN 10407 (_bcm_td2_cosq_localport_resolve(unit, port, &local_port)); 10408 BCM_IF_ERROR_RETURN 10409 (counter_get(unit, local_port, 10410 SOC_COUNTER_NON_DMA_PORT_DROP_PKT_YELLOW, 0, 10411 value)); 10412 break; 10413 case bcmCosqStatRedCongestionDroppedPackets: 10414 if (cosq != BCM_COS_INVALID) { 10415 return BCM_E_UNAVAIL; 10416 } 10417 BCM_IF_ERROR_RETURN 10418 (_bcm_td2_cosq_localport_resolve(unit, port, &local_port)); 10419 BCM_IF_ERROR_RETURN 10420 (counter_get(unit, local_port, 10421 SOC_COUNTER_NON_DMA_PORT_DROP_PKT_RED, 0, 10422 value)); 10423 break; 10424 case bcmCosqStatGreenDiscardDroppedPackets: 10425 if (cosq != BCM_COS_INVALID) { 10426 return BCM_E_UNAVAIL; 10427 } 10428 BCM_IF_ERROR_RETURN 10429 (_bcm_td2_cosq_localport_resolve(unit, port, &local_port)); 10430 BCM_IF_ERROR_RETURN 10431 (counter_get(unit, local_port, 10432 SOC_COUNTER_NON_DMA_PORT_WRED_PKT_GREEN, 0, 10433 value)); 10434 break; 10435 case bcmCosqStatYellowDiscardDroppedPackets: 10436 if (cosq != BCM_COS_INVALID) { 10437 return BCM_E_UNAVAIL; 10438 } 10439 BCM_IF_ERROR_RETURN 10440 (_bcm_td2_cosq_localport_resolve(unit, port, &local_port)); 10441 BCM_IF_ERROR_RETURN 10442 (counter_get(unit, local_port, 10443 SOC_COUNTER_NON_DMA_PORT_WRED_PKT_YELLOW, 0, 10444 value)); 10445 break; 10446 case bcmCosqStatRedDiscardDroppedPackets: 10447 if (cosq != BCM_COS_INVALID) { 10448 return BCM_E_UNAVAIL; 10449 } 10450 BCM_IF_ERROR_RETURN 10451 (_bcm_td2_cosq_localport_resolve(unit, port, &local_port)); 10452 BCM_IF_ERROR_RETURN 10453 (counter_get(unit, local_port, 10454 SOC_COUNTER_NON_DMA_PORT_WRED_PKT_RED, 0, value)); 10455 break; 10456 case bcmCosqStatOutPackets: 10457 if (BCM_GPORT_IS_SCHEDULER(port)) { 10458 BCM_IF_ERROR_RETURN 10459 (_bcm_td2_cosq_node_get(unit, port, 0, NULL, 10460 &local_port, NULL, &node)); 10461 BCM_IF_ERROR_RETURN( 10462 _bcm_td2_cosq_child_node_at_input(node, cosq, &node)); 10463 port = node->gport; 10464 } 10465 10466 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) { 10467 BCM_IF_ERROR_RETURN 10468 (_bcm_td2_cosq_node_get(unit, port, 0, NULL, 10469 &local_port, NULL, &node)); 10470 if ((node->type == _BCM_TD2_NODE_VM_UCAST) || 10471 (node->type == _BCM_TD2_NODE_SERVICE_UCAST)) { 10472 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10473 BCM_IF_ERROR_RETURN 10474 (counter_get(unit, local_port, 10475 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT_EXT, node->hw_index, 10476 value)); 10477 10478 } else { 10479 BCM_IF_ERROR_RETURN 10480 (_bcm_td2_cosq_index_resolve 10481 (unit, port, cosq, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_UCAST, 10482 &local_port, &startq, NULL)); 10483 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10484 BCM_IF_ERROR_RETURN 10485 (counter_get(unit, local_port, 10486 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT_UC, startq, 10487 value)); 10488 } 10489 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 10490 BCM_IF_ERROR_RETURN 10491 (_bcm_td2_cosq_index_resolve 10492 (unit, port, cosq, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_MCAST, 10493 &local_port, &startq, NULL)); 10494 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10495 BCM_IF_ERROR_RETURN 10496 (counter_get(unit, local_port, 10497 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT, startq, 10498 value)); 10499 } else { 10500 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_localport_resolve(unit, port, &local_port)); 10501 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_port_has_ets(unit, local_port)); 10502 COMPILER_64_ZERO(sum); 10503 if (cosq == BCM_COS_INVALID) { 10504 from_cos = 0; 10505 to_cos = (IS_CPU_PORT(unit, local_port)) ? 10506 NUM_CPU_COSQ(unit) - 1 : _TD2_NUM_COS(unit) - 1; 10507 } else { 10508 from_cos = to_cos = cosq; 10509 } 10510 10511 for (ci = from_cos; ci <= to_cos; ci++) { 10512 if (!IS_CPU_PORT(unit, local_port)) { 10513 BCM_IF_ERROR_RETURN 10514 (_bcm_td2_cosq_index_resolve 10515 (unit, port, ci, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_UCAST, 10516 &local_port, &startq, &numq)); 10517 for (i = 0; i < numq; i++) { 10518 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10519 BCM_IF_ERROR_RETURN 10520 (counter_get(unit, local_port, 10521 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT_UC, 10522 startq + i, &value64)); 10523 COMPILER_64_ADD_64(sum, value64); 10524 } 10525 } 10526 BCM_IF_ERROR_RETURN 10527 (_bcm_td2_cosq_index_resolve 10528 (unit, port, ci, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_MCAST, 10529 &local_port, &startq, &numq)); 10530 for (i = 0; i < numq; i++) { 10531 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10532 BCM_IF_ERROR_RETURN 10533 (counter_get(unit, local_port, 10534 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT, 10535 startq + i, &value64)); 10536 COMPILER_64_ADD_64(sum, value64); 10537 } 10538 } 10539 *value = sum; 10540 } 10541 break; 10542 case bcmCosqStatOutBytes: 10543 if (BCM_GPORT_IS_SCHEDULER(port)) { 10544 BCM_IF_ERROR_RETURN 10545 (_bcm_td2_cosq_node_get(unit, port, 0, NULL, 10546 &local_port, NULL, &node)); 10547 BCM_IF_ERROR_RETURN( 10548 _bcm_td2_cosq_child_node_at_input(node, cosq, &node)); 10549 port = node->gport; 10550 } 10551 10552 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) { 10553 BCM_IF_ERROR_RETURN 10554 (_bcm_td2_cosq_node_get(unit, port, 0, NULL, 10555 &local_port, NULL, &node)); 10556 if ((node->type == _BCM_TD2_NODE_VM_UCAST) || 10557 (node->type == _BCM_TD2_NODE_SERVICE_UCAST)) { 10558 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10559 BCM_IF_ERROR_RETURN 10560 (counter_get(unit, local_port, 10561 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE_EXT, node->hw_index, 10562 value)); 10563 10564 } else { 10565 BCM_IF_ERROR_RETURN 10566 (_bcm_td2_cosq_index_resolve 10567 (unit, port, cosq, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_UCAST, 10568 &local_port, &startq, NULL)); 10569 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10570 BCM_IF_ERROR_RETURN 10571 (counter_get(unit, local_port, 10572 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE_UC, startq, 10573 value)); 10574 } 10575 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 10576 BCM_IF_ERROR_RETURN 10577 (_bcm_td2_cosq_index_resolve 10578 (unit, port, cosq, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_MCAST, 10579 &local_port, &startq, NULL)); 10580 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10581 BCM_IF_ERROR_RETURN 10582 (counter_get(unit, local_port, 10583 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE, startq, 10584 value)); 10585 } else { 10586 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_localport_resolve(unit, port, &local_port)); 10587 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_port_has_ets(unit, local_port)); 10588 COMPILER_64_ZERO(sum); 10589 if (cosq == BCM_COS_INVALID) { 10590 from_cos = 0; 10591 to_cos = (IS_CPU_PORT(unit, local_port)) ? 10592 NUM_CPU_COSQ(unit) - 1 : _TD2_NUM_COS(unit) - 1; 10593 } else { 10594 from_cos = to_cos = cosq; 10595 } 10596 10597 for (ci = from_cos; ci <= to_cos; ci++) { 10598 if (!IS_CPU_PORT(unit, local_port)) { 10599 BCM_IF_ERROR_RETURN 10600 (_bcm_td2_cosq_index_resolve 10601 (unit, port, ci, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_UCAST, 10602 &local_port, &startq, &numq)); 10603 for (i = 0; i < numq; i++) { 10604 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10605 BCM_IF_ERROR_RETURN 10606 (counter_get(unit, local_port, 10607 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE_UC, 10608 startq + i, &value64)); 10609 COMPILER_64_ADD_64(sum, value64); 10610 } 10611 } 10612 BCM_IF_ERROR_RETURN 10613 (_bcm_td2_cosq_index_resolve 10614 (unit, port, ci, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_MCAST, 10615 &local_port, &startq, &numq)); 10616 for (i = 0; i < numq; i++) { 10617 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10618 BCM_IF_ERROR_RETURN 10619 (counter_get(unit, local_port, 10620 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE, 10621 startq + i, &value64)); 10622 COMPILER_64_ADD_64(sum, value64); 10623 } 10624 } 10625 *value = sum; 10626 } 10627 break; 10628 case bcmCosqStatUCOutPackets: 10629 case bcmCosqStatUCOutBytes: 10630 if (BCM_GPORT_IS_SCHEDULER(port)) { 10631 BCM_IF_ERROR_RETURN 10632 (_bcm_td2_cosq_node_get(unit, port, 0, NULL, 10633 &local_port, NULL, &node)); 10634 BCM_IF_ERROR_RETURN( 10635 _bcm_td2_cosq_child_node_at_input(node, cosq, &node)); 10636 port = node->gport; 10637 } 10638 10639 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) { 10640 BCM_IF_ERROR_RETURN 10641 (_bcm_td2_cosq_node_get(unit, port, 0, NULL, 10642 &local_port, NULL, &node)); 10643 if ((node->type == _BCM_TD2_NODE_VM_UCAST) || 10644 (node->type == _BCM_TD2_NODE_SERVICE_UCAST)) { 10645 soc_reg_t ctr_reg_uc = (stat == bcmCosqStatUCOutPackets) ? 10646 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT_EXT : 10647 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE_EXT; 10648 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10649 BCM_IF_ERROR_RETURN 10650 (counter_get(unit, local_port, ctr_reg_uc, node->hw_index, value)); 10651 10652 } else { 10653 soc_reg_t ctr_reg_uc = (stat == bcmCosqStatUCOutPackets) ? 10654 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT_UC : 10655 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE_UC; 10656 BCM_IF_ERROR_RETURN 10657 (_bcm_td2_cosq_index_resolve 10658 (unit, port, cosq, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_UCAST, 10659 &local_port, &startq, NULL)); 10660 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10661 BCM_IF_ERROR_RETURN 10662 (counter_get(unit, local_port, ctr_reg_uc, startq, value)); 10663 } 10664 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 10665 return BCM_E_PARAM; 10666 } else { 10667 soc_reg_t ctr_reg_uc = (stat == bcmCosqStatUCOutPackets) ? 10668 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT_UC : 10669 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE_UC; 10670 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_localport_resolve(unit, port, &local_port)); 10671 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_port_has_ets(unit, local_port)); 10672 COMPILER_64_ZERO(sum); 10673 if (cosq == BCM_COS_INVALID) { 10674 from_cos = 0; 10675 to_cos = (IS_CPU_PORT(unit, local_port)) ? 10676 NUM_CPU_COSQ(unit) - 1 : _TD2_NUM_COS(unit) - 1; 10677 } else { 10678 from_cos = to_cos = cosq; 10679 } 10680 10681 for (ci = from_cos; ci <= to_cos; ci++) { 10682 if (!IS_CPU_PORT(unit, local_port)) { 10683 BCM_IF_ERROR_RETURN 10684 (_bcm_td2_cosq_index_resolve 10685 (unit, port, ci, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_UCAST, 10686 &local_port, &startq, &numq)); 10687 for (i = 0; i < numq; i++) { 10688 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10689 BCM_IF_ERROR_RETURN 10690 (counter_get(unit, local_port, ctr_reg_uc, startq + i, &value64)); 10691 COMPILER_64_ADD_64(sum, value64); 10692 } 10693 } 10694 } 10695 *value = sum; 10696 } 10697 break; 10698 case bcmCosqStatMCOutPackets: 10699 case bcmCosqStatMCOutBytes: 10700 if (BCM_GPORT_IS_SCHEDULER(port)) { 10701 BCM_IF_ERROR_RETURN 10702 (_bcm_td2_cosq_node_get(unit, port, 0, NULL, 10703 &local_port, NULL, &node)); 10704 BCM_IF_ERROR_RETURN( 10705 _bcm_td2_cosq_child_node_at_input(node, cosq, &node)); 10706 port = node->gport; 10707 } 10708 10709 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) { 10710 return BCM_E_PARAM; 10711 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 10712 soc_reg_t ctr_reg_mc = ( stat == bcmCosqStatMCOutPackets ) ? 10713 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT : 10714 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE; 10715 BCM_IF_ERROR_RETURN 10716 (_bcm_td2_cosq_index_resolve 10717 (unit, port, cosq, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_MCAST, 10718 &local_port, &startq, NULL)); 10719 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10720 BCM_IF_ERROR_RETURN 10721 (counter_get(unit, local_port, ctr_reg_mc, startq, value)); 10722 } else { 10723 soc_reg_t ctr_reg_mc = ( stat == bcmCosqStatMCOutPackets ) ? 10724 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT : 10725 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE; 10726 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_localport_resolve(unit, port, &local_port)); 10727 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_port_has_ets(unit, local_port)); 10728 COMPILER_64_ZERO(sum); 10729 if (cosq == BCM_COS_INVALID) { 10730 from_cos = 0; 10731 to_cos = (IS_CPU_PORT(unit, local_port)) ? 10732 NUM_CPU_COSQ(unit) - 1 : _TD2_NUM_COS(unit) - 1; 10733 } else { 10734 from_cos = to_cos = cosq; 10735 } 10736 10737 for (ci = from_cos; ci <= to_cos; ci++) { 10738 BCM_IF_ERROR_RETURN 10739 (_bcm_td2_cosq_index_resolve 10740 (unit, port, ci, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_MCAST, 10741 &local_port, &startq, &numq)); 10742 for (i = 0; i < numq; i++) { 10743 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10744 BCM_IF_ERROR_RETURN 10745 (counter_get(unit, local_port, ctr_reg_mc, startq + i, &value64)); 10746 COMPILER_64_ADD_64(sum, value64); 10747 } 10748 } 10749 *value = sum; 10750 } 10751 break; 10752 case bcmCosqStatIeee8021CnCpTransmittedCnms: 10753 BCM_IF_ERROR_RETURN 10754 (_bcm_td2_cosq_index_resolve 10755 (unit, port, cosq, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_UCAST, 10756 &local_port, &startq, NULL)); 10757 BCM_IF_ERROR_RETURN 10758 (counter_get(unit, local_port, 10759 SOC_COUNTER_NON_DMA_MMU_QCN_CNM, startq, value)); 10760 break; 10761 case bcmCosqStatIngressPortPoolSharedBytesPeak: 10762 10763 COMPILER_64_ZERO(sum); 10764 BCM_IF_ERROR_RETURN 10765 (_bcm_td2_cosq_ingress_sp_get(unit, port, cosq, 10766 &start_hw_index, &end_hw_index)); 10767 10768 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_localport_resolve(unit, port, &local_port)); 10769 for (i = start_hw_index; i <= end_hw_index; i++) { 10770 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10771 BCM_IF_ERROR_RETURN 10772 (counter_get(unit, local_port, 10773 SOC_COUNTER_NON_DMA_POOL_PEAK, 10774 i, &value64)); 10775 COMPILER_64_ADD_64(sum, value64); 10776 } 10777 10778 COMPILER_64_UMUL_32(sum, _BCM_TD2_BYTES_PER_CELL); 10779 *value = sum; 10780 break; 10781 case bcmCosqStatIngressPortPoolSharedBytesCurrent: 10782 10783 BCM_IF_ERROR_RETURN 10784 (_bcm_td2_cosq_ingress_sp_get(unit, port, cosq, 10785 &start_hw_index, &end_hw_index)); 10786 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_localport_resolve(unit, port, &local_port)); 10787 10788 COMPILER_64_ZERO(sum); 10789 for (i = start_hw_index; i <= end_hw_index; i++) { 10790 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10791 BCM_IF_ERROR_RETURN 10792 (counter_get(unit, local_port, 10793 SOC_COUNTER_NON_DMA_POOL_CURRENT, 10794 i, &value64)); 10795 COMPILER_64_ADD_64(sum, value64); 10796 } 10797 10798 COMPILER_64_UMUL_32(sum, _BCM_TD2_BYTES_PER_CELL); 10799 *value = sum; 10800 break; 10801 10802 case bcmCosqStatIngressPortPGMinBytesPeak: 10803 10804 BCM_IF_ERROR_RETURN 10805 (_bcm_td2_cosq_ingress_pg_get(unit, port, cosq, 10806 &start_hw_index, &end_hw_index)); 10807 COMPILER_64_ZERO(sum); 10808 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_localport_resolve(unit, port, &local_port)); 10809 10810 for (i = start_hw_index; i <= end_hw_index; i++) { 10811 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10812 BCM_IF_ERROR_RETURN 10813 (counter_get(unit, local_port, 10814 SOC_COUNTER_NON_DMA_PG_MIN_PEAK, 10815 i, &value64)); 10816 COMPILER_64_ADD_64(sum, value64); 10817 } 10818 10819 COMPILER_64_UMUL_32(sum, _BCM_TD2_BYTES_PER_CELL); 10820 *value = sum; 10821 break; 10822 case bcmCosqStatIngressPortPGMinBytesCurrent: 10823 10824 BCM_IF_ERROR_RETURN 10825 (_bcm_td2_cosq_ingress_pg_get(unit, port, cosq, 10826 &start_hw_index, &end_hw_index)); 10827 COMPILER_64_ZERO(sum); 10828 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_localport_resolve(unit, port, &local_port)); 10829 10830 for (i = start_hw_index; i <= end_hw_index; i++) { 10831 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10832 BCM_IF_ERROR_RETURN 10833 (counter_get(unit, local_port, 10834 SOC_COUNTER_NON_DMA_PG_MIN_CURRENT, 10835 i, &value64)); 10836 COMPILER_64_ADD_64(sum, value64); 10837 } 10838 10839 COMPILER_64_UMUL_32(sum, _BCM_TD2_BYTES_PER_CELL); 10840 *value = sum; 10841 break; 10842 10843 case bcmCosqStatIngressPortPGSharedBytesPeak: 10844 10845 BCM_IF_ERROR_RETURN 10846 (_bcm_td2_cosq_ingress_pg_get(unit, port, cosq, 10847 &start_hw_index, &end_hw_index)); 10848 COMPILER_64_ZERO(sum); 10849 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_localport_resolve(unit, port, &local_port)); 10850 10851 for (i = start_hw_index; i <= end_hw_index; i++) { 10852 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10853 BCM_IF_ERROR_RETURN 10854 (counter_get(unit, local_port, 10855 SOC_COUNTER_NON_DMA_PG_SHARED_PEAK, 10856 i, &value64)); 10857 COMPILER_64_ADD_64(sum, value64); 10858 } 10859 10860 COMPILER_64_UMUL_32(sum, _BCM_TD2_BYTES_PER_CELL); 10861 *value = sum; 10862 break; 10863 10864 case bcmCosqStatIngressPortPGSharedBytesCurrent: 10865 10866 BCM_IF_ERROR_RETURN 10867 (_bcm_td2_cosq_ingress_pg_get(unit, port, cosq, 10868 &start_hw_index, &end_hw_index)); 10869 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_localport_resolve(unit, port, &local_port)); 10870 COMPILER_64_ZERO(sum); 10871 10872 for (i = start_hw_index; i <= end_hw_index; i++) { 10873 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10874 BCM_IF_ERROR_RETURN 10875 (counter_get(unit, local_port, 10876 SOC_COUNTER_NON_DMA_PG_SHARED_CURRENT, 10877 i, &value64)); 10878 COMPILER_64_ADD_64(sum, value64); 10879 } 10880 COMPILER_64_UMUL_32(sum, _BCM_TD2_BYTES_PER_CELL); 10881 *value = sum; 10882 10883 break; 10884 10885 case bcmCosqStatIngressPortPGHeadroomBytesPeak: 10886 10887 BCM_IF_ERROR_RETURN 10888 (_bcm_td2_cosq_ingress_pg_get(unit, port, cosq, 10889 &start_hw_index, &end_hw_index)); 10890 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_localport_resolve(unit, port, &local_port)); 10891 COMPILER_64_ZERO(sum); 10892 10893 for (i = start_hw_index; i <= end_hw_index; i++) { 10894 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10895 BCM_IF_ERROR_RETURN 10896 (counter_get(unit, local_port, 10897 SOC_COUNTER_NON_DMA_PG_HDRM_PEAK, 10898 i, &value64)); 10899 COMPILER_64_ADD_64(sum, value64); 10900 } 10901 COMPILER_64_UMUL_32(sum, _BCM_TD2_BYTES_PER_CELL); 10902 *value = sum; 10903 10904 break; 10905 10906 case bcmCosqStatIngressPortPGHeadroomBytesCurrent: 10907 10908 BCM_IF_ERROR_RETURN 10909 (_bcm_td2_cosq_ingress_pg_get(unit, port, cosq, 10910 &start_hw_index, &end_hw_index)); 10911 10912 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_localport_resolve(unit, port, &local_port)); 10913 COMPILER_64_ZERO(sum); 10914 for (i = start_hw_index; i <= end_hw_index; i++) { 10915 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10916 BCM_IF_ERROR_RETURN 10917 (counter_get(unit, local_port, 10918 SOC_COUNTER_NON_DMA_PG_HDRM_CURRENT, 10919 i, &value64)); 10920 COMPILER_64_ADD_64(sum, value64); 10921 } 10922 COMPILER_64_UMUL_32(sum, _BCM_TD2_BYTES_PER_CELL); 10923 *value = sum; 10924 10925 break; 10926 10927 case bcmCosqStatEgressMCQueueBytesPeak: 10928 if (BCM_GPORT_IS_SCHEDULER(port)) { 10929 BCM_IF_ERROR_RETURN 10930 (_bcm_td2_cosq_node_get(unit, port, 0, NULL, 10931 &local_port, NULL, &node)); 10932 if (node->level != SOC_TD2_NODE_LVL_ROOT) { 10933 return BCM_E_PARAM; 10934 } 10935 10936 BCM_IF_ERROR_RETURN( 10937 _bcm_td2_cosq_child_node_at_input(node, cosq, &node)); 10938 port = node->gport; 10939 } 10940 10941 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) { 10942 return BCM_E_PARAM; 10943 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 10944 BCM_IF_ERROR_RETURN 10945 (_bcm_td2_cosq_index_resolve 10946 (unit, port, cosq, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_MCAST, 10947 &local_port, &startq, NULL)); 10948 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10949 BCM_IF_ERROR_RETURN 10950 (counter_get(unit, local_port, 10951 SOC_COUNTER_NON_DMA_QUEUE_PEAK, startq, 10952 value)); 10953 COMPILER_64_UMUL_32(*value, _BCM_TD2_BYTES_PER_CELL); 10954 } else { 10955 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_localport_resolve(unit, port, &local_port)); 10956 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_port_has_ets(unit, port)); 10957 COMPILER_64_ZERO(sum); 10958 if (cosq == BCM_COS_INVALID) { 10959 from_cos = 0; 10960 to_cos = (IS_CPU_PORT(unit, local_port)) ? 10961 NUM_CPU_COSQ(unit) - 1 : _TD2_NUM_COS(unit) - 1; 10962 } else { 10963 from_cos = to_cos = cosq; 10964 } 10965 10966 for (ci = from_cos; ci <= to_cos; ci++) { 10967 BCM_IF_ERROR_RETURN 10968 (_bcm_td2_cosq_index_resolve 10969 (unit, port, ci, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_MCAST, 10970 &local_port, &startq, &numq)); 10971 for (i = 0; i < numq; i++) { 10972 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10973 BCM_IF_ERROR_RETURN 10974 (counter_get(unit, local_port, 10975 SOC_COUNTER_NON_DMA_QUEUE_PEAK, 10976 startq + i, &value64)); 10977 COMPILER_64_ADD_64(sum, value64); 10978 } 10979 } 10980 COMPILER_64_UMUL_32(sum, _BCM_TD2_BYTES_PER_CELL); 10981 *value = sum; 10982 } 10983 break; 10984 10985 case bcmCosqStatEgressUCQueueBytesPeak: 10986 if (BCM_GPORT_IS_SCHEDULER(port)) { 10987 BCM_IF_ERROR_RETURN 10988 (_bcm_td2_cosq_node_get(unit, port, 0, NULL, 10989 &local_port, NULL, &node)); 10990 if (node->level != SOC_TD2_NODE_LVL_ROOT) { 10991 return BCM_E_PARAM; 10992 } 10993 10994 BCM_IF_ERROR_RETURN( 10995 _bcm_td2_cosq_child_node_at_input(node, cosq, &node)); 10996 port = node->gport; 10997 } 10998 10999 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) { 11000 BCM_IF_ERROR_RETURN 11001 (_bcm_td2_cosq_index_resolve 11002 (unit, port, cosq, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_UCAST, 11003 &local_port, &startq, NULL)); 11004 /* coverity[NEGATIVE_RETURNS: FALSE] */ 11005 BCM_IF_ERROR_RETURN 11006 (counter_get(unit, local_port, 11007 SOC_COUNTER_NON_DMA_UC_QUEUE_PEAK, startq, 11008 value)); 11009 COMPILER_64_UMUL_32(*value, _BCM_TD2_BYTES_PER_CELL); 11010 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 11011 return BCM_E_PARAM; 11012 } else { 11013 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_localport_resolve(unit, port, &local_port)); 11014 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_port_has_ets(unit, port)); 11015 COMPILER_64_ZERO(sum); 11016 if (cosq == BCM_COS_INVALID) { 11017 from_cos = 0; 11018 to_cos = (IS_CPU_PORT(unit, local_port)) ? 11019 NUM_CPU_COSQ(unit) - 1 : _TD2_NUM_COS(unit) - 1; 11020 } else { 11021 from_cos = to_cos = cosq; 11022 } 11023 11024 if (IS_CPU_PORT(unit, local_port)) { 11025 return BCM_E_PARAM; 11026 } 11027 for (ci = from_cos; ci <= to_cos; ci++) { 11028 BCM_IF_ERROR_RETURN 11029 (_bcm_td2_cosq_index_resolve 11030 (unit, port, ci, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_UCAST, 11031 &local_port, &startq, &numq)); 11032 for (i = 0; i < numq; i++) { 11033 /* coverity[NEGATIVE_RETURNS: FALSE] */ 11034 BCM_IF_ERROR_RETURN 11035 (counter_get(unit, local_port, 11036 SOC_COUNTER_NON_DMA_UC_QUEUE_PEAK, 11037 startq + i, &value64)); 11038 COMPILER_64_ADD_64(sum, value64); 11039 } 11040 } 11041 COMPILER_64_UMUL_32(sum, _BCM_TD2_BYTES_PER_CELL); 11042 *value = sum; 11043 } 11044 break; 11045 11046 case bcmCosqStatHighPriDroppedPackets: 11047 if (cosq != BCM_COS_INVALID) { 11048 return BCM_E_UNAVAIL; 11049 } 11050 BCM_IF_ERROR_RETURN 11051 (_bcm_td2_cosq_localport_resolve(unit, port, &local_port)); 11052 BCM_IF_ERROR_RETURN 11053 (id = _port_l2c_mapping(unit,local_port,bcmCosqStatHighPriDroppedPackets,&xlp_port)); 11054 BCM_IF_ERROR_RETURN 11055 (counter_get(unit, local_port, id, xlp_port, value)); 11056 break; 11057 case bcmCosqStatLowPriDroppedPackets: 11058 if (cosq != BCM_COS_INVALID) { 11059 return BCM_E_UNAVAIL; 11060 } 11061 11062 BCM_IF_ERROR_RETURN 11063 (_bcm_td2_cosq_localport_resolve(unit, port, &local_port)); 11064 BCM_IF_ERROR_RETURN 11065 (id = _port_l2c_mapping(unit,local_port,bcmCosqStatLowPriDroppedPackets,&xlp_port)); 11066 BCM_IF_ERROR_RETURN 11067 (counter_get(unit, local_port, id, xlp_port, value)); 11068 break; 11069 case bcmCosqStatHighPriDroppedBytes: 11070 if (cosq != BCM_COS_INVALID) { 11071 return BCM_E_UNAVAIL; 11072 } 11073 11074 BCM_IF_ERROR_RETURN 11075 (_bcm_td2_cosq_localport_resolve(unit, port, &local_port)); 11076 BCM_IF_ERROR_RETURN 11077 (id = _port_l2c_mapping(unit,local_port,bcmCosqStatHighPriDroppedBytes,&xlp_port)); 11078 BCM_IF_ERROR_RETURN 11079 (counter_get(unit, local_port, id, xlp_port, value)); 11080 break; 11081 case bcmCosqStatLowPriDroppedBytes: 11082 if (cosq != BCM_COS_INVALID) { 11083 return BCM_E_UNAVAIL; 11084 } 11085 11086 BCM_IF_ERROR_RETURN 11087 (_bcm_td2_cosq_localport_resolve(unit, port, &local_port)); 11088 BCM_IF_ERROR_RETURN 11089 (id = _port_l2c_mapping(unit,local_port,bcmCosqStatLowPriDroppedBytes,&xlp_port)); 11090 BCM_IF_ERROR_RETURN 11091 (counter_get(unit, local_port, id, xlp_port, value)); 11092 break; 11093 case bcmCosqStatGlobalHeadroomBytes0Peak: 11094 BCM_IF_ERROR_RETURN 11095 (counter_get(unit, -1, 11096 SOC_COUNTER_NON_DMA_COSQ_GLOBAL_HDR_COUNT_X_PEAK, 11097 0, value)); 11098 COMPILER_64_UMUL_32(*value, _BCM_TD2_BYTES_PER_CELL); 11099 break; 11100 case bcmCosqStatGlobalHeadroomBytes0Current: 11101 BCM_IF_ERROR_RETURN 11102 (counter_get(unit, -1, 11103 SOC_COUNTER_NON_DMA_COSQ_GLOBAL_HDR_COUNT_X_CURRENT, 11104 0, value)); 11105 COMPILER_64_UMUL_32(*value, _BCM_TD2_BYTES_PER_CELL); 11106 break; 11107 case bcmCosqStatGlobalHeadroomBytes1Peak: 11108 BCM_IF_ERROR_RETURN 11109 (counter_get(unit, -1, 11110 SOC_COUNTER_NON_DMA_COSQ_GLOBAL_HDR_COUNT_Y_PEAK, 11111 0, value)); 11112 COMPILER_64_UMUL_32(*value, _BCM_TD2_BYTES_PER_CELL); 11113 break; 11114 case bcmCosqStatGlobalHeadroomBytes1Current: 11115 BCM_IF_ERROR_RETURN 11116 (counter_get(unit, -1, 11117 SOC_COUNTER_NON_DMA_COSQ_GLOBAL_HDR_COUNT_Y_CURRENT, 11118 0, value)); 11119 COMPILER_64_UMUL_32(*value, _BCM_TD2_BYTES_PER_CELL); 11120 break; 11121 11122 case bcmCosqStatEgressPortPoolTotalBytesCurrent: 11123 if (cosq != BCM_COS_INVALID) { 11124 return BCM_E_UNAVAIL; 11125 } 11126 BCM_IF_ERROR_RETURN 11127 (_bcm_td2_cosq_localport_resolve(unit, port, &local_port)); 11128 BCM_IF_ERROR_RETURN 11129 (soc_reg32_get(unit, MMU_THDM_DB_PORTSP_TOTAL_COUNTr, local_port, 0, &rval)); 11130 value32 = soc_reg_field_get(unit, MMU_THDM_DB_PORTSP_TOTAL_COUNTr, rval, COUNTf); 11131 COMPILER_64_ADD_32(*value, value32); 11132 COMPILER_64_UMUL_32(*value, _BCM_TD2_BYTES_PER_CELL); 11133 break; 11134 11135 case bcmCosqStatEgressPortPoolSharedBytesCurrent: 11136 BCM_IF_ERROR_RETURN 11137 (_bcm_td2_cosq_index_resolve(unit, port, cosq, 11138 _BCM_TD2_COSQ_INDEX_STYLE_EGR_POOL, 11139 &local_port, &pool, NULL)); 11140 BCM_IF_ERROR_RETURN 11141 (soc_reg32_get(unit, MMU_THDM_DB_PORTSP_SHARED_COUNTr, local_port, pool, &rval)); 11142 value32 = soc_reg_field_get(unit, MMU_THDM_DB_PORTSP_SHARED_COUNTr, rval, COUNTf); 11143 COMPILER_64_ADD_32(*value, value32); 11144 COMPILER_64_UMUL_32(*value, _BCM_TD2_BYTES_PER_CELL); 11145 break; 11146 11147 case bcmCosqStatEgressMCQueueMinBytesCurrent: 11148 case bcmCosqStatEgressMCQueueBytesCurrent: 11149 if (stat == bcmCosqStatEgressMCQueueMinBytesCurrent) { 11150 field = MIN_COUNTf; 11151 } else if (stat == bcmCosqStatEgressMCQueueBytesCurrent) { 11152 field = SHARED_COUNTf; 11153 } 11154 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) { 11155 return BCM_E_PARAM; 11156 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 11157 BCM_IF_ERROR_RETURN 11158 (_bcm_td2_cosq_index_resolve(unit, port, cosq, 11159 _BCM_TD2_COSQ_INDEX_STYLE_MCAST_QUEUE, 11160 &local_port, &startq, NULL)); 11161 11162 mem = SOC_TD2_PMEM(unit, local_port, MMU_THDM_DB_QUEUE_COUNT_0m, 11163 MMU_THDM_DB_QUEUE_COUNT_1m); 11164 startq -= 1480; /* MC queues comes after UC queues */ 11165 11166 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, 11167 startq, entry)); 11168 value32 = soc_mem_field32_get(unit, mem, entry, field); 11169 COMPILER_64_ADD_32(*value, value32); 11170 COMPILER_64_UMUL_32(*value, _BCM_TD2_BYTES_PER_CELL); 11171 } else { 11172 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_localport_resolve(unit, port, &local_port)); 11173 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_port_has_ets(unit, port)); 11174 COMPILER_64_ZERO(sum); 11175 sum32 =0; 11176 if (cosq == BCM_COS_INVALID) { 11177 from_cos = 0; 11178 to_cos = (IS_CPU_PORT(unit, local_port)) ? 11179 NUM_CPU_COSQ(unit) - 1 : _TD2_NUM_COS(unit) - 1; 11180 } else { 11181 from_cos = to_cos = cosq; 11182 } 11183 11184 if (local_port < 0) { 11185 return BCM_E_PORT; 11186 } 11187 11188 mem = SOC_TD2_PMEM(unit, local_port, MMU_THDM_DB_QUEUE_COUNT_0m, 11189 MMU_THDM_DB_QUEUE_COUNT_1m); 11190 11191 for (ci = from_cos; ci <= to_cos; ci++) { 11192 BCM_IF_ERROR_RETURN 11193 (_bcm_td2_cosq_index_resolve 11194 (unit, local_port, ci, _BCM_TD2_COSQ_INDEX_STYLE_MCAST_QUEUE, 11195 NULL, &startq, NULL)); 11196 startq -= 1480; /* MC queues comes after UC queues */ 11197 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, 11198 startq, entry)); 11199 sum32 += soc_mem_field32_get(unit, mem, entry, field); 11200 } 11201 COMPILER_64_ADD_32(sum, sum32); 11202 COMPILER_64_UMUL_32(sum, _BCM_TD2_BYTES_PER_CELL); 11203 *value = sum; 11204 } 11205 break; 11206 11207 case bcmCosqStatEgressUCQueuePortBytesCurrent: 11208 BCM_IF_ERROR_RETURN 11209 (_bcm_td2_cosq_index_resolve(unit, port, cosq, 11210 _BCM_TD2_COSQ_INDEX_STYLE_UC_EGR_POOL, 11211 &local_port, &pool, NULL)); 11212 11213 mem = SOC_TD2_PMEM(unit, local_port, MMU_THDU_XPIPE_COUNTER_PORTm, 11214 MMU_THDU_YPIPE_COUNTER_PORTm); 11215 11216 midx = SOC_TD2_MMU_PIPED_MEM_INDEX(unit, local_port, mem, pool); 11217 11218 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, 11219 midx, entry)); 11220 value32 = soc_mem_field32_get(unit, mem, entry, SHARED_COUNTf); 11221 11222 COMPILER_64_ADD_32(*value, value32); 11223 COMPILER_64_UMUL_32(*value, _BCM_TD2_BYTES_PER_CELL); 11224 break; 11225 11226 case bcmCosqStatEgressQgroupMinBytesCurrent: 11227 case bcmCosqStatEgressQgroupBytesCurrent: 11228 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) { 11229 BCM_IF_ERROR_RETURN 11230 (_bcm_td2_cosq_index_resolve(unit, port, cosq, 11231 _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE, 11232 &local_port, &startq, NULL)); 11233 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 11234 return BCM_E_PARAM; 11235 } else { 11236 BCM_IF_ERROR_RETURN 11237 (_bcm_td2_cosq_localport_resolve(unit, port, &local_port)); 11238 if (local_port < 0) { 11239 return BCM_E_PORT; 11240 } 11241 BCM_IF_ERROR_RETURN 11242 (_bcm_td2_cosq_index_resolve(unit, local_port, cosq, 11243 _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE, 11244 NULL, &startq, NULL)); 11245 } 11246 11247 mem = SOC_TD2_PMEM(unit, local_port, MMU_THDU_XPIPE_Q_TO_QGRP_MAPm, 11248 MMU_THDU_YPIPE_Q_TO_QGRP_MAPm); 11249 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 11250 valid = soc_mem_field32_get(unit, mem, entry, QGROUP_VALIDf); 11251 if (!valid) { 11252 LOG_INFO(BSL_LS_BCM_COSQ, 11253 (BSL_META_U(unit, 11254 "UCQ doesn't associate with a queue group!\n"))); 11255 return BCM_E_UNAVAIL; 11256 } 11257 11258 startq = soc_mem_field32_get(unit, mem, entry, QGROUPf); 11259 11260 mem = SOC_TD2_PMEM(unit, local_port, MMU_THDU_XPIPE_COUNTER_QGROUPm, 11261 MMU_THDU_YPIPE_COUNTER_QGROUPm); 11262 if (stat == bcmCosqStatEgressQgroupMinBytesCurrent) { 11263 field = MIN_COUNTf; 11264 } else if (stat == bcmCosqStatEgressQgroupBytesCurrent) { 11265 field = SHARED_COUNTf; 11266 } 11267 11268 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 11269 value32 = soc_mem_field32_get(unit, mem, entry, field); 11270 11271 COMPILER_64_ADD_32(*value, value32); 11272 COMPILER_64_UMUL_32(*value, _BCM_TD2_BYTES_PER_CELL); 11273 break; 11274 11275 case bcmCosqStatEgressUCQueueMinBytesCurrent: 11276 case bcmCosqStatEgressUCQueueBytesCurrent: 11277 if (stat == bcmCosqStatEgressUCQueueMinBytesCurrent) { 11278 field = MIN_COUNTf; 11279 } else if (stat == bcmCosqStatEgressUCQueueBytesCurrent) { 11280 field = SHARED_COUNTf; 11281 } 11282 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) { 11283 BCM_IF_ERROR_RETURN 11284 (_bcm_td2_cosq_index_resolve(unit, port, cosq, 11285 _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE, 11286 &local_port, &startq, NULL)); 11287 11288 mem = SOC_TD2_PMEM(unit, local_port, MMU_THDU_XPIPE_COUNTER_QUEUEm, 11289 MMU_THDU_YPIPE_COUNTER_QUEUEm); 11290 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, 11291 startq, entry)); 11292 value32 = soc_mem_field32_get(unit, mem, entry, field); 11293 COMPILER_64_ADD_32(*value, value32); 11294 COMPILER_64_UMUL_32(*value, _BCM_TD2_BYTES_PER_CELL); 11295 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 11296 return BCM_E_PARAM; 11297 } else { 11298 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_localport_resolve(unit, port, &local_port)); 11299 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_port_has_ets(unit, port)); 11300 11301 if (IS_CPU_PORT(unit, local_port)) { 11302 return BCM_E_PARAM; 11303 } 11304 COMPILER_64_ZERO(sum); 11305 sum32 =0; 11306 if (cosq == BCM_COS_INVALID) { 11307 from_cos = 0; 11308 to_cos = (IS_CPU_PORT(unit, local_port)) ? 11309 NUM_CPU_COSQ(unit) - 1 : _TD2_NUM_COS(unit) - 1; 11310 } else { 11311 from_cos = to_cos = cosq; 11312 } 11313 11314 if (local_port < 0) { 11315 return BCM_E_PORT; 11316 } 11317 mem = SOC_TD2_PMEM(unit, local_port, MMU_THDU_XPIPE_COUNTER_QUEUEm, 11318 MMU_THDU_YPIPE_COUNTER_QUEUEm); 11319 for (ci = from_cos; ci <= to_cos; ci++) { 11320 BCM_IF_ERROR_RETURN 11321 (_bcm_td2_cosq_index_resolve 11322 (unit, local_port, ci, _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE, 11323 NULL, &startq, NULL)); 11324 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, 11325 startq, entry)); 11326 sum32 += soc_mem_field32_get(unit, mem, entry, field); 11327 } 11328 COMPILER_64_ADD_32(sum, sum32); 11329 COMPILER_64_UMUL_32(sum, _BCM_TD2_BYTES_PER_CELL); 11330 *value = sum; 11331 } 11332 break; 11333 11334 default: 11335 return BCM_E_PARAM; 11336 } 11337 11338 return BCM_E_NONE; 11339 } 11340 11341 /* 11342 * Function: 11343 * _bcm_td2_cosq_quantize_table_set 11344 * Purpose: 11345 * Generate quantized feedback lookup table 11346 * Parameters: 11347 * unit - (IN) unit number 11348 * profile_index - (IN) profile index 11349 * weight_code - (IN) weight encoding 11350 * set_point - (IN) queue size set point 11351 * active_offset - (OUT) most significant non-zero bit position 11352 * Returns: 11353 * BCM_E_XXX 11354 * Notes: 11355 * The formular to quantize feedback value is: 11356 * quantized_feedbad = celling(feedback / max_feedback * 63) 11357 * where max_feedback = (2 * cpW + 1) * cpQsp 11358 * cpW is feedback weight 11359 * cpQsp is queue size set point 11360 */ 11361 STATIC int 11362 _bcm_td2_cosq_quantize_table_set(int unit, int profile_index, int weight_code, 11363 int set_point, int *active_offset) 11364 { 11365 int ref_count; 11366 int weight_x_4, feedback, max_feedback, quantized_feedback, shift; 11367 int base_index, index; 11368 11369 /* weight = 2 ** (weight_code - 2) e.g. 0 for 1/4, 1 for 1/2, ... */ 11370 weight_x_4 = 1 << weight_code; 11371 max_feedback = ((2 * weight_x_4 + 4) * set_point + 3) / 4; 11372 shift = 0; 11373 while ((max_feedback >> shift) > 127) { 11374 shift++; 11375 } 11376 11377 BCM_IF_ERROR_RETURN 11378 (soc_profile_reg_ref_count_get(unit, _bcm_td2_feedback_profile[unit], 11379 profile_index, &ref_count)); 11380 11381 /* 11382 * Hardware use lookup table to find quantized feedback in order to avoid 11383 * division, use most significant 7-bit of feedback value as lookup table 11384 * index to find quantized_feedback value 11385 */ 11386 if (ref_count == 1) { 11387 base_index = profile_index << 7; 11388 for (index = 0; index < 128; index++) { 11389 feedback = index << shift; 11390 if (feedback > max_feedback) { 11391 quantized_feedback = 63; 11392 } else { 11393 quantized_feedback = (feedback * 63 + max_feedback - 1) / 11394 max_feedback; 11395 } 11396 BCM_IF_ERROR_RETURN 11397 (soc_mem_field32_modify(unit, MMU_QCN_QFBTBm, 11398 base_index + index, CPQ_QNTZFBf, 11399 quantized_feedback)); 11400 } 11401 } 11402 11403 *active_offset = shift + 6; 11404 11405 return BCM_E_NONE; 11406 } 11407 11408 11409 STATIC int 11410 _bcm_td2_cosq_sample_int_table_set(int unit, int min, int max, 11411 uint32 *profile_index) 11412 { 11413 mmu_qcn_sitb_entry_t sitb_entries[64]; 11414 void *entries[1]; 11415 int i, j, center, inc, value, index; 11416 11417 sal_memset(sitb_entries, 0, sizeof(sitb_entries)); 11418 entries[0] = &sitb_entries; 11419 for (i = 0; i < 8; i++) { 11420 center = max - (max - min) * i / 7; 11421 inc = (max - min) / 7 / 8; 11422 for (j = 0; j < 8; j++, inc = -inc) { 11423 index = i * 8 + j; 11424 value = center + (j + 1) / 2 * inc; 11425 if (value > 255) { 11426 value = 255; 11427 } else if (value < 1) { 11428 value = 1; 11429 } 11430 soc_mem_field32_set(unit, MMU_QCN_SITBm, &sitb_entries[index], 11431 CPQ_SIf, value); 11432 } 11433 } 11434 11435 return soc_profile_mem_add(unit, _bcm_td2_sample_int_profile[unit], entries, 11436 64, (uint32 *)profile_index); 11437 } 11438 11439 /* 11440 * Function: 11441 * bcm_td2_cosq_congestion_queue_set 11442 * Purpose: 11443 * Enable/Disable a cos queue as congestion managed queue 11444 * Parameters: 11445 * unit - (IN) unit number 11446 * port - (IN) port number or GPORT identifier 11447 * cosq - (IN) COS queue number 11448 * index - (IN) congestion managed queue index 11449 * Returns: 11450 * BCM_E_XXX 11451 */ 11452 int 11453 bcm_td2_cosq_congestion_queue_set(int unit, bcm_port_t port, 11454 bcm_cos_queue_t cosq, int index) 11455 { 11456 bcm_port_t local_port; 11457 uint32 rval; 11458 uint64 rval64, *rval64s[1]; 11459 mmu_qcn_enable_entry_t enable_entry; 11460 int active_offset, qindex; 11461 uint32 profile_index, sample_profile_index; 11462 int weight_code, set_point; 11463 soc_mem_t mem; 11464 int pipe; 11465 11466 if (cosq < 0 || cosq >= _TD2_NUM_COS(unit)) { 11467 return BCM_E_PARAM; 11468 } 11469 11470 if ((index < -1) || (index >= 1480)) { 11471 return BCM_E_PARAM; 11472 } 11473 11474 BCM_IF_ERROR_RETURN 11475 (_bcm_td2_cosq_index_resolve(unit, port, cosq, 11476 _BCM_TD2_COSQ_INDEX_STYLE_QCN, 11477 &local_port, &qindex, NULL)); 11478 11479 pipe = _BCM_TD2_PORT_TO_PIPE(unit, local_port); 11480 if (pipe) { 11481 mem = MMU_QCN_ENABLE_1m; 11482 } else { 11483 mem = MMU_QCN_ENABLE_0m; 11484 } 11485 11486 11487 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ANY, 11488 qindex, &enable_entry)); 11489 if (index == -1) { 11490 if (!soc_mem_field32_get(unit, mem, &enable_entry, CPQ_ENf)) { 11491 return BCM_E_NONE; 11492 } 11493 11494 index = soc_mem_field32_get(unit, mem, &enable_entry, CPQ_PROFILE_INDEXf); 11495 soc_mem_field32_set(unit, mem, &enable_entry, CPQ_ENf, 0); 11496 BCM_IF_ERROR_RETURN 11497 (soc_mem_write(unit, mem, MEM_BLOCK_ANY, qindex, &enable_entry)); 11498 11499 profile_index = soc_mem_field32_get(unit, mem, &enable_entry, EQTB_INDEXf); 11500 11501 BCM_IF_ERROR_RETURN 11502 (soc_profile_reg_delete(unit, _bcm_td2_feedback_profile[unit], 11503 profile_index)); 11504 11505 profile_index = 11506 soc_mem_field32_get(unit, mem, &enable_entry, SITB_SELf); 11507 11508 BCM_IF_ERROR_RETURN 11509 (soc_profile_mem_delete(unit, _bcm_td2_sample_int_profile[unit], 11510 profile_index * 64)); 11511 } else { 11512 if (soc_mem_field32_get(unit, mem, &enable_entry, CPQ_ENf)) { 11513 return BCM_E_BUSY; 11514 } 11515 11516 /* Use hardware reset value as default quantize setting */ 11517 weight_code = 3; 11518 set_point = 0x96; 11519 rval = 0; 11520 soc_reg_field_set(unit, MMU_QCN_CPQ_SEQr, &rval, CPWf, weight_code); 11521 soc_reg_field_set(unit, MMU_QCN_CPQ_SEQr, &rval, CPQEQf, set_point); 11522 COMPILER_64_SET(rval64, 0, rval); 11523 rval64s[0] = &rval64; 11524 BCM_IF_ERROR_RETURN 11525 (soc_profile_reg_add(unit, _bcm_td2_feedback_profile[unit], 11526 rval64s, 1, (uint32 *)&profile_index)); 11527 11528 /* Update quantized feedback calculation lookup table */ 11529 BCM_IF_ERROR_RETURN 11530 (_bcm_td2_cosq_quantize_table_set(unit, profile_index, weight_code, 11531 set_point, &active_offset)); 11532 11533 /* Pick some sample interval */ 11534 BCM_IF_ERROR_RETURN 11535 (_bcm_td2_cosq_sample_int_table_set(unit, 13, 127, 11536 &sample_profile_index)); 11537 11538 soc_mem_field32_set(unit, mem, &enable_entry, 11539 QNTZ_ACT_OFFSETf, active_offset); 11540 11541 soc_mem_field32_set(unit, mem, &enable_entry, 11542 SITB_SELf, sample_profile_index/64); 11543 11544 soc_mem_field32_set(unit, mem, &enable_entry, EQTB_INDEXf, 11545 profile_index); 11546 11547 soc_mem_field32_set(unit, mem, &enable_entry, CPQ_IDf, index); 11548 11549 soc_mem_field32_set(unit, mem, &enable_entry, CPQ_ENf, 1); 11550 11551 BCM_IF_ERROR_RETURN 11552 (soc_mem_write(unit, mem, MEM_BLOCK_ANY, qindex, &enable_entry)); 11553 } 11554 11555 return BCM_E_NONE; 11556 } 11557 11558 /* 11559 * Function: 11560 * bcm_td2_cosq_congestion_queue_get 11561 * Purpose: 11562 * Get congestion managed queue index of the specified cos queue 11563 * Parameters: 11564 * unit - (IN) unit number 11565 * port - (IN) port number or GPORT identifier 11566 * cosq - (IN) COS queue number 11567 * index - (OUT) congestion managed queue index 11568 * Returns: 11569 * BCM_E_XXX 11570 */ 11571 int 11572 bcm_td2_cosq_congestion_queue_get(int unit, bcm_port_t port, 11573 bcm_cos_queue_t cosq, int *index) 11574 { 11575 bcm_port_t local_port; 11576 int qindex; 11577 mmu_qcn_enable_entry_t entry; 11578 soc_mem_t mem; 11579 int pipe; 11580 11581 if (cosq < 0 || cosq >= _TD2_NUM_COS(unit)) { 11582 return BCM_E_PARAM; 11583 } 11584 11585 if (index == NULL) { 11586 return BCM_E_PARAM; 11587 } 11588 11589 BCM_IF_ERROR_RETURN 11590 (_bcm_td2_cosq_index_resolve(unit, port, cosq, 11591 _BCM_TD2_COSQ_INDEX_STYLE_QCN, 11592 &local_port, &qindex, NULL)); 11593 11594 pipe = _BCM_TD2_PORT_TO_PIPE(unit, local_port); 11595 if (pipe) { 11596 mem = MMU_QCN_ENABLE_1m; 11597 } else { 11598 mem = MMU_QCN_ENABLE_0m; 11599 } 11600 11601 11602 11603 BCM_IF_ERROR_RETURN 11604 (soc_mem_read(unit, mem, MEM_BLOCK_ANY, qindex, &entry)); 11605 if (soc_mem_field32_get(unit, mem, &entry, CPQ_ENf)) { 11606 *index = soc_mem_field32_get(unit, mem, &entry, CPQ_IDf); 11607 } else { 11608 *index = -1; 11609 } 11610 11611 return BCM_E_NONE; 11612 } 11613 11614 /* 11615 * Function: 11616 * bcm_td2_cosq_congestion_quantize_set 11617 * Purpose: 11618 * Set quantized congestion feedback algorithm parameters 11619 * Parameters: 11620 * unit - (IN) unit number 11621 * port - (IN) port number or GPORT identifier 11622 * cosq - (IN) COS queue number 11623 * weight_code - (IN) weight encoding (use -1 for unchange) 11624 * set_point - (IN) queue size set point (use -1 for unchange) 11625 * Returns: 11626 * BCM_E_XXX 11627 */ 11628 int 11629 bcm_td2_cosq_congestion_quantize_set(int unit, bcm_port_t port, 11630 bcm_cos_queue_t cosq, int weight_code, 11631 int set_point) 11632 { 11633 bcm_port_t local_port; 11634 uint32 rval; 11635 uint64 rval64, *rval64s[1]; 11636 mmu_qcn_enable_entry_t enable_entry; 11637 int cpq_index, active_offset, qindex; 11638 uint32 profile_index, old_profile_index; 11639 soc_mem_t mem; 11640 int pipe; 11641 11642 if (cosq < 0 || cosq >= _TD2_NUM_COS(unit)) { 11643 return BCM_E_PARAM; 11644 } 11645 11646 BCM_IF_ERROR_RETURN 11647 (_bcm_td2_cosq_index_resolve(unit, port, cosq, 11648 _BCM_TD2_COSQ_INDEX_STYLE_QCN, 11649 &local_port, &qindex, NULL)); 11650 11651 pipe = _BCM_TD2_PORT_TO_PIPE(unit, local_port); 11652 if (pipe) { 11653 mem = MMU_QCN_ENABLE_1m; 11654 } else { 11655 mem = MMU_QCN_ENABLE_0m; 11656 } 11657 11658 BCM_IF_ERROR_RETURN 11659 (bcm_td2_cosq_congestion_queue_get(unit, port, cosq, &cpq_index)); 11660 if (cpq_index == -1) { 11661 /* The cosq specified is not enabled as congestion managed queue */ 11662 return BCM_E_PARAM; 11663 } 11664 11665 BCM_IF_ERROR_RETURN 11666 (_bcm_td2_cosq_index_resolve(unit, port, cosq, 11667 _BCM_TD2_COSQ_INDEX_STYLE_QCN, &local_port, &qindex, NULL)); 11668 11669 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ANY, qindex, &enable_entry)); 11670 old_profile_index = 11671 soc_mem_field32_get(unit, mem, &enable_entry, EQTB_INDEXf); 11672 11673 BCM_IF_ERROR_RETURN(READ_MMU_QCN_CPQ_SEQr(unit, old_profile_index, &rval)); 11674 if (weight_code == -1) { 11675 weight_code = soc_reg_field_get(unit, MMU_QCN_CPQ_SEQr, rval, CPWf); 11676 } else { 11677 if (weight_code < 0 || weight_code > 7) { 11678 return BCM_E_PARAM; 11679 } 11680 soc_reg_field_set(unit, MMU_QCN_CPQ_SEQr, &rval, CPWf, weight_code); 11681 } 11682 if (set_point == -1) { 11683 set_point = soc_reg_field_get(unit, MMU_QCN_CPQ_SEQr, rval, CPQEQf); 11684 } else { 11685 if (set_point < 0 || set_point > 0xffff) { 11686 return BCM_E_PARAM; 11687 } 11688 soc_reg_field_set(unit, MMU_QCN_CPQ_SEQr, &rval, CPQEQf, set_point); 11689 } 11690 COMPILER_64_SET(rval64, 0, rval); 11691 rval64s[0] = &rval64; 11692 /* Add new feedback parameter profile */ 11693 BCM_IF_ERROR_RETURN 11694 (soc_profile_reg_add(unit, _bcm_td2_feedback_profile[unit], rval64s, 11695 1, (uint32 *)&profile_index)); 11696 /* Delete original feedback parameter profile */ 11697 BCM_IF_ERROR_RETURN 11698 (soc_profile_reg_delete(unit, _bcm_td2_feedback_profile[unit], 11699 old_profile_index)); 11700 11701 /* Update quantized feedback calculation lookup table */ 11702 BCM_IF_ERROR_RETURN 11703 (_bcm_td2_cosq_quantize_table_set(unit, profile_index, weight_code, 11704 set_point, &active_offset)); 11705 11706 soc_mem_field32_set(unit, mem, &enable_entry, 11707 QNTZ_ACT_OFFSETf, active_offset); 11708 soc_mem_field32_set(unit, mem, &enable_entry, 11709 EQTB_INDEXf, profile_index); 11710 BCM_IF_ERROR_RETURN 11711 (soc_mem_write(unit, mem, MEM_BLOCK_ANY, qindex, 11712 &enable_entry)); 11713 11714 return BCM_E_NONE; 11715 } 11716 11717 /* 11718 * Function: 11719 * bcm_td2_cosq_congestion_quantize_get 11720 * Purpose: 11721 * Get quantized congestion feedback algorithm parameters 11722 * Parameters: 11723 * unit - (IN) unit number 11724 * port - (IN) port number or GPORT identifier 11725 * cosq - (IN) COS queue number 11726 * weight_code - (OUT) weight encoding 11727 * set_point - (OUT) queue size set point 11728 * Returns: 11729 * BCM_E_XXX 11730 */ 11731 int 11732 bcm_td2_cosq_congestion_quantize_get(int unit, bcm_port_t port, 11733 bcm_cos_queue_t cosq, int *weight_code, 11734 int *set_point) 11735 { 11736 bcm_port_t local_port; 11737 int cpq_index, profile_index, qindex; 11738 uint32 rval; 11739 mmu_qcn_enable_entry_t enable_entry; 11740 soc_mem_t mem; 11741 int pipe; 11742 11743 BCM_IF_ERROR_RETURN 11744 (bcm_td2_cosq_congestion_queue_get(unit, port, cosq, &cpq_index)); 11745 if (cpq_index == -1) { 11746 /* The cosq specified is not enabled as congestion managed queue */ 11747 return BCM_E_PARAM; 11748 } 11749 11750 BCM_IF_ERROR_RETURN 11751 (_bcm_td2_cosq_index_resolve(unit, port, cosq, 11752 _BCM_TD2_COSQ_INDEX_STYLE_QCN, 11753 &local_port, &qindex, NULL)); 11754 11755 pipe = _BCM_TD2_PORT_TO_PIPE(unit, local_port); 11756 if (pipe) { 11757 mem = MMU_QCN_ENABLE_1m; 11758 } else { 11759 mem = MMU_QCN_ENABLE_0m; 11760 } 11761 11762 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, 11763 MEM_BLOCK_ANY, qindex, &enable_entry)); 11764 11765 profile_index = 11766 soc_mem_field32_get(unit, mem, &enable_entry, EQTB_INDEXf); 11767 11768 BCM_IF_ERROR_RETURN(READ_MMU_QCN_CPQ_SEQr(unit, profile_index, &rval)); 11769 if (weight_code != NULL) { 11770 *weight_code = soc_reg_field_get(unit, MMU_QCN_CPQ_SEQr, rval, CPWf); 11771 } 11772 if (set_point != NULL) { 11773 *set_point = soc_reg_field_get(unit, MMU_QCN_CPQ_SEQr, rval, CPQEQf); 11774 } 11775 11776 return BCM_E_NONE; 11777 } 11778 11779 int 11780 bcm_td2_cosq_congestion_sample_int_set(int unit, bcm_port_t port, 11781 bcm_cos_queue_t cosq, int min, int max) 11782 { 11783 bcm_port_t local_port; 11784 mmu_qcn_enable_entry_t entry; 11785 mmu_qcn_sitb_entry_t sitb_entry; 11786 int qindex; 11787 uint32 profile_index, old_profile_index; 11788 soc_mem_t mem; 11789 int pipe; 11790 11791 BCM_IF_ERROR_RETURN 11792 (_bcm_td2_cosq_index_resolve(unit, port, cosq, 11793 _BCM_TD2_COSQ_INDEX_STYLE_QCN, 11794 &local_port, &qindex, NULL)); 11795 11796 pipe = _BCM_TD2_PORT_TO_PIPE(unit, local_port); 11797 if (pipe) { 11798 mem = MMU_QCN_ENABLE_1m; 11799 } else { 11800 mem = MMU_QCN_ENABLE_0m; 11801 } 11802 11803 11804 BCM_IF_ERROR_RETURN 11805 (soc_mem_read(unit, mem, MEM_BLOCK_ANY, qindex, &entry)); 11806 11807 if (!soc_mem_field32_get(unit, mem, &entry, CPQ_ENf)) { 11808 return BCM_E_PARAM; 11809 } 11810 11811 old_profile_index = 11812 soc_mem_field32_get(unit, mem, &entry, SITB_SELf); 11813 11814 if (max == -1) { 11815 BCM_IF_ERROR_RETURN(soc_mem_read(unit, MMU_QCN_SITBm, MEM_BLOCK_ANY, 11816 old_profile_index * 64, &sitb_entry)); 11817 max = soc_mem_field32_get(unit, MMU_QCN_SITBm, &sitb_entry, CPQ_SIf); 11818 } else { 11819 if (max < 1 || max > 255) { 11820 return BCM_E_PARAM; 11821 } 11822 } 11823 if (min == -1) { 11824 BCM_IF_ERROR_RETURN(soc_mem_read(unit, MMU_QCN_SITBm, MEM_BLOCK_ANY, 11825 old_profile_index * 64 + 63, 11826 &sitb_entry)); 11827 min = soc_mem_field32_get(unit, MMU_QCN_SITBm, &sitb_entry, CPQ_SIf); 11828 } else { 11829 if (min < 1 || min > 255) { 11830 return BCM_E_PARAM; 11831 } 11832 } 11833 11834 /* Add new sample interval profile */ 11835 BCM_IF_ERROR_RETURN 11836 (_bcm_td2_cosq_sample_int_table_set(unit, min, max, &profile_index)); 11837 11838 /* Delete original sample interval profile */ 11839 BCM_IF_ERROR_RETURN 11840 (soc_profile_mem_delete(unit, _bcm_td2_sample_int_profile[unit], 11841 old_profile_index * 64)); 11842 11843 soc_mem_field32_set(unit, mem, &entry, SITB_SELf, 11844 profile_index / 64); 11845 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ANY, 11846 qindex, &entry)); 11847 return BCM_E_NONE; 11848 } 11849 11850 int 11851 bcm_td2_cosq_congestion_sample_int_get(int unit, bcm_port_t port, 11852 bcm_cos_queue_t cosq, int *min, int *max) 11853 { 11854 bcm_port_t local_port; 11855 mmu_qcn_enable_entry_t entry; 11856 mmu_qcn_sitb_entry_t sitb_entry; 11857 int qindex; 11858 uint32 old_profile_index; 11859 soc_mem_t mem; 11860 int pipe; 11861 11862 BCM_IF_ERROR_RETURN 11863 (_bcm_td2_cosq_index_resolve(unit, port, cosq, 11864 _BCM_TD2_COSQ_INDEX_STYLE_QCN, 11865 &local_port, &qindex, NULL)); 11866 11867 pipe = _BCM_TD2_PORT_TO_PIPE(unit, local_port); 11868 if (pipe) { 11869 mem = MMU_QCN_ENABLE_1m; 11870 } else { 11871 mem = MMU_QCN_ENABLE_0m; 11872 } 11873 11874 BCM_IF_ERROR_RETURN 11875 (soc_mem_read(unit, mem, MEM_BLOCK_ANY, qindex, &entry)); 11876 11877 if (!soc_mem_field32_get(unit, mem, &entry, CPQ_ENf)) { 11878 return BCM_E_PARAM; 11879 } 11880 11881 old_profile_index = 11882 soc_mem_field32_get(unit, mem, &entry, SITB_SELf); 11883 11884 if (max) { 11885 BCM_IF_ERROR_RETURN(soc_mem_read(unit, MMU_QCN_SITBm, MEM_BLOCK_ANY, 11886 old_profile_index * 64, &sitb_entry)); 11887 *max = soc_mem_field32_get(unit, MMU_QCN_SITBm, &sitb_entry, CPQ_SIf); 11888 } 11889 11890 if (min) { 11891 BCM_IF_ERROR_RETURN(soc_mem_read(unit, MMU_QCN_SITBm, MEM_BLOCK_ANY, 11892 old_profile_index * 64 + 63, 11893 &sitb_entry)); 11894 *min = soc_mem_field32_get(unit, MMU_QCN_SITBm, &sitb_entry, CPQ_SIf); 11895 } 11896 11897 return BCM_E_NONE; 11898 } 11899 11900 STATIC int 11901 _bcm_td2_cosq_ing_pool_set(int unit, bcm_gport_t gport, bcm_cos_queue_t pri_grp, 11902 bcm_cosq_control_t type, int arg) 11903 { 11904 int local_port; 11905 uint32 rval; 11906 static const soc_field_t prigroup_spid_field[] = { 11907 PG0_SPIDf, PG1_SPIDf, PG2_SPIDf, PG3_SPIDf, 11908 PG4_SPIDf, PG5_SPIDf, PG6_SPIDf, PG7_SPIDf 11909 }; 11910 if(( arg < 0 ) || (arg > 3 )) { 11911 return BCM_E_PARAM; 11912 } 11913 11914 BCM_IF_ERROR_RETURN 11915 (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port)); 11916 11917 if (!SOC_PORT_VALID(unit, local_port)) { 11918 return BCM_E_PORT; 11919 } 11920 /* coverity fix : pri_grp can take value from 0 to 7 */ 11921 if ((pri_grp < 0) || (pri_grp >= 8)) { 11922 return BCM_E_PARAM; 11923 } 11924 11925 SOC_IF_ERROR_RETURN(READ_THDI_PORT_PG_SPIDr(unit, local_port, &rval)); 11926 soc_reg_field_set(unit, THDI_PORT_PG_SPIDr, &rval, 11927 prigroup_spid_field[pri_grp],arg); 11928 BCM_IF_ERROR_RETURN(WRITE_THDI_PORT_PG_SPIDr(unit, local_port, rval)); 11929 return BCM_E_NONE; 11930 } 11931 11932 STATIC int 11933 _bcm_td2_cosq_ing_pool_get(int unit, bcm_gport_t gport, 11934 bcm_cos_queue_t pri_grp, 11935 bcm_cosq_control_t type, int *arg) 11936 { 11937 int pool_start_idx = 0, pool_end_idx =0; 11938 BCM_IF_ERROR_RETURN( 11939 _bcm_td2_cosq_ingress_sp_get( 11940 unit, gport, pri_grp, &pool_start_idx, &pool_end_idx)); 11941 *arg = pool_start_idx; 11942 return BCM_E_NONE; 11943 } 11944 11945 /* 11946 * Function: 11947 * _bcm_td2_cosq_port_qnum_get 11948 * Purpose: 11949 * Get the hw queue number used to tx packets on respective Queue 11950 * Parameters: 11951 * unit - (IN) unit number 11952 * port - (IN) port number or GPORT identifier 11953 * cosq - (IN) COS queue number 11954 * type - (IN) unicast/multicast queue indicator 11955 * arg - (out) hw queue number 11956 * Returns: 11957 * BCM_E_XXX 11958 */ 11959 STATIC int 11960 _bcm_td2_cosq_port_qnum_get(int unit, bcm_gport_t gport, 11961 bcm_cos_queue_t cosq, bcm_cosq_control_t type, int *arg) 11962 { 11963 bcm_port_t local_port; 11964 int hw_index; 11965 int uc; 11966 int qnum; 11967 int id, startq, numq; 11968 _bcm_td2_cosq_node_t *node; 11969 soc_info_t *si = &SOC_INFO(unit); 11970 11971 if (!arg) { 11972 return BCM_E_PARAM; 11973 } 11974 11975 if (cosq <= -1) { 11976 return BCM_E_PARAM; 11977 } else { 11978 startq = cosq; 11979 numq = 1; 11980 } 11981 11982 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 11983 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 11984 BCM_IF_ERROR_RETURN 11985 (_bcm_td2_cosq_node_get(unit, gport, cosq, NULL, &local_port, &id, 11986 &node)); 11987 if (node->attached_to_input < 0) { /* Not resolved yet */ 11988 return BCM_E_NOT_FOUND; 11989 } 11990 11991 startq = 0; 11992 } else { 11993 /* optionally validate port */ 11994 BCM_IF_ERROR_RETURN 11995 (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port)); 11996 if (local_port < 0) { 11997 return BCM_E_PORT; 11998 } 11999 node = NULL; 12000 numq = (IS_CPU_PORT(unit, local_port)) ? 12001 NUM_CPU_COSQ(unit) : NUM_COS(unit); 12002 } 12003 12004 if (startq >= numq) { 12005 return BCM_E_PARAM; 12006 } 12007 12008 uc =(type == bcmCosqControlPortQueueUcast) ? 1 : 0; 12009 12010 if (node) { 12011 hw_index = node->hw_index; 12012 } else { 12013 hw_index = soc_td2_l2_hw_index(unit, 12014 si->port_uc_cosq_base[local_port] + startq, uc); 12015 } 12016 12017 qnum = soc_td2_hw_index_logical_num(unit,local_port,hw_index,uc); 12018 *arg = soc_td2_logical_qnum_hw_qnum(unit,local_port,qnum,uc); 12019 12020 return BCM_E_NONE; 12021 } 12022 12023 STATIC int 12024 _bcm_td2_cosq_egr_pool_set(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 12025 bcm_cosq_control_t type, int arg) 12026 { 12027 bcm_port_t local_port; 12028 int startq, pool, midx; 12029 uint32 max_val; 12030 uint32 entry[SOC_MAX_MEM_WORDS]; 12031 uint32 entry2[SOC_MAX_MEM_WORDS]; 12032 soc_mem_t mem = INVALIDm, mem2 = INVALIDm; 12033 soc_field_t fld_limit = INVALIDf; 12034 int granularity = 1; 12035 12036 if ((arg < 0) || (cosq < 0)) { 12037 return BCM_E_PARAM; 12038 } 12039 12040 BCM_IF_ERROR_RETURN 12041 (_bcm_td2_cosq_index_resolve(unit, gport, cosq, 12042 _BCM_TD2_COSQ_INDEX_STYLE_EGR_POOL, 12043 &local_port, &pool, NULL)); 12044 12045 mem = SOC_TD2_PMEM(unit, local_port, MMU_THDM_DB_PORTSP_CONFIG_0m, 12046 MMU_THDM_DB_PORTSP_CONFIG_1m); 12047 12048 if (type == bcmCosqControlEgressPoolLimitEnable) { 12049 midx = SOC_TD2_MMU_PIPED_MEM_INDEX(unit, local_port, mem, pool); 12050 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, 12051 midx, entry)); 12052 12053 soc_mem_field32_set(unit, mem, entry, SHARED_LIMIT_ENABLEf, !!arg); 12054 12055 return soc_mem_write(unit, mem, MEM_BLOCK_ALL, midx, entry); 12056 } 12057 if (type == bcmCosqControlEgressPool || type == bcmCosqControlUCEgressPool || 12058 type == bcmCosqControlMCEgressPool) { 12059 if(( arg < 0 ) || (arg > 3 )) { 12060 return BCM_E_PARAM; 12061 } 12062 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 12063 if (type != bcmCosqControlEgressPool) { 12064 return BCM_E_PARAM; 12065 } 12066 /* regular unicast queue */ 12067 BCM_IF_ERROR_RETURN 12068 (_bcm_td2_cosq_index_resolve(unit, gport, cosq, 12069 _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE, 12070 &local_port, &startq, NULL)); 12071 mem = SOC_TD2_PMEM(unit, local_port, 12072 MMU_THDU_XPIPE_Q_TO_QGRP_MAPm, MMU_THDU_YPIPE_Q_TO_QGRP_MAPm); 12073 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 12074 if (type != bcmCosqControlEgressPool) { 12075 return BCM_E_PARAM; 12076 } 12077 BCM_IF_ERROR_RETURN 12078 (_bcm_td2_cosq_index_resolve(unit, gport, cosq, 12079 _BCM_TD2_COSQ_INDEX_STYLE_MCAST_QUEUE, 12080 &local_port, &startq, NULL)); 12081 startq -= 1480; /* MC queues comes after UC queues */ 12082 mem = SOC_TD2_PMEM(unit, local_port, 12083 MMU_THDM_MCQE_QUEUE_CONFIG_0m, MMU_THDM_MCQE_QUEUE_CONFIG_1m); 12084 mem2 = SOC_TD2_PMEM(unit, local_port, 12085 MMU_THDM_DB_QUEUE_CONFIG_0m, MMU_THDM_DB_QUEUE_CONFIG_1m); 12086 } else { /* local port */ 12087 if (BCM_GPORT_IS_SCHEDULER(gport) && 12088 (type != bcmCosqControlEgressPool)) { 12089 return BCM_E_PARAM; 12090 } 12091 if (type == bcmCosqControlUCEgressPool) { 12092 BCM_IF_ERROR_RETURN 12093 (_bcm_td2_cosq_index_resolve(unit, gport, cosq, 12094 _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE, 12095 &local_port, &startq, NULL)); 12096 mem = SOC_TD2_PMEM(unit, local_port, 12097 MMU_THDU_XPIPE_Q_TO_QGRP_MAPm, 12098 MMU_THDU_YPIPE_Q_TO_QGRP_MAPm); 12099 } else { 12100 BCM_IF_ERROR_RETURN 12101 (_bcm_td2_cosq_index_resolve(unit, gport, cosq, 12102 _BCM_TD2_COSQ_INDEX_STYLE_MCAST_QUEUE, 12103 &local_port, &startq, NULL)); 12104 startq -= 1480; /* MC queues comes after UC queues */ 12105 mem = SOC_TD2_PMEM(unit, local_port, 12106 MMU_THDM_MCQE_QUEUE_CONFIG_0m, 12107 MMU_THDM_MCQE_QUEUE_CONFIG_1m); 12108 mem2 = SOC_TD2_PMEM(unit, local_port, 12109 MMU_THDM_DB_QUEUE_CONFIG_0m, 12110 MMU_THDM_DB_QUEUE_CONFIG_1m); 12111 } 12112 } 12113 12114 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 12115 soc_mem_field32_set(unit, mem, entry, Q_SPIDf, arg); 12116 12117 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 12118 if (mem2 != INVALIDm) { 12119 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem2, MEM_BLOCK_ALL, startq, entry2)); 12120 soc_mem_field32_set(unit, mem2, entry2, Q_SPIDf, arg); 12121 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem2, MEM_BLOCK_ALL, startq, entry2)); 12122 } 12123 return BCM_E_NONE; 12124 } 12125 12126 arg = arg / _BCM_TD2_BYTES_PER_CELL; 12127 12128 /* per service pool settings */ 12129 if (type == bcmCosqControlEgressPoolSharedLimitBytes || 12130 type == bcmCosqControlEgressPoolResumeLimitBytes || 12131 type == bcmCosqControlEgressPoolYellowSharedLimitBytes || 12132 type == bcmCosqControlEgressPoolYellowResumeLimitBytes || 12133 type == bcmCosqControlEgressPoolRedSharedLimitBytes || 12134 type == bcmCosqControlEgressPoolRedResumeLimitBytes) { 12135 uint32 rval; 12136 soc_reg_t reg; 12137 switch (type) { 12138 case bcmCosqControlEgressPoolSharedLimitBytes: 12139 reg = MMU_THDM_DB_POOL_SHARED_LIMITr; 12140 fld_limit = SHARED_LIMITf; 12141 granularity = 1; 12142 break; 12143 case bcmCosqControlEgressPoolResumeLimitBytes: 12144 reg = MMU_THDM_DB_POOL_RESUME_LIMITr; 12145 fld_limit = RESUME_LIMITf; 12146 granularity = 8; 12147 break; 12148 case bcmCosqControlEgressPoolYellowSharedLimitBytes: 12149 reg = MMU_THDM_DB_POOL_YELLOW_SHARED_LIMITr; 12150 fld_limit = YELLOW_SHARED_LIMITf; 12151 granularity = 8; 12152 break; 12153 case bcmCosqControlEgressPoolYellowResumeLimitBytes: 12154 reg = MMU_THDM_DB_POOL_YELLOW_RESUME_LIMITr; 12155 fld_limit = YELLOW_RESUME_LIMITf; 12156 granularity = 8; 12157 break; 12158 case bcmCosqControlEgressPoolRedSharedLimitBytes: 12159 reg = MMU_THDM_DB_POOL_RED_SHARED_LIMITr; 12160 fld_limit = RED_SHARED_LIMITf; 12161 granularity = 8; 12162 break; 12163 case bcmCosqControlEgressPoolRedResumeLimitBytes: 12164 reg = MMU_THDM_DB_POOL_RED_RESUME_LIMITr; 12165 fld_limit = RED_RESUME_LIMITf; 12166 granularity = 8; 12167 break; 12168 /* 12169 * COVERITY 12170 * 12171 * This default is unreachable but needed for some compiler. 12172 */ 12173 /* coverity[dead_error_begin] */ 12174 default: 12175 return BCM_E_UNAVAIL; 12176 } 12177 12178 BCM_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, pool, &rval)); 12179 12180 /* Check for min/max values */ 12181 max_val = (1 << soc_reg_field_length(unit, reg, fld_limit)) - 1; 12182 if ((arg < 0) || ((arg/granularity) > max_val)) { 12183 return BCM_E_PARAM; 12184 } else { 12185 soc_reg_field_set(unit, reg, &rval, fld_limit, (arg/granularity)); 12186 } 12187 12188 BCM_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, pool, rval)); 12189 12190 return BCM_E_NONE; 12191 } 12192 12193 /* per port settings */ 12194 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 12195 BCM_IF_ERROR_RETURN 12196 (_bcm_td2_cosq_index_resolve(unit, gport, cosq, 12197 _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE, 12198 &local_port, &startq, NULL)); 12199 mem = SOC_TD2_PMEM(unit, local_port, MMU_THDU_XPIPE_CONFIG_QUEUEm, 12200 MMU_THDU_YPIPE_CONFIG_QUEUEm); 12201 12202 mem2 = SOC_TD2_PMEM(unit, local_port, MMU_THDU_XPIPE_Q_TO_QGRP_MAPm, 12203 MMU_THDU_YPIPE_Q_TO_QGRP_MAPm); 12204 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 12205 BCM_IF_ERROR_RETURN 12206 (_bcm_td2_cosq_index_resolve(unit, gport, cosq, 12207 _BCM_TD2_COSQ_INDEX_STYLE_MCAST_QUEUE, 12208 &local_port, &startq, NULL)); 12209 mem = SOC_TD2_PMEM(unit, local_port, MMU_THDM_DB_QUEUE_CONFIG_0m, 12210 MMU_THDM_DB_QUEUE_CONFIG_1m); 12211 startq -= 1480; /* MC queues comes after UC queues */ 12212 } else { 12213 if (soc_property_get(unit, spn_PORT_UC_MC_ACCOUNTING_COMBINE, 0) == 0) { 12214 /* Need to have the UC_MC_Combine config enabled */ 12215 return BCM_E_PARAM; 12216 } 12217 mem = SOC_TD2_PMEM(unit, local_port, MMU_THDM_DB_PORTSP_CONFIG_0m, 12218 MMU_THDM_DB_PORTSP_CONFIG_1m); 12219 startq = SOC_TD2_MMU_PIPED_MEM_INDEX(unit, local_port, mem, pool); 12220 } 12221 12222 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 12223 12224 if (mem2 != INVALIDm) { 12225 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem2, MEM_BLOCK_ALL, startq, entry2)); 12226 } 12227 12228 switch (type) { 12229 case bcmCosqControlEgressPoolLimitBytes: 12230 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 12231 fld_limit = Q_SHARED_LIMIT_CELLf; 12232 12233 if (mem2 != INVALIDm) { 12234 soc_mem_field32_set(unit, mem2, entry2, Q_LIMIT_ENABLEf, 1); 12235 } 12236 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 12237 fld_limit = Q_SHARED_LIMITf; 12238 soc_mem_field32_set(unit, mem, entry, Q_LIMIT_ENABLEf, 1); 12239 } else { 12240 fld_limit = SHARED_LIMITf; 12241 soc_mem_field32_set(unit, mem, entry, SHARED_LIMIT_ENABLEf, 1); 12242 } 12243 granularity = 1; 12244 break; 12245 case bcmCosqControlEgressPoolYellowLimitBytes: 12246 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 12247 fld_limit = LIMIT_YELLOW_CELLf; 12248 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 12249 fld_limit = YELLOW_SHARED_LIMITf; 12250 } else { 12251 fld_limit = YELLOW_SHARED_LIMITf; 12252 } 12253 granularity = 8; 12254 break; 12255 case bcmCosqControlEgressPoolRedLimitBytes: 12256 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 12257 fld_limit = LIMIT_RED_CELLf; 12258 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 12259 fld_limit = RED_SHARED_LIMITf; 12260 } else { 12261 fld_limit = RED_SHARED_LIMITf; 12262 } 12263 granularity = 8; 12264 break; 12265 default: 12266 return BCM_E_UNAVAIL; 12267 } 12268 12269 /* Check for min/max values */ 12270 max_val = (1 << soc_mem_field_length(unit, mem, fld_limit)) - 1; 12271 if ((arg < 0) || ((arg/granularity) > max_val)) { 12272 return BCM_E_PARAM; 12273 } else { 12274 soc_mem_field32_set(unit, mem, entry, fld_limit, (arg/granularity)); 12275 } 12276 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 12277 12278 if (mem2 != INVALIDm) { 12279 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem2, MEM_BLOCK_ALL, startq, entry2)); 12280 } 12281 return BCM_E_NONE; 12282 } 12283 12284 12285 12286 STATIC int 12287 _bcm_td2_cosq_egr_port_pool_set(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 12288 bcm_cosq_control_t type, int arg) 12289 { 12290 bcm_port_t local_port; 12291 uint32 max_val; 12292 uint32 entry[SOC_MAX_MEM_WORDS]; 12293 soc_mem_t mem = INVALIDm; 12294 soc_field_t fld_limit = INVALIDf; 12295 int granularity = 1; 12296 int pool, midx; 12297 12298 if (arg < 0) { 12299 return BCM_E_PARAM; 12300 } 12301 12302 BCM_IF_ERROR_RETURN 12303 (_bcm_td2_cosq_index_resolve(unit, gport, cosq, 12304 _BCM_TD2_COSQ_INDEX_STYLE_EGR_POOL, 12305 &local_port, &pool, NULL)); 12306 mem = SOC_TD2_PMEM(unit, local_port, MMU_THDU_XPIPE_CONFIG_PORTm, 12307 MMU_THDU_YPIPE_CONFIG_PORTm); 12308 midx = SOC_TD2_MMU_PIPED_MEM_INDEX(unit, local_port, mem, pool); 12309 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, entry)); 12310 12311 switch (type) { 12312 case bcmCosqControlEgressPortPoolYellowLimitBytes: 12313 fld_limit = YELLOW_LIMITf; 12314 granularity = 8; 12315 break; 12316 case bcmCosqControlEgressPortPoolRedLimitBytes: 12317 fld_limit = RED_LIMITf; 12318 granularity = 8; 12319 break; 12320 default: 12321 return BCM_E_UNAVAIL; 12322 } 12323 12324 arg = arg / _BCM_TD2_BYTES_PER_CELL; 12325 12326 /* Check for min/max values */ 12327 max_val = (1 << soc_mem_field_length(unit, mem, fld_limit)) - 1; 12328 if ((arg < 0) || ((arg/granularity) > max_val)) { 12329 return BCM_E_PARAM; 12330 } else { 12331 soc_mem_field32_set(unit, mem, entry, fld_limit, (arg/granularity)); 12332 } 12333 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, midx, entry)); 12334 12335 return BCM_E_NONE; 12336 } 12337 12338 12339 STATIC int 12340 _bcm_td2_cosq_egr_pool_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 12341 bcm_cosq_control_t type, int *arg) 12342 { 12343 bcm_port_t local_port; 12344 int startq, pool, midx; 12345 uint32 entry[SOC_MAX_MEM_WORDS]; 12346 soc_mem_t mem; 12347 int granularity = 1; 12348 12349 if ((!arg) || (cosq < 0)){ 12350 return BCM_E_PARAM; 12351 } 12352 12353 if (type == bcmCosqControlUCEgressPool) { 12354 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 12355 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) || 12356 BCM_GPORT_IS_SCHEDULER(gport)) { 12357 return BCM_E_PARAM; 12358 } 12359 12360 BCM_IF_ERROR_RETURN 12361 (_bcm_td2_cosq_index_resolve(unit, gport, cosq, 12362 _BCM_TD2_COSQ_INDEX_STYLE_UC_EGR_POOL, 12363 &local_port, &pool, NULL)); 12364 *arg = pool; 12365 return BCM_E_NONE; 12366 } else { 12367 if (type == bcmCosqControlMCEgressPool) { 12368 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 12369 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) || 12370 BCM_GPORT_IS_SCHEDULER(gport)) { 12371 return BCM_E_PARAM; 12372 } 12373 } 12374 BCM_IF_ERROR_RETURN 12375 (_bcm_td2_cosq_index_resolve(unit, gport, cosq, 12376 _BCM_TD2_COSQ_INDEX_STYLE_EGR_POOL, 12377 &local_port, &pool, NULL)); 12378 if (type == bcmCosqControlMCEgressPool || 12379 type == bcmCosqControlEgressPool) { 12380 *arg = pool; 12381 return BCM_E_NONE; 12382 } 12383 } 12384 12385 /* per service pool settings */ 12386 if (type == bcmCosqControlEgressPoolSharedLimitBytes || 12387 type == bcmCosqControlEgressPoolResumeLimitBytes || 12388 type == bcmCosqControlEgressPoolYellowSharedLimitBytes || 12389 type == bcmCosqControlEgressPoolYellowResumeLimitBytes || 12390 type == bcmCosqControlEgressPoolRedSharedLimitBytes || 12391 type == bcmCosqControlEgressPoolRedResumeLimitBytes) { 12392 uint32 rval; 12393 soc_reg_t reg; 12394 soc_field_t fld_limit = INVALIDf; 12395 switch (type) { 12396 case bcmCosqControlEgressPoolSharedLimitBytes: 12397 reg = MMU_THDM_DB_POOL_SHARED_LIMITr; 12398 fld_limit = SHARED_LIMITf; 12399 granularity = 1; 12400 break; 12401 case bcmCosqControlEgressPoolResumeLimitBytes: 12402 reg = MMU_THDM_DB_POOL_RESUME_LIMITr; 12403 fld_limit = RESUME_LIMITf; 12404 granularity = 8; 12405 break; 12406 case bcmCosqControlEgressPoolYellowSharedLimitBytes: 12407 reg = MMU_THDM_DB_POOL_YELLOW_SHARED_LIMITr; 12408 fld_limit = YELLOW_SHARED_LIMITf; 12409 granularity = 8; 12410 break; 12411 case bcmCosqControlEgressPoolYellowResumeLimitBytes: 12412 reg = MMU_THDM_DB_POOL_YELLOW_RESUME_LIMITr; 12413 fld_limit = YELLOW_RESUME_LIMITf; 12414 granularity = 8; 12415 break; 12416 case bcmCosqControlEgressPoolRedSharedLimitBytes: 12417 reg = MMU_THDM_DB_POOL_RED_SHARED_LIMITr; 12418 fld_limit = RED_SHARED_LIMITf; 12419 granularity = 8; 12420 break; 12421 case bcmCosqControlEgressPoolRedResumeLimitBytes: 12422 reg = MMU_THDM_DB_POOL_RED_RESUME_LIMITr; 12423 fld_limit = RED_RESUME_LIMITf; 12424 granularity = 8; 12425 break; 12426 /* coverity[dead_error_begin] */ 12427 default: 12428 return BCM_E_UNAVAIL; 12429 } 12430 12431 BCM_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, pool, &rval)); 12432 12433 *arg = soc_reg_field_get(unit, reg, rval, fld_limit); 12434 *arg = (*arg) * granularity * _BCM_TD2_BYTES_PER_CELL; 12435 12436 return BCM_E_NONE; 12437 } 12438 12439 mem = SOC_TD2_PMEM(unit, local_port, MMU_THDM_DB_PORTSP_CONFIG_0m, 12440 MMU_THDM_DB_PORTSP_CONFIG_1m); 12441 12442 if (type == bcmCosqControlEgressPoolLimitEnable) { 12443 midx = SOC_TD2_MMU_PIPED_MEM_INDEX(unit, local_port, mem, pool); 12444 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, 12445 midx, entry)); 12446 12447 *arg = soc_mem_field32_get(unit, mem, entry, SHARED_LIMIT_ENABLEf); 12448 return BCM_E_NONE; 12449 } 12450 12451 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 12452 BCM_IF_ERROR_RETURN 12453 (_bcm_td2_cosq_index_resolve(unit, gport, cosq, 12454 _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE, 12455 &local_port, &startq, NULL)); 12456 mem = SOC_TD2_PMEM(unit, local_port, MMU_THDU_XPIPE_CONFIG_QUEUEm, 12457 MMU_THDU_YPIPE_CONFIG_QUEUEm); 12458 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 12459 BCM_IF_ERROR_RETURN 12460 (_bcm_td2_cosq_index_resolve(unit, gport, cosq, 12461 _BCM_TD2_COSQ_INDEX_STYLE_MCAST_QUEUE, 12462 &local_port, &startq, NULL)); 12463 mem = SOC_TD2_PMEM(unit, local_port, MMU_THDM_DB_QUEUE_CONFIG_0m, 12464 MMU_THDM_DB_QUEUE_CONFIG_1m); 12465 startq -= 1480; /* MC queues comes after UC queues */ 12466 } else { 12467 if (soc_property_get(unit, spn_PORT_UC_MC_ACCOUNTING_COMBINE, 0) == 0) { 12468 /* Need to have the UC_MC_Combine config enabled */ 12469 return BCM_E_PARAM; 12470 } 12471 mem = SOC_TD2_PMEM(unit, local_port, MMU_THDM_DB_PORTSP_CONFIG_0m, 12472 MMU_THDM_DB_PORTSP_CONFIG_1m); 12473 startq = SOC_TD2_MMU_PIPED_MEM_INDEX(unit, local_port, mem, pool); 12474 } 12475 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, 12476 startq, entry)); 12477 12478 switch (type) { 12479 case bcmCosqControlEgressPoolLimitBytes: 12480 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 12481 *arg = soc_mem_field32_get(unit, mem, entry, Q_SHARED_LIMIT_CELLf); 12482 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 12483 *arg = soc_mem_field32_get(unit, mem, entry, Q_SHARED_LIMITf); 12484 } else { 12485 *arg = soc_mem_field32_get(unit, mem, entry, SHARED_LIMITf); 12486 } 12487 granularity = 1; 12488 break; 12489 case bcmCosqControlEgressPoolYellowLimitBytes: 12490 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 12491 *arg = soc_mem_field32_get(unit, mem, entry, LIMIT_YELLOW_CELLf); 12492 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 12493 *arg = soc_mem_field32_get(unit, mem, entry, YELLOW_SHARED_LIMITf); 12494 } else { 12495 *arg = soc_mem_field32_get(unit, mem, entry, YELLOW_SHARED_LIMITf); 12496 } 12497 granularity = 8; 12498 break; 12499 case bcmCosqControlEgressPoolRedLimitBytes: 12500 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 12501 *arg = soc_mem_field32_get(unit, mem, entry, LIMIT_RED_CELLf); 12502 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 12503 *arg = soc_mem_field32_get(unit, mem, entry, RED_SHARED_LIMITf); 12504 } else { 12505 *arg = soc_mem_field32_get(unit, mem, entry, RED_SHARED_LIMITf); 12506 } 12507 granularity = 8; 12508 break; 12509 default: 12510 return BCM_E_UNAVAIL; 12511 } 12512 *arg = (*arg) * granularity * _BCM_TD2_BYTES_PER_CELL; 12513 return BCM_E_NONE; 12514 } 12515 12516 12517 STATIC int 12518 _bcm_td2_cosq_egr_port_pool_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 12519 bcm_cosq_control_t type, int *arg) 12520 { 12521 bcm_port_t local_port; 12522 uint32 entry[SOC_MAX_MEM_WORDS]; 12523 soc_mem_t mem = INVALIDm; 12524 int granularity = 1; 12525 int pool, midx; 12526 12527 if (!arg) { 12528 return BCM_E_PARAM; 12529 } 12530 12531 BCM_IF_ERROR_RETURN 12532 (_bcm_td2_cosq_index_resolve(unit, gport, cosq, 12533 _BCM_TD2_COSQ_INDEX_STYLE_EGR_POOL, 12534 &local_port, &pool, NULL)); 12535 mem = SOC_TD2_PMEM(unit, local_port, MMU_THDU_XPIPE_CONFIG_PORTm, 12536 MMU_THDU_YPIPE_CONFIG_PORTm); 12537 midx = SOC_TD2_MMU_PIPED_MEM_INDEX(unit, local_port, mem, pool); 12538 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, entry)); 12539 12540 switch (type) { 12541 case bcmCosqControlEgressPortPoolYellowLimitBytes: 12542 *arg = soc_mem_field32_get(unit, mem, entry, YELLOW_LIMITf); 12543 granularity = 8; 12544 break; 12545 case bcmCosqControlEgressPortPoolRedLimitBytes: 12546 *arg = soc_mem_field32_get(unit, mem, entry, RED_LIMITf); 12547 granularity = 8; 12548 break; 12549 default: 12550 return BCM_E_UNAVAIL; 12551 } 12552 12553 12554 *arg = (*arg) * granularity * _BCM_TD2_BYTES_PER_CELL; 12555 return BCM_E_NONE; 12556 } 12557 12558 12559 12560 STATIC int 12561 _bcm_td2_cosq_egr_queue_set(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 12562 bcm_cosq_control_t type, int arg) 12563 { 12564 bcm_port_t local_port; 12565 int startq; 12566 uint32 max_val, rval = 0; 12567 uint32 shared_size, spid; 12568 uint32 entry[SOC_MAX_MEM_WORDS]; 12569 uint32 entry2[SOC_MAX_MEM_WORDS]; 12570 soc_mem_t mem = INVALIDm, mem2 = INVALIDm; 12571 soc_field_t fld_limit = INVALIDf; 12572 soc_field_t fld_sp = INVALIDf; 12573 int granularity = 1; 12574 int from_cos, to_cos, ci; 12575 int cur_val, rv, post_update; 12576 int limit; 12577 12578 if (arg < 0) { 12579 return BCM_E_PARAM; 12580 } 12581 12582 arg /= _BCM_TD2_BYTES_PER_CELL; 12583 12584 if ((type == bcmCosqControlEgressUCQueueMinLimitBytes) || 12585 (type == bcmCosqControlEgressUCQueueSharedLimitBytes)) { 12586 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 12587 BCM_IF_ERROR_RETURN 12588 (_bcm_td2_cosq_index_resolve(unit, gport, cosq, 12589 _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE, 12590 &local_port, &startq, NULL)); 12591 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 12592 return BCM_E_PARAM; 12593 } 12594 else { 12595 if (cosq == BCM_COS_INVALID) { 12596 from_cos = to_cos = 0; 12597 } else { 12598 from_cos = to_cos = cosq; 12599 } 12600 12601 BCM_IF_ERROR_RETURN 12602 (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port)); 12603 if (local_port < 0) { 12604 return BCM_E_PORT; 12605 } 12606 for (ci = from_cos; ci <= to_cos; ci++) { 12607 BCM_IF_ERROR_RETURN 12608 (_bcm_td2_cosq_index_resolve 12609 (unit, local_port, ci, _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE, 12610 NULL, &startq, NULL)); 12611 } 12612 } 12613 mem = SOC_TD2_PMEM(unit, local_port, MMU_THDU_XPIPE_CONFIG_QUEUEm, 12614 MMU_THDU_YPIPE_CONFIG_QUEUEm); 12615 12616 mem2 = SOC_TD2_PMEM(unit, local_port, MMU_THDU_XPIPE_Q_TO_QGRP_MAPm, 12617 MMU_THDU_YPIPE_Q_TO_QGRP_MAPm); 12618 fld_sp = Q_SPIDf; 12619 } else if ((type == bcmCosqControlEgressMCQueueMinLimitBytes) || 12620 (type == bcmCosqControlEgressMCQueueSharedLimitBytes)) { 12621 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 12622 return BCM_E_PARAM; 12623 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 12624 BCM_IF_ERROR_RETURN 12625 (_bcm_td2_cosq_index_resolve(unit, gport, cosq, 12626 _BCM_TD2_COSQ_INDEX_STYLE_MCAST_QUEUE, 12627 &local_port, &startq, NULL)); 12628 } 12629 else { 12630 if (cosq == BCM_COS_INVALID) { 12631 from_cos = to_cos = 0; 12632 } else { 12633 from_cos = to_cos = cosq; 12634 } 12635 12636 BCM_IF_ERROR_RETURN 12637 (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port)); 12638 if (local_port < 0) { 12639 return BCM_E_PORT; 12640 } 12641 for (ci = from_cos; ci <= to_cos; ci++) { 12642 BCM_IF_ERROR_RETURN 12643 (_bcm_td2_cosq_index_resolve 12644 (unit, local_port, ci, _BCM_TD2_COSQ_INDEX_STYLE_MCAST_QUEUE, 12645 NULL, &startq, NULL)); 12646 } 12647 } 12648 mem = SOC_TD2_PMEM(unit, local_port, MMU_THDM_DB_QUEUE_CONFIG_0m, 12649 MMU_THDM_DB_QUEUE_CONFIG_1m); 12650 mem2 = SOC_TD2_PMEM(unit, local_port, MMU_THDM_MCQE_QUEUE_CONFIG_0m, 12651 MMU_THDM_MCQE_QUEUE_CONFIG_1m); 12652 fld_sp = Q_SPIDf; 12653 startq -= 1480; /* MC queues comes after UC queues */ 12654 } else { 12655 return BCM_E_PARAM; 12656 } 12657 12658 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 12659 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem2, MEM_BLOCK_ALL, startq, entry2)); 12660 12661 switch (type) { 12662 case bcmCosqControlEgressUCQueueSharedLimitBytes: 12663 fld_limit = Q_SHARED_LIMIT_CELLf; 12664 12665 soc_mem_field32_set(unit, mem2, entry2, Q_LIMIT_ENABLEf, 1); 12666 12667 /* Set MMU_THDU_XPIPE_Q_TO_QGRP_MAP.DISABLE_QUEUING to 1 when both MIN 12668 * and SHARED LIMIT are 0. Set it to 0 when either MIN or SHARED LIMIT 12669 * is non-zero. 12670 */ 12671 limit = soc_mem_field32_get(unit, mem, entry, Q_MIN_LIMIT_CELLf); 12672 if (arg == 0 && limit == 0) { 12673 soc_mem_field32_set(unit, mem2, entry2, DISABLE_QUEUINGf, 1); 12674 } else if (arg != 0 || limit != 0) { 12675 soc_mem_field32_set(unit, mem2, entry2, DISABLE_QUEUINGf, 0); 12676 } 12677 spid = soc_mem_field32_get(unit, mem2, entry2, fld_sp); 12678 granularity = 1; 12679 break; 12680 case bcmCosqControlEgressMCQueueSharedLimitBytes: 12681 fld_limit = Q_SHARED_LIMITf; 12682 soc_mem_field32_set(unit, mem, entry, Q_LIMIT_ENABLEf, 1); 12683 12684 /* Config LIMIT in THDO_MC_QE: in 4-enties granularity */ 12685 granularity = 4; 12686 soc_mem_field32_set(unit, mem2, entry2, fld_limit, (arg/granularity)); 12687 soc_mem_field32_set(unit, mem2, entry2, Q_LIMIT_ENABLEf, 1); 12688 spid = soc_mem_field32_get(unit, mem, entry, fld_sp); 12689 granularity = 1; 12690 break; 12691 case bcmCosqControlEgressUCQueueMinLimitBytes: 12692 fld_limit = Q_MIN_LIMIT_CELLf; 12693 12694 /* Set MMU_THDU_XPIPE_Q_TO_QGRP_MAP.DISABLE_QUEUING to 1 when both MIN 12695 * and SHARED LIMIT are 0. Set it to 0 when either MIN or SHARED LIMIT is non-zero 12696 */ 12697 limit = soc_mem_field32_get(unit, mem, entry, Q_SHARED_LIMIT_CELLf); 12698 if (arg == 0 && limit == 0) { 12699 soc_mem_field32_set(unit, mem2, entry2, DISABLE_QUEUINGf, 1); 12700 } else if (arg != 0 || limit != 0) { 12701 soc_mem_field32_set(unit, mem2, entry2, DISABLE_QUEUINGf, 0); 12702 } 12703 spid = soc_mem_field32_get(unit, mem2, entry2, fld_sp); 12704 granularity = 1; 12705 break; 12706 case bcmCosqControlEgressMCQueueMinLimitBytes: 12707 fld_limit = Q_MIN_LIMITf; 12708 12709 /* Config LIMIT in THDO_MC_QE: in 4-enties granularity */ 12710 granularity = 4; 12711 soc_mem_field32_set(unit, mem2, entry2, fld_limit, (arg/granularity)); 12712 spid = soc_mem_field32_get(unit, mem, entry, fld_sp); 12713 granularity = 1; 12714 break; 12715 default: 12716 return BCM_E_UNAVAIL; 12717 } 12718 12719 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 12720 12721 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem2, MEM_BLOCK_ALL, startq, entry2)); 12722 12723 12724 /* Recalculate Shared Values if Min Changed */ 12725 SOC_IF_ERROR_RETURN(READ_MMU_THDM_DB_POOL_SHARED_LIMITr(unit, spid, &rval)); 12726 shared_size = soc_reg_field_get(unit, MMU_THDM_DB_POOL_SHARED_LIMITr, 12727 rval, SHARED_LIMITf); 12728 cur_val = soc_mem_field32_get(unit, mem, entry, fld_limit); 12729 12730 if ((arg / granularity) > cur_val) { 12731 /* New Min Val > Cur Min Val 12732 * So reduce the Shared values first and then 12733 * Increase the Min Value for given resource 12734 */ 12735 post_update = 0; 12736 } else if ((arg / granularity) < cur_val) { 12737 /* New Min Val < Cur Min Val 12738 * So reduce the Min values first and then 12739 * Increase Shared values everywhere 12740 */ 12741 post_update = 1; 12742 } else { 12743 return BCM_E_NONE; 12744 } 12745 12746 if (!post_update && 12747 ((type == bcmCosqControlEgressUCQueueMinLimitBytes) || 12748 (type == bcmCosqControlEgressMCQueueMinLimitBytes))) { 12749 int delta = 0; /* In Cells */ 12750 delta = ((arg / granularity) - cur_val) * granularity; 12751 if (delta > shared_size) { 12752 return BCM_E_RESOURCE; 12753 } 12754 rv = soc_td2_mmu_config_res_limits_update(unit, spid, 12755 shared_size - delta, 1); 12756 if (rv < 0) { 12757 return rv; 12758 } 12759 } 12760 12761 12762 /* Check for min/max values */ 12763 max_val = (1 << soc_mem_field_length(unit, mem, fld_limit)) - 1; 12764 if ((arg < 0) || ((arg/granularity) > max_val)) { 12765 return BCM_E_PARAM; 12766 } else { 12767 /* Get the latest entry data and update. */ 12768 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, 12769 startq, entry)); 12770 soc_mem_field32_set(unit, mem, entry, fld_limit, (arg/granularity)); 12771 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 12772 } 12773 12774 if (post_update && 12775 ((type == bcmCosqControlEgressUCQueueMinLimitBytes) || 12776 (type == bcmCosqControlEgressMCQueueMinLimitBytes))) { 12777 int delta = 0; 12778 delta = (cur_val - (arg / granularity)) * granularity; 12779 rv = soc_td2_mmu_config_res_limits_update(unit, spid, 12780 shared_size + delta, 0); 12781 if (rv < 0) { 12782 return rv; 12783 } 12784 } 12785 12786 return BCM_E_NONE; 12787 } 12788 12789 STATIC int 12790 _bcm_td2_cosq_egr_queue_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 12791 bcm_cosq_control_t type, int *arg) 12792 { 12793 bcm_port_t local_port; 12794 int startq; 12795 uint32 entry[SOC_MAX_MEM_WORDS]; 12796 soc_mem_t mem = INVALIDm; 12797 soc_field_t fld_limit = INVALIDf; 12798 int granularity = 1; 12799 int from_cos, to_cos, ci; 12800 12801 if (!arg) { 12802 return BCM_E_PARAM; 12803 } 12804 12805 if ((type == bcmCosqControlEgressUCQueueMinLimitBytes) || 12806 (type == bcmCosqControlEgressUCQueueSharedLimitBytes)) { 12807 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 12808 BCM_IF_ERROR_RETURN 12809 (_bcm_td2_cosq_index_resolve(unit, gport, cosq, 12810 _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE, 12811 &local_port, &startq, NULL)); 12812 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 12813 return BCM_E_PARAM; 12814 } 12815 else { 12816 if (cosq == BCM_COS_INVALID) { 12817 from_cos = to_cos = 0; 12818 } else { 12819 from_cos = to_cos = cosq; 12820 } 12821 12822 BCM_IF_ERROR_RETURN 12823 (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port)); 12824 if (local_port < 0) { 12825 return BCM_E_PORT; 12826 } 12827 for (ci = from_cos; ci <= to_cos; ci++) { 12828 BCM_IF_ERROR_RETURN 12829 (_bcm_td2_cosq_index_resolve 12830 (unit, local_port, ci, _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE, 12831 NULL, &startq, NULL)); 12832 } 12833 } 12834 mem = SOC_TD2_PMEM(unit, local_port, MMU_THDU_XPIPE_CONFIG_QUEUEm, 12835 MMU_THDU_YPIPE_CONFIG_QUEUEm); 12836 } else if ((type == bcmCosqControlEgressMCQueueMinLimitBytes) || 12837 (type == bcmCosqControlEgressMCQueueSharedLimitBytes)) { 12838 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 12839 return BCM_E_PARAM; 12840 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 12841 BCM_IF_ERROR_RETURN 12842 (_bcm_td2_cosq_index_resolve(unit, gport, cosq, 12843 _BCM_TD2_COSQ_INDEX_STYLE_MCAST_QUEUE, 12844 &local_port, &startq, NULL)); 12845 } 12846 else { 12847 if (cosq == BCM_COS_INVALID) { 12848 from_cos = to_cos = 0; 12849 } else { 12850 from_cos = to_cos = cosq; 12851 } 12852 12853 BCM_IF_ERROR_RETURN 12854 (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port)); 12855 if (local_port < 0) { 12856 return BCM_E_PORT; 12857 } 12858 for (ci = from_cos; ci <= to_cos; ci++) { 12859 BCM_IF_ERROR_RETURN 12860 (_bcm_td2_cosq_index_resolve 12861 (unit, local_port, ci, _BCM_TD2_COSQ_INDEX_STYLE_MCAST_QUEUE, 12862 NULL, &startq, NULL)); 12863 } 12864 } 12865 mem = SOC_TD2_PMEM(unit, local_port, MMU_THDM_DB_QUEUE_CONFIG_0m, 12866 MMU_THDM_DB_QUEUE_CONFIG_1m); 12867 startq -= 1480; /* MC queues comes after UC queues */ 12868 } else { 12869 return BCM_E_PARAM; 12870 } 12871 12872 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, 12873 startq, entry)); 12874 12875 switch (type) { 12876 case bcmCosqControlEgressUCQueueSharedLimitBytes: 12877 fld_limit = Q_SHARED_LIMIT_CELLf; 12878 granularity = 1; 12879 break; 12880 case bcmCosqControlEgressMCQueueSharedLimitBytes: 12881 fld_limit = Q_SHARED_LIMITf; 12882 granularity = 1; 12883 break; 12884 case bcmCosqControlEgressUCQueueMinLimitBytes: 12885 fld_limit = Q_MIN_LIMIT_CELLf; 12886 granularity = 1; 12887 break; 12888 case bcmCosqControlEgressMCQueueMinLimitBytes: 12889 fld_limit = Q_MIN_LIMITf; 12890 granularity = 1; 12891 break; 12892 default: 12893 return BCM_E_UNAVAIL; 12894 } 12895 *arg = soc_mem_field32_get(unit, mem, entry, fld_limit); 12896 *arg = (*arg) * granularity * _BCM_TD2_BYTES_PER_CELL; 12897 return BCM_E_NONE; 12898 } 12899 12900 STATIC int 12901 _bcm_td2_cosq_ing_res_set(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 12902 bcm_cosq_control_t type, int arg) 12903 { 12904 bcm_port_t local_port; 12905 int midx; 12906 uint32 max_val, rval; 12907 uint32 entry[SOC_MAX_MEM_WORDS]; 12908 soc_mem_t mem = INVALIDm; 12909 soc_field_t fld_limit = INVALIDf; 12910 soc_reg_t reg = INVALIDr; 12911 int port_pg, port_pg_pool, granularity = 1; 12912 static const soc_reg_t prigroup_reg[] = { 12913 THDI_PORT_PRI_GRP0r, THDI_PORT_PRI_GRP1r 12914 }; 12915 static const soc_field_t prigroup_field[] = { 12916 PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf, 12917 PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf, 12918 PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf, 12919 PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf 12920 }; 12921 static const soc_field_t prigroup_spid_field[] = { 12922 PG0_SPIDf, PG1_SPIDf, PG2_SPIDf, PG3_SPIDf, 12923 PG4_SPIDf, PG5_SPIDf, PG6_SPIDf, PG7_SPIDf 12924 }; 12925 12926 if (cosq > 15 || cosq < 0) { 12927 /* Error. Input pri > Max Pri_Grp */ 12928 return BCM_E_PARAM; 12929 } 12930 12931 if (arg < 0) { 12932 return BCM_E_PARAM; 12933 } 12934 12935 arg /= _BCM_TD2_BYTES_PER_CELL; 12936 BCM_IF_ERROR_RETURN 12937 (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port)); 12938 if (local_port < 0) { 12939 return BCM_E_PORT; 12940 } 12941 12942 /* get PG for port using Port+Cos */ 12943 if (cosq < 8) { 12944 reg = prigroup_reg[0]; 12945 } else { 12946 reg = prigroup_reg[1]; 12947 } 12948 12949 SOC_IF_ERROR_RETURN 12950 (soc_reg32_get(unit, reg, local_port, 0, &rval)); 12951 port_pg = soc_reg_field_get(unit, reg, rval, prigroup_field[cosq]); 12952 12953 12954 if ((type == bcmCosqControlIngressPortPGSharedLimitBytes) || 12955 (type == bcmCosqControlIngressPortPGMinLimitBytes)|| 12956 (type == bcmCosqControlIngressPortPGHeadroomLimitBytes)|| 12957 (type == bcmCosqControlIngressPortPGResetFloorBytes)) { 12958 mem = SOC_TD2_PMEM(unit, local_port, THDI_PORT_PG_CONFIG_Xm, 12959 THDI_PORT_PG_CONFIG_Ym); 12960 /* get index for Port-PG */ 12961 midx = SOC_TD2_MMU_PIPED_MEM_INDEX(unit, local_port, mem, port_pg); 12962 12963 } else if ((type == bcmCosqControlIngressPortPoolMaxLimitBytes) || 12964 (type == bcmCosqControlIngressPortPoolMinLimitBytes)) { 12965 reg = THDI_PORT_PG_SPIDr; 12966 12967 SOC_IF_ERROR_RETURN 12968 (soc_reg32_get(unit, reg, local_port, 0, &rval)); 12969 port_pg_pool = soc_reg_field_get(unit, reg, rval, prigroup_spid_field[port_pg]); 12970 12971 mem = SOC_TD2_PMEM(unit, local_port, THDI_PORT_SP_CONFIG_Xm, 12972 THDI_PORT_SP_CONFIG_Ym); 12973 /* get index for Port-SP */ 12974 midx = SOC_TD2_MMU_PIPED_MEM_INDEX(unit, local_port, mem, port_pg_pool); 12975 } else { 12976 return BCM_E_UNAVAIL; 12977 } 12978 12979 if (midx < 0) { 12980 return BCM_E_PARAM; 12981 } 12982 12983 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, entry)); 12984 12985 switch (type) { 12986 case bcmCosqControlIngressPortPGSharedLimitBytes: 12987 fld_limit = PG_SHARED_LIMITf; 12988 granularity = 1; 12989 break; 12990 case bcmCosqControlIngressPortPoolMaxLimitBytes: 12991 fld_limit = PORT_SP_MAX_LIMITf; 12992 granularity = 1; 12993 break; 12994 case bcmCosqControlIngressPortPGMinLimitBytes: 12995 fld_limit = PG_MIN_LIMITf; 12996 granularity = 1; 12997 break; 12998 case bcmCosqControlIngressPortPoolMinLimitBytes: 12999 fld_limit = PORT_SP_MIN_LIMITf; 13000 granularity = 1; 13001 break; 13002 case bcmCosqControlIngressPortPGHeadroomLimitBytes: 13003 fld_limit = PG_HDRM_LIMITf; 13004 granularity = 1; 13005 break; 13006 case bcmCosqControlIngressPortPGResetFloorBytes: 13007 fld_limit = PG_RESET_FLOORf; 13008 granularity = 1; 13009 break; 13010 /* coverity[dead_error_begin] */ 13011 default: 13012 return BCM_E_UNAVAIL; 13013 } 13014 13015 /* Check for min/max values */ 13016 max_val = (1 << soc_mem_field_length(unit, mem, fld_limit)) - 1; 13017 if ((arg < 0) || ((arg/granularity) > max_val)) { 13018 return BCM_E_PARAM; 13019 } else { 13020 soc_mem_field32_set(unit, mem, entry, fld_limit, (arg/granularity)); 13021 } 13022 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, midx, entry)); 13023 13024 return BCM_E_NONE; 13025 } 13026 13027 STATIC int 13028 _bcm_td2_cosq_state_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 13029 bcm_cosq_control_t type, int *arg) 13030 { 13031 bcm_port_t local_port; 13032 uint32 rval, state , mask = 1 , bitno = 0; 13033 static const soc_field_t pool_field[] = { 13034 POOL_0f, POOL_1f, POOL_2f, POOL_3f }; 13035 int start_pool_idx = 0,end_pool_idx = 0; 13036 if (!arg) { 13037 return BCM_E_PARAM; 13038 } 13039 switch (type) { 13040 case bcmCosqControlSPPortLimitState: 13041 case bcmCosqControlPoolRedDropState: 13042 case bcmCosqControlPoolYellowDropState: 13043 case bcmCosqControlPoolGreenDropState: 13044 BCM_IF_ERROR_RETURN 13045 (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port)); 13046 13047 if (!SOC_PORT_VALID(unit, local_port)) { 13048 return BCM_E_PORT; 13049 } 13050 BCM_IF_ERROR_RETURN (_bcm_td2_cosq_egress_sp_get(unit, gport, cosq, &start_pool_idx, 13051 &end_pool_idx)); 13052 bitno = start_pool_idx; 13053 break; 13054 13055 case bcmCosqControlPGPortLimitState: 13056 case bcmCosqControlPGPortXoffState: 13057 BCM_IF_ERROR_RETURN 13058 (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port)); 13059 13060 if (!SOC_PORT_VALID(unit, local_port)) { 13061 return BCM_E_PORT; 13062 } 13063 if ((cosq < 0 ) || (cosq > 7)) { 13064 return BCM_E_PARAM; 13065 } 13066 bitno = cosq; 13067 break; 13068 default: 13069 return BCM_E_PARAM; 13070 } 13071 switch (type) { 13072 case bcmCosqControlSPPortLimitState: 13073 SOC_IF_ERROR_RETURN( 13074 READ_THDI_PORT_LIMIT_STATESr(unit, local_port, &rval)); 13075 state = soc_reg_field_get(unit, THDI_PORT_LIMIT_STATESr, rval, 13076 SP_LIMIT_STATEf); 13077 break; 13078 case bcmCosqControlPGPortLimitState: 13079 SOC_IF_ERROR_RETURN( 13080 READ_THDI_PORT_LIMIT_STATESr(unit, local_port, &rval)); 13081 state = soc_reg_field_get(unit, THDI_PORT_LIMIT_STATESr, rval, 13082 PG_LIMIT_STATEf); 13083 break; 13084 case bcmCosqControlPGPortXoffState: 13085 SOC_IF_ERROR_RETURN( 13086 READ_THDI_FLOW_CONTROL_XOFF_STATEr(unit, local_port, &rval)); 13087 state = soc_reg_field_get(unit, THDI_FLOW_CONTROL_XOFF_STATEr, rval, 13088 PG_BMPf); 13089 break; 13090 case bcmCosqControlPoolRedDropState: 13091 SOC_IF_ERROR_RETURN( 13092 READ_THDI_POOL_DROP_STATEr(unit, &rval)); 13093 state = soc_reg_field_get(unit, THDI_POOL_DROP_STATEr, rval, 13094 pool_field[start_pool_idx]); 13095 bitno = 2; 13096 break; 13097 case bcmCosqControlPoolYellowDropState: 13098 SOC_IF_ERROR_RETURN( 13099 READ_THDI_POOL_DROP_STATEr(unit, &rval)); 13100 state = soc_reg_field_get(unit, THDI_POOL_DROP_STATEr, rval, 13101 pool_field[start_pool_idx]); 13102 bitno = 1; 13103 break; 13104 case bcmCosqControlPoolGreenDropState: 13105 SOC_IF_ERROR_RETURN( 13106 READ_THDI_POOL_DROP_STATEr(unit, &rval)); 13107 state = soc_reg_field_get(unit, THDI_POOL_DROP_STATEr, rval, 13108 pool_field[start_pool_idx]); 13109 bitno = 0; 13110 break; 13111 /* 13112 * COVERITY 13113 * 13114 * This default is unreachable but needed for some compiler. 13115 */ 13116 /* coverity[dead_error_begin] */ 13117 default : 13118 return BCM_E_PARAM; 13119 } 13120 mask = mask<<bitno; 13121 state = state & mask ; 13122 if (state) { 13123 *arg = 1 ; 13124 } else { 13125 *arg = 0 ; 13126 } 13127 return BCM_E_NONE; 13128 } 13129 13130 STATIC int 13131 _bcm_td2_cosq_ing_res_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 13132 bcm_cosq_control_t type, int *arg) 13133 { 13134 bcm_port_t local_port; 13135 uint32 rval; 13136 uint32 entry[SOC_MAX_MEM_WORDS]; 13137 soc_mem_t mem = INVALIDm; 13138 soc_field_t fld_limit = INVALIDf; 13139 soc_reg_t reg = INVALIDr; 13140 int midx, port_pg, port_pg_pool, granularity = 1; 13141 static const soc_reg_t prigroup_reg[] = { 13142 THDI_PORT_PRI_GRP0r, THDI_PORT_PRI_GRP1r 13143 }; 13144 static const soc_field_t prigroup_field[] = { 13145 PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf, 13146 PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf, 13147 PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf, 13148 PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf 13149 }; 13150 static const soc_field_t prigroup_spid_field[] = { 13151 PG0_SPIDf, PG1_SPIDf, PG2_SPIDf, PG3_SPIDf, 13152 PG4_SPIDf, PG5_SPIDf, PG6_SPIDf, PG7_SPIDf 13153 }; 13154 13155 if (cosq > 15 || cosq < 0) { 13156 /* Error. Input pri > Max Pri_Grp */ 13157 return BCM_E_PARAM; 13158 } 13159 if (!arg) { 13160 return BCM_E_PARAM; 13161 } 13162 13163 BCM_IF_ERROR_RETURN 13164 (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port)); 13165 if (local_port < 0) { 13166 return BCM_E_PORT; 13167 } 13168 13169 /* get PG for port using Port+Cos */ 13170 if (cosq < 8) { 13171 reg = prigroup_reg[0]; 13172 } else { 13173 reg = prigroup_reg[1]; 13174 } 13175 13176 SOC_IF_ERROR_RETURN 13177 (soc_reg32_get(unit, reg, local_port, 0, &rval)); 13178 port_pg = soc_reg_field_get(unit, reg, rval, prigroup_field[cosq]); 13179 13180 13181 if ((type == bcmCosqControlIngressPortPGSharedLimitBytes) || 13182 (type == bcmCosqControlIngressPortPGMinLimitBytes)|| 13183 (type == bcmCosqControlIngressPortPGHeadroomLimitBytes)|| 13184 (type == bcmCosqControlIngressPortPGResetFloorBytes)) { 13185 mem = SOC_TD2_PMEM(unit, local_port, THDI_PORT_PG_CONFIG_Xm, 13186 THDI_PORT_PG_CONFIG_Ym); 13187 /* get index for Port-PG */ 13188 midx = SOC_TD2_MMU_PIPED_MEM_INDEX(unit, local_port, mem, port_pg); 13189 } else if ((type == bcmCosqControlIngressPortPoolMaxLimitBytes) || 13190 (type == bcmCosqControlIngressPortPoolMinLimitBytes)) { 13191 reg = THDI_PORT_PG_SPIDr; 13192 13193 SOC_IF_ERROR_RETURN 13194 (soc_reg32_get(unit, reg, local_port, 0, &rval)); 13195 port_pg_pool = soc_reg_field_get(unit, reg, rval, prigroup_spid_field[port_pg]); 13196 13197 mem = SOC_TD2_PMEM(unit, local_port, THDI_PORT_SP_CONFIG_Xm, 13198 THDI_PORT_SP_CONFIG_Ym); 13199 /* get index for Port-SP */ 13200 midx = SOC_TD2_MMU_PIPED_MEM_INDEX(unit, local_port, mem, port_pg_pool); 13201 } else { 13202 return BCM_E_UNAVAIL; 13203 } 13204 13205 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, entry)); 13206 13207 switch (type) { 13208 case bcmCosqControlIngressPortPGSharedLimitBytes: 13209 fld_limit = PG_SHARED_LIMITf; 13210 granularity = 1; 13211 break; 13212 case bcmCosqControlIngressPortPoolMaxLimitBytes: 13213 fld_limit = PORT_SP_MAX_LIMITf; 13214 granularity = 1; 13215 break; 13216 case bcmCosqControlIngressPortPGMinLimitBytes: 13217 fld_limit = PG_MIN_LIMITf; 13218 granularity = 1; 13219 break; 13220 case bcmCosqControlIngressPortPoolMinLimitBytes: 13221 fld_limit = PORT_SP_MIN_LIMITf; 13222 granularity = 1; 13223 break; 13224 case bcmCosqControlIngressPortPGHeadroomLimitBytes: 13225 fld_limit = PG_HDRM_LIMITf; 13226 granularity = 1; 13227 break; 13228 case bcmCosqControlIngressPortPGResetFloorBytes: 13229 fld_limit = PG_RESET_FLOORf; 13230 granularity = 1; 13231 break; 13232 /* coverity[dead_error_begin] */ 13233 default: 13234 return BCM_E_UNAVAIL; 13235 } 13236 13237 *arg = soc_mem_field32_get(unit, mem, entry, fld_limit); 13238 *arg = (*arg) * granularity * _BCM_TD2_BYTES_PER_CELL; 13239 return BCM_E_NONE; 13240 } 13241 13242 /* 13243 * This function is used to get ingress pool 13244 * limit given Ingress [Port, Priority] 13245 */ 13246 STATIC int 13247 _bcm_td2_cosq_ing_res_limit_get(int unit, bcm_gport_t gport, bcm_cos_t cosq, 13248 bcm_cosq_control_t type, int *arg) 13249 { 13250 bcm_port_t local_port; 13251 uint32 rval; 13252 soc_reg_t reg = INVALIDr; 13253 int port_pg, port_pg_pool; 13254 static const soc_reg_t prigroup_reg[] = { 13255 THDI_PORT_PRI_GRP0r, THDI_PORT_PRI_GRP1r 13256 }; 13257 static const soc_field_t prigroup_field[] = { 13258 PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf, 13259 PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf, 13260 PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf, 13261 PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf 13262 }; 13263 static const soc_field_t prigroup_spid_field[] = { 13264 PG0_SPIDf, PG1_SPIDf, PG2_SPIDf, PG3_SPIDf, 13265 PG4_SPIDf, PG5_SPIDf, PG6_SPIDf, PG7_SPIDf 13266 }; 13267 13268 if (cosq > 15 || cosq < 0) { 13269 /* Error. Input pri > Max Pri_Grp */ 13270 return BCM_E_PARAM; 13271 } 13272 if (!arg) { 13273 return BCM_E_PARAM; 13274 } 13275 13276 BCM_IF_ERROR_RETURN 13277 (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port)); 13278 if (local_port < 0) { 13279 return BCM_E_PORT; 13280 } 13281 13282 /* get PG for port using Port+Cos */ 13283 if (cosq < 8) { 13284 reg = prigroup_reg[0]; 13285 } else { 13286 reg = prigroup_reg[1]; 13287 } 13288 13289 SOC_IF_ERROR_RETURN 13290 (soc_reg32_get(unit, reg, local_port, 0, &rval)); 13291 port_pg = soc_reg_field_get(unit, reg, rval, prigroup_field[cosq]); 13292 13293 13294 if (type == bcmCosqControlIngressPoolLimitBytes) { 13295 reg = THDI_PORT_PG_SPIDr; 13296 13297 SOC_IF_ERROR_RETURN 13298 (soc_reg32_get(unit, reg, local_port, 0, &rval)); 13299 port_pg_pool = soc_reg_field_get(unit, reg, rval, prigroup_spid_field[port_pg]); 13300 13301 SOC_IF_ERROR_RETURN 13302 (READ_THDI_BUFFER_CELL_LIMIT_SPr(unit, port_pg_pool, &rval)); 13303 *arg = soc_reg_field_get(unit, THDI_BUFFER_CELL_LIMIT_SPr, rval, LIMITf); 13304 } else { 13305 return BCM_E_PARAM; 13306 } 13307 13308 *arg = (*arg) * _BCM_TD2_BYTES_PER_CELL; 13309 13310 return BCM_E_NONE; 13311 } 13312 13313 /* 13314 * This function is used to set ingress pool 13315 * limit given Ingress [Port, Priority] 13316 */ 13317 STATIC int 13318 _bcm_td2_cosq_ing_res_limit_set(int unit, bcm_gport_t gport, bcm_cos_t cosq, 13319 bcm_cosq_control_t type, int arg) 13320 { 13321 bcm_port_t local_port; 13322 uint32 max_val, rval; 13323 soc_reg_t reg = INVALIDr; 13324 int port_pg, port_pg_pool; 13325 static const soc_reg_t prigroup_reg[] = { 13326 THDI_PORT_PRI_GRP0r, THDI_PORT_PRI_GRP1r 13327 }; 13328 static const soc_field_t prigroup_field[] = { 13329 PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf, 13330 PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf, 13331 PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf, 13332 PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf 13333 }; 13334 static const soc_field_t prigroup_spid_field[] = { 13335 PG0_SPIDf, PG1_SPIDf, PG2_SPIDf, PG3_SPIDf, 13336 PG4_SPIDf, PG5_SPIDf, PG6_SPIDf, PG7_SPIDf 13337 }; 13338 13339 if (cosq > 15 || cosq < 0) { 13340 /* Error. Input pri > Max Pri_Grp */ 13341 return BCM_E_PARAM; 13342 } 13343 13344 if (arg < 0) { 13345 return BCM_E_PARAM; 13346 } 13347 13348 arg /= _BCM_TD2_BYTES_PER_CELL; 13349 BCM_IF_ERROR_RETURN 13350 (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port)); 13351 if (local_port < 0) { 13352 return BCM_E_PORT; 13353 } 13354 13355 /* get PG for port using Port+Cos */ 13356 if (cosq < 8) { 13357 reg = prigroup_reg[0]; 13358 } else { 13359 reg = prigroup_reg[1]; 13360 } 13361 13362 SOC_IF_ERROR_RETURN 13363 (soc_reg32_get(unit, reg, local_port, 0, &rval)); 13364 port_pg = soc_reg_field_get(unit, reg, rval, prigroup_field[cosq]); 13365 13366 if (type == bcmCosqControlIngressPoolLimitBytes) { 13367 reg = THDI_PORT_PG_SPIDr; 13368 13369 SOC_IF_ERROR_RETURN 13370 (soc_reg32_get(unit, reg, local_port, 0, &rval)); 13371 port_pg_pool = soc_reg_field_get(unit, reg, rval, prigroup_spid_field[port_pg]); 13372 13373 rval = 0; 13374 SOC_IF_ERROR_RETURN(READ_THDI_BUFFER_CELL_LIMIT_SPr(unit, port_pg_pool, &rval)); 13375 /* Check for min/max values */ 13376 max_val = (1 << soc_reg_field_length(unit, THDI_BUFFER_CELL_LIMIT_SPr, LIMITf)) - 1; 13377 if ((arg < 0) || (arg > max_val)) { 13378 return BCM_E_PARAM; 13379 } else { 13380 soc_reg_field_set(unit, THDI_BUFFER_CELL_LIMIT_SPr, &rval, LIMITf, arg); 13381 } 13382 13383 SOC_IF_ERROR_RETURN(WRITE_THDI_BUFFER_CELL_LIMIT_SPr(unit, port_pg_pool, rval)); 13384 } else { 13385 return BCM_E_PARAM; 13386 } 13387 13388 return BCM_E_NONE; 13389 } 13390 13391 13392 STATIC int 13393 _bcm_td2_cosq_ef_op_at_index(int unit, int port, int hw_index, _bcm_cosq_op_t op, 13394 int *ef_val) 13395 { 13396 uint32 entry[SOC_MAX_MEM_WORDS]; 13397 soc_trident2_sched_type_t sched_type; 13398 soc_mem_t mem; 13399 13400 sched_type = _soc_trident2_port_sched_type_get(unit, port); 13401 13402 if (sched_type == SOC_TD2_SCHED_LLS) { 13403 mem = _SOC_TD2_NODE_PARENT_MEM(unit, port, SOC_TD2_NODE_LVL_L2); 13404 SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, hw_index, &entry)); 13405 13406 if (op == _BCM_COSQ_OP_GET) { 13407 *ef_val = soc_mem_field32_get(unit, mem, &entry, C_EFf); 13408 } else { 13409 soc_mem_field32_set(unit, mem, &entry, C_EFf, *ef_val); 13410 SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, 13411 hw_index, &entry)); 13412 } 13413 } else { 13414 return BCM_E_UNAVAIL; 13415 } 13416 13417 return BCM_E_NONE; 13418 } 13419 13420 STATIC int 13421 _bcm_td2_cosq_ef_op(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, int *arg, 13422 _bcm_cosq_op_t op) 13423 { 13424 _bcm_td2_cosq_node_t *node; 13425 bcm_port_t local_port; 13426 int index, numq, from_cos, to_cos, ci; 13427 13428 if (BCM_GPORT_IS_SCHEDULER(gport)) { 13429 BCM_IF_ERROR_RETURN 13430 (_bcm_td2_cosq_node_get(unit, gport, 0, NULL, 13431 &local_port, NULL, &node)); 13432 BCM_IF_ERROR_RETURN( 13433 _bcm_td2_cosq_child_node_at_input(node, cosq, &node)); 13434 gport = node->gport; 13435 cosq = 0; 13436 } 13437 13438 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 13439 BCM_IF_ERROR_RETURN 13440 (_bcm_td2_cosq_index_resolve 13441 (unit, gport, cosq, _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE, 13442 &local_port, &index, NULL)); 13443 return _bcm_td2_cosq_ef_op_at_index(unit, local_port, index, op, arg); 13444 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 13445 BCM_IF_ERROR_RETURN 13446 (_bcm_td2_cosq_index_resolve 13447 (unit, gport, cosq, _BCM_TD2_COSQ_INDEX_STYLE_MCAST_QUEUE, 13448 &local_port, &index, NULL)); 13449 return _bcm_td2_cosq_ef_op_at_index(unit, local_port, index, op, arg); 13450 } else if (BCM_GPORT_IS_SCHEDULER(gport)) { 13451 return BCM_E_PARAM; 13452 } else { 13453 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_port_has_ets(unit, local_port)); 13454 if (cosq == BCM_COS_INVALID) { 13455 from_cos = 0; 13456 to_cos = _TD2_NUM_COS(unit) - 1; 13457 } else { 13458 from_cos = to_cos = cosq; 13459 } 13460 for (ci = from_cos; ci <= to_cos; ci++) { 13461 BCM_IF_ERROR_RETURN 13462 (_bcm_td2_cosq_index_resolve 13463 (unit, gport, ci, _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE, 13464 &local_port, &index, &numq)); 13465 13466 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_ef_op_at_index(unit, 13467 local_port, index, op, arg)); 13468 if (op == _BCM_COSQ_OP_GET) { 13469 return BCM_E_NONE; 13470 } 13471 13472 BCM_IF_ERROR_RETURN 13473 (_bcm_td2_cosq_index_resolve 13474 (unit, gport, ci, _BCM_TD2_COSQ_INDEX_STYLE_MCAST_QUEUE, 13475 &local_port, &index, &numq)); 13476 13477 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_ef_op_at_index(unit, 13478 local_port, index, op, arg)); 13479 } 13480 } 13481 return BCM_E_NONE; 13482 } 13483 13484 STATIC int 13485 _bcm_td2_cosq_qcn_proxy_set(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 13486 bcm_cosq_control_t type, int arg) 13487 { 13488 int local_port; 13489 uint32 rval; 13490 13491 BCM_IF_ERROR_RETURN 13492 (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port)); 13493 13494 BCM_IF_ERROR_RETURN(READ_QCN_CNM_PRP_CTRLr(unit, local_port, &rval)); 13495 soc_reg_field_set(unit, QCN_CNM_PRP_CTRLr, &rval, ENABLEf, !!arg); 13496 soc_reg_field_set(unit, QCN_CNM_PRP_CTRLr, &rval, PRIORITY_BMAPf, 0xff); 13497 BCM_IF_ERROR_RETURN(WRITE_QCN_CNM_PRP_CTRLr(unit, local_port, rval)); 13498 return BCM_E_NONE; 13499 } 13500 13501 STATIC int 13502 _bcm_td2_cosq_qcn_proxy_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 13503 bcm_cosq_control_t type, int *arg) 13504 { 13505 int local_port; 13506 uint32 rval; 13507 13508 BCM_IF_ERROR_RETURN 13509 (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port)); 13510 13511 BCM_IF_ERROR_RETURN(READ_QCN_CNM_PRP_CTRLr(unit, local_port, &rval)); 13512 *arg = soc_reg_field_get(unit, QCN_CNM_PRP_CTRLr, rval, ENABLEf); 13513 13514 return BCM_E_NONE; 13515 } 13516 13517 STATIC int 13518 _bcm_td2_cosq_alpha_bcm_to_soc(int unit, 13519 bcm_cosq_control_drop_limit_alpha_value_t arg, 13520 soc_td2_drop_limit_alpha_value_t *val) 13521 { 13522 if (!val) { 13523 return BCM_E_PARAM; 13524 } 13525 13526 switch(arg) { 13527 case bcmCosqControlDropLimitAlpha_1_128: 13528 *val = SOC_TD2_COSQ_DROP_LIMIT_ALPHA_1_128; 13529 break; 13530 case bcmCosqControlDropLimitAlpha_1_64: 13531 *val = SOC_TD2_COSQ_DROP_LIMIT_ALPHA_1_64; 13532 break; 13533 case bcmCosqControlDropLimitAlpha_1_32: 13534 *val = SOC_TD2_COSQ_DROP_LIMIT_ALPHA_1_32; 13535 break; 13536 case bcmCosqControlDropLimitAlpha_1_16: 13537 *val = SOC_TD2_COSQ_DROP_LIMIT_ALPHA_1_16; 13538 break; 13539 case bcmCosqControlDropLimitAlpha_1_8: 13540 *val = SOC_TD2_COSQ_DROP_LIMIT_ALPHA_1_8; 13541 break; 13542 case bcmCosqControlDropLimitAlpha_1_4: 13543 *val = SOC_TD2_COSQ_DROP_LIMIT_ALPHA_1_4; 13544 break; 13545 case bcmCosqControlDropLimitAlpha_1_2: 13546 *val = SOC_TD2_COSQ_DROP_LIMIT_ALPHA_1_2; 13547 break; 13548 case bcmCosqControlDropLimitAlpha_1: 13549 *val = SOC_TD2_COSQ_DROP_LIMIT_ALPHA_1; 13550 break; 13551 case bcmCosqControlDropLimitAlpha_2: 13552 *val = SOC_TD2_COSQ_DROP_LIMIT_ALPHA_2; 13553 break; 13554 case bcmCosqControlDropLimitAlpha_4: 13555 *val = SOC_TD2_COSQ_DROP_LIMIT_ALPHA_4; 13556 break; 13557 case bcmCosqControlDropLimitAlpha_8: 13558 *val = SOC_TD2_COSQ_DROP_LIMIT_ALPHA_8; 13559 break; 13560 default: 13561 return BCM_E_PARAM; 13562 } 13563 13564 return BCM_E_NONE; 13565 } 13566 13567 STATIC int 13568 _bcm_td2_cosq_alpha_soc_to_bcm(int unit, 13569 soc_td2_drop_limit_alpha_value_t arg, 13570 bcm_cosq_control_drop_limit_alpha_value_t *val) 13571 { 13572 if (!val) { 13573 return BCM_E_PARAM; 13574 } 13575 13576 switch(arg) { 13577 case SOC_TD2_COSQ_DROP_LIMIT_ALPHA_1_128: 13578 *val = bcmCosqControlDropLimitAlpha_1_128; 13579 break; 13580 case SOC_TD2_COSQ_DROP_LIMIT_ALPHA_1_64: 13581 *val = bcmCosqControlDropLimitAlpha_1_64; 13582 break; 13583 case SOC_TD2_COSQ_DROP_LIMIT_ALPHA_1_32: 13584 *val = bcmCosqControlDropLimitAlpha_1_32; 13585 break; 13586 case SOC_TD2_COSQ_DROP_LIMIT_ALPHA_1_16: 13587 *val = bcmCosqControlDropLimitAlpha_1_16; 13588 break; 13589 case SOC_TD2_COSQ_DROP_LIMIT_ALPHA_1_8: 13590 *val = bcmCosqControlDropLimitAlpha_1_8; 13591 break; 13592 case SOC_TD2_COSQ_DROP_LIMIT_ALPHA_1_4: 13593 *val = bcmCosqControlDropLimitAlpha_1_4; 13594 break; 13595 case SOC_TD2_COSQ_DROP_LIMIT_ALPHA_1_2: 13596 *val = bcmCosqControlDropLimitAlpha_1_2; 13597 break; 13598 case SOC_TD2_COSQ_DROP_LIMIT_ALPHA_1: 13599 *val = bcmCosqControlDropLimitAlpha_1; 13600 break; 13601 case SOC_TD2_COSQ_DROP_LIMIT_ALPHA_2: 13602 *val = bcmCosqControlDropLimitAlpha_2; 13603 break; 13604 case SOC_TD2_COSQ_DROP_LIMIT_ALPHA_4: 13605 *val = bcmCosqControlDropLimitAlpha_4; 13606 break; 13607 case SOC_TD2_COSQ_DROP_LIMIT_ALPHA_8: 13608 *val = bcmCosqControlDropLimitAlpha_8; 13609 break; 13610 default: 13611 return BCM_E_PARAM; 13612 } 13613 13614 return BCM_E_NONE; 13615 } 13616 13617 STATIC int 13618 _bcm_td2_cosq_alpha_set(int unit, 13619 bcm_gport_t gport, bcm_cos_queue_t cosq, 13620 bcm_cosq_control_drop_limit_alpha_value_t arg) 13621 { 13622 bcm_port_t local_port; 13623 int startq; 13624 int midx; 13625 uint32 rval, alpha; 13626 uint32 entry[SOC_MAX_MEM_WORDS]; 13627 uint32 entry2[SOC_MAX_MEM_WORDS]; 13628 soc_mem_t mem = INVALIDm, mem2 = INVALIDm; 13629 int dynamic_thresh_mode; 13630 soc_reg_t reg = INVALIDr; 13631 int port_pg; 13632 soc_td2_drop_limit_alpha_value_t aget; 13633 static const soc_reg_t prigroup_reg[] = { 13634 THDI_PORT_PRI_GRP0r, THDI_PORT_PRI_GRP1r 13635 }; 13636 static const soc_field_t prigroup_field[] = { 13637 PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf, 13638 PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf, 13639 PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf, 13640 PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf 13641 }; 13642 13643 BCM_IF_ERROR_RETURN( 13644 _bcm_td2_cosq_alpha_bcm_to_soc(unit, arg, &aget)); 13645 alpha = (uint32)aget; 13646 13647 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 13648 BCM_IF_ERROR_RETURN 13649 (_bcm_td2_cosq_dynamic_thresh_enable_get(unit, gport, cosq, 13650 bcmCosqControlEgressUCSharedDynamicEnable, 13651 &dynamic_thresh_mode)); 13652 if (!dynamic_thresh_mode){ 13653 return BCM_E_CONFIG; 13654 } 13655 13656 BCM_IF_ERROR_RETURN 13657 (_bcm_td2_cosq_index_resolve(unit, gport, cosq, 13658 _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE, 13659 &local_port, &startq, NULL)); 13660 mem = SOC_TD2_PMEM(unit, local_port, MMU_THDU_XPIPE_CONFIG_QUEUEm, 13661 MMU_THDU_YPIPE_CONFIG_QUEUEm); 13662 13663 BCM_IF_ERROR_RETURN 13664 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 13665 soc_mem_field32_set(unit, mem, entry, 13666 Q_SHARED_ALPHA_CELLf, alpha); 13667 SOC_IF_ERROR_RETURN 13668 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 13669 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 13670 BCM_IF_ERROR_RETURN 13671 (_bcm_td2_cosq_dynamic_thresh_enable_get(unit, gport, cosq, 13672 bcmCosqControlEgressMCSharedDynamicEnable, 13673 &dynamic_thresh_mode)); 13674 if (!dynamic_thresh_mode){ 13675 return BCM_E_CONFIG; 13676 } 13677 13678 BCM_IF_ERROR_RETURN 13679 (_bcm_td2_cosq_index_resolve(unit, gport, cosq, 13680 _BCM_TD2_COSQ_INDEX_STYLE_MCAST_QUEUE, 13681 &local_port, &startq, NULL)); 13682 mem = SOC_TD2_PMEM(unit, local_port, MMU_THDM_DB_QUEUE_CONFIG_0m, 13683 MMU_THDM_DB_QUEUE_CONFIG_1m); 13684 mem2 = SOC_TD2_PMEM(unit, local_port, MMU_THDM_MCQE_QUEUE_CONFIG_0m, 13685 MMU_THDM_MCQE_QUEUE_CONFIG_1m); 13686 13687 startq -= 1480; /* MC queues comes after UC queues */ 13688 BCM_IF_ERROR_RETURN 13689 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 13690 soc_mem_field32_set(unit, mem, entry, Q_SHARED_ALPHAf, alpha); 13691 SOC_IF_ERROR_RETURN 13692 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 13693 13694 BCM_IF_ERROR_RETURN 13695 (soc_mem_read(unit, mem2, MEM_BLOCK_ALL, startq, entry2)); 13696 soc_mem_field32_set(unit, mem2, entry2, Q_SHARED_ALPHAf, alpha); 13697 SOC_IF_ERROR_RETURN 13698 (soc_mem_write(unit, mem2, MEM_BLOCK_ALL, startq, entry2)); 13699 } else { 13700 if (cosq > 15 || cosq < 0) { 13701 return BCM_E_PARAM; 13702 } 13703 13704 BCM_IF_ERROR_RETURN 13705 (_bcm_td2_cosq_dynamic_thresh_enable_get(unit, gport, cosq, 13706 bcmCosqControlIngressPortPGSharedDynamicEnable, 13707 &dynamic_thresh_mode)); 13708 if (!dynamic_thresh_mode){ 13709 return BCM_E_CONFIG; 13710 } 13711 13712 BCM_IF_ERROR_RETURN 13713 (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port)); 13714 if (local_port < 0) { 13715 return BCM_E_PORT; 13716 } 13717 13718 /* get PG for port using Port+Cos */ 13719 if (cosq < 8) { 13720 reg = prigroup_reg[0]; 13721 } else { 13722 reg = prigroup_reg[1]; 13723 } 13724 13725 SOC_IF_ERROR_RETURN 13726 (soc_reg32_get(unit, reg, local_port, 0, &rval)); 13727 port_pg = soc_reg_field_get(unit, reg, rval, prigroup_field[cosq]); 13728 mem = SOC_TD2_PMEM(unit, local_port, THDI_PORT_PG_CONFIG_Xm, 13729 THDI_PORT_PG_CONFIG_Ym); 13730 /* get index for Port-PG */ 13731 midx = SOC_TD2_MMU_PIPED_MEM_INDEX(unit, local_port, mem, port_pg); 13732 BCM_IF_ERROR_RETURN 13733 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, entry)); 13734 soc_mem_field32_set(unit, mem, entry, 13735 PG_SHARED_LIMITf, alpha); 13736 SOC_IF_ERROR_RETURN 13737 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, midx, entry)); 13738 } 13739 13740 return BCM_E_NONE; 13741 } 13742 13743 13744 STATIC int 13745 _bcm_td2_cosq_alpha_get(int unit, 13746 bcm_gport_t gport, bcm_cos_queue_t cosq, 13747 bcm_cosq_control_drop_limit_alpha_value_t *arg) 13748 { 13749 bcm_port_t local_port; 13750 int startq; 13751 int midx; 13752 uint32 rval; 13753 uint32 entry[SOC_MAX_MEM_WORDS]; 13754 soc_mem_t mem = INVALIDm; 13755 int alpha; 13756 int dynamic_thresh_mode; 13757 soc_reg_t reg = INVALIDr; 13758 int port_pg; 13759 static const soc_reg_t prigroup_reg[] = { 13760 THDI_PORT_PRI_GRP0r, THDI_PORT_PRI_GRP1r 13761 }; 13762 static const soc_field_t prigroup_field[] = { 13763 PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf, 13764 PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf, 13765 PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf, 13766 PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf 13767 }; 13768 13769 if (!arg) { 13770 return BCM_E_PARAM; 13771 } 13772 13773 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 13774 BCM_IF_ERROR_RETURN 13775 (_bcm_td2_cosq_dynamic_thresh_enable_get(unit, gport, cosq, 13776 bcmCosqControlEgressUCSharedDynamicEnable, 13777 &dynamic_thresh_mode)); 13778 if (!dynamic_thresh_mode){ 13779 return BCM_E_CONFIG; 13780 } 13781 13782 BCM_IF_ERROR_RETURN 13783 (_bcm_td2_cosq_index_resolve(unit, gport, cosq, 13784 _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE, 13785 &local_port, &startq, NULL)); 13786 mem = SOC_TD2_PMEM(unit, local_port, MMU_THDU_XPIPE_CONFIG_QUEUEm, 13787 MMU_THDU_YPIPE_CONFIG_QUEUEm); 13788 13789 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, 13790 startq, entry)); 13791 alpha = soc_mem_field32_get(unit, mem, entry, Q_SHARED_ALPHA_CELLf); 13792 13793 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 13794 BCM_IF_ERROR_RETURN 13795 (_bcm_td2_cosq_dynamic_thresh_enable_get(unit, gport, cosq, 13796 bcmCosqControlEgressMCSharedDynamicEnable, 13797 &dynamic_thresh_mode)); 13798 if (!dynamic_thresh_mode){ 13799 return BCM_E_CONFIG; 13800 } 13801 13802 BCM_IF_ERROR_RETURN 13803 (_bcm_td2_cosq_index_resolve(unit, gport, cosq, 13804 _BCM_TD2_COSQ_INDEX_STYLE_MCAST_QUEUE, 13805 &local_port, &startq, NULL)); 13806 mem = SOC_TD2_PMEM(unit, local_port, MMU_THDM_DB_QUEUE_CONFIG_0m, 13807 MMU_THDM_DB_QUEUE_CONFIG_1m); 13808 13809 startq -= 1480; /* MC queues comes after UC queues */ 13810 BCM_IF_ERROR_RETURN 13811 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 13812 alpha = soc_mem_field32_get(unit, mem, entry, Q_SHARED_ALPHAf); 13813 13814 } else { 13815 if (cosq > 15 || cosq < 0) { 13816 return BCM_E_PARAM; 13817 } 13818 13819 BCM_IF_ERROR_RETURN 13820 (_bcm_td2_cosq_dynamic_thresh_enable_get(unit, gport, cosq, 13821 bcmCosqControlIngressPortPGSharedDynamicEnable, 13822 &dynamic_thresh_mode)); 13823 if (!dynamic_thresh_mode){ 13824 return BCM_E_CONFIG; 13825 } 13826 13827 BCM_IF_ERROR_RETURN 13828 (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port)); 13829 if (local_port < 0) { 13830 return BCM_E_PORT; 13831 } 13832 13833 /* get PG for port using Port+Cos */ 13834 if (cosq < 8) { 13835 reg = prigroup_reg[0]; 13836 } else { 13837 reg = prigroup_reg[1]; 13838 } 13839 13840 SOC_IF_ERROR_RETURN 13841 (soc_reg32_get(unit, reg, local_port, 0, &rval)); 13842 port_pg = soc_reg_field_get(unit, reg, rval, prigroup_field[cosq]); 13843 mem = SOC_TD2_PMEM(unit, local_port, THDI_PORT_PG_CONFIG_Xm, 13844 THDI_PORT_PG_CONFIG_Ym); 13845 /* get index for Port-PG */ 13846 midx = SOC_TD2_MMU_PIPED_MEM_INDEX(unit, local_port, mem, port_pg); 13847 13848 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, 13849 midx, entry)); 13850 alpha = soc_mem_field32_get(unit, mem, entry, PG_SHARED_LIMITf); 13851 13852 } 13853 13854 BCM_IF_ERROR_RETURN( 13855 _bcm_td2_cosq_alpha_soc_to_bcm(unit, 13856 (soc_td2_drop_limit_alpha_value_t)alpha, arg)); 13857 13858 return BCM_E_NONE; 13859 } 13860 13861 STATIC int 13862 _bcm_td2_cosq_dynamic_thresh_enable_set(int unit, 13863 bcm_gport_t gport, bcm_cos_queue_t cosq, 13864 bcm_cosq_control_t type, int arg) 13865 { 13866 bcm_port_t local_port; 13867 int startq; 13868 int from_cos, to_cos, ci; 13869 int midx; 13870 uint32 rval; 13871 uint32 entry[SOC_MAX_MEM_WORDS]; 13872 uint32 entry2[SOC_MAX_MEM_WORDS]; 13873 soc_mem_t mem = INVALIDm, mem2 = INVALIDm; 13874 soc_reg_t reg = INVALIDr; 13875 int port_pg; 13876 static const soc_reg_t prigroup_reg[] = { 13877 THDI_PORT_PRI_GRP0r, THDI_PORT_PRI_GRP1r 13878 }; 13879 static const soc_field_t prigroup_field[] = { 13880 PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf, 13881 PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf, 13882 PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf, 13883 PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf 13884 }; 13885 13886 13887 if (type == bcmCosqControlIngressPortPGSharedDynamicEnable) { 13888 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 13889 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 13890 return BCM_E_PARAM; 13891 } 13892 13893 BCM_IF_ERROR_RETURN 13894 (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port)); 13895 if (local_port < 0) { 13896 return BCM_E_PORT; 13897 } 13898 if ((cosq < 0) || (cosq >= _TD2_NUM_INTERNAL_PRI)) { 13899 return BCM_E_PARAM; 13900 } 13901 13902 /* get PG for port using Port+Cos */ 13903 if (cosq < 8) { 13904 reg = prigroup_reg[0]; 13905 } else { 13906 reg = prigroup_reg[1]; 13907 } 13908 13909 SOC_IF_ERROR_RETURN 13910 (soc_reg32_get(unit, reg, local_port, 0, &rval)); 13911 port_pg = soc_reg_field_get(unit, reg, rval, prigroup_field[cosq]); 13912 mem = SOC_TD2_PMEM(unit, local_port, THDI_PORT_PG_CONFIG_Xm, 13913 THDI_PORT_PG_CONFIG_Ym); 13914 /* get index for Port-PG */ 13915 midx = SOC_TD2_MMU_PIPED_MEM_INDEX(unit, local_port, mem, port_pg); 13916 BCM_IF_ERROR_RETURN 13917 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, entry)); 13918 soc_mem_field32_set(unit, mem, entry, 13919 PG_SHARED_DYNAMICf, arg ? 1 : 0); 13920 /* Set default alpha value*/ 13921 if (arg) { 13922 soc_mem_field32_set(unit, mem, entry, 13923 PG_SHARED_LIMITf, bcmCosqControlDropLimitAlpha_1_128); 13924 } 13925 13926 SOC_IF_ERROR_RETURN 13927 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, midx, entry)); 13928 } else if (type == bcmCosqControlEgressUCSharedDynamicEnable) { 13929 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 13930 BCM_IF_ERROR_RETURN 13931 (_bcm_td2_cosq_index_resolve(unit, gport, cosq, 13932 _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE, 13933 &local_port, &startq, NULL)); 13934 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 13935 return BCM_E_PARAM; 13936 } else { 13937 if (cosq == BCM_COS_INVALID) { 13938 from_cos = to_cos = 0; 13939 } else { 13940 from_cos = to_cos = cosq; 13941 } 13942 13943 BCM_IF_ERROR_RETURN 13944 (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port)); 13945 if (local_port < 0) { 13946 return BCM_E_PORT; 13947 } 13948 for (ci = from_cos; ci <= to_cos; ci++) { 13949 BCM_IF_ERROR_RETURN 13950 (_bcm_td2_cosq_index_resolve(unit, local_port, ci, 13951 _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE, 13952 NULL, &startq, NULL)); 13953 13954 } 13955 } 13956 mem = SOC_TD2_PMEM(unit, local_port, MMU_THDU_XPIPE_CONFIG_QUEUEm, 13957 MMU_THDU_YPIPE_CONFIG_QUEUEm); 13958 13959 BCM_IF_ERROR_RETURN 13960 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 13961 soc_mem_field32_set(unit, mem, entry, 13962 Q_LIMIT_DYNAMIC_CELLf, arg ? 1 : 0); 13963 /* Set default alpha value*/ 13964 if (arg) { 13965 soc_mem_field32_set(unit, mem, entry, 13966 Q_SHARED_ALPHA_CELLf, bcmCosqControlDropLimitAlpha_1_128); 13967 } 13968 13969 SOC_IF_ERROR_RETURN 13970 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 13971 } else if (type == bcmCosqControlEgressMCSharedDynamicEnable) { 13972 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 13973 return BCM_E_PARAM; 13974 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 13975 BCM_IF_ERROR_RETURN 13976 (_bcm_td2_cosq_index_resolve(unit, gport, cosq, 13977 _BCM_TD2_COSQ_INDEX_STYLE_MCAST_QUEUE, 13978 &local_port, &startq, NULL)); 13979 } 13980 else { 13981 if (cosq == BCM_COS_INVALID) { 13982 from_cos = to_cos = 0; 13983 } else { 13984 from_cos = to_cos = cosq; 13985 } 13986 13987 BCM_IF_ERROR_RETURN 13988 (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port)); 13989 if (local_port < 0) { 13990 return BCM_E_PORT; 13991 } 13992 for (ci = from_cos; ci <= to_cos; ci++) { 13993 BCM_IF_ERROR_RETURN 13994 (_bcm_td2_cosq_index_resolve(unit, local_port, ci, 13995 _BCM_TD2_COSQ_INDEX_STYLE_MCAST_QUEUE, 13996 NULL, &startq, NULL)); 13997 13998 } 13999 } 14000 14001 mem = SOC_TD2_PMEM(unit, local_port, MMU_THDM_DB_QUEUE_CONFIG_0m, 14002 MMU_THDM_DB_QUEUE_CONFIG_1m); 14003 mem2 = SOC_TD2_PMEM(unit, local_port, MMU_THDM_MCQE_QUEUE_CONFIG_0m, 14004 MMU_THDM_MCQE_QUEUE_CONFIG_1m); 14005 14006 startq -= 1480; /* MC queues comes after UC queues */ 14007 BCM_IF_ERROR_RETURN 14008 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 14009 soc_mem_field32_set(unit, mem, entry, Q_LIMIT_DYNAMICf, arg ? 1 : 0); 14010 /* Set default alpha value*/ 14011 if (arg) { 14012 soc_mem_field32_set(unit, mem, entry, 14013 Q_SHARED_ALPHAf, bcmCosqControlDropLimitAlpha_1_128); 14014 } 14015 14016 SOC_IF_ERROR_RETURN 14017 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 14018 14019 BCM_IF_ERROR_RETURN 14020 (soc_mem_read(unit, mem2, MEM_BLOCK_ALL, startq, entry2)); 14021 soc_mem_field32_set(unit, mem2, entry2, Q_LIMIT_DYNAMICf, arg ? 1 : 0); 14022 /* Set default alpha value*/ 14023 if (arg) { 14024 soc_mem_field32_set(unit, mem2, entry2, 14025 Q_SHARED_ALPHAf, bcmCosqControlDropLimitAlpha_1_128); 14026 } 14027 14028 SOC_IF_ERROR_RETURN 14029 (soc_mem_write(unit, mem2, MEM_BLOCK_ALL, startq, entry2)); 14030 14031 } else { 14032 return BCM_E_PARAM; 14033 } 14034 14035 return BCM_E_NONE; 14036 } 14037 14038 STATIC int 14039 _bcm_td2_cosq_dynamic_thresh_enable_get(int unit, 14040 bcm_gport_t gport, bcm_cos_queue_t cosq, 14041 bcm_cosq_control_t type, int *arg) 14042 { 14043 bcm_port_t local_port; 14044 int startq; 14045 int from_cos, to_cos, ci; 14046 int midx; 14047 uint32 rval; 14048 uint32 entry[SOC_MAX_MEM_WORDS]; 14049 soc_mem_t mem = INVALIDm; 14050 soc_reg_t reg = INVALIDr; 14051 int port_pg; 14052 static const soc_reg_t prigroup_reg[] = { 14053 THDI_PORT_PRI_GRP0r, THDI_PORT_PRI_GRP1r 14054 }; 14055 static const soc_field_t prigroup_field[] = { 14056 PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf, 14057 PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf, 14058 PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf, 14059 PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf 14060 }; 14061 14062 if (!arg) { 14063 return BCM_E_PARAM; 14064 } 14065 14066 if (type == bcmCosqControlIngressPortPGSharedDynamicEnable) { 14067 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 14068 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 14069 return BCM_E_PARAM; 14070 } 14071 14072 BCM_IF_ERROR_RETURN 14073 (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port)); 14074 if (local_port < 0) { 14075 return BCM_E_PORT; 14076 } 14077 if ((cosq < 0) || (cosq >= _TD2_NUM_INTERNAL_PRI)) { 14078 return BCM_E_PARAM; 14079 } 14080 14081 /* get PG for port using Port+Cos */ 14082 if (cosq < 8) { 14083 reg = prigroup_reg[0]; 14084 } else { 14085 reg = prigroup_reg[1]; 14086 } 14087 14088 SOC_IF_ERROR_RETURN 14089 (soc_reg32_get(unit, reg, local_port, 0, &rval)); 14090 port_pg = soc_reg_field_get(unit, reg, rval, prigroup_field[cosq]); 14091 mem = SOC_TD2_PMEM(unit, local_port, THDI_PORT_PG_CONFIG_Xm, 14092 THDI_PORT_PG_CONFIG_Ym); 14093 /* get index for Port-PG */ 14094 midx = SOC_TD2_MMU_PIPED_MEM_INDEX(unit, local_port, mem, port_pg); 14095 14096 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, 14097 midx, entry)); 14098 *arg = soc_mem_field32_get(unit, mem, entry, PG_SHARED_DYNAMICf); 14099 14100 } else if (type == bcmCosqControlEgressUCSharedDynamicEnable) { 14101 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 14102 BCM_IF_ERROR_RETURN 14103 (_bcm_td2_cosq_index_resolve(unit, gport, cosq, 14104 _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE, 14105 &local_port, &startq, NULL)); 14106 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 14107 return BCM_E_PARAM; 14108 } else { 14109 if (cosq == BCM_COS_INVALID) { 14110 from_cos = to_cos = 0; 14111 } else { 14112 from_cos = to_cos = cosq; 14113 } 14114 14115 BCM_IF_ERROR_RETURN 14116 (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port)); 14117 if (local_port < 0) { 14118 return BCM_E_PORT; 14119 } 14120 for (ci = from_cos; ci <= to_cos; ci++) { 14121 BCM_IF_ERROR_RETURN 14122 (_bcm_td2_cosq_index_resolve(unit, local_port, ci, 14123 _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE, 14124 NULL, &startq, NULL)); 14125 } 14126 } 14127 mem = SOC_TD2_PMEM(unit, local_port, MMU_THDU_XPIPE_CONFIG_QUEUEm, 14128 MMU_THDU_YPIPE_CONFIG_QUEUEm); 14129 14130 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, 14131 startq, entry)); 14132 *arg = soc_mem_field32_get(unit, mem, entry, Q_LIMIT_DYNAMIC_CELLf); 14133 } else if (type == bcmCosqControlEgressMCSharedDynamicEnable) { 14134 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 14135 return BCM_E_PARAM; 14136 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 14137 BCM_IF_ERROR_RETURN 14138 (_bcm_td2_cosq_index_resolve(unit, gport, cosq, 14139 _BCM_TD2_COSQ_INDEX_STYLE_MCAST_QUEUE, 14140 &local_port, &startq, NULL)); 14141 } 14142 else { 14143 if (cosq == BCM_COS_INVALID) { 14144 from_cos = to_cos = 0; 14145 } else { 14146 from_cos = to_cos = cosq; 14147 } 14148 14149 BCM_IF_ERROR_RETURN 14150 (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port)); 14151 if (local_port < 0) { 14152 return BCM_E_PORT; 14153 } 14154 for (ci = from_cos; ci <= to_cos; ci++) { 14155 BCM_IF_ERROR_RETURN 14156 (_bcm_td2_cosq_index_resolve(unit, local_port, ci, 14157 _BCM_TD2_COSQ_INDEX_STYLE_MCAST_QUEUE, 14158 NULL, &startq, NULL)); 14159 } 14160 } 14161 mem = SOC_TD2_PMEM(unit, local_port, MMU_THDM_DB_QUEUE_CONFIG_0m, 14162 MMU_THDM_DB_QUEUE_CONFIG_1m); 14163 14164 startq -= 1480; /* MC queues comes after UC queues */ 14165 BCM_IF_ERROR_RETURN 14166 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 14167 *arg = soc_mem_field32_get(unit, mem, entry, Q_LIMIT_DYNAMICf); 14168 } else { 14169 return BCM_E_PARAM; 14170 } 14171 14172 return BCM_E_NONE; 14173 } 14174 14175 STATIC int 14176 _bcm_td2_cosq_egr_queue_limit_enable_set(int unit, bcm_gport_t gport, 14177 bcm_cos_queue_t cosq, 14178 bcm_cosq_control_t type, 14179 int arg) 14180 { 14181 bcm_port_t local_port; 14182 int startq; 14183 uint32 entry[SOC_MAX_MEM_WORDS]; 14184 soc_mem_t mem = INVALIDm; 14185 int enable; 14186 soc_field_t field_name = INVALIDf; 14187 14188 if (arg < 0) { 14189 return BCM_E_PARAM; 14190 } 14191 14192 arg = arg ? 1 : 0; 14193 14194 if ((type == bcmCosqControlEgressUCQueueLimitEnable) || 14195 (type == bcmCosqControlEgressUCQueueColorLimitEnable)) { 14196 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 14197 BCM_IF_ERROR_RETURN 14198 (_bcm_td2_cosq_index_resolve(unit, gport, cosq, 14199 _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE, 14200 &local_port, &startq, NULL)); 14201 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 14202 return BCM_E_PARAM; 14203 } else { 14204 if (cosq < 0) { 14205 return BCM_E_PARAM; 14206 } 14207 BCM_IF_ERROR_RETURN 14208 (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port)); 14209 if (local_port < 0) { 14210 return BCM_E_PORT; 14211 } 14212 BCM_IF_ERROR_RETURN 14213 (_bcm_td2_cosq_index_resolve 14214 (unit, local_port, cosq, _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE, 14215 NULL, &startq, NULL)); 14216 } 14217 14218 mem = SOC_TD2_PMEM(unit, local_port, MMU_THDU_XPIPE_Q_TO_QGRP_MAPm, 14219 MMU_THDU_YPIPE_Q_TO_QGRP_MAPm); 14220 if (type == bcmCosqControlEgressUCQueueLimitEnable) { 14221 field_name = Q_LIMIT_ENABLEf; 14222 } else if (type == bcmCosqControlEgressUCQueueColorLimitEnable) { 14223 field_name = Q_COLOR_ENABLE_CELLf; 14224 } 14225 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 14226 enable = soc_mem_field32_get(unit, mem, entry, field_name); 14227 if (enable != arg) { 14228 soc_mem_field32_set(unit, mem, entry, field_name, arg); 14229 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 14230 } 14231 }else if ((type == bcmCosqControlEgressMCQueueLimitEnable) || 14232 (type == bcmCosqControlEgressMCQueueColorLimitEnable)) { 14233 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 14234 return BCM_E_PARAM; 14235 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 14236 BCM_IF_ERROR_RETURN 14237 (_bcm_td2_cosq_index_resolve(unit, gport, cosq, 14238 _BCM_TD2_COSQ_INDEX_STYLE_MCAST_QUEUE, 14239 &local_port, &startq, NULL)); 14240 } else { 14241 if (cosq < 0) { 14242 return BCM_E_PARAM; 14243 } 14244 BCM_IF_ERROR_RETURN 14245 (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port)); 14246 if (local_port < 0) { 14247 return BCM_E_PORT; 14248 } 14249 BCM_IF_ERROR_RETURN 14250 (_bcm_td2_cosq_index_resolve(unit, local_port, cosq, 14251 _BCM_TD2_COSQ_INDEX_STYLE_MCAST_QUEUE, 14252 NULL, &startq, NULL)); 14253 } 14254 startq -= 1480; /* MC queues comes after UC queues */ 14255 14256 mem = SOC_TD2_PMEM(unit, local_port, MMU_THDM_MCQE_QUEUE_CONFIG_0m, 14257 MMU_THDM_MCQE_QUEUE_CONFIG_1m); 14258 if (type == bcmCosqControlEgressMCQueueLimitEnable) { 14259 field_name = Q_LIMIT_ENABLEf; 14260 } else if (type == bcmCosqControlEgressMCQueueColorLimitEnable) { 14261 field_name = Q_COLOR_LIMIT_ENABLEf; 14262 } 14263 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 14264 enable = soc_mem_field32_get(unit, mem, entry, field_name); 14265 if (enable != arg) { 14266 soc_mem_field32_set(unit, mem, entry, field_name, arg); 14267 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 14268 } 14269 14270 mem = SOC_TD2_PMEM(unit, local_port, MMU_THDM_DB_QUEUE_CONFIG_0m, 14271 MMU_THDM_DB_QUEUE_CONFIG_1m); 14272 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 14273 enable = soc_mem_field32_get(unit, mem, entry, field_name); 14274 if (enable != arg) { 14275 soc_mem_field32_set(unit, mem, entry, field_name, arg); 14276 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 14277 } 14278 } else { 14279 return BCM_E_PARAM; 14280 } 14281 14282 return BCM_E_NONE; 14283 } 14284 14285 STATIC int 14286 _bcm_td2_cosq_egr_queue_limit_enable_get(int unit, bcm_gport_t gport, 14287 bcm_cos_queue_t cosq, 14288 bcm_cosq_control_t type, 14289 int *arg) 14290 { 14291 bcm_port_t local_port; 14292 int startq; 14293 uint32 entry[SOC_MAX_MEM_WORDS]; 14294 soc_mem_t mem = INVALIDm; 14295 soc_field_t field_name = INVALIDf; 14296 14297 if ((type == bcmCosqControlEgressUCQueueLimitEnable) || 14298 (type == bcmCosqControlEgressUCQueueColorLimitEnable)) { 14299 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 14300 BCM_IF_ERROR_RETURN 14301 (_bcm_td2_cosq_index_resolve(unit, gport, cosq, 14302 _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE, 14303 &local_port, &startq, NULL)); 14304 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 14305 return BCM_E_PARAM; 14306 } else { 14307 if (cosq < 0) { 14308 return BCM_E_PARAM; 14309 } 14310 BCM_IF_ERROR_RETURN 14311 (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port)); 14312 if (local_port < 0) { 14313 return BCM_E_PORT; 14314 } 14315 BCM_IF_ERROR_RETURN 14316 (_bcm_td2_cosq_index_resolve 14317 (unit, local_port, cosq, _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE, 14318 NULL, &startq, NULL)); 14319 } 14320 14321 mem = SOC_TD2_PMEM(unit, local_port, MMU_THDU_XPIPE_Q_TO_QGRP_MAPm, 14322 MMU_THDU_YPIPE_Q_TO_QGRP_MAPm); 14323 if (type == bcmCosqControlEgressUCQueueLimitEnable) { 14324 field_name = Q_LIMIT_ENABLEf; 14325 } else if (type == bcmCosqControlEgressUCQueueColorLimitEnable) { 14326 field_name = Q_COLOR_ENABLE_CELLf; 14327 } 14328 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 14329 *arg = soc_mem_field32_get(unit, mem, entry, field_name); 14330 }else if ((type == bcmCosqControlEgressMCQueueLimitEnable) || 14331 (type == bcmCosqControlEgressMCQueueColorLimitEnable)) { 14332 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 14333 return BCM_E_PARAM; 14334 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 14335 BCM_IF_ERROR_RETURN 14336 (_bcm_td2_cosq_index_resolve(unit, gport, cosq, 14337 _BCM_TD2_COSQ_INDEX_STYLE_MCAST_QUEUE, 14338 &local_port, &startq, NULL)); 14339 } else { 14340 if (cosq < 0) { 14341 return BCM_E_PARAM; 14342 } 14343 BCM_IF_ERROR_RETURN 14344 (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port)); 14345 if (local_port < 0) { 14346 return BCM_E_PORT; 14347 } 14348 BCM_IF_ERROR_RETURN 14349 (_bcm_td2_cosq_index_resolve 14350 (unit, local_port, cosq, _BCM_TD2_COSQ_INDEX_STYLE_MCAST_QUEUE, 14351 NULL, &startq, NULL)); 14352 } 14353 mem = SOC_TD2_PMEM(unit, local_port, MMU_THDM_MCQE_QUEUE_CONFIG_0m, 14354 MMU_THDM_MCQE_QUEUE_CONFIG_1m); 14355 if (type == bcmCosqControlEgressMCQueueLimitEnable) { 14356 field_name = Q_LIMIT_ENABLEf; 14357 } else if (type == bcmCosqControlEgressMCQueueColorLimitEnable) { 14358 field_name = Q_COLOR_LIMIT_ENABLEf; 14359 } 14360 startq -= 1480; /* MC queues comes after UC queues */ 14361 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 14362 *arg = soc_mem_field32_get(unit, mem, entry, field_name); 14363 } else { 14364 return BCM_E_PARAM; 14365 } 14366 14367 return BCM_E_NONE; 14368 } 14369 14370 STATIC int 14371 _bcm_td2_cosq_qgroup_limit_enable_set(int unit, bcm_gport_t gport, 14372 bcm_cos_queue_t cosq, 14373 bcm_cosq_control_t type, 14374 int arg) 14375 { 14376 bcm_port_t local_port; 14377 int startq; 14378 uint32 entry[SOC_MAX_MEM_WORDS], valid; 14379 soc_mem_t mem = INVALIDm; 14380 soc_field_t field = INVALIDf; 14381 14382 if (arg < 0) { 14383 return BCM_E_PARAM; 14384 } 14385 14386 arg = arg ? 1 : 0; 14387 14388 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 14389 BCM_IF_ERROR_RETURN 14390 (_bcm_td2_cosq_index_resolve(unit, gport, cosq, 14391 _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE, 14392 &local_port, &startq, NULL)); 14393 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 14394 return BCM_E_PARAM; 14395 } else { 14396 if (cosq < -1) { 14397 return BCM_E_PARAM; 14398 } 14399 BCM_IF_ERROR_RETURN 14400 (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port)); 14401 if (local_port < 0) { 14402 return BCM_E_PORT; 14403 } 14404 BCM_IF_ERROR_RETURN 14405 (_bcm_td2_cosq_index_resolve(unit, local_port, cosq, 14406 _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE, 14407 NULL, &startq, NULL)); 14408 } 14409 14410 mem = SOC_TD2_PMEM(unit, local_port, MMU_THDU_XPIPE_Q_TO_QGRP_MAPm, 14411 MMU_THDU_YPIPE_Q_TO_QGRP_MAPm); 14412 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 14413 valid = soc_mem_field32_get(unit, mem, entry, QGROUP_VALIDf); 14414 if (!valid) { 14415 LOG_INFO(BSL_LS_BCM_COSQ, 14416 (BSL_META_U(unit, 14417 "UCQ doesn't associate with a queue group!\n"))); 14418 return BCM_E_UNAVAIL; 14419 } 14420 14421 if (type == bcmCosqControlEgressUCQueueGroupMinEnable) { 14422 field = USE_QGROUP_MINf; 14423 } else if (type == bcmCosqControlEgressUCQueueGroupSharedLimitEnable) { 14424 field = QGROUP_LIMIT_ENABLEf; 14425 } else if (type == bcmCosqControlEgressUCQueueGroupSharedDynamicEnable) { 14426 startq = soc_mem_field32_get(unit, mem, entry, QGROUPf); 14427 14428 mem = SOC_TD2_PMEM(unit, local_port, MMU_THDU_XPIPE_CONFIG_QGROUPm, 14429 MMU_THDU_YPIPE_CONFIG_QGROUPm); 14430 field = Q_LIMIT_DYNAMIC_CELLf; 14431 } else { 14432 return BCM_E_PARAM; 14433 } 14434 14435 if ((mem != INVALIDm) && (field != INVALIDf)) { 14436 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 14437 soc_mem_field32_set(unit, mem, entry, field, arg); 14438 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 14439 } 14440 14441 return BCM_E_NONE; 14442 } 14443 14444 STATIC int 14445 _bcm_td2_cosq_qgroup_limit_enable_get(int unit, bcm_gport_t gport, 14446 bcm_cos_queue_t cosq, 14447 bcm_cosq_control_t type, 14448 int *arg) 14449 { 14450 bcm_port_t local_port; 14451 int startq; 14452 uint32 entry[SOC_MAX_MEM_WORDS], valid; 14453 soc_mem_t mem = INVALIDm; 14454 soc_field_t field = INVALIDf; 14455 14456 if (!arg) { 14457 return BCM_E_PARAM; 14458 } 14459 14460 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 14461 BCM_IF_ERROR_RETURN 14462 (_bcm_td2_cosq_index_resolve(unit, gport, cosq, 14463 _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE, 14464 &local_port, &startq, NULL)); 14465 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 14466 return BCM_E_PARAM; 14467 } else { 14468 if (cosq < -1) { 14469 return BCM_E_PARAM; 14470 } 14471 BCM_IF_ERROR_RETURN 14472 (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port)); 14473 if (local_port < 0) { 14474 return BCM_E_PORT; 14475 } 14476 BCM_IF_ERROR_RETURN 14477 (_bcm_td2_cosq_index_resolve(unit, local_port, cosq, 14478 _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE, 14479 NULL, &startq, NULL)); 14480 } 14481 14482 mem = SOC_TD2_PMEM(unit, local_port, MMU_THDU_XPIPE_Q_TO_QGRP_MAPm, 14483 MMU_THDU_YPIPE_Q_TO_QGRP_MAPm); 14484 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 14485 valid = soc_mem_field32_get(unit, mem, entry, QGROUP_VALIDf); 14486 if (!valid) { 14487 LOG_INFO(BSL_LS_BCM_COSQ, 14488 (BSL_META_U(unit, 14489 "UCQ doesn't associate with a queue group!\n"))); 14490 return BCM_E_UNAVAIL; 14491 } 14492 14493 if (type == bcmCosqControlEgressUCQueueGroupMinEnable) { 14494 field = USE_QGROUP_MINf; 14495 } else if (type == bcmCosqControlEgressUCQueueGroupSharedLimitEnable) { 14496 field = QGROUP_LIMIT_ENABLEf; 14497 } else if (type == bcmCosqControlEgressUCQueueGroupSharedDynamicEnable) { 14498 startq = soc_mem_field32_get(unit, mem, entry, QGROUPf); 14499 14500 mem = SOC_TD2_PMEM(unit, local_port, MMU_THDU_XPIPE_CONFIG_QGROUPm, 14501 MMU_THDU_YPIPE_CONFIG_QGROUPm); 14502 field = Q_LIMIT_DYNAMIC_CELLf; 14503 } else { 14504 return BCM_E_PARAM; 14505 } 14506 14507 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 14508 *arg = soc_mem_field32_get(unit, mem, entry, field); 14509 14510 return BCM_E_NONE; 14511 } 14512 14513 STATIC int 14514 _bcm_td2_cosq_qgroup_limit_set(int unit, bcm_gport_t gport, 14515 bcm_cos_queue_t cosq, 14516 bcm_cosq_control_t type, 14517 int arg) 14518 { 14519 bcm_port_t local_port; 14520 int startq, granularity = 1; 14521 int cur_val, rv, post_update; 14522 int delta = 0; /* In Cells */ 14523 uint32 entry[SOC_MAX_MEM_WORDS], valid; 14524 uint32 shared_size, spid, max_val, rval = 0; 14525 soc_mem_t mem = INVALIDm; 14526 soc_field_t fld_limit = INVALIDf; 14527 14528 if (arg < 0) { 14529 return BCM_E_PARAM; 14530 } 14531 14532 arg /= _BCM_TD2_BYTES_PER_CELL; 14533 14534 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 14535 BCM_IF_ERROR_RETURN 14536 (_bcm_td2_cosq_index_resolve(unit, gport, cosq, 14537 _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE, 14538 &local_port, &startq, NULL)); 14539 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 14540 return BCM_E_PARAM; 14541 } else { 14542 if (cosq < -1) { 14543 return BCM_E_PARAM; 14544 } 14545 BCM_IF_ERROR_RETURN 14546 (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port)); 14547 if (local_port < 0) { 14548 return BCM_E_PORT; 14549 } 14550 BCM_IF_ERROR_RETURN 14551 (_bcm_td2_cosq_index_resolve(unit, local_port, cosq, 14552 _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE, 14553 NULL, &startq, NULL)); 14554 } 14555 14556 mem = SOC_TD2_PMEM(unit, local_port, MMU_THDU_XPIPE_Q_TO_QGRP_MAPm, 14557 MMU_THDU_YPIPE_Q_TO_QGRP_MAPm); 14558 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 14559 spid = soc_mem_field32_get(unit, mem, entry, Q_SPIDf); 14560 valid = soc_mem_field32_get(unit, mem, entry, QGROUP_VALIDf); 14561 if (!valid) { 14562 LOG_INFO(BSL_LS_BCM_COSQ, 14563 (BSL_META_U(unit, 14564 "UCQ doesn't associate with a queue group!\n"))); 14565 return BCM_E_UNAVAIL; 14566 } 14567 14568 startq = soc_mem_field32_get(unit, mem, entry, QGROUPf); 14569 14570 mem = SOC_TD2_PMEM(unit, local_port, MMU_THDU_XPIPE_CONFIG_QGROUPm, 14571 MMU_THDU_YPIPE_CONFIG_QGROUPm); 14572 if (type == bcmCosqControlEgressUCQueueGroupMinLimitBytes) { 14573 fld_limit = Q_MIN_LIMIT_CELLf; 14574 granularity = 1; 14575 } else if (type == bcmCosqControlEgressUCQueueGroupSharedLimitBytes) { 14576 fld_limit = Q_SHARED_LIMIT_CELLf; 14577 granularity = 1; 14578 } else { 14579 return BCM_E_PARAM; 14580 } 14581 14582 /* Recalculate Shared Values if Min Changed */ 14583 SOC_IF_ERROR_RETURN(READ_MMU_THDM_DB_POOL_SHARED_LIMITr(unit, spid, &rval)); 14584 shared_size = soc_reg_field_get(unit, MMU_THDM_DB_POOL_SHARED_LIMITr, 14585 rval, SHARED_LIMITf); 14586 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 14587 cur_val = soc_mem_field32_get(unit, mem, entry, fld_limit); 14588 14589 if ((arg / granularity) > cur_val) { 14590 /* New Min Val > Cur Min Val 14591 * So reduce the Shared values first and then 14592 * Increase the Min Value for given resource 14593 */ 14594 post_update = 0; 14595 } else if ((arg / granularity) < cur_val) { 14596 /* New Min Val < Cur Min Val 14597 * So reduce the Min values first and then 14598 * Increase Shared values everywhere 14599 */ 14600 post_update = 1; 14601 } else { 14602 return BCM_E_NONE; 14603 } 14604 14605 if (!post_update && 14606 (type == bcmCosqControlEgressUCQueueGroupMinLimitBytes)) { 14607 delta = ((arg / granularity) - cur_val) * granularity; 14608 if (delta > shared_size) { 14609 return BCM_E_RESOURCE; 14610 } 14611 rv = soc_td2_mmu_config_res_limits_update(unit, spid, 14612 shared_size - delta, 1); 14613 if (rv < 0) { 14614 return rv; 14615 } 14616 } 14617 14618 /* Check for min/max values */ 14619 max_val = (1 << soc_mem_field_length(unit, mem, fld_limit)) - 1; 14620 if ((arg < 0) || ((arg/granularity) > max_val)) { 14621 return BCM_E_PARAM; 14622 } else { 14623 /* Get the latest entry data and update. */ 14624 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 14625 soc_mem_field32_set(unit, mem, entry, fld_limit, (arg/granularity)); 14626 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 14627 } 14628 14629 if (post_update && 14630 (type == bcmCosqControlEgressUCQueueGroupMinLimitBytes)) { 14631 delta = (cur_val - (arg / granularity)) * granularity; 14632 rv = soc_td2_mmu_config_res_limits_update(unit, spid, 14633 shared_size + delta, 0); 14634 if (rv < 0) { 14635 return rv; 14636 } 14637 } 14638 14639 return BCM_E_NONE; 14640 } 14641 14642 STATIC int 14643 _bcm_td2_cosq_qgroup_limit_get(int unit, bcm_gport_t gport, 14644 bcm_cos_queue_t cosq, 14645 bcm_cosq_control_t type, 14646 int *arg) 14647 { 14648 bcm_port_t local_port; 14649 int startq, granularity = 1; 14650 uint32 entry[SOC_MAX_MEM_WORDS], valid; 14651 soc_mem_t mem = INVALIDm; 14652 soc_field_t fld_limit = INVALIDf; 14653 14654 if (!arg) { 14655 return BCM_E_PARAM; 14656 } 14657 14658 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 14659 BCM_IF_ERROR_RETURN 14660 (_bcm_td2_cosq_index_resolve(unit, gport, cosq, 14661 _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE, 14662 &local_port, &startq, NULL)); 14663 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 14664 return BCM_E_PARAM; 14665 } else { 14666 if (cosq < -1) { 14667 return BCM_E_PARAM; 14668 } 14669 BCM_IF_ERROR_RETURN 14670 (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port)); 14671 if (local_port < 0) { 14672 return BCM_E_PORT; 14673 } 14674 BCM_IF_ERROR_RETURN 14675 (_bcm_td2_cosq_index_resolve(unit, local_port, cosq, 14676 _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE, 14677 NULL, &startq, NULL)); 14678 } 14679 14680 mem = SOC_TD2_PMEM(unit, local_port, MMU_THDU_XPIPE_Q_TO_QGRP_MAPm, 14681 MMU_THDU_YPIPE_Q_TO_QGRP_MAPm); 14682 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 14683 valid = soc_mem_field32_get(unit, mem, entry, QGROUP_VALIDf); 14684 if (!valid) { 14685 LOG_INFO(BSL_LS_BCM_COSQ, 14686 (BSL_META_U(unit, 14687 "UCQ doesn't associate with a queue group!\n"))); 14688 return BCM_E_UNAVAIL; 14689 } 14690 14691 startq = soc_mem_field32_get(unit, mem, entry, QGROUPf); 14692 14693 mem = SOC_TD2_PMEM(unit, local_port, MMU_THDU_XPIPE_CONFIG_QGROUPm, 14694 MMU_THDU_YPIPE_CONFIG_QGROUPm); 14695 if (type == bcmCosqControlEgressUCQueueGroupMinLimitBytes) { 14696 fld_limit = Q_MIN_LIMIT_CELLf; 14697 granularity = 1; 14698 } else if (type == bcmCosqControlEgressUCQueueGroupSharedLimitBytes) { 14699 fld_limit = Q_SHARED_LIMIT_CELLf; 14700 granularity = 1; 14701 } else { 14702 return BCM_E_PARAM; 14703 } 14704 14705 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 14706 *arg = soc_mem_field32_get(unit, mem, entry, fld_limit); 14707 *arg = (*arg) * granularity * _BCM_TD2_BYTES_PER_CELL; 14708 14709 return BCM_E_NONE; 14710 } 14711 14712 STATIC int 14713 _bcm_td2_cosq_qgroup_alpha_set(int unit, 14714 bcm_gport_t gport, bcm_cos_queue_t cosq, 14715 bcm_cosq_control_drop_limit_alpha_value_t arg) 14716 { 14717 bcm_port_t local_port; 14718 int startq; 14719 uint32 entry[SOC_MAX_MEM_WORDS], valid, alpha; 14720 uint32 dyn_mode; 14721 soc_mem_t mem = INVALIDm; 14722 soc_td2_drop_limit_alpha_value_t aget; 14723 14724 BCM_IF_ERROR_RETURN( 14725 _bcm_td2_cosq_alpha_bcm_to_soc(unit, arg, &aget)); 14726 alpha = (uint32)aget; 14727 14728 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 14729 BCM_IF_ERROR_RETURN 14730 (_bcm_td2_cosq_index_resolve(unit, gport, cosq, 14731 _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE, 14732 &local_port, &startq, NULL)); 14733 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 14734 return BCM_E_PARAM; 14735 } else { 14736 if (cosq < -1) { 14737 return BCM_E_PARAM; 14738 } 14739 BCM_IF_ERROR_RETURN 14740 (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port)); 14741 if (local_port < 0) { 14742 return BCM_E_PORT; 14743 } 14744 BCM_IF_ERROR_RETURN 14745 (_bcm_td2_cosq_index_resolve(unit, local_port, cosq, 14746 _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE, 14747 NULL, &startq, NULL)); 14748 } 14749 14750 mem = SOC_TD2_PMEM(unit, local_port, MMU_THDU_XPIPE_Q_TO_QGRP_MAPm, 14751 MMU_THDU_YPIPE_Q_TO_QGRP_MAPm); 14752 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 14753 valid = soc_mem_field32_get(unit, mem, entry, QGROUP_VALIDf); 14754 if (!valid) { 14755 LOG_INFO(BSL_LS_BCM_COSQ, 14756 (BSL_META_U(unit, 14757 "UCQ doesn't associate with a queue group!\n"))); 14758 return BCM_E_UNAVAIL; 14759 } 14760 14761 startq = soc_mem_field32_get(unit, mem, entry, QGROUPf); 14762 mem = SOC_TD2_PMEM(unit, local_port, MMU_THDU_XPIPE_CONFIG_QGROUPm, 14763 MMU_THDU_YPIPE_CONFIG_QGROUPm); 14764 14765 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 14766 dyn_mode = soc_mem_field32_get(unit, mem, entry, Q_LIMIT_DYNAMIC_CELLf); 14767 if (!dyn_mode){ 14768 return BCM_E_CONFIG; 14769 } 14770 soc_mem_field32_set(unit, mem, entry, Q_SHARED_ALPHA_CELLf, alpha); 14771 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 14772 14773 return BCM_E_NONE; 14774 } 14775 14776 STATIC int 14777 _bcm_td2_cosq_qgroup_alpha_get(int unit, 14778 bcm_gport_t gport, bcm_cos_queue_t cosq, 14779 bcm_cosq_control_drop_limit_alpha_value_t *arg) 14780 { 14781 bcm_port_t local_port; 14782 int startq; 14783 uint32 entry[SOC_MAX_MEM_WORDS], valid, alpha; 14784 uint32 dyn_mode; 14785 soc_mem_t mem = INVALIDm; 14786 14787 if (!arg) { 14788 return BCM_E_PARAM; 14789 } 14790 14791 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 14792 BCM_IF_ERROR_RETURN 14793 (_bcm_td2_cosq_index_resolve(unit, gport, cosq, 14794 _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE, 14795 &local_port, &startq, NULL)); 14796 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 14797 return BCM_E_PARAM; 14798 } else { 14799 if (cosq < -1) { 14800 return BCM_E_PARAM; 14801 } 14802 BCM_IF_ERROR_RETURN 14803 (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port)); 14804 if (local_port < 0) { 14805 return BCM_E_PORT; 14806 } 14807 BCM_IF_ERROR_RETURN 14808 (_bcm_td2_cosq_index_resolve(unit, local_port, cosq, 14809 _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE, 14810 NULL, &startq, NULL)); 14811 } 14812 14813 mem = SOC_TD2_PMEM(unit, local_port, MMU_THDU_XPIPE_Q_TO_QGRP_MAPm, 14814 MMU_THDU_YPIPE_Q_TO_QGRP_MAPm); 14815 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 14816 valid = soc_mem_field32_get(unit, mem, entry, QGROUP_VALIDf); 14817 if (!valid) { 14818 LOG_INFO(BSL_LS_BCM_COSQ, 14819 (BSL_META_U(unit, 14820 "UCQ doesn't associate with a queue group!\n"))); 14821 return BCM_E_UNAVAIL; 14822 } 14823 14824 startq = soc_mem_field32_get(unit, mem, entry, QGROUPf); 14825 mem = SOC_TD2_PMEM(unit, local_port, MMU_THDU_XPIPE_CONFIG_QGROUPm, 14826 MMU_THDU_YPIPE_CONFIG_QGROUPm); 14827 14828 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 14829 dyn_mode = soc_mem_field32_get(unit, mem, entry, Q_LIMIT_DYNAMIC_CELLf); 14830 if (!dyn_mode){ 14831 return BCM_E_CONFIG; 14832 } 14833 alpha = soc_mem_field32_get(unit, mem, entry, Q_SHARED_ALPHA_CELLf); 14834 14835 BCM_IF_ERROR_RETURN( 14836 _bcm_td2_cosq_alpha_soc_to_bcm(unit, 14837 (soc_td2_drop_limit_alpha_value_t)alpha, arg)); 14838 14839 return BCM_E_NONE; 14840 } 14841 14842 int 14843 bcm_td2_cosq_priority_mapping_get_all(int unit, bcm_gport_t gport, int index, 14844 bcm_cosq_priority_mapping_t type, 14845 int pri_max, int *pri_array, 14846 int *pri_count) 14847 { 14848 bcm_port_t port; 14849 int i, pg, sp, count = 0; 14850 14851 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_localport_resolve(unit, gport, &port)); 14852 if (!SOC_PORT_VALID(unit, port)) { 14853 return BCM_E_PORT; 14854 } 14855 14856 switch (type) { 14857 case bcmCosqPriorityGroup: 14858 if ((index < TD2_PRIOROTY_GROUP_ID_MIN) || 14859 (index > TD2_PRIOROTY_GROUP_ID_MAX)) { 14860 return BCM_E_PARAM; 14861 } 14862 for (i = 0; i < _TD2_NUM_INTERNAL_PRI; i++) { 14863 BCM_IF_ERROR_RETURN 14864 (bcm_td2_port_priority_group_mapping_get(unit, gport, 14865 i, &pg)); 14866 if (pg == index) { 14867 if (pri_max != 0 && pri_array != NULL) { 14868 if (count < pri_max) { 14869 pri_array[count] = i; 14870 } 14871 } 14872 count++; 14873 } 14874 } 14875 break; 14876 case bcmCosqIngressPool: 14877 if ((index < 0) || (index >= _TD2_NUM_SERVICE_POOL)) { 14878 return BCM_E_PARAM; 14879 } 14880 for (i = 0; i < _TD2_NUM_INTERNAL_PRI; i++) { 14881 BCM_IF_ERROR_RETURN 14882 (bcm_td2_port_priority_group_mapping_get(unit, gport, 14883 i, &pg)); 14884 BCM_IF_ERROR_RETURN 14885 (_bcm_td2_cosq_ing_pool_get(unit, gport, pg, 14886 bcmCosqControlIngressPool, 14887 &sp)); 14888 if (sp == index) { 14889 if (pri_max != 0 && pri_array != NULL) { 14890 if (count < pri_max) { 14891 pri_array[count] = i; 14892 } 14893 } 14894 count++; 14895 } 14896 } 14897 break; 14898 default: 14899 return BCM_E_UNAVAIL; 14900 } 14901 14902 if ((count < pri_max) && (pri_array != NULL)) { 14903 for (i = count; i < pri_max; i++) { 14904 pri_array[i] = -1; 14905 } 14906 *pri_count = count; 14907 } else if (pri_max == 0) { 14908 *pri_count = count; 14909 } else { 14910 *pri_count = pri_max; 14911 } 14912 return BCM_E_NONE; 14913 } 14914 14915 /* 14916 * Function: _bcm_td2_cosq_egr_queue_color_limit_set 14917 * Purpose: Set Red and Yellow color limit per queue 14918 * IF color mode dynamic: limit should be between 0-7 14919 * 0: 100% of green threshold 14920 * 1: 12.5% of green threshold 14921 * 2: 25% of green threshold 14922 * 3: 37.5% of green threshold 14923 * 4: 50% of green threshold 14924 * 5: 67.5% of green threshold 14925 * 6: 75% of green threshold 14926 * 7: 87.5% of green threshold 14927 * If color mode static: Limit is number of bytes 14928 */ 14929 14930 STATIC int 14931 _bcm_td2_cosq_egr_queue_color_limit_set(int unit, bcm_gport_t gport, 14932 bcm_cos_queue_t cosq, 14933 bcm_cosq_control_t type, 14934 int arg) 14935 { 14936 bcm_port_t local_port; 14937 int startq; 14938 uint32 entry[SOC_MAX_MEM_WORDS]; 14939 soc_mem_t mem = INVALIDm; 14940 soc_field_t fld_limit = INVALIDf; 14941 int color_mode, granularity, max_val; 14942 14943 if (arg < 0) { 14944 return BCM_E_PARAM; 14945 } 14946 granularity = 8; 14947 14948 if ((type == bcmCosqControlEgressUCQueueRedLimit) || 14949 (type == bcmCosqControlEgressUCQueueYellowLimit)) { 14950 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 14951 BCM_IF_ERROR_RETURN 14952 (_bcm_td2_cosq_index_resolve(unit, gport, cosq, 14953 _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE, 14954 &local_port, &startq, NULL)); 14955 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 14956 return BCM_E_PARAM; 14957 } else { 14958 if (cosq < 0) { 14959 return BCM_E_PARAM; 14960 } 14961 BCM_IF_ERROR_RETURN 14962 (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port)); 14963 if (local_port < 0) { 14964 return BCM_E_PORT; 14965 } 14966 BCM_IF_ERROR_RETURN 14967 (_bcm_td2_cosq_index_resolve 14968 (unit, local_port, cosq, _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE, 14969 NULL, &startq, NULL)); 14970 } 14971 if (type == bcmCosqControlEgressUCQueueRedLimit) { 14972 fld_limit = LIMIT_RED_CELLf; 14973 } else { 14974 fld_limit = LIMIT_YELLOW_CELLf; 14975 } 14976 mem = SOC_TD2_PMEM(unit, local_port, MMU_THDU_XPIPE_CONFIG_QUEUEm, 14977 MMU_THDU_YPIPE_CONFIG_QUEUEm); 14978 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 14979 color_mode = soc_mem_field32_get(unit, mem, entry, Q_COLOR_LIMIT_DYNAMIC_CELLf); 14980 14981 if (color_mode == 1) { /* Dynamic color limit */ 14982 if (arg > 7) { /* Legal values are 0 - 7 */ 14983 return BCM_E_PARAM; 14984 } else { 14985 soc_mem_field32_set(unit, mem, entry, fld_limit, arg); 14986 } 14987 } else { /* Static color limit */ 14988 arg = (arg + _TD2_MMU_BYTES_PER_CELL - 1) / _TD2_MMU_BYTES_PER_CELL; 14989 14990 /* Check for min/max values */ 14991 max_val = (1 << soc_mem_field_length(unit, mem, fld_limit)) - 1; 14992 if ((arg/granularity) > max_val) { 14993 return BCM_E_PARAM; 14994 } else { 14995 soc_mem_field32_set(unit, mem, entry, fld_limit, (arg/granularity)); 14996 } 14997 } 14998 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 14999 } else if ((type == bcmCosqControlEgressMCQueueRedLimit) || 15000 (type == bcmCosqControlEgressMCQueueYellowLimit)) { 15001 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 15002 return BCM_E_PARAM; 15003 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 15004 BCM_IF_ERROR_RETURN 15005 (_bcm_td2_cosq_index_resolve(unit, gport, cosq, 15006 _BCM_TD2_COSQ_INDEX_STYLE_MCAST_QUEUE, 15007 &local_port, &startq, NULL)); 15008 } else { 15009 if (cosq < 0) { 15010 return BCM_E_PARAM; 15011 } 15012 BCM_IF_ERROR_RETURN 15013 (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port)); 15014 if (local_port < 0) { 15015 return BCM_E_PORT; 15016 } 15017 BCM_IF_ERROR_RETURN 15018 (_bcm_td2_cosq_index_resolve(unit, local_port, cosq, 15019 _BCM_TD2_COSQ_INDEX_STYLE_MCAST_QUEUE, 15020 NULL, &startq, NULL)); 15021 } 15022 startq -= 1480; /* MC queues comes after UC queues */ 15023 if (type == bcmCosqControlEgressMCQueueRedLimit) { 15024 fld_limit = RED_SHARED_LIMITf; 15025 } else { 15026 fld_limit = YELLOW_SHARED_LIMITf; 15027 } 15028 mem = SOC_TD2_PMEM(unit, local_port, MMU_THDM_DB_QUEUE_CONFIG_0m, 15029 MMU_THDM_DB_QUEUE_CONFIG_1m); 15030 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 15031 color_mode = soc_mem_field32_get(unit, mem, entry, Q_COLOR_LIMIT_DYNAMICf); 15032 15033 if (color_mode == 1) { /* Dynamic color limit */ 15034 if (arg > 7) { /* Legal values are 0 - 7 */ 15035 return BCM_E_PARAM; 15036 } else { 15037 soc_mem_field32_set(unit, mem, entry, fld_limit, arg); 15038 } 15039 } else { /* Static color limit */ 15040 arg = (arg + _TD2_MMU_BYTES_PER_CELL - 1) / _TD2_MMU_BYTES_PER_CELL; 15041 15042 /* Check for min/max values */ 15043 max_val = (1 << soc_mem_field_length(unit, mem, fld_limit)) - 1; 15044 if ((arg/granularity) > max_val) { 15045 return BCM_E_PARAM; 15046 } else { 15047 soc_mem_field32_set(unit, mem, entry, fld_limit, (arg/granularity)); 15048 } 15049 } 15050 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 15051 15052 } else { 15053 return BCM_E_PARAM; 15054 } 15055 15056 return BCM_E_NONE; 15057 } 15058 15059 /* 15060 * Function: _bcm_td2_cosq_egr_queue_color_limit_get 15061 * Purpose: Get Red and Yellow color limit per queue 15062 * Return value: IF color mode dynamic: limit should be between 0-7 15063 * 0: 100% of green threshold 15064 * 1: 12.5% of green threshold 15065 * 2: 25% of green threshold 15066 * 3: 37.5% of green threshold 15067 * 4: 50% of green threshold 15068 * 5: 67.5% of green threshold 15069 * 6: 75% of green threshold 15070 * 7: 87.5% of green threshold 15071 * If color mode static: Limit is number of bytes 15072 */ 15073 15074 STATIC int 15075 _bcm_td2_cosq_egr_queue_color_limit_get(int unit, bcm_gport_t gport, 15076 bcm_cos_queue_t cosq, 15077 bcm_cosq_control_t type, 15078 int* arg) 15079 { 15080 bcm_port_t local_port; 15081 int startq; 15082 uint32 entry[SOC_MAX_MEM_WORDS]; 15083 soc_mem_t mem = INVALIDm; 15084 soc_field_t fld_limit = INVALIDf; 15085 int color_mode, granularity; 15086 15087 if (arg == NULL) { 15088 return BCM_E_PARAM; 15089 } 15090 15091 granularity = 8; 15092 15093 if ((type == bcmCosqControlEgressUCQueueRedLimit) || 15094 (type == bcmCosqControlEgressUCQueueYellowLimit)) { 15095 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 15096 BCM_IF_ERROR_RETURN 15097 (_bcm_td2_cosq_index_resolve(unit, gport, cosq, 15098 _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE, 15099 &local_port, &startq, NULL)); 15100 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 15101 return BCM_E_PARAM; 15102 } else { 15103 if (cosq < 0) { 15104 return BCM_E_PARAM; 15105 } 15106 BCM_IF_ERROR_RETURN 15107 (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port)); 15108 if (local_port < 0) { 15109 return BCM_E_PORT; 15110 } 15111 BCM_IF_ERROR_RETURN 15112 (_bcm_td2_cosq_index_resolve 15113 (unit, local_port, cosq, _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE, 15114 NULL, &startq, NULL)); 15115 } 15116 15117 if (type == bcmCosqControlEgressUCQueueRedLimit) { 15118 fld_limit = LIMIT_RED_CELLf; 15119 } else { 15120 fld_limit = LIMIT_YELLOW_CELLf; 15121 } 15122 mem = SOC_TD2_PMEM(unit, local_port, MMU_THDU_XPIPE_CONFIG_QUEUEm, 15123 MMU_THDU_YPIPE_CONFIG_QUEUEm); 15124 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 15125 color_mode = soc_mem_field32_get(unit, mem, entry, Q_COLOR_LIMIT_DYNAMIC_CELLf); 15126 15127 if (color_mode == 1) { /* Dynamic color limit */ 15128 *arg = soc_mem_field32_get(unit, mem, entry, fld_limit); 15129 } else { /* Static color limit */ 15130 *arg = soc_mem_field32_get(unit, mem, entry, fld_limit); 15131 *arg = (*arg) * granularity * _TD2_MMU_BYTES_PER_CELL; 15132 } 15133 } else if ((type == bcmCosqControlEgressMCQueueRedLimit) || 15134 (type == bcmCosqControlEgressMCQueueYellowLimit)) { 15135 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 15136 return BCM_E_PARAM; 15137 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 15138 BCM_IF_ERROR_RETURN 15139 (_bcm_td2_cosq_index_resolve(unit, gport, cosq, 15140 _BCM_TD2_COSQ_INDEX_STYLE_MCAST_QUEUE, 15141 &local_port, &startq, NULL)); 15142 } else { 15143 if (cosq < 0) { 15144 return BCM_E_PARAM; 15145 } 15146 BCM_IF_ERROR_RETURN 15147 (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port)); 15148 if (local_port < 0) { 15149 return BCM_E_PORT; 15150 } 15151 BCM_IF_ERROR_RETURN 15152 (_bcm_td2_cosq_index_resolve(unit, local_port, cosq, 15153 _BCM_TD2_COSQ_INDEX_STYLE_MCAST_QUEUE, 15154 NULL, &startq, NULL)); 15155 } 15156 startq -= 1480; /* MC queues comes after UC queues */ 15157 if (type == bcmCosqControlEgressMCQueueRedLimit) { 15158 fld_limit = RED_SHARED_LIMITf; 15159 } else { 15160 fld_limit = YELLOW_SHARED_LIMITf; 15161 } 15162 mem = SOC_TD2_PMEM(unit, local_port, MMU_THDM_DB_QUEUE_CONFIG_0m, 15163 MMU_THDM_DB_QUEUE_CONFIG_1m); 15164 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 15165 color_mode = soc_mem_field32_get(unit, mem, entry, Q_COLOR_LIMIT_DYNAMICf); 15166 15167 if (color_mode == 1) { /* Dynamic color limit */ 15168 *arg = soc_mem_field32_get(unit, mem, entry, fld_limit); 15169 } else { /* Static color limit */ 15170 *arg = soc_mem_field32_get(unit, mem, entry, fld_limit); 15171 *arg = (*arg) * granularity * _TD2_MMU_BYTES_PER_CELL; 15172 } 15173 15174 } else { 15175 return BCM_E_PARAM; 15176 } 15177 15178 return BCM_E_NONE; 15179 } 15180 15181 15182 /* 15183 * Function: _bcm_td2_cosq_egr_queue_color_limit_mode_set 15184 * Purpose: Set color limit mode per queue to static (0) or 15185 * dynamic (1) 15186 */ 15187 15188 STATIC int 15189 _bcm_td2_cosq_egr_queue_color_limit_mode_set(int unit, bcm_gport_t gport, 15190 bcm_cos_queue_t cosq, 15191 bcm_cosq_control_t type, 15192 int arg) 15193 { 15194 bcm_port_t local_port; 15195 int startq; 15196 uint32 entry[SOC_MAX_MEM_WORDS]; 15197 soc_mem_t mem = INVALIDm; 15198 int enable; 15199 15200 if (arg < 0) { 15201 return BCM_E_PARAM; 15202 } 15203 15204 arg = arg ? 1 : 0; 15205 15206 if (type == bcmCosqControlEgressUCQueueColorLimitDynamicEnable) { 15207 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 15208 BCM_IF_ERROR_RETURN 15209 (_bcm_td2_cosq_index_resolve(unit, gport, cosq, 15210 _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE, 15211 &local_port, &startq, NULL)); 15212 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 15213 return BCM_E_PARAM; 15214 } else { 15215 if (cosq < 0) { 15216 return BCM_E_PARAM; 15217 } 15218 BCM_IF_ERROR_RETURN 15219 (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port)); 15220 if (local_port < 0) { 15221 return BCM_E_PORT; 15222 } 15223 BCM_IF_ERROR_RETURN 15224 (_bcm_td2_cosq_index_resolve 15225 (unit, local_port, cosq, _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE, 15226 NULL, &startq, NULL)); 15227 } 15228 mem = SOC_TD2_PMEM(unit, local_port, MMU_THDU_XPIPE_CONFIG_QUEUEm, 15229 MMU_THDU_YPIPE_CONFIG_QUEUEm); 15230 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 15231 enable = soc_mem_field32_get(unit, mem, entry, Q_COLOR_LIMIT_DYNAMIC_CELLf); 15232 if (enable != arg) { 15233 soc_mem_field32_set(unit, mem, entry, Q_COLOR_LIMIT_DYNAMIC_CELLf, arg); 15234 /* Reset the Red and Yellow limits when color limit mode is changed */ 15235 soc_mem_field32_set(unit, mem, entry, LIMIT_RED_CELLf, 0); 15236 soc_mem_field32_set(unit, mem, entry, LIMIT_YELLOW_CELLf, 0); 15237 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 15238 } 15239 } else if (type == bcmCosqControlEgressMCQueueColorLimitDynamicEnable) { 15240 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 15241 return BCM_E_PARAM; 15242 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 15243 BCM_IF_ERROR_RETURN 15244 (_bcm_td2_cosq_index_resolve(unit, gport, cosq, 15245 _BCM_TD2_COSQ_INDEX_STYLE_MCAST_QUEUE, 15246 &local_port, &startq, NULL)); 15247 } else { 15248 if (cosq < 0) { 15249 return BCM_E_PARAM; 15250 } 15251 BCM_IF_ERROR_RETURN 15252 (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port)); 15253 if (local_port < 0) { 15254 return BCM_E_PORT; 15255 } 15256 BCM_IF_ERROR_RETURN 15257 (_bcm_td2_cosq_index_resolve(unit, local_port, cosq, 15258 _BCM_TD2_COSQ_INDEX_STYLE_MCAST_QUEUE, 15259 NULL, &startq, NULL)); 15260 } 15261 startq -= 1480; /* MC queues comes after UC queues */ 15262 mem = SOC_TD2_PMEM(unit, local_port, MMU_THDM_DB_QUEUE_CONFIG_0m, 15263 MMU_THDM_DB_QUEUE_CONFIG_1m); 15264 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 15265 enable = soc_mem_field32_get(unit, mem, entry, Q_COLOR_LIMIT_DYNAMICf); 15266 if (enable != arg) { 15267 soc_mem_field32_set(unit, mem, entry, Q_COLOR_LIMIT_DYNAMICf, arg); 15268 /* Reset the Red and Yellow limits when color limit mode is changed */ 15269 soc_mem_field32_set(unit, mem, entry, RED_SHARED_LIMITf, 0); 15270 soc_mem_field32_set(unit, mem, entry, YELLOW_SHARED_LIMITf, 0); 15271 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 15272 } 15273 } else { 15274 return BCM_E_PARAM; 15275 } 15276 15277 return BCM_E_NONE; 15278 } 15279 15280 /* 15281 * Function: _bcm_td2_cosq_egr_queue_color_limit_mode_get 15282 * Purpose: Get color limit mode per queue. 15283 * Returns: 0 (static) or 1 (dynamic) 15284 */ 15285 STATIC int 15286 _bcm_td2_cosq_egr_queue_color_limit_mode_get(int unit, bcm_gport_t gport, 15287 bcm_cos_queue_t cosq, 15288 bcm_cosq_control_t type, 15289 int* arg) 15290 { 15291 bcm_port_t local_port; 15292 int startq; 15293 uint32 entry[SOC_MAX_MEM_WORDS]; 15294 soc_mem_t mem = INVALIDm; 15295 15296 if (arg == NULL) { 15297 return BCM_E_PARAM; 15298 } 15299 15300 if (type == bcmCosqControlEgressUCQueueColorLimitDynamicEnable) { 15301 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 15302 BCM_IF_ERROR_RETURN 15303 (_bcm_td2_cosq_index_resolve(unit, gport, cosq, 15304 _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE, 15305 &local_port, &startq, NULL)); 15306 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 15307 return BCM_E_PARAM; 15308 } else { 15309 if (cosq < 0) { 15310 return BCM_E_PARAM; 15311 } 15312 BCM_IF_ERROR_RETURN 15313 (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port)); 15314 if (local_port < 0) { 15315 return BCM_E_PORT; 15316 } 15317 BCM_IF_ERROR_RETURN 15318 (_bcm_td2_cosq_index_resolve 15319 (unit, local_port, cosq, _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE, 15320 NULL, &startq, NULL)); 15321 } 15322 mem = SOC_TD2_PMEM(unit, local_port, MMU_THDU_XPIPE_CONFIG_QUEUEm, 15323 MMU_THDU_YPIPE_CONFIG_QUEUEm); 15324 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 15325 *arg = soc_mem_field32_get(unit, mem, entry, Q_COLOR_LIMIT_DYNAMIC_CELLf); 15326 } else if (type == bcmCosqControlEgressMCQueueColorLimitDynamicEnable) { 15327 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 15328 return BCM_E_PARAM; 15329 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 15330 BCM_IF_ERROR_RETURN 15331 (_bcm_td2_cosq_index_resolve(unit, gport, cosq, 15332 _BCM_TD2_COSQ_INDEX_STYLE_MCAST_QUEUE, 15333 &local_port, &startq, NULL)); 15334 } else { 15335 if (cosq < 0) { 15336 return BCM_E_PARAM; 15337 } 15338 BCM_IF_ERROR_RETURN 15339 (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port)); 15340 if (local_port < 0) { 15341 return BCM_E_PORT; 15342 } 15343 BCM_IF_ERROR_RETURN 15344 (_bcm_td2_cosq_index_resolve(unit, local_port, cosq, 15345 _BCM_TD2_COSQ_INDEX_STYLE_MCAST_QUEUE, 15346 NULL, &startq, NULL)); 15347 } 15348 startq -= 1480; /* MC queues comes after UC queues */ 15349 mem = SOC_TD2_PMEM(unit, local_port, MMU_THDM_DB_QUEUE_CONFIG_0m, 15350 MMU_THDM_DB_QUEUE_CONFIG_1m); 15351 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 15352 *arg = soc_mem_field32_get(unit, mem, entry, Q_COLOR_LIMIT_DYNAMICf); 15353 } else { 15354 return BCM_E_PARAM; 15355 } 15356 15357 return BCM_E_NONE; 15358 } 15359 15360 int 15361 bcm_td2_cosq_control_set(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 15362 bcm_cosq_control_t type, int arg) 15363 { 15364 switch (type) { 15365 case bcmCosqControlEgressPool: 15366 case bcmCosqControlEgressPoolLimitBytes: 15367 case bcmCosqControlEgressPoolYellowLimitBytes: 15368 case bcmCosqControlEgressPoolRedLimitBytes: 15369 case bcmCosqControlEgressPoolLimitEnable: 15370 case bcmCosqControlUCEgressPool: 15371 case bcmCosqControlMCEgressPool: 15372 case bcmCosqControlEgressPoolSharedLimitBytes: 15373 case bcmCosqControlEgressPoolResumeLimitBytes: 15374 case bcmCosqControlEgressPoolYellowSharedLimitBytes: 15375 case bcmCosqControlEgressPoolYellowResumeLimitBytes: 15376 case bcmCosqControlEgressPoolRedSharedLimitBytes: 15377 case bcmCosqControlEgressPoolRedResumeLimitBytes: 15378 return _bcm_td2_cosq_egr_pool_set(unit, gport, cosq, type, arg); 15379 case bcmCosqControlEfPropagation: 15380 return _bcm_td2_cosq_ef_op(unit, gport, cosq, &arg, _BCM_COSQ_OP_SET); 15381 case bcmCosqControlCongestionProxy: 15382 return _bcm_td2_cosq_qcn_proxy_set(unit, gport, cosq, type, arg); 15383 case bcmCosqControlEgressUCQueueSharedLimitBytes: 15384 case bcmCosqControlEgressMCQueueSharedLimitBytes: 15385 case bcmCosqControlEgressUCQueueMinLimitBytes: 15386 case bcmCosqControlEgressMCQueueMinLimitBytes: 15387 return _bcm_td2_cosq_egr_queue_set(unit, gport, cosq, type, arg); 15388 case bcmCosqControlIngressPortPGSharedLimitBytes: 15389 case bcmCosqControlIngressPortPoolMaxLimitBytes: 15390 case bcmCosqControlIngressPortPGMinLimitBytes: 15391 case bcmCosqControlIngressPortPoolMinLimitBytes: 15392 case bcmCosqControlIngressPortPGHeadroomLimitBytes: 15393 case bcmCosqControlIngressPortPGResetFloorBytes: 15394 return _bcm_td2_cosq_ing_res_set(unit, gport, cosq, type, arg); 15395 case bcmCosqControlIngressPoolLimitBytes: 15396 return _bcm_td2_cosq_ing_res_limit_set(unit, gport, cosq, type, arg); 15397 case bcmCosqControlIngressPool: 15398 return _bcm_td2_cosq_ing_pool_set(unit, gport, cosq, type, arg); 15399 case bcmCosqControlDropLimitAlpha: 15400 return _bcm_td2_cosq_alpha_set(unit, gport, cosq, 15401 (bcm_cosq_control_drop_limit_alpha_value_t)arg); 15402 case bcmCosqControlIngressPortPGSharedDynamicEnable: 15403 case bcmCosqControlEgressUCSharedDynamicEnable: 15404 case bcmCosqControlEgressMCSharedDynamicEnable: 15405 return _bcm_td2_cosq_dynamic_thresh_enable_set(unit, gport, cosq, 15406 type, arg); 15407 case bcmCosqControlEgressPortPoolYellowLimitBytes: 15408 case bcmCosqControlEgressPortPoolRedLimitBytes: 15409 return _bcm_td2_cosq_egr_port_pool_set(unit, gport, cosq, type, arg); 15410 case bcmCosqControlEgressUCQueueLimitEnable: 15411 case bcmCosqControlEgressMCQueueLimitEnable: 15412 case bcmCosqControlEgressMCQueueColorLimitEnable: 15413 case bcmCosqControlEgressUCQueueColorLimitEnable: 15414 return _bcm_td2_cosq_egr_queue_limit_enable_set(unit, gport, cosq, type, arg); 15415 case bcmCosqControlEgressUCQueueGroupMinEnable: 15416 case bcmCosqControlEgressUCQueueGroupSharedLimitEnable: 15417 case bcmCosqControlEgressUCQueueGroupSharedDynamicEnable: 15418 return _bcm_td2_cosq_qgroup_limit_enable_set(unit, gport, cosq, type, arg); 15419 case bcmCosqControlEgressUCQueueGroupMinLimitBytes: 15420 case bcmCosqControlEgressUCQueueGroupSharedLimitBytes: 15421 return _bcm_td2_cosq_qgroup_limit_set(unit, gport, cosq, type, arg); 15422 case bcmCosqControlEgressUCQueueGroupDropLimitAlpha: 15423 return _bcm_td2_cosq_qgroup_alpha_set(unit, gport, cosq, 15424 (bcm_cosq_control_drop_limit_alpha_value_t)arg); 15425 case bcmCosqControlEgressUCQueueColorLimitDynamicEnable: 15426 case bcmCosqControlEgressMCQueueColorLimitDynamicEnable: 15427 return _bcm_td2_cosq_egr_queue_color_limit_mode_set(unit, gport, cosq, 15428 type, arg); 15429 case bcmCosqControlEgressUCQueueRedLimit: 15430 case bcmCosqControlEgressUCQueueYellowLimit: 15431 case bcmCosqControlEgressMCQueueRedLimit: 15432 case bcmCosqControlEgressMCQueueYellowLimit: 15433 return _bcm_td2_cosq_egr_queue_color_limit_set(unit, gport, cosq, type, arg); 15434 15435 default: 15436 break; 15437 } 15438 15439 return BCM_E_UNAVAIL; 15440 } 15441 15442 int 15443 bcm_td2_cosq_control_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 15444 bcm_cosq_control_t type, int *arg) 15445 { 15446 switch (type) { 15447 case bcmCosqControlEgressPool: 15448 case bcmCosqControlEgressPoolLimitBytes: 15449 case bcmCosqControlEgressPoolYellowLimitBytes: 15450 case bcmCosqControlEgressPoolRedLimitBytes: 15451 case bcmCosqControlEgressPoolLimitEnable: 15452 case bcmCosqControlUCEgressPool: 15453 case bcmCosqControlMCEgressPool: 15454 case bcmCosqControlEgressPoolSharedLimitBytes: 15455 case bcmCosqControlEgressPoolResumeLimitBytes: 15456 case bcmCosqControlEgressPoolYellowSharedLimitBytes: 15457 case bcmCosqControlEgressPoolYellowResumeLimitBytes: 15458 case bcmCosqControlEgressPoolRedSharedLimitBytes: 15459 case bcmCosqControlEgressPoolRedResumeLimitBytes: 15460 return _bcm_td2_cosq_egr_pool_get(unit, gport, cosq, type, arg); 15461 case bcmCosqControlEfPropagation: 15462 return _bcm_td2_cosq_ef_op(unit, gport, cosq, arg, _BCM_COSQ_OP_GET); 15463 case bcmCosqControlCongestionProxy: 15464 return _bcm_td2_cosq_qcn_proxy_get(unit, gport, cosq, type, arg); 15465 case bcmCosqControlEgressUCQueueSharedLimitBytes: 15466 case bcmCosqControlEgressMCQueueSharedLimitBytes: 15467 case bcmCosqControlEgressUCQueueMinLimitBytes: 15468 case bcmCosqControlEgressMCQueueMinLimitBytes: 15469 return _bcm_td2_cosq_egr_queue_get(unit, gport, cosq, type, arg); 15470 case bcmCosqControlIngressPortPGSharedLimitBytes: 15471 case bcmCosqControlIngressPortPoolMaxLimitBytes: 15472 case bcmCosqControlIngressPortPGMinLimitBytes: 15473 case bcmCosqControlIngressPortPoolMinLimitBytes: 15474 case bcmCosqControlIngressPortPGHeadroomLimitBytes: 15475 case bcmCosqControlIngressPortPGResetFloorBytes: 15476 return _bcm_td2_cosq_ing_res_get(unit, gport, cosq, type, arg); 15477 case bcmCosqControlIngressPoolLimitBytes: 15478 return _bcm_td2_cosq_ing_res_limit_get(unit, gport, cosq, type, arg); 15479 case bcmCosqControlSPPortLimitState: 15480 case bcmCosqControlPGPortLimitState: 15481 case bcmCosqControlPGPortXoffState: 15482 case bcmCosqControlPoolRedDropState: 15483 case bcmCosqControlPoolYellowDropState: 15484 case bcmCosqControlPoolGreenDropState: 15485 return _bcm_td2_cosq_state_get(unit, gport, cosq, type, arg); 15486 case bcmCosqControlIngressPool: 15487 return _bcm_td2_cosq_ing_pool_get(unit, gport, cosq, type, arg); 15488 case bcmCosqControlDropLimitAlpha: 15489 return _bcm_td2_cosq_alpha_get(unit, gport, cosq, 15490 (bcm_cosq_control_drop_limit_alpha_value_t *)arg); 15491 case bcmCosqControlIngressPortPGSharedDynamicEnable: 15492 case bcmCosqControlEgressUCSharedDynamicEnable: 15493 case bcmCosqControlEgressMCSharedDynamicEnable: 15494 return _bcm_td2_cosq_dynamic_thresh_enable_get(unit, gport, cosq, 15495 type, arg); 15496 case bcmCosqControlPortQueueUcast: 15497 case bcmCosqControlPortQueueMcast: 15498 return _bcm_td2_cosq_port_qnum_get(unit, gport, cosq, type, arg); 15499 case bcmCosqControlEgressPortPoolYellowLimitBytes: 15500 case bcmCosqControlEgressPortPoolRedLimitBytes: 15501 return _bcm_td2_cosq_egr_port_pool_get(unit, gport, cosq, type, arg); 15502 case bcmCosqControlEgressUCQueueLimitEnable: 15503 case bcmCosqControlEgressMCQueueLimitEnable: 15504 case bcmCosqControlEgressMCQueueColorLimitEnable: 15505 case bcmCosqControlEgressUCQueueColorLimitEnable: 15506 return _bcm_td2_cosq_egr_queue_limit_enable_get(unit, gport, cosq, type, arg); 15507 case bcmCosqControlEgressUCQueueGroupMinEnable: 15508 case bcmCosqControlEgressUCQueueGroupSharedLimitEnable: 15509 case bcmCosqControlEgressUCQueueGroupSharedDynamicEnable: 15510 return _bcm_td2_cosq_qgroup_limit_enable_get(unit, gport, cosq, type, arg); 15511 case bcmCosqControlEgressUCQueueGroupMinLimitBytes: 15512 case bcmCosqControlEgressUCQueueGroupSharedLimitBytes: 15513 return _bcm_td2_cosq_qgroup_limit_get(unit, gport, cosq, type, arg); 15514 case bcmCosqControlEgressUCQueueGroupDropLimitAlpha: 15515 return _bcm_td2_cosq_qgroup_alpha_get(unit, gport, cosq, 15516 (bcm_cosq_control_drop_limit_alpha_value_t *)arg); 15517 case bcmCosqControlEgressUCQueueColorLimitDynamicEnable: 15518 case bcmCosqControlEgressMCQueueColorLimitDynamicEnable: 15519 return _bcm_td2_cosq_egr_queue_color_limit_mode_get(unit, gport, cosq, 15520 type, arg); 15521 case bcmCosqControlEgressUCQueueRedLimit: 15522 case bcmCosqControlEgressUCQueueYellowLimit: 15523 case bcmCosqControlEgressMCQueueRedLimit: 15524 case bcmCosqControlEgressMCQueueYellowLimit: 15525 return _bcm_td2_cosq_egr_queue_color_limit_get(unit, gport, cosq, type, arg); 15526 15527 default: 15528 break; 15529 } 15530 15531 return BCM_E_UNAVAIL; 15532 } 15533 15534 int 15535 bcm_td2_cosq_service_pool_set( 15536 int unit, 15537 bcm_service_pool_id_t id, 15538 bcm_cosq_service_pool_t cosq_service_pool) 15539 { 15540 uint32 rval; 15541 soc_field_t fld_enable = INVALIDf; 15542 static const soc_field_t pool_port_color_enable_fields[] = { 15543 PORTSP_COLOR_LIMIT_ENABLE_0f, PORTSP_COLOR_LIMIT_ENABLE_1f, 15544 PORTSP_COLOR_LIMIT_ENABLE_2f, PORTSP_COLOR_LIMIT_ENABLE_3f 15545 }; 15546 static const soc_field_t pool_color_enable_fields[] = { 15547 POOL_COLOR_LIMIT_ENABLE_0f, POOL_COLOR_LIMIT_ENABLE_1f, 15548 POOL_COLOR_LIMIT_ENABLE_2f, POOL_COLOR_LIMIT_ENABLE_3f 15549 }; 15550 15551 if (id < 0 || (id > _TD2_NUM_SERVICE_POOL - 1)) { 15552 return BCM_E_PARAM; 15553 } 15554 15555 SOC_IF_ERROR_RETURN(READ_MMU_THDM_DB_DEVICE_THR_CONFIGr(unit, &rval)); 15556 switch (cosq_service_pool.type) { 15557 case bcmCosqServicePoolPortColorAware: 15558 fld_enable = pool_port_color_enable_fields[id]; 15559 break; 15560 case bcmCosqServicePoolColorAware: 15561 fld_enable = pool_color_enable_fields[id]; 15562 break; 15563 default: 15564 return BCM_E_PARAM; 15565 } 15566 15567 soc_reg_field_set(unit, MMU_THDM_DB_DEVICE_THR_CONFIGr, &rval, 15568 fld_enable, cosq_service_pool.enabled ? 1 : 0); 15569 SOC_IF_ERROR_RETURN(WRITE_MMU_THDM_DB_DEVICE_THR_CONFIGr(unit, rval)); 15570 return BCM_E_NONE; 15571 } 15572 15573 15574 int 15575 bcm_td2_cosq_service_pool_get( 15576 int unit, 15577 bcm_service_pool_id_t id, 15578 bcm_cosq_service_pool_t *cosq_service_pool) 15579 { 15580 uint32 rval; 15581 soc_field_t fld_enable = INVALIDf; 15582 static const soc_field_t pool_port_color_enable_fields[] = { 15583 PORTSP_COLOR_LIMIT_ENABLE_0f, PORTSP_COLOR_LIMIT_ENABLE_1f, 15584 PORTSP_COLOR_LIMIT_ENABLE_2f, PORTSP_COLOR_LIMIT_ENABLE_3f 15585 }; 15586 static const soc_field_t pool_color_enable_fields[] = { 15587 POOL_COLOR_LIMIT_ENABLE_0f, POOL_COLOR_LIMIT_ENABLE_1f, 15588 POOL_COLOR_LIMIT_ENABLE_2f, POOL_COLOR_LIMIT_ENABLE_3f 15589 }; 15590 15591 if (cosq_service_pool == NULL) { 15592 return BCM_E_PARAM; 15593 } 15594 15595 if (id < 0 || (id > _TD2_NUM_SERVICE_POOL - 1)) { 15596 return BCM_E_PARAM; 15597 } 15598 15599 SOC_IF_ERROR_RETURN(READ_MMU_THDM_DB_DEVICE_THR_CONFIGr(unit, &rval)); 15600 switch (cosq_service_pool->type) { 15601 case bcmCosqServicePoolPortColorAware: 15602 fld_enable = pool_port_color_enable_fields[id]; 15603 break; 15604 case bcmCosqServicePoolColorAware: 15605 fld_enable = pool_color_enable_fields[id]; 15606 break; 15607 default: 15608 return BCM_E_PARAM; 15609 } 15610 15611 cosq_service_pool->enabled = soc_reg_field_get(unit, MMU_THDM_DB_DEVICE_THR_CONFIGr, rval, 15612 fld_enable); 15613 return BCM_E_NONE; 15614 } 15615 15616 15617 15618 int 15619 _bcm_td2_cosq_gport_detach(int unit, bcm_port_t port) 15620 { 15621 return BCM_E_NONE; 15622 } 15623 15624 /* 15625 * Function: 15626 * bcm_td2_cosq_gport_bandwidth_set 15627 * Purpose: 15628 * Configure COS queue bandwidth control 15629 * Parameters: 15630 * unit - (IN) unit number 15631 * gport - (IN) GPORT identifier 15632 * cosq - (IN) COS queue to configure, -1 for all COS queues 15633 * kbits_sec_min - (IN) minimum bandwidth, kbits/sec 15634 * kbits_sec_max - (IN) maximum bandwidth, kbits/sec 15635 * flags - (IN) BCM_COSQ_BW_* 15636 * Returns: 15637 * BCM_E_XXX 15638 */ 15639 int 15640 bcm_td2_cosq_gport_bandwidth_set(int unit, bcm_gport_t gport, 15641 bcm_cos_queue_t cosq, uint32 kbits_sec_min, 15642 uint32 kbits_sec_max, uint32 flags) 15643 { 15644 int i, start_cos, end_cos, local_port, ets_mode; 15645 _bcm_td2_cosq_node_t *node, *child_node; 15646 uint32 burst_min, burst_max; 15647 int mode = 0, weight = 0, weight_sum = 0; 15648 15649 if (cosq <= -1) { 15650 if (BCM_GPORT_IS_SET(gport)) { 15651 BCM_IF_ERROR_RETURN 15652 (_bcm_td2_cosq_node_get(unit, gport, 0, NULL, 15653 NULL, NULL, &node)); 15654 start_cos = 0; 15655 end_cos = node->numq - 1; 15656 } else { 15657 start_cos = 0; 15658 end_cos = _TD2_NUM_COS(unit) - 1; 15659 } 15660 } else { 15661 start_cos = end_cos = cosq; 15662 } 15663 15664 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_localport_resolve(unit, gport, &local_port)); 15665 ets_mode = _bcm_td2_cosq_port_has_ets(unit, local_port); 15666 for (i = start_cos; i <= end_cos; i++) { 15667 /* Workaround for bandwidth distriution inaccuracy when max bandwidth 15668 * shaping is used in conjunction with round robin scheduling. 15669 * Burst Size=SUM((RR_weights[except for Queue_i]+1))*MTU*ShapedRate/AvailableExcessBWRate 15670 */ 15671 if (BCM_GPORT_IS_SET(gport) && ets_mode && SOC_IS_TRIDENT2(unit)) { 15672 BCM_IF_ERROR_RETURN 15673 (_bcm_td2_cosq_node_get(unit, gport, 0, NULL, 15674 NULL, NULL, &node)); 15675 /* SUM((RR_weights[except for Queue_i]+1)) */ 15676 for (child_node = node->child; 15677 child_node != NULL; 15678 child_node = child_node->sibling) { 15679 if (child_node->attached_to_input != i) { 15680 BCM_IF_ERROR_RETURN( 15681 bcm_td2_cosq_gport_sched_get( 15682 unit, gport, child_node->attached_to_input, &mode, &weight)); 15683 if (mode != SOC_TD2_SCHED_MODE_STRICT) { 15684 weight_sum += weight + 1; 15685 } 15686 } 15687 } 15688 } 15689 15690 burst_min = (kbits_sec_min > 0) ? 15691 _bcm_td_default_burst_size_by_weight( 15692 unit, local_port, kbits_sec_min, weight_sum) : 0; 15693 15694 burst_max = (kbits_sec_max > 0) ? 15695 _bcm_td_default_burst_size_by_weight( 15696 unit, local_port, kbits_sec_max, weight_sum) : 0; 15697 15698 15699 BCM_IF_ERROR_RETURN 15700 (_bcm_td2_cosq_bucket_set(unit, gport, i, kbits_sec_min, 15701 kbits_sec_max, burst_min, burst_max, flags)); 15702 } 15703 15704 return BCM_E_NONE; 15705 } 15706 15707 /* 15708 * Function: 15709 * bcm_td2_cosq_gport_bandwidth_get 15710 * Purpose: 15711 * Get COS queue bandwidth control configuration 15712 * Parameters: 15713 * unit - (IN) unit number 15714 * gport - (IN) GPORT identifier 15715 * cosq - (IN) COS queue to get, -1 for any COS queue 15716 * kbits_sec_min - (OUT) minimum bandwidth, kbits/sec 15717 * kbits_sec_max - (OUT) maximum bandwidth, kbits/sec 15718 * flags - (OUT) BCM_COSQ_BW_* 15719 * Returns: 15720 * BCM_E_XXX 15721 */ 15722 int 15723 bcm_td2_cosq_gport_bandwidth_get(int unit, bcm_gport_t gport, 15724 bcm_cos_queue_t cosq, uint32 *kbits_sec_min, 15725 uint32 *kbits_sec_max, uint32 *flags) 15726 { 15727 uint32 kbits_sec_burst; 15728 15729 if (cosq == -1) { 15730 return BCM_E_PARAM; 15731 } 15732 15733 BCM_IF_ERROR_RETURN 15734 (_bcm_td2_cosq_bucket_get(unit, gport, cosq, 15735 kbits_sec_min, kbits_sec_max, 15736 &kbits_sec_burst, &kbits_sec_burst, flags)); 15737 return BCM_E_NONE; 15738 } 15739 15740 /* 15741 * Function: 15742 * bcm_td2_cosq_gport_bandwidth_burst_set 15743 * Purpose: 15744 * Configure COS queue bandwidth burst setting 15745 * Parameters: 15746 * unit - (IN) unit number 15747 * gport - (IN) GPORT identifier 15748 * cosq - (IN) COS queue to configure, -1 for all COS queues 15749 * kbits_burst - (IN) maximum burst, kbits 15750 * Returns: 15751 * BCM_E_XXX 15752 */ 15753 int 15754 bcm_td2_cosq_gport_bandwidth_burst_set(int unit, bcm_gport_t gport, 15755 bcm_cos_queue_t cosq, 15756 uint32 kbits_burst_min, 15757 uint32 kbits_burst_max) 15758 { 15759 int i, start_cos, end_cos; 15760 uint32 kbits_sec_min, kbits_sec_max, kbits_sec_burst, flags; 15761 _bcm_td2_cosq_node_t *node; 15762 15763 if (cosq < -1) { 15764 return BCM_E_PARAM; 15765 } 15766 15767 if (cosq == -1) { 15768 if (BCM_GPORT_IS_SET(gport)) { 15769 BCM_IF_ERROR_RETURN 15770 (_bcm_td2_cosq_node_get(unit, gport, 0, NULL, 15771 NULL, NULL, &node)); 15772 start_cos = 0; 15773 end_cos = node->numq - 1; 15774 } else { 15775 start_cos = 0; 15776 end_cos = _TD2_NUM_COS(unit) - 1; 15777 } 15778 } else { 15779 start_cos = end_cos = cosq; 15780 } 15781 15782 for (i = start_cos; i <= end_cos; i++) { 15783 BCM_IF_ERROR_RETURN 15784 (_bcm_td2_cosq_bucket_get(unit, gport, i, &kbits_sec_min, 15785 &kbits_sec_max, &kbits_sec_burst, 15786 &kbits_sec_burst, &flags)); 15787 BCM_IF_ERROR_RETURN 15788 (_bcm_td2_cosq_bucket_set(unit, gport, i, kbits_sec_min, 15789 kbits_sec_max, kbits_burst_min, 15790 kbits_burst_max, flags)); 15791 } 15792 15793 return BCM_E_NONE; 15794 } 15795 15796 /* 15797 * Function: 15798 * bcm_td2_cosq_gport_bandwidth_burst_get 15799 * Purpose: 15800 * Get COS queue bandwidth burst setting 15801 * Parameters: 15802 * unit - (IN) unit number 15803 * gport - (IN) GPORT identifier 15804 * cosq - (IN) COS queue to get, -1 for any queue 15805 * kbits_burst - (OUT) maximum burst, kbits 15806 * Returns: 15807 * BCM_E_XXX 15808 */ 15809 int 15810 bcm_td2_cosq_gport_bandwidth_burst_get(int unit, bcm_gport_t gport, 15811 bcm_cos_queue_t cosq, 15812 uint32 *kbits_burst_min, 15813 uint32 *kbits_burst_max) 15814 { 15815 uint32 kbits_sec_min, kbits_sec_max, flags; 15816 15817 if (cosq < -1) { 15818 return BCM_E_PARAM; 15819 } 15820 15821 BCM_IF_ERROR_RETURN 15822 (_bcm_td2_cosq_bucket_get(unit, gport, cosq == -1 ? 0 : cosq, 15823 &kbits_sec_min, &kbits_sec_max, kbits_burst_min, 15824 kbits_burst_max, &flags)); 15825 15826 return BCM_E_NONE; 15827 } 15828 15829 /* 15830 * Function: 15831 * bcm_td2_cosq_gport_sched_set 15832 * Purpose: 15833 * Configure COS queue scheduler setting 15834 * Parameters: 15835 * unit - (IN) unit number 15836 * gport - (IN) GPORT identifier 15837 * cosq - (IN) COS queue to configure, -1 for all COS queues 15838 * mode - (IN) Scheduling mode, one of BCM_COSQ_xxx 15839 * weight - (IN) queue weight 15840 * Returns: 15841 * BCM_E_XXX 15842 */ 15843 int 15844 bcm_td2_cosq_gport_sched_set(int unit, bcm_gport_t gport, 15845 bcm_cos_queue_t cosq, int mode, int weight) 15846 { 15847 int rv, numq, i, count; 15848 15849 if (cosq == -1) { 15850 BCM_IF_ERROR_RETURN 15851 (_bcm_td2_cosq_index_resolve(unit, gport, cosq, 15852 _BCM_TD2_COSQ_INDEX_STYLE_SCHEDULER, 15853 NULL, NULL, &numq)); 15854 cosq = 0; 15855 } else { 15856 numq = 1; 15857 } 15858 15859 count = 0; 15860 for (i = 0; i < numq; i++) { 15861 rv = _bcm_td2_cosq_sched_set(unit, gport, cosq + i, mode, weight); 15862 if (rv == BCM_E_NOT_FOUND) { 15863 continue; 15864 } else if (BCM_FAILURE(rv)) { 15865 return rv; 15866 } else { 15867 count++; 15868 } 15869 } 15870 15871 return count > 0 ? BCM_E_NONE : BCM_E_NOT_FOUND; 15872 } 15873 15874 /* 15875 * Function: 15876 * bcm_td2_cosq_gport_sched_get 15877 * Purpose: 15878 * Get COS queue scheduler setting 15879 * Parameters: 15880 * unit - (IN) unit number 15881 * gport - (IN) GPORT identifier 15882 * cosq - (IN) COS queue to get, -1 for any queue 15883 * mode - (OUT) Scheduling mode, one of BCM_COSQ_xxx 15884 * weight - (OUT) queue weight 15885 * Returns: 15886 * BCM_E_XXX 15887 */ 15888 int 15889 bcm_td2_cosq_gport_sched_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 15890 int *mode, int *weight) 15891 { 15892 int rv, numq, i; 15893 15894 if (cosq == -1) { 15895 BCM_IF_ERROR_RETURN 15896 (_bcm_td2_cosq_index_resolve(unit, gport, 0, 15897 _BCM_TD2_COSQ_INDEX_STYLE_SCHEDULER, 15898 NULL, NULL, &numq)); 15899 cosq = 0; 15900 } else { 15901 numq = 1; 15902 } 15903 15904 for (i = 0; i < numq; i++) { 15905 rv = _bcm_td2_cosq_sched_get(unit, gport, cosq + i, mode, weight); 15906 if (rv == BCM_E_NOT_FOUND) { 15907 continue; 15908 } else { 15909 return rv; 15910 } 15911 } 15912 15913 return BCM_E_NOT_FOUND; 15914 } 15915 15916 /* 15917 * Function: 15918 * bcm_td2_cosq_gport_discard_set 15919 * Purpose: 15920 * Configure port WRED setting 15921 * Parameters: 15922 * unit - (IN) unit number 15923 * port - (IN) GPORT identifier 15924 * cosq - (IN) COS queue to configure, -1 for all COS queues 15925 * discard - (IN) discard settings 15926 * Returns: 15927 * BCM_E_XXX 15928 */ 15929 int 15930 bcm_td2_cosq_gport_discard_set(int unit, bcm_gport_t gport, 15931 bcm_cos_queue_t cosq, 15932 bcm_cosq_gport_discard_t *discard) 15933 { 15934 uint32 min_thresh, max_thresh, flags = 0; 15935 int cell_size, cell_field_max; 15936 bcm_port_t local_port = -1; 15937 15938 /* refresh_time from 1 to 7 be set the same as default 8,so the reasonable 15939 range of refresh_time is from 1 to 512 */ 15940 if (discard == NULL || 15941 discard->gain < 0 || discard->gain > 15 || 15942 discard->drop_probability < 0 || discard->drop_probability > 100 || 15943 discard->refresh_time <= 0 || discard->refresh_time > 512 || 15944 (discard->min_thresh > discard->max_thresh) || 15945 (discard->min_thresh < 0)) { 15946 return BCM_E_PARAM; 15947 } 15948 15949 cell_size = _BCM_TD2_BYTES_PER_CELL; 15950 cell_field_max = TD2_CELL_FIELD_MAX; 15951 15952 min_thresh = discard->min_thresh; 15953 max_thresh = discard->max_thresh; 15954 if (discard->flags & BCM_COSQ_DISCARD_BYTES) { 15955 /* Convert bytes to cells */ 15956 min_thresh += (cell_size - 1); 15957 min_thresh /= cell_size; 15958 15959 max_thresh += (cell_size - 1); 15960 max_thresh /= cell_size; 15961 15962 if ((min_thresh > cell_field_max) || 15963 (max_thresh > cell_field_max)) { 15964 return BCM_E_PARAM; 15965 } 15966 } else { 15967 /* Packet mode not supported */ 15968 return BCM_E_PARAM; 15969 } 15970 15971 if (gport != BCM_GPORT_INVALID) { 15972 BCM_IF_ERROR_RETURN 15973 (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port)); 15974 if (IS_CPU_PORT(unit,local_port) || IS_LB_PORT(unit,local_port)) { 15975 return BCM_E_PORT; 15976 } 15977 } 15978 15979 BCM_IF_ERROR_RETURN 15980 (_bcm_td2_cosq_wred_set(unit, gport, cosq, discard->flags, 15981 min_thresh, max_thresh, 15982 discard->drop_probability, discard->gain, 15983 FALSE, flags,discard->refresh_time)); 15984 15985 return BCM_E_NONE; 15986 } 15987 15988 /* 15989 * Function: 15990 * bcm_td2_cosq_gport_discard_get 15991 * Purpose: 15992 * Get port WRED setting 15993 * Parameters: 15994 * unit - (IN) unit number 15995 * port - (IN) GPORT identifier 15996 * cosq - (IN) COS queue to get, -1 for any queue 15997 * discard - (OUT) discard settings 15998 * Returns: 15999 * BCM_E_XXX 16000 */ 16001 int 16002 bcm_td2_cosq_gport_discard_get(int unit, bcm_gport_t gport, 16003 bcm_cos_queue_t cosq, 16004 bcm_cosq_gport_discard_t *discard) 16005 { 16006 uint32 min_thresh, max_thresh; 16007 bcm_port_t local_port = -1; 16008 16009 if (discard == NULL) { 16010 return BCM_E_PARAM; 16011 } 16012 16013 if (discard->flags & BCM_COSQ_DISCARD_PACKETS) { 16014 /* Packet mode not supported */ 16015 return BCM_E_PARAM; 16016 } 16017 16018 if (gport != BCM_GPORT_INVALID) { 16019 BCM_IF_ERROR_RETURN 16020 (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port)); 16021 if (IS_CPU_PORT(unit,local_port) || IS_LB_PORT(unit,local_port)) { 16022 return BCM_E_PORT; 16023 } 16024 } 16025 16026 BCM_IF_ERROR_RETURN 16027 (_bcm_td2_cosq_wred_get(unit, gport, cosq == -1 ? 0 : cosq, 16028 &discard->flags, &min_thresh, &max_thresh, 16029 &discard->drop_probability, &discard->gain, 16030 0,&discard->refresh_time)); 16031 16032 /* Convert number of cells to number of bytes */ 16033 discard->min_thresh = min_thresh * _BCM_TD2_BYTES_PER_CELL; 16034 discard->max_thresh = max_thresh * _BCM_TD2_BYTES_PER_CELL; 16035 16036 return BCM_E_NONE; 16037 } 16038 16039 int 16040 _bcm_td2_cosq_pfc_class_resolve(bcm_switch_control_t sctype, int *type, 16041 int *class) 16042 { 16043 switch (sctype) { 16044 case bcmSwitchPFCClass7Queue: 16045 case bcmSwitchPFCClass6Queue: 16046 case bcmSwitchPFCClass5Queue: 16047 case bcmSwitchPFCClass4Queue: 16048 case bcmSwitchPFCClass3Queue: 16049 case bcmSwitchPFCClass2Queue: 16050 case bcmSwitchPFCClass1Queue: 16051 case bcmSwitchPFCClass0Queue: 16052 *type = _BCM_TD2_COSQ_TYPE_UCAST; 16053 break; 16054 case bcmSwitchPFCClass7McastQueue: 16055 case bcmSwitchPFCClass6McastQueue: 16056 case bcmSwitchPFCClass5McastQueue: 16057 case bcmSwitchPFCClass4McastQueue: 16058 case bcmSwitchPFCClass3McastQueue: 16059 case bcmSwitchPFCClass2McastQueue: 16060 case bcmSwitchPFCClass1McastQueue: 16061 case bcmSwitchPFCClass0McastQueue: 16062 *type = _BCM_TD2_COSQ_TYPE_MCAST; 16063 break; 16064 case bcmSwitchPFCClass7DestmodQueue: 16065 case bcmSwitchPFCClass6DestmodQueue: 16066 case bcmSwitchPFCClass5DestmodQueue: 16067 case bcmSwitchPFCClass4DestmodQueue: 16068 case bcmSwitchPFCClass3DestmodQueue: 16069 case bcmSwitchPFCClass2DestmodQueue: 16070 case bcmSwitchPFCClass1DestmodQueue: 16071 case bcmSwitchPFCClass0DestmodQueue: 16072 *type = _BCM_TD2_COSQ_TYPE_EXT_UCAST; 16073 break; 16074 default: 16075 return BCM_E_PARAM; 16076 } 16077 16078 switch (sctype) { 16079 case bcmSwitchPFCClass7Queue: 16080 case bcmSwitchPFCClass7McastQueue: 16081 case bcmSwitchPFCClass7DestmodQueue: 16082 *class = 7; 16083 break; 16084 case bcmSwitchPFCClass6Queue: 16085 case bcmSwitchPFCClass6McastQueue: 16086 case bcmSwitchPFCClass6DestmodQueue: 16087 *class = 6; 16088 break; 16089 case bcmSwitchPFCClass5Queue: 16090 case bcmSwitchPFCClass5McastQueue: 16091 case bcmSwitchPFCClass5DestmodQueue: 16092 *class = 5; 16093 break; 16094 case bcmSwitchPFCClass4Queue: 16095 case bcmSwitchPFCClass4McastQueue: 16096 case bcmSwitchPFCClass4DestmodQueue: 16097 *class = 4; 16098 break; 16099 case bcmSwitchPFCClass3Queue: 16100 case bcmSwitchPFCClass3McastQueue: 16101 case bcmSwitchPFCClass3DestmodQueue: 16102 *class = 3; 16103 break; 16104 case bcmSwitchPFCClass2Queue: 16105 case bcmSwitchPFCClass2McastQueue: 16106 case bcmSwitchPFCClass2DestmodQueue: 16107 *class = 2; 16108 break; 16109 case bcmSwitchPFCClass1Queue: 16110 case bcmSwitchPFCClass1McastQueue: 16111 case bcmSwitchPFCClass1DestmodQueue: 16112 *class = 1; 16113 break; 16114 case bcmSwitchPFCClass0Queue: 16115 case bcmSwitchPFCClass0McastQueue: 16116 case bcmSwitchPFCClass0DestmodQueue: 16117 *class = 0; 16118 break; 16119 /* 16120 * COVERITY 16121 * 16122 * This default is unreachable but needed for some compiler. 16123 */ 16124 /* coverity[dead_error_begin] */ 16125 default: 16126 return BCM_E_INTERNAL; 16127 } 16128 return BCM_E_NONE; 16129 } 16130 16131 /* 16132 * Function: 16133 * _bcm_td2_pfc_map_index_resolve 16134 * Purpose: 16135 * Resolve table index and field of MMU_INTFI_X/YPIPE_FC_MAP_TBL0/1/2. 16136 * Parameters: 16137 * unit - (IN) unit number 16138 * port - (IN) port number 16139 * hw_index - (IN) Gport node hw_index 16140 * level - (IN) Sched level 16141 * index - (OUT) Resolved table index 16142 * field - (OUT) Resolved index field 16143 * Returns: 16144 * BCM_E_XXX 16145 */ 16146 STATIC int 16147 _bcm_td2_pfc_map_index_resolve(int unit, int port, 16148 uint32 hw_index, int level, 16149 int *index, int *field) 16150 { 16151 int map_entry_index, eindex; 16152 int port_num = 0; 16153 int map_entry_index_num = 0; 16154 int mcq_offset; 16155 uint16 dev_id; 16156 uint8 rev_id; 16157 16158 if ((index == NULL) || (field == NULL)) { 16159 return BCM_E_PARAM; 16160 } 16161 if ((level != SOC_TD2_NODE_LVL_L0) && 16162 (level != SOC_TD2_NODE_LVL_L1) && 16163 (level != SOC_TD2_NODE_LVL_L2)) { 16164 return BCM_E_PARAM; 16165 } 16166 16167 /* FC_MAP_TBL[Level] has 4 Index[0-3], whose values become Index to PFC_ST_TBL. 16168 * Each Index of PFC_ST_TBL can point to congestion state of 4 Qs. 16169 * Hence each Entry of FC_MAP_TBL can refer to 16 Qs. 16170 * 16171 * NOTE: Index of FC_MAP_TBL CANNOT be used to point to Qs/Nodes belonging 16172 * to Different Ports. 16173 */ 16174 if (level == SOC_TD2_NODE_LVL_L0) { 16175 if (IS_TD2_HSP_PORT(unit, port)) { 16176 if ((hw_index % _BCM_TD2_HSP_PORT_MAX_L0) > 3) { 16177 return BCM_E_UNAVAIL; 16178 } 16179 port_num = hw_index / _BCM_TD2_HSP_PORT_MAX_L0; 16180 16181 map_entry_index_num = port_num; 16182 /* each entry contains 4 indices */ 16183 map_entry_index = map_entry_index_num / 4; 16184 eindex = map_entry_index_num & 0x3; 16185 } else { 16186 map_entry_index = hw_index/16; 16187 eindex = (hw_index % 16) / 4; 16188 } 16189 } else if (level == SOC_TD2_NODE_LVL_L1) { 16190 if (IS_TD2_HSP_PORT(unit, port)) { 16191 if ((hw_index % _BCM_TD2_HSP_PORT_MAX_L1) > 7) { 16192 return BCM_E_UNAVAIL; 16193 } 16194 port_num = hw_index / _BCM_TD2_HSP_PORT_MAX_L1; 16195 soc_cm_get_id_otp(unit, &dev_id, &rev_id); 16196 if ((dev_id == BCM56850_DEVICE_ID) && 16197 (rev_id <= BCM56850_A1_REV_ID)) { 16198 /* A0 & A1: even port takes 2 entries, odd port takes 3 entries. */ 16199 map_entry_index_num = (port_num * 2) + port_num / 2; 16200 if (port_num % 2) { 16201 map_entry_index_num += ((hw_index % 10) + 2) / 4; 16202 } else { 16203 map_entry_index_num += ((hw_index % 10) >= 4)? 1 : 0; 16204 } 16205 } else { 16206 map_entry_index_num = port_num * 2 + 16207 (((hw_index % 10) >= 4)? 1 : 0); 16208 } 16209 map_entry_index = map_entry_index_num / 4; 16210 eindex = map_entry_index_num & 0x3; 16211 } else { 16212 map_entry_index = hw_index/16; 16213 eindex = (hw_index % 16) / 4; 16214 } 16215 } else { 16216 if (hw_index < 1480) { 16217 /* UC queue */ 16218 if (IS_TD2_HSP_PORT(unit, port)) { 16219 if ((hw_index % 10) > 7) { 16220 return BCM_E_UNAVAIL; 16221 } 16222 port_num = hw_index / 10; 16223 map_entry_index_num = port_num * 2 + 16224 (((hw_index % 10) >= 4)? 1 : 0); 16225 map_entry_index = map_entry_index_num / 4; 16226 eindex = map_entry_index_num & 0x3; 16227 } else { 16228 map_entry_index = hw_index/16; 16229 eindex = (hw_index % 16) / 4; 16230 } 16231 } else { 16232 /* MC queue - Index Calculation 16233 * PFC can work only on 8 out of 10 MC queues of each port. 16234 * So in FC_MAP_TBL2, each Port will use only 2 Index(4 Qs each) for 16235 * MC Qs. 16236 * MC queue base starts at 1480, 1480/16 = 92.5 16237 * Hence MC Qs starts at = Map_Tbl2_Idx[92] and Index2. 16238 */ 16239 mcq_offset = hw_index % 1480; 16240 if ((mcq_offset % 10) > 7) { 16241 /* FC support only for Q0-7 */ 16242 return BCM_E_INTERNAL; 16243 } 16244 map_entry_index = hw_index - (mcq_offset * 2 / 10); 16245 map_entry_index /= 16; 16246 eindex = (mcq_offset % 10)/4; 16247 eindex += ((mcq_offset /10) % 2) ? 0 : 2; 16248 } 16249 } 16250 16251 *index = map_entry_index; 16252 *field = eindex; 16253 return BCM_E_NONE; 16254 } 16255 16256 STATIC int 16257 _bcm_td2_map_fc_status_to_node(int unit, int port, _bcm_td2_fc_type_t fct, 16258 int spad_offset, int cosq, uint32 hw_index, int level) 16259 { 16260 int map_entry_index, eindex, pipe, pfc; 16261 uint32 map_entry[SOC_MAX_MEM_WORDS]; 16262 static const soc_field_t self[] = { 16263 SEL0f, SEL1f, SEL2f, SEL3f 16264 }; 16265 static const soc_field_t indexf[] = { 16266 INDEX0f, INDEX1f, INDEX2f, INDEX3f 16267 }; 16268 static const soc_mem_t memx[] = { 16269 INVALIDm, 16270 MMU_INTFI_XPIPE_FC_MAP_TBL0m, 16271 MMU_INTFI_XPIPE_FC_MAP_TBL1m, 16272 MMU_INTFI_XPIPE_FC_MAP_TBL2m 16273 }; 16274 static const soc_mem_t memy[] = { 16275 INVALIDm, 16276 MMU_INTFI_YPIPE_FC_MAP_TBL0m, 16277 MMU_INTFI_YPIPE_FC_MAP_TBL1m, 16278 MMU_INTFI_YPIPE_FC_MAP_TBL2m 16279 }; 16280 soc_mem_t mem; 16281 int port_num = 0; 16282 uint16 dev_id; 16283 uint8 rev_id; 16284 16285 pfc = (fct == _BCM_TD2_COSQ_FC_PFC) ? 1 : 0; 16286 pipe = _BCM_TD2_PORT_TO_PIPE(unit, port); 16287 mem = (pipe == _TD2_XPIPE) ? memx[level] : memy[level]; 16288 if (mem == INVALIDm) { 16289 return BCM_E_PARAM; 16290 } 16291 16292 if (IS_TD2_HSP_PORT(unit, port)) { 16293 port_num = hw_index / 10; 16294 soc_cm_get_id_otp(unit, &dev_id, &rev_id); 16295 if ((dev_id == BCM56850_DEVICE_ID) && 16296 (rev_id <= BCM56850_A1_REV_ID) && 16297 ((level == SOC_TD2_NODE_LVL_L1) || 16298 (level == SOC_TD2_NODE_LVL_L2))) { 16299 if (port_num % 2) { 16300 cosq += 2; 16301 } 16302 } 16303 } 16304 16305 BCM_IF_ERROR_RETURN(_bcm_td2_pfc_map_index_resolve(unit, port, 16306 hw_index, level, &map_entry_index, &eindex)); 16307 BCM_IF_ERROR_RETURN 16308 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, map_entry_index, &map_entry)); 16309 /* coverity[overrun-local : FALSE] */ 16310 soc_mem_field32_set(unit, mem, &map_entry, 16311 indexf[eindex], spad_offset + cosq/4); 16312 /* coverity[overrun-local : FALSE] */ 16313 soc_mem_field32_set(unit, mem, &map_entry, self[eindex], !!pfc); 16314 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, 16315 MEM_BLOCK_ALL, map_entry_index, &map_entry)); 16316 return BCM_E_NONE; 16317 } 16318 16319 /* 16320 * Function: 16321 * _bcm_td2_clear_fc_status_to_node 16322 * Purpose: 16323 * Clear MMU_INTFI_PIPE_FC_MAP_TBL setting of a port. 16324 * Parameters: 16325 * unit - (IN) unit number 16326 * port - (IN) port number 16327 * Returns: 16328 * BCM_E_XXX 16329 */ 16330 STATIC int 16331 _bcm_td2_clear_fc_status_to_node(int unit, int port) 16332 { 16333 uint32 map_entry[SOC_MAX_MEM_WORDS], i_value, s_value; 16334 static const soc_field_t self[] = { 16335 SEL0f, SEL1f, SEL2f, SEL3f 16336 }; 16337 static const soc_field_t indexf[] = { 16338 INDEX0f, INDEX1f, INDEX2f, INDEX3f 16339 }; 16340 static const soc_mem_t memx[] = { 16341 MMU_INTFI_XPIPE_FC_MAP_TBL0m, 16342 MMU_INTFI_XPIPE_FC_MAP_TBL1m, 16343 MMU_INTFI_XPIPE_FC_MAP_TBL2m 16344 }; 16345 static const soc_mem_t memy[] = { 16346 MMU_INTFI_YPIPE_FC_MAP_TBL0m, 16347 MMU_INTFI_YPIPE_FC_MAP_TBL1m, 16348 MMU_INTFI_YPIPE_FC_MAP_TBL2m 16349 }; 16350 static const soc_mem_t *mem; 16351 int base, table, index, count, field; 16352 int mmu_port, phy_port, update; 16353 bcm_port_t local_port; 16354 soc_info_t *si; 16355 16356 BCM_IF_ERROR_RETURN 16357 (_bcm_td2_cosq_localport_resolve(unit, port, &local_port)); 16358 16359 si = &SOC_INFO(unit); 16360 phy_port = si->port_l2p_mapping[local_port]; 16361 mmu_port = si->port_p2m_mapping[phy_port]; 16362 mem = (mmu_port < SOC_TD2_NUM_MMU_PORTS_PER_PIPE)? memx : memy; 16363 16364 base = mmu_port * 4; 16365 for (table = 0; table < COUNTOF(memx); table++) { 16366 count = soc_mem_index_count(unit, mem[table]); 16367 for (index = 0; index < count; index++) { 16368 update = 0; 16369 SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem[table], 16370 MEM_BLOCK_ALL, index, &map_entry)); 16371 for (field = 0; field < COUNTOF(indexf); field++) { 16372 s_value = soc_mem_field32_get(unit, mem[table], 16373 &map_entry, self[field]); 16374 i_value = soc_mem_field32_get(unit, mem[table], 16375 &map_entry, indexf[field]); 16376 if (s_value && (i_value >= base) && (i_value < (base + 4))) { 16377 soc_mem_field32_set(unit, mem[table], 16378 &map_entry, self[field], 0); 16379 soc_mem_field32_set(unit, mem[table], 16380 &map_entry, indexf[field], 0); 16381 update = 1; 16382 } 16383 } 16384 if (update) { 16385 SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem[table], 16386 MEM_BLOCK_ALL, index, &map_entry)); 16387 } 16388 } 16389 } 16390 16391 return BCM_E_NONE; 16392 } 16393 16394 /* 16395 * Function: 16396 * _bcm_td2_fc_status_map_gport 16397 * Purpose: 16398 * Set mapping in FC_MAP_TBL for gport, and update cos_bmp with gport cosq. 16399 * Parameters: 16400 * unit - (IN) unit number 16401 * port - (IN) port number 16402 * gport - (IN) gport to be mapped 16403 * fct - (IN) FC type 16404 * cos_map - (OUT) hw_cosq of gport 16405 * Returns: 16406 * BCM_E_XXX 16407 * Note: 16408 * This function assumes gport has been validated by 16409 * "_bcm_td2_fc_map_gport_check". 16410 */ 16411 STATIC int 16412 _bcm_td2_fc_status_map_gport(int unit, int port, 16413 bcm_gport_t gport, _bcm_td2_fc_type_t fct, uint32 *cos_bmp) 16414 { 16415 int hw_index, hw_index1; 16416 int hw_cosq, hw_cosq1; 16417 int id, lvl; 16418 int pipe, mmu_port, phy_port; 16419 bcm_port_t local_port, resolved_port; 16420 _bcm_td2_cosq_node_t *node; 16421 _bcm_td2_pipe_resources_t *res; 16422 _bcm_td2_cosq_port_info_t *port_info; 16423 soc_info_t *si; 16424 _bcm_td2_mmu_info_t *mmu_info; 16425 16426 BCM_IF_ERROR_RETURN 16427 (_bcm_td2_cosq_localport_resolve(unit, port, &local_port)); 16428 16429 si = &SOC_INFO(unit); 16430 phy_port = si->port_l2p_mapping[local_port]; 16431 mmu_port = si->port_p2m_mapping[phy_port]; 16432 16433 mmu_info = _bcm_td2_mmu_info[unit]; 16434 port_info = &mmu_info->port_info[local_port]; 16435 pipe = _BCM_TD2_PORT_TO_PIPE(unit, local_port); 16436 res = _BCM_TD2_PRESOURCES(mmu_info, pipe); 16437 16438 hw_index = hw_index1 = -1; 16439 hw_cosq = hw_cosq1 = -1; 16440 if (BCM_GPORT_IS_SET(gport)) { 16441 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_node_get(unit, gport, 16442 0, NULL, &resolved_port, &id, &node)); 16443 hw_index = node->hw_index; 16444 hw_cosq = node->hw_cosq; 16445 lvl = node->level; 16446 } else { 16447 if (_bcm_td2_cosq_port_has_ets(unit, local_port)) { 16448 hw_cosq = gport; 16449 node = &res->p_queue_node[port_info->uc_base + hw_cosq]; 16450 hw_index = node->hw_index; 16451 16452 node = &res->p_mc_queue_node[port_info->mc_base + hw_cosq]; 16453 hw_index1 = node->hw_index; 16454 hw_cosq1 = hw_cosq; 16455 lvl = SOC_TD2_NODE_LVL_L2; 16456 } else { 16457 lvl = SOC_TD2_NODE_LVL_L1; 16458 /* gport[] represnts the physical Cos value */ 16459 hw_cosq = gport; 16460 BCM_IF_ERROR_RETURN(soc_td2_sched_hw_index_get(unit, local_port, 16461 SOC_TD2_NODE_LVL_L1, hw_cosq, &hw_index)); 16462 } 16463 } 16464 16465 BCM_IF_ERROR_RETURN( 16466 _bcm_td2_map_fc_status_to_node(unit, local_port, fct, 16467 mmu_port*4, hw_cosq, hw_index, lvl)); 16468 if (cos_bmp != NULL) { 16469 *cos_bmp |= 1 << hw_cosq; 16470 } 16471 16472 if (hw_cosq1 >= 0) { 16473 BCM_IF_ERROR_RETURN( 16474 _bcm_td2_map_fc_status_to_node(unit, local_port, fct, 16475 mmu_port*4, hw_cosq1, hw_index1, lvl)); 16476 if (cos_bmp != NULL) { 16477 *cos_bmp |= 1 << hw_cosq1; 16478 } 16479 } 16480 16481 return BCM_E_NONE; 16482 } 16483 16484 /* 16485 * Function: 16486 * bcm_td2_cosq_default_llfc_profile_attach 16487 * Purpose: 16488 * Add default entries for PRIO2COS_PROFILE register profile 16489 * Parameters: 16490 * unit - (IN) unit number 16491 * port - (IN) port number 16492 * Returns: 16493 * BCM_E_XXX 16494 */ 16495 int 16496 bcm_td2_cosq_default_llfc_profile_attach(int unit, int port) 16497 { 16498 soc_reg_t reg; 16499 soc_info_t *si; 16500 bcm_port_t local_port; 16501 int mmu_port, phy_port; 16502 uint32 profile_index; 16503 uint64 tmp, rval, index_map; 16504 uint64 rval64s[16], *prval64s[1]; 16505 static const soc_reg_t llfc_cfgr[] = { 16506 PORT_PFC_CFG0r, PORT_PFC_CFG1r, PORT_PFC_CFG2r, PORT_PFC_CFG3r 16507 }; 16508 16509 BCM_IF_ERROR_RETURN( 16510 _bcm_td2_cosq_localport_resolve(unit, port, &local_port)); 16511 16512 si = &SOC_INFO(unit); 16513 phy_port = si->port_l2p_mapping[local_port]; 16514 mmu_port = si->port_p2m_mapping[phy_port]; 16515 reg = llfc_cfgr[mmu_port/32]; 16516 16517 /* Add default entries for PRIO2COS_PROFILE register profile */ 16518 sal_memset(rval64s, 0, sizeof(rval64s)); 16519 prval64s[0] = rval64s; 16520 16521 BCM_IF_ERROR_RETURN 16522 (soc_profile_reg_add(unit, _bcm_td2_llfc_profile[unit], 16523 prval64s, 16, &profile_index)); 16524 16525 BCM_IF_ERROR_RETURN(soc_reg64_get(unit, reg, 0, 0, &rval)); 16526 index_map = soc_reg64_field_get(unit, reg, rval, PROFILE_INDEXf); 16527 16528 COMPILER_64_SET(tmp, 0, 3); 16529 COMPILER_64_SHL(tmp, (mmu_port % 32) * 2); 16530 COMPILER_64_NOT(tmp); 16531 COMPILER_64_AND(index_map, tmp); 16532 COMPILER_64_SET(tmp, 0, profile_index/16); 16533 COMPILER_64_SHL(tmp, (mmu_port % 32) * 2); 16534 COMPILER_64_OR(index_map, tmp); 16535 16536 soc_reg64_field_set(unit, reg, &rval, PROFILE_INDEXf, 16537 index_map); 16538 16539 BCM_IF_ERROR_RETURN(soc_reg64_set(unit, reg, 0, 0, rval)); 16540 16541 return BCM_E_NONE; 16542 } 16543 16544 /* 16545 * Function: 16546 * bcm_td2_cosq_llfc_profile_detach 16547 * Purpose: 16548 * Delete old entries for PRIO2COS_PROFILE register profile 16549 * Parameters: 16550 * unit - (IN) unit number 16551 * port - (IN) port number 16552 * Returns: 16553 * BCM_E_XXX 16554 */ 16555 int 16556 bcm_td2_cosq_llfc_profile_detach(int unit, int port) 16557 { 16558 soc_reg_t reg; 16559 bcm_port_t local_port; 16560 int mmu_port, phy_port; 16561 uint32 old_profile_index; 16562 uint32 tmp32; 16563 uint64 rval, index_map; 16564 soc_info_t *si; 16565 static const soc_reg_t llfc_cfgr[] = { 16566 PORT_PFC_CFG0r, PORT_PFC_CFG1r, PORT_PFC_CFG2r, PORT_PFC_CFG3r 16567 }; 16568 16569 BCM_IF_ERROR_RETURN( 16570 _bcm_td2_cosq_localport_resolve(unit, port, &local_port)); 16571 16572 si = &SOC_INFO(unit); 16573 phy_port = si->port_l2p_mapping[local_port]; 16574 mmu_port = si->port_p2m_mapping[phy_port]; 16575 16576 reg = llfc_cfgr[mmu_port/32]; 16577 BCM_IF_ERROR_RETURN(soc_reg64_get(unit, reg, 0, 0, &rval)); 16578 16579 index_map = soc_reg64_field_get(unit, reg, rval, PROFILE_INDEXf); 16580 COMPILER_64_SHR(index_map, ((mmu_port % 32) * 2)); 16581 COMPILER_64_TO_32_LO(tmp32, index_map); 16582 old_profile_index = (tmp32 & 3)*16; 16583 16584 BCM_IF_ERROR_RETURN 16585 (soc_profile_reg_delete(unit, _bcm_td2_llfc_profile[unit], 16586 old_profile_index)); 16587 16588 return BCM_E_NONE; 16589 } 16590 16591 /* 16592 * Function: 16593 * _bcm_td2_port_pfc_profile_set 16594 * Purpose: 16595 * Set PFC mapping profile for port. Updates PRIO2COS_PROFILE & PORT_PFC_CFG. 16596 * Parameters: 16597 * unit - (IN) unit number 16598 * port - (IN) port number 16599 * op - (IN) operation type 16600 * entry_cnt - (IN) count of bmp 16601 * pfc_class - (IN) class list 16602 * cos_bmp - (IN) bmp list 16603 * Returns: 16604 * BCM_E_XXX 16605 */ 16606 STATIC int 16607 _bcm_td2_port_pfc_profile_set(int unit, int port, _bcm_cosq_op_t op, 16608 int entry_cnt, int *pfc_class, uint32 *cos_bmp) 16609 { 16610 soc_reg_t reg; 16611 bcm_port_t local_port; 16612 int rv, entry, cur_class; 16613 int mmu_port, phy_port, p_mmu_port; 16614 uint16 dev_id; 16615 uint8 rev_id; 16616 uint32 profile_index, old_profile_index; 16617 uint32 fval, tmp32, cur_bmp; 16618 uint64 rval64[16], tmp, *rval64s[1], rval, index_map; 16619 soc_info_t *si; 16620 static const soc_reg_t llfc_cfgr[] = { 16621 PORT_PFC_CFG0r, PORT_PFC_CFG1r, PORT_PFC_CFG2r, PORT_PFC_CFG3r 16622 }; 16623 16624 if (pfc_class == NULL) { 16625 return BCM_E_PARAM; 16626 } 16627 if (cos_bmp == NULL) { 16628 return BCM_E_PARAM; 16629 } 16630 if ((entry_cnt < 0 ) || (entry_cnt > _BCM_TD2_NUM_PFC_CLASS)) { 16631 return BCM_E_PARAM; 16632 } 16633 16634 BCM_IF_ERROR_RETURN( 16635 _bcm_td2_cosq_localport_resolve(unit, port, &local_port)); 16636 16637 si = &SOC_INFO(unit); 16638 phy_port = si->port_l2p_mapping[local_port]; 16639 mmu_port = si->port_p2m_mapping[phy_port]; 16640 16641 reg = llfc_cfgr[mmu_port/32]; 16642 rval64s[0] = rval64; 16643 BCM_IF_ERROR_RETURN(soc_reg64_get(unit, reg, 0, 0, &rval)); 16644 16645 index_map = soc_reg64_field_get(unit, reg, rval, PROFILE_INDEXf); 16646 COMPILER_64_SHR(index_map, ((mmu_port % 32) * 2)); 16647 COMPILER_64_TO_32_LO(tmp32, index_map); 16648 old_profile_index = (tmp32 & 3)*16; 16649 BCM_IF_ERROR_RETURN 16650 (soc_profile_reg_get(unit, _bcm_td2_llfc_profile[unit], 16651 old_profile_index, 16, rval64s)); 16652 16653 for (entry = 0; entry < entry_cnt; entry++) { 16654 cur_class = pfc_class[entry]; 16655 cur_bmp = cos_bmp[entry]; 16656 /* A0 & A1: odd HSP port bitmap needs shifting 2 bits to left. */ 16657 if (IS_TD2_HSP_PORT(unit, local_port)) { 16658 soc_cm_get_id_otp(unit, &dev_id, &rev_id); 16659 p_mmu_port = _BCM_TD2_ROOT_SCHED_INDEX(unit, mmu_port); 16660 if ((dev_id == BCM56850_DEVICE_ID) && 16661 (rev_id <= BCM56850_A1_REV_ID) && 16662 (p_mmu_port % 2)) { 16663 cur_bmp = cur_bmp << 2; 16664 } 16665 } 16666 if (op == _BCM_COSQ_OP_SET) { 16667 soc_reg64_field32_set(unit, PRIO2COS_PROFILEr, &rval64[cur_class], 16668 COS_BMPf, cur_bmp); 16669 } else { 16670 if (cur_bmp != 0) { 16671 fval = soc_reg64_field32_get(unit, PRIO2COS_PROFILEr, 16672 rval64[cur_class], COS_BMPf); 16673 if (op == _BCM_COSQ_OP_ADD) { 16674 fval |= cur_bmp; 16675 } else { /* _BCM_COSQ_OP_DELETE */ 16676 fval &= ~cur_bmp; 16677 } 16678 soc_reg64_field32_set(unit, PRIO2COS_PROFILEr, 16679 &rval64[cur_class], COS_BMPf, fval); 16680 } 16681 } 16682 } 16683 16684 BCM_IF_ERROR_RETURN 16685 (soc_profile_reg_delete(unit, _bcm_td2_llfc_profile[unit], 16686 old_profile_index)); 16687 16688 rv = soc_profile_reg_add(unit, _bcm_td2_llfc_profile[unit], rval64s, 16689 16, &profile_index); 16690 if (SOC_FAILURE(rv)) { 16691 BCM_IF_ERROR_RETURN 16692 (soc_profile_reg_reference(unit, _bcm_td2_llfc_profile[unit], 16693 old_profile_index, 16)); 16694 return rv; 16695 } 16696 16697 16698 index_map = soc_reg64_field_get(unit, reg, rval, PROFILE_INDEXf); 16699 16700 COMPILER_64_SET(tmp, 0, 3); 16701 COMPILER_64_SHL(tmp, (mmu_port % 32) * 2); 16702 COMPILER_64_NOT(tmp); 16703 COMPILER_64_AND(index_map, tmp); 16704 COMPILER_64_SET(tmp, 0, profile_index/16); 16705 COMPILER_64_SHL(tmp, (mmu_port % 32) * 2); 16706 COMPILER_64_OR(index_map, tmp); 16707 16708 soc_reg64_field_set(unit, reg, &rval, PROFILE_INDEXf, 16709 index_map); 16710 16711 BCM_IF_ERROR_RETURN(soc_reg64_set(unit, reg, 0, 0, rval)); 16712 16713 return BCM_E_NONE; 16714 } 16715 16716 /* 16717 * Function: 16718 * _bcm_td2_fc_map_gport_check 16719 * Purpose: 16720 * Validate if a gport can be mapped to a port's PFC/FC status. 16721 * Parameters: 16722 * unit - (IN) unit number 16723 * port - (IN) port number 16724 * gport - (IN) gport that will be mapped 16725 * Returns: 16726 * BCM_E_XXX 16727 */ 16728 STATIC int 16729 _bcm_td2_fc_map_gport_check(int unit, 16730 bcm_gport_t port, 16731 bcm_gport_t gport) 16732 { 16733 bcm_port_t local_port = -1, resolved_port; 16734 int hw_cosq, pipe; 16735 _bcm_td2_pipe_resources_t *res; 16736 _bcm_td2_cosq_port_info_t *port_info; 16737 _bcm_td2_mmu_info_t *mmu_info; 16738 _bcm_td2_cosq_node_t *node; 16739 16740 BCM_IF_ERROR_RETURN 16741 (_bcm_td2_cosq_localport_resolve(unit, port, &local_port)); 16742 16743 if (local_port < 0) { 16744 return BCM_E_PORT; 16745 } 16746 16747 mmu_info = _bcm_td2_mmu_info[unit]; 16748 port_info = &mmu_info->port_info[local_port]; 16749 pipe = _BCM_TD2_PORT_TO_PIPE(unit, local_port); 16750 res = _BCM_TD2_PRESOURCES(mmu_info, pipe); 16751 16752 hw_cosq = -1; 16753 if (BCM_GPORT_IS_SET(gport)) { 16754 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_node_get(unit, gport, 16755 0, NULL, &resolved_port, NULL, &node)); 16756 if (!((node->type == _BCM_TD2_NODE_UCAST) || 16757 (node->type == _BCM_TD2_NODE_MCAST) || 16758 (node->type == _BCM_TD2_NODE_SCHEDULER))) { 16759 return BCM_E_PARAM; 16760 } 16761 if ((node->type == _BCM_TD2_NODE_SCHEDULER) && 16762 (node->node_align_value != _BCM_TD2_START_INDEX_ALIGN_PFC) && 16763 (node->level != SOC_TD2_NODE_LVL_ROOT)) { 16764 LOG_ERROR(BSL_LS_BCM_COSQ, 16765 (BSL_META_U(unit, 16766 "Gport without BCM_COSQ_GPORT_SCHEDULER_PFC_ALIGN!\n"))); 16767 return BCM_E_PARAM; 16768 } 16769 if (resolved_port != local_port) { 16770 return BCM_E_PARAM; 16771 } 16772 hw_cosq = node->hw_cosq; 16773 } else { 16774 hw_cosq = gport; 16775 if (_bcm_td2_cosq_port_has_ets(unit, local_port)) { 16776 node = &res->p_queue_node[port_info->uc_base + hw_cosq]; 16777 if ((!node->in_use) || (node->attached_to_input == -1)) { 16778 return BCM_E_PARAM; 16779 } 16780 node = &res->p_mc_queue_node[port_info->mc_base + hw_cosq]; 16781 if ((!node->in_use) || (node->attached_to_input == -1)) { 16782 return BCM_E_PARAM; 16783 } 16784 } 16785 } 16786 if ((hw_cosq < 0) || (hw_cosq >= _TD2_NUM_INTERNAL_PRI)) { 16787 return BCM_E_PARAM; 16788 } 16789 16790 return BCM_E_NONE; 16791 } 16792 16793 /* 16794 * Function: 16795 * _bcm_td2_pfc_class_mapping_check 16796 * Purpose: 16797 * Validate param of bcm_cosq_pfc_class_mapping_t. 16798 * Parameters: 16799 * unit - (IN) unit number 16800 * port - (IN) port number 16801 * array_count - (IN) count of mapping array 16802 * mapping_array - (IN) mapping array list 16803 * Returns: 16804 * BCM_E_XXX 16805 */ 16806 STATIC int 16807 _bcm_td2_pfc_class_mapping_check(int unit, 16808 bcm_gport_t port, 16809 int array_count, 16810 bcm_cosq_pfc_class_mapping_t *mapping_array) 16811 { 16812 int count, index, cur_class; 16813 bcm_gport_t cur_gport = 0; 16814 16815 if (mapping_array == NULL) { 16816 return BCM_E_PARAM; 16817 } 16818 16819 for (count = 0; count < array_count; count++) { 16820 cur_class = mapping_array[count].class_id; 16821 if ((cur_class < 0) || (cur_class >= _BCM_TD2_NUM_PFC_CLASS)) { 16822 return BCM_E_PARAM; 16823 } 16824 16825 for (index = 0; index < BCM_COSQ_PFC_GPORT_COUNT; index++) { 16826 cur_gport = mapping_array[count].gport_list[index]; 16827 if (cur_gport == BCM_GPORT_INVALID) { 16828 break; 16829 } 16830 BCM_IF_ERROR_RETURN(_bcm_td2_fc_map_gport_check(unit, 16831 port, cur_gport)); 16832 } 16833 } 16834 16835 return BCM_E_NONE; 16836 } 16837 16838 int 16839 bcm_td2_cosq_port_pfc_op(int unit, bcm_port_t port, 16840 bcm_switch_control_t sctype, _bcm_cosq_op_t op, 16841 bcm_gport_t *gport, int gport_count) 16842 { 16843 int type, class = -1, index; 16844 uint32 cos_bmp; 16845 _bcm_td2_fc_type_t fct; 16846 16847 if (gport_count < 0) { 16848 return BCM_E_PARAM; 16849 } 16850 for (index = 0; index < gport_count; index++) { 16851 BCM_IF_ERROR_RETURN(_bcm_td2_fc_map_gport_check(unit, 16852 port, gport[index])); 16853 } 16854 16855 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_pfc_class_resolve(sctype, &type, &class)); 16856 16857 cos_bmp = 0; 16858 fct = (op == _BCM_COSQ_OP_CLEAR)? 0 : _BCM_TD2_COSQ_FC_PFC; 16859 for (index = 0; index < gport_count; index++) { 16860 BCM_IF_ERROR_RETURN( 16861 _bcm_td2_fc_status_map_gport(unit, port, gport[index], 16862 fct, &cos_bmp)); 16863 } 16864 16865 if (op == _BCM_COSQ_OP_CLEAR) { 16866 cos_bmp = (1 << _TD2_NUM_INTERNAL_PRI) - 1; 16867 } 16868 16869 BCM_IF_ERROR_RETURN(_bcm_td2_port_pfc_profile_set(unit, port, op, 16870 1, &class, &cos_bmp)); 16871 16872 return BCM_E_NONE; 16873 } 16874 16875 int 16876 bcm_td2_cosq_port_pfc_get(int unit, bcm_port_t port, 16877 bcm_switch_control_t sctype, 16878 bcm_gport_t *gport, int gport_count, 16879 int *actual_gport_count) 16880 { 16881 _bcm_td2_cosq_node_t *node; 16882 bcm_port_t local_port; 16883 int type = -1, class = -1, hw_cosq, count = 0; 16884 uint32 profile_index; 16885 uint64 rval64[16], *rval64s[1], rval, index_map; 16886 uint32 tmp32, bmp, bmp_len; 16887 _bcm_td2_mmu_info_t *mmu_info; 16888 int phy_port, mmu_port, p_mmu_port; 16889 soc_info_t *si; 16890 soc_reg_t reg; 16891 _bcm_td2_pipe_resources_t *res; 16892 _bcm_td2_cosq_port_info_t *port_info; 16893 static const soc_reg_t llfc_cfgr[] = { 16894 PORT_PFC_CFG0r, PORT_PFC_CFG1r, PORT_PFC_CFG2r, PORT_PFC_CFG3r 16895 }; 16896 static const soc_field_t self[] = { 16897 SEL0f, SEL1f, SEL2f, SEL3f 16898 }; 16899 int j, finished = 0, hw_index, pipe, eindex; 16900 soc_mem_t mem; 16901 uint32 map_entry[SOC_MAX_MEM_WORDS]; 16902 uint16 dev_id; 16903 uint8 rev_id; 16904 16905 if (IS_CPU_PORT(unit, port)) { 16906 return BCM_E_PORT; 16907 } 16908 16909 if ((gport == NULL) && (gport_count > 0)) { 16910 return BCM_E_PARAM; 16911 } 16912 16913 if (actual_gport_count == NULL) { 16914 return BCM_E_PARAM; 16915 } 16916 16917 BCM_IF_ERROR_RETURN 16918 (_bcm_td2_cosq_localport_resolve(unit, port, &local_port)); 16919 16920 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_pfc_class_resolve(sctype, &type, &class)); 16921 16922 si = &SOC_INFO(unit); 16923 mmu_info = _bcm_td2_mmu_info[unit]; 16924 pipe = _BCM_TD2_PORT_TO_PIPE(unit, local_port); 16925 res = _BCM_TD2_PRESOURCES(mmu_info, pipe); 16926 phy_port = si->port_l2p_mapping[local_port]; 16927 mmu_port = si->port_p2m_mapping[phy_port]; 16928 port_info = &mmu_info->port_info[local_port]; 16929 16930 rval64s[0] = rval64; 16931 reg = llfc_cfgr[mmu_port/32]; 16932 BCM_IF_ERROR_RETURN(soc_reg64_get(unit, reg, REG_PORT_ANY, 0, &rval)); 16933 16934 index_map = soc_reg64_field_get(unit, reg, rval, PROFILE_INDEXf); 16935 COMPILER_64_SHR(index_map, ((mmu_port % 32) * 2)); 16936 COMPILER_64_TO_32_LO(tmp32, index_map); 16937 profile_index = (tmp32 & 3)*16; 16938 16939 BCM_IF_ERROR_RETURN 16940 (soc_profile_reg_get(unit, _bcm_td2_llfc_profile[unit], 16941 profile_index, 16, rval64s)); 16942 16943 bmp = soc_reg64_field32_get(unit, PRIO2COS_PROFILEr, rval64[class], 16944 COS_BMPf); 16945 bmp_len = soc_reg_field_length(unit, PRIO2COS_PROFILEr, COS_BMPf); 16946 /* A0 & A1: odd HSP port bitmap has been shifted 2 bits to left. */ 16947 if (IS_TD2_HSP_PORT(unit, port)) { 16948 soc_cm_get_id_otp(unit, &dev_id, &rev_id); 16949 p_mmu_port = _BCM_TD2_ROOT_SCHED_INDEX(unit, mmu_port); 16950 if ((dev_id == BCM56850_DEVICE_ID) && 16951 (rev_id <= BCM56850_A1_REV_ID) && 16952 (p_mmu_port % 2)) { 16953 bmp = bmp >> 2; 16954 } 16955 } 16956 for (hw_cosq = 0; hw_cosq < bmp_len; hw_cosq++) { 16957 if (!(bmp & (1 << hw_cosq))) { 16958 continue; 16959 } 16960 if (_bcm_td2_cosq_port_has_ets(unit, local_port)) { 16961 for (j = _BCM_TD2_NUM_PORT_SCHEDULERS; 16962 j < _BCM_TD2_NUM_TOTAL_SCHEDULERS; j++) { 16963 node = &mmu_info->sched_node[j]; 16964 if ((!node->in_use) || (node->local_port != local_port) || 16965 (node->hw_cosq != hw_cosq)) { 16966 continue; 16967 } 16968 16969 if (node->level == SOC_TD2_NODE_LVL_L0) { 16970 mem = (pipe == _TD2_XPIPE) ? MMU_INTFI_XPIPE_FC_MAP_TBL0m : 16971 MMU_INTFI_YPIPE_FC_MAP_TBL0m; 16972 } else if (node->level == SOC_TD2_NODE_LVL_L1) { 16973 mem = (pipe == _TD2_XPIPE) ? MMU_INTFI_XPIPE_FC_MAP_TBL1m : 16974 MMU_INTFI_YPIPE_FC_MAP_TBL1m; 16975 } else { 16976 continue; 16977 } 16978 BCM_IF_ERROR_RETURN(_bcm_td2_pfc_map_index_resolve(unit, port, 16979 node->hw_index, node->level, &hw_index, &eindex)); 16980 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, 16981 MEM_BLOCK_ALL, hw_index, &map_entry)); 16982 16983 if (soc_mem_field32_get(unit, mem, &map_entry, self[eindex])) { 16984 if (gport_count > 0) { 16985 gport[count] = node->gport; 16986 } 16987 count++; 16988 if ((count == gport_count) && (gport_count > 0)) { 16989 finished = 1; 16990 break; 16991 } 16992 } 16993 } 16994 16995 for (j = port_info->uc_base; 16996 (finished == 0) && (j < port_info->uc_limit); j++) { 16997 node = &res->p_queue_node[j]; 16998 if ((!node->in_use) || (node->local_port != local_port)) { 16999 continue; 17000 } 17001 if (node->hw_cosq != hw_cosq) { 17002 continue; 17003 } 17004 mem = (pipe == _TD2_XPIPE) ? MMU_INTFI_XPIPE_FC_MAP_TBL2m : 17005 MMU_INTFI_YPIPE_FC_MAP_TBL2m; 17006 BCM_IF_ERROR_RETURN(_bcm_td2_pfc_map_index_resolve(unit, port, 17007 node->hw_index, node->level, &hw_index, &eindex)); 17008 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, 17009 MEM_BLOCK_ALL, hw_index, &map_entry)); 17010 17011 if (soc_mem_field32_get(unit, mem, &map_entry, self[eindex])) { 17012 if (gport_count > 0) { 17013 gport[count] = node->gport; 17014 } 17015 count++; 17016 if ((count == gport_count) && (gport_count > 0)) { 17017 finished = 1; 17018 break; 17019 } 17020 } 17021 } 17022 for (j = port_info->mc_base; 17023 (finished == 0) && (j < port_info->mc_limit); j++) { 17024 node = &res->p_mc_queue_node[j]; 17025 if ((!node->in_use) || (node->local_port != local_port)) { 17026 continue; 17027 } 17028 if (node->hw_cosq != hw_cosq) { 17029 continue; 17030 } 17031 mem = (pipe == _TD2_XPIPE) ? MMU_INTFI_XPIPE_FC_MAP_TBL2m : 17032 MMU_INTFI_YPIPE_FC_MAP_TBL2m; 17033 BCM_IF_ERROR_RETURN(_bcm_td2_pfc_map_index_resolve(unit, port, 17034 node->hw_index, node->level, &hw_index, &eindex)); 17035 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, 17036 MEM_BLOCK_ALL, hw_index, &map_entry)); 17037 /* coverity[overrun-local : FALSE] */ 17038 if (soc_mem_field32_get(unit, mem, &map_entry, self[eindex])) { 17039 if (gport_count > 0) { 17040 gport[count] = node->gport; 17041 } 17042 count++; 17043 if ((count == gport_count) && (gport_count > 0)) { 17044 break; 17045 } 17046 } 17047 } 17048 } else { 17049 if (gport_count > 0) { 17050 gport[count] = hw_cosq; 17051 } 17052 count++; 17053 } 17054 if ((count == gport_count) && (gport_count > 0)) { 17055 break; 17056 } 17057 } 17058 17059 if (count == 0) { 17060 return BCM_E_NOT_FOUND; 17061 } 17062 *actual_gport_count = count; 17063 return BCM_E_NONE; 17064 } 17065 17066 /* 17067 * Function: 17068 * bcm_td2_cosq_pfc_class_mapping_set 17069 * Purpose: 17070 * Set PFC mapping for port. PFC class is mapped to cosq or scheduler node gports. 17071 * Parameters: 17072 * unit - (IN) unit number 17073 * port - (IN) port number 17074 * array_count - (IN) count of mapping 17075 * mapping_array - (IN) mappings 17076 * Returns: 17077 * BCM_E_XXX 17078 */ 17079 int 17080 bcm_td2_cosq_pfc_class_mapping_set(int unit, 17081 bcm_gport_t port, 17082 int array_count, 17083 bcm_cosq_pfc_class_mapping_t *mapping_array) 17084 { 17085 int index, count; 17086 int cur_class = 0, pfc_class[_BCM_TD2_NUM_PFC_CLASS]; 17087 bcm_gport_t cur_gport = 0; 17088 uint32 cos_bmp[_BCM_TD2_NUM_PFC_CLASS]; 17089 17090 17091 if ((array_count < 0) || (array_count > _BCM_TD2_NUM_PFC_CLASS)) { 17092 return BCM_E_PARAM; 17093 } 17094 if (mapping_array == NULL) { 17095 return BCM_E_PARAM; 17096 } 17097 BCM_IF_ERROR_RETURN(_bcm_td2_pfc_class_mapping_check(unit, port, 17098 array_count, mapping_array)); 17099 17100 (void) _bcm_td2_clear_fc_status_to_node(unit, port); 17101 sal_memset(cos_bmp, 0, sizeof(cos_bmp)); 17102 for (count = 0; count < array_count; count++) { 17103 cur_class = mapping_array[count].class_id; 17104 17105 for (index = 0; index < BCM_COSQ_PFC_GPORT_COUNT; index++) { 17106 cur_gport = mapping_array[count].gport_list[index]; 17107 if (cur_gport == BCM_GPORT_INVALID) { 17108 break; 17109 } 17110 17111 BCM_IF_ERROR_RETURN(_bcm_td2_fc_status_map_gport(unit, port, 17112 cur_gport, _BCM_TD2_COSQ_FC_PFC, &cos_bmp[cur_class])); 17113 } 17114 } 17115 17116 for (index = 0; index < _BCM_TD2_NUM_PFC_CLASS; index++) { 17117 pfc_class[index] = index; 17118 } 17119 BCM_IF_ERROR_RETURN(_bcm_td2_port_pfc_profile_set(unit, port, 17120 _BCM_COSQ_OP_SET, _BCM_TD2_NUM_PFC_CLASS, pfc_class, cos_bmp)); 17121 17122 return BCM_E_NONE; 17123 } 17124 17125 /* 17126 * Function: 17127 * bcm_td2_cosq_pfc_class_mapping_get 17128 * Purpose: 17129 * Get PFC mapping for port. 17130 * Retrieves cosq or scheduler node gports 17131 * associated to PFC classes. 17132 * Parameters: 17133 * unit - (IN) unit number 17134 * port - (IN) port number 17135 * array_max - (IN) max retrieve count 17136 * mapping_array - (OUT) mappings 17137 * array_count - (OUT) retrieved mapping count 17138 * Returns: 17139 * BCM_E_XXX 17140 */ 17141 int 17142 bcm_td2_cosq_pfc_class_mapping_get(int unit, 17143 bcm_gport_t port, 17144 int array_max, 17145 bcm_cosq_pfc_class_mapping_t *mapping_array, 17146 int *array_count) 17147 { 17148 int rv = 0; 17149 int cur_class = 0; 17150 int actual_gport_count, class_count = 0; 17151 bcm_switch_control_t sc[] = { bcmSwitchPFCClass0Queue, 17152 bcmSwitchPFCClass1Queue, 17153 bcmSwitchPFCClass2Queue, 17154 bcmSwitchPFCClass3Queue, 17155 bcmSwitchPFCClass4Queue, 17156 bcmSwitchPFCClass5Queue, 17157 bcmSwitchPFCClass6Queue, 17158 bcmSwitchPFCClass7Queue 17159 }; 17160 17161 if ((mapping_array == NULL) && (array_max > 0)) { 17162 return BCM_E_PARAM; 17163 } 17164 if (array_count == NULL) { 17165 return BCM_E_PARAM; 17166 } 17167 17168 for (cur_class = 0; cur_class < _BCM_TD2_NUM_PFC_CLASS; cur_class++) { 17169 actual_gport_count = 0; 17170 if (array_max > 0) { 17171 rv = bcm_td2_cosq_port_pfc_get(unit, port, sc[cur_class], 17172 mapping_array[class_count].gport_list, 17173 BCM_COSQ_PFC_GPORT_COUNT, &actual_gport_count); 17174 } else { 17175 rv = bcm_td2_cosq_port_pfc_get(unit, port, sc[cur_class], 17176 NULL, -1, &actual_gport_count); 17177 } 17178 if (rv == BCM_E_NONE) { 17179 if (array_max > 0) { 17180 mapping_array[class_count].class_id = cur_class; 17181 if (actual_gport_count < BCM_COSQ_PFC_GPORT_COUNT) { 17182 mapping_array[class_count].gport_list[actual_gport_count] = 17183 BCM_GPORT_INVALID; 17184 } 17185 } 17186 class_count++; 17187 } else if (rv != BCM_E_NOT_FOUND) { 17188 return rv; 17189 } 17190 17191 if ((class_count == array_max) && (array_max > 0)) { 17192 break; 17193 } 17194 } 17195 17196 *array_count = class_count; 17197 if (class_count == 0) { 17198 return BCM_E_NOT_FOUND; 17199 } 17200 17201 return BCM_E_NONE; 17202 } 17203 17204 /* 17205 * Function: 17206 * bcm_td2_port_priority_group_mapping_set 17207 * Purpose: 17208 * Assign a Priority Group for the input priority. 17209 * Parameters: 17210 * unit - (IN) device id. 17211 * gport - (IN) generic port. 17212 * prio - (IN) input priority. 17213 * priority_group - (IN) PG ID that the input priority mapped to. 17214 * Returns: 17215 * BCM_E_XXX 17216 */ 17217 int 17218 bcm_td2_port_priority_group_mapping_set(int unit, bcm_gport_t gport, 17219 int prio, int priority_group) 17220 { 17221 bcm_port_t port; 17222 uint32 value; 17223 int field_count; 17224 soc_field_t fields_0[]={PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf, 17225 PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf}; 17226 soc_field_t fields_1[]={PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf, 17227 PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf}; 17228 17229 if (!soc_feature(unit, soc_feature_priority_flow_control)) { 17230 return BCM_E_UNAVAIL; 17231 } 17232 /* PFC : 0-7, SAFC : 0-15. Taking the larger range for comparison */ 17233 if ((prio < TD2_SAFC_INPUT_PRIORITY_MIN) || 17234 (prio > TD2_SAFC_INPUT_PRIORITY_MAX)) { 17235 return BCM_E_PARAM; 17236 } 17237 17238 if ((priority_group < TD2_PRIOROTY_GROUP_ID_MIN) || 17239 (priority_group > TD2_PRIOROTY_GROUP_ID_MAX)) { 17240 return BCM_E_PARAM; 17241 } 17242 17243 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_localport_resolve(unit, gport, &port)); 17244 if (!SOC_PORT_VALID(unit, port)) { 17245 return BCM_E_PORT; 17246 } 17247 field_count = COUNTOF(fields_0); 17248 if (prio < field_count) { 17249 /* input priority 0~7 */ 17250 BCM_IF_ERROR_RETURN(READ_THDI_PORT_PRI_GRP0r(unit, port, &value)); 17251 soc_reg_field_set(unit, THDI_PORT_PRI_GRP0r, &value, 17252 fields_0[prio], priority_group); 17253 BCM_IF_ERROR_RETURN(WRITE_THDI_PORT_PRI_GRP0r(unit, port, value)); 17254 } else { 17255 /* input priority 8~15 */ 17256 BCM_IF_ERROR_RETURN(READ_THDI_PORT_PRI_GRP1r(unit, port, &value)); 17257 soc_reg_field_set(unit, THDI_PORT_PRI_GRP1r, &value, 17258 fields_1[prio - field_count], priority_group); 17259 BCM_IF_ERROR_RETURN(WRITE_THDI_PORT_PRI_GRP1r(unit, port, value)); 17260 } 17261 17262 return BCM_E_NONE; 17263 } 17264 17265 /* 17266 * Function: 17267 * bcm_td2_port_priority_group_mapping_get 17268 * Purpose: 17269 * Get the assigned Priority Group ID of the input priority. 17270 * Parameters: 17271 * unit - (IN) device id. 17272 * gport - (IN) generic port. 17273 * prio - (IN) input priority. 17274 * priority_group - (OUT) PG ID that the input priority mapped to. 17275 * Returns: 17276 * BCM_E_XXX 17277 */ 17278 int 17279 bcm_td2_port_priority_group_mapping_get(int unit, bcm_gport_t gport, 17280 int prio, int *priority_group) 17281 { 17282 bcm_port_t port; 17283 uint32 value; 17284 int field_count; 17285 soc_field_t fields_0[]={PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf, 17286 PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf}; 17287 soc_field_t fields_1[]={PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf, 17288 PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf}; 17289 17290 if (!soc_feature(unit, soc_feature_priority_flow_control)) { 17291 return BCM_E_UNAVAIL; 17292 } 17293 if (priority_group == NULL) { 17294 return BCM_E_PARAM; 17295 } 17296 /* PFC : 0-7, SAFC : 0-15. Taking the larger range for comparison */ 17297 if ((prio < TD2_SAFC_INPUT_PRIORITY_MIN) || 17298 (prio > TD2_SAFC_INPUT_PRIORITY_MAX)) { 17299 return BCM_E_PARAM; 17300 } 17301 17302 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_localport_resolve(unit, gport, &port)); 17303 if (!SOC_PORT_VALID(unit, port)) { 17304 return BCM_E_PORT; 17305 } 17306 field_count = COUNTOF(fields_0); 17307 if (prio < field_count) { 17308 /* input priority 0~7 */ 17309 BCM_IF_ERROR_RETURN(READ_THDI_PORT_PRI_GRP0r(unit, port, &value)); 17310 *priority_group = soc_reg_field_get(unit, THDI_PORT_PRI_GRP0r, 17311 value, fields_0[prio]); 17312 } else { 17313 /* input priority 8~15 */ 17314 BCM_IF_ERROR_RETURN(READ_THDI_PORT_PRI_GRP1r(unit, port, &value)); 17315 *priority_group = soc_reg_field_get(unit, THDI_PORT_PRI_GRP1r, 17316 value, 17317 fields_1[prio - field_count]); 17318 } 17319 17320 return BCM_E_NONE; 17321 } 17322 17323 /* 17324 * Function: 17325 * bcm_td2_port_priority_group_config_set 17326 * Purpose: 17327 * Set the port priority group configuration. 17328 * Parameters: 17329 * unit - (IN) device id. 17330 * gport - (IN) generic port. 17331 * priority_group - (IN) priority group id. 17332 * prigrp_config - (IN) structure describes port PG configuration. 17333 * Returns: 17334 * BCM_E_XXX 17335 */ 17336 int 17337 bcm_td2_port_priority_group_config_set(int unit, bcm_gport_t gport, 17338 int priority_group, bcm_port_priority_group_config_t *prigrp_config) 17339 { 17340 bcm_port_t port; 17341 uint32 rval, pri_bmp; 17342 17343 if (!soc_feature(unit, soc_feature_priority_flow_control)) { 17344 return BCM_E_UNAVAIL; 17345 } 17346 if ((priority_group < TD2_PRIOROTY_GROUP_ID_MIN) || 17347 (priority_group > TD2_PRIOROTY_GROUP_ID_MAX)) { 17348 return BCM_E_PARAM; 17349 } 17350 if (prigrp_config == NULL) { 17351 return BCM_E_PARAM; 17352 } 17353 if (prigrp_config->shared_pool_xoff_enable || 17354 prigrp_config->shared_pool_discard_enable || 17355 prigrp_config->priority_enable_vector_mask) { 17356 return BCM_E_UNAVAIL; 17357 } 17358 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_localport_resolve(unit, gport, &port)); 17359 if (!SOC_PORT_VALID(unit, port)) { 17360 return BCM_E_PORT; 17361 } 17362 17363 SOC_IF_ERROR_RETURN(READ_THDI_INPUT_PORT_XON_ENABLESr(unit, port, &rval)); 17364 pri_bmp = soc_reg_field_get(unit, THDI_INPUT_PORT_XON_ENABLESr, rval, 17365 PORT_PRI_XON_ENABLEf); 17366 17367 if (prigrp_config->pfc_transmit_enable) { 17368 pri_bmp |= (1 << priority_group); 17369 } else { 17370 pri_bmp &= ~(1 << priority_group); 17371 } 17372 /* To cover higher 8 PFC classes that have no corresponding PG. */ 17373 if ((pri_bmp & 0xff) == 0) { 17374 pri_bmp = 0; 17375 } 17376 17377 BCM_IF_ERROR_RETURN(_bcm_sc_tr_port_pfc_tx_set(unit, port, pri_bmp)); 17378 17379 return BCM_E_NONE; 17380 } 17381 17382 /* 17383 * Function: 17384 * bcm_td2_port_priority_group_config_get 17385 * Purpose: 17386 * Get the port priority group configuration. 17387 * Parameters: 17388 * unit - (IN) device id. 17389 * gport - (IN) generic port. 17390 * priority_group - (IN) priority group id. 17391 * prigrp_config - (OUT) structure describes port PG configuration. 17392 * Returns: 17393 * BCM_E_XXX 17394 */ 17395 int 17396 bcm_td2_port_priority_group_config_get(int unit, bcm_gport_t gport, 17397 int priority_group, bcm_port_priority_group_config_t *prigrp_config) 17398 { 17399 bcm_port_t port; 17400 uint32 rval, pri_bmp; 17401 17402 if (!soc_feature(unit, soc_feature_priority_flow_control)) { 17403 return BCM_E_UNAVAIL; 17404 } 17405 if ((priority_group < TD2_PRIOROTY_GROUP_ID_MIN) || 17406 (priority_group > TD2_PRIOROTY_GROUP_ID_MAX)) { 17407 return BCM_E_PARAM; 17408 } 17409 if (prigrp_config == NULL) { 17410 return BCM_E_PARAM; 17411 } 17412 17413 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_localport_resolve(unit, gport, &port)); 17414 if (!SOC_PORT_VALID(unit, port)) { 17415 return BCM_E_PORT; 17416 } 17417 17418 SOC_IF_ERROR_RETURN(READ_THDI_INPUT_PORT_XON_ENABLESr(unit, port, &rval)); 17419 pri_bmp = soc_reg_field_get(unit, THDI_INPUT_PORT_XON_ENABLESr, rval, 17420 PORT_PRI_XON_ENABLEf); 17421 if (pri_bmp & (1U << priority_group)) { 17422 prigrp_config->pfc_transmit_enable = 1; 17423 } else { 17424 prigrp_config->pfc_transmit_enable = 0; 17425 } 17426 17427 return BCM_E_NONE; 17428 } 17429 17430 /* 17431 * Function: 17432 * bcm_td2p_cosq_subport_flow_control_set 17433 * Purpose: 17434 * Set a port or node (L0, L1, L2) to flow control when 17435 * a CoE control frame is received on a subtended port. 17436 * Parameters: 17437 * unit - (IN) Unit number. 17438 * subport - (IN) Subtended port 17439 * sched_port - (IN) Node (Port, L0, L1, L2) to flow control 17440 * Returns: 17441 * BCM_E_xxx 17442 * Notes: 17443 */ 17444 int 17445 bcm_td2p_cosq_subport_flow_control_set( 17446 int unit, 17447 bcm_gport_t subport, 17448 bcm_gport_t sched_port) 17449 { 17450 #ifdef BCM_HGPROXY_COE_SUPPORT 17451 uint16 coe_fc_index, row, column; 17452 uint32 rval; 17453 bcm_gport_t subport_id, resolved_port; 17454 _bcm_td2_cosq_node_t *node; 17455 int hw_index, rv, pipe; 17456 soc_td2_node_lvl_e level; 17457 subport_tag_sgpp_map_entry_t entry; 17458 bcm_port_t phy_port, mmu_port; 17459 soc_info_t *si; 17460 _bcm_td2_fc_type_t fct; 17461 17462 /* Find subport id from port to index into SUBPORT_TAG_SGPP_MAP */ 17463 BCM_IF_ERROR_RETURN(_bcmi_coe_subport_tcam_idx_get(unit, subport, &subport_id)); 17464 17465 /* From sched_port, need to find if it's port, L0, L1, or L2 */ 17466 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_node_get(unit, sched_port, 0, NULL, NULL, NULL, &node)); 17467 17468 /* Port, L0, L1, or L2 from node */ 17469 level = node->level; 17470 17471 /* index into L0, L1, or L2 */ 17472 hw_index = node->hw_index; 17473 17474 /* Get the port associated with the passed in gport */ 17475 BCM_IF_ERROR_RETURN 17476 (_bcm_td2_cosq_localport_resolve(unit, sched_port, &resolved_port)); 17477 if (resolved_port < 0) { 17478 return BCM_E_PORT; 17479 } 17480 17481 pipe = _BCM_TD2_PORT_TO_PIPE(unit, resolved_port); 17482 17483 17484 si = &SOC_INFO(unit); 17485 17486 /* Getting MMU port. Used to disable cut through for it at the end as well as 17487 to index into MMU_INTFI_PORT_COEFC_TB if we're setting flow control for port */ 17488 phy_port = si->port_l2p_mapping[resolved_port]; 17489 mmu_port = si->port_p2m_mapping[phy_port]; 17490 17491 if (IS_TD2_HSP_PORT( unit, resolved_port )) { 17492 /* SC/QM L1/L2 nodes do not support FC. 17493 * Hence, L1/L2 indices 8, 9, 18, 19 ... should not be configured 17494 * for FC. 17495 * similarly the last L0 of the HSP port does not support flow control 17496 */ 17497 if (level == SOC_TD2_NODE_LVL_L0) { 17498 if ((hw_index % 5) > 3) { 17499 return BCM_E_PARAM; 17500 } 17501 column = hw_index % 5; 17502 } else { 17503 if ((hw_index % 10) > 7) { 17504 return BCM_E_PARAM; 17505 } 17506 column = ((hw_index % 10) % 4); 17507 } 17508 } else { 17509 column = hw_index % 4 ; 17510 } 17511 17512 /* Checking valid reference to address for each entry of FC_STATE tables per 17513 MMU - INTFI Table 1-9. We also need to offset the hw_index properly per pipe. 17514 We are dividing the FC STATE tables in half with the X Pipe taking the lower half 17515 and the Y Pipe taking the upper half, hence 134/2, 256/2, 1024/2. */ 17516 switch(level) { 17517 case SOC_TD2_NODE_LVL_ROOT: 17518 /* At the port level we have to do it a bit different since it's indexing into 17519 MMU_INTFI_PORT_COEFC_TB, which is a 128 entry x 1 bit table with each entry signifying 17520 an MMU Port, so we need to use the MMU Port number as the row. Column we don't care 17521 for. */ 17522 row = mmu_port; 17523 column = 0; 17524 17525 if ( (row > 52 && row < 64) || (row > 116) ) { 17526 return BCM_E_PARAM; 17527 } 17528 break; 17529 case SOC_TD2_NODE_LVL_L0: 17530 if (IS_TD2_HSP_PORT( unit, resolved_port )) { 17531 /* The last L0 does not support FC and so each index in fc_st_tbl represents 17532 * 5 l0 nodes instead of 4 the last 1 is masked by the hardware 17533 */ 17534 row = hw_index / 5; 17535 } else { 17536 row = hw_index / 4; 17537 } 17538 17539 if(pipe == _TD2_YPIPE) { 17540 row += 134/2; 17541 } 17542 if (row > 133) { 17543 return BCM_E_PARAM; 17544 } 17545 break; 17546 case SOC_TD2_NODE_LVL_L1: 17547 17548 if (IS_TD2_HSP_PORT( unit, resolved_port )) { 17549 /* FC not supported on last two L1/L2 nodes The hardware internally adjusts the value 17550 * say index 24 which for non hsp port will result in index 6 will result in 5 for HSP 17551 */ 17552 row = mmu_port * 2 + 17553 (((hw_index % 10) >= 4)? 1 : 0); 17554 } else { 17555 row = hw_index / 4; 17556 } 17557 if(pipe == _TD2_YPIPE) { 17558 row += 512/2; 17559 } 17560 if (row > 511) { 17561 return BCM_E_PARAM; 17562 } 17563 17564 break; 17565 case SOC_TD2_NODE_LVL_L2: 17566 if (IS_TD2_HSP_PORT( unit, resolved_port )) { 17567 /* FC not supported on last two L1/L2 nodes The hardware internally adjusts the value 17568 * say index 24 which for non hsp port will result in index 6 will result in 5 for HSP 17569 */ 17570 row = mmu_port * 2 + 17571 (((hw_index % 10) >= 4)? 1 : 0); 17572 } else { 17573 row = hw_index / 4; 17574 } 17575 if(pipe == _TD2_YPIPE) { 17576 row += 1024/2; 17577 } 17578 if (row > 1023) { 17579 return BCM_E_PARAM; 17580 } 17581 break; 17582 default: 17583 return BCM_E_PARAM; 17584 17585 } 17586 17587 /* Column is only 4 bits wide */ 17588 if (column > 3) { 17589 return BCM_E_PARAM; 17590 } 17591 17592 /* set coe_fc_index for us to program into the register */ 17593 coe_fc_index = (row << 5) | /* row bits 15:5 */ 17594 (column << 2) | /* column bits 4:2 */ 17595 (level); /* type bits 1:0 */ 17596 17597 /* Program SUBPORT_TAG_SGPP_MAP with the subport as the index and 17598 COE_FC_INDEX as the data */ 17599 rv = READ_SUBPORT_TAG_SGPP_MAPm(unit, 17600 MEM_BLOCK_ANY, subport_id, &entry); 17601 if (SOC_SUCCESS(rv)) { 17602 soc_SUBPORT_TAG_SGPP_MAPm_field32_set(unit, 17603 (uint32 *)&entry, COE_FC_INDEXf, coe_fc_index); 17604 } 17605 WRITE_SUBPORT_TAG_SGPP_MAPm(unit, MEM_BLOCK_ANY, subport_id, &entry); 17606 17607 /* Program FC Map Table to select FC State Table (vs PFC State Table) for the node */ 17608 fct = _BCM_TD2_COSQ_FC_E2ECC; 17609 17610 /* To pass the proper FC STATE Table entries, we're modifying the FC MAP Table, one of its 17611 4 indexes, with the appropriate row in the FC STATE Table. FC MAP Table at index 0 17612 will handle the rows 0-3 of FC STATE Table, at index 1 will handle rows 4-7 of the 17613 FC STATE Table, and so on. 17614 17615 resolved_port is passed so that the function will know which pipe to use (X or Y). 17616 fct will select FC STATE Table on the mux so that PFC STATE Table won't be selected. 17617 row is passed in this first time so that a proper row index for the FC STATE Table will be selected. 17618 node->hw_index is passed in because the proper FC MAP Table index will be calculated. 17619 node->level is passed in so that the function will know with FC MAP Table (L0, L1, L2) to use. 17620 */ 17621 if(level != SOC_TD2_NODE_LVL_ROOT) { 17622 BCM_IF_ERROR_RETURN(_bcm_td2_map_fc_status_to_node(unit, resolved_port, fct, row, 17623 0, node->hw_index, node->level)); 17624 } 17625 17626 /* Disable Cut-Through for the port specified or L0/L1/L2 node associated with it */ 17627 BCM_IF_ERROR_RETURN(READ_ASF_PORT_CFGr(unit, mmu_port, &rval)); 17628 soc_reg_field_set(unit, ASF_PORT_CFGr, &rval, UC_ASF_ENABLEf, 0); 17629 soc_reg_field_set(unit, ASF_PORT_CFGr, &rval, MC_ASF_ENABLEf, 0); 17630 BCM_IF_ERROR_RETURN(WRITE_ASF_PORT_CFGr(unit, mmu_port, rval)); 17631 17632 return BCM_E_NONE; 17633 #else 17634 return BCM_E_UNAVAIL; 17635 #endif /* BCM_HGPROXY_COE_SUPPORT */ 17636 } 17637 17638 int 17639 bcm_td2p_cosq_subport_flow_control_get( 17640 int unit, 17641 bcm_gport_t subport, 17642 bcm_gport_t * sched_port) 17643 { 17644 #ifdef BCM_HGPROXY_COE_SUPPORT 17645 int row, column, level, hw_index, i, temp_pipe, coe_fc_index = 0; 17646 int pipe = _TD2_XPIPE; 17647 bcm_gport_t subport_id; 17648 _bcm_td2_cosq_node_t * node; 17649 _bcm_td2_mmu_info_t * mmu_info; 17650 subport_tag_sgpp_map_entry_t entry; 17651 17652 int resolved_port = 0; 17653 int mmu_port = 0; 17654 int phy_port = 0; 17655 soc_info_t *si; 17656 17657 /* Find subport id from port to index into SUBPORT_TAG_SGPP_MAP */ 17658 BCM_IF_ERROR_RETURN(_bcmi_coe_subport_tcam_idx_get(unit, subport, &subport_id)); 17659 17660 BCM_IF_ERROR_RETURN( 17661 _bcmi_coe_subport_physical_port_get(unit, subport, &resolved_port)); 17662 si = &SOC_INFO(unit); 17663 /* Getting MMU port. Used to disable cut through for it at the end as well as 17664 to index into MMU_INTFI_PORT_COEFC_TB if we're setting flow control for port */ 17665 phy_port = si->port_l2p_mapping[resolved_port]; 17666 mmu_port = si->port_p2m_mapping[phy_port]; 17667 17668 BCM_IF_ERROR_RETURN(READ_SUBPORT_TAG_SGPP_MAPm(unit, 17669 MEM_BLOCK_ANY, subport_id, &entry)); 17670 coe_fc_index = soc_SUBPORT_TAG_SGPP_MAPm_field32_get(unit, 17671 (uint32 *)&entry, COE_FC_INDEXf); 17672 17673 level = coe_fc_index & 0x3; 17674 column = (coe_fc_index >> 2) & 0x7; 17675 row = (coe_fc_index >> 5); 17676 17677 /* Get the proper row to calculate hw_index because this could be in either pipe. 17678 We are dividing the FC STATE tables in half with the X Pipe taking the lower half 17679 and the Y Pipe taking the upper half, hence 134/2, 256/2, 1024/2. */ 17680 switch(level) { 17681 case SOC_TD2_NODE_LVL_ROOT: 17682 if(row >= 64) { 17683 row -= 64; 17684 pipe = _TD2_YPIPE; 17685 } 17686 17687 hw_index = row; 17688 17689 break; 17690 case SOC_TD2_NODE_LVL_L0: 17691 if(row >= 134/2) { 17692 pipe = _TD2_YPIPE; 17693 row -= 134/2; 17694 } 17695 if (row > 133) { 17696 return BCM_E_PARAM; 17697 } 17698 17699 if (IS_TD2_HSP_PORT( unit, resolved_port )) { 17700 hw_index = row * 5 + column ; 17701 } else { 17702 hw_index = row * 4 + column ; 17703 } 17704 17705 break; 17706 case SOC_TD2_NODE_LVL_L1: 17707 if(row >= 512/2) { 17708 pipe = _TD2_YPIPE; 17709 row -= 512/2; 17710 } 17711 if (row > 511) { 17712 return BCM_E_PARAM; 17713 } 17714 /* FC not supported on last two L1/L2 nodes The hardware internally adjusts the value 17715 * say index 24 which for non hsp port will result in index 6 will result in 5 for HSP 17716 */ 17717 if (IS_TD2_HSP_PORT( unit, resolved_port )) { 17718 hw_index = ((mmu_port%_TD2_PORTS_PER_PIPE) * 10) + ((row % 2)? 4: 0) + column ; 17719 } else { 17720 hw_index = row * 4 + column ; 17721 } 17722 break; 17723 case SOC_TD2_NODE_LVL_L2: 17724 if(row >= 1024/2) { 17725 pipe = _TD2_YPIPE; 17726 row -= 1024/2; 17727 } 17728 if (row > 1023) { 17729 return BCM_E_PARAM; 17730 } 17731 17732 /* FC not supported on last two L1/L2 nodes The hardware internally adjusts the value 17733 * say index 24 which for non hsp port will result in index 6 will result in 5 for HSP 17734 */ 17735 if (IS_TD2_HSP_PORT( unit, resolved_port )) { 17736 hw_index = ((mmu_port%_TD2_PORTS_PER_PIPE) * 10) + ((row % 2)? 4: 0) + column ; 17737 } else { 17738 hw_index = row * 4 + column ; 17739 } 17740 break; 17741 /* 17742 * COVERITY 17743 * 17744 * This default is unreachable but needed for some compiler. 17745 */ 17746 /* coverity[dead_error_begin] */ 17747 default: 17748 return BCM_E_PARAM; 17749 17750 } 17751 17752 mmu_info = _bcm_td2_mmu_info[unit]; 17753 17754 if (!mmu_info) { 17755 return BCM_E_INIT; 17756 } 17757 17758 /* Fetch the node based upon level and hw_index */ 17759 switch(level) { 17760 /* port, L0, and L1 are all scheduling nodes */ 17761 case SOC_TD2_NODE_LVL_ROOT: 17762 case SOC_TD2_NODE_LVL_L0: 17763 case SOC_TD2_NODE_LVL_L1: 17764 for(i = 0; i < _BCM_TD2_NUM_TOTAL_SCHEDULERS; i++) { 17765 node = &mmu_info->sched_node[i]; 17766 if(node->level == level) { 17767 if(node->hw_index == hw_index) { 17768 /* if the hw_index matches, check the pipe. Must pass in local port */ 17769 temp_pipe = _BCM_TD2_PORT_TO_PIPE(unit, node->local_port); 17770 17771 /* if the pipe matches too, we've found the associated gport */ 17772 if(pipe == temp_pipe) { 17773 *sched_port = node->gport; 17774 return BCM_E_NONE; 17775 } 17776 } 17777 } 17778 } 17779 break; 17780 case SOC_TD2_NODE_LVL_L2: 17781 for(i = 0; i < _BCM_TD2_NUM_L2_UC_LEAVES; i++) { 17782 node = &mmu_info->queue_node[i]; 17783 if(node->level == level) { 17784 if(node->hw_index == hw_index) { 17785 /* if the hw_index matches, check the pipe */ 17786 temp_pipe = _BCM_TD2_PORT_TO_PIPE(unit, node->local_port); 17787 17788 /* if the pipe matches too, we've found the associated gport */ 17789 if(pipe == temp_pipe) { 17790 *sched_port = node->gport; 17791 return BCM_E_NONE; 17792 } 17793 } 17794 } 17795 } 17796 break; 17797 /* Intentional process */ 17798 /* coverity[dead_error_begin] */ 17799 default: 17800 return BCM_E_PARAM; 17801 17802 } 17803 17804 /* not found */ 17805 return BCM_E_PARAM; 17806 #else 17807 return BCM_E_UNAVAIL; 17808 #endif /* BCM_HGPROXY_COE_SUPPORT */ 17809 } 17810 17811 int 17812 bcm_td2_cosq_drop_status_enable_set(int unit, bcm_port_t port, int enable) 17813 { 17814 _bcm_td2_mmu_info_t *mmu_info; 17815 soc_info_t *si; 17816 int count, idx, pipe, base; 17817 uint32 rval; 17818 _bcm_td2_cosq_node_t *node; 17819 _bcm_td2_pipe_resources_t *res; 17820 soc_mem_t mem; 17821 soc_reg_t reg; 17822 uint32 entry[SOC_MAX_MEM_WORDS]; 17823 uint32 e2ecc_ds_config; 17824 #ifdef BCM_TRIDENT2PLUS_SUPPORT 17825 uint32 qgroup_valid; 17826 #endif 17827 17828 if ((mmu_info = _bcm_td2_mmu_info[unit]) == NULL) { 17829 return BCM_E_INIT; 17830 } 17831 17832 si = &SOC_INFO(unit); 17833 17834 mem = SOC_TD2_PMEM(unit, port, MMU_THDM_DB_QUEUE_CONFIG_0m, 17835 MMU_THDM_DB_QUEUE_CONFIG_1m); 17836 reg = SOC_TD2_PREG(unit, port, MMU_THDM_DB_QUEUE_E2E_DS_EN_0r, 17837 MMU_THDM_DB_QUEUE_E2E_DS_EN_1r); 17838 17839 17840 count = si->port_num_cosq[port]; 17841 SOC_IF_ERROR_RETURN(_bcm_td2_cosq_index_resolve 17842 (unit, port, 0, _BCM_TD2_COSQ_INDEX_STYLE_MCAST_QUEUE, 17843 &port, &base, NULL)); 17844 17845 for (idx = 0; idx < count; idx++) { 17846 if ( SOC_REG_IS_VALID(unit, reg) ) { 17847 SOC_IF_ERROR_RETURN ( 17848 soc_reg_field32_modify(unit, reg, port, 17849 Q_COS_E2E_DS_ENf, enable)); 17850 } else { 17851 SOC_IF_ERROR_RETURN ( 17852 soc_mem_field32_modify(unit, mem, base + idx - 1480, 17853 Q_E2E_DS_ENf, enable)); 17854 } 17855 } 17856 17857 mem = SOC_TD2_PMEM(unit, port, MMU_THDU_XPIPE_Q_TO_QGRP_MAPm, 17858 MMU_THDU_YPIPE_Q_TO_QGRP_MAPm); 17859 SOC_IF_ERROR_RETURN(_bcm_td2_cosq_index_resolve 17860 (unit, port, 0, _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE, 17861 &port, &base, NULL)); 17862 count = si->port_num_uc_cosq[port]; 17863 for (idx = 0; idx < count; idx++) { 17864 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, base + idx, entry)); 17865 soc_mem_field32_set(unit, mem, entry, Q_E2E_DS_EN_CELLf, !!enable); 17866 e2ecc_ds_config = 1; 17867 #ifdef BCM_TRIDENT2PLUS_SUPPORT 17868 if (SOC_IS_TRIDENT2PLUS(unit)) { 17869 if (IS_TD2_HSP_PORT(unit, port)) { 17870 qgroup_valid = soc_mem_field32_get(unit, mem, entry, QGROUP_VALIDf); 17871 if ((idx < 8) && (qgroup_valid == 0)) { 17872 /* If HSP port does not use qgroup for its lower 8 queues */ 17873 e2ecc_ds_config = 2; 17874 } 17875 } 17876 } 17877 #endif 17878 soc_mem_field32_set(unit, mem, entry, Q_E2ECC_DS_CONFIGf, e2ecc_ds_config); 17879 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, base + idx, entry)); 17880 } 17881 17882 pipe = _BCM_TD2_PORT_TO_PIPE(unit, port); 17883 res = _BCM_TD2_PRESOURCES(mmu_info, pipe); 17884 for (idx = res->num_base_queues; idx < _BCM_TD2_NUM_L2_UC_LEAVES; idx++) { 17885 node = &res->p_queue_node[idx]; 17886 if ((node->in_use == TRUE) && (node->local_port == port)) { 17887 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, node->hw_index, entry)); 17888 soc_mem_field32_set(unit, mem, entry, Q_E2E_DS_EN_CELLf, !!enable); 17889 soc_mem_field32_set(unit, mem, entry, Q_E2ECC_DS_CONFIGf, 1); 17890 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, node->hw_index, entry)); 17891 } 17892 } 17893 17894 BCM_IF_ERROR_RETURN(READ_OP_THDU_CONFIGr(unit, &rval)); 17895 soc_reg_field_set(unit, OP_THDU_CONFIGr, &rval, EARLY_E2E_SELECTf, 17896 enable ? 1 : 0); 17897 BCM_IF_ERROR_RETURN(WRITE_OP_THDU_CONFIGr(unit, rval)); 17898 17899 return BCM_E_NONE; 17900 } 17901 17902 STATIC int 17903 _bcm_td2_voq_min_hw_index(int unit, bcm_port_t port, 17904 bcm_module_t modid, 17905 bcm_port_t remote_port, 17906 int *q_offset) 17907 { 17908 int i, hw_index_base = -1, pipe; 17909 _bcm_td2_cosq_node_t *node; 17910 _bcm_td2_pipe_resources_t *res; 17911 _bcm_td2_mmu_info_t *mmu_info; 17912 int qmin, qmax; 17913 17914 mmu_info = _bcm_td2_mmu_info[unit]; 17915 pipe = _BCM_TD2_PORT_TO_PIPE(unit, port); 17916 res = _BCM_TD2_PRESOURCES(mmu_info, pipe); 17917 qmin = res->num_base_queues + (pipe * _BCM_TD2_NUM_L2_UC_LEAVES_PER_PIPE); 17918 qmax = (pipe + 1) * _BCM_TD2_NUM_L2_UC_LEAVES_PER_PIPE; 17919 17920 for (i = qmin; i < qmax; i++) { 17921 node = &res->p_queue_node[i]; 17922 if ((node->in_use == FALSE) || (node->hw_index == -1)) { 17923 continue; 17924 } 17925 17926 if (((modid == -1) ? 1 : (node->remote_modid == modid)) && 17927 (node->remote_port == remote_port) && 17928 ((port == -1) ? 1 : (port == node->local_port))) { 17929 if (hw_index_base == -1) { 17930 hw_index_base = node->hw_index; 17931 break; 17932 } 17933 } 17934 } 17935 17936 if (hw_index_base != -1) { 17937 *q_offset = hw_index_base & ~7; 17938 return BCM_E_NONE; 17939 } 17940 17941 return BCM_E_NOT_FOUND; 17942 } 17943 17944 STATIC int 17945 _bcm_td2_voq_base_node_get(int unit, bcm_port_t port, 17946 int modid, 17947 _bcm_td2_cosq_node_t **base_node) 17948 { 17949 int i, pipe; 17950 _bcm_td2_pipe_resources_t *res; 17951 _bcm_td2_mmu_info_t *mmu_info; 17952 _bcm_td2_cosq_node_t *node; 17953 int qmin, qmax; 17954 17955 mmu_info = _bcm_td2_mmu_info[unit]; 17956 pipe = _BCM_TD2_PORT_TO_PIPE(unit, port); 17957 for (pipe = _TD2_XPIPE ; pipe < _TD2_NUM_PIPES ; pipe++) { 17958 res = _BCM_TD2_PRESOURCES(mmu_info, pipe); 17959 qmin = res->num_base_queues + (pipe * _BCM_TD2_NUM_L2_UC_LEAVES_PER_PIPE); 17960 qmax = (pipe + 1) * _BCM_TD2_NUM_L2_UC_LEAVES_PER_PIPE; 17961 for ( i = qmin; 17962 i < qmax ; i++) { 17963 node = &res->p_queue_node[i]; 17964 if ((node->in_use == FALSE) || (node->hw_index == -1)) { 17965 continue; 17966 } 17967 if (node->remote_modid == modid) { 17968 *base_node = node ; 17969 break; 17970 } 17971 } 17972 } 17973 return BCM_E_NONE; 17974 } 17975 17976 STATIC int 17977 _bcm_td2_voq_next_base_node_get(int unit, bcm_port_t port, 17978 int modid, 17979 _bcm_td2_cosq_node_t **base_node) 17980 { 17981 int i, pipe, qmin, qmax; 17982 _bcm_td2_pipe_resources_t *res; 17983 _bcm_td2_mmu_info_t *mmu_info; 17984 _bcm_td2_cosq_node_t *node; 17985 int found = FALSE; 17986 17987 mmu_info = _bcm_td2_mmu_info[unit]; 17988 pipe = _BCM_TD2_PORT_TO_PIPE(unit, port); 17989 for (pipe = _TD2_XPIPE ; pipe < _TD2_NUM_PIPES ; pipe++) { 17990 res = _BCM_TD2_PRESOURCES(mmu_info, pipe); 17991 qmin = res->num_base_queues + (pipe * _BCM_TD2_NUM_L2_UC_LEAVES_PER_PIPE); 17992 qmax = (pipe + 1) * _BCM_TD2_NUM_L2_UC_LEAVES_PER_PIPE; 17993 for ( i = qmin ; 17994 i < qmax ; i++) { 17995 node = &res->p_queue_node[i]; 17996 if ((node->in_use == FALSE) || (node->hw_index == -1)) { 17997 continue; 17998 } 17999 if (node->remote_modid == modid) { 18000 if ( found == TRUE) { 18001 *base_node = node; 18002 break; 18003 } 18004 found = TRUE; 18005 } 18006 } 18007 } 18008 return BCM_E_NONE; 18009 } 18010 18011 STATIC int 18012 _bcm_td2_port_voq_base_set(int unit, bcm_port_t local_port, int base) 18013 { 18014 uint64 rval; 18015 int pipe; 18016 18017 pipe = _BCM_TD2_PORT_TO_PIPE(unit, local_port); 18018 BCM_IF_ERROR_RETURN(READ_ING_COS_MODE_64r(unit, local_port, &rval)); 18019 soc_reg64_field32_set(unit, ING_COS_MODE_64r, &rval, BASE_QUEUE_NUM_1f, 18020 pipe == _TD2_XPIPE ? base : base + 2048); 18021 BCM_IF_ERROR_RETURN(WRITE_ING_COS_MODE_64r(unit, local_port, rval)); 18022 return BCM_E_NONE; 18023 } 18024 18025 STATIC int 18026 _bcm_td2_port_voq_base_get(int unit, bcm_port_t local_port, int *base) 18027 { 18028 uint64 rval; 18029 int pipe; 18030 18031 pipe = _BCM_TD2_PORT_TO_PIPE(unit, local_port); 18032 BCM_IF_ERROR_RETURN(READ_ING_COS_MODE_64r(unit, local_port, &rval)); 18033 if (soc_reg64_field32_get(unit, ING_COS_MODE_64r, rval, QUEUE_MODEf) == 1) { 18034 *base = soc_reg64_field32_get(unit, ING_COS_MODE_64r, rval, 18035 BASE_QUEUE_NUM_1f); 18036 if (pipe == _TD2_YPIPE) { 18037 *base -= 2048; 18038 } 18039 18040 return BCM_E_NONE; 18041 } 18042 18043 BCM_IF_ERROR_RETURN( 18044 _bcm_td2_voq_min_hw_index(unit, local_port, -1, -1, base)); 18045 18046 return BCM_E_NONE; 18047 } 18048 18049 STATIC int 18050 _bcm_td2_resolve_dmvoq_hw_index(int unit, _bcm_td2_cosq_node_t *node, 18051 int cosq, bcm_module_t modid, bcm_port_t local_port) 18052 { 18053 int try, preffered_offset = -1, alloc_size; 18054 int from_offset, max_offset, port, rv, q_base, port_voq_base, pipe; 18055 _bcm_td2_pipe_resources_t *res; 18056 _bcm_td2_mmu_info_t *mmu_info; 18057 18058 mmu_info = _bcm_td2_mmu_info[unit]; 18059 pipe = _BCM_TD2_PORT_TO_PIPE(unit, local_port); 18060 res = _BCM_TD2_PRESOURCES(mmu_info, pipe); 18061 18062 from_offset = res->num_base_queues + 18063 (pipe * _BCM_TD2_NUM_L2_UC_LEAVES_PER_PIPE); 18064 max_offset = (pipe + 1) * _BCM_TD2_NUM_L2_UC_LEAVES_PER_PIPE; 18065 alloc_size = _TD2_NUM_COS(unit); 18066 18067 for (try = 0; try < 2; try++) { 18068 PBMP_HG_ITER(unit, port) { 18069 if ((try == 1) && (port == local_port)) { 18070 continue; 18071 } 18072 18073 if ((try == 0) && (port != local_port)) { 18074 continue; 18075 } 18076 18077 rv = _bcm_td2_voq_min_hw_index(unit, port, modid, -1, &q_base); 18078 if (!rv) { 18079 if (port == local_port) { 18080 /* Found VOQ for the same port/dest modid */ 18081 node->hw_index = q_base + cosq; 18082 return BCM_E_NONE; 18083 } else if (modid == -1) { 18084 rv = _bcm_td2_port_voq_base_get(unit, port, &port_voq_base); 18085 if (rv) { 18086 continue; 18087 } 18088 preffered_offset = q_base - port_voq_base; 18089 rv = _bcm_td2_port_voq_base_get(unit, local_port, 18090 &port_voq_base); 18091 if (rv) { 18092 /* No VOQ on the port yet */ 18093 alloc_size += preffered_offset; 18094 } else { 18095 /* port has already VOQs */ 18096 from_offset = port_voq_base + preffered_offset; 18097 } 18098 break; 18099 } 18100 } 18101 } 18102 if (preffered_offset != -1) { 18103 break; 18104 } 18105 } 18106 if (modid == -1) { 18107 /* Alloc hw index. */ 18108 rv = _bcm_td2_node_index_get(res->ext_qlist.bits, 18109 from_offset, max_offset, 18110 alloc_size, _TD2_NUM_COS(unit), &q_base); 18111 if (rv) { 18112 return BCM_E_RESOURCE; 18113 } 18114 18115 if (_bcm_td2_port_voq_base_get(unit, local_port, &port_voq_base)) { 18116 _bcm_td2_port_voq_base_set(unit, local_port, q_base); 18117 } 18118 q_base = q_base + alloc_size - _TD2_NUM_COS(unit); 18119 node->hw_index = q_base + cosq; 18120 node->hw_cosq = node->hw_index % _TD2_NUM_COS(unit); 18121 node->remote_modid = modid; 18122 _bcm_td2_node_index_set(&res->ext_qlist, q_base, _TD2_NUM_COS(unit)); 18123 } else { 18124 _bcm_td2_port_voq_base_set(unit, local_port, node->hw_index); 18125 node->remote_modid = modid; 18126 rv = BCM_E_NONE; 18127 } 18128 return rv; 18129 } 18130 18131 typedef struct _bcm_td2_voq_info_s { 18132 int valid; 18133 _bcm_td2_cosq_node_t *node; 18134 bcm_module_t remote_modid; 18135 bcm_port_t remote_port; 18136 bcm_port_t local_port; 18137 int hw_cosq; 18138 int hw_index; 18139 } _bcm_td2_voq_info_t; 18140 18141 STATIC int 18142 _bcm_td2_cosq_sort_voq_list(void *a, void *b) 18143 { 18144 _bcm_td2_voq_info_t *va, *vb; 18145 int sa, sb; 18146 18147 va = (_bcm_td2_voq_info_t*)a; 18148 vb = (_bcm_td2_voq_info_t*)b; 18149 18150 sa = (va->remote_modid << 19) | (va->remote_port << 11) | 18151 (va->local_port << 3) | (va->hw_cosq); 18152 18153 sb = (vb->remote_modid << 19) | (vb->remote_port << 11) | 18154 (vb->local_port << 3) | (vb->hw_cosq); 18155 18156 return sa - sb; 18157 } 18158 18159 STATIC int 18160 _bcm_td2_get_queue_skip_count_on_cos(uint32 cbmp, int cur_cos, int next_cos) 18161 { 18162 int i,skip = 0; 18163 18164 if ((next_cos >= 4) && (cur_cos/4 != next_cos/4)) { 18165 cur_cos = -1; 18166 next_cos -= 4; 18167 } 18168 18169 for (i = cur_cos + 1; i < next_cos; i++) { 18170 if (cbmp & (1 << i)) { 18171 skip += 1; 18172 } 18173 } 18174 return skip; 18175 } 18176 18177 STATIC int 18178 _bcm_td2_msg_buf_get(int unit, bcm_port_t srcid) 18179 { 18180 int ii, hole = -1; 18181 uint32 rval, csrc; 18182 18183 for (ii = 0; ii < 16; ii++) { 18184 BCM_IF_ERROR_RETURN(READ_BUF_CFGr(unit, ii, &rval)); 18185 if (srcid == (csrc = soc_reg_field_get(unit, BUF_CFGr, rval, SRC_IDf))) { 18186 return ii; 18187 } 18188 if ((hole == -1) && (csrc == 0)) { 18189 hole = ii; 18190 } 18191 } 18192 18193 if (hole == -1) { 18194 return BCM_E_RESOURCE; 18195 } 18196 18197 rval = 0; 18198 soc_reg_field_set(unit, BUF_CFGr, &rval, SRC_IDf, srcid); 18199 BCM_IF_ERROR_RETURN(WRITE_BUF_CFGr(unit, hole, rval)); 18200 18201 return hole; 18202 } 18203 18204 STATIC int 18205 _bcm_td2_gport_dpvoq_config_set(int unit, bcm_gport_t gport, 18206 bcm_cos_queue_t cosq, 18207 bcm_module_t remote_modid, 18208 bcm_port_t remote_port) 18209 { 18210 uint32 profile = 0xFFFFFFFF; 18211 _bcm_td2_cosq_node_t *node; 18212 bcm_port_t local_port; 18213 uint32 cng_offset; 18214 uint8 cbmp = 0, nib_cbmp = 0; 18215 _bcm_td2_mmu_info_t *mmu_info; 18216 _bcm_td2_voq_info_t *plist = NULL, *vlist = NULL; 18217 int pcount, ii, vcount = 0; 18218 voq_port_map_entry_t *voq_port_map_entries = NULL; 18219 int rv = BCM_E_NONE, mod_base = 0, num_cos = 0, dm = -1, eq_base; 18220 voq_mod_map_entry_t voq_mod_map; 18221 void *entries[1]; 18222 int cng_bytes_per_e2ecc_msg = 32; 18223 int p2ioff[64], ioff, port, skip, *dm2off, count, pipe; 18224 _bcm_td2_pipe_resources_t *res; 18225 18226 if ((cosq < 0) || (cosq > _TD2_NUM_COS(unit))) { 18227 return BCM_E_PARAM; 18228 } 18229 18230 if ((mmu_info = _bcm_td2_mmu_info[unit]) == NULL) { 18231 return BCM_E_INIT; 18232 } 18233 18234 BCM_IF_ERROR_RETURN 18235 (_bcm_td2_cosq_node_get(unit, gport, 0, NULL, &local_port, NULL, &node)); 18236 18237 pipe = _BCM_TD2_PORT_TO_PIPE(unit, local_port); 18238 res = _BCM_TD2_PRESOURCES(mmu_info, pipe); 18239 18240 eq_base = (res->num_base_queues + 7) & ~7; 18241 18242 node->remote_modid = remote_modid; 18243 node->remote_port = remote_port; 18244 node->hw_cosq = cosq; 18245 18246 dm2off = sal_alloc(sizeof(int) * 256, "voq_vlist"); 18247 if (!dm2off) { 18248 return BCM_E_MEMORY; 18249 } 18250 sal_memset(dm2off, 0, sizeof(int)*256); 18251 18252 /* alloc temp vlist */ 18253 vlist = sal_alloc(sizeof(_bcm_td2_voq_info_t) * 1480, "voq_vlist"); 18254 if (!vlist) { 18255 sal_free(dm2off); 18256 return BCM_E_MEMORY; 18257 } 18258 sal_memset(vlist, 0, sizeof(_bcm_td2_voq_info_t)*1480); 18259 18260 for (ii = 0; ii < _BCM_TD2_NUM_L2_UC_LEAVES; ii++) { 18261 node = &res->p_queue_node[ii]; 18262 if ((node->remote_modid == -1) || (node->remote_port == -1)) { 18263 continue; 18264 } 18265 vlist[vcount].remote_modid = node->remote_modid; 18266 vlist[vcount].remote_port = node->remote_port; 18267 vlist[vcount].local_port = node->local_port; 18268 vlist[vcount].hw_cosq = node->hw_cosq; 18269 vlist[vcount].node = node; 18270 vcount += 1; 18271 } 18272 18273 /* Sort the nodes */ 18274 _shr_sort(vlist, vcount, sizeof(_bcm_td2_voq_info_t), 18275 _bcm_td2_cosq_sort_voq_list); 18276 18277 for (ii = 0; ii < 64; ii++) { 18278 p2ioff[ii] = -1; 18279 } 18280 18281 PBMP_HG_ITER(unit, port) { 18282 ioff = _bcm_td2_msg_buf_get(unit, port); 18283 p2ioff[port] = ioff; 18284 } 18285 18286 for (ii = 0; ii < vcount; ii++) { 18287 cbmp |= 1 << vlist[ii].hw_cosq; 18288 } 18289 18290 nib_cbmp = (cbmp >> 4) | (cbmp & 0xf); 18291 18292 for (ii = 0; ii < 4; ii++) { 18293 if ((1 << ii) & nib_cbmp) { 18294 num_cos += 1; 18295 } 18296 } 18297 18298 for (count = 1, ii = 0; ii < vcount; ii++) { 18299 if (dm2off[vlist[ii].remote_modid]==0) { 18300 dm2off[vlist[ii].remote_modid] = count; 18301 } 18302 } 18303 18304 plist = sal_alloc(sizeof(_bcm_td2_voq_info_t) * 1480, "voq_vlist"); 18305 if (!plist) { 18306 sal_free(dm2off); 18307 sal_free(vlist); 18308 return BCM_E_MEMORY; 18309 } 18310 sal_memset(plist, 0, sizeof(_bcm_td2_voq_info_t)*1480); 18311 18312 for (pcount = 0, ii = 0; ii < vcount; ii++) { 18313 if (pcount % 4) { 18314 if ((plist[pcount - 1].remote_modid != vlist[ii].remote_modid) || 18315 (plist[pcount - 1].remote_port != vlist[ii].remote_port)) { 18316 pcount = (pcount + 3) & ~3; 18317 } else if (plist[pcount - 1].local_port != vlist[ii].local_port) { 18318 skip = (p2ioff[vlist[ii].local_port] - 18319 p2ioff[plist[pcount - 1].local_port] - 1) * num_cos; 18320 skip += _bcm_td2_get_queue_skip_count_on_cos(nib_cbmp, 18321 plist[pcount - 1].hw_cosq, 18322 vlist[ii].hw_cosq); 18323 if (skip >= 4) { 18324 pcount = ((pcount + 3) & ~3) + (skip % 4); 18325 } else { 18326 pcount += skip; 18327 } 18328 } else if ((vlist[ii].hw_cosq - plist[pcount - 1].hw_cosq) > 1) { 18329 if (plist[pcount - 1].hw_cosq/4 != vlist[ii].hw_cosq/4) { 18330 pcount = (pcount + 3) & ~3; 18331 } 18332 pcount += _bcm_td2_get_queue_skip_count_on_cos(nib_cbmp, 18333 plist[pcount - 1].hw_cosq, 18334 vlist[ii].hw_cosq); 18335 } 18336 } else { 18337 pcount += _bcm_td2_get_queue_skip_count_on_cos(nib_cbmp, -1, 18338 vlist[ii].hw_cosq); 18339 } 18340 18341 plist[pcount].valid = 1; 18342 plist[pcount].local_port = vlist[ii].local_port; 18343 plist[pcount].remote_modid = vlist[ii].remote_modid; 18344 plist[pcount].remote_port = vlist[ii].remote_port; 18345 plist[pcount].hw_cosq = vlist[ii].hw_cosq; 18346 plist[pcount].node = vlist[ii].node; 18347 vlist[ii].node->hw_index = pcount + eq_base; 18348 18349 #ifdef DEBUG_TD2_COSQ 18350 LOG_CLI((BSL_META_U(unit, 18351 "DPVOQ DM=%d DP=%d LocalPort=%d COS=%d HWIndex=%d\n"), 18352 plist[pcount].remote_modid, 18353 plist[pcount].remote_port, 18354 plist[pcount].local_port, 18355 plist[pcount].hw_cosq, 18356 plist[pcount].node->hw_index)); 18357 #endif 18358 pcount += 1; 18359 } 18360 18361 /* program the voq port profiles. */ 18362 voq_port_map_entries = sal_alloc(sizeof(voq_port_map_entry_t)*128, 18363 "voq port map entries"); 18364 if (!voq_port_map_entries) { 18365 goto fail; 18366 } 18367 sal_memset(voq_port_map_entries, 0, sizeof(voq_port_map_entry_t)*128); 18368 18369 entries[0] = voq_port_map_entries; 18370 dm = -1; 18371 for (ii = 0; ii <= pcount; ii++) { 18372 if ((ii == pcount) || 18373 ((dm != -1) && (plist[ii - 1].remote_modid != dm))) { 18374 18375 rv = READ_VOQ_MOD_MAPm(unit, MEM_BLOCK_ALL, dm, &voq_mod_map); 18376 if (rv) { 18377 goto fail; 18378 } 18379 if (soc_mem_field32_get(unit, VOQ_MOD_MAPm, 18380 &voq_mod_map, VOQ_VALIDf)) { 18381 profile = soc_mem_field32_get(unit, VOQ_MOD_MAPm, 18382 &voq_mod_map, VOQ_MOD_PORT_PROFILE_INDEXf); 18383 18384 rv = soc_profile_mem_delete(unit, 18385 _bcm_td2_voq_port_map_profile[unit], profile*128); 18386 if (rv) { 18387 goto fail; 18388 } 18389 } 18390 rv = soc_profile_mem_add(unit, 18391 _bcm_td2_voq_port_map_profile[unit], 18392 entries, 128, &profile); 18393 if (rv) { 18394 goto fail; 18395 } 18396 18397 soc_mem_field32_set(unit, VOQ_MOD_MAPm, &voq_mod_map, 18398 VOQ_MOD_PORT_PROFILE_INDEXf, profile/128); 18399 soc_mem_field32_set(unit, VOQ_MOD_MAPm, &voq_mod_map, 18400 VOQ_VALIDf, 1); 18401 soc_mem_field32_set(unit, VOQ_MOD_MAPm, &voq_mod_map, 18402 VOQ_MOD_OFFSETf, mod_base); 18403 rv = soc_mem_write(unit, VOQ_MOD_MAPm, MEM_BLOCK_ALL, 18404 dm, &voq_mod_map); 18405 if (rv) { 18406 goto fail; 18407 } 18408 sal_memset(voq_port_map_entries, 0, sizeof(voq_port_map_entry_t)*128); 18409 if (ii != pcount) { 18410 mod_base = plist[ii].hw_index & ~3; 18411 dm = plist[ii].remote_modid; 18412 } 18413 } 18414 18415 if (ii == pcount) { 18416 break; 18417 } 18418 18419 if (plist[ii].valid == 0) { 18420 continue; 18421 } 18422 18423 dm = plist[ii].remote_modid; 18424 soc_mem_field32_set(unit, VOQ_PORT_MAPm, 18425 &voq_port_map_entries[plist[ii].remote_port], 18426 VOQ_PORT_OFFSETf, 18427 plist[ii].node->hw_index - mod_base); 18428 } 18429 18430 dm = -1; 18431 for (ii = 0; ii < pcount; ii += 1) { 18432 if (plist[ii].valid == 0) { 18433 continue; 18434 } 18435 18436 cng_offset = (dm2off[plist[ii].remote_modid] - 1) * 18437 cng_bytes_per_e2ecc_msg; 18438 18439 _bcm_td2_map_fc_status_to_node(unit, 18440 local_port, 18441 _BCM_TD2_COSQ_FC_E2ECC, 18442 cng_offset + plist[ii].remote_port, 18443 plist[ii].hw_cosq, 18444 plist[ii].node->hw_index, 18445 SOC_TD2_NODE_LVL_L2); 18446 } 18447 18448 fail: 18449 if (vlist) { 18450 sal_free(vlist); 18451 } 18452 18453 if (plist) { 18454 sal_free(plist); 18455 } 18456 18457 if (dm2off) { 18458 sal_free(dm2off); 18459 } 18460 18461 if (voq_port_map_entries) { 18462 sal_free(voq_port_map_entries); 18463 } 18464 18465 if (rv) { 18466 node->remote_modid = -1; 18467 node->remote_port = -1; 18468 } 18469 return rv; 18470 } 18471 18472 STATIC int 18473 _bcm_td2_gport_dmvoq_config_set(int unit, bcm_gport_t gport, 18474 bcm_cos_queue_t cosq, 18475 bcm_module_t fabric_modid, 18476 bcm_module_t dest_modid, 18477 bcm_port_t fabric_port) 18478 { 18479 int intf_index; 18480 _bcm_td2_cosq_node_t *node; 18481 _bcm_td2_cosq_node_t *base_node = NULL; 18482 bcm_port_t local_port; 18483 voq_mod_map_entry_t voq_mod_map_entry; 18484 mmu_intfi_offset_map_tbl_entry_t offset_map_tbl_entry; 18485 mmu_intfi_base_index_tbl_entry_t base_tbl_entry; 18486 uint32 cng_offset = 0; 18487 _bcm_td2_mmu_info_t *mmu_info; 18488 int fabric_port_count, count = 0; 18489 int map_offset = 0; 18490 int port = 0; 18491 18492 if ((mmu_info = _bcm_td2_mmu_info[unit]) == NULL) { 18493 return BCM_E_INIT; 18494 } 18495 18496 if (fabric_modid >= 64) { 18497 return BCM_E_PARAM; 18498 } 18499 18500 BCM_IF_ERROR_RETURN 18501 (_bcm_td2_cosq_node_get(unit, gport, 0, NULL, &local_port, NULL, &node)); 18502 18503 if (!node) { 18504 return BCM_E_NOT_FOUND; 18505 } 18506 18507 BCM_IF_ERROR_RETURN(_bcm_td2_resolve_dmvoq_hw_index(unit, node, cosq, 18508 dest_modid, local_port)); 18509 BCM_IF_ERROR_RETURN(_bcm_td2_voq_base_node_get( 18510 unit, local_port, dest_modid, &base_node)); 18511 if (base_node == NULL) { 18512 base_node = node ; 18513 } 18514 BCM_PBMP_COUNT(base_node->fabric_pbmp, fabric_port_count); 18515 if (fabric_port_count == 0) { 18516 map_offset = mmu_info->curr_merger_index; 18517 if (map_offset >= soc_mem_index_count(unit, MMU_INTFI_MERGE_ST_TBLm)) { 18518 return BCM_E_RESOURCE; 18519 } 18520 } else { 18521 BCM_PBMP_ITER(base_node->fabric_pbmp, port) { 18522 BCM_IF_ERROR_RETURN(soc_mem_read(unit, MMU_INTFI_OFFSET_MAP_TBLm, 18523 MEM_BLOCK_ALL, 18524 port * 2, &offset_map_tbl_entry)); 18525 map_offset = soc_mem_field32_get(unit, MMU_INTFI_OFFSET_MAP_TBLm, 18526 &offset_map_tbl_entry, 18527 MAP_OFFSETf); 18528 break; 18529 } 18530 } 18531 if (!BCM_PBMP_MEMBER(base_node->fabric_pbmp, fabric_port)) { 18532 if (map_offset == mmu_info->curr_merger_index ) { 18533 mmu_info->curr_merger_index += 2; 18534 } 18535 18536 BCM_PBMP_PORT_ADD (base_node->fabric_pbmp, fabric_port); 18537 BCM_PBMP_COUNT(base_node->fabric_pbmp, fabric_port_count); 18538 BCM_PBMP_ITER(base_node->fabric_pbmp, port) { 18539 count++; 18540 BCM_IF_ERROR_RETURN(soc_mem_read(unit, MMU_INTFI_OFFSET_MAP_TBLm, 18541 MEM_BLOCK_ALL, 18542 port * 2, &offset_map_tbl_entry)); 18543 soc_mem_field32_set(unit, MMU_INTFI_OFFSET_MAP_TBLm, 18544 &offset_map_tbl_entry, 18545 MAP_OFFSETf, map_offset); 18546 soc_mem_field32_set(unit, MMU_INTFI_OFFSET_MAP_TBLm, 18547 &offset_map_tbl_entry, 18548 LASTf, count < fabric_port_count ? 0 : 1 ); 18549 BCM_IF_ERROR_RETURN(soc_mem_write(unit, MMU_INTFI_OFFSET_MAP_TBLm, 18550 MEM_BLOCK_ALL, 18551 port * 2, &offset_map_tbl_entry)); 18552 18553 BCM_IF_ERROR_RETURN(soc_mem_read(unit, MMU_INTFI_OFFSET_MAP_TBLm, 18554 MEM_BLOCK_ALL, 18555 (port * 2) + 1, &offset_map_tbl_entry)); 18556 soc_mem_field32_set(unit, MMU_INTFI_OFFSET_MAP_TBLm, 18557 &offset_map_tbl_entry, 18558 MAP_OFFSETf, map_offset + 1); 18559 soc_mem_field32_set(unit, MMU_INTFI_OFFSET_MAP_TBLm, 18560 &offset_map_tbl_entry, 18561 LASTf, count < fabric_port_count ? 0 : 1 ); 18562 BCM_IF_ERROR_RETURN(soc_mem_write(unit, MMU_INTFI_OFFSET_MAP_TBLm, 18563 MEM_BLOCK_ALL, 18564 (port * 2) + 1, &offset_map_tbl_entry)); 18565 } 18566 } 18567 18568 BCM_IF_ERROR_RETURN(soc_mem_read(unit, VOQ_MOD_MAPm, MEM_BLOCK_ALL, 18569 dest_modid, &voq_mod_map_entry)); 18570 soc_mem_field32_set(unit, VOQ_MOD_MAPm, &voq_mod_map_entry, 18571 VOQ_VALIDf, 1); 18572 18573 soc_mem_field32_set(unit, VOQ_MOD_MAPm, &voq_mod_map_entry, 18574 VOQ_MOD_OFFSETf, 0); 18575 18576 BCM_IF_ERROR_RETURN( 18577 soc_mem_write(unit, VOQ_MOD_MAPm, MEM_BLOCK_ALL, dest_modid, 18578 &voq_mod_map_entry)); 18579 18580 intf_index = _bcm_td2_msg_buf_get(unit, fabric_modid); 18581 if (intf_index < 0) { 18582 return BCM_E_INTERNAL; 18583 } 18584 18585 cng_offset = intf_index * 64 * 2; 18586 18587 BCM_IF_ERROR_RETURN 18588 (soc_mem_read(unit, MMU_INTFI_BASE_INDEX_TBLm, 18589 MEM_BLOCK_ALL, fabric_modid, &base_tbl_entry)); 18590 18591 soc_mem_field32_set(unit, MMU_INTFI_BASE_INDEX_TBLm, &base_tbl_entry, 18592 BASE_ADDRf, cng_offset); 18593 soc_mem_field32_set(unit, MMU_INTFI_BASE_INDEX_TBLm, &base_tbl_entry, 18594 ENf, 2); 18595 18596 BCM_IF_ERROR_RETURN(soc_mem_write(unit, MMU_INTFI_BASE_INDEX_TBLm, 18597 MEM_BLOCK_ALL, fabric_modid, &base_tbl_entry)); 18598 18599 /* set the mapping from congestion bits in flow control table 18600 * to corresponding cosq. */ 18601 BCM_IF_ERROR_RETURN(_bcm_td2_map_fc_status_to_node(unit, local_port, 18602 _BCM_TD2_COSQ_FC_VOQFC, cng_offset + map_offset, 18603 cosq, node->hw_index, SOC_TD2_NODE_LVL_L2)); 18604 18605 #ifdef DEBUG_TD2_COSQ 18606 LOG_CLI((BSL_META_U(unit, 18607 "Gport=0x%08x hw_index=%d cosq=%d\n"), 18608 gport, node->hw_index, cosq)); 18609 #endif 18610 18611 return BCM_E_NONE; 18612 } 18613 18614 int bcm_td2_cosq_gport_congestion_config_set(int unit, bcm_gport_t gport, 18615 bcm_cos_queue_t cosq, 18616 bcm_cosq_congestion_info_t *config) 18617 { 18618 _bcm_td2_mmu_info_t *mmu_info; 18619 18620 if (!config) { 18621 return BCM_E_PARAM; 18622 } 18623 18624 if ((mmu_info = _bcm_td2_mmu_info[unit]) == NULL) { 18625 return BCM_E_INIT; 18626 } 18627 18628 /* determine if this gport is DPVOQ or DMVOQ */ 18629 if ((config->fabric_port != -1) && (config->dest_modid != -1)) { 18630 return _bcm_td2_gport_dmvoq_config_set(unit, gport, cosq, 18631 config->fabric_modid, 18632 config->dest_modid, 18633 config->fabric_port); 18634 } else if ((config->dest_modid != -1) && (config->dest_port != -1)) { 18635 return _bcm_td2_gport_dpvoq_config_set(unit, gport, cosq, 18636 config->dest_modid, 18637 config->dest_port); 18638 } 18639 18640 return BCM_E_PARAM; 18641 } 18642 18643 int bcm_td2_cosq_gport_congestion_config_get(int unit, bcm_gport_t port, 18644 bcm_cos_queue_t cosq, 18645 bcm_cosq_congestion_info_t *config) 18646 { 18647 _bcm_td2_mmu_info_t *mmu_info; 18648 bcm_port_t local_port; 18649 _bcm_td2_cosq_node_t *node; 18650 18651 if (!config) { 18652 return BCM_E_PARAM; 18653 } 18654 18655 if ((mmu_info = _bcm_td2_mmu_info[unit]) == NULL) { 18656 return BCM_E_INIT; 18657 } 18658 18659 BCM_IF_ERROR_RETURN 18660 (_bcm_td2_cosq_node_get(unit, port, 0, NULL, &local_port, NULL, &node)); 18661 18662 18663 if (!node) { 18664 return BCM_E_NOT_FOUND; 18665 } 18666 18667 config->dest_modid = node->remote_modid; 18668 config->dest_port = node->remote_port; 18669 18670 return BCM_E_NONE; 18671 } 18672 18673 18674 18675 int bcm_td2_cosq_bst_profile_set(int unit, 18676 bcm_gport_t port, 18677 bcm_cos_queue_t cosq, 18678 bcm_bst_stat_id_t bid, 18679 bcm_cosq_bst_profile_t *profile) 18680 { 18681 BCM_IF_ERROR_RETURN(_bcm_bst_cmn_profile_set 18682 (unit, port, cosq, BCM_BST_DUP_XPE, bid, profile)); 18683 return BCM_E_NONE; 18684 } 18685 18686 int bcm_td2_cosq_bst_profile_get(int unit, 18687 bcm_gport_t port, 18688 bcm_cos_queue_t cosq, 18689 bcm_bst_stat_id_t bid, 18690 bcm_cosq_bst_profile_t *profile) 18691 { 18692 BCM_IF_ERROR_RETURN(_bcm_bst_cmn_profile_get 18693 (unit, port, cosq, BCM_BST_DUP_XPE, bid, profile)); 18694 return BCM_E_NONE; 18695 } 18696 18697 int bcm_td2_cosq_bst_stat_get(int unit, 18698 bcm_gport_t port, 18699 bcm_cos_queue_t cosq, 18700 bcm_bst_stat_id_t bid, 18701 uint32 options, 18702 uint64 *pvalue) 18703 { 18704 return _bcm_bst_cmn_stat_get(unit, port, cosq, -1, bid, options, pvalue); 18705 } 18706 18707 int bcm_td2_cosq_bst_stat_multi_get(int unit, 18708 bcm_gport_t port, 18709 bcm_cos_queue_t cosq, 18710 uint32 options, 18711 int max_values, 18712 bcm_bst_stat_id_t *id_list, 18713 uint64 *pvalues) 18714 { 18715 return _bcm_bst_cmn_stat_multi_get(unit, port, cosq, options, max_values, 18716 id_list, pvalues); 18717 } 18718 18719 int bcm_td2_cosq_bst_stat_clear(int unit, bcm_gport_t port, 18720 bcm_cos_queue_t cosq, bcm_bst_stat_id_t bid) 18721 { 18722 return _bcm_bst_cmn_stat_clear(unit, port, cosq, bid); 18723 } 18724 18725 int bcm_td2_cosq_bst_stat_sync(int unit, bcm_bst_stat_id_t bid) 18726 { 18727 return _bcm_bst_cmn_stat_sync(unit, bid); 18728 } 18729 18730 18731 /* 18732 * Function: 18733 * _bcm_td2_cosq_endpoint_l2_create 18734 * Purpose: 18735 * Create a L2 endpoint. 18736 * Parameters: 18737 * unit - (IN) Unit number. 18738 * endpoint_id - (IN) Endpoint ID 18739 * vlan - (IN) VLAN 18740 * mac - (IN) MAC address 18741 * Returns: 18742 * BCM_E_xxx 18743 */ 18744 STATIC int 18745 _bcm_td2_cosq_endpoint_l2_create( 18746 int unit, 18747 int endpoint_id, 18748 bcm_vlan_t vlan, 18749 bcm_mac_t mac) 18750 { 18751 int rv; 18752 bcm_l2_addr_t l2addr; 18753 l2_endpoint_id_entry_t l2_endpoint_entry; 18754 int vfi; 18755 18756 /* Make sure (vlan, mac) entry is already in L2 table */ 18757 rv = bcm_esw_l2_addr_get(unit, mac, vlan, &l2addr); 18758 if (rv == BCM_E_NOT_FOUND) { 18759 /* The (vlan, mac) entry needs to be added to L2 table 18760 * before configuring it for endpoint queuing. 18761 */ 18762 return BCM_E_CONFIG; 18763 } else if (BCM_FAILURE(rv)) { 18764 return rv; 18765 } 18766 18767 /* Add (vlan, mac) entry to L2_ENDPOINT_ID table */ 18768 sal_memcpy(&l2_endpoint_entry, soc_mem_entry_null(unit, L2_ENDPOINT_IDm), 18769 sizeof(l2_endpoint_id_entry_t)); 18770 soc_L2_ENDPOINT_IDm_field32_set(unit, &l2_endpoint_entry, VALIDf, 1); 18771 if (_BCM_MPLS_VPN_IS_VPLS(vlan)) { 18772 _BCM_MPLS_VPN_GET(vfi, _BCM_MPLS_VPN_TYPE_VPLS, vlan); 18773 soc_L2_ENDPOINT_IDm_field32_set(unit, &l2_endpoint_entry, L2__VFIf, 18774 vfi); 18775 soc_L2_ENDPOINT_IDm_field32_set(unit, &l2_endpoint_entry, KEY_TYPEf, 18776 TD2_L2_HASH_KEY_TYPE_VFI); 18777 } else if (_BCM_IS_MIM_VPN(vlan)) { 18778 _BCM_MIM_VPN_GET(vfi, _BCM_MIM_VPN_TYPE_MIM, vlan); 18779 soc_L2_ENDPOINT_IDm_field32_set(unit, &l2_endpoint_entry, L2__VFIf, 18780 vfi); 18781 soc_L2_ENDPOINT_IDm_field32_set(unit, &l2_endpoint_entry, KEY_TYPEf, 18782 TD2_L2_HASH_KEY_TYPE_VFI); 18783 } else { 18784 VLAN_CHK_ID(unit, vlan); 18785 soc_L2_ENDPOINT_IDm_field32_set(unit, &l2_endpoint_entry, L2__VLAN_IDf, 18786 vlan); 18787 soc_L2_ENDPOINT_IDm_field32_set(unit, &l2_endpoint_entry, KEY_TYPEf, 18788 TD2_L2_HASH_KEY_TYPE_BRIDGE); 18789 } 18790 soc_L2_ENDPOINT_IDm_mac_addr_set(unit, &l2_endpoint_entry, L2__MAC_ADDRf, 18791 mac); 18792 soc_L2_ENDPOINT_IDm_field32_set(unit, &l2_endpoint_entry, EH_TAG_TYPEf, 2); 18793 soc_L2_ENDPOINT_IDm_field32_set(unit, &l2_endpoint_entry, EH_QUEUE_TAGf, 18794 endpoint_id); 18795 SOC_IF_ERROR_RETURN(soc_mem_insert(unit, L2_ENDPOINT_IDm, MEM_BLOCK_ANY, 18796 &l2_endpoint_entry)); 18797 18798 return BCM_E_NONE; 18799 } 18800 18801 /* 18802 * Function: 18803 * _bcm_td2_cosq_endpoint_l2_destroy 18804 * Purpose: 18805 * Destroy a L2 endpoint. 18806 * Parameters: 18807 * unit - (IN) Unit number. 18808 * vlan - (IN) VLAN 18809 * mac - (IN) MAC address 18810 * Returns: 18811 * BCM_E_xxx 18812 */ 18813 STATIC int 18814 _bcm_td2_cosq_endpoint_l2_destroy( 18815 int unit, 18816 bcm_vlan_t vlan, 18817 bcm_mac_t mac) 18818 { 18819 l2_endpoint_id_entry_t l2_endpoint_entry; 18820 int vfi; 18821 18822 /* Delete (vlan, mac) entry from L2_ENDPOINT_ID table */ 18823 sal_memcpy(&l2_endpoint_entry, soc_mem_entry_null(unit, L2_ENDPOINT_IDm), 18824 sizeof(l2_endpoint_id_entry_t)); 18825 if (_BCM_MPLS_VPN_IS_VPLS(vlan)) { 18826 _BCM_MPLS_VPN_GET(vfi, _BCM_MPLS_VPN_TYPE_VPLS, vlan); 18827 soc_L2_ENDPOINT_IDm_field32_set(unit, &l2_endpoint_entry, L2__VFIf, 18828 vfi); 18829 soc_L2_ENDPOINT_IDm_field32_set(unit, &l2_endpoint_entry, KEY_TYPEf, 18830 TD2_L2_HASH_KEY_TYPE_VFI); 18831 } else if (_BCM_IS_MIM_VPN(vlan)) { 18832 _BCM_MIM_VPN_GET(vfi, _BCM_MIM_VPN_TYPE_MIM, vlan); 18833 soc_L2_ENDPOINT_IDm_field32_set(unit, &l2_endpoint_entry, L2__VFIf, 18834 vfi); 18835 soc_L2_ENDPOINT_IDm_field32_set(unit, &l2_endpoint_entry, KEY_TYPEf, 18836 TD2_L2_HASH_KEY_TYPE_VFI); 18837 } else { 18838 VLAN_CHK_ID(unit, vlan); 18839 soc_L2_ENDPOINT_IDm_field32_set(unit, &l2_endpoint_entry, L2__VLAN_IDf, 18840 vlan); 18841 soc_L2_ENDPOINT_IDm_field32_set(unit, &l2_endpoint_entry, KEY_TYPEf, 18842 TD2_L2_HASH_KEY_TYPE_BRIDGE); 18843 } 18844 soc_L2_ENDPOINT_IDm_mac_addr_set(unit, &l2_endpoint_entry, L2__MAC_ADDRf, 18845 mac); 18846 SOC_IF_ERROR_RETURN(soc_mem_delete(unit, L2_ENDPOINT_IDm, MEM_BLOCK_ANY, 18847 &l2_endpoint_entry)); 18848 18849 return BCM_E_NONE; 18850 } 18851 18852 #ifdef INCLUDE_L3 18853 /* 18854 * Function: 18855 * _bcm_td2_cosq_endpoint_ip4_create 18856 * Purpose: 18857 * Create an IPv4 endpoint. 18858 * Parameters: 18859 * unit - (IN) Unit number. 18860 * endpoint_id - (IN) Endpoint ID 18861 * vrf - (IN) Virtual router instance 18862 * ip_addr - (IN) IPv4 address 18863 * Returns: 18864 * BCM_E_xxx 18865 */ 18866 STATIC int 18867 _bcm_td2_cosq_endpoint_ip4_create( 18868 int unit, 18869 int endpoint_id, 18870 bcm_vrf_t vrf, 18871 bcm_ip_t ip_addr) 18872 { 18873 int rv; 18874 _bcm_l3_cfg_t l3cfg; 18875 18876 if ((vrf > SOC_VRF_MAX(unit)) || 18877 (vrf < BCM_L3_VRF_DEFAULT)) { 18878 return BCM_E_PARAM; 18879 } 18880 18881 L3_LOCK(unit); 18882 18883 /* Make sure (vrf, ip_addr) entry is already in L3 host table */ 18884 sal_memset(&l3cfg, 0, sizeof(_bcm_l3_cfg_t)); 18885 l3cfg.l3c_vrf = vrf; 18886 l3cfg.l3c_ip_addr = ip_addr; 18887 rv = mbcm_driver[unit]->mbcm_l3_ip4_get(unit, &l3cfg); 18888 if (rv == BCM_E_NOT_FOUND) { 18889 /* The (vrf, ip_addr) entry needs to be added to L3 table 18890 * before configuring it for endpoint queuing. 18891 */ 18892 L3_UNLOCK(unit); 18893 return BCM_E_CONFIG; 18894 } else if (BCM_FAILURE(rv)) { 18895 L3_UNLOCK(unit); 18896 return rv; 18897 } else { 18898 /* Make sure the L3 ENTRY is in extender view */ 18899 if (!BCM_TD2_L3_USE_EMBEDDED_NEXT_HOP(unit, l3cfg.l3c_intf, 18900 BCM_XGS3_L3_INVALID_INDEX)) { 18901 L3_UNLOCK(unit); 18902 return BCM_E_CONFIG; 18903 } 18904 } 18905 18906 if (l3cfg.l3c_eh_q_tag_type != 0) { 18907 /* A queue tag has already been configured for this L3 entry. */ 18908 L3_UNLOCK(unit); 18909 return BCM_E_EXISTS; 18910 } 18911 18912 /* Replace (vrf, ip_addr) entry's endpoint_id */ 18913 l3cfg.l3c_flags |= BCM_L3_REPLACE; 18914 l3cfg.l3c_eh_q_tag_type = 2; 18915 l3cfg.l3c_eh_q_tag = endpoint_id; 18916 rv = mbcm_driver[unit]->mbcm_l3_ip4_replace(unit, &l3cfg); 18917 if (BCM_FAILURE(rv)) { 18918 L3_UNLOCK(unit); 18919 return rv; 18920 } 18921 18922 L3_UNLOCK(unit); 18923 18924 return rv; 18925 } 18926 18927 /* 18928 * Function: 18929 * _bcm_td2_cosq_endpoint_ip4_destroy 18930 * Purpose: 18931 * Destroy an IPv4 endpoint. 18932 * Parameters: 18933 * unit - (IN) Unit number. 18934 * vrf - (IN) Virtual router instance 18935 * ip_addr - (IN) IPv4 address 18936 * Returns: 18937 * BCM_E_xxx 18938 */ 18939 STATIC int 18940 _bcm_td2_cosq_endpoint_ip4_destroy( 18941 int unit, 18942 bcm_vrf_t vrf, 18943 bcm_ip_t ip_addr) 18944 { 18945 int rv; 18946 _bcm_l3_cfg_t l3cfg; 18947 18948 if ((vrf > SOC_VRF_MAX(unit)) || 18949 (vrf < BCM_L3_VRF_DEFAULT)) { 18950 return BCM_E_PARAM; 18951 } 18952 18953 L3_LOCK(unit); 18954 18955 /* Get (vrf, ip_addr) entry */ 18956 sal_memset(&l3cfg, 0, sizeof(_bcm_l3_cfg_t)); 18957 l3cfg.l3c_vrf = vrf; 18958 l3cfg.l3c_ip_addr = ip_addr; 18959 rv = mbcm_driver[unit]->mbcm_l3_ip4_get(unit, &l3cfg); 18960 if (BCM_FAILURE(rv)) { 18961 L3_UNLOCK(unit); 18962 return rv; 18963 } else { 18964 /* Make sure the L3 ENTRY is in extender view */ 18965 if (!BCM_TD2_L3_USE_EMBEDDED_NEXT_HOP(unit, l3cfg.l3c_intf, 18966 BCM_XGS3_L3_INVALID_INDEX)) { 18967 L3_UNLOCK(unit); 18968 return BCM_E_CONFIG; 18969 } 18970 } 18971 18972 /* Delete (vrf, ip_addr) entry's endpoint_id */ 18973 l3cfg.l3c_flags |= BCM_L3_REPLACE; 18974 l3cfg.l3c_eh_q_tag_type = 0; 18975 l3cfg.l3c_eh_q_tag = 0; 18976 rv = mbcm_driver[unit]->mbcm_l3_ip4_replace(unit, &l3cfg); 18977 if (BCM_FAILURE(rv)) { 18978 L3_UNLOCK(unit); 18979 return rv; 18980 } 18981 18982 L3_UNLOCK(unit); 18983 18984 return rv; 18985 } 18986 18987 /* 18988 * Function: 18989 * _bcm_td2_cosq_endpoint_ip6_create 18990 * Purpose: 18991 * Create an IPv6 endpoint. 18992 * Parameters: 18993 * unit - (IN) Unit number. 18994 * endpoint_id - (IN) Endpoint ID 18995 * vrf - (IN) Virtual router instance 18996 * ip6_addr - (IN) IPv6 address 18997 * Returns: 18998 * BCM_E_xxx 18999 */ 19000 STATIC int 19001 _bcm_td2_cosq_endpoint_ip6_create( 19002 int unit, 19003 int endpoint_id, 19004 bcm_vrf_t vrf, 19005 bcm_ip6_t ip6_addr) 19006 { 19007 int rv; 19008 _bcm_l3_cfg_t l3cfg; 19009 19010 if ((vrf > SOC_VRF_MAX(unit)) || 19011 (vrf < BCM_L3_VRF_DEFAULT)) { 19012 return BCM_E_PARAM; 19013 } 19014 19015 L3_LOCK(unit); 19016 19017 /* Make sure (vrf, ip6_addr) entry is already in L3 host table */ 19018 sal_memset(&l3cfg, 0, sizeof(_bcm_l3_cfg_t)); 19019 l3cfg.l3c_flags = BCM_L3_IP6; 19020 l3cfg.l3c_vrf = vrf; 19021 sal_memcpy(l3cfg.l3c_ip6, ip6_addr, BCM_IP6_ADDRLEN); 19022 rv = mbcm_driver[unit]->mbcm_l3_ip6_get(unit, &l3cfg); 19023 if (rv == BCM_E_NOT_FOUND) { 19024 /* The (vrf, ip6_addr) entry needs to be added to L3 table 19025 * before configuring it for endpoint queuing. 19026 */ 19027 L3_UNLOCK(unit); 19028 return BCM_E_CONFIG; 19029 } else if (BCM_FAILURE(rv)) { 19030 L3_UNLOCK(unit); 19031 return rv; 19032 } else { 19033 /* Make sure the L3 ENTRY is in extender view */ 19034 if (!BCM_TD2_L3_USE_EMBEDDED_NEXT_HOP(unit, l3cfg.l3c_intf, 19035 BCM_XGS3_L3_INVALID_INDEX)) { 19036 L3_UNLOCK(unit); 19037 return BCM_E_CONFIG; 19038 } 19039 } 19040 19041 if (l3cfg.l3c_eh_q_tag_type != 0) { 19042 /* A queue tag has already been configured for this L3 entry. */ 19043 L3_UNLOCK(unit); 19044 return BCM_E_EXISTS; 19045 } 19046 19047 /* Replace (vrf, ip_addr) entry's endpoint_id */ 19048 l3cfg.l3c_flags |= BCM_L3_REPLACE; 19049 l3cfg.l3c_eh_q_tag_type = 2; 19050 l3cfg.l3c_eh_q_tag = endpoint_id; 19051 rv = mbcm_driver[unit]->mbcm_l3_ip6_replace(unit, &l3cfg); 19052 if (BCM_FAILURE(rv)) { 19053 L3_UNLOCK(unit); 19054 return rv; 19055 } 19056 19057 L3_UNLOCK(unit); 19058 19059 return rv; 19060 } 19061 19062 /* 19063 * Function: 19064 * _bcm_td2_cosq_endpoint_ip6_destroy 19065 * Purpose: 19066 * Destroy an IPv6 endpoint. 19067 * Parameters: 19068 * unit - (IN) Unit number. 19069 * vrf - (IN) Virtual router instance 19070 * ip6_addr - (IN) IPv6 address 19071 * Returns: 19072 * BCM_E_xxx 19073 */ 19074 STATIC int 19075 _bcm_td2_cosq_endpoint_ip6_destroy( 19076 int unit, 19077 bcm_vrf_t vrf, 19078 bcm_ip6_t ip6_addr) 19079 { 19080 int rv; 19081 _bcm_l3_cfg_t l3cfg; 19082 19083 if ((vrf > SOC_VRF_MAX(unit)) || 19084 (vrf < BCM_L3_VRF_DEFAULT)) { 19085 return BCM_E_PARAM; 19086 } 19087 19088 L3_LOCK(unit); 19089 19090 /* Get (vrf, ip6_addr) entry */ 19091 sal_memset(&l3cfg, 0, sizeof(_bcm_l3_cfg_t)); 19092 l3cfg.l3c_flags = BCM_L3_IP6; 19093 l3cfg.l3c_vrf = vrf; 19094 sal_memcpy(l3cfg.l3c_ip6, ip6_addr, BCM_IP6_ADDRLEN); 19095 rv = mbcm_driver[unit]->mbcm_l3_ip6_get(unit, &l3cfg); 19096 if (BCM_FAILURE(rv)) { 19097 L3_UNLOCK(unit); 19098 return rv; 19099 } else { 19100 /* Make sure the L3 ENTRY is in extender view */ 19101 if (!BCM_TD2_L3_USE_EMBEDDED_NEXT_HOP(unit, l3cfg.l3c_intf, 19102 BCM_XGS3_L3_INVALID_INDEX)) { 19103 L3_UNLOCK(unit); 19104 return BCM_E_CONFIG; 19105 } 19106 } 19107 19108 /* Delete (vrf, ip_addr) entry's endpoint_id */ 19109 l3cfg.l3c_flags |= BCM_L3_REPLACE; 19110 l3cfg.l3c_eh_q_tag_type = 0; 19111 l3cfg.l3c_eh_q_tag = 0; 19112 rv = mbcm_driver[unit]->mbcm_l3_ip6_replace(unit, &l3cfg); 19113 if (BCM_FAILURE(rv)) { 19114 L3_UNLOCK(unit); 19115 return rv; 19116 } 19117 19118 L3_UNLOCK(unit); 19119 19120 return rv; 19121 } 19122 19123 19124 /* 19125 * Function: 19126 * _bcm_td2_cosq_endpoint_L3_egress_create 19127 * Purpose: 19128 * Create a L3 egress endpoint. 19129 * Parameters: 19130 * unit - (IN) Unit number. 19131 * endpoint_id - (IN) Endpoint ID 19132 * egress_if - (IN) egress object ID 19133 * Returns: 19134 * BCM_E_xxx 19135 */ 19136 STATIC int 19137 _bcm_td2_cosq_endpoint_l3_egress_create( 19138 int unit, 19139 int endpoint_id, 19140 bcm_if_t egress_if) 19141 { 19142 int nh_index; 19143 ing_l3_next_hop_entry_t nh_entry; 19144 int eh_tag_type; 19145 if (!BCM_XGS3_L3_EGRESS_IDX_VALID(unit, egress_if)) { 19146 return BCM_E_PARAM; 19147 } 19148 nh_index = egress_if - BCM_XGS3_EGRESS_IDX_MIN(unit); 19149 /* Set endpoint ID in next hop entry */ 19150 BCM_IF_ERROR_RETURN 19151 (READ_ING_L3_NEXT_HOPm(unit, MEM_BLOCK_ANY, nh_index, &nh_entry)); 19152 eh_tag_type = soc_ING_L3_NEXT_HOPm_field32_get(unit, &nh_entry, 19153 EH_TAG_TYPEf); 19154 if (eh_tag_type != 0) { 19155 /* A queue tag has already been configured for this next hop entry. */ 19156 return BCM_E_EXISTS; 19157 } 19158 soc_ING_L3_NEXT_HOPm_field32_set(unit, &nh_entry, EH_TAG_TYPEf, 2); 19159 soc_ING_L3_NEXT_HOPm_field32_set(unit, &nh_entry, EH_QUEUE_TAGf, endpoint_id); 19160 BCM_IF_ERROR_RETURN 19161 (WRITE_ING_L3_NEXT_HOPm(unit, MEM_BLOCK_ALL, nh_index, &nh_entry)); 19162 return BCM_E_NONE; 19163 } 19164 19165 /* 19166 * Function: 19167 * _bcm_td2_cosq_endpoint_gport_destroy 19168 * Purpose: 19169 * Destroy a GPORT endpoint. 19170 * Parameters: 19171 * unit - (IN) Unit number. 19172 * egress_if - (IN) Egress object. 19173 * Returns: 19174 * BCM_E_xxx 19175 */ 19176 STATIC int 19177 _bcm_td2_cosq_endpoint_l3_egress_destroy( 19178 int unit, 19179 bcm_if_t egress_if) 19180 { 19181 int nh_index; 19182 ing_l3_next_hop_entry_t nh_entry; 19183 if (!BCM_XGS3_L3_EGRESS_IDX_VALID(unit, egress_if)) { 19184 return BCM_E_PARAM; 19185 } 19186 nh_index = egress_if - BCM_XGS3_EGRESS_IDX_MIN(unit); 19187 /* Set endpoint ID in next hop entry */ 19188 BCM_IF_ERROR_RETURN 19189 (READ_ING_L3_NEXT_HOPm(unit, MEM_BLOCK_ANY, nh_index, &nh_entry)); 19190 soc_ING_L3_NEXT_HOPm_field32_set(unit, &nh_entry, EH_TAG_TYPEf, 0); 19191 soc_ING_L3_NEXT_HOPm_field32_set(unit, &nh_entry, EH_QUEUE_TAGf, 0); 19192 BCM_IF_ERROR_RETURN 19193 (WRITE_ING_L3_NEXT_HOPm(unit, MEM_BLOCK_ALL, nh_index, &nh_entry)); 19194 return BCM_E_NONE; 19195 } 19196 19197 #endif /* INCLUDE_L3 */ 19198 19199 /* 19200 * Function: 19201 * _bcm_td2_cosq_endpoint_gport_create 19202 * Purpose: 19203 * Create a GPORT endpoint. 19204 * Parameters: 19205 * unit - (IN) Unit number. 19206 * endpoint_id - (IN) Endpoint ID 19207 * gport - (IN) GPORT ID 19208 * Returns: 19209 * BCM_E_xxx 19210 */ 19211 STATIC int 19212 _bcm_td2_cosq_endpoint_gport_create( 19213 int unit, 19214 int endpoint_id, 19215 bcm_gport_t gport) 19216 { 19217 int vp; 19218 ing_dvp_table_entry_t dvp_entry; 19219 int nh_index; 19220 ing_l3_next_hop_entry_t nh_entry; 19221 int eh_tag_type; 19222 19223 /* Get virtual port value */ 19224 if (BCM_GPORT_IS_VLAN_PORT(gport)) { 19225 vp = BCM_GPORT_VLAN_PORT_ID_GET(gport); 19226 #if defined(INCLUDE_L3) 19227 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeVlan)) { 19228 /* VP is not configured yet */ 19229 return BCM_E_CONFIG; 19230 } 19231 #endif 19232 } else if (BCM_GPORT_IS_NIV_PORT(gport)) { 19233 vp = BCM_GPORT_NIV_PORT_ID_GET(gport); 19234 #if defined(INCLUDE_L3) 19235 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeNiv)) { 19236 /* VP is not configured yet */ 19237 return BCM_E_CONFIG; 19238 } 19239 #endif 19240 } else if (BCM_GPORT_IS_MPLS_PORT(gport)) { 19241 vp = BCM_GPORT_MPLS_PORT_ID_GET(gport); 19242 #if defined(INCLUDE_L3) 19243 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) { 19244 /* VP is not configured yet */ 19245 return BCM_E_CONFIG; 19246 } 19247 #endif 19248 } else { 19249 return BCM_E_PARAM; 19250 } 19251 19252 /* Get VP's next hop index */ 19253 BCM_IF_ERROR_RETURN 19254 (READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp_entry)); 19255 nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp_entry, 19256 NEXT_HOP_INDEXf); 19257 19258 /* Set endpoint ID in next hop entry */ 19259 BCM_IF_ERROR_RETURN 19260 (READ_ING_L3_NEXT_HOPm(unit, MEM_BLOCK_ANY, nh_index, &nh_entry)); 19261 eh_tag_type = soc_ING_L3_NEXT_HOPm_field32_get(unit, &nh_entry, 19262 EH_TAG_TYPEf); 19263 if (eh_tag_type != 0) { 19264 /* A queue tag has already been configured for this next hop entry. */ 19265 return BCM_E_EXISTS; 19266 } 19267 soc_ING_L3_NEXT_HOPm_field32_set(unit, &nh_entry, EH_TAG_TYPEf, 2); 19268 soc_ING_L3_NEXT_HOPm_field32_set(unit, &nh_entry, EH_QUEUE_TAGf, endpoint_id); 19269 BCM_IF_ERROR_RETURN 19270 (WRITE_ING_L3_NEXT_HOPm(unit, MEM_BLOCK_ALL, nh_index, &nh_entry)); 19271 19272 return BCM_E_NONE; 19273 } 19274 19275 /* 19276 * Function: 19277 * _bcm_td2_cosq_endpoint_gport_destroy 19278 * Purpose: 19279 * Destroy a GPORT endpoint. 19280 * Parameters: 19281 * unit - (IN) Unit number. 19282 * gport - (IN) GPORT ID 19283 * Returns: 19284 * BCM_E_xxx 19285 */ 19286 STATIC int 19287 _bcm_td2_cosq_endpoint_gport_destroy( 19288 int unit, 19289 bcm_gport_t gport) 19290 { 19291 int vp; 19292 ing_dvp_table_entry_t dvp_entry; 19293 int nh_index; 19294 ing_l3_next_hop_entry_t nh_entry; 19295 19296 /* Get virtual port value */ 19297 if (BCM_GPORT_IS_VLAN_PORT(gport)) { 19298 vp = BCM_GPORT_VLAN_PORT_ID_GET(gport); 19299 #if defined(INCLUDE_L3) 19300 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeVlan)) { 19301 /* VP is not configured yet */ 19302 return BCM_E_CONFIG; 19303 } 19304 #endif 19305 } else if (BCM_GPORT_IS_NIV_PORT(gport)) { 19306 vp = BCM_GPORT_NIV_PORT_ID_GET(gport); 19307 #if defined(INCLUDE_L3) 19308 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeNiv)) { 19309 /* VP is not configured yet */ 19310 return BCM_E_CONFIG; 19311 } 19312 #endif 19313 } else if (BCM_GPORT_IS_MPLS_PORT(gport)) { 19314 vp = BCM_GPORT_MPLS_PORT_ID_GET(gport); 19315 #if defined(INCLUDE_L3) 19316 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) { 19317 /* VP is not configured yet */ 19318 return BCM_E_CONFIG; 19319 } 19320 #endif 19321 } else { 19322 return BCM_E_PARAM; 19323 } 19324 19325 /* Get VP's next hop index */ 19326 BCM_IF_ERROR_RETURN 19327 (READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp_entry)); 19328 nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp_entry, 19329 NEXT_HOP_INDEXf); 19330 19331 /* Delete endpoint ID in next hop entry */ 19332 BCM_IF_ERROR_RETURN 19333 (READ_ING_L3_NEXT_HOPm(unit, MEM_BLOCK_ANY, nh_index, &nh_entry)); 19334 soc_ING_L3_NEXT_HOPm_field32_set(unit, &nh_entry, EH_TAG_TYPEf, 0); 19335 soc_ING_L3_NEXT_HOPm_field32_set(unit, &nh_entry, EH_QUEUE_TAGf, 0); 19336 BCM_IF_ERROR_RETURN 19337 (WRITE_ING_L3_NEXT_HOPm(unit, MEM_BLOCK_ALL, nh_index, &nh_entry)); 19338 19339 return BCM_E_NONE; 19340 } 19341 19342 /* 19343 * Function: 19344 * bcm_td2_cosq_endpoint_create 19345 * Purpose: 19346 * Create an endpoint. 19347 * Parameters: 19348 * unit - (IN) Unit number. 19349 * classifier - (IN) Classifier attributes 19350 * classifier_id - (IN/OUT) Classifier ID 19351 * Returns: 19352 * BCM_E_xxx 19353 */ 19354 int 19355 bcm_td2_cosq_endpoint_create( 19356 int unit, 19357 bcm_cosq_classifier_t *classifier, 19358 int *classifier_id) 19359 { 19360 int endpoint_id = 0; 19361 int i; 19362 19363 if (NULL == classifier || NULL == classifier_id) { 19364 return BCM_E_PARAM; 19365 } 19366 19367 if (classifier->flags & BCM_COSQ_CLASSIFIER_WITH_ID) { 19368 if (!_BCM_COSQ_CLASSIFIER_IS_ENDPOINT(*classifier_id)) { 19369 return BCM_E_PARAM; 19370 } 19371 endpoint_id = _BCM_COSQ_CLASSIFIER_ENDPOINT_GET(*classifier_id); 19372 if (endpoint_id >= _BCM_TD2_NUM_ENDPOINT(unit)) { 19373 return BCM_E_PARAM; 19374 } 19375 if (_BCM_TD2_ENDPOINT_IS_USED(unit, endpoint_id)) { 19376 return BCM_E_EXISTS; 19377 } 19378 } else { 19379 /* Get a free endpoint ID */ 19380 for (i = 0; i < _BCM_TD2_NUM_ENDPOINT(unit); i++) { 19381 if (!_BCM_TD2_ENDPOINT_IS_USED(unit, i)) { 19382 endpoint_id = i; 19383 break; 19384 } 19385 } 19386 if (i == _BCM_TD2_NUM_ENDPOINT(unit)) { 19387 /* No available endpoint ID */ 19388 return BCM_E_RESOURCE; 19389 } 19390 } 19391 _BCM_TD2_ENDPOINT(unit, endpoint_id) = sal_alloc( 19392 sizeof(_bcm_td2_endpoint_t), "Endpoint Info"); 19393 if (NULL == _BCM_TD2_ENDPOINT(unit, endpoint_id)) { 19394 return BCM_E_MEMORY; 19395 } 19396 sal_memset(_BCM_TD2_ENDPOINT(unit, endpoint_id), 0, 19397 sizeof(_bcm_td2_endpoint_t)); 19398 19399 if (classifier->flags & BCM_COSQ_CLASSIFIER_L2) { 19400 _BCM_TD2_ENDPOINT(unit, endpoint_id)->flags = BCM_COSQ_CLASSIFIER_L2; 19401 _BCM_TD2_ENDPOINT(unit, endpoint_id)->vlan = classifier->vlan; 19402 sal_memcpy(_BCM_TD2_ENDPOINT(unit, endpoint_id)->mac, classifier->mac, 19403 sizeof(bcm_mac_t)); 19404 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_endpoint_l2_create(unit, 19405 endpoint_id, classifier->vlan, classifier->mac)); 19406 } else if (classifier->flags & BCM_COSQ_CLASSIFIER_L3) { 19407 #if defined(INCLUDE_L3) 19408 _BCM_TD2_ENDPOINT(unit, endpoint_id)->flags = BCM_COSQ_CLASSIFIER_L3; 19409 _BCM_TD2_ENDPOINT(unit, endpoint_id)->vrf = classifier->vrf; 19410 if (classifier->flags & BCM_COSQ_CLASSIFIER_IP6) { 19411 _BCM_TD2_ENDPOINT(unit, endpoint_id)->flags |= BCM_COSQ_CLASSIFIER_IP6; 19412 sal_memcpy(_BCM_TD2_ENDPOINT(unit, endpoint_id)->ip6_addr, 19413 classifier->ip6_addr, BCM_IP6_ADDRLEN); 19414 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_endpoint_ip6_create(unit, 19415 endpoint_id, classifier->vrf, classifier->ip6_addr)); 19416 } else { 19417 _BCM_TD2_ENDPOINT(unit, endpoint_id)->ip_addr = classifier->ip_addr; 19418 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_endpoint_ip4_create(unit, 19419 endpoint_id, classifier->vrf, classifier->ip_addr)); 19420 } 19421 #endif /* INCLUDE_L3 */ 19422 } else if (classifier->flags & BCM_COSQ_CLASSIFIER_GPORT) { 19423 _BCM_TD2_ENDPOINT(unit, endpoint_id)->flags = BCM_COSQ_CLASSIFIER_GPORT; 19424 _BCM_TD2_ENDPOINT(unit, endpoint_id)->gport = classifier->gport; 19425 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_endpoint_gport_create(unit, 19426 endpoint_id, classifier->gport)); 19427 } else if (classifier->flags & BCM_COSQ_CLASSIFIER_L3_EGRESS) { 19428 #if defined(INCLUDE_L3) 19429 _BCM_TD2_ENDPOINT(unit, endpoint_id)->flags = BCM_COSQ_CLASSIFIER_L3_EGRESS; 19430 _BCM_TD2_ENDPOINT(unit, endpoint_id)->egress_if = classifier->egress_if; 19431 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_endpoint_l3_egress_create(unit, 19432 endpoint_id, classifier->egress_if)); 19433 #endif /* INCLUDE_L3 */ 19434 } else { 19435 return BCM_E_PARAM; 19436 } 19437 19438 _BCM_COSQ_CLASSIFIER_ENDPOINT_SET(*classifier_id, endpoint_id); 19439 19440 return BCM_E_NONE; 19441 } 19442 19443 /* 19444 * Function: 19445 * bcm_td2_cosq_endpoint_destroy 19446 * Purpose: 19447 * Destroy an endpoint. 19448 * Parameters: 19449 * unit - (IN) Unit number. 19450 * classifier_id - (IN) Classifier ID 19451 * Returns: 19452 * BCM_E_xxx 19453 */ 19454 int 19455 bcm_td2_cosq_endpoint_destroy( 19456 int unit, 19457 int classifier_id) 19458 { 19459 int endpoint_id; 19460 19461 if (!_BCM_COSQ_CLASSIFIER_IS_ENDPOINT(classifier_id)) { 19462 return BCM_E_PARAM; 19463 } 19464 endpoint_id = _BCM_COSQ_CLASSIFIER_ENDPOINT_GET(classifier_id); 19465 if (endpoint_id >= _BCM_TD2_NUM_ENDPOINT(unit)) { 19466 return BCM_E_PARAM; 19467 } 19468 if (!_BCM_TD2_ENDPOINT_IS_USED(unit, endpoint_id)) { 19469 return BCM_E_NOT_FOUND; 19470 } 19471 19472 if (_BCM_TD2_ENDPOINT(unit, endpoint_id)->flags & 19473 BCM_COSQ_CLASSIFIER_L2) { 19474 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_endpoint_l2_destroy(unit, 19475 _BCM_TD2_ENDPOINT(unit, endpoint_id)->vlan, 19476 _BCM_TD2_ENDPOINT(unit, endpoint_id)->mac)); 19477 } else if (_BCM_TD2_ENDPOINT(unit, endpoint_id)->flags & 19478 BCM_COSQ_CLASSIFIER_L3) { 19479 #if defined(INCLUDE_L3) 19480 if (_BCM_TD2_ENDPOINT(unit, endpoint_id)->flags & 19481 BCM_COSQ_CLASSIFIER_IP6) { 19482 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_endpoint_ip6_destroy(unit, 19483 _BCM_TD2_ENDPOINT(unit, endpoint_id)->vrf, 19484 _BCM_TD2_ENDPOINT(unit, endpoint_id)->ip6_addr)); 19485 } else { 19486 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_endpoint_ip4_destroy(unit, 19487 _BCM_TD2_ENDPOINT(unit, endpoint_id)->vrf, 19488 _BCM_TD2_ENDPOINT(unit, endpoint_id)->ip_addr)); 19489 } 19490 #endif 19491 } else if (_BCM_TD2_ENDPOINT(unit, endpoint_id)->flags & 19492 BCM_COSQ_CLASSIFIER_GPORT) { 19493 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_endpoint_gport_destroy(unit, 19494 _BCM_TD2_ENDPOINT(unit, endpoint_id)->gport)); 19495 } else if (_BCM_TD2_ENDPOINT(unit, endpoint_id)->flags & 19496 BCM_COSQ_CLASSIFIER_L3_EGRESS) { 19497 #if defined(INCLUDE_L3) 19498 BCM_IF_ERROR_RETURN( 19499 _bcm_td2_cosq_endpoint_l3_egress_destroy( 19500 unit, _BCM_TD2_ENDPOINT(unit, endpoint_id)->egress_if)); 19501 #endif 19502 } else { 19503 return BCM_E_INTERNAL; 19504 } 19505 19506 sal_free(_BCM_TD2_ENDPOINT(unit, endpoint_id)); 19507 _BCM_TD2_ENDPOINT(unit, endpoint_id) = NULL; 19508 19509 return BCM_E_NONE; 19510 } 19511 19512 /* 19513 * Function: 19514 * bcm_td2_cosq_endpoint_get 19515 * Purpose: 19516 * Get info about an endpoint. 19517 * Parameters: 19518 * unit - (IN) Unit number. 19519 * classifier_id - (IN) Classifier ID 19520 * classifier - (OUT) Classifier info 19521 * Returns: 19522 * BCM_E_xxx 19523 */ 19524 int 19525 bcm_td2_cosq_endpoint_get( 19526 int unit, 19527 int classifier_id, 19528 bcm_cosq_classifier_t *classifier) 19529 { 19530 int endpoint_id; 19531 19532 if (!_BCM_COSQ_CLASSIFIER_IS_ENDPOINT(classifier_id)) { 19533 return BCM_E_PARAM; 19534 } 19535 endpoint_id = _BCM_COSQ_CLASSIFIER_ENDPOINT_GET(classifier_id); 19536 if (endpoint_id >= _BCM_TD2_NUM_ENDPOINT(unit)) { 19537 return BCM_E_PARAM; 19538 } 19539 if (!_BCM_TD2_ENDPOINT_IS_USED(unit, endpoint_id)) { 19540 return BCM_E_NOT_FOUND; 19541 } 19542 19543 classifier->flags = _BCM_TD2_ENDPOINT(unit, endpoint_id)->flags; 19544 classifier->vlan = _BCM_TD2_ENDPOINT(unit, endpoint_id)->vlan; 19545 sal_memcpy(classifier->mac, _BCM_TD2_ENDPOINT(unit, endpoint_id)->mac, 19546 sizeof(bcm_mac_t)); 19547 classifier->vrf = _BCM_TD2_ENDPOINT(unit, endpoint_id)->vrf; 19548 classifier->ip_addr = _BCM_TD2_ENDPOINT(unit, endpoint_id)->ip_addr; 19549 sal_memcpy(classifier->ip6_addr, 19550 _BCM_TD2_ENDPOINT(unit, endpoint_id)->ip6_addr, BCM_IP6_ADDRLEN); 19551 classifier->gport = _BCM_TD2_ENDPOINT(unit, endpoint_id)->gport; 19552 classifier->egress_if = _BCM_TD2_ENDPOINT(unit, endpoint_id)->egress_if; 19553 return BCM_E_NONE; 19554 } 19555 19556 /* 19557 * Function: 19558 * bcm_td2_cosq_endpoint_map_set 19559 * Purpose: 19560 * Set the mapping from port, classifier, and multiple internal priorities 19561 * to multiple COS queues in a queue group. 19562 * Parameters: 19563 * unit - (IN) Unit number. 19564 * port - (IN) local port ID 19565 * classifier_id - (IN) Classifier ID 19566 * queue_group - (IN) Base queue ID 19567 * array_count - (IN) Number of elements in priority_array and 19568 * cosq_array 19569 * priority_array - (IN) Array of internal priorities 19570 * cosq_array - (IN) Array of COS queues 19571 * Returns: 19572 * BCM_E_xxx 19573 */ 19574 int 19575 bcm_td2_cosq_endpoint_map_set( 19576 int unit, 19577 bcm_port_t port, 19578 int classifier_id, 19579 bcm_gport_t queue_group, 19580 int array_count, 19581 bcm_cos_t *priority_array, 19582 bcm_cos_queue_t *cosq_array) 19583 { 19584 int rv = BCM_E_NONE; 19585 int endpoint_id; 19586 int qid; 19587 int num_entries_per_profile; 19588 int alloc_size; 19589 endpoint_cos_map_entry_t *entry_array = NULL; 19590 void *entries[1]; 19591 endpoint_queue_map_entry_t qmap_key, qmap_data, qmap_entry; 19592 int qmap_index; 19593 int old_profile_index, new_profile_index; 19594 int endpoint_cos_map_prof_idx; 19595 int old_qid; 19596 int i; 19597 int priority; 19598 uint64 rval64; 19599 19600 if (!_BCM_COSQ_CLASSIFIER_IS_ENDPOINT(classifier_id)) { 19601 return BCM_E_PARAM; 19602 } 19603 endpoint_id = _BCM_COSQ_CLASSIFIER_ENDPOINT_GET(classifier_id); 19604 if (endpoint_id >= _BCM_TD2_NUM_ENDPOINT(unit)) { 19605 return BCM_E_PARAM; 19606 } 19607 if (!_BCM_TD2_ENDPOINT_IS_USED(unit, endpoint_id)) { 19608 return BCM_E_PARAM; 19609 } 19610 19611 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(queue_group)) { 19612 int pipe; 19613 _bcm_td2_cosq_node_t *node; 19614 19615 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_node_get(unit, queue_group, 0, NULL, 19616 NULL, NULL, &node)); 19617 if (port != node->local_port) { 19618 return BCM_E_PARAM; 19619 } 19620 pipe = _BCM_TD2_PORT_TO_PIPE(unit, port); 19621 qid = (pipe == _TD2_XPIPE)? node->hw_index: node->hw_index + 2048; 19622 } else { 19623 return BCM_E_PARAM; 19624 } 19625 19626 /* Allocate an Endpoint CoS Map profile */ 19627 num_entries_per_profile = _TD2_EPCM_ENTRIES_PER_SET; 19628 alloc_size = sizeof(endpoint_cos_map_entry_t) * num_entries_per_profile; 19629 entry_array = sal_alloc(alloc_size, "Endpoint CoS Map Profile"); 19630 if (NULL == entry_array) { 19631 return BCM_E_MEMORY; 19632 } 19633 sal_memset(entry_array, 0, alloc_size); 19634 19635 /* Search Endpoint Queue Map table */ 19636 sal_memcpy(&qmap_key, soc_mem_entry_null(unit, 19637 ENDPOINT_QUEUE_MAPm), sizeof(endpoint_queue_map_entry_t)); 19638 soc_ENDPOINT_QUEUE_MAPm_field32_set(unit, &qmap_key, KEY_TYPEf, 0); 19639 soc_ENDPOINT_QUEUE_MAPm_field32_set(unit, &qmap_key, DEST_PORTf, port); 19640 soc_ENDPOINT_QUEUE_MAPm_field32_set(unit, &qmap_key, EH_QUEUE_TAGf, 19641 endpoint_id); 19642 rv = soc_mem_search(unit, ENDPOINT_QUEUE_MAPm, MEM_BLOCK_ANY, 19643 &qmap_index, &qmap_key, &qmap_data, 0); 19644 if (rv == SOC_E_NOT_FOUND) { 19645 old_profile_index = -1; 19646 } else if (rv == SOC_E_NONE) { 19647 /* Existing entry found. Compare base queue ID and extract 19648 * old Endpoint CoS Map profile. 19649 */ 19650 old_qid = soc_ENDPOINT_QUEUE_MAPm_field32_get(unit, 19651 &qmap_data, ENDPOINT_QUEUE_BASEf); 19652 if (old_qid != qid) { 19653 /* The classifier is already mapped to another queue group */ 19654 sal_free(entry_array); 19655 return BCM_E_EXISTS; 19656 } 19657 endpoint_cos_map_prof_idx = soc_ENDPOINT_QUEUE_MAPm_field32_get(unit, 19658 &qmap_data, ENDPOINT_COS_MAP_PROFILE_INDEXf); 19659 entries[0] = entry_array; 19660 /* 19661 * The index of ENDPOINT_COS_MAP = 19662 * ENDPOINT_COS_MAP_PROFILE_INDEX * 16 + INT_PRI 19663 */ 19664 old_profile_index = endpoint_cos_map_prof_idx * num_entries_per_profile; 19665 rv = soc_profile_mem_get(unit, _BCM_TD2_ENDPOINT_COS_MAP_PROFILE(unit), 19666 old_profile_index, num_entries_per_profile, entries); 19667 if (SOC_FAILURE(rv)) { 19668 sal_free(entry_array); 19669 return rv; 19670 } 19671 } else { 19672 sal_free(entry_array); 19673 return rv; 19674 } 19675 19676 /* Construct or modify Endpoint CoS Map profile and add it */ 19677 for (i = 0; i < array_count; i++) { 19678 priority = priority_array[i]; 19679 if (priority < 0 || priority >= 16) { 19680 sal_free(entry_array); 19681 return BCM_E_PARAM; 19682 } 19683 soc_ENDPOINT_COS_MAPm_field32_set(unit, &entry_array[priority], 19684 ENDPOINT_COS_OFFSETf, cosq_array[i]); 19685 } 19686 entries[0] = entry_array; 19687 rv = soc_profile_mem_add(unit, _BCM_TD2_ENDPOINT_COS_MAP_PROFILE(unit), 19688 entries, num_entries_per_profile, (uint32 *)&new_profile_index); 19689 sal_free(entry_array); 19690 if (SOC_FAILURE(rv)) { 19691 return rv; 19692 } 19693 19694 /* Insert or replace Endpoint Queue Map entry */ 19695 sal_memcpy(&qmap_entry, &qmap_key, sizeof(endpoint_queue_map_entry_t)); 19696 soc_ENDPOINT_QUEUE_MAPm_field32_set(unit, &qmap_entry, VALIDf, 1); 19697 soc_ENDPOINT_QUEUE_MAPm_field32_set(unit, &qmap_entry, 19698 ENDPOINT_QUEUE_BASEf, qid); 19699 endpoint_cos_map_prof_idx = new_profile_index / num_entries_per_profile; 19700 soc_ENDPOINT_QUEUE_MAPm_field32_set(unit, &qmap_entry, 19701 ENDPOINT_COS_MAP_PROFILE_INDEXf, endpoint_cos_map_prof_idx); 19702 rv = soc_mem_insert(unit, ENDPOINT_QUEUE_MAPm, MEM_BLOCK_ALL, &qmap_entry); 19703 if (SOC_FAILURE(rv) && rv != SOC_E_EXISTS) { 19704 return rv; 19705 } 19706 19707 /* Delete old Endpoint CoS Map profile */ 19708 if (old_profile_index != -1) { 19709 SOC_IF_ERROR_RETURN 19710 (soc_profile_mem_delete(unit, 19711 _BCM_TD2_ENDPOINT_COS_MAP_PROFILE(unit), 19712 old_profile_index)); 19713 } 19714 19715 /* Set port's queuing mode to be endpoint queuing */ 19716 SOC_IF_ERROR_RETURN(READ_ING_COS_MODE_64r(unit, port, &rval64)); 19717 if (4 != soc_reg64_field32_get(unit, ING_COS_MODE_64r, rval64, 19718 QUEUE_MODEf)) { 19719 soc_reg64_field32_set(unit, ING_COS_MODE_64r, &rval64, QUEUE_MODEf, 4); 19720 SOC_IF_ERROR_RETURN(WRITE_ING_COS_MODE_64r(unit, port, rval64)); 19721 } 19722 19723 return rv; 19724 } 19725 19726 /* 19727 * Function: 19728 * bcm_td2_cosq_endpoint_map_get 19729 * Purpose: 19730 * Get the mapping from port, classifier, and multiple internal priorities 19731 * to multiple COS queues in a queue group. 19732 * Parameters: 19733 * unit - (IN) Unit number. 19734 * port - (IN) Local port ID 19735 * classifier_id - (IN) Classifier ID 19736 * queue_group - (OUT) Queue group 19737 * array_max - (IN) Size of priority_array and cosq_array 19738 * priority_array - (IN) Array of internal priorities 19739 * cosq_array - (OUT) Array of COS queues 19740 * array_count - (OUT) Size of cosq_array 19741 * Returns: 19742 * BCM_E_xxx 19743 */ 19744 int 19745 bcm_td2_cosq_endpoint_map_get( 19746 int unit, 19747 bcm_port_t port, 19748 int classifier_id, 19749 bcm_gport_t *queue_group, 19750 int array_max, 19751 bcm_cos_t *priority_array, 19752 bcm_cos_queue_t *cosq_array, 19753 int *array_count) 19754 { 19755 int rv = BCM_E_NONE; 19756 int endpoint_id; 19757 endpoint_queue_map_entry_t qmap_key, qmap_data; 19758 int qmap_index; 19759 int qid; 19760 int num_entries_per_profile; 19761 int alloc_size; 19762 endpoint_cos_map_entry_t *entry_array = NULL; 19763 void *entries[1]; 19764 int profile_index; 19765 int endpoint_cos_map_prof_idx; 19766 int i; 19767 int priority; 19768 int pipe, hw_index, qmin, qmax; 19769 _bcm_td2_pipe_resources_t *res = NULL; 19770 19771 if (!_BCM_COSQ_CLASSIFIER_IS_ENDPOINT(classifier_id)) { 19772 return BCM_E_PARAM; 19773 } 19774 endpoint_id = _BCM_COSQ_CLASSIFIER_ENDPOINT_GET(classifier_id); 19775 if (endpoint_id >= _BCM_TD2_NUM_ENDPOINT(unit)) { 19776 return BCM_E_PARAM; 19777 } 19778 if (!_BCM_TD2_ENDPOINT_IS_USED(unit, endpoint_id)) { 19779 return BCM_E_PARAM; 19780 } 19781 19782 /* Search Endpoint Queue Map table */ 19783 sal_memcpy(&qmap_key, soc_mem_entry_null(unit, 19784 ENDPOINT_QUEUE_MAPm), sizeof(endpoint_queue_map_entry_t)); 19785 soc_ENDPOINT_QUEUE_MAPm_field32_set(unit, &qmap_key, KEY_TYPEf, 0); 19786 soc_ENDPOINT_QUEUE_MAPm_field32_set(unit, &qmap_key, DEST_PORTf, port); 19787 soc_ENDPOINT_QUEUE_MAPm_field32_set(unit, &qmap_key, EH_QUEUE_TAGf, 19788 endpoint_id); 19789 SOC_IF_ERROR_RETURN(soc_mem_search(unit, ENDPOINT_QUEUE_MAPm, MEM_BLOCK_ANY, 19790 &qmap_index, &qmap_key, &qmap_data, 0)); 19791 19792 /* Get queue group */ 19793 qid = soc_ENDPOINT_QUEUE_MAPm_field32_get(unit, &qmap_data, 19794 ENDPOINT_QUEUE_BASEf); 19795 pipe = _BCM_TD2_PORT_TO_PIPE(unit, port); 19796 res = _BCM_TD2_PRESOURCES(_bcm_td2_mmu_info[unit], pipe); 19797 hw_index = (pipe == _TD2_XPIPE)? qid: qid - 2048; 19798 19799 qmin = res->num_base_queues + (pipe * _BCM_TD2_NUM_L2_UC_LEAVES_PER_PIPE); 19800 qmax = (pipe + 1) * _BCM_TD2_NUM_L2_UC_LEAVES_PER_PIPE; 19801 19802 for (i = qmin; i < qmax; i++) { 19803 if ((res->p_queue_node[i].local_port == port) && 19804 (res->p_queue_node[i].hw_index == hw_index)) { 19805 *queue_group = res->p_queue_node[i].gport; 19806 break; 19807 } 19808 } 19809 19810 if (i == qmax) { 19811 return BCM_E_NOT_FOUND; 19812 } 19813 19814 /* Get Endpoint CoS Map profile */ 19815 num_entries_per_profile = _TD2_EPCM_ENTRIES_PER_SET; 19816 alloc_size = sizeof(endpoint_cos_map_entry_t) * num_entries_per_profile; 19817 entry_array = sal_alloc(alloc_size, "Endpoint CoS Map Profile"); 19818 if (NULL == entry_array) { 19819 return BCM_E_MEMORY; 19820 } 19821 sal_memset(entry_array, 0, alloc_size); 19822 entries[0] = entry_array; 19823 endpoint_cos_map_prof_idx = soc_ENDPOINT_QUEUE_MAPm_field32_get(unit, &qmap_data, 19824 ENDPOINT_COS_MAP_PROFILE_INDEXf); 19825 /* 19826 * The index of ENDPOINT_COS_MAP = 19827 * ENDPOINT_COS_MAP_PROFILE_INDEX * 16 + INT_PRI 19828 */ 19829 profile_index = endpoint_cos_map_prof_idx * num_entries_per_profile; 19830 rv = soc_profile_mem_get(unit, _BCM_TD2_ENDPOINT_COS_MAP_PROFILE(unit), 19831 profile_index, num_entries_per_profile, entries); 19832 if (SOC_FAILURE(rv)) { 19833 sal_free(entry_array); 19834 return rv; 19835 } 19836 19837 /* Get internal priority to CoS mapping */ 19838 if (array_max == 0) { 19839 if (NULL != array_count) { 19840 *array_count = num_entries_per_profile; 19841 } 19842 } else { 19843 *array_count = 0; 19844 for (i = 0; i < array_max; i++) { 19845 priority = priority_array[i]; 19846 if (priority < 0 || priority >= 16) { 19847 sal_free(entry_array); 19848 return BCM_E_PARAM; 19849 } 19850 cosq_array[i] = soc_ENDPOINT_COS_MAPm_field32_get(unit, 19851 &entry_array[priority], ENDPOINT_COS_OFFSETf); 19852 (*array_count)++; 19853 } 19854 } 19855 19856 sal_free(entry_array); 19857 return rv; 19858 } 19859 19860 /* 19861 * Function: 19862 * bcm_td2_cosq_endpoint_map_clear 19863 * Purpose: 19864 * Clear the mapping from port, classifier, and internal priorities 19865 * to COS queues in a queue group. 19866 * Parameters: 19867 * unit - (IN) Unit number. 19868 * port - (IN) Local port ID 19869 * classifier_id - (IN) Classifier ID 19870 * Returns: 19871 * BCM_E_xxx 19872 */ 19873 int 19874 bcm_td2_cosq_endpoint_map_clear( 19875 int unit, 19876 bcm_gport_t port, 19877 int classifier_id) 19878 { 19879 int endpoint_id; 19880 endpoint_queue_map_entry_t qmap_key, qmap_data; 19881 int profile_index; 19882 int endpoint_cos_map_prof_idx; 19883 19884 if (!_BCM_COSQ_CLASSIFIER_IS_ENDPOINT(classifier_id)) { 19885 return BCM_E_PARAM; 19886 } 19887 endpoint_id = _BCM_COSQ_CLASSIFIER_ENDPOINT_GET(classifier_id); 19888 if (endpoint_id >= _BCM_TD2_NUM_ENDPOINT(unit)) { 19889 return BCM_E_PARAM; 19890 } 19891 if (!_BCM_TD2_ENDPOINT_IS_USED(unit, endpoint_id)) { 19892 return BCM_E_PARAM; 19893 } 19894 19895 /* Delete (port, endpoint_id) entry from Endpoint Queue Map table */ 19896 sal_memcpy(&qmap_key, soc_mem_entry_null(unit, 19897 ENDPOINT_QUEUE_MAPm), sizeof(endpoint_queue_map_entry_t)); 19898 soc_ENDPOINT_QUEUE_MAPm_field32_set(unit, &qmap_key, KEY_TYPEf, 0); 19899 soc_ENDPOINT_QUEUE_MAPm_field32_set(unit, &qmap_key, DEST_PORTf, port); 19900 soc_ENDPOINT_QUEUE_MAPm_field32_set(unit, &qmap_key, EH_QUEUE_TAGf, 19901 endpoint_id); 19902 SOC_IF_ERROR_RETURN(soc_mem_delete_return_old(unit, ENDPOINT_QUEUE_MAPm, 19903 MEM_BLOCK_ALL, &qmap_key, &qmap_data)); 19904 19905 /* Delete priority to CoS mapping profile */ 19906 endpoint_cos_map_prof_idx = soc_ENDPOINT_QUEUE_MAPm_field32_get(unit, &qmap_data, 19907 ENDPOINT_COS_MAP_PROFILE_INDEXf); 19908 /* 19909 * The index of ENDPOINT_COS_MAP = 19910 * ENDPOINT_COS_MAP_PROFILE_INDEX * 16 + INT_PRI 19911 */ 19912 profile_index = endpoint_cos_map_prof_idx * 16; 19913 SOC_IF_ERROR_RETURN(soc_profile_mem_delete(unit, 19914 _BCM_TD2_ENDPOINT_COS_MAP_PROFILE(unit), profile_index)); 19915 19916 return BCM_E_NONE; 19917 } 19918 19919 /* 19920 * Function: 19921 * bcm_td2_cosq_field_classifier_get 19922 * Purpose: 19923 * Get classifier type information. 19924 * Parameters: 19925 * unit - (IN) Unit number. 19926 * classifier_id - (IN) Classifier ID 19927 * classifier - (OUT) Classifier info 19928 * Returns: 19929 * BCM_E_xxx 19930 */ 19931 int 19932 bcm_td2_cosq_field_classifier_get( 19933 int unit, 19934 int classifier_id, 19935 bcm_cosq_classifier_t *classifier) 19936 { 19937 if (classifier == NULL) { 19938 return BCM_E_PARAM; 19939 } 19940 sal_memset(classifier, 0, sizeof(bcm_cosq_classifier_t)); 19941 19942 if (_BCM_COSQ_CLASSIFIER_IS_FIELD(classifier_id)) { 19943 classifier->flags |= BCM_COSQ_CLASSIFIER_FIELD; 19944 } 19945 19946 return BCM_E_NONE; 19947 } 19948 19949 19950 19951 /* 19952 * Function: 19953 * bcm_td2_cosq_field_classifier_id_create 19954 * Purpose: 19955 * Create a cosq classifier. 19956 * Parameters: 19957 * unit - (IN) Unit number. 19958 * classifier - (IN) Classifier attributes 19959 * classifier_id - (OUT) Classifier ID 19960 * Returns: 19961 * BCM_E_xxx 19962 */ 19963 int 19964 bcm_td2_cosq_field_classifier_id_create( 19965 int unit, 19966 bcm_cosq_classifier_t *classifier, 19967 int *classifier_id) 19968 { 19969 int rv; 19970 int ref_count = 0; 19971 int ent_per_set = _TD2_NUM_INTERNAL_PRI; 19972 int i; 19973 19974 if (NULL == classifier || NULL == classifier_id) { 19975 return BCM_E_PARAM; 19976 } 19977 19978 for (i = 0; i < SOC_MEM_SIZE(unit, IFP_COS_MAPm); i += ent_per_set) { 19979 rv = soc_profile_mem_ref_count_get( 19980 unit, _bcm_td2_ifp_cos_map_profile[unit], i, &ref_count); 19981 if (SOC_FAILURE(rv)) { 19982 return rv; 19983 } 19984 if (0 == ref_count) { 19985 break; 19986 } 19987 } 19988 19989 if (i >= SOC_MEM_SIZE(unit, IFP_COS_MAPm) && ref_count != 0) { 19990 *classifier_id = 0; 19991 return BCM_E_RESOURCE; 19992 } 19993 19994 _BCM_COSQ_CLASSIFIER_FIELD_SET(*classifier_id, (i / ent_per_set)); 19995 19996 return BCM_E_NONE; 19997 } 19998 19999 20000 /* 20001 * Function: 20002 * bcm_td2_cosq_field_classifier_map_set 20003 * Purpose: 20004 * Set internal priority to ingress field processor CoS queue 20005 * override mapping. 20006 * Parameters: 20007 * unit - (IN) Unit number. 20008 * classifier_id - (IN) Classifier ID 20009 * count - (IN) Number of elements in priority_array and 20010 * cosq_array 20011 * priority_array - (IN) Array of internal priorities 20012 * cosq_array - (IN) Array of COS queues 20013 * Returns: 20014 * BCM_E_xxx 20015 */ 20016 int 20017 bcm_td2_cosq_field_classifier_map_set( 20018 int unit, 20019 int classifier_id, 20020 int count, 20021 bcm_cos_t *priority_array, 20022 bcm_cos_queue_t *cosq_array) 20023 { 20024 int rv; 20025 int i; 20026 int max_entries = _TD2_NUM_INTERNAL_PRI; 20027 uint32 index; 20028 void *entries[1]; 20029 ifp_cos_map_entry_t ent_buf[_TD2_NUM_INTERNAL_PRI]; 20030 int field_width; 20031 int ref_count = 0; 20032 20033 /* Input parameter check. */ 20034 if (!_BCM_COSQ_CLASSIFIER_IS_FIELD(classifier_id)) { 20035 return BCM_E_PARAM; 20036 } 20037 20038 if (NULL == priority_array || NULL == cosq_array) { 20039 return BCM_E_PARAM; 20040 } 20041 20042 if (count > max_entries) { 20043 return BCM_E_PARAM; 20044 } 20045 20046 field_width = soc_mem_field_length(unit, IFP_COS_MAPm, IFP_COSf); 20047 sal_memset(ent_buf, 0, sizeof(ifp_cos_map_entry_t) * max_entries); 20048 entries[0] = ent_buf; 20049 20050 for (i = 0; i < count; i++) { 20051 if (priority_array[i] < max_entries) { 20052 if (cosq_array[i] >= (1 << field_width)) { 20053 return BCM_E_PARAM; 20054 } 20055 soc_mem_field32_set(unit, IFP_COS_MAPm, &ent_buf[priority_array[i]], 20056 IFP_COSf, cosq_array[i]); 20057 } 20058 } 20059 20060 index = _BCM_COSQ_CLASSIFIER_FIELD_GET(classifier_id); 20061 SOC_IF_ERROR_RETURN( 20062 soc_profile_mem_ref_count_get(unit, _bcm_td2_ifp_cos_map_profile[unit], 20063 index * max_entries, &ref_count)); 20064 20065 if (ref_count == 0) { 20066 rv = soc_profile_mem_add(unit, _bcm_td2_ifp_cos_map_profile[unit], 20067 entries, max_entries, &index); 20068 } else { 20069 rv = soc_profile_mem_set(unit, _bcm_td2_ifp_cos_map_profile[unit], 20070 entries, index * max_entries); 20071 if (rv == SOC_E_NONE) { 20072 /* decrease the profile ref_count increased by mem_set */ 20073 rv = soc_profile_mem_delete(unit, 20074 _bcm_td2_ifp_cos_map_profile[unit], 20075 index * max_entries); 20076 } 20077 } 20078 return rv; 20079 } 20080 20081 20082 /* 20083 * Function: 20084 * bcm_td2_cosq_field_classifier_map_get 20085 * Purpose: 20086 * Get internal priority to ingress field processor CoS queue 20087 * override mapping information. 20088 * Parameters: 20089 * unit - (IN) Unit number. 20090 * classifier_id - (IN) Classifier ID 20091 * array_max - (IN) Size of priority_array and cosq_array 20092 * priority_array - (IN) Array of internal priorities 20093 * cosq_array - (OUT) Array of COS queues 20094 * array_count - (OUT) Size of cosq_array 20095 * Returns: 20096 * BCM_E_xxx 20097 */ 20098 int 20099 bcm_td2_cosq_field_classifier_map_get( 20100 int unit, 20101 int classifier_id, 20102 int array_max, 20103 bcm_cos_t *priority_array, 20104 bcm_cos_queue_t *cosq_array, 20105 int *array_count) 20106 { 20107 int rv; 20108 int i; 20109 int ent_per_set = _TD2_NUM_INTERNAL_PRI; 20110 uint32 index; 20111 void *entries[1]; 20112 ifp_cos_map_entry_t ent_buf[_TD2_NUM_INTERNAL_PRI]; 20113 20114 /* Input parameter check. */ 20115 if (NULL == priority_array || NULL == cosq_array || NULL == array_count) { 20116 return BCM_E_PARAM; 20117 } 20118 20119 sal_memset(ent_buf, 0, sizeof(ifp_cos_map_entry_t) * ent_per_set); 20120 entries[0] = ent_buf; 20121 20122 /* Get profile table entry set base index. */ 20123 index = _BCM_COSQ_CLASSIFIER_FIELD_GET(classifier_id); 20124 20125 /* Read out entries from profile table into allocated buffer. */ 20126 rv = soc_profile_mem_get(unit, _bcm_td2_ifp_cos_map_profile[unit], 20127 index * ent_per_set, ent_per_set, entries); 20128 if (SOC_FAILURE(rv)) { 20129 return rv; 20130 } 20131 20132 *array_count = array_max > ent_per_set ? ent_per_set : array_max; 20133 20134 /* Copy values into API OUT parameters. */ 20135 for (i = 0; i < *array_count; i++) { 20136 if (priority_array[i] >= _TD2_NUM_INTERNAL_PRI) { 20137 return BCM_E_PARAM; 20138 } 20139 cosq_array[i] = soc_mem_field32_get(unit, IFP_COS_MAPm, 20140 &ent_buf[priority_array[i]], 20141 IFP_COSf); 20142 } 20143 20144 return BCM_E_NONE; 20145 } 20146 20147 20148 /* 20149 * Function: 20150 * bcm_td2_cosq_field_classifier_map_clear 20151 * Purpose: 20152 * Delete an internal priority to ingress field processor CoS queue 20153 * override mapping profile set. 20154 * Parameters: 20155 * unit - (IN) Unit number. 20156 * classifier_id - (IN) Classifier ID 20157 * Returns: 20158 * BCM_E_xxx 20159 */ 20160 int 20161 bcm_td2_cosq_field_classifier_map_clear(int unit, int classifier_id) 20162 { 20163 int ent_per_set = _TD2_NUM_INTERNAL_PRI; 20164 uint32 index; 20165 20166 /* Get profile table entry set base index. */ 20167 index = _BCM_COSQ_CLASSIFIER_FIELD_GET(classifier_id); 20168 20169 /* Delete the profile entries set. */ 20170 SOC_IF_ERROR_RETURN 20171 (soc_profile_mem_delete(unit, 20172 _bcm_td2_ifp_cos_map_profile[unit], 20173 index * ent_per_set)); 20174 return BCM_E_NONE; 20175 } 20176 20177 20178 /* 20179 * Function: 20180 * bcm_td2_cosq_field_classifier_id_destroy 20181 * Purpose: 20182 * Free resource associated with this field classifier id. 20183 * Parameters: 20184 * unit - (IN) Unit number. 20185 * classifier_id - (IN) Classifier ID 20186 * Returns: 20187 * BCM_E_xxx 20188 */ 20189 int 20190 bcm_td2_cosq_field_classifier_id_destroy(int unit, int classifier_id) 20191 { 20192 return BCM_E_NONE; 20193 } 20194 20195 /* 20196 * Function: 20197 * bcm_td_cosq_cpu_cosq_enable_set 20198 * Purpose: 20199 * To enable/disable Rx of packets on the specified CPU cosq. 20200 * Parameters: 20201 * unit - (IN) Unit number. 20202 * cosq - (IN) CPU Cosq ID 20203 * enable - (IN) Enable/Disable 20204 * Returns: 20205 * BCM_E_xxx 20206 */ 20207 int 20208 bcm_td2_cosq_cpu_cosq_enable_set( 20209 int unit, 20210 bcm_cos_queue_t cosq, 20211 int enable) 20212 { 20213 uint32 entry[SOC_MAX_MEM_WORDS]; 20214 int i, index, enable_status; 20215 _bcm_td2_cosq_cpu_cosq_config_t *cpu_cosq; 20216 soc_info_t *si; 20217 soc_mem_t thdm_mem[] = { 20218 MMU_THDM_DB_QUEUE_CONFIG_0m, 20219 MMU_THDM_MCQE_QUEUE_CONFIG_0m 20220 }; 20221 20222 si = &SOC_INFO(unit); 20223 20224 if ((cosq < 0) || (cosq >= si->num_cpu_cosq)) { 20225 return BCM_E_PARAM; 20226 } 20227 20228 cpu_cosq = _bcm_td2_cosq_cpu_cosq_config[unit][cosq]; 20229 20230 if (!cpu_cosq) { 20231 return BCM_E_INTERNAL; 20232 } 20233 if (enable) { 20234 enable = 1; 20235 } 20236 BCM_IF_ERROR_RETURN(bcm_td2_cosq_cpu_cosq_enable_get(unit, cosq, 20237 &enable_status)); 20238 if (enable == enable_status) { 20239 return BCM_E_NONE; 20240 } 20241 20242 /* CPU MC cosq's range from 520 - 568. 0-519 are MC's of Regular ports */ 20243 index = 520 + cosq; 20244 20245 for (i = 0; i < 2; i++) { 20246 BCM_IF_ERROR_RETURN 20247 (soc_mem_read(unit, thdm_mem[i], MEM_BLOCK_ALL, index, &entry)); 20248 20249 if (enable) { 20250 soc_mem_field32_set(unit, thdm_mem[i], &entry, 20251 Q_MIN_LIMITf, cpu_cosq->q_min_limit[i]); 20252 soc_mem_field32_set(unit, thdm_mem[i], &entry, 20253 Q_SHARED_LIMITf, cpu_cosq->q_shared_limit[i]); 20254 } 20255 else { 20256 cpu_cosq->q_min_limit[i] = soc_mem_field32_get(unit, 20257 thdm_mem[i], 20258 &entry, 20259 Q_MIN_LIMITf); 20260 cpu_cosq->q_shared_limit[i] = soc_mem_field32_get(unit, 20261 thdm_mem[i], 20262 &entry, 20263 Q_SHARED_LIMITf); 20264 cpu_cosq->q_limit_dynamic[i] = soc_mem_field32_get(unit, 20265 thdm_mem[i], 20266 &entry, 20267 Q_LIMIT_DYNAMICf); 20268 cpu_cosq->q_limit_enable[i] = soc_mem_field32_get(unit, 20269 thdm_mem[i], 20270 &entry, 20271 Q_LIMIT_ENABLEf); 20272 soc_mem_field32_set(unit, thdm_mem[i], &entry, Q_MIN_LIMITf, 0); 20273 soc_mem_field32_set(unit, thdm_mem[i], &entry, Q_SHARED_LIMITf, 0); 20274 } 20275 soc_mem_field32_set(unit, thdm_mem[i], &entry, 20276 Q_LIMIT_DYNAMICf, enable ? cpu_cosq->q_limit_dynamic[i] : 0); 20277 soc_mem_field32_set(unit, thdm_mem[i], &entry, 20278 Q_LIMIT_ENABLEf, enable ? cpu_cosq->q_limit_enable[i] : 1); 20279 cpu_cosq->enable = enable; 20280 BCM_IF_ERROR_RETURN( 20281 soc_mem_write(unit, thdm_mem[i], MEM_BLOCK_ALL, index, &entry)); 20282 } 20283 20284 return BCM_E_NONE; 20285 } 20286 20287 /* 20288 * Function: 20289 * bcm_td_cosq_cpu_cosq_enable_get 20290 * Purpose: 20291 * To get enable/disable status on Rx of packets on the specified CPU cosq. 20292 * Parameters: 20293 * unit - (IN) Unit number. 20294 * cosq - (IN) CPU Cosq ID 20295 * enable - (OUT) Enable/Disable 20296 * Returns: 20297 * BCM_E_xxx 20298 */ 20299 int 20300 bcm_td2_cosq_cpu_cosq_enable_get( 20301 int unit, 20302 bcm_cos_queue_t cosq, 20303 int *enable) 20304 { 20305 _bcm_td2_cosq_cpu_cosq_config_t *cpu_cosq; 20306 soc_info_t *si; 20307 int index, hw_enable; 20308 uint32 entry[SOC_MAX_MEM_WORDS]; 20309 soc_field_t min_limit, shared_limit, limit_enable, dynamic_enable; 20310 soc_mem_t thdm_mem = MMU_THDM_DB_QUEUE_CONFIG_0m; 20311 20312 si = &SOC_INFO(unit); 20313 20314 if ((cosq < 0) || (cosq >= si->num_cpu_cosq)) { 20315 return BCM_E_PARAM; 20316 } 20317 20318 cpu_cosq = _bcm_td2_cosq_cpu_cosq_config[unit][cosq]; 20319 if (!cpu_cosq) { 20320 return BCM_E_INTERNAL; 20321 } 20322 20323 /* CPU MC cosq's range from 520 - 568. 0-519 are MC's of Regular ports */ 20324 index = 520 + cosq; 20325 hw_enable = 1; 20326 /* Sync up software record with hardware status. */ 20327 BCM_IF_ERROR_RETURN(soc_mem_read(unit, thdm_mem, MEM_BLOCK_ALL, 20328 index, &entry)); 20329 min_limit = soc_mem_field32_get(unit, thdm_mem, &entry, 20330 Q_MIN_LIMITf); 20331 shared_limit = soc_mem_field32_get(unit, thdm_mem, &entry, 20332 Q_SHARED_LIMITf); 20333 limit_enable = soc_mem_field32_get(unit, thdm_mem, &entry, 20334 Q_LIMIT_ENABLEf); 20335 dynamic_enable = soc_mem_field32_get(unit, thdm_mem, &entry, 20336 Q_LIMIT_DYNAMICf); 20337 if (limit_enable && (dynamic_enable == 0) && 20338 (min_limit == 0) && (shared_limit == 0)) { 20339 hw_enable = 0; 20340 } 20341 cpu_cosq->enable = hw_enable; 20342 20343 *enable = cpu_cosq->enable; 20344 return BCM_E_NONE; 20345 } 20346 20347 /* 20348 * Function: 20349 * bcm_td2_cosq_service_classifier_id_create 20350 * Purpose: 20351 * Create an endpoint. 20352 * Parameters: 20353 * unit - (IN) Unit number. 20354 * classifier - (IN) Classifier attributes 20355 * classifier_id - (OUT) Classifier ID 20356 * Returns: 20357 * BCM_E_xxx 20358 */ 20359 int 20360 bcm_td2_cosq_service_classifier_id_create( 20361 int unit, 20362 bcm_cosq_classifier_t *classifier, 20363 int *classifier_id) 20364 { 20365 if (NULL == classifier || NULL == classifier_id) { 20366 return BCM_E_PARAM; 20367 } 20368 20369 _BCM_COSQ_CLASSIFIER_SERVICE_SET(*classifier_id, classifier->vlan); 20370 return BCM_E_NONE; 20371 } 20372 20373 /* 20374 * Function: 20375 * bcm_td2_cosq_service_classifier_id_destroy 20376 * Purpose: 20377 * free resource associated with this service classifier id. 20378 * Parameters: 20379 * unit - (IN) Unit number. 20380 * classifier_id - (IN) Classifier ID 20381 * Returns: 20382 * BCM_E_xxx 20383 */ 20384 int 20385 bcm_td2_cosq_service_classifier_id_destroy( 20386 int unit, 20387 int classifier_id) 20388 { 20389 return BCM_E_NONE; 20390 } 20391 20392 /* 20393 * Function: 20394 * bcm_td2_cosq_service_classifier_get 20395 * Purpose: 20396 * Get info about an endpoint. 20397 * Parameters: 20398 * unit - (IN) Unit number. 20399 * classifier_id - (IN) Classifier ID 20400 * classifier - (OUT) Classifier info 20401 * Returns: 20402 * BCM_E_xxx 20403 */ 20404 int 20405 bcm_td2_cosq_service_classifier_get( 20406 int unit, 20407 int classifier_id, 20408 bcm_cosq_classifier_t *classifier) 20409 { 20410 int val = 0; 20411 20412 sal_memset(classifier, 0, sizeof(bcm_cosq_classifier_t)); 20413 20414 val = _BCM_COSQ_CLASSIFIER_SERVICE_GET(classifier_id); 20415 20416 if (val > BCM_VLAN_MAX) { 20417 /* VFI classifier */ 20418 classifier->flags = BCM_COSQ_CLASSIFIER_VFI; 20419 classifier->vfi_index = val - BCM_VLAN_MAX - 1; 20420 } else { 20421 classifier->flags = BCM_COSQ_CLASSIFIER_VLAN; 20422 classifier->vlan = val; 20423 } 20424 return BCM_E_NONE; 20425 } 20426 20427 /* 20428 * Function: 20429 * bcm_td2_cosq_service_map_set 20430 * Purpose: 20431 * Set the mapping from port, classifier, and multiple internal priorities 20432 * to multiple COS queues in a queue group. 20433 * Parameters: 20434 * unit - (IN) Unit number. 20435 * port - (IN) local port ID 20436 * classifier_id - (IN) Classifier ID 20437 * queue_group - (IN) Base queue ID 20438 * array_count - (IN) Number of elements in priority_array and 20439 * cosq_array 20440 * priority_array - (IN) Array of internal priorities 20441 * cosq_array - (IN) Array of COS queues 20442 * Returns: 20443 * BCM_E_xxx 20444 */ 20445 int 20446 bcm_td2_cosq_service_map_set( 20447 int unit, 20448 bcm_port_t port, 20449 int classifier_id, 20450 bcm_gport_t queue_group, 20451 int array_count, 20452 bcm_cos_t *priority_array, 20453 bcm_cos_queue_t *cosq_array) 20454 { 20455 service_queue_map_entry_t sqm; 20456 service_port_map_entry_t *spm = NULL; 20457 service_cos_map_entry_t *scm = NULL; 20458 void *spm_entries[1]; 20459 void *scm_entries[1]; 20460 int rv = BCM_E_NONE; 20461 int i, valid_cosq, alloc_size, exists = 0; 20462 int local_port, vid, qid, cos_offset = 0; 20463 int port_offset, port_offset_old; 20464 int qptr_old, qptr_new; 20465 int pipe; 20466 uint32 scm_idx, scm_idx_old = 0, spm_idx, spm_idx_old = 0; 20467 _bcm_td2_cosq_node_t *node,*cur_node; 20468 soc_profile_mem_t *spm_profile_mem, *scm_profile_mem; 20469 /* 20470 * The port_offset= 0 is treated as the invalid offset so that 20471 * the ports without being service map set can be recognized easily by software. 20472 * Accordingly, The valid port_offset needs to be at least 1 for a given port. 20473 * the queue base to be written into SERVICE_QUEUE_PTRf will 20474 * be (the actual base - 1). 20475 */ 20476 #define VALID_PORT_OFFSET_MIN 1 20477 20478 if (!_BCM_COSQ_CLASSIFIER_IS_SERVICE(classifier_id)) { 20479 return BCM_E_PARAM; 20480 } 20481 20482 /* index above 4K is for VFI */ 20483 vid = _BCM_COSQ_CLASSIFIER_SERVICE_GET(classifier_id); 20484 if (vid < 0 || vid >= SOC_MEM_SIZE(unit, SERVICE_QUEUE_MAPm)) { 20485 return BCM_E_PARAM; 20486 } 20487 20488 if (array_count > _TD2_SCM_ENTRIES_PER_SET) { 20489 return BCM_E_PARAM; 20490 } 20491 scm_profile_mem = _bcm_td2_service_cos_map_profile[unit]; 20492 spm_profile_mem = _bcm_td2_service_port_map_profile[unit]; 20493 20494 BCM_IF_ERROR_RETURN( 20495 _bcm_td2_cosq_node_get(unit, queue_group, 0, NULL, 20496 &local_port, &qid, &node)); 20497 if (node->attached_to_input < 0) { 20498 return BCM_E_PARAM; 20499 } 20500 20501 pipe = _BCM_TD2_PORT_TO_PIPE(unit, port); 20502 qid = (pipe == _TD2_XPIPE)? node->hw_index: node->hw_index + 2048; 20503 20504 for (i = 0; i < array_count; i++) { 20505 valid_cosq= 0; 20506 for (cur_node = node->parent->child; 20507 cur_node != NULL; 20508 cur_node = cur_node->sibling) { 20509 if (cosq_array[i] == cur_node->attached_to_input) { 20510 valid_cosq = 1; 20511 break; 20512 } 20513 } 20514 if(valid_cosq == 0){ 20515 return BCM_E_PARAM; 20516 } 20517 } 20518 20519 sal_memset(&sqm, 0, sizeof(service_queue_map_entry_t)); 20520 SOC_IF_ERROR_RETURN( 20521 soc_mem_read(unit, SERVICE_QUEUE_MAPm, MEM_BLOCK_ANY, (int)vid, &sqm)); 20522 20523 if (soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, &sqm, VALIDf)) { 20524 exists = 1; 20525 } else { 20526 exists = 0; 20527 } 20528 20529 alloc_size = sizeof(service_port_map_entry_t) * _TD2_SPM_ENTRIES_PER_SET; 20530 spm = sal_alloc(alloc_size, "SERVICE_PORT_MAP temp Mem"); 20531 if (spm == NULL) { 20532 rv = BCM_E_MEMORY; 20533 goto cleanup; 20534 } 20535 sal_memset(spm, 0, alloc_size); 20536 spm_entries[0] = spm; 20537 20538 alloc_size = sizeof(service_cos_map_entry_t) * _TD2_SCM_ENTRIES_PER_SET; 20539 scm = sal_alloc(alloc_size, "SERVICE_COS_MAP temp Mem"); 20540 if (scm == NULL) { 20541 rv = BCM_E_MEMORY; 20542 goto cleanup; 20543 } 20544 sal_memset(scm, 0, alloc_size); 20545 scm_entries[0] = scm; 20546 20547 /* 1. program the SERVICE_COS_MAPm. */ 20548 if (!exists) { 20549 for (i = 0; i < array_count; i++) { 20550 if (priority_array[i] < _TD2_SCM_ENTRIES_PER_SET) { 20551 soc_mem_field32_set(unit, SERVICE_COS_MAPm, 20552 &scm[priority_array[i]], 20553 SERVICE_COS_OFFSETf, cosq_array[i]); 20554 } 20555 } 20556 20557 rv = soc_profile_mem_add(unit, scm_profile_mem, scm_entries, 20558 _TD2_SCM_ENTRIES_PER_SET, &scm_idx); 20559 if (rv != SOC_E_NONE) { 20560 goto cleanup; 20561 } 20562 } else { 20563 /* 20564 * only one service_cos_map profile is allowed per vlan/vfi. 20565 * If the subsequent profile doesn't match the existing one, 20566 * Then update the old profile, the new map may be added by other port. 20567 */ 20568 scm_idx_old = _TD2_SCM_ENTRIES_PER_SET * 20569 soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, &sqm, 20570 SERVICE_COS_PROFILE_INDEXf); 20571 rv = soc_profile_mem_get(unit, scm_profile_mem, scm_idx_old, 20572 _TD2_SCM_ENTRIES_PER_SET, scm_entries); 20573 if (rv != SOC_E_NONE) { 20574 goto cleanup; 20575 } 20576 20577 for (i = 0; i < array_count; i++) { 20578 cos_offset = soc_mem_field32_get(unit, SERVICE_COS_MAPm, 20579 &scm[priority_array[i]], 20580 SERVICE_COS_OFFSETf); 20581 if (cosq_array[i] != cos_offset) { 20582 if (priority_array[i] < _TD2_SCM_ENTRIES_PER_SET) { 20583 soc_mem_field32_set(unit, SERVICE_COS_MAPm, 20584 &scm[priority_array[i]], 20585 SERVICE_COS_OFFSETf, cosq_array[i]); 20586 } 20587 } 20588 } 20589 20590 rv = soc_profile_mem_add(unit, scm_profile_mem, scm_entries, 20591 _TD2_SCM_ENTRIES_PER_SET, &scm_idx); 20592 if (rv != SOC_E_NONE) { 20593 goto cleanup; 20594 } 20595 20596 if (scm_idx_old != scm_idx) { 20597 rv = soc_profile_mem_delete(unit, scm_profile_mem, scm_idx_old); 20598 if (rv != SOC_E_NONE) { 20599 goto cleanup; 20600 } 20601 } 20602 20603 } 20604 20605 /* 2. program the SERVICE_PORT_MAPm. */ 20606 if (!exists) { 20607 port_offset = VALID_PORT_OFFSET_MIN; 20608 soc_mem_field32_set(unit, SERVICE_PORT_MAPm, &spm[local_port], 20609 SERVICE_PORT_OFFSETf, port_offset); 20610 } else { 20611 spm_idx_old = _TD2_SPM_ENTRIES_PER_SET * 20612 soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, &sqm, 20613 SERVICE_PORT_PROFILE_INDEXf); 20614 rv = soc_profile_mem_get(unit, spm_profile_mem, spm_idx_old, 20615 _TD2_SPM_ENTRIES_PER_SET, spm_entries); 20616 if (!(rv == SOC_E_NOT_FOUND || rv == SOC_E_NONE)) { 20617 goto cleanup; 20618 } 20619 20620 qptr_old = soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, 20621 &sqm, SERVICE_QUEUE_PTRf); 20622 if (qid <= qptr_old) { 20623 qptr_new = qid - VALID_PORT_OFFSET_MIN; 20624 for (i = 0; i < _TD2_SPM_ENTRIES_PER_SET; i++) { 20625 port_offset_old = soc_mem_field32_get(unit, SERVICE_PORT_MAPm, 20626 &spm[i], 20627 SERVICE_PORT_OFFSETf); 20628 if (i == local_port) { 20629 port_offset = VALID_PORT_OFFSET_MIN; 20630 } else if (!port_offset_old) { 20631 /* 20632 * For the old port_offsets with 0, 20633 * the new port_offsest are still 0. 20634 */ 20635 continue; 20636 } else { 20637 port_offset = qptr_old + port_offset_old - qptr_new; 20638 } 20639 soc_mem_field32_set(unit, SERVICE_PORT_MAPm, &spm[i], 20640 SERVICE_PORT_OFFSETf, port_offset); 20641 } 20642 } else { 20643 port_offset = qid - qptr_old; 20644 soc_mem_field32_set(unit, SERVICE_PORT_MAPm, &spm[local_port], 20645 SERVICE_PORT_OFFSETf, port_offset); 20646 } 20647 } 20648 rv = soc_profile_mem_add(unit, spm_profile_mem, 20649 spm_entries, _TD2_SPM_ENTRIES_PER_SET, &spm_idx); 20650 if (rv != SOC_E_NONE) { 20651 goto cleanup; 20652 } 20653 20654 /* 3. program the SERVICE_QUEUE_MAPm */ 20655 if (!exists) { 20656 qptr_new = qid - VALID_PORT_OFFSET_MIN; 20657 } else { 20658 qptr_old = soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, 20659 &sqm, SERVICE_QUEUE_PTRf); 20660 if (qid <= qptr_old) { 20661 qptr_new = qid - VALID_PORT_OFFSET_MIN; 20662 } else { 20663 qptr_new = qptr_old; 20664 } 20665 } 20666 20667 soc_mem_field32_set(unit, SERVICE_QUEUE_MAPm, &sqm, 20668 SERVICE_QUEUE_PTRf, qptr_new); 20669 soc_mem_field32_set(unit, SERVICE_QUEUE_MAPm, &sqm, 20670 SERVICE_COS_PROFILE_INDEXf, 20671 scm_idx / _TD2_SCM_ENTRIES_PER_SET); 20672 soc_mem_field32_set(unit, SERVICE_QUEUE_MAPm, &sqm, 20673 SERVICE_PORT_PROFILE_INDEXf, 20674 spm_idx / _TD2_SPM_ENTRIES_PER_SET); 20675 /* use port indexed and cos indexed for this base queue */ 20676 soc_mem_field32_set(unit, SERVICE_QUEUE_MAPm, &sqm, 20677 SERVICE_QUEUE_MODELf, 3); 20678 soc_mem_field32_set(unit, SERVICE_QUEUE_MAPm, &sqm, VALIDf, 1); 20679 20680 rv = soc_mem_write(unit, SERVICE_QUEUE_MAPm, MEM_BLOCK_ALL, (int)vid, &sqm); 20681 20682 if (exists) { 20683 if (spm_idx_old != spm_idx) { 20684 rv = soc_profile_mem_delete(unit, spm_profile_mem, spm_idx_old); 20685 } 20686 } 20687 20688 cleanup: 20689 if (spm != NULL) { 20690 sal_free(spm); 20691 } 20692 if (scm != NULL) { 20693 sal_free(scm); 20694 } 20695 return rv; 20696 } 20697 20698 /* 20699 * Function: 20700 * bcm_td2_cosq_service_map_get 20701 * Purpose: 20702 * Get the mapping from port, classifier, and multiple internal priorities 20703 * to multiple COS queues in a queue group. 20704 * Parameters: 20705 * unit - (IN) Unit number. 20706 * port - (IN) Local port ID 20707 * classifier_id - (IN) Classifier ID 20708 * queue_group - (OUT) Queue group 20709 * array_max - (IN) Size of priority_array and cosq_array 20710 * priority_array - (IN) Array of internal priorities 20711 * cosq_array - (OUT) Array of COS queues 20712 * array_count - (OUT) Size of cosq_array 20713 * Returns: 20714 * BCM_E_xxx 20715 */ 20716 int 20717 bcm_td2_cosq_service_map_get( 20718 int unit, 20719 bcm_port_t port, 20720 int classifier_id, 20721 bcm_gport_t *queue_group, 20722 int array_max, 20723 bcm_cos_t *priority_array, 20724 bcm_cos_queue_t *cosq_array, 20725 int *array_count) 20726 { 20727 int alloc_size, port_offset, i, vid, qptr; 20728 int spm_index, scm_index, pipe; 20729 int rv = BCM_E_NONE; 20730 void *spm_entries[1]; 20731 void *scm_entries[1]; 20732 service_queue_map_entry_t sqm; 20733 service_port_map_entry_t *spm; 20734 service_cos_map_entry_t *scm; 20735 soc_profile_mem_t *spm_profile_mem, *scm_profile_mem; 20736 20737 if (priority_array == NULL || cosq_array == NULL || 20738 array_count == NULL || queue_group == NULL) { 20739 return BCM_E_PARAM; 20740 } 20741 20742 if (!_BCM_COSQ_CLASSIFIER_IS_SERVICE(classifier_id)) { 20743 return BCM_E_PARAM; 20744 } 20745 20746 /* index above 4K is for VFI */ 20747 vid = _BCM_COSQ_CLASSIFIER_SERVICE_GET(classifier_id); 20748 if (vid < 0 || vid >= SOC_MEM_SIZE(unit, SERVICE_QUEUE_MAPm)) { 20749 return BCM_E_PARAM; 20750 } 20751 20752 scm_profile_mem = _bcm_td2_service_cos_map_profile[unit]; 20753 spm_profile_mem = _bcm_td2_service_port_map_profile[unit]; 20754 20755 SOC_IF_ERROR_RETURN( 20756 soc_mem_read(unit, SERVICE_QUEUE_MAPm, MEM_BLOCK_ANY, (int)vid, &sqm)); 20757 20758 if (!soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, &sqm, VALIDf)) { 20759 return BCM_E_CONFIG; 20760 } 20761 20762 qptr = soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, 20763 &sqm, SERVICE_QUEUE_PTRf); 20764 pipe = _BCM_TD2_PORT_TO_PIPE(unit, port); 20765 qptr = (pipe == _TD2_XPIPE)? qptr: qptr - 2048; 20766 spm_index = _TD2_SPM_ENTRIES_PER_SET * 20767 soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, &sqm, 20768 SERVICE_PORT_PROFILE_INDEXf); 20769 scm_index = _TD2_SCM_ENTRIES_PER_SET * 20770 soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, &sqm, 20771 SERVICE_COS_PROFILE_INDEXf); 20772 20773 alloc_size = sizeof(service_port_map_entry_t) * _TD2_SPM_ENTRIES_PER_SET; 20774 spm = sal_alloc(alloc_size, "SERVICE_PORT_MAP temp Mem"); 20775 if (spm == NULL) { 20776 return BCM_E_MEMORY; 20777 } 20778 sal_memset(spm, 0, alloc_size); 20779 spm_entries[0] = spm; 20780 20781 alloc_size = sizeof(service_cos_map_entry_t) * _TD2_SCM_ENTRIES_PER_SET; 20782 scm = sal_alloc(alloc_size, "SERVICE_COS_MAP temp Mem"); 20783 if (scm == NULL) { 20784 goto cleaup; 20785 } 20786 sal_memset(scm, 0, alloc_size); 20787 scm_entries[0] = scm; 20788 20789 rv = soc_profile_mem_get(unit, spm_profile_mem, 20790 spm_index, _TD2_SPM_ENTRIES_PER_SET, spm_entries); 20791 if (!(rv == SOC_E_NOT_FOUND || rv == SOC_E_NONE)) { 20792 goto cleaup; 20793 } 20794 20795 rv = soc_profile_mem_get(unit, scm_profile_mem, 20796 scm_index, _TD2_SCM_ENTRIES_PER_SET, scm_entries); 20797 if (!(rv == SOC_E_NOT_FOUND || rv == SOC_E_NONE)) { 20798 goto cleaup; 20799 } 20800 20801 port_offset = soc_mem_field32_get(unit, SERVICE_PORT_MAPm, 20802 &spm[port], SERVICE_PORT_OFFSETf); 20803 if (port_offset == 0) { 20804 rv = BCM_E_NOT_FOUND; 20805 goto cleaup; 20806 } 20807 pipe = _BCM_TD2_PORT_TO_PIPE(unit, port); 20808 BCM_GPORT_UCAST_QUEUE_GROUP_SYSQID_SET(*queue_group, port, 20809 ((pipe * _BCM_TD2_NUM_L2_UC_LEAVES_PER_PIPE) + port_offset + qptr)); 20810 20811 *array_count = array_max > _TD2_SCM_ENTRIES_PER_SET ? 20812 _TD2_SCM_ENTRIES_PER_SET : array_max; 20813 for (i = 0; i < *array_count; i++) { 20814 if (priority_array[i] >= _TD2_SCM_ENTRIES_PER_SET) { 20815 rv = BCM_E_PARAM; 20816 goto cleaup; 20817 } 20818 cosq_array[i] = soc_mem_field32_get(unit, SERVICE_COS_MAPm, 20819 &scm[priority_array[i]], 20820 SERVICE_COS_OFFSETf); 20821 } 20822 20823 cleaup: 20824 if (spm != NULL) { 20825 sal_free(spm); 20826 } 20827 if (scm != NULL) { 20828 sal_free(scm); 20829 } 20830 return rv; 20831 } 20832 20833 /* 20834 * Function: 20835 * bcm_td2_cosq_service_map_clear 20836 * Purpose: 20837 * Clear the mapping from port, classifier, and internal priorities 20838 * to COS queues in a queue group. 20839 * Parameters: 20840 * unit - (IN) Unit number. 20841 * port - (IN) Local port ID 20842 * classifier_id - (IN) Classifier ID 20843 * Returns: 20844 * BCM_E_xxx 20845 */ 20846 int 20847 bcm_td2_cosq_service_map_clear( 20848 int unit, 20849 bcm_gport_t port, 20850 int classifier_id) 20851 { 20852 int i, alloc_size, vid, classifier_in_use; 20853 int rv = BCM_E_NONE; 20854 int scm_index; 20855 uint32 spm_index, spm_index_new; 20856 void *spm_entries[1]; 20857 service_port_map_entry_t *spm; 20858 service_queue_map_entry_t sqm; 20859 soc_profile_mem_t *spm_profile_mem, *scm_profile_mem; 20860 20861 if (!_BCM_COSQ_CLASSIFIER_IS_SERVICE(classifier_id)) { 20862 return BCM_E_PARAM; 20863 } 20864 20865 /* index above 4K is for VFI */ 20866 vid = _BCM_COSQ_CLASSIFIER_SERVICE_GET(classifier_id); 20867 if (vid < 0 || vid >= SOC_MEM_SIZE(unit, SERVICE_QUEUE_MAPm)) { 20868 return BCM_E_PARAM; 20869 } 20870 20871 scm_profile_mem = _bcm_td2_service_cos_map_profile[unit]; 20872 spm_profile_mem = _bcm_td2_service_port_map_profile[unit]; 20873 20874 SOC_IF_ERROR_RETURN( 20875 soc_mem_read(unit, SERVICE_QUEUE_MAPm, MEM_BLOCK_ANY, (int)vid, &sqm)); 20876 20877 if (!soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, &sqm, VALIDf)) { 20878 return BCM_E_NONE; 20879 } 20880 20881 /* 1. program the SERVICE_PORT_MAPm. */ 20882 alloc_size = sizeof(service_port_map_entry_t) * _TD2_SPM_ENTRIES_PER_SET; 20883 spm = sal_alloc(alloc_size, "SERVICE_PORT_MAP temp Mem"); 20884 if (spm == NULL) { 20885 return BCM_E_MEMORY; 20886 } 20887 sal_memset(spm, 0, alloc_size); 20888 spm_entries[0] = spm; 20889 20890 spm_index = _TD2_SPM_ENTRIES_PER_SET * 20891 soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, &sqm, 20892 SERVICE_PORT_PROFILE_INDEXf); 20893 rv = soc_profile_mem_get(unit, spm_profile_mem, 20894 spm_index, _TD2_SPM_ENTRIES_PER_SET, spm_entries); 20895 if (!(rv == SOC_E_NOT_FOUND || rv == SOC_E_NONE)) { 20896 goto cleanup; 20897 } 20898 20899 soc_mem_field32_set(unit, SERVICE_PORT_MAPm, 20900 &spm[port], SERVICE_PORT_OFFSETf, 0); 20901 classifier_in_use = 0; 20902 for (i = 0; i < _TD2_SPM_ENTRIES_PER_SET; i++) { 20903 if (soc_mem_field32_get(unit, SERVICE_PORT_MAPm, 20904 &spm[i], SERVICE_PORT_OFFSETf)) { 20905 classifier_in_use = 1; 20906 break; 20907 } 20908 } 20909 20910 rv = soc_profile_mem_delete(unit, spm_profile_mem, spm_index); 20911 if (rv != SOC_E_NONE) { 20912 goto cleanup; 20913 } 20914 20915 if (classifier_in_use) { 20916 rv = soc_profile_mem_add(unit, spm_profile_mem, 20917 spm_entries, _TD2_SPM_ENTRIES_PER_SET, 20918 &spm_index_new); 20919 if (rv != SOC_E_NONE) { 20920 goto cleanup; 20921 } 20922 } 20923 20924 /* 2. program the SERVICE_COS_MAPm. */ 20925 if (!classifier_in_use) { 20926 scm_index = _TD2_SCM_ENTRIES_PER_SET * 20927 soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, &sqm, 20928 SERVICE_COS_PROFILE_INDEXf); 20929 rv = soc_profile_mem_delete(unit, scm_profile_mem, scm_index); 20930 if (rv != SOC_E_NONE) { 20931 goto cleanup; 20932 } 20933 } 20934 20935 /* 3. program the SERVICE_QUEUE_MAPm. */ 20936 if (classifier_in_use) { 20937 soc_mem_field32_set(unit, SERVICE_QUEUE_MAPm, &sqm, 20938 SERVICE_PORT_PROFILE_INDEXf, 20939 spm_index_new / _TD2_SPM_ENTRIES_PER_SET); 20940 } else { 20941 sal_memset(&sqm,0, sizeof(service_queue_map_entry_t)); 20942 } 20943 20944 rv = soc_mem_write(unit, SERVICE_QUEUE_MAPm, MEM_BLOCK_ALL, 20945 (int)vid, &sqm); 20946 20947 cleanup: 20948 if (spm != NULL) { 20949 sal_free(spm); 20950 } 20951 return rv; 20952 } 20953 20954 /* 20955 * Function: 20956 * bcm_td2p_rx_queue_channel_set 20957 * Purpose: 20958 * Validate if the queue id to channel id mapping 20959 * is in accordance with the LLS Hierarchy created 20960 * If queue_id is -1, find the LLS Hierarchy & program 20961 * CMIC accordingly 20962 * JIRA:- SDK-57255 20963 * Parameters: 20964 * unit - (IN) unit number 20965 * queue_id - CPU cos queue index (0 - (max cosq - 1)) 20966 * (Negative for all) 20967 * chan_id - channel index (0 - (BCM_RX_CHANNELS-1)) 20968 * Returns: 20969 * BCM_E_XXX 20970 */ 20971 int 20972 bcm_td2p_rx_queue_channel_set(int unit, bcm_cos_queue_t queue_id, 20973 bcm_rx_chan_t chan_id) 20974 { 20975 #ifdef BCM_CMICM_SUPPORT 20976 uint32 chan_off; 20977 uint32 l0_index; 20978 uint32 l0_hw_index; 20979 bcm_gport_t cpu_gport; 20980 _bcm_td2_cosq_node_t *node; 20981 _bcm_td2_cosq_node_t *l0_node; 20982 _bcm_td2_cosq_node_t *l1_node; 20983 _bcm_td2_cosq_node_t *l2_queue; 20984 bcm_port_t local_port; 20985 int i,id = 0; 20986 int bit = 0; 20987 int pci_cmc = SOC_PCI_CMC(unit); 20988 int queue_in_tree = FALSE; 20989 bcm_cos_queue_t new_queue_id; 20990 bcm_rx_chan_t new_chan_id; 20991 _bcm_td2_mmu_info_t *mmu_info; 20992 20993 mmu_info = _bcm_td2_mmu_info[unit]; 20994 cpu_gport = BCM_GPORT_LOCAL_CPU; 20995 20996 /* Find the cosq node for cpu port */ 20997 BCM_IF_ERROR_RETURN 20998 (_bcm_td2_cosq_localport_resolve(unit, cpu_gport, &local_port)); 20999 21000 /* We are passing a gport to _bcm_td2_cosq_localport_resolve 21001 * So local_port is NOT returning gport but resolving it. 21002 * Ignoring the coverity error 21003 */ 21004 /* coverity[overrun-local] */ 21005 if (!IS_CPU_PORT(unit, local_port)) { 21006 LOG_ERROR(BSL_LS_BCM_COSQ, (BSL_META_U(unit, 21007 "Cannot find CPU port. cpu gport 0x%x local port %d\n"), 21008 cpu_gport, local_port)); 21009 return BCM_E_PARAM; 21010 } 21011 21012 id = local_port; 21013 node = &mmu_info->sched_node[id]; 21014 21015 SHR_BITCLR_RANGE(CPU_ARM_RSVD_QUEUE_BITMAP(unit, pci_cmc),58,6); 21016 21017 if (queue_id == -1) { 21018 /* No verification. Map all queues to corresponding channel */ 21019 /* loop through all l0 nodes */ 21020 /* 21021 * COVERITY 21022 * We passed a gport to _bcm_td2_cosq_localport_resolve 21023 * So local_port is NOT returning gport but resolving it. 21024 * Ignoring the coverity error 21025 */ 21026 /* coverity[overrun-local] */ 21027 l0_node = node->child; 21028 while (l0_node) { 21029 /* loop through all l1 nodes */ 21030 l0_hw_index = l0_node->hw_index; 21031 new_chan_id = -1; 21032 for (i = 0; i< BCM_RX_CHANNELS; i++) { 21033 if (bcm_td2p_cosq_rx_chan_l0_map[i] == l0_hw_index) { 21034 new_chan_id = i; 21035 break; 21036 } 21037 } 21038 if (new_chan_id == -1) { 21039 LOG_ERROR(BSL_LS_BCM_COSQ, (BSL_META_U(unit, 21040 "Cannot find channel id for l0 node %d" 21041 " Check the LLS hierarchy" 21042 " configured on this device\n"),l0_hw_index)); 21043 return BCM_E_PARAM; 21044 } 21045 SHR_BITCLR_RANGE(CPU_ARM_RSVD_QUEUE_BITMAP(unit, pci_cmc),58,6); 21046 bit = bcm_td2p_cmic_to_mmu_cosmask_map[(l0_hw_index % SOC_TD2_COSQ_CPU_RESERVED_L0_BASE(unit))%_TD2PLUS_COSQ_NUM_CPU_L0_NODES]; 21047 LOG_INFO(BSL_LS_BCM_COSQ, (BSL_META_U(unit, 21048 "Setting bit %d & channel id %d" 21049 " configured on l0 index %d\n "), 21050 bit, new_chan_id, l0_hw_index)); 21051 SHR_BITSET(CPU_ARM_RSVD_QUEUE_BITMAP(unit, pci_cmc), bit); 21052 l1_node = l0_node->child; 21053 while (l1_node) { 21054 /* loop through all l2 queues */ 21055 l2_queue = l1_node->child; 21056 while (l2_queue) { 21057 /* CPU queues start from 2000 in HW. Deriving the logical cpu queue number (0 to 48) here */ 21058 new_queue_id = (l2_queue->hw_index-2000)%NUM_CPU_ARM_COSQ(unit, pci_cmc); 21059 BCM_IF_ERROR_RETURN(_bcm_common_rx_queue_channel_set_helper( 21060 unit, 21061 new_queue_id, 21062 new_chan_id, 21063 pci_cmc)); 21064 21065 LOG_INFO(BSL_LS_BCM_COSQ, (BSL_META_U(unit, 21066 "Queue id %d & channel id %d" 21067 " configured on l0 index %d\n "), 21068 new_queue_id, new_chan_id, l0_hw_index)); 21069 l2_queue = l2_queue->sibling; 21070 } 21071 l1_node = l1_node->sibling; 21072 } 21073 l0_node = l0_node->sibling; 21074 } 21075 } else { 21076 chan_off = chan_id % BCM_RX_CHANNELS; 21077 l0_index = bcm_td2p_cosq_rx_chan_l0_map[chan_off]; 21078 l0_node = node->child; 21079 while (l0_node) { 21080 if (l0_node->hw_index == l0_index) { 21081 break; 21082 } 21083 l0_node = l0_node->sibling; 21084 } 21085 21086 if (!l0_node) { 21087 LOG_ERROR(BSL_LS_BCM_COSQ, 21088 (BSL_META_U(unit, "Invalid input, channel_id %d\n"), chan_id)); 21089 return BCM_E_PARAM; 21090 } 21091 21092 if (l0_node->hw_index != l0_index) { 21093 LOG_ERROR(BSL_LS_BCM_COSQ, 21094 (BSL_META_U(unit, "MMU L0 node not found for this channel %d\n"), chan_id)); 21095 return BCM_E_NOT_FOUND; 21096 } 21097 21098 /* Verify if the given queue_id is in correct LLS hierarchy */ 21099 l1_node = l0_node->child; 21100 queue_in_tree = FALSE; 21101 while (l1_node) { 21102 l2_queue = l1_node->child; 21103 while (l2_queue) { 21104 /* CPU queues start from 2000 in HW. Deriving the logical cpu queue number (0 to 48) here */ 21105 if (queue_id == (l2_queue->hw_index-2000)%NUM_CPU_ARM_COSQ(unit, pci_cmc)) { 21106 queue_in_tree = TRUE; 21107 break; 21108 } 21109 l2_queue = l2_queue->sibling; 21110 } 21111 if (queue_in_tree) { 21112 break; 21113 } 21114 l1_node = l1_node->sibling; 21115 } 21116 21117 if (!queue_in_tree) { 21118 /* Verification failed. Throw error */ 21119 LOG_ERROR(BSL_LS_BCM_COSQ, (BSL_META_U(unit, 21120 "Queue id %d & channel id %d" 21121 " params do not match the LLS hierarchy" 21122 " configured on this device\n"), 21123 queue_id, chan_id)); 21124 return BCM_E_PARAM; 21125 } 21126 else { 21127 bit = bcm_td2p_cmic_to_mmu_cosmask_map[(l0_index % SOC_TD2_COSQ_CPU_RESERVED_L0_BASE(unit))%_TD2PLUS_COSQ_NUM_CPU_L0_NODES]; 21128 LOG_INFO(BSL_LS_BCM_COSQ, (BSL_META_U(unit, 21129 "Setting bit %d & channel id %d" 21130 " configured on l0 index %d\n "), 21131 bit, chan_off, l0_index)); 21132 SHR_BITSET(CPU_ARM_RSVD_QUEUE_BITMAP(unit, pci_cmc), bit); 21133 /* Verification suceeded. Program CMIC */ 21134 BCM_IF_ERROR_RETURN(_bcm_common_rx_queue_channel_set_helper( 21135 unit, 21136 queue_id, 21137 chan_off , 21138 pci_cmc)); 21139 21140 LOG_INFO(BSL_LS_BCM_COSQ, (BSL_META_U(unit, 21141 "Queue id %d & channel id %d" 21142 " configured on l0 index %d\n "), 21143 queue_id, chan_off, l0_index)); 21144 } 21145 } 21146 21147 #endif /* CMICM Support */ 21148 return BCM_E_NONE; 21149 } 21150 21151 int 21152 bcm_td2p_cosq_ets_mode(int unit) 21153 { 21154 /* second argument not being used by the function. 21155 * passing 0 as a workaround. 21156 * Should be passing local port for cpu port. 21157 */ 21158 return _bcm_td2_cosq_port_has_ets(unit,0); 21159 } 21160 21161 #endif /* defined(BCM_TRIDENT2_SUPPORT) */