cosq.c (558475B)
1 /* 2 * 3 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 4 * 5 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 6 * 7 * COS Queue Management 8 * Purpose: API to set different cosq, priorities, and scheduler registers. 9 */ 10 11 #include <shared/bsl.h> 12 13 #include <soc/defs.h> 14 #include <sal/core/libc.h> 15 #if defined(BCM_TRIUMPH3_SUPPORT) 16 #include <soc/drv.h> 17 #include <soc/scache.h> 18 #include <soc/profile_mem.h> 19 #include <soc/triumph3.h> 20 #include <soc/phyctrl.h> 21 #include <bcm/error.h> 22 #include <bcm/cosq.h> 23 #include <bcm_int/esw/mbcm.h> 24 #include <bcm_int/esw/stack.h> 25 #include <bcm_int/esw/cosq.h> 26 #include <bcm_int/esw/triumph3.h> 27 28 #include <bcm_int/esw_dispatch.h> 29 30 #include <bcm_int/bst.h> 31 #include <bcm_int/esw/cosq.h> 32 33 #ifdef BCM_WARM_BOOT_SUPPORT 34 #include <bcm_int/esw/switch.h> 35 #endif /* BCM_WARM_BOOT_SUPPORT */ 36 37 #define TR3_CELL_FIELD_MAX 0x7fff 38 39 /* MMU cell size in bytes */ 40 #define _BCM_TR3_PACKET_HEADER_BYTES 64 /* bytes */ 41 #define _BCM_TR3_DEFAULT_MTU_BYTES 1536 /* bytes */ 42 #define _BCM_TR3_TOTAL_CELLS 24576 /* 24k cells */ 43 #define _BCM_TR3_BYTES_PER_CELL 208 /* bytes */ 44 #define _BCM_TR3_BYTES_TO_CELLS(_byte_) \ 45 (((_byte_) + _BCM_TR3_BYTES_PER_CELL - 1) / _BCM_TR3_BYTES_PER_CELL) 46 47 #define _BCM_TR3_NUM_PORT_SCHEDULERS 64 48 #define _BCM_TR3_NUM_L0_SCHEDULER 256 49 #define _BCM_TR3_NUM_L1_SCHEDULER 512 50 #define _BCM_TR3_NUM_L2_UC_LEAVES 1024 51 #define _BCM_TR3_NUM_L2_MC_LEAVES 568 52 #define _BCM_TR3_NUM_TOTAL_SCHEDULERS (_BCM_TR3_NUM_PORT_SCHEDULERS + \ 53 _BCM_TR3_NUM_L0_SCHEDULER + \ 54 _BCM_TR3_NUM_L1_SCHEDULER) 55 56 #define _BCM_TR3_MMU_NUM_PG 8 57 58 #define _BCM_TR3_COSQ_LIST_NODE_INIT(list, node) \ 59 list[node].in_use = FALSE; \ 60 list[node].gport = -1; \ 61 list[node].base_index = -1; \ 62 list[node].numq = 0; \ 63 list[node].base_size = 0; \ 64 list[node].numq_expandable = 0; \ 65 list[node].hw_index = -1; \ 66 list[node].level = -1; \ 67 list[node].attached_to_input = -1; \ 68 list[node].hw_cosq = 0; \ 69 list[node].remote_modid = -1; \ 70 list[node].remote_port = -1; \ 71 BCM_PBMP_CLEAR(list[node].fabric_pbmp); \ 72 list[node].local_port = -1; \ 73 list[node].parent = NULL; \ 74 list[node].sibling = NULL; \ 75 list[node].child = NULL; \ 76 list[node].type = _BCM_TR3_NODE_UNKNOWN; 77 78 #define _BCM_TR3_COSQ_NODE_INIT(node) \ 79 node->in_use = FALSE; \ 80 node->gport = -1; \ 81 node->base_index = -1; \ 82 node->numq = 0; \ 83 node->base_size = 0; \ 84 node->numq_expandable = 0; \ 85 node->hw_index = -1; \ 86 node->level = -1; \ 87 node->attached_to_input = -1; \ 88 node->hw_cosq = 0; \ 89 node->remote_modid = -1; \ 90 node->remote_port = -1; \ 91 BCM_PBMP_CLEAR(node->fabric_pbmp); \ 92 node->local_port = -1; \ 93 node->parent = NULL; \ 94 node->sibling = NULL; \ 95 node->child = NULL; \ 96 node->num_child = 0; \ 97 node->type = _BCM_TR3_NODE_UNKNOWN; 98 99 #define _BCM_TR3_MERGE_COLLATE(val3, val2, val1, val0) \ 100 (val0 | ((val1 & 0xff) << 8) | \ 101 ((val2 & 0xff) << 16) | ((val3 & 0xff) << 24)) 102 103 #define _BCM_TR3_MERGE_RETRIEVE_0(val) (val & 0xff) 104 #define _BCM_TR3_MERGE_RETRIEVE_1(val) ((val >> 8) & 0xff) 105 #define _BCM_TR3_MERGE_RETRIEVE_2(val) ((val >> 16) & 0xff) 106 #define _BCM_TR3_MERGE_RETRIEVE_3(val) ((val >> 24) & 0xff) 107 108 /* TR3 supports eight PFC priority */ 109 #define _BCM_TR3_NUM_PFC_CLASS 8 110 #define _TR3_NUM_INTERNAL_PRI 16 111 112 typedef enum { 113 _BCM_TR3_NODE_UNKNOWN = 0, 114 _BCM_TR3_NODE_UCAST, 115 _BCM_TR3_NODE_MCAST, 116 _BCM_TR3_NODE_DMVOQ, 117 _BCM_TR3_NODE_VLAN, 118 _BCM_TR3_NODE_SCHEDULER 119 } _bcm_tr3_node_type_e; 120 121 typedef struct _bcm_tr3_cosq_node_s { 122 struct _bcm_tr3_cosq_node_s *parent; 123 struct _bcm_tr3_cosq_node_s *sibling; 124 struct _bcm_tr3_cosq_node_s *child; 125 bcm_gport_t gport; 126 int in_use; 127 int base_index; 128 uint16 numq_expandable; 129 uint16 base_size; 130 int numq; 131 int hw_index; 132 soc_tr3_node_lvl_e level; 133 _bcm_tr3_node_type_e type; 134 int attached_to_input; 135 int hw_cosq; 136 137 /* DPVOQ specific information */ 138 bcm_port_t local_port; 139 bcm_module_t remote_modid; 140 bcm_port_t remote_port; 141 int num_child; 142 bcm_pbmp_t fabric_pbmp; 143 }_bcm_tr3_cosq_node_t; 144 145 typedef struct _bcm_tr3_cosq_list_s { 146 int count; 147 SHR_BITDCL *bits; 148 }_bcm_tr3_cosq_list_t; 149 150 typedef struct { 151 int enable; 152 int shared_limit; 153 int min_limit; 154 int q_limit_dynamic; 155 } _bcm_tr3_gport_q_disable_t; 156 157 #define _BCM_TR3_MAX_PORT SOC_MAX_NUM_PORTS 158 159 #define _BCM_TR3_IS_UC_QUEUE(mmu_info,qid) \ 160 (((qid) < mmu_info->num_base_queues) ? 1 : 0) 161 162 #define _BCM_TR3_IS_DESTMOD_QUEUE_GROUP(mmu_info, gport) \ 163 (((BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) && \ 164 ((BCM_GPORT_UCAST_QUEUE_GROUP_QID_GET(gport)) >= \ 165 (mmu_info)->num_base_queues)) || \ 166 (BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport) && \ 167 ((BCM_GPORT_DESTMOD_QUEUE_GROUP_QID_GET(gport)) < \ 168 (mmu_info)->num_dmvoq_queues))) \ 169 ? 1 : 0) 170 171 #define _SOC_TR3_ROOT_SCHEDULER_INDEX(u,p) \ 172 SOC_INFO((u)).max_port_p2m_mapping[SOC_INFO((u)).port_l2p_mapping[(p)]] 173 174 typedef struct _bcm_tr3_cosq_port_info_s { 175 int mc_base; 176 int mc_limit; 177 int uc_base; 178 int uc_limit; 179 int eq_base; 180 int eq_limit; 181 } _bcm_tr3_cosq_port_info_t; 182 183 typedef struct _bcm_tr3_mmu_info_s { 184 int num_base_queues; /* Number of classical queues */ 185 186 _bcm_tr3_cosq_list_t ext_qlist; /* list of extended queues */ 187 _bcm_tr3_cosq_list_t dmvoq_qlist; /* list of extended queues */ 188 _bcm_tr3_cosq_list_t l0_sched_list; /* list of l0 sched nodes */ 189 _bcm_tr3_cosq_list_t l1_sched_list; /* list of l1 sched nodes */ 190 191 _bcm_tr3_cosq_node_t sched_node[_BCM_TR3_NUM_TOTAL_SCHEDULERS]; /* sched nodes */ 192 _bcm_tr3_cosq_node_t queue_node[_BCM_TR3_NUM_L2_UC_LEAVES]; /* queue nodes */ 193 _bcm_tr3_cosq_node_t mc_queue_node[_BCM_TR3_NUM_L2_MC_LEAVES]; /* queue nodes */ 194 _bcm_tr3_cosq_port_info_t port_info[_BCM_TR3_MAX_PORT]; 195 196 bcm_pbmp_t gport_unavail_pbm; 197 198 int ets_mode; 199 int curr_shared_limit; 200 int curr_merger_index[4]; 201 int num_dmvoq_queues; /* Number of dmvoq queues */ 202 int base_dmvoq_queue; /* Base DMVOQ queue */ 203 int axp_ets_mode; /*ETS mode for each AXP ports*/ 204 }_bcm_tr3_mmu_info_t; 205 206 static _bcm_tr3_mmu_info_t *_bcm_tr3_mmu_info[BCM_MAX_NUM_UNITS]; /* MMU info */ 207 208 static soc_profile_mem_t *_bcm_tr3_wred_profile[BCM_MAX_NUM_UNITS]; 209 static soc_profile_mem_t *_bcm_tr3_cos_map_profile[BCM_MAX_NUM_UNITS]; 210 static soc_profile_mem_t *_bcm_tr3_sample_int_profile[BCM_MAX_NUM_UNITS]; 211 static soc_profile_reg_t *_bcm_tr3_feedback_profile[BCM_MAX_NUM_UNITS]; 212 static soc_profile_reg_t *_bcm_tr3_llfc_profile[BCM_MAX_NUM_UNITS]; 213 static soc_profile_mem_t *_bcm_tr3_voq_port_map_profile[BCM_MAX_NUM_UNITS]; 214 static soc_profile_mem_t *_bcm_tr3_service_cos_map_profile[BCM_MAX_NUM_UNITS]; 215 static soc_profile_mem_t *_bcm_tr3_service_port_map_profile[BCM_MAX_NUM_UNITS]; 216 static soc_profile_mem_t *_bcm_tr3_ifp_cos_map_profile[BCM_MAX_NUM_UNITS]; 217 218 typedef enum { 219 _BCM_TR3_COSQ_TYPE_UCAST, 220 _BCM_TR3_COSQ_TYPE_MCAST, 221 _BCM_TR3_COSQ_TYPE_EXT_UCAST 222 } _bcm_tr3_cosq_type_t; 223 224 #define IS_TR3_HSP_PORT(u,p) \ 225 ((IS_CE_PORT((u),(p))) || \ 226 ((IS_HG_PORT((u),(p))) && (SOC_INFO((u)).port_speed_max[(p)] >= 100000))) 227 228 229 /* Number of COSQs configured for this device */ 230 #if 0 231 static int _bcm_tr3_num_cosq[SOC_MAX_NUM_DEVICES]; 232 #define _TR3_NUM_COS(unit) _bcm_tr3_num_cosq[(unit)] 233 #else 234 #define _TR3_NUM_COS NUM_COS 235 #endif 236 237 #define _TR3_NUM_HSP_COSQ 10 238 #define _TR3_NUM_HG_COSQ 10 239 240 STATIC int 241 _bcm_tr3_cosq_node_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cos, 242 bcm_module_t *modid, bcm_port_t *port, 243 int *id, _bcm_tr3_cosq_node_t **node); 244 245 STATIC int 246 _bcm_tr3_cosq_mapping_set(int unit, bcm_port_t ing_port, bcm_cos_t priority, 247 uint32 flags, bcm_gport_t gport, bcm_cos_queue_t cosq); 248 249 STATIC int 250 _bcm_tr3_cosq_sched_set(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 251 int mode, int weight, int adjust_cos); 252 253 STATIC int 254 _bcm_tr3_cosq_egress_sp_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 255 int *p_pool_start, int *p_pool_end); 256 STATIC int 257 _bcm_tr3_cosq_reserve_gport_resources(int unit, bcm_port_t port); 258 259 STATIC int 260 _bcm_tr3_cosq_unreserve_gport_resources(int unit, bcm_port_t port); 261 262 STATIC int 263 _bcm_tr3_node_index_set(_bcm_tr3_cosq_list_t *list, int start, int range); 264 STATIC int 265 _bcm_tr3_cosq_dynamic_thresh_enable_get(int unit, 266 bcm_gport_t gport, bcm_cos_queue_t cosq, 267 bcm_cosq_control_t type, int *arg); 268 STATIC int _bcm_tr3_voq_next_base_node_get(int unit, bcm_port_t port, 269 int modid, 270 _bcm_tr3_cosq_node_t **base_node); 271 272 #ifdef BCM_WARM_BOOT_SUPPORT 273 274 #define BCM_WB_VERSION_1_0 SOC_SCACHE_VERSION(1,0) 275 #define BCM_WB_VERSION_1_1 SOC_SCACHE_VERSION(1,1) 276 #define BCM_WB_VERSION_1_2 SOC_SCACHE_VERSION(1,2) 277 #define BCM_WB_VERSION_1_3 SOC_SCACHE_VERSION(1,3) 278 #define BCM_WB_VERSION_1_4 SOC_SCACHE_VERSION(1,4) 279 #define BCM_WB_VERSION_1_5 SOC_SCACHE_VERSION(1,5) 280 #define BCM_WB_DEFAULT_VERSION BCM_WB_VERSION_1_5 281 282 #define _BCM_TR3_COSQ_WB_NUMCOSQ_MASK 0xf /* [3:0] */ 283 #define _BCM_TR3_COSQ_WB_NUMCOSQ_SHIFT 0 284 285 #define SET_FIELD(_field, _value) \ 286 (((_value) & _BCM_TR3_COSQ_WB_## _field## _MASK) << \ 287 _BCM_TR3_COSQ_WB_## _field## _SHIFT) 288 #define GET_FIELD(_field, _byte) \ 289 (((_byte) >> _BCM_TR3_COSQ_WB_## _field## _SHIFT) & \ 290 _BCM_TR3_COSQ_WB_## _field## _MASK) 291 292 /* 293 * This funtion encodes the 1 byte of the common data to be written in to 294 * scache.Currently only last 4 bits of the byte are used for storing 295 * numcosq value rest can be used if necessary later. 296 */ 297 STATIC void 298 _bcm_tr3_cosq_wb_encode_data(int unit,char *scache_ptr) 299 { 300 char data = 0; 301 int numq = 0; 302 303 bcm_tr3_cosq_config_get(unit,&numq); 304 data = SET_FIELD(NUMCOSQ, numq); 305 *scache_ptr = data; 306 307 } 308 309 STATIC int 310 _bcm_tr3_cosq_wb_alloc(int unit) 311 { 312 _bcm_tr3_mmu_info_t *mmu_info; 313 soc_scache_handle_t scache_handle; 314 uint8 *scache_ptr; 315 int rv, alloc_size, node_list_sizes[3], ii, jj; 316 int qcount=0; 317 318 mmu_info = _bcm_tr3_mmu_info[unit]; 319 320 if (!mmu_info) { 321 return BCM_E_INIT; 322 } 323 324 node_list_sizes[0] = _BCM_TR3_NUM_L2_UC_LEAVES; 325 node_list_sizes[1] = _BCM_TR3_NUM_L2_MC_LEAVES; 326 node_list_sizes[2] = _BCM_TR3_NUM_TOTAL_SCHEDULERS; 327 328 alloc_size = 0; 329 for(ii = 0; ii < 3; ii++) { 330 alloc_size += sizeof(uint32); 331 for(jj = 0; jj < node_list_sizes[ii]; jj++) { 332 alloc_size += 4 * sizeof(uint32); 333 } 334 } 335 /* 336 * Allocating 1 byte of data first 4 bits will be used 337 * for storing numcosq 338 */ 339 alloc_size += sizeof(char); 340 341 /* Adjust the pointer to quad boundary (1byte previously+3by pad */ 342 alloc_size += 3; 343 344 /* BCM_WB_VERSION_1_2: a) Added numq */ 345 /* Each qcount is stored in 11 LSBs of 16bits in scache, 346 * leaving 5 bits free which can be used later. 347 */ 348 for (ii = 0; ii < 3; ii++) { 349 for (jj = 0; jj < node_list_sizes[ii]; jj++) { 350 qcount++; 351 } 352 } 353 354 /* Align the mem requiremet to quad boundary. */ 355 if (qcount & 0x1) { 356 qcount++; 357 } 358 alloc_size += qcount * 2; 359 360 /* BCM_WB_VERSION_1_2: b) Added ets_mode. */ 361 alloc_size += 1 * sizeof(int); 362 363 for (ii = 0; ii < 3; ii++) { 364 for (jj = 0; jj < node_list_sizes[ii]; jj++) { 365 alloc_size += sizeof(bcm_pbmp_t); 366 } 367 } 368 alloc_size += sizeof(int); 369 alloc_size += sizeof(int); 370 371 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_COSQ, 0); 372 373 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, TRUE, alloc_size, 374 &scache_ptr, BCM_WB_DEFAULT_VERSION, NULL); 375 if (rv == BCM_E_NOT_FOUND) { 376 rv = BCM_E_NONE; 377 } 378 379 return rv; 380 } 381 382 #define _BCM_TR3_WB_SET_NODE_W1(ntype,nid,sz,parentid,cosqatt,lvl) \ 383 (((ntype & 3)) | \ 384 (((sz) & 7) << 2) | \ 385 (((nid) & 0x3ff) << 5) | \ 386 (((parentid) & 0x3ff) << 15) | \ 387 (((cosqatt) & 0xf) << 25) | \ 388 (((lvl) & 0x7) << 29)) 389 390 #define _BCM_TR3_WB_GET_NODE_ID_W1(w1) (((w1) >> 5) & 0x3ff) 391 392 #define _BCM_TR3_WB_GET_NODE_TYPE_W1(w1) ((w1) & 3) 393 394 #define _BCM_TR3_WB_GET_NODE_SIZE_W1(w1) (((w1) >> 2) & 7) 395 396 #define _BCM_TR3_WB_GET_NODE_PARENT_W1(w1) (((w1) >> 15) & 0x3ff) 397 398 #define _BCM_TR3_WB_GET_NODE_COSQATTT_W1(w1) (((w1) >> 25) & 0xf) 399 400 #define _BCM_TR3_WB_GET_NODE_LEVEL_W1(w1) (((w1) >> 29) & 0x7) 401 402 403 /* 11 bit hw index, 3 bit hw cosq, 1 bit parent high */ 404 /* Parent index requires 11 bits (10 bits + 1 for invalid bit). Since 10 bits 405 are already stored above, the higher 1 bit is stored here */ 406 407 #define _BCM_TR3_WB_SET_NODE_W2(hwindex,hwcosq,parent_hi) \ 408 ((((hwindex) & 0x7ff)) | (((hwcosq) & 0xf) << 11) | (((parent_hi) & 0x1) << 15)) 409 410 #define _BCM_TR3_WB_GET_NODE_HW_INDEX_W2(w1) ((w1) & 0x7ff) 411 412 #define _BCM_TR3_WB_GET_NODE_HW_COSQ_W2(w1) (((w1) >> 11) & 0xf) 413 414 #define _BCM_TR3_WB_GET_NODE_PARENT_HI_W2(w1) (((w1) >> 15) & 0x1) 415 416 #define _BCM_TR3_WB_SET_NODE_W3(gport) (gport) 417 418 #define _BCM_TR3_WB_SET_NODE_W4(remote_modid,remote_port,voq_cosq) \ 419 ((((remote_modid) & 0x1ff)) | \ 420 (((remote_port) & 0x1ff) << 9) | \ 421 (((voq_cosq) & 0xf) << 18)) 422 423 #define _BCM_TR3_WB_GET_NODE_DEST_MODID_W4(w1) ((w1) & 0x1ff) 424 425 #define _BCM_TR3_WB_GET_NODE_DEST_PORT_W4(w1) (((w1) >> 9) & 0x1ff) 426 427 #define _BCM_TR3_WB_GET_NODE_VOQ_COSQ_W4(w1) (((w1) >> 18) & 0xf) 428 429 #define _BCM_TR3_NODE_ID(np,np0) (np - np0) 430 431 int 432 bcm_tr3_cosq_sync(int unit) 433 { 434 soc_scache_handle_t scache_handle; 435 uint8 *scache_ptr,*u8_scache_ptr; 436 uint32 *u32_scache_ptr; 437 uint16 *u16_scache_ptr; 438 _bcm_tr3_cosq_node_t *node; 439 int node_list_sizes[3], ii, jj; 440 _bcm_tr3_cosq_node_t *nodes[3]; 441 int xnode_id, xnode_id_hi, node_size, count; 442 uint32 *psize; 443 _bcm_tr3_mmu_info_t *mmu_info; 444 int scache_hw_index = 0; 445 int qcount = 0; 446 447 mmu_info = _bcm_tr3_mmu_info[unit]; 448 449 if (!mmu_info) { 450 return BCM_E_INIT; 451 } 452 453 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_COSQ, 0); 454 BCM_IF_ERROR_RETURN 455 (_bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 0, 456 &scache_ptr, BCM_WB_DEFAULT_VERSION, NULL)); 457 458 u32_scache_ptr = (uint32*) scache_ptr; 459 460 nodes[0] = &mmu_info->queue_node[0]; 461 node_list_sizes[0] = _BCM_TR3_NUM_L2_UC_LEAVES; 462 nodes[1] = &mmu_info->mc_queue_node[0]; 463 node_list_sizes[1] = _BCM_TR3_NUM_L2_MC_LEAVES; 464 nodes[2] = &mmu_info->sched_node[0]; 465 node_list_sizes[2] = _BCM_TR3_NUM_TOTAL_SCHEDULERS; 466 467 for(ii = 0; ii < 3; ii++) { 468 psize = u32_scache_ptr++; 469 for(count = 0, jj = 0; jj < node_list_sizes[ii]; jj++) { 470 node = nodes[ii] + jj; 471 if (node->in_use == FALSE) { 472 continue; 473 } 474 count += 1; 475 node_size = 3; 476 if ((node->remote_modid != -1) || (node->remote_port != -1) || 477 (node->hw_cosq != -1)) { 478 node_size += 1; 479 } 480 481 xnode_id = _BCM_TR3_NODE_ID(node->parent, mmu_info->sched_node); 482 if (node->parent == NULL) { 483 xnode_id_hi = 0x1; 484 } else { 485 xnode_id_hi = 0; 486 } 487 488 *u32_scache_ptr++ = _BCM_TR3_WB_SET_NODE_W1(ii, jj, node_size, 489 xnode_id, 490 ((node->attached_to_input == -1) ? 0x8 : node->attached_to_input), 491 node->level); 492 493 494 /* Multicast queues use indexes above 1024 */ 495 if (ii == 1) { 496 scache_hw_index = (node->hw_index == -1) ? 0x400 : (node->hw_index - 1024); 497 } else { 498 scache_hw_index = (node->hw_index == -1) ? 0x400 : (node->hw_index); 499 } 500 501 *u32_scache_ptr++ = _BCM_TR3_WB_SET_NODE_W2(scache_hw_index, 502 ((node->hw_cosq == -1) ? 8 : node->hw_cosq), xnode_id_hi); 503 504 *u32_scache_ptr++ = _BCM_TR3_WB_SET_NODE_W3(node->gport); 505 506 if ((node->remote_modid != -1) || (node->remote_port != -1) || 507 (node->hw_cosq != -1)) { 508 node_size += 1; 509 *u32_scache_ptr++ = _BCM_TR3_WB_SET_NODE_W4( 510 (node->remote_modid == -1) ? 0x100 : node->remote_modid, 511 (node->remote_port == -1) ? 0x100 : node->remote_port, 512 (node->hw_cosq == -1) ? 0x8 : node->hw_cosq); 513 } 514 } 515 *psize = count; 516 } 517 /* add numcosq info to the scache */ 518 _bcm_tr3_cosq_wb_encode_data( unit,(char *)u32_scache_ptr); 519 520 /* Advance ptr by 4bytes, 1 for above encoding + 3 bytes for padding */ 521 u32_scache_ptr++; 522 u16_scache_ptr = (uint16 *)u32_scache_ptr; 523 524 /* BCM_WB_VERSION_1_2: Sync numq (11bits) parameter.5 MSBits free */ 525 for (ii = 0; ii < 3; ii++) { 526 for (count = 0, jj = 0; jj < node_list_sizes[ii]; jj++) { 527 node = nodes[ii] + jj; 528 if (node->in_use == FALSE) { 529 continue; 530 } 531 *u16_scache_ptr++ = node->numq & 0x7ff; 532 qcount++; 533 } 534 } 535 /* Move the pointer to quad boundary */ 536 if (qcount & 0x1) { 537 u16_scache_ptr++; 538 } 539 540 u32_scache_ptr = (uint32 *)u16_scache_ptr; 541 542 /* BCM_WB_VERSION_1_2: Sync ets_mode. */ 543 *u32_scache_ptr++ = mmu_info->ets_mode; 544 545 u8_scache_ptr =(uint8 *) u32_scache_ptr; 546 /* BCM_WB_VERSION_1_4: Sync fabric parameter. */ 547 for (ii = 0; ii < 3; ii++) { 548 for (count = 0, jj = 0; jj < node_list_sizes[ii]; jj++) { 549 node = nodes[ii] + jj; 550 if (node->in_use == FALSE) { 551 continue; 552 } 553 sal_memcpy(u8_scache_ptr, &node->fabric_pbmp, sizeof(bcm_pbmp_t)); 554 u8_scache_ptr += sizeof(bcm_pbmp_t); 555 } 556 } 557 558 u32_scache_ptr = (uint32 *)u8_scache_ptr; 559 560 *u32_scache_ptr++ = _BCM_TR3_MERGE_COLLATE ( 561 mmu_info->curr_merger_index[3], 562 mmu_info->curr_merger_index[2], 563 mmu_info->curr_merger_index[1], 564 mmu_info->curr_merger_index[0]); 565 /* BCM_WB_VERSION_1_5: Sync axp_ets_mode parameter. */ 566 *u32_scache_ptr++ = mmu_info->axp_ets_mode; 567 568 return BCM_E_NONE; 569 } 570 571 int 572 bcm_tr3_cosq_reinit(int unit) 573 { 574 soc_scache_handle_t scache_handle; 575 uint8 *scache_ptr, *u8_scache_ptr; 576 uint32 *u32_scache_ptr, *u32_base_ptr, *u32_base_ptr1, wval, fval; 577 uint16 *u16_scache_ptr; 578 _bcm_tr3_cosq_node_t *node; 579 bcm_port_t port; 580 int rv, ii, jj, set_index; 581 _bcm_tr3_cosq_node_t *nodes[3]; 582 int xnode_id, stable_size, node_size, count; 583 _bcm_tr3_mmu_info_t *mmu_info; 584 uint32 entry[SOC_MAX_MEM_WORDS], tmp32; 585 soc_profile_mem_t *profile_mem; 586 soc_info_t *si; 587 int phy_port, mmu_port, profile_index; 588 uint64 rval64, index_map; 589 soc_reg_t reg; 590 mmu_wred_config_entry_t qentry; 591 int numq = 0; 592 uint16 recovered_ver = 0; 593 char data; 594 int additional_scache_size = 0; 595 int qcount=0; 596 int parent_id = 0; 597 int node_list_sizes[3]; 598 static const soc_reg_t llfc_cfgr[] = { 599 PORT_PFC_CFG0r, PORT_PFC_CFG1r 600 }; 601 602 SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size)); 603 if ((stable_size == 0) || (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit))) { 604 /* COSQ warmboot requires extended scache support i.e. level2 warmboot*/ 605 return BCM_E_NONE; 606 } 607 608 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_COSQ, 0); 609 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 0, &scache_ptr, 610 BCM_WB_DEFAULT_VERSION, &recovered_ver); 611 if (BCM_FAILURE(rv)) { 612 return rv; 613 } 614 615 mmu_info = _bcm_tr3_mmu_info[unit]; 616 617 if (!mmu_info) { 618 return BCM_E_INIT; 619 } 620 621 si = &SOC_INFO(unit); 622 u32_scache_ptr = (uint32*) scache_ptr; 623 624 nodes[0] = &mmu_info->queue_node[0]; 625 nodes[1] = &mmu_info->mc_queue_node[0]; 626 nodes[2] = &mmu_info->sched_node[0]; 627 628 u32_base_ptr = u32_scache_ptr; 629 u32_base_ptr1 = u32_scache_ptr; 630 for(ii = 0; ii < 3; ii++) { 631 count = *u32_scache_ptr; 632 u32_scache_ptr++; 633 for(jj = 0; jj < count; jj++) { 634 wval = *u32_scache_ptr; 635 u32_scache_ptr++; 636 xnode_id = _BCM_TR3_WB_GET_NODE_ID_W1(wval); 637 node = nodes[ii] + xnode_id; 638 node->in_use = TRUE; 639 node->numq = 1; 640 node_size = _BCM_TR3_WB_GET_NODE_SIZE_W1(wval); 641 fval = _BCM_TR3_WB_GET_NODE_PARENT_W1(wval); 642 if (recovered_ver >= BCM_WB_VERSION_1_3) { 643 parent_id = fval; 644 } else { 645 if (fval & 0x200) { 646 } else { 647 node->parent = &mmu_info->sched_node[fval]; 648 if (node->parent->child) { 649 node->sibling = node->parent->child; 650 } 651 node->parent->child = node; 652 } 653 } 654 655 fval = _BCM_TR3_WB_GET_NODE_COSQATTT_W1(wval); 656 if (fval & 8) { 657 node->attached_to_input = -1; 658 } else { 659 node->attached_to_input = fval; 660 } 661 662 node->level = _BCM_TR3_WB_GET_NODE_LEVEL_W1(wval); 663 664 wval = *u32_scache_ptr; 665 u32_scache_ptr++; 666 667 fval = _BCM_TR3_WB_GET_NODE_HW_INDEX_W2(wval); 668 if (fval & 0x400) { 669 node->hw_index = -1; 670 } else { 671 node->hw_index = fval; 672 if (recovered_ver >= BCM_WB_VERSION_1_3) { 673 /* Multicast queues use indexes above 1024 */ 674 if(ii == 1) { 675 node->hw_index = fval + 1024; 676 } 677 } 678 } 679 680 fval = _BCM_TR3_WB_GET_NODE_HW_COSQ_W2(wval); 681 if (fval & 8) { 682 node->hw_cosq = -1; 683 } else { 684 node->hw_cosq = fval; 685 } 686 687 if (recovered_ver >= BCM_WB_VERSION_1_3) { 688 /* The parent is now 11 bit and the 11th bit is 689 * stored separately for backward compatibility (upgrade / 690 * downgrade). The invalid parent id is checked for 691 * with 0x400. 692 */ 693 fval = _BCM_TR3_WB_GET_NODE_PARENT_HI_W2(wval); 694 parent_id |= (fval << 10); 695 if (parent_id & 0x400) { 696 } else { 697 node->parent = &mmu_info->sched_node[parent_id]; 698 if (node->parent->child) { 699 node->sibling = node->parent->child; 700 } 701 node->parent->child = node; 702 } 703 } 704 705 wval = *u32_scache_ptr; 706 u32_scache_ptr++; 707 node->gport = wval; 708 709 /* 710 * The function is used for getting local_port. 711 * Return value is intentionally not checked. 712 */ 713 (void)_bcm_tr3_cosq_node_get(unit, node->gport, 0, NULL, 714 &node->local_port, NULL, NULL); 715 716 if (node->hw_index != -1) { 717 if (node->level == SOC_TR3_NODE_LVL_L0) { 718 _bcm_tr3_node_index_set(&mmu_info->l0_sched_list, 719 node->hw_index, 1); 720 } else if (node->level == SOC_TR3_NODE_LVL_L1) { 721 _bcm_tr3_node_index_set(&mmu_info->l1_sched_list, 722 node->hw_index, 1); 723 } else if (node->level == SOC_TR3_NODE_LVL_L2) { 724 if (_BCM_TR3_IS_DESTMOD_QUEUE_GROUP(mmu_info, node->gport)) { 725 if (mmu_info->num_dmvoq_queues > 0) { 726 _bcm_tr3_node_index_set(&mmu_info->dmvoq_qlist, 727 node->hw_index, 1); 728 } else { 729 _bcm_tr3_node_index_set(&mmu_info->ext_qlist, 730 node->hw_index, 1); 731 } 732 } 733 } 734 } 735 736 if (node_size > 3) { 737 wval = *u32_scache_ptr; 738 u32_scache_ptr++; 739 740 fval = _BCM_TR3_WB_GET_NODE_DEST_MODID_W4(wval); 741 if (fval & 0x100) { 742 node->remote_modid = -1; 743 } else { 744 node->remote_modid = fval; 745 } 746 747 fval = _BCM_TR3_WB_GET_NODE_DEST_PORT_W4(wval); 748 if (fval & 0x100) { 749 node->remote_port = -1; 750 } else { 751 node->remote_port = fval; 752 } 753 754 fval = _BCM_TR3_WB_GET_NODE_VOQ_COSQ_W4(wval); 755 if (fval & 0x8) { 756 node->hw_cosq = -1; 757 } else { 758 node->hw_cosq = fval; 759 } 760 } 761 } 762 } 763 if(recovered_ver >= BCM_WB_VERSION_1_1) { 764 data=*((char *)u32_scache_ptr); 765 numq = GET_FIELD(NUMCOSQ,data); 766 bcm_tr3_cosq_config_set(unit,numq); 767 } 768 else { 769 additional_scache_size = sizeof(char); 770 } 771 772 /* Advance ptr by 4bytes=1byte for previous encoding+3bytes of padding */ 773 u32_scache_ptr++; 774 u16_scache_ptr = (uint16 *)u32_scache_ptr; 775 776 /* BCM_WB_VERSION_1_2: Recover numq parameter. */ 777 if (recovered_ver >= BCM_WB_VERSION_1_2) { 778 for (ii = 0; ii < 3; ii++) { 779 count = *u32_base_ptr++; 780 for (jj = 0; jj < count; jj++) { 781 wval = *u32_base_ptr++; 782 xnode_id = _BCM_TR3_WB_GET_NODE_ID_W1(wval); 783 node = nodes[ii] + xnode_id; 784 node_size = _BCM_TR3_WB_GET_NODE_SIZE_W1(wval); 785 786 node->numq = *u16_scache_ptr++ & 0x7ff; 787 qcount++; 788 789 u32_base_ptr += 2; 790 if (node_size > 3) { 791 u32_base_ptr++; 792 } 793 } 794 } 795 /* Adjust ptr to quad boundary */ 796 if (qcount & 0x1) { 797 u16_scache_ptr++; 798 } 799 800 u32_scache_ptr = (uint32 *)u16_scache_ptr; 801 /* BCM_WB_VERSION_1_2: Recover ets_mode. */ 802 mmu_info->ets_mode = *u32_scache_ptr++; 803 } else { 804 node_list_sizes[0] = _BCM_TR3_NUM_L2_UC_LEAVES; 805 node_list_sizes[1] = _BCM_TR3_NUM_L2_MC_LEAVES; 806 node_list_sizes[2] = _BCM_TR3_NUM_TOTAL_SCHEDULERS; 807 808 /* BCM_WB_VERSION_1_2: a) Added numq */ 809 /* Each qcount is stored in 11 LSBs of 16bits in scache, 810 * leaving 5 bits free which can be used later. 811 */ 812 for (ii = 0; ii < 3; ii++) { 813 for (jj = 0; jj < node_list_sizes[ii]; jj++) { 814 qcount++; 815 } 816 } 817 818 /* Align the mem requiremet to quad boundary. */ 819 if (qcount & 0x1) { 820 qcount++; 821 } 822 additional_scache_size += qcount * 2; 823 824 /* BCM_WB_VERSION_1_2: Added ets_mode. */ 825 additional_scache_size += 1 * sizeof(int); 826 } 827 828 /* BCM_WB_VERSION_1_4: Recover fabric parameter. */ 829 if (recovered_ver >= BCM_WB_VERSION_1_4) { 830 u8_scache_ptr = (uint8 *)u32_scache_ptr; 831 for (ii = 0; ii < 3; ii++) { 832 count = *u32_base_ptr1++; 833 for (jj = 0; jj < count; jj++) { 834 wval = *u32_base_ptr1++; 835 xnode_id = _BCM_TR3_WB_GET_NODE_ID_W1(wval); 836 node = nodes[ii] + xnode_id; 837 node_size = _BCM_TR3_WB_GET_NODE_SIZE_W1(wval); 838 839 sal_memcpy(&node->fabric_pbmp, u8_scache_ptr, 840 sizeof(bcm_pbmp_t)); 841 u8_scache_ptr += sizeof(bcm_pbmp_t); 842 u32_base_ptr1 += 2; 843 if (node_size > 3) { 844 u32_base_ptr1++; 845 } 846 } 847 } 848 u32_scache_ptr = (uint32 *)u8_scache_ptr; 849 mmu_info->curr_merger_index[0] = _BCM_TR3_MERGE_RETRIEVE_0(*u32_scache_ptr); 850 mmu_info->curr_merger_index[1] = _BCM_TR3_MERGE_RETRIEVE_1(*u32_scache_ptr); 851 mmu_info->curr_merger_index[2] = _BCM_TR3_MERGE_RETRIEVE_2(*u32_scache_ptr); 852 mmu_info->curr_merger_index[3] = _BCM_TR3_MERGE_RETRIEVE_3(*u32_scache_ptr); 853 u32_scache_ptr++; 854 } else { 855 for (ii = 0; ii < 3; ii++) { 856 for (jj = 0; jj < node_list_sizes[ii]; jj++) { 857 additional_scache_size += sizeof(bcm_pbmp_t); 858 } 859 } 860 additional_scache_size++; 861 } 862 863 if (recovered_ver >= BCM_WB_VERSION_1_5) { 864 mmu_info->axp_ets_mode = *u32_scache_ptr++; 865 } else { 866 additional_scache_size++; 867 } 868 869 /* Update PORT_COS_MAP memory profile reference counter */ 870 profile_mem = _bcm_tr3_cos_map_profile[unit]; 871 PBMP_ALL_ITER(unit, port) { 872 SOC_IF_ERROR_RETURN 873 (soc_mem_read(unit, COS_MAP_SELm, MEM_BLOCK_ALL, port, &entry)); 874 set_index = soc_mem_field32_get(unit, COS_MAP_SELm, &entry, SELECTf); 875 SOC_IF_ERROR_RETURN 876 (soc_profile_mem_reference(unit, profile_mem, set_index * 16, 16)); 877 } 878 if (SOC_INFO(unit).cpu_hg_index != -1) { 879 SOC_IF_ERROR_RETURN(soc_mem_read(unit, COS_MAP_SELm, MEM_BLOCK_ALL, 880 SOC_INFO(unit).cpu_hg_index, &entry)); 881 set_index = soc_mem_field32_get(unit, COS_MAP_SELm, &entry, SELECTf); 882 SOC_IF_ERROR_RETURN 883 (soc_profile_mem_reference(unit, profile_mem, set_index, 1)); 884 } 885 886 PBMP_ALL_ITER(unit, port) { 887 if (IS_CPU_PORT(unit, port)) { 888 continue; 889 } 890 891 phy_port = si->port_l2p_mapping[port]; 892 mmu_port = si->port_p2m_mapping[phy_port]; 893 894 reg = llfc_cfgr[mmu_port/32]; 895 896 BCM_IF_ERROR_RETURN(soc_reg64_get(unit, reg, 0, 0, &rval64)); 897 898 index_map = soc_reg64_field_get(unit, reg, rval64, PROFILE_INDEXf); 899 COMPILER_64_SHR(index_map, ((mmu_port % 32) * 2)); 900 COMPILER_64_TO_32_LO(tmp32, index_map); 901 set_index = (tmp32 & 3)*16; 902 903 SOC_IF_ERROR_RETURN 904 (soc_profile_reg_reference(unit, _bcm_tr3_llfc_profile[unit], 905 set_index * 16, 16)); 906 } 907 908 for (ii = soc_mem_index_min(unit, MMU_WRED_CONFIGm); 909 ii <= soc_mem_index_max(unit, MMU_WRED_CONFIGm); ii++) { 910 BCM_IF_ERROR_RETURN( 911 soc_mem_read(unit, MMU_WRED_CONFIGm, MEM_BLOCK_ALL, ii, &qentry)); 912 913 profile_index = soc_mem_field32_get(unit, MMU_WRED_CONFIGm, 914 &qentry, PROFILE_INDEXf); 915 916 BCM_IF_ERROR_RETURN 917 (soc_profile_mem_reference(unit, _bcm_tr3_wred_profile[unit], 918 profile_index, 1)); 919 } 920 921 /* addtional space is required for scache */ 922 if(additional_scache_size) { 923 rv = soc_scache_realloc(unit,scache_handle,additional_scache_size); 924 if(BCM_FAILURE(rv)) { 925 return rv; 926 } 927 } 928 return BCM_E_NONE; 929 } 930 #endif /* BCM_WARM_BOOT_SUPPORT */ 931 932 #ifndef BCM_SW_STATE_DUMP_DISABLE 933 STATIC char* 934 _bcm_tr3_cosq_node_lvl_str(soc_tr3_node_lvl_e lvl) 935 { 936 switch(lvl) { 937 case SOC_TR3_NODE_LVL_ROOT: 938 return "Root"; 939 break; 940 case SOC_TR3_NODE_LVL_L0: 941 return " L0"; 942 break; 943 case SOC_TR3_NODE_LVL_L1: 944 return " L1"; 945 break; 946 case SOC_TR3_NODE_LVL_L2: 947 return " Q"; 948 break; 949 case SOC_TR3_NODE_LVL_MAX: 950 break; 951 } 952 return ""; 953 } 954 955 STATIC void 956 _bcm_tr3_cosq_dump_node(_bcm_tr3_cosq_node_t *node, int loff) 957 { 958 LOG_CLI((BSL_META("%s.%d index=%d cosq=%d gport=0x%08x numq=%d\n"), 959 _bcm_tr3_cosq_node_lvl_str(node->level), 960 loff, node->hw_index, node->attached_to_input, 961 node->gport, node->numq)); 962 963 if (node->child) { 964 _bcm_tr3_cosq_dump_node(node->child, 0); 965 } 966 967 if (node->sibling) { 968 _bcm_tr3_cosq_dump_node(node->sibling, loff+1); 969 } 970 } 971 972 STATIC void 973 _bcm_tr3_cosq_port_sw_dump(int unit, bcm_port_t port) 974 { 975 _bcm_tr3_mmu_info_t *mmu_info; 976 int phy_port, mmu_port, ii; 977 _bcm_tr3_cosq_node_t *node = NULL, *tnode; 978 soc_info_t *si; 979 980 si = &SOC_INFO(unit); 981 mmu_info = _bcm_tr3_mmu_info[unit]; 982 983 phy_port = si->port_l2p_mapping[port]; 984 mmu_port = si->port_p2m_mapping[phy_port]; 985 986 for (ii = 0; ii < _BCM_TR3_NUM_PORT_SCHEDULERS; ii++) { 987 tnode = &mmu_info->sched_node[ii]; 988 if (tnode->in_use == FALSE) { 989 continue; 990 } 991 if ((tnode->level == SOC_TR3_NODE_LVL_ROOT) && 992 (tnode->hw_index == mmu_port)) { 993 node = tnode; 994 break; 995 } 996 } 997 if (node == NULL) { 998 return; 999 } 1000 1001 _bcm_tr3_cosq_dump_node(node, 0); 1002 } 1003 1004 /* 1005 * Function: 1006 * bcm_tr3_cosq_sw_dump 1007 * Purpose: 1008 * Displays COS Queue information maintained by software. 1009 * Parameters: 1010 * unit - Device unit number 1011 * Returns: 1012 * None 1013 */ 1014 void 1015 bcm_tr3_cosq_sw_dump(int unit) 1016 { 1017 bcm_port_t port; 1018 1019 PBMP_ALL_ITER(unit, port) { 1020 _bcm_tr3_cosq_port_sw_dump(unit, port); 1021 } 1022 1023 return; 1024 } 1025 #endif /* BCM_SW_STATE_DUMP_DISABLE */ 1026 1027 /* 1028 * Function: 1029 * _bcm_tr3_cosq_localport_resolve 1030 * Purpose: 1031 * Resolve GRPOT if it is a local port 1032 * Parameters: 1033 * unit - (IN) unit number 1034 * gport - (IN) GPORT identifier 1035 * local_port - (OUT) local port number 1036 * Returns: 1037 * BCM_E_XXX 1038 */ 1039 int 1040 _bcm_tr3_cosq_localport_resolve(int unit, bcm_gport_t gport, 1041 bcm_port_t *local_port) 1042 { 1043 bcm_module_t module; 1044 bcm_port_t port; 1045 bcm_trunk_t trunk; 1046 int id, result; 1047 1048 if (!BCM_GPORT_IS_SET(gport)) { 1049 if (!SOC_PORT_VALID(unit, gport)) { 1050 return BCM_E_PORT; 1051 } 1052 *local_port = gport; 1053 return BCM_E_NONE; 1054 } 1055 1056 BCM_IF_ERROR_RETURN 1057 (_bcm_esw_gport_resolve(unit, gport, &module, &port, &trunk, &id)); 1058 1059 BCM_IF_ERROR_RETURN(_bcm_esw_modid_is_local(unit, module, &result)); 1060 if (result == FALSE) { 1061 return BCM_E_PARAM; 1062 } 1063 1064 *local_port = port; 1065 1066 return BCM_E_NONE; 1067 } 1068 1069 STATIC int 1070 _bcm_tr3_cosq_port_has_ets(int unit, bcm_port_t port) 1071 { 1072 _bcm_tr3_mmu_info_t *mmu_info = _bcm_tr3_mmu_info[unit]; 1073 1074 /* For HSP port we create Hierarchy internally. So return TRUE for HSP port */ 1075 if (IS_TR3_HSP_PORT(unit, port)) { 1076 return 1; 1077 } 1078 return mmu_info->ets_mode; 1079 } 1080 1081 /* 1082 * Function: 1083 * _bcm_tr3_node_index_get 1084 * Purpose: 1085 * Allocate free index from the given list 1086 * Parameters: 1087 * list - (IN) bit list 1088 * start - (IN) start index 1089 * end - (IN) end index 1090 * qset - (IN) size of queue set 1091 * range - (IN) range bits 1092 * id - (OUT) start index 1093 * Returns: 1094 * BCM_E_XXX 1095 */ 1096 STATIC int 1097 _bcm_tr3_node_index_get(SHR_BITDCL *list, int start, int end, 1098 int count, int align, int *id) 1099 { 1100 int i, j, range_empty; 1101 1102 *id = -1; 1103 1104 if ((align <= 0) || (count == 0)) { 1105 return BCM_E_PARAM; 1106 } 1107 1108 if (start & (align - 1)) { 1109 start = (start + align - 1) & ~(align - 1); 1110 } 1111 1112 end = end - align + 1; 1113 1114 for (i = start; i < end; i += align) { 1115 range_empty = 1; 1116 for (j = i; j < (i + count); j++) { 1117 if (SHR_BITGET(list, j) != 0) { 1118 range_empty = 0; 1119 break; 1120 } 1121 } 1122 1123 if (range_empty) { 1124 *id = i; 1125 return BCM_E_NONE; 1126 } 1127 } 1128 return BCM_E_RESOURCE; 1129 } 1130 1131 /* 1132 * Function: 1133 * _bcm_tr3_node_index_set 1134 * Purpose: 1135 * Mark indices as allocated 1136 * Parameters: 1137 * list - (IN) bit list 1138 * start - (IN) start index 1139 * range - (IN) range bits 1140 * Returns: 1141 * BCM_E_XXX 1142 */ 1143 STATIC int 1144 _bcm_tr3_node_index_set(_bcm_tr3_cosq_list_t *list, int start, int range) 1145 { 1146 list->count += range; 1147 SHR_BITSET_RANGE(list->bits, start, range); 1148 1149 return BCM_E_NONE; 1150 } 1151 1152 /* 1153 * Function: 1154 * _bcm_tr3_node_index_clear 1155 * Purpose: 1156 * Mark indices as free 1157 * Parameters: 1158 * list - (IN) bit list 1159 * start - (IN) start index 1160 * range - (IN) range bits 1161 * Returns: 1162 * BCM_E_XXX 1163 */ 1164 STATIC int 1165 _bcm_tr3_node_index_clear(_bcm_tr3_cosq_list_t *list, int start, int range) 1166 { 1167 list->count -= range; 1168 SHR_BITCLR_RANGE(list->bits, start, range); 1169 1170 return BCM_E_NONE; 1171 } 1172 1173 /* 1174 * Function: 1175 * _bcm_tr3_cosq_alloc_clear 1176 * Purpose: 1177 * Allocate cosq memory and clear 1178 * Parameters: 1179 * size - (IN) size of memory required 1180 * description- (IN) description about the structure 1181 * Returns: 1182 * BCM_E_XXX 1183 */ 1184 STATIC void * 1185 _bcm_tr3_cosq_alloc_clear(void *cp, unsigned int size, char *description) 1186 { 1187 void *block_p; 1188 1189 block_p = (cp) ? cp : sal_alloc(size, description); 1190 1191 if (block_p != NULL) { 1192 sal_memset(block_p, 0, size); 1193 } 1194 1195 return block_p; 1196 } 1197 1198 /* 1199 * Function: 1200 * _bcm_tr3_cosq_free_memory 1201 * Purpose: 1202 * Free memory allocated for mmu info members 1203 * Parameters: 1204 * mmu_info - (IN) MMU info pointer 1205 * Returns: 1206 * BCM_E_XXX 1207 */ 1208 STATIC void 1209 _bcm_tr3_cosq_free_memory(_bcm_tr3_mmu_info_t *mmu_info_p) 1210 { 1211 sal_free(mmu_info_p->ext_qlist.bits); 1212 sal_free(mmu_info_p->dmvoq_qlist.bits); 1213 sal_free(mmu_info_p->l0_sched_list.bits); 1214 sal_free(mmu_info_p->l1_sched_list.bits); 1215 } 1216 1217 STATIC int 1218 _bcm_tr3_higig_intf_index(int unit, bcm_port_t local_port) 1219 { 1220 int index = 0, port; 1221 1222 PBMP_HG_ITER(unit, port) { 1223 if (port == local_port) { 1224 return index; 1225 } 1226 index += 1; 1227 } 1228 return -1; 1229 } 1230 1231 STATIC int 1232 _bcm_tr3_voq_min_hw_index(int unit, bcm_port_t port, 1233 bcm_module_t modid, 1234 bcm_port_t remote_port, 1235 int *q_offset) 1236 { 1237 int i, hw_index_base = -1; 1238 _bcm_tr3_cosq_node_t *node; 1239 _bcm_tr3_mmu_info_t *mmu_info; 1240 1241 mmu_info = _bcm_tr3_mmu_info[unit]; 1242 1243 for (i = mmu_info->num_base_queues; i < _BCM_TR3_NUM_L2_UC_LEAVES; i++) { 1244 node = &mmu_info->queue_node[i]; 1245 if ((node->in_use == FALSE) || (node->hw_index == -1)) { 1246 continue; 1247 } 1248 1249 if (((modid == -1) ? 1 : (node->remote_modid == modid)) && 1250 (node->remote_port == remote_port) && 1251 ((port == -1) ? 1 : (port == node->local_port))) { 1252 if ((hw_index_base == -1) || (hw_index_base > node->hw_index)) { 1253 hw_index_base = node->hw_index; 1254 } 1255 } 1256 } 1257 1258 if (hw_index_base != -1) { 1259 *q_offset = hw_index_base & ~7; 1260 return BCM_E_NONE; 1261 } 1262 1263 return BCM_E_NOT_FOUND; 1264 } 1265 1266 STATIC int 1267 _bcm_tr3_voq_base_node_get(int unit, bcm_port_t port, 1268 int modid, 1269 _bcm_tr3_cosq_node_t **base_node) 1270 { 1271 int i; 1272 _bcm_tr3_cosq_node_t *node; 1273 _bcm_tr3_mmu_info_t *mmu_info; 1274 int dmvoq_found = 0; 1275 1276 mmu_info = _bcm_tr3_mmu_info[unit]; 1277 1278 *base_node = NULL; 1279 1280 for (i = mmu_info->num_base_queues; i < _BCM_TR3_NUM_L2_UC_LEAVES; i++) { 1281 node = &mmu_info->queue_node[i]; 1282 if ((node->in_use == FALSE) || (node->hw_index == -1)) { 1283 continue; 1284 } 1285 1286 /* 1287 * Identify if at least one dmvoq configuration 1288 * is applied on this port. 1289 */ 1290 if ((node->local_port == port) && 1291 (node->type == _BCM_TR3_NODE_DMVOQ) && 1292 (node->remote_modid != -1)) { 1293 dmvoq_found = 1; 1294 } 1295 1296 if ((node->local_port == port) && (node->remote_modid == modid)) { 1297 *base_node = node ; 1298 break; 1299 } 1300 } 1301 1302 /* No dmvoq configuration applied on this port */ 1303 if ((*base_node == NULL) && (dmvoq_found == 0)) { 1304 return BCM_E_NOT_FOUND; 1305 } 1306 1307 return BCM_E_NONE; 1308 } 1309 1310 STATIC int 1311 _bcm_tr3_voq_next_base_node_get(int unit, bcm_port_t port, 1312 int modid, 1313 _bcm_tr3_cosq_node_t **base_node) 1314 { 1315 1316 int i; 1317 _bcm_tr3_cosq_node_t *node; 1318 _bcm_tr3_mmu_info_t *mmu_info; 1319 int found = FALSE; 1320 1321 mmu_info = _bcm_tr3_mmu_info[unit]; 1322 1323 for (i = mmu_info->num_base_queues; i < _BCM_TR3_NUM_L2_UC_LEAVES; i++) { 1324 node = &mmu_info->queue_node[i]; 1325 if ((node->in_use == FALSE) || (node->hw_index == -1)) { 1326 continue; 1327 } 1328 1329 if (node->remote_modid == modid) { 1330 if ( found == TRUE) { 1331 *base_node = node; 1332 break; 1333 } 1334 found = TRUE; 1335 } 1336 } 1337 1338 return BCM_E_NONE; 1339 } 1340 1341 STATIC int 1342 _bcm_tr3_port_voq_base_set(int unit, bcm_port_t local_port, int base) 1343 { 1344 uint32 rval; 1345 1346 BCM_IF_ERROR_RETURN(READ_ING_COS_MODEr(unit, local_port, &rval)); 1347 soc_reg_field_set(unit, ING_COS_MODEr, &rval, BASE_QUEUE_NUM_1f, base); 1348 BCM_IF_ERROR_RETURN(WRITE_ING_COS_MODEr(unit, local_port, rval)); 1349 return BCM_E_NONE; 1350 } 1351 1352 STATIC int 1353 _bcm_tr3_port_voq_base_get(int unit, bcm_port_t local_port, int *base) 1354 { 1355 uint32 rval; 1356 1357 BCM_IF_ERROR_RETURN(READ_ING_COS_MODEr(unit, local_port, &rval)); 1358 if (soc_reg_field_get(unit, ING_COS_MODEr, rval, QUEUE_MODEf) == 1) { 1359 *base = soc_reg_field_get(unit, ING_COS_MODEr, rval, 1360 BASE_QUEUE_NUM_1f); 1361 return BCM_E_NONE; 1362 } 1363 1364 BCM_IF_ERROR_RETURN( 1365 _bcm_tr3_voq_min_hw_index(unit, local_port, -1, -1, base)); 1366 1367 return BCM_E_NONE; 1368 } 1369 1370 STATIC int 1371 _bcm_tr3_resolve_dmvoq_hw_index(int unit, _bcm_tr3_cosq_node_t *node, 1372 int cosq, bcm_module_t modid, bcm_port_t local_port) 1373 { 1374 int try, preffered_offset = -1, alloc_size; 1375 int from_offset, port, rv, q_base, port_voq_base; 1376 _bcm_tr3_mmu_info_t *mmu_info; 1377 1378 mmu_info = _bcm_tr3_mmu_info[unit]; 1379 1380 if ((modid == -1) && (mmu_info->num_dmvoq_queues > 0)) { 1381 return BCM_E_PARAM; 1382 } 1383 from_offset = mmu_info->num_base_queues; 1384 alloc_size = _TR3_NUM_COS(unit); 1385 1386 for (try = 0; try < 2; try++) { 1387 PBMP_HG_ITER(unit, port) { 1388 if ((try == 1) && (port == local_port)) { 1389 continue; 1390 } 1391 1392 if ((try == 0) && (port != local_port)) { 1393 continue; 1394 } 1395 1396 rv = _bcm_tr3_voq_min_hw_index(unit, port, modid, -1, &q_base); 1397 if (!rv) { 1398 if (port == local_port) { 1399 /* Found VOQ for the same port/dest modid */ 1400 /* Assign hw_index only if it is not assigned in gport_add */ 1401 if (node->hw_index == -1) { 1402 node->hw_index = q_base + cosq; 1403 } 1404 return BCM_E_NONE; 1405 } else if (modid == -1) { 1406 rv = _bcm_tr3_port_voq_base_get(unit, port, &port_voq_base); 1407 if (rv) { 1408 continue; 1409 } 1410 preffered_offset = q_base - port_voq_base; 1411 rv = _bcm_tr3_port_voq_base_get(unit, local_port, 1412 &port_voq_base); 1413 if (rv) { 1414 /* No VOQ on the port yet */ 1415 alloc_size += preffered_offset; 1416 } else { 1417 /* port has already VOQs */ 1418 from_offset = port_voq_base + preffered_offset; 1419 } 1420 break; 1421 } 1422 } 1423 } 1424 if (preffered_offset != -1) { 1425 break; 1426 } 1427 } 1428 1429 if (modid == -1) { 1430 /* Alloc hw index. */ 1431 rv = _bcm_tr3_node_index_get(mmu_info->ext_qlist.bits, 1432 from_offset, _BCM_TR3_NUM_L2_UC_LEAVES, 1433 alloc_size, _TR3_NUM_COS(unit), &q_base); 1434 if (rv) { 1435 return BCM_E_RESOURCE; 1436 } 1437 1438 if (_bcm_tr3_port_voq_base_get(unit, local_port, &port_voq_base)) { 1439 _bcm_tr3_port_voq_base_set(unit, local_port, q_base); 1440 } 1441 q_base = q_base + alloc_size - _TR3_NUM_COS(unit); 1442 node->hw_index = q_base + cosq; 1443 node->remote_modid = modid; 1444 _bcm_tr3_node_index_set(&mmu_info->ext_qlist, q_base, _TR3_NUM_COS(unit)); 1445 } else { 1446 1447 if (_bcm_tr3_port_voq_base_get(unit, local_port, &port_voq_base)) { 1448 _bcm_tr3_port_voq_base_set(unit, local_port, node->hw_index); 1449 } else { 1450 _bcm_tr3_port_voq_base_set(unit, local_port, MIN(port_voq_base, node->hw_index)); 1451 } 1452 1453 node->remote_modid = modid; 1454 rv = BCM_E_NONE; 1455 } 1456 return rv; 1457 } 1458 1459 typedef struct _bcm_tr3_voq_info_s { 1460 int valid; 1461 _bcm_tr3_cosq_node_t *node; 1462 bcm_module_t remote_modid; 1463 bcm_port_t remote_port; 1464 bcm_port_t local_port; 1465 int hw_cosq; 1466 int hw_index; 1467 } _bcm_tr3_voq_info_t; 1468 1469 STATIC int 1470 _bcm_tr3_cosq_sort_voq_list(void *a, void *b) 1471 { 1472 _bcm_tr3_voq_info_t *va, *vb; 1473 int sa, sb; 1474 1475 va = (_bcm_tr3_voq_info_t*)a; 1476 vb = (_bcm_tr3_voq_info_t*)b; 1477 1478 sa = (va->remote_modid << 19) | (va->remote_port << 11) | 1479 (va->local_port << 3) | (va->hw_cosq); 1480 1481 sb = (vb->remote_modid << 19) | (vb->remote_port << 11) | 1482 (vb->local_port << 3) | (vb->hw_cosq); 1483 1484 return sa - sb; 1485 } 1486 1487 STATIC int 1488 _bcm_tr3_map_fc_status_to_node(int unit, int spad_offset, int cosq, 1489 uint32 hw_index, int pfc, int lls_level) 1490 { 1491 int map_entry_index, eindex; 1492 soc_mem_t mem; 1493 uint32 map_entry[SOC_MAX_MEM_WORDS]; 1494 static const soc_field_t self[] = { 1495 SEL0f, SEL1f, SEL2f, SEL3f 1496 }; 1497 static const soc_field_t indexf[] = { 1498 INDEX0f, INDEX1f, INDEX2f, INDEX3f 1499 }; 1500 static const soc_reg_t mems[] = { 1501 INVALIDm, MMU_INTFI_FC_MAP_TBL0m, 1502 MMU_INTFI_FC_MAP_TBL1m, MMU_INTFI_FC_MAP_TBL2m 1503 }; 1504 1505 mem = mems[lls_level]; 1506 if (mem == INVALIDm) { 1507 return BCM_E_PARAM; 1508 } 1509 map_entry_index = hw_index/16; 1510 eindex = (hw_index % 16)/4; 1511 1512 BCM_IF_ERROR_RETURN 1513 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, map_entry_index, &map_entry)); 1514 soc_mem_field32_set(unit, mem, &map_entry, 1515 indexf[eindex], spad_offset + cosq/4); 1516 soc_mem_field32_set(unit, mem, &map_entry, self[eindex], !!pfc); 1517 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, 1518 MEM_BLOCK_ALL, map_entry_index, &map_entry)); 1519 return BCM_E_NONE; 1520 } 1521 1522 STATIC int 1523 _bcm_tr3_get_queue_skip_count_on_cos(uint32 cbmp, int cur_cos, int next_cos) 1524 { 1525 int i,skip = 0; 1526 1527 if ((next_cos >= 4) && (cur_cos/4 != next_cos/4)) { 1528 cur_cos = -1; 1529 next_cos -= 4; 1530 } 1531 1532 for (i = cur_cos + 1; i < next_cos; i++) { 1533 if (cbmp & (1 << i)) { 1534 skip += 1; 1535 } 1536 } 1537 return skip; 1538 } 1539 1540 STATIC int 1541 _bcm_tr3_src_mod_id_set(int unit, bcm_port_t srcid) 1542 { 1543 int ii, hole = -1; 1544 uint32 rval, csrc; 1545 1546 for (ii = 0; ii < 16; ii++) { 1547 BCM_IF_ERROR_RETURN(READ_SRC_MOD_IDr(unit, ii, &rval)); 1548 if (srcid == (csrc = soc_reg_field_get(unit, SRC_MOD_IDr, rval, SRC_MODf))) { 1549 return ii; 1550 } 1551 if ((hole == -1) && (csrc == 0)) { 1552 hole = ii; 1553 } 1554 } 1555 1556 if (hole == -1) { 1557 return BCM_E_RESOURCE; 1558 } 1559 1560 rval = 0; 1561 soc_reg_field_set(unit, SRC_MOD_IDr, &rval, SRC_MODf, srcid); 1562 soc_reg_field_set(unit, SRC_MOD_IDr, &rval, IF_IDf, (hole < 4) ? hole : 3); 1563 BCM_IF_ERROR_RETURN(WRITE_SRC_MOD_IDr(unit, hole, rval)); 1564 1565 return hole; 1566 } 1567 1568 STATIC int 1569 _bcm_tr3_gport_dpvoq_config_set(int unit, bcm_gport_t gport, 1570 bcm_cos_queue_t cosq, 1571 bcm_module_t remote_modid, 1572 bcm_port_t remote_port) 1573 { 1574 uint32 profile = 0xFFFFFFFF; 1575 _bcm_tr3_cosq_node_t *node; 1576 bcm_port_t local_port; 1577 uint32 cng_offset; 1578 uint8 cbmp = 0, nib_cbmp = 0; 1579 _bcm_tr3_mmu_info_t *mmu_info; 1580 _bcm_tr3_voq_info_t *plist = NULL, *vlist = NULL; 1581 int pcount, ii, vcount = 0; 1582 voq_port_map_entry_t *voq_port_map_entries = NULL; 1583 int rv = BCM_E_NONE, mod_base = 0, num_cos = 0, dm = -1, eq_base; 1584 voq_mod_map_entry_t voq_mod_map; 1585 void *entries[1]; 1586 int cng_bytes_per_e2ecc_msg = 32; 1587 int p2ioff[64], ioff, port, skip, *dm2off, count; 1588 1589 if ((cosq < 0) || (cosq > _TR3_NUM_COS(unit))) { 1590 return BCM_E_PARAM; 1591 } 1592 1593 if ((mmu_info = _bcm_tr3_mmu_info[unit]) == NULL) { 1594 return BCM_E_INIT; 1595 } 1596 1597 BCM_IF_ERROR_RETURN 1598 (_bcm_tr3_cosq_node_get(unit, gport, 0, NULL, &local_port, NULL, &node)); 1599 1600 eq_base = (mmu_info->num_base_queues + 7) & ~7; 1601 1602 node->remote_modid = remote_modid; 1603 node->remote_port = remote_port; 1604 node->hw_cosq = cosq; 1605 1606 dm2off = sal_alloc(sizeof(int) * 256, "voq_vlist"); 1607 if (!dm2off) { 1608 return BCM_E_MEMORY; 1609 } 1610 sal_memset(dm2off, 0, sizeof(int)*256); 1611 1612 /* alloc temp vlist */ 1613 vlist = sal_alloc(sizeof(_bcm_tr3_voq_info_t) * 1024, "voq_vlist"); 1614 if (!vlist) { 1615 sal_free(dm2off); 1616 return BCM_E_MEMORY; 1617 } 1618 sal_memset(vlist, 0, sizeof(_bcm_tr3_voq_info_t)*1024); 1619 1620 for (ii = 0; ii < _BCM_TR3_NUM_L2_UC_LEAVES; ii++) { 1621 node = &mmu_info->queue_node[ii]; 1622 if ((node->remote_modid == -1) || (node->remote_port == -1)) { 1623 continue; 1624 } 1625 vlist[vcount].remote_modid = node->remote_modid; 1626 vlist[vcount].remote_port = node->remote_port; 1627 vlist[vcount].local_port = node->local_port; 1628 vlist[vcount].hw_cosq = node->hw_cosq; 1629 vlist[vcount].node = node; 1630 vcount += 1; 1631 } 1632 1633 /* Sort the nodes */ 1634 _shr_sort(vlist, vcount, sizeof(_bcm_tr3_voq_info_t), 1635 _bcm_tr3_cosq_sort_voq_list); 1636 1637 for (ii = 0; ii < 64; ii++) { 1638 p2ioff[ii] = -1; 1639 } 1640 1641 PBMP_HG_ITER(unit, port) { 1642 ioff = _bcm_tr3_higig_intf_index(unit, port); 1643 p2ioff[port] = ioff; 1644 } 1645 1646 for (ii = 0; ii < vcount; ii++) { 1647 cbmp |= 1 << vlist[ii].hw_cosq; 1648 } 1649 1650 nib_cbmp = (cbmp >> 4) | (cbmp & 0xf); 1651 1652 for (ii = 0; ii < 4; ii++) { 1653 if ((1 << ii) & nib_cbmp) { 1654 num_cos += 1; 1655 } 1656 } 1657 1658 for (count = 1, ii = 0; ii < vcount; ii++) { 1659 if (dm2off[vlist[ii].remote_modid]==0) { 1660 dm2off[vlist[ii].remote_modid] = count; 1661 } 1662 } 1663 1664 plist = sal_alloc(sizeof(_bcm_tr3_voq_info_t) * 1024, "voq_vlist"); 1665 if (!plist) { 1666 sal_free(vlist); 1667 sal_free(dm2off); 1668 return BCM_E_MEMORY; 1669 } 1670 sal_memset(plist, 0, sizeof(_bcm_tr3_voq_info_t)*1024); 1671 1672 for (pcount = 0, ii = 0; ii < vcount; ii++) { 1673 if (pcount % 4) { 1674 if ((plist[pcount - 1].remote_modid != vlist[ii].remote_modid) || 1675 (plist[pcount - 1].remote_port != vlist[ii].remote_port)) { 1676 pcount = (pcount + 3) & ~3; 1677 } else if (plist[pcount - 1].local_port != vlist[ii].local_port) { 1678 skip = (p2ioff[vlist[ii].local_port] - 1679 p2ioff[plist[pcount - 1].local_port] - 1) * num_cos; 1680 skip += _bcm_tr3_get_queue_skip_count_on_cos(nib_cbmp, 1681 plist[pcount - 1].hw_cosq, 1682 vlist[ii].hw_cosq); 1683 if (skip >= 4) { 1684 pcount = ((pcount + 3) & ~3) + (skip % 4); 1685 } else { 1686 pcount += skip; 1687 } 1688 } else if ((vlist[ii].hw_cosq - plist[pcount - 1].hw_cosq) > 1) { 1689 if (plist[pcount - 1].hw_cosq/4 != vlist[ii].hw_cosq/4) { 1690 pcount = (pcount + 3) & ~3; 1691 } 1692 pcount += _bcm_tr3_get_queue_skip_count_on_cos(nib_cbmp, 1693 plist[pcount - 1].hw_cosq, 1694 vlist[ii].hw_cosq); 1695 } 1696 } else { 1697 pcount += _bcm_tr3_get_queue_skip_count_on_cos(nib_cbmp, -1, 1698 vlist[ii].hw_cosq); 1699 } 1700 1701 plist[pcount].valid = 1; 1702 plist[pcount].local_port = vlist[ii].local_port; 1703 plist[pcount].remote_modid = vlist[ii].remote_modid; 1704 plist[pcount].remote_port = vlist[ii].remote_port; 1705 plist[pcount].hw_cosq = vlist[ii].hw_cosq; 1706 plist[pcount].node = vlist[ii].node; 1707 vlist[ii].node->hw_index = pcount + eq_base; 1708 1709 #ifdef DEBUG_TR3_COSQ 1710 LOG_CLI((BSL_META_U(unit, 1711 "DPVOQ DM=%d DP=%d LocalPort=%d COS=%d HWIndex=%d\n"), 1712 plist[pcount].remote_modid, 1713 plist[pcount].remote_port, 1714 plist[pcount].local_port, 1715 plist[pcount].hw_cosq, 1716 plist[pcount].node->hw_index)); 1717 #endif 1718 pcount += 1; 1719 } 1720 1721 /* program the voq port profiles. */ 1722 voq_port_map_entries = sal_alloc(sizeof(voq_port_map_entry_t)*128, 1723 "voq port map entries"); 1724 if (!voq_port_map_entries) { 1725 goto fail; 1726 } 1727 sal_memset(voq_port_map_entries, 0, sizeof(voq_port_map_entry_t)*128); 1728 1729 entries[0] = voq_port_map_entries; 1730 dm = -1; 1731 for (ii = 0; ii <= pcount; ii++) { 1732 if ((ii == pcount) || 1733 ((dm != -1) && (plist[ii - 1].remote_modid != dm))) { 1734 1735 READ_VOQ_MOD_MAPm(unit, MEM_BLOCK_ALL, dm, &voq_mod_map); 1736 if (soc_mem_field32_get(unit, VOQ_MOD_MAPm, 1737 &voq_mod_map, VOQ_VALIDf)) { 1738 profile = soc_mem_field32_get(unit, VOQ_MOD_MAPm, 1739 &voq_mod_map, VOQ_MOD_PORT_PROFILE_INDEXf); 1740 1741 rv = soc_profile_mem_delete(unit, 1742 _bcm_tr3_voq_port_map_profile[unit], profile*128); 1743 if (rv) { 1744 goto fail; 1745 } 1746 } 1747 rv = soc_profile_mem_add(unit, 1748 _bcm_tr3_voq_port_map_profile[unit], 1749 entries, 128, &profile); 1750 if (rv) { 1751 goto fail; 1752 } 1753 1754 soc_mem_field32_set(unit, VOQ_MOD_MAPm, &voq_mod_map, 1755 VOQ_MOD_PORT_PROFILE_INDEXf, profile/128); 1756 soc_mem_field32_set(unit, VOQ_MOD_MAPm, &voq_mod_map, 1757 VOQ_VALIDf, 1); 1758 soc_mem_field32_set(unit, VOQ_MOD_MAPm, &voq_mod_map, 1759 VOQ_MOD_OFFSETf, mod_base); 1760 rv = soc_mem_write(unit, VOQ_MOD_MAPm, MEM_BLOCK_ALL, 1761 dm, &voq_mod_map); 1762 if (rv) { 1763 goto fail; 1764 } 1765 sal_memset(voq_port_map_entries, 0, sizeof(voq_port_map_entry_t)*128); 1766 if (ii != pcount) { 1767 mod_base = plist[ii].hw_index & ~3; 1768 dm = plist[ii].remote_modid; 1769 } 1770 } 1771 1772 if (ii == pcount) { 1773 break; 1774 } 1775 1776 if (plist[ii].valid == 0) { 1777 continue; 1778 } 1779 1780 dm = plist[ii].remote_modid; 1781 soc_mem_field32_set(unit, VOQ_PORT_MAPm, 1782 &voq_port_map_entries[plist[ii].remote_port], 1783 VOQ_PORT_OFFSETf, 1784 plist[ii].node->hw_index - mod_base); 1785 } 1786 1787 dm = -1; 1788 for (ii = 0; ii < pcount; ii += 1) { 1789 if (plist[ii].valid == 0) { 1790 continue; 1791 } 1792 1793 cng_offset = (dm2off[plist[ii].remote_modid] - 1) * 1794 cng_bytes_per_e2ecc_msg; 1795 1796 _bcm_tr3_map_fc_status_to_node(unit, 1797 cng_offset + plist[ii].remote_port, 1798 plist[ii].hw_cosq, 1799 plist[ii].node->hw_index, 0, 1800 SOC_TR3_NODE_LVL_L2); 1801 } 1802 1803 fail: 1804 if (vlist) { 1805 sal_free(vlist); 1806 } 1807 1808 if (plist) { 1809 sal_free(plist); 1810 } 1811 1812 if (dm2off) { 1813 sal_free(dm2off); 1814 } 1815 1816 if (voq_port_map_entries) { 1817 sal_free(voq_port_map_entries); 1818 } 1819 1820 if (rv) { 1821 node->remote_modid = -1; 1822 node->remote_port = -1; 1823 } 1824 return rv; 1825 } 1826 1827 STATIC int 1828 _bcm_tr3_gport_dmvoq_config_set(int unit, bcm_gport_t gport, 1829 bcm_cos_queue_t cosq, 1830 bcm_module_t fabric_modid, 1831 bcm_module_t dest_modid, 1832 bcm_port_t fabric_port) 1833 { 1834 int port_voq_base, intf_index; 1835 _bcm_tr3_cosq_node_t *node; 1836 _bcm_tr3_cosq_node_t *base_node = NULL; 1837 bcm_port_t local_port; 1838 voq_mod_map_entry_t voq_mod_map_entry; 1839 mmu_intfi_offset_map_tbl_entry_t offset_map_tbl_entry; 1840 mmu_intfi_base_index_tbl_entry_t base_tbl_entry; 1841 uint32 cng_offset = 0; 1842 int fabric_port_count, count = 0; 1843 int map_offset = 0; 1844 int port = 0; 1845 _bcm_tr3_mmu_info_t *mmu_info; 1846 int index; 1847 int voq_mod_offset = -1; 1848 int rv = BCM_E_NONE; 1849 1850 if ((mmu_info = _bcm_tr3_mmu_info[unit]) == NULL) { 1851 return BCM_E_INIT; 1852 } 1853 1854 if (fabric_modid >= 64) { 1855 return BCM_E_PARAM; 1856 } 1857 1858 BCM_IF_ERROR_RETURN 1859 (_bcm_tr3_cosq_node_get(unit, gport, 0, NULL, &local_port, NULL, &node)); 1860 1861 if (!node) { 1862 return BCM_E_NOT_FOUND; 1863 } 1864 1865 intf_index = _bcm_tr3_src_mod_id_set(unit, fabric_modid); 1866 if (intf_index < 0) { 1867 return intf_index; 1868 } 1869 1870 rv = _bcm_tr3_voq_base_node_get( 1871 unit, local_port, dest_modid, &base_node); 1872 if ((rv != BCM_E_NONE) && (rv != BCM_E_NOT_FOUND)) { 1873 return rv; 1874 } 1875 1876 if (base_node == NULL) { 1877 base_node = node ; 1878 } 1879 1880 /* This is the first dmvoq configuration on this port. 1881 * Restart programming of offset map table from start. 1882 */ 1883 if (rv == BCM_E_NOT_FOUND) { 1884 mmu_info->curr_merger_index[intf_index] = 2; 1885 } 1886 1887 BCM_IF_ERROR_RETURN(_bcm_tr3_resolve_dmvoq_hw_index(unit, node, cosq, 1888 dest_modid, local_port)); 1889 1890 1891 1892 BCM_PBMP_COUNT(base_node->fabric_pbmp, fabric_port_count); 1893 if (fabric_port_count == 0) { 1894 map_offset = mmu_info->curr_merger_index[intf_index]; 1895 if (map_offset >= soc_mem_index_count(unit, MMU_INTFI_MERGE_ST_TBLm)) { 1896 return BCM_E_RESOURCE; 1897 } 1898 } else { 1899 BCM_PBMP_ITER(base_node->fabric_pbmp, port) { 1900 index = (intf_index << 6) | (port * 2); 1901 if (index > 255) { 1902 continue; 1903 } 1904 BCM_IF_ERROR_RETURN(soc_mem_read(unit, MMU_INTFI_OFFSET_MAP_TBLm, 1905 MEM_BLOCK_ALL, 1906 index, &offset_map_tbl_entry)); 1907 map_offset = soc_mem_field32_get(unit, MMU_INTFI_OFFSET_MAP_TBLm, 1908 &offset_map_tbl_entry, 1909 MAP_OFFSETf); 1910 break; 1911 } 1912 } 1913 if (!BCM_PBMP_MEMBER(base_node->fabric_pbmp, fabric_port)) { 1914 if (map_offset == mmu_info->curr_merger_index[intf_index]) { 1915 mmu_info->curr_merger_index[intf_index] += 2; 1916 } 1917 1918 BCM_PBMP_PORT_ADD (base_node->fabric_pbmp, fabric_port); 1919 BCM_PBMP_COUNT(base_node->fabric_pbmp, fabric_port_count); 1920 BCM_PBMP_ITER(base_node->fabric_pbmp, port) { 1921 count++; 1922 index = (intf_index << 6) | (port * 2); 1923 if (index > 255) { 1924 continue; 1925 } 1926 BCM_IF_ERROR_RETURN(soc_mem_read(unit, MMU_INTFI_OFFSET_MAP_TBLm, 1927 MEM_BLOCK_ALL, 1928 index, &offset_map_tbl_entry)); 1929 soc_mem_field32_set(unit, MMU_INTFI_OFFSET_MAP_TBLm, 1930 &offset_map_tbl_entry, 1931 MAP_OFFSETf, map_offset); 1932 soc_mem_field32_set(unit, MMU_INTFI_OFFSET_MAP_TBLm, 1933 &offset_map_tbl_entry, 1934 LASTf, count < fabric_port_count ? 0 : 1 ); 1935 BCM_IF_ERROR_RETURN(soc_mem_write(unit, MMU_INTFI_OFFSET_MAP_TBLm, 1936 MEM_BLOCK_ALL, 1937 index, &offset_map_tbl_entry)); 1938 1939 index = (intf_index << 6) | ((port * 2) + 1); 1940 if (index > 255) { 1941 continue; 1942 } 1943 BCM_IF_ERROR_RETURN(soc_mem_read(unit, MMU_INTFI_OFFSET_MAP_TBLm, 1944 MEM_BLOCK_ALL, 1945 index, &offset_map_tbl_entry)); 1946 soc_mem_field32_set(unit, MMU_INTFI_OFFSET_MAP_TBLm, 1947 &offset_map_tbl_entry, 1948 MAP_OFFSETf, map_offset + 1); 1949 soc_mem_field32_set(unit, MMU_INTFI_OFFSET_MAP_TBLm, 1950 &offset_map_tbl_entry, 1951 LASTf, count < fabric_port_count ? 0 : 1 ); 1952 BCM_IF_ERROR_RETURN(soc_mem_write(unit, MMU_INTFI_OFFSET_MAP_TBLm, 1953 MEM_BLOCK_ALL, 1954 index, &offset_map_tbl_entry)); 1955 } 1956 } 1957 1958 BCM_IF_ERROR_RETURN(soc_mem_read(unit, VOQ_MOD_MAPm, MEM_BLOCK_ALL, 1959 dest_modid, &voq_mod_map_entry)); 1960 1961 BCM_IF_ERROR_RETURN(_bcm_tr3_port_voq_base_get(unit, local_port, 1962 &port_voq_base)); 1963 if (soc_mem_field32_get(unit, VOQ_MOD_MAPm, &voq_mod_map_entry, VOQ_VALIDf)) { 1964 voq_mod_offset = soc_mem_field32_get(unit, VOQ_MOD_MAPm, &voq_mod_map_entry, 1965 VOQ_MOD_OFFSETf); 1966 } 1967 if ((voq_mod_offset != -1) && 1968 (voq_mod_offset != ((node->hw_index & ~7) - port_voq_base))) { 1969 1970 /* This module offset had already been configured with a 1971 * different value. Changing it might affect other port 1972 * configurations. 1973 */ 1974 return BCM_E_PARAM; 1975 } 1976 soc_mem_field32_set(unit, VOQ_MOD_MAPm, &voq_mod_map_entry, 1977 VOQ_VALIDf, 1); 1978 1979 soc_mem_field32_set(unit, VOQ_MOD_MAPm, &voq_mod_map_entry, 1980 VOQ_MOD_OFFSETf, ((node->hw_index & ~7) - port_voq_base)); 1981 1982 BCM_IF_ERROR_RETURN( 1983 soc_mem_write(unit, VOQ_MOD_MAPm, MEM_BLOCK_ALL, dest_modid, 1984 &voq_mod_map_entry)); 1985 1986 cng_offset = intf_index * 128; 1987 1988 /* set the mapping from congestion bits in flow control table 1989 * to corresponding cosq. */ 1990 BCM_IF_ERROR_RETURN(_bcm_tr3_map_fc_status_to_node(unit, 1991 cng_offset + map_offset, cosq, node->hw_index, 0, 1992 SOC_TR3_NODE_LVL_L2)); 1993 1994 1995 BCM_IF_ERROR_RETURN 1996 (soc_mem_read(unit, MMU_INTFI_BASE_INDEX_TBLm, 1997 MEM_BLOCK_ALL, fabric_modid, &base_tbl_entry)); 1998 1999 soc_mem_field32_set(unit, MMU_INTFI_BASE_INDEX_TBLm, &base_tbl_entry, 2000 BASE_ADDRf, cng_offset); 2001 soc_mem_field32_set(unit, MMU_INTFI_BASE_INDEX_TBLm, &base_tbl_entry, 2002 ENf, 2); 2003 2004 BCM_IF_ERROR_RETURN(soc_mem_write(unit, MMU_INTFI_BASE_INDEX_TBLm, 2005 MEM_BLOCK_ALL, fabric_modid, &base_tbl_entry)); 2006 2007 #ifdef DEBUG_TR3_COSQ 2008 LOG_CLI((BSL_META_U(unit, 2009 "Gport=0x%08x hw_index=%d cosq=%d\n"), 2010 gport, node->hw_index, cosq)); 2011 #endif 2012 2013 return BCM_E_NONE; 2014 } 2015 2016 int bcm_tr3_cosq_gport_congestion_config_set(int unit, bcm_gport_t gport, 2017 bcm_cos_queue_t cosq, 2018 bcm_cosq_congestion_info_t *config) 2019 { 2020 _bcm_tr3_mmu_info_t *mmu_info; 2021 2022 if (!config) { 2023 return BCM_E_PARAM; 2024 } 2025 2026 if ((mmu_info = _bcm_tr3_mmu_info[unit]) == NULL) { 2027 return BCM_E_INIT; 2028 } 2029 2030 if (!_BCM_TR3_IS_DESTMOD_QUEUE_GROUP(mmu_info, gport)) { 2031 return BCM_E_PARAM; 2032 } 2033 2034 /* determine if this gport is DPVOQ or DMVOQ */ 2035 if ((config->fabric_port != -1) && (config->dest_modid != -1)) { 2036 if (config->fabric_modid == -1) { 2037 return BCM_E_PARAM; 2038 } 2039 return _bcm_tr3_gport_dmvoq_config_set(unit, gport, cosq, 2040 config->fabric_modid, 2041 config->dest_modid, 2042 config->fabric_port); 2043 } else if ((config->dest_modid != -1) && (config->dest_port != -1)) { 2044 return _bcm_tr3_gport_dpvoq_config_set(unit, gport, cosq, 2045 config->dest_modid, 2046 config->dest_port); 2047 } 2048 2049 return BCM_E_PARAM; 2050 } 2051 2052 int bcm_tr3_cosq_gport_congestion_config_get(int unit, bcm_gport_t port, 2053 bcm_cos_queue_t cosq, 2054 bcm_cosq_congestion_info_t *config) 2055 { 2056 _bcm_tr3_mmu_info_t *mmu_info; 2057 bcm_port_t local_port; 2058 _bcm_tr3_cosq_node_t *node; 2059 2060 if (!config) { 2061 return BCM_E_PARAM; 2062 } 2063 2064 if ((mmu_info = _bcm_tr3_mmu_info[unit]) == NULL) { 2065 return BCM_E_INIT; 2066 } 2067 2068 if (!_BCM_TR3_IS_DESTMOD_QUEUE_GROUP(mmu_info, port)) { 2069 return BCM_E_PARAM; 2070 } 2071 2072 BCM_IF_ERROR_RETURN 2073 (_bcm_tr3_cosq_node_get(unit, port, 0, NULL, &local_port, NULL, &node)); 2074 2075 2076 if (!node) { 2077 return BCM_E_NOT_FOUND; 2078 } 2079 2080 config->dest_modid = node->remote_modid; 2081 config->dest_port = node->remote_port; 2082 2083 return BCM_E_NONE; 2084 } 2085 2086 /* 2087 * Function: 2088 * _bcm_tr3_cosq_node_get 2089 * Purpose: 2090 * Get internal information of queue group or scheduler type GPORT 2091 * Parameters: 2092 * unit - (IN) unit number 2093 * gport - (IN) queue group/scheduler GPORT identifier 2094 * modid - (OUT) module identifier 2095 * port - (OUT) port number 2096 * id - (OUT) queue group or scheduler identifier 2097 * node - (OUT) node structure for the specified GPORT 2098 * Returns: 2099 * BCM_E_XXX 2100 */ 2101 STATIC int 2102 _bcm_tr3_cosq_node_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 2103 bcm_module_t *modid, bcm_port_t *port, 2104 int *id, _bcm_tr3_cosq_node_t **node) 2105 { 2106 _bcm_tr3_mmu_info_t *mmu_info; 2107 _bcm_tr3_cosq_node_t *node_base = NULL; 2108 bcm_module_t modid_out = 0; 2109 bcm_port_t port_out = 0; 2110 uint32 encap_id = -1; 2111 int index; 2112 2113 if ((mmu_info = _bcm_tr3_mmu_info[unit]) == NULL) { 2114 return BCM_E_INIT; 2115 } 2116 2117 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 2118 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid_out)); 2119 port_out = BCM_GPORT_UCAST_QUEUE_GROUP_SYSPORTID_GET(gport); 2120 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 2121 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid_out)); 2122 port_out = BCM_GPORT_MCAST_QUEUE_GROUP_SYSPORTID_GET(gport); 2123 } else if (BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) { 2124 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid_out)); 2125 port_out = BCM_GPORT_DESTMOD_QUEUE_GROUP_SYSPORTID_GET(gport); 2126 } else if (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport)) { 2127 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid_out)); 2128 port_out = (gport >> 16) & 0xff; 2129 } else if (BCM_GPORT_IS_SCHEDULER(gport)) { 2130 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid_out)); 2131 port_out = BCM_GPORT_SCHEDULER_GET(gport) & 0xff; 2132 } else if (BCM_GPORT_IS_LOCAL(gport)) { 2133 encap_id = BCM_GPORT_LOCAL_GET(gport); 2134 port_out = encap_id; 2135 } else if (BCM_GPORT_IS_MODPORT(gport)) { 2136 modid_out = SOC_GPORT_MODPORT_MODID_GET(gport); 2137 port_out = SOC_GPORT_MODPORT_PORT_GET(gport); 2138 encap_id = port_out; 2139 } else { 2140 return BCM_E_PORT; 2141 } 2142 2143 if (!SOC_PORT_VALID(unit, port_out)) { 2144 return BCM_E_PORT; 2145 } 2146 2147 if (port != NULL) { 2148 *port = port_out; 2149 } 2150 2151 if (!_bcm_tr3_cosq_port_has_ets(unit, port_out)) { 2152 return BCM_E_NOT_FOUND; 2153 } 2154 2155 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 2156 encap_id = BCM_GPORT_UCAST_QUEUE_GROUP_QID_GET(gport); 2157 index = encap_id; 2158 node_base = mmu_info->queue_node; 2159 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 2160 encap_id = BCM_GPORT_MCAST_QUEUE_GROUP_QID_GET(gport); 2161 index = encap_id; 2162 node_base = mmu_info->mc_queue_node; 2163 } else if (BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) { 2164 encap_id = BCM_GPORT_DESTMOD_QUEUE_GROUP_QID_GET(gport); 2165 index = encap_id; 2166 if (mmu_info->num_dmvoq_queues > 0) { 2167 index += mmu_info->base_dmvoq_queue; 2168 } 2169 node_base = mmu_info->queue_node; 2170 } else if (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport)) { 2171 encap_id = BCM_GPORT_UCAST_SUBSCRIBER_QUEUE_GROUP_QID_GET(gport); 2172 index = encap_id; 2173 node_base = mmu_info->queue_node; 2174 } else if (BCM_GPORT_IS_SCHEDULER(gport)) { 2175 encap_id = (BCM_GPORT_SCHEDULER_GET(gport) >> 8) & 0x7ff; 2176 index = encap_id; 2177 node_base = mmu_info->sched_node; 2178 } else { 2179 index = encap_id; 2180 node_base = mmu_info->sched_node; 2181 } 2182 2183 if (index < 0) { 2184 return BCM_E_NOT_FOUND; 2185 } 2186 2187 if (node_base[index].numq == 0) { 2188 return BCM_E_NOT_FOUND; 2189 } 2190 2191 if (modid != NULL) { 2192 *modid = modid_out; 2193 } 2194 if (id != NULL) { 2195 *id = encap_id; 2196 } 2197 if (node != NULL) { 2198 *node = &node_base[index]; 2199 } 2200 2201 return BCM_E_NONE; 2202 } 2203 2204 int 2205 _bcm_tr3_cosq_port_resolve(int unit, bcm_gport_t gport, bcm_module_t *modid, 2206 bcm_port_t *port, bcm_trunk_t *trunk_id, int *id, 2207 int *qnum) 2208 { 2209 _bcm_tr3_cosq_node_t *node; 2210 2211 BCM_IF_ERROR_RETURN 2212 (_bcm_tr3_cosq_node_get(unit, gport, 0, modid, port, id, &node)); 2213 *trunk_id = -1; 2214 2215 if (qnum) { 2216 if (node->hw_index == -1) { 2217 return BCM_E_PARAM; 2218 } 2219 *qnum = node->hw_index; 2220 } 2221 2222 return BCM_E_NONE; 2223 } 2224 2225 /* 2226 * Function: 2227 * _bcm_tr3_cosq_gport_traverse 2228 * Purpose: 2229 * Walks through the valid COSQ GPORTs and calls 2230 * the user supplied callback function for each entry. 2231 * Parameters: 2232 * unit - (IN) unit number 2233 * gport - (IN) 2234 * cb - (IN) Callback function. 2235 * user_data - (IN) User data to be passed to callback function 2236 * Returns: 2237 * BCM_E_NONE - Success. 2238 * BCM_E_XXX 2239 */ 2240 int 2241 _bcm_tr3_cosq_gport_traverse(int unit, bcm_gport_t gport, 2242 bcm_cosq_gport_traverse_cb cb, 2243 void *user_data) 2244 { 2245 _bcm_tr3_mmu_info_t *mmu_info; 2246 _bcm_tr3_cosq_node_t *node; 2247 uint32 flags = BCM_COSQ_GPORT_SCHEDULER; 2248 int rv = BCM_E_NONE, id; 2249 bcm_gport_t local_gport; 2250 2251 if ((mmu_info = _bcm_tr3_mmu_info[unit]) == NULL) { 2252 return BCM_E_INIT; 2253 } 2254 2255 BCM_IF_ERROR_RETURN 2256 (_bcm_tr3_cosq_node_get(unit, gport, 0, NULL, NULL, NULL, &node)); 2257 2258 if (node != NULL) { 2259 if (node->level == SOC_TR3_NODE_LVL_L2) { 2260 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(node->gport)) { 2261 id = BCM_GPORT_UCAST_QUEUE_GROUP_QID_GET(node->gport); 2262 if (_BCM_TR3_IS_UC_QUEUE(mmu_info, id)) { 2263 flags = BCM_COSQ_GPORT_UCAST_QUEUE_GROUP; 2264 } else if (node->type == _BCM_TR3_NODE_DMVOQ) { 2265 flags = BCM_COSQ_GPORT_DESTMOD_UCAST_QUEUE_GROUP; 2266 } else if (node->type == _BCM_TR3_NODE_VLAN) { 2267 flags = BCM_COSQ_GPORT_VLAN_UCAST_QUEUE_GROUP; 2268 } 2269 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(node->gport)) { 2270 flags = BCM_COSQ_GPORT_MCAST_QUEUE_GROUP; 2271 } else if (BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(node->gport)) { 2272 flags = BCM_COSQ_GPORT_DESTMOD_UCAST_QUEUE_GROUP; 2273 } 2274 } else { 2275 flags = BCM_COSQ_GPORT_SCHEDULER; 2276 } 2277 BCM_IF_ERROR_RETURN 2278 (bcm_esw_port_gport_get(unit, node->local_port, &local_gport)); 2279 rv = cb(unit, local_gport, node->numq, flags, 2280 node->gport, user_data); 2281 if (BCM_FAILURE(rv)) { 2282 #ifdef BCM_CB_ABORT_ON_ERR 2283 if (SOC_CB_ABORT_ON_ERR(unit)) { 2284 return rv; 2285 } 2286 #endif 2287 } 2288 } else { 2289 return BCM_E_NONE; 2290 } 2291 2292 if (node->sibling != NULL) { 2293 _bcm_tr3_cosq_gport_traverse(unit, node->sibling->gport, cb, user_data); 2294 } 2295 2296 if (node->child != NULL) { 2297 _bcm_tr3_cosq_gport_traverse(unit, node->child->gport, cb, user_data); 2298 } 2299 2300 return BCM_E_NONE; 2301 } 2302 2303 STATIC int 2304 _bcm_tr3_cosq_traverse_lls_tree(int unit, int port, _bcm_tr3_cosq_node_t *node, 2305 _soc_tr3_lls_traverse_cb cb, void *cookie) 2306 { 2307 if (node->child) { 2308 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_traverse_lls_tree(unit, port, node->child, 2309 cb, cookie)); 2310 } 2311 2312 if (node->sibling) { 2313 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_traverse_lls_tree(unit, port, 2314 node->sibling, cb, cookie)); 2315 } 2316 2317 if (node->level != SOC_TR3_NODE_LVL_ROOT) { 2318 BCM_IF_ERROR_RETURN(cb(unit, port, node->level, node->hw_index, cookie)); 2319 } 2320 2321 return BCM_E_NONE; 2322 } 2323 2324 STATIC int 2325 _bcm_tr3_cosq_child_node_at_input(_bcm_tr3_cosq_node_t *node, int cosq, 2326 _bcm_tr3_cosq_node_t **child_node) 2327 { 2328 _bcm_tr3_cosq_node_t *cur_node; 2329 2330 for (cur_node = node->child; cur_node; cur_node = cur_node->sibling) { 2331 if (cur_node->attached_to_input == cosq) { 2332 break; 2333 } 2334 } 2335 if (!cur_node) { 2336 return BCM_E_NOT_FOUND; 2337 } 2338 2339 *child_node = cur_node; 2340 2341 return BCM_E_NONE; 2342 } 2343 2344 STATIC int 2345 _bcm_tr3_cosq_l2_gport(int unit, int port, int cosq, 2346 _bcm_tr3_node_type_e type, bcm_gport_t *gport, 2347 _bcm_tr3_cosq_node_t **p_node) 2348 { 2349 int i, max; 2350 _bcm_tr3_cosq_node_t *node, *fnode; 2351 _bcm_tr3_mmu_info_t *mmu_info; 2352 2353 mmu_info = _bcm_tr3_mmu_info[unit]; 2354 2355 max = 0; 2356 if ((type == _BCM_TR3_NODE_UCAST) || (type == _BCM_TR3_NODE_DMVOQ) || 2357 (type == _BCM_TR3_NODE_VLAN)) { 2358 max = _BCM_TR3_NUM_L2_UC_LEAVES; 2359 fnode = &mmu_info->queue_node[0]; 2360 } else if (type == _BCM_TR3_NODE_MCAST) { 2361 max = _BCM_TR3_NUM_L2_MC_LEAVES; 2362 fnode = &mmu_info->mc_queue_node[0]; 2363 } else { 2364 return BCM_E_PARAM; 2365 } 2366 2367 for (i = 0; i < max; i++) { 2368 node = fnode + i; 2369 if (node->in_use && (node->local_port == port) && 2370 (node->type == type) && (node->hw_cosq == cosq)) { 2371 if (gport) { 2372 *gport = node->gport; 2373 } 2374 if (p_node) { 2375 *p_node = node; 2376 } 2377 return BCM_E_NONE; 2378 } 2379 } 2380 return BCM_E_NOT_FOUND; 2381 } 2382 2383 /* 2384 * Function: 2385 * _bcm_tr3_cosq_index_resolve 2386 * Purpose: 2387 * Find hardware index for the given port/cosq 2388 * Parameters: 2389 * unit - (IN) unit number 2390 * port - (IN) port number or GPORT identifier 2391 * cosq - (IN) COS queue number 2392 * style - (IN) index style (_BCM_KA_COSQ_INDEX_STYLE_XXX) 2393 * local_port - (OUT) local port number 2394 * index - (OUT) result index 2395 * count - (OUT) number of index 2396 * Returns: 2397 * BCM_E_XXX 2398 */ 2399 int 2400 _bcm_tr3_cosq_index_resolve(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 2401 _bcm_tr3_cosq_index_style_t style, 2402 bcm_port_t *local_port, int *index, int *count) 2403 { 2404 _bcm_tr3_cosq_node_t *node, *cur_node; 2405 bcm_port_t resolved_port; 2406 int resolved_index = -1; 2407 int id, startq, numq, pool_start, pool_end, lvl; 2408 soc_info_t *si; 2409 int phy_port, mmu_port; 2410 2411 si = &SOC_INFO(unit); 2412 2413 if (cosq < -1) { 2414 return BCM_E_PARAM; 2415 } else if (cosq == -1) { 2416 startq = 0; 2417 numq = _TR3_NUM_COS(unit); 2418 } else { 2419 startq = cosq; 2420 numq = 1; 2421 } 2422 2423 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 2424 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port) || 2425 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) || 2426 BCM_GPORT_IS_SCHEDULER(port)) { 2427 BCM_IF_ERROR_RETURN 2428 (_bcm_tr3_cosq_node_get(unit, port, cosq, NULL, &resolved_port, &id, 2429 &node)); 2430 if (node->attached_to_input < 0) { /* Not resolved yet */ 2431 return BCM_E_PARAM; 2432 } 2433 numq = (node->numq != -1) ? node->numq : 64; 2434 } else { 2435 /* optionally validate port */ 2436 BCM_IF_ERROR_RETURN 2437 (_bcm_tr3_cosq_localport_resolve(unit, port, &resolved_port)); 2438 if (resolved_port < 0) { 2439 return BCM_E_PORT; 2440 } 2441 node = NULL; 2442 if (IS_CPU_PORT(unit, resolved_port)) { 2443 numq = NUM_CPU_COSQ(unit); 2444 } else if (IS_TR3_HSP_PORT(unit, resolved_port)) { 2445 numq = _TR3_NUM_HSP_COSQ; 2446 } else { 2447 numq = soc_port_hg_capable(unit, resolved_port) ? _TR3_NUM_HG_COSQ: _TR3_NUM_COS(unit); 2448 } 2449 } 2450 2451 if (startq >= numq) { 2452 return BCM_E_PARAM; 2453 } 2454 2455 phy_port = si->port_l2p_mapping[resolved_port]; 2456 mmu_port = si->port_p2m_mapping[phy_port]; 2457 2458 2459 if ((node == NULL) && (BCM_GPORT_IS_MODPORT(port) && 2460 (!IS_TR3_HSP_PORT(unit, resolved_port))) && 2461 (_bcm_tr3_cosq_port_has_ets(unit, resolved_port))) { 2462 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_node_get(unit, port, 0, 2463 NULL, NULL, NULL, &node)); 2464 } 2465 2466 switch (style) { 2467 case _BCM_TR3_COSQ_INDEX_STYLE_BUCKET: 2468 if (node != NULL) { 2469 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 2470 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port)) { 2471 resolved_index = node->hw_index; 2472 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 2473 resolved_index = node->hw_index; 2474 } else if (BCM_GPORT_IS_SCHEDULER(port) || BCM_GPORT_IS_MODPORT(port)) { 2475 /* resolve the child attached to input cosq */ 2476 BCM_IF_ERROR_RETURN( 2477 _bcm_tr3_cosq_child_node_at_input(node, startq, &cur_node)); 2478 if (IS_TR3_HSP_PORT(unit, resolved_port)) { 2479 lvl = cur_node->level; 2480 BCM_IF_ERROR_RETURN(soc_tr3_hsp_sched_hw_index_get(unit, 2481 resolved_port, lvl, 2482 node->attached_to_input, 2483 startq, &resolved_index)); 2484 } else { 2485 resolved_index = cur_node->hw_index; 2486 } 2487 } else { 2488 return BCM_E_PARAM; 2489 } 2490 } else { /* node == NULL */ 2491 if (IS_CPU_PORT(unit, resolved_port)) { 2492 resolved_index = SOC_INFO(unit).port_cosq_base[resolved_port] + 2493 startq; 2494 resolved_index = soc_tr3_l2_hw_index(unit, resolved_index, 0); 2495 } else { 2496 if (IS_TR3_HSP_PORT(unit, resolved_port)) { 2497 lvl = SOC_TR3_NODE_LVL_L0; 2498 if (startq >= _TR3_NUM_HSP_COSQ) { 2499 startq = _TR3_NUM_HSP_COSQ - 1; 2500 } 2501 BCM_IF_ERROR_RETURN(soc_tr3_hsp_sched_hw_index_get(unit, 2502 resolved_port, lvl, 0, 2503 startq, &resolved_index)); 2504 2505 } else { 2506 lvl = SOC_TR3_NODE_LVL_L1; 2507 BCM_IF_ERROR_RETURN(soc_tr3_sched_hw_index_get(unit, 2508 resolved_port, lvl, 2509 startq, &resolved_index)); 2510 } 2511 } 2512 } 2513 break; 2514 2515 case _BCM_TR3_COSQ_INDEX_STYLE_QCN: 2516 if (node != NULL) { 2517 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 2518 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port)) { 2519 resolved_index = node->hw_index; 2520 } else { 2521 return BCM_E_PARAM; 2522 } 2523 } else { /* node == NULL */ 2524 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_port_has_ets(unit, resolved_port)); 2525 if (IS_CPU_PORT(unit, resolved_port)) { 2526 return BCM_E_PARAM; 2527 } else { 2528 resolved_index = si->port_uc_cosq_base[resolved_port] + startq; 2529 } 2530 } 2531 break; 2532 2533 case _BCM_TR3_COSQ_INDEX_STYLE_WRED: 2534 if (node != NULL) { 2535 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 2536 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port)) { 2537 resolved_index = node->hw_index; 2538 } else if (BCM_GPORT_IS_SCHEDULER(port)) { 2539 BCM_IF_ERROR_RETURN( 2540 _bcm_tr3_cosq_child_node_at_input(node, startq, &cur_node)); 2541 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(cur_node->gport)) { 2542 resolved_index = cur_node->hw_index; 2543 } else { 2544 return BCM_E_PARAM; 2545 } 2546 } else if (BCM_GPORT_IS_MODPORT(port)) { 2547 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_l2_gport(unit, node->local_port, 2548 startq, _BCM_TR3_NODE_UCAST, NULL, &cur_node)); 2549 resolved_index = cur_node->hw_index; 2550 } else { 2551 return BCM_E_PARAM; 2552 } 2553 } else { /* node == NULL */ 2554 if (IS_CPU_PORT(unit, resolved_port) || 2555 IS_LB_PORT(unit, resolved_port)) { 2556 return BCM_E_PARAM; 2557 } 2558 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_port_has_ets(unit, resolved_port)); 2559 resolved_index = si->port_uc_cosq_base[resolved_port] + startq; 2560 numq = 1; 2561 } 2562 break; 2563 2564 case _BCM_TR3_COSQ_INDEX_STYLE_WRED_PORT: 2565 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_egress_sp_get(unit, resolved_port, 2566 startq, &pool_start, &pool_end)); 2567 resolved_index = 1280 + (mmu_port*4) + pool_start; 2568 numq = 4; 2569 break; 2570 2571 case _BCM_TR3_COSQ_INDEX_STYLE_SCHEDULER: 2572 if (node != NULL) { 2573 if (!BCM_GPORT_IS_SCHEDULER(port)) { 2574 return BCM_E_PARAM; 2575 } 2576 BCM_IF_ERROR_RETURN( 2577 _bcm_tr3_cosq_child_node_at_input(node, startq, &cur_node)); 2578 if (IS_TR3_HSP_PORT(unit, resolved_port)) { 2579 lvl = cur_node->level; 2580 BCM_IF_ERROR_RETURN(soc_tr3_hsp_sched_hw_index_get(unit, 2581 resolved_port, lvl, 2582 node->attached_to_input, 2583 startq, &resolved_index)); 2584 } else { 2585 resolved_index = cur_node->hw_index; 2586 } 2587 } else { /* node == NULL */ 2588 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_port_has_ets(unit, resolved_port)); 2589 if (IS_CPU_PORT(unit, resolved_port)) { 2590 resolved_index = 1024 + si->port_cosq_base[resolved_port] + startq; 2591 } else { 2592 if (IS_TR3_HSP_PORT(unit, resolved_port)) { 2593 lvl = SOC_TR3_NODE_LVL_L0; 2594 if (startq >= _TR3_NUM_HSP_COSQ) { 2595 startq = _TR3_NUM_HSP_COSQ - 1; 2596 } 2597 BCM_IF_ERROR_RETURN(soc_tr3_hsp_sched_hw_index_get(unit, 2598 resolved_port, lvl, 0, startq, 2599 &resolved_index)); 2600 } else { 2601 lvl = SOC_TR3_NODE_LVL_L1; 2602 BCM_IF_ERROR_RETURN(soc_tr3_sched_hw_index_get(unit, 2603 resolved_port, lvl, startq, 2604 &resolved_index)); 2605 } 2606 } 2607 } 2608 break; 2609 2610 case _BCM_TR3_COSQ_INDEX_STYLE_COS: 2611 if (node) { 2612 if ((BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) || 2613 (BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port)) || 2614 (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port))) { 2615 resolved_index = node->hw_cosq; 2616 } else if (BCM_GPORT_IS_SCHEDULER(port)) { 2617 BCM_IF_ERROR_RETURN( 2618 _bcm_tr3_cosq_child_node_at_input(node, startq, &cur_node)); 2619 if (BCM_GPORT_IS_SCHEDULER(cur_node->gport)) { 2620 return BCM_E_PARAM; 2621 } 2622 resolved_index = cur_node->hw_cosq; 2623 } 2624 } else { 2625 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_port_has_ets(unit, resolved_port)); 2626 resolved_index = startq; 2627 } 2628 break; 2629 2630 case _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE: 2631 if (node) { 2632 resolved_index = node->hw_index; 2633 numq = 1; 2634 } else { 2635 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_port_has_ets(unit, resolved_port)); 2636 if (IS_CPU_PORT(unit, resolved_port)) { 2637 numq = 0; 2638 resolved_index = -1; 2639 } else { 2640 numq = 1; 2641 resolved_index = si->port_uc_cosq_base[resolved_port] + startq; 2642 } 2643 } 2644 break; 2645 2646 case _BCM_TR3_COSQ_INDEX_STYLE_MCAST_QUEUE: 2647 if (node) { 2648 resolved_index = node->hw_index; 2649 numq = 1; 2650 } else { 2651 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_port_has_ets(unit, resolved_port)); 2652 numq = 1; 2653 resolved_index = 1024 + si->port_cosq_base[resolved_port] + startq; 2654 } 2655 break; 2656 2657 case _BCM_TR3_COSQ_INDEX_STYLE_EGR_POOL: 2658 if ((node != NULL) && (!BCM_GPORT_IS_MODPORT(port))) { 2659 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 2660 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port)) { 2661 /* regular unicast queue */ 2662 resolved_index = node->hw_index + startq; 2663 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 2664 resolved_index = node->hw_index - 2665 (si->port_cosq_base[resolved_port] + _BCM_TR3_NUM_L2_UC_LEAVES); 2666 } else { /* scheduler */ 2667 return BCM_E_PARAM; 2668 } 2669 } else { /* node == NULL */ 2670 numq = si->port_num_cosq[resolved_port]; 2671 if (startq >= numq) { 2672 return BCM_E_PARAM; 2673 } 2674 resolved_index = startq; 2675 } 2676 break; 2677 2678 case _BCM_TR3_COSQ_INDEX_STYLE_EGR_PERQ_UCAST: 2679 if (node) { 2680 resolved_index = node->hw_index + startq; 2681 resolved_index -= soc_tr3_l2_hw_index(unit, 2682 si->port_uc_cosq_base[resolved_port], 1); 2683 numq = 1; 2684 } else { 2685 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_port_has_ets(unit, resolved_port)); 2686 numq = 1; 2687 resolved_index = startq; 2688 } 2689 break; 2690 2691 case _BCM_TR3_COSQ_INDEX_STYLE_EGR_PERQ_MCAST: 2692 if (node) { 2693 resolved_index = node->hw_index + startq; 2694 resolved_index -= soc_tr3_l2_hw_index(unit, 2695 si->port_cosq_base[resolved_port], 0); 2696 numq = 1; 2697 } else { 2698 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_port_has_ets(unit, resolved_port)); 2699 numq = 1; 2700 resolved_index = startq; 2701 } 2702 break; 2703 2704 case _BCM_TR3_COSQ_INDEX_STYLE_UC_EGR_POOL: 2705 numq = si->port_num_uc_cosq[resolved_port]; 2706 if (startq >= numq) { 2707 return BCM_E_PARAM; 2708 } 2709 resolved_index = startq; 2710 break; 2711 2712 default: 2713 return BCM_E_INTERNAL; 2714 } 2715 2716 if (local_port != NULL) { 2717 *local_port = resolved_port; 2718 } 2719 if (index != NULL) { 2720 *index = resolved_index; 2721 } 2722 if (count != NULL) { 2723 *count = (cosq == -1) ? numq : 1; 2724 } 2725 2726 return BCM_E_NONE; 2727 } 2728 2729 STATIC int _bcm_tr3_cosq_min_child_index(_bcm_tr3_cosq_node_t *child, int lvl, int uc) 2730 { 2731 int min_index = -1; 2732 2733 if ((lvl == SOC_TR3_NODE_LVL_L2) && (uc)) { 2734 while (child) { 2735 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(child->gport) || 2736 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(child->gport)) { 2737 if (min_index == -1) { 2738 min_index = child->hw_index; 2739 } 2740 2741 if (child->hw_index < min_index) { 2742 min_index = child->hw_index; 2743 } 2744 } 2745 child = child->sibling; 2746 } 2747 } else if ((lvl == SOC_TR3_NODE_LVL_L2) && (!uc)) { 2748 while (child) { 2749 if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(child->gport)) { 2750 if (min_index == -1) { 2751 min_index = child->hw_index; 2752 } 2753 2754 if (child->hw_index < min_index) { 2755 min_index = child->hw_index; 2756 } 2757 } 2758 child = child->sibling; 2759 } 2760 } else { 2761 while (child) { 2762 if (min_index == -1) { 2763 min_index = child->hw_index; 2764 } 2765 2766 if (child->hw_index < min_index) { 2767 min_index = child->hw_index; 2768 } 2769 child = child->sibling; 2770 } 2771 } 2772 2773 return min_index; 2774 } 2775 2776 STATIC int 2777 _bcm_tr3_attach_node_in_hw(int unit, _bcm_tr3_cosq_node_t *node) 2778 { 2779 int local_port, fc = 0, fmc = 0, num_spri = 0; 2780 _bcm_tr3_cosq_node_t *child_node; 2781 uint32 spmap = 0, ucmap=0; 2782 int weight; 2783 2784 local_port = node->local_port; 2785 2786 if (node->level == SOC_TR3_NODE_LVL_ROOT) { 2787 return 0; 2788 } else if (node->level == SOC_TR3_NODE_LVL_L2) { 2789 fc = _bcm_tr3_cosq_min_child_index(node->parent->child, SOC_TR3_NODE_LVL_L2, 1); 2790 if (fc < 0) { 2791 fc = 0; 2792 } 2793 fmc = _bcm_tr3_cosq_min_child_index(node->parent->child, SOC_TR3_NODE_LVL_L2, 0); 2794 if (fmc < 0) { 2795 fmc = 1024; 2796 } 2797 } else { 2798 fc = _bcm_tr3_cosq_min_child_index(node->parent->child, node->level, 0); 2799 fmc = 0; 2800 } 2801 2802 /* If node is scheduler, reset the scheduler and attach it to the parent.*/ 2803 BCM_IF_ERROR_RETURN( 2804 soc_tr3_cosq_set_sched_parent(unit, local_port, node->level, 2805 node->hw_index, node->parent->hw_index)); 2806 2807 /* retriving the strict priority bitmap */ 2808 BCM_IF_ERROR_RETURN(soc_tr3_cosq_get_sched_config(unit, 2809 local_port, 2810 node->parent->level, 2811 node->parent->hw_index, 2812 node->hw_index, 2813 &num_spri, 2814 NULL, 2815 NULL, 2816 &ucmap, 2817 &spmap, 2818 NULL, 2819 &weight)); 2820 2821 /* set the node by default in WRR mode with wt=1 */ 2822 BCM_IF_ERROR_RETURN(soc_tr3_cosq_set_sched_config(unit, 2823 local_port, node->parent->level, 2824 node->parent->hw_index, node->hw_index, 2825 num_spri, fc, fmc, ucmap, spmap, 2826 SOC_TR3_SCHED_MODE_WRR, 1)); 2827 2828 if (node->child) { 2829 child_node = node->child; 2830 while (child_node) { 2831 BCM_IF_ERROR_RETURN(_bcm_tr3_attach_node_in_hw(unit, child_node)); 2832 child_node = child_node->sibling; 2833 } 2834 } 2835 2836 return BCM_E_NONE; 2837 } 2838 2839 /* 2840 * Function: 2841 * _bcm_tr3_cosq_node_resolve 2842 * Purpose: 2843 * Resolve queue number in the specified scheduler tree and its subtree 2844 * Parameters: 2845 * unit - (IN) unit number 2846 * node - (IN) node structure for the specified scheduler node 2847 * cosq - (IN) COS queue to attach to 2848 * Returns: 2849 * BCM_E_XXX 2850 */ 2851 STATIC int 2852 _bcm_tr3_cosq_node_resolve(int unit, _bcm_tr3_cosq_node_t *node, 2853 bcm_cos_queue_t cosq) 2854 { 2855 _bcm_tr3_cosq_node_t *cur_node, *parent; 2856 _bcm_tr3_mmu_info_t *mmu_info; 2857 _bcm_tr3_cosq_list_t *list; 2858 int numq, id, i, ii, prev_base = -1; 2859 bcm_port_t port; 2860 uint64 map, tmp_map; 2861 2862 if ((parent = node->parent) == NULL) { 2863 /* Not attached, should never happen */ 2864 return BCM_E_NOT_FOUND; 2865 } 2866 2867 if (parent->numq == 0 || parent->numq < -1) { 2868 return BCM_E_PARAM; 2869 } 2870 2871 if (parent->numq != -1) { 2872 /* find the current attached_to_input usage */ 2873 COMPILER_64_ZERO(map); 2874 for (cur_node = parent->child; cur_node != NULL; 2875 cur_node = cur_node->sibling) { 2876 if (cur_node->attached_to_input >= 0) { 2877 COMPILER_64_SET(tmp_map, 0, 1); 2878 COMPILER_64_SHL(tmp_map, cur_node->attached_to_input); 2879 COMPILER_64_OR(map, tmp_map); 2880 } 2881 } 2882 2883 if (cosq < 0) { 2884 for (i = 0; i < parent->numq; i++) { 2885 if (!COMPILER_64_BITTEST(map, i)) { 2886 node->attached_to_input = i; 2887 cosq = i; 2888 break; 2889 } 2890 } 2891 if (i == parent->numq) { 2892 return BCM_E_PARAM; 2893 } 2894 } else { 2895 if (COMPILER_64_BITTEST(map, cosq)) { 2896 return BCM_E_EXISTS; 2897 } 2898 node->attached_to_input = cosq; 2899 } 2900 } else if (parent->numq == -1) { 2901 COMPILER_64_ZERO(map); 2902 for (cur_node = parent->child; cur_node != NULL; 2903 cur_node = cur_node->sibling) { 2904 if (cur_node->attached_to_input >= 0) { 2905 COMPILER_64_SET(tmp_map, 0, 1); 2906 COMPILER_64_SHL(tmp_map, cur_node->attached_to_input); 2907 COMPILER_64_OR(map, tmp_map); 2908 } 2909 } 2910 if (cosq >= 0) { 2911 if (COMPILER_64_BITTEST(map, cosq)) { 2912 return BCM_E_EXISTS; 2913 } 2914 } else { 2915 /* Attach anywhere. find first free slot */ 2916 for (ii = 0; ii < 64; ii++) { 2917 if (!COMPILER_64_BITTEST(map, ii)) { 2918 cosq = ii; 2919 break; 2920 } 2921 } 2922 } 2923 node->attached_to_input = cosq; 2924 } 2925 2926 BCM_IF_ERROR_RETURN 2927 (_bcm_tr3_cosq_node_get(unit, node->gport, 0, NULL, &port, NULL, NULL)); 2928 2929 mmu_info = _bcm_tr3_mmu_info[unit]; 2930 numq = (parent->numq == -1) ? 1 : parent->numq; 2931 2932 switch (parent->level) { 2933 case SOC_TR3_NODE_LVL_ROOT: 2934 list = &mmu_info->l0_sched_list; 2935 /* if parent node has queue number which is dynamic, 2936 * free the previos queues, and get the new number of queues. 2937 * NOTE : This attach routine should not be called when live 2938 * traffic, this should be dont in the beginning only. */ 2939 if (parent->numq_expandable && parent->base_index >= 0 && 2940 parent->base_size != parent->numq) { 2941 _bcm_tr3_node_index_clear(list, parent->base_index, 2942 parent->base_size); 2943 prev_base = parent->base_index; 2944 parent->base_index = -1; 2945 } 2946 2947 if ((parent->base_index < 0) || (parent->numq == -1)) { 2948 id = -1; 2949 if (IS_CPU_PORT(unit, node->local_port)) { 2950 BCM_IF_ERROR_RETURN( 2951 _bcm_tr3_node_index_get(list->bits, 0, NUM_COS(unit), 2952 numq, 1, &id)); 2953 } 2954 if (id == -1) { 2955 BCM_IF_ERROR_RETURN( 2956 _bcm_tr3_node_index_get(list->bits, NUM_COS(unit), 2957 _BCM_TR3_NUM_L0_SCHEDULER, numq, 1, &id)); 2958 } 2959 if ((id == -1) && (!IS_CPU_PORT(unit, node->local_port))) { 2960 BCM_IF_ERROR_RETURN( 2961 _bcm_tr3_node_index_get(list->bits, 0, NUM_COS(unit), 2962 numq, 1, &id)); 2963 } 2964 _bcm_tr3_node_index_set(list, id, numq); 2965 if (parent->numq != -1) { 2966 parent->base_index = id; 2967 node->hw_index = parent->base_index + node->attached_to_input; 2968 parent->base_size = numq; 2969 if ((prev_base >= 0) && (prev_base != id)) { 2970 for (cur_node = parent->child; cur_node; 2971 cur_node = cur_node->sibling) { 2972 if (cur_node->attached_to_input >= 0) { 2973 cur_node->hw_index = parent->base_index + 2974 cur_node->attached_to_input; 2975 BCM_IF_ERROR_RETURN(_bcm_tr3_attach_node_in_hw(unit, cur_node)); 2976 } 2977 } 2978 } 2979 } else { 2980 node->hw_index = id; 2981 } 2982 } else { 2983 node->hw_index = parent->base_index + node->attached_to_input; 2984 } 2985 node->hw_cosq = node->hw_index % NUM_COS(unit); 2986 2987 break; 2988 2989 case SOC_TR3_NODE_LVL_L0: 2990 /* Bypass for HSP Ports as hw idx is already assined in gport_add */ 2991 if (IS_TR3_HSP_PORT(unit, node->local_port)) { 2992 break; 2993 } 2994 if ((parent->base_index < 0) || (parent->numq == -1)) { 2995 list = &mmu_info->l1_sched_list; 2996 BCM_IF_ERROR_RETURN(_bcm_tr3_node_index_get(list->bits, 0, 2997 _BCM_TR3_NUM_L1_SCHEDULER, numq, 1, &id)); 2998 _bcm_tr3_node_index_set(list, id, numq); 2999 parent->base_size = numq; 3000 if (parent->numq != -1) { 3001 parent->base_index = id; 3002 node->hw_index = parent->base_index + node->attached_to_input; 3003 } else { 3004 node->hw_index = id; 3005 } 3006 } else { 3007 node->hw_index = parent->base_index + node->attached_to_input; 3008 } 3009 node->hw_cosq = node->hw_index % NUM_COS(unit); 3010 break; 3011 3012 case SOC_TR3_NODE_LVL_L1: 3013 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(node->gport) || 3014 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(node->gport)) { 3015 if (node->type == _BCM_TR3_NODE_VLAN) { 3016 if ((parent->base_index < 0) || (parent->numq == -1)) { 3017 BCM_IF_ERROR_RETURN( 3018 _bcm_tr3_node_index_get(mmu_info->ext_qlist.bits, 3019 mmu_info->num_base_queues, _BCM_TR3_NUM_L2_UC_LEAVES, 3020 numq, 1, &id)); 3021 _bcm_tr3_node_index_set(&mmu_info->ext_qlist, id, numq); 3022 /* Since hardware, require continous queues only if 3023 numq <= 8 */ 3024 if ((parent->numq != -1) && (parent->numq <=8)) { 3025 parent->base_index = id; 3026 node->hw_index = id; 3027 } else { 3028 node->hw_index = id; 3029 } 3030 } else { 3031 /* Since indexes are already reserverved in the first iteration, 3032 just assigning the hardware index */ 3033 if (node->hw_index < 0) { 3034 node->hw_index = parent->base_index + node->attached_to_input; 3035 } 3036 } 3037 node->hw_cosq = node->attached_to_input; 3038 parent->num_child++; 3039 } else if (node->type == _BCM_TR3_NODE_DMVOQ) { 3040 if (mmu_info->num_dmvoq_queues > 0) { 3041 _bcm_tr3_node_index_set(&mmu_info->dmvoq_qlist, 3042 (node->hw_index - mmu_info->base_dmvoq_queue), 1); 3043 if (parent->base_index < 0) { 3044 parent->base_index = node->hw_index; 3045 } 3046 node->hw_cosq = node->attached_to_input; 3047 } else if (parent->base_index < 0) { 3048 BCM_IF_ERROR_RETURN( 3049 _bcm_tr3_node_index_get(mmu_info->ext_qlist.bits, 3050 mmu_info->num_base_queues, _BCM_TR3_NUM_L2_UC_LEAVES, 3051 _TR3_NUM_COS(unit), _TR3_NUM_COS(unit), &id)); 3052 while (id % 8 != 0) { 3053 id = ((id + 8) & 0xfffffff8); 3054 if (id > _BCM_TR3_NUM_L2_UC_LEAVES) { 3055 return BCM_E_RESOURCE; 3056 } 3057 BCM_IF_ERROR_RETURN( 3058 _bcm_tr3_node_index_get(mmu_info->ext_qlist.bits, 3059 id, _BCM_TR3_NUM_L2_UC_LEAVES, 3060 _TR3_NUM_COS(unit), _TR3_NUM_COS(unit), &id)); 3061 } 3062 _bcm_tr3_node_index_set(&mmu_info->ext_qlist, id, _TR3_NUM_COS(unit)); 3063 3064 parent->base_index = node->hw_index = id; 3065 node->hw_cosq = node->attached_to_input; 3066 } else { 3067 node->hw_cosq = node->attached_to_input; 3068 node->hw_index = parent->base_index + 3069 node->attached_to_input; 3070 } 3071 parent->num_child++; 3072 } 3073 } else if (node->hw_index == -1) { 3074 return BCM_E_PARAM; 3075 } 3076 break; 3077 3078 case SOC_TR3_NODE_LVL_L2: 3079 /* passthru */ 3080 default: 3081 return BCM_E_PARAM; 3082 3083 } 3084 3085 BCM_IF_ERROR_RETURN(_bcm_tr3_attach_node_in_hw(unit, node)); 3086 3087 #ifdef DEBUG_TR3_COSQ 3088 LOG_CLI((BSL_META_U(unit, 3089 "Resolved gport: 0x%08x level:%d to hw_index=%d\n"), 3090 node->gport, node->level, node->hw_index)); 3091 #endif 3092 3093 return BCM_E_NONE; 3094 } 3095 3096 /* 3097 * Function: 3098 * _bcm_tr3_cosq_node_unresolve 3099 * Purpose: 3100 * Unresolve queue number in the specified scheduler tree and its subtree 3101 * Parameters: 3102 * unit - (IN) unit number 3103 * node - (IN) node structure for the specified scheduler node 3104 * cosq - (IN) COS queue to attach to 3105 * Returns: 3106 * BCM_E_XXX 3107 */ 3108 STATIC int 3109 _bcm_tr3_cosq_node_unresolve(int unit, _bcm_tr3_cosq_node_t *node, 3110 bcm_cos_queue_t cosq) 3111 { 3112 _bcm_tr3_cosq_node_t *parent; 3113 _bcm_tr3_mmu_info_t *mmu_info; 3114 _bcm_tr3_cosq_list_t *list; 3115 int numq = 1; 3116 int base_index; 3117 3118 if (node->attached_to_input < 0) { 3119 /* Has been unresolved already */ 3120 return BCM_E_NONE; 3121 } 3122 3123 parent = node->parent; 3124 3125 if (!parent) { 3126 return BCM_E_PARAM; 3127 } 3128 3129 mmu_info = _bcm_tr3_mmu_info[unit]; 3130 3131 list = NULL; 3132 base_index = node->hw_index; 3133 3134 switch (parent->level) { 3135 case SOC_TR3_NODE_LVL_ROOT: 3136 list = &mmu_info->l0_sched_list; 3137 break; 3138 3139 case SOC_TR3_NODE_LVL_L0: 3140 list = &mmu_info->l1_sched_list; 3141 break; 3142 3143 case SOC_TR3_NODE_LVL_L1: 3144 if ((node->type == _BCM_TR3_NODE_DMVOQ) && 3145 (mmu_info->num_dmvoq_queues > 0)) { 3146 base_index = node->hw_index - mmu_info->base_dmvoq_queue; 3147 if (base_index < 0) { 3148 return BCM_E_INTERNAL; 3149 } 3150 list = &mmu_info->dmvoq_qlist; 3151 } else if (node->type == _BCM_TR3_NODE_VLAN) { 3152 parent->num_child--; 3153 if ( parent->numq == -1) { 3154 list = &mmu_info->ext_qlist; 3155 } else { 3156 if (parent->num_child == 0) { 3157 base_index = parent->base_index; 3158 parent->base_index = -1; 3159 numq = parent->numq; 3160 list = &mmu_info->ext_qlist; 3161 } 3162 } 3163 } 3164 break; 3165 3166 case SOC_TR3_NODE_LVL_L2: 3167 /* passthru */ 3168 default: 3169 return BCM_E_PARAM; 3170 3171 } 3172 3173 if (list) { 3174 _bcm_tr3_node_index_clear(list, base_index, numq); 3175 } 3176 node->attached_to_input = -1; 3177 3178 return BCM_E_NONE; 3179 } 3180 3181 static int 3182 _bcm_tr3_axp_id_get(int unit, int local_port) 3183 { 3184 int axp_min, axp_max, count, id; 3185 int port, retval = -1; 3186 _bcm_tr3_mmu_info_t *mmu_info; 3187 3188 mmu_info = _bcm_tr3_mmu_info[unit]; 3189 for (port = 0; port < 4; port++) { 3190 if (_tr3_axp_lls_config[port].local_port != local_port) { 3191 continue; 3192 } 3193 count = 0; 3194 while (count < 3) { 3195 axp_min = _tr3_axp_lls_config[port].base[count]; 3196 if (axp_min == -1) { 3197 count++; 3198 continue; 3199 } 3200 axp_max = axp_min + _tr3_axp_lls_config[port].numq[count]; 3201 for (id = axp_min; id < axp_max; id++) { 3202 if ((id > 1024) && 3203 (mmu_info->mc_queue_node[id - 1024].numq == 0)) { 3204 if (retval == -1) { 3205 retval = (id - 1024); 3206 } 3207 } 3208 } 3209 count++; 3210 } 3211 break; 3212 } 3213 return retval; 3214 } 3215 /* 3216 * Function: 3217 * bcm_tr3_cosq_gport_add 3218 * Purpose: 3219 * Create a cosq gport structure 3220 * Parameters: 3221 * unit - (IN) unit number 3222 * port - (IN) port number 3223 * numq - (IN) number of COS queues 3224 * flags - (IN) flags (BCM_COSQ_GPORT_XXX) 3225 * gport - (OUT) GPORT identifier 3226 * Returns: 3227 * BCM_E_XXX 3228 */ 3229 int 3230 bcm_tr3_cosq_gport_add(int unit, bcm_gport_t port, int numq, uint32 flags, 3231 bcm_gport_t *gport, int internal) 3232 { 3233 _bcm_tr3_mmu_info_t *mmu_info; 3234 _bcm_tr3_cosq_node_t *node = NULL; 3235 _bcm_tr3_cosq_port_info_t *port_info; 3236 uint32 sched_encap; 3237 int phy_port, mmu_port, local_port; 3238 int id; 3239 _bcm_tr3_cosq_list_t *list; 3240 int i, index, base_index; 3241 int axp_port_bmp = 0; 3242 int base_axp_port = 0; 3243 3244 LOG_INFO(BSL_LS_BCM_COSQ, 3245 (BSL_META_U(unit, 3246 "bcm_tr3_cosq_gport_add: unit=%d port=0x%x numq=%d flags=0x%x\n"), 3247 unit, port, numq, flags)); 3248 3249 if (gport == NULL) { 3250 return BCM_E_PARAM; 3251 } 3252 3253 if (_bcm_tr3_mmu_info[unit] == NULL) { 3254 return BCM_E_INIT; 3255 } 3256 3257 BCM_IF_ERROR_RETURN 3258 (_bcm_tr3_cosq_localport_resolve(unit, port, &local_port)); 3259 3260 if (local_port < 0) { 3261 return BCM_E_PORT; 3262 } 3263 if (IS_TR3_HSP_PORT(unit, local_port) && (!internal)) { 3264 return BCM_E_PARAM; 3265 } 3266 mmu_info = _bcm_tr3_mmu_info[unit]; 3267 port_info = &mmu_info->port_info[local_port]; 3268 3269 if ((!mmu_info->ets_mode) && (!internal)) { 3270 SOC_IF_ERROR_RETURN(soc_tr3_lls_l2_disable(unit)); 3271 SOC_IF_ERROR_RETURN(soc_tr3_lls_reset(unit)); 3272 /* 3273 * stale bits still be set as the detach is not called 3274 * Reset the complete list. 3275 */ 3276 list = &mmu_info->l0_sched_list; 3277 SOC_IF_ERROR_RETURN( 3278 _bcm_tr3_node_index_clear(list, 0, _BCM_TR3_NUM_L0_SCHEDULER)); 3279 list = &mmu_info->l1_sched_list; 3280 SOC_IF_ERROR_RETURN( 3281 _bcm_tr3_node_index_clear(list, 0, _BCM_TR3_NUM_L1_SCHEDULER)); 3282 SOC_IF_ERROR_RETURN(soc_tr3_lb_lls_init(unit)); 3283 PBMP_ITER(PBMP_AXP_ALL(unit), port) { 3284 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_reserve_gport_resources(unit, port)); 3285 } 3286 PBMP_CE_ITER(unit, port) { 3287 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_reserve_gport_resources(unit, port)); 3288 } 3289 /* 3290 * Reserve the last node as invalid. 3291 */ 3292 for (i = SOC_TR3_NODE_LVL_L1; i <= SOC_TR3_NODE_LVL_L2; i++) { 3293 index = _soc_tr3_invalid_parent_index(unit, i); 3294 if (i == SOC_TR3_NODE_LVL_L1) { 3295 list = &mmu_info->l0_sched_list; 3296 } else if (i == SOC_TR3_NODE_LVL_L2) { 3297 list = &mmu_info->l1_sched_list; 3298 } else { 3299 continue; 3300 } 3301 if (index >= 0) { 3302 _bcm_tr3_node_index_set(list, index, 1); 3303 } 3304 } 3305 mmu_info->ets_mode = 1; 3306 } 3307 3308 if (IS_AXP_PORT(unit, local_port)) { 3309 PBMP_AXP_ITER(unit, base_axp_port) { 3310 break; 3311 } 3312 if (local_port < base_axp_port) { 3313 return BCM_E_INTERNAL; 3314 } 3315 axp_port_bmp = (1 << (local_port - base_axp_port)); 3316 if (!(mmu_info->axp_ets_mode & axp_port_bmp)) { 3317 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_unreserve_gport_resources(unit, local_port)); 3318 SOC_IF_ERROR_RETURN(soc_tr3_lb_lls_port_uninit(unit, local_port)); 3319 mmu_info->axp_ets_mode |= axp_port_bmp; 3320 } 3321 } 3322 3323 if (BCM_PBMP_MEMBER(mmu_info->gport_unavail_pbm, local_port) && 3324 !internal) { 3325 return BCM_E_UNAVAIL; 3326 } 3327 3328 switch (flags) { 3329 case BCM_COSQ_GPORT_UCAST_QUEUE_GROUP: 3330 if (numq != 1) { 3331 return BCM_E_PARAM; 3332 } 3333 3334 if (IS_CPU_PORT(unit, local_port)) { 3335 return BCM_E_PARAM; 3336 } 3337 3338 for (id = port_info->uc_base; id < port_info->uc_limit; id++) { 3339 if (mmu_info->queue_node[id].numq == 0) { 3340 break; 3341 } 3342 } 3343 3344 /* allocating more then num-cos uc queues */ 3345 if (id == port_info->uc_limit) { 3346 if (mmu_info->num_dmvoq_queues > 0) { 3347 base_index = mmu_info->base_dmvoq_queue + 3348 mmu_info->num_dmvoq_queues; 3349 } else { 3350 base_index = mmu_info->num_base_queues; 3351 } 3352 for (id = base_index; 3353 id < _BCM_TR3_NUM_L2_UC_LEAVES; id++) { 3354 if (mmu_info->queue_node[id].numq == 0) { 3355 break; 3356 } 3357 } 3358 } 3359 3360 if (id == _BCM_TR3_NUM_L2_UC_LEAVES) { 3361 return BCM_E_RESOURCE; 3362 } 3363 3364 BCM_GPORT_UCAST_QUEUE_GROUP_SYSQID_SET(*gport, local_port, id); 3365 node = &mmu_info->queue_node[id]; 3366 node->gport = *gport; 3367 node->numq = numq; 3368 node->level = SOC_TR3_NODE_LVL_L2; 3369 node->hw_cosq = id - port_info->uc_base; 3370 node->hw_index = soc_tr3_l2_hw_index(unit, id, 1); 3371 node->local_port = local_port; 3372 node->remote_modid = -1; 3373 node->remote_port = -1; 3374 node->type = _BCM_TR3_NODE_UCAST; 3375 node->in_use = TRUE; 3376 break; 3377 3378 case BCM_COSQ_GPORT_VLAN_UCAST_QUEUE_GROUP: 3379 /* Service Queueing are outside default queues. Hence NO alignment 3380 * required. 3381 */ 3382 if (numq != 1) { 3383 return BCM_E_PARAM; 3384 } 3385 for (id = mmu_info->num_base_queues; 3386 id < _BCM_TR3_NUM_L2_UC_LEAVES; id++) { 3387 if (mmu_info->queue_node[id].numq == 0) { 3388 break; 3389 } 3390 } 3391 3392 if (id >= _BCM_TR3_NUM_L2_UC_LEAVES) { 3393 return BCM_E_RESOURCE; 3394 } 3395 3396 BCM_GPORT_UCAST_QUEUE_GROUP_SYSQID_SET(*gport, local_port, id); 3397 node = &mmu_info->queue_node[id]; 3398 node->gport = *gport; 3399 node->numq = numq ; 3400 node->level = SOC_TR3_NODE_LVL_L2; 3401 node->hw_index = -1; 3402 node->local_port = local_port; 3403 node->remote_modid = -1; 3404 node->remote_port = -1; 3405 node->type = _BCM_TR3_NODE_VLAN; 3406 node->in_use = TRUE; 3407 break; 3408 3409 case BCM_COSQ_GPORT_DESTMOD_UCAST_QUEUE_GROUP: 3410 if (numq != 1) { 3411 return BCM_E_PARAM; 3412 } 3413 3414 if (!IS_HG_PORT(unit, local_port)) { 3415 return BCM_E_PORT; 3416 } 3417 3418 if (mmu_info->num_dmvoq_queues > 0) { 3419 return BCM_E_PARAM; 3420 } 3421 3422 for (id = mmu_info->num_base_queues; 3423 id < _BCM_TR3_NUM_L2_UC_LEAVES; id++) { 3424 if (mmu_info->queue_node[id].numq == 0) { 3425 break; 3426 } 3427 } 3428 3429 if (id >= _BCM_TR3_NUM_L2_UC_LEAVES) { 3430 return BCM_E_RESOURCE; 3431 } 3432 3433 BCM_GPORT_UCAST_QUEUE_GROUP_SYSQID_SET(*gport, local_port, id); 3434 node = &mmu_info->queue_node[id]; 3435 node->gport = *gport; 3436 node->numq = 1; 3437 node->level = SOC_TR3_NODE_LVL_L2; 3438 node->hw_index = -1; 3439 /* by default assign the cosq on order of order of alocation, 3440 * can be overriddedn by cos_mapping_set */ 3441 node->hw_cosq = -1; 3442 node->local_port = local_port; 3443 node->remote_modid = -1; 3444 node->remote_port = -1; 3445 node->in_use = TRUE; 3446 node->type = _BCM_TR3_NODE_DMVOQ; 3447 break; 3448 3449 case (BCM_COSQ_GPORT_WITH_ID | BCM_COSQ_GPORT_DESTMOD_UCAST_QUEUE_GROUP): 3450 if (numq != 1) { 3451 return BCM_E_PARAM; 3452 } 3453 3454 if (!IS_HG_PORT(unit, local_port)) { 3455 return BCM_E_PORT; 3456 } 3457 3458 id = BCM_GPORT_DESTMOD_QUEUE_GROUP_QID_GET(*gport); 3459 if ((id >= mmu_info->num_dmvoq_queues) || 3460 (mmu_info->num_dmvoq_queues == 0)) { 3461 return BCM_E_PARAM; 3462 } 3463 node = &mmu_info->queue_node[id + mmu_info->base_dmvoq_queue]; 3464 3465 node->gport = *gport; 3466 node->numq = 1; 3467 node->level = SOC_TR3_NODE_LVL_L2; 3468 node->hw_index = mmu_info->base_dmvoq_queue + id; 3469 node->hw_cosq = -1; 3470 node->local_port = local_port; 3471 node->remote_modid = -1; 3472 node->remote_port = -1; 3473 node->in_use = TRUE; 3474 node->type = _BCM_TR3_NODE_DMVOQ; 3475 break; 3476 3477 case BCM_COSQ_GPORT_MCAST_QUEUE_GROUP: 3478 if (numq != 1) { 3479 return BCM_E_PARAM; 3480 } 3481 id = -1; 3482 if (IS_AXP_PORT(unit, local_port)) { 3483 id = _bcm_tr3_axp_id_get(unit, local_port); 3484 } 3485 3486 if (id == -1) { 3487 for (id = port_info->mc_base; id < port_info->mc_limit; id++) { 3488 if (mmu_info->mc_queue_node[id].numq == 0) { 3489 break; 3490 } 3491 } 3492 if (id == port_info->mc_limit) { 3493 return BCM_E_RESOURCE; 3494 } 3495 } 3496 3497 /* set index bits */ 3498 BCM_GPORT_MCAST_QUEUE_GROUP_SYSQID_SET(*gport, local_port, id); 3499 node = &mmu_info->mc_queue_node[id]; 3500 node->gport = *gport; 3501 node->numq = numq; 3502 node->level = SOC_TR3_NODE_LVL_L2; 3503 node->hw_cosq = id - port_info->mc_base; 3504 node->hw_index = soc_tr3_l2_hw_index(unit, id, 0); 3505 node->local_port = local_port; 3506 node->remote_modid = -1; 3507 node->remote_port = -1; 3508 node->type = _BCM_TR3_NODE_MCAST; 3509 node->in_use = TRUE; 3510 break; 3511 3512 case BCM_COSQ_GPORT_SCHEDULER: 3513 /* passthru */ 3514 case BCM_COSQ_GPORT_WITH_ID: 3515 case 0: 3516 if (numq < -1) { 3517 return BCM_E_PARAM; 3518 } 3519 3520 if (( flags & BCM_COSQ_GPORT_WITH_ID) || (flags == 0)) { 3521 /* this is a port level scheduler */ 3522 id = local_port; 3523 3524 if ( id < 0 || id >= _BCM_TR3_NUM_PORT_SCHEDULERS) { 3525 return BCM_E_PARAM; 3526 } 3527 3528 node = &mmu_info->sched_node[id]; 3529 sched_encap = (id << 8) | local_port; 3530 BCM_GPORT_SCHEDULER_SET(*gport, sched_encap); 3531 node->gport = *gport; 3532 node->level = SOC_TR3_NODE_LVL_ROOT; 3533 phy_port = SOC_INFO(unit).port_l2p_mapping[local_port]; 3534 mmu_port = SOC_INFO(unit).port_p2m_mapping[phy_port]; 3535 node->hw_index = mmu_port; 3536 node->local_port = local_port; 3537 node->numq = numq; 3538 node->in_use = TRUE; 3539 node->type = _BCM_TR3_NODE_SCHEDULER; 3540 node->attached_to_input = 0; 3541 } else { 3542 for (id = _BCM_TR3_NUM_PORT_SCHEDULERS; 3543 id < _BCM_TR3_NUM_TOTAL_SCHEDULERS; id++) { 3544 if (mmu_info->sched_node[id].in_use == FALSE) { 3545 node = &mmu_info->sched_node[id]; 3546 node->in_use = TRUE; 3547 break; 3548 } 3549 } 3550 if (!node) { 3551 return BCM_E_RESOURCE; 3552 } 3553 3554 node = &mmu_info->sched_node[id]; 3555 sched_encap = (id << 8) | local_port; 3556 BCM_GPORT_SCHEDULER_SET(*gport, sched_encap); 3557 node->gport = *gport; 3558 node->numq = numq; 3559 node->local_port = local_port; 3560 node->type = _BCM_TR3_NODE_SCHEDULER; 3561 node->attached_to_input = -1; 3562 } 3563 break; 3564 3565 default: 3566 return BCM_E_PARAM; 3567 } 3568 3569 LOG_INFO(BSL_LS_BCM_COSQ, 3570 (BSL_META_U(unit, 3571 " gport=0x%x\n"), 3572 *gport)); 3573 3574 return BCM_E_NONE; 3575 } 3576 3577 int 3578 _bcm_tr3_cosq_gport_node_disable(int unit, _bcm_tr3_cosq_node_t *node, 3579 uint32 disable) 3580 { 3581 int hw_index, disable_q = 0; 3582 uint32 entry[SOC_MAX_MEM_WORDS]; 3583 3584 if (!node) { 3585 return BCM_E_PARAM; 3586 } 3587 if ((node->level != SOC_TR3_NODE_LVL_L2) || 3588 BCM_GPORT_IS_MCAST_QUEUE_GROUP(node->gport)) { 3589 return BCM_E_PARAM; 3590 } 3591 if (node->hw_index < 0) { 3592 return BCM_E_PARAM; 3593 } 3594 3595 hw_index = node->hw_index; 3596 3597 BCM_IF_ERROR_RETURN(soc_mem_read(unit, MMU_THDO_Q_TO_QGRP_MAPm, 3598 MEM_BLOCK_ANY, hw_index, &entry)); 3599 disable_q = soc_mem_field32_get(unit, MMU_THDO_Q_TO_QGRP_MAPm, 3600 entry, DISABLE_QUEUINGf); 3601 if (disable) { 3602 if (!disable_q) { 3603 soc_mem_field32_set(unit, MMU_THDO_Q_TO_QGRP_MAPm, entry, 3604 DISABLE_QUEUINGf, 1); 3605 BCM_IF_ERROR_RETURN( 3606 soc_mem_write(unit, MMU_THDO_Q_TO_QGRP_MAPm, 3607 MEM_BLOCK_ALL, hw_index, entry)); 3608 } 3609 } else { 3610 if (disable_q) { 3611 soc_mem_field32_set(unit, MMU_THDO_Q_TO_QGRP_MAPm, entry, 3612 DISABLE_QUEUINGf, 0); 3613 BCM_IF_ERROR_RETURN( 3614 soc_mem_write(unit, MMU_THDO_Q_TO_QGRP_MAPm, 3615 MEM_BLOCK_ALL, hw_index, entry)); 3616 } 3617 } 3618 return BCM_E_NONE; 3619 } 3620 3621 int 3622 _bcm_tr3_cosq_gport_mcastq_disable(int unit, _bcm_tr3_cosq_node_t *sched_node, 3623 _bcm_tr3_gport_q_disable_t *mcastq) 3624 { 3625 uint32 rval; 3626 3627 if (!BCM_GPORT_IS_MCAST_QUEUE_GROUP(sched_node->gport)) { 3628 return BCM_E_PARAM; 3629 } 3630 3631 if (mcastq == NULL) { 3632 return BCM_E_PARAM; 3633 } 3634 3635 BCM_IF_ERROR_RETURN(soc_reg32_get(unit, OP_QUEUE_CONFIG_CELLr, 3636 sched_node->local_port, sched_node->hw_cosq, &rval)); 3637 mcastq->shared_limit = soc_reg_field_get(unit, OP_QUEUE_CONFIG_CELLr, 3638 rval, Q_SHARED_LIMIT_CELLf); 3639 mcastq->min_limit = soc_reg_field_get(unit, OP_QUEUE_CONFIG_CELLr, 3640 rval, Q_MIN_CELLf); 3641 3642 soc_reg_field_set(unit, OP_QUEUE_CONFIG_CELLr, &rval, Q_SHARED_LIMIT_CELLf, 0); 3643 soc_reg_field_set(unit, OP_QUEUE_CONFIG_CELLr, &rval, Q_MIN_CELLf, 0); 3644 3645 BCM_IF_ERROR_RETURN(soc_reg32_set(unit, OP_QUEUE_CONFIG_CELLr, 3646 sched_node->local_port, sched_node->hw_cosq, rval)); 3647 3648 BCM_IF_ERROR_RETURN(soc_reg32_get(unit, OP_QUEUE_CONFIG1_CELLr, 3649 sched_node->local_port, sched_node->hw_cosq, &rval)); 3650 mcastq->enable = soc_reg_field_get(unit, OP_QUEUE_CONFIG1_CELLr, 3651 rval, Q_LIMIT_ENABLE_CELLf); 3652 mcastq->q_limit_dynamic = soc_reg_field_get(unit, OP_QUEUE_CONFIG1_CELLr, 3653 rval, Q_LIMIT_DYNAMIC_CELLf); 3654 soc_reg_field_set(unit, OP_QUEUE_CONFIG1_CELLr, &rval, Q_LIMIT_ENABLE_CELLf, 1); 3655 soc_reg_field_set(unit, OP_QUEUE_CONFIG1_CELLr, &rval, Q_LIMIT_DYNAMIC_CELLf, 0); 3656 3657 BCM_IF_ERROR_RETURN(soc_reg32_set(unit, OP_QUEUE_CONFIG1_CELLr, 3658 sched_node->local_port, sched_node->hw_cosq, rval)); 3659 3660 return BCM_E_NONE; 3661 } 3662 3663 int _bcm_tr3_cosq_gport_mcastq_enable(int unit, _bcm_tr3_cosq_node_t *sched_node, 3664 _bcm_tr3_gport_q_disable_t *mcastq) 3665 { 3666 uint32 rval; 3667 if (!BCM_GPORT_IS_MCAST_QUEUE_GROUP(sched_node->gport)) { 3668 return BCM_E_PARAM; 3669 } 3670 3671 if (mcastq == NULL) { 3672 return BCM_E_PARAM; 3673 } 3674 3675 BCM_IF_ERROR_RETURN(soc_reg32_get(unit, OP_QUEUE_CONFIG_CELLr, 3676 sched_node->local_port, sched_node->hw_cosq, &rval)); 3677 3678 soc_reg_field_set(unit, OP_QUEUE_CONFIG_CELLr, &rval, Q_SHARED_LIMIT_CELLf, mcastq->shared_limit); 3679 soc_reg_field_set(unit, OP_QUEUE_CONFIG_CELLr, &rval, Q_MIN_CELLf, mcastq->min_limit); 3680 3681 BCM_IF_ERROR_RETURN(soc_reg32_set(unit, OP_QUEUE_CONFIG_CELLr, 3682 sched_node->local_port, sched_node->hw_cosq, rval)); 3683 3684 BCM_IF_ERROR_RETURN(soc_reg32_get(unit, OP_QUEUE_CONFIG1_CELLr, 3685 sched_node->local_port, sched_node->hw_cosq, &rval)); 3686 3687 soc_reg_field_set(unit, OP_QUEUE_CONFIG1_CELLr, &rval, Q_LIMIT_ENABLE_CELLf, mcastq->enable); 3688 soc_reg_field_set(unit, OP_QUEUE_CONFIG1_CELLr, &rval, Q_LIMIT_DYNAMIC_CELLf, mcastq->q_limit_dynamic); 3689 BCM_IF_ERROR_RETURN(soc_reg32_set(unit, OP_QUEUE_CONFIG1_CELLr, 3690 sched_node->local_port, sched_node->hw_cosq, rval)); 3691 3692 return BCM_E_NONE; 3693 } 3694 /* 3695 * Function: 3696 * bcm_tr3_cosq_gport_detach 3697 * Purpose: 3698 * Detach sched_port from the specified index (cosq) of input_port 3699 * Parameters: 3700 * unit - (IN) unit number 3701 * sched_port - (IN) scheduler GPORT identifier 3702 * input_port - (IN) GPORT to detach from 3703 * cosq - (IN) COS queue to detach from 3704 * Returns: 3705 * BCM_E_XXX 3706 */ 3707 int 3708 bcm_tr3_cosq_gport_detach(int unit, bcm_gport_t sched_gport, 3709 bcm_gport_t input_gport, bcm_cos_queue_t cosq) 3710 { 3711 _bcm_tr3_cosq_node_t *sched_node, *input_node = NULL, *prev_node, *parent; 3712 bcm_port_t sched_port, input_port; 3713 _bcm_tr3_mmu_info_t *mmu_info; 3714 _bcm_tr3_cosq_list_t *list; 3715 _bcm_tr3_gport_q_disable_t mcastq; 3716 3717 if ((mmu_info = _bcm_tr3_mmu_info[unit]) == NULL) { 3718 return BCM_E_INIT; 3719 } 3720 3721 if ((BCM_GPORT_IS_UCAST_QUEUE_GROUP(input_gport)) || 3722 (BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(input_gport)) || 3723 (BCM_GPORT_IS_MCAST_QUEUE_GROUP(input_gport))) { 3724 return BCM_E_PARAM; 3725 } 3726 3727 BCM_IF_ERROR_RETURN 3728 (_bcm_tr3_cosq_node_get(unit, sched_gport, 0, NULL, &sched_port, NULL, 3729 &sched_node)); 3730 3731 if (sched_node->attached_to_input < 0) { 3732 /* Not attached yet */ 3733 return BCM_E_PORT; 3734 } 3735 3736 if (input_gport != BCM_GPORT_INVALID) { 3737 if (BCM_GPORT_IS_SCHEDULER(input_gport) || 3738 BCM_GPORT_IS_MODPORT(input_gport) || 3739 BCM_GPORT_IS_LOCAL(input_gport)) { 3740 BCM_IF_ERROR_RETURN 3741 (_bcm_tr3_cosq_node_get(unit, input_gport, 0, NULL, 3742 &input_port, NULL, &input_node)); 3743 } else { 3744 if (!(BCM_GPORT_IS_SCHEDULER(sched_gport) || 3745 BCM_GPORT_IS_UCAST_QUEUE_GROUP(sched_gport) || 3746 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(sched_gport) || 3747 BCM_GPORT_IS_MCAST_QUEUE_GROUP(sched_gport))) { 3748 return BCM_E_PARAM; 3749 } 3750 else { 3751 BCM_IF_ERROR_RETURN 3752 (_bcm_tr3_cosq_localport_resolve(unit, input_gport, 3753 &input_port)); 3754 input_node = NULL; 3755 } 3756 } 3757 } 3758 3759 if (sched_port != input_port) { 3760 return BCM_E_PORT; 3761 } 3762 3763 if (sched_node->parent != input_node) { 3764 return BCM_E_PORT; 3765 } 3766 3767 if ((cosq < -1) || 3768 (input_node && (input_node->numq != -1) && (cosq >= input_node->numq))) { 3769 return BCM_E_PARAM; 3770 } 3771 3772 if (cosq != -1) { 3773 if (sched_node->attached_to_input != cosq) { 3774 return BCM_E_PARAM; 3775 } 3776 } 3777 3778 if (sched_node->parent == NULL) { 3779 return BCM_E_PARAM; 3780 } 3781 3782 if((sched_node->level == SOC_TR3_NODE_LVL_L2) && 3783 BCM_GPORT_IS_MCAST_QUEUE_GROUP(sched_node->gport)) { 3784 memset(&mcastq, 0, sizeof(_bcm_tr3_gport_q_disable_t)); 3785 if (!IS_AXP_PORT(unit, sched_port) || 3786 ((sched_node->hw_cosq >= 0) && (sched_node->hw_cosq < 8))) { 3787 BCM_IF_ERROR_RETURN( 3788 _bcm_tr3_cosq_gport_mcastq_disable(unit, sched_node, &mcastq)); 3789 } 3790 } 3791 3792 if (soc_property_get(unit, spn_BCM5664X_WRR_GRANULARITY_1, 0)) { 3793 BCM_IF_ERROR_RETURN( 3794 _bcm_tr3_cosq_sched_set(unit, sched_node->parent->gport, 3795 sched_node->attached_to_input, 3796 BCM_COSQ_WEIGHTED_ROUND_ROBIN, 2, 0)); 3797 } else { 3798 BCM_IF_ERROR_RETURN( 3799 _bcm_tr3_cosq_sched_set(unit, sched_node->parent->gport, 3800 sched_node->attached_to_input, 3801 BCM_COSQ_WEIGHTED_ROUND_ROBIN, 1, 0)); 3802 } 3803 3804 BCM_IF_ERROR_RETURN( 3805 soc_tr3_cosq_set_sched_parent(unit, input_port, 3806 sched_node->level, sched_node->hw_index, 3807 _soc_tr3_invalid_parent_index(unit, sched_node->level))); 3808 3809 if ((sched_node->level == SOC_TR3_NODE_LVL_L2) && 3810 !BCM_GPORT_IS_MCAST_QUEUE_GROUP(sched_node->gport)) { 3811 _bcm_tr3_cosq_gport_node_disable(unit, sched_node, 1); 3812 } 3813 3814 /* unresolve the node - delete this node from parent's child list */ 3815 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_node_unresolve(unit, sched_node, cosq)); 3816 3817 if((sched_node->level == SOC_TR3_NODE_LVL_L2) && 3818 BCM_GPORT_IS_MCAST_QUEUE_GROUP(sched_node->gport)) { 3819 if (!IS_AXP_PORT(unit, sched_port) || 3820 ((sched_node->hw_cosq >= 0) && (sched_node->hw_cosq < 8))) { 3821 BCM_IF_ERROR_RETURN( 3822 _bcm_tr3_cosq_gport_mcastq_enable(unit, sched_node, &mcastq)); 3823 } 3824 } 3825 3826 /* now remove from the sw tree */ 3827 if (sched_node->parent != NULL) { 3828 parent = sched_node->parent; 3829 if (sched_node->parent->child == sched_node) { 3830 sched_node->parent->child = sched_node->sibling; 3831 } else { 3832 prev_node = sched_node->parent->child; 3833 while (prev_node != NULL && prev_node->sibling != sched_node) { 3834 prev_node = prev_node->sibling; 3835 } 3836 if (prev_node == NULL) { 3837 return BCM_E_INTERNAL; 3838 } 3839 prev_node->sibling = sched_node->sibling; 3840 } 3841 sched_node->parent = NULL; 3842 sched_node->sibling = NULL; 3843 sched_node->attached_to_input = -1; 3844 3845 if (parent->child == NULL) { 3846 list = NULL; 3847 switch (parent->level) { 3848 case SOC_TR3_NODE_LVL_ROOT: 3849 list = &mmu_info->l0_sched_list; 3850 break; 3851 case SOC_TR3_NODE_LVL_L0: 3852 list = &mmu_info->l1_sched_list; 3853 break; 3854 case SOC_TR3_NODE_LVL_L1: 3855 if ((sched_node->type == _BCM_TR3_NODE_DMVOQ) && 3856 (mmu_info->num_dmvoq_queues > 0)) { 3857 list = &mmu_info->dmvoq_qlist; 3858 } else { 3859 list = &mmu_info->ext_qlist; 3860 } 3861 default: 3862 break; 3863 } 3864 if (list) { 3865 BCM_IF_ERROR_RETURN(_bcm_tr3_node_index_clear(list, 3866 parent->base_index, parent->base_size)); 3867 parent->base_index = -1; 3868 parent->base_size = 0; 3869 } 3870 } 3871 } 3872 3873 LOG_INFO(BSL_LS_BCM_COSQ, 3874 (BSL_META_U(unit, 3875 " hw_cosq=%d\n"), 3876 sched_node->attached_to_input)); 3877 3878 return BCM_E_NONE; 3879 } 3880 3881 /* 3882 * Function: 3883 * _bcm_tr3_cosq_gport_delete 3884 * Purpose: 3885 * Destroy a cosq gport structure 3886 * Parameters: 3887 * unit - (IN) unit number 3888 * gport - (IN) GPORT identifier 3889 * sibling_delete - (IN) if it is zero then don't delete sibling 3890 * Returns: 3891 * BCM_E_XXX 3892 */ 3893 STATIC int 3894 _bcm_tr3_cosq_gport_delete(int unit, bcm_gport_t gport, int sibling_delete) 3895 { 3896 _bcm_tr3_cosq_node_t *node = NULL, *tnode, *base_node = NULL; 3897 int local_port; 3898 soc_info_t *si; 3899 _bcm_tr3_mmu_info_t *mmu_info; 3900 int phy_port, mmu_port, ii; 3901 3902 LOG_INFO(BSL_LS_BCM_COSQ, 3903 (BSL_META_U(unit, 3904 "_bcm_tr3_cosq_gport_delete: unit=%d gport=0x%x\n"), 3905 unit, gport)); 3906 3907 si = &SOC_INFO(unit); 3908 3909 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 3910 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport) || 3911 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) || 3912 BCM_GPORT_IS_SCHEDULER(gport)) { 3913 BCM_IF_ERROR_RETURN 3914 (_bcm_tr3_cosq_node_get(unit, gport, 0, NULL, &local_port, NULL, &node)); 3915 } else { 3916 local_port = (BCM_GPORT_IS_LOCAL(gport)) ? 3917 BCM_GPORT_LOCAL_GET(gport) : BCM_GPORT_MODPORT_PORT_GET(gport); 3918 3919 if (!SOC_PORT_VALID(unit, local_port)) { 3920 return BCM_E_PORT; 3921 } 3922 3923 mmu_info = _bcm_tr3_mmu_info[unit]; 3924 phy_port = si->port_l2p_mapping[local_port]; 3925 mmu_port = si->port_p2m_mapping[phy_port]; 3926 3927 for (ii = 0; ii < _BCM_TR3_NUM_PORT_SCHEDULERS; ii++) { 3928 tnode = &mmu_info->sched_node[ii]; 3929 if (tnode->in_use == FALSE) { 3930 continue; 3931 } 3932 if ((tnode->level == SOC_TR3_NODE_LVL_ROOT) && 3933 (tnode->hw_index == mmu_port)) { 3934 node = tnode; 3935 break; 3936 } 3937 } 3938 if (node == NULL) { 3939 return BCM_E_NONE; 3940 } 3941 } 3942 if (IS_TR3_HSP_PORT(unit, local_port)) { 3943 return BCM_E_PARAM; 3944 } 3945 if (node->child != NULL) { 3946 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_gport_delete(unit, node->child->gport, 1)); 3947 } 3948 3949 if ((node->sibling != NULL) && sibling_delete) { 3950 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_gport_delete(unit, node->sibling->gport, 1)); 3951 } 3952 3953 if (node->level != SOC_TR3_NODE_LVL_ROOT && node->attached_to_input >= 0) { 3954 BCM_IF_ERROR_RETURN 3955 (bcm_tr3_cosq_gport_detach(unit, node->gport, 3956 node->parent->gport, node->attached_to_input)); 3957 } 3958 3959 if ((node->type == _BCM_TR3_NODE_DMVOQ) && 3960 (node->remote_modid > 0)) { 3961 _bcm_tr3_voq_next_base_node_get (unit, local_port, 3962 node->remote_modid, &base_node); 3963 if (base_node != NULL) { 3964 BCM_PBMP_ASSIGN(base_node->fabric_pbmp, 3965 node->fabric_pbmp); 3966 } 3967 } 3968 3969 _BCM_TR3_COSQ_NODE_INIT(node); 3970 return BCM_E_NONE; 3971 } 3972 3973 /* 3974 * Function: 3975 * bcm_tr3_cosq_gport_delete 3976 * Purpose: 3977 * Destroy a cosq gport structure 3978 * Parameters: 3979 * unit - (IN) unit number 3980 * gport - (IN) GPORT identifier 3981 * Returns: 3982 * BCM_E_XXX 3983 */ 3984 int 3985 bcm_tr3_cosq_gport_delete(int unit, bcm_gport_t gport) 3986 { 3987 return _bcm_tr3_cosq_gport_delete(unit, gport, 0); 3988 } 3989 3990 /* 3991 * Function: 3992 * bcm_tr3_cosq_gport_get 3993 * Purpose: 3994 * Get a cosq gport structure 3995 * Parameters: 3996 * unit - (IN) unit number 3997 * gport - (IN) GPORT identifier 3998 * port - (OUT) port number 3999 * numq - (OUT) number of COS queues 4000 * flags - (OUT) flags (BCM_COSQ_GPORT_XXX) 4001 * Returns: 4002 * BCM_E_XXX 4003 */ 4004 int 4005 bcm_tr3_cosq_gport_get(int unit, bcm_gport_t gport, bcm_gport_t *port, 4006 int *numq, uint32 *flags) 4007 { 4008 _bcm_tr3_mmu_info_t *mmu_info; 4009 _bcm_tr3_cosq_node_t *node; 4010 bcm_module_t modid; 4011 bcm_port_t local_port; 4012 int id; 4013 _bcm_gport_dest_t dest; 4014 4015 if ((mmu_info = _bcm_tr3_mmu_info[unit]) == NULL) { 4016 return BCM_E_INIT; 4017 } 4018 4019 if (port == NULL || numq == NULL || flags == NULL) { 4020 return BCM_E_PARAM; 4021 } 4022 4023 LOG_INFO(BSL_LS_BCM_COSQ, 4024 (BSL_META_U(unit, 4025 "bcm_tr3_cosq_gport_get: unit=%d gport=0x%x\n"), 4026 unit, gport)); 4027 4028 BCM_IF_ERROR_RETURN 4029 (_bcm_tr3_cosq_node_get(unit, gport, 0, NULL, &local_port, &id, &node)); 4030 4031 if (SOC_USE_GPORT(unit)) { 4032 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid)); 4033 dest.gport_type = _SHR_GPORT_TYPE_MODPORT; 4034 dest.modid = modid; 4035 dest.port = local_port; 4036 BCM_IF_ERROR_RETURN(_bcm_esw_gport_construct(unit, &dest, port)); 4037 } else { 4038 *port = local_port; 4039 } 4040 4041 *numq = node->numq; 4042 4043 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 4044 id = BCM_GPORT_UCAST_QUEUE_GROUP_QID_GET(gport); 4045 if (_BCM_TR3_IS_UC_QUEUE(mmu_info, id)) { 4046 *flags = BCM_COSQ_GPORT_UCAST_QUEUE_GROUP; 4047 } else if (node->type == _BCM_TR3_NODE_DMVOQ) { 4048 *flags = BCM_COSQ_GPORT_DESTMOD_UCAST_QUEUE_GROUP; 4049 } else if (node->type == _BCM_TR3_NODE_VLAN) { 4050 *flags = BCM_COSQ_GPORT_VLAN_UCAST_QUEUE_GROUP; 4051 } 4052 } else if (BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) { 4053 *flags = BCM_COSQ_GPORT_DESTMOD_UCAST_QUEUE_GROUP; 4054 } else if (BCM_GPORT_IS_SCHEDULER(gport)) { 4055 *flags = BCM_COSQ_GPORT_SCHEDULER; 4056 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 4057 *flags = BCM_COSQ_GPORT_MCAST_QUEUE_GROUP; 4058 } else { 4059 *flags = 0; 4060 } 4061 4062 LOG_INFO(BSL_LS_BCM_COSQ, 4063 (BSL_META_U(unit, 4064 " port=0x%x numq=%d flags=0x%x\n"), 4065 *port, *numq, *flags)); 4066 4067 return BCM_E_NONE; 4068 } 4069 4070 /* 4071 * Function: 4072 * bcm_tr3_cosq_gport_traverse 4073 * Purpose: 4074 * Walks through the valid COSQ GPORTs and calls 4075 * the user supplied callback function for each entry. 4076 * Parameters: 4077 * unit - (IN) unit number 4078 * trav_fn - (IN) Callback function. 4079 * user_data - (IN) User data to be passed to callback function 4080 * Returns: 4081 * BCM_E_NONE - Success. 4082 * BCM_E_XXX 4083 */ 4084 int 4085 bcm_tr3_cosq_gport_traverse(int unit, bcm_cosq_gport_traverse_cb cb, 4086 void *user_data) 4087 { 4088 _bcm_tr3_cosq_node_t *port_info; 4089 _bcm_tr3_mmu_info_t *mmu_info; 4090 bcm_module_t my_modid, modid_out; 4091 bcm_port_t port, port_out; 4092 4093 if (_bcm_tr3_mmu_info[unit] == NULL) { 4094 return BCM_E_INIT; 4095 } 4096 mmu_info = _bcm_tr3_mmu_info[unit]; 4097 4098 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_modid)); 4099 PBMP_ALL_ITER(unit, port) { 4100 BCM_IF_ERROR_RETURN 4101 (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, 4102 my_modid, port, &modid_out, &port_out)); 4103 4104 /* root node */ 4105 port_info = &mmu_info->sched_node[port_out]; 4106 4107 if (port_info->gport >= 0) { 4108 _bcm_tr3_cosq_gport_traverse(unit, port_info->gport, cb, user_data); 4109 } 4110 } 4111 4112 return BCM_E_NONE; 4113 } 4114 4115 /* 4116 * Function: 4117 * bcm_tr3_cosq_gport_attach 4118 * Purpose: 4119 * Attach sched_port to the specified index (cosq) of input_port 4120 * Parameters: 4121 * unit - (IN) unit number 4122 * sched_port - (IN) scheduler GPORT identifier 4123 * input_port - (IN) GPORT to attach to 4124 * cosq - (IN) COS queue to attach to (-1 for first available cosq) 4125 * Returns: 4126 * BCM_E_XXX 4127 */ 4128 int 4129 bcm_tr3_cosq_gport_attach(int unit, bcm_gport_t gport, 4130 bcm_gport_t to_gport, 4131 bcm_cos_queue_t to_cosq) 4132 { 4133 _bcm_tr3_mmu_info_t *mmu_info; 4134 _bcm_tr3_cosq_node_t *node, *to_node; 4135 bcm_port_t port, to_port, local_port = -1; 4136 int rv; 4137 4138 if ((mmu_info = _bcm_tr3_mmu_info[unit]) == NULL) { 4139 return BCM_E_INIT; 4140 } 4141 4142 if ((BCM_GPORT_IS_UCAST_QUEUE_GROUP(to_gport)) || 4143 (BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(to_gport)) || 4144 (BCM_GPORT_IS_MCAST_QUEUE_GROUP(to_gport)) || 4145 (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(to_gport))) { 4146 return BCM_E_PARAM; 4147 } 4148 4149 if(!(BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 4150 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) || 4151 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport) || 4152 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport) || 4153 BCM_GPORT_IS_SCHEDULER(gport))) { 4154 return BCM_E_PORT; 4155 } 4156 4157 if (to_cosq >= 64) { 4158 return BCM_E_RESOURCE; 4159 } 4160 4161 BCM_IF_ERROR_RETURN 4162 (_bcm_tr3_cosq_node_get(unit, gport, 0, NULL, &port, NULL, &node)); 4163 4164 if (node->attached_to_input >= 0) { 4165 /* Has already attached */ 4166 return BCM_E_EXISTS; 4167 } 4168 4169 if (BCM_GPORT_IS_SCHEDULER(to_gport)) { 4170 BCM_IF_ERROR_RETURN 4171 (_bcm_tr3_cosq_node_get(unit, to_gport, 0, NULL, &to_port, NULL, 4172 &to_node)); 4173 } else { 4174 BCM_IF_ERROR_RETURN 4175 (_bcm_tr3_cosq_localport_resolve(unit, to_gport, &to_port)); 4176 to_node = &mmu_info->sched_node[to_port]; 4177 } 4178 4179 if (port != to_port) { 4180 return BCM_E_PORT; 4181 } 4182 4183 /* Identify the levels of schedulers 4184 * to_port == phy_port && gport == scheduler => gport = L0 4185 * to_port == schduler && gport == scheduler => to_port = L0 and port = L1 4186 * to_port == scheduler && port == queue_group => to_port = L1 and port = L2 4187 */ 4188 if (to_node != NULL) { 4189 if (!BCM_GPORT_IS_SCHEDULER(to_gport)) { 4190 if ((to_node->numq == 0) || (to_node->numq_expandable)) { 4191 local_port = (BCM_GPORT_IS_LOCAL(to_gport)) ? 4192 BCM_GPORT_LOCAL_GET(to_gport) : 4193 BCM_GPORT_MODPORT_PORT_GET(to_gport); 4194 to_node->gport = to_gport; 4195 to_node->hw_index = 4196 SOC_INFO(unit).port_p2m_mapping[SOC_INFO(unit).port_l2p_mapping[local_port]]; 4197 to_node->in_use = TRUE; 4198 to_node->level = SOC_TR3_NODE_LVL_ROOT; 4199 to_node->local_port = port; 4200 to_node->attached_to_input = 0; 4201 to_node->numq_expandable = 1; 4202 4203 /* How many children do we need, 1 if unknown, else 4204 * take the max of to_cosq or current numq */ 4205 if (to_cosq == -1) { 4206 to_node->numq += 1; 4207 } else { 4208 if (to_cosq >= to_node->numq) { 4209 to_node->numq = to_cosq + 1; 4210 } 4211 } 4212 } 4213 4214 if (!BCM_GPORT_IS_SCHEDULER(gport)) { 4215 return BCM_E_PARAM; 4216 } 4217 4218 node->level = SOC_TR3_NODE_LVL_L0; 4219 } else { 4220 if (to_node->level == SOC_TR3_NODE_LVL_ROOT) { 4221 to_node->attached_to_input = 0; 4222 node->level = SOC_TR3_NODE_LVL_L0; 4223 } 4224 4225 if (IS_TR3_HSP_PORT(unit, to_port)) { 4226 if ((to_node->level == -1)) { 4227 to_node->level = 4228 (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 4229 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) || 4230 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport)) ? 4231 SOC_TR3_NODE_LVL_L0 : 4232 SOC_TR3_NODE_LVL_ROOT; 4233 } 4234 4235 if (node->level == -1) { 4236 node->level = 4237 (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 4238 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) || 4239 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport)) ? 4240 SOC_TR3_NODE_LVL_L2 : SOC_TR3_NODE_LVL_L0; 4241 } 4242 4243 } else { 4244 if ((to_node->level == -1)) { 4245 to_node->level = (BCM_GPORT_IS_SCHEDULER(gport)) ? 4246 SOC_TR3_NODE_LVL_L0 : SOC_TR3_NODE_LVL_L1; 4247 } 4248 4249 if (node->level == -1) { 4250 node->level = 4251 (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 4252 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport) || 4253 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) || 4254 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport)) ? 4255 SOC_TR3_NODE_LVL_L2 : SOC_TR3_NODE_LVL_L1; 4256 } 4257 } 4258 } 4259 } 4260 4261 if ((to_cosq < -1) || ((to_node->numq != -1) && (to_cosq >= to_node->numq))) { 4262 return BCM_E_PARAM; 4263 } 4264 if (to_node->hw_index == -1) { 4265 return BCM_E_PARAM; 4266 } 4267 4268 if (local_port == -1) { 4269 if (node->local_port != -1) { 4270 local_port = node->local_port; 4271 } else { 4272 BCM_IF_ERROR_RETURN 4273 (_bcm_tr3_cosq_localport_resolve(unit, gport, &local_port)); 4274 } 4275 } 4276 if ((local_port != -1) && IS_AXP_PORT(unit, local_port)) { 4277 if (node->level == SOC_TR3_NODE_LVL_L2) { 4278 BCM_IF_ERROR_RETURN 4279 (_soc_tr3_cosq_axp_node_validate(unit, local_port, node->hw_index, node->hw_cosq)); 4280 } 4281 } 4282 4283 if (BCM_GPORT_IS_SCHEDULER(to_gport) || BCM_GPORT_IS_LOCAL(to_gport) || 4284 BCM_GPORT_IS_MODPORT(to_gport)) { 4285 if (to_node->attached_to_input < 0) { 4286 /* dont allow to attach to a node that has already attached */ 4287 return BCM_E_PARAM; 4288 } 4289 4290 node->parent = to_node; 4291 node->sibling = to_node->child; 4292 to_node->child = node; 4293 /* resolve the nodes */ 4294 rv = _bcm_tr3_cosq_node_resolve(unit, node, to_cosq); 4295 if (BCM_FAILURE(rv)) { 4296 to_node->child = node->sibling; 4297 node->parent = NULL; 4298 return rv; 4299 } 4300 4301 if ((node->level == SOC_TR3_NODE_LVL_L2) && 4302 !BCM_GPORT_IS_MCAST_QUEUE_GROUP(node->gport)) { 4303 _bcm_tr3_cosq_gport_node_disable(unit, node, 0); 4304 } 4305 4306 LOG_INFO(BSL_LS_BCM_COSQ, 4307 (BSL_META_U(unit, 4308 " hw_cosq=%d\n"), 4309 node->attached_to_input)); 4310 4311 } else { 4312 return BCM_E_PORT; 4313 } 4314 4315 return BCM_E_NONE; 4316 } 4317 4318 /* 4319 * Function: 4320 * bcm_tr3_cosq_gport_attach_get 4321 * Purpose: 4322 * Get attached status of a scheduler port 4323 * Parameters: 4324 * unit - (IN) unit number 4325 * sched_port - (IN) scheduler GPORT identifier 4326 * input_port - (OUT) GPORT to attach to 4327 * cosq - (OUT) COS queue to attached to 4328 * Returns: 4329 * BCM_E_XXX 4330 * Notes: 4331 */ 4332 int 4333 bcm_tr3_cosq_gport_attach_get(int unit, bcm_gport_t sched_gport, 4334 bcm_gport_t *input_gport, bcm_cos_queue_t *cosq) 4335 { 4336 _bcm_tr3_cosq_node_t *sched_node; 4337 bcm_module_t modid, modid_out; 4338 bcm_port_t port, port_out; 4339 4340 if (input_gport == NULL || cosq == NULL) { 4341 return BCM_E_PARAM; 4342 } 4343 4344 BCM_IF_ERROR_RETURN 4345 (_bcm_tr3_cosq_node_get(unit, sched_gport, 0, &modid, &port, NULL, 4346 &sched_node)); 4347 4348 if (sched_node->attached_to_input < 0) { 4349 /* Not attached yet */ 4350 return BCM_E_NOT_FOUND; 4351 } 4352 4353 if (sched_node->parent != NULL) { /* sched_node is not an S1 scheduler */ 4354 *input_gport = sched_node->parent->gport; 4355 } else { /* sched_node is an S1 scheduler */ 4356 BCM_IF_ERROR_RETURN 4357 (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, modid, port, 4358 &modid_out, &port_out)); 4359 BCM_GPORT_MODPORT_SET(*input_gport, modid_out, port_out); 4360 } 4361 *cosq = sched_node->attached_to_input; 4362 4363 return BCM_E_NONE; 4364 } 4365 4366 /* 4367 * Function: 4368 * bcm_tr3_cosq_gport_child_get 4369 * Purpose: 4370 * Get the child node GPORT atatched to N-th index (cosq) 4371 * of the scheduler GPORT. 4372 * Parameters: 4373 * unit - (IN) Unit number. 4374 * in_gport - (IN) Scheduler GPORT ID. 4375 * cosq - (IN) COS queue attached to. 4376 * out_gport - (OUT) child GPORT ID. 4377 * Returns: 4378 * BCM_E_XXX 4379 * Notes: 4380 */ 4381 int 4382 bcm_tr3_cosq_gport_child_get(int unit, bcm_gport_t in_gport, 4383 bcm_cos_queue_t cosq, 4384 bcm_gport_t *out_gport) 4385 { 4386 _bcm_tr3_cosq_node_t *in_node = NULL; 4387 _bcm_tr3_cosq_node_t *cur_node = NULL; 4388 _bcm_tr3_cosq_node_t *tmp_node = NULL; 4389 bcm_module_t modid; 4390 bcm_port_t port; 4391 4392 if (out_gport == NULL) { 4393 return BCM_E_PARAM; 4394 } 4395 4396 /* get the child of the input gport node 4397 * at an index of cosq 4398 */ 4399 4400 if ((cosq < 0) || ( cosq >= 64)) { 4401 return BCM_E_PARAM; 4402 } 4403 /* Check if gport is not set than set it */ 4404 if(!BCM_GPORT_IS_SET(in_gport)) { 4405 BCM_IF_ERROR_RETURN(bcm_esw_port_gport_get(unit, in_gport, &in_gport)); 4406 } 4407 BCM_IF_ERROR_RETURN 4408 (_bcm_tr3_cosq_node_get(unit, in_gport, 0, &modid, &port, NULL, 4409 &in_node)); 4410 if ((in_node->child == NULL) && (in_node->level == SOC_TR3_NODE_LVL_L2)) { 4411 return BCM_E_PARAM; 4412 } 4413 4414 for (cur_node = in_node->child; cur_node != NULL; 4415 cur_node = cur_node->sibling) { 4416 if (cur_node->attached_to_input == cosq) { 4417 tmp_node = cur_node; 4418 break; 4419 } 4420 } 4421 if (tmp_node == NULL) { 4422 return BCM_E_NOT_FOUND; 4423 } 4424 *out_gport = tmp_node->gport; 4425 4426 return BCM_E_NONE; 4427 } 4428 /* 4429 * Convert HW drop probability to percent value 4430 */ 4431 static int 4432 _bcm_tr3_hw_drop_prob_to_percent[] = { 4433 0, /* 0 */ 4434 1, /* 1 */ 4435 2, /* 2 */ 4436 3, /* 3 */ 4437 4, /* 4 */ 4438 5, /* 5 */ 4439 6, /* 6 */ 4440 7, /* 7 */ 4441 8, /* 8 */ 4442 9, /* 9 */ 4443 10, /* 10 */ 4444 25, /* 11 */ 4445 50, /* 12 */ 4446 75, /* 13 */ 4447 100, /* 14 */ 4448 -1 /* 15 */ 4449 }; 4450 4451 STATIC int 4452 _bcm_tr3_percent_to_drop_prob(int percent) 4453 { 4454 int i; 4455 4456 for (i = 14; i > 0 ; i--) { 4457 if (percent >= _bcm_tr3_hw_drop_prob_to_percent[i]) { 4458 break; 4459 } 4460 } 4461 return i; 4462 } 4463 4464 STATIC int 4465 _bcm_tr3_drop_prob_to_percent(int drop_prob) { 4466 return (_bcm_tr3_hw_drop_prob_to_percent[drop_prob]); 4467 } 4468 4469 /* 4470 * index: degree, value: contangent(degree) * 100 4471 * max value is 0xffff (16-bit) at 0 degree 4472 */ 4473 static int 4474 _bcm_tr3_cotangent_lookup_table[] = 4475 { 4476 /* 0.. 5 */ 65535, 5728, 2863, 1908, 1430, 1143, 4477 /* 6..11 */ 951, 814, 711, 631, 567, 514, 4478 /* 12..17 */ 470, 433, 401, 373, 348, 327, 4479 /* 18..23 */ 307, 290, 274, 260, 247, 235, 4480 /* 24..29 */ 224, 214, 205, 196, 188, 180, 4481 /* 30..35 */ 173, 166, 160, 153, 148, 142, 4482 /* 36..41 */ 137, 132, 127, 123, 119, 115, 4483 /* 42..47 */ 111, 107, 103, 100, 96, 93, 4484 /* 48..53 */ 90, 86, 83, 80, 78, 75, 4485 /* 54..59 */ 72, 70, 67, 64, 62, 60, 4486 /* 60..65 */ 57, 55, 53, 50, 48, 46, 4487 /* 66..71 */ 44, 42, 40, 38, 36, 34, 4488 /* 72..77 */ 32, 30, 28, 26, 24, 23, 4489 /* 78..83 */ 21, 19, 17, 15, 14, 12, 4490 /* 84..89 */ 10, 8, 6, 5, 3, 1, 4491 /* 90 */ 0 4492 }; 4493 4494 /* 4495 * Given a slope (angle in degrees) from 0 to 90, return the number of cells 4496 * in the range from 0% drop probability to 100% drop probability. 4497 */ 4498 STATIC int 4499 _bcm_tr3_angle_to_cells(int angle) 4500 { 4501 return (_bcm_tr3_cotangent_lookup_table[angle]); 4502 } 4503 4504 /* 4505 * Given a number of packets in the range from 0% drop probability 4506 * to 100% drop probability, return the slope (angle in degrees). 4507 */ 4508 STATIC int 4509 _bcm_tr3_cells_to_angle(int packets) 4510 { 4511 int angle; 4512 4513 for (angle = 90; angle >= 0 ; angle--) { 4514 if (packets <= _bcm_tr3_cotangent_lookup_table[angle]) { 4515 break; 4516 } 4517 } 4518 return angle; 4519 } 4520 4521 /* 4522 * Function: 4523 * _bcm_tr3_cosq_bucket_set 4524 * Purpose: 4525 * Configure COS queue bandwidth control bucket 4526 * Parameters: 4527 * unit - (IN) unit number 4528 * port - (IN) port number or GPORT identifier 4529 * cosq - (IN) COS queue number 4530 * min_quantum - (IN) kbps or packet/second 4531 * max_quantum - (IN) kbps or packet/second 4532 * burst_quantum - (IN) kbps or packet/second 4533 * flags - (IN) 4534 * Returns: 4535 * BCM_E_XXX 4536 * Notes: 4537 * If port is any form of local port, cosq is the hardware queue index. 4538 */ 4539 STATIC int 4540 _bcm_tr3_cosq_bucket_set(int unit, bcm_gport_t port, bcm_cos_queue_t cosq, 4541 uint32 min_quantum, uint32 max_quantum, 4542 uint32 kbits_burst_min, uint32 kbits_burst_max, 4543 uint32 flags) 4544 { 4545 _bcm_tr3_cosq_node_t *node = NULL; 4546 bcm_port_t local_port; 4547 int index, rv; 4548 uint32 rval; 4549 uint32 meter_flags; 4550 uint32 bucketsize_max, bucketsize_min; 4551 uint32 granularity_max, granularity_min; 4552 uint32 refresh_rate_max, refresh_rate_min; 4553 int refresh_bitsize = 0, bucket_bitsize = 0; 4554 soc_mem_t config_mem = INVALIDm; 4555 uint32 entry[SOC_MAX_MEM_WORDS]; 4556 4557 /* caller should resolve the cosq. */ 4558 if (cosq < 0) { 4559 if (cosq == -1) { 4560 /* caller needs to resolve the wild card value (-1) */ 4561 return BCM_E_INTERNAL; 4562 } else { /* reject all other negative value */ 4563 return BCM_E_PARAM; 4564 } 4565 } 4566 4567 BCM_IF_ERROR_RETURN 4568 (_bcm_tr3_cosq_index_resolve(unit, port, cosq, 4569 _BCM_TR3_COSQ_INDEX_STYLE_BUCKET, 4570 &local_port, &index, NULL)); 4571 4572 if (BCM_GPORT_IS_SET(port) && 4573 ((BCM_GPORT_IS_SCHEDULER(port)) || 4574 BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 4575 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port) || 4576 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) || 4577 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port))) { 4578 4579 BCM_IF_ERROR_RETURN 4580 (_bcm_tr3_cosq_node_get(unit, port, cosq, NULL, 4581 NULL, NULL, &node)); 4582 } 4583 4584 if (node) { 4585 if (BCM_GPORT_IS_SCHEDULER(port)) { 4586 if (node->level == SOC_TR3_NODE_LVL_ROOT) { 4587 config_mem = MMU_MTRO_L0_MEMm; 4588 } else if (node->level == SOC_TR3_NODE_LVL_L0) { 4589 if (IS_TR3_HSP_PORT(unit, local_port)) { 4590 config_mem = MMU_MTRO_L2_MEMm; 4591 } else { 4592 config_mem = MMU_MTRO_L1_MEMm; 4593 } 4594 } else if (node->level == SOC_TR3_NODE_LVL_L1) { 4595 config_mem = MMU_MTRO_L2_MEMm; 4596 } else { 4597 return BCM_E_PARAM; 4598 } 4599 } else if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 4600 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port) || 4601 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 4602 config_mem = MMU_MTRO_L2_MEMm; 4603 } else { 4604 return BCM_E_PARAM; 4605 } 4606 } else { 4607 if (IS_CPU_PORT(unit, local_port)) { 4608 config_mem = MMU_MTRO_L2_MEMm; 4609 } else if (IS_TR3_HSP_PORT(unit, local_port)) { 4610 config_mem = MMU_MTRO_L0_MEMm; 4611 } else { 4612 config_mem = MMU_MTRO_L1_MEMm; 4613 } 4614 } 4615 4616 meter_flags = flags & BCM_COSQ_BW_PACKET_MODE ? 4617 _BCM_TD_METER_FLAG_PACKET_MODE : 0; 4618 BCM_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, &rval)); 4619 if (soc_reg_field_get(unit, MISCCONFIGr, rval, ITU_MODE_SELf)) { 4620 meter_flags |= _BCM_TD_METER_FLAG_NON_LINEAR; 4621 } 4622 4623 refresh_bitsize = soc_mem_field_length(unit, config_mem, MAX_REFRESHf); 4624 bucket_bitsize = soc_mem_field_length(unit, config_mem, MAX_THD_SELf); 4625 4626 BCM_IF_ERROR_RETURN 4627 (_bcm_td_rate_to_bucket_encoding(unit, max_quantum, kbits_burst_max, 4628 meter_flags, refresh_bitsize, 4629 bucket_bitsize, &refresh_rate_max, 4630 &bucketsize_max, &granularity_max)); 4631 4632 BCM_IF_ERROR_RETURN 4633 (_bcm_td_rate_to_bucket_encoding(unit, min_quantum, kbits_burst_min, 4634 meter_flags, refresh_bitsize, 4635 bucket_bitsize, &refresh_rate_min, 4636 &bucketsize_min, &granularity_min)); 4637 4638 sal_memset(entry, 0, sizeof(uint32)*SOC_MAX_MEM_WORDS); 4639 soc_mem_field32_set(unit, config_mem, &entry, MAX_METER_GRANf, granularity_max); 4640 soc_mem_field32_set(unit, config_mem, &entry, MAX_REFRESHf, refresh_rate_max); 4641 soc_mem_field32_set(unit, config_mem, &entry, MAX_THD_SELf, bucketsize_max); 4642 4643 soc_mem_field32_set(unit, config_mem, &entry, MIN_METER_GRANf, granularity_min); 4644 soc_mem_field32_set(unit, config_mem, &entry, MIN_REFRESHf, refresh_rate_min); 4645 soc_mem_field32_set(unit, config_mem, &entry, MIN_THD_SELf, bucketsize_min); 4646 4647 soc_mem_field32_set(unit, config_mem, &entry, SHAPER_CONTROLf, 4648 (flags & BCM_COSQ_BW_PACKET_MODE) ? 1 : 0); 4649 SOC_EGRESS_METERING_LOCK(unit); 4650 rv = soc_mem_write(unit, config_mem, MEM_BLOCK_ALL, index, &entry); 4651 SOC_EGRESS_METERING_UNLOCK(unit); 4652 if (rv < 0) { 4653 return rv; 4654 } 4655 if ((node==NULL) && (!IS_CPU_PORT(unit, local_port)) && 4656 ((!soc_feature(unit, soc_feature_tr3_sp_vector_mask)) && 4657 soc_property_port_get(unit, local_port, spn_PORT_SCHED_DYNAMIC, 0))) { 4658 if (soc_port_hg_capable(unit, port)) { 4659 /* As the 8th index is meant for SC/QM adding offset of 9 on dyn Q's */ 4660 BCM_IF_ERROR_RETURN 4661 (soc_mem_write(unit, config_mem, MEM_BLOCK_ALL, index + 9, &entry)); 4662 } else { 4663 BCM_IF_ERROR_RETURN 4664 (soc_mem_write(unit, config_mem, MEM_BLOCK_ALL, index + 8, &entry)); 4665 } 4666 } 4667 4668 return BCM_E_NONE; 4669 } 4670 4671 /* 4672 * Function: 4673 * _bcm_tr3_cosq_bucket_get 4674 * Purpose: 4675 * Get COS queue bandwidth control bucket setting 4676 * Parameters: 4677 * unit - (IN) unit number 4678 * port - (IN) port number or GPORT identifier 4679 * cosq - (IN) COS queue number 4680 * min_quantum - (OUT) kbps or packet/second 4681 * max_quantum - (OUT) kbps or packet/second 4682 * burst_quantum - (OUT) kbps or packet/second 4683 * flags - (IN) 4684 * Returns: 4685 * BCM_E_XXX 4686 * Notes: 4687 * If port is any form of local port, cosq is the hardware queue index. 4688 */ 4689 STATIC int 4690 _bcm_tr3_cosq_bucket_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 4691 uint32 *min_quantum, uint32 *max_quantum, 4692 uint32 *kbits_burst_min, uint32 *kbits_burst_max, 4693 uint32 *flags) 4694 { 4695 _bcm_tr3_cosq_node_t *node = NULL; 4696 bcm_port_t local_port; 4697 int index, rv; 4698 uint32 rval; 4699 uint32 refresh_rate, bucketsize, granularity, meter_flags; 4700 soc_mem_t config_mem = INVALIDm; 4701 uint32 entry[SOC_MAX_MEM_WORDS]; 4702 4703 if (cosq < 0) { 4704 if (cosq == -1) { 4705 /* caller needs to resolve the wild card value (-1) */ 4706 return BCM_E_INTERNAL; 4707 } else { /* reject all other negative value */ 4708 return BCM_E_PARAM; 4709 } 4710 } 4711 4712 BCM_IF_ERROR_RETURN 4713 (_bcm_tr3_cosq_index_resolve(unit, port, cosq, 4714 _BCM_TR3_COSQ_INDEX_STYLE_BUCKET, 4715 &local_port, &index, NULL)); 4716 4717 if (BCM_GPORT_IS_SET(port) && 4718 ((BCM_GPORT_IS_SCHEDULER(port)) || 4719 BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 4720 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port) || 4721 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) || 4722 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port))) { 4723 4724 BCM_IF_ERROR_RETURN 4725 (_bcm_tr3_cosq_node_get(unit, port, cosq, NULL, 4726 &local_port, NULL, &node)); 4727 } 4728 4729 if (node) { 4730 if (BCM_GPORT_IS_SCHEDULER(port)) { 4731 if (node->level == SOC_TR3_NODE_LVL_ROOT) { 4732 config_mem = MMU_MTRO_L0_MEMm; 4733 } else if (node->level == SOC_TR3_NODE_LVL_L0) { 4734 if (IS_TR3_HSP_PORT(unit, local_port)) { 4735 config_mem = MMU_MTRO_L2_MEMm; 4736 } else { 4737 config_mem = MMU_MTRO_L1_MEMm; 4738 } 4739 } else if (node->level == SOC_TR3_NODE_LVL_L1) { 4740 config_mem = MMU_MTRO_L2_MEMm; 4741 } else { 4742 return BCM_E_PARAM; 4743 } 4744 } else if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 4745 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port) || 4746 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 4747 config_mem = MMU_MTRO_L2_MEMm; 4748 } else { 4749 return BCM_E_PARAM; 4750 } 4751 } else { 4752 if (IS_CPU_PORT(unit, local_port)) { 4753 config_mem = MMU_MTRO_L2_MEMm; 4754 } else if (IS_TR3_HSP_PORT(unit, local_port)) { 4755 config_mem = MMU_MTRO_L0_MEMm; 4756 } else { 4757 config_mem = MMU_MTRO_L1_MEMm; 4758 } 4759 } 4760 4761 if (min_quantum == NULL || max_quantum == NULL || 4762 kbits_burst_max == NULL || kbits_burst_min == NULL) { 4763 return BCM_E_PARAM; 4764 } 4765 4766 #ifdef DEBUG_TR3_COSQ 4767 LOG_CLI((BSL_META_U(unit, 4768 "_bcm_tr3_cosq_bucket_get : gport=0x%08x Index : %d mem=%d\n"), 4769 port, index, config_mem)); 4770 #endif 4771 SOC_EGRESS_METERING_LOCK(unit); 4772 rv = soc_mem_read(unit, config_mem, MEM_BLOCK_ALL, index, &entry); 4773 SOC_EGRESS_METERING_UNLOCK(unit); 4774 if (rv < 0) { 4775 return rv; 4776 } 4777 meter_flags = 0; 4778 *flags = 0; 4779 BCM_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, &rval)); 4780 if (soc_reg_field_get(unit, MISCCONFIGr, rval, ITU_MODE_SELf)) { 4781 meter_flags |= _BCM_TD_METER_FLAG_NON_LINEAR; 4782 } 4783 if (soc_mem_field32_get(unit, config_mem, &entry, SHAPER_CONTROLf)) { 4784 meter_flags |= _BCM_TD_METER_FLAG_PACKET_MODE; 4785 *flags |= BCM_COSQ_BW_PACKET_MODE; 4786 } 4787 4788 granularity = soc_mem_field32_get(unit, config_mem, &entry, MAX_METER_GRANf); 4789 refresh_rate = soc_mem_field32_get(unit, config_mem, &entry, MAX_REFRESHf); 4790 bucketsize = soc_mem_field32_get(unit, config_mem, &entry, MAX_THD_SELf); 4791 BCM_IF_ERROR_RETURN 4792 (_bcm_td_bucket_encoding_to_rate(unit, refresh_rate, bucketsize, 4793 granularity, meter_flags, 4794 max_quantum, kbits_burst_max)); 4795 4796 granularity = soc_mem_field32_get(unit, config_mem, &entry, MIN_METER_GRANf); 4797 refresh_rate = soc_mem_field32_get(unit, config_mem, &entry, MIN_REFRESHf); 4798 bucketsize = soc_mem_field32_get(unit, config_mem, &entry, MIN_THD_SELf); 4799 BCM_IF_ERROR_RETURN 4800 (_bcm_td_bucket_encoding_to_rate(unit, refresh_rate, bucketsize, 4801 granularity, meter_flags, 4802 min_quantum, kbits_burst_min)); 4803 return BCM_E_NONE; 4804 } 4805 4806 /* 4807 * Function: 4808 * _bcm_tr3_cosq_wred_set 4809 * Purpose: 4810 * Configure unicast queue WRED setting 4811 * Parameters: 4812 * unit - (IN) unit number 4813 * port - (IN) port number or GPORT identifier 4814 * cosq - (IN) COS queue number 4815 * flags - (IN) BCM_COSQ_DISCARD_XXX 4816 * min_thresh - (IN) 4817 * max_thresh - (IN) 4818 * drop_probablity - (IN) 4819 * gain - (IN) 4820 * ignore_enable_flags - (IN) 4821 * Returns: 4822 * BCM_E_XXX 4823 * Notes: 4824 * If port is any form of local port, cosq is the hardware queue index. 4825 */ 4826 STATIC int 4827 _bcm_tr3_cosq_wred_set(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 4828 uint32 flags, uint32 min_thresh, uint32 max_thresh, 4829 int drop_probability, int gain, int ignore_enable_flags, 4830 uint32 lflags) 4831 { 4832 soc_mem_t wred_mem; 4833 bcm_port_t local_port; 4834 int index, to_index; 4835 uint32 profile_index, old_profile_index; 4836 mmu_wred_drop_curve_profile_0_entry_t entry_tcp_green; 4837 mmu_wred_drop_curve_profile_1_entry_t entry_tcp_yellow; 4838 mmu_wred_drop_curve_profile_2_entry_t entry_tcp_red; 4839 mmu_wred_drop_curve_profile_3_entry_t entry_nontcp_green; 4840 mmu_wred_drop_curve_profile_4_entry_t entry_nontcp_yellow; 4841 mmu_wred_drop_curve_profile_5_entry_t entry_nontcp_red; 4842 mmu_wred_config_entry_t qentry; 4843 void *entries[6]; 4844 soc_mem_t mems[6]; 4845 int rate, i, jj, exists = 0; 4846 static soc_mem_t wred_mems[6] = { 4847 MMU_WRED_DROP_CURVE_PROFILE_0m, MMU_WRED_DROP_CURVE_PROFILE_1m, 4848 MMU_WRED_DROP_CURVE_PROFILE_2m, MMU_WRED_DROP_CURVE_PROFILE_3m, 4849 MMU_WRED_DROP_CURVE_PROFILE_4m, MMU_WRED_DROP_CURVE_PROFILE_5m 4850 }; 4851 /* For port -1 , set global wred discard profile for all ports by 4852 setting for all global profile indices */ 4853 4854 if (((port == -1) && (flags & BCM_COSQ_DISCARD_DEVICE)) || (lflags & BCM_COSQ_DISCARD_DEVICE)) { 4855 index = 1532; 4856 to_index = 1535; 4857 } else { 4858 if (lflags & BCM_COSQ_DISCARD_PORT) { 4859 BCM_IF_ERROR_RETURN 4860 (_bcm_tr3_cosq_index_resolve(unit, port, cosq, 4861 _BCM_TR3_COSQ_INDEX_STYLE_WRED_PORT, 4862 &local_port, &index, NULL)); 4863 } else { 4864 BCM_IF_ERROR_RETURN 4865 (_bcm_tr3_cosq_index_resolve(unit, port, cosq, 4866 _BCM_TR3_COSQ_INDEX_STYLE_WRED, 4867 &local_port, &index, NULL)); 4868 } 4869 to_index = index; 4870 } 4871 4872 wred_mem = MMU_WRED_CONFIGm; 4873 4874 for (jj = index; jj <= to_index; jj++) { 4875 BCM_IF_ERROR_RETURN 4876 (soc_mem_read(unit, wred_mem, MEM_BLOCK_ALL, jj, &qentry)); 4877 4878 old_profile_index = 0xffffffff; 4879 if (flags & (BCM_COSQ_DISCARD_NONTCP | BCM_COSQ_DISCARD_COLOR_ALL | 4880 BCM_COSQ_DISCARD_TCP)) { 4881 old_profile_index = soc_mem_field32_get(unit, wred_mem, 4882 &qentry, PROFILE_INDEXf); 4883 entries[0] = &entry_tcp_green; 4884 entries[1] = &entry_tcp_yellow; 4885 entries[2] = &entry_tcp_red; 4886 entries[3] = &entry_nontcp_green; 4887 entries[4] = &entry_nontcp_yellow; 4888 entries[5] = &entry_nontcp_red; 4889 BCM_IF_ERROR_RETURN 4890 (soc_profile_mem_get(unit, _bcm_tr3_wred_profile[unit], 4891 old_profile_index, 1, entries)); 4892 for (i = 0; i < 6; i++) { 4893 mems[i] = INVALIDm; 4894 } 4895 if (!(flags & (BCM_COSQ_DISCARD_COLOR_GREEN | 4896 BCM_COSQ_DISCARD_COLOR_YELLOW | 4897 BCM_COSQ_DISCARD_COLOR_RED))) { 4898 flags |= BCM_COSQ_DISCARD_COLOR_ALL; 4899 } 4900 if (!(flags & BCM_COSQ_DISCARD_NONTCP) || (flags & BCM_COSQ_DISCARD_TCP)) { 4901 if (flags & BCM_COSQ_DISCARD_COLOR_GREEN) { 4902 mems[0] = MMU_WRED_DROP_CURVE_PROFILE_0m; 4903 } 4904 if (flags & BCM_COSQ_DISCARD_COLOR_YELLOW) { 4905 mems[1] = MMU_WRED_DROP_CURVE_PROFILE_1m; 4906 } 4907 if (flags & BCM_COSQ_DISCARD_COLOR_RED) { 4908 mems[2] = MMU_WRED_DROP_CURVE_PROFILE_2m; 4909 } 4910 } 4911 if (flags & BCM_COSQ_DISCARD_NONTCP) { 4912 if (flags & BCM_COSQ_DISCARD_COLOR_GREEN) { 4913 mems[3] = MMU_WRED_DROP_CURVE_PROFILE_3m; 4914 } 4915 if (flags & BCM_COSQ_DISCARD_COLOR_YELLOW) { 4916 mems[4] = MMU_WRED_DROP_CURVE_PROFILE_4m; 4917 } 4918 if (flags & BCM_COSQ_DISCARD_COLOR_RED) { 4919 mems[5] = MMU_WRED_DROP_CURVE_PROFILE_5m; 4920 } 4921 } 4922 rate = _bcm_tr3_percent_to_drop_prob(drop_probability); 4923 for (i = 0; i < 6; i++) { 4924 exists = 0; 4925 if ((soc_mem_field32_get(unit, wred_mems[i], entries[i], 4926 MIN_THDf) != 0x7fff) && (mems[i] == INVALIDm)) { 4927 mems[i] = wred_mems[i]; 4928 exists = 1; 4929 } else { 4930 soc_mem_field32_set(unit, wred_mems[i], entries[i], MIN_THDf, 4931 (mems[i] == INVALIDm) ? 0x7fff : min_thresh); 4932 } 4933 4934 if ((soc_mem_field32_get(unit, wred_mems[i], entries[i], 4935 MAX_THDf) != 0x7fff) && ((mems[i] == INVALIDm) || exists)) { 4936 mems[i] = wred_mems[i]; 4937 exists = 1; 4938 } else { 4939 soc_mem_field32_set(unit, wred_mems[i], entries[i], MAX_THDf, 4940 (mems[i] == INVALIDm) ? 0x7fff : max_thresh); 4941 } 4942 4943 if (!exists) { 4944 soc_mem_field32_set(unit, wred_mems[i], entries[i], MAX_DROP_RATEf, 4945 (mems[i] == INVALIDm) ? 0 : rate); 4946 } 4947 } 4948 4949 BCM_IF_ERROR_RETURN 4950 (soc_profile_mem_add(unit, _bcm_tr3_wred_profile[unit], entries, 1, 4951 &profile_index)); 4952 soc_mem_field32_set(unit, wred_mem, &qentry, PROFILE_INDEXf, profile_index); 4953 soc_mem_field32_set(unit, wred_mem, &qentry, WEIGHTf, gain); 4954 } 4955 4956 /* Some APIs only modify profiles */ 4957 if (!ignore_enable_flags) { 4958 soc_mem_field32_set(unit, wred_mem, &qentry, CAP_AVERAGEf, 4959 flags & BCM_COSQ_DISCARD_CAP_AVERAGE ? 1 : 0); 4960 soc_mem_field32_set(unit, wred_mem, &qentry, WRED_ENf, 4961 flags & BCM_COSQ_DISCARD_ENABLE ? 1 : 0); 4962 soc_mem_field32_set(unit, wred_mem, &qentry, ECN_MARKING_ENf, 4963 flags & BCM_COSQ_DISCARD_MARK_CONGESTION ? 1 : 0); 4964 } 4965 BCM_IF_ERROR_RETURN( 4966 soc_mem_write(unit, wred_mem, MEM_BLOCK_ALL, jj, &qentry)); 4967 4968 if (old_profile_index != 0xffffffff) { 4969 4970 SOC_IF_ERROR_RETURN 4971 (soc_profile_mem_delete(unit, _bcm_tr3_wred_profile[unit], 4972 old_profile_index)); 4973 } 4974 } 4975 4976 return BCM_E_NONE; 4977 } 4978 4979 /* 4980 * Function: 4981 * _bcm_tr3_cosq_wred_get 4982 * Purpose: 4983 * Get unicast queue WRED setting 4984 * Parameters: 4985 * unit - (IN) unit number 4986 * port - (IN) port number or GPORT identifier 4987 * cosq - (IN) COS queue number 4988 * flags - (IN/OUT) BCM_COSQ_DISCARD_XXX 4989 * min_thresh - (OUT) 4990 * max_thresh - (OUT) 4991 * drop_probablity - (OUT) 4992 * gain - (OUT) 4993 * Returns: 4994 * BCM_E_XXX 4995 * Notes: 4996 * If port is any form of local port, cosq is the hardware queue index. 4997 */ 4998 STATIC int 4999 _bcm_tr3_cosq_wred_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 5000 uint32 *flags, uint32 *min_thresh, uint32 *max_thresh, 5001 int *drop_probability, int *gain, uint32 lflags) 5002 { 5003 bcm_port_t local_port; 5004 int index, profile_index; 5005 mmu_wred_drop_curve_profile_0_entry_t entry_tcp_green; 5006 mmu_wred_drop_curve_profile_1_entry_t entry_tcp_yellow; 5007 mmu_wred_drop_curve_profile_2_entry_t entry_tcp_red; 5008 mmu_wred_drop_curve_profile_3_entry_t entry_nontcp_green; 5009 mmu_wred_drop_curve_profile_4_entry_t entry_nontcp_yellow; 5010 mmu_wred_drop_curve_profile_5_entry_t entry_nontcp_red; 5011 void *entries[6]; 5012 void *entry_p; 5013 soc_mem_t mem; 5014 soc_mem_t wred_mem = 0; 5015 mmu_wred_config_entry_t qentry; 5016 int rate; 5017 5018 if ((port == -1) && ((*flags & BCM_COSQ_DISCARD_DEVICE) || 5019 (lflags & BCM_COSQ_DISCARD_DEVICE))) { 5020 index = 1532; 5021 } else { 5022 if (lflags & BCM_COSQ_DISCARD_PORT) { 5023 BCM_IF_ERROR_RETURN 5024 (_bcm_tr3_cosq_index_resolve(unit, port, cosq, 5025 _BCM_TR3_COSQ_INDEX_STYLE_WRED_PORT, 5026 &local_port, &index, NULL)); 5027 } else { 5028 BCM_IF_ERROR_RETURN 5029 (_bcm_tr3_cosq_index_resolve(unit, port, cosq, 5030 _BCM_TR3_COSQ_INDEX_STYLE_WRED, 5031 &local_port, &index, NULL)); 5032 } 5033 } 5034 5035 wred_mem = MMU_WRED_CONFIGm; 5036 5037 BCM_IF_ERROR_RETURN 5038 (soc_mem_read(unit, wred_mem, MEM_BLOCK_ALL, index, &qentry)); 5039 profile_index = soc_mem_field32_get(unit, wred_mem, 5040 &qentry, PROFILE_INDEXf); 5041 5042 if (!(*flags & BCM_COSQ_DISCARD_NONTCP)) { 5043 if (*flags & BCM_COSQ_DISCARD_COLOR_GREEN) { 5044 mem = MMU_WRED_DROP_CURVE_PROFILE_0m; 5045 entry_p = &entry_tcp_green; 5046 } else if (*flags & BCM_COSQ_DISCARD_COLOR_YELLOW) { 5047 mem = MMU_WRED_DROP_CURVE_PROFILE_1m; 5048 entry_p = &entry_tcp_yellow; 5049 } else if (*flags & BCM_COSQ_DISCARD_COLOR_RED) { 5050 mem = MMU_WRED_DROP_CURVE_PROFILE_2m; 5051 entry_p = &entry_tcp_red; 5052 } else { 5053 mem = MMU_WRED_DROP_CURVE_PROFILE_0m; 5054 entry_p = &entry_tcp_green; 5055 } 5056 } else { 5057 if (*flags & BCM_COSQ_DISCARD_COLOR_GREEN) { 5058 mem = MMU_WRED_DROP_CURVE_PROFILE_3m; 5059 entry_p = &entry_nontcp_green; 5060 } else if (*flags & BCM_COSQ_DISCARD_COLOR_YELLOW) { 5061 mem = MMU_WRED_DROP_CURVE_PROFILE_4m; 5062 entry_p = &entry_nontcp_yellow; 5063 } else if (*flags & BCM_COSQ_DISCARD_COLOR_RED) { 5064 mem = MMU_WRED_DROP_CURVE_PROFILE_5m; 5065 entry_p = &entry_nontcp_red; 5066 } else { 5067 mem = MMU_WRED_DROP_CURVE_PROFILE_3m; 5068 entry_p = &entry_nontcp_green; 5069 } 5070 } 5071 5072 entries[0] = &entry_tcp_green; 5073 entries[1] = &entry_tcp_yellow; 5074 entries[2] = &entry_tcp_red; 5075 entries[3] = &entry_nontcp_green; 5076 entries[4] = &entry_nontcp_yellow; 5077 entries[5] = &entry_nontcp_red; 5078 BCM_IF_ERROR_RETURN 5079 (soc_profile_mem_get(unit, _bcm_tr3_wred_profile[unit], 5080 profile_index, 1, entries)); 5081 if (min_thresh != NULL) { 5082 *min_thresh = soc_mem_field32_get(unit, mem, entry_p, MIN_THDf); 5083 } 5084 if (max_thresh != NULL) { 5085 *max_thresh = soc_mem_field32_get(unit, mem, entry_p, MAX_THDf); 5086 } 5087 if (drop_probability != NULL) { 5088 rate = soc_mem_field32_get(unit, mem, entry_p, MAX_DROP_RATEf); 5089 *drop_probability = _bcm_tr3_drop_prob_to_percent(rate); 5090 } 5091 5092 if (gain) { 5093 *gain = soc_mem_field32_get(unit, wred_mem, &qentry, WEIGHTf); 5094 } 5095 5096 *flags &= ~(BCM_COSQ_DISCARD_CAP_AVERAGE | BCM_COSQ_DISCARD_ENABLE); 5097 if (soc_mem_field32_get(unit, wred_mem, &qentry, CAP_AVERAGEf)) { 5098 *flags |= BCM_COSQ_DISCARD_CAP_AVERAGE; 5099 } 5100 if (soc_mem_field32_get(unit, wred_mem, &qentry, WRED_ENf)) { 5101 *flags |= BCM_COSQ_DISCARD_ENABLE; 5102 } 5103 if (soc_mem_field32_get(unit, wred_mem, &qentry, ECN_MARKING_ENf)) { 5104 *flags |= BCM_COSQ_DISCARD_MARK_CONGESTION; 5105 } 5106 return BCM_E_NONE; 5107 } 5108 5109 STATIC int 5110 _bcm_tr3_decode_sp_masks(int num_sp, uint32 ucmap, uint32 *umap, int *numuc, 5111 uint32 *mmap, int *nummc) 5112 { 5113 int i, uindex, mindex; 5114 uint32 tmp_umap = 0, tmp_mmap = 0; 5115 5116 mindex = uindex = 0; 5117 5118 for (i = 0; i < num_sp; i++) { 5119 if (ucmap & (1 << i)) { 5120 /* MC */ 5121 tmp_mmap |= 1 << mindex; 5122 mindex += 1; 5123 } else { 5124 /* UC */ 5125 tmp_umap |= 1 << uindex; 5126 uindex += 1; 5127 } 5128 } 5129 5130 if (numuc) { 5131 *numuc = uindex; 5132 } 5133 5134 if (umap) { 5135 *umap = tmp_umap; 5136 } 5137 5138 if (mmap) { 5139 *mmap = tmp_mmap; 5140 } 5141 5142 if (nummc) { 5143 *nummc = mindex; 5144 } 5145 5146 return 0; 5147 } 5148 5149 STATIC uint32 _bcm_tr3_num_ones(uint32 m) 5150 { 5151 uint32 ii = 0; 5152 5153 while (m) { 5154 m &= m - 1; 5155 ii += 1; 5156 } 5157 return ii; 5158 } 5159 5160 5161 STATIC int 5162 _bcm_tr3_compute_lls_config_b0(int unit, int port, int level, 5163 int *first_sp_child, 5164 int *first_sp_mc_child, 5165 int *num_spri, 5166 uint32 *ucmap, 5167 uint32 *spmap, 5168 int child_index, 5169 soc_tr3_sched_mode_e cur_mode, 5170 soc_tr3_sched_mode_e mode, 5171 int max_children) 5172 { 5173 uint32 ucm = 0, mcm = 0, cur_spmap, cur_num_spri, lucmap = 0; 5174 int ii, *pfc, uc, mc, fc, oc, *use_fc; 5175 5176 cur_num_spri = _bcm_tr3_num_ones(*spmap); 5177 cur_spmap = *spmap; 5178 5179 if (level == SOC_TR3_NODE_LVL_L1) { 5180 if (IS_CPU_PORT(unit, port)) { 5181 use_fc = first_sp_mc_child; 5182 } else { 5183 use_fc = (child_index >= 1024) ? first_sp_mc_child : first_sp_child; 5184 } 5185 } else { 5186 use_fc = first_sp_child; 5187 } 5188 5189 if (cur_num_spri == 0) { 5190 *ucmap = 0; 5191 *spmap = 0; 5192 } 5193 5194 if (child_index > *use_fc) { 5195 if (((child_index - *use_fc) > max_children)) { 5196 return BCM_E_PARAM; 5197 } 5198 } else { 5199 if (((*use_fc + cur_num_spri) - child_index) > max_children) { 5200 return BCM_E_PARAM; 5201 } 5202 } 5203 5204 if (level == SOC_TR3_NODE_LVL_L1) { 5205 for (mcm = 0, mc = 0, ucm = 0, uc = 0, ii = 0; ii < 8; ii++) { 5206 if (*ucmap & (1 << ii)) { 5207 mcm |= (cur_spmap & (1 << ii)) ? (1 << mc) : 0; 5208 mc += 1; 5209 } else { 5210 ucm |= (cur_spmap & (1 << ii)) ? (1 << uc) : 0; 5211 uc += 1; 5212 } 5213 } 5214 5215 if (child_index < 1024) { 5216 fc = *first_sp_child; 5217 oc = _bcm_tr3_num_ones(ucm); 5218 BCM_IF_ERROR_RETURN(_bcm_tr3_compute_lls_config_b0(unit, port, 5219 level - 1, &fc, NULL, &oc, &lucmap, &ucm, child_index, 5220 cur_mode, mode, 8)); 5221 } else { 5222 fc = *first_sp_mc_child; 5223 oc = _bcm_tr3_num_ones(mcm); 5224 BCM_IF_ERROR_RETURN(_bcm_tr3_compute_lls_config_b0(unit, port, 5225 level - 1, &fc, NULL, &oc, &lucmap, &mcm, 5226 child_index, cur_mode, mode, 8)); 5227 } 5228 5229 cur_spmap = 0; 5230 *ucmap = 0; 5231 for (fc = 0, ii = 0; ii < 8; ii++) { 5232 if (ucm) { 5233 cur_spmap |= (ucm & (1 << ii)) ? 1 << fc : 0; 5234 fc += 1; 5235 ucm &= ~(1 << ii); 5236 } 5237 5238 if (mcm) { 5239 cur_spmap |= (mcm & (1 << ii)) ? 1 << fc : 0; 5240 *ucmap |= 1 << fc; 5241 fc += 1; 5242 mcm &= ~(1 << ii); 5243 } 5244 5245 if (fc > max_children) { 5246 return BCM_E_PARAM; 5247 } 5248 5249 if ((mcm == 0) && (ucm == 0)) { 5250 break; 5251 } 5252 } 5253 5254 } else { 5255 pfc = first_sp_child; 5256 if (mode == SOC_TR3_SCHED_MODE_STRICT) { 5257 if (*pfc > child_index) { 5258 cur_spmap <<= (*pfc - child_index); 5259 cur_spmap |= 1; 5260 *pfc = child_index; 5261 *num_spri += 1; 5262 } else { 5263 if (((1 << (child_index - *pfc)) & cur_spmap) == 0) { 5264 cur_spmap |= 1 << (child_index - *pfc); 5265 *num_spri += 1; 5266 } 5267 } 5268 } else { 5269 if (1 << (child_index - *pfc) & cur_spmap) { 5270 cur_spmap &= ~(1 << (child_index - *pfc)); 5271 *num_spri -= 1; 5272 } 5273 } 5274 } 5275 5276 *num_spri = _bcm_tr3_num_ones(cur_spmap); 5277 5278 *spmap = cur_spmap; 5279 5280 return BCM_E_NONE; 5281 } 5282 5283 STATIC int 5284 _bcm_tr3_compute_lls_config(int unit, int port, int level, 5285 int *first_sp_child, 5286 int *first_sp_mc_child, 5287 int *num_spri, 5288 uint32 *ucmap, 5289 uint32 *spmap, 5290 int child_index, 5291 soc_tr3_sched_mode_e cur_mode, 5292 soc_tr3_sched_mode_e mode) 5293 { 5294 int cur_first_child; 5295 int cur_num_spri; 5296 int cur_ucmap; 5297 int diff; 5298 uint32 umap = 0, mmap = 0; 5299 int numuc = 0, nummc = 0; 5300 uint32 pnumn = 0; 5301 5302 if (((cur_mode != SOC_TR3_SCHED_MODE_STRICT) && 5303 (mode != SOC_TR3_SCHED_MODE_STRICT)) || 5304 ((cur_mode == SOC_TR3_SCHED_MODE_STRICT) && 5305 (mode == SOC_TR3_SCHED_MODE_STRICT))) { 5306 return BCM_E_NONE; 5307 } 5308 5309 if (soc_feature(unit, soc_feature_tr3_sp_vector_mask)) { 5310 return _bcm_tr3_compute_lls_config_b0(unit, port, level, first_sp_child, 5311 first_sp_mc_child, num_spri, 5312 ucmap, spmap, child_index, 5313 cur_mode, mode, 8); 5314 } 5315 5316 cur_num_spri = *num_spri; 5317 cur_ucmap = *ucmap; 5318 5319 if (level == SOC_TR3_NODE_LVL_L1) { 5320 _bcm_tr3_decode_sp_masks(cur_num_spri, cur_ucmap, &umap, 5321 &numuc, &mmap, &nummc); 5322 if (child_index < 1024) { 5323 /* UC */ 5324 pnumn = numuc; 5325 cur_first_child = *first_sp_child; 5326 } else { 5327 /* MC */ 5328 pnumn = nummc; 5329 cur_first_child = *first_sp_mc_child; 5330 } 5331 } else { 5332 pnumn = cur_num_spri; 5333 cur_first_child = *first_sp_child; 5334 } 5335 5336 if (cur_mode == SOC_TR3_SCHED_MODE_STRICT) { 5337 /* this node is not in the middle of SP nodes */ 5338 if (child_index != (cur_first_child + pnumn - 1)) { 5339 return BCM_E_UNAVAIL; 5340 } 5341 5342 cur_num_spri -= 1; 5343 pnumn -= 1; 5344 5345 if (level == SOC_TR3_NODE_LVL_L1) { 5346 if (child_index < 1024) { 5347 *num_spri = pnumn + nummc; 5348 *ucmap = 0; 5349 } else { 5350 *num_spri = pnumn + numuc; 5351 *ucmap = (1 << (*num_spri)) - 1; 5352 } 5353 } else { 5354 *num_spri = cur_num_spri; 5355 *ucmap = cur_num_spri ? (1 << cur_num_spri) -1 : 0; 5356 } 5357 if (*num_spri == 0) { 5358 *ucmap = 0; 5359 } 5360 } else { 5361 if (cur_num_spri) { 5362 /* adding new sp */ 5363 diff = child_index - cur_first_child; 5364 if (diff != cur_num_spri) { 5365 return BCM_E_UNAVAIL; 5366 } 5367 5368 if (level == SOC_TR3_NODE_LVL_L1) { 5369 if (child_index < 1024) { 5370 pnumn += 1; 5371 *num_spri = pnumn + nummc; 5372 *ucmap = 0; 5373 } else { 5374 pnumn += 1; 5375 *num_spri = pnumn + numuc; 5376 *ucmap = (1 << (*num_spri)) - 1; 5377 } 5378 } else { 5379 pnumn += 1; 5380 *num_spri = pnumn; 5381 *ucmap = (1 << pnumn) - 1; 5382 } 5383 } else { 5384 /* The node must be the first wrr/wdrr children of the parent if */ 5385 /* the node scheduler change wrr/wdrr to sp on triumph3 A0&A1. */ 5386 if (child_index != cur_first_child) { 5387 return BCM_E_UNAVAIL; 5388 } 5389 *num_spri = 1; 5390 if (child_index < 1024) { 5391 *ucmap = 0; 5392 } else { 5393 *ucmap = 1; 5394 5395 } 5396 5397 } 5398 } 5399 return BCM_E_NONE; 5400 } 5401 5402 STATIC int 5403 _bcm_tr3_cosq_dyn_move_queue(int unit, bcm_port_t local_port, 5404 int cosq, int *l2_index, int numl2, 5405 int from_sched_idx, int to_sched_index) 5406 { 5407 lls_l2_parent_entry_t l2p[2]; 5408 mmu_mtro_l2_mem_entry_t mtro[2], tmp_mtro; 5409 mmu_mtro_l1_mem_entry_t l1mtro, l1mtro_tmp; 5410 lls_l2_child_state1_entry_t l2cse; 5411 lls_l1_parent_state_entry_t l1pe_old; 5412 int ii, empty_count, actives[2], sync; 5413 uint32 rval; 5414 int rv = BCM_E_NONE; 5415 soc_timeout_t timeout; 5416 uint32 timeout_val; 5417 int rcnt = 0; 5418 5419 timeout_val = soc_property_get(unit, spn_MMU_QUEUE_FLUSH_TIMEOUT, 2000000); 5420 5421 for (ii = 0; ii < numl2; ii++) { 5422 SOC_IF_ERROR_RETURN(READ_MMU_MTRO_L2_MEMm(unit, MEM_BLOCK_ANY, 5423 l2_index[ii], &mtro[ii])); 5424 /* configure max shaper */ 5425 /* coverity[suspicious_sizeof:FALSE] */ 5426 sal_memset(&tmp_mtro, 0, sizeof(mmu_mtro_l2_mem_entry_t)); 5427 soc_mem_field32_set(unit, MMU_MTRO_L2_MEMm, &tmp_mtro, MAX_METER_GRANf, 0); 5428 soc_mem_field32_set(unit, MMU_MTRO_L2_MEMm, &tmp_mtro, MAX_THD_SELf, 1); 5429 soc_mem_field32_set(unit, MMU_MTRO_L2_MEMm, &tmp_mtro, MAX_REFRESHf, 0); 5430 SOC_IF_ERROR_RETURN(WRITE_MMU_MTRO_L2_MEMm(unit, MEM_BLOCK_ANY, 5431 l2_index[ii], &tmp_mtro)); 5432 /* cache the L2 parent mem. */ 5433 SOC_IF_ERROR_RETURN(READ_LLS_L2_PARENTm(unit, MEM_BLOCK_ANY, 5434 l2_index[ii], &l2p[ii])); 5435 soc_mem_field32_set(unit, LLS_L2_PARENTm, &l2p[ii], C_PARENTf, to_sched_index); 5436 } 5437 5438 /* give l1 a small min guarantee */ 5439 SOC_IF_ERROR_RETURN(READ_MMU_MTRO_L1_MEMm(unit, MEM_BLOCK_ANY, 5440 from_sched_idx, &l1mtro)); 5441 sal_memset(&l1mtro_tmp, 0, sizeof(sizeof(mmu_mtro_l1_mem_entry_t))); 5442 soc_mem_field32_set(unit, MMU_MTRO_L1_MEMm, &l1mtro_tmp, MIN_METER_GRANf, 3); 5443 soc_mem_field32_set(unit, MMU_MTRO_L1_MEMm, &l1mtro_tmp, MIN_THD_SELf, 64); 5444 soc_mem_field32_set(unit, MMU_MTRO_L1_MEMm, &l1mtro_tmp, MIN_REFRESHf, 15625); 5445 SOC_IF_ERROR_RETURN(WRITE_MMU_MTRO_L1_MEMm(unit, MEM_BLOCK_ANY, 5446 from_sched_idx, &l1mtro_tmp)); 5447 5448 soc_timeout_init(&timeout, timeout_val, 0); 5449 5450 do { 5451 empty_count = 0; 5452 if (soc_timeout_check(&timeout)) { 5453 LOG_ERROR(BSL_LS_BCM_COMMON, 5454 (BSL_META_U(unit, 5455 "ERROR: timeout on L2 child c_on_active_list not zero (read count=%d)\n"), 5456 rcnt)); 5457 rv = BCM_E_BUSY; 5458 goto failed; 5459 } 5460 for (empty_count = 0, ii = 0; ii < numl2; ii++) { 5461 rcnt += 1; 5462 SOC_IF_ERROR_RETURN(READ_LLS_L2_CHILD_STATE1m(unit, 5463 MEM_BLOCK_ANY, l2_index[ii], &l2cse)); 5464 if (soc_mem_field32_get(unit, LLS_L2_CHILD_STATE1m, &l2cse, 5465 C_ON_ACTIVE_LISTf)==0) { 5466 empty_count += 1; 5467 } else { 5468 break; 5469 } 5470 } 5471 } while (empty_count != numl2); 5472 5473 /* change the parent */ 5474 for (ii = 0; ii < numl2; ii++) { 5475 SOC_IF_ERROR_RETURN( 5476 WRITE_LLS_L2_PARENTm(unit, MEM_BLOCK_ANY, l2_index[ii], &l2p[ii])); 5477 } 5478 5479 for (empty_count = 0, ii = 0; ii < numl2; ii++) { 5480 SOC_IF_ERROR_RETURN(READ_LLS_L2_CHILD_STATE1m(unit, 5481 MEM_BLOCK_ANY, l2_index[ii], &l2cse)); 5482 actives[ii] = 0; 5483 if (soc_mem_field32_get(unit, LLS_L2_CHILD_STATE1m, &l2cse, 5484 C_ON_ACTIVE_LISTf)==0) { 5485 empty_count += 1; 5486 } else { 5487 actives[ii] = 1; 5488 } 5489 } 5490 5491 sync = 0; 5492 if (empty_count != numl2) { 5493 for (ii = 0; ii < numl2; ii++) { 5494 if (actives[ii] == 0) { 5495 continue; 5496 } 5497 SOC_IF_ERROR_RETURN(READ_LLS_L1_PARENT_STATEm(unit, 5498 MEM_BLOCK_ANY, from_sched_idx, &l1pe_old)); 5499 if ((soc_mem_field32_get(unit, LLS_L1_PARENT_STATEm, &l1pe_old, 5500 P_WRR_0_NOT_EMPTYf)) || 5501 (soc_mem_field32_get(unit, LLS_L1_PARENT_STATEm, &l1pe_old, 5502 P_WRR_1_NOT_EMPTYf))) { 5503 sync = 1; 5504 } 5505 } 5506 } 5507 5508 if (sync) { 5509 empty_count = 0; 5510 soc_timeout_init(&timeout, timeout_val, 0); 5511 while (empty_count != numl2) { 5512 if (soc_timeout_check(&timeout)) { 5513 rv = BCM_E_BUSY; 5514 break; 5515 } 5516 for (empty_count = 0, ii = 0; ii < numl2; ii++) { 5517 SOC_IF_ERROR_RETURN(READ_LLS_L2_CHILD_STATE1m(unit, 5518 MEM_BLOCK_ANY, l2_index[ii], &l2cse)); 5519 if (soc_mem_field32_get(unit, LLS_L2_CHILD_STATE1m, &l2cse, 5520 C_ON_ACTIVE_LISTf)==0) { 5521 empty_count += 1; 5522 } else { 5523 break; 5524 } 5525 } 5526 } 5527 } 5528 5529 failed: 5530 for (ii = 0; ii < numl2; ii++) { 5531 SOC_IF_ERROR_RETURN(WRITE_MMU_MTRO_L2_MEMm(unit, MEM_BLOCK_ANY, 5532 l2_index[ii], &mtro[ii])); 5533 } 5534 5535 if (!rv) { 5536 for (ii = 0; ii < numl2; ii++) { 5537 rval = 0; 5538 soc_reg_field_set(unit, LLS_DEBUG_INJECT_ACTIVATIONr, &rval, INJECTf, 1); 5539 soc_reg_field_set(unit, LLS_DEBUG_INJECT_ACTIVATIONr, &rval, ENTITY_TYPEf, 1); 5540 soc_reg_field_set(unit, LLS_DEBUG_INJECT_ACTIVATIONr, &rval, ENTITY_LEVELf, 3); 5541 soc_reg_field_set(unit, LLS_DEBUG_INJECT_ACTIVATIONr, &rval, 5542 ENTITY_IDENTIFIERf, l2_index[ii]); 5543 SOC_IF_ERROR_RETURN(WRITE_LLS_DEBUG_INJECT_ACTIVATIONr(unit, rval)); 5544 } 5545 } 5546 5547 SOC_IF_ERROR_RETURN(WRITE_MMU_MTRO_L1_MEMm(unit, MEM_BLOCK_ANY, 5548 from_sched_idx, &l1mtro)); 5549 return rv; 5550 } 5551 5552 typedef struct _bcm_tr3_lls_info_s { 5553 int child_lvl; 5554 int child_hw_index; 5555 int node_count[SOC_TR3_NODE_LVL_MAX]; 5556 int count[SOC_TR3_NODE_LVL_MAX]; 5557 int offset[SOC_TR3_NODE_LVL_MAX]; 5558 5559 int kbit_max; 5560 int kbit_min; 5561 5562 uint32 *mtro_entries; 5563 } _bcm_tr3_lls_info_t; 5564 5565 STATIC int _bcm_tr3_lls_node_count(int unit, int port, int level, 5566 int hw_index, void *cookie) 5567 { 5568 _bcm_tr3_lls_info_t *i_lls_tree = (_bcm_tr3_lls_info_t *) cookie; 5569 i_lls_tree->node_count[level] += 1; 5570 return 0; 5571 } 5572 5573 STATIC int _bcm_tr3_lls_shapers_remove(int unit, int port, int level, 5574 int hw_index, void *cookie) 5575 { 5576 _bcm_tr3_lls_info_t *i_lls_tree = (_bcm_tr3_lls_info_t *) cookie; 5577 soc_mem_t config_mem; 5578 uint32 *p_entry; 5579 uint32 entry[SOC_MAX_MEM_WORDS]; 5580 int index, kbit_max; 5581 uint32 meter_flags; 5582 uint32 bucketsize_max, granularity_max, refresh_rate_max, 5583 refresh_bitsize = 0, bucket_bitsize = 0; 5584 5585 if (level == SOC_TR3_NODE_LVL_ROOT) { 5586 return SOC_E_NONE; 5587 } else if (level == SOC_TR3_NODE_LVL_L0) { 5588 config_mem = MMU_MTRO_L0_MEMm; 5589 } else if (level == SOC_TR3_NODE_LVL_L1) { 5590 config_mem = MMU_MTRO_L1_MEMm; 5591 } else if (level == SOC_TR3_NODE_LVL_L2) { 5592 config_mem = MMU_MTRO_L2_MEMm; 5593 } else { 5594 return SOC_E_PARAM; 5595 } 5596 5597 index = i_lls_tree->offset[level] + i_lls_tree->count[level]; 5598 p_entry = &i_lls_tree->mtro_entries[index * SOC_MAX_MEM_WORDS]; 5599 5600 SOC_IF_ERROR_RETURN(soc_mem_read(unit, config_mem, MEM_BLOCK_ALL, hw_index, 5601 p_entry)); 5602 5603 sal_memset(entry, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS); 5604 5605 if ((i_lls_tree->child_lvl == level) && 5606 (hw_index != i_lls_tree->child_hw_index)) { 5607 5608 meter_flags = 0; 5609 5610 kbit_max = i_lls_tree->kbit_max; 5611 refresh_bitsize = soc_mem_field_length(unit, config_mem, MAX_REFRESHf); 5612 bucket_bitsize = soc_mem_field_length(unit, config_mem, MAX_THD_SELf); 5613 5614 BCM_IF_ERROR_RETURN 5615 (_bcm_td_rate_to_bucket_encoding(unit, kbit_max, kbit_max, 5616 meter_flags, refresh_bitsize, 5617 bucket_bitsize, &refresh_rate_max, 5618 &bucketsize_max, &granularity_max)); 5619 5620 sal_memset(entry, 0, sizeof(uint32)*SOC_MAX_MEM_WORDS); 5621 soc_mem_field32_set(unit, config_mem, &entry, MAX_METER_GRANf, granularity_max); 5622 soc_mem_field32_set(unit, config_mem, &entry, MAX_REFRESHf, refresh_rate_max); 5623 soc_mem_field32_set(unit, config_mem, &entry, MAX_THD_SELf, bucketsize_max); 5624 5625 BCM_IF_ERROR_RETURN 5626 (soc_mem_write(unit, config_mem, MEM_BLOCK_ALL, hw_index, &entry)); 5627 5628 } else { 5629 SOC_IF_ERROR_RETURN(soc_mem_write(unit, config_mem, MEM_BLOCK_ALL, 5630 hw_index, &entry)); 5631 } 5632 5633 i_lls_tree->count[level] += 1; 5634 5635 return 0; 5636 } 5637 5638 STATIC int _bcm_tr3_lls_shapers_restore(int unit, int port, int level, 5639 int hw_index, void *cookie) 5640 { 5641 _bcm_tr3_lls_info_t *i_lls_tree = (_bcm_tr3_lls_info_t *) cookie; 5642 soc_mem_t config_mem; 5643 uint32 *p_entry; 5644 int index; 5645 5646 if (level == SOC_TR3_NODE_LVL_ROOT) { 5647 return SOC_E_NONE; 5648 } else if (level == SOC_TR3_NODE_LVL_L0) { 5649 config_mem = MMU_MTRO_L0_MEMm; 5650 } else if (level == SOC_TR3_NODE_LVL_L1) { 5651 config_mem = MMU_MTRO_L1_MEMm; 5652 } else if (level == SOC_TR3_NODE_LVL_L2) { 5653 config_mem = MMU_MTRO_L2_MEMm; 5654 } else { 5655 return SOC_E_PARAM; 5656 } 5657 5658 index = i_lls_tree->offset[level] + i_lls_tree->count[level]; 5659 p_entry = &i_lls_tree->mtro_entries[index * SOC_MAX_MEM_WORDS]; 5660 5661 SOC_IF_ERROR_RETURN(soc_mem_write(unit, config_mem, MEM_BLOCK_ALL, 5662 hw_index, p_entry)); 5663 5664 i_lls_tree->count[level] += 1; 5665 5666 return 0; 5667 } 5668 5669 STATIC int 5670 _bcm_tr3_adjust_lls_bw(int unit, bcm_port_t port, _bcm_tr3_cosq_node_t *node, 5671 int child_lvl, int child_hw_index, int start, 5672 _bcm_tr3_lls_info_t *i_lls_tree) 5673 { 5674 int rv = BCM_E_NONE, count, mem_size, ii, speed, jj; 5675 soc_info_t *si; 5676 5677 if (!soc_feature(unit, soc_feature_tr3_sp_vector_mask)) { 5678 return BCM_E_NONE; 5679 } 5680 5681 if (start) { 5682 sal_memset(i_lls_tree, 0, sizeof(_bcm_tr3_lls_info_t)); 5683 5684 i_lls_tree->child_lvl = child_lvl; 5685 i_lls_tree->child_hw_index = child_hw_index; 5686 5687 if (node) { 5688 5689 /* get to top node */ 5690 while(node->parent) { node = node->parent; } 5691 5692 if ((rv = _bcm_tr3_cosq_traverse_lls_tree(unit, port, node, 5693 _bcm_tr3_lls_node_count, i_lls_tree))) { 5694 goto error; 5695 } 5696 } else { 5697 if ((rv = soc_tr3_port_lls_traverse(unit, port, 5698 _bcm_tr3_lls_node_count, i_lls_tree))) { 5699 goto error; 5700 } 5701 } 5702 5703 for (count = 0, ii = 0; ii < SOC_TR3_NODE_LVL_MAX; ii++) { 5704 count += i_lls_tree->node_count[ii]; 5705 for (jj = ii - 1; jj >= 0; jj--) { 5706 i_lls_tree->offset[ii] += i_lls_tree->node_count[jj]; 5707 } 5708 } 5709 5710 if (count == 0) { 5711 return BCM_E_INIT; 5712 } 5713 5714 mem_size = sizeof(uint32)*SOC_MAX_MEM_WORDS*count; 5715 i_lls_tree->mtro_entries = sal_alloc(mem_size, "lls_war_buf"); 5716 5717 rv = soc_phyctrl_speed_get(unit, port, &speed); 5718 if (rv == BCM_E_UNAVAIL) { 5719 si = &SOC_INFO(unit); 5720 speed = si->port_speed_max[port]; 5721 } 5722 5723 i_lls_tree->kbit_min = 0; 5724 i_lls_tree->kbit_max = ((speed * 9)/10)/i_lls_tree->node_count[child_lvl]; 5725 5726 for (count = 0, ii = 0; ii < SOC_TR3_NODE_LVL_MAX; ii++) { 5727 i_lls_tree->count[ii] = 0; 5728 } 5729 5730 sal_memset(i_lls_tree->mtro_entries, 0, mem_size); 5731 5732 if (node) { 5733 5734 /* get to top node */ 5735 while(node->parent) { node = node->parent; } 5736 5737 if ((rv = _bcm_tr3_cosq_traverse_lls_tree(unit, port, node, 5738 _bcm_tr3_lls_shapers_remove, i_lls_tree))) { 5739 goto error; 5740 } 5741 } else { 5742 if ((rv = soc_tr3_port_lls_traverse(unit, port, 5743 _bcm_tr3_lls_shapers_remove, i_lls_tree))) { 5744 goto error; 5745 } 5746 } 5747 5748 } else { 5749 for (count = 0, ii = 0; ii < SOC_TR3_NODE_LVL_MAX; ii++) { 5750 i_lls_tree->count[ii] = 0; 5751 } 5752 5753 if (node) { 5754 /* get to top node */ 5755 while(node->parent) { node = node->parent; } 5756 5757 if ((rv = _bcm_tr3_cosq_traverse_lls_tree(unit, port, node, 5758 _bcm_tr3_lls_shapers_restore, i_lls_tree))) { 5759 goto error; 5760 } 5761 } else { 5762 if ((rv = soc_tr3_port_lls_traverse(unit, port, 5763 _bcm_tr3_lls_shapers_restore, i_lls_tree))) { 5764 goto error; 5765 } 5766 } 5767 5768 /* cleanup */ 5769 if (i_lls_tree->mtro_entries) { 5770 sal_free(i_lls_tree->mtro_entries); 5771 i_lls_tree->mtro_entries = NULL; 5772 } 5773 } 5774 5775 return BCM_E_NONE; 5776 5777 error: 5778 /* cleanup */ 5779 if (i_lls_tree->mtro_entries) { 5780 sal_free(i_lls_tree->mtro_entries); 5781 i_lls_tree->mtro_entries = NULL; 5782 } 5783 5784 return rv; 5785 } 5786 5787 STATIC int 5788 _bcm_tr3_cosq_sched_parent_child_set(int unit, int port, int level, 5789 int sched_index, int child_index, 5790 soc_tr3_sched_mode_e sched_mode, 5791 int weight) 5792 { 5793 int wt, rv = BCM_E_NONE, num_spri, first_sp_child, first_sp_mc_child; 5794 uint32 ucmap = 0, spmap = 0, mmu_cells = 0, rval; 5795 soc_tr3_sched_mode_e cur_sched_mode; 5796 _bcm_tr3_lls_info_t lls_tree_info; 5797 5798 SOC_IF_ERROR_RETURN(READ_OP_PORT_TOTAL_COUNT_CELLr(unit, port, &rval)); 5799 mmu_cells = soc_reg_field_get(unit, OP_PORT_TOTAL_COUNT_CELLr, rval, 5800 TOTAL_COUNTf); 5801 BCM_IF_ERROR_RETURN(soc_tr3_cosq_get_sched_config(unit, 5802 port, 5803 level, 5804 sched_index, 5805 child_index, 5806 &num_spri, 5807 &first_sp_child, 5808 &first_sp_mc_child, 5809 &ucmap, 5810 &spmap, 5811 &cur_sched_mode, 5812 &wt)); 5813 5814 if (_bcm_tr3_compute_lls_config(unit, port, 5815 level, 5816 &first_sp_child, 5817 &first_sp_mc_child, 5818 &num_spri, 5819 &ucmap, 5820 &spmap, 5821 child_index, 5822 cur_sched_mode, 5823 sched_mode)) { 5824 return BCM_E_UNAVAIL; 5825 } 5826 if (mmu_cells) { 5827 SOC_EGRESS_METERING_LOCK(unit); 5828 if ((rv = _bcm_tr3_adjust_lls_bw(unit, port, NULL, 5829 level + 1, child_index, 1, &lls_tree_info))) { 5830 SOC_EGRESS_METERING_UNLOCK(unit); 5831 goto error; 5832 } 5833 SOC_EGRESS_METERING_UNLOCK(unit); 5834 } 5835 if ((rv = soc_tr3_cosq_set_sched_config(unit, port, level, 5836 sched_index, child_index, num_spri, first_sp_child, 5837 first_sp_mc_child, ucmap, spmap, sched_mode, weight))) { 5838 goto error; 5839 } 5840 5841 error: 5842 if (mmu_cells) { 5843 SOC_EGRESS_METERING_LOCK(unit); 5844 rv = _bcm_tr3_adjust_lls_bw(unit, port, NULL, 5845 level + 1, child_index, 0, &lls_tree_info); 5846 SOC_EGRESS_METERING_UNLOCK(unit); 5847 } 5848 return rv; 5849 } 5850 5851 /* 5852 * Function: 5853 * _bcm_tr3_cosq_sched_set 5854 * Purpose: 5855 * Set scheduling mode 5856 * Parameters: 5857 * unit - (IN) unit number 5858 * port - (IN) port number or GPORT identifier 5859 * cosq - (IN) COS queue number 5860 * mode - (IN) scheduling mode (BCM_COSQ_XXX) 5861 * num_weights - (IN) number of entries in weights array 5862 * weights - (IN) weights array 5863 * Returns: 5864 * BCM_E_XXX 5865 */ 5866 STATIC int 5867 _bcm_tr3_cosq_sched_set(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 5868 int mode, int weight, int adjust_cos) 5869 { 5870 _bcm_tr3_cosq_node_t *node = NULL, *child_node; 5871 bcm_port_t local_port; 5872 int sch_index, lvl = SOC_TR3_NODE_LVL_L0, child_index; 5873 /* , root_index; */ 5874 int numq, lwts = 1, to_sched_index, cpu_l0_index, cpu_l1_index; 5875 soc_tr3_sched_mode_e sched_mode; 5876 int l2_index[2], l1_base, l0_base, ii, rv, lvl_off; 5877 uint32 entry[SOC_MAX_MEM_WORDS]; 5878 mmu_mtro_l1_mem_entry_t l1mtro[16], l1mtro_tmp; 5879 mmu_mtro_l1_mem_entry_t l0mtro; 5880 uint64 egrm, tmp64; 5881 5882 if (cosq < 0) { 5883 if (cosq == -1) { 5884 /* caller needs to resolve the wild card value (-1) */ 5885 return BCM_E_INTERNAL; 5886 } else { /* reject all other negative value */ 5887 return BCM_E_PARAM; 5888 } 5889 } 5890 5891 if ((weight < 0) || (weight > 127)) { 5892 return BCM_E_PARAM; 5893 } 5894 5895 switch(mode) { 5896 case BCM_COSQ_STRICT: 5897 sched_mode = SOC_TR3_SCHED_MODE_STRICT; 5898 break; 5899 case BCM_COSQ_ROUND_ROBIN: 5900 sched_mode = SOC_TR3_SCHED_MODE_WRR; 5901 lwts = 1; 5902 break; 5903 case BCM_COSQ_WEIGHTED_ROUND_ROBIN: 5904 if (soc_property_get(unit, spn_BCM5664X_WRR_GRANULARITY_1, 0)) { 5905 if (weight == 1) { 5906 return BCM_E_PARAM; 5907 } 5908 } else if (weight > 63) { 5909 return BCM_E_PARAM; 5910 } 5911 sched_mode = SOC_TR3_SCHED_MODE_WRR; 5912 lwts = weight; 5913 break; 5914 case BCM_COSQ_DEFICIT_ROUND_ROBIN: 5915 sched_mode = SOC_TR3_SCHED_MODE_WDRR; 5916 lwts = weight; 5917 break; 5918 default: 5919 return BCM_E_PARAM; 5920 } 5921 5922 if (lwts == 0) { 5923 /* On weight 0 it should be considered as SP */ 5924 sched_mode = SOC_TR3_SCHED_MODE_STRICT; 5925 } 5926 5927 BCM_IF_ERROR_RETURN 5928 (_bcm_tr3_cosq_localport_resolve(unit, port, &local_port)); 5929 5930 if (IS_TR3_HSP_PORT(unit, local_port)) { 5931 /* If port is set as gport get the node and configure sched */ 5932 if (BCM_GPORT_IS_SET(port)) { 5933 5934 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_node_get(unit, port, 5935 0, NULL, &local_port, NULL, &node)); 5936 lvl = node->level; 5937 if (lvl >= SOC_TR3_NODE_LVL_L1) { 5938 return BCM_E_PARAM; 5939 } 5940 if (lvl == SOC_TR3_NODE_LVL_L0) { 5941 BCM_IF_ERROR_RETURN( 5942 _soc_tr3_hsp_sched_weight_set(unit, local_port, 5943 node->attached_to_input, cosq, lwts)); 5944 BCM_IF_ERROR_RETURN( 5945 _soc_tr3_hsp_set_sched_config(unit, local_port, 5946 node->attached_to_input, cosq, sched_mode)); 5947 } else { 5948 if (cosq >= _TR3_NUM_HSP_COSQ) { 5949 return BCM_E_PARAM; 5950 } 5951 BCM_IF_ERROR_RETURN( 5952 soc_tr3_hsp_sched_weight_set(unit, local_port, cosq, lwts, adjust_cos)); 5953 BCM_IF_ERROR_RETURN( 5954 soc_tr3_hsp_set_sched_config(unit, local_port, cosq, sched_mode, adjust_cos)); 5955 } 5956 } else { 5957 if (cosq >= _TR3_NUM_HSP_COSQ) { 5958 return BCM_E_PARAM; 5959 } 5960 BCM_IF_ERROR_RETURN( 5961 soc_tr3_hsp_sched_weight_set(unit, local_port, cosq, lwts, adjust_cos)); 5962 BCM_IF_ERROR_RETURN( 5963 soc_tr3_hsp_set_sched_config(unit, local_port, cosq, sched_mode, adjust_cos)); 5964 } 5965 return BCM_E_NONE; 5966 } 5967 5968 if (_bcm_tr3_cosq_port_has_ets(unit, local_port)) { 5969 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_node_get(unit, port, 5970 0, NULL, &local_port, NULL, &node)); 5971 lvl = node->level; 5972 numq = node->numq; 5973 sch_index = node->hw_index; 5974 5975 if ((node->numq > 0) && (cosq >= node->numq)) { 5976 return BCM_E_PARAM; 5977 } 5978 5979 BCM_IF_ERROR_RETURN( 5980 _bcm_tr3_cosq_child_node_at_input(node, cosq, &child_node)); 5981 child_index = child_node->hw_index; 5982 5983 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_sched_parent_child_set(unit, 5984 local_port, node->level, node->hw_index, 5985 child_node->hw_index, sched_mode, lwts)); 5986 } else { 5987 numq = IS_CPU_PORT(unit, local_port) ? 5988 SOC_INFO(unit).num_cpu_cosq : _TR3_NUM_COS(unit); 5989 5990 if (cosq >= numq) { 5991 return BCM_E_PARAM; 5992 } 5993 5994 if (!IS_CPU_PORT(unit, local_port) && 5995 (!soc_feature(unit, soc_feature_tr3_sp_vector_mask) && 5996 soc_property_port_get(unit, local_port, spn_PORT_SCHED_DYNAMIC, 0))) { 5997 5998 BCM_IF_ERROR_RETURN( 5999 _bcm_tr3_cosq_index_resolve(unit, local_port, cosq, 6000 _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE, NULL, &l2_index[0], NULL)); 6001 6002 BCM_IF_ERROR_RETURN( 6003 _bcm_tr3_cosq_index_resolve(unit, local_port, cosq, 6004 _BCM_TR3_COSQ_INDEX_STYLE_MCAST_QUEUE, NULL, &l2_index[1], NULL)); 6005 6006 BCM_IF_ERROR_RETURN(soc_tr3_sched_hw_index_get(unit, local_port, 6007 SOC_TR3_NODE_LVL_L1, 6008 cosq, &to_sched_index)); 6009 6010 if (sched_mode == SOC_TR3_SCHED_MODE_STRICT) { 6011 to_sched_index += soc_port_hg_capable(unit, local_port) ? 9 : 8; 6012 } 6013 6014 /* current parent */ 6015 SOC_IF_ERROR_RETURN(READ_LLS_L2_PARENTm(unit, MEM_BLOCK_ANY, 6016 l2_index[0], entry)); 6017 sch_index = soc_mem_field32_get(unit, LLS_L2_PARENTm, entry, C_PARENTf); 6018 6019 if (sch_index != to_sched_index) { 6020 SOC_IF_ERROR_RETURN(READ_EGRMETERINGCONFIG_64r(unit, local_port, &egrm)); 6021 COMPILER_64_ZERO(tmp64); 6022 SOC_IF_ERROR_RETURN(WRITE_EGRMETERINGCONFIG_64r(unit, local_port, tmp64)); 6023 sal_memset(&l1mtro_tmp, 0, sizeof(l1mtro_tmp)); 6024 BCM_IF_ERROR_RETURN(soc_tr3_sched_hw_index_get(unit, local_port, 6025 SOC_TR3_NODE_LVL_L0, 6026 0, &l0_base)); 6027 SOC_EGRESS_METERING_LOCK(unit); 6028 rv = READ_MMU_MTRO_L0_MEMm(unit, MEM_BLOCK_ANY, 6029 l0_base, &l0mtro); 6030 if (BCM_FAILURE(rv)) { 6031 SOC_EGRESS_METERING_UNLOCK(unit); 6032 return rv; 6033 } 6034 rv = WRITE_MMU_MTRO_L0_MEMm(unit, MEM_BLOCK_ANY, 6035 l0_base, &l1mtro_tmp); 6036 if (BCM_FAILURE(rv)) { 6037 SOC_EGRESS_METERING_UNLOCK(unit); 6038 return rv; 6039 } 6040 SOC_EGRESS_METERING_UNLOCK(unit); 6041 6042 BCM_IF_ERROR_RETURN(soc_tr3_sched_hw_index_get(unit, local_port, 6043 SOC_TR3_NODE_LVL_L1, 6044 0, &l1_base)); 6045 for (ii = 0; ii < 16; ii++) { 6046 SOC_EGRESS_METERING_LOCK(unit); 6047 rv = READ_MMU_MTRO_L1_MEMm(unit, MEM_BLOCK_ANY, 6048 l1_base + ii, &l1mtro[ii]); 6049 if (BCM_FAILURE(rv)) { 6050 SOC_EGRESS_METERING_UNLOCK(unit); 6051 return rv; 6052 } 6053 rv = WRITE_MMU_MTRO_L1_MEMm(unit, MEM_BLOCK_ANY, l1_base + ii, 6054 &l1mtro_tmp); 6055 if (BCM_FAILURE(rv)) { 6056 SOC_EGRESS_METERING_UNLOCK(unit); 6057 return rv; 6058 } 6059 SOC_EGRESS_METERING_UNLOCK(unit); 6060 } 6061 SOC_EGRESS_METERING_LOCK(unit); 6062 rv = _bcm_tr3_cosq_dyn_move_queue(unit, local_port, cosq, 6063 l2_index, 2, sch_index, to_sched_index); 6064 SOC_EGRESS_METERING_UNLOCK(unit); 6065 /* restore l1 mtros */ 6066 for (ii = 0; ii < 16; ii++) { 6067 SOC_IF_ERROR_RETURN(WRITE_MMU_MTRO_L1_MEMm(unit, MEM_BLOCK_ANY, l1_base + ii, 6068 &l1mtro[ii])); 6069 } 6070 6071 SOC_IF_ERROR_RETURN(WRITE_MMU_MTRO_L0_MEMm(unit, MEM_BLOCK_ANY, 6072 l0_base, &l0mtro)); 6073 6074 SOC_IF_ERROR_RETURN(WRITE_EGRMETERINGCONFIG_64r(unit, local_port, egrm)); 6075 6076 if (rv) { 6077 return rv; 6078 } 6079 } 6080 6081 if (sched_mode != SOC_TR3_SCHED_MODE_STRICT) { 6082 SOC_IF_ERROR_RETURN(soc_tr3_cosq_set_sched_mode(unit, 6083 local_port, SOC_TR3_NODE_LVL_L1, to_sched_index, 6084 sched_mode, lwts)); 6085 } 6086 6087 return SOC_E_NONE; 6088 } else { 6089 if (IS_CPU_PORT(unit, local_port)) { 6090 /* set the L0.0 index as parent, L0.(cosq/8) as child in 6091 * schduling mode */ 6092 BCM_IF_ERROR_RETURN(soc_tr3_sched_hw_index_get(unit, local_port, 6093 SOC_TR3_NODE_LVL_L0, 0, &cpu_l0_index)); 6094 BCM_IF_ERROR_RETURN(soc_tr3_sched_hw_index_get(unit, local_port, 6095 SOC_TR3_NODE_LVL_L1, cosq/8, &cpu_l1_index)); 6096 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_sched_parent_child_set(unit, 6097 local_port, SOC_TR3_NODE_LVL_L0, cpu_l0_index, 6098 cpu_l1_index, sched_mode, 1)); 6099 } 6100 6101 lvl_off = cosq/8; 6102 lvl = IS_CPU_PORT(unit, local_port) ? 6103 SOC_TR3_NODE_LVL_L1 : SOC_TR3_NODE_LVL_L0; 6104 6105 BCM_IF_ERROR_RETURN(soc_tr3_sched_hw_index_get(unit, local_port, 6106 lvl, lvl_off, &sch_index)); 6107 6108 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_index_resolve(unit, local_port, cosq, 6109 _BCM_TR3_COSQ_INDEX_STYLE_SCHEDULER, NULL, &child_index, NULL)); 6110 6111 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_sched_parent_child_set(unit, 6112 local_port, lvl, sch_index, child_index, sched_mode, lwts)); 6113 } 6114 } 6115 6116 return BCM_E_NONE; 6117 } 6118 6119 /* 6120 * Function: 6121 * _bcm_tr3_cosq_sched_get 6122 * Purpose: 6123 * Get scheduling mode setting 6124 * Parameters: 6125 * unit - (IN) unit number 6126 * port - (IN) port number or GPORT identifier 6127 * cosq - (IN) COS queue number 6128 * mode - (OUT) scheduling mode (BCM_COSQ_XXX) 6129 * num_weights - (IN) number of entries in weights array 6130 * weights - (OUT) weights array 6131 * Returns: 6132 * BCM_E_XXX 6133 */ 6134 STATIC int 6135 _bcm_tr3_cosq_sched_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 6136 int *mode, int *weight) 6137 { 6138 _bcm_tr3_cosq_node_t *node, *child_node; 6139 bcm_port_t local_port; 6140 int sch_index, lvl = SOC_TR3_NODE_LVL_L1, numq; 6141 int child_index; 6142 soc_tr3_sched_mode_e sched_mode; 6143 _bcm_tr3_mmu_info_t *mmu_info; 6144 lls_l2_parent_entry_t l2pe; 6145 6146 if ((mmu_info = _bcm_tr3_mmu_info[unit]) == NULL) { 6147 return BCM_E_INIT; 6148 } 6149 6150 if (cosq < 0) { 6151 if (cosq == -1) { 6152 /* caller needs to resolve the wild card value (-1) */ 6153 return BCM_E_INTERNAL; 6154 } else { /* reject all other negative value */ 6155 return BCM_E_PARAM; 6156 } 6157 } 6158 6159 BCM_IF_ERROR_RETURN 6160 (_bcm_tr3_cosq_localport_resolve(unit, port, &local_port)); 6161 6162 if (IS_TR3_HSP_PORT(unit, local_port)) { 6163 if (cosq >= _TR3_NUM_HSP_COSQ) { 6164 return BCM_E_PARAM; 6165 } 6166 /* Check if port is set as gport */ 6167 if (BCM_GPORT_IS_SET(port)) { 6168 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_node_get(unit, port, 6169 0, NULL, &local_port, NULL, &node)); 6170 lvl = node->level; 6171 if (lvl >= SOC_TR3_NODE_LVL_L1) { 6172 return BCM_E_PARAM; 6173 } 6174 if (lvl == SOC_TR3_NODE_LVL_L0) { 6175 BCM_IF_ERROR_RETURN( 6176 _soc_tr3_hsp_sched_weight_get(unit, local_port, 6177 node->attached_to_input, cosq, weight)); 6178 BCM_IF_ERROR_RETURN( 6179 _soc_tr3_hsp_get_sched_config(unit, local_port, 6180 node->attached_to_input, cosq, &sched_mode)); 6181 } else { 6182 BCM_IF_ERROR_RETURN( 6183 soc_tr3_hsp_sched_weight_get(unit, local_port, cosq, weight)); 6184 BCM_IF_ERROR_RETURN( 6185 soc_tr3_hsp_get_sched_config(unit, local_port, cosq, &sched_mode)); 6186 } 6187 } else { 6188 BCM_IF_ERROR_RETURN( 6189 soc_tr3_hsp_sched_weight_get(unit, local_port, cosq, weight)); 6190 BCM_IF_ERROR_RETURN( 6191 soc_tr3_hsp_get_sched_config(unit, local_port, cosq, &sched_mode)); 6192 } 6193 switch (sched_mode) { 6194 case SOC_TR3_SCHED_MODE_STRICT: 6195 *mode = BCM_COSQ_STRICT; 6196 break; 6197 case SOC_TR3_SCHED_MODE_WRR: 6198 *mode = BCM_COSQ_WEIGHTED_ROUND_ROBIN; 6199 break; 6200 case SOC_TR3_SCHED_MODE_WDRR: 6201 *mode = BCM_COSQ_DEFICIT_ROUND_ROBIN; 6202 break; 6203 default: 6204 return BCM_E_INTERNAL; 6205 } 6206 return BCM_E_NONE; 6207 } 6208 6209 if (_bcm_tr3_cosq_port_has_ets(unit, local_port) && BCM_GPORT_IS_SET(port)) { 6210 BCM_IF_ERROR_RETURN 6211 (_bcm_tr3_cosq_node_get(unit, port, 0, NULL, &local_port, NULL, &node)); 6212 sch_index = node->hw_index; 6213 numq = node->numq; 6214 6215 if ((numq > 0) && (cosq >= numq)) { 6216 return BCM_E_PARAM; 6217 } 6218 6219 BCM_IF_ERROR_RETURN( 6220 _bcm_tr3_cosq_child_node_at_input(node, cosq, &child_node)); 6221 lvl = child_node->level; 6222 sch_index = child_node->hw_index; 6223 } else { 6224 numq = (IS_CPU_PORT(unit, local_port)) ? SOC_INFO(unit).num_cpu_cosq : _TR3_NUM_COS(unit); 6225 6226 if (cosq >= numq) { 6227 return BCM_E_PARAM; 6228 } 6229 6230 if (!IS_CPU_PORT(unit, local_port) && 6231 (!soc_feature(unit, soc_feature_tr3_sp_vector_mask) && 6232 soc_property_port_get(unit, local_port, spn_PORT_SCHED_DYNAMIC, 0))) { 6233 6234 BCM_IF_ERROR_RETURN( 6235 _bcm_tr3_cosq_index_resolve(unit, local_port, cosq, 6236 _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE, NULL, &child_index, NULL)); 6237 6238 SOC_IF_ERROR_RETURN(READ_LLS_L2_PARENTm(unit, MEM_BLOCK_ANY, 6239 child_index, &l2pe)); 6240 sch_index = soc_mem_field32_get(unit, LLS_L2_PARENTm, &l2pe, C_PARENTf); 6241 lvl = SOC_TR3_NODE_LVL_L1; 6242 } else { 6243 lvl = (IS_CPU_PORT(unit, local_port)) ? 6244 SOC_TR3_NODE_LVL_L2 : SOC_TR3_NODE_LVL_L1; 6245 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_index_resolve(unit, local_port, cosq, 6246 _BCM_TR3_COSQ_INDEX_STYLE_SCHEDULER, NULL, &sch_index, NULL)); 6247 } 6248 } 6249 6250 BCM_IF_ERROR_RETURN( 6251 soc_tr3_cosq_get_sched_mode(unit, local_port, lvl, sch_index, 6252 &sched_mode, weight)); 6253 6254 switch(sched_mode) { 6255 case SOC_TR3_SCHED_MODE_STRICT: 6256 *mode = BCM_COSQ_STRICT; 6257 break; 6258 case SOC_TR3_SCHED_MODE_WRR: 6259 *mode = BCM_COSQ_WEIGHTED_ROUND_ROBIN; 6260 break; 6261 case SOC_TR3_SCHED_MODE_WDRR: 6262 *mode = BCM_COSQ_DEFICIT_ROUND_ROBIN; 6263 break; 6264 default: 6265 return BCM_E_INTERNAL; 6266 break; 6267 } 6268 6269 return BCM_E_NONE; 6270 } 6271 6272 /* 6273 * Function: 6274 * bcm_tr3_cosq_detach 6275 * Purpose: 6276 * Discard all COS schedule/mapping state. 6277 * Parameters: 6278 * unit - unit number 6279 * Returns: 6280 * BCM_E_XXX 6281 */ 6282 int 6283 bcm_tr3_cosq_detach(int unit, int software_state_only) 6284 { 6285 return BCM_E_NONE; 6286 } 6287 6288 /* 6289 * Function: 6290 * bcm_tr3_cosq_config_set 6291 * Purpose: 6292 * Set the number of COS queues 6293 * Parameters: 6294 * unit - unit number 6295 * numq - number of COS queues (1-8). 6296 * Returns: 6297 * BCM_E_XXX 6298 */ 6299 int 6300 bcm_tr3_cosq_config_set(int unit, int numq) 6301 { 6302 port_cos_map_entry_t cos_map_entries[16]; 6303 void *entries[1], *hg_entries[1]; 6304 uint32 index, hg_index; 6305 int count, hg_count; 6306 bcm_port_t port; 6307 int cos, prio; 6308 uint32 i; 6309 int cpu_hg_index = 0; 6310 #ifdef BCM_COSQ_HIGIG_MAP_DISABLE 6311 port_cos_map_entry_t hg_cos_map_entries[16]; 6312 #endif 6313 voq_cos_map_entry_t voq_cos_map; 6314 int ref_count; 6315 6316 if (numq < 1 || numq > 8) { 6317 return BCM_E_PARAM; 6318 } 6319 6320 /* clear out old profiles. */ 6321 index = 0; 6322 while (index < soc_mem_index_count(unit, PORT_COS_MAPm)) { 6323 BCM_IF_ERROR_RETURN(soc_profile_mem_ref_count_get(unit, 6324 _bcm_tr3_cos_map_profile[unit], 6325 index, &ref_count)); 6326 if (ref_count > 0) { 6327 while (ref_count) { 6328 BCM_IF_ERROR_RETURN(soc_profile_mem_delete(unit, 6329 _bcm_tr3_cos_map_profile[unit], index)); 6330 ref_count -= 1; 6331 } 6332 } 6333 index += 16; 6334 } 6335 6336 /* Distribute first 8 internal priority levels into the specified number 6337 * of cosq, map remaining internal priority levels to highest priority 6338 * cosq */ 6339 sal_memset(cos_map_entries, 0, sizeof(cos_map_entries)); 6340 entries[0] = &cos_map_entries; 6341 hg_entries[0] = &cos_map_entries; 6342 prio = 0; 6343 for (cos = 0; cos < numq; cos++) { 6344 for (i = 8 / numq + (cos < 8 % numq ? 1 : 0); i > 0; i--) { 6345 soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio], 6346 UC_COS1f, cos); 6347 soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio], 6348 MC_COS1f, cos); 6349 soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio], 6350 HG_COSf, cos); 6351 prio++; 6352 } 6353 } 6354 for (prio = 8; prio < 16; prio++) { 6355 soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio], UC_COS1f, 6356 numq - 1); 6357 soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio], MC_COS1f, 6358 numq - 1); 6359 soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio], HG_COSf, 6360 numq - 1); 6361 } 6362 6363 /* Map internal priority levels to CPU CoS queues */ 6364 BCM_IF_ERROR_RETURN(_bcm_esw_cpu_cosq_mapping_default_set(unit, numq)); 6365 6366 #ifdef BCM_COSQ_HIGIG_MAP_DISABLE 6367 /* Use identical mapping for Higig port */ 6368 sal_memset(hg_cos_map_entries, 0, sizeof(hg_cos_map_entries)); 6369 hg_entries[0] = &hg_cos_map_entries; 6370 prio = 0; 6371 for (prio = 0; prio < 8; prio++) { 6372 soc_mem_field32_set(unit, PORT_COS_MAPm, &hg_cos_map_entries[prio], 6373 COSf, prio); 6374 } 6375 for (prio = 8; prio < 16; prio++) { 6376 soc_mem_field32_set(unit, PORT_COS_MAPm, &hg_cos_map_entries[prio], 6377 COSf, 7); 6378 } 6379 #endif /* BCM_COSQ_HIGIG_MAP_DISABLE */ 6380 6381 BCM_IF_ERROR_RETURN 6382 (soc_profile_mem_add(unit, _bcm_tr3_cos_map_profile[unit], entries, 16, 6383 &index)); 6384 /* for higig ports the mapping is slight different */ 6385 soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[14], 6386 HG_COSf, 8); 6387 soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[15], 6388 HG_COSf, 9); 6389 6390 BCM_IF_ERROR_RETURN 6391 (soc_profile_mem_add(unit, _bcm_tr3_cos_map_profile[unit], hg_entries, 6392 16, &hg_index)); 6393 count = 0; 6394 hg_count = 0; 6395 PBMP_ALL_ITER(unit, port) { 6396 if (IS_LB_PORT(unit, port)) { 6397 continue; 6398 } 6399 6400 if (IS_HG_PORT(unit, port)) { 6401 BCM_IF_ERROR_RETURN 6402 (soc_mem_field32_modify(unit, COS_MAP_SELm, port, SELECTf, 6403 hg_index / 16)); 6404 hg_count++; 6405 } else { 6406 BCM_IF_ERROR_RETURN 6407 (soc_mem_field32_modify(unit, COS_MAP_SELm, port, SELECTf, 6408 index / 16)); 6409 count++; 6410 } 6411 } 6412 cpu_hg_index = SOC_INFO(unit).cpu_hg_index; 6413 if (cpu_hg_index != -1) { 6414 BCM_IF_ERROR_RETURN 6415 (soc_mem_field32_modify(unit, COS_MAP_SELm, 6416 cpu_hg_index, SELECTf, index / 16)); 6417 count++; 6418 } 6419 for (i = 1; i < count; i++) { 6420 soc_profile_mem_reference(unit, _bcm_tr3_cos_map_profile[unit], index, 6421 0); 6422 } 6423 for (i = 1; i < hg_count; i++) { 6424 soc_profile_mem_reference(unit, _bcm_tr3_cos_map_profile[unit], 6425 hg_index, 0); 6426 } 6427 6428 sal_memset(&voq_cos_map, 0, sizeof(voq_cos_map)); 6429 for (cos = 0; cos < numq; cos++) { 6430 for (i = 8 / numq + (i < 8 % numq ? 1 : 0); i > 0; i--) { 6431 soc_mem_field32_set(unit, VOQ_COS_MAPm, &voq_cos_map, VOQ_COS_OFFSETf, cos); 6432 BCM_IF_ERROR_RETURN( 6433 soc_mem_write(unit, VOQ_COS_MAPm, MEM_BLOCK_ANY, cos, 6434 &voq_cos_map)); 6435 prio++; 6436 } 6437 } 6438 for (prio = 8; prio < 16; prio++) { 6439 soc_mem_field32_set(unit, VOQ_COS_MAPm, &voq_cos_map, VOQ_COS_OFFSETf, numq - 1); 6440 BCM_IF_ERROR_RETURN( 6441 soc_mem_write(unit, VOQ_COS_MAPm, MEM_BLOCK_ANY, prio, 6442 &voq_cos_map)); 6443 } 6444 6445 _TR3_NUM_COS(unit) = numq; 6446 6447 return BCM_E_NONE; 6448 } 6449 6450 STATIC int 6451 _bcm_tr3_cosq_egress_sp_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 6452 int *p_pool_start, int *p_pool_end) 6453 { 6454 int local_port, uc, hw_index; 6455 _bcm_tr3_cosq_node_t *node; 6456 uint32 entry[SOC_MAX_MEM_WORDS], pool, rval; 6457 6458 BCM_IF_ERROR_RETURN 6459 (_bcm_tr3_cosq_localport_resolve(unit, gport, &local_port)); 6460 6461 if (!SOC_PORT_VALID(unit, local_port)) { 6462 return BCM_E_PORT; 6463 } 6464 6465 if (cosq == BCM_COS_INVALID) { 6466 *p_pool_start = 0; 6467 *p_pool_end = 3; 6468 return BCM_E_NONE; 6469 } 6470 6471 node = NULL; 6472 if (BCM_GPORT_IS_SCHEDULER(gport)) { 6473 BCM_IF_ERROR_RETURN( 6474 _bcm_tr3_cosq_node_get(unit, gport, ((cosq < 0) ? 0 : cosq), 6475 NULL, &local_port, NULL, &node)); 6476 BCM_IF_ERROR_RETURN( 6477 _bcm_tr3_cosq_child_node_at_input(node, cosq, &node)); 6478 cosq = 0; 6479 } else if ((BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) || 6480 (BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) || 6481 (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport))) { 6482 BCM_IF_ERROR_RETURN( 6483 _bcm_tr3_cosq_node_get(unit, gport, 0, 6484 NULL, &local_port, NULL, &node)); 6485 } 6486 6487 if (node) { 6488 if (node->hw_index < 0) { 6489 return BCM_E_PARAM; 6490 } 6491 6492 hw_index = node->hw_index; 6493 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(node->gport) || 6494 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(node->gport)) { 6495 uc = 1; 6496 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(node->gport)) { 6497 uc = 0; 6498 } else { 6499 return BCM_E_PARAM; 6500 } 6501 } else { 6502 uc = 1; 6503 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_index_resolve(unit, local_port, cosq, 6504 _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE, NULL, &hw_index, NULL)); 6505 6506 } 6507 6508 if (uc) { 6509 BCM_IF_ERROR_RETURN(soc_mem_read(unit, MMU_THDO_Q_TO_QGRP_MAPm, 6510 MEM_BLOCK_ANY, hw_index, &entry)); 6511 pool = soc_mem_field32_get(unit, MMU_THDO_Q_TO_QGRP_MAPm, 6512 entry, Q_SPIDf); 6513 } else { 6514 BCM_IF_ERROR_RETURN(soc_reg32_get(unit, OP_QUEUE_CONFIG1_CELLr, 6515 local_port, hw_index, &rval)); 6516 pool = soc_reg_field_get(unit, OP_QUEUE_CONFIG1_CELLr, 6517 rval, Q_SPIDf); 6518 } 6519 6520 *p_pool_start = *p_pool_end = pool; 6521 return BCM_E_NONE; 6522 } 6523 6524 STATIC int 6525 _bcm_tr3_cosq_ingress_sp_get(int unit, bcm_gport_t gport, bcm_cos_queue_t pri_grp, 6526 int *p_pool_start, int *p_pool_end) 6527 { 6528 int local_port; 6529 uint32 rval, pool; 6530 static const soc_field_t prigroup_spid_field[] = { 6531 PG0_SPIDf, PG1_SPIDf, PG2_SPIDf, PG3_SPIDf, 6532 PG4_SPIDf, PG5_SPIDf, PG6_SPIDf, PG7_SPIDf 6533 }; 6534 6535 if (pri_grp == BCM_COS_INVALID) { 6536 *p_pool_start = 0; 6537 *p_pool_end = 3; 6538 return BCM_E_NONE; 6539 } 6540 6541 BCM_IF_ERROR_RETURN 6542 (_bcm_tr3_cosq_localport_resolve(unit, gport, &local_port)); 6543 6544 if (!SOC_PORT_VALID(unit, local_port)) { 6545 return BCM_E_PORT; 6546 } 6547 6548 if (pri_grp >= 8) { 6549 return BCM_E_PARAM; 6550 } 6551 6552 SOC_IF_ERROR_RETURN(READ_PORT_PG_SPIDr(unit, local_port, &rval)); 6553 pool = soc_reg_field_get(unit, PORT_PG_SPIDr, rval, 6554 prigroup_spid_field[pri_grp]); 6555 6556 *p_pool_start = *p_pool_end = pool; 6557 return BCM_E_NONE; 6558 } 6559 6560 STATIC int 6561 _bcm_tr3_cosq_ingress_pg_get(int unit, bcm_gport_t gport, bcm_cos_queue_t pri, 6562 int *p_pg_start, int *p_pg_end) 6563 { 6564 bcm_port_t local_port; 6565 uint32 rval,pool; 6566 soc_reg_t reg = INVALIDr; 6567 static const soc_reg_t prigroup_reg[] = { 6568 PORT_PRI_GRP0r, PORT_PRI_GRP1r 6569 }; 6570 static const soc_field_t prigroup_field[] = { 6571 PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf, 6572 PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf, 6573 PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf, 6574 PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf 6575 }; 6576 6577 if (pri == BCM_COS_INVALID) { 6578 *p_pg_start = 0; 6579 *p_pg_end = 7; 6580 return BCM_E_NONE; 6581 } 6582 6583 BCM_IF_ERROR_RETURN 6584 (_bcm_tr3_cosq_localport_resolve(unit, gport, &local_port)); 6585 6586 if (!SOC_PORT_VALID(unit, local_port)) { 6587 return BCM_E_PORT; 6588 } 6589 6590 if (pri > 15) { 6591 return BCM_E_PARAM; 6592 } 6593 /* get PG for port using Port+Cos */ 6594 if (pri < 8) { 6595 reg = prigroup_reg[0]; 6596 } else { 6597 reg = prigroup_reg[1]; 6598 } 6599 6600 SOC_IF_ERROR_RETURN 6601 (soc_reg32_get(unit, reg, local_port, 0, &rval)); 6602 pool = soc_reg_field_get(unit, reg, rval, prigroup_field[pri]); 6603 6604 *p_pg_start = *p_pg_end = pool; 6605 return BCM_E_NONE; 6606 } 6607 6608 STATIC _bcm_bst_cb_ret_t 6609 _bcm_tr3_bst_index_resolve(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 6610 bcm_bst_stat_id_t bid, int *pipe, int *start_hw_index, 6611 int *end_hw_index, int *rcb_data, void **cb_data, int *bcm_rv) 6612 { 6613 int phy_port, mmu_port, local_port; 6614 _bcm_tr3_cosq_node_t *node = NULL; 6615 soc_info_t *si; 6616 int rv; 6617 6618 *bcm_rv = BCM_E_NONE; 6619 *pipe = 0; 6620 si = &SOC_INFO(unit); 6621 6622 rv = _bcm_tr3_cosq_localport_resolve(unit, gport, &local_port); 6623 if (BCM_FAILURE(rv)) { 6624 goto error; 6625 } 6626 6627 if (bid == bcmBstStatIdDevice) { 6628 *start_hw_index = *end_hw_index = 0; 6629 *bcm_rv = BCM_E_NONE; 6630 return _BCM_BST_RV_OK; 6631 } 6632 6633 /* only 48 CPU queues 0-47 supported for bcmBstStatIdMcast */ 6634 if (bid == bcmBstStatIdMcast) { 6635 if (IS_CPU_PORT(unit, local_port)) { 6636 *start_hw_index = 0; 6637 *end_hw_index = cosq; 6638 *bcm_rv = BCM_E_NONE; 6639 return _BCM_BST_RV_OK; 6640 } else { 6641 *start_hw_index = *end_hw_index = 0; 6642 *bcm_rv = BCM_E_PARAM; 6643 return _BCM_BST_RV_ERROR; 6644 } 6645 } 6646 6647 /* resolve pool */ 6648 if (bid == bcmBstStatIdEgrPool) { 6649 if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 6650 goto error; 6651 } 6652 if(_bcm_tr3_cosq_egress_sp_get(unit, gport, cosq, start_hw_index, 6653 end_hw_index)) { 6654 goto error; 6655 } 6656 return _BCM_BST_RV_OK; 6657 } else if (bid == bcmBstStatIdEgrMCastPool) { 6658 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 6659 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) { 6660 goto error; 6661 } 6662 if(_bcm_tr3_cosq_egress_sp_get(unit, gport, cosq, start_hw_index, 6663 end_hw_index)) { 6664 goto error; 6665 } 6666 return _BCM_BST_RV_OK; 6667 } else if (bid == bcmBstStatIdIngPool) { 6668 /* ingress pool */ 6669 if (_bcm_tr3_cosq_ingress_sp_get(unit, gport, cosq, 6670 start_hw_index, end_hw_index)) { 6671 goto error; 6672 } 6673 return _BCM_BST_RV_OK; 6674 } else if ((bid == bcmBstStatIdPriGroupShared) || 6675 (bid == bcmBstStatIdPriGroupHeadroom)) { 6676 if (_bcm_tr3_cosq_ingress_pg_get(unit, gport, cosq, 6677 start_hw_index, end_hw_index)){ 6678 goto error; 6679 } 6680 } 6681 6682 phy_port = si->port_l2p_mapping[local_port]; 6683 mmu_port = si->port_p2m_mapping[phy_port]; 6684 6685 if (bid == bcmBstStatIdPortPool) { 6686 *start_hw_index = (mmu_port * 4) + *start_hw_index; 6687 *end_hw_index = (mmu_port * 4) + *end_hw_index; 6688 } else if ((bid == bcmBstStatIdPriGroupShared) || 6689 (bid == bcmBstStatIdPriGroupHeadroom)) { 6690 *start_hw_index = (mmu_port * 8) + *start_hw_index; 6691 *end_hw_index = (mmu_port * 8) + *end_hw_index; 6692 6693 } else { 6694 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 6695 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) { 6696 if (bid != bcmBstStatIdUcast) { 6697 goto error; 6698 } 6699 BCM_IF_ERROR_RETURN 6700 (_bcm_tr3_cosq_node_get(unit, gport, 0, NULL, 6701 &local_port, NULL, &node)); 6702 if (!node) { 6703 goto error; 6704 } 6705 *start_hw_index = *end_hw_index = node->hw_index; 6706 } else { 6707 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_port_has_ets(unit, local_port)); 6708 6709 if (cosq < 0) { 6710 if (bid == bcmBstStatIdUcast) { 6711 *start_hw_index = si->port_uc_cosq_base[local_port]; 6712 *end_hw_index = si->port_uc_cosq_base[local_port] + 7; 6713 } else { 6714 *start_hw_index = si->port_cosq_base[local_port]; 6715 *end_hw_index = si->port_cosq_base[local_port] + 7; 6716 } 6717 } else { 6718 if (bid == bcmBstStatIdUcast) { 6719 *start_hw_index = si->port_uc_cosq_base[local_port] + cosq; 6720 *end_hw_index = si->port_uc_cosq_base[local_port] + cosq; 6721 } else { 6722 *start_hw_index = si->port_cosq_base[local_port] + cosq; 6723 *end_hw_index = si->port_cosq_base[local_port] + cosq; 6724 } 6725 } 6726 } 6727 } 6728 6729 *bcm_rv = BCM_E_NONE; 6730 return _BCM_BST_RV_OK; 6731 6732 error: 6733 *bcm_rv = BCM_E_PARAM; 6734 return _BCM_BST_RV_ERROR; 6735 } 6736 6737 STATIC int 6738 _bcm_tr3_cosq_bst_map_resource_to_gport_cos(int unit, bcm_bst_stat_id_t bid, int port, 6739 int index, bcm_gport_t *gport, bcm_cos_t *cosq) 6740 { 6741 soc_info_t *si; 6742 _bcm_tr3_cosq_node_t *node; 6743 _bcm_tr3_mmu_info_t *mmu_info; 6744 int resolved = 0, ii, phy_port, mmu_port; 6745 6746 mmu_info = _bcm_tr3_mmu_info[unit]; 6747 si = &SOC_INFO(unit); 6748 6749 switch(bid) { 6750 case bcmBstStatIdDevice: 6751 *gport = -1; 6752 *cosq = BCM_COS_INVALID; 6753 break; 6754 6755 case bcmBstStatIdIngPool: 6756 case bcmBstStatIdEgrPool: 6757 *gport = -1; 6758 *cosq = index; 6759 break; 6760 6761 case bcmBstStatIdPortPool: 6762 mmu_port= index/4; 6763 phy_port = si->port_m2p_mapping[mmu_port]; 6764 *gport = si->port_p2l_mapping[phy_port]; 6765 *cosq = index % 4; 6766 break; 6767 6768 case bcmBstStatIdPriGroupHeadroom: 6769 case bcmBstStatIdPriGroupShared: 6770 mmu_port = index/8; 6771 phy_port = si->port_m2p_mapping[mmu_port]; 6772 *gport = si->port_p2l_mapping[phy_port]; 6773 *cosq = index % 8; 6774 break; 6775 6776 case bcmBstStatIdUcast: 6777 for (ii = mmu_info->num_base_queues; 6778 ii < _BCM_TR3_NUM_L2_UC_LEAVES; ii++) { 6779 node = &mmu_info->queue_node[ii]; 6780 if ((node->in_use == TRUE) && (node->hw_index == index)) { 6781 *gport = node->gport; 6782 *cosq = 0; 6783 resolved = 1; 6784 break; 6785 } 6786 } 6787 6788 if (!resolved) { 6789 for (ii = index/8; ii < 64; ii++) { 6790 if ((index - si->port_uc_cosq_base[ii]) < 8) { 6791 *gport = ii; 6792 *cosq = index - si->port_uc_cosq_base[ii]; 6793 break; 6794 } 6795 } 6796 } 6797 break; 6798 default: 6799 *gport = -1; 6800 *cosq = BCM_COS_INVALID; 6801 break; 6802 } 6803 6804 return BCM_E_NONE; 6805 } 6806 6807 STATIC int 6808 _bcm_tr3_cosq_unreserve_gport_resources(int unit, bcm_port_t port) 6809 { 6810 int lvl, lvl_offset, hw_index, rv; 6811 _bcm_tr3_mmu_info_t *mmu_info; 6812 _bcm_tr3_cosq_list_t *list; 6813 6814 mmu_info = _bcm_tr3_mmu_info[unit]; 6815 6816 for (lvl = SOC_TR3_NODE_LVL_L0; lvl <= SOC_TR3_NODE_LVL_L1; lvl++) { 6817 lvl_offset = 0; 6818 6819 list = NULL; 6820 if (lvl == SOC_TR3_NODE_LVL_L0) { 6821 list = &mmu_info->l0_sched_list; 6822 } else if (lvl == SOC_TR3_NODE_LVL_L1) { 6823 list = &mmu_info->l1_sched_list; 6824 } 6825 6826 if (!list) { 6827 continue; 6828 } 6829 while ((rv = soc_tr3_sched_hw_index_get(unit, port, lvl, 6830 lvl_offset, &hw_index)) == SOC_E_NONE) { 6831 _bcm_tr3_node_index_clear(list, hw_index, 1); 6832 lvl_offset += 1; 6833 } 6834 } 6835 return BCM_E_NONE; 6836 } 6837 STATIC int 6838 _bcm_tr3_cosq_reserve_gport_resources(int unit, bcm_port_t port) 6839 { 6840 int lvl, lvl_offset, hw_index, rv; 6841 _bcm_tr3_mmu_info_t *mmu_info; 6842 _bcm_tr3_cosq_list_t *list; 6843 6844 mmu_info = _bcm_tr3_mmu_info[unit]; 6845 6846 for (lvl = SOC_TR3_NODE_LVL_L0; lvl <= SOC_TR3_NODE_LVL_L1; lvl++) { 6847 lvl_offset = 0; 6848 6849 list = NULL; 6850 if (lvl == SOC_TR3_NODE_LVL_L0) { 6851 list = &mmu_info->l0_sched_list; 6852 } else if (lvl == SOC_TR3_NODE_LVL_L1) { 6853 list = &mmu_info->l1_sched_list; 6854 } 6855 6856 if (!list) { 6857 continue; 6858 } 6859 while ((rv = soc_tr3_sched_hw_index_get(unit, port, lvl, 6860 lvl_offset, &hw_index)) == SOC_E_NONE) { 6861 _bcm_tr3_node_index_set(list, hw_index, 1); 6862 lvl_offset += 1; 6863 } 6864 } 6865 return BCM_E_NONE; 6866 } 6867 STATIC 6868 int _bcm_tr3_hsp_hierarchy_setup(int unit, int port) 6869 { 6870 bcm_gport_t gport; 6871 bcm_gport_t port_sched, l0_sched[_SOC_HSP_MAX_L0_NODES]; 6872 bcm_gport_t Uqueue[_SOC_HSP_NUM_UC_QUEUE]; 6873 bcm_gport_t Mqueue[_SOC_HSP_NUM_MC_QUEUE]; 6874 int cos; 6875 6876 BCM_IF_ERROR_RETURN(bcm_esw_port_gport_get(unit, port, &gport)); 6877 6878 BCM_IF_ERROR_RETURN(bcm_tr3_cosq_gport_add(unit, gport, 10, 0, &port_sched, 1)); 6879 6880 for(cos = 0; cos < _SOC_HSP_MAX_L0_NODES; cos++) { 6881 BCM_IF_ERROR_RETURN(bcm_tr3_cosq_gport_add(unit, gport, -1, 6882 BCM_COSQ_GPORT_SCHEDULER, 6883 &l0_sched[cos], 1)); 6884 BCM_IF_ERROR_RETURN(bcm_tr3_cosq_gport_attach(unit, l0_sched[cos], port_sched, cos)); 6885 } 6886 for (cos = 0; cos < (_SOC_HSP_NUM_UC_QUEUE - _SOC_HSP_LAST_L0_NUM_UC_QUEUE); cos++) { 6887 BCM_IF_ERROR_RETURN(bcm_tr3_cosq_gport_add(unit, gport, 1, 6888 BCM_COSQ_GPORT_UCAST_QUEUE_GROUP, 6889 &Uqueue[cos], 1)); 6890 BCM_IF_ERROR_RETURN(bcm_tr3_cosq_gport_attach(unit, Uqueue[cos], l0_sched[cos+1], 0)); 6891 } 6892 for (cos = 0; cos < (_SOC_HSP_NUM_MC_QUEUE - _SOC_HSP_LAST_L0_NUM_UC_QUEUE); cos++) { 6893 BCM_IF_ERROR_RETURN(bcm_tr3_cosq_gport_add(unit, gport, 1, 6894 BCM_COSQ_GPORT_MCAST_QUEUE_GROUP, 6895 &Mqueue[cos], 1)); 6896 BCM_IF_ERROR_RETURN(bcm_tr3_cosq_gport_attach(unit, Mqueue[cos], l0_sched[cos+1], 1)); 6897 } 6898 for (cos = 0; cos < _SOC_HSP_LAST_L0_NUM_UC_QUEUE; cos++) { 6899 BCM_IF_ERROR_RETURN(bcm_tr3_cosq_gport_add(unit, gport, 1, 6900 BCM_COSQ_GPORT_UCAST_QUEUE_GROUP, 6901 &Uqueue[cos+8],1)); 6902 BCM_IF_ERROR_RETURN(bcm_tr3_cosq_gport_attach(unit, Uqueue[cos+8], l0_sched[9], cos)); 6903 } 6904 for (cos = 0; cos < _SOC_HSP_LAST_L0_NUM_MC_QUEUE; cos++) { 6905 BCM_IF_ERROR_RETURN(bcm_tr3_cosq_gport_add(unit, gport, 1, 6906 BCM_COSQ_GPORT_MCAST_QUEUE_GROUP, 6907 &Mqueue[cos+8], 1)); 6908 BCM_IF_ERROR_RETURN(bcm_tr3_cosq_gport_attach(unit, Mqueue[cos+8], l0_sched[9], cos+2)); 6909 } 6910 return BCM_E_NONE; 6911 } 6912 /* 6913 * Function: 6914 * bcm_tr3_cosq_init 6915 * Purpose: 6916 * Initialize (clear) all COS schedule/mapping state. 6917 * Parameters: 6918 * unit - unit number 6919 * Returns: 6920 * BCM_E_XXX 6921 */ 6922 int 6923 bcm_tr3_cosq_init(int unit) 6924 { 6925 int numq, alloc_size, ii; 6926 soc_info_t *si; 6927 bcm_port_t port; 6928 soc_reg_t reg; 6929 soc_reg_t mem; 6930 static soc_mem_t wred_mems[6] = { 6931 MMU_WRED_DROP_CURVE_PROFILE_0m, MMU_WRED_DROP_CURVE_PROFILE_1m, 6932 MMU_WRED_DROP_CURVE_PROFILE_2m, MMU_WRED_DROP_CURVE_PROFILE_3m, 6933 MMU_WRED_DROP_CURVE_PROFILE_4m, MMU_WRED_DROP_CURVE_PROFILE_5m 6934 }; 6935 int entry_words[6]; 6936 mmu_wred_drop_curve_profile_0_entry_t entry_tcp_green; 6937 mmu_wred_drop_curve_profile_1_entry_t entry_tcp_yellow; 6938 mmu_wred_drop_curve_profile_2_entry_t entry_tcp_red; 6939 mmu_wred_drop_curve_profile_3_entry_t entry_nontcp_green; 6940 mmu_wred_drop_curve_profile_4_entry_t entry_nontcp_yellow; 6941 mmu_wred_drop_curve_profile_5_entry_t entry_nontcp_red; 6942 void *entries[6]; 6943 uint64 rval64s[16], *prval64s[1]; 6944 uint32 rval, profile_index; 6945 _bcm_tr3_mmu_info_t *mmu_info; 6946 int i, wred_prof_count, index; 6947 _bcm_bst_device_handlers_t bst_callbks; 6948 _bcm_tr3_cosq_list_t *list = NULL; 6949 if (!SOC_WARM_BOOT(unit)) { /* Cold Boot */ 6950 BCM_IF_ERROR_RETURN (bcm_tr3_cosq_detach(unit, 0)); 6951 } 6952 6953 si = &SOC_INFO(unit); 6954 numq = soc_property_get(unit, spn_BCM_NUM_COS, BCM_COS_DEFAULT); 6955 6956 if (numq < 1) { 6957 numq = 1; 6958 } else if (numq > 8) { 6959 numq = 8; 6960 } 6961 _TR3_NUM_COS(unit) = numq; 6962 6963 /* Create profile for PORT_COS_MAP table */ 6964 if (_bcm_tr3_cos_map_profile[unit] == NULL) { 6965 _bcm_tr3_cos_map_profile[unit] = sal_alloc(sizeof(soc_profile_mem_t), 6966 "COS_MAP Profile Mem"); 6967 if (_bcm_tr3_cos_map_profile[unit] == NULL) { 6968 return BCM_E_MEMORY; 6969 } 6970 soc_profile_mem_t_init(_bcm_tr3_cos_map_profile[unit]); 6971 } 6972 mem = PORT_COS_MAPm; 6973 entry_words[0] = sizeof(port_cos_map_entry_t) / sizeof(uint32); 6974 BCM_IF_ERROR_RETURN(soc_profile_mem_create(unit, &mem, entry_words, 1, 6975 _bcm_tr3_cos_map_profile[unit])); 6976 6977 /* Create profile for SERVICE_COS_MAP table */ 6978 if (_bcm_tr3_service_cos_map_profile[unit] == NULL) { 6979 _bcm_tr3_service_cos_map_profile[unit] = sal_alloc(sizeof(soc_profile_mem_t), 6980 "SERVICE_COS_MAP Profile Mem"); 6981 if (_bcm_tr3_service_cos_map_profile[unit] == NULL) { 6982 return BCM_E_MEMORY; 6983 } 6984 soc_profile_mem_t_init(_bcm_tr3_service_cos_map_profile[unit]); 6985 } 6986 mem = SERVICE_COS_MAPm; 6987 entry_words[0] = sizeof(service_cos_map_entry_t) / sizeof(uint32); 6988 BCM_IF_ERROR_RETURN(soc_profile_mem_create(unit, &mem, entry_words, 1, 6989 _bcm_tr3_service_cos_map_profile[unit])); 6990 6991 /* Create profile for SERVICE_PORT_MAP table */ 6992 if (_bcm_tr3_service_port_map_profile[unit] == NULL) { 6993 _bcm_tr3_service_port_map_profile[unit] = sal_alloc(sizeof(soc_profile_mem_t), 6994 "SERVICE_PORT_MAP Profile Mem"); 6995 if (_bcm_tr3_service_port_map_profile[unit] == NULL) { 6996 return BCM_E_MEMORY; 6997 } 6998 soc_profile_mem_t_init(_bcm_tr3_service_port_map_profile[unit]); 6999 } 7000 7001 /* Create profile for IFP_COS_MAP table. */ 7002 if (_bcm_tr3_ifp_cos_map_profile[unit] == NULL) { 7003 _bcm_tr3_ifp_cos_map_profile[unit] 7004 = sal_alloc(sizeof(soc_profile_mem_t), "IFP_COS_MAP Profile Mem"); 7005 if (_bcm_tr3_ifp_cos_map_profile[unit] == NULL) { 7006 return BCM_E_MEMORY; 7007 } 7008 soc_profile_mem_t_init(_bcm_tr3_ifp_cos_map_profile[unit]); 7009 } 7010 mem = IFP_COS_MAPm; 7011 entry_words[0] = sizeof(ifp_cos_map_entry_t) / sizeof(uint32); 7012 BCM_IF_ERROR_RETURN 7013 (soc_profile_mem_create(unit, &mem, entry_words, 1, 7014 _bcm_tr3_ifp_cos_map_profile[unit])); 7015 7016 mem = SERVICE_PORT_MAPm; 7017 entry_words[0] = sizeof(service_port_map_entry_t) / sizeof(uint32); 7018 BCM_IF_ERROR_RETURN(soc_profile_mem_create(unit, &mem, entry_words, 1, 7019 _bcm_tr3_service_port_map_profile[unit])); 7020 7021 alloc_size = sizeof(_bcm_tr3_mmu_info_t) * 1; 7022 if (_bcm_tr3_mmu_info[unit] == NULL) { 7023 _bcm_tr3_mmu_info[unit] = 7024 sal_alloc(alloc_size, "_bcm_tr3_mmu_info"); 7025 7026 if (_bcm_tr3_mmu_info[unit] == NULL) { 7027 return BCM_E_MEMORY; 7028 } 7029 7030 sal_memset(_bcm_tr3_mmu_info[unit], 0, alloc_size); 7031 }else{ 7032 bcm_tr3_cosq_stat_init(unit); 7033 } 7034 7035 mmu_info = _bcm_tr3_mmu_info[unit]; 7036 mmu_info->num_base_queues = 0; 7037 7038 /* assign queues to ports */ 7039 PBMP_ALL_ITER(unit, port) { 7040 mmu_info->port_info[port].mc_base = si->port_cosq_base[port]; 7041 mmu_info->port_info[port].mc_limit = si->port_cosq_base[port] + 7042 si->port_num_cosq[port]; 7043 7044 mmu_info->port_info[port].uc_base = si->port_uc_cosq_base[port];; 7045 mmu_info->port_info[port].uc_limit = si->port_uc_cosq_base[port] + 7046 si->port_num_uc_cosq[port]; 7047 mmu_info->num_base_queues += si->port_num_uc_cosq[port]; 7048 7049 if (!SOC_WARM_BOOT(unit)) { 7050 rval = 0; 7051 soc_reg_field_set(unit, ING_COS_MODEr, &rval, BASE_QUEUE_NUM_0f, 7052 mmu_info->port_info[port].uc_base); 7053 soc_reg_field_set(unit, ING_COS_MODEr, &rval, BASE_QUEUE_NUM_1f, 7054 mmu_info->port_info[port].uc_base); 7055 BCM_IF_ERROR_RETURN(soc_reg32_set(unit, ING_COS_MODEr, port, 0, rval)); 7056 } 7057 } 7058 7059 mmu_info->ets_mode = 0; 7060 mmu_info->num_dmvoq_queues = soc_property_get(unit, 7061 spn_MMU_NUM_DMVOQ_QUEUES, 0); 7062 7063 if (mmu_info->num_dmvoq_queues > 0) { 7064 mmu_info->base_dmvoq_queue = (mmu_info->num_base_queues + 7) & 0xfffffff8; 7065 mmu_info->dmvoq_qlist.count = mmu_info->num_dmvoq_queues; 7066 mmu_info->dmvoq_qlist.bits = _bcm_tr3_cosq_alloc_clear( 7067 mmu_info->dmvoq_qlist.bits, 7068 SHR_BITALLOCSIZE(mmu_info->num_dmvoq_queues), 7069 "dmvoq_qlist"); 7070 if (mmu_info->dmvoq_qlist.bits == NULL) { 7071 _bcm_tr3_cosq_free_memory(mmu_info); 7072 return BCM_E_MEMORY; 7073 } 7074 } 7075 7076 mmu_info->ext_qlist.count = _BCM_TR3_NUM_L2_UC_LEAVES; 7077 mmu_info->ext_qlist.bits = _bcm_tr3_cosq_alloc_clear( 7078 mmu_info->ext_qlist.bits, 7079 SHR_BITALLOCSIZE(_BCM_TR3_NUM_L2_UC_LEAVES), "ext_qlist"); 7080 if (mmu_info->ext_qlist.bits == NULL) { 7081 _bcm_tr3_cosq_free_memory(mmu_info); 7082 return BCM_E_MEMORY; 7083 } 7084 7085 mmu_info->l0_sched_list.count = _BCM_TR3_NUM_L0_SCHEDULER; 7086 mmu_info->l0_sched_list.bits = _bcm_tr3_cosq_alloc_clear( 7087 mmu_info->l0_sched_list.bits, 7088 SHR_BITALLOCSIZE(_BCM_TR3_NUM_L0_SCHEDULER), "l0_sched_list"); 7089 if (mmu_info->l0_sched_list.bits == NULL) { 7090 _bcm_tr3_cosq_free_memory(mmu_info); 7091 return BCM_E_MEMORY; 7092 } 7093 7094 mmu_info->l1_sched_list.count = _BCM_TR3_NUM_L1_SCHEDULER; 7095 mmu_info->l1_sched_list.bits = _bcm_tr3_cosq_alloc_clear( 7096 mmu_info->l1_sched_list.bits, 7097 SHR_BITALLOCSIZE(_BCM_TR3_NUM_L1_SCHEDULER), "l1_sched_list"); 7098 if (mmu_info->l1_sched_list.bits == NULL) { 7099 _bcm_tr3_cosq_free_memory(mmu_info); 7100 return BCM_E_MEMORY; 7101 } 7102 7103 for (i = 0; i < _BCM_TR3_NUM_TOTAL_SCHEDULERS; i++) { 7104 _BCM_TR3_COSQ_LIST_NODE_INIT(mmu_info->sched_node, i); 7105 } 7106 7107 for (i = 0; i < _BCM_TR3_NUM_L2_UC_LEAVES; i++) { 7108 _BCM_TR3_COSQ_LIST_NODE_INIT(mmu_info->queue_node, i); 7109 } 7110 7111 for (i = 0; i < _BCM_TR3_NUM_L2_MC_LEAVES; i++) { 7112 _BCM_TR3_COSQ_LIST_NODE_INIT(mmu_info->mc_queue_node, i); 7113 } 7114 7115 for (i = SOC_TR3_NODE_LVL_L1; i <= SOC_TR3_NODE_LVL_L2; i++) { 7116 index = _soc_tr3_invalid_parent_index(unit, i); 7117 if (i == SOC_TR3_NODE_LVL_L1) { 7118 list = &mmu_info->l0_sched_list; 7119 } else if (i == SOC_TR3_NODE_LVL_L2) { 7120 list = &mmu_info->l1_sched_list; 7121 } else { 7122 continue; 7123 } 7124 if (index >= 0) { 7125 _bcm_tr3_node_index_set(list, index, 1); 7126 } 7127 } 7128 if (mmu_info->num_dmvoq_queues > 0) { 7129 BCM_IF_ERROR_RETURN 7130 (_bcm_tr3_node_index_set(&mmu_info->ext_qlist, 7131 mmu_info->base_dmvoq_queue, 7132 mmu_info->num_dmvoq_queues)); 7133 } 7134 7135 /* Create profile for MMU_QCN_SITB table */ 7136 if (_bcm_tr3_sample_int_profile[unit] == NULL) { 7137 _bcm_tr3_sample_int_profile[unit] = 7138 sal_alloc(sizeof(soc_profile_mem_t), "QCN sample Int Profile Mem"); 7139 if (_bcm_tr3_sample_int_profile[unit] == NULL) { 7140 return BCM_E_MEMORY; 7141 } 7142 soc_profile_mem_t_init(_bcm_tr3_sample_int_profile[unit]); 7143 } 7144 mem = MMU_QCN_SITBm; 7145 entry_words[0] = sizeof(mmu_qcn_sitb_entry_t) / sizeof(uint32); 7146 BCM_IF_ERROR_RETURN 7147 (soc_profile_mem_create(unit, &mem, entry_words, 1, 7148 _bcm_tr3_sample_int_profile[unit])); 7149 7150 /* Create profile for MMU_QCN_CPQ_SEQ register */ 7151 if (_bcm_tr3_feedback_profile[unit] == NULL) { 7152 _bcm_tr3_feedback_profile[unit] = 7153 sal_alloc(sizeof(soc_profile_reg_t), "QCN Feedback Profile Reg"); 7154 if (_bcm_tr3_feedback_profile[unit] == NULL) { 7155 return BCM_E_MEMORY; 7156 } 7157 soc_profile_reg_t_init(_bcm_tr3_feedback_profile[unit]); 7158 } 7159 reg = MMU_QCN_CPQ_SEQr; 7160 BCM_IF_ERROR_RETURN 7161 (soc_profile_reg_create(unit, ®, 1, 7162 _bcm_tr3_feedback_profile[unit])); 7163 7164 /* Create profile for PRIO2COS_LLFC register */ 7165 if (_bcm_tr3_llfc_profile[unit] == NULL) { 7166 _bcm_tr3_llfc_profile[unit] = 7167 sal_alloc(sizeof(soc_profile_reg_t), "PRIO2COS_LLFC Profile Reg"); 7168 if (_bcm_tr3_llfc_profile[unit] == NULL) { 7169 return BCM_E_MEMORY; 7170 } 7171 soc_profile_reg_t_init(_bcm_tr3_llfc_profile[unit]); 7172 } 7173 reg = PRIO2COS_PROFILEr; 7174 BCM_IF_ERROR_RETURN 7175 (soc_profile_reg_create(unit, ®, 1, _bcm_tr3_llfc_profile[unit])); 7176 7177 /* Create profile for MMU_WRED_DROP_CURVE_PROFILE_x tables */ 7178 if (_bcm_tr3_wred_profile[unit] == NULL) { 7179 _bcm_tr3_wred_profile[unit] = sal_alloc(sizeof(soc_profile_mem_t), 7180 "WRED Profile Mem"); 7181 if (_bcm_tr3_wred_profile[unit] == NULL) { 7182 return BCM_E_MEMORY; 7183 } 7184 soc_profile_mem_t_init(_bcm_tr3_wred_profile[unit]); 7185 } 7186 7187 entry_words[0] = 7188 sizeof(mmu_wred_drop_curve_profile_0_entry_t) / sizeof(uint32); 7189 entry_words[1] = 7190 sizeof(mmu_wred_drop_curve_profile_1_entry_t) / sizeof(uint32); 7191 entry_words[2] = 7192 sizeof(mmu_wred_drop_curve_profile_2_entry_t) / sizeof(uint32); 7193 entry_words[3] = 7194 sizeof(mmu_wred_drop_curve_profile_3_entry_t) / sizeof(uint32); 7195 entry_words[4] = 7196 sizeof(mmu_wred_drop_curve_profile_4_entry_t) / sizeof(uint32); 7197 entry_words[5] = 7198 sizeof(mmu_wred_drop_curve_profile_5_entry_t) / sizeof(uint32); 7199 BCM_IF_ERROR_RETURN 7200 (soc_profile_mem_create(unit, wred_mems, entry_words, 6, 7201 _bcm_tr3_wred_profile[unit])); 7202 7203 /* Create profile for VOQ_MOD_MAP table */ 7204 if (_bcm_tr3_voq_port_map_profile[unit] == NULL) { 7205 _bcm_tr3_voq_port_map_profile[unit] = sal_alloc(sizeof(soc_profile_mem_t), 7206 "VOQ_PORT_MAP Profile Mem"); 7207 if (_bcm_tr3_voq_port_map_profile[unit] == NULL) { 7208 return BCM_E_MEMORY; 7209 } 7210 soc_profile_mem_t_init(_bcm_tr3_voq_port_map_profile[unit]); 7211 } 7212 mem = VOQ_PORT_MAPm; 7213 entry_words[0] = sizeof(voq_port_map_entry_t) / sizeof(uint32); 7214 BCM_IF_ERROR_RETURN(soc_profile_mem_create(unit, &mem, entry_words, 1, 7215 _bcm_tr3_voq_port_map_profile[unit])); 7216 7217 sal_memset(&bst_callbks, 0, sizeof(_bcm_bst_device_handlers_t)); 7218 bst_callbks.resolve_index = &_bcm_tr3_bst_index_resolve; 7219 bst_callbks.reverse_resolve_index = &_bcm_tr3_cosq_bst_map_resource_to_gport_cos; 7220 BCM_IF_ERROR_RETURN(_bcm_bst_attach(unit, &bst_callbks)); 7221 7222 /* reserve resources ie schedulers and queues which are allocated by 7223 * soc layer and no gport support is available for the ports. */ 7224 BCM_PBMP_CLEAR(mmu_info->gport_unavail_pbm); 7225 PBMP_CE_ITER(unit, port) { 7226 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_reserve_gport_resources(unit, port)); 7227 BCM_PBMP_PORT_ADD(mmu_info->gport_unavail_pbm, port); 7228 } 7229 7230 PBMP_ITER(PBMP_AXP_ALL(unit), port) { 7231 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_reserve_gport_resources(unit, port)); 7232 } 7233 7234 if (!mmu_info->curr_shared_limit) { 7235 BCM_IF_ERROR_RETURN(soc_tr3_mmu_get_shared_size(unit, 7236 &mmu_info->curr_shared_limit)); 7237 } 7238 mmu_info->axp_ets_mode = 0; 7239 7240 #ifdef BCM_WARM_BOOT_SUPPORT 7241 if (SOC_WARM_BOOT(unit)) { 7242 return bcm_tr3_cosq_reinit(unit); 7243 } else { 7244 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_wb_alloc(unit)); 7245 } 7246 #endif /* BCM_WARM_BOOT_SUPPORT */ 7247 /* Setup hsp gport and software structures */ 7248 PBMP_ALL_ITER(unit, port) { 7249 if (IS_TR3_HSP_PORT(unit, port)) { 7250 BCM_IF_ERROR_RETURN(_bcm_tr3_hsp_hierarchy_setup(unit, port)); 7251 } 7252 } 7253 /* Add default entries for PORT_COS_MAP memory profile */ 7254 BCM_IF_ERROR_RETURN(bcm_tr3_cosq_config_set(unit, numq)); 7255 7256 /* Add default entries for PRIO2COS_PROFILE register profile */ 7257 sal_memset(rval64s, 0, sizeof(rval64s)); 7258 prval64s[0] = rval64s; 7259 profile_index = 0xffffffff; 7260 PBMP_PORT_ITER(unit, port) { 7261 if (profile_index == 0xffffffff) { 7262 BCM_IF_ERROR_RETURN 7263 (soc_profile_reg_add(unit, _bcm_tr3_llfc_profile[unit], 7264 prval64s, 16, &profile_index)); 7265 } else { 7266 BCM_IF_ERROR_RETURN 7267 (soc_profile_reg_reference(unit, _bcm_tr3_llfc_profile[unit], 7268 profile_index, 0)); 7269 } 7270 } 7271 7272 /* Add default entries for MMU_WRED_DROP_CURVE_PROFILE_x memory profile */ 7273 sal_memset(&entry_tcp_green, 0, sizeof(entry_tcp_green)); 7274 sal_memset(&entry_tcp_yellow, 0, sizeof(entry_tcp_yellow)); 7275 sal_memset(&entry_tcp_red, 0, sizeof(entry_tcp_red)); 7276 sal_memset(&entry_nontcp_green, 0, sizeof(entry_nontcp_green)); 7277 sal_memset(&entry_nontcp_yellow, 0, sizeof(entry_nontcp_yellow)); 7278 sal_memset(&entry_nontcp_red, 0, sizeof(entry_nontcp_red)); 7279 entries[0] = &entry_tcp_green; 7280 entries[1] = &entry_tcp_yellow; 7281 entries[2] = &entry_tcp_red; 7282 entries[3] = &entry_nontcp_green; 7283 entries[4] = &entry_nontcp_yellow; 7284 entries[5] = &entry_nontcp_red; 7285 for (ii = 0; ii < 6; ii++) { 7286 soc_mem_field32_set(unit, wred_mems[ii], entries[ii], MIN_THDf, 0x7fff); 7287 soc_mem_field32_set(unit, wred_mems[ii], entries[ii], MAX_THDf, 0x7fff); 7288 } 7289 profile_index = 0xffffffff; 7290 wred_prof_count = soc_mem_index_count(unit, MMU_WRED_CONFIGm); 7291 while (wred_prof_count) { 7292 if (profile_index == 0xffffffff) { 7293 BCM_IF_ERROR_RETURN 7294 (soc_profile_mem_add(unit, _bcm_tr3_wred_profile[unit], 7295 entries, 1, &profile_index)); 7296 } else { 7297 BCM_IF_ERROR_RETURN 7298 (soc_profile_mem_reference(unit, 7299 _bcm_tr3_wred_profile[unit], 7300 profile_index, 0)); 7301 } 7302 wred_prof_count -= 1; 7303 } 7304 7305 /* Starting the curr_merger_index from 2, 7306 * since 0 is configured in all the FC_MAP_TBL2 by default, 7307 * so it might effect the traffic of other queues 7308 */ 7309 mmu_info->curr_merger_index[0] = 2; 7310 mmu_info->curr_merger_index[1] = 2; 7311 mmu_info->curr_merger_index[2] = 2; 7312 mmu_info->curr_merger_index[3] = 2; 7313 return BCM_E_NONE; 7314 } 7315 7316 7317 /* 7318 * Function: 7319 * bcm_tr3_cosq_config_get 7320 * Purpose: 7321 * Get the number of cos queues 7322 * Parameters: 7323 * unit - unit number 7324 * numq - (Output) number of cosq 7325 * Returns: 7326 * BCM_E_XXX 7327 */ 7328 int 7329 bcm_tr3_cosq_config_get(int unit, int *numq) 7330 { 7331 if (numq != NULL) { 7332 *numq = _TR3_NUM_COS(unit); 7333 } 7334 7335 return BCM_E_NONE; 7336 } 7337 7338 /* 7339 * Function: 7340 * _bcm_tr3_cosq_mapping_set 7341 * Purpose: 7342 * Set COS queue for the specified priority of an ingress port 7343 * Parameters: 7344 * unit - (IN) unit number 7345 * ing_port - (IN) ingress port 7346 * gport - (IN) queue group GPORT identifier 7347 * priority - (IN) priority value to map 7348 * flags - (IN) BCM_COSQ_GPORT_XXX_QUEUE_GROUP 7349 * gport - (IN) queue group GPORT identifier 7350 * cosq - (IN) COS queue number 7351 * Returns: 7352 * BCM_E_XXX 7353 */ 7354 STATIC int 7355 _bcm_tr3_cosq_mapping_set(int unit, bcm_port_t ing_port, bcm_cos_t priority, 7356 uint32 flags, bcm_gport_t gport, bcm_cos_queue_t cosq) 7357 { 7358 bcm_port_t local_port, outport = -1; 7359 bcm_cos_queue_t hw_cosq; 7360 soc_field_t field = INVALIDf, field2 = INVALIDf; 7361 cos_map_sel_entry_t cos_map_sel_entry; 7362 port_cos_map_entry_t cos_map_entries[16]; 7363 void *entries[1]; 7364 uint32 old_index, new_index; 7365 voq_cos_map_entry_t voq_cos_map; 7366 _bcm_tr3_cosq_node_t *node = NULL; 7367 _bcm_tr3_mmu_info_t *mmu_info; 7368 int rv; 7369 7370 if (priority < 0 || priority >= 16) { 7371 return BCM_E_PARAM; 7372 } 7373 7374 BCM_IF_ERROR_RETURN 7375 (_bcm_tr3_cosq_localport_resolve(unit, ing_port, &local_port)); 7376 7377 if (gport != -1) { 7378 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_localport_resolve(unit, gport, &outport)); 7379 } 7380 7381 mmu_info = _bcm_tr3_mmu_info[unit]; 7382 7383 switch (flags) { 7384 case BCM_COSQ_GPORT_UCAST_QUEUE_GROUP: 7385 if (gport == -1) { 7386 hw_cosq = cosq; 7387 } else { 7388 BCM_IF_ERROR_RETURN 7389 (_bcm_tr3_cosq_index_resolve 7390 (unit, gport, cosq, _BCM_TR3_COSQ_INDEX_STYLE_COS, 7391 NULL, &hw_cosq, NULL)); 7392 7393 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 7394 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) { 7395 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_node_get(unit, gport, cosq, 7396 NULL, NULL, NULL, &node)); 7397 7398 if (node->hw_index >= mmu_info->num_base_queues) { 7399 return BCM_E_PARAM; 7400 } 7401 } 7402 } 7403 7404 if ((outport != -1) && (IS_HG_PORT(unit, outport))) { 7405 field = HG_COSf; 7406 } else { 7407 field = UC_COS1f; 7408 } 7409 break; 7410 case BCM_COSQ_GPORT_MCAST_QUEUE_GROUP: 7411 if (gport == -1) { 7412 hw_cosq = cosq; 7413 } else { 7414 BCM_IF_ERROR_RETURN 7415 (_bcm_tr3_cosq_index_resolve 7416 (unit, gport, cosq, _BCM_TR3_COSQ_INDEX_STYLE_COS, 7417 NULL, &hw_cosq, NULL)); 7418 } 7419 field = MC_COS1f; 7420 break; 7421 case BCM_COSQ_GPORT_UCAST_QUEUE_GROUP | BCM_COSQ_GPORT_MCAST_QUEUE_GROUP: 7422 if (gport == -1) { 7423 hw_cosq = cosq; 7424 } else { 7425 return BCM_E_PARAM; 7426 } 7427 field = UC_COS1f; 7428 field2 = MC_COS1f; 7429 break; 7430 case BCM_COSQ_GPORT_DESTMOD_UCAST_QUEUE_GROUP: 7431 case (BCM_COSQ_GPORT_WITH_ID | BCM_COSQ_GPORT_DESTMOD_UCAST_QUEUE_GROUP): 7432 if (gport == -1) { 7433 hw_cosq = cosq; 7434 } else { 7435 BCM_IF_ERROR_RETURN 7436 (_bcm_tr3_cosq_index_resolve 7437 (unit, gport, cosq, _BCM_TR3_COSQ_INDEX_STYLE_COS, 7438 NULL, &hw_cosq, NULL)); 7439 } 7440 7441 BCM_IF_ERROR_RETURN( 7442 READ_VOQ_COS_MAPm(unit, MEM_BLOCK_ALL, priority, &voq_cos_map)); 7443 soc_mem_field32_get(unit, VOQ_COS_MAPm, &voq_cos_map, 7444 VOQ_COS_USE_MODf); 7445 7446 /* Setting the VOQ_PORT_BASE_SELECT, 7447 so that BASE_QUEUE_NUM_1 is used for queue 7448 calculation */ 7449 7450 soc_mem_field32_set(unit, VOQ_COS_MAPm, 7451 &voq_cos_map, VOQ_PORT_BASE_SELECTf, 1); 7452 soc_mem_field32_set(unit, VOQ_COS_MAPm, 7453 &voq_cos_map, VOQ_COS_USE_MODf, 1); 7454 7455 if (soc_mem_field32_get(unit, VOQ_COS_MAPm, &voq_cos_map, 7456 VOQ_COS_OFFSETf) != hw_cosq) { 7457 soc_mem_field32_set(unit, VOQ_COS_MAPm, 7458 &voq_cos_map, VOQ_COS_OFFSETf, hw_cosq); 7459 } 7460 7461 BCM_IF_ERROR_RETURN( 7462 soc_mem_write(unit, VOQ_COS_MAPm, MEM_BLOCK_ANY, priority, 7463 &voq_cos_map)); 7464 return BCM_E_NONE; 7465 break; 7466 default: 7467 return BCM_E_PARAM; 7468 } 7469 7470 entries[0] = &cos_map_entries; 7471 7472 if (local_port == CMIC_PORT(unit)) { 7473 local_port = SOC_INFO(unit).cpu_hg_index; 7474 } 7475 BCM_IF_ERROR_RETURN 7476 (READ_COS_MAP_SELm(unit, MEM_BLOCK_ANY, local_port, 7477 &cos_map_sel_entry)); 7478 old_index = soc_mem_field32_get(unit, COS_MAP_SELm, &cos_map_sel_entry, 7479 SELECTf); 7480 old_index *= 16; 7481 7482 BCM_IF_ERROR_RETURN 7483 (soc_profile_mem_get(unit, _bcm_tr3_cos_map_profile[unit], 7484 old_index, 16, entries)); 7485 soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[priority], field, 7486 hw_cosq); 7487 if (field2 != INVALIDf) { 7488 soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[priority], 7489 field2,hw_cosq); 7490 } 7491 7492 soc_mem_lock(unit, PORT_COS_MAPm); 7493 7494 rv = soc_profile_mem_delete(unit, _bcm_tr3_cos_map_profile[unit], 7495 old_index); 7496 7497 if (BCM_FAILURE(rv)) { 7498 soc_mem_unlock(unit, PORT_COS_MAPm); 7499 return rv; 7500 } 7501 7502 rv = soc_profile_mem_add(unit, _bcm_tr3_cos_map_profile[unit], entries, 7503 16, &new_index); 7504 7505 if (rv == SOC_E_RESOURCE) { 7506 (void)soc_profile_mem_reference(unit, _bcm_tr3_cos_map_profile[unit], 7507 old_index, 16); 7508 } 7509 7510 soc_mem_unlock(unit, PORT_COS_MAPm); 7511 7512 if (BCM_FAILURE(rv)) { 7513 return rv; 7514 } 7515 7516 soc_mem_field32_set(unit, COS_MAP_SELm, &cos_map_sel_entry, SELECTf, 7517 new_index / 16); 7518 BCM_IF_ERROR_RETURN 7519 (WRITE_COS_MAP_SELm(unit, MEM_BLOCK_ANY, local_port, 7520 &cos_map_sel_entry)); 7521 7522 #ifndef BCM_COSQ_HIGIG_MAP_DISABLE 7523 if (IS_CPU_PORT(unit, local_port)) { 7524 BCM_IF_ERROR_RETURN 7525 (soc_mem_field32_modify(unit, COS_MAP_SELm, 7526 SOC_INFO(unit).cpu_hg_index, SELECTf, 7527 new_index / 16)); 7528 } 7529 #endif /* BCM_COSQ_HIGIG_MAP_DISABLE */ 7530 7531 return BCM_E_NONE; 7532 } 7533 7534 /* 7535 * Function: 7536 * bcm_tr3_cosq_mapping_set 7537 * Purpose: 7538 * Set which cosq a given priority should fall into 7539 * Parameters: 7540 * unit - (IN) unit number 7541 * gport - (IN) queue group GPORT identifier 7542 * priority - (IN) priority value to map 7543 * cosq - (IN) COS queue to map to 7544 * Returns: 7545 * BCM_E_XXX 7546 */ 7547 7548 int 7549 bcm_tr3_cosq_mapping_set(int unit, bcm_port_t port, bcm_cos_t priority, 7550 bcm_cos_queue_t cosq) 7551 { 7552 bcm_port_t local_port; 7553 bcm_pbmp_t pbmp; 7554 7555 BCM_PBMP_CLEAR(pbmp); 7556 7557 if (port == -1) { 7558 BCM_PBMP_ASSIGN(pbmp, PBMP_ALL(unit)); 7559 } else { 7560 if (BCM_GPORT_IS_SET(port)) { 7561 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 7562 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port) || 7563 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) || 7564 BCM_GPORT_IS_SCHEDULER(port)) { 7565 return BCM_E_PARAM; 7566 } else if (BCM_GPORT_IS_LOCAL(port)) { 7567 local_port = BCM_GPORT_LOCAL_GET(port); 7568 } else { 7569 return BCM_E_PARAM; 7570 } 7571 } else { 7572 local_port = port; 7573 } 7574 7575 if (!SOC_PORT_VALID(unit, local_port)) { 7576 return BCM_E_PORT; 7577 } 7578 7579 BCM_PBMP_PORT_ADD(pbmp, local_port); 7580 } 7581 7582 PBMP_ITER(pbmp, local_port) { 7583 if (_bcm_tr3_cosq_port_has_ets(unit, local_port)) 7584 return BCM_E_PARAM; 7585 } 7586 7587 if ((cosq < 0) || (cosq >= _TR3_NUM_COS(unit))) { 7588 return BCM_E_PARAM; 7589 } 7590 7591 PBMP_ITER(pbmp, local_port) { 7592 if (IS_LB_PORT(unit, local_port) || IS_HG_PORT(unit, local_port)) { 7593 continue; 7594 } 7595 7596 /* If no ETS/port, map the int prio symmetrically for ucast and 7597 * mcast */ 7598 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_mapping_set(unit, local_port, 7599 priority, 7600 BCM_COSQ_GPORT_UCAST_QUEUE_GROUP | BCM_COSQ_GPORT_MCAST_QUEUE_GROUP, 7601 -1, cosq)); 7602 } 7603 7604 PBMP_ITER(pbmp, local_port) { 7605 if (IS_HG_PORT(unit, local_port)) { 7606 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_mapping_set(unit, local_port, 7607 priority, 7608 BCM_COSQ_GPORT_UCAST_QUEUE_GROUP | BCM_COSQ_GPORT_MCAST_QUEUE_GROUP, 7609 -1, cosq)); 7610 } 7611 } 7612 7613 return BCM_E_NONE; 7614 } 7615 7616 /* 7617 * Function: 7618 * bcm_tr3_cosq_mapping_get 7619 * Purpose: 7620 * Determine which COS queue a given priority currently maps to. 7621 * Parameters: 7622 * unit - (IN) unit number 7623 * gport - (IN) queue group GPORT identifier 7624 * priority - (IN) priority value to map 7625 * cosq - (OUT) COS queue to map to 7626 * Returns: 7627 * BCM_E_XXX 7628 */ 7629 int 7630 _bcm_tr3_cosq_mapping_get(int unit, bcm_port_t ing_port, bcm_cos_t priority, 7631 uint32 flags, bcm_gport_t *gport, 7632 bcm_cos_queue_t *cosq) 7633 { 7634 _bcm_tr3_mmu_info_t *mmu_info; 7635 _bcm_tr3_cosq_port_info_t *port_info; 7636 _bcm_tr3_cosq_node_t *node; 7637 bcm_port_t local_port; 7638 bcm_cos_queue_t hw_cosq = BCM_COS_INVALID; 7639 int index, ii; 7640 cos_map_sel_entry_t cos_map_sel_entry; 7641 voq_cos_map_entry_t voq_cos_map; 7642 void *entry_p; 7643 7644 if (priority < 0 || priority >= 16) { 7645 return BCM_E_PARAM; 7646 } 7647 7648 if (flags != BCM_COSQ_GPORT_UCAST_QUEUE_GROUP && 7649 flags != BCM_COSQ_GPORT_MCAST_QUEUE_GROUP && 7650 flags != (BCM_COSQ_GPORT_DESTMOD_UCAST_QUEUE_GROUP | 7651 BCM_COSQ_GPORT_WITH_ID) && 7652 flags != BCM_COSQ_GPORT_DESTMOD_UCAST_QUEUE_GROUP) { 7653 return BCM_E_PARAM; 7654 } 7655 7656 BCM_IF_ERROR_RETURN 7657 (_bcm_tr3_cosq_localport_resolve(unit, ing_port, &local_port)); 7658 7659 if (gport) { 7660 *gport = BCM_GPORT_INVALID; 7661 } 7662 7663 *cosq = BCM_COS_INVALID; 7664 7665 if (local_port == CMIC_PORT(unit)) { 7666 BCM_IF_ERROR_RETURN 7667 (READ_COS_MAP_SELm(unit, MEM_BLOCK_ANY, SOC_INFO(unit).cpu_hg_index, 7668 &cos_map_sel_entry)); 7669 } else { 7670 BCM_IF_ERROR_RETURN 7671 (READ_COS_MAP_SELm(unit, MEM_BLOCK_ANY, local_port, 7672 &cos_map_sel_entry)); 7673 } 7674 index = soc_mem_field32_get(unit, COS_MAP_SELm, &cos_map_sel_entry, 7675 SELECTf); 7676 index *= 16; 7677 7678 mmu_info = _bcm_tr3_mmu_info[unit]; 7679 port_info = &mmu_info->port_info[local_port]; 7680 7681 switch (flags) { 7682 case BCM_COSQ_GPORT_UCAST_QUEUE_GROUP: 7683 entry_p = SOC_PROFILE_MEM_ENTRY(unit, _bcm_tr3_cos_map_profile[unit], 7684 port_cos_map_entry_t *, 7685 index + priority); 7686 7687 hw_cosq = soc_mem_field32_get(unit, PORT_COS_MAPm, entry_p, UC_COS1f); 7688 if (gport) { 7689 for (ii = port_info->uc_base; ii < port_info->uc_limit; ii++) { 7690 node = &mmu_info->queue_node[ii]; 7691 if (node->numq > 0 && node->hw_cosq == hw_cosq) { 7692 *gport = node->gport; 7693 *cosq = 0; 7694 break; 7695 } 7696 } 7697 if (ii == port_info->uc_limit) { 7698 return BCM_E_NOT_FOUND; 7699 } 7700 } 7701 break; 7702 case BCM_COSQ_GPORT_MCAST_QUEUE_GROUP: 7703 entry_p = SOC_PROFILE_MEM_ENTRY(unit, _bcm_tr3_cos_map_profile[unit], 7704 port_cos_map_entry_t *, 7705 index + priority); 7706 7707 hw_cosq = soc_mem_field32_get(unit, PORT_COS_MAPm, entry_p, MC_COS1f); 7708 if (gport) { 7709 for (ii = port_info->mc_base; ii < port_info->mc_limit; ii++) { 7710 node = &mmu_info->mc_queue_node[ii]; 7711 if (node->numq > 0 && node->hw_cosq == hw_cosq) { 7712 *gport = node->gport; 7713 *cosq = 0; 7714 break; 7715 } 7716 } 7717 if (ii == port_info->mc_limit) { 7718 return BCM_E_NOT_FOUND; 7719 } 7720 } 7721 break; 7722 case BCM_COSQ_GPORT_DESTMOD_UCAST_QUEUE_GROUP: 7723 case (BCM_COSQ_GPORT_WITH_ID | BCM_COSQ_GPORT_DESTMOD_UCAST_QUEUE_GROUP): 7724 BCM_IF_ERROR_RETURN( 7725 READ_VOQ_COS_MAPm(unit, MEM_BLOCK_ALL, priority, &voq_cos_map)); 7726 hw_cosq = soc_mem_field32_get(unit, VOQ_COS_MAPm, 7727 &voq_cos_map, VOQ_COS_OFFSETf); 7728 if (gport) { 7729 for (ii = mmu_info->num_base_queues; 7730 ii < _BCM_TR3_NUM_L2_UC_LEAVES; ii++) { 7731 7732 node = &mmu_info->queue_node[ii]; 7733 if ((node->in_use == FALSE) || (node->local_port == local_port)) { 7734 continue; 7735 } 7736 7737 if (node->hw_cosq == hw_cosq) { 7738 *gport = node->gport; 7739 break; 7740 } 7741 } 7742 if (ii == _BCM_TR3_NUM_L2_UC_LEAVES) { 7743 return BCM_E_NOT_FOUND; 7744 } 7745 } 7746 break; 7747 /* Keeping this as safe check, keep this intentionally */ 7748 /* coverity[dead_error_begin] */ 7749 default: 7750 break; 7751 } 7752 7753 if (gport && 7754 (*gport == BCM_GPORT_INVALID) && (*cosq == BCM_COS_INVALID)) { 7755 return BCM_E_NOT_FOUND; 7756 } 7757 7758 *cosq = hw_cosq; 7759 7760 return BCM_E_NONE; 7761 } 7762 7763 int 7764 bcm_tr3_cosq_mapping_get(int unit, bcm_port_t port, bcm_cos_t priority, 7765 bcm_cos_queue_t *cosq) 7766 { 7767 bcm_port_t local_port; 7768 bcm_pbmp_t pbmp; 7769 7770 BCM_PBMP_CLEAR(pbmp); 7771 7772 if (port == -1) { 7773 BCM_PBMP_ASSIGN(pbmp, PBMP_ALL(unit)); 7774 } else { 7775 if (BCM_GPORT_IS_SET(port)) { 7776 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 7777 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port) || 7778 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) || 7779 BCM_GPORT_IS_SCHEDULER(port)) { 7780 return BCM_E_PARAM; 7781 } else if (BCM_GPORT_IS_LOCAL(port)) { 7782 local_port = BCM_GPORT_LOCAL_GET(port); 7783 } else { 7784 return BCM_E_PARAM; 7785 } 7786 } else { 7787 local_port = port; 7788 } 7789 7790 if (!SOC_PORT_VALID(unit, local_port)) { 7791 return BCM_E_PORT; 7792 } 7793 7794 BCM_PBMP_PORT_ADD(pbmp, local_port); 7795 } 7796 7797 PBMP_ITER(pbmp, local_port) { 7798 if (IS_LB_PORT(unit, local_port)) { 7799 continue; 7800 } 7801 7802 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_mapping_get(unit, local_port, 7803 priority, BCM_COSQ_GPORT_UCAST_QUEUE_GROUP, NULL, cosq)); 7804 break; 7805 } 7806 7807 return BCM_E_NONE; 7808 } 7809 7810 int 7811 bcm_tr3_cosq_gport_mapping_set(int unit, bcm_port_t ing_port, 7812 bcm_cos_t int_pri, uint32 flags, 7813 bcm_gport_t gport, bcm_cos_queue_t cosq) 7814 { 7815 return _bcm_tr3_cosq_mapping_set(unit, ing_port, int_pri, flags, gport, 7816 cosq); 7817 } 7818 7819 int 7820 bcm_tr3_cosq_gport_mapping_get(int unit, bcm_port_t ing_port, 7821 bcm_cos_t int_pri, uint32 flags, 7822 bcm_gport_t *gport, bcm_cos_queue_t *cosq) 7823 { 7824 if (gport == NULL || cosq == NULL) { 7825 return BCM_E_PARAM; 7826 } 7827 7828 return _bcm_tr3_cosq_mapping_get(unit, ing_port, int_pri, flags, gport, 7829 cosq); 7830 } 7831 7832 /* 7833 * Function: 7834 * bcm_tr3_cosq_port_sched_set 7835 * Purpose: 7836 * Set up class-of-service policy and corresponding weights and delay 7837 * Parameters: 7838 * unit - (IN) unit number 7839 * pbm - (IN) port bitmap 7840 * mode - (IN) Scheduling mode (BCM_COSQ_xxx) 7841 * weights - (IN) Weights for each COS queue 7842 * delay - This parameter is not used 7843 * Returns: 7844 * BCM_E_XXX 7845 */ 7846 int 7847 bcm_tr3_cosq_port_sched_set(int unit, bcm_pbmp_t pbm, 7848 int mode, const int *weights, int delay) 7849 { 7850 bcm_port_t port; 7851 int num_weights, i; 7852 7853 BCM_PBMP_ITER(pbm, port) { 7854 num_weights = _TR3_NUM_COS(unit); 7855 if (mode == BCM_COSQ_STRICT) { 7856 for (i = 0; i < num_weights; i++) { 7857 BCM_IF_ERROR_RETURN 7858 (_bcm_tr3_cosq_sched_set(unit, port, i, mode, weights[i], 1)); 7859 } 7860 } else { 7861 for (i = (num_weights-1); i >= 0; i--) { 7862 BCM_IF_ERROR_RETURN 7863 (_bcm_tr3_cosq_sched_set(unit, port, i, mode, weights[i], 1)); 7864 } 7865 } 7866 } 7867 7868 return BCM_E_NONE; 7869 } 7870 7871 /* 7872 * Function: 7873 * bcm_tr3_cosq_port_sched_get 7874 * Purpose: 7875 * Retrieve class-of-service policy and corresponding weights and delay 7876 * Parameters: 7877 * unit - (IN) unit number 7878 * pbm - (IN) port bitmap 7879 * mode - (OUT) Scheduling mode (BCM_COSQ_XXX) 7880 * weights - (OUT) Weights for each COS queue 7881 * delay - This parameter is not used 7882 * Returns: 7883 * BCM_E_XXX 7884 */ 7885 int 7886 bcm_tr3_cosq_port_sched_get(int unit, bcm_pbmp_t pbm, 7887 int *mode, int *weights, int *delay) 7888 { 7889 bcm_port_t port; 7890 int num_weights, i; 7891 7892 BCM_PBMP_ITER(pbm, port) { 7893 num_weights = _TR3_NUM_COS(unit); 7894 for (i = 0 ; i < num_weights; i++) { 7895 BCM_IF_ERROR_RETURN( 7896 _bcm_tr3_cosq_sched_get(unit, port, i, mode, &weights[i])); 7897 } 7898 } 7899 7900 return BCM_E_NONE; 7901 } 7902 7903 /* 7904 * Function: 7905 * bcm_tr3_cosq_sched_weight_max_get 7906 * Purpose: 7907 * Retrieve maximum weights for given COS policy 7908 * Parameters: 7909 * unit - (IN) unit number 7910 * mode - (IN) Scheduling mode (BCM_COSQ_xxx) 7911 * weight_max - (OUT) Maximum weight for COS queue. 7912 * Returns: 7913 * BCM_E_XXX 7914 */ 7915 int 7916 bcm_tr3_cosq_sched_weight_max_get(int unit, int mode, int *weight_max) 7917 { 7918 switch (mode) { 7919 case BCM_COSQ_STRICT: 7920 *weight_max = BCM_COSQ_WEIGHT_STRICT; 7921 break; 7922 case BCM_COSQ_ROUND_ROBIN: 7923 *weight_max = 1; 7924 break; 7925 case BCM_COSQ_WEIGHTED_ROUND_ROBIN: 7926 if (soc_property_get(unit, spn_BCM5664X_WRR_GRANULARITY_1, 0)) { 7927 *weight_max = (1 << 7) - 1; 7928 } else { 7929 *weight_max = (1 << 6) - 1; 7930 } 7931 break; 7932 case BCM_COSQ_DEFICIT_ROUND_ROBIN: 7933 *weight_max = (1 << 7) - 1; 7934 break; 7935 default: 7936 return BCM_E_PARAM; 7937 } 7938 7939 return BCM_E_NONE; 7940 } 7941 7942 /* 7943 * Function: 7944 * bcm_tr3_cosq_bandwidth_set 7945 * Purpose: 7946 * Configure COS queue bandwidth control 7947 * Parameters: 7948 * unit - (IN) unit number 7949 * port - (IN) port number or GPORT identifier 7950 * cosq - (IN) COS queue number 7951 * min_quantum - (IN) 7952 * max_quantum - (IN) 7953 * burst_quantum - (IN) 7954 * flags - (IN) 7955 * Returns: 7956 * BCM_E_XXX 7957 * Notes: 7958 * If port is any form of local port, cosq is the hardware queue index. 7959 */ 7960 int 7961 bcm_tr3_cosq_port_bandwidth_set(int unit, bcm_port_t port, 7962 bcm_cos_queue_t cosq, 7963 uint32 min_quantum, uint32 max_quantum, 7964 uint32 burst_quantum, uint32 flags) 7965 { 7966 uint32 burst_min, burst_max; 7967 7968 if (cosq < 0) { 7969 return BCM_E_PARAM; 7970 } 7971 7972 burst_min = (min_quantum > 0) ? 7973 _bcm_td_default_burst_size(unit, port, min_quantum) : 0; 7974 7975 burst_max = (max_quantum > 0) ? 7976 _bcm_td_default_burst_size(unit, port, max_quantum) : 0; 7977 7978 return _bcm_tr3_cosq_bucket_set(unit, port, cosq, min_quantum, max_quantum, 7979 burst_min, burst_max, flags); 7980 } 7981 7982 /* 7983 * Function: 7984 * bcm_tr3_cosq_bandwidth_get 7985 * Purpose: 7986 * Get COS queue bandwidth control configuration 7987 * Parameters: 7988 * unit - (IN) unit number 7989 * port - (IN) port number or GPORT identifier 7990 * cosq - (IN) COS queue number 7991 * min_quantum - (OUT) 7992 * max_quantum - (OUT) 7993 * burst_quantum - (OUT) 7994 * flags - (OUT) 7995 * Returns: 7996 * BCM_E_XXX 7997 * Notes: 7998 * If port is any form of local port, cosq is the hardware queue index. 7999 */ 8000 int 8001 bcm_tr3_cosq_port_bandwidth_get(int unit, bcm_port_t port, 8002 bcm_cos_queue_t cosq, 8003 uint32 *min_quantum, uint32 *max_quantum, 8004 uint32 *burst_quantum, uint32 *flags) 8005 { 8006 uint32 kbit_burst_min; 8007 8008 if (cosq < -1) { 8009 return BCM_E_PARAM; 8010 } 8011 8012 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_bucket_get(unit, port, cosq, 8013 min_quantum, max_quantum, &kbit_burst_min, 8014 burst_quantum, flags)); 8015 return BCM_E_NONE; 8016 } 8017 8018 int 8019 bcm_tr3_cosq_port_pps_set(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 8020 int pps) 8021 { 8022 uint32 min, max, burst, burst_min, flags; 8023 bcm_port_t local_port = port; 8024 8025 if (!IS_CPU_PORT(unit, port)) { 8026 return BCM_E_PORT; 8027 } else if (cosq < 0 || cosq >= NUM_CPU_COSQ(unit)) { 8028 return BCM_E_PARAM; 8029 } 8030 8031 if (_bcm_tr3_cosq_port_has_ets(unit, port)) { 8032 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_l2_gport(unit, port, cosq, 8033 _BCM_TR3_NODE_MCAST, &port, NULL)); 8034 cosq = 0; 8035 } 8036 8037 BCM_IF_ERROR_RETURN 8038 (_bcm_tr3_cosq_bucket_get(unit, port, cosq, &min, &max, &burst_min, 8039 &burst, &flags)); 8040 8041 min = pps; 8042 burst_min = (min > 0) ? 8043 _bcm_td_default_burst_size(unit, local_port, min) : 0; 8044 burst = burst_min; 8045 8046 return _bcm_tr3_cosq_bucket_set(unit, port, cosq, min, pps, burst_min, burst, 8047 flags | BCM_COSQ_BW_PACKET_MODE); 8048 } 8049 8050 int 8051 bcm_tr3_cosq_port_pps_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 8052 int *pps) 8053 { 8054 uint32 min, max, burst, flags; 8055 8056 if (!IS_CPU_PORT(unit, port)) { 8057 return BCM_E_PORT; 8058 } else if (cosq < 0 || cosq >= NUM_CPU_COSQ(unit)) { 8059 return BCM_E_PARAM; 8060 } 8061 8062 if (_bcm_tr3_cosq_port_has_ets(unit, port)) { 8063 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_l2_gport(unit, port, cosq, 8064 _BCM_TR3_NODE_MCAST, &port, NULL)); 8065 cosq = 0; 8066 } 8067 8068 BCM_IF_ERROR_RETURN 8069 (_bcm_tr3_cosq_bucket_get(unit, port, cosq, &min, &max, &burst, &burst, 8070 &flags)); 8071 *pps = max; 8072 8073 return BCM_E_NONE; 8074 } 8075 8076 int 8077 bcm_tr3_cosq_port_burst_set(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 8078 int burst) 8079 { 8080 uint32 min, max, cur_burst, flags; 8081 8082 if (!IS_CPU_PORT(unit, port)) { 8083 return BCM_E_PORT; 8084 } else if (cosq < 0 || cosq >= NUM_CPU_COSQ(unit)) { 8085 return BCM_E_PARAM; 8086 } 8087 8088 if (_bcm_tr3_cosq_port_has_ets(unit, port)) { 8089 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_l2_gport(unit, port, cosq, 8090 _BCM_TR3_NODE_MCAST, &port, NULL)); 8091 cosq = 0; 8092 } 8093 8094 /* Get the current PPS and BURST settings */ 8095 BCM_IF_ERROR_RETURN 8096 (_bcm_tr3_cosq_bucket_get(unit, port, cosq, &min, &max, &cur_burst, 8097 &cur_burst, &flags)); 8098 8099 /* Replace the current BURST setting, keep PPS the same */ 8100 return _bcm_tr3_cosq_bucket_set(unit, port, cosq, min, max, burst, burst, 8101 flags | BCM_COSQ_BW_PACKET_MODE); 8102 } 8103 8104 int 8105 bcm_tr3_cosq_port_burst_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 8106 int *burst) 8107 { 8108 uint32 min, max, cur_burst, cur_burst_min, flags; 8109 8110 if (!IS_CPU_PORT(unit, port)) { 8111 return BCM_E_PORT; 8112 } else if (cosq < 0 || cosq >= NUM_CPU_COSQ(unit)) { 8113 return BCM_E_PARAM; 8114 } 8115 8116 if (_bcm_tr3_cosq_port_has_ets(unit, port)) { 8117 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_l2_gport(unit, port, cosq, 8118 _BCM_TR3_NODE_MCAST, &port, NULL)); 8119 cosq = 0; 8120 } 8121 8122 BCM_IF_ERROR_RETURN 8123 (_bcm_tr3_cosq_bucket_get(unit, port, cosq, &min, &max, 8124 &cur_burst_min, &cur_burst, &flags)); 8125 *burst = cur_burst; 8126 8127 return BCM_E_NONE; 8128 } 8129 8130 int 8131 bcm_tr3_cosq_discard_set(int unit, uint32 flags) 8132 { 8133 bcm_port_t port; 8134 int pool; 8135 _bcm_tr3_mmu_info_t *mmu_info; 8136 8137 if ((mmu_info = _bcm_tr3_mmu_info[unit]) == NULL) { 8138 return BCM_E_INIT; 8139 } 8140 8141 if (flags & ~(BCM_COSQ_DISCARD_DEVICE | 8142 BCM_COSQ_DISCARD_NONTCP | 8143 BCM_COSQ_DISCARD_COLOR_ALL | 8144 BCM_COSQ_DISCARD_TCP | 8145 BCM_COSQ_DISCARD_COLOR_GREEN | 8146 BCM_COSQ_DISCARD_COLOR_YELLOW | 8147 BCM_COSQ_DISCARD_COLOR_RED | 8148 BCM_COSQ_DISCARD_CAP_AVERAGE | 8149 BCM_COSQ_DISCARD_ENABLE | 8150 BCM_COSQ_DISCARD_MARK_CONGESTION)) { 8151 return BCM_E_PARAM; 8152 } 8153 8154 flags &= ~(BCM_COSQ_DISCARD_NONTCP | BCM_COSQ_DISCARD_COLOR_ALL); 8155 8156 PBMP_PORT_ITER(unit, port) { 8157 for (pool = 0; pool < 4; pool++) { 8158 BCM_IF_ERROR_RETURN 8159 (_bcm_tr3_cosq_wred_set(unit, port, pool, flags, 0, 0, 0, 0, 8160 FALSE, BCM_COSQ_DISCARD_PORT)); 8161 } 8162 } 8163 8164 return BCM_E_NONE; 8165 } 8166 8167 int 8168 bcm_tr3_cosq_discard_get(int unit, uint32 *flags) 8169 { 8170 bcm_port_t port; 8171 8172 PBMP_PORT_ITER(unit, port) { 8173 *flags = 0; 8174 /* use setting from hardware cosq index 0 of the first port */ 8175 return _bcm_tr3_cosq_wred_get(unit, port, 0, flags, NULL, NULL, NULL, 8176 NULL, BCM_COSQ_DISCARD_PORT); 8177 } 8178 8179 return BCM_E_NOT_FOUND; 8180 } 8181 8182 /* 8183 * Function: 8184 * bcm_tr3_cosq_discard_port_set 8185 * Purpose: 8186 * Configure port WRED setting 8187 * Parameters: 8188 * unit - (IN) unit number 8189 * port - (IN) port number or GPORT identifier 8190 * cosq - (IN) COS queue number 8191 * color - (IN) 8192 * drop_start - (IN) 8193 * drop_slot - (IN) 8194 * average_time - (IN) 8195 * Returns: 8196 * BCM_E_XXX 8197 * Notes: 8198 * If port is any form of local port, cosq is the hardware queue index. 8199 */ 8200 int 8201 bcm_tr3_cosq_discard_port_set(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 8202 uint32 color, int drop_start, int drop_slope, 8203 int average_time) 8204 { 8205 bcm_port_t local_port; 8206 bcm_pbmp_t pbmp; 8207 int gain; 8208 uint32 min_thresh, max_thresh, shared_limit; 8209 uint32 rval, bits; 8210 int numq, i, flags = 0; 8211 8212 if (drop_start < 0 || drop_start > 100 || 8213 drop_slope < 0 || drop_slope > 90) { 8214 return BCM_E_PARAM; 8215 } 8216 8217 /* 8218 * average queue size is reculated every 8us, the formula is 8219 * avg_qsize(t + 1) = 8220 * avg_qsize(t) + (cur_qsize - avg_qsize(t)) / (2 ** gain) 8221 * gain = log2(average_time / 8) 8222 */ 8223 bits = (average_time / 8) & 0xffff; 8224 if (bits != 0) { 8225 bits |= bits >> 1; 8226 bits |= bits >> 2; 8227 bits |= bits >> 4; 8228 bits |= bits >> 8; 8229 gain = _shr_popcount(bits) - 1; 8230 } else { 8231 gain = 0; 8232 } 8233 8234 /* 8235 * per-port cell limit may be disabled. 8236 * per-port per-cos cell limit may be set to use dynamic method. 8237 * therefore drop_start percentage is based on per-device total shared 8238 * cells. 8239 */ 8240 BCM_IF_ERROR_RETURN(READ_OP_BUFFER_SHARED_LIMIT_CELLr(unit, &rval)); 8241 shared_limit = soc_reg_field_get(unit, OP_BUFFER_SHARED_LIMIT_CELLr, 8242 rval, OP_BUFFER_SHARED_LIMIT_CELLf); 8243 min_thresh = drop_start * shared_limit / 100; 8244 8245 /* Calculate the max threshold. For a given slope (angle in 8246 * degrees), determine how many packets are in the range from 8247 * 0% drop probability to 100% drop probability. Add that 8248 * number to the min_treshold to the the max_threshold. 8249 */ 8250 max_thresh = min_thresh + _bcm_tr3_angle_to_cells(drop_slope); 8251 if (max_thresh > TR3_CELL_FIELD_MAX) { 8252 max_thresh = TR3_CELL_FIELD_MAX; 8253 } 8254 8255 if (BCM_GPORT_IS_SET(port)) { 8256 if (cosq == -1) { 8257 cosq = 0; 8258 flags = BCM_COSQ_DISCARD_PORT; 8259 } 8260 numq = 1; 8261 for (i = 0; i < numq; i++) { 8262 BCM_IF_ERROR_RETURN 8263 (_bcm_tr3_cosq_wred_set(unit, port, cosq + i, color, 8264 min_thresh, max_thresh, 100, gain, 8265 TRUE, flags)); 8266 } 8267 } else { 8268 if (port == -1) { 8269 BCM_PBMP_ASSIGN(pbmp, PBMP_PORT_ALL(unit)); 8270 } else if (!SOC_PORT_VALID(unit, port)) { 8271 return BCM_E_PORT; 8272 } else { 8273 BCM_PBMP_PORT_SET(pbmp, port); 8274 } 8275 8276 BCM_PBMP_ITER(pbmp, local_port) { 8277 if (cosq == -1) { 8278 BCM_IF_ERROR_RETURN 8279 (_bcm_tr3_cosq_index_resolve(unit, local_port, cosq, 8280 _BCM_TR3_COSQ_INDEX_STYLE_WRED, 8281 NULL, NULL, &numq)); 8282 cosq = 0; 8283 } else { 8284 numq = 1; 8285 } 8286 for (i = 0; i < numq; i++) { 8287 BCM_IF_ERROR_RETURN 8288 (_bcm_tr3_cosq_wred_set(unit, local_port, cosq + i, 8289 color, min_thresh, max_thresh, 100, 8290 gain, TRUE, 0)); 8291 } 8292 } 8293 } 8294 8295 return BCM_E_NONE; 8296 } 8297 8298 /* 8299 * Function: 8300 * bcm_tr3_cosq_discard_port_get 8301 * Purpose: 8302 * Get port WRED setting 8303 * Parameters: 8304 * unit - (IN) unit number 8305 * port - (IN) port number or GPORT identifier 8306 * cosq - (IN) COS queue number 8307 * color - (OUT) 8308 * drop_start - (OUT) 8309 * drop_slot - (OUT) 8310 * average_time - (OUT) 8311 * Returns: 8312 * BCM_E_XXX 8313 * Notes: 8314 * If port is any form of local port, cosq is the hardware queue index. 8315 */ 8316 int 8317 bcm_tr3_cosq_discard_port_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 8318 uint32 color, int *drop_start, int *drop_slope, 8319 int *average_time) 8320 { 8321 bcm_port_t local_port; 8322 bcm_pbmp_t pbmp; 8323 int gain, drop_prob; 8324 uint32 min_thresh, max_thresh, shared_limit; 8325 uint32 rval; 8326 8327 if (drop_start == NULL || drop_slope == NULL || average_time == NULL) { 8328 return BCM_E_PARAM; 8329 } 8330 8331 if (BCM_GPORT_IS_SET(port)) { 8332 local_port = port; 8333 } else { 8334 if (port == -1) { 8335 BCM_PBMP_ASSIGN(pbmp, PBMP_PORT_ALL(unit)); 8336 } else if (!SOC_PORT_VALID(unit, port)) { 8337 return BCM_E_PORT; 8338 } else { 8339 BCM_PBMP_PORT_SET(pbmp, port); 8340 } 8341 BCM_PBMP_ITER(pbmp, local_port) { 8342 break; 8343 } 8344 } 8345 8346 BCM_IF_ERROR_RETURN 8347 (_bcm_tr3_cosq_wred_get(unit, local_port, cosq == -1 ? 0 : cosq, 8348 &color, &min_thresh, &max_thresh, &drop_prob, 8349 &gain, 0)); 8350 8351 /* 8352 * average queue size is reculated every 4us, the formula is 8353 * avg_qsize(t + 1) = 8354 * avg_qsize(t) + (cur_qsize - avg_qsize(t)) / (2 ** gain) 8355 */ 8356 *average_time = (1 << gain) * 4; 8357 8358 /* 8359 * per-port cell limit may be disabled. 8360 * per-port per-cos cell limit may be set to use dynamic method. 8361 * therefore drop_start percentage is based on per-device total shared 8362 * cells. 8363 */ 8364 BCM_IF_ERROR_RETURN(READ_OP_BUFFER_SHARED_LIMIT_CELLr(unit, &rval)); 8365 shared_limit = soc_reg_field_get(unit, OP_BUFFER_SHARED_LIMIT_CELLr, 8366 rval, OP_BUFFER_SHARED_LIMIT_CELLf); 8367 8368 if (min_thresh > shared_limit) { 8369 min_thresh = shared_limit; 8370 } 8371 8372 if (max_thresh > shared_limit) { 8373 max_thresh = shared_limit; 8374 } 8375 8376 *drop_start = min_thresh * 100 / shared_limit; 8377 8378 /* Calculate the slope using the min and max threshold. 8379 * The angle is calculated knowing drop probability at min 8380 * threshold is 0% and drop probability at max threshold is 100%. 8381 */ 8382 *drop_slope = _bcm_tr3_cells_to_angle(max_thresh - min_thresh); 8383 8384 return BCM_E_NONE; 8385 } 8386 8387 STATIC int 8388 _bcm_tr3_distribute_u64(uint64 value, uint64 *l, uint64 *r) 8389 { 8390 uint64 tmp, tmp1; 8391 8392 tmp = value; 8393 COMPILER_64_SHR(tmp, 1); 8394 *l = tmp; 8395 8396 COMPILER_64_SET(tmp1, 0, 1); 8397 COMPILER_64_AND(tmp1, value); 8398 COMPILER_64_ADD_64(tmp1, tmp); 8399 *r = tmp1; 8400 return 0; 8401 } 8402 8403 8404 int 8405 bcm_tr3_cosq_node_stat_init(int unit, _bcm_tr3_cosq_node_t *node) 8406 { 8407 8408 bcm_cosq_stat_t stat; 8409 uint64 val64; 8410 8411 COMPILER_64_ZERO(val64); 8412 8413 if(node->level == SOC_TR3_NODE_LVL_L2){ 8414 for (stat = bcmCosqStatDroppedPackets; stat <= bcmCosqStatOutBytes; stat++){ 8415 BCM_IF_ERROR_RETURN(bcm_tr3_cosq_stat_set(unit, node->gport, BCM_COS_INVALID, stat, val64)); 8416 } 8417 8418 } 8419 if (node->child) { 8420 bcm_tr3_cosq_node_stat_init(unit, node->child); 8421 } 8422 8423 if (node->sibling) { 8424 bcm_tr3_cosq_node_stat_init(unit, node->sibling); 8425 } 8426 return BCM_E_NONE; 8427 } 8428 8429 void 8430 bcm_tr3_cosq_port_stat_init(int unit, bcm_port_t port) 8431 { 8432 _bcm_tr3_mmu_info_t *mmu_info; 8433 int phy_port, mmu_port, ii; 8434 _bcm_tr3_cosq_node_t *node = NULL, *tnode; 8435 soc_info_t *si; 8436 8437 si = &SOC_INFO(unit); 8438 mmu_info = _bcm_tr3_mmu_info[unit]; 8439 8440 phy_port = si->port_l2p_mapping[port]; 8441 mmu_port = si->port_p2m_mapping[phy_port]; 8442 8443 for (ii = 0; ii < _BCM_TR3_NUM_PORT_SCHEDULERS; ii++) { 8444 tnode = &mmu_info->sched_node[ii]; 8445 if (tnode->in_use == FALSE) { 8446 continue; 8447 } 8448 if ((tnode->level == SOC_TR3_NODE_LVL_ROOT) && 8449 (tnode->hw_index == mmu_port)) { 8450 node = tnode; 8451 break; 8452 } 8453 } 8454 if (node == NULL) { 8455 return; 8456 } 8457 8458 bcm_tr3_cosq_node_stat_init(unit, node); 8459 } 8460 8461 void 8462 bcm_tr3_cosq_stat_init(int unit) 8463 { 8464 bcm_port_t port; 8465 8466 PBMP_ALL_ITER(unit, port) { 8467 bcm_tr3_cosq_port_stat_init(unit, port); 8468 } 8469 return; 8470 } 8471 8472 8473 8474 int 8475 bcm_tr3_cosq_stat_set(int unit, bcm_gport_t port, bcm_cos_queue_t cosq, 8476 bcm_cosq_stat_t stat, uint64 value) 8477 { 8478 _bcm_tr3_cosq_node_t *node; 8479 bcm_port_t local_port; 8480 int startq, numq, i, from_cos, to_cos, ci; 8481 uint64 l, r; 8482 8483 _bcm_tr3_distribute_u64(value, &l, &r); 8484 8485 switch (stat) { 8486 case bcmCosqStatDroppedPackets: 8487 if (BCM_GPORT_IS_SCHEDULER(port)) { 8488 BCM_IF_ERROR_RETURN 8489 (_bcm_tr3_cosq_node_get(unit, port, 0, NULL, 8490 &local_port, NULL, &node)); 8491 BCM_IF_ERROR_RETURN( 8492 _bcm_tr3_cosq_child_node_at_input(node, cosq, &node)); 8493 port = node->gport; 8494 cosq = 0; 8495 } 8496 8497 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 8498 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port)) { 8499 BCM_IF_ERROR_RETURN 8500 (_bcm_tr3_cosq_index_resolve 8501 (unit, port, cosq, _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE, 8502 &local_port, &startq, NULL)); 8503 /* coverity[NEGATIVE_RETURNS: FALSE] */ 8504 BCM_IF_ERROR_RETURN 8505 (soc_counter_set(unit, REG_PORT_ANY, 8506 SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_UC, startq, 8507 value)); 8508 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 8509 BCM_IF_ERROR_RETURN 8510 (_bcm_tr3_cosq_index_resolve 8511 (unit, port, cosq, _BCM_TR3_COSQ_INDEX_STYLE_MCAST_QUEUE, 8512 &local_port, &startq, NULL)); 8513 /* coverity[NEGATIVE_RETURNS: FALSE] */ 8514 BCM_IF_ERROR_RETURN 8515 (soc_counter_set(unit, REG_PORT_ANY, 8516 SOC_COUNTER_NON_DMA_COSQ_DROP_PKT, startq - 1024, 8517 value)); 8518 } else if (BCM_GPORT_IS_SCHEDULER(port)) { 8519 return BCM_E_PARAM; 8520 } else { 8521 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_localport_resolve(unit, port, &local_port)); 8522 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_port_has_ets(unit, local_port)); 8523 if (cosq == BCM_COS_INVALID) { 8524 from_cos = to_cos = 0; 8525 } else { 8526 from_cos = to_cos = cosq; 8527 } 8528 for (ci = from_cos; ci <= to_cos; ci++) { 8529 BCM_IF_ERROR_RETURN 8530 (_bcm_tr3_cosq_index_resolve 8531 (unit, port, ci, _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE, 8532 &local_port, &startq, &numq)); 8533 for (i = 0; i < numq; i++) { 8534 /* coverity[NEGATIVE_RETURNS: FALSE] */ 8535 BCM_IF_ERROR_RETURN 8536 (soc_counter_set(unit, REG_PORT_ANY, 8537 SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_UC, 8538 startq + i, l)); 8539 } 8540 BCM_IF_ERROR_RETURN 8541 (_bcm_tr3_cosq_index_resolve 8542 (unit, port, ci, _BCM_TR3_COSQ_INDEX_STYLE_MCAST_QUEUE, 8543 &local_port, &startq, &numq)); 8544 for (i = 0; i < numq; i++) { 8545 /* coverity[negative_returns : FALSE] */ 8546 BCM_IF_ERROR_RETURN 8547 (soc_counter_set(unit, -1, 8548 SOC_COUNTER_NON_DMA_COSQ_DROP_PKT, 8549 startq + i - 1024, r)); 8550 } 8551 } 8552 } 8553 break; 8554 case bcmCosqStatDroppedBytes: 8555 if (BCM_GPORT_IS_SCHEDULER(port)) { 8556 BCM_IF_ERROR_RETURN 8557 (_bcm_tr3_cosq_node_get(unit, port, 0, NULL, 8558 &local_port, NULL, &node)); 8559 BCM_IF_ERROR_RETURN( 8560 _bcm_tr3_cosq_child_node_at_input(node, cosq, &node)); 8561 port = node->gport; 8562 cosq = 0; 8563 } 8564 8565 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 8566 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port)) { 8567 BCM_IF_ERROR_RETURN 8568 (_bcm_tr3_cosq_index_resolve 8569 (unit, port, cosq, _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE, 8570 &local_port, &startq, NULL)); 8571 /* coverity[NEGATIVE_RETURNS: FALSE] */ 8572 BCM_IF_ERROR_RETURN 8573 (soc_counter_set(unit, REG_PORT_ANY, 8574 SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE_UC, startq, 8575 value)); 8576 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 8577 BCM_IF_ERROR_RETURN 8578 (_bcm_tr3_cosq_index_resolve 8579 (unit, port, cosq, _BCM_TR3_COSQ_INDEX_STYLE_MCAST_QUEUE, 8580 &local_port, &startq, NULL)); 8581 /* coverity[NEGATIVE_RETURNS: FALSE] */ 8582 BCM_IF_ERROR_RETURN 8583 (soc_counter_set(unit, REG_PORT_ANY, 8584 SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE, startq - 1024, value)); 8585 } else if (BCM_GPORT_IS_SCHEDULER(port)) { 8586 return BCM_E_PARAM; 8587 } else { 8588 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_localport_resolve(unit, port, &local_port)); 8589 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_port_has_ets(unit, local_port)); 8590 if (cosq == BCM_COS_INVALID) { 8591 from_cos = to_cos = 0; 8592 } else { 8593 from_cos = to_cos = cosq; 8594 } 8595 for (ci = from_cos; ci <= to_cos; ci++) { 8596 BCM_IF_ERROR_RETURN 8597 (_bcm_tr3_cosq_index_resolve 8598 (unit, port, ci, _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE, 8599 &local_port, &startq, &numq)); 8600 for (i = 0; i < numq; i++) { 8601 /* coverity[NEGATIVE_RETURNS: FALSE] */ 8602 BCM_IF_ERROR_RETURN 8603 (soc_counter_set(unit, REG_PORT_ANY, 8604 SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE_UC, startq + i, l)); 8605 } 8606 BCM_IF_ERROR_RETURN 8607 (_bcm_tr3_cosq_index_resolve 8608 (unit, port, ci, _BCM_TR3_COSQ_INDEX_STYLE_MCAST_QUEUE, 8609 &local_port, &startq, &numq)); 8610 for (i = 0; i < numq; i++) { 8611 BCM_IF_ERROR_RETURN 8612 (soc_counter_set(unit, REG_PORT_ANY, 8613 SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE, startq + i - 1024, r)); 8614 } 8615 } 8616 } 8617 break; 8618 case bcmCosqStatYellowCongestionDroppedPackets: 8619 if (cosq != BCM_COS_INVALID) { 8620 return BCM_E_UNAVAIL; 8621 } 8622 BCM_IF_ERROR_RETURN 8623 (_bcm_tr3_cosq_localport_resolve(unit, port, &local_port)); 8624 BCM_IF_ERROR_RETURN 8625 (soc_counter_set(unit, local_port, 8626 SOC_COUNTER_NON_DMA_PORT_DROP_PKT_YELLOW, 0, 8627 value)); 8628 break; 8629 case bcmCosqStatRedCongestionDroppedPackets: 8630 if (cosq != BCM_COS_INVALID) { 8631 return BCM_E_UNAVAIL; 8632 } 8633 BCM_IF_ERROR_RETURN 8634 (_bcm_tr3_cosq_localport_resolve(unit, port, &local_port)); 8635 BCM_IF_ERROR_RETURN 8636 (soc_counter_set(unit, local_port, 8637 SOC_COUNTER_NON_DMA_PORT_DROP_PKT_RED, 0, 8638 value)); 8639 break; 8640 case bcmCosqStatGreenDiscardDroppedPackets: 8641 if (cosq != BCM_COS_INVALID) { 8642 return BCM_E_UNAVAIL; 8643 } 8644 BCM_IF_ERROR_RETURN 8645 (_bcm_tr3_cosq_localport_resolve(unit, port, &local_port)); 8646 BCM_IF_ERROR_RETURN 8647 (soc_counter_set(unit, local_port, 8648 SOC_COUNTER_NON_DMA_PORT_WRED_PKT_GREEN, 0, 8649 value)); 8650 break; 8651 case bcmCosqStatYellowDiscardDroppedPackets: 8652 if (cosq != BCM_COS_INVALID) { 8653 return BCM_E_UNAVAIL; 8654 } 8655 BCM_IF_ERROR_RETURN 8656 (_bcm_tr3_cosq_localport_resolve(unit, port, &local_port)); 8657 BCM_IF_ERROR_RETURN 8658 (soc_counter_set(unit, local_port, 8659 SOC_COUNTER_NON_DMA_PORT_WRED_PKT_YELLOW, 0, 8660 value)); 8661 break; 8662 case bcmCosqStatRedDiscardDroppedPackets: 8663 if (cosq != BCM_COS_INVALID) { 8664 return BCM_E_UNAVAIL; 8665 } 8666 BCM_IF_ERROR_RETURN 8667 (_bcm_tr3_cosq_localport_resolve(unit, port, &local_port)); 8668 BCM_IF_ERROR_RETURN 8669 (soc_counter_set(unit, local_port, 8670 SOC_COUNTER_NON_DMA_PORT_WRED_PKT_RED, 0, value)); 8671 break; 8672 case bcmCosqStatOutPackets: 8673 if (BCM_GPORT_IS_SCHEDULER(port)) { 8674 BCM_IF_ERROR_RETURN 8675 (_bcm_tr3_cosq_node_get(unit, port, 0, NULL, 8676 &local_port, NULL, &node)); 8677 BCM_IF_ERROR_RETURN( 8678 _bcm_tr3_cosq_child_node_at_input(node, cosq, &node)); 8679 port = node->gport; 8680 cosq = 0; 8681 } 8682 8683 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 8684 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port)) { 8685 BCM_IF_ERROR_RETURN 8686 (_bcm_tr3_cosq_index_resolve 8687 (unit, port, cosq, _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE, 8688 &local_port, &startq, NULL)); 8689 /* coverity[NEGATIVE_RETURNS: FALSE] */ 8690 BCM_IF_ERROR_RETURN 8691 (soc_counter_set(unit, REG_PORT_ANY, 8692 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT_UC, startq, 8693 value)); 8694 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 8695 BCM_IF_ERROR_RETURN 8696 (_bcm_tr3_cosq_index_resolve 8697 (unit, port, cosq, _BCM_TR3_COSQ_INDEX_STYLE_MCAST_QUEUE, 8698 &local_port, &startq, NULL)); 8699 /* coverity[NEGATIVE_RETURNS: FALSE] */ 8700 BCM_IF_ERROR_RETURN 8701 (soc_counter_set(unit, REG_PORT_ANY, 8702 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT, startq, 8703 value)); 8704 } else if (BCM_GPORT_IS_SCHEDULER(port)) { 8705 return BCM_E_PARAM; 8706 } else { 8707 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_localport_resolve(unit, port, &local_port)); 8708 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_port_has_ets(unit, local_port)); 8709 if (cosq == BCM_COS_INVALID) { 8710 from_cos = to_cos = 0; 8711 } else { 8712 from_cos = to_cos = cosq; 8713 } 8714 for (ci = from_cos; ci <= to_cos; ci++) { 8715 BCM_IF_ERROR_RETURN 8716 (_bcm_tr3_cosq_index_resolve 8717 (unit, port, ci, _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE, 8718 &local_port, &startq, &numq)); 8719 for (i = 0; i < numq; i++) { 8720 /* coverity[NEGATIVE_RETURNS: FALSE] */ 8721 BCM_IF_ERROR_RETURN 8722 (soc_counter_set(unit, REG_PORT_ANY, 8723 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT_UC, startq + i, l)); 8724 } 8725 BCM_IF_ERROR_RETURN 8726 (_bcm_tr3_cosq_index_resolve 8727 (unit, port, ci, _BCM_TR3_COSQ_INDEX_STYLE_MCAST_QUEUE, 8728 &local_port, &startq, &numq)); 8729 for (i = 0; i < numq; i++) { 8730 BCM_IF_ERROR_RETURN 8731 (soc_counter_set(unit, REG_PORT_ANY, 8732 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT, startq + i, r)); 8733 } 8734 } 8735 } 8736 break; 8737 case bcmCosqStatOutBytes: 8738 if (BCM_GPORT_IS_SCHEDULER(port)) { 8739 BCM_IF_ERROR_RETURN 8740 (_bcm_tr3_cosq_node_get(unit, port, 0, NULL, 8741 &local_port, NULL, &node)); 8742 BCM_IF_ERROR_RETURN( 8743 _bcm_tr3_cosq_child_node_at_input(node, cosq, &node)); 8744 port = node->gport; 8745 cosq = 0; 8746 } 8747 8748 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 8749 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port)) { 8750 BCM_IF_ERROR_RETURN 8751 (_bcm_tr3_cosq_index_resolve 8752 (unit, port, cosq, _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE, 8753 &local_port, &startq, NULL)); 8754 /* coverity[NEGATIVE_RETURNS: FALSE] */ 8755 BCM_IF_ERROR_RETURN 8756 (soc_counter_set(unit, REG_PORT_ANY, 8757 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE_UC, startq, 8758 value)); 8759 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 8760 BCM_IF_ERROR_RETURN 8761 (_bcm_tr3_cosq_index_resolve 8762 (unit, port, cosq, _BCM_TR3_COSQ_INDEX_STYLE_MCAST_QUEUE, 8763 &local_port, &startq, NULL)); 8764 /* coverity[NEGATIVE_RETURNS: FALSE] */ 8765 BCM_IF_ERROR_RETURN 8766 (soc_counter_set(unit, REG_PORT_ANY, 8767 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE, startq, 8768 value)); 8769 } else if (BCM_GPORT_IS_SCHEDULER(port)) { 8770 return BCM_E_PARAM; 8771 } else { 8772 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_localport_resolve(unit, port, &local_port)); 8773 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_port_has_ets(unit, local_port)); 8774 if (cosq == BCM_COS_INVALID) { 8775 from_cos = to_cos = 0; 8776 } else { 8777 from_cos = to_cos = cosq; 8778 } 8779 for (ci = from_cos; ci <= to_cos; ci++) { 8780 BCM_IF_ERROR_RETURN 8781 (_bcm_tr3_cosq_index_resolve 8782 (unit, port, ci, _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE, 8783 &local_port, &startq, &numq)); 8784 for (i = 0; i < numq; i++) { 8785 /* coverity[NEGATIVE_RETURNS: FALSE] */ 8786 BCM_IF_ERROR_RETURN 8787 (soc_counter_set(unit, REG_PORT_ANY, 8788 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE_UC, startq + i, l)); 8789 } 8790 BCM_IF_ERROR_RETURN 8791 (_bcm_tr3_cosq_index_resolve 8792 (unit, port, ci, _BCM_TR3_COSQ_INDEX_STYLE_MCAST_QUEUE, 8793 &local_port, &startq, &numq)); 8794 for (i = 0; i < numq; i++) { 8795 BCM_IF_ERROR_RETURN 8796 (soc_counter_set(unit, REG_PORT_ANY, 8797 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE, startq + i, r)); 8798 } 8799 } 8800 } 8801 break; 8802 default: 8803 return BCM_E_PARAM; 8804 } 8805 8806 return BCM_E_NONE; 8807 } 8808 8809 int 8810 bcm_tr3_cosq_stat_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 8811 bcm_cosq_stat_t stat, int sync_mode, uint64 *value) 8812 { 8813 _bcm_tr3_cosq_node_t *node, *child_node; 8814 bcm_port_t local_port; 8815 int startq, numq, i, from_cos, to_cos, ci, start_hw_index, end_hw_index; 8816 uint64 sum, value64; 8817 int (*counter_get) (int , soc_port_t , soc_reg_t , int , uint64 *); 8818 8819 if (value == NULL) { 8820 return BCM_E_PARAM; 8821 } 8822 8823 /* 8824 * if sync-mode is set, update the software cached counter value, 8825 * with the hardware count and then retrieve the count. 8826 * else return the software cache counter value. 8827 */ 8828 counter_get = (sync_mode == 1)? soc_counter_sync_get: soc_counter_get; 8829 8830 switch (stat) { 8831 case bcmCosqStatDroppedPackets: 8832 if (BCM_GPORT_IS_SCHEDULER(port) && cosq==-1) { 8833 BCM_IF_ERROR_RETURN 8834 (_bcm_tr3_cosq_node_get(unit, port, 0, NULL, 8835 &local_port, NULL, &node)); 8836 COMPILER_64_ZERO(sum); 8837 from_cos = 0; 8838 to_cos = (IS_CPU_PORT(unit, local_port)) ? 8839 NUM_CPU_COSQ(unit) - 1 : _TR3_NUM_COS(unit) - 1; 8840 for (ci = from_cos; ci <= to_cos; ci++) { 8841 if ((_bcm_tr3_cosq_child_node_at_input(node, ci, &child_node)) 8842 == BCM_E_NOT_FOUND) { 8843 continue; 8844 } 8845 port = child_node->gport; 8846 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 8847 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port)) { 8848 BCM_IF_ERROR_RETURN 8849 (_bcm_tr3_cosq_index_resolve 8850 (unit, port, 0, _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE, 8851 &local_port, &startq, &numq)); 8852 /* coverity[NEGATIVE_RETURNS: FALSE] */ 8853 BCM_IF_ERROR_RETURN 8854 (counter_get(unit, REG_PORT_ANY, 8855 SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_UC, 8856 startq, &value64)); 8857 COMPILER_64_ADD_64(sum, value64); 8858 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 8859 8860 BCM_IF_ERROR_RETURN 8861 (_bcm_tr3_cosq_index_resolve 8862 (unit, port, 0, _BCM_TR3_COSQ_INDEX_STYLE_MCAST_QUEUE, 8863 &local_port, &startq, &numq)); 8864 /* coverity[NEGATIVE_RETURNS: FALSE] */ 8865 BCM_IF_ERROR_RETURN 8866 (counter_get(unit, REG_PORT_ANY, 8867 SOC_COUNTER_NON_DMA_COSQ_DROP_PKT, 8868 startq - 1024, &value64)); 8869 COMPILER_64_ADD_64(sum, value64); 8870 } 8871 } 8872 *value = sum; 8873 break; 8874 } 8875 if (BCM_GPORT_IS_SCHEDULER(port)) { 8876 BCM_IF_ERROR_RETURN 8877 (_bcm_tr3_cosq_node_get(unit, port, 0, NULL, 8878 &local_port, NULL, &node)); 8879 BCM_IF_ERROR_RETURN( 8880 _bcm_tr3_cosq_child_node_at_input(node, cosq, &node)); 8881 port = node->gport; 8882 cosq = 0; 8883 } 8884 8885 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 8886 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port)) { 8887 BCM_IF_ERROR_RETURN 8888 (_bcm_tr3_cosq_index_resolve 8889 (unit, port, cosq, _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE, 8890 &local_port, &startq, NULL)); 8891 /* coverity[NEGATIVE_RETURNS: FALSE] */ 8892 BCM_IF_ERROR_RETURN 8893 (counter_get(unit, REG_PORT_ANY, 8894 SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_UC, startq, 8895 value)); 8896 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 8897 BCM_IF_ERROR_RETURN 8898 (_bcm_tr3_cosq_index_resolve 8899 (unit, port, cosq, _BCM_TR3_COSQ_INDEX_STYLE_MCAST_QUEUE, 8900 &local_port, &startq, NULL)); 8901 /* coverity[NEGATIVE_RETURNS: FALSE] */ 8902 BCM_IF_ERROR_RETURN 8903 (counter_get(unit, REG_PORT_ANY, 8904 SOC_COUNTER_NON_DMA_COSQ_DROP_PKT, startq - 1024, value)); 8905 } else if (BCM_GPORT_IS_SCHEDULER(port)) { 8906 return BCM_E_PARAM; 8907 } else { 8908 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_localport_resolve(unit, port, &local_port)); 8909 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_port_has_ets(unit, local_port)); 8910 COMPILER_64_ZERO(sum); 8911 if (cosq == BCM_COS_INVALID) { 8912 from_cos = 0; 8913 to_cos = (IS_CPU_PORT(unit, local_port)) ? 8914 NUM_CPU_COSQ(unit) - 1 : _TR3_NUM_COS(unit) - 1; 8915 } else { 8916 from_cos = to_cos = cosq; 8917 } 8918 for (ci = from_cos; ci <= to_cos; ci++) { 8919 BCM_IF_ERROR_RETURN 8920 (_bcm_tr3_cosq_index_resolve 8921 (unit, port, ci, _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE, 8922 &local_port, &startq, &numq)); 8923 for (i = 0; i < numq; i++) { 8924 /* coverity[NEGATIVE_RETURNS: FALSE] */ 8925 BCM_IF_ERROR_RETURN 8926 (counter_get(unit, REG_PORT_ANY, 8927 SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_UC, 8928 startq + i, &value64)); 8929 COMPILER_64_ADD_64(sum, value64); 8930 } 8931 BCM_IF_ERROR_RETURN 8932 (_bcm_tr3_cosq_index_resolve 8933 (unit, port, ci, _BCM_TR3_COSQ_INDEX_STYLE_MCAST_QUEUE, 8934 &local_port, &startq, &numq)); 8935 for (i = 0; i < numq; i++) { 8936 /* coverity[NEGATIVE_RETURNS: FALSE] */ 8937 BCM_IF_ERROR_RETURN 8938 (counter_get(unit, REG_PORT_ANY, 8939 SOC_COUNTER_NON_DMA_COSQ_DROP_PKT, 8940 startq + i - 1024, &value64)); 8941 COMPILER_64_ADD_64(sum, value64); 8942 } 8943 } 8944 *value = sum; 8945 } 8946 break; 8947 case bcmCosqStatDroppedBytes: 8948 if (BCM_GPORT_IS_SCHEDULER(port) && cosq==-1) { 8949 BCM_IF_ERROR_RETURN 8950 (_bcm_tr3_cosq_node_get(unit, port, 0, NULL, 8951 &local_port, NULL, &node)); 8952 COMPILER_64_ZERO(sum); 8953 from_cos = 0; 8954 to_cos = (IS_CPU_PORT(unit, local_port)) ? 8955 NUM_CPU_COSQ(unit) - 1 : _TR3_NUM_COS(unit) - 1; 8956 for (ci = from_cos; ci <= to_cos; ci++) { 8957 if ((_bcm_tr3_cosq_child_node_at_input(node, ci, &child_node)) 8958 == BCM_E_NOT_FOUND) { 8959 continue; 8960 } 8961 port = child_node->gport; 8962 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 8963 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port)) { 8964 BCM_IF_ERROR_RETURN 8965 (_bcm_tr3_cosq_index_resolve 8966 (unit, port, 0, _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE, 8967 &local_port, &startq, &numq)); 8968 /* coverity[NEGATIVE_RETURNS: FALSE] */ 8969 BCM_IF_ERROR_RETURN 8970 (counter_get(unit, REG_PORT_ANY, 8971 SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE_UC, 8972 startq, &value64)); 8973 COMPILER_64_ADD_64(sum, value64); 8974 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 8975 8976 BCM_IF_ERROR_RETURN 8977 (_bcm_tr3_cosq_index_resolve 8978 (unit, port, 0, _BCM_TR3_COSQ_INDEX_STYLE_MCAST_QUEUE, 8979 &local_port, &startq, &numq)); 8980 /* coverity[NEGATIVE_RETURNS: FALSE] */ 8981 BCM_IF_ERROR_RETURN 8982 (counter_get(unit, REG_PORT_ANY, 8983 SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE, 8984 startq - 1024, &value64)); 8985 COMPILER_64_ADD_64(sum, value64); 8986 } 8987 } 8988 *value = sum; 8989 break; 8990 } 8991 if (BCM_GPORT_IS_SCHEDULER(port)) { 8992 BCM_IF_ERROR_RETURN 8993 (_bcm_tr3_cosq_node_get(unit, port, 0, NULL, 8994 &local_port, NULL, &node)); 8995 BCM_IF_ERROR_RETURN( 8996 _bcm_tr3_cosq_child_node_at_input(node, cosq, &node)); 8997 port = node->gport; 8998 cosq = 0; 8999 } 9000 9001 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 9002 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port)) { 9003 BCM_IF_ERROR_RETURN 9004 (_bcm_tr3_cosq_index_resolve 9005 (unit, port, cosq, _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE, 9006 &local_port, &startq, NULL)); 9007 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9008 BCM_IF_ERROR_RETURN 9009 (counter_get(unit, REG_PORT_ANY, 9010 SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE_UC, startq, 9011 value)); 9012 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 9013 BCM_IF_ERROR_RETURN 9014 (_bcm_tr3_cosq_index_resolve 9015 (unit, port, cosq, _BCM_TR3_COSQ_INDEX_STYLE_MCAST_QUEUE, 9016 &local_port, &startq, NULL)); 9017 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9018 BCM_IF_ERROR_RETURN 9019 (counter_get(unit, REG_PORT_ANY, 9020 SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE, 9021 startq - 1024, value)); 9022 } else if (BCM_GPORT_IS_SCHEDULER(port)) { 9023 return BCM_E_PARAM; 9024 } else { 9025 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_localport_resolve(unit, port, &local_port)); 9026 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_port_has_ets(unit, local_port)); 9027 COMPILER_64_ZERO(sum); 9028 if (cosq == BCM_COS_INVALID) { 9029 from_cos = 0; 9030 to_cos = (IS_CPU_PORT(unit, local_port)) ? 9031 NUM_CPU_COSQ(unit) - 1 : _TR3_NUM_COS(unit) - 1; 9032 } else { 9033 from_cos = to_cos = cosq; 9034 } 9035 for (ci = from_cos; ci <= to_cos; ci++) { 9036 BCM_IF_ERROR_RETURN 9037 (_bcm_tr3_cosq_index_resolve 9038 (unit, port, ci, _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE, 9039 &local_port, &startq, &numq)); 9040 for (i = 0; i < numq; i++) { 9041 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9042 BCM_IF_ERROR_RETURN 9043 (counter_get(unit, REG_PORT_ANY, 9044 SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE_UC, 9045 startq + i, &value64)); 9046 COMPILER_64_ADD_64(sum, value64); 9047 } 9048 BCM_IF_ERROR_RETURN 9049 (_bcm_tr3_cosq_index_resolve 9050 (unit, port, ci, _BCM_TR3_COSQ_INDEX_STYLE_MCAST_QUEUE, 9051 &local_port, &startq, &numq)); 9052 for (i = 0; i < numq; i++) { 9053 BCM_IF_ERROR_RETURN 9054 (counter_get(unit, REG_PORT_ANY, 9055 SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE, 9056 startq + i - 1024, &value64)); 9057 COMPILER_64_ADD_64(sum, value64); 9058 } 9059 } 9060 *value = sum; 9061 } 9062 break; 9063 case bcmCosqStatYellowCongestionDroppedPackets: 9064 if (cosq != BCM_COS_INVALID) { 9065 return BCM_E_UNAVAIL; 9066 } 9067 BCM_IF_ERROR_RETURN 9068 (_bcm_tr3_cosq_localport_resolve(unit, port, &local_port)); 9069 BCM_IF_ERROR_RETURN 9070 (counter_get(unit, local_port, 9071 SOC_COUNTER_NON_DMA_PORT_DROP_PKT_YELLOW, 0, 9072 value)); 9073 break; 9074 case bcmCosqStatRedCongestionDroppedPackets: 9075 if (cosq != BCM_COS_INVALID) { 9076 return BCM_E_UNAVAIL; 9077 } 9078 BCM_IF_ERROR_RETURN 9079 (_bcm_tr3_cosq_localport_resolve(unit, port, &local_port)); 9080 BCM_IF_ERROR_RETURN 9081 (counter_get(unit, local_port, 9082 SOC_COUNTER_NON_DMA_PORT_DROP_PKT_RED, 0, 9083 value)); 9084 break; 9085 case bcmCosqStatGreenDiscardDroppedPackets: 9086 if (cosq != BCM_COS_INVALID) { 9087 return BCM_E_UNAVAIL; 9088 } 9089 BCM_IF_ERROR_RETURN 9090 (_bcm_tr3_cosq_localport_resolve(unit, port, &local_port)); 9091 BCM_IF_ERROR_RETURN 9092 (counter_get(unit, local_port, 9093 SOC_COUNTER_NON_DMA_PORT_WRED_PKT_GREEN, 0, 9094 value)); 9095 break; 9096 case bcmCosqStatYellowDiscardDroppedPackets: 9097 if (cosq != BCM_COS_INVALID) { 9098 return BCM_E_UNAVAIL; 9099 } 9100 BCM_IF_ERROR_RETURN 9101 (_bcm_tr3_cosq_localport_resolve(unit, port, &local_port)); 9102 BCM_IF_ERROR_RETURN 9103 (counter_get(unit, local_port, 9104 SOC_COUNTER_NON_DMA_PORT_WRED_PKT_YELLOW, 0, 9105 value)); 9106 break; 9107 case bcmCosqStatRedDiscardDroppedPackets: 9108 if (cosq != BCM_COS_INVALID) { 9109 return BCM_E_UNAVAIL; 9110 } 9111 BCM_IF_ERROR_RETURN 9112 (_bcm_tr3_cosq_localport_resolve(unit, port, &local_port)); 9113 BCM_IF_ERROR_RETURN 9114 (counter_get(unit, local_port, 9115 SOC_COUNTER_NON_DMA_PORT_WRED_PKT_RED, 0, value)); 9116 break; 9117 case bcmCosqStatOutPackets: 9118 if (BCM_GPORT_IS_SCHEDULER(port) && cosq==-1) { 9119 BCM_IF_ERROR_RETURN 9120 (_bcm_tr3_cosq_node_get(unit, port, 0, NULL, 9121 &local_port, NULL, &node)); 9122 COMPILER_64_ZERO(sum); 9123 from_cos = 0; 9124 to_cos = (IS_CPU_PORT(unit, local_port)) ? 9125 NUM_CPU_COSQ(unit) - 1 : _TR3_NUM_COS(unit) - 1; 9126 for (ci = from_cos; ci <= to_cos; ci++) { 9127 if ((_bcm_tr3_cosq_child_node_at_input(node, ci, &child_node)) 9128 == BCM_E_NOT_FOUND) { 9129 continue; 9130 } 9131 port = child_node->gport; 9132 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 9133 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port)) { 9134 BCM_IF_ERROR_RETURN 9135 (_bcm_tr3_cosq_index_resolve 9136 (unit, port, 0, _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE, 9137 &local_port, &startq, &numq)); 9138 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9139 BCM_IF_ERROR_RETURN 9140 (counter_get(unit, REG_PORT_ANY, 9141 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT_UC, 9142 startq, &value64)); 9143 COMPILER_64_ADD_64(sum, value64); 9144 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 9145 9146 BCM_IF_ERROR_RETURN 9147 (_bcm_tr3_cosq_index_resolve 9148 (unit, port, 0, _BCM_TR3_COSQ_INDEX_STYLE_MCAST_QUEUE, 9149 &local_port, &startq, &numq)); 9150 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9151 BCM_IF_ERROR_RETURN 9152 (counter_get(unit, REG_PORT_ANY, 9153 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT, 9154 startq, &value64)); 9155 COMPILER_64_ADD_64(sum, value64); 9156 } 9157 } 9158 *value = sum; 9159 break; 9160 } 9161 if (BCM_GPORT_IS_SCHEDULER(port)) { 9162 BCM_IF_ERROR_RETURN 9163 (_bcm_tr3_cosq_node_get(unit, port, 0, NULL, 9164 &local_port, NULL, &node)); 9165 BCM_IF_ERROR_RETURN( 9166 _bcm_tr3_cosq_child_node_at_input(node, cosq, &node)); 9167 port = node->gport; 9168 cosq = 0; 9169 } 9170 9171 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 9172 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port)) { 9173 BCM_IF_ERROR_RETURN 9174 (_bcm_tr3_cosq_index_resolve 9175 (unit, port, cosq, _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE, 9176 &local_port, &startq, NULL)); 9177 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9178 BCM_IF_ERROR_RETURN 9179 (counter_get(unit, REG_PORT_ANY, 9180 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT_UC, startq, 9181 value)); 9182 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 9183 BCM_IF_ERROR_RETURN 9184 (_bcm_tr3_cosq_index_resolve 9185 (unit, port, cosq, _BCM_TR3_COSQ_INDEX_STYLE_MCAST_QUEUE, 9186 &local_port, &startq, NULL)); 9187 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9188 BCM_IF_ERROR_RETURN 9189 (counter_get(unit, REG_PORT_ANY, 9190 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT, startq, 9191 value)); 9192 } else if (BCM_GPORT_IS_SCHEDULER(port)) { 9193 return BCM_E_PARAM; 9194 } else { 9195 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_localport_resolve(unit, port, &local_port)); 9196 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_port_has_ets(unit, local_port)); 9197 COMPILER_64_ZERO(sum); 9198 if (cosq == BCM_COS_INVALID) { 9199 from_cos = 0; 9200 to_cos = (IS_CPU_PORT(unit, local_port)) ? 9201 NUM_CPU_COSQ(unit) - 1 : _TR3_NUM_COS(unit) - 1; 9202 } else { 9203 from_cos = to_cos = cosq; 9204 } 9205 for (ci = from_cos; ci <= to_cos; ci++) { 9206 BCM_IF_ERROR_RETURN 9207 (_bcm_tr3_cosq_index_resolve 9208 (unit, port, ci, _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE, 9209 &local_port, &startq, &numq)); 9210 for (i = 0; i < numq; i++) { 9211 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9212 BCM_IF_ERROR_RETURN 9213 (counter_get(unit, REG_PORT_ANY, 9214 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT_UC, 9215 startq + i, &value64)); 9216 COMPILER_64_ADD_64(sum, value64); 9217 } 9218 BCM_IF_ERROR_RETURN 9219 (_bcm_tr3_cosq_index_resolve 9220 (unit, port, ci, _BCM_TR3_COSQ_INDEX_STYLE_MCAST_QUEUE, 9221 &local_port, &startq, &numq)); 9222 for (i = 0; i < numq; i++) { 9223 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9224 BCM_IF_ERROR_RETURN 9225 (counter_get(unit, REG_PORT_ANY, 9226 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT, 9227 startq + i, &value64)); 9228 COMPILER_64_ADD_64(sum, value64); 9229 } 9230 } 9231 *value = sum; 9232 } 9233 break; 9234 case bcmCosqStatOutBytes: 9235 if (BCM_GPORT_IS_SCHEDULER(port) && cosq==-1) { 9236 BCM_IF_ERROR_RETURN 9237 (_bcm_tr3_cosq_node_get(unit, port, 0, NULL, 9238 &local_port, NULL, &node)); 9239 COMPILER_64_ZERO(sum); 9240 from_cos = 0; 9241 to_cos = (IS_CPU_PORT(unit, local_port)) ? 9242 NUM_CPU_COSQ(unit) - 1 : _TR3_NUM_COS(unit) - 1; 9243 for (ci = from_cos; ci <= to_cos; ci++) { 9244 if ((_bcm_tr3_cosq_child_node_at_input(node, ci, &child_node)) 9245 == BCM_E_NOT_FOUND) { 9246 continue; 9247 } 9248 port = child_node->gport; 9249 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 9250 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port)) { 9251 BCM_IF_ERROR_RETURN 9252 (_bcm_tr3_cosq_index_resolve 9253 (unit, port, 0, _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE, 9254 &local_port, &startq, &numq)); 9255 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9256 BCM_IF_ERROR_RETURN 9257 (counter_get(unit, REG_PORT_ANY, 9258 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE_UC, 9259 startq, &value64)); 9260 COMPILER_64_ADD_64(sum, value64); 9261 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 9262 9263 BCM_IF_ERROR_RETURN 9264 (_bcm_tr3_cosq_index_resolve 9265 (unit, port, 0, _BCM_TR3_COSQ_INDEX_STYLE_MCAST_QUEUE, 9266 &local_port, &startq, &numq)); 9267 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9268 BCM_IF_ERROR_RETURN 9269 (counter_get(unit, REG_PORT_ANY, 9270 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE, 9271 startq, &value64)); 9272 COMPILER_64_ADD_64(sum, value64); 9273 } 9274 } 9275 *value = sum; 9276 break; 9277 } 9278 if (BCM_GPORT_IS_SCHEDULER(port)) { 9279 BCM_IF_ERROR_RETURN 9280 (_bcm_tr3_cosq_node_get(unit, port, 0, NULL, 9281 &local_port, NULL, &node)); 9282 BCM_IF_ERROR_RETURN( 9283 _bcm_tr3_cosq_child_node_at_input(node, cosq, &node)); 9284 port = node->gport; 9285 cosq = 0; 9286 } 9287 9288 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 9289 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port)) { 9290 BCM_IF_ERROR_RETURN 9291 (_bcm_tr3_cosq_index_resolve 9292 (unit, port, cosq, _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE, 9293 &local_port, &startq, NULL)); 9294 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9295 BCM_IF_ERROR_RETURN 9296 (counter_get(unit, REG_PORT_ANY, 9297 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE_UC, startq, 9298 value)); 9299 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 9300 BCM_IF_ERROR_RETURN 9301 (_bcm_tr3_cosq_index_resolve 9302 (unit, port, cosq, _BCM_TR3_COSQ_INDEX_STYLE_MCAST_QUEUE, 9303 &local_port, &startq, NULL)); 9304 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9305 BCM_IF_ERROR_RETURN 9306 (counter_get(unit, REG_PORT_ANY, 9307 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE, startq, 9308 value)); 9309 } else if (BCM_GPORT_IS_SCHEDULER(port)) { 9310 return BCM_E_PARAM; 9311 } else { 9312 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_localport_resolve(unit, port, &local_port)); 9313 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_port_has_ets(unit, local_port)); 9314 COMPILER_64_ZERO(sum); 9315 if (cosq == BCM_COS_INVALID) { 9316 from_cos = 0; 9317 to_cos = (IS_CPU_PORT(unit, local_port)) ? 9318 NUM_CPU_COSQ(unit) - 1 : _TR3_NUM_COS(unit) - 1; 9319 } else { 9320 from_cos = to_cos = cosq; 9321 } 9322 for (ci = from_cos; ci <= to_cos; ci++) { 9323 BCM_IF_ERROR_RETURN 9324 (_bcm_tr3_cosq_index_resolve 9325 (unit, port, ci, _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE, 9326 &local_port, &startq, &numq)); 9327 for (i = 0; i < numq; i++) { 9328 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9329 BCM_IF_ERROR_RETURN 9330 (counter_get(unit, REG_PORT_ANY, 9331 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE_UC, 9332 startq + i, &value64)); 9333 COMPILER_64_ADD_64(sum, value64); 9334 } 9335 BCM_IF_ERROR_RETURN 9336 (_bcm_tr3_cosq_index_resolve 9337 (unit, port, ci, _BCM_TR3_COSQ_INDEX_STYLE_MCAST_QUEUE, 9338 &local_port, &startq, &numq)); 9339 for (i = 0; i < numq; i++) { 9340 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9341 BCM_IF_ERROR_RETURN 9342 (counter_get(unit, REG_PORT_ANY, 9343 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE, 9344 startq + i, &value64)); 9345 COMPILER_64_ADD_64(sum, value64); 9346 } 9347 } 9348 *value = sum; 9349 } 9350 break; 9351 9352 case bcmCosqStatIngressPortPoolSharedBytesPeak: 9353 9354 COMPILER_64_ZERO(sum); 9355 BCM_IF_ERROR_RETURN 9356 (_bcm_tr3_cosq_ingress_sp_get(unit, port, cosq, 9357 &start_hw_index, &end_hw_index)); 9358 9359 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_localport_resolve(unit, port, &local_port)); 9360 for (i = start_hw_index; i <= end_hw_index; i++) { 9361 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9362 BCM_IF_ERROR_RETURN 9363 (counter_get(unit, local_port, 9364 SOC_COUNTER_NON_DMA_POOL_PEAK, 9365 i, &value64)); 9366 COMPILER_64_ADD_64(sum, value64); 9367 } 9368 9369 COMPILER_64_UMUL_32(sum, _BCM_TR3_BYTES_PER_CELL); 9370 *value = sum; 9371 break; 9372 case bcmCosqStatIngressPortPoolSharedBytesCurrent: 9373 9374 BCM_IF_ERROR_RETURN 9375 (_bcm_tr3_cosq_ingress_sp_get(unit, port, cosq, 9376 &start_hw_index, &end_hw_index)); 9377 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_localport_resolve(unit, port, &local_port)); 9378 9379 COMPILER_64_ZERO(sum); 9380 for (i = start_hw_index; i <= end_hw_index; i++) { 9381 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9382 BCM_IF_ERROR_RETURN 9383 (counter_get(unit, local_port, 9384 SOC_COUNTER_NON_DMA_POOL_CURRENT, 9385 i, &value64)); 9386 COMPILER_64_ADD_64(sum, value64); 9387 } 9388 9389 COMPILER_64_UMUL_32(sum, _BCM_TR3_BYTES_PER_CELL); 9390 *value = sum; 9391 break; 9392 9393 case bcmCosqStatIngressPortPGMinBytesPeak: 9394 9395 BCM_IF_ERROR_RETURN 9396 (_bcm_tr3_cosq_ingress_pg_get(unit, port, cosq, 9397 &start_hw_index, &end_hw_index)); 9398 COMPILER_64_ZERO(sum); 9399 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_localport_resolve(unit, port, &local_port)); 9400 9401 for (i = start_hw_index; i <= end_hw_index; i++) { 9402 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9403 BCM_IF_ERROR_RETURN 9404 (counter_get(unit, local_port, 9405 SOC_COUNTER_NON_DMA_PG_MIN_PEAK, 9406 i, &value64)); 9407 COMPILER_64_ADD_64(sum, value64); 9408 } 9409 9410 COMPILER_64_UMUL_32(sum, _BCM_TR3_BYTES_PER_CELL); 9411 *value = sum; 9412 break; 9413 case bcmCosqStatIngressPortPGMinBytesCurrent: 9414 9415 BCM_IF_ERROR_RETURN 9416 (_bcm_tr3_cosq_ingress_pg_get(unit, port, cosq, 9417 &start_hw_index, &end_hw_index)); 9418 COMPILER_64_ZERO(sum); 9419 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_localport_resolve(unit, port, &local_port)); 9420 9421 for (i = start_hw_index; i <= end_hw_index; i++) { 9422 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9423 BCM_IF_ERROR_RETURN 9424 (counter_get(unit, local_port, 9425 SOC_COUNTER_NON_DMA_PG_MIN_CURRENT, 9426 i, &value64)); 9427 COMPILER_64_ADD_64(sum, value64); 9428 } 9429 9430 COMPILER_64_UMUL_32(sum, _BCM_TR3_BYTES_PER_CELL); 9431 *value = sum; 9432 break; 9433 9434 case bcmCosqStatIngressPortPGSharedBytesPeak: 9435 9436 BCM_IF_ERROR_RETURN 9437 (_bcm_tr3_cosq_ingress_pg_get(unit, port, cosq, 9438 &start_hw_index, &end_hw_index)); 9439 COMPILER_64_ZERO(sum); 9440 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_localport_resolve(unit, port, &local_port)); 9441 9442 for (i = start_hw_index; i <= end_hw_index; i++) { 9443 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9444 BCM_IF_ERROR_RETURN 9445 (counter_get(unit, local_port, 9446 SOC_COUNTER_NON_DMA_PG_SHARED_PEAK, 9447 i, &value64)); 9448 COMPILER_64_ADD_64(sum, value64); 9449 } 9450 9451 COMPILER_64_UMUL_32(sum, _BCM_TR3_BYTES_PER_CELL); 9452 *value = sum; 9453 break; 9454 9455 case bcmCosqStatIngressPortPGSharedBytesCurrent: 9456 9457 BCM_IF_ERROR_RETURN 9458 (_bcm_tr3_cosq_ingress_pg_get(unit, port, cosq, 9459 &start_hw_index, &end_hw_index)); 9460 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_localport_resolve(unit, port, &local_port)); 9461 COMPILER_64_ZERO(sum); 9462 9463 for (i = start_hw_index; i <= end_hw_index; i++) { 9464 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9465 BCM_IF_ERROR_RETURN 9466 (counter_get(unit, local_port, 9467 SOC_COUNTER_NON_DMA_PG_SHARED_CURRENT, 9468 i, &value64)); 9469 COMPILER_64_ADD_64(sum, value64); 9470 } 9471 COMPILER_64_UMUL_32(sum, _BCM_TR3_BYTES_PER_CELL); 9472 *value = sum; 9473 9474 break; 9475 9476 case bcmCosqStatIngressPortPGHeadroomBytesPeak: 9477 9478 BCM_IF_ERROR_RETURN 9479 (_bcm_tr3_cosq_ingress_pg_get(unit, port, cosq, 9480 &start_hw_index, &end_hw_index)); 9481 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_localport_resolve(unit, port, &local_port)); 9482 COMPILER_64_ZERO(sum); 9483 9484 for (i = start_hw_index; i <= end_hw_index; i++) { 9485 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9486 BCM_IF_ERROR_RETURN 9487 (counter_get(unit, local_port, 9488 SOC_COUNTER_NON_DMA_PG_HDRM_PEAK, 9489 i, &value64)); 9490 COMPILER_64_ADD_64(sum, value64); 9491 } 9492 COMPILER_64_UMUL_32(sum, _BCM_TR3_BYTES_PER_CELL); 9493 *value = sum; 9494 9495 break; 9496 9497 case bcmCosqStatIngressPortPGHeadroomBytesCurrent: 9498 9499 BCM_IF_ERROR_RETURN 9500 (_bcm_tr3_cosq_ingress_pg_get(unit, port, cosq, 9501 &start_hw_index, &end_hw_index)); 9502 9503 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_localport_resolve(unit, port, &local_port)); 9504 COMPILER_64_ZERO(sum); 9505 for (i = start_hw_index; i <= end_hw_index; i++) { 9506 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9507 BCM_IF_ERROR_RETURN 9508 (counter_get(unit, local_port, 9509 SOC_COUNTER_NON_DMA_PG_HDRM_CURRENT, 9510 i, &value64)); 9511 COMPILER_64_ADD_64(sum, value64); 9512 } 9513 COMPILER_64_UMUL_32(sum, _BCM_TR3_BYTES_PER_CELL); 9514 *value = sum; 9515 9516 break; 9517 9518 case bcmCosqStatEgressMCQueueBytesPeak: 9519 if (BCM_GPORT_IS_SCHEDULER(port)) { 9520 BCM_IF_ERROR_RETURN 9521 (_bcm_tr3_cosq_node_get(unit, port, 0, NULL, 9522 &local_port, NULL, &node)); 9523 BCM_IF_ERROR_RETURN( 9524 _bcm_tr3_cosq_child_node_at_input(node, cosq, &node)); 9525 port = node->gport; 9526 } 9527 9528 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 9529 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port)) { 9530 return BCM_E_PARAM; 9531 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 9532 BCM_IF_ERROR_RETURN 9533 (_bcm_tr3_cosq_index_resolve 9534 (unit, port, cosq, _BCM_TR3_COSQ_INDEX_STYLE_EGR_PERQ_MCAST, 9535 &local_port, &startq, NULL)); 9536 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9537 BCM_IF_ERROR_RETURN 9538 (counter_get(unit, local_port, 9539 SOC_COUNTER_NON_DMA_QUEUE_PEAK, startq, 9540 value)); 9541 COMPILER_64_UMUL_32(*value, _BCM_TR3_BYTES_PER_CELL); 9542 } else { 9543 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_localport_resolve(unit, port, &local_port)); 9544 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_port_has_ets(unit, port)); 9545 COMPILER_64_ZERO(sum); 9546 if (cosq == BCM_COS_INVALID) { 9547 from_cos = 0; 9548 to_cos = (IS_CPU_PORT(unit, local_port)) ? 9549 NUM_CPU_COSQ(unit) - 1 : _TR3_NUM_COS(unit) - 1; 9550 } else { 9551 from_cos = to_cos = cosq; 9552 } 9553 9554 for (ci = from_cos; ci <= to_cos; ci++) { 9555 BCM_IF_ERROR_RETURN 9556 (_bcm_tr3_cosq_index_resolve 9557 (unit, port, ci, _BCM_TR3_COSQ_INDEX_STYLE_EGR_PERQ_MCAST, 9558 &local_port, &startq, &numq)); 9559 for (i = 0; i < numq; i++) { 9560 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9561 BCM_IF_ERROR_RETURN 9562 (counter_get(unit, local_port, 9563 SOC_COUNTER_NON_DMA_QUEUE_PEAK, 9564 startq + i, &value64)); 9565 COMPILER_64_ADD_64(sum, value64); 9566 } 9567 } 9568 COMPILER_64_UMUL_32(sum, _BCM_TR3_BYTES_PER_CELL); 9569 *value = sum; 9570 } 9571 break; 9572 9573 case bcmCosqStatEgressMCQueueBytesCurrent: 9574 if (BCM_GPORT_IS_SCHEDULER(port)) { 9575 BCM_IF_ERROR_RETURN 9576 (_bcm_tr3_cosq_node_get(unit, port, 0, NULL, 9577 &local_port, NULL, &node)); 9578 BCM_IF_ERROR_RETURN( 9579 _bcm_tr3_cosq_child_node_at_input(node, cosq, &node)); 9580 port = node->gport; 9581 } 9582 9583 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 9584 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port)) { 9585 return BCM_E_PARAM; 9586 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 9587 BCM_IF_ERROR_RETURN 9588 (_bcm_tr3_cosq_index_resolve 9589 (unit, port, cosq, _BCM_TR3_COSQ_INDEX_STYLE_EGR_PERQ_MCAST, 9590 &local_port, &startq, NULL)); 9591 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9592 BCM_IF_ERROR_RETURN 9593 (counter_get(unit, local_port, 9594 SOC_COUNTER_NON_DMA_QUEUE_CURRENT, startq, 9595 value)); 9596 COMPILER_64_UMUL_32(*value, _BCM_TR3_BYTES_PER_CELL); 9597 } else { 9598 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_localport_resolve(unit, port, &local_port)); 9599 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_port_has_ets(unit, port)); 9600 COMPILER_64_ZERO(sum); 9601 if (cosq == BCM_COS_INVALID) { 9602 from_cos = 0; 9603 to_cos = (IS_CPU_PORT(unit, local_port)) ? 9604 NUM_CPU_COSQ(unit) - 1 : _TR3_NUM_COS(unit) - 1; 9605 } else { 9606 from_cos = to_cos = cosq; 9607 } 9608 9609 for (ci = from_cos; ci <= to_cos; ci++) { 9610 BCM_IF_ERROR_RETURN 9611 (_bcm_tr3_cosq_index_resolve 9612 (unit, port, ci, _BCM_TR3_COSQ_INDEX_STYLE_EGR_PERQ_MCAST, 9613 &local_port, &startq, &numq)); 9614 for (i = 0; i < numq; i++) { 9615 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9616 BCM_IF_ERROR_RETURN 9617 (counter_get(unit, local_port, 9618 SOC_COUNTER_NON_DMA_QUEUE_CURRENT, 9619 startq + i, &value64)); 9620 COMPILER_64_ADD_64(sum, value64); 9621 } 9622 } 9623 COMPILER_64_UMUL_32(sum, _BCM_TR3_BYTES_PER_CELL); 9624 *value = sum; 9625 } 9626 break; 9627 9628 case bcmCosqStatEgressUCQueueBytesPeak: 9629 if (BCM_GPORT_IS_SCHEDULER(port)) { 9630 BCM_IF_ERROR_RETURN 9631 (_bcm_tr3_cosq_node_get(unit, port, 0, NULL, 9632 &local_port, NULL, &node)); 9633 BCM_IF_ERROR_RETURN( 9634 _bcm_tr3_cosq_child_node_at_input(node, cosq, &node)); 9635 port = node->gport; 9636 } 9637 9638 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 9639 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port)) { 9640 BCM_IF_ERROR_RETURN 9641 (_bcm_tr3_cosq_index_resolve 9642 (unit, port, cosq, _BCM_TR3_COSQ_INDEX_STYLE_EGR_PERQ_UCAST, 9643 &local_port, &startq, NULL)); 9644 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9645 BCM_IF_ERROR_RETURN 9646 (counter_get(unit, local_port, 9647 SOC_COUNTER_NON_DMA_UC_QUEUE_PEAK, startq, 9648 value)); 9649 COMPILER_64_UMUL_32(*value, _BCM_TR3_BYTES_PER_CELL); 9650 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 9651 return BCM_E_PARAM; 9652 } else { 9653 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_localport_resolve(unit, port, &local_port)); 9654 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_port_has_ets(unit, port)); 9655 COMPILER_64_ZERO(sum); 9656 if (cosq == BCM_COS_INVALID) { 9657 from_cos = 0; 9658 to_cos = (IS_CPU_PORT(unit, local_port)) ? 9659 NUM_CPU_COSQ(unit) - 1 : _TR3_NUM_COS(unit) - 1; 9660 } else { 9661 from_cos = to_cos = cosq; 9662 } 9663 9664 if (IS_CPU_PORT(unit, local_port)) { 9665 return BCM_E_PARAM; 9666 } 9667 for (ci = from_cos; ci <= to_cos; ci++) { 9668 BCM_IF_ERROR_RETURN 9669 (_bcm_tr3_cosq_index_resolve 9670 (unit, port, ci, _BCM_TR3_COSQ_INDEX_STYLE_EGR_PERQ_UCAST, 9671 &local_port, &startq, &numq)); 9672 for (i = 0; i < numq; i++) { 9673 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9674 BCM_IF_ERROR_RETURN 9675 (counter_get(unit, local_port, 9676 SOC_COUNTER_NON_DMA_UC_QUEUE_PEAK, 9677 startq + i, &value64)); 9678 COMPILER_64_ADD_64(sum, value64); 9679 } 9680 } 9681 COMPILER_64_UMUL_32(sum, _BCM_TR3_BYTES_PER_CELL); 9682 *value = sum; 9683 } 9684 break; 9685 9686 case bcmCosqStatEgressUCQueueBytesCurrent: 9687 if (BCM_GPORT_IS_SCHEDULER(port)) { 9688 BCM_IF_ERROR_RETURN 9689 (_bcm_tr3_cosq_node_get(unit, port, 0, NULL, 9690 &local_port, NULL, &node)); 9691 BCM_IF_ERROR_RETURN( 9692 _bcm_tr3_cosq_child_node_at_input(node, cosq, &node)); 9693 port = node->gport; 9694 } 9695 9696 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 9697 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port)) { 9698 BCM_IF_ERROR_RETURN 9699 (_bcm_tr3_cosq_index_resolve 9700 (unit, port, cosq, _BCM_TR3_COSQ_INDEX_STYLE_EGR_PERQ_UCAST, 9701 &local_port, &startq, NULL)); 9702 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9703 BCM_IF_ERROR_RETURN 9704 (counter_get(unit, local_port, 9705 SOC_COUNTER_NON_DMA_UC_QUEUE_CURRENT, startq, 9706 value)); 9707 COMPILER_64_UMUL_32(*value, _BCM_TR3_BYTES_PER_CELL); 9708 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 9709 return BCM_E_PARAM; 9710 } else { 9711 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_localport_resolve(unit, port, &local_port)); 9712 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_port_has_ets(unit, port)); 9713 9714 if (IS_CPU_PORT(unit, local_port)) { 9715 return BCM_E_PARAM; 9716 } 9717 COMPILER_64_ZERO(sum); 9718 if (cosq == BCM_COS_INVALID) { 9719 from_cos = 0; 9720 to_cos = (IS_CPU_PORT(unit, local_port)) ? 9721 NUM_CPU_COSQ(unit) - 1 : _TR3_NUM_COS(unit) - 1; 9722 } else { 9723 from_cos = to_cos = cosq; 9724 } 9725 9726 for (ci = from_cos; ci <= to_cos; ci++) { 9727 BCM_IF_ERROR_RETURN 9728 (_bcm_tr3_cosq_index_resolve 9729 (unit, port, ci, _BCM_TR3_COSQ_INDEX_STYLE_EGR_PERQ_UCAST, 9730 &local_port, &startq, &numq)); 9731 for (i = 0; i < numq; i++) { 9732 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9733 BCM_IF_ERROR_RETURN 9734 (counter_get(unit, local_port, 9735 SOC_COUNTER_NON_DMA_UC_QUEUE_CURRENT, 9736 startq + i, &value64)); 9737 COMPILER_64_ADD_64(sum, value64); 9738 } 9739 } 9740 COMPILER_64_UMUL_32(sum, _BCM_TR3_BYTES_PER_CELL); 9741 *value = sum; 9742 } 9743 break; 9744 9745 case bcmCosqStatUCDroppedPackets: 9746 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 9747 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port) || 9748 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) || 9749 BCM_GPORT_IS_SCHEDULER(port)) { 9750 return BCM_E_PARAM; 9751 } 9752 else { 9753 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_localport_resolve(unit, port, &local_port)); 9754 COMPILER_64_ZERO(sum); 9755 if (cosq == BCM_COS_INVALID) { 9756 from_cos = 0; 9757 if (IS_CPU_PORT(unit, local_port)) { 9758 to_cos = NUM_CPU_COSQ(unit) - 1; 9759 } else if (IS_TR3_HSP_PORT(unit, local_port)) { 9760 to_cos = _TR3_NUM_HSP_COSQ - 1; 9761 } else { 9762 to_cos = _TR3_NUM_COS(unit) - 1; 9763 } 9764 } else { 9765 from_cos = to_cos = cosq; 9766 } 9767 for (ci = from_cos; ci <= to_cos; ci++) { 9768 BCM_IF_ERROR_RETURN 9769 (_bcm_tr3_cosq_index_resolve 9770 (unit, port, ci, _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE, 9771 &local_port, &startq, &numq)); 9772 for (i = 0; i < numq; i++) { 9773 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9774 BCM_IF_ERROR_RETURN 9775 (counter_get(unit, REG_PORT_ANY, 9776 SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_UC, 9777 startq + i, &value64)); 9778 COMPILER_64_ADD_64(sum, value64); 9779 } 9780 } 9781 *value = sum; 9782 } 9783 break; 9784 9785 case bcmCosqStatMCDroppedPackets: 9786 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 9787 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port) || 9788 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) || 9789 BCM_GPORT_IS_SCHEDULER(port)) { 9790 return BCM_E_PARAM; 9791 } 9792 else { 9793 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_localport_resolve(unit, port, &local_port)); 9794 COMPILER_64_ZERO(sum); 9795 if (cosq == BCM_COS_INVALID) { 9796 from_cos = 0; 9797 if (IS_CPU_PORT(unit, local_port)) { 9798 to_cos = NUM_CPU_COSQ(unit) - 1; 9799 } else if (IS_TR3_HSP_PORT(unit, local_port)) { 9800 to_cos = _TR3_NUM_HSP_COSQ - 1; 9801 } else { 9802 to_cos = _TR3_NUM_COS(unit) - 1; 9803 } 9804 } else { 9805 from_cos = to_cos = cosq; 9806 } 9807 for (ci = from_cos; ci <= to_cos; ci++) { 9808 BCM_IF_ERROR_RETURN 9809 (_bcm_tr3_cosq_index_resolve 9810 (unit, port, ci, _BCM_TR3_COSQ_INDEX_STYLE_MCAST_QUEUE, 9811 &local_port, &startq, &numq)); 9812 for (i = 0; i < numq; i++) { 9813 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9814 BCM_IF_ERROR_RETURN 9815 (counter_get(unit, REG_PORT_ANY, 9816 SOC_COUNTER_NON_DMA_COSQ_DROP_PKT, 9817 startq + i - 1024, &value64)); 9818 COMPILER_64_ADD_64(sum, value64); 9819 } 9820 } 9821 *value = sum; 9822 } 9823 break; 9824 9825 case bcmCosqStatUCDroppedBytes: 9826 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 9827 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port) || 9828 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) || 9829 BCM_GPORT_IS_SCHEDULER(port)) { 9830 return BCM_E_PARAM; 9831 } 9832 else { 9833 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_localport_resolve(unit, port, &local_port)); 9834 COMPILER_64_ZERO(sum); 9835 if (cosq == BCM_COS_INVALID) { 9836 from_cos = 0; 9837 if (IS_CPU_PORT(unit, local_port)) { 9838 to_cos = NUM_CPU_COSQ(unit) - 1; 9839 } else if (IS_TR3_HSP_PORT(unit, local_port)) { 9840 to_cos = _TR3_NUM_HSP_COSQ - 1; 9841 } else { 9842 to_cos = _TR3_NUM_COS(unit) - 1; 9843 } 9844 } else { 9845 from_cos = to_cos = cosq; 9846 } 9847 for (ci = from_cos; ci <= to_cos; ci++) { 9848 BCM_IF_ERROR_RETURN 9849 (_bcm_tr3_cosq_index_resolve 9850 (unit, port, ci, _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE, 9851 &local_port, &startq, &numq)); 9852 for (i = 0; i < numq; i++) { 9853 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9854 BCM_IF_ERROR_RETURN 9855 (counter_get(unit, REG_PORT_ANY, 9856 SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE_UC, 9857 startq + i, &value64)); 9858 COMPILER_64_ADD_64(sum, value64); 9859 } 9860 } 9861 *value = sum; 9862 } 9863 break; 9864 9865 case bcmCosqStatMCDroppedBytes: 9866 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 9867 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port) || 9868 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) || 9869 BCM_GPORT_IS_SCHEDULER(port)) { 9870 return BCM_E_PARAM; 9871 } 9872 else { 9873 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_localport_resolve(unit, port, &local_port)); 9874 COMPILER_64_ZERO(sum); 9875 if (cosq == BCM_COS_INVALID) { 9876 from_cos = 0; 9877 if (IS_CPU_PORT(unit, local_port)) { 9878 to_cos = NUM_CPU_COSQ(unit) - 1; 9879 } else if (IS_TR3_HSP_PORT(unit, local_port)) { 9880 to_cos = _TR3_NUM_HSP_COSQ - 1; 9881 } else { 9882 to_cos = _TR3_NUM_COS(unit) - 1; 9883 } 9884 } else { 9885 from_cos = to_cos = cosq; 9886 } 9887 for (ci = from_cos; ci <= to_cos; ci++) { 9888 BCM_IF_ERROR_RETURN 9889 (_bcm_tr3_cosq_index_resolve 9890 (unit, port, ci, _BCM_TR3_COSQ_INDEX_STYLE_MCAST_QUEUE, 9891 &local_port, &startq, &numq)); 9892 for (i = 0; i < numq; i++) { 9893 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9894 BCM_IF_ERROR_RETURN 9895 (counter_get(unit, REG_PORT_ANY, 9896 SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE, 9897 startq + i - 1024, &value64)); 9898 COMPILER_64_ADD_64(sum, value64); 9899 } 9900 } 9901 *value = sum; 9902 } 9903 break; 9904 9905 case bcmCosqStatUCOutPackets: 9906 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 9907 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port) || 9908 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) || 9909 BCM_GPORT_IS_SCHEDULER(port)) { 9910 return BCM_E_PARAM; 9911 } 9912 else { 9913 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_localport_resolve(unit, port, &local_port)); 9914 COMPILER_64_ZERO(sum); 9915 if (cosq == BCM_COS_INVALID) { 9916 from_cos = 0; 9917 if (IS_CPU_PORT(unit, local_port)) { 9918 to_cos = NUM_CPU_COSQ(unit) - 1; 9919 } else if (IS_TR3_HSP_PORT(unit, local_port)) { 9920 to_cos = _TR3_NUM_HSP_COSQ - 1; 9921 } else { 9922 to_cos = _TR3_NUM_COS(unit) - 1; 9923 } 9924 } else { 9925 from_cos = to_cos = cosq; 9926 } 9927 for (ci = from_cos; ci <= to_cos; ci++) { 9928 BCM_IF_ERROR_RETURN 9929 (_bcm_tr3_cosq_index_resolve 9930 (unit, port, ci, _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE, 9931 &local_port, &startq, &numq)); 9932 for (i = 0; i < numq; i++) { 9933 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9934 BCM_IF_ERROR_RETURN 9935 (counter_get(unit, REG_PORT_ANY, 9936 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT_UC, 9937 startq + i, &value64)); 9938 COMPILER_64_ADD_64(sum, value64); 9939 } 9940 } 9941 *value = sum; 9942 } 9943 break; 9944 9945 case bcmCosqStatMCOutPackets: 9946 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 9947 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port) || 9948 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) || 9949 BCM_GPORT_IS_SCHEDULER(port)) { 9950 return BCM_E_PARAM; 9951 } 9952 else { 9953 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_localport_resolve(unit, port, &local_port)); 9954 COMPILER_64_ZERO(sum); 9955 if (cosq == BCM_COS_INVALID) { 9956 from_cos = 0; 9957 if (IS_CPU_PORT(unit, local_port)) { 9958 to_cos = NUM_CPU_COSQ(unit) - 1; 9959 } else if (IS_TR3_HSP_PORT(unit, local_port)) { 9960 to_cos = _TR3_NUM_HSP_COSQ - 1; 9961 } else { 9962 to_cos = _TR3_NUM_COS(unit) - 1; 9963 } 9964 } else { 9965 from_cos = to_cos = cosq; 9966 } 9967 for (ci = from_cos; ci <= to_cos; ci++) { 9968 BCM_IF_ERROR_RETURN 9969 (_bcm_tr3_cosq_index_resolve 9970 (unit, port, ci, _BCM_TR3_COSQ_INDEX_STYLE_MCAST_QUEUE, 9971 &local_port, &startq, &numq)); 9972 for (i = 0; i < numq; i++) { 9973 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9974 BCM_IF_ERROR_RETURN 9975 (counter_get(unit, REG_PORT_ANY, 9976 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT, 9977 startq + i, &value64)); 9978 COMPILER_64_ADD_64(sum, value64); 9979 } 9980 } 9981 *value = sum; 9982 } 9983 break; 9984 9985 case bcmCosqStatUCOutBytes: 9986 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 9987 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port) || 9988 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) || 9989 BCM_GPORT_IS_SCHEDULER(port)) { 9990 return BCM_E_PARAM; 9991 } 9992 else { 9993 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_localport_resolve(unit, port, &local_port)); 9994 COMPILER_64_ZERO(sum); 9995 if (cosq == BCM_COS_INVALID) { 9996 from_cos = 0; 9997 if (IS_CPU_PORT(unit, local_port)) { 9998 to_cos = NUM_CPU_COSQ(unit) - 1; 9999 } else if (IS_TR3_HSP_PORT(unit, local_port)) { 10000 to_cos = _TR3_NUM_HSP_COSQ - 1; 10001 } else { 10002 to_cos = _TR3_NUM_COS(unit) - 1; 10003 } 10004 } else { 10005 from_cos = to_cos = cosq; 10006 } 10007 for (ci = from_cos; ci <= to_cos; ci++) { 10008 BCM_IF_ERROR_RETURN 10009 (_bcm_tr3_cosq_index_resolve 10010 (unit, port, ci, _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE, 10011 &local_port, &startq, &numq)); 10012 for (i = 0; i < numq; i++) { 10013 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10014 BCM_IF_ERROR_RETURN 10015 (counter_get(unit, REG_PORT_ANY, 10016 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE_UC, 10017 startq + i, &value64)); 10018 COMPILER_64_ADD_64(sum, value64); 10019 } 10020 } 10021 *value = sum; 10022 } 10023 break; 10024 10025 case bcmCosqStatMCOutBytes: 10026 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 10027 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port) || 10028 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) || 10029 BCM_GPORT_IS_SCHEDULER(port)) { 10030 return BCM_E_PARAM; 10031 } 10032 else { 10033 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_localport_resolve(unit, port, &local_port)); 10034 COMPILER_64_ZERO(sum); 10035 if (cosq == BCM_COS_INVALID) { 10036 from_cos = 0; 10037 if (IS_CPU_PORT(unit, local_port)) { 10038 to_cos = NUM_CPU_COSQ(unit) - 1; 10039 } else if (IS_TR3_HSP_PORT(unit, local_port)) { 10040 to_cos = _TR3_NUM_HSP_COSQ - 1; 10041 } else { 10042 to_cos = _TR3_NUM_COS(unit) - 1; 10043 } 10044 } else { 10045 from_cos = to_cos = cosq; 10046 } 10047 for (ci = from_cos; ci <= to_cos; ci++) { 10048 BCM_IF_ERROR_RETURN 10049 (_bcm_tr3_cosq_index_resolve 10050 (unit, port, ci, _BCM_TR3_COSQ_INDEX_STYLE_MCAST_QUEUE, 10051 &local_port, &startq, &numq)); 10052 for (i = 0; i < numq; i++) { 10053 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10054 BCM_IF_ERROR_RETURN 10055 (counter_get(unit, REG_PORT_ANY, 10056 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE, 10057 startq + i, &value64)); 10058 COMPILER_64_ADD_64(sum, value64); 10059 } 10060 } 10061 *value = sum; 10062 } 10063 break; 10064 10065 default: 10066 return BCM_E_PARAM; 10067 } 10068 10069 return BCM_E_NONE; 10070 } 10071 10072 /* 10073 * Function: 10074 * _bcm_tr3_cosq_quantize_table_set 10075 * Purpose: 10076 * Generate quantized feedback lookup table 10077 * Parameters: 10078 * unit - (IN) unit number 10079 * profile_index - (IN) profile index 10080 * weight_code - (IN) weight encoding 10081 * set_point - (IN) queue size set point 10082 * active_offset - (OUT) most significant non-zero bit position 10083 * Returns: 10084 * BCM_E_XXX 10085 * Notes: 10086 * The formular to quantize feedback value is: 10087 * quantized_feedbad = celling(feedback / max_feedback * 63) 10088 * where max_feedback = (2 * cpW + 1) * cpQsp 10089 * cpW is feedback weight 10090 * cpQsp is queue size set point 10091 */ 10092 STATIC int 10093 _bcm_tr3_cosq_quantize_table_set(int unit, int profile_index, int weight_code, 10094 int set_point, int *active_offset) 10095 { 10096 int ref_count; 10097 int weight_x_4, feedback, max_feedback, quantized_feedback, shift; 10098 int base_index, index; 10099 10100 /* weight = 2 ** (weight_code - 2) e.g. 0 for 1/4, 1 for 1/2, ... */ 10101 weight_x_4 = 1 << weight_code; 10102 max_feedback = ((2 * weight_x_4 + 4) * set_point + 3) / 4; 10103 shift = 0; 10104 while ((max_feedback >> shift) > 127) { 10105 shift++; 10106 } 10107 10108 BCM_IF_ERROR_RETURN 10109 (soc_profile_reg_ref_count_get(unit, _bcm_tr3_feedback_profile[unit], 10110 profile_index, &ref_count)); 10111 10112 /* 10113 * Hardware use lookup table to find quantized feedback in order to avoid 10114 * division, use most significant 7-bit of feedback value as lookup table 10115 * index to find quantized_feedback value 10116 */ 10117 if (ref_count == 1) { 10118 base_index = profile_index << 7; 10119 for (index = 0; index < 128; index++) { 10120 feedback = index << shift; 10121 if (feedback > max_feedback) { 10122 quantized_feedback = 63; 10123 } else { 10124 quantized_feedback = (feedback * 63 + max_feedback - 1) / 10125 max_feedback; 10126 } 10127 BCM_IF_ERROR_RETURN 10128 (soc_mem_field32_modify(unit, MMU_QCN_QFBTBm, 10129 base_index + index, CPQ_QNTZFBf, 10130 quantized_feedback)); 10131 } 10132 } 10133 10134 *active_offset = shift + 6; 10135 10136 return BCM_E_NONE; 10137 } 10138 10139 10140 STATIC int 10141 _bcm_tr3_cosq_sample_int_table_set(int unit, int min, int max, 10142 uint32 *profile_index) 10143 { 10144 mmu_qcn_sitb_entry_t sitb_entries[64]; 10145 void *entries[1]; 10146 int i, j, center, inc, value, index; 10147 10148 sal_memset(sitb_entries, 0, sizeof(sitb_entries)); 10149 entries[0] = &sitb_entries; 10150 for (i = 0; i < 8; i++) { 10151 center = max - (max - min) * i / 7; 10152 inc = (max - min) / 7 / 8; 10153 for (j = 0; j < 8; j++, inc = -inc) { 10154 index = i * 8 + j; 10155 value = center + (j + 1) / 2 * inc; 10156 if (value > 255) { 10157 value = 255; 10158 } else if (value < 1) { 10159 value = 1; 10160 } 10161 soc_mem_field32_set(unit, MMU_QCN_SITBm, &sitb_entries[index], 10162 CPQ_SIf, value); 10163 } 10164 } 10165 10166 return soc_profile_mem_add(unit, _bcm_tr3_sample_int_profile[unit], entries, 10167 64, (uint32 *)profile_index); 10168 } 10169 10170 /* 10171 * Function: 10172 * bcm_tr3_cosq_congestion_queue_set 10173 * Purpose: 10174 * Enable/Disable a cos queue as congestion managed queue 10175 * Parameters: 10176 * unit - (IN) unit number 10177 * port - (IN) port number or GPORT identifier 10178 * cosq - (IN) COS queue number 10179 * index - (IN) congestion managed queue index 10180 * Returns: 10181 * BCM_E_XXX 10182 */ 10183 int 10184 bcm_tr3_cosq_congestion_queue_set(int unit, bcm_port_t port, 10185 bcm_cos_queue_t cosq, int index) 10186 { 10187 bcm_port_t local_port; 10188 uint32 rval; 10189 uint64 rval64, *rval64s[1]; 10190 mmu_qcn_enable_entry_t enable_entry; 10191 int active_offset, qindex; 10192 uint32 profile_index, sample_profile_index; 10193 int weight_code, set_point; 10194 10195 if (cosq < 0 || cosq >= _TR3_NUM_COS(unit)) { 10196 return BCM_E_PARAM; 10197 } 10198 if (index < -1 || index >= 512) { 10199 return BCM_E_PARAM; 10200 } 10201 10202 BCM_IF_ERROR_RETURN 10203 (_bcm_tr3_cosq_localport_resolve(unit, port, &local_port)); 10204 10205 BCM_IF_ERROR_RETURN 10206 (_bcm_tr3_cosq_index_resolve(unit, port, cosq, 10207 _BCM_TR3_COSQ_INDEX_STYLE_QCN, 10208 &local_port, &qindex, NULL)); 10209 10210 BCM_IF_ERROR_RETURN(soc_mem_read(unit, MMU_QCN_ENABLEm, 10211 MEM_BLOCK_ANY, qindex, &enable_entry)); 10212 if (index == -1) { 10213 if (!soc_mem_field32_get(unit, MMU_QCN_ENABLEm, &enable_entry, CPQ_ENf)) { 10214 return BCM_E_NONE; 10215 } 10216 10217 index = soc_mem_field32_get(unit, MMU_QCN_ENABLEm, &enable_entry, 10218 CPQ_PROFILE_INDEXf); 10219 soc_mem_field32_set(unit, MMU_QCN_ENABLEm, &enable_entry, 10220 CPQ_ENf, 0); 10221 BCM_IF_ERROR_RETURN 10222 (soc_mem_write(unit, MMU_QCN_ENABLEm, MEM_BLOCK_ANY, qindex, 10223 &enable_entry)); 10224 10225 profile_index = 10226 soc_mem_field32_get(unit, MMU_QCN_ENABLEm, &enable_entry, 10227 EQTB_INDEXf); 10228 10229 BCM_IF_ERROR_RETURN 10230 (soc_profile_reg_delete(unit, _bcm_tr3_feedback_profile[unit], 10231 profile_index)); 10232 10233 profile_index = 10234 soc_mem_field32_get(unit, MMU_QCN_ENABLEm, &enable_entry, SITB_SELf); 10235 10236 BCM_IF_ERROR_RETURN 10237 (soc_profile_mem_delete(unit, _bcm_tr3_sample_int_profile[unit], 10238 profile_index * 64)); 10239 } else { 10240 if (soc_mem_field32_get(unit, MMU_QCN_ENABLEm, 10241 &enable_entry, CPQ_ENf)) { 10242 return BCM_E_BUSY; 10243 } 10244 10245 /* Use hardware reset value as default quantize setting */ 10246 weight_code = 2; 10247 set_point = 0x96; 10248 rval = 0; 10249 soc_reg_field_set(unit, MMU_QCN_CPQ_SEQr, &rval, CPWf, weight_code); 10250 soc_reg_field_set(unit, MMU_QCN_CPQ_SEQr, &rval, CPQEQf, set_point); 10251 COMPILER_64_SET(rval64, 0, rval); 10252 rval64s[0] = &rval64; 10253 BCM_IF_ERROR_RETURN 10254 (soc_profile_reg_add(unit, _bcm_tr3_feedback_profile[unit], 10255 rval64s, 1, (uint32 *)&profile_index)); 10256 10257 /* Update quantized feedback calculation lookup table */ 10258 BCM_IF_ERROR_RETURN 10259 (_bcm_tr3_cosq_quantize_table_set(unit, profile_index, weight_code, 10260 set_point, &active_offset)); 10261 10262 /* Pick some sample interval */ 10263 BCM_IF_ERROR_RETURN 10264 (_bcm_tr3_cosq_sample_int_table_set(unit, 13, 127, 10265 &sample_profile_index)); 10266 10267 soc_mem_field32_set(unit, MMU_QCN_ENABLEm, &enable_entry, 10268 QNTZ_ACT_OFFSETf, active_offset); 10269 10270 soc_mem_field32_set(unit, MMU_QCN_ENABLEm, &enable_entry, 10271 SITB_SELf, sample_profile_index/64); 10272 10273 soc_mem_field32_set(unit, MMU_QCN_ENABLEm, &enable_entry, 10274 CPQ_INDEXf, index); 10275 10276 soc_mem_field32_set(unit, MMU_QCN_ENABLEm, &enable_entry, 10277 CPQ_ENf, 1); 10278 10279 BCM_IF_ERROR_RETURN 10280 (soc_mem_write(unit, MMU_QCN_ENABLEm, MEM_BLOCK_ANY, qindex, 10281 &enable_entry)); 10282 } 10283 10284 return BCM_E_NONE; 10285 } 10286 10287 /* 10288 * Function: 10289 * bcm_tr3_cosq_congestion_queue_get 10290 * Purpose: 10291 * Get congestion managed queue index of the specified cos queue 10292 * Parameters: 10293 * unit - (IN) unit number 10294 * port - (IN) port number or GPORT identifier 10295 * cosq - (IN) COS queue number 10296 * index - (OUT) congestion managed queue index 10297 * Returns: 10298 * BCM_E_XXX 10299 */ 10300 int 10301 bcm_tr3_cosq_congestion_queue_get(int unit, bcm_port_t port, 10302 bcm_cos_queue_t cosq, int *index) 10303 { 10304 bcm_port_t local_port; 10305 int qindex; 10306 mmu_qcn_enable_entry_t entry; 10307 10308 BCM_IF_ERROR_RETURN 10309 (_bcm_tr3_cosq_localport_resolve(unit, port, &local_port)); 10310 10311 if (cosq < 0 || cosq >= _TR3_NUM_COS(unit)) { 10312 return BCM_E_PARAM; 10313 } 10314 if (index == NULL) { 10315 return BCM_E_PARAM; 10316 } 10317 10318 BCM_IF_ERROR_RETURN 10319 (_bcm_tr3_cosq_index_resolve(unit, port, cosq, 10320 _BCM_TR3_COSQ_INDEX_STYLE_QCN, 10321 &local_port, &qindex, NULL)); 10322 10323 BCM_IF_ERROR_RETURN 10324 (soc_mem_read(unit, MMU_QCN_ENABLEm, MEM_BLOCK_ANY, qindex, &entry)); 10325 if (soc_mem_field32_get(unit, MMU_QCN_ENABLEm, &entry, CPQ_ENf)) { 10326 *index = soc_mem_field32_get(unit, MMU_QCN_ENABLEm, &entry, 10327 CPQ_INDEXf); 10328 } else { 10329 *index = -1; 10330 } 10331 10332 return BCM_E_NONE; 10333 } 10334 10335 /* 10336 * Function: 10337 * bcm_tr3_cosq_congestion_quantize_set 10338 * Purpose: 10339 * Set quantized congestion feedback algorithm parameters 10340 * Parameters: 10341 * unit - (IN) unit number 10342 * port - (IN) port number or GPORT identifier 10343 * cosq - (IN) COS queue number 10344 * weight_code - (IN) weight encoding (use -1 for unchange) 10345 * set_point - (IN) queue size set point (use -1 for unchange) 10346 * Returns: 10347 * BCM_E_XXX 10348 */ 10349 int 10350 bcm_tr3_cosq_congestion_quantize_set(int unit, bcm_port_t port, 10351 bcm_cos_queue_t cosq, int weight_code, 10352 int set_point) 10353 { 10354 bcm_port_t local_port; 10355 uint32 rval; 10356 uint64 rval64, *rval64s[1]; 10357 mmu_qcn_enable_entry_t enable_entry; 10358 int cpq_index, active_offset, qindex; 10359 uint32 profile_index, old_profile_index; 10360 10361 BCM_IF_ERROR_RETURN 10362 (_bcm_tr3_cosq_localport_resolve(unit, port, &local_port)); 10363 10364 BCM_IF_ERROR_RETURN 10365 (bcm_tr3_cosq_congestion_queue_get(unit, port, cosq, &cpq_index)); 10366 if (cpq_index == -1) { 10367 /* The cosq specified is not enabled as congestion managed queue */ 10368 return BCM_E_PARAM; 10369 } 10370 10371 BCM_IF_ERROR_RETURN 10372 (_bcm_tr3_cosq_index_resolve(unit, port, cosq, 10373 _BCM_TR3_COSQ_INDEX_STYLE_QCN, 10374 &local_port, &qindex, NULL)); 10375 10376 BCM_IF_ERROR_RETURN(soc_mem_read(unit, MMU_QCN_ENABLEm, 10377 MEM_BLOCK_ANY, qindex, &enable_entry)); 10378 old_profile_index = 10379 soc_mem_field32_get(unit, MMU_QCN_ENABLEm, &enable_entry, CPQ_PROFILE_INDEXf); 10380 10381 BCM_IF_ERROR_RETURN(READ_MMU_QCN_CPQ_SEQr(unit, old_profile_index, &rval)); 10382 if (weight_code == -1) { 10383 weight_code = soc_reg_field_get(unit, MMU_QCN_CPQ_SEQr, rval, CPWf); 10384 } else { 10385 if (weight_code < 0 || weight_code > 7) { 10386 return BCM_E_PARAM; 10387 } 10388 soc_reg_field_set(unit, MMU_QCN_CPQ_SEQr, &rval, CPWf, weight_code); 10389 } 10390 if (set_point == -1) { 10391 set_point = soc_reg_field_get(unit, MMU_QCN_CPQ_SEQr, rval, CPQEQf); 10392 } else { 10393 if (set_point < 0 || set_point > 0xffff) { 10394 return BCM_E_PARAM; 10395 } 10396 soc_reg_field_set(unit, MMU_QCN_CPQ_SEQr, &rval, CPQEQf, set_point); 10397 } 10398 COMPILER_64_SET(rval64, 0, rval); 10399 rval64s[0] = &rval64; 10400 /* Add new feedback parameter profile */ 10401 BCM_IF_ERROR_RETURN 10402 (soc_profile_reg_add(unit, _bcm_tr3_feedback_profile[unit], rval64s, 10403 1, (uint32 *)&profile_index)); 10404 /* Delete original feedback parameter profile */ 10405 BCM_IF_ERROR_RETURN 10406 (soc_profile_reg_delete(unit, _bcm_tr3_feedback_profile[unit], 10407 old_profile_index)); 10408 10409 /* Update quantized feedback calculation lookup table */ 10410 BCM_IF_ERROR_RETURN 10411 (_bcm_tr3_cosq_quantize_table_set(unit, profile_index, weight_code, 10412 set_point, &active_offset)); 10413 10414 soc_mem_field32_set(unit, MMU_QCN_ENABLEm, &enable_entry, 10415 QNTZ_ACT_OFFSETf, active_offset); 10416 soc_mem_field32_set(unit, MMU_QCN_ENABLEm, &enable_entry, 10417 CPQ_PROFILE_INDEXf, profile_index); 10418 BCM_IF_ERROR_RETURN 10419 (soc_mem_write(unit, MMU_QCN_ENABLEm, MEM_BLOCK_ANY, qindex, 10420 &enable_entry)); 10421 10422 return BCM_E_NONE; 10423 } 10424 10425 /* 10426 * Function: 10427 * bcm_tr3_cosq_congestion_quantize_get 10428 * Purpose: 10429 * Get quantized congestion feedback algorithm parameters 10430 * Parameters: 10431 * unit - (IN) unit number 10432 * port - (IN) port number or GPORT identifier 10433 * cosq - (IN) COS queue number 10434 * weight_code - (OUT) weight encoding 10435 * set_point - (OUT) queue size set point 10436 * Returns: 10437 * BCM_E_XXX 10438 */ 10439 int 10440 bcm_tr3_cosq_congestion_quantize_get(int unit, bcm_port_t port, 10441 bcm_cos_queue_t cosq, int *weight_code, 10442 int *set_point) 10443 { 10444 bcm_port_t local_port; 10445 int cpq_index, profile_index, qindex; 10446 uint32 rval; 10447 mmu_qcn_enable_entry_t enable_entry; 10448 10449 BCM_IF_ERROR_RETURN 10450 (_bcm_tr3_cosq_localport_resolve(unit, port, &local_port)); 10451 10452 BCM_IF_ERROR_RETURN 10453 (bcm_tr3_cosq_congestion_queue_get(unit, port, cosq, &cpq_index)); 10454 if (cpq_index == -1) { 10455 /* The cosq specified is not enabled as congestion managed queue */ 10456 return BCM_E_PARAM; 10457 } 10458 10459 BCM_IF_ERROR_RETURN 10460 (_bcm_tr3_cosq_index_resolve(unit, port, cosq, 10461 _BCM_TR3_COSQ_INDEX_STYLE_QCN, 10462 &local_port, &qindex, NULL)); 10463 BCM_IF_ERROR_RETURN(soc_mem_read(unit, MMU_QCN_ENABLEm, 10464 MEM_BLOCK_ANY, qindex, &enable_entry)); 10465 10466 profile_index = 10467 soc_mem_field32_get(unit, MMU_QCN_ENABLEm, &enable_entry, CPQ_PROFILE_INDEXf); 10468 10469 BCM_IF_ERROR_RETURN(READ_MMU_QCN_CPQ_SEQr(unit, profile_index, &rval)); 10470 if (weight_code != NULL) { 10471 *weight_code = soc_reg_field_get(unit, MMU_QCN_CPQ_SEQr, rval, CPWf); 10472 } 10473 if (set_point != NULL) { 10474 *set_point = soc_reg_field_get(unit, MMU_QCN_CPQ_SEQr, rval, CPQEQf); 10475 } 10476 10477 return BCM_E_NONE; 10478 } 10479 10480 int 10481 bcm_tr3_cosq_congestion_sample_int_set(int unit, bcm_port_t port, 10482 bcm_cos_queue_t cosq, int min, int max) 10483 { 10484 bcm_port_t local_port; 10485 mmu_qcn_enable_entry_t entry; 10486 mmu_qcn_sitb_entry_t sitb_entry; 10487 int qindex; 10488 uint32 profile_index, old_profile_index; 10489 10490 BCM_IF_ERROR_RETURN 10491 (_bcm_tr3_cosq_localport_resolve(unit, port, &local_port)); 10492 10493 BCM_IF_ERROR_RETURN 10494 (_bcm_tr3_cosq_index_resolve(unit, port, cosq, 10495 _BCM_TR3_COSQ_INDEX_STYLE_QCN, 10496 &local_port, &qindex, NULL)); 10497 10498 BCM_IF_ERROR_RETURN 10499 (soc_mem_read(unit, MMU_QCN_ENABLEm, MEM_BLOCK_ANY, qindex, &entry)); 10500 10501 if (!soc_mem_field32_get(unit, MMU_QCN_ENABLEm, &entry, CPQ_ENf)) { 10502 return BCM_E_PARAM; 10503 } 10504 10505 old_profile_index = 10506 soc_mem_field32_get(unit, MMU_QCN_ENABLEm, &entry, SITB_SELf); 10507 10508 if (max == -1) { 10509 BCM_IF_ERROR_RETURN(soc_mem_read(unit, MMU_QCN_SITBm, MEM_BLOCK_ANY, 10510 old_profile_index * 64, &sitb_entry)); 10511 max = soc_mem_field32_get(unit, MMU_QCN_SITBm, &sitb_entry, CPQ_SIf); 10512 } else { 10513 if (max < 1 || max > 255) { 10514 return BCM_E_PARAM; 10515 } 10516 } 10517 if (min == -1) { 10518 BCM_IF_ERROR_RETURN(soc_mem_read(unit, MMU_QCN_SITBm, MEM_BLOCK_ANY, 10519 old_profile_index * 64 + 63, 10520 &sitb_entry)); 10521 min = soc_mem_field32_get(unit, MMU_QCN_SITBm, &sitb_entry, CPQ_SIf); 10522 } else { 10523 if (min < 1 || min > 255) { 10524 return BCM_E_PARAM; 10525 } 10526 } 10527 10528 /* Add new sample interval profile */ 10529 BCM_IF_ERROR_RETURN 10530 (_bcm_tr3_cosq_sample_int_table_set(unit, min, max, &profile_index)); 10531 10532 /* Delete original sample interval profile */ 10533 BCM_IF_ERROR_RETURN 10534 (soc_profile_mem_delete(unit, _bcm_tr3_sample_int_profile[unit], 10535 old_profile_index * 64)); 10536 10537 soc_mem_field32_set(unit, MMU_QCN_ENABLEm, &entry, SITB_SELf, 10538 profile_index / 64); 10539 BCM_IF_ERROR_RETURN(soc_mem_write(unit, MMU_QCN_ENABLEm, MEM_BLOCK_ANY, 10540 qindex, &entry)); 10541 return BCM_E_NONE; 10542 } 10543 10544 int 10545 bcm_tr3_cosq_congestion_sample_int_get(int unit, bcm_port_t port, 10546 bcm_cos_queue_t cosq, int *min, int *max) 10547 { 10548 bcm_port_t local_port; 10549 mmu_qcn_enable_entry_t entry; 10550 mmu_qcn_sitb_entry_t sitb_entry; 10551 int qindex; 10552 uint32 old_profile_index; 10553 10554 BCM_IF_ERROR_RETURN 10555 (_bcm_tr3_cosq_localport_resolve(unit, port, &local_port)); 10556 10557 BCM_IF_ERROR_RETURN 10558 (_bcm_tr3_cosq_index_resolve(unit, port, cosq, 10559 _BCM_TR3_COSQ_INDEX_STYLE_QCN, 10560 &local_port, &qindex, NULL)); 10561 10562 BCM_IF_ERROR_RETURN 10563 (soc_mem_read(unit, MMU_QCN_ENABLEm, MEM_BLOCK_ANY, qindex, &entry)); 10564 10565 if (!soc_mem_field32_get(unit, MMU_QCN_ENABLEm, &entry, CPQ_ENf)) { 10566 return BCM_E_PARAM; 10567 } 10568 10569 old_profile_index = 10570 soc_mem_field32_get(unit, MMU_QCN_ENABLEm, &entry, SITB_SELf); 10571 10572 if (max) { 10573 BCM_IF_ERROR_RETURN(soc_mem_read(unit, MMU_QCN_SITBm, MEM_BLOCK_ANY, 10574 old_profile_index * 64, &sitb_entry)); 10575 *max = soc_mem_field32_get(unit, MMU_QCN_SITBm, &sitb_entry, CPQ_SIf); 10576 } 10577 10578 if (min) { 10579 BCM_IF_ERROR_RETURN(soc_mem_read(unit, MMU_QCN_SITBm, MEM_BLOCK_ANY, 10580 old_profile_index * 64 + 63, 10581 &sitb_entry)); 10582 *min = soc_mem_field32_get(unit, MMU_QCN_SITBm, &sitb_entry, CPQ_SIf); 10583 } 10584 10585 return BCM_E_NONE; 10586 } 10587 10588 STATIC int 10589 _bcm_tr3_cosq_egr_pool_set(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 10590 bcm_cosq_control_t type, int arg) 10591 { 10592 bcm_port_t local_port; 10593 int startq; 10594 uint32 rval; 10595 int num_cells; 10596 uint32 entry[SOC_MAX_MEM_WORDS]; 10597 10598 num_cells = 0; 10599 10600 if (type == bcmCosqControlUCEgressPool) { 10601 BCM_IF_ERROR_RETURN 10602 (_bcm_tr3_cosq_index_resolve(unit, gport, cosq, 10603 _BCM_TR3_COSQ_INDEX_STYLE_UC_EGR_POOL, 10604 &local_port, &startq, NULL)); 10605 } else { 10606 BCM_IF_ERROR_RETURN 10607 (_bcm_tr3_cosq_index_resolve(unit, gport, cosq, 10608 _BCM_TR3_COSQ_INDEX_STYLE_EGR_POOL, 10609 &local_port, &startq, NULL)); 10610 } 10611 10612 if (type == bcmCosqControlEgressPoolLimitEnable) { 10613 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 10614 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) { 10615 BCM_IF_ERROR_RETURN(soc_reg32_get(unit, OP_PORT_CONFIG1_CELLr, 10616 local_port, 0, &rval)); 10617 soc_reg_field_set(unit, OP_PORT_CONFIG1_CELLr, &rval, 10618 PORT_LIMIT_ENABLE_CELLf, arg ? 1 : 0); 10619 BCM_IF_ERROR_RETURN(soc_reg32_set(unit, OP_PORT_CONFIG1_CELLr, 10620 local_port, 0, rval)); 10621 } else { 10622 BCM_IF_ERROR_RETURN(soc_reg32_get(unit, OP_QUEUE_CONFIG1_CELLr, 10623 local_port, startq, &rval)); 10624 soc_reg_field_set(unit, OP_QUEUE_CONFIG1_CELLr, 10625 &rval, Q_LIMIT_ENABLE_CELLf, arg ? 1 : 0); 10626 10627 BCM_IF_ERROR_RETURN(soc_reg32_set(unit, OP_QUEUE_CONFIG1_CELLr, 10628 local_port, startq, rval)); 10629 } 10630 return BCM_E_NONE; 10631 } else if (type == bcmCosqControlEgressPool || type == bcmCosqControlUCEgressPool || 10632 type == bcmCosqControlMCEgressPool) { 10633 if (arg < 0 || arg > 3) { 10634 return BCM_E_PARAM; 10635 } 10636 } else if (type == bcmCosqControlEgressPoolLimitBytes || 10637 type == bcmCosqControlEgressPoolYellowLimitBytes || 10638 type == bcmCosqControlEgressPoolRedLimitBytes) { 10639 if (arg < 0) { 10640 return BCM_E_PARAM; 10641 } 10642 num_cells = _BCM_TR3_BYTES_TO_CELLS(arg); 10643 if (num_cells > _BCM_TR3_TOTAL_CELLS) { 10644 return BCM_E_PARAM; 10645 } 10646 } 10647 10648 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 10649 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) { 10650 BCM_IF_ERROR_RETURN( 10651 soc_mem_read(unit, MMU_THDO_Q_TO_QGRP_MAPm, MEM_BLOCK_ALL, 10652 startq, entry)); 10653 } else { 10654 BCM_IF_ERROR_RETURN( 10655 soc_reg32_get(unit, OP_QUEUE_CONFIG1_CELLr, local_port, startq, &rval)); 10656 } 10657 10658 10659 /* per service pool settings */ 10660 if (type == bcmCosqControlEgressPoolSharedLimitBytes || 10661 type == bcmCosqControlEgressPoolResumeLimitBytes || 10662 type == bcmCosqControlEgressPoolYellowSharedLimitBytes || 10663 type == bcmCosqControlEgressPoolYellowResumeLimitBytes || 10664 type == bcmCosqControlEgressPoolRedSharedLimitBytes || 10665 type == bcmCosqControlEgressPoolRedResumeLimitBytes) { 10666 uint32 rval, max_val; 10667 soc_reg_t reg; 10668 soc_field_t fld_limit = INVALIDf; 10669 int granularity = 1,pool; 10670 10671 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 10672 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) { 10673 pool = soc_mem_field32_get(unit, MMU_THDO_Q_TO_QGRP_MAPm, entry, Q_SPIDf); 10674 } else { 10675 pool = soc_reg_field_get(unit, OP_QUEUE_CONFIG1_CELLr, rval, Q_SPIDf); 10676 } 10677 10678 switch (type) { 10679 case bcmCosqControlEgressPoolSharedLimitBytes: 10680 reg = OP_BUFFER_SHARED_LIMIT_CELLr; 10681 fld_limit = OP_BUFFER_SHARED_LIMIT_CELLf; 10682 granularity = 1; 10683 break; 10684 case bcmCosqControlEgressPoolResumeLimitBytes: 10685 reg = OP_BUFFER_SHARED_LIMIT_RESUME_CELLr; 10686 fld_limit = OP_BUFFER_SHARED_LIMIT_RESUME_CELLf; 10687 granularity = 1; 10688 break; 10689 case bcmCosqControlEgressPoolYellowSharedLimitBytes: 10690 reg = OP_BUFFER_LIMIT_YELLOW_CELLr; 10691 fld_limit = OP_BUFFER_LIMIT_YELLOW_CELLf; 10692 granularity = 8; 10693 break; 10694 case bcmCosqControlEgressPoolYellowResumeLimitBytes: 10695 reg = OP_BUFFER_LIMIT_RESUME_YELLOW_CELLr; 10696 fld_limit = OP_BUFFER_LIMIT_RESUME_YELLOW_CELLf; 10697 granularity = 8; 10698 break; 10699 case bcmCosqControlEgressPoolRedSharedLimitBytes: 10700 reg = OP_BUFFER_LIMIT_RED_CELLr; 10701 fld_limit = OP_BUFFER_LIMIT_RED_CELLf; 10702 granularity = 8; 10703 break; 10704 case bcmCosqControlEgressPoolRedResumeLimitBytes: 10705 reg = OP_BUFFER_LIMIT_RESUME_RED_CELLr; 10706 fld_limit = OP_BUFFER_LIMIT_RESUME_RED_CELLf; 10707 granularity = 8; 10708 break; 10709 /* 10710 * COVERITY 10711 * 10712 * This default is unreachable but needed for some compiler. 10713 */ 10714 /* coverity[dead_error_begin] */ 10715 default: 10716 return BCM_E_UNAVAIL; 10717 } 10718 10719 num_cells = _BCM_TR3_BYTES_TO_CELLS(arg); 10720 if (num_cells > _BCM_TR3_TOTAL_CELLS) { 10721 return BCM_E_PARAM; 10722 } 10723 10724 BCM_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, pool, &rval)); 10725 10726 /* Check for min/max values */ 10727 max_val = (1 << soc_reg_field_length(unit, reg, fld_limit)) - 1; 10728 if ((num_cells < 0) || ((num_cells/granularity) > max_val)) { 10729 return BCM_E_PARAM; 10730 } else { 10731 soc_reg_field_set(unit, reg, &rval, fld_limit, (num_cells/granularity)); 10732 } 10733 10734 BCM_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, pool, rval)); 10735 10736 return BCM_E_NONE; 10737 } 10738 10739 switch (type) { 10740 case bcmCosqControlEgressPool: 10741 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 10742 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) { 10743 soc_mem_field32_set(unit, MMU_THDO_Q_TO_QGRP_MAPm, entry, Q_SPIDf, arg); 10744 BCM_IF_ERROR_RETURN 10745 (soc_mem_write(unit, MMU_THDO_Q_TO_QGRP_MAPm, 10746 MEM_BLOCK_ALL, startq, entry)); 10747 } else { 10748 soc_reg_field_set(unit, OP_QUEUE_CONFIG1_CELLr, &rval, Q_SPIDf, arg); 10749 SOC_IF_ERROR_RETURN 10750 (WRITE_OP_QUEUE_CONFIG1_CELLr(unit, local_port, startq, rval)); 10751 } 10752 break; 10753 10754 case bcmCosqControlUCEgressPool: 10755 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 10756 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport) || 10757 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 10758 return BCM_E_PARAM; 10759 } 10760 startq = SOC_INFO(unit).port_uc_cosq_base[local_port] + startq; 10761 BCM_IF_ERROR_RETURN( 10762 soc_mem_read(unit, MMU_THDO_Q_TO_QGRP_MAPm, MEM_BLOCK_ALL, 10763 startq, entry)); 10764 soc_mem_field32_set(unit, MMU_THDO_Q_TO_QGRP_MAPm, entry, Q_SPIDf, arg); 10765 BCM_IF_ERROR_RETURN 10766 (soc_mem_write(unit, MMU_THDO_Q_TO_QGRP_MAPm, 10767 MEM_BLOCK_ALL, startq, entry)); 10768 break; 10769 10770 case bcmCosqControlMCEgressPool: 10771 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 10772 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport) || 10773 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 10774 return BCM_E_PARAM; 10775 } 10776 soc_reg_field_set(unit, OP_QUEUE_CONFIG1_CELLr, &rval, Q_SPIDf, arg); 10777 SOC_IF_ERROR_RETURN 10778 (WRITE_OP_QUEUE_CONFIG1_CELLr(unit, local_port, startq, rval)); 10779 break; 10780 10781 case bcmCosqControlEgressPoolLimitBytes: 10782 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 10783 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) { 10784 BCM_IF_ERROR_RETURN( 10785 soc_mem_read(unit, MMU_THDO_CONFIG_QUEUEm, MEM_BLOCK_ALL, 10786 startq, entry)); 10787 soc_mem_field32_set(unit, MMU_THDO_CONFIG_QUEUEm, entry, 10788 Q_SHARED_LIMIT_CELLf, num_cells); 10789 BCM_IF_ERROR_RETURN 10790 (soc_mem_write(unit, MMU_THDO_CONFIG_QUEUEm, 10791 MEM_BLOCK_ALL, startq, entry)); 10792 } else { 10793 BCM_IF_ERROR_RETURN( 10794 soc_reg32_get(unit, OP_QUEUE_CONFIG_CELLr, local_port, startq, &rval)); 10795 soc_reg_field_set(unit, OP_QUEUE_CONFIG_CELLr, &rval, 10796 Q_SHARED_LIMIT_CELLf, num_cells); 10797 BCM_IF_ERROR_RETURN(soc_reg32_set(unit, OP_QUEUE_CONFIG_CELLr, 10798 local_port, startq, rval)); 10799 } 10800 10801 break; 10802 case bcmCosqControlEgressPoolYellowLimitBytes: 10803 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 10804 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) { 10805 BCM_IF_ERROR_RETURN( 10806 soc_mem_read(unit, MMU_THDO_CONFIG_QUEUEm, MEM_BLOCK_ALL, 10807 startq, entry)); 10808 soc_mem_field32_set(unit, MMU_THDO_CONFIG_QUEUEm, 10809 entry, LIMIT_YELLOW_CELLf, num_cells / 8); 10810 BCM_IF_ERROR_RETURN 10811 (soc_mem_write(unit, MMU_THDO_CONFIG_QUEUEm, 10812 MEM_BLOCK_ALL, startq, entry)); 10813 } else { 10814 return BCM_E_UNAVAIL; 10815 } 10816 break; 10817 case bcmCosqControlEgressPoolRedLimitBytes: 10818 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 10819 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) { 10820 BCM_IF_ERROR_RETURN( 10821 soc_mem_read(unit, MMU_THDO_CONFIG_QUEUEm, MEM_BLOCK_ALL, 10822 startq, entry)); 10823 soc_mem_field32_set(unit, MMU_THDO_CONFIG_QUEUEm, 10824 entry, LIMIT_RED_CELLf, num_cells / 8); 10825 BCM_IF_ERROR_RETURN 10826 (soc_mem_write(unit, MMU_THDO_CONFIG_QUEUEm, 10827 MEM_BLOCK_ALL, startq, entry)); 10828 } else { 10829 BCM_IF_ERROR_RETURN( 10830 soc_reg32_get(unit, OP_QUEUE_LIMIT_COLOR_CELLr, 10831 local_port, startq, &rval)); 10832 soc_reg_field_set(unit, OP_QUEUE_LIMIT_COLOR_CELLr, &rval, REDf, num_cells/8); 10833 BCM_IF_ERROR_RETURN(soc_reg32_set(unit, OP_QUEUE_LIMIT_COLOR_CELLr, 10834 local_port, startq, rval)); 10835 } 10836 break; 10837 default: 10838 return BCM_E_UNAVAIL; 10839 } 10840 return BCM_E_NONE; 10841 } 10842 10843 STATIC int 10844 _bcm_tr3_cosq_alpha_set(int unit, bcm_gport_t gport, 10845 bcm_cos_queue_t cosq, bcm_cosq_control_t type, 10846 bcm_cosq_control_drop_limit_alpha_value_t arg) 10847 { 10848 bcm_port_t local_port; 10849 int startq; 10850 int midx; 10851 uint32 rval; 10852 uint32 entry[SOC_MAX_MEM_WORDS]; 10853 soc_mem_t mem = INVALIDm; 10854 int alpha; 10855 int dynamic_thresh_mode; 10856 soc_reg_t reg = INVALIDr; 10857 int phy_port, mmu_port, idx; 10858 thdi_port_pg_config_entry_t pg_config_mem; 10859 soc_info_t *si; 10860 int type_uc = 0, type_mc = 0; 10861 10862 if (type == bcmCosqControlDropLimitAlpha) { 10863 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 10864 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) { 10865 type_uc = 1; 10866 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 10867 type_mc = 1; 10868 } 10869 } else if (type == bcmCosqControlUCDropLimitAlpha) { 10870 if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 10871 return BCM_E_PARAM; 10872 } 10873 type_uc = 1; 10874 } else if (type == bcmCosqControlMCDropLimitAlpha) { 10875 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 10876 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) { 10877 return BCM_E_PARAM; 10878 } 10879 type_mc = 1; 10880 } 10881 10882 si = &SOC_INFO(unit); 10883 switch(arg) { 10884 case bcmCosqControlDropLimitAlpha_1_64: 10885 alpha = SOC_TR3_COSQ_DROP_LIMIT_ALPHA_1_64; 10886 break; 10887 case bcmCosqControlDropLimitAlpha_1_32: 10888 alpha = SOC_TR3_COSQ_DROP_LIMIT_ALPHA_1_32; 10889 break; 10890 case bcmCosqControlDropLimitAlpha_1_16: 10891 alpha = SOC_TR3_COSQ_DROP_LIMIT_ALPHA_1_16; 10892 break; 10893 case bcmCosqControlDropLimitAlpha_1_8: 10894 alpha = SOC_TR3_COSQ_DROP_LIMIT_ALPHA_1_8; 10895 break; 10896 case bcmCosqControlDropLimitAlpha_1_4: 10897 alpha = SOC_TR3_COSQ_DROP_LIMIT_ALPHA_1_4; 10898 break; 10899 case bcmCosqControlDropLimitAlpha_1_2: 10900 alpha = SOC_TR3_COSQ_DROP_LIMIT_ALPHA_1_2; 10901 break; 10902 case bcmCosqControlDropLimitAlpha_1: 10903 alpha = SOC_TR3_COSQ_DROP_LIMIT_ALPHA_1; 10904 break; 10905 case bcmCosqControlDropLimitAlpha_2: 10906 alpha = SOC_TR3_COSQ_DROP_LIMIT_ALPHA_2; 10907 break; 10908 case bcmCosqControlDropLimitAlpha_4: 10909 alpha = SOC_TR3_COSQ_DROP_LIMIT_ALPHA_4; 10910 break; 10911 case bcmCosqControlDropLimitAlpha_8: 10912 alpha = SOC_TR3_COSQ_DROP_LIMIT_ALPHA_8; 10913 break; 10914 default: 10915 return BCM_E_PARAM; 10916 } 10917 10918 if (type_uc == 1) { 10919 BCM_IF_ERROR_RETURN 10920 (_bcm_tr3_cosq_dynamic_thresh_enable_get(unit, gport, cosq, 10921 bcmCosqControlEgressUCSharedDynamicEnable, 10922 &dynamic_thresh_mode)); 10923 if (!dynamic_thresh_mode){ 10924 return BCM_E_CONFIG; 10925 } 10926 10927 BCM_IF_ERROR_RETURN 10928 (_bcm_tr3_cosq_index_resolve(unit, gport, cosq, 10929 _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE, 10930 &local_port, &startq, NULL)); 10931 10932 mem = MMU_THDO_CONFIG_QUEUEm; 10933 BCM_IF_ERROR_RETURN 10934 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 10935 soc_mem_field32_set(unit, mem, entry, 10936 Q_SHARED_ALPHA_CELLf, alpha); 10937 SOC_IF_ERROR_RETURN 10938 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 10939 } else if (type_mc == 1) { 10940 BCM_IF_ERROR_RETURN 10941 (_bcm_tr3_cosq_dynamic_thresh_enable_get(unit, gport, cosq, 10942 bcmCosqControlEgressMCSharedDynamicEnable, 10943 &dynamic_thresh_mode)); 10944 if (!dynamic_thresh_mode){ 10945 return BCM_E_CONFIG; 10946 } 10947 if (cosq < 0) { 10948 return BCM_E_PARAM; 10949 } 10950 10951 BCM_IF_ERROR_RETURN 10952 (_bcm_tr3_cosq_index_resolve(unit, gport, cosq, 10953 _BCM_TR3_COSQ_INDEX_STYLE_MCAST_QUEUE, 10954 &local_port, &startq, NULL)); 10955 reg = OP_QUEUE_CONFIG_CELLr; 10956 if (startq >= _BCM_TR3_NUM_L2_UC_LEAVES) { 10957 startq -= (_BCM_TR3_NUM_L2_UC_LEAVES + si->port_cosq_base[local_port]); 10958 } 10959 10960 BCM_IF_ERROR_RETURN 10961 (soc_reg32_get(unit, reg, local_port, 10962 startq, &rval)); 10963 soc_reg_field_set(unit, reg, &rval, Q_SHARED_ALPHA_CELLf, alpha); 10964 BCM_IF_ERROR_RETURN 10965 (soc_reg32_set(unit, reg, local_port, 10966 startq, rval)); 10967 } else { 10968 BCM_IF_ERROR_RETURN 10969 (_bcm_tr3_cosq_localport_resolve(unit, gport, &local_port)); 10970 if (local_port < 0) { 10971 return BCM_E_PORT; 10972 } 10973 phy_port = si->port_l2p_mapping[local_port]; 10974 mmu_port = si->port_p2m_mapping[phy_port]; 10975 10976 /* Input port per port per priority group settings */ 10977 for (idx = 0; idx < _BCM_TR3_MMU_NUM_PG; idx++) { 10978 midx = (mmu_port * 8) + idx; 10979 mem = THDI_PORT_PG_CONFIGm; 10980 sal_memset(&pg_config_mem, 0, sizeof(pg_config_mem)); 10981 BCM_IF_ERROR_RETURN 10982 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, &pg_config_mem)); 10983 soc_mem_field32_set(unit, mem, &pg_config_mem, 10984 PG_SHARED_LIMITf, alpha); 10985 soc_mem_field32_set(unit, mem, &pg_config_mem, 10986 PG_SHARED_DYNAMICf, 1); 10987 SOC_IF_ERROR_RETURN 10988 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, midx, &pg_config_mem)); 10989 } 10990 } 10991 10992 return BCM_E_NONE; 10993 } 10994 10995 STATIC int 10996 _bcm_tr3_cosq_alpha_get(int unit, bcm_gport_t gport, 10997 bcm_cos_queue_t cosq, bcm_cosq_control_t type, 10998 bcm_cosq_control_drop_limit_alpha_value_t *arg) 10999 { 11000 bcm_port_t local_port; 11001 int startq; 11002 int midx; 11003 uint32 rval; 11004 uint32 entry[SOC_MAX_MEM_WORDS]; 11005 soc_mem_t mem = INVALIDm; 11006 int dynamic_thresh_mode; 11007 soc_reg_t reg = INVALIDr; 11008 int phy_port, mmu_port, idx; 11009 thdi_port_pg_config_entry_t pg_config_mem; 11010 soc_info_t *si; 11011 int alpha = -1; 11012 int type_uc = 0, type_mc = 0; 11013 11014 if (!arg) { 11015 return BCM_E_PARAM; 11016 } 11017 11018 if (type == bcmCosqControlDropLimitAlpha) { 11019 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 11020 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) { 11021 type_uc = 1; 11022 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 11023 type_mc = 1; 11024 } 11025 } else if (type == bcmCosqControlUCDropLimitAlpha) { 11026 if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 11027 return BCM_E_PARAM; 11028 } 11029 type_uc = 1; 11030 } else if (type == bcmCosqControlMCDropLimitAlpha) { 11031 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 11032 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) { 11033 return BCM_E_PARAM; 11034 } 11035 type_mc = 1; 11036 } 11037 11038 si = &SOC_INFO(unit); 11039 11040 if (type_uc == 1) { 11041 BCM_IF_ERROR_RETURN 11042 (_bcm_tr3_cosq_dynamic_thresh_enable_get(unit, gport, cosq, 11043 bcmCosqControlEgressUCSharedDynamicEnable, 11044 &dynamic_thresh_mode)); 11045 if (!dynamic_thresh_mode){ 11046 return BCM_E_CONFIG; 11047 } 11048 11049 BCM_IF_ERROR_RETURN 11050 (_bcm_tr3_cosq_index_resolve(unit, gport, cosq, 11051 _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE, 11052 &local_port, &startq, NULL)); 11053 11054 mem = MMU_THDO_CONFIG_QUEUEm; 11055 BCM_IF_ERROR_RETURN 11056 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 11057 alpha = soc_mem_field32_get(unit, mem, entry, 11058 Q_SHARED_ALPHA_CELLf); 11059 } else if (type_mc == 1) { 11060 BCM_IF_ERROR_RETURN 11061 (_bcm_tr3_cosq_dynamic_thresh_enable_get(unit, gport, cosq, 11062 bcmCosqControlEgressMCSharedDynamicEnable, 11063 &dynamic_thresh_mode)); 11064 if (!dynamic_thresh_mode){ 11065 return BCM_E_CONFIG; 11066 } 11067 if (cosq < 0) { 11068 return BCM_E_PARAM; 11069 } 11070 11071 BCM_IF_ERROR_RETURN 11072 (_bcm_tr3_cosq_index_resolve(unit, gport, cosq, 11073 _BCM_TR3_COSQ_INDEX_STYLE_MCAST_QUEUE, 11074 &local_port, &startq, NULL)); 11075 reg = OP_QUEUE_CONFIG_CELLr; 11076 if (startq >= _BCM_TR3_NUM_L2_UC_LEAVES) { 11077 startq -= (_BCM_TR3_NUM_L2_UC_LEAVES + si->port_cosq_base[local_port]); 11078 } 11079 11080 BCM_IF_ERROR_RETURN 11081 (soc_reg32_get(unit, reg, local_port, 11082 startq, &rval)); 11083 alpha = soc_reg_field_get(unit, reg, rval, Q_SHARED_ALPHA_CELLf); 11084 } else { 11085 BCM_IF_ERROR_RETURN 11086 (_bcm_tr3_cosq_localport_resolve(unit, gport, &local_port)); 11087 if (local_port < 0) { 11088 return BCM_E_PORT; 11089 } 11090 phy_port = si->port_l2p_mapping[local_port]; 11091 mmu_port = si->port_p2m_mapping[phy_port]; 11092 11093 /* Input port per port per priority group settings */ 11094 for (idx = 0; idx < _BCM_TR3_MMU_NUM_PG; idx++) { 11095 midx = (mmu_port * 8) + idx; 11096 mem = THDI_PORT_PG_CONFIGm; 11097 sal_memset(&pg_config_mem, 0, sizeof(pg_config_mem)); 11098 BCM_IF_ERROR_RETURN 11099 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, &pg_config_mem)); 11100 if (soc_mem_field32_get(unit, mem, &pg_config_mem, PG_SHARED_DYNAMICf)) { 11101 alpha = soc_mem_field32_get(unit, mem, &pg_config_mem, 11102 PG_SHARED_LIMITf); 11103 break; 11104 } 11105 } 11106 } 11107 11108 switch(alpha) { 11109 case SOC_TR3_COSQ_DROP_LIMIT_ALPHA_1_64: 11110 *arg = bcmCosqControlDropLimitAlpha_1_64; 11111 break; 11112 case SOC_TR3_COSQ_DROP_LIMIT_ALPHA_1_32: 11113 *arg = bcmCosqControlDropLimitAlpha_1_32; 11114 break; 11115 case SOC_TR3_COSQ_DROP_LIMIT_ALPHA_1_16: 11116 *arg = bcmCosqControlDropLimitAlpha_1_16; 11117 break; 11118 case SOC_TR3_COSQ_DROP_LIMIT_ALPHA_1_8: 11119 *arg = bcmCosqControlDropLimitAlpha_1_8; 11120 break; 11121 case SOC_TR3_COSQ_DROP_LIMIT_ALPHA_1_4: 11122 *arg = bcmCosqControlDropLimitAlpha_1_4; 11123 break; 11124 case SOC_TR3_COSQ_DROP_LIMIT_ALPHA_1_2: 11125 *arg = bcmCosqControlDropLimitAlpha_1_2; 11126 break; 11127 case SOC_TR3_COSQ_DROP_LIMIT_ALPHA_1: 11128 *arg = bcmCosqControlDropLimitAlpha_1; 11129 break; 11130 case SOC_TR3_COSQ_DROP_LIMIT_ALPHA_2: 11131 *arg = bcmCosqControlDropLimitAlpha_2; 11132 break; 11133 case SOC_TR3_COSQ_DROP_LIMIT_ALPHA_4: 11134 *arg = bcmCosqControlDropLimitAlpha_4; 11135 break; 11136 case SOC_TR3_COSQ_DROP_LIMIT_ALPHA_8: 11137 *arg = bcmCosqControlDropLimitAlpha_8; 11138 break; 11139 default: 11140 return BCM_E_NONE; 11141 } 11142 11143 return BCM_E_NONE; 11144 } 11145 11146 STATIC int 11147 _bcm_tr3_cosq_egr_queue_set(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 11148 bcm_cosq_control_t type, int arg) 11149 { 11150 bcm_port_t local_port; 11151 int startq; 11152 uint32 max_val = 0; 11153 uint32 entry[SOC_MAX_MEM_WORDS]; 11154 uint32 entry2[SOC_MAX_MEM_WORDS]; 11155 uint32 rval, rval2; 11156 soc_mem_t mem = INVALIDm; 11157 soc_mem_t mem2 = INVALIDm; 11158 soc_reg_t reg = INVALIDr; 11159 soc_reg_t reg2 = INVALIDr; 11160 soc_field_t fld_limit = INVALIDf; 11161 soc_field_t fld_limit2 = INVALIDf; 11162 int granularity = 1; 11163 int from_cos, to_cos, ci; 11164 int shared_size, cur_val = 0, rv, post_update; 11165 _bcm_tr3_mmu_info_t *mmu_info = _bcm_tr3_mmu_info[unit]; 11166 int delta = 0; /* In Cells */ 11167 int limit; 11168 int spid = 0; 11169 11170 if (arg < 0) { 11171 return BCM_E_PARAM; 11172 } 11173 11174 arg = _BCM_TR3_BYTES_TO_CELLS(arg); 11175 11176 if ((type == bcmCosqControlEgressUCQueueMinLimitBytes) || 11177 (type == bcmCosqControlEgressUCQueueSharedLimitBytes)) { 11178 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 11179 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) { 11180 BCM_IF_ERROR_RETURN 11181 (_bcm_tr3_cosq_index_resolve(unit, gport, cosq, 11182 _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE, 11183 &local_port, &startq, NULL)); 11184 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 11185 return BCM_E_PARAM; 11186 } 11187 else { 11188 if (cosq == BCM_COS_INVALID) { 11189 from_cos = to_cos = 0; 11190 } else { 11191 from_cos = to_cos = cosq; 11192 } 11193 11194 BCM_IF_ERROR_RETURN 11195 (_bcm_tr3_cosq_localport_resolve(unit, gport, &local_port)); 11196 if (local_port < 0) { 11197 return BCM_E_PORT; 11198 } 11199 for (ci = from_cos; ci <= to_cos; ci++) { 11200 BCM_IF_ERROR_RETURN 11201 (_bcm_tr3_cosq_index_resolve 11202 (unit, local_port, ci, _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE, 11203 NULL, &startq, NULL)); 11204 } 11205 } 11206 mem = MMU_THDO_CONFIG_QUEUEm; 11207 mem2 = MMU_THDO_Q_TO_QGRP_MAPm; 11208 } else if ((type == bcmCosqControlEgressMCQueueMinLimitBytes) || 11209 (type == bcmCosqControlEgressMCQueueSharedLimitBytes)) { 11210 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 11211 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) { 11212 return BCM_E_PARAM; 11213 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 11214 BCM_IF_ERROR_RETURN 11215 (_bcm_tr3_cosq_index_resolve(unit, gport, cosq, 11216 _BCM_TR3_COSQ_INDEX_STYLE_EGR_POOL, 11217 &local_port, &startq, NULL)); 11218 } 11219 else { 11220 if (cosq == BCM_COS_INVALID) { 11221 from_cos = to_cos = 0; 11222 } else { 11223 from_cos = to_cos = cosq; 11224 } 11225 11226 BCM_IF_ERROR_RETURN 11227 (_bcm_tr3_cosq_localport_resolve(unit, gport, &local_port)); 11228 if (local_port < 0) { 11229 return BCM_E_PORT; 11230 } 11231 for (ci = from_cos; ci <= to_cos; ci++) { 11232 BCM_IF_ERROR_RETURN 11233 (_bcm_tr3_cosq_index_resolve 11234 (unit, local_port, ci, _BCM_TR3_COSQ_INDEX_STYLE_EGR_POOL, 11235 NULL, &startq, NULL)); 11236 } 11237 /* Here is just crash issue, there are some logical issue need to be fixed later */ 11238 if (cosq == BCM_COS_INVALID) { 11239 startq = 0; 11240 } 11241 else { 11242 startq = cosq; 11243 } 11244 } 11245 reg = OP_QUEUE_CONFIG_CELLr; 11246 reg2 = OP_QUEUE_CONFIG1_CELLr; 11247 } else { 11248 return BCM_E_PARAM; 11249 } 11250 11251 if (mem != INVALIDm) { 11252 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 11253 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem2, MEM_BLOCK_ALL, startq, entry2)); 11254 spid = soc_mem_field32_get(unit, mem2, entry2, Q_SPIDf); 11255 } else if (reg != INVALIDr) { 11256 BCM_IF_ERROR_RETURN(soc_reg32_get(unit, reg, 11257 local_port, startq, &rval)); 11258 BCM_IF_ERROR_RETURN(soc_reg32_get(unit, reg2, 11259 local_port, startq, &rval2)); 11260 spid = soc_reg_field_get(unit, reg2, rval2, Q_SPIDf); 11261 } 11262 11263 switch (type) { 11264 case bcmCosqControlEgressUCQueueSharedLimitBytes: 11265 fld_limit = Q_SHARED_LIMIT_CELLf; 11266 fld_limit2 = Q_LIMIT_ENABLE_CELLf; 11267 break; 11268 case bcmCosqControlEgressMCQueueSharedLimitBytes: 11269 fld_limit = Q_SHARED_LIMIT_CELLf; 11270 break; 11271 case bcmCosqControlEgressUCQueueMinLimitBytes: 11272 fld_limit = Q_MIN_LIMIT_CELLf; 11273 break; 11274 case bcmCosqControlEgressMCQueueMinLimitBytes: 11275 fld_limit = Q_MIN_CELLf; 11276 break; 11277 default: 11278 return BCM_E_UNAVAIL; 11279 } 11280 11281 /* Check for min/max values */ 11282 if (mem != INVALIDm) { 11283 max_val = (1 << soc_mem_field_length(unit, mem, fld_limit)) - 1; 11284 } else if (reg != INVALIDr) { 11285 max_val = (1 << soc_reg_field_length(unit, reg, fld_limit)) - 1; 11286 } 11287 if ((arg < 0) || ((arg/granularity) > max_val)) { 11288 return BCM_E_PARAM; 11289 } 11290 11291 /* Recalculate Shared Values if Min Changed */ 11292 shared_size = mmu_info->curr_shared_limit; 11293 if (mem != INVALIDm) { 11294 cur_val = soc_mem_field32_get(unit, mem, entry, fld_limit); 11295 } else if (reg != INVALIDr) { 11296 cur_val = soc_reg_field_get(unit, reg, rval, fld_limit); 11297 } 11298 11299 if ((arg / granularity) > cur_val) { 11300 /* New Min Val > Cur Min Val 11301 * So reduce the Shared values first and then 11302 * Increase the Min Value for given resource 11303 */ 11304 post_update = 0; 11305 } else if ((arg / granularity) < cur_val) { 11306 /* New Min Val < Cur Min Val 11307 * So reduce the Min values first and then 11308 * Increase Shared values everywhere 11309 */ 11310 post_update = 1; 11311 } else { 11312 return BCM_E_NONE; 11313 } 11314 11315 if (!post_update && 11316 ((type == bcmCosqControlEgressUCQueueMinLimitBytes) || 11317 (type == bcmCosqControlEgressMCQueueMinLimitBytes))) { 11318 delta = ((arg / granularity) - cur_val) * granularity; 11319 if (delta > shared_size) { 11320 return BCM_E_PARAM; 11321 } 11322 rv = soc_tr3_mmu_config_shared_buf_recalc(unit, spid, 11323 delta, 1); 11324 if (rv < 0) { 11325 return rv; 11326 } 11327 11328 mmu_info->curr_shared_limit = shared_size - delta; 11329 11330 /* Reading mem again as recalc would have updated the mem/reg. */ 11331 if (mem != INVALIDm) { 11332 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 11333 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem2, MEM_BLOCK_ALL, startq, entry2)); 11334 } else if (reg != INVALIDr) { 11335 BCM_IF_ERROR_RETURN(soc_reg32_get(unit, reg, 11336 local_port, startq, &rval)); 11337 BCM_IF_ERROR_RETURN(soc_reg32_get(unit, reg2, 11338 local_port, startq, &rval2)); 11339 } 11340 } 11341 11342 11343 switch (type) { 11344 case bcmCosqControlEgressUCQueueSharedLimitBytes: 11345 11346 soc_mem_field32_set(unit, mem, entry, fld_limit, (arg/granularity)); 11347 soc_mem_field32_set(unit, mem, entry, fld_limit2, 1); 11348 11349 /* Set MMU_THDO_Q_TO_QGRP_MAP.DISABLE_QUEUING to 1 when both MIN 11350 * and SHARED LIMIT are 0. Set it to 0 when either MIN or SHARED LIMIT 11351 * is non-zero. 11352 */ 11353 limit = soc_mem_field32_get(unit, mem, entry, Q_MIN_LIMIT_CELLf); 11354 if ((arg == 0) && (limit == 0)) { 11355 soc_mem_field32_set(unit, mem2, entry2, DISABLE_QUEUINGf, 1); 11356 } else if ((arg != 0) || (limit != 0)) { 11357 soc_mem_field32_set(unit, mem2, entry2, DISABLE_QUEUINGf, 0); 11358 } 11359 break; 11360 case bcmCosqControlEgressMCQueueSharedLimitBytes: 11361 11362 soc_reg_field_set(unit, reg, &rval, fld_limit, (arg/granularity)); 11363 soc_reg_field_set(unit, reg2, &rval2, Q_LIMIT_ENABLE_CELLf, 1); 11364 11365 break; 11366 case bcmCosqControlEgressUCQueueMinLimitBytes: 11367 11368 soc_mem_field32_set(unit, mem, entry, fld_limit, (arg/granularity)); 11369 /* Set MMU_THDO_Q_TO_QGRP_MAP.DISABLE_QUEUING to 1 when both MIN 11370 * and SHARED LIMIT are 0. Set it to 0 when either MIN or SHARED LIMIT is non-zero 11371 */ 11372 limit = soc_mem_field32_get(unit, mem, entry, Q_SHARED_LIMIT_CELLf); 11373 if ((arg == 0) && (limit == 0)) { 11374 soc_mem_field32_set(unit, mem2, entry2, DISABLE_QUEUINGf, 1); 11375 } else if ((arg != 0) || (limit != 0)) { 11376 soc_mem_field32_set(unit, mem2, entry2, DISABLE_QUEUINGf, 0); 11377 } 11378 break; 11379 case bcmCosqControlEgressMCQueueMinLimitBytes: 11380 11381 soc_reg_field_set(unit, reg, &rval, fld_limit, (arg/granularity)); 11382 break; 11383 /* 11384 * COVERITY 11385 * 11386 * This default is unreachable but needed for some compiler. 11387 */ 11388 /* coverity[dead_error_begin] */ 11389 default: 11390 return BCM_E_UNAVAIL; 11391 } 11392 11393 11394 if (mem != INVALIDm) { 11395 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 11396 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem2, MEM_BLOCK_ALL, startq, entry2)); 11397 } else if (reg != INVALIDr) { 11398 BCM_IF_ERROR_RETURN(soc_reg32_set(unit, reg, 11399 local_port, startq, rval)); 11400 BCM_IF_ERROR_RETURN(soc_reg32_set(unit, reg2, 11401 local_port, startq, rval2)); 11402 } 11403 11404 if (post_update && 11405 ((type == bcmCosqControlEgressUCQueueMinLimitBytes) || 11406 (type == bcmCosqControlEgressMCQueueMinLimitBytes))) { 11407 int delta = 0; 11408 delta = (cur_val - (arg / granularity)) * granularity; 11409 if (delta > shared_size) { 11410 return BCM_E_PARAM; 11411 } 11412 rv = soc_tr3_mmu_config_shared_buf_recalc(unit, spid, 11413 delta, 0); 11414 if (rv < 0) { 11415 return rv; 11416 } 11417 mmu_info->curr_shared_limit = shared_size + delta; 11418 } 11419 11420 return BCM_E_NONE; 11421 } 11422 11423 STATIC int 11424 _bcm_tr3_cosq_dynamic_thresh_enable_set(int unit, 11425 bcm_gport_t gport, bcm_cos_queue_t cosq, 11426 bcm_cosq_control_t type, int arg) 11427 { 11428 bcm_port_t local_port; 11429 int startq; 11430 int from_cos, to_cos, ci; 11431 uint32 entry[SOC_MAX_MEM_WORDS]; 11432 uint32 rval; 11433 soc_mem_t mem = INVALIDm; 11434 soc_reg_t reg = INVALIDr; 11435 int port_pg; 11436 int phy_port, mmu_port, midx; 11437 static const soc_reg_t prigroup_reg[] = { 11438 PORT_PRI_GRP0r, PORT_PRI_GRP1r 11439 }; 11440 static const soc_field_t prigroup_field[] = { 11441 PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf, 11442 PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf, 11443 PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf, 11444 PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf 11445 }; 11446 soc_info_t *si; 11447 11448 if (type == bcmCosqControlIngressPortPGSharedDynamicEnable) { 11449 BCM_IF_ERROR_RETURN 11450 (_bcm_tr3_cosq_localport_resolve(unit, gport, &local_port)); 11451 if (local_port < 0) { 11452 return BCM_E_PORT; 11453 } 11454 si = &SOC_INFO(unit); 11455 phy_port = si->port_l2p_mapping[local_port]; 11456 mmu_port = si->port_p2m_mapping[phy_port]; 11457 /* get PG for port using Port+Cos */ 11458 if (cosq < 8) { 11459 reg = prigroup_reg[0]; 11460 } else { 11461 reg = prigroup_reg[1]; 11462 } 11463 11464 SOC_IF_ERROR_RETURN 11465 (soc_reg32_get(unit, reg, local_port, 0, &rval)); 11466 port_pg = soc_reg_field_get(unit, reg, rval, prigroup_field[cosq]); 11467 11468 mem = THDI_PORT_PG_CONFIGm; 11469 /* get index for Port-PG */ 11470 midx = (mmu_port * 8) + port_pg; 11471 BCM_IF_ERROR_RETURN 11472 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, entry)); 11473 soc_mem_field32_set(unit, mem, entry, 11474 PG_SHARED_DYNAMICf, arg ? 1 : 0); 11475 SOC_IF_ERROR_RETURN 11476 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, midx, entry)); 11477 11478 if (arg) { 11479 BCM_IF_ERROR_RETURN 11480 (_bcm_tr3_cosq_alpha_set(unit, gport, cosq, bcmCosqControlDropLimitAlpha, 11481 bcmCosqControlDropLimitAlpha_1_64)); 11482 } 11483 } else if (type == bcmCosqControlEgressUCSharedDynamicEnable) { 11484 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 11485 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) { 11486 BCM_IF_ERROR_RETURN 11487 (_bcm_tr3_cosq_index_resolve(unit, gport, cosq, 11488 _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE, 11489 &local_port, &startq, NULL)); 11490 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 11491 return BCM_E_PARAM; 11492 } else { 11493 if (cosq == BCM_COS_INVALID) { 11494 from_cos = to_cos = 0; 11495 } else { 11496 from_cos = to_cos = cosq; 11497 } 11498 11499 BCM_IF_ERROR_RETURN 11500 (_bcm_tr3_cosq_localport_resolve(unit, gport, &local_port)); 11501 if (local_port < 0) { 11502 return BCM_E_PORT; 11503 } 11504 for (ci = from_cos; ci <= to_cos; ci++) { 11505 BCM_IF_ERROR_RETURN 11506 (_bcm_tr3_cosq_index_resolve(unit, local_port, ci, 11507 _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE, 11508 NULL, &startq, NULL)); 11509 11510 } 11511 } 11512 mem = MMU_THDO_CONFIG_QUEUEm; 11513 11514 BCM_IF_ERROR_RETURN 11515 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 11516 soc_mem_field32_set(unit, mem, entry, 11517 Q_LIMIT_DYNAMIC_CELLf, arg ? 1 : 0); 11518 SOC_IF_ERROR_RETURN 11519 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 11520 11521 if (arg) { 11522 BCM_IF_ERROR_RETURN 11523 (_bcm_tr3_cosq_alpha_set(unit, gport, cosq, bcmCosqControlUCDropLimitAlpha, 11524 bcmCosqControlDropLimitAlpha_1_64)); 11525 } 11526 } else if (type == bcmCosqControlEgressMCSharedDynamicEnable) { 11527 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 11528 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) { 11529 return BCM_E_PARAM; 11530 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 11531 BCM_IF_ERROR_RETURN 11532 (_bcm_tr3_cosq_index_resolve(unit, gport, cosq, 11533 _BCM_TR3_COSQ_INDEX_STYLE_EGR_POOL, 11534 &local_port, &startq, NULL)); 11535 } 11536 else { 11537 if (cosq == BCM_COS_INVALID) { 11538 from_cos = to_cos = 0; 11539 } else { 11540 from_cos = to_cos = cosq; 11541 } 11542 11543 BCM_IF_ERROR_RETURN 11544 (_bcm_tr3_cosq_localport_resolve(unit, gport, &local_port)); 11545 if (local_port < 0) { 11546 return BCM_E_PORT; 11547 } 11548 for (ci = from_cos; ci <= to_cos; ci++) { 11549 BCM_IF_ERROR_RETURN 11550 (_bcm_tr3_cosq_index_resolve(unit, local_port, ci, 11551 _BCM_TR3_COSQ_INDEX_STYLE_EGR_POOL, 11552 NULL, &startq, NULL)); 11553 11554 } 11555 } 11556 if (cosq < 0) { 11557 return BCM_E_PARAM; 11558 } 11559 11560 BCM_IF_ERROR_RETURN 11561 (READ_OP_QUEUE_CONFIG1_CELLr(unit, local_port, startq, &rval)); 11562 soc_reg_field_set(unit, OP_QUEUE_CONFIG1_CELLr, &rval, Q_LIMIT_DYNAMIC_CELLf, arg); 11563 WRITE_OP_QUEUE_CONFIG1_CELLr(unit, local_port, startq, rval); 11564 11565 if (arg) { 11566 BCM_IF_ERROR_RETURN 11567 (_bcm_tr3_cosq_alpha_set(unit, gport, cosq, bcmCosqControlMCDropLimitAlpha, 11568 bcmCosqControlDropLimitAlpha_1_64)); 11569 } 11570 } else { 11571 return BCM_E_PARAM; 11572 } 11573 11574 return BCM_E_NONE; 11575 } 11576 11577 STATIC int 11578 _bcm_tr3_cosq_egr_queue_limit_enable_set(int unit, bcm_gport_t gport, 11579 bcm_cos_queue_t cosq, 11580 bcm_cosq_control_t type, 11581 int arg) 11582 { 11583 bcm_port_t local_port; 11584 int startq; 11585 uint32 entry[SOC_MAX_MEM_WORDS]; 11586 uint32 rval; 11587 soc_mem_t mem = INVALIDm; 11588 int enable; 11589 11590 if (arg < 0) { 11591 return BCM_E_PARAM; 11592 } 11593 11594 arg = arg ? 1 : 0; 11595 11596 if (type == bcmCosqControlEgressUCQueueLimitEnable) { 11597 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 11598 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) { 11599 BCM_IF_ERROR_RETURN 11600 (_bcm_tr3_cosq_index_resolve(unit, gport, cosq, 11601 _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE, 11602 &local_port, &startq, NULL)); 11603 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 11604 return BCM_E_PARAM; 11605 } else { 11606 if (cosq < 0) { 11607 return BCM_E_PARAM; 11608 } 11609 BCM_IF_ERROR_RETURN 11610 (_bcm_tr3_cosq_localport_resolve(unit, gport, &local_port)); 11611 if (local_port < 0) { 11612 return BCM_E_PORT; 11613 } 11614 BCM_IF_ERROR_RETURN 11615 (_bcm_tr3_cosq_index_resolve 11616 (unit, local_port, cosq, _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE, 11617 NULL, &startq, NULL)); 11618 } 11619 11620 mem = MMU_THDO_CONFIG_QUEUEm; 11621 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 11622 enable = soc_mem_field32_get(unit, mem, entry, Q_LIMIT_ENABLE_CELLf); 11623 if (enable != arg) { 11624 soc_mem_field32_set(unit, mem, entry, Q_LIMIT_ENABLE_CELLf, arg); 11625 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 11626 } 11627 } else if (type == bcmCosqControlEgressMCQueueLimitEnable) { 11628 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 11629 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) { 11630 return BCM_E_PARAM; 11631 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 11632 BCM_IF_ERROR_RETURN 11633 (_bcm_tr3_cosq_index_resolve(unit, gport, cosq, 11634 _BCM_TR3_COSQ_INDEX_STYLE_MCAST_QUEUE, 11635 &local_port, &startq, NULL)); 11636 } else { 11637 if (cosq < 0) { 11638 return BCM_E_PARAM; 11639 } 11640 BCM_IF_ERROR_RETURN 11641 (_bcm_tr3_cosq_localport_resolve(unit, gport, &local_port)); 11642 if (local_port < 0) { 11643 return BCM_E_PORT; 11644 } 11645 BCM_IF_ERROR_RETURN 11646 (_bcm_tr3_cosq_index_resolve(unit, local_port, cosq, 11647 _BCM_TR3_COSQ_INDEX_STYLE_MCAST_QUEUE, 11648 NULL, &startq, NULL)); 11649 } 11650 if (cosq < 0) { 11651 return BCM_E_PARAM; 11652 } 11653 11654 BCM_IF_ERROR_RETURN 11655 (READ_OP_QUEUE_CONFIG1_CELLr(unit, local_port, cosq, &rval)); 11656 enable = soc_reg_field_get(unit, OP_QUEUE_CONFIG1_CELLr, rval, Q_LIMIT_ENABLE_CELLf); 11657 if (enable != arg) { 11658 soc_reg_field_set(unit, OP_QUEUE_CONFIG1_CELLr, &rval, Q_LIMIT_ENABLE_CELLf, arg); 11659 WRITE_OP_QUEUE_CONFIG1_CELLr(unit, local_port, cosq, rval); 11660 } 11661 } else { 11662 return BCM_E_PARAM; 11663 } 11664 11665 return BCM_E_NONE; 11666 } 11667 11668 STATIC int 11669 _bcm_tr3_cosq_egr_queue_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 11670 bcm_cosq_control_t type, int *arg) 11671 { 11672 bcm_port_t local_port; 11673 int startq; 11674 uint32 entry[SOC_MAX_MEM_WORDS]; 11675 uint32 rval; 11676 soc_mem_t mem = INVALIDm; 11677 soc_reg_t reg = INVALIDr; 11678 soc_field_t fld_limit = INVALIDf; 11679 int granularity = 1; 11680 int from_cos, to_cos, ci; 11681 11682 if (arg == NULL) { 11683 return BCM_E_PARAM; 11684 } 11685 11686 if ((type == bcmCosqControlEgressUCQueueMinLimitBytes) || 11687 (type == bcmCosqControlEgressUCQueueSharedLimitBytes)) { 11688 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 11689 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) { 11690 BCM_IF_ERROR_RETURN 11691 (_bcm_tr3_cosq_index_resolve(unit, gport, cosq, 11692 _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE, 11693 &local_port, &startq, NULL)); 11694 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 11695 return BCM_E_PARAM; 11696 } 11697 else { 11698 if (cosq == BCM_COS_INVALID) { 11699 from_cos = to_cos = 0; 11700 } else { 11701 from_cos = to_cos = cosq; 11702 } 11703 11704 BCM_IF_ERROR_RETURN 11705 (_bcm_tr3_cosq_localport_resolve(unit, gport, &local_port)); 11706 if (local_port < 0) { 11707 return BCM_E_PORT; 11708 } 11709 for (ci = from_cos; ci <= to_cos; ci++) { 11710 BCM_IF_ERROR_RETURN 11711 (_bcm_tr3_cosq_index_resolve 11712 (unit, local_port, ci, _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE, 11713 NULL, &startq, NULL)); 11714 } 11715 } 11716 mem = MMU_THDO_CONFIG_QUEUEm; 11717 } else if ((type == bcmCosqControlEgressMCQueueMinLimitBytes) || 11718 (type == bcmCosqControlEgressMCQueueSharedLimitBytes)) { 11719 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 11720 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) { 11721 return BCM_E_PARAM; 11722 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 11723 BCM_IF_ERROR_RETURN 11724 (_bcm_tr3_cosq_index_resolve(unit, gport, cosq, 11725 _BCM_TR3_COSQ_INDEX_STYLE_EGR_POOL, 11726 &local_port, &startq, NULL)); 11727 } 11728 else { 11729 if (cosq == BCM_COS_INVALID) { 11730 from_cos = to_cos = 0; 11731 } else { 11732 from_cos = to_cos = cosq; 11733 } 11734 11735 BCM_IF_ERROR_RETURN 11736 (_bcm_tr3_cosq_localport_resolve(unit, gport, &local_port)); 11737 if (local_port < 0) { 11738 return BCM_E_PORT; 11739 } 11740 for (ci = from_cos; ci <= to_cos; ci++) { 11741 BCM_IF_ERROR_RETURN 11742 (_bcm_tr3_cosq_index_resolve 11743 (unit, local_port, ci, _BCM_TR3_COSQ_INDEX_STYLE_EGR_POOL, 11744 NULL, &startq, NULL)); 11745 } 11746 } 11747 reg = OP_QUEUE_CONFIG_CELLr; 11748 } else { 11749 return BCM_E_PARAM; 11750 } 11751 11752 switch (type) { 11753 case bcmCosqControlEgressUCQueueMinLimitBytes: 11754 fld_limit = Q_MIN_LIMIT_CELLf; 11755 break; 11756 case bcmCosqControlEgressUCQueueSharedLimitBytes: 11757 fld_limit = Q_SHARED_LIMIT_CELLf; 11758 break; 11759 case bcmCosqControlEgressMCQueueMinLimitBytes: 11760 fld_limit = Q_MIN_CELLf; 11761 break; 11762 case bcmCosqControlEgressMCQueueSharedLimitBytes: 11763 fld_limit = Q_SHARED_LIMIT_CELLf; 11764 break; 11765 default: 11766 return BCM_E_PARAM; 11767 } 11768 11769 if (mem != INVALIDm) { 11770 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 11771 *arg = soc_mem_field32_get(unit, mem, entry, fld_limit); 11772 } else if (reg != INVALIDr) { 11773 BCM_IF_ERROR_RETURN(soc_reg32_get(unit, reg, 11774 local_port, startq, &rval)); 11775 *arg = soc_reg_field_get(unit, reg, rval, fld_limit); 11776 } 11777 *arg = (*arg) * granularity * _BCM_TR3_BYTES_PER_CELL; 11778 return BCM_E_NONE; 11779 } 11780 11781 STATIC int 11782 _bcm_tr3_cosq_dynamic_thresh_enable_get(int unit, 11783 bcm_gport_t gport, bcm_cos_queue_t cosq, 11784 bcm_cosq_control_t type, int *arg) 11785 { 11786 bcm_port_t local_port; 11787 int startq; 11788 int from_cos, to_cos, ci; 11789 uint32 entry[SOC_MAX_MEM_WORDS]; 11790 uint32 rval; 11791 soc_mem_t mem = INVALIDm; 11792 soc_reg_t reg = INVALIDr; 11793 int port_pg; 11794 int phy_port, mmu_port, midx; 11795 static const soc_reg_t prigroup_reg[] = { 11796 PORT_PRI_GRP0r, PORT_PRI_GRP1r 11797 }; 11798 static const soc_field_t prigroup_field[] = { 11799 PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf, 11800 PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf, 11801 PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf, 11802 PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf 11803 }; 11804 soc_info_t *si; 11805 11806 if (arg == NULL) { 11807 return BCM_E_PARAM; 11808 } 11809 11810 if (type == bcmCosqControlIngressPortPGSharedDynamicEnable) { 11811 BCM_IF_ERROR_RETURN 11812 (_bcm_tr3_cosq_localport_resolve(unit, gport, &local_port)); 11813 if (local_port < 0) { 11814 return BCM_E_PORT; 11815 } 11816 si = &SOC_INFO(unit); 11817 phy_port = si->port_l2p_mapping[local_port]; 11818 mmu_port = si->port_p2m_mapping[phy_port]; 11819 /* get PG for port using Port+Cos */ 11820 if (cosq < 8) { 11821 reg = prigroup_reg[0]; 11822 } else { 11823 reg = prigroup_reg[1]; 11824 } 11825 11826 SOC_IF_ERROR_RETURN 11827 (soc_reg32_get(unit, reg, local_port, 0, &rval)); 11828 port_pg = soc_reg_field_get(unit, reg, rval, prigroup_field[cosq]); 11829 11830 mem = THDI_PORT_PG_CONFIGm; 11831 /* get index for Port-PG */ 11832 midx = (mmu_port * 8) + port_pg; 11833 BCM_IF_ERROR_RETURN 11834 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, entry)); 11835 *arg = soc_mem_field32_get(unit, mem, entry, PG_SHARED_DYNAMICf); 11836 11837 } else if (type == bcmCosqControlEgressUCSharedDynamicEnable) { 11838 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 11839 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) { 11840 BCM_IF_ERROR_RETURN 11841 (_bcm_tr3_cosq_index_resolve(unit, gport, cosq, 11842 _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE, 11843 &local_port, &startq, NULL)); 11844 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 11845 return BCM_E_PARAM; 11846 } else { 11847 if (cosq == BCM_COS_INVALID) { 11848 from_cos = to_cos = 0; 11849 } else { 11850 from_cos = to_cos = cosq; 11851 } 11852 11853 BCM_IF_ERROR_RETURN 11854 (_bcm_tr3_cosq_localport_resolve(unit, gport, &local_port)); 11855 if (local_port < 0) { 11856 return BCM_E_PORT; 11857 } 11858 for (ci = from_cos; ci <= to_cos; ci++) { 11859 BCM_IF_ERROR_RETURN 11860 (_bcm_tr3_cosq_index_resolve(unit, local_port, ci, 11861 _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE, 11862 NULL, &startq, NULL)); 11863 11864 } 11865 } 11866 mem = MMU_THDO_CONFIG_QUEUEm; 11867 11868 BCM_IF_ERROR_RETURN 11869 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 11870 *arg = soc_mem_field32_get(unit, mem, entry, Q_LIMIT_DYNAMIC_CELLf); 11871 11872 } else if (type == bcmCosqControlEgressMCSharedDynamicEnable) { 11873 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 11874 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) { 11875 return BCM_E_PARAM; 11876 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 11877 BCM_IF_ERROR_RETURN 11878 (_bcm_tr3_cosq_index_resolve(unit, gport, cosq, 11879 _BCM_TR3_COSQ_INDEX_STYLE_EGR_POOL, 11880 &local_port, &startq, NULL)); 11881 } 11882 else { 11883 if (cosq == BCM_COS_INVALID) { 11884 from_cos = to_cos = 0; 11885 } else { 11886 from_cos = to_cos = cosq; 11887 } 11888 11889 BCM_IF_ERROR_RETURN 11890 (_bcm_tr3_cosq_localport_resolve(unit, gport, &local_port)); 11891 if (local_port < 0) { 11892 return BCM_E_PORT; 11893 } 11894 for (ci = from_cos; ci <= to_cos; ci++) { 11895 BCM_IF_ERROR_RETURN 11896 (_bcm_tr3_cosq_index_resolve(unit, local_port, ci, 11897 _BCM_TR3_COSQ_INDEX_STYLE_EGR_POOL, 11898 NULL, &startq, NULL)); 11899 11900 } 11901 } 11902 if (cosq < 0) { 11903 return BCM_E_PARAM; 11904 } 11905 11906 BCM_IF_ERROR_RETURN 11907 (READ_OP_QUEUE_CONFIG1_CELLr(unit, local_port, startq, &rval)); 11908 *arg = soc_reg_field_get(unit, OP_QUEUE_CONFIG1_CELLr, rval, Q_LIMIT_DYNAMIC_CELLf); 11909 11910 } else { 11911 return BCM_E_PARAM; 11912 } 11913 11914 return BCM_E_NONE; 11915 } 11916 11917 /* 11918 * Function: 11919 * _bcm_tr3_cosq_qgroup_limit_enable_set 11920 * Purpose: 11921 * Enable/Disable COS queue Queue group 11922 * Parameters: 11923 * unit - (IN) unit number 11924 * gport - (IN) GPORT identifier 11925 * cosq - (IN) COS queue to configure 11926 * type - (IN) Operation type 11927 * enable - (IN) Enable/Disable 11928 * Returns: 11929 * BCM_E_XXX 11930 */ 11931 STATIC int 11932 _bcm_tr3_cosq_qgroup_limit_enable_set(int unit, bcm_gport_t gport, 11933 bcm_cos_queue_t cosq, bcm_cosq_control_t type, int enable) 11934 { 11935 bcm_port_t local_port; 11936 soc_mem_t mem = INVALIDm; 11937 uint32 entry[SOC_MAX_MEM_WORDS]; 11938 int startq; 11939 int qgroup_valid; 11940 11941 if (!((enable == 0) || (enable == 1))) { 11942 return BCM_E_PARAM; 11943 } 11944 11945 if (type == bcmCosqControlEgressUCQueueGroupMinEnable) { 11946 11947 /* Resolve cosq for port or take from input argument */ 11948 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 11949 BCM_IF_ERROR_RETURN 11950 (_bcm_tr3_cosq_index_resolve(unit, gport, cosq, 11951 _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE, 11952 &local_port, &startq, NULL)); 11953 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 11954 /* Operation not valid for the multicast queue */ 11955 return BCM_E_PARAM; 11956 } else { 11957 if (cosq < -1) { 11958 return BCM_E_PARAM; 11959 } 11960 BCM_IF_ERROR_RETURN 11961 (_bcm_tr3_cosq_localport_resolve(unit, gport, &local_port)); 11962 if (local_port < 0) { 11963 return BCM_E_PORT; 11964 } 11965 11966 BCM_IF_ERROR_RETURN 11967 (_bcm_tr3_cosq_index_resolve(unit, local_port, cosq, 11968 _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE, 11969 NULL, &startq, NULL)); 11970 } /* if BCM_GPORT_IS_UCAST_QUEUE_GROUP */ 11971 11972 /* Update Table */ 11973 mem = MMU_THDO_Q_TO_QGRP_MAPm; 11974 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, 11975 startq, entry)); 11976 qgroup_valid = soc_mem_field32_get(unit, mem, entry, QGROUP_VALIDf); 11977 if (enable != qgroup_valid) { 11978 soc_mem_field32_set(unit, mem, entry, USE_QGROUP_MINf, enable); 11979 soc_mem_field32_set(unit, mem, entry, QGROUP_VALIDf, enable); 11980 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, 11981 startq, entry)); 11982 } 11983 } else { 11984 return BCM_E_PARAM; 11985 } /* If type */ 11986 11987 return BCM_E_NONE; 11988 } 11989 11990 /* 11991 * Function: 11992 * _bcm_tr3_cosq_qgroup_limit_enable_get 11993 * Purpose: 11994 * Enable/Disable COS queue Queue group 11995 * Parameters: 11996 * unit - (IN) unit number 11997 * gport - (IN) GPORT identifier 11998 * cosq - (IN) COS queue to configure 11999 * type - (IN) Operation type 12000 * enable - (OUT) Enable/Disable status 12001 * Returns: 12002 * BCM_E_XXX 12003 */ 12004 STATIC int 12005 _bcm_tr3_cosq_qgroup_limit_enable_get(int unit, bcm_gport_t gport, 12006 bcm_cos_queue_t cosq, bcm_cosq_control_t type, int *enable) 12007 { 12008 bcm_port_t local_port; 12009 soc_mem_t mem = INVALIDm; 12010 uint32 entry[SOC_MAX_MEM_WORDS]; 12011 int startq; 12012 12013 if (type == bcmCosqControlEgressUCQueueGroupMinEnable) { 12014 12015 /* Resolve cosq for port or take from input argument */ 12016 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 12017 BCM_IF_ERROR_RETURN 12018 (_bcm_tr3_cosq_index_resolve(unit, gport, cosq, 12019 _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE, 12020 &local_port, &startq, NULL)); 12021 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 12022 /* Operation not valid for the multicast queue */ 12023 return BCM_E_PARAM; 12024 } else { 12025 if (cosq < -1) { 12026 return BCM_E_PARAM; 12027 } 12028 BCM_IF_ERROR_RETURN 12029 (_bcm_tr3_cosq_localport_resolve(unit, gport, &local_port)); 12030 if (local_port < 0) { 12031 return BCM_E_PORT; 12032 } 12033 12034 BCM_IF_ERROR_RETURN 12035 (_bcm_tr3_cosq_index_resolve(unit, local_port, cosq, 12036 _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE, 12037 NULL, &startq, NULL)); 12038 } /* if BCM_GPORT_IS_UCAST_QUEUE_GROUP */ 12039 12040 /* Retireve data from the table */ 12041 mem = MMU_THDO_Q_TO_QGRP_MAPm; 12042 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, 12043 startq, entry)); 12044 *enable = soc_mem_field32_get(unit, mem, entry, USE_QGROUP_MINf); 12045 } else { 12046 return BCM_E_PARAM; 12047 } /* If type */ 12048 12049 return BCM_E_NONE; 12050 } 12051 12052 STATIC int 12053 _bcm_tr3_cosq_egr_queue_limit_enable_get(int unit, bcm_gport_t gport, 12054 bcm_cos_queue_t cosq, 12055 bcm_cosq_control_t type, 12056 int *arg) 12057 { 12058 bcm_port_t local_port; 12059 int startq; 12060 uint32 entry[SOC_MAX_MEM_WORDS]; 12061 uint32 rval; 12062 soc_mem_t mem = INVALIDm; 12063 12064 if (arg == NULL) { 12065 return BCM_E_PARAM; 12066 } 12067 12068 if (type == bcmCosqControlEgressUCQueueLimitEnable) { 12069 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 12070 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) { 12071 BCM_IF_ERROR_RETURN 12072 (_bcm_tr3_cosq_index_resolve(unit, gport, cosq, 12073 _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE, 12074 &local_port, &startq, NULL)); 12075 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 12076 return BCM_E_PARAM; 12077 } else { 12078 if (cosq < 0) { 12079 return BCM_E_PARAM; 12080 } 12081 BCM_IF_ERROR_RETURN 12082 (_bcm_tr3_cosq_localport_resolve(unit, gport, &local_port)); 12083 if (local_port < 0) { 12084 return BCM_E_PORT; 12085 } 12086 BCM_IF_ERROR_RETURN 12087 (_bcm_tr3_cosq_index_resolve 12088 (unit, local_port, cosq, _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE, 12089 NULL, &startq, NULL)); 12090 } 12091 12092 mem = MMU_THDO_CONFIG_QUEUEm; 12093 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 12094 *arg = soc_mem_field32_get(unit, mem, entry, Q_LIMIT_ENABLE_CELLf); 12095 } else if (type == bcmCosqControlEgressMCQueueLimitEnable) { 12096 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 12097 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) { 12098 return BCM_E_PARAM; 12099 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 12100 BCM_IF_ERROR_RETURN 12101 (_bcm_tr3_cosq_index_resolve(unit, gport, cosq, 12102 _BCM_TR3_COSQ_INDEX_STYLE_MCAST_QUEUE, 12103 &local_port, &startq, NULL)); 12104 } else { 12105 if (cosq < 0) { 12106 return BCM_E_PARAM; 12107 } 12108 BCM_IF_ERROR_RETURN 12109 (_bcm_tr3_cosq_localport_resolve(unit, gport, &local_port)); 12110 if (local_port < 0) { 12111 return BCM_E_PORT; 12112 } 12113 BCM_IF_ERROR_RETURN 12114 (_bcm_tr3_cosq_index_resolve(unit, local_port, cosq, 12115 _BCM_TR3_COSQ_INDEX_STYLE_MCAST_QUEUE, 12116 NULL, &startq, NULL)); 12117 } 12118 if (cosq < 0) { 12119 return BCM_E_PARAM; 12120 } 12121 12122 BCM_IF_ERROR_RETURN 12123 (READ_OP_QUEUE_CONFIG1_CELLr(unit, local_port, cosq, &rval)); 12124 *arg = soc_reg_field_get(unit, OP_QUEUE_CONFIG1_CELLr, rval, Q_LIMIT_ENABLE_CELLf); 12125 } else { 12126 return BCM_E_PARAM; 12127 } 12128 12129 return BCM_E_NONE; 12130 } 12131 12132 12133 STATIC int 12134 _bcm_tr3_cosq_ing_pool_set(int unit, bcm_gport_t gport, bcm_cos_queue_t pri_grp, 12135 bcm_cosq_control_t type, int arg) 12136 { 12137 int local_port; 12138 uint32 rval; 12139 static const soc_field_t prigroup_spid_field[] = { 12140 PG0_SPIDf, PG1_SPIDf, PG2_SPIDf, PG3_SPIDf, 12141 PG4_SPIDf, PG5_SPIDf, PG6_SPIDf, PG7_SPIDf 12142 }; 12143 if(( arg < 0 ) || (arg > 3 )) { 12144 return BCM_E_PARAM; 12145 } 12146 12147 BCM_IF_ERROR_RETURN 12148 (_bcm_tr3_cosq_localport_resolve(unit, gport, &local_port)); 12149 12150 if (!SOC_PORT_VALID(unit, local_port)) { 12151 return BCM_E_PORT; 12152 } 12153 /* coverity fix : pri_grp can take value from 0 to 7 */ 12154 if ((pri_grp < 0) || (pri_grp >= 8)) { 12155 return BCM_E_PARAM; 12156 } 12157 12158 SOC_IF_ERROR_RETURN(READ_PORT_PG_SPIDr(unit, local_port, &rval)); 12159 soc_reg_field_set(unit, PORT_PG_SPIDr, &rval, 12160 prigroup_spid_field[pri_grp],arg); 12161 BCM_IF_ERROR_RETURN(WRITE_PORT_PG_SPIDr(unit, local_port, rval)); 12162 return BCM_E_NONE; 12163 } 12164 12165 STATIC int 12166 _bcm_tr3_cosq_ing_pool_get(int unit, bcm_gport_t gport, 12167 bcm_cos_queue_t pri_grp, 12168 bcm_cosq_control_t type, int *arg) 12169 { 12170 int pool_start_idx = 0, pool_end_idx =0; 12171 BCM_IF_ERROR_RETURN( 12172 _bcm_tr3_cosq_ingress_sp_get( 12173 unit, gport, pri_grp, &pool_start_idx, &pool_end_idx)); 12174 *arg = pool_start_idx; 12175 return BCM_E_NONE; 12176 } 12177 12178 12179 STATIC int 12180 _bcm_tr3_cosq_ing_res_set(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 12181 bcm_cosq_control_t type, int arg) 12182 { 12183 bcm_port_t local_port; 12184 int phy_port, mmu_port, midx; 12185 uint32 max_val, rval; 12186 uint32 entry[SOC_MAX_MEM_WORDS]; 12187 soc_mem_t mem = INVALIDm; 12188 soc_field_t fld_limit = INVALIDf; 12189 soc_reg_t reg = INVALIDr; 12190 int port_pg, port_pg_pool, granularity = 1; 12191 static const soc_reg_t prigroup_reg[] = { 12192 PORT_PRI_GRP0r, PORT_PRI_GRP1r 12193 }; 12194 static const soc_field_t prigroup_field[] = { 12195 PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf, 12196 PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf, 12197 PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf, 12198 PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf 12199 }; 12200 static const soc_field_t prigroup_spid_field[] = { 12201 PG0_SPIDf, PG1_SPIDf, PG2_SPIDf, PG3_SPIDf, 12202 PG4_SPIDf, PG5_SPIDf, PG6_SPIDf, PG7_SPIDf 12203 }; 12204 soc_info_t *si; 12205 12206 if (cosq > 15 || cosq < 0) { 12207 /* Error. Input pri > Max Pri_Grp */ 12208 return BCM_E_PARAM; 12209 } 12210 12211 if (arg < 0) { 12212 return BCM_E_PARAM; 12213 } 12214 12215 arg = _BCM_TR3_BYTES_TO_CELLS(arg); 12216 BCM_IF_ERROR_RETURN 12217 (_bcm_tr3_cosq_localport_resolve(unit, gport, &local_port)); 12218 if (local_port < 0) { 12219 return BCM_E_PORT; 12220 } 12221 12222 /* get PG for port using Port+Cos */ 12223 if (cosq < 8) { 12224 reg = prigroup_reg[0]; 12225 } else { 12226 reg = prigroup_reg[1]; 12227 } 12228 12229 SOC_IF_ERROR_RETURN 12230 (soc_reg32_get(unit, reg, local_port, 0, &rval)); 12231 port_pg = soc_reg_field_get(unit, reg, rval, prigroup_field[cosq]); 12232 12233 si = &SOC_INFO(unit); 12234 phy_port = si->port_l2p_mapping[local_port]; 12235 mmu_port = si->port_p2m_mapping[phy_port]; 12236 12237 if ((type == bcmCosqControlIngressPortPGSharedLimitBytes) || 12238 (type == bcmCosqControlIngressPortPGMinLimitBytes)|| 12239 (type == bcmCosqControlIngressPortPGHeadroomLimitBytes)|| 12240 (type == bcmCosqControlIngressPortPGResetFloorBytes)) { 12241 mem = THDI_PORT_PG_CONFIGm; 12242 /* get index for Port-PG */ 12243 midx = (mmu_port * 8) + port_pg; 12244 12245 } else if ((type == bcmCosqControlIngressPortPoolMaxLimitBytes) || 12246 (type == bcmCosqControlIngressPortPoolMinLimitBytes)) { 12247 reg = PORT_PG_SPIDr; 12248 12249 SOC_IF_ERROR_RETURN 12250 (soc_reg32_get(unit, reg, local_port, 0, &rval)); 12251 port_pg_pool = soc_reg_field_get(unit, reg, rval, prigroup_spid_field[port_pg]); 12252 12253 mem = THDI_PORT_SP_CONFIGm; 12254 /* get index for Port-SP */ 12255 midx = (mmu_port * 4) + port_pg_pool;; 12256 } else { 12257 return BCM_E_UNAVAIL; 12258 } 12259 12260 if (midx < 0) { 12261 return BCM_E_PARAM; 12262 } 12263 12264 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, entry)); 12265 12266 switch (type) { 12267 case bcmCosqControlIngressPortPGSharedLimitBytes: 12268 fld_limit = PG_SHARED_LIMITf; 12269 granularity = 1; 12270 break; 12271 case bcmCosqControlIngressPortPoolMaxLimitBytes: 12272 fld_limit = PORT_SP_MAX_LIMITf; 12273 granularity = 1; 12274 break; 12275 case bcmCosqControlIngressPortPGMinLimitBytes: 12276 fld_limit = PG_MIN_LIMITf; 12277 granularity = 1; 12278 break; 12279 case bcmCosqControlIngressPortPoolMinLimitBytes: 12280 fld_limit = PORT_SP_MIN_LIMITf; 12281 granularity = 1; 12282 break; 12283 case bcmCosqControlIngressPortPGHeadroomLimitBytes: 12284 fld_limit = PG_HDRM_LIMITf; 12285 granularity = 1; 12286 break; 12287 case bcmCosqControlIngressPortPGResetFloorBytes: 12288 fld_limit = PG_RESET_FLOORf; 12289 granularity = 1; 12290 break; 12291 /* coverity[dead_error_begin] */ 12292 default: 12293 return BCM_E_UNAVAIL; 12294 } 12295 12296 /* Check for min/max values */ 12297 max_val = (1 << soc_mem_field_length(unit, mem, fld_limit)) - 1; 12298 if ((arg < 0) || ((arg/granularity) > max_val)) { 12299 return BCM_E_PARAM; 12300 } else { 12301 soc_mem_field32_set(unit, mem, entry, fld_limit, (arg/granularity)); 12302 } 12303 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, midx, entry)); 12304 12305 return BCM_E_NONE; 12306 } 12307 12308 STATIC int 12309 _bcm_tr3_cosq_ing_res_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 12310 bcm_cosq_control_t type, int *arg) 12311 { 12312 bcm_port_t local_port; 12313 int phy_port, mmu_port, midx; 12314 uint32 rval; 12315 uint32 entry[SOC_MAX_MEM_WORDS]; 12316 soc_mem_t mem = INVALIDm; 12317 soc_field_t fld_limit = INVALIDf; 12318 soc_reg_t reg = INVALIDr; 12319 int port_pg, port_pg_pool, granularity = 1; 12320 static const soc_reg_t prigroup_reg[] = { 12321 PORT_PRI_GRP0r, PORT_PRI_GRP1r 12322 }; 12323 static const soc_field_t prigroup_field[] = { 12324 PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf, 12325 PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf, 12326 PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf, 12327 PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf 12328 }; 12329 static const soc_field_t prigroup_spid_field[] = { 12330 PG0_SPIDf, PG1_SPIDf, PG2_SPIDf, PG3_SPIDf, 12331 PG4_SPIDf, PG5_SPIDf, PG6_SPIDf, PG7_SPIDf 12332 }; 12333 soc_info_t *si; 12334 12335 if (cosq > 15 || cosq < 0) { 12336 /* Error. Input pri > Max Pri_Grp */ 12337 return BCM_E_PARAM; 12338 } 12339 12340 if (!arg) { 12341 return BCM_E_PARAM; 12342 } 12343 12344 BCM_IF_ERROR_RETURN 12345 (_bcm_tr3_cosq_localport_resolve(unit, gport, &local_port)); 12346 if (local_port < 0) { 12347 return BCM_E_PORT; 12348 } 12349 12350 /* get PG for port using Port+Cos */ 12351 if (cosq < 8) { 12352 reg = prigroup_reg[0]; 12353 } else { 12354 reg = prigroup_reg[1]; 12355 } 12356 12357 SOC_IF_ERROR_RETURN 12358 (soc_reg32_get(unit, reg, local_port, 0, &rval)); 12359 port_pg = soc_reg_field_get(unit, reg, rval, prigroup_field[cosq]); 12360 12361 si = &SOC_INFO(unit); 12362 phy_port = si->port_l2p_mapping[local_port]; 12363 mmu_port = si->port_p2m_mapping[phy_port]; 12364 12365 if ((type == bcmCosqControlIngressPortPGSharedLimitBytes) || 12366 (type == bcmCosqControlIngressPortPGMinLimitBytes)|| 12367 (type == bcmCosqControlIngressPortPGHeadroomLimitBytes)|| 12368 (type == bcmCosqControlIngressPortPGResetFloorBytes)) { 12369 mem = THDI_PORT_PG_CONFIGm; 12370 /* get index for Port-PG */ 12371 midx = (mmu_port * 8) + port_pg; 12372 12373 } else if ((type == bcmCosqControlIngressPortPoolMaxLimitBytes) || 12374 (type == bcmCosqControlIngressPortPoolMinLimitBytes)) { 12375 reg = PORT_PG_SPIDr; 12376 12377 SOC_IF_ERROR_RETURN 12378 (soc_reg32_get(unit, reg, local_port, 0, &rval)); 12379 port_pg_pool = soc_reg_field_get(unit, reg, rval, prigroup_spid_field[port_pg]); 12380 12381 mem = THDI_PORT_SP_CONFIGm; 12382 /* get index for Port-SP */ 12383 midx = (mmu_port * 4) + port_pg_pool;; 12384 } else { 12385 return BCM_E_UNAVAIL; 12386 } 12387 12388 if (midx < 0) { 12389 return BCM_E_PARAM; 12390 } 12391 12392 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, entry)); 12393 12394 switch (type) { 12395 case bcmCosqControlIngressPortPGSharedLimitBytes: 12396 fld_limit = PG_SHARED_LIMITf; 12397 granularity = 1; 12398 break; 12399 case bcmCosqControlIngressPortPoolMaxLimitBytes: 12400 fld_limit = PORT_SP_MAX_LIMITf; 12401 granularity = 1; 12402 break; 12403 case bcmCosqControlIngressPortPGMinLimitBytes: 12404 fld_limit = PG_MIN_LIMITf; 12405 granularity = 1; 12406 break; 12407 case bcmCosqControlIngressPortPoolMinLimitBytes: 12408 fld_limit = PORT_SP_MIN_LIMITf; 12409 granularity = 1; 12410 break; 12411 case bcmCosqControlIngressPortPGHeadroomLimitBytes: 12412 fld_limit = PG_HDRM_LIMITf; 12413 granularity = 1; 12414 break; 12415 case bcmCosqControlIngressPortPGResetFloorBytes: 12416 fld_limit = PG_RESET_FLOORf; 12417 granularity = 1; 12418 break; 12419 /* coverity[dead_error_begin] */ 12420 default: 12421 return BCM_E_UNAVAIL; 12422 } 12423 12424 *arg = soc_mem_field32_get(unit, mem, entry, fld_limit); 12425 *arg = (*arg) * granularity * _BCM_TR3_BYTES_PER_CELL; 12426 12427 return BCM_E_NONE; 12428 } 12429 12430 /* 12431 * This function is used to get ingress pool 12432 * limit given Ingress [Port, Priority] 12433 */ 12434 STATIC int 12435 _bcm_tr3_cosq_ing_res_limit_get(int unit, bcm_gport_t gport, bcm_cos_t cosq, 12436 bcm_cosq_control_t type, int *arg) 12437 { 12438 bcm_port_t local_port; 12439 uint32 rval; 12440 soc_reg_t reg = INVALIDr; 12441 int port_pg, port_pg_pool; 12442 static const soc_reg_t prigroup_reg[] = { 12443 PORT_PRI_GRP0r, PORT_PRI_GRP1r 12444 }; 12445 static const soc_field_t prigroup_field[] = { 12446 PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf, 12447 PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf, 12448 PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf, 12449 PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf 12450 }; 12451 static const soc_field_t prigroup_spid_field[] = { 12452 PG0_SPIDf, PG1_SPIDf, PG2_SPIDf, PG3_SPIDf, 12453 PG4_SPIDf, PG5_SPIDf, PG6_SPIDf, PG7_SPIDf 12454 }; 12455 12456 if (cosq > 15 || cosq < 0) { 12457 /* Error. Input pri > Max Pri_Grp */ 12458 return BCM_E_PARAM; 12459 } 12460 if (!arg) { 12461 return BCM_E_PARAM; 12462 } 12463 12464 BCM_IF_ERROR_RETURN 12465 (_bcm_tr3_cosq_localport_resolve(unit, gport, &local_port)); 12466 if (local_port < 0) { 12467 return BCM_E_PORT; 12468 } 12469 12470 /* get PG for port using Port+Cos */ 12471 if (cosq < 8) { 12472 reg = prigroup_reg[0]; 12473 } else { 12474 reg = prigroup_reg[1]; 12475 } 12476 12477 SOC_IF_ERROR_RETURN 12478 (soc_reg32_get(unit, reg, local_port, 0, &rval)); 12479 port_pg = soc_reg_field_get(unit, reg, rval, prigroup_field[cosq]); 12480 12481 12482 if (type == bcmCosqControlIngressPoolLimitBytes) { 12483 reg = PORT_PG_SPIDr; 12484 12485 SOC_IF_ERROR_RETURN 12486 (soc_reg32_get(unit, reg, local_port, 0, &rval)); 12487 port_pg_pool = soc_reg_field_get(unit, reg, rval, prigroup_spid_field[port_pg]); 12488 12489 SOC_IF_ERROR_RETURN 12490 (READ_BUFFER_CELL_LIMIT_SPr(unit, port_pg_pool, &rval)); 12491 *arg = soc_reg_field_get(unit, BUFFER_CELL_LIMIT_SPr, rval, LIMITf); 12492 } else { 12493 return BCM_E_PARAM; 12494 } 12495 12496 *arg = (*arg) * _BCM_TR3_BYTES_PER_CELL; 12497 12498 return BCM_E_NONE; 12499 } 12500 12501 /* 12502 * This function is used to set ingress pool 12503 * limit given Ingress [Port, Priority] 12504 */ 12505 STATIC int 12506 _bcm_tr3_cosq_ing_res_limit_set(int unit, bcm_gport_t gport, bcm_cos_t cosq, 12507 bcm_cosq_control_t type, int arg) 12508 { 12509 bcm_port_t local_port; 12510 uint32 max_val, rval; 12511 soc_reg_t reg = INVALIDr; 12512 int port_pg, port_pg_pool; 12513 static const soc_reg_t prigroup_reg[] = { 12514 PORT_PRI_GRP0r, PORT_PRI_GRP1r 12515 }; 12516 static const soc_field_t prigroup_field[] = { 12517 PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf, 12518 PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf, 12519 PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf, 12520 PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf 12521 }; 12522 static const soc_field_t prigroup_spid_field[] = { 12523 PG0_SPIDf, PG1_SPIDf, PG2_SPIDf, PG3_SPIDf, 12524 PG4_SPIDf, PG5_SPIDf, PG6_SPIDf, PG7_SPIDf 12525 }; 12526 12527 if (cosq > 15 || cosq < 0) { 12528 /* Error. Input pri > Max Pri_Grp */ 12529 return BCM_E_PARAM; 12530 } 12531 12532 if (arg < 0) { 12533 return BCM_E_PARAM; 12534 } 12535 12536 arg = _BCM_TR3_BYTES_TO_CELLS(arg); 12537 BCM_IF_ERROR_RETURN 12538 (_bcm_tr3_cosq_localport_resolve(unit, gport, &local_port)); 12539 if (local_port < 0) { 12540 return BCM_E_PORT; 12541 } 12542 12543 /* get PG for port using Port+Cos */ 12544 if (cosq < 8) { 12545 reg = prigroup_reg[0]; 12546 } else { 12547 reg = prigroup_reg[1]; 12548 } 12549 12550 SOC_IF_ERROR_RETURN 12551 (soc_reg32_get(unit, reg, local_port, 0, &rval)); 12552 port_pg = soc_reg_field_get(unit, reg, rval, prigroup_field[cosq]); 12553 12554 if (type == bcmCosqControlIngressPoolLimitBytes) { 12555 reg = PORT_PG_SPIDr; 12556 12557 SOC_IF_ERROR_RETURN 12558 (soc_reg32_get(unit, reg, local_port, 0, &rval)); 12559 port_pg_pool = soc_reg_field_get(unit, reg, rval, prigroup_spid_field[port_pg]); 12560 12561 rval = 0; 12562 SOC_IF_ERROR_RETURN(READ_BUFFER_CELL_LIMIT_SPr(unit, port_pg_pool, &rval)); 12563 /* Check for min/max values */ 12564 max_val = (1 << soc_reg_field_length(unit, BUFFER_CELL_LIMIT_SPr, LIMITf)) - 1; 12565 if ((arg < 0) || (arg > max_val)) { 12566 return BCM_E_PARAM; 12567 } else { 12568 soc_reg_field_set(unit, BUFFER_CELL_LIMIT_SPr, &rval, LIMITf, arg); 12569 } 12570 12571 SOC_IF_ERROR_RETURN(WRITE_BUFFER_CELL_LIMIT_SPr(unit, port_pg_pool, rval)); 12572 } else { 12573 return BCM_E_PARAM; 12574 } 12575 12576 return BCM_E_NONE; 12577 } 12578 12579 12580 STATIC int 12581 _bcm_tr3_cosq_egr_pool_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 12582 bcm_cosq_control_t type, int *arg) 12583 { 12584 bcm_port_t local_port; 12585 int startq, pool; 12586 uint32 rval; 12587 uint32 entry[SOC_MAX_MEM_WORDS]; 12588 12589 if (!arg) { 12590 return BCM_E_PARAM; 12591 } 12592 12593 if (type == bcmCosqControlUCEgressPool) { 12594 BCM_IF_ERROR_RETURN 12595 (_bcm_tr3_cosq_index_resolve(unit, gport, cosq, 12596 _BCM_TR3_COSQ_INDEX_STYLE_UC_EGR_POOL, 12597 &local_port, &startq, NULL)); 12598 } else { 12599 BCM_IF_ERROR_RETURN 12600 (_bcm_tr3_cosq_index_resolve(unit, gport, cosq, 12601 _BCM_TR3_COSQ_INDEX_STYLE_EGR_POOL, 12602 &local_port, &startq, NULL)); 12603 } 12604 12605 if (type == bcmCosqControlEgressPoolLimitEnable) { 12606 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 12607 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) { 12608 BCM_IF_ERROR_RETURN(soc_reg32_get(unit, OP_PORT_CONFIG1_CELLr, 12609 local_port, 0, &rval)); 12610 *arg = soc_reg_field_get(unit, OP_PORT_CONFIG1_CELLr, rval, 12611 PORT_LIMIT_ENABLE_CELLf); 12612 } else { 12613 BCM_IF_ERROR_RETURN(soc_reg32_get(unit, OP_QUEUE_CONFIG1_CELLr, 12614 local_port, startq, &rval)); 12615 *arg = soc_reg_field_get(unit, OP_QUEUE_CONFIG1_CELLr, 12616 rval, Q_LIMIT_ENABLE_CELLf); 12617 } 12618 return BCM_E_NONE; 12619 } 12620 12621 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 12622 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) { 12623 BCM_IF_ERROR_RETURN( 12624 soc_mem_read(unit, MMU_THDO_Q_TO_QGRP_MAPm, MEM_BLOCK_ALL, 12625 startq, entry)); 12626 pool = soc_mem_field32_get(unit, MMU_THDO_Q_TO_QGRP_MAPm, entry, Q_SPIDf); 12627 } else { 12628 BCM_IF_ERROR_RETURN( 12629 soc_reg32_get(unit, OP_QUEUE_CONFIG1_CELLr, local_port, startq, &rval)); 12630 pool = soc_reg_field_get(unit, OP_QUEUE_CONFIG1_CELLr, rval, Q_SPIDf); 12631 } 12632 12633 /* per service pool settings */ 12634 if (type == bcmCosqControlEgressPoolSharedLimitBytes || 12635 type == bcmCosqControlEgressPoolResumeLimitBytes || 12636 type == bcmCosqControlEgressPoolYellowSharedLimitBytes || 12637 type == bcmCosqControlEgressPoolYellowResumeLimitBytes || 12638 type == bcmCosqControlEgressPoolRedSharedLimitBytes || 12639 type == bcmCosqControlEgressPoolRedResumeLimitBytes) { 12640 soc_reg_t reg; 12641 soc_field_t fld_limit = INVALIDf; 12642 int granularity = 1; 12643 12644 switch (type) { 12645 case bcmCosqControlEgressPoolSharedLimitBytes: 12646 reg = OP_BUFFER_SHARED_LIMIT_CELLr; 12647 fld_limit = OP_BUFFER_SHARED_LIMIT_CELLf; 12648 granularity = 1; 12649 break; 12650 case bcmCosqControlEgressPoolResumeLimitBytes: 12651 reg = OP_BUFFER_SHARED_LIMIT_RESUME_CELLr; 12652 fld_limit = OP_BUFFER_SHARED_LIMIT_RESUME_CELLf; 12653 granularity = 1; 12654 break; 12655 case bcmCosqControlEgressPoolYellowSharedLimitBytes: 12656 reg = OP_BUFFER_LIMIT_YELLOW_CELLr; 12657 fld_limit = OP_BUFFER_LIMIT_YELLOW_CELLf; 12658 granularity = 8; 12659 break; 12660 case bcmCosqControlEgressPoolYellowResumeLimitBytes: 12661 reg = OP_BUFFER_LIMIT_RESUME_YELLOW_CELLr; 12662 fld_limit = OP_BUFFER_LIMIT_RESUME_YELLOW_CELLf; 12663 granularity = 8; 12664 break; 12665 case bcmCosqControlEgressPoolRedSharedLimitBytes: 12666 reg = OP_BUFFER_LIMIT_RED_CELLr; 12667 fld_limit = OP_BUFFER_LIMIT_RED_CELLf; 12668 granularity = 8; 12669 break; 12670 case bcmCosqControlEgressPoolRedResumeLimitBytes: 12671 reg = OP_BUFFER_LIMIT_RESUME_RED_CELLr; 12672 fld_limit = OP_BUFFER_LIMIT_RESUME_RED_CELLf; 12673 granularity = 8; 12674 break; 12675 /* 12676 * COVERITY 12677 * 12678 * This default is unreachable but needed for some compiler. 12679 */ 12680 /* coverity[dead_error_begin] */ 12681 default: 12682 return BCM_E_UNAVAIL; 12683 } 12684 12685 BCM_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, pool, &rval)); 12686 12687 *arg = soc_reg_field_get(unit, reg, rval, fld_limit); 12688 *arg = (*arg) * granularity * _BCM_TR3_BYTES_PER_CELL; 12689 12690 return BCM_E_NONE; 12691 } 12692 12693 switch (type) { 12694 case bcmCosqControlEgressPool: 12695 *arg = pool; 12696 break; 12697 case bcmCosqControlMCEgressPool: 12698 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 12699 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport) || 12700 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 12701 return BCM_E_PARAM; 12702 } 12703 *arg = pool; 12704 break; 12705 12706 case bcmCosqControlUCEgressPool: 12707 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 12708 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport) || 12709 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 12710 return BCM_E_PARAM; 12711 } 12712 startq = SOC_INFO(unit).port_uc_cosq_base[local_port] + startq; 12713 BCM_IF_ERROR_RETURN( 12714 soc_mem_read(unit, MMU_THDO_Q_TO_QGRP_MAPm, MEM_BLOCK_ALL, 12715 startq, entry)); 12716 pool = soc_mem_field32_get(unit, MMU_THDO_Q_TO_QGRP_MAPm, entry, Q_SPIDf); 12717 *arg = pool; 12718 break; 12719 12720 case bcmCosqControlEgressPoolLimitBytes: 12721 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 12722 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) { 12723 BCM_IF_ERROR_RETURN( 12724 soc_mem_read(unit, MMU_THDO_CONFIG_QUEUEm, MEM_BLOCK_ALL, 12725 startq, entry)); 12726 *arg = soc_mem_field32_get(unit, MMU_THDO_CONFIG_QUEUEm, entry, 12727 Q_SHARED_LIMIT_CELLf); 12728 } else { 12729 BCM_IF_ERROR_RETURN( 12730 soc_reg32_get(unit, OP_QUEUE_CONFIG_CELLr, local_port, startq, &rval)); 12731 *arg = soc_reg_field_get(unit, OP_QUEUE_CONFIG_CELLr, rval, 12732 Q_SHARED_LIMIT_CELLf) * 8; 12733 } 12734 break; 12735 case bcmCosqControlEgressPoolYellowLimitBytes: 12736 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 12737 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) { 12738 BCM_IF_ERROR_RETURN( 12739 soc_mem_read(unit, MMU_THDO_CONFIG_QUEUEm, MEM_BLOCK_ALL, 12740 startq, entry)); 12741 *arg = soc_mem_field32_get(unit, MMU_THDO_CONFIG_QUEUEm, 12742 entry, LIMIT_YELLOW_CELLf) * 8; 12743 } else { 12744 return BCM_E_UNAVAIL; 12745 } 12746 break; 12747 case bcmCosqControlEgressPoolRedLimitBytes: 12748 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 12749 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) { 12750 BCM_IF_ERROR_RETURN( 12751 soc_mem_read(unit, MMU_THDO_CONFIG_QUEUEm, MEM_BLOCK_ALL, 12752 startq, entry)); 12753 *arg = soc_mem_field32_get(unit, MMU_THDO_CONFIG_QUEUEm, 12754 entry, LIMIT_RED_CELLf) * 8; 12755 } else { 12756 BCM_IF_ERROR_RETURN( 12757 soc_reg32_get(unit, OP_QUEUE_LIMIT_COLOR_CELLr, 12758 local_port, startq, &rval)); 12759 *arg = soc_reg_field_get(unit, OP_QUEUE_LIMIT_COLOR_CELLr, rval, REDf)*8; 12760 } 12761 break; 12762 default: 12763 return BCM_E_UNAVAIL; 12764 } 12765 return BCM_E_NONE; 12766 } 12767 12768 STATIC int 12769 _bcm_tr3_cosq_ef_op_at_index(int unit, int hw_index, _bcm_cosq_op_t op, 12770 int *ef_val) 12771 { 12772 lls_l2_parent_entry_t entry; 12773 12774 SOC_IF_ERROR_RETURN 12775 (soc_mem_read(unit, LLS_L2_PARENTm, MEM_BLOCK_ALL, hw_index, &entry)); 12776 12777 if (op == _BCM_COSQ_OP_GET) { 12778 *ef_val = soc_mem_field32_get(unit, LLS_L2_PARENTm, &entry, C_EFf); 12779 } else { 12780 soc_mem_field32_set(unit, LLS_L2_PARENTm, &entry, C_EFf, *ef_val); 12781 SOC_IF_ERROR_RETURN 12782 (soc_mem_write(unit, LLS_L2_PARENTm, MEM_BLOCK_ALL, 12783 hw_index, &entry)); 12784 } 12785 12786 return BCM_E_NONE; 12787 } 12788 12789 STATIC int 12790 _bcm_tr3_cosq_ef_op(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, int *arg, 12791 _bcm_cosq_op_t op) 12792 { 12793 _bcm_tr3_cosq_node_t *node; 12794 bcm_port_t local_port; 12795 int index, numq, from_cos, to_cos, ci; 12796 12797 if (BCM_GPORT_IS_SCHEDULER(gport)) { 12798 BCM_IF_ERROR_RETURN 12799 (_bcm_tr3_cosq_node_get(unit, gport, 0, NULL, 12800 &local_port, NULL, &node)); 12801 BCM_IF_ERROR_RETURN( 12802 _bcm_tr3_cosq_child_node_at_input(node, cosq, &node)); 12803 gport = node->gport; 12804 cosq = 0; 12805 } 12806 12807 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 12808 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) { 12809 BCM_IF_ERROR_RETURN 12810 (_bcm_tr3_cosq_index_resolve 12811 (unit, gport, cosq, _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE, 12812 &local_port, &index, NULL)); 12813 return _bcm_tr3_cosq_ef_op_at_index(unit, index, op, arg); 12814 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 12815 BCM_IF_ERROR_RETURN 12816 (_bcm_tr3_cosq_index_resolve 12817 (unit, gport, cosq, _BCM_TR3_COSQ_INDEX_STYLE_MCAST_QUEUE, 12818 &local_port, &index, NULL)); 12819 return _bcm_tr3_cosq_ef_op_at_index(unit, index, op, arg); 12820 } else if (BCM_GPORT_IS_SCHEDULER(gport)) { 12821 return BCM_E_PARAM; 12822 } else { 12823 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_port_has_ets(unit, local_port)); 12824 if (cosq == BCM_COS_INVALID) { 12825 from_cos = 0; 12826 to_cos = _TR3_NUM_COS(unit) - 1; 12827 } else { 12828 from_cos = to_cos = cosq; 12829 } 12830 for (ci = from_cos; ci <= to_cos; ci++) { 12831 BCM_IF_ERROR_RETURN 12832 (_bcm_tr3_cosq_index_resolve 12833 (unit, gport, ci, _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE, 12834 &local_port, &index, &numq)); 12835 12836 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_ef_op_at_index(unit, 12837 index, op, arg)); 12838 if (op == _BCM_COSQ_OP_GET) { 12839 return BCM_E_NONE; 12840 } 12841 12842 BCM_IF_ERROR_RETURN 12843 (_bcm_tr3_cosq_index_resolve 12844 (unit, gport, ci, _BCM_TR3_COSQ_INDEX_STYLE_MCAST_QUEUE, 12845 &local_port, &index, &numq)); 12846 12847 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_ef_op_at_index(unit, 12848 index, op, arg)); 12849 } 12850 } 12851 return BCM_E_NONE; 12852 } 12853 12854 STATIC int 12855 _bcm_tr3_cosq_port_qnum_get(int unit, bcm_gport_t gport, 12856 bcm_cos_queue_t cosq, bcm_cosq_control_t type, int *arg) 12857 { 12858 bcm_port_t local_port; 12859 if (!arg) { 12860 return BCM_E_PARAM; 12861 } 12862 12863 if (!BCM_COSQ_QUEUE_VALID(unit, cosq)) { 12864 return BCM_E_PARAM; 12865 } 12866 12867 BCM_IF_ERROR_RETURN 12868 (_bcm_tr3_cosq_localport_resolve(unit, gport, &local_port)); 12869 if (local_port < 0) { 12870 return BCM_E_PORT; 12871 } 12872 12873 if (type == bcmCosqControlPortQueueUcast) { 12874 *arg = SOC_INFO(unit).port_uc_cosq_base[local_port] + cosq; 12875 } else { 12876 *arg = SOC_INFO(unit).port_cosq_base[local_port] + cosq; 12877 } 12878 12879 return BCM_E_NONE; 12880 } 12881 12882 STATIC int 12883 _bcm_tr3_cosq_qcn_proxy_set(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 12884 bcm_cosq_control_t type, int arg) 12885 { 12886 int local_port; 12887 uint32 rval; 12888 12889 BCM_IF_ERROR_RETURN 12890 (_bcm_tr3_cosq_localport_resolve(unit, gport, &local_port)); 12891 12892 BCM_IF_ERROR_RETURN(READ_QCN_CNM_PRP_CTRLr(unit, local_port, &rval)); 12893 soc_reg_field_set(unit, QCN_CNM_PRP_CTRLr, &rval, ENABLEf, !!arg); 12894 soc_reg_field_set(unit, QCN_CNM_PRP_CTRLr, &rval, PRIORITY_BMAPf, 0xff); 12895 BCM_IF_ERROR_RETURN(WRITE_QCN_CNM_PRP_CTRLr(unit, local_port, rval)); 12896 return BCM_E_NONE; 12897 } 12898 12899 int 12900 bcm_tr3_cosq_control_set(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 12901 bcm_cosq_control_t type, int arg) 12902 { 12903 switch (type) { 12904 case bcmCosqControlEgressPool: 12905 case bcmCosqControlEgressPoolLimitBytes: 12906 case bcmCosqControlEgressPoolYellowLimitBytes: 12907 case bcmCosqControlEgressPoolRedLimitBytes: 12908 case bcmCosqControlEgressPoolLimitEnable: 12909 case bcmCosqControlUCEgressPool: 12910 case bcmCosqControlMCEgressPool: 12911 case bcmCosqControlEgressPoolSharedLimitBytes: 12912 case bcmCosqControlEgressPoolResumeLimitBytes: 12913 case bcmCosqControlEgressPoolYellowSharedLimitBytes: 12914 case bcmCosqControlEgressPoolYellowResumeLimitBytes: 12915 case bcmCosqControlEgressPoolRedSharedLimitBytes: 12916 case bcmCosqControlEgressPoolRedResumeLimitBytes: 12917 return _bcm_tr3_cosq_egr_pool_set(unit, gport, cosq, type, arg); 12918 case bcmCosqControlEgressUCQueueSharedLimitBytes: 12919 case bcmCosqControlEgressMCQueueSharedLimitBytes: 12920 case bcmCosqControlEgressUCQueueMinLimitBytes: 12921 case bcmCosqControlEgressMCQueueMinLimitBytes: 12922 return _bcm_tr3_cosq_egr_queue_set(unit, gport, cosq, type, arg); 12923 case bcmCosqControlIngressPortPGSharedLimitBytes: 12924 case bcmCosqControlIngressPortPGMinLimitBytes: 12925 case bcmCosqControlIngressPortPoolMaxLimitBytes: 12926 case bcmCosqControlIngressPortPoolMinLimitBytes: 12927 case bcmCosqControlIngressPortPGHeadroomLimitBytes: 12928 case bcmCosqControlIngressPortPGResetFloorBytes: 12929 return _bcm_tr3_cosq_ing_res_set(unit, gport, cosq, type, arg); 12930 case bcmCosqControlIngressPoolLimitBytes: 12931 return _bcm_tr3_cosq_ing_res_limit_set(unit, gport, cosq, type, arg); 12932 case bcmCosqControlIngressPool: 12933 return _bcm_tr3_cosq_ing_pool_set(unit, gport, cosq, type, arg); 12934 case bcmCosqControlIngressPortPGSharedDynamicEnable: 12935 case bcmCosqControlEgressUCSharedDynamicEnable: 12936 case bcmCosqControlEgressMCSharedDynamicEnable: 12937 return _bcm_tr3_cosq_dynamic_thresh_enable_set(unit, gport, cosq, 12938 type, arg); 12939 case bcmCosqControlEgressUCQueueLimitEnable: 12940 case bcmCosqControlEgressMCQueueLimitEnable: 12941 return _bcm_tr3_cosq_egr_queue_limit_enable_set(unit, gport, cosq, type, arg); 12942 case bcmCosqControlDropLimitAlpha: 12943 case bcmCosqControlUCDropLimitAlpha: 12944 case bcmCosqControlMCDropLimitAlpha: 12945 return _bcm_tr3_cosq_alpha_set(unit, gport, cosq, type, 12946 (bcm_cosq_control_drop_limit_alpha_value_t)arg); 12947 case bcmCosqControlEfPropagation: 12948 return _bcm_tr3_cosq_ef_op(unit, gport, cosq, &arg, _BCM_COSQ_OP_SET); 12949 case bcmCosqControlCongestionProxy: 12950 return _bcm_tr3_cosq_qcn_proxy_set(unit, gport, cosq, type, arg); 12951 case bcmCosqControlEgressUCQueueGroupMinEnable: 12952 return _bcm_tr3_cosq_qgroup_limit_enable_set(unit, gport, cosq, type, arg); 12953 default: 12954 break; 12955 } 12956 12957 return BCM_E_UNAVAIL; 12958 } 12959 12960 int 12961 bcm_tr3_cosq_control_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 12962 bcm_cosq_control_t type, int *arg) 12963 { 12964 switch (type) { 12965 case bcmCosqControlEgressPool: 12966 case bcmCosqControlEgressPoolLimitBytes: 12967 case bcmCosqControlEgressPoolYellowLimitBytes: 12968 case bcmCosqControlEgressPoolRedLimitBytes: 12969 case bcmCosqControlEgressPoolLimitEnable: 12970 case bcmCosqControlUCEgressPool: 12971 case bcmCosqControlMCEgressPool: 12972 case bcmCosqControlEgressPoolSharedLimitBytes: 12973 case bcmCosqControlEgressPoolResumeLimitBytes: 12974 case bcmCosqControlEgressPoolYellowSharedLimitBytes: 12975 case bcmCosqControlEgressPoolYellowResumeLimitBytes: 12976 case bcmCosqControlEgressPoolRedSharedLimitBytes: 12977 case bcmCosqControlEgressPoolRedResumeLimitBytes: 12978 return _bcm_tr3_cosq_egr_pool_get(unit, gport, cosq, type, arg); 12979 case bcmCosqControlEgressUCQueueSharedLimitBytes: 12980 case bcmCosqControlEgressMCQueueSharedLimitBytes: 12981 case bcmCosqControlEgressUCQueueMinLimitBytes: 12982 case bcmCosqControlEgressMCQueueMinLimitBytes: 12983 return _bcm_tr3_cosq_egr_queue_get(unit, gport, cosq, type, arg); 12984 case bcmCosqControlIngressPortPGSharedLimitBytes: 12985 case bcmCosqControlIngressPortPGMinLimitBytes: 12986 case bcmCosqControlIngressPortPoolMaxLimitBytes: 12987 case bcmCosqControlIngressPortPoolMinLimitBytes: 12988 case bcmCosqControlIngressPortPGHeadroomLimitBytes: 12989 case bcmCosqControlIngressPortPGResetFloorBytes: 12990 return _bcm_tr3_cosq_ing_res_get(unit, gport, cosq, type, arg); 12991 case bcmCosqControlIngressPoolLimitBytes: 12992 return _bcm_tr3_cosq_ing_res_limit_get(unit, gport, cosq, type, arg); 12993 case bcmCosqControlIngressPool: 12994 return _bcm_tr3_cosq_ing_pool_get(unit, gport, cosq, type, arg); 12995 case bcmCosqControlIngressPortPGSharedDynamicEnable: 12996 case bcmCosqControlEgressUCSharedDynamicEnable: 12997 case bcmCosqControlEgressMCSharedDynamicEnable: 12998 return _bcm_tr3_cosq_dynamic_thresh_enable_get(unit, gport, cosq, 12999 type, arg); 13000 case bcmCosqControlEgressUCQueueLimitEnable: 13001 case bcmCosqControlEgressMCQueueLimitEnable: 13002 return _bcm_tr3_cosq_egr_queue_limit_enable_get(unit, gport, cosq, type, arg); 13003 case bcmCosqControlDropLimitAlpha: 13004 case bcmCosqControlUCDropLimitAlpha: 13005 case bcmCosqControlMCDropLimitAlpha: 13006 return _bcm_tr3_cosq_alpha_get(unit, gport, cosq, type, 13007 (bcm_cosq_control_drop_limit_alpha_value_t *)arg); 13008 case bcmCosqControlEfPropagation: 13009 return _bcm_tr3_cosq_ef_op(unit, gport, cosq, arg, _BCM_COSQ_OP_GET); 13010 case bcmCosqControlPortQueueUcast: 13011 case bcmCosqControlPortQueueMcast: 13012 return _bcm_tr3_cosq_port_qnum_get(unit, gport, cosq, type, arg); 13013 case bcmCosqControlEgressUCQueueGroupMinEnable: 13014 return _bcm_tr3_cosq_qgroup_limit_enable_get(unit, gport, cosq, type, arg); 13015 default: 13016 break; 13017 } 13018 13019 return BCM_E_UNAVAIL; 13020 } 13021 13022 /* 13023 * Function: 13024 * bcm_tr3_cosq_gport_bandwidth_set 13025 * Purpose: 13026 * Configure COS queue bandwidth control 13027 * Parameters: 13028 * unit - (IN) unit number 13029 * gport - (IN) GPORT identifier 13030 * cosq - (IN) COS queue to configure, -1 for all COS queues 13031 * kbits_sec_min - (IN) minimum bandwidth, kbits/sec 13032 * kbits_sec_max - (IN) maximum bandwidth, kbits/sec 13033 * flags - (IN) BCM_COSQ_BW_* 13034 * Returns: 13035 * BCM_E_XXX 13036 */ 13037 int 13038 bcm_tr3_cosq_gport_bandwidth_set(int unit, bcm_gport_t gport, 13039 bcm_cos_queue_t cosq, uint32 kbits_sec_min, 13040 uint32 kbits_sec_max, uint32 flags) 13041 { 13042 int i, start_cos, end_cos, local_port; 13043 _bcm_tr3_cosq_node_t *node; 13044 uint32 burst_min, burst_max; 13045 13046 if (cosq <= -1) { 13047 if (BCM_GPORT_IS_SET(gport)) { 13048 BCM_IF_ERROR_RETURN 13049 (_bcm_tr3_cosq_node_get(unit, gport, 0, NULL, 13050 NULL, NULL, &node)); 13051 start_cos = 0; 13052 end_cos = node->numq - 1; 13053 } else { 13054 start_cos = 0; 13055 end_cos = _TR3_NUM_COS(unit) - 1; 13056 } 13057 } else { 13058 start_cos = end_cos = cosq; 13059 } 13060 13061 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_localport_resolve(unit, gport, &local_port)); 13062 13063 burst_min = (kbits_sec_min > 0) ? 13064 _bcm_td_default_burst_size(unit, local_port, kbits_sec_min) : 0; 13065 13066 burst_max = (kbits_sec_max > 0) ? 13067 _bcm_td_default_burst_size(unit, local_port, kbits_sec_max) : 0; 13068 13069 for (i = start_cos; i <= end_cos; i++) { 13070 BCM_IF_ERROR_RETURN 13071 (_bcm_tr3_cosq_bucket_set(unit, gport, i, kbits_sec_min, 13072 kbits_sec_max, burst_min, burst_max, flags)); 13073 } 13074 13075 return BCM_E_NONE; 13076 } 13077 13078 /* 13079 * Function: 13080 * bcm_tr3_cosq_gport_bandwidth_get 13081 * Purpose: 13082 * Get COS queue bandwidth control configuration 13083 * Parameters: 13084 * unit - (IN) unit number 13085 * gport - (IN) GPORT identifier 13086 * cosq - (IN) COS queue to get, -1 for any COS queue 13087 * kbits_sec_min - (OUT) minimum bandwidth, kbits/sec 13088 * kbits_sec_max - (OUT) maximum bandwidth, kbits/sec 13089 * flags - (OUT) BCM_COSQ_BW_* 13090 * Returns: 13091 * BCM_E_XXX 13092 */ 13093 int 13094 bcm_tr3_cosq_gport_bandwidth_get(int unit, bcm_gport_t gport, 13095 bcm_cos_queue_t cosq, uint32 *kbits_sec_min, 13096 uint32 *kbits_sec_max, uint32 *flags) 13097 { 13098 uint32 kbits_sec_burst; 13099 13100 if (cosq == -1) { 13101 return BCM_E_PARAM; 13102 } 13103 13104 BCM_IF_ERROR_RETURN 13105 (_bcm_tr3_cosq_bucket_get(unit, gport, cosq, 13106 kbits_sec_min, kbits_sec_max, 13107 &kbits_sec_burst, &kbits_sec_burst, flags)); 13108 return BCM_E_NONE; 13109 } 13110 13111 /* 13112 * Function: 13113 * bcm_tr3_cosq_gport_bandwidth_burst_set 13114 * Purpose: 13115 * Configure COS queue bandwidth burst setting 13116 * Parameters: 13117 * unit - (IN) unit number 13118 * gport - (IN) GPORT identifier 13119 * cosq - (IN) COS queue to configure, -1 for all COS queues 13120 * kbits_burst - (IN) maximum burst, kbits 13121 * Returns: 13122 * BCM_E_XXX 13123 */ 13124 int 13125 bcm_tr3_cosq_gport_bandwidth_burst_set(int unit, bcm_gport_t gport, 13126 bcm_cos_queue_t cosq, 13127 uint32 kbits_burst_min, 13128 uint32 kbits_burst_max) 13129 { 13130 int i, start_cos, end_cos; 13131 uint32 kbits_sec_min, kbits_sec_max, kbits_sec_burst, flags; 13132 _bcm_tr3_cosq_node_t *node; 13133 13134 if (cosq < -1) { 13135 return BCM_E_PARAM; 13136 } 13137 13138 if (cosq == -1) { 13139 if (BCM_GPORT_IS_SET(gport)) { 13140 BCM_IF_ERROR_RETURN 13141 (_bcm_tr3_cosq_node_get(unit, gport, 0, NULL, 13142 NULL, NULL, &node)); 13143 start_cos = 0; 13144 end_cos = node->numq - 1; 13145 } else { 13146 start_cos = 0; 13147 end_cos = _TR3_NUM_COS(unit) - 1; 13148 } 13149 } else { 13150 start_cos = end_cos = cosq; 13151 } 13152 13153 for (i = start_cos; i <= end_cos; i++) { 13154 BCM_IF_ERROR_RETURN 13155 (_bcm_tr3_cosq_bucket_get(unit, gport, i, &kbits_sec_min, 13156 &kbits_sec_max, &kbits_sec_burst, 13157 &kbits_sec_burst, &flags)); 13158 BCM_IF_ERROR_RETURN 13159 (_bcm_tr3_cosq_bucket_set(unit, gport, i, kbits_sec_min, 13160 kbits_sec_max, kbits_burst_min, 13161 kbits_burst_max, flags)); 13162 } 13163 13164 return BCM_E_NONE; 13165 } 13166 13167 /* 13168 * Function: 13169 * bcm_tr3_cosq_gport_bandwidth_burst_get 13170 * Purpose: 13171 * Get COS queue bandwidth burst setting 13172 * Parameters: 13173 * unit - (IN) unit number 13174 * gport - (IN) GPORT identifier 13175 * cosq - (IN) COS queue to get, -1 for any queue 13176 * kbits_burst - (OUT) maximum burst, kbits 13177 * Returns: 13178 * BCM_E_XXX 13179 */ 13180 int 13181 bcm_tr3_cosq_gport_bandwidth_burst_get(int unit, bcm_gport_t gport, 13182 bcm_cos_queue_t cosq, 13183 uint32 *kbits_burst_min, 13184 uint32 *kbits_burst_max) 13185 { 13186 uint32 kbits_sec_min, kbits_sec_max, flags; 13187 13188 if (cosq < -1) { 13189 return BCM_E_PARAM; 13190 } 13191 13192 BCM_IF_ERROR_RETURN 13193 (_bcm_tr3_cosq_bucket_get(unit, gport, cosq == -1 ? 0 : cosq, 13194 &kbits_sec_min, &kbits_sec_max, kbits_burst_min, 13195 kbits_burst_max, &flags)); 13196 return BCM_E_NONE; 13197 } 13198 13199 /* 13200 * Function: 13201 * bcm_tr3_cosq_gport_sched_set 13202 * Purpose: 13203 * Configure COS queue scheduler setting 13204 * Parameters: 13205 * unit - (IN) unit number 13206 * gport - (IN) GPORT identifier 13207 * cosq - (IN) COS queue to configure, -1 for all COS queues 13208 * mode - (IN) Scheduling mode, one of BCM_COSQ_xxx 13209 * weight - (IN) queue weight 13210 * Returns: 13211 * BCM_E_XXX 13212 */ 13213 int 13214 bcm_tr3_cosq_gport_sched_set(int unit, bcm_gport_t gport, 13215 bcm_cos_queue_t cosq, int mode, int weight) 13216 { 13217 int rv, numq, i, count; 13218 13219 if (cosq == -1) { 13220 BCM_IF_ERROR_RETURN 13221 (_bcm_tr3_cosq_index_resolve(unit, gport, cosq, 13222 _BCM_TR3_COSQ_INDEX_STYLE_SCHEDULER, 13223 NULL, NULL, &numq)); 13224 cosq = 0; 13225 } else { 13226 numq = 1; 13227 } 13228 13229 count = 0; 13230 for (i = 0; i < numq; i++) { 13231 rv = _bcm_tr3_cosq_sched_set(unit, gport, cosq + i, mode, weight, 1); 13232 if (rv == BCM_E_NOT_FOUND) { 13233 continue; 13234 } else if (BCM_FAILURE(rv)) { 13235 return rv; 13236 } else { 13237 count++; 13238 } 13239 } 13240 13241 return count > 0 ? BCM_E_NONE : BCM_E_NOT_FOUND; 13242 } 13243 13244 /* 13245 * Function: 13246 * bcm_tr3_cosq_gport_sched_get 13247 * Purpose: 13248 * Get COS queue scheduler setting 13249 * Parameters: 13250 * unit - (IN) unit number 13251 * gport - (IN) GPORT identifier 13252 * cosq - (IN) COS queue to get, -1 for any queue 13253 * mode - (OUT) Scheduling mode, one of BCM_COSQ_xxx 13254 * weight - (OUT) queue weight 13255 * Returns: 13256 * BCM_E_XXX 13257 */ 13258 int 13259 bcm_tr3_cosq_gport_sched_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 13260 int *mode, int *weight) 13261 { 13262 int rv, numq, i; 13263 13264 if (cosq == -1) { 13265 BCM_IF_ERROR_RETURN 13266 (_bcm_tr3_cosq_index_resolve(unit, gport, 0, 13267 _BCM_TR3_COSQ_INDEX_STYLE_SCHEDULER, 13268 NULL, NULL, &numq)); 13269 cosq = 0; 13270 } else { 13271 numq = 1; 13272 } 13273 13274 for (i = 0; i < numq; i++) { 13275 rv = _bcm_tr3_cosq_sched_get(unit, gport, cosq + i, mode, weight); 13276 if (rv == BCM_E_NONE) { 13277 continue; 13278 } else { 13279 return rv; 13280 } 13281 } 13282 13283 return BCM_E_NONE; 13284 } 13285 13286 /* 13287 * Function: 13288 * bcm_tr3_cosq_gport_discard_set 13289 * Purpose: 13290 * Configure port WRED setting 13291 * Parameters: 13292 * unit - (IN) unit number 13293 * port - (IN) GPORT identifier 13294 * cosq - (IN) COS queue to configure, -1 for all COS queues 13295 * discard - (IN) discard settings 13296 * Returns: 13297 * BCM_E_XXX 13298 */ 13299 int 13300 bcm_tr3_cosq_gport_discard_set(int unit, bcm_gport_t gport, 13301 bcm_cos_queue_t cosq, 13302 bcm_cosq_gport_discard_t *discard) 13303 { 13304 int numq, i; 13305 uint32 min_thresh, max_thresh; 13306 int cell_size, cell_field_max, flags = 0; 13307 13308 if (discard == NULL || 13309 discard->gain < 0 || discard->gain > 15 || 13310 discard->drop_probability < 0 || discard->drop_probability > 100) { 13311 return BCM_E_PARAM; 13312 } 13313 13314 cell_size = _BCM_TR3_BYTES_PER_CELL; 13315 cell_field_max = TR3_CELL_FIELD_MAX; 13316 13317 min_thresh = discard->min_thresh; 13318 max_thresh = discard->max_thresh; 13319 if (discard->flags & BCM_COSQ_DISCARD_BYTES) { 13320 /* Convert bytes to cells */ 13321 min_thresh += (cell_size - 1); 13322 min_thresh /= cell_size; 13323 13324 max_thresh += (cell_size - 1); 13325 max_thresh /= cell_size; 13326 13327 if ((min_thresh > cell_field_max) || 13328 (max_thresh > cell_field_max)) { 13329 return BCM_E_PARAM; 13330 } 13331 } else { 13332 /* Packet mode not supported */ 13333 return BCM_E_PARAM; 13334 } 13335 13336 if (cosq == -1) { 13337 if (gport == -1) { 13338 numq= 1; 13339 } else { 13340 numq= _TR3_NUM_COS(unit); 13341 } 13342 cosq = 0; 13343 flags = BCM_COSQ_DISCARD_PORT; 13344 } 13345 else { 13346 numq = 1; 13347 } 13348 13349 for (i = 0; i < numq; i++) { 13350 BCM_IF_ERROR_RETURN 13351 (_bcm_tr3_cosq_wred_set(unit, gport, cosq + i, discard->flags, 13352 min_thresh, max_thresh, 13353 discard->drop_probability, discard->gain, 13354 FALSE, flags)); 13355 } 13356 13357 return BCM_E_NONE; 13358 } 13359 13360 /* 13361 * Function: 13362 * bcm_tr3_cosq_gport_discard_get 13363 * Purpose: 13364 * Get port WRED setting 13365 * Parameters: 13366 * unit - (IN) unit number 13367 * port - (IN) GPORT identifier 13368 * cosq - (IN) COS queue to get, -1 for any queue 13369 * discard - (OUT) discard settings 13370 * Returns: 13371 * BCM_E_XXX 13372 */ 13373 int 13374 bcm_tr3_cosq_gport_discard_get(int unit, bcm_gport_t gport, 13375 bcm_cos_queue_t cosq, 13376 bcm_cosq_gport_discard_t *discard) 13377 { 13378 uint32 min_thresh, max_thresh; 13379 13380 if (discard == NULL) { 13381 return BCM_E_PARAM; 13382 } 13383 13384 BCM_IF_ERROR_RETURN 13385 (_bcm_tr3_cosq_wred_get(unit, gport, cosq == -1 ? 0 : cosq, 13386 &discard->flags, &min_thresh, &max_thresh, 13387 &discard->drop_probability, &discard->gain, 0)); 13388 13389 /* Convert number of cells to number of bytes */ 13390 discard->min_thresh = min_thresh * _BCM_TR3_BYTES_PER_CELL; 13391 discard->max_thresh = max_thresh * _BCM_TR3_BYTES_PER_CELL; 13392 13393 return BCM_E_NONE; 13394 } 13395 13396 int 13397 _bcm_tr3_cosq_pfc_class_resolve(bcm_switch_control_t sctype, int *type, 13398 int *class) 13399 { 13400 switch (sctype) { 13401 case bcmSwitchPFCClass7Queue: 13402 case bcmSwitchPFCClass6Queue: 13403 case bcmSwitchPFCClass5Queue: 13404 case bcmSwitchPFCClass4Queue: 13405 case bcmSwitchPFCClass3Queue: 13406 case bcmSwitchPFCClass2Queue: 13407 case bcmSwitchPFCClass1Queue: 13408 case bcmSwitchPFCClass0Queue: 13409 *type = _BCM_TR3_COSQ_TYPE_UCAST; 13410 break; 13411 case bcmSwitchPFCClass7McastQueue: 13412 case bcmSwitchPFCClass6McastQueue: 13413 case bcmSwitchPFCClass5McastQueue: 13414 case bcmSwitchPFCClass4McastQueue: 13415 case bcmSwitchPFCClass3McastQueue: 13416 case bcmSwitchPFCClass2McastQueue: 13417 case bcmSwitchPFCClass1McastQueue: 13418 case bcmSwitchPFCClass0McastQueue: 13419 *type = _BCM_TR3_COSQ_TYPE_MCAST; 13420 break; 13421 case bcmSwitchPFCClass7DestmodQueue: 13422 case bcmSwitchPFCClass6DestmodQueue: 13423 case bcmSwitchPFCClass5DestmodQueue: 13424 case bcmSwitchPFCClass4DestmodQueue: 13425 case bcmSwitchPFCClass3DestmodQueue: 13426 case bcmSwitchPFCClass2DestmodQueue: 13427 case bcmSwitchPFCClass1DestmodQueue: 13428 case bcmSwitchPFCClass0DestmodQueue: 13429 *type = _BCM_TR3_COSQ_TYPE_EXT_UCAST; 13430 break; 13431 default: 13432 return BCM_E_PARAM; 13433 } 13434 13435 switch (sctype) { 13436 case bcmSwitchPFCClass7Queue: 13437 case bcmSwitchPFCClass7McastQueue: 13438 case bcmSwitchPFCClass7DestmodQueue: 13439 *class = 7; 13440 break; 13441 case bcmSwitchPFCClass6Queue: 13442 case bcmSwitchPFCClass6McastQueue: 13443 case bcmSwitchPFCClass6DestmodQueue: 13444 *class = 6; 13445 break; 13446 case bcmSwitchPFCClass5Queue: 13447 case bcmSwitchPFCClass5McastQueue: 13448 case bcmSwitchPFCClass5DestmodQueue: 13449 *class = 5; 13450 break; 13451 case bcmSwitchPFCClass4Queue: 13452 case bcmSwitchPFCClass4McastQueue: 13453 case bcmSwitchPFCClass4DestmodQueue: 13454 *class = 4; 13455 break; 13456 case bcmSwitchPFCClass3Queue: 13457 case bcmSwitchPFCClass3McastQueue: 13458 case bcmSwitchPFCClass3DestmodQueue: 13459 *class = 3; 13460 break; 13461 case bcmSwitchPFCClass2Queue: 13462 case bcmSwitchPFCClass2McastQueue: 13463 case bcmSwitchPFCClass2DestmodQueue: 13464 *class = 2; 13465 break; 13466 case bcmSwitchPFCClass1Queue: 13467 case bcmSwitchPFCClass1McastQueue: 13468 case bcmSwitchPFCClass1DestmodQueue: 13469 *class = 1; 13470 break; 13471 case bcmSwitchPFCClass0Queue: 13472 case bcmSwitchPFCClass0McastQueue: 13473 case bcmSwitchPFCClass0DestmodQueue: 13474 *class = 0; 13475 break; 13476 /* 13477 * COVERITY 13478 * 13479 * This default is unreachable but needed for some compiler. 13480 */ 13481 /* coverity[dead_error_begin] */ 13482 default: 13483 return BCM_E_INTERNAL; 13484 } 13485 return BCM_E_NONE; 13486 } 13487 13488 int 13489 bcm_tr3_cosq_port_pfc_op(int unit, bcm_port_t port, 13490 bcm_switch_control_t sctype, _bcm_cosq_op_t op, 13491 bcm_gport_t *gport, int gport_count) 13492 { 13493 _bcm_tr3_cosq_node_t *node; 13494 bcm_port_t local_port, resolved_port; 13495 int type, class = -1, id, index, hw_cosq, hw_cosq1; 13496 uint32 profile_index, old_profile_index; 13497 uint64 rval64[16], tmp, *rval64s[1], rval, index_map; 13498 uint32 fval, cos_bmp, tmp32; 13499 int hw_index, hw_index1; 13500 _bcm_tr3_mmu_info_t *mmu_info; 13501 _bcm_tr3_cosq_port_info_t *port_info; 13502 soc_reg_t reg; 13503 int phy_port, mmu_port, lvl; 13504 soc_info_t *si; 13505 static const soc_reg_t llfc_cfgr[] = { 13506 PORT_PFC_CFG0r, PORT_PFC_CFG1r 13507 }; 13508 13509 if (gport_count < 0) { 13510 return BCM_E_PARAM; 13511 } 13512 13513 BCM_IF_ERROR_RETURN 13514 (_bcm_tr3_cosq_localport_resolve(unit, port, &local_port)); 13515 13516 if (IS_CPU_PORT(unit, local_port)) { 13517 return BCM_E_PARAM; 13518 } 13519 13520 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_pfc_class_resolve(sctype, &type, &class)); 13521 13522 si = &SOC_INFO(unit); 13523 phy_port = si->port_l2p_mapping[local_port]; 13524 mmu_port = si->port_p2m_mapping[phy_port]; 13525 13526 mmu_info = _bcm_tr3_mmu_info[unit]; 13527 port_info = &mmu_info->port_info[local_port]; 13528 13529 cos_bmp = 0; 13530 for (index = 0; index < gport_count; index++) { 13531 hw_index = hw_index1 = -1; 13532 hw_cosq = hw_cosq1 = -1; 13533 if (BCM_GPORT_IS_SET(gport[index])) { 13534 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_node_get(unit, gport[index], 13535 0, NULL, &resolved_port, &id, &node)); 13536 13537 if (!((node->type == _BCM_TR3_NODE_UCAST) || 13538 (node->type == _BCM_TR3_NODE_MCAST) || 13539 (node->type == _BCM_TR3_NODE_SCHEDULER))) { 13540 return BCM_E_PARAM; 13541 } 13542 13543 hw_index = node->hw_index; 13544 hw_cosq = node->hw_cosq; 13545 lvl = node->level; 13546 } else { 13547 if (_bcm_tr3_cosq_port_has_ets(unit, local_port)) { 13548 hw_cosq = gport[index]; 13549 node = &mmu_info->queue_node[port_info->uc_base + hw_cosq]; 13550 if ((!node->in_use) || (node->attached_to_input == -1)) { 13551 return BCM_E_PARAM; 13552 } 13553 hw_index = node->hw_index; 13554 node = &mmu_info->mc_queue_node[port_info->mc_base + hw_cosq]; 13555 if ((!node->in_use) || (node->attached_to_input == -1)) { 13556 return BCM_E_PARAM; 13557 } 13558 hw_index1 = node->hw_index; 13559 hw_cosq1 = hw_cosq + 8; 13560 lvl = SOC_TR3_NODE_LVL_L2; 13561 } else { 13562 hw_cosq = gport[index]; 13563 if (IS_TR3_HSP_PORT(unit, local_port)) { 13564 /* HSP ports use Level-0 scheduler */ 13565 lvl = SOC_TR3_NODE_LVL_L0; 13566 BCM_IF_ERROR_RETURN(soc_tr3_hsp_sched_hw_index_get(unit, local_port, 13567 SOC_TR3_NODE_LVL_L0, 0, hw_cosq, &hw_index)); 13568 } else { 13569 lvl = SOC_TR3_NODE_LVL_L1; 13570 BCM_IF_ERROR_RETURN(soc_tr3_sched_hw_index_get(unit, local_port, 13571 SOC_TR3_NODE_LVL_L1, hw_cosq, &hw_index)); 13572 } 13573 } 13574 } 13575 if ((hw_cosq < 0) || (hw_cosq >= _TR3_NUM_COS(unit))) { 13576 return BCM_E_PARAM; 13577 } 13578 BCM_IF_ERROR_RETURN( 13579 _bcm_tr3_map_fc_status_to_node(unit, mmu_port*4, hw_cosq, 13580 hw_index, ((op == _BCM_COSQ_OP_CLEAR) ? 0 : 1), lvl)); 13581 cos_bmp |= 1 << hw_cosq; 13582 if (hw_cosq1 >= 0) { 13583 BCM_IF_ERROR_RETURN( 13584 _bcm_tr3_map_fc_status_to_node(unit, mmu_port*4, hw_cosq1, 13585 hw_index1, ((op == _BCM_COSQ_OP_CLEAR) ? 0 : 1), lvl)); 13586 cos_bmp |= 1 << hw_cosq1; 13587 } 13588 } 13589 13590 if (op == _BCM_COSQ_OP_CLEAR) { 13591 cos_bmp = (1 << NUM_COS(unit)) - 1; 13592 cos_bmp |= (cos_bmp << 8); 13593 } 13594 13595 reg = llfc_cfgr[mmu_port/32]; 13596 rval64s[0] = rval64; 13597 BCM_IF_ERROR_RETURN(soc_reg64_get(unit, reg, 0, 0, &rval)); 13598 if (op == _BCM_COSQ_OP_SET || cos_bmp != 0) { 13599 index_map = soc_reg64_field_get(unit, reg, rval, PROFILE_INDEXf); 13600 COMPILER_64_SHR(index_map, ((mmu_port % 32) * 2)); 13601 COMPILER_64_TO_32_LO(tmp32, index_map); 13602 old_profile_index = (tmp32 & 3)*16; 13603 BCM_IF_ERROR_RETURN 13604 (soc_profile_reg_get(unit, _bcm_tr3_llfc_profile[unit], 13605 old_profile_index, 16, rval64s)); 13606 if (op == _BCM_COSQ_OP_SET) { 13607 soc_reg64_field32_set(unit, PRIO2COS_PROFILEr, &rval64[class], 13608 COS_BMPf, cos_bmp); 13609 } else if (cos_bmp != 0) { 13610 fval = soc_reg64_field32_get(unit, PRIO2COS_PROFILEr, rval64[class], 13611 COS_BMPf); 13612 if (op == _BCM_COSQ_OP_ADD) { 13613 fval |= cos_bmp; 13614 } else { /* _BCM_COSQ_OP_DELETE */ 13615 fval &= ~cos_bmp; 13616 } 13617 soc_reg64_field32_set(unit, PRIO2COS_PROFILEr, &rval64[class], 13618 COS_BMPf, fval); 13619 } 13620 BCM_IF_ERROR_RETURN 13621 (soc_profile_reg_add(unit, _bcm_tr3_llfc_profile[unit], rval64s, 13622 16, &profile_index)); 13623 13624 13625 index_map = soc_reg64_field_get(unit, reg, rval, PROFILE_INDEXf); 13626 13627 COMPILER_64_SET(tmp, 0, 3); 13628 COMPILER_64_SHL(tmp, (mmu_port % 32) * 2); 13629 COMPILER_64_NOT(tmp); 13630 COMPILER_64_AND(index_map, tmp); 13631 COMPILER_64_SET(tmp, 0, profile_index/16); 13632 COMPILER_64_SHL(tmp, (mmu_port % 32) * 2); 13633 COMPILER_64_OR(index_map, tmp); 13634 13635 soc_reg64_field_set(unit, reg, &rval, PROFILE_INDEXf, 13636 index_map); 13637 13638 BCM_IF_ERROR_RETURN 13639 (soc_profile_reg_delete(unit, _bcm_tr3_llfc_profile[unit], 13640 old_profile_index)); 13641 } 13642 13643 BCM_IF_ERROR_RETURN(soc_reg64_set(unit, reg, 0, 0, rval)); 13644 13645 return BCM_E_NONE; 13646 } 13647 13648 int 13649 bcm_tr3_cosq_port_pfc_get(int unit, bcm_port_t port, 13650 bcm_switch_control_t sctype, 13651 bcm_gport_t *gport, int gport_count, 13652 int *actual_gport_count) 13653 { 13654 _bcm_tr3_cosq_node_t *node; 13655 bcm_port_t local_port; 13656 int type = -1, class = -1, hw_cosq, count = 0, j, inv_mapped, hw_index; 13657 uint32 profile_index; 13658 uint64 rval64[16], *rval64s[1], rval, index_map; 13659 uint32 tmp32, bmp; 13660 _bcm_tr3_mmu_info_t *mmu_info; 13661 int phy_port, mmu_port; 13662 int eindex; 13663 soc_info_t *si; 13664 soc_reg_t reg; 13665 soc_mem_t mem; 13666 static const soc_reg_t llfc_cfgr[] = { 13667 PORT_PFC_CFG0r, PORT_PFC_CFG1r 13668 }; 13669 static const soc_field_t self[] = { 13670 SEL0f, SEL1f, SEL2f, SEL3f 13671 }; 13672 uint32 map_entry[SOC_MAX_MEM_WORDS]; 13673 13674 if (IS_CPU_PORT(unit, port)) { 13675 return BCM_E_PORT; 13676 } 13677 13678 if (gport == NULL || gport_count <= 0 || actual_gport_count == NULL) { 13679 return BCM_E_PARAM; 13680 } 13681 13682 BCM_IF_ERROR_RETURN 13683 (_bcm_tr3_cosq_localport_resolve(unit, port, &local_port)); 13684 13685 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_pfc_class_resolve(sctype, &type, &class)); 13686 13687 si = &SOC_INFO(unit); 13688 mmu_info = _bcm_tr3_mmu_info[unit]; 13689 phy_port = si->port_l2p_mapping[local_port]; 13690 mmu_port = si->port_p2m_mapping[phy_port]; 13691 13692 rval64s[0] = rval64; 13693 reg = llfc_cfgr[mmu_port/32]; 13694 BCM_IF_ERROR_RETURN(soc_reg64_get(unit, reg, 0, 0, &rval)); 13695 13696 index_map = soc_reg64_field_get(unit, reg, rval, PROFILE_INDEXf); 13697 COMPILER_64_SHR(index_map, ((mmu_port % 32) * 2)); 13698 COMPILER_64_TO_32_LO(tmp32, index_map); 13699 profile_index = (tmp32 & 3)*16; 13700 13701 BCM_IF_ERROR_RETURN 13702 (soc_profile_reg_get(unit, _bcm_tr3_llfc_profile[unit], 13703 profile_index, 16, rval64s)); 13704 13705 bmp = soc_reg64_field32_get(unit, PRIO2COS_PROFILEr, rval64[class], 13706 COS_BMPf); 13707 for (hw_cosq = 0; hw_cosq < 16; hw_cosq++) { 13708 if (!(bmp & (1 << hw_cosq))) { 13709 continue; 13710 } 13711 if (_bcm_tr3_cosq_port_has_ets(unit, local_port)) { 13712 inv_mapped = 0; 13713 for (j = _BCM_TR3_NUM_PORT_SCHEDULERS; 13714 j < _BCM_TR3_NUM_TOTAL_SCHEDULERS; j++) { 13715 node = &mmu_info->sched_node[j]; 13716 if ((!node->in_use) || (node->local_port != local_port) || 13717 (node->hw_cosq != hw_cosq)) { 13718 continue; 13719 } 13720 13721 hw_index = (node->hw_index / 16); 13722 eindex = (node->hw_index % 16)/4; 13723 if (node->level == SOC_TR3_NODE_LVL_L0) { 13724 mem = MMU_INTFI_FC_MAP_TBL0m; 13725 } else if (node->level == SOC_TR3_NODE_LVL_L1) { 13726 mem = MMU_INTFI_FC_MAP_TBL1m; 13727 } else { 13728 continue; 13729 } 13730 13731 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, 13732 MEM_BLOCK_ALL, hw_index, &map_entry)); 13733 13734 if (soc_mem_field32_get(unit, mem, &map_entry, self[eindex])) { 13735 inv_mapped = 1; 13736 gport[count++] = node->gport; 13737 break; 13738 } 13739 } 13740 13741 for (j = 0; inv_mapped==0 && j < _BCM_TR3_NUM_L2_UC_LEAVES; j++) { 13742 node = &mmu_info->queue_node[j]; 13743 if ((!node->in_use) || (node->local_port != local_port) || 13744 (node->hw_cosq != hw_cosq)) { 13745 continue; 13746 } 13747 13748 mem = MMU_INTFI_FC_MAP_TBL2m; 13749 hw_index = (node->hw_index / 16); 13750 eindex = (node->hw_index % 16)/4; 13751 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, 13752 MEM_BLOCK_ALL, hw_index, &map_entry)); 13753 13754 if (soc_mem_field32_get(unit, mem, &map_entry, self[eindex])) { 13755 gport[count++] = node->gport; 13756 } 13757 break; 13758 } 13759 } else { 13760 gport[count++] = hw_cosq; 13761 } 13762 if (count == gport_count) { 13763 break; 13764 } 13765 } 13766 13767 if (count == 0) { 13768 return BCM_E_NOT_FOUND; 13769 } 13770 *actual_gport_count = count; 13771 13772 return BCM_E_NONE; 13773 } 13774 13775 /* 13776 * Function: 13777 * _bcm_tr3_fc_map_gport_check 13778 * Purpose: 13779 * Validate if a gport can be mapped to a port's PFC/FC status. 13780 * Parameters: 13781 * unit - (IN) unit number 13782 * port - (IN) port number 13783 * gport - (IN) gport that will be mapped 13784 * Returns: 13785 * BCM_E_XXX 13786 */ 13787 STATIC int 13788 _bcm_tr3_fc_map_gport_check(int unit, 13789 bcm_gport_t port, 13790 bcm_gport_t gport) 13791 { 13792 bcm_port_t local_port = -1, resolved_port; 13793 int hw_cosq; 13794 _bcm_tr3_cosq_port_info_t *port_info; 13795 _bcm_tr3_mmu_info_t *mmu_info; 13796 _bcm_tr3_cosq_node_t *node; 13797 13798 BCM_IF_ERROR_RETURN 13799 (_bcm_tr3_cosq_localport_resolve(unit, port, &local_port)); 13800 13801 if (local_port < 0) { 13802 return BCM_E_PORT; 13803 } 13804 13805 mmu_info = _bcm_tr3_mmu_info[unit]; 13806 port_info = &mmu_info->port_info[local_port]; 13807 13808 hw_cosq = -1; 13809 if (BCM_GPORT_IS_SET(gport)) { 13810 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_node_get(unit, gport, 13811 0, NULL, &resolved_port, NULL, &node)); 13812 if (!((node->type == _BCM_TR3_NODE_UCAST) || 13813 (node->type == _BCM_TR3_NODE_MCAST) || 13814 (node->type == _BCM_TR3_NODE_SCHEDULER))) { 13815 return BCM_E_PARAM; 13816 } 13817 if (resolved_port != local_port) { 13818 return BCM_E_PARAM; 13819 } 13820 hw_cosq = node->hw_cosq; 13821 } else { 13822 hw_cosq = gport; 13823 if (_bcm_tr3_cosq_port_has_ets(unit, local_port)) { 13824 node = &mmu_info->queue_node[port_info->uc_base + hw_cosq]; 13825 if ((!node->in_use) || (node->attached_to_input == -1)) { 13826 return BCM_E_PARAM; 13827 } 13828 node = &mmu_info->mc_queue_node[port_info->mc_base + hw_cosq]; 13829 if ((!node->in_use) || (node->attached_to_input == -1)) { 13830 return BCM_E_PARAM; 13831 } 13832 } 13833 } 13834 if ((hw_cosq < 0) || (hw_cosq >= _TR3_NUM_INTERNAL_PRI)) { 13835 return BCM_E_PARAM; 13836 } 13837 13838 return BCM_E_NONE; 13839 } 13840 13841 /* 13842 * Function: 13843 * _bcm_tr3_pfc_class_mapping_check 13844 * Purpose: 13845 * Validate param of bcm_cosq_pfc_class_mapping_t. 13846 * Parameters: 13847 * unit - (IN) unit number 13848 * port - (IN) port number 13849 * array_count - (IN) count of mapping array 13850 * mapping_array - (IN) mapping array list 13851 * Returns: 13852 * BCM_E_XXX 13853 */ 13854 STATIC int 13855 _bcm_tr3_pfc_class_mapping_check(int unit, 13856 bcm_gport_t port, 13857 int array_count, 13858 bcm_cosq_pfc_class_mapping_t *mapping_array) 13859 { 13860 int count, index, cur_class; 13861 bcm_gport_t cur_gport = 0; 13862 13863 if (mapping_array == NULL) { 13864 return BCM_E_PARAM; 13865 } 13866 13867 for (count = 0; count < array_count; count++) { 13868 cur_class = mapping_array[count].class_id; 13869 if ((cur_class < 0) || (cur_class >= _BCM_TR3_NUM_PFC_CLASS)) { 13870 return BCM_E_PARAM; 13871 } 13872 13873 for (index = 0; index < BCM_COSQ_PFC_GPORT_COUNT; index++) { 13874 cur_gport = mapping_array[count].gport_list[index]; 13875 if (cur_gport == BCM_GPORT_INVALID) { 13876 break; 13877 } 13878 BCM_IF_ERROR_RETURN(_bcm_tr3_fc_map_gport_check(unit, 13879 port, cur_gport)); 13880 } 13881 } 13882 13883 return BCM_E_NONE; 13884 } 13885 13886 /* 13887 * Function: 13888 * _bcm_tr3_clear_fc_status_to_node 13889 * Purpose: 13890 * Clear MMU_INTFI_PIPE_FC_MAP_TBL setting of a port. 13891 * Parameters: 13892 * unit - (IN) unit number 13893 * port - (IN) port number 13894 * Returns: 13895 * BCM_E_XXX 13896 */ 13897 STATIC int 13898 _bcm_tr3_clear_fc_status_to_node(int unit, int port) 13899 { 13900 uint32 map_entry[SOC_MAX_MEM_WORDS], i_value, s_value; 13901 static const soc_field_t self[] = { 13902 SEL0f, SEL1f, SEL2f, SEL3f 13903 }; 13904 static const soc_field_t indexf[] = { 13905 INDEX0f, INDEX1f, INDEX2f, INDEX3f 13906 }; 13907 static const soc_mem_t mem[] = { 13908 MMU_INTFI_FC_MAP_TBL0m, 13909 MMU_INTFI_FC_MAP_TBL1m, 13910 MMU_INTFI_FC_MAP_TBL2m 13911 }; 13912 int base, table, index, count, field; 13913 int mmu_port, phy_port, update; 13914 bcm_port_t local_port; 13915 soc_info_t *si; 13916 13917 BCM_IF_ERROR_RETURN 13918 (_bcm_tr3_cosq_localport_resolve(unit, port, &local_port)); 13919 13920 si = &SOC_INFO(unit); 13921 phy_port = si->port_l2p_mapping[local_port]; 13922 mmu_port = si->port_p2m_mapping[phy_port]; 13923 13924 base = mmu_port * 4; 13925 for (table = 0; table < COUNTOF(mem); table++) { 13926 count = soc_mem_index_count(unit, mem[table]); 13927 for (index = 0; index < count; index++) { 13928 update = 0; 13929 SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem[table], 13930 MEM_BLOCK_ALL, index, &map_entry)); 13931 for (field = 0; field < COUNTOF(indexf); field++) { 13932 s_value = soc_mem_field32_get(unit, mem[table], 13933 &map_entry, self[field]); 13934 i_value = soc_mem_field32_get(unit, mem[table], 13935 &map_entry, indexf[field]); 13936 if (s_value && (i_value >= base) && (i_value < (base + 4))) { 13937 soc_mem_field32_set(unit, mem[table], 13938 &map_entry, self[field], 0); 13939 soc_mem_field32_set(unit, mem[table], 13940 &map_entry, indexf[field], 0); 13941 update = 1; 13942 } 13943 } 13944 if (update) { 13945 SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem[table], 13946 MEM_BLOCK_ALL, index, &map_entry)); 13947 } 13948 } 13949 } 13950 13951 return BCM_E_NONE; 13952 } 13953 13954 /* 13955 * Function: 13956 * _bcm_tr3_fc_status_map_gport 13957 * Purpose: 13958 * Set mapping in FC_MAP_TBL for gport, and update cos_bmp with gport cosq. 13959 * Parameters: 13960 * unit - (IN) unit number 13961 * port - (IN) port number 13962 * gport - (IN) gport to be mapped 13963 * cos_map - (OUT) hw_cosq of gport 13964 * Returns: 13965 * BCM_E_XXX 13966 * Note: 13967 * This function assumes gport has been validated by 13968 * "_bcm_tr3_fc_map_gport_check". 13969 */ 13970 STATIC int 13971 _bcm_tr3_fc_status_map_gport(int unit, int port, 13972 bcm_gport_t gport, uint32 *cos_bmp) 13973 { 13974 int hw_index, hw_index1; 13975 int hw_cosq, hw_cosq1; 13976 int id, lvl; 13977 int mmu_port, phy_port; 13978 bcm_port_t local_port, resolved_port; 13979 _bcm_tr3_cosq_node_t *node; 13980 _bcm_tr3_cosq_port_info_t *port_info; 13981 soc_info_t *si; 13982 _bcm_tr3_mmu_info_t *mmu_info; 13983 13984 BCM_IF_ERROR_RETURN 13985 (_bcm_tr3_cosq_localport_resolve(unit, port, &local_port)); 13986 13987 si = &SOC_INFO(unit); 13988 phy_port = si->port_l2p_mapping[local_port]; 13989 mmu_port = si->port_p2m_mapping[phy_port]; 13990 13991 mmu_info = _bcm_tr3_mmu_info[unit]; 13992 port_info = &mmu_info->port_info[local_port]; 13993 13994 hw_index = hw_index1 = -1; 13995 hw_cosq = hw_cosq1 = -1; 13996 if (BCM_GPORT_IS_SET(gport)) { 13997 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_node_get(unit, gport, 13998 0, NULL, &resolved_port, &id, &node)); 13999 hw_index = node->hw_index; 14000 hw_cosq = node->hw_cosq; 14001 lvl = node->level; 14002 } else { 14003 if (_bcm_tr3_cosq_port_has_ets(unit, local_port)) { 14004 hw_cosq = gport; 14005 node = &mmu_info->queue_node[port_info->uc_base + hw_cosq]; 14006 hw_index = node->hw_index; 14007 14008 node = &mmu_info->mc_queue_node[port_info->mc_base + hw_cosq]; 14009 hw_index1 = node->hw_index; 14010 hw_cosq1 = hw_cosq; 14011 lvl = SOC_TR3_NODE_LVL_L2; 14012 } else { 14013 lvl = SOC_TR3_NODE_LVL_L1; 14014 /* gport[] represnts the physical Cos value */ 14015 hw_cosq = gport; 14016 BCM_IF_ERROR_RETURN(soc_tr3_sched_hw_index_get(unit, local_port, 14017 SOC_TR3_NODE_LVL_L1, hw_cosq, &hw_index)); 14018 } 14019 } 14020 14021 BCM_IF_ERROR_RETURN( 14022 _bcm_tr3_map_fc_status_to_node(unit, mmu_port*4, hw_cosq, 14023 hw_index, 1, lvl)); 14024 if (cos_bmp != NULL) { 14025 *cos_bmp |= 1 << hw_cosq; 14026 } 14027 14028 if (hw_cosq1 >= 0) { 14029 BCM_IF_ERROR_RETURN( 14030 _bcm_tr3_map_fc_status_to_node(unit, mmu_port*4, hw_cosq1, 14031 hw_index1, 1, lvl)); 14032 if (cos_bmp != NULL) { 14033 *cos_bmp |= 1 << hw_cosq1; 14034 } 14035 } 14036 14037 return BCM_E_NONE; 14038 } 14039 14040 /* 14041 * Function: 14042 * _bcm_tr3_port_pfc_profile_set 14043 * Purpose: 14044 * Set PFC mapping profile for port. Updates PRIO2COS_PROFILE & PORT_PFC_CFG. 14045 * Parameters: 14046 * unit - (IN) unit number 14047 * port - (IN) port number 14048 * op - (IN) operation type 14049 * entry_cnt - (IN) count of bmp 14050 * pfc_class - (IN) class list 14051 * cos_bmp - (IN) bmp list 14052 * Returns: 14053 * BCM_E_XXX 14054 */ 14055 STATIC int 14056 _bcm_tr3_port_pfc_profile_set(int unit, int port, _bcm_cosq_op_t op, 14057 int entry_cnt, int *pfc_class, uint32 *cos_bmp) 14058 { 14059 soc_reg_t reg; 14060 bcm_port_t local_port; 14061 int rv, entry, cur_class; 14062 int mmu_port, phy_port; 14063 uint32 profile_index, old_profile_index; 14064 uint32 fval, tmp32, cur_bmp; 14065 uint64 rval64[16], tmp, *rval64s[1], rval, index_map; 14066 soc_info_t *si; 14067 static const soc_reg_t llfc_cfgr[] = { 14068 PORT_PFC_CFG0r, PORT_PFC_CFG1r 14069 }; 14070 14071 if (pfc_class == NULL) { 14072 return BCM_E_PARAM; 14073 } 14074 if (cos_bmp == NULL) { 14075 return BCM_E_PARAM; 14076 } 14077 if ((entry_cnt < 0 ) || (entry_cnt > _BCM_TR3_NUM_PFC_CLASS)) { 14078 return BCM_E_PARAM; 14079 } 14080 14081 BCM_IF_ERROR_RETURN( 14082 _bcm_tr3_cosq_localport_resolve(unit, port, &local_port)); 14083 14084 si = &SOC_INFO(unit); 14085 phy_port = si->port_l2p_mapping[local_port]; 14086 mmu_port = si->port_p2m_mapping[phy_port]; 14087 14088 reg = llfc_cfgr[mmu_port/32]; 14089 rval64s[0] = rval64; 14090 BCM_IF_ERROR_RETURN(soc_reg64_get(unit, reg, 0, 0, &rval)); 14091 14092 index_map = soc_reg64_field_get(unit, reg, rval, PROFILE_INDEXf); 14093 COMPILER_64_SHR(index_map, ((mmu_port % 32) * 2)); 14094 COMPILER_64_TO_32_LO(tmp32, index_map); 14095 old_profile_index = (tmp32 & 3)*16; 14096 BCM_IF_ERROR_RETURN 14097 (soc_profile_reg_get(unit, _bcm_tr3_llfc_profile[unit], 14098 old_profile_index, 16, rval64s)); 14099 14100 for (entry = 0; entry < entry_cnt; entry++) { 14101 cur_class = pfc_class[entry]; 14102 cur_bmp = cos_bmp[entry]; 14103 if (op == _BCM_COSQ_OP_SET) { 14104 soc_reg64_field32_set(unit, PRIO2COS_PROFILEr, &rval64[cur_class], 14105 COS_BMPf, cur_bmp); 14106 } else { 14107 if (cur_bmp != 0) { 14108 fval = soc_reg64_field32_get(unit, PRIO2COS_PROFILEr, 14109 rval64[cur_class], COS_BMPf); 14110 if (op == _BCM_COSQ_OP_ADD) { 14111 fval |= cur_bmp; 14112 } else { /* _BCM_COSQ_OP_DELETE */ 14113 fval &= ~cur_bmp; 14114 } 14115 soc_reg64_field32_set(unit, PRIO2COS_PROFILEr, 14116 &rval64[cur_class], COS_BMPf, fval); 14117 } 14118 } 14119 } 14120 14121 BCM_IF_ERROR_RETURN 14122 (soc_profile_reg_delete(unit, _bcm_tr3_llfc_profile[unit], 14123 old_profile_index)); 14124 14125 rv = soc_profile_reg_add(unit, _bcm_tr3_llfc_profile[unit], rval64s, 14126 16, &profile_index); 14127 if (SOC_FAILURE(rv)) { 14128 BCM_IF_ERROR_RETURN 14129 (soc_profile_reg_reference(unit, _bcm_tr3_llfc_profile[unit], 14130 old_profile_index, 16)); 14131 return rv; 14132 } 14133 14134 14135 index_map = soc_reg64_field_get(unit, reg, rval, PROFILE_INDEXf); 14136 14137 COMPILER_64_SET(tmp, 0, 3); 14138 COMPILER_64_SHL(tmp, (mmu_port % 32) * 2); 14139 COMPILER_64_NOT(tmp); 14140 COMPILER_64_AND(index_map, tmp); 14141 COMPILER_64_SET(tmp, 0, profile_index/16); 14142 COMPILER_64_SHL(tmp, (mmu_port % 32) * 2); 14143 COMPILER_64_OR(index_map, tmp); 14144 14145 soc_reg64_field_set(unit, reg, &rval, PROFILE_INDEXf, 14146 index_map); 14147 14148 BCM_IF_ERROR_RETURN(soc_reg64_set(unit, reg, 0, 0, rval)); 14149 14150 return BCM_E_NONE; 14151 } 14152 14153 /* 14154 * Function: 14155 * bcm_tr3_cosq_pfc_class_mapping_set 14156 * Purpose: 14157 * Set PFC mapping for port. PFC class is mapped to cosq or scheduler node gports. 14158 * Parameters: 14159 * unit - (IN) unit number 14160 * port - (IN) port number 14161 * array_count - (IN) count of mapping 14162 * mapping_array - (IN) mappings 14163 * Returns: 14164 * BCM_E_XXX 14165 */ 14166 int 14167 bcm_tr3_cosq_pfc_class_mapping_set(int unit, 14168 bcm_gport_t port, 14169 int array_count, 14170 bcm_cosq_pfc_class_mapping_t *mapping_array) 14171 { 14172 int index, count; 14173 int cur_class = 0, pfc_class[_BCM_TR3_NUM_PFC_CLASS]; 14174 bcm_gport_t cur_gport = 0; 14175 uint32 cos_bmp[_BCM_TR3_NUM_PFC_CLASS]; 14176 14177 14178 if ((array_count < 0) || (array_count > _BCM_TR3_NUM_PFC_CLASS)) { 14179 return BCM_E_PARAM; 14180 } 14181 if (mapping_array == NULL) { 14182 return BCM_E_PARAM; 14183 } 14184 BCM_IF_ERROR_RETURN(_bcm_tr3_pfc_class_mapping_check(unit, port, 14185 array_count, mapping_array)); 14186 14187 (void) _bcm_tr3_clear_fc_status_to_node(unit, port); 14188 sal_memset(cos_bmp, 0, sizeof(cos_bmp)); 14189 for (count = 0; count < array_count; count++) { 14190 cur_class = mapping_array[count].class_id; 14191 14192 for (index = 0; index < BCM_COSQ_PFC_GPORT_COUNT; index++) { 14193 cur_gport = mapping_array[count].gport_list[index]; 14194 if (cur_gport == BCM_GPORT_INVALID) { 14195 break; 14196 } 14197 14198 BCM_IF_ERROR_RETURN(_bcm_tr3_fc_status_map_gport(unit, port, 14199 cur_gport, &cos_bmp[cur_class])); 14200 } 14201 } 14202 14203 for (index = 0; index < _BCM_TR3_NUM_PFC_CLASS; index++) { 14204 pfc_class[index] = index; 14205 } 14206 BCM_IF_ERROR_RETURN(_bcm_tr3_port_pfc_profile_set(unit, port, 14207 _BCM_COSQ_OP_SET, _BCM_TR3_NUM_PFC_CLASS, pfc_class, cos_bmp)); 14208 14209 return BCM_E_NONE; 14210 } 14211 14212 /* 14213 * Function: 14214 * bcm_tr3_cosq_pfc_class_mapping_get 14215 * Purpose: 14216 * Get PFC mapping for port. 14217 * Retrieves cosq or scheduler node gports 14218 * associated to PFC classes. 14219 * Parameters: 14220 * unit - (IN) unit number 14221 * port - (IN) port number 14222 * array_max - (IN) max retrieve count 14223 * mapping_array - (OUT) mappings 14224 * array_count - (OUT) retrieved mapping count 14225 * Returns: 14226 * BCM_E_XXX 14227 */ 14228 int 14229 bcm_tr3_cosq_pfc_class_mapping_get(int unit, 14230 bcm_gport_t port, 14231 int array_max, 14232 bcm_cosq_pfc_class_mapping_t *mapping_array, 14233 int *array_count) 14234 { 14235 int rv = 0; 14236 int cur_class = 0; 14237 int actual_gport_count, class_count = 0; 14238 bcm_switch_control_t sc[] = { bcmSwitchPFCClass0Queue, 14239 bcmSwitchPFCClass1Queue, 14240 bcmSwitchPFCClass2Queue, 14241 bcmSwitchPFCClass3Queue, 14242 bcmSwitchPFCClass4Queue, 14243 bcmSwitchPFCClass5Queue, 14244 bcmSwitchPFCClass6Queue, 14245 bcmSwitchPFCClass7Queue 14246 }; 14247 14248 if ((mapping_array == NULL) && (array_max > 0)) { 14249 return BCM_E_PARAM; 14250 } 14251 if (array_count == NULL) { 14252 return BCM_E_PARAM; 14253 } 14254 14255 for (cur_class = 0; cur_class < _BCM_TR3_NUM_PFC_CLASS; cur_class++) { 14256 actual_gport_count = 0; 14257 if (array_max > 0) { 14258 rv = bcm_tr3_cosq_port_pfc_get(unit, port, sc[cur_class], 14259 mapping_array[class_count].gport_list, 14260 BCM_COSQ_PFC_GPORT_COUNT, &actual_gport_count); 14261 } else { 14262 rv = bcm_tr3_cosq_port_pfc_get(unit, port, sc[cur_class], 14263 NULL, -1, &actual_gport_count); 14264 } 14265 if (rv == BCM_E_NONE) { 14266 if (array_max > 0) { 14267 mapping_array[class_count].class_id = cur_class; 14268 if (actual_gport_count < BCM_COSQ_PFC_GPORT_COUNT) { 14269 mapping_array[class_count].gport_list[actual_gport_count] = 14270 BCM_GPORT_INVALID; 14271 } 14272 } 14273 class_count++; 14274 } else if (rv != BCM_E_NOT_FOUND) { 14275 return rv; 14276 } 14277 14278 if ((class_count == array_max) && (array_max > 0)) { 14279 break; 14280 } 14281 } 14282 14283 *array_count = class_count; 14284 if (class_count == 0) { 14285 return BCM_E_NOT_FOUND; 14286 } 14287 14288 return BCM_E_NONE; 14289 } 14290 14291 int 14292 bcm_tr3_cosq_drop_status_enable_set(int unit, bcm_port_t port, int enable) 14293 { 14294 _bcm_tr3_mmu_info_t *mmu_info; 14295 soc_info_t *si; 14296 int base, count, idx; 14297 uint32 rval; 14298 _bcm_tr3_cosq_node_t *node; 14299 14300 if ((mmu_info = _bcm_tr3_mmu_info[unit]) == NULL) { 14301 return BCM_E_INIT; 14302 } 14303 14304 si = &SOC_INFO(unit); 14305 14306 count = si->port_num_cosq[port]; 14307 for (idx = 0; idx < count; idx++) { 14308 BCM_IF_ERROR_RETURN 14309 (READ_OP_QUEUE_CONFIG1_CELLr(unit, port, idx, &rval)); 14310 soc_reg_field_set(unit,OP_QUEUE_CONFIG1_CELLr, &rval, 14311 Q_E2E_DS_EN_CELLf, enable ? 1 : 0); 14312 BCM_IF_ERROR_RETURN 14313 (WRITE_OP_QUEUE_CONFIG1_CELLr(unit, port, idx, rval)); 14314 } 14315 14316 count = si->port_num_uc_cosq[port]; 14317 base = si->port_uc_cosq_base[port]; 14318 for (idx = 0; idx < count; idx++) { 14319 BCM_IF_ERROR_RETURN 14320 (soc_mem_field32_modify(unit, MMU_THDO_Q_TO_QGRP_MAPm, 14321 base + idx, Q_E2E_DS_EN_CELLf, !!enable)); 14322 } 14323 14324 for (idx = mmu_info->num_base_queues; 14325 idx < _BCM_TR3_NUM_L2_UC_LEAVES; idx++) { 14326 node = &mmu_info->queue_node[idx]; 14327 if ((node->in_use == FALSE) || (node->local_port != port)) { 14328 BCM_IF_ERROR_RETURN 14329 (soc_mem_field32_modify(unit, MMU_THDO_Q_TO_QGRP_MAPm, 14330 idx, Q_E2E_DS_EN_CELLf, !!enable)); 14331 } 14332 } 14333 14334 BCM_IF_ERROR_RETURN(READ_OP_THR_CONFIGr(unit, &rval)); 14335 soc_reg_field_set(unit, OP_THR_CONFIGr, &rval, EARLY_E2E_SELECTf, 14336 enable ? 1 : 0); 14337 BCM_IF_ERROR_RETURN(WRITE_OP_THR_CONFIGr(unit, rval)); 14338 14339 return BCM_E_NONE; 14340 } 14341 14342 14343 14344 int bcm_tr3_cosq_bst_profile_set(int unit, 14345 bcm_gport_t port, 14346 bcm_cos_queue_t cosq, 14347 bcm_bst_stat_id_t bid, 14348 bcm_cosq_bst_profile_t *profile) 14349 { 14350 BCM_IF_ERROR_RETURN(_bcm_bst_cmn_profile_set 14351 (unit, port, cosq, BCM_BST_DUP_XPE, bid, profile)); 14352 return BCM_E_NONE; 14353 } 14354 14355 int bcm_tr3_cosq_bst_profile_get(int unit, 14356 bcm_gport_t port, 14357 bcm_cos_queue_t cosq, 14358 bcm_bst_stat_id_t bid, 14359 bcm_cosq_bst_profile_t *profile) 14360 { 14361 BCM_IF_ERROR_RETURN(_bcm_bst_cmn_profile_get 14362 (unit, port, cosq, BCM_BST_DUP_XPE, bid, profile)); 14363 return BCM_E_NONE; 14364 } 14365 14366 int bcm_tr3_cosq_bst_stat_get(int unit, 14367 bcm_gport_t port, 14368 bcm_cos_queue_t cosq, 14369 bcm_bst_stat_id_t bid, 14370 uint32 options, 14371 uint64 *value) 14372 { 14373 return _bcm_bst_cmn_stat_get(unit, port, cosq, -1, bid, options, value); 14374 } 14375 14376 int bcm_tr3_cosq_bst_stat_multi_get(int unit, 14377 bcm_gport_t port, 14378 bcm_cos_queue_t cosq, 14379 uint32 options, 14380 int max_values, 14381 bcm_bst_stat_id_t *id_list, 14382 uint64 *values) 14383 { 14384 return _bcm_bst_cmn_stat_multi_get(unit, port, cosq, options, max_values, 14385 id_list, values); 14386 } 14387 14388 int bcm_tr3_cosq_bst_stat_clear(int unit, 14389 bcm_gport_t port, 14390 bcm_cos_queue_t cosq, 14391 bcm_bst_stat_id_t bid) 14392 { 14393 return _bcm_bst_cmn_stat_clear(unit, port, cosq, bid); 14394 } 14395 14396 int bcm_tr3_cosq_bst_stat_sync(int unit, bcm_bst_stat_id_t bid) 14397 { 14398 return _bcm_bst_cmn_stat_sync(unit, bid); 14399 } 14400 14401 /* 14402 * Function: 14403 * bcm_tr3_cosq_field_classifier_id_create 14404 * Purpose: 14405 * Create an endpoint. 14406 * Parameters: 14407 * unit - (IN) Unit number. 14408 * classifier - (IN) Classifier attributes 14409 * classifier_id - (OUT) Classifier ID 14410 * Returns: 14411 * BCM_E_xxx 14412 */ 14413 int 14414 bcm_tr3_cosq_field_classifier_id_create( 14415 int unit, 14416 bcm_cosq_classifier_t *classifier, 14417 int *classifier_id) 14418 { 14419 int rv; 14420 int ref_count = 0; 14421 int ent_per_set = 16; 14422 int i; 14423 14424 if (NULL == classifier || NULL == classifier_id) { 14425 return BCM_E_PARAM; 14426 } 14427 14428 for (i = 0; i < SOC_MEM_SIZE(unit, IFP_COS_MAPm);) { 14429 rv = soc_profile_mem_ref_count_get 14430 (unit, _bcm_tr3_ifp_cos_map_profile[unit], i, &ref_count); 14431 if (SOC_E_NONE != rv) { 14432 return (rv); 14433 } 14434 if (0 == ref_count) { 14435 break; 14436 } 14437 i = i + ent_per_set; 14438 } 14439 14440 if (i >= SOC_MEM_SIZE(unit, IFP_COS_MAPm) && ref_count != 0) { 14441 *classifier_id = 0; 14442 return (BCM_E_RESOURCE); 14443 } 14444 14445 _BCM_COSQ_CLASSIFIER_FIELD_SET(*classifier_id, (i / ent_per_set)); 14446 14447 return (BCM_E_NONE); 14448 } 14449 14450 /* 14451 * Function: 14452 * bcm_tr3_cosq_field_classifier_get 14453 * Purpose: 14454 * Get classifier type information. 14455 * Parameters: 14456 * unit - (IN) Unit number. 14457 * classifier_id - (IN) Classifier ID 14458 * classifier - (OUT) Classifier info 14459 * Returns: 14460 * BCM_E_xxx 14461 */ 14462 int 14463 bcm_tr3_cosq_field_classifier_get( 14464 int unit, 14465 int classifier_id, 14466 bcm_cosq_classifier_t *classifier) 14467 { 14468 sal_memset(classifier, 0, sizeof(bcm_cosq_classifier_t)); 14469 14470 if (_BCM_COSQ_CLASSIFIER_IS_FIELD(classifier_id)) { 14471 classifier->flags |= BCM_COSQ_CLASSIFIER_FIELD; 14472 } 14473 14474 return BCM_E_NONE; 14475 } 14476 14477 /* 14478 * Function: 14479 * bcm_tr3_cosq_service_classifier_id_create 14480 * Purpose: 14481 * Create an endpoint. 14482 * Parameters: 14483 * unit - (IN) Unit number. 14484 * classifier - (IN) Classifier attributes 14485 * classifier_id - (OUT) Classifier ID 14486 * Returns: 14487 * BCM_E_xxx 14488 */ 14489 int 14490 bcm_tr3_cosq_service_classifier_id_create( 14491 int unit, 14492 bcm_cosq_classifier_t *classifier, 14493 int *classifier_id) 14494 { 14495 if (NULL == classifier || NULL == classifier_id) { 14496 return BCM_E_PARAM; 14497 } 14498 /* XXX check classifier->vlan for valid vlan/vfi */ 14499 _BCM_COSQ_CLASSIFIER_SERVICE_SET(*classifier_id,classifier->vlan); 14500 return BCM_E_NONE; 14501 } 14502 14503 /* 14504 * Function: 14505 * bcm_tr3_cosq_service_classifier_id_destroy 14506 * Purpose: 14507 * free resource associated with this service classifier id. 14508 * Parameters: 14509 * unit - (IN) Unit number. 14510 * classifier_id - (IN) Classifier ID 14511 * Returns: 14512 * BCM_E_xxx 14513 */ 14514 int 14515 bcm_tr3_cosq_service_classifier_id_destroy( 14516 int unit, 14517 int classifier_id) 14518 { 14519 return BCM_E_NONE; 14520 } 14521 14522 /* 14523 * Function: 14524 * bcm_tr3_cosq_field_classifier_map_set 14525 * Purpose: 14526 * Set internal priority to ingress field processor CoS queue 14527 * override mapping. 14528 * Parameters: 14529 * unit - (IN) Unit number. 14530 * classifier_id - (IN) Classifier ID 14531 * count - (IN) Number of elements in priority_array and 14532 * cosq_array 14533 * priority_array - (IN) Array of internal priorities 14534 * cosq_array - (IN) Array of COS queues 14535 * Returns: 14536 * BCM_E_xxx 14537 */ 14538 int 14539 bcm_tr3_cosq_field_classifier_map_set(int unit, 14540 int classifier_id, 14541 int count, 14542 bcm_cos_t *priority_array, 14543 bcm_cos_queue_t *cosq_array) 14544 { 14545 int rv; 14546 int i, update = 0; 14547 int max_entries = 16; 14548 uint32 index; 14549 void *entries[1], *entries_out[2]; 14550 ifp_cos_map_entry_t *ent_buf, *ent_buf_out; 14551 int field_width; 14552 int ref_count = 0; 14553 /* Input parameter check. */ 14554 if (!_BCM_COSQ_CLASSIFIER_IS_FIELD(classifier_id)) { 14555 return (BCM_E_PARAM); 14556 } 14557 14558 if (count > max_entries) { 14559 return (BCM_E_PARAM); 14560 } 14561 14562 ent_buf = sal_alloc(sizeof(ifp_cos_map_entry_t) * max_entries, 14563 "IFP_COS_MAP entry"); 14564 if (ent_buf == NULL) { 14565 return (BCM_E_MEMORY); 14566 } 14567 14568 field_width = soc_mem_field_length(unit, IFP_COS_MAPm, IFP_COSf); 14569 sal_memset(ent_buf, 0, sizeof(ifp_cos_map_entry_t) * max_entries); 14570 entries[0] = ent_buf; 14571 14572 for (i = 0; i < count; i++) { 14573 if (priority_array[i] < max_entries) { 14574 if (cosq_array[i] >= (1 << field_width)) { 14575 return BCM_E_PARAM; 14576 } 14577 soc_mem_field32_set(unit, IFP_COS_MAPm, &ent_buf[priority_array[i]], 14578 IFP_COSf, cosq_array[i]); 14579 } 14580 } 14581 index = _BCM_COSQ_CLASSIFIER_FIELD_GET(classifier_id); 14582 rv = soc_profile_mem_ref_count_get 14583 (unit, _bcm_tr3_ifp_cos_map_profile[unit], 14584 index * max_entries, &ref_count); 14585 if (SOC_E_NONE != rv) { 14586 sal_free(ent_buf); 14587 return (rv); 14588 } 14589 /* 14590 * UPDATE: 14591 * 1. if ref count is 1 only then update can be called for since it is called 14592 * per port and cosq group. Cannot be updated for all the ports in one go 14593 * 2. then get the pre-configured profile for the classifier id 14594 * 3. If profile varies then call an delete and then add the new one 14595 */ 14596 14597 if (ref_count == 1) { 14598 ent_buf_out = sal_alloc(sizeof(ifp_cos_map_entry_t) * max_entries, 14599 "IFP_COS_MAP entry"); 14600 if (ent_buf_out == NULL) { 14601 sal_free(ent_buf); 14602 return (BCM_E_MEMORY); 14603 } 14604 sal_memset(ent_buf_out, 0, sizeof(ifp_cos_map_entry_t) * max_entries); 14605 entries_out[0] = ent_buf_out; 14606 14607 rv = soc_profile_mem_get(unit, _bcm_tr3_ifp_cos_map_profile[unit], 14608 index * max_entries, max_entries, entries_out); 14609 if (rv < 0) { 14610 sal_free(ent_buf); 14611 sal_free(ent_buf_out); 14612 return rv; 14613 } 14614 14615 /* check if both the profiles are same */ 14616 for (i = 0; i < count; i++) { 14617 if (cosq_array[i] != soc_mem_field32_get(unit, IFP_COS_MAPm, 14618 &ent_buf_out[priority_array[i]], 14619 IFP_COSf)) { 14620 update = 1; 14621 break; 14622 } 14623 } 14624 sal_free(ent_buf_out); 14625 if (update) { 14626 rv = soc_profile_mem_delete(unit, 14627 _bcm_tr3_ifp_cos_map_profile[unit], 14628 index * max_entries); 14629 if (rv < 0) { 14630 sal_free(ent_buf); 14631 return rv; 14632 } 14633 } 14634 } 14635 rv = soc_profile_mem_add(unit, _bcm_tr3_ifp_cos_map_profile[unit], 14636 entries, max_entries, &index); 14637 14638 sal_free(ent_buf); 14639 return (rv); 14640 } 14641 14642 /* 14643 * Function: 14644 * bcm_tr3_cosq_field_classifier_map_get 14645 * Purpose: 14646 * Get internal priority to ingress field processor CoS queue 14647 * override mapping information. 14648 * Parameters: 14649 * unit - (IN) Unit number. 14650 * classifier_id - (IN) Classifier ID 14651 * array_max - (IN) Size of priority_array and cosq_array 14652 * priority_array - (IN) Array of internal priorities 14653 * cosq_array - (OUT) Array of COS queues 14654 * array_count - (OUT) Size of cosq_array 14655 * Returns: 14656 * BCM_E_xxx 14657 */ 14658 int 14659 bcm_tr3_cosq_field_classifier_map_get(int unit, 14660 int classifier_id, 14661 int array_max, 14662 bcm_cos_t *priority_array, 14663 bcm_cos_queue_t *cosq_array, 14664 int *array_count) 14665 { 14666 int rv; 14667 int i; 14668 int ent_per_set = 16; 14669 uint32 index; 14670 void *entries[1]; 14671 ifp_cos_map_entry_t *ent_buf; 14672 14673 /* Input parameter check. */ 14674 if (NULL == priority_array || NULL == cosq_array || NULL == array_count) { 14675 return (BCM_E_PARAM); 14676 } 14677 14678 /* Allocate entry buffer. */ 14679 ent_buf = sal_alloc(sizeof(ifp_cos_map_entry_t) * ent_per_set, 14680 "IFP_COS_MAP entry"); 14681 if (ent_buf == NULL) { 14682 return (BCM_E_MEMORY); 14683 } 14684 sal_memset(ent_buf, 0, sizeof(ifp_cos_map_entry_t) * ent_per_set); 14685 entries[0] = ent_buf; 14686 14687 /* Get profile table entry set base index. */ 14688 index = _BCM_COSQ_CLASSIFIER_FIELD_GET(classifier_id); 14689 14690 /* Read out entries from profile table into allocated buffer. */ 14691 rv = soc_profile_mem_get(unit, _bcm_tr3_ifp_cos_map_profile[unit], 14692 index * ent_per_set, ent_per_set, entries); 14693 if (!(rv == SOC_E_NOT_FOUND || rv == SOC_E_NONE)) { 14694 sal_free(ent_buf); 14695 return rv; 14696 } 14697 14698 *array_count = array_max > ent_per_set ? ent_per_set : array_max; 14699 14700 /* Copy values into API OUT parameters. */ 14701 for (i = 0; i < *array_count; i++) { 14702 if (priority_array[i] >= 16) { 14703 sal_free(ent_buf); 14704 return BCM_E_PARAM; 14705 } 14706 cosq_array[i] = soc_mem_field32_get(unit, IFP_COS_MAPm, 14707 &ent_buf[priority_array[i]], 14708 IFP_COSf); 14709 } 14710 14711 sal_free(ent_buf); 14712 return (BCM_E_NONE); 14713 } 14714 14715 /* 14716 * Function: 14717 * bcm_tr3_cosq_field_classifier_map_clear 14718 * Purpose: 14719 * Delete an internal priority to ingress field processor CoS queue 14720 * override mapping profile set. 14721 * Parameters: 14722 * unit - (IN) Unit number. 14723 * classifier_id - (IN) Classifier ID 14724 * Returns: 14725 * BCM_E_xxx 14726 */ 14727 int 14728 bcm_tr3_cosq_field_classifier_map_clear(int unit, int classifier_id) 14729 { 14730 int ent_per_set = 16; 14731 uint32 index; 14732 14733 /* Get profile table entry set base index. */ 14734 index = _BCM_COSQ_CLASSIFIER_FIELD_GET(classifier_id); 14735 14736 /* Delete the profile entries set. */ 14737 BCM_IF_ERROR_RETURN 14738 (soc_profile_mem_delete(unit, 14739 _bcm_tr3_ifp_cos_map_profile[unit], 14740 index * ent_per_set)); 14741 return (BCM_E_NONE); 14742 } 14743 14744 /* 14745 * Function: 14746 * bcm_tr3_cosq_field_classifier_id_destroy 14747 * Purpose: 14748 * Free resource associated with this field classifier id. 14749 * Parameters: 14750 * unit - (IN) Unit number. 14751 * classifier_id - (IN) Classifier ID 14752 * Returns: 14753 * BCM_E_xxx 14754 */ 14755 int 14756 bcm_tr3_cosq_field_classifier_id_destroy(int unit, int classifier_id) 14757 { 14758 return (BCM_E_NONE); 14759 } 14760 14761 /* 14762 * Function: 14763 * bcm_tr3_cosq_service_map_set 14764 * Purpose: 14765 * Set the mapping from port, classifier, and multiple internal priorities 14766 * to multiple COS queues in a queue group. 14767 * Parameters: 14768 * unit - (IN) Unit number. 14769 * port - (IN) local port ID 14770 * classifier_id - (IN) Classifier ID 14771 * queue_group - (IN) Base queue ID 14772 * array_count - (IN) Number of elements in priority_array and 14773 * cosq_array 14774 * priority_array - (IN) Array of internal priorities 14775 * cosq_array - (IN) Array of COS queues 14776 * Returns: 14777 * BCM_E_xxx 14778 */ 14779 int 14780 bcm_tr3_cosq_service_map_set( 14781 int unit, 14782 bcm_port_t port, 14783 int classifier_id, 14784 bcm_gport_t queue_group, 14785 int array_count, 14786 bcm_cos_t *priority_array, 14787 bcm_cos_queue_t *cosq_array) 14788 { 14789 int rv = BCM_E_NONE; 14790 int i; 14791 int j; 14792 service_queue_map_entry_t sqm; 14793 service_port_map_entry_t *spm; 14794 service_cos_map_entry_t *scm; 14795 void *spm_entries[1]; 14796 void *scm_entries[1]; 14797 int local_port,local_id; 14798 int spm_entries_per_set = 128; 14799 int scm_entries_per_set = 16; 14800 int q_offset = 0; 14801 uint32 spm_idx; 14802 uint32 scm_idx; 14803 int spm_old_index = 0; 14804 int scm_old_index = 0; 14805 int qptr; 14806 int valid_cosq; 14807 int vid; 14808 int valid_entry; 14809 _bcm_tr3_cosq_node_t *node, *cur_node; 14810 14811 if (!_BCM_COSQ_CLASSIFIER_IS_SERVICE(classifier_id)) { 14812 return BCM_E_PARAM; 14813 } 14814 14815 /* index above 4K is for VFI */ 14816 vid = _BCM_COSQ_CLASSIFIER_SERVICE_GET(classifier_id); 14817 14818 /* validate the vlan id */ 14819 if (vid < 0 || vid >= SOC_MEM_SIZE(unit, SERVICE_QUEUE_MAPm)) { 14820 return BCM_E_PARAM; 14821 } 14822 14823 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_node_get(unit, queue_group, 0, 14824 NULL, &local_port, &local_id, &node)); 14825 14826 if (node->attached_to_input < 0) { 14827 return BCM_E_PARAM; 14828 } 14829 14830 /* Reading the parent numq so that , it will not exceed 14831 max number of inputs of the parent can have*/ 14832 local_id = node->hw_index; 14833 /* validate the user parameters */ 14834 if (array_count > scm_entries_per_set) { 14835 return BCM_E_PARAM; 14836 } 14837 14838 /* queues allocated for this queue_group should be contiguous.*/ 14839 /* check if user's queue number is valid */ 14840 for (i = 0; i < array_count; i++) { 14841 valid_cosq= 0; 14842 for (cur_node = node->parent->child; 14843 cur_node != NULL; 14844 cur_node = cur_node->sibling) { 14845 if (cosq_array[i] == cur_node->attached_to_input) { 14846 valid_cosq = 1; 14847 break; 14848 } 14849 } 14850 if (valid_cosq == 0) { 14851 return BCM_E_PARAM; 14852 } 14853 } 14854 14855 BCM_IF_ERROR_RETURN( 14856 soc_mem_read(unit, SERVICE_QUEUE_MAPm, MEM_BLOCK_ANY, (int)vid, &sqm)); 14857 14858 valid_entry = soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, &sqm, VALIDf); 14859 if (!valid_entry) { 14860 /* We need the offset to be atleast 1 to find if we have valid offset 14861 * for a given port.So reducing the base by 1 14862 */ 14863 qptr = local_id - 1 ; 14864 14865 sal_memset(&sqm,0, sizeof(service_queue_map_entry_t)); 14866 } else { 14867 qptr = soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, &sqm, SERVICE_QUEUE_PTRf); 14868 spm_old_index = soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, &sqm, 14869 SERVICE_PORT_PROFILE_INDEXf); 14870 scm_old_index = soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, &sqm, 14871 SERVICE_COS_PROFILE_INDEXf); 14872 } 14873 14874 /* allocate space for service port map profile */ 14875 spm = sal_alloc(sizeof(service_port_map_entry_t) * 14876 spm_entries_per_set, 14877 "SERVICE_PORT_MAP temp Mem"); 14878 if (spm == NULL) { 14879 return BCM_E_MEMORY; 14880 } 14881 sal_memset(spm,0, 14882 sizeof(service_port_map_entry_t) * spm_entries_per_set); 14883 spm_entries[0] = spm; 14884 14885 /* allocate space for service cos map profile */ 14886 scm = sal_alloc(sizeof(service_cos_map_entry_t) * 14887 scm_entries_per_set, 14888 "SERVICE_COS_MAP temp Mem"); 14889 if (scm == NULL) { 14890 sal_free(spm); 14891 return BCM_E_MEMORY; 14892 } 14893 sal_memset(scm,0, 14894 sizeof(service_cos_map_entry_t) * scm_entries_per_set); 14895 scm_entries[0] = scm; 14896 14897 if (soc_property_get(unit, spn_SERVICE_QUEUE_DYNAMIC_CONFIG, FALSE) == FALSE) { 14898 /* spn_SERVICE_QUEUE_DYNAMIC_CONFIG=FALSE, Default behavior */ 14899 14900 if (valid_entry) { 14901 /* only one service_cos_map profile is allowed per vlan/vfi. The first one is 14902 * used. If the subsequent profile doesn't match the existing one, 14903 * Then update the old profile, the new map may be added by other port. 14904 */ 14905 rv = soc_profile_mem_get(unit, _bcm_tr3_service_cos_map_profile[unit], 14906 scm_old_index * scm_entries_per_set, 14907 scm_entries_per_set, scm_entries); 14908 if (rv != SOC_E_NONE) { 14909 goto cleanup; 14910 } 14911 scm_idx = scm_old_index * scm_entries_per_set; 14912 14913 for (i = 0; i < array_count; i++) { 14914 if (cosq_array[i] != soc_mem_field32_get(unit,SERVICE_COS_MAPm, 14915 &scm[priority_array[i]],SERVICE_COS_OFFSETf) ) { 14916 if (priority_array[i] < scm_entries_per_set) { 14917 soc_mem_field32_set(unit, SERVICE_COS_MAPm, 14918 &scm[priority_array[i]], 14919 SERVICE_COS_OFFSETf, cosq_array[i]); 14920 } 14921 } 14922 } 14923 14924 rv = soc_profile_mem_add(unit, _bcm_tr3_service_cos_map_profile[unit], 14925 scm_entries, scm_entries_per_set, &scm_idx); 14926 if (rv != SOC_E_NONE) { 14927 goto cleanup; 14928 } 14929 14930 if (scm_old_index != scm_idx) { 14931 rv = soc_profile_mem_delete(unit, _bcm_tr3_service_cos_map_profile[unit], 14932 scm_old_index); 14933 if (rv != SOC_E_NONE) { 14934 goto cleanup; 14935 } 14936 } 14937 sal_free(scm); 14938 14939 rv = soc_profile_mem_get(unit, _bcm_tr3_service_port_map_profile[unit], 14940 spm_old_index * spm_entries_per_set, 14941 spm_entries_per_set, spm_entries); 14942 if (!(rv == SOC_E_NOT_FOUND || rv == SOC_E_NONE)) { 14943 sal_free(spm); 14944 return rv; 14945 } 14946 14947 if (local_id < qptr) { 14948 /* need to adjust the offset in service_port_map. 14949 * The new base -> qptr, offset added to qptr-local_id 14950 */ 14951 for (i = 0; i < spm_entries_per_set; i++) { 14952 q_offset = soc_mem_field32_get(unit,SERVICE_PORT_MAPm,&spm[i], 14953 SERVICE_PORT_OFFSETf); 14954 if (q_offset) { 14955 soc_mem_field32_set(unit, SERVICE_PORT_MAPm,&spm[i], 14956 SERVICE_PORT_OFFSETf, 14957 (qptr - (local_id - 1)) + q_offset); 14958 } 14959 } 14960 14961 /* We need the offset to be atleast 1 to find if we have valid offset 14962 * for a given port.So reducing the base by 1 14963 */ 14964 qptr = local_id - 1 ; 14965 q_offset = 1; /* use the new base queue */ 14966 } else { 14967 q_offset = local_id - qptr ; 14968 /* no change in queue base */ 14969 } 14970 } else { /* first time setup */ 14971 q_offset = 1; /* use the new base queue */ 14972 14973 /* add the cos profile if first time */ 14974 for (i = 0; i < array_count; i++) { 14975 if (priority_array[i] < scm_entries_per_set) { 14976 soc_mem_field32_set(unit,SERVICE_COS_MAPm,&scm[priority_array[i]], 14977 SERVICE_COS_OFFSETf, 14978 cosq_array[i]); 14979 } 14980 } 14981 /* add a new profile */ 14982 rv = soc_profile_mem_add(unit, _bcm_tr3_service_cos_map_profile[unit], 14983 scm_entries, scm_entries_per_set, 14984 &scm_idx); 14985 sal_free(scm); 14986 if (rv != SOC_E_NONE) { 14987 sal_free(spm); 14988 return rv; 14989 } 14990 } 14991 14992 soc_mem_field32_set(unit, SERVICE_PORT_MAPm, 14993 &spm[local_port], SERVICE_PORT_OFFSETf, 14994 q_offset); 14995 /* add a new profile */ 14996 rv = soc_profile_mem_add(unit, _bcm_tr3_service_port_map_profile[unit], spm_entries, 14997 spm_entries_per_set, 14998 &spm_idx); 14999 15000 if (rv != SOC_E_NONE) { 15001 if (valid_entry) { 15002 /* delete the old spm porfile */ 15003 BCM_IF_ERROR_RETURN 15004 (soc_profile_mem_delete(unit, _bcm_tr3_service_port_map_profile[unit], 15005 spm_old_index * spm_entries_per_set)); 15006 } 15007 rv = soc_profile_mem_add(unit, _bcm_tr3_service_port_map_profile[unit], spm_entries, 15008 spm_entries_per_set, 15009 &spm_idx); 15010 if (rv != SOC_E_NONE) { 15011 sal_free(spm); 15012 return rv; 15013 } 15014 valid_entry = 0; 15015 } 15016 sal_free(spm); 15017 } else { 15018 /* spn_SERVICE_QUEUE_DYNAMIC_CONFIG=TRUE, Behavior with dynamic configuration */ 15019 if (valid_entry) { 15020 /* only one service_cos_map profile is allowed per vlan/vfi. The first one is 15021 * used. If the subsequent profile doesn't match the existing one, 15022 * it is treated as error. Should always use the xxx_multi_set instead of xxx_set. 15023 */ 15024 rv = soc_profile_mem_get(unit, _bcm_tr3_service_cos_map_profile[unit], 15025 scm_old_index * scm_entries_per_set, 15026 scm_entries_per_set, scm_entries); 15027 if (rv != SOC_E_NONE) { 15028 goto cleanup; 15029 } 15030 scm_idx = scm_old_index * scm_entries_per_set; 15031 15032 for (i = 0; i < array_count; i++) { 15033 if (cosq_array[i] != soc_mem_field32_get(unit,SERVICE_COS_MAPm, 15034 &scm[priority_array[i]],SERVICE_COS_OFFSETf) ) { 15035 rv = BCM_E_PARAM; 15036 goto cleanup; 15037 } 15038 } 15039 15040 for (i = 0; i < scm_entries_per_set; i++) { 15041 for (j = 0; j < array_count; j++) { 15042 if (i == priority_array[j]) { 15043 break; 15044 } 15045 } 15046 /* for priorities not in priority_array, the cosq should be 0 */ 15047 if (j == array_count) { 15048 if (soc_mem_field32_get(unit,SERVICE_COS_MAPm,&scm[i],SERVICE_COS_OFFSETf)) { 15049 rv = BCM_E_PARAM; 15050 goto cleanup; 15051 } 15052 } 15053 } 15054 sal_free(scm); 15055 15056 rv = soc_profile_mem_get(unit, _bcm_tr3_service_port_map_profile[unit], 15057 spm_old_index * spm_entries_per_set, 15058 spm_entries_per_set, spm_entries); 15059 if (!(rv == SOC_E_NOT_FOUND || rv == SOC_E_NONE)) { 15060 sal_free(spm); 15061 return rv; 15062 } 15063 15064 q_offset = (local_id - qptr) & 0x3ff; /* Might wrap here */ 15065 #ifdef DEBUG_TR3_COSQ 15066 soc_cm_print("DEBUG %s[%d] COMPUTED q_offset = %u;\r\n", FUNCTION_NAME(), 15067 __LINE__, q_offset); 15068 #endif 15069 } else { /* first time setup */ 15070 q_offset = 1; /* use the new base queue */ 15071 15072 #ifdef DEBUG_TR3_COSQ 15073 soc_cm_print("DEBUG %s[%d] NEW q_offset = %u;\r\n", FUNCTION_NAME(), 15074 __LINE__, q_offset); 15075 #endif 15076 15077 /* add the cos profile if first time */ 15078 for (i = 0; i < array_count; i++) { 15079 if (priority_array[i] < scm_entries_per_set) { 15080 soc_mem_field32_set(unit,SERVICE_COS_MAPm,&scm[priority_array[i]], 15081 SERVICE_COS_OFFSETf, 15082 cosq_array[i]); 15083 } 15084 } 15085 /* add a new profile */ 15086 rv = soc_profile_mem_add(unit, _bcm_tr3_service_cos_map_profile[unit], 15087 scm_entries, scm_entries_per_set, 15088 &scm_idx); 15089 sal_free(scm); 15090 if (rv != SOC_E_NONE) { 15091 return rv; 15092 } 15093 15094 /* Initialize all port service offsets to ensure that they map to diffServe */ 15095 PBMP_PORT_ITER(unit, i) { 15096 int diffserv = (SOC_INFO(unit).port_uc_cosq_base[i] - qptr) & 0x3ff; 15097 if (SOC_INFO(unit).port_uc_cosq_base[i] >= 0) { 15098 soc_mem_field32_set(unit, SERVICE_PORT_MAPm, 15099 &spm[i], SERVICE_PORT_OFFSETf, 15100 diffserv); 15101 } 15102 } 15103 } 15104 15105 soc_mem_field32_set(unit, SERVICE_PORT_MAPm, 15106 &spm[local_port], SERVICE_PORT_OFFSETf, 15107 q_offset); 15108 /* add a new profile */ 15109 rv = soc_profile_mem_add(unit, _bcm_tr3_service_port_map_profile[unit], spm_entries, 15110 spm_entries_per_set, 15111 &spm_idx); 15112 sal_free(spm); 15113 if (rv != SOC_E_NONE) { 15114 return rv; 15115 } 15116 } /* spn_SERVICE_QUEUE_DYNAMIC_CONFIG */ 15117 15118 /* program the vlan base queue */ 15119 soc_mem_field32_set(unit, SERVICE_QUEUE_MAPm, &sqm, 15120 SERVICE_QUEUE_PTRf, qptr ); 15121 15122 /* set the SERVICE_COS_MAP profile index 15123 * scm_idx: hardware table base index for the set */ 15124 soc_mem_field32_set(unit, SERVICE_QUEUE_MAPm, &sqm, 15125 SERVICE_COS_PROFILE_INDEXf, 15126 scm_idx/scm_entries_per_set); 15127 15128 /* set the SERVICE_PORT_MAP profile index 15129 * spm_idx: hardware table base index for the set */ 15130 soc_mem_field32_set(unit, SERVICE_QUEUE_MAPm, &sqm, 15131 SERVICE_PORT_PROFILE_INDEXf, 15132 spm_idx/spm_entries_per_set); 15133 15134 if (!valid_entry) { /* first time */ 15135 /* use port indexed and cos indexed for this base queue */ 15136 soc_mem_field32_set(unit, SERVICE_QUEUE_MAPm, &sqm, 15137 SERVICE_QUEUE_MODELf, 3); 15138 soc_mem_field32_set(unit, SERVICE_QUEUE_MAPm, &sqm, 15139 VALIDf, 1); 15140 } 15141 15142 /* Write back updated buffer. */ 15143 rv = soc_mem_write(unit, SERVICE_QUEUE_MAPm, MEM_BLOCK_ALL, 15144 (int)vid, &sqm); 15145 15146 if (valid_entry) { 15147 /* delete the old spm porfile */ 15148 if ((spm_old_index * spm_entries_per_set) != spm_idx) { 15149 rv = soc_profile_mem_delete(unit, _bcm_tr3_service_port_map_profile[unit], 15150 spm_old_index * spm_entries_per_set); 15151 } 15152 } 15153 return BCM_E_NONE; 15154 15155 cleanup: 15156 sal_free(spm); 15157 sal_free(scm); 15158 return rv; 15159 } 15160 15161 /* 15162 * Function: 15163 * bcm_tr3_cosq_service_classifier_get 15164 * Purpose: 15165 * Get info about an endpoint. 15166 * Parameters: 15167 * unit - (IN) Unit number. 15168 * classifier_id - (IN) Classifier ID 15169 * classifier - (OUT) Classifier info 15170 * Returns: 15171 * BCM_E_xxx 15172 */ 15173 int 15174 bcm_tr3_cosq_service_classifier_get( 15175 int unit, 15176 int classifier_id, 15177 bcm_cosq_classifier_t *classifier) 15178 { 15179 sal_memset(classifier, 0, sizeof(bcm_cosq_classifier_t)); 15180 classifier->flags = BCM_COSQ_CLASSIFIER_VLAN; 15181 classifier->vlan = _BCM_COSQ_CLASSIFIER_SERVICE_GET(classifier_id); 15182 return BCM_E_NONE; 15183 } 15184 15185 /* 15186 * Function: 15187 * bcm_tr3_cosq_service_map_get 15188 * Purpose: 15189 * Get the mapping from port, classifier, and multiple internal priorities 15190 * to multiple COS queues in a queue group. 15191 * Parameters: 15192 * unit - (IN) Unit number. 15193 * port - (IN) Local port ID 15194 * classifier_id - (IN) Classifier ID 15195 * queue_group - (OUT) Queue group 15196 * array_max - (IN) Size of priority_array and cosq_array 15197 * priority_array - (IN) Array of internal priorities 15198 * cosq_array - (OUT) Array of COS queues 15199 * array_count - (OUT) Size of cosq_array 15200 * Returns: 15201 * BCM_E_xxx 15202 */ 15203 int 15204 bcm_tr3_cosq_service_map_get( 15205 int unit, 15206 bcm_port_t port, 15207 int classifier_id, 15208 bcm_gport_t *queue_group, 15209 int array_max, 15210 bcm_cos_t *priority_array, 15211 bcm_cos_queue_t *cosq_array, 15212 int *array_count) 15213 { 15214 service_queue_map_entry_t sqm; 15215 service_port_map_entry_t *spm; 15216 service_cos_map_entry_t *scm; 15217 void *spm_entries[1]; 15218 void *scm_entries[1]; 15219 int spm_entries_per_set = 128; 15220 int scm_entries_per_set = 16; 15221 int q_offset; 15222 int spm_index; 15223 int scm_index; 15224 int qptr; 15225 int vid; 15226 int valid_entry; 15227 int rv; 15228 int i; 15229 _bcm_tr3_cosq_node_t *node; 15230 _bcm_tr3_mmu_info_t *mmu_info; 15231 15232 mmu_info = _bcm_tr3_mmu_info[unit]; 15233 node = &mmu_info->queue_node[0]; 15234 15235 vid = _BCM_COSQ_CLASSIFIER_SERVICE_GET(classifier_id); 15236 15237 BCM_IF_ERROR_RETURN( 15238 soc_mem_read(unit, SERVICE_QUEUE_MAPm, MEM_BLOCK_ANY, (int)vid, &sqm)); 15239 15240 valid_entry = soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, &sqm, VALIDf); 15241 if (!valid_entry) { 15242 return BCM_E_CONFIG; /* service queue is configured */ 15243 } 15244 15245 qptr = soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, &sqm, SERVICE_QUEUE_PTRf); 15246 spm_index = soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, &sqm, 15247 SERVICE_PORT_PROFILE_INDEXf); 15248 scm_index = soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, &sqm, 15249 SERVICE_COS_PROFILE_INDEXf); 15250 15251 /* allocate space for service port map profile */ 15252 spm = sal_alloc(sizeof(service_port_map_entry_t) * 15253 spm_entries_per_set, 15254 "SERVICE_PORT_MAP temp Mem"); 15255 if (spm == NULL) { 15256 return BCM_E_MEMORY; 15257 } 15258 sal_memset(spm,0, 15259 sizeof(service_port_map_entry_t) * spm_entries_per_set); 15260 spm_entries[0] = spm; 15261 15262 /* allocate space for service cos map profile */ 15263 scm = sal_alloc(sizeof(service_cos_map_entry_t) * 15264 scm_entries_per_set, 15265 "SERVICE_COS_MAP temp Mem"); 15266 if (scm == NULL) { 15267 sal_free(spm); 15268 return BCM_E_MEMORY; 15269 } 15270 sal_memset(scm,0, 15271 sizeof(service_cos_map_entry_t) * scm_entries_per_set); 15272 scm_entries[0] = scm; 15273 15274 rv = soc_profile_mem_get(unit, _bcm_tr3_service_port_map_profile[unit], 15275 spm_index * spm_entries_per_set, 15276 spm_entries_per_set, spm_entries); 15277 if (!(rv == SOC_E_NOT_FOUND || rv == SOC_E_NONE)) { 15278 sal_free(spm); 15279 sal_free(scm); 15280 return rv; 15281 } 15282 15283 rv = soc_profile_mem_get(unit, _bcm_tr3_service_cos_map_profile[unit], 15284 scm_index * scm_entries_per_set, 15285 scm_entries_per_set, scm_entries); 15286 if (!(rv == SOC_E_NOT_FOUND || rv == SOC_E_NONE)) { 15287 sal_free(spm); 15288 sal_free(scm); 15289 return rv; 15290 } 15291 15292 q_offset = soc_mem_field32_get(unit, SERVICE_PORT_MAPm, 15293 &spm[port], SERVICE_PORT_OFFSETf); 15294 if (0 == q_offset) { 15295 sal_free(spm); 15296 sal_free(scm); 15297 return BCM_E_NOT_FOUND; 15298 } 15299 15300 for (i = 0; i < _BCM_TR3_NUM_L2_UC_LEAVES; i++) { 15301 if (node->in_use && (node->hw_index == (q_offset + qptr))) { 15302 *queue_group = node->gport; 15303 break; 15304 } 15305 node++; 15306 } 15307 if (i == _BCM_TR3_NUM_L2_UC_LEAVES) { 15308 sal_free(spm); 15309 sal_free(scm); 15310 return BCM_E_NOT_FOUND; 15311 } 15312 15313 *array_count = array_max > scm_entries_per_set? scm_entries_per_set : 15314 array_max; 15315 for (i = 0; i < *array_count; i++) { 15316 if (priority_array[i] >= 16) { 15317 sal_free(spm); 15318 sal_free(scm); 15319 return BCM_E_PARAM; 15320 } 15321 cosq_array[i] = soc_mem_field32_get(unit,SERVICE_COS_MAPm, 15322 &scm[priority_array[i]],SERVICE_COS_OFFSETf); 15323 } 15324 sal_free(spm); 15325 sal_free(scm); 15326 return BCM_E_NONE; 15327 } 15328 15329 /* 15330 * Function: 15331 * bcm_tr3_cosq_service_map_clear 15332 * Purpose: 15333 * Clear the mapping from port, classifier, and internal priorities 15334 * to COS queues in a queue group. 15335 * Parameters: 15336 * unit - (IN) Unit number. 15337 * port - (IN) Local port ID 15338 * classifier_id - (IN) Classifier ID 15339 * Returns: 15340 * BCM_E_xxx 15341 */ 15342 int 15343 bcm_tr3_cosq_service_map_clear( 15344 int unit, 15345 bcm_gport_t port, 15346 int classifier_id) 15347 { 15348 service_queue_map_entry_t sqm; 15349 int spm_entries_per_set = 128; 15350 int scm_entries_per_set = 16; 15351 int spm_index; 15352 uint32 newspm_index; 15353 int scm_index; 15354 int vid; 15355 int valid_entry; 15356 int q_ptr = 0; 15357 int oldq_ptr = 0; 15358 service_port_map_entry_t *spm; 15359 void *spm_entries[1]; 15360 int i = 0; 15361 int rv = 0; 15362 int offset_valid = 0; 15363 int port_offset = 0 ; 15364 int q_offset = 0; 15365 int classifier_in_use; 15366 int diffserv; 15367 15368 vid = _BCM_COSQ_CLASSIFIER_SERVICE_GET(classifier_id); 15369 15370 BCM_IF_ERROR_RETURN(soc_mem_read(unit, SERVICE_QUEUE_MAPm, MEM_BLOCK_ANY, 15371 (int)vid, &sqm)); 15372 15373 valid_entry = soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, &sqm, VALIDf); 15374 if (!valid_entry) { 15375 return BCM_E_NONE; /* service queue is already cleared */ 15376 } 15377 15378 if (soc_property_get(unit, spn_SERVICE_QUEUE_DYNAMIC_CONFIG, FALSE) == FALSE) { 15379 /* spn_SERVICE_QUEUE_DYNAMIC_CONFIG=FALSE, Default behavior */ 15380 #if 0 15381 qptr = soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, &sqm, SERVICE_QUEUE_PTRf); 15382 #endif 15383 spm_index = soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, &sqm, 15384 SERVICE_PORT_PROFILE_INDEXf); 15385 scm_index = soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, &sqm, 15386 SERVICE_COS_PROFILE_INDEXf); 15387 15388 /* allocate space for service port map profile */ 15389 spm = sal_alloc(sizeof(service_port_map_entry_t) * 15390 spm_entries_per_set, 15391 "SERVICE_PORT_MAP temp Mem"); 15392 if (spm == NULL) { 15393 return BCM_E_MEMORY; 15394 } 15395 sal_memset(spm, 0, 15396 sizeof(service_port_map_entry_t) * spm_entries_per_set); 15397 spm_entries[0] = spm; 15398 15399 rv = soc_profile_mem_get(unit, _bcm_tr3_service_port_map_profile[unit], 15400 spm_index * spm_entries_per_set, 15401 spm_entries_per_set, spm_entries); 15402 if (!(rv == SOC_E_NOT_FOUND || rv == SOC_E_NONE)) { 15403 sal_free(spm); 15404 return BCM_E_NOT_FOUND; 15405 } 15406 15407 soc_mem_field32_set(unit, SERVICE_PORT_MAPm,&spm[port], 15408 SERVICE_PORT_OFFSETf, 0); 15409 15410 classifier_in_use = 0; 15411 for (i = 0; i < spm_entries_per_set; i++) { 15412 if (soc_mem_field32_get(unit, SERVICE_PORT_MAPm, 15413 &spm[i], SERVICE_PORT_OFFSETf)) { 15414 classifier_in_use = 1; 15415 break; 15416 } 15417 } 15418 15419 /* delete the spm porfile */ 15420 rv = soc_profile_mem_delete(unit, 15421 _bcm_tr3_service_port_map_profile[unit], 15422 spm_index * spm_entries_per_set); 15423 if (rv != SOC_E_NONE) { 15424 goto cleanup; 15425 } 15426 15427 if (classifier_in_use) { 15428 rv = soc_profile_mem_add(unit, _bcm_tr3_service_port_map_profile[unit], 15429 spm_entries,spm_entries_per_set, 15430 &newspm_index); 15431 if (rv != SOC_E_NONE) { 15432 goto cleanup; 15433 } 15434 15435 soc_mem_field32_set(unit, SERVICE_QUEUE_MAPm, &sqm, 15436 SERVICE_PORT_PROFILE_INDEXf, 15437 newspm_index / spm_entries_per_set); 15438 } 15439 else { 15440 /* delete the scm profile */ 15441 rv = soc_profile_mem_delete(unit, 15442 _bcm_tr3_service_cos_map_profile[unit], 15443 scm_index * scm_entries_per_set); 15444 if (rv != SOC_E_NONE) { 15445 goto cleanup; 15446 } 15447 sal_memset(&sqm, 0, sizeof(service_queue_map_entry_t)); 15448 } 15449 } else { 15450 /* spn_SERVICE_QUEUE_DYNAMIC_CONFIG=TRUE, Behavior with dynamic configuration */ 15451 spm_index = soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, &sqm, 15452 SERVICE_PORT_PROFILE_INDEXf); 15453 newspm_index = spm_index; 15454 scm_index = soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, &sqm, 15455 SERVICE_COS_PROFILE_INDEXf); 15456 15457 oldq_ptr = soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, &sqm, SERVICE_QUEUE_PTRf); 15458 /* allocate space for service port map profile */ 15459 spm = sal_alloc(sizeof(service_port_map_entry_t) * 15460 spm_entries_per_set, 15461 "SERVICE_PORT_MAP temp Mem"); 15462 if (spm == NULL) { 15463 return BCM_E_MEMORY; 15464 } 15465 sal_memset(spm, 0, 15466 sizeof(service_port_map_entry_t) * spm_entries_per_set); 15467 spm_entries[0] = spm; 15468 15469 rv = soc_profile_mem_get(unit, _bcm_tr3_service_port_map_profile[unit], 15470 spm_index * spm_entries_per_set, 15471 spm_entries_per_set, spm_entries); 15472 if (!(rv == SOC_E_NOT_FOUND || rv == SOC_E_NONE)) { 15473 sal_free(spm); 15474 return BCM_E_NOT_FOUND; 15475 } 15476 15477 port_offset = soc_mem_field32_get(unit, SERVICE_PORT_MAPm, &spm[port], 15478 SERVICE_PORT_OFFSETf); 15479 if (SOC_INFO(unit).port_uc_cosq_base[port]>=0) { 15480 diffserv = (SOC_INFO(unit).port_uc_cosq_base[port] - oldq_ptr) & 0x3ff; 15481 soc_mem_field32_set(unit, SERVICE_PORT_MAPm, &spm[port], 15482 SERVICE_PORT_OFFSETf, 15483 diffserv); 15484 } else { 15485 soc_mem_field32_set(unit, SERVICE_PORT_MAPm,&spm[port], 15486 SERVICE_PORT_OFFSETf, 0); 15487 } 15488 #ifdef DEBUG_TR3_COSQ 15489 soc_cm_print("%d:: old_offset=%d new_offset=0x%x \r\n", 15490 __LINE__, port_offset, 15491 soc_mem_field32_get(unit, SERVICE_PORT_MAPm, &spm[port], 15492 SERVICE_PORT_OFFSETf)); 15493 #endif 15494 if (port_offset == 1) { /* Removing first entry ? */ 15495 int lowest_offset = spm_entries_per_set * 8; /* Set to invalid range */ 15496 int found = 0; 15497 for (i = 0; i < spm_entries_per_set; i++) { 15498 15499 /* We need not iterate beyond Max Ports */ 15500 if ( i >= ((SOC_MAX_NUM_PP_PORTS > SOC_MAX_NUM_PORTS ? 15501 SOC_MAX_NUM_PP_PORTS : SOC_MAX_NUM_PORTS)) ) { 15502 /* This check is reqd. for partial builds, as MAX_PORTS can be 15503 less than depth of SERVICE_PORT_MAPm (128) */ 15504 /* coverity[dead_error_line] */ 15505 break; 15506 } 15507 15508 q_offset = soc_mem_field32_get(unit, SERVICE_PORT_MAPm, &spm[i], 15509 SERVICE_PORT_OFFSETf); 15510 diffserv = 15511 (SOC_INFO(unit).port_uc_cosq_base[i] - oldq_ptr) & 0x3ff; 15512 15513 if (q_offset && diffserv && (q_offset != diffserv)) { 15514 if (q_offset < lowest_offset) { 15515 lowest_offset = q_offset; 15516 q_ptr = oldq_ptr + lowest_offset - port_offset; 15517 found = 1; 15518 } 15519 } 15520 } 15521 15522 15523 #ifdef DEBUG_TR3_COSQ 15524 soc_cm_print("%d:: found=%d, lowest_os=%d, q_ptr=0x%x, old_ptr=0x%x\r\n", 15525 __LINE__, found, lowest_offset, q_ptr, oldq_ptr); 15526 #endif 15527 /* Found leftover port(s) ? */ 15528 if (found) { 15529 lowest_offset--; /* adjust by one */ 15530 offset_valid = 1; 15531 for (i = 0; i < spm_entries_per_set; i++) { 15532 q_offset = soc_mem_field32_get(unit, 15533 SERVICE_PORT_MAPm, &spm[i], 15534 SERVICE_PORT_OFFSETf); 15535 if (q_offset) { 15536 /* Adjust offsets */ 15537 soc_mem_field32_set(unit, SERVICE_PORT_MAPm, &spm[i], 15538 SERVICE_PORT_OFFSETf, 15539 ((q_offset - lowest_offset) & 0x3FF)); 15540 } 15541 } 15542 } 15543 else { 15544 /* No more ports ??? */ 15545 15546 /* Clear out SQM */ 15547 sal_memset(&sqm,0, sizeof(service_queue_map_entry_t)); 15548 15549 /* Write back updated buffer. */ 15550 rv = soc_mem_write(unit, SERVICE_QUEUE_MAPm, MEM_BLOCK_ALL, 15551 (int)vid, &sqm); 15552 15553 /* Remove SPM */ 15554 rv = soc_profile_mem_delete(unit, 15555 _bcm_tr3_service_port_map_profile[unit], 15556 spm_index * spm_entries_per_set); 15557 15558 /* delete the scm profile (profile refcount is decremented and 15559 is deleted when refcount is 0) */ 15560 rv = soc_profile_mem_delete(unit, 15561 _bcm_tr3_service_cos_map_profile[unit], 15562 scm_index * scm_entries_per_set); 15563 15564 goto cleanup; 15565 } 15566 } 15567 else { 15568 /* No need to adjust offsets since port w/base-q-pttr still exists ? */ 15569 for (i = 0; i < spm_entries_per_set; i++) { 15570 q_offset = soc_mem_field32_get(unit, SERVICE_PORT_MAPm, &spm[i], 15571 SERVICE_PORT_OFFSETf); 15572 diffserv = 15573 (SOC_INFO(unit).port_uc_cosq_base[i] - oldq_ptr) & 0x3ff; 15574 15575 if (q_offset && diffserv && (q_offset != diffserv)) { 15576 offset_valid = 1; 15577 break; 15578 } 15579 } 15580 } 15581 15582 #ifdef DEBUG_TR3_COSQ 15583 soc_cm_print("%d:: offset_valid=%d, spm_index=%d \r\n", __LINE__, offset_valid, spm_index); 15584 #endif 15585 if(offset_valid) { 15586 /* 15587 * Update sequence 15588 * a. Add new SPM. 15589 * b. Update SQM->SPM_Index to new SPM 15590 * c. Clear old SPM. 15591 */ 15592 rv = soc_profile_mem_add(unit, _bcm_tr3_service_port_map_profile[unit], 15593 spm_entries,spm_entries_per_set, 15594 &newspm_index); 15595 newspm_index = newspm_index / spm_entries_per_set; 15596 if (rv != SOC_E_NONE) { 15597 goto cleanup; 15598 } 15599 soc_mem_field32_set(unit, SERVICE_QUEUE_MAPm, &sqm, 15600 SERVICE_PORT_PROFILE_INDEXf, 15601 newspm_index); 15602 if (port_offset == 1 ) { 15603 soc_mem_field32_set(unit, SERVICE_QUEUE_MAPm, &sqm, 15604 SERVICE_QUEUE_PTRf, (q_ptr & 0x3FF)); 15605 } 15606 15607 rv = soc_mem_write(unit, SERVICE_QUEUE_MAPm, MEM_BLOCK_ALL, 15608 (int)vid, &sqm); 15609 if (!rv && (spm_index != newspm_index)) 15610 { 15611 /* delete the spm porfile */ 15612 rv = soc_profile_mem_delete(unit, 15613 _bcm_tr3_service_port_map_profile[unit], 15614 spm_index * spm_entries_per_set); 15615 } 15616 goto cleanup; 15617 } 15618 } /* spn_SERVICE_QUEUE_DYNAMIC_CONFIG */ 15619 /* Write back updated buffer. */ 15620 rv = soc_mem_write(unit, SERVICE_QUEUE_MAPm, MEM_BLOCK_ALL, 15621 (int)vid, &sqm); 15622 15623 cleanup: 15624 sal_free(spm); 15625 return rv; 15626 } 15627 15628 #define IFP_COS_MAP_MAX_ENTRIES 16 15629 int 15630 bcm_tr3_cosq_classifier_id_get(int unit, bcm_cosq_classifier_t *classifier, 15631 int array_count, 15632 bcm_cos_t *priority_array, 15633 bcm_cos_queue_t *cosq_array, 15634 int *classifier_id) 15635 { 15636 int rv = BCM_E_NONE; 15637 ifp_cos_map_entry_t *ent_buf = NULL; 15638 int field_width; 15639 uint32 index; 15640 void *entries[1]; 15641 15642 if (array_count > IFP_COS_MAP_MAX_ENTRIES) { 15643 return (BCM_E_PARAM); 15644 } 15645 15646 ent_buf = sal_alloc(sizeof(ifp_cos_map_entry_t) * IFP_COS_MAP_MAX_ENTRIES, 15647 "IFP_COS_MAP entry"); 15648 if (ent_buf == NULL) { 15649 return (BCM_E_MEMORY); 15650 } 15651 15652 field_width = soc_mem_field_length(unit, IFP_COS_MAPm, IFP_COSf); 15653 sal_memset(ent_buf, 0, sizeof(ifp_cos_map_entry_t) * IFP_COS_MAP_MAX_ENTRIES); 15654 entries[0] = ent_buf; 15655 15656 for (index = 0; index < array_count; index++) { 15657 if (priority_array[index] < IFP_COS_MAP_MAX_ENTRIES) { 15658 if (cosq_array[index] >= (1 << field_width)) { 15659 sal_free(ent_buf); 15660 return BCM_E_PARAM; 15661 } 15662 soc_mem_field32_set(unit, IFP_COS_MAPm, &ent_buf[priority_array[index]], 15663 IFP_COSf, cosq_array[index]); 15664 } 15665 } 15666 15667 rv = soc_profile_mem_search(unit, _bcm_tr3_ifp_cos_map_profile[unit], 15668 entries, IFP_COS_MAP_MAX_ENTRIES, &index); 15669 if (rv == SOC_E_EXISTS) { 15670 _BCM_COSQ_CLASSIFIER_FIELD_SET(*classifier_id,index ); 15671 rv = BCM_E_NONE; 15672 } else { 15673 rv = BCM_E_NOT_FOUND; 15674 } 15675 15676 sal_free(ent_buf); 15677 return rv; 15678 } 15679 /* 15680 * Function: 15681 * bcm_td_cosq_cpu_cosq_enable_set 15682 * Purpose: 15683 * To enable/disable Rx of packets on the specified CPU cosq. 15684 * Parameters: 15685 * unit - (IN) Unit number. 15686 * cosq - (IN) CPU Cosq ID 15687 * enable - (IN) Enable/Disable 15688 * Returns: 15689 * BCM_E_xxx 15690 */ 15691 int 15692 bcm_tr3_cosq_cpu_cosq_enable_set( 15693 int unit, 15694 bcm_cos_queue_t cosq, 15695 int enable) 15696 { 15697 return BCM_E_UNAVAIL; 15698 } 15699 15700 /* 15701 * Function: 15702 * bcm_td_cosq_cpu_cosq_enable_get 15703 * Purpose: 15704 * To get enable/disable status on Rx of packets on the specified CPU cosq. 15705 * Parameters: 15706 * unit - (IN) Unit number. 15707 * cosq - (IN) CPU Cosq ID 15708 * enable - (OUT) Enable/Disable 15709 * Returns: 15710 * BCM_E_xxx 15711 */ 15712 int 15713 bcm_tr3_cosq_cpu_cosq_enable_get( 15714 int unit, 15715 bcm_cos_queue_t cosq, 15716 int *enable) 15717 { 15718 return BCM_E_UNAVAIL; 15719 } 15720 15721 int 15722 bcm_tr3_switch_qcn_mac_set(int unit, bcm_switch_control_t type, 15723 soc_mem_t mem,soc_field_t field, void* entry, 15724 uint32 mac_field) 15725 { 15726 bcm_mac_t mac; 15727 sal_memset(mac, 0, sizeof(bcm_mac_t)); 15728 soc_mem_mac_addr_get(unit, mem, entry, 15729 field, mac); 15730 switch(type) { 15731 case bcmSwitchCongestionCnmSrcMacNonOui: 15732 mac[3] = (uint8) (mac_field >> 16 & 0xff); 15733 mac[4] = (uint8) (mac_field >> 8 & 0xff); 15734 mac[5] = (uint8) (mac_field & 0xff); 15735 break; 15736 case bcmSwitchCongestionCnmSrcMacOui: 15737 mac[0] = (uint8) (mac_field >> 16 & 0xff); 15738 mac[1] = (uint8) (mac_field >> 8 & 0xff); 15739 mac[2] = (uint8) (mac_field & 0xff); 15740 break; 15741 default : 15742 return BCM_E_PARAM; 15743 } 15744 soc_mem_mac_addr_set(unit, mem, entry, 15745 field, mac); 15746 return BCM_E_NONE; 15747 } 15748 int 15749 bcm_tr3_switch_qcn_mac_get(int unit, bcm_switch_control_t type, 15750 soc_mem_t mem,soc_field_t field, void* entry, 15751 uint32 *mac_field) 15752 { 15753 bcm_mac_t mac; 15754 soc_mem_mac_addr_get(unit, mem, entry, 15755 field, mac); 15756 switch (type) { 15757 case bcmSwitchCongestionCnmSrcMacNonOui: 15758 *mac_field = ((mac[3] << 16) | (mac[4] << 8) | (mac[5] << 0)); 15759 break; 15760 case bcmSwitchCongestionCnmSrcMacOui: 15761 *mac_field = ((mac[0] << 16) | (mac[1] << 8) | (mac[2] << 0)); 15762 break; 15763 default : 15764 return BCM_E_PARAM; 15765 } 15766 return BCM_E_NONE; 15767 } 15768 /* 15769 * Function: 15770 * _bcm_tr3_port_enqueue_set 15771 * Purpose: 15772 * Enable or Disable the enqueing the packets to the port 15773 * Parameters: 15774 * unit - (IN) unit number 15775 * gport - (IN) gport of the port 15776 * enable - (IN) TRUE to enable 15777 * FALSE to disable 15778 * Returns: 15779 * BCM_E_XXX 15780 */ 15781 15782 int 15783 _bcm_tr3_port_enqueue_set(int unit, bcm_port_t gport, 15784 int enable) 15785 { 15786 uint64 rval64, rval64_tmp; 15787 int mmu_port, phy_port, i; 15788 int rv = BCM_E_NONE; 15789 bcm_port_t local_port; 15790 soc_info_t *si; 15791 soc_reg_t reg_tmp; 15792 soc_reg_t reg[2] = { 15793 OUTPUT_PORT_RX_ENABLE0_64r, 15794 INPUT_PORT_RX_ENABLE_64r 15795 }; 15796 int max_reg = 2; 15797 15798 BCM_IF_ERROR_RETURN 15799 (_bcm_tr3_cosq_localport_resolve(unit, gport, &local_port)); 15800 15801 si = &SOC_INFO(unit); 15802 15803 phy_port = si->port_l2p_mapping[local_port]; 15804 mmu_port = si->port_p2m_mapping[phy_port]; 15805 15806 COMPILER_64_ZERO(rval64); 15807 COMPILER_64_ZERO(rval64_tmp); 15808 15809 /* Disable enqueue to the port */ 15810 for (i = 0; i < max_reg; i++) { 15811 reg_tmp = reg[i]; 15812 15813 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg_tmp, REG_PORT_ANY, 0, &rval64)); 15814 15815 if (mmu_port < 32) { 15816 COMPILER_64_SET(rval64_tmp, 0, 1 << mmu_port); 15817 } else { 15818 COMPILER_64_SET(rval64_tmp, 1 << (mmu_port - 32), 0); 15819 } 15820 if (!enable) { 15821 COMPILER_64_NOT(rval64_tmp); 15822 COMPILER_64_AND(rval64, rval64_tmp); 15823 } else { 15824 COMPILER_64_OR(rval64, rval64_tmp); 15825 } 15826 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg_tmp, REG_PORT_ANY, 0, rval64)); 15827 } 15828 return rv; 15829 } 15830 15831 /* 15832 * Function: 15833 * _bcm_tr3_port_tx_set 15834 * Purpose: 15835 * Enable or Disable the enqueing the packets to the port 15836 * Parameters: 15837 * unit - (IN) unit number 15838 * gport - (IN) gport of the port 15839 * enable - (IN) TRUE to enable 15840 * FALSE to disable 15841 * Returns: 15842 * BCM_E_XXX 15843 */ 15844 int 15845 _bcm_tr3_port_tx_set(int unit, bcm_port_t gport, int enable) 15846 { 15847 uint64 rval64, rval64_tmp; 15848 int mmu_port, phy_port; 15849 int rv = BCM_E_NONE; 15850 bcm_port_t local_port; 15851 soc_info_t *si; 15852 soc_reg_t reg = OUTPUT_PORT_RX_ENABLE0_64r; 15853 15854 BCM_IF_ERROR_RETURN 15855 (_bcm_tr3_cosq_localport_resolve(unit, gport, &local_port)); 15856 15857 si = &SOC_INFO(unit); 15858 15859 phy_port = si->port_l2p_mapping[local_port]; 15860 mmu_port = si->port_p2m_mapping[phy_port]; 15861 15862 COMPILER_64_ZERO(rval64); 15863 COMPILER_64_ZERO(rval64_tmp); 15864 15865 /* Disable enqueue to the port */ 15866 15867 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, REG_PORT_ANY, 0, &rval64)); 15868 15869 if (mmu_port < 32) { 15870 COMPILER_64_SET(rval64_tmp, 0, 1 << mmu_port); 15871 } else { 15872 COMPILER_64_SET(rval64_tmp, 1 << (mmu_port - 32), 0); 15873 } 15874 if (!enable) { 15875 COMPILER_64_NOT(rval64_tmp); 15876 COMPILER_64_AND(rval64, rval64_tmp); 15877 } else { 15878 COMPILER_64_OR(rval64, rval64_tmp); 15879 } 15880 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, REG_PORT_ANY, 0, rval64)); 15881 15882 return rv; 15883 } 15884 15885 /* 15886 * Function: 15887 * _bcm_tr3_port_enqueue_get 15888 * Purpose: 15889 * Getting the enqueing state of the port 15890 * Parameters: 15891 * unit - (IN) unit number 15892 * gport - (IN) gport of the port 15893 * enable - (IN) TRUE to enable 15894 * FALSE to disable 15895 * Returns: 15896 * BCM_E_XXX 15897 */ 15898 15899 int 15900 _bcm_tr3_port_enqueue_get(int unit, bcm_port_t gport, 15901 int *enable) 15902 { 15903 uint64 rval64; 15904 int mmu_port, phy_port, i; 15905 int rv = BCM_E_NONE; 15906 bcm_port_t local_port; 15907 soc_info_t *si; 15908 soc_reg_t reg_tmp; 15909 soc_reg_t reg[2] = { 15910 OUTPUT_PORT_RX_ENABLE0_64r, 15911 INPUT_PORT_RX_ENABLE_64r 15912 }; 15913 int max_reg = 2; 15914 15915 BCM_IF_ERROR_RETURN 15916 (_bcm_tr3_cosq_localport_resolve(unit, gport, &local_port)); 15917 15918 si = &SOC_INFO(unit); 15919 15920 phy_port = si->port_l2p_mapping[local_port]; 15921 mmu_port = si->port_p2m_mapping[phy_port]; 15922 15923 COMPILER_64_ZERO(rval64); 15924 15925 /* Disable enqueue to the port */ 15926 for (i = 0; i < max_reg; i++) { 15927 reg_tmp = reg[i]; 15928 15929 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg_tmp, REG_PORT_ANY, 0, &rval64)); 15930 15931 if (COMPILER_64_BITTEST(rval64 , mmu_port)) { 15932 *enable = TRUE; 15933 } else { 15934 *enable = FALSE; 15935 } 15936 } 15937 return rv; 15938 } 15939 #endif /* BCM_TRIUMPH3_SUPPORT */ 15940