cosq.c (774658B)
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 #include <shared/bsl.h> 11 #include <sal/core/libc.h> 12 #include <soc/defs.h> 13 #if defined(BCM_KATANA2_SUPPORT) 14 #include <soc/drv.h> 15 #include <soc/scache.h> 16 #include <soc/katana.h> 17 #include <soc/katana2.h> 18 #include <soc/profile_mem.h> 19 #include <soc/macutil.h> 20 #ifdef BCM_CMICM_SUPPORT 21 #include <soc/cmicm.h> 22 #endif 23 #include <soc/saber2.h> 24 #if defined(BCM_METROLITE_SUPPORT) 25 #include <soc/metrolite.h> 26 #endif 27 28 #include <bcm/error.h> 29 #include <bcm/cosq.h> 30 #include <bcm_int/esw/mbcm.h> 31 #include <bcm_int/esw/firebolt.h> 32 #include <bcm_int/esw/katana.h> 33 #include <bcm_int/esw/katana2.h> 34 #include <bcm_int/esw/stack.h> 35 #include <bcm_int/esw/cosq.h> 36 #include <bcm_int/esw_dispatch.h> 37 #include <bcm_int/esw/subport.h> 38 #include <bcm_int/esw/trx.h> 39 #include <bcm_int/esw/oob.h> 40 #include <bcm_int/esw/link.h> 41 #include <bcm/types.h> 42 43 #ifdef BCM_WARM_BOOT_SUPPORT 44 #include <bcm_int/esw/switch.h> 45 #endif /* BCM_WARM_BOOT_SUPPORT */ 46 47 #if defined(BCM_KATANA2_SUPPORT) 48 #include <soc/katana2.h> 49 #include <bcm_int/esw/multicast.h> 50 #endif 51 52 #define KT2_CELL_FIELD_MAX (SOC_IS_SABER2(unit) ? \ 53 0xffff : 0x3ffff) 54 55 /* MMU cell size in bytes */ 56 #define _BCM_KT2_COSQ_CELLSIZE 192 57 #define _BCM_KT2_COSQ_EXT_CELLSIZE (SOC_IS_SABER2(unit) ? \ 58 _BCM_KT2_COSQ_EXT_PACKING_CELLSIZE :_BCM_KT2_COSQ_CELLSIZE * 4) 59 #define _BCM_KT2_COSQ_EXT_PACKING_CELLSIZE _BCM_KT2_COSQ_CELLSIZE * 15 60 #define _BCM_KT2_MAX_PRIORITY_GROUPS 8 61 62 #define _BCM_KT2_NUM_UCAST_QUEUE_GROUP 8 63 #define _BCM_KT2_NUM_VLAN_UCAST_QUEUE_GROUP 16 64 #define _BCM_KT2_NUM_INTERNAL_PRI 16 65 #define _BCM_KT2_NUM_PFC_CLASS 8 66 #define _BCM_KT2_NUM_SAFC_CLASS 16 67 #define _SOC_KT2_COSQ_MAX_INDEX_S0 128 68 #define _SOC_KT2_COSQ_MAX_INDEX_S1 256 69 70 #if defined (BCM_SABER2_SUPPORT) 71 #define _SOC_SB2_COSQ_MAX_INDEX_S0 16 72 #endif 73 74 #if defined (BCM_METROLITE_SUPPORT) 75 #define _SOC_ML_COSQ_MAX_INDEX_S0 24 76 #endif 77 78 extern kt2_port_to_mxqblock_subports_t *kt2_port_to_mxqblock_subports[SOC_MAX_NUM_DEVICES]; 79 80 #define _BCM_KT2_COSQ_LIST_NODE_INIT(list, node) \ 81 list[node].in_use = FALSE; \ 82 list[node].wrr_in_use = 0; \ 83 list[node].wrr_mode = 0; \ 84 list[node].gport = -1; \ 85 list[node].base_index = -1; \ 86 list[node].mc_base_index = -1; \ 87 list[node].numq = 0; \ 88 list[node].hw_index = -1; \ 89 list[node].level = -1; \ 90 list[node].cosq_attached_to = -1; \ 91 list[node].num_child = 0; \ 92 list[node].first_child = 4095; \ 93 list[node].linkphy_enabled = 0; \ 94 list[node].subport_enabled = 0; \ 95 list[node].cosq_map = NULL; \ 96 list[node].parent = NULL; \ 97 list[node].sibling = NULL; \ 98 list[node].child = NULL; \ 99 list[node].local_port = -1; \ 100 list[node].wred_disabled = 0; \ 101 list[node].burst_calculation_enable = 0; \ 102 BCM_PBMP_CLEAR(list[node].fabric_pbmp); \ 103 list[node].remote_modid = -1; \ 104 list[node].fabric_modid = -1; \ 105 list[node].remote_port = -1; 106 107 #define _BCM_KT2_COSQ_NODE_INIT(node) \ 108 node->in_use = FALSE; \ 109 node->wrr_in_use = 0; \ 110 node->wrr_mode = 0; \ 111 node->gport = -1; \ 112 node->base_index = -1; \ 113 node->mc_base_index = -1; \ 114 node->numq = 0; \ 115 node->hw_index = -1; \ 116 node->level = -1; \ 117 node->cosq_attached_to = -1; \ 118 node->num_child = 0; \ 119 node->first_child = 4095; \ 120 node->linkphy_enabled = 0; \ 121 node->subport_enabled = 0; \ 122 node->wred_disabled = 0; \ 123 node->burst_calculation_enable = 0; \ 124 node->cosq_map = NULL; \ 125 node->parent = NULL; \ 126 node->sibling = NULL; \ 127 node->child = NULL; \ 128 BCM_PBMP_CLEAR(node->fabric_pbmp); \ 129 node->remote_modid = -1; \ 130 node->fabric_modid = -1; \ 131 node->remote_port = -1; 132 133 #define _BCM_KT2_LLS_DYN_CHG_REG_B 0x3FF 134 #define _BCM_SB2_LLS_DYN_CHG_REG_B 0x3F 135 #define _BCM_ML_LLS_DYN_CHG_REG_B 0xF 136 #define _BCM_KT2_LLS_DYN_CHG_REG_C 0xFFFFFFFF 137 138 #define _BCM_KT2_LB_BASE_QUEUE 0x40 139 140 typedef enum { 141 _BCM_KT2_COSQ_FC_PAUSE = 0, 142 _BCM_KT2_COSQ_FC_PFC, 143 _BCM_KT2_COSQ_FC_VOQFC, 144 _BCM_KT2_COSQ_FC_E2ECC, 145 _BCM_KT2_COSQ_FC_E2ECC_COE, 146 _BCM_KT2_COSQ_FC_SAFC 147 } _bcm_kt2_fc_type_t; 148 149 typedef enum { 150 _BCM_KT2_COSQ_DMVOQ = 0, 151 _BCM_KT2_COSQ_DPVOQ, 152 _BCM_KT2_COSQ_E2ECC_COE 153 } _bcm_kt2_voq_type_t; 154 155 156 typedef enum { 157 _BCM_KT2_COSQ_STATE_NO_CHANGE, 158 _BCM_KT2_COSQ_STATE_DISABLE, 159 _BCM_KT2_COSQ_STATE_ENABLE, 160 _BCM_KT2_COSQ_STATE_SPRI_TO_WRR, 161 _BCM_KT2_COSQ_STATE_WRR_TO_SPRI, 162 _BCM_KT2_COSQ_STATE_MAX 163 }_bcm_kt2_cosq_state_t; 164 165 typedef struct _bcm_kt2_cosq_list_s { 166 int count; 167 SHR_BITDCL *bits; 168 }_bcm_kt2_cosq_list_t; 169 170 typedef struct _bcm_kt2_cosq_port_info { 171 int q_offset; 172 int q_limit; 173 int mcq_offset; 174 int mcq_limit; 175 int uc_vlan_base; 176 }_bcm_kt2_cosq_port_info_t; 177 178 typedef struct _bcm_kt2_mmu_info_s { 179 int num_base_queues; /* Number of classical queues */ 180 int num_ext_queues; /* Number of extended queues */ 181 int qset_size; /* subscriber queue set size */ 182 int num_dmvoq_queues; /* Number of dmvoq queues */ 183 int base_dmvoq_queue; /* Base DMVOQ queue */ 184 int num_sub_queues; /* Number of subscriber queues */ 185 int base_sub_queue; /* Base subscriber queue */ 186 uint32 num_queues; /* total number of queues */ 187 uint32 num_nodes; /* max number of sched nodes */ 188 uint32 max_nodes[_BCM_KT2_COSQ_NODE_LEVEL_MAX];/* max nodes in each level */ 189 bcm_gport_t *l1_gport_pair; /* L1 gport mapping for dynamic update */ 190 _bcm_kt2_cosq_port_info_t *port; /* port information */ 191 _bcm_kt2_cosq_list_t global_qlist; /* list of extended queues */ 192 _bcm_kt2_cosq_list_t l2_global_qlist; /* list of extended queues */ 193 _bcm_kt2_cosq_list_t dmvoq_qlist; /* list of dmvoq queues */ 194 _bcm_kt2_cosq_list_t sched_list; /* list of sched nodes */ 195 _bcm_kt2_cosq_list_t sub_qlist; /* list of subscriber queues */ 196 _bcm_kt2_cosq_list_t sub_mcqlist; /* list of multicast subscriber queues */ 197 _bcm_kt2_cosq_list_t sched_hw_list[_BCM_KT2_COSQ_NODE_LEVEL_MAX]; 198 /* list of sched hw list */ 199 _bcm_kt2_cosq_list_t l2_base_qlist; 200 /* list of l2 base uc queue index list */ 201 _bcm_kt2_cosq_list_t l2_base_mcqlist; 202 /* list of l2 base mc queue index list */ 203 _bcm_kt2_cosq_list_t l2_dmvoq_qlist; 204 /* list of l2 dmvoq queue index list */ 205 _bcm_kt2_cosq_list_t l2_sub_qlist; 206 /* list of l2 subscriber queue index list */ 207 _bcm_kt2_cosq_list_t l2_sub_mcqlist; 208 /* list of l2 multicast subscriber queue index list */ 209 _bcm_kt2_cosq_node_t *sched_node; 210 /* sched nodes */ 211 _bcm_kt2_cosq_node_t *queue_node; 212 /* queue nodes */ 213 int curr_merger_index[4]; 214 uint32 intf_ref_cnt[BCM_MULTICAST_PORT_MAX]; /* Interface reference count 215 for queues */ 216 }_bcm_kt2_mmu_info_t; 217 218 219 typedef struct _pfc_port_support_s { 220 int supported; 221 /* if PFC is supported for given port will be true*/ 222 int mmu_port; 223 int index1;/*index in to PFC_ST_TBL for given port*/ 224 int index2;/*index in to PFC_ST_TBL for given port*/ 225 }_pfc_port_support_t; 226 _pfc_port_support_t kt2_pfc_support[KT2_MAX_LOGICAL_PORTS] = { 227 {0, -1, -1, -1}, 228 {1, 0, 0, 1}, 229 {0, -1, -1, -1}, 230 {0, -1, -1, -1}, 231 {0, -1, -1, -1}, 232 {1, 1, 2, 3}, 233 {0, -1, -1, -1}, 234 {0, -1, -1, -1}, 235 {0, -1, -1, -1}, 236 {1, 2, 4, 5}, 237 {0, -1, -1, -1}, 238 {0, -1, -1, -1}, 239 {0, -1, -1, -1}, 240 {1, 3, 6, 7}, 241 {0, -1, -1, -1}, 242 {0, -1, -1, -1}, 243 {0, -1, -1, -1}, 244 {1, 4, 8, 9}, 245 {0, -1, -1, -1}, 246 {0, -1, -1, -1}, 247 {0, -1, -1, -1}, 248 {1, 5, 10, 11}, 249 {0, -1, -1, -1}, 250 {0, -1, -1, -1}, 251 {0, -1, -1, -1}, 252 {1, 6, 12, 13}, 253 {1, 8, 16, 17}, 254 {1, 10, 20, 21}, 255 {1, 12, 24, 25}, 256 {0, -1, -1, -1}, 257 {1, 13, 26, 27}, 258 {0, -1, -1, -1}, 259 {0, -1, -1, -1}, 260 {1, 11, 22, 23}, 261 {0, -1, -1, -1}, 262 {0, -1, -1, -1}, 263 {1, 7, 14, 15}, 264 {0, -1, -1, -1}, 265 {0, -1, -1, -1}, 266 {1, 9, 18, 19}, 267 {0, -1, -1, -1}, 268 {0, -1, -1, -1} 269 }; 270 271 #ifdef BCM_SABER2_SUPPORT 272 _pfc_port_support_t sb2_pfc_support[SB2_MAX_LOGICAL_PORTS] = { 273 {0, -1, -1, -1}, 274 {1, 0, 0, 1,}, 275 {1, 1, 2, 3}, 276 {1, 2, 4, 5}, 277 {1, 3, 6, 7}, 278 {1, 4, 8, 9}, 279 {1, 5, 10, 11}, 280 {1, 6, 12, 13}, 281 {1, 7, 14, 15}, 282 {1, 8, 16, 17}, 283 {0, -1, -1, -1}, 284 {0, -1, -1, -1}, 285 {0, -1, -1, -1}, 286 {1, 9, 18, 19}, 287 {0, -1, -1, -1}, 288 {0, -1, -1, -1}, 289 {0, -1, -1, -1}, 290 {1, 10, 20, 21}, 291 {0, -1, -1, -1}, 292 {0, -1, -1, -1}, 293 {0, -1, -1, -1}, 294 {1, 11, 22, 23}, 295 {1, 12, 24, 25}, 296 {1, 13, 26, 27}, 297 {1, 14, 28, 29}, 298 {1, 15, 30, 31}, 299 {1, 16, 32, 33}, 300 {1, 17, 34, 35}, 301 {1, 18, 36, 37}, 302 {0, -1, -1, -1} 303 }; 304 #endif 305 #ifdef BCM_METROLITE_SUPPORT 306 _pfc_port_support_t ml_pfc_support[ML_MAX_LOGICAL_PORTS] = { 307 {0, -1, -1, -1}, 308 {1, 0, 0, 1,}, 309 {1, 1, 2, 3}, 310 {1, 2, 4, 5}, 311 {1, 3, 6, 7}, 312 {1, 4, 8, 9}, 313 {1, 5, 10, 11}, 314 {1, 6, 12, 13}, 315 {1, 7, 14, 15}, 316 {1, 8, 16, 17}, 317 {1, 9, 18, 19}, 318 {1, 10,20, 21}, 319 {1, 11,22, 23}, 320 {0, -1, -1, -1} 321 }; 322 #endif 323 324 STATIC _bcm_kt2_mmu_info_t *_bcm_kt2_mmu_info[BCM_MAX_NUM_UNITS]; 325 326 STATIC soc_profile_mem_t *_bcm_kt2_cos_map_profile[BCM_MAX_NUM_UNITS]; 327 STATIC soc_profile_mem_t *_bcm_kt2_egr_cos_map_profile[BCM_MAX_NUM_UNITS]; 328 STATIC soc_profile_mem_t *_bcm_kt2_wred_profile[BCM_MAX_NUM_UNITS]; 329 STATIC soc_profile_mem_t *_bcm_kt2_ifp_cos_map_profile[BCM_MAX_NUM_UNITS]; 330 STATIC soc_profile_reg_t *_bcm_kt2_llfc_profile[BCM_MAX_NUM_UNITS]; 331 332 /* Number of COSQs configured for this device */ 333 STATIC int _bcm_kt2_num_cosq[SOC_MAX_NUM_DEVICES]; 334 335 STATIC int num_pp_ports[BCM_MAX_NUM_UNITS]; 336 STATIC int num_port_schedulers[BCM_MAX_NUM_UNITS]; 337 338 STATIC int num_s0_schedulers[BCM_MAX_NUM_UNITS]; 339 STATIC int num_s1_schedulers[BCM_MAX_NUM_UNITS]; 340 STATIC int num_l0_schedulers[BCM_MAX_NUM_UNITS]; 341 STATIC int num_l1_schedulers[BCM_MAX_NUM_UNITS]; 342 STATIC int num_total_schedulers[BCM_MAX_NUM_UNITS]; 343 344 STATIC int num_l2_queues[BCM_MAX_NUM_UNITS]; 345 STATIC int max_l1_shaper_bucket[BCM_MAX_NUM_UNITS]; 346 STATIC int max_l2_shaper_bucket[BCM_MAX_NUM_UNITS]; 347 STATIC soc_mem_t l2_shaper_memory[BCM_MAX_NUM_UNITS][4]; 348 STATIC uint8 pg_profile_refcount[BCM_MAX_NUM_UNITS][4]; 349 STATIC int soc_max_num_pp_ports[BCM_MAX_NUM_UNITS]; 350 351 STATIC int 352 _bcm_kt2_cosq_packing_mode_get(int unit, int index, int *set); 353 354 STATIC int 355 _bcm_kt2_subport_cosq_config_set(int unit, int numq); 356 int 357 _bcm_kt2_cosq_subport_get(int unit, bcm_gport_t sched_gport, 358 int *pp_port); 359 STATIC int 360 _bcm_kt2_cosq_cpu_fc_set(int unit); 361 362 STATIC int 363 _bcm_kt2_cosq_dynamic_thresh_enable_get(int unit, 364 bcm_gport_t gport, bcm_cos_queue_t cosq, 365 bcm_cosq_control_t type, int *arg); 366 367 STATIC int 368 _bcm_kt2_cosq_child_node_at_input(_bcm_kt2_cosq_node_t *node, int cosq, 369 _bcm_kt2_cosq_node_t **child_node); 370 371 STATIC int 372 _bcm_kt2_init_all_queue_counters(int unit); 373 374 extern sal_mutex_t cosq_sync_lock[SOC_MAX_NUM_DEVICES]; 375 376 /* Function: 377 * _bcm_kt2_cosq_source_intf_set 378 * Purpose: 379 * Function to set the SRC_INTF table and 380 * return the index 381 * Parameters: 382 * unit - (IN) unit number 383 * src_modid - (IN) source module ID 384 * src_port_num - (IN) source port number 385 * Returns: 386 * BCM_E_XXX 387 */ 388 389 STATIC int 390 _bcm_kt2_cosq_source_intf_set(int unit, bcm_port_t src_modid, 391 bcm_port_t src_port_num, _bcm_kt2_voq_type_t type) 392 { 393 int index, free_index = -1; 394 uint32 rval, modid = 0, port_num = 0, valid; 395 396 for (index = 0; index < SOC_REG_NUMELS(unit, SRC_INTFr); index++) { 397 modid=0; 398 port_num=0; 399 BCM_IF_ERROR_RETURN(READ_SRC_INTFr(unit, index, &rval)); 400 valid = soc_reg_field_get(unit, SRC_INTFr, rval, SRC_MODID_VALIDf); 401 if (1 == valid) { 402 modid = soc_reg_field_get(unit, SRC_INTFr, rval, SOURCEf); 403 if (src_modid == modid) { 404 return index; 405 } 406 } 407 valid = soc_reg_field_get(unit, SRC_INTFr, rval, SRC_PORT_NUM_VALIDf); 408 if (1 == valid) { 409 port_num = soc_reg_field_get(unit, SRC_INTFr, rval, SOURCEf); 410 if (src_port_num == port_num) { 411 return index; 412 } 413 } 414 if ((port_num == 0) && (modid == 0) && 415 (free_index == -1)) { 416 free_index = index; 417 } 418 } 419 if (free_index == -1) { 420 return BCM_E_RESOURCE; 421 } 422 423 rval = 0; 424 if ((type == _BCM_KT2_COSQ_DMVOQ) || 425 (type == _BCM_KT2_COSQ_DPVOQ)) { 426 soc_reg_field_set(unit, SRC_INTFr, &rval, SRC_MODID_VALIDf, 1); 427 soc_reg_field_set(unit, SRC_INTFr, &rval, SOURCEf, src_modid); 428 if (type != _BCM_KT2_COSQ_DPVOQ) { 429 if (SOC_IS_SABER2(unit)) { 430 if (SOC_IS_METROLITE(unit)) { 431 soc_reg_field_set(unit, SRC_INTFr, &rval, IF_IDf, 0); 432 } else { 433 soc_reg_field_set(unit, SRC_INTFr, &rval, IF_IDf, 434 free_index > 1 ? 0 :free_index); 435 } 436 } else { 437 soc_reg_field_set(unit, SRC_INTFr, &rval, IF_IDf, 438 free_index > 3 ? 0 :free_index); 439 } 440 } 441 } else if (type == _BCM_KT2_COSQ_E2ECC_COE) { 442 soc_reg_field_set(unit, SRC_INTFr, &rval, SRC_PORT_NUM_VALIDf, 1); 443 soc_reg_field_set(unit, SRC_INTFr, &rval, SOURCEf, src_port_num); 444 } else { 445 return BCM_E_PARAM; 446 } 447 448 BCM_IF_ERROR_RETURN(WRITE_SRC_INTFr(unit, free_index, rval)); 449 450 return free_index; 451 } 452 453 /* Function: 454 * _bcm_kt2_cosq_source_intf_profile_get 455 * Purpose: 456 * Function to get the SRC_INTF table and match with SOURCE field 457 * return the IF_ID 458 * Parameters: 459 * unit - (IN) unit number 460 * src_modid - (IN) source module ID 461 * src_port_num - (IN) source port number 462 * type - (IN) voq type 463 * Returns: 464 * profile_index 465 */ 466 467 468 STATIC int 469 _bcm_kt2_cosq_source_intf_profile_get(int unit, bcm_port_t src_modid, 470 bcm_port_t src_port_num, _bcm_kt2_voq_type_t type) 471 { 472 int index = -1; 473 int profile_id = -1; 474 uint32 rval, modid = 0, port_num = 0, valid; 475 476 for (index = 0; index < 16; index++) { 477 modid=0; 478 port_num=0; 479 BCM_IF_ERROR_RETURN(READ_SRC_INTFr(unit, index, &rval)); 480 valid = soc_reg_field_get(unit, SRC_INTFr, rval, SRC_MODID_VALIDf); 481 if (1 == valid) { 482 modid = soc_reg_field_get(unit, SRC_INTFr, rval, SOURCEf); 483 if (src_modid == modid) { 484 profile_id = soc_reg_field_get(unit, SRC_INTFr, rval, IF_IDf); 485 break; 486 } 487 } 488 valid = soc_reg_field_get(unit, SRC_INTFr, rval, SRC_PORT_NUM_VALIDf); 489 if (1 == valid) { 490 port_num = soc_reg_field_get(unit, SRC_INTFr, rval, SOURCEf); 491 if (src_port_num == port_num) { 492 profile_id = soc_reg_field_get(unit, SRC_INTFr, rval, IF_IDf); 493 break; 494 } 495 } 496 } 497 return profile_id; 498 } 499 500 /* 501 * Function: 502 * _bcm_kt2_cosq_map_fc_status_to_node 503 * Purpose: 504 * Function will fill the appropriate indexes and SEL 505 * in MMU_INTFI_FC_MAP_TBL as per the table requirement 506 * Parameters: 507 * unit - (IN) unit number 508 * fct - (IN) type is PFC/VOQ 509 * hw_index - (IN) hw_index of the queue 510 * level - (IN) Node level L2/L1/L0 511 * Returns: 512 * BCM_E_XXX 513 */ 514 515 STATIC int 516 _bcm_kt2_cosq_map_fc_status_to_node(int unit, _bcm_kt2_fc_type_t fct, 517 uint32 hw_index, int level, uint32 base_offset ) 518 { 519 int map_entry_index, eindex, pfc; 520 uint32 map_entry[SOC_MAX_MEM_WORDS]; 521 static const soc_field_t self[] = { 522 SEL0f, SEL1f 523 }; 524 static const soc_field_t indexf[] = { 525 INDEX0f, INDEX1f 526 }; 527 static const soc_mem_t mem[] = { 528 INVALIDm, 529 MMU_INTFI_FC_MAP_TBL0m, 530 MMU_INTFI_FC_MAP_TBL1m, 531 MMU_INTFI_FC_MAP_TBL2m 532 }; 533 if ((fct == _BCM_KT2_COSQ_FC_PFC) || 534 (fct == _BCM_KT2_COSQ_FC_SAFC)) { 535 pfc = 1; 536 }else { 537 pfc = 0; 538 } 539 540 map_entry_index = hw_index / 16; 541 eindex = (hw_index % 16) / 8; 542 BCM_IF_ERROR_RETURN 543 (soc_mem_read(unit, mem[level], MEM_BLOCK_ALL, map_entry_index, &map_entry)); 544 soc_mem_field32_set(unit, mem[level], &map_entry, 545 indexf[eindex], base_offset); 546 soc_mem_field32_set(unit, mem[level], &map_entry, self[eindex], pfc); 547 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem[level], 548 MEM_BLOCK_ALL, map_entry_index, &map_entry)); 549 return BCM_E_NONE; 550 } 551 552 /* 553 * Function: 554 * _bcm_kt2_cosq_localport_resolve 555 * Purpose: 556 * Resolve GRPOT if it is a local port 557 * Parameters: 558 * unit - (IN) unit number 559 * gport - (IN) GPORT identifier 560 * local_port - (OUT) local port number 561 * Returns: 562 * BCM_E_XXX 563 */ 564 int 565 _bcm_kt2_cosq_localport_resolve(int unit, bcm_gport_t gport, 566 bcm_port_t *local_port) 567 { 568 bcm_module_t module; 569 bcm_port_t port; 570 bcm_trunk_t trunk; 571 int id/*, result*/; 572 573 if (!BCM_GPORT_IS_SET(gport)) { 574 if (!SOC_PORT_VALID_RANGE(unit, gport)) { 575 return BCM_E_PORT; 576 } 577 *local_port = gport; 578 return BCM_E_NONE; 579 } else if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 580 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) || 581 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport) || 582 BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(gport) || 583 BCM_GPORT_IS_SCHEDULER(gport)) { 584 return BCM_E_PORT; 585 } 586 587 BCM_IF_ERROR_RETURN 588 (_bcm_esw_gport_resolve(unit, gport, &module, &port, &trunk, &id)); 589 590 BCM_IF_ERROR_RETURN 591 (_bcm_kt2_modport_to_pp_port_get(unit, module, port, &port)); 592 593 *local_port = port; 594 595 return BCM_E_NONE; 596 } 597 598 /* 599 * Function: 600 * _bcm_kt2_cosq_node_get 601 * Purpose: 602 * Get internal information of queue group or scheduler type GPORT 603 * Parameters: 604 * unit - (IN) unit number 605 * gport - (IN) queue group/scheduler GPORT identifier 606 * modid - (OUT) module identifier 607 * port - (OUT) port number 608 * id - (OUT) queue group or scheduler identifier 609 * node - (OUT) node structure for the specified GPORT 610 * Returns: 611 * BCM_E_XXX 612 */ 613 STATIC int 614 _bcm_kt2_cosq_node_get(int unit, bcm_gport_t gport, bcm_module_t *modid, 615 bcm_port_t *port, int *id, _bcm_kt2_cosq_node_t **node) 616 { 617 _bcm_kt2_mmu_info_t *mmu_info; 618 _bcm_kt2_cosq_node_t *node_base; 619 bcm_module_t modid_out = 0; 620 bcm_port_t port_out = 0; 621 uint32 encap_id = 0; 622 int index; 623 624 625 if (_bcm_kt2_mmu_info[unit] == NULL) { 626 return BCM_E_INIT; 627 } 628 629 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 630 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid_out)); 631 port_out = BCM_GPORT_UCAST_QUEUE_GROUP_SYSPORTID_GET(gport); 632 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 633 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid_out)); 634 port_out = BCM_GPORT_MCAST_QUEUE_GROUP_SYSPORTID_GET(gport); 635 } else if (BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) { 636 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid_out)); 637 port_out = BCM_GPORT_DESTMOD_QUEUE_GROUP_SYSPORTID_GET(gport); 638 } else if (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport)) { 639 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid_out)); 640 port_out = BCM_GPORT_UCAST_SUBSCRIBER_QUEUE_GROUP_SYSPORTID_GET(gport); 641 } else if (BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(gport)) { 642 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid_out)); 643 port_out = BCM_GPORT_MCAST_SUBSCRIBER_QUEUE_GROUP_SYSPORTID_GET(gport); 644 } else if (BCM_GPORT_IS_SCHEDULER(gport)) { 645 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid_out)); 646 port_out = BCM_GPORT_SCHEDULER_GET(gport) & 0xff; 647 } else if (BCM_GPORT_IS_LOCAL(gport)) { 648 encap_id = BCM_GPORT_LOCAL_GET(gport); 649 port_out = encap_id; 650 } else if (BCM_GPORT_IS_MODPORT(gport)) { 651 encap_id = BCM_GPORT_MODPORT_PORT_GET(gport); 652 port_out = encap_id; 653 } else if (BCM_GPORT_IS_SUBPORT_PORT(gport)) { 654 encap_id = BCM_GPORT_SUBPORT_PORT_GET(gport); 655 port_out = encap_id; 656 } else { 657 return BCM_E_PORT; 658 } 659 660 mmu_info = _bcm_kt2_mmu_info[unit]; 661 662 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 663 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 664 encap_id = (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) ? 665 BCM_GPORT_UCAST_QUEUE_GROUP_QID_GET(gport) : 666 BCM_GPORT_MCAST_QUEUE_GROUP_QID_GET(gport); 667 index = encap_id; 668 node_base = mmu_info->queue_node; 669 } else if (BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) { 670 encap_id = BCM_GPORT_DESTMOD_QUEUE_GROUP_QID_GET(gport); 671 index = encap_id; 672 if (mmu_info->num_dmvoq_queues > 0) { 673 index += mmu_info->base_dmvoq_queue; 674 } 675 node_base = mmu_info->queue_node; 676 } else if (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport) || 677 BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(gport)) { 678 encap_id = (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport)) ? 679 BCM_GPORT_UCAST_SUBSCRIBER_QUEUE_GROUP_QID_GET(gport): 680 BCM_GPORT_MCAST_SUBSCRIBER_QUEUE_GROUP_QID_GET(gport); 681 682 index = encap_id; 683 if (mmu_info->num_sub_queues > 0) { 684 if (BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(gport)) { 685 index += (mmu_info->base_sub_queue + mmu_info->num_queues/2); 686 } else { 687 index += mmu_info->base_sub_queue; 688 } 689 } 690 node_base = mmu_info->queue_node; 691 } 692 else { 693 if (BCM_GPORT_IS_SCHEDULER(gport)) { 694 /* scheduler */ 695 encap_id = (BCM_GPORT_SCHEDULER_GET(gport) >> 8) & 0x7ff; 696 if (encap_id == 0) { 697 encap_id = (BCM_GPORT_SCHEDULER_GET(gport) & 0xff); 698 } 699 } 700 index = encap_id; 701 if (index >= num_total_schedulers[unit]) { 702 return BCM_E_PORT; 703 } 704 node_base = mmu_info->sched_node; 705 } 706 707 if (soc_feature(unit, soc_feature_discontinuous_pp_port)) { 708 /* 709 * Get S1 node from extended sched list if pp_port is reused 710 */ 711 if (BCM_GPORT_IS_SUBPORT_PORT(gport) && 712 _SOC_IS_PP_PORT_LINKPHY_SUBTAG(unit, index) && 713 (index <= num_port_schedulers[unit])) { 714 index += SOC_INFO(unit).cpu_hg_pp_port_index; 715 } 716 } 717 718 if (!(BCM_GPORT_IS_LOCAL(gport) || BCM_GPORT_IS_MODPORT(gport)) && 719 node_base[index].numq == 0) { 720 return BCM_E_NOT_FOUND; 721 } 722 723 if (modid != NULL) { 724 *modid = modid_out; 725 } 726 if (port != NULL) { 727 *port = port_out; 728 } 729 if (id != NULL) { 730 *id = encap_id; 731 } 732 if (node != NULL) { 733 *node = &node_base[index]; 734 } 735 736 return BCM_E_NONE; 737 } 738 739 STATIC int 740 _bcm_kt2_voq_base_node_get(int unit, int modid, int fabric_modid, 741 _bcm_kt2_cosq_node_t **node) 742 { 743 _bcm_kt2_mmu_info_t *mmu_info; 744 _bcm_kt2_cosq_node_t *node_base; 745 int index; 746 *node = NULL; 747 mmu_info = _bcm_kt2_mmu_info[unit]; 748 node_base = mmu_info->queue_node; 749 mmu_info = _bcm_kt2_mmu_info[unit]; 750 for(index = 0 ; 751 index < mmu_info->num_queues ; index++) { 752 if ((node_base[index].remote_modid == modid) && 753 (node_base[index].fabric_modid == fabric_modid)) { 754 *node = &node_base[index]; 755 break; 756 } 757 } 758 return BCM_E_NONE; 759 } 760 /* 761 * Function: 762 * _bcm_kt2_node_index_get 763 * Purpose: 764 * Allocate free index from the given list 765 * Parameters: 766 * unit - (IN) unit number 767 * list - (IN) bit list 768 * start - (IN) start index 769 * end - (IN) end index 770 * qset - (IN) size of queue set 771 * range - (IN) range bits 772 * id - (OUT) start index 773 * Returns: 774 * BCM_E_XXX 775 */ 776 STATIC int 777 _bcm_kt2_node_index_get(int unit, SHR_BITDCL *list, int start, int end, 778 int qset, int range, int *id) 779 { 780 int i, j, inc; 781 _bcm_kt2_mmu_info_t *mmu_info; 782 783 if (_bcm_kt2_mmu_info[unit] == NULL) { 784 return BCM_E_INIT; 785 } 786 mmu_info = _bcm_kt2_mmu_info[unit]; 787 *id = -1; 788 789 if (range != qset) { 790 inc = 1; 791 for (i = start; i < end; i = (i + inc)) { 792 inc = 1; 793 for (j = i; j < (i + range); j++, inc++) { 794 if (SHR_BITGET(list, j) != 0) { 795 break; 796 } 797 } 798 799 if ((j == (i + range)) && (mmu_info->intf_ref_cnt[i] == 0)) { 800 *id = i; 801 return BCM_E_NONE; 802 } 803 } 804 if (i == end) { 805 return BCM_E_RESOURCE; 806 } 807 } 808 809 for (i = start; i < end; i = i + range) { 810 for (j = i; j < (i + range); j++) { 811 if (SHR_BITGET(list, j) != 0) { 812 break; 813 } 814 } 815 816 if ((j == (i + range)) && (mmu_info->intf_ref_cnt[i] == 0)) { 817 *id = i; 818 return BCM_E_NONE; 819 } 820 } 821 822 if (i == end) { 823 return BCM_E_RESOURCE; 824 } 825 826 return BCM_E_NONE; 827 } 828 829 /* 830 * Function: 831 * _bcm_kt2_node_index_set 832 * Purpose: 833 * Mark indices as allocated 834 * Parameters: 835 * list - (IN) bit list 836 * start - (IN) start index 837 * range - (IN) range bits 838 * Returns: 839 * BCM_E_XXX 840 */ 841 STATIC int 842 _bcm_kt2_node_index_set(_bcm_kt2_cosq_list_t *list, int start, int range) 843 { 844 list->count += range; 845 SHR_BITSET_RANGE(list->bits, start, range); 846 847 return BCM_E_NONE; 848 } 849 850 /* 851 * Function: 852 * _bcm_kt2_node_index_clear 853 * Purpose: 854 * Mark indices as free 855 * Parameters: 856 * list - (IN) bit list 857 * start - (IN) start index 858 * range - (IN) range bits 859 * Returns: 860 * BCM_E_XXX 861 */ 862 STATIC int 863 _bcm_kt2_node_index_clear(_bcm_kt2_cosq_list_t *list, int start, int range) 864 { 865 list->count -= range; 866 SHR_BITCLR_RANGE(list->bits, start, range); 867 868 return BCM_E_NONE; 869 } 870 871 /* 872 * Function: 873 * _bcm_kt2_cosq_map_index_get 874 * Purpose: 875 * Allocate free index from the given list 876 * Parameters: 877 * list - (IN) bit list 878 * start - (IN) start index 879 * end - (IN) end index 880 * id - (OUT) start index 881 * Returns: 882 * BCM_E_XXX 883 */ 884 STATIC int 885 _bcm_kt2_cosq_map_index_get(SHR_BITDCL *list, int start, int end, int *id) 886 { 887 int i; 888 889 for (i = start; i < end; i++) { 890 if (SHR_BITGET(list, i) != 0) { 891 continue; 892 } 893 *id = i; 894 return BCM_E_NONE; 895 } 896 897 return BCM_E_RESOURCE; 898 } 899 900 /* 901 * Function: 902 * _bcm_kt2_cosq_map_index_set 903 * Purpose: 904 * Mark indices as allocated 905 * Parameters: 906 * list - (IN) bit list 907 * start - (IN) start index 908 * range - (IN) range bits 909 * Returns: 910 * BCM_E_XXX 911 */ 912 STATIC int 913 _bcm_kt2_cosq_map_index_set(SHR_BITDCL *list, int start, int range) 914 { 915 SHR_BITSET_RANGE(list, start, range); 916 return BCM_E_NONE; 917 } 918 919 /* 920 * Function: 921 * _bcm_kt2_cosq_map_index_clear 922 * Purpose: 923 * Mark indices as free 924 * Parameters: 925 * list - (IN) bit list 926 * start - (IN) start index 927 * range - (IN) range bits 928 * Returns: 929 * BCM_E_XXX 930 */ 931 STATIC int 932 _bcm_kt2_cosq_map_index_clear(SHR_BITDCL *list, int start, int range) 933 { 934 if (list != NULL) { 935 SHR_BITCLR_RANGE(list, start, range); 936 } 937 return BCM_E_NONE; 938 } 939 940 /* 941 * Function: 942 * _bcm_kt2_cosq_map_index_is_set 943 * Purpose: 944 * Check index is allocated 945 * Parameters: 946 * list - (IN) bit list 947 * index - (IN) index 948 * Returns: 949 * BCM_E_XXX 950 */ 951 STATIC int 952 _bcm_kt2_cosq_map_index_is_set(SHR_BITDCL *list, int index) 953 { 954 if (SHR_BITGET(list, index) != 0) { 955 return TRUE; 956 } 957 958 return FALSE; 959 } 960 961 STATIC int 962 _bcm_kt2_cosq_max_nodes_get(int unit, _bcm_kt2_cosq_node_level_t level, 963 int *id) 964 { 965 _bcm_kt2_mmu_info_t *mmu_info; 966 967 if (level < _BCM_KT2_COSQ_NODE_LEVEL_ROOT || 968 level >= _BCM_KT2_COSQ_NODE_LEVEL_MAX) { 969 return BCM_E_PARAM; 970 } 971 mmu_info = _bcm_kt2_mmu_info[unit]; 972 *id = mmu_info->max_nodes[level]; 973 974 return BCM_E_NONE; 975 } 976 977 typedef struct _bcm_kt2_lls_info_s { 978 int node_count[_BCM_KT2_COSQ_NODE_LEVEL_MAX]; 979 uint32 *min_entries[_BCM_KT2_COSQ_NODE_LEVEL_MAX]; 980 uint32 *max_entries[_BCM_KT2_COSQ_NODE_LEVEL_MAX]; 981 uint32 *max_burst_entries[_BCM_KT2_COSQ_NODE_LEVEL_MAX]; 982 uint32 *min_burst_entries[_BCM_KT2_COSQ_NODE_LEVEL_MAX]; 983 } _bcm_kt2_lls_info_t; 984 985 /* Max 1G rate to expedite draining packets during congestion */ 986 #define _BCM_KT2_COSQ_MAX_FLUSH_RATE 1000000 987 988 STATIC int 989 _bcm_kt2_cosq_lls_shapers_remove(int unit, int port, 990 _bcm_kt2_cosq_node_t *node, 991 _bcm_kt2_lls_info_t *lls_tree) 992 { 993 int alloc_size, speed; 994 _bcm_kt2_cosq_node_t *cur_node, *parent; 995 uint32 *min_entries, *max_entries, *min_burst_entries, *max_burst_entries; 996 uint32 max_shaper, min, max, flags, burst_max, burst_min; 997 uint32 burst, mode; 998 int count = 0; 999 int num_entries = 0; 1000 1001 parent = node->parent; 1002 if ((parent == NULL) && 1003 (node->level != _BCM_KT2_COSQ_NODE_LEVEL_ROOT)) { 1004 return BCM_E_INTERNAL; 1005 } 1006 1007 num_entries = (node->level != _BCM_KT2_COSQ_NODE_LEVEL_ROOT) ? 1008 parent->num_child : 1; 1009 1010 /* Allocate memory based on child nodes */ 1011 alloc_size = sizeof(uint32) * num_entries; 1012 lls_tree->min_entries[node->level] = sal_alloc(alloc_size, "lls_war_buf"); 1013 lls_tree->max_entries[node->level] = sal_alloc(alloc_size, "lls_war_buf"); 1014 lls_tree->max_burst_entries[node->level] = sal_alloc(alloc_size, "lls_war_buf"); 1015 lls_tree->min_burst_entries[node->level] = sal_alloc(alloc_size, "lls_war_buf"); 1016 1017 min_entries = lls_tree->min_entries[node->level]; 1018 max_entries = lls_tree->max_entries[node->level]; 1019 min_burst_entries = lls_tree->min_burst_entries[node->level]; 1020 max_burst_entries = lls_tree->max_burst_entries[node->level]; 1021 1022 sal_memset(min_entries, 0, alloc_size); 1023 sal_memset(max_entries, 0, alloc_size); 1024 sal_memset(min_burst_entries, 0, alloc_size); 1025 sal_memset(max_burst_entries, 0, alloc_size); 1026 lls_tree->node_count[node->level] = num_entries; 1027 1028 /* 1029 * Reserve 10% for the node which is being flushes and 1030 * distribute remaining bandwidth across other nodes 1031 */ 1032 speed = _BCM_KT2_COSQ_MAX_FLUSH_RATE; 1033 max_shaper = ((speed * 9)/10)/lls_tree->node_count[node->level]; 1034 1035 if (node->level == _BCM_KT2_COSQ_NODE_LEVEL_ROOT) { 1036 BCM_IF_ERROR_RETURN 1037 (bcm_kt_port_rate_egress_get(unit, port, &max, &burst, &mode)); 1038 min_entries[count] = 0; 1039 max_entries[count] = max; 1040 BCM_IF_ERROR_RETURN 1041 (bcm_kt_port_rate_egress_set(unit, port, speed, burst, mode)); 1042 return BCM_E_NONE; 1043 } 1044 1045 /* store configured bandwidth of all the nodes */ 1046 for (cur_node = parent->child; cur_node != NULL; 1047 cur_node = cur_node->sibling) { 1048 BCM_IF_ERROR_RETURN 1049 (bcm_kt2_cosq_gport_bandwidth_get(unit, cur_node->gport, 0, 1050 &min, &max, &burst_min, &burst_max, &flags)); 1051 min_entries[count] = min; 1052 max_entries[count] = max; 1053 min_burst_entries[count] = burst_min; 1054 max_burst_entries[count] = burst_max; 1055 count++; 1056 if (cur_node->hw_index == node->hw_index) { 1057 BCM_IF_ERROR_RETURN 1058 (bcm_kt2_cosq_gport_bandwidth_set(unit, cur_node->gport, 0, 1059 (speed / 10), speed, flags)); 1060 } else { 1061 BCM_IF_ERROR_RETURN 1062 (bcm_kt2_cosq_gport_bandwidth_set(unit, cur_node->gport, 0, 1063 0, max_shaper, flags)); 1064 } 1065 } 1066 1067 return BCM_E_NONE; 1068 } 1069 1070 STATIC int 1071 _bcm_kt2_cosq_lls_shapers_restore(int unit, int port, 1072 _bcm_kt2_cosq_node_t *node, 1073 _bcm_kt2_lls_info_t *lls_tree) 1074 { 1075 _bcm_kt2_cosq_node_t *cur_node, *parent; 1076 uint32 *min_entries, *max_entries, *burst_max_entries, *burst_min_entries; 1077 uint32 min, max, burst_max, burst_min; 1078 uint32 burst, mode; 1079 int count = 0; 1080 1081 parent = node->parent; 1082 if ((parent == NULL) && 1083 (node->level != _BCM_KT2_COSQ_NODE_LEVEL_ROOT)) { 1084 return BCM_E_INTERNAL; 1085 } 1086 1087 min_entries = lls_tree->min_entries[node->level]; 1088 max_entries = lls_tree->max_entries[node->level]; 1089 burst_max_entries = lls_tree->max_burst_entries[node->level]; 1090 burst_min_entries = lls_tree->min_burst_entries[node->level]; 1091 1092 if (node->level == _BCM_KT2_COSQ_NODE_LEVEL_ROOT) { 1093 BCM_IF_ERROR_RETURN 1094 (bcm_kt_port_rate_egress_get(unit, port, &max, &burst, &mode)); 1095 max = max_entries[count]; 1096 BCM_IF_ERROR_RETURN 1097 (bcm_kt_port_rate_egress_set(unit, port, max, burst, mode)); 1098 return BCM_E_NONE; 1099 } 1100 1101 /* restore bandwidth */ 1102 for (cur_node = parent->child; cur_node != NULL; 1103 cur_node = cur_node->sibling) { 1104 min = min_entries[count]; 1105 max = max_entries[count]; 1106 burst_max = burst_max_entries[count]; 1107 burst_min = burst_min_entries[count]; 1108 count++; 1109 1110 BCM_IF_ERROR_RETURN 1111 (bcm_kt2_cosq_gport_bandwidth_set(unit, cur_node->gport, 0, 1112 min, max, 0)); 1113 BCM_IF_ERROR_RETURN(bcm_kt2_cosq_gport_bandwidth_burst_set(unit, 1114 cur_node->gport, 0, burst_min, burst_max)); 1115 } 1116 1117 return BCM_E_NONE; 1118 } 1119 1120 STATIC int 1121 _bcm_kt2_cosq_poll_flush_active(int unit, bcm_port_t port, 1122 _bcm_kt2_cosq_node_t *node) 1123 { 1124 soc_timeout_t timeout; 1125 int flush_active = 1; 1126 uint32 timeout_val; 1127 uint32 rval = 0; 1128 int packing_mode = 0; 1129 1130 if (soc_feature(unit, soc_feature_mmu_packing)) { 1131 BCM_IF_ERROR_RETURN 1132 (_bcm_kt2_cosq_packing_mode_get(unit, node->hw_index, &packing_mode)); 1133 1134 } 1135 if (packing_mode == 1) { 1136 timeout_val = soc_property_get(unit, spn_MMU_QUEUE_FLUSH_TIMEOUT, 1137 _BCM_COSQ_QUEUE_FLUSH_TIMEOUT_PACKING_DEFAULT); 1138 } else { 1139 1140 timeout_val = soc_property_get(unit, spn_MMU_QUEUE_FLUSH_TIMEOUT, 1141 _BCM_COSQ_QUEUE_FLUSH_TIMEOUT_DEFAULT); 1142 } 1143 soc_timeout_init(&timeout, timeout_val, 0); 1144 1145 while (flush_active) { 1146 BCM_IF_ERROR_RETURN(READ_TOQ_FLUSH0r(unit, &rval)); 1147 flush_active = soc_reg_field_get(unit, TOQ_FLUSH0r, 1148 rval, FLUSH_ACTIVEf); 1149 if (soc_timeout_check(&timeout)) { 1150 return (BCM_E_TIMEOUT); 1151 } 1152 } 1153 1154 return BCM_E_NONE; 1155 } 1156 1157 STATIC int 1158 _bcm_kt2_cosq_adjust_lls_bw(int unit, bcm_gport_t gport, 1159 _bcm_kt2_cosq_node_t *node) 1160 { 1161 int rv = BCM_E_NONE; 1162 _bcm_kt2_lls_info_t lls_tree; 1163 _bcm_kt2_cosq_node_t *cur_node; 1164 bcm_port_t port; 1165 int count = 0, i; 1166 uint32 map_entry[SOC_MAX_MEM_WORDS]; 1167 int index = 0 , eindex = 0; 1168 static const soc_field_t indexf[] = { 1169 INDEX0f, INDEX1f 1170 }; 1171 int map_offset = 0; 1172 1173 /* resolve the port */ 1174 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 1175 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) || 1176 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport) || 1177 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport) || 1178 BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(gport) || 1179 BCM_GPORT_IS_SCHEDULER(gport)) { 1180 BCM_IF_ERROR_RETURN 1181 (_bcm_kt2_cosq_node_get(unit, gport, NULL, &port, NULL, 1182 NULL)); 1183 if (node->hw_index > 0) { 1184 index = node->hw_index / 16 ; 1185 eindex = (node->hw_index % 16) / 8; 1186 BCM_IF_ERROR_RETURN 1187 (soc_mem_read(unit, MMU_INTFI_FC_MAP_TBL2m, 1188 MEM_BLOCK_ALL, index, &map_entry)); 1189 map_offset = soc_mem_field32_get(unit, MMU_INTFI_FC_MAP_TBL2m, &map_entry, 1190 indexf[eindex]); 1191 if (map_offset) { 1192 soc_mem_field32_set(unit, MMU_INTFI_FC_MAP_TBL2m, &map_entry, 1193 indexf[eindex], 0); 1194 BCM_IF_ERROR_RETURN(soc_mem_write(unit, MMU_INTFI_FC_MAP_TBL2m, 1195 MEM_BLOCK_ALL, index, &map_entry)); 1196 1197 } 1198 } 1199 } else { 1200 /* optionally validate port */ 1201 BCM_IF_ERROR_RETURN 1202 (_bcm_kt2_cosq_localport_resolve(unit, gport, &port)); 1203 if (port < 0) { 1204 return BCM_E_PORT; 1205 } 1206 } 1207 1208 sal_memset(&lls_tree, 0, sizeof(_bcm_kt2_lls_info_t)); 1209 cur_node = node; 1210 while (cur_node != NULL) { 1211 count++; 1212 rv = _bcm_kt2_cosq_lls_shapers_remove(unit, port, cur_node, &lls_tree); 1213 if (rv != BCM_E_NONE) { 1214 goto cleanup; 1215 } 1216 1217 rv = _bcm_kt2_cosq_poll_flush_active(unit, port, node); 1218 if (rv == BCM_E_NONE) { 1219 break; 1220 } else { 1221 cur_node = cur_node->parent; 1222 } 1223 } 1224 1225 cleanup: 1226 cur_node = node; 1227 for (i = 0; i < count; i++) { 1228 rv = _bcm_kt2_cosq_lls_shapers_restore(unit, port, cur_node, &lls_tree); 1229 if (rv != BCM_E_NONE) { 1230 goto cleanup; 1231 } 1232 cur_node = cur_node->parent; 1233 } 1234 if (map_offset) { 1235 soc_mem_field32_set(unit, MMU_INTFI_FC_MAP_TBL2m, &map_entry, 1236 indexf[eindex], map_offset); 1237 BCM_IF_ERROR_RETURN(soc_mem_write(unit, MMU_INTFI_FC_MAP_TBL2m, 1238 MEM_BLOCK_ALL, index, &map_entry)); 1239 1240 } 1241 for (i = _BCM_KT2_COSQ_NODE_LEVEL_ROOT; i < _BCM_KT2_COSQ_NODE_LEVEL_MAX; 1242 i++) { 1243 if (lls_tree.min_entries[i]) { 1244 sal_free(lls_tree.min_entries[i]); 1245 lls_tree.min_entries[i] = NULL; 1246 } 1247 if (lls_tree.max_entries[i]) { 1248 sal_free(lls_tree.max_entries[i]); 1249 lls_tree.max_entries[i] = NULL; 1250 } 1251 if (lls_tree.max_burst_entries[i]) { 1252 sal_free(lls_tree.max_burst_entries[i]); 1253 lls_tree.max_burst_entries[i] = NULL; 1254 } 1255 if (lls_tree.min_burst_entries[i]) { 1256 sal_free(lls_tree.min_burst_entries[i]); 1257 lls_tree.min_burst_entries[i] = NULL; 1258 } 1259 } 1260 1261 return rv; 1262 } 1263 1264 1265 /* 1266 * Function: 1267 * _bcm_kt2_cosq_alloc_clear 1268 * Purpose: 1269 * Allocate cosq memory and clear 1270 * Parameters: 1271 * size - (IN) size of memory required 1272 * description- (IN) description about the structure 1273 * Returns: 1274 * BCM_E_XXX 1275 */ 1276 STATIC void * 1277 _bcm_kt2_cosq_alloc_clear(unsigned int size, char *description) 1278 { 1279 void *block_p; 1280 1281 block_p = sal_alloc(size, description); 1282 1283 if (block_p != NULL) { 1284 sal_memset(block_p, 0, size); 1285 } 1286 1287 return block_p; 1288 } 1289 1290 /* 1291 * Function: 1292 * _bcm_kt2_cosq_free_memory 1293 * Purpose: 1294 * Free memory allocated for mmu info members 1295 * Parameters: 1296 * mmu_info_p - (IN) MMU info pointer 1297 * Returns: 1298 * BCM_E_XXX 1299 */ 1300 STATIC void 1301 _bcm_kt2_cosq_free_memory(_bcm_kt2_mmu_info_t *mmu_info_p) 1302 { 1303 int i; 1304 1305 if (mmu_info_p->port != NULL) { 1306 sal_free(mmu_info_p->port); 1307 mmu_info_p->port = NULL; 1308 } 1309 if (mmu_info_p->l1_gport_pair != NULL) { 1310 sal_free(mmu_info_p->l1_gport_pair); 1311 mmu_info_p->l1_gport_pair = NULL; 1312 } 1313 if (mmu_info_p->global_qlist.bits != NULL) { 1314 sal_free(mmu_info_p->global_qlist.bits); 1315 mmu_info_p->global_qlist.bits = NULL; 1316 } 1317 if (mmu_info_p->dmvoq_qlist.bits != NULL) { 1318 sal_free(mmu_info_p->dmvoq_qlist.bits); 1319 mmu_info_p->dmvoq_qlist.bits = NULL; 1320 } 1321 if (mmu_info_p->sched_list.bits != NULL) { 1322 sal_free(mmu_info_p->sched_list.bits); 1323 mmu_info_p->sched_list.bits = NULL; 1324 } 1325 if (mmu_info_p->sub_qlist.bits != NULL) { 1326 sal_free(mmu_info_p->sub_qlist.bits); 1327 mmu_info_p->sub_qlist.bits = NULL; 1328 } 1329 if (mmu_info_p->sub_mcqlist.bits != NULL) { 1330 sal_free(mmu_info_p->sub_mcqlist.bits); 1331 mmu_info_p->sub_mcqlist.bits = NULL; 1332 } 1333 if (mmu_info_p->l2_base_qlist.bits != NULL) { 1334 sal_free(mmu_info_p->l2_base_qlist.bits); 1335 mmu_info_p->l2_base_qlist.bits = NULL; 1336 } 1337 if (mmu_info_p->l2_base_mcqlist.bits != NULL) { 1338 sal_free(mmu_info_p->l2_base_mcqlist.bits); 1339 mmu_info_p->l2_base_mcqlist.bits = NULL; 1340 } 1341 if (mmu_info_p->l2_global_qlist.bits != NULL) { 1342 sal_free(mmu_info_p->l2_global_qlist.bits); 1343 mmu_info_p->l2_global_qlist.bits = NULL; 1344 } 1345 if (mmu_info_p->l2_dmvoq_qlist.bits != NULL) { 1346 sal_free(mmu_info_p->l2_dmvoq_qlist.bits); 1347 mmu_info_p->l2_dmvoq_qlist.bits = NULL; 1348 } 1349 if (mmu_info_p->l2_sub_qlist.bits != NULL) { 1350 sal_free(mmu_info_p->l2_sub_qlist.bits); 1351 mmu_info_p->l2_sub_qlist.bits = NULL; 1352 } 1353 if (mmu_info_p->l2_sub_mcqlist.bits != NULL) { 1354 sal_free(mmu_info_p->l2_sub_mcqlist.bits); 1355 mmu_info_p->l2_sub_mcqlist.bits = NULL; 1356 } 1357 for (i = 0; i < _BCM_KT2_COSQ_NODE_LEVEL_L2; i++) { 1358 if (mmu_info_p->sched_hw_list[i].bits != NULL) { 1359 sal_free(mmu_info_p->sched_hw_list[i].bits); 1360 mmu_info_p->sched_hw_list[i].bits = NULL; 1361 } 1362 } 1363 if (mmu_info_p->sched_node != NULL) { 1364 for (i = 0; i < mmu_info_p->num_nodes; i++) { 1365 if (((&mmu_info_p->sched_node[i]) != NULL) && 1366 ((&mmu_info_p->sched_node[i])->cosq_map != NULL)) { 1367 sal_free((&mmu_info_p->sched_node[i])->cosq_map); 1368 (&mmu_info_p->sched_node[i])->cosq_map = NULL; 1369 } 1370 } 1371 sal_free(mmu_info_p->sched_node); 1372 mmu_info_p->sched_node = NULL; 1373 } 1374 if (mmu_info_p->queue_node != NULL) { 1375 for (i = 0; i < mmu_info_p->num_queues; i++) { 1376 if (((&mmu_info_p->queue_node[i]) != NULL) && 1377 ((&mmu_info_p->queue_node[i])->cosq_map != NULL)) { 1378 sal_free((&mmu_info_p->queue_node[i])->cosq_map); 1379 (&mmu_info_p->queue_node[i])->cosq_map = NULL; 1380 } 1381 } 1382 sal_free(mmu_info_p->queue_node); 1383 mmu_info_p->queue_node = NULL; 1384 } 1385 } 1386 STATIC int 1387 _bcm_kt2_port_is_coe_linkphy(_bcm_kt2_cosq_node_t *node) 1388 { 1389 while(node != NULL) { 1390 if ((node->level == _BCM_KT2_COSQ_NODE_LEVEL_S0) || 1391 (node->level == _BCM_KT2_COSQ_NODE_LEVEL_S1)) { 1392 return TRUE; 1393 } 1394 node = node->parent; 1395 } 1396 return FALSE; 1397 } 1398 1399 /* 1400 * _bcm_is_port_linkphy_subport(int unit, int port, int min_port_index) { 1401 * 1402 * IN: 1403 * unit : 1404 * port : pp_port or physical port 1405 * min_port_index : Start of subport pp_port. This can be -1 in which case 1406 * min_port_index will be automatically fetched. 1407 * OUT: 1408 * TRUE - if port is a subport/linkphy pp_port 1409 * FALSE - if port is a physical port 1410 */ 1411 1412 STATIC int 1413 _bcm_is_port_linkphy_subport(int unit, bcm_gport_t gport, int min_port_index) 1414 { 1415 soc_info_t *si; 1416 int port, encap_id, rv; 1417 _bcm_kt2_cosq_node_t *node = NULL; 1418 1419 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 1420 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) || 1421 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport) || 1422 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport) || 1423 BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(gport) || 1424 BCM_GPORT_IS_SCHEDULER(gport)) { 1425 rv = _bcm_kt2_cosq_node_get(unit, gport, NULL, &port, &encap_id, &node); 1426 } else { 1427 rv = _bcm_kt2_cosq_localport_resolve(unit, gport, &port); 1428 encap_id = port; 1429 } 1430 1431 if (rv != BCM_E_NONE) { 1432 LOG_ERROR(BSL_LS_BCM_COMMON, 1433 (BSL_META_U(unit, 1434 "Unable to retrieve port info.\n"))); 1435 } 1436 1437 #if defined BCM_METROLITE_SUPPORT 1438 if (soc_feature(unit, soc_feature_discontinuous_pp_port)) { 1439 if ((node && (encap_id > num_port_schedulers[unit]) && (encap_id <= num_pp_ports[unit])) || 1440 _bcm_kt2_port_is_coe_linkphy(node) || 1441 (!node && (BCM_GPORT_IS_SUBPORT_PORT(gport) || 1442 _SOC_IS_PP_PORT_LINKPHY_SUBTAG(unit, port)))) { 1443 return TRUE; 1444 } 1445 } else 1446 #endif 1447 { 1448 if (min_port_index == -1) { 1449 si = &SOC_INFO(unit); 1450 min_port_index = si->pp_port_index_min; 1451 } 1452 if (port >= min_port_index) { 1453 return TRUE; 1454 } 1455 } 1456 return FALSE; 1457 } 1458 1459 int 1460 _bcm_kt2_cosq_port_resolve(int unit, bcm_gport_t gport, bcm_module_t *modid, 1461 bcm_port_t *port, bcm_trunk_t *trunk_id, int *id, 1462 int *qnum) 1463 { 1464 _bcm_kt2_cosq_node_t *node; 1465 1466 BCM_IF_ERROR_RETURN 1467 (_bcm_kt2_cosq_node_get(unit, gport, modid, port, NULL, &node)); 1468 *trunk_id = -1; 1469 1470 if (_bcm_is_port_linkphy_subport(unit, gport, num_port_schedulers[unit])) { 1471 BCM_IF_ERROR_RETURN( 1472 _bcm_kt2_pp_port_to_modport_get(unit,*port, 1473 modid, port)); 1474 } 1475 1476 if (qnum) { 1477 if (node->hw_index == -1) { 1478 return BCM_E_PARAM; 1479 } 1480 *qnum = node->hw_index; 1481 } 1482 1483 return BCM_E_NONE; 1484 } 1485 1486 /* 1487 * Function: 1488 * _bcm_kt2_cosq_gport_traverse 1489 * Purpose: 1490 * Walks through the valid COSQ GPORTs and calls 1491 * the user supplied callback function for each entry. 1492 * Parameters: 1493 * unit - (IN) unit number 1494 * gport - (IN) 1495 * cb - (IN) Callback function. 1496 * user_data - (IN) User data to be passed to callback function 1497 * Returns: 1498 * BCM_E_NONE - Success. 1499 * BCM_E_XXX 1500 */ 1501 int 1502 _bcm_kt2_cosq_gport_traverse(int unit, bcm_gport_t gport, 1503 bcm_cosq_gport_traverse_cb cb, 1504 void *user_data) 1505 { 1506 _bcm_kt2_cosq_node_t *node; 1507 bcm_port_t port, port_out; 1508 uint32 flags = BCM_COSQ_GPORT_SCHEDULER; 1509 int rv = BCM_E_NONE; 1510 bcm_module_t modid, modid_out; 1511 bcm_gport_t gport_out; 1512 1513 BCM_IF_ERROR_RETURN 1514 (_bcm_kt2_cosq_node_get(unit, gport, &modid, &port, NULL, &node)); 1515 1516 if (node != NULL) { 1517 if (node->level == _BCM_KT2_COSQ_NODE_LEVEL_L2) { 1518 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(node->gport)) { 1519 flags = BCM_COSQ_GPORT_UCAST_QUEUE_GROUP; 1520 } else if (BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) { 1521 flags = BCM_COSQ_GPORT_DESTMOD_UCAST_QUEUE_GROUP; 1522 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(node->gport)) { 1523 flags = BCM_COSQ_GPORT_MCAST_QUEUE_GROUP; 1524 } else if (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(node->gport)) { 1525 flags = BCM_COSQ_GPORT_SUBSCRIBER; 1526 } else if (BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(node->gport)) { 1527 flags = (BCM_COSQ_GPORT_SUBSCRIBER | BCM_COSQ_GPORT_MCAST_QUEUE_GROUP);; 1528 } 1529 } 1530 if (BCM_GPORT_IS_SCHEDULER(gport)) { 1531 if (node->type == _BCM_KT2_NODE_SCHEDULER_WFQ) { 1532 if (node->level == _BCM_KT2_COSQ_NODE_LEVEL_ROOT) { 1533 flags = BCM_COSQ_GPORT_SCHEDULER_WFQ; 1534 } else { 1535 flags = BCM_COSQ_GPORT_SCHEDULER_WFQ | 1536 BCM_COSQ_GPORT_SCHEDULER; 1537 } 1538 } 1539 } 1540 BCM_IF_ERROR_RETURN 1541 (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, modid, port, 1542 &modid_out, &port_out)); 1543 BCM_GPORT_MODPORT_SET(gport_out, modid_out, port_out); 1544 1545 rv = cb(unit, gport_out, node->numq, flags, 1546 node->gport, user_data); 1547 if (BCM_FAILURE(rv)) { 1548 #ifdef BCM_CB_ABORT_ON_ERR 1549 if (SOC_CB_ABORT_ON_ERR(unit)) { 1550 return rv; 1551 } 1552 #endif 1553 } 1554 } else { 1555 return BCM_E_NONE; 1556 } 1557 1558 if (node->sibling != NULL) { 1559 _bcm_kt2_cosq_gport_traverse(unit, node->sibling->gport, cb, user_data); 1560 } 1561 1562 if (node->child != NULL) { 1563 _bcm_kt2_cosq_gport_traverse(unit, node->child->gport, cb, user_data); 1564 } 1565 1566 return BCM_E_NONE; 1567 } 1568 1569 /* 1570 * Function: 1571 * _bcm_kt2_cosq_index_resolve 1572 * Purpose: 1573 * Find hardware index for the given port/cosq 1574 * Parameters: 1575 * unit - (IN) unit number 1576 * port - (IN) port number or GPORT identifier 1577 * cosq - (IN) COS queue number 1578 * style - (IN) index style (_BCM_KA_COSQ_INDEX_STYLE_XXX) 1579 * local_port - (OUT) local port number 1580 * index - (OUT) result index 1581 * count - (OUT) number of index 1582 * Returns: 1583 * BCM_E_XXX 1584 */ 1585 int 1586 _bcm_kt2_cosq_index_resolve(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 1587 _bcm_kt2_cosq_index_style_t style, 1588 bcm_port_t *local_port, int *index, int *count) 1589 { 1590 _bcm_kt2_cosq_node_t *node = NULL; 1591 _bcm_kt2_cosq_node_t *cur_node = NULL; 1592 bcm_port_t resolved_port; 1593 int resolved_index; 1594 int id, startq, numq = 0; 1595 _bcm_kt2_mmu_info_t *mmu_info; 1596 1597 if (cosq < -1) { 1598 return BCM_E_PARAM; 1599 } else if (cosq == -1) { 1600 startq = 0; 1601 } else { 1602 startq = cosq; 1603 } 1604 1605 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 1606 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) || 1607 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port) || 1608 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port) || 1609 BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(port) || 1610 BCM_GPORT_IS_SCHEDULER(port)) { 1611 BCM_IF_ERROR_RETURN 1612 (_bcm_kt2_cosq_node_get(unit, port, NULL, &resolved_port, &id, 1613 &node)); 1614 if ((node->cosq_attached_to < 0) || (node->hw_index == -1)) { 1615 /* Not resolved yet */ 1616 return BCM_E_NOT_FOUND; 1617 } 1618 if (BCM_GPORT_IS_SCHEDULER(port) && 1619 (style != _BCM_KT2_COSQ_INDEX_STYLE_BUCKET)) { 1620 numq = node->numq; 1621 if (startq >= numq) { 1622 return BCM_E_PARAM; 1623 } 1624 } else { 1625 numq = node->numq; 1626 } 1627 } else { 1628 /* optionally validate port */ 1629 BCM_IF_ERROR_RETURN 1630 (_bcm_kt2_cosq_localport_resolve(unit, port, &resolved_port)); 1631 if (resolved_port < 0) { 1632 return BCM_E_PORT; 1633 } 1634 node = NULL; 1635 numq = 0; 1636 } 1637 1638 switch (style) { 1639 case _BCM_KT2_COSQ_INDEX_STYLE_BUCKET: 1640 if (node != NULL) { 1641 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 1642 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) || 1643 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port) || 1644 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port) || 1645 BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(port)) { 1646 resolved_index = node->hw_index; 1647 } else if (BCM_GPORT_IS_SCHEDULER(port)) { 1648 if (node->level > _BCM_KT2_COSQ_NODE_LEVEL_L1) { 1649 return BCM_E_PARAM; 1650 } 1651 resolved_index = node->hw_index; 1652 } else { 1653 return BCM_E_PARAM; 1654 } 1655 } else { /* node == NULL */ 1656 mmu_info = _bcm_kt2_mmu_info[unit]; 1657 numq = mmu_info->port[resolved_port].q_limit - 1658 mmu_info->port[resolved_port].q_offset; 1659 1660 if (cosq >= numq) { 1661 return BCM_E_PARAM; 1662 } 1663 resolved_index = mmu_info->port[resolved_port].q_offset + startq; 1664 } 1665 break; 1666 1667 case _BCM_KT2_COSQ_INDEX_STYLE_WRED: 1668 if (node != NULL) { 1669 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 1670 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) || 1671 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port) || 1672 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port) || 1673 BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(port)) { 1674 resolved_index = node->hw_index; 1675 } else if (BCM_GPORT_IS_SCHEDULER(port)) { 1676 if (node->level != _BCM_KT2_COSQ_NODE_LEVEL_L1 && 1677 node->level !=_BCM_KT2_COSQ_NODE_LEVEL_L0) { 1678 return BCM_E_PARAM; 1679 } 1680 _bcm_kt2_cosq_child_node_at_input(node ,startq , 1681 &cur_node); 1682 resolved_index = cur_node->hw_index; 1683 } else { 1684 return BCM_E_PARAM; 1685 } 1686 } else { /* node == NULL */ 1687 mmu_info = _bcm_kt2_mmu_info[unit]; 1688 numq = mmu_info->port[resolved_port].q_limit - 1689 mmu_info->port[resolved_port].q_offset; 1690 1691 if (cosq >= numq) { 1692 return BCM_E_PARAM; 1693 } 1694 resolved_index = mmu_info->port[resolved_port].q_offset + startq; 1695 } 1696 break; 1697 1698 case _BCM_KT2_COSQ_INDEX_STYLE_SCHEDULER: 1699 if (node != NULL) { 1700 if (BCM_GPORT_IS_SCHEDULER(port)) { 1701 for (cur_node = node->child; cur_node != NULL; 1702 cur_node = cur_node->sibling) { 1703 if (cur_node->cosq_attached_to == startq) { 1704 break; 1705 } 1706 } 1707 1708 if (cur_node == NULL) { 1709 /* this cosq is not yet attached */ 1710 return BCM_E_INTERNAL; 1711 } 1712 if ((cur_node->type == _BCM_KT2_NODE_VOQ_ID) || 1713 (cur_node->type == _BCM_KT2_NODE_SUBSCRIBER_GPORT_ID)) { 1714 numq = node->num_child; 1715 } 1716 resolved_index = cur_node->hw_index; 1717 } else { /* unicast queue group or multicast queue group */ 1718 return BCM_E_PARAM; 1719 } 1720 } else { /* node == NULL */ 1721 mmu_info = _bcm_kt2_mmu_info[unit]; 1722 numq = mmu_info->port[resolved_port].q_limit - 1723 mmu_info->port[resolved_port].q_offset; 1724 1725 if (cosq >= numq) { 1726 return BCM_E_PARAM; 1727 } 1728 resolved_index = mmu_info->port[resolved_port].q_offset + startq; 1729 } 1730 break; 1731 case _BCM_KT2_COSQ_INDEX_STYLE_UCAST_QUEUE: 1732 mmu_info = _bcm_kt2_mmu_info[unit]; 1733 if (node != NULL) { 1734 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 1735 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) || 1736 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port) || 1737 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port) || 1738 BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(port)) { 1739 resolved_index = node->hw_index; 1740 } else if (BCM_GPORT_IS_SCHEDULER(port)) { 1741 if (node->level != _BCM_KT2_COSQ_NODE_LEVEL_L1) { 1742 return BCM_E_PARAM; 1743 } 1744 resolved_index = node->base_index; 1745 } else { 1746 return BCM_E_PARAM; 1747 } 1748 1749 if ((BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) || 1750 (!(soc_feature(unit, soc_feature_mmu_packing)) && 1751 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port))) { 1752 resolved_index -= mmu_info->port[resolved_port].q_offset; 1753 } 1754 } else { /* node == NULL */ 1755 mmu_info = _bcm_kt2_mmu_info[unit]; 1756 numq = mmu_info->port[resolved_port].q_limit - 1757 mmu_info->port[resolved_port].q_offset; 1758 1759 if (startq >= numq) { 1760 return BCM_E_PARAM; 1761 } 1762 resolved_index = startq; 1763 } 1764 break; 1765 1766 case _BCM_KT2_COSQ_INDEX_STYLE_QUEUE_REPLICATION: 1767 mmu_info = _bcm_kt2_mmu_info[unit]; 1768 if (node != NULL) { 1769 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 1770 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port) || 1771 BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(port)) { 1772 resolved_index = node->hw_index; 1773 } else { 1774 return BCM_E_PARAM; 1775 } 1776 1777 } else { /* node == NULL */ 1778 mmu_info = _bcm_kt2_mmu_info[unit]; 1779 numq = mmu_info->port[resolved_port].q_limit - 1780 mmu_info->port[resolved_port].q_offset; 1781 1782 if (startq >= numq) { 1783 return BCM_E_PARAM; 1784 } 1785 resolved_index = startq + mmu_info->port 1786 [resolved_port].q_offset; 1787 } 1788 break; 1789 1790 default: 1791 return BCM_E_INTERNAL; 1792 } 1793 1794 if (local_port != NULL) { 1795 *local_port = resolved_port; 1796 } 1797 if (index != NULL) { 1798 if (resolved_index < 0) { 1799 return BCM_E_INTERNAL; 1800 } 1801 *index = resolved_index; 1802 } 1803 if (count != NULL) { 1804 *count = (cosq == -1) ? numq : 1; 1805 } 1806 1807 return BCM_E_NONE; 1808 } 1809 /* 1810 * Function: 1811 * _bcm_kt2_cosq_get_dmvoq_index 1812 * Purpose: 1813 * This logic is to make sure that the base index is always 1814 * multiple of 8 1815 * unit - (IN) unit number 1816 * mmu_info - (IN) MMU info structure 1817 * list - (IN)list from which index need to be selected 1818 * numq - (IN) number of queues 1819 * id - (IN) START ID 1820 * limit - (IN) limit 1821 * Returns: 1822 * BCM_E_XXX 1823 */ 1824 1825 1826 STATIC int 1827 _bcm_kt2_cosq_get_dmvoq_index( 1828 int unit, 1829 _bcm_kt2_mmu_info_t *mmu_info, 1830 _bcm_kt2_cosq_list_t *list, 1831 int numq, int *id , int limit ) 1832 { 1833 while (((mmu_info->base_dmvoq_queue + *id) % 8) != 0) { 1834 *id = (*id + 8 - ((mmu_info->base_dmvoq_queue + *id) % 8)); 1835 BCM_IF_ERROR_RETURN 1836 (_bcm_kt2_node_index_get(unit, list->bits, *id, limit, 1837 mmu_info->qset_size, numq, id)); 1838 } 1839 return BCM_E_NONE; 1840 } 1841 /* 1842 * Function: 1843 * _bcm_kt2_cosq_node_resolve 1844 * Purpose: 1845 * Resolve queue number in the specified scheduler tree and its subtree 1846 * Parameters: 1847 * unit - (IN) unit number 1848 * node - (IN) node structure for the specified scheduler node 1849 * cosq - (IN) COS queue to attach to 1850 * Returns: 1851 * BCM_E_XXX 1852 */ 1853 STATIC int 1854 _bcm_kt2_cosq_node_resolve(int unit, _bcm_kt2_cosq_node_t *node, 1855 bcm_cos_queue_t cosq) 1856 { 1857 _bcm_kt2_cosq_node_t *parent; 1858 _bcm_kt2_mmu_info_t *mmu_info; 1859 _bcm_kt2_cosq_list_t *list; 1860 bcm_port_t local_port; 1861 int start_idx = 0, end_idx = 0; 1862 int base_idx; 1863 int alloc_size; 1864 int numq, id = 0, rv = BCM_E_NONE; 1865 int offset, limit; 1866 _bcm_kt2_subport_info_t info; 1867 bcm_gport_t pp_port; 1868 int dev_int_stream_id = 0; 1869 soc_pbmp_t pbmp_linkphy_one_stream_per_subport; 1870 1871 parent = node->parent; 1872 if (parent == NULL) { 1873 /* Not attached, should never happen */ 1874 return BCM_E_NOT_FOUND; 1875 } 1876 1877 if (parent->numq == 0 || parent->numq < -1) { 1878 return BCM_E_PARAM; 1879 } 1880 1881 if (parent->cosq_map == NULL) { 1882 alloc_size = SHR_BITALLOCSIZE(parent->numq); 1883 parent->cosq_map = _bcm_kt2_cosq_alloc_clear(alloc_size, 1884 "parent->cosq_map"); 1885 if (parent->cosq_map == NULL) { 1886 return BCM_E_MEMORY; 1887 } 1888 } 1889 1890 if (cosq < 0) { 1891 BCM_IF_ERROR_RETURN 1892 (_bcm_kt2_cosq_map_index_get(parent->cosq_map, 1893 0, parent->numq, &id)); 1894 BCM_IF_ERROR_RETURN 1895 (_bcm_kt2_cosq_map_index_set(parent->cosq_map, id, 1)); 1896 node->cosq_attached_to = id; 1897 } else { 1898 if (_bcm_kt2_cosq_map_index_is_set(parent->cosq_map, 1899 cosq) == TRUE) { 1900 return BCM_E_EXISTS; 1901 } 1902 BCM_IF_ERROR_RETURN 1903 (_bcm_kt2_cosq_map_index_set(parent->cosq_map, cosq, 1)); 1904 node->cosq_attached_to = cosq; 1905 } 1906 1907 mmu_info = _bcm_kt2_mmu_info[unit]; 1908 numq = (parent->wrr_mode == 0) ? ((parent->numq > 8) ? 8 : parent->numq) : 1; 1909 1910 switch (parent->level) { 1911 case _BCM_KT2_COSQ_NODE_LEVEL_ROOT: 1912 case _BCM_KT2_COSQ_NODE_LEVEL_S1: 1913 case _BCM_KT2_COSQ_NODE_LEVEL_L0: 1914 list = &mmu_info->sched_hw_list[node->level]; 1915 if (node->level == _BCM_KT2_COSQ_NODE_LEVEL_S0) { 1916 BCM_IF_ERROR_RETURN 1917 (_bcm_kt2_cosq_subport_get(unit, node->gport, &pp_port)); 1918 BCM_IF_ERROR_RETURN 1919 (bcm_kt2_subport_pp_port_subport_info_get(unit, pp_port, 1920 &info)); 1921 node->hw_index = (BCM_GPORT_SCHEDULER_GET(node->gport) >> 8); 1922 node->hw_index &= 0x7FF; 1923 if (info.port_type == _BCM_SUBPORT_COE_TYPE_LINKPHY) { 1924 /* linkphy 1925 * s0 index = stream_id/num_streams 1926 */ 1927 dev_int_stream_id = info.dev_int_stream_id[0]; 1928 1929 SOC_PBMP_CLEAR(pbmp_linkphy_one_stream_per_subport); 1930 pbmp_linkphy_one_stream_per_subport = 1931 soc_property_get_pbmp(unit, 1932 spn_PBMP_LINKPHY_ONE_STREAM_PER_SUBPORT, 0); 1933 BCM_IF_ERROR_RETURN(_bcm_kt2_cosq_node_get( 1934 unit, parent->gport, NULL, &local_port, 1935 NULL, NULL)); 1936 if (SOC_IS_METROLITE(unit) || (SOC_IS_SABER2(unit) && 1937 SOC_PBMP_MEMBER(pbmp_linkphy_one_stream_per_subport, 1938 local_port))) { 1939 node->hw_index = dev_int_stream_id; 1940 } else if (SOC_IS_SABER2(unit) && (info.num_streams == 1)) { 1941 1942 /* When num_streams is 1, only 4 subports are supported in SB2 */ 1943 if ((dev_int_stream_id % 8) > 3) { 1944 return BCM_E_PARAM; 1945 } 1946 1947 /* The following is the mapping in S1 when num_streams = 1. 1948 * S1 S0 1949 * 0 - 3 0 - 3 1950 * 8 - 11 4 - 7 1951 * 16 - 19 8 - 11 1952 * 24 - 27 12 - 15 1953 * 1954 * The formula used is (4 * (S1 / 8) + (S1 % 8)). 1955 */ 1956 node->hw_index = (4 * (dev_int_stream_id / 8)) + 1957 (dev_int_stream_id %4); 1958 1959 } else { 1960 node->hw_index = (dev_int_stream_id / info.num_streams); 1961 } 1962 /* S0 is always WRR */ 1963 node->wrr_in_use = 1; 1964 1965 } else 1966 #if defined BCM_METROLITE_SUPPORT 1967 if (soc_feature(unit, soc_feature_discontinuous_pp_port)) { 1968 if (info.port_type == _BCM_SUBPORT_COE_TYPE_SUBTAG) { 1969 BCM_IF_ERROR_RETURN 1970 (bcm_kt2_subport_pp_port_s1_index_get(unit, pp_port, &node->hw_index)); 1971 /* S0 is always WRR */ 1972 node->wrr_in_use = 1; 1973 } 1974 } else 1975 #endif 1976 { 1977 node->hw_index -= num_port_schedulers[unit]; 1978 } 1979 if (parent->base_index < 0) { 1980 parent->base_index = node->hw_index; 1981 } 1982 1983 /*for single stream cases in LINKPhy we donot need to configure S0 as 1984 S1 gets scheduled */ 1985 if (node->level == _BCM_KT2_COSQ_NODE_LEVEL_S0) { 1986 if (node->hw_index < 128){ 1987 _bcm_kt2_node_index_set(list, node->hw_index, 1); 1988 } 1989 } else { 1990 _bcm_kt2_node_index_set(list, node->hw_index, 1); 1991 } 1992 break; 1993 } 1994 if (parent->level == _BCM_KT2_COSQ_NODE_LEVEL_S1 && 1995 node->level == _BCM_KT2_COSQ_NODE_LEVEL_L0 && 1996 parent->linkphy_enabled) { 1997 /* S1 == L0 incase of linkphy */ 1998 parent->base_index = parent->hw_index; 1999 node->hw_index = parent->hw_index; 2000 break; 2001 } 2002 2003 /* Indexes from 0 to num_s1_schedulers[unit] is used for S1 nodes, 2004 remaining num_s1_schedulers[unit]++ are used for L0 and S0 */ 2005 start_idx = (node->level == _BCM_KT2_COSQ_NODE_LEVEL_L0) ? 2006 num_s1_schedulers[unit] : 0; 2007 if (soc_feature(unit, soc_feature_discontinuous_pp_port)) { 2008 start_idx = 0; 2009 } 2010 end_idx = mmu_info->max_nodes[node->level]; 2011 if (node->hw_index > 0) { 2012 if (parent->base_index < 0) { 2013 parent->base_index = node->hw_index; 2014 } 2015 } else { 2016 if ( (parent->base_index < 0) && (parent->wrr_mode == 0) ) { 2017 rv = _bcm_kt2_node_index_get(unit, list->bits, start_idx, end_idx, 2018 mmu_info->qset_size, numq, &id); 2019 if (BCM_FAILURE(rv)) { 2020 _bcm_kt2_cosq_map_index_clear(parent->cosq_map, 2021 node->cosq_attached_to, 1); 2022 node->cosq_attached_to = -1; 2023 return rv; 2024 } 2025 _bcm_kt2_node_index_set(list, id, numq); 2026 parent->base_index = id; 2027 } else if ((node->cosq_attached_to >= numq) || (parent->wrr_mode == 1)) { 2028 rv = _bcm_kt2_node_index_get(unit, list->bits, start_idx, end_idx, 2029 mmu_info->qset_size, 1, &id); 2030 if (BCM_FAILURE(rv)) { 2031 _bcm_kt2_cosq_map_index_clear(parent->cosq_map, 2032 node->cosq_attached_to, 1); 2033 node->cosq_attached_to = -1; 2034 return rv; 2035 } 2036 _bcm_kt2_node_index_set(list, id, 1); 2037 if (parent->wrr_mode == 1) { 2038 if (parent->base_index < 0 ) { 2039 parent->base_index = id; 2040 } 2041 } 2042 } 2043 } 2044 break; 2045 2046 case _BCM_KT2_COSQ_NODE_LEVEL_S0: 2047 list = &mmu_info->sched_hw_list[node->level]; 2048 if (parent->linkphy_enabled && 2049 !soc_feature(unit, soc_feature_discontinuous_pp_port)) { 2050 BCM_IF_ERROR_RETURN 2051 (_bcm_kt2_cosq_subport_get(unit, parent->gport, &pp_port)); 2052 BCM_IF_ERROR_RETURN 2053 (bcm_kt2_subport_pp_port_subport_info_get(unit, pp_port, 2054 &info)); 2055 if (node->cosq_attached_to > 1) { 2056 return BCM_E_PARAM; 2057 } 2058 if ((info.num_streams == 1) && 2059 (node->cosq_attached_to > 0)) { 2060 _bcm_kt2_cosq_map_index_clear(parent->cosq_map, 2061 node->cosq_attached_to, 1); 2062 return BCM_E_PARAM; 2063 } 2064 if (SOC_IS_SABER2(unit) && (info.num_streams == 1)) { 2065 node->hw_index = info.dev_int_stream_id[0]; 2066 } else { 2067 node->hw_index = (parent->hw_index * info.num_streams) + 2068 node->cosq_attached_to; 2069 } 2070 if (parent->base_index < 0) { 2071 parent->base_index = node->hw_index; 2072 } 2073 node->linkphy_enabled = 1; 2074 _bcm_kt2_node_index_set(list, node->hw_index, 1); 2075 } else { 2076 if (node->level != _BCM_KT2_COSQ_NODE_LEVEL_L0) { 2077 return BCM_E_PARAM; 2078 } 2079 start_idx = num_s1_schedulers[unit]; 2080 end_idx = mmu_info->max_nodes[node->level]; 2081 if (node->hw_index > 0) { 2082 if (parent->base_index < 0) { 2083 parent->base_index = node->hw_index; 2084 } 2085 } else { 2086 if ((parent->base_index < 0) && (parent->wrr_mode == 0)) { 2087 rv = _bcm_kt2_node_index_get(unit, list->bits, start_idx, end_idx, 2088 mmu_info->qset_size, numq, &id); 2089 if (BCM_FAILURE(rv)) { 2090 _bcm_kt2_cosq_map_index_clear(parent->cosq_map, 2091 node->cosq_attached_to, 1); 2092 node->cosq_attached_to = -1; 2093 return rv; 2094 } 2095 _bcm_kt2_node_index_set(list, id, numq); 2096 parent->base_index = id; 2097 } else if ((node->cosq_attached_to >= numq) || (parent->wrr_mode == 1)) { 2098 rv = _bcm_kt2_node_index_get(unit, list->bits, start_idx, end_idx, 2099 mmu_info->qset_size, 1, &id); 2100 if (BCM_FAILURE(rv)) { 2101 _bcm_kt2_cosq_map_index_clear(parent->cosq_map, 2102 node->cosq_attached_to, 1); 2103 node->cosq_attached_to = -1; 2104 return rv; 2105 } 2106 _bcm_kt2_node_index_set(list, id, 1); 2107 if (parent->wrr_mode == 1) { 2108 if (parent->base_index < 0 ) { 2109 parent->base_index = id; 2110 } 2111 } 2112 } 2113 } 2114 } 2115 break; 2116 2117 case _BCM_KT2_COSQ_NODE_LEVEL_L1: 2118 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(node->gport)) { 2119 list = &mmu_info->l2_base_qlist; 2120 local_port = BCM_GPORT_UCAST_QUEUE_GROUP_SYSPORTID_GET 2121 (node->gport); 2122 offset = mmu_info->port[local_port].q_offset; 2123 limit = mmu_info->port[local_port].q_limit; 2124 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(node->gport)) { 2125 list = &mmu_info->l2_base_mcqlist; 2126 local_port = BCM_GPORT_MCAST_QUEUE_GROUP_SYSPORTID_GET 2127 (node->gport); 2128 if (soc_feature(unit, soc_feature_mmu_packing)) { 2129 offset = mmu_info->port[local_port].mcq_offset; 2130 limit = mmu_info->port[local_port].mcq_limit; 2131 } 2132 else { 2133 offset = mmu_info->port[local_port].q_offset; 2134 limit = mmu_info->port[local_port].q_limit; 2135 } 2136 } else if (BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(node->gport)) { 2137 local_port = BCM_GPORT_DESTMOD_QUEUE_GROUP_SYSPORTID_GET 2138 (node->gport); 2139 offset = 0; 2140 if (mmu_info->num_dmvoq_queues > 0) { 2141 list = &mmu_info->l2_dmvoq_qlist; 2142 limit = mmu_info->num_dmvoq_queues; 2143 } else { 2144 list = &mmu_info->l2_global_qlist; 2145 limit = mmu_info->num_queues; 2146 } 2147 } else if (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(node->gport) || 2148 BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(node->gport)) { 2149 local_port = 2150 ((BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(node->gport)) ? 2151 BCM_GPORT_UCAST_SUBSCRIBER_QUEUE_GROUP_SYSPORTID_GET 2152 (node->gport): 2153 BCM_GPORT_MCAST_SUBSCRIBER_QUEUE_GROUP_SYSPORTID_GET 2154 (node->gport)); 2155 offset = 0; 2156 if (mmu_info->num_sub_queues > 0) { 2157 if (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(node->gport)) { 2158 list = &mmu_info->l2_sub_qlist; 2159 } else { 2160 list = &mmu_info->l2_sub_mcqlist; 2161 } 2162 limit = mmu_info->num_sub_queues; 2163 } else { 2164 list = &mmu_info->l2_global_qlist; 2165 limit = mmu_info->num_queues; 2166 } 2167 } else { 2168 list = &mmu_info->l2_global_qlist; 2169 offset = 0; 2170 limit = mmu_info->num_queues; 2171 } 2172 if (node->hw_index < 0) { 2173 if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(node->gport) && 2174 parent->mc_base_index < 0 && 2175 node->cosq_attached_to < 8) { 2176 rv = _bcm_kt2_node_index_get(unit, list->bits, offset, limit, 2177 mmu_info->qset_size, numq, &id); 2178 if (BCM_FAILURE(rv)) { 2179 _bcm_kt2_cosq_map_index_clear(parent->cosq_map, 2180 node->cosq_attached_to, 1); 2181 node->cosq_attached_to = -1; 2182 return rv; 2183 } 2184 _bcm_kt2_node_index_set(list, id, numq); 2185 parent->mc_base_index = id; 2186 node->mc_base_index = parent->mc_base_index; 2187 } else if ((BCM_GPORT_IS_UCAST_QUEUE_GROUP(node->gport)) && 2188 parent->base_index < 0 && 2189 node->cosq_attached_to < 8) { 2190 rv = _bcm_kt2_node_index_get(unit, list->bits, offset, limit, 2191 mmu_info->qset_size, numq, &id); 2192 if (BCM_FAILURE(rv)) { 2193 _bcm_kt2_cosq_map_index_clear(parent->cosq_map, 2194 node->cosq_attached_to, 1); 2195 node->cosq_attached_to = -1; 2196 return rv; 2197 } 2198 _bcm_kt2_node_index_set(list, id, numq); 2199 parent->base_index = id ; 2200 node->base_index = parent->base_index; 2201 } else if ((BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(node->gport)) && 2202 (((parent->base_index < 0) && 2203 (node->cosq_attached_to < 8)) || parent->wrr_mode == 1)) { 2204 rv = _bcm_kt2_node_index_get(unit, list->bits, offset, limit, 2205 mmu_info->qset_size, numq, &id); 2206 if (BCM_FAILURE(rv)) { 2207 _bcm_kt2_cosq_map_index_clear(parent->cosq_map, 2208 node->cosq_attached_to, 1); 2209 node->cosq_attached_to = -1; 2210 return rv; 2211 } 2212 2213 _bcm_kt2_node_index_set(list, id, numq); 2214 if (mmu_info->num_sub_queues > 0) { 2215 parent->base_index = id + mmu_info->base_sub_queue ; 2216 } else { 2217 parent->base_index = id ; 2218 } 2219 node->base_index = parent->base_index; 2220 } else if ( 2221 (BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(node->gport)) && 2222 (((parent->mc_base_index < 0) && 2223 (node->cosq_attached_to < 8)) || parent->wrr_mode == 1)) { 2224 rv = _bcm_kt2_node_index_get(unit, list->bits, offset, limit, 2225 mmu_info->qset_size, numq, &id); 2226 if (BCM_FAILURE(rv)) { 2227 _bcm_kt2_cosq_map_index_clear(parent->cosq_map, 2228 node->cosq_attached_to, 1); 2229 node->cosq_attached_to = -1; 2230 return rv; 2231 } 2232 2233 _bcm_kt2_node_index_set(list, id, numq); 2234 if (mmu_info->num_sub_queues > 0) { 2235 parent->mc_base_index = id + mmu_info->base_sub_queue ; 2236 } else { 2237 parent->mc_base_index = id; 2238 } 2239 node->mc_base_index = parent->mc_base_index; 2240 } else if (BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(node->gport) && 2241 (( parent->base_index < 0 && 2242 node->cosq_attached_to < 8) || parent->wrr_mode == 1)) { 2243 rv = _bcm_kt2_node_index_get(unit, list->bits, offset, limit, 2244 mmu_info->qset_size, numq, &id); 2245 if (BCM_FAILURE(rv)) { 2246 _bcm_kt2_cosq_map_index_clear(parent->cosq_map, 2247 node->cosq_attached_to, 1); 2248 node->cosq_attached_to = -1; 2249 return rv; 2250 } 2251 if (((mmu_info->base_dmvoq_queue + id) % 8) != 0) { 2252 BCM_IF_ERROR_RETURN 2253 (_bcm_kt2_cosq_get_dmvoq_index(unit, mmu_info, list, 2254 numq, &id, limit)); 2255 } 2256 _bcm_kt2_node_index_set(list, id, numq); 2257 if (mmu_info->num_dmvoq_queues > 0) { 2258 parent->base_index = id + mmu_info->base_dmvoq_queue ; 2259 } else { 2260 parent->base_index = id ; 2261 } 2262 node->base_index = parent->base_index; 2263 } else if (node->cosq_attached_to >= 8) { 2264 rv = _bcm_kt2_node_index_get(unit, list->bits, offset, limit, 2265 mmu_info->qset_size, 1, &id); 2266 if (BCM_FAILURE(rv)) { 2267 _bcm_kt2_cosq_map_index_clear(parent->cosq_map, 2268 node->cosq_attached_to, 1); 2269 node->cosq_attached_to = -1; 2270 return rv; 2271 } 2272 if (node->type == _BCM_KT2_NODE_VOQ) { 2273 return BCM_E_PARAM; 2274 } 2275 _bcm_kt2_node_index_set(list, id, 1); 2276 } 2277 if (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(node->gport) || 2278 BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(node->gport)) { 2279 if (mmu_info->num_sub_queues > 0 ) { 2280 id += mmu_info->base_sub_queue; 2281 } 2282 } 2283 } else { 2284 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(node->gport) || 2285 BCM_GPORT_IS_MCAST_QUEUE_GROUP(node->gport) || 2286 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(node->gport) || 2287 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(node->gport) || 2288 BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(node->gport)) { 2289 /*input 0 should be atttached first to get the correct base*/ 2290 if (node->cosq_attached_to < 8) { 2291 if ((BCM_GPORT_IS_UCAST_QUEUE_GROUP(node->gport) || 2292 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(node->gport) || 2293 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(node->gport)) && 2294 (parent->base_index < 0)) { 2295 parent->base_index = node->hw_index; 2296 } 2297 if ((BCM_GPORT_IS_MCAST_QUEUE_GROUP(node->gport) || 2298 BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(node->gport)) && 2299 (parent->mc_base_index < 0)) { 2300 parent->mc_base_index = node->hw_index; 2301 } 2302 } 2303 2304 } 2305 } 2306 break; 2307 2308 case _BCM_KT2_COSQ_NODE_LEVEL_L2: 2309 /* passthru */ 2310 default: 2311 return BCM_E_PARAM; 2312 2313 } 2314 2315 if (parent->numq <= 8) { 2316 if (parent->level <= _BCM_KT2_COSQ_NODE_LEVEL_L1) { 2317 if (node->hw_index < 0) { 2318 base_idx = 2319 (BCM_GPORT_IS_MCAST_QUEUE_GROUP(node->gport) || 2320 BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(node->gport)) ? 2321 parent->mc_base_index : parent->base_index; 2322 node->hw_index = (parent->wrr_mode == 1) ? id : base_idx + node->cosq_attached_to; 2323 } 2324 } 2325 2326 parent->num_child++; 2327 /* get the lowest cosq as a first child */ 2328 if (node->hw_index < parent->first_child) { 2329 parent->first_child = node->hw_index; 2330 } 2331 } else { 2332 if (parent->level <= _BCM_KT2_COSQ_NODE_LEVEL_L1) { 2333 if (node->hw_index < 0) { 2334 base_idx = (BCM_GPORT_IS_MCAST_QUEUE_GROUP(node->gport) || 2335 BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(node->gport)) ? 2336 parent->mc_base_index : parent->base_index; 2337 node->hw_index = (node->cosq_attached_to < numq) ? 2338 (base_idx + node->cosq_attached_to) : id; 2339 } 2340 if (node->cosq_attached_to >= numq) { 2341 node->wrr_in_use = 1; 2342 } 2343 } 2344 parent->num_child++; 2345 } 2346 2347 return BCM_E_NONE; 2348 } 2349 2350 /* 2351 * Function: 2352 * _bcm_kt2_cosq_node_unresolve 2353 * Purpose: 2354 * Unresolve queue number in the specified scheduler tree and its subtree 2355 * Parameters: 2356 * unit - (IN) unit number 2357 * node - (IN) node structure for the specified scheduler node 2358 * cosq - (IN) COS queue to attach to 2359 * Returns: 2360 * BCM_E_XXX 2361 */ 2362 STATIC int 2363 _bcm_kt2_cosq_node_unresolve(int unit, _bcm_kt2_cosq_node_t *node, 2364 bcm_cos_queue_t cosq) 2365 { 2366 _bcm_kt2_cosq_node_t *cur_node, *parent; 2367 _bcm_kt2_mmu_info_t *mmu_info; 2368 _bcm_kt2_cosq_list_t *list; 2369 uint32 map; 2370 int min_index; 2371 int id, offset, numq; 2372 int min_flag = 0; 2373 2374 if (node->cosq_attached_to < 0) { 2375 /* Has been unresolved already */ 2376 return BCM_E_NONE; 2377 } 2378 2379 parent = node->parent; 2380 2381 if (parent->numq == 0 || parent->numq < -1) { 2382 return BCM_E_PARAM; 2383 } 2384 2385 if (parent->numq <= 8) { 2386 /* find the current cosq_attached_to usage */ 2387 map = 0; 2388 if (parent->first_child == node->hw_index && node->wrr_in_use == 0) { 2389 min_flag = 1; 2390 min_index = (node->level == _BCM_KT2_COSQ_NODE_LEVEL_L2) ? 4095 : 2391 ((node->level == _BCM_KT2_COSQ_NODE_LEVEL_L1) ? 1023 : 2392 255); 2393 } else { 2394 min_index = parent->first_child; 2395 } 2396 2397 for (cur_node = parent->child; cur_node != NULL; 2398 cur_node = cur_node->sibling) { 2399 if (cur_node->cosq_attached_to >= 0) { 2400 map |= 1 << cur_node->cosq_attached_to; 2401 /* dont update the min node is not this node */ 2402 if (min_flag && cur_node->hw_index != node->hw_index) { 2403 if (cur_node->hw_index < min_index) { 2404 min_index = cur_node->hw_index; 2405 } 2406 } 2407 } 2408 } 2409 2410 if (!(map & (1 << node->cosq_attached_to))) { 2411 return BCM_E_PARAM; 2412 } 2413 2414 BCM_IF_ERROR_RETURN 2415 (_bcm_kt2_cosq_map_index_clear(parent->cosq_map, 2416 node->cosq_attached_to, 1)); 2417 parent->first_child = min_index; 2418 2419 } else { 2420 2421 /* check whether the entry is available */ 2422 for (cur_node = parent->child; cur_node != NULL; 2423 cur_node = cur_node->sibling) { 2424 if (cur_node->gport == node->gport) { 2425 break; 2426 } 2427 } 2428 2429 if (cur_node == NULL) { 2430 return BCM_E_PARAM; 2431 } 2432 BCM_IF_ERROR_RETURN 2433 (_bcm_kt2_cosq_map_index_clear(parent->cosq_map, 2434 cur_node->cosq_attached_to, 1)); 2435 } 2436 2437 mmu_info = _bcm_kt2_mmu_info[unit]; 2438 numq = (parent->wrr_mode == 0) ? ((parent->numq > 8) ? 8 : parent->numq) : 1; 2439 2440 switch (parent->level) { 2441 case _BCM_KT2_COSQ_NODE_LEVEL_ROOT: 2442 case _BCM_KT2_COSQ_NODE_LEVEL_S0: 2443 case _BCM_KT2_COSQ_NODE_LEVEL_S1: 2444 case _BCM_KT2_COSQ_NODE_LEVEL_L0: 2445 list = &mmu_info->sched_hw_list[node->level]; 2446 parent->num_child--; 2447 if ((node->level != _BCM_KT2_COSQ_NODE_LEVEL_S0) && 2448 (parent->num_child >= 0)) { 2449 if (node->cosq_attached_to >= numq) { 2450 _bcm_kt2_node_index_clear(list, node->hw_index, 1); 2451 } 2452 if (parent->num_child == 0 && 2453 parent->base_index >= 0) { 2454 /* release contiguous queue ids */ 2455 _bcm_kt2_node_index_clear(list, parent->base_index, numq); 2456 parent->base_index = -1; 2457 } 2458 } 2459 if (node->level == _BCM_KT2_COSQ_NODE_LEVEL_S0) { 2460 if ( node->hw_index < 128) { 2461 _bcm_kt2_node_index_clear(list, node->hw_index, 1); 2462 } 2463 } 2464 break; 2465 2466 case _BCM_KT2_COSQ_NODE_LEVEL_L1: 2467 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(node->gport)) { 2468 list = &mmu_info->l2_base_qlist; 2469 offset = 0; 2470 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(node->gport)) { 2471 list = &mmu_info->l2_base_mcqlist; 2472 offset = 0; 2473 } else if (BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(node->gport) 2474 && (mmu_info->num_dmvoq_queues > 0)) { 2475 list = &mmu_info->l2_dmvoq_qlist; 2476 offset = mmu_info->base_dmvoq_queue; 2477 } else if ((BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(node->gport) || 2478 BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(node->gport)) 2479 && (mmu_info->num_sub_queues > 0)) { 2480 if (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(node->gport)) { 2481 list = &mmu_info->l2_sub_qlist; 2482 offset = mmu_info->base_sub_queue; 2483 } else { 2484 list = &mmu_info->l2_sub_mcqlist; 2485 offset = mmu_info->base_sub_queue + mmu_info->num_queues/2; 2486 } 2487 } else { 2488 list = &mmu_info->l2_global_qlist; 2489 offset = 0 ; 2490 } 2491 2492 parent->num_child--; 2493 id = node->hw_index - offset; 2494 if (parent->num_child >= 0) { 2495 if (node->cosq_attached_to >= 8) { 2496 _bcm_kt2_node_index_clear(list, id, 1); 2497 } 2498 if (BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(node->gport)) { 2499 if (parent->num_child == 0 && 2500 parent->mc_base_index >= 0) { 2501 /* release contiguous queue ids */ 2502 id = parent->mc_base_index - offset; 2503 _bcm_kt2_node_index_clear(list, id, numq); 2504 parent->mc_base_index = -1; 2505 } 2506 } else { 2507 if (parent->num_child == 0 && 2508 parent->base_index >= 0) { 2509 /* release contiguous queue ids */ 2510 id = parent->base_index - offset; 2511 _bcm_kt2_node_index_clear(list, id, numq); 2512 parent->base_index = -1; 2513 } 2514 } 2515 } 2516 break; 2517 2518 case _BCM_KT2_COSQ_NODE_LEVEL_L2: 2519 /* passthru */ 2520 default: 2521 return BCM_E_PARAM; 2522 2523 } 2524 2525 return BCM_E_NONE; 2526 } 2527 2528 /* 2529 * Function: 2530 * _bcm_kt2_cosq_valid_dynamic_request 2531 * Purpose: 2532 * Validate the new dynamic request 2533 * Parameters: 2534 * unit - (IN) unit number 2535 * port - (IN) port 2536 * level - (IN) scheduler level 2537 * node_id - (IN) node index 2538 * parent_id - (IN) parent index 2539 * rval - (IN) dynamic reg value 2540 * Returns: 2541 * BCM_E_XXX 2542 */ 2543 2544 STATIC int 2545 _bcm_kt2_cosq_valid_dynamic_request(int unit, bcm_port_t port, int node_level, 2546 int node_id, int parent_id, uint32 rval) 2547 { 2548 soc_reg_t dyn_reg = LLS_SP_WERR_DYN_CHANGE_0Ar; 2549 lls_l0_parent_entry_t l0_parent; 2550 lls_l1_parent_entry_t l1_parent; 2551 bcm_port_t req_port, req_parent; 2552 2553 /* dont allow more than one req per parent */ 2554 req_parent = soc_reg_field_get(unit, dyn_reg, rval, PARENT_IDf); 2555 if ((node_level == soc_reg_field_get(unit, dyn_reg, rval, NODE_LEVELf)) && 2556 (parent_id == req_parent)) { 2557 return FALSE; 2558 } 2559 2560 switch (node_level) { 2561 case _BCM_KT2_COSQ_NODE_LEVEL_L0: 2562 req_port = parent_id; 2563 break; 2564 case _BCM_KT2_COSQ_NODE_LEVEL_L1: 2565 SOC_IF_ERROR_RETURN 2566 (READ_LLS_L0_PARENTm(unit, MEM_BLOCK_ALL, req_parent, 2567 &l0_parent)); 2568 req_port = soc_mem_field32_get(unit, LLS_L0_PARENTm, &l0_parent, 2569 C_PARENTf); 2570 break; 2571 case _BCM_KT2_COSQ_NODE_LEVEL_L2: 2572 SOC_IF_ERROR_RETURN 2573 (READ_LLS_L1_PARENTm(unit, MEM_BLOCK_ALL, req_parent, 2574 &l1_parent)); 2575 req_port = soc_mem_field32_get(unit, LLS_L1_PARENTm, &l1_parent, 2576 C_PARENTf); 2577 SOC_IF_ERROR_RETURN 2578 (READ_LLS_L0_PARENTm(unit, MEM_BLOCK_ALL, req_port, 2579 &l0_parent)); 2580 req_port = soc_mem_field32_get(unit, LLS_L0_PARENTm, &l0_parent, 2581 C_PARENTf); 2582 break; 2583 default: 2584 return FALSE; 2585 } 2586 2587 /* dont allow more than one req per port */ 2588 if (port == req_port) { 2589 return FALSE; 2590 } 2591 return TRUE; 2592 } 2593 2594 /* 2595 * Function: 2596 * _bcm_kt2_cosq_dynamic_sp_werr_change 2597 * Purpose: 2598 * Set LLS dynamic scheduler registers based on level and hw index 2599 * Parameters: 2600 * unit - (IN) unit number 2601 * level - (IN) scheduler level 2602 * node_id - (IN) node index 2603 * parent_id - (IN) parent index 2604 * config - (IN) config details 2605 * Returns: 2606 * BCM_E_XXX 2607 */ 2608 STATIC int 2609 _bcm_kt2_cosq_dynamic_sp_werr_change(int unit, bcm_port_t port, int node_level, 2610 int node_id, int parent_id, uint32 *config, 2611 _bcm_kt2_cosq_state_t state) 2612 { 2613 soc_timeout_t timeout; 2614 uint32 timeout_val, rval; 2615 int i, in_use; 2616 soc_reg_t dyn_reg_a, dyn_reg_b, dyn_reg_c; 2617 uint32 entry_b, entry_c; 2618 lls_l0_parent_entry_t l0_parent; 2619 int packing_mode = 0, abort; 2620 2621 soc_reg_t dyn_change_a[] = 2622 { 2623 LLS_SP_WERR_DYN_CHANGE_0Ar, 2624 LLS_SP_WERR_DYN_CHANGE_1Ar, 2625 LLS_SP_WERR_DYN_CHANGE_2Ar, 2626 LLS_SP_WERR_DYN_CHANGE_3Ar 2627 }; 2628 soc_reg_t dyn_change_b[] = 2629 { 2630 LLS_SP_WERR_DYN_CHANGE_0Br, 2631 LLS_SP_WERR_DYN_CHANGE_1Br, 2632 LLS_SP_WERR_DYN_CHANGE_2Br, 2633 LLS_SP_WERR_DYN_CHANGE_3Br 2634 }; 2635 soc_reg_t dyn_change_c[] = 2636 { 2637 LLS_SP_WERR_DYN_CHANGE_0Cr, 2638 LLS_SP_WERR_DYN_CHANGE_1Cr, 2639 LLS_SP_WERR_DYN_CHANGE_2Cr, 2640 LLS_SP_WERR_DYN_CHANGE_3Cr 2641 }; 2642 2643 2644 /* New value for the node_ids parent config bits 41:32 2645 * to be programmed into dynamic change register 2646 * LLS_SP_WERR_DYN_CHANGE_XB 2647 */ 2648 if (SOC_IS_METROLITE(unit)) { 2649 entry_b = (config[1] & _BCM_ML_LLS_DYN_CHG_REG_B); 2650 } else if (SOC_IS_SABER2(unit)) { 2651 entry_b = (config[1] & _BCM_SB2_LLS_DYN_CHG_REG_B); 2652 } else { 2653 entry_b = (config[1] & _BCM_KT2_LLS_DYN_CHG_REG_B); 2654 } 2655 2656 /* New value for the node_ids parent config bits 31:0. 2657 * to be programmed into dynamic change register 2658 * LLS_SP_WERR_DYN_CHANGE_XC 2659 */ 2660 entry_c = (config[0] & _BCM_KT2_LLS_DYN_CHG_REG_C); 2661 2662 /* Get one of the free register to place the request */ 2663 for (i = 0; i < 4; i++) { 2664 dyn_reg_a = dyn_change_a[i]; 2665 dyn_reg_b = dyn_change_b[i]; 2666 dyn_reg_c = dyn_change_c[i]; 2667 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, dyn_reg_a, REG_PORT_ANY, 2668 0, &rval)); 2669 if (SAL_BOOT_SIMULATION) { 2670 break; 2671 } 2672 2673 if (soc_reg_field_get(unit, dyn_reg_a, rval, IN_USEf) == 0) { 2674 break; 2675 } else { 2676 /* verify any other req pending from this port or same parent */ 2677 if (_bcm_kt2_cosq_valid_dynamic_request(unit, port, node_level, 2678 node_id, parent_id, rval) == FALSE) { 2679 return BCM_E_UNAVAIL; 2680 } 2681 } 2682 } 2683 2684 if (i == 4) { 2685 /* None of the registers are available */ 2686 return BCM_E_UNAVAIL; 2687 } 2688 2689 rval = 0 ; 2690 /* subtract 2 due to addional level of s0 and s1 */ 2691 soc_reg_field_set(unit, dyn_reg_a, &rval, NODE_LEVELf, (node_level - 2)); 2692 soc_reg_field_set(unit, dyn_reg_a, &rval, NODE_IDf, node_id); 2693 soc_reg_field_set(unit, dyn_reg_a, &rval, IN_USEf, 1); 2694 if (node_level == _BCM_KT2_COSQ_NODE_LEVEL_L0) { 2695 SOC_IF_ERROR_RETURN 2696 (READ_LLS_L0_PARENTm(unit, MEM_BLOCK_ALL, node_id, 2697 &l0_parent)); 2698 if (soc_mem_field32_get(unit, LLS_L0_PARENTm, 2699 &l0_parent, C_TYPEf) == 1) { 2700 if (SOC_IS_METROLITE(unit)) { 2701 /* 2702 * For Ports, set parent_id[6:5] = 0x1, 2703 * set parent_id[5:0] = {1b0, port_id[3:0]}. 2704 */ 2705 parent_id = ((0x1 << 5) | (parent_id & 0xF)); 2706 } else if (SOC_IS_SABER2(unit)) { 2707 /* 2708 For Ports, set parent_id[7:6] = 0x1, 2709 set parent_id[5:0] = {1b0, port_id[4:0]}. 2710 */ 2711 parent_id = ((0x1 << 6) | (parent_id & 0x1F)); 2712 } else if (SOC_IS_KATANA2(unit)) { 2713 /* 2714 For Ports, set parent_id[9:7] = 0x2, 2715 set parent_id[6:0] = {1b0, port_id[5:0]}. 2716 */ 2717 parent_id = ((0x2 << 7) | (parent_id & 0x3F)); 2718 } 2719 } 2720 } 2721 soc_reg_field_set(unit, dyn_reg_a, &rval, PARENT_IDf, parent_id); 2722 2723 /* Write DYN_CHANGE_XB register first */ 2724 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, dyn_reg_c, REG_PORT_ANY, 2725 0, entry_c)); 2726 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, dyn_reg_b, REG_PORT_ANY, 2727 0, entry_b)); 2728 /* Write DYN_CHANGE_XA register next. this triggers the request */ 2729 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, dyn_reg_a, REG_PORT_ANY, 2730 0, rval)); 2731 if (SAL_BOOT_SIMULATION) { 2732 return BCM_E_NONE; 2733 } 2734 2735 in_use = 1; 2736 if (soc_feature(unit, soc_feature_mmu_packing)) { 2737 BCM_IF_ERROR_RETURN 2738 (_bcm_kt2_cosq_packing_mode_get(unit, node_id, &packing_mode)); 2739 2740 } 2741 if (packing_mode == 1) { 2742 timeout_val = soc_property_get(unit, spn_MMU_QUEUE_FLUSH_TIMEOUT, 2743 _BCM_COSQ_QUEUE_FLUSH_TIMEOUT_PACKING_DEFAULT); 2744 } else { 2745 2746 timeout_val = soc_property_get(unit, spn_MMU_QUEUE_FLUSH_TIMEOUT, 2747 _BCM_COSQ_QUEUE_FLUSH_TIMEOUT_DEFAULT); 2748 } 2749 soc_timeout_init(&timeout, timeout_val, 0); 2750 2751 while (in_use) { 2752 SOC_IF_ERROR_RETURN 2753 (soc_reg32_get(unit, dyn_reg_a, REG_PORT_ANY, 0, &rval)); 2754 in_use = soc_reg_field_get(unit, dyn_reg_a, rval, IN_USEf); 2755 if (in_use && soc_timeout_check(&timeout)) { 2756 LOG_ERROR(BSL_LS_BCM_COMMON, 2757 (BSL_META_U(unit, 2758 "ERROR: dynamic sp <-> werr change operation failed \n"))); 2759 LOG_ERROR(BSL_LS_BCM_COMMON, 2760 (BSL_META_U(unit, 2761 " node_level %d node_id %d parent_id %d \n"), 2762 node_level, node_id, parent_id)); 2763 soc_reg_field_set(unit, dyn_reg_a, &rval, IN_USEf, 0); 2764 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, dyn_reg_a, REG_PORT_ANY, 2765 0, rval)); 2766 abort = 0; 2767 if (packing_mode == 1) { 2768 timeout_val = soc_property_get(unit, spn_MMU_QUEUE_FLUSH_TIMEOUT, 2769 _BCM_COSQ_QUEUE_FLUSH_TIMEOUT_PACKING_DEFAULT); 2770 } else { 2771 2772 timeout_val = soc_property_get(unit, spn_MMU_QUEUE_FLUSH_TIMEOUT, 2773 _BCM_COSQ_QUEUE_FLUSH_TIMEOUT_DEFAULT); 2774 } 2775 soc_timeout_init(&timeout, timeout_val, 0); 2776 while (!abort) { 2777 SOC_IF_ERROR_RETURN 2778 (soc_reg32_get(unit, dyn_reg_a, REG_PORT_ANY, 0, &rval)); 2779 /* ABORT_BEFORE_COMPLETE would be set by hw if operation is aborted */ 2780 abort = soc_reg_field_get(unit, dyn_reg_a, rval, ABORT_BEFORE_COMPLETEf); 2781 if (abort) { 2782 soc_reg_field_set(unit, dyn_reg_a, &rval, ABORT_BEFORE_COMPLETEf, 0); 2783 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, dyn_reg_a, REG_PORT_ANY, 2784 0, rval)); 2785 break; 2786 } 2787 if (soc_timeout_check(&timeout)) { 2788 return BCM_E_TIMEOUT; 2789 } 2790 } 2791 return BCM_E_TIMEOUT; 2792 } 2793 } 2794 2795 return BCM_E_NONE; 2796 } 2797 2798 int 2799 _bcm_kt2_cosq_subport_get(int unit, bcm_gport_t sched_gport, 2800 int *pp_port) 2801 { 2802 int rv = BCM_E_NOT_FOUND; 2803 bcm_cos_queue_t cosq; 2804 bcm_gport_t gport; 2805 _bcm_kt2_cosq_node_t *node; 2806 int encap_id = 0; 2807 bcm_gport_t input_gport; 2808 2809 gport = sched_gport; 2810 BCM_IF_ERROR_RETURN 2811 (_bcm_kt2_cosq_node_get(unit, gport, NULL, NULL, NULL, 2812 &node)); 2813 2814 while (node->level != _BCM_KT2_COSQ_NODE_LEVEL_ROOT) { 2815 BCM_IF_ERROR_RETURN 2816 (bcm_kt2_cosq_gport_attach_get(unit, gport, &input_gport, &cosq)); 2817 gport = input_gport; 2818 if (BCM_GPORT_IS_SCHEDULER(gport)) { 2819 encap_id = (BCM_GPORT_SCHEDULER_GET(node->gport) >> 8) & 0x7ff; 2820 if (node->subport_enabled == 1) { 2821 *pp_port = encap_id; 2822 /*BCM_GPORT_SUBPORT_PORT_SET(*input_gport, encap_id);*/ 2823 rv = BCM_E_NONE; 2824 break; 2825 } 2826 } 2827 BCM_IF_ERROR_RETURN 2828 (_bcm_kt2_cosq_node_get(unit, gport, NULL, NULL, NULL, 2829 &node)); 2830 } 2831 #if defined BCM_METROLITE_SUPPORT 2832 if ((rv == BCM_E_NONE) && 2833 soc_feature(unit, soc_feature_discontinuous_pp_port)) { 2834 if (*pp_port > SOC_INFO(unit).cpu_hg_pp_port_index) { 2835 *pp_port -= SOC_INFO(unit).cpu_hg_pp_port_index; 2836 } 2837 } 2838 #endif 2839 2840 return rv; 2841 } 2842 2843 int 2844 _bcm_kt2_cosq_packing_mode_get(int unit, int index, int *set) 2845 { 2846 mmu_toq_qpack_mode_entry_t qpack_entry; 2847 uint32 mode = 0; 2848 2849 /* MMU_TOQ_QPACK_MODE register not present on Saber_2 */ 2850 if (SOC_IS_SABER2(unit)) { 2851 return BCM_E_NONE; 2852 } 2853 SOC_IF_ERROR_RETURN 2854 (READ_MMU_TOQ_QPACK_MODEm(unit, MEM_BLOCK_ALL, 2855 index/16, &qpack_entry)); 2856 soc_mem_field_get(unit, MMU_TOQ_QPACK_MODEm, 2857 (uint32 *)&qpack_entry, 2858 QMODEf, &mode); 2859 2860 *set = (mode & (1 << (index % 16))) ? 1 : 0; 2861 return BCM_E_NONE; 2862 } 2863 2864 int 2865 _bcm_kt2_cosq_packing_mode_set(int unit, int index, int set) 2866 { 2867 int rv = BCM_E_NONE; 2868 mmu_toq_qpack_mode_entry_t qpack_entry; 2869 uint32 mode = 0; 2870 2871 /* MMU_TOQ_QPACK_MODE register not present on Saber_2 */ 2872 if (SOC_IS_SABER2(unit)) { 2873 return BCM_E_NONE; 2874 } 2875 SOC_IF_ERROR_RETURN 2876 (READ_MMU_TOQ_QPACK_MODEm(unit, MEM_BLOCK_ALL, 2877 index/16, &qpack_entry)); 2878 soc_mem_field_get(unit, MMU_TOQ_QPACK_MODEm, 2879 (uint32 *)&qpack_entry, 2880 QMODEf, &mode); 2881 if (set) { 2882 mode |= (1 << (index % 16)); 2883 } else { 2884 mode &= ~(1 << (index % 16)); 2885 } 2886 2887 soc_mem_field32_set(unit, MMU_TOQ_QPACK_MODEm, 2888 &qpack_entry, QMODEf, mode); 2889 SOC_IF_ERROR_RETURN 2890 (WRITE_MMU_TOQ_QPACK_MODEm(unit, MEM_BLOCK_ALL, 2891 index/16, &qpack_entry)); 2892 2893 return rv; 2894 } 2895 2896 STATIC 2897 int _bcm_kt2_cosq_flush_queues(int unit, 2898 bcm_port_t port, 2899 _bcm_kt2_cosq_node_t *node, 2900 bcm_gport_t gport) 2901 { 2902 int flush_active = 0; 2903 uint32 rval = 0; 2904 uint32 timeout_val = 0; 2905 soc_timeout_t timeout; 2906 2907 /* flush the queue */ 2908 if (!(SAL_BOOT_SIMULATION)) { 2909 BCM_IF_ERROR_RETURN(READ_TOQ_FLUSH0r(unit, &rval)); 2910 flush_active = soc_reg_field_get(unit, TOQ_FLUSH0r, rval, FLUSH_ACTIVEf); 2911 if (flush_active == 1) { 2912 /* some other queue is in flush state, return failure */ 2913 LOG_ERROR(BSL_LS_BCM_COMMON, 2914 (BSL_META_U(unit, 2915 "ERROR: Queue %d is already in flush state \n"), 2916 (soc_reg_field_get(unit, TOQ_FLUSH0r, rval, FLUSH_ID0f)))); 2917 return BCM_E_BUSY; 2918 } 2919 soc_reg_field_set(unit, TOQ_FLUSH0r, &rval, FLUSH_TYPEf, 0); 2920 soc_reg_field_set(unit, TOQ_FLUSH0r, &rval, FLUSH_ID0f, node->hw_index); 2921 soc_reg_field_set(unit, TOQ_FLUSH0r, &rval, FLUSH_NUMf, 1); 2922 soc_reg_field_set(unit, TOQ_FLUSH0r, &rval, FLUSH_ACTIVEf, 1); 2923 if (IS_EXT_MEM_PORT(unit, port)) { 2924 soc_reg_field_set(unit, TOQ_FLUSH0r, &rval, FLUSH_EXTERNALf, 1); 2925 } else { 2926 if (soc_reg_field_valid(unit, TOQ_FLUSH0r, FLUSH_EXTERNALf)){ 2927 soc_reg_field_set(unit, TOQ_FLUSH0r, &rval, FLUSH_EXTERNALf, 0); 2928 } 2929 } 2930 BCM_IF_ERROR_RETURN(WRITE_TOQ_FLUSH0r(unit, rval)); 2931 flush_active = 1; 2932 timeout_val = soc_property_get(unit, spn_MMU_QUEUE_FLUSH_TIMEOUT, 2933 20000); 2934 soc_timeout_init(&timeout, timeout_val, 0); 2935 2936 while (flush_active) { 2937 BCM_IF_ERROR_RETURN (READ_TOQ_FLUSH0r(unit, &rval)); 2938 flush_active = soc_reg_field_get(unit, TOQ_FLUSH0r, rval, 2939 FLUSH_ACTIVEf); 2940 if (soc_timeout_check(&timeout)) { 2941 BCM_IF_ERROR_RETURN(_bcm_kt2_cosq_adjust_lls_bw(unit, gport, 2942 node)); 2943 BCM_IF_ERROR_RETURN(READ_TOQ_FLUSH0r(unit, &rval)); 2944 flush_active = soc_reg_field_get(unit, TOQ_FLUSH0r, 2945 rval, FLUSH_ACTIVEf); 2946 if (flush_active) { 2947 LOG_ERROR(BSL_LS_BCM_COMMON, 2948 (BSL_META_U(unit, 2949 "ERROR: Queue %d flush operation failed \n"), 2950 node->hw_index)); 2951 return (BCM_E_TIMEOUT); 2952 } 2953 } 2954 } 2955 } 2956 return BCM_E_NONE; 2957 } 2958 2959 STATIC int 2960 _bcm_kt2_cosq_l2_max_bucket_set(int unit, int port, 2961 _bcm_kt2_cosq_node_t *node) 2962 { 2963 int rv; 2964 2965 if (node->level != _BCM_KT2_COSQ_NODE_LEVEL_L2) { 2966 for (node = node->child; node; node = node->sibling) { 2967 rv = _bcm_kt2_cosq_l2_max_bucket_set(unit, port, node); 2968 if (!BCM_SUCCESS(rv)) { 2969 return rv; 2970 } 2971 } 2972 return BCM_E_NONE; 2973 } 2974 2975 #if defined(BCM_SABER2_SUPPORT) 2976 if (SOC_IS_SABER2(unit)) { 2977 rv = soc_sb2_cosq_max_bucket_set(unit, port, node->hw_index, 2978 _BCM_KT2_COSQ_NODE_LEVEL_L2); 2979 } else 2980 #endif 2981 { 2982 rv = soc_kt2_cosq_max_bucket_set(unit, port, node->hw_index, 2983 _BCM_KT2_COSQ_NODE_LEVEL_L2); 2984 } 2985 return rv; 2986 } 2987 2988 /* 2989 * Function: 2990 * _bcm_kt2_cosq_min_clear(unit, physical_port, node); 2991 * Parameters: 2992 * unit - (IN) unit number 2993 * port - (IN) physical port 2994 * node - (IN) node undergoing switchover 2995 * Returns: 2996 * BCM_E_XXX 2997 */ 2998 STATIC int 2999 _bcm_kt2_cosq_min_clear(int unit, int port, 3000 _bcm_kt2_cosq_node_t *node) 3001 { 3002 int rv = BCM_E_NONE; 3003 #if defined(BCM_SABER2_SUPPORT) 3004 if (SOC_IS_SABER2(unit)) { 3005 rv = soc_sb2_cosq_min_clear(unit, port, node->hw_index, 3006 node->level); 3007 } else 3008 #endif 3009 { 3010 rv = soc_kt2_cosq_min_clear(unit, port, node->hw_index, 3011 node->level); 3012 } 3013 return rv; 3014 } 3015 3016 int 3017 _bcm_egress_metering_freeze(int unit, bcm_gport_t gport, void **setting) 3018 { 3019 int rv = BCM_E_NONE; 3020 soc_mem_t mem; 3021 uint32 *bmap, *bmap_list[6]; 3022 int word_count, wdc[6], blk_size=0; 3023 int lvl, j, index, word, bit, index_count, count; 3024 int idx, upper_flag = 0; 3025 int prev_idx, prev_upper_flag; 3026 mem_entry_t *buffer; 3027 uint32 mant = 0, cycle = 0 , f_idx; 3028 uint32 entry[SOC_MAX_MEM_WORDS]; 3029 uint32 lvl_count = 0; 3030 uint32 min = 0; 3031 uint32 exp = 0; 3032 uint32 sched_mode = 0; 3033 int wt = 0; 3034 uint32 burst_mant = 0; 3035 uint32 burst_exp = 0; 3036 uint32 *l2bmap = NULL; 3037 int alloc_size; 3038 bcm_port_t port; 3039 soc_info_t *si; 3040 _bcm_kt2_cosq_node_t *node = NULL; 3041 _bcm_kt2_cosq_node_t *l1node = NULL; 3042 _bcm_kt2_cosq_node_t *cur_node = NULL; 3043 3044 static const soc_mem_t parent_mems[] = { 3045 0, 3046 LLS_L0_PARENTm, 3047 LLS_L0_PARENTm, 3048 LLS_L0_PARENTm, 3049 LLS_L1_PARENTm, 3050 LLS_L2_PARENTm 3051 }; 3052 3053 static const soc_mem_t cfg_mems[][2] = { 3054 { LLS_PORT_SHAPER_CONFIG_Cm, INVALIDm }, 3055 { LLS_S0_SHAPER_CONFIG_Cm, INVALIDm }, 3056 { LLS_S1_SHAPER_CONFIG_Cm, INVALIDm }, 3057 { LLS_L0_SHAPER_CONFIG_Cm, LLS_L0_MIN_CONFIG_Cm }, 3058 { LLS_L1_SHAPER_CONFIG_Cm, LLS_L1_MIN_CONFIG_Cm }, 3059 { LLS_L2_SHAPER_CONFIG_LOWERm, LLS_L2_MIN_CONFIG_LOWER_Cm }, 3060 { LLS_L2_SHAPER_CONFIG_UPPERm, LLS_L2_MIN_CONFIG_UPPER_Cm }, 3061 }; 3062 3063 static const soc_field_t rate_mant_fields[] = { 3064 C_MAX_REF_RATE_MANT_0f, C_MAX_REF_RATE_MANT_1f, 3065 C_MAX_REF_RATE_MANT_2f, C_MAX_REF_RATE_MANT_3f, 3066 C_MIN_REF_RATE_MANT_0f, C_MIN_REF_RATE_MANT_1f, 3067 C_MIN_REF_RATE_MANT_2f, C_MIN_REF_RATE_MANT_3f 3068 }; 3069 3070 static const soc_field_t rate_exp_fields[] = { 3071 C_MAX_REF_RATE_EXP_0f, C_MAX_REF_RATE_EXP_1f, 3072 C_MAX_REF_RATE_EXP_2f, C_MAX_REF_RATE_EXP_3f, 3073 C_MIN_REF_RATE_EXP_0f, C_MIN_REF_RATE_EXP_1f, 3074 C_MIN_REF_RATE_EXP_2f, C_MIN_REF_RATE_EXP_3f 3075 }; 3076 static const soc_field_t burst_exp_fields[] = { 3077 C_MAX_THLD_EXP_0f, C_MAX_THLD_EXP_1f, 3078 C_MAX_THLD_EXP_2f, C_MAX_THLD_EXP_3f, 3079 C_MIN_THLD_EXP_0f, C_MIN_THLD_EXP_1f, 3080 C_MIN_THLD_EXP_2f, C_MIN_THLD_EXP_3f 3081 }; 3082 static const soc_field_t burst_mant_fields[] = { 3083 C_MAX_THLD_MANT_0f, C_MAX_THLD_MANT_1f, 3084 C_MAX_THLD_MANT_2f, C_MAX_THLD_MANT_3f, 3085 C_MIN_THLD_MANT_0f, C_MIN_THLD_MANT_1f, 3086 C_MIN_THLD_MANT_2f, C_MIN_THLD_MANT_3f 3087 }; 3088 3089 static const soc_field_t cycle_sel_fields[] = { 3090 C_MAX_CYCLE_SEL_0f, C_MAX_CYCLE_SEL_1f, 3091 C_MAX_CYCLE_SEL_2f, C_MAX_CYCLE_SEL_3f, 3092 C_MIN_CYCLE_SEL_0f, C_MIN_CYCLE_SEL_1f, 3093 C_MIN_CYCLE_SEL_2f, C_MIN_CYCLE_SEL_3f 3094 }; 3095 3096 SOC_EGRESS_METERING_LOCK(unit); 3097 3098 alloc_size = SHR_BITALLOCSIZE(soc_mem_index_count(unit, LLS_L2_PARENTm)); 3099 3100 l2bmap = sal_alloc(alloc_size, "l2bmap"); 3101 if(l2bmap == NULL) { 3102 rv = SOC_E_MEMORY; 3103 goto _ka2_freeze_abort; 3104 } 3105 3106 sal_memset(l2bmap, 0, alloc_size); 3107 rv = _bcm_kt2_cosq_node_get(unit, gport, NULL, &port, NULL, &node); 3108 if (rv < 0) { 3109 sal_free(l2bmap); 3110 goto _ka2_freeze_abort; 3111 } 3112 3113 l1node = node->parent; 3114 for (cur_node = l1node->child; cur_node != NULL ; cur_node = cur_node->sibling) { 3115 SHR_BITSET(l2bmap, cur_node->hw_index); 3116 } 3117 3118 bmap_list[0] = NULL; 3119 bmap_list[1] = SOC_CONTROL(unit)->port_lls_s0_bmap[port]; 3120 bmap_list[2] = SOC_CONTROL(unit)->port_lls_s1_bmap[port]; 3121 bmap_list[3] = SOC_CONTROL(unit)->port_lls_l0_bmap[port]; 3122 bmap_list[4] = SOC_CONTROL(unit)->port_lls_l1_bmap[port]; 3123 bmap_list[5] = l2bmap; 3124 3125 si = &SOC_INFO(unit); 3126 /* 3127 * On KTX we can have both s0 and s1 node or only 3128 * s1 node but can not have only s0 node 3129 */ 3130 bmap = bmap_list[2]; 3131 index_count = _SOC_KT2_COSQ_MAX_INDEX_S1; 3132 word_count = _SHR_BITDCLSIZE(index_count); 3133 for (word = 0; word < word_count; word++) { 3134 if (bmap[word] != 0) { 3135 break; 3136 } 3137 } 3138 if (word == word_count) { 3139 /* s1 list is zero */ 3140 bmap = bmap_list[1]; 3141 index_count = _SOC_KT2_COSQ_MAX_INDEX_S0; 3142 word_count = _SHR_BITDCLSIZE(index_count); 3143 for (word = 0; word < word_count; word++) { 3144 if (bmap[word] != 0) { 3145 break; 3146 } 3147 } 3148 if (word < word_count) { 3149 /* s0 list is non zero */ 3150 /* swap s0 ans s1 list */ 3151 bmap = bmap_list[2]; 3152 bmap_list[2] = bmap_list[1]; 3153 bmap_list[1] = bmap; 3154 } 3155 } 3156 count = 0; 3157 /* Count the number of the valid Root,S0,S1 3158 * L0/L1/L2 entries per port. 3159 * To allocate the buffer to store the Min, Max shaper 3160 * entries for the valid indices 3161 */ 3162 for (lvl = 0; lvl < _SOC_KT2_COSQ_NODE_LVL_MAX; lvl++) { 3163 lvl_count = 0; 3164 if (lvl == _SOC_KT2_COSQ_NODE_LVL_ROOT) { 3165 /* Port entry */ 3166 lvl_count = 1; 3167 wdc[lvl] = 0; 3168 } else { 3169 bmap = bmap_list[lvl]; 3170 mem = parent_mems[lvl]; 3171 index_count = soc_mem_index_count(unit, mem); 3172 3173 if (lvl == _SOC_KT2_COSQ_NODE_LVL_S0) { 3174 index_count = _SOC_KT2_COSQ_MAX_INDEX_S0; 3175 } else 3176 if (lvl == _SOC_KT2_COSQ_NODE_LVL_S1) { 3177 index_count =_SOC_KT2_COSQ_MAX_INDEX_S1; 3178 } 3179 wdc[lvl] = _SHR_BITDCLSIZE(index_count); 3180 word_count = wdc[lvl]; 3181 3182 for (word = 0; word < word_count; word++) { 3183 if (bmap[word] != 0) { 3184 lvl_count += _shr_popcount(bmap[word]); 3185 } 3186 } 3187 if (lvl >= _SOC_KT2_COSQ_NODE_LVL_L0) { 3188 /* for MIN/MAX shaper config */ 3189 /* count allocation is based on worst case 3190 * estimate that entries might fall into different 3191 * table entries 3192 */ 3193 lvl_count = (lvl_count * 2); 3194 } 3195 } 3196 count += lvl_count; 3197 } 3198 count = count + 1; 3199 3200 3201 buffer = sal_alloc((count + 1) * sizeof(mem_entry_t), 3202 "shaper buffer"); 3203 3204 if (buffer == NULL) { 3205 rv = SOC_E_MEMORY; 3206 sal_free(l2bmap); 3207 goto _ka2_freeze_abort; 3208 } 3209 count = 0; 3210 /* port */ 3211 mem = LLS_PORT_SHAPER_CONFIG_Cm; 3212 index = port & 0x3f; 3213 3214 /* Save the entry */ 3215 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, index, 3216 &buffer[count].entry); 3217 if (BCM_FAILURE(rv)) { 3218 sal_free(buffer); 3219 sal_free(l2bmap); 3220 goto _ka2_freeze_abort; 3221 } 3222 buffer[count].mem = mem; 3223 buffer[count].index = index; 3224 count++; 3225 3226 /* Set the threshold for the port to max shaper rate */ 3227 rv = soc_kt2_cosq_max_bucket_set(unit, port, index, 3228 _SOC_KT2_COSQ_NODE_LVL_ROOT); 3229 if (BCM_FAILURE(rv)) { 3230 sal_free(buffer); 3231 sal_free(l2bmap); 3232 goto _ka2_freeze_abort; 3233 } 3234 3235 /* S0, S1, L0, L1, L2 meter */ 3236 for (lvl = _SOC_KT2_COSQ_NODE_LVL_S0; 3237 lvl < _SOC_KT2_COSQ_NODE_LVL_MAX; lvl++) { 3238 idx = upper_flag = 0; 3239 prev_idx = prev_upper_flag = -1; 3240 blk_size = ((lvl == _SOC_KT2_COSQ_NODE_LVL_L2) ? 8: 3241 ((lvl == _SOC_KT2_COSQ_NODE_LVL_L1)? 4: 1)); 3242 bmap = bmap_list[lvl]; 3243 word_count = wdc[lvl]; 3244 for (word = 0; word < word_count; word++) { 3245 if (bmap[word] == 0) { 3246 continue; 3247 } 3248 for (bit = 0; bit < SHR_BITWID; bit++) { 3249 if (!(bmap[word] & (1 << bit))) { 3250 continue; 3251 } 3252 index = word * SHR_BITWID + bit; 3253 idx = index / blk_size; 3254 3255 for (j = 0; j < 2; j++) { 3256 mem = cfg_mems[lvl][j]; 3257 3258 if (mem == INVALIDm) { 3259 continue; 3260 } 3261 3262 if (lvl == _SOC_KT2_COSQ_NODE_LVL_L2) { 3263 if ((index % 8) >= 4) { 3264 mem = cfg_mems[lvl+1][j]; 3265 upper_flag = 1; 3266 } else { 3267 upper_flag = 0; 3268 } 3269 } 3270 3271 /* Store the Threshold MIN/MAX table entries only 3272 * once per table index as for the 3273 * next consecutive L1/L2 indices falling on 3274 * to the same table index need not be stored 3275 */ 3276 if ((prev_idx != idx) || 3277 ((lvl == _SOC_KT2_COSQ_NODE_LVL_L2) && 3278 (prev_upper_flag != upper_flag))) { 3279 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, idx, 3280 &buffer[count].entry); 3281 if (BCM_FAILURE(rv)) { 3282 sal_free(buffer); 3283 sal_free(l2bmap); 3284 goto _ka2_freeze_abort; 3285 } 3286 buffer[count].mem = mem; 3287 buffer[count].index = idx; 3288 count++; 3289 } 3290 3291 if (lvl == _SOC_KT2_COSQ_NODE_LVL_L2){ 3292 if (SOC_PBMP_MEMBER(si->linkphy_pbm, port)) { 3293 /* coverity[leaked_storage] */ 3294 rv = soc_kt2_cosq_get_sched_mode(unit, port, lvl, 3295 index, &sched_mode, &wt); 3296 } else { 3297 /* coverity[leaked_storage] */ 3298 /* coverity[resource_leak : FALSE] */ 3299 rv = soc_kt2_cosq_get_sched_mode(unit, port, lvl - 2, 3300 index, &sched_mode, &wt); 3301 } 3302 if (BCM_FAILURE(rv)) { 3303 sal_free(buffer); 3304 sal_free(l2bmap); 3305 goto _ka2_freeze_abort; 3306 } 3307 3308 if ( sched_mode == BCM_COSQ_STRICT ) 3309 { 3310 rv = _soc_kt2_cosq_min_bucket_get(unit, port, 3311 index, lvl, 3312 &min, &mant, 3313 &exp, &cycle); 3314 if (BCM_FAILURE(rv)) { 3315 sal_free(buffer); 3316 sal_free(l2bmap); 3317 goto _ka2_freeze_abort; 3318 } 3319 if (min) { 3320 if (exp != 0) { 3321 if (exp < 10) { 3322 burst_exp = 5; 3323 burst_mant = 0; 3324 } else { 3325 burst_exp = exp - 4; 3326 burst_mant = (mant >> 3); 3327 } 3328 } 3329 else { 3330 burst_mant = 0; 3331 burst_exp = 0; 3332 } 3333 } 3334 } 3335 if (!min) 3336 { 3337 /* Set the MIN/MAX thresholds for L2 node 3338 * to 2 Kbps 3339 */ 3340 mant = 1; 3341 cycle = 4; 3342 exp = 0; 3343 } 3344 f_idx = (j * 4) + (index % 4); 3345 sal_memset(entry, 0, (sizeof(uint32) * SOC_MAX_MEM_WORDS)); 3346 rv = soc_mem_read(unit, mem, MEM_BLOCK_ALL, 3347 idx, &entry); 3348 if (BCM_FAILURE(rv)) { 3349 sal_free(buffer); 3350 sal_free(l2bmap); 3351 goto _ka2_freeze_abort; 3352 } 3353 3354 soc_mem_field32_set(unit, mem, &entry, 3355 rate_mant_fields[f_idx], mant); 3356 soc_mem_field32_set(unit, mem, &entry, 3357 rate_exp_fields[f_idx], exp); 3358 soc_mem_field32_set(unit, mem, &entry, 3359 burst_exp_fields[f_idx], burst_exp); 3360 soc_mem_field32_set(unit, mem, &entry, 3361 burst_mant_fields[f_idx], burst_mant); 3362 soc_mem_field32_set(unit, mem, &entry, 3363 cycle_sel_fields[f_idx], cycle); 3364 rv = soc_mem_write(unit, mem, MEM_BLOCK_ANY, 3365 idx, &entry); 3366 min = 0; 3367 sched_mode = 0; 3368 cycle = 0; 3369 exp = 0; 3370 mant = 0; 3371 burst_exp = 0; 3372 burst_mant = 0; 3373 } else if (((lvl >= _SOC_KT2_COSQ_NODE_LVL_L0) && (j == 1)) || 3374 (lvl < _SOC_KT2_COSQ_NODE_LVL_L0)) { 3375 /* Set the MIN/MAX thresholds for L0/L1 node 3376 * to max shaper rate 3377 */ 3378 rv = soc_kt2_cosq_max_bucket_set(unit, port, 3379 index, lvl); 3380 } 3381 if (BCM_FAILURE(rv)) { 3382 sal_free(buffer); 3383 sal_free(l2bmap); 3384 goto _ka2_freeze_abort; 3385 } 3386 }/*END of for j */ 3387 prev_idx = idx; 3388 prev_upper_flag = upper_flag; 3389 } /* END of the valid bit */ 3390 } /* END of the word */ 3391 } /* END of lvl */ 3392 3393 buffer[count].mem = INVALIDm; 3394 *setting = buffer; 3395 _ka2_freeze_abort: 3396 if (BCM_FAILURE(rv)) { 3397 /* UNLOCK if fail */ 3398 SOC_EGRESS_METERING_UNLOCK(unit); 3399 } 3400 return rv; 3401 } 3402 3403 int 3404 _bcm_egress_metering_thaw(int unit, void *setting) 3405 { 3406 int rv = BCM_E_NONE; 3407 mem_entry_t *buffer; 3408 int index; 3409 3410 if (setting == NULL) { 3411 SOC_EGRESS_METERING_UNLOCK(unit); 3412 return SOC_E_NONE; 3413 } 3414 buffer = setting; 3415 for (index = 0; buffer[index].mem != INVALIDm ;index++) { 3416 rv = soc_mem_write(unit, buffer[index].mem, MEM_BLOCK_ANY, 3417 buffer[index].index, &buffer[index].entry); 3418 if (BCM_FAILURE(rv)) { 3419 break; 3420 } 3421 } 3422 sal_free(setting); 3423 3424 SOC_EGRESS_METERING_UNLOCK(unit); 3425 return rv; 3426 } 3427 /* 3428 * Function: 3429 * _bcm_kt2_cosq_sched_config_set 3430 * Purpose: 3431 * Set LLS scheduler registers based on GPORT 3432 * Parameters: 3433 * unit - (IN) unit number 3434 * gport - (IN) queue group/scheduler GPORT identifier 3435 * state - (IN) sched state change 3436 * Returns: 3437 * BCM_E_XXX 3438 */ 3439 STATIC int 3440 _bcm_kt2_cosq_sched_config_set(int unit, bcm_gport_t gport, 3441 _bcm_kt2_cosq_state_t state) 3442 { 3443 int rv = BCM_E_NONE; 3444 _bcm_kt2_mmu_info_t *mmu_info; 3445 _bcm_kt2_cosq_node_t *node, *parent; 3446 mmu_rqe_queue_op_node_map_entry_t rqe_op_node; 3447 mmu_wred_queue_op_node_map_entry_t wred_op_node; 3448 egr_queue_to_pp_port_map_entry_t pp_port_map; 3449 _bcm_kt2_subport_info_t info; 3450 bcm_gport_t pp_port; 3451 lls_l2_child_state1_entry_t l2_child_state; 3452 uint32 entry_c[SOC_MAX_MEM_WORDS]; 3453 uint32 entry_p[SOC_MAX_MEM_WORDS]; 3454 int port, physical_port, start_spri = 0; 3455 int update_spri_vector = 0; 3456 uint8 spri_vector = 0, spri_select = 0; 3457 int parent_index, numq; 3458 uint8 vec_3_0, vec_7_4; 3459 uint32 spare, min_list, ef_list, not_empty; 3460 soc_mem_t config_mem, parent_mem; 3461 soc_field_t start_spri_field = P_START_UC_SPRIf; 3462 bcm_port_t local_port; 3463 uint32 *bmap = NULL; 3464 void *setting = NULL; 3465 int s1_index = -1, link_state = BCM_PORT_LINK_STATUS_UP; 3466 _bcm_kt2_cosq_node_t *s1_node = NULL; 3467 soc_mem_t mem_c[] = { 3468 LLS_PORT_CONFIGm, 3469 LLS_S1_CONFIGm, 3470 INVALIDm, 3471 LLS_L0_CONFIGm, 3472 LLS_L1_CONFIGm 3473 }; 3474 soc_mem_t mem_p[] = { 3475 LLS_L0_PARENTm, 3476 LLS_L0_PARENTm, 3477 INVALIDm, 3478 LLS_L1_PARENTm, 3479 LLS_L2_PARENTm 3480 }; 3481 mmu_thdo_opnconfig_cell_entry_t mmu_thdo_opnconfig_cell_entry={{0}}; 3482 mmu_thdo_opnconfig_qentry_entry_t mmu_thdo_opnconfig_qentry_entry={{0}}; 3483 mmu_enq_src_ppp_to_s1_lookup_entry_t ppp_to_s1; 3484 3485 memset(&ppp_to_s1, 0, sizeof(ppp_to_s1)); 3486 3487 BCM_IF_ERROR_RETURN 3488 (_bcm_kt2_cosq_node_get(unit, gport, NULL, &port, NULL, 3489 &node)); 3490 3491 /* MMU_ENQ_SRC_PPP_TO_S1_LOOKUP is programmed 3492 * to map the PP ports to S1 node associated with 3493 * COE port for E2ECC COE Flow Control 3494 */ 3495 if (node->level == _BCM_KT2_COSQ_NODE_LEVEL_S0) { 3496 rv = _bcm_kt2_cosq_subport_get(unit, gport, &pp_port); 3497 if (rv == BCM_E_NONE) { 3498 BCM_IF_ERROR_RETURN 3499 (bcm_kt2_subport_pp_port_subport_info_get(unit, pp_port, 3500 &info)); 3501 if (info.port_type == _BCM_KT2_SUBPORT_TYPE_SUBTAG) { 3502 SOC_IF_ERROR_RETURN 3503 (READ_MMU_ENQ_SRC_PPP_TO_S1_LOOKUPm(unit, MEM_BLOCK_ALL, 3504 pp_port, &ppp_to_s1)); 3505 if (state == _BCM_KT2_COSQ_STATE_ENABLE) { 3506 soc_mem_field32_set(unit, MMU_ENQ_SRC_PPP_TO_S1_LOOKUPm, 3507 &ppp_to_s1, S1_VLDf, 1); 3508 soc_mem_field32_set(unit, MMU_ENQ_SRC_PPP_TO_S1_LOOKUPm, 3509 &ppp_to_s1, S1f, node->hw_index); 3510 SOC_IF_ERROR_RETURN 3511 (WRITE_MMU_ENQ_SRC_PPP_TO_S1_LOOKUPm(unit, 3512 MEM_BLOCK_ALL, 3513 pp_port, &ppp_to_s1)); 3514 3515 } else if (state == _BCM_KT2_COSQ_STATE_DISABLE) { 3516 SOC_IF_ERROR_RETURN 3517 (WRITE_MMU_ENQ_SRC_PPP_TO_S1_LOOKUPm(unit, 3518 MEM_BLOCK_ALL, 3519 pp_port, 3520 (soc_mem_entry_null(unit, 3521 MMU_ENQ_SRC_PPP_TO_S1_LOOKUPm)))); 3522 } 3523 3524 } 3525 } 3526 } 3527 parent = node->parent; 3528 /* 3529 * Programming the LLS_L0_PARENT and LLS_S1_CONFIG so that 3530 * credits are exchanged between the TXLP and MMU is proper in case of LinkPHY 3531 */ 3532 if (soc_feature(unit, soc_feature_discontinuous_pp_port) && 3533 parent->level == _BCM_KT2_COSQ_NODE_LEVEL_S0) { 3534 sal_memset(entry_p, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS); 3535 parent_mem = LLS_L0_PARENTm; 3536 soc_mem_field32_set(unit, parent_mem, &entry_p, C_PARENTf, 3537 parent->hw_index); 3538 soc_mem_field32_set(unit, parent_mem, &entry_p, C_TYPEf, 0); 3539 SOC_IF_ERROR_RETURN 3540 (soc_mem_write(unit, parent_mem, MEM_BLOCK_ANY, 3541 node->hw_index, &entry_p)); 3542 config_mem = LLS_S1_CONFIGm; 3543 sal_memset(entry_c, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS); 3544 /* Programming the L0 start node, since l0==s1, 3545 * using parent->hw_index 3546 */ 3547 soc_mem_field32_set(unit, config_mem, &entry_c, P_START_SPRIf, 3548 node->hw_index); 3549 soc_mem_field32_set(unit, config_mem, &entry_c, P_NUM_SPRIf, 3550 1); 3551 (soc_mem_write(unit, config_mem, MEM_BLOCK_ANY, 3552 parent->hw_index, 3553 &entry_c)); 3554 } else if ((node->level == _BCM_KT2_COSQ_NODE_LEVEL_L0) && 3555 (parent->level == _BCM_KT2_COSQ_NODE_LEVEL_S1)) { 3556 sal_memset(entry_p, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS); 3557 parent_mem = LLS_L0_PARENTm; 3558 soc_mem_field32_set(unit, parent_mem, &entry_p, C_PARENTf, 3559 parent->hw_index); 3560 soc_mem_field32_set(unit, parent_mem, &entry_p, C_TYPEf, 0); 3561 SOC_IF_ERROR_RETURN 3562 (soc_mem_write(unit, parent_mem, MEM_BLOCK_ANY, 3563 parent->hw_index, &entry_p)); 3564 if ((parent->hw_index >= 0) && (parent->hw_index <=127)) { 3565 config_mem = LLS_S1_CONFIGm; 3566 sal_memset(entry_c, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS); 3567 /* Programming the L0 start node, since l0==s1, 3568 * using parent->hw_index 3569 */ 3570 soc_mem_field32_set(unit, config_mem, &entry_c, P_START_SPRIf, 3571 parent->hw_index); 3572 soc_mem_field32_set(unit, config_mem, &entry_c, P_NUM_SPRIf, 3573 1); 3574 (soc_mem_write(unit, config_mem, MEM_BLOCK_ANY, 3575 parent->hw_index, 3576 &entry_c)); 3577 } 3578 3579 } 3580 3581 physical_port = port; 3582 rv = _bcm_kt2_cosq_subport_get(unit, gport, &pp_port); 3583 if (rv == BCM_E_NONE) { 3584 BCM_IF_ERROR_RETURN 3585 (bcm_kt2_subport_pp_port_subport_info_get(unit, pp_port, 3586 &info)); 3587 physical_port = info.port; 3588 if (state == _BCM_KT2_COSQ_STATE_ENABLE) { 3589 node->local_port = physical_port; 3590 } 3591 } 3592 3593 if (node->level == _BCM_KT2_COSQ_NODE_LEVEL_S0) { 3594 bmap = SOC_CONTROL(unit)->port_lls_s0_bmap[physical_port]; 3595 } else if (node->level == _BCM_KT2_COSQ_NODE_LEVEL_S1) { 3596 bmap = SOC_CONTROL(unit)->port_lls_s1_bmap[physical_port]; 3597 } else if (node->level == _BCM_KT2_COSQ_NODE_LEVEL_L0) { 3598 bmap = SOC_CONTROL(unit)->port_lls_l0_bmap[physical_port]; 3599 } else if (node->level == _BCM_KT2_COSQ_NODE_LEVEL_L1) { 3600 bmap = SOC_CONTROL(unit)->port_lls_l1_bmap[physical_port]; 3601 } else if (node->level == _BCM_KT2_COSQ_NODE_LEVEL_L2) { 3602 bmap = SOC_CONTROL(unit)->port_lls_l2_bmap[physical_port]; 3603 } else { 3604 return BCM_E_PARAM; 3605 } 3606 3607 if ((node->level == _BCM_KT2_COSQ_NODE_LEVEL_S0 || 3608 node->level == _BCM_KT2_COSQ_NODE_LEVEL_S1) && 3609 (state == _BCM_KT2_COSQ_STATE_ENABLE || 3610 state == _BCM_KT2_COSQ_STATE_DISABLE) && 3611 (!SOC_IS_METROLITE(unit) || !node->linkphy_enabled)) { 3612 if (state == _BCM_KT2_COSQ_STATE_ENABLE) { 3613 SHR_BITSET(bmap, node->hw_index); 3614 } else if (state == _BCM_KT2_COSQ_STATE_DISABLE) { 3615 SHR_BITCLR(bmap, node->hw_index); 3616 } 3617 return BCM_E_NONE; 3618 } 3619 3620 if (node->level == _BCM_KT2_COSQ_NODE_LEVEL_S0 && 3621 (state == _BCM_KT2_COSQ_STATE_WRR_TO_SPRI || 3622 state == _BCM_KT2_COSQ_STATE_SPRI_TO_WRR)) { 3623 return BCM_E_NONE; 3624 } 3625 3626 3627 if (((parent->level == _BCM_KT2_COSQ_NODE_LEVEL_S1) || 3628 (SOC_IS_METROLITE(unit) && parent->linkphy_enabled)) && 3629 node->level == _BCM_KT2_COSQ_NODE_LEVEL_L0) { 3630 return BCM_E_NONE; 3631 } 3632 3633 numq = (parent->wrr_mode == 0) ? ((parent->numq > 8) ? 8 : parent->numq) : 1; 3634 if ((node->cosq_attached_to < numq) && (parent->base_index < 0) && 3635 (parent->mc_base_index < 0)) { 3636 return BCM_E_PARAM; 3637 } 3638 3639 config_mem = mem_c[parent->level]; 3640 if ((node->cosq_attached_to < numq) && (parent->hw_index != -1)) { 3641 start_spri = (BCM_GPORT_IS_MCAST_QUEUE_GROUP(node->gport) || 3642 BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(node->gport)) ? 3643 parent->mc_base_index : parent->base_index; 3644 spri_vector = 1 << node->cosq_attached_to; 3645 update_spri_vector = 1; 3646 3647 sal_memset(entry_c, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS); 3648 3649 if ((parent->level == _BCM_KT2_COSQ_NODE_LEVEL_S0) 3650 && (parent->hw_index >= 128)) { 3651 config_mem = LLS_L0_CONFIGm; 3652 } 3653 SOC_IF_ERROR_RETURN 3654 (soc_mem_read(unit, config_mem, MEM_BLOCK_ALL, parent->hw_index, 3655 &entry_c)); 3656 vec_3_0 = soc_mem_field32_get(unit, config_mem, &entry_c, 3657 P_NUM_SPRIf); 3658 vec_7_4 = soc_mem_field32_get(unit, config_mem, &entry_c, 3659 P_VECT_SPRI_7_4f); 3660 if (state == _BCM_KT2_COSQ_STATE_ENABLE || 3661 state == _BCM_KT2_COSQ_STATE_WRR_TO_SPRI) { 3662 vec_3_0 |= (spri_vector & 0xF); 3663 vec_7_4 |= (spri_vector >> 4); 3664 } else if ((state == _BCM_KT2_COSQ_STATE_SPRI_TO_WRR) || 3665 (state == _BCM_KT2_COSQ_STATE_DISABLE)) { 3666 vec_3_0 &= ~(spri_vector & 0xF); 3667 vec_7_4 &= ~(spri_vector >> 4); 3668 } 3669 3670 /* update LLS_CONFIG with the updated vector */ 3671 if (config_mem == LLS_L1_CONFIGm) { 3672 spri_select = soc_mem_field32_get(unit, config_mem, &entry_c, 3673 P_SPRI_SELECTf); 3674 if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(node->gport) || 3675 BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(node->gport)) { 3676 start_spri_field = P_START_MC_SPRIf; 3677 spri_select |= spri_vector; 3678 } else { 3679 spri_select &= ~(spri_vector); 3680 } 3681 /* Valid if num_spri is not 0 */ 3682 if (vec_3_0 != 0) { 3683 soc_mem_field32_set(unit, config_mem, &entry_c, start_spri_field, start_spri); 3684 } 3685 soc_mem_field32_set(unit, config_mem, &entry_c, P_SPRI_SELECTf, 3686 spri_select); 3687 } else { 3688 /* Valid if num_spri is not 0 */ 3689 if (vec_3_0 != 0) { 3690 soc_mem_field32_set(unit, config_mem, &entry_c, P_START_SPRIf, start_spri); 3691 } 3692 } 3693 soc_mem_field32_set(unit, config_mem, &entry_c, P_NUM_SPRIf, vec_3_0); 3694 soc_mem_field32_set(unit, config_mem, &entry_c, P_VECT_SPRI_7_4f, vec_7_4); 3695 } 3696 3697 parent_mem = mem_p[parent->level]; 3698 sal_memset(entry_p, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS); 3699 sal_memset(&wred_op_node, 0, sizeof(mmu_wred_queue_op_node_map_entry_t)); 3700 3701 switch (state) { 3702 case _BCM_KT2_COSQ_STATE_ENABLE: 3703 if ((parent_mem == LLS_L0_PARENTm) && 3704 (parent->level == _BCM_KT2_COSQ_NODE_LEVEL_ROOT) && 3705 (node->level == _BCM_KT2_COSQ_NODE_LEVEL_L0)) { 3706 soc_mem_field32_set(unit, parent_mem, &entry_p, C_TYPEf, 1); 3707 } 3708 if (parent->level != _BCM_KT2_COSQ_NODE_LEVEL_S1) { 3709 soc_mem_field32_set(unit, parent_mem, &entry_p, C_PARENTf, 3710 parent->hw_index); 3711 if (parent->level == _BCM_KT2_COSQ_NODE_LEVEL_S0) { 3712 soc_mem_field32_set(unit, parent_mem, &entry_p, C_TYPEf, 0); 3713 } 3714 SOC_IF_ERROR_RETURN 3715 (soc_mem_write(unit, parent_mem, MEM_BLOCK_ANY, 3716 node->hw_index, &entry_p)); 3717 } 3718 if (update_spri_vector && parent->linkphy_enabled == 0) { 3719 SOC_IF_ERROR_RETURN 3720 (soc_mem_write(unit, config_mem, MEM_BLOCK_ANY, 3721 parent->hw_index, &entry_c)); 3722 } 3723 3724 if (parent->level == _BCM_KT2_COSQ_NODE_LEVEL_L1) { 3725 /* Read the entry from the RQE map in order to preserve 3726 * the E_TYPE field 3727 */ 3728 SOC_IF_ERROR_RETURN 3729 (READ_MMU_RQE_QUEUE_OP_NODE_MAPm(unit, MEM_BLOCK_ALL, 3730 node->hw_index, 3731 &rqe_op_node)); 3732 soc_mem_field32_set(unit, MMU_RQE_QUEUE_OP_NODE_MAPm, 3733 &rqe_op_node, 3734 OP_NODEf, parent->hw_index); 3735 soc_mem_field32_set(unit, MMU_WRED_QUEUE_OP_NODE_MAPm, 3736 &wred_op_node, 3737 OP_NODEf, parent->hw_index); 3738 SOC_IF_ERROR_RETURN 3739 (WRITE_MMU_RQE_QUEUE_OP_NODE_MAPm(unit, MEM_BLOCK_ALL, 3740 node->hw_index, 3741 &rqe_op_node)); 3742 SOC_IF_ERROR_RETURN 3743 (WRITE_MMU_WRED_QUEUE_OP_NODE_MAPm(unit, MEM_BLOCK_ALL, 3744 node->hw_index, 3745 &wred_op_node)); 3746 3747 if ((soc_feature(unit, soc_feature_mmu_packing) && 3748 IS_EXT_MEM_PORT(unit, port)) && 3749 (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 3750 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport) || 3751 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport))) { 3752 BCM_IF_ERROR_RETURN 3753 (_bcm_kt2_cosq_packing_mode_set(unit, node->hw_index, 1)); 3754 } 3755 3756 /* 3757 * Enable queue only if link is up. If port is down then 3758 * queue will be enabaled during link up event. 3759 */ 3760 BCM_IF_ERROR_RETURN 3761 (_bcm_kt2_cosq_node_get(unit, gport, NULL ,&local_port, NULL, 3762 NULL)); 3763 rv = _bcm_esw_link_get(unit, local_port, &link_state); 3764 if (rv == BCM_E_NONE) { 3765 if (link_state == BCM_PORT_LINK_STATUS_UP) { 3766 _soc_kt2_cosq_end_port_flush(unit,node->hw_index); 3767 } 3768 } else { 3769 _soc_kt2_cosq_end_port_flush(unit,node->hw_index); 3770 } 3771 3772 if (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport) || 3773 BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(gport) || 3774 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) { 3775 SOC_IF_ERROR_RETURN 3776 (READ_EGR_QUEUE_TO_PP_PORT_MAPm(unit, MEM_BLOCK_ALL, 3777 node->hw_index, 3778 &pp_port_map)); 3779 BCM_IF_ERROR_RETURN 3780 (_bcm_kt2_cosq_node_get(unit, gport, NULL ,&local_port, NULL, 3781 NULL)); 3782 3783 soc_mem_field32_set(unit, EGR_QUEUE_TO_PP_PORT_MAPm, 3784 &pp_port_map, PP_PORTf, local_port); 3785 SOC_IF_ERROR_RETURN 3786 (WRITE_EGR_QUEUE_TO_PP_PORT_MAPm(unit, MEM_BLOCK_ALL, 3787 node->hw_index, 3788 &pp_port_map)); 3789 } 3790 3791 rv = _bcm_kt2_cosq_subport_get(unit, gport, &pp_port); 3792 if (rv == BCM_E_NONE) { 3793 BCM_IF_ERROR_RETURN 3794 (bcm_kt2_subport_pp_port_subport_info_get(unit, pp_port, 3795 &info)); 3796 port = info.port; 3797 SOC_IF_ERROR_RETURN 3798 (READ_EGR_QUEUE_TO_PP_PORT_MAPm(unit, MEM_BLOCK_ALL, 3799 node->hw_index, 3800 &pp_port_map)); 3801 soc_mem_field32_set(unit, EGR_QUEUE_TO_PP_PORT_MAPm, 3802 &pp_port_map, PP_PORTf, pp_port); 3803 3804 if (info.port_type == _BCM_KT2_SUBPORT_TYPE_LINKPHY) { 3805 /* LinkPhy - two streams per S0 node 3806 * To understand the queue association with the streams 3807 * read the parent L1 and S1 associated with the queue 3808 * read the stream ID 3809 */ 3810 if ((parent->parent) && (parent->parent->parent)) { 3811 s1_node = parent->parent->parent; 3812 if (SOC_IS_METROLITE(unit)) { 3813 /* Metrolite doesn't have an S0 node in hardware. 3814 * However, SW treats the level as S0 so as to be 3815 * consistant with subport APIs. 3816 */ 3817 if (s1_node->level != _BCM_KT2_COSQ_NODE_LEVEL_S0) { 3818 return BCM_E_INTERNAL; 3819 } 3820 } else if (s1_node->level != _BCM_KT2_COSQ_NODE_LEVEL_S1) { 3821 return BCM_E_INTERNAL; 3822 } 3823 s1_index = s1_node->hw_index; 3824 if (s1_index < 0) { 3825 return BCM_E_INTERNAL; 3826 } 3827 } else { 3828 return BCM_E_INTERNAL; 3829 } 3830 soc_mem_field32_set(unit, EGR_QUEUE_TO_PP_PORT_MAPm, 3831 &pp_port_map, DEVICE_STREAM_IDf, 3832 s1_index); 3833 } else { 3834 soc_mem_field32_set(unit, EGR_QUEUE_TO_PP_PORT_MAPm, 3835 &pp_port_map, SUBPORT_TAGf, 3836 info.subtag); 3837 } 3838 SOC_IF_ERROR_RETURN 3839 (WRITE_EGR_QUEUE_TO_PP_PORT_MAPm(unit, MEM_BLOCK_ALL, 3840 node->hw_index, 3841 &pp_port_map)); 3842 } 3843 SOC_IF_ERROR_RETURN(READ_MMU_THDO_OPNCONFIG_CELLm(unit, 3844 MEM_BLOCK_ANY, parent->hw_index, 3845 &mmu_thdo_opnconfig_cell_entry)); 3846 soc_mem_field32_set(unit, MMU_THDO_OPNCONFIG_CELLm, 3847 &mmu_thdo_opnconfig_cell_entry, 3848 PIDf, port); 3849 SOC_IF_ERROR_RETURN(WRITE_MMU_THDO_OPNCONFIG_CELLm(unit, 3850 MEM_BLOCK_ALL, parent->hw_index, 3851 &mmu_thdo_opnconfig_cell_entry)); 3852 SOC_IF_ERROR_RETURN(READ_MMU_THDO_OPNCONFIG_QENTRYm(unit, 3853 MEM_BLOCK_ANY, parent->hw_index , 3854 &mmu_thdo_opnconfig_qentry_entry)); 3855 soc_mem_field32_set(unit, MMU_THDO_OPNCONFIG_QENTRYm, 3856 &mmu_thdo_opnconfig_qentry_entry, 3857 PIDf, port); 3858 SOC_IF_ERROR_RETURN(WRITE_MMU_THDO_OPNCONFIG_QENTRYm(unit, 3859 MEM_BLOCK_ALL, parent->hw_index , 3860 &mmu_thdo_opnconfig_qentry_entry)); 3861 } 3862 SHR_BITSET(bmap, node->hw_index); 3863 break; 3864 case _BCM_KT2_COSQ_STATE_DISABLE: 3865 mmu_info = _bcm_kt2_mmu_info[unit]; 3866 if (parent->level == _BCM_KT2_COSQ_NODE_LEVEL_ROOT) { 3867 parent_index = (1 << soc_mem_field_length(unit, parent_mem, 3868 C_PARENTf)) - 1; 3869 } else { 3870 parent_index = mmu_info->max_nodes[parent->level] - 1; 3871 } 3872 soc_mem_field32_set(unit, parent_mem, &entry_p, C_PARENTf, 3873 parent_index); 3874 3875 if (parent->level == _BCM_KT2_COSQ_NODE_LEVEL_L1) { 3876 /* flush the queue */ 3877 BCM_IF_ERROR_RETURN(_bcm_kt2_cosq_flush_queues( 3878 unit, physical_port, node, gport)); 3879 SOC_IF_ERROR_RETURN 3880 (READ_LLS_L2_CHILD_STATE1m(unit, MEM_BLOCK_ALL, 3881 node->hw_index, 3882 &l2_child_state)); 3883 if (SOC_MEM_FIELD_VALID(unit, LLS_L2_CHILD_STATE1m, SPAREf)) { 3884 soc_mem_field_get(unit, LLS_L2_CHILD_STATE1m, 3885 (uint32 *)&l2_child_state, SPAREf, 3886 &spare); 3887 } else { 3888 soc_mem_field_get(unit, LLS_L2_CHILD_STATE1m, 3889 (uint32 *)&l2_child_state, 3890 C_ON_WERR_LISTf, &spare); 3891 } 3892 soc_mem_field_get(unit, LLS_L2_CHILD_STATE1m, 3893 (uint32 *)&l2_child_state, 3894 C_ON_MIN_LIST_0f, &min_list); 3895 soc_mem_field_get(unit, LLS_L2_CHILD_STATE1m, 3896 (uint32 *)&l2_child_state, 3897 C_ON_EF_LIST_0f, &ef_list); 3898 soc_mem_field_get(unit, LLS_L2_CHILD_STATE1m, 3899 (uint32 *)&l2_child_state, 3900 C_NOT_EMPTY_0f, ¬_empty); 3901 /* check LLS_L2_CHILD_STATE[7:4] == 4'b0000 to confirm 3902 * that the node is empty */ 3903 if (spare || min_list || ef_list || not_empty) { 3904 return BCM_E_BUSY; 3905 } 3906 SOC_IF_ERROR_RETURN 3907 (READ_LLS_L2_CHILD_STATE1m(unit, MEM_BLOCK_ALL, 3908 node->hw_index, 3909 &l2_child_state)); 3910 if (SOC_MEM_FIELD_VALID(unit, LLS_L2_CHILD_STATE1m, SPAREf)) { 3911 soc_mem_field_get(unit, LLS_L2_CHILD_STATE1m, 3912 (uint32 *)&l2_child_state, SPAREf, 3913 &spare); 3914 } else { 3915 soc_mem_field_get(unit, LLS_L2_CHILD_STATE1m, 3916 (uint32 *)&l2_child_state, 3917 C_ON_WERR_LISTf, &spare); 3918 } 3919 soc_mem_field_get(unit, LLS_L2_CHILD_STATE1m, 3920 (uint32 *)&l2_child_state, 3921 C_ON_MIN_LIST_0f, &min_list); 3922 soc_mem_field_get(unit, LLS_L2_CHILD_STATE1m, 3923 (uint32 *)&l2_child_state, 3924 C_ON_EF_LIST_0f, &ef_list); 3925 soc_mem_field_get(unit, LLS_L2_CHILD_STATE1m, 3926 (uint32 *)&l2_child_state, 3927 C_NOT_EMPTY_0f, ¬_empty); 3928 /* check LLS_L2_CHILD_STATE[7:4] == 4'b0000 to confirm 3929 * that the node is empty */ 3930 if (spare || min_list || ef_list || not_empty) { 3931 return BCM_E_BUSY; 3932 } 3933 3934 if ((soc_feature(unit, soc_feature_mmu_packing) && 3935 IS_EXT_MEM_PORT(unit, port)) && 3936 (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 3937 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport) || 3938 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport))) { 3939 BCM_IF_ERROR_RETURN 3940 (_bcm_kt2_cosq_packing_mode_set(unit, node->hw_index, 0)); 3941 } 3942 3943 SOC_IF_ERROR_RETURN 3944 (READ_MMU_RQE_QUEUE_OP_NODE_MAPm(unit, MEM_BLOCK_ALL, 3945 node->hw_index, 3946 &rqe_op_node)); 3947 soc_mem_field32_set(unit, MMU_RQE_QUEUE_OP_NODE_MAPm, 3948 &rqe_op_node, 3949 OP_NODEf, parent_index); 3950 soc_mem_field32_set(unit, MMU_WRED_QUEUE_OP_NODE_MAPm, 3951 &wred_op_node, 3952 OP_NODEf, parent_index); 3953 SOC_IF_ERROR_RETURN 3954 (soc_mem_write(unit, parent_mem, MEM_BLOCK_ANY, 3955 node->hw_index, &entry_p)); 3956 SOC_IF_ERROR_RETURN 3957 (WRITE_MMU_RQE_QUEUE_OP_NODE_MAPm(unit, MEM_BLOCK_ALL, 3958 node->hw_index, 3959 &rqe_op_node)); 3960 SOC_IF_ERROR_RETURN 3961 (WRITE_MMU_WRED_QUEUE_OP_NODE_MAPm(unit, MEM_BLOCK_ALL, 3962 node->hw_index, 3963 &wred_op_node)); 3964 }else { 3965 if (parent->level != _BCM_KT2_COSQ_NODE_LEVEL_S1) { 3966 SOC_IF_ERROR_RETURN 3967 (soc_mem_write(unit, parent_mem, MEM_BLOCK_ANY, 3968 node->hw_index, 3969 &entry_p)); 3970 } 3971 } 3972 if (update_spri_vector && parent->linkphy_enabled == 0) { 3973 SOC_IF_ERROR_RETURN 3974 (soc_mem_write(unit, config_mem, MEM_BLOCK_ANY, 3975 parent->hw_index, 3976 &entry_c)); 3977 } 3978 SHR_BITCLR(bmap, node->hw_index); 3979 break; 3980 case _BCM_KT2_COSQ_STATE_WRR_TO_SPRI: 3981 case _BCM_KT2_COSQ_STATE_SPRI_TO_WRR: 3982 if (node->level == _BCM_KT2_COSQ_NODE_LEVEL_S1) { 3983 SOC_IF_ERROR_RETURN 3984 (soc_kt2_cosq_s0_sched_set(unit, parent->hw_index, 3985 (state == _BCM_KT2_COSQ_STATE_WRR_TO_SPRI) ? 1 : 0)); 3986 return BCM_E_NONE; 3987 } 3988 3989 if (update_spri_vector) { 3990 #ifdef BCM_KATANA2_SUPPORT 3991 if ( SOC_IS_KATANA2(unit) && !SOC_IS_SABER2(unit) && !SOC_IS_METROLITE(unit) && 3992 (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport) || 3993 BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(gport)) ) { 3994 SOC_IF_ERROR_RETURN(_bcm_egress_metering_freeze(unit, 3995 gport, &setting)); 3996 3997 rv = soc_kt2_cosq_max_bucket_set(unit, physical_port, node->parent->hw_index, _SOC_KT2_COSQ_NODE_LVL_L1); 3998 if (BCM_FAILURE(rv)) { 3999 SOC_IF_ERROR_RETURN(_bcm_egress_metering_thaw(unit, setting)); 4000 return rv; 4001 } 4002 4003 rv = _bcm_kt2_cosq_l2_max_bucket_set(unit, physical_port, node); 4004 if (BCM_FAILURE(rv)) { 4005 SOC_IF_ERROR_RETURN(_bcm_egress_metering_thaw(unit, setting)); 4006 return rv; 4007 } 4008 /* 4009 * for WERR to SP it is possible to have the node in two list min and WERR which 4010 * may lead to time out. To avoid this we need to configure the min as 0 4011 */ 4012 rv = _bcm_kt2_cosq_min_clear(unit, physical_port, node); 4013 if (BCM_FAILURE(rv)) { 4014 SOC_IF_ERROR_RETURN(_bcm_egress_metering_thaw(unit, setting)); 4015 return rv; 4016 } 4017 rv = _bcm_kt2_cosq_dynamic_sp_werr_change(unit, port, 4018 node->level, 4019 node->hw_index, 4020 parent->hw_index, entry_c, 4021 state); 4022 SOC_IF_ERROR_RETURN(_bcm_egress_metering_thaw(unit, setting)); 4023 if (BCM_FAILURE(rv)) { 4024 return rv; 4025 } 4026 }else 4027 #endif 4028 { 4029 SOC_IF_ERROR_RETURN(_soc_egress_metering_freeze(unit, 4030 physical_port, &setting)); 4031 4032 rv = _bcm_kt2_cosq_l2_max_bucket_set(unit, physical_port, node); 4033 if (BCM_FAILURE(rv)) { 4034 SOC_IF_ERROR_RETURN(_soc_egress_metering_thaw(unit, physical_port, setting)); 4035 return rv; 4036 } 4037 /* 4038 * for WERR to SP it is possible to have the node in two list min and WERR which 4039 * may lead to time out. To avoid this we need to configure the min as 0 4040 */ 4041 rv = _bcm_kt2_cosq_min_clear(unit, physical_port, node); 4042 if (BCM_FAILURE(rv)) { 4043 SOC_IF_ERROR_RETURN(_soc_egress_metering_thaw(unit, physical_port, setting)); 4044 return rv; 4045 } 4046 rv = _bcm_kt2_cosq_dynamic_sp_werr_change(unit, port, 4047 node->level, 4048 node->hw_index, 4049 parent->hw_index, entry_c, 4050 state); 4051 SOC_IF_ERROR_RETURN(_soc_egress_metering_thaw(unit, physical_port, setting)); 4052 if (!BCM_SUCCESS(rv)) { 4053 return rv; 4054 } 4055 } 4056 } 4057 break; 4058 default: 4059 break; 4060 } 4061 return BCM_E_NONE; 4062 } 4063 4064 /* 4065 * Function: 4066 * _bcm_kt2_cosq_sched_node_set 4067 * Purpose: 4068 * Set LLS scheduler registers based on GPORT 4069 * Parameters: 4070 * unit - (IN) unit number 4071 * gport - (IN) queue group/scheduler GPORT identifier 4072 * Returns: 4073 * BCM_E_XXX 4074 */ 4075 STATIC int 4076 _bcm_kt2_cosq_sched_node_set(int unit, bcm_gport_t gport, 4077 _bcm_kt2_cosq_state_t state) 4078 { 4079 if (soc_feature(unit, soc_feature_vector_based_spri)) { 4080 return _bcm_kt2_cosq_sched_config_set(unit, gport, state); 4081 } 4082 4083 return BCM_E_PARAM; 4084 } 4085 4086 /* 4087 * Function: 4088 * _bcm_kt2_cosq_port_base_queue_get 4089 * Purpose: 4090 * Get base queue node for a port given any gport 4091 * Parameters: 4092 * unit - (IN) unit number 4093 * port - (IN) port number or GPORT identifier 4094 * cosq - (IN) COS queue number 4095 * node - (OUT) Base queue node 4096 * Returns: 4097 * BCM_E_XXX 4098 */ 4099 STATIC int 4100 _bcm_kt2_cosq_port_base_queue_get(int unit, bcm_port_t port, int cosq, 4101 _bcm_kt2_cosq_node_t **node) 4102 { 4103 int queue_idx, numq, local_port; 4104 _bcm_kt2_mmu_info_t *mmu_info; 4105 4106 if (node == NULL) { 4107 return BCM_E_PARAM; 4108 } 4109 4110 mmu_info = _bcm_kt2_mmu_info[unit]; 4111 BCM_IF_ERROR_RETURN 4112 (_bcm_kt2_cosq_localport_resolve(unit, port, &local_port)); 4113 numq = mmu_info->port[local_port].q_limit - 4114 mmu_info->port[local_port].q_offset; 4115 if (cosq > numq) { 4116 return BCM_E_PARAM; 4117 } 4118 queue_idx = mmu_info->port[local_port].q_offset + cosq; 4119 4120 if (queue_idx > mmu_info->num_queues) { 4121 return BCM_E_INTERNAL; 4122 } 4123 *node = &mmu_info->queue_node[queue_idx]; 4124 return BCM_E_NONE; 4125 } 4126 4127 /* 4128 * Function: 4129 * _bcm_kt2_cosq_sched_set 4130 * Purpose: 4131 * Set scheduling mode 4132 * Parameters: 4133 * unit - (IN) unit number 4134 * port - (IN) port number or GPORT identifier 4135 * cosq - (IN) COS queue number 4136 * mode - (IN) scheduling mode (BCM_COSQ_XXX) 4137 * num_weights - (IN) number of entries in weights array 4138 * weights - (IN) weights array 4139 * Returns: 4140 * BCM_E_XXX 4141 */ 4142 STATIC int 4143 _bcm_kt2_cosq_sched_set(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 4144 int mode, int num_weights, const int weights[]) 4145 { 4146 _bcm_kt2_mmu_info_t *mmu_info; 4147 _bcm_kt2_cosq_node_t *node, *cur_node = NULL, *l0_node, *temp_node = NULL; 4148 bcm_port_t local_port; 4149 int index; 4150 int i, default_weight = -1; 4151 int max_weight; 4152 uint32 fval; 4153 lls_l0_child_weight_cfg_cnt_entry_t l0_weight_cfg; 4154 lls_l1_child_weight_cfg_cnt_entry_t l1_weight_cfg; 4155 lls_l2_child_weight_cfg_cnt_entry_t l2_weight_cfg; 4156 lls_l2_parent_entry_t l2_parent; 4157 _bcm_kt2_cosq_state_t state = _BCM_KT2_COSQ_STATE_NO_CHANGE; 4158 soc_mem_t mem; 4159 uint32 entry[SOC_MAX_MEM_WORDS]; 4160 int rv; 4161 int status = 0; 4162 int physical_port; 4163 4164 if (cosq < 0) { 4165 if (cosq == -1) { 4166 /* caller needs to resolve the wild card value (-1) */ 4167 return BCM_E_INTERNAL; 4168 } else { /* reject all other negative value */ 4169 return BCM_E_PARAM; 4170 } 4171 } 4172 4173 /* Validate weight values */ 4174 if (mode == BCM_COSQ_ROUND_ROBIN || 4175 mode == BCM_COSQ_WEIGHTED_ROUND_ROBIN || 4176 mode == BCM_COSQ_DEFICIT_ROUND_ROBIN || 4177 mode == BCM_COSQ_STRICT) { 4178 max_weight = 4179 (1 << soc_mem_field_length(unit, LLS_L0_CHILD_WEIGHT_CFG_CNTm, 4180 C_WEIGHTf)) - 1; 4181 for (i = 0; i < num_weights; i++) { 4182 if (weights[i] < 0 || weights[i] > max_weight) { 4183 return BCM_E_PARAM; 4184 } 4185 } 4186 } else { 4187 return BCM_E_PARAM; 4188 } 4189 4190 /* To support legacy device compatibility to configure STRICT 4191 mode if weight is "0". 4192 */ 4193 if ((num_weights == 1) && (weights[0] == BCM_COSQ_WEIGHT_STRICT)) { 4194 mode = BCM_COSQ_STRICT; 4195 } 4196 4197 mmu_info = _bcm_kt2_mmu_info[unit]; 4198 4199 if (BCM_GPORT_IS_SUBPORT_PORT(port)) { 4200 BCM_IF_ERROR_RETURN 4201 (_bcm_kt2_cosq_localport_resolve(unit, port, &local_port)); 4202 BCM_IF_ERROR_RETURN 4203 (_bcm_kt2_cosq_port_base_queue_get(unit, port, cosq, &cur_node)); 4204 if (cur_node) { 4205 node = cur_node->parent; 4206 } 4207 } 4208 4209 if (BCM_GPORT_IS_SCHEDULER(port)) { /* ETS style scheduler */ 4210 BCM_IF_ERROR_RETURN 4211 (_bcm_kt2_cosq_node_get(unit, port, NULL, &local_port, NULL, 4212 &node)); 4213 if ((node->wrr_mode == 1) && (mode == BCM_COSQ_STRICT)) { 4214 return BCM_E_PARAM; 4215 } 4216 } else if (!BCM_GPORT_IS_SUBPORT_PORT(port)) { 4217 BCM_IF_ERROR_RETURN 4218 (_bcm_kt2_cosq_localport_resolve(unit, port, &local_port)); 4219 4220 node = &mmu_info->sched_node[local_port]; 4221 4222 if (node->gport < 0) { 4223 return BCM_E_PARAM; 4224 } 4225 4226 if ((node->level == _BCM_KT2_COSQ_NODE_LEVEL_S0) && 4227 ((node = node->child) == NULL)) { 4228 return BCM_E_PARAM; 4229 } 4230 4231 if ((l0_node = node->child) == NULL) { 4232 return BCM_E_PARAM; 4233 } 4234 if (((node = l0_node->child) == NULL) && !(IS_CPU_PORT(unit, local_port))) { 4235 return BCM_E_PARAM; 4236 } 4237 /* 4238 * Adding HG and LB port too. These two ports have 24 queues 4239 * resulting in three L1 nodes. During scheduler configuration 4240 * we need to find first L1 nodes which is last in sibling list. 4241 */ 4242 if (IS_CPU_PORT(unit, local_port) || 4243 IS_HG_PORT(unit, local_port) || 4244 IS_LB_PORT(unit, local_port)) { 4245 /* 4246 * In case when number of cpu queues are not multiples of 8 4247 * there is chance last siblings gets numq < 8, 4248 * which may result in failure , So node is moved to the 4249 * first sibling, which guarantee to have numq = 8 4250 */ 4251 for (cur_node = l0_node; cur_node->sibling != NULL; 4252 cur_node = cur_node->sibling); 4253 for (cur_node = cur_node->child; cur_node->sibling != NULL; 4254 cur_node = cur_node->sibling); 4255 node = cur_node; 4256 } 4257 if (soc_feature(unit, soc_feature_mmu_packing)) { 4258 for (cur_node = node; cur_node != NULL; 4259 cur_node = cur_node->sibling) { 4260 if(cur_node->cosq_attached_to == cosq) { 4261 node = cur_node; 4262 break; 4263 } 4264 } 4265 if (cur_node == NULL) { 4266 /* this cosq is not yet attached */ 4267 return BCM_E_INTERNAL; 4268 } 4269 } 4270 } 4271 4272 if (!BCM_GPORT_IS_SUBPORT_PORT(port)) { 4273 if (!soc_feature(unit, soc_feature_mmu_packing)) { 4274 if ((mode != BCM_COSQ_STRICT) && 4275 (node->numq > 0 && (cosq + num_weights) > node->numq)) { 4276 return BCM_E_PARAM; 4277 } 4278 4279 4280 if (node->cosq_attached_to < 0) { /* Not resolved yet */ 4281 return BCM_E_NOT_FOUND; 4282 } 4283 4284 for (cur_node = node->child; cur_node != NULL; 4285 cur_node = cur_node->sibling) { 4286 if (cur_node->cosq_attached_to == cosq) { 4287 break; 4288 } 4289 } 4290 } else { 4291 for (cur_node = node->child; cur_node != NULL; 4292 cur_node = cur_node->sibling) { 4293 if (cur_node->cosq_attached_to == cosq) { 4294 break; 4295 } 4296 } 4297 } 4298 } 4299 4300 if (cur_node == NULL) { 4301 /* this cosq is not yet attached */ 4302 return BCM_E_INTERNAL; 4303 } 4304 4305 if ((cur_node->level == _BCM_KT2_COSQ_NODE_LEVEL_S0) && 4306 (mode == BCM_COSQ_STRICT)) { 4307 /* S0 supports only RR. */ 4308 return BCM_E_PARAM; 4309 } 4310 4311 if (cur_node->wrr_in_use == 1 && mode == BCM_COSQ_STRICT) { 4312 if (cur_node->cosq_attached_to >= 8) { 4313 return BCM_E_PARAM; 4314 } 4315 state = _BCM_KT2_COSQ_STATE_WRR_TO_SPRI; 4316 } 4317 4318 if (cur_node->wrr_in_use == 0 && mode != BCM_COSQ_STRICT) { 4319 state = _BCM_KT2_COSQ_STATE_SPRI_TO_WRR; 4320 } 4321 4322 if (state == _BCM_KT2_COSQ_STATE_SPRI_TO_WRR && 4323 cur_node->level == _BCM_KT2_COSQ_NODE_LEVEL_L2) { 4324 SOC_IF_ERROR_RETURN 4325 (READ_LLS_L2_PARENTm(unit, MEM_BLOCK_ALL, cur_node->hw_index, 4326 &l2_parent)); 4327 if (soc_mem_field32_get(unit, LLS_L2_PARENTm, 4328 &l2_parent, C_EFf) == 1) { 4329 return BCM_E_PARAM; 4330 } 4331 } 4332 4333 /* Protect LLS hierachy schedule mode change as 4334 * port flush on link flap might be effected 4335 * when there is a change in the LLS hierarchy 4336 */ 4337 SOC_LLS_SCHEDULER_LOCK(unit); 4338 soc_kt_port_flush_state_get(unit, local_port, &status); 4339 if (status) { 4340 4341 LOG_ERROR(BSL_LS_BCM_COSQ, 4342 (BSL_META_U(unit, 4343 "Unit %d Port %d is in flush state," 4344 "Cannot change LLS hierarchy scheduler mode for Cosq hw_cosq=%d.\n"), 4345 unit, local_port, cur_node->cosq_attached_to)); 4346 SOC_LLS_SCHEDULER_UNLOCK(unit); 4347 return BCM_E_RESOURCE; 4348 } 4349 4350 cur_node->wrr_in_use = (mode != BCM_COSQ_STRICT) ? 1 : 0; 4351 if ((cur_node->level == _BCM_KT2_COSQ_NODE_LEVEL_S1) && 4352 (node->num_child == 2)) { 4353 if (cur_node->sibling != NULL) { 4354 temp_node = cur_node->sibling; 4355 } else if (node->child != NULL) { 4356 temp_node = node->child; 4357 } 4358 if (temp_node) { 4359 temp_node->wrr_in_use = (mode != BCM_COSQ_STRICT) ? 1 : 0; 4360 } 4361 } 4362 4363 rv = _bcm_kt2_cosq_sched_node_set(unit, cur_node->gport, state); 4364 SOC_LLS_SCHEDULER_UNLOCK(unit); 4365 if (BCM_FAILURE(rv)) { 4366 if (state == _BCM_KT2_COSQ_STATE_SPRI_TO_WRR) { 4367 cur_node->wrr_in_use = 0; 4368 } else if (state == _BCM_KT2_COSQ_STATE_WRR_TO_SPRI) { 4369 cur_node->wrr_in_use = 1; 4370 } 4371 if ((cur_node->level == _BCM_KT2_COSQ_NODE_LEVEL_S1) && 4372 (node->num_child == 2)) { 4373 if (cur_node->sibling != NULL) { 4374 temp_node = cur_node->sibling; 4375 } else if (node->child != NULL) { 4376 temp_node = node->child; 4377 } 4378 if (temp_node) { 4379 if (state == _BCM_KT2_COSQ_STATE_SPRI_TO_WRR) { 4380 temp_node->wrr_in_use = 0; 4381 } else if (state == _BCM_KT2_COSQ_STATE_WRR_TO_SPRI) { 4382 temp_node->wrr_in_use = 1; 4383 } 4384 } 4385 } 4386 return rv; 4387 } 4388 4389 if ((mode != BCM_COSQ_STRICT)) { 4390 if (_bcm_is_port_linkphy_subport(unit, port, -1)) { 4391 BCM_IF_ERROR_RETURN(_bcm_subport_physical_port_get(unit, 4392 local_port, &physical_port)); 4393 local_port = physical_port; 4394 } 4395 mem = LLS_PORT_CONFIGm; 4396 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, 4397 local_port, &entry)); 4398 fval = ((mode == BCM_COSQ_WEIGHTED_ROUND_ROBIN) || 4399 (mode == BCM_COSQ_ROUND_ROBIN)) ? 1 : 0; 4400 if (soc_mem_field32_get(unit, mem, entry, 4401 PACKET_MODE_WRR_ACCOUNTING_ENABLEf) != fval) { 4402 soc_mem_field32_set(unit, mem, entry, 4403 PACKET_MODE_WRR_ACCOUNTING_ENABLEf, fval); 4404 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ANY, 4405 local_port, &entry)); 4406 } 4407 } 4408 4409 /* 4410 * Check mode and if it is BCM_COSQ_STRICT or BCM_COSQ_ROUND_ROBIN then 4411 * configure default_weight 0 or 1 respectively. 4412 */ 4413 if (mode == BCM_COSQ_STRICT) { 4414 default_weight = 0; 4415 } else if ((node->level == _BCM_KT2_COSQ_NODE_LEVEL_S0) || 4416 (cur_node->level == _BCM_KT2_COSQ_NODE_LEVEL_S0) || 4417 (mode == BCM_COSQ_ROUND_ROBIN)) { 4418 default_weight = 1; 4419 } 4420 4421 switch (node->level) { 4422 case _BCM_KT2_COSQ_NODE_LEVEL_ROOT: /* port scheduler */ 4423 case _BCM_KT2_COSQ_NODE_LEVEL_S0: /* S0 scheduler */ 4424 case _BCM_KT2_COSQ_NODE_LEVEL_S1: /* S1 scheduler */ 4425 for (i = 0; i < num_weights; i++) { 4426 BCM_IF_ERROR_RETURN 4427 (_bcm_kt2_cosq_index_resolve(unit, port, cosq + i, 4428 _BCM_KT2_COSQ_INDEX_STYLE_SCHEDULER, 4429 NULL, &index, NULL)); 4430 SOC_IF_ERROR_RETURN 4431 (READ_LLS_L0_CHILD_WEIGHT_CFG_CNTm(unit, MEM_BLOCK_ALL, 4432 index, &l0_weight_cfg)); 4433 soc_mem_field32_set(unit, LLS_L0_CHILD_WEIGHT_CFG_CNTm, 4434 (uint32 *)&l0_weight_cfg, 4435 C_WEIGHTf, (default_weight == -1) ? weights[i] : default_weight); 4436 soc_mem_field32_set(unit, LLS_L0_CHILD_WEIGHT_CFG_CNTm, 4437 (uint32 *)&l0_weight_cfg, 4438 C_WEIGHT_SURPLUS_COUNTf, 0); 4439 soc_mem_field32_set(unit, LLS_L0_CHILD_WEIGHT_CFG_CNTm, 4440 (uint32 *)&l0_weight_cfg, 4441 C_WEIGHT_COUNTf, 0); 4442 SOC_IF_ERROR_RETURN 4443 (WRITE_LLS_L0_CHILD_WEIGHT_CFG_CNTm(unit, MEM_BLOCK_ALL, 4444 index, &l0_weight_cfg)); 4445 if ((cur_node->level == _BCM_KT2_COSQ_NODE_LEVEL_S1) && 4446 (node->num_child == 2)) { 4447 if (cur_node->sibling != NULL) { 4448 index = cur_node->sibling->hw_index; 4449 } else if (node->child != NULL) { 4450 index = node->child->hw_index; 4451 } 4452 SOC_IF_ERROR_RETURN 4453 (READ_LLS_L0_CHILD_WEIGHT_CFG_CNTm(unit, MEM_BLOCK_ALL, 4454 index, &l0_weight_cfg)); 4455 soc_mem_field32_set(unit, LLS_L0_CHILD_WEIGHT_CFG_CNTm, 4456 (uint32 *)&l0_weight_cfg, 4457 C_WEIGHTf, (default_weight == -1) ? weights[i] : default_weight); 4458 soc_mem_field32_set(unit, LLS_L0_CHILD_WEIGHT_CFG_CNTm, 4459 (uint32 *)&l0_weight_cfg, 4460 C_WEIGHT_SURPLUS_COUNTf, 0); 4461 soc_mem_field32_set(unit, LLS_L0_CHILD_WEIGHT_CFG_CNTm, 4462 (uint32 *)&l0_weight_cfg, 4463 C_WEIGHT_COUNTf, 0); 4464 SOC_IF_ERROR_RETURN 4465 (WRITE_LLS_L0_CHILD_WEIGHT_CFG_CNTm(unit, MEM_BLOCK_ALL, 4466 index, &l0_weight_cfg)); 4467 } 4468 4469 } 4470 break; 4471 4472 case _BCM_KT2_COSQ_NODE_LEVEL_L0: /* L0 scheduler */ 4473 for (i = 0; i < num_weights; i++) { 4474 BCM_IF_ERROR_RETURN 4475 (_bcm_kt2_cosq_index_resolve(unit, port, cosq + i, 4476 _BCM_KT2_COSQ_INDEX_STYLE_SCHEDULER, 4477 NULL, &index, NULL)); 4478 SOC_IF_ERROR_RETURN 4479 (READ_LLS_L1_CHILD_WEIGHT_CFG_CNTm(unit, MEM_BLOCK_ALL, 4480 index, &l1_weight_cfg)); 4481 soc_mem_field32_set(unit, LLS_L1_CHILD_WEIGHT_CFG_CNTm, 4482 (uint32 *)&l1_weight_cfg, 4483 C_WEIGHTf, (default_weight == -1) ? weights[i] : default_weight); 4484 soc_mem_field32_set(unit, LLS_L1_CHILD_WEIGHT_CFG_CNTm, 4485 (uint32 *)&l1_weight_cfg, 4486 C_WEIGHT_SURPLUS_COUNTf, 0); 4487 soc_mem_field32_set(unit, LLS_L1_CHILD_WEIGHT_CFG_CNTm, 4488 (uint32 *)&l1_weight_cfg, 4489 C_WEIGHT_COUNTf, 0); 4490 SOC_IF_ERROR_RETURN 4491 (WRITE_LLS_L1_CHILD_WEIGHT_CFG_CNTm(unit, MEM_BLOCK_ALL, 4492 index, &l1_weight_cfg)); 4493 4494 } 4495 break; 4496 4497 case _BCM_KT2_COSQ_NODE_LEVEL_L1: /* L1 scheduler */ 4498 for (i = 0; i < num_weights; i++) { 4499 BCM_IF_ERROR_RETURN 4500 (_bcm_kt2_cosq_index_resolve(unit, port, cosq + i, 4501 _BCM_KT2_COSQ_INDEX_STYLE_SCHEDULER, 4502 NULL, &index, NULL)); 4503 SOC_IF_ERROR_RETURN 4504 (READ_LLS_L2_CHILD_WEIGHT_CFG_CNTm(unit, MEM_BLOCK_ALL, 4505 index, &l2_weight_cfg)); 4506 soc_mem_field32_set(unit, LLS_L2_CHILD_WEIGHT_CFG_CNTm, 4507 (uint32 *)&l2_weight_cfg, 4508 C_WEIGHTf, (default_weight == -1) ? weights[i] : default_weight); 4509 soc_mem_field32_set(unit, LLS_L2_CHILD_WEIGHT_CFG_CNTm, 4510 (uint32 *)&l2_weight_cfg, 4511 C_WEIGHT_SURPLUS_COUNTf, 0); 4512 soc_mem_field32_set(unit, LLS_L2_CHILD_WEIGHT_CFG_CNTm, 4513 (uint32 *)&l2_weight_cfg, 4514 C_WEIGHT_COUNTf, 0); 4515 SOC_IF_ERROR_RETURN 4516 (WRITE_LLS_L2_CHILD_WEIGHT_CFG_CNTm(unit, MEM_BLOCK_ALL, 4517 index, &l2_weight_cfg)); 4518 4519 } 4520 break; 4521 4522 default: 4523 return BCM_E_INTERNAL; 4524 } 4525 4526 return BCM_E_NONE; 4527 } 4528 4529 /* 4530 * Function: 4531 * _bcm_kt2_cosq_sched_get 4532 * Purpose: 4533 * Get scheduling mode setting 4534 * Parameters: 4535 * unit - (IN) unit number 4536 * port - (IN) port number or GPORT identifier 4537 * cosq - (IN) COS queue number 4538 * mode - (OUT) scheduling mode (BCM_COSQ_XXX) 4539 * num_weights - (IN) number of entries in weights array 4540 * weights - (OUT) weights array 4541 * Returns: 4542 * BCM_E_XXX 4543 */ 4544 STATIC int 4545 _bcm_kt2_cosq_sched_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 4546 int *mode, int num_weights, int weights[]) 4547 { 4548 _bcm_kt2_mmu_info_t *mmu_info; 4549 _bcm_kt2_cosq_node_t *node = NULL, *l0_node = NULL; 4550 _bcm_kt2_cosq_node_t *cur_node = NULL; 4551 bcm_port_t local_port; 4552 int index; 4553 int i; 4554 lls_l0_child_weight_cfg_cnt_entry_t l0_weight_cfg; 4555 lls_l1_child_weight_cfg_cnt_entry_t l1_weight_cfg; 4556 lls_l2_child_weight_cfg_cnt_entry_t l2_weight_cfg; 4557 soc_mem_t mem; 4558 uint32 entry[SOC_MAX_MEM_WORDS]; 4559 int physical_port; 4560 4561 if (cosq < 0) { 4562 if (cosq == -1) { 4563 /* caller needs to resolve the wild card value (-1) */ 4564 return BCM_E_INTERNAL; 4565 } else { /* reject all other negative value */ 4566 return BCM_E_PARAM; 4567 } 4568 } 4569 4570 if (BCM_GPORT_IS_SUBPORT_PORT(port)) { 4571 BCM_IF_ERROR_RETURN 4572 (_bcm_kt2_cosq_localport_resolve(unit, port, &local_port)); 4573 BCM_IF_ERROR_RETURN 4574 (_bcm_kt2_cosq_port_base_queue_get(unit, port, cosq, &cur_node)); 4575 if (cur_node) { 4576 node = cur_node->parent; 4577 } 4578 } 4579 4580 if (BCM_GPORT_IS_SCHEDULER(port)) { /* ETS style scheduler */ 4581 BCM_IF_ERROR_RETURN 4582 (_bcm_kt2_cosq_node_get(unit, port, NULL, &local_port, NULL, 4583 &node)); 4584 } else if (!BCM_GPORT_IS_SUBPORT_PORT(port)) { 4585 if (_BCM_KT2_GPORT_IS_LINKPHY_OR_SUBTAG_SUBPORT_GPORT(unit, port)) { 4586 local_port = _BCM_KT2_SUBPORT_PORT_ID_GET(port); 4587 } else { 4588 BCM_IF_ERROR_RETURN 4589 (_bcm_kt2_cosq_localport_resolve(unit, port, &local_port)); 4590 } 4591 mmu_info = _bcm_kt2_mmu_info[unit]; 4592 4593 node = &mmu_info->sched_node[local_port]; 4594 4595 if (node->gport < 0) { 4596 return BCM_E_PARAM; 4597 } 4598 4599 if ((node->level == _BCM_KT2_COSQ_NODE_LEVEL_S0) && 4600 ((node = node->child) == NULL)) { 4601 return BCM_E_PARAM; 4602 } 4603 4604 if ((l0_node = node->child) == NULL) { 4605 return BCM_E_PARAM; 4606 } 4607 if (((node = l0_node->child) == NULL) && !(IS_CPU_PORT(unit, local_port))) { 4608 return BCM_E_PARAM; 4609 } 4610 /* 4611 * Adding HG and LB port too. These two ports have 24 queues 4612 * resulting in three L1 nodes. During scheduler configuration 4613 * we need to find first L1 nodes which is last in sibling list. 4614 */ 4615 if (IS_CPU_PORT(unit, local_port) || 4616 IS_HG_PORT(unit, local_port) || 4617 IS_LB_PORT(unit, local_port)) { 4618 /* 4619 * In case when number of cpu queues are not multiples of 8 4620 * there is chance last siblings gets numq < 8, 4621 * which may result in failure , So node is moved to the 4622 * first sibling, which guarantee to have numq = 8 4623 */ 4624 for (cur_node = l0_node; cur_node->sibling != NULL; 4625 cur_node = cur_node->sibling); 4626 for (cur_node = cur_node->child; cur_node->sibling != NULL; 4627 cur_node = cur_node->sibling); 4628 node = cur_node; 4629 } 4630 } 4631 4632 if (node == NULL) { 4633 return BCM_E_INTERNAL; 4634 } 4635 if (node->numq > 0 && (cosq + num_weights) > node->numq) { 4636 return BCM_E_PARAM; 4637 } 4638 4639 if (node->cosq_attached_to < 0) { /* Not resolved yet */ 4640 return BCM_E_NOT_FOUND; 4641 } 4642 4643 if (!BCM_GPORT_IS_SUBPORT_PORT(port)) { 4644 for (cur_node = node->child; cur_node != NULL; 4645 cur_node = cur_node->sibling) { 4646 if (cur_node->cosq_attached_to == cosq) { 4647 break; 4648 } 4649 } 4650 } 4651 4652 if (cur_node == NULL) { 4653 /* this cosq is not yet attached */ 4654 return BCM_E_INTERNAL; 4655 } 4656 4657 switch (node->level) { 4658 case _BCM_KT2_COSQ_NODE_LEVEL_ROOT: /* port scheduler */ 4659 case _BCM_KT2_COSQ_NODE_LEVEL_S0: /* S0 scheduler */ 4660 case _BCM_KT2_COSQ_NODE_LEVEL_S1: /* S1 scheduler */ 4661 for (i = 0; i < num_weights; i++) { 4662 BCM_IF_ERROR_RETURN 4663 (_bcm_kt2_cosq_index_resolve(unit, port, cosq + i, 4664 _BCM_KT2_COSQ_INDEX_STYLE_SCHEDULER, 4665 NULL, &index, NULL)); 4666 SOC_IF_ERROR_RETURN 4667 (READ_LLS_L0_CHILD_WEIGHT_CFG_CNTm(unit, MEM_BLOCK_ALL, 4668 index, &l0_weight_cfg)); 4669 weights[i] = soc_mem_field32_get(unit, LLS_L0_CHILD_WEIGHT_CFG_CNTm, 4670 (uint32 *)&l0_weight_cfg, 4671 C_WEIGHTf); 4672 } 4673 break; 4674 4675 case _BCM_KT2_COSQ_NODE_LEVEL_L0: /* L0 scheduler */ 4676 for (i = 0; i < num_weights; i++) { 4677 BCM_IF_ERROR_RETURN 4678 (_bcm_kt2_cosq_index_resolve(unit, port, cosq + i, 4679 _BCM_KT2_COSQ_INDEX_STYLE_SCHEDULER, 4680 NULL, &index, NULL)); 4681 SOC_IF_ERROR_RETURN 4682 (READ_LLS_L1_CHILD_WEIGHT_CFG_CNTm(unit, MEM_BLOCK_ALL, 4683 index, &l1_weight_cfg)); 4684 weights[i] = soc_mem_field32_get(unit, LLS_L1_CHILD_WEIGHT_CFG_CNTm, 4685 (uint32 *)&l1_weight_cfg, 4686 C_WEIGHTf); 4687 4688 } 4689 break; 4690 4691 case _BCM_KT2_COSQ_NODE_LEVEL_L1: /* L1 scheduler */ 4692 for (i = 0; i < num_weights; i++) { 4693 BCM_IF_ERROR_RETURN 4694 (_bcm_kt2_cosq_index_resolve(unit, port, cosq + i, 4695 _BCM_KT2_COSQ_INDEX_STYLE_SCHEDULER, 4696 NULL, &index, NULL)); 4697 SOC_IF_ERROR_RETURN 4698 (READ_LLS_L2_CHILD_WEIGHT_CFG_CNTm(unit, MEM_BLOCK_ALL, 4699 index, &l2_weight_cfg)); 4700 weights[i] = soc_mem_field32_get(unit, LLS_L2_CHILD_WEIGHT_CFG_CNTm, 4701 (uint32 *)&l2_weight_cfg, 4702 C_WEIGHTf); 4703 4704 } 4705 break; 4706 default: 4707 return BCM_E_INTERNAL; 4708 } 4709 4710 if (cur_node->wrr_in_use == 0) { 4711 *mode = BCM_COSQ_STRICT; 4712 } else { 4713 if (_bcm_is_port_linkphy_subport(unit, port, -1)) { 4714 BCM_IF_ERROR_RETURN(_bcm_subport_physical_port_get(unit, 4715 local_port, &physical_port)); 4716 local_port = physical_port; 4717 } 4718 mem = LLS_PORT_CONFIGm; 4719 BCM_IF_ERROR_RETURN( 4720 soc_mem_read(unit, mem, MEM_BLOCK_ALL, local_port, &entry)); 4721 if (soc_mem_field32_get(unit, mem, entry, 4722 PACKET_MODE_WRR_ACCOUNTING_ENABLEf)) { 4723 *mode = BCM_COSQ_WEIGHTED_ROUND_ROBIN; 4724 } else { 4725 *mode = BCM_COSQ_DEFICIT_ROUND_ROBIN; 4726 } 4727 } 4728 4729 return BCM_E_NONE; 4730 } 4731 4732 /* 4733 * Function: 4734 * _bcm_kt2_cosq_port_sched_set 4735 * Purpose: 4736 * Set scheduling mode setting for a port 4737 * Parameters: 4738 * unit - (IN) unit number 4739 * port - (IN) port number or GPORT identifier 4740 * cosq - (IN) COS queue number 4741 * mode - (IN) scheduling mode (BCM_COSQ_XXX) 4742 * num_weights - (IN) number of entries in weights array 4743 * weights - (IN) weights array 4744 * Returns: 4745 * BCM_E_XXX 4746 */ 4747 STATIC int 4748 _bcm_kt2_cosq_port_sched_set(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 4749 int mode, int num_weights, int *weights) 4750 { 4751 int i; 4752 4753 for (i = 0; i < num_weights; i++) { 4754 BCM_IF_ERROR_RETURN 4755 (_bcm_kt2_cosq_sched_set(unit, port, (cosq + i), 4756 mode, 1, &weights[i])); 4757 4758 } 4759 4760 return BCM_E_NONE; 4761 } 4762 4763 /* 4764 * Function: 4765 * _bcm_kt2_cosq_port_sched_get 4766 * Purpose: 4767 * Set scheduling mode setting for a port 4768 * Parameters: 4769 * unit - (IN) unit number 4770 * port - (IN) port number or GPORT identifier 4771 * cosq - (IN) COS queue number 4772 * mode - (OUT) scheduling mode (BCM_COSQ_XXX) 4773 * num_weights - (IN) number of entries in weights array 4774 * weights - (OUT) weights array 4775 * Returns: 4776 * BCM_E_XXX 4777 */ 4778 STATIC int 4779 _bcm_kt2_cosq_port_sched_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 4780 int *mode, int num_weights, int *weights) 4781 { 4782 int i; 4783 4784 for (i = 0; i < num_weights; i++) { 4785 BCM_IF_ERROR_RETURN 4786 (_bcm_kt2_cosq_sched_get(unit, port, (cosq + i), 4787 mode, 1, &weights[i])); 4788 4789 } 4790 4791 return BCM_E_NONE; 4792 } 4793 4794 /* 4795 * Function: 4796 * _bcm_kt2_cosq_gport_egress_mapping_set_regular 4797 * Purpose: 4798 * Determine which COS queue a given priority currently maps to. 4799 * Parameters: 4800 * unit - (IN) unit number 4801 * gport - (IN) queue group GPORT identifier 4802 * priority - (IN) priority value to map 4803 * cosq - (IN) COS queue to map to 4804 * Returns: 4805 * BCM_E_XXX 4806 */ 4807 STATIC int 4808 _bcm_kt2_cosq_gport_egress_mapping_set_regular(int unit, bcm_port_t gport, 4809 bcm_cos_t priority, 4810 bcm_cos_queue_t cosq , int flags) 4811 { 4812 bcm_port_t port; 4813 soc_field_t field = REDIRECT_COSf; 4814 egr_port_entry_t egr_port_entry; 4815 egr_cos_map_entry_t cos_map_entries[16]; 4816 void *entries[1]; 4817 uint32 old_index, new_index; 4818 int rv; 4819 4820 if (priority < 0 || priority >= 16) { 4821 return BCM_E_PARAM; 4822 } 4823 4824 if (BCM_GPORT_IS_SET(gport)) { 4825 BCM_IF_ERROR_RETURN( 4826 bcm_esw_port_local_get(unit, gport, &port)); 4827 } else { 4828 port = gport; 4829 } 4830 4831 if (cosq < 0 || cosq > 7) { 4832 return BCM_E_PARAM; 4833 } 4834 4835 if (!SOC_PORT_VALID(unit, port) || !IS_ALL_PORT(unit, port)) { 4836 return BCM_E_PORT; 4837 } 4838 4839 4840 entries[0] = &cos_map_entries; 4841 4842 BCM_IF_ERROR_RETURN 4843 (READ_EGR_PORTm(unit, MEM_BLOCK_ANY, port, &egr_port_entry)); 4844 old_index = soc_mem_field32_get(unit, EGR_PORTm, &egr_port_entry, 4845 EGR_COS_MAP_SELf); 4846 old_index *= 16; 4847 4848 soc_mem_lock(unit, EGR_PORTm); 4849 4850 rv = soc_profile_mem_get(unit, _bcm_kt2_egr_cos_map_profile[unit], 4851 old_index, 16, entries); 4852 if (BCM_SUCCESS(rv)) { 4853 soc_mem_field32_set(unit, EGR_COS_MAPm, &cos_map_entries[priority], field, 4854 cosq); 4855 4856 rv = soc_profile_mem_delete(unit, _bcm_kt2_egr_cos_map_profile[unit], 4857 old_index); 4858 if (BCM_FAILURE(rv)) { 4859 soc_mem_unlock(unit, EGR_PORTm); 4860 return rv; 4861 } 4862 4863 rv = soc_profile_mem_add(unit, _bcm_kt2_egr_cos_map_profile[unit], entries, 4864 16, &new_index); 4865 if (rv == SOC_E_RESOURCE) { 4866 (void)soc_profile_mem_reference(unit, _bcm_kt2_egr_cos_map_profile[unit], 4867 old_index, 16); 4868 } 4869 } else { 4870 rv = soc_profile_mem_add(unit, _bcm_kt2_egr_cos_map_profile[unit], entries, 4871 16, &new_index); 4872 } 4873 4874 soc_mem_unlock(unit, EGR_PORTm); 4875 4876 if (BCM_FAILURE(rv)) { 4877 return rv; 4878 } 4879 4880 soc_mem_field32_set(unit, EGR_PORTm, &egr_port_entry, EGR_COS_MAP_SELf, 4881 new_index / 16); 4882 BCM_IF_ERROR_RETURN 4883 (WRITE_EGR_PORTm(unit, MEM_BLOCK_ANY, port, &egr_port_entry)); 4884 4885 return BCM_E_NONE; 4886 } 4887 /* 4888 * Function: 4889 * _bcm_kt2_cosq_mapping_set_regular 4890 * Purpose: 4891 * Determine which COS queue a given priority currently maps to. 4892 * Parameters: 4893 * unit - (IN) unit number 4894 * gport - (IN) queue group GPORT identifier 4895 * count - (IN) number of entries to be configured 4896 * priority_array - (IN) priority array value to map 4897 * cosq_array - (IN) COS queue array to map to 4898 * Returns: 4899 * BCM_E_XXX 4900 */ 4901 STATIC int 4902 _bcm_kt2_cosq_mapping_set_regular(int unit, bcm_port_t gport, 4903 int count, 4904 bcm_cos_t *priority_array, 4905 bcm_cos_queue_t *cosq_array) 4906 { 4907 _bcm_kt2_mmu_info_t *mmu_info; 4908 bcm_port_t port; 4909 int numq; 4910 bcm_cos_queue_t hw_cosq[16]; 4911 soc_field_t field = COSf; 4912 cos_map_sel_entry_t cos_map_sel_entry; 4913 port_cos_map_entry_t cos_map_entries[16]; 4914 void *entries[1]; 4915 uint32 old_index, new_index; 4916 int count_index= 0; 4917 int rv; 4918 #ifndef BCM_COSQ_HIGIG_MAP_DISABLE 4919 int cpu_hg_index = 0; 4920 #endif 4921 4922 if (count < 1 || count > 16) { 4923 return BCM_E_PARAM; 4924 } 4925 4926 if (priority_array == NULL || cosq_array == NULL){ 4927 return BCM_E_PARAM; 4928 } 4929 4930 for (count_index = 0; count_index < count; count_index++) { 4931 if (priority_array[count_index] < 0 || priority_array[count_index] >= 16) { 4932 return BCM_E_PARAM; 4933 } 4934 4935 hw_cosq[count_index] = cosq_array[count_index]; 4936 } 4937 4938 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 4939 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 4940 for (count_index = 0; count_index < count; count_index++) { 4941 BCM_IF_ERROR_RETURN 4942 (_bcm_kt2_cosq_index_resolve 4943 (unit, gport, cosq_array[count_index], _BCM_KT2_COSQ_INDEX_STYLE_UCAST_QUEUE, 4944 &port, &(hw_cosq[count_index]), NULL)); 4945 } 4946 } else if(_BCM_KT2_GPORT_IS_LINKPHY_OR_SUBTAG_SUBPORT_GPORT (unit, gport)) { 4947 port = _BCM_KT2_SUBPORT_PORT_ID_GET(gport); 4948 } else { 4949 if (BCM_GPORT_IS_SET(gport)) { 4950 BCM_IF_ERROR_RETURN( 4951 bcm_esw_port_local_get(unit, gport, &port)); 4952 } else { 4953 port = gport; 4954 } 4955 4956 if (!SOC_PORT_VALID(unit, port) || !IS_ALL_PORT(unit, port)) { 4957 return BCM_E_PORT; 4958 } 4959 4960 } 4961 4962 mmu_info = _bcm_kt2_mmu_info[unit]; 4963 numq = mmu_info->port[port].q_limit - 4964 mmu_info->port[port].q_offset; 4965 4966 for (count_index = 0; count_index < count; count_index++) { 4967 if (cosq_array[count_index] >= numq) { 4968 return BCM_E_PARAM; 4969 } 4970 4971 } 4972 4973 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 4974 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 4975 field = (numq <= 8) ? COSf : HG_COSf; 4976 } 4977 4978 entries[0] = &cos_map_entries; 4979 4980 BCM_IF_ERROR_RETURN 4981 (READ_COS_MAP_SELm(unit, MEM_BLOCK_ANY, port, &cos_map_sel_entry)); 4982 old_index = soc_mem_field32_get(unit, COS_MAP_SELm, &cos_map_sel_entry, 4983 SELECTf); 4984 old_index *= 16; 4985 4986 soc_mem_lock(unit, PORT_COS_MAPm); 4987 4988 rv = soc_profile_mem_get(unit, _bcm_kt2_cos_map_profile[unit], 4989 old_index, 16, entries); 4990 if (BCM_SUCCESS(rv)) { 4991 for (count_index = 0; count_index < count; count_index++) { 4992 soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[priority_array[count_index]], field, 4993 hw_cosq[count_index]); 4994 } 4995 4996 4997 rv = soc_profile_mem_delete(unit, _bcm_kt2_cos_map_profile[unit], 4998 old_index); 4999 #ifndef BCM_COSQ_HIGIG_MAP_DISABLE 5000 if (BCM_SUCCESS(rv) && IS_CPU_PORT(unit, port)) { 5001 rv = soc_profile_mem_delete(unit, _bcm_kt2_cos_map_profile[unit], 5002 old_index); 5003 } 5004 #endif /* BCM_COSQ_HIGIG_MAP_DISABLE */ 5005 if (BCM_FAILURE(rv)) { 5006 soc_mem_unlock(unit, PORT_COS_MAPm); 5007 return rv; 5008 } 5009 5010 rv = soc_profile_mem_add(unit, _bcm_kt2_cos_map_profile[unit], entries, 5011 16, &new_index); 5012 #ifndef BCM_COSQ_HIGIG_MAP_DISABLE 5013 if (BCM_SUCCESS(rv) && IS_CPU_PORT(unit, port)) { 5014 rv = soc_profile_mem_reference(unit, _bcm_kt2_cos_map_profile[unit], 5015 new_index, 16); 5016 } 5017 #endif /* BCM_COSQ_HIGIG_MAP_DISABLE */ 5018 5019 if (rv == SOC_E_RESOURCE) { 5020 (void)soc_profile_mem_reference(unit, _bcm_kt2_cos_map_profile[unit], 5021 old_index, 16); 5022 #ifndef BCM_COSQ_HIGIG_MAP_DISABLE 5023 if (IS_CPU_PORT(unit, port)) { 5024 (void)soc_profile_mem_reference(unit, 5025 _bcm_kt2_cos_map_profile[unit], 5026 old_index, 16); 5027 } 5028 #endif /* BCM_COSQ_HIGIG_MAP_DISABLE */ 5029 } 5030 } else { 5031 rv = soc_profile_mem_add(unit, _bcm_kt2_cos_map_profile[unit], entries, 5032 16, &new_index); 5033 #ifndef BCM_COSQ_HIGIG_MAP_DISABLE 5034 if (BCM_SUCCESS(rv) && IS_CPU_PORT(unit, port)) { 5035 rv = soc_profile_mem_reference(unit, _bcm_kt2_cos_map_profile[unit], 5036 new_index, 16); 5037 } 5038 #endif /* BCM_COSQ_HIGIG_MAP_DISABLE */ 5039 } 5040 5041 soc_mem_unlock(unit, PORT_COS_MAPm); 5042 5043 if (BCM_FAILURE(rv)) { 5044 return rv; 5045 } 5046 5047 soc_mem_field32_set(unit, COS_MAP_SELm, &cos_map_sel_entry, SELECTf, 5048 new_index / 16); 5049 BCM_IF_ERROR_RETURN 5050 (WRITE_COS_MAP_SELm(unit, MEM_BLOCK_ANY, port, &cos_map_sel_entry)); 5051 5052 #ifndef BCM_COSQ_HIGIG_MAP_DISABLE 5053 if (IS_CPU_PORT(unit, port)) { 5054 cpu_hg_index = SOC_INFO(unit).cpu_hg_pp_port_index; 5055 BCM_IF_ERROR_RETURN 5056 (soc_mem_field32_modify(unit, COS_MAP_SELm, 5057 cpu_hg_index, SELECTf, 5058 new_index / 16)); 5059 } 5060 #endif /* BCM_COSQ_HIGIG_MAP_DISABLE */ 5061 5062 return BCM_E_NONE; 5063 } 5064 5065 /* 5066 * Function: 5067 * _bcm_kt2_cosq_bucket_set 5068 * Purpose: 5069 * Configure COS queue bandwidth control bucket 5070 * Parameters: 5071 * unit - (IN) unit number 5072 * port - (IN) port number or GPORT identifier 5073 * cosq - (IN) COS queue number 5074 * min_quantum - (IN) kbps or packet/second 5075 * max_quantum - (IN) kbps or packet/second 5076 * burst_quantum - (IN) kbps or packet/second 5077 * flags - (IN) 5078 * Returns: 5079 * BCM_E_XXX 5080 * Notes: 5081 * If port is any form of local port, cosq is the hardware queue index. 5082 */ 5083 STATIC int 5084 _bcm_kt2_cosq_bucket_set(int unit, bcm_gport_t port, bcm_cos_queue_t cosq, 5085 uint32 min_quantum, uint32 max_quantum, 5086 uint32 burst_min_quantum, uint32 burst_max_quantum, 5087 uint32 flags) 5088 { 5089 int rv; 5090 _bcm_kt2_cosq_node_t *node; 5091 bcm_port_t local_port; 5092 int index; 5093 soc_mem_t config_mem[2]; 5094 lls_port_shaper_config_c_entry_t port_entry; 5095 lls_l0_shaper_config_c_entry_t l0_entry; 5096 lls_l1_shaper_config_c_entry_t l1_entry; 5097 lls_l2_shaper_config_lower_entry_t l2_entry; 5098 lls_s0_shaper_config_c_entry_t s0_entry; 5099 uint32 rate_exp[2], rate_mantissa[2]; 5100 uint32 burst_exp[2], burst_mantissa[2]; 5101 uint32 cycle_sel[2]; 5102 uint32 burst_min, burst_max; 5103 int i, idx, status; 5104 int level = _BCM_KT2_COSQ_NODE_LEVEL_L2; 5105 soc_field_t rate_exp_f[] = { 5106 C_MAX_REF_RATE_EXPf, C_MIN_REF_RATE_EXPf 5107 }; 5108 soc_field_t rate_mant_f[] = { 5109 C_MAX_REF_RATE_MANTf, C_MIN_REF_RATE_MANTf 5110 }; 5111 soc_field_t burst_exp_f[] = { 5112 C_MAX_THLD_EXPf, C_MIN_THLD_EXPf 5113 }; 5114 soc_field_t burst_mant_f[] = { 5115 C_MAX_THLD_MANTf, C_MIN_THLD_MANTf 5116 }; 5117 soc_field_t cycle_sel_f[] = { 5118 C_MAX_CYCLE_SELf, C_MIN_CYCLE_SELf 5119 }; 5120 soc_field_t rate_exp_fields[] = { 5121 C_MAX_REF_RATE_EXP_0f, C_MAX_REF_RATE_EXP_1f, 5122 C_MAX_REF_RATE_EXP_2f, C_MAX_REF_RATE_EXP_3f, 5123 C_MIN_REF_RATE_EXP_0f, C_MIN_REF_RATE_EXP_1f, 5124 C_MIN_REF_RATE_EXP_2f, C_MIN_REF_RATE_EXP_3f 5125 }; 5126 soc_field_t rate_mant_fields[] = { 5127 C_MAX_REF_RATE_MANT_0f, C_MAX_REF_RATE_MANT_1f, 5128 C_MAX_REF_RATE_MANT_2f, C_MAX_REF_RATE_MANT_3f, 5129 C_MIN_REF_RATE_MANT_0f, C_MIN_REF_RATE_MANT_1f, 5130 C_MIN_REF_RATE_MANT_2f, C_MIN_REF_RATE_MANT_3f 5131 }; 5132 soc_field_t burst_exp_fields[] = { 5133 C_MAX_THLD_EXP_0f, C_MAX_THLD_EXP_1f, 5134 C_MAX_THLD_EXP_2f, C_MAX_THLD_EXP_3f, 5135 C_MIN_THLD_EXP_0f, C_MIN_THLD_EXP_1f, 5136 C_MIN_THLD_EXP_2f, C_MIN_THLD_EXP_3f 5137 }; 5138 soc_field_t burst_mant_fields[] = { 5139 C_MAX_THLD_MANT_0f, C_MAX_THLD_MANT_1f, 5140 C_MAX_THLD_MANT_2f, C_MAX_THLD_MANT_3f, 5141 C_MIN_THLD_MANT_0f, C_MIN_THLD_MANT_1f, 5142 C_MIN_THLD_MANT_2f, C_MIN_THLD_MANT_3f 5143 }; 5144 soc_field_t cycle_sel_fields[] = { 5145 C_MAX_CYCLE_SEL_0f, C_MAX_CYCLE_SEL_1f, 5146 C_MAX_CYCLE_SEL_2f, C_MAX_CYCLE_SEL_3f, 5147 C_MIN_CYCLE_SEL_0f, C_MIN_CYCLE_SEL_1f, 5148 C_MIN_CYCLE_SEL_2f, C_MIN_CYCLE_SEL_3f 5149 }; 5150 int shaper_bucket_index = 0; 5151 5152 if (cosq < 0) { 5153 if (cosq == -1) { 5154 /* caller needs to resolve the wild card value (-1) */ 5155 return BCM_E_INTERNAL; 5156 } else { /* reject all other negative value */ 5157 return BCM_E_PARAM; 5158 } 5159 } 5160 5161 5162 BCM_IF_ERROR_RETURN 5163 (_bcm_kt2_cosq_index_resolve(unit, port, cosq, 5164 _BCM_KT2_COSQ_INDEX_STYLE_BUCKET, 5165 &local_port, &index, NULL)); 5166 5167 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 5168 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) || 5169 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port) || 5170 BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(port) || 5171 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port) || 5172 BCM_GPORT_IS_SCHEDULER(port)) { 5173 BCM_IF_ERROR_RETURN 5174 (_bcm_kt2_cosq_node_get(unit, port, NULL, NULL, NULL, &node)); 5175 level = node->level; 5176 5177 if ((level == _BCM_KT2_COSQ_NODE_LEVEL_S0 || 5178 level == _BCM_KT2_COSQ_NODE_LEVEL_S1 || 5179 level== _BCM_KT2_COSQ_NODE_LEVEL_ROOT) && 5180 (min_quantum > 0)) { 5181 /* min shaper is not supported */ 5182 return BCM_E_PARAM; 5183 } 5184 } 5185 5186 for (i=0; i<2; i++) { 5187 sal_memset(&rate_mantissa[i], 0, sizeof(rate_mantissa[i])); 5188 sal_memset(&rate_exp[i], 0, sizeof(rate_exp[i])); 5189 sal_memset(&burst_mantissa[i] , 0, sizeof(burst_mantissa[i])); 5190 sal_memset(&burst_exp[i], 0, sizeof(burst_exp[i])); 5191 sal_memset(&cycle_sel[i], 0, sizeof(cycle_sel[i])); 5192 } 5193 if (!(flags & _BCM_XGS_METER_FLAG_RESET)) { 5194 5195 /* compute exp and mantissa and program the registers */ 5196 rv = soc_katana_get_shaper_rate_info(unit, max_quantum, 5197 &rate_mantissa[0], &rate_exp[0]); 5198 if (BCM_FAILURE(rv)) { 5199 return(rv); 5200 } 5201 5202 rv = soc_katana_get_shaper_rate_info(unit, min_quantum, 5203 &rate_mantissa[1], &rate_exp[1]); 5204 if (BCM_FAILURE(rv)) { 5205 return(rv); 5206 } 5207 5208 burst_max = burst_max_quantum; 5209 burst_min = burst_min_quantum; 5210 rv = soc_katana_get_shaper_burst_info(unit, burst_max, 5211 &burst_mantissa[0], 5212 &burst_exp[0], flags); 5213 if (BCM_FAILURE(rv)) { 5214 return(rv); 5215 } 5216 5217 rv = soc_katana_get_shaper_burst_info(unit, burst_min, 5218 &burst_mantissa[1], 5219 &burst_exp[1], flags); 5220 if (BCM_FAILURE(rv)) { 5221 return(rv); 5222 } 5223 5224 if (!(flags & _BCM_XGS_METER_FLAG_NON_BURST_CORRECTION)) { 5225 /* set recommended burst settings */ 5226 for (i = 0; i < 2; i++) { 5227 if (rate_exp[i] != 0) { 5228 if (rate_exp[i] < 10) { 5229 burst_exp[i] = 5; 5230 burst_mantissa[i] = 0; 5231 } else { 5232 burst_exp[i] = rate_exp[i] - 4; 5233 burst_mantissa[i] = (rate_mantissa[i] >> 3); 5234 } 5235 } 5236 } 5237 /* set recommended refresh rate/cycle_sel settings */ 5238 for (i = 0; i < 2; i++) { 5239 if (rate_exp[i] > 4) { 5240 cycle_sel[i] = 0; 5241 } else if (rate_exp[i] > 1) { 5242 cycle_sel[i] = 5 - rate_exp[i]; 5243 } else { 5244 cycle_sel[i] = 4; 5245 } 5246 } 5247 } else { 5248 for (i = 0; i < 2; i++) { 5249 if ((burst_exp[i] >= 14) && (burst_mantissa[i] >= 124)) { 5250 /* maximum supported is 2064384 byte */ 5251 burst_exp[i] = 14; 5252 burst_mantissa[i] = 124; 5253 } 5254 rv = soc_katana_compute_refresh_rate(unit, rate_exp[i], 5255 rate_mantissa[i], burst_exp[i], 5256 burst_mantissa[i], &cycle_sel[i]); 5257 if (BCM_FAILURE(rv)) { 5258 return(rv); 5259 } 5260 } 5261 } 5262 } 5263 5264 /* 5265 * At this point, port might be in flush state. 5266 * If so, return. 5267 */ 5268 SOC_EGRESS_METERING_LOCK(unit); 5269 soc_kt_port_flush_state_get(unit, local_port, &status); 5270 if (status) { 5271 5272 LOG_INFO(BSL_LS_BCM_COSQ, 5273 (BSL_META_U(unit, 5274 "Unit %d Port %d is in flush state.\n"), unit, local_port)); 5275 5276 SOC_EGRESS_METERING_UNLOCK(unit); 5277 return BCM_E_RESOURCE; 5278 } 5279 5280 switch (level) { 5281 case _BCM_KT2_COSQ_NODE_LEVEL_ROOT: 5282 config_mem[0] = LLS_PORT_SHAPER_CONFIG_Cm; 5283 rv = soc_mem_read(unit, config_mem[0], MEM_BLOCK_ALL, 5284 index, &port_entry); 5285 if (BCM_FAILURE(rv)) { 5286 SOC_EGRESS_METERING_UNLOCK(unit); 5287 return(rv); 5288 } 5289 soc_mem_field32_set(unit, config_mem[0], &port_entry, 5290 rate_exp_f[0], rate_exp[0]); 5291 soc_mem_field32_set(unit, config_mem[0], &port_entry, 5292 rate_mant_f[0], rate_mantissa[0]); 5293 soc_mem_field32_set(unit, config_mem[0], &port_entry, 5294 burst_exp_f[0], burst_exp[0]); 5295 soc_mem_field32_set(unit, config_mem[0], &port_entry, 5296 burst_mant_f[0], burst_mantissa[0]); 5297 soc_mem_field32_set(unit, config_mem[0], &port_entry, 5298 cycle_sel_f[0], cycle_sel[0]); 5299 rv = soc_mem_write(unit, config_mem[0], 5300 MEM_BLOCK_ALL, index, &port_entry); 5301 if (BCM_FAILURE(rv)) { 5302 SOC_EGRESS_METERING_UNLOCK(unit); 5303 return(rv); 5304 } 5305 5306 break; 5307 5308 case _BCM_KT2_COSQ_NODE_LEVEL_L0: 5309 config_mem[0] = LLS_L0_SHAPER_CONFIG_Cm; 5310 config_mem[1] = LLS_L0_MIN_CONFIG_Cm; 5311 for (i = 0; i < 2; i++) { 5312 rv = soc_mem_read(unit, config_mem[i], MEM_BLOCK_ALL, 5313 index, &l0_entry); 5314 if (BCM_FAILURE(rv)) { 5315 SOC_EGRESS_METERING_UNLOCK(unit); 5316 return(rv); 5317 } 5318 5319 soc_mem_field32_set(unit, config_mem[i], &l0_entry, 5320 rate_exp_f[i], rate_exp[i]); 5321 soc_mem_field32_set(unit, config_mem[i], &l0_entry, 5322 rate_mant_f[i], rate_mantissa[i]); 5323 soc_mem_field32_set(unit, config_mem[i], &l0_entry, 5324 burst_exp_f[i], burst_exp[i]); 5325 soc_mem_field32_set(unit, config_mem[i], &l0_entry, 5326 burst_mant_f[i], burst_mantissa[i]); 5327 soc_mem_field32_set(unit, config_mem[i], &l0_entry, 5328 cycle_sel_f[i], cycle_sel[i]); 5329 rv = soc_mem_write(unit, config_mem[i], 5330 MEM_BLOCK_ALL, index, &l0_entry); 5331 if (BCM_FAILURE(rv)) { 5332 SOC_EGRESS_METERING_UNLOCK(unit); 5333 return(rv); 5334 } 5335 } 5336 break; 5337 5338 case _BCM_KT2_COSQ_NODE_LEVEL_L1: 5339 config_mem[0] = LLS_L1_SHAPER_CONFIG_Cm; 5340 config_mem[1] = LLS_L1_MIN_CONFIG_Cm; 5341 if (SOC_IS_SABER2(unit)) { 5342 rate_exp_fields[0] = C_MAX_REF_RATE_EXPf; 5343 rate_exp_fields[1] = INVALIDf; 5344 rate_exp_fields[2] = INVALIDf; 5345 rate_exp_fields[3] = INVALIDf; 5346 rate_exp_fields[4] = C_MIN_REF_RATE_EXPf; 5347 5348 rate_mant_fields[0] = C_MAX_REF_RATE_MANTf; 5349 rate_mant_fields[1] = INVALIDf; 5350 rate_mant_fields[2] = INVALIDf; 5351 rate_mant_fields[3] = INVALIDf; 5352 rate_mant_fields[4] = C_MIN_REF_RATE_MANTf; 5353 5354 burst_exp_fields[0] = C_MAX_THLD_EXPf; 5355 burst_exp_fields[1] = INVALIDf; 5356 burst_exp_fields[2] = INVALIDf; 5357 burst_exp_fields[3] = INVALIDf; 5358 burst_exp_fields[4] = C_MIN_THLD_EXPf; 5359 5360 burst_mant_fields[0] = C_MAX_THLD_MANTf; 5361 burst_mant_fields[1] = INVALIDf; 5362 burst_mant_fields[2] = INVALIDf; 5363 burst_mant_fields[3] = INVALIDf; 5364 burst_mant_fields[4] = C_MIN_THLD_MANTf; 5365 5366 cycle_sel_fields[0] = C_MAX_CYCLE_SELf; 5367 cycle_sel_fields[1] = INVALIDf; 5368 cycle_sel_fields[2] = INVALIDf; 5369 cycle_sel_fields[3] = INVALIDf; 5370 cycle_sel_fields[4] = C_MIN_CYCLE_SELf; 5371 5372 shaper_bucket_index = 0; 5373 } else { 5374 shaper_bucket_index = index % max_l1_shaper_bucket[unit]; 5375 } 5376 for (i = 0; i < 2; i++) { 5377 idx = (i * 4) + shaper_bucket_index; 5378 rv = soc_mem_read(unit, config_mem[i], MEM_BLOCK_ALL, 5379 index / max_l1_shaper_bucket[unit], &l1_entry); 5380 if (BCM_FAILURE(rv)) { 5381 SOC_EGRESS_METERING_UNLOCK(unit); 5382 return(rv); 5383 } 5384 5385 soc_mem_field32_set(unit, config_mem[i], &l1_entry, 5386 rate_exp_fields[idx], rate_exp[i]); 5387 soc_mem_field32_set(unit, config_mem[i], &l1_entry, 5388 rate_mant_fields[idx], rate_mantissa[i]); 5389 soc_mem_field32_set(unit, config_mem[i], &l1_entry, 5390 burst_exp_fields[idx], burst_exp[i]); 5391 soc_mem_field32_set(unit, config_mem[i], &l1_entry, 5392 burst_mant_fields[idx], burst_mantissa[i]); 5393 soc_mem_field32_set(unit, config_mem[i], &l1_entry, 5394 cycle_sel_fields[idx], cycle_sel[i]); 5395 rv = soc_mem_write(unit, config_mem[i], MEM_BLOCK_ALL, 5396 index / max_l1_shaper_bucket[unit], &l1_entry); 5397 if (BCM_FAILURE(rv)) { 5398 SOC_EGRESS_METERING_UNLOCK(unit); 5399 return(rv); 5400 } 5401 } 5402 break; 5403 5404 case _BCM_KT2_COSQ_NODE_LEVEL_L2: 5405 if ((index % max_l2_shaper_bucket[unit]) < 4) { 5406 config_mem[0] = l2_shaper_memory[unit][0]; 5407 config_mem[1] = l2_shaper_memory[unit][1]; 5408 } else { 5409 config_mem[0] = l2_shaper_memory[unit][2]; 5410 config_mem[1] = l2_shaper_memory[unit][3]; 5411 } 5412 for (i = 0; i < 2; i++) { 5413 idx = (i * 4) + (index % 4); 5414 rv = soc_mem_read(unit, config_mem[i], MEM_BLOCK_ALL, 5415 index/max_l2_shaper_bucket[unit], &l2_entry); 5416 if (BCM_FAILURE(rv)) { 5417 SOC_EGRESS_METERING_UNLOCK(unit); 5418 return(rv); 5419 } 5420 soc_mem_field32_set(unit, config_mem[i], &l2_entry, 5421 rate_exp_fields[idx], rate_exp[i]); 5422 soc_mem_field32_set(unit, config_mem[i], &l2_entry, 5423 rate_mant_fields[idx], rate_mantissa[i]); 5424 soc_mem_field32_set(unit, config_mem[i], &l2_entry, 5425 burst_exp_fields[idx], burst_exp[i]); 5426 soc_mem_field32_set(unit, config_mem[i], &l2_entry, 5427 burst_mant_fields[idx], burst_mantissa[i]); 5428 soc_mem_field32_set(unit, config_mem[i], &l2_entry, 5429 cycle_sel_fields[idx], cycle_sel[i]); 5430 rv = soc_mem_write(unit, config_mem[i], MEM_BLOCK_ALL, 5431 index/max_l2_shaper_bucket[unit], &l2_entry); 5432 if (BCM_FAILURE(rv)) { 5433 SOC_EGRESS_METERING_UNLOCK(unit); 5434 return(rv); 5435 } 5436 } 5437 break; 5438 5439 case _BCM_KT2_COSQ_NODE_LEVEL_S0: 5440 case _BCM_KT2_COSQ_NODE_LEVEL_S1: 5441 config_mem[0] = (level == _BCM_KT2_COSQ_NODE_LEVEL_S0 && 5442 (node->linkphy_enabled) && !SOC_IS_METROLITE(unit)) ? 5443 LLS_S0_SHAPER_CONFIG_Cm : 5444 LLS_S1_SHAPER_CONFIG_Cm; 5445 5446 if ((level == _BCM_KT2_COSQ_NODE_LEVEL_S1) 5447 && (node->hw_index > 127 && node->hw_index < 256)){ 5448 config_mem[0] = LLS_L0_SHAPER_CONFIG_Cm; 5449 } else { 5450 #if defined (BCM_SABER2_SUPPORT) 5451 if (SOC_IS_SABER2(unit)) { 5452 #if defined (BCM_METROLITE_SUPPORT) 5453 if (SOC_IS_METROLITE(unit)) { 5454 if (level == _BCM_KT2_COSQ_NODE_LEVEL_S0) { 5455 if ((node->hw_index >= _SOC_ML_COSQ_MAX_INDEX_S0) && 5456 node->linkphy_enabled) { 5457 SOC_EGRESS_METERING_UNLOCK(unit); 5458 return BCM_E_PARAM; 5459 } 5460 } 5461 } else 5462 #endif /* BCM_METROLITE_SUPPORT */ 5463 { 5464 if (level == _BCM_KT2_COSQ_NODE_LEVEL_S0) { 5465 if ((node->hw_index >= _SOC_SB2_COSQ_MAX_INDEX_S0) && 5466 node->linkphy_enabled) { 5467 SOC_EGRESS_METERING_UNLOCK(unit); 5468 return BCM_E_PARAM; 5469 } 5470 } 5471 } 5472 } else 5473 #endif /* BCM_SABER2_SUPPORT */ 5474 if ((level == _BCM_KT2_COSQ_NODE_LEVEL_S0) && 5475 (node->hw_index >= _SOC_KT2_COSQ_MAX_INDEX_S0)) { 5476 SOC_EGRESS_METERING_UNLOCK(unit); 5477 return BCM_E_NONE; 5478 } 5479 } 5480 5481 rv = soc_mem_read(unit, config_mem[0], MEM_BLOCK_ALL, 5482 index, &s0_entry); 5483 if (BCM_FAILURE(rv)) { 5484 SOC_EGRESS_METERING_UNLOCK(unit); 5485 return(rv); 5486 } 5487 soc_mem_field32_set(unit, config_mem[0], &s0_entry, 5488 rate_exp_f[0], rate_exp[0]); 5489 soc_mem_field32_set(unit, config_mem[0], &s0_entry, 5490 rate_mant_f[0], rate_mantissa[0]); 5491 soc_mem_field32_set(unit, config_mem[0], &s0_entry, 5492 burst_exp_f[0], burst_exp[0]); 5493 soc_mem_field32_set(unit, config_mem[0], &s0_entry, 5494 burst_mant_f[0], burst_mantissa[0]); 5495 soc_mem_field32_set(unit, config_mem[0], &s0_entry, 5496 cycle_sel_f[0], cycle_sel[0]); 5497 rv = soc_mem_write(unit, config_mem[0], 5498 MEM_BLOCK_ALL, index, &s0_entry); 5499 if (BCM_FAILURE(rv)) { 5500 SOC_EGRESS_METERING_UNLOCK(unit); 5501 return(rv); 5502 } 5503 break; 5504 5505 default: 5506 SOC_EGRESS_METERING_UNLOCK(unit); 5507 return BCM_E_PARAM; 5508 } 5509 5510 SOC_EGRESS_METERING_UNLOCK(unit); 5511 return BCM_E_NONE; 5512 } 5513 5514 /* 5515 * Function: 5516 * _bcm_kt2_cosq_bucket_get 5517 * Purpose: 5518 * Get COS queue bandwidth control bucket setting 5519 * Parameters: 5520 * unit - (IN) unit number 5521 * port - (IN) port number or GPORT identifier 5522 * cosq - (IN) COS queue number 5523 * min_quantum - (OUT) kbps or packet/second 5524 * max_quantum - (OUT) kbps or packet/second 5525 * burst_quantum - (OUT) kbps or packet/second 5526 * flags - (IN) 5527 * Returns: 5528 * BCM_E_XXX 5529 * Notes: 5530 * If port is any form of local port, cosq is the hardware queue index. 5531 */ 5532 STATIC int 5533 _bcm_kt2_cosq_bucket_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 5534 uint32 *min_quantum, uint32 *max_quantum, 5535 uint32 *burst_min_quantum, uint32 *burst_max_quantum, 5536 uint32 flags) 5537 { 5538 int rv; 5539 _bcm_kt2_cosq_node_t *node; 5540 bcm_port_t local_port; 5541 int index; 5542 soc_mem_t config_mem[2]; 5543 lls_port_shaper_config_c_entry_t port_entry; 5544 lls_l0_shaper_config_c_entry_t l0_entry; 5545 lls_l1_shaper_config_c_entry_t l1_entry; 5546 lls_l2_shaper_config_lower_entry_t l2_entry; 5547 lls_s0_shaper_config_c_entry_t s0_entry; 5548 uint32 rate_exp[2], rate_mantissa[2]; 5549 uint32 burst_exp[2], burst_mantissa[2]; 5550 int i, idx, status; 5551 int level = _BCM_KT2_COSQ_NODE_LEVEL_L2; 5552 soc_field_t rate_exp_f[] = { 5553 C_MAX_REF_RATE_EXPf, C_MIN_REF_RATE_EXPf 5554 }; 5555 soc_field_t rate_mant_f[] = { 5556 C_MAX_REF_RATE_MANTf, C_MIN_REF_RATE_MANTf 5557 }; 5558 soc_field_t burst_exp_f[] = { 5559 C_MAX_THLD_EXPf, C_MIN_THLD_EXPf 5560 }; 5561 soc_field_t burst_mant_f[] = { 5562 C_MAX_THLD_MANTf, C_MIN_THLD_MANTf 5563 }; 5564 soc_field_t rate_exp_fields[] = { 5565 C_MAX_REF_RATE_EXP_0f, C_MAX_REF_RATE_EXP_1f, 5566 C_MAX_REF_RATE_EXP_2f, C_MAX_REF_RATE_EXP_3f, 5567 C_MIN_REF_RATE_EXP_0f, C_MIN_REF_RATE_EXP_1f, 5568 C_MIN_REF_RATE_EXP_2f, C_MIN_REF_RATE_EXP_3f 5569 }; 5570 soc_field_t rate_mant_fields[] = { 5571 C_MAX_REF_RATE_MANT_0f, C_MAX_REF_RATE_MANT_1f, 5572 C_MAX_REF_RATE_MANT_2f, C_MAX_REF_RATE_MANT_3f, 5573 C_MIN_REF_RATE_MANT_0f, C_MIN_REF_RATE_MANT_1f, 5574 C_MIN_REF_RATE_MANT_2f, C_MIN_REF_RATE_MANT_3f 5575 }; 5576 soc_field_t burst_exp_fields[] = { 5577 C_MAX_THLD_EXP_0f, C_MAX_THLD_EXP_1f, 5578 C_MAX_THLD_EXP_2f, C_MAX_THLD_EXP_3f, 5579 C_MIN_THLD_EXP_0f, C_MIN_THLD_EXP_1f, 5580 C_MIN_THLD_EXP_2f, C_MIN_THLD_EXP_3f 5581 }; 5582 soc_field_t burst_mant_fields[] = { 5583 C_MAX_THLD_MANT_0f, C_MAX_THLD_MANT_1f, 5584 C_MAX_THLD_MANT_2f, C_MAX_THLD_MANT_3f, 5585 C_MIN_THLD_MANT_0f, C_MIN_THLD_MANT_1f, 5586 C_MIN_THLD_MANT_2f, C_MIN_THLD_MANT_3f 5587 }; 5588 int shaper_bucket_index = 0; 5589 5590 if (cosq < 0) { 5591 if (cosq == -1) { 5592 /* caller needs to resolve the wild card value (-1) */ 5593 return BCM_E_INTERNAL; 5594 } else { /* reject all other negative value */ 5595 return BCM_E_PARAM; 5596 } 5597 } 5598 5599 if (min_quantum == NULL || max_quantum == NULL || 5600 burst_min_quantum == NULL || burst_max_quantum == NULL) { 5601 return BCM_E_PARAM; 5602 } 5603 5604 BCM_IF_ERROR_RETURN 5605 (_bcm_kt2_cosq_index_resolve(unit, port, cosq, 5606 _BCM_KT2_COSQ_INDEX_STYLE_BUCKET, 5607 &local_port, &index, NULL)); 5608 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 5609 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) || 5610 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port) || 5611 BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(port) || 5612 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port) || 5613 BCM_GPORT_IS_SCHEDULER(port)) { 5614 BCM_IF_ERROR_RETURN 5615 (_bcm_kt2_cosq_node_get(unit, port, NULL, NULL, NULL, &node)); 5616 level = node->level; 5617 } 5618 5619 /* 5620 * At this point, port might be in flush state. 5621 * If so, the max shaper might have been set to a large 5622 * value temporarily which must not be returned. 5623 */ 5624 SOC_EGRESS_METERING_LOCK(unit); 5625 soc_kt_port_flush_state_get(unit, local_port, &status); 5626 if (status) { 5627 5628 LOG_INFO(BSL_LS_BCM_COSQ, 5629 (BSL_META_U(unit, 5630 "Unit %d Port %d is in flush state.\n"), unit, local_port)); 5631 5632 SOC_EGRESS_METERING_UNLOCK(unit); 5633 return BCM_E_RESOURCE; 5634 } 5635 5636 switch (level) { 5637 case _BCM_KT2_COSQ_NODE_LEVEL_ROOT: 5638 config_mem[0] = LLS_PORT_SHAPER_CONFIG_Cm; 5639 rv = (soc_mem_read(unit, config_mem[0], MEM_BLOCK_ALL, 5640 index, &port_entry)); 5641 if (BCM_FAILURE(rv)) { 5642 SOC_EGRESS_METERING_UNLOCK(unit); 5643 return rv; 5644 } 5645 rate_exp[0] = soc_mem_field32_get(unit, config_mem[0], &port_entry, 5646 rate_exp_f[0]); 5647 rate_mantissa[0] = soc_mem_field32_get(unit, config_mem[0], 5648 &port_entry, 5649 rate_mant_f[0]); 5650 rate_exp[1] = rate_exp[0]; 5651 rate_mantissa[1] = rate_mantissa[0]; 5652 burst_exp[0] = soc_mem_field32_get(unit, config_mem[0], &port_entry, 5653 burst_exp_f[0]); 5654 burst_mantissa[0] = soc_mem_field32_get(unit, config_mem[0], 5655 &port_entry, 5656 burst_mant_f[0]); 5657 burst_exp[1] = burst_exp[0]; 5658 burst_mantissa[1] = burst_mantissa[0]; 5659 break; 5660 5661 case _BCM_KT2_COSQ_NODE_LEVEL_L0: 5662 config_mem[0] = LLS_L0_SHAPER_CONFIG_Cm; 5663 config_mem[1] = LLS_L0_MIN_CONFIG_Cm; 5664 5665 for (i = 0; i < 2; i++) { 5666 rv = soc_mem_read(unit, config_mem[i], MEM_BLOCK_ALL, 5667 index, &l0_entry); 5668 if (BCM_FAILURE(rv)) { 5669 SOC_EGRESS_METERING_UNLOCK(unit); 5670 return rv; 5671 } 5672 5673 rate_exp[i] = soc_mem_field32_get(unit, config_mem[i], 5674 &l0_entry, 5675 rate_exp_f[i]); 5676 rate_mantissa[i] = soc_mem_field32_get(unit, config_mem[i], 5677 &l0_entry, 5678 rate_mant_f[i]); 5679 burst_exp[i] = soc_mem_field32_get(unit, config_mem[i], 5680 &l0_entry, 5681 burst_exp_f[i]); 5682 burst_mantissa[i] = soc_mem_field32_get(unit, config_mem[i], 5683 &l0_entry, 5684 burst_mant_f[i]); 5685 } 5686 break; 5687 5688 case _BCM_KT2_COSQ_NODE_LEVEL_L1: 5689 config_mem[0] = LLS_L1_SHAPER_CONFIG_Cm; 5690 config_mem[1] = LLS_L1_MIN_CONFIG_Cm; 5691 if (SOC_IS_SABER2(unit)) { 5692 rate_exp_fields[0] = C_MAX_REF_RATE_EXPf; 5693 rate_exp_fields[1] = INVALIDf; 5694 rate_exp_fields[2] = INVALIDf; 5695 rate_exp_fields[3] = INVALIDf; 5696 rate_exp_fields[4] = C_MIN_REF_RATE_EXPf; 5697 5698 rate_mant_fields[0] = C_MAX_REF_RATE_MANTf; 5699 rate_mant_fields[1] = INVALIDf; 5700 rate_mant_fields[2] = INVALIDf; 5701 rate_mant_fields[3] = INVALIDf; 5702 rate_mant_fields[4] = C_MIN_REF_RATE_MANTf; 5703 5704 burst_exp_fields[0] = C_MAX_THLD_EXPf; 5705 burst_exp_fields[1] = INVALIDf; 5706 burst_exp_fields[2] = INVALIDf; 5707 burst_exp_fields[3] = INVALIDf; 5708 burst_exp_fields[4] = C_MIN_THLD_EXPf; 5709 5710 burst_mant_fields[0] = C_MAX_THLD_MANTf; 5711 burst_mant_fields[1] = INVALIDf; 5712 burst_mant_fields[2] = INVALIDf; 5713 burst_mant_fields[3] = INVALIDf; 5714 burst_mant_fields[4] = C_MIN_THLD_MANTf; 5715 5716 shaper_bucket_index = 0; 5717 } else { 5718 shaper_bucket_index = index % max_l1_shaper_bucket[unit]; 5719 } 5720 for (i = 0; i < 2; i++) { 5721 idx = (i * 4) + shaper_bucket_index; 5722 rv = soc_mem_read(unit, config_mem[i], MEM_BLOCK_ALL, 5723 index / max_l1_shaper_bucket[unit], &l1_entry); 5724 if (BCM_FAILURE(rv)) { 5725 SOC_EGRESS_METERING_UNLOCK(unit); 5726 return rv; 5727 } 5728 rate_exp[i] = soc_mem_field32_get(unit, config_mem[i], 5729 &l1_entry, 5730 rate_exp_fields[idx]); 5731 rate_mantissa[i] = soc_mem_field32_get(unit, config_mem[i], 5732 &l1_entry, 5733 rate_mant_fields[idx]); 5734 burst_exp[i] = soc_mem_field32_get(unit, config_mem[i], 5735 &l1_entry, 5736 burst_exp_fields[idx]); 5737 burst_mantissa[i] = soc_mem_field32_get(unit, config_mem[i], 5738 &l1_entry, 5739 burst_mant_fields[idx]); 5740 } 5741 break; 5742 5743 case _BCM_KT2_COSQ_NODE_LEVEL_L2: 5744 if ((index % max_l2_shaper_bucket[unit]) < 4) { 5745 config_mem[0] = l2_shaper_memory[unit][0]; 5746 config_mem[1] = l2_shaper_memory[unit][1]; 5747 } else { 5748 config_mem[0] = l2_shaper_memory[unit][2]; 5749 config_mem[1] = l2_shaper_memory[unit][3]; 5750 } 5751 5752 for (i = 0; i < 2; i++) { 5753 idx = (i * 4) + (index % 4); 5754 rv = soc_mem_read(unit, config_mem[i], MEM_BLOCK_ALL, 5755 index/max_l2_shaper_bucket[unit], &l2_entry); 5756 if (BCM_FAILURE(rv)) { 5757 SOC_EGRESS_METERING_UNLOCK(unit); 5758 return rv; 5759 } 5760 rate_exp[i] = soc_mem_field32_get(unit, config_mem[i], 5761 &l2_entry, 5762 rate_exp_fields[idx]); 5763 rate_mantissa[i] = soc_mem_field32_get(unit, config_mem[i], 5764 &l2_entry, 5765 rate_mant_fields[idx]); 5766 burst_exp[i] = soc_mem_field32_get(unit, config_mem[i], 5767 &l2_entry, 5768 burst_exp_fields[idx]); 5769 burst_mantissa[i] = soc_mem_field32_get(unit, config_mem[i], 5770 &l2_entry, 5771 burst_mant_fields[idx]); 5772 } 5773 break; 5774 5775 case _BCM_KT2_COSQ_NODE_LEVEL_S0: 5776 case _BCM_KT2_COSQ_NODE_LEVEL_S1: 5777 #if defined (BCM_SABER2_SUPPORT) 5778 if (SOC_IS_SABER2(unit) && (level == _BCM_KT2_COSQ_NODE_LEVEL_S0)) { 5779 if ((node->hw_index >= _SOC_SB2_COSQ_MAX_INDEX_S0) && 5780 node->linkphy_enabled) { 5781 SOC_EGRESS_METERING_UNLOCK(unit); 5782 return BCM_E_PARAM; 5783 } 5784 } else 5785 #endif 5786 if ((level == _BCM_KT2_COSQ_NODE_LEVEL_S0) && 5787 (node->hw_index >= _SOC_KT2_COSQ_MAX_INDEX_S0)) { 5788 SOC_EGRESS_METERING_UNLOCK(unit); 5789 return BCM_E_NONE; 5790 } 5791 config_mem[0] = (level == _BCM_KT2_COSQ_NODE_LEVEL_S0 && 5792 (node->linkphy_enabled) && !SOC_IS_METROLITE(unit)) ? 5793 LLS_S0_SHAPER_CONFIG_Cm : 5794 LLS_S1_SHAPER_CONFIG_Cm; 5795 rv = soc_mem_read(unit, config_mem[0], MEM_BLOCK_ALL, 5796 index, &s0_entry); 5797 if (BCM_FAILURE(rv)) { 5798 SOC_EGRESS_METERING_UNLOCK(unit); 5799 return rv; 5800 } 5801 rate_exp[0] = soc_mem_field32_get(unit, config_mem[0], &s0_entry, 5802 rate_exp_f[0]); 5803 rate_mantissa[0] = soc_mem_field32_get(unit, config_mem[0], 5804 &s0_entry, 5805 rate_mant_f[0]); 5806 burst_exp[0] = soc_mem_field32_get(unit, config_mem[0], &s0_entry, 5807 burst_exp_f[0]); 5808 burst_mantissa[0] = soc_mem_field32_get(unit, config_mem[0], 5809 &s0_entry, 5810 burst_mant_f[0]); 5811 break; 5812 5813 default: 5814 SOC_EGRESS_METERING_UNLOCK(unit); 5815 return BCM_E_PARAM; 5816 } 5817 SOC_EGRESS_METERING_UNLOCK(unit); 5818 5819 /* convert exp and mantissa to bps */ 5820 rv = soc_katana_compute_shaper_rate(unit, rate_mantissa[0], rate_exp[0], 5821 max_quantum); 5822 if (BCM_FAILURE(rv)) { 5823 return(rv); 5824 } 5825 5826 rv = soc_katana_compute_shaper_rate(unit, rate_mantissa[1], rate_exp[1], 5827 min_quantum); 5828 if (BCM_FAILURE(rv)) { 5829 return(rv); 5830 } 5831 if((level == _BCM_KT2_COSQ_NODE_LEVEL_ROOT) || 5832 (level == _BCM_KT2_COSQ_NODE_LEVEL_S0) || 5833 (level == _BCM_KT2_COSQ_NODE_LEVEL_S1)) 5834 { 5835 *min_quantum=0; 5836 } 5837 rv = soc_katana_compute_shaper_burst(unit, burst_mantissa[0], burst_exp[0], 5838 burst_max_quantum); 5839 if (BCM_FAILURE(rv)) { 5840 return(rv); 5841 } 5842 5843 rv = soc_katana_compute_shaper_burst(unit, burst_mantissa[1], burst_exp[1], 5844 burst_min_quantum); 5845 if (BCM_FAILURE(rv)) { 5846 return(rv); 5847 } 5848 5849 return BCM_E_NONE; 5850 } 5851 5852 /* 5853 * Convert HW drop probability to percent value 5854 */ 5855 STATIC int 5856 _bcm_kt2_hw_drop_prob_to_percent[] = { 5857 0, /* 0 */ 5858 1, /* 1 */ 5859 2, /* 2 */ 5860 3, /* 3 */ 5861 4, /* 4 */ 5862 5, /* 5 */ 5863 6, /* 6 */ 5864 7, /* 7 */ 5865 8, /* 8 */ 5866 9, /* 9 */ 5867 10, /* 10 */ 5868 25, /* 11 */ 5869 50, /* 12 */ 5870 75, /* 13 */ 5871 100, /* 14 */ 5872 -1 /* 15 */ 5873 }; 5874 5875 STATIC int 5876 _bcm_kt2_percent_to_drop_prob(int percent) 5877 { 5878 int i; 5879 5880 for (i = 14; i > 0 ; i--) { 5881 if (percent >= _bcm_kt2_hw_drop_prob_to_percent[i]) { 5882 break; 5883 } 5884 } 5885 return i; 5886 } 5887 5888 STATIC int 5889 _bcm_kt2_drop_prob_to_percent(int drop_prob) { 5890 return (_bcm_kt2_hw_drop_prob_to_percent[drop_prob]); 5891 } 5892 5893 /* 5894 * Function: 5895 * _bcm_kt2_cosq_wred_set 5896 * Purpose: 5897 * Configure unicast queue WRED setting 5898 * Parameters: 5899 * unit - (IN) unit number 5900 * port - (IN) port number or GPORT identifier 5901 * cosq - (IN) COS queue number 5902 * flags - (IN) BCM_COSQ_DISCARD_XXX 5903 * min_thresh - (IN) 5904 * max_thresh - (IN) 5905 * drop_probablity - (IN) 5906 * gain - (IN) 5907 * ignore_enable_flags - (IN) 5908 * Returns: 5909 * BCM_E_XXX 5910 * Notes: 5911 * If port is any form of local port, cosq is the hardware queue index. 5912 */ 5913 STATIC int 5914 _bcm_kt2_cosq_wred_set(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 5915 uint32 flags, uint32 min_thresh, uint32 max_thresh, 5916 int drop_probability, int gain, int ignore_enable_flags) 5917 { 5918 soc_reg_t reg = 0; 5919 soc_field_t field; 5920 uint32 rval = 0; 5921 bcm_port_t local_port; 5922 int index; 5923 uint32 profile_index, old_profile_index, partner_index; 5924 mmu_wred_drop_curve_profile_0_entry_t entry_tcp_green; 5925 mmu_wred_drop_curve_profile_1_entry_t entry_tcp_yellow; 5926 mmu_wred_drop_curve_profile_2_entry_t entry_tcp_red; 5927 mmu_wred_drop_curve_profile_3_entry_t entry_nontcp_green; 5928 mmu_wred_drop_curve_profile_4_entry_t entry_nontcp_yellow; 5929 mmu_wred_drop_curve_profile_5_entry_t entry_nontcp_red; 5930 void *entries[6]; 5931 soc_mem_t mems[6]; 5932 _bcm_kt2_cosq_node_t *node; 5933 soc_mem_t wred_mem = MMU_WRED_QUEUE_CONFIG_BUFFERm; 5934 soc_mem_t partner_mem = MMU_WRED_QUEUE_CONFIG_QENTRYm; 5935 mmu_wred_queue_config_buffer_entry_t qentry, entry; 5936 int rate, i; 5937 int wred_enabled = 0; 5938 int ext_mem_port_count = 0; 5939 int wred_disable_request = 0; 5940 _bcm_kt2_mmu_info_t *mmu_info; 5941 5942 reg = WRED_CONFIGr; 5943 if (flags & BCM_COSQ_DISCARD_DEVICE) { 5944 /* For port -1 , set global wred discard profile for all ports */ 5945 if ((port == -1) || (flags & BCM_COSQ_DISCARD_PACKETS)) { 5946 reg = GLOBAL_WRED_CONFIG_QENTRYr; 5947 field = WRED_ENABLEf; 5948 local_port = 0; 5949 index = 0; /* mmu init code uses service pool 0 only */ 5950 } else { 5951 return BCM_E_PARAM; 5952 } 5953 } else { 5954 if (cosq == -1) { 5955 return BCM_E_PARAM; 5956 } 5957 wred_disable_request = (!ignore_enable_flags) && 5958 (!(flags & BCM_COSQ_DISCARD_ENABLE)); 5959 BCM_IF_ERROR_RETURN 5960 (_bcm_kt2_cosq_index_resolve(unit, port, cosq, 5961 _BCM_KT2_COSQ_INDEX_STYLE_WRED, 5962 &local_port, &index, NULL)); 5963 /* WRED doesn't work on CPU/LB Ports */ 5964 if (IS_LB_PORT(unit, local_port) || IS_CPU_PORT(unit, local_port)) { 5965 return BCM_E_PORT; 5966 } 5967 5968 if (flags & BCM_COSQ_DISCARD_PACKETS) { 5969 wred_mem = MMU_WRED_QUEUE_CONFIG_QENTRYm; 5970 partner_mem = MMU_WRED_QUEUE_CONFIG_BUFFERm; 5971 } 5972 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 5973 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) || 5974 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port) || 5975 BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(port) || 5976 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port) || 5977 BCM_GPORT_IS_SCHEDULER(port)) { 5978 BCM_IF_ERROR_RETURN 5979 (_bcm_kt2_cosq_node_get(unit, port, NULL, &local_port, NULL, 5980 &node)); 5981 node->wred_disabled = wred_disable_request; 5982 if (node->level == _BCM_KT2_COSQ_NODE_LEVEL_L0) { 5983 wred_mem = (flags & BCM_COSQ_DISCARD_PACKETS) ? 5984 MMU_WRED_OPN_CONFIG_QENTRYm : 5985 MMU_WRED_OPN_CONFIG_BUFFERm; 5986 partner_mem = (flags & BCM_COSQ_DISCARD_PACKETS) ? 5987 MMU_WRED_OPN_CONFIG_BUFFERm : 5988 MMU_WRED_OPN_CONFIG_QENTRYm; 5989 } 5990 } else { 5991 mmu_info = _bcm_kt2_mmu_info[unit]; 5992 if (cosq >= (mmu_info->port[local_port].q_limit - 5993 mmu_info->port[local_port].q_offset)) { 5994 return BCM_E_PARAM; 5995 } 5996 node = &mmu_info->queue_node[mmu_info->port[local_port].q_offset + cosq]; 5997 node->wred_disabled = wred_disable_request; 5998 } 5999 field = WRED_ENf; 6000 } 6001 6002 old_profile_index = 0xffffffff; 6003 profile_index = 0xffffffff; 6004 if (reg == GLOBAL_WRED_CONFIG_QENTRYr) { 6005 BCM_IF_ERROR_RETURN(soc_reg32_get(unit, reg, local_port, index, &rval)); 6006 } else { 6007 SOC_IF_ERROR_RETURN 6008 (soc_mem_read(unit, wred_mem, MEM_BLOCK_ALL, 6009 index, &qentry)); 6010 } 6011 /* 6012 * Note that there is issue with dynamic disable of WRED 6013 * if low rate shaper is configured. There will be huge 6014 * queue build up and average queue size calculated will 6015 * be high resulting in WRED entering into tail drop. At 6016 * this time if WRED gets disabled then re-claculation of 6017 * average queue size will not be done by WRED and it will 6018 * remain in tail drop state even if queue is emptied. So 6019 * instead of diabling WRED attach default WRED profile 6020 * which have very high min and max threshold and zero 6021 * dropping rate. 6022 */ 6023 if (wred_disable_request && (reg != GLOBAL_WRED_CONFIG_QENTRYr)) { 6024 old_profile_index = soc_mem_field32_get(unit, wred_mem, 6025 &qentry, PROFILE_INDEXf); 6026 soc_mem_field32_set(unit, wred_mem, &qentry, PROFILE_INDEXf, 0); 6027 soc_mem_field32_set(unit, wred_mem, &qentry, WEIGHTf, 0); 6028 } else 6029 if (flags & (BCM_COSQ_DISCARD_NONTCP | BCM_COSQ_DISCARD_COLOR_ALL)) { 6030 if (reg == GLOBAL_WRED_CONFIG_QENTRYr) { 6031 old_profile_index = soc_reg_field_get(unit, reg, rval, 6032 PROFILE_INDEXf); 6033 } else { 6034 old_profile_index = soc_mem_field32_get(unit, wred_mem, 6035 &qentry, PROFILE_INDEXf); 6036 } 6037 entries[0] = &entry_tcp_green; 6038 entries[1] = &entry_tcp_yellow; 6039 entries[2] = &entry_tcp_red; 6040 entries[3] = &entry_nontcp_green; 6041 entries[4] = &entry_nontcp_yellow; 6042 entries[5] = &entry_nontcp_red; 6043 BCM_IF_ERROR_RETURN 6044 (soc_profile_mem_get(unit, _bcm_kt2_wred_profile[unit], 6045 old_profile_index, 1, entries)); 6046 for (i = 0; i < 6; i++) { 6047 mems[i] = INVALIDm; 6048 } 6049 if (!(flags & BCM_COSQ_DISCARD_NONTCP)) { 6050 if (flags & BCM_COSQ_DISCARD_COLOR_GREEN) { 6051 mems[0] = MMU_WRED_DROP_CURVE_PROFILE_0m; 6052 } 6053 if (flags & BCM_COSQ_DISCARD_COLOR_YELLOW) { 6054 mems[1] = MMU_WRED_DROP_CURVE_PROFILE_1m; 6055 } 6056 if (flags & BCM_COSQ_DISCARD_COLOR_RED) { 6057 mems[2] = MMU_WRED_DROP_CURVE_PROFILE_2m; 6058 } 6059 } else if (!(flags & (BCM_COSQ_DISCARD_COLOR_GREEN | 6060 BCM_COSQ_DISCARD_COLOR_YELLOW | 6061 BCM_COSQ_DISCARD_COLOR_RED))) { 6062 mems[3] = MMU_WRED_DROP_CURVE_PROFILE_3m; 6063 mems[4] = MMU_WRED_DROP_CURVE_PROFILE_4m; 6064 mems[5] = MMU_WRED_DROP_CURVE_PROFILE_5m; 6065 6066 } else { 6067 if (flags & BCM_COSQ_DISCARD_COLOR_GREEN) { 6068 mems[3] = MMU_WRED_DROP_CURVE_PROFILE_3m; 6069 } 6070 if (flags & BCM_COSQ_DISCARD_COLOR_YELLOW) { 6071 mems[4] = MMU_WRED_DROP_CURVE_PROFILE_4m; 6072 } 6073 if (flags & BCM_COSQ_DISCARD_COLOR_RED) { 6074 mems[5] = MMU_WRED_DROP_CURVE_PROFILE_5m; 6075 } 6076 } 6077 rate = _bcm_kt2_percent_to_drop_prob(drop_probability); 6078 for (i = 0; i < 6; i++) { 6079 if (mems[i] == INVALIDm) { 6080 continue; 6081 } 6082 soc_mem_field32_set(unit, mems[i], entries[i], MIN_THDf, 6083 min_thresh); 6084 soc_mem_field32_set(unit, mems[i], entries[i], MAX_THDf, 6085 max_thresh); 6086 soc_mem_field32_set(unit, mems[i], entries[i], MAX_DROP_RATEf, 6087 rate); 6088 } 6089 BCM_IF_ERROR_RETURN 6090 (soc_profile_mem_add(unit, _bcm_kt2_wred_profile[unit], entries, 1, 6091 &profile_index)); 6092 if (reg == GLOBAL_WRED_CONFIG_QENTRYr) { 6093 soc_reg_field_set(unit, reg, &rval, PROFILE_INDEXf, profile_index); 6094 soc_reg_field_set(unit, reg, &rval, WEIGHTf, gain); 6095 } else { 6096 soc_mem_field32_set(unit, wred_mem, &qentry, PROFILE_INDEXf, 6097 profile_index); 6098 soc_mem_field32_set(unit, wred_mem, &qentry, WEIGHTf, gain); 6099 } 6100 } 6101 6102 /* Some APIs only modify profiles */ 6103 if (!ignore_enable_flags) { 6104 if ( reg == GLOBAL_WRED_CONFIG_QENTRYr) { 6105 soc_reg_field_set(unit, reg, &rval, CAP_AVERAGEf, 6106 flags & BCM_COSQ_DISCARD_CAP_AVERAGE ? 1 : 0); 6107 soc_reg_field_set(unit, reg, &rval, field, 6108 flags & BCM_COSQ_DISCARD_ENABLE ? 1 : 0); 6109 } else { 6110 soc_mem_field32_set(unit, wred_mem, &qentry, CAP_AVERAGEf, 6111 flags & BCM_COSQ_DISCARD_CAP_AVERAGE ? 1 : 0); 6112 if (flags & BCM_COSQ_DISCARD_ENABLE) { 6113 soc_mem_field32_set(unit, wred_mem, &qentry, field, 1); 6114 } 6115 if (wred_mem == MMU_WRED_QUEUE_CONFIG_BUFFERm || 6116 wred_mem == MMU_WRED_QUEUE_CONFIG_QENTRYm) { 6117 /* ECN marking is applicable only for queues */ 6118 soc_mem_field32_set(unit, wred_mem, &qentry, ECN_MARKING_ENf, 6119 flags & BCM_COSQ_DISCARD_MARK_CONGESTION ? 6120 1 : 0); 6121 if (wred_mem == MMU_WRED_QUEUE_CONFIG_QENTRYm) { 6122 /* ECN marking needs to be enabled in BUFFER entry */ 6123 SOC_IF_ERROR_RETURN 6124 (soc_mem_read(unit, MMU_WRED_QUEUE_CONFIG_BUFFERm, 6125 MEM_BLOCK_ALL, index, &entry)); 6126 soc_mem_field32_set(unit, MMU_WRED_QUEUE_CONFIG_BUFFERm, 6127 &entry, ECN_MARKING_ENf, 6128 flags & BCM_COSQ_DISCARD_MARK_CONGESTION ? 6129 1 : 0); 6130 SOC_IF_ERROR_RETURN 6131 (soc_mem_write(unit, MMU_WRED_QUEUE_CONFIG_BUFFERm, 6132 MEM_BLOCK_ALL, index, &entry)); 6133 } 6134 } 6135 } 6136 } 6137 6138 partner_index = 0xffffffff; 6139 if (reg == GLOBAL_WRED_CONFIG_QENTRYr) { 6140 BCM_IF_ERROR_RETURN(soc_reg32_set(unit, reg, local_port, index, rval)); 6141 6142 /* update interna/external buffer entries based on port configuration */ 6143 BCM_IF_ERROR_RETURN(soc_reg32_get(unit, GLOBAL_WRED_CONFIG_BUFFERIr, 6144 local_port, index, &rval)); 6145 soc_reg_field_set(unit, GLOBAL_WRED_CONFIG_BUFFERIr, &rval, field, 6146 flags & BCM_COSQ_DISCARD_ENABLE ? 1 : 0); 6147 soc_reg_field_set(unit, GLOBAL_WRED_CONFIG_BUFFERIr, &rval, 6148 PROFILE_INDEXf, 0); 6149 BCM_IF_ERROR_RETURN(soc_reg32_set(unit, GLOBAL_WRED_CONFIG_BUFFERIr, 6150 local_port, index, rval)); 6151 BCM_PBMP_COUNT(PBMP_EXT_MEM (unit), ext_mem_port_count); 6152 if (ext_mem_port_count > 0) { 6153 BCM_IF_ERROR_RETURN(soc_reg32_get(unit, GLOBAL_WRED_CONFIG_BUFFERE_POOL0r, 6154 local_port, index, &rval)); 6155 soc_reg_field_set(unit, GLOBAL_WRED_CONFIG_BUFFERE_POOL0r, &rval, field, 6156 flags & BCM_COSQ_DISCARD_ENABLE ? 1 : 0); 6157 soc_reg_field_set(unit, GLOBAL_WRED_CONFIG_BUFFERE_POOL0r, &rval, 6158 PROFILE_INDEXf, 0); 6159 BCM_IF_ERROR_RETURN(soc_reg32_set(unit, GLOBAL_WRED_CONFIG_BUFFERE_POOL0r, 6160 local_port, index, rval)); 6161 } 6162 } else { 6163 SOC_IF_ERROR_RETURN 6164 (soc_mem_write(unit, wred_mem, MEM_BLOCK_ALL, 6165 index, &qentry)); 6166 SOC_IF_ERROR_RETURN 6167 (soc_mem_read(unit, partner_mem, MEM_BLOCK_ALL, 6168 index, &qentry)); 6169 wred_enabled = soc_mem_field32_get(unit, partner_mem, 6170 &qentry, WRED_ENf); 6171 6172 /* if buffer/qentry_mem WRED enabled, make sure the partner_mem 6173 * (qentry/buffer_mem) also WRED enabled. 6174 * if buffer/qentry_mem WRED disabled, make sure the partner_mem 6175 * (qentry/buffer_mem) also WRED disabled. 6176 */ 6177 if (((flags & BCM_COSQ_DISCARD_ENABLE) && (wred_enabled == 0)) || 6178 (!(flags & BCM_COSQ_DISCARD_ENABLE) && (wred_enabled == 1))) { 6179 partner_index = soc_mem_field32_get(unit, partner_mem, 6180 &qentry, PROFILE_INDEXf); 6181 soc_mem_field32_set(unit, partner_mem, &qentry, PROFILE_INDEXf, 0); 6182 if (flags & BCM_COSQ_DISCARD_ENABLE) { 6183 soc_mem_field32_set(unit, partner_mem, &qentry, WRED_ENf, 1); 6184 } 6185 SOC_IF_ERROR_RETURN 6186 (soc_mem_write(unit, partner_mem, MEM_BLOCK_ALL, 6187 index, &qentry)); 6188 } 6189 } 6190 6191 /* Replacing old profiles with new global profiles when wred discard 6192 profile is set for all ports */ 6193 6194 if ((port== -1) && (flags & BCM_COSQ_DISCARD_DEVICE) && 6195 (profile_index != 0xffffffff)) { 6196 for(i = 1; i < SOC_REG_NUMELS(unit, reg); i++) { 6197 BCM_IF_ERROR_RETURN(soc_profile_mem_add(unit, 6198 _bcm_kt2_wred_profile[unit], entries, 1, 6199 &profile_index)); 6200 BCM_IF_ERROR_RETURN(soc_reg32_set(unit, reg, local_port, i, rval)); 6201 } 6202 } 6203 6204 if (old_profile_index != 0xffffffff && old_profile_index > 0) { 6205 BCM_IF_ERROR_RETURN 6206 (soc_profile_mem_delete(unit, _bcm_kt2_wred_profile[unit], 6207 old_profile_index)); 6208 if ((port==-1) && (flags & BCM_COSQ_DISCARD_DEVICE)) { 6209 for (i = 1; i < SOC_REG_NUMELS(unit, reg); i++) { 6210 BCM_IF_ERROR_RETURN(soc_profile_mem_delete(unit, 6211 _bcm_kt2_wred_profile[unit],old_profile_index)); 6212 } 6213 } 6214 } 6215 6216 if (partner_index != 0xffffffff && partner_index > 0) { 6217 BCM_IF_ERROR_RETURN 6218 (soc_profile_mem_delete(unit, _bcm_kt2_wred_profile[unit], 6219 partner_index)); 6220 } 6221 6222 return BCM_E_NONE; 6223 } 6224 6225 /* 6226 * Function: 6227 * _bcm_kt2_cosq_wred_get 6228 * Purpose: 6229 * Get unicast queue WRED setting 6230 * Parameters: 6231 * unit - (IN) unit number 6232 * port - (IN) port number or GPORT identifier 6233 * cosq - (IN) COS queue number 6234 * flags - (IN/OUT) BCM_COSQ_DISCARD_XXX 6235 * min_thresh - (OUT) 6236 * max_thresh - (OUT) 6237 * drop_probablity - (OUT) 6238 * gain - (OUT) 6239 * Returns: 6240 * BCM_E_XXX 6241 * Notes: 6242 * If port is any form of local port, cosq is the hardware queue index. 6243 */ 6244 STATIC int 6245 _bcm_kt2_cosq_wred_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 6246 uint32 *flags, uint32 *min_thresh, uint32 *max_thresh, 6247 int *drop_probability, int *gain) 6248 { 6249 soc_reg_t reg = 0; 6250 soc_field_t field; 6251 uint32 rval; 6252 bcm_port_t local_port; 6253 int index, profile_index; 6254 mmu_wred_drop_curve_profile_0_entry_t entry_tcp_green; 6255 mmu_wred_drop_curve_profile_1_entry_t entry_tcp_yellow; 6256 mmu_wred_drop_curve_profile_2_entry_t entry_tcp_red; 6257 mmu_wred_drop_curve_profile_3_entry_t entry_nontcp_green; 6258 mmu_wred_drop_curve_profile_4_entry_t entry_nontcp_yellow; 6259 mmu_wred_drop_curve_profile_5_entry_t entry_nontcp_red; 6260 void *entries[6]; 6261 void *entry_p; 6262 soc_mem_t mem; 6263 _bcm_kt2_cosq_node_t *node; 6264 soc_mem_t wred_mem = MMU_WRED_QUEUE_CONFIG_BUFFERm; 6265 mmu_wred_queue_config_buffer_entry_t qentry; 6266 int rate; 6267 int wred_disabled = 0; 6268 _bcm_kt2_mmu_info_t *mmu_info; 6269 6270 if (*flags & BCM_COSQ_DISCARD_DEVICE) { 6271 if ((port == -1) || (*flags & BCM_COSQ_DISCARD_PACKETS)) { 6272 reg = GLOBAL_WRED_CONFIG_QENTRYr; 6273 field = WRED_ENABLEf; 6274 local_port = 0; 6275 index = 0; /* mmu init code uses service pool 0 only */ 6276 wred_mem = 0; 6277 } else { 6278 return BCM_E_PARAM; 6279 } 6280 } else { 6281 if (cosq == -1) { 6282 return BCM_E_PARAM; 6283 } 6284 BCM_IF_ERROR_RETURN 6285 (_bcm_kt2_cosq_index_resolve(unit, port, cosq, 6286 _BCM_KT2_COSQ_INDEX_STYLE_WRED, 6287 &local_port, &index, NULL)); 6288 /* WRED doesn't work on CPU/LB Ports */ 6289 if (IS_LB_PORT(unit, local_port) || IS_CPU_PORT(unit, local_port)) { 6290 return BCM_E_PORT; 6291 } 6292 if (*flags & BCM_COSQ_DISCARD_PACKETS) { 6293 wred_mem = MMU_WRED_QUEUE_CONFIG_QENTRYm; 6294 } 6295 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 6296 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) || 6297 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port) || 6298 BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(port) || 6299 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port) || 6300 BCM_GPORT_IS_SCHEDULER(port)) { 6301 BCM_IF_ERROR_RETURN 6302 (_bcm_kt2_cosq_node_get(unit, port, NULL, &local_port, NULL, 6303 &node)); 6304 if (node->level == _BCM_KT2_COSQ_NODE_LEVEL_L1) { 6305 wred_mem = (*flags & BCM_COSQ_DISCARD_PACKETS) ? 6306 MMU_WRED_OPN_CONFIG_QENTRYm : 6307 MMU_WRED_OPN_CONFIG_BUFFERm; 6308 } else { 6309 wred_disabled = node->wred_disabled; 6310 } 6311 } else { 6312 mmu_info = _bcm_kt2_mmu_info[unit]; 6313 if (cosq >= (mmu_info->port[local_port].q_limit - 6314 mmu_info->port[local_port].q_offset)) { 6315 return BCM_E_PARAM; 6316 } 6317 node = &mmu_info->queue_node[mmu_info->port[local_port].q_offset + cosq]; 6318 wred_disabled = node->wred_disabled; 6319 } 6320 field = WRED_ENf; 6321 } 6322 6323 if (reg == GLOBAL_WRED_CONFIG_QENTRYr) { 6324 BCM_IF_ERROR_RETURN(soc_reg32_get(unit, reg, local_port, index, &rval)); 6325 profile_index = soc_reg_field_get(unit, reg, rval, PROFILE_INDEXf); 6326 } else { 6327 SOC_IF_ERROR_RETURN 6328 (soc_mem_read(unit, wred_mem, MEM_BLOCK_ALL, 6329 index, &qentry)); 6330 profile_index = soc_mem_field32_get(unit, wred_mem, 6331 &qentry, PROFILE_INDEXf); 6332 } 6333 6334 if (!(*flags & BCM_COSQ_DISCARD_NONTCP)) { 6335 if (*flags & BCM_COSQ_DISCARD_COLOR_GREEN) { 6336 mem = MMU_WRED_DROP_CURVE_PROFILE_0m; 6337 entry_p = &entry_tcp_green; 6338 } else if (*flags & BCM_COSQ_DISCARD_COLOR_YELLOW) { 6339 mem = MMU_WRED_DROP_CURVE_PROFILE_1m; 6340 entry_p = &entry_tcp_yellow; 6341 } else if (*flags & BCM_COSQ_DISCARD_COLOR_RED) { 6342 mem = MMU_WRED_DROP_CURVE_PROFILE_2m; 6343 entry_p = &entry_tcp_red; 6344 } else { 6345 mem = MMU_WRED_DROP_CURVE_PROFILE_0m; 6346 entry_p = &entry_tcp_green; 6347 } 6348 } else { 6349 if (*flags & BCM_COSQ_DISCARD_COLOR_GREEN) { 6350 mem = MMU_WRED_DROP_CURVE_PROFILE_3m; 6351 entry_p = &entry_nontcp_green; 6352 } else if (*flags & BCM_COSQ_DISCARD_COLOR_YELLOW) { 6353 mem = MMU_WRED_DROP_CURVE_PROFILE_4m; 6354 entry_p = &entry_nontcp_yellow; 6355 } else if (*flags & BCM_COSQ_DISCARD_COLOR_RED) { 6356 mem = MMU_WRED_DROP_CURVE_PROFILE_5m; 6357 entry_p = &entry_nontcp_red; 6358 } else { 6359 mem = MMU_WRED_DROP_CURVE_PROFILE_3m; 6360 entry_p = &entry_nontcp_green; 6361 } 6362 } 6363 entries[0] = &entry_tcp_green; 6364 entries[1] = &entry_tcp_yellow; 6365 entries[2] = &entry_tcp_red; 6366 entries[3] = &entry_nontcp_green; 6367 entries[4] = &entry_nontcp_yellow; 6368 entries[5] = &entry_nontcp_red; 6369 BCM_IF_ERROR_RETURN 6370 (soc_profile_mem_get(unit, _bcm_kt2_wred_profile[unit], 6371 profile_index, 1, entries)); 6372 if (min_thresh != NULL) { 6373 *min_thresh = soc_mem_field32_get(unit, mem, entry_p, MIN_THDf); 6374 } 6375 if (max_thresh != NULL) { 6376 *max_thresh = soc_mem_field32_get(unit, mem, entry_p, MAX_THDf); 6377 } 6378 if (drop_probability != NULL) { 6379 rate = soc_mem_field32_get(unit, mem, entry_p, MAX_DROP_RATEf); 6380 *drop_probability = _bcm_kt2_drop_prob_to_percent(rate); 6381 } 6382 6383 if (gain != NULL && reg == GLOBAL_WRED_CONFIG_QENTRYr) { 6384 *gain = soc_reg_field_get(unit, reg, rval, WEIGHTf); 6385 } 6386 if (gain != NULL && wred_mem != 0) { 6387 *gain = soc_mem_field32_get(unit, wred_mem, &qentry, WEIGHTf); 6388 } 6389 6390 *flags &= ~(BCM_COSQ_DISCARD_CAP_AVERAGE | BCM_COSQ_DISCARD_ENABLE); 6391 if ((reg == GLOBAL_WRED_CONFIG_QENTRYr) && 6392 soc_reg_field_get(unit, reg, rval, CAP_AVERAGEf)) { 6393 *flags |= BCM_COSQ_DISCARD_CAP_AVERAGE; 6394 } 6395 if ((wred_mem != 0) && 6396 soc_mem_field32_get(unit, wred_mem, &qentry, CAP_AVERAGEf)) { 6397 *flags |= BCM_COSQ_DISCARD_CAP_AVERAGE; 6398 } 6399 6400 if ((reg == GLOBAL_WRED_CONFIG_QENTRYr) && 6401 soc_reg_field_get(unit, reg, rval, field)) { 6402 *flags |= BCM_COSQ_DISCARD_ENABLE; 6403 } 6404 if ((wred_mem != 0) && (wred_disabled == 0) && 6405 soc_mem_field32_get(unit, wred_mem, &qentry, field)) { 6406 *flags |= BCM_COSQ_DISCARD_ENABLE; 6407 } 6408 6409 if (wred_mem == MMU_WRED_QUEUE_CONFIG_BUFFERm || 6410 wred_mem == MMU_WRED_QUEUE_CONFIG_QENTRYm) { 6411 if (soc_mem_field32_get(unit, wred_mem, &qentry, ECN_MARKING_ENf)) { 6412 *flags |= BCM_COSQ_DISCARD_MARK_CONGESTION; 6413 } 6414 } 6415 6416 return BCM_E_NONE; 6417 } 6418 STATIC int 6419 bcm_kt2_handle_queue_min_accounting(int unit, 6420 bcm_port_t port, 6421 int queue_id, 6422 int active) 6423 { 6424 int shared_size, conf_size, recalc_type; 6425 _bcm_kt2_mmu_info_t *mmu_info_p; 6426 mmu_thdo_qconfig_cell_entry_t mmu_thdo_qconfig_cell_entry={{0}}; 6427 6428 /* Currently it is handled only for Saber2 */ 6429 #ifdef BCM_SABER2_SUPPORT 6430 if (SOC_IS_SABER2(unit)) { 6431 #ifdef BCM_METROLITE_SUPPORT 6432 if (SOC_IS_METROLITE(unit)) { 6433 return BCM_E_NONE; 6434 } 6435 #endif 6436 } else 6437 #endif 6438 { 6439 return BCM_E_NONE; 6440 } 6441 /* Do run time accounting only for front panel port */ 6442 if ((port <= 0) || (port >= LB_PORT(unit))) { 6443 return BCM_E_NONE; 6444 } 6445 /* Check if queue is classical queue then return */ 6446 mmu_info_p = _bcm_kt2_mmu_info[unit]; 6447 if ((queue_id >= mmu_info_p->port[port].q_offset) && 6448 (queue_id < mmu_info_p->port[port].q_limit)) { 6449 return BCM_E_NONE; 6450 } 6451 if ((queue_id >= mmu_info_p->port[port].mcq_offset) && 6452 (queue_id < mmu_info_p->port[port].mcq_limit)) { 6453 return BCM_E_NONE; 6454 } 6455 if ((queue_id <= 0) || (queue_id >= soc_mem_index_count( 6456 unit, MMU_THDO_QCONFIG_CELLm))) { 6457 return BCM_E_NONE; 6458 } 6459 if (active) { 6460 /* queue is going to be used */ 6461 if (IS_EXT_MEM_PORT(unit, port)) { 6462 soc_kt2_mmu_get_shared_size(unit, NULL, &shared_size); 6463 soc_sb2_get_queue_min_size(unit, NULL, &conf_size); 6464 recalc_type = BCM_KT2_RECALC_SHARED_EXT_DECREMENT; 6465 if (shared_size < conf_size) { 6466 LOG_ERROR(BSL_LS_SOC_COMMON, (BSL_META_U(unit, "\nGlobal external" 6467 " shared buffer exhausted"))); 6468 return BCM_E_RESOURCE; 6469 } 6470 BCM_IF_ERROR_RETURN( 6471 soc_sb2_mmu_config_shared_buf_recalc(unit, 6472 shared_size - conf_size, 6473 recalc_type)); 6474 } else { 6475 soc_kt2_mmu_get_shared_size(unit, &shared_size, NULL); 6476 soc_sb2_get_queue_min_size(unit, &conf_size, NULL); 6477 recalc_type = BCM_KT2_RECALC_SHARED_INT_DECREMENT; 6478 if (shared_size < conf_size) { 6479 LOG_ERROR(BSL_LS_SOC_COMMON, (BSL_META_U(unit, "\nGlobal internal" 6480 " shared buffer exhausted"))); 6481 return BCM_E_RESOURCE; 6482 } 6483 BCM_IF_ERROR_RETURN( 6484 soc_sb2_mmu_config_shared_buf_recalc(unit, 6485 shared_size - conf_size, 6486 recalc_type)); 6487 } 6488 BCM_IF_ERROR_RETURN( 6489 READ_MMU_THDO_QCONFIG_CELLm(unit, 6490 MEM_BLOCK_ANY, queue_id, 6491 &mmu_thdo_qconfig_cell_entry)); 6492 soc_mem_field32_set(unit, MMU_THDO_QCONFIG_CELLm, 6493 &mmu_thdo_qconfig_cell_entry, Q_MIN_CELLf, 6494 conf_size); 6495 BCM_IF_ERROR_RETURN(WRITE_MMU_THDO_QCONFIG_CELLm(unit, 6496 MEM_BLOCK_ANY, queue_id, 6497 &mmu_thdo_qconfig_cell_entry)); 6498 } else { 6499 /* queue is going to be freed */ 6500 BCM_IF_ERROR_RETURN( 6501 READ_MMU_THDO_QCONFIG_CELLm(unit, 6502 MEM_BLOCK_ANY, queue_id, 6503 &mmu_thdo_qconfig_cell_entry)); 6504 conf_size = soc_mem_field32_get(unit, MMU_THDO_QCONFIG_CELLm, 6505 &mmu_thdo_qconfig_cell_entry, Q_MIN_CELLf); 6506 if (IS_EXT_MEM_PORT(unit, port)) { 6507 soc_kt2_mmu_get_shared_size(unit, NULL, &shared_size); 6508 recalc_type = BCM_KT2_RECALC_SHARED_EXT_INCREMENT; 6509 BCM_IF_ERROR_RETURN( 6510 soc_sb2_mmu_config_shared_buf_recalc(unit, 6511 shared_size + conf_size, 6512 recalc_type)); 6513 } else { 6514 soc_kt2_mmu_get_shared_size(unit, &shared_size, NULL); 6515 recalc_type = BCM_KT2_RECALC_SHARED_INT_INCREMENT; 6516 BCM_IF_ERROR_RETURN( 6517 soc_sb2_mmu_config_shared_buf_recalc(unit, 6518 shared_size + conf_size, 6519 recalc_type)); 6520 } 6521 } 6522 return BCM_E_NONE; 6523 } 6524 STATIC int 6525 _bcm_kt2_cosq_gport_delete_node(int unit, bcm_gport_t gport) 6526 { 6527 _bcm_kt2_cosq_node_t *node; 6528 _bcm_kt2_mmu_info_t *mmu_info; 6529 int encap_id; 6530 6531 BCM_IF_ERROR_RETURN 6532 (_bcm_kt2_cosq_node_get(unit, gport, NULL, NULL, NULL, &node)); 6533 6534 /* reset the shaper configuration for the 6535 * node 6536 */ 6537 if (node->level != _BCM_KT2_COSQ_NODE_LEVEL_ROOT && node->cosq_attached_to >= 0) { 6538 BCM_IF_ERROR_RETURN (bcm_kt2_cosq_gport_bandwidth_set(unit, 6539 node->gport, 0, 0, 0, _BCM_XGS_METER_FLAG_RESET)); 6540 } 6541 6542 if (node->level != _BCM_KT2_COSQ_NODE_LEVEL_ROOT && 6543 node->cosq_attached_to >= 0) { 6544 BCM_IF_ERROR_RETURN (bcm_kt2_cosq_gport_detach(unit, node->gport, 6545 node->parent->gport, 6546 node->cosq_attached_to)); 6547 } 6548 6549 mmu_info = _bcm_kt2_mmu_info[unit]; 6550 6551 if (BCM_GPORT_IS_SCHEDULER(gport)) { 6552 /* scheduler node */ 6553 encap_id = (BCM_GPORT_SCHEDULER_GET(gport) >> 8) & 0x7ff; 6554 6555 if (encap_id == 0) { 6556 encap_id = (BCM_GPORT_SCHEDULER_GET(gport) & 0xff); 6557 } 6558 } else if (BCM_GPORT_IS_LOCAL(gport)) { 6559 encap_id = BCM_GPORT_LOCAL_GET(gport); 6560 } else if (BCM_GPORT_IS_MODPORT(gport)) { 6561 encap_id = BCM_GPORT_MODPORT_PORT_GET(gport); 6562 } else if (BCM_GPORT_IS_SUBPORT_PORT(gport)) { 6563 encap_id = BCM_GPORT_SUBPORT_PORT_GET(gport); 6564 } else { 6565 return BCM_E_PARAM; 6566 } 6567 6568 _bcm_kt2_node_index_clear(&mmu_info->sched_list, encap_id, 1); 6569 6570 if (node->cosq_map != NULL) { 6571 sal_free(node->cosq_map); 6572 node->cosq_map = NULL; 6573 } 6574 6575 _BCM_KT2_COSQ_NODE_INIT(node); 6576 6577 return BCM_E_NONE; 6578 } 6579 6580 6581 STATIC int 6582 _bcm_kt2_cosq_gport_delete_all(int unit, bcm_gport_t gport, int *rv) 6583 { 6584 _bcm_kt2_cosq_node_t *node; 6585 _bcm_kt2_mmu_info_t *mmu_info; 6586 _bcm_kt2_cosq_port_info_t *port_info; 6587 int vlan_queue_present = 1; 6588 bcm_port_t local_port; 6589 uint32 rval = 0; 6590 int encap_id; 6591 6592 BCM_IF_ERROR_RETURN 6593 (_bcm_kt2_cosq_node_get(unit, gport, NULL, &local_port, NULL, &node)); 6594 6595 if (node->child != NULL) { 6596 _bcm_kt2_cosq_gport_delete_all(unit, node->child->gport, rv); 6597 BCM_IF_ERROR_RETURN(*rv); 6598 } 6599 6600 if (node->sibling != NULL) { 6601 _bcm_kt2_cosq_gport_delete_all(unit, node->sibling->gport, rv); 6602 BCM_IF_ERROR_RETURN(*rv); 6603 } 6604 6605 /* reset the shaper configuration for the 6606 * node 6607 */ 6608 if (node->cosq_attached_to >= 0) { 6609 BCM_IF_ERROR_RETURN (bcm_kt2_cosq_gport_bandwidth_set(unit, 6610 node->gport, 0, 0, 0, _BCM_XGS_METER_FLAG_RESET)); 6611 } 6612 6613 if (node->level != _BCM_KT2_COSQ_NODE_LEVEL_ROOT && 6614 node->cosq_attached_to >= 0) { 6615 6616 *rv = bcm_kt2_cosq_gport_detach(unit, node->gport, node->parent->gport, 6617 node->cosq_attached_to); 6618 BCM_IF_ERROR_RETURN(*rv); 6619 } 6620 6621 mmu_info = _bcm_kt2_mmu_info[unit]; 6622 6623 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { /* unicast queue group */ 6624 encap_id = BCM_GPORT_UCAST_QUEUE_GROUP_QID_GET(gport); 6625 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 6626 /* multicast queue group */ 6627 encap_id = BCM_GPORT_MCAST_QUEUE_GROUP_QID_GET(gport); 6628 } else if (BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) { 6629 encap_id = BCM_GPORT_DESTMOD_QUEUE_GROUP_QID_GET(gport); 6630 if (mmu_info->num_dmvoq_queues > 0) { 6631 _bcm_kt2_node_index_clear(&mmu_info->dmvoq_qlist, 6632 encap_id , 1); 6633 encap_id += mmu_info->base_dmvoq_queue; 6634 } else { 6635 _bcm_kt2_node_index_clear(&mmu_info->global_qlist, 6636 encap_id , 1); 6637 } 6638 } else if (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport)) { 6639 /* subscriber queue group */ 6640 encap_id = BCM_GPORT_UCAST_SUBSCRIBER_QUEUE_GROUP_QID_GET(gport); 6641 if (mmu_info->num_sub_queues > 0) { 6642 _bcm_kt2_node_index_clear(&mmu_info->sub_qlist, 6643 encap_id , 1); 6644 encap_id += mmu_info->base_sub_queue; 6645 } else { 6646 6647 _bcm_kt2_node_index_clear(&mmu_info->global_qlist, 6648 encap_id, 1); 6649 } 6650 /* Check if all unicast vlan queues of this port are deleted */ 6651 BCM_IF_ERROR_RETURN( 6652 bcm_kt2_cosq_is_attached(unit, local_port, 1, 6653 &vlan_queue_present)); 6654 port_info = &mmu_info->port[local_port]; 6655 if (!vlan_queue_present) { 6656 port_info->uc_vlan_base = mmu_info->num_queues - 1; 6657 SOC_IF_ERROR_RETURN(READ_ING_COS_MODEr(unit, local_port, &rval)); 6658 soc_reg_field_set(unit, ING_COS_MODEr, &rval, 6659 SERVICE_BASE_QUEUE_NUMf, port_info->uc_vlan_base); 6660 SOC_IF_ERROR_RETURN(WRITE_ING_COS_MODEr(unit, local_port, rval)); 6661 } 6662 } else if (BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(gport)) { 6663 /* subscriber queue group */ 6664 encap_id = BCM_GPORT_MCAST_SUBSCRIBER_QUEUE_GROUP_QID_GET(gport); 6665 if (mmu_info->num_sub_queues > 0) { 6666 _bcm_kt2_node_index_clear(&mmu_info->sub_mcqlist, 6667 encap_id , 1); 6668 encap_id += mmu_info->base_sub_queue; 6669 } else { 6670 6671 _bcm_kt2_node_index_clear(&mmu_info->global_qlist, 6672 encap_id, 1); 6673 } 6674 } else { 6675 if (BCM_GPORT_IS_SCHEDULER(gport)) { 6676 /* scheduler node */ 6677 encap_id = (BCM_GPORT_SCHEDULER_GET(gport) >> 8) & 0x7ff; 6678 6679 if (encap_id == 0) { 6680 encap_id = (BCM_GPORT_SCHEDULER_GET(gport) & 0xff); 6681 } 6682 } else if (BCM_GPORT_IS_LOCAL(gport)) { 6683 encap_id = BCM_GPORT_LOCAL_GET(gport); 6684 } else if (BCM_GPORT_IS_MODPORT(gport)) { 6685 encap_id = BCM_GPORT_MODPORT_PORT_GET(gport); 6686 } else if (BCM_GPORT_IS_SUBPORT_PORT(gport)) { 6687 encap_id = BCM_GPORT_SUBPORT_PORT_GET(gport); 6688 } else { 6689 return BCM_E_PARAM; 6690 } 6691 6692 _bcm_kt2_node_index_clear(&mmu_info->sched_list, encap_id, 1); 6693 } 6694 6695 if (node->cosq_map != NULL) { 6696 sal_free(node->cosq_map); 6697 node->cosq_map = NULL; 6698 } 6699 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 6700 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) || 6701 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport) || 6702 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport) || 6703 BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(gport)) { 6704 BCM_IF_ERROR_RETURN( 6705 bcm_kt2_handle_queue_min_accounting(unit, local_port, 6706 encap_id, 0)); 6707 } 6708 _BCM_KT2_COSQ_NODE_INIT(node); 6709 6710 return BCM_E_NONE; 6711 } 6712 6713 STATIC int 6714 _bcm_kt2_cosq_queue_map_set(int unit, _bcm_kt2_cosq_node_t *node, 6715 bcm_port_t port) 6716 { 6717 _bcm_kt2_cosq_node_t *cur_node, *l1_node; 6718 egr_queue_to_pp_port_map_entry_t pp_port_map; 6719 mmu_thdo_opnconfig_cell_entry_t opnconfig_cell; 6720 mmu_thdo_opnconfig_qentry_entry_t opnconfig_qentry; 6721 int update_opn = 0; 6722 6723 switch(node->level) { 6724 case _BCM_KT2_COSQ_NODE_LEVEL_L0: 6725 for (l1_node = node->child; l1_node != NULL; 6726 l1_node = l1_node->sibling) { 6727 update_opn = 0; 6728 for (cur_node = l1_node->child; cur_node != NULL; 6729 cur_node = cur_node->sibling) { 6730 if (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP 6731 (cur_node->gport) || 6732 BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP 6733 (cur_node->gport) ) { 6734 SOC_IF_ERROR_RETURN 6735 (READ_EGR_QUEUE_TO_PP_PORT_MAPm(unit, MEM_BLOCK_ALL, 6736 cur_node->hw_index, &pp_port_map)); 6737 soc_mem_field32_set(unit, EGR_QUEUE_TO_PP_PORT_MAPm, 6738 &pp_port_map, PP_PORTf, port); 6739 SOC_IF_ERROR_RETURN 6740 (WRITE_EGR_QUEUE_TO_PP_PORT_MAPm(unit, MEM_BLOCK_ALL, 6741 cur_node->hw_index, 6742 &pp_port_map)); 6743 update_opn = 1; 6744 } 6745 } 6746 if (update_opn) { 6747 SOC_IF_ERROR_RETURN 6748 (READ_MMU_THDO_OPNCONFIG_CELLm(unit, MEM_BLOCK_ANY, 6749 l1_node->hw_index, &opnconfig_cell)); 6750 soc_mem_field32_set(unit, MMU_THDO_OPNCONFIG_CELLm, 6751 &opnconfig_cell, PIDf, port); 6752 SOC_IF_ERROR_RETURN 6753 (WRITE_MMU_THDO_OPNCONFIG_CELLm(unit, MEM_BLOCK_ALL, 6754 l1_node->hw_index, &opnconfig_cell)); 6755 SOC_IF_ERROR_RETURN 6756 (READ_MMU_THDO_OPNCONFIG_QENTRYm(unit, MEM_BLOCK_ANY, 6757 l1_node->hw_index, &opnconfig_qentry)); 6758 soc_mem_field32_set(unit, MMU_THDO_OPNCONFIG_QENTRYm, 6759 &opnconfig_qentry, PIDf, port); 6760 SOC_IF_ERROR_RETURN 6761 (WRITE_MMU_THDO_OPNCONFIG_QENTRYm(unit, MEM_BLOCK_ALL, 6762 l1_node->hw_index, &opnconfig_qentry)); 6763 } 6764 } 6765 break; 6766 case _BCM_KT2_COSQ_NODE_LEVEL_L1: 6767 for (cur_node = node->child; cur_node != NULL; 6768 cur_node = cur_node->sibling) { 6769 if (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(cur_node->gport) || 6770 BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(cur_node->gport)) { 6771 SOC_IF_ERROR_RETURN 6772 (READ_EGR_QUEUE_TO_PP_PORT_MAPm(unit, MEM_BLOCK_ALL, 6773 cur_node->hw_index, &pp_port_map)); 6774 soc_mem_field32_set(unit, EGR_QUEUE_TO_PP_PORT_MAPm, 6775 &pp_port_map, PP_PORTf, port); 6776 SOC_IF_ERROR_RETURN 6777 (WRITE_EGR_QUEUE_TO_PP_PORT_MAPm(unit, MEM_BLOCK_ALL, 6778 cur_node->hw_index, 6779 &pp_port_map)); 6780 update_opn = 1; 6781 } 6782 } 6783 if (update_opn) { 6784 SOC_IF_ERROR_RETURN 6785 (READ_MMU_THDO_OPNCONFIG_CELLm(unit, MEM_BLOCK_ANY, 6786 node->hw_index, &opnconfig_cell)); 6787 soc_mem_field32_set(unit, MMU_THDO_OPNCONFIG_CELLm, 6788 &opnconfig_cell, PIDf, port); 6789 SOC_IF_ERROR_RETURN 6790 (WRITE_MMU_THDO_OPNCONFIG_CELLm(unit, MEM_BLOCK_ALL, 6791 node->hw_index, &opnconfig_cell)); 6792 SOC_IF_ERROR_RETURN 6793 (READ_MMU_THDO_OPNCONFIG_QENTRYm(unit, MEM_BLOCK_ANY, 6794 node->hw_index, &opnconfig_qentry)); 6795 soc_mem_field32_set(unit, MMU_THDO_OPNCONFIG_QENTRYm, 6796 &opnconfig_qentry, PIDf, port); 6797 SOC_IF_ERROR_RETURN 6798 (WRITE_MMU_THDO_OPNCONFIG_QENTRYm(unit, MEM_BLOCK_ALL, 6799 node->hw_index, &opnconfig_qentry)); 6800 } 6801 break; 6802 default: 6803 return BCM_E_PARAM; 6804 } 6805 6806 return BCM_E_NONE; 6807 } 6808 6809 STATIC int 6810 _bcm_kt_cosq_bucket_start(int unit, 6811 int index, int level, int cycle_sel, int rate_exp, int thld_exp, 6812 int max_bucket) 6813 { 6814 lls_l0_shaper_config_c_entry_t l0_entry; 6815 lls_l0_shaper_bucket_c_entry_t l0_bucket; 6816 lls_l1_shaper_config_c_entry_t l1_entry; 6817 lls_l1_shaper_bucket_c_entry_t l1_bucket; 6818 soc_field_t cycle_sel_f[] = { 6819 C_MAX_CYCLE_SEL_0f, C_MAX_CYCLE_SEL_1f, 6820 C_MAX_CYCLE_SEL_2f, C_MAX_CYCLE_SEL_3f 6821 }; 6822 soc_field_t rate_exp_f[] = { 6823 C_MAX_REF_RATE_EXP_0f, C_MAX_REF_RATE_EXP_1f, 6824 C_MAX_REF_RATE_EXP_2f, C_MAX_REF_RATE_EXP_3f 6825 }; 6826 soc_field_t thld_exp_f[] = { 6827 C_MAX_THLD_EXP_0f, C_MAX_THLD_EXP_1f, 6828 C_MAX_THLD_EXP_2f, C_MAX_THLD_EXP_3f 6829 }; 6830 soc_field_t active_in_lls_f[] = { 6831 NOT_ACTIVE_IN_LLS_0f, NOT_ACTIVE_IN_LLS_1f, 6832 NOT_ACTIVE_IN_LLS_2f, NOT_ACTIVE_IN_LLS_3f 6833 }; 6834 soc_field_t max_bucket_f[] = { 6835 C_MAX_BUCKET_0f, C_MAX_BUCKET_1f, 6836 C_MAX_BUCKET_2f, C_MAX_BUCKET_3f 6837 }; 6838 soc_field_t not_empty_f[] = { 6839 NOT_EMPTY_0f, NOT_EMPTY_1f, 6840 NOT_EMPTY_2f, NOT_EMPTY_3f 6841 }; 6842 6843 switch(level) { 6844 case _BCM_KT2_COSQ_NODE_LEVEL_L0: 6845 SOC_IF_ERROR_RETURN 6846 (soc_mem_read(unit, LLS_L0_SHAPER_CONFIG_Cm, MEM_BLOCK_ALL, 6847 index, &l0_entry)); 6848 soc_mem_field32_set(unit, LLS_L0_SHAPER_CONFIG_Cm, &l0_entry, 6849 C_MAX_CYCLE_SELf, cycle_sel); 6850 soc_mem_field32_set(unit, LLS_L0_SHAPER_CONFIG_Cm, &l0_entry, 6851 C_MAX_REF_RATE_EXPf, rate_exp?rate_exp:0xe); 6852 soc_mem_field32_set(unit, LLS_L0_SHAPER_CONFIG_Cm, &l0_entry, 6853 C_MAX_THLD_EXPf, thld_exp); 6854 SOC_IF_ERROR_RETURN 6855 (soc_mem_write(unit, LLS_L0_SHAPER_CONFIG_Cm, MEM_BLOCK_ALL, 6856 index, &l0_entry)); 6857 6858 sal_memset(&l0_bucket, 0, sizeof(lls_l0_shaper_bucket_c_entry_t)); 6859 soc_mem_field32_set(unit, LLS_L0_SHAPER_BUCKET_Cm, &l0_bucket, 6860 NOT_ACTIVE_IN_LLSf, 1); 6861 soc_mem_field32_set(unit, LLS_L0_SHAPER_BUCKET_Cm, &l0_bucket, 6862 C_MAX_BUCKETf, max_bucket); 6863 soc_mem_field32_set(unit, LLS_L0_SHAPER_BUCKET_Cm, &l0_bucket, 6864 NOT_EMPTYf, 0); 6865 SOC_IF_ERROR_RETURN 6866 (soc_mem_write(unit, LLS_L0_SHAPER_BUCKET_Cm, 6867 MEM_BLOCK_ALL, index, &l0_bucket)); 6868 break; 6869 case _BCM_KT2_COSQ_NODE_LEVEL_L1: 6870 SOC_IF_ERROR_RETURN 6871 (soc_mem_read(unit, LLS_L1_SHAPER_CONFIG_Cm, MEM_BLOCK_ALL, 6872 (index / 4), &l1_entry)); 6873 soc_mem_field32_set(unit, LLS_L1_SHAPER_CONFIG_Cm, &l1_entry, 6874 cycle_sel_f[index % 4], cycle_sel); 6875 soc_mem_field32_set(unit, LLS_L1_SHAPER_CONFIG_Cm, &l1_entry, 6876 rate_exp_f[index % 4], rate_exp); 6877 soc_mem_field32_set(unit, LLS_L1_SHAPER_CONFIG_Cm, &l1_entry, 6878 thld_exp_f[index % 4], thld_exp); 6879 SOC_IF_ERROR_RETURN 6880 (soc_mem_write(unit, LLS_L1_SHAPER_CONFIG_Cm, MEM_BLOCK_ALL, 6881 (index / 4), &l1_entry)); 6882 6883 sal_memset(&l1_bucket, 0, sizeof(lls_l1_shaper_bucket_c_entry_t)); 6884 soc_mem_field32_set(unit, LLS_L1_SHAPER_BUCKET_Cm, &l1_bucket, 6885 active_in_lls_f[index % 4], 1); 6886 soc_mem_field32_set(unit, LLS_L1_SHAPER_BUCKET_Cm, &l1_bucket, 6887 max_bucket_f[index % 4], max_bucket); 6888 soc_mem_field32_set(unit, LLS_L1_SHAPER_BUCKET_Cm, &l1_bucket, 6889 not_empty_f[index % 4], 0); 6890 SOC_IF_ERROR_RETURN 6891 (soc_mem_write(unit, LLS_L1_SHAPER_BUCKET_Cm, 6892 MEM_BLOCK_ALL, (index / 4), &l1_bucket)); 6893 break; 6894 default: 6895 return BCM_E_PARAM; 6896 } 6897 6898 return BCM_E_NONE; 6899 } 6900 6901 STATIC int 6902 _bcm_kt_cosq_bucket_stop(int unit, 6903 int index, int level, int *cycle_sel, int *rate_exp, int *thld_exp, 6904 int *max_bucket) 6905 { 6906 lls_l0_shaper_config_c_entry_t l0_entry; 6907 lls_l0_child_state1_entry_t l0_state; 6908 lls_l0_shaper_bucket_c_entry_t l0_bucket; 6909 lls_l1_shaper_config_c_entry_t l1_entry; 6910 lls_l1_child_state1_entry_t l1_state; 6911 lls_l1_shaper_bucket_c_entry_t l1_bucket; 6912 #if defined(BROADCOM_DEBUG) 6913 int cycle_sel1, rate_exp1, thld_exp1, max_bucket1; 6914 #endif 6915 int werr_list, min_list, ef_list, i; 6916 int count = 0; 6917 soc_field_t cycle_sel_f[] = { 6918 C_MAX_CYCLE_SEL_0f, C_MAX_CYCLE_SEL_1f, 6919 C_MAX_CYCLE_SEL_2f, C_MAX_CYCLE_SEL_3f 6920 }; 6921 soc_field_t rate_exp_f[] = { 6922 C_MAX_REF_RATE_EXP_0f, C_MAX_REF_RATE_EXP_1f, 6923 C_MAX_REF_RATE_EXP_2f, C_MAX_REF_RATE_EXP_3f 6924 }; 6925 soc_field_t thld_exp_f[] = { 6926 C_MAX_THLD_EXP_0f, C_MAX_THLD_EXP_1f, 6927 C_MAX_THLD_EXP_2f, C_MAX_THLD_EXP_3f 6928 }; 6929 soc_field_t active_in_lls_f[] = { 6930 NOT_ACTIVE_IN_LLS_0f, NOT_ACTIVE_IN_LLS_1f, 6931 NOT_ACTIVE_IN_LLS_2f, NOT_ACTIVE_IN_LLS_3f 6932 }; 6933 soc_field_t max_bucket_f[] = { 6934 C_MAX_BUCKET_0f, C_MAX_BUCKET_1f, 6935 C_MAX_BUCKET_2f, C_MAX_BUCKET_3f 6936 }; 6937 soc_field_t not_empty_f[] = { 6938 NOT_EMPTY_0f, NOT_EMPTY_1f, 6939 NOT_EMPTY_2f, NOT_EMPTY_3f 6940 }; 6941 6942 switch(level) { 6943 case _BCM_KT2_COSQ_NODE_LEVEL_L0: 6944 SOC_IF_ERROR_RETURN 6945 (soc_mem_read(unit, LLS_L0_SHAPER_CONFIG_Cm, MEM_BLOCK_ALL, 6946 index, &l0_entry)); 6947 *cycle_sel = soc_mem_field32_get(unit, LLS_L0_SHAPER_CONFIG_Cm, 6948 &l0_entry, C_MAX_CYCLE_SELf); 6949 *rate_exp = soc_mem_field32_get(unit, LLS_L0_SHAPER_CONFIG_Cm, 6950 &l0_entry, C_MAX_REF_RATE_EXPf); 6951 *thld_exp = soc_mem_field32_get(unit, LLS_L0_SHAPER_CONFIG_Cm, 6952 &l0_entry, C_MAX_THLD_EXPf); 6953 soc_mem_field32_set(unit, LLS_L0_SHAPER_CONFIG_Cm, &l0_entry, 6954 C_MAX_CYCLE_SELf, 0xF); 6955 soc_mem_field32_set(unit, LLS_L0_SHAPER_CONFIG_Cm, &l0_entry, 6956 C_MAX_REF_RATE_EXPf, 0xE); 6957 soc_mem_field32_set(unit, LLS_L0_SHAPER_CONFIG_Cm, &l0_entry, 6958 C_MAX_THLD_EXPf, 9); 6959 SOC_IF_ERROR_RETURN 6960 (soc_mem_write(unit, LLS_L0_SHAPER_CONFIG_Cm, MEM_BLOCK_ALL, 6961 index, &l0_entry)); 6962 sal_usleep(10); 6963 6964 sal_memset(&l0_bucket, 0, sizeof(lls_l0_shaper_bucket_c_entry_t)); 6965 SOC_IF_ERROR_RETURN 6966 (soc_mem_read(unit, LLS_L0_SHAPER_BUCKET_Cm, MEM_BLOCK_ALL, 6967 index, &l0_bucket)); 6968 *max_bucket = soc_mem_field32_get(unit, LLS_L0_SHAPER_BUCKET_Cm, 6969 &l0_bucket, C_MAX_BUCKETf); 6970 soc_mem_field32_set(unit, LLS_L0_SHAPER_BUCKET_Cm, &l0_bucket, 6971 NOT_ACTIVE_IN_LLSf, 0); 6972 soc_mem_field32_set(unit, LLS_L0_SHAPER_BUCKET_Cm, &l0_bucket, 6973 C_MAX_BUCKETf, 0); 6974 soc_mem_field32_set(unit, LLS_L0_SHAPER_BUCKET_Cm, &l0_bucket, 6975 NOT_EMPTYf, 0); 6976 SOC_IF_ERROR_RETURN 6977 (soc_mem_write(unit, LLS_L0_SHAPER_BUCKET_Cm, 6978 MEM_BLOCK_ALL, index, &l0_bucket)); 6979 6980 sal_usleep(1000000); 6981 count = 0; 6982 6983 /* check twice to avoid any transient states */ 6984 for (i = 0; i < 20; i++) { 6985 SOC_IF_ERROR_RETURN 6986 (READ_LLS_L0_CHILD_STATE1m(unit, MEM_BLOCK_ALL, 6987 index, &l0_state)); 6988 werr_list = soc_mem_field32_get(unit, LLS_L0_CHILD_STATE1m, 6989 &l0_state, C_ON_WERR_LISTf); 6990 min_list = soc_mem_field32_get(unit, LLS_L0_CHILD_STATE1m, 6991 &l0_state, C_ON_MIN_LISTf); 6992 ef_list = soc_mem_field32_get(unit, LLS_L0_CHILD_STATE1m, 6993 &l0_state, C_ON_EF_LISTf); 6994 SOC_IF_ERROR_RETURN 6995 (soc_mem_read(unit, LLS_L0_SHAPER_CONFIG_Cm, MEM_BLOCK_ALL, 6996 index, &l0_entry)); 6997 #if defined(BROADCOM_DEBUG) 6998 cycle_sel1 = soc_mem_field32_get(unit, LLS_L0_SHAPER_CONFIG_Cm, 6999 &l0_entry, C_MAX_CYCLE_SELf); 7000 rate_exp1 = soc_mem_field32_get(unit, LLS_L0_SHAPER_CONFIG_Cm, 7001 &l0_entry, C_MAX_REF_RATE_EXPf); 7002 thld_exp1 = soc_mem_field32_get(unit, LLS_L0_SHAPER_CONFIG_Cm, 7003 &l0_entry, C_MAX_THLD_EXPf); 7004 SOC_IF_ERROR_RETURN 7005 (soc_mem_read(unit, LLS_L0_SHAPER_BUCKET_Cm, MEM_BLOCK_ALL, 7006 index, &l0_bucket)); 7007 max_bucket1 = soc_mem_field32_get(unit, LLS_L0_SHAPER_BUCKET_Cm, 7008 &l0_bucket, C_MAX_BUCKETf); 7009 7010 7011 LOG_INFO(BSL_LS_BCM_COSQ, 7012 (BSL_META_U(unit, 7013 "Iteration No :%d \n" 7014 "LLS_L0_SHAPER_CONFIG_C.C_MAX_CYCLE_SELf = %d \n" 7015 "LLS_L0_SHAPER_CONFIG_C.C_MAX_REF_RATE_EXPf = %d \n" 7016 "LLS_L0_SHAPER_CONFIG_C.C_MAX_THLD_EXPf = %d \n" 7017 "LLS_L0_SHAPER_BUCKET_C.C_MAX_BUCKET =%d \n" 7018 "LLS_L0_CHILD_STATE1.C_ON_WERR_LIST= %d \n" 7019 "LLS_L0_CHILD_STATE1.C_ON_MIN_LIST= %d \n" 7020 "LLS_L0_CHILD_STATE1.C_ON_EF_LISTf = %d \n"), 7021 i, cycle_sel1, rate_exp1, thld_exp1,max_bucket1, 7022 werr_list, min_list, ef_list)); 7023 #endif 7024 7025 7026 if ((i < 19) && (werr_list || min_list || ef_list)) { 7027 /* If any of the above states are set during first read then 7028 * wait for 1 second and read again.*/ 7029 sal_usleep(1000000); 7030 count = 0; 7031 } 7032 if ((i == 19) && (werr_list || min_list || ef_list)) { 7033 /* If any of the above states are set during second read then 7034 * return appropriate error */ 7035 return BCM_E_BUSY; 7036 } 7037 if (count < 4) { 7038 /* forcefully iterating for four times, 7039 so that transient state is ignored */ 7040 sal_usleep(1000000); 7041 count++ ; 7042 } 7043 if ( count == 4) { 7044 break; 7045 } 7046 } 7047 break; 7048 7049 case _BCM_KT2_COSQ_NODE_LEVEL_L1: 7050 SOC_IF_ERROR_RETURN 7051 (soc_mem_read(unit, LLS_L1_SHAPER_CONFIG_Cm, MEM_BLOCK_ALL, 7052 (index / 4), &l1_entry)); 7053 *cycle_sel = soc_mem_field32_get(unit, LLS_L1_SHAPER_CONFIG_Cm, 7054 &l1_entry, cycle_sel_f[index % 4]); 7055 *rate_exp = soc_mem_field32_get(unit, LLS_L1_SHAPER_CONFIG_Cm, 7056 &l1_entry, rate_exp_f[index % 4]); 7057 *thld_exp = soc_mem_field32_get(unit, LLS_L1_SHAPER_CONFIG_Cm, 7058 &l1_entry, thld_exp_f[index % 4]); 7059 soc_mem_field32_set(unit, LLS_L1_SHAPER_CONFIG_Cm, &l1_entry, 7060 cycle_sel_f[index % 4], 0xF); 7061 soc_mem_field32_set(unit, LLS_L1_SHAPER_CONFIG_Cm, &l1_entry, 7062 rate_exp_f[index % 4], 0xE); 7063 soc_mem_field32_set(unit, LLS_L1_SHAPER_CONFIG_Cm, &l1_entry, 7064 thld_exp_f[index % 4], 9); 7065 SOC_IF_ERROR_RETURN 7066 (soc_mem_write(unit, LLS_L1_SHAPER_CONFIG_Cm, MEM_BLOCK_ALL, 7067 (index / 4), &l1_entry)); 7068 sal_usleep(10); 7069 7070 sal_memset(&l1_bucket, 0, sizeof(lls_l1_shaper_bucket_c_entry_t)); 7071 SOC_IF_ERROR_RETURN 7072 (soc_mem_read(unit, LLS_L1_SHAPER_BUCKET_Cm, MEM_BLOCK_ALL, 7073 (index / 4), &l1_bucket)); 7074 *max_bucket = soc_mem_field32_get(unit, LLS_L1_SHAPER_BUCKET_Cm, 7075 &l1_bucket, max_bucket_f[index % 4]); 7076 soc_mem_field32_set(unit, LLS_L1_SHAPER_BUCKET_Cm, &l1_bucket, 7077 active_in_lls_f[index % 4], 0); 7078 soc_mem_field32_set(unit, LLS_L1_SHAPER_BUCKET_Cm, &l1_bucket, 7079 max_bucket_f[index % 4], 0); 7080 soc_mem_field32_set(unit, LLS_L1_SHAPER_BUCKET_Cm, &l1_bucket, 7081 not_empty_f[index % 4], 0); 7082 SOC_IF_ERROR_RETURN 7083 (soc_mem_write(unit, LLS_L1_SHAPER_BUCKET_Cm, 7084 MEM_BLOCK_ALL, (index / 4), &l1_bucket)); 7085 7086 sal_usleep(10); 7087 7088 /* check twice to avoid any transient states */ 7089 for (i = 0; i < 2; i++) { 7090 SOC_IF_ERROR_RETURN 7091 (READ_LLS_L1_CHILD_STATE1m(unit, MEM_BLOCK_ALL, 7092 index, &l1_state)); 7093 werr_list = soc_mem_field32_get(unit, LLS_L1_CHILD_STATE1m, 7094 &l1_state, C_ON_WERR_LISTf); 7095 min_list = soc_mem_field32_get(unit, LLS_L1_CHILD_STATE1m, 7096 &l1_state, C_ON_MIN_LIST_0f); 7097 ef_list = soc_mem_field32_get(unit, LLS_L1_CHILD_STATE1m, 7098 &l1_state, C_ON_EF_LIST_0f); 7099 if ((i == 0) && (werr_list || min_list || ef_list)) { 7100 /* If any of the above states are set during first read then 7101 * wait for 1 second and read again.*/ 7102 sal_usleep(1000000); 7103 } 7104 if ((i == 1) && (werr_list || min_list || ef_list)) { 7105 /* If any of the above states are set during second read then 7106 * return appropriate error */ 7107 return BCM_E_BUSY; 7108 } 7109 } 7110 break; 7111 7112 default: 7113 return BCM_E_PARAM; 7114 } 7115 7116 return BCM_E_NONE; 7117 } 7118 7119 STATIC int 7120 _bcm_kt2_cosq_child_node_at_input(_bcm_kt2_cosq_node_t *node, int cosq, 7121 _bcm_kt2_cosq_node_t **child_node) 7122 { 7123 _bcm_kt2_cosq_node_t *cur_node; 7124 7125 for (cur_node = node->child; cur_node; cur_node = cur_node->sibling) { 7126 if (cur_node->cosq_attached_to == cosq) { 7127 break; 7128 } 7129 } 7130 if (!cur_node) { 7131 return BCM_E_NOT_FOUND; 7132 } 7133 7134 *child_node = cur_node; 7135 7136 return BCM_E_NONE; 7137 } 7138 7139 int 7140 bcm_kt2_sw_hw_queue(int unit, int *queue_array) 7141 { 7142 _bcm_kt2_mmu_info_t *mmu_info; 7143 int index = 0; 7144 mmu_info = _bcm_kt2_mmu_info[unit]; 7145 7146 for (index = 0; index < mmu_info->num_queues; index++){ 7147 if( mmu_info->queue_node[index].hw_index == *queue_array){ 7148 *queue_array = index; 7149 return BCM_E_NONE; 7150 } 7151 } 7152 *queue_array = -1; 7153 return BCM_E_PARAM; 7154 } 7155 7156 int 7157 bcm_kt2_is_uc_queue(int unit,int queue_id,int *is_ucq) 7158 { 7159 _bcm_kt2_mmu_info_t *mmu_info; 7160 _bcm_kt2_cosq_list_t *list; 7161 7162 mmu_info = _bcm_kt2_mmu_info[unit]; 7163 7164 list = &mmu_info->l2_base_qlist; 7165 7166 if(SHR_BITGET(list->bits, queue_id)) 7167 { 7168 *is_ucq = TRUE; 7169 } 7170 else 7171 { 7172 *is_ucq = FALSE ; 7173 } 7174 return BCM_E_NONE; 7175 } 7176 /* 7177 * Function: 7178 * bcm_kt2_cosq_subscriber_qid_set 7179 * Purpose: 7180 * Setting a relative queue id as per the configured value 7181 * Parameters: 7182 * unit - (IN) unit number 7183 * gport - (IN) GPORT identifier 7184 * queue_id - (IN) QUEUE identifier 7185 * Returns: 7186 * BCM_E_XXX 7187 */ 7188 7189 int 7190 bcm_kt2_cosq_subscriber_qid_set(int unit, 7191 bcm_gport_t *gport, 7192 int queue_id) 7193 { 7194 _bcm_kt2_mmu_info_t *mmu_info; 7195 _bcm_kt2_cosq_node_t *node = NULL; 7196 mmu_info = _bcm_kt2_mmu_info[unit]; 7197 if (mmu_info == NULL) { 7198 return BCM_E_INIT; 7199 } 7200 7201 node = &mmu_info->queue_node[queue_id]; 7202 if (node->cosq_attached_to < 0) { 7203 return BCM_E_PARAM; 7204 } 7205 if (mmu_info->num_sub_queues) { 7206 queue_id -= mmu_info->base_sub_queue; 7207 } 7208 if (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(node->gport)) { 7209 BCM_GPORT_UCAST_SUBSCRIBER_QUEUE_GROUP_QID_SET(*gport, queue_id); 7210 } else if (BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(node->gport)) { 7211 BCM_GPORT_MCAST_SUBSCRIBER_QUEUE_GROUP_QID_SET(*gport, queue_id); 7212 } else { 7213 return BCM_E_INIT; 7214 } 7215 7216 return BCM_E_NONE; 7217 } 7218 7219 /* 7220 * Function: 7221 * _bcm_kt2_subscriber_sw_qid_set 7222 * Purpose: 7223 * Set queue id for the subscriber software queue index 7224 * Parameters: 7225 * unit - (IN) unit number 7226 * gport - (OUT) GPORT identifier 7227 * queue_id - (IN) QUEUE identifier 7228 * Returns: 7229 * BCM_E_XXX 7230 */ 7231 7232 int 7233 _bcm_kt2_subscriber_sw_qid_set(int unit, 7234 bcm_gport_t *gport, 7235 int queue_id) 7236 { 7237 _bcm_kt2_mmu_info_t *mmu_info; 7238 mmu_info = _bcm_kt2_mmu_info[unit]; 7239 if (mmu_info == NULL) { 7240 return BCM_E_INIT; 7241 } 7242 if (mmu_info->num_sub_queues) { 7243 queue_id -= mmu_info->base_sub_queue; 7244 } 7245 BCM_GPORT_UCAST_SUBSCRIBER_QUEUE_GROUP_QID_SET(*gport, queue_id); 7246 7247 return BCM_E_NONE; 7248 } 7249 7250 /* 7251 * Function: 7252 * _bcm_kt2_intf_ref_cnt_increment 7253 * Purpose: 7254 * Increase interface reference count for queue id 7255 * Parameters: 7256 * unit - (IN) unit number 7257 * queue_id - (IN) HW queue id 7258 * count - (IN) Interface count 7259 * Returns: 7260 * BCM_E_XXX 7261 */ 7262 7263 int 7264 _bcm_kt2_intf_ref_cnt_increment(int unit, uint32 queue_id, int count) 7265 { 7266 _bcm_kt2_mmu_info_t *mmu_info; 7267 7268 if (_bcm_kt2_mmu_info[unit] == NULL) { 7269 return BCM_E_INIT; 7270 } 7271 7272 mmu_info = _bcm_kt2_mmu_info[unit]; 7273 mmu_info->intf_ref_cnt[queue_id] = mmu_info->intf_ref_cnt[queue_id] 7274 + count; 7275 return BCM_E_NONE; 7276 } 7277 7278 /* 7279 * Function: 7280 * _bcm_kt2_intf_ref_cnt_decrement 7281 * Purpose: 7282 * Decrease interface reference count for queue id 7283 * Parameters: 7284 * unit - (IN) unit number 7285 * queue_id - (IN) HW queue id 7286 * count - (IN) Interface count 7287 * Returns: 7288 * BCM_E_XXX 7289 */ 7290 7291 int 7292 _bcm_kt2_intf_ref_cnt_decrement(int unit, uint32 queue_id, int count) 7293 { 7294 _bcm_kt2_mmu_info_t *mmu_info; 7295 7296 if (_bcm_kt2_mmu_info[unit] == NULL) { 7297 return BCM_E_INIT; 7298 } 7299 7300 mmu_info = _bcm_kt2_mmu_info[unit]; 7301 if (mmu_info->intf_ref_cnt[queue_id] > 0) { 7302 mmu_info->intf_ref_cnt[queue_id] = mmu_info->intf_ref_cnt[queue_id] 7303 - count; 7304 } else { 7305 return BCM_E_PARAM; 7306 } 7307 return BCM_E_NONE; 7308 } 7309 7310 /* 7311 * Function: 7312 * bcm_kt2_cosq_gport_add 7313 * Purpose: 7314 * Create a cosq gport structure 7315 * Parameters: 7316 * unit - (IN) unit number 7317 * port - (IN) port number 7318 * numq - (IN) number of COS queues 7319 * flags - (IN) flags (BCM_COSQ_GPORT_XXX) 7320 * gport - (OUT) GPORT identifier 7321 * Returns: 7322 * BCM_E_XXX 7323 */ 7324 int 7325 bcm_kt2_cosq_gport_add(int unit, bcm_gport_t port, int numq, uint32 flags, 7326 bcm_gport_t *gport) 7327 { 7328 _bcm_kt2_mmu_info_t *mmu_info; 7329 _bcm_kt2_cosq_port_info_t *port_info; 7330 _bcm_kt2_cosq_node_t *node = NULL; 7331 bcm_module_t local_modid, modid_out; 7332 bcm_port_t local_port, port_out; 7333 int id, max_nodes; 7334 uint32 sched_encap; 7335 _bcm_kt2_cosq_list_t *list; 7336 int max_queues; 7337 7338 LOG_INFO(BSL_LS_BCM_COSQ, 7339 (BSL_META_U(unit, 7340 "bcm_kt2_cosq_gport_add: unit=%d port=0x%x numq=%d flags=0x%x\n"), 7341 unit, port, numq, flags)); 7342 7343 if (gport == NULL) { 7344 return BCM_E_PARAM; 7345 } 7346 7347 if (_bcm_kt2_mmu_info[unit] == NULL) { 7348 return BCM_E_INIT; 7349 } 7350 7351 BCM_IF_ERROR_RETURN 7352 (_bcm_kt2_cosq_localport_resolve(unit, port, &local_port)); 7353 7354 if (local_port < 0) { 7355 return BCM_E_PORT; 7356 } 7357 7358 mmu_info = _bcm_kt2_mmu_info[unit]; 7359 port_info = &mmu_info->port[local_port]; 7360 switch (flags) { 7361 case BCM_COSQ_GPORT_UCAST_QUEUE_GROUP: 7362 if (numq != 1) { 7363 return BCM_E_PARAM; 7364 } 7365 7366 for (id = port_info->q_offset; id < port_info->q_limit; id++) { 7367 if (mmu_info->queue_node[id].numq == 0) { 7368 break; 7369 } 7370 } 7371 7372 if (id == port_info->q_limit) { 7373 return BCM_E_RESOURCE; 7374 } 7375 7376 BCM_GPORT_UCAST_QUEUE_GROUP_SYSQID_SET(*gport, local_port, id); 7377 list = &mmu_info->l2_base_qlist; 7378 _bcm_kt2_node_index_set(&mmu_info->l2_base_qlist, id, 1); 7379 node = &mmu_info->queue_node[id]; 7380 node->gport = *gport; 7381 node->numq = numq; 7382 node->hw_index = id; 7383 break; 7384 7385 case BCM_COSQ_GPORT_MCAST_QUEUE_GROUP: 7386 if ((numq != 1) || 7387 (!soc_feature(unit, soc_feature_mmu_packing))) { 7388 return BCM_E_PARAM; 7389 } 7390 for (id = port_info->mcq_offset; id < port_info->mcq_limit; id++) { 7391 if (mmu_info->queue_node[id].numq == 0) { 7392 break; 7393 } 7394 } 7395 7396 if (id == port_info->mcq_limit) { 7397 return BCM_E_RESOURCE; 7398 } 7399 7400 BCM_GPORT_MCAST_QUEUE_GROUP_SYSQID_SET(*gport, local_port, id); 7401 node = &mmu_info->queue_node[id]; 7402 node->gport = *gport; 7403 node->numq = numq; 7404 node->hw_index = id; 7405 break; 7406 7407 case BCM_COSQ_GPORT_VLAN_UCAST_QUEUE_GROUP: 7408 case BCM_COSQ_GPORT_SUBSCRIBER: 7409 case (BCM_COSQ_GPORT_SUBSCRIBER | BCM_COSQ_GPORT_MCAST_QUEUE_GROUP): 7410 if (numq != 1) { 7411 return BCM_E_PARAM; 7412 } 7413 7414 if ((flags & BCM_COSQ_GPORT_MCAST_QUEUE_GROUP) && 7415 (!soc_feature(unit, soc_feature_mmu_packing))) { 7416 return BCM_E_PARAM; 7417 } 7418 7419 if (flags & BCM_COSQ_GPORT_MCAST_QUEUE_GROUP) { 7420 /* check for pre allocated subscriber queues */ 7421 if (mmu_info->num_sub_queues == 0) { 7422 list = &mmu_info->global_qlist; 7423 max_queues = mmu_info->num_queues; 7424 BCM_IF_ERROR_RETURN 7425 (_bcm_kt2_node_index_get(unit, list->bits, mmu_info->num_queues/2, 7426 max_queues, mmu_info->qset_size, 1, &id)); 7427 _bcm_kt2_node_index_set(list, id, 1); 7428 BCM_GPORT_MCAST_SUBSCRIBER_QUEUE_GROUP_SYSQID_SET(*gport, 7429 local_port, id); 7430 } else { 7431 list = &mmu_info->sub_mcqlist; 7432 max_queues = mmu_info->num_sub_queues; 7433 BCM_IF_ERROR_RETURN 7434 (_bcm_kt2_node_index_get(unit, list->bits, 0, max_queues, 7435 mmu_info->qset_size, 1, &id)); 7436 _bcm_kt2_node_index_set(list, id, 1); 7437 BCM_GPORT_MCAST_SUBSCRIBER_QUEUE_GROUP_SYSQID_SET(*gport, 7438 local_port, id); 7439 id += (mmu_info->base_sub_queue + mmu_info->num_queues / 2); 7440 } 7441 } else { 7442 /* check for pre allocated subscriber queues */ 7443 if (mmu_info->num_sub_queues == 0) { 7444 list = &mmu_info->global_qlist; 7445 max_queues = (soc_feature(unit, soc_feature_mmu_packing) ? 7446 mmu_info->num_queues / 2 : mmu_info->num_queues); 7447 BCM_IF_ERROR_RETURN 7448 (_bcm_kt2_node_index_get(unit, list->bits, 0, max_queues, 7449 mmu_info->qset_size, 1, &id)); 7450 _bcm_kt2_node_index_set(list, id, 1); 7451 BCM_GPORT_UCAST_SUBSCRIBER_QUEUE_GROUP_SYSQID_SET(*gport, 7452 local_port, id); 7453 } else { 7454 list = &mmu_info->sub_qlist; 7455 max_queues = mmu_info->num_sub_queues; 7456 BCM_IF_ERROR_RETURN 7457 (_bcm_kt2_node_index_get(unit, list->bits, 0, max_queues, 7458 mmu_info->qset_size, 1, &id)); 7459 _bcm_kt2_node_index_set(list, id, 1); 7460 BCM_GPORT_UCAST_SUBSCRIBER_QUEUE_GROUP_SYSQID_SET(*gport, 7461 local_port, id); 7462 id += mmu_info->base_sub_queue; 7463 } 7464 } 7465 node = &mmu_info->queue_node[id]; 7466 node->gport = *gport; 7467 node->numq = numq; 7468 if (flags & BCM_COSQ_GPORT_SUBSCRIBER) { 7469 node->hw_index = id; 7470 } 7471 if (flags == BCM_COSQ_GPORT_VLAN_UCAST_QUEUE_GROUP) { 7472 node->type = _BCM_KT2_NODE_VLAN_UCAST; 7473 } 7474 if (id < port_info->uc_vlan_base) { 7475 port_info->uc_vlan_base = id; 7476 } 7477 break; 7478 7479 case (BCM_COSQ_GPORT_WITH_ID | BCM_COSQ_GPORT_SUBSCRIBER): 7480 if (numq != 1) { 7481 return BCM_E_PARAM; 7482 } 7483 7484 if (BCM_GPORT_UCAST_SUBSCRIBER_QUEUE_GROUP_SYSPORTID_GET(*gport) 7485 != local_port) { 7486 return BCM_E_PARAM; 7487 } 7488 7489 id = BCM_GPORT_UCAST_SUBSCRIBER_QUEUE_GROUP_QID_GET(*gport); 7490 if ((id >= mmu_info->num_sub_queues) || 7491 (mmu_info->num_sub_queues == 0) || 7492 (mmu_info->intf_ref_cnt[id] != 0)) { 7493 return BCM_E_PARAM; 7494 } 7495 max_queues = mmu_info->num_sub_queues; 7496 7497 node = &mmu_info->queue_node[id + mmu_info->base_sub_queue]; 7498 if(node->numq != 0) { 7499 return BCM_E_EXISTS; 7500 } 7501 _bcm_kt2_node_index_set(&mmu_info->sub_qlist, id, 1); 7502 _bcm_kt2_node_index_set(&mmu_info->l2_sub_qlist, id, 1); 7503 7504 id += mmu_info->base_sub_queue; 7505 node->hw_index = id; 7506 node->gport = *gport; 7507 node->numq = numq; 7508 node->type = _BCM_KT2_NODE_SUBSCRIBER_GPORT_ID; 7509 node->level = _BCM_KT2_COSQ_NODE_LEVEL_L2; 7510 if (id < port_info->uc_vlan_base) { 7511 port_info->uc_vlan_base = id; 7512 } 7513 break; 7514 7515 case (BCM_COSQ_GPORT_WITH_ID | BCM_COSQ_GPORT_SUBSCRIBER | 7516 BCM_COSQ_GPORT_MCAST_QUEUE_GROUP): 7517 7518 if (numq != 1) { 7519 return BCM_E_PARAM; 7520 } 7521 7522 if ((flags & BCM_COSQ_GPORT_MCAST_QUEUE_GROUP) && 7523 (!soc_feature(unit, soc_feature_mmu_packing))) { 7524 return BCM_E_PARAM; 7525 } 7526 7527 if (BCM_GPORT_MCAST_SUBSCRIBER_QUEUE_GROUP_SYSPORTID_GET(*gport) 7528 != local_port) { 7529 return BCM_E_PARAM; 7530 } 7531 7532 id = BCM_GPORT_MCAST_SUBSCRIBER_QUEUE_GROUP_QID_GET(*gport); 7533 if ((id >= mmu_info->num_sub_queues) || 7534 (mmu_info->num_sub_queues == 0) || 7535 (mmu_info->intf_ref_cnt[id] != 0)) { 7536 return BCM_E_PARAM; 7537 } 7538 max_queues = mmu_info->num_sub_queues; 7539 7540 node = &mmu_info->queue_node[id + mmu_info->base_sub_queue + mmu_info->num_queues/2]; 7541 if(node->numq != 0) { 7542 return BCM_E_EXISTS; 7543 } 7544 _bcm_kt2_node_index_set(&mmu_info->sub_mcqlist, id, 1); 7545 _bcm_kt2_node_index_set(&mmu_info->l2_sub_mcqlist, id, 1); 7546 7547 id += (mmu_info->base_sub_queue + mmu_info->num_queues/2); 7548 node->hw_index = id; 7549 node->gport = *gport; 7550 node->numq = numq; 7551 node->type = _BCM_KT2_NODE_SUBSCRIBER_GPORT_ID; 7552 node->level = _BCM_KT2_COSQ_NODE_LEVEL_L2; 7553 break; 7554 7555 case BCM_COSQ_GPORT_DESTMOD_UCAST_QUEUE_GROUP: 7556 if (numq != 1) { 7557 return BCM_E_PARAM; 7558 } 7559 7560 if (!IS_HG_PORT(unit, local_port)) { 7561 return BCM_E_PORT; 7562 } 7563 if (mmu_info->num_dmvoq_queues == 0) { 7564 list = &mmu_info->global_qlist; 7565 max_queues = mmu_info->num_queues; 7566 } else { 7567 list = &mmu_info->dmvoq_qlist; 7568 max_queues = mmu_info->num_dmvoq_queues; 7569 } 7570 7571 BCM_IF_ERROR_RETURN 7572 (_bcm_kt2_node_index_get(unit, list->bits, 0, max_queues, 7573 mmu_info->qset_size, 1, &id)); 7574 _bcm_kt2_node_index_set(list, id, 1); 7575 BCM_GPORT_DESTMOD_QUEUE_GROUP_SYSQID_SET(*gport, local_port, id); 7576 if (mmu_info->num_dmvoq_queues == 1) { 7577 id += mmu_info->base_dmvoq_queue; 7578 } 7579 node = &mmu_info->queue_node[id]; 7580 node->gport = *gport; 7581 node->numq = numq; 7582 node->level = _BCM_KT2_COSQ_NODE_LEVEL_L2; 7583 node->type = _BCM_KT2_NODE_VOQ; 7584 break; 7585 7586 case (BCM_COSQ_GPORT_WITH_ID | BCM_COSQ_GPORT_DESTMOD_UCAST_QUEUE_GROUP): 7587 if (numq != 1) { 7588 return BCM_E_PARAM; 7589 } 7590 7591 if (!IS_HG_PORT(unit, local_port)) { 7592 return BCM_E_PORT; 7593 } 7594 7595 if (BCM_GPORT_DESTMOD_QUEUE_GROUP_SYSPORTID_GET(*gport) 7596 != local_port) { 7597 return BCM_E_PARAM; 7598 } 7599 7600 id = BCM_GPORT_DESTMOD_QUEUE_GROUP_QID_GET(*gport); 7601 if ((id >= mmu_info->num_dmvoq_queues) || 7602 (mmu_info->num_dmvoq_queues == 0)) { 7603 return BCM_E_PARAM; 7604 } 7605 max_queues = mmu_info->num_dmvoq_queues; 7606 node = &mmu_info->queue_node[id + mmu_info->base_dmvoq_queue]; 7607 if(node->numq != 0) { 7608 return BCM_E_EXISTS; 7609 } 7610 _bcm_kt2_node_index_set(&mmu_info->dmvoq_qlist, id, 1); 7611 _bcm_kt2_node_index_set(&mmu_info->l2_dmvoq_qlist, id, 1); 7612 id += mmu_info->base_dmvoq_queue; 7613 node->hw_index = id; 7614 node->gport = *gport; 7615 node->numq = numq; 7616 node->level = _BCM_KT2_COSQ_NODE_LEVEL_L2; 7617 node->type = _BCM_KT2_NODE_VOQ_ID; 7618 break; 7619 7620 case BCM_COSQ_GPORT_SCHEDULER_WFQ: 7621 case BCM_COSQ_GPORT_SCHEDULER: 7622 case (BCM_COSQ_GPORT_SCHEDULER | BCM_COSQ_GPORT_SCHEDULER_WFQ): 7623 /* passthru */ 7624 case 0: 7625 7626 if (numq == 0 || numq < -1) { 7627 return BCM_E_PARAM; 7628 } 7629 7630 if (flags & BCM_COSQ_GPORT_SCHEDULER) { 7631 BCM_IF_ERROR_RETURN 7632 (_bcm_kt2_cosq_max_nodes_get(unit, _BCM_KT2_COSQ_NODE_LEVEL_L2, 7633 &max_nodes)); 7634 } else { 7635 BCM_IF_ERROR_RETURN 7636 (_bcm_kt2_cosq_max_nodes_get(unit, _BCM_KT2_COSQ_NODE_LEVEL_L0, 7637 &max_nodes)); 7638 } 7639 if (numq > max_nodes) { 7640 return BCM_E_PARAM; 7641 } 7642 7643 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &local_modid)); 7644 BCM_IF_ERROR_RETURN 7645 (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, local_modid, 7646 local_port, &modid_out, &port_out)); 7647 7648 if ((flags == 0) || (flags == BCM_COSQ_GPORT_SCHEDULER_WFQ)) { 7649 /* this is a port level scheduler */ 7650 id = port_out; 7651 7652 if ( id < 0 || id >= num_port_schedulers[unit]) { 7653 return BCM_E_PARAM; 7654 } 7655 7656 _bcm_kt2_node_index_set(&mmu_info->sched_list, id, 1); 7657 node = &mmu_info->sched_node[id]; 7658 sched_encap = (id << 8) | port_out; 7659 BCM_GPORT_SCHEDULER_SET(*gport, sched_encap); 7660 node->gport = *gport; 7661 node->level = _BCM_KT2_COSQ_NODE_LEVEL_ROOT; 7662 node->hw_index = id; 7663 node->numq = numq; 7664 node->cosq_attached_to = 0; 7665 if (flags == BCM_COSQ_GPORT_SCHEDULER_WFQ) { 7666 node->wrr_mode = 1; 7667 node->type = _BCM_KT2_NODE_SCHEDULER_WFQ; 7668 } 7669 } else { 7670 if (BCM_GPORT_IS_SUBPORT_PORT(port)) { 7671 id = BCM_GPORT_SUBPORT_PORT_GET(port); 7672 #if defined BCM_METROLITE_SUPPORT 7673 if (soc_feature(unit, soc_feature_discontinuous_pp_port)) { 7674 /* 7675 * Allocate S1 node from extended sched list if pp_port 7676 * is reused 7677 */ 7678 if (_SOC_IS_PP_PORT_LINKPHY_SUBTAG(unit, id) && 7679 (id <= num_port_schedulers[unit])) { 7680 id += SOC_INFO(unit).cpu_hg_pp_port_index; 7681 } 7682 } 7683 #endif 7684 } else { 7685 BCM_IF_ERROR_RETURN 7686 (_bcm_kt2_node_index_get(unit, mmu_info->sched_list.bits, 7687 soc_max_num_pp_ports[unit] + 1, 7688 mmu_info->num_nodes, 1, 1, &id)); 7689 } 7690 _bcm_kt2_node_index_set(&mmu_info->sched_list, id, 1); 7691 node = &mmu_info->sched_node[id]; 7692 sched_encap = (id << 8) | port_out; 7693 BCM_GPORT_SCHEDULER_SET(*gport, sched_encap); 7694 node->gport = *gport; 7695 node->numq = numq; 7696 node->cosq_attached_to = -1; 7697 if (flags & BCM_COSQ_GPORT_SCHEDULER_WFQ) { 7698 node->wrr_mode = 1; 7699 node->type = _BCM_KT2_NODE_SCHEDULER_WFQ; 7700 } 7701 if (BCM_GPORT_IS_SUBPORT_PORT(port)) { 7702 node->subport_enabled = 1; 7703 } 7704 } 7705 break; 7706 7707 case BCM_COSQ_GPORT_WITH_ID: 7708 if (BCM_GPORT_IS_SCHEDULER(*gport)) { 7709 if (numq == 0 || numq < -1 || numq > 8) { 7710 return BCM_E_PARAM; 7711 } 7712 id = BCM_GPORT_SCHEDULER_GET(*gport); 7713 7714 if (id != local_port) { 7715 return BCM_E_PARAM; 7716 } 7717 7718 /* allow only port or subport level scheduler with id */ 7719 if ( id < 0 || id >= soc_max_num_pp_ports[unit]) { 7720 return BCM_E_PARAM; 7721 } 7722 7723 _bcm_kt2_node_index_set(&mmu_info->sched_list, id, 1); 7724 node = &mmu_info->sched_node[id]; 7725 node->gport = *gport; 7726 node->level = _BCM_KT2_COSQ_NODE_LEVEL_ROOT; 7727 node->hw_index = id; 7728 node->numq = numq; 7729 node->cosq_attached_to = 0; 7730 } else if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(*gport)) { 7731 if (numq != 1) { 7732 return BCM_E_PARAM; 7733 } 7734 7735 if (BCM_GPORT_UCAST_QUEUE_GROUP_SYSPORTID_GET(*gport) 7736 != local_port) { 7737 return BCM_E_PARAM; 7738 } 7739 7740 id = BCM_GPORT_UCAST_QUEUE_GROUP_QID_GET(*gport); 7741 port_info = &mmu_info->port[local_port]; 7742 /* allow only base queues */ 7743 if (id < port_info->q_offset || id >= port_info->q_limit) { 7744 return BCM_E_PARAM; 7745 } 7746 7747 list = &mmu_info->l2_base_qlist; 7748 if (SHR_BITGET(list->bits, id) != 0) { 7749 return BCM_E_RESOURCE; 7750 } 7751 7752 node = &mmu_info->queue_node[id]; 7753 if (node->numq != 0) { 7754 return BCM_E_EXISTS; 7755 } 7756 7757 _bcm_kt2_node_index_set(&mmu_info->l2_base_qlist, id, 1); 7758 node->hw_index = id; 7759 node->gport = *gport; 7760 node->numq = numq; 7761 } else { 7762 return BCM_E_PARAM; 7763 } 7764 break; 7765 7766 default: 7767 return BCM_E_PARAM; 7768 } 7769 if ((flags == BCM_COSQ_GPORT_UCAST_QUEUE_GROUP) || 7770 (flags == BCM_COSQ_GPORT_MCAST_QUEUE_GROUP) || 7771 (flags == BCM_COSQ_GPORT_VLAN_UCAST_QUEUE_GROUP) || 7772 (flags == BCM_COSQ_GPORT_SUBSCRIBER) || 7773 (flags == (BCM_COSQ_GPORT_SUBSCRIBER | BCM_COSQ_GPORT_MCAST_QUEUE_GROUP)) || 7774 (flags == (BCM_COSQ_GPORT_WITH_ID | BCM_COSQ_GPORT_SUBSCRIBER)) || 7775 (flags == (BCM_COSQ_GPORT_WITH_ID | BCM_COSQ_GPORT_SUBSCRIBER | 7776 BCM_COSQ_GPORT_MCAST_QUEUE_GROUP)) || 7777 (flags == BCM_COSQ_GPORT_DESTMOD_UCAST_QUEUE_GROUP) || 7778 (flags == (BCM_COSQ_GPORT_WITH_ID | BCM_COSQ_GPORT_DESTMOD_UCAST_QUEUE_GROUP))) { 7779 BCM_IF_ERROR_RETURN( 7780 bcm_kt2_handle_queue_min_accounting(unit, local_port, 7781 node->hw_index, 1)); 7782 } 7783 LOG_INFO(BSL_LS_BCM_COSQ, 7784 (BSL_META_U(unit, 7785 " gport=0x%x\n"), 7786 *gport)); 7787 7788 return BCM_E_NONE; 7789 } 7790 /* 7791 * Function: 7792 * bcm_kt2_cosq_is_attached 7793 * Purpose: 7794 * To check if any queue is attached to port 7795 * Parameters: 7796 * unit - (IN) unit number 7797 * port - (IN) Physical port number 7798 * exclude_default - (IN) if set skip default queues 7799 * vlan_queue_present - (OUT) Set TRUE if queue is attached 7800 * Returns: 7801 * BCM_E_XXX 7802 */ 7803 int 7804 bcm_kt2_cosq_is_attached(int unit, 7805 bcm_port_t port, 7806 int exclude_default, 7807 int *vlan_queue_present) 7808 { 7809 _bcm_kt2_mmu_info_t *mmu_info; 7810 _bcm_kt2_cosq_port_info_t *port_info; 7811 uint32 *bmap = NULL; 7812 int max_word_count, word, index, bit; 7813 7814 /* Parameter sanity check */ 7815 if (port < 0) { 7816 return BCM_E_PORT; 7817 } 7818 if (vlan_queue_present == NULL) { 7819 return BCM_E_PARAM; 7820 } 7821 max_word_count = _SHR_BITDCLSIZE(soc_mem_index_count(unit, 7822 LLS_L2_PARENTm)); 7823 bmap = SOC_CONTROL(unit)->port_lls_l2_bmap[port]; 7824 7825 /* 7826 * Caller of this routine may invoke it with logical 7827 * port number for coe, linkphy or mpls applications. 7828 * In these cases bmap will be null. If it is NULL then 7829 * return BCM_E_NONE without changing vlan_queue_present. 7830 */ 7831 if (bmap == NULL) { 7832 return BCM_E_NONE; 7833 } 7834 7835 for (word = 0; word < max_word_count; word++) { 7836 if (bmap[word] == 0) { 7837 continue; 7838 } 7839 for (bit = 0; bit < SHR_BITWID; bit++) { 7840 if (!(bmap[word] & (1 << bit))) { 7841 continue; 7842 } 7843 index = word * SHR_BITWID + bit; 7844 /* check if index is for default queue */ 7845 mmu_info = _bcm_kt2_mmu_info[unit]; 7846 port_info = &mmu_info->port[port]; 7847 if (exclude_default && 7848 ((index >= port_info->q_offset && 7849 index < port_info->q_limit) || 7850 (index >= port_info->mcq_offset && 7851 index < port_info->mcq_limit))) { 7852 continue; 7853 } 7854 *vlan_queue_present = 1; 7855 return BCM_E_NONE; 7856 } 7857 } 7858 *vlan_queue_present = 0; 7859 return BCM_E_NONE; 7860 } 7861 /* 7862 * Function: 7863 * bcm_kt2_cosq_gport_delete 7864 * Purpose: 7865 * Destroy a cosq gport structure 7866 * Parameters: 7867 * unit - (IN) unit number 7868 * gport - (IN) GPORT identifier 7869 * Returns: 7870 * BCM_E_XXX 7871 */ 7872 int 7873 bcm_kt2_cosq_gport_delete(int unit, bcm_gport_t gport) 7874 { 7875 _bcm_kt2_cosq_node_t *node; 7876 _bcm_kt2_mmu_info_t *mmu_info; 7877 _bcm_kt2_cosq_port_info_t *port_info; 7878 int vlan_queue_present = 1; 7879 bcm_port_t local_port; 7880 uint32 rval = 0; 7881 int encap_id = 0; 7882 int rv = BCM_E_NONE; 7883 7884 LOG_INFO(BSL_LS_BCM_COSQ, 7885 (BSL_META_U(unit, 7886 "bcm_kt2_cosq_gport_delete: unit=%d gport=0x%x\n"), 7887 unit, gport)); 7888 7889 if (_bcm_kt2_mmu_info[unit] == NULL) { 7890 return BCM_E_INIT; 7891 } 7892 mmu_info = _bcm_kt2_mmu_info[unit]; 7893 7894 BCM_IF_ERROR_RETURN 7895 (_bcm_kt2_cosq_node_get(unit, gport, NULL, &local_port, NULL, &node)); 7896 7897 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 7898 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) || 7899 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport) || 7900 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport) || 7901 BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(gport)) { 7902 if (node->cosq_attached_to >= 0) { 7903 /* reset the shaper configuration for the 7904 * node 7905 */ 7906 7907 BCM_IF_ERROR_RETURN (bcm_kt2_cosq_gport_bandwidth_set(unit, 7908 node->gport, 0, 0, 0, _BCM_XGS_METER_FLAG_RESET)); 7909 BCM_IF_ERROR_RETURN 7910 (bcm_kt2_cosq_gport_detach(unit, gport, node->parent->gport, 7911 node->cosq_attached_to)); 7912 } 7913 if (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport)) { 7914 encap_id = BCM_GPORT_UCAST_SUBSCRIBER_QUEUE_GROUP_QID_GET(gport); 7915 if (mmu_info->num_sub_queues > 0) { 7916 _bcm_kt2_node_index_clear(&mmu_info->sub_qlist, 7917 encap_id, 1); 7918 encap_id += mmu_info->base_sub_queue; 7919 } else { 7920 _bcm_kt2_node_index_clear(&mmu_info->global_qlist, 7921 encap_id, 1); 7922 } 7923 /* Check if all unicast vlan queues of this port are deleted */ 7924 BCM_IF_ERROR_RETURN( 7925 bcm_kt2_cosq_is_attached(unit, local_port, 1, 7926 &vlan_queue_present)); 7927 port_info = &mmu_info->port[local_port]; 7928 if (!vlan_queue_present) { 7929 port_info->uc_vlan_base = mmu_info->num_queues - 1; 7930 SOC_IF_ERROR_RETURN(READ_ING_COS_MODEr(unit, local_port, &rval)); 7931 soc_reg_field_set(unit, ING_COS_MODEr, &rval, 7932 SERVICE_BASE_QUEUE_NUMf, port_info->uc_vlan_base); 7933 SOC_IF_ERROR_RETURN(WRITE_ING_COS_MODEr(unit, local_port, rval)); 7934 } 7935 } 7936 if (BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(gport)) { 7937 encap_id = BCM_GPORT_MCAST_SUBSCRIBER_QUEUE_GROUP_QID_GET(gport); 7938 if (mmu_info->num_sub_queues > 0) { 7939 _bcm_kt2_node_index_clear(&mmu_info->sub_mcqlist, 7940 encap_id - mmu_info->num_queues/2, 1); 7941 encap_id += mmu_info->base_sub_queue; 7942 } else { 7943 _bcm_kt2_node_index_clear(&mmu_info->global_qlist, 7944 encap_id, 1); 7945 } 7946 } 7947 7948 if (BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) { 7949 encap_id = BCM_GPORT_DESTMOD_QUEUE_GROUP_QID_GET(gport); 7950 if (mmu_info->num_dmvoq_queues > 0) { 7951 _bcm_kt2_node_index_clear(&mmu_info->dmvoq_qlist, 7952 encap_id, 1); 7953 encap_id += mmu_info->base_dmvoq_queue; 7954 } else { 7955 _bcm_kt2_node_index_clear(&mmu_info->global_qlist, 7956 encap_id, 1); 7957 } 7958 } 7959 BCM_IF_ERROR_RETURN( 7960 bcm_kt2_handle_queue_min_accounting(unit, local_port, 7961 encap_id, 0)); 7962 _BCM_KT2_COSQ_NODE_INIT(node); 7963 } else { 7964 /* 7965 * Deleting the SUB-Tree 7966 */ 7967 if (node->child != NULL) { 7968 BCM_IF_ERROR_RETURN 7969 (_bcm_kt2_cosq_gport_delete_all(unit, node->child->gport, &rv)); 7970 } 7971 /* 7972 * Deleting the parent Node 7973 */ 7974 BCM_IF_ERROR_RETURN 7975 (_bcm_kt2_cosq_gport_delete_node(unit, gport)); 7976 } 7977 7978 return rv; 7979 } 7980 7981 /* 7982 * Function: 7983 * bcm_kt2_cosq_gport_get 7984 * Purpose: 7985 * Get a cosq gport structure 7986 * Parameters: 7987 * unit - (IN) unit number 7988 * gport - (IN) GPORT identifier 7989 * port - (OUT) port number 7990 * numq - (OUT) number of COS queues 7991 * flags - (OUT) flags (BCM_COSQ_GPORT_XXX) 7992 * Returns: 7993 * BCM_E_XXX 7994 */ 7995 int 7996 bcm_kt2_cosq_gport_get(int unit, bcm_gport_t gport, bcm_gport_t *port, 7997 int *numq, uint32 *flags) 7998 { 7999 _bcm_kt2_cosq_node_t *node; 8000 bcm_module_t modid; 8001 bcm_port_t local_port; 8002 int id; 8003 _bcm_gport_dest_t dest; 8004 8005 if (port == NULL || numq == NULL || flags == NULL) { 8006 return BCM_E_PARAM; 8007 } 8008 8009 LOG_INFO(BSL_LS_BCM_COSQ, 8010 (BSL_META_U(unit, 8011 "bcm_kt2_cosq_gport_get: unit=%d gport=0x%x\n"), 8012 unit, gport)); 8013 8014 BCM_IF_ERROR_RETURN 8015 (_bcm_kt2_cosq_node_get(unit, gport, NULL, &local_port, &id, &node)); 8016 8017 if (SOC_USE_GPORT(unit)) { 8018 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid)); 8019 dest.gport_type = _SHR_GPORT_TYPE_MODPORT; 8020 dest.modid = modid; 8021 dest.port = local_port; 8022 BCM_IF_ERROR_RETURN(_bcm_esw_gport_construct(unit, &dest, port)); 8023 } else { 8024 *port = local_port; 8025 } 8026 8027 *numq = node->numq; 8028 8029 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 8030 *flags = BCM_COSQ_GPORT_UCAST_QUEUE_GROUP; 8031 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 8032 *flags = BCM_COSQ_GPORT_MCAST_QUEUE_GROUP; 8033 } else if (BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) { 8034 *flags = BCM_COSQ_GPORT_DESTMOD_UCAST_QUEUE_GROUP; 8035 } else if (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport)) { 8036 *flags = BCM_COSQ_GPORT_SUBSCRIBER; 8037 if (node->type == _BCM_KT2_NODE_VLAN_UCAST) { 8038 *flags = BCM_COSQ_GPORT_VLAN_UCAST_QUEUE_GROUP; 8039 } 8040 } else if (BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(gport)) { 8041 *flags = (BCM_COSQ_GPORT_SUBSCRIBER | 8042 BCM_COSQ_GPORT_MCAST_QUEUE_GROUP); 8043 } else if (BCM_GPORT_IS_SCHEDULER(gport)) { 8044 *flags = BCM_COSQ_GPORT_SCHEDULER; 8045 if (node->type == _BCM_KT2_NODE_SCHEDULER_WFQ) { 8046 if (node->level == _BCM_KT2_COSQ_NODE_LEVEL_ROOT) { 8047 *flags = BCM_COSQ_GPORT_SCHEDULER_WFQ; 8048 } else { 8049 *flags = BCM_COSQ_GPORT_SCHEDULER_WFQ | 8050 BCM_COSQ_GPORT_SCHEDULER; 8051 } 8052 } 8053 } else { 8054 *flags = 0; 8055 } 8056 8057 LOG_INFO(BSL_LS_BCM_COSQ, 8058 (BSL_META_U(unit, 8059 " port=0x%x numq=%d flags=0x%x\n"), 8060 *port, *numq, *flags)); 8061 8062 return BCM_E_NONE; 8063 } 8064 8065 /* 8066 * Function: 8067 * bcm_kt2_cosq_gport_traverse 8068 * Purpose: 8069 * Walks through the valid COSQ GPORTs and calls 8070 * the user supplied callback function for each entry. 8071 * Parameters: 8072 * unit - (IN) unit number 8073 * trav_fn - (IN) Callback function. 8074 * user_data - (IN) User data to be passed to callback function 8075 * Returns: 8076 * BCM_E_NONE - Success. 8077 * BCM_E_XXX 8078 */ 8079 int 8080 bcm_kt2_cosq_gport_traverse(int unit, bcm_cosq_gport_traverse_cb cb, 8081 void *user_data) 8082 { 8083 _bcm_kt2_cosq_node_t *port_info; 8084 _bcm_kt2_mmu_info_t *mmu_info; 8085 bcm_module_t my_modid, modid_out; 8086 bcm_port_t port, port_out; 8087 8088 if (_bcm_kt2_mmu_info[unit] == NULL) { 8089 return BCM_E_INIT; 8090 } 8091 mmu_info = _bcm_kt2_mmu_info[unit]; 8092 8093 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_modid)); 8094 PBMP_ALL_ITER(unit, port) { 8095 BCM_IF_ERROR_RETURN 8096 (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, 8097 my_modid, port, &modid_out, &port_out)); 8098 /* root node */ 8099 port_info = &mmu_info->sched_node[port_out]; 8100 8101 if (port_info->gport >= 0) { 8102 _bcm_kt2_cosq_gport_traverse(unit, port_info->gport, cb, user_data); 8103 } 8104 } 8105 8106 return BCM_E_NONE; 8107 } 8108 8109 /* 8110 * Function: 8111 * bcm_kt2_cosq_gport_egress_mapping_set 8112 * Purpose: 8113 * Determine which COS queue a given priority currently maps to. 8114 * Parameters: 8115 * unit - (IN) unit number 8116 * gport - (IN) queue group GPORT identifier 8117 * priority - (IN) priority value to map 8118 * cosq - (IN) COS queue to map to 8119 * Returns: 8120 * BCM_E_XXX 8121 */ 8122 int 8123 bcm_kt2_cosq_gport_egress_mapping_set(int unit, bcm_port_t gport, bcm_cos_t priority, 8124 bcm_cos_t cosq, uint32 flags) 8125 { 8126 bcm_pbmp_t ports; 8127 bcm_port_t local_port; 8128 BCM_PBMP_CLEAR(ports); 8129 8130 if (gport == -1) { /* all ports */ 8131 BCM_PBMP_ASSIGN(ports, PBMP_ALL(unit)); 8132 if ( soc_feature(unit, soc_feature_flex_port)) { 8133 BCM_IF_ERROR_RETURN( 8134 _bcm_kt2_flexio_pbmp_update(unit, 8135 &ports)); 8136 } 8137 } else { 8138 return _bcm_kt2_cosq_gport_egress_mapping_set_regular(unit, gport, priority, cosq, flags); 8139 } 8140 8141 PBMP_ITER(ports, local_port) { 8142 BCM_IF_ERROR_RETURN 8143 (_bcm_kt2_cosq_gport_egress_mapping_set_regular(unit, local_port, priority, 8144 cosq, flags)); 8145 8146 } 8147 8148 return BCM_E_NONE; 8149 } 8150 8151 8152 /* 8153 * Function: 8154 * bcm_kt2_cosq_mapping_get 8155 * Purpose: 8156 * Determine which COS queue a given priority currently maps to. 8157 * Parameters: 8158 * unit - (IN) unit number 8159 * gport - (IN) queue group GPORT identifier 8160 * priority - (IN) priority value to map 8161 * cosq - (OUT) COS queue to map to 8162 * Returns: 8163 * BCM_E_XXX 8164 */ 8165 int 8166 bcm_kt2_cosq_gport_egress_mapping_get(int unit, bcm_port_t gport, bcm_cos_t *priority, 8167 bcm_cos_queue_t *cosq, uint32 flags) 8168 { 8169 bcm_port_t port; 8170 soc_field_t field = REDIRECT_COSf; 8171 int index; 8172 egr_port_entry_t egr_port_entry; 8173 void *entry_p; 8174 8175 if (BCM_GPORT_IS_SET(gport)) { 8176 BCM_IF_ERROR_RETURN( 8177 bcm_esw_port_local_get(unit, gport, &port)); 8178 } else { 8179 port = gport; 8180 } 8181 8182 if (!SOC_PORT_VALID(unit, port) || !IS_ALL_PORT(unit, port)) { 8183 return BCM_E_PORT; 8184 } 8185 8186 BCM_IF_ERROR_RETURN 8187 (READ_EGR_PORTm(unit, MEM_BLOCK_ANY, port, &egr_port_entry)); 8188 index = soc_mem_field32_get(unit, EGR_PORTm, &egr_port_entry, 8189 EGR_COS_MAP_SELf); 8190 index *= 16; 8191 8192 entry_p = SOC_PROFILE_MEM_ENTRY(unit, _bcm_kt2_egr_cos_map_profile[unit], 8193 egr_cos_map_entry_t *, 8194 index + *priority); 8195 *cosq = soc_mem_field32_get(unit, EGR_COS_MAPm, entry_p, field); 8196 8197 8198 return BCM_E_NONE; 8199 } 8200 /* 8201 * Function: 8202 * bcm_kt2_cosq_mapping_set 8203 * Purpose: 8204 * Determine which COS queue a given priority currently maps to. 8205 * Parameters: 8206 * unit - (IN) unit number 8207 * gport - (IN) queue group GPORT identifier 8208 * priority - (IN) priority value to map 8209 * cosq - (IN) COS queue to map to 8210 * Returns: 8211 * BCM_E_XXX 8212 */ 8213 int 8214 bcm_kt2_cosq_mapping_set(int unit, bcm_port_t gport, bcm_cos_t priority, 8215 bcm_cos_queue_t cosq) 8216 { 8217 bcm_pbmp_t ports; 8218 bcm_port_t local_port; 8219 BCM_PBMP_CLEAR(ports); 8220 8221 if (gport == -1) { /* all ports */ 8222 BCM_PBMP_ASSIGN(ports, PBMP_ALL(unit)); 8223 if ( soc_feature(unit, soc_feature_flex_port)) { 8224 BCM_IF_ERROR_RETURN( 8225 _bcm_kt2_flexio_pbmp_update(unit, 8226 &ports)); 8227 } 8228 } else { 8229 return _bcm_kt2_cosq_mapping_set_regular(unit, gport, 1, &priority, &cosq); 8230 } 8231 8232 PBMP_ITER(ports, local_port) { 8233 BCM_IF_ERROR_RETURN 8234 (_bcm_kt2_cosq_mapping_set_regular(unit, local_port, 1, &priority, 8235 &cosq)); 8236 8237 } 8238 8239 return BCM_E_NONE; 8240 } 8241 8242 /* 8243 * Function: 8244 * bcm_kt2_cosq_port_mapping_multi_set 8245 * Purpose: 8246 * Determine which COS queue a given priority currently maps to. 8247 * Parameters: 8248 * unit - (IN) unit number 8249 * gport - (IN) queue group GPORT identifier 8250 * count - (IN) number of entries to be configured (or retrieved) 8251 * priority_array - (IN) array of priority value to map 8252 * cosq_array - (IN) array of COS queue to map to 8253 * Returns: 8254 * BCM_E_XXX 8255 */ 8256 int 8257 bcm_kt2_cosq_port_mapping_multi_set(int unit, bcm_port_t gport,int count, 8258 bcm_cos_t *priority_array, bcm_cos_queue_t *cosq_array) 8259 { 8260 bcm_pbmp_t ports; 8261 bcm_port_t local_port; 8262 BCM_PBMP_CLEAR(ports); 8263 8264 if (gport == -1) { /* all ports */ 8265 BCM_PBMP_ASSIGN(ports, PBMP_ALL(unit)); 8266 if ( soc_feature(unit, soc_feature_flex_port)) { 8267 BCM_IF_ERROR_RETURN( 8268 _bcm_kt2_flexio_pbmp_update(unit, 8269 &ports)); 8270 } 8271 } else { 8272 return _bcm_kt2_cosq_mapping_set_regular(unit, gport, count, 8273 priority_array, cosq_array); 8274 } 8275 8276 PBMP_ITER(ports, local_port) { 8277 BCM_IF_ERROR_RETURN 8278 (_bcm_kt2_cosq_mapping_set_regular(unit, local_port, count, 8279 priority_array, cosq_array)); 8280 } 8281 return BCM_E_NONE; 8282 } 8283 8284 /* 8285 * Function: 8286 * _bcm_kt2_cosq_mapping_get_regular 8287 * Purpose: 8288 * Determine which COS queue a given priority currently maps to. 8289 * Parameters: 8290 * unit - (IN) unit number 8291 * gport - (IN) queue group GPORT identifier 8292 * count - (IN) number of entries to be retrieved 8293 * priority_array - (IN) priority array values 8294 * cosq_array - (OUT) COS queue values mapped to priority 8295 * Returns: 8296 * BCM_E_XXX 8297 */ 8298 8299 STATIC 8300 int _bcm_kt2_cosq_mapping_get_regular (int unit, bcm_port_t gport,int count, 8301 bcm_cos_t *priority_array, bcm_cos_queue_t *cosq_array) 8302 { 8303 _bcm_kt2_mmu_info_t *mmu_info; 8304 bcm_port_t port; 8305 int numq; 8306 bcm_cos_queue_t hw_cosq; 8307 soc_field_t field = COSf; 8308 int index; 8309 int count_index = 0; 8310 cos_map_sel_entry_t cos_map_sel_entry; 8311 void *entry_p; 8312 bcm_pbmp_t ports; 8313 8314 8315 if (count < 1 || count > 16){ 8316 return BCM_E_PARAM; 8317 } 8318 8319 if ((NULL == priority_array) || (NULL == cosq_array)){ 8320 return BCM_E_PARAM; 8321 } 8322 8323 for (count_index = 0; count_index < count; count_index++) { 8324 if (priority_array[count_index] < 0 || priority_array[count_index] >= 16) { 8325 return BCM_E_PARAM; 8326 } 8327 } 8328 8329 if (gport == -1) { 8330 BCM_PBMP_ASSIGN(ports, PBMP_ALL(unit)); 8331 PBMP_ITER(ports, port) { 8332 BCM_IF_ERROR_RETURN 8333 (READ_COS_MAP_SELm(unit, MEM_BLOCK_ANY, port, 8334 &cos_map_sel_entry)); 8335 index = soc_mem_field32_get(unit, COS_MAP_SELm, 8336 &cos_map_sel_entry, 8337 SELECTf); 8338 index *= 16; 8339 8340 entry_p = SOC_PROFILE_MEM_ENTRY(unit, _bcm_kt2_cos_map_profile[unit], 8341 port_cos_map_entry_t *, 8342 index + priority_array[0]); /*only return for first priority*/ 8343 cosq_array[0] = soc_mem_field32_get(unit, PORT_COS_MAPm, entry_p, field); 8344 return BCM_E_NONE; 8345 } 8346 } 8347 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 8348 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 8349 BCM_IF_ERROR_RETURN 8350 (_bcm_kt2_cosq_index_resolve 8351 (unit, gport, -1, _BCM_KT2_COSQ_INDEX_STYLE_UCAST_QUEUE, 8352 &port, NULL, NULL)); 8353 } else if(_BCM_KT2_GPORT_IS_LINKPHY_OR_SUBTAG_SUBPORT_GPORT (unit, gport)) { 8354 port = _BCM_KT2_SUBPORT_PORT_ID_GET(gport); 8355 } else { 8356 if (BCM_GPORT_IS_SET(gport)) { 8357 BCM_IF_ERROR_RETURN( 8358 bcm_esw_port_local_get(unit, gport, &port)); 8359 } else { 8360 port = gport; 8361 } 8362 8363 if (!SOC_PORT_VALID(unit, port) || !IS_ALL_PORT(unit, port)) { 8364 return BCM_E_PORT; 8365 } 8366 } 8367 8368 mmu_info = _bcm_kt2_mmu_info[unit]; 8369 numq = mmu_info->port[port].q_limit - 8370 mmu_info->port[port].q_offset; 8371 8372 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 8373 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 8374 field = (numq <= 8) ? COSf : HG_COSf; 8375 } 8376 8377 BCM_IF_ERROR_RETURN 8378 (READ_COS_MAP_SELm(unit, MEM_BLOCK_ANY, port, &cos_map_sel_entry)); 8379 index = soc_mem_field32_get(unit, COS_MAP_SELm, &cos_map_sel_entry, 8380 SELECTf); 8381 index *= 16; 8382 8383 for (count_index = 0; count_index < count; count_index++) { 8384 entry_p = SOC_PROFILE_MEM_ENTRY(unit, _bcm_kt2_cos_map_profile[unit], 8385 port_cos_map_entry_t *, 8386 index + priority_array[count_index]); 8387 hw_cosq = soc_mem_field32_get(unit, PORT_COS_MAPm, entry_p, field); 8388 8389 if (hw_cosq >= numq) { 8390 return BCM_E_NOT_FOUND; 8391 } 8392 cosq_array[count_index] = hw_cosq; 8393 } 8394 return BCM_E_NONE; 8395 } 8396 8397 /* 8398 * Function: 8399 * bcm_kt2_cosq_port_mapping_multi_get 8400 * Purpose: 8401 * Determine which COS queue a given priority currently maps to. 8402 * Parameters: 8403 * unit - (IN) unit number 8404 * gport - (IN) queue group GPORT identifier 8405 * count - (IN) number of entries to be retrieved 8406 * priority_array - (IN) priority array values 8407 * cosq_array - (OUT) COS queue values mapped to priority 8408 * Returns: 8409 * BCM_E_XXX 8410 */ 8411 int 8412 bcm_kt2_cosq_port_mapping_multi_get(int unit, bcm_port_t gport, int count, 8413 bcm_cos_t *priority_array, bcm_cos_queue_t *cosq_array) 8414 { 8415 return _bcm_kt2_cosq_mapping_get_regular (unit, gport,count, 8416 priority_array, cosq_array); 8417 } 8418 8419 /* 8420 * Function: 8421 * bcm_kt2_cosq_mapping_get 8422 * Purpose: 8423 * Determine which COS queue a given priority currently maps to. 8424 * Parameters: 8425 * unit - (IN) unit number 8426 * gport - (IN) queue group GPORT identifier 8427 * priority - (IN) priority value to map 8428 * cosq - (OUT) COS queue to map to 8429 * Returns: 8430 * BCM_E_XXX 8431 */ 8432 int 8433 bcm_kt2_cosq_mapping_get(int unit, bcm_port_t gport, bcm_cos_t priority, 8434 bcm_cos_queue_t *cosq) 8435 { 8436 return _bcm_kt2_cosq_mapping_get_regular (unit, gport, 1, 8437 &priority, cosq); 8438 8439 } 8440 8441 /* 8442 * Function: 8443 * bcm_kt2_cosq_port_sched_set 8444 * Purpose: 8445 * Set up class-of-service policy and corresponding weights and delay 8446 * Parameters: 8447 * unit - (IN) unit number 8448 * pbm - (IN) port bitmap 8449 * mode - (IN) Scheduling mode (BCM_COSQ_xxx) 8450 * weights - (IN) Weights for each COS queue 8451 * delay - This parameter is not used 8452 * Returns: 8453 * BCM_E_XXX 8454 * Notes: 8455 * For non-ETS style scheduler (CPU port) only. 8456 */ 8457 int 8458 bcm_kt2_cosq_port_sched_set(int unit, bcm_pbmp_t pbm, 8459 int mode, const int *weights, int delay) 8460 { 8461 bcm_port_t port; 8462 int num_cos=0; 8463 int num_weights; 8464 8465 bcm_kt2_cosq_config_get(unit, &num_cos); 8466 BCM_PBMP_ITER(pbm, port) { 8467 num_weights = IS_CPU_PORT(unit, port) ? BCM_COS_COUNT : num_cos; 8468 8469 BCM_IF_ERROR_RETURN 8470 (_bcm_kt2_cosq_port_sched_set(unit, port, 0, mode, num_weights, 8471 (int *)weights)); 8472 } 8473 8474 return BCM_E_NONE; 8475 } 8476 8477 /* 8478 * Function: 8479 * bcm_kt2_cosq_port_sched_get 8480 * Purpose: 8481 * Retrieve class-of-service policy and corresponding weights and delay 8482 * Parameters: 8483 * unit - (IN) unit number 8484 * pbm - (IN) port bitmap 8485 * mode - (OUT) Scheduling mode (BCM_COSQ_XXX) 8486 * weights - (OUT) Weights for each COS queue 8487 * delay - This parameter is not used 8488 * Returns: 8489 * BCM_E_XXX 8490 * Notes: 8491 * For non-ETS style scheduler (CPU port) only. 8492 */ 8493 int 8494 bcm_kt2_cosq_port_sched_get(int unit, bcm_pbmp_t pbm, 8495 int *mode, int *weights, int *delay) 8496 { 8497 bcm_port_t port; 8498 int num_cos=0; 8499 int num_weights; 8500 8501 8502 bcm_kt2_cosq_config_get(unit, &num_cos); 8503 BCM_PBMP_ITER(pbm, port) { 8504 num_weights = IS_CPU_PORT(unit, port) ? BCM_COS_COUNT : num_cos; 8505 8506 BCM_IF_ERROR_RETURN 8507 (_bcm_kt2_cosq_port_sched_get(unit, port, 0, mode, num_weights, 8508 weights)); 8509 } 8510 8511 return BCM_E_NONE; 8512 } 8513 8514 /* 8515 * Function: 8516 * bcm_kt2_cosq_sched_weight_max_get 8517 * Purpose: 8518 * Retrieve maximum weights for given COS policy 8519 * Parameters: 8520 * unit - (IN) unit number 8521 * mode - (IN) Scheduling mode (BCM_COSQ_xxx) 8522 * weight_max - (OUT) Maximum weight for COS queue. 8523 * Returns: 8524 * BCM_E_XXX 8525 */ 8526 int 8527 bcm_kt2_cosq_sched_weight_max_get(int unit, int mode, int *weight_max) 8528 { 8529 switch (mode) { 8530 case BCM_COSQ_STRICT: 8531 *weight_max = BCM_COSQ_WEIGHT_STRICT; 8532 break; 8533 case BCM_COSQ_ROUND_ROBIN: 8534 *weight_max = BCM_COSQ_WEIGHT_MIN; 8535 break; 8536 case BCM_COSQ_WEIGHTED_ROUND_ROBIN: 8537 case BCM_COSQ_DEFICIT_ROUND_ROBIN: 8538 *weight_max = 8539 (1 << soc_mem_field_length(unit, LLS_L0_CHILD_WEIGHT_CFG_CNTm, 8540 C_WEIGHTf)) - 1; 8541 break; 8542 default: 8543 return BCM_E_PARAM; 8544 } 8545 8546 return BCM_E_NONE; 8547 } 8548 8549 /* 8550 * Function: 8551 * bcm_kt2_cosq_bandwidth_set 8552 * Purpose: 8553 * Configure COS queue bandwidth control 8554 * Parameters: 8555 * unit - (IN) unit number 8556 * port - (IN) port number or GPORT identifier 8557 * cosq - (IN) COS queue number 8558 * min_quantum - (IN) 8559 * max_quantum - (IN) 8560 * burst_quantum - (IN) 8561 * flags - (IN) 8562 * Returns: 8563 * BCM_E_XXX 8564 * Notes: 8565 * If port is any form of local port, cosq is the hardware queue index. 8566 */ 8567 int 8568 bcm_kt2_cosq_port_bandwidth_set(int unit, bcm_port_t port, 8569 bcm_cos_queue_t cosq, 8570 uint32 min_quantum, uint32 max_quantum, 8571 uint32 burst_quantum, uint32 flags) 8572 { 8573 if (cosq < 0) { 8574 return BCM_E_PARAM; 8575 } 8576 8577 return _bcm_kt2_cosq_bucket_set(unit, port, cosq, min_quantum, 8578 max_quantum, min_quantum, 8579 burst_quantum, flags); 8580 } 8581 8582 /* 8583 * Function: 8584 * bcm_kt2_cosq_bandwidth_get 8585 * Purpose: 8586 * Get COS queue bandwidth control configuration 8587 * Parameters: 8588 * unit - (IN) unit number 8589 * port - (IN) port number or GPORT identifier 8590 * cosq - (IN) COS queue number 8591 * min_quantum - (OUT) 8592 * max_quantum - (OUT) 8593 * burst_quantum - (OUT) 8594 * flags - (OUT) 8595 * Returns: 8596 * BCM_E_XXX 8597 * Notes: 8598 * If port is any form of local port, cosq is the hardware queue index. 8599 */ 8600 int 8601 bcm_kt2_cosq_port_bandwidth_get(int unit, bcm_port_t port, 8602 bcm_cos_queue_t cosq, 8603 uint32 *min_quantum, uint32 *max_quantum, 8604 uint32 *burst_quantum, uint32 *flags) 8605 { 8606 8607 if (cosq < 0) { 8608 return BCM_E_PARAM; 8609 } 8610 8611 BCM_IF_ERROR_RETURN(_bcm_kt2_cosq_bucket_get(unit, port, cosq, min_quantum, 8612 max_quantum, burst_quantum, 8613 burst_quantum, *flags)); 8614 *flags = 0; 8615 8616 return BCM_E_NONE; 8617 } 8618 8619 int 8620 bcm_kt2_cosq_port_pps_set(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 8621 int pps) 8622 { 8623 uint32 min, max, burst_min, burst_max; 8624 8625 if (!IS_CPU_PORT(unit, port)) { 8626 return BCM_E_PORT; 8627 } else if (cosq < 0 || cosq >= NUM_CPU_COSQ(unit)) { 8628 return BCM_E_PARAM; 8629 } 8630 8631 BCM_IF_ERROR_RETURN 8632 (_bcm_kt2_cosq_bucket_get(unit, port, cosq, &min, &max, &burst_min, 8633 &burst_max, _BCM_XGS_METER_FLAG_PACKET_MODE)); 8634 8635 return _bcm_kt2_cosq_bucket_set(unit, port, cosq, min, pps, burst_min, 8636 burst_max, _BCM_XGS_METER_FLAG_PACKET_MODE); 8637 } 8638 8639 int 8640 bcm_kt2_cosq_port_pps_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 8641 int *pps) 8642 { 8643 uint32 min, max, burst_min, burst_max; 8644 8645 if (!IS_CPU_PORT(unit, port)) { 8646 return BCM_E_PORT; 8647 } else if (cosq < 0 || cosq >= NUM_CPU_COSQ(unit)) { 8648 return BCM_E_PARAM; 8649 } 8650 8651 BCM_IF_ERROR_RETURN 8652 (_bcm_kt2_cosq_bucket_get(unit, port, cosq, &min, &max, &burst_min, 8653 &burst_max, _BCM_XGS_METER_FLAG_PACKET_MODE)); 8654 *pps = max; 8655 8656 return BCM_E_NONE; 8657 } 8658 8659 int 8660 bcm_kt2_cosq_port_burst_set(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 8661 int burst) 8662 { 8663 uint32 min, max, cur_burst_min, cur_burst_max; 8664 8665 if (!IS_CPU_PORT(unit, port)) { 8666 return BCM_E_PORT; 8667 } else if (cosq < 0 || cosq >= NUM_CPU_COSQ(unit)) { 8668 return BCM_E_PARAM; 8669 } 8670 8671 /* Get the current PPS and BURST settings */ 8672 BCM_IF_ERROR_RETURN 8673 (_bcm_kt2_cosq_bucket_get(unit, port, cosq, &min, &max, &cur_burst_min, 8674 &cur_burst_max, _BCM_XGS_METER_FLAG_PACKET_MODE)); 8675 8676 /* Replace the current BURST setting, keep PPS the same */ 8677 return _bcm_kt2_cosq_bucket_set(unit, port, cosq, min, max, cur_burst_min, 8678 burst, _BCM_XGS_METER_FLAG_PACKET_MODE); 8679 } 8680 8681 int 8682 bcm_kt2_cosq_port_burst_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 8683 int *burst) 8684 { 8685 uint32 min, max, cur_burst_min, cur_burst_max; 8686 8687 if (!IS_CPU_PORT(unit, port)) { 8688 return BCM_E_PORT; 8689 } else if (cosq < 0 || cosq >= NUM_CPU_COSQ(unit)) { 8690 return BCM_E_PARAM; 8691 } 8692 8693 BCM_IF_ERROR_RETURN 8694 (_bcm_kt2_cosq_bucket_get(unit, port, cosq, &min, &max, &cur_burst_min, 8695 &cur_burst_max, _BCM_XGS_METER_FLAG_PACKET_MODE)); 8696 *burst = cur_burst_max; 8697 8698 return BCM_E_NONE; 8699 } 8700 8701 /* 8702 * Function: 8703 * bcm_kt2_cosq_gport_sched_set 8704 * Purpose: 8705 * Configure COS queue scheduler setting 8706 * Parameters: 8707 * unit - (IN) unit number 8708 * gport - (IN) GPORT identifier 8709 * cosq - (IN) COS queue to configure, -1 for all COS queues 8710 * mode - (IN) Scheduling mode, one of BCM_COSQ_xxx 8711 * weight - (IN) queue weight 8712 * Returns: 8713 * BCM_E_XXX 8714 */ 8715 int 8716 bcm_kt2_cosq_gport_sched_set(int unit, bcm_gport_t gport, 8717 bcm_cos_queue_t cosq, int mode, int weight) 8718 { 8719 int rv, numq, i, count; 8720 8721 if (cosq == -1) { 8722 BCM_IF_ERROR_RETURN 8723 (_bcm_kt2_cosq_index_resolve(unit, gport, cosq, 8724 _BCM_KT2_COSQ_INDEX_STYLE_SCHEDULER, 8725 NULL, NULL, &numq)); 8726 cosq = 0; 8727 } else { 8728 numq = 1; 8729 } 8730 8731 count = 0; 8732 for (i = 0; i < numq; i++) { 8733 rv = _bcm_kt2_cosq_sched_set(unit, gport, cosq + i, mode, 1, &weight); 8734 if (rv == BCM_E_NOT_FOUND) { 8735 continue; 8736 } else if (BCM_FAILURE(rv)) { 8737 return rv; 8738 } else { 8739 count++; 8740 } 8741 } 8742 8743 return count > 0 ? BCM_E_NONE : BCM_E_NOT_FOUND; 8744 } 8745 8746 /* 8747 * Function: 8748 * bcm_kt2_cosq_gport_sched_get 8749 * Purpose: 8750 * Get COS queue scheduler setting 8751 * Parameters: 8752 * unit - (IN) unit number 8753 * gport - (IN) GPORT identifier 8754 * cosq - (IN) COS queue to get, -1 for any queue 8755 * mode - (OUT) Scheduling mode, one of BCM_COSQ_xxx 8756 * weight - (OUT) queue weight 8757 * Returns: 8758 * BCM_E_XXX 8759 */ 8760 int 8761 bcm_kt2_cosq_gport_sched_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 8762 int *mode, int *weight) 8763 { 8764 int rv, numq, i; 8765 8766 if (cosq == -1) { 8767 BCM_IF_ERROR_RETURN 8768 (_bcm_kt2_cosq_index_resolve(unit, gport, cosq, 8769 _BCM_KT2_COSQ_INDEX_STYLE_SCHEDULER, 8770 NULL, NULL, &numq)); 8771 cosq = 0; 8772 } else { 8773 numq = 1; 8774 } 8775 8776 for (i = 0; i < numq; i++) { 8777 rv = _bcm_kt2_cosq_sched_get(unit, gport, cosq + i, mode, 1, weight); 8778 if (rv == BCM_E_NOT_FOUND) { 8779 continue; 8780 } else { 8781 return rv; 8782 } 8783 } 8784 8785 return BCM_E_NOT_FOUND; 8786 } 8787 8788 /* 8789 * Function: 8790 * bcm_kt2_cosq_gport_child_node_bandwidth_set 8791 * Purpose: 8792 * Configure COS queue bandwidth control 8793 * Parameters: 8794 * unit - (IN) unit number 8795 * gport - (IN) GPORT identifier 8796 * cosq - (IN) COS queue to configure, -1 for all COS queues 8797 * kbits_sec_min - (IN) minimum bandwidth, kbits/sec 8798 * kbits_sec_max - (IN) maximum bandwidth, kbits/sec 8799 * flags - (IN) BCM_COSQ_BW_* 8800 * Returns: 8801 * BCM_E_XXX 8802 */ 8803 int 8804 bcm_kt2_cosq_gport_child_node_bandwidth_set(int unit, 8805 bcm_gport_t gport, bcm_cos_queue_t cosq, 8806 uint32 kbits_sec_min, uint32 kbits_sec_max, 8807 uint32 flags) 8808 { 8809 _bcm_kt2_cosq_node_t *node = NULL; 8810 _bcm_kt2_cosq_node_t *cur_node = NULL; 8811 bcm_gport_t cur_gport; 8812 int start_cos; 8813 int end_cos; 8814 int numq, i; 8815 uint32 temp_kbits_sec_min = 0; 8816 uint32 temp_kbits_sec_max = 0; 8817 uint32 kbits_sec_burst_min = 0; 8818 uint32 kbits_sec_burst_max = 0; 8819 uint32 child_found_flag=0; 8820 bcm_port_t local_port; 8821 _bcm_kt2_mmu_info_t *mmu_info; 8822 8823 cur_gport = gport; 8824 8825 BCM_IF_ERROR_RETURN 8826 (_bcm_kt2_cosq_index_resolve(unit, gport, cosq, 8827 _BCM_KT2_COSQ_INDEX_STYLE_BUCKET, 8828 &local_port, NULL, &numq)); 8829 if (cosq == -1) { 8830 start_cos = 0; 8831 end_cos = numq - 1; 8832 8833 } else { 8834 start_cos = end_cos = cosq; 8835 } 8836 8837 if ((BCM_GPORT_IS_SET(gport)) && 8838 (BCM_GPORT_IS_SCHEDULER(gport))) { 8839 BCM_IF_ERROR_RETURN 8840 (_bcm_kt2_cosq_node_get(unit, gport, NULL, NULL, NULL, &node)); 8841 } 8842 8843 if (node) { 8844 /* For Port gport, L0, L1 scheduler nodes */ 8845 if (cosq >= node->numq) { 8846 return BCM_E_PARAM; 8847 } 8848 child_found_flag = 0; 8849 for (i = 0, cur_node = node->child; cur_node; 8850 cur_node = cur_node->sibling, i++) { 8851 8852 /* get the child node at cosq */ 8853 if ((cosq != -1) && (cur_node->cosq_attached_to != cosq)) { 8854 continue; 8855 } 8856 child_found_flag = 1; 8857 cur_gport = cur_node->gport; 8858 8859 BCM_IF_ERROR_RETURN 8860 (_bcm_kt2_cosq_bucket_get(unit, cur_gport 8861 ,cur_node->cosq_attached_to, 8862 &temp_kbits_sec_min, 8863 &temp_kbits_sec_max, 8864 &kbits_sec_burst_min, 8865 &kbits_sec_burst_max, 0)); 8866 if ((kbits_sec_burst_min || kbits_sec_burst_max) && 8867 (!(flags & BCM_COSQ_BW_BURST_CALCULATE))) 8868 { 8869 flags = _BCM_XGS_METER_FLAG_NON_BURST_CORRECTION; 8870 } 8871 8872 BCM_IF_ERROR_RETURN 8873 (_bcm_kt2_cosq_bucket_set(unit, cur_gport, 8874 cur_node->cosq_attached_to, kbits_sec_min, 8875 kbits_sec_max, kbits_sec_burst_min, 8876 kbits_sec_burst_max, flags)); 8877 if (flags & BCM_COSQ_BW_BURST_CALCULATE) { 8878 cur_node->burst_calculation_enable = 1; 8879 } else { 8880 cur_node->burst_calculation_enable = 0; 8881 } 8882 } 8883 if (child_found_flag == 0) { 8884 return BCM_E_NOT_FOUND; 8885 } 8886 } else { 8887 /* For Port and L2 queues */ 8888 for (i = start_cos; i <= end_cos; i++) { 8889 BCM_IF_ERROR_RETURN 8890 (_bcm_kt2_cosq_bucket_get(unit, cur_gport, i, 8891 &temp_kbits_sec_min, 8892 &temp_kbits_sec_max, 8893 &kbits_sec_burst_min, 8894 &kbits_sec_burst_max, 0)); 8895 8896 if ((kbits_sec_burst_min || kbits_sec_burst_max) && 8897 (!(flags & BCM_COSQ_BW_BURST_CALCULATE))) 8898 { 8899 flags = _BCM_XGS_METER_FLAG_NON_BURST_CORRECTION; 8900 } 8901 BCM_IF_ERROR_RETURN 8902 (_bcm_kt2_cosq_bucket_set(unit, cur_gport, 8903 i, kbits_sec_min, 8904 kbits_sec_max, 8905 kbits_sec_burst_min, 8906 kbits_sec_burst_max, flags)); 8907 mmu_info = _bcm_kt2_mmu_info[unit]; 8908 cur_node = &mmu_info->queue_node[mmu_info->port[ 8909 local_port].q_offset + i]; 8910 if (flags & BCM_COSQ_BW_BURST_CALCULATE) { 8911 cur_node->burst_calculation_enable = 1; 8912 } else { 8913 cur_node->burst_calculation_enable = 0; 8914 } 8915 } 8916 } 8917 8918 return BCM_E_NONE; 8919 } 8920 8921 /* 8922 * Function: 8923 * bcm_kt2_cosq_gport_child_node_bandwidth_get 8924 * Purpose: 8925 * Get COS queue bandwidth control configuration 8926 * Parameters: 8927 * unit - (IN) unit number 8928 * gport - (IN) GPORT identifier 8929 * cosq - (IN) COS queue to get, -1 for any COS queue 8930 * kbits_sec_min - (OUT) minimum bandwidth, kbits/sec 8931 * kbits_sec_max - (OUT) maximum bandwidth, kbits/sec 8932 * flags - (OUT) BCM_COSQ_BW_* 8933 * Returns: 8934 * BCM_E_XXX 8935 */ 8936 int 8937 bcm_kt2_cosq_gport_child_node_bandwidth_get(int unit, bcm_gport_t gport, 8938 bcm_cos_queue_t cosq, uint32 *kbits_sec_min, 8939 uint32 *kbits_sec_max, uint32 *flags) 8940 { 8941 uint32 burst_min, burst_max; 8942 _bcm_kt2_cosq_node_t *node = NULL; 8943 _bcm_kt2_cosq_node_t *cur_node = NULL; 8944 bcm_gport_t cur_gport; 8945 int i; 8946 bcm_port_t local_port; 8947 _bcm_kt2_mmu_info_t *mmu_info; 8948 8949 i = (cosq == -1) ? 0 : cosq; 8950 8951 cur_gport = gport; 8952 if ((BCM_GPORT_IS_SET(gport)) && 8953 (BCM_GPORT_IS_SCHEDULER(gport))) { 8954 /* get the child node at cosq 8955 */ 8956 BCM_IF_ERROR_RETURN 8957 (_bcm_kt2_cosq_node_get(unit, gport, NULL, NULL, NULL, &node)); 8958 if (node != NULL) { 8959 if (cosq >= node->numq) { 8960 return BCM_E_PARAM; 8961 } 8962 /* resolve the child attached to input cosq */ 8963 BCM_IF_ERROR_RETURN( 8964 _bcm_kt2_cosq_child_node_at_input(node, i, &cur_node)); 8965 cur_gport = cur_node->gport; 8966 8967 } else { 8968 return BCM_E_PARAM; 8969 } 8970 8971 } else { 8972 BCM_IF_ERROR_RETURN 8973 (_bcm_kt2_cosq_index_resolve(unit, gport, i, 8974 _BCM_KT2_COSQ_INDEX_STYLE_BUCKET, 8975 &local_port, NULL, NULL)); 8976 mmu_info = _bcm_kt2_mmu_info[unit]; 8977 cur_node = &mmu_info->queue_node[mmu_info->port[ 8978 local_port].q_offset + i]; 8979 } 8980 8981 BCM_IF_ERROR_RETURN 8982 (_bcm_kt2_cosq_bucket_get(unit, cur_gport, i, 8983 kbits_sec_min, kbits_sec_max, 8984 &burst_min, &burst_max, *flags)); 8985 8986 *flags = 0; 8987 if (cur_node->burst_calculation_enable == 1) { 8988 *flags |= BCM_COSQ_BW_BURST_CALCULATE; 8989 } 8990 return BCM_E_NONE; 8991 } 8992 8993 /* 8994 * Function: 8995 * bcm_kt2_cosq_gport_bandwidth_set 8996 * Purpose: 8997 * Configure COS queue bandwidth control 8998 * Parameters: 8999 * unit - (IN) unit number 9000 * gport - (IN) GPORT identifier 9001 * cosq - (IN) COS queue to configure, -1 for all COS queues 9002 * kbits_sec_min - (IN) minimum bandwidth, kbits/sec 9003 * kbits_sec_max - (IN) maximum bandwidth, kbits/sec 9004 * flags - (IN) BCM_COSQ_BW_* 9005 * Returns: 9006 * BCM_E_XXX 9007 */ 9008 int 9009 bcm_kt2_cosq_gport_bandwidth_set(int unit, bcm_gport_t gport, 9010 bcm_cos_queue_t cosq, uint32 kbits_sec_min, 9011 uint32 kbits_sec_max, uint32 flags) 9012 { 9013 int numq, i; 9014 if (cosq == -1) { 9015 BCM_IF_ERROR_RETURN 9016 (_bcm_kt2_cosq_index_resolve(unit, gport, cosq, 9017 _BCM_KT2_COSQ_INDEX_STYLE_BUCKET, 9018 NULL, NULL, &numq)); 9019 cosq = 0; 9020 } else { 9021 numq = 1; 9022 } 9023 for (i = 0; i < numq; i++) { 9024 BCM_IF_ERROR_RETURN 9025 (_bcm_kt2_cosq_bucket_set(unit, gport, cosq + i, kbits_sec_min, 9026 kbits_sec_max, kbits_sec_min, 9027 kbits_sec_max, flags)); 9028 } 9029 9030 return BCM_E_NONE; 9031 } 9032 9033 /* 9034 * Function: 9035 * bcm_kt2_cosq_gport_bandwidth_get 9036 * Purpose: 9037 * Get COS queue bandwidth control configuration 9038 * Parameters: 9039 * unit - (IN) unit number 9040 * gport - (IN) GPORT identifier 9041 * cosq - (IN) COS queue to get, -1 for any COS queue 9042 * kbits_sec_min - (OUT) minimum bandwidth, kbits/sec 9043 * kbits_sec_max - (OUT) maximum bandwidth, kbits/sec 9044 * burst_min - (OUT) minimum burst rate 9045 * burst_max - (OUT) maximum burst rate 9046 * flags - (OUT) BCM_COSQ_BW_* 9047 * Returns: 9048 * BCM_E_XXX 9049 */ 9050 int 9051 bcm_kt2_cosq_gport_bandwidth_get(int unit, bcm_gport_t gport, 9052 bcm_cos_queue_t cosq, uint32 *kbits_sec_min, 9053 uint32 *kbits_sec_max, uint32 *burst_min, 9054 uint32 *burst_max, uint32 *flags) 9055 { 9056 BCM_IF_ERROR_RETURN 9057 (_bcm_kt2_cosq_bucket_get(unit, gport, 9058 cosq == -1 ? 0 : cosq, 9059 kbits_sec_min, kbits_sec_max, 9060 burst_min, burst_max, *flags)); 9061 9062 *flags = 0; 9063 9064 return BCM_E_NONE; 9065 } 9066 9067 /* 9068 * Function: 9069 * bcm_kt2_cosq_gport_bandwidth_burst_set 9070 * Purpose: 9071 * Configure COS queue bandwidth burst setting 9072 * Parameters: 9073 * unit - (IN) unit number 9074 * gport - (IN) GPORT identifier 9075 * cosq - (IN) COS queue to configure, -1 for all COS queues 9076 * kbits_burst - (IN) maximum burst, kbits 9077 * Returns: 9078 * BCM_E_XXX 9079 */ 9080 int 9081 bcm_kt2_cosq_gport_bandwidth_burst_set(int unit, bcm_gport_t gport, 9082 bcm_cos_queue_t cosq, 9083 uint32 kbits_burst_min, 9084 uint32 kbits_burst_max) 9085 { 9086 int numq, i; 9087 uint32 kbits_sec_min, kbits_sec_max; 9088 uint32 kbits_sec_burst_min, kbits_sec_burst_max; 9089 _bcm_kt2_cosq_node_t *node = NULL; 9090 _bcm_kt2_cosq_node_t *cur_node = NULL; 9091 bcm_gport_t cur_gport; 9092 uint8 child_node_found = 0; 9093 9094 if (cosq == -1) { 9095 BCM_IF_ERROR_RETURN 9096 (_bcm_kt2_cosq_index_resolve(unit, gport, cosq, 9097 _BCM_KT2_COSQ_INDEX_STYLE_BUCKET, 9098 NULL, NULL, &numq)); 9099 cosq = 0; 9100 } else { 9101 numq = 1; 9102 } 9103 9104 if ((soc_property_get(unit, 9105 spn_COSQ_CONTROL_BURST_NODE_SELECT, 0)) && 9106 (BCM_GPORT_IS_SET(gport)) && 9107 (BCM_GPORT_IS_SCHEDULER(gport))) { 9108 BCM_IF_ERROR_RETURN 9109 (_bcm_kt2_cosq_node_get(unit, gport, NULL, NULL, NULL, &node)); 9110 if (node) { 9111 /* For Port gport, L0, L1 scheduler nodes */ 9112 if (cosq >= node->numq) { 9113 return BCM_E_PARAM; 9114 } 9115 for (cur_node = node->child; cur_node; cur_node = cur_node->sibling) { 9116 /* get the child node at cosq */ 9117 if ((cosq != -1) && (cur_node->cosq_attached_to != cosq)) { 9118 continue; 9119 } 9120 child_node_found = 1; 9121 cur_gport = cur_node->gport; 9122 9123 BCM_IF_ERROR_RETURN 9124 (_bcm_kt2_cosq_bucket_get(unit, 9125 cur_gport, 9126 cur_node->cosq_attached_to, 9127 &kbits_sec_min, 9128 &kbits_sec_max, 9129 &kbits_sec_burst_min, 9130 &kbits_sec_burst_max, 9131 0)); 9132 BCM_IF_ERROR_RETURN 9133 (_bcm_kt2_cosq_bucket_set(unit, 9134 cur_gport, 9135 cur_node->cosq_attached_to, 9136 kbits_sec_min, 9137 kbits_sec_max, 9138 kbits_burst_min, 9139 kbits_burst_max, 9140 _BCM_XGS_METER_FLAG_NON_BURST_CORRECTION)); 9141 if (cosq != -1) { 9142 break; 9143 } 9144 } 9145 if (child_node_found == 0) { 9146 return BCM_E_NOT_FOUND; 9147 } 9148 } else { 9149 /* It should never come here */ 9150 return BCM_E_INTERNAL; 9151 } 9152 } else { 9153 for (i = 0; i < numq; i++) { 9154 BCM_IF_ERROR_RETURN 9155 (_bcm_kt2_cosq_bucket_get(unit, gport, cosq + i, &kbits_sec_min, 9156 &kbits_sec_max, &kbits_sec_burst_min, 9157 &kbits_sec_burst_max, 0)); 9158 BCM_IF_ERROR_RETURN 9159 (_bcm_kt2_cosq_bucket_set(unit, gport, cosq + i, kbits_sec_min, 9160 kbits_sec_max, kbits_burst_min, 9161 kbits_burst_max, 9162 _BCM_XGS_METER_FLAG_NON_BURST_CORRECTION)); 9163 } 9164 } 9165 return BCM_E_NONE; 9166 } 9167 9168 /* 9169 * Function: 9170 * bcm_kt2_cosq_gport_bandwidth_burst_get 9171 * Purpose: 9172 * Get COS queue bandwidth burst setting 9173 * Parameters: 9174 * unit - (IN) unit number 9175 * gport - (IN) GPORT identifier 9176 * cosq - (IN) COS queue to get, -1 for any queue 9177 * kbits_burst - (OUT) maximum burst, kbits 9178 * Returns: 9179 * BCM_E_XXX 9180 */ 9181 int 9182 bcm_kt2_cosq_gport_bandwidth_burst_get(int unit, bcm_gport_t gport, 9183 bcm_cos_queue_t cosq, 9184 uint32 *kbits_burst_min, 9185 uint32 *kbits_burst_max) 9186 { 9187 uint32 kbits_sec_min, kbits_sec_max; 9188 _bcm_kt2_cosq_node_t *node = NULL; 9189 _bcm_kt2_cosq_node_t *cur_node = NULL; 9190 bcm_gport_t cur_gport; 9191 uint8 child_node_found = 0; 9192 9193 if ((soc_property_get(unit, 9194 spn_COSQ_CONTROL_BURST_NODE_SELECT, 0)) && 9195 (BCM_GPORT_IS_SET(gport)) && 9196 (BCM_GPORT_IS_SCHEDULER(gport))) { 9197 BCM_IF_ERROR_RETURN 9198 (_bcm_kt2_cosq_node_get(unit, gport, NULL, NULL, NULL, &node)); 9199 if (node) { 9200 9201 /* For Port gport, L0, L1 scheduler nodes */ 9202 if (cosq >= node->numq) { 9203 return BCM_E_PARAM; 9204 } 9205 for (cur_node = node->child; cur_node; cur_node = cur_node->sibling) { 9206 /* get the child node at cosq */ 9207 if ((cosq != -1) && (cur_node->cosq_attached_to != cosq)) { 9208 continue; 9209 } 9210 cur_gport = cur_node->gport; 9211 child_node_found = 1; 9212 BCM_IF_ERROR_RETURN 9213 (_bcm_kt2_cosq_bucket_get(unit, 9214 cur_gport, 9215 cur_node->cosq_attached_to, 9216 &kbits_sec_min, 9217 &kbits_sec_max, 9218 kbits_burst_min, 9219 kbits_burst_max, 9220 0)); 9221 break; 9222 } 9223 if (child_node_found == 0) { 9224 return BCM_E_NOT_FOUND; 9225 } 9226 } else { 9227 /* It should never come here */ 9228 return BCM_E_INTERNAL; 9229 } 9230 } else { 9231 BCM_IF_ERROR_RETURN 9232 (_bcm_kt2_cosq_bucket_get(unit, gport, cosq == -1 ? 0 : cosq, 9233 &kbits_sec_min, &kbits_sec_max, 9234 kbits_burst_min, kbits_burst_max, 0)); 9235 } 9236 return BCM_E_NONE; 9237 } 9238 9239 /* 9240 * Function: 9241 * bcm_kt2_cosq_gport_discard_set 9242 * Purpose: 9243 * Configure gport WRED setting 9244 * Parameters: 9245 * unit - (IN) unit number 9246 * port - (IN) GPORT identifier 9247 * cosq - (IN) COS queue to configure, -1 for all COS queues 9248 * discard - (IN) discard settings 9249 * Returns: 9250 * BCM_E_XXX 9251 */ 9252 int 9253 bcm_kt2_cosq_gport_discard_set(int unit, bcm_gport_t gport, 9254 bcm_cos_queue_t cosq, 9255 bcm_cosq_gport_discard_t *discard) 9256 { 9257 int numq, i; 9258 uint32 min_thresh, max_thresh; 9259 int cell_size, cell_field_max; 9260 int local_port; 9261 9262 if (discard == NULL || 9263 discard->gain < 0 || discard->gain > 15 || 9264 discard->drop_probability < 0 || discard->drop_probability > 100) { 9265 return BCM_E_PARAM; 9266 } 9267 9268 if (cosq < -1) { 9269 return BCM_E_PARAM; 9270 } 9271 cell_size = _BCM_KT2_COSQ_CELLSIZE; 9272 cell_field_max = KT2_CELL_FIELD_MAX; 9273 9274 if (gport != -1) { 9275 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 9276 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport) || 9277 BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(gport) || 9278 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport) || 9279 BCM_GPORT_IS_SCHEDULER(gport)) { 9280 BCM_IF_ERROR_RETURN 9281 (_bcm_kt2_cosq_node_get(unit, gport, NULL, &local_port, NULL, 9282 NULL)); 9283 } else { 9284 BCM_IF_ERROR_RETURN 9285 (_bcm_kt2_cosq_localport_resolve(unit, gport, &local_port)); 9286 } 9287 if (IS_EXT_MEM_PORT(unit, local_port)) { 9288 cell_size = _BCM_KT2_COSQ_EXT_CELLSIZE; 9289 if (soc_feature(unit, soc_feature_mmu_packing)) { 9290 cell_size = _BCM_KT2_COSQ_EXT_PACKING_CELLSIZE; 9291 } 9292 cell_field_max = soc_kt2_get_max_buffer_size(unit, 1, cell_field_max); 9293 } else { 9294 cell_field_max = soc_kt2_get_max_buffer_size(unit, 0, cell_field_max); 9295 } 9296 } 9297 9298 min_thresh = discard->min_thresh; 9299 max_thresh = discard->max_thresh; 9300 if (discard->flags & BCM_COSQ_DISCARD_BYTES) { 9301 /* Convert bytes to cells */ 9302 min_thresh += (cell_size - 1); 9303 min_thresh /= cell_size; 9304 9305 max_thresh += (cell_size - 1); 9306 max_thresh /= cell_size; 9307 9308 if ((min_thresh > cell_field_max) || 9309 (max_thresh > cell_field_max)) { 9310 return BCM_E_PARAM; 9311 } 9312 } else { /* BCM_COSQ_DISCARD_PACKETS */ 9313 if ((min_thresh > KT2_CELL_FIELD_MAX) || 9314 (max_thresh > KT2_CELL_FIELD_MAX)) { 9315 return BCM_E_PARAM; 9316 } 9317 } 9318 9319 if (cosq == -1) { 9320 BCM_IF_ERROR_RETURN 9321 (_bcm_kt2_cosq_index_resolve(unit, gport, cosq, 9322 _BCM_KT2_COSQ_INDEX_STYLE_WRED, 9323 NULL, NULL, &numq)); 9324 cosq = 0; 9325 } else { 9326 numq = 1; 9327 } 9328 9329 for (i = 0; i < numq; i++) { 9330 BCM_IF_ERROR_RETURN 9331 (_bcm_kt2_cosq_wred_set(unit, gport, cosq + i, discard->flags, 9332 min_thresh, max_thresh, 9333 discard->drop_probability, discard->gain, 9334 FALSE)); 9335 } 9336 9337 return BCM_E_NONE; 9338 } 9339 9340 /* 9341 * Function: 9342 * bcm_kt2_cosq_gport_discard_get 9343 * Purpose: 9344 * Get port WRED setting 9345 * Parameters: 9346 * unit - (IN) unit number 9347 * port - (IN) GPORT identifier 9348 * cosq - (IN) COS queue to get, -1 for any queue 9349 * discard - (OUT) discard settings 9350 * Returns: 9351 * BCM_E_XXX 9352 */ 9353 int 9354 bcm_kt2_cosq_gport_discard_get(int unit, bcm_gport_t gport, 9355 bcm_cos_queue_t cosq, 9356 bcm_cosq_gport_discard_t *discard) 9357 { 9358 uint32 min_thresh, max_thresh; 9359 int cell_size, cell_field_max; 9360 int local_port; 9361 9362 9363 if (discard == NULL) { 9364 return BCM_E_PARAM; 9365 } 9366 9367 if (cosq < -1) { 9368 return BCM_E_PARAM; 9369 } 9370 cell_size = _BCM_KT2_COSQ_CELLSIZE; 9371 cell_field_max = KT2_CELL_FIELD_MAX; 9372 9373 if (gport != -1) { 9374 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 9375 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport) || 9376 BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(gport) || 9377 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport) || 9378 BCM_GPORT_IS_SCHEDULER(gport)) { 9379 BCM_IF_ERROR_RETURN 9380 (_bcm_kt2_cosq_node_get(unit, gport, NULL, &local_port, NULL, 9381 NULL)); 9382 } else { 9383 BCM_IF_ERROR_RETURN 9384 (_bcm_kt2_cosq_localport_resolve(unit, gport, &local_port)); 9385 } 9386 if (IS_EXT_MEM_PORT(unit, local_port)) { 9387 cell_size = _BCM_KT2_COSQ_EXT_CELLSIZE; 9388 if (soc_feature(unit, soc_feature_mmu_packing)) { 9389 cell_size = _BCM_KT2_COSQ_EXT_PACKING_CELLSIZE; 9390 } 9391 cell_field_max = soc_kt2_get_max_buffer_size(unit, 1, cell_field_max); 9392 } else { 9393 cell_field_max = soc_kt2_get_max_buffer_size(unit, 0, cell_field_max); 9394 } 9395 } 9396 9397 BCM_IF_ERROR_RETURN 9398 (_bcm_kt2_cosq_wred_get(unit, gport, cosq == -1 ? 0 : cosq, 9399 &discard->flags, &min_thresh, &max_thresh, 9400 &discard->drop_probability, &discard->gain)); 9401 9402 /* 9403 * During cosq init we associated same wred profile for all (internal memory and 9404 * external memory) port. So need to cap get threshold for external memory port. 9405 */ 9406 if (min_thresh > cell_field_max) { 9407 min_thresh = cell_field_max; 9408 } 9409 if (max_thresh > cell_field_max) { 9410 max_thresh = cell_field_max; 9411 } 9412 /* Convert number of cells to number of bytes */ 9413 if (discard->flags & BCM_COSQ_DISCARD_BYTES) { 9414 discard->min_thresh = min_thresh * cell_size; 9415 discard->max_thresh = max_thresh * cell_size; 9416 } else { 9417 discard->min_thresh = min_thresh; 9418 discard->max_thresh = max_thresh; 9419 } 9420 9421 return BCM_E_NONE; 9422 } 9423 9424 /* 9425 * Function: 9426 * bcm_kt2_cosq_discard_set 9427 * Purpose: 9428 * Get port WRED setting 9429 * Parameters: 9430 * unit - (IN) unit number 9431 * flags - (IN) flags 9432 * Returns: 9433 * BCM_E_XXX 9434 */ 9435 int 9436 bcm_kt2_cosq_discard_set(int unit, uint32 flags) 9437 { 9438 bcm_port_t port; 9439 bcm_cos_queue_t cosq; 9440 int numq; 9441 9442 if (flags & ~(BCM_COSQ_DISCARD_DEVICE | 9443 BCM_COSQ_DISCARD_NONTCP | 9444 BCM_COSQ_DISCARD_COLOR_ALL | 9445 BCM_COSQ_DISCARD_PACKETS | 9446 BCM_COSQ_DISCARD_CAP_AVERAGE | 9447 BCM_COSQ_DISCARD_ENABLE | 9448 BCM_COSQ_DISCARD_MARK_CONGESTION)) { 9449 return BCM_E_PARAM; 9450 } 9451 9452 flags &= ~(BCM_COSQ_DISCARD_NONTCP | BCM_COSQ_DISCARD_COLOR_ALL); 9453 9454 PBMP_PORT_ITER(unit, port) { 9455 BCM_IF_ERROR_RETURN 9456 (_bcm_kt2_cosq_index_resolve(unit, port, -1, 9457 _BCM_KT2_COSQ_INDEX_STYLE_WRED, NULL, 9458 NULL, &numq)); 9459 for (cosq = 0; cosq < numq; cosq++) { 9460 BCM_IF_ERROR_RETURN 9461 (_bcm_kt2_cosq_wred_set(unit, port, cosq, flags, 0, 0, 0, 0, 9462 FALSE)); 9463 } 9464 } 9465 9466 return BCM_E_NONE; 9467 9468 } 9469 9470 /* 9471 * Function: 9472 * bcm_kt2_cosq_discard_get 9473 * Purpose: 9474 * Get port WRED setting 9475 * Parameters: 9476 * unit - (IN) unit number 9477 * flags - (OUT) flags 9478 * Returns: 9479 * BCM_E_XXX 9480 */ 9481 int 9482 bcm_kt2_cosq_discard_get(int unit, uint32 *flags) 9483 { 9484 bcm_port_t port; 9485 9486 PBMP_PORT_ITER(unit, port) { 9487 *flags = 0; 9488 /* use setting from hardware cosq index 0 of the first port */ 9489 return _bcm_kt2_cosq_wred_get(unit, port, 0, flags, NULL, NULL, NULL, 9490 NULL); 9491 } 9492 9493 return BCM_E_NOT_FOUND; 9494 9495 } 9496 9497 /* 9498 * Function: 9499 * bcm_kt2_cosq_discard_port_set 9500 * Purpose: 9501 * Configure port WRED setting 9502 * Parameters: 9503 * unit - (IN) unit number 9504 * port - (IN) port number or GPORT identifier 9505 * cosq - (IN) COS queue number 9506 * color - (IN) 9507 * drop_start - (IN) 9508 * drop_slot - (IN) 9509 * average_time - (IN) 9510 * Returns: 9511 * BCM_E_XXX 9512 * Notes: 9513 * If port is any form of local port, cosq is the hardware queue index. 9514 */ 9515 int 9516 bcm_kt2_cosq_discard_port_set(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 9517 uint32 color, int drop_start, int drop_slope, 9518 int average_time) 9519 { 9520 return SOC_E_UNAVAIL; 9521 } 9522 9523 /* 9524 * Function: 9525 * bcm_kt2_cosq_discard_port_get 9526 * Purpose: 9527 * Get port WRED setting 9528 * Parameters: 9529 * unit - (IN) unit number 9530 * port - (IN) port number or GPORT identifier 9531 * cosq - (IN) COS queue number 9532 * color - (OUT) 9533 * drop_start - (OUT) 9534 * drop_slot - (OUT) 9535 * average_time - (OUT) 9536 * Returns: 9537 * BCM_E_XXX 9538 * Notes: 9539 * If port is any form of local port, cosq is the hardware queue index. 9540 */ 9541 int 9542 bcm_kt2_cosq_discard_port_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 9543 uint32 color, int *drop_start, int *drop_slope, 9544 int *average_time) 9545 { 9546 return SOC_E_UNAVAIL; 9547 9548 } 9549 STATIC int 9550 _bcm_kt2_cosq_current_stat_set_get(int unit, 9551 bcm_gport_t gport, 9552 bcm_cos_queue_t cosq, 9553 bcm_cosq_stat_t stat, 9554 int set, 9555 uint64 *value) 9556 { 9557 bcm_port_t local_port; 9558 uint32 entry[SOC_MAX_MEM_WORDS]; 9559 uint32 sw_val, hw_val; 9560 soc_mem_t mem = INVALIDm; 9561 soc_field_t field; 9562 _bcm_kt2_cosq_node_t *node; 9563 _bcm_kt2_mmu_info_t *mmu_info = _bcm_kt2_mmu_info[unit]; 9564 int startq, numq, cell_size = _BCM_KT2_COSQ_CELLSIZE; 9565 int rv = BCM_E_NONE; 9566 9567 9568 rv = _bcm_kt2_cosq_node_get(unit, gport, NULL, &local_port, NULL, 9569 &node); 9570 if ((rv != BCM_E_NONE) && (rv != BCM_E_PORT)) { 9571 return BCM_E_PARAM; 9572 } 9573 if (rv == BCM_E_PORT) { 9574 if ((gport <= CMIC_PORT(unit)) || (gport >= LB_PORT(unit))) { 9575 return BCM_E_PARAM; 9576 } else { 9577 local_port = gport; 9578 } 9579 } 9580 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 9581 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) || 9582 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport) || 9583 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport) || 9584 BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(gport) || 9585 BCM_GPORT_IS_SCHEDULER(gport)) { 9586 if ((node->level != _BCM_KT2_COSQ_NODE_LEVEL_L1) && 9587 (node->level != _BCM_KT2_COSQ_NODE_LEVEL_L2)) { 9588 return BCM_E_PARAM; 9589 } 9590 if (BCM_GPORT_IS_SCHEDULER(gport)) { 9591 BCM_IF_ERROR_RETURN( 9592 _bcm_kt2_cosq_child_node_at_input(node, cosq, 9593 &node)); 9594 } 9595 9596 startq = node->hw_index; 9597 } else { 9598 mmu_info = _bcm_kt2_mmu_info[unit]; 9599 numq = mmu_info->port[local_port].q_limit - 9600 mmu_info->port[local_port].q_offset; 9601 9602 if (cosq < 0 || cosq >= numq) { 9603 return BCM_E_PARAM; 9604 } 9605 startq = mmu_info->port[local_port].q_offset + cosq; 9606 } 9607 9608 if (IS_EXT_MEM_PORT(unit, local_port)) { 9609 cell_size = _BCM_KT2_COSQ_EXT_CELLSIZE; 9610 if (soc_feature(unit, soc_feature_mmu_packing)) { 9611 cell_size = _BCM_KT2_COSQ_EXT_PACKING_CELLSIZE; 9612 } 9613 } 9614 9615 switch (stat) { 9616 case bcmCosqStatEgressUCQueueBytesCurrent: 9617 mem = MMU_THDO_QCOUNT_CELLm; 9618 field = TOTAL_COUNTf; 9619 break; 9620 default: 9621 return BCM_E_PARAM; 9622 } 9623 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 9624 if (set) { 9625 COMPILER_64_TO_32_LO(sw_val, *value); 9626 hw_val = (sw_val + cell_size - 1) / cell_size; 9627 soc_mem_field32_set(unit, mem, entry, field, hw_val); 9628 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 9629 } else { 9630 hw_val = soc_mem_field32_get(unit, mem, entry, field); 9631 sw_val = hw_val * cell_size; 9632 COMPILER_64_SET(*value, 0, sw_val); 9633 } 9634 return BCM_E_NONE; 9635 } 9636 9637 int 9638 bcm_kt2_cosq_stat_set(int unit, bcm_gport_t port, bcm_cos_queue_t cosq, 9639 bcm_cosq_stat_t stat, uint64 value) 9640 { 9641 bcm_port_t local_port; 9642 int startq, numq, i; 9643 soc_counter_non_dma_id_t dma_id; 9644 _bcm_kt2_cosq_node_t *node = NULL; 9645 _bcm_kt2_cosq_node_t *child_node = NULL; 9646 int first_child = 1; 9647 uint64 value64; 9648 uint64 zero; 9649 #ifdef BCM_SABER2_SUPPORT 9650 uint32 drop_type, total_drop_mask, wred_drop_mask; 9651 uint32 rval; 9652 #endif 9653 9654 if (stat == bcmCosqStatEgressUCQueueBytesCurrent) { 9655 return _bcm_kt2_cosq_current_stat_set_get(unit, port, 9656 cosq, stat, 9657 1, &value); 9658 } 9659 BCM_IF_ERROR_RETURN 9660 (_bcm_kt2_cosq_index_resolve 9661 (unit, port, cosq, _BCM_KT2_COSQ_INDEX_STYLE_UCAST_QUEUE, 9662 &local_port, &startq, &numq)); 9663 if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) || 9664 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port) || 9665 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port) || 9666 BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(port)) { 9667 /* pass port as queue number */ 9668 local_port = startq; 9669 startq = 0; 9670 } 9671 9672 #ifdef BCM_SABER2_SUPPORT 9673 if(SOC_IS_SABER2(unit)) { 9674 #ifdef BCM_METROLITE_SUPPORT 9675 if(SOC_IS_METROLITE(unit)) { 9676 total_drop_mask = BCM_ML_COSQ_TOTAL_DROP_MASK; 9677 wred_drop_mask = BCM_ML_COSQ_WRED_DROP_MASK; 9678 } else 9679 #endif 9680 { 9681 total_drop_mask = BCM_SB2_COSQ_TOTAL_DROP_MASK; 9682 wred_drop_mask = BCM_SB2_COSQ_WRED_DROP_MASK; 9683 } 9684 SOC_IF_ERROR_RETURN(READ_THDO_DROP_CTR_CONFIGr(unit, &rval)); 9685 drop_type = soc_reg_field_get(unit, THDO_DROP_CTR_CONFIGr, rval, OP_DROP_MASKf); 9686 9687 if (drop_type == total_drop_mask) { 9688 if (!((stat == bcmCosqStatDroppedPackets)|| 9689 (stat == bcmCosqStatDroppedBytes)|| 9690 (stat == bcmCosqStatRedCongestionDroppedPackets)|| 9691 (stat == bcmCosqStatRedCongestionDroppedBytes)|| 9692 (stat == bcmCosqStatYellowCongestionDroppedPackets)|| 9693 (stat == bcmCosqStatYellowCongestionDroppedBytes)|| 9694 (stat == bcmCosqStatOutPackets)||(stat == bcmCosqStatOutBytes))){ 9695 return BCM_E_PARAM; 9696 } 9697 9698 } 9699 else if (drop_type == wred_drop_mask) { 9700 if (!((stat == bcmCosqStatDiscardDroppedPackets)|| 9701 (stat == bcmCosqStatDiscardDroppedBytes)|| 9702 (stat == bcmCosqStatRedDiscardDroppedPackets)|| 9703 (stat == bcmCosqStatRedDiscardDroppedBytes)|| 9704 (stat == bcmCosqStatYellowDiscardDroppedPackets)|| 9705 (stat == bcmCosqStatYellowDiscardDroppedBytes)|| 9706 (stat == bcmCosqStatGreenDiscardDroppedBytes)|| 9707 (stat == bcmCosqStatGreenDiscardDroppedPackets)|| 9708 (stat == bcmCosqStatOutPackets)||(stat == bcmCosqStatOutBytes))){ 9709 return BCM_E_PARAM; 9710 } 9711 } 9712 } 9713 #endif 9714 9715 switch (stat) { 9716 case bcmCosqStatDroppedPackets: 9717 case bcmCosqStatDiscardDroppedPackets: 9718 dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_PKT; 9719 break; 9720 9721 case bcmCosqStatDroppedBytes: 9722 case bcmCosqStatDiscardDroppedBytes: 9723 dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE; 9724 break; 9725 9726 9727 case bcmCosqStatRedCongestionDroppedPackets: 9728 case bcmCosqStatRedDiscardDroppedPackets: 9729 dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_RED; 9730 break; 9731 9732 case bcmCosqStatRedCongestionDroppedBytes: 9733 case bcmCosqStatRedDiscardDroppedBytes: 9734 dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE_RED; 9735 break; 9736 9737 case bcmCosqStatYellowCongestionDroppedPackets: 9738 case bcmCosqStatYellowDiscardDroppedPackets : 9739 dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_YELLOW; 9740 break; 9741 9742 case bcmCosqStatYellowCongestionDroppedBytes: 9743 case bcmCosqStatYellowDiscardDroppedBytes: 9744 dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE_YELLOW; 9745 break; 9746 9747 case bcmCosqStatGreenDiscardDroppedPackets: 9748 dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_GREEN; 9749 break; 9750 9751 case bcmCosqStatGreenDiscardDroppedBytes: 9752 dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE_GREEN; 9753 break; 9754 9755 case bcmCosqStatOutPackets: 9756 dma_id = SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT; 9757 break; 9758 case bcmCosqStatOutBytes: 9759 dma_id = SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE; 9760 break; 9761 default: 9762 return BCM_E_PARAM; 9763 } 9764 9765 if (!BCM_GPORT_IS_SCHEDULER(port)) { 9766 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 9767 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port) || 9768 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) || 9769 BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(port) || 9770 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port) || 9771 (cosq != BCM_COS_INVALID)) { 9772 BCM_IF_ERROR_RETURN 9773 (soc_counter_set(unit, local_port, dma_id, startq, value)); 9774 } else { 9775 numq = soc_property_get(unit, spn_BCM_NUM_COS, BCM_COS_DEFAULT); 9776 if (numq < 1) { 9777 numq = 1; 9778 } else if (numq > 8) { 9779 numq = 8; 9780 } 9781 for (i = 0; i < numq; i++) { 9782 COMPILER_64_ZERO(zero); 9783 BCM_IF_ERROR_RETURN 9784 (soc_counter_set(unit, local_port, dma_id, i, i == 0 ? value : zero )); 9785 } 9786 } 9787 } else { 9788 9789 BCM_IF_ERROR_RETURN 9790 (_bcm_kt2_cosq_node_get(unit, port, 0, 9791 &local_port, NULL, &node)); 9792 if (cosq == -1) { 9793 for (i = 0; i < node->numq; i++) { 9794 if ((_bcm_kt2_cosq_child_node_at_input(node, i, &child_node)) 9795 == BCM_E_NOT_FOUND) { 9796 continue; 9797 } 9798 9799 port = child_node->gport; 9800 9801 BCM_IF_ERROR_RETURN 9802 (_bcm_kt2_cosq_index_resolve 9803 (unit, port, 0, _BCM_KT2_COSQ_INDEX_STYLE_UCAST_QUEUE, 9804 &local_port, &startq, &numq)); 9805 9806 if (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port) || 9807 BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(port) || 9808 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port)) { 9809 /* pass port as queue number */ 9810 local_port = startq; 9811 startq = 0; 9812 } 9813 if(first_child) { 9814 /* 9815 *According to api guide only first child should be set with given value 9816 *all other are set to 0 9817 */ 9818 BCM_IF_ERROR_RETURN 9819 (soc_counter_set(unit, local_port, dma_id, 9820 startq , value)); 9821 first_child = 0; 9822 } 9823 else { 9824 COMPILER_64_ZERO(value64); 9825 BCM_IF_ERROR_RETURN 9826 (soc_counter_set(unit, local_port, dma_id, 9827 startq , value64)); 9828 } 9829 } 9830 } 9831 else { 9832 9833 if ((_bcm_kt2_cosq_child_node_at_input(node, cosq, &child_node)) 9834 == BCM_E_NOT_FOUND) { 9835 return BCM_E_NOT_FOUND; 9836 } 9837 9838 port = child_node->gport; 9839 9840 BCM_IF_ERROR_RETURN 9841 (_bcm_kt2_cosq_index_resolve 9842 (unit, port, 0, _BCM_KT2_COSQ_INDEX_STYLE_UCAST_QUEUE, 9843 &local_port, &startq, &numq)); 9844 9845 if (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port) || 9846 BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(port) || 9847 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port)) { 9848 /* pass port as queue number */ 9849 local_port = startq; 9850 startq = 0; 9851 } 9852 BCM_IF_ERROR_RETURN 9853 (soc_counter_set(unit, local_port, dma_id, 9854 startq , value)); 9855 } 9856 } 9857 9858 9859 return BCM_E_NONE; 9860 } 9861 9862 int 9863 _bcm_kt2_cosq_pfc_class_resolve(bcm_switch_control_t sctype, int *type, 9864 int *class) 9865 { 9866 switch (sctype) { 9867 case bcmSwitchPFCClass7Queue: 9868 case bcmSwitchPFCClass6Queue: 9869 case bcmSwitchPFCClass5Queue: 9870 case bcmSwitchPFCClass4Queue: 9871 case bcmSwitchPFCClass3Queue: 9872 case bcmSwitchPFCClass2Queue: 9873 case bcmSwitchPFCClass1Queue: 9874 case bcmSwitchPFCClass0Queue: 9875 *type = _BCM_KT2_NODE_UCAST; 9876 break; 9877 case bcmSwitchPFCClass7McastQueue: 9878 case bcmSwitchPFCClass6McastQueue: 9879 case bcmSwitchPFCClass5McastQueue: 9880 case bcmSwitchPFCClass4McastQueue: 9881 case bcmSwitchPFCClass3McastQueue: 9882 case bcmSwitchPFCClass2McastQueue: 9883 case bcmSwitchPFCClass1McastQueue: 9884 case bcmSwitchPFCClass0McastQueue: 9885 *type = _BCM_KT2_NODE_MCAST; 9886 break; 9887 /* case bcmSwitchPFCClass7DestmodQueue: 9888 case bcmSwitchPFCClass6DestmodQueue: 9889 case bcmSwitchPFCClass5DestmodQueue: 9890 case bcmSwitchPFCClass4DestmodQueue: 9891 case bcmSwitchPFCClass3DestmodQueue: 9892 case bcmSwitchPFCClass2DestmodQueue: 9893 case bcmSwitchPFCClass1DestmodQueue: 9894 case bcmSwitchPFCClass0DestmodQueue: 9895 *type = _BCM_KT2_COSQ_TYPE_EXT_UCAST; 9896 break; 9897 */ 9898 default: 9899 return BCM_E_PARAM; 9900 } 9901 9902 switch (sctype) { 9903 case bcmSwitchPFCClass7Queue: 9904 case bcmSwitchPFCClass7McastQueue: 9905 case bcmSwitchPFCClass7DestmodQueue: 9906 *class = 7; 9907 break; 9908 case bcmSwitchPFCClass6Queue: 9909 case bcmSwitchPFCClass6McastQueue: 9910 case bcmSwitchPFCClass6DestmodQueue: 9911 *class = 6; 9912 break; 9913 case bcmSwitchPFCClass5Queue: 9914 case bcmSwitchPFCClass5McastQueue: 9915 case bcmSwitchPFCClass5DestmodQueue: 9916 *class = 5; 9917 break; 9918 case bcmSwitchPFCClass4Queue: 9919 case bcmSwitchPFCClass4McastQueue: 9920 case bcmSwitchPFCClass4DestmodQueue: 9921 *class = 4; 9922 break; 9923 case bcmSwitchPFCClass3Queue: 9924 case bcmSwitchPFCClass3McastQueue: 9925 case bcmSwitchPFCClass3DestmodQueue: 9926 *class = 3; 9927 break; 9928 case bcmSwitchPFCClass2Queue: 9929 case bcmSwitchPFCClass2McastQueue: 9930 case bcmSwitchPFCClass2DestmodQueue: 9931 *class = 2; 9932 break; 9933 case bcmSwitchPFCClass1Queue: 9934 case bcmSwitchPFCClass1McastQueue: 9935 case bcmSwitchPFCClass1DestmodQueue: 9936 *class = 1; 9937 break; 9938 case bcmSwitchPFCClass0Queue: 9939 case bcmSwitchPFCClass0McastQueue: 9940 case bcmSwitchPFCClass0DestmodQueue: 9941 *class = 0; 9942 break; 9943 /* 9944 * COVERITY 9945 * 9946 * This default is unreachable but needed for some compiler. 9947 */ 9948 /* coverity[dead_error_begin] */ 9949 default: 9950 return BCM_E_INTERNAL; 9951 } 9952 return BCM_E_NONE; 9953 } 9954 #ifdef BCM_SABER2_SUPPORT 9955 /* 9956 * Function: 9957 * _bcm_kt2_port_pfc_supported 9958 * Purpose: 9959 * To check if given port support 8 PGs or not. 9960 * Parameters: 9961 * unit - (IN) unit number 9962 * port - (IN) port number 9963 * Returns: 9964 * 1 if port support 8 PGs else 0 9965 */ 9966 STATIC int 9967 _bcm_kt2_port_pfc_supported(int unit, bcm_port_t local_port) 9968 { 9969 9970 #ifdef BCM_METROLITE_SUPPORT 9971 if(SOC_IS_METROLITE(unit) && (local_port < ML_MAX_LOGICAL_PORTS)) { 9972 return ml_pfc_support[local_port].supported ; 9973 } else 9974 #endif 9975 if(SOC_IS_SABER2(unit) && (local_port < SB2_MAX_LOGICAL_PORTS)) { 9976 return sb2_pfc_support[local_port].supported ; 9977 } 9978 return BCM_E_NONE; 9979 } 9980 STATIC int 9981 bcm_kt2_pg_profile_refcount_init(int unit) 9982 { 9983 uint64 rval64; 9984 int i; 9985 uint32 low, high, temp; 9986 9987 pg_profile_refcount[unit][0] = 0; 9988 pg_profile_refcount[unit][1] = 0; 9989 pg_profile_refcount[unit][2] = 0; 9990 pg_profile_refcount[unit][3] = 0; 9991 if(SOC_IS_SABER2(unit)) { 9992 SOC_IF_ERROR_RETURN( 9993 READ_MMU_ENQ_IP_PRI_TO_PG_PROFILE_0r(unit, &rval64)); 9994 low = COMPILER_64_LO(rval64); 9995 high = COMPILER_64_HI(rval64); 9996 for(i = 0; i < 40; i = i + 2) { 9997 if (i < 32) { 9998 temp = 0x3 & (low >> i); 9999 } else { 10000 temp = 0x3 & (high >> (i -32)); 10001 } 10002 pg_profile_refcount[unit][temp] = pg_profile_refcount[unit][temp] + 1; 10003 } 10004 } 10005 return BCM_E_NONE; 10006 } 10007 #endif 10008 10009 /* 10010 * Function: 10011 * _bcm_kt2_fc_status_map_gport 10012 * Purpose: 10013 * Set mapping in FC_MAP_TBL for gport, and update cos_bmp with gport cosq. 10014 * Parameters: 10015 * unit - (IN) unit number 10016 * port - (IN) port number 10017 * gport - (IN) gport to be mapped 10018 * fct - (IN) FC type 10019 * cos_map - (OUT) hw_cosq of gport 10020 * Returns: 10021 * BCM_E_XXX 10022 */ 10023 STATIC int 10024 _bcm_kt2_fc_status_map_gport(int unit, int port, 10025 bcm_gport_t gport, _bcm_kt2_fc_type_t fct, 10026 uint32 *cos_bmp) 10027 { 10028 int hw_index, hw_index1; 10029 int base_index = 0; 10030 int hw_cosq, hw_cosq1; 10031 int id, lvl; 10032 bcm_port_t local_port, resolved_port; 10033 _bcm_kt2_cosq_node_t *node; 10034 _bcm_kt2_cosq_port_info_t *port_info; 10035 _bcm_kt2_mmu_info_t *mmu_info; 10036 int supported = 0 ; 10037 10038 10039 BCM_IF_ERROR_RETURN 10040 (_bcm_kt2_cosq_localport_resolve(unit, port, &local_port)); 10041 #ifdef BCM_METROLITE_SUPPORT 10042 if(SOC_IS_METROLITE(unit)) { 10043 supported = ml_pfc_support[local_port].supported ; 10044 } else 10045 #endif 10046 #ifdef BCM_SABER2_SUPPORT 10047 if(SOC_IS_SABER2(unit)) { 10048 supported = sb2_pfc_support[local_port].supported ; 10049 } else 10050 #endif 10051 { 10052 supported = kt2_pfc_support[local_port].supported ; 10053 } 10054 if (!supported) { 10055 return BCM_E_PARAM; 10056 } 10057 mmu_info = _bcm_kt2_mmu_info[unit]; 10058 port_info = &mmu_info->port[local_port]; 10059 10060 hw_index = hw_index1 = -1; 10061 hw_cosq = hw_cosq1 = -1; 10062 if (BCM_GPORT_IS_SET(gport)) { 10063 BCM_IF_ERROR_RETURN(_bcm_kt2_cosq_node_get(unit, gport, 10064 0, &resolved_port, &id, &node)); 10065 /* hardware supports pfc at l0 and l1 level but the index needs to be 10066 * assigned in multiple of 8 for pfc to work.Since we are not doing it 10067 * returning E_PARAM for scheduler node as of now can be corrected if 10068 * index allocation is changed .Rest of the code programmed to handle 10069 * schedulers 10070 */ 10071 if (!(BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) || 10072 BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)|| 10073 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport) 10074 )) { 10075 return BCM_E_PARAM; 10076 } 10077 hw_index = node->hw_index; 10078 if (!IS_HG_PORT(unit,local_port)) { 10079 hw_cosq = node->hw_index % NUM_COS(unit); 10080 } 10081 else { 10082 hw_cosq = node->hw_index - port_info->q_offset ; 10083 } 10084 10085 lvl = node->level; 10086 } else { 10087 hw_cosq = gport; 10088 node = &mmu_info->queue_node[port_info->q_offset + hw_cosq]; 10089 if ((node->cosq_attached_to == -1)) { 10090 return BCM_E_PARAM; 10091 } 10092 hw_index = node->hw_index; 10093 if (soc_feature(unit, soc_feature_mmu_packing)) { 10094 node = &mmu_info->queue_node[port_info->mcq_offset + hw_cosq]; 10095 if (!(node->cosq_attached_to == -1)) { 10096 hw_index1 = node->hw_index; 10097 hw_cosq1 = hw_cosq ; 10098 } 10099 } 10100 lvl = _BCM_KT2_COSQ_NODE_LEVEL_L2; 10101 } 10102 if ((hw_cosq < 0) || (hw_cosq >= _BCM_KT2_NUM_INTERNAL_PRI)) { 10103 return BCM_E_PARAM; 10104 } 10105 #ifdef BCM_METROLITE_SUPPORT 10106 if(SOC_IS_METROLITE(unit)) { 10107 base_index = ml_pfc_support[local_port].index1 + hw_cosq / 8 ; 10108 } else 10109 #endif 10110 #ifdef BCM_SABER2_SUPPORT 10111 if(SOC_IS_SABER2(unit)) { 10112 base_index = sb2_pfc_support[local_port].index1 + hw_cosq / 8 ; 10113 } else 10114 #endif 10115 { 10116 base_index = kt2_pfc_support[local_port].index1 + hw_cosq / 8 ; 10117 } 10118 BCM_IF_ERROR_RETURN( 10119 _bcm_kt2_cosq_map_fc_status_to_node(unit, fct, 10120 hw_index, lvl - 2, base_index )); 10121 if (cos_bmp != NULL) { 10122 *cos_bmp |= 1 << hw_cosq; 10123 } 10124 if (hw_cosq1 >= 0) { 10125 BCM_IF_ERROR_RETURN( 10126 _bcm_kt2_cosq_map_fc_status_to_node(unit, fct, 10127 hw_index1, lvl - 2, base_index)); 10128 if (cos_bmp != NULL) { 10129 *cos_bmp |= 1 << hw_cosq1; 10130 } 10131 } 10132 10133 return BCM_E_NONE; 10134 } 10135 10136 /* 10137 * Function: 10138 * _bcm_kt2_port_pfc_profile_set 10139 * Purpose: 10140 * Set PFC mapping profile for port. Updates PRIO2COS_PROFILE & PORT_PFC_CFG. 10141 * Parameters: 10142 * unit - (IN) unit number 10143 * port - (IN) port number 10144 * op - (IN) operation type 10145 * entry_cnt - (IN) count of bmp 10146 * pfc_class - (IN) class list 10147 * cos_bmp - (IN) bmp list 10148 * Returns: 10149 * BCM_E_XXX 10150 */ 10151 STATIC int 10152 _bcm_kt2_port_pfc_profile_set(int unit, int port, _bcm_cosq_op_t op, 10153 int entry_cnt, int *pfc_class, uint32 *cos_bmp) 10154 { 10155 soc_reg_t reg; 10156 bcm_port_t local_port; 10157 int rv, entry, cur_class; 10158 int mmu_port; 10159 uint32 profile_index, old_profile_index; 10160 uint32 fval, tmp32, cur_bmp; 10161 uint64 rval64[16], tmp, *rval64s[1], rval, index_map; 10162 #ifdef BCM_METROLITE_SUPPORT 10163 uint32 rval32, index_map32; 10164 #endif 10165 if (pfc_class == NULL) { 10166 return BCM_E_PARAM; 10167 } 10168 if (cos_bmp == NULL) { 10169 return BCM_E_PARAM; 10170 } 10171 if ((entry_cnt < 0 ) ) { 10172 return BCM_E_PARAM; 10173 } 10174 10175 BCM_IF_ERROR_RETURN( 10176 _bcm_kt2_cosq_localport_resolve(unit, port, &local_port)); 10177 #ifdef BCM_METROLITE_SUPPORT 10178 if(SOC_IS_METROLITE(unit)) { 10179 mmu_port = ml_pfc_support[local_port].mmu_port; 10180 } else 10181 #endif 10182 #ifdef BCM_SABER2_SUPPORT 10183 if(SOC_IS_SABER2(unit)) { 10184 mmu_port = sb2_pfc_support[local_port].mmu_port; 10185 } else 10186 #endif 10187 { 10188 mmu_port = kt2_pfc_support[local_port].mmu_port; 10189 } 10190 if (mmu_port == -1) { 10191 return BCM_E_PARAM; 10192 } 10193 reg = PORT_PFC_CFG0r; 10194 rval64s[0] = rval64; 10195 #ifdef BCM_METROLITE_SUPPORT 10196 if(SOC_IS_METROLITE(unit)) { 10197 BCM_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval32)); 10198 index_map32 = soc_reg_field_get(unit, reg, rval32, PROFILE_INDEXf); 10199 index_map32 = index_map32 >> (mmu_port * 2); 10200 old_profile_index = (index_map32 & 3) * 16; 10201 } else 10202 #endif 10203 { 10204 BCM_IF_ERROR_RETURN(soc_reg64_get(unit, reg, 0, 0, &rval)); 10205 10206 index_map = soc_reg64_field_get(unit, reg, rval, PROFILE_INDEXf); 10207 COMPILER_64_SHR(index_map, ((mmu_port % 32) * 2)); 10208 COMPILER_64_TO_32_LO(tmp32, index_map); 10209 old_profile_index = (tmp32 & 3)*16; 10210 } 10211 BCM_IF_ERROR_RETURN 10212 (soc_profile_reg_get(unit, _bcm_kt2_llfc_profile[unit], 10213 old_profile_index, 16, rval64s)); 10214 10215 for (entry = 0; entry < entry_cnt; entry++) { 10216 cur_class = pfc_class[entry]; 10217 cur_bmp = cos_bmp[entry]; 10218 if (op == _BCM_COSQ_OP_SET) { 10219 soc_reg64_field32_set(unit, PRIO2COS_PROFILEr, &rval64[cur_class], 10220 COS_BMPf, cur_bmp); 10221 } else { 10222 if (cur_bmp != 0) { 10223 fval = soc_reg64_field32_get(unit, PRIO2COS_PROFILEr, 10224 rval64[cur_class], COS_BMPf); 10225 if (op == _BCM_COSQ_OP_ADD) { 10226 fval |= cur_bmp; 10227 } else { /* _BCM_COSQ_OP_DELETE */ 10228 fval &= ~cur_bmp; 10229 } 10230 soc_reg64_field32_set(unit, PRIO2COS_PROFILEr, 10231 &rval64[cur_class], COS_BMPf, fval); 10232 } 10233 } 10234 } 10235 10236 BCM_IF_ERROR_RETURN 10237 (soc_profile_reg_delete(unit, _bcm_kt2_llfc_profile[unit], 10238 old_profile_index)); 10239 10240 rv = soc_profile_reg_add(unit, _bcm_kt2_llfc_profile[unit], rval64s, 10241 16, &profile_index); 10242 if (SOC_FAILURE(rv)) { 10243 BCM_IF_ERROR_RETURN 10244 (soc_profile_reg_reference(unit, _bcm_kt2_llfc_profile[unit], 10245 old_profile_index, 16)); 10246 return rv; 10247 } 10248 10249 #ifdef BCM_METROLITE_SUPPORT 10250 if(SOC_IS_METROLITE(unit)) { 10251 index_map32 = soc_reg_field_get(unit, reg, rval32, PROFILE_INDEXf); 10252 tmp32 = 3 << (mmu_port * 2); 10253 tmp32 = ~tmp32; 10254 index_map32 = index_map32 & tmp32; 10255 tmp32 = (profile_index / 16) << (mmu_port * 2); 10256 index_map32 = index_map32 | tmp32; 10257 soc_reg_field_set(unit, reg, &rval32, PROFILE_INDEXf, 10258 index_map32); 10259 BCM_IF_ERROR_RETURN(soc_reg32_set(unit, reg, 0, 0, rval32)); 10260 } else 10261 #endif 10262 { 10263 index_map = soc_reg64_field_get(unit, reg, rval, PROFILE_INDEXf); 10264 10265 COMPILER_64_SET(tmp, 0, 3); 10266 COMPILER_64_SHL(tmp, (mmu_port % 32) * 2); 10267 COMPILER_64_NOT(tmp); 10268 COMPILER_64_AND(index_map, tmp); 10269 COMPILER_64_SET(tmp, 0, profile_index/16); 10270 COMPILER_64_SHL(tmp, (mmu_port % 32) * 2); 10271 COMPILER_64_OR(index_map, tmp); 10272 10273 soc_reg64_field_set(unit, reg, &rval, PROFILE_INDEXf, 10274 index_map); 10275 10276 BCM_IF_ERROR_RETURN(soc_reg64_set(unit, reg, 0, 0, rval)); 10277 } 10278 return BCM_E_NONE; 10279 } 10280 10281 int 10282 bcm_kt2_cosq_port_pfc_op(int unit, bcm_port_t port, 10283 bcm_switch_control_t sctype, _bcm_cosq_op_t op, 10284 bcm_gport_t *gport, int gport_count) 10285 { 10286 int type, class = -1, index; 10287 uint32 cos_bmp; 10288 _bcm_kt2_fc_type_t fct; 10289 10290 if (gport_count < 0) { 10291 return BCM_E_PARAM; 10292 } 10293 if (!SOC_IS_SABER2(unit) && !IS_XE_PORT(unit,port)) { 10294 return BCM_E_PARAM; 10295 } 10296 BCM_IF_ERROR_RETURN(_bcm_kt2_cosq_pfc_class_resolve(sctype, &type, &class)); 10297 10298 cos_bmp = 0; 10299 fct = (op == _BCM_COSQ_OP_CLEAR)? 0 : _BCM_KT2_COSQ_FC_PFC; 10300 for (index = 0; index < gport_count; index++) { 10301 BCM_IF_ERROR_RETURN( 10302 _bcm_kt2_fc_status_map_gport(unit, port, gport[index], 10303 fct, &cos_bmp)); 10304 } 10305 10306 if (op == _BCM_COSQ_OP_CLEAR) { 10307 cos_bmp = (1 << _BCM_KT2_NUM_INTERNAL_PRI) - 1; 10308 } 10309 10310 BCM_IF_ERROR_RETURN(_bcm_kt2_port_pfc_profile_set(unit, port, op, 10311 1, &class, &cos_bmp)); 10312 10313 return BCM_E_NONE; 10314 } 10315 10316 int 10317 bcm_kt2_cosq_port_pfc_get(int unit, bcm_port_t port, 10318 bcm_switch_control_t sctype, 10319 bcm_gport_t *gport, int gport_count, 10320 int *actual_gport_count) 10321 { 10322 _bcm_kt2_cosq_node_t *node; 10323 bcm_port_t local_port; 10324 int type = -1, class = -1, hw_cosq, count = 0; 10325 uint32 profile_index; 10326 uint64 rval64[16], *rval64s[1], rval, index_map; 10327 uint32 tmp32, bmp; 10328 _bcm_kt2_mmu_info_t *mmu_info; 10329 int mmu_port; 10330 soc_reg_t reg; 10331 int node_port = 0 ; 10332 _bcm_kt2_cosq_port_info_t *port_info; 10333 static const soc_field_t self[] = { 10334 SEL0f, SEL1f, 10335 }; 10336 int j, hw_index, eindex; 10337 soc_mem_t mem; 10338 uint32 map_entry[SOC_MAX_MEM_WORDS]; 10339 #ifdef BCM_METROLITE_SUPPORT 10340 uint32 rval32, index_map32; 10341 #endif 10342 if (IS_CPU_PORT(unit, port)) { 10343 return BCM_E_PORT; 10344 } 10345 10346 if ((gport == NULL) && (gport_count > 0)) { 10347 return BCM_E_PARAM; 10348 } 10349 10350 if (actual_gport_count == NULL) { 10351 return BCM_E_PARAM; 10352 } 10353 10354 BCM_IF_ERROR_RETURN 10355 (_bcm_kt2_cosq_localport_resolve(unit, port, &local_port)); 10356 10357 BCM_IF_ERROR_RETURN(_bcm_kt2_cosq_pfc_class_resolve(sctype, &type, &class)); 10358 10359 mmu_info = _bcm_kt2_mmu_info[unit]; 10360 #ifdef BCM_METROLITE_SUPPORT 10361 if(SOC_IS_METROLITE(unit)) { 10362 mmu_port = ml_pfc_support[local_port].mmu_port; 10363 } else 10364 #endif 10365 #ifdef BCM_SABER2_SUPPORT 10366 if(SOC_IS_SABER2(unit)) { 10367 mmu_port = sb2_pfc_support[local_port].mmu_port; 10368 } else 10369 #endif 10370 { 10371 mmu_port = kt2_pfc_support[local_port].mmu_port; 10372 } 10373 if (mmu_port == -1) { 10374 return BCM_E_PARAM; 10375 } 10376 port_info = &mmu_info->port[local_port]; 10377 10378 rval64s[0] = rval64; 10379 reg = PORT_PFC_CFG0r; 10380 #ifdef BCM_METROLITE_SUPPORT 10381 if(SOC_IS_METROLITE(unit)) { 10382 BCM_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval32)); 10383 index_map32 = soc_reg_field_get(unit, reg, rval32, PROFILE_INDEXf); 10384 index_map32 = index_map32 >> (mmu_port * 2); 10385 profile_index = (index_map32 & 3) * 16; 10386 } else 10387 #endif 10388 { 10389 BCM_IF_ERROR_RETURN(soc_reg64_get(unit, reg, REG_PORT_ANY, 0, &rval)); 10390 10391 index_map = soc_reg64_field_get(unit, reg, rval, PROFILE_INDEXf); 10392 COMPILER_64_SHR(index_map, ((mmu_port % 32) * 2)); 10393 COMPILER_64_TO_32_LO(tmp32, index_map); 10394 profile_index = (tmp32 & 3)*16; 10395 } 10396 BCM_IF_ERROR_RETURN 10397 (soc_profile_reg_get(unit, _bcm_kt2_llfc_profile[unit], 10398 profile_index, 16, rval64s)); 10399 10400 bmp = soc_reg64_field32_get(unit, PRIO2COS_PROFILEr, rval64[class], 10401 COS_BMPf); 10402 10403 for (hw_cosq = 0; hw_cosq < 8; hw_cosq++) { 10404 if (!(bmp & (1 << hw_cosq))) { 10405 continue; 10406 } 10407 for (j = num_pp_ports[unit] ; 10408 j < num_total_schedulers[unit]; j++) { 10409 node = &mmu_info->sched_node[j]; 10410 if (node->cosq_attached_to == -1) { 10411 continue ; 10412 } 10413 BCM_IF_ERROR_RETURN 10414 (_bcm_kt2_cosq_node_get(unit, node->gport, NULL 10415 ,&node_port, NULL, NULL)); 10416 if ( (node_port != local_port) || 10417 ((node->hw_index % NUM_COS(unit)) != hw_cosq)) { 10418 continue; 10419 } 10420 10421 hw_index = (node->hw_index / 16); 10422 eindex = (node->hw_index % 16)/8; 10423 if (node->level == _BCM_KT2_COSQ_NODE_LEVEL_L0) { 10424 mem = MMU_INTFI_FC_MAP_TBL0m ; 10425 } else if (node->level == _BCM_KT2_COSQ_NODE_LEVEL_L1) { 10426 mem = MMU_INTFI_FC_MAP_TBL1m; 10427 } else { 10428 continue; 10429 } 10430 10431 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, 10432 MEM_BLOCK_ALL, hw_index, &map_entry)); 10433 10434 if (soc_mem_field32_get(unit, mem, &map_entry, self[eindex])) { 10435 if (gport_count > 0 && count < gport_count) { 10436 gport[count] = node->gport; 10437 } 10438 count++; 10439 break; 10440 } 10441 } 10442 for (j = port_info->q_offset; 10443 (j < port_info->q_limit); j++) { 10444 node = &mmu_info->queue_node[j]; 10445 if (node->cosq_attached_to == -1) { 10446 continue ; 10447 } 10448 BCM_IF_ERROR_RETURN 10449 (_bcm_kt2_cosq_node_get(unit, node->gport, NULL ,&node_port, 10450 NULL, NULL)); 10451 if ((node_port != local_port)) { 10452 continue; 10453 } 10454 if ((node->hw_index % NUM_COS(unit)) != hw_cosq) { 10455 continue; 10456 } 10457 mem = MMU_INTFI_FC_MAP_TBL2m ; 10458 hw_index = (node->hw_index / 16); 10459 eindex = (node->hw_index % 16) / 8; 10460 10461 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, 10462 MEM_BLOCK_ALL, hw_index, &map_entry)); 10463 10464 if (soc_mem_field32_get(unit, mem, &map_entry, self[eindex])) { 10465 10466 if (gport_count > 0 && count < gport_count) { 10467 10468 gport[count] = node->gport; 10469 } 10470 count++; 10471 break; 10472 } 10473 } 10474 if(soc_feature(unit, soc_feature_mmu_packing)) { 10475 for (j = port_info->mcq_offset; 10476 (j < port_info->mcq_limit); j++) { 10477 node = &mmu_info->queue_node[j]; 10478 if (node->cosq_attached_to == -1) { 10479 continue ; 10480 } 10481 BCM_IF_ERROR_RETURN 10482 (_bcm_kt2_cosq_node_get(unit, node->gport, NULL ,&node_port, 10483 NULL, NULL)); 10484 if ((node_port != local_port)) { 10485 continue; 10486 } 10487 if ((node->hw_index % NUM_COS(unit)) != hw_cosq) { 10488 continue; 10489 } 10490 mem = MMU_INTFI_FC_MAP_TBL2m ; 10491 hw_index = (node->hw_index / 16); 10492 eindex = (node->hw_index % 16) / 8; 10493 10494 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, 10495 MEM_BLOCK_ALL, hw_index, &map_entry)); 10496 10497 if (soc_mem_field32_get(unit, mem, &map_entry, self[eindex])) { 10498 if (gport_count > 0 && count < gport_count ) { 10499 gport[count] = node->gport; 10500 } 10501 count++; 10502 break; 10503 } 10504 } 10505 } 10506 if (mmu_info->num_sub_queues) { 10507 for (j=mmu_info->base_sub_queue; 10508 j < (mmu_info->base_sub_queue+mmu_info->num_sub_queues); j++) { 10509 10510 node = &mmu_info->queue_node[j]; 10511 if (node->cosq_attached_to == -1) { 10512 continue; 10513 } 10514 BCM_IF_ERROR_RETURN 10515 (_bcm_kt2_cosq_node_get(unit, node->gport, NULL ,&node_port, 10516 NULL, NULL)); 10517 if (node_port != local_port) { 10518 continue; 10519 } 10520 if ((node->hw_index % NUM_COS(unit)) != hw_cosq) { 10521 continue; 10522 } 10523 mem = MMU_INTFI_FC_MAP_TBL2m ; 10524 hw_index = (node->hw_index / 16); 10525 eindex = (node->hw_index % 16) / 8; 10526 10527 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, 10528 MEM_BLOCK_ALL, hw_index, &map_entry)); 10529 10530 if (soc_mem_field32_get(unit, mem, &map_entry, self[eindex])) { 10531 if (gport_count > 0 && count < gport_count ) { 10532 gport[count] = node->gport; 10533 } 10534 count++; 10535 break; 10536 } 10537 10538 10539 } 10540 10541 } 10542 if ((count == gport_count) && (gport_count > 0)) { 10543 break; 10544 } 10545 } 10546 10547 if (count == 0) { 10548 return BCM_E_NOT_FOUND; 10549 } 10550 *actual_gport_count = count; 10551 return BCM_E_NONE; 10552 } 10553 10554 /* 10555 * Function: 10556 * bcm_kt2_cosq_pfc_class_mapping_set 10557 * Purpose: 10558 * Set PFC mapping for port. PFC class is mapped to cosq or scheduler node gports. 10559 * Parameters: 10560 * unit - (IN) unit number 10561 * port - (IN) port number 10562 * array_count - (IN) count of mapping 10563 * mapping_array - (IN) mappings 10564 * Returns: 10565 * BCM_E_XXX 10566 */ 10567 int 10568 bcm_kt2_cosq_safc_class_mapping_set(int unit, 10569 bcm_gport_t port, 10570 int array_count, 10571 bcm_cosq_safc_class_mapping_t *mapping_array) 10572 { 10573 int index, count; 10574 int cur_class = 0, pfc_class[_BCM_KT2_NUM_SAFC_CLASS]; 10575 bcm_gport_t cur_gport = 0; 10576 int local_port = 0; 10577 uint32 cos_bmp[_BCM_KT2_NUM_SAFC_CLASS]; 10578 10579 BCM_IF_ERROR_RETURN 10580 (_bcm_kt2_cosq_localport_resolve(unit, port, &local_port)); 10581 /*safc is supported only on higig interfaces */ 10582 if (!IS_HG_PORT(unit, local_port)) { 10583 return BCM_E_PARAM; 10584 } 10585 if ((array_count < 0) || (array_count > _BCM_KT2_NUM_SAFC_CLASS)) { 10586 return BCM_E_PARAM; 10587 } 10588 if (mapping_array == NULL) { 10589 return BCM_E_PARAM; 10590 } 10591 10592 for (count = 0; count < array_count; count++) { 10593 cur_class = mapping_array[count].class_id; 10594 if ((cur_class < 0) || (cur_class >= _BCM_KT2_NUM_SAFC_CLASS)) { 10595 return BCM_E_PARAM; 10596 } else { 10597 cos_bmp[cur_class] = 0; 10598 } 10599 10600 for (index = 0; index < BCM_COSQ_SAFC_GPORT_COUNT; index++) { 10601 cur_gport = mapping_array[count].gport_list[index]; 10602 if (cur_gport == BCM_GPORT_INVALID) { 10603 break; 10604 } 10605 10606 BCM_IF_ERROR_RETURN(_bcm_kt2_fc_status_map_gport(unit, port, 10607 cur_gport, _BCM_KT2_COSQ_FC_SAFC, &cos_bmp[cur_class])); 10608 } 10609 } 10610 10611 for (index = 0; index < _BCM_KT2_NUM_SAFC_CLASS; index++) { 10612 pfc_class[index] = index; 10613 } 10614 BCM_IF_ERROR_RETURN(_bcm_kt2_port_pfc_profile_set(unit, port, 10615 _BCM_COSQ_OP_SET, _BCM_KT2_NUM_SAFC_CLASS, pfc_class, cos_bmp)); 10616 10617 return BCM_E_NONE; 10618 } 10619 10620 int 10621 bcm_kt2_cosq_port_safc_get(int unit, bcm_port_t port, 10622 int cur_class, 10623 bcm_gport_t *gport, int gport_count, 10624 int *actual_gport_count) 10625 { 10626 _bcm_kt2_cosq_node_t *node; 10627 bcm_port_t local_port; 10628 int hw_cosq, count = 0; 10629 uint32 profile_index; 10630 uint64 rval64[16], *rval64s[1], rval, index_map; 10631 uint32 tmp32, bmp; 10632 _bcm_kt2_mmu_info_t *mmu_info; 10633 int mmu_port; 10634 soc_info_t *si; 10635 soc_reg_t reg; 10636 int node_port = 0 ; 10637 int supported = 0 ; 10638 _bcm_kt2_cosq_port_info_t *port_info; 10639 static const soc_reg_t llfc_cfgr[] = { 10640 PORT_PFC_CFG0r, 10641 }; 10642 static const soc_field_t self[] = { 10643 SEL0f, SEL1f, 10644 }; 10645 int j, hw_index, eindex; 10646 soc_mem_t mem; 10647 uint32 map_entry[SOC_MAX_MEM_WORDS]; 10648 10649 if (IS_CPU_PORT(unit, port)) { 10650 return BCM_E_PORT; 10651 } 10652 10653 if ((gport == NULL) && (gport_count > 0)) { 10654 return BCM_E_PARAM; 10655 } 10656 10657 if (actual_gport_count == NULL) { 10658 return BCM_E_PARAM; 10659 } 10660 10661 BCM_IF_ERROR_RETURN 10662 (_bcm_kt2_cosq_localport_resolve(unit, port, &local_port)); 10663 10664 si = &SOC_INFO(unit); 10665 mmu_info = _bcm_kt2_mmu_info[unit]; 10666 #ifdef BCM_METROLITE_SUPPORT 10667 if(SOC_IS_METROLITE(unit)) { 10668 mmu_port = ml_pfc_support[local_port].mmu_port; 10669 supported = ml_pfc_support[local_port].supported; 10670 } else 10671 #endif 10672 #ifdef BCM_SABER2_SUPPORT 10673 if(SOC_IS_SABER2(unit)) { 10674 mmu_port = sb2_pfc_support[local_port].mmu_port; 10675 supported = sb2_pfc_support[local_port].supported; 10676 } else 10677 #endif 10678 { 10679 mmu_port = kt2_pfc_support[local_port].mmu_port; 10680 supported = kt2_pfc_support[local_port].supported; 10681 } 10682 if (!supported) { 10683 return BCM_E_PARAM; 10684 10685 } 10686 port_info = &mmu_info->port[local_port]; 10687 10688 rval64s[0] = rval64; 10689 reg = llfc_cfgr[mmu_port/32]; 10690 BCM_IF_ERROR_RETURN(soc_reg64_get(unit, reg, REG_PORT_ANY, 0, &rval)); 10691 10692 index_map = soc_reg64_field_get(unit, reg, rval, PROFILE_INDEXf); 10693 COMPILER_64_SHR(index_map, ((mmu_port % 32) * 2)); 10694 COMPILER_64_TO_32_LO(tmp32, index_map); 10695 profile_index = (tmp32 & 3)*16; 10696 10697 BCM_IF_ERROR_RETURN 10698 (soc_profile_reg_get(unit, _bcm_kt2_llfc_profile[unit], 10699 profile_index, 16, rval64s)); 10700 10701 bmp = soc_reg64_field32_get(unit, PRIO2COS_PROFILEr, rval64[cur_class], 10702 COS_BMPf); 10703 10704 num_port_schedulers[unit] = si->cpu_hg_index; 10705 10706 for (hw_cosq = 0; hw_cosq < 8; hw_cosq++) { 10707 if (!(bmp & (1 << hw_cosq))) { 10708 continue; 10709 } 10710 for (j = num_pp_ports[unit] ; 10711 j < num_total_schedulers[unit] ; j++) { 10712 node = &mmu_info->sched_node[j]; 10713 if (node->cosq_attached_to == -1) { 10714 continue ; 10715 } 10716 BCM_IF_ERROR_RETURN 10717 (_bcm_kt2_cosq_node_get(unit, node->gport, NULL 10718 ,&node_port, NULL, NULL)); 10719 if ( (node_port != local_port) || 10720 ((node->hw_index - port_info->q_offset) != hw_cosq)) { 10721 continue; 10722 } 10723 10724 hw_index = (node->hw_index / 16); 10725 eindex = (node->hw_index % 16)/8; 10726 if (node->level == _BCM_KT2_COSQ_NODE_LEVEL_L0) { 10727 mem = MMU_INTFI_FC_MAP_TBL0m ; 10728 } else if (node->level == _BCM_KT2_COSQ_NODE_LEVEL_L1) { 10729 mem = MMU_INTFI_FC_MAP_TBL1m; 10730 } else { 10731 continue; 10732 } 10733 10734 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, 10735 MEM_BLOCK_ALL, hw_index, &map_entry)); 10736 10737 if (soc_mem_field32_get(unit, mem, &map_entry, self[eindex])) { 10738 if (gport_count > 0 && count < gport_count) { 10739 gport[count] = node->gport; 10740 } 10741 count++; 10742 break; 10743 } 10744 } 10745 for (j = port_info->q_offset; 10746 (j < port_info->q_limit); j++) { 10747 node = &mmu_info->queue_node[j]; 10748 if (node->cosq_attached_to == -1) { 10749 continue ; 10750 } 10751 BCM_IF_ERROR_RETURN 10752 (_bcm_kt2_cosq_node_get(unit, node->gport, NULL ,&node_port, 10753 NULL, NULL)); 10754 if ((node_port != local_port)) { 10755 continue; 10756 } 10757 if ((node->hw_index - port_info->q_offset) != hw_cosq) { 10758 continue; 10759 } 10760 mem = MMU_INTFI_FC_MAP_TBL2m ; 10761 hw_index = (node->hw_index / 16); 10762 eindex = (node->hw_index % 16) / 8; 10763 10764 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, 10765 MEM_BLOCK_ALL, hw_index, &map_entry)); 10766 10767 if (soc_mem_field32_get(unit, mem, &map_entry, self[eindex])) { 10768 10769 if (gport_count > 0 && count < gport_count) { 10770 10771 gport[count] = node->gport; 10772 } 10773 count++; 10774 break; 10775 } 10776 } 10777 if(soc_feature(unit, soc_feature_mmu_packing)) { 10778 for (j = port_info->mcq_offset; 10779 (j < port_info->mcq_limit); j++) { 10780 node = &mmu_info->queue_node[j]; 10781 if (node->cosq_attached_to == -1) { 10782 continue ; 10783 } 10784 BCM_IF_ERROR_RETURN 10785 (_bcm_kt2_cosq_node_get(unit, node->gport, NULL ,&node_port, 10786 NULL, NULL)); 10787 if ((node_port != local_port)) { 10788 continue; 10789 } 10790 if ((node->hw_index % NUM_COS(unit)) != hw_cosq) { 10791 continue; 10792 } 10793 mem = MMU_INTFI_FC_MAP_TBL2m ; 10794 hw_index = (node->hw_index / 16); 10795 eindex = (node->hw_index % 16) / 8; 10796 10797 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, 10798 MEM_BLOCK_ALL, hw_index, &map_entry)); 10799 10800 if (soc_mem_field32_get(unit, mem, &map_entry, self[eindex])) { 10801 if (gport_count > 0 && count < gport_count ) { 10802 gport[count] = node->gport; 10803 } 10804 count++; 10805 break; 10806 } 10807 } 10808 } 10809 if ((count == gport_count) && (gport_count > 0)) { 10810 break; 10811 } 10812 } 10813 10814 if (count == 0) { 10815 return BCM_E_NOT_FOUND; 10816 } 10817 *actual_gport_count = count; 10818 return BCM_E_NONE; 10819 } 10820 10821 10822 int 10823 bcm_kt2_cosq_safc_class_mapping_get(int unit, 10824 bcm_gport_t port, 10825 int array_max, 10826 int *array_count, 10827 bcm_cosq_safc_class_mapping_t *mapping_array) 10828 { 10829 int rv = 0; 10830 int cur_class = 0; 10831 int actual_gport_count, class_count = 0; 10832 int local_port = 0 ; 10833 10834 BCM_IF_ERROR_RETURN 10835 (_bcm_kt2_cosq_localport_resolve(unit, port, &local_port)); 10836 if (!IS_HG_PORT(unit,local_port)) { 10837 return BCM_E_PARAM; 10838 } 10839 if ((mapping_array == NULL) && (array_max > 0)) { 10840 return BCM_E_PARAM; 10841 } 10842 if (array_count == NULL) { 10843 return BCM_E_PARAM; 10844 } 10845 10846 for (cur_class = 0; cur_class < _BCM_KT2_NUM_SAFC_CLASS; cur_class++) { 10847 actual_gport_count = 0; 10848 if (array_max > 0) { 10849 rv = bcm_kt2_cosq_port_safc_get(unit, local_port, cur_class, 10850 mapping_array[class_count].gport_list, 10851 BCM_COSQ_PFC_GPORT_COUNT, &actual_gport_count); 10852 } else { 10853 rv = bcm_kt2_cosq_port_safc_get(unit, local_port, cur_class, 10854 NULL, -1, &actual_gport_count); 10855 } 10856 if (rv == BCM_E_NONE) { 10857 if (array_max > 0) { 10858 mapping_array[class_count].class_id = cur_class; 10859 if (actual_gport_count < BCM_COSQ_PFC_GPORT_COUNT) { 10860 mapping_array[class_count].gport_list[actual_gport_count] = 10861 BCM_GPORT_INVALID; 10862 } 10863 } 10864 class_count++; 10865 } else if (rv != BCM_E_NOT_FOUND) { 10866 return rv; 10867 } 10868 10869 if ((class_count == array_max) && (array_max > 0)) { 10870 break; 10871 } 10872 } 10873 10874 *array_count = class_count; 10875 if (class_count == 0) { 10876 return BCM_E_NOT_FOUND; 10877 } 10878 10879 return BCM_E_NONE; 10880 } 10881 10882 /* 10883 * Function: 10884 * bcm_kt2_cosq_pfc_class_mapping_set 10885 * Purpose: 10886 * Set PFC mapping for port. PFC class is mapped to cosq or scheduler node gports. 10887 * Parameters: 10888 * unit - (IN) unit number 10889 * port - (IN) port number 10890 * array_count - (IN) count of mapping 10891 * mapping_array - (IN) mappings 10892 * Returns: 10893 * BCM_E_XXX 10894 */ 10895 int 10896 bcm_kt2_cosq_pfc_class_mapping_set(int unit, 10897 bcm_gport_t port, 10898 int array_count, 10899 bcm_cosq_pfc_class_mapping_t *mapping_array) 10900 { 10901 int index, count; 10902 int cur_class = 0, pfc_class[_BCM_KT2_NUM_PFC_CLASS]; 10903 bcm_gport_t cur_gport = 0; 10904 int local_port = 0; 10905 uint32 cos_bmp[_BCM_KT2_NUM_PFC_CLASS]; 10906 10907 BCM_IF_ERROR_RETURN 10908 (_bcm_kt2_cosq_localport_resolve(unit, port, &local_port)); 10909 if (!SOC_IS_SABER2(unit) && !IS_XE_PORT(unit,local_port)) { 10910 return BCM_E_PARAM; 10911 } 10912 if ((array_count < 0) || (array_count > _BCM_KT2_NUM_PFC_CLASS)) { 10913 return BCM_E_PARAM; 10914 } 10915 if (mapping_array == NULL) { 10916 return BCM_E_PARAM; 10917 } 10918 10919 for (count = 0; count < array_count; count++) { 10920 cur_class = mapping_array[count].class_id; 10921 if ((cur_class < 0) || (cur_class >= _BCM_KT2_NUM_PFC_CLASS)) { 10922 return BCM_E_PARAM; 10923 } else { 10924 cos_bmp[cur_class] = 0; 10925 } 10926 10927 for (index = 0; index < BCM_COSQ_PFC_GPORT_COUNT; index++) { 10928 cur_gport = mapping_array[count].gport_list[index]; 10929 if (cur_gport == BCM_GPORT_INVALID) { 10930 break; 10931 } 10932 10933 BCM_IF_ERROR_RETURN(_bcm_kt2_fc_status_map_gport(unit, port, 10934 cur_gport, _BCM_KT2_COSQ_FC_PFC, &cos_bmp[cur_class])); 10935 } 10936 } 10937 10938 for (index = 0; index < _BCM_KT2_NUM_PFC_CLASS; index++) { 10939 pfc_class[index] = index; 10940 } 10941 BCM_IF_ERROR_RETURN(_bcm_kt2_port_pfc_profile_set(unit, port, 10942 _BCM_COSQ_OP_SET, _BCM_KT2_NUM_PFC_CLASS, pfc_class, cos_bmp)); 10943 10944 return BCM_E_NONE; 10945 } 10946 10947 int 10948 bcm_kt2_cosq_pfc_class_mapping_get(int unit, 10949 bcm_gport_t port, 10950 int array_max, 10951 int *array_count, 10952 bcm_cosq_pfc_class_mapping_t *mapping_array) 10953 { 10954 int rv = 0; 10955 int cur_class = 0; 10956 int actual_gport_count, class_count = 0; 10957 int local_port = 0 ; 10958 bcm_switch_control_t sc[] = { bcmSwitchPFCClass0Queue, 10959 bcmSwitchPFCClass1Queue, 10960 bcmSwitchPFCClass2Queue, 10961 bcmSwitchPFCClass3Queue, 10962 bcmSwitchPFCClass4Queue, 10963 bcmSwitchPFCClass5Queue, 10964 bcmSwitchPFCClass6Queue, 10965 bcmSwitchPFCClass7Queue 10966 }; 10967 10968 BCM_IF_ERROR_RETURN 10969 (_bcm_kt2_cosq_localport_resolve(unit, port, &local_port)); 10970 if (!SOC_IS_SABER2(unit) && !IS_XE_PORT(unit,local_port)) { 10971 return BCM_E_PARAM; 10972 } 10973 if ((mapping_array == NULL) && (array_max > 0)) { 10974 return BCM_E_PARAM; 10975 } 10976 if (array_count == NULL) { 10977 return BCM_E_PARAM; 10978 } 10979 10980 for (cur_class = 0; cur_class < _BCM_KT2_NUM_PFC_CLASS; cur_class++) { 10981 actual_gport_count = 0; 10982 if (array_max > 0) { 10983 rv = bcm_kt2_cosq_port_pfc_get(unit, local_port, sc[cur_class], 10984 mapping_array[class_count].gport_list, 10985 BCM_COSQ_PFC_GPORT_COUNT, &actual_gport_count); 10986 } else { 10987 rv = bcm_kt2_cosq_port_pfc_get(unit, local_port, sc[cur_class], 10988 NULL, -1, &actual_gport_count); 10989 } 10990 if (rv == BCM_E_NONE) { 10991 if (array_max > 0) { 10992 mapping_array[class_count].class_id = cur_class; 10993 if (actual_gport_count < BCM_COSQ_PFC_GPORT_COUNT) { 10994 mapping_array[class_count].gport_list[actual_gport_count] = 10995 BCM_GPORT_INVALID; 10996 } 10997 } 10998 class_count++; 10999 } else if (rv != BCM_E_NOT_FOUND) { 11000 return rv; 11001 } 11002 11003 if ((class_count == array_max) && (array_max > 0)) { 11004 break; 11005 } 11006 } 11007 11008 *array_count = class_count; 11009 if (class_count == 0) { 11010 return BCM_E_NOT_FOUND; 11011 } 11012 11013 return BCM_E_NONE; 11014 } 11015 11016 int 11017 bcm_kt2_cosq_stat_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 11018 bcm_cosq_stat_t stat, int sync_mode, uint64 *value) 11019 { 11020 bcm_port_t local_port; 11021 int startq, numq, i; 11022 uint64 sum, value64; 11023 soc_counter_non_dma_id_t dma_id; 11024 _bcm_kt2_cosq_node_t *node = NULL; 11025 _bcm_kt2_cosq_node_t *child_node = NULL; 11026 #ifdef BCM_SABER2_SUPPORT 11027 uint32 drop_type, total_drop_mask, wred_drop_mask; 11028 uint32 rval; 11029 #endif 11030 int (*counter_get) (int , soc_port_t , soc_reg_t , int , uint64 *); 11031 11032 if (value == NULL) { 11033 return BCM_E_PARAM; 11034 } 11035 if (stat == bcmCosqStatEgressUCQueueBytesCurrent) { 11036 return _bcm_kt2_cosq_current_stat_set_get(unit, port, 11037 cosq, stat, 11038 0, value); 11039 } 11040 11041 /* 11042 * if sync-mode is set, update the software cached counter value, 11043 * with the hardware count and then retrieve the count. 11044 * else return the software cache counter value. 11045 */ 11046 counter_get = (sync_mode == 1)? soc_counter_sync_get: soc_counter_get; 11047 11048 BCM_IF_ERROR_RETURN 11049 (_bcm_kt2_cosq_index_resolve 11050 (unit, port, cosq, _BCM_KT2_COSQ_INDEX_STYLE_UCAST_QUEUE, 11051 &local_port, &startq, &numq)); 11052 11053 if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) || 11054 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port) || 11055 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port) || 11056 BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(port)) { 11057 /* pass port as queue number */ 11058 local_port = startq; 11059 startq = 0; 11060 } 11061 11062 #ifdef BCM_SABER2_SUPPORT 11063 if(SOC_IS_SABER2(unit)) { 11064 #ifdef BCM_METROLITE_SUPPORT 11065 if(SOC_IS_METROLITE(unit)) { 11066 total_drop_mask = BCM_ML_COSQ_TOTAL_DROP_MASK; 11067 wred_drop_mask = BCM_ML_COSQ_WRED_DROP_MASK; 11068 } else 11069 #endif 11070 { 11071 total_drop_mask = BCM_SB2_COSQ_TOTAL_DROP_MASK; 11072 wred_drop_mask = BCM_SB2_COSQ_WRED_DROP_MASK; 11073 } 11074 SOC_IF_ERROR_RETURN(READ_THDO_DROP_CTR_CONFIGr(unit, &rval)); 11075 drop_type = soc_reg_field_get(unit, THDO_DROP_CTR_CONFIGr, rval, OP_DROP_MASKf); 11076 11077 if (drop_type == total_drop_mask) { 11078 if (!((stat == bcmCosqStatDroppedPackets)|| 11079 (stat == bcmCosqStatDroppedBytes)|| 11080 (stat == bcmCosqStatRedCongestionDroppedPackets)|| 11081 (stat == bcmCosqStatRedCongestionDroppedBytes)|| 11082 (stat == bcmCosqStatYellowCongestionDroppedPackets)|| 11083 (stat == bcmCosqStatYellowCongestionDroppedBytes)|| 11084 (stat == bcmCosqStatOutPackets)||(stat == bcmCosqStatOutBytes))){ 11085 return BCM_E_PARAM; 11086 } 11087 11088 } 11089 else if (drop_type == wred_drop_mask) { 11090 if (!((stat == bcmCosqStatDiscardDroppedPackets)|| 11091 (stat == bcmCosqStatDiscardDroppedBytes)|| 11092 (stat == bcmCosqStatRedDiscardDroppedPackets)|| 11093 (stat == bcmCosqStatRedDiscardDroppedBytes)|| 11094 (stat == bcmCosqStatYellowDiscardDroppedPackets)|| 11095 (stat == bcmCosqStatYellowDiscardDroppedBytes)|| 11096 (stat == bcmCosqStatGreenDiscardDroppedBytes)|| 11097 (stat == bcmCosqStatGreenDiscardDroppedPackets)|| 11098 (stat == bcmCosqStatOutPackets)||(stat == bcmCosqStatOutBytes))){ 11099 return BCM_E_PARAM; 11100 } 11101 } 11102 } 11103 #endif 11104 switch (stat) { 11105 case bcmCosqStatDroppedPackets: 11106 case bcmCosqStatDiscardDroppedPackets: 11107 dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_PKT; 11108 break; 11109 11110 case bcmCosqStatDroppedBytes: 11111 case bcmCosqStatDiscardDroppedBytes: 11112 dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE; 11113 break; 11114 11115 case bcmCosqStatRedCongestionDroppedPackets: 11116 case bcmCosqStatRedDiscardDroppedPackets: 11117 dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_RED; 11118 break; 11119 11120 case bcmCosqStatRedCongestionDroppedBytes: 11121 case bcmCosqStatRedDiscardDroppedBytes: 11122 dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE_RED; 11123 break; 11124 11125 case bcmCosqStatYellowCongestionDroppedPackets: 11126 case bcmCosqStatYellowDiscardDroppedPackets : 11127 dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_YELLOW; 11128 break; 11129 11130 case bcmCosqStatYellowCongestionDroppedBytes: 11131 case bcmCosqStatYellowDiscardDroppedBytes: 11132 dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE_YELLOW; 11133 break; 11134 11135 case bcmCosqStatGreenDiscardDroppedPackets: 11136 dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_GREEN; 11137 break; 11138 11139 case bcmCosqStatGreenDiscardDroppedBytes: 11140 dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE_GREEN; 11141 break; 11142 11143 case bcmCosqStatOutPackets: 11144 dma_id = SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT; 11145 break; 11146 11147 case bcmCosqStatOutBytes: 11148 dma_id = SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE; 11149 break; 11150 default: 11151 return BCM_E_PARAM; 11152 } 11153 11154 if (!BCM_GPORT_IS_SCHEDULER(port)) { 11155 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 11156 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port) || 11157 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) || 11158 BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(port) || 11159 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port) || 11160 (cosq != BCM_COS_INVALID)) { 11161 BCM_IF_ERROR_RETURN 11162 (counter_get(unit, local_port, dma_id, startq, value)); 11163 } else { 11164 numq = soc_property_get(unit, spn_BCM_NUM_COS, BCM_COS_DEFAULT); 11165 if (numq < 1) { 11166 numq = 1; 11167 } else if (numq > 8) { 11168 numq = 8; 11169 } 11170 COMPILER_64_ZERO(sum); 11171 COMPILER_64_ZERO(value64); 11172 for (i = 0; i < numq; i++) { 11173 BCM_IF_ERROR_RETURN 11174 (counter_get(unit, local_port, dma_id, i, &value64)); 11175 COMPILER_64_ADD_64(sum, value64); 11176 } 11177 *value = sum; 11178 } 11179 } else { 11180 BCM_IF_ERROR_RETURN 11181 (_bcm_kt2_cosq_node_get(unit, port, 0, 11182 &local_port, NULL, &node)); 11183 COMPILER_64_ZERO(sum); 11184 if (cosq == -1) { 11185 for (i = 0; i < node->numq; i++) { 11186 if ((_bcm_kt2_cosq_child_node_at_input(node, i, &child_node)) 11187 == BCM_E_NOT_FOUND) { 11188 continue; 11189 } 11190 port = child_node->gport; 11191 11192 BCM_IF_ERROR_RETURN 11193 (_bcm_kt2_cosq_index_resolve 11194 (unit, port, 0, _BCM_KT2_COSQ_INDEX_STYLE_UCAST_QUEUE, 11195 &local_port, &startq, &numq)); 11196 11197 if (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port) || 11198 BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(port) || 11199 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port)) { 11200 /* pass port as queue number */ 11201 local_port = startq; 11202 startq = 0; 11203 } 11204 BCM_IF_ERROR_RETURN 11205 (counter_get(unit, local_port, dma_id, 11206 startq , &value64)); 11207 COMPILER_64_ADD_64(sum, value64); 11208 } 11209 } 11210 else { 11211 11212 if ((_bcm_kt2_cosq_child_node_at_input(node, cosq, &child_node)) 11213 == BCM_E_NOT_FOUND) { 11214 return BCM_E_NOT_FOUND; 11215 } 11216 port = child_node->gport; 11217 11218 BCM_IF_ERROR_RETURN 11219 (_bcm_kt2_cosq_index_resolve 11220 (unit, port, 0, _BCM_KT2_COSQ_INDEX_STYLE_UCAST_QUEUE, 11221 &local_port, &startq, &numq)); 11222 11223 if (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port) || 11224 BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(port) || 11225 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port)) { 11226 /* pass port as queue number */ 11227 local_port = startq; 11228 startq = 0; 11229 } 11230 BCM_IF_ERROR_RETURN 11231 (counter_get(unit, local_port, dma_id, 11232 startq , &value64)); 11233 COMPILER_64_ADD_64(sum, value64); 11234 } 11235 *value = sum; 11236 } 11237 11238 return BCM_E_NONE; 11239 } 11240 11241 int 11242 bcm_kt2_cosq_gport_stat_set(int unit, bcm_gport_t port, bcm_cos_queue_t cosq, 11243 bcm_cosq_gport_stats_t stat, uint64 value) 11244 { 11245 bcm_port_t local_port; 11246 int startq, numq, i; 11247 uint64 value64; 11248 soc_counter_non_dma_id_t dma_id; 11249 11250 if (BCM_GPORT_IS_SCHEDULER(port) && cosq != BCM_COS_INVALID) { 11251 return BCM_E_PARAM; 11252 } 11253 11254 BCM_IF_ERROR_RETURN 11255 (_bcm_kt2_cosq_index_resolve 11256 (unit, port, cosq, _BCM_KT2_COSQ_INDEX_STYLE_UCAST_QUEUE, 11257 &local_port, &startq, &numq)); 11258 if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) || 11259 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port) || 11260 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port) || 11261 BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(port)) { 11262 /* pass port as queue number */ 11263 local_port = startq; 11264 startq = 0; 11265 } 11266 11267 switch (stat) { 11268 case bcmCosqGportGreenAcceptedPkts: 11269 dma_id = SOC_COUNTER_NON_DMA_COSQ_ACCEPT_PKT_GREEN; 11270 break; 11271 case bcmCosqGportGreenAcceptedBytes: 11272 dma_id = SOC_COUNTER_NON_DMA_COSQ_ACCEPT_BYTE_GREEN; 11273 break; 11274 case bcmCosqGportYellowAcceptedPkts: 11275 dma_id = SOC_COUNTER_NON_DMA_COSQ_ACCEPT_PKT_YELLOW; 11276 break; 11277 case bcmCosqGportYellowAcceptedBytes: 11278 dma_id = SOC_COUNTER_NON_DMA_COSQ_ACCEPT_BYTE_YELLOW; 11279 break; 11280 case bcmCosqGportRedAcceptedPkts: 11281 dma_id = SOC_COUNTER_NON_DMA_COSQ_ACCEPT_PKT_RED; 11282 break; 11283 case bcmCosqGportRedAcceptedBytes: 11284 dma_id = SOC_COUNTER_NON_DMA_COSQ_ACCEPT_BYTE_RED; 11285 break; 11286 case bcmCosqGportReceivedPkts: 11287 dma_id = SOC_COUNTER_NON_DMA_COSQ_ACCEPT_PKT; 11288 break; 11289 case bcmCosqGportReceivedBytes: 11290 dma_id = SOC_COUNTER_NON_DMA_COSQ_ACCEPT_BYTE; 11291 break; 11292 case bcmCosqGportGreenDroppedPkts: 11293 dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_GREEN; 11294 break; 11295 case bcmCosqGportGreenDroppedBytes: 11296 dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE_GREEN; 11297 break; 11298 case bcmCosqGportYellowDroppedPkts: 11299 dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_YELLOW; 11300 break; 11301 case bcmCosqGportYellowDroppedBytes: 11302 dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE_YELLOW; 11303 break; 11304 case bcmCosqGportRedDroppedPkts: 11305 dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_RED; 11306 break; 11307 case bcmCosqGportRedDroppedBytes: 11308 dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE_RED; 11309 break; 11310 case bcmCosqGportDroppedPkts: 11311 dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_PKT; 11312 break; 11313 case bcmCosqGportDroppedBytes: 11314 dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE; 11315 break; 11316 case bcmCosqGportOutPkts: 11317 dma_id = SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT; 11318 break; 11319 case bcmCosqGportOutBytes: 11320 dma_id = SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE; 11321 break; 11322 default: 11323 return BCM_E_PARAM; 11324 } 11325 11326 if (!BCM_GPORT_IS_SCHEDULER(port)) { 11327 BCM_IF_ERROR_RETURN 11328 (soc_counter_set(unit, local_port, dma_id, startq, value)); 11329 } else { 11330 11331 COMPILER_64_ZERO(value64); 11332 for (i = 0; i < numq; i++) { 11333 BCM_IF_ERROR_RETURN 11334 (soc_counter_set(unit, local_port, dma_id, startq + i, 11335 value64)); 11336 } 11337 } 11338 11339 return BCM_E_NONE; 11340 } 11341 11342 int 11343 bcm_kt2_cosq_gport_stat_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 11344 bcm_cosq_gport_stats_t stat, uint64 *value) 11345 { 11346 bcm_port_t local_port; 11347 int startq, numq, i; 11348 uint64 sum, value64; 11349 soc_counter_non_dma_id_t dma_id; 11350 11351 if (value == NULL) { 11352 return BCM_E_PARAM; 11353 } 11354 11355 if (BCM_GPORT_IS_SCHEDULER(port) && cosq != BCM_COS_INVALID) { 11356 return BCM_E_PARAM; 11357 } 11358 11359 BCM_IF_ERROR_RETURN 11360 (_bcm_kt2_cosq_index_resolve 11361 (unit, port, cosq, _BCM_KT2_COSQ_INDEX_STYLE_UCAST_QUEUE, 11362 &local_port, &startq, &numq)); 11363 11364 if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) || 11365 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port) || 11366 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port) || 11367 BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(port)) { 11368 /* pass port as queue number */ 11369 local_port = startq; 11370 startq = 0; 11371 } 11372 11373 switch (stat) { 11374 case bcmCosqGportGreenAcceptedPkts: 11375 dma_id = SOC_COUNTER_NON_DMA_COSQ_ACCEPT_PKT_GREEN; 11376 break; 11377 case bcmCosqGportGreenAcceptedBytes: 11378 dma_id = SOC_COUNTER_NON_DMA_COSQ_ACCEPT_BYTE_GREEN; 11379 break; 11380 case bcmCosqGportYellowAcceptedPkts: 11381 dma_id = SOC_COUNTER_NON_DMA_COSQ_ACCEPT_PKT_YELLOW; 11382 break; 11383 case bcmCosqGportYellowAcceptedBytes: 11384 dma_id = SOC_COUNTER_NON_DMA_COSQ_ACCEPT_BYTE_YELLOW; 11385 break; 11386 case bcmCosqGportRedAcceptedPkts: 11387 dma_id = SOC_COUNTER_NON_DMA_COSQ_ACCEPT_PKT_RED; 11388 break; 11389 case bcmCosqGportRedAcceptedBytes: 11390 dma_id = SOC_COUNTER_NON_DMA_COSQ_ACCEPT_BYTE_RED; 11391 break; 11392 case bcmCosqGportReceivedPkts: 11393 dma_id = SOC_COUNTER_NON_DMA_COSQ_ACCEPT_PKT; 11394 break; 11395 case bcmCosqGportReceivedBytes: 11396 dma_id = SOC_COUNTER_NON_DMA_COSQ_ACCEPT_BYTE; 11397 break; 11398 case bcmCosqGportGreenDroppedPkts: 11399 dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_GREEN; 11400 break; 11401 case bcmCosqGportGreenDroppedBytes: 11402 dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE_GREEN; 11403 break; 11404 case bcmCosqGportYellowDroppedPkts: 11405 dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_YELLOW; 11406 break; 11407 case bcmCosqGportYellowDroppedBytes: 11408 dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE_YELLOW; 11409 break; 11410 case bcmCosqGportRedDroppedPkts: 11411 dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_RED; 11412 break; 11413 case bcmCosqGportRedDroppedBytes: 11414 dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE_RED; 11415 break; 11416 case bcmCosqGportDroppedPkts: 11417 dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_PKT; 11418 break; 11419 case bcmCosqGportDroppedBytes: 11420 dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE; 11421 break; 11422 case bcmCosqGportOutPkts: 11423 dma_id = SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT; 11424 break; 11425 case bcmCosqGportOutBytes: 11426 dma_id = SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE; 11427 break; 11428 default: 11429 return BCM_E_PARAM; 11430 } 11431 11432 if (!BCM_GPORT_IS_SCHEDULER(port)) { 11433 BCM_IF_ERROR_RETURN 11434 (soc_counter_get(unit, local_port, dma_id, startq, value)); 11435 } else { 11436 COMPILER_64_ZERO(sum); 11437 for (i = 0; i < numq; i++) { 11438 BCM_IF_ERROR_RETURN 11439 (soc_counter_get(unit, local_port, dma_id, startq + i, 11440 &value64)); 11441 COMPILER_64_ADD_64(sum, value64); 11442 } 11443 *value = sum; 11444 } 11445 11446 return BCM_E_NONE; 11447 } 11448 11449 #ifdef BCM_KATANA2_SUPPORT 11450 STATIC 11451 void _bcm_kt2_flex_config_set (int unit, bcm_cosq_stat_t *stat_array, 11452 int stat_count) 11453 { 11454 _sb2_cosq_counter_mem_map_t *mem_map; 11455 int num_elem = 0, elem_size = 4; 11456 int index = 0; 11457 int i = 0; 11458 char *cname_pkt = NULL; 11459 char *cname_byte = NULL; 11460 soc_counter_non_dma_id_t non_dma_id = 0; 11461 uint16 dev_id; 11462 uint8 rev_id; 11463 11464 soc_sb2_cosq_counter_mem_map_get(unit, &num_elem, &mem_map); 11465 if (SOC_IS_SABER2(unit)) { 11466 elem_size = 2; 11467 } 11468 soc_cm_get_id(unit, &dev_id, &rev_id); 11469 if ((dev_id == BCM56233_DEVICE_ID) || 11470 (SOC_IS_METROLITE(unit))) { 11471 elem_size = 1; 11472 } 11473 11474 /*updating the mem map for cosq counters*/ 11475 for (index = 0; index < stat_count; index++) { 11476 switch (stat_array[index]) { 11477 case bcmCosqStatDroppedPackets: 11478 non_dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_PKT; 11479 cname_pkt = "DROP_PKT"; 11480 cname_byte = "DROP_BYTE"; 11481 break; 11482 case bcmCosqStatDiscardDroppedPackets: 11483 non_dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_PKT; 11484 cname_pkt = "WRED_DROP_PKT"; 11485 cname_byte = "WRED_DROP_BYTE"; 11486 break; 11487 case bcmCosqStatYellowCongestionDroppedPackets: 11488 non_dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_YELLOW; 11489 cname_pkt = "DROP_PKT_Y"; 11490 cname_byte = "DROP_BYTE_Y"; 11491 break; 11492 case bcmCosqStatYellowDiscardDroppedPackets: 11493 non_dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_YELLOW; 11494 cname_pkt = "WRED_DROP_PKT_Y"; 11495 cname_byte = "WRED_DROP_BYTE_Y"; 11496 break; 11497 11498 case bcmCosqStatRedCongestionDroppedPackets: 11499 non_dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_RED; 11500 cname_pkt = "DROP_PKT_R"; 11501 cname_byte = "DROP_BYTE_R"; 11502 break; 11503 case bcmCosqStatRedDiscardDroppedPackets: 11504 non_dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_RED; 11505 cname_pkt = "WRED_DROP_PKT_R"; 11506 cname_byte = "WRED_DROP_BYTE_R"; 11507 break; 11508 11509 case bcmCosqStatGreenDiscardDroppedPackets: 11510 non_dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_GREEN; 11511 cname_pkt = "WRED_DROP_PKT_G"; 11512 cname_byte = "WRED_DROP_BYTE_G"; 11513 break; 11514 11515 case bcmCosqStatOutPackets : 11516 non_dma_id = SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT; 11517 cname_pkt = "PERQ_PKT"; 11518 cname_byte ="PERQ_BYTE"; 11519 break; 11520 default: 11521 break; 11522 } 11523 for ( i = 0; i < elem_size; i++) { 11524 mem_map[index*elem_size + i].non_dma_id = non_dma_id; 11525 mem_map[index*elem_size + i].cname_pkt = cname_pkt; 11526 mem_map[index*elem_size + i].cname_byte = cname_byte; 11527 } 11528 } 11529 } 11530 11531 int 11532 bcm_kt2_cosq_stat_config_set(int unit, int stat_count, 11533 bcm_cosq_stat_t *stat_array) 11534 { 11535 int index = 0; 11536 uint32 drop_type; 11537 uint32 type = 0; 11538 int rv; 11539 pbmp_t pbmp; 11540 sal_usecs_t interval; 11541 uint32 flags; 11542 soc_port_t port; 11543 #ifdef BCM_KATANA2_SUPPORT 11544 uint32 total_drop_mask, wred_drop_mask, default_drop_mask; 11545 #endif 11546 11547 #ifdef BCM_METROLITE_SUPPORT 11548 if(SOC_IS_METROLITE(unit)) { 11549 total_drop_mask = BCM_ML_COSQ_TOTAL_DROP_MASK; 11550 wred_drop_mask = BCM_ML_COSQ_WRED_DROP_MASK; 11551 default_drop_mask = BCM_ML_COSQ_DEFAULT_DROP_MASK; 11552 drop_type = BCM_ML_COSQ_DEFAULT_DROP_MASK; 11553 } else 11554 #endif 11555 { 11556 total_drop_mask = BCM_SB2_COSQ_TOTAL_DROP_MASK; 11557 wred_drop_mask = BCM_SB2_COSQ_WRED_DROP_MASK; 11558 default_drop_mask = BCM_SB2_COSQ_DEFAULT_DROP_MASK; 11559 drop_type = BCM_SB2_COSQ_DEFAULT_DROP_MASK; 11560 } 11561 11562 if ((stat_count != BCM_SB2_COSQ_FLEX_COUNT_SUPPORTED) || 11563 (stat_array == NULL)) { 11564 return BCM_E_PARAM; 11565 } 11566 11567 /*validating the stat_types, aligning the stats order generating the type*/ 11568 for ( index = 0; index < stat_count; index++) { 11569 switch(stat_array[index]) { 11570 case bcmCosqStatDroppedPackets: 11571 /*swap with position 0*/ 11572 stat_array[index] = stat_array[0]; 11573 stat_array[0] = bcmCosqStatDroppedPackets; 11574 /*fall through*/ 11575 case bcmCosqStatYellowCongestionDroppedPackets: 11576 case bcmCosqStatRedCongestionDroppedPackets: 11577 type = total_drop_mask; 11578 break; 11579 11580 case bcmCosqStatDiscardDroppedPackets: 11581 /*swap with position 0*/ 11582 stat_array[index] = stat_array[0]; 11583 stat_array[0] = bcmCosqStatDiscardDroppedPackets; 11584 /*fall through*/ 11585 case bcmCosqStatGreenDiscardDroppedPackets: 11586 case bcmCosqStatYellowDiscardDroppedPackets: 11587 case bcmCosqStatRedDiscardDroppedPackets: 11588 type = wred_drop_mask; 11589 break; 11590 case bcmCosqStatOutPackets : 11591 break; 11592 default: 11593 return BCM_E_PARAM; 11594 } 11595 if (stat_array[index] != bcmCosqStatOutPackets) { 11596 if (drop_type != default_drop_mask) { 11597 if (BCM_SB2_COSQ_CHECK_STAT_TYPE(drop_type,type)) { 11598 return BCM_E_PARAM; 11599 } 11600 } 11601 else { 11602 drop_type = type; 11603 } 11604 } 11605 11606 } 11607 /* 11608 * populate the configuration variable. 11609 * we need to configure super set first 11610 */ 11611 _bcm_kt2_flex_config_set (unit, stat_array, stat_count); 11612 11613 /*detaching and disabling the counter threads*/ 11614 rv = soc_counter_detach(unit); 11615 BCM_IF_ERROR_RETURN(rv); 11616 11617 rv = soc_counter_attach(unit); 11618 BCM_IF_ERROR_RETURN(rv); 11619 if (SOC_IS_SABER2(unit)) { 11620 SOC_IF_ERROR_RETURN(soc_saber2_perq_flex_counters_init(unit,drop_type)); 11621 } else { 11622 SOC_IF_ERROR_RETURN(_soc_katana2_perq_flex_counters_init(unit,drop_type)); 11623 } 11624 11625 /*starting the counter thread*/ 11626 SOC_PBMP_CLEAR(pbmp); 11627 for (port = SOC_INFO(unit).cmic_port; 11628 port <= SOC_INFO(unit).lb_port; 11629 port++) { 11630 if (SOC_IS_SABER2(unit) && (!SOC_IS_METROLITE(unit)) && 11631 soc_saber2_port_is_unused(unit, port)) { 11632 continue; 11633 } 11634 if (SOC_INFO(unit).block_valid[SOC_PORT_BLOCK(unit,port)]) { 11635 LOG_VERBOSE(BSL_LS_APPL_SHELL, 11636 (BSL_META_U(unit, 11637 "BlockName:%s \n"), 11638 SOC_BLOCK_NAME(unit, SOC_PORT_BLOCK(unit,port)))); 11639 SOC_PBMP_PORT_ADD(pbmp, port); 11640 } 11641 } 11642 interval = (SAL_BOOT_BCMSIM) ? 11643 SOC_COUNTER_INTERVAL_SIM_DEFAULT : SOC_COUNTER_INTERVAL_DEFAULT; 11644 interval = soc_property_get(unit, spn_BCM_STAT_INTERVAL, interval); 11645 flags = 11646 soc_property_get(unit, spn_BCM_STAT_FLAGS, SOC_COUNTER_F_DMA); 11647 11648 rv = soc_counter_start(unit, flags, interval,pbmp); 11649 BCM_IF_ERROR_RETURN(rv); 11650 11651 /*reset all the previous configured counters*/ 11652 BCM_IF_ERROR_RETURN(_bcm_kt2_init_all_queue_counters(unit)); 11653 return BCM_E_NONE; 11654 } 11655 11656 11657 int bcm_kt2_cosq_stat_config_get (int unit, int stat_count, 11658 bcm_cosq_stat_t *stat_array) 11659 { 11660 _sb2_cosq_counter_mem_map_t *mem_map; 11661 int num_elem, index = 0, elem_size = 4; 11662 uint32 rval; 11663 uint32 drop_type; 11664 uint16 dev_id; 11665 uint8 rev_id; 11666 #ifdef BCM_KATANA2_SUPPORT 11667 uint32 wred_drop_mask, default_drop_mask; 11668 #endif 11669 if (SOC_IS_SABER2(unit)) { 11670 elem_size = 2; 11671 } 11672 soc_cm_get_id(unit, &dev_id, &rev_id); 11673 if ((dev_id == BCM56233_DEVICE_ID) || 11674 (SOC_IS_METROLITE(unit))) { 11675 elem_size = 1; 11676 } 11677 11678 #ifdef BCM_METROLITE_SUPPORT 11679 if (SOC_IS_METROLITE(unit)) { 11680 wred_drop_mask = BCM_ML_COSQ_WRED_DROP_MASK; 11681 default_drop_mask = BCM_ML_COSQ_DEFAULT_DROP_MASK; 11682 } else 11683 #endif 11684 { 11685 wred_drop_mask = BCM_SB2_COSQ_WRED_DROP_MASK; 11686 default_drop_mask = BCM_SB2_COSQ_DEFAULT_DROP_MASK; 11687 } 11688 if ((stat_array == NULL)|| (stat_count != BCM_SB2_COSQ_FLEX_COUNT_SUPPORTED)) { 11689 return BCM_E_PARAM; 11690 } 11691 soc_sb2_cosq_counter_mem_map_get(unit, &num_elem, &mem_map); 11692 11693 /*get the type of THDO counters configured */ 11694 11695 SOC_IF_ERROR_RETURN(READ_THDO_DROP_CTR_CONFIGr(unit, &rval)); 11696 drop_type = soc_reg_field_get(unit, THDO_DROP_CTR_CONFIGr, rval, OP_DROP_MASKf); 11697 11698 for (index = 0; index < num_elem; index+= elem_size) { 11699 switch (mem_map[index].non_dma_id) { 11700 case SOC_COUNTER_NON_DMA_COSQ_DROP_PKT: 11701 if ((drop_type & default_drop_mask) == wred_drop_mask ) { 11702 stat_array[index/elem_size] = bcmCosqStatDiscardDroppedPackets; 11703 } else { 11704 stat_array[index/elem_size] = bcmCosqStatDroppedPackets; 11705 } 11706 break; 11707 11708 case SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_YELLOW: 11709 if ((drop_type & default_drop_mask) == wred_drop_mask) { 11710 stat_array[index/elem_size] = bcmCosqStatYellowDiscardDroppedPackets; 11711 } else { 11712 stat_array[index/elem_size] = bcmCosqStatYellowCongestionDroppedPackets; 11713 } 11714 break; 11715 11716 case SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_RED: 11717 if ((drop_type & default_drop_mask) == wred_drop_mask) { 11718 stat_array[index/elem_size] = bcmCosqStatRedDiscardDroppedPackets; 11719 } else { 11720 stat_array[index/elem_size] = bcmCosqStatRedCongestionDroppedPackets; 11721 } 11722 break; 11723 11724 case SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_GREEN: 11725 if ((drop_type & default_drop_mask) == wred_drop_mask) { 11726 stat_array[index/elem_size] = bcmCosqStatGreenDiscardDroppedPackets; 11727 } 11728 break; 11729 11730 case SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT: 11731 stat_array[index/elem_size] = bcmCosqStatOutPackets; 11732 break; 11733 default: 11734 break; 11735 } 11736 } 11737 return BCM_E_NONE; 11738 } 11739 11740 #endif 11741 11742 int bcm_kt2_cosq_port_get(int unit, int queue_id, bcm_port_t *port) 11743 { 11744 _bcm_kt2_mmu_info_t *mmu_info; 11745 lls_l0_parent_entry_t l0_parent; 11746 lls_l1_parent_entry_t l1_parent; 11747 lls_l2_parent_entry_t l2_parent; 11748 egr_queue_to_pp_port_map_entry_t pp_port_map; 11749 int index; 11750 int ctype; 11751 int rv = BCM_E_NONE; 11752 11753 if (_bcm_kt2_mmu_info[unit] == NULL) { 11754 return BCM_E_INIT; 11755 } 11756 11757 mmu_info = _bcm_kt2_mmu_info[unit]; 11758 11759 if (queue_id >= mmu_info->num_queues) { 11760 return BCM_E_PARAM; 11761 } 11762 11763 SOC_IF_ERROR_RETURN 11764 (READ_LLS_L2_PARENTm(unit, MEM_BLOCK_ALL, queue_id, &l2_parent)); 11765 index = soc_mem_field32_get(unit, LLS_L2_PARENTm, &l2_parent, C_PARENTf); 11766 11767 SOC_IF_ERROR_RETURN 11768 (READ_LLS_L1_PARENTm(unit, MEM_BLOCK_ALL, index, &l1_parent)); 11769 index = soc_mem_field32_get(unit, LLS_L1_PARENTm, &l1_parent, C_PARENTf); 11770 11771 SOC_IF_ERROR_RETURN 11772 (READ_LLS_L0_PARENTm(unit, MEM_BLOCK_ALL, index, &l0_parent)); 11773 11774 /* 11775 * Ctype 1 indicates parent is a port, 0 indicates parent is an s1. 11776 */ 11777 ctype = soc_mem_field32_get(unit, LLS_L0_PARENTm, &l0_parent, C_TYPEf);; 11778 if (ctype) { 11779 *port = soc_mem_field32_get(unit, LLS_L0_PARENTm, 11780 &l0_parent, C_PARENTf); 11781 } else { 11782 /* 11783 * Get the subport that this queue is associated with. 11784 */ 11785 SOC_IF_ERROR_RETURN 11786 (READ_EGR_QUEUE_TO_PP_PORT_MAPm(unit, MEM_BLOCK_ALL, 11787 queue_id, &pp_port_map)); 11788 *port = soc_mem_field32_get(unit, EGR_QUEUE_TO_PP_PORT_MAPm, 11789 &pp_port_map, PP_PORTf); 11790 } 11791 11792 return rv; 11793 } 11794 11795 #ifdef BCM_WARM_BOOT_SUPPORT 11796 11797 #define BCM_WB_VERSION_1_0 SOC_SCACHE_VERSION(1,0) 11798 #define BCM_WB_VERSION_1_1 SOC_SCACHE_VERSION(1,1) 11799 #define BCM_WB_VERSION_1_2 SOC_SCACHE_VERSION(1,2) 11800 #define BCM_WB_VERSION_1_3 SOC_SCACHE_VERSION(1,3) 11801 #define BCM_WB_VERSION_1_4 SOC_SCACHE_VERSION(1,4) 11802 #define BCM_WB_VERSION_1_5 SOC_SCACHE_VERSION(1,5) 11803 #define BCM_WB_VERSION_1_6 SOC_SCACHE_VERSION(1,6) 11804 #define BCM_WB_VERSION_1_7 SOC_SCACHE_VERSION(1,7) 11805 #define BCM_WB_VERSION_1_8 SOC_SCACHE_VERSION(1,8) 11806 #define BCM_WB_DEFAULT_VERSION BCM_WB_VERSION_1_8 11807 11808 #define _BCM_KT2_COSQ_WB_END_NODE_VALUE 0xffffffff 11809 11810 #define _BCM_KT2_COSQ_WB_NODE_COSQ_MASK 0x3f /* LW-1 [5:0] */ 11811 #define _BCM_KT2_COSQ_WB_NODE_COSQ_SHIFT 0 11812 #define _BCM_KT2_COSQ_WB_NODE_NUMQ_MASK 0x3f /* LW-1 [11:6] */ 11813 #define _BCM_KT2_COSQ_WB_NODE_NUMQ_SHIFT 6 11814 #define _BCM_KT2_COSQ_WB_NODE_HW_INDEX_MASK 0xfff /* LW-1 [23:12] */ 11815 #define _BCM_KT2_COSQ_WB_NODE_HW_INDEX_SHIFT 12 11816 #define _BCM_KT2_COSQ_WB_NODE_LEVEL_MASK 0x7 /* LW-1 [26:24] */ 11817 #define _BCM_KT2_COSQ_WB_NODE_LEVEL_SHIFT 24 11818 #define _BCM_KT2_COSQ_WB_NODE_WRR_MASK 0x1 /* LW-1 [27] */ 11819 #define _BCM_KT2_COSQ_WB_NODE_WRR_SHIFT 27 11820 #define _BCM_KT2_COSQ_WB_NODE_SUBPORT_MASK 0x1 /* LW-1 [28] */ 11821 #define _BCM_KT2_COSQ_WB_NODE_SUBPORT_SHIFT 28 11822 #define _BCM_KT2_COSQ_WB_NODE_LINKPHY_MASK 0x1 /* LW-1 [29] */ 11823 #define _BCM_KT2_COSQ_WB_NODE_LINKPHY_SHIFT 29 11824 #define _BCM_KT2_COSQ_WB_NODE_IDBASED_MASK 0x1 /* LW-1 [30] */ 11825 #define _BCM_KT2_COSQ_WB_NODE_IDBASED_SHIFT 30 11826 #define _BCM_KT2_COSQ_WB_NODE_NUMQ_MAX_MASK 0x1 /* LW-1 [31] */ 11827 #define _BCM_KT2_COSQ_WB_NODE_NUMQ_MAX_SHIFT 31 11828 11829 #define _BCM_KT2_COSQ_WB_NUM_COS_MASK 0xf /* [3:0] */ 11830 #define _BCM_KT2_COSQ_WB_NUM_COS_SHIFT 0 11831 11832 #define _BCM_KT2_COSQ_WB_NODE_TYPE_MASK 0xf 11833 #define _BCM_KT2_COSQ_WB_NODE_TYPE_SHIFT 0 /*[0:3] 8*/ 11834 #define _BCM_KT2_COSQ_WB_NODE_WRR_MODE_MASK 0x1 11835 #define _BCM_KT2_COSQ_WB_NODE_WRR_MODE_SHIFT 4 /*[4]*/ 11836 #define _BCM_KT2_COSQ_WB_NODE_WRED_DISABLE_MASK 0x1 11837 #define _BCM_KT2_COSQ_WB_NODE_WRED_DISABLE_SHIFT 5 /*[5]*/ 11838 #define _BCM_KT2_COSQ_WB_NODE_BW_BURST_CAL_MASK 0x1 11839 #define _BCM_KT2_COSQ_WB_NODE_BW_BURST_CAL_SHIFT 6 /*[6]*/ 11840 11841 #define SET_FIELD(_field, _value) \ 11842 (((_value) & _BCM_KT2_COSQ_WB_## _field## _MASK) << \ 11843 _BCM_KT2_COSQ_WB_## _field## _SHIFT) 11844 #define GET_FIELD(_field, _byte) \ 11845 (((_byte) >> _BCM_KT2_COSQ_WB_## _field## _SHIFT) & \ 11846 _BCM_KT2_COSQ_WB_## _field## _MASK) 11847 11848 #define _BCM_KT2_NODE_TYPE_WRR_SET(ptr, node) \ 11849 do {*((uint8 *)ptr) = node->type; \ 11850 *((uint8 *)ptr) |= (node->wrr_mode << _BCM_KT2_COSQ_WB_NODE_WRR_MODE_SHIFT);\ 11851 }while(0); 11852 11853 #define _BCM_KT2_NODE_WRED_DISABLE_SET(ptr, node) \ 11854 do {\ 11855 *((uint8 *)ptr) |= ((node->wred_disabled & _BCM_KT2_COSQ_WB_NODE_WRED_DISABLE_MASK)\ 11856 << _BCM_KT2_COSQ_WB_NODE_WRED_DISABLE_SHIFT);\ 11857 }while(0); 11858 11859 #define _BCM_KT2_NODE_BW_BURST_CAL_SET(ptr, node) \ 11860 do {\ 11861 *((uint8 *)ptr) |= ((node->burst_calculation_enable & _BCM_KT2_COSQ_WB_NODE_BW_BURST_CAL_MASK)\ 11862 << _BCM_KT2_COSQ_WB_NODE_BW_BURST_CAL_SHIFT);\ 11863 }while(0); 11864 11865 #define _BCM_KT2_NODE_TYPE_WRR_GET(ptr, node) \ 11866 do { node->type = ((*(uint8 *)ptr) & _BCM_KT2_COSQ_WB_NODE_TYPE_MASK); \ 11867 node->wrr_mode = ((*(uint8 *)ptr) >> _BCM_KT2_COSQ_WB_NODE_WRR_MODE_SHIFT);\ 11868 }while(0); 11869 11870 #define _BCM_KT2_NODE_WRED_DISABLE_GET(ptr, node) \ 11871 do {\ 11872 node->wred_disabled = (((*(uint8 *)ptr) >> _BCM_KT2_COSQ_WB_NODE_WRED_DISABLE_SHIFT) \ 11873 & _BCM_KT2_COSQ_WB_NODE_WRED_DISABLE_MASK);\ 11874 }while(0); 11875 11876 #define _BCM_KT2_NODE_BW_BURST_CAL_GET(ptr, node) \ 11877 do {\ 11878 node->burst_calculation_enable = (((*(uint8 *)ptr) >> _BCM_KT2_COSQ_WB_NODE_BW_BURST_CAL_SHIFT) \ 11879 & _BCM_KT2_COSQ_WB_NODE_BW_BURST_CAL_MASK);\ 11880 }while(0); 11881 11882 /* 11883 * This funtion encodes the 1 byte of the common data to be written in to 11884 * scache.Currently only last 4 bits of the byte are used for storing 11885 * num_cos value rest can be used if necessary later. 11886 */ 11887 STATIC void 11888 _bcm_kt2_cosq_wb_encode_data(int unit, uint8 *scache_ptr) 11889 { 11890 uint8 data = 0; 11891 int numq = 0; 11892 bcm_kt2_cosq_config_get(unit,&numq); 11893 data = SET_FIELD(NUM_COS, numq); 11894 *scache_ptr = data; 11895 } 11896 11897 STATIC int 11898 _bcm_kt2_cosq_wb_alloc(int unit) 11899 { 11900 soc_scache_handle_t scache_handle; 11901 uint8 *scache_ptr; 11902 _bcm_kt2_mmu_info_t *mmu_info; 11903 int rv, alloc_size; 11904 11905 mmu_info = _bcm_kt2_mmu_info[unit]; 11906 11907 alloc_size = 0; 11908 alloc_size += sizeof(mmu_info->num_base_queues); 11909 alloc_size += sizeof(mmu_info->num_ext_queues); 11910 alloc_size += sizeof(mmu_info->qset_size); 11911 alloc_size += sizeof(mmu_info->num_queues); 11912 alloc_size += sizeof(mmu_info->num_nodes); 11913 alloc_size += sizeof(mmu_info->max_nodes); 11914 alloc_size += (num_total_schedulers[unit] * sizeof(uint32) * 3); 11915 alloc_size += (num_l2_queues[unit] * sizeof(uint32) * 2); 11916 alloc_size += sizeof(uint32); 11917 11918 /* Following is the addition memory for Version 1_1 */ 11919 11920 /* Allocating memory for storing fabric_pbmp and we require 11921 fabric_pbmp only for l2 nodes*/ 11922 alloc_size += (num_l2_queues[unit] * sizeof(bcm_pbmp_t)); 11923 /* Allocating memory for storing remote_modid and we require 11924 remote_modid only for l2 nodes*/ 11925 alloc_size += (num_l2_queues[unit] * sizeof(uint32)); 11926 /* Allocating memory for storing fabric_modid and we require 11927 fabric_modid only for l2 nodes*/ 11928 alloc_size += (num_l2_queues[unit] * sizeof(uint32)); 11929 /* Allocating memory for storing curr_merger_index */ 11930 alloc_size += (4 * sizeof(int)); 11931 /* Storing the _BCM_KT2_COSQ_WB_END_NODE_VALUE */ 11932 alloc_size += sizeof(uint32); 11933 /* Storing NUM_COS */ 11934 alloc_size += sizeof(uint8); 11935 11936 /* Allocating memory for storing the multicast mc base index 11937 for the L1 nodes*/ 11938 alloc_size += (num_l1_schedulers[unit] * sizeof(uint32)); 11939 /* Storing the _BCM_KT2_COSQ_WB_END_NODE_VALUE */ 11940 alloc_size += sizeof(uint32); 11941 /* Allocating memory for storing the IFP_COS_MAP refcount */ 11942 alloc_size += (4 * sizeof(uint32)); 11943 /* Storing the _BCM_KT2_COSQ_WB_END_NODE_VALUE */ 11944 alloc_size += sizeof(uint32); 11945 11946 /*Storing the COSQ_STAT_CONFIG*/ 11947 alloc_size += (sizeof(bcm_cosq_stat_t)* 3); 11948 11949 /*Storing the node data*/ 11950 alloc_size += sizeof(uint8)*(num_total_schedulers[unit] + num_l2_queues[unit]); 11951 11952 /* Storing interface reference count for all queues */ 11953 alloc_size += (BCM_MULTICAST_PORT_MAX * sizeof(uint32)); 11954 11955 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_COSQ, 0); 11956 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, TRUE, alloc_size, 11957 &scache_ptr, BCM_WB_DEFAULT_VERSION, NULL); 11958 if (rv == BCM_E_NOT_FOUND) { 11959 rv = BCM_E_NONE; 11960 } 11961 11962 return rv; 11963 } 11964 11965 STATIC uint32 11966 _bcm_kt2_cosq_wb_encode_node(int unit, _bcm_kt2_cosq_node_t *node) 11967 { 11968 uint32 data = 0; 11969 int max_numq; 11970 11971 data = SET_FIELD(NODE_COSQ, node->cosq_attached_to); 11972 data |= SET_FIELD(NODE_NUMQ, node->numq); 11973 max_numq = ((1 << _BCM_KT2_COSQ_WB_NODE_NUMQ_SHIFT) - 1); 11974 if (node->numq > max_numq) { 11975 data |= SET_FIELD(NODE_NUMQ_MAX, 1); 11976 } 11977 data |= SET_FIELD(NODE_LEVEL, node->level); 11978 data |= SET_FIELD(NODE_HW_INDEX, node->hw_index); 11979 data |= SET_FIELD(NODE_WRR, node->wrr_in_use); 11980 data |= SET_FIELD(NODE_SUBPORT, node->subport_enabled); 11981 data |= SET_FIELD(NODE_LINKPHY, node->linkphy_enabled); 11982 if (node->level == _BCM_KT2_COSQ_NODE_LEVEL_L2) { 11983 if ((node->type == _BCM_KT2_NODE_VOQ_ID) || 11984 (node->type == _BCM_KT2_NODE_SUBSCRIBER_GPORT_ID)) { 11985 data |= SET_FIELD(NODE_IDBASED, 1); 11986 } 11987 } 11988 11989 return data; 11990 } 11991 11992 STATIC int 11993 _bcm_kt2_cosq_update_scache(int unit, uint8 *scache_ptr, 11994 _bcm_kt2_cosq_node_t *node, int *length) 11995 { 11996 uint8 *ptr; 11997 uint32 node_data; 11998 bcm_gport_t sub_gport = 0; 11999 int id; 12000 int port = 0; 12001 _bcm_kt2_mmu_info_t *mmu_info; 12002 12003 ptr = scache_ptr; 12004 mmu_info = _bcm_kt2_mmu_info[unit]; 12005 12006 if (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(node->gport)){ 12007 id = BCM_GPORT_UCAST_SUBSCRIBER_QUEUE_GROUP_QID_GET(node->gport); 12008 if(mmu_info->num_sub_queues) { 12009 id += mmu_info->base_sub_queue; 12010 } 12011 port = BCM_GPORT_UCAST_SUBSCRIBER_QUEUE_GROUP_SYSPORTID_GET(node->gport); 12012 BCM_GPORT_UCAST_SUBSCRIBER_QUEUE_GROUP_SYSQID_SET(sub_gport, port, id); 12013 *(((uint32 *)ptr)) = sub_gport; 12014 ptr += sizeof(uint32); 12015 } else if (BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(node->gport)){ 12016 id = BCM_GPORT_MCAST_SUBSCRIBER_QUEUE_GROUP_QID_GET(node->gport); 12017 if(mmu_info->num_sub_queues) { 12018 id += mmu_info->base_sub_queue; 12019 } 12020 port = 12021 BCM_GPORT_MCAST_SUBSCRIBER_QUEUE_GROUP_SYSPORTID_GET(node->gport); 12022 BCM_GPORT_MCAST_SUBSCRIBER_QUEUE_GROUP_SYSQID_SET(sub_gport, port, id); 12023 *(((uint32 *)ptr)) = sub_gport; 12024 ptr += sizeof(uint32); 12025 } else { 12026 *(((uint32 *)ptr)) = node->gport; 12027 ptr += sizeof(uint32); 12028 } 12029 12030 node_data = _bcm_kt2_cosq_wb_encode_node(unit, node); 12031 *(((uint32 *)ptr)) = node_data; 12032 ptr += sizeof(uint32); 12033 12034 if (node->level != _BCM_KT2_COSQ_NODE_LEVEL_L2) { 12035 *(((uint32 *)ptr)) = node->base_index; 12036 ptr += sizeof(uint32); 12037 } 12038 12039 *length = ptr - scache_ptr; 12040 return BCM_E_NONE; 12041 } 12042 12043 STATIC int 12044 _bcm_kt2_cosq_update_l0_tree(int unit, uint8 *scache_ptr, 12045 _bcm_kt2_cosq_node_t *node, 12046 int *length) 12047 { 12048 uint8 *ptr; 12049 _bcm_kt2_cosq_node_t *l0_node, *l1_node, *l2_node; 12050 int inc; 12051 12052 ptr = scache_ptr; 12053 12054 for (l0_node = node; l0_node != NULL; 12055 l0_node = l0_node->sibling) { 12056 BCM_IF_ERROR_RETURN 12057 (_bcm_kt2_cosq_update_scache(unit, ptr, l0_node, &inc)); 12058 ptr += inc; 12059 12060 for (l1_node = l0_node->child; l1_node != NULL; 12061 l1_node = l1_node->sibling) { 12062 BCM_IF_ERROR_RETURN 12063 (_bcm_kt2_cosq_update_scache(unit, ptr, l1_node, &inc)); 12064 ptr += inc; 12065 12066 for (l2_node = l1_node->child; l2_node != NULL; 12067 l2_node = l2_node->sibling) { 12068 BCM_IF_ERROR_RETURN 12069 (_bcm_kt2_cosq_update_scache(unit, ptr, l2_node, &inc)); 12070 ptr += inc; 12071 } 12072 } 12073 } 12074 12075 *length = ptr - scache_ptr; 12076 return BCM_E_NONE; 12077 } 12078 12079 12080 int 12081 bcm_kt2_cosq_sync(int unit) 12082 { 12083 soc_scache_handle_t scache_handle; 12084 uint8 *scache_ptr, *ptr; 12085 _bcm_kt2_mmu_info_t *mmu_info; 12086 _bcm_kt2_cosq_node_t *port_node, *l0_node; 12087 _bcm_kt2_cosq_node_t *s0_node, *s1_node; 12088 bcm_port_t port; 12089 int i, inc; 12090 _bcm_kt2_cosq_node_t *l1_node, *l2_node; 12091 soc_info_t *si; 12092 uint32 profile_index; 12093 int ref_count; 12094 12095 #ifdef BCM_KATANA2_SUPPORT 12096 bcm_cosq_stat_t stat_array[BCM_SB2_COSQ_FLEX_COUNT_SUPPORTED]; 12097 #endif 12098 si = &SOC_INFO(unit); 12099 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_COSQ, 0); 12100 BCM_IF_ERROR_RETURN 12101 (_bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 0, 12102 &scache_ptr, BCM_WB_DEFAULT_VERSION, NULL)); 12103 12104 if (_bcm_kt2_mmu_info[unit] == NULL) { 12105 return BCM_E_INIT; 12106 } 12107 12108 mmu_info = _bcm_kt2_mmu_info[unit]; 12109 12110 ptr = scache_ptr; 12111 12112 *(((uint32 *)ptr)) = mmu_info->num_base_queues; 12113 ptr += sizeof(uint32); 12114 12115 12116 *(((uint32 *)ptr)) = mmu_info->num_ext_queues; 12117 ptr += sizeof(uint32); 12118 12119 *(((uint32 *)ptr)) = mmu_info->qset_size; 12120 ptr += sizeof(uint32); 12121 12122 *(((uint32 *)ptr)) = mmu_info->num_queues; 12123 ptr += sizeof(uint32); 12124 12125 *(((uint32 *)ptr)) = mmu_info->num_nodes; 12126 ptr += sizeof(uint32); 12127 12128 for (i = 0; i < _BCM_KT2_COSQ_NODE_LEVEL_MAX; i++) { 12129 *(((uint32 *)ptr)) = mmu_info->max_nodes[i]; 12130 ptr += sizeof(uint32); 12131 } 12132 12133 for (port = 0; port < (si->lb_port + 1) ; port++) { 12134 if (SOC_IS_SABER2(unit) && (!SOC_IS_METROLITE(unit)) && 12135 soc_saber2_port_is_unused(unit, port)) { 12136 continue; 12137 } 12138 port_node = &mmu_info->sched_node[port]; 12139 12140 if (port_node->cosq_attached_to < 0) { 12141 continue; 12142 } 12143 12144 if (port_node->child != NULL) { 12145 BCM_IF_ERROR_RETURN 12146 (_bcm_kt2_cosq_update_scache(unit, ptr, port_node, &inc)); 12147 ptr += inc; 12148 } 12149 12150 s0_node = port_node->child; 12151 if (s0_node != NULL && 12152 s0_node->level == _BCM_KT2_COSQ_NODE_LEVEL_S0) { 12153 for (s0_node = port_node->child; s0_node != NULL; 12154 s0_node = s0_node->sibling) { 12155 BCM_IF_ERROR_RETURN 12156 (_bcm_kt2_cosq_update_scache(unit, ptr, s0_node, &inc)); 12157 ptr += inc; 12158 12159 s1_node = s0_node->child; 12160 if (s1_node != NULL && 12161 s1_node->level == _BCM_KT2_COSQ_NODE_LEVEL_S1) { 12162 for (s1_node = s0_node->child; s1_node != NULL; 12163 s1_node = s1_node->sibling) { 12164 BCM_IF_ERROR_RETURN 12165 (_bcm_kt2_cosq_update_scache(unit, ptr, s1_node, &inc)); 12166 ptr += inc; 12167 for (l0_node = s1_node->child; l0_node != NULL; 12168 l0_node = l0_node->sibling) { 12169 BCM_IF_ERROR_RETURN 12170 (_bcm_kt2_cosq_update_l0_tree(unit, ptr, l0_node, &inc)); 12171 ptr += inc; 12172 } 12173 } 12174 } else { 12175 l0_node = s1_node; 12176 BCM_IF_ERROR_RETURN 12177 (_bcm_kt2_cosq_update_l0_tree(unit, ptr, l0_node, &inc)); 12178 ptr += inc; 12179 } 12180 } 12181 } else { 12182 l0_node = port_node->child; 12183 BCM_IF_ERROR_RETURN 12184 (_bcm_kt2_cosq_update_l0_tree(unit, ptr, l0_node, &inc)); 12185 ptr += inc; 12186 } 12187 } 12188 12189 *(((uint32 *)ptr)) = _BCM_KT2_COSQ_WB_END_NODE_VALUE; 12190 12191 ptr += sizeof(uint32) ; 12192 12193 for (i = 0; i < 4; i++) { 12194 *(((uint32 *)ptr)) = mmu_info->curr_merger_index[i]; 12195 ptr += sizeof(uint32); 12196 } 12197 12198 PBMP_ALL_ITER(unit, port) { 12199 if (!(IS_HG_PORT(unit, port)|| IS_HL_PORT(unit, port))) { 12200 continue; 12201 } 12202 port_node = &mmu_info->sched_node[port]; 12203 12204 if (port_node->cosq_attached_to < 0) { 12205 continue; 12206 } 12207 12208 s0_node = port_node->child; 12209 if (s0_node != NULL && 12210 s0_node->level == _BCM_KT2_COSQ_NODE_LEVEL_S0) { 12211 continue; 12212 } else { 12213 l0_node = port_node->child; 12214 for (; l0_node != NULL; 12215 l0_node = l0_node->sibling) { 12216 for (l1_node = l0_node->child; l1_node != NULL; 12217 l1_node = l1_node->sibling) { 12218 for (l2_node = l1_node->child; l2_node != NULL; 12219 l2_node = l2_node->sibling) { 12220 sal_memcpy(ptr, &l2_node->fabric_pbmp, sizeof(bcm_pbmp_t)); 12221 ptr += sizeof(bcm_pbmp_t); 12222 *(((uint32 *)ptr)) = l2_node->remote_modid; 12223 ptr += sizeof(uint32); 12224 *(((uint32 *)ptr)) = l2_node->fabric_modid; 12225 ptr += sizeof(uint32); 12226 } 12227 } 12228 } 12229 } 12230 } 12231 *(((uint32 *)ptr)) = _BCM_KT2_COSQ_WB_END_NODE_VALUE; 12232 ptr += sizeof(uint32); 12233 12234 /* add NUM_COS to the scache */ 12235 _bcm_kt2_cosq_wb_encode_data( unit, (uint8 *)ptr); 12236 ptr += sizeof(uint8); 12237 12238 /* Store the mc base index for L1 node */ 12239 PBMP_ALL_ITER(unit, port) { 12240 #ifdef BCM_METROLITE_SUPPORT 12241 if (SOC_IS_METROLITE(unit)) { 12242 if((soc_property_get(unit, spn_SAT_ENABLE, 0) != 0) && 12243 (port == SOC_SB2_SAT_OAMP_PHY_PORT_NUMBER)) { 12244 /* no need to store SAT port*/ 12245 continue; 12246 } 12247 } 12248 #endif 12249 port_node = &mmu_info->sched_node[port]; 12250 12251 if (port_node->cosq_attached_to < 0) { 12252 continue; 12253 } 12254 if (!port_node->child) { 12255 continue; 12256 } 12257 s0_node = (port_node->child->level == _BCM_KT2_COSQ_NODE_LEVEL_S0) ? 12258 port_node->child : port_node; 12259 12260 do { 12261 s1_node = (s0_node->child->level == _BCM_KT2_COSQ_NODE_LEVEL_S1) ? 12262 s0_node->child : s0_node; 12263 do { 12264 for (l0_node = s1_node->child; 12265 l0_node != NULL; 12266 l0_node = l0_node->sibling) { 12267 for (l1_node = l0_node->child; 12268 l1_node != NULL; 12269 l1_node = l1_node->sibling) { 12270 *(((uint32 *)ptr)) = l1_node->mc_base_index; 12271 ptr += sizeof(uint32); 12272 12273 } 12274 } 12275 if (s1_node == s0_node) { 12276 break; 12277 } 12278 /* It comes here 12279 only in case s1 is valid */ 12280 s1_node = s1_node->sibling; 12281 } while (s1_node != NULL); 12282 if (s0_node == port_node) { 12283 break; 12284 } 12285 /* It comes here 12286 only in case s0 is valid */ 12287 s0_node = s0_node->sibling; 12288 } while (s0_node != NULL); 12289 12290 } 12291 12292 *(((uint32 *)ptr)) = _BCM_KT2_COSQ_WB_END_NODE_VALUE; 12293 12294 ptr += sizeof(uint32); 12295 for (profile_index = 0 ; profile_index < 4 ; profile_index++) { 12296 BCM_IF_ERROR_RETURN (soc_profile_mem_ref_count_get(unit, 12297 _bcm_kt2_ifp_cos_map_profile[unit], 12298 (profile_index * 16), &ref_count)); 12299 *(((uint32 *)ptr)) = ref_count; 12300 ptr += sizeof(uint32); 12301 } 12302 12303 *(((uint32 *)ptr)) = _BCM_KT2_COSQ_WB_END_NODE_VALUE; 12304 12305 /*saving the counter values*/ 12306 #ifdef BCM_KATANA2_SUPPORT 12307 if (SOC_IS_KATANA2(unit)) { 12308 bcm_kt2_cosq_stat_config_get(unit, BCM_SB2_COSQ_FLEX_COUNT_SUPPORTED, stat_array); 12309 for (profile_index = 0; profile_index < 3; profile_index++) { 12310 *(((uint32 *)ptr)) = stat_array[profile_index]; 12311 ptr += sizeof(uint32); 12312 } 12313 } 12314 else { 12315 ptr += (sizeof(uint32) * 3); 12316 } 12317 #else 12318 ptr += (sizeof(uint32) * 3); 12319 #endif 12320 12321 PBMP_ALL_ITER(unit, port) { 12322 port_node = &mmu_info->sched_node[port]; 12323 if (port_node->cosq_attached_to < 0) { 12324 continue; 12325 } 12326 _BCM_KT2_NODE_TYPE_WRR_SET(ptr, port_node); 12327 _BCM_KT2_NODE_BW_BURST_CAL_SET(ptr, port_node); 12328 ptr += sizeof(uint8); 12329 s0_node = port_node->child; 12330 if (s0_node != NULL && 12331 s0_node->level == _BCM_KT2_COSQ_NODE_LEVEL_S0) { 12332 continue; 12333 } else { 12334 /*copy the node type to the node*/ 12335 for (l0_node = port_node->child;l0_node != NULL; 12336 l0_node = l0_node->sibling) { 12337 /*copy the node type to the node*/ 12338 _BCM_KT2_NODE_TYPE_WRR_SET(ptr, l0_node); 12339 _BCM_KT2_NODE_BW_BURST_CAL_SET(ptr, port_node); 12340 ptr += sizeof(uint8); 12341 for (l1_node = l0_node->child; l1_node != NULL; 12342 l1_node = l1_node->sibling) { 12343 /*copy the node type to the node*/ 12344 _BCM_KT2_NODE_TYPE_WRR_SET(ptr, l1_node); 12345 _BCM_KT2_NODE_BW_BURST_CAL_SET(ptr, port_node); 12346 ptr += sizeof(uint8); 12347 for (l2_node = l1_node->child; l2_node != NULL; 12348 l2_node = l2_node->sibling) { 12349 /*copy the node type to the node*/ 12350 _BCM_KT2_NODE_TYPE_WRR_SET(ptr,l2_node); 12351 _BCM_KT2_NODE_BW_BURST_CAL_SET(ptr, port_node); 12352 _BCM_KT2_NODE_WRED_DISABLE_SET(ptr,l2_node); 12353 ptr += sizeof(uint8); 12354 } 12355 } 12356 } 12357 } 12358 } 12359 12360 /* copy interface reference count values for all queues into scache ptr */ 12361 sal_memcpy(ptr, mmu_info->intf_ref_cnt, 12362 (sizeof(uint32) * BCM_MULTICAST_PORT_MAX)); 12363 ptr += (sizeof(uint32) * BCM_MULTICAST_PORT_MAX); 12364 return BCM_E_NONE; 12365 } 12366 12367 /* 12368 * Function: 12369 * _bcm_kt2_cosq_map_alloc_set 12370 * Purpose: 12371 * Allocate the cosq_map bitmap and 12372 * restore 12373 * Parameters: 12374 * node - (IN) cosq_node 12375 * Returns: 12376 * BCM_E_XXX 12377 */ 12378 STATIC int 12379 _bcm_kt2_cosq_map_alloc_set(_bcm_kt2_cosq_node_t *node) 12380 { 12381 _bcm_kt2_cosq_node_t *child; 12382 int alloc_size; 12383 if (node->cosq_map == NULL) { 12384 alloc_size = SHR_BITALLOCSIZE(node->numq); 12385 node->cosq_map = _bcm_kt2_cosq_alloc_clear(alloc_size, 12386 "node->cosq_map"); 12387 if (node->cosq_map == NULL) { 12388 return BCM_E_MEMORY; 12389 } 12390 } 12391 child = node->child; 12392 while (child != NULL) { 12393 BCM_IF_ERROR_RETURN 12394 (_bcm_kt2_cosq_map_index_set(node->cosq_map, 12395 child->cosq_attached_to, 1)); 12396 child = child->sibling; 12397 } 12398 12399 return BCM_E_NONE; 12400 } 12401 12402 /* 12403 * Function: 12404 * _bcm_kt2_cosq_map_recover_next_level_node 12405 * Purpose: 12406 * Used to recover cos_map for S0,S1,L0,L1 levels 12407 * Parameters: 12408 * node - (IN) cosq_node 12409 * Returns: 12410 * BCM_E_XXX 12411 */ 12412 12413 STATIC int 12414 _bcm_kt2_cosq_map_recover_next_level_node(_bcm_kt2_cosq_node_t *node) 12415 { 12416 if (!node) { 12417 return BCM_E_NONE; 12418 } 12419 if (node->level == _BCM_KT2_COSQ_NODE_LEVEL_L2) { 12420 return BCM_E_NONE; 12421 } 12422 BCM_IF_ERROR_RETURN(_bcm_kt2_cosq_map_alloc_set(node)); 12423 BCM_IF_ERROR_RETURN(_bcm_kt2_cosq_map_recover_next_level_node(node->sibling)); 12424 BCM_IF_ERROR_RETURN(_bcm_kt2_cosq_map_recover_next_level_node(node->child)); 12425 return BCM_E_NONE; 12426 } 12427 12428 int 12429 bcm_kt2_cosq_reinit(int unit) 12430 { 12431 soc_scache_handle_t scache_handle; 12432 uint8 *scache_ptr, *ptr; 12433 _bcm_kt2_cosq_node_t *port_info; 12434 _bcm_kt2_mmu_info_t *mmu_info; 12435 _bcm_kt2_cosq_node_t *port_node = NULL; 12436 _bcm_kt2_cosq_node_t *queue_node = NULL; 12437 _bcm_kt2_cosq_node_t *node = NULL; 12438 _bcm_kt2_cosq_node_t *temp_node = NULL; 12439 _bcm_kt2_cosq_node_t *s0_node = NULL; 12440 _bcm_kt2_cosq_node_t *s1_node = NULL; 12441 _bcm_kt2_cosq_node_t *l0_node = NULL; 12442 _bcm_kt2_cosq_node_t *l1_node = NULL; 12443 _bcm_kt2_cosq_node_t *tmp_node = NULL; 12444 uint32 *s0_bmap = NULL; 12445 uint32 *s1_bmap = NULL; 12446 uint32 *l0_bmap = NULL; 12447 uint32 *l1_bmap = NULL; 12448 uint32 *l2_bmap = NULL; 12449 int additional_scache_size = 0; 12450 int rv, stable_size = 0; 12451 bcm_port_t port = 0; 12452 bcm_gport_t gport; 12453 int i, index, numq; 12454 uint32 node_data; 12455 uint32 encap_id; 12456 int set_index, cosq; 12457 uint32 entry[SOC_MAX_MEM_WORDS]; 12458 soc_profile_mem_t *profile_mem; 12459 _bcm_kt2_cosq_list_t *list; 12460 _bcm_kt2_cosq_node_t *l2_node; 12461 soc_mem_t mem; 12462 mmu_wred_queue_config_buffer_entry_t qentry; 12463 mmu_wred_queue_config_qentry_entry_t qentry1; 12464 int cpu_hg_index = 0; 12465 bcm_pbmp_t all_pbmp; 12466 bcm_port_t tmp_port = 0; 12467 bcm_gport_t tmp_gport = 0; 12468 uint16 recovered_ver = 0; 12469 int offset = 0; 12470 int node_id_based = 0; 12471 uint8 data; 12472 int num_cos = 0; 12473 soc_profile_reg_t *profile_reg; 12474 soc_reg_t reg; 12475 uint64 rval,index_map; 12476 int mmu_port = 0 ; 12477 uint32 tmp32; 12478 int max_numq; 12479 uint32 refcount = 0, profile_index; 12480 #ifdef BCM_KATANA2_SUPPORT 12481 bcm_cosq_stat_t stat_array[BCM_SB2_COSQ_FLEX_COUNT_SUPPORTED]; 12482 #endif 12483 #ifdef BCM_METROLITE_SUPPORT 12484 uint32 rval32, index_map32; 12485 #endif 12486 SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size)); 12487 if ((stable_size == 0) || (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit))) { 12488 /* COSQ warmboot requires extended scache support i.e. level2 warmboot*/ 12489 return BCM_E_NONE; 12490 } 12491 12492 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_COSQ, 0); 12493 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 0, &scache_ptr, 12494 BCM_WB_DEFAULT_VERSION, &recovered_ver); 12495 if (BCM_FAILURE(rv)) { 12496 return rv; 12497 } 12498 12499 if (_bcm_kt2_mmu_info[unit] == NULL) { 12500 return BCM_E_INIT; 12501 } 12502 12503 mmu_info = _bcm_kt2_mmu_info[unit]; 12504 12505 ptr = scache_ptr; 12506 12507 mmu_info->num_base_queues = *(((uint32 *)ptr)); 12508 ptr += sizeof(uint32); 12509 12510 12511 mmu_info->num_ext_queues = *(((uint32 *)ptr)); 12512 ptr += sizeof(uint32); 12513 12514 mmu_info->qset_size = *(((uint32 *)ptr)); 12515 ptr += sizeof(uint32); 12516 12517 mmu_info->num_queues = *(((uint32 *)ptr)); 12518 ptr += sizeof(uint32); 12519 12520 mmu_info->num_nodes = *(((uint32 *)ptr)); 12521 ptr += sizeof(uint32); 12522 12523 for (i = 0; i < _BCM_KT2_COSQ_NODE_LEVEL_MAX; i++) { 12524 mmu_info->max_nodes[i] = *(((uint32 *)ptr)); 12525 ptr += sizeof(uint32); 12526 } 12527 12528 while (*(((uint32 *)ptr)) != _BCM_KT2_COSQ_WB_END_NODE_VALUE) { 12529 gport = *(((uint32 *)ptr)); 12530 ptr += sizeof(uint32); 12531 node_data = *(((uint32 *)ptr)); 12532 ptr += sizeof(uint32); 12533 12534 if (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport)) { 12535 tmp_port = 0; 12536 tmp_gport = 0; 12537 12538 if (mmu_info->num_sub_queues ==0) { 12539 list = &mmu_info->global_qlist; 12540 } else { 12541 list = &mmu_info->sub_qlist; 12542 } 12543 encap_id = BCM_GPORT_UCAST_SUBSCRIBER_QUEUE_GROUP_QID_GET(gport); 12544 node = &mmu_info->queue_node[encap_id]; 12545 12546 if (mmu_info->num_sub_queues) { 12547 encap_id -= mmu_info->base_sub_queue; 12548 } 12549 tmp_port = BCM_GPORT_UCAST_SUBSCRIBER_QUEUE_GROUP_SYSPORTID_GET(gport); 12550 BCM_GPORT_UCAST_SUBSCRIBER_QUEUE_GROUP_SYSQID_SET(tmp_gport, tmp_port, encap_id); 12551 gport = tmp_gport; 12552 } else if (BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(gport)) { 12553 tmp_port = 0; 12554 tmp_gport = 0; 12555 if (mmu_info->num_sub_queues ==0) { 12556 list = &mmu_info->global_qlist; 12557 } else { 12558 list = &mmu_info->sub_mcqlist; 12559 } 12560 encap_id = BCM_GPORT_MCAST_SUBSCRIBER_QUEUE_GROUP_QID_GET(gport); 12561 node = &mmu_info->queue_node[encap_id]; 12562 12563 if (mmu_info->num_sub_queues) { 12564 encap_id = encap_id - mmu_info->base_sub_queue - mmu_info->num_queues/2; 12565 } 12566 tmp_port = 12567 BCM_GPORT_MCAST_SUBSCRIBER_QUEUE_GROUP_SYSPORTID_GET(gport); 12568 BCM_GPORT_MCAST_SUBSCRIBER_QUEUE_GROUP_SYSQID_SET(tmp_gport, 12569 tmp_port, encap_id); 12570 gport = tmp_gport; 12571 _bcm_kt2_node_index_set(list, encap_id, 1); 12572 } else if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 12573 encap_id = BCM_GPORT_UCAST_QUEUE_GROUP_QID_GET(gport); 12574 node = &mmu_info->queue_node[encap_id]; 12575 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 12576 encap_id = BCM_GPORT_MCAST_QUEUE_GROUP_QID_GET(gport); 12577 node = &mmu_info->queue_node[encap_id]; 12578 } else if (BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) { 12579 encap_id = BCM_GPORT_DESTMOD_QUEUE_GROUP_QID_GET(gport); 12580 if (mmu_info->num_dmvoq_queues ==0) { 12581 list = &mmu_info->global_qlist; 12582 } else { 12583 list = &mmu_info->dmvoq_qlist; 12584 } 12585 if (mmu_info->num_dmvoq_queues == 1) { 12586 encap_id += mmu_info->base_dmvoq_queue; 12587 } 12588 node = &mmu_info->queue_node[encap_id]; 12589 } else { 12590 encap_id = (BCM_GPORT_SCHEDULER_GET(gport) >> 8) & 0x7ff; 12591 if (encap_id == 0) { 12592 encap_id = (BCM_GPORT_SCHEDULER_GET(gport) & 0xff); 12593 } 12594 list = &mmu_info->sched_list; 12595 _bcm_kt2_node_index_set(list, encap_id, 1); 12596 node = &mmu_info->sched_node[encap_id]; 12597 node->first_child = 4095; 12598 node->base_index = *(((uint32 *)ptr)); 12599 ptr += sizeof(uint32); 12600 } 12601 12602 node->gport = gport; 12603 node->numq = GET_FIELD(NODE_NUMQ, node_data); 12604 node->cosq_attached_to = GET_FIELD(NODE_COSQ, node_data); 12605 node->level = GET_FIELD(NODE_LEVEL, node_data); 12606 node->hw_index = GET_FIELD(NODE_HW_INDEX, node_data); 12607 node->wrr_in_use = GET_FIELD(NODE_WRR, node_data); 12608 node->subport_enabled = GET_FIELD(NODE_SUBPORT, node_data); 12609 node->linkphy_enabled = GET_FIELD(NODE_LINKPHY, node_data); 12610 node_id_based = GET_FIELD(NODE_IDBASED, node_data); 12611 12612 switch (node->level) { 12613 case _BCM_KT2_COSQ_NODE_LEVEL_ROOT: 12614 port_node = node; 12615 if (port_node != NULL) { 12616 port_node->parent = NULL; 12617 port_node->sibling = NULL; 12618 port_node->child = NULL; 12619 s1_node = NULL; 12620 s0_node = NULL; 12621 } 12622 break; 12623 12624 case _BCM_KT2_COSQ_NODE_LEVEL_S0: 12625 s0_node = node; 12626 list = &mmu_info->sched_hw_list[_BCM_KT2_COSQ_NODE_LEVEL_S0]; 12627 12628 if (port_node != NULL && s0_node != NULL) { 12629 s0_node->parent = port_node; 12630 tmp_node = port_node; 12631 if (tmp_node->child == NULL) { 12632 tmp_node->child = s0_node; 12633 s0_node->sibling = NULL; 12634 } else { 12635 temp_node = tmp_node->child; 12636 while (temp_node->sibling != NULL) { 12637 temp_node = temp_node->sibling; 12638 } 12639 temp_node->sibling = s0_node; 12640 } 12641 port_node->num_child++; 12642 if ((port_node->numq > 0) && 12643 (port_node->numq != mmu_info->max_nodes[s0_node->level])) { 12644 if (s0_node->hw_index < port_node->first_child) { 12645 port_node->first_child = s0_node->hw_index; 12646 } 12647 if (port_node->num_child == 1) { 12648 if ((port_node->base_index + port_node->numq - 1) 12649 < soc_mem_index_count(unit, LLS_S1_CONFIGm)) { 12650 _bcm_kt2_node_index_set(list, port_node->base_index, 12651 port_node->numq); 12652 } 12653 } 12654 } else if (s0_node->hw_index < 128) { 12655 _bcm_kt2_node_index_set(list, s0_node->hw_index, 1); 12656 } 12657 if (port_node->numq == -1) { 12658 BCM_IF_ERROR_RETURN 12659 (_bcm_kt2_cosq_max_nodes_get(unit, s0_node->level, 12660 &max_numq)); 12661 port_node->numq = max_numq; 12662 } 12663 } 12664 break; 12665 12666 case _BCM_KT2_COSQ_NODE_LEVEL_S1: 12667 s1_node = node; 12668 list = &mmu_info->sched_hw_list[_BCM_KT2_COSQ_NODE_LEVEL_S1]; 12669 12670 if (s0_node != NULL && s1_node != NULL) { 12671 s1_node->parent = s0_node; 12672 tmp_node = s0_node; 12673 if (tmp_node->child == NULL) { 12674 tmp_node->child = s1_node; 12675 s1_node->sibling = NULL; 12676 } else { 12677 temp_node = tmp_node->child; 12678 while (temp_node->sibling != NULL) { 12679 temp_node = temp_node->sibling; 12680 } 12681 temp_node->sibling = s1_node; 12682 } 12683 s0_node->num_child++; 12684 12685 if ((s0_node->numq > 0) && 12686 (s0_node->numq != mmu_info->max_nodes[node->level])) { 12687 if (s1_node->hw_index < s0_node->first_child) { 12688 s0_node->first_child = s1_node->hw_index; 12689 } 12690 if (s0_node->num_child == 1) { 12691 _bcm_kt2_node_index_set(list, s0_node->base_index, 12692 s0_node->numq); 12693 } 12694 } else { 12695 _bcm_kt2_node_index_set(list, s1_node->hw_index, 1); 12696 } 12697 if (s0_node->numq == -1) { 12698 BCM_IF_ERROR_RETURN 12699 (_bcm_kt2_cosq_max_nodes_get(unit, s1_node->level, 12700 &max_numq)); 12701 s0_node->numq = max_numq; 12702 } 12703 } 12704 break; 12705 12706 case _BCM_KT2_COSQ_NODE_LEVEL_L0: 12707 l0_node = node; 12708 list = &mmu_info->sched_hw_list[_BCM_KT2_COSQ_NODE_LEVEL_L0]; 12709 12710 tmp_node = (s1_node != NULL) ? 12711 s1_node : ((s0_node != NULL) ? s0_node : port_node); 12712 if (tmp_node != NULL && l0_node != NULL) { 12713 l0_node->parent = tmp_node; 12714 if (tmp_node->child == NULL) { 12715 tmp_node->child = l0_node; 12716 l0_node->sibling = NULL; 12717 } else { 12718 temp_node = tmp_node->child; 12719 while (temp_node->sibling != NULL) { 12720 temp_node = temp_node->sibling; 12721 } 12722 temp_node->sibling = l0_node; 12723 } 12724 tmp_node->num_child++; 12725 if ((tmp_node->numq > 0) && 12726 (tmp_node->numq != mmu_info->max_nodes[node->level])) { 12727 if (l0_node->hw_index < tmp_node->first_child) { 12728 tmp_node->first_child = l0_node->hw_index; 12729 } 12730 if (tmp_node->num_child == 1) { 12731 _bcm_kt2_node_index_set(list, tmp_node->base_index, 12732 tmp_node->numq); 12733 } 12734 } else { 12735 _bcm_kt2_node_index_set(list, l0_node->hw_index, 1); 12736 } 12737 if (tmp_node->numq == -1) { 12738 BCM_IF_ERROR_RETURN 12739 (_bcm_kt2_cosq_max_nodes_get(unit, l0_node->level, 12740 &max_numq)); 12741 tmp_node->numq = max_numq; 12742 } 12743 } 12744 break; 12745 12746 case _BCM_KT2_COSQ_NODE_LEVEL_L1: 12747 l1_node = node; 12748 list = &mmu_info->sched_hw_list[_BCM_KT2_COSQ_NODE_LEVEL_L1]; 12749 if (l0_node != NULL && l1_node != NULL) { 12750 l1_node->parent = l0_node; 12751 if (l0_node->child == NULL) { 12752 l0_node->child = l1_node; 12753 l1_node->sibling = NULL; 12754 } else { 12755 temp_node = l0_node->child; 12756 while (temp_node->sibling != NULL) { 12757 temp_node = temp_node->sibling; 12758 } 12759 temp_node->sibling = l1_node; 12760 } 12761 l0_node->num_child++; 12762 12763 if ((l0_node->numq > 0) && 12764 (l0_node->numq != mmu_info->max_nodes[node->level])) { 12765 if (l1_node->hw_index < l0_node->first_child) { 12766 l0_node->first_child = l1_node->hw_index; 12767 } 12768 if (l0_node->num_child == 1) { 12769 _bcm_kt2_node_index_set(list, l0_node->base_index, 12770 l0_node->numq); 12771 } 12772 } else { 12773 _bcm_kt2_node_index_set(list, l1_node->hw_index, 1); 12774 } 12775 if (l0_node->numq == -1) { 12776 BCM_IF_ERROR_RETURN 12777 (_bcm_kt2_cosq_max_nodes_get(unit, l1_node->level, 12778 &max_numq)); 12779 l0_node->numq = max_numq; 12780 } 12781 } 12782 break; 12783 12784 case _BCM_KT2_COSQ_NODE_LEVEL_L2: 12785 queue_node = node; 12786 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 12787 list = &mmu_info->l2_base_qlist; 12788 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 12789 list = &mmu_info->l2_base_mcqlist; 12790 } else if (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport)) { 12791 12792 if (mmu_info->num_sub_queues == 0) { 12793 list = &mmu_info->l2_global_qlist; 12794 } else { 12795 list = &mmu_info->l2_sub_qlist; 12796 } 12797 if (node_id_based) { 12798 queue_node->type = _BCM_KT2_NODE_SUBSCRIBER_GPORT_ID; 12799 } 12800 } else if (BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(gport)) { 12801 if (mmu_info->num_sub_queues == 0) { 12802 list = &mmu_info->l2_global_qlist; 12803 } else { 12804 list = &mmu_info->l2_sub_mcqlist; 12805 } 12806 if (node_id_based) { 12807 queue_node->type = _BCM_KT2_NODE_SUBSCRIBER_GPORT_ID; 12808 } 12809 } else if (BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) { 12810 if (mmu_info->num_dmvoq_queues ==0) { 12811 12812 list = &mmu_info->l2_global_qlist; 12813 offset = 0 ; 12814 } else { 12815 list = &mmu_info->l2_dmvoq_qlist; 12816 offset = mmu_info->base_dmvoq_queue; 12817 } 12818 if (node_id_based) { 12819 queue_node->type = _BCM_KT2_NODE_VOQ_ID; 12820 } else { 12821 queue_node->type = _BCM_KT2_NODE_VOQ; 12822 } 12823 } else { 12824 list = &mmu_info->l2_global_qlist; 12825 } 12826 if (l1_node != NULL && queue_node != NULL) { 12827 queue_node->parent = l1_node; 12828 queue_node->hw_index = GET_FIELD(NODE_HW_INDEX, node_data); 12829 /* Creating LLS tree how it is created */ 12830 if (l1_node->child == NULL) { 12831 l1_node->child = queue_node; 12832 queue_node->sibling = NULL; 12833 } else { 12834 temp_node = l1_node->child; 12835 while (temp_node->sibling != NULL) { 12836 temp_node = temp_node->sibling; 12837 } 12838 temp_node->sibling = queue_node; 12839 } 12840 l1_node->num_child++; 12841 12842 if ((l1_node->numq > 0) && 12843 (l1_node->numq != mmu_info->max_nodes[node->level])) { 12844 if (queue_node->hw_index < l1_node->first_child) { 12845 l1_node->first_child = queue_node->hw_index; 12846 } 12847 if (BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) { 12848 if (node_id_based) { 12849 _bcm_kt2_node_index_set(list, encap_id - offset , 1); 12850 } else if (encap_id % 8 == 0) { 12851 _bcm_kt2_node_index_set(list, encap_id - offset , l1_node->numq); 12852 } 12853 } else if (l1_node->num_child == 1) { 12854 if ( 12855 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport) || 12856 BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(gport)) { 12857 if(node_id_based) { 12858 _bcm_kt2_node_index_set(list, 12859 encap_id, 12860 1); 12861 } else { 12862 _bcm_kt2_node_index_set(list, 12863 encap_id, 12864 l1_node->numq); 12865 } 12866 } else { 12867 _bcm_kt2_node_index_set(list, l1_node->base_index, 12868 l1_node->numq); 12869 } 12870 } 12871 } else { 12872 _bcm_kt2_node_index_set(list, queue_node->hw_index, 1); 12873 } 12874 if (l1_node->numq == -1) { 12875 BCM_IF_ERROR_RETURN 12876 (_bcm_kt2_cosq_max_nodes_get(unit, queue_node->level, 12877 &max_numq)); 12878 l1_node->numq = max_numq; 12879 } 12880 } 12881 break; 12882 12883 default: 12884 break; 12885 } 12886 if (GET_FIELD(NODE_NUMQ_MAX, node_data)) { 12887 node->numq = -1; 12888 } 12889 } 12890 /* Update reference counts for DSCP_TABLE profile*/ 12891 BCM_PBMP_CLEAR(all_pbmp); 12892 BCM_PBMP_ASSIGN(all_pbmp, PBMP_ALL(unit)); 12893 #ifdef BCM_KATANA2_SUPPORT 12894 if (SOC_IS_KATANA2(unit) && soc_feature(unit, soc_feature_flex_port)) { 12895 BCM_IF_ERROR_RETURN(_bcm_kt2_flexio_pbmp_update(unit, &all_pbmp)); 12896 } 12897 if (soc_feature(unit, soc_feature_linkphy_coe) || 12898 soc_feature(unit, soc_feature_subtag_coe)) { 12899 _bcm_kt2_subport_pbmp_update(unit, &all_pbmp); 12900 } 12901 #endif 12902 12903 12904 /* Update PORT_COS_MAP memory profile reference counter */ 12905 profile_mem = _bcm_kt2_cos_map_profile[unit]; 12906 PBMP_ITER(all_pbmp, port) { 12907 SOC_IF_ERROR_RETURN 12908 (soc_mem_read(unit, COS_MAP_SELm, MEM_BLOCK_ALL, port, &entry)); 12909 set_index = soc_mem_field32_get(unit, COS_MAP_SELm, &entry, SELECTf); 12910 SOC_IF_ERROR_RETURN 12911 (soc_profile_mem_reference(unit, profile_mem, set_index * 16, 16)); 12912 } 12913 /* Update EGR_COS_MAP memory profile reference counter */ 12914 profile_mem = _bcm_kt2_egr_cos_map_profile[unit]; 12915 PBMP_ITER(all_pbmp, port) { 12916 SOC_IF_ERROR_RETURN 12917 (soc_mem_read(unit, EGR_PORTm, MEM_BLOCK_ALL, port, &entry)); 12918 set_index = soc_mem_field32_get(unit, EGR_PORTm, &entry, EGR_COS_MAP_SELf); 12919 SOC_IF_ERROR_RETURN 12920 (soc_profile_mem_reference(unit, profile_mem, set_index * 16, 16)); 12921 } 12922 12923 /* Update ING_QUEUE_OFFSET_MAPPING_TABLE memory profile reference counter */ 12924 for (i = 0; i < soc_mem_index_count(unit, SERVICE_COS_MAPm); i++) { 12925 SOC_IF_ERROR_RETURN 12926 (soc_mem_read(unit, SERVICE_COS_MAPm, MEM_BLOCK_ALL, i, &entry)); 12927 if (!soc_mem_field32_get(unit, SERVICE_COS_MAPm, &entry, VALIDf)) { 12928 continue; 12929 } 12930 set_index = soc_mem_field32_get(unit, SERVICE_COS_MAPm, 12931 &entry, QUEUE_OFFSET_PROFILE_INDEXf); 12932 SOC_IF_ERROR_RETURN 12933 (_bcm_offset_map_table_entry_reference(unit, set_index * 16, 16)); 12934 } 12935 12936 cpu_hg_index = SOC_INFO(unit).cpu_hg_pp_port_index; 12937 profile_mem = _bcm_kt2_cos_map_profile[unit]; 12938 if (cpu_hg_index != -1) { 12939 SOC_IF_ERROR_RETURN(soc_mem_read(unit, COS_MAP_SELm, MEM_BLOCK_ALL, 12940 cpu_hg_index, &entry)); 12941 set_index = soc_mem_field32_get(unit, COS_MAP_SELm, &entry, SELECTf); 12942 SOC_IF_ERROR_RETURN 12943 (soc_profile_mem_reference(unit, profile_mem, set_index * 16, 16)); 12944 } 12945 12946 PBMP_ITER(all_pbmp, port) { 12947 if (IS_LB_PORT(unit, port)) { 12948 /* Loopback port base starts from 64 */ 12949 continue; 12950 } 12951 SOC_IF_ERROR_RETURN(soc_mem_read(unit, PORT_TABm, MEM_BLOCK_ALL, 12952 port, &entry)); 12953 index = soc_mem_field32_get(unit, PORT_TABm, &entry, TRUST_DSCP_PTRf); 12954 12955 SOC_IF_ERROR_RETURN(_bcm_dscp_table_entry_reference(unit, index * 64, 12956 64)); 12957 } 12958 12959 /* Update MMU_WRED_DROP_CURVE_PROFILE_x memory profile reference counter */ 12960 profile_mem = _bcm_kt2_wred_profile[unit]; 12961 PBMP_PORT_ITER(unit, port) { 12962 12963 /* 12964 * Wred data can be in two tables depending on packet based or byte based 12965 * we scan both and update the software profile 12966 */ 12967 BCM_IF_ERROR_RETURN 12968 (_bcm_kt2_cosq_index_resolve(unit, port, -1, 12969 _BCM_KT2_COSQ_INDEX_STYLE_WRED, NULL, 12970 NULL, &numq)); 12971 for (cosq = 0; cosq < numq; cosq++) { 12972 BCM_IF_ERROR_RETURN 12973 (_bcm_kt2_cosq_index_resolve(unit, port, cosq, 12974 _BCM_KT2_COSQ_INDEX_STYLE_WRED, 12975 NULL, &index, NULL)); 12976 /* scan byte based wred table */ 12977 mem = MMU_WRED_QUEUE_CONFIG_BUFFERm; 12978 SOC_IF_ERROR_RETURN 12979 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, index, &qentry)); 12980 set_index = soc_mem_field32_get(unit, mem, &qentry, PROFILE_INDEXf); 12981 SOC_IF_ERROR_RETURN 12982 (soc_profile_mem_reference(unit, profile_mem, set_index, 1)); 12983 12984 /* scan packet based wred table */ 12985 mem=MMU_WRED_QUEUE_CONFIG_QENTRYm; 12986 set_index = 0; 12987 memset(&qentry1, 0, sizeof(mmu_wred_queue_config_qentry_entry_t)); 12988 12989 SOC_IF_ERROR_RETURN 12990 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, index, &qentry1)); 12991 set_index = soc_mem_field32_get(unit, mem, &qentry1, PROFILE_INDEXf); 12992 SOC_IF_ERROR_RETURN 12993 (soc_profile_mem_reference(unit, profile_mem, set_index, 1)); 12994 } 12995 } 12996 12997 /* Restoring the cosq_map */ 12998 PBMP_ITER(all_pbmp, port) { 12999 if (IS_LB_PORT(unit, port)) { 13000 continue; 13001 } 13002 node = NULL; 13003 13004 /* root node */ 13005 port_info = &mmu_info->sched_node[port]; 13006 if (port_info->gport >= 0) { 13007 /* Should not be checking for return value, as we are check for node not NULL */ 13008 /* coverity[unchecked_value] */ 13009 (void)_bcm_kt2_cosq_node_get(unit, port_info->gport, NULL, NULL, NULL, &node); 13010 if (node != NULL) { 13011 SOC_IF_ERROR_RETURN ( 13012 _bcm_kt2_cosq_map_recover_next_level_node(node)); 13013 } 13014 } 13015 } 13016 13017 if (recovered_ver >= BCM_WB_VERSION_1_1) { 13018 ptr += sizeof(uint32); 13019 for (i = 0; i < 4; i++) { 13020 mmu_info->curr_merger_index[i] = *(((uint32 *)ptr)); 13021 ptr += sizeof(uint32); 13022 } 13023 PBMP_ALL_ITER(unit, port) { 13024 if (!(IS_HG_PORT(unit, port)|| IS_HL_PORT(unit, port))) { 13025 continue; 13026 } 13027 port_node = &mmu_info->sched_node[port]; 13028 13029 if (port_node->cosq_attached_to < 0) { 13030 continue; 13031 } 13032 13033 s0_node = port_node->child; 13034 if (s0_node != NULL && 13035 s0_node->level == _BCM_KT2_COSQ_NODE_LEVEL_S0) { 13036 continue; 13037 } else { 13038 for (l0_node = port_node->child; l0_node != NULL; 13039 l0_node = l0_node->sibling) { 13040 for (l1_node = l0_node->child; l1_node != NULL; 13041 l1_node = l1_node->sibling) { 13042 for (l2_node = l1_node->child; l2_node != NULL; 13043 l2_node = l2_node->sibling) { 13044 sal_memcpy(&l2_node->fabric_pbmp, ptr, sizeof(bcm_pbmp_t)); 13045 ptr += sizeof(bcm_pbmp_t); 13046 l2_node->remote_modid = *(((uint32 *)ptr)); 13047 ptr += sizeof(uint32); 13048 l2_node->fabric_modid = *(((uint32 *)ptr)); 13049 ptr += sizeof(uint32); 13050 } 13051 } 13052 } 13053 } 13054 13055 } 13056 } else { 13057 /* Extra memory for storing fabric_pbmp and we require 13058 fabric_pbmp only for l2 nodes*/ 13059 additional_scache_size += (num_l2_queues[unit] * sizeof(bcm_pbmp_t)); 13060 /* Extra memory for storing remote_modid and we require 13061 remote_modid only for l2 nodes*/ 13062 additional_scache_size += (num_l2_queues[unit] * sizeof(uint32)); 13063 /* Extra memory for storing fabric_modid and we require 13064 fabric_modid only for l2 nodes*/ 13065 additional_scache_size += (num_l2_queues[unit] * sizeof(uint32)); 13066 /* Extra memory for storing curr_merger_index */ 13067 additional_scache_size += (sizeof(int) * 4); 13068 /* Extra memory forStoring the _BCM_KT2_COSQ_WB_END_NODE_VALUE */ 13069 additional_scache_size += sizeof(uint32); 13070 } 13071 if (recovered_ver >= BCM_WB_VERSION_1_2) { 13072 ptr += sizeof(uint32); 13073 data = *((uint8 *) ptr); 13074 num_cos = GET_FIELD(NUM_COS, data); 13075 if (_bcm_kt2_num_cosq[unit] == 0) { 13076 return BCM_E_INIT; 13077 } 13078 _bcm_kt2_num_cosq[unit] = num_cos; 13079 } else { 13080 additional_scache_size += sizeof(uint8); 13081 } 13082 13083 if (recovered_ver >= BCM_WB_VERSION_1_3) { 13084 ptr += sizeof(uint8); 13085 PBMP_ALL_ITER(unit, port) { 13086 port_node = &mmu_info->sched_node[port]; 13087 if (port_node->cosq_attached_to < 0) { 13088 continue; 13089 } 13090 13091 if (port_node->child == NULL) { 13092 continue; 13093 } 13094 s0_node = (port_node->child->level == _BCM_KT2_COSQ_NODE_LEVEL_S0) ? 13095 port_node->child : port_node; 13096 13097 do { 13098 if (s0_node->child) { 13099 s1_node = (s0_node->child->level == _BCM_KT2_COSQ_NODE_LEVEL_S1) ? 13100 s0_node->child : s0_node; 13101 do { 13102 for (l0_node = s1_node->child; 13103 l0_node != NULL; 13104 l0_node = l0_node->sibling) { 13105 for (l1_node = l0_node->child; 13106 l1_node != NULL; 13107 l1_node = l1_node->sibling) { 13108 l1_node->mc_base_index = *(((uint32 *)ptr)); 13109 ptr += sizeof(uint32); 13110 13111 } 13112 } 13113 if (s1_node == s0_node) { 13114 break; 13115 } 13116 /* It comes here 13117 only in case s1 is valid */ 13118 s1_node = s1_node->sibling; 13119 } while (s1_node != NULL); 13120 } 13121 if (s0_node == port_node) { 13122 break; 13123 } 13124 /* It comes here 13125 only in case s0 is valid */ 13126 s0_node = s0_node->sibling; 13127 } while (s0_node != NULL); 13128 } 13129 } else { 13130 /* Extra memory for storing mc base index for L1 nodes*/ 13131 additional_scache_size += (num_l1_schedulers[unit] * sizeof(uint32)); 13132 /* Extra memory forStoring the _BCM_KT2_COSQ_WB_END_NODE_VALUE */ 13133 additional_scache_size += sizeof(uint32); 13134 } 13135 if (recovered_ver >= BCM_WB_VERSION_1_4) { 13136 /* Update PORT_COS_MAP memory profile reference counter */ 13137 profile_mem = _bcm_kt2_ifp_cos_map_profile[unit]; 13138 ptr += sizeof(uint32); 13139 for (profile_index = 0; profile_index < 4 ; profile_index++) { 13140 refcount = *(((uint32 *)ptr)); 13141 while (refcount) { 13142 SOC_IF_ERROR_RETURN 13143 (soc_profile_mem_reference(unit, profile_mem, profile_index * 16, 16)); 13144 refcount--; 13145 } 13146 ptr += sizeof(uint32); 13147 } 13148 } else { 13149 /* Extra memory for storing IFP_COS_MAP refcount*/ 13150 additional_scache_size += (4 * sizeof(uint32)); 13151 /* Extra memory forStoring the _BCM_KT2_COSQ_WB_END_NODE_VALUE */ 13152 additional_scache_size += sizeof(uint32); 13153 } 13154 if (recovered_ver >= BCM_WB_VERSION_1_5) { 13155 #ifdef BCM_KATANA2_SUPPORT 13156 /* flex counter warm boot support for saber2*/ 13157 if (SOC_IS_KATANA2(unit)) { 13158 for (index =0 ; index < BCM_SB2_COSQ_FLEX_COUNT_SUPPORTED; index++) { 13159 stat_array[index] = *(((uint32 *)ptr)); 13160 ptr += sizeof(uint32); 13161 } 13162 bcm_kt2_cosq_stat_config_set(unit, BCM_SB2_COSQ_FLEX_COUNT_SUPPORTED, 13163 stat_array); 13164 } 13165 else { 13166 ptr += (sizeof(uint32) *3); 13167 } 13168 #else 13169 ptr += (sizeof(uint32) *3); 13170 #endif 13171 } 13172 else { 13173 /*Extra memory for cosq stat config*/ 13174 additional_scache_size += (sizeof(bcm_cosq_stat_t)* 3); 13175 } 13176 13177 /*populating node type and wrr mode to the node from scache*/ 13178 if (recovered_ver >= BCM_WB_VERSION_1_6) { 13179 PBMP_ALL_ITER(unit, port) { 13180 port_node = &mmu_info->sched_node[port]; 13181 if (port_node->cosq_attached_to < 0) { 13182 continue; 13183 } 13184 /*copy the node type to the node*/ 13185 _BCM_KT2_NODE_TYPE_WRR_GET(ptr, port_node); 13186 if (recovered_ver >= BCM_WB_VERSION_1_8) { 13187 _BCM_KT2_NODE_BW_BURST_CAL_GET(ptr, port_node); 13188 } 13189 ptr += sizeof(uint8); 13190 s0_node = port_node->child; 13191 if (s0_node != NULL && 13192 s0_node->level == _BCM_KT2_COSQ_NODE_LEVEL_S0) { 13193 continue; 13194 } else { 13195 for ( l0_node = port_node->child; l0_node != NULL; 13196 l0_node = l0_node->sibling) { 13197 /*copy the node type to the node*/ 13198 _BCM_KT2_NODE_TYPE_WRR_GET(ptr, l0_node); 13199 if (recovered_ver >= BCM_WB_VERSION_1_8) { 13200 _BCM_KT2_NODE_BW_BURST_CAL_GET(ptr, port_node); 13201 } 13202 ptr += sizeof(uint8); 13203 for (l1_node = l0_node->child; l1_node != NULL; 13204 l1_node = l1_node->sibling) { 13205 /*copy the node type to the node*/ 13206 _BCM_KT2_NODE_TYPE_WRR_GET(ptr, l1_node); 13207 if (recovered_ver >= BCM_WB_VERSION_1_8) { 13208 _BCM_KT2_NODE_BW_BURST_CAL_GET(ptr, port_node); 13209 } 13210 ptr += sizeof(uint8); 13211 for (l2_node = l1_node->child; l2_node != NULL; 13212 l2_node = l2_node->sibling) { 13213 /*copy the node type to the node*/ 13214 _BCM_KT2_NODE_TYPE_WRR_GET(ptr,l2_node); 13215 if (recovered_ver >= BCM_WB_VERSION_1_8) { 13216 _BCM_KT2_NODE_WRED_DISABLE_GET(ptr,l2_node); 13217 _BCM_KT2_NODE_BW_BURST_CAL_GET(ptr, port_node); 13218 } 13219 ptr += sizeof(uint8); 13220 } 13221 } 13222 } 13223 } 13224 } 13225 } else { 13226 /* Extra memory for storing mc base index for L1 nodes*/ 13227 additional_scache_size += ((num_total_schedulers[unit] + num_l2_queues[unit]) * sizeof(uint8)); 13228 } 13229 13230 if (recovered_ver >= BCM_WB_VERSION_1_7) { 13231 /* Update interface reference count values for all queues */ 13232 sal_memcpy(mmu_info->intf_ref_cnt, ptr, 13233 (sizeof(uint32) * BCM_MULTICAST_PORT_MAX)); 13234 ptr += (sizeof(uint32) * BCM_MULTICAST_PORT_MAX); 13235 } else { 13236 /* Extra memory to store interface ref count of queues */ 13237 additional_scache_size += (sizeof(uint32) * BCM_MULTICAST_PORT_MAX); 13238 } 13239 13240 if (additional_scache_size > 0) { 13241 BCM_IF_ERROR_RETURN( 13242 soc_scache_realloc(unit, scache_handle, additional_scache_size)); 13243 } 13244 13245 /* Iterating through all the ports to update the bmaps */ 13246 for (port = CMIC_PORT(unit); port < (LB_PORT(unit)+1); port++) { 13247 port_node = &mmu_info->sched_node[port]; 13248 s0_bmap = SOC_CONTROL(unit)->port_lls_s0_bmap[port]; 13249 s1_bmap = SOC_CONTROL(unit)->port_lls_s1_bmap[port]; 13250 l0_bmap = SOC_CONTROL(unit)->port_lls_l0_bmap[port]; 13251 l1_bmap = SOC_CONTROL(unit)->port_lls_l1_bmap[port]; 13252 l2_bmap = SOC_CONTROL(unit)->port_lls_l2_bmap[port]; 13253 13254 if (port_node->cosq_attached_to < 0) { 13255 continue; 13256 } 13257 if (port_node->child == NULL) { 13258 continue; 13259 } 13260 s0_node = (port_node->child->level == _BCM_KT2_COSQ_NODE_LEVEL_S0) ? 13261 port_node->child : port_node; 13262 13263 do { 13264 if (s0_node->child) { 13265 s1_node = (s0_node->child->level == _BCM_KT2_COSQ_NODE_LEVEL_S1) ? 13266 s0_node->child : s0_node; 13267 do { 13268 for (l0_node = s1_node->child; 13269 l0_node != NULL; 13270 l0_node = l0_node->sibling) { 13271 SHR_BITSET(l0_bmap, l0_node->hw_index); 13272 for (l1_node = l0_node->child; 13273 l1_node != NULL; 13274 l1_node = l1_node->sibling) { 13275 SHR_BITSET(l1_bmap, l1_node->hw_index); 13276 for (l2_node = l1_node->child; 13277 l2_node != NULL; 13278 l2_node = l2_node->sibling) { 13279 SHR_BITSET(l2_bmap, l2_node->hw_index); 13280 } 13281 } 13282 } 13283 if (s1_node == s0_node) { 13284 break; 13285 } 13286 /* It comes here 13287 only in case s1 is valid */ 13288 SHR_BITSET(s1_bmap, s1_node->hw_index); 13289 s1_node = s1_node->sibling; 13290 } while (s1_node != NULL); 13291 } 13292 if (s0_node == port_node) { 13293 break; 13294 } 13295 /* It comes here 13296 only in case s0 is valid */ 13297 SHR_BITSET(s0_bmap, s0_node->hw_index); 13298 s0_node = s0_node->sibling; 13299 } while (s0_node != NULL); 13300 13301 } 13302 /* Update PRIO2COS_LLFC register profile reference counter */ 13303 profile_reg = _bcm_kt2_llfc_profile[unit]; 13304 PBMP_PORT_ITER(unit, port) { 13305 #ifdef BCM_METROLITE_SUPPORT 13306 if (SOC_IS_METROLITE(unit)) { 13307 mmu_port = ml_pfc_support[port].mmu_port; 13308 } else 13309 #endif 13310 #ifdef BCM_SABER2_SUPPORT 13311 if (SOC_IS_SABER2(unit)) { 13312 mmu_port = sb2_pfc_support[port].mmu_port; 13313 } else 13314 #endif 13315 { 13316 mmu_port = kt2_pfc_support[port].mmu_port; 13317 } 13318 if (mmu_port == -1) { 13319 continue; 13320 } 13321 reg = PORT_PFC_CFG0r; 13322 #ifdef BCM_METROLITE_SUPPORT 13323 if(SOC_IS_METROLITE(unit)) { 13324 BCM_IF_ERROR_RETURN(soc_reg32_get(unit, reg, 13325 REG_PORT_ANY, 0, &rval32)); 13326 index_map32 = soc_reg_field_get(unit, reg, 13327 rval32, PROFILE_INDEXf); 13328 index_map32 = index_map32 >> (mmu_port * 2); 13329 set_index = (index_map32 & 3); 13330 } else 13331 #endif 13332 { 13333 BCM_IF_ERROR_RETURN(soc_reg64_get(unit, reg, 0, 0, &rval)); 13334 13335 index_map = soc_reg64_field_get(unit, reg, rval, PROFILE_INDEXf); 13336 COMPILER_64_SHR(index_map, ((mmu_port % 32) * 2)); 13337 COMPILER_64_TO_32_LO(tmp32, index_map); 13338 set_index = (tmp32 & 3); 13339 } 13340 SOC_IF_ERROR_RETURN 13341 (soc_profile_reg_reference(unit, profile_reg, 13342 set_index * 16, 16)); 13343 } 13344 return BCM_E_NONE; 13345 } 13346 #endif /* BCM_WARM_BOOT_SUPPORT */ 13347 13348 int 13349 _bcm_kt2_subport_config_set(int unit) 13350 { 13351 soc_info_t *si; 13352 bcm_port_t port; 13353 bcm_port_t lp_ports = 0; 13354 int start = 0, end = 0; 13355 int min_subport_index; 13356 int num_max_stream = 0; 13357 soc_pbmp_t pbmp_linkphy_one_stream_per_subport; 13358 13359 si = &SOC_INFO(unit); 13360 min_subport_index = si->pp_port_index_min; 13361 13362 num_max_stream = si->lp_streams_per_subport; 13363 13364 SOC_PBMP_CLEAR(pbmp_linkphy_one_stream_per_subport); 13365 if (SOC_IS_SABER2(unit)) { 13366 pbmp_linkphy_one_stream_per_subport = 13367 soc_property_get_pbmp(unit, spn_PBMP_LINKPHY_ONE_STREAM_PER_SUBPORT, 0); 13368 } 13369 13370 SOC_PBMP_ITER(si->linkphy_pbm, port) { 13371 /* coverity[dead_error_condition] */ 13372 if (port >= si->lb_port) { 13373 /* coverity[dead_error_begin] */ 13374 break; 13375 } 13376 start = si->port_linkphy_s1_base[port]; 13377 end = start + 13378 si->port_num_subport[port] * 13379 (SOC_PBMP_MEMBER(pbmp_linkphy_one_stream_per_subport, port) ? 13380 1 : num_max_stream) - 1; 13381 SOC_IF_ERROR_RETURN 13382 (soc_kt2_cosq_s1_range_set(unit, port, start, end, 1)); 13383 SOC_IF_ERROR_RETURN 13384 (soc_kt2_cosq_port_coe_linkphy_status_set(unit, port, 1)); 13385 lp_ports++; 13386 } 13387 13388 /* 13389 * setup linkphy destination stream mapping if 13390 * linkphy is enabled on the ports OR 13391 * the linkphy_allowed_pbmp is not NULL, meaning 13392 * there are ports on which linkphy could be 13393 * enabled in future. 13394 */ 13395 if ((lp_ports > 0) || 13396 (SOC_PBMP_NOT_NULL(si->linkphy_allowed_pbm))) { 13397 SOC_IF_ERROR_RETURN 13398 (soc_kt2_cosq_stream_mapping_set(unit)); 13399 } 13400 13401 SOC_PBMP_ITER(si->subtag_pbm, port) { 13402 /* coverity[dead_error_condition] */ 13403 if (port >= si->lb_port) { 13404 /* coverity[dead_error_begin] */ 13405 break; 13406 } 13407 start = si->port_subport_base[port] - min_subport_index; 13408 end = start + si->port_num_subport[port] - 1; 13409 SOC_IF_ERROR_RETURN 13410 (soc_kt2_cosq_s1_range_set(unit, port, start, end, 0)); 13411 SOC_IF_ERROR_RETURN 13412 (soc_kt2_cosq_port_coe_linkphy_status_set(unit, port, 1)); 13413 } 13414 13415 return BCM_E_NONE; 13416 } 13417 13418 int 13419 _bcm_kt2_packing_config_set(int unit, bcm_port_t port, int numq) 13420 { 13421 bcm_gport_t port_sched, l0_sched; 13422 bcm_gport_t l1_sched; 13423 bcm_gport_t cosq; 13424 int cos, i; 13425 uint32 type; 13426 BCM_IF_ERROR_RETURN 13427 (bcm_kt2_cosq_gport_add(unit, port, 1, 0, &port_sched)); 13428 13429 /* coverity[uninit_use_in_call : FALSE] */ 13430 BCM_IF_ERROR_RETURN 13431 (bcm_kt2_cosq_gport_add(unit, port, numq, 13432 BCM_COSQ_GPORT_SCHEDULER, 13433 &l0_sched)); 13434 BCM_IF_ERROR_RETURN 13435 (bcm_kt2_cosq_gport_attach(unit, l0_sched, port_sched, 0)); 13436 13437 for (cos = 0; cos < numq; cos++) { 13438 BCM_IF_ERROR_RETURN 13439 (bcm_kt2_cosq_gport_add(unit, port, 2, BCM_COSQ_GPORT_SCHEDULER, 13440 &l1_sched)); 13441 BCM_IF_ERROR_RETURN 13442 (bcm_kt2_cosq_gport_attach(unit, l1_sched, l0_sched, cos)); 13443 for (i = 0; i < 2; i++) { 13444 type = (i == 0) ? BCM_COSQ_GPORT_UCAST_QUEUE_GROUP : 13445 BCM_COSQ_GPORT_MCAST_QUEUE_GROUP; 13446 BCM_IF_ERROR_RETURN 13447 (bcm_kt2_cosq_gport_add(unit, port, 1, type, &cosq)); 13448 BCM_IF_ERROR_RETURN 13449 (bcm_kt2_cosq_gport_attach(unit, cosq, l1_sched, i)); 13450 BCM_IF_ERROR_RETURN 13451 (bcm_kt2_cosq_gport_sched_set(unit, l1_sched, i, 13452 BCM_COSQ_WEIGHTED_ROUND_ROBIN, 1)); 13453 } 13454 } 13455 13456 return BCM_E_NONE; 13457 } 13458 13459 int 13460 _bcm_kt2_port_lls_config_set(int unit, 13461 bcm_port_t port, 13462 int startq, 13463 int total_queues, 13464 int numq) 13465 { 13466 bcm_gport_t port_sched, l0_sched; 13467 bcm_gport_t l1_sched; 13468 bcm_gport_t cosq; 13469 int cos, i; 13470 uint32 type; 13471 uint32 total_opnodes = (total_queues + 7)/8; 13472 13473 BCM_IF_ERROR_RETURN 13474 (bcm_kt2_cosq_gport_add(unit, port, 1, 0, &port_sched)); 13475 13476 /* coverity[uninit_use_in_call : FALSE] */ 13477 BCM_IF_ERROR_RETURN 13478 (bcm_kt2_cosq_gport_add(unit, port, total_opnodes, 13479 BCM_COSQ_GPORT_SCHEDULER, 13480 &l0_sched)); 13481 BCM_IF_ERROR_RETURN 13482 (bcm_kt2_cosq_gport_attach(unit, l0_sched, port_sched, 0)); 13483 13484 for (i = 0; i < total_opnodes; i++) { 13485 if (IS_HG_PORT(unit, port) && soc_feature(unit, soc_feature_mmu_packing)) { 13486 BCM_IF_ERROR_RETURN 13487 (bcm_kt2_cosq_gport_add(unit, port, numq * 2 , BCM_COSQ_GPORT_SCHEDULER, 13488 &l1_sched)); 13489 } 13490 else { 13491 13492 BCM_IF_ERROR_RETURN 13493 (bcm_kt2_cosq_gport_add(unit, port, numq, BCM_COSQ_GPORT_SCHEDULER, 13494 &l1_sched)); 13495 } 13496 13497 BCM_IF_ERROR_RETURN 13498 (bcm_kt2_cosq_gport_attach(unit, l1_sched, l0_sched, i)); 13499 for (cos = 0; cos < numq; cos++) { 13500 type = BCM_COSQ_GPORT_WITH_ID; 13501 BCM_GPORT_UCAST_QUEUE_GROUP_SYSQID_SET(cosq, port, (startq + cos)); 13502 BCM_IF_ERROR_RETURN 13503 (bcm_kt2_cosq_gport_add(unit, port, 1, type, &cosq)); 13504 BCM_IF_ERROR_RETURN 13505 (bcm_kt2_cosq_gport_attach(unit, cosq, l1_sched, cos)); 13506 BCM_IF_ERROR_RETURN 13507 (bcm_kt2_cosq_gport_sched_set(unit, l1_sched, cos, 13508 BCM_COSQ_WEIGHTED_ROUND_ROBIN, 1)); 13509 if (IS_HG_PORT(unit, port) && soc_feature(unit, soc_feature_mmu_packing)) { 13510 BCM_IF_ERROR_RETURN 13511 (bcm_kt2_cosq_gport_add(unit, port, 1, 13512 BCM_COSQ_GPORT_MCAST_QUEUE_GROUP, &cosq)); 13513 BCM_IF_ERROR_RETURN 13514 (bcm_kt2_cosq_gport_attach(unit, cosq, l1_sched, cos + numq)); 13515 BCM_IF_ERROR_RETURN 13516 (bcm_kt2_cosq_gport_sched_set(unit, l1_sched, (cos + numq) , 13517 BCM_COSQ_WEIGHTED_ROUND_ROBIN, 1)); 13518 } 13519 } 13520 startq += 8; 13521 } 13522 13523 return BCM_E_NONE; 13524 } 13525 13526 int 13527 _bcm_kt2_create_default_lls_tree(int unit, bcm_port_t port) 13528 { 13529 soc_info_t *si; 13530 int numq = 0, cosq; 13531 bcm_gport_t port_sched, l0_sched, l1_sched, queue; 13532 13533 si = &SOC_INFO(unit); 13534 bcm_kt2_cosq_config_get(unit, &numq); 13535 if (numq < 1) { 13536 numq = 1; 13537 } else if (numq > 8) { 13538 numq = 8; 13539 } 13540 if (IS_HG_PORT(unit, port)) { 13541 BCM_IF_ERROR_RETURN 13542 (_bcm_kt2_port_lls_config_set(unit, port, 13543 si->port_uc_cosq_base[port], 13544 si->port_num_uc_cosq[port], 13545 numq)); 13546 } else { 13547 if (!soc_feature(unit, soc_feature_mmu_packing)) { 13548 BCM_IF_ERROR_RETURN 13549 (bcm_kt2_cosq_gport_add(unit, port, 1, 0, &port_sched)); 13550 13551 /* coverity[uninit_use_in_call : FALSE] */ 13552 BCM_IF_ERROR_RETURN 13553 (bcm_kt2_cosq_gport_add(unit, port, 1, 13554 BCM_COSQ_GPORT_SCHEDULER, 13555 &l0_sched)); 13556 BCM_IF_ERROR_RETURN 13557 (bcm_kt2_cosq_gport_attach(unit, l0_sched, port_sched, 0)); 13558 BCM_IF_ERROR_RETURN 13559 (bcm_kt2_cosq_gport_add(unit, port, numq, 13560 BCM_COSQ_GPORT_SCHEDULER, 13561 &l1_sched)); 13562 BCM_IF_ERROR_RETURN 13563 (bcm_kt2_cosq_gport_attach(unit, l1_sched, l0_sched, 0)); 13564 for (cosq = 0; cosq < numq; cosq++) { 13565 BCM_IF_ERROR_RETURN 13566 (bcm_kt2_cosq_gport_add(unit, port, 1, 13567 BCM_COSQ_GPORT_UCAST_QUEUE_GROUP, &queue)); 13568 BCM_IF_ERROR_RETURN 13569 (bcm_kt2_cosq_gport_attach(unit, queue, l1_sched, 13570 cosq)); 13571 BCM_IF_ERROR_RETURN 13572 (bcm_kt2_cosq_gport_sched_set(unit, l1_sched, cosq, 13573 BCM_COSQ_STRICT, 0)); 13574 } 13575 }else { 13576 BCM_IF_ERROR_RETURN 13577 (_bcm_kt2_packing_config_set(unit, port, numq)); 13578 } 13579 } 13580 13581 return BCM_E_NONE; 13582 13583 } 13584 13585 int 13586 bcm_katana2_cosq_reconfigure_flexio(int unit, bcm_port_t port, int lanes) 13587 { 13588 bcm_gport_t gport; 13589 int i; 13590 BCM_IF_ERROR_RETURN 13591 (bcm_esw_port_gport_get(unit, port , &gport)); 13592 13593 /* Deleting the LLS tree */ 13594 BCM_IF_ERROR_RETURN 13595 ( bcm_kt2_cosq_gport_delete(unit, gport)); 13596 /* Creating the default LLS tree */ 13597 BCM_IF_ERROR_RETURN 13598 ( _bcm_kt2_create_default_lls_tree(unit, port)); 13599 for (i = 1; i < lanes; i++) { 13600 BCM_IF_ERROR_RETURN 13601 (bcm_esw_port_gport_get(unit, port + i , &gport)); 13602 /* Deleting the LLS tree */ 13603 BCM_IF_ERROR_RETURN 13604 ( bcm_kt2_cosq_gport_delete(unit, gport)); 13605 } 13606 return BCM_E_NONE; 13607 } 13608 13609 STATIC int 13610 _bcm_kt2_init_all_queue_counters(int unit) 13611 { 13612 uint32 max_queue = soc_mem_index_count(unit, LLS_L2_PARENTm); 13613 uint32 queue_index; 13614 uint64 val; 13615 #ifdef BCM_KATANA2_SUPPORT 13616 int num_elem = 0; 13617 int index = 0, increment = 4; 13618 _sb2_cosq_counter_mem_map_t *mem_map; 13619 soc_reg_t non_dma_id_1 = 0, non_dma_id_2 = 0; 13620 if (SOC_IS_SABER2(unit)) { 13621 uint16 dev_id; 13622 uint8 rev_id; 13623 increment = 2; 13624 soc_cm_get_id(unit, &dev_id, &rev_id); 13625 if (dev_id == BCM56233_DEVICE_ID) { 13626 increment = 1; 13627 } 13628 } 13629 #ifdef BCM_METROLITE_SUPPORT 13630 if(SOC_IS_METROLITE(unit)) { 13631 increment = 1; 13632 } 13633 #endif 13634 soc_sb2_cosq_counter_mem_map_get(unit, &num_elem, &mem_map); 13635 COMPILER_64_ZERO(val); 13636 /* This API is mainly for clearing the extended queues only, 13637 So Looping only for queue_id > SOC_MAX_NUM_PP_PORTS */ 13638 13639 for ( index = 0; index < num_elem; index += increment ) { 13640 switch (mem_map[index].non_dma_id) { 13641 case SOC_COUNTER_NON_DMA_COSQ_DROP_PKT: 13642 non_dma_id_1 = SOC_COUNTER_NON_DMA_COSQ_DROP_PKT; 13643 non_dma_id_2 = SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE; 13644 break; 13645 case SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_YELLOW: 13646 non_dma_id_1 = SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_YELLOW; 13647 non_dma_id_2 = SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE_YELLOW; 13648 break; 13649 case SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_RED: 13650 non_dma_id_1 = SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_RED; 13651 non_dma_id_2 = SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE_RED; 13652 break; 13653 case SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_GREEN: 13654 non_dma_id_1 = SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_GREEN; 13655 non_dma_id_2 = SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE_GREEN; 13656 break; 13657 case SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT: 13658 non_dma_id_1 = SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT; 13659 non_dma_id_2 = SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE; 13660 break; 13661 default: 13662 break; 13663 } 13664 for (queue_index = soc_max_num_pp_ports[unit] + 1; 13665 queue_index < max_queue; queue_index++) { 13666 BCM_IF_ERROR_RETURN(soc_counter_set(unit, queue_index, 13667 non_dma_id_1, 0, val)); 13668 BCM_IF_ERROR_RETURN(soc_counter_set(unit, queue_index, 13669 non_dma_id_2, 0, val)); 13670 } 13671 } 13672 #else 13673 COMPILER_64_ZERO(val); 13674 /* This API is mainly for clearing the extended queues only, 13675 So Looping only for queue_id > SOC_MAX_NUM_PP_PORTS */ 13676 for (queue_index = SOC_MAX_NUM_PP_PORTS + 1; 13677 queue_index < max_queue; queue_index++) { 13678 BCM_IF_ERROR_RETURN(soc_counter_set(unit, queue_index, 13679 SOC_COUNTER_NON_DMA_COSQ_DROP_PKT, 0, val)); 13680 BCM_IF_ERROR_RETURN(soc_counter_set(unit, queue_index, 13681 SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE, 0, val)); 13682 BCM_IF_ERROR_RETURN(soc_counter_set(unit, queue_index, 13683 SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_RED, 0, val)); 13684 BCM_IF_ERROR_RETURN(soc_counter_set(unit, queue_index, 13685 SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE_RED, 0, val)); 13686 BCM_IF_ERROR_RETURN(soc_counter_set(unit, queue_index, 13687 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT, 0, val)); 13688 BCM_IF_ERROR_RETURN(soc_counter_set(unit, queue_index, 13689 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE, 0, val)); 13690 } 13691 13692 #endif 13693 return BCM_E_NONE; 13694 } 13695 int 13696 bcm_kt2_init_fc_map_tbl(int unit) 13697 { 13698 int max_index; 13699 int max_nodes; 13700 uint32 map_entry[SOC_MAX_MEM_WORDS]; 13701 int mem; 13702 int index; 13703 int field ; 13704 static const soc_field_t indexf[] = { 13705 INDEX0f, INDEX1f 13706 }; 13707 static const soc_mem_t memx[] = { 13708 MMU_INTFI_FC_MAP_TBL0m, 13709 MMU_INTFI_FC_MAP_TBL1m, 13710 MMU_INTFI_FC_MAP_TBL2m 13711 }; 13712 static const soc_mem_t memy[] = { 13713 MMU_INTFI_FC_ST_TBL0m, 13714 MMU_INTFI_FC_ST_TBL1m, 13715 MMU_INTFI_FC_ST_TBL2m, 13716 }; 13717 13718 for ( mem = 0 ; mem < 3 ; mem++) 13719 { 13720 max_index = soc_mem_index_count(unit, memy[mem]) - 1; 13721 max_nodes = soc_mem_index_count(unit,memx[mem]); 13722 for ( index = 0 ; index < max_nodes ; index++) 13723 { 13724 SOC_IF_ERROR_RETURN(soc_mem_read(unit, memx[mem], 13725 MEM_BLOCK_ALL, index, &map_entry)); 13726 for (field = 0; field < COUNTOF(indexf); field++) 13727 { 13728 soc_mem_field32_set(unit, memx[mem], 13729 &map_entry, indexf[field], max_index); 13730 } 13731 SOC_IF_ERROR_RETURN(soc_mem_write(unit, memx[mem], 13732 MEM_BLOCK_ALL, index, &map_entry)); 13733 } 13734 } 13735 return BCM_E_NONE; 13736 } 13737 13738 /* 13739 * Function: 13740 * bcm_kt2_cosq_init 13741 * Purpose: 13742 * Initialize (clear) all COS schedule/mapping state. 13743 * Parameters: 13744 * unit - unit number 13745 * Returns: 13746 * BCM_E_XXX 13747 */ 13748 int 13749 bcm_kt2_cosq_init(int unit) 13750 { 13751 soc_info_t *si; 13752 STATIC int _kt2_max_cosq = -1; 13753 int cosq, numq, alloc_size, ext_pbmp_count; 13754 bcm_port_t port; 13755 soc_reg_t mem; 13756 soc_pbmp_t pbmp_linkphy, ext_pbmp; 13757 STATIC soc_mem_t wred_mems[6] = { 13758 MMU_WRED_DROP_CURVE_PROFILE_0m, MMU_WRED_DROP_CURVE_PROFILE_1m, 13759 MMU_WRED_DROP_CURVE_PROFILE_2m, MMU_WRED_DROP_CURVE_PROFILE_3m, 13760 MMU_WRED_DROP_CURVE_PROFILE_4m, MMU_WRED_DROP_CURVE_PROFILE_5m 13761 }; 13762 int entry_words[6]; 13763 mmu_wred_drop_curve_profile_0_entry_t entry_tcp_green; 13764 mmu_wred_drop_curve_profile_1_entry_t entry_tcp_yellow; 13765 mmu_wred_drop_curve_profile_2_entry_t entry_tcp_red; 13766 mmu_wred_drop_curve_profile_3_entry_t entry_nontcp_green; 13767 mmu_wred_drop_curve_profile_4_entry_t entry_nontcp_yellow; 13768 mmu_wred_drop_curve_profile_5_entry_t entry_nontcp_red; 13769 void *entries[6]; 13770 uint64 rval64s[16], *prval64s[1]; 13771 uint32 profile_index,rval; 13772 _bcm_kt2_mmu_info_t *mmu_info_p; 13773 int i, cmc; 13774 bcm_gport_t port_sched, l0_sched, l1_sched, queue; 13775 uint32 max_threshold, min_threshold; 13776 int num_queues, num_inputs; 13777 int num_base_queues = 0, total_sub_queues = 0; 13778 int start_pp_port = 0, end_pp_port = 0; 13779 int pre_alloc_queues = 0; 13780 int pp_port_cos = 0; 13781 uint32 qbase = 0; 13782 uint32 qoffset = 0; 13783 soc_reg_t reg; 13784 13785 /* Initialize static variables */ 13786 num_pp_ports[unit]=-1; 13787 num_port_schedulers[unit]=-1; 13788 num_s0_schedulers[unit]=-1; 13789 num_s1_schedulers[unit]=-1; 13790 num_l0_schedulers[unit]=-1; 13791 num_l1_schedulers[unit]=-1; 13792 num_total_schedulers[unit]=-1; 13793 num_l2_queues[unit]=-1; 13794 max_l1_shaper_bucket[unit]=-1; 13795 max_l2_shaper_bucket[unit]=-1; 13796 soc_max_num_pp_ports[unit] = SOC_MAX_NUM_PP_PORTS; 13797 13798 if (_kt2_max_cosq < 0) { 13799 _kt2_max_cosq = NUM_COS(unit); 13800 NUM_COS(unit) = 8; 13801 } 13802 13803 if (soc_property_get(unit, spn_MMU_MULTI_PACKETS_PER_CELL, 0)) { 13804 ext_pbmp = soc_property_get_pbmp(unit, spn_PBMP_EXT_MEM, 0); 13805 SOC_PBMP_COUNT(ext_pbmp, ext_pbmp_count); 13806 if (ext_pbmp_count == 0){ 13807 LOG_ERROR(BSL_LS_BCM_COMMON, 13808 (BSL_META_U(unit, 13809 "With packing mode set you need have" 13810 "the pbmp_ext_mem bitmap for the ports" 13811 "for those requires external memory \n"))); 13812 return BCM_E_CONFIG; 13813 } 13814 } 13815 13816 BCM_IF_ERROR_RETURN (bcm_kt2_cosq_detach(unit, 0)); 13817 13818 numq = soc_property_get(unit, spn_BCM_NUM_COS, BCM_COS_DEFAULT); 13819 13820 if (numq < 1) { 13821 numq = 1; 13822 } else if (numq > 8) { 13823 numq = 8; 13824 } 13825 13826 /* Create profile for PORT_COS_MAP table */ 13827 if (_bcm_kt2_cos_map_profile[unit] == NULL) { 13828 _bcm_kt2_cos_map_profile[unit] = sal_alloc(sizeof(soc_profile_mem_t), 13829 "COS_MAP Profile Mem"); 13830 if (_bcm_kt2_cos_map_profile[unit] == NULL) { 13831 return BCM_E_MEMORY; 13832 } 13833 soc_profile_mem_t_init(_bcm_kt2_cos_map_profile[unit]); 13834 } 13835 mem = PORT_COS_MAPm; 13836 entry_words[0] = sizeof(port_cos_map_entry_t) / sizeof(uint32); 13837 BCM_IF_ERROR_RETURN(soc_profile_mem_create(unit, &mem, entry_words, 1, 13838 _bcm_kt2_cos_map_profile[unit])); 13839 13840 /* Create profile for EGR_COS_MAP table */ 13841 if (_bcm_kt2_egr_cos_map_profile[unit] == NULL) { 13842 _bcm_kt2_egr_cos_map_profile[unit] = sal_alloc(sizeof(soc_profile_mem_t), 13843 "EGR_COS_MAP Profile Mem"); 13844 if (_bcm_kt2_egr_cos_map_profile[unit] == NULL) { 13845 return BCM_E_MEMORY; 13846 } 13847 soc_profile_mem_t_init(_bcm_kt2_egr_cos_map_profile[unit]); 13848 } 13849 mem = EGR_COS_MAPm; 13850 entry_words[0] = sizeof(egr_cos_map_entry_t) / sizeof(uint32); 13851 BCM_IF_ERROR_RETURN(soc_profile_mem_create(unit, &mem, entry_words, 1, 13852 _bcm_kt2_egr_cos_map_profile[unit])); 13853 13854 /* Create profile for PRIO2COS_LLFC register */ 13855 if (_bcm_kt2_llfc_profile[unit] == NULL) { 13856 _bcm_kt2_llfc_profile[unit] = 13857 sal_alloc(sizeof(soc_profile_reg_t), "PRIO2COS_LLFC Profile Reg"); 13858 if (_bcm_kt2_llfc_profile[unit] == NULL) { 13859 return BCM_E_MEMORY; 13860 } 13861 soc_profile_reg_t_init(_bcm_kt2_llfc_profile[unit]); 13862 } 13863 reg = PRIO2COS_PROFILEr; 13864 BCM_IF_ERROR_RETURN 13865 (soc_profile_reg_create(unit, ®, 1, _bcm_kt2_llfc_profile[unit])); 13866 13867 /* Inititilise pg profile refcount */ 13868 #if defined(BCM_SABER2_SUPPORT) 13869 BCM_IF_ERROR_RETURN(bcm_kt2_pg_profile_refcount_init(unit)); 13870 #endif 13871 /* Create profile for IFP_COS_MAP table. */ 13872 if (_bcm_kt2_ifp_cos_map_profile[unit] == NULL) { 13873 _bcm_kt2_ifp_cos_map_profile[unit] 13874 = sal_alloc(sizeof(soc_profile_mem_t), "IFP_COS_MAP Profile Mem"); 13875 if (_bcm_kt2_ifp_cos_map_profile[unit] == NULL) { 13876 return BCM_E_MEMORY; 13877 } 13878 soc_profile_mem_t_init(_bcm_kt2_ifp_cos_map_profile[unit]); 13879 } 13880 mem = IFP_COS_MAPm; 13881 entry_words[0] = sizeof(ifp_cos_map_entry_t) / sizeof(uint32); 13882 BCM_IF_ERROR_RETURN 13883 (soc_profile_mem_create(unit, &mem, entry_words, 1, 13884 _bcm_kt2_ifp_cos_map_profile[unit])); 13885 13886 /* Create profile for MMU_WRED_DROP_CURVE_PROFILE_x tables */ 13887 if (_bcm_kt2_wred_profile[unit] == NULL) { 13888 _bcm_kt2_wred_profile[unit] = sal_alloc(sizeof(soc_profile_mem_t), 13889 "WRED Profile Mem"); 13890 if (_bcm_kt2_wred_profile[unit] == NULL) { 13891 return BCM_E_MEMORY; 13892 } 13893 soc_profile_mem_t_init(_bcm_kt2_wred_profile[unit]); 13894 } 13895 entry_words[0] = 13896 sizeof(mmu_wred_drop_curve_profile_0_entry_t) / sizeof(uint32); 13897 entry_words[1] = 13898 sizeof(mmu_wred_drop_curve_profile_1_entry_t) / sizeof(uint32); 13899 entry_words[2] = 13900 sizeof(mmu_wred_drop_curve_profile_2_entry_t) / sizeof(uint32); 13901 entry_words[3] = 13902 sizeof(mmu_wred_drop_curve_profile_3_entry_t) / sizeof(uint32); 13903 entry_words[4] = 13904 sizeof(mmu_wred_drop_curve_profile_4_entry_t) / sizeof(uint32); 13905 entry_words[5] = 13906 sizeof(mmu_wred_drop_curve_profile_5_entry_t) / sizeof(uint32); 13907 BCM_IF_ERROR_RETURN(soc_profile_mem_create(unit, wred_mems, entry_words, 6, 13908 _bcm_kt2_wred_profile[unit])); 13909 13910 alloc_size = sizeof(_bcm_kt2_mmu_info_t) * 1; 13911 if (_bcm_kt2_mmu_info[unit] == NULL) { 13912 _bcm_kt2_mmu_info[unit] = 13913 sal_alloc(alloc_size, "_bcm_kt2_mmu_info"); 13914 13915 if (_bcm_kt2_mmu_info[unit] == NULL) { 13916 return BCM_E_MEMORY; 13917 } 13918 } else { 13919 _bcm_kt2_cosq_free_memory(_bcm_kt2_mmu_info[unit]); 13920 } 13921 13922 sal_memset(_bcm_kt2_mmu_info[unit], 0, alloc_size); 13923 13924 mmu_info_p = _bcm_kt2_mmu_info[unit]; 13925 13926 /* ======================== */ 13927 /* Time Being commenting below part under if 0 */ 13928 /* ======================== */ 13929 /* 13930 if (soc_feature(unit, soc_feature_ddr3)) { 13931 mmu_info_p->num_queues = soc_mem_index_count(unit, LLS_L2_PARENTm); 13932 } else { 13933 13934 mmu_info_p->num_queues = 1024; 13935 } 13936 */ 13937 mmu_info_p->num_queues = soc_mem_index_count(unit, LLS_L2_PARENTm); 13938 13939 mmu_info_p->max_nodes[_BCM_KT2_COSQ_NODE_LEVEL_ROOT] = 13940 soc_mem_index_count(unit, LLS_PORT_CONFIGm); 13941 mmu_info_p->max_nodes[_BCM_KT2_COSQ_NODE_LEVEL_S0] = 13942 soc_mem_index_count(unit, LLS_S1_CONFIGm); 13943 mmu_info_p->max_nodes[_BCM_KT2_COSQ_NODE_LEVEL_S1] = 13944 2 * soc_mem_index_count(unit, LLS_S1_CONFIGm); 13945 if (SOC_IS_SABER2(unit)) { 13946 mmu_info_p->max_nodes[_BCM_KT2_COSQ_NODE_LEVEL_S1] = 13947 soc_mem_index_count(unit, LLS_S1_CONFIGm); 13948 #if defined BCM_METROLITE_SUPPORT 13949 if (soc_feature(unit, soc_feature_discontinuous_pp_port)) { 13950 /* Allocate additional nodes equal to amount of physical nodes. 13951 * This is to hold the subport nodes which are reused with physical nodes */ 13952 mmu_info_p->max_nodes[_BCM_KT2_COSQ_NODE_LEVEL_S1] += SOC_INFO(unit).cpu_hg_index; 13953 } 13954 #endif 13955 } 13956 mmu_info_p->max_nodes[_BCM_KT2_COSQ_NODE_LEVEL_L0] = 13957 soc_mem_index_count(unit, LLS_L0_CONFIGm); 13958 mmu_info_p->max_nodes[_BCM_KT2_COSQ_NODE_LEVEL_L1] = 13959 soc_mem_index_count(unit, LLS_L1_CONFIGm); 13960 mmu_info_p->max_nodes[_BCM_KT2_COSQ_NODE_LEVEL_L2] = 13961 mmu_info_p->num_queues; 13962 13963 mmu_info_p->num_nodes = 0; 13964 13965 13966 for (i= 0; i < _BCM_KT2_COSQ_NODE_LEVEL_L2; i++) { 13967 mmu_info_p->num_nodes += mmu_info_p->max_nodes[i]; 13968 } 13969 13970 si = &SOC_INFO(unit); 13971 13972 num_pp_ports[unit] = si->cpu_hg_pp_port_index; 13973 num_port_schedulers[unit] = si->cpu_hg_index; 13974 #if defined BCM_METROLITE_SUPPORT 13975 if (soc_feature(unit, soc_feature_discontinuous_pp_port)) { 13976 num_pp_ports[unit] += num_port_schedulers[unit]; 13977 } 13978 #endif 13979 13980 pbmp_linkphy = soc_property_get_pbmp(unit, spn_PBMP_LINKPHY, 0); 13981 13982 if (SOC_PBMP_NOT_NULL(pbmp_linkphy)) { 13983 #ifdef BCM_METROLITE_SUPPORT 13984 if(SOC_IS_METROLITE(unit)) { 13985 /* Metrolite doesn't have s0 schedulers */ 13986 num_s0_schedulers[unit] = 0; 13987 } else 13988 #endif 13989 { 13990 num_s0_schedulers[unit] = soc_mem_index_count(unit, LLS_S0_SHAPER_CONFIG_Cm); 13991 } 13992 num_s1_schedulers[unit] = soc_mem_index_count(unit, LLS_S1_SHAPER_CONFIG_Cm); 13993 } else { 13994 num_s0_schedulers[unit] = 0; 13995 num_s1_schedulers[unit] = 0; 13996 } 13997 num_l0_schedulers[unit] = soc_mem_index_count(unit,LLS_L0_PARENTm); 13998 num_l1_schedulers[unit] = soc_mem_index_count(unit,LLS_L1_PARENTm);; 13999 num_l2_queues[unit] = soc_mem_index_count(unit,LLS_L2_PARENTm); 14000 max_l1_shaper_bucket[unit] = num_l1_schedulers[unit] / 14001 soc_mem_index_count(unit, 14002 LLS_L1_SHAPER_CONFIG_Cm); 14003 if (SOC_IS_SABER2(unit)) { 14004 max_l2_shaper_bucket[unit] = num_l2_queues[unit] / 14005 soc_mem_index_count(unit, 14006 LLS_L2_SHAPER_CONFIG_Cm); 14007 l2_shaper_memory[unit][0] = LLS_L2_SHAPER_CONFIG_Cm; 14008 l2_shaper_memory[unit][1] = LLS_L2_MIN_CONFIG_Cm; 14009 l2_shaper_memory[unit][2] = INVALIDm; 14010 l2_shaper_memory[unit][3] = INVALIDm; 14011 soc_max_num_pp_ports[unit] = num_pp_ports[unit]; 14012 } else { 14013 max_l2_shaper_bucket[unit] = num_l2_queues[unit] / 14014 soc_mem_index_count(unit, 14015 LLS_L2_SHAPER_CONFIG_LOWERm); 14016 l2_shaper_memory[unit][0] = LLS_L2_SHAPER_CONFIG_LOWERm; 14017 l2_shaper_memory[unit][1] = LLS_L2_MIN_CONFIG_LOWER_Cm; 14018 l2_shaper_memory[unit][2] = LLS_L2_SHAPER_CONFIG_UPPERm; 14019 l2_shaper_memory[unit][3] = LLS_L2_MIN_CONFIG_UPPER_Cm; 14020 } 14021 14022 num_total_schedulers[unit] = mmu_info_p->num_nodes; 14023 LOG_VERBOSE(BSL_LS_BCM_COSQ, 14024 (BSL_META_U(unit, 14025 "Useful Info:\n" 14026 "num_pp_ports[unit]:%d num_port_schedulers[unit]:%d num_s0_schedulers[unit]:%d\n" 14027 "num_s1_schedulers[unit]:%d num_l0_schedulers[unit]:%d num_l1_schedulers[unit]:%d\n" 14028 "num_l2_queues[unit]:%d num_total_schedulers[unit]:%d\n"), 14029 num_pp_ports[unit], num_port_schedulers[unit], num_s0_schedulers[unit], 14030 num_s1_schedulers[unit], num_l0_schedulers[unit], num_l1_schedulers[unit], 14031 num_l2_queues[unit], num_total_schedulers[unit])); 14032 14033 mmu_info_p->port = _bcm_kt2_cosq_alloc_clear((soc_max_num_pp_ports[unit] * 14034 sizeof(_bcm_kt2_cosq_port_info_t)), 14035 "port_info"); 14036 if (mmu_info_p->port == NULL) { 14037 _bcm_kt2_cosq_free_memory(mmu_info_p); 14038 return BCM_E_MEMORY; 14039 } 14040 14041 mmu_info_p->sched_node = _bcm_kt2_cosq_alloc_clear(((num_total_schedulers[unit]) * 14042 sizeof(_bcm_kt2_cosq_node_t)), 14043 "sched_node"); 14044 if (mmu_info_p->sched_node == NULL) { 14045 _bcm_kt2_cosq_free_memory(mmu_info_p); 14046 return BCM_E_MEMORY; 14047 } 14048 14049 mmu_info_p->queue_node = _bcm_kt2_cosq_alloc_clear(((num_l2_queues[unit]) * 14050 sizeof(_bcm_kt2_cosq_node_t)), 14051 "queue_node"); 14052 if (mmu_info_p->queue_node == NULL) { 14053 _bcm_kt2_cosq_free_memory(mmu_info_p); 14054 return BCM_E_MEMORY; 14055 } 14056 14057 mmu_info_p->global_qlist.bits = _bcm_kt2_cosq_alloc_clear( 14058 SHR_BITALLOCSIZE(mmu_info_p->num_queues), 14059 "global_qlist"); 14060 if (mmu_info_p->global_qlist.bits == NULL) { 14061 _bcm_kt2_cosq_free_memory(mmu_info_p); 14062 return BCM_E_MEMORY; 14063 } 14064 14065 mmu_info_p->l2_global_qlist.bits = _bcm_kt2_cosq_alloc_clear( 14066 SHR_BITALLOCSIZE(mmu_info_p->num_queues), 14067 "l2_global_qlist"); 14068 if (mmu_info_p->l2_global_qlist.bits == NULL) { 14069 _bcm_kt2_cosq_free_memory(mmu_info_p); 14070 return BCM_E_MEMORY; 14071 } 14072 for (port = 0; port < (si->lb_port + 1); port++) { 14073 14074 if (SOC_IS_SABER2(unit) && (!SOC_IS_METROLITE(unit)) && 14075 soc_saber2_port_is_unused(unit, port)) { 14076 continue; 14077 } 14078 14079 SOC_IF_ERROR_RETURN(READ_ING_COS_MODEr(unit, port, &rval)); 14080 if(SOC_WARM_BOOT(unit) && !(IS_LB_PORT(unit, port))) { 14081 /* In case of warmboot the queue base is restored 14082 * from the hardware. 14083 */ 14084 qbase = soc_reg_field_get(unit, ING_COS_MODEr, rval, 14085 BASE_QUEUE_NUMf); 14086 mmu_info_p->port[port].q_offset =qbase; 14087 14088 i = soc_reg_field_get(unit, ING_COS_MODEr, rval, 14089 SERVICE_BASE_QUEUE_NUMf); 14090 mmu_info_p->port[port].uc_vlan_base = i ? i : 14091 mmu_info_p->num_queues -1; 14092 14093 if (IS_HG_PORT(unit, port)) { 14094 qoffset = KT2_HG_NUM_PHYSICAL_QUEUES ; 14095 14096 } else if (IS_CPU_PORT(unit,port)) { 14097 qoffset = KT2_CPU_NUM_PHYSICAL_QUEUES ; 14098 } else { 14099 qoffset = KT2_DEFAULT_NUM_PHYSICAL_QUEUES; 14100 } 14101 mmu_info_p->port[port].q_limit = qbase + qoffset; 14102 si->port_uc_cosq_base[port] = mmu_info_p->port[port].q_offset ; 14103 si->port_num_uc_cosq[port] = qoffset; 14104 } 14105 else { 14106 mmu_info_p->port[port].q_offset = si->port_uc_cosq_base[port]; 14107 mmu_info_p->port[port].q_limit = si->port_uc_cosq_base[port] + 14108 si->port_num_uc_cosq[port]; 14109 } 14110 /* reserve the queues for the ports from the global bitmap */ 14111 BCM_IF_ERROR_RETURN 14112 (_bcm_kt2_node_index_set(&mmu_info_p->l2_global_qlist, 14113 mmu_info_p->port[port].q_offset, 14114 (mmu_info_p->port[port].q_limit - 14115 mmu_info_p->port[port].q_offset))); 14116 BCM_IF_ERROR_RETURN 14117 (_bcm_kt2_node_index_set(&mmu_info_p->global_qlist, 14118 mmu_info_p->port[port].q_offset, 14119 (mmu_info_p->port[port].q_limit - 14120 mmu_info_p->port[port].q_offset))); 14121 14122 14123 soc_reg_field_set(unit, ING_COS_MODEr, &rval, BASE_QUEUE_NUMf, 14124 mmu_info_p->port[port].q_offset); 14125 if (IS_LB_PORT(unit, port)) { 14126 /* Loopback port base starts from 64 */ 14127 soc_reg_field_set(unit, ING_COS_MODEr, &rval, BASE_QUEUE_NUMf, 14128 _BCM_KT2_LB_BASE_QUEUE); 14129 } 14130 if (IS_HG_PORT(unit, port)) { 14131 soc_reg_field_set(unit, ING_COS_MODEr, &rval, COS_MODEf, 2); 14132 } 14133 SOC_IF_ERROR_RETURN(WRITE_ING_COS_MODEr(unit, port, rval)); 14134 14135 if (si->port_num_subport[port] > 0) { 14136 start_pp_port = si->port_subport_base[port]; 14137 end_pp_port = si->port_subport_base[port] + 14138 si->port_num_subport[port]; 14139 14140 #if defined BCM_METROLITE_SUPPORT 14141 if (soc_feature(unit, soc_feature_discontinuous_pp_port)) { 14142 SOC_PBMP_ITER(SOC_PORT_PP_BITMAP(unit, port), i) { 14143 SOC_IF_ERROR_RETURN(READ_ING_COS_MODEr(unit, i, &rval)); 14144 if(SOC_WARM_BOOT(unit)) { 14145 qbase =soc_reg_field_get(unit,ING_COS_MODEr, rval, 14146 BASE_QUEUE_NUMf); 14147 mmu_info_p->port[i].q_offset =qbase; 14148 mmu_info_p->port[i].q_limit = qbase + 8 ; 14149 si->port_uc_cosq_base[i] = mmu_info_p->port[i].q_offset; 14150 si->port_num_uc_cosq[i] = qoffset ; 14151 } 14152 else { 14153 mmu_info_p->port[i].q_offset = si->port_uc_cosq_base[i]; 14154 mmu_info_p->port[i].q_limit = si->port_uc_cosq_base[i] + 14155 si->port_num_uc_cosq[i]; 14156 } 14157 14158 BCM_IF_ERROR_RETURN 14159 (_bcm_kt2_node_index_set(&mmu_info_p->l2_global_qlist, 14160 mmu_info_p->port[i].q_offset, 14161 (mmu_info_p->port[i].q_limit - 14162 mmu_info_p->port[i].q_offset))); 14163 BCM_IF_ERROR_RETURN 14164 (_bcm_kt2_node_index_set(&mmu_info_p->global_qlist, 14165 mmu_info_p->port[i].q_offset, 14166 (mmu_info_p->port[i].q_limit - 14167 mmu_info_p->port[i].q_offset))); 14168 14169 soc_reg_field_set(unit, ING_COS_MODEr, &rval, BASE_QUEUE_NUMf, 14170 mmu_info_p->port[i].q_offset); 14171 SOC_IF_ERROR_RETURN(WRITE_ING_COS_MODEr(unit, i, rval)); 14172 } 14173 } else 14174 #endif 14175 { 14176 for (i = start_pp_port; i < end_pp_port; i++) { 14177 SOC_IF_ERROR_RETURN(READ_ING_COS_MODEr(unit, i, &rval)); 14178 if(SOC_WARM_BOOT(unit)) { 14179 qbase =soc_reg_field_get(unit,ING_COS_MODEr, rval, 14180 BASE_QUEUE_NUMf); 14181 mmu_info_p->port[i].q_offset =qbase; 14182 mmu_info_p->port[i].q_limit = qbase + 8 ; 14183 si->port_uc_cosq_base[i] = mmu_info_p->port[i].q_offset; 14184 si->port_num_uc_cosq[i] = qoffset ; 14185 } 14186 else { 14187 mmu_info_p->port[i].q_offset = si->port_uc_cosq_base[i]; 14188 mmu_info_p->port[i].q_limit = si->port_uc_cosq_base[i] + 14189 si->port_num_uc_cosq[i]; 14190 } 14191 14192 BCM_IF_ERROR_RETURN 14193 (_bcm_kt2_node_index_set(&mmu_info_p->l2_global_qlist, 14194 mmu_info_p->port[i].q_offset, 14195 (mmu_info_p->port[i].q_limit - 14196 mmu_info_p->port[i].q_offset))); 14197 BCM_IF_ERROR_RETURN 14198 (_bcm_kt2_node_index_set(&mmu_info_p->global_qlist, 14199 mmu_info_p->port[i].q_offset, 14200 (mmu_info_p->port[i].q_limit - 14201 mmu_info_p->port[i].q_offset))); 14202 14203 soc_reg_field_set(unit, ING_COS_MODEr, &rval, BASE_QUEUE_NUMf, 14204 mmu_info_p->port[i].q_offset); 14205 SOC_IF_ERROR_RETURN(WRITE_ING_COS_MODEr(unit, i, rval)); 14206 } 14207 } 14208 } 14209 14210 SOC_IF_ERROR_RETURN(READ_RQE_PP_PORT_CONFIGr(unit, port, &rval)); 14211 14212 if (soc_feature(unit, soc_feature_mmu_packing)) { 14213 if(SOC_WARM_BOOT(unit)) { 14214 qbase = soc_reg_field_get(unit, RQE_PP_PORT_CONFIGr, 14215 rval, BASE_QUEUEf); 14216 mmu_info_p->port[port].mcq_offset =qbase ; 14217 if (IS_HG_PORT(unit, port)) { 14218 qoffset = KT2_HG_NUM_PHYSICAL_QUEUES ; 14219 } else if (IS_CPU_PORT(unit, port)) { 14220 qoffset = KT2_CPU_NUM_PHYSICAL_QUEUES ; 14221 } else { 14222 qoffset = KT2_DEFAULT_NUM_PHYSICAL_QUEUES; 14223 } 14224 mmu_info_p->port[port].mcq_limit = qbase + qoffset; 14225 si->port_cosq_base[port] = mmu_info_p->port[port].mcq_offset; 14226 si->port_num_cosq[port] = qoffset; 14227 } 14228 else { 14229 mmu_info_p->port[port].mcq_offset = si->port_cosq_base[port]; 14230 mmu_info_p->port[port].mcq_limit = si->port_cosq_base[port] + 14231 si->port_num_cosq[port]; 14232 } 14233 BCM_IF_ERROR_RETURN 14234 (_bcm_kt2_node_index_set(&mmu_info_p->l2_global_qlist, 14235 mmu_info_p->port[port].mcq_offset, 14236 (mmu_info_p->port[port].mcq_limit - 14237 mmu_info_p->port[port].mcq_offset))); 14238 BCM_IF_ERROR_RETURN 14239 (_bcm_kt2_node_index_set(&mmu_info_p->global_qlist, 14240 mmu_info_p->port[port].mcq_offset, 14241 (mmu_info_p->port[port].mcq_limit - 14242 mmu_info_p->port[port].mcq_offset))); 14243 } 14244 soc_reg_field_set(unit, RQE_PP_PORT_CONFIGr, &rval, BASE_QUEUEf, 14245 (soc_feature(unit, soc_feature_mmu_packing)) ? 14246 mmu_info_p->port[port].mcq_offset : 14247 mmu_info_p->port[port].q_offset); 14248 14249 if (IS_EXT_MEM_PORT(unit, port)) { 14250 if (SOC_REG_FIELD_VALID(unit, RQE_PP_PORT_CONFIGr, BUFF_TYPEf)) { 14251 soc_reg_field_set(unit, RQE_PP_PORT_CONFIGr, 14252 &rval, BUFF_TYPEf, 1); 14253 } 14254 } 14255 if (IS_LB_PORT(unit, port)) { 14256 soc_reg_field_set(unit, RQE_PP_PORT_CONFIGr, &rval, BASE_QUEUEf, 14257 _BCM_KT2_LB_BASE_QUEUE); 14258 } 14259 if (IS_HG_PORT(unit, port)) { 14260 soc_reg_field_set(unit, RQE_PP_PORT_CONFIGr, 14261 &rval, COS_MODEf, 2); 14262 } 14263 SOC_IF_ERROR_RETURN(WRITE_RQE_PP_PORT_CONFIGr(unit, port, rval)); 14264 14265 if (si->port_num_subport[port] > 0) { 14266 #if defined BCM_METROLITE_SUPPORT 14267 if (soc_feature(unit, soc_feature_discontinuous_pp_port)) { 14268 SOC_PBMP_ITER(SOC_PORT_PP_BITMAP(unit, port), i) { 14269 soc_reg_field_set(unit, RQE_PP_PORT_CONFIGr, &rval, BASE_QUEUEf, 14270 (soc_feature(unit, soc_feature_mmu_packing)) ? 14271 mmu_info_p->port[port].mcq_offset : 14272 mmu_info_p->port[i].q_offset); 14273 14274 SOC_IF_ERROR_RETURN(WRITE_RQE_PP_PORT_CONFIGr(unit, i, rval)); 14275 } 14276 } else 14277 #endif 14278 { 14279 for (i = start_pp_port; i < end_pp_port; i++) { 14280 soc_reg_field_set(unit, RQE_PP_PORT_CONFIGr, &rval, BASE_QUEUEf, 14281 (soc_feature(unit, soc_feature_mmu_packing)) ? 14282 mmu_info_p->port[port].mcq_offset : 14283 mmu_info_p->port[i].q_offset); 14284 14285 SOC_IF_ERROR_RETURN(WRITE_RQE_PP_PORT_CONFIGr(unit, i, rval)); 14286 } 14287 } 14288 } 14289 14290 rval = 0; 14291 soc_reg_field_set(unit, OP_E2ECC_PORT_CONFIGr, &rval, BASE_QUEUEf, 14292 mmu_info_p->port[port].q_offset); 14293 if (IS_EXT_MEM_PORT(unit, port)) { 14294 soc_reg_field_set(unit, OP_E2ECC_PORT_CONFIGr, &rval, 14295 BUFF_TYPEf, 1); 14296 } 14297 if (!IS_LB_PORT(unit, port)) { 14298 SOC_IF_ERROR_RETURN(WRITE_OP_E2ECC_PORT_CONFIGr(unit, port, rval)); 14299 } 14300 for (i = mmu_info_p->port[port].q_offset; 14301 i < mmu_info_p->port[port].q_limit; i++) { 14302 SOC_IF_ERROR_RETURN (soc_mem_field32_modify(unit, 14303 EGR_QUEUE_TO_PP_PORT_MAPm, i, PP_PORTf, port)); 14304 } 14305 14306 if (soc_feature(unit, soc_feature_mmu_packing)) { 14307 for (i = mmu_info_p->port[port].mcq_offset; 14308 i < mmu_info_p->port[port].mcq_limit; i++) { 14309 SOC_IF_ERROR_RETURN (soc_mem_field32_modify(unit, 14310 EGR_QUEUE_TO_PP_PORT_MAPm, i, PP_PORTf, port)); 14311 } 14312 } 14313 if (!IS_LB_PORT(unit, port)) { 14314 num_base_queues = mmu_info_p->port[port].q_limit; 14315 } 14316 if(!SOC_WARM_BOOT(unit)) { 14317 mmu_info_p->port[port].uc_vlan_base = mmu_info_p->num_queues - 1; 14318 } 14319 } 14320 14321 /* mmu_info-> num_base_queues is the maximum number of queue configured 14322 * or available with the system */ 14323 mmu_info_p->num_base_queues = mmu_info_p->num_queues; 14324 14325 mmu_info_p->num_dmvoq_queues = soc_property_get(unit, 14326 spn_MMU_NUM_DMVOQ_QUEUES, 14327 0); 14328 14329 /* Config variable defining 14330 * the number of pre reserved subscriber queues 14331 * spn_MMU_NUM_SUBSCRIBER_QUEUES 14332 */ 14333 14334 mmu_info_p->num_sub_queues = soc_property_get(unit, 14335 spn_MMU_NUM_SUBSCRIBER_QUEUES, 14336 0); 14337 14338 mmu_info_p->num_ext_queues = mmu_info_p->num_queues ; 14339 14340 14341 /* Pre reserved queues include DVMOQ and subscriber queues 14342 * from extended queues 14343 */ 14344 pre_alloc_queues = mmu_info_p->num_dmvoq_queues + 14345 mmu_info_p->num_sub_queues; 14346 14347 14348 if (pre_alloc_queues > mmu_info_p->num_queues ) { 14349 _bcm_kt2_cosq_free_memory(mmu_info_p); 14350 return BCM_E_MEMORY; 14351 } 14352 14353 mmu_info_p->base_dmvoq_queue = (num_base_queues + 7) & 0xfffffff8; 14354 14355 /* Check if number of dmvoq queue configured is not crossing limit */ 14356 if((mmu_info_p->base_dmvoq_queue + 14357 mmu_info_p->num_dmvoq_queues) > num_l2_queues[unit]) { 14358 LOG_ERROR(BSL_LS_BCM_COMMON, 14359 (BSL_META_U(unit, 14360 "Configured value of number of DMVOQ" 14361 " queue %d more than allowed number %d\n"), 14362 mmu_info_p->num_dmvoq_queues, 14363 num_l2_queues[unit] - mmu_info_p->base_dmvoq_queue)); 14364 _bcm_kt2_cosq_free_memory(mmu_info_p); 14365 return BCM_E_CONFIG; 14366 } 14367 14368 BCM_IF_ERROR_RETURN 14369 (_bcm_kt2_node_index_set(&mmu_info_p->l2_global_qlist, 14370 mmu_info_p->base_dmvoq_queue, 14371 mmu_info_p->num_dmvoq_queues 14372 )); 14373 BCM_IF_ERROR_RETURN 14374 (_bcm_kt2_node_index_set(&mmu_info_p->global_qlist, 14375 mmu_info_p->base_dmvoq_queue, 14376 mmu_info_p->num_dmvoq_queues 14377 )); 14378 14379 mmu_info_p->qset_size = soc_property_get(unit, 14380 spn_MMU_SUBSCRIBER_NUM_COS_LEVEL, 14381 1); 14382 14383 mmu_info_p->l1_gport_pair = _bcm_kt2_cosq_alloc_clear( 14384 (mmu_info_p->num_nodes * sizeof(bcm_gport_t)), 14385 "l1_pair_info"); 14386 if (mmu_info_p->l1_gport_pair == NULL) { 14387 _bcm_kt2_cosq_free_memory(mmu_info_p); 14388 return BCM_E_MEMORY; 14389 } 14390 14391 14392 if (mmu_info_p->num_dmvoq_queues > 0) { 14393 mmu_info_p->dmvoq_qlist.bits = _bcm_kt2_cosq_alloc_clear( 14394 SHR_BITALLOCSIZE(mmu_info_p->num_dmvoq_queues), 14395 "dmvoq_qlist"); 14396 if (mmu_info_p->dmvoq_qlist.bits == NULL) { 14397 _bcm_kt2_cosq_free_memory(mmu_info_p); 14398 return BCM_E_MEMORY; 14399 } 14400 } 14401 14402 14403 mmu_info_p->sched_list.bits = _bcm_kt2_cosq_alloc_clear( 14404 SHR_BITALLOCSIZE(mmu_info_p->num_nodes), 14405 "sched_list"); 14406 if (mmu_info_p->sched_list.bits == NULL) { 14407 _bcm_kt2_cosq_free_memory(mmu_info_p); 14408 return BCM_E_MEMORY; 14409 } 14410 14411 for (i = _BCM_KT2_COSQ_NODE_LEVEL_S0; i < _BCM_KT2_COSQ_NODE_LEVEL_L2; 14412 i++) { 14413 mmu_info_p->sched_hw_list[i].bits = _bcm_kt2_cosq_alloc_clear( 14414 SHR_BITALLOCSIZE 14415 (mmu_info_p->max_nodes[i]), 14416 "sched_hw_list"); 14417 if (mmu_info_p->sched_hw_list[i].bits == NULL) { 14418 _bcm_kt2_cosq_free_memory(mmu_info_p); 14419 return BCM_E_MEMORY; 14420 } 14421 } 14422 14423 mmu_info_p->l2_base_qlist.bits = _bcm_kt2_cosq_alloc_clear( 14424 SHR_BITALLOCSIZE 14425 (mmu_info_p->num_queues), 14426 "l2_base_qlist"); 14427 if (mmu_info_p->l2_base_qlist.bits == NULL) { 14428 _bcm_kt2_cosq_free_memory(mmu_info_p); 14429 return BCM_E_MEMORY; 14430 } 14431 14432 mmu_info_p->l2_base_mcqlist.bits = _bcm_kt2_cosq_alloc_clear( 14433 SHR_BITALLOCSIZE 14434 (mmu_info_p->num_queues), 14435 "l2_base_mcqlist"); 14436 if (mmu_info_p->l2_base_mcqlist.bits == NULL) { 14437 _bcm_kt2_cosq_free_memory(mmu_info_p); 14438 return BCM_E_MEMORY; 14439 } 14440 14441 14442 if (mmu_info_p->num_dmvoq_queues > 0) { 14443 mmu_info_p->l2_dmvoq_qlist.bits = _bcm_kt2_cosq_alloc_clear( 14444 SHR_BITALLOCSIZE 14445 (mmu_info_p->num_dmvoq_queues), 14446 "l2_dmvoq_qlist"); 14447 if (mmu_info_p->l2_dmvoq_qlist.bits == NULL) { 14448 _bcm_kt2_cosq_free_memory(mmu_info_p); 14449 return BCM_E_MEMORY; 14450 } 14451 } 14452 14453 for (i = 0; i < num_total_schedulers[unit]; i++) { 14454 _BCM_KT2_COSQ_LIST_NODE_INIT(mmu_info_p->sched_node, i); 14455 } 14456 14457 for (i = 0; i < num_l2_queues[unit]; i++) { 14458 _BCM_KT2_COSQ_LIST_NODE_INIT(mmu_info_p->queue_node, i); 14459 } 14460 14461 /* reserve last entry of S0, S1, L0 and L1 nodes */ 14462 for (i = _BCM_KT2_COSQ_NODE_LEVEL_S0; i < _BCM_KT2_COSQ_NODE_LEVEL_L2; 14463 i++) { 14464 BCM_IF_ERROR_RETURN 14465 (_bcm_kt2_node_index_set(&mmu_info_p->sched_hw_list[i], 14466 (mmu_info_p->max_nodes[i] - 1), 1)); 14467 } 14468 14469 if (mmu_info_p->num_sub_queues) { 14470 if (mmu_info_p->num_dmvoq_queues) { 14471 /* Pre reserved DVMOQ 14472 * Revisit as DVMOQ used the indices in multiples of 8 14473 * hence used shift 14474 */ 14475 mmu_info_p->base_sub_queue = (mmu_info_p->base_dmvoq_queue + 14476 mmu_info_p->num_dmvoq_queues); 14477 14478 } 14479 else { 14480 mmu_info_p->base_sub_queue = num_base_queues; 14481 } 14482 /* Check if number of sub queue configured is not crossing limit. 14483 * Config variable mmu_num_subscriber_queues used to configure this */ 14484 total_sub_queues = mmu_info_p->base_sub_queue + 14485 mmu_info_p->num_sub_queues; 14486 if (total_sub_queues > (soc_feature(unit, soc_feature_mmu_packing) ? 14487 num_l2_queues[unit]/2 : num_l2_queues[unit] )) { 14488 LOG_ERROR(BSL_LS_BCM_COMMON, 14489 (BSL_META_U(unit, 14490 "Configured value of number of subscriber" 14491 " queue %d more than allowed number %d\n"), 14492 mmu_info_p->num_sub_queues, 14493 ((soc_feature(unit, soc_feature_mmu_packing) ? 14494 num_l2_queues[unit] / 2 : num_l2_queues[unit]) - mmu_info_p->base_sub_queue))); 14495 _bcm_kt2_cosq_free_memory(mmu_info_p); 14496 return BCM_E_CONFIG; 14497 } 14498 14499 /*setting base sub queue as multiple of 8 same as DMVOQ*/ 14500 mmu_info_p->base_sub_queue = (mmu_info_p->base_sub_queue + 7) & 0xfffffff8; 14501 14502 mmu_info_p->sub_qlist.bits = _bcm_kt2_cosq_alloc_clear( 14503 SHR_BITALLOCSIZE(mmu_info_p->num_sub_queues), 14504 "sub_qlist"); 14505 if (mmu_info_p->sub_qlist.bits == NULL) { 14506 _bcm_kt2_cosq_free_memory(mmu_info_p); 14507 return BCM_E_MEMORY; 14508 } 14509 14510 mmu_info_p->l2_sub_qlist.bits = _bcm_kt2_cosq_alloc_clear( 14511 SHR_BITALLOCSIZE 14512 (mmu_info_p->num_sub_queues), 14513 "l2_sub_qlist"); 14514 14515 if (mmu_info_p->l2_sub_qlist.bits == NULL) { 14516 _bcm_kt2_cosq_free_memory(mmu_info_p); 14517 return BCM_E_MEMORY; 14518 } 14519 14520 BCM_IF_ERROR_RETURN 14521 (_bcm_kt2_node_index_set(&mmu_info_p->l2_global_qlist, 14522 mmu_info_p->base_sub_queue, 14523 mmu_info_p->num_sub_queues)); 14524 BCM_IF_ERROR_RETURN 14525 (_bcm_kt2_node_index_set(&mmu_info_p->global_qlist, 14526 mmu_info_p->base_sub_queue, 14527 mmu_info_p->num_sub_queues)); 14528 if (soc_feature(unit, soc_feature_mmu_packing)) { 14529 mmu_info_p->sub_mcqlist.bits = _bcm_kt2_cosq_alloc_clear( 14530 SHR_BITALLOCSIZE(mmu_info_p->num_sub_queues), 14531 "sub_mcqlist"); 14532 if (mmu_info_p->sub_mcqlist.bits == NULL) { 14533 _bcm_kt2_cosq_free_memory(mmu_info_p); 14534 return BCM_E_MEMORY; 14535 } 14536 14537 mmu_info_p->l2_sub_mcqlist.bits = _bcm_kt2_cosq_alloc_clear( 14538 SHR_BITALLOCSIZE 14539 (mmu_info_p->num_sub_queues), 14540 "l2_sub_mcqlist"); 14541 14542 if (mmu_info_p->l2_sub_mcqlist.bits == NULL) { 14543 _bcm_kt2_cosq_free_memory(mmu_info_p); 14544 return BCM_E_MEMORY; 14545 } 14546 14547 BCM_IF_ERROR_RETURN 14548 (_bcm_kt2_node_index_set(&mmu_info_p->l2_global_qlist, 14549 mmu_info_p->base_sub_queue + 14550 mmu_info_p->num_queues/2, 14551 mmu_info_p->num_sub_queues)); 14552 BCM_IF_ERROR_RETURN 14553 (_bcm_kt2_node_index_set(&mmu_info_p->global_qlist, 14554 mmu_info_p->base_sub_queue + 14555 mmu_info_p->num_queues/2, 14556 mmu_info_p->num_sub_queues)); 14557 } 14558 14559 }else { 14560 mmu_info_p->base_sub_queue = 0; 14561 } 14562 14563 if (!SOC_WARM_BOOT(unit)) { /* Cold Boot */ 14564 /* create LLS tree for CPU */ 14565 port = KT2_CMIC_PORT; 14566 BCM_IF_ERROR_RETURN 14567 (bcm_kt2_cosq_gport_add(unit, port, SOC_CMCS_NUM(unit) + 1, 14568 0, &port_sched)); 14569 for (cmc = 0; cmc < SOC_CMCS_NUM(unit); cmc++) { 14570 if (NUM_CPU_ARM_COSQ(unit, cmc) == 0) { 14571 continue; 14572 } 14573 cosq = (NUM_CPU_ARM_COSQ(unit, cmc) + 7) / 8; 14574 14575 /* coverity[uninit_use_in_call : FALSE] */ 14576 BCM_IF_ERROR_RETURN 14577 (bcm_kt2_cosq_gport_add(unit, port, cosq, 14578 BCM_COSQ_GPORT_SCHEDULER, &l0_sched)); 14579 BCM_IF_ERROR_RETURN 14580 (bcm_kt2_cosq_gport_attach(unit, l0_sched, port_sched, cmc)); 14581 cosq = 0; 14582 num_queues = NUM_CPU_ARM_COSQ(unit, cmc); 14583 for (i = 0; i < NUM_CPU_ARM_COSQ(unit, cmc); i++) { 14584 if (i % 8 == 0) { 14585 num_inputs = (num_queues >= 8) ? 8 : num_queues; 14586 BCM_IF_ERROR_RETURN 14587 (bcm_kt2_cosq_gport_add(unit, port, num_inputs, 14588 BCM_COSQ_GPORT_SCHEDULER, 14589 &l1_sched)); 14590 BCM_IF_ERROR_RETURN 14591 (bcm_kt2_cosq_gport_attach(unit, l1_sched, 14592 l0_sched, cosq)); 14593 cosq++; 14594 num_queues -= num_inputs; 14595 } 14596 BCM_IF_ERROR_RETURN 14597 (bcm_kt2_cosq_gport_add(unit, port, 1, 14598 BCM_COSQ_GPORT_UCAST_QUEUE_GROUP, &queue)); 14599 BCM_IF_ERROR_RETURN 14600 (bcm_kt2_cosq_gport_attach(unit, queue, l1_sched, 14601 (i % 8))); 14602 14603 } 14604 } 14605 14606 /* Reserve additional L0 node for RPE as indicated for 14607 * flow control from MMU to CMIC block, Refer the register 14608 * LLS_FC_CONFIG - FC_CFG_COSMASK_L0_MAP 14609 */ 14610 /* coverity[uninit_use_in_call : FALSE] */ 14611 BCM_IF_ERROR_RETURN 14612 (bcm_kt2_cosq_gport_add(unit, port, -1, 14613 BCM_COSQ_GPORT_SCHEDULER, &l0_sched)); 14614 BCM_IF_ERROR_RETURN 14615 (bcm_kt2_cosq_gport_attach(unit, l0_sched, port_sched, cmc)); 14616 14617 /* create LLS tree for Loopback port*/ 14618 port = LB_PORT(unit);; 14619 BCM_IF_ERROR_RETURN 14620 (_bcm_kt2_port_lls_config_set(unit, port, 14621 si->port_uc_cosq_base[port], si->port_num_uc_cosq[port], numq)); 14622 14623 14624 for (port = 1; port < si->lb_port ; port++) { 14625 /* don't create lls for invalid port */ 14626 if (!SOC_PORT_VALID(unit, port)) { 14627 continue; 14628 } 14629 if (SOC_IS_SABER2(unit) && (!SOC_IS_METROLITE(unit)) && 14630 soc_saber2_port_is_unused(unit, port)) { 14631 continue; 14632 } 14633 #if defined BCM_METROLITE_SUPPORT 14634 if (soc_feature(unit, soc_feature_discontinuous_pp_port)) { 14635 if (_SOC_IS_PORT_LINKPHY_SUBTAG(unit, port)) { 14636 numq = si->port_num_uc_cosq[port]; 14637 } else { 14638 numq = soc_property_get(unit, spn_BCM_NUM_COS, BCM_COS_DEFAULT); 14639 if (numq < 1) { 14640 numq = 1; 14641 } else if (numq > 8) { 14642 numq = 8; 14643 } 14644 } 14645 if (!(_SOC_IS_PORT_LINKPHY_SUBTAG(unit, port)) && 14646 _SOC_IS_PP_PORT_LINKPHY_SUBTAG(unit, port)) { 14647 continue; 14648 } 14649 } 14650 #endif 14651 if (IS_HG_PORT(unit, port)) { 14652 BCM_IF_ERROR_RETURN 14653 (_bcm_kt2_port_lls_config_set(unit, port, 14654 si->port_uc_cosq_base[port], 14655 si->port_num_uc_cosq[port], 14656 numq)); 14657 } else { 14658 if (!soc_feature(unit, soc_feature_mmu_packing)) { 14659 BCM_IF_ERROR_RETURN 14660 (bcm_kt2_cosq_gport_add(unit, port, 1, 0, &port_sched)); 14661 BCM_IF_ERROR_RETURN 14662 (bcm_kt2_cosq_gport_add(unit, port, 1, 14663 BCM_COSQ_GPORT_SCHEDULER, 14664 &l0_sched)); 14665 BCM_IF_ERROR_RETURN 14666 (bcm_kt2_cosq_gport_attach(unit, l0_sched, port_sched, 0)); 14667 BCM_IF_ERROR_RETURN 14668 (bcm_kt2_cosq_gport_add(unit, port, numq, 14669 BCM_COSQ_GPORT_SCHEDULER, 14670 &l1_sched)); 14671 BCM_IF_ERROR_RETURN 14672 (bcm_kt2_cosq_gport_attach(unit, l1_sched, l0_sched, 0)); 14673 for (cosq = 0; cosq < numq; cosq++) { 14674 BCM_IF_ERROR_RETURN 14675 (bcm_kt2_cosq_gport_add(unit, port, 1, 14676 BCM_COSQ_GPORT_UCAST_QUEUE_GROUP, &queue)); 14677 BCM_IF_ERROR_RETURN 14678 (bcm_kt2_cosq_gport_attach(unit, queue, l1_sched, 14679 cosq)); 14680 BCM_IF_ERROR_RETURN 14681 (bcm_kt2_cosq_gport_sched_set(unit, l1_sched, cosq, 14682 BCM_COSQ_STRICT, 0)); 14683 } 14684 }else { 14685 BCM_IF_ERROR_RETURN 14686 (_bcm_kt2_packing_config_set(unit, port, numq)); 14687 } 14688 } 14689 } 14690 } 14691 /* Initialize oob driver */ 14692 BCM_IF_ERROR_RETURN(_bcm_oob_init(unit)); 14693 14694 /* Add default entries for PORT_COS_MAP memory profile 14695 * for front panel ports 14696 */ 14697 BCM_IF_ERROR_RETURN(bcm_kt2_cosq_config_set(unit, numq)); 14698 14699 /* Add default entries for PORT_COS_MAP memory 14700 * profile for subports 14701 */ 14702 pp_port_cos = soc_property_port_get(unit, port, 14703 spn_NUM_SUBPORT_COS, 4); 14704 14705 BCM_IF_ERROR_RETURN(_bcm_kt2_subport_cosq_config_set(unit, pp_port_cos)); 14706 14707 /* setup subport specific LLS configuration */ 14708 BCM_IF_ERROR_RETURN(_bcm_kt2_subport_config_set(unit)); 14709 14710 if (!cosq_sync_lock[unit]) { 14711 cosq_sync_lock[unit] = sal_mutex_create("KT2 cosq sync lock"); 14712 if (cosq_sync_lock[unit] == NULL) { 14713 return BCM_E_MEMORY; 14714 } 14715 } 14716 14717 #ifdef BCM_WARM_BOOT_SUPPORT 14718 if (SOC_WARM_BOOT(unit)) { 14719 if (!SOC_IS_METROLITE(unit)) { 14720 SOC_PBMP_CLEAR(si->pbm_ext_mem); 14721 for (port = 1; port < si->lb_port; port++) { 14722 SOC_IF_ERROR_RETURN(READ_RQE_PP_PORT_CONFIGr(unit, port, &rval)); 14723 if (soc_reg_field_get(unit, RQE_PP_PORT_CONFIGr, rval, BUFF_TYPEf)) { 14724 SOC_PBMP_PORT_ADD(si->pbm_ext_mem, port); 14725 } 14726 } 14727 } 14728 return bcm_kt2_cosq_reinit(unit); 14729 } else { 14730 BCM_IF_ERROR_RETURN(_bcm_kt2_cosq_wb_alloc(unit)); 14731 } 14732 #endif /* BCM_WARM_BOOT_SUPPORT */ 14733 14734 14735 sal_memset(rval64s, 0, sizeof(rval64s)); 14736 prval64s[0] = rval64s; 14737 profile_index = 0xffffffff; 14738 PBMP_PORT_ITER(unit, port) { 14739 if (profile_index == 0xffffffff) { 14740 BCM_IF_ERROR_RETURN 14741 (soc_profile_reg_add(unit, _bcm_kt2_llfc_profile[unit], 14742 prval64s, 16, &profile_index)); 14743 } else { 14744 BCM_IF_ERROR_RETURN 14745 (soc_profile_reg_reference(unit, _bcm_kt2_llfc_profile[unit], 14746 profile_index, 0)); 14747 } 14748 } 14749 sal_memset(&entry_tcp_green, 0, sizeof(entry_tcp_green)); 14750 sal_memset(&entry_tcp_yellow, 0, sizeof(entry_tcp_yellow)); 14751 sal_memset(&entry_tcp_red, 0, sizeof(entry_tcp_red)); 14752 sal_memset(&entry_nontcp_green, 0, sizeof(entry_nontcp_green)); 14753 sal_memset(&entry_nontcp_yellow, 0, sizeof(entry_nontcp_yellow)); 14754 sal_memset(&entry_nontcp_red, 0, sizeof(entry_nontcp_red)); 14755 entries[0] = &entry_tcp_green; 14756 entries[1] = &entry_tcp_yellow; 14757 entries[2] = &entry_tcp_red; 14758 entries[3] = &entry_nontcp_green; 14759 entries[4] = &entry_nontcp_yellow; 14760 entries[5] = &entry_nontcp_red; 14761 max_threshold = (1 << soc_mem_field_length(unit, 14762 MMU_WRED_DROP_CURVE_PROFILE_0m, MAX_THDf)) - 1; 14763 min_threshold = (1 << soc_mem_field_length(unit, 14764 MMU_WRED_DROP_CURVE_PROFILE_0m, MIN_THDf)) - 1; 14765 for (i = 0; i < 6; i++) { 14766 soc_mem_field32_set(unit, wred_mems[i], entries[i], MIN_THDf, 14767 max_threshold); 14768 soc_mem_field32_set(unit, wred_mems[i], entries[i], MAX_THDf, 14769 min_threshold); 14770 } 14771 profile_index = 0xffffffff; 14772 for (port = 0; port < (si->lb_port + 1); port++) { 14773 if (SOC_IS_SABER2(unit) && (!SOC_IS_METROLITE(unit)) && 14774 soc_saber2_port_is_unused(unit, port)) { 14775 continue; 14776 } 14777 BCM_IF_ERROR_RETURN 14778 (_bcm_kt2_cosq_index_resolve(unit, port, -1, 14779 _BCM_KT2_COSQ_INDEX_STYLE_WRED, NULL, 14780 NULL, &numq)); 14781 for (cosq = 0; cosq < numq; cosq++) { 14782 if (profile_index == 0xffffffff) { 14783 BCM_IF_ERROR_RETURN 14784 (soc_profile_mem_add(unit, _bcm_kt2_wred_profile[unit], 14785 entries, 1, &profile_index)); 14786 } else { 14787 BCM_IF_ERROR_RETURN 14788 (soc_profile_mem_reference(unit, 14789 _bcm_kt2_wred_profile[unit], 14790 profile_index, 0)); 14791 } 14792 } 14793 } 14794 /* 14795 * Set all CPU queues to disable enqueue. Enqueue will be enabled when 14796 * RX DMA is enabled. This is to prevent packets from getting wedged in 14797 * the CMIC when they don't have a means of egressing from the CMIC. 14798 */ 14799 if (!(SAL_BOOT_SIMULATION) && !SOC_IS_RCPU_ONLY(unit)) { 14800 for (i = 0; i < NUM_CPU_COSQ(unit); i++) { 14801 rval = 0; 14802 soc_reg_field_set(unit, TOQ_FLUSH0r, &rval, FLUSH_ID0f, i); 14803 soc_reg_field_set(unit, TOQ_FLUSH0r, &rval, FLUSH_NUMf, 1); 14804 soc_reg_field_set(unit, TOQ_FLUSH0r, &rval, FLUSH_ACTIVEf, 1); 14805 if (SOC_PBMP_MEMBER (PBMP_EXT_MEM (unit), CMIC_PORT(unit))) { 14806 soc_reg_field_set(unit, TOQ_FLUSH0r, &rval, FLUSH_EXTERNALf, 1); 14807 } 14808 SOC_IF_ERROR_RETURN(WRITE_TOQ_FLUSH0r(unit, rval)); 14809 while (rval) { 14810 SOC_IF_ERROR_RETURN(READ_TOQ_FLUSH0r(unit, &rval)); 14811 rval = soc_reg_field_get(unit, TOQ_FLUSH0r, rval, 14812 FLUSH_ACTIVEf); 14813 } 14814 rval = 0; 14815 soc_reg_field_set(unit, TOQ_ERROR2r, &rval, FLUSH_COMPLETEf, 1); 14816 SOC_IF_ERROR_RETURN(WRITE_TOQ_ERROR2r(unit, rval)); 14817 } 14818 } 14819 14820 mmu_info_p->curr_merger_index[0] = 1; 14821 mmu_info_p->curr_merger_index[1] = 0; 14822 mmu_info_p->curr_merger_index[2] = 0; 14823 mmu_info_p->curr_merger_index[3] = 0; 14824 14825 if (SOC_IS_SABER2(unit)) { 14826 if (!SOC_WARM_BOOT(unit)) { /* Cold Boot */ 14827 WRITE_CMIC_CMC0_CH1_COS_CTRL_RX_1r(unit, 0xfffff); 14828 } 14829 } 14830 /* Clear Counters */ 14831 if (!SOC_WARM_BOOT(unit)) { 14832 BCM_IF_ERROR_RETURN(_bcm_kt2_init_all_queue_counters(unit)); 14833 } 14834 /* 14835 * Enable the MMU to CPU flow control 14836 * per L0 nodes 14837 */ 14838 BCM_IF_ERROR_RETURN 14839 (_bcm_kt2_cosq_cpu_fc_set(unit)); 14840 BCM_IF_ERROR_RETURN 14841 (bcm_kt2_init_fc_map_tbl(unit)); 14842 return BCM_E_NONE; 14843 } 14844 14845 /* 14846 * Function: 14847 * bcm_kt2_cosq_detach 14848 * Purpose: 14849 * Discard all COS schedule/mapping state. 14850 * Parameters: 14851 * unit - unit number 14852 * Returns: 14853 * BCM_E_XXX 14854 */ 14855 int 14856 bcm_kt2_cosq_detach(int unit, int software_state_only) 14857 { 14858 if (_bcm_kt2_cos_map_profile[unit] != NULL) { 14859 SOC_IF_ERROR_RETURN(soc_profile_mem_destroy(unit, 14860 _bcm_kt2_cos_map_profile[unit])); 14861 sal_free(_bcm_kt2_cos_map_profile[unit]); 14862 _bcm_kt2_cos_map_profile[unit] = NULL; 14863 } 14864 if (_bcm_kt2_egr_cos_map_profile[unit] != NULL) { 14865 SOC_IF_ERROR_RETURN(soc_profile_mem_destroy(unit, 14866 _bcm_kt2_egr_cos_map_profile[unit])); 14867 sal_free(_bcm_kt2_egr_cos_map_profile[unit]); 14868 _bcm_kt2_egr_cos_map_profile[unit] = NULL; 14869 } 14870 if (_bcm_kt2_ifp_cos_map_profile[unit] != NULL) { 14871 SOC_IF_ERROR_RETURN(soc_profile_mem_destroy(unit, 14872 _bcm_kt2_ifp_cos_map_profile[unit])); 14873 sal_free(_bcm_kt2_ifp_cos_map_profile[unit]); 14874 _bcm_kt2_ifp_cos_map_profile[unit] = NULL; 14875 } 14876 if (_bcm_kt2_wred_profile[unit] != NULL) { 14877 SOC_IF_ERROR_RETURN(soc_profile_mem_destroy(unit, 14878 _bcm_kt2_wred_profile[unit])); 14879 sal_free(_bcm_kt2_wred_profile[unit]); 14880 _bcm_kt2_wred_profile[unit] = NULL; 14881 } 14882 if (_bcm_kt2_llfc_profile[unit] != NULL) { 14883 SOC_IF_ERROR_RETURN(soc_profile_reg_destroy(unit, 14884 _bcm_kt2_llfc_profile[unit])); 14885 sal_free(_bcm_kt2_llfc_profile[unit]); 14886 _bcm_kt2_llfc_profile[unit] = NULL; 14887 } 14888 if (_bcm_kt2_mmu_info[unit] != NULL) { 14889 _bcm_kt2_cosq_free_memory(_bcm_kt2_mmu_info[unit]); 14890 sal_free(_bcm_kt2_mmu_info[unit]); 14891 _bcm_kt2_mmu_info[unit] = NULL; 14892 } 14893 if (cosq_sync_lock[unit]) { 14894 sal_mutex_destroy(cosq_sync_lock[unit]); 14895 cosq_sync_lock[unit] = NULL; 14896 } 14897 return BCM_E_NONE; 14898 } 14899 14900 /* 14901 * Function: 14902 * _bcm_kt2_subport_cosq_config_set 14903 * Purpose: 14904 * Set the number of COS queues for subports. 14905 * Parameters: 14906 * unit - unit number 14907 * numq - number of COS queues (1-8). 14908 * Returns: 14909 * BCM_E_XXX 14910 */ 14911 int 14912 _bcm_kt2_subport_cosq_config_set(int unit, int numq) 14913 { 14914 port_cos_map_entry_t cos_map_entries[16]; 14915 void *entries[1]; 14916 uint32 index , egr_index; 14917 int count; 14918 bcm_port_t port; 14919 int cos, prio; 14920 uint32 i; 14921 bcm_pbmp_t subport_pbmp; 14922 14923 BCM_PBMP_CLEAR(subport_pbmp); 14924 BCM_PBMP_ASSIGN(subport_pbmp, SOC_INFO(unit).subtag_pp_port_pbm); 14925 BCM_PBMP_OR(subport_pbmp, SOC_INFO(unit).linkphy_pp_port_pbm); 14926 14927 if (numq < 1 || numq > 8) { 14928 return BCM_E_PARAM; 14929 } 14930 SOC_PBMP_COUNT(subport_pbmp,count); 14931 if (count == 0) { 14932 return BCM_E_NONE; 14933 } 14934 14935 /* Distribute first 8 internal priority levels into the specified number 14936 * of cosq, map remaining internal priority levels to highest priority 14937 * cosq. 14938 */ 14939 sal_memset(cos_map_entries, 0, sizeof(cos_map_entries)); 14940 entries[0] = &cos_map_entries; 14941 prio = 0; 14942 for (cos = 0; cos < numq; cos++) { 14943 for (i = 8 / numq + (cos < 8 % numq ? 1 : 0); i > 0; i--) { 14944 soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio], 14945 COSf, cos); 14946 prio++; 14947 } 14948 } 14949 for (prio = 8; prio < 16; prio++) { 14950 soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio], COSf, 14951 numq - 1); 14952 } 14953 14954 BCM_IF_ERROR_RETURN 14955 (soc_profile_mem_add(unit, _bcm_kt2_cos_map_profile[unit], entries, 16, 14956 &index)); 14957 BCM_IF_ERROR_RETURN 14958 (soc_profile_mem_add(unit, _bcm_kt2_egr_cos_map_profile[unit], entries, 16, 14959 &egr_index)); 14960 14961 PBMP_ITER(subport_pbmp, port) { 14962 BCM_IF_ERROR_RETURN 14963 (soc_mem_field32_modify(unit, COS_MAP_SELm, port, SELECTf, 14964 index / 16)); 14965 BCM_IF_ERROR_RETURN 14966 (soc_mem_field32_modify(unit, EGR_PORTm, port, EGR_COS_MAP_SELf, 14967 egr_index / 16)); 14968 14969 } 14970 14971 for (i = 0; i < count; i++) { 14972 soc_profile_mem_reference(unit, _bcm_kt2_cos_map_profile[unit], index, 14973 0); 14974 soc_profile_mem_reference(unit, _bcm_kt2_egr_cos_map_profile[unit], egr_index, 14975 0); 14976 14977 } 14978 14979 return BCM_E_NONE; 14980 } 14981 14982 /* 14983 * Function: 14984 * bcm_kt2_cosq_config_set 14985 * Purpose: 14986 * Set the number of COS queues 14987 * Parameters: 14988 * unit - unit number 14989 * numq - number of COS queues (1-8). 14990 * Returns: 14991 * BCM_E_XXX 14992 */ 14993 int 14994 bcm_kt2_cosq_config_set(int unit, int numq) 14995 { 14996 port_cos_map_entry_t cos_map_entries[16]; 14997 void *entries[1], *hg_entries[1]; 14998 uint32 index, hg_index, egr_index; 14999 int count, hg_count, egr_count; 15000 bcm_port_t port; 15001 int cos, prio; 15002 uint32 i; 15003 int cpu_hg_index = 0; 15004 #ifdef BCM_COSQ_HIGIG_MAP_DISABLE 15005 port_cos_map_entry_t hg_cos_map_entries[16]; 15006 #endif 15007 bcm_pbmp_t all_pbmp; 15008 int *profile_ref_count, profile_count, ref_count, rv; 15009 cos_map_sel_entry_t cos_map_sel_entry; 15010 15011 BCM_PBMP_CLEAR(all_pbmp); 15012 BCM_PBMP_ASSIGN(all_pbmp, PBMP_ALL(unit)); 15013 15014 15015 if (numq < 1 || numq > 8) { 15016 return BCM_E_PARAM; 15017 } 15018 15019 if(SOC_WARM_BOOT(unit)) { 15020 _bcm_kt2_num_cosq[unit] = numq; 15021 return BCM_E_NONE; 15022 } 15023 15024 profile_count = (soc_mem_index_count(unit, PORT_COS_MAPm) / 16); 15025 profile_ref_count = sal_alloc(profile_count * sizeof(int), 15026 "Profile reference count"); 15027 15028 sal_memset(profile_ref_count, 0, profile_count * sizeof(int)); 15029 15030 if ( soc_feature(unit, soc_feature_flex_port)) { 15031 rv = _bcm_kt2_flexio_pbmp_update(unit, &all_pbmp); 15032 if (BCM_FAILURE(rv)) { 15033 sal_free(profile_ref_count); 15034 return rv; 15035 } 15036 } 15037 15038 /* Get the profile reference count for front panel ports. */ 15039 PBMP_ITER(all_pbmp, port) { 15040 rv = READ_COS_MAP_SELm(unit, MEM_BLOCK_ANY, port, &cos_map_sel_entry); 15041 if (BCM_FAILURE(rv)) { 15042 sal_free(profile_ref_count); 15043 return rv; 15044 } 15045 index = soc_mem_field32_get(unit, COS_MAP_SELm, &cos_map_sel_entry, SELECTf); 15046 if (index >= profile_count) { 15047 LOG_ERROR(BSL_LS_BCM_COMMON, 15048 (BSL_META_U(unit, 15049 "Error. COS_MAP_SEL value %d greater than expected %d.\n"), index, profile_count)); 15050 sal_free(profile_ref_count); 15051 return BCM_E_INTERNAL; 15052 } 15053 profile_ref_count[index]++; 15054 } 15055 15056 cpu_hg_index = SOC_INFO(unit).cpu_hg_pp_port_index; 15057 if (cpu_hg_index != -1) { 15058 rv = READ_COS_MAP_SELm(unit, MEM_BLOCK_ANY, cpu_hg_index, &cos_map_sel_entry); 15059 if (BCM_FAILURE(rv)) { 15060 sal_free(profile_ref_count); 15061 return rv; 15062 } 15063 index = soc_mem_field32_get(unit, COS_MAP_SELm, &cos_map_sel_entry, SELECTf); 15064 if (index >= profile_count) { 15065 LOG_ERROR(BSL_LS_BCM_COMMON, 15066 (BSL_META_U(unit, 15067 "Error. COS_MAP_SEL value %d greater than expected %d.\n"), index, profile_count)); 15068 sal_free(profile_ref_count); 15069 return BCM_E_INTERNAL; 15070 } 15071 profile_ref_count[index]++; 15072 } 15073 15074 /* Clear out old profile referenced with front panel ports */ 15075 index = 0; 15076 while (index < profile_count) { 15077 rv = soc_profile_mem_ref_count_get(unit, 15078 _bcm_kt2_cos_map_profile[unit], 15079 (index * 16), &ref_count); 15080 if (BCM_FAILURE(rv)) { 15081 sal_free(profile_ref_count); 15082 return rv; 15083 } 15084 while(profile_ref_count[index] && ref_count) { 15085 rv = soc_profile_mem_delete(unit, 15086 _bcm_kt2_cos_map_profile[unit], (index * 16)); 15087 if (BCM_FAILURE(rv)) { 15088 sal_free(profile_ref_count); 15089 return rv; 15090 } 15091 profile_ref_count[index]--; 15092 ref_count--; 15093 } 15094 /* Clear egress cos_map profile */ 15095 rv = soc_profile_mem_ref_count_get(unit, 15096 _bcm_kt2_egr_cos_map_profile[unit], 15097 (index * 16), &egr_count); 15098 if (BCM_FAILURE(rv)) { 15099 sal_free(profile_ref_count); 15100 return rv; 15101 } 15102 while(egr_count) { 15103 rv = soc_profile_mem_delete(unit, 15104 _bcm_kt2_egr_cos_map_profile[unit], (index * 16)); 15105 if (BCM_FAILURE(rv)) { 15106 sal_free(profile_ref_count); 15107 return rv; 15108 } 15109 egr_count--; 15110 } 15111 index++; 15112 } 15113 sal_free(profile_ref_count); 15114 15115 /* Distribute first 8 internal priority levels into the specified number 15116 * of cosq, map remaining internal priority levels to highest priority 15117 * cosq */ 15118 sal_memset(cos_map_entries, 0, sizeof(cos_map_entries)); 15119 entries[0] = &cos_map_entries; 15120 hg_entries[0] = &cos_map_entries; 15121 prio = 0; 15122 for (cos = 0; cos < numq; cos++) { 15123 for (i = 8 / numq + (cos < 8 % numq ? 1 : 0); i > 0; i--) { 15124 soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio], 15125 COSf, cos); 15126 soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio], 15127 HG_COSf, cos); 15128 prio++; 15129 } 15130 } 15131 for (prio = 8; prio < 16; prio++) { 15132 soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio], COSf, 15133 numq - 1); 15134 soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio],HG_COSf, 15135 numq - 1); 15136 } 15137 15138 /* Map internal priority levels to CPU CoS queues */ 15139 BCM_IF_ERROR_RETURN(_bcm_esw_cpu_cosq_mapping_default_set(unit, numq)); 15140 15141 #ifdef BCM_COSQ_HIGIG_MAP_DISABLE 15142 /* Use identical mapping for Higig port */ 15143 sal_memset(hg_cos_map_entries, 0, sizeof(hg_cos_map_entries)); 15144 hg_entries[0] = &hg_cos_map_entries; 15145 prio = 0; 15146 for (prio = 0; prio < 8; prio++) { 15147 soc_mem_field32_set(unit, PORT_COS_MAPm, &hg_cos_map_entries[prio], 15148 COSf, prio); 15149 } 15150 for (prio = 8; prio < 16; prio++) { 15151 soc_mem_field32_set(unit, PORT_COS_MAPm, &hg_cos_map_entries[prio], 15152 COSf, 7); 15153 } 15154 15155 #endif /* BCM_COSQ_HIGIG_MAP_DISABLE */ 15156 15157 BCM_IF_ERROR_RETURN 15158 (soc_profile_mem_add(unit, _bcm_kt2_cos_map_profile[unit], entries, 16, 15159 &index)); 15160 BCM_IF_ERROR_RETURN 15161 (soc_profile_mem_add(unit, _bcm_kt2_cos_map_profile[unit], hg_entries, 15162 16, &hg_index)); 15163 BCM_IF_ERROR_RETURN 15164 (soc_profile_mem_add(unit, _bcm_kt2_egr_cos_map_profile[unit], entries, 16, 15165 &egr_index)); 15166 count = 0; 15167 hg_count = 0; 15168 15169 PBMP_ITER(all_pbmp, port) { 15170 if (IS_HG_PORT(unit, port)) { 15171 BCM_IF_ERROR_RETURN 15172 (soc_mem_field32_modify(unit, COS_MAP_SELm, port, SELECTf, 15173 hg_index / 16)); 15174 hg_count++; 15175 } else { 15176 BCM_IF_ERROR_RETURN 15177 (soc_mem_field32_modify(unit, COS_MAP_SELm, port, SELECTf, 15178 index / 16)); 15179 count++; 15180 } 15181 BCM_IF_ERROR_RETURN 15182 (soc_mem_field32_modify(unit, EGR_PORTm, port, EGR_COS_MAP_SELf, 15183 egr_index / 16)); 15184 soc_profile_mem_reference(unit, _bcm_kt2_egr_cos_map_profile[unit], egr_index, 15185 0); 15186 } 15187 15188 cpu_hg_index = SOC_INFO(unit).cpu_hg_pp_port_index; 15189 if (cpu_hg_index != -1) { 15190 BCM_IF_ERROR_RETURN 15191 (soc_mem_field32_modify(unit, COS_MAP_SELm, 15192 cpu_hg_index, SELECTf, 15193 hg_index / 16)); 15194 hg_count++; 15195 } 15196 15197 for (i = 1; i < count; i++) { 15198 soc_profile_mem_reference(unit, _bcm_kt2_cos_map_profile[unit], index, 15199 0); 15200 } 15201 for (i = 1; i < hg_count; i++) { 15202 soc_profile_mem_reference(unit, _bcm_kt2_cos_map_profile[unit], 15203 hg_index, 0); 15204 } 15205 15206 _bcm_kt2_num_cosq[unit] = numq; 15207 15208 return BCM_E_NONE; 15209 } 15210 15211 /* 15212 * Function: 15213 * bcm_kt2_cosq_config_get 15214 * Purpose: 15215 * Get the number of cos queues 15216 * Parameters: 15217 * unit - unit number 15218 * numq - (Output) number of cosq 15219 * Returns: 15220 * BCM_E_XXX 15221 */ 15222 int 15223 bcm_kt2_cosq_config_get(int unit, int *numq) 15224 { 15225 if (_bcm_kt2_num_cosq[unit] == 0) { 15226 return BCM_E_INIT; 15227 } 15228 15229 if (numq != NULL) { 15230 *numq = _bcm_kt2_num_cosq[unit]; 15231 } 15232 15233 return BCM_E_NONE; 15234 } 15235 15236 int 15237 bcm_kt2_cosq_gport_reattach(int unit, bcm_gport_t sched_gport, 15238 bcm_gport_t input_gport, bcm_cos_queue_t cosq) 15239 { 15240 _bcm_kt2_cosq_node_t *sched_node; 15241 _bcm_kt2_mmu_info_t *mmu_info; 15242 _bcm_kt2_cosq_node_t *parent , *new_parent; 15243 int cycle_sel = 0, index, rate_exp = 0; 15244 int thld_exp = 0, max_bucket = 0; 15245 bcm_port_t old_port, new_port; 15246 int alloc_size; 15247 int max_nodes; 15248 int temp_index; 15249 _bcm_kt2_cosq_list_t *list; 15250 15251 if (!BCM_GPORT_IS_SCHEDULER(sched_gport)) { 15252 return BCM_E_PARAM; 15253 } 15254 15255 if (cosq < -1) { 15256 return BCM_E_PARAM; 15257 } 15258 15259 BCM_IF_ERROR_RETURN 15260 (_bcm_kt2_cosq_node_get(unit, sched_gport, NULL, NULL, NULL, 15261 &sched_node)); 15262 15263 if (sched_node->cosq_attached_to < 0) { 15264 /* Not yet attached */ 15265 return BCM_E_PARAM; 15266 } 15267 15268 if (!(sched_node->level == _BCM_KT2_COSQ_NODE_LEVEL_L0 || 15269 sched_node->level == _BCM_KT2_COSQ_NODE_LEVEL_L1)) { 15270 return BCM_E_PARAM; 15271 } 15272 15273 15274 BCM_IF_ERROR_RETURN 15275 (_bcm_kt2_cosq_node_get(unit, input_gport, NULL, &new_port, NULL, 15276 &new_parent)); 15277 if ((new_parent->wrr_mode == 0) || (sched_node->parent->wrr_mode == 0)) { 15278 return BCM_E_PARAM; 15279 } 15280 15281 if (new_parent->cosq_map == NULL) { 15282 BCM_IF_ERROR_RETURN 15283 (_bcm_kt2_cosq_max_nodes_get(unit, sched_node->level, &max_nodes)); 15284 if (new_parent->numq == -1) { 15285 new_parent->numq = max_nodes; 15286 } else { 15287 if (new_parent->numq > max_nodes) { 15288 return BCM_E_PARAM; 15289 } 15290 } 15291 15292 alloc_size = SHR_BITALLOCSIZE(new_parent->numq); 15293 new_parent->cosq_map = _bcm_kt2_cosq_alloc_clear(alloc_size, 15294 "new_parent->cosq_map"); 15295 if (new_parent->cosq_map == NULL) { 15296 return BCM_E_MEMORY; 15297 } 15298 } 15299 15300 if (cosq < 0) { 15301 BCM_IF_ERROR_RETURN 15302 (_bcm_kt2_cosq_map_index_get(new_parent->cosq_map, 15303 0, new_parent->numq, &cosq)); 15304 } else { 15305 if (_bcm_kt2_cosq_map_index_is_set(new_parent->cosq_map, 15306 cosq) == TRUE) { 15307 return BCM_E_EXISTS; 15308 } 15309 } 15310 15311 BCM_IF_ERROR_RETURN 15312 (_bcm_kt2_cosq_index_resolve(unit, sched_gport, sched_node->cosq_attached_to, 15313 _BCM_KT2_COSQ_INDEX_STYLE_BUCKET, 15314 NULL, &index, NULL)); 15315 15316 /* set max shaper with cycle_sel = 0xF, and store old cycle_sel */ 15317 BCM_IF_ERROR_RETURN 15318 (_bcm_kt_cosq_bucket_stop(unit, index, sched_node->level, 15319 &cycle_sel, &rate_exp, &thld_exp, &max_bucket)); 15320 15321 parent = sched_node->parent; 15322 BCM_IF_ERROR_RETURN 15323 (_bcm_kt2_cosq_node_get(unit, parent->gport, NULL, &old_port, NULL, 15324 NULL)); 15325 temp_index = sched_node->hw_index; 15326 15327 /* detach from old parent */ 15328 BCM_IF_ERROR_RETURN 15329 (bcm_kt2_cosq_gport_detach(unit, sched_gport, parent->gport, 15330 sched_node->cosq_attached_to)); 15331 mmu_info = _bcm_kt2_mmu_info[unit]; 15332 list = &mmu_info->sched_hw_list[sched_node->level]; 15333 _bcm_kt2_node_index_set(list, temp_index, 1); 15334 15335 sched_node->hw_index = temp_index; 15336 15337 /* attach to new parent */ 15338 BCM_IF_ERROR_RETURN 15339 (bcm_kt2_cosq_gport_attach(unit, sched_gport, input_gport, cosq)); 15340 15341 /* update queue map to reflect new port */ 15342 if (old_port != new_port) { 15343 BCM_IF_ERROR_RETURN 15344 (_bcm_kt2_cosq_queue_map_set(unit, sched_node, new_port)); 15345 } 15346 15347 /* restore cycle_sel */ 15348 BCM_IF_ERROR_RETURN 15349 (_bcm_kt_cosq_bucket_start(unit, index, sched_node->level, 15350 cycle_sel, rate_exp, thld_exp, max_bucket)); 15351 15352 return BCM_E_NONE; 15353 } 15354 /* 15355 * Function: 15356 * bcm_kt2_cosq_gport_attach 15357 * Purpose: 15358 * Attach sched_port to the specified index (cosq) of input_port 15359 * Parameters: 15360 * unit - (IN) unit number 15361 * sched_port - (IN) scheduler GPORT identifier 15362 * input_port - (IN) GPORT to attach to 15363 * cosq - (IN) COS queue to attach to (-1 for first available cosq) 15364 * Returns: 15365 * BCM_E_XXX 15366 */ 15367 int 15368 bcm_kt2_cosq_gport_attach(int unit, bcm_gport_t sched_gport, 15369 bcm_gport_t input_gport, bcm_cos_queue_t cosq) 15370 { 15371 _bcm_kt2_cosq_node_t *sched_node, *input_node; 15372 bcm_port_t sched_port, input_port, local_port; 15373 int rv, max_nodes; 15374 int status = 0; 15375 _bcm_kt2_subport_info_t subport_info; 15376 15377 if (_bcm_kt2_mmu_info[unit] == NULL) { 15378 return BCM_E_INIT; 15379 } 15380 15381 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(input_gport) || 15382 BCM_GPORT_IS_MCAST_QUEUE_GROUP(input_gport) || 15383 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(input_gport) || 15384 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(input_gport) || 15385 BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(input_gport)) { 15386 return BCM_E_PORT; 15387 } 15388 15389 if(!(BCM_GPORT_IS_UCAST_QUEUE_GROUP(sched_gport) || 15390 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(sched_gport) || 15391 BCM_GPORT_IS_MCAST_QUEUE_GROUP(sched_gport) || 15392 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(sched_gport) || 15393 BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(sched_gport) || 15394 BCM_GPORT_IS_SCHEDULER(sched_gport))) { 15395 return BCM_E_PORT; 15396 } 15397 15398 if (cosq < -1) { 15399 return BCM_E_PARAM; 15400 } 15401 15402 BCM_IF_ERROR_RETURN 15403 (_bcm_kt2_cosq_node_get(unit, sched_gport, NULL, &sched_port, NULL, 15404 &sched_node)); 15405 15406 if (sched_node->cosq_attached_to >= 0) { 15407 /* Has already attached */ 15408 return BCM_E_EXISTS; 15409 } 15410 15411 if (BCM_GPORT_IS_SCHEDULER(input_gport) || 15412 BCM_GPORT_IS_LOCAL(input_gport) || 15413 BCM_GPORT_IS_MODPORT(input_gport)) { 15414 BCM_IF_ERROR_RETURN 15415 (_bcm_kt2_cosq_node_get(unit, input_gport, NULL, &input_port, NULL, 15416 &input_node)); 15417 } else { 15418 BCM_IF_ERROR_RETURN 15419 (_bcm_kt2_cosq_localport_resolve(unit, input_gport, &input_port)); 15420 input_node = NULL; 15421 } 15422 15423 if (input_node != NULL) { 15424 if (!BCM_GPORT_IS_SCHEDULER(input_gport)) { 15425 if (input_node->numq == 0) { 15426 local_port = (BCM_GPORT_IS_LOCAL(input_gport)) ? 15427 BCM_GPORT_LOCAL_GET(input_gport) : 15428 BCM_GPORT_MODPORT_PORT_GET(input_gport); 15429 input_node->gport = input_gport; 15430 input_node->hw_index = local_port; 15431 input_node->level = _BCM_KT2_COSQ_NODE_LEVEL_ROOT; 15432 input_node->cosq_attached_to = 0; 15433 input_node->numq = 4; /* Assign max of 4 L0 nodes */ 15434 input_node->base_index = -1; 15435 } 15436 15437 if (!BCM_GPORT_IS_SCHEDULER(sched_gport)) { 15438 return BCM_E_PARAM; 15439 } 15440 15441 sched_node->level = (!_bcm_is_port_linkphy_subport(unit, sched_gport, 15442 num_port_schedulers[unit])) ? 15443 _BCM_KT2_COSQ_NODE_LEVEL_L0 : 15444 _BCM_KT2_COSQ_NODE_LEVEL_S0; 15445 } else { 15446 if (input_node->level == _BCM_KT2_COSQ_NODE_LEVEL_ROOT) { 15447 if (!BCM_GPORT_IS_SCHEDULER(input_gport)) { 15448 return BCM_E_PARAM; 15449 } 15450 sched_node->level = 15451 (!_bcm_is_port_linkphy_subport(unit, sched_gport, 15452 num_port_schedulers[unit])) ? 15453 _BCM_KT2_COSQ_NODE_LEVEL_L0 : 15454 _BCM_KT2_COSQ_NODE_LEVEL_S0; 15455 } 15456 15457 if (BCM_GPORT_IS_SCHEDULER(input_gport) && 15458 BCM_GPORT_IS_SCHEDULER(sched_gport)) { 15459 if (input_node->level == _BCM_KT2_COSQ_NODE_LEVEL_S0) { 15460 BCM_IF_ERROR_RETURN 15461 (bcm_kt2_subport_pp_port_subport_info_get(unit, 15462 input_port, 15463 &subport_info)); 15464 if (subport_info.port_type == _BCM_KT2_SUBPORT_TYPE_LINKPHY) { 15465 if (SOC_IS_METROLITE(unit)) { 15466 sched_node->level = _BCM_KT2_COSQ_NODE_LEVEL_L0; 15467 } else { 15468 sched_node->level = _BCM_KT2_COSQ_NODE_LEVEL_S1; 15469 } 15470 input_node->linkphy_enabled = 1; 15471 } else { 15472 sched_node->level = _BCM_KT2_COSQ_NODE_LEVEL_L0; 15473 } 15474 } 15475 if (input_node->level == _BCM_KT2_COSQ_NODE_LEVEL_S1) { 15476 sched_node->level = _BCM_KT2_COSQ_NODE_LEVEL_L0; 15477 } 15478 if (input_node->level == _BCM_KT2_COSQ_NODE_LEVEL_L0) { 15479 sched_node->level = _BCM_KT2_COSQ_NODE_LEVEL_L1; 15480 } 15481 } 15482 15483 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(sched_gport) || 15484 BCM_GPORT_IS_MCAST_QUEUE_GROUP(sched_gport) || 15485 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(sched_gport) || 15486 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(sched_gport) || 15487 BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(sched_gport)) { 15488 if (!BCM_GPORT_IS_SCHEDULER(input_gport)) { 15489 return BCM_E_PARAM; 15490 } 15491 if (input_node->level != _BCM_KT2_COSQ_NODE_LEVEL_L1) { 15492 return BCM_E_PARAM; 15493 } 15494 sched_node->level = _BCM_KT2_COSQ_NODE_LEVEL_L2; 15495 } 15496 15497 BCM_IF_ERROR_RETURN 15498 (_bcm_kt2_cosq_max_nodes_get(unit, sched_node->level, &max_nodes)); 15499 if (input_node->numq == -1) { 15500 input_node->numq = max_nodes; 15501 } else { 15502 if (input_node->numq > max_nodes) { 15503 return BCM_E_PARAM; 15504 } 15505 } 15506 } 15507 15508 if (input_node->cosq_attached_to < 0) { 15509 /* Only allow to attach to a node that has already attached */ 15510 return BCM_E_PARAM; 15511 } 15512 if (cosq < -1 || (input_node->numq != -1 && cosq >= input_node->numq)) { 15513 return BCM_E_PARAM; 15514 } 15515 } 15516 15517 if (BCM_GPORT_IS_SCHEDULER(input_gport) || 15518 BCM_GPORT_IS_LOCAL(input_gport) || 15519 BCM_GPORT_IS_MODPORT(input_gport)) { 15520 if (input_node->cosq_attached_to < 0) { 15521 /* dont allow to attach to a node that has already attached */ 15522 return BCM_E_PARAM; 15523 } 15524 15525 sched_node->parent = input_node; 15526 sched_node->sibling = input_node->child; 15527 input_node->child = sched_node; 15528 /* resolve the nodes */ 15529 rv = _bcm_kt2_cosq_node_resolve(unit, sched_node, cosq); 15530 if (BCM_FAILURE(rv)) { 15531 input_node->child = sched_node->sibling; 15532 return rv; 15533 } 15534 15535 /* Protect LLS hierachy change as 15536 * port flush on link flap might be effected 15537 * when there is a change in the LLS hierarchy 15538 */ 15539 SOC_LLS_SCHEDULER_LOCK(unit); 15540 soc_kt_port_flush_state_get(unit, input_port, &status); 15541 if (status) { 15542 LOG_ERROR(BSL_LS_BCM_COSQ, 15543 (BSL_META_U(unit, 15544 "Unit %d Port %d is in flush state, Cannot change LLS hierarchy." 15545 "\n Attach of Cosq hw_cosq=%d failed.\n"), 15546 unit, input_port, sched_node->cosq_attached_to)); 15547 15548 input_node->child = sched_node->sibling; 15549 SOC_LLS_SCHEDULER_UNLOCK(unit); 15550 return BCM_E_RESOURCE; 15551 } 15552 15553 rv = _bcm_kt2_cosq_sched_node_set(unit, sched_gport, 15554 _BCM_KT2_COSQ_STATE_ENABLE); 15555 SOC_LLS_SCHEDULER_UNLOCK(unit); 15556 if (BCM_FAILURE(rv)) { 15557 return rv; 15558 } 15559 15560 /* Set the default sched mode to SP. In case where 15561 * BCM_COSQ_GPORT_SCHEDULER_WFQ flag is set or packing mode is set 15562 * or cosq offset is greater than 8, we need to set to WRR. 15563 */ 15564 if (BCM_GPORT_IS_SCHEDULER(input_gport)) { 15565 if (input_node->wrr_mode || 15566 ((sched_node->level == _BCM_KT2_COSQ_NODE_LEVEL_L2) && 15567 (soc_feature(unit, soc_feature_mmu_packing))) || 15568 (sched_node->cosq_attached_to >= 8)) { 15569 BCM_IF_ERROR_RETURN 15570 (bcm_kt2_cosq_gport_sched_set(unit, input_gport, 15571 sched_node->cosq_attached_to, 15572 BCM_COSQ_WEIGHTED_ROUND_ROBIN, 15573 1)); 15574 } else if (sched_node->level == _BCM_KT2_COSQ_NODE_LEVEL_S0) { 15575 BCM_IF_ERROR_RETURN 15576 (bcm_kt2_subport_pp_port_subport_info_get(unit, sched_port, 15577 &subport_info)); 15578 if (subport_info.port_type == _BCM_KT2_SUBPORT_TYPE_LINKPHY) { 15579 BCM_IF_ERROR_RETURN 15580 (bcm_kt2_cosq_gport_sched_set(unit, input_gport, 15581 sched_node->cosq_attached_to, 15582 BCM_COSQ_WEIGHTED_ROUND_ROBIN, 15583 1)); 15584 } 15585 } else { 15586 BCM_IF_ERROR_RETURN 15587 (bcm_kt2_cosq_gport_sched_set(unit, input_gport, 15588 sched_node->cosq_attached_to, 15589 BCM_COSQ_STRICT, 0)); 15590 } 15591 } 15592 15593 LOG_INFO(BSL_LS_BCM_COSQ, 15594 (BSL_META_U(unit, 15595 " hw_cosq=%d\n"), 15596 sched_node->cosq_attached_to)); 15597 } else { 15598 return BCM_E_PORT; 15599 } 15600 15601 return BCM_E_NONE; 15602 } 15603 15604 int 15605 bcm_kt2_cosq_gport_validate(int unit, bcm_gport_t sched_gport, 15606 bcm_gport_t input_gport, bcm_cos_queue_t cosq) 15607 { 15608 _bcm_kt2_cosq_node_t *sched_node, *input_node; 15609 bcm_port_t sched_port, input_port; 15610 15611 if (_bcm_kt2_mmu_info[unit] == NULL) { 15612 return BCM_E_INIT; 15613 } 15614 15615 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(input_gport) || 15616 BCM_GPORT_IS_MCAST_QUEUE_GROUP(input_gport) || 15617 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(input_gport) || 15618 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(input_gport) || 15619 BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(input_gport)) { 15620 return BCM_E_PORT; 15621 } 15622 15623 if(!(BCM_GPORT_IS_UCAST_QUEUE_GROUP(sched_gport) || 15624 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(sched_gport) || 15625 BCM_GPORT_IS_MCAST_QUEUE_GROUP(sched_gport) || 15626 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(sched_gport) || 15627 BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(sched_gport) || 15628 BCM_GPORT_IS_SCHEDULER(sched_gport))) { 15629 return BCM_E_PORT; 15630 } 15631 15632 BCM_IF_ERROR_RETURN 15633 (_bcm_kt2_cosq_node_get(unit, sched_gport, NULL, &sched_port, NULL, 15634 &sched_node)); 15635 15636 if (BCM_GPORT_IS_SCHEDULER(input_gport) || 15637 BCM_GPORT_IS_LOCAL(input_gport) || 15638 BCM_GPORT_IS_MODPORT(input_gport)) { 15639 BCM_IF_ERROR_RETURN 15640 (_bcm_kt2_cosq_node_get(unit, input_gport, NULL, &input_port, NULL, 15641 &input_node)); 15642 } else { 15643 BCM_IF_ERROR_RETURN 15644 (_bcm_kt2_cosq_localport_resolve(unit, input_gport, &input_port)); 15645 input_node = NULL; 15646 } 15647 15648 #if defined BCM_METROLITE_SUPPORT 15649 if (soc_feature(unit, soc_feature_discontinuous_pp_port)) { 15650 if ((sched_port < num_port_schedulers[unit]) && 15651 (input_port < num_port_schedulers[unit]) && 15652 (sched_port != input_port) && 15653 (!(_SOC_IS_PP_PORT_LINKPHY_SUBTAG(unit, sched_port) || 15654 _SOC_IS_PP_PORT_LINKPHY_SUBTAG(unit, input_port)))) { 15655 return BCM_E_PORT; 15656 } 15657 } else 15658 #endif 15659 { 15660 if ((sched_port < num_port_schedulers[unit]) && 15661 (input_port < num_port_schedulers[unit]) && 15662 (sched_port != input_port)) { 15663 return BCM_E_PORT; 15664 } 15665 } 15666 return BCM_E_NONE; 15667 } 15668 15669 15670 /* 15671 * Function: 15672 * bcm_kt2_cosq_gport_detach 15673 * Purpose: 15674 * Detach sched_port to the specified index (cosq) of input_port 15675 * Parameters: 15676 * unit - (IN) unit number 15677 * sched_port - (IN) scheduler GPORT identifier 15678 * input_port - (IN) GPORT to attach to 15679 * cosq - (IN) COS queue to attach to (-1 for first available cosq) 15680 * Returns: 15681 * BCM_E_XXX 15682 */ 15683 int 15684 bcm_kt2_cosq_gport_detach(int unit, bcm_gport_t sched_gport, 15685 bcm_gport_t input_gport, bcm_cos_queue_t cosq) 15686 { 15687 _bcm_kt2_cosq_node_t *sched_node, *input_node, *prev_node; 15688 bcm_port_t sched_port, input_port; 15689 int rv; 15690 int status = 0; 15691 15692 if (_bcm_kt2_mmu_info[unit] == NULL) { 15693 return BCM_E_INIT; 15694 } 15695 15696 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(input_gport) || 15697 BCM_GPORT_IS_MCAST_QUEUE_GROUP(input_gport) || 15698 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(input_gport) || 15699 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(input_gport) || 15700 BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(input_gport)) { 15701 return BCM_E_PARAM; 15702 } 15703 15704 BCM_IF_ERROR_RETURN 15705 (_bcm_kt2_cosq_node_get(unit, sched_gport, NULL, &sched_port, NULL, 15706 &sched_node)); 15707 15708 if (sched_node->cosq_attached_to < 0) { 15709 /* Not attached yet */ 15710 return BCM_E_PORT; 15711 } 15712 15713 if (input_gport != BCM_GPORT_INVALID) { 15714 15715 if (BCM_GPORT_IS_SCHEDULER(input_gport) || 15716 BCM_GPORT_IS_LOCAL(input_gport) || 15717 BCM_GPORT_IS_MODPORT(input_gport)) { 15718 BCM_IF_ERROR_RETURN 15719 (_bcm_kt2_cosq_node_get(unit, input_gport, NULL, &input_port, 15720 NULL, &input_node)); 15721 } 15722 else { 15723 if (!(BCM_GPORT_IS_SCHEDULER(sched_gport) || 15724 BCM_GPORT_IS_UCAST_QUEUE_GROUP(sched_gport) || 15725 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(sched_gport) || 15726 BCM_GPORT_IS_MCAST_QUEUE_GROUP(sched_gport) || 15727 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(sched_gport) || 15728 BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(sched_gport) )) { 15729 return BCM_E_PARAM; 15730 } 15731 else { 15732 BCM_IF_ERROR_RETURN 15733 (_bcm_kt2_cosq_localport_resolve(unit, input_gport, 15734 &input_port)); 15735 input_node = NULL; 15736 } 15737 } 15738 } 15739 15740 /* When local port is passed as gport, BCM_E_PORT is thrown as this 15741 is not handled in attach scenario */ 15742 if (input_node == NULL) { 15743 return BCM_E_PORT; 15744 } 15745 15746 if (sched_node->parent != input_node) { 15747 return BCM_E_PORT; 15748 } 15749 15750 if (cosq < -1 || (input_node->numq != -1 && cosq >= input_node->numq)) { 15751 return BCM_E_PARAM; 15752 } 15753 15754 if (cosq != -1) { 15755 if (sched_node->cosq_attached_to != cosq) { 15756 return BCM_E_PARAM; 15757 } 15758 } 15759 15760 /* Update the hw accordingly 15761 * Protect LLS hierachy change as 15762 * port flush on link flap might be effected 15763 * when there is a change in the LLS hierarchy 15764 */ 15765 SOC_LLS_SCHEDULER_LOCK(unit); 15766 soc_kt_port_flush_state_get(unit, input_port, &status); 15767 if (status) { 15768 LOG_ERROR(BSL_LS_BCM_COSQ, 15769 (BSL_META_U(unit, 15770 " Unit %d Port %d is in flush state, Cannot change LLS hierarchy." 15771 "\n Detach of Cosq hw_cosq=%d failed.\n"), 15772 unit, input_port, sched_node->cosq_attached_to)); 15773 SOC_LLS_SCHEDULER_UNLOCK(unit); 15774 return BCM_E_RESOURCE; 15775 } 15776 15777 rv = _bcm_kt2_cosq_sched_node_set(unit, sched_gport, 15778 _BCM_KT2_COSQ_STATE_DISABLE); 15779 SOC_LLS_SCHEDULER_UNLOCK(unit); 15780 if (BCM_FAILURE(rv)) { 15781 return rv; 15782 } 15783 /* unresolve the node - delete this node from parent's child list */ 15784 BCM_IF_ERROR_RETURN 15785 (_bcm_kt2_cosq_node_unresolve(unit, sched_node, cosq)); 15786 15787 /* now remove from the sw tree */ 15788 if (sched_node->parent != NULL) { 15789 if (sched_node->parent->child == sched_node) { 15790 sched_node->parent->child = sched_node->sibling; 15791 } else { 15792 prev_node = sched_node->parent->child; 15793 while (prev_node != NULL && prev_node->sibling != sched_node) { 15794 prev_node = prev_node->sibling; 15795 } 15796 if (prev_node == NULL) { 15797 return BCM_E_INTERNAL; 15798 } 15799 prev_node->sibling = sched_node->sibling; 15800 } 15801 sched_node->parent = NULL; 15802 sched_node->sibling = NULL; 15803 sched_node->wrr_in_use = 0; 15804 sched_node->cosq_attached_to = -1; 15805 if (!(BCM_GPORT_IS_UCAST_QUEUE_GROUP(input_gport) || 15806 BCM_GPORT_IS_MCAST_QUEUE_GROUP(input_gport) || 15807 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(input_gport) || 15808 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(input_gport) || 15809 BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(input_gport))) { 15810 if (sched_node->type != 15811 _BCM_KT2_NODE_SUBSCRIBER_GPORT_ID) { 15812 sched_node->hw_index = -1; 15813 } 15814 } 15815 } 15816 15817 LOG_INFO(BSL_LS_BCM_COSQ, 15818 (BSL_META_U(unit, 15819 " hw_cosq=%d\n"), 15820 sched_node->cosq_attached_to)); 15821 15822 return BCM_E_NONE; 15823 } 15824 15825 /* 15826 * Function: 15827 * bcm_kt2_cosq_gport_attach_get 15828 * Purpose: 15829 * Get attached status of a scheduler port 15830 * Parameters: 15831 * unit - (IN) unit number 15832 * sched_port - (IN) scheduler GPORT identifier 15833 * input_port - (OUT) GPORT to attach to 15834 * cosq - (OUT) COS queue to attached to 15835 * Returns: 15836 * BCM_E_XXX 15837 * Notes: 15838 */ 15839 int 15840 bcm_kt2_cosq_gport_attach_get(int unit, bcm_gport_t sched_gport, 15841 bcm_gport_t *input_gport, bcm_cos_queue_t *cosq) 15842 { 15843 _bcm_kt2_cosq_node_t *sched_node; 15844 bcm_module_t modid, modid_out; 15845 bcm_port_t port, port_out; 15846 15847 if (input_gport == NULL || cosq == NULL) { 15848 return BCM_E_PARAM; 15849 } 15850 15851 BCM_IF_ERROR_RETURN 15852 (_bcm_kt2_cosq_node_get(unit, sched_gport, &modid, &port, NULL, 15853 &sched_node)); 15854 15855 if (sched_node->level == _BCM_KT2_COSQ_NODE_LEVEL_ROOT) { 15856 return BCM_E_PARAM; 15857 } 15858 15859 if (sched_node->cosq_attached_to < 0) { 15860 /* Not attached yet */ 15861 return BCM_E_NOT_FOUND; 15862 } 15863 15864 if (sched_node->parent != NULL) { 15865 *input_gport = sched_node->parent->gport; 15866 } else { /* sched_node is in L2 level */ 15867 BCM_IF_ERROR_RETURN 15868 (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, modid, port, 15869 &modid_out, &port_out)); 15870 BCM_GPORT_MODPORT_SET(*input_gport, modid_out, port_out); 15871 } 15872 *cosq = sched_node->cosq_attached_to; 15873 15874 return BCM_E_NONE; 15875 } 15876 15877 STATIC int 15878 _bcm_kt2_cosq_ef_update_war(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 15879 int hw_index, lls_l2_parent_entry_t *entry) 15880 { 15881 lls_l1_config_entry_t l1_config; 15882 uint32 min_bw, max_bw, min_burst, max_burst, flags = 0; 15883 int parent_index, spri_vector; 15884 uint32 start_pri, vec_3_0 =0, vec_7_4 = 0; 15885 uint32 rval = 0, bit_offset; 15886 15887 LOG_INFO(BSL_LS_BCM_COSQ, 15888 (BSL_META_U(unit, 15889 "_bcm_kt2_cosq_ef_update_war:unit=%d gport=0x%x cosq=%d idx=%d\n"), 15890 unit, gport, cosq, hw_index)); 15891 15892 BCM_IF_ERROR_RETURN 15893 (_bcm_kt2_cosq_bucket_get(unit, gport, cosq, &min_bw, &max_bw, 15894 &min_burst, &max_burst, flags)); 15895 15896 if ((min_bw == 0) && (max_bw == 0)) { 15897 SOC_IF_ERROR_RETURN 15898 (soc_mem_write(unit, LLS_L2_PARENTm, MEM_BLOCK_ALL, 15899 hw_index, entry)); 15900 } else { 15901 parent_index = soc_mem_field32_get(unit, LLS_L2_PARENTm, entry, 15902 C_PARENTf); 15903 SOC_IF_ERROR_RETURN 15904 (soc_mem_read(unit, LLS_L1_CONFIGm, MEM_BLOCK_ALL, parent_index, 15905 &l1_config)); 15906 start_pri = soc_mem_field32_get(unit, LLS_L1_CONFIGm, &l1_config, 15907 P_START_UC_SPRIf); 15908 vec_3_0 = soc_mem_field32_get(unit, LLS_L1_CONFIGm, &l1_config, 15909 P_NUM_SPRIf); 15910 vec_7_4 = soc_mem_field32_get(unit, LLS_L1_CONFIGm, &l1_config, 15911 P_VECT_SPRI_7_4f); 15912 spri_vector = vec_3_0 | (vec_7_4 << 4); 15913 bit_offset = hw_index - start_pri; 15914 if (bit_offset >= 8) { 15915 return BCM_E_PARAM; 15916 } 15917 LOG_INFO(BSL_LS_BCM_COSQ, 15918 (BSL_META_U(unit, 15919 "parent=%d spri_vector=0x%x bit_offset=%d\n"), 15920 parent_index, spri_vector, bit_offset)); 15921 spri_vector &= ~(1 << bit_offset); 15922 soc_mem_field32_set(unit, LLS_L1_CONFIGm, &l1_config, P_NUM_SPRIf, 15923 (spri_vector & 0xF)); 15924 soc_mem_field32_set(unit, LLS_L1_CONFIGm, &l1_config, P_VECT_SPRI_7_4f, 15925 ((spri_vector >> 4) & 0xF)); 15926 BCM_IF_ERROR_RETURN 15927 (_bcm_kt2_cosq_bucket_set(unit, gport, cosq, 0, 0, 15928 min_burst, max_burst, flags)); 15929 SOC_IF_ERROR_RETURN 15930 (soc_mem_write(unit, LLS_L2_PARENTm, MEM_BLOCK_ALL, 15931 hw_index, entry)); 15932 SOC_IF_ERROR_RETURN 15933 (soc_mem_write(unit, LLS_L1_CONFIGm, MEM_BLOCK_ALL, 15934 parent_index, &l1_config)); 15935 15936 soc_reg_field_set(unit, LLS_DEBUG_INJECT_ACTIVATIONr, &rval, 15937 INJECTf, 1); 15938 /* 0 = enqueue event,1 = shaper event,2 = xon event,3 = xoff event */ 15939 soc_reg_field_set(unit, LLS_DEBUG_INJECT_ACTIVATIONr, &rval, 15940 ENTITY_TYPEf, 1); 15941 /* 0 = port, 1 = level 0, 2 = level 1, 3 = level 2 */ 15942 soc_reg_field_set(unit, LLS_DEBUG_INJECT_ACTIVATIONr, &rval, 15943 ENTITY_LEVELf, 3); 15944 soc_reg_field_set(unit, LLS_DEBUG_INJECT_ACTIVATIONr, &rval, 15945 ENTITY_IDENTIFIERf, hw_index); 15946 SOC_IF_ERROR_RETURN(WRITE_LLS_DEBUG_INJECT_ACTIVATIONr(unit, rval)); 15947 spri_vector |= (1 << bit_offset); 15948 soc_mem_field32_set(unit, LLS_L1_CONFIGm, &l1_config, P_NUM_SPRIf, 15949 (spri_vector & 0xF)); 15950 soc_mem_field32_set(unit, LLS_L1_CONFIGm, &l1_config, P_VECT_SPRI_7_4f, 15951 ((spri_vector >> 4) & 0xF)); 15952 SOC_IF_ERROR_RETURN 15953 (soc_mem_write(unit, LLS_L1_CONFIGm, MEM_BLOCK_ALL, 15954 parent_index, &l1_config)); 15955 BCM_IF_ERROR_RETURN 15956 (_bcm_kt2_cosq_bucket_set(unit, gport, cosq, min_bw, max_bw, 15957 min_burst, max_burst, flags)); 15958 } 15959 15960 return BCM_E_NONE; 15961 } 15962 15963 STATIC int 15964 _bcm_kt2_cosq_valid_ef_node(int unit, lls_l1_config_entry_t *entry, 15965 int hw_index) 15966 { 15967 lls_l2_parent_entry_t l2_parent; 15968 int index, start_pri, spri_vector, num_spri, vec_7_4; 15969 uint32 bit_offset; 15970 int i; 15971 15972 start_pri = soc_mem_field32_get(unit, LLS_L1_CONFIGm, entry, 15973 P_START_UC_SPRIf); 15974 num_spri = soc_mem_field32_get(unit, LLS_L1_CONFIGm, entry, 15975 P_NUM_SPRIf); 15976 if (soc_feature(unit, soc_feature_vector_based_spri)) { 15977 vec_7_4 = soc_mem_field32_get(unit, LLS_L1_CONFIGm, entry, 15978 P_VECT_SPRI_7_4f); 15979 spri_vector = num_spri | (vec_7_4 << 4); 15980 bit_offset = hw_index - start_pri; 15981 if (bit_offset >= 8) { 15982 return BCM_E_PARAM; 15983 } 15984 if (!(spri_vector & (1 << bit_offset))) { 15985 /* werr node cannot be EF */ 15986 return BCM_E_PARAM; 15987 } 15988 for (i = 0; i < 8; i++) { 15989 if (spri_vector & (1 << i)) { 15990 index = start_pri + i; 15991 SOC_IF_ERROR_RETURN 15992 (soc_mem_read(unit, LLS_L2_PARENTm, MEM_BLOCK_ALL, 15993 index, &l2_parent)); 15994 if (soc_mem_field32_get(unit, LLS_L2_PARENTm, 15995 &l2_parent, C_EFf) == 1) { 15996 /* maximum of 1 EF node is supported */ 15997 return FALSE; 15998 } 15999 } 16000 } 16001 } else { 16002 if ((hw_index < start_pri) || (hw_index >= (start_pri + num_spri))) { 16003 /* werr node cannot be EF */ 16004 return BCM_E_PARAM; 16005 } 16006 for (i = start_pri; i < (start_pri + num_spri); i++) { 16007 SOC_IF_ERROR_RETURN 16008 (soc_mem_read(unit, LLS_L2_PARENTm, MEM_BLOCK_ALL, 16009 i, &l2_parent)); 16010 if (soc_mem_field32_get(unit, LLS_L2_PARENTm, 16011 &l2_parent, C_EFf) == 1) { 16012 /* maximum of 1 EF node is supported */ 16013 return FALSE; 16014 } 16015 } 16016 } 16017 16018 return TRUE; 16019 } 16020 16021 STATIC int 16022 _bcm_kt2_cosq_ef_op_at_index(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 16023 int hw_index, _bcm_cosq_op_t op, int *ef_val) 16024 { 16025 lls_l2_parent_entry_t entry; 16026 lls_l1_parent_entry_t l1_entry; 16027 lls_l1_config_entry_t l1_config; 16028 lls_l0_config_entry_t l0_config; 16029 uint32 current_ef = 0, set_ef = 0; 16030 uint32 index; 16031 16032 SOC_IF_ERROR_RETURN 16033 (soc_mem_read(unit, LLS_L2_PARENTm, MEM_BLOCK_ALL, hw_index, &entry)); 16034 16035 if (op == _BCM_COSQ_OP_GET) { 16036 *ef_val = soc_mem_field32_get(unit, LLS_L2_PARENTm, &entry, C_EFf); 16037 } else { 16038 current_ef = soc_mem_field32_get(unit, LLS_L2_PARENTm, &entry, C_EFf); 16039 set_ef = (*ef_val != 0) ? 1 : 0; 16040 soc_mem_field32_set(unit, LLS_L2_PARENTm, &entry, C_EFf, set_ef); 16041 if ((current_ef == 0) && (set_ef == 1)) { 16042 index = soc_mem_field32_get(unit, LLS_L2_PARENTm, &entry, 16043 C_PARENTf); 16044 SOC_IF_ERROR_RETURN 16045 (soc_mem_read(unit, LLS_L1_CONFIGm, MEM_BLOCK_ALL, 16046 index, &l1_config)); 16047 if (_bcm_kt2_cosq_valid_ef_node(unit, &l1_config, 16048 hw_index) != TRUE) { 16049 return BCM_E_PARAM; 16050 } 16051 soc_mem_field32_set(unit, LLS_L1_CONFIGm, &l1_config, 16052 P_CFG_EF_PROPAGATEf, set_ef); 16053 SOC_IF_ERROR_RETURN 16054 (soc_mem_write(unit, LLS_L1_CONFIGm, MEM_BLOCK_ALL, 16055 index, &l1_config)); 16056 SOC_IF_ERROR_RETURN 16057 (soc_mem_read(unit, LLS_L1_PARENTm, MEM_BLOCK_ALL, 16058 index, &l1_entry)); 16059 index = soc_mem_field32_get(unit, LLS_L1_PARENTm, &l1_entry, 16060 C_PARENTf); 16061 SOC_IF_ERROR_RETURN 16062 (soc_mem_read(unit, LLS_L0_CONFIGm, MEM_BLOCK_ALL, 16063 index, &l0_config)); 16064 soc_mem_field32_set(unit, LLS_L0_CONFIGm, &l0_config, 16065 P_CFG_EF_PROPAGATEf, set_ef); 16066 SOC_IF_ERROR_RETURN 16067 (soc_mem_write(unit, LLS_L0_CONFIGm, MEM_BLOCK_ALL, 16068 index, &l0_config)); 16069 SOC_IF_ERROR_RETURN 16070 (soc_mem_write(unit, LLS_L2_PARENTm, MEM_BLOCK_ALL, 16071 hw_index, &entry)); 16072 } else if ((current_ef == 1) && (set_ef == 0)) { 16073 if (soc_feature(unit, soc_feature_vector_based_spri)) { 16074 return _bcm_kt2_cosq_ef_update_war(unit, gport, cosq, 16075 hw_index, &entry); 16076 } 16077 SOC_IF_ERROR_RETURN 16078 (soc_mem_write(unit, LLS_L2_PARENTm, MEM_BLOCK_ALL, 16079 hw_index, &entry)); 16080 } else { 16081 return BCM_E_NONE; 16082 } 16083 } 16084 16085 return BCM_E_NONE; 16086 } 16087 16088 STATIC int 16089 _bcm_kt2_cosq_port_qnum_get(int unit, bcm_gport_t gport, 16090 bcm_cos_queue_t cosq, bcm_cosq_control_t type, int *arg) 16091 { 16092 bcm_port_t local_port; 16093 if (!arg) { 16094 return BCM_E_PARAM; 16095 } 16096 16097 if (!BCM_COSQ_QUEUE_VALID(unit, cosq)) { 16098 return BCM_E_PARAM; 16099 } 16100 16101 BCM_IF_ERROR_RETURN 16102 (_bcm_kt2_cosq_localport_resolve(unit, gport, &local_port)); 16103 if (local_port < 0) { 16104 return BCM_E_PORT; 16105 } 16106 16107 if (type == bcmCosqControlPortQueueUcast) { 16108 *arg = SOC_INFO(unit).port_uc_cosq_base[local_port] + cosq; 16109 } else { 16110 *arg = SOC_INFO(unit).port_cosq_base[local_port] + cosq; 16111 } 16112 16113 return BCM_E_NONE; 16114 } 16115 16116 STATIC int 16117 _bcm_kt2_cosq_ef_op(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, int *arg, 16118 _bcm_cosq_op_t op) 16119 { 16120 bcm_port_t local_port; 16121 int index, numq, from_cos, to_cos, ci; 16122 16123 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 16124 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) || 16125 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport) || 16126 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport) || 16127 BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(gport)) { 16128 BCM_IF_ERROR_RETURN 16129 (_bcm_kt2_cosq_index_resolve 16130 (unit, gport, cosq, _BCM_KT2_COSQ_INDEX_STYLE_BUCKET, 16131 &local_port, &index, NULL)); 16132 return _bcm_kt2_cosq_ef_op_at_index(unit, gport, cosq, 16133 index, op, arg); 16134 } else if (BCM_GPORT_IS_SCHEDULER(gport)) { 16135 return BCM_E_PARAM; 16136 } else { 16137 BCM_IF_ERROR_RETURN 16138 (_bcm_kt2_cosq_index_resolve 16139 (unit, gport, cosq, _BCM_KT2_COSQ_INDEX_STYLE_BUCKET, 16140 &local_port, &index, &numq)); 16141 if (cosq == BCM_COS_INVALID) { 16142 /* Maximum 1 spri can be EF enabled */ 16143 from_cos = to_cos = 0; 16144 } else { 16145 from_cos = to_cos = cosq; 16146 } 16147 for (ci = from_cos; ci <= to_cos; ci++) { 16148 BCM_IF_ERROR_RETURN 16149 (_bcm_kt2_cosq_index_resolve 16150 (unit, gport, ci, _BCM_KT2_COSQ_INDEX_STYLE_BUCKET, 16151 &local_port, &index, NULL)); 16152 16153 BCM_IF_ERROR_RETURN(_bcm_kt2_cosq_ef_op_at_index(unit, 16154 gport, ci, index, op, arg)); 16155 if (op == _BCM_COSQ_OP_GET) { 16156 return BCM_E_NONE; 16157 } 16158 } 16159 } 16160 return BCM_E_NONE; 16161 } 16162 16163 int 16164 _bcm_kt2_cosq_redirect_parameter_set (int unit, soc_reg_t reg, 16165 soc_field_t field, bcm_cos_queue_t cosq, int arg) 16166 { 16167 uint32 rval; 16168 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, cosq, 16169 &rval)); 16170 soc_reg_field_set(unit, reg, &rval, field, arg); 16171 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, cosq, 16172 rval)); 16173 return BCM_E_NONE; 16174 } 16175 16176 #if defined(BCM_SABER2_SUPPORT) 16177 STATIC int 16178 _bcm_sb2_cosq_port_pg_idx_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 16179 int *midx) 16180 { 16181 bcm_port_t local_port; 16182 soc_reg_t reg = INVALIDr; 16183 int port_pg, pg_profile = 0; 16184 uint64 rval64; 16185 uint32 rval; 16186 16187 soc_reg_t pri_to_prigrp_reg = MMU_ENQ_IP_PRI_TO_PG_PROFILE_0r; 16188 soc_field_t pri_to_prigrp_field[SB2_MAX_LOGICAL_PORTS]={ 16189 SRCPORT_0f, 16190 SRCPORT_1f, SRCPORT_2f, SRCPORT_3f, SRCPORT_4f, 16191 SRCPORT_5f, SRCPORT_6f, SRCPORT_7f, SRCPORT_8f, 16192 SRCPORT_9f, SRCPORT_10f, SRCPORT_11f, SRCPORT_12f, 16193 SRCPORT_13f, SRCPORT_14f, SRCPORT_15f, SRCPORT_16f, 16194 SRCPORT_17f, SRCPORT_18f, SRCPORT_19f, SRCPORT_20f, 16195 SRCPORT_21f, SRCPORT_22f, SRCPORT_23f, SRCPORT_24f, 16196 SRCPORT_25f, SRCPORT_26f, SRCPORT_27f, SRCPORT_28f, 16197 SRCPORT_29f 16198 }; 16199 16200 static const soc_reg_t prigroup_reg[] = { 16201 PROFILE0_PRI_GRP0r, PROFILE0_PRI_GRP1r, 16202 PROFILE1_PRI_GRP0r, PROFILE1_PRI_GRP1r, 16203 PROFILE2_PRI_GRP0r, PROFILE2_PRI_GRP1r, 16204 PROFILE3_PRI_GRP0r, PROFILE3_PRI_GRP1r 16205 }; 16206 static const soc_field_t prigroup_field0[] = { 16207 PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf, 16208 PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf 16209 }; 16210 16211 static const soc_field_t prigroup_field1[] = { 16212 PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf, 16213 PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf 16214 }; 16215 16216 if (midx == NULL) { 16217 return BCM_E_PARAM; 16218 } 16219 16220 if (cosq > 15 || cosq < 0) { 16221 /* Error. Input pri > Max Pri_Grp */ 16222 return BCM_E_PARAM; 16223 } 16224 16225 BCM_IF_ERROR_RETURN 16226 (_bcm_kt2_cosq_node_get(unit, gport, NULL, &local_port, NULL, 16227 NULL)); 16228 16229 if (local_port < 0) { 16230 return BCM_E_PORT; 16231 } 16232 16233 /* The valid fields below are those which correspond to valid 16234 * PFC ports 16235 */ 16236 READ_MMU_ENQ_IP_PRI_TO_PG_PROFILE_0r(unit, &rval64); 16237 if (soc_reg_field_valid(unit, MMU_ENQ_IP_PRI_TO_PG_PROFILE_0r, 16238 pri_to_prigrp_field[local_port])) { 16239 pg_profile = soc_reg64_field32_get(unit, pri_to_prigrp_reg, rval64, 16240 pri_to_prigrp_field[local_port]); 16241 16242 if (cosq < 8) { 16243 reg = prigroup_reg[pg_profile * 2]; 16244 SOC_IF_ERROR_RETURN 16245 (soc_reg32_get(unit, reg, local_port, 0, &rval)); 16246 port_pg = soc_reg_field_get(unit, reg, rval, prigroup_field0[cosq]); 16247 } else { 16248 reg = prigroup_reg[(pg_profile * 2) + 1]; 16249 SOC_IF_ERROR_RETURN 16250 (soc_reg32_get(unit, reg, local_port, 0, &rval)); 16251 port_pg = soc_reg_field_get(unit, reg, rval, prigroup_field1[cosq - 8]); 16252 } 16253 } else { 16254 port_pg = 0; 16255 } 16256 #if defined(BCM_METROLITE_SUPPORT) 16257 if (SOC_IS_METROLITE(unit)) { 16258 *midx = ML_GET_THDI_PORT_PG(local_port) - 7 + port_pg; 16259 } else 16260 #endif 16261 { 16262 *midx = (local_port * SB2_MAX_PRIORITY_GROUPS) + port_pg; 16263 } 16264 16265 if (*midx < 0) { 16266 return BCM_E_PARAM; 16267 } 16268 16269 return BCM_E_NONE; 16270 } 16271 #endif 16272 16273 STATIC int 16274 _bcm_kt2_cosq_port_pg_idx_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 16275 int *midx) 16276 { 16277 bcm_port_t local_port; 16278 soc_reg_t reg = INVALIDr; 16279 int port_pg, pg_profile = 0; 16280 uint32 rval; 16281 16282 soc_reg_t pri_to_prigrp_reg = MMU_ENQ_IP_PRI_TO_PG_PROFILE_0r; 16283 soc_field_t pri_to_prigrp_field[KT2_MAX_LOGICAL_PORTS]={ 16284 SRCPORT_0f, 16285 SRCPORT_1f, SRCPORT_2f, SRCPORT_3f, SRCPORT_4f, 16286 SRCPORT_5f, SRCPORT_6f, SRCPORT_7f, SRCPORT_8f, 16287 SRCPORT_9f, SRCPORT_10f, SRCPORT_11f, SRCPORT_12f, 16288 SRCPORT_13f, SRCPORT_14f, SRCPORT_15f, SRCPORT_16f, 16289 SRCPORT_17f, SRCPORT_18f, SRCPORT_19f, SRCPORT_20f, 16290 SRCPORT_21f, SRCPORT_22f, SRCPORT_23f, SRCPORT_24f, 16291 SRCPORT_25f, SRCPORT_26f, SRCPORT_27f, SRCPORT_28f, 16292 SRCPORT_29f, SRCPORT_30f, SRCPORT_31f, SRCPORT_32f, 16293 SRCPORT_33f, SRCPORT_34f, SRCPORT_35f, SRCPORT_36f, 16294 SRCPORT_37f, SRCPORT_38f, SRCPORT_39f, SRCPORT_40f, 16295 SRCPORT_41f 16296 }; 16297 16298 static const soc_reg_t prigroup_reg[] = { 16299 MMU_ENQ_PROFILE_0_PRI_GRP0r, MMU_ENQ_PROFILE_0_PRI_GRP1r, 16300 MMU_ENQ_PROFILE_1_PRI_GRP0r, MMU_ENQ_PROFILE_1_PRI_GRP1r, 16301 MMU_ENQ_PROFILE_2_PRI_GRP0r, MMU_ENQ_PROFILE_2_PRI_GRP1r, 16302 MMU_ENQ_PROFILE_3_PRI_GRP0r, MMU_ENQ_PROFILE_3_PRI_GRP1r 16303 }; 16304 16305 static const soc_field_t prigroup_field0[] = { 16306 PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf, 16307 PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf 16308 }; 16309 16310 static const soc_field_t prigroup_field1[] = { 16311 PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf, 16312 PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf 16313 }; 16314 16315 if (midx == NULL) { 16316 return BCM_E_PARAM; 16317 } 16318 16319 if (cosq > 15 || cosq < 0) { 16320 /* Error. Input pri > Max Pri_Grp */ 16321 return BCM_E_PARAM; 16322 } 16323 16324 BCM_IF_ERROR_RETURN 16325 (_bcm_kt2_cosq_node_get(unit, gport, NULL, &local_port, NULL, 16326 NULL)); 16327 16328 if (local_port < 0) { 16329 return BCM_E_PORT; 16330 } 16331 16332 /* The valid fields below are those which correspond to valid 16333 * PFC ports 16334 */ 16335 READ_MMU_ENQ_IP_PRI_TO_PG_PROFILE_0r_REG32(unit, &rval); 16336 if (soc_reg_field_valid(unit, MMU_ENQ_IP_PRI_TO_PG_PROFILE_0r, 16337 pri_to_prigrp_field[local_port])) { 16338 pg_profile = soc_reg_field_get(unit, pri_to_prigrp_reg, rval, 16339 pri_to_prigrp_field[local_port]); 16340 16341 if (cosq < 8) { 16342 reg = prigroup_reg[pg_profile * 2]; 16343 SOC_IF_ERROR_RETURN 16344 (soc_reg32_get(unit, reg, local_port, 0, &rval)); 16345 port_pg = soc_reg_field_get(unit, reg, rval, prigroup_field0[cosq]); 16346 } else { 16347 reg = prigroup_reg[(pg_profile * 2) + 1]; 16348 SOC_IF_ERROR_RETURN 16349 (soc_reg32_get(unit, reg, local_port, 0, &rval)); 16350 port_pg = soc_reg_field_get(unit, reg, rval, prigroup_field1[cosq - 8]); 16351 } 16352 } else { 16353 port_pg = 0; 16354 } 16355 16356 *midx = (local_port * _BCM_KT2_MAX_PRIORITY_GROUPS) + port_pg; 16357 16358 if (*midx < 0) { 16359 return BCM_E_PARAM; 16360 } 16361 16362 return BCM_E_NONE; 16363 } 16364 16365 16366 STATIC int 16367 _bcm_kt2_cosq_egr_pool_set(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 16368 bcm_cosq_control_t type, int arg) 16369 { 16370 int startq; 16371 uint32 max_val; 16372 uint32 entry[SOC_MAX_MEM_WORDS]; 16373 soc_mem_t mem = INVALIDm; 16374 soc_mem_t mem2 = INVALIDm; 16375 soc_field_t fld_limit = INVALIDf, fld_limit2 = INVALIDf; 16376 int granularity = 1; 16377 bcm_port_t local_port; 16378 int cell_size = _BCM_KT2_COSQ_CELLSIZE; 16379 _bcm_kt2_mmu_info_t *mmu_info; 16380 _bcm_kt2_cosq_node_t *node; 16381 int numq; 16382 16383 if (arg < 0) { 16384 return BCM_E_PARAM; 16385 } 16386 16387 BCM_IF_ERROR_RETURN 16388 (_bcm_kt2_cosq_node_get(unit, gport, NULL, &local_port, NULL, 16389 &node)); 16390 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 16391 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) || 16392 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport) || 16393 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport) || 16394 BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(gport) || 16395 BCM_GPORT_IS_SCHEDULER(gport)) { 16396 if ((node->level != _BCM_KT2_COSQ_NODE_LEVEL_L1) && 16397 (node->level != _BCM_KT2_COSQ_NODE_LEVEL_L2)) { 16398 return BCM_E_PARAM; 16399 } 16400 if (BCM_GPORT_IS_SCHEDULER(gport)) { 16401 BCM_IF_ERROR_RETURN( 16402 _bcm_kt2_cosq_child_node_at_input(node, cosq, 16403 &node)); 16404 } 16405 startq = node->hw_index; 16406 } else { 16407 mmu_info = _bcm_kt2_mmu_info[unit]; 16408 numq = mmu_info->port[local_port].q_limit - 16409 mmu_info->port[local_port].q_offset; 16410 16411 if (cosq < 0 || cosq >= numq) { 16412 return BCM_E_PARAM; 16413 } 16414 startq = mmu_info->port[local_port].q_offset + cosq; 16415 } 16416 16417 if (IS_EXT_MEM_PORT(unit, local_port)) { 16418 cell_size = _BCM_KT2_COSQ_EXT_CELLSIZE; 16419 if (soc_feature(unit, soc_feature_mmu_packing)) { 16420 cell_size = _BCM_KT2_COSQ_EXT_PACKING_CELLSIZE; 16421 } 16422 } 16423 16424 if (type != bcmCosqControlEgressPoolLimitEnable) { 16425 arg = arg / cell_size; 16426 } 16427 16428 mem = MMU_THDO_QCONFIG_CELLm; 16429 if (type == bcmCosqControlEgressPoolRedLimitBytes) { 16430 mem = MMU_THDO_QOFFSET_CELLm; 16431 mem2 = MMU_THDO_QCONFIG_CELLm; 16432 } 16433 16434 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 16435 16436 switch (type) { 16437 case bcmCosqControlEgressPoolLimitBytes: 16438 fld_limit = Q_SHARED_LIMIT_CELLf; 16439 fld_limit2 = Q_LIMIT_ENABLE_CELLf; 16440 granularity = 1; 16441 break; 16442 case bcmCosqControlEgressPoolYellowLimitBytes: 16443 fld_limit = LIMIT_YELLOW_CELLf; 16444 fld_limit2 = Q_COLOR_ENABLE_CELLf; 16445 granularity = 8; 16446 break; 16447 case bcmCosqControlEgressPoolRedLimitBytes: 16448 fld_limit = LIMIT_RED_CELLf; 16449 fld_limit2 = Q_COLOR_ENABLE_CELLf; 16450 granularity = 8; 16451 break; 16452 case bcmCosqControlEgressPoolLimitEnable: 16453 fld_limit = Q_LIMIT_ENABLE_CELLf; 16454 granularity = 1; 16455 break; 16456 default: 16457 return BCM_E_UNAVAIL; 16458 } 16459 16460 /* Check for min/max values */ 16461 max_val = (1 << soc_mem_field_length(unit, mem, fld_limit)) - 1; 16462 if (IS_EXT_MEM_PORT(unit, local_port)) { 16463 max_val = soc_kt2_get_max_buffer_size(unit, 1, max_val); 16464 } else { 16465 max_val = soc_kt2_get_max_buffer_size(unit, 0, max_val); 16466 } 16467 if ((arg < 0) || ((arg/granularity) > max_val)) { 16468 return BCM_E_PARAM; 16469 } else { 16470 soc_mem_field32_set(unit, mem, entry, fld_limit, (arg/granularity)); 16471 if (fld_limit2 != INVALIDr) { 16472 if (mem2 != INVALIDm) { 16473 soc_mem_field32_set(unit, mem2, entry, fld_limit2, 1); 16474 } else { 16475 soc_mem_field32_set(unit, mem, entry, fld_limit2, 1); 16476 } 16477 } 16478 } 16479 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 16480 16481 return BCM_E_NONE; 16482 } 16483 16484 STATIC int 16485 _bcm_kt2_cosq_egr_queue_set(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 16486 bcm_cosq_control_t type, int arg) 16487 { 16488 bcm_port_t local_port; 16489 int startq, startq1; 16490 uint32 max_val; 16491 uint32 entry[SOC_MAX_MEM_WORDS]; 16492 soc_mem_t mem = INVALIDm; 16493 soc_field_t fld_limit = INVALIDf, fld_limit2 = INVALIDf; 16494 int granularity = 1; 16495 int shared_size, cur_val, rv, post_update; 16496 _bcm_kt2_mmu_info_t *mmu_info = _bcm_kt2_mmu_info[unit]; 16497 int cell_size = _BCM_KT2_COSQ_CELLSIZE; 16498 _bcm_kt2_cosq_node_t *node; 16499 int limit, numq; 16500 bcm_kt2_cosq_recalc_type_t recalc_type; 16501 16502 if (arg < 0) { 16503 return BCM_E_PARAM; 16504 } 16505 16506 BCM_IF_ERROR_RETURN 16507 (_bcm_kt2_cosq_node_get(unit, gport, NULL, &local_port, NULL, 16508 &node)); 16509 16510 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 16511 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) || 16512 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport) || 16513 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport) || 16514 BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(gport) || 16515 BCM_GPORT_IS_SCHEDULER(gport)) { 16516 if ((node->level != _BCM_KT2_COSQ_NODE_LEVEL_L1) && 16517 (node->level != _BCM_KT2_COSQ_NODE_LEVEL_L2)) { 16518 return BCM_E_PARAM; 16519 } 16520 if (BCM_GPORT_IS_SCHEDULER(gport)) { 16521 BCM_IF_ERROR_RETURN( 16522 _bcm_kt2_cosq_child_node_at_input(node, cosq, 16523 &node)); 16524 } 16525 16526 startq = node->hw_index; 16527 startq1 = node->hw_index; 16528 } else { 16529 mmu_info = _bcm_kt2_mmu_info[unit]; 16530 numq = mmu_info->port[local_port].q_limit - 16531 mmu_info->port[local_port].q_offset; 16532 16533 if (cosq < 0 || cosq >= numq) { 16534 return BCM_E_PARAM; 16535 } 16536 startq = mmu_info->port[local_port].q_offset + cosq; 16537 startq1 = mmu_info->port[local_port].mcq_offset + cosq; 16538 } 16539 16540 if (IS_EXT_MEM_PORT(unit, local_port)) { 16541 cell_size = _BCM_KT2_COSQ_EXT_CELLSIZE; 16542 if (soc_feature(unit, soc_feature_mmu_packing)) { 16543 cell_size = _BCM_KT2_COSQ_EXT_PACKING_CELLSIZE; 16544 } 16545 } 16546 16547 arg /= cell_size; 16548 16549 mem = MMU_THDO_QCONFIG_CELLm; 16550 16551 if ((type == bcmCosqControlEgressUCQueueSharedLimitBytes) || 16552 (type == bcmCosqControlEgressUCQueueMinLimitBytes)) { 16553 if (node && (BCM_GPORT_IS_MCAST_QUEUE_GROUP(node->gport) || 16554 BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(node->gport))) { 16555 return BCM_E_PARAM; 16556 } 16557 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 16558 } else if ((type == bcmCosqControlEgressMCQueueSharedLimitBytes) || 16559 (type == bcmCosqControlEgressMCQueueMinLimitBytes)) { 16560 if (node && (BCM_GPORT_IS_UCAST_QUEUE_GROUP(node->gport) || 16561 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(node->gport))) { 16562 return BCM_E_PARAM; 16563 } 16564 startq = startq1; 16565 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 16566 } 16567 16568 switch (type) { 16569 case bcmCosqControlEgressUCQueueSharedLimitBytes: 16570 case bcmCosqControlEgressMCQueueSharedLimitBytes: 16571 fld_limit = Q_SHARED_LIMIT_CELLf; 16572 fld_limit2 = Q_LIMIT_ENABLE_CELLf; 16573 16574 /* Disable queuing when both MIN and SHARED LIMITS are zero. 16575 * Enable it when either MIN or SHARED LIMIT is non-zero. 16576 */ 16577 limit = soc_mem_field32_get(unit, mem, entry, Q_MIN_CELLf); 16578 if (arg == 0 && limit == 0) { 16579 soc_kt2_cosq_queue_enable(unit, startq, 0); 16580 } else { 16581 soc_kt2_cosq_queue_enable(unit, startq, 1); 16582 } 16583 granularity = 1; 16584 break; 16585 case bcmCosqControlEgressUCQueueMinLimitBytes: 16586 case bcmCosqControlEgressMCQueueMinLimitBytes: 16587 fld_limit = Q_MIN_CELLf; 16588 16589 /* Disable queuing when both MIN and SHARED LIMITS are zero. 16590 * Enable it when either MIN or SHARED LIMIT is non-zero. 16591 */ 16592 limit = soc_mem_field32_get(unit, mem, entry, Q_SHARED_LIMIT_CELLf); 16593 if (arg == 0 && limit == 0) { 16594 soc_kt2_cosq_queue_enable(unit, startq, 0); 16595 } else { 16596 soc_kt2_cosq_queue_enable(unit, startq, 1); 16597 } 16598 granularity = 1; 16599 break; 16600 default: 16601 return BCM_E_UNAVAIL; 16602 } 16603 16604 /* Recalculate Shared Values if Min Changed */ 16605 if (IS_EXT_MEM_PORT(unit, local_port)) { 16606 soc_kt2_mmu_get_shared_size(unit, NULL, &shared_size); 16607 } else { 16608 soc_kt2_mmu_get_shared_size(unit, &shared_size, NULL); 16609 } 16610 cur_val = soc_mem_field32_get(unit, mem, entry, fld_limit); 16611 16612 if ((arg / granularity) > cur_val) { 16613 /* New Min Val > Cur Min Val 16614 * So reduce the Shared values first and then 16615 * Increase the Min Value for given resource 16616 */ 16617 post_update = 0; 16618 } else if ((arg / granularity) < cur_val) { 16619 /* New Min Val < Cur Min Val 16620 * So reduce the Min values first and then 16621 * Increase Shared values everywhere 16622 */ 16623 post_update = 1; 16624 } else { 16625 return BCM_E_NONE; 16626 } 16627 16628 if (!post_update && 16629 ((type == bcmCosqControlEgressUCQueueMinLimitBytes) || 16630 (type == bcmCosqControlEgressMCQueueMinLimitBytes))) { 16631 int delta = 0; /* In Cells */ 16632 delta = ((arg / granularity) - cur_val) * granularity; 16633 if (delta > shared_size) { 16634 return BCM_E_RESOURCE; 16635 } 16636 if (IS_EXT_MEM_PORT(unit, local_port)) { 16637 recalc_type = BCM_KT2_RECALC_SHARED_EXT_DECREMENT; 16638 } else { 16639 recalc_type = BCM_KT2_RECALC_SHARED_INT_DECREMENT; 16640 } 16641 #if defined(BCM_SABER2_SUPPORT) 16642 if (SOC_IS_SABER2(unit)) { 16643 rv = soc_sb2_mmu_config_shared_buf_recalc(unit, 16644 shared_size - delta, 16645 recalc_type); 16646 } else 16647 #endif 16648 { 16649 rv = soc_kt2_mmu_config_shared_buf_recalc(unit, 16650 shared_size - delta, 16651 recalc_type); 16652 } 16653 if (rv < 0) { 16654 return rv; 16655 } 16656 } 16657 16658 /* Check for min/max values */ 16659 max_val = (1 << soc_mem_field_length(unit, mem, fld_limit)) - 1; 16660 if (IS_EXT_MEM_PORT(unit, local_port)) { 16661 max_val = soc_kt2_get_max_buffer_size(unit, 1, max_val); 16662 } else { 16663 max_val = soc_kt2_get_max_buffer_size(unit, 0, max_val); 16664 } 16665 if ((arg < 0) || ((arg/granularity) > max_val)) { 16666 return BCM_E_PARAM; 16667 } else { 16668 soc_mem_field32_set(unit, mem, entry, fld_limit, (arg/granularity)); 16669 if (fld_limit2 != INVALIDr) { 16670 soc_mem_field32_set(unit, mem, entry, fld_limit2, 1); 16671 } 16672 } 16673 16674 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 16675 16676 if (post_update && 16677 ((type == bcmCosqControlEgressUCQueueMinLimitBytes) || 16678 (type == bcmCosqControlEgressMCQueueMinLimitBytes))) { 16679 int delta = 0; 16680 delta = (cur_val - (arg / granularity)) * granularity; 16681 if (delta > shared_size) { 16682 return BCM_E_RESOURCE; 16683 } 16684 if (IS_EXT_MEM_PORT(unit, local_port)) { 16685 recalc_type = BCM_KT2_RECALC_SHARED_EXT_INCREMENT; 16686 } else { 16687 recalc_type = BCM_KT2_RECALC_SHARED_INT_INCREMENT; 16688 } 16689 #if defined(BCM_SABER2_SUPPORT) 16690 if (SOC_IS_SABER2(unit)) { 16691 rv = soc_sb2_mmu_config_shared_buf_recalc(unit, 16692 shared_size + delta, 16693 recalc_type); 16694 } else 16695 #endif 16696 { 16697 rv = soc_kt2_mmu_config_shared_buf_recalc(unit, 16698 shared_size + delta, 16699 recalc_type); 16700 } 16701 if (rv < 0) { 16702 return rv; 16703 } 16704 } 16705 16706 return BCM_E_NONE; 16707 } 16708 16709 STATIC int 16710 _bcm_kt2_cosq_ing_res_set(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 16711 bcm_cosq_control_t type, int arg) 16712 { 16713 bcm_port_t local_port; 16714 int midx, cell_size = _BCM_KT2_COSQ_CELLSIZE; 16715 uint32 max_val; 16716 uint32 entry[SOC_MAX_MEM_WORDS]; 16717 soc_mem_t mem = INVALIDm; 16718 soc_field_t fld_limit = INVALIDf; 16719 int granularity = 1; 16720 16721 if (arg < 0) { 16722 return BCM_E_PARAM; 16723 } 16724 16725 BCM_IF_ERROR_RETURN 16726 (_bcm_kt2_cosq_node_get(unit, gport, NULL, &local_port, NULL, 16727 NULL)); 16728 16729 if (local_port < 0) { 16730 return BCM_E_PORT; 16731 } 16732 16733 if (IS_EXT_MEM_PORT(unit, local_port)) { 16734 cell_size = _BCM_KT2_COSQ_EXT_CELLSIZE; 16735 if (soc_feature(unit, soc_feature_mmu_packing)) { 16736 cell_size = _BCM_KT2_COSQ_EXT_PACKING_CELLSIZE; 16737 } 16738 } 16739 16740 arg /= cell_size; 16741 16742 #if defined(BCM_SABER2_SUPPORT) 16743 if (SOC_IS_SABER2(unit)) { 16744 BCM_IF_ERROR_RETURN( 16745 _bcm_sb2_cosq_port_pg_idx_get(unit, gport, cosq, &midx)); 16746 } else 16747 #endif 16748 { 16749 BCM_IF_ERROR_RETURN( 16750 _bcm_kt2_cosq_port_pg_idx_get(unit, gport, cosq, &midx)); 16751 } 16752 16753 mem = THDI_PORT_PG_CONFIGm; 16754 16755 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, entry)); 16756 16757 switch (type) { 16758 case bcmCosqControlIngressPortPGSharedLimitBytes: 16759 fld_limit = PG_SHARED_LIMITf; 16760 granularity = 1; 16761 break; 16762 case bcmCosqControlIngressPortPGMinLimitBytes: 16763 fld_limit = PG_MIN_LIMITf; 16764 granularity = 1; 16765 break; 16766 case bcmCosqControlIngressPortPGHeadroomLimitBytes: 16767 fld_limit = PG_HDRM_LIMITf; 16768 granularity = 1; 16769 break; 16770 case bcmCosqControlIngressPortPGResetFloorBytes: 16771 fld_limit = PG_RESET_FLOORf; 16772 granularity = 1; 16773 break; 16774 default: 16775 return BCM_E_UNAVAIL; 16776 } 16777 16778 /* Check for min/max values */ 16779 max_val = (1 << soc_mem_field_length(unit, mem, fld_limit)) - 1; 16780 16781 if (IS_EXT_MEM_PORT(unit, local_port)) { 16782 max_val = soc_kt2_get_max_buffer_size(unit, 1, max_val); 16783 } else { 16784 max_val = soc_kt2_get_max_buffer_size(unit, 0, max_val); 16785 } 16786 16787 if ((arg < 0) || ((arg/granularity) > max_val)) { 16788 return BCM_E_PARAM; 16789 } else { 16790 soc_mem_field32_set(unit, mem, entry, fld_limit, (arg/granularity)); 16791 } 16792 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, midx, entry)); 16793 16794 return BCM_E_NONE; 16795 } 16796 16797 STATIC int 16798 _bcm_kt2_cosq_alpha_set(int unit, 16799 bcm_gport_t gport, bcm_cos_queue_t cosq, 16800 bcm_cosq_control_drop_limit_alpha_value_t arg) 16801 { 16802 int startq = -1; 16803 int midx; 16804 uint32 entry[SOC_MAX_MEM_WORDS]; 16805 soc_mem_t mem = INVALIDm; 16806 int alpha; 16807 int dynamic_thresh_mode; 16808 _bcm_kt2_cosq_node_t *node; 16809 16810 switch(arg) { 16811 case bcmCosqControlDropLimitAlpha_1_64: 16812 alpha = SOC_KT2_COSQ_DROP_LIMIT_ALPHA_1_64; 16813 break; 16814 case bcmCosqControlDropLimitAlpha_1_32: 16815 alpha = SOC_KT2_COSQ_DROP_LIMIT_ALPHA_1_32; 16816 break; 16817 case bcmCosqControlDropLimitAlpha_1_16: 16818 alpha = SOC_KT2_COSQ_DROP_LIMIT_ALPHA_1_16; 16819 break; 16820 case bcmCosqControlDropLimitAlpha_1_8: 16821 alpha = SOC_KT2_COSQ_DROP_LIMIT_ALPHA_1_8; 16822 break; 16823 case bcmCosqControlDropLimitAlpha_1_4: 16824 alpha = SOC_KT2_COSQ_DROP_LIMIT_ALPHA_1_4; 16825 break; 16826 case bcmCosqControlDropLimitAlpha_1_2: 16827 alpha = SOC_KT2_COSQ_DROP_LIMIT_ALPHA_1_2; 16828 break; 16829 case bcmCosqControlDropLimitAlpha_1: 16830 alpha = SOC_KT2_COSQ_DROP_LIMIT_ALPHA_1; 16831 break; 16832 case bcmCosqControlDropLimitAlpha_2: 16833 alpha = SOC_KT2_COSQ_DROP_LIMIT_ALPHA_2; 16834 break; 16835 case bcmCosqControlDropLimitAlpha_4: 16836 alpha = SOC_KT2_COSQ_DROP_LIMIT_ALPHA_4; 16837 break; 16838 case bcmCosqControlDropLimitAlpha_8: 16839 alpha = SOC_KT2_COSQ_DROP_LIMIT_ALPHA_8; 16840 break; 16841 default: 16842 return BCM_E_PARAM; 16843 } 16844 16845 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 16846 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) || 16847 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport) || 16848 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport) || 16849 BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(gport) || 16850 BCM_GPORT_IS_SCHEDULER(gport)) { 16851 BCM_IF_ERROR_RETURN 16852 (_bcm_kt2_cosq_node_get(unit, gport, NULL, NULL, NULL, 16853 &node)); 16854 if ((node->level != _BCM_KT2_COSQ_NODE_LEVEL_L1) && 16855 (node->level != _BCM_KT2_COSQ_NODE_LEVEL_L2)) { 16856 return BCM_E_PARAM; 16857 } 16858 if (BCM_GPORT_IS_SCHEDULER(gport)) { 16859 BCM_IF_ERROR_RETURN( 16860 _bcm_kt2_cosq_child_node_at_input(node, cosq, 16861 &node)); 16862 } 16863 startq = node->hw_index; 16864 } 16865 16866 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 16867 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) || 16868 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport) || 16869 BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(gport)) { 16870 16871 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 16872 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport)) { 16873 BCM_IF_ERROR_RETURN 16874 (_bcm_kt2_cosq_dynamic_thresh_enable_get(unit, gport, cosq, 16875 bcmCosqControlEgressUCSharedDynamicEnable, 16876 &dynamic_thresh_mode)); 16877 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) || 16878 BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(gport)) { 16879 BCM_IF_ERROR_RETURN 16880 (_bcm_kt2_cosq_dynamic_thresh_enable_get(unit, gport, cosq, 16881 bcmCosqControlEgressMCSharedDynamicEnable, 16882 &dynamic_thresh_mode)); 16883 } 16884 16885 if (!dynamic_thresh_mode){ 16886 return BCM_E_CONFIG; 16887 } 16888 16889 mem = MMU_THDO_QCONFIG_CELLm; 16890 16891 BCM_IF_ERROR_RETURN 16892 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 16893 soc_mem_field32_set(unit, mem, entry, 16894 Q_SHARED_ALPHA_CELLf, alpha); 16895 SOC_IF_ERROR_RETURN 16896 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 16897 } else { 16898 #if defined(BCM_SABER2_SUPPORT) 16899 if (SOC_IS_SABER2(unit)) { 16900 BCM_IF_ERROR_RETURN( 16901 _bcm_sb2_cosq_port_pg_idx_get(unit, gport, cosq, &midx)); 16902 } else 16903 #endif 16904 { 16905 BCM_IF_ERROR_RETURN( 16906 _bcm_kt2_cosq_port_pg_idx_get(unit, gport, cosq, &midx)); 16907 } 16908 16909 mem = THDI_PORT_PG_CONFIGm; 16910 16911 BCM_IF_ERROR_RETURN 16912 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, entry)); 16913 soc_mem_field32_set(unit, mem, entry, 16914 PG_SHARED_LIMITf, alpha); 16915 SOC_IF_ERROR_RETURN 16916 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, midx, entry)); 16917 } 16918 16919 return BCM_E_NONE; 16920 } 16921 16922 STATIC int 16923 _bcm_kt2_cosq_dynamic_thresh_enable_set(int unit, 16924 bcm_gport_t gport, bcm_cos_queue_t cosq, 16925 bcm_cosq_control_t type, int arg) 16926 { 16927 bcm_port_t local_port; 16928 int startq, startq1; 16929 int midx, numq; 16930 uint32 entry[SOC_MAX_MEM_WORDS]; 16931 soc_mem_t mem = INVALIDm; 16932 _bcm_kt2_mmu_info_t *mmu_info = _bcm_kt2_mmu_info[unit]; 16933 _bcm_kt2_cosq_node_t *node; 16934 16935 BCM_IF_ERROR_RETURN 16936 (_bcm_kt2_cosq_node_get(unit, gport, NULL, &local_port, NULL, 16937 &node)); 16938 16939 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 16940 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) || 16941 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport) || 16942 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport) || 16943 BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(gport) || 16944 BCM_GPORT_IS_SCHEDULER(gport)) { 16945 if ((node->level != _BCM_KT2_COSQ_NODE_LEVEL_L1) && 16946 (node->level != _BCM_KT2_COSQ_NODE_LEVEL_L2)) { 16947 return BCM_E_PARAM; 16948 } 16949 if (BCM_GPORT_IS_SCHEDULER(gport)) { 16950 BCM_IF_ERROR_RETURN( 16951 _bcm_kt2_cosq_child_node_at_input(node, cosq, 16952 &node)); 16953 } 16954 16955 startq = node->hw_index; 16956 startq1 = node->hw_index; 16957 } else { 16958 mmu_info = _bcm_kt2_mmu_info[unit]; 16959 numq = mmu_info->port[local_port].q_limit - 16960 mmu_info->port[local_port].q_offset; 16961 16962 if (cosq < 0 || cosq >= numq) { 16963 return BCM_E_PARAM; 16964 } 16965 startq = mmu_info->port[local_port].q_offset + cosq; 16966 startq1 = mmu_info->port[local_port].mcq_offset + cosq; 16967 } 16968 16969 if (type == bcmCosqControlIngressPortPGSharedDynamicEnable) { 16970 #if defined(BCM_SABER2_SUPPORT) 16971 if (SOC_IS_SABER2(unit)) { 16972 BCM_IF_ERROR_RETURN( 16973 _bcm_sb2_cosq_port_pg_idx_get(unit, gport, cosq, &midx)); 16974 } else 16975 #endif 16976 { 16977 BCM_IF_ERROR_RETURN( 16978 _bcm_kt2_cosq_port_pg_idx_get(unit, gport, cosq, &midx)); 16979 } 16980 16981 mem = THDI_PORT_PG_CONFIGm; 16982 16983 BCM_IF_ERROR_RETURN 16984 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, entry)); 16985 soc_mem_field32_set(unit, mem, entry, 16986 PG_SHARED_DYNAMICf, arg ? 1 : 0); 16987 if (arg) { 16988 soc_mem_field32_set(unit, mem, entry, 16989 PG_SHARED_LIMITf, SOC_KT2_COSQ_DROP_LIMIT_ALPHA_1_64); 16990 } 16991 SOC_IF_ERROR_RETURN 16992 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, midx, entry)); 16993 } else if (type == bcmCosqControlEgressUCSharedDynamicEnable) { 16994 if (node && 16995 BCM_GPORT_IS_MCAST_QUEUE_GROUP(node->gport)) { 16996 return BCM_E_PARAM; 16997 } 16998 16999 mem = MMU_THDO_QCONFIG_CELLm; 17000 BCM_IF_ERROR_RETURN 17001 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 17002 soc_mem_field32_set(unit, mem, entry, 17003 Q_LIMIT_DYNAMIC_CELLf, arg ? 1 : 0); 17004 if (arg) { 17005 soc_mem_field32_set(unit, mem, entry, 17006 Q_SHARED_ALPHA_CELLf, SOC_KT2_COSQ_DROP_LIMIT_ALPHA_1_64); 17007 } 17008 SOC_IF_ERROR_RETURN 17009 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 17010 } else if (type == bcmCosqControlEgressMCSharedDynamicEnable) { 17011 if (node && BCM_GPORT_IS_UCAST_QUEUE_GROUP(node->gport)) { 17012 return BCM_E_PARAM; 17013 } 17014 17015 mem = MMU_THDO_QCONFIG_CELLm; 17016 BCM_IF_ERROR_RETURN 17017 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq1, entry)); 17018 soc_mem_field32_set(unit, mem, entry, 17019 Q_LIMIT_DYNAMIC_CELLf, arg ? 1 : 0); 17020 if (arg) { 17021 soc_mem_field32_set(unit, mem, entry, 17022 Q_SHARED_ALPHA_CELLf, SOC_KT2_COSQ_DROP_LIMIT_ALPHA_1_64); 17023 } 17024 SOC_IF_ERROR_RETURN 17025 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq1, entry)); 17026 } else { 17027 return BCM_E_PARAM; 17028 } 17029 17030 return BCM_E_NONE; 17031 } 17032 17033 STATIC int 17034 _bcm_kt2_cosq_egr_queue_limit_enable_set(int unit, bcm_gport_t gport, 17035 bcm_cos_queue_t cosq, 17036 bcm_cosq_control_t type, 17037 int arg) 17038 { 17039 bcm_port_t local_port; 17040 int startq, startq1, numq; 17041 uint32 entry[SOC_MAX_MEM_WORDS]; 17042 soc_mem_t mem = INVALIDm; 17043 _bcm_kt2_cosq_node_t *node; 17044 _bcm_kt2_mmu_info_t *mmu_info = _bcm_kt2_mmu_info[unit]; 17045 int enable; 17046 17047 if (arg < 0) { 17048 return BCM_E_PARAM; 17049 } 17050 17051 arg = arg ? 1 : 0; 17052 17053 BCM_IF_ERROR_RETURN 17054 (_bcm_kt2_cosq_node_get(unit, gport, NULL, &local_port, NULL, 17055 &node)); 17056 17057 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 17058 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) || 17059 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport) || 17060 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport) || 17061 BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(gport) || 17062 BCM_GPORT_IS_SCHEDULER(gport)) { 17063 if ((node->level != _BCM_KT2_COSQ_NODE_LEVEL_L1) && 17064 (node->level != _BCM_KT2_COSQ_NODE_LEVEL_L2)) { 17065 return BCM_E_PARAM; 17066 } 17067 if (BCM_GPORT_IS_SCHEDULER(gport)) { 17068 BCM_IF_ERROR_RETURN( 17069 _bcm_kt2_cosq_child_node_at_input(node, cosq, 17070 &node)); 17071 } 17072 17073 startq = node->hw_index; 17074 startq1 = node->hw_index; 17075 } else { 17076 mmu_info = _bcm_kt2_mmu_info[unit]; 17077 numq = mmu_info->port[local_port].q_limit - 17078 mmu_info->port[local_port].q_offset; 17079 17080 if (cosq < 0 || cosq >= numq) { 17081 return BCM_E_PARAM; 17082 } 17083 startq = mmu_info->port[local_port].q_offset + cosq; 17084 startq1 = mmu_info->port[local_port].mcq_offset + cosq; 17085 } 17086 17087 17088 if (type == bcmCosqControlEgressUCQueueLimitEnable) { 17089 if (node && BCM_GPORT_IS_MCAST_QUEUE_GROUP(node->gport)) { 17090 return BCM_E_PARAM; 17091 } 17092 mem = MMU_THDO_QCONFIG_CELLm; 17093 17094 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 17095 enable = soc_mem_field32_get(unit, mem, entry, Q_LIMIT_ENABLE_CELLf); 17096 if (enable != arg) { 17097 soc_mem_field32_set(unit, mem, entry, Q_LIMIT_ENABLE_CELLf, arg); 17098 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 17099 } 17100 }else if (type == bcmCosqControlEgressMCQueueLimitEnable) { 17101 if (node && BCM_GPORT_IS_UCAST_QUEUE_GROUP(node->gport)) { 17102 return BCM_E_PARAM; 17103 } 17104 mem = MMU_THDO_QCONFIG_CELLm; 17105 17106 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq1, entry)); 17107 enable = soc_mem_field32_get(unit, mem, entry, Q_LIMIT_ENABLE_CELLf); 17108 if (enable != arg) { 17109 soc_mem_field32_set(unit, mem, entry, Q_LIMIT_ENABLE_CELLf, arg); 17110 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq1, entry)); 17111 } 17112 } else { 17113 return BCM_E_PARAM; 17114 } 17115 17116 return BCM_E_NONE; 17117 } 17118 17119 int 17120 bcm_kt2_cosq_control_set(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 17121 bcm_cosq_control_t type, int arg) 17122 { 17123 LOG_INFO(BSL_LS_BCM_COSQ, 17124 (BSL_META_U(unit, 17125 "bcm_kt2_cosq_control_set: unit=%d gport=0x%x cosq=%d \ 17126 type=%d arg=%d\n"), 17127 unit, gport, cosq, type, arg)); 17128 switch (type) { 17129 case bcmCosqControlEfPropagation: 17130 return _bcm_kt2_cosq_ef_op(unit, gport, cosq, &arg, _BCM_COSQ_OP_SET); 17131 17132 case bcmCosqControlRedirectQueueSharedLimitBytes: 17133 return _bcm_kt2_cosq_redirect_parameter_set(unit, OP_QUEUE_CONFIG_THDORDEQr, 17134 Q_SHARED_LIMITf, cosq, arg); 17135 17136 case bcmCosqControlRedirectQueueMinLimitBytes: 17137 return _bcm_kt2_cosq_redirect_parameter_set(unit, OP_QUEUE_CONFIG1_THDORDEQr, 17138 Q_MINf, cosq, arg); 17139 17140 case bcmCosqControlRedirectSharedDynamicEnable: 17141 return _bcm_kt2_cosq_redirect_parameter_set(unit, OP_QUEUE_CONFIG_THDORDEQr, 17142 Q_LIMIT_DYNAMICf, cosq, arg); 17143 17144 case bcmCosqControlRedirectQueueLimitEnable: 17145 return _bcm_kt2_cosq_redirect_parameter_set(unit, OP_QUEUE_CONFIG_THDORDEQr, 17146 Q_LIMIT_ENABLEf, cosq, arg); 17147 17148 case bcmCosqControlRedirectColorDynamicEnable: 17149 return _bcm_kt2_cosq_redirect_parameter_set(unit, OP_QUEUE_CONFIG1_THDORDEQr, 17150 Q_COLOR_DYNAMICf, cosq, arg); 17151 17152 case bcmCosqControlRedirectColorEnable: 17153 return _bcm_kt2_cosq_redirect_parameter_set(unit, OP_QUEUE_CONFIG1_THDORDEQr, 17154 Q_COLOR_ENABLEf, cosq, arg); 17155 17156 case bcmCosqControlEgressPoolLimitBytes: 17157 case bcmCosqControlEgressPoolYellowLimitBytes: 17158 case bcmCosqControlEgressPoolRedLimitBytes: 17159 case bcmCosqControlEgressPoolLimitEnable: 17160 return _bcm_kt2_cosq_egr_pool_set(unit, gport, cosq, type, arg); 17161 case bcmCosqControlEgressUCQueueSharedLimitBytes: 17162 case bcmCosqControlEgressMCQueueSharedLimitBytes: 17163 case bcmCosqControlEgressUCQueueMinLimitBytes: 17164 case bcmCosqControlEgressMCQueueMinLimitBytes: 17165 return _bcm_kt2_cosq_egr_queue_set(unit, gport, cosq, type, arg); 17166 case bcmCosqControlIngressPortPGSharedLimitBytes: 17167 case bcmCosqControlIngressPortPGMinLimitBytes: 17168 case bcmCosqControlIngressPortPGHeadroomLimitBytes: 17169 case bcmCosqControlIngressPortPGResetFloorBytes: 17170 return _bcm_kt2_cosq_ing_res_set(unit, gport, cosq, type, arg); 17171 case bcmCosqControlDropLimitAlpha: 17172 return _bcm_kt2_cosq_alpha_set(unit, gport, cosq, 17173 (bcm_cosq_control_drop_limit_alpha_value_t)arg); 17174 case bcmCosqControlIngressPortPGSharedDynamicEnable: 17175 case bcmCosqControlEgressUCSharedDynamicEnable: 17176 case bcmCosqControlEgressMCSharedDynamicEnable: 17177 return _bcm_kt2_cosq_dynamic_thresh_enable_set(unit, gport, cosq, 17178 type, arg); 17179 case bcmCosqControlEgressUCQueueLimitEnable: 17180 case bcmCosqControlEgressMCQueueLimitEnable: 17181 return _bcm_kt2_cosq_egr_queue_limit_enable_set(unit, gport, cosq, type, arg); 17182 17183 default: 17184 break; 17185 } 17186 17187 return BCM_E_UNAVAIL; 17188 } 17189 17190 int 17191 _bcm_kt2_cosq_redirect_parameter_get (int unit, soc_reg_t reg, 17192 soc_field_t field, bcm_cos_queue_t cosq, int *arg) 17193 { 17194 uint32 rval; 17195 if (!arg) { 17196 return BCM_E_PARAM; 17197 } 17198 17199 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, cosq, 17200 &rval)); 17201 *arg = soc_reg_field_get(unit, reg, rval, field); 17202 17203 return BCM_E_NONE; 17204 } 17205 17206 STATIC int 17207 _bcm_kt2_cosq_egr_pool_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 17208 bcm_cosq_control_t type, int *arg) 17209 { 17210 17211 int startq; 17212 uint32 entry[SOC_MAX_MEM_WORDS]; 17213 soc_mem_t mem = INVALIDm; 17214 soc_field_t fld_limit = INVALIDf; 17215 int granularity = 1; 17216 bcm_port_t local_port; 17217 _bcm_kt2_cosq_node_t *node; 17218 int cell_size = _BCM_KT2_COSQ_CELLSIZE; 17219 _bcm_kt2_mmu_info_t *mmu_info = _bcm_kt2_mmu_info[unit]; 17220 int numq; 17221 17222 if (!arg) { 17223 return BCM_E_PARAM; 17224 } 17225 17226 BCM_IF_ERROR_RETURN 17227 (_bcm_kt2_cosq_node_get(unit, gport, NULL, &local_port, NULL, 17228 &node)); 17229 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 17230 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) || 17231 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport) || 17232 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport) || 17233 BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(gport) || 17234 BCM_GPORT_IS_SCHEDULER(gport)) { 17235 if ((node->level != _BCM_KT2_COSQ_NODE_LEVEL_L1) && 17236 (node->level != _BCM_KT2_COSQ_NODE_LEVEL_L2)) { 17237 return BCM_E_PARAM; 17238 } 17239 if (BCM_GPORT_IS_SCHEDULER(gport)) { 17240 BCM_IF_ERROR_RETURN( 17241 _bcm_kt2_cosq_child_node_at_input(node, cosq, 17242 &node)); 17243 } 17244 17245 startq = node->hw_index; 17246 17247 } else { 17248 mmu_info = _bcm_kt2_mmu_info[unit]; 17249 numq = mmu_info->port[local_port].q_limit - 17250 mmu_info->port[local_port].q_offset; 17251 17252 if (cosq < 0 || cosq >= numq) { 17253 return BCM_E_PARAM; 17254 } 17255 startq = mmu_info->port[local_port].q_offset + cosq; 17256 } 17257 17258 if (IS_EXT_MEM_PORT(unit, local_port)) { 17259 cell_size = _BCM_KT2_COSQ_EXT_CELLSIZE; 17260 if (soc_feature(unit, soc_feature_mmu_packing)) { 17261 cell_size = _BCM_KT2_COSQ_EXT_PACKING_CELLSIZE; 17262 } 17263 } 17264 17265 mem = MMU_THDO_QCONFIG_CELLm; 17266 if (type == bcmCosqControlEgressPoolRedLimitBytes) { 17267 mem = MMU_THDO_QOFFSET_CELLm; 17268 } 17269 17270 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 17271 17272 switch (type) { 17273 case bcmCosqControlEgressPoolLimitBytes: 17274 fld_limit = Q_SHARED_LIMIT_CELLf; 17275 granularity = 1; 17276 break; 17277 case bcmCosqControlEgressPoolYellowLimitBytes: 17278 fld_limit = LIMIT_YELLOW_CELLf; 17279 granularity = 8; 17280 break; 17281 case bcmCosqControlEgressPoolRedLimitBytes: 17282 fld_limit = LIMIT_RED_CELLf; 17283 granularity = 8; 17284 break; 17285 case bcmCosqControlEgressPoolLimitEnable: 17286 fld_limit = Q_LIMIT_ENABLE_CELLf; 17287 granularity = 1; 17288 break; 17289 default: 17290 return BCM_E_UNAVAIL; 17291 } 17292 17293 /* Check for min/max values */ 17294 *arg = soc_mem_field32_get(unit, mem, entry, fld_limit); 17295 if (type == bcmCosqControlEgressPoolLimitEnable) { 17296 *arg = (*arg) * granularity; 17297 } else { 17298 *arg = (*arg) * cell_size * granularity; 17299 } 17300 17301 return BCM_E_NONE; 17302 } 17303 17304 STATIC int 17305 _bcm_kt2_cosq_egr_queue_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 17306 bcm_cosq_control_t type, int *arg) 17307 { 17308 bcm_port_t local_port; 17309 int startq, startq1; 17310 uint32 entry[SOC_MAX_MEM_WORDS]; 17311 soc_mem_t mem = INVALIDm; 17312 soc_field_t fld_limit = INVALIDf; 17313 int granularity = 1; 17314 int cell_size = _BCM_KT2_COSQ_CELLSIZE; 17315 _bcm_kt2_cosq_node_t *node; 17316 _bcm_kt2_mmu_info_t *mmu_info = _bcm_kt2_mmu_info[unit]; 17317 int numq; 17318 17319 if (!arg) { 17320 return BCM_E_PARAM; 17321 } 17322 17323 BCM_IF_ERROR_RETURN 17324 (_bcm_kt2_cosq_node_get(unit, gport, NULL, &local_port, NULL, 17325 &node)); 17326 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 17327 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) || 17328 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport) || 17329 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport) || 17330 BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(gport) || 17331 BCM_GPORT_IS_SCHEDULER(gport)) { 17332 if ((node->level != _BCM_KT2_COSQ_NODE_LEVEL_L1) && 17333 (node->level != _BCM_KT2_COSQ_NODE_LEVEL_L2)) { 17334 return BCM_E_PARAM; 17335 } 17336 if (BCM_GPORT_IS_SCHEDULER(gport)) { 17337 BCM_IF_ERROR_RETURN( 17338 _bcm_kt2_cosq_child_node_at_input(node, cosq, 17339 &node)); 17340 } 17341 17342 startq = node->hw_index; 17343 startq1 = node->hw_index; 17344 } else { 17345 mmu_info = _bcm_kt2_mmu_info[unit]; 17346 numq = mmu_info->port[local_port].q_limit - 17347 mmu_info->port[local_port].q_offset; 17348 17349 if (cosq < 0 || cosq >= numq) { 17350 return BCM_E_PARAM; 17351 } 17352 startq = mmu_info->port[local_port].q_offset + cosq; 17353 startq1 = mmu_info->port[local_port].mcq_offset + cosq; 17354 } 17355 17356 if (IS_EXT_MEM_PORT(unit, local_port)) { 17357 cell_size = _BCM_KT2_COSQ_EXT_CELLSIZE; 17358 if (soc_feature(unit, soc_feature_mmu_packing)) { 17359 cell_size = _BCM_KT2_COSQ_EXT_PACKING_CELLSIZE; 17360 } 17361 } 17362 17363 mem = MMU_THDO_QCONFIG_CELLm; 17364 17365 if ((type == bcmCosqControlEgressUCQueueSharedLimitBytes) || 17366 (type == bcmCosqControlEgressUCQueueMinLimitBytes)) { 17367 if (node && (BCM_GPORT_IS_MCAST_QUEUE_GROUP(node->gport) || 17368 BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(node->gport))) { 17369 return BCM_E_PARAM; 17370 } 17371 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, 17372 startq, entry)); 17373 } else if ((type == bcmCosqControlEgressMCQueueSharedLimitBytes) || 17374 (type == bcmCosqControlEgressMCQueueMinLimitBytes)) { 17375 if (node && (BCM_GPORT_IS_UCAST_QUEUE_GROUP(node->gport) || 17376 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(node->gport))) { 17377 return BCM_E_PARAM; 17378 } 17379 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, 17380 startq1, entry)); 17381 } 17382 17383 switch (type) { 17384 case bcmCosqControlEgressUCQueueSharedLimitBytes: 17385 case bcmCosqControlEgressMCQueueSharedLimitBytes: 17386 fld_limit = Q_SHARED_LIMIT_CELLf; 17387 granularity = 1; 17388 break; 17389 case bcmCosqControlEgressUCQueueMinLimitBytes: 17390 case bcmCosqControlEgressMCQueueMinLimitBytes: 17391 fld_limit = Q_MIN_CELLf; 17392 granularity = 1; 17393 break; 17394 default: 17395 return BCM_E_UNAVAIL; 17396 } 17397 17398 *arg = soc_mem_field32_get(unit, mem, entry, fld_limit); 17399 *arg = (*arg) * granularity * cell_size; 17400 return BCM_E_NONE; 17401 } 17402 17403 STATIC int 17404 _bcm_kt2_cosq_ing_res_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 17405 bcm_cosq_control_t type, int *arg) 17406 { 17407 bcm_port_t local_port; 17408 int midx; 17409 uint32 entry[SOC_MAX_MEM_WORDS]; 17410 soc_mem_t mem = INVALIDm; 17411 soc_field_t fld_limit = INVALIDf; 17412 int granularity = 1; 17413 int cell_size = _BCM_KT2_COSQ_CELLSIZE; 17414 17415 if (!arg) { 17416 return BCM_E_PARAM; 17417 } 17418 17419 BCM_IF_ERROR_RETURN 17420 (_bcm_kt2_cosq_node_get(unit, gport, NULL, &local_port, NULL, 17421 NULL)); 17422 17423 if (local_port < 0) { 17424 return BCM_E_PORT; 17425 } 17426 17427 if (IS_EXT_MEM_PORT(unit, local_port)) { 17428 cell_size = _BCM_KT2_COSQ_EXT_CELLSIZE; 17429 if (soc_feature(unit, soc_feature_mmu_packing)) { 17430 cell_size = _BCM_KT2_COSQ_EXT_PACKING_CELLSIZE; 17431 } 17432 } 17433 17434 #if defined(BCM_SABER2_SUPPORT) 17435 if (SOC_IS_SABER2(unit)) { 17436 BCM_IF_ERROR_RETURN( 17437 _bcm_sb2_cosq_port_pg_idx_get(unit, gport, cosq, &midx)); 17438 } else 17439 #endif 17440 { 17441 BCM_IF_ERROR_RETURN( 17442 _bcm_kt2_cosq_port_pg_idx_get(unit, gport, cosq, &midx)); 17443 } 17444 17445 mem = THDI_PORT_PG_CONFIGm; 17446 17447 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, entry)); 17448 17449 switch (type) { 17450 case bcmCosqControlIngressPortPGSharedLimitBytes: 17451 fld_limit = PG_SHARED_LIMITf; 17452 granularity = 1; 17453 break; 17454 case bcmCosqControlIngressPortPGMinLimitBytes: 17455 fld_limit = PG_MIN_LIMITf; 17456 granularity = 1; 17457 break; 17458 case bcmCosqControlIngressPortPGHeadroomLimitBytes: 17459 fld_limit = PG_HDRM_LIMITf; 17460 granularity = 1; 17461 break; 17462 case bcmCosqControlIngressPortPGResetFloorBytes: 17463 fld_limit = PG_RESET_FLOORf; 17464 granularity = 1; 17465 break; 17466 default: 17467 return BCM_E_UNAVAIL; 17468 } 17469 *arg = soc_mem_field32_get(unit, mem, entry, fld_limit); 17470 *arg = (*arg) * granularity * cell_size; 17471 return BCM_E_NONE; 17472 } 17473 17474 STATIC int 17475 _bcm_kt2_cosq_alpha_get(int unit, 17476 bcm_gport_t gport, bcm_cos_queue_t cosq, 17477 bcm_cosq_control_drop_limit_alpha_value_t *arg) 17478 { 17479 int startq = -1; 17480 int midx; 17481 uint32 entry[SOC_MAX_MEM_WORDS]; 17482 soc_mem_t mem = INVALIDm; 17483 int alpha; 17484 int dynamic_thresh_mode; 17485 _bcm_kt2_cosq_node_t *node; 17486 17487 if (!arg) { 17488 return BCM_E_PARAM; 17489 } 17490 17491 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 17492 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) || 17493 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport) || 17494 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport) || 17495 BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(gport) || 17496 BCM_GPORT_IS_SCHEDULER(gport)) { 17497 BCM_IF_ERROR_RETURN 17498 (_bcm_kt2_cosq_node_get(unit, gport, NULL, NULL, NULL, 17499 &node)); 17500 if ((node->level != _BCM_KT2_COSQ_NODE_LEVEL_L1) && 17501 (node->level != _BCM_KT2_COSQ_NODE_LEVEL_L2)) { 17502 return BCM_E_PARAM; 17503 } 17504 if (BCM_GPORT_IS_SCHEDULER(gport)) { 17505 BCM_IF_ERROR_RETURN( 17506 _bcm_kt2_cosq_child_node_at_input(node, cosq, 17507 &node)); 17508 } 17509 17510 startq = node->hw_index; 17511 } 17512 17513 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 17514 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) || 17515 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport) || 17516 BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(gport)) { 17517 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 17518 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport)) { 17519 BCM_IF_ERROR_RETURN 17520 (_bcm_kt2_cosq_dynamic_thresh_enable_get(unit, gport, cosq, 17521 bcmCosqControlEgressUCSharedDynamicEnable, 17522 &dynamic_thresh_mode)); 17523 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) || 17524 BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(gport)) { 17525 BCM_IF_ERROR_RETURN 17526 (_bcm_kt2_cosq_dynamic_thresh_enable_get(unit, gport, cosq, 17527 bcmCosqControlEgressMCSharedDynamicEnable, 17528 &dynamic_thresh_mode)); 17529 } 17530 if (!dynamic_thresh_mode){ 17531 return BCM_E_CONFIG; 17532 } 17533 17534 mem = MMU_THDO_QCONFIG_CELLm; 17535 17536 BCM_IF_ERROR_RETURN 17537 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 17538 17539 alpha = soc_mem_field32_get(unit, mem, entry, Q_SHARED_ALPHA_CELLf); 17540 17541 } else { 17542 #if defined(BCM_SABER2_SUPPORT) 17543 if (SOC_IS_SABER2(unit)) { 17544 BCM_IF_ERROR_RETURN( 17545 _bcm_sb2_cosq_port_pg_idx_get(unit, gport, cosq, &midx)); 17546 } else 17547 #endif 17548 { 17549 BCM_IF_ERROR_RETURN( 17550 _bcm_kt2_cosq_port_pg_idx_get(unit, gport, cosq, &midx)); 17551 } 17552 17553 mem = THDI_PORT_PG_CONFIGm; 17554 17555 BCM_IF_ERROR_RETURN 17556 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, entry)); 17557 17558 alpha = soc_mem_field32_get(unit, mem, entry, PG_SHARED_LIMITf); 17559 } 17560 17561 switch(alpha) { 17562 case SOC_KT2_COSQ_DROP_LIMIT_ALPHA_1_64: 17563 *arg = bcmCosqControlDropLimitAlpha_1_64; 17564 break; 17565 case SOC_KT2_COSQ_DROP_LIMIT_ALPHA_1_32: 17566 *arg = bcmCosqControlDropLimitAlpha_1_32; 17567 break; 17568 case SOC_KT2_COSQ_DROP_LIMIT_ALPHA_1_16: 17569 *arg = bcmCosqControlDropLimitAlpha_1_16; 17570 break; 17571 case SOC_KT2_COSQ_DROP_LIMIT_ALPHA_1_8: 17572 *arg = bcmCosqControlDropLimitAlpha_1_8; 17573 break; 17574 case SOC_KT2_COSQ_DROP_LIMIT_ALPHA_1_4: 17575 *arg = bcmCosqControlDropLimitAlpha_1_4; 17576 break; 17577 case SOC_KT2_COSQ_DROP_LIMIT_ALPHA_1_2: 17578 *arg = bcmCosqControlDropLimitAlpha_1_2; 17579 break; 17580 case SOC_KT2_COSQ_DROP_LIMIT_ALPHA_1: 17581 *arg = bcmCosqControlDropLimitAlpha_1; 17582 break; 17583 case SOC_KT2_COSQ_DROP_LIMIT_ALPHA_2: 17584 *arg = bcmCosqControlDropLimitAlpha_2; 17585 break; 17586 case SOC_KT2_COSQ_DROP_LIMIT_ALPHA_4: 17587 *arg = bcmCosqControlDropLimitAlpha_4; 17588 break; 17589 case SOC_KT2_COSQ_DROP_LIMIT_ALPHA_8: 17590 *arg = bcmCosqControlDropLimitAlpha_8; 17591 break; 17592 default: 17593 return BCM_E_PARAM; 17594 } 17595 17596 return BCM_E_NONE; 17597 } 17598 17599 STATIC int 17600 _bcm_kt2_cosq_dynamic_thresh_enable_get(int unit, 17601 bcm_gport_t gport, bcm_cos_queue_t cosq, 17602 bcm_cosq_control_t type, int *arg) 17603 { 17604 bcm_port_t local_port; 17605 int startq, startq1; 17606 int midx; 17607 uint32 entry[SOC_MAX_MEM_WORDS]; 17608 _bcm_kt2_cosq_node_t *node; 17609 soc_mem_t mem = INVALIDm; 17610 _bcm_kt2_mmu_info_t *mmu_info = _bcm_kt2_mmu_info[unit]; 17611 int numq; 17612 17613 if (arg == NULL) { 17614 return BCM_E_PARAM; 17615 } 17616 17617 BCM_IF_ERROR_RETURN 17618 (_bcm_kt2_cosq_node_get(unit, gport, NULL, &local_port, NULL, 17619 &node)); 17620 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 17621 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) || 17622 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport) || 17623 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport) || 17624 BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(gport) || 17625 BCM_GPORT_IS_SCHEDULER(gport)) { 17626 if ((node->level != _BCM_KT2_COSQ_NODE_LEVEL_L1) && 17627 (node->level != _BCM_KT2_COSQ_NODE_LEVEL_L2)) { 17628 return BCM_E_PARAM; 17629 } 17630 if (BCM_GPORT_IS_SCHEDULER(gport)) { 17631 BCM_IF_ERROR_RETURN( 17632 _bcm_kt2_cosq_child_node_at_input(node, cosq, 17633 &node)); 17634 } 17635 17636 startq = node->hw_index; 17637 startq1 = node->hw_index; 17638 } else { 17639 mmu_info = _bcm_kt2_mmu_info[unit]; 17640 numq = mmu_info->port[local_port].q_limit - 17641 mmu_info->port[local_port].q_offset; 17642 17643 if (cosq < 0 || cosq >= numq) { 17644 return BCM_E_PARAM; 17645 } 17646 startq = mmu_info->port[local_port].q_offset + cosq; 17647 startq1 = mmu_info->port[local_port].mcq_offset + cosq; 17648 } 17649 17650 if (type == bcmCosqControlIngressPortPGSharedDynamicEnable) { 17651 #if defined(BCM_SABER2_SUPPORT) 17652 if (SOC_IS_SABER2(unit)) { 17653 BCM_IF_ERROR_RETURN( 17654 _bcm_sb2_cosq_port_pg_idx_get(unit, gport, cosq, &midx)); 17655 } else 17656 #endif 17657 { 17658 BCM_IF_ERROR_RETURN( 17659 _bcm_kt2_cosq_port_pg_idx_get(unit, gport, cosq, &midx)); 17660 } 17661 17662 mem = THDI_PORT_PG_CONFIGm; 17663 17664 BCM_IF_ERROR_RETURN 17665 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, entry)); 17666 *arg = soc_mem_field32_get(unit, mem, entry, PG_SHARED_DYNAMICf); 17667 } else if (type == bcmCosqControlEgressUCSharedDynamicEnable) { 17668 if (node && BCM_GPORT_IS_MCAST_QUEUE_GROUP(node->gport)) { 17669 return BCM_E_PARAM; 17670 } 17671 17672 mem = MMU_THDO_QCONFIG_CELLm; 17673 BCM_IF_ERROR_RETURN 17674 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 17675 *arg = soc_mem_field32_get(unit, mem, entry, Q_LIMIT_DYNAMIC_CELLf); 17676 } else if (type == bcmCosqControlEgressMCSharedDynamicEnable) { 17677 if (node && BCM_GPORT_IS_UCAST_QUEUE_GROUP(node->gport)) { 17678 return BCM_E_PARAM; 17679 } 17680 17681 mem = MMU_THDO_QCONFIG_CELLm; 17682 BCM_IF_ERROR_RETURN 17683 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq1, entry)); 17684 *arg = soc_mem_field32_get(unit, mem, entry, Q_LIMIT_DYNAMIC_CELLf); 17685 } else { 17686 return BCM_E_PARAM; 17687 } 17688 17689 return BCM_E_NONE; 17690 } 17691 17692 STATIC int 17693 _bcm_kt2_cosq_egr_queue_limit_enable_get(int unit, bcm_gport_t gport, 17694 bcm_cos_queue_t cosq, 17695 bcm_cosq_control_t type, 17696 int *arg) 17697 { 17698 bcm_port_t local_port; 17699 int startq, startq1; 17700 uint32 entry[SOC_MAX_MEM_WORDS]; 17701 soc_mem_t mem = INVALIDm; 17702 _bcm_kt2_cosq_node_t *node; 17703 _bcm_kt2_mmu_info_t *mmu_info = _bcm_kt2_mmu_info[unit]; 17704 int numq; 17705 17706 BCM_IF_ERROR_RETURN 17707 (_bcm_kt2_cosq_node_get(unit, gport, NULL, &local_port, NULL, 17708 &node)); 17709 17710 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 17711 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) || 17712 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport) || 17713 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport) || 17714 BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(gport) || 17715 BCM_GPORT_IS_SCHEDULER(gport)) { 17716 if ((node->level != _BCM_KT2_COSQ_NODE_LEVEL_L1) && 17717 (node->level != _BCM_KT2_COSQ_NODE_LEVEL_L2)) { 17718 return BCM_E_PARAM; 17719 } 17720 if (BCM_GPORT_IS_SCHEDULER(gport)) { 17721 BCM_IF_ERROR_RETURN( 17722 _bcm_kt2_cosq_child_node_at_input(node, cosq, 17723 &node)); 17724 } 17725 17726 startq = node->hw_index; 17727 startq1 = node->hw_index; 17728 } else { 17729 mmu_info = _bcm_kt2_mmu_info[unit]; 17730 numq = mmu_info->port[local_port].q_limit - 17731 mmu_info->port[local_port].q_offset; 17732 17733 if (cosq < 0 || cosq >= numq) { 17734 return BCM_E_PARAM; 17735 } 17736 startq = mmu_info->port[local_port].q_offset + cosq; 17737 startq1 = mmu_info->port[local_port].mcq_offset + cosq; 17738 } 17739 17740 if (type == bcmCosqControlEgressUCQueueLimitEnable) { 17741 if (node && BCM_GPORT_IS_MCAST_QUEUE_GROUP(node->gport)) { 17742 return BCM_E_PARAM; 17743 } 17744 mem = MMU_THDO_QCONFIG_CELLm; 17745 mem = MMU_THDO_QCONFIG_CELLm; 17746 17747 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 17748 *arg = soc_mem_field32_get(unit, mem, entry, Q_LIMIT_ENABLE_CELLf); 17749 } else if (type == bcmCosqControlEgressMCQueueLimitEnable) { 17750 if (node && BCM_GPORT_IS_UCAST_QUEUE_GROUP(node->gport)) { 17751 return BCM_E_PARAM; 17752 } 17753 mem = MMU_THDO_QCONFIG_CELLm; 17754 17755 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq1, entry)); 17756 *arg = soc_mem_field32_get(unit, mem, entry, Q_LIMIT_ENABLE_CELLf); 17757 } else { 17758 return BCM_E_PARAM; 17759 } 17760 17761 return BCM_E_NONE; 17762 } 17763 17764 int 17765 bcm_kt2_cosq_control_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 17766 bcm_cosq_control_t type, int *arg) 17767 { 17768 LOG_INFO(BSL_LS_BCM_COSQ, 17769 (BSL_META_U(unit, 17770 "bcm_kt2_cosq_control_get: unit=%d gport=0x%x cosq=%d type=%d\n"), 17771 unit, gport, cosq, type)); 17772 switch (type) { 17773 case bcmCosqControlEfPropagation: 17774 return _bcm_kt2_cosq_ef_op(unit, gport, cosq, arg, _BCM_COSQ_OP_GET); 17775 case bcmCosqControlPortQueueUcast: 17776 case bcmCosqControlPortQueueMcast: 17777 return _bcm_kt2_cosq_port_qnum_get(unit, gport, cosq, type, arg); 17778 case bcmCosqControlRedirectQueueSharedLimitBytes: 17779 return _bcm_kt2_cosq_redirect_parameter_get(unit, OP_QUEUE_CONFIG_THDORDEQr, 17780 Q_SHARED_LIMITf, cosq, arg); 17781 case bcmCosqControlRedirectQueueMinLimitBytes: 17782 return _bcm_kt2_cosq_redirect_parameter_get(unit, OP_QUEUE_CONFIG1_THDORDEQr, 17783 Q_MINf, cosq, arg); 17784 case bcmCosqControlRedirectSharedDynamicEnable: 17785 return _bcm_kt2_cosq_redirect_parameter_get(unit, OP_QUEUE_CONFIG_THDORDEQr, 17786 Q_LIMIT_DYNAMICf, cosq, arg); 17787 case bcmCosqControlRedirectQueueLimitEnable: 17788 return _bcm_kt2_cosq_redirect_parameter_get(unit, OP_QUEUE_CONFIG_THDORDEQr, 17789 Q_LIMIT_ENABLEf, cosq, arg); 17790 case bcmCosqControlRedirectColorDynamicEnable: 17791 return _bcm_kt2_cosq_redirect_parameter_get(unit, OP_QUEUE_CONFIG1_THDORDEQr, 17792 Q_COLOR_DYNAMICf, cosq, arg); 17793 case bcmCosqControlRedirectColorEnable: 17794 return _bcm_kt2_cosq_redirect_parameter_get(unit, OP_QUEUE_CONFIG1_THDORDEQr, 17795 Q_COLOR_ENABLEf, cosq, arg); 17796 case bcmCosqControlEgressPoolLimitBytes: 17797 case bcmCosqControlEgressPoolYellowLimitBytes: 17798 case bcmCosqControlEgressPoolRedLimitBytes: 17799 case bcmCosqControlEgressPoolLimitEnable: 17800 return _bcm_kt2_cosq_egr_pool_get(unit, gport, cosq, type, arg); 17801 case bcmCosqControlEgressUCQueueSharedLimitBytes: 17802 case bcmCosqControlEgressMCQueueSharedLimitBytes: 17803 case bcmCosqControlEgressUCQueueMinLimitBytes: 17804 case bcmCosqControlEgressMCQueueMinLimitBytes: 17805 return _bcm_kt2_cosq_egr_queue_get(unit, gport, cosq, type, arg); 17806 case bcmCosqControlIngressPortPGSharedLimitBytes: 17807 case bcmCosqControlIngressPortPGMinLimitBytes: 17808 case bcmCosqControlIngressPortPGHeadroomLimitBytes: 17809 case bcmCosqControlIngressPortPGResetFloorBytes: 17810 return _bcm_kt2_cosq_ing_res_get(unit, gport, cosq, type, arg); 17811 case bcmCosqControlDropLimitAlpha: 17812 return _bcm_kt2_cosq_alpha_get(unit, gport, cosq, 17813 (bcm_cosq_control_drop_limit_alpha_value_t *)arg); 17814 case bcmCosqControlIngressPortPGSharedDynamicEnable: 17815 case bcmCosqControlEgressUCSharedDynamicEnable: 17816 case bcmCosqControlEgressMCSharedDynamicEnable: 17817 return _bcm_kt2_cosq_dynamic_thresh_enable_get(unit, gport, cosq, 17818 type, arg); 17819 case bcmCosqControlEgressUCQueueLimitEnable: 17820 case bcmCosqControlEgressMCQueueLimitEnable: 17821 return _bcm_kt2_cosq_egr_queue_limit_enable_get(unit, gport, cosq, type, arg); 17822 default: 17823 break; 17824 } 17825 17826 return BCM_E_UNAVAIL; 17827 } 17828 17829 int 17830 bcm_kt2_cosq_port_flush(int unit, 17831 bcm_port_t port, 17832 bcm_cosq_flush_type_t type) 17833 { 17834 _bcm_kt2_mmu_info_t *mmu_info; 17835 _bcm_kt2_cosq_node_t *port_node = NULL; 17836 _bcm_kt2_cosq_node_t *s0_node = NULL; 17837 _bcm_kt2_cosq_node_t *s1_node = NULL; 17838 _bcm_kt2_cosq_node_t *l0_node = NULL; 17839 _bcm_kt2_cosq_node_t *l1_node = NULL; 17840 _bcm_kt2_cosq_node_t *l2_node = NULL; 17841 uint32 flush_reg=0; 17842 17843 if (!SOC_PORT_VALID(unit, port)) { 17844 LOG_CLI((BSL_META_U(unit, 17845 "Invalid Port:%d \n"), port)); 17846 return BCM_E_PORT; 17847 } 17848 switch (type) { 17849 case bcmCosqFlushTypePort : 17850 BCM_IF_ERROR_RETURN(READ_TOQ_FLUSH0r(unit, &flush_reg)); 17851 soc_reg_field_set(unit, TOQ_FLUSH0r, &flush_reg, 17852 FLUSH_ACTIVEf,1); 17853 soc_reg_field_set(unit, TOQ_FLUSH0r, &flush_reg, FLUSH_TYPEf,1); 17854 soc_reg_field_set(unit, TOQ_FLUSH0r, &flush_reg, FLUSH_NUMf,1); 17855 soc_reg_field_set(unit, TOQ_FLUSH0r, &flush_reg, 17856 FLUSH_ID0f, port); 17857 if (IS_EXT_MEM_PORT(unit, port)) { 17858 soc_reg_field_set(unit, TOQ_FLUSH0r, &flush_reg, 17859 FLUSH_EXTERNALf, 1); 17860 } else { 17861 soc_reg_field_set(unit, TOQ_FLUSH0r, &flush_reg, 17862 FLUSH_EXTERNALf, 0); 17863 } 17864 BCM_IF_ERROR_RETURN(WRITE_TOQ_FLUSH0r(unit, flush_reg)); 17865 break; 17866 case bcmCosqFlushTypeQueue: 17867 default: 17868 /* Queue Flushing one by one so ... */ 17869 mmu_info = _bcm_kt2_mmu_info[unit]; 17870 /* get the root node */ 17871 port_node = &mmu_info->sched_node[port]; 17872 if (port_node && port_node->cosq_attached_to < 0) { 17873 LOG_CLI((BSL_META_U(unit, 17874 "No Scheduling node found for port:%d\n"), port)); 17875 return BCM_E_NONE; 17876 } 17877 if (port_node->child == NULL) { 17878 /*Flushing the Queue when only Root Node is present with no child*/ 17879 BCM_IF_ERROR_RETURN(_bcm_kt2_cosq_flush_queues(unit, port, 17880 port_node, port_node->gport)); 17881 break; 17882 } 17883 s0_node = port_node->child->level == _BCM_KT2_COSQ_NODE_LEVEL_S0 ? 17884 port_node->child : port_node; 17885 if (s0_node->child == NULL) { 17886 /*Flushing the Queue when S0 Node is present with no child*/ 17887 BCM_IF_ERROR_RETURN(_bcm_kt2_cosq_flush_queues(unit, port, 17888 s0_node, s0_node->gport)); 17889 break; 17890 } 17891 17892 do { 17893 s1_node = s0_node->child->level == _BCM_KT2_COSQ_NODE_LEVEL_S1 ? 17894 s0_node->child : s0_node; 17895 do { 17896 for (l0_node = s1_node->child; 17897 l0_node != NULL; 17898 l0_node = l0_node->sibling) { 17899 for (l1_node = l0_node->child; 17900 l1_node != NULL; 17901 l1_node = l1_node->sibling) { 17902 for (l2_node = l1_node->child; 17903 l2_node != NULL; 17904 l2_node = l2_node->sibling) { 17905 /* Get Queue from L2 Node */ 17906 LOG_VERBOSE(BSL_LS_BCM_COSQ, (BSL_META_U(unit, 17907 "Flushing Port:%d => " 17908 "QueueNumber:%d \n"), 17909 port, l2_node->hw_index)); 17910 /* Now flush the queue */ 17911 BCM_IF_ERROR_RETURN(_bcm_kt2_cosq_flush_queues( 17912 unit, port, 17913 l2_node, l2_node->gport)); 17914 /* SDK-116300 After queue flush operation l2 nodes are getting disabled. 17915 Need to enable the l2 nodes after flush. */ 17916 BCM_IF_ERROR_RETURN(soc_kt2_cosq_queue_enable(unit, l2_node->hw_index, 1)); 17917 } 17918 } 17919 } 17920 if (s1_node == s0_node) { 17921 break; 17922 } 17923 s1_node = s1_node->sibling; 17924 } while (s1_node != NULL); 17925 if (s0_node == port_node) { 17926 break; 17927 } 17928 s0_node = s0_node->sibling; 17929 } while (s0_node != NULL); 17930 break; 17931 } 17932 return BCM_E_NONE; 17933 } 17934 17935 int 17936 bcm_kt2_cosq_drop_status_enable_set(int unit, bcm_port_t port, int enable) 17937 { 17938 uint32 rval; 17939 uint64 r64val; 17940 17941 BCM_IF_ERROR_RETURN(READ_OP_E2ECC_PORT_CONFIGr(unit, port, &rval)); 17942 soc_reg_field_set(unit, OP_E2ECC_PORT_CONFIGr, &rval, 17943 COS_MASKf, enable ? 0xFF : 0x0); 17944 soc_reg_field_set(unit, OP_E2ECC_PORT_CONFIGr, &rval, 17945 E2ECC_RPT_ENf, enable ? 1 : 0); 17946 BCM_IF_ERROR_RETURN(WRITE_OP_E2ECC_PORT_CONFIGr(unit, port, rval)); 17947 17948 17949 BCM_IF_ERROR_RETURN(READ_OP_THR_CONFIGr(unit, &rval)); 17950 soc_reg_field_set(unit, OP_THR_CONFIGr, &rval, EARLY_E2E_SELECTf, 17951 enable ? 1 : 0); 17952 BCM_IF_ERROR_RETURN(WRITE_OP_THR_CONFIGr(unit, rval)); 17953 17954 COMPILER_64_ZERO(r64val); 17955 soc_reg64_field32_set(unit, MMU_INTFO_CONGST_STr, 17956 &r64val, ENf, 1); 17957 SOC_IF_ERROR_RETURN(WRITE_MMU_INTFO_CONGST_STr(unit, 17958 port, r64val)); 17959 17960 return BCM_E_NONE; 17961 } 17962 17963 /* 17964 * Function: 17965 * bcm_kt2_cosq_field_classifier_id_create 17966 * Purpose: 17967 * Create an endpoint. 17968 * Parameters: 17969 * unit - (IN) Unit number. 17970 * classifier - (IN) Classifier attributes 17971 * classifier_id - (OUT) Classifier ID 17972 * Returns: 17973 * BCM_E_xxx 17974 */ 17975 int 17976 bcm_kt2_cosq_field_classifier_id_create( 17977 int unit, 17978 bcm_cosq_classifier_t *classifier, 17979 int *classifier_id) 17980 { 17981 int rv; 17982 int ref_count = 0; 17983 int ent_per_set = 16; 17984 int i; 17985 17986 if (NULL == classifier || NULL == classifier_id) { 17987 return BCM_E_PARAM; 17988 } 17989 17990 for (i = 0; i < SOC_MEM_SIZE(unit, IFP_COS_MAPm);) { 17991 rv = soc_profile_mem_ref_count_get 17992 (unit, _bcm_kt2_ifp_cos_map_profile[unit], i, &ref_count); 17993 if (SOC_E_NONE != rv) { 17994 return (rv); 17995 } 17996 if (0 == ref_count) { 17997 break; 17998 } 17999 i = i + ent_per_set; 18000 } 18001 18002 if (i >= SOC_MEM_SIZE(unit, IFP_COS_MAPm) && ref_count != 0) { 18003 *classifier_id = 0; 18004 return (BCM_E_RESOURCE); 18005 } 18006 18007 _BCM_COSQ_CLASSIFIER_FIELD_SET(*classifier_id, (i / ent_per_set)); 18008 18009 return (BCM_E_NONE); 18010 } 18011 18012 /* 18013 * Function: 18014 * bcm_kt2_cosq_field_classifier_get 18015 * Purpose: 18016 * Get classifier type information. 18017 * Parameters: 18018 * unit - (IN) Unit number. 18019 * classifier_id - (IN) Classifier ID 18020 * classifier - (OUT) Classifier info 18021 * Returns: 18022 * BCM_E_xxx 18023 */ 18024 int 18025 bcm_kt2_cosq_field_classifier_get( 18026 int unit, 18027 int classifier_id, 18028 bcm_cosq_classifier_t *classifier) 18029 { 18030 sal_memset(classifier, 0, sizeof(bcm_cosq_classifier_t)); 18031 18032 if (_BCM_COSQ_CLASSIFIER_IS_FIELD(classifier_id)) { 18033 classifier->flags |= BCM_COSQ_CLASSIFIER_FIELD; 18034 } 18035 18036 return BCM_E_NONE; 18037 } 18038 18039 /* 18040 * Function: 18041 * bcm_kt2_cosq_service_classifier_id_create 18042 * Purpose: 18043 * Create an endpoint. 18044 * Parameters: 18045 * unit - (IN) Unit number. 18046 * classifier - (IN) Classifier attributes 18047 * classifier_id - (OUT) Classifier ID 18048 * Returns: 18049 * BCM_E_xxx 18050 */ 18051 int 18052 bcm_kt2_cosq_service_classifier_id_create( 18053 int unit, 18054 bcm_cosq_classifier_t *classifier, 18055 int *classifier_id) 18056 { 18057 if (NULL == classifier || NULL == classifier_id) { 18058 return BCM_E_PARAM; 18059 } 18060 /* XXX check classifier->vlan for valid vlan */ 18061 if (classifier->flags & BCM_COSQ_CLASSIFIER_VLAN) { 18062 if (!BCM_VLAN_VALID(classifier->vlan)) { 18063 return BCM_E_PARAM; 18064 } 18065 _BCM_COSQ_CLASSIFIER_SERVICE_SET(*classifier_id, 18066 classifier->vlan); 18067 } 18068 /* XXX check classifier->vfi_index for valid vfi index */ 18069 if (classifier->flags & BCM_COSQ_CLASSIFIER_VFI) { 18070 /* coverity[unsigned_compare] */ 18071 if ((classifier->vfi_index < 0) || 18072 (classifier->vfi_index > BCM_VLAN_MAX)) { 18073 /* KT2 supports 4096 vfi indices */ 18074 return BCM_E_PARAM; 18075 } 18076 _BCM_COSQ_CLASSIFIER_SERVICE_SET(*classifier_id, 18077 (classifier->vfi_index + BCM_VLAN_MAX + 1)); 18078 } 18079 return BCM_E_NONE; 18080 } 18081 18082 /* 18083 * Function: 18084 * bcm_kt2_cosq_service_classifier_id_destroy 18085 * Purpose: 18086 * free resource associated with this service classifier id. 18087 * Parameters: 18088 * unit - (IN) Unit number. 18089 * classifier_id - (IN) Classifier ID 18090 * Returns: 18091 * BCM_E_xxx 18092 */ 18093 int 18094 bcm_kt2_cosq_service_classifier_id_destroy( 18095 int unit, 18096 int classifier_id) 18097 { 18098 return BCM_E_NONE; 18099 } 18100 18101 /* 18102 * Function: 18103 * bcm_kt2_cosq_field_classifier_map_set 18104 * Purpose: 18105 * Set internal priority to ingress field processor CoS queue 18106 * override mapping. 18107 * Parameters: 18108 * unit - (IN) Unit number. 18109 * classifier_id - (IN) Classifier ID 18110 * count - (IN) Number of elements in priority_array and 18111 * cosq_array 18112 * priority_array - (IN) Array of internal priorities 18113 * cosq_array - (IN) Array of COS queues 18114 * Returns: 18115 * BCM_E_xxx 18116 */ 18117 int 18118 bcm_kt2_cosq_field_classifier_map_set(int unit, 18119 int classifier_id, 18120 int count, 18121 bcm_cos_t *priority_array, 18122 bcm_cos_queue_t *cosq_array) 18123 { 18124 int rv; 18125 int i; 18126 int max_entries = 16; 18127 uint32 index; 18128 void *entries[1]; 18129 ifp_cos_map_entry_t *ent_buf; 18130 int field_width; 18131 int ref_count = 0; 18132 18133 /* Input parameter check. */ 18134 if (!_BCM_COSQ_CLASSIFIER_IS_FIELD(classifier_id)) { 18135 return (BCM_E_PARAM); 18136 } 18137 18138 if (count > max_entries) { 18139 return (BCM_E_PARAM); 18140 } 18141 18142 ent_buf = sal_alloc(sizeof(ifp_cos_map_entry_t) * max_entries, 18143 "IFP_COS_MAP entry"); 18144 if (ent_buf == NULL) { 18145 return (BCM_E_MEMORY); 18146 } 18147 18148 field_width = soc_mem_field_length(unit, IFP_COS_MAPm, IFP_COSf); 18149 sal_memset(ent_buf, 0, sizeof(ifp_cos_map_entry_t) * max_entries); 18150 entries[0] = ent_buf; 18151 18152 for (i = 0; i < count; i++) { 18153 if (priority_array[i] < max_entries) { 18154 if (cosq_array[i] >= (1 << field_width)) { 18155 return BCM_E_PARAM; 18156 } 18157 soc_mem_field32_set(unit, IFP_COS_MAPm, &ent_buf[priority_array[i]], 18158 IFP_COSf, cosq_array[i]); 18159 } 18160 } 18161 18162 index = _BCM_COSQ_CLASSIFIER_FIELD_GET(classifier_id); 18163 rv = soc_profile_mem_ref_count_get 18164 (unit, _bcm_kt2_ifp_cos_map_profile[unit], 18165 index * max_entries, &ref_count); 18166 if (SOC_E_NONE != rv) { 18167 sal_free(ent_buf); 18168 return (rv); 18169 } 18170 if (ref_count == 0) { 18171 rv = soc_profile_mem_add(unit, _bcm_kt2_ifp_cos_map_profile[unit], 18172 entries, max_entries, &index); 18173 } else { 18174 rv = soc_profile_mem_set(unit, _bcm_kt2_ifp_cos_map_profile[unit], 18175 entries, index * max_entries); 18176 /* Now decrement the ref_count which got incremented by mem_set */ 18177 BCM_IF_ERROR_RETURN 18178 (soc_profile_mem_delete(unit, 18179 _bcm_kt2_ifp_cos_map_profile[unit], 18180 index * max_entries)); 18181 } 18182 sal_free(ent_buf); 18183 return (rv); 18184 } 18185 18186 /* 18187 * Function: 18188 * bcm_kt2_cosq_field_classifier_map_get 18189 * Purpose: 18190 * Get internal priority to ingress field processor CoS queue 18191 * override mapping information. 18192 * Parameters: 18193 * unit - (IN) Unit number. 18194 * classifier_id - (IN) Classifier ID 18195 * array_max - (IN) Size of priority_array and cosq_array 18196 * priority_array - (IN) Array of internal priorities 18197 * cosq_array - (OUT) Array of COS queues 18198 * array_count - (OUT) Size of cosq_array 18199 * Returns: 18200 * BCM_E_xxx 18201 */ 18202 int 18203 bcm_kt2_cosq_field_classifier_map_get(int unit, 18204 int classifier_id, 18205 int array_max, 18206 bcm_cos_t *priority_array, 18207 bcm_cos_queue_t *cosq_array, 18208 int *array_count) 18209 { 18210 int rv; 18211 int i; 18212 int ent_per_set = 16; 18213 uint32 index; 18214 void *entries[1]; 18215 ifp_cos_map_entry_t *ent_buf; 18216 18217 /* Input parameter check. */ 18218 if (NULL == priority_array || NULL == cosq_array || NULL == array_count) { 18219 return (BCM_E_PARAM); 18220 } 18221 18222 /* Allocate entry buffer. */ 18223 ent_buf = sal_alloc(sizeof(ifp_cos_map_entry_t) * ent_per_set, 18224 "IFP_COS_MAP entry"); 18225 if (ent_buf == NULL) { 18226 return (BCM_E_MEMORY); 18227 } 18228 sal_memset(ent_buf, 0, sizeof(ifp_cos_map_entry_t) * ent_per_set); 18229 entries[0] = ent_buf; 18230 18231 /* Get profile table entry set base index. */ 18232 index = _BCM_COSQ_CLASSIFIER_FIELD_GET(classifier_id); 18233 18234 /* Read out entries from profile table into allocated buffer. */ 18235 rv = soc_profile_mem_get(unit, _bcm_kt2_ifp_cos_map_profile[unit], 18236 index * ent_per_set, ent_per_set, entries); 18237 if (!(rv == SOC_E_NOT_FOUND || rv == SOC_E_NONE)) { 18238 sal_free(ent_buf); 18239 return rv; 18240 } 18241 18242 *array_count = array_max > ent_per_set ? ent_per_set : array_max; 18243 18244 /* Copy values into API OUT parameters. */ 18245 for (i = 0; i < *array_count; i++) { 18246 if (priority_array[i] >= 16) { 18247 sal_free(ent_buf); 18248 return BCM_E_PARAM; 18249 } 18250 cosq_array[i] = soc_mem_field32_get(unit, IFP_COS_MAPm, 18251 &ent_buf[priority_array[i]], 18252 IFP_COSf); 18253 } 18254 18255 sal_free(ent_buf); 18256 return (BCM_E_NONE); 18257 } 18258 18259 /* 18260 * Function: 18261 * bcm_kt2_cosq_field_classifier_map_clear 18262 * Purpose: 18263 * Delete an internal priority to ingress field processor CoS queue 18264 * override mapping profile set. 18265 * Parameters: 18266 * unit - (IN) Unit number. 18267 * classifier_id - (IN) Classifier ID 18268 * Returns: 18269 * BCM_E_xxx 18270 */ 18271 int 18272 bcm_kt2_cosq_field_classifier_map_clear(int unit, int classifier_id) 18273 { 18274 int ent_per_set = 16; 18275 uint32 index; 18276 18277 /* Get profile table entry set base index. */ 18278 index = _BCM_COSQ_CLASSIFIER_FIELD_GET(classifier_id); 18279 18280 /* Delete the profile entries set. */ 18281 BCM_IF_ERROR_RETURN 18282 (soc_profile_mem_delete(unit, 18283 _bcm_kt2_ifp_cos_map_profile[unit], 18284 index * ent_per_set)); 18285 return (BCM_E_NONE); 18286 } 18287 18288 /* 18289 * Function: 18290 * bcm_kt2_cosq_field_classifier_id_destroy 18291 * Purpose: 18292 * Free resource associated with this field classifier id. 18293 * Parameters: 18294 * unit - (IN) Unit number. 18295 * classifier_id - (IN) Classifier ID 18296 * Returns: 18297 * BCM_E_xxx 18298 */ 18299 int 18300 bcm_kt2_cosq_field_classifier_id_destroy(int unit, int classifier_id) 18301 { 18302 return (BCM_E_NONE); 18303 } 18304 18305 /* 18306 * Function: 18307 * bcm_kt2_cosq_service_map_set 18308 * Purpose: 18309 * Set the mapping from port, classifier, and multiple internal priorities 18310 * to multiple COS queues in a queue group. 18311 * Parameters: 18312 * unit - (IN) Unit number. 18313 * port - (IN) local port ID 18314 * classifier_id - (IN) Classifier ID 18315 * queue_group - (IN) Base queue ID 18316 * array_count - (IN) Number of elements in priority_array and 18317 * cosq_array 18318 * priority_array - (IN) Array of internal priorities 18319 * cosq_array - (IN) Array of COS queues 18320 * Returns: 18321 * BCM_E_xxx 18322 * Comments: 18323 * <service_cos> = 18324 * SERVICE_COS_MAP[VLAN].SERVICE_COS + 18325 * ING_QUEUE_OFFSET_MAPPING_TABLE[PRI].QUEUE_OFFSET 18326 * 18327 * Unicast Service Queue Number = 18328 * ING_COS_MODE[PORT].SERVICE_BASE_QUEUE_NUM + 18329 * PHYSICAL_PORT_BASE_QUEUE[PORT].BASE_QUEUE_NUMBER + 18330 * <service_cos> 18331 * 18332 * Multicast Service Queue Number = 18333 * RQE_PP_PORT_CONFIG[PORT].BASE_QUEUE + <service_cos> 18334 */ 18335 int 18336 bcm_kt2_cosq_service_map_set( 18337 int unit, 18338 bcm_port_t port, 18339 int classifier_id, 18340 bcm_gport_t queue_group, 18341 int count, 18342 bcm_cos_t *priority, 18343 bcm_cos_queue_t *cosq) 18344 { 18345 int rv = BCM_E_NONE; 18346 int i; 18347 service_cos_map_entry_t scm; 18348 ing_queue_offset_mapping_table_entry_t map_entries[16]; 18349 void *entries[1]; 18350 uint32 old_index = 0; 18351 uint32 new_index = 0; 18352 int vid; 18353 int valid_entry; 18354 _bcm_kt2_cosq_node_t *node; 18355 uint32 rval = 0, rval1 = 0; 18356 uint32 uc_base = 0, required_base = 0; 18357 uint32 service_cos = 0; 18358 bcm_port_t local_port; 18359 _bcm_kt2_mmu_info_t *mmu_info; 18360 _bcm_kt2_cosq_port_info_t *port_info; 18361 18362 if (!_BCM_COSQ_CLASSIFIER_IS_SERVICE(classifier_id)) { 18363 return BCM_E_PARAM; 18364 } 18365 18366 /* index above 4K is for VFI */ 18367 vid = _BCM_COSQ_CLASSIFIER_SERVICE_GET(classifier_id); 18368 18369 /* validate the vlan id */ 18370 if (vid < 0 || vid >= SOC_MEM_SIZE(unit, SERVICE_COS_MAPm)) { 18371 return BCM_E_PARAM; 18372 } 18373 18374 BCM_IF_ERROR_RETURN(_bcm_kt2_cosq_node_get(unit, queue_group, NULL, 18375 &local_port, NULL, &node)); 18376 18377 if (node->cosq_attached_to < 0) { 18378 return BCM_E_PARAM; 18379 } 18380 18381 /* validate the user parameters */ 18382 if (count > 16) { 18383 return BCM_E_PARAM; 18384 } 18385 18386 /* queues allocated for this queue_group should be contiguous.*/ 18387 /* check if user's queue number is valid */ 18388 for (i = 0; i < count; i++) { 18389 if (cosq[i] >= 8 || priority[i] >= 16) { 18390 return BCM_E_PARAM; 18391 } 18392 } 18393 18394 sal_memset(map_entries, 0, sizeof(map_entries)); 18395 18396 BCM_IF_ERROR_RETURN( 18397 soc_mem_read(unit, SERVICE_COS_MAPm, MEM_BLOCK_ANY, (int)vid, &scm)); 18398 valid_entry = soc_mem_field32_get(unit, SERVICE_COS_MAPm, &scm, VALIDf); 18399 18400 SOC_IF_ERROR_RETURN(READ_RQE_PP_PORT_CONFIGr(unit, port, &rval1)); 18401 SOC_IF_ERROR_RETURN(READ_ING_COS_MODEr(unit, port, &rval)); 18402 18403 if ((soc_reg_field_get(unit, RQE_PP_PORT_CONFIGr, rval1, COS_MODEf) != 3) && 18404 (soc_reg_field_get(unit, ING_COS_MODEr, rval, COS_MODEf) == 3)) { 18405 uc_base = soc_reg_field_get(unit, ING_COS_MODEr, rval, 18406 SERVICE_BASE_QUEUE_NUMf); 18407 mmu_info = _bcm_kt2_mmu_info[unit]; 18408 port_info = &mmu_info->port[local_port]; 18409 required_base = port_info->uc_vlan_base < mmu_info->num_queues -1 ? 18410 port_info->uc_vlan_base : 18411 ((uc_base == 0) ? node->hw_index : uc_base); 18412 if (uc_base != required_base) { 18413 uc_base = required_base; 18414 soc_reg_field_set(unit, ING_COS_MODEr, &rval, 18415 SERVICE_BASE_QUEUE_NUMf, uc_base); 18416 SOC_IF_ERROR_RETURN(WRITE_ING_COS_MODEr(unit, port, rval)); 18417 } 18418 } else { 18419 uc_base = soc_reg_field_get(unit, ING_COS_MODEr, rval, BASE_QUEUE_NUMf); 18420 if (uc_base != soc_reg_field_get(unit, ING_COS_MODEr, rval, 18421 SERVICE_BASE_QUEUE_NUMf)) { 18422 /* First time service queuing being configured on this port */ 18423 soc_reg_field_set(unit, ING_COS_MODEr, &rval, 18424 SERVICE_BASE_QUEUE_NUMf, uc_base); 18425 SOC_IF_ERROR_RETURN(WRITE_ING_COS_MODEr(unit, port, rval)); 18426 } 18427 } 18428 18429 service_cos = node->hw_index - uc_base; 18430 18431 entries[0] = &map_entries; 18432 if (valid_entry) { 18433 uint32 current_service_cos; 18434 /* 18435 * We reached here, so at least one mapping must have been configured. 18436 * For next configuration base queue must be same. 18437 */ 18438 current_service_cos = soc_mem_field32_get(unit, SERVICE_COS_MAPm, &scm, SERVICE_COSf); 18439 if (current_service_cos != service_cos) { 18440 LOG_ERROR(BSL_LS_BCM_COMMON, 18441 (BSL_META_U(unit, 18442 "Error: Cannot satisfy service queue offset " 18443 "requirement for new map on port %d/VID %d, " 18444 "current offset: %d; required offset: %d\n"), 18445 port, vid, current_service_cos, service_cos)); 18446 return BCM_E_PARAM; 18447 } 18448 old_index = soc_mem_field32_get(unit, SERVICE_COS_MAPm, &scm, 18449 QUEUE_OFFSET_PROFILE_INDEXf); 18450 old_index *= 16; 18451 18452 BCM_IF_ERROR_RETURN 18453 (_bcm_offset_map_table_entry_get(unit, old_index, 16, entries)); 18454 rv = _bcm_offset_map_table_entry_delete(unit, old_index); 18455 if (!(rv == SOC_E_NOT_FOUND || rv == SOC_E_NONE)) { 18456 return rv; 18457 } 18458 } else { 18459 soc_mem_field32_set(unit, SERVICE_COS_MAPm, &scm, VALIDf, 1); 18460 } 18461 18462 for (i = 0; i < count; i++) { 18463 soc_mem_field32_set(unit, ING_QUEUE_OFFSET_MAPPING_TABLEm, 18464 &map_entries[priority[i]], QUEUE_OFFSETf, cosq[i]); 18465 } 18466 18467 BCM_IF_ERROR_RETURN 18468 (_bcm_offset_map_table_entry_add(unit, entries, 16, &new_index)); 18469 18470 soc_mem_field32_set(unit, SERVICE_COS_MAPm, &scm, QUEUE_OFFSET_PROFILE_INDEXf, 18471 new_index / 16); 18472 soc_mem_field32_set(unit, SERVICE_COS_MAPm, &scm, SERVICE_COSf, 18473 service_cos); 18474 BCM_IF_ERROR_RETURN( 18475 soc_mem_write(unit, SERVICE_COS_MAPm, MEM_BLOCK_ANY, (int)vid, &scm)); 18476 18477 return BCM_E_NONE; 18478 } 18479 18480 /* 18481 * Function: 18482 * bcm_kt2_cosq_service_classifier_get 18483 * Purpose: 18484 * Get info about an endpoint. 18485 * Parameters: 18486 * unit - (IN) Unit number. 18487 * classifier_id - (IN) Classifier ID 18488 * classifier - (OUT) Classifier info 18489 * Returns: 18490 * BCM_E_xxx 18491 */ 18492 int 18493 bcm_kt2_cosq_service_classifier_get( 18494 int unit, 18495 int classifier_id, 18496 bcm_cosq_classifier_t *classifier) 18497 { 18498 int val = 0; 18499 18500 sal_memset(classifier, 0, sizeof(bcm_cosq_classifier_t)); 18501 18502 val = _BCM_COSQ_CLASSIFIER_SERVICE_GET(classifier_id); 18503 18504 if (val > BCM_VLAN_MAX) { 18505 /* VFI classifier */ 18506 classifier->flags = BCM_COSQ_CLASSIFIER_VFI; 18507 classifier->vfi_index = val - BCM_VLAN_MAX - 1; 18508 } else { 18509 classifier->flags = BCM_COSQ_CLASSIFIER_VLAN; 18510 classifier->vlan = val; 18511 } 18512 return BCM_E_NONE; 18513 } 18514 18515 /* 18516 * Function: 18517 * bcm_kt2_cosq_service_map_get 18518 * Purpose: 18519 * Get the mapping from port, classifier, and multiple internal priorities 18520 * to multiple COS queues in a queue group. 18521 * Parameters: 18522 * unit - (IN) Unit number. 18523 * port - (IN) Local port ID 18524 * classifier_id - (IN) Classifier ID 18525 * queue_group - (OUT) Queue group 18526 * array_max - (IN) Size of priority_array and cosq_array 18527 * priority_array - (IN) Array of internal priorities 18528 * cosq_array - (OUT) Array of COS queues 18529 * array_count - (OUT) Size of cosq_array 18530 * Returns: 18531 * BCM_E_xxx 18532 */ 18533 int 18534 bcm_kt2_cosq_service_map_get( 18535 int unit, 18536 bcm_port_t port, 18537 int classifier_id, 18538 bcm_gport_t *queue_group, 18539 int array_max, 18540 bcm_cos_t *priority, 18541 bcm_cos_queue_t *cosq, 18542 int *array_count) 18543 { 18544 service_cos_map_entry_t scm; 18545 ing_queue_offset_mapping_table_entry_t map_entries[16]; 18546 void *entries[1]; 18547 int index; 18548 int vid; 18549 int valid_entry; 18550 int i; 18551 int cos_offset; 18552 uint32 uc_base = 0; 18553 uint32 rval = 0; 18554 18555 vid = _BCM_COSQ_CLASSIFIER_SERVICE_GET(classifier_id); 18556 18557 BCM_IF_ERROR_RETURN( 18558 soc_mem_read(unit, SERVICE_COS_MAPm, MEM_BLOCK_ANY, (int)vid, &scm)); 18559 18560 valid_entry = soc_mem_field32_get(unit, SERVICE_COS_MAPm, &scm, VALIDf); 18561 if (!valid_entry) { 18562 return BCM_E_CONFIG; /* service queue is not configured */ 18563 } 18564 18565 index = soc_mem_field32_get(unit, SERVICE_COS_MAPm, &scm, 18566 QUEUE_OFFSET_PROFILE_INDEXf); 18567 index *= 16; 18568 entries[0] = &map_entries; 18569 BCM_IF_ERROR_RETURN 18570 (_bcm_offset_map_table_entry_get(unit, index, 16, entries)); 18571 18572 cos_offset = soc_mem_field32_get(unit, SERVICE_COS_MAPm, 18573 &scm, SERVICE_COSf); 18574 18575 BCM_IF_ERROR_RETURN(READ_ING_COS_MODEr(unit, port, &rval)); 18576 uc_base = soc_reg_field_get(unit, ING_COS_MODEr, rval, SERVICE_BASE_QUEUE_NUMf); 18577 18578 bcm_kt2_cosq_subscriber_qid_set(unit, queue_group, cos_offset+uc_base); 18579 *queue_group |= (port << 16); 18580 *array_count = array_max > 16 ? 16 : 18581 array_max; 18582 18583 for (i = 0; i < *array_count; i++) { 18584 if (priority[i] >= 16) { 18585 return BCM_E_PARAM; 18586 } 18587 cosq[i] = soc_mem_field32_get(unit,ING_QUEUE_OFFSET_MAPPING_TABLEm, 18588 &map_entries[priority[i]], QUEUE_OFFSETf); 18589 } 18590 18591 return BCM_E_NONE; 18592 } 18593 18594 /* 18595 * Function: 18596 * bcm_kt2_cosq_service_map_clear 18597 * Purpose: 18598 * Clear the mapping from port, classifier, and internal priorities 18599 * to COS queues in a queue group. 18600 * Parameters: 18601 * unit - (IN) Unit number. 18602 * port - (IN) Local port ID 18603 * classifier_id - (IN) Classifier ID 18604 * Returns: 18605 * BCM_E_xxx 18606 */ 18607 int 18608 bcm_kt2_cosq_service_map_clear( 18609 int unit, 18610 bcm_gport_t port, 18611 int classifier_id) 18612 { 18613 int rv = BCM_E_NONE; 18614 service_cos_map_entry_t scm; 18615 int index; 18616 int vid; 18617 int valid_entry; 18618 18619 vid = _BCM_COSQ_CLASSIFIER_SERVICE_GET(classifier_id); 18620 18621 BCM_IF_ERROR_RETURN(soc_mem_read(unit, SERVICE_COS_MAPm, MEM_BLOCK_ANY, 18622 (int)vid, &scm)); 18623 18624 valid_entry = soc_mem_field32_get(unit, SERVICE_COS_MAPm, &scm, VALIDf); 18625 if (!valid_entry) { 18626 return BCM_E_NONE; /* service queue is already cleared */ 18627 } 18628 18629 index = soc_mem_field32_get(unit, SERVICE_COS_MAPm, &scm, 18630 QUEUE_OFFSET_PROFILE_INDEXf); 18631 index *= 16; 18632 18633 /* delete the profile */ 18634 rv = _bcm_offset_map_table_entry_delete(unit, index); 18635 if (!(rv == SOC_E_NOT_FOUND || rv == SOC_E_NONE)) { 18636 return rv; 18637 } 18638 18639 sal_memset(&scm,0, sizeof(service_cos_map_entry_t)); 18640 18641 /* Write back updated buffer. */ 18642 BCM_IF_ERROR_RETURN(soc_mem_write(unit, SERVICE_COS_MAPm, MEM_BLOCK_ALL, 18643 (int)vid, &scm)); 18644 return BCM_E_NONE; 18645 } 18646 /* 18647 * Function: 18648 * _bcm_kt2_cosq_gport_dmvoq_config_set 18649 * Purpose: 18650 * Setting SOURCE_MODMAP , FC table and BASEINDEX table 18651 * appropriately as per the architecture 18652 * Parameters: 18653 * unit - (IN) Unit number. 18654 * gport - (IN) gport identifier 18655 * cos - (IN) cos value 18656 * fabric_modid - (IN) Fabric Mod ID 18657 * dest_modid - (IN) Destination Mod ID 18658 * fabric_port - (IN) Fabric port ID 18659 * Returns: 18660 * BCM_E_xxx 18661 */ 18662 STATIC int 18663 _bcm_kt2_cosq_gport_dmvoq_config_set(int unit, bcm_gport_t gport, 18664 bcm_cos_queue_t cosq, 18665 bcm_module_t dest_modid, 18666 bcm_module_t fabric_modid, 18667 bcm_port_t fabric_port) 18668 { 18669 int intf_index, rv; 18670 _bcm_kt2_cosq_node_t *node; 18671 _bcm_kt2_cosq_node_t *base_node = NULL; 18672 bcm_port_t local_port; 18673 mmu_intfi_base_index_tbl_entry_t base_tbl_entry; 18674 uint32 index; 18675 uint32 val; 18676 int stack_port; 18677 uint32 modport_map_index; 18678 modport_map_sw_entry_t sw_entry; 18679 ing_queue_map_entry_t ing_queue_entry; 18680 ing_queue_offset_mapping_table_entry_t map_entries[16]; 18681 void *entries[1]; 18682 int map_offset = 0, fabric_port_count, port; 18683 int count = 0, cng_offset; 18684 mmu_intfi_offset_map_tbl_entry_t offset_map_tbl_entry; 18685 _bcm_kt2_mmu_info_t *mmu_info; 18686 _bcm_kt2_cosq_node_t *node_base; 18687 int enable, base_queue = 0; 18688 int istrunk; 18689 entries[0] = &map_entries; 18690 mmu_info = _bcm_kt2_mmu_info[unit]; 18691 18692 if (fabric_modid >= 64) { 18693 return BCM_E_PARAM; 18694 } 18695 18696 if (dest_modid >= 256) { 18697 return BCM_E_PARAM; 18698 } 18699 18700 BCM_IF_ERROR_RETURN 18701 (_bcm_kt2_cosq_node_get(unit, gport, NULL ,&local_port, NULL, &node)); 18702 18703 if (!node) { 18704 return BCM_E_NOT_FOUND; 18705 } 18706 if (node->level != _BCM_KT2_COSQ_NODE_LEVEL_L2) { 18707 return BCM_E_PARAM; 18708 } 18709 18710 BCM_IF_ERROR_RETURN(_bcm_kt2_voq_base_node_get( 18711 unit, dest_modid, fabric_modid, &base_node)); 18712 if (base_node == NULL) { 18713 base_node = node ; 18714 } 18715 intf_index = _bcm_kt2_cosq_source_intf_set(unit, fabric_modid, 18716 0, _BCM_KT2_COSQ_DMVOQ); 18717 18718 if (intf_index < 0) { 18719 return BCM_E_RESOURCE; 18720 } 18721 if (SOC_IS_METROLITE(unit)) { 18722 intf_index = 0; 18723 } else if (SOC_IS_SABER2(unit)) { 18724 if (intf_index > 1) { 18725 intf_index = 0; 18726 } 18727 } else { 18728 if (intf_index > 3) { 18729 intf_index = 0; 18730 } 18731 } 18732 18733 BCM_PBMP_COUNT(base_node->fabric_pbmp, fabric_port_count); 18734 18735 if (fabric_port_count == 0) { 18736 map_offset = mmu_info->curr_merger_index[intf_index]; 18737 if (map_offset >= soc_mem_index_count(unit, MMU_INTFI_MERGE_ST_TBLm)) { 18738 return BCM_E_RESOURCE; 18739 } 18740 } else { 18741 BCM_PBMP_ITER(base_node->fabric_pbmp, port) { 18742 BCM_IF_ERROR_RETURN(soc_mem_read(unit, MMU_INTFI_OFFSET_MAP_TBLm, 18743 MEM_BLOCK_ALL, 18744 port + (intf_index * 64), &offset_map_tbl_entry)); 18745 map_offset = soc_mem_field32_get(unit, MMU_INTFI_OFFSET_MAP_TBLm, 18746 &offset_map_tbl_entry, 18747 MAP_OFFSETf); 18748 break; 18749 } 18750 } 18751 18752 /* clean up fabric pbmp code if fabric mod_id and dest mod id are different 18753 if the mod id are different then we need to update the pbmp else it will 18754 be appended as in case of trunk. 18755 */ 18756 if ((base_node->remote_modid != dest_modid) || 18757 (base_node->fabric_modid != fabric_modid)) { 18758 if (node->hw_index % 8 == 0) { 18759 BCM_PBMP_CLEAR(base_node->fabric_pbmp); 18760 18761 } 18762 } 18763 if (!BCM_PBMP_MEMBER(base_node->fabric_pbmp, fabric_port)) { 18764 if (map_offset == mmu_info->curr_merger_index[intf_index]) { 18765 mmu_info->curr_merger_index[intf_index]++; 18766 } 18767 18768 BCM_PBMP_PORT_ADD (base_node->fabric_pbmp, fabric_port); 18769 BCM_PBMP_COUNT(base_node->fabric_pbmp, fabric_port_count); 18770 BCM_PBMP_ITER(base_node->fabric_pbmp, port) { 18771 count++; 18772 BCM_IF_ERROR_RETURN(soc_mem_read(unit, MMU_INTFI_OFFSET_MAP_TBLm, 18773 MEM_BLOCK_ALL, 18774 port + (intf_index * 64), &offset_map_tbl_entry)); 18775 soc_mem_field32_set(unit, MMU_INTFI_OFFSET_MAP_TBLm, 18776 &offset_map_tbl_entry, 18777 MAP_OFFSETf, map_offset); 18778 soc_mem_field32_set(unit, MMU_INTFI_OFFSET_MAP_TBLm, 18779 &offset_map_tbl_entry, 18780 LASTf, count < fabric_port_count ? 0 : 1 ); 18781 BCM_IF_ERROR_RETURN(soc_mem_write(unit, MMU_INTFI_OFFSET_MAP_TBLm, 18782 MEM_BLOCK_ALL, 18783 port + (intf_index * 64), &offset_map_tbl_entry)); 18784 } 18785 } 18786 18787 18788 18789 if (node->hw_index % 8 == 0) { 18790 18791 node->remote_modid = dest_modid; 18792 node->fabric_modid = fabric_modid; 18793 node_base = mmu_info->queue_node; 18794 count = 0; 18795 SOC_IF_ERROR_RETURN 18796 (READ_MODPORT_MAP_SELr(unit, local_port, &val)); 18797 index = soc_reg_field_get(unit, MODPORT_MAP_SELr, val, 18798 MODPORT_MAP_INDEX_UPPERf); 18799 if (SOC_IS_METROLITE(unit)) { 18800 modport_map_index = (index * 64) + dest_modid; 18801 } else { 18802 modport_map_index = (index * 256) + dest_modid; 18803 } 18804 18805 soc_mem_lock(unit, MODPORT_MAP_SWm); 18806 rv = soc_mem_read(unit, MODPORT_MAP_SWm, MEM_BLOCK_ANY, modport_map_index, 18807 &sw_entry); 18808 istrunk = soc_mem_field32_get(unit, MODPORT_MAP_SWm, &sw_entry, 18809 ISTRUNK0f); 18810 soc_mem_unlock(unit, MODPORT_MAP_SWm); 18811 for(index = mmu_info->base_dmvoq_queue ; 18812 index < mmu_info->num_queues; index++) { 18813 if ((node_base[index].remote_modid == dest_modid) && 18814 ((node_base[index].fabric_modid == fabric_modid) || (istrunk))) { 18815 count++; 18816 BCM_IF_ERROR_RETURN 18817 (_bcm_kt2_cosq_node_get(unit, node_base[index].gport, 18818 NULL ,&port, NULL, NULL)); 18819 SOC_IF_ERROR_RETURN(READ_ING_COS_MODEr(unit, port, &val)); 18820 18821 base_queue = soc_reg_field_get(unit, ING_COS_MODEr, val, BASE_QUEUE_NUMf); 18822 18823 } 18824 } 18825 if(count == 1) { 18826 SOC_IF_ERROR_RETURN 18827 (READ_MODPORT_MAP_SELr(unit, local_port, &val)); 18828 18829 index = soc_reg_field_get(unit, MODPORT_MAP_SELr, val, 18830 MODPORT_MAP_INDEX_UPPERf); 18831 18832 if (SOC_IS_METROLITE(unit)) { 18833 modport_map_index = (index * 64) + dest_modid; 18834 } else { 18835 modport_map_index = (index * 256) + dest_modid; 18836 } 18837 18838 soc_mem_lock(unit, MODPORT_MAP_SWm); 18839 rv = soc_mem_read(unit, MODPORT_MAP_SWm, MEM_BLOCK_ANY, modport_map_index, 18840 &sw_entry); 18841 if (SOC_SUCCESS(rv)) { 18842 enable = soc_mem_field32_get(unit, MODPORT_MAP_SWm, &sw_entry, 18843 ENABLE0f); 18844 if (!enable) { 18845 #ifdef BCM_METROLITE_SUPPORT 18846 if(SOC_IS_METROLITE(unit)) { 18847 stack_port = ((local_port << 5) | local_port); 18848 } else 18849 #endif 18850 { 18851 stack_port = ((local_port << (SOC_IS_SABER2(unit)? 7: 8)) | local_port); 18852 } 18853 soc_mem_field32_set(unit, MODPORT_MAP_SWm, &sw_entry, DEST0f, 18854 stack_port); 18855 soc_mem_field32_set(unit, MODPORT_MAP_SWm, &sw_entry, ISTRUNK0f,0); 18856 soc_mem_field32_set(unit, MODPORT_MAP_SWm, &sw_entry, ADD_DESTINATION_PORTf, 18857 0); 18858 soc_mem_field32_set(unit, MODPORT_MAP_SWm, &sw_entry, ENABLE0f, 1); 18859 } 18860 soc_mem_field32_set(unit, MODPORT_MAP_SWm, &sw_entry, PER_MODID_QUEUEING_ENABLEf, 18861 1); 18862 soc_mem_field32_set(unit, MODPORT_MAP_SWm, &sw_entry, QUEUE_MAP_POINTERf, 18863 node->hw_index); 18864 rv = soc_mem_write(unit, MODPORT_MAP_SWm, MEM_BLOCK_ALL, modport_map_index, 18865 &sw_entry); 18866 } 18867 soc_mem_unlock(unit, MODPORT_MAP_SWm); 18868 18869 sal_memset(map_entries, 0, sizeof(map_entries)); 18870 /* Hardcoding the ING_QUEUE_OFFSET_MAPPING_TABLE */ 18871 for (index = 0; index < 16; index++) { 18872 soc_mem_field32_set(unit, ING_QUEUE_OFFSET_MAPPING_TABLEm, 18873 &map_entries[index], QUEUE_OFFSETf, index > 7 ? 7 : index); 18874 } 18875 BCM_IF_ERROR_RETURN 18876 (_bcm_offset_map_table_entry_add(unit, entries, 16, &index)); 18877 18878 sal_memset(&ing_queue_entry, 0, sizeof(ing_queue_map_entry_t)); 18879 soc_mem_field32_set(unit, ING_QUEUE_MAPm, 18880 &ing_queue_entry, QUEUE_SET_BASEf, 18881 node->hw_index - base_queue); 18882 soc_mem_field32_set(unit, ING_QUEUE_MAPm, &ing_queue_entry, 18883 QUEUE_OFFSET_PROFILE_INDEXf, index/16); 18884 soc_mem_field32_set(unit, ING_QUEUE_MAPm, &ing_queue_entry, 18885 ADD_EGRESS_PORT_BASE_QUEUEf, 1); 18886 BCM_IF_ERROR_RETURN(BCM_XGS3_MEM_WRITE(unit, ING_QUEUE_MAPm, 18887 node->hw_index, &ing_queue_entry)); 18888 } 18889 18890 /* 18891 * SRC_INTF and MMU_INTFI_BASE_INDEX_TBL is mapped one to one, 18892 * so writing the base index at same index where SRC_INTF is written 18893 */ 18894 18895 cng_offset = intf_index * 64 ; 18896 18897 BCM_IF_ERROR_RETURN 18898 (soc_mem_read(unit, MMU_INTFI_BASE_INDEX_TBLm, 18899 MEM_BLOCK_ALL, intf_index, &base_tbl_entry)); 18900 soc_mem_field32_set(unit, MMU_INTFI_BASE_INDEX_TBLm, &base_tbl_entry, 18901 BASE_ADDRf, cng_offset); 18902 soc_mem_field32_set(unit, MMU_INTFI_BASE_INDEX_TBLm, &base_tbl_entry, 18903 ENf, (node->level - 3 )); 18904 18905 BCM_IF_ERROR_RETURN(soc_mem_write(unit, MMU_INTFI_BASE_INDEX_TBLm, 18906 MEM_BLOCK_ALL, intf_index, &base_tbl_entry)); 18907 18908 /* set the mapping from congestion bits in flow control table 18909 * to corresponding hw_index */ 18910 BCM_IF_ERROR_RETURN(_bcm_kt2_cosq_map_fc_status_to_node(unit, 18911 _BCM_KT2_COSQ_FC_VOQFC, 18912 node->hw_index, (node->level - 2), cng_offset + map_offset)); 18913 18914 18915 } 18916 return BCM_E_NONE; 18917 } 18918 18919 /* 18920 * Function: 18921 * _bcm_kt2_cosq_gport_e2ecc_coe_config_set 18922 * Purpose: 18923 * Setting SOURCE_MODMAP, FC table and BASEINDEX table 18924 * appropriately as per the architecture 18925 * Parameters: 18926 * unit - (IN) Unit number. 18927 * gport - (IN) gport identifier 18928 * cos - (IN) cos value 18929 * Returns: 18930 * BCM_E_xxx 18931 */ 18932 STATIC int 18933 _bcm_kt2_cosq_gport_e2ecc_coe_config_set(int unit, bcm_gport_t gport) 18934 { 18935 soc_info_t *si; 18936 int intf_index; 18937 _bcm_kt2_cosq_node_t *node; 18938 bcm_port_t local_port; 18939 bcm_port_t subport; 18940 int subport_start = 0; 18941 int subport_end = 0; 18942 mmu_intfi_base_index_tbl_entry_t base_tbl_entry; 18943 int cng_offset; 18944 int subport_offset = 0; 18945 uint32 regval; 18946 int num_subports = 0; 18947 #if defined BCM_METROLITE_SUPPORT 18948 int pp_port = 0; 18949 #endif 18950 18951 si = &SOC_INFO(unit); 18952 18953 BCM_IF_ERROR_RETURN 18954 (_bcm_kt2_cosq_node_get(unit, gport, NULL , 18955 &subport, NULL, &node)); 18956 18957 if (!node) { 18958 return BCM_E_NOT_FOUND; 18959 } 18960 if (node->level != _BCM_KT2_COSQ_NODE_LEVEL_L2) { 18961 return BCM_E_PARAM; 18962 } 18963 18964 local_port = node->local_port; 18965 18966 /* Subport base for the COE port */ 18967 subport_start = si->port_subport_base[local_port]; 18968 subport_end = si->port_subport_base[local_port] + 18969 si->port_num_subport[local_port]; 18970 18971 /* number of subports on the COE port 18972 * indicating maximum number of FC bytes 18973 * that can be received on a COE 18974 * port 18975 */ 18976 num_subports = si->port_num_subport[local_port]; 18977 18978 if (num_subports == 0) { 18979 return BCM_E_INIT; 18980 } 18981 18982 /* Maximum of 64 FC bytes are supported in E2ECC 18983 * message. Hence limiting the number of subports 18984 * to 64 when more number of subports configured 18985 * on a COE port. 18986 */ 18987 num_subports = ((num_subports > 64) ? 64 : num_subports); 18988 #if defined BCM_METROLITE_SUPPORT 18989 if (soc_feature(unit, soc_feature_discontinuous_pp_port)) { 18990 if (!_SOC_IS_PP_PORT_LINKPHY_SUBTAG(unit, subport)) { 18991 return BCM_E_INIT; 18992 } 18993 SOC_PBMP_ITER(SOC_PORT_PP_BITMAP(unit, local_port), pp_port) { 18994 if (subport != pp_port) { 18995 subport_offset++; 18996 continue; 18997 } else { 18998 break; 18999 } 19000 } 19001 } else 19002 #endif 19003 { 19004 subport_offset = subport - subport_start; 19005 if ((subport < subport_start) || 19006 (subport > subport_end)) { 19007 return BCM_E_INIT; 19008 } 19009 } 19010 if (node->hw_index % 8 == 0) { 19011 19012 intf_index = _bcm_kt2_cosq_source_intf_set(unit, 0, 19013 local_port, _BCM_KT2_COSQ_E2ECC_COE); 19014 if (intf_index < 0) { 19015 return BCM_E_RESOURCE; 19016 } 19017 19018 /* 19019 * SRC_INTF and MMU_INTFI_BASE_INDEX_TBL is mapped one to one, 19020 * so writing the base index at same index where SRC_INTF is written 19021 */ 19022 19023 cng_offset = (intf_index * num_subports) ; 19024 /* set the congestion state bytes max to number of subports on a port 19025 * as max num subports FC bytes can be received for for src_intf 19026 */ 19027 soc_reg_field_set(unit, CONGESTION_STATE_BYTESr, ®val, 19028 DATAf, num_subports); 19029 SOC_IF_ERROR_RETURN(WRITE_CONGESTION_STATE_BYTESr(unit, 19030 intf_index, regval)); 19031 19032 BCM_IF_ERROR_RETURN 19033 (soc_mem_read(unit, MMU_INTFI_BASE_INDEX_TBLm, 19034 MEM_BLOCK_ALL, intf_index, &base_tbl_entry)); 19035 soc_mem_field32_set(unit, MMU_INTFI_BASE_INDEX_TBLm, &base_tbl_entry, 19036 BASE_ADDRf, cng_offset); 19037 /* set Enf - 2 for level 2 */ 19038 soc_mem_field32_set(unit, MMU_INTFI_BASE_INDEX_TBLm, &base_tbl_entry, 19039 ENf, (node->level - 3 )); 19040 19041 BCM_IF_ERROR_RETURN(soc_mem_write(unit, MMU_INTFI_BASE_INDEX_TBLm, 19042 MEM_BLOCK_ALL, intf_index, &base_tbl_entry)); 19043 19044 /* set the mapping from congestion bits in flow control table 19045 * to corresponding hw_index */ 19046 BCM_IF_ERROR_RETURN(_bcm_kt2_cosq_map_fc_status_to_node(unit, 19047 _BCM_KT2_COSQ_FC_E2ECC_COE, 19048 node->hw_index, (node->level - 2), 19049 (cng_offset + (subport_offset)))); 19050 19051 19052 } 19053 return BCM_E_NONE; 19054 } 19055 19056 STATIC int 19057 _bcm_kt2_cosq_gport_dpvoq_config_set(int unit, bcm_gport_t gport, 19058 bcm_cos_queue_t cosq, 19059 bcm_module_t dest_modid, 19060 bcm_port_t dest_port) 19061 { 19062 int intf_index, rv; 19063 _bcm_kt2_cosq_node_t *node; 19064 bcm_port_t local_port; 19065 mmu_intfi_base_index_tbl_entry_t base_tbl_entry; 19066 uint32 index; 19067 uint32 val; 19068 int stack_port; 19069 uint32 modport_map_index; 19070 modport_map_sw_entry_t sw_entry; 19071 ing_queue_map_entry_t ing_queue_entry; 19072 ing_queue_offset_mapping_table_entry_t map_entries[16]; 19073 physical_port_base_queue_entry_t phy_port_entry; 19074 void *entries[1]; 19075 int count = 0, cng_offset; 19076 _bcm_kt2_mmu_info_t *mmu_info; 19077 _bcm_kt2_cosq_node_t *node_base; 19078 int enable, base_queue; 19079 int phy_base_index = 0, offset = 0 , hw_index = 0; 19080 int port; 19081 entries[0] = &map_entries; 19082 mmu_info = _bcm_kt2_mmu_info[unit]; 19083 19084 if (dest_modid >= 64) { 19085 return BCM_E_PARAM; 19086 } 19087 19088 BCM_IF_ERROR_RETURN 19089 (_bcm_kt2_cosq_node_get(unit, gport, NULL ,&local_port, NULL, &node)); 19090 19091 if (!node) { 19092 return BCM_E_NOT_FOUND; 19093 } 19094 if (node->level != _BCM_KT2_COSQ_NODE_LEVEL_L2) { 19095 return BCM_E_PARAM; 19096 } 19097 19098 if (node->hw_index % 8 == 0) { 19099 19100 node->remote_modid = dest_modid; 19101 node_base = mmu_info->queue_node; 19102 count = 0; 19103 for(index = mmu_info->base_dmvoq_queue ; 19104 index < mmu_info->num_queues ; index++) { 19105 if (node_base[index].remote_modid == dest_modid) { 19106 count++; 19107 BCM_IF_ERROR_RETURN 19108 (_bcm_kt2_cosq_node_get(unit, node_base[index].gport, 19109 NULL ,&port, NULL, NULL)); 19110 SOC_IF_ERROR_RETURN(READ_ING_COS_MODEr(unit, port, &val)); 19111 base_queue = soc_reg_field_get(unit, ING_COS_MODEr, val, BASE_QUEUE_NUMf); 19112 19113 SOC_IF_ERROR_RETURN (soc_mem_read(unit, PHYSICAL_PORT_BASE_QUEUEm, 19114 MEM_BLOCK_ANY, port, 19115 &phy_port_entry)); 19116 phy_base_index = soc_mem_field32_get(unit, PHYSICAL_PORT_BASE_QUEUEm, 19117 &phy_port_entry, BASE_QUEUE_NUMBERf); 19118 if (!soc_mem_field32_get(unit, PHYSICAL_PORT_BASE_QUEUEm, 19119 &phy_port_entry, BASE_QUEUE_NUMBERf)) { 19120 soc_mem_field32_set(unit, PHYSICAL_PORT_BASE_QUEUEm, 19121 &phy_port_entry, BASE_QUEUE_NUMBERf, 19122 (node_base[index].hw_index - base_queue) ); 19123 SOC_IF_ERROR_RETURN (soc_mem_write(unit, PHYSICAL_PORT_BASE_QUEUEm, 19124 MEM_BLOCK_ALL, port, 19125 &phy_port_entry)); 19126 offset = 0; 19127 } else { 19128 if ( phy_base_index == node_base[index].hw_index - base_queue) { 19129 if ( port == local_port ) { 19130 offset = node->hw_index - node_base[index].hw_index; 19131 } 19132 } 19133 } 19134 } 19135 } 19136 SOC_IF_ERROR_RETURN 19137 (READ_MODPORT_MAP_SELr(unit, local_port, &val)); 19138 19139 index = soc_reg_field_get(unit, MODPORT_MAP_SELr, val, 19140 MODPORT_MAP_INDEX_UPPERf); 19141 19142 modport_map_index = (index * 256) + dest_modid; 19143 19144 soc_mem_lock(unit, MODPORT_MAP_SWm); 19145 rv = soc_mem_read(unit, MODPORT_MAP_SWm, MEM_BLOCK_ANY, modport_map_index, 19146 &sw_entry); 19147 19148 if(count == 1) { 19149 if (SOC_SUCCESS(rv)) { 19150 enable = soc_mem_field32_get(unit, MODPORT_MAP_SWm, &sw_entry, 19151 ENABLE0f); 19152 if (!enable) { 19153 stack_port = ((local_port << 8) | local_port); 19154 soc_mem_field32_set(unit, MODPORT_MAP_SWm, &sw_entry, DEST0f, 19155 stack_port); 19156 soc_mem_field32_set(unit, MODPORT_MAP_SWm, &sw_entry, ISTRUNK0f,0); 19157 soc_mem_field32_set(unit, MODPORT_MAP_SWm, &sw_entry, ADD_DESTINATION_PORTf, 19158 0); 19159 soc_mem_field32_set(unit, MODPORT_MAP_SWm, &sw_entry, ENABLE0f, 1); 19160 } 19161 soc_mem_field32_set(unit, MODPORT_MAP_SWm, &sw_entry, ADD_DESTINATION_PORTf, 19162 1); 19163 soc_mem_field32_set(unit, MODPORT_MAP_SWm, &sw_entry, PER_MODID_QUEUEING_ENABLEf, 19164 1); 19165 soc_mem_field32_set(unit, MODPORT_MAP_SWm, &sw_entry, QUEUE_MAP_POINTERf, 19166 node->hw_index); 19167 rv = soc_mem_write(unit, MODPORT_MAP_SWm, MEM_BLOCK_ALL, modport_map_index, 19168 &sw_entry); 19169 } 19170 soc_mem_unlock(unit, MODPORT_MAP_SWm); 19171 19172 sal_memset(map_entries, 0, sizeof(map_entries)); 19173 /* Hardcoding the ING_QUEUE_OFFSET_MAPPING_TABLE */ 19174 for (index = 0; index < 16; index++) { 19175 soc_mem_field32_set(unit, ING_QUEUE_OFFSET_MAPPING_TABLEm, 19176 &map_entries[index], QUEUE_OFFSETf, index > 7 ? 7 : index); 19177 } 19178 BCM_IF_ERROR_RETURN 19179 (_bcm_offset_map_table_entry_add(unit, entries, 16, &index)); 19180 SOC_IF_ERROR_RETURN(READ_ING_COS_MODEr(unit, local_port, &val)); 19181 base_queue = soc_reg_field_get(unit, ING_COS_MODEr, val, BASE_QUEUE_NUMf); 19182 19183 for (port = 0; port < KT2_LPBK_PORT; port++) { 19184 sal_memset(&ing_queue_entry, 0, sizeof(ing_queue_map_entry_t)); 19185 soc_mem_field32_set(unit, ING_QUEUE_MAPm, 19186 &ing_queue_entry, QUEUE_SET_BASEf, base_queue); 19187 soc_mem_field32_set(unit, ING_QUEUE_MAPm, &ing_queue_entry, 19188 QUEUE_OFFSET_PROFILE_INDEXf, index/16); 19189 soc_mem_field32_set(unit, ING_QUEUE_MAPm, &ing_queue_entry, 19190 ADD_EGRESS_PORT_BASE_QUEUEf, 0); 19191 BCM_IF_ERROR_RETURN(BCM_XGS3_MEM_WRITE(unit, ING_QUEUE_MAPm, 19192 node->hw_index + port , &ing_queue_entry)); 19193 } 19194 19195 sal_memset(&ing_queue_entry, 0, sizeof(ing_queue_map_entry_t)); 19196 soc_mem_field32_set(unit, ING_QUEUE_MAPm, 19197 &ing_queue_entry, QUEUE_SET_BASEf, offset); 19198 soc_mem_field32_set(unit, ING_QUEUE_MAPm, &ing_queue_entry, 19199 QUEUE_OFFSET_PROFILE_INDEXf, index/16); 19200 soc_mem_field32_set(unit, ING_QUEUE_MAPm, &ing_queue_entry, 19201 ADD_EGRESS_PORT_BASE_QUEUEf, 1); 19202 BCM_IF_ERROR_RETURN(BCM_XGS3_MEM_WRITE(unit, ING_QUEUE_MAPm, 19203 node->hw_index + dest_port, &ing_queue_entry)); 19204 19205 } else if (offset > 0) { 19206 if (SOC_SUCCESS(rv)) { 19207 hw_index = soc_mem_field32_get(unit, MODPORT_MAP_SWm, &sw_entry, 19208 QUEUE_MAP_POINTERf); 19209 soc_mem_unlock(unit, MODPORT_MAP_SWm); 19210 sal_memset(&ing_queue_entry, 0, sizeof(ing_queue_map_entry_t)); 19211 rv = BCM_XGS3_MEM_READ(unit, ING_QUEUE_MAPm, 19212 hw_index, &ing_queue_entry); 19213 if (!SOC_SUCCESS(rv)) { 19214 return rv; 19215 } 19216 soc_mem_field32_set(unit, ING_QUEUE_MAPm, 19217 &ing_queue_entry, QUEUE_SET_BASEf, offset); 19218 soc_mem_field32_set(unit, ING_QUEUE_MAPm, &ing_queue_entry, 19219 ADD_EGRESS_PORT_BASE_QUEUEf, 1); 19220 rv = BCM_XGS3_MEM_WRITE(unit, ING_QUEUE_MAPm, 19221 hw_index + dest_port, &ing_queue_entry); 19222 if (!SOC_SUCCESS(rv)) { 19223 return rv; 19224 } 19225 19226 } 19227 } else { 19228 soc_mem_unlock(unit, MODPORT_MAP_SWm); 19229 } 19230 19231 intf_index = _bcm_kt2_cosq_source_intf_set(unit, dest_modid, 19232 0, _BCM_KT2_COSQ_DPVOQ); 19233 if (intf_index < 0) { 19234 return BCM_E_RESOURCE; 19235 } 19236 19237 /* 19238 * SRC_INTF and MMU_INTFI_BASE_INDEX_TBL is mapped one to one, 19239 * so writing the base index at same index where SRC_INTF is written 19240 */ 19241 19242 cng_offset = intf_index * 64 ; 19243 19244 BCM_IF_ERROR_RETURN 19245 (soc_mem_read(unit, MMU_INTFI_BASE_INDEX_TBLm, 19246 MEM_BLOCK_ALL, intf_index, &base_tbl_entry)); 19247 soc_mem_field32_set(unit, MMU_INTFI_BASE_INDEX_TBLm, &base_tbl_entry, 19248 BASE_ADDRf, cng_offset); 19249 soc_mem_field32_set(unit, MMU_INTFI_BASE_INDEX_TBLm, &base_tbl_entry, 19250 ENf, (node->level - 3 )); 19251 19252 BCM_IF_ERROR_RETURN(soc_mem_write(unit, MMU_INTFI_BASE_INDEX_TBLm, 19253 MEM_BLOCK_ALL, intf_index, &base_tbl_entry)); 19254 19255 /* set the mapping from congestion bits in flow control table 19256 * to corresponding hw_index */ 19257 BCM_IF_ERROR_RETURN(_bcm_kt2_cosq_map_fc_status_to_node(unit, 19258 _BCM_KT2_COSQ_FC_VOQFC, 19259 node->hw_index , (node->level - 2), cng_offset + dest_port)); 19260 19261 19262 } 19263 return BCM_E_NONE; 19264 } 19265 /* 19266 * Function: 19267 * bcm_kt2_cosq_gport_congestion_config_set 19268 * Purpose: 19269 * Setting the dmvoq/dpvoq related configuration 19270 * Parameters: 19271 * unit - (IN) Unit number. 19272 * gport - (IN) gport identifier 19273 * cos - (IN) cos value 19274 * config - (IN) congestion data 19275 * Returns: 19276 * BCM_E_xxx 19277 */ 19278 19279 int bcm_kt2_cosq_gport_congestion_config_set(int unit, bcm_gport_t gport, 19280 bcm_cos_queue_t cosq, 19281 bcm_cosq_congestion_info_t *config) 19282 { 19283 /* config is used by DMVOQ/DPVOQ 19284 * E2ECC COE FC will ignore the config 19285 * and cos parameters. 19286 */ 19287 19288 bcm_port_t subport; 19289 _bcm_kt2_cosq_node_t *node; 19290 int max_subport = SOC_INFO(unit).pp_port_index_max; 19291 BCM_IF_ERROR_RETURN 19292 (_bcm_kt2_cosq_node_get(unit, gport, NULL , &subport, NULL, &node)); 19293 19294 /* E2ECC on COE -queue added to subport */ 19295 if (soc_feature(unit, soc_feature_subtag_coe) && 19296 (_bcm_is_port_linkphy_subport(unit, gport, -1) && 19297 (subport <= max_subport))) { 19298 if (!IS_SUBTAG_PORT(unit, node->local_port)) { 19299 return BCM_E_PORT; 19300 } 19301 return _bcm_kt2_cosq_gport_e2ecc_coe_config_set(unit, gport); 19302 } 19303 19304 if (!config) { 19305 return BCM_E_PARAM; 19306 } 19307 /* when user specify dest_modid, fabric_port, fabric_modid 19308 then we consider as DMVOQ */ 19309 if ((config->dest_modid != -1) && 19310 (config->fabric_port != -1) && 19311 (config->fabric_modid != -1)) { 19312 return _bcm_kt2_cosq_gport_dmvoq_config_set(unit, gport, cosq, 19313 config->dest_modid, 19314 config->fabric_modid, 19315 config->fabric_port); 19316 } 19317 /* when user specify dest_modid, dest_port with fabric_port, fabric_modid as -1 19318 then we consider as DPVOQ */ 19319 19320 if ((config->dest_modid != -1) && 19321 (config->dest_port != -1)) { 19322 return _bcm_kt2_cosq_gport_dpvoq_config_set(unit, gport, cosq, 19323 config->dest_modid, 19324 config->dest_port); 19325 } 19326 return BCM_E_PARAM; 19327 } 19328 19329 /* 19330 * Function: 19331 * bcm_kt2_cosq_gport_congestion_config_set 19332 * Purpose: 19333 * Setting the dmvoq/dpvoq related configuration 19334 * Parameters: 19335 * unit - (IN) Unit number. 19336 * gport - (IN) gport identifier 19337 * cos - (IN) cos value 19338 * config - (IN) congestion data 19339 * Returns: 19340 * BCM_E_xxx 19341 */ 19342 19343 19344 int bcm_kt2_cosq_gport_congestion_config_get(int unit, bcm_gport_t port, 19345 bcm_cos_queue_t cosq, 19346 bcm_cosq_congestion_info_t *config) 19347 { 19348 _bcm_kt2_cosq_node_t *node; 19349 _bcm_kt2_mmu_info_t *mmu_info; 19350 int fabric_port = 0; 19351 int base_index = 0; 19352 mmu_info = _bcm_kt2_mmu_info[unit]; 19353 19354 if (!config) { 19355 return BCM_E_PARAM; 19356 } 19357 19358 BCM_IF_ERROR_RETURN 19359 (_bcm_kt2_cosq_node_get(unit, port, NULL, NULL, NULL, &node)); 19360 19361 19362 if (!node) { 19363 return BCM_E_NOT_FOUND; 19364 } 19365 19366 if (node->level != _BCM_KT2_COSQ_NODE_LEVEL_L2) { 19367 return BCM_E_PARAM; 19368 } 19369 19370 19371 BCM_PBMP_ITER(node->fabric_pbmp, fabric_port) { 19372 config->fabric_port = fabric_port; 19373 break; 19374 } 19375 if ( node->hw_index % 8 != 0){ 19376 /*base hw_index */ 19377 base_index = node->hw_index - (node->hw_index % 8); 19378 bcm_kt2_sw_hw_queue(unit, &base_index); 19379 node = &(mmu_info->queue_node[base_index]); 19380 } 19381 19382 config->dest_modid = node->remote_modid; 19383 config->dest_port = node->remote_port; 19384 config->fabric_modid = node->fabric_modid; 19385 19386 19387 return BCM_E_NONE; 19388 } 19389 19390 19391 /* 19392 * Function: 19393 * _bcm_kt2_cosq_mapping_set 19394 * Purpose: 19395 * Set COS queue for the specified priority of an ingress port 19396 * Parameters: 19397 * unit - (IN) unit number 19398 * ing_port - (IN) ingress port 19399 * gport - (IN) queue group GPORT identifier 19400 * priority - (IN) priority value to map 19401 * flags - (IN) BCM_COSQ_GPORT_XXX_QUEUE_GROUP 19402 * gport - (IN) queue group GPORT identifier 19403 * cosq - (IN) COS queue number 19404 * Returns: 19405 * BCM_E_XXX 19406 */ 19407 STATIC int 19408 _bcm_kt2_cosq_mapping_set(int unit, bcm_port_t ing_port, bcm_cos_t priority, 19409 uint32 flags, bcm_gport_t gport, bcm_cos_queue_t cosq) 19410 { 19411 _bcm_kt2_cosq_node_t *node; 19412 bcm_port_t local_port; 19413 ing_queue_map_entry_t ing_queue_entry; 19414 ing_queue_offset_mapping_table_entry_t map_entries[16]; 19415 void *entries[1]; 19416 int rv; 19417 uint32 old_index = 0; 19418 uint32 new_index = 0; 19419 19420 if (priority < 0 || priority >= 16) { 19421 return BCM_E_PARAM; 19422 } 19423 19424 if (gport == -1) { 19425 return BCM_E_UNAVAIL; 19426 } 19427 19428 switch (flags) { 19429 case BCM_COSQ_GPORT_DESTMOD_UCAST_QUEUE_GROUP: 19430 BCM_IF_ERROR_RETURN 19431 (_bcm_kt2_cosq_node_get(unit, gport, NULL ,&local_port, NULL, &node)); 19432 if ((!BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) && (node->parent == NULL)) { 19433 return BCM_E_PARAM; 19434 } 19435 19436 if ( node->hw_index % 8 == 0) { 19437 sal_memset(map_entries, 0, sizeof(map_entries)); 19438 19439 BCM_IF_ERROR_RETURN( 19440 soc_mem_read(unit, ING_QUEUE_MAPm, MEM_BLOCK_ANY, node->hw_index, 19441 &ing_queue_entry)); 19442 old_index = soc_mem_field32_get(unit, ING_QUEUE_MAPm, 19443 &ing_queue_entry, QUEUE_OFFSET_PROFILE_INDEXf); 19444 old_index *= 16; 19445 19446 entries[0] = &map_entries; 19447 BCM_IF_ERROR_RETURN 19448 (_bcm_offset_map_table_entry_get(unit, old_index, 16, entries)); 19449 rv = _bcm_offset_map_table_entry_delete(unit, old_index); 19450 if (!(rv == SOC_E_NOT_FOUND || rv == SOC_E_NONE)) { 19451 return rv; 19452 } 19453 soc_mem_field32_set(unit, ING_QUEUE_OFFSET_MAPPING_TABLEm, 19454 &map_entries[priority], QUEUE_OFFSETf, cosq); 19455 19456 BCM_IF_ERROR_RETURN 19457 (_bcm_offset_map_table_entry_add(unit, entries, 16, &new_index)); 19458 19459 soc_mem_field32_set(unit, ING_QUEUE_MAPm, &ing_queue_entry, 19460 QUEUE_OFFSET_PROFILE_INDEXf, 19461 new_index / 16); 19462 BCM_IF_ERROR_RETURN( 19463 soc_mem_write(unit, ING_QUEUE_MAPm, MEM_BLOCK_ANY, 19464 node->hw_index, &ing_queue_entry)); 19465 } 19466 19467 19468 break; 19469 default: 19470 return BCM_E_UNAVAIL; 19471 } 19472 19473 return BCM_E_NONE; 19474 } 19475 19476 /* 19477 * Function: 19478 * _bcm_kt2_cosq_mapping_get 19479 * Purpose: 19480 * Set COS queue for the specified priority of an ingress port 19481 * Parameters: 19482 * unit - (IN) unit number 19483 * ing_port - (IN) ingress port 19484 * gport - (IN) queue group GPORT identifier 19485 * priority - (IN) priority value to map 19486 * flags - (IN) BCM_COSQ_GPORT_XXX_QUEUE_GROUP 19487 * gport - (IN) queue group GPORT identifier 19488 * cosq - (IN) COS queue number 19489 * Returns: 19490 * BCM_E_XXX 19491 */ 19492 STATIC int 19493 _bcm_kt2_cosq_mapping_get(int unit, bcm_port_t ing_port, bcm_cos_t priority, 19494 uint32 flags, bcm_gport_t *gport, bcm_cos_queue_t *cosq) 19495 { 19496 _bcm_kt2_cosq_node_t *node; 19497 void *entries[1]; 19498 bcm_port_t local_port; 19499 ing_queue_map_entry_t ing_queue_entry; 19500 ing_queue_offset_mapping_table_entry_t map_entries[16]; 19501 uint32 index = 0; 19502 19503 if (priority < 0 || priority >= 16) { 19504 return BCM_E_PARAM; 19505 } 19506 19507 19508 switch (flags) { 19509 case BCM_COSQ_GPORT_DESTMOD_UCAST_QUEUE_GROUP: 19510 BCM_IF_ERROR_RETURN 19511 (_bcm_kt2_cosq_node_get(unit, *gport, NULL ,&local_port, NULL, &node)); 19512 if ((!BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(*gport)) && (node->parent == NULL)) { 19513 return BCM_E_PARAM; 19514 } 19515 19516 sal_memset(map_entries, 0, sizeof(map_entries)); 19517 19518 entries[0] = &map_entries; 19519 BCM_IF_ERROR_RETURN( 19520 soc_mem_read(unit, ING_QUEUE_MAPm, MEM_BLOCK_ANY, node->hw_index, 19521 &ing_queue_entry)); 19522 index = soc_mem_field32_get(unit, ING_QUEUE_MAPm, 19523 &ing_queue_entry, QUEUE_OFFSET_PROFILE_INDEXf); 19524 index *= 16; 19525 19526 BCM_IF_ERROR_RETURN 19527 (_bcm_offset_map_table_entry_get(unit, index, 16, entries)); 19528 *cosq = soc_mem_field32_get(unit, ING_QUEUE_OFFSET_MAPPING_TABLEm, 19529 &map_entries[priority], QUEUE_OFFSETf); 19530 19531 break; 19532 default: 19533 return BCM_E_UNAVAIL; 19534 } 19535 19536 return BCM_E_NONE; 19537 } 19538 int 19539 bcm_kt2_cosq_gport_mapping_set(int unit, bcm_port_t ing_port, 19540 bcm_cos_t int_pri, uint32 flags, 19541 bcm_gport_t gport, bcm_cos_queue_t cosq) 19542 { 19543 return _bcm_kt2_cosq_mapping_set(unit, ing_port, int_pri, flags, gport, 19544 cosq); 19545 } 19546 19547 int 19548 bcm_kt2_cosq_gport_mapping_get(int unit, bcm_port_t ing_port, 19549 bcm_cos_t int_pri, uint32 flags, 19550 bcm_gport_t *gport, bcm_cos_queue_t *cosq) 19551 { 19552 return _bcm_kt2_cosq_mapping_get(unit, ing_port, int_pri, flags, gport, 19553 cosq); 19554 } 19555 19556 int 19557 bcm_kt2_cosq_congestion_mapping_set(int unit,int fabric_modid , 19558 bcm_cosq_congestion_mapping_info_t *config) 19559 { 19560 int profile_index , index, desired_congestion_state; 19561 int i ,j , value, bit_position, max_value = 0, max_congestion_state; 19562 mmu_intfi_st_trans_tbl_entry_t st_trans_entry; 19563 int desired_congestion_value[8] = 19564 {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80} ; 19565 19566 /* CHECK if valid fabric_modid is passed. */ 19567 if (fabric_modid < 0) { 19568 return BCM_E_BADID; 19569 } 19570 profile_index = _bcm_kt2_cosq_source_intf_profile_get(unit, fabric_modid, 19571 0, _BCM_KT2_COSQ_DMVOQ); 19572 if (profile_index == -1 ) { 19573 return BCM_E_PARAM; 19574 } 19575 19576 /* Find the Max flow control bit */ 19577 for (i = 0; i < 8 ; i++) { 19578 if (max_value < config->flow_control_bits[i]) { 19579 max_value = config->flow_control_bits[i]; 19580 } 19581 } 19582 max_congestion_state = 1 << (max_value + 1) ; 19583 19584 if (max_congestion_state > 256 ) { 19585 return BCM_E_PARAM; 19586 } 19587 19588 /* Configure all the congestion states as per 19589 the flow control bits passed */ 19590 for ( i = 0; i < max_congestion_state ; i++) { 19591 desired_congestion_state = 0; 19592 value = i; 19593 bit_position = 0; 19594 /* Loop to set all the congestion states bit by bit */ 19595 while ( value != 0 ) { 19596 if (value & 0x1) { 19597 for (j = 0 ; j < 8 ; j++) { 19598 if (config->flow_control_bits[j] == bit_position) { 19599 desired_congestion_state |= 19600 desired_congestion_value[j]; 19601 } 19602 } 19603 } 19604 bit_position++; 19605 value = value >> 1; 19606 } 19607 19608 index = (profile_index * 256) + i ; 19609 SOC_IF_ERROR_RETURN(READ_MMU_INTFI_ST_TRANS_TBLm( 19610 unit, MEM_BLOCK_ALL, index, 19611 &st_trans_entry)); 19612 soc_mem_field32_set(unit, MMU_INTFI_ST_TRANS_TBLm, 19613 &st_trans_entry, FC_ST_XLATEf, 19614 desired_congestion_state); 19615 SOC_IF_ERROR_RETURN(WRITE_MMU_INTFI_ST_TRANS_TBLm( 19616 unit, MEM_BLOCK_ALL, index, 19617 &st_trans_entry)); 19618 19619 19620 } 19621 /* Configure remaining the congestion states as zero */ 19622 19623 if (max_congestion_state < 256 ) { 19624 for ( i = max_congestion_state; i < 256 ; i++) { 19625 index = (profile_index * 256) + i ; 19626 SOC_IF_ERROR_RETURN(READ_MMU_INTFI_ST_TRANS_TBLm( 19627 unit, MEM_BLOCK_ALL, index, 19628 &st_trans_entry)); 19629 soc_mem_field32_set(unit, MMU_INTFI_ST_TRANS_TBLm, 19630 &st_trans_entry, FC_ST_XLATEf, 19631 0); 19632 SOC_IF_ERROR_RETURN(WRITE_MMU_INTFI_ST_TRANS_TBLm( 19633 unit, MEM_BLOCK_ALL, index, 19634 &st_trans_entry)); 19635 } 19636 } 19637 19638 19639 return BCM_E_NONE; 19640 19641 } 19642 19643 int 19644 bcm_kt2_cosq_congestion_mapping_get(int unit,int fabric_modid , 19645 bcm_cosq_congestion_mapping_info_t *config) 19646 { 19647 int index, profile_index, i; 19648 mmu_intfi_st_trans_tbl_entry_t st_trans_entry; 19649 int congestion_data , bit_position; 19650 19651 /* CHECK if valid fabric_modid is passed. */ 19652 if (fabric_modid < 0) { 19653 return BCM_E_BADID; 19654 } 19655 profile_index = _bcm_kt2_cosq_source_intf_profile_get(unit, fabric_modid, 19656 0, _BCM_KT2_COSQ_DMVOQ); 19657 if (profile_index == -1 ) { 19658 return BCM_E_PARAM; 19659 } 19660 19661 /* Initially fill all the control bits as -1 */ 19662 19663 for (i = 0; i < 8 ; i++) { 19664 config->flow_control_bits[i] = -1; 19665 } 19666 /* Read the congestion state at index 1,2,4,8,16,32,64,128 and update the control bits 19667 accordingly */ 19668 for (i = 0; i < 8 ; i++) { 19669 index = ((profile_index * 256) + (1 << i)) ; 19670 19671 SOC_IF_ERROR_RETURN(READ_MMU_INTFI_ST_TRANS_TBLm( 19672 unit, MEM_BLOCK_ALL, index, 19673 &st_trans_entry)); 19674 congestion_data = 19675 soc_mem_field32_get(unit, MMU_INTFI_ST_TRANS_TBLm, 19676 &st_trans_entry, FC_ST_XLATEf); 19677 bit_position = 0; 19678 /* Loop to check all the bits in the congestion data */ 19679 while ( congestion_data != 0 ) { 19680 if (congestion_data & 0x1) { 19681 config->flow_control_bits[bit_position] = i; 19682 } 19683 bit_position++; 19684 congestion_data = congestion_data >> 1; 19685 } 19686 } 19687 return BCM_E_NONE; 19688 } 19689 19690 19691 int 19692 _bcm_kt2_cosq_dynamic_port_encap_change(int unit,bcm_port_t port) 19693 { 19694 19695 bcm_gport_t gport; 19696 _bcm_kt2_mmu_info_t *mmu_info; 19697 _bcm_kt2_cosq_list_t *list; 19698 int numq,cosq; 19699 int num_cos = 0; 19700 int id = 0 ; 19701 int mcid = 0; 19702 uint32 rval; 19703 bcm_gport_t port_sched, l0_sched, l1_sched, queue; 19704 int rv; 19705 int limit,offset; 19706 soc_info_t *si; 19707 int queuenum = 0; 19708 19709 si = &SOC_INFO(unit); 19710 mmu_info = _bcm_kt2_mmu_info[unit]; 19711 19712 #if defined BCM_METROLITE_SUPPORT 19713 if (soc_feature(unit, soc_feature_discontinuous_pp_port) && 19714 (SOC_PBMP_MEMBER(si->linkphy_pbm, port) || 19715 SOC_PBMP_MEMBER(si->subtag_pbm, port))) { 19716 /* Port encap change should not be called for Linkphy ports */ 19717 return BCM_E_PARAM; 19718 } 19719 #endif 19720 19721 bcm_kt2_cosq_config_get(unit, &num_cos); 19722 BCM_IF_ERROR_RETURN 19723 (bcm_esw_port_gport_get(unit, port , &gport)); 19724 19725 19726 list = &mmu_info->global_qlist; 19727 offset = 0; 19728 19729 /* We do not want to recreate lls tree if we're not involving 19730 * HG ports. 19731 */ 19732 if ((si->port_num_uc_cosq[port] == KT2_DEFAULT_NUM_PHYSICAL_QUEUES) && 19733 (!IS_HG_PORT(unit, port))) { 19734 return BCM_E_NONE; 19735 } 19736 if ((si->port_num_uc_cosq[port] == KT2_HG_NUM_PHYSICAL_QUEUES) && 19737 (IS_HG_PORT(unit, port))) { 19738 return BCM_E_NONE; 19739 } 19740 if (IS_HG_PORT(unit, port)) { 19741 numq = KT2_HG_NUM_PHYSICAL_QUEUES; 19742 } 19743 else { 19744 numq = KT2_DEFAULT_NUM_PHYSICAL_QUEUES ; 19745 } 19746 limit = mmu_info->num_base_queues; 19747 19748 rv = _bcm_kt2_node_index_get(unit, list->bits, offset, limit, 19749 mmu_info->qset_size, numq, &id); 19750 if( rv != BCM_E_NONE) { 19751 return BCM_E_RESOURCE; 19752 19753 } 19754 if (soc_feature(unit, soc_feature_mmu_packing)) { 19755 /* reserving queues for mc if its packing */ 19756 rv = _bcm_kt2_node_index_get(unit, list->bits, (id + numq), limit, 19757 mmu_info->qset_size, numq, &mcid); 19758 if (rv != BCM_E_NONE) { 19759 return BCM_E_RESOURCE; 19760 } 19761 } 19762 BCM_IF_ERROR_RETURN 19763 ( bcm_kt2_cosq_gport_delete(unit , gport)); 19764 19765 BCM_IF_ERROR_RETURN 19766 (_bcm_kt2_node_index_clear(list, si->port_uc_cosq_base[port] , 19767 si->port_num_uc_cosq[port])); 19768 19769 BCM_IF_ERROR_RETURN 19770 (_bcm_kt2_node_index_set(list ,id, numq)); 19771 si->port_uc_cosq_base[port] = id ; 19772 si->port_cosq_base[port] = id ; 19773 si->port_num_uc_cosq[port] = numq ; 19774 mmu_info->port[port].q_offset = id; 19775 mmu_info->port[port].q_limit = id + numq; 19776 if (soc_feature(unit, soc_feature_mmu_packing)) { 19777 BCM_IF_ERROR_RETURN 19778 (_bcm_kt2_node_index_clear(list, si->port_cosq_base[port] , 19779 si->port_num_cosq[port])); 19780 BCM_IF_ERROR_RETURN 19781 (_bcm_kt2_node_index_set(list, mcid, numq)); 19782 si->port_cosq_base[port] = mcid ; 19783 si->port_num_cosq[port] = numq; 19784 mmu_info->port[port].mcq_offset = mcid; 19785 mmu_info->port[port].mcq_limit = mcid + numq ; 19786 } 19787 19788 SOC_IF_ERROR_RETURN(READ_ING_COS_MODEr(unit, port, &rval)); 19789 soc_reg_field_set(unit, ING_COS_MODEr, &rval, BASE_QUEUE_NUMf, 19790 mmu_info->port[port].q_offset); 19791 if (IS_HG_PORT(unit, port)) { 19792 soc_reg_field_set(unit, ING_COS_MODEr, &rval, COS_MODEf, 2); 19793 } 19794 else { 19795 soc_reg_field_set(unit, ING_COS_MODEr, &rval, COS_MODEf, 0); 19796 } 19797 SOC_IF_ERROR_RETURN(WRITE_ING_COS_MODEr(unit, port, rval)); 19798 19799 SOC_IF_ERROR_RETURN(READ_RQE_PP_PORT_CONFIGr(unit, port, &rval)); 19800 soc_reg_field_set(unit, RQE_PP_PORT_CONFIGr, &rval, BASE_QUEUEf, 19801 (soc_feature(unit, soc_feature_mmu_packing)) ? 19802 mmu_info->port[port].mcq_offset : 19803 mmu_info->port[port].q_offset); 19804 19805 if (IS_HG_PORT(unit, port)) { 19806 soc_reg_field_set(unit, RQE_PP_PORT_CONFIGr, 19807 &rval, COS_MODEf, 2); 19808 } 19809 else { 19810 soc_reg_field_set(unit, RQE_PP_PORT_CONFIGr, 19811 &rval, COS_MODEf, 0); 19812 } 19813 SOC_IF_ERROR_RETURN(WRITE_RQE_PP_PORT_CONFIGr(unit, port, rval)); 19814 19815 for (queuenum = mmu_info->port[port].q_offset; 19816 queuenum < mmu_info->port[port].q_limit; queuenum++) { 19817 SOC_IF_ERROR_RETURN (soc_mem_field32_modify(unit, 19818 EGR_QUEUE_TO_PP_PORT_MAPm, queuenum, PP_PORTf, port)); 19819 } 19820 19821 if (soc_feature(unit, soc_feature_mmu_packing)) { 19822 for (queuenum = mmu_info->port[port].mcq_offset; 19823 queuenum < mmu_info->port[port].mcq_limit; queuenum++) { 19824 SOC_IF_ERROR_RETURN (soc_mem_field32_modify(unit, 19825 EGR_QUEUE_TO_PP_PORT_MAPm, queuenum, PP_PORTf, port)); 19826 } 19827 } 19828 if (IS_HG_PORT(unit, port)) { 19829 BCM_IF_ERROR_RETURN 19830 (_bcm_kt2_port_lls_config_set(unit, port, 19831 si->port_uc_cosq_base[port], 19832 si->port_num_uc_cosq[port], 19833 num_cos)); 19834 } else { 19835 if (!soc_feature(unit, soc_feature_mmu_packing)) { 19836 BCM_IF_ERROR_RETURN 19837 (bcm_kt2_cosq_gport_add(unit, gport, 1, 0, &port_sched)); 19838 BCM_IF_ERROR_RETURN 19839 (bcm_kt2_cosq_gport_add(unit, port, 1, 19840 BCM_COSQ_GPORT_SCHEDULER, 19841 &l0_sched)); 19842 BCM_IF_ERROR_RETURN 19843 (bcm_kt2_cosq_gport_attach(unit, l0_sched, port_sched, 0)); 19844 BCM_IF_ERROR_RETURN 19845 (bcm_kt2_cosq_gport_add(unit, port,num_cos, 19846 BCM_COSQ_GPORT_SCHEDULER, 19847 &l1_sched)); 19848 BCM_IF_ERROR_RETURN 19849 (bcm_kt2_cosq_gport_attach(unit, l1_sched, l0_sched, 0)); 19850 for (cosq = 0; cosq < num_cos; cosq++) { 19851 BCM_IF_ERROR_RETURN 19852 (bcm_kt2_cosq_gport_add(unit, port, 1, 19853 BCM_COSQ_GPORT_UCAST_QUEUE_GROUP, &queue)); 19854 BCM_IF_ERROR_RETURN 19855 (bcm_kt2_cosq_gport_attach(unit, queue, l1_sched, 19856 cosq)); 19857 } 19858 }else { 19859 BCM_IF_ERROR_RETURN 19860 (_bcm_kt2_packing_config_set(unit, port, num_cos )); 19861 } 19862 } 19863 return BCM_E_NONE; 19864 19865 } 19866 19867 /* 19868 * Function: 19869 * _bcm_kt2_port_enqueue_set 19870 * Purpose: 19871 * Enable or Disable the enqueing the packets to the port 19872 * Parameters: 19873 * unit - (IN) unit number 19874 * gport - (IN) gport of the port 19875 * enable - (IN) TRUE to enable 19876 * FALSE to disable 19877 * Returns: 19878 * BCM_E_XXX 19879 */ 19880 19881 int 19882 _bcm_kt2_port_enqueue_set(int unit, bcm_port_t gport, 19883 int enable) 19884 { 19885 bcm_port_t local_port; 19886 uint64 tmp64, r64val, rval64; 19887 19888 BCM_IF_ERROR_RETURN 19889 (_bcm_kt2_cosq_localport_resolve(unit, gport, &local_port)); 19890 19891 if (!BCM_PBMP_MEMBER((PBMP_ALL(unit)), local_port)) { 19892 return BCM_E_PORT; 19893 } 19894 /* Enable in TX direction*/ 19895 BCM_IF_ERROR_RETURN 19896 (soc_katana2_mmu_port_enable_set(unit, local_port, enable)); 19897 19898 /* Enable in RX direction*/ 19899 SOC_IF_ERROR_RETURN(READ_INPUT_PORT_RX_ENABLE_64r(unit, &r64val)); 19900 rval64 = soc_reg64_field_get(unit, INPUT_PORT_RX_ENABLE_64r, r64val, 19901 INPUT_PORT_RX_ENABLEf); 19902 COMPILER_64_SET(tmp64, 0, 1); 19903 COMPILER_64_SHL(tmp64, (local_port)); 19904 if (enable) { 19905 COMPILER_64_OR(rval64, tmp64); 19906 } else { 19907 COMPILER_64_NOT(tmp64); 19908 COMPILER_64_AND(rval64, tmp64); 19909 } 19910 19911 soc_reg64_field_set(unit, INPUT_PORT_RX_ENABLE_64r, &r64val, 19912 INPUT_PORT_RX_ENABLEf, rval64); 19913 SOC_IF_ERROR_RETURN(WRITE_INPUT_PORT_RX_ENABLE_64r(unit, r64val)); 19914 return BCM_E_NONE; 19915 } 19916 /* 19917 * Function: 19918 * bcm_kt2_cosq_gport_e2ecc_transmit_set 19919 * Purpose: 19920 * Enable or Disable queue of a given port for e2ecc reporting. 19921 * Parameters: 19922 * unit - (IN) unit number 19923 * gport - (IN) gport of the port 19924 * cosq - (IN) cosq number (0-7) -1 for all queues. 19925 * type - (IN) Flag indicating e2ecc transmit. 19926 * arg - (IN) TRUE to enable 19927 * FALSE to disable 19928 * Returns: 19929 * BCM_E_XXX 19930 */ 19931 int 19932 bcm_kt2_cosq_gport_e2ecc_transmit_set(int unit, bcm_gport_t gport, 19933 bcm_cos_queue_t cosq, 19934 bcm_cosq_control_t type, 19935 int arg) 19936 { 19937 bcm_port_t port; 19938 uint32 rval; 19939 uint32 fval; 19940 uint64 r64val; 19941 19942 LOG_INFO(BSL_LS_BCM_COSQ, 19943 (BSL_META_U(unit, 19944 "bcm_kt2_cosq_gport_e2ecc_transmit_set: \ 19945 unit=%d gport=0x%x cosq=%d \ 19946 type=%d arg=%d\n"), 19947 unit, gport, cosq, type, arg)); 19948 switch (type) { 19949 case bcmCosqControlE2ECCTransmitEnable: 19950 if ((!BCM_COSQ_QUEUE_VALID(unit, cosq)) && (cosq != -1)) { 19951 return BCM_E_PARAM; 19952 } 19953 if (BCM_GPORT_IS_SET(gport)) { 19954 BCM_IF_ERROR_RETURN( 19955 bcm_esw_port_local_get(unit, gport, &port)); 19956 } else { 19957 port = gport; 19958 } 19959 if (!SOC_PORT_VALID(unit, port) || !IS_ALL_PORT(unit, port)) { 19960 return BCM_E_PORT; 19961 } 19962 19963 BCM_IF_ERROR_RETURN(READ_OP_E2ECC_PORT_CONFIGr(unit, port, &rval)); 19964 fval = soc_reg_field_get(unit, OP_E2ECC_PORT_CONFIGr, 19965 rval, COS_MASKf); 19966 if (cosq != -1) { 19967 if (arg) { 19968 fval |= (1 << cosq); 19969 } else { 19970 fval &= ~(1 << cosq); 19971 } 19972 } else { 19973 if (arg) { 19974 fval = 0xff; 19975 } else { 19976 fval = 0; 19977 } 19978 } 19979 soc_reg_field_set(unit, OP_E2ECC_PORT_CONFIGr, 19980 &rval, COS_MASKf, fval); 19981 soc_reg_field_set(unit, OP_E2ECC_PORT_CONFIGr, &rval, 19982 E2ECC_RPT_ENf, arg ? 1 : 0); 19983 BCM_IF_ERROR_RETURN(WRITE_OP_E2ECC_PORT_CONFIGr(unit, port, rval)); 19984 19985 /* Now enable monitoring in INTFO if at least one queue active */ 19986 COMPILER_64_ZERO(r64val); 19987 soc_reg64_field32_set(unit, MMU_INTFO_CONGST_STr, 19988 &r64val, ENf, fval ? 1: 0); 19989 SOC_IF_ERROR_RETURN(WRITE_MMU_INTFO_CONGST_STr(unit, 19990 port, r64val)); 19991 break; 19992 default: 19993 return BCM_E_UNAVAIL; 19994 } 19995 19996 return BCM_E_NONE; 19997 } 19998 19999 /* 20000 * Function: 20001 * bcm_kt2_cosq_gport_e2ecc_transmit_get 20002 * Purpose: 20003 * Get the Enable or Disable value for a queue of a given port for e2ecc reporting. 20004 * Parameters: 20005 * unit - (IN) unit number 20006 * gport - (IN) gport of the port 20007 * cosq - (IN) cosq number (0-7) -1 for all queues. 20008 * type - (IN) Flag indicating e2ecc transmit. 20009 * arg - (OUT)TRUE to enable 20010 * FALSE to disable 20011 * Returns: 20012 * BCM_E_XXX 20013 */ 20014 int 20015 bcm_kt2_cosq_gport_e2ecc_transmit_get(int unit, bcm_gport_t gport, 20016 bcm_cos_queue_t cosq, 20017 bcm_cosq_control_t type, 20018 int *arg) 20019 { 20020 bcm_port_t port; 20021 uint32 rval; 20022 uint32 fval; 20023 20024 LOG_INFO(BSL_LS_BCM_COSQ, 20025 (BSL_META_U(unit, 20026 "bcm_kt2_cosq_gport_e2ecc_transmit_set: \ 20027 unit=%d gport=0x%x cosq=%d \ 20028 type=%d \n"), 20029 unit, gport, cosq, type)); 20030 switch (type) { 20031 case bcmCosqControlE2ECCTransmitEnable: 20032 if (!BCM_COSQ_QUEUE_VALID(unit, cosq)) { 20033 return BCM_E_PARAM; 20034 } 20035 if (BCM_GPORT_IS_SET(gport)) { 20036 BCM_IF_ERROR_RETURN( 20037 bcm_esw_port_local_get(unit, gport, &port)); 20038 } else { 20039 port = gport; 20040 } 20041 if (!SOC_PORT_VALID(unit, port) || !IS_ALL_PORT(unit, port)) { 20042 return BCM_E_PORT; 20043 } 20044 20045 BCM_IF_ERROR_RETURN(READ_OP_E2ECC_PORT_CONFIGr(unit, port, &rval)); 20046 fval = soc_reg_field_get(unit, OP_E2ECC_PORT_CONFIGr, 20047 rval, COS_MASKf); 20048 fval = fval & (1 << cosq); 20049 *arg = fval ? 1 : 0; 20050 break; 20051 default: 20052 return BCM_E_UNAVAIL; 20053 } 20054 20055 return BCM_E_NONE; 20056 } 20057 #if defined(BCM_SABER2_SUPPORT) 20058 STATIC int 20059 _bcm_kt2_get_pg_profile_mapping(int unit, int profile_index, 20060 uint32 *reg0, uint32 *reg1) 20061 { 20062 uint32 rval, rval1; 20063 20064 if (profile_index < 0 || profile_index > 3) { 20065 return BCM_E_PARAM; 20066 } 20067 if (profile_index == 0) { 20068 SOC_IF_ERROR_RETURN 20069 (READ_MMU_ENQ_PROFILE_0_PRI_GRP0r(unit, &rval)); 20070 SOC_IF_ERROR_RETURN 20071 (READ_MMU_ENQ_PROFILE_0_PRI_GRP1r(unit, &rval1)); 20072 } else if (profile_index == 1) { 20073 SOC_IF_ERROR_RETURN 20074 (READ_MMU_ENQ_PROFILE_1_PRI_GRP0r(unit, &rval)); 20075 SOC_IF_ERROR_RETURN 20076 (READ_MMU_ENQ_PROFILE_1_PRI_GRP1r(unit, &rval1)); 20077 } else if (profile_index == 2) { 20078 SOC_IF_ERROR_RETURN 20079 (READ_MMU_ENQ_PROFILE_2_PRI_GRP0r(unit, &rval)); 20080 SOC_IF_ERROR_RETURN 20081 (READ_MMU_ENQ_PROFILE_2_PRI_GRP1r(unit, &rval1)); 20082 } else { 20083 SOC_IF_ERROR_RETURN 20084 (READ_MMU_ENQ_PROFILE_3_PRI_GRP0r(unit, &rval)); 20085 SOC_IF_ERROR_RETURN 20086 (READ_MMU_ENQ_PROFILE_3_PRI_GRP1r(unit, &rval1)); 20087 } 20088 *reg0 = rval; 20089 *reg1 = rval1; 20090 return BCM_E_NONE; 20091 } 20092 20093 STATIC int 20094 _bcm_kt2_set_pg_profile_mapping(int unit, int profile_index, 20095 uint32 reg0, uint32 reg1) 20096 { 20097 20098 if (profile_index < 0 || profile_index > 3) { 20099 return BCM_E_PARAM; 20100 } 20101 if (profile_index == 0) { 20102 SOC_IF_ERROR_RETURN 20103 (WRITE_MMU_ENQ_PROFILE_0_PRI_GRP0r(unit, reg0)); 20104 SOC_IF_ERROR_RETURN 20105 (WRITE_MMU_ENQ_PROFILE_0_PRI_GRP1r(unit, reg1)); 20106 } else if (profile_index == 1) { 20107 SOC_IF_ERROR_RETURN 20108 (WRITE_MMU_ENQ_PROFILE_1_PRI_GRP0r(unit, reg0)); 20109 SOC_IF_ERROR_RETURN 20110 (WRITE_MMU_ENQ_PROFILE_1_PRI_GRP1r(unit, reg1)); 20111 } else if (profile_index == 2) { 20112 SOC_IF_ERROR_RETURN 20113 (WRITE_MMU_ENQ_PROFILE_2_PRI_GRP0r(unit, reg0)); 20114 SOC_IF_ERROR_RETURN 20115 (WRITE_MMU_ENQ_PROFILE_2_PRI_GRP1r(unit, reg1)); 20116 } else { 20117 SOC_IF_ERROR_RETURN 20118 (WRITE_MMU_ENQ_PROFILE_3_PRI_GRP0r(unit, reg0)); 20119 SOC_IF_ERROR_RETURN 20120 (WRITE_MMU_ENQ_PROFILE_3_PRI_GRP1r(unit, reg1)); 20121 } 20122 return BCM_E_NONE; 20123 } 20124 20125 STATIC int 20126 _bcm_kt2_get_port_profile_index(int unit, bcm_port_t port, int *p_index) 20127 { 20128 uint64 rval64; 20129 soc_field_t sb2_pri_to_prigrp_field[SB2_MAX_LOGICAL_PORTS]={ 20130 SRCPORT_0f, 20131 SRCPORT_1f, SRCPORT_2f, SRCPORT_3f, SRCPORT_4f, 20132 SRCPORT_5f, SRCPORT_6f, SRCPORT_7f, SRCPORT_8f, 20133 SRCPORT_9f, SRCPORT_10f, SRCPORT_11f, SRCPORT_12f, 20134 SRCPORT_13f, SRCPORT_14f, SRCPORT_15f, SRCPORT_16f, 20135 SRCPORT_17f, SRCPORT_18f, SRCPORT_19f, SRCPORT_20f, 20136 SRCPORT_21f, SRCPORT_22f, SRCPORT_23f, SRCPORT_24f, 20137 SRCPORT_25f, SRCPORT_26f, SRCPORT_27f, SRCPORT_28f, 20138 SRCPORT_29f 20139 }; 20140 if(SOC_IS_SABER2(unit)) { 20141 SOC_IF_ERROR_RETURN( 20142 READ_MMU_ENQ_IP_PRI_TO_PG_PROFILE_0r(unit, &rval64)); 20143 if (soc_reg_field_valid(unit, MMU_ENQ_IP_PRI_TO_PG_PROFILE_0r, 20144 sb2_pri_to_prigrp_field[port])) { 20145 *p_index = soc_reg64_field32_get(unit, 20146 MMU_ENQ_IP_PRI_TO_PG_PROFILE_0r, 20147 rval64, 20148 sb2_pri_to_prigrp_field[port]); 20149 return BCM_E_NONE; 20150 } 20151 } 20152 return BCM_E_PARAM; 20153 } 20154 STATIC int 20155 _bcm_kt2_config_all_pg_profile_register(int unit, bcm_port_t port) 20156 { 20157 int profile_index; 20158 uint32 reg0, reg1; 20159 uint64 rval64; 20160 20161 BCM_IF_ERROR_RETURN(_bcm_kt2_get_port_profile_index(unit, port, &profile_index)); 20162 BCM_IF_ERROR_RETURN(_bcm_kt2_get_pg_profile_mapping(unit, profile_index, 20163 ®0, ®1)); 20164 if (profile_index < 0 || profile_index > 3) { 20165 return BCM_E_PARAM; 20166 } 20167 if (profile_index == 0) { 20168 SOC_IF_ERROR_RETURN 20169 (WRITE_PROFILE0_PRI_GRP0r(unit, reg0)); 20170 SOC_IF_ERROR_RETURN 20171 (WRITE_PROFILE0_PRI_GRP1r(unit, reg1)); 20172 if (SOC_REG_IS_VALID(unit, THDIEXT_PROFILE0_PRI_GRP0r)) { 20173 SOC_IF_ERROR_RETURN 20174 (WRITE_THDIEXT_PROFILE0_PRI_GRP0r(unit, reg0)); 20175 } 20176 if (SOC_REG_IS_VALID(unit, THDIEXT_PROFILE0_PRI_GRP1r)) { 20177 SOC_IF_ERROR_RETURN 20178 (WRITE_THDIEXT_PROFILE0_PRI_GRP1r(unit, reg1)); 20179 } 20180 if (SOC_REG_IS_VALID(unit, THDIEMA_PROFILE0_PRI_GRP0r)) { 20181 SOC_IF_ERROR_RETURN 20182 (WRITE_THDIEMA_PROFILE0_PRI_GRP0r(unit, reg0)); 20183 } 20184 if (SOC_REG_IS_VALID(unit, THDIEMA_PROFILE0_PRI_GRP1r)) { 20185 SOC_IF_ERROR_RETURN 20186 (WRITE_THDIEMA_PROFILE0_PRI_GRP1r(unit, reg1)); 20187 } 20188 SOC_IF_ERROR_RETURN 20189 (WRITE_THDIRQE_PROFILE0_PRI_GRP0r(unit, reg0)); 20190 SOC_IF_ERROR_RETURN 20191 (WRITE_THDIRQE_PROFILE0_PRI_GRP1r(unit, reg1)); 20192 SOC_IF_ERROR_RETURN 20193 (WRITE_THDIQEN_PROFILE0_PRI_GRP0r(unit, reg0)); 20194 SOC_IF_ERROR_RETURN 20195 (WRITE_THDIQEN_PROFILE0_PRI_GRP1r(unit, reg1)); 20196 20197 } else if (profile_index == 1) { 20198 SOC_IF_ERROR_RETURN 20199 (WRITE_PROFILE1_PRI_GRP0r(unit, reg0)); 20200 SOC_IF_ERROR_RETURN 20201 (WRITE_PROFILE1_PRI_GRP1r(unit, reg1)); 20202 if (SOC_REG_IS_VALID(unit, THDIEXT_PROFILE1_PRI_GRP0r)) { 20203 SOC_IF_ERROR_RETURN 20204 (WRITE_THDIEXT_PROFILE1_PRI_GRP0r(unit, reg0)); 20205 } 20206 if (SOC_REG_IS_VALID(unit, THDIEXT_PROFILE1_PRI_GRP1r)) { 20207 SOC_IF_ERROR_RETURN 20208 (WRITE_THDIEXT_PROFILE1_PRI_GRP1r(unit, reg1)); 20209 } 20210 if (SOC_REG_IS_VALID(unit, THDIEMA_PROFILE1_PRI_GRP0r)) { 20211 SOC_IF_ERROR_RETURN 20212 (WRITE_THDIEMA_PROFILE1_PRI_GRP0r(unit, reg0)); 20213 } 20214 if (SOC_REG_IS_VALID(unit, THDIEMA_PROFILE1_PRI_GRP1r)) { 20215 SOC_IF_ERROR_RETURN 20216 (WRITE_THDIEMA_PROFILE1_PRI_GRP1r(unit, reg1)); 20217 } 20218 SOC_IF_ERROR_RETURN 20219 (WRITE_THDIRQE_PROFILE1_PRI_GRP0r(unit, reg0)); 20220 SOC_IF_ERROR_RETURN 20221 (WRITE_THDIRQE_PROFILE1_PRI_GRP1r(unit, reg1)); 20222 SOC_IF_ERROR_RETURN 20223 (WRITE_THDIQEN_PROFILE1_PRI_GRP0r(unit, reg0)); 20224 SOC_IF_ERROR_RETURN 20225 (WRITE_THDIQEN_PROFILE1_PRI_GRP1r(unit, reg1)); 20226 } else if (profile_index == 2) { 20227 SOC_IF_ERROR_RETURN 20228 (WRITE_PROFILE2_PRI_GRP0r(unit, reg0)); 20229 SOC_IF_ERROR_RETURN 20230 (WRITE_PROFILE2_PRI_GRP1r(unit, reg1)); 20231 if (SOC_REG_IS_VALID(unit, THDIEXT_PROFILE2_PRI_GRP0r)) { 20232 SOC_IF_ERROR_RETURN 20233 (WRITE_THDIEXT_PROFILE2_PRI_GRP0r(unit, reg0)); 20234 } 20235 if (SOC_REG_IS_VALID(unit, THDIEXT_PROFILE2_PRI_GRP1r)) { 20236 SOC_IF_ERROR_RETURN 20237 (WRITE_THDIEXT_PROFILE2_PRI_GRP1r(unit, reg1)); 20238 } 20239 if (SOC_REG_IS_VALID(unit, THDIEMA_PROFILE2_PRI_GRP0r)) { 20240 SOC_IF_ERROR_RETURN 20241 (WRITE_THDIEMA_PROFILE2_PRI_GRP0r(unit, reg0)); 20242 } 20243 if (SOC_REG_IS_VALID(unit, THDIEMA_PROFILE2_PRI_GRP1r)) { 20244 SOC_IF_ERROR_RETURN 20245 (WRITE_THDIEMA_PROFILE2_PRI_GRP1r(unit, reg1)); 20246 } 20247 SOC_IF_ERROR_RETURN 20248 (WRITE_THDIRQE_PROFILE2_PRI_GRP0r(unit, reg0)); 20249 SOC_IF_ERROR_RETURN 20250 (WRITE_THDIRQE_PROFILE2_PRI_GRP1r(unit, reg1)); 20251 SOC_IF_ERROR_RETURN 20252 (WRITE_THDIQEN_PROFILE2_PRI_GRP0r(unit, reg0)); 20253 SOC_IF_ERROR_RETURN 20254 (WRITE_THDIQEN_PROFILE2_PRI_GRP1r(unit, reg1)); 20255 } else { 20256 SOC_IF_ERROR_RETURN 20257 (WRITE_PROFILE3_PRI_GRP0r(unit, reg0)); 20258 SOC_IF_ERROR_RETURN 20259 (WRITE_PROFILE3_PRI_GRP1r(unit, reg1)); 20260 if (SOC_REG_IS_VALID(unit, THDIEXT_PROFILE3_PRI_GRP0r)) { 20261 SOC_IF_ERROR_RETURN 20262 (WRITE_THDIEXT_PROFILE3_PRI_GRP0r(unit, reg0)); 20263 } 20264 if (SOC_REG_IS_VALID(unit, THDIEXT_PROFILE3_PRI_GRP1r)) { 20265 SOC_IF_ERROR_RETURN 20266 (WRITE_THDIEXT_PROFILE3_PRI_GRP1r(unit, reg1)); 20267 } 20268 if (SOC_REG_IS_VALID(unit, THDIEMA_PROFILE3_PRI_GRP0r)) { 20269 SOC_IF_ERROR_RETURN 20270 (WRITE_THDIEMA_PROFILE3_PRI_GRP0r(unit, reg0)); 20271 } 20272 if (SOC_REG_IS_VALID(unit, THDIEMA_PROFILE3_PRI_GRP1r)) { 20273 SOC_IF_ERROR_RETURN 20274 (WRITE_THDIEMA_PROFILE3_PRI_GRP1r(unit, reg1)); 20275 } 20276 SOC_IF_ERROR_RETURN 20277 (WRITE_THDIRQE_PROFILE3_PRI_GRP0r(unit, reg0)); 20278 SOC_IF_ERROR_RETURN 20279 (WRITE_THDIRQE_PROFILE3_PRI_GRP1r(unit, reg1)); 20280 SOC_IF_ERROR_RETURN 20281 (WRITE_THDIQEN_PROFILE3_PRI_GRP0r(unit, reg0)); 20282 SOC_IF_ERROR_RETURN 20283 (WRITE_THDIQEN_PROFILE3_PRI_GRP1r(unit, reg1)); 20284 } 20285 SOC_IF_ERROR_RETURN( 20286 READ_MMU_ENQ_IP_PRI_TO_PG_PROFILE_0r(unit, &rval64)); 20287 20288 SOC_IF_ERROR_RETURN( 20289 WRITE_PORT_PROFILE_MAPr(unit, rval64)); 20290 if (SOC_REG_IS_VALID(unit, THDIEXT_PORT_PROFILE_MAPr)) { 20291 SOC_IF_ERROR_RETURN( 20292 WRITE_THDIEXT_PORT_PROFILE_MAPr(unit, rval64)); 20293 } 20294 if (SOC_REG_IS_VALID(unit, THDIEMA_PORT_PROFILE_MAPr)) { 20295 SOC_IF_ERROR_RETURN( 20296 WRITE_THDIEMA_PORT_PROFILE_MAPr(unit, rval64)); 20297 } 20298 SOC_IF_ERROR_RETURN( 20299 WRITE_THDIRQE_PORT_PROFILE_MAPr(unit, rval64)); 20300 SOC_IF_ERROR_RETURN( 20301 WRITE_THDIQEN_PORT_PROFILE_MAPr(unit, rval64)); 20302 return BCM_E_NONE; 20303 } 20304 20305 STATIC int 20306 _bcm_kt2_check_port_pg_status(int unit, int port, int new_pg, int old_pg) 20307 { 20308 uint32 new_mem_idx, old_mem_idx; 20309 thdi_port_pg_cntrs_entry_t thdi_port_pg_cntrs={{0}}; 20310 thdiext_thdi_port_pg_cntrs_entry_t thdiext_thdi_port_pg_cntrs={{0}}; 20311 thdiema_thdi_port_pg_cntrs_entry_t thdiema_thdi_port_pg_cntrs={{0}}; 20312 thdirqe_thdi_port_pg_cntrs_entry_t thdirqe_thdi_port_pg_cntrs={{0}}; 20313 thdiqen_thdi_port_pg_cntrs_entry_t thdiqen_thdi_port_pg_cntrs = {{0}}; 20314 20315 new_mem_idx= (port * SB2_MAX_PRIORITY_GROUPS) + new_pg; 20316 old_mem_idx= (port * SB2_MAX_PRIORITY_GROUPS) + old_pg; 20317 20318 /* Checm if pg min count is zero or not */ 20319 SOC_IF_ERROR_RETURN (soc_mem_read( 20320 unit, THDI_PORT_PG_CNTRSm, MEM_BLOCK_ALL, 20321 new_mem_idx, &thdi_port_pg_cntrs)); 20322 if (soc_mem_field32_get(unit, THDI_PORT_PG_CNTRSm, 20323 &thdi_port_pg_cntrs, PG_MIN_COUNTf)) { 20324 return BCM_E_BUSY; 20325 } 20326 SOC_IF_ERROR_RETURN (soc_mem_read( 20327 unit, THDI_PORT_PG_CNTRSm, MEM_BLOCK_ALL, 20328 old_mem_idx, &thdi_port_pg_cntrs)); 20329 if (soc_mem_field32_get(unit, THDI_PORT_PG_CNTRSm, 20330 &thdi_port_pg_cntrs, PG_MIN_COUNTf)) { 20331 return BCM_E_BUSY; 20332 } 20333 if (SOC_MEM_IS_VALID(unit, THDIEXT_THDI_PORT_PG_CNTRSm)) { 20334 SOC_IF_ERROR_RETURN (soc_mem_read( 20335 unit, THDIEXT_THDI_PORT_PG_CNTRSm, MEM_BLOCK_ALL, 20336 new_mem_idx, &thdiext_thdi_port_pg_cntrs)); 20337 if (soc_mem_field32_get(unit, THDIEXT_THDI_PORT_PG_CNTRSm, 20338 &thdiext_thdi_port_pg_cntrs, PG_MIN_COUNTf)) { 20339 return BCM_E_BUSY; 20340 } 20341 SOC_IF_ERROR_RETURN (soc_mem_read( 20342 unit, THDIEXT_THDI_PORT_PG_CNTRSm, MEM_BLOCK_ALL, 20343 old_mem_idx, &thdiext_thdi_port_pg_cntrs)); 20344 if (soc_mem_field32_get(unit, THDIEXT_THDI_PORT_PG_CNTRSm, 20345 &thdiext_thdi_port_pg_cntrs, PG_MIN_COUNTf)) { 20346 return BCM_E_BUSY; 20347 } 20348 } 20349 if (SOC_MEM_IS_VALID(unit, THDIEMA_THDI_PORT_PG_CNTRSm)) { 20350 SOC_IF_ERROR_RETURN (soc_mem_read( 20351 unit, THDIEMA_THDI_PORT_PG_CNTRSm, MEM_BLOCK_ALL, 20352 new_mem_idx, &thdiema_thdi_port_pg_cntrs)); 20353 if (soc_mem_field32_get(unit, THDIEMA_THDI_PORT_PG_CNTRSm, 20354 &thdiema_thdi_port_pg_cntrs, PG_MIN_COUNTf)) { 20355 return BCM_E_BUSY; 20356 } 20357 SOC_IF_ERROR_RETURN (soc_mem_read( 20358 unit, THDIEMA_THDI_PORT_PG_CNTRSm, MEM_BLOCK_ALL, 20359 old_mem_idx, &thdiema_thdi_port_pg_cntrs)); 20360 if (soc_mem_field32_get(unit, THDIEMA_THDI_PORT_PG_CNTRSm, 20361 &thdiema_thdi_port_pg_cntrs, PG_MIN_COUNTf)) { 20362 return BCM_E_BUSY; 20363 } 20364 } 20365 SOC_IF_ERROR_RETURN (soc_mem_read( 20366 unit, THDIRQE_THDI_PORT_PG_CNTRSm, MEM_BLOCK_ALL, 20367 new_mem_idx, &thdirqe_thdi_port_pg_cntrs)); 20368 if (soc_mem_field32_get(unit, THDIRQE_THDI_PORT_PG_CNTRSm, 20369 &thdirqe_thdi_port_pg_cntrs, PG_MIN_COUNTf)) { 20370 return BCM_E_BUSY; 20371 } 20372 SOC_IF_ERROR_RETURN (soc_mem_read( 20373 unit, THDIRQE_THDI_PORT_PG_CNTRSm, MEM_BLOCK_ALL, 20374 old_mem_idx, &thdirqe_thdi_port_pg_cntrs)); 20375 if (soc_mem_field32_get(unit, THDIRQE_THDI_PORT_PG_CNTRSm, 20376 &thdirqe_thdi_port_pg_cntrs, PG_MIN_COUNTf)) { 20377 return BCM_E_BUSY; 20378 } 20379 20380 SOC_IF_ERROR_RETURN (soc_mem_read( 20381 unit, THDIQEN_THDI_PORT_PG_CNTRSm, MEM_BLOCK_ALL, 20382 new_mem_idx, &thdiqen_thdi_port_pg_cntrs)); 20383 if (soc_mem_field32_get(unit, THDIQEN_THDI_PORT_PG_CNTRSm, 20384 &thdiqen_thdi_port_pg_cntrs, PG_MIN_COUNTf)) { 20385 return BCM_E_BUSY; 20386 } 20387 SOC_IF_ERROR_RETURN (soc_mem_read( 20388 unit, THDIQEN_THDI_PORT_PG_CNTRSm, MEM_BLOCK_ALL, 20389 old_mem_idx, &thdiqen_thdi_port_pg_cntrs)); 20390 if (soc_mem_field32_get(unit, THDIQEN_THDI_PORT_PG_CNTRSm, 20391 &thdiqen_thdi_port_pg_cntrs, PG_MIN_COUNTf)) { 20392 return BCM_E_BUSY; 20393 } 20394 20395 return BCM_E_NONE; 20396 } 20397 /* 20398 * Function: 20399 * bcm_kt2_port_priority_group_mapping_set 20400 * Purpose: 20401 * Assign a Priority Group for the input priority. 20402 * Parameters: 20403 * unit - (IN) device id. 20404 * gport - (IN) generic port. 20405 * prio - (IN) input priority. 20406 * priority_group - (IN) priority group ID that the input priority mapped to. 20407 * Returns: 20408 * BCM_E_XXX 20409 */ 20410 int 20411 bcm_kt2_port_priority_group_mapping_set(int unit, bcm_gport_t gport, 20412 int prio, int priority_group) 20413 { 20414 bcm_port_t port; 20415 uint32 old_reg0, old_reg1, new_reg0, new_reg1, temp = 0x7; 20416 int old_profile_index, new_profile_index, free_profile_index = -1; 20417 uint64 rval64; 20418 int old_pg = 0x7, new_pg = priority_group; 20419 soc_field_t sb2_srcport_field_names[SB2_MAX_LOGICAL_PORTS]={ 20420 SRCPORT_0f, 20421 SRCPORT_1f, SRCPORT_2f, SRCPORT_3f, SRCPORT_4f, 20422 SRCPORT_5f, SRCPORT_6f, SRCPORT_7f, SRCPORT_8f, 20423 SRCPORT_9f, SRCPORT_10f, SRCPORT_11f, SRCPORT_12f, 20424 SRCPORT_13f, SRCPORT_14f, SRCPORT_15f, SRCPORT_16f, 20425 SRCPORT_17f, SRCPORT_18f, SRCPORT_19f, SRCPORT_20f, 20426 SRCPORT_21f, SRCPORT_22f, SRCPORT_23f, SRCPORT_24f, 20427 SRCPORT_25f, SRCPORT_26f, SRCPORT_27f, SRCPORT_28f, 20428 SRCPORT_29f 20429 }; 20430 20431 /* PFC : 0-7, SAFC : 0-15. Taking the larger range for comparison */ 20432 if ((prio < KT2_SAFC_INPUT_PRIORITY_MIN) || 20433 (prio > KT2_SAFC_INPUT_PRIORITY_MAX)) { 20434 return BCM_E_PARAM; 20435 } 20436 20437 if ((priority_group < KT2_PRIOROTY_GROUP_ID_MIN) || 20438 (priority_group > KT2_PRIOROTY_GROUP_ID_MAX)) { 20439 return BCM_E_PARAM; 20440 } 20441 20442 BCM_IF_ERROR_RETURN(_bcm_kt2_cosq_localport_resolve(unit, gport, &port)); 20443 if ((SB2_MAX_PHYSICAL_PORTS <= port) || 20444 !_bcm_kt2_port_pfc_supported(unit, port)) { 20445 return BCM_E_PORT; 20446 } 20447 /* Get the profile index and correponding profile for the port */ 20448 BCM_IF_ERROR_RETURN(_bcm_kt2_get_port_profile_index(unit, port, &old_profile_index)); 20449 BCM_IF_ERROR_RETURN(_bcm_kt2_get_pg_profile_mapping(unit, old_profile_index, 20450 &old_reg0, &old_reg1)); 20451 if (prio < 8) { 20452 old_pg = ((old_pg << (prio * 3)) & old_reg0) >> (prio * 3); 20453 } else { 20454 old_pg = ((old_pg << ((prio - 8) * 3)) & old_reg1) >> ((prio - 8) * 3); 20455 } 20456 if (pg_profile_refcount[unit][old_profile_index] == 1) { 20457 free_profile_index = old_profile_index; 20458 } 20459 if (prio < 8) { 20460 temp = temp << (prio * 3); 20461 temp = ~temp; 20462 temp = old_reg0 & temp; 20463 temp = temp | (priority_group << (prio * 3)); 20464 for (new_profile_index = 0; new_profile_index < 4; new_profile_index ++) { 20465 if (pg_profile_refcount[unit][new_profile_index] != 0) { 20466 BCM_IF_ERROR_RETURN(_bcm_kt2_get_pg_profile_mapping(unit, 20467 new_profile_index, 20468 &new_reg0, &new_reg1)); 20469 if ((new_reg0 == temp) && (new_reg1 == old_reg1)) { 20470 break; 20471 } 20472 } else { 20473 if (free_profile_index == -1) { 20474 free_profile_index = new_profile_index; 20475 } 20476 } 20477 } 20478 if ((new_profile_index == 4) && (free_profile_index == -1)) { 20479 return BCM_E_RESOURCE; 20480 } 20481 } else { 20482 temp = temp << ((prio - 8) * 3); 20483 temp = ~temp; 20484 temp = old_reg1 & temp; 20485 temp = temp | (priority_group << ((prio - 8) * 3)); 20486 for (new_profile_index = 0; new_profile_index < 4; new_profile_index ++) { 20487 if (pg_profile_refcount[unit][new_profile_index] != 0) { 20488 BCM_IF_ERROR_RETURN(_bcm_kt2_get_pg_profile_mapping(unit, 20489 new_profile_index, 20490 &new_reg0, &new_reg1)); 20491 if ((new_reg1 == temp) && (new_reg0 == old_reg0)) { 20492 break; 20493 } 20494 } else { 20495 if (free_profile_index == -1) { 20496 free_profile_index = new_profile_index; 20497 } 20498 } 20499 } 20500 if ((new_profile_index == 4) && (free_profile_index == -1)) { 20501 return BCM_E_RESOURCE; 20502 } 20503 20504 } 20505 /* We reached here either because of an existing profile match or a free profile */ 20506 if (new_profile_index == 4) { 20507 new_profile_index = free_profile_index; 20508 if (prio < 8) { 20509 new_reg0 = temp; 20510 new_reg1 = old_reg1; 20511 } else { 20512 new_reg0 = old_reg0; 20513 new_reg1 = temp; 20514 } 20515 } 20516 /* 20517 * For dynamic configuration we need to check status of pgs before 20518 * updating it. 20519 */ 20520 BCM_IF_ERROR_RETURN(_bcm_kt2_check_port_pg_status(unit, port, new_pg, old_pg)); 20521 20522 SOC_IF_ERROR_RETURN( 20523 READ_MMU_ENQ_IP_PRI_TO_PG_PROFILE_0r(unit, &rval64)); 20524 BCM_IF_ERROR_RETURN(_bcm_kt2_set_pg_profile_mapping(unit, new_profile_index, 20525 new_reg0, new_reg1)); 20526 if (soc_reg_field_valid(unit, MMU_ENQ_IP_PRI_TO_PG_PROFILE_0r, 20527 sb2_srcport_field_names[port])) { 20528 soc_reg64_field32_set(unit, MMU_ENQ_IP_PRI_TO_PG_PROFILE_0r, 20529 &rval64, sb2_srcport_field_names[port], 20530 new_profile_index); 20531 } 20532 SOC_IF_ERROR_RETURN( 20533 WRITE_MMU_ENQ_IP_PRI_TO_PG_PROFILE_0r(unit, rval64)); 20534 20535 BCM_IF_ERROR_RETURN( 20536 _bcm_kt2_config_all_pg_profile_register(unit, port)); 20537 /* Now update refcount */ 20538 pg_profile_refcount[unit][old_profile_index] = pg_profile_refcount[unit][old_profile_index] - 1; 20539 pg_profile_refcount[unit][new_profile_index] = pg_profile_refcount[unit][new_profile_index] + 1; 20540 20541 return BCM_E_NONE; 20542 } 20543 20544 /* 20545 * Function: 20546 * bcm_kt2_port_priority_group_mapping_get 20547 * Purpose: 20548 * Return Priority Group for the input priority. 20549 * Parameters: 20550 * unit - (IN) device id. 20551 * gport - (IN) generic port. 20552 * prio - (IN) input priority. 20553 * priority_group - (OUT) priority group ID that the input priority mapped to. 20554 * Returns: 20555 * BCM_E_XXX 20556 */ 20557 int 20558 bcm_kt2_port_priority_group_mapping_get(int unit, bcm_gport_t gport, 20559 int prio, int *priority_group) 20560 { 20561 bcm_port_t port; 20562 uint32 reg0, reg1,temp = 0x7; 20563 int profile_index; 20564 20565 /* PFC : 0-7, SAFC : 0-15. Taking the larger range for comparison */ 20566 if ((prio < KT2_SAFC_INPUT_PRIORITY_MIN) || 20567 (prio > KT2_SAFC_INPUT_PRIORITY_MAX)) { 20568 return BCM_E_PARAM; 20569 } 20570 20571 if (priority_group == NULL) { 20572 return BCM_E_PARAM; 20573 } 20574 20575 BCM_IF_ERROR_RETURN(_bcm_kt2_cosq_localport_resolve(unit, gport, &port)); 20576 if ((SB2_MAX_PHYSICAL_PORTS <= port) || 20577 !_bcm_kt2_port_pfc_supported(unit, port)) { 20578 return BCM_E_PORT; 20579 } 20580 /* Get the profile index and correponding profile for the port */ 20581 BCM_IF_ERROR_RETURN(_bcm_kt2_get_port_profile_index(unit, port, &profile_index)); 20582 BCM_IF_ERROR_RETURN(_bcm_kt2_get_pg_profile_mapping(unit, profile_index, 20583 ®0, ®1)); 20584 if (prio < 8) { 20585 temp = temp << (prio * 3); 20586 temp = reg0 & temp; 20587 temp = temp >> (prio * 3); 20588 *priority_group = temp; 20589 } else { 20590 temp = temp << ((prio - 8) * 3); 20591 temp = reg1 & temp; 20592 temp = temp >> ((prio - 8) * 3); 20593 } 20594 *priority_group = temp; 20595 return BCM_E_NONE; 20596 } 20597 #endif 20598 20599 STATIC int 20600 _bcm_kt2_dump_config(int unit, bcm_port_t port, 20601 _bcm_kt2_cosq_node_t *node) 20602 { 20603 int num_spri, first_child, first_mc_child; 20604 uint32 spmap, ucmap; 20605 soc_kt2_sched_mode_e sched_mode = SOC_KT2_SCHED_MODE_UNKNOWN; 20606 int wt = 0; 20607 char *lvl_name[] = { "Root", "S0", "S1", "L0", "L1", "L2" }; 20608 char *sched_modes[] = {"X", "SP", "WRR", "WDRR"}; 20609 int subport = 0; 20610 uint32 entry[SOC_MAX_MEM_WORDS]; 20611 soc_info_t *si; 20612 int physical_port; 20613 bcm_gport_t pp_port; 20614 _bcm_kt2_subport_info_t info; 20615 soc_kt2_sched_mode_e mode = 0; 20616 int rv = BCM_E_NONE; 20617 int soc_node_level = node->level; 20618 int is_mc_queue; 20619 20620 si = &SOC_INFO(unit); 20621 if ((!(SOC_PBMP_MEMBER(si->linkphy_pbm, port))) && 20622 (node->level != _BCM_KT2_COSQ_NODE_LEVEL_ROOT)) { 20623 /* KT2 soc level does not include S0 and S1 */ 20624 soc_node_level = soc_node_level - 2; 20625 } 20626 20627 /* get sched config */ 20628 if (node->level != _BCM_KT2_COSQ_NODE_LEVEL_L2) { 20629 SOC_IF_ERROR_RETURN( 20630 soc_kt2_sched_get_node_config(unit, port, 20631 soc_node_level, node->hw_index, 20632 &num_spri, &first_child, 20633 &first_mc_child, &ucmap, &spmap)); 20634 20635 } 20636 sched_mode = 0; 20637 if (node->level != _BCM_KT2_COSQ_NODE_LEVEL_ROOT) { 20638 SOC_IF_ERROR_RETURN( 20639 soc_kt2_cosq_get_sched_mode(unit, port, soc_node_level, 20640 node->hw_index, &sched_mode, &wt)); 20641 } 20642 20643 if (wt && SOC_PBMP_MEMBER(si->linkphy_pbm, port)) { 20644 20645 /* Re-write the node info if num_streams is 1 */ 20646 if (node->level == _BCM_KT2_COSQ_NODE_LEVEL_S0) { 20647 BCM_IF_ERROR_RETURN 20648 (_bcm_kt2_cosq_subport_get(unit, node->gport, &pp_port)); 20649 BCM_IF_ERROR_RETURN 20650 (bcm_kt2_subport_pp_port_subport_info_get(unit, pp_port, 20651 &info)); 20652 if (info.num_streams == 1) { 20653 first_child = node->hw_index; 20654 num_spri = 1; 20655 spmap = 1; 20656 rv = soc_kt2_cosq_s0_sched_get(unit, node->hw_index, &mode); 20657 if (rv == BCM_E_NONE) { 20658 num_spri = (mode == SOC_KT2_SCHED_MODE_STRICT) ? 1 : 0; 20659 spmap = (mode == SOC_KT2_SCHED_MODE_STRICT) ? 1 : 0; 20660 } 20661 20662 #ifdef BCM_METROLITE_SUPPORT 20663 if(SOC_IS_METROLITE(unit)) { 20664 first_child = node->first_child; 20665 } 20666 #endif 20667 } else { 20668 rv = soc_kt2_cosq_s0_sched_get(unit, node->hw_index, &mode); 20669 if (rv == BCM_E_NONE) { 20670 num_spri = (mode == SOC_KT2_SCHED_MODE_STRICT) ? 2 : 0; 20671 spmap = (mode == SOC_KT2_SCHED_MODE_STRICT) ? 3 : 0; 20672 } 20673 } 20674 } 20675 20676 if (_bcm_is_port_linkphy_subport(unit, port, -1)) { 20677 SOC_IF_ERROR_RETURN(_bcm_subport_physical_port_get(unit, port, &physical_port)); 20678 20679 SOC_IF_ERROR_RETURN( 20680 soc_mem_read(unit, LLS_PORT_CONFIGm, MEM_BLOCK_ALL, physical_port, &entry)); 20681 if (soc_mem_field32_get(unit, LLS_PORT_CONFIGm, entry, PACKET_MODE_WRR_ACCOUNTING_ENABLEf)) { 20682 sched_mode = SOC_KT2_SCHED_MODE_WRR; 20683 } else { 20684 sched_mode = SOC_KT2_SCHED_MODE_WDRR; 20685 } 20686 } 20687 } 20688 switch (node->level) { 20689 case _BCM_KT2_COSQ_NODE_LEVEL_ROOT: 20690 case _BCM_KT2_COSQ_NODE_LEVEL_S1: 20691 case _BCM_KT2_COSQ_NODE_LEVEL_L0: 20692 case _BCM_KT2_COSQ_NODE_LEVEL_L1: 20693 LOG_CLI((BSL_META_U(unit, 20694 " %s.%d : INDEX=%d NUM_SP=%d FC=%d FMC=%d " 20695 "UCMAP=0x%08x SPMAP=0x%08x MODE=%s WT=%d\n"), 20696 lvl_name[node->level], node->cosq_attached_to, 20697 node->hw_index, num_spri, 20698 first_child, first_mc_child, ucmap, spmap, 20699 sched_modes[sched_mode], wt)); 20700 break; 20701 case _BCM_KT2_COSQ_NODE_LEVEL_S0: 20702 BCM_IF_ERROR_RETURN 20703 (_bcm_kt2_cosq_subport_get(unit, node->gport, &subport)); 20704 LOG_CLI((BSL_META_U(unit, 20705 "-------%s subport %d (LLS)------\n"),SOC_PORT_NAME(unit, 20706 (port)), subport)); 20707 LOG_CLI((BSL_META_U(unit, 20708 " %s.%d : INDEX=%d NUM_SP=%d FC=%d FMC=%d " 20709 "UCMAP=0x%08x SPMAP=0x%08x MODE=%s WT=%d\n"), 20710 lvl_name[node->level], node->cosq_attached_to, 20711 node->hw_index, num_spri, 20712 first_child, first_mc_child, ucmap, spmap, 20713 sched_modes[sched_mode], wt)); 20714 break; 20715 case _BCM_KT2_COSQ_NODE_LEVEL_L2: 20716 is_mc_queue = BCM_GPORT_IS_MCAST_QUEUE_GROUP(node->gport) || 20717 BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(node->gport); 20718 LOG_CLI((BSL_META_U(unit, 20719 " L2.%d.%s INDEX=%d Mode=%s WEIGHT=%d\n"), 20720 node->cosq_attached_to, 20721 is_mc_queue?"mc":"uc", 20722 node->hw_index, 20723 sched_modes[sched_mode], wt)); 20724 break; 20725 default: 20726 return BCM_E_INTERNAL; 20727 20728 } 20729 return BCM_E_NONE; 20730 } 20731 20732 STATIC int 20733 _bcm_kt2_dump_sched(int unit, bcm_port_t port, bcm_gport_t gport) 20734 { 20735 _bcm_kt2_cosq_node_t *node; 20736 _bcm_kt2_cosq_node_t *cur_node; 20737 int i = 0; 20738 int start_cos = 0; 20739 int end_cos = 0; 20740 20741 BCM_IF_ERROR_RETURN 20742 (_bcm_kt2_cosq_node_get(unit, gport, NULL, NULL, NULL, &node)); 20743 20744 if (node != NULL) { 20745 if (node->level == _BCM_KT2_COSQ_NODE_LEVEL_L2) { 20746 return BCM_E_INTERNAL; 20747 } 20748 20749 start_cos = 0; 20750 end_cos = node->numq; 20751 _bcm_kt2_dump_config(unit, port, node); 20752 20753 for (i = start_cos; i < end_cos; i++) 20754 { 20755 if(_bcm_kt2_cosq_child_node_at_input(node, i, &cur_node) 20756 == BCM_E_NOT_FOUND) { 20757 continue; 20758 } 20759 if (cur_node->level == _BCM_KT2_COSQ_NODE_LEVEL_L2) { 20760 BCM_IF_ERROR_RETURN 20761 (_bcm_kt2_dump_config(unit, port, cur_node)); 20762 } else { 20763 BCM_IF_ERROR_RETURN 20764 (_bcm_kt2_dump_sched(unit, port, cur_node->gport)); 20765 } 20766 } 20767 } 20768 return BCM_E_NONE; 20769 20770 } 20771 20772 STATIC int 20773 _bcm_kt2_cosq_cpu_fc_set(int unit) 20774 { 20775 bcm_pbmp_t pbmp_linkphy; 20776 uint32 rval; 20777 uint32 cos_bmp_value = 0; 20778 uint64 lls_l2; 20779 uint32 l2_mask=0; 20780 20781 pbmp_linkphy = soc_property_get_pbmp(unit, spn_PBMP_LINKPHY, 0); 20782 BCM_IF_ERROR_RETURN(READ_LLS_FC_CONFIGr(unit, &rval)); 20783 20784 /* Allows CMIC Cosmask flow control to update the 20785 * XON-XOFF state for those queues 47:0 */ 20786 soc_reg_field_set(unit, LLS_FC_CONFIGr, &rval, FC_CFG_DISABLE_L2_COSMASK_XOFFf, 0); 20787 20788 if (!SOC_IS_METROLITE(unit) && BCM_PBMP_NOT_NULL(pbmp_linkphy)) { 20789 soc_reg_field_set(unit, LLS_FC_CONFIGr, &rval, FC_CFG_COSMASK_L0_MAPf, 2); 20790 } else { 20791 soc_reg_field_set(unit, LLS_FC_CONFIGr, &rval, FC_CFG_COSMASK_L0_MAPf, 1); 20792 } 20793 BCM_IF_ERROR_RETURN(WRITE_LLS_FC_CONFIGr(unit, rval)); 20794 20795 COMPILER_64_ZERO(lls_l2); 20796 BCM_IF_ERROR_RETURN 20797 (soc_mem_read(unit, LLS_L2_XOFFm, MEM_BLOCK_ANY, 0, &lls_l2)); 20798 l2_mask = COMPILER_64_HI(lls_l2); 20799 l2_mask &= 0xffff0000; 20800 COMPILER_64_SET(lls_l2, l2_mask, 0); 20801 BCM_IF_ERROR_RETURN(soc_mem_write(unit, LLS_L2_XOFFm, MEM_BLOCK_ALL, 0, &lls_l2)); 20802 20803 cos_bmp_value = 0; 20804 cos_bmp_value |= (1 << 16); 20805 rval = 0; 20806 BCM_IF_ERROR_RETURN(READ_CMIC_CMC0_CH1_COS_CTRL_RX_1r(unit, &rval)); 20807 soc_reg_field_set(unit, CMIC_CMC0_CH1_COS_CTRL_RX_1r, &rval, COS_BMPf, cos_bmp_value); 20808 WRITE_CMIC_CMC0_CH1_COS_CTRL_RX_1r(unit, rval); 20809 20810 BCM_IF_ERROR_RETURN(READ_CMIC_CMC0_CH2_COS_CTRL_RX_1r(unit, &rval)); 20811 soc_reg_field_set(unit, CMIC_CMC0_CH2_COS_CTRL_RX_1r, &rval, COS_BMPf, cos_bmp_value); 20812 WRITE_CMIC_CMC0_CH2_COS_CTRL_RX_1r(unit, rval); 20813 20814 BCM_IF_ERROR_RETURN(READ_CMIC_CMC0_CH3_COS_CTRL_RX_1r(unit, &rval)); 20815 soc_reg_field_set(unit, CMIC_CMC0_CH3_COS_CTRL_RX_1r, &rval, COS_BMPf, cos_bmp_value); 20816 WRITE_CMIC_CMC0_CH3_COS_CTRL_RX_1r(unit, rval); 20817 20818 cos_bmp_value = 0; 20819 cos_bmp_value |= (1 << 17); 20820 rval = 0; 20821 BCM_IF_ERROR_RETURN(READ_CMIC_CMC1_CH1_COS_CTRL_RX_1r(unit, &rval)); 20822 soc_reg_field_set(unit, CMIC_CMC1_CH1_COS_CTRL_RX_1r, &rval, COS_BMPf, cos_bmp_value); 20823 WRITE_CMIC_CMC1_CH1_COS_CTRL_RX_1r(unit, rval); 20824 20825 cos_bmp_value = 0; 20826 cos_bmp_value |= (1 << 18); 20827 rval = 0; 20828 BCM_IF_ERROR_RETURN(READ_CMIC_CMC2_CH1_COS_CTRL_RX_1r(unit, &rval)); 20829 soc_reg_field_set(unit, CMIC_CMC2_CH1_COS_CTRL_RX_1r, &rval, COS_BMPf, cos_bmp_value); 20830 WRITE_CMIC_CMC2_CH1_COS_CTRL_RX_1r(unit, rval); 20831 20832 /* SABER2 has 2 channels mapped to one CMC2 */ 20833 if (SOC_IS_SABER2(unit)) { 20834 cos_bmp_value = 0; 20835 cos_bmp_value |= (1 << 18); 20836 rval = 0; 20837 BCM_IF_ERROR_RETURN(READ_CMIC_CMC2_CH3_COS_CTRL_RX_1r(unit, &rval)); 20838 soc_reg_field_set(unit, CMIC_CMC2_CH3_COS_CTRL_RX_1r, &rval, COS_BMPf, cos_bmp_value); 20839 WRITE_CMIC_CMC2_CH3_COS_CTRL_RX_1r(unit, rval); 20840 } 20841 20842 return BCM_E_NONE; 20843 } 20844 20845 STATIC int 20846 _bcm_kt2_dump_port_lls(int unit, bcm_port_t port) 20847 { 20848 _bcm_kt2_cosq_node_t *port_info; 20849 _bcm_kt2_mmu_info_t *mmu_info; 20850 bcm_port_t port_out; 20851 20852 if (_bcm_kt2_mmu_info[unit] == NULL) { 20853 return BCM_E_INIT; 20854 } 20855 mmu_info = _bcm_kt2_mmu_info[unit]; 20856 20857 BCM_IF_ERROR_RETURN 20858 (_bcm_kt2_cosq_localport_resolve(unit, port, &port_out)); 20859 20860 /* root node */ 20861 port_info = &mmu_info->sched_node[port_out]; 20862 20863 if (port_info->gport >= 0) { 20864 _bcm_kt2_dump_sched(unit, port, port_info->gport); 20865 } 20866 return BCM_E_NONE; 20867 } 20868 20869 20870 int bcm_kt2_dump_port_lls(int unit, bcm_port_t port) 20871 { 20872 20873 LOG_CLI((BSL_META_U(unit, 20874 "-------%s (LLS)------\n"), SOC_PORT_NAME(unit, (port)))); 20875 _bcm_kt2_dump_port_lls(unit, port); 20876 return SOC_E_NONE; 20877 } 20878 20879 20880 #ifndef BCM_SW_STATE_DUMP_DISABLE 20881 20882 STATIC int 20883 _bcm_kt2_cosq_node_info_dump(int unit, _bcm_kt2_cosq_node_t *node) 20884 { 20885 LOG_CLI((BSL_META_U(unit, 20886 "base = %d mc_base_index = %d numq = %d hw_index = %d \n"), 20887 node->base_index, node->mc_base_index, node->numq, node->hw_index)); 20888 LOG_CLI((BSL_META_U(unit, 20889 "level = %d cosq_attach = %d \n"), 20890 node->level, node->cosq_attached_to)); 20891 LOG_CLI((BSL_META_U(unit, 20892 "num_child = %d first_child = %d wrr_in_use = %d \n"), 20893 node->num_child, node->first_child, 20894 node->wrr_in_use)); 20895 LOG_CLI((BSL_META_U(unit, 20896 "subport_enabled = %d linkphy_enabled = %d \n"), 20897 node->subport_enabled, 20898 node->linkphy_enabled)); 20899 if (node->parent != NULL) { 20900 LOG_CLI((BSL_META_U(unit, 20901 " parent gport = 0x%08x\n"), node->parent->gport)); 20902 } 20903 if (node->sibling != NULL) { 20904 LOG_CLI((BSL_META_U(unit, 20905 " sibling gport = 0x%08x\n"), node->sibling->gport)); 20906 } 20907 if (node->child != NULL) { 20908 LOG_CLI((BSL_META_U(unit, 20909 " child gport = 0x%08x\n"), node->child->gport)); 20910 } 20911 20912 return BCM_E_NONE; 20913 } 20914 20915 STATIC int 20916 _bcm_kt2_cosq_l0_tree_dump(int unit, _bcm_kt2_cosq_node_t *node) 20917 { 20918 _bcm_kt2_cosq_node_t *l0_node, *l1_node, *l2_node; 20919 20920 for (l0_node = node; l0_node != NULL; 20921 l0_node = l0_node->sibling) { 20922 LOG_CLI((BSL_META_U(unit, 20923 "=== L0 gport 0x%08x\n"), l0_node->gport)); 20924 BCM_IF_ERROR_RETURN 20925 (_bcm_kt2_cosq_node_info_dump(unit, l0_node)); 20926 20927 for (l1_node = l0_node->child; l1_node != NULL; 20928 l1_node = l1_node->sibling) { 20929 LOG_CLI((BSL_META_U(unit, 20930 "=== L1 gport 0x%08x\n"), l1_node->gport)); 20931 BCM_IF_ERROR_RETURN 20932 (_bcm_kt2_cosq_node_info_dump(unit, l1_node)); 20933 20934 for (l2_node = l1_node->child; l2_node != NULL; 20935 l2_node = l2_node->sibling) { 20936 LOG_CLI((BSL_META_U(unit, 20937 "=== L2 gport 0x%08x\n"), l2_node->gport)); 20938 BCM_IF_ERROR_RETURN 20939 (_bcm_kt2_cosq_node_info_dump(unit, l2_node)); 20940 } 20941 } 20942 } 20943 20944 return BCM_E_NONE; 20945 } 20946 20947 STATIC int 20948 _bcm_kt2_cosq_port_info_dump(int unit, bcm_port_t port) 20949 { 20950 _bcm_kt2_mmu_info_t *mmu_info; 20951 _bcm_kt2_cosq_node_t *port_node = NULL; 20952 _bcm_kt2_cosq_node_t *l0_node = NULL; 20953 _bcm_kt2_cosq_node_t *s0_node = NULL; 20954 _bcm_kt2_cosq_node_t *s1_node = NULL; 20955 20956 if (!SOC_PORT_VALID(unit, port)) { 20957 return BCM_E_PORT; 20958 } 20959 20960 mmu_info = _bcm_kt2_mmu_info[unit]; 20961 20962 /* get the root node */ 20963 port_node = &mmu_info->sched_node[port]; 20964 20965 if (port_node && port_node->cosq_attached_to < 0) { 20966 return BCM_E_NONE; 20967 } 20968 20969 LOG_CLI((BSL_META_U(unit, 20970 "=== port %d\n"), port)); 20971 BCM_IF_ERROR_RETURN 20972 (_bcm_kt2_cosq_node_info_dump(unit, port_node)); 20973 20974 s0_node = port_node->child; 20975 if (s0_node != NULL && 20976 s0_node->level == _BCM_KT2_COSQ_NODE_LEVEL_S0) { 20977 for (s0_node = port_node->child; s0_node != NULL; 20978 s0_node = s0_node->sibling) { 20979 LOG_CLI((BSL_META_U(unit, 20980 "=== S0 gport 0x%08x\n"), s0_node->gport)); 20981 BCM_IF_ERROR_RETURN 20982 (_bcm_kt2_cosq_node_info_dump(unit, s0_node)); 20983 20984 s1_node = s0_node->child; 20985 if (s1_node != NULL && 20986 s1_node->level == _BCM_KT2_COSQ_NODE_LEVEL_S1) { 20987 for (s1_node = s0_node->child; s1_node != NULL; 20988 s1_node = s1_node->sibling) { 20989 LOG_CLI((BSL_META_U(unit, 20990 "=== S1 gport 0x%08x\n"), s1_node->gport)); 20991 BCM_IF_ERROR_RETURN 20992 (_bcm_kt2_cosq_node_info_dump(unit, s1_node)); 20993 for (l0_node = s1_node->child; l0_node != NULL; 20994 l0_node = l0_node->sibling) { 20995 BCM_IF_ERROR_RETURN 20996 (_bcm_kt2_cosq_l0_tree_dump(unit, l0_node)); 20997 } 20998 } 20999 } else { 21000 l0_node = s1_node; 21001 BCM_IF_ERROR_RETURN 21002 (_bcm_kt2_cosq_l0_tree_dump(unit, l0_node)); 21003 } 21004 } 21005 } else { 21006 l0_node = port_node->child; 21007 BCM_IF_ERROR_RETURN 21008 (_bcm_kt2_cosq_l0_tree_dump(unit, l0_node)); 21009 } 21010 21011 return BCM_E_NONE; 21012 } 21013 21014 /* 21015 * Function: 21016 * bcm_kt2_cosq_sw_dump 21017 * Purpose: 21018 * Displays COS Queue information maintained by software. 21019 * Parameters: 21020 * unit - Device unit number 21021 * Returns: 21022 * None 21023 */ 21024 void 21025 bcm_kt2_cosq_sw_dump(int unit) 21026 { 21027 _bcm_kt2_mmu_info_t *mmu_info; 21028 bcm_port_t port; 21029 int i; 21030 21031 mmu_info = _bcm_kt2_mmu_info[unit]; 21032 21033 LOG_CLI((BSL_META_U(unit, 21034 "\nSW Information COSQ - Unit %d\n"), unit)); 21035 21036 for (port = 0; port <= KT2_LPBK_PORT; port++) { 21037 (void)_bcm_kt2_cosq_port_info_dump(unit, port); 21038 } 21039 21040 LOG_CLI((BSL_META_U(unit, 21041 "global_qlist = %d \n"), mmu_info->global_qlist.count)); 21042 LOG_CLI((BSL_META_U(unit, 21043 "sched_list = %d \n"), mmu_info->sched_list.count)); 21044 LOG_CLI((BSL_META_U(unit, 21045 "l2_base_qlist = %d \n"), mmu_info->l2_base_qlist.count)); 21046 LOG_CLI((BSL_META_U(unit, 21047 "l2_base_mcqlist = %d \n"), mmu_info->l2_base_mcqlist.count)); 21048 LOG_CLI((BSL_META_U(unit, 21049 "l2_global_qlist = %d \n"), mmu_info->l2_global_qlist.count)); 21050 21051 for (i = 0; i < _BCM_KT2_COSQ_NODE_LEVEL_MAX; i++) { 21052 LOG_CLI((BSL_META_U(unit, 21053 "Level %d count = %d \n"), 21054 i, mmu_info->sched_hw_list[i].count)); 21055 } 21056 21057 return; 21058 } 21059 #endif /* BCM_SW_STATE_DUMP_DISABLE */ 21060 21061 #else /* BCM_KATANA2_SUPPORT */ 21062 int _kt2_cosq_not_empty; 21063 #endif /* BCM_KATANA2_SUPPORT */