cosq.c (745398B)
1 /* 2 * 3 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 4 * 5 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 6 * 7 * COS Queue Management 8 * Purpose: API to set different cosq, priorities, and scheduler registers. 9 */ 10 11 #include <shared/bsl.h> 12 13 #include <soc/defs.h> 14 #include <sal/core/libc.h> 15 16 #if defined(BCM_MONTEREY_SUPPORT) 17 #include <soc/drv.h> 18 #include <soc/scache.h> 19 #include <soc/profile_mem.h> 20 #include <soc/l3x.h> 21 22 #include <soc/trident2.h> 23 #include <soc/monterey.h> 24 25 26 #include <bcm/error.h> 27 #include <bcm/cosq.h> 28 #include <bcm_int/esw/mbcm.h> 29 #include <bcm_int/esw/stack.h> 30 #include <bcm_int/esw/cosq.h> 31 #include <bcm_int/esw/virtual.h> 32 #include <bcm_int/esw/apache.h> 33 #include <bcm_int/esw/monterey.h> 34 #include <bcm_int/esw/oob.h> 35 #include <bcm_int/esw/trx.h> 36 37 #include <bcm_int/esw_dispatch.h> 38 39 #include <bcm_int/bst.h> 40 #include <bcm_int/common/lock.h> 41 42 #include <bcm/subport.h> 43 #include <bcm_int/esw/xgs5.h> 44 #include <bcm_int/esw/switch.h> 45 46 /* COS max value for MN is 10 */ 47 #define BCM_MN_COS_MAX 10 48 49 #define AP_CELL_FIELD_MAX 0x1ffff 50 #define _BCM_PORT_SERVICE_POOL 768 51 #define _BCM_WRED_GLOBAL_SERVICE_POOL 1036 52 #define IS_SPECIAL_PORT(unit, port) (IS_CPU_PORT(unit, port) || \ 53 IS_LB_PORT(unit, port) || IS_MACSEC_PORT(unit, port)) 54 /* MMU cell size in bytes */ 55 #define _BCM_MN_BYTES_PER_CELL 208 /* bytes */ 56 #define _BCM_MN_BYTES_TO_CELLS(_byte_) \ 57 (((_byte_) + _BCM_MN_BYTES_PER_CELL - 1) / _BCM_MN_BYTES_PER_CELL) 58 #define _BCM_MN_NUM_PIPES 1 59 #define _BCM_MN_NUM_PORT_SCHEDULERS 76 60 #define _BCM_MN_NUM_S1_SCHEDULER_PER_PIPE 328 61 #define _BCM_MN_NUM_L0_SCHEDULER_PER_PIPE 1024 62 #define _BCM_MN_NUM_L0_SCHEDULER _BCM_MN_NUM_L0_SCHEDULER_PER_PIPE * _BCM_MN_NUM_PIPES 63 #define _BCM_MN_NUM_L1_SCHEDULER_PER_PIPE 4224 /* Reserved for default val */ 64 #define _BCM_MN_NUM_L1_SCHEDULER _BCM_MN_NUM_L1_SCHEDULER_PER_PIPE * _BCM_MN_NUM_PIPES 65 #define _BCM_MN_NUM_L2_UC_LEAVES_PER_PIPE 640 /* Reserved for default val */ 66 #define _BCM_MN_NUM_L2_UC_LEAVES _BCM_MN_NUM_L2_UC_LEAVES_PER_PIPE * _BCM_MN_NUM_PIPES 67 #define _BCM_MN_NUM_L2_MC_LEAVES_PER_PIPE 708 68 #define _BCM_MN_NUM_L2_MC_LEAVES _BCM_MN_NUM_L2_MC_LEAVES_PER_PIPE * _BCM_MN_NUM_PIPES 69 #define _BCM_MN_NUM_L2_LEAVES_PER_PIPE (_BCM_MN_NUM_L2_MC_LEAVES_PER_PIPE + \ 70 _BCM_MN_NUM_L2_UC_LEAVES_PER_PIPE) 71 #define _BCM_MN_NUM_L2_LEAVES _BCM_MN_NUM_L2_LEAVES_PER_PIPE * _BCM_MN_NUM_PIPES 72 #define _BCM_MN_NUM_TOTAL_SCHEDULERS (_BCM_MN_NUM_PORT_SCHEDULERS + \ 73 _BCM_MN_NUM_S1_SCHEDULER_PER_PIPE + \ 74 _BCM_MN_NUM_L0_SCHEDULER + \ 75 _BCM_MN_NUM_L1_SCHEDULER) 76 #define _BCM_MN_CPU_COSQ_START 660 77 #define _MN_SPM_ENTRIES_PER_SET 128 78 #define _MN_VPM_ENTRIES_PER_SET 128 79 #define _MN_SCM_ENTRIES_PER_SET 16 80 81 #define _BCM_MN_LLS_DYN_CHG_REG_B 0x3FFF 82 #define _BCM_MN_LLS_DYN_CHG_REG_C 0xFFFFFFFF 83 84 /* All CPU leaves Ranges from 17114-17161.*/ 85 #define _BCM_MN_NUM_L2_CPU_LEAVES 48 86 /* All Lb leaves Ranges from 17104-17111.*/ 87 #define _BCM_MN_NUM_L2_LB_LEAVES 8 88 89 #define _MN_NUM_COS NUM_COS 90 #define _MN_NUM_INTERNAL_PRI 16 91 92 #define _BCM_MN_NUM_PFC_CLASS 8 93 #define _BCM_MN_NUM_SAFC_CLASS 16 94 #define _BCM_MN_COSQ_LIST_NODE_INIT(list, node) \ 95 list[node].in_use = FALSE; \ 96 list[node].gport = -1; \ 97 list[node].base_index = -1; \ 98 list[node].numq = 0; \ 99 list[node].base_size = 0; \ 100 list[node].numq_expandable = 0; \ 101 list[node].hw_index = -1; \ 102 list[node].level = -1; \ 103 list[node].attached_to_input = -1; \ 104 list[node].hw_cosq = 0; \ 105 list[node].remote_modid = -1; \ 106 list[node].remote_port = -1; \ 107 list[node].cosq_map = NULL; \ 108 BCM_PBMP_CLEAR(list[node].fabric_pbmp); \ 109 list[node].local_port = -1; \ 110 list[node].parent = NULL; \ 111 list[node].sibling = NULL; \ 112 list[node].child = NULL; \ 113 list[node].coe_base_index = -1; \ 114 list[node].coe_num_l2 = 0; \ 115 list[node].port_gport = -1; 116 117 #define _BCM_MN_COSQ_NODE_INIT(node) \ 118 node->in_use = FALSE; \ 119 node->gport = -1; \ 120 node->base_index = -1; \ 121 node->numq = 0; \ 122 node->base_size = 0; \ 123 node->numq_expandable = 0; \ 124 node->hw_index = -1; \ 125 node->level = -1; \ 126 node->attached_to_input = -1; \ 127 node->hw_cosq = 0; \ 128 node->remote_modid = -1; \ 129 node->remote_port = -1; \ 130 node->cosq_map = NULL; \ 131 BCM_PBMP_CLEAR(node->fabric_pbmp); \ 132 node->local_port = -1; \ 133 node->parent = NULL; \ 134 node->sibling = NULL; \ 135 node->child = NULL; \ 136 node->coe_base_index = -1; \ 137 node->coe_num_l2 = 0; \ 138 node->port_gport = -1; 139 140 typedef enum { 141 _BCM_MN_COSQ_FC_PAUSE = 0, 142 _BCM_MN_COSQ_FC_PFC, 143 _BCM_MN_COSQ_FC_VOQFC, 144 _BCM_MN_COSQ_FC_E2ECC, 145 _BCM_MN_COSQ_FC_SAFC 146 } _bcm_mn_fc_type_t; 147 148 typedef enum { 149 _BCM_MN_NODE_UNKNOWN = 0, 150 _BCM_MN_NODE_UCAST, 151 _BCM_MN_NODE_MCAST, 152 _BCM_MN_NODE_VOQ, 153 _BCM_MN_NODE_VLAN_UCAST, 154 _BCM_MN_NODE_VM_UCAST, 155 _BCM_MN_NODE_SERVICE_UCAST, 156 _BCM_MN_NODE_SCHEDULER 157 } _bcm_mn_node_type_e; 158 159 typedef enum { 160 _BCM_MN_COSQ_STATE_NO_CHANGE, 161 _BCM_MN_COSQ_STATE_DISABLE, 162 _BCM_MN_COSQ_STATE_ENABLE, 163 _BCM_MN_COSQ_STATE_SPRI_TO_WRR, 164 _BCM_MN_COSQ_STATE_WRR_TO_SPRI, 165 _BCM_MN_COSQ_STATE_MAX 166 }_bcm_mn_cosq_state_t; 167 168 typedef struct _bcm_mn_cosq_node_s { 169 struct _bcm_mn_cosq_node_s *parent; 170 struct _bcm_mn_cosq_node_s *sibling; 171 struct _bcm_mn_cosq_node_s *child; 172 bcm_gport_t gport; 173 int in_use; 174 int base_index; 175 uint16 numq_expandable; 176 uint16 base_size; 177 int numq; 178 int hw_index; 179 soc_monterey_node_lvl_e level; 180 _bcm_mn_node_type_e type; 181 int attached_to_input; 182 int hw_cosq; 183 int wrr_in_use; 184 185 /* DPVOQ specific information */ 186 bcm_port_t local_port; 187 bcm_module_t remote_modid; 188 bcm_port_t remote_port; 189 bcm_pbmp_t fabric_pbmp; 190 SHR_BITDCL *cosq_map; 191 int coe_num_l2;/* Number of active l2 queues for the subport*/ 192 /*Used in S1 node to store the base index for that sub port*/ 193 int coe_base_index; 194 /* the port gport the node was created with*/ 195 bcm_gport_t port_gport; 196 }_bcm_mn_cosq_node_t; 197 198 typedef struct _bcm_mn_lls_info_s { 199 int child_lvl; /* level of the node */ 200 int child_hw_index; /* hw index of the node */ 201 int node_count[SOC_MONTEREY_NODE_LVL_MAX]; /* total number of nodes in the lls */ 202 int count[SOC_MONTEREY_NODE_LVL_MAX]; /* number of nodes in each level */ 203 int offset[SOC_MONTEREY_NODE_LVL_MAX]; /* index of the starting node at each level */ 204 205 int kbit_max; /* max speed for the node */ 206 int kbit_min; /* min speed for the node */ 207 208 uint32 *mtro_entries; /* entries to maintain mmu mtro level mem */ 209 } _bcm_mn_lls_info_t; 210 211 typedef struct _bcm_mn_cosq_list_s { 212 int count; 213 SHR_BITDCL *bits; 214 }_bcm_mn_cosq_list_t; 215 216 /* Monterey CPRI and RSVD4 port HSP default shaper setting and service pool mapping */ 217 typedef struct _bcm_mn_mtro_node_info_s { 218 uint32 mode; /* 0 for byte mode and 1 for packet mode */ 219 uint32 refresh_period; 220 uint32 bucket_threshold; 221 uint32 rate; 222 int spid; 223 } _bcm_mn_mtro_node_info_t; 224 225 /* 226 * There are 9 nodes indexed 0-8. index 0 is for L0.1 and index 227 * 1-7 are for L1.1 to L1.7 respectively. Index 8 is for L1.5 in 228 * case this node is in HDLC mode instead of Ethernet mode. 229 */ 230 231 #define _BCM_MN_NUM_CPRI_CONFIG_NODE 9 232 233 STATIC _bcm_mn_mtro_node_info_t mtro0_max_bucket_info[_BCM_MN_NUM_CPRI_CONFIG_NODE] = { 234 {0, 390625, 512, 1000000, 1}, {0, 390625, 256, 119940, 0}, 235 {0, 390625, 256, 119940, 0}, {0, 390625, 256, 119940, 0}, 236 {0, 390625, 256, 119940, 0}, {0, 390625, 256, 337920, 0}, 237 {0, 390625, 256, 122820, 1}, {0, 390625, 256, 32768, 1}, 238 {0, 390625, 256, 7680, 0} 239 }; 240 STATIC _bcm_mn_mtro_node_info_t mtro1_max_bucket_info[_BCM_MN_NUM_CPRI_CONFIG_NODE] = { 241 {0, 390625, 256, 150000, 1}, {0, 390625, 256, 98300, 0}, 242 {0, 390625, 256, 2670, 1}, {0, 390625, 256, 2670, 1}, 243 {0, 390625, 256, 2670, 1}, {0, 390625, 256, 2670, 1}, 244 {0, 390625, 256, 32768, 1}, {0, 390625, 256, 51, 1}, 245 {0, 390625, 256, 2670, 1} 246 }; 247 248 #define _BCM_MN_HSP_PORT_MAX_ROOT 67 249 #define _BCM_MN_HSP_PORT_MAX_L0 5 250 #define _BCM_MN_HSP_PORT_MAX_L1 10 251 #define _BCM_MN_HSP_PORT_MAX_L2 10 252 #define _BCM_MN_HSP_PORT_MAX_L2_PER_L1 2 253 #define _BCM_MN_HSP_PORT_MAX_COS 8 254 255 #define _BCM_MN_CPU_PORT_L0_MIN 1018 256 #define _BCM_MN_CPU_PORT_L0_MAX 1023 257 #define _BCM_MN_MAX_PORT 76 258 259 #define _BCM_MN_ROOT_SCHED_INDEX(u,mmu_port) \ 260 ((mmu_port >= 74) ? (mmu_port - 74) : (mmu_port)) 261 262 #define _BCM_MN_HSP_L0_INDEX(u,mmu_port,cosq) \ 263 ((((mmu_port >= 74) ? (mmu_port - 74) : (mmu_port)) * _BCM_MN_HSP_PORT_MAX_L0) +\ 264 (cosq)) 265 266 #define _BCM_MN_HSP_L1_INDEX(u,mmu_port,cosq) \ 267 ((((mmu_port >= 74) ? (mmu_port - 74) : (mmu_port)) * _BCM_MN_HSP_PORT_MAX_L1) +\ 268 (cosq)) 269 270 #define _BCM_MN_HSP_L2_INDEX(u,mmu_port,cosq) \ 271 ((((mmu_port >= 74) ? (mmu_port - 74) : (mmu_port)) * _BCM_MN_HSP_PORT_MAX_L2) +\ 272 (cosq)) 273 274 275 typedef struct _bcm_mn_pipe_resources_s { 276 int num_base_queues; /* Number of classical queues */ 277 278 _bcm_mn_cosq_list_t l2_queue_list; /* list of l2 queues */ 279 _bcm_mn_cosq_list_t hsp_l2_queue_list; /* list of l2 queues */ 280 _bcm_mn_cosq_list_t l0_sched_list; /* list of l0 sched nodes */ 281 _bcm_mn_cosq_list_t hsp_l0_sched_list; /* list of l0 sched nodes */ 282 _bcm_mn_cosq_list_t cpu_l0_sched_list; /* list of l0 sched nodes */ 283 _bcm_mn_cosq_list_t l1_sched_list; /* list of l1 sched nodes */ 284 _bcm_mn_cosq_list_t hsp_l1_sched_list; /* list of l1 sched nodes */ 285 _bcm_mn_cosq_list_t s1_sched_list; /* list of s1 sched nodes */ 286 287 _bcm_mn_cosq_node_t *p_queue_node; 288 _bcm_mn_cosq_node_t *p_mc_queue_node; 289 } _bcm_mn_pipe_resources_t; 290 291 typedef struct _bcm_mn_cosq_port_info_s { 292 int mc_base; 293 int mc_limit; 294 int uc_base; 295 int uc_limit; 296 int eq_base; 297 int eq_limit; 298 _bcm_mn_pipe_resources_t *resources; 299 } _bcm_mn_cosq_port_info_t; 300 301 typedef struct _bcm_mn_cosq_cpu_cosq_config_s { 302 /* All MC queues have DB and MCQE space */ 303 int enable; 304 int q_min_limit[2]; 305 int q_shared_limit[2]; 306 uint8 q_limit_dynamic[2]; 307 uint8 q_limit_enable[2]; 308 uint8 q_color_limit_enable[2]; 309 } _bcm_mn_cosq_cpu_cosq_config_t; 310 311 #define _MN_XPIPE 0 312 #define _MN_YPIPE 1 313 #define _MN_NUM_PIPES 1 314 315 #define _BCM_MN_PORT_TO_PIPE(u, p) _MN_XPIPE 316 typedef struct _bcm_mn_mmu_info_s { 317 318 _bcm_mn_cosq_node_t sched_node[_BCM_MN_NUM_TOTAL_SCHEDULERS]; /* sched nodes */ 319 _bcm_mn_cosq_node_t queue_node[_BCM_MN_NUM_L2_UC_LEAVES]; /* queue nodes */ 320 _bcm_mn_cosq_node_t mc_queue_node[_BCM_MN_NUM_L2_MC_LEAVES]; /* queue nodes */ 321 _bcm_mn_cosq_port_info_t port_info[_BCM_MN_MAX_PORT]; 322 323 _bcm_mn_pipe_resources_t pipe_resources[_MN_NUM_PIPES]; 324 325 int ets_mode; 326 int curr_shared_limit; 327 int curr_merger_index; 328 /* this should be programmed by reading the soc_info which will have 329 * the info from the software OTP 330 */ 331 int num_l2_queues; 332 int _bcm_mn_default_lls; 333 }_bcm_mn_mmu_info_t; 334 335 #define _BCM_DEFAULT_LLS_SET(mmu_info) \ 336 do { \ 337 mmu_info->_bcm_mn_default_lls = 1; \ 338 } while(0); 339 340 #define _BCM_DEFAULT_LLS_IS_SET(mmu_info) \ 341 (mmu_info->_bcm_mn_default_lls) 342 343 #define _BCM_DEFAULT_LLS_RESET(mmu_info) \ 344 do { \ 345 mmu_info->_bcm_mn_default_lls = 0; \ 346 } while(0); 347 348 #define _BCM_MN_START_INDEX_ALIGN_PFC 4 349 #define _BCM_MN_START_INDEX_ALIGN_DEFAULT 1 350 #define _MN_NUM_TIME_DOMAIN 4 351 352 typedef struct _bcm_mn_cosq_time_info_s { 353 soc_field_t field; 354 uint32 ref_count; 355 } _bcm_mn_cosq_time_info_t; 356 357 /* WRED can be enabled at per UC queue / queue group/ port / service pool basis 358 639 ~ 0: Unicast Queue 359 767 - 640: Queue Group per PIPE 360 1035 ~ 768: Port Service Pool (Port 0 to 73) 361 1039 ~ 1036: Global Service Pool 362 */ 363 STATIC _bcm_mn_cosq_time_info_t time_domain_mn[_MN_NUM_TIME_DOMAIN] = { 364 {TIME_0f, 1040}, /* Default all entries are pointing to TIME_0 */ 365 {TIME_1f, 0}, 366 {TIME_2f, 0}, 367 {TIME_3f, 0} 368 }; 369 370 #define _MN_NUM_SERVICE_POOL 4 371 372 #define _BCM_MN_PRESOURCES(mi, p) (&(mi)->pipe_resources[(p)]) 373 374 STATIC _bcm_mn_mmu_info_t *_bcm_mn_mmu_info[BCM_MAX_NUM_UNITS]; /* MMU info */ 375 376 STATIC soc_profile_mem_t *_bcm_mn_wred_profile[BCM_MAX_NUM_UNITS]; 377 STATIC soc_profile_mem_t *_bcm_mn_cos_map_profile[BCM_MAX_NUM_UNITS]; 378 STATIC soc_profile_mem_t *_bcm_mn_sample_int_profile[BCM_MAX_NUM_UNITS]; 379 STATIC soc_profile_reg_t *_bcm_mn_feedback_profile[BCM_MAX_NUM_UNITS]; 380 STATIC soc_profile_reg_t *_bcm_mn_llfc_profile[BCM_MAX_NUM_UNITS]; 381 STATIC soc_profile_mem_t *_bcm_mn_voq_port_map_profile[BCM_MAX_NUM_UNITS]; 382 static soc_profile_mem_t *_bcm_mn_ifp_cos_map_profile[BCM_MAX_NUM_UNITS]; 383 STATIC soc_profile_mem_t *_bcm_mn_service_port_map_profile[BCM_MAX_NUM_UNITS]; 384 STATIC soc_profile_mem_t *_bcm_mn_service_cos_map_profile[BCM_MAX_NUM_UNITS]; 385 386 STATIC _bcm_mn_cosq_cpu_cosq_config_t *_bcm_mn_cosq_cpu_cosq_config[BCM_MAX_NUM_UNITS][_BCM_MN_NUM_L2_CPU_LEAVES]; 387 388 STATIC int 389 _bcm_mn_node_index_set(_bcm_mn_cosq_list_t *list, int start, int range); 390 391 STATIC int _bcm_mn_voq_next_base_node_get(int unit, bcm_port_t port, 392 int modid, 393 _bcm_mn_cosq_node_t **base_node); 394 STATIC int 395 _bcm_mn_cosq_mapping_set(int unit, bcm_port_t ing_port, bcm_cos_t priority, 396 uint32 flags, bcm_gport_t gport, bcm_cos_queue_t cosq); 397 398 STATIC int 399 _bcm_mn_map_fc_status_to_node(int unit, int port, _bcm_mn_fc_type_t fct, 400 int spad_offset, int cosq, uint32 hw_index, int level); 401 STATIC int 402 _bcm_mn_cosq_max_nodes_get(int unit, soc_monterey_node_lvl_e level, 403 int *id); 404 405 typedef enum { 406 _BCM_MN_COSQ_TYPE_UCAST, 407 _BCM_MN_COSQ_TYPE_MCAST, 408 _BCM_MN_COSQ_TYPE_EXT_UCAST 409 } _bcm_mn_cosq_type_t; 410 411 #define IS_MN_HSP_PORT(u,p) \ 412 (SOC_IS_MONTEREY(unit) ? TRUE : \ 413 ((_soc_monterey_port_sched_type_get((u),(p)) == SOC_MONTEREY_SCHED_HSP) ? 1 : 0)) 414 415 typedef struct _bcm_mn_endpoint_s { 416 uint32 flags; /* BCM_COSQ_CLASSIFIER_xxx flags */ 417 bcm_vlan_t vlan; /* VLAN */ 418 bcm_mac_t mac; /* MAC address */ 419 bcm_vrf_t vrf; /* Virtual Router Instance */ 420 bcm_ip_t ip_addr; /* IPv4 address */ 421 bcm_ip6_t ip6_addr; /* IPv6 address */ 422 bcm_gport_t gport; /* GPORT ID */ 423 } _bcm_mn_endpoint_t; 424 425 typedef struct _bcm_mn_endpoint_queuing_info_s { 426 int num_endpoint; /* Number of endpoints */ 427 _bcm_mn_endpoint_t **ptr_array; /* Array of pointers to endpoints */ 428 soc_profile_mem_t *cos_map_profile; /* Internal priority to CoS queue 429 mapping profile */ 430 } _bcm_mn_endpoint_queuing_info_t; 431 432 STATIC int 433 _bcm_mn_cosq_egress_sp_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 434 int *p_pool_start, int *p_pool_end); 435 436 STATIC _bcm_mn_endpoint_queuing_info_t *_bcm_mn_endpoint_queuing_info[BCM_MAX_NUM_UNITS]; 437 438 STATIC int 439 _bcm_mn_cosq_dynamic_thresh_enable_get(int unit, 440 bcm_gport_t gport, bcm_cos_queue_t cosq, 441 bcm_cosq_control_t type, int *arg); 442 443 STATIC int 444 _bcm_mn_fc_status_map_gport(int unit, int port, 445 bcm_gport_t gport, _bcm_mn_fc_type_t fct, uint32 *cos_bmp); 446 STATIC int 447 _bcm_mn_port_fc_profile_set(int unit, int port, _bcm_cosq_op_t op, 448 int entry_cnt, int *pfc_class, uint32 *cos_bmp); 449 STATIC int 450 _bcm_mn_cosq_node_get(int unit, bcm_gport_t gport, 451 bcm_cos_queue_t cosq,bcm_module_t *modid, bcm_port_t *port, 452 int *id, _bcm_mn_cosq_node_t **node); 453 454 int _bcm_mn_get_s1_node(int unit, bcm_gport_t subport, 455 _bcm_mn_cosq_node_t **s1_node) ; 456 STATIC int 457 _bcm_mn_cosq_sched_parent_child_set(int unit, int port, int level, 458 int sched_index, int child_index, 459 soc_monterey_sched_mode_e sched_mode, 460 int weight, _bcm_mn_cosq_node_t *child_node); 461 #define _BCM_MN_NUM_ENDPOINT(unit) \ 462 (_bcm_mn_endpoint_queuing_info[unit]->num_endpoint) 463 464 #define _BCM_MN_ENDPOINT(unit, id) \ 465 (_bcm_mn_endpoint_queuing_info[unit]->ptr_array[id]) 466 467 #define _BCM_MN_ENDPOINT_IS_USED(unit, id) \ 468 (_bcm_mn_endpoint_queuing_info[unit]->ptr_array[id] != NULL) 469 470 #define _BCM_MN_ENDPOINT_COS_MAP_PROFILE(unit) \ 471 (_bcm_mn_endpoint_queuing_info[unit]->cos_map_profile) 472 473 474 /* 475 * Function: 476 * _bcm_mn_cosq_map_index_set 477 * Purpose: 478 * Mark indices as allocated 479 * Parameters: 480 * list - (IN) bit list 481 * start - (IN) start index 482 * range - (IN) range bits 483 * Returns: 484 * BCM_E_XXX 485 */ 486 STATIC int 487 _bcm_mn_cosq_map_index_set(SHR_BITDCL *list, int start, int range) 488 { 489 SHR_BITSET_RANGE(list, start, range); 490 return BCM_E_NONE; 491 } 492 493 #ifdef BCM_WARM_BOOT_SUPPORT 494 495 #define BCM_WB_VERSION_1_0 SOC_SCACHE_VERSION(1,0) 496 #define BCM_WB_VERSION_1_1 SOC_SCACHE_VERSION(1,1) 497 #define BCM_WB_VERSION_1_2 SOC_SCACHE_VERSION(1,2) 498 499 #define BCM_WB_DEFAULT_VERSION BCM_WB_VERSION_1_2 500 501 STATIC int 502 _bcm_mn_cosq_wb_alloc(int unit) 503 { 504 _bcm_mn_mmu_info_t *mmu_info; 505 soc_scache_handle_t scache_handle; 506 uint8 *scache_ptr; 507 int rv, alloc_size, node_list_sizes[3], ii, jj; 508 uint32 shadow_size = 0; 509 510 mmu_info = _bcm_mn_mmu_info[unit]; 511 512 if (!mmu_info) { 513 return BCM_E_INIT; 514 } 515 516 node_list_sizes[0] = _BCM_MN_NUM_L2_UC_LEAVES; 517 node_list_sizes[1] = _BCM_MN_NUM_L2_MC_LEAVES; 518 node_list_sizes[2] = _BCM_MN_NUM_TOTAL_SCHEDULERS; 519 520 alloc_size = 0; 521 for(ii = 0; ii < 3; ii++) { 522 alloc_size += sizeof(uint32); 523 for(jj = 0; jj < node_list_sizes[ii]; jj++) { 524 alloc_size += 8 * sizeof(uint32); 525 } 526 } 527 528 /* Size of TIME_DOMAINr field and count reference */ 529 alloc_size += _MN_NUM_TIME_DOMAIN * sizeof(_bcm_mn_cosq_time_info_t); 530 531 soc_monterey_shadow_size_get(unit, &shadow_size); 532 alloc_size += shadow_size; 533 534 /* added in BCM_WB_VERSION_1_1 535 * to sync _bcm_mn_mmu_info[unit]->ets_mode/curr_shared_limit 536 */ 537 alloc_size += 2 * sizeof(int); 538 539 /* added in BCM_WB_VERSION_1_1 540 * to sync the reference count of IFP_COS_MAPm 541 */ 542 alloc_size += (SOC_MEM_SIZE(unit,IFP_COS_MAPm) / _MN_NUM_INTERNAL_PRI) * 543 sizeof(uint16); 544 545 /* 546 * Sync num_cos value 547 */ 548 alloc_size += sizeof(int); 549 550 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_COSQ, 0); 551 552 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, TRUE, alloc_size, 553 &scache_ptr, BCM_WB_DEFAULT_VERSION, NULL); 554 if (rv == BCM_E_NOT_FOUND) { 555 rv = BCM_E_NONE; 556 } 557 558 return rv; 559 } 560 561 #define _BCM_MN_WB_NTYPE_UCAST 0 562 #define _BCM_MN_WB_NTYPE_MCAST 1 563 #define _BCM_MN_WB_NTYPE_SCHED 2 564 565 566 /* 2 bit node type, 15 bit nid, 15 hw cosq */ 567 #define _BCM_MN_WB_SET_NODE_W1(ntype,nid,hwcosq) \ 568 (((ntype & 3)) | \ 569 (((nid) & 0x7fff) << 2) | \ 570 (((hwcosq) & 0x7fff) << 17)) 571 572 #define _BCM_MN_WB_GET_NODE_TYPE_W1(w1) ((w1) & 3) 573 #define _BCM_MN_WB_GET_NODE_ID_W1(w1) (((w1) >> 2) & 0x7fff) 574 #define _BCM_MN_WB_GET_NODE_HW_COSQ_W1(w1) (((w1) >> 17) & 0x7fff) 575 576 577 /* 15 bit hw index, 13 bit parent id, 3 bit level, 1 bit wrr_in_use 578 */ 579 580 #define _BCM_MN_WB_SET_NODE_W2(hwindex,parentid,lvl,wrr_in_use) \ 581 ((hwindex & 0x7fff) | \ 582 ((parentid & 0x1fff) << 15) | \ 583 ((lvl & 0x7) << 28) | \ 584 ((wrr_in_use & 0x1) << 31)) 585 586 #define _BCM_MN_WB_GET_NODE_HW_INDEX_W2(w1) ((w1) & 0x7fff) 587 #define _BCM_MN_WB_GET_NODE_PARENTID_W2(w1) (((w1) >> 15) & 0x1fff) 588 #define _BCM_MN_WB_GET_NODE_LEVEL_W2(w1) (((w1) >> 28) & 0x7) 589 #define _BCM_MN_WB_GET_NODE_WRR_IN_USE_W2(w1) (((w1) >> 31) & 0x1) 590 591 #define _BCM_MN_WB_SET_NODE_W3(gport) (gport) 592 #define _BCM_MN_WB_SET_NODE_W4(gport) (gport) 593 594 /* 15 bit numq, 15 bit cosq, 1 bit dmvoq_en, 1 bit coe_en 595 */ 596 #define _BCM_MN_WB_SET_NODE_W5(numq,cosq,dmvoq_en,coe_en) \ 597 ((numq & 0x7fff) | \ 598 ((cosq & 0x7fff) << 15) | \ 599 ((dmvoq_en &0x01) << 30) | \ 600 ((coe_en & 0x01) << 31)) 601 602 #define _BCM_MN_WB_GET_NODE_NUMQ_W5(w1) ((w1) & 0x7fff) 603 #define _BCM_MN_WB_GET_NODE_COSQATTT_W5(w1) (((w1) >> 15) & 0x7fff) 604 #define _BCM_MN_WB_GET_NODE_DMVOQ_EN_W5(w1) (((w1) >> 30) & 0x1) 605 #define _BCM_MN_WB_GET_NODE_COE_EN_W5(w1) (((w1) >> 31) & 0x1) 606 607 /* 10 bit base size, 15 bit base_index, 1 bit expand, 4 bit type */ 608 #define _BCM_MN_WB_SET_NODE_W6(base_size,base_index,expand,type) \ 609 ((base_size & 0x3ff) | \ 610 ((base_index & 0x7fff) << 10) | \ 611 ((expand & 0x1) << 25) | \ 612 ((type & 0xf) << 26)) 613 614 #define _BCM_MN_WB_GET_BASE_SIZE_W6(w1) ((w1) & 0x3ff) 615 #define _BCM_MN_WB_GET_BASE_INDEX_W6(w1) (((w1) >> 10) & 0x7fff) 616 #define _BCM_MN_WB_GET_EXPAND_W6(w1) (((w1) >> 25) & 0x1) 617 #define _BCM_MN_WB_TYPE_W6(w1) (((w1) >> 26) & 0xf) 618 619 /* 9 bit remote_modid, 9 bit remote_port. 620 * Present only if dmvoq bit is set in W6 621 */ 622 #define _BCM_MN_WB_SET_NODE_W7(remote_modid,remote_port) \ 623 ((((remote_modid) & 0x1ff)) | \ 624 (((remote_port) & 0x1ff) << 9)) 625 626 #define _BCM_MN_WB_GET_NODE_DEST_MODID_W7(w1) ((w1) & 0x1ff) 627 #define _BCM_MN_WB_GET_NODE_DEST_PORT_W7(w1) (((w1) >> 9) & 0x1ff) 628 629 /* 14 bit coe base index, 8 bit coe_num_l2 */ 630 #define _BCM_MN_WB_SET_NODE_W8(coe_base_index, coe_num_l2) \ 631 ((coe_base_index & 0x3fff) | \ 632 ((coe_num_l2 & 0xff) << 14)) 633 634 #define _BCM_MN_WB_GET_COE_BASE_INDEX_W8(w1) ((w1) & 0x3fff) 635 #define _BCM_MN_WB_GET_COE_NUM_L2_W8(w1) (((w1) >> 14) & 0xff) 636 637 #define _BCM_MN_NODE_ID(np,np0) (np - np0) 638 639 STATIC void * 640 _bcm_mn_cosq_alloc_clear(void *cp, unsigned int size, char *description); 641 642 643 STATIC int 644 _bcm_mn_child_level_get(int unit, _bcm_mn_cosq_node_t *node , int *child_level) 645 { 646 647 if (!node) 648 { 649 return BCM_E_INTERNAL; 650 } 651 if (node->level == SOC_MONTEREY_NODE_LVL_ROOT) 652 { 653 *child_level = SOC_MONTEREY_NODE_LVL_S1; 654 655 }else if (node->level == SOC_MONTEREY_NODE_LVL_S1) 656 { 657 *child_level = SOC_MONTEREY_NODE_LVL_L0; 658 }else if (node->level == SOC_MONTEREY_NODE_LVL_L0) 659 { 660 *child_level = SOC_MONTEREY_NODE_LVL_L1; 661 }else if (node->level == SOC_MONTEREY_NODE_LVL_L1) 662 { 663 *child_level = SOC_MONTEREY_NODE_LVL_L2; 664 } 665 return BCM_E_NONE; 666 } 667 /* 668 * Function: 669 * _bcm_mn_cosq_map_alloc_set 670 * Purpose: 671 * Allocate the cosq_map bitmap and 672 * restore 673 * Parameters: 674 * node - (IN) cosq_node 675 * Returns: 676 * BCM_E_XXX 677 */ 678 STATIC int 679 _bcm_mn_cosq_map_alloc_set(int unit, _bcm_mn_cosq_node_t *node) 680 { 681 _bcm_mn_cosq_node_t *child; 682 int alloc_size; 683 int max_nodes = 0; 684 int child_level = 0; 685 686 BCM_IF_ERROR_RETURN 687 (_bcm_mn_child_level_get(unit, node, &child_level)); 688 BCM_IF_ERROR_RETURN 689 (_bcm_mn_cosq_max_nodes_get(unit, child_level, &max_nodes)); 690 if (node->cosq_map == NULL) { 691 if ( node->numq == -1 ) { 692 alloc_size = SHR_BITALLOCSIZE(max_nodes); 693 } else { 694 alloc_size = SHR_BITALLOCSIZE(node->numq); 695 } 696 node->cosq_map = _bcm_mn_cosq_alloc_clear(node->cosq_map, 697 alloc_size, 698 "cosq_map"); 699 if (node->cosq_map == NULL) { 700 return BCM_E_MEMORY; 701 } 702 } 703 child = node->child; 704 while (child != NULL) { 705 BCM_IF_ERROR_RETURN 706 (_bcm_mn_cosq_map_index_set(node->cosq_map, 707 child->attached_to_input, 1)); 708 child = child->sibling; 709 } 710 711 return BCM_E_NONE; 712 } 713 714 /* 715 * Function: 716 * _bcm_mn_cosq_map_node_recover 717 * Purpose: 718 * Used to recover cos_map for S0,S1,L0,L1 levels 719 * Parameters: 720 * node - (IN) cosq_node 721 * Returns: 722 * BCM_E_XXX 723 */ 724 725 STATIC int 726 _bcm_mn_cosq_map_node_recover(int unit ,_bcm_mn_cosq_node_t *node) 727 { 728 if (!node) { 729 return BCM_E_NONE; 730 } 731 if (node->level == SOC_MONTEREY_NODE_LVL_L2) { 732 return BCM_E_NONE; 733 } 734 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_map_alloc_set(unit , node)); 735 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_map_node_recover(unit, node->sibling)); 736 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_map_node_recover(unit, node->child)); 737 return BCM_E_NONE; 738 } 739 int 740 bcm_mn_cosq_reinit(int unit) 741 { 742 soc_scache_handle_t scache_handle; 743 uint8 *scache_ptr; 744 uint32 *u32_scache_ptr, wval, fval; 745 uint16 *u16_scache_ptr; 746 _bcm_mn_cosq_node_t *node; 747 bcm_port_t port; 748 int rv, ii, jj, set_index; 749 _bcm_mn_cosq_node_t *nodes[3]; 750 int xnode_id, stable_size, count, profile_index; 751 _bcm_mn_mmu_info_t *mmu_info; 752 uint32 entry[SOC_MAX_MEM_WORDS]; 753 soc_profile_mem_t *profile_mem; 754 _bcm_mn_pipe_resources_t *res; 755 soc_mem_t mem; 756 mmu_wred_config_entry_t qentry; 757 int alloc_size; 758 int additional_scache_size = 0; 759 uint16 recovered_ver = 0; 760 int index=0; 761 bcm_pbmp_t all_pbmp; 762 soc_profile_reg_t *profile_reg; 763 soc_info_t *si; 764 bcm_port_t phy_port, mmu_port; 765 soc_reg_t reg; 766 uint32 tmp32; 767 int dmvoq_en = 0, coe_en = 0; 768 uint64 rval, index_map; 769 static const soc_reg_t llfc_cfgr[] = { 770 PORT_PFC_CFG0r, PORT_PFC_CFG1r, PORT_PFC_CFG2r 771 }; 772 int num; 773 _bcm_mn_cosq_node_t *port_info; 774 775 si = &SOC_INFO(unit); 776 SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size)); 777 if ((stable_size == 0) || (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit))) { 778 /* COSQ warmboot requires extended scache support i.e. level2 warmboot*/ 779 return BCM_E_NONE; 780 } 781 782 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_COSQ, 0); 783 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 0, &scache_ptr, 784 BCM_WB_DEFAULT_VERSION, &recovered_ver); 785 if (BCM_FAILURE(rv)) { 786 return rv; 787 } 788 789 mmu_info = _bcm_mn_mmu_info[unit]; 790 791 if (!mmu_info) { 792 return BCM_E_INIT; 793 } 794 795 res = _BCM_MN_PRESOURCES(mmu_info, _MN_XPIPE); 796 u32_scache_ptr = (uint32*) scache_ptr; 797 798 nodes[0] = &mmu_info->queue_node[0]; 799 nodes[1] = &mmu_info->mc_queue_node[0]; 800 nodes[2] = &mmu_info->sched_node[0]; 801 802 for(ii = 0; ii < 3; ii++) { 803 count = *u32_scache_ptr; 804 u32_scache_ptr++; 805 for(jj = 0; jj < count; jj++) { 806 wval = *u32_scache_ptr; 807 u32_scache_ptr++; 808 xnode_id = _BCM_MN_WB_GET_NODE_ID_W1(wval); 809 node = nodes[ii] + xnode_id; 810 node->in_use = TRUE; 811 node->numq = 1; 812 fval = _BCM_MN_WB_GET_NODE_HW_COSQ_W1(wval); 813 node->hw_cosq = (fval == 0x7fff)? -1 : fval; 814 815 wval = *u32_scache_ptr; 816 u32_scache_ptr++; 817 fval = _BCM_MN_WB_GET_NODE_HW_INDEX_W2(wval); 818 node->hw_index = (fval == 0x7fff) ? -1 : fval; 819 fval = _BCM_MN_WB_GET_NODE_PARENTID_W2(wval); 820 if (fval == 0x1fff) { 821 node->parent = NULL; 822 } else { 823 node->parent = &mmu_info->sched_node[fval]; 824 if (node->parent->child) { 825 node->sibling = node->parent->child; 826 } 827 node->parent->child = node; 828 } 829 node->level = _BCM_MN_WB_GET_NODE_LEVEL_W2(wval); 830 node->wrr_in_use = _BCM_MN_WB_GET_NODE_WRR_IN_USE_W2(wval); 831 832 node->gport = *u32_scache_ptr++; 833 node->port_gport = *u32_scache_ptr++; 834 835 wval = *u32_scache_ptr; 836 u32_scache_ptr++; 837 node->numq = _BCM_MN_WB_GET_NODE_NUMQ_W5(wval); 838 /* numq of -1 will be recovered as 32767 need to update back as -1 */ 839 if (node->numq == 32767) 840 { 841 node->numq = -1 ; 842 } 843 fval = _BCM_MN_WB_GET_NODE_COSQATTT_W5(wval); 844 node->attached_to_input = (fval == 0x7fff) ? -1 : fval; 845 dmvoq_en = _BCM_MN_WB_GET_NODE_DMVOQ_EN_W5(wval); 846 coe_en = _BCM_MN_WB_GET_NODE_COE_EN_W5(wval); 847 848 wval = *u32_scache_ptr; 849 u32_scache_ptr++; 850 node->base_size = _BCM_MN_WB_GET_BASE_SIZE_W6(wval); 851 fval = _BCM_MN_WB_GET_BASE_INDEX_W6(wval); 852 node->base_index = (fval == 0x7fff) ? -1 : fval; 853 node->numq_expandable = _BCM_MN_WB_GET_EXPAND_W6(wval); 854 node->type = _BCM_MN_WB_TYPE_W6(wval); 855 856 if (dmvoq_en) { 857 wval = *u32_scache_ptr; 858 u32_scache_ptr++; 859 fval = _BCM_MN_WB_GET_NODE_DEST_MODID_W7(wval); 860 node->remote_modid = (fval == 0x1ff) ? -1 : fval; 861 fval = _BCM_MN_WB_GET_NODE_DEST_PORT_W7(wval); 862 node->remote_port = (fval == 0x1ff) ? -1 : fval; 863 } 864 865 if (soc_feature(unit, soc_feature_mmu_hqos_four_level) && 866 (node->level == SOC_MONTEREY_NODE_LVL_S1) && 867 coe_en) { 868 wval = *u32_scache_ptr; 869 u32_scache_ptr++; 870 node->coe_base_index = _BCM_MN_WB_GET_COE_BASE_INDEX_W8(wval); 871 if (node->coe_base_index == 16383 ) 872 { 873 node->coe_base_index = -1; 874 } 875 node->coe_num_l2 = _BCM_MN_WB_GET_COE_NUM_L2_W8(wval); 876 } 877 878 /* 879 * Not checking the return value intentionally 880 * to take care of warmboot case. 881 */ 882 /* coverity[unchecked_value] */ 883 (void)_bcm_mn_cosq_node_get(unit, node->gport, 0, NULL, 884 &node->local_port, NULL, NULL); 885 886 if (node->hw_index != -1) { 887 if (node->level == SOC_MONTEREY_NODE_LVL_S1) { 888 _bcm_mn_node_index_set(&res->s1_sched_list, 889 node->hw_index, 1); 890 } else if (node->level == SOC_MONTEREY_NODE_LVL_L0) { 891 _bcm_mn_node_index_set(&res->l0_sched_list, 892 node->hw_index, 1); 893 if (IS_MN_HSP_PORT(unit, node->local_port)) { 894 _bcm_mn_node_index_set(&res->hsp_l0_sched_list, 895 node->hw_index, 1); 896 } 897 if (IS_CPU_PORT(unit, node->local_port)) { 898 _bcm_mn_node_index_set(&res->cpu_l0_sched_list, 899 node->hw_index - _BCM_MN_CPU_PORT_L0_MIN, 1); 900 } 901 } else if (node->level == SOC_MONTEREY_NODE_LVL_L1) { 902 _bcm_mn_node_index_set(&res->l1_sched_list, 903 node->hw_index, 1); 904 if (IS_MN_HSP_PORT(unit, node->local_port)) { 905 _bcm_mn_node_index_set(&res->hsp_l1_sched_list, 906 node->hw_index, 1); 907 } 908 } else if (node->level == SOC_MONTEREY_NODE_LVL_L2) { 909 _bcm_mn_node_index_set(&res->l2_queue_list, 910 node->hw_index, 1); 911 if (IS_MN_HSP_PORT(unit, node->local_port)) { 912 _bcm_mn_node_index_set(&res->hsp_l2_queue_list, 913 node->hw_index, 1); 914 } 915 } 916 } 917 } 918 } 919 920 BCM_PBMP_CLEAR(all_pbmp); 921 BCM_PBMP_ASSIGN(all_pbmp, PBMP_ALL(unit)); 922 923 /* Restoring the cosq_map */ 924 PBMP_ITER(all_pbmp, port) { 925 node = NULL; 926 927 /* root node */ 928 port_info = &mmu_info->sched_node[port]; 929 if (port_info && (port_info->gport >= 0)) { 930 SOC_IF_ERROR_RETURN ( 931 _bcm_mn_cosq_map_node_recover(unit, port_info)); 932 } 933 } 934 935 /* Recovery TIME_DOMAINr field and count reference */ 936 alloc_size = _MN_NUM_TIME_DOMAIN * sizeof(_bcm_mn_cosq_time_info_t); 937 sal_memcpy(&time_domain_mn[0], u32_scache_ptr, alloc_size); 938 time_domain_mn[0].field = TIME_0f; 939 time_domain_mn[1].field = TIME_1f; 940 time_domain_mn[2].field = TIME_2f; 941 time_domain_mn[3].field = TIME_3f; 942 u32_scache_ptr += alloc_size / sizeof(uint32); 943 soc_monterey_shadow_load(unit, &u32_scache_ptr); 944 945 mmu_info->curr_shared_limit = *u32_scache_ptr++; 946 947 u16_scache_ptr = (uint16 *)u32_scache_ptr; 948 949 /* Update IFP_COS_MAP memory profile reference counter */ 950 profile_mem = _bcm_mn_ifp_cos_map_profile[unit]; 951 num = SOC_MEM_SIZE(unit,IFP_COS_MAPm) / _MN_NUM_INTERNAL_PRI; 952 for (ii = 0; ii < num; ii++) { 953 for (jj = 0; jj < *u16_scache_ptr; jj++) { 954 SOC_IF_ERROR_RETURN( 955 soc_profile_mem_reference(unit, profile_mem, 956 ii * _MN_NUM_INTERNAL_PRI, 957 _MN_NUM_INTERNAL_PRI)); 958 } 959 u16_scache_ptr++; 960 } 961 962 u32_scache_ptr = (uint32 *)u16_scache_ptr; 963 NUM_COS(unit) = *u32_scache_ptr; 964 965 if (additional_scache_size > 0) { 966 /* coverity[dead_error_begin] */ 967 BCM_IF_ERROR_RETURN( 968 soc_scache_realloc(unit, scache_handle, additional_scache_size)); 969 } 970 971 /* Update reference counts for DSCP_TABLE profile*/ 972 PBMP_ITER(all_pbmp, port) { 973 if (IS_LB_PORT(unit, port)) { 974 /* Loopback port base starts from 64 */ 975 continue; 976 } 977 SOC_IF_ERROR_RETURN(soc_mem_read(unit, PORT_TABm, MEM_BLOCK_ALL, 978 port, &entry)); 979 index = soc_mem_field32_get(unit, PORT_TABm, &entry, TRUST_DSCP_PTRf); 980 981 SOC_IF_ERROR_RETURN(_bcm_dscp_table_entry_reference(unit, index * 64, 982 64)); 983 } 984 985 /* Update PORT_COS_MAP memory profile reference counter */ 986 profile_mem = _bcm_mn_cos_map_profile[unit]; 987 PBMP_ALL_ITER(unit, port) { 988 SOC_IF_ERROR_RETURN 989 (soc_mem_read(unit, COS_MAP_SELm, MEM_BLOCK_ALL, port, &entry)); 990 set_index = soc_mem_field32_get(unit, COS_MAP_SELm, &entry, SELECTf); 991 SOC_IF_ERROR_RETURN 992 (soc_profile_mem_reference(unit, profile_mem, set_index * 16, 16)); 993 } 994 if (SOC_INFO(unit).cpu_hg_index != -1) { 995 SOC_IF_ERROR_RETURN(soc_mem_read(unit, COS_MAP_SELm, MEM_BLOCK_ALL, 996 SOC_INFO(unit).cpu_hg_index, &entry)); 997 set_index = soc_mem_field32_get(unit, COS_MAP_SELm, &entry, SELECTf); 998 SOC_IF_ERROR_RETURN 999 (soc_profile_mem_reference(unit, profile_mem, set_index, 1)); 1000 } 1001 1002 mem = MMU_WRED_CONFIG_X_PIPEm; 1003 for (ii = soc_mem_index_min(unit, mem); 1004 ii <= soc_mem_index_max(unit, mem); ii++) { 1005 BCM_IF_ERROR_RETURN( 1006 soc_mem_read(unit, mem, MEM_BLOCK_ALL, ii, &qentry)); 1007 1008 profile_index = soc_mem_field32_get(unit, mem, &qentry, PROFILE_INDEXf); 1009 1010 BCM_IF_ERROR_RETURN 1011 (soc_profile_mem_reference(unit, _bcm_mn_wred_profile[unit], 1012 profile_index, 1)); 1013 } 1014 1015 profile_reg = _bcm_mn_llfc_profile[unit]; 1016 PBMP_PORT_ITER(unit, port) { 1017 phy_port = si->port_l2p_mapping[port]; 1018 mmu_port = si->port_p2m_mapping[phy_port]; 1019 if (mmu_port == -1) { 1020 continue; 1021 } 1022 reg = llfc_cfgr[mmu_port/32]; 1023 BCM_IF_ERROR_RETURN(soc_reg64_get(unit, reg, 0, 0, &rval)); 1024 1025 index_map = soc_reg64_field_get(unit, reg, rval, PROFILE_INDEXf); 1026 COMPILER_64_SHR(index_map, ((mmu_port % 32) * 2)); 1027 COMPILER_64_TO_32_LO(tmp32, index_map); 1028 set_index = (tmp32 & 3); 1029 SOC_IF_ERROR_RETURN 1030 (soc_profile_reg_reference(unit, profile_reg, set_index * 16, 16)); 1031 } 1032 1033 return BCM_E_NONE; 1034 } 1035 1036 int 1037 bcm_mn_cosq_sync(int unit) 1038 { 1039 soc_scache_handle_t scache_handle; 1040 uint8 *scache_ptr; 1041 uint32 *u32_scache_ptr; 1042 uint16 *u16_scache_ptr; 1043 _bcm_mn_cosq_node_t *node; 1044 int node_list_sizes[3], ii, jj, cosq; 1045 _bcm_mn_cosq_node_t *nodes[3]; 1046 int xnode_id; /*, count, pipe; */ 1047 _bcm_mn_mmu_info_t *mmu_info; 1048 int alloc_size; 1049 int rv = BCM_E_NONE; 1050 int ref_count; 1051 int count; 1052 int dmvoq_en = 0, coe_en = 0; 1053 uint32 *psize; 1054 1055 mmu_info = _bcm_mn_mmu_info[unit]; 1056 1057 if (!mmu_info) { 1058 return BCM_E_INIT; 1059 } 1060 1061 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_COSQ, 0); 1062 BCM_IF_ERROR_RETURN 1063 (_bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 0, 1064 &scache_ptr, BCM_WB_DEFAULT_VERSION, NULL)); 1065 1066 u32_scache_ptr = (uint32*) scache_ptr; 1067 1068 nodes[0] = &mmu_info->queue_node[0]; 1069 node_list_sizes[0] = _BCM_MN_NUM_L2_UC_LEAVES; 1070 nodes[1] = &mmu_info->mc_queue_node[0]; 1071 node_list_sizes[1] = _BCM_MN_NUM_L2_MC_LEAVES; 1072 nodes[2] = &mmu_info->sched_node[0]; 1073 node_list_sizes[2] = _BCM_MN_NUM_TOTAL_SCHEDULERS; 1074 1075 for(ii = 0; ii < 3; ii++) { 1076 psize = u32_scache_ptr++; 1077 for(count = 0, jj = 0; jj < node_list_sizes[ii]; jj++) { 1078 node = nodes[ii] + jj; 1079 if (node->in_use == FALSE) { 1080 continue; 1081 } 1082 dmvoq_en = 0; 1083 coe_en = 0; 1084 count += 1; 1085 1086 if (node->parent == NULL) { 1087 xnode_id = 0x1fff; 1088 } else { 1089 xnode_id = _BCM_MN_NODE_ID(node->parent, mmu_info->sched_node); 1090 } 1091 cosq = ((node->attached_to_input == -1) ? 0x7fff : node->attached_to_input); 1092 1093 *u32_scache_ptr++ = _BCM_MN_WB_SET_NODE_W1(ii, jj, 1094 ((node->hw_cosq == -1) ? 0x7fff : node->hw_cosq)); 1095 1096 if ((node->remote_modid != -1) || (node->remote_port != -1)) { 1097 dmvoq_en = 1; 1098 } 1099 if (soc_feature(unit, soc_feature_mmu_hqos_four_level) && 1100 (node->level == SOC_MONTEREY_NODE_LVL_S1)) { 1101 coe_en = 1; 1102 } 1103 1104 *u32_scache_ptr++ = _BCM_MN_WB_SET_NODE_W2( 1105 (node->hw_index == -1) ? 0x7fff : node->hw_index, xnode_id, 1106 node->level, node->wrr_in_use); 1107 1108 *u32_scache_ptr++ = _BCM_MN_WB_SET_NODE_W3(node->gport); 1109 *u32_scache_ptr++ = _BCM_MN_WB_SET_NODE_W4(node->port_gport); 1110 *u32_scache_ptr++ = _BCM_MN_WB_SET_NODE_W5(node->numq, cosq, 1111 dmvoq_en, coe_en); 1112 1113 *u32_scache_ptr++ = _BCM_MN_WB_SET_NODE_W6( 1114 (node->base_size), 1115 ((node->base_index == -1 ) ? 0x7fff : 1116 node->base_index), 1117 (node->numq_expandable), (node->type)); 1118 1119 if (dmvoq_en) { 1120 *u32_scache_ptr++ = _BCM_MN_WB_SET_NODE_W7( 1121 (node->remote_modid == -1) ? 0x1ff : node->remote_modid, 1122 (node->remote_port == -1) ? 0x1ff : node->remote_port); 1123 } 1124 1125 if (soc_feature(unit, 1126 soc_feature_mmu_hqos_four_level)) { 1127 if (node->level == SOC_MONTEREY_NODE_LVL_S1) { 1128 *u32_scache_ptr++ = _BCM_MN_WB_SET_NODE_W8(node->coe_base_index, 1129 node->coe_num_l2); 1130 } 1131 } 1132 } 1133 *psize = count; 1134 } 1135 1136 /* Sync TIME_DOMAINr field and count reference */ 1137 alloc_size = _MN_NUM_TIME_DOMAIN * sizeof(_bcm_mn_cosq_time_info_t); 1138 sal_memcpy(u32_scache_ptr, &time_domain_mn[0], alloc_size); 1139 u32_scache_ptr += alloc_size / sizeof(uint32); 1140 soc_monterey_shadow_sync(unit, &u32_scache_ptr); 1141 1142 *u32_scache_ptr++ = mmu_info->curr_shared_limit; 1143 u16_scache_ptr = (uint16 *)u32_scache_ptr; 1144 1145 for (ii = 0; 1146 ii < (SOC_MEM_SIZE(unit, IFP_COS_MAPm) / _MN_NUM_INTERNAL_PRI); 1147 ii++) { 1148 rv = soc_profile_mem_ref_count_get(unit, 1149 _bcm_mn_ifp_cos_map_profile[unit], 1150 ii * _MN_NUM_INTERNAL_PRI, 1151 &ref_count); 1152 if (!(rv == SOC_E_NOT_FOUND || rv == SOC_E_NONE)) { 1153 return rv; 1154 } 1155 *u16_scache_ptr++ = (uint16)(ref_count & 0xffff); 1156 } 1157 /* Update num cosq */ 1158 u32_scache_ptr = (uint32 *)u16_scache_ptr; 1159 *u32_scache_ptr = NUM_COS(unit); 1160 1161 return BCM_E_NONE; 1162 } 1163 1164 #endif /* BCM_WARM_BOOT_SUPPORT */ 1165 1166 #ifndef BCM_SW_STATE_DUMP_DISABLE 1167 /* 1168 * Function: 1169 * bcm_mn_cosq_sw_dump 1170 * Purpose: 1171 * Displays COS Queue information maintained by software. 1172 * Parameters: 1173 * unit - Device unit number 1174 * Returns: 1175 * None 1176 */ 1177 void 1178 bcm_mn_cosq_sw_dump(int unit) 1179 { 1180 1181 return; 1182 } 1183 #endif /* BCM_SW_STATE_DUMP_DISABLE */ 1184 1185 /* 1186 * Function: 1187 * _bcm_mn_cosq_localport_resolve 1188 * Purpose: 1189 * Resolve GRPOT if it is a local port 1190 * Parameters: 1191 * unit - (IN) unit number 1192 * gport - (IN) GPORT identifier 1193 * local_port - (OUT) local port number 1194 * Returns: 1195 * BCM_E_XXX 1196 */ 1197 int 1198 _bcm_mn_cosq_localport_resolve(int unit, bcm_gport_t gport, 1199 bcm_port_t *local_port) 1200 { 1201 bcm_module_t module; 1202 bcm_port_t port; 1203 bcm_trunk_t trunk; 1204 int id, result; 1205 1206 if (!BCM_GPORT_IS_SET(gport)) { 1207 if (!SOC_PORT_VALID(unit, gport)) { 1208 return BCM_E_PORT; 1209 } 1210 *local_port = gport; 1211 return BCM_E_NONE; 1212 } 1213 1214 BCM_IF_ERROR_RETURN 1215 (_bcm_esw_gport_resolve(unit, gport, &module, &port, &trunk, &id)); 1216 1217 BCM_IF_ERROR_RETURN(_bcm_esw_modid_is_local(unit, module, &result)); 1218 if (result == FALSE) { 1219 return BCM_E_PARAM; 1220 } 1221 1222 *local_port = port; 1223 1224 return BCM_E_NONE; 1225 } 1226 1227 STATIC int 1228 _bcm_mn_cosq_port_has_ets(int unit, bcm_port_t port) 1229 { 1230 /* In Apache it is always ETS mode */ 1231 return TRUE; 1232 } 1233 1234 /* 1235 * Function: 1236 * _bcm_mn_node_index_get 1237 * Purpose: 1238 * Allocate free index from the given list 1239 * Parameters: 1240 * list - (IN) bit list 1241 * start - (IN) start index 1242 * end - (IN) end index 1243 * count - (IN) size of queue set 1244 * align - (IN) adjusting the bits 1245 * id - (OUT) start index 1246 * Returns: 1247 * BCM_E_XXX 1248 */ 1249 STATIC int 1250 _bcm_mn_node_index_get(SHR_BITDCL *list, int start, int end, 1251 int count, int align, int *id) 1252 { 1253 int i, j, range_empty; 1254 1255 *id = -1; 1256 1257 if ((align <= 0) || (count == 0)) { 1258 return BCM_E_PARAM; 1259 } 1260 1261 if (start & (align - 1)) { 1262 start = (start + align - 1) & ~(align - 1); 1263 } 1264 1265 end = end - align + 1; 1266 1267 for (i = start; i < end; i += align) { 1268 range_empty = 1; 1269 /* Make sure the j doesn not cross the end */ 1270 for (j = i; ((j < (i + count)) && ( j < end)); j++) { 1271 if (SHR_BITGET(list, j) != 0) { 1272 range_empty = 0; 1273 break; 1274 } 1275 } 1276 1277 if (range_empty) { 1278 *id = i; 1279 return BCM_E_NONE; 1280 } 1281 } 1282 return BCM_E_RESOURCE; 1283 } 1284 1285 /* 1286 * Function: 1287 * _bcm_mn_node_index_set 1288 * Purpose: 1289 * Mark indices as allocated 1290 * Parameters: 1291 * list - (IN) bit list 1292 * start - (IN) start index 1293 * range - (IN) range bits 1294 * Returns: 1295 * BCM_E_XXX 1296 */ 1297 STATIC int 1298 _bcm_mn_node_index_set(_bcm_mn_cosq_list_t *list, int start, int range) 1299 { 1300 if ( range == 0) 1301 { 1302 return BCM_E_NONE; 1303 } 1304 if ((start < 0) || 1305 (range < 0) || 1306 ((start + range) > list->count)) { 1307 return BCM_E_RESOURCE; 1308 } 1309 1310 SHR_BITSET_RANGE(list->bits, start, range); 1311 1312 return BCM_E_NONE; 1313 } 1314 1315 /* 1316 * Function: 1317 * _bcm_mn_node_index_clear 1318 * Purpose: 1319 * Mark indices as free 1320 * Parameters: 1321 * list - (IN) bit list 1322 * start - (IN) start index 1323 * range - (IN) range bits 1324 * Returns: 1325 * BCM_E_XXX 1326 */ 1327 STATIC int 1328 _bcm_mn_node_index_clear(_bcm_mn_cosq_list_t *list, int start, int range) 1329 { 1330 if ( range == 0) 1331 { 1332 return BCM_E_NONE; 1333 } 1334 if ((start < 0) || 1335 (range < 0) || 1336 ((start + range) > list->count)) { 1337 return BCM_E_RESOURCE; 1338 } 1339 1340 SHR_BITCLR_RANGE(list->bits, start, range); 1341 1342 return BCM_E_NONE; 1343 } 1344 STATIC int 1345 _bcm_mn_cosq_max_nodes_get(int unit, soc_monterey_node_lvl_e level, 1346 int *id) 1347 { 1348 _bcm_mn_mmu_info_t *mmu_info; 1349 if ((mmu_info = _bcm_mn_mmu_info[unit]) == NULL) { 1350 return BCM_E_INIT; 1351 } 1352 if (id == NULL) { 1353 return BCM_E_PARAM; 1354 } 1355 if (level == SOC_MONTEREY_NODE_LVL_S1) { 1356 *id = _BCM_MN_NUM_S1_SCHEDULER_PER_PIPE; 1357 } else if (level == SOC_MONTEREY_NODE_LVL_L0) { 1358 *id = _BCM_MN_NUM_L0_SCHEDULER_PER_PIPE; 1359 } else if (level == SOC_MONTEREY_NODE_LVL_L1) { 1360 *id = _BCM_MN_NUM_L1_SCHEDULER_PER_PIPE; 1361 } else if (level == SOC_MONTEREY_NODE_LVL_L2) { 1362 *id = mmu_info->num_l2_queues + _BCM_MN_NUM_L2_MC_LEAVES; 1363 } 1364 return BCM_E_NONE; 1365 1366 } 1367 /* 1368 * Function: 1369 * _bcm_mn_cosq_alloc_clear 1370 * Purpose: 1371 * Allocate cosq memory and clear 1372 * Parameters: 1373 * size - (IN) size of memory required 1374 * description- (IN) description about the structure 1375 * Returns: 1376 * BCM_E_XXX 1377 */ 1378 STATIC void * 1379 _bcm_mn_cosq_alloc_clear(void *cp, unsigned int size, char *description) 1380 { 1381 void *block_p; 1382 1383 block_p = (cp) ? cp : sal_alloc(size, description); 1384 1385 if (block_p != NULL) { 1386 sal_memset(block_p, 0, size); 1387 } 1388 1389 return block_p; 1390 } 1391 1392 /* 1393 * Function: 1394 * _bcm_mn_cosq_free_memory 1395 * Purpose: 1396 * Free memory allocated for mmu info members 1397 * Parameters: 1398 * mmu_info - (IN) MMU info pointer 1399 * Returns: 1400 * BCM_E_XXX 1401 */ 1402 STATIC void 1403 _bcm_mn_cosq_free_memory(_bcm_mn_mmu_info_t *mmu_info_p) 1404 { 1405 int pipe; 1406 _bcm_mn_pipe_resources_t *res; 1407 1408 1409 if (mmu_info_p == NULL) { 1410 return; 1411 } 1412 1413 for (pipe = _MN_XPIPE; pipe < _MN_YPIPE; pipe++) { 1414 res = _BCM_MN_PRESOURCES(mmu_info_p, pipe); 1415 if (res->l2_queue_list.bits != NULL) { 1416 sal_free(res->l2_queue_list.bits); 1417 res->l2_queue_list.bits = NULL; 1418 } 1419 if (res->l1_sched_list.bits != NULL) { 1420 sal_free(res->l1_sched_list.bits); 1421 res->l1_sched_list.bits = NULL; 1422 } 1423 if (res->l0_sched_list.bits != NULL) { 1424 sal_free(res->l0_sched_list.bits); 1425 res->l0_sched_list.bits = NULL; 1426 } 1427 if (res->cpu_l0_sched_list.bits != NULL) { 1428 sal_free(res->cpu_l0_sched_list.bits); 1429 res->cpu_l0_sched_list.bits = NULL; 1430 } 1431 if (res->hsp_l2_queue_list.bits != NULL) { 1432 sal_free(res->hsp_l2_queue_list.bits); 1433 res->hsp_l2_queue_list.bits = NULL; 1434 } 1435 if (res->hsp_l1_sched_list.bits != NULL) { 1436 sal_free(res->hsp_l1_sched_list.bits); 1437 res->hsp_l1_sched_list.bits = NULL; 1438 } 1439 if (res->hsp_l0_sched_list.bits != NULL) { 1440 sal_free(res->hsp_l0_sched_list.bits); 1441 res->hsp_l0_sched_list.bits = NULL; 1442 } 1443 if (res->s1_sched_list.bits != NULL) { 1444 sal_free(res->s1_sched_list.bits); 1445 res->s1_sched_list.bits = NULL; 1446 } 1447 } 1448 } 1449 1450 /* 1451 * Function: 1452 * _bcm_mn_cosq_node_get 1453 * Purpose: 1454 * Get internal information of queue group or scheduler type GPORT 1455 * Parameters: 1456 * unit - (IN) unit number 1457 * gport - (IN) queue group/scheduler GPORT identifier 1458 * modid - (OUT) module identifier 1459 * port - (OUT) port number 1460 * id - (OUT) queue group or scheduler identifier 1461 * node - (OUT) node structure for the specified GPORT 1462 * Returns: 1463 * BCM_E_XXX 1464 */ 1465 STATIC int 1466 _bcm_mn_cosq_node_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 1467 bcm_module_t *modid, bcm_port_t *port, 1468 int *id, _bcm_mn_cosq_node_t **node) 1469 { 1470 _bcm_mn_mmu_info_t *mmu_info; 1471 _bcm_mn_cosq_node_t *node_base = NULL; 1472 bcm_module_t modid_out = 0; 1473 bcm_port_t port_out = 0; 1474 uint32 encap_id = -1; 1475 int index; 1476 1477 if ((mmu_info = _bcm_mn_mmu_info[unit]) == NULL) { 1478 return BCM_E_INIT; 1479 } 1480 1481 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 1482 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid_out)); 1483 port_out = BCM_GPORT_UCAST_QUEUE_GROUP_SYSPORTID_GET(gport); 1484 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 1485 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid_out)); 1486 port_out = BCM_GPORT_MCAST_QUEUE_GROUP_SYSPORTID_GET(gport); 1487 } else if (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport)) { 1488 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid_out)); 1489 port_out = (gport >> 16) & 0xff; 1490 } else if (BCM_GPORT_IS_SCHEDULER(gport)) { 1491 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid_out)); 1492 port_out = BCM_GPORT_SCHEDULER_GET(gport) & 0xff; 1493 } else if (BCM_GPORT_IS_LOCAL(gport)) { 1494 encap_id = BCM_GPORT_LOCAL_GET(gport); 1495 port_out = encap_id; 1496 } else if (BCM_GPORT_IS_MODPORT(gport)) { 1497 modid_out = SOC_GPORT_MODPORT_MODID_GET(gport); 1498 port_out = SOC_GPORT_MODPORT_PORT_GET(gport); 1499 encap_id = port_out; 1500 } else { 1501 return BCM_E_PORT; 1502 } 1503 1504 if (!SOC_PORT_VALID(unit, port_out)) { 1505 return BCM_E_PORT; 1506 } 1507 1508 if (port != NULL) { 1509 *port = port_out; 1510 } 1511 #if 0 1512 if (!_bcm_mn_cosq_port_has_ets(unit, port_out)) { 1513 return BCM_E_NOT_FOUND; 1514 } 1515 #endif 1516 1517 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 1518 encap_id = BCM_GPORT_UCAST_QUEUE_GROUP_QID_GET(gport); 1519 index = encap_id; 1520 node_base = mmu_info->queue_node; 1521 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 1522 encap_id = BCM_GPORT_MCAST_QUEUE_GROUP_QID_GET(gport); 1523 index = encap_id; 1524 node_base = mmu_info->mc_queue_node; 1525 } else if (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport)) { 1526 encap_id = BCM_GPORT_UCAST_SUBSCRIBER_QUEUE_GROUP_QID_GET(gport); 1527 index = encap_id; 1528 node_base = mmu_info->queue_node; 1529 } else if (BCM_GPORT_IS_SCHEDULER(gport)) { 1530 encap_id = (BCM_GPORT_SCHEDULER_GET(gport) >> 8) & 0x3fff; 1531 index = encap_id; 1532 node_base = mmu_info->sched_node; 1533 } else { 1534 index = encap_id; 1535 node_base = mmu_info->sched_node; 1536 } 1537 1538 if (index < 0) { 1539 return BCM_E_NOT_FOUND; 1540 } 1541 1542 if (node_base[index].numq == 0) { 1543 return BCM_E_NOT_FOUND; 1544 } 1545 1546 if (modid != NULL) { 1547 *modid = modid_out; 1548 } 1549 if (id != NULL) { 1550 *id = encap_id; 1551 } 1552 if (node != NULL) { 1553 *node = &node_base[index]; 1554 if (*node) { 1555 _bcm_mn_cosq_node_t *tmp_node; 1556 tmp_node = *node; 1557 if (tmp_node->type == _BCM_MN_NODE_SERVICE_UCAST) { 1558 *node = &node_base[index + cosq]; 1559 if (id != NULL) { 1560 *id = tmp_node->hw_index; 1561 } 1562 } 1563 } 1564 1565 } 1566 1567 return BCM_E_NONE; 1568 } 1569 1570 int 1571 _bcm_mn_cosq_port_resolve(int unit, bcm_gport_t gport, bcm_module_t *modid, 1572 bcm_port_t *port, bcm_trunk_t *trunk_id, int *id, 1573 int *qnum) 1574 { 1575 _bcm_mn_cosq_node_t *node; 1576 1577 BCM_IF_ERROR_RETURN 1578 (_bcm_mn_cosq_node_get(unit, gport, 0, modid, port, id, &node)); 1579 *trunk_id = -1; 1580 1581 if (qnum) { 1582 if (node->hw_index == -1) { 1583 return BCM_E_PARAM; 1584 } 1585 *qnum = node->hw_index; 1586 } 1587 1588 return BCM_E_NONE; 1589 } 1590 1591 /* 1592 * Function: 1593 * _bcm_mn_cosq_gport_traverse 1594 * Purpose: 1595 * Walks through the valid COSQ GPORTs and calls 1596 * the user supplied callback function for each entry. 1597 * Parameters: 1598 * unit - (IN) unit number 1599 * gport - (IN) 1600 * cb - (IN) Callback function. 1601 * user_data - (IN) User data to be passed to callback function 1602 * Returns: 1603 * BCM_E_NONE - Success. 1604 * BCM_E_XXX 1605 */ 1606 int 1607 _bcm_mn_cosq_gport_traverse(int unit, bcm_gport_t gport, 1608 bcm_cosq_gport_traverse_cb cb, 1609 void *user_data) 1610 { 1611 _bcm_mn_cosq_node_t *node; 1612 uint32 flags = BCM_COSQ_GPORT_SCHEDULER; 1613 bcm_port_t port, port_out; 1614 bcm_module_t modid, modid_out; 1615 bcm_gport_t gport_out; 1616 int rv = BCM_E_NONE; 1617 1618 BCM_IF_ERROR_RETURN 1619 (_bcm_mn_cosq_node_get(unit, gport, 0, &modid, &port, NULL, &node)); 1620 1621 if (node != NULL) { 1622 if (!soc_feature(unit, soc_feature_mmu_hqos_four_level) && 1623 node->level == SOC_MONTEREY_NODE_LVL_ROOT) 1624 { 1625 node = node->child; 1626 if (!node) 1627 { 1628 return BCM_E_NONE; 1629 } 1630 } 1631 if (node->level == SOC_MONTEREY_NODE_LVL_L2) { 1632 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(node->gport)) { 1633 flags = BCM_COSQ_GPORT_UCAST_QUEUE_GROUP; 1634 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(node->gport)) { 1635 flags = BCM_COSQ_GPORT_MCAST_QUEUE_GROUP; 1636 } 1637 } else { 1638 flags = BCM_COSQ_GPORT_SCHEDULER; 1639 } 1640 BCM_IF_ERROR_RETURN 1641 (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, modid, port, 1642 &modid_out, &port_out)); 1643 BCM_GPORT_MODPORT_SET(gport_out, modid_out, port_out); 1644 1645 rv = cb(unit, gport_out, node->numq, flags, 1646 node->gport, user_data); 1647 if (BCM_FAILURE(rv)) { 1648 #ifdef BCM_CB_ABORT_ON_ERR 1649 if (SOC_CB_ABORT_ON_ERR(unit)) { 1650 return rv; 1651 } 1652 #endif 1653 } 1654 } else { 1655 return BCM_E_NONE; 1656 } 1657 1658 if (node->sibling != NULL) { 1659 _bcm_mn_cosq_gport_traverse(unit, node->sibling->gport, cb, user_data); 1660 } 1661 1662 if (node->child != NULL) { 1663 _bcm_mn_cosq_gport_traverse(unit, node->child->gport, cb, user_data); 1664 } 1665 1666 return BCM_E_NONE; 1667 } 1668 1669 STATIC int 1670 _bcm_mn_cosq_child_node_at_input(_bcm_mn_cosq_node_t *node, int cosq, 1671 _bcm_mn_cosq_node_t **child_node) 1672 { 1673 _bcm_mn_cosq_node_t *cur_node; 1674 1675 for (cur_node = node->child; cur_node; cur_node = cur_node->sibling) { 1676 if (cur_node->attached_to_input == (cosq % _BCM_MN_HSP_PORT_MAX_COS)) { 1677 break; 1678 } 1679 } 1680 if (!cur_node) { 1681 return BCM_E_NOT_FOUND; 1682 } 1683 1684 *child_node = cur_node; 1685 1686 return BCM_E_NONE; 1687 } 1688 1689 STATIC int 1690 _bcm_mn_cosq_l2_gport(int unit, int port, int cosq, 1691 _bcm_mn_node_type_e type, bcm_gport_t *gport, 1692 _bcm_mn_cosq_node_t **p_node) 1693 { 1694 int i, max; 1695 _bcm_mn_cosq_node_t *node, *fnode; 1696 _bcm_mn_mmu_info_t *mmu_info; 1697 _bcm_mn_cosq_port_info_t *port_info; 1698 _bcm_mn_pipe_resources_t *res; 1699 1700 mmu_info = _bcm_mn_mmu_info[unit]; 1701 port_info = &mmu_info->port_info[port]; 1702 res = port_info->resources; 1703 1704 max = 0; 1705 if ((type == _BCM_MN_NODE_UCAST) || (type == _BCM_MN_NODE_VOQ) || 1706 (type == _BCM_MN_NODE_VLAN_UCAST) || (type == _BCM_MN_NODE_VM_UCAST) || 1707 (type == _BCM_MN_NODE_SERVICE_UCAST)) { 1708 max = _BCM_MN_NUM_L2_UC_LEAVES; 1709 fnode = &res->p_queue_node[0]; 1710 } else if (type == _BCM_MN_NODE_MCAST) { 1711 max = _BCM_MN_NUM_L2_MC_LEAVES; 1712 fnode = &res->p_mc_queue_node[0]; 1713 } else { 1714 return BCM_E_PARAM; 1715 } 1716 1717 for (i = 0; i < max; i++) { 1718 node = fnode + i; 1719 if (node->in_use && (node->local_port == port) && 1720 (node->type == type) && (node->hw_cosq == cosq)) { 1721 if (gport) { 1722 *gport = node->gport; 1723 } 1724 if (p_node) { 1725 *p_node = node; 1726 } 1727 return BCM_E_NONE; 1728 } 1729 } 1730 return BCM_E_NOT_FOUND; 1731 } 1732 1733 /* 1734 * Function: 1735 * _bcm_mn_cosq_index_resolve 1736 * Purpose: 1737 * Find hardware index for the given port/cosq 1738 * Parameters: 1739 * unit - (IN) unit number 1740 * port - (IN) port number or GPORT identifier 1741 * cosq - (IN) COS queue number 1742 * style - (IN) index style (_BCM_KA_COSQ_INDEX_STYLE_XXX) 1743 * local_port - (OUT) local port number 1744 * index - (OUT) result index 1745 * count - (OUT) number of index 1746 * Returns: 1747 * BCM_E_XXX 1748 */ 1749 int 1750 _bcm_mn_cosq_index_resolve(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 1751 _bcm_mn_cosq_index_style_t style, 1752 bcm_port_t *local_port, int *index, int *count) 1753 { 1754 _bcm_mn_cosq_node_t *node, *cur_node , *s1_node; 1755 bcm_port_t resolved_port; 1756 int resolved_index = -1; 1757 int id, startq, numq; 1758 soc_info_t *si; 1759 int phy_port, mmu_port; 1760 uint32 entry0[SOC_MAX_MEM_WORDS]; 1761 soc_mem_t mem; 1762 _bcm_mn_mmu_info_t *mmu_info; 1763 si = &SOC_INFO(unit); 1764 1765 mmu_info = _bcm_mn_mmu_info[unit]; 1766 if (cosq < -1) { 1767 return BCM_E_PARAM; 1768 } else if (cosq == -1) { 1769 startq = 0; 1770 numq = NUM_COS(unit); 1771 } else { 1772 startq = cosq; 1773 numq = 1; 1774 } 1775 1776 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 1777 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) || 1778 BCM_GPORT_IS_SCHEDULER(port)) { 1779 BCM_IF_ERROR_RETURN 1780 (_bcm_mn_cosq_node_get(unit, port, cosq, NULL, &resolved_port, &id, 1781 &node)); 1782 if (node->attached_to_input < 0) { /* Not resolved yet */ 1783 return BCM_E_NOT_FOUND; 1784 } 1785 numq = (node->numq != -1) ? node->numq : 64; 1786 1787 } else if(_BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port)){ 1788 BCM_IF_ERROR_RETURN( 1789 _bcmi_coe_subport_physical_port_get(unit, port, &resolved_port)); 1790 BCM_IF_ERROR_RETURN 1791 (_bcm_mn_get_s1_node(unit, port, &s1_node)); 1792 node = &mmu_info->queue_node[s1_node->coe_base_index + startq ]; 1793 if (node->attached_to_input < 0) { /* Not resolved yet */ 1794 return BCM_E_NOT_FOUND; 1795 } 1796 numq = _MN_NUM_COS(unit); 1797 } else { 1798 /* optionally validate port */ 1799 BCM_IF_ERROR_RETURN 1800 (_bcm_mn_cosq_localport_resolve(unit, port, &resolved_port)); 1801 if (resolved_port < 0) { 1802 return BCM_E_PORT; 1803 } 1804 node = NULL; 1805 numq = (IS_CPU_PORT(unit, resolved_port)) ? NUM_CPU_COSQ(unit) : BCM_MN_COS_MAX; 1806 } 1807 1808 if (startq >= numq) { 1809 return BCM_E_PARAM; 1810 } 1811 1812 phy_port = si->port_l2p_mapping[resolved_port]; 1813 mmu_port = si->port_p2m_mapping[phy_port]; 1814 1815 switch (style) { 1816 case _BCM_MN_COSQ_INDEX_STYLE_BUCKET: 1817 if (node != NULL) { 1818 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) { 1819 resolved_index = node->hw_index; 1820 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 1821 resolved_index = node->hw_index; 1822 } else if(_BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port)){ 1823 resolved_index = node->hw_index; 1824 } else if (BCM_GPORT_IS_SCHEDULER(port) || BCM_GPORT_IS_MODPORT(port)) { 1825 /* resolve the child attached to input cosq */ 1826 BCM_IF_ERROR_RETURN( 1827 _bcm_mn_cosq_child_node_at_input(node, startq, &cur_node)); 1828 resolved_index = cur_node->hw_index; 1829 } else { 1830 return BCM_E_PARAM; 1831 } 1832 } else { /* node == NULL */ 1833 if (IS_CPU_PORT(unit, resolved_port)) { 1834 resolved_index = SOC_INFO(unit).port_cosq_base[resolved_port] + 1835 startq; 1836 resolved_index = soc_monterey_l2_hw_index(unit, resolved_index, 0); 1837 } else { 1838 resolved_index = soc_monterey_l2_hw_index(unit, 1839 si->port_uc_cosq_base[resolved_port] + startq, 1); 1840 if (!IS_MN_HSP_PORT(unit, resolved_port)) { 1841 mem = _SOC_MONTEREY_NODE_PARENT_MEM(unit, port, SOC_MONTEREY_NODE_LVL_L2); 1842 SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, resolved_index, &entry0)); 1843 resolved_index = soc_mem_field32_get(unit, mem, entry0, C_PARENTf); 1844 } 1845 } 1846 } 1847 break; 1848 1849 case _BCM_MN_COSQ_INDEX_STYLE_QCN: 1850 if (node != NULL) { 1851 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) { 1852 resolved_index = node->hw_index; 1853 } else { 1854 return BCM_E_PARAM; 1855 } 1856 } else { /* node == NULL */ 1857 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_port_has_ets(unit, resolved_port)); 1858 if (IS_CPU_PORT(unit, resolved_port)) { 1859 return BCM_E_PARAM; 1860 } else { 1861 resolved_index = soc_monterey_l2_hw_index(unit, 1862 si->port_uc_cosq_base[resolved_port] + startq, 1); 1863 } 1864 } 1865 break; 1866 1867 case _BCM_MN_COSQ_INDEX_STYLE_WRED: 1868 if (node != NULL) { 1869 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) { 1870 resolved_index = node->hw_index + startq; 1871 } else if (BCM_GPORT_IS_SCHEDULER(port)) { 1872 BCM_IF_ERROR_RETURN( 1873 _bcm_mn_cosq_child_node_at_input(node, startq, &cur_node)); 1874 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(cur_node->gport)) { 1875 resolved_index = cur_node->hw_index; 1876 } else { 1877 return BCM_E_PARAM; 1878 } 1879 } else if(_BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port)){ 1880 resolved_index = node->hw_index ; 1881 } else if (BCM_GPORT_IS_MODPORT(port)) { 1882 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_l2_gport(unit, node->local_port, 1883 startq, _BCM_MN_NODE_UCAST, NULL, &cur_node)); 1884 resolved_index = cur_node->hw_index ; 1885 } else { 1886 return BCM_E_PARAM; 1887 } 1888 } else { /* node == NULL */ 1889 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_port_has_ets(unit, resolved_port)); 1890 resolved_index = soc_monterey_l2_hw_index(unit, 1891 si->port_uc_cosq_base[resolved_port] + startq, 1); 1892 numq = 1; 1893 } 1894 break; 1895 1896 case _BCM_MN_COSQ_INDEX_STYLE_WRED_PORT: 1897 resolved_index = _BCM_PORT_SERVICE_POOL + (mmu_port * 4); 1898 numq = 4; 1899 break; 1900 1901 case _BCM_MN_COSQ_INDEX_STYLE_SCHEDULER: 1902 if (node != NULL) { 1903 if (!BCM_GPORT_IS_SCHEDULER(port)) { 1904 return BCM_E_PARAM; 1905 } 1906 BCM_IF_ERROR_RETURN( 1907 _bcm_mn_cosq_child_node_at_input(node, startq, &cur_node)); 1908 resolved_index = cur_node->hw_index; 1909 } else { /* node == NULL */ 1910 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_port_has_ets(unit, resolved_port)); 1911 if (IS_CPU_PORT(unit, resolved_port)) { 1912 resolved_index = soc_monterey_l2_hw_index(unit, 1913 si->port_cosq_base[resolved_port] + startq, 0); 1914 } else { 1915 resolved_index = soc_monterey_l2_hw_index(unit, 1916 si->port_uc_cosq_base[resolved_port] + startq, 1); 1917 } 1918 } 1919 break; 1920 1921 case _BCM_MN_COSQ_INDEX_STYLE_COS: 1922 if (node) { 1923 if ((BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) || 1924 (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port))) { 1925 resolved_index = node->hw_cosq; 1926 } else if (BCM_GPORT_IS_SCHEDULER(port)) { 1927 BCM_IF_ERROR_RETURN( 1928 _bcm_mn_cosq_child_node_at_input(node, startq, &cur_node)); 1929 if (BCM_GPORT_IS_SCHEDULER(cur_node->gport)) { 1930 return BCM_E_PARAM; 1931 } 1932 resolved_index = cur_node->hw_cosq; 1933 } else if(_BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port)){ 1934 resolved_index = node->hw_cosq ; 1935 } 1936 } else { 1937 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_port_has_ets(unit, resolved_port)); 1938 resolved_index = startq; 1939 } 1940 break; 1941 1942 case _BCM_MN_COSQ_INDEX_STYLE_UCAST_QUEUE: 1943 if (node) { 1944 resolved_index = node->hw_index + startq; 1945 numq = 1; 1946 } else { 1947 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_port_has_ets(unit, resolved_port)); 1948 numq = 1; 1949 resolved_index = soc_monterey_l2_hw_index(unit, 1950 si->port_uc_cosq_base[resolved_port] + startq, 1); 1951 } 1952 break; 1953 1954 case _BCM_MN_COSQ_INDEX_STYLE_MCAST_QUEUE: 1955 if (node) { 1956 resolved_index = node->hw_index + startq; 1957 numq = 1; 1958 } else { 1959 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_port_has_ets(unit, resolved_port)); 1960 numq = 1; 1961 resolved_index = soc_monterey_l2_hw_index(unit, 1962 si->port_cosq_base[resolved_port] + startq, 0); 1963 } 1964 break; 1965 1966 case _BCM_MN_COSQ_INDEX_STYLE_EGR_POOL: 1967 if ((node != NULL) && (!BCM_GPORT_IS_MODPORT(port))) { 1968 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) { 1969 /* regular unicast queue */ 1970 resolved_index = soc_monterey_l2_hw_index(unit, node->hw_index + startq, 1); 1971 mem = MMU_THDU_XPIPE_Q_TO_QGRP_MAPm; 1972 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 1973 resolved_index = soc_monterey_l2_hw_index(unit, 1974 si->port_cosq_base[resolved_port] + startq, 0) - 1975 _BCM_MN_NUM_L2_UC_LEAVES; 1976 mem = MMU_THDM_MCQE_QUEUE_CONFIG_0m; 1977 } else { /* scheduler */ 1978 return BCM_E_PARAM; 1979 } 1980 } else { /* node == NULL */ 1981 if (IS_CPU_PORT(unit, resolved_port) || 1982 IS_LB_PORT(unit, resolved_port)) { 1983 return BCM_E_PARAM; 1984 } 1985 numq = si->port_num_cosq[resolved_port]; 1986 if (startq >= numq) { 1987 return BCM_E_PARAM; 1988 } 1989 resolved_index = soc_monterey_l2_hw_index(unit, 1990 si->port_cosq_base[resolved_port] + startq, 0) - 1991 _BCM_MN_NUM_L2_UC_LEAVES ; 1992 mem = MMU_THDM_MCQE_QUEUE_CONFIG_0m; 1993 } 1994 1995 SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, resolved_index, 1996 entry0)); 1997 1998 resolved_index = soc_mem_field32_get(unit, mem, entry0, Q_SPIDf); 1999 2000 break; 2001 case _BCM_MN_COSQ_INDEX_STYLE_UC_EGR_POOL: 2002 if (IS_CPU_PORT(unit, resolved_port) || 2003 IS_LB_PORT(unit, resolved_port)) { 2004 return BCM_E_PARAM; 2005 } 2006 2007 numq = si->port_num_uc_cosq[resolved_port]; 2008 if (startq >= numq) { 2009 return BCM_E_PARAM; 2010 } 2011 2012 resolved_index = soc_monterey_l2_hw_index(unit, 2013 si->port_uc_cosq_base[resolved_port] + startq, 1); 2014 mem = MMU_THDU_XPIPE_Q_TO_QGRP_MAPm; 2015 2016 SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, resolved_index, 2017 entry0)); 2018 2019 resolved_index = soc_mem_field32_get(unit, mem, entry0, Q_SPIDf); 2020 break; 2021 2022 case _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_UCAST: 2023 if (node) { 2024 resolved_index = node->hw_index + startq; 2025 resolved_index -= soc_monterey_l2_hw_index(unit, 2026 si->port_uc_cosq_base[resolved_port], 1); 2027 numq = 1; 2028 } else { 2029 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_port_has_ets(unit, resolved_port)); 2030 numq = 1; 2031 resolved_index = startq; 2032 } 2033 break; 2034 2035 case _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_MCAST: 2036 if (node) { 2037 resolved_index = node->hw_index + startq; 2038 resolved_index -= soc_monterey_l2_hw_index(unit, 2039 si->port_cosq_base[resolved_port], 0); 2040 numq = 1; 2041 } else { 2042 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_port_has_ets(unit, resolved_port)); 2043 numq = 1; 2044 resolved_index = startq; 2045 } 2046 break; 2047 case _BCM_MN_COSQ_INDEX_STYLE_UCAST_QUEUE_GROUP: 2048 if (IS_CPU_PORT(unit, resolved_port) || 2049 IS_LB_PORT(unit, resolved_port)) { 2050 return BCM_E_PARAM; 2051 } 2052 if (node) { 2053 resolved_index = node->hw_index + startq; 2054 numq = 1; 2055 } else { 2056 /* Not support -1 for queue group index resolving, as group may not consecutive */ 2057 if (cosq == -1) { 2058 return BCM_E_PARAM; 2059 } 2060 numq = 1; 2061 resolved_index = si->port_uc_cosq_base[resolved_port] + startq; 2062 } 2063 mem = MMU_THDU_XPIPE_Q_TO_QGRP_MAPm; 2064 SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, 2065 resolved_index, entry0)); 2066 if (soc_mem_field32_get(unit, mem, entry0, QGROUP_VALIDf)) { 2067 resolved_index = soc_mem_field32_get(unit, mem, entry0, QGROUPf); 2068 } else { 2069 return BCM_E_NOT_FOUND; 2070 } 2071 break; 2072 default: 2073 return BCM_E_INTERNAL; 2074 } 2075 2076 if (local_port != NULL) { 2077 *local_port = resolved_port; 2078 } 2079 if (index != NULL) { 2080 *index = resolved_index; 2081 } 2082 if (count != NULL) { 2083 *count = (cosq == -1) ? numq : 1; 2084 } 2085 2086 return BCM_E_NONE; 2087 } 2088 2089 STATIC int _bcm_mn_cosq_min_child_index(_bcm_mn_cosq_node_t *child, int lvl, int uc) 2090 { 2091 int min_index = -1; 2092 2093 if ((lvl == SOC_MONTEREY_NODE_LVL_L2) && (uc)) { 2094 while (child) { 2095 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(child->gport)) { 2096 if (min_index == -1) { 2097 min_index = child->hw_index; 2098 } 2099 2100 if (child->hw_index < min_index) { 2101 min_index = child->hw_index; 2102 } 2103 } 2104 child = child->sibling; 2105 } 2106 } else if ((lvl == SOC_MONTEREY_NODE_LVL_L2) && (!uc)) { 2107 while (child) { 2108 if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(child->gport)) { 2109 if (min_index == -1) { 2110 min_index = child->hw_index; 2111 } 2112 2113 if (child->hw_index < min_index) { 2114 min_index = child->hw_index; 2115 } 2116 } 2117 child = child->sibling; 2118 } 2119 } else { 2120 while (child) { 2121 if (min_index == -1) { 2122 min_index = child->hw_index; 2123 } 2124 2125 if (child->hw_index < min_index) { 2126 min_index = child->hw_index; 2127 } 2128 child = child->sibling; 2129 } 2130 } 2131 2132 return min_index; 2133 } 2134 2135 STATIC int 2136 _bcm_mn_child_state_check(int unit, bcm_port_t gport, 2137 bcm_cos_queue_t cosq, int ets_mode) 2138 { 2139 _bcm_mn_cosq_node_t *node, *child_node = NULL; 2140 bcm_port_t local_port; 2141 int level, sch_index, empty = 0; 2142 int rv = BCM_E_NONE; 2143 soc_timeout_t timeout; 2144 uint32 timeout_val; 2145 uint32 entry[SOC_MAX_MEM_WORDS]; 2146 soc_mem_t mem = INVALIDm; 2147 static const soc_mem_t memx[] = { 2148 INVALIDm, 2149 LLS_L0_CHILD_STATE1m, 2150 LLS_L1_CHILD_STATE1m, 2151 LLS_L2_CHILD_STATE1m 2152 }; 2153 2154 /* Timeout val = Static for now. Need to quantify the max wait time */ 2155 timeout_val = 2000000; 2156 2157 BCM_IF_ERROR_RETURN 2158 (_bcm_mn_cosq_localport_resolve(unit, gport, &local_port)); 2159 2160 if (ets_mode & (!IS_MN_HSP_PORT(unit, local_port))) { 2161 BCM_IF_ERROR_RETURN 2162 (_bcm_mn_cosq_node_get(unit, gport, 0, NULL, 2163 &local_port, NULL, &node)); 2164 2165 /* Get the Child node for the Given Gport */ 2166 rv = _bcm_mn_cosq_child_node_at_input(node, cosq, &child_node); 2167 2168 if ((!child_node) || (rv == BCM_E_NOT_FOUND)) { 2169 /* No Child present */ 2170 return BCM_E_NONE; 2171 } 2172 2173 BCM_IF_ERROR_RETURN 2174 (_bcm_mn_cosq_localport_resolve(unit, gport, &local_port)); 2175 2176 level = child_node->level; 2177 sch_index = child_node->hw_index; 2178 2179 /* Child State Check is NOT necessary for Non-L0/L1/L2 levels */ 2180 if ((level < SOC_MONTEREY_NODE_LVL_L0) || (level > SOC_MONTEREY_NODE_LVL_L2)) { 2181 /* Sanity for Node's level should be done in the caller */ 2182 return BCM_E_NONE; 2183 } 2184 2185 mem = memx[level]; 2186 2187 if (mem == INVALIDm) { 2188 return BCM_E_INTERNAL; 2189 } 2190 2191 soc_timeout_init(&timeout, timeout_val, 0); 2192 2193 for(;;) { 2194 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, 2195 sch_index, entry)); 2196 empty = 0; 2197 if (soc_timeout_check(&timeout)) { 2198 LOG_ERROR(BSL_LS_BCM_COMMON, 2199 (BSL_META_U(unit, 2200 "ERROR: Timeout during Child lists Not zero\n"))); 2201 return BCM_E_BUSY; 2202 } 2203 empty += soc_mem_field32_get(unit, mem, &entry, C_ACTIVE_0f); 2204 empty += soc_mem_field32_get(unit, mem, &entry, C_ON_MIN_LIST_0f); 2205 empty += soc_mem_field32_get(unit, mem, &entry, C_NOT_EMPTY_0f); 2206 2207 if (!empty) { 2208 break; 2209 } 2210 } 2211 } else { 2212 /* TBD: Non-ETS mode not supported. May not be possible to support the same on HSP queues */ 2213 return BCM_E_NONE; 2214 } 2215 2216 return BCM_E_NONE; 2217 } 2218 2219 STATIC int 2220 _bcm_mn_cosq_node_queue_state_check(int unit, 2221 _bcm_mn_cosq_node_t *node, int ets_mode) 2222 { 2223 int cosq = 0; 2224 2225 if (node == NULL) { 2226 return BCM_E_PARAM; 2227 } 2228 2229 for (cosq = 0; cosq < node->numq; cosq++) { 2230 BCM_IF_ERROR_RETURN 2231 (_bcm_mn_child_state_check(unit, node->gport, 2232 cosq, ets_mode)); 2233 } 2234 2235 if ((node->level <= SOC_MONTEREY_NODE_LVL_L1) && 2236 (node->child != NULL)) { 2237 BCM_IF_ERROR_RETURN 2238 (_bcm_mn_cosq_node_queue_state_check(unit, 2239 node->child,ets_mode)); 2240 } 2241 2242 if (node->sibling != NULL) { 2243 2244 BCM_IF_ERROR_RETURN 2245 (_bcm_mn_cosq_node_queue_state_check(unit, 2246 node->sibling,ets_mode)); 2247 } 2248 2249 return BCM_E_NONE; 2250 } 2251 2252 int 2253 _bcm_mn_cosq_port_queue_state_check(int unit, bcm_port_t gport) 2254 { 2255 bcm_port_t local_port; 2256 int ets_mode; 2257 _bcm_mn_cosq_node_t *node; 2258 2259 BCM_IF_ERROR_RETURN 2260 (_bcm_mn_cosq_localport_resolve(unit, gport, &local_port)); 2261 ets_mode = _bcm_mn_cosq_port_has_ets(unit, local_port); 2262 if (!ets_mode) { 2263 return BCM_E_NONE; 2264 } 2265 2266 BCM_IF_ERROR_RETURN 2267 (bcm_esw_port_gport_get(unit, local_port, 2268 &gport)); 2269 2270 BCM_IF_ERROR_RETURN 2271 (_bcm_mn_cosq_node_get(unit, gport, 0, NULL, 2272 NULL, NULL, &node)); 2273 2274 BCM_IF_ERROR_RETURN 2275 (_bcm_mn_cosq_node_queue_state_check(unit, 2276 node,ets_mode)); 2277 return BCM_E_NONE; 2278 } 2279 2280 2281 /* 2282 * Function: 2283 * _bcm_mn_mmu_rx_enable_set 2284 * Purpose: 2285 * enable/disable mmu rx traffic from the gport. 2286 * Parameters: 2287 * unit - (IN) unit number 2288 * gport - (IN) GPORT identifier 2289 * enable - (IN) enable/disable 2290 * Returns: 2291 * BCM_E_XXX 2292 */ 2293 STATIC int 2294 _bcm_mn_mmu_rx_enable_set(int unit, bcm_port_t local_port, 2295 int enable) 2296 { 2297 uint32 rval; 2298 2299 /* Disable/Enable INPUT_PORT_RX to the port */ 2300 SOC_IF_ERROR_RETURN 2301 (soc_reg32_get(unit, THDI_INPUT_PORT_XON_ENABLESr, 2302 local_port, 0, &rval)); 2303 2304 if (!enable) { 2305 soc_reg_field_set(unit, THDI_INPUT_PORT_XON_ENABLESr, &rval, 2306 INPUT_PORT_RX_ENABLEf, 2307 0); 2308 } else { 2309 soc_reg_field_set(unit, THDI_INPUT_PORT_XON_ENABLESr, &rval, 2310 INPUT_PORT_RX_ENABLEf, 2311 1); 2312 } 2313 2314 SOC_IF_ERROR_RETURN 2315 (soc_reg32_set(unit, THDI_INPUT_PORT_XON_ENABLESr, 2316 local_port, 0, rval)); 2317 2318 return BCM_E_NONE; 2319 } 2320 2321 STATIC int 2322 _bcm_mn_attach_node_in_hw(int unit, _bcm_mn_cosq_node_t *node) 2323 { 2324 int local_port, fc = 0, fmc = 0; 2325 _bcm_mn_cosq_node_t *child_node; 2326 int num_spri = 0, first_sp_child = 0, first_sp_mc_child; 2327 uint32 ucmap = 0, spmap = 0; 2328 soc_monterey_sched_type_t sched_type; 2329 2330 local_port = node->local_port; 2331 2332 if (node->level == SOC_MONTEREY_NODE_LVL_ROOT) { 2333 return 0; 2334 } else if (node->level == SOC_MONTEREY_NODE_LVL_L2) { 2335 fc = _bcm_mn_cosq_min_child_index(node->parent->child, SOC_MONTEREY_NODE_LVL_L2, 1); 2336 if (fc < 0) { 2337 fc = 0; 2338 } 2339 fmc = _bcm_mn_cosq_min_child_index(node->parent->child, SOC_MONTEREY_NODE_LVL_L2, 0); 2340 if (fmc < 0) { 2341 fmc = _BCM_MN_NUM_L2_UC_LEAVES; 2342 } 2343 } else { 2344 fc = _bcm_mn_cosq_min_child_index(node->parent->child, node->level, 0); 2345 fmc = 0; 2346 } 2347 2348 /* If node is scheduler, reset the scheduler and attach it to the parent.*/ 2349 BCM_IF_ERROR_RETURN( 2350 soc_monterey_cosq_set_sched_parent(unit, local_port, node->level, 2351 node->hw_index, node->parent->hw_index, 1)); 2352 2353 sched_type = _soc_monterey_port_sched_type_get(unit, local_port); 2354 2355 if (sched_type == SOC_MONTEREY_SCHED_LLS) { 2356 if (node->parent->level != SOC_MONTEREY_NODE_LVL_ROOT) { 2357 BCM_IF_ERROR_RETURN( 2358 soc_monterey_cosq_get_sched_child_config(unit, local_port, 2359 node->parent->level, 2360 node->parent->hw_index, 2361 &num_spri, &first_sp_child, 2362 &first_sp_mc_child, &ucmap, &spmap)); 2363 } 2364 /* set the node by default in WRR mode with wt=1 */ 2365 BCM_IF_ERROR_RETURN(soc_monterey_cosq_set_sched_config(unit, 2366 local_port, node->parent->level, 2367 node->parent->hw_index, node->hw_index, 2368 num_spri, fc, fmc, ucmap, spmap, 2369 SOC_MONTEREY_SCHED_MODE_WRR, 1)); 2370 } 2371 2372 2373 if (node->child) { 2374 child_node = node->child; 2375 while (child_node) { 2376 BCM_IF_ERROR_RETURN(_bcm_mn_attach_node_in_hw(unit, child_node)); 2377 child_node = child_node->sibling; 2378 } 2379 } 2380 2381 return BCM_E_NONE; 2382 } 2383 /* 2384 * Function: 2385 * _bcm_mn_cosq_map_index_get 2386 * Purpose: 2387 * Allocate free index from the given list 2388 * Parameters: 2389 * list - (IN) bit list 2390 * start - (IN) start index 2391 * end - (IN) end index 2392 * id - (OUT) start index 2393 * Returns: 2394 * BCM_E_XXX 2395 */ 2396 STATIC int 2397 _bcm_mn_cosq_map_index_get(SHR_BITDCL *list, int start, int end, int *id) 2398 { 2399 int i; 2400 2401 for (i = start; i < end; i++) { 2402 if (SHR_BITGET(list, i) != 0) { 2403 continue; 2404 } 2405 *id = i; 2406 return BCM_E_NONE; 2407 } 2408 2409 return BCM_E_RESOURCE; 2410 } 2411 2412 /* 2413 * Function: 2414 * _bcm_mn_cosq_map_index_clear 2415 * Purpose: 2416 * Mark indices as free 2417 * Parameters: 2418 * list - (IN) bit list 2419 * start - (IN) start index 2420 * range - (IN) range bits 2421 * Returns: 2422 * BCM_E_XXX 2423 */ 2424 STATIC int 2425 _bcm_mn_cosq_map_index_clear(SHR_BITDCL *list, int start, int range) 2426 { 2427 SHR_BITCLR_RANGE(list, start, range); 2428 return BCM_E_NONE; 2429 } 2430 2431 /* 2432 * Function: 2433 * _bcm_mn_cosq_map_index_is_set 2434 * Purpose: 2435 * Check index is allocated 2436 * Parameters: 2437 * list - (IN) bit list 2438 * index - (IN) index 2439 * Returns: 2440 * BCM_E_XXX 2441 */ 2442 STATIC int 2443 _bcm_mn_cosq_map_index_is_set(SHR_BITDCL *list, int index) 2444 { 2445 if (SHR_BITGET(list, index) != 0) { 2446 return TRUE; 2447 } 2448 2449 return FALSE; 2450 } 2451 /* 2452 * Function: 2453 * _bcm_mn_cosq_node_resolve 2454 * Purpose: 2455 * Resolve queue number in the specified scheduler tree and its subtree 2456 * Parameters: 2457 * unit - (IN) unit number 2458 * node - (IN) node structure for the specified scheduler node 2459 * cosq - (IN) COS queue to attach to 2460 * Returns: 2461 * BCM_E_XXX 2462 */ 2463 STATIC int 2464 _bcm_mn_cosq_node_resolve(int unit, _bcm_mn_cosq_node_t *node, 2465 bcm_cos_queue_t cosq) 2466 { 2467 _bcm_mn_cosq_node_t *cur_node, *parent; 2468 _bcm_mn_cosq_port_info_t *port_info; 2469 _bcm_mn_pipe_resources_t * res; 2470 _bcm_mn_mmu_info_t *mmu_info; 2471 _bcm_mn_cosq_list_t *list; 2472 int numq, id = -1 , prev_base = -1, rv; 2473 int valid_index_lo, valid_index_hi; 2474 bcm_port_t port; 2475 int alloc_size; 2476 int phy_port, mmu_port; 2477 int max_nodes = 0; 2478 uint32 rval = 0; 2479 uint32 mc_group_mode = 0; 2480 2481 if ((parent = node->parent) == NULL) { 2482 /* Not attached, should never happen */ 2483 return BCM_E_NOT_FOUND; 2484 } 2485 2486 if (parent->numq == 0 || parent->numq < -1) { 2487 return BCM_E_PARAM; 2488 } 2489 2490 port = node->local_port; 2491 2492 BCM_IF_ERROR_RETURN 2493 (_bcm_mn_cosq_max_nodes_get(unit, node->level, &max_nodes)); 2494 if (parent->cosq_map == NULL) { 2495 if (parent->numq == -1) { 2496 alloc_size = SHR_BITALLOCSIZE(max_nodes); 2497 } else { 2498 alloc_size = SHR_BITALLOCSIZE(parent->numq); 2499 } 2500 parent->cosq_map = _bcm_mn_cosq_alloc_clear(parent->cosq_map, 2501 alloc_size, 2502 "cosq_map"); 2503 if (parent->cosq_map == NULL) { 2504 return BCM_E_MEMORY; 2505 } 2506 } 2507 if (cosq < 0) { 2508 BCM_IF_ERROR_RETURN 2509 (_bcm_mn_cosq_map_index_get(parent->cosq_map, 2510 0, 2511 parent->numq == -1 ? 2512 max_nodes: parent->numq, &id)); 2513 BCM_IF_ERROR_RETURN 2514 (_bcm_mn_cosq_map_index_set(parent->cosq_map, id, 1)); 2515 node->attached_to_input = id; 2516 } else { 2517 if (_bcm_mn_cosq_map_index_is_set(parent->cosq_map, 2518 cosq) == TRUE) { 2519 return BCM_E_EXISTS; 2520 } 2521 if (cosq > ((parent->numq == -1) ? max_nodes : parent->numq)) { 2522 return BCM_E_PARAM; 2523 } 2524 BCM_IF_ERROR_RETURN 2525 (_bcm_mn_cosq_map_index_set(parent->cosq_map, cosq, 1)); 2526 node->attached_to_input = cosq; 2527 } 2528 2529 mmu_info = _bcm_mn_mmu_info[unit]; 2530 port_info = &mmu_info->port_info[port]; 2531 res = port_info->resources; 2532 numq = (parent->numq == -1) ? 1 : parent->numq; 2533 phy_port = SOC_INFO(unit).port_l2p_mapping[port]; 2534 mmu_port = SOC_INFO(unit).port_p2m_mapping[phy_port]; 2535 /* On Monterey mmu_port no for CPU is 65 but use 66 for node 2536 * allocation and use 65 for loopback node allocation */ 2537 if (IS_CPU_PORT(unit, port)) { 2538 mmu_port++; 2539 } else if (IS_LB_PORT(unit, port)) { 2540 mmu_port--; 2541 } 2542 switch (parent->level) { 2543 case SOC_MONTEREY_NODE_LVL_ROOT: 2544 list = &res->s1_sched_list; 2545 if (IS_MN_HSP_PORT(unit, port)) { 2546 list = &res->hsp_l0_sched_list; 2547 } 2548 if (parent->numq_expandable && parent->base_index >= 0 && 2549 parent->base_size != parent->numq) { 2550 _bcm_mn_node_index_clear(list, parent->base_index, 2551 parent->base_size); 2552 prev_base = parent->base_index; 2553 parent->base_index = -1; 2554 } 2555 if (IS_MN_HSP_PORT(unit, port)) { 2556 valid_index_lo = _BCM_MN_HSP_L0_INDEX(unit, mmu_port, 0); 2557 valid_index_hi = _BCM_MN_HSP_L0_INDEX(unit, (mmu_port + 1), 2558 0); 2559 } else { 2560 valid_index_lo = 0; 2561 valid_index_hi = _BCM_MN_NUM_S1_SCHEDULER_PER_PIPE; 2562 } 2563 2564 if (((parent->base_index < 0) && (node->attached_to_input < numq)) 2565 || (parent->numq == -1)) { 2566 rv = _bcm_mn_node_index_get(list->bits, valid_index_lo, 2567 valid_index_hi, numq, 1, &id); 2568 if (rv) { 2569 return rv; 2570 } 2571 2572 _bcm_mn_node_index_set(list, id, numq); 2573 if (parent->numq != -1) { 2574 parent->base_index = id; 2575 node->hw_index = parent->base_index + node->attached_to_input; 2576 parent->base_size = numq; 2577 if ((prev_base >= 0) && (prev_base != id)) { 2578 for (cur_node = parent->child; cur_node; 2579 cur_node = cur_node->sibling) { 2580 if (cur_node->attached_to_input >= 0) { 2581 cur_node->hw_index = parent->base_index + 2582 cur_node->attached_to_input; 2583 BCM_IF_ERROR_RETURN(_bcm_mn_attach_node_in_hw(unit, cur_node)); 2584 } 2585 } 2586 } 2587 } else { 2588 node->hw_index = id; 2589 } 2590 } else if (node->attached_to_input >= numq) { 2591 rv = _bcm_mn_node_index_get(list->bits, valid_index_lo, 2592 valid_index_hi, 1, 1, &id); 2593 if (rv) { 2594 return rv; 2595 } 2596 _bcm_mn_node_index_set(list, id, 1); 2597 node->hw_index = id; 2598 2599 } else { 2600 node->hw_index = parent->base_index + node->attached_to_input; 2601 } 2602 node->hw_cosq = node->attached_to_input; 2603 node->wrr_in_use = 1; 2604 2605 break; 2606 2607 case SOC_MONTEREY_NODE_LVL_S1: 2608 if (IS_MN_HSP_PORT(unit, port)) { 2609 return BCM_E_PARAM; 2610 } 2611 list = &res->l0_sched_list; 2612 if (parent->numq_expandable && parent->base_index >= 0 && 2613 parent->base_size != parent->numq) { 2614 _bcm_mn_node_index_clear(list, parent->base_index, 2615 parent->base_size); 2616 prev_base = parent->base_index; 2617 parent->base_index = -1; 2618 } 2619 valid_index_lo = 0; 2620 valid_index_hi = _BCM_MN_NUM_L0_SCHEDULER_PER_PIPE; 2621 if (IS_CPU_PORT(unit, port)) { 2622 list = &res->cpu_l0_sched_list; 2623 valid_index_lo = 0; 2624 valid_index_hi = _BCM_MN_CPU_PORT_L0_MAX - _BCM_MN_CPU_PORT_L0_MIN; 2625 } 2626 2627 if (((parent->base_index < 0) && (node->attached_to_input < numq)) 2628 || (parent->numq == -1)) { 2629 if (_BCM_DEFAULT_LLS_IS_SET(mmu_info)) { 2630 rv = _bcm_mn_node_index_get(list->bits, valid_index_lo, 2631 valid_index_hi, numq, _BCM_MN_START_INDEX_ALIGN_PFC, 2632 &id); 2633 } else { 2634 rv = _bcm_mn_node_index_get(list->bits, valid_index_lo, 2635 valid_index_hi, numq, _BCM_MN_START_INDEX_ALIGN_DEFAULT, 2636 &id); 2637 } 2638 if (rv) { 2639 return rv; 2640 } 2641 2642 _bcm_mn_node_index_set(list, id, numq); 2643 if (IS_CPU_PORT(unit, port)) { 2644 id += _BCM_MN_CPU_PORT_L0_MIN; 2645 } 2646 if (parent->numq != -1) { 2647 parent->base_index = id; 2648 node->hw_index = parent->base_index + node->attached_to_input; 2649 parent->base_size = numq; 2650 if ((prev_base >= 0) && (prev_base != id)) { 2651 for (cur_node = parent->child; cur_node; 2652 cur_node = cur_node->sibling) { 2653 if (cur_node->attached_to_input >= 0) { 2654 cur_node->hw_index = parent->base_index + 2655 cur_node->attached_to_input; 2656 BCM_IF_ERROR_RETURN(_bcm_mn_attach_node_in_hw(unit, cur_node)); 2657 } 2658 } 2659 } 2660 } else { 2661 node->hw_index = id; 2662 } 2663 } else if (node->attached_to_input >= numq) { 2664 rv = _bcm_mn_node_index_get(list->bits, valid_index_lo, 2665 valid_index_hi, 1, 1, &id); 2666 if (rv) { 2667 return rv; 2668 } 2669 _bcm_mn_node_index_set(list, id, 1); 2670 node->hw_index = id; 2671 } else { 2672 node->hw_index = parent->base_index + node->attached_to_input; 2673 } 2674 node->hw_cosq = node->attached_to_input; 2675 2676 break; 2677 2678 2679 case SOC_MONTEREY_NODE_LVL_L0: 2680 if (IS_MN_HSP_PORT(unit, port)) { 2681 if (node->attached_to_input >= _BCM_MN_HSP_PORT_MAX_L1) { 2682 return BCM_E_PARAM; 2683 } 2684 2685 if ((parent->hw_index % _BCM_MN_HSP_PORT_MAX_L0) == 0) { 2686 /* L0.0 could only be attached by MC nodes */ 2687 if (node->type == _BCM_MN_NODE_MCAST) { 2688 SOC_IF_ERROR_RETURN( 2689 READ_HSP_SCHED_PORT_CONFIGr(unit, port, &rval)); 2690 mc_group_mode = soc_reg_field_get( 2691 unit, HSP_SCHED_PORT_CONFIGr, 2692 rval, MC_GROUP_MODEf); 2693 /* check mc group mode and the node offset */ 2694 if ((!mc_group_mode) || 2695 (((node->hw_index -_BCM_MN_NUM_L2_UC_LEAVES_PER_PIPE) % _BCM_MN_HSP_PORT_MAX_L1) >= 2696 _BCM_MN_HSP_PORT_MAX_COS)) { 2697 return BCM_E_PARAM; 2698 } 2699 break; 2700 } else { 2701 if (!IS_SPECIAL_PORT(unit, port)) { 2702 return BCM_E_PARAM; 2703 } 2704 } 2705 } 2706 2707 list = &res->hsp_l1_sched_list; 2708 valid_index_lo = _BCM_MN_HSP_L1_INDEX(unit, mmu_port, 0); 2709 valid_index_hi = _BCM_MN_HSP_L1_INDEX(unit, (mmu_port + 1), 2710 0); 2711 BCM_IF_ERROR_RETURN(_bcm_mn_node_index_get(list->bits, valid_index_lo, 2712 valid_index_hi, 1, 1, &id)); 2713 if (parent->base_index == -1) { 2714 parent->base_index = id; 2715 } 2716 node->hw_index = id; 2717 2718 if ((node->hw_index % _BCM_MN_HSP_PORT_MAX_L1) >= 8) { 2719 if ((parent->hw_index % _BCM_MN_HSP_PORT_MAX_L0) != 4) { 2720 return BCM_E_PARAM; 2721 } 2722 } else { 2723 if ((parent->hw_index % _BCM_MN_HSP_PORT_MAX_L0) == 4) { 2724 return BCM_E_PARAM; 2725 } 2726 } 2727 _bcm_mn_node_index_set(list, id, 1); 2728 } else { 2729 list = &res->l1_sched_list; 2730 if (((parent->base_index < 0) && (node->attached_to_input < numq)) 2731 || (parent->numq == -1)) { 2732 if (_BCM_DEFAULT_LLS_IS_SET(mmu_info)) { 2733 BCM_IF_ERROR_RETURN(_bcm_mn_node_index_get(list->bits, 0, 2734 _BCM_MN_NUM_L1_SCHEDULER_PER_PIPE, numq, 2735 _BCM_MN_START_INDEX_ALIGN_PFC, &id)); 2736 } else { 2737 BCM_IF_ERROR_RETURN(_bcm_mn_node_index_get(list->bits, 0, 2738 _BCM_MN_NUM_L1_SCHEDULER_PER_PIPE, numq, 2739 _BCM_MN_START_INDEX_ALIGN_DEFAULT, &id)); 2740 } 2741 2742 _bcm_mn_node_index_set(list, id, numq); 2743 parent->base_size = numq; 2744 if (parent->base_index == -1) { 2745 parent->base_index = id; 2746 } 2747 if (parent->numq != -1) { 2748 node->hw_index = parent->base_index + node->attached_to_input; 2749 } else { 2750 node->hw_index = id; 2751 } 2752 } else if (node->attached_to_input >= numq) { 2753 2754 BCM_IF_ERROR_RETURN(_bcm_mn_node_index_get(list->bits, 0, 2755 _BCM_MN_NUM_L1_SCHEDULER_PER_PIPE, 1, 1, &id)); 2756 _bcm_mn_node_index_set(list, id, 1); 2757 node->hw_index = id; 2758 } else { 2759 node->hw_index = parent->base_index + node->attached_to_input; 2760 } 2761 } 2762 node->hw_cosq = node->attached_to_input; 2763 2764 break; 2765 2766 case SOC_MONTEREY_NODE_LVL_L1: 2767 if (IS_MN_HSP_PORT(unit, port)) { 2768 uint32 rval = 0; 2769 uint32 mc_group_mode = 0; 2770 SOC_IF_ERROR_RETURN( 2771 READ_HSP_SCHED_PORT_CONFIGr(unit, port, &rval)); 2772 mc_group_mode = soc_reg_field_get(unit, HSP_SCHED_PORT_CONFIGr, 2773 rval, MC_GROUP_MODEf); 2774 if (mc_group_mode && 2775 ((node->hw_index % _BCM_MN_HSP_PORT_MAX_L1) < 2776 _BCM_MN_HSP_PORT_MAX_COS)) { 2777 if (node->attached_to_input >= 1) { 2778 return BCM_E_PARAM; 2779 } 2780 if (node->type == _BCM_MN_NODE_MCAST) { 2781 return BCM_E_PARAM; 2782 } 2783 } else { 2784 if (!IS_SPECIAL_PORT(unit, port)) { 2785 if (node->attached_to_input >= _BCM_MN_HSP_PORT_MAX_L2_PER_L1) { 2786 return BCM_E_PARAM; 2787 } 2788 if ((node->sibling) && 2789 (node->type == node->sibling->type)) { 2790 return BCM_E_PARAM; 2791 } 2792 } 2793 } 2794 } 2795 if ((node->hw_index == -1) && 2796 (node->type != _BCM_MN_NODE_VOQ)) { 2797 return BCM_E_PARAM; 2798 } else if (node->type == _BCM_MN_NODE_VOQ) { 2799 if (parent->base_index < 0) { 2800 BCM_IF_ERROR_RETURN( 2801 _bcm_mn_node_index_get(res->l2_queue_list.bits, 2802 res->num_base_queues, 2803 _BCM_MN_NUM_L2_UC_LEAVES_PER_PIPE , 2804 _MN_NUM_COS(unit), 2805 _MN_NUM_COS(unit), &id)); 2806 /* The following logic is to make sure the id is always 2807 * multiple of 8 2808 */ 2809 while ( id % 8 != 0) { 2810 id = ((id + 8) & 0xfffffff8); 2811 if (id > _BCM_MN_NUM_L2_UC_LEAVES_PER_PIPE ) { 2812 return BCM_E_RESOURCE; 2813 } 2814 BCM_IF_ERROR_RETURN( 2815 _bcm_mn_node_index_get(res->l2_queue_list.bits, id, 2816 _BCM_MN_NUM_L2_UC_LEAVES_PER_PIPE, 2817 NUM_COS(unit), 2818 NUM_COS(unit), &id)); 2819 } 2820 _bcm_mn_node_index_set(&res->l2_queue_list, id, 2821 (parent->numq == -1) ? _MN_NUM_COS(unit) : parent->numq); 2822 parent->base_index = id ; 2823 node->hw_index = parent->base_index; 2824 node->hw_cosq = node->hw_index % 2825 ((parent->numq == -1) ? _MN_NUM_COS(unit) : parent->numq); 2826 } else { 2827 node->hw_index = parent->base_index + 2828 node->attached_to_input; 2829 node->hw_cosq = node->hw_index % NUM_COS(unit); 2830 } 2831 } else if((node->hw_index != -1) && (parent->base_index < 0)) { 2832 parent->base_index = node->hw_index; 2833 } 2834 break; 2835 2836 case SOC_MONTEREY_NODE_LVL_L2: 2837 /* passthru */ 2838 default: 2839 return BCM_E_PARAM; 2840 2841 } 2842 2843 BCM_IF_ERROR_RETURN(_bcm_mn_attach_node_in_hw(unit, node)); 2844 return BCM_E_NONE; 2845 } 2846 2847 STATIC int 2848 _bcm_mn_detach_node_in_hw(int unit, _bcm_mn_cosq_node_t *node) 2849 { 2850 int local_port; 2851 2852 local_port = node->local_port; 2853 2854 if (!IS_MN_HSP_PORT(unit, local_port)) { 2855 BCM_IF_ERROR_RETURN( 2856 _bcm_mn_cosq_sched_parent_child_set(unit, 2857 local_port, node->parent->level, node->parent->hw_index, 2858 node->hw_index, SOC_TD2_SCHED_MODE_WRR, 1, node)); 2859 } 2860 2861 return BCM_E_NONE; 2862 } 2863 2864 /* 2865 * Function: 2866 * _bcm_mn_cosq_clear_child_list 2867 * Purpose: 2868 * Reset the child list to 0. To be called when deleting the node. 2869 * Parameters: 2870 * unit - (IN) unit number 2871 * node - (IN) node structure for the specified scheduler node 2872 * Returns: 2873 * BCM_E_XXX 2874 */ 2875 STATIC int 2876 _bcm_mn_cosq_clear_child_list(int unit, _bcm_mn_cosq_node_t *node) 2877 { 2878 _bcm_mn_mmu_info_t *mmu_info; 2879 _bcm_mn_pipe_resources_t * res; 2880 _bcm_mn_cosq_port_info_t *port_info; 2881 _bcm_mn_cosq_list_t *list; 2882 int start_index = 0, numq = 0; 2883 int port; 2884 2885 mmu_info = _bcm_mn_mmu_info[unit]; 2886 BCM_IF_ERROR_RETURN 2887 (_bcm_mn_cosq_node_get(unit, node->gport, 0, NULL, &port, NULL, NULL)); 2888 2889 port_info = &mmu_info->port_info[port]; 2890 res = port_info->resources; 2891 2892 list = NULL; 2893 switch (node->level) { 2894 case SOC_MONTEREY_NODE_LVL_ROOT: 2895 if (IS_MN_HSP_PORT(unit, port)) { 2896 list = &res->hsp_l0_sched_list; 2897 start_index = node->base_index; 2898 numq = (node->numq == -1) ? 2899 _BCM_MN_HSP_PORT_MAX_L0 : node->numq; 2900 } 2901 break; 2902 default: 2903 return BCM_E_NONE; 2904 } 2905 2906 if(list){ 2907 _bcm_mn_node_index_clear(list, start_index, numq); 2908 } 2909 return BCM_E_NONE; 2910 } 2911 /* 2912 * Function: 2913 * _bcm_mn_cosq_node_unresolve 2914 * Purpose: 2915 * Unresolve queue number in the specified scheduler tree and its subtree 2916 * Parameters: 2917 * unit - (IN) unit number 2918 * node - (IN) node structure for the specified scheduler node 2919 * cosq - (IN) COS queue to attach to 2920 * Returns: 2921 * BCM_E_XXX 2922 */ 2923 STATIC int 2924 _bcm_mn_cosq_node_unresolve(int unit, _bcm_mn_cosq_node_t *node, 2925 bcm_cos_queue_t cosq) 2926 { 2927 _bcm_mn_cosq_node_t *parent; 2928 _bcm_mn_mmu_info_t *mmu_info; 2929 _bcm_mn_pipe_resources_t * res; 2930 _bcm_mn_cosq_port_info_t *port_info; 2931 _bcm_mn_cosq_list_t *list; 2932 int numq = 1, port; 2933 int hw_index; 2934 2935 if (node->attached_to_input < 0) { 2936 /* Has been unresolved already */ 2937 return BCM_E_NONE; 2938 } 2939 2940 parent = node->parent; 2941 2942 if (!parent) { 2943 return BCM_E_PARAM; 2944 } 2945 2946 mmu_info = _bcm_mn_mmu_info[unit]; 2947 2948 BCM_IF_ERROR_RETURN 2949 (_bcm_mn_cosq_node_get(unit, node->gport, 0, NULL, &port, NULL, NULL)); 2950 2951 port_info = &mmu_info->port_info[port]; 2952 res = port_info->resources; 2953 2954 list = NULL; 2955 2956 switch (parent->level) { 2957 case SOC_MONTEREY_NODE_LVL_ROOT: 2958 if (IS_MN_HSP_PORT(unit, port)) { 2959 list = &res->hsp_l0_sched_list; 2960 } else { 2961 list = &res->s1_sched_list; 2962 } 2963 break; 2964 2965 case SOC_MONTEREY_NODE_LVL_S1: 2966 if (IS_MN_HSP_PORT(unit, port)) { 2967 return BCM_E_PARAM; 2968 } else if (IS_CPU_PORT(unit, port)) { 2969 list = &res->cpu_l0_sched_list; 2970 } else { 2971 list = &res->l0_sched_list; 2972 } 2973 break; 2974 2975 case SOC_MONTEREY_NODE_LVL_L0: 2976 if (IS_MN_HSP_PORT(unit, port)) { 2977 list = &res->hsp_l1_sched_list; 2978 } else { 2979 2980 list = &res->l1_sched_list; 2981 } 2982 break; 2983 2984 case SOC_MONTEREY_NODE_LVL_L1: 2985 break; 2986 2987 case SOC_MONTEREY_NODE_LVL_L2: 2988 /* passthru */ 2989 default: 2990 return BCM_E_PARAM; 2991 2992 } 2993 2994 if ((list) && (node->attached_to_input >= 8)) { 2995 hw_index = node->hw_index; 2996 if (IS_CPU_PORT(unit, port)) { 2997 hw_index = node->hw_index - _BCM_MN_CPU_PORT_L0_MIN; 2998 } 2999 _bcm_mn_node_index_clear(list, hw_index, numq); 3000 } else if((list) && (IS_MN_HSP_PORT(unit, port))){ 3001 _bcm_mn_node_index_clear(list, node->hw_index, 1); 3002 } 3003 BCM_IF_ERROR_RETURN 3004 (_bcm_mn_cosq_map_index_clear(node->parent->cosq_map, 3005 node->attached_to_input , 1)); 3006 node->attached_to_input = -1; 3007 3008 BCM_IF_ERROR_RETURN(_bcm_mn_detach_node_in_hw(unit, node)); 3009 return BCM_E_NONE; 3010 } 3011 3012 /* 3013 * Function: 3014 * _bcm_mn_port_enqueue_set 3015 * Purpose: 3016 * Enable or Disable the enqueing the packets to the port 3017 * Parameters: 3018 * unit - (IN) unit number 3019 * gport - (IN) gport of the port 3020 * enable - (IN) TRUE to enable 3021 * FALSE to disable 3022 * Returns: 3023 * BCM_E_XXX 3024 */ 3025 3026 int 3027 _bcm_mn_port_enqueue_set(int unit, bcm_port_t gport, int enable) 3028 { 3029 bcm_port_t local_port; 3030 3031 BCM_IF_ERROR_RETURN 3032 (_bcm_mn_cosq_localport_resolve(unit, gport, &local_port)); 3033 3034 SOC_IF_ERROR_RETURN( 3035 soc_monterey_port_mmu_tx_enable_set(unit, local_port, enable)); 3036 SOC_IF_ERROR_RETURN( 3037 _bcm_mn_mmu_rx_enable_set(unit, local_port, enable)); 3038 3039 return BCM_E_NONE; 3040 } 3041 /* 3042 * Function: 3043 * _bcm_mn_port_enqueue_get 3044 * Purpose: 3045 * Getting the enqueing state of the port 3046 * Parameters: 3047 * unit - (IN) unit number 3048 * gport - (IN) gport of the port 3049 * enable - (IN) TRUE to enable 3050 * FALSE to disable 3051 * Returns: 3052 * BCM_E_XXX 3053 */ 3054 3055 int 3056 _bcm_mn_port_enqueue_get(int unit, bcm_port_t gport, 3057 int *enable) 3058 { 3059 uint64 rval64; 3060 int mmu_port, phy_port, i, reg_grp = 0; 3061 int rv = BCM_E_NONE; 3062 bcm_port_t local_port; 3063 soc_info_t *si; 3064 soc_reg_t reg_tmp; 3065 soc_reg_t reg[3][2] = { 3066 { 3067 THDU_OUTPUT_PORT_RX_ENABLE0_64r, 3068 THDU_OUTPUT_PORT_RX_ENABLE1_64r 3069 }, 3070 { 3071 MMU_THDM_DB_PORTSP_RX_ENABLE0_64r, 3072 MMU_THDM_DB_PORTSP_RX_ENABLE1_64r 3073 }, 3074 { 3075 MMU_THDM_MCQE_PORTSP_RX_ENABLE0_64r, 3076 MMU_THDM_MCQE_PORTSP_RX_ENABLE1_64r 3077 } 3078 }; 3079 int max_reg = 3; 3080 3081 BCM_IF_ERROR_RETURN 3082 (_bcm_mn_cosq_localport_resolve(unit, gport, &local_port)); 3083 3084 si = &SOC_INFO(unit); 3085 3086 phy_port = si->port_l2p_mapping[local_port]; 3087 mmu_port = si->port_p2m_mapping[phy_port]; 3088 3089 COMPILER_64_ZERO(rval64); 3090 if (mmu_port < 64 ) { 3091 mmu_port &= 0x3f; 3092 } else { 3093 mmu_port &= 0xf; 3094 reg_grp = 1; 3095 } 3096 3097 for (i = 0; i < max_reg; i++) { 3098 reg_tmp = reg[i][reg_grp]; 3099 3100 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg_tmp, REG_PORT_ANY, 0, &rval64)); 3101 3102 if (COMPILER_64_BITTEST(rval64 , mmu_port)) { 3103 *enable = TRUE; 3104 } else { 3105 *enable = FALSE; 3106 } 3107 } 3108 return rv; 3109 } 3110 3111 /* 3112 * Function: 3113 * _bcm_mn_get_s1_node 3114 * Purpose: 3115 * finds the s1 node for given subport 3116 * Parameters: 3117 * unit - (IN) unit number 3118 * subport - (IN)gport of the subport 3119 * s1_node - (OUT) pointer to the s1 node 3120 * Returns: 3121 * BCM_E_XXX 3122 */ 3123 int _bcm_mn_get_s1_node(int unit, bcm_gport_t subport, 3124 _bcm_mn_cosq_node_t **s1_node) 3125 { 3126 3127 int local_port = 0; 3128 _bcm_mn_cosq_node_t *port_node; 3129 _bcm_mn_cosq_node_t *child_node; 3130 _bcm_mn_mmu_info_t *mmu_info; 3131 int s1_found = 0; 3132 if (!s1_node) 3133 { 3134 return BCM_E_INTERNAL; 3135 } 3136 if (!soc_feature(unit, 3137 soc_feature_mmu_hqos_four_level)) { 3138 return BCM_E_PARAM; 3139 } 3140 mmu_info = _bcm_mn_mmu_info[unit]; 3141 if(!(BCM_GPORT_IS_SET(subport) && 3142 _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, subport))) { 3143 return BCM_E_PARAM; 3144 } 3145 BCM_IF_ERROR_RETURN 3146 (_bcmi_coe_subport_physical_port_get(unit, subport, &local_port)); 3147 port_node = &mmu_info->sched_node[local_port]; 3148 if (!port_node->in_use) { 3149 return BCM_E_INTERNAL; 3150 } 3151 child_node = port_node->child; 3152 while (child_node) { 3153 if((child_node->port_gport == subport)) 3154 { 3155 s1_found = 1 ; 3156 break; 3157 } 3158 child_node = child_node->sibling; 3159 } 3160 if (!s1_found) 3161 { 3162 return BCM_E_NOT_FOUND; 3163 } 3164 *s1_node = child_node; 3165 return BCM_E_NONE; 3166 } 3167 3168 /* 3169 * Function: 3170 * _bcm_mn_allocate_coe_queues 3171 * Purpose: 3172 * allocates deallocated l2 queues for given subport 3173 * Parameters: 3174 * unit - (IN) unit number 3175 * s1_node - (IN) subport s1 node 3176 * enable - (IN) flag to enable/disable 3177 * Returns: 3178 * BCM_E_XXX 3179 */ 3180 int _bcm_mn_allocate_coe_queues(int unit ,_bcm_mn_cosq_node_t *s1_node, 3181 int enable) 3182 { 3183 int id = 0; 3184 int pipe = 0 ; 3185 _bcm_mn_pipe_resources_t *res; 3186 _bcm_mn_mmu_info_t *mmu_info; 3187 3188 mmu_info = _bcm_mn_mmu_info[unit]; 3189 pipe = 0; 3190 res = _BCM_MN_PRESOURCES(mmu_info, pipe); 3191 3192 if (enable) { 3193 /* The following logic is to make sure the id is always 3194 * multiple of 8 3195 */ 3196 BCM_IF_ERROR_RETURN( 3197 _bcm_mn_node_index_get(res->l2_queue_list.bits, 3198 res->num_base_queues, 3199 _BCM_MN_NUM_L2_UC_LEAVES_PER_PIPE , 3200 _MN_NUM_COS(unit), 3201 _MN_NUM_COS(unit), &id)); 3202 while (id % 8 != 0) { 3203 id = ((id + 8) & 0xfffffff8); 3204 if (id > _BCM_MN_NUM_L2_UC_LEAVES_PER_PIPE ) { 3205 return BCM_E_RESOURCE; 3206 } 3207 BCM_IF_ERROR_RETURN( 3208 _bcm_mn_node_index_get(res->l2_queue_list.bits, id, 3209 _BCM_MN_NUM_L2_UC_LEAVES_PER_PIPE, 3210 NUM_COS(unit), 3211 NUM_COS(unit), &id)); 3212 } 3213 _bcm_mn_node_index_set(&res->l2_queue_list, id, 3214 _MN_NUM_COS(unit)); 3215 s1_node->coe_base_index = id; 3216 } else 3217 { 3218 _bcm_mn_node_index_clear(&res->l2_queue_list, id, 3219 _MN_NUM_COS(unit)); 3220 s1_node->coe_base_index = -1; 3221 } 3222 return BCM_E_NONE; 3223 } 3224 3225 /* 3226 * Function: 3227 * _bcm_mn_coe_queue_offset_add 3228 * Purpose: 3229 * Programs the offset in voq_mod_map and voq_port_map table 3230 * Parameters: 3231 * unit - (IN) unit number 3232 * subport - (IN) subport gport 3233 * queue_id - (IN) base queue_id for the subport 3234 * Returns: 3235 * BCM_E_XXX 3236 */ 3237 int _bcm_mn_coe_queue_offset_add(int unit, int queue_id, 3238 bcm_gport_t subport) 3239 { 3240 bcm_module_t modid = 0; 3241 bcm_port_t port = 0; 3242 voq_port_map_entry_t *voq_port_map_entries = NULL; 3243 voq_mod_map_entry_t voq_mod_map; 3244 int rv = BCM_E_NONE; 3245 void *entries[1]; 3246 int port_offset = 0 ; 3247 int vpm_idx_old = 0 ; 3248 int baseq_old = 0 ; 3249 uint32 profile = 0 ; 3250 bcm_trunk_t trunk_id; 3251 int id; 3252 int port_base = 0; 3253 uint64 rval; 3254 int local_port = 0 ; 3255 BCM_IF_ERROR_RETURN( 3256 _bcm_esw_gport_resolve(unit, subport, &modid, &port, &trunk_id, &id)); 3257 BCM_IF_ERROR_RETURN 3258 (_bcmi_coe_subport_physical_port_get(unit, subport, &local_port)); 3259 /* program the voq port profiles. */ 3260 voq_port_map_entries = sal_alloc(sizeof(voq_port_map_entry_t)*128, 3261 "voq port map entries"); 3262 if (!voq_port_map_entries) { 3263 goto fail; 3264 } 3265 sal_memset(voq_port_map_entries, 0, sizeof(voq_port_map_entry_t)*128); 3266 entries[0] = voq_port_map_entries; 3267 rv = READ_VOQ_MOD_MAPm(unit, MEM_BLOCK_ALL, modid, &voq_mod_map); 3268 if (rv) { 3269 goto fail; 3270 } 3271 BCM_IF_ERROR_RETURN(READ_ING_COS_MODE_64r(unit, local_port, &rval)); 3272 port_base = soc_reg64_field32_get(unit, ING_COS_MODE_64r, rval, 3273 BASE_QUEUE_NUM_0f); 3274 if (!soc_mem_field32_get(unit, VOQ_MOD_MAPm, 3275 &voq_mod_map, VOQ_VALIDf)) { 3276 port_offset = 1; 3277 soc_mem_field32_set(unit, VOQ_PORT_MAPm, &voq_port_map_entries[port], 3278 VOQ_PORT_OFFSETf, port_offset); 3279 soc_mem_field32_set(unit, VOQ_MOD_MAPm, &voq_mod_map, 3280 VOQ_MOD_OFFSETf, queue_id - 1 - port_base ); 3281 soc_mem_field32_set(unit, VOQ_MOD_MAPm, &voq_mod_map, 3282 VOQ_VALIDf, 1); 3283 } else { 3284 vpm_idx_old = _MN_VPM_ENTRIES_PER_SET * 3285 soc_mem_field32_get(unit, VOQ_MOD_MAPm, &voq_mod_map, 3286 VOQ_MOD_PORT_PROFILE_INDEXf); 3287 rv = soc_profile_mem_get(unit, _bcm_mn_voq_port_map_profile[unit], 3288 vpm_idx_old, _MN_VPM_ENTRIES_PER_SET, entries ); 3289 3290 if (!(rv == SOC_E_NOT_FOUND || rv == SOC_E_NONE)) { 3291 goto fail; 3292 } 3293 3294 baseq_old = soc_mem_field32_get(unit, VOQ_MOD_MAPm, 3295 &voq_mod_map,VOQ_MOD_OFFSETf); 3296 3297 port_offset = (queue_id - baseq_old - port_base) & 0x3FFF; 3298 soc_mem_field32_set(unit, VOQ_PORT_MAPm, &voq_port_map_entries[port], 3299 VOQ_PORT_OFFSETf, port_offset); 3300 rv =soc_profile_mem_delete(unit, _bcm_mn_voq_port_map_profile[unit], 3301 vpm_idx_old); 3302 if (!(rv == SOC_E_NOT_FOUND || rv == SOC_E_NONE)) { 3303 goto fail; 3304 } 3305 } 3306 rv = soc_profile_mem_add(unit, 3307 _bcm_mn_voq_port_map_profile[unit], 3308 entries, 128, &profile); 3309 if (rv) { 3310 goto fail; 3311 } 3312 3313 soc_mem_field32_set(unit, VOQ_MOD_MAPm, &voq_mod_map, 3314 VOQ_MOD_PORT_PROFILE_INDEXf, profile/128); 3315 rv = soc_mem_write(unit, VOQ_MOD_MAPm, MEM_BLOCK_ALL, 3316 modid, &voq_mod_map); 3317 if (rv) { 3318 goto fail; 3319 } 3320 fail : 3321 if (voq_port_map_entries) 3322 { 3323 sal_free(voq_port_map_entries); 3324 } 3325 return rv; 3326 } 3327 3328 /* 3329 * Function: 3330 * _bcm_mn_coe_queue_offset_clear 3331 * Purpose: 3332 * clears the offset in voq_mod_map and voq_port_map table for the subport 3333 * Parameters: 3334 * unit - (IN) unit number 3335 * subport - (IN) subport gport 3336 * queue_id - (IN) base queue_id for the subport 3337 * Returns: 3338 * BCM_E_XXX 3339 */ 3340 int _bcm_mn_coe_queue_offset_clear(int unit, int queue_id, 3341 bcm_gport_t subport) 3342 { 3343 3344 bcm_module_t modid = 0; 3345 bcm_port_t port = 0; 3346 voq_port_map_entry_t *voq_port_map_entries = NULL; 3347 voq_mod_map_entry_t voq_mod_map; 3348 int rv = BCM_E_NONE; 3349 void *entries[1]; 3350 int vpm_idx_old = 0 ; 3351 int port_offset = 0 ; 3352 int i =0 ; 3353 int module_in_use = 0; 3354 uint32 profile = 0 ; 3355 bcm_trunk_t trunk_id; 3356 int id; 3357 3358 BCM_IF_ERROR_RETURN( 3359 _bcm_esw_gport_resolve( unit, subport, &modid, &port, &trunk_id, &id)); 3360 /* program the voq port profiles. */ 3361 voq_port_map_entries = sal_alloc(sizeof(voq_port_map_entry_t)*128, 3362 "voq port map entries"); 3363 if (!voq_port_map_entries) { 3364 goto fail; 3365 } 3366 sal_memset(voq_port_map_entries, 0, sizeof(voq_port_map_entry_t)*128); 3367 entries[0] = voq_port_map_entries; 3368 rv = READ_VOQ_MOD_MAPm(unit, MEM_BLOCK_ALL, modid, &voq_mod_map); 3369 if (rv) { 3370 goto fail; 3371 } 3372 if (!soc_mem_field32_get(unit, VOQ_MOD_MAPm, 3373 &voq_mod_map, VOQ_VALIDf)) { 3374 rv = BCM_E_NOT_FOUND; 3375 goto fail; 3376 } 3377 3378 vpm_idx_old = _MN_VPM_ENTRIES_PER_SET * 3379 soc_mem_field32_get(unit, VOQ_MOD_MAPm, &voq_mod_map, 3380 VOQ_MOD_PORT_PROFILE_INDEXf); 3381 rv = soc_profile_mem_get(unit, _bcm_mn_voq_port_map_profile[unit], 3382 vpm_idx_old, _MN_VPM_ENTRIES_PER_SET, entries ); 3383 3384 if (!(rv == SOC_E_NOT_FOUND || rv == SOC_E_NONE)) { 3385 goto fail; 3386 } 3387 3388 3389 3390 port_offset = 0; 3391 soc_mem_field32_set(unit, VOQ_PORT_MAPm, &voq_port_map_entries[port], 3392 VOQ_PORT_OFFSETf, port_offset); 3393 rv =soc_profile_mem_delete(unit, _bcm_mn_voq_port_map_profile[unit], 3394 vpm_idx_old); 3395 if (rv) { 3396 goto fail; 3397 } 3398 3399 for (i = 0; i < _MN_VPM_ENTRIES_PER_SET; i++) { 3400 if (soc_mem_field32_get(unit, VOQ_PORT_MAPm, 3401 &voq_port_map_entries[i], VOQ_PORT_OFFSETf)) { 3402 module_in_use = 1; 3403 break; 3404 } 3405 } 3406 if (module_in_use) { 3407 rv = soc_profile_mem_add(unit, 3408 _bcm_mn_voq_port_map_profile[unit], 3409 entries, 128, &profile); 3410 if (rv) { 3411 goto fail; 3412 } 3413 soc_mem_field32_set(unit, VOQ_MOD_MAPm, &voq_mod_map, 3414 VOQ_MOD_PORT_PROFILE_INDEXf, profile/128); 3415 } else 3416 { 3417 soc_mem_field32_set(unit, VOQ_MOD_MAPm, &voq_mod_map, 3418 VOQ_VALIDf, 0); 3419 soc_mem_field32_set(unit, VOQ_MOD_MAPm, &voq_mod_map, 3420 VOQ_MOD_OFFSETf, 0 ); 3421 } 3422 3423 rv = soc_mem_write(unit, VOQ_MOD_MAPm, MEM_BLOCK_ALL, 3424 modid, &voq_mod_map); 3425 fail : 3426 if (voq_port_map_entries) 3427 { 3428 sal_free(voq_port_map_entries); 3429 } 3430 return rv; 3431 } 3432 3433 /* 3434 * Function: 3435 * _bcm_mn_mmu_port_coe_control 3436 * Purpose: 3437 * Programs the ing_cos_mode to enable/disable subport in the physical port 3438 * Parameters: 3439 * unit - (IN) unit number 3440 * local_port - (IN) physical port 3441 * eanble - (IN) flag to control enable/disable 3442 * Returns: 3443 * BCM_E_XXX 3444 */ 3445 int _bcm_mn_mmu_port_coe_control(int unit ,int local_port, int enable) 3446 { 3447 uint64 rval; 3448 3449 BCM_IF_ERROR_RETURN(READ_ING_COS_MODE_64r(unit, local_port, &rval)); 3450 soc_reg64_field32_set(unit, ING_COS_MODE_64r, &rval, USE_MODf, enable) ; 3451 soc_reg64_field32_set(unit, ING_COS_MODE_64r, &rval, USE_PORTf, enable) ; 3452 BCM_IF_ERROR_RETURN(WRITE_ING_COS_MODE_64r(unit, local_port, rval)); 3453 return BCM_E_NONE; 3454 3455 } 3456 3457 /* 3458 * Function: 3459 * bcm_mn_cosq_gport_add 3460 * Purpose: 3461 * Create a cosq gport structure 3462 * Parameters: 3463 * unit - (IN) unit number 3464 * port - (IN) port number 3465 * numq - (IN) number of COS queues 3466 * flags - (IN) flags (BCM_COSQ_GPORT_XXX) 3467 * gport - (OUT) GPORT identifier 3468 * Returns: 3469 * BCM_E_XXX 3470 */ 3471 int 3472 bcm_mn_cosq_gport_add(int unit, bcm_gport_t port, int numq, uint32 flags, 3473 bcm_gport_t *gport) 3474 { 3475 _bcm_mn_mmu_info_t *mmu_info; 3476 _bcm_mn_cosq_node_t *node = NULL; 3477 _bcm_mn_cosq_node_t *s1_node = NULL ; 3478 _bcm_mn_cosq_port_info_t *port_info; 3479 uint32 sched_encap; 3480 _bcm_mn_pipe_resources_t *res; 3481 int phy_port, mmu_port, local_port; 3482 int id, ii, q_base, pipe, qmin, qmax; 3483 bcm_gport_t tmp_gport; 3484 bcm_gport_t s1_sched; 3485 3486 3487 LOG_INFO(BSL_LS_BCM_COSQ, 3488 (BSL_META_U(unit, 3489 "bcm_mn_cosq_gport_add: unit=%d port=0x%x numq=%d flags=0x%x\n"), 3490 unit, port, numq, flags)); 3491 3492 if (!soc_feature(unit, soc_feature_ets)) { 3493 return BCM_E_UNAVAIL; 3494 } 3495 3496 if (gport == NULL) { 3497 return BCM_E_PARAM; 3498 } 3499 3500 if (_bcm_mn_mmu_info[unit] == NULL) { 3501 return BCM_E_INIT; 3502 } 3503 3504 if (!soc_feature(unit, 3505 soc_feature_mmu_hqos_four_level)) { 3506 if(_BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port)){ 3507 return BCM_E_UNAVAIL; 3508 } 3509 } 3510 if(_BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port)){ 3511 BCM_IF_ERROR_RETURN( 3512 _bcmi_coe_subport_physical_port_get(unit, port, &local_port)); 3513 } else { 3514 BCM_IF_ERROR_RETURN 3515 (_bcm_mn_cosq_localport_resolve(unit, port, &local_port)); 3516 } 3517 if (local_port < 0) { 3518 return BCM_E_PORT; 3519 } 3520 3521 mmu_info = _bcm_mn_mmu_info[unit]; 3522 3523 port_info = &mmu_info->port_info[local_port]; 3524 pipe = _BCM_MN_PORT_TO_PIPE(unit, local_port); 3525 res = _BCM_MN_PRESOURCES(mmu_info, pipe); 3526 #if 0 3527 if (!mmu_info->ets_mode) { 3528 /* cleanup the default lls setup */ 3529 SOC_IF_ERROR_RETURN(soc_monterey_lls_reset(unit)); 3530 SOC_IF_ERROR_RETURN(soc_monterey_lb_lls_init(unit)); 3531 mmu_info->ets_mode = 1; 3532 } 3533 #endif 3534 3535 switch (flags) { 3536 case BCM_COSQ_GPORT_UCAST_QUEUE_GROUP: 3537 if (numq != 1) { 3538 return BCM_E_PARAM; 3539 } 3540 3541 if (IS_CPU_PORT(unit, local_port) || IS_LB_PORT(unit, local_port)) { 3542 return BCM_E_PARAM; 3543 } 3544 3545 if (_BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port)){ 3546 BCM_IF_ERROR_RETURN( 3547 _bcm_mn_get_s1_node( unit, port, &s1_node)); 3548 if (s1_node->coe_base_index == -1) { 3549 _bcm_mn_allocate_coe_queues(unit, s1_node, 1); 3550 _bcm_mn_coe_queue_offset_add(unit, s1_node->coe_base_index, 3551 port); 3552 } 3553 for (id = s1_node->coe_base_index; 3554 id < (s1_node->coe_base_index + _MN_NUM_COS(unit)); id++) { 3555 if (!res->p_queue_node[id].in_use) { 3556 s1_node->coe_num_l2++; 3557 break; 3558 } 3559 } 3560 if (id == (s1_node->coe_base_index + NUM_COS(unit))) 3561 { 3562 return BCM_E_RESOURCE; 3563 } 3564 } else { 3565 for (id = port_info->uc_base; id < port_info->uc_limit; id++) { 3566 if (res->p_queue_node[id].numq == 0) { 3567 break; 3568 } 3569 } 3570 if ((id == port_info->uc_limit) && 3571 (IS_MN_HSP_PORT(unit, local_port))) { 3572 return BCM_E_RESOURCE; 3573 } 3574 if (id == port_info->uc_limit) { 3575 BCM_IF_ERROR_RETURN( 3576 _bcm_mn_node_index_get(res->l2_queue_list.bits, 0, 3577 _BCM_MN_NUM_L2_UC_LEAVES_PER_PIPE, numq, 3578 1, &id)); 3579 3580 _bcm_mn_node_index_set(&res->l2_queue_list, id, 1); 3581 } 3582 } 3583 3584 BCM_GPORT_UCAST_QUEUE_GROUP_SYSQID_SET(*gport, local_port, id); 3585 node = &res->p_queue_node[id]; 3586 node->gport = *gport; 3587 node->numq = numq; 3588 node->level = SOC_MONTEREY_NODE_LVL_L2; 3589 if (_BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port)) 3590 { 3591 node->hw_cosq = id - s1_node->coe_base_index; 3592 } else 3593 { 3594 node->hw_cosq = id - port_info->uc_base; 3595 } 3596 if (IS_MN_HSP_PORT(unit, local_port)) { 3597 phy_port = SOC_INFO(unit).port_l2p_mapping[local_port]; 3598 mmu_port = SOC_INFO(unit).port_p2m_mapping[phy_port]; 3599 node->hw_index = _BCM_MN_HSP_L2_INDEX(unit, mmu_port, node->hw_cosq); 3600 } else { 3601 node->hw_index = soc_monterey_l2_hw_index(unit, id, 1); 3602 } 3603 node->local_port = local_port; 3604 node->remote_modid = -1; 3605 node->remote_port = -1; 3606 node->type = _BCM_MN_NODE_UCAST; 3607 node->in_use = TRUE; 3608 node->port_gport = port; 3609 break; 3610 3611 case BCM_COSQ_GPORT_MCAST_QUEUE_GROUP: 3612 if (numq != 1) { 3613 return BCM_E_PARAM; 3614 } 3615 3616 for (id = port_info->mc_base; id < port_info->mc_limit; id++) { 3617 if (res->p_mc_queue_node[id].numq == 0) { 3618 break; 3619 } 3620 } 3621 3622 if (id == port_info->mc_limit) { 3623 return BCM_E_RESOURCE; 3624 } 3625 3626 /* set index bits */ 3627 BCM_GPORT_MCAST_QUEUE_GROUP_SYSQID_SET(*gport, local_port, id); 3628 node = &res->p_mc_queue_node[id]; 3629 node->gport = *gport; 3630 node->numq = numq; 3631 node->level = SOC_MONTEREY_NODE_LVL_L2; 3632 node->type = _BCM_MN_NODE_MCAST; 3633 node->hw_cosq = id - port_info->mc_base; 3634 if (IS_MN_HSP_PORT(unit, local_port)) { 3635 phy_port = SOC_INFO(unit).port_l2p_mapping[local_port]; 3636 mmu_port = SOC_INFO(unit).port_p2m_mapping[phy_port]; 3637 node->hw_index = id; 3638 node->hw_index = soc_monterey_l2_hw_index(unit, node->hw_index, 0); 3639 } else { 3640 node->hw_index = soc_monterey_l2_hw_index(unit, id, 0); 3641 } 3642 node->local_port = local_port; 3643 node->remote_modid = -1; 3644 node->remote_port = -1; 3645 node->in_use = TRUE; 3646 node->port_gport = port; 3647 break; 3648 3649 3650 3651 case BCM_COSQ_GPORT_SUBSCRIBER: 3652 case BCM_COSQ_GPORT_VIRTUAL_PORT: 3653 case BCM_COSQ_GPORT_VLAN_UCAST_QUEUE_GROUP: 3654 /* Service Queueing are outside default queues. Hence NO alignment 3655 * required. 3656 */ 3657 BCM_IF_ERROR_RETURN( 3658 _bcm_mn_node_index_get(res->l2_queue_list.bits, res->num_base_queues, 3659 _BCM_MN_NUM_L2_UC_LEAVES_PER_PIPE, numq, 3660 1, &q_base)); 3661 3662 _bcm_mn_node_index_set(&res->l2_queue_list, q_base, numq); 3663 qmin = res->num_base_queues + (pipe * _BCM_MN_NUM_L2_UC_LEAVES_PER_PIPE); 3664 qmax = (pipe + 1) * _BCM_MN_NUM_L2_UC_LEAVES_PER_PIPE; 3665 3666 for (ii = 0, id = qmin; id < qmax; id++) { 3667 if (res->p_queue_node[id].numq > 0) { 3668 ii = 0; 3669 } else { 3670 ii += 1; 3671 3672 if (ii == numq) { 3673 break; 3674 } 3675 } 3676 } 3677 3678 if (ii != numq) { 3679 return BCM_E_RESOURCE; 3680 } 3681 3682 id = id - (numq - 1); 3683 3684 for (ii = 0; ii < numq; ii++, id++) { 3685 BCM_GPORT_UCAST_QUEUE_GROUP_SYSQID_SET(tmp_gport, local_port, id); 3686 node= &res->p_queue_node[id]; 3687 node->gport = tmp_gport; 3688 node->numq = numq - ii; 3689 node->level = SOC_MONTEREY_NODE_LVL_L2; 3690 node->type = (flags == BCM_COSQ_GPORT_VIRTUAL_PORT) ? 3691 _BCM_MN_NODE_VM_UCAST : _BCM_MN_NODE_SERVICE_UCAST; 3692 node->hw_index = q_base + ii + (pipe * _BCM_MN_NUM_L2_UC_LEAVES_PER_PIPE); 3693 /* by default assign the cosq on order of order of alocation, 3694 * can be overriddedn by cos_mapping_set */ 3695 node->hw_cosq = ii; 3696 node->local_port = local_port; 3697 node->remote_modid = -1; 3698 node->remote_port = -1; 3699 node->in_use = TRUE; 3700 node->port_gport = port; 3701 if (ii == 0) { 3702 *gport = tmp_gport; 3703 } 3704 } 3705 break; 3706 3707 case BCM_COSQ_GPORT_DESTMOD_UCAST_QUEUE_GROUP: 3708 if (numq != 1) { 3709 return BCM_E_PARAM; 3710 } 3711 3712 if (!IS_HG_PORT(unit, local_port)) { 3713 return BCM_E_PORT; 3714 } 3715 3716 qmin = res->num_base_queues; 3717 qmax = _BCM_MN_NUM_L2_UC_LEAVES_PER_PIPE; 3718 for (id = qmin; id < qmax; id++) { 3719 if (res->p_queue_node[id].numq == 0) { 3720 break; 3721 } 3722 } 3723 3724 if (id >= qmax) { 3725 return BCM_E_RESOURCE; 3726 } 3727 3728 BCM_GPORT_UCAST_QUEUE_GROUP_SYSQID_SET(*gport, local_port, id); 3729 node = &res->p_queue_node[id]; 3730 node->gport = *gport; 3731 node->numq = numq; 3732 node->level = SOC_MONTEREY_NODE_LVL_L2; 3733 node->type = _BCM_MN_NODE_VOQ; 3734 node->hw_index = -1; 3735 /* by default assign the cosq on order of order of alocation, 3736 * can be overriddedn by cos_mapping_set */ 3737 node->hw_cosq = -1; 3738 node->local_port = local_port; 3739 node->remote_modid = -1; 3740 node->remote_port = -1; 3741 node->in_use = TRUE; 3742 node->port_gport = port; 3743 break; 3744 3745 case BCM_COSQ_GPORT_SCHEDULER: 3746 if (numq < -1) { 3747 return BCM_E_PARAM; 3748 } 3749 for (id = _BCM_MN_NUM_PORT_SCHEDULERS; 3750 id < _BCM_MN_NUM_TOTAL_SCHEDULERS; id++) { 3751 if (mmu_info->sched_node[id].in_use == FALSE) { 3752 node = &mmu_info->sched_node[id]; 3753 node->in_use = TRUE; 3754 break; 3755 } 3756 } 3757 if (!node) { 3758 return BCM_E_RESOURCE; 3759 } 3760 3761 node = &mmu_info->sched_node[id]; 3762 sched_encap = (id << 8) | local_port; 3763 BCM_GPORT_SCHEDULER_SET(*gport, sched_encap); 3764 node->gport = *gport; 3765 node->numq = numq; 3766 node->local_port = local_port; 3767 node->type = _BCM_MN_NODE_SCHEDULER; 3768 node->attached_to_input = -1; 3769 node->port_gport = port; 3770 break; 3771 3772 case BCM_COSQ_GPORT_WITH_ID: 3773 case 0: 3774 if (numq < -1) { 3775 return BCM_E_PARAM; 3776 } 3777 3778 /* this is a port level scheduler */ 3779 id = local_port; 3780 3781 if ( id < 0 || id >= _BCM_MN_NUM_PORT_SCHEDULERS) { 3782 return BCM_E_PARAM; 3783 } 3784 if (IS_MN_HSP_PORT(unit, local_port)) { 3785 if (numq > _BCM_MN_HSP_PORT_MAX_L0) { 3786 return BCM_E_PARAM; 3787 } 3788 } 3789 node = &mmu_info->sched_node[id]; 3790 sched_encap = (id << 8) | local_port; 3791 BCM_GPORT_SCHEDULER_SET(*gport, sched_encap); 3792 node->gport = *gport; 3793 node->level = SOC_MONTEREY_NODE_LVL_ROOT; 3794 node->type = _BCM_MN_NODE_SCHEDULER; 3795 phy_port = SOC_INFO(unit).port_l2p_mapping[local_port]; 3796 mmu_port = SOC_INFO(unit).port_p2m_mapping[phy_port]; 3797 node->hw_index = mmu_port; 3798 if (IS_MN_HSP_PORT(unit, local_port)) { 3799 node->numq = _BCM_MN_HSP_PORT_MAX_L0; 3800 } else { 3801 node->numq = -1; 3802 } 3803 node->local_port = local_port; 3804 node->in_use = TRUE; 3805 node->attached_to_input = 0; 3806 node->port_gport = port; 3807 if (!(soc_feature(unit,soc_feature_mmu_hqos_four_level)) && 3808 !(IS_MN_HSP_PORT(unit, local_port))) 3809 { 3810 node->numq = 1; 3811 BCM_IF_ERROR_RETURN 3812 (bcm_mn_cosq_gport_add(unit, port, numq, 3813 BCM_COSQ_GPORT_SCHEDULER, 3814 &s1_sched)); 3815 BCM_IF_ERROR_RETURN 3816 (bcm_mn_cosq_gport_attach(unit, s1_sched, *gport, 0)); 3817 *gport = s1_sched ; 3818 } 3819 break; 3820 3821 default: 3822 return BCM_E_PARAM; 3823 } 3824 3825 LOG_INFO(BSL_LS_BCM_COSQ, 3826 (BSL_META_U(unit, 3827 " gport=0x%x\n"), 3828 *gport)); 3829 3830 return BCM_E_NONE; 3831 } 3832 3833 /* 3834 * Function: 3835 * bcm_mn_cosq_gport_detach 3836 * Purpose: 3837 * Detach sched_port from the specified index (cosq) of parent_port 3838 * Parameters: 3839 * unit - (IN) unit number 3840 * sched_port - (IN) scheduler GPORT identifier 3841 * parent_port - (IN) GPORT to detach from 3842 * cosq - (IN) COS queue to detach from 3843 * Returns: 3844 * BCM_E_XXX 3845 */ 3846 int 3847 bcm_mn_cosq_gport_detach(int unit, bcm_gport_t sched_gport, 3848 bcm_gport_t parent_gport, bcm_cos_queue_t cosq) 3849 { 3850 _bcm_mn_cosq_node_t *sched_node, *parent_node = NULL, *prev_node; 3851 _bcm_mn_cosq_node_t *child_node = NULL; 3852 bcm_port_t sched_port, parent_port = -1; 3853 _bcm_mn_cosq_node_t *parent; 3854 _bcm_mn_cosq_list_t *list = NULL; 3855 _bcm_mn_mmu_info_t *mmu_info; 3856 _bcm_mn_pipe_resources_t * res; 3857 _bcm_mn_cosq_port_info_t *port_info; 3858 int start = 0, end = 0; 3859 int base_index; 3860 int subport_enabled = 0 ; 3861 int hw_index = 0 ; 3862 if (_bcm_mn_mmu_info[unit] == NULL) { 3863 return BCM_E_INIT; 3864 } 3865 3866 if ((BCM_GPORT_IS_UCAST_QUEUE_GROUP(parent_gport)) || 3867 (BCM_GPORT_IS_MCAST_QUEUE_GROUP(parent_gport)) || 3868 (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(parent_gport))) { 3869 return BCM_E_PARAM; 3870 } 3871 3872 BCM_IF_ERROR_RETURN 3873 (_bcm_mn_cosq_node_get(unit, sched_gport, 0, NULL, &sched_port, NULL, 3874 &sched_node)); 3875 3876 if (sched_node->attached_to_input < 0) { 3877 /* Not attached yet */ 3878 return BCM_E_PORT; 3879 } 3880 3881 if (parent_gport != BCM_GPORT_INVALID) { 3882 if (BCM_GPORT_IS_SCHEDULER(parent_gport) || 3883 BCM_GPORT_IS_MODPORT(parent_gport) || 3884 BCM_GPORT_IS_LOCAL(parent_gport)) { 3885 BCM_IF_ERROR_RETURN 3886 (_bcm_mn_cosq_node_get(unit, parent_gport, 0, NULL, 3887 &parent_port, NULL, &parent_node)); 3888 } else { 3889 if (!(BCM_GPORT_IS_SCHEDULER(sched_gport) || 3890 BCM_GPORT_IS_UCAST_QUEUE_GROUP(sched_gport) || 3891 BCM_GPORT_IS_MCAST_QUEUE_GROUP(sched_gport)) || 3892 (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(parent_gport))) { 3893 return BCM_E_PARAM; 3894 } 3895 else { 3896 BCM_IF_ERROR_RETURN 3897 (_bcm_mn_cosq_localport_resolve(unit, parent_gport, 3898 &parent_port)); 3899 parent_node = NULL; 3900 } 3901 } 3902 } 3903 3904 if (parent_port == -1) { 3905 return BCM_E_PORT; 3906 } 3907 3908 mmu_info = _bcm_mn_mmu_info[unit]; 3909 port_info = &mmu_info->port_info[parent_port]; 3910 res = port_info->resources; 3911 3912 if (sched_port != parent_port) { 3913 return BCM_E_PORT; 3914 } 3915 3916 if (sched_node->parent != parent_node) { 3917 return BCM_E_PORT; 3918 } 3919 3920 if ((cosq < -1) || 3921 (parent_node && (parent_node->numq != -1) && (cosq >= parent_node->numq))) { 3922 return BCM_E_PARAM; 3923 } 3924 3925 if (cosq != -1) { 3926 if (sched_node->attached_to_input != cosq) { 3927 return BCM_E_PARAM; 3928 } 3929 } 3930 3931 if (sched_node->type == _BCM_MN_NODE_SERVICE_UCAST) { 3932 end = sched_node->numq; 3933 } else { 3934 end = 1; 3935 } 3936 3937 for (start = 0; start < end; start++) { 3938 if (sched_node->parent != NULL) { 3939 BCM_IF_ERROR_RETURN( 3940 soc_monterey_cosq_set_sched_parent(unit, parent_port, 3941 sched_node->level, sched_node->hw_index, 3942 sched_node->parent->hw_index, 0)); 3943 /* unresolve the node - delete this node from parent's child list */ 3944 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_node_unresolve(unit, sched_node, cosq)); 3945 3946 /* now remove from the sw tree */ 3947 parent = sched_node->parent; 3948 if (sched_node->parent->child == sched_node) { 3949 sched_node->parent->child = sched_node->sibling; 3950 } else { 3951 prev_node = sched_node->parent->child; 3952 while (prev_node != NULL && prev_node->sibling != sched_node) { 3953 prev_node = prev_node->sibling; 3954 } 3955 if (prev_node == NULL) { 3956 return BCM_E_INTERNAL; 3957 } 3958 prev_node->sibling = sched_node->sibling; 3959 } 3960 sched_node->parent = NULL; 3961 sched_node->sibling = NULL; 3962 sched_node->attached_to_input = -1; 3963 hw_index = sched_node->hw_index; 3964 if (!IS_MN_HSP_PORT(unit, parent_port)) { 3965 switch (parent->level) { 3966 case SOC_MONTEREY_NODE_LVL_ROOT: 3967 list = &res->s1_sched_list; 3968 sched_node->hw_index = -1; 3969 break; 3970 case SOC_MONTEREY_NODE_LVL_S1: 3971 if (IS_CPU_PORT(unit, parent_port)) { 3972 list = &res->cpu_l0_sched_list; 3973 } else { 3974 list = &res->l0_sched_list; 3975 } 3976 sched_node->hw_index = -1; 3977 break; 3978 case SOC_MONTEREY_NODE_LVL_L0: 3979 list = &res->l1_sched_list; 3980 sched_node->hw_index = -1; 3981 break; 3982 case SOC_MONTEREY_NODE_LVL_L1: 3983 list = &res->l2_queue_list; 3984 break; 3985 default: 3986 break; 3987 } 3988 3989 if (!BCM_GPORT_IS_MCAST_QUEUE_GROUP(sched_gport)){ 3990 if (parent->numq == -1) { 3991 BCM_IF_ERROR_RETURN(_bcm_mn_node_index_clear(list, 3992 hw_index, 1)); 3993 } else if ((parent->child == NULL) && 3994 (sched_node->level != SOC_MONTEREY_NODE_LVL_L2)) { 3995 if (list) { 3996 base_index = parent->base_index; 3997 if (IS_CPU_PORT(unit, parent_port) && 3998 (sched_node->level == SOC_MONTEREY_NODE_LVL_L0)) { 3999 base_index = parent->base_index - _BCM_MN_CPU_PORT_L0_MIN; 4000 } 4001 BCM_IF_ERROR_RETURN(_bcm_mn_node_index_clear(list, 4002 base_index, parent->base_size)); 4003 } 4004 list = NULL; 4005 parent->base_index = -1; 4006 parent->base_size = 0; 4007 } 4008 } 4009 /* Indexes that are allocated statically is not released to the pool*/ 4010 if ((sched_node->level == SOC_MONTEREY_NODE_LVL_L2) && 4011 (BCM_GPORT_IS_UCAST_QUEUE_GROUP(sched_gport))){ 4012 if ((sched_node->type == _BCM_MN_NODE_VOQ)) { 4013 _bcm_mn_node_index_clear(list, sched_node->hw_index, 1); 4014 sched_node->hw_index = -1; 4015 } 4016 } 4017 } 4018 } 4019 if ((sched_node->type == _BCM_MN_NODE_SERVICE_UCAST) && 4020 ((start + 1) < end)){ 4021 BCM_IF_ERROR_RETURN 4022 (_bcm_mn_cosq_node_get(unit, sched_gport, start + 1, NULL, 4023 &sched_port, NULL, &sched_node)); 4024 if (!sched_node) { 4025 return BCM_E_NOT_FOUND; 4026 } 4027 } 4028 } 4029 4030 if (soc_feature(unit, 4031 soc_feature_mmu_hqos_four_level) && 4032 sched_node->level == SOC_MONTEREY_NODE_LVL_S1) { 4033 child_node = parent_node->child; 4034 while(child_node) { 4035 if(_BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, 4036 child_node->port_gport)) { 4037 subport_enabled = 1; 4038 break; 4039 } 4040 child_node = child_node->sibling; 4041 } 4042 if (!subport_enabled) { 4043 BCM_IF_ERROR_RETURN( 4044 _bcm_mn_mmu_port_coe_control(unit, 4045 sched_node->local_port, 0)); 4046 } 4047 } 4048 LOG_INFO(BSL_LS_BCM_COSQ, 4049 (BSL_META_U(unit, 4050 " hw_cosq=%d\n"), 4051 sched_node->attached_to_input)); 4052 4053 return BCM_E_NONE; 4054 } 4055 4056 /* 4057 * Function: 4058 * bcm_mn_cosq_gport_delete 4059 * Purpose: 4060 * Destroy a cosq gport structure 4061 * Parameters: 4062 * unit - (IN) unit number 4063 * gport - (IN) GPORT identifier 4064 * Returns: 4065 * BCM_E_XXX 4066 */ 4067 int 4068 bcm_mn_cosq_gport_delete(int unit, bcm_gport_t gport) 4069 { 4070 _bcm_mn_cosq_node_t *node, *tnode, *base_node; 4071 _bcm_mn_cosq_node_t * s1_node = NULL ; 4072 int ii, local_port, phy_port, mmu_port, hw_index; 4073 _bcm_mn_mmu_info_t *mmu_info; 4074 soc_info_t *si; 4075 bcm_gport_t parent_gport = 0 ; 4076 int level = 0 ; 4077 _bcm_mn_pipe_resources_t * res; 4078 _bcm_mn_cosq_port_info_t *port_info; 4079 LOG_INFO(BSL_LS_BCM_COSQ, 4080 (BSL_META_U(unit, 4081 "bcm_mn_cosq_gport_delete: unit=%d gport=0x%x\n"), 4082 unit, gport)); 4083 4084 node = NULL; 4085 base_node= NULL; 4086 4087 mmu_info = _bcm_mn_mmu_info[unit]; 4088 si = &SOC_INFO(unit); 4089 if (!soc_feature(unit, soc_feature_ets)) { 4090 return BCM_E_UNAVAIL; 4091 } 4092 4093 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 4094 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) || 4095 (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport)) || 4096 BCM_GPORT_IS_SCHEDULER(gport)) { 4097 BCM_IF_ERROR_RETURN 4098 (_bcm_mn_cosq_node_get(unit, gport, 0, NULL, &local_port, NULL, &node)); 4099 port_info = &mmu_info->port_info[local_port]; 4100 res = port_info->resources; 4101 4102 } else if(_BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, gport)) { 4103 BCM_IF_ERROR_RETURN 4104 (_bcm_mn_get_s1_node(unit, gport, &node)); 4105 BCM_IF_ERROR_RETURN 4106 (_bcmi_coe_subport_physical_port_get(unit, gport, &local_port)); 4107 port_info = &mmu_info->port_info[local_port]; 4108 res = port_info->resources; 4109 4110 } else { 4111 BCM_IF_ERROR_RETURN( 4112 bcm_esw_port_local_get(unit, gport, &local_port)); 4113 if (local_port >= _BCM_MN_MAX_PORT) { 4114 return BCM_E_PORT; 4115 } 4116 4117 port_info = &mmu_info->port_info[local_port]; 4118 res = port_info->resources; 4119 phy_port = si->port_l2p_mapping[local_port]; 4120 mmu_port = si->port_p2m_mapping[phy_port]; 4121 hw_index = _BCM_MN_ROOT_SCHED_INDEX(unit, mmu_port); 4122 4123 for (ii = 0; ii < _BCM_MN_NUM_TOTAL_SCHEDULERS; ii++) { 4124 tnode = &mmu_info->sched_node[ii]; 4125 if (tnode->in_use == FALSE) { 4126 continue; 4127 } 4128 if ((tnode->level == SOC_MONTEREY_NODE_LVL_ROOT) && 4129 (tnode->hw_index == hw_index) && 4130 (tnode->local_port == local_port)) { 4131 /* check both mmu_port(unique only within a pipe) 4132 and local_port(unique witin system) to get the 4133 correct node */ 4134 node = tnode; 4135 break; 4136 } 4137 } 4138 if (node == NULL) { 4139 return BCM_E_NONE; 4140 } 4141 } 4142 if (!node->in_use) { 4143 return BCM_E_NONE; 4144 } 4145 level = node->level; 4146 if (node->parent) 4147 { 4148 parent_gport = node->parent->gport; 4149 } 4150 while(node->child != NULL) { 4151 BCM_IF_ERROR_RETURN(bcm_mn_cosq_gport_delete(unit, node->child->gport)); 4152 } 4153 4154 if (!soc_feature(unit, soc_feature_mmu_hqos_four_level) && 4155 (level == SOC_MONTEREY_NODE_LVL_ROOT) && (!node->in_use)) 4156 { 4157 return BCM_E_NONE; 4158 } 4159 if (node->level != SOC_MONTEREY_NODE_LVL_ROOT && node->attached_to_input >= 0) { 4160 BCM_IF_ERROR_RETURN 4161 (bcm_mn_cosq_gport_detach(unit, node->gport, 4162 node->parent->gport, node->attached_to_input)); 4163 } 4164 4165 4166 if (soc_feature(unit, soc_feature_mmu_hqos_four_level)) { 4167 if ((node->level == SOC_MONTEREY_NODE_LVL_L2) && 4168 _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, node->port_gport)) { 4169 BCM_IF_ERROR_RETURN 4170 (_bcm_mn_get_s1_node(unit, node->port_gport, &s1_node)); 4171 s1_node->coe_num_l2--; 4172 if (!s1_node->coe_num_l2) { 4173 BCM_IF_ERROR_RETURN 4174 (_bcm_mn_coe_queue_offset_clear(unit, s1_node->coe_base_index, 4175 node->port_gport)); 4176 BCM_IF_ERROR_RETURN 4177 (_bcm_mn_allocate_coe_queues(unit, s1_node, 0)); 4178 } 4179 } 4180 } 4181 if ((node->type == _BCM_MN_NODE_VOQ) && 4182 (node->remote_modid > 0)) { 4183 _bcm_mn_voq_next_base_node_get (unit, local_port, 4184 node->remote_modid, &base_node); 4185 if (base_node != NULL) { 4186 BCM_PBMP_ASSIGN(base_node->fabric_pbmp, 4187 node->fabric_pbmp); 4188 } 4189 } 4190 4191 if ((node->level == SOC_MONTEREY_NODE_LVL_L2) && 4192 (BCM_GPORT_IS_UCAST_QUEUE_GROUP(node->gport)) && 4193 (node->type != _BCM_MN_NODE_VOQ) && 4194 ((node->hw_index < port_info->uc_base) || 4195 (node->hw_index >= port_info->uc_limit))) 4196 { 4197 _bcm_mn_node_index_clear(&res->l2_queue_list, 4198 node->hw_index, 1); 4199 node->hw_index = -1; 4200 } 4201 if (node->cosq_map != NULL) { 4202 sal_free(node->cosq_map); 4203 } 4204 if ((!(soc_feature(unit, soc_feature_mmu_hqos_four_level)) && 4205 node->level == SOC_MONTEREY_NODE_LVL_S1) && parent_gport ) 4206 { 4207 BCM_IF_ERROR_RETURN(bcm_mn_cosq_gport_delete(unit, parent_gport)); 4208 } 4209 if (IS_MN_HSP_PORT(unit, local_port)) { 4210 BCM_IF_ERROR_RETURN 4211 (_bcm_mn_cosq_clear_child_list(unit, node)); 4212 } 4213 _BCM_MN_COSQ_NODE_INIT(node); 4214 return BCM_E_NONE; 4215 } 4216 4217 /* 4218 * Function: 4219 * bcm_mn_cosq_gport_get 4220 * Purpose: 4221 * Get a cosq gport structure 4222 * Parameters: 4223 * unit - (IN) unit number 4224 * gport - (IN) GPORT identifier 4225 * port - (OUT) port number 4226 * numq - (OUT) number of COS queues 4227 * flags - (OUT) flags (BCM_COSQ_GPORT_XXX) 4228 * Returns: 4229 * BCM_E_XXX 4230 */ 4231 int 4232 bcm_mn_cosq_gport_get(int unit, bcm_gport_t gport, bcm_gport_t *port, 4233 int *numq, uint32 *flags) 4234 { 4235 _bcm_mn_cosq_node_t *node; 4236 bcm_module_t modid; 4237 bcm_port_t local_port; 4238 int id; 4239 _bcm_gport_dest_t dest; 4240 4241 if (port == NULL || numq == NULL || flags == NULL) { 4242 return BCM_E_PARAM; 4243 } 4244 4245 LOG_INFO(BSL_LS_BCM_COSQ, 4246 (BSL_META_U(unit, 4247 "bcm_mn_cosq_gport_get: unit=%d gport=0x%x\n"), 4248 unit, gport)); 4249 4250 BCM_IF_ERROR_RETURN 4251 (_bcm_mn_cosq_node_get(unit, gport, 0, NULL, &local_port, &id, &node)); 4252 4253 if (SOC_USE_GPORT(unit)) { 4254 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid)); 4255 dest.gport_type = _SHR_GPORT_TYPE_MODPORT; 4256 dest.modid = modid; 4257 dest.port = local_port; 4258 BCM_IF_ERROR_RETURN(_bcm_esw_gport_construct(unit, &dest, port)); 4259 } else { 4260 *port = local_port; 4261 } 4262 4263 *numq = node->numq; 4264 4265 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 4266 if (node->type == _BCM_MN_NODE_SERVICE_UCAST) { 4267 *flags = BCM_COSQ_GPORT_VLAN_UCAST_QUEUE_GROUP; 4268 } else if (node->type == _BCM_MN_NODE_VM_UCAST) { 4269 *flags = BCM_COSQ_GPORT_VIRTUAL_PORT; 4270 } else if (node->type == _BCM_MN_NODE_VOQ) { 4271 *flags = BCM_COSQ_GPORT_DESTMOD_UCAST_QUEUE_GROUP; 4272 } else { 4273 *flags = BCM_COSQ_GPORT_UCAST_QUEUE_GROUP; 4274 } 4275 } else if (BCM_GPORT_IS_SCHEDULER(gport)) { 4276 *flags = BCM_COSQ_GPORT_SCHEDULER; 4277 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 4278 *flags = BCM_COSQ_GPORT_MCAST_QUEUE_GROUP; 4279 } else { 4280 *flags = 0; 4281 } 4282 4283 LOG_INFO(BSL_LS_BCM_COSQ, 4284 (BSL_META_U(unit, 4285 " port=0x%x numq=%d flags=0x%x\n"), 4286 *port, *numq, *flags)); 4287 4288 return BCM_E_NONE; 4289 } 4290 4291 /* 4292 * Function: 4293 * bcm_mn_cosq_gport_traverse 4294 * Purpose: 4295 * Walks through the valid COSQ GPORTs and calls 4296 * the user supplied callback function for each entry. 4297 * Parameters: 4298 * unit - (IN) unit number 4299 * trav_fn - (IN) Callback function. 4300 * user_data - (IN) User data to be passed to callback function 4301 * Returns: 4302 * BCM_E_NONE - Success. 4303 * BCM_E_XXX 4304 */ 4305 int 4306 bcm_mn_cosq_gport_traverse(int unit, bcm_cosq_gport_traverse_cb cb, 4307 void *user_data) 4308 { 4309 _bcm_mn_cosq_node_t *port_info; 4310 _bcm_mn_mmu_info_t *mmu_info; 4311 bcm_module_t my_modid, modid_out; 4312 bcm_port_t port, port_out; 4313 4314 if (_bcm_mn_mmu_info[unit] == NULL) { 4315 return BCM_E_INIT; 4316 } 4317 mmu_info = _bcm_mn_mmu_info[unit]; 4318 4319 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_modid)); 4320 PBMP_ALL_ITER(unit, port) { 4321 BCM_IF_ERROR_RETURN 4322 (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, 4323 my_modid, port, &modid_out, &port_out)); 4324 4325 /* root node */ 4326 port_info = &mmu_info->sched_node[port_out]; 4327 4328 if (port_info->gport >= 0) { 4329 _bcm_mn_cosq_gport_traverse(unit, port_info->gport, cb, user_data); 4330 } 4331 } 4332 4333 return BCM_E_NONE; 4334 } 4335 4336 4337 /* 4338 * Function: 4339 * bcm_mn_cosq_gport_attach 4340 * Purpose: 4341 * Attach sched_port to the specified index (cosq) of parent_port 4342 * Parameters: 4343 * unit - (IN) unit number 4344 * sched_port - (IN) scheduler GPORT identifier 4345 * parent_port - (IN) GPORT to attach to 4346 * cosq - (IN) COS queue to attach to (-1 for first available cosq) 4347 * Returns: 4348 * BCM_E_XXX 4349 */ 4350 int 4351 bcm_mn_cosq_gport_attach(int unit, bcm_gport_t gport, 4352 bcm_gport_t parent_gport, 4353 bcm_cos_queue_t to_cosq) 4354 { 4355 _bcm_mn_mmu_info_t *mmu_info; 4356 _bcm_mn_cosq_node_t *node, *parent_node, *child_node, *s1_node; 4357 bcm_port_t port, to_port, local_port = 0, mmu_port; 4358 int rv, tmp; 4359 int max_nodes = 0; 4360 int subport_enabled = 0; 4361 uint32 rval = 0; 4362 uint32 mc_group_mode = 0; 4363 4364 if ((mmu_info = _bcm_mn_mmu_info[unit]) == NULL) { 4365 return BCM_E_INIT; 4366 } 4367 4368 if ((BCM_GPORT_IS_UCAST_QUEUE_GROUP(parent_gport)) || 4369 (BCM_GPORT_IS_MCAST_QUEUE_GROUP(parent_gport)) || 4370 (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(parent_gport))) { 4371 return BCM_E_PARAM; 4372 } 4373 4374 if(!(BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 4375 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) || 4376 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport) || 4377 BCM_GPORT_IS_SCHEDULER(gport))) { 4378 return BCM_E_PORT; 4379 } 4380 4381 BCM_IF_ERROR_RETURN 4382 (_bcm_mn_cosq_node_get(unit, gport, 0, NULL, &port, NULL, &node)); 4383 4384 if (node->attached_to_input >= 0) { 4385 /* Has already attached */ 4386 return BCM_E_EXISTS; 4387 } 4388 tmp = node->attached_to_input; 4389 4390 if (BCM_GPORT_IS_SCHEDULER(parent_gport)) { 4391 BCM_IF_ERROR_RETURN 4392 (_bcm_mn_cosq_node_get(unit, parent_gport, 0, NULL, &to_port, NULL, 4393 &parent_node)); 4394 } else { 4395 BCM_IF_ERROR_RETURN 4396 (_bcm_mn_cosq_localport_resolve(unit, parent_gport, &to_port)); 4397 parent_node = &mmu_info->sched_node[to_port]; 4398 } 4399 4400 if (port != to_port) { 4401 return BCM_E_PORT; 4402 } 4403 if (!parent_node) 4404 { 4405 return BCM_E_NOT_FOUND; 4406 } 4407 4408 if ((parent_node->level == SOC_MONTEREY_NODE_LVL_ROOT) && 4409 _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, node->port_gport)) { 4410 rv = _bcm_mn_get_s1_node(unit, node->port_gport, 4411 &s1_node); 4412 if( rv != BCM_E_NOT_FOUND) { 4413 return BCM_E_EXISTS; 4414 } 4415 4416 } 4417 if (parent_node->level != SOC_MONTEREY_NODE_LVL_ROOT && 4418 parent_node->port_gport != node->port_gport) 4419 { 4420 return BCM_E_PARAM; 4421 } 4422 mmu_port = SOC_MONTEREY_MMU_PORT(unit, port); 4423 4424 /* Identify the levels of schedulers 4425 * parent_port == phy_port && gport == scheduler => gport = S1 4426 * parent_port == scheduler && level = S1 && gport == scheduler => gport = L0 4427 * parent_port == schduler && lvel = L0 && gport == scheduler => parent_port = L0 and gport = L1 4428 * parent_port == scheduler && port == queue_group => parent_port = L1 and gport = L2 4429 */ 4430 if (!BCM_GPORT_IS_SCHEDULER(parent_gport)) { 4431 if ((parent_node->numq == 0) || (parent_node->numq_expandable)) { 4432 local_port = (BCM_GPORT_IS_LOCAL(parent_gport)) ? 4433 BCM_GPORT_LOCAL_GET(parent_gport) : 4434 BCM_GPORT_MODPORT_PORT_GET(parent_gport); 4435 4436 if (!SOC_PORT_VALID(unit, local_port)) { 4437 return BCM_E_PORT; 4438 } 4439 parent_node->in_use = TRUE; 4440 parent_node->local_port = port; 4441 if (IS_MN_HSP_PORT(unit, local_port)) { 4442 parent_node->base_index = _BCM_MN_HSP_L0_INDEX(unit, mmu_port, 0); 4443 parent_node->numq = _BCM_MN_HSP_PORT_MAX_L0; 4444 } else { 4445 parent_node->gport = parent_gport; 4446 parent_node->hw_index = _BCM_MN_ROOT_SCHED_INDEX(unit, mmu_port); 4447 parent_node->level = SOC_MONTEREY_NODE_LVL_ROOT; 4448 parent_node->attached_to_input = 0; 4449 parent_node->numq_expandable = 1; 4450 if (to_cosq == -1) { 4451 parent_node->numq += 1; 4452 } else { 4453 if (to_cosq >= parent_node->numq) { 4454 parent_node->numq = to_cosq + 1; 4455 } 4456 } 4457 } 4458 } 4459 4460 if (!BCM_GPORT_IS_SCHEDULER(gport)) { 4461 return BCM_E_PARAM; 4462 } 4463 4464 if (IS_MN_HSP_PORT(unit, to_port)) { 4465 node->level = SOC_MONTEREY_NODE_LVL_L0; 4466 } else { 4467 node->level = SOC_MONTEREY_NODE_LVL_S1; 4468 } 4469 } else { 4470 if (parent_node->level == SOC_MONTEREY_NODE_LVL_ROOT) { 4471 if (IS_MN_HSP_PORT(unit, to_port)) { 4472 node->level = SOC_MONTEREY_NODE_LVL_L0; 4473 } else { 4474 node->level = SOC_MONTEREY_NODE_LVL_S1; 4475 } 4476 } 4477 if (parent_node->level == SOC_MONTEREY_NODE_LVL_S1) { 4478 node->level = SOC_MONTEREY_NODE_LVL_L0; 4479 } 4480 if (parent_node->level == SOC_MONTEREY_NODE_LVL_L0) { 4481 node->level = SOC_MONTEREY_NODE_LVL_L1; 4482 4483 /*only for hsp ports with mc-group-mode enabled 2 l2 mulicast 4484 can be attached directly to L0.0 */ 4485 if (IS_MN_HSP_PORT(unit, to_port)) { 4486 SOC_IF_ERROR_RETURN( 4487 READ_HSP_SCHED_PORT_CONFIGr(unit, to_port, &rval)); 4488 mc_group_mode = soc_reg_field_get(unit, HSP_SCHED_PORT_CONFIGr, 4489 rval, MC_GROUP_MODEf); 4490 if ((mc_group_mode) && (parent_node->attached_to_input == 0)) 4491 node->level = SOC_MONTEREY_NODE_LVL_L2; 4492 } 4493 } 4494 if (parent_node->level == SOC_MONTEREY_NODE_LVL_L1) { 4495 node->level = SOC_MONTEREY_NODE_LVL_L2; 4496 } 4497 BCM_IF_ERROR_RETURN 4498 (_bcm_mn_cosq_max_nodes_get(unit, node->level, &max_nodes)); 4499 if (parent_node->numq > max_nodes) { 4500 return BCM_E_PARAM; 4501 } 4502 } 4503 4504 if ((to_cosq < -1) || ((parent_node->numq != -1) && (to_cosq >= parent_node->numq))) { 4505 return BCM_E_PARAM; 4506 } 4507 4508 if (BCM_GPORT_IS_SCHEDULER(parent_gport) || BCM_GPORT_IS_LOCAL(parent_gport) || 4509 BCM_GPORT_IS_MODPORT(parent_gport)) { 4510 int start = 0, end = 0; 4511 if (parent_node->attached_to_input < 0) { 4512 /* dont allow to attach to a node that has already attached */ 4513 return BCM_E_PARAM; 4514 } 4515 4516 if (node->type == _BCM_MN_NODE_SERVICE_UCAST) { 4517 end = node->numq; 4518 } else { 4519 end = 1; 4520 } 4521 4522 for (start = 0; start < end; start++) { 4523 node->parent = parent_node; 4524 node->sibling = parent_node->child; 4525 parent_node->child = node; 4526 /* resolve the nodes */ 4527 rv = _bcm_mn_cosq_node_resolve(unit, node, to_cosq + start); 4528 if (BCM_FAILURE(rv)) { 4529 parent_node->child = node->sibling; 4530 node->parent = NULL; 4531 node->attached_to_input = tmp; 4532 return rv; 4533 } 4534 LOG_INFO(BSL_LS_BCM_COSQ, 4535 (BSL_META_U(unit, 4536 " hw_cosq=%d\n"), 4537 node->attached_to_input)); 4538 4539 if ((node->type == _BCM_MN_NODE_SERVICE_UCAST) && 4540 ((start + 1) < end)){ 4541 BCM_IF_ERROR_RETURN 4542 (_bcm_mn_cosq_node_get(unit, gport, start + 1, NULL, 4543 &port, NULL, &node)); 4544 if (!node) { 4545 return BCM_E_NOT_FOUND; 4546 } 4547 } 4548 } 4549 if (soc_feature(unit, 4550 soc_feature_mmu_hqos_four_level) && 4551 node->level == SOC_MONTEREY_NODE_LVL_S1) { 4552 child_node = parent_node->child; 4553 while(child_node) { 4554 if(_BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, 4555 child_node->port_gport)) { 4556 subport_enabled++ ; 4557 if(subport_enabled > 1) { 4558 break; 4559 } 4560 } 4561 child_node = child_node->sibling; 4562 } 4563 if (subport_enabled == 1) { 4564 BCM_IF_ERROR_RETURN( 4565 _bcm_mn_mmu_port_coe_control(unit, 4566 node->local_port, 1)); 4567 } 4568 } 4569 } else { 4570 return BCM_E_PORT; 4571 } 4572 4573 return BCM_E_NONE; 4574 } 4575 4576 /* 4577 * Function: 4578 * bcm_mn_cosq_gport_attach_get 4579 * Purpose: 4580 * Get attached status of a scheduler port 4581 * Parameters: 4582 * unit - (IN) unit number 4583 * sched_port - (IN) scheduler GPORT identifier 4584 * parent_port - (OUT) GPORT to attach to 4585 * cosq - (OUT) COS queue to attached to 4586 * Returns: 4587 * BCM_E_XXX 4588 * Notes: 4589 */ 4590 int 4591 bcm_mn_cosq_gport_attach_get(int unit, bcm_gport_t sched_gport, 4592 bcm_gport_t *parent_gport, bcm_cos_queue_t *cosq) 4593 { 4594 _bcm_mn_cosq_node_t *sched_node; 4595 bcm_module_t modid, modid_out; 4596 bcm_port_t port, port_out; 4597 4598 if (parent_gport == NULL || cosq == NULL) { 4599 return BCM_E_PARAM; 4600 } 4601 4602 BCM_IF_ERROR_RETURN 4603 (_bcm_mn_cosq_node_get(unit, sched_gport, 0, &modid, &port, NULL, 4604 &sched_node)); 4605 4606 if (sched_node->attached_to_input < 0) { 4607 /* Not attached yet */ 4608 return BCM_E_NOT_FOUND; 4609 } 4610 4611 if (sched_node->parent != NULL) { /* sched_node is not an S1 scheduler */ 4612 *parent_gport = sched_node->parent->gport; 4613 } else { /* sched_node is an S1 scheduler */ 4614 BCM_IF_ERROR_RETURN 4615 (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, modid, port, 4616 &modid_out, &port_out)); 4617 BCM_GPORT_MODPORT_SET(*parent_gport, modid_out, port_out); 4618 } 4619 *cosq = sched_node->attached_to_input; 4620 4621 return BCM_E_NONE; 4622 } 4623 4624 /* 4625 * Function: 4626 * bcm_mn_cosq_gport_child_get 4627 * Purpose: 4628 * Get the child node GPORT atatched to N-th index (cosq) 4629 * of the scheduler GPORT. 4630 * Parameters: 4631 * unit - (IN) Unit number. 4632 * in_gport - (IN) Scheduler GPORT ID. 4633 * cosq - (IN) COS queue attached to. 4634 * out_gport - (OUT) child GPORT ID. 4635 * Returns: 4636 * BCM_E_XXX 4637 * Notes: 4638 */ 4639 int 4640 bcm_mn_cosq_gport_child_get(int unit, bcm_gport_t in_gport, 4641 bcm_cos_queue_t cosq, 4642 bcm_gport_t *out_gport) 4643 { 4644 _bcm_mn_cosq_node_t *in_node = NULL; 4645 _bcm_mn_cosq_node_t *cur_node = NULL; 4646 _bcm_mn_cosq_node_t *tmp_node = NULL; 4647 bcm_module_t modid; 4648 bcm_port_t port; 4649 4650 if (out_gport == NULL) { 4651 return BCM_E_PARAM; 4652 } 4653 4654 /* get the child of the input gport node 4655 * at an index of cosq 4656 */ 4657 4658 if ((cosq < 0) || ( cosq >= 64)) { 4659 return BCM_E_PARAM; 4660 } 4661 4662 BCM_IF_ERROR_RETURN 4663 (_bcm_mn_cosq_node_get(unit, in_gport, 0, &modid, &port, NULL, 4664 &in_node)); 4665 if ((in_node->child == NULL) && (in_node->level == SOC_MONTEREY_NODE_LVL_L2)) { 4666 return BCM_E_PARAM; 4667 } 4668 4669 for (cur_node = in_node->child; cur_node != NULL; 4670 cur_node = cur_node->sibling) { 4671 if (cur_node->attached_to_input == cosq) { 4672 tmp_node = cur_node; 4673 break; 4674 } 4675 } 4676 if (tmp_node == NULL) { 4677 return BCM_E_NOT_FOUND; 4678 } 4679 *out_gport = tmp_node->gport; 4680 4681 return BCM_E_NONE; 4682 } 4683 4684 /* 4685 * Convert HW drop probability to percent value 4686 */ 4687 STATIC int 4688 _bcm_mn_hw_drop_prob_to_percent[] = { 4689 0, /* 0 */ 4690 1, /* 1 */ 4691 2, /* 2 */ 4692 3, /* 3 */ 4693 4, /* 4 */ 4694 5, /* 5 */ 4695 6, /* 6 */ 4696 7, /* 7 */ 4697 8, /* 8 */ 4698 9, /* 9 */ 4699 10, /* 10 */ 4700 25, /* 11 */ 4701 50, /* 12 */ 4702 75, /* 13 */ 4703 100, /* 14 */ 4704 -1 /* 15 */ 4705 }; 4706 4707 STATIC int 4708 _bcm_mn_percent_to_drop_prob(int percent) 4709 { 4710 int i; 4711 4712 for (i = 14; i > 0 ; i--) { 4713 if (percent >= _bcm_mn_hw_drop_prob_to_percent[i]) { 4714 break; 4715 } 4716 } 4717 return i; 4718 } 4719 4720 STATIC int 4721 _bcm_mn_drop_prob_to_percent(int drop_prob) { 4722 return (_bcm_mn_hw_drop_prob_to_percent[drop_prob]); 4723 } 4724 4725 /* 4726 * index: degree, value: contangent(degree) * 100 4727 * max value is 0xffff (16-bit) at 0 degree 4728 */ 4729 STATIC int 4730 _bcm_mn_cotangent_lookup_table[] = 4731 { 4732 /* 0.. 5 */ 65535, 5728, 2863, 1908, 1430, 1143, 4733 /* 6..11 */ 951, 814, 711, 631, 567, 514, 4734 /* 12..17 */ 470, 433, 401, 373, 348, 327, 4735 /* 18..23 */ 307, 290, 274, 260, 247, 235, 4736 /* 24..29 */ 224, 214, 205, 196, 188, 180, 4737 /* 30..35 */ 173, 166, 160, 153, 148, 142, 4738 /* 36..41 */ 137, 132, 127, 123, 119, 115, 4739 /* 42..47 */ 111, 107, 103, 100, 96, 93, 4740 /* 48..53 */ 90, 86, 83, 80, 78, 75, 4741 /* 54..59 */ 72, 70, 67, 64, 62, 60, 4742 /* 60..65 */ 57, 55, 53, 50, 48, 46, 4743 /* 66..71 */ 44, 42, 40, 38, 36, 34, 4744 /* 72..77 */ 32, 30, 28, 26, 24, 23, 4745 /* 78..83 */ 21, 19, 17, 15, 14, 12, 4746 /* 84..89 */ 10, 8, 6, 5, 3, 1, 4747 /* 90 */ 0 4748 }; 4749 4750 /* 4751 * Given a slope (angle in degrees) from 0 to 90, return the number of cells 4752 * in the range from 0% drop probability to 100% drop probability. 4753 */ 4754 STATIC int 4755 _bcm_mn_angle_to_cells(int angle) 4756 { 4757 return (_bcm_mn_cotangent_lookup_table[angle]); 4758 } 4759 4760 /* 4761 * Given a number of packets in the range from 0% drop probability 4762 * to 100% drop probability, return the slope (angle in degrees). 4763 */ 4764 STATIC int 4765 _bcm_mn_cells_to_angle(int packets) 4766 { 4767 int angle; 4768 4769 for (angle = 90; angle >= 0 ; angle--) { 4770 if (packets <= _bcm_mn_cotangent_lookup_table[angle]) { 4771 break; 4772 } 4773 } 4774 return angle; 4775 } 4776 4777 /* 4778 * Function: 4779 * _bcm_mn_cosq_bucket_set 4780 * Purpose: 4781 * Configure COS queue bandwidth control bucket 4782 * Parameters: 4783 * unit - (IN) unit number 4784 * port - (IN) port number or GPORT identifier 4785 * cosq - (IN) COS queue number 4786 * min_quantum - (IN) kbps or packet/second 4787 * max_quantum - (IN) kbps or packet/second 4788 * burst_quantum - (IN) kbps or packet/second 4789 * flags - (IN) 4790 * Returns: 4791 * BCM_E_XXX 4792 * Notes: 4793 * If port is any form of local port, cosq is the hardware queue index. 4794 */ 4795 STATIC int 4796 _bcm_mn_cosq_bucket_set(int unit, bcm_gport_t port, bcm_cos_queue_t cosq, 4797 uint32 min_quantum, uint32 max_quantum, 4798 uint32 kbits_burst_min, uint32 kbits_burst_max, 4799 uint32 flags) 4800 { 4801 _bcm_mn_cosq_node_t *node = NULL; 4802 bcm_port_t local_port; 4803 int index; 4804 uint32 rval; 4805 uint32 meter_flags; 4806 uint32 bucketsize_max, bucketsize_min; 4807 uint32 granularity_max, granularity_min; 4808 uint32 refresh_rate_max, refresh_rate_min; 4809 int refresh_bitsize = 0, bucket_bitsize = 0; 4810 soc_mem_t config_mem = INVALIDm; 4811 uint32 mc_group_mode = 0; 4812 uint32 entry[SOC_MAX_MEM_WORDS]; 4813 4814 /* caller should resolve the cosq. */ 4815 if (cosq < 0) { 4816 if (cosq == -1) { 4817 /* caller needs to resolve the wild card value (-1) */ 4818 return BCM_E_INTERNAL; 4819 } else { /* reject all other negative value */ 4820 return BCM_E_PARAM; 4821 } 4822 } 4823 4824 BCM_IF_ERROR_RETURN 4825 (_bcm_mn_cosq_index_resolve(unit, port, cosq, 4826 _BCM_MN_COSQ_INDEX_STYLE_BUCKET, 4827 &local_port, &index, NULL)); 4828 4829 if (BCM_GPORT_IS_SET(port) && 4830 ((BCM_GPORT_IS_SCHEDULER(port)) || 4831 BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 4832 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) || 4833 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port))) { 4834 4835 BCM_IF_ERROR_RETURN 4836 (_bcm_mn_cosq_node_get(unit, port, cosq, NULL, 4837 NULL, NULL, &node)); 4838 if ((node->level == SOC_MONTEREY_NODE_LVL_ROOT) && 4839 !IS_MN_HSP_PORT(unit, local_port) && 4840 (min_quantum > 0)) { 4841 /* min shaper is not supported */ 4842 return BCM_E_PARAM; 4843 } 4844 } 4845 4846 if (node) { 4847 if (BCM_GPORT_IS_SCHEDULER(port) || BCM_GPORT_IS_MODPORT(port)) { 4848 if (node->level == SOC_MONTEREY_NODE_LVL_ROOT) { 4849 config_mem = MMU_MTRO_L0_MEMm; 4850 } else if (node->level == SOC_MONTEREY_NODE_LVL_L0) { 4851 SOC_IF_ERROR_RETURN( 4852 READ_HSP_SCHED_PORT_CONFIGr(unit, local_port, &rval)); 4853 4854 mc_group_mode = soc_reg_field_get(unit, HSP_SCHED_PORT_CONFIGr, 4855 rval, MC_GROUP_MODEf); 4856 if (mc_group_mode) { 4857 config_mem = MMU_MTRO_L2_MEMm; 4858 } else { 4859 config_mem = MMU_MTRO_L1_MEMm; 4860 } 4861 } else if (node->level == SOC_MONTEREY_NODE_LVL_L1) { 4862 config_mem = MMU_MTRO_L2_MEMm; 4863 } else { 4864 return BCM_E_PARAM; 4865 } 4866 } else if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 4867 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 4868 config_mem = MMU_MTRO_L2_MEMm; 4869 } else { 4870 return BCM_E_PARAM; 4871 } 4872 } else { 4873 if (IS_CPU_PORT(unit, local_port)) { 4874 config_mem = MMU_MTRO_L2_MEMm; 4875 } else { 4876 config_mem = MMU_MTRO_L1_MEMm; 4877 } 4878 } 4879 4880 meter_flags = flags & BCM_COSQ_BW_PACKET_MODE ? 4881 _BCM_TD_METER_FLAG_PACKET_MODE : 0; 4882 BCM_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, &rval)); 4883 if (soc_reg_field_get(unit, MISCCONFIGr, rval, ITU_MODE_SELf)) { 4884 meter_flags |= _BCM_TD_METER_FLAG_NON_LINEAR; 4885 } 4886 4887 refresh_bitsize = soc_mem_field_length(unit, config_mem, MAX_REFRESHf); 4888 bucket_bitsize = soc_mem_field_length(unit, config_mem, MAX_THD_SELf); 4889 4890 BCM_IF_ERROR_RETURN 4891 (_bcm_td_rate_to_bucket_encoding(unit, max_quantum, kbits_burst_max, 4892 meter_flags, refresh_bitsize, 4893 bucket_bitsize, &refresh_rate_max, 4894 &bucketsize_max, &granularity_max)); 4895 4896 BCM_IF_ERROR_RETURN 4897 (_bcm_td_rate_to_bucket_encoding(unit, min_quantum, kbits_burst_min, 4898 meter_flags, refresh_bitsize, 4899 bucket_bitsize, &refresh_rate_min, 4900 &bucketsize_min, &granularity_min)); 4901 4902 sal_memset(entry, 0, sizeof(uint32)*SOC_MAX_MEM_WORDS); 4903 soc_mem_field32_set(unit, config_mem, &entry, MAX_METER_GRANf, granularity_max); 4904 soc_mem_field32_set(unit, config_mem, &entry, MAX_REFRESHf, refresh_rate_max); 4905 soc_mem_field32_set(unit, config_mem, &entry, MAX_THD_SELf, bucketsize_max); 4906 4907 soc_mem_field32_set(unit, config_mem, &entry, MIN_METER_GRANf, granularity_min); 4908 soc_mem_field32_set(unit, config_mem, &entry, MIN_REFRESHf, refresh_rate_min); 4909 soc_mem_field32_set(unit, config_mem, &entry, MIN_THD_SELf, bucketsize_min); 4910 4911 soc_mem_field32_set(unit, config_mem, &entry, SHAPER_CONTROLf, 4912 (flags & BCM_COSQ_BW_PACKET_MODE) ? 1 : 0); 4913 4914 soc_mem_field32_set(unit, config_mem, &entry, EAV_ENABLEf, 4915 (flags & BCM_COSQ_BW_EAV_MODE) ? 1 : 0); 4916 BCM_IF_ERROR_RETURN 4917 (soc_mem_write(unit, config_mem, MEM_BLOCK_ALL, index, &entry)); 4918 4919 return BCM_E_NONE; 4920 } 4921 4922 /* 4923 * Function: 4924 * _bcm_mn_cosq_bucket_get 4925 * Purpose: 4926 * Get COS queue bandwidth control bucket setting 4927 * Parameters: 4928 * unit - (IN) unit number 4929 * port - (IN) port number or GPORT identifier 4930 * cosq - (IN) COS queue number 4931 * min_quantum - (OUT) kbps or packet/second 4932 * max_quantum - (OUT) kbps or packet/second 4933 * burst_quantum - (OUT) kbps or packet/second 4934 * flags - (IN) 4935 * Returns: 4936 * BCM_E_XXX 4937 * Notes: 4938 * If port is any form of local port, cosq is the hardware queue index. 4939 */ 4940 STATIC int 4941 _bcm_mn_cosq_bucket_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 4942 uint32 *min_quantum, uint32 *max_quantum, 4943 uint32 *kbits_burst_min, uint32 *kbits_burst_max, 4944 uint32 *flags) 4945 { 4946 _bcm_mn_cosq_node_t *node = NULL; 4947 bcm_port_t local_port; 4948 int index; 4949 uint32 rval; 4950 uint32 refresh_rate, bucketsize, granularity, meter_flags; 4951 soc_mem_t config_mem = INVALIDm; 4952 uint32 mc_group_mode = 0; 4953 uint32 entry[SOC_MAX_MEM_WORDS]; 4954 4955 if (cosq < 0) { 4956 if (cosq == -1) { 4957 /* caller needs to resolve the wild card value (-1) */ 4958 return BCM_E_INTERNAL; 4959 } else { /* reject all other negative value */ 4960 return BCM_E_PARAM; 4961 } 4962 } 4963 4964 BCM_IF_ERROR_RETURN 4965 (_bcm_mn_cosq_index_resolve(unit, port, cosq, 4966 _BCM_MN_COSQ_INDEX_STYLE_BUCKET, 4967 &local_port, &index, NULL)); 4968 4969 if (BCM_GPORT_IS_SET(port) && 4970 ((BCM_GPORT_IS_SCHEDULER(port)) || 4971 BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 4972 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) || 4973 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port))) { 4974 4975 BCM_IF_ERROR_RETURN 4976 (_bcm_mn_cosq_node_get(unit, port, cosq, NULL, 4977 &local_port, NULL, &node)); 4978 } 4979 4980 if (node) { 4981 if (BCM_GPORT_IS_SCHEDULER(port) || BCM_GPORT_IS_MODPORT(port)) { 4982 if (node->level == SOC_MONTEREY_NODE_LVL_ROOT) { 4983 config_mem = MMU_MTRO_L0_MEMm; 4984 } else if (node->level == SOC_MONTEREY_NODE_LVL_L0) { 4985 SOC_IF_ERROR_RETURN( 4986 READ_HSP_SCHED_PORT_CONFIGr(unit, 4987 local_port, &rval)); 4988 mc_group_mode = soc_reg_field_get(unit, HSP_SCHED_PORT_CONFIGr, 4989 rval, MC_GROUP_MODEf); 4990 if (mc_group_mode){ 4991 config_mem = MMU_MTRO_L2_MEMm; 4992 } else { 4993 config_mem = MMU_MTRO_L1_MEMm; 4994 } 4995 } else if (node->level == SOC_MONTEREY_NODE_LVL_L1) { 4996 config_mem = MMU_MTRO_L2_MEMm; 4997 } else { 4998 return BCM_E_PARAM; 4999 } 5000 } else if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 5001 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 5002 config_mem = MMU_MTRO_L2_MEMm; 5003 } else { 5004 return BCM_E_PARAM; 5005 } 5006 } else { 5007 if (IS_CPU_PORT(unit, local_port)) { 5008 config_mem = MMU_MTRO_L2_MEMm; 5009 } else { 5010 config_mem = MMU_MTRO_L1_MEMm; 5011 } 5012 } 5013 5014 if (min_quantum == NULL || max_quantum == NULL || 5015 kbits_burst_max == NULL || kbits_burst_min == NULL) { 5016 return BCM_E_PARAM; 5017 } 5018 5019 5020 BCM_IF_ERROR_RETURN 5021 (soc_mem_read(unit, config_mem, MEM_BLOCK_ALL, index, &entry)); 5022 5023 meter_flags = 0; 5024 *flags = 0; 5025 BCM_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, &rval)); 5026 if (soc_reg_field_get(unit, MISCCONFIGr, rval, ITU_MODE_SELf)) { 5027 meter_flags |= _BCM_TD_METER_FLAG_NON_LINEAR; 5028 } 5029 if (soc_mem_field32_get(unit, config_mem, &entry, SHAPER_CONTROLf)) { 5030 meter_flags |= _BCM_TD_METER_FLAG_PACKET_MODE; 5031 *flags |= BCM_COSQ_BW_PACKET_MODE; 5032 } 5033 5034 granularity = soc_mem_field32_get(unit, config_mem, &entry, MAX_METER_GRANf); 5035 refresh_rate = soc_mem_field32_get(unit, config_mem, &entry, MAX_REFRESHf); 5036 bucketsize = soc_mem_field32_get(unit, config_mem, &entry, MAX_THD_SELf); 5037 BCM_IF_ERROR_RETURN 5038 (_bcm_td_bucket_encoding_to_rate(unit, refresh_rate, bucketsize, 5039 granularity, meter_flags, 5040 max_quantum, kbits_burst_max)); 5041 5042 granularity = soc_mem_field32_get(unit, config_mem, &entry, MIN_METER_GRANf); 5043 refresh_rate = soc_mem_field32_get(unit, config_mem, &entry, MIN_REFRESHf); 5044 bucketsize = soc_mem_field32_get(unit, config_mem, &entry, MIN_THD_SELf); 5045 5046 BCM_IF_ERROR_RETURN 5047 (_bcm_td_bucket_encoding_to_rate(unit, refresh_rate, bucketsize, 5048 granularity, meter_flags, 5049 min_quantum, kbits_burst_min)); 5050 5051 if (soc_mem_field32_get(unit, config_mem, &entry, EAV_ENABLEf)) { 5052 *flags |= BCM_COSQ_BW_EAV_MODE; 5053 } 5054 return BCM_E_NONE; 5055 } 5056 5057 5058 STATIC int 5059 _bcm_mn_cosq_time_domain_mn_get(int unit, int time_id, int *time_value) 5060 { 5061 uint32 rval; 5062 5063 if (time_id < 0 || time_id > _MN_NUM_TIME_DOMAIN - 1) { 5064 return SOC_E_PARAM; 5065 } 5066 5067 if (time_value == NULL) { 5068 return SOC_E_PARAM; 5069 } 5070 5071 rval = 0; 5072 SOC_IF_ERROR_RETURN(READ_TIME_DOMAINr(unit, &rval)); 5073 *time_value = soc_reg_field_get(unit, TIME_DOMAINr, rval, 5074 time_domain_mn[time_id].field); 5075 5076 return SOC_E_NONE; 5077 } 5078 5079 5080 5081 5082 STATIC int 5083 _bcm_mn_cosq_time_domain_mn_set(int unit, int time_value, int *time_id) 5084 { 5085 uint32 rval; 5086 int rv = SOC_E_NONE; 5087 int id; 5088 5089 if (time_value < 0 || time_value > 63) { 5090 return SOC_E_PARAM; 5091 } 5092 5093 rval = 0; 5094 SOC_IF_ERROR_RETURN(READ_TIME_DOMAINr(unit, &rval)); 5095 for (id = 0; id < _MN_NUM_TIME_DOMAIN; id++) {/* Find a unset field from TIME_0 to TIME_3 */ 5096 if (!time_domain_mn[id].ref_count) { 5097 soc_reg_field_set(unit, TIME_DOMAINr, &rval, time_domain_mn[id].field, 5098 time_value); 5099 time_domain_mn[id].ref_count++; 5100 break; 5101 } 5102 } 5103 5104 if(id == _MN_NUM_TIME_DOMAIN){/* No field in TIME_DOMAINr is free,return ERR*/ 5105 rv = BCM_E_RESOURCE; 5106 } 5107 5108 if(time_id){ 5109 *time_id = id; 5110 } 5111 5112 SOC_IF_ERROR_RETURN(WRITE_TIME_DOMAINr(unit, rval)); 5113 return rv; 5114 } 5115 5116 STATIC int 5117 _bcm_mn_cosq_wred_index_resolve(int unit, bcm_port_t port, 5118 bcm_cos_queue_t cosq, uint32 flags, uint32 lflags, 5119 bcm_port_t *local_port, int *index_start, int *index_end) 5120 { 5121 int index; 5122 int to_index = -1; 5123 int start_pool_idx, end_pool_idx; 5124 bcm_port_t local_p = -1; 5125 5126 if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 5127 return BCM_E_PARAM; 5128 } 5129 5130 if((lflags & BCM_COSQ_DISCARD_DEVICE) || (flags & BCM_COSQ_DISCARD_DEVICE)) { 5131 if((port == -1) || (cosq == -1)) { 5132 index = _BCM_WRED_GLOBAL_SERVICE_POOL; 5133 to_index = index + 3; 5134 } else { 5135 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_egress_sp_get(unit, port, cosq, &start_pool_idx, 5136 &end_pool_idx)); 5137 index = to_index = _BCM_WRED_GLOBAL_SERVICE_POOL + start_pool_idx; 5138 } 5139 } else { 5140 if ((lflags & BCM_COSQ_DISCARD_PORT) || (flags & BCM_COSQ_DISCARD_PORT)) { 5141 if (port == -1) { 5142 return BCM_E_PARAM; 5143 } 5144 BCM_IF_ERROR_RETURN 5145 (_bcm_mn_cosq_index_resolve(unit, port, cosq, 5146 _BCM_MN_COSQ_INDEX_STYLE_WRED_PORT, 5147 local_port, &index, NULL)); 5148 if (cosq != -1) { 5149 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_egress_sp_get(unit, port, cosq, &start_pool_idx, 5150 &end_pool_idx)); 5151 index = to_index = index + start_pool_idx; 5152 } else { 5153 to_index = index + 3; 5154 } 5155 } else { 5156 BCM_IF_ERROR_RETURN 5157 (_bcm_mn_cosq_index_resolve(unit, port, cosq == -1 ? 0:cosq, 5158 _BCM_MN_COSQ_INDEX_STYLE_WRED, 5159 local_port, &index, NULL)); 5160 5161 if(cosq == -1) { 5162 to_index = index + NUM_COS(unit) - 1; 5163 } else { 5164 to_index = index; 5165 } 5166 } 5167 } 5168 5169 if (index < 0) { 5170 return BCM_E_PARAM; 5171 } 5172 5173 if (local_port != NULL) { 5174 *local_port = local_p; 5175 } 5176 if (index_start != NULL) { 5177 *index_start = index; 5178 } 5179 if (index_end != NULL) { 5180 *index_end = to_index; 5181 } 5182 5183 return BCM_E_NONE; 5184 } 5185 5186 /* 5187 * Function: 5188 * _bcm_mn_cosq_wred_set 5189 * Purpose: 5190 * Configure unicast queue WRED setting 5191 * Parameters: 5192 * unit - (IN) unit number 5193 * port - (IN) port number or GPORT identifier 5194 * cosq - (IN) COS queue number 5195 * flags - (IN) BCM_COSQ_DISCARD_XXX 5196 * min_thresh - (IN) 5197 * max_thresh - (IN) 5198 * drop_probablity - (IN) 5199 * gain - (IN) 5200 * ignore_enable_flags - (IN) 5201 * Returns: 5202 * BCM_E_XXX 5203 * Notes: 5204 * If port is any form of local port, cosq is the hardware queue index. 5205 */ 5206 STATIC int 5207 _bcm_mn_cosq_wred_set(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 5208 uint32 flags, uint32 min_thresh, uint32 max_thresh, 5209 int drop_probability, int gain, int ignore_enable_flags, 5210 uint32 lflags,int refresh_time) 5211 { 5212 soc_mem_t wred_mem; 5213 bcm_port_t local_port = -1; 5214 int index; 5215 uint32 profile_index, old_profile_index; 5216 mmu_wred_drop_curve_profile_0_x_pipe_entry_t profile_entry; 5217 mmu_wred_config_entry_t qentry; 5218 void *entries[1]; 5219 soc_field_t fields[6][3]; 5220 int rate, i, jj, to_index = -1, exists = 0; 5221 int time_id,time,old_time,current_time_sel; 5222 int rv = SOC_E_NONE; 5223 uint32 rval; 5224 static soc_field_t wred_fields[6][3] = { 5225 {MIN_THD0f, MAX_THD0f, MAX_DROP_RATE0f}, 5226 {MIN_THD1f, MAX_THD1f, MAX_DROP_RATE1f}, 5227 {MIN_THD2f, MAX_THD2f, MAX_DROP_RATE2f}, 5228 {MIN_THD3f, MAX_THD3f, MAX_DROP_RATE3f}, 5229 {MIN_THD4f, MAX_THD4f, MAX_DROP_RATE4f}, 5230 {MIN_THD5f, MAX_THD5f, MAX_DROP_RATE5f} 5231 }; 5232 5233 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_wred_index_resolve(unit, port, cosq, 5234 flags, lflags, &local_port, &index, &to_index)); 5235 5236 for(jj = index; jj <= to_index; jj++) { 5237 wred_mem = MMU_WRED_CONFIG_X_PIPEm; 5238 5239 BCM_IF_ERROR_RETURN 5240 (soc_mem_read(unit, wred_mem, MEM_BLOCK_ALL, jj, &qentry)); 5241 5242 old_profile_index = 0xffffffff; 5243 if (flags & (BCM_COSQ_DISCARD_NONTCP | BCM_COSQ_DISCARD_COLOR_ALL | 5244 BCM_COSQ_DISCARD_TCP)) { 5245 old_profile_index = soc_mem_field32_get(unit, wred_mem, 5246 &qentry, PROFILE_INDEXf); 5247 entries[0] = &profile_entry; 5248 BCM_IF_ERROR_RETURN 5249 (soc_profile_mem_get(unit, _bcm_mn_wred_profile[unit], 5250 old_profile_index, 1, entries)); 5251 for (i = 0; i < 6; i++) { 5252 fields[i][0] = INVALIDf; 5253 fields[i][1] = INVALIDf; 5254 fields[i][2] = INVALIDf; 5255 } 5256 if (!(flags & (BCM_COSQ_DISCARD_COLOR_GREEN | 5257 BCM_COSQ_DISCARD_COLOR_YELLOW | 5258 BCM_COSQ_DISCARD_COLOR_RED))) { 5259 flags |= BCM_COSQ_DISCARD_COLOR_ALL; 5260 } 5261 if (!(flags & BCM_COSQ_DISCARD_NONTCP) || (flags & BCM_COSQ_DISCARD_TCP)) { 5262 if (flags & BCM_COSQ_DISCARD_COLOR_GREEN) { 5263 fields[0][0] = wred_fields[0][0]; 5264 fields[0][1] = wred_fields[0][1]; 5265 fields[0][2] = wred_fields[0][2]; 5266 } 5267 if (flags & BCM_COSQ_DISCARD_COLOR_YELLOW) { 5268 fields[1][0] = wred_fields[1][0]; 5269 fields[1][1] = wred_fields[1][1]; 5270 fields[1][2] = wred_fields[1][2]; 5271 } 5272 if (flags & BCM_COSQ_DISCARD_COLOR_RED) { 5273 fields[2][0] = wred_fields[2][0]; 5274 fields[2][1] = wred_fields[2][1]; 5275 fields[2][2] = wred_fields[2][2]; 5276 } 5277 } 5278 if (flags & BCM_COSQ_DISCARD_NONTCP) { 5279 if (flags & BCM_COSQ_DISCARD_COLOR_GREEN) { 5280 fields[3][0] = wred_fields[3][0]; 5281 fields[3][1] = wred_fields[3][1]; 5282 fields[3][2] = wred_fields[3][2]; 5283 } 5284 if (flags & BCM_COSQ_DISCARD_COLOR_YELLOW) { 5285 fields[4][0] = wred_fields[4][0]; 5286 fields[4][1] = wred_fields[4][1]; 5287 fields[4][2] = wred_fields[4][2]; 5288 } 5289 if (flags & BCM_COSQ_DISCARD_COLOR_RED) { 5290 fields[5][0] = wred_fields[5][0]; 5291 fields[5][1] = wred_fields[5][1]; 5292 fields[5][2] = wred_fields[5][2]; 5293 } 5294 } 5295 rate = _bcm_mn_percent_to_drop_prob(drop_probability); 5296 for (i = 0; i < 6; i++) { 5297 exists = 0; 5298 if ((soc_mem_field32_get(unit, MMU_WRED_DROP_CURVE_PROFILE_0_X_PIPEm, entries[0], 5299 wred_fields[i][0]) != 0x1ffff) && (fields[i][0] == INVALIDf)) { 5300 fields[i][0] = wred_fields[i][0]; 5301 exists = 1; 5302 } else { 5303 soc_mem_field32_set(unit, MMU_WRED_DROP_CURVE_PROFILE_0_X_PIPEm, entries[0], 5304 wred_fields[i][0], (fields[i][0] == INVALIDf) ? 0x1ffff : min_thresh); 5305 } 5306 if ((soc_mem_field32_get(unit, MMU_WRED_DROP_CURVE_PROFILE_0_X_PIPEm, entries[0], 5307 wred_fields[i][1]) != 0x1ffff) && (fields[i][1] == INVALIDf)) { 5308 fields[i][1] = wred_fields[i][1]; 5309 exists = 1; 5310 } else { 5311 soc_mem_field32_set(unit, MMU_WRED_DROP_CURVE_PROFILE_0_X_PIPEm, entries[0], 5312 wred_fields[i][1], (fields[i][1] == INVALIDf) ? 0x1ffff : max_thresh); 5313 } 5314 5315 if (!exists) { 5316 soc_mem_field32_set(unit, MMU_WRED_DROP_CURVE_PROFILE_0_X_PIPEm, entries[0], 5317 wred_fields[i][2], (fields[i][2] == INVALIDf) ? 0 : rate); 5318 } 5319 } 5320 BCM_IF_ERROR_RETURN 5321 (soc_profile_mem_add(unit, _bcm_mn_wred_profile[unit], 5322 entries, 1, &profile_index)); 5323 soc_mem_field32_set(unit, wred_mem, &qentry, PROFILE_INDEXf, profile_index); 5324 soc_mem_field32_set(unit, wred_mem, &qentry, WEIGHTf, gain); 5325 } 5326 5327 /* Some APIs only modify profiles */ 5328 if (!ignore_enable_flags) { 5329 soc_mem_field32_set(unit, wred_mem, &qentry, CAP_AVERAGEf, 5330 flags & BCM_COSQ_DISCARD_CAP_AVERAGE ? 1 : 0); 5331 soc_mem_field32_set(unit, wred_mem, &qentry, WRED_ENf, 5332 flags & BCM_COSQ_DISCARD_ENABLE ? 1 : 0); 5333 soc_mem_field32_set(unit, wred_mem, &qentry, ECN_MARKING_ENf, 5334 flags & BCM_COSQ_DISCARD_MARK_CONGESTION ? 1 : 0); 5335 } 5336 5337 current_time_sel = soc_mem_field32_get(unit, wred_mem, &qentry, TIME_DOMAIN_SELf); 5338 time = (refresh_time + 7) / 8 - 1; /* Round it up to avoid negative value */ 5339 exists = 0; 5340 /* If the time value exist, update reference count only */ 5341 for (time_id = 0; time_id < _MN_NUM_TIME_DOMAIN; time_id++) { 5342 BCM_IF_ERROR_RETURN 5343 (_bcm_mn_cosq_time_domain_mn_get(unit, time_id, &old_time)); 5344 if (time == old_time) { 5345 /* Only set exist flag if this entry reference count already update, 5346 otherwise update reference count */ 5347 if(time_id != current_time_sel){ 5348 soc_mem_field32_set(unit, wred_mem, &qentry, TIME_DOMAIN_SELf, 5349 time_id); 5350 time_domain_mn[time_id].ref_count++; 5351 time_domain_mn[current_time_sel].ref_count--; 5352 } 5353 exists = 1; 5354 break; 5355 } 5356 } 5357 5358 if(!exists){ 5359 rv = _bcm_mn_cosq_time_domain_mn_set(unit, time, &time_id); 5360 if(rv == SOC_E_NONE){ 5361 soc_mem_field32_set(unit, wred_mem, &qentry, TIME_DOMAIN_SELf, 5362 time_id); 5363 time_domain_mn[current_time_sel].ref_count--; 5364 } 5365 } 5366 /* 5367 *Disabling the wred sampling and writing to wred mem 5368 *This was required for an hardware bug and can be taken out for apache b0 5369 */ 5370 BCM_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, &rval)); 5371 soc_reg_field_set(unit, MISCCONFIGr, &rval, REFRESH_ENf, 0); 5372 BCM_IF_ERROR_RETURN(WRITE_MISCCONFIGr(unit, rval)); 5373 5374 BCM_IF_ERROR_RETURN( 5375 soc_mem_write(unit, wred_mem, MEM_BLOCK_ALL, jj, &qentry)); 5376 5377 BCM_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, &rval)); 5378 soc_reg_field_set(unit, MISCCONFIGr, &rval, REFRESH_ENf, 1); 5379 BCM_IF_ERROR_RETURN(WRITE_MISCCONFIGr(unit, rval)); 5380 if (old_profile_index != 0xffffffff) { 5381 SOC_IF_ERROR_RETURN 5382 (soc_profile_mem_delete(unit, _bcm_mn_wred_profile[unit], 5383 old_profile_index)); 5384 } 5385 } 5386 5387 return rv; 5388 } 5389 5390 /* 5391 * Function: 5392 * _bcm_mn_cosq_wred_get 5393 * Purpose: 5394 * Get unicast queue WRED setting 5395 * Parameters: 5396 * unit - (IN) unit number 5397 * port - (IN) port number or GPORT identifier 5398 * cosq - (IN) COS queue number 5399 * flags - (IN/OUT) BCM_COSQ_DISCARD_XXX 5400 * min_thresh - (OUT) 5401 * max_thresh - (OUT) 5402 * drop_probablity - (OUT) 5403 * gain - (OUT) 5404 * Returns: 5405 * BCM_E_XXX 5406 * Notes: 5407 * If port is any form of local port, cosq is the hardware queue index. 5408 */ 5409 STATIC int 5410 _bcm_mn_cosq_wred_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 5411 uint32 *flags, uint32 *min_thresh, uint32 *max_thresh, 5412 int *drop_probability, int *gain, uint32 lflags,int *refresh_time) 5413 { 5414 bcm_port_t local_port = -1; 5415 int index, profile_index; 5416 mmu_wred_drop_curve_profile_0_x_pipe_entry_t profile_entry; 5417 void *entries[1]; 5418 void *entry_p; 5419 soc_mem_t wred_mem = 0; 5420 soc_field_t fields[3]; 5421 static soc_field_t wred_fields[6][3] = { 5422 {MIN_THD0f, MAX_THD0f, MAX_DROP_RATE0f}, 5423 {MIN_THD1f, MAX_THD1f, MAX_DROP_RATE1f}, 5424 {MIN_THD2f, MAX_THD2f, MAX_DROP_RATE2f}, 5425 {MIN_THD3f, MAX_THD3f, MAX_DROP_RATE3f}, 5426 {MIN_THD4f, MAX_THD4f, MAX_DROP_RATE4f}, 5427 {MIN_THD5f, MAX_THD5f, MAX_DROP_RATE5f} 5428 }; 5429 mmu_wred_config_entry_t qentry; 5430 int rate, time_id,time; 5431 5432 if ((port == -1 ) && 5433 !((*flags & BCM_COSQ_DISCARD_DEVICE) || (lflags & BCM_COSQ_DISCARD_DEVICE))) { 5434 return (BCM_E_PORT); 5435 } 5436 5437 local_port = -1; 5438 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_wred_index_resolve(unit, port, cosq, 5439 *flags, lflags, &local_port, &index, NULL)); 5440 5441 wred_mem = MMU_WRED_CONFIG_X_PIPEm; 5442 5443 BCM_IF_ERROR_RETURN 5444 (soc_mem_read(unit, wred_mem, MEM_BLOCK_ALL, index, &qentry)); 5445 profile_index = soc_mem_field32_get(unit, wred_mem, 5446 &qentry, PROFILE_INDEXf); 5447 5448 if (!(*flags & BCM_COSQ_DISCARD_NONTCP)) { 5449 if (*flags & BCM_COSQ_DISCARD_COLOR_GREEN) { 5450 fields[0] = wred_fields[0][0]; 5451 fields[1] = wred_fields[0][1]; 5452 fields[2] = wred_fields[0][2]; 5453 entry_p = &profile_entry; 5454 } else if (*flags & BCM_COSQ_DISCARD_COLOR_YELLOW) { 5455 fields[0] = wred_fields[1][0]; 5456 fields[1] = wred_fields[1][1]; 5457 fields[2] = wred_fields[1][2]; 5458 entry_p = &profile_entry; 5459 } else if (*flags & BCM_COSQ_DISCARD_COLOR_RED) { 5460 fields[0] = wred_fields[2][0]; 5461 fields[1] = wred_fields[2][1]; 5462 fields[2] = wred_fields[2][2]; 5463 entry_p = &profile_entry; 5464 } else { 5465 fields[0] = wred_fields[0][0]; 5466 fields[1] = wred_fields[0][1]; 5467 fields[2] = wred_fields[0][2]; 5468 entry_p = &profile_entry; 5469 } 5470 } else { 5471 if (*flags & BCM_COSQ_DISCARD_COLOR_GREEN) { 5472 fields[0] = wred_fields[3][0]; 5473 fields[1] = wred_fields[3][1]; 5474 fields[2] = wred_fields[3][2]; 5475 entry_p = &profile_entry; 5476 } else if (*flags & BCM_COSQ_DISCARD_COLOR_YELLOW) { 5477 fields[0] = wred_fields[4][0]; 5478 fields[1] = wred_fields[4][1]; 5479 fields[2] = wred_fields[4][2]; 5480 entry_p = &profile_entry; 5481 } else if (*flags & BCM_COSQ_DISCARD_COLOR_RED) { 5482 fields[0] = wred_fields[5][0]; 5483 fields[1] = wred_fields[5][1]; 5484 fields[2] = wred_fields[5][2]; 5485 entry_p = &profile_entry; 5486 } else { 5487 fields[0] = wred_fields[3][0]; 5488 fields[1] = wred_fields[3][1]; 5489 fields[2] = wred_fields[3][2]; 5490 entry_p = &profile_entry; 5491 } 5492 } 5493 5494 entries[0] = &profile_entry; 5495 BCM_IF_ERROR_RETURN 5496 (soc_profile_mem_get(unit, _bcm_mn_wred_profile[unit], 5497 profile_index, 1, entries)); 5498 if (min_thresh != NULL) { 5499 *min_thresh = soc_mem_field32_get(unit, MMU_WRED_DROP_CURVE_PROFILE_0_X_PIPEm, entry_p, fields[0]); 5500 } 5501 if (max_thresh != NULL) { 5502 *max_thresh = soc_mem_field32_get(unit, MMU_WRED_DROP_CURVE_PROFILE_0_X_PIPEm, entry_p, fields[1]); 5503 } 5504 if (drop_probability != NULL) { 5505 rate = soc_mem_field32_get(unit, MMU_WRED_DROP_CURVE_PROFILE_0_X_PIPEm, entry_p, fields[2]); 5506 *drop_probability = _bcm_mn_drop_prob_to_percent(rate); 5507 } 5508 5509 if (gain) { 5510 *gain = soc_mem_field32_get(unit, wred_mem, &qentry, WEIGHTf); 5511 } 5512 5513 if (refresh_time) { 5514 time_id = soc_mem_field32_get(unit, wred_mem, &qentry, TIME_DOMAIN_SELf); 5515 BCM_IF_ERROR_RETURN 5516 (_bcm_mn_cosq_time_domain_mn_get(unit,time_id,&time)); 5517 *refresh_time = (time + 1) * 8; 5518 } 5519 5520 *flags &= ~(BCM_COSQ_DISCARD_CAP_AVERAGE | BCM_COSQ_DISCARD_ENABLE); 5521 if (soc_mem_field32_get(unit, wred_mem, &qentry, CAP_AVERAGEf)) { 5522 *flags |= BCM_COSQ_DISCARD_CAP_AVERAGE; 5523 } 5524 if (soc_mem_field32_get(unit, wred_mem, &qentry, WRED_ENf)) { 5525 *flags |= BCM_COSQ_DISCARD_ENABLE; 5526 } 5527 if (soc_mem_field32_get(unit, wred_mem, &qentry, ECN_MARKING_ENf)) { 5528 *flags |= BCM_COSQ_DISCARD_MARK_CONGESTION; 5529 } 5530 return BCM_E_NONE; 5531 } 5532 5533 /* 5534 * Function: 5535 * _bcm_mn_cosq_sched_get 5536 * Purpose: 5537 * Get scheduling mode setting 5538 * Parameters: 5539 * unit - (IN) unit number 5540 * port - (IN) port number or GPORT identifier 5541 * cosq - (IN) COS queue number 5542 * mode - (OUT) scheduling mode (BCM_COSQ_XXX) 5543 * num_weights - (IN) number of entries in weights array 5544 * weights - (OUT) weights array 5545 * Returns: 5546 * BCM_E_XXX 5547 */ 5548 STATIC int 5549 _bcm_mn_cosq_sched_get(int unit, bcm_port_t gport, bcm_cos_queue_t cosq, 5550 int *mode, int *weight) 5551 { 5552 _bcm_mn_cosq_node_t *node, *child_node , *s1_node; 5553 bcm_port_t local_port; 5554 int sch_index, lvl = SOC_MONTEREY_NODE_LVL_L1; 5555 soc_monterey_sched_mode_e sched_mode; 5556 int index, numq; 5557 _bcm_mn_mmu_info_t *mmu_info; 5558 soc_info_t *si; 5559 5560 if ((mmu_info = _bcm_mn_mmu_info[unit]) == NULL) { 5561 return BCM_E_INIT; 5562 } 5563 5564 if (cosq < 0) { 5565 if (cosq == -1) { 5566 /* caller needs to resolve the wild card value (-1) */ 5567 return BCM_E_INTERNAL; 5568 } else { /* reject all other negative value */ 5569 return BCM_E_PARAM; 5570 } 5571 } 5572 5573 if(_BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, gport)){ 5574 BCM_IF_ERROR_RETURN( 5575 _bcmi_coe_subport_physical_port_get(unit, gport, &local_port)); 5576 } else { 5577 BCM_IF_ERROR_RETURN 5578 (_bcm_mn_cosq_localport_resolve(unit, gport, &local_port)); 5579 } 5580 si = &SOC_INFO(unit); 5581 if (BCM_GPORT_IS_SCHEDULER(gport)) { /* ETS style scheduler */ 5582 BCM_IF_ERROR_RETURN 5583 (_bcm_mn_cosq_node_get(unit, gport, 0, NULL, &local_port, NULL, 5584 &node)); 5585 if ((node->numq >= 0) && (cosq > node->numq)) { 5586 return BCM_E_PARAM; 5587 } 5588 BCM_IF_ERROR_RETURN 5589 (_bcm_mn_cosq_child_node_at_input(node, cosq, &child_node)); 5590 } else if (_BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT 5591 (unit, gport)) { 5592 if (soc_feature(unit, 5593 soc_feature_mmu_hqos_four_level)) { 5594 BCM_IF_ERROR_RETURN 5595 (_bcm_mn_get_s1_node(unit, gport, 5596 &s1_node)); 5597 index = s1_node->coe_base_index; 5598 child_node = &mmu_info->queue_node[index + cosq ]; 5599 if (!child_node) { 5600 return BCM_E_INTERNAL; 5601 } 5602 if (child_node->attached_to_input == -1) { 5603 return BCM_E_NOT_FOUND; 5604 } 5605 node = child_node->parent ; 5606 if (!node) { 5607 return BCM_E_INTERNAL; 5608 } 5609 5610 } else { 5611 return BCM_E_PARAM; 5612 } 5613 } else { 5614 if (IS_CPU_PORT(unit, local_port)) { 5615 numq = SOC_INFO(unit).num_cpu_cosq; 5616 if (cosq >= numq) { 5617 return BCM_E_PARAM; 5618 } 5619 index = soc_monterey_l2_hw_index(unit, 5620 si->port_cosq_base[local_port] + cosq, 0); 5621 } else { 5622 index = soc_monterey_l2_hw_index(unit, 5623 si->port_uc_cosq_base[local_port] + cosq, 1); 5624 } 5625 child_node = &mmu_info->queue_node[index]; 5626 if (!child_node) { 5627 return BCM_E_INTERNAL; 5628 } 5629 if (child_node->attached_to_input == -1) { 5630 return BCM_E_NOT_FOUND; 5631 } 5632 node = child_node->parent; 5633 if (node && !IS_CPU_PORT(unit, local_port)) { 5634 child_node = node; 5635 node = node->parent; 5636 if (!node) { 5637 return BCM_E_INTERNAL; 5638 } 5639 if ((node->numq >= 0) && ((cosq % _BCM_MN_HSP_PORT_MAX_COS) > node->numq)) { 5640 return BCM_E_PARAM; 5641 } 5642 BCM_IF_ERROR_RETURN 5643 (_bcm_mn_cosq_child_node_at_input(node, cosq, 5644 &child_node)); 5645 } 5646 } 5647 5648 if (!child_node) { 5649 return BCM_E_INTERNAL; 5650 } 5651 5652 sch_index = child_node->hw_index; 5653 lvl = child_node->level; 5654 5655 BCM_IF_ERROR_RETURN( 5656 soc_monterey_cosq_get_sched_mode(unit, local_port, lvl, sch_index, 5657 &sched_mode, weight)); 5658 5659 switch(sched_mode) { 5660 case SOC_MONTEREY_SCHED_MODE_STRICT: 5661 *mode = BCM_COSQ_STRICT; 5662 break; 5663 case SOC_MONTEREY_SCHED_MODE_WRR: 5664 *mode = BCM_COSQ_WEIGHTED_ROUND_ROBIN; 5665 break; 5666 case SOC_MONTEREY_SCHED_MODE_WDRR: 5667 *mode = BCM_COSQ_DEFICIT_ROUND_ROBIN; 5668 break; 5669 default: 5670 return BCM_E_INTERNAL; 5671 break; 5672 } 5673 return BCM_E_NONE; 5674 } 5675 5676 /* 5677 * Function: 5678 * _bcm_mn_lls_node_count 5679 * Purpose: 5680 * This function counts the number of nodes at a particular level 5681 * Parameters: 5682 * unit - (IN) unit number 5683 * port - (IN) local port number 5684 * level - (IN) level of the node in LLS 5685 * hw_index - (IN) h/w index of the node 5686 * cookie - (IN) state of the LLS structure 5687 */ 5688 STATIC int _bcm_mn_lls_node_count(int unit, int port, int level, 5689 int hw_index, void *cookie) 5690 { 5691 _bcm_mn_lls_info_t *i_lls_tree = (_bcm_mn_lls_info_t *) cookie; 5692 i_lls_tree->node_count[level] += 1; 5693 return 0; 5694 } 5695 5696 /* 5697 * Function: 5698 * _bcm_mn_num_ones 5699 * Purpose: 5700 * This function calculates the numbers of 1s in the binary format 5701 * of the number 5702 * Parameters: 5703 * m - (IN) number 5704 * Returns: 5705 * The number of 1s in the binary format of the number 5706 */ 5707 STATIC uint32 5708 _bcm_mn_num_ones(uint32 m) 5709 { 5710 uint32 i = 0; 5711 5712 while (m) { 5713 m &= m - 1; 5714 i += 1; 5715 } 5716 return i; 5717 } 5718 5719 STATIC int 5720 _bcm_mn_cosq_traverse_lls_tree(int unit, int port, _bcm_mn_cosq_node_t *node, 5721 _soc_monterey_lls_traverse_cb cb, void *cookie) 5722 { 5723 if (node->child) { 5724 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_traverse_lls_tree(unit, port, 5725 node->child, 5726 cb, cookie)); 5727 } 5728 5729 if (node->sibling) { 5730 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_traverse_lls_tree(unit, port, 5731 node->sibling, cb, cookie)); 5732 } 5733 5734 if (node->level != SOC_MONTEREY_NODE_LVL_ROOT) { 5735 BCM_IF_ERROR_RETURN(cb(unit, port, node->level, node->hw_index, cookie)); 5736 } 5737 5738 return BCM_E_NONE; 5739 } 5740 5741 /* 5742 * Function: 5743 * _bcm_mn_lls_shapers_remove 5744 * Purpose: 5745 * This function removes shapers on the nodes by setting them 5746 * to the max rate and setting min to 0 so that each node can only schedule upto 5747 * the max rate. It also calculates the leaky bucket parameters based on 5748 * the kbit max 5749 * Parameters: 5750 * unit - (IN) unit number 5751 * port - (IN) local port number 5752 * level - (IN) level of the node in LLS 5753 * hw_index - (IN) h/w index of the node 5754 * cookie - (IN) state of the LLS structure 5755 */ 5756 STATIC int _bcm_mn_lls_shapers_remove(int unit, int port, int level, 5757 int hw_index, void *cookie) 5758 { 5759 _bcm_mn_lls_info_t *i_lls_tree = (_bcm_mn_lls_info_t *) cookie; 5760 soc_mem_t config_mem; 5761 uint32 *p_entry; 5762 uint32 entry[SOC_MAX_MEM_WORDS]; 5763 int index, kbit_max, kbit_min; 5764 uint32 meter_flags; 5765 uint32 bucketsize_max, granularity_max, refresh_rate_max, 5766 refresh_bitsize = 0, bucket_bitsize = 0; 5767 5768 5769 if (level == SOC_MONTEREY_NODE_LVL_MAX) { 5770 return SOC_E_PARAM; 5771 } 5772 5773 if (i_lls_tree->child_lvl != level) { 5774 return BCM_E_NONE; 5775 } 5776 5777 if (level == SOC_MONTEREY_NODE_LVL_L0) { 5778 config_mem = MMU_MTRO_L0_MEMm; 5779 } else if (level == SOC_MONTEREY_NODE_LVL_L1) { 5780 config_mem = MMU_MTRO_L1_MEMm; 5781 } else if (level == SOC_MONTEREY_NODE_LVL_L2) { 5782 config_mem = MMU_MTRO_L2_MEMm; 5783 } else { 5784 return BCM_E_PARAM; 5785 } 5786 5787 5788 index = i_lls_tree->offset[level] + i_lls_tree->count[level]; 5789 p_entry = &i_lls_tree->mtro_entries[index * SOC_MAX_MEM_WORDS]; 5790 5791 if (*p_entry == 0) { 5792 SOC_IF_ERROR_RETURN(soc_mem_read(unit, config_mem, MEM_BLOCK_ALL, hw_index, 5793 p_entry)); 5794 } 5795 5796 sal_memset(entry, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS); 5797 5798 5799 meter_flags = 0; 5800 5801 refresh_bitsize = soc_mem_field_length(unit, config_mem, MAX_REFRESHf); 5802 bucket_bitsize = soc_mem_field_length(unit, config_mem, MAX_THD_SELf); 5803 5804 /* Setting the max metering configuration */ 5805 kbit_max = i_lls_tree->kbit_max; 5806 BCM_IF_ERROR_RETURN 5807 (_bcm_td_rate_to_bucket_encoding(unit, kbit_max, kbit_max, 5808 meter_flags, refresh_bitsize, 5809 bucket_bitsize, &refresh_rate_max, 5810 &bucketsize_max, &granularity_max)); 5811 5812 soc_mem_field32_set(unit, config_mem, entry, MAX_METER_GRANf, 5813 granularity_max); 5814 soc_mem_field32_set(unit, config_mem, entry, MAX_REFRESHf, 5815 refresh_rate_max); 5816 soc_mem_field32_set(unit, config_mem, entry, MAX_THD_SELf, 5817 bucketsize_max); 5818 5819 5820 /* Setting the min metering configuration */ 5821 kbit_min = i_lls_tree->kbit_min; 5822 BCM_IF_ERROR_RETURN 5823 (_bcm_td_rate_to_bucket_encoding(unit, kbit_min, kbit_min, 5824 meter_flags, refresh_bitsize, 5825 bucket_bitsize, &refresh_rate_max, 5826 &bucketsize_max, &granularity_max)); 5827 5828 soc_mem_field32_set(unit, config_mem, entry, MIN_METER_GRANf, 5829 granularity_max); 5830 soc_mem_field32_set(unit, config_mem, entry, MIN_REFRESHf, 5831 refresh_rate_max); 5832 soc_mem_field32_set(unit, config_mem, entry, MIN_THD_SELf, 5833 bucketsize_max); 5834 5835 BCM_IF_ERROR_RETURN 5836 (soc_mem_write(unit, config_mem, MEM_BLOCK_ALL, hw_index, entry)); 5837 5838 sal_usleep(100); 5839 i_lls_tree->count[level] += 1; 5840 return 0; 5841 } 5842 5843 /* 5844 * Function: 5845 * _bcm_mn_lls_shapers_restore 5846 * Purpose: 5847 * This function restores the shapers on the nodes 5848 * Parameters: 5849 * unit - (IN) unit number 5850 * port - (IN) local port number 5851 * level - (IN) level of the node in LLS 5852 * hw_index - (IN) h/w index of the node 5853 * cookie - (IN) state of the LLS structure 5854 */ 5855 STATIC int _bcm_mn_lls_shapers_restore(int unit, int port, int level, 5856 int hw_index, void *cookie) 5857 { 5858 _bcm_mn_lls_info_t *i_lls_tree = (_bcm_mn_lls_info_t *) cookie; 5859 soc_mem_t config_mem; 5860 uint32 *p_entry; 5861 int index; 5862 uint32 entry[SOC_MAX_MEM_WORDS]; 5863 5864 if (level == SOC_MONTEREY_NODE_LVL_MAX) { 5865 return SOC_E_PARAM; 5866 } 5867 5868 if (level == SOC_MONTEREY_NODE_LVL_L0) { 5869 config_mem = MMU_MTRO_L0_MEMm; 5870 } else if (level == SOC_MONTEREY_NODE_LVL_L1) { 5871 config_mem = MMU_MTRO_L1_MEMm; 5872 } else if (level == SOC_MONTEREY_NODE_LVL_L2) { 5873 config_mem = MMU_MTRO_L0_MEMm; 5874 } else { 5875 return BCM_E_PARAM; 5876 } 5877 5878 if (i_lls_tree->child_lvl != level) { 5879 return BCM_E_NONE; 5880 } 5881 5882 5883 5884 sal_memset(entry, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS); 5885 5886 soc_mem_field32_set(unit, config_mem, entry, MIN_REFRESHf, 5887 500); 5888 soc_mem_field32_set(unit, config_mem, entry, MIN_THD_SELf, 5889 3); 5890 5891 SOC_IF_ERROR_RETURN 5892 (soc_mem_write(unit, config_mem, MEM_BLOCK_ALL, hw_index, entry)); 5893 5894 sal_usleep(100); 5895 5896 index = i_lls_tree->offset[level] + i_lls_tree->count[level]; 5897 p_entry = &i_lls_tree->mtro_entries[index * SOC_MAX_MEM_WORDS]; 5898 5899 SOC_IF_ERROR_RETURN(soc_mem_write(unit, config_mem, MEM_BLOCK_ALL, 5900 hw_index, p_entry)); 5901 5902 i_lls_tree->count[level] += 1; 5903 5904 return 0; 5905 } 5906 5907 /* 5908 * Function: 5909 * _bcm_mn_adjust_lls_bw 5910 * Purpose: 5911 * This function adjusts the bandwidth at the level in which the node is 5912 * being switched so that each node gets sufficient bandwidth to do the 5913 * switchover. 5914 * Parameters: 5915 * unit - (IN) unit number 5916 * port - (IN) local port number 5917 * node - (IN) cosq node structure 5918 * child_lvl - (IN) level of the child node 5919 * child_hw_index - (IN) h/w index of the child node 5920 * start - (IN) flag 5921 * i_lls_tree - (OUT) LLS info 5922 * Returns: 5923 * BCM_E_XXX 5924 */ 5925 STATIC int 5926 _bcm_mn_adjust_lls_bw(int unit, bcm_port_t port, _bcm_mn_cosq_node_t *node, 5927 int child_lvl, int child_hw_index, int start, 5928 _bcm_mn_lls_info_t *i_lls_tree) 5929 { 5930 int rv = BCM_E_NONE, count, mem_size, ii, speed, jj; 5931 soc_info_t *si; 5932 if (!soc_feature(unit, soc_feature_vector_based_spri)) { 5933 return BCM_E_NONE; 5934 } 5935 5936 if (IS_LB_PORT(unit, port)) { 5937 return BCM_E_NONE; 5938 } 5939 if (start) { 5940 sal_memset(i_lls_tree, 0, sizeof(_bcm_mn_lls_info_t)); 5941 i_lls_tree->child_lvl = child_lvl; 5942 i_lls_tree->child_hw_index = child_hw_index; 5943 5944 if (node) { 5945 /* get to top node */ 5946 while(node->parent) { node = node->parent; } 5947 5948 if ((rv = _bcm_mn_cosq_traverse_lls_tree(unit, port, node, 5949 _bcm_mn_lls_node_count, i_lls_tree))) { 5950 goto cleanup; 5951 } 5952 } 5953 5954 for (count = 0, ii = 0; ii < SOC_MONTEREY_NODE_LVL_MAX; ii++) { 5955 count += i_lls_tree->node_count[ii]; 5956 for (jj = ii - 1; jj >= 0; jj--) { 5957 i_lls_tree->offset[ii] += i_lls_tree->node_count[jj]; 5958 } 5959 } 5960 5961 if (count == 0) { 5962 return BCM_E_INIT; 5963 } 5964 5965 mem_size = sizeof(uint32) * SOC_MAX_MEM_WORDS * count; 5966 i_lls_tree->mtro_entries = sal_alloc(mem_size, "lls_war_buf"); 5967 5968 rv = bcm_esw_port_speed_get(unit, port, &speed); 5969 if ((rv == BCM_E_UNAVAIL) || (speed == 0)) { 5970 si = &SOC_INFO(unit); 5971 speed = si->port_speed_max[port]; 5972 } 5973 5974 i_lls_tree->kbit_min = 0; 5975 i_lls_tree->kbit_max = ((speed)/10)/i_lls_tree->node_count[child_lvl]; 5976 5977 for (count = 0, ii = 0; ii < SOC_MONTEREY_NODE_LVL_MAX; ii++) { 5978 i_lls_tree->count[ii] = 0; 5979 } 5980 5981 sal_memset(i_lls_tree->mtro_entries, 0, mem_size); 5982 5983 if (node) { 5984 5985 /* get to top node */ 5986 while(node->parent) { node = node->parent; } 5987 5988 if ((rv = _bcm_mn_cosq_traverse_lls_tree(unit, port, node, 5989 _bcm_mn_lls_shapers_remove, i_lls_tree))) { 5990 5991 goto cleanup; 5992 } 5993 } 5994 } else { 5995 for (count = 0, ii = 0; ii < SOC_MONTEREY_NODE_LVL_MAX; ii++) { 5996 i_lls_tree->count[ii] = 0; 5997 } 5998 5999 if (node) { 6000 /* get to top node */ 6001 while(node->parent) { node = node->parent; } 6002 6003 if ((rv = _bcm_mn_cosq_traverse_lls_tree(unit, port, node, 6004 _bcm_mn_lls_shapers_restore, i_lls_tree))) { 6005 goto cleanup; 6006 } 6007 } 6008 6009 if (i_lls_tree->mtro_entries) { 6010 sal_free(i_lls_tree->mtro_entries); 6011 i_lls_tree->mtro_entries = NULL; 6012 } 6013 6014 } 6015 6016 return rv; 6017 6018 cleanup: 6019 /* cleanup */ 6020 if (i_lls_tree->mtro_entries) { 6021 sal_free(i_lls_tree->mtro_entries); 6022 i_lls_tree->mtro_entries = NULL; 6023 } 6024 6025 return rv; 6026 } 6027 6028 /* 6029 * Function: 6030 * _bcm_monterey_compute_lls_config 6031 * Purpose: 6032 * This function computes the LLS configuration at each level 6033 * Parameters: 6034 * unit - (IN) unit number 6035 * port - (IN) local port number 6036 * level - (IN) level of the node in LLS 6037 * first_sp_child - (OUT) first sp child 6038 * first_sp_mc_child - (OUT) first so multicast child 6039 * ucmap - (OUT) unicast node map 6040 * spmap - (OUT) SPRI node map 6041 * child_index - (IN) index of the child node 6042 * cur_mode - (IN) current schedling mode of the node 6043 * mode - (IN) new scheduling mode of the node 6044 * max_children - (IN) maximum number of children in the level 6045 * Returns: 6046 * BCM_E_XXX 6047 */ 6048 STATIC int 6049 _bcm_monterey_compute_lls_config (int unit, int port, int level, 6050 int *first_sp_child, 6051 int *first_sp_mc_child, 6052 int *num_spri, 6053 uint32 *ucmap, 6054 uint32 *spmap, 6055 int child_index, 6056 soc_monterey_sched_mode_e cur_mode, 6057 soc_monterey_sched_mode_e mode, 6058 int max_children) 6059 { 6060 uint32 ucm = 0, mcm = 0, cur_spmap, cur_num_spri, lucmap = 0; 6061 int ii, *pfc, uc, mc, fc, oc, *use_fc; 6062 6063 cur_num_spri = _bcm_mn_num_ones(*spmap); 6064 cur_spmap = *spmap; 6065 6066 if (level == SOC_MONTEREY_NODE_LVL_L1) { 6067 if (IS_CPU_PORT(unit, port)) { 6068 use_fc = first_sp_mc_child; 6069 } else { 6070 use_fc = (child_index >= _BCM_MN_NUM_L2_UC_LEAVES_PER_PIPE) ? 6071 first_sp_mc_child : first_sp_child; 6072 } 6073 } else { 6074 use_fc = first_sp_child; 6075 } 6076 6077 if (cur_num_spri == 0) { 6078 *ucmap = 0; 6079 *spmap = 0; 6080 } 6081 6082 if (mode == SOC_MONTEREY_SCHED_MODE_STRICT) { 6083 if (child_index > *use_fc) { 6084 if ((child_index - *use_fc) >= max_children && cur_num_spri > 0) { 6085 return BCM_E_UNAVAIL; 6086 } 6087 } else if (child_index < *use_fc) { 6088 return BCM_E_UNAVAIL; 6089 } 6090 } 6091 6092 if (level == SOC_MONTEREY_NODE_LVL_L1) { 6093 for (mcm = 0, mc = 0, ucm = 0, uc = 0, ii = 0; ii < 8; ii++) { 6094 if (*ucmap & (1 << ii)) { 6095 mcm |= (cur_spmap & (1 << ii)) ? (1 << mc) : 0; 6096 mc += 1; 6097 } else { 6098 ucm |= (cur_spmap & (1 << ii)) ? (1 << uc) : 0; 6099 uc += 1; 6100 } 6101 } 6102 6103 if (child_index < _BCM_MN_NUM_L2_UC_LEAVES_PER_PIPE) { 6104 fc = *first_sp_child; 6105 oc = _bcm_mn_num_ones(ucm); 6106 BCM_IF_ERROR_RETURN(_bcm_monterey_compute_lls_config(unit, port, 6107 level - 1, &fc, NULL, &oc, &lucmap, &ucm, child_index, 6108 cur_mode, mode, 8)); 6109 } else { 6110 fc = *first_sp_mc_child; 6111 oc = _bcm_mn_num_ones(mcm); 6112 BCM_IF_ERROR_RETURN(_bcm_monterey_compute_lls_config(unit, port, 6113 level - 1, &fc, NULL, &oc, &lucmap, &mcm, 6114 child_index, cur_mode, mode, 8)); 6115 } 6116 6117 cur_spmap = 0; 6118 *ucmap = 0; 6119 for (fc = 0, ii = 0; ii < 8; ii++) { 6120 if (ucm) { 6121 cur_spmap |= (ucm & (1 << ii)) ? 1 << fc : 0; 6122 fc += 1; 6123 ucm &= ~(1 << ii); 6124 } 6125 6126 if (mcm) { 6127 cur_spmap |= (mcm & (1 << ii)) ? 1 << fc : 0; 6128 *ucmap |= 1 << fc; 6129 fc += 1; 6130 mcm &= ~(1 << ii); 6131 } 6132 6133 if (fc > max_children) { 6134 return BCM_E_PARAM; 6135 } 6136 6137 if ((mcm == 0) && (ucm == 0)) { 6138 break; 6139 } 6140 } 6141 6142 } else { 6143 pfc = first_sp_child; 6144 if (mode == SOC_MONTEREY_SCHED_MODE_STRICT) { 6145 if (*pfc > child_index) { 6146 cur_spmap <<= (*pfc - child_index); 6147 cur_spmap |= 1; 6148 *pfc = child_index; 6149 *num_spri += 1; 6150 } else { 6151 if (((1 << (child_index - *pfc)) & cur_spmap) == 0) { 6152 cur_spmap |= 1 << (child_index - *pfc); 6153 *num_spri += 1; 6154 } 6155 } 6156 } else { 6157 if (1 << (child_index - *pfc) & cur_spmap) { 6158 cur_spmap &= ~(1 << (child_index - *pfc)); 6159 *num_spri -= 1; 6160 } 6161 } 6162 } 6163 6164 *num_spri = _bcm_mn_num_ones(cur_spmap); 6165 6166 *spmap = cur_spmap; 6167 6168 return BCM_E_NONE; 6169 } 6170 6171 /* 6172 * Function: 6173 * _bcm_mn_compute_lls_config 6174 * Purpose: 6175 * This function computes the LLS configuration at each level 6176 * Parameters: 6177 * unit - (IN) unit number 6178 * port - (IN) local port number 6179 * level - (IN) level of the node in LLS 6180 * first_sp_child - (OUT) first sp child 6181 * first_sp_mc_child - (OUT) first so multicast child 6182 * ucmap - (OUT) unicast node map 6183 * spmap - (OUT) SPRI node map 6184 * child_index - (IN) index of the child node 6185 * cur_mode - (IN) current schedling mode of the node 6186 * mode - (IN) new scheduling mode of the node 6187 * max_children - (IN) maximum number of children in the level 6188 * Returns: 6189 * BCM_E_XXX 6190 */ 6191 STATIC int 6192 _bcm_mn_compute_lls_config(int unit, int port, int level, 6193 int *first_sp_child, 6194 int *first_sp_mc_child, 6195 int *num_spri, 6196 uint32 *ucmap, 6197 uint32 *spmap, 6198 int child_index, 6199 soc_monterey_sched_mode_e cur_mode, 6200 soc_monterey_sched_mode_e mode) 6201 { 6202 if (!soc_feature(unit, soc_feature_vector_based_spri)) { 6203 return BCM_E_UNAVAIL; 6204 } 6205 6206 if (((cur_mode != SOC_MONTEREY_SCHED_MODE_STRICT) && 6207 (mode != SOC_MONTEREY_SCHED_MODE_STRICT)) || 6208 ((cur_mode == SOC_MONTEREY_SCHED_MODE_STRICT) && 6209 (mode == SOC_MONTEREY_SCHED_MODE_STRICT))) { 6210 return BCM_E_NONE; 6211 } 6212 6213 return _bcm_monterey_compute_lls_config(unit, port, level, first_sp_child, 6214 first_sp_mc_child, num_spri, 6215 ucmap, spmap, child_index, 6216 cur_mode, mode, 8); 6217 } 6218 6219 STATIC int 6220 _bcm_mn_cosq_sched_parent_child_set(int unit, int port, int level, 6221 int sched_index, int child_index, 6222 soc_monterey_sched_mode_e sched_mode, 6223 int weight, _bcm_mn_cosq_node_t *child_node) 6224 { 6225 int wt, num_spri, first_sp_child, first_sp_mc_child; 6226 uint32 ucmap = 0, spmap = 0; 6227 soc_monterey_sched_mode_e cur_sched_mode; 6228 _bcm_mn_lls_info_t lls_tree_info; 6229 int rv; 6230 if (child_node == NULL) { 6231 return BCM_E_PARAM; 6232 } 6233 6234 BCM_IF_ERROR_RETURN(soc_monterey_cosq_get_sched_config(unit, port, level, 6235 sched_index, child_index, &num_spri, &first_sp_child, 6236 &first_sp_mc_child, &ucmap, &spmap, &cur_sched_mode, 6237 &wt)); 6238 /* If the dynamic switchover feature is enabled, then compute the LLS 6239 configuration and adjust the bandwidth at the level such that each 6240 node has sufficient bandwidth to perform the switchover. Also set 6241 the new scheduler config based on the request */ 6242 if (soc_feature(unit, soc_feature_vector_based_spri)) { 6243 6244 if ((rv = _bcm_mn_compute_lls_config(unit, port, level, &first_sp_child, 6245 &first_sp_mc_child, &num_spri, 6246 &ucmap, &spmap, child_index, 6247 cur_sched_mode, sched_mode))) { 6248 return rv; 6249 } 6250 6251 if (cur_sched_mode != sched_mode) { 6252 if ((rv = _bcm_mn_adjust_lls_bw(unit, port, child_node, 6253 child_node->level, child_index, 1, &lls_tree_info))){ 6254 goto error; 6255 } 6256 } 6257 6258 if ((rv = soc_monterey_cosq_set_sched_config(unit, port, level, 6259 sched_index, child_index, 6260 num_spri, first_sp_child, 6261 first_sp_mc_child, ucmap, 6262 spmap, sched_mode, weight))){ 6263 goto error; 6264 } 6265 6266 if (cur_sched_mode != sched_mode) { 6267 /* restore the default bw */ 6268 BCM_IF_ERROR_RETURN(_bcm_mn_adjust_lls_bw(unit, port, child_node, 6269 child_node->level, 6270 child_index, 6271 0, &lls_tree_info)); 6272 } 6273 } 6274 6275 return BCM_E_NONE; 6276 6277 /* If there is an error during the switchover process, then restore the 6278 bandwidth to the previous state */ 6279 error: 6280 if (cur_sched_mode != sched_mode) { 6281 BCM_IF_ERROR_RETURN(_bcm_mn_adjust_lls_bw(unit, port, child_node, 6282 child_node->level, 6283 child_index, 6284 0, &lls_tree_info)); 6285 } 6286 return rv; 6287 } 6288 6289 /* 6290 * Function: 6291 * _bcm_mn_cosq_sched_set 6292 * Purpose: 6293 * Set scheduling mode 6294 * Parameters: 6295 * unit - (IN) unit number 6296 * port - (IN) port number or GPORT identifier 6297 * cosq - (IN) COS queue number 6298 * mode - (IN) scheduling mode (BCM_COSQ_XXX) 6299 * num_weights - (IN) number of entries in weights array 6300 * weights - (IN) weights array 6301 * Returns: 6302 * BCM_E_XXX 6303 */ 6304 STATIC int 6305 _bcm_mn_cosq_sched_set(int unit, bcm_port_t gport, bcm_cos_queue_t cosq, 6306 int mode, int weight) 6307 { 6308 _bcm_mn_cosq_node_t *node = NULL, *child_node , *s1_node; 6309 bcm_port_t local_port; 6310 int lwts = 1, index, numq; 6311 soc_monterey_sched_mode_e sched_mode; 6312 _bcm_mn_mmu_info_t *mmu_info; 6313 soc_info_t *si; 6314 int rv = BCM_E_NONE; 6315 6316 if (cosq < 0) { 6317 if (cosq == -1) { 6318 /* caller needs to resolve the wild card value (-1) */ 6319 return BCM_E_INTERNAL; 6320 } else { /* reject all other negative value */ 6321 return BCM_E_PARAM; 6322 } 6323 } 6324 6325 if ((weight < 0) || (weight > 127)) { 6326 return BCM_E_PARAM; 6327 } 6328 6329 if(_BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, gport)){ 6330 BCM_IF_ERROR_RETURN( 6331 _bcmi_coe_subport_physical_port_get(unit, gport, &local_port)); 6332 } else { 6333 BCM_IF_ERROR_RETURN 6334 (_bcm_mn_cosq_localport_resolve(unit, gport, &local_port)); 6335 } 6336 si = &SOC_INFO(unit); 6337 mmu_info = _bcm_mn_mmu_info[unit]; 6338 6339 switch(mode) { 6340 case BCM_COSQ_STRICT: 6341 sched_mode = SOC_MONTEREY_SCHED_MODE_STRICT; 6342 lwts = 0; 6343 break; 6344 case BCM_COSQ_ROUND_ROBIN: 6345 sched_mode = SOC_MONTEREY_SCHED_MODE_WRR; 6346 lwts = 1; 6347 break; 6348 case BCM_COSQ_WEIGHTED_ROUND_ROBIN: 6349 sched_mode = SOC_MONTEREY_SCHED_MODE_WRR; 6350 lwts = weight; 6351 break; 6352 case BCM_COSQ_DEFICIT_ROUND_ROBIN: 6353 sched_mode = SOC_MONTEREY_SCHED_MODE_WDRR; 6354 lwts = weight; 6355 break; 6356 default: 6357 return BCM_E_PARAM; 6358 } 6359 6360 if (lwts == 0) { 6361 sched_mode = SOC_MONTEREY_SCHED_MODE_STRICT; 6362 } 6363 6364 if (BCM_GPORT_IS_SCHEDULER(gport)) { /* ETS style scheduler */ 6365 BCM_IF_ERROR_RETURN 6366 (_bcm_mn_cosq_node_get(unit, gport, 0, NULL, &local_port, NULL, 6367 &node)); 6368 if ((node->numq >= 0) && (cosq > node->numq)) { 6369 return BCM_E_PARAM; 6370 } 6371 BCM_IF_ERROR_RETURN 6372 (_bcm_mn_cosq_child_node_at_input(node, cosq, &child_node)); 6373 } else if (_BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT 6374 (unit, gport)) { 6375 if (soc_feature(unit, 6376 soc_feature_mmu_hqos_four_level)) { 6377 BCM_IF_ERROR_RETURN 6378 (_bcm_mn_get_s1_node(unit, gport, 6379 &s1_node)); 6380 index = s1_node->coe_base_index; 6381 child_node = &mmu_info->queue_node[index + cosq ]; 6382 if (!child_node) { 6383 return BCM_E_INTERNAL; 6384 } 6385 if (child_node->attached_to_input == -1) { 6386 return BCM_E_NOT_FOUND; 6387 } 6388 node = child_node->parent ; 6389 if (!node) { 6390 return BCM_E_INTERNAL; 6391 } 6392 6393 } else { 6394 return BCM_E_PARAM; 6395 } 6396 } else { 6397 if (IS_CPU_PORT(unit, local_port)) { 6398 numq = SOC_INFO(unit).num_cpu_cosq; 6399 if (cosq >= numq) { 6400 return BCM_E_PARAM; 6401 } 6402 index = soc_monterey_l2_hw_index(unit, 6403 si->port_cosq_base[local_port] + cosq, 0); 6404 } else { 6405 index = soc_monterey_l2_hw_index(unit, 6406 si->port_uc_cosq_base[local_port] + cosq, 1); 6407 } 6408 6409 child_node = &mmu_info->queue_node[index]; 6410 if (!child_node) { 6411 return BCM_E_INTERNAL; 6412 } 6413 if (child_node->attached_to_input == -1) { 6414 return BCM_E_NOT_FOUND; 6415 } 6416 node = child_node->parent; 6417 if (node && !IS_CPU_PORT(unit, local_port)) { 6418 child_node = node; 6419 node = node->parent; 6420 if (!node) { 6421 return BCM_E_INTERNAL; 6422 } 6423 if ((node->numq >= 0) && ((cosq % _BCM_MN_HSP_PORT_MAX_COS) > node->numq)) { 6424 return BCM_E_PARAM; 6425 } 6426 BCM_IF_ERROR_RETURN 6427 (_bcm_mn_cosq_child_node_at_input(node, cosq, 6428 &child_node)); 6429 } 6430 } 6431 6432 if (!node || !child_node) { 6433 return BCM_E_INTERNAL; 6434 } 6435 6436 /* S1 is always in WRR in Apache */ 6437 if (!IS_MN_HSP_PORT(unit, local_port) && 6438 (soc_feature(unit, soc_feature_mmu_hqos_four_level)) && 6439 (node->level == SOC_MONTEREY_NODE_LVL_ROOT) && 6440 (mode == BCM_COSQ_STRICT)) { 6441 return BCM_E_PARAM; 6442 } 6443 6444 if (node->attached_to_input < 0) { /* Not resolved yet */ 6445 return BCM_E_NOT_FOUND; 6446 } 6447 6448 /* HSP/LLS - child node at cosq index of parent gport 6449 * is resloved to set it's schedule mode and weight 6450 */ 6451 if (IS_MN_HSP_PORT(unit, local_port)) { 6452 rv = soc_monterey_cosq_set_sched_mode(unit, local_port, 6453 child_node->level, child_node->hw_index, sched_mode, lwts); 6454 } else { 6455 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_sched_parent_child_set(unit, 6456 local_port, node->level, node->hw_index, 6457 child_node->hw_index, sched_mode, lwts, child_node)); 6458 if (!BCM_GPORT_IS_SCHEDULER(gport) && 6459 !BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) && 6460 !BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) && 6461 node && IS_CPU_PORT(unit, local_port)) { 6462 child_node = node; 6463 node = node->parent; 6464 lwts = (sched_mode == SOC_MONTEREY_SCHED_MODE_STRICT) ? 0 : 1; 6465 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_sched_parent_child_set(unit, 6466 local_port, node->level, node->hw_index, 6467 child_node->hw_index, sched_mode, lwts, child_node)); 6468 } 6469 } 6470 6471 return rv; 6472 } 6473 6474 /* 6475 * Function: 6476 * bcm_mn_cosq_detach 6477 * Purpose: 6478 * Discard all COS schedule/mapping state. 6479 * Parameters: 6480 * unit - unit number 6481 * Returns: 6482 * BCM_E_XXX 6483 */ 6484 int 6485 bcm_mn_cosq_detach(int unit, int software_state_only) 6486 { 6487 int i; 6488 soc_info_t *si; 6489 bcm_port_t port; 6490 bcm_gport_t gport; 6491 6492 if (!_bcm_mn_mmu_info[unit] ) { 6493 return BCM_E_NONE; 6494 } 6495 6496 (void) _bcm_bst_detach(unit); 6497 6498 PBMP_ALL_ITER(unit, port) { 6499 /* need to clean the ports even in case of failure. So not checking 6500 return value intentionally 6501 */ 6502 /* coverity[checked_return:FALSE]*/ 6503 /* coverity[unchecked_value:FALSE] */ 6504 (void)bcm_esw_port_gport_get(unit, port, &gport); 6505 /* coverity[checked_return:FALSE]*/ 6506 /* coverity[unchecked_value:FALSE] */ 6507 bcm_mn_cosq_gport_delete(unit, gport); 6508 } 6509 if (NULL != _bcm_mn_endpoint_queuing_info[unit]) { 6510 if (NULL != _bcm_mn_endpoint_queuing_info[unit]->ptr_array) { 6511 for (i = 0; i < _BCM_MN_NUM_ENDPOINT(unit); i++) { 6512 if (_BCM_MN_ENDPOINT_IS_USED(unit, i)) { 6513 sal_free(_BCM_MN_ENDPOINT(unit, i)); 6514 _BCM_MN_ENDPOINT(unit, i) = NULL; 6515 } 6516 } 6517 sal_free(_bcm_mn_endpoint_queuing_info[unit]->ptr_array); 6518 _bcm_mn_endpoint_queuing_info[unit]->ptr_array = NULL; 6519 } 6520 if (NULL != _bcm_mn_endpoint_queuing_info[unit]->cos_map_profile) { 6521 soc_profile_mem_destroy(unit, 6522 _bcm_mn_endpoint_queuing_info[unit]->cos_map_profile); 6523 sal_free(_bcm_mn_endpoint_queuing_info[unit]->cos_map_profile); 6524 _bcm_mn_endpoint_queuing_info[unit]->cos_map_profile = NULL; 6525 } 6526 sal_free(_bcm_mn_endpoint_queuing_info[unit]); 6527 _bcm_mn_endpoint_queuing_info[unit] = NULL; 6528 } 6529 6530 si = &SOC_INFO(unit); 6531 for (i = 0; i < si->num_cpu_cosq; i++) { 6532 if (_bcm_mn_cosq_cpu_cosq_config[unit][i] != NULL) { 6533 sal_free(_bcm_mn_cosq_cpu_cosq_config[unit][i]); 6534 _bcm_mn_cosq_cpu_cosq_config[unit][i] = NULL; 6535 } 6536 } 6537 if (_bcm_mn_wred_profile[unit] != NULL ) 6538 { 6539 soc_profile_mem_destroy(unit, _bcm_mn_wred_profile[unit]); 6540 sal_free(_bcm_mn_wred_profile[unit]); 6541 _bcm_mn_wred_profile[unit] = NULL; 6542 } 6543 if (_bcm_mn_cos_map_profile[unit] != NULL ) 6544 { 6545 soc_profile_mem_destroy(unit, _bcm_mn_cos_map_profile[unit]); 6546 sal_free(_bcm_mn_cos_map_profile[unit]); 6547 _bcm_mn_cos_map_profile[unit] = NULL; 6548 } 6549 if (_bcm_mn_sample_int_profile[unit] != NULL ) 6550 { 6551 soc_profile_mem_destroy(unit, _bcm_mn_sample_int_profile[unit]); 6552 sal_free(_bcm_mn_sample_int_profile[unit]); 6553 _bcm_mn_sample_int_profile[unit] = NULL; 6554 } 6555 if (_bcm_mn_feedback_profile[unit] != NULL ) 6556 { 6557 soc_profile_reg_destroy(unit, _bcm_mn_feedback_profile[unit]); 6558 sal_free(_bcm_mn_feedback_profile[unit]); 6559 _bcm_mn_feedback_profile[unit] = NULL ; 6560 } 6561 if (_bcm_mn_llfc_profile[unit] != NULL ) 6562 { 6563 soc_profile_reg_destroy(unit, _bcm_mn_llfc_profile[unit]); 6564 sal_free(_bcm_mn_llfc_profile[unit]); 6565 _bcm_mn_llfc_profile[unit] = NULL ; 6566 } 6567 if (_bcm_mn_voq_port_map_profile[unit] != NULL ) 6568 { 6569 soc_profile_mem_destroy(unit, _bcm_mn_voq_port_map_profile[unit]); 6570 sal_free(_bcm_mn_voq_port_map_profile[unit]); 6571 _bcm_mn_voq_port_map_profile[unit] = NULL; 6572 } 6573 if (_bcm_mn_ifp_cos_map_profile[unit] != NULL ) 6574 { 6575 soc_profile_mem_destroy(unit, _bcm_mn_ifp_cos_map_profile[unit]); 6576 sal_free(_bcm_mn_ifp_cos_map_profile[unit]); 6577 _bcm_mn_ifp_cos_map_profile[unit] = NULL; 6578 } 6579 if (_bcm_mn_service_port_map_profile[unit] != NULL ) 6580 { 6581 soc_profile_mem_destroy(unit, _bcm_mn_service_port_map_profile[unit]); 6582 sal_free(_bcm_mn_service_port_map_profile[unit]); 6583 _bcm_mn_service_port_map_profile[unit] = NULL; 6584 } 6585 if (_bcm_mn_service_cos_map_profile[unit] != NULL ) 6586 { 6587 soc_profile_mem_destroy(unit, _bcm_mn_service_cos_map_profile[unit]); 6588 sal_free(_bcm_mn_service_cos_map_profile[unit]); 6589 _bcm_mn_service_cos_map_profile[unit] = NULL; 6590 } 6591 if (_bcm_mn_mmu_info[unit] != NULL) { 6592 _bcm_mn_cosq_free_memory(_bcm_mn_mmu_info[unit]); 6593 sal_free(_bcm_mn_mmu_info[unit]); 6594 _bcm_mn_mmu_info[unit] = NULL; 6595 } 6596 soc_monterey_shadow_free(unit); 6597 return BCM_E_NONE; 6598 } 6599 6600 /* 6601 * Function: 6602 * bcm_mn_cosq_config_set 6603 * Purpose: 6604 * Set the number of COS queues 6605 * Parameters: 6606 * unit - unit number 6607 * numq - number of COS queues (1-8). 6608 * Returns: 6609 * BCM_E_XXX 6610 */ 6611 int 6612 bcm_mn_cosq_config_set(int unit, int numq) 6613 { 6614 port_cos_map_entry_t cos_map_entries[16]; 6615 port_cos_map_entry_t hg_cos_map_entries[16]; 6616 void *entries[1], *hg_entries[1]; 6617 uint32 index, hg_index; 6618 int count, hg_count; 6619 bcm_port_t port; 6620 int cos, prio; 6621 uint32 i; 6622 int ref_count; 6623 int cpu_hg_index = 0; 6624 6625 if (numq < 1 || numq > BCM_MN_COS_MAX) { 6626 return BCM_E_PARAM; 6627 } 6628 6629 /* clear out old profiles. */ 6630 index = 0; 6631 while (index < soc_mem_index_count(unit, PORT_COS_MAPm)) { 6632 BCM_IF_ERROR_RETURN(soc_profile_mem_ref_count_get(unit, 6633 _bcm_mn_cos_map_profile[unit], 6634 index, &ref_count)); 6635 if (ref_count > 0) { 6636 while (ref_count) { 6637 if (!soc_profile_mem_delete(unit, _bcm_mn_cos_map_profile[unit], index)) { 6638 ref_count -= 1; 6639 } 6640 } 6641 } 6642 index += 16; 6643 } 6644 6645 /* Distribute first 8 internal priority levels into the specified number 6646 * of cosq, map remaining internal priority levels to highest priority 6647 * cosq */ 6648 sal_memset(cos_map_entries, 0, sizeof(cos_map_entries)); 6649 entries[0] = &cos_map_entries; 6650 hg_entries[0] = &hg_cos_map_entries; 6651 prio = 0; 6652 for (cos = 0; cos < numq; cos++) { 6653 for (i = 8 / numq + (cos < 8 % numq ? 1 : 0); i > 0; i--) { 6654 soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio], 6655 UC_COS1f, cos); 6656 soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio], 6657 MC_COS1f, cos); 6658 soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio], 6659 HG_COSf, cos); 6660 soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio], 6661 RQE_Q_NUMf, cos); 6662 prio++; 6663 } 6664 } 6665 for (prio = 8; prio < 16; prio++) { 6666 soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio], 6667 UC_COS1f, numq - 1); 6668 soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio], 6669 MC_COS1f, numq - 1); 6670 soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio], 6671 HG_COSf, numq - 1); 6672 soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio], 6673 RQE_Q_NUMf, numq - 1); 6674 } 6675 6676 /* Map internal priority levels to CPU CoS queues */ 6677 BCM_IF_ERROR_RETURN(_bcm_esw_cpu_cosq_mapping_default_set(unit, numq)); 6678 6679 #ifdef BCM_COSQ_HIGIG_MAP_DISABLE 6680 /* Use identical mapping for Higig port */ 6681 sal_memset(hg_cos_map_entries, 0, sizeof(hg_cos_map_entries)); 6682 prio = 0; 6683 for (prio = 0; prio < 8; prio++) { 6684 soc_mem_field32_set(unit, PORT_COS_MAPm, &hg_cos_map_entries[prio], 6685 UC_COS1f, prio); 6686 soc_mem_field32_set(unit, PORT_COS_MAPm, &hg_cos_map_entries[prio], 6687 MC_COS1f, prio); 6688 soc_mem_field32_set(unit, PORT_COS_MAPm, &hg_cos_map_entries[prio], 6689 RQE_Q_NUMf, prio); 6690 } 6691 for (prio = 8; prio < 13; prio++) { 6692 soc_mem_field32_set(unit, PORT_COS_MAPm, &hg_cos_map_entries[prio], 6693 UC_COS1f, 7); 6694 soc_mem_field32_set(unit, PORT_COS_MAPm, &hg_cos_map_entries[prio], 6695 MC_COS1f, 7); 6696 soc_mem_field32_set(unit, PORT_COS_MAPm, &hg_cos_map_entries[prio], 6697 RQE_Q_NUMf, 7); 6698 } 6699 #else /* BCM_COSQ_HIGIG_MAP_DISABLE */ 6700 sal_memcpy(hg_cos_map_entries, cos_map_entries, sizeof(cos_map_entries)); 6701 #endif /* !BCM_COSQ_HIGIG_MAP_DISABLE */ 6702 6703 BCM_IF_ERROR_RETURN 6704 (soc_profile_mem_add(unit, _bcm_mn_cos_map_profile[unit], 6705 entries, 16, &index)); 6706 soc_mem_field32_set(unit, PORT_COS_MAPm, &hg_cos_map_entries[14], 6707 HG_COSf, 8); 6708 soc_mem_field32_set(unit, PORT_COS_MAPm, &hg_cos_map_entries[15], 6709 HG_COSf, 9); 6710 6711 BCM_IF_ERROR_RETURN 6712 (soc_profile_mem_add(unit, _bcm_mn_cos_map_profile[unit], 6713 hg_entries, 16, &hg_index)); 6714 count = 0; 6715 hg_count = 0; 6716 PBMP_ALL_ITER(unit, port) { 6717 if (IS_LB_PORT(unit, port)) { 6718 continue; 6719 } 6720 6721 if (IS_HG_PORT(unit, port)) { 6722 BCM_IF_ERROR_RETURN 6723 (soc_mem_field32_modify(unit, COS_MAP_SELm, port, SELECTf, 6724 hg_index / 16)); 6725 hg_count++; 6726 } else { 6727 BCM_IF_ERROR_RETURN 6728 (soc_mem_field32_modify(unit, COS_MAP_SELm, port, SELECTf, 6729 index / 16)); 6730 count++; 6731 } 6732 } 6733 6734 cpu_hg_index = SOC_INFO(unit).cpu_hg_index; 6735 if (cpu_hg_index != -1) { 6736 BCM_IF_ERROR_RETURN 6737 (soc_mem_field32_modify(unit, COS_MAP_SELm, 6738 cpu_hg_index, SELECTf, index / 16)); 6739 count++; 6740 } 6741 6742 for (i = 1; i < count; i++) { 6743 soc_profile_mem_reference(unit, _bcm_mn_cos_map_profile[unit], index, 0); 6744 } 6745 for (i = 1; i < hg_count; i++) { 6746 soc_profile_mem_reference(unit, _bcm_mn_cos_map_profile[unit], 6747 hg_index, 0); 6748 } 6749 6750 /* Delete the default higig cos map profile for the non-higig system */ 6751 if (hg_count == 0) { 6752 soc_profile_mem_delete(unit, _bcm_mn_cos_map_profile[unit], hg_index); 6753 } 6754 6755 _MN_NUM_COS(unit) = numq; 6756 6757 return BCM_E_NONE; 6758 } 6759 6760 STATIC int 6761 _bcm_mn_cosq_egress_sp_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 6762 int *p_pool_start, int *p_pool_end) 6763 { 6764 int local_port; 6765 int pool; 6766 if (cosq == BCM_COS_INVALID) { 6767 *p_pool_start = 0; 6768 *p_pool_end = 3; 6769 return BCM_E_NONE; 6770 } 6771 6772 BCM_IF_ERROR_RETURN 6773 (_bcm_mn_cosq_index_resolve(unit, gport, cosq, 6774 _BCM_MN_COSQ_INDEX_STYLE_EGR_POOL, 6775 &local_port, &pool, NULL)); 6776 6777 *p_pool_start = *p_pool_end = pool; 6778 return BCM_E_NONE; 6779 } 6780 6781 STATIC int 6782 _bcm_mn_cosq_ingress_sp_get(int unit, bcm_gport_t gport, bcm_cos_queue_t pri_grp, 6783 int *p_pool_start, int *p_pool_end) 6784 { 6785 int local_port; 6786 uint32 rval, pool; 6787 static const soc_field_t prigroup_spid_field[] = { 6788 PG0_SPIDf, PG1_SPIDf, PG2_SPIDf, PG3_SPIDf, 6789 PG4_SPIDf, PG5_SPIDf, PG6_SPIDf, PG7_SPIDf 6790 }; 6791 6792 if (pri_grp == BCM_COS_INVALID) { 6793 *p_pool_start = 0; 6794 *p_pool_end = 3; 6795 return BCM_E_NONE; 6796 } 6797 6798 BCM_IF_ERROR_RETURN 6799 (_bcm_mn_cosq_localport_resolve(unit, gport, &local_port)); 6800 6801 if (!SOC_PORT_VALID(unit, local_port)) { 6802 return BCM_E_PORT; 6803 } 6804 6805 if ((pri_grp < 0) || (pri_grp >= 8)) { 6806 return BCM_E_PARAM; 6807 } 6808 6809 SOC_IF_ERROR_RETURN(READ_THDI_PORT_PG_SPIDr(unit, local_port, &rval)); 6810 pool = soc_reg_field_get(unit, THDI_PORT_PG_SPIDr, rval, 6811 prigroup_spid_field[pri_grp]); 6812 6813 *p_pool_start = *p_pool_end = pool; 6814 return BCM_E_NONE; 6815 } 6816 6817 STATIC int 6818 _bcm_mn_cosq_ingress_pg_get(int unit, bcm_gport_t gport, bcm_cos_queue_t pri, 6819 int *p_pg_start, int *p_pg_end) 6820 { 6821 bcm_port_t local_port; 6822 uint32 rval,pool; 6823 soc_reg_t reg = INVALIDr; 6824 static const soc_reg_t prigroup_reg[] = { 6825 THDI_PORT_PRI_GRP0r, THDI_PORT_PRI_GRP1r 6826 }; 6827 static const soc_field_t prigroup_field[] = { 6828 PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf, 6829 PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf, 6830 PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf, 6831 PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf 6832 }; 6833 6834 if (pri == BCM_COS_INVALID) { 6835 *p_pg_start = 0; 6836 *p_pg_end = 7; 6837 return BCM_E_NONE; 6838 } 6839 6840 BCM_IF_ERROR_RETURN 6841 (_bcm_mn_cosq_localport_resolve(unit, gport, &local_port)); 6842 6843 if (!SOC_PORT_VALID(unit, local_port)) { 6844 return BCM_E_PORT; 6845 } 6846 6847 if (pri > 15) { 6848 return BCM_E_PARAM; 6849 } 6850 /* get PG for port using Port+Cos */ 6851 if (pri < 8) { 6852 reg = prigroup_reg[0]; 6853 } else { 6854 reg = prigroup_reg[1]; 6855 } 6856 6857 SOC_IF_ERROR_RETURN 6858 (soc_reg32_get(unit, reg, local_port, 0, &rval)); 6859 pool = soc_reg_field_get(unit, reg, rval, prigroup_field[pri]); 6860 6861 *p_pg_start = *p_pg_end = pool; 6862 return BCM_E_NONE; 6863 } 6864 6865 6866 STATIC _bcm_bst_cb_ret_t 6867 _bcm_mn_bst_index_resolve(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 6868 bcm_bst_stat_id_t bid, int *pipe, int *start_hw_index, 6869 int *end_hw_index, int *rcb_data, void **cb_data, int *bcm_rv) 6870 { 6871 int phy_port, mmu_port, local_port; 6872 _bcm_mn_cosq_node_t *node = NULL; 6873 soc_info_t *si; 6874 uint32 rval = 0; 6875 int pool_idx; 6876 *bcm_rv = BCM_E_NONE; 6877 6878 #define _BST_IF_ERROR_GOTO_EXIT(op) \ 6879 do { int __rv__; if ((__rv__ = (op)) < 0) { goto error_exit; } } while(0) 6880 6881 _BST_IF_ERROR_GOTO_EXIT 6882 (_bcm_mn_cosq_localport_resolve(unit, gport, &local_port)); 6883 6884 si = &SOC_INFO(unit); 6885 phy_port = si->port_l2p_mapping[local_port]; 6886 mmu_port = si->port_p2m_mapping[phy_port]; 6887 6888 *pipe = 0; 6889 6890 if (bid == bcmBstStatIdDevice) { 6891 *start_hw_index = *end_hw_index = 0; 6892 *bcm_rv = BCM_E_NONE; 6893 return _BCM_BST_RV_OK; 6894 } 6895 6896 if (bid == bcmBstStatIdEgrPool) { 6897 /* Egress Unicast Pool */ 6898 if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 6899 goto error_exit; 6900 } 6901 _BST_IF_ERROR_GOTO_EXIT(_bcm_mn_cosq_egress_sp_get(unit, gport, cosq, 6902 start_hw_index, end_hw_index)); 6903 return _BCM_BST_RV_OK; 6904 } else if (bid == bcmBstStatIdEgrMCastPool) { 6905 /* Egress Multicast Pool */ 6906 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 6907 goto error_exit; 6908 } 6909 _BST_IF_ERROR_GOTO_EXIT(_bcm_mn_cosq_egress_sp_get(unit, gport, cosq, 6910 start_hw_index, end_hw_index)); 6911 return _BCM_BST_RV_OK; 6912 } else if (bid == bcmBstStatIdIngPool) { 6913 /* ingress pool */ 6914 _BST_IF_ERROR_GOTO_EXIT(_bcm_mn_cosq_ingress_sp_get(unit, gport, cosq, 6915 start_hw_index, end_hw_index)); 6916 return _BCM_BST_RV_OK; 6917 } else if (bid == bcmBstStatIdRQEPool) { 6918 /* RQE pool */ 6919 if (cosq == BCM_COS_INVALID) { 6920 *start_hw_index = 0; 6921 *end_hw_index = _MONTEREY_MMU_NUM_POOL - 1; 6922 } else if ((cosq < 0) || (cosq >= _MONTEREY_MMU_NUM_RQE_QUEUES)) { 6923 return BCM_E_PARAM; 6924 } else { 6925 SOC_IF_ERROR_RETURN 6926 (READ_MMU_THDR_DB_CONFIG1_PRIQr(unit, cosq, &rval)); 6927 6928 pool_idx = soc_reg_field_get(unit, MMU_THDR_DB_CONFIG1_PRIQr, rval, 6929 SPIDf); 6930 *start_hw_index = *end_hw_index = pool_idx; 6931 } 6932 return _BCM_BST_RV_OK; 6933 } else if (bid == bcmBstStatIdRQEQueue) { 6934 /* RQE queue */ 6935 if (cosq == BCM_COS_INVALID) { 6936 *start_hw_index = 0; 6937 *end_hw_index = _MONTEREY_MMU_NUM_RQE_QUEUES - 1; 6938 } else if ((cosq < 0) || (cosq >= _MONTEREY_MMU_NUM_RQE_QUEUES)) { 6939 return BCM_E_PARAM; 6940 } else { 6941 *start_hw_index = *end_hw_index = cosq; 6942 } 6943 return _BCM_BST_RV_OK; 6944 } else if (bid == bcmBstStatIdUCQueueGroup) { 6945 /* unicast queue group */ 6946 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_index_resolve(unit, 6947 gport, cosq, _BCM_MN_COSQ_INDEX_STYLE_UCAST_QUEUE_GROUP, 6948 NULL, start_hw_index, NULL)); 6949 *end_hw_index = *start_hw_index; 6950 return _BCM_BST_RV_OK; 6951 } 6952 6953 if (bid == bcmBstStatIdPortPool) { 6954 /* ingress pool */ 6955 _BST_IF_ERROR_GOTO_EXIT( 6956 _bcm_mn_cosq_ingress_sp_get(unit, gport, cosq, 6957 start_hw_index, end_hw_index)); 6958 *start_hw_index = ((mmu_port) * 4) + *start_hw_index; 6959 *end_hw_index = ((mmu_port) * 4) + *end_hw_index; 6960 } else if ((bid == bcmBstStatIdPriGroupShared) || 6961 (bid == bcmBstStatIdPriGroupHeadroom)) { 6962 /* ingress pool */ 6963 _BST_IF_ERROR_GOTO_EXIT( 6964 _bcm_mn_cosq_ingress_pg_get(unit, gport, cosq, 6965 start_hw_index, end_hw_index)); 6966 *start_hw_index = ((mmu_port) * 8) + *start_hw_index; 6967 *end_hw_index = ((mmu_port) * 8) + *end_hw_index; 6968 } else { 6969 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 6970 if (bid != bcmBstStatIdUcast) { 6971 goto error_exit; 6972 } 6973 _BST_IF_ERROR_GOTO_EXIT 6974 (_bcm_mn_cosq_node_get(unit, gport, 0, NULL, 6975 &local_port, NULL, &node)); 6976 if (!node) { 6977 goto error_exit; 6978 } 6979 *start_hw_index = *end_hw_index = node->hw_index; 6980 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 6981 if (bid != bcmBstStatIdMcast) { 6982 goto error_exit; 6983 } 6984 _BST_IF_ERROR_GOTO_EXIT 6985 (_bcm_mn_cosq_node_get(unit, gport, 0, NULL, 6986 &local_port, NULL, &node)); 6987 if (!node) { 6988 goto error_exit; 6989 } 6990 *start_hw_index = *end_hw_index = node->hw_index - _BCM_MN_NUM_L2_UC_LEAVES; 6991 } else { 6992 _BST_IF_ERROR_GOTO_EXIT(_bcm_mn_cosq_port_has_ets(unit, local_port)); 6993 6994 if (cosq < 0) { 6995 if (bid == bcmBstStatIdUcast) { 6996 _BST_IF_ERROR_GOTO_EXIT(_bcm_mn_cosq_index_resolve(unit, 6997 local_port, 0, _BCM_MN_COSQ_INDEX_STYLE_UCAST_QUEUE, 6998 NULL, start_hw_index, NULL)); 6999 7000 _BST_IF_ERROR_GOTO_EXIT(_bcm_mn_cosq_index_resolve(unit, 7001 local_port, BCM_MN_COS_MAX - 1, 7002 _BCM_MN_COSQ_INDEX_STYLE_UCAST_QUEUE, 7003 NULL, end_hw_index, NULL)); 7004 7005 } else { 7006 _BST_IF_ERROR_GOTO_EXIT(_bcm_mn_cosq_index_resolve(unit, 7007 local_port, 0, _BCM_MN_COSQ_INDEX_STYLE_MCAST_QUEUE, 7008 NULL, start_hw_index, NULL)); 7009 *start_hw_index -= _BCM_MN_NUM_L2_UC_LEAVES; 7010 7011 _BST_IF_ERROR_GOTO_EXIT(_bcm_mn_cosq_index_resolve(unit, 7012 local_port, BCM_MN_COS_MAX - 1, 7013 _BCM_MN_COSQ_INDEX_STYLE_MCAST_QUEUE, 7014 NULL, end_hw_index, NULL)); 7015 *end_hw_index -= _BCM_MN_NUM_L2_UC_LEAVES; 7016 } 7017 } else { 7018 if (bid == bcmBstStatIdUcast) { 7019 _BST_IF_ERROR_GOTO_EXIT(_bcm_mn_cosq_index_resolve(unit, 7020 local_port, cosq, _BCM_MN_COSQ_INDEX_STYLE_UCAST_QUEUE, 7021 NULL, start_hw_index, NULL)); 7022 *end_hw_index = *start_hw_index; 7023 } else { 7024 _BST_IF_ERROR_GOTO_EXIT(_bcm_mn_cosq_index_resolve(unit, 7025 local_port, cosq, _BCM_MN_COSQ_INDEX_STYLE_MCAST_QUEUE, 7026 NULL, start_hw_index, NULL)); 7027 *start_hw_index -= _BCM_MN_NUM_L2_UC_LEAVES; 7028 *end_hw_index = *start_hw_index; 7029 } 7030 } /* if (cosq < 0) */ 7031 } /* if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { */ 7032 } /* if (bid == bcmBstStatIdPortPool) { */ 7033 7034 *bcm_rv = BCM_E_NONE; 7035 return _BCM_BST_RV_OK; 7036 7037 error_exit: 7038 *bcm_rv = BCM_E_PARAM; 7039 return _BCM_BST_RV_ERROR; 7040 } 7041 7042 7043 7044 STATIC int 7045 _bcm_mn_cosq_bst_map_resource_to_gport_cos(int unit, bcm_bst_stat_id_t bid, int port, 7046 int index, bcm_gport_t *gport, bcm_cos_t *cosq) 7047 { 7048 soc_info_t *si; 7049 _bcm_mn_cosq_node_t *node; 7050 _bcm_mn_mmu_info_t *mmu_info; 7051 _bcm_mn_pipe_resources_t *pres; 7052 int ii, pipe; 7053 int hw_index, mmu_port, phy_port; 7054 7055 pipe = _MN_XPIPE; 7056 mmu_info = _bcm_mn_mmu_info[unit]; 7057 pres = _BCM_MN_PRESOURCES(mmu_info, pipe); 7058 si = &SOC_INFO(unit); 7059 7060 switch (bid) { 7061 case bcmBstStatIdDevice: 7062 *gport = -1; 7063 *cosq = BCM_COS_INVALID; 7064 break; 7065 7066 case bcmBstStatIdIngPool: 7067 case bcmBstStatIdEgrPool: 7068 case bcmBstStatIdRQEPool: 7069 *gport = -1; 7070 *cosq = index; 7071 break; 7072 7073 case bcmBstStatIdRQEQueue: 7074 *gport = -1; 7075 *cosq = index % _MONTEREY_MMU_NUM_RQE_QUEUES; 7076 break; 7077 7078 case bcmBstStatIdUCQueueGroup: 7079 *gport = index; 7080 *cosq = -1; 7081 break; 7082 7083 case bcmBstStatIdPortPool: 7084 mmu_port = index/4; 7085 phy_port = si->port_m2p_mapping[mmu_port]; 7086 *gport = si->port_p2l_mapping[phy_port]; 7087 *cosq = index % 4; 7088 break; 7089 7090 case bcmBstStatIdPriGroupHeadroom: 7091 case bcmBstStatIdPriGroupShared: 7092 mmu_port = index / 8; 7093 phy_port = si->port_m2p_mapping[mmu_port]; 7094 *gport = si->port_p2l_mapping[phy_port]; 7095 *cosq = index % 8; 7096 break; 7097 7098 case bcmBstStatIdUcast: 7099 pipe = _MN_XPIPE; 7100 hw_index = soc_monterey_l2_hw_index(unit, index, 1); 7101 7102 if (mmu_info->ets_mode) { 7103 for (ii = 0; ii < _BCM_MN_NUM_L2_UC_LEAVES; ii++) { 7104 node = &pres->p_queue_node[ii]; 7105 if (node->in_use == TRUE) { 7106 7107 if (node->hw_index == hw_index) { 7108 *gport = node->gport; 7109 *cosq = 0; 7110 break; 7111 } 7112 } 7113 } 7114 } else { 7115 int port_uc_base = 0; 7116 int port_num_uc = 0; 7117 PBMP_ALL_ITER(unit, port) { 7118 7119 if (IS_LB_PORT(unit, port)) { 7120 continue; 7121 } 7122 7123 port_num_uc = si->port_num_uc_cosq[port]; 7124 port_uc_base = si->port_uc_cosq_base[port]; 7125 7126 if ((index >= port_uc_base) && 7127 (index < port_uc_base + port_num_uc)) { 7128 *gport = port; 7129 *cosq = index - port_uc_base; 7130 break; 7131 } 7132 } 7133 } 7134 break; 7135 case bcmBstStatIdMcast: 7136 pipe = _MN_XPIPE; 7137 hw_index = soc_monterey_l2_hw_index(unit, index, 0); 7138 7139 if (mmu_info->ets_mode) { 7140 for (ii = 0; ii < _BCM_MN_NUM_L2_MC_LEAVES; ii++) { 7141 node = &pres->p_queue_node[ii]; 7142 if (node->in_use == TRUE) { 7143 7144 if (node->hw_index == hw_index) { 7145 *gport = node->gport; 7146 *cosq = 0; 7147 break; 7148 } 7149 } 7150 } 7151 } else { 7152 int port_mc_base = 0; 7153 int port_num_mc = 0; 7154 PBMP_ALL_ITER(unit, port) { 7155 7156 port_num_mc = si->port_num_cosq[port]; 7157 port_mc_base = si->port_cosq_base[port]; 7158 7159 if ((index >= port_mc_base) && 7160 (index < port_mc_base + port_num_mc)) { 7161 *gport = port; 7162 *cosq = index - port_mc_base; 7163 break; 7164 } 7165 } 7166 } 7167 break; 7168 case bcmBstStatIdEgrMCastPool: 7169 /* MMU_THDM_DB_POOL_MC_BST_STAT only 4 indices */ 7170 *gport = -1; 7171 *cosq = index; 7172 break; 7173 default: 7174 break; 7175 } 7176 7177 return BCM_E_NONE; 7178 } 7179 7180 STATIC int 7181 _bcm_mn_cosq_cpri_gport_init_config(int unit, 7182 bcm_port_t port, 7183 bcm_gport_t gport, 7184 bcm_cos_queue_t cosq, 7185 int index, 7186 int uc_index, 7187 int mc_index) 7188 { 7189 uint32 min_quantum; 7190 uint32 max_quantum; 7191 uint32 kbits_burst_min; 7192 uint32 kbits_burst_max; 7193 uint32 flags; 7194 int roe_speed_rsvd4, eth_mode = 1, spid; 7195 _bcm_mn_mtro_node_info_t *node_info; 7196 uint32 uc_entry[SOC_MAX_MEM_WORDS]; 7197 uint32 mc_entry[SOC_MAX_MEM_WORDS]; 7198 soc_mem_t uc_mem, mc_mem; 7199 7200 if ((index < 0) || (index >= _BCM_MN_NUM_CPRI_CONFIG_NODE)) { 7201 return BCM_E_PARAM; 7202 } 7203 roe_speed_rsvd4 = soc_property_port_get(unit, port, 7204 spn_RSVD4_PORT_INIT_SPEED_ID, -1); 7205 if (roe_speed_rsvd4 != -1) { 7206 node_info = &mtro1_max_bucket_info[0]; 7207 } else { 7208 node_info = &mtro0_max_bucket_info[0]; 7209 if (!eth_mode && (index == 5)) { 7210 index = 8; 7211 } 7212 } 7213 BCM_IF_ERROR_RETURN( 7214 _bcm_mn_cosq_bucket_get(unit, gport, cosq, &min_quantum, 7215 &max_quantum, &kbits_burst_min, 7216 &kbits_burst_max, &flags)); 7217 /* Assign all params */ 7218 max_quantum = node_info[index].rate; 7219 kbits_burst_max = node_info[index].bucket_threshold; 7220 flags = node_info[index].mode; 7221 7222 BCM_IF_ERROR_RETURN( 7223 _bcm_mn_cosq_bucket_set(unit, gport, cosq, min_quantum, 7224 max_quantum, kbits_burst_min, 7225 kbits_burst_max, flags)); 7226 spid = node_info[index].spid; 7227 uc_mem = MMU_THDU_XPIPE_Q_TO_QGRP_MAPm; 7228 mc_mem = MMU_THDM_MCQE_QUEUE_CONFIG_0m; 7229 7230 7231 BCM_IF_ERROR_RETURN(soc_mem_read(unit, uc_mem, MEM_BLOCK_ALL, 7232 uc_index, uc_entry)); 7233 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mc_mem, MEM_BLOCK_ALL, 7234 mc_index, mc_entry)); 7235 7236 soc_mem_field32_set(unit, uc_mem, uc_entry, Q_SPIDf, spid); 7237 soc_mem_field32_set(unit, mc_mem, mc_entry, Q_SPIDf, spid); 7238 7239 BCM_IF_ERROR_RETURN(soc_mem_write(unit, uc_mem, MEM_BLOCK_ALL, 7240 uc_index, uc_entry)); 7241 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mc_mem, MEM_BLOCK_ALL, 7242 mc_index, mc_entry)); 7243 7244 return BCM_E_NONE; 7245 7246 } 7247 7248 int 7249 _bcm_mn_port_hsp_config_set(int unit, 7250 bcm_port_t port) 7251 { 7252 bcm_gport_t port_sched, l0_sched[5]; 7253 bcm_gport_t l1_sched[10]; 7254 bcm_gport_t uc_cosq[10], mc_cosq[10]; 7255 int i, index, cpri_port = 0, uc_index, mc_index; 7256 uint32 num_of_l0 = 5; 7257 uint32 num_of_l1 = 10; 7258 7259 bcm_switch_control_t sc[] = { bcmSwitchPFCClass0Queue, 7260 bcmSwitchPFCClass1Queue, 7261 bcmSwitchPFCClass2Queue, 7262 bcmSwitchPFCClass3Queue, 7263 bcmSwitchPFCClass4Queue, 7264 bcmSwitchPFCClass5Queue, 7265 bcmSwitchPFCClass6Queue, 7266 bcmSwitchPFCClass7Queue 7267 }; 7268 7269 cpri_port = IS_CPRI_PORT(unit, port); 7270 BCM_IF_ERROR_RETURN 7271 (bcm_mn_cosq_gport_add(unit, port, num_of_l0 , 0, &port_sched)); 7272 7273 for (i = 0; i < num_of_l0; i++) { 7274 BCM_IF_ERROR_RETURN 7275 (bcm_mn_cosq_gport_add(unit, port, 8, 7276 BCM_COSQ_GPORT_SCHEDULER, 7277 &l0_sched[i])); 7278 BCM_IF_ERROR_RETURN 7279 (bcm_mn_cosq_gport_attach(unit, l0_sched[i], port_sched, i)); 7280 } 7281 7282 for (i = 0; i < num_of_l1; i++) { 7283 BCM_IF_ERROR_RETURN 7284 (bcm_mn_cosq_gport_add(unit, port, 2, 7285 BCM_COSQ_GPORT_SCHEDULER, 7286 &l1_sched[i])); 7287 if (cpri_port) { 7288 index = i == 0 ? 1 : (i < 8 ? 2 : 4); 7289 } else { 7290 index = i < 8 ? 1 : 4; 7291 } 7292 7293 BCM_IF_ERROR_RETURN 7294 (bcm_mn_cosq_gport_attach(unit, l1_sched[i], l0_sched[index], 7295 i >= 8 ? i - 8 :i)); 7296 BCM_IF_ERROR_RETURN 7297 (bcm_mn_cosq_gport_sched_set(unit, l0_sched[index], (i >= 8 ? i - 8 :i), 7298 BCM_COSQ_DEFICIT_ROUND_ROBIN, 1)); 7299 BCM_IF_ERROR_RETURN 7300 (bcm_mn_cosq_gport_add(unit, port, 1, BCM_COSQ_GPORT_UCAST_QUEUE_GROUP, 7301 &uc_cosq[i])); 7302 BCM_IF_ERROR_RETURN 7303 (bcm_mn_cosq_gport_attach(unit, uc_cosq[i], l1_sched[i], 0)); 7304 BCM_IF_ERROR_RETURN 7305 (bcm_mn_cosq_gport_sched_set(unit, l1_sched[i], 0, 7306 BCM_COSQ_DEFICIT_ROUND_ROBIN, 1)); 7307 BCM_IF_ERROR_RETURN 7308 (bcm_mn_cosq_gport_add(unit, port, 1, BCM_COSQ_GPORT_MCAST_QUEUE_GROUP, 7309 &mc_cosq[i])); 7310 BCM_IF_ERROR_RETURN 7311 (bcm_mn_cosq_gport_attach(unit, mc_cosq[i], l1_sched[i], 1)); 7312 BCM_IF_ERROR_RETURN 7313 (bcm_mn_cosq_gport_sched_set(unit, l1_sched[i], 1, 7314 BCM_COSQ_DEFICIT_ROUND_ROBIN, 1)); 7315 } 7316 if (cpri_port) { 7317 uc_index = BCM_GPORT_UCAST_QUEUE_GROUP_QID_GET(uc_cosq[0]); 7318 mc_index = BCM_GPORT_MCAST_QUEUE_GROUP_QID_GET(mc_cosq[0]); 7319 BCM_IF_ERROR_RETURN( 7320 _bcm_mn_cosq_cpri_gport_init_config(unit, port, port_sched, 7321 2, 0, uc_index, mc_index)); 7322 BCM_IF_ERROR_RETURN( 7323 bcm_esw_port_control_set(unit, port, bcmPortControlLLFCReceive, 1)); 7324 for (i = 1; i < 8; i++) { 7325 uc_index = BCM_GPORT_UCAST_QUEUE_GROUP_QID_GET(uc_cosq[i]); 7326 mc_index = BCM_GPORT_MCAST_QUEUE_GROUP_QID_GET(mc_cosq[i]); 7327 BCM_IF_ERROR_RETURN( 7328 _bcm_mn_cosq_cpri_gport_init_config(unit, port, l0_sched[2], 7329 i, i, uc_index, mc_index)); 7330 BCM_IF_ERROR_RETURN( 7331 bcm_mn_cosq_port_pfc_op(unit, port, sc[i], _BCM_COSQ_OP_ADD, 7332 &l1_sched[i], 1)); 7333 } 7334 } 7335 7336 return BCM_E_NONE; 7337 } 7338 7339 int 7340 bcm_mn_init_fc_map_tbl(int unit) 7341 { 7342 int max_index; 7343 int max_nodes; 7344 uint32 map_entry[SOC_MAX_MEM_WORDS]; 7345 int mem; 7346 int index; 7347 int field ; 7348 static const soc_field_t indexf[] = { 7349 INDEX0f, INDEX1f, INDEX2f, INDEX3f 7350 }; 7351 static const soc_mem_t memx[] = { 7352 MMU_INTFI_XPIPE_FC_MAP_TBL0m, 7353 MMU_INTFI_XPIPE_FC_MAP_TBL1m, 7354 MMU_INTFI_XPIPE_FC_MAP_TBL2m 7355 }; 7356 static const soc_mem_t memy[] = { 7357 MMU_INTFI_FC_ST_TBL0m, 7358 MMU_INTFI_FC_ST_TBL1m, 7359 MMU_INTFI_FC_ST_TBL2m, 7360 }; 7361 7362 for ( mem = 0 ; mem < 3 ; mem++) 7363 { 7364 max_index = soc_mem_index_count(unit, memy[mem]) - 1; 7365 max_nodes = soc_mem_index_count(unit,memx[mem]); 7366 for ( index = 0 ; index < max_nodes ; index++) 7367 { 7368 SOC_IF_ERROR_RETURN(soc_mem_read(unit, memx[mem], 7369 MEM_BLOCK_ALL, index, &map_entry)); 7370 for (field = 0; field < COUNTOF(indexf); field++) 7371 { 7372 soc_mem_field32_set(unit, memx[mem], 7373 &map_entry, indexf[field], max_index); 7374 } 7375 SOC_IF_ERROR_RETURN(soc_mem_write(unit, memx[mem], 7376 MEM_BLOCK_ALL, index, &map_entry)); 7377 } 7378 } 7379 return BCM_E_NONE; 7380 } 7381 STATIC int 7382 _bcm_mn_cpu_port_config_set(int unit, int port) 7383 { 7384 bcm_gport_t port_sched, l0_sched; 7385 bcm_gport_t l1_sched; 7386 bcm_gport_t mc_cosq; 7387 int i, j, k; 7388 uint32 num_of_l0 = 5; 7389 uint32 num_of_l1 = 1; 7390 7391 7392 BCM_IF_ERROR_RETURN 7393 (bcm_mn_cosq_gport_add(unit, port, num_of_l0 , 0, &port_sched)); 7394 7395 for (i = 0; i < num_of_l0; i++) { 7396 if (i == 1) { 7397 num_of_l1 = 4; 7398 } else { 7399 num_of_l1 = 1; 7400 } 7401 BCM_IF_ERROR_RETURN 7402 (bcm_mn_cosq_gport_add(unit, port, num_of_l1, 7403 BCM_COSQ_GPORT_SCHEDULER, 7404 &l0_sched)); 7405 BCM_IF_ERROR_RETURN 7406 (bcm_mn_cosq_gport_attach(unit, l0_sched, port_sched, i)); 7407 if ((i == 0) || (i == 4)) { 7408 continue; 7409 } 7410 for (j = 0; j < num_of_l1; j++) { 7411 BCM_IF_ERROR_RETURN 7412 (bcm_mn_cosq_gport_add(unit, port, 8, 7413 BCM_COSQ_GPORT_SCHEDULER, 7414 &l1_sched)); 7415 BCM_IF_ERROR_RETURN 7416 (bcm_mn_cosq_gport_attach(unit, l1_sched, l0_sched, 7417 j)); 7418 for (k = 0; k < 8; k++) { 7419 BCM_IF_ERROR_RETURN 7420 (bcm_mn_cosq_gport_add(unit, port, 1, BCM_COSQ_GPORT_MCAST_QUEUE_GROUP, 7421 &mc_cosq)); 7422 BCM_IF_ERROR_RETURN 7423 (bcm_mn_cosq_gport_attach(unit, mc_cosq, l1_sched, k)); 7424 } 7425 } 7426 } 7427 return BCM_E_NONE; 7428 } 7429 7430 STATIC int 7431 _bcm_mn_lb_msec_port_config_set(int unit, int port) 7432 { 7433 bcm_gport_t port_sched, l0_sched[5]; 7434 bcm_gport_t l1_sched; 7435 bcm_gport_t mc_cosq; 7436 int i; 7437 uint32 num_of_l0 = 5; 7438 uint32 num_of_l1 = 10; 7439 int index; 7440 7441 7442 BCM_IF_ERROR_RETURN 7443 (bcm_mn_cosq_gport_add(unit, port, num_of_l0 , 0, &port_sched)); 7444 7445 for (i = 0; i < num_of_l0; i++) { 7446 BCM_IF_ERROR_RETURN 7447 (bcm_mn_cosq_gport_add(unit, port, 8, 7448 BCM_COSQ_GPORT_SCHEDULER, 7449 &l0_sched[i])); 7450 BCM_IF_ERROR_RETURN 7451 (bcm_mn_cosq_gport_attach(unit, l0_sched[i], port_sched, i)); 7452 } 7453 7454 for (i = 0; i < num_of_l1; i++) { 7455 BCM_IF_ERROR_RETURN 7456 (bcm_mn_cosq_gport_add(unit, port, 2, 7457 BCM_COSQ_GPORT_SCHEDULER, 7458 &l1_sched)); 7459 index = i < 8 ? 1 : 4; 7460 7461 BCM_IF_ERROR_RETURN 7462 (bcm_mn_cosq_gport_attach(unit, l1_sched, l0_sched[index], 7463 i >= 8 ? i - 8 :i)); 7464 BCM_IF_ERROR_RETURN 7465 (bcm_mn_cosq_gport_sched_set(unit, l0_sched[index], (i >= 8 ? i - 8 :i), 7466 BCM_COSQ_DEFICIT_ROUND_ROBIN, 1)); 7467 BCM_IF_ERROR_RETURN 7468 (bcm_mn_cosq_gport_add(unit, port, 1, BCM_COSQ_GPORT_MCAST_QUEUE_GROUP, 7469 &mc_cosq)); 7470 BCM_IF_ERROR_RETURN 7471 (bcm_mn_cosq_gport_attach(unit, mc_cosq, l1_sched, 1)); 7472 } 7473 return BCM_E_NONE; 7474 } 7475 STATIC int 7476 _bcm_mn_internal_port_config_set(int unit, int port) 7477 { 7478 if (IS_CPU_PORT(unit, port)) { 7479 return _bcm_mn_cpu_port_config_set(unit, port); 7480 } else if (IS_LB_PORT(unit, port) || IS_MACSEC_PORT(unit, port)) { 7481 return _bcm_mn_lb_msec_port_config_set(unit, port); 7482 } else { 7483 return SOC_E_NONE; 7484 } 7485 } 7486 7487 /* 7488 * Function: 7489 * bcm_mn_cosq_default_llfc_profile_attach 7490 * Purpose: 7491 * Add default entries for PRIO2COS_PROFILE register profile 7492 * Parameters: 7493 * unit - (IN) unit number 7494 * port - (IN) port number 7495 * Returns: 7496 * BCM_E_XXX 7497 */ 7498 int 7499 bcm_mn_cosq_default_llfc_profile_attach(int unit, int port) 7500 { 7501 soc_reg_t reg; 7502 soc_info_t *si; 7503 bcm_port_t local_port; 7504 int mmu_port, phy_port; 7505 uint32 profile_index; 7506 uint64 tmp, rval, index_map; 7507 uint64 rval64s[16], *prval64s[1]; 7508 static const soc_reg_t llfc_cfgr[] = { 7509 PORT_PFC_CFG0r, PORT_PFC_CFG1r, PORT_PFC_CFG2r 7510 }; 7511 7512 BCM_IF_ERROR_RETURN( 7513 _bcm_mn_cosq_localport_resolve(unit, port, &local_port)); 7514 7515 si = &SOC_INFO(unit); 7516 phy_port = si->port_l2p_mapping[local_port]; 7517 mmu_port = si->port_p2m_mapping[phy_port]; 7518 reg = llfc_cfgr[mmu_port/32]; 7519 /* Add default entries for PRIO2COS_PROFILE register profile */ 7520 sal_memset(rval64s, 0, sizeof(rval64s)); 7521 prval64s[0] = rval64s; 7522 7523 BCM_IF_ERROR_RETURN 7524 (soc_profile_reg_add(unit, _bcm_mn_llfc_profile[unit], 7525 prval64s, 16, &profile_index)); 7526 7527 BCM_IF_ERROR_RETURN(soc_reg64_get(unit, reg, 0, 0, &rval)); 7528 index_map = soc_reg64_field_get(unit, reg, rval, PROFILE_INDEXf); 7529 7530 COMPILER_64_SET(tmp, 0, 3); 7531 COMPILER_64_SHL(tmp, (mmu_port % 32) * 2); 7532 COMPILER_64_NOT(tmp); 7533 COMPILER_64_AND(index_map, tmp); 7534 COMPILER_64_SET(tmp, 0, profile_index/16); 7535 COMPILER_64_SHL(tmp, (mmu_port % 32) * 2); 7536 COMPILER_64_OR(index_map, tmp); 7537 7538 soc_reg64_field_set(unit, reg, &rval, PROFILE_INDEXf, 7539 index_map); 7540 7541 BCM_IF_ERROR_RETURN(soc_reg64_set(unit, reg, 0, 0, rval)); 7542 7543 return BCM_E_NONE; 7544 } 7545 7546 /* 7547 * Function: 7548 * bcm_mn_cosq_llfc_profile_detach 7549 * Purpose: 7550 * Delete old entries for PRIO2COS_PROFILE register profile 7551 * Parameters: 7552 * unit - (IN) unit number 7553 * port - (IN) port number 7554 * Returns: 7555 * BCM_E_XXX 7556 */ 7557 int 7558 bcm_mn_cosq_llfc_profile_detach(int unit, int port) 7559 { 7560 soc_reg_t reg; 7561 bcm_port_t local_port; 7562 int mmu_port, phy_port; 7563 uint32 old_profile_index; 7564 uint32 tmp32; 7565 uint64 rval, index_map; 7566 soc_info_t *si; 7567 static const soc_reg_t llfc_cfgr[] = { 7568 PORT_PFC_CFG0r, PORT_PFC_CFG1r, PORT_PFC_CFG2r 7569 }; 7570 7571 BCM_IF_ERROR_RETURN( 7572 _bcm_mn_cosq_localport_resolve(unit, port, &local_port)); 7573 7574 si = &SOC_INFO(unit); 7575 phy_port = si->port_l2p_mapping[local_port]; 7576 mmu_port = si->port_p2m_mapping[phy_port]; 7577 7578 reg = llfc_cfgr[mmu_port/32]; 7579 BCM_IF_ERROR_RETURN(soc_reg64_get(unit, reg, 0, 0, &rval)); 7580 7581 index_map = soc_reg64_field_get(unit, reg, rval, PROFILE_INDEXf); 7582 COMPILER_64_SHR(index_map, ((mmu_port % 32) * 2)); 7583 COMPILER_64_TO_32_LO(tmp32, index_map); 7584 old_profile_index = (tmp32 & 3)*16; 7585 7586 BCM_IF_ERROR_RETURN 7587 (soc_profile_reg_delete(unit, _bcm_mn_llfc_profile[unit], 7588 old_profile_index)); 7589 7590 return BCM_E_NONE; 7591 } 7592 7593 7594 7595 /* 7596 * Function: 7597 * bcm_mn_cosq_init 7598 * Purpose: 7599 * Initialize (clear) all COS schedule/mapping state. 7600 * Parameters: 7601 * unit - unit number 7602 * Returns: 7603 * BCM_E_XXX 7604 */ 7605 int 7606 bcm_mn_cosq_init(int unit) 7607 { 7608 int numq, alloc_size, ii, index; 7609 soc_info_t *si; 7610 bcm_port_t port; 7611 soc_reg_t mem; 7612 soc_reg_t reg; 7613 int count; 7614 static soc_field_t wred_fields[6][3] = { 7615 {MIN_THD0f, MAX_THD0f, MAX_DROP_RATE0f}, 7616 {MIN_THD1f, MAX_THD1f, MAX_DROP_RATE1f}, 7617 {MIN_THD2f, MAX_THD2f, MAX_DROP_RATE2f}, 7618 {MIN_THD3f, MAX_THD3f, MAX_DROP_RATE3f}, 7619 {MIN_THD4f, MAX_THD4f, MAX_DROP_RATE4f}, 7620 {MIN_THD5f, MAX_THD5f, MAX_DROP_RATE5f} 7621 }; 7622 static soc_mem_t wred_mems[1] = { 7623 MMU_WRED_DROP_CURVE_PROFILE_0_X_PIPEm 7624 }; 7625 int entry_words[6], pipe; 7626 mmu_wred_drop_curve_profile_0_x_pipe_entry_t entry_tcp_green; 7627 mmu_wred_config_entry_t qentry; 7628 void *entries[6]; 7629 uint32 profile_index; 7630 _bcm_mn_mmu_info_t *mmu_info; 7631 int i, qnum, wred_prof_count; 7632 _bcm_bst_device_handlers_t bst_callbks; 7633 _bcm_mn_pipe_resources_t *pres; 7634 uint64 rval64; 7635 _bcm_mn_cosq_list_t *list = NULL; 7636 int baseq = 0; 7637 int numl2uc = 0; 7638 int phy_port ,mmu_port ; 7639 uint64 rval ; 7640 7641 BCM_IF_ERROR_RETURN (bcm_mn_cosq_detach(unit, 0)); 7642 7643 si = &SOC_INFO(unit); 7644 7645 numq = soc_property_get(unit, spn_BCM_NUM_COS, BCM_COS_DEFAULT); 7646 NUM_COS(unit) = numq; 7647 7648 if (numq < 1) { 7649 numq = 1; 7650 } else if (numq > BCM_MN_COS_MAX) { 7651 numq = BCM_MN_COS_MAX; 7652 } 7653 7654 NUM_COS(unit) = numq; 7655 7656 /* Create profile for PORT_COS_MAP table */ 7657 if (_bcm_mn_cos_map_profile[unit] == NULL) { 7658 _bcm_mn_cos_map_profile[unit] = sal_alloc(sizeof(soc_profile_mem_t), 7659 "COS_MAP Profile Mem"); 7660 if (_bcm_mn_cos_map_profile[unit] == NULL) { 7661 return BCM_E_MEMORY; 7662 } 7663 soc_profile_mem_t_init(_bcm_mn_cos_map_profile[unit]); 7664 } 7665 mem = PORT_COS_MAPm; 7666 entry_words[0] = sizeof(port_cos_map_entry_t) / sizeof(uint32); 7667 BCM_IF_ERROR_RETURN(soc_profile_mem_create(unit, &mem, entry_words, 1, 7668 _bcm_mn_cos_map_profile[unit])); 7669 7670 /* Create profile for IFP_COS_MAP table. */ 7671 if (_bcm_mn_ifp_cos_map_profile[unit] == NULL) { 7672 _bcm_mn_ifp_cos_map_profile[unit] 7673 = sal_alloc(sizeof(soc_profile_mem_t), "IFP_COS_MAP Profile Mem"); 7674 if (_bcm_mn_ifp_cos_map_profile[unit] == NULL) { 7675 return BCM_E_MEMORY; 7676 } 7677 soc_profile_mem_t_init(_bcm_mn_ifp_cos_map_profile[unit]); 7678 } 7679 mem = IFP_COS_MAPm; 7680 entry_words[0] = sizeof(ifp_cos_map_entry_t) / sizeof(uint32); 7681 SOC_IF_ERROR_RETURN 7682 (soc_profile_mem_create(unit, &mem, entry_words, 1, 7683 _bcm_mn_ifp_cos_map_profile[unit])); 7684 7685 /* Create profile for PRIO2COS_PROFILE register */ 7686 if (_bcm_mn_llfc_profile[unit] == NULL) { 7687 _bcm_mn_llfc_profile[unit] = 7688 sal_alloc(sizeof(soc_profile_reg_t), "PRIO2COS_LLFC Profile Reg"); 7689 if (_bcm_mn_llfc_profile[unit] == NULL) { 7690 return BCM_E_MEMORY; 7691 } 7692 soc_profile_reg_t_init(_bcm_mn_llfc_profile[unit]); 7693 } 7694 7695 alloc_size = sizeof(_bcm_mn_mmu_info_t) * 1; 7696 if (_bcm_mn_mmu_info[unit] == NULL) { 7697 _bcm_mn_mmu_info[unit] = 7698 sal_alloc(alloc_size, "_bcm_mn_mmu_info"); 7699 7700 if (_bcm_mn_mmu_info[unit] == NULL) { 7701 return BCM_E_MEMORY; 7702 } 7703 7704 sal_memset(_bcm_mn_mmu_info[unit], 0, alloc_size); 7705 } 7706 reg = PRIO2COS_PROFILEr; 7707 BCM_IF_ERROR_RETURN 7708 (soc_profile_reg_create(unit, ®, 1, _bcm_mn_llfc_profile[unit])); 7709 /* Add default entries for PRIO2COS_PROFILE register profile */ 7710 PBMP_PORT_ITER(unit, port) { 7711 BCM_IF_ERROR_RETURN(bcm_mn_cosq_default_llfc_profile_attach(unit, port)); 7712 } 7713 mmu_info = _bcm_mn_mmu_info[unit]; 7714 mmu_info->ets_mode = 0; 7715 mmu_info->pipe_resources[_MN_XPIPE].num_base_queues = 0; 7716 7717 if (soc_feature(unit, soc_feature_mmu_3k_uc_queue)) { 7718 mmu_info->num_l2_queues = _BCM_MN_NUM_L2_UC_LEAVES_PER_PIPE; 7719 } else if (soc_feature(unit, soc_feature_mmu_1k_uc_queue)) { 7720 mmu_info->num_l2_queues = _BCM_MN_NUM_L2_UC_LEAVES_PER_PIPE; 7721 } else { 7722 mmu_info->num_l2_queues = _BCM_MN_NUM_L2_UC_LEAVES_PER_PIPE; 7723 } 7724 7725 for (pipe = _MN_XPIPE; pipe < _MN_YPIPE; pipe++) { 7726 pres = _BCM_MN_PRESOURCES(mmu_info, pipe); 7727 pres->p_queue_node = &mmu_info->queue_node[0]; 7728 pres->p_mc_queue_node = &mmu_info->mc_queue_node[0]; 7729 pres->l2_queue_list.count = mmu_info->num_l2_queues; 7730 pres->l2_queue_list.bits = _bcm_mn_cosq_alloc_clear( 7731 pres->l2_queue_list.bits, 7732 SHR_BITALLOCSIZE(mmu_info->num_l2_queues), 7733 "l2_queue_list"); 7734 if (pres->l2_queue_list.bits == NULL) { 7735 _bcm_mn_cosq_free_memory(mmu_info); 7736 return BCM_E_MEMORY; 7737 } 7738 7739 pres->l0_sched_list.count = _BCM_MN_NUM_L0_SCHEDULER_PER_PIPE; 7740 pres->l0_sched_list.bits = _bcm_mn_cosq_alloc_clear( 7741 pres->l0_sched_list.bits, 7742 SHR_BITALLOCSIZE(_BCM_MN_NUM_L0_SCHEDULER_PER_PIPE), 7743 "l0_sched_list"); 7744 if (pres->l0_sched_list.bits == NULL) { 7745 _bcm_mn_cosq_free_memory(mmu_info); 7746 return BCM_E_MEMORY; 7747 } 7748 7749 pres->l1_sched_list.count = _BCM_MN_NUM_L1_SCHEDULER_PER_PIPE; 7750 pres->l1_sched_list.bits = _bcm_mn_cosq_alloc_clear( 7751 pres->l1_sched_list.bits, 7752 SHR_BITALLOCSIZE(_BCM_MN_NUM_L1_SCHEDULER_PER_PIPE), 7753 "l1_sched_list"); 7754 if (pres->l1_sched_list.bits == NULL) { 7755 _bcm_mn_cosq_free_memory(mmu_info); 7756 return BCM_E_MEMORY; 7757 } 7758 pres->s1_sched_list.count = _BCM_MN_NUM_S1_SCHEDULER_PER_PIPE; 7759 pres->s1_sched_list.bits = _bcm_mn_cosq_alloc_clear( 7760 pres->s1_sched_list.bits, 7761 SHR_BITALLOCSIZE(_BCM_MN_NUM_S1_SCHEDULER_PER_PIPE), 7762 "s1_sched_list"); 7763 if (pres->s1_sched_list.bits == NULL) { 7764 _bcm_mn_cosq_free_memory(mmu_info); 7765 return BCM_E_MEMORY; 7766 } 7767 7768 } 7769 /* assign queues to ports */ 7770 PBMP_ALL_ITER(unit, port) { 7771 pipe = _BCM_MN_PORT_TO_PIPE(unit, port); 7772 7773 if ((SOC_WARM_BOOT(unit) && !IS_LB_PORT(unit, port)) && 7774 ! IS_CPU_PORT(unit, port)) { 7775 if(IS_MN_HSP_PORT(unit, port)) { 7776 numl2uc = 10; 7777 } else { 7778 numl2uc = soc_property_port_get(unit, port, spn_LLS_NUM_L2UC, 16); 7779 } 7780 if (numl2uc < 10 || numl2uc > 16) { 7781 numl2uc = 10; 7782 } 7783 phy_port = si->port_l2p_mapping[port]; 7784 mmu_port = si->port_p2m_mapping[phy_port]; 7785 COMPILER_64_ZERO(rval); 7786 BCM_IF_ERROR_RETURN(READ_ING_COS_MODE_64r(unit, port, &rval)); 7787 baseq = soc_reg64_field32_get(unit, ING_COS_MODE_64r, rval, 7788 BASE_QUEUE_NUM_0f); 7789 si->port_num_cosq[port] = 10; 7790 si->port_cosq_base[port] = (mmu_port * si->port_num_cosq[port]) ; 7791 si->port_num_uc_cosq[port] = numl2uc ; 7792 si->port_uc_cosq_base[port] = baseq; 7793 } 7794 mmu_info->port_info[port].resources = &mmu_info->pipe_resources[pipe]; 7795 mmu_info->port_info[port].mc_base = si->port_cosq_base[port]; 7796 mmu_info->port_info[port].mc_limit = si->port_cosq_base[port] + 7797 si->port_num_cosq[port]; 7798 7799 mmu_info->port_info[port].uc_base = si->port_uc_cosq_base[port]; 7800 mmu_info->port_info[port].uc_limit = si->port_uc_cosq_base[port] + 7801 si->port_num_uc_cosq[port]; 7802 if (mmu_info->port_info[port].resources->num_base_queues < 7803 mmu_info->port_info[port].uc_limit) { 7804 mmu_info->port_info[port].resources->num_base_queues = 7805 mmu_info->port_info[port].uc_limit; 7806 } 7807 if (!SOC_WARM_BOOT(unit)) { 7808 COMPILER_64_ZERO(rval64); 7809 if(IS_MN_HSP_PORT(unit, port)) { 7810 SOC_IF_ERROR_RETURN(soc_monterey_sched_hw_index_get(unit, 7811 port, SOC_MONTEREY_NODE_LVL_L1, 0, &qnum)); 7812 } else { 7813 qnum = soc_monterey_logical_qnum_hw_qnum(unit, port, 7814 si->port_uc_cosq_base[port], 1); 7815 } 7816 soc_reg64_field32_set(unit, ING_COS_MODE_64r, 7817 &rval64, BASE_QUEUE_NUM_0f, qnum); 7818 soc_reg64_field32_set(unit, ING_COS_MODE_64r, 7819 &rval64, BASE_QUEUE_NUM_1f, qnum); 7820 BCM_IF_ERROR_RETURN(soc_reg_set(unit, ING_COS_MODE_64r, port, 0, rval64)); 7821 } 7822 } 7823 7824 7825 for (i = 0; i < _BCM_MN_NUM_TOTAL_SCHEDULERS; i++) { 7826 _BCM_MN_COSQ_LIST_NODE_INIT(mmu_info->sched_node, i); 7827 } 7828 7829 for (i = 0; i < _BCM_MN_NUM_L2_UC_LEAVES; i++) { 7830 _BCM_MN_COSQ_LIST_NODE_INIT(mmu_info->queue_node, i); 7831 } 7832 7833 for (i = 0; i < _BCM_MN_NUM_L2_MC_LEAVES; i++) { 7834 _BCM_MN_COSQ_LIST_NODE_INIT(mmu_info->mc_queue_node, i); 7835 } 7836 7837 for (pipe = _MN_XPIPE; pipe < _MN_YPIPE; pipe++) { 7838 pres = _BCM_MN_PRESOURCES(mmu_info, pipe); 7839 for (i = SOC_MONTEREY_NODE_LVL_L0; i <= SOC_MONTEREY_NODE_LVL_L2; i++) { 7840 index = _soc_monterey_invalid_parent_index(unit, i); 7841 if (i == SOC_MONTEREY_NODE_LVL_L0) { 7842 list = &pres->s1_sched_list; 7843 } else if (i == SOC_MONTEREY_NODE_LVL_L1) { 7844 list = &pres->l0_sched_list; 7845 } else if (i == SOC_MONTEREY_NODE_LVL_L2) { 7846 list = &pres->l1_sched_list; 7847 } else { 7848 continue; 7849 } 7850 if (index >= 0) { 7851 _bcm_mn_node_index_set(list, index, 1); 7852 } 7853 } 7854 } 7855 7856 /* reserve the resources for HSP ports */ 7857 count = _BCM_MN_HSP_PORT_MAX_ROOT; 7858 7859 for (pipe = _MN_XPIPE; pipe < _MN_YPIPE; pipe++) { 7860 pres = _BCM_MN_PRESOURCES(mmu_info, pipe); 7861 _bcm_mn_node_index_set(&pres->l0_sched_list, 0, 5 * count); 7862 _bcm_mn_node_index_set(&pres->l1_sched_list, 0, 10 * count); 7863 _bcm_mn_node_index_set(&pres->l2_queue_list, 0, 10 * count); 7864 7865 pres->cpu_l0_sched_list.count = (_BCM_MN_CPU_PORT_L0_MAX - 7866 _BCM_MN_CPU_PORT_L0_MIN); 7867 pres->cpu_l0_sched_list.bits = _bcm_mn_cosq_alloc_clear( 7868 pres->cpu_l0_sched_list.bits, 7869 SHR_BITALLOCSIZE(pres->cpu_l0_sched_list.count), 7870 "cpu_l0_sched_list"); 7871 if (pres->cpu_l0_sched_list.bits == NULL) { 7872 _bcm_mn_cosq_free_memory(mmu_info); 7873 return BCM_E_MEMORY; 7874 } 7875 _bcm_mn_node_index_set(&pres->l0_sched_list, _BCM_MN_CPU_PORT_L0_MIN, 7876 pres->cpu_l0_sched_list.count); 7877 7878 7879 7880 7881 if (count > 0) { 7882 pres->hsp_l0_sched_list.count = 5 * count; 7883 pres->hsp_l0_sched_list.bits = _bcm_mn_cosq_alloc_clear( 7884 pres->hsp_l0_sched_list.bits, 7885 SHR_BITALLOCSIZE(pres->hsp_l0_sched_list.count), 7886 "hsp_l0_sched_list"); 7887 if (pres->hsp_l0_sched_list.bits == NULL) { 7888 _bcm_mn_cosq_free_memory(mmu_info); 7889 return BCM_E_MEMORY; 7890 } 7891 pres->hsp_l1_sched_list.count = 10 * count; 7892 pres->hsp_l1_sched_list.bits = _bcm_mn_cosq_alloc_clear( 7893 pres->hsp_l1_sched_list.bits, 7894 SHR_BITALLOCSIZE(pres->hsp_l1_sched_list.count), 7895 "hsp_l1_sched_list"); 7896 if (pres->hsp_l1_sched_list.bits == NULL) { 7897 _bcm_mn_cosq_free_memory(mmu_info); 7898 return BCM_E_MEMORY; 7899 } 7900 pres->hsp_l2_queue_list.count = 10 * count; 7901 pres->hsp_l2_queue_list.bits = _bcm_mn_cosq_alloc_clear( 7902 pres->hsp_l2_queue_list.bits, 7903 SHR_BITALLOCSIZE(pres->hsp_l2_queue_list.count), 7904 "hsp_l2_queue_list"); 7905 if (pres->hsp_l2_queue_list.bits == NULL) { 7906 _bcm_mn_cosq_free_memory(mmu_info); 7907 return BCM_E_MEMORY; 7908 } 7909 } 7910 } 7911 7912 for (pipe = _MN_XPIPE; pipe < _MN_YPIPE; pipe++) { 7913 pres = _BCM_MN_PRESOURCES(mmu_info, pipe); 7914 PBMP_ALL_ITER(unit, port) { 7915 _bcm_mn_node_index_set(&pres->l2_queue_list, 7916 mmu_info->port_info[port].uc_base, 7917 si->port_num_uc_cosq[port]); 7918 } 7919 } 7920 7921 /* Initialize oob driver */ 7922 BCM_IF_ERROR_RETURN(_bcm_oob_init(unit)); 7923 7924 /* Create profile for MMU_WRED_DROP_CURVE_PROFILE_x tables */ 7925 if (_bcm_mn_wred_profile[unit] == NULL) { 7926 _bcm_mn_wred_profile[unit] = 7927 sal_alloc(sizeof(soc_profile_mem_t), "WRED Profile Mem"); 7928 if (_bcm_mn_wred_profile[unit] == NULL) { 7929 return BCM_E_MEMORY; 7930 } 7931 soc_profile_mem_t_init(_bcm_mn_wred_profile[unit]); 7932 } 7933 7934 entry_words[0] = 7935 sizeof(mmu_wred_drop_curve_profile_0_x_pipe_entry_t) / sizeof(uint32); 7936 BCM_IF_ERROR_RETURN 7937 (soc_profile_mem_create(unit, wred_mems, entry_words, 1, 7938 _bcm_mn_wred_profile[unit])); 7939 7940 sal_memset(&bst_callbks, 0, sizeof(_bcm_bst_device_handlers_t)); 7941 bst_callbks.resolve_index = &_bcm_mn_bst_index_resolve; 7942 bst_callbks.reverse_resolve_index = &_bcm_mn_cosq_bst_map_resource_to_gport_cos; 7943 BCM_IF_ERROR_RETURN(_bcm_bst_attach(unit, &bst_callbks)); 7944 7945 7946 for (i = 0; i < si->num_cpu_cosq; i++) { 7947 if (_bcm_mn_cosq_cpu_cosq_config[unit][i] == NULL) { 7948 _bcm_mn_cosq_cpu_cosq_config[unit][i] = 7949 sal_alloc(sizeof(_bcm_mn_cosq_cpu_cosq_config_t), "CPU Cosq Config"); 7950 7951 if (_bcm_mn_cosq_cpu_cosq_config[unit][i] == NULL) { 7952 return BCM_E_MEMORY; 7953 } 7954 sal_memset(_bcm_mn_cosq_cpu_cosq_config[unit][i], 0, 7955 sizeof(_bcm_mn_cosq_cpu_cosq_config_t)); 7956 _bcm_mn_cosq_cpu_cosq_config[unit][i]->enable = 1; 7957 } 7958 } 7959 7960 #ifdef BCM_WARM_BOOT_SUPPORT 7961 if (SOC_WARM_BOOT(unit)) { 7962 return bcm_mn_cosq_reinit(unit); 7963 } else { 7964 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_wb_alloc(unit)); 7965 } 7966 #endif /* BCM_WARM_BOOT_SUPPORT */ 7967 PBMP_ALL_ITER(unit, port) { 7968 if (!IS_MN_HSP_PORT( unit, port)) { 7969 continue; 7970 } 7971 if (IS_SPECIAL_PORT(unit, port)) { 7972 SOC_IF_ERROR_RETURN( 7973 _bcm_mn_internal_port_config_set(unit, port)); 7974 continue; 7975 } 7976 BCM_IF_ERROR_RETURN (_bcm_mn_port_hsp_config_set(unit, port)); 7977 } 7978 7979 sal_memset(&entry_tcp_green, 0, sizeof(entry_tcp_green)); 7980 entries[0] = &entry_tcp_green; 7981 for (ii = 0; ii < 6; ii++) { 7982 soc_mem_field32_set(unit, MMU_WRED_DROP_CURVE_PROFILE_0_X_PIPEm, entries[0], 7983 wred_fields[ii][0], 0x1ffff); 7984 soc_mem_field32_set(unit, MMU_WRED_DROP_CURVE_PROFILE_0_X_PIPEm, entries[0], 7985 wred_fields[ii][1], 0x1ffff); 7986 } 7987 profile_index = 0xffffffff; 7988 wred_prof_count = soc_mem_index_count(unit, MMU_WRED_CONFIG_X_PIPEm); 7989 while(wred_prof_count) { 7990 if (profile_index == 0xffffffff) { 7991 BCM_IF_ERROR_RETURN 7992 (soc_profile_mem_add(unit, 7993 _bcm_mn_wred_profile[unit], 7994 entries, 1, &profile_index)); 7995 } else { 7996 BCM_IF_ERROR_RETURN 7997 (soc_profile_mem_reference(unit, 7998 _bcm_mn_wred_profile[unit], 7999 profile_index, 0)); 8000 } 8001 wred_prof_count -= 1; 8002 8003 /* During rc these entry needs to be reset */ 8004 BCM_IF_ERROR_RETURN 8005 (soc_mem_read(unit, MMU_WRED_CONFIG_X_PIPEm, MEM_BLOCK_ALL, wred_prof_count, &qentry)); 8006 soc_mem_field32_set(unit, MMU_WRED_CONFIG_X_PIPEm, &qentry, PROFILE_INDEXf, profile_index); 8007 soc_mem_field32_set(unit, MMU_WRED_CONFIG_X_PIPEm, &qentry, WEIGHTf, 0); 8008 soc_mem_field32_set(unit, MMU_WRED_CONFIG_X_PIPEm, &qentry, CAP_AVERAGEf, 0); 8009 soc_mem_field32_set(unit, MMU_WRED_CONFIG_X_PIPEm, &qentry, WRED_ENf, 0); 8010 soc_mem_field32_set(unit, MMU_WRED_CONFIG_X_PIPEm, &qentry, ECN_MARKING_ENf, 0); 8011 soc_mem_field32_set(unit, MMU_WRED_CONFIG_X_PIPEm, &qentry, TIME_DOMAIN_SELf, 0); 8012 BCM_IF_ERROR_RETURN 8013 (soc_mem_write(unit, MMU_WRED_CONFIG_X_PIPEm, MEM_BLOCK_ALL, wred_prof_count, &qentry)); 8014 } 8015 SOC_IF_ERROR_RETURN(WRITE_TIME_DOMAINr(unit, 0)); 8016 time_domain_mn[0].ref_count = 1040; 8017 time_domain_mn[1].ref_count = 0; 8018 time_domain_mn[2].ref_count = 0; 8019 time_domain_mn[3].ref_count = 0; 8020 /* Add default entries for PORT_COS_MAP memory profile */ 8021 BCM_IF_ERROR_RETURN(bcm_mn_cosq_config_set(unit, numq)); 8022 8023 /* Starting the curr_merger_index from 2, 8024 * since 0 is configured in all the FC_MAP_TBL2 by default, 8025 * so it might effect the traffic of other queues 8026 */ 8027 mmu_info->curr_merger_index = 2; 8028 if (!mmu_info->curr_shared_limit) { 8029 BCM_IF_ERROR_RETURN(soc_monterey_mmu_get_shared_size(unit, 8030 &mmu_info->curr_shared_limit)); 8031 } 8032 BCM_IF_ERROR_RETURN(bcm_mn_init_fc_map_tbl(unit)); 8033 BCM_IF_ERROR_RETURN(soc_monterey_shadow_create(unit)); 8034 return BCM_E_NONE; 8035 } 8036 8037 8038 /* 8039 * Function: 8040 * bcm_mn_cosq_config_get 8041 * Purpose: 8042 * Get the number of cos queues 8043 * Parameters: 8044 * unit - unit number 8045 * numq - (Output) number of cosq 8046 * Returns: 8047 * BCM_E_XXX 8048 */ 8049 int 8050 bcm_mn_cosq_config_get(int unit, int *numq) 8051 { 8052 if (numq != NULL) { 8053 *numq = _MN_NUM_COS(unit); 8054 } 8055 8056 return BCM_E_NONE; 8057 } 8058 8059 /* 8060 * Function: 8061 * _bcm_mn_cosq_mapping_set 8062 * Purpose: 8063 * Set COS queue for the specified priority of an ingress port 8064 * Parameters: 8065 * unit - (IN) unit number 8066 * ing_port - (IN) ingress port 8067 * gport - (IN) queue group GPORT identifier 8068 * priority - (IN) priority value to map 8069 * flags - (IN) BCM_COSQ_GPORT_XXX_QUEUE_GROUP 8070 * gport - (IN) queue group GPORT identifier 8071 * cosq - (IN) COS queue number 8072 * Returns: 8073 * BCM_E_XXX 8074 */ 8075 STATIC int 8076 _bcm_mn_cosq_mapping_set(int unit, bcm_port_t ing_port, bcm_cos_t priority, 8077 uint32 flags, bcm_gport_t gport, bcm_cos_queue_t cosq) 8078 { 8079 bcm_port_t local_port, outport = -1; 8080 bcm_cos_queue_t hw_cosq; 8081 soc_field_t field = INVALIDf, field2 = INVALIDf, field3 = INVALIDf; 8082 cos_map_sel_entry_t cos_map_sel_entry; 8083 port_cos_map_entry_t cos_map_entries[16]; 8084 void *entries[1]; 8085 uint32 old_index, new_index, max_val; 8086 voq_cos_map_entry_t voq_cos_map; 8087 int rv; 8088 int valid = 0; 8089 8090 if (priority < 0 || priority >= 16) { 8091 return BCM_E_PARAM; 8092 } 8093 8094 BCM_IF_ERROR_RETURN 8095 (_bcm_mn_cosq_localport_resolve(unit, ing_port, &local_port)); 8096 8097 if (gport != -1) { 8098 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_localport_resolve(unit, gport, &outport)); 8099 } 8100 8101 8102 switch (flags) { 8103 case BCM_COSQ_GPORT_UCAST_QUEUE_GROUP: 8104 if (gport == -1) { 8105 hw_cosq = cosq; 8106 } else { 8107 BCM_IF_ERROR_RETURN 8108 (_bcm_mn_cosq_index_resolve 8109 (unit, gport, cosq, _BCM_MN_COSQ_INDEX_STYLE_COS, 8110 NULL, &hw_cosq, NULL)); 8111 8112 } 8113 if ((outport != -1) && (IS_HG_PORT(unit, outport))) { 8114 field = HG_COSf; 8115 } else { 8116 field = UC_COS1f; 8117 } 8118 break; 8119 case BCM_COSQ_GPORT_MCAST_QUEUE_GROUP: 8120 if (gport == -1) { 8121 hw_cosq = cosq; 8122 } else { 8123 BCM_IF_ERROR_RETURN 8124 (_bcm_mn_cosq_index_resolve 8125 (unit, gport, cosq, _BCM_MN_COSQ_INDEX_STYLE_COS, 8126 NULL, &hw_cosq, NULL)); 8127 } 8128 field = MC_COS1f; 8129 field2 = RQE_Q_NUMf; 8130 break; 8131 case BCM_COSQ_GPORT_UCAST_QUEUE_GROUP | BCM_COSQ_GPORT_MCAST_QUEUE_GROUP: 8132 if (gport == -1) { 8133 hw_cosq = cosq; 8134 } else { 8135 return BCM_E_PARAM; 8136 } 8137 field = UC_COS1f; 8138 field2 = MC_COS1f; 8139 field3 = RQE_Q_NUMf; 8140 break; 8141 case BCM_COSQ_GPORT_DESTMOD_UCAST_QUEUE_GROUP: 8142 if (gport == -1) { 8143 hw_cosq = cosq; 8144 } else { 8145 BCM_IF_ERROR_RETURN 8146 (_bcm_mn_cosq_index_resolve 8147 (unit, gport, cosq, _BCM_MN_COSQ_INDEX_STYLE_COS, 8148 NULL, &hw_cosq, NULL)); 8149 } 8150 8151 BCM_IF_ERROR_RETURN( 8152 READ_VOQ_COS_MAPm(unit, MEM_BLOCK_ALL, priority, &voq_cos_map)); 8153 valid = soc_mem_field32_get(unit, VOQ_COS_MAPm, &voq_cos_map, 8154 VOQ_COS_USE_MODf); 8155 8156 /* Setting the VOQ_PORT_BASE_SELECT, 8157 so that BASE_QUEUE_NUM_1 is used for queue 8158 calculation */ 8159 8160 soc_mem_field32_set(unit, VOQ_COS_MAPm, 8161 &voq_cos_map, VOQ_PORT_BASE_SELECTf, 1); 8162 soc_mem_field32_set(unit, VOQ_COS_MAPm, 8163 &voq_cos_map, VOQ_COS_USE_MODf, 1); 8164 8165 if (valid && (soc_mem_field32_get(unit, VOQ_COS_MAPm, &voq_cos_map, 8166 VOQ_COS_OFFSETf) != hw_cosq)) { 8167 soc_mem_field32_set(unit, VOQ_COS_MAPm, 8168 &voq_cos_map, VOQ_COS_OFFSETf, hw_cosq); 8169 } 8170 BCM_IF_ERROR_RETURN( 8171 soc_mem_write(unit, VOQ_COS_MAPm, MEM_BLOCK_ANY, priority, 8172 &voq_cos_map)); 8173 return BCM_E_NONE; 8174 break; 8175 default: 8176 return BCM_E_PARAM; 8177 } 8178 8179 entries[0] = &cos_map_entries; 8180 8181 BCM_IF_ERROR_RETURN 8182 (READ_COS_MAP_SELm(unit, MEM_BLOCK_ANY, local_port, 8183 &cos_map_sel_entry)); 8184 old_index = soc_mem_field32_get(unit, COS_MAP_SELm, &cos_map_sel_entry, 8185 SELECTf); 8186 old_index *= 16; 8187 8188 BCM_IF_ERROR_RETURN 8189 (soc_profile_mem_get(unit, _bcm_mn_cos_map_profile[unit], 8190 old_index, 16, entries)); 8191 max_val = soc_property_port_get(unit, local_port, spn_LLS_NUM_L2UC, 16); 8192 if (hw_cosq < 0 || hw_cosq >= max_val) { 8193 return BCM_E_PARAM; 8194 } 8195 8196 soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[priority], field, 8197 hw_cosq); 8198 if (field2 != INVALIDf) { 8199 soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[priority], 8200 field2, hw_cosq); 8201 } 8202 if (field3 != INVALIDf) { 8203 soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[priority], 8204 field3, hw_cosq); 8205 } 8206 8207 soc_mem_lock(unit, PORT_COS_MAPm); 8208 8209 rv = soc_profile_mem_delete(unit, _bcm_mn_cos_map_profile[unit], 8210 old_index); 8211 if (BCM_FAILURE(rv)) { 8212 soc_mem_unlock(unit, PORT_COS_MAPm); 8213 return rv; 8214 } 8215 8216 rv = soc_profile_mem_add(unit, _bcm_mn_cos_map_profile[unit], entries, 8217 16, &new_index); 8218 8219 soc_mem_unlock(unit, PORT_COS_MAPm); 8220 8221 if (BCM_FAILURE(rv)) { 8222 return rv; 8223 } 8224 8225 soc_mem_field32_set(unit, COS_MAP_SELm, &cos_map_sel_entry, SELECTf, 8226 new_index / 16); 8227 BCM_IF_ERROR_RETURN 8228 (WRITE_COS_MAP_SELm(unit, MEM_BLOCK_ANY, local_port, 8229 &cos_map_sel_entry)); 8230 8231 #ifndef BCM_COSQ_HIGIG_MAP_DISABLE 8232 if (IS_CPU_PORT(unit, local_port)) { 8233 BCM_IF_ERROR_RETURN 8234 (soc_mem_field32_modify(unit, COS_MAP_SELm, 8235 SOC_INFO(unit).cpu_hg_index, SELECTf, 8236 new_index / 16)); 8237 } 8238 #endif /* BCM_COSQ_HIGIG_MAP_DISABLE */ 8239 8240 return BCM_E_NONE; 8241 } 8242 8243 /* 8244 * Function: 8245 * bcm_mn_cosq_mapping_set 8246 * Purpose: 8247 * Set which cosq a given priority should fall into 8248 * Parameters: 8249 * unit - (IN) unit number 8250 * gport - (IN) queue group GPORT identifier 8251 * priority - (IN) priority value to map 8252 * cosq - (IN) COS queue to map to 8253 * Returns: 8254 * BCM_E_XXX 8255 */ 8256 8257 int 8258 bcm_mn_cosq_mapping_set(int unit, bcm_port_t port, bcm_cos_t priority, 8259 bcm_cos_queue_t cosq) 8260 { 8261 bcm_pbmp_t pbmp, pbmp1; 8262 bcm_port_t local_port; 8263 8264 BCM_PBMP_CLEAR(pbmp); 8265 BCM_PBMP_CLEAR(pbmp1); 8266 8267 if (port == -1) { 8268 BCM_PBMP_ASSIGN(pbmp, PBMP_ALL(unit)); 8269 BCM_PBMP_ASSIGN(pbmp1, PBMP_HG_ALL(unit)); 8270 BCM_PBMP_REMOVE(pbmp, pbmp1); 8271 } else { 8272 if (BCM_GPORT_IS_SET(port)) { 8273 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 8274 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) || 8275 BCM_GPORT_IS_SCHEDULER(port)) { 8276 return BCM_E_PARAM; 8277 } else if (BCM_GPORT_IS_LOCAL(port)) { 8278 local_port = BCM_GPORT_LOCAL_GET(port); 8279 } else if (BCM_GPORT_IS_MODPORT(port)) { 8280 BCM_IF_ERROR_RETURN( 8281 bcm_esw_port_local_get(unit, port, &local_port)); 8282 } else { 8283 return BCM_E_PARAM; 8284 } 8285 } else { 8286 local_port = port; 8287 } 8288 8289 if (!SOC_PORT_VALID(unit, local_port)) { 8290 return BCM_E_PORT; 8291 } 8292 8293 BCM_PBMP_PORT_ADD(pbmp, local_port); 8294 } 8295 8296 PBMP_ITER(pbmp, local_port) { 8297 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_port_has_ets(unit, local_port)); 8298 } 8299 8300 if ((cosq < 0) || (cosq >= _MN_NUM_COS(unit))) { 8301 return BCM_E_PARAM; 8302 } 8303 8304 PBMP_ITER(pbmp, local_port) { 8305 if (IS_LB_PORT(unit, local_port)) { 8306 continue; 8307 } 8308 8309 /* If no ETS/gport, map the int prio symmetrically for ucast and 8310 * mcast */ 8311 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_mapping_set(unit, local_port, 8312 priority, 8313 BCM_COSQ_GPORT_UCAST_QUEUE_GROUP | 8314 BCM_COSQ_GPORT_MCAST_QUEUE_GROUP, 8315 -1, cosq)); 8316 } 8317 8318 PBMP_ITER(pbmp1, local_port) { 8319 if (IS_LB_PORT(unit, local_port)) { 8320 continue; 8321 } 8322 8323 /* If no ETS/gport, map the int prio symmetrically for ucast and 8324 * mcast */ 8325 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_mapping_set(unit, local_port, 8326 priority, 8327 BCM_COSQ_GPORT_UCAST_QUEUE_GROUP | 8328 BCM_COSQ_GPORT_MCAST_QUEUE_GROUP, 8329 -1, cosq)); 8330 } 8331 return BCM_E_NONE; 8332 } 8333 8334 /* 8335 * Function: 8336 * bcm_mn_cosq_mapping_get 8337 * Purpose: 8338 * Determine which COS queue a given priority currently maps to. 8339 * Parameters: 8340 * unit - (IN) unit number 8341 * gport - (IN) queue group GPORT identifier 8342 * priority - (IN) priority value to map 8343 * cosq - (OUT) COS queue to map to 8344 * Returns: 8345 * BCM_E_XXX 8346 */ 8347 int 8348 _bcm_mn_cosq_mapping_get(int unit, bcm_port_t ing_port, bcm_cos_t priority, 8349 uint32 flags, bcm_gport_t *gport, 8350 bcm_cos_queue_t *cosq) 8351 { 8352 _bcm_mn_mmu_info_t *mmu_info; 8353 _bcm_mn_pipe_resources_t *res; 8354 _bcm_mn_cosq_port_info_t *port_info; 8355 _bcm_mn_cosq_node_t *node; 8356 bcm_port_t local_port; 8357 bcm_cos_queue_t hw_cosq = BCM_COS_INVALID; 8358 int index, ii; 8359 cos_map_sel_entry_t cos_map_sel_entry; 8360 voq_cos_map_entry_t voq_cos_map; 8361 void *entry_p; 8362 8363 if (priority < 0 || priority >= 16) { 8364 return BCM_E_PARAM; 8365 } 8366 8367 if (flags != BCM_COSQ_GPORT_UCAST_QUEUE_GROUP && 8368 flags != BCM_COSQ_GPORT_MCAST_QUEUE_GROUP && 8369 flags != BCM_COSQ_GPORT_DESTMOD_UCAST_QUEUE_GROUP) { 8370 return BCM_E_PARAM; 8371 } 8372 8373 BCM_IF_ERROR_RETURN 8374 (_bcm_mn_cosq_localport_resolve(unit, ing_port, &local_port)); 8375 8376 if (gport) { 8377 *gport = BCM_GPORT_INVALID; 8378 } 8379 8380 *cosq = BCM_COS_INVALID; 8381 8382 BCM_IF_ERROR_RETURN 8383 (READ_COS_MAP_SELm(unit, MEM_BLOCK_ANY, local_port, 8384 &cos_map_sel_entry)); 8385 index = soc_mem_field32_get(unit, COS_MAP_SELm, &cos_map_sel_entry, 8386 SELECTf); 8387 index *= 16; 8388 8389 entry_p = SOC_PROFILE_MEM_ENTRY(unit, _bcm_mn_cos_map_profile[unit], 8390 port_cos_map_entry_t *, 8391 index + priority); 8392 8393 mmu_info = _bcm_mn_mmu_info[unit]; 8394 port_info = &mmu_info->port_info[local_port]; 8395 res = _BCM_MN_PRESOURCES(mmu_info, _BCM_MN_PORT_TO_PIPE(unit, local_port)); 8396 8397 switch (flags) { 8398 case BCM_COSQ_GPORT_UCAST_QUEUE_GROUP: 8399 hw_cosq = soc_mem_field32_get(unit, PORT_COS_MAPm, entry_p, UC_COS1f); 8400 if ((IS_CPU_PORT(unit, local_port) == FALSE) && gport) { 8401 for (ii = port_info->uc_base; ii < port_info->uc_limit; ii++) { 8402 node = &mmu_info->queue_node[ii]; 8403 if (node->numq > 0 && node->hw_cosq == hw_cosq) { 8404 *gport = node->gport; 8405 *cosq = 0; 8406 break; 8407 } 8408 } 8409 if (ii == port_info->uc_limit) { 8410 return BCM_E_NOT_FOUND; 8411 } 8412 } 8413 break; 8414 case BCM_COSQ_GPORT_MCAST_QUEUE_GROUP: 8415 hw_cosq = soc_mem_field32_get(unit, PORT_COS_MAPm, entry_p, MC_COS1f); 8416 if (gport) { 8417 for (ii = port_info->mc_base; ii < port_info->mc_limit; ii++) { 8418 node = &mmu_info->mc_queue_node[ii]; 8419 if (node->numq > 0 && node->hw_cosq == hw_cosq) { 8420 *gport = node->gport; 8421 *cosq = 0; 8422 break; 8423 } 8424 } 8425 if (ii == port_info->mc_limit) { 8426 return BCM_E_NOT_FOUND; 8427 } 8428 } 8429 break; 8430 8431 case BCM_COSQ_GPORT_DESTMOD_UCAST_QUEUE_GROUP: 8432 BCM_IF_ERROR_RETURN( 8433 READ_VOQ_COS_MAPm(unit, MEM_BLOCK_ALL, priority, &voq_cos_map)); 8434 hw_cosq = soc_mem_field32_get(unit, VOQ_COS_MAPm, 8435 &voq_cos_map, VOQ_COS_OFFSETf); 8436 if (gport) { 8437 for (ii = res->num_base_queues; ii < _BCM_MN_NUM_L2_UC_LEAVES; ii++) { 8438 node = &mmu_info->queue_node[ii]; 8439 8440 if (node->numq > 0 && node->hw_cosq == hw_cosq) { 8441 *gport = node->gport; 8442 break; 8443 } 8444 } 8445 if (ii == _BCM_MN_NUM_L2_UC_LEAVES) { 8446 return BCM_E_NOT_FOUND; 8447 } 8448 } 8449 break; 8450 } 8451 8452 *cosq = hw_cosq; 8453 8454 if (((gport && 8455 (*gport == BCM_GPORT_INVALID) && (*cosq == BCM_COS_INVALID))) || 8456 (*cosq == BCM_COS_INVALID)) { 8457 return BCM_E_NOT_FOUND; 8458 } 8459 8460 return BCM_E_NONE; 8461 } 8462 8463 int 8464 bcm_mn_cosq_mapping_get(int unit, bcm_port_t port, bcm_cos_t priority, 8465 bcm_cos_queue_t *cosq) 8466 { 8467 bcm_port_t local_port; 8468 bcm_pbmp_t pbmp; 8469 8470 BCM_PBMP_CLEAR(pbmp); 8471 8472 if (port == -1) { 8473 BCM_PBMP_ASSIGN(pbmp, PBMP_ALL(unit)); 8474 } else { 8475 if (BCM_GPORT_IS_SET(port)) { 8476 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 8477 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) || 8478 BCM_GPORT_IS_SCHEDULER(port)) { 8479 return BCM_E_PARAM; 8480 } else if (BCM_GPORT_IS_LOCAL(port)) { 8481 local_port = BCM_GPORT_LOCAL_GET(port); 8482 } else if (BCM_GPORT_IS_MODPORT(port)) { 8483 BCM_IF_ERROR_RETURN( 8484 bcm_esw_port_local_get(unit, port, &local_port)); 8485 } else { 8486 return BCM_E_PARAM; 8487 } 8488 } else { 8489 local_port = port; 8490 } 8491 8492 if (!SOC_PORT_VALID(unit, local_port)) { 8493 return BCM_E_PORT; 8494 } 8495 8496 BCM_PBMP_PORT_ADD(pbmp, local_port); 8497 } 8498 8499 PBMP_ITER(pbmp, local_port) { 8500 if (IS_LB_PORT(unit, local_port)) { 8501 continue; 8502 } 8503 8504 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_mapping_get(unit, local_port, 8505 priority, BCM_COSQ_GPORT_UCAST_QUEUE_GROUP, NULL, cosq)); 8506 break; 8507 } 8508 return BCM_E_NONE; 8509 } 8510 8511 int 8512 bcm_mn_cosq_gport_mapping_set(int unit, bcm_port_t ing_port, 8513 bcm_cos_t int_pri, uint32 flags, 8514 bcm_gport_t gport, bcm_cos_queue_t cosq) 8515 { 8516 return _bcm_mn_cosq_mapping_set(unit, ing_port, int_pri, flags, gport, 8517 cosq); 8518 } 8519 8520 int 8521 bcm_mn_cosq_gport_mapping_get(int unit, bcm_port_t ing_port, 8522 bcm_cos_t int_pri, uint32 flags, 8523 bcm_gport_t *gport, bcm_cos_queue_t *cosq) 8524 { 8525 if (gport == NULL || cosq == NULL) { 8526 return BCM_E_PARAM; 8527 } 8528 8529 return _bcm_mn_cosq_mapping_get(unit, ing_port, int_pri, flags, gport, 8530 cosq); 8531 } 8532 8533 /* 8534 * Function: 8535 * bcm_mn_cosq_port_sched_set 8536 * Purpose: 8537 * Set up class-of-service policy and corresponding weights and delay 8538 * Parameters: 8539 * unit - (IN) unit number 8540 * pbm - (IN) port bitmap 8541 * mode - (IN) Scheduling mode (BCM_COSQ_xxx) 8542 * weights - (IN) Weights for each COS queue 8543 * delay - This parameter is not used 8544 * Returns: 8545 * BCM_E_XXX 8546 */ 8547 int 8548 bcm_mn_cosq_port_sched_set(int unit, bcm_pbmp_t pbm, 8549 int mode, const int *weights, int delay) 8550 { 8551 bcm_port_t port; 8552 int num_weights, i; 8553 int cur_mode, cur_weight; 8554 int reset_mode = BCM_COSQ_WEIGHTED_ROUND_ROBIN; 8555 8556 num_weights = _MN_NUM_COS(unit); 8557 BCM_PBMP_ITER(pbm, port) { 8558 /*WRR mode is a property per port, 8559 * so just get cosq=0 schedule mode*/ 8560 BCM_IF_ERROR_RETURN 8561 (_bcm_mn_cosq_sched_get(unit, port, 0, 8562 &cur_mode, &cur_weight)); 8563 if (cur_mode == BCM_COSQ_STRICT) { 8564 reset_mode = BCM_COSQ_WEIGHTED_ROUND_ROBIN; 8565 } else { 8566 reset_mode = cur_mode; 8567 } 8568 8569 /* Schedule mode switch need base on default wrr mode */ 8570 for (i = 0; i < num_weights; i++) { 8571 BCM_IF_ERROR_RETURN 8572 (_bcm_mn_cosq_sched_set(unit, port, i, 8573 reset_mode, 1)); 8574 } 8575 8576 for (i = 0; i < num_weights; i++) { 8577 BCM_IF_ERROR_RETURN 8578 (_bcm_mn_cosq_sched_set(unit, port, i, mode, weights[i])); 8579 } 8580 } 8581 8582 return BCM_E_NONE; 8583 } 8584 8585 /* 8586 * Function: 8587 * bcm_mn_cosq_port_sched_get 8588 * Purpose: 8589 * Retrieve class-of-service policy and corresponding weights and delay 8590 * Parameters: 8591 * unit - (IN) unit number 8592 * pbm - (IN) port bitmap 8593 * mode - (OUT) Scheduling mode (BCM_COSQ_XXX) 8594 * weights - (OUT) Weights for each COS queue 8595 * delay - This parameter is not used 8596 * Returns: 8597 * BCM_E_XXX 8598 */ 8599 int 8600 bcm_mn_cosq_port_sched_get(int unit, bcm_pbmp_t pbm, 8601 int *mode, int *weights, int *delay) 8602 { 8603 bcm_port_t port; 8604 int i, num_weights; 8605 8606 BCM_PBMP_ITER(pbm, port) { 8607 if (IS_CPU_PORT(unit, port) && SOC_PBMP_NEQ(pbm, PBMP_CMIC(unit))) { 8608 continue; 8609 } 8610 num_weights = _MN_NUM_COS(unit); 8611 for (i = 0; i < num_weights; i++) { 8612 BCM_IF_ERROR_RETURN( 8613 _bcm_mn_cosq_sched_get(unit, port, i, mode, &weights[i])); 8614 } 8615 } 8616 8617 return BCM_E_NONE; 8618 } 8619 8620 /* 8621 * Function: 8622 * bcm_mn_cosq_sched_weight_max_get 8623 * Purpose: 8624 * Retrieve maximum weights for given COS policy 8625 * Parameters: 8626 * unit - (IN) unit number 8627 * mode - (IN) Scheduling mode (BCM_COSQ_xxx) 8628 * weight_max - (OUT) Maximum weight for COS queue. 8629 * Returns: 8630 * BCM_E_XXX 8631 */ 8632 int 8633 bcm_mn_cosq_sched_weight_max_get(int unit, int mode, int *weight_max) 8634 { 8635 switch (mode) { 8636 case BCM_COSQ_STRICT: 8637 *weight_max = BCM_COSQ_WEIGHT_STRICT; 8638 break; 8639 case BCM_COSQ_ROUND_ROBIN: 8640 case BCM_COSQ_WEIGHTED_ROUND_ROBIN: 8641 case BCM_COSQ_DEFICIT_ROUND_ROBIN: 8642 *weight_max = 8643 (1 << soc_mem_field_length(unit, HSP_SCHED_L0_NODE_WEIGHTm, 8644 L0_NODE_WEIGHTf)) - 1; 8645 break; 8646 default: 8647 return BCM_E_PARAM; 8648 } 8649 8650 return BCM_E_NONE; 8651 } 8652 8653 /* 8654 * Function: 8655 * bcm_mn_cosq_bandwidth_set 8656 * Purpose: 8657 * Configure COS queue bandwidth control 8658 * Parameters: 8659 * unit - (IN) unit number 8660 * port - (IN) port number or GPORT identifier 8661 * cosq - (IN) COS queue number 8662 * min_quantum - (IN) 8663 * max_quantum - (IN) 8664 * burst_quantum - (IN) 8665 * flags - (IN) 8666 * Returns: 8667 * BCM_E_XXX 8668 * Notes: 8669 * If port is any form of local port, cosq is the hardware queue index. 8670 */ 8671 int 8672 bcm_mn_cosq_port_bandwidth_set(int unit, bcm_port_t port, 8673 bcm_cos_queue_t cosq, 8674 uint32 min_quantum, uint32 max_quantum, 8675 uint32 burst_quantum, uint32 flags) 8676 { 8677 uint32 burst_min, burst_max; 8678 8679 if (cosq < 0) { 8680 return BCM_E_PARAM; 8681 } 8682 8683 burst_min = (min_quantum > 0) ? 8684 _bcm_td_default_burst_size(unit, port, min_quantum) : 0; 8685 8686 burst_max = (max_quantum > 0) ? 8687 _bcm_td_default_burst_size(unit, port, max_quantum) : 0; 8688 8689 return _bcm_mn_cosq_bucket_set(unit, port, cosq, min_quantum, max_quantum, 8690 burst_min, burst_max, flags); 8691 } 8692 8693 /* 8694 * Function: 8695 * bcm_mn_cosq_bandwidth_get 8696 * Purpose: 8697 * Get COS queue bandwidth control configuration 8698 * Parameters: 8699 * unit - (IN) unit number 8700 * port - (IN) port number or GPORT identifier 8701 * cosq - (IN) COS queue number 8702 * min_quantum - (OUT) 8703 * max_quantum - (OUT) 8704 * burst_quantum - (OUT) 8705 * flags - (OUT) 8706 * Returns: 8707 * BCM_E_XXX 8708 * Notes: 8709 * If port is any form of local port, cosq is the hardware queue index. 8710 */ 8711 int 8712 bcm_mn_cosq_port_bandwidth_get(int unit, bcm_port_t port, 8713 bcm_cos_queue_t cosq, 8714 uint32 *min_quantum, uint32 *max_quantum, 8715 uint32 *burst_quantum, uint32 *flags) 8716 { 8717 uint32 kbit_burst_min; 8718 8719 if (cosq < -1) { 8720 return BCM_E_PARAM; 8721 } 8722 8723 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_bucket_get(unit, port, cosq, 8724 min_quantum, max_quantum, &kbit_burst_min, 8725 burst_quantum, flags)); 8726 return BCM_E_NONE; 8727 } 8728 8729 int 8730 bcm_mn_cosq_port_pps_set(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 8731 int pps) 8732 { 8733 uint32 min, max, burst, burst_min, flags; 8734 bcm_port_t local_port = port; 8735 8736 if (!IS_CPU_PORT(unit, port)) { 8737 return BCM_E_PORT; 8738 } else if (cosq < 0 || cosq >= NUM_CPU_COSQ(unit)) { 8739 return BCM_E_PARAM; 8740 } 8741 8742 if (_bcm_mn_cosq_port_has_ets(unit, port)) { 8743 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_l2_gport(unit, port, cosq, 8744 _BCM_MN_NODE_MCAST, &port, NULL)); 8745 cosq = 0; 8746 } 8747 8748 BCM_IF_ERROR_RETURN 8749 (_bcm_mn_cosq_bucket_get(unit, port, cosq, &min, &max, &burst_min, 8750 &burst, &flags)); 8751 8752 min = pps; 8753 burst_min = (min > 0) ? 8754 _bcm_td_default_burst_size(unit, local_port, min) : 0; 8755 burst = burst_min; 8756 8757 return _bcm_mn_cosq_bucket_set(unit, port, cosq, min, pps, burst_min, burst, 8758 flags | BCM_COSQ_BW_PACKET_MODE); 8759 } 8760 8761 int 8762 bcm_mn_cosq_port_pps_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 8763 int *pps) 8764 { 8765 uint32 min, max, burst, flags; 8766 8767 if (!IS_CPU_PORT(unit, port)) { 8768 return BCM_E_PORT; 8769 } else if (cosq < 0 || cosq >= NUM_CPU_COSQ(unit)) { 8770 return BCM_E_PARAM; 8771 } 8772 8773 if (_bcm_mn_cosq_port_has_ets(unit, port)) { 8774 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_l2_gport(unit, port, cosq, 8775 _BCM_MN_NODE_MCAST, &port, NULL)); 8776 cosq = 0; 8777 } 8778 8779 BCM_IF_ERROR_RETURN 8780 (_bcm_mn_cosq_bucket_get(unit, port, cosq, &min, &max, &burst, &burst, 8781 &flags)); 8782 *pps = max; 8783 8784 return BCM_E_NONE; 8785 } 8786 8787 int 8788 bcm_mn_cosq_port_burst_set(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 8789 int burst) 8790 { 8791 uint32 min, max, cur_burst, flags; 8792 8793 if (!IS_CPU_PORT(unit, port)) { 8794 return BCM_E_PORT; 8795 } else if (cosq < 0 || cosq >= NUM_CPU_COSQ(unit)) { 8796 return BCM_E_PARAM; 8797 } 8798 8799 if (_bcm_mn_cosq_port_has_ets(unit, port)) { 8800 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_l2_gport(unit, port, cosq, 8801 _BCM_MN_NODE_MCAST, &port, NULL)); 8802 cosq = 0; 8803 } 8804 8805 BCM_IF_ERROR_RETURN 8806 (_bcm_mn_cosq_bucket_get(unit, port, cosq, &min, &max, &cur_burst, 8807 &cur_burst, &flags)); 8808 8809 /* Replace the current BURST setting, keep PPS the same */ 8810 return _bcm_mn_cosq_bucket_set(unit, port, cosq, min, max, burst, burst, 8811 flags | BCM_COSQ_BW_PACKET_MODE); 8812 } 8813 8814 int 8815 bcm_mn_cosq_port_burst_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 8816 int *burst) 8817 { 8818 uint32 min, max, cur_burst, cur_burst_min, flags; 8819 8820 if (!IS_CPU_PORT(unit, port)) { 8821 return BCM_E_PORT; 8822 } else if (cosq < 0 || cosq >= NUM_CPU_COSQ(unit)) { 8823 return BCM_E_PARAM; 8824 } 8825 8826 if (_bcm_mn_cosq_port_has_ets(unit, port)) { 8827 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_l2_gport(unit, port, cosq, 8828 _BCM_MN_NODE_MCAST, &port, NULL)); 8829 cosq = 0; 8830 } 8831 8832 BCM_IF_ERROR_RETURN 8833 (_bcm_mn_cosq_bucket_get(unit, port, cosq, &min, &max, 8834 &cur_burst_min, &cur_burst, &flags)); 8835 *burst = cur_burst; 8836 8837 return BCM_E_NONE; 8838 } 8839 8840 int 8841 bcm_mn_cosq_discard_set(int unit, uint32 flags) 8842 { 8843 bcm_port_t port; 8844 _bcm_mn_mmu_info_t *mmu_info; 8845 8846 if ((mmu_info = _bcm_mn_mmu_info[unit]) == NULL) { 8847 return BCM_E_INIT; 8848 } 8849 8850 flags &= ~(BCM_COSQ_DISCARD_NONTCP | BCM_COSQ_DISCARD_COLOR_ALL); 8851 8852 PBMP_PORT_ITER(unit, port) { 8853 BCM_IF_ERROR_RETURN 8854 (_bcm_mn_cosq_wred_set(unit, port, 0, flags, 0, 0, 0, 0, 8855 FALSE, BCM_COSQ_DISCARD_PORT,8)); 8856 } 8857 8858 return BCM_E_NONE; 8859 } 8860 8861 int 8862 bcm_mn_cosq_discard_get(int unit, uint32 *flags) 8863 { 8864 bcm_port_t port; 8865 PBMP_PORT_ITER(unit, port) { 8866 *flags = 0; 8867 /* use setting from hardware cosq index 0 of the first port */ 8868 return _bcm_mn_cosq_wred_get(unit, port, 0, flags, NULL, NULL, NULL, 8869 NULL, BCM_COSQ_DISCARD_PORT,NULL); 8870 } 8871 8872 return BCM_E_NOT_FOUND; 8873 } 8874 8875 /* 8876 * Function: 8877 * bcm_mn_cosq_discard_port_set 8878 * Purpose: 8879 * Configure port WRED setting 8880 * Parameters: 8881 * unit - (IN) unit number 8882 * port - (IN) port number or GPORT identifier 8883 * cosq - (IN) COS queue number 8884 * color - (IN) 8885 * drop_start - (IN) 8886 * drop_slot - (IN) 8887 * average_time - (IN) 8888 * Returns: 8889 * BCM_E_XXX 8890 * Notes: 8891 * If port is any form of local port, cosq is the hardware queue index. 8892 */ 8893 int 8894 bcm_mn_cosq_discard_port_set(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 8895 uint32 color, int drop_start, int drop_slope, 8896 int average_time) 8897 { 8898 bcm_port_t local_port; 8899 bcm_pbmp_t pbmp; 8900 int gain; 8901 uint32 min_thresh, max_thresh, shared_limit; 8902 uint32 rval, bits, flags = 0; 8903 int numq, i; 8904 8905 if (drop_start < 0 || drop_start > 100 || 8906 drop_slope < 0 || drop_slope > 90) { 8907 return BCM_E_PARAM; 8908 } 8909 8910 /* 8911 * average queue size is reculated every 8us, the formula is 8912 * avg_qsize(t + 1) = 8913 * avg_qsize(t) + (cur_qsize - avg_qsize(t)) / (2 ** gain) 8914 * gain = log2(average_time / 8) 8915 */ 8916 bits = (average_time / 8) & 0xffff; 8917 if (bits != 0) { 8918 bits |= bits >> 1; 8919 bits |= bits >> 2; 8920 bits |= bits >> 4; 8921 bits |= bits >> 8; 8922 gain = _shr_popcount(bits) - 1; 8923 } else { 8924 gain = 0; 8925 } 8926 8927 /* 8928 * per-port cell limit may be disabled. 8929 * per-port per-cos cell limit may be set to use dynamic method. 8930 * therefore drop_start percentage is based on per-device total shared 8931 * cells. 8932 */ 8933 BCM_IF_ERROR_RETURN(READ_MMU_THDM_DB_POOL_SHARED_LIMITr(unit, 0, &rval)); 8934 shared_limit = soc_reg_field_get(unit, MMU_THDM_DB_POOL_SHARED_LIMITr, 8935 rval, SHARED_LIMITf); 8936 min_thresh = ((drop_start * shared_limit) + (100 - 1)) / 100; 8937 8938 if ( min_thresh == shared_limit ) { 8939 min_thresh = AP_CELL_FIELD_MAX; 8940 } 8941 /* Calculate the max threshold. For a given slope (angle in 8942 * degrees), determine how many packets are in the range from 8943 * 0% drop probability to 100% drop probability. Add that 8944 * number to the min_treshold to the the max_threshold. 8945 */ 8946 max_thresh = min_thresh + _bcm_mn_angle_to_cells(drop_slope); 8947 if (max_thresh > AP_CELL_FIELD_MAX) { 8948 max_thresh = AP_CELL_FIELD_MAX; 8949 } 8950 8951 if (BCM_GPORT_IS_SET(port)) { 8952 numq = 1; 8953 for (i = 0; i < numq; i++) { 8954 BCM_IF_ERROR_RETURN 8955 (_bcm_mn_cosq_wred_set(unit, port, cosq + i, color, 8956 min_thresh, max_thresh, 100, gain, 8957 TRUE, flags,8)); 8958 } 8959 } else { 8960 if (port == -1) { 8961 BCM_PBMP_ASSIGN(pbmp, PBMP_PORT_ALL(unit)); 8962 } else if (!SOC_PORT_VALID(unit, port)) { 8963 return BCM_E_PORT; 8964 } else { 8965 BCM_PBMP_PORT_SET(pbmp, port); 8966 } 8967 8968 BCM_PBMP_ITER(pbmp, local_port) { 8969 numq = 1; 8970 for (i = 0; i < numq; i++) { 8971 BCM_IF_ERROR_RETURN 8972 (_bcm_mn_cosq_wred_set(unit, local_port, cosq + i, 8973 color, min_thresh, max_thresh, 100, 8974 gain, TRUE, 0,8)); 8975 } 8976 } 8977 } 8978 8979 return BCM_E_NONE; 8980 } 8981 8982 /* 8983 * Function: 8984 * bcm_mn_cosq_discard_port_get 8985 * Purpose: 8986 * Get port WRED setting 8987 * Parameters: 8988 * unit - (IN) unit number 8989 * port - (IN) port number or GPORT identifier 8990 * cosq - (IN) COS queue number 8991 * color - (OUT) 8992 * drop_start - (OUT) 8993 * drop_slot - (OUT) 8994 * average_time - (OUT) 8995 * Returns: 8996 * BCM_E_XXX 8997 * Notes: 8998 * If port is any form of local port, cosq is the hardware queue index. 8999 */ 9000 int 9001 bcm_mn_cosq_discard_port_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 9002 uint32 color, int *drop_start, int *drop_slope, 9003 int *average_time) 9004 { 9005 bcm_port_t local_port; 9006 bcm_pbmp_t pbmp; 9007 int gain, drop_prob; 9008 int refresh_time = 0; 9009 uint32 min_thresh, max_thresh, shared_limit; 9010 uint32 rval; 9011 9012 if (drop_start == NULL || drop_slope == NULL || average_time == NULL) { 9013 return BCM_E_PARAM; 9014 } 9015 9016 if (BCM_GPORT_IS_SET(port)) { 9017 local_port = port; 9018 } else { 9019 if (port == -1) { 9020 BCM_PBMP_ASSIGN(pbmp, PBMP_PORT_ALL(unit)); 9021 } else if (!SOC_PORT_VALID(unit, port)) { 9022 return BCM_E_PORT; 9023 } else { 9024 BCM_PBMP_PORT_SET(pbmp, port); 9025 } 9026 BCM_PBMP_ITER(pbmp, local_port) { 9027 break; 9028 } 9029 } 9030 9031 BCM_IF_ERROR_RETURN 9032 (_bcm_mn_cosq_wred_get(unit, local_port, cosq == -1 ? 0 : cosq, 9033 &color, &min_thresh, &max_thresh, &drop_prob, 9034 &gain, 0,&refresh_time)); 9035 9036 /* 9037 * average queue size is reculated every 4us, the formula is 9038 * avg_qsize(t + 1) = 9039 * avg_qsize(t) + (cur_qsize - avg_qsize(t)) / (2 ** gain) 9040 */ 9041 *average_time = (1 << gain) * refresh_time; 9042 BCM_IF_ERROR_RETURN(READ_MMU_THDM_DB_POOL_SHARED_LIMITr(unit, 0, &rval)); 9043 shared_limit = soc_reg_field_get(unit, MMU_THDM_DB_POOL_SHARED_LIMITr, 9044 rval, SHARED_LIMITf); 9045 if (shared_limit == 0) { 9046 return BCM_E_RESOURCE; 9047 } 9048 9049 if (min_thresh > shared_limit) { 9050 min_thresh = shared_limit; 9051 } 9052 9053 if (max_thresh > shared_limit) { 9054 max_thresh = shared_limit; 9055 } 9056 9057 *drop_start = min_thresh * 100 / shared_limit; 9058 9059 /* Calculate the slope using the min and max threshold. 9060 * The angle is calculated knowing drop probability at min 9061 * threshold is 0% and drop probability at max threshold is 100%. 9062 */ 9063 *drop_slope = _bcm_mn_cells_to_angle(max_thresh - min_thresh); 9064 9065 return BCM_E_NONE; 9066 } 9067 9068 STATIC int 9069 _bcm_mn_distribute_u64(uint64 value, uint64 *l, uint64 *r) 9070 { 9071 uint64 tmp, tmp1; 9072 9073 tmp = value; 9074 COMPILER_64_SHR(tmp, 1); 9075 *l = tmp; 9076 9077 COMPILER_64_SET(tmp1, 0, 1); 9078 COMPILER_64_AND(tmp1, value); 9079 COMPILER_64_ADD_64(tmp1, tmp); 9080 *r = tmp1; 9081 return 0; 9082 } 9083 9084 9085 int 9086 bcm_mn_cosq_stat_set(int unit, bcm_gport_t port, bcm_cos_queue_t cosq, 9087 bcm_cosq_stat_t stat, uint64 value) 9088 { 9089 _bcm_mn_cosq_node_t *node; 9090 bcm_port_t local_port; 9091 int startq, numq, i, from_cos, to_cos, ci; 9092 uint64 l, r; 9093 uint64 max; 9094 soc_reg_t ctr_reg; 9095 soc_ctr_control_info_t ctrl_info; 9096 _bcm_mn_mmu_info_t *mmu_info; 9097 _bcm_mn_cosq_port_info_t *port_info; 9098 9099 COMPILER_64_SET(max, 0, 0xffffffff); 9100 if ((cosq < -1) || COMPILER_64_GT(value, max)) { 9101 return BCM_E_PARAM; 9102 } 9103 _bcm_mn_distribute_u64(value, &l, &r); 9104 9105 mmu_info = _bcm_mn_mmu_info[unit]; 9106 9107 switch (stat) { 9108 case bcmCosqStatDroppedPackets: 9109 if (BCM_GPORT_IS_SCHEDULER(port)) { 9110 BCM_IF_ERROR_RETURN 9111 (_bcm_mn_cosq_node_get(unit, port, 0, NULL, 9112 &local_port, NULL, &node)); 9113 BCM_IF_ERROR_RETURN( 9114 _bcm_mn_cosq_child_node_at_input(node, cosq, &node)); 9115 port = node->gport; 9116 } 9117 9118 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) { 9119 BCM_IF_ERROR_RETURN 9120 (_bcm_mn_cosq_index_resolve 9121 (unit, port, cosq, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_UCAST, 9122 &local_port, &startq, NULL)); 9123 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9124 BCM_IF_ERROR_RETURN 9125 (_bcm_mn_cosq_node_get(unit, port, 0, NULL, 9126 &local_port, NULL, &node)); 9127 port_info = &mmu_info->port_info[local_port]; 9128 if (node->hw_index < port_info->uc_base || 9129 node->hw_index >= port_info->uc_limit) { 9130 BCM_IF_ERROR_RETURN 9131 (soc_counter_set(unit, node->hw_index, 9132 SOC_COUNTER_NON_DMA_COSQ_DROP_PKT, 0, 9133 value)); 9134 } else { 9135 BCM_IF_ERROR_RETURN 9136 (soc_counter_set(unit, local_port, 9137 SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_UC, startq, 9138 value)); 9139 } 9140 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 9141 BCM_IF_ERROR_RETURN 9142 (_bcm_mn_cosq_index_resolve 9143 (unit, port, cosq, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_MCAST, 9144 &local_port, &startq, NULL)); 9145 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9146 BCM_IF_ERROR_RETURN 9147 (soc_counter_set(unit, local_port, 9148 SOC_COUNTER_NON_DMA_COSQ_DROP_PKT, startq, 9149 value)); 9150 } else { 9151 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_localport_resolve(unit, port, &local_port)); 9152 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_port_has_ets(unit, local_port)); 9153 if (cosq == BCM_COS_INVALID) { 9154 from_cos = to_cos = 0; 9155 } else { 9156 from_cos = to_cos = cosq; 9157 } 9158 for (ci = from_cos; ci <= to_cos; ci++) { 9159 if (!IS_CPU_PORT(unit, local_port)) { 9160 BCM_IF_ERROR_RETURN 9161 (_bcm_mn_cosq_index_resolve 9162 (unit, port, ci, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_UCAST, 9163 &local_port, &startq, &numq)); 9164 for (i = 0; i < numq; i++) { 9165 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9166 BCM_IF_ERROR_RETURN 9167 (soc_counter_set(unit, local_port, 9168 SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_UC, 9169 startq + i, l)); 9170 } 9171 } 9172 BCM_IF_ERROR_RETURN 9173 (_bcm_mn_cosq_index_resolve 9174 (unit, port, ci, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_MCAST, 9175 &local_port, &startq, &numq)); 9176 for (i = 0; i < numq; i++) { 9177 BCM_IF_ERROR_RETURN 9178 (soc_counter_set(unit, local_port, 9179 SOC_COUNTER_NON_DMA_COSQ_DROP_PKT, 9180 startq + i , r)); 9181 } 9182 } 9183 } 9184 break; 9185 case bcmCosqStatDroppedBytes: 9186 if (BCM_GPORT_IS_SCHEDULER(port)) { 9187 BCM_IF_ERROR_RETURN 9188 (_bcm_mn_cosq_node_get(unit, port, 0, NULL, 9189 &local_port, NULL, &node)); 9190 BCM_IF_ERROR_RETURN( 9191 _bcm_mn_cosq_child_node_at_input(node, cosq, &node)); 9192 port = node->gport; 9193 } 9194 9195 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) { 9196 BCM_IF_ERROR_RETURN 9197 (_bcm_mn_cosq_index_resolve 9198 (unit, port, cosq, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_UCAST, 9199 &local_port, &startq, NULL)); 9200 BCM_IF_ERROR_RETURN 9201 (_bcm_mn_cosq_node_get(unit, port, 0, NULL, 9202 &local_port, NULL, &node)); 9203 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9204 port_info = &mmu_info->port_info[local_port]; 9205 if (node->hw_index < port_info->uc_base || 9206 node->hw_index >= port_info->uc_limit) { 9207 BCM_IF_ERROR_RETURN 9208 (soc_counter_set(unit, node->hw_index, 9209 SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE, 0, 9210 value)); 9211 } else { 9212 BCM_IF_ERROR_RETURN 9213 (soc_counter_set(unit, local_port, 9214 SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE_UC, startq, 9215 value)); 9216 } 9217 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 9218 BCM_IF_ERROR_RETURN 9219 (_bcm_mn_cosq_index_resolve 9220 (unit, port, cosq, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_MCAST, 9221 &local_port, &startq, NULL)); 9222 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9223 BCM_IF_ERROR_RETURN 9224 (soc_counter_set(unit, local_port, 9225 SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE, startq , value)); 9226 } else { 9227 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_localport_resolve(unit, port, &local_port)); 9228 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_port_has_ets(unit, local_port)); 9229 if (cosq == BCM_COS_INVALID) { 9230 from_cos = to_cos = 0; 9231 } else { 9232 from_cos = to_cos = cosq; 9233 } 9234 for (ci = from_cos; ci <= to_cos; ci++) { 9235 if (!IS_CPU_PORT(unit, local_port)) { 9236 BCM_IF_ERROR_RETURN 9237 (_bcm_mn_cosq_index_resolve 9238 (unit, port, ci, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_UCAST, 9239 &local_port, &startq, &numq)); 9240 for (i = 0; i < numq; i++) { 9241 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9242 BCM_IF_ERROR_RETURN 9243 (soc_counter_set(unit, local_port, 9244 SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE_UC, 9245 startq + i, l)); 9246 } 9247 } 9248 BCM_IF_ERROR_RETURN 9249 (_bcm_mn_cosq_index_resolve 9250 (unit, port, ci, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_MCAST, 9251 &local_port, &startq, &numq)); 9252 for (i = 0; i < numq; i++) { 9253 BCM_IF_ERROR_RETURN 9254 (soc_counter_set(unit, local_port, 9255 SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE, 9256 startq + i , r)); 9257 } 9258 } 9259 } 9260 break; 9261 case bcmCosqStatYellowCongestionDroppedPackets: 9262 if (cosq != BCM_COS_INVALID) { 9263 return BCM_E_UNAVAIL; 9264 } 9265 BCM_IF_ERROR_RETURN 9266 (_bcm_mn_cosq_localport_resolve(unit, port, &local_port)); 9267 BCM_IF_ERROR_RETURN 9268 (soc_counter_set(unit, local_port, 9269 SOC_COUNTER_NON_DMA_PORT_DROP_PKT_YELLOW, 0, 9270 value)); 9271 break; 9272 case bcmCosqStatRedCongestionDroppedPackets: 9273 if (cosq != BCM_COS_INVALID) { 9274 return BCM_E_UNAVAIL; 9275 } 9276 BCM_IF_ERROR_RETURN 9277 (_bcm_mn_cosq_localport_resolve(unit, port, &local_port)); 9278 BCM_IF_ERROR_RETURN 9279 (soc_counter_set(unit, local_port, 9280 SOC_COUNTER_NON_DMA_PORT_DROP_PKT_RED, 0, 9281 value)); 9282 break; 9283 case bcmCosqStatGreenDiscardDroppedPackets: 9284 if (cosq != BCM_COS_INVALID) { 9285 return BCM_E_UNAVAIL; 9286 } 9287 BCM_IF_ERROR_RETURN 9288 (_bcm_mn_cosq_localport_resolve(unit, port, &local_port)); 9289 BCM_IF_ERROR_RETURN 9290 (soc_counter_set(unit, local_port, 9291 SOC_COUNTER_NON_DMA_PORT_WRED_PKT_GREEN, 0, 9292 value)); 9293 break; 9294 case bcmCosqStatYellowDiscardDroppedPackets: 9295 if (cosq != BCM_COS_INVALID) { 9296 return BCM_E_UNAVAIL; 9297 } 9298 BCM_IF_ERROR_RETURN 9299 (_bcm_mn_cosq_localport_resolve(unit, port, &local_port)); 9300 BCM_IF_ERROR_RETURN 9301 (soc_counter_set(unit, local_port, 9302 SOC_COUNTER_NON_DMA_PORT_WRED_PKT_YELLOW, 0, 9303 value)); 9304 break; 9305 case bcmCosqStatRedDiscardDroppedPackets: 9306 if (cosq != BCM_COS_INVALID) { 9307 return BCM_E_UNAVAIL; 9308 } 9309 BCM_IF_ERROR_RETURN 9310 (_bcm_mn_cosq_localport_resolve(unit, port, &local_port)); 9311 BCM_IF_ERROR_RETURN 9312 (soc_counter_set(unit, local_port, 9313 SOC_COUNTER_NON_DMA_PORT_WRED_PKT_RED, 0, value)); 9314 break; 9315 case bcmCosqStatOutPackets: 9316 if (BCM_GPORT_IS_SCHEDULER(port)) { 9317 BCM_IF_ERROR_RETURN 9318 (_bcm_mn_cosq_node_get(unit, port, 0, NULL, 9319 &local_port, NULL, &node)); 9320 BCM_IF_ERROR_RETURN( 9321 _bcm_mn_cosq_child_node_at_input(node, cosq, &node)); 9322 port = node->gport; 9323 } 9324 9325 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) { 9326 BCM_IF_ERROR_RETURN 9327 (_bcm_mn_cosq_index_resolve 9328 (unit, port, cosq, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_UCAST, 9329 &local_port, &startq, NULL)); 9330 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9331 BCM_IF_ERROR_RETURN 9332 (_bcm_mn_cosq_node_get(unit, port, 0, NULL, 9333 &local_port, NULL, &node)); 9334 port_info = &mmu_info->port_info[local_port]; 9335 if (node->hw_index < port_info->uc_base 9336 || node->hw_index >= port_info->uc_limit) { 9337 BCM_IF_ERROR_RETURN 9338 (soc_counter_set(unit, node->hw_index, 9339 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT, 0, 9340 value)); 9341 } else { 9342 BCM_IF_ERROR_RETURN 9343 (soc_counter_set(unit, local_port, 9344 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT_UC, startq, 9345 value)); 9346 } 9347 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 9348 BCM_IF_ERROR_RETURN 9349 (_bcm_mn_cosq_index_resolve 9350 (unit, port, cosq, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_MCAST, 9351 &local_port, &startq, NULL)); 9352 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9353 BCM_IF_ERROR_RETURN 9354 (soc_counter_set(unit, local_port, 9355 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT, startq, 9356 value)); 9357 } else { 9358 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_localport_resolve(unit, port, &local_port)); 9359 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_port_has_ets(unit, local_port)); 9360 if (cosq == BCM_COS_INVALID) { 9361 from_cos = to_cos = 0; 9362 } else { 9363 from_cos = to_cos = cosq; 9364 } 9365 for (ci = from_cos; ci <= to_cos; ci++) { 9366 if (!IS_CPU_PORT(unit, local_port)) { 9367 BCM_IF_ERROR_RETURN 9368 (_bcm_mn_cosq_index_resolve 9369 (unit, port, ci, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_UCAST, 9370 &local_port, &startq, &numq)); 9371 for (i = 0; i < numq; i++) { 9372 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9373 BCM_IF_ERROR_RETURN 9374 (soc_counter_set(unit, local_port, 9375 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT_UC, 9376 startq + i, l)); 9377 } 9378 } 9379 BCM_IF_ERROR_RETURN 9380 (_bcm_mn_cosq_index_resolve 9381 (unit, port, ci, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_MCAST, 9382 &local_port, &startq, &numq)); 9383 for (i = 0; i < numq; i++) { 9384 BCM_IF_ERROR_RETURN 9385 (soc_counter_set(unit, local_port, 9386 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT, 9387 startq + i, r)); 9388 } 9389 } 9390 } 9391 break; 9392 case bcmCosqStatOutBytes: 9393 if (BCM_GPORT_IS_SCHEDULER(port)) { 9394 BCM_IF_ERROR_RETURN 9395 (_bcm_mn_cosq_node_get(unit, port, 0, NULL, 9396 &local_port, NULL, &node)); 9397 BCM_IF_ERROR_RETURN( 9398 _bcm_mn_cosq_child_node_at_input(node, cosq, &node)); 9399 port = node->gport; 9400 } 9401 9402 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) { 9403 BCM_IF_ERROR_RETURN 9404 (_bcm_mn_cosq_index_resolve 9405 (unit, port, cosq, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_UCAST, 9406 &local_port, &startq, NULL)); 9407 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9408 BCM_IF_ERROR_RETURN 9409 (_bcm_mn_cosq_node_get(unit, port, 0, NULL, 9410 &local_port, NULL, &node)); 9411 port_info = &mmu_info->port_info[local_port]; 9412 if (node->hw_index < port_info->uc_base || 9413 node->hw_index >= port_info->uc_limit) { 9414 BCM_IF_ERROR_RETURN 9415 (soc_counter_set(unit, node->hw_index, 9416 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE, 0, 9417 value)); 9418 } else { 9419 BCM_IF_ERROR_RETURN 9420 (soc_counter_set(unit, local_port, 9421 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE_UC, startq, 9422 value)); 9423 } 9424 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 9425 BCM_IF_ERROR_RETURN 9426 (_bcm_mn_cosq_index_resolve 9427 (unit, port, cosq, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_MCAST, 9428 &local_port, &startq, NULL)); 9429 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9430 BCM_IF_ERROR_RETURN 9431 (soc_counter_set(unit, local_port, 9432 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE, startq, 9433 value)); 9434 } else { 9435 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_localport_resolve(unit, port, &local_port)); 9436 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_port_has_ets(unit, local_port)); 9437 if (cosq == BCM_COS_INVALID) { 9438 from_cos = to_cos = 0; 9439 } else { 9440 from_cos = to_cos = cosq; 9441 } 9442 for (ci = from_cos; ci <= to_cos; ci++) { 9443 if (!IS_CPU_PORT(unit, local_port)) { 9444 BCM_IF_ERROR_RETURN 9445 (_bcm_mn_cosq_index_resolve 9446 (unit, port, ci, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_UCAST, 9447 &local_port, &startq, &numq)); 9448 for (i = 0; i < numq; i++) { 9449 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9450 BCM_IF_ERROR_RETURN 9451 (soc_counter_set(unit, local_port, 9452 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE_UC, 9453 startq + i, l)); 9454 } 9455 } 9456 BCM_IF_ERROR_RETURN 9457 (_bcm_mn_cosq_index_resolve 9458 (unit, port, ci, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_MCAST, 9459 &local_port, &startq, &numq)); 9460 for (i = 0; i < numq; i++) { 9461 BCM_IF_ERROR_RETURN 9462 (soc_counter_set(unit, local_port, 9463 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE, 9464 startq + i, r)); 9465 } 9466 } 9467 } 9468 break; 9469 case bcmCosqStatIeee8021CnCpTransmittedCnms: 9470 BCM_IF_ERROR_RETURN 9471 (_bcm_mn_cosq_index_resolve 9472 (unit, port, cosq, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_UCAST, 9473 &local_port, &startq, NULL)); 9474 BCM_IF_ERROR_RETURN 9475 (soc_counter_set(unit, local_port, 9476 SOC_COUNTER_NON_DMA_MMU_QCN_CNM, startq, value)); 9477 break; 9478 9479 case bcmCosqStatHighPriDroppedPackets: 9480 case bcmCosqStatOBMLossyHighPriDroppedPackets: 9481 case bcmCosqStatLowPriDroppedPackets: 9482 case bcmCosqStatOBMLossyLowPriDroppedPackets: 9483 case bcmCosqStatHighPriDroppedBytes: 9484 case bcmCosqStatOBMLossyHighPriDroppedBytes: 9485 case bcmCosqStatLowPriDroppedBytes: 9486 case bcmCosqStatOBMLossyLowPriDroppedBytes: 9487 case bcmCosqStatOBMLossless0DroppedPackets: 9488 case bcmCosqStatOBMLossless1DroppedPackets: 9489 case bcmCosqStatOBMLossless0DroppedBytes: 9490 case bcmCosqStatOBMLossless1DroppedBytes: 9491 case bcmCosqStatOBMLossless0EnqueuedPackets: 9492 case bcmCosqStatOBMLossless0EnqueuedBytes: 9493 case bcmCosqStatOBMLossless1EnqueuedPackets: 9494 case bcmCosqStatOBMLossless1EnqueuedBytes: 9495 case bcmCosqStatOBMLossyHighPriEnqueuedPackets: 9496 case bcmCosqStatOBMLossyHighPriEnqueuedBytes: 9497 case bcmCosqStatOBMLossyLowPriEnqueuedPackets: 9498 case bcmCosqStatOBMLossyLowPriEnqueuedBytes: 9499 case bcmCosqStatOBMExpressEnqueuedPackets: 9500 case bcmCosqStatOBMExpressEnqueuedBytes: 9501 case bcmCosqStatOBMExpressDroppedPackets: 9502 case bcmCosqStatOBMExpressDroppedBytes: 9503 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 9504 BCM_GPORT_IS_SCHEDULER(port) || 9505 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 9506 return BCM_E_PARAM; 9507 } 9508 BCM_IF_ERROR_RETURN( 9509 _bcm_mn_cosq_localport_resolve(unit, port, &local_port)); 9510 if ((stat == bcmCosqStatHighPriDroppedPackets) || 9511 (stat == bcmCosqStatOBMLossyHighPriDroppedPackets)) { 9512 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM_LOSSY_HI; 9513 } else if ((stat == bcmCosqStatLowPriDroppedPackets) || 9514 (stat == bcmCosqStatOBMLossyLowPriDroppedPackets)) { 9515 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM_LOSSY_LO; 9516 } else if ((stat == bcmCosqStatHighPriDroppedBytes) || 9517 (stat == bcmCosqStatOBMLossyHighPriDroppedBytes)) { 9518 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM_LOSSY_HI; 9519 } else if ((stat == bcmCosqStatLowPriDroppedBytes) || 9520 (stat == bcmCosqStatOBMLossyLowPriDroppedBytes)) { 9521 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM_LOSSY_LO; 9522 } else if (stat == bcmCosqStatOBMLossless0DroppedPackets) { 9523 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM_LOSSLESS0; 9524 } else if (stat == bcmCosqStatOBMLossless1DroppedPackets) { 9525 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM_LOSSLESS1; 9526 } else if (stat == bcmCosqStatOBMLossless0DroppedBytes) { 9527 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM_LOSSLESS0; 9528 } else if (stat == bcmCosqStatOBMLossless1DroppedBytes) { 9529 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM_LOSSLESS1; 9530 } else if (stat == bcmCosqStatOBMLossless0EnqueuedPackets) { 9531 ctr_reg = SOC_COUNTER_NON_DMA_PORT_ENQUEUE_PKT_OBM_LOSSLESS0; 9532 } else if (stat == bcmCosqStatOBMLossless0EnqueuedBytes) { 9533 ctr_reg = SOC_COUNTER_NON_DMA_PORT_ENQUEUE_BYTE_OBM_LOSSLESS0; 9534 } else if (stat == bcmCosqStatOBMLossless1EnqueuedPackets) { 9535 ctr_reg = SOC_COUNTER_NON_DMA_PORT_ENQUEUE_PKT_OBM_LOSSLESS1; 9536 } else if (stat == bcmCosqStatOBMLossless1EnqueuedBytes) { 9537 ctr_reg = SOC_COUNTER_NON_DMA_PORT_ENQUEUE_BYTE_OBM_LOSSLESS1; 9538 } else if (stat == bcmCosqStatOBMLossyHighPriEnqueuedPackets) { 9539 ctr_reg = SOC_COUNTER_NON_DMA_PORT_ENQUEUE_PKT_OBM_LOSSY_HI; 9540 } else if (stat == bcmCosqStatOBMLossyHighPriEnqueuedBytes) { 9541 ctr_reg = SOC_COUNTER_NON_DMA_PORT_ENQUEUE_BYTE_OBM_LOSSY_HI; 9542 } else if (stat == bcmCosqStatOBMLossyLowPriEnqueuedPackets) { 9543 ctr_reg = SOC_COUNTER_NON_DMA_PORT_ENQUEUE_PKT_OBM_LOSSY_LO; 9544 } else if (stat == bcmCosqStatOBMLossyLowPriEnqueuedBytes) { 9545 ctr_reg = SOC_COUNTER_NON_DMA_PORT_ENQUEUE_BYTE_OBM_LOSSY_LO; 9546 } else if (stat == bcmCosqStatOBMExpressEnqueuedPackets) { 9547 ctr_reg = SOC_COUNTER_NON_DMA_PORT_ENQUEUE_PKT_OBM_EXPRESS; 9548 } else if (stat == bcmCosqStatOBMExpressEnqueuedBytes) { 9549 ctr_reg = SOC_COUNTER_NON_DMA_PORT_ENQUEUE_BYTE_OBM_EXPRESS; 9550 } else if (stat == bcmCosqStatOBMExpressDroppedPackets) { 9551 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM_EXPRESS; 9552 } else { /*if (stat == bcmCosqStatOBMExpressDroppedBytes) */ 9553 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM_EXPRESS; 9554 } 9555 ctrl_info.instance_type = SOC_CTR_INSTANCE_TYPE_PORT; 9556 ctrl_info.instance = local_port; 9557 BCM_IF_ERROR_RETURN 9558 (soc_counter_generic_set(unit, ctr_reg, ctrl_info, 0, 9559 0, value)); 9560 9561 break; 9562 default: 9563 return BCM_E_PARAM; 9564 } 9565 9566 return BCM_E_NONE; 9567 } 9568 9569 9570 static int 9571 _bcm_mn_cosq_uc_stat_get(int unit, bcm_port_t port, uint64 *value, soc_reg_t regs1, 9572 soc_reg_t regs2, int sync_mode, int cosq) 9573 { 9574 int (*counter_get) (int , soc_port_t , soc_reg_t , int , uint64 *); 9575 bcm_port_t local_port; 9576 _bcm_mn_cosq_node_t *node; 9577 _bcm_mn_cosq_port_info_t *port_info; 9578 9579 _bcm_mn_mmu_info_t *mmu_info; 9580 mmu_info = _bcm_mn_mmu_info[unit]; 9581 counter_get = (sync_mode == 1)? soc_counter_sync_get: soc_counter_get; 9582 9583 BCM_IF_ERROR_RETURN 9584 (_bcm_mn_cosq_node_get(unit, port, 0, NULL, 9585 &local_port, NULL, &node)); 9586 port_info = &mmu_info->port_info[local_port]; 9587 if (node->hw_index < port_info->uc_base || 9588 node->hw_index >= port_info->uc_limit) { 9589 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9590 BCM_IF_ERROR_RETURN 9591 (counter_get(unit, node->hw_index, 9592 regs2, 0, 9593 value)); 9594 } else { 9595 9596 9597 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9598 9599 BCM_IF_ERROR_RETURN 9600 (counter_get(unit, local_port, 9601 regs1, cosq, 9602 value)); 9603 } 9604 return BCM_E_NONE; 9605 } 9606 9607 static int 9608 _bcm_mn_cosq_mc_stat_get(int unit, bcm_port_t port, uint64 *value, soc_reg_t regs, 9609 int sync_mode, int cosq) 9610 { 9611 int startq; 9612 int (*counter_get) (int , soc_port_t , soc_reg_t , int , uint64 *); 9613 bcm_port_t local_port; 9614 9615 counter_get = (sync_mode == 1)? soc_counter_sync_get: soc_counter_get; 9616 BCM_IF_ERROR_RETURN 9617 (_bcm_mn_cosq_index_resolve 9618 (unit, port, cosq, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_MCAST, 9619 &local_port, &startq, NULL)); 9620 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9621 BCM_IF_ERROR_RETURN 9622 (counter_get(unit, local_port, regs, startq, value)); 9623 return BCM_E_NONE; 9624 } 9625 9626 9627 /* get the l2 queues for the scheduler node*/ 9628 STATIC int 9629 _bcm_mn_cosq_stat_get(int unit, bcm_port_t port, _bcm_mn_cosq_node_t *node,int sync_mode, 9630 uint64 *value, soc_reg_t uc_regs, soc_reg_t mc_regs) 9631 { 9632 uint64 sum; 9633 uint64 value64; 9634 9635 COMPILER_64_ZERO(value64); 9636 COMPILER_64_ZERO(sum); 9637 /*the function will be called recursively */ 9638 if (node->level == SOC_MONTEREY_NODE_LVL_L2) { 9639 while (node){ 9640 port = node->gport; 9641 /* 9642 *check if the port is uc or mc and get the stats for the needed 9643 *type 9644 */ 9645 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) { 9646 if (uc_regs == -1){ 9647 return BCM_E_PARAM; 9648 } 9649 BCM_IF_ERROR_RETURN( 9650 _bcm_mn_cosq_uc_stat_get(unit, port, &value64, uc_regs, mc_regs, 9651 sync_mode, node->hw_cosq)); 9652 COMPILER_64_ADD_64(sum, value64); 9653 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 9654 if (mc_regs == -1){ 9655 return BCM_E_PARAM; 9656 } 9657 BCM_IF_ERROR_RETURN( 9658 _bcm_mn_cosq_mc_stat_get(unit, port, &value64, mc_regs, 9659 sync_mode, node->hw_cosq)); 9660 COMPILER_64_ADD_64(sum, value64); 9661 } 9662 node = node->sibling; 9663 } 9664 } 9665 else { 9666 if(node->sibling){ 9667 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_stat_get(unit, port, node->sibling, sync_mode, 9668 value, uc_regs, mc_regs)); 9669 } 9670 if(node->child){ 9671 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_stat_get(unit, port, node->child, sync_mode, 9672 value, uc_regs, mc_regs)); 9673 } 9674 } 9675 COMPILER_64_ADD_64(*value, sum); 9676 return BCM_E_NONE; 9677 9678 } 9679 9680 9681 int 9682 bcm_mn_cosq_stat_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 9683 bcm_cosq_stat_t stat, int sync_mode, uint64 *value) 9684 { 9685 _bcm_mn_cosq_node_t *node; 9686 bcm_port_t local_port; 9687 int startq, numq, i, from_cos, to_cos, ci, start_hw_index, end_hw_index; 9688 uint64 sum, value64; 9689 int (*counter_get) (int , soc_port_t , soc_reg_t , int , uint64 *); 9690 soc_reg_t ctr_reg; 9691 soc_ctr_control_info_t ctrl_info; 9692 _bcm_mn_mmu_info_t *mmu_info; 9693 _bcm_mn_cosq_port_info_t *port_info; 9694 if ((value == NULL) || (cosq < -1)) { 9695 return BCM_E_PARAM; 9696 } 9697 9698 9699 mmu_info = _bcm_mn_mmu_info[unit]; 9700 9701 /* 9702 * if sync-mode is set, update the software cached counter value, 9703 * with the hardware count and then retrieve the count. 9704 * else return the software cache counter value. 9705 */ 9706 counter_get = (sync_mode == 1)? soc_counter_sync_get: soc_counter_get; 9707 9708 switch (stat) { 9709 case bcmCosqStatDroppedPackets: 9710 9711 if (BCM_GPORT_IS_SCHEDULER(port)) { 9712 BCM_IF_ERROR_RETURN 9713 (_bcm_mn_cosq_node_get(unit, port, 0, NULL, 9714 &local_port, NULL, &node)); 9715 9716 if (cosq == BCM_COS_INVALID) { 9717 node = node->child; 9718 if (node){ 9719 COMPILER_64_ZERO(value64); 9720 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_stat_get(unit, port, 9721 node, sync_mode, &value64,SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_UC, 9722 SOC_COUNTER_NON_DMA_COSQ_DROP_PKT)); 9723 *value = value64; 9724 break; 9725 } 9726 } 9727 BCM_IF_ERROR_RETURN( 9728 _bcm_mn_cosq_child_node_at_input(node, cosq, &node)); 9729 port = node->gport; 9730 } 9731 9732 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) { 9733 BCM_IF_ERROR_RETURN 9734 (_bcm_mn_cosq_index_resolve 9735 (unit, port, cosq, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_UCAST, 9736 &local_port, &startq, NULL)); 9737 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9738 9739 BCM_IF_ERROR_RETURN 9740 (_bcm_mn_cosq_node_get(unit, port, 0, NULL, 9741 &local_port, NULL, &node)); 9742 port_info = &mmu_info->port_info[local_port]; 9743 if (node->hw_index < port_info->uc_base || 9744 node->hw_index >= port_info->uc_limit) 9745 { 9746 BCM_IF_ERROR_RETURN 9747 (counter_get(unit, node->hw_index, 9748 SOC_COUNTER_NON_DMA_COSQ_DROP_PKT, 0, 9749 value)); 9750 } else { 9751 BCM_IF_ERROR_RETURN 9752 (counter_get(unit, local_port, 9753 SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_UC, startq, 9754 value)); 9755 } 9756 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 9757 BCM_IF_ERROR_RETURN 9758 (_bcm_mn_cosq_index_resolve 9759 (unit, port, cosq, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_MCAST, 9760 &local_port, &startq, NULL)); 9761 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9762 BCM_IF_ERROR_RETURN 9763 (counter_get(unit, local_port, 9764 SOC_COUNTER_NON_DMA_COSQ_DROP_PKT, startq, value)); 9765 } else { 9766 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_localport_resolve(unit, port, &local_port)); 9767 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_port_has_ets(unit, local_port)); 9768 COMPILER_64_ZERO(sum); 9769 if (cosq == BCM_COS_INVALID) { 9770 from_cos = 0; 9771 to_cos = (IS_CPU_PORT(unit, local_port)) ? 9772 NUM_CPU_COSQ(unit) - 1 : _MN_NUM_COS(unit) - 1; 9773 } else { 9774 from_cos = to_cos = cosq; 9775 } 9776 for (ci = from_cos; ci <= to_cos; ci++) { 9777 if (!IS_CPU_PORT(unit, local_port)) { 9778 BCM_IF_ERROR_RETURN 9779 (_bcm_mn_cosq_index_resolve 9780 (unit, port, ci, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_UCAST, 9781 &local_port, &startq, &numq)); 9782 for (i = 0; i < numq; i++) { 9783 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9784 BCM_IF_ERROR_RETURN 9785 (counter_get(unit, local_port, 9786 SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_UC, 9787 startq + i, &value64)); 9788 COMPILER_64_ADD_64(sum, value64); 9789 } 9790 } 9791 BCM_IF_ERROR_RETURN 9792 (_bcm_mn_cosq_index_resolve 9793 (unit, port, ci, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_MCAST, 9794 &local_port, &startq, &numq)); 9795 9796 for (i = 0; i < numq; i++) { 9797 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9798 BCM_IF_ERROR_RETURN 9799 (counter_get(unit, local_port, 9800 SOC_COUNTER_NON_DMA_COSQ_DROP_PKT, 9801 startq + i, &value64)); 9802 COMPILER_64_ADD_64(sum, value64); 9803 } 9804 } 9805 *value = sum; 9806 } 9807 break; 9808 case bcmCosqStatDroppedBytes: 9809 if (BCM_GPORT_IS_SCHEDULER(port)) { 9810 BCM_IF_ERROR_RETURN 9811 (_bcm_mn_cosq_node_get(unit, port, 0, NULL, 9812 &local_port, NULL, &node)); 9813 if (cosq == BCM_COS_INVALID) { 9814 node = node->child; 9815 if (node){ 9816 COMPILER_64_ZERO(value64); 9817 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_stat_get(unit, port, 9818 node, sync_mode, &value64,SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE_UC, 9819 SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE)); 9820 *value = value64; 9821 break; 9822 } 9823 } 9824 9825 BCM_IF_ERROR_RETURN( 9826 _bcm_mn_cosq_child_node_at_input(node, cosq, &node)); 9827 port = node->gport; 9828 } 9829 9830 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) { 9831 BCM_IF_ERROR_RETURN 9832 (_bcm_mn_cosq_index_resolve 9833 (unit, port, cosq, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_UCAST, 9834 &local_port, &startq, NULL)); 9835 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9836 BCM_IF_ERROR_RETURN 9837 (_bcm_mn_cosq_node_get(unit, port, 0, NULL, 9838 &local_port, NULL, &node)); 9839 port_info = &mmu_info->port_info[local_port]; 9840 if (node->hw_index < port_info->uc_base || 9841 node->hw_index >= port_info->uc_limit) { 9842 BCM_IF_ERROR_RETURN 9843 (counter_get(unit, node->hw_index, 9844 SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE, 0, 9845 value)); 9846 } else { 9847 BCM_IF_ERROR_RETURN 9848 (counter_get(unit, local_port, 9849 SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE_UC, startq, 9850 value)); 9851 } 9852 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 9853 BCM_IF_ERROR_RETURN 9854 (_bcm_mn_cosq_index_resolve 9855 (unit, port, cosq, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_MCAST, 9856 &local_port, &startq, NULL)); 9857 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9858 BCM_IF_ERROR_RETURN 9859 (counter_get(unit, local_port, 9860 SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE, startq, value)); 9861 } else { 9862 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_localport_resolve(unit, port, &local_port)); 9863 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_port_has_ets(unit, local_port)); 9864 COMPILER_64_ZERO(sum); 9865 if (cosq == BCM_COS_INVALID) { 9866 from_cos = 0; 9867 to_cos = (IS_CPU_PORT(unit, local_port)) ? 9868 NUM_CPU_COSQ(unit) - 1 : _MN_NUM_COS(unit) - 1; 9869 } else { 9870 from_cos = to_cos = cosq; 9871 } 9872 for (ci = from_cos; ci <= to_cos; ci++) { 9873 if (!IS_CPU_PORT(unit, local_port)) { 9874 BCM_IF_ERROR_RETURN 9875 (_bcm_mn_cosq_index_resolve 9876 (unit, port, ci, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_UCAST, 9877 &local_port, &startq, &numq)); 9878 for (i = 0; i < numq; i++) { 9879 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9880 BCM_IF_ERROR_RETURN 9881 (counter_get(unit, local_port, 9882 SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE_UC, 9883 startq + i, &value64)); 9884 COMPILER_64_ADD_64(sum, value64); 9885 } 9886 } 9887 BCM_IF_ERROR_RETURN 9888 (_bcm_mn_cosq_index_resolve 9889 (unit, port, ci, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_MCAST, 9890 &local_port, &startq, &numq)); 9891 for (i = 0; i < numq; i++) { 9892 BCM_IF_ERROR_RETURN 9893 (counter_get(unit, local_port, 9894 SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE, 9895 startq + i, &value64)); 9896 COMPILER_64_ADD_64(sum, value64); 9897 } 9898 } 9899 *value = sum; 9900 } 9901 break; 9902 case bcmCosqStatYellowCongestionDroppedPackets: 9903 if (cosq != BCM_COS_INVALID) { 9904 return BCM_E_UNAVAIL; 9905 } 9906 BCM_IF_ERROR_RETURN 9907 (_bcm_mn_cosq_localport_resolve(unit, port, &local_port)); 9908 BCM_IF_ERROR_RETURN 9909 (counter_get(unit, local_port, 9910 SOC_COUNTER_NON_DMA_PORT_DROP_PKT_YELLOW, 0, 9911 value)); 9912 break; 9913 case bcmCosqStatRedCongestionDroppedPackets: 9914 if (cosq != BCM_COS_INVALID) { 9915 return BCM_E_UNAVAIL; 9916 } 9917 BCM_IF_ERROR_RETURN 9918 (_bcm_mn_cosq_localport_resolve(unit, port, &local_port)); 9919 BCM_IF_ERROR_RETURN 9920 (counter_get(unit, local_port, 9921 SOC_COUNTER_NON_DMA_PORT_DROP_PKT_RED, 0, 9922 value)); 9923 break; 9924 case bcmCosqStatGreenDiscardDroppedPackets: 9925 if (cosq != BCM_COS_INVALID) { 9926 return BCM_E_UNAVAIL; 9927 } 9928 BCM_IF_ERROR_RETURN 9929 (_bcm_mn_cosq_localport_resolve(unit, port, &local_port)); 9930 BCM_IF_ERROR_RETURN 9931 (counter_get(unit, local_port, 9932 SOC_COUNTER_NON_DMA_PORT_WRED_PKT_GREEN, 0, 9933 value)); 9934 break; 9935 case bcmCosqStatYellowDiscardDroppedPackets: 9936 if (cosq != BCM_COS_INVALID) { 9937 return BCM_E_UNAVAIL; 9938 } 9939 BCM_IF_ERROR_RETURN 9940 (_bcm_mn_cosq_localport_resolve(unit, port, &local_port)); 9941 BCM_IF_ERROR_RETURN 9942 (counter_get(unit, local_port, 9943 SOC_COUNTER_NON_DMA_PORT_WRED_PKT_YELLOW, 0, 9944 value)); 9945 break; 9946 case bcmCosqStatRedDiscardDroppedPackets: 9947 if (cosq != BCM_COS_INVALID) { 9948 return BCM_E_UNAVAIL; 9949 } 9950 BCM_IF_ERROR_RETURN 9951 (_bcm_mn_cosq_localport_resolve(unit, port, &local_port)); 9952 BCM_IF_ERROR_RETURN 9953 (counter_get(unit, local_port, 9954 SOC_COUNTER_NON_DMA_PORT_WRED_PKT_RED, 0, value)); 9955 break; 9956 case bcmCosqStatOutPackets: 9957 if (BCM_GPORT_IS_SCHEDULER(port)) { 9958 BCM_IF_ERROR_RETURN 9959 (_bcm_mn_cosq_node_get(unit, port, 0, NULL, 9960 &local_port, NULL, &node)); 9961 if (cosq == BCM_COS_INVALID) { 9962 node = node->child; 9963 if (node){ 9964 COMPILER_64_ZERO(value64); 9965 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_stat_get(unit, port, 9966 node, sync_mode, &value64,SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT_UC, 9967 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT)); 9968 *value = value64; 9969 break; 9970 } 9971 } 9972 9973 9974 BCM_IF_ERROR_RETURN( 9975 _bcm_mn_cosq_child_node_at_input(node, cosq, &node)); 9976 port = node->gport; 9977 } 9978 9979 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) { 9980 BCM_IF_ERROR_RETURN 9981 (_bcm_mn_cosq_node_get(unit, port, 0, NULL, 9982 &local_port, NULL, &node)); 9983 port_info = &mmu_info->port_info[local_port]; 9984 if (node->hw_index < port_info->uc_base || 9985 node->hw_index >= port_info->uc_limit) { 9986 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9987 BCM_IF_ERROR_RETURN 9988 (counter_get(unit, node->hw_index, 9989 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT, 0, 9990 value)); 9991 } else { 9992 9993 (_bcm_mn_cosq_index_resolve 9994 (unit, port, cosq, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_UCAST, 9995 &local_port, &startq, NULL)); 9996 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9997 BCM_IF_ERROR_RETURN 9998 (counter_get(unit, local_port, 9999 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT_UC, startq, 10000 value)); 10001 } 10002 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 10003 BCM_IF_ERROR_RETURN 10004 (_bcm_mn_cosq_index_resolve 10005 (unit, port, cosq, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_MCAST, 10006 &local_port, &startq, NULL)); 10007 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10008 BCM_IF_ERROR_RETURN 10009 (counter_get(unit, local_port, 10010 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT, startq, 10011 value)); 10012 } else { 10013 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_localport_resolve(unit, port, &local_port)); 10014 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_port_has_ets(unit, local_port)); 10015 COMPILER_64_ZERO(sum); 10016 if (cosq == BCM_COS_INVALID) { 10017 from_cos = 0; 10018 to_cos = (IS_CPU_PORT(unit, local_port)) ? 10019 NUM_CPU_COSQ(unit) - 1 : _MN_NUM_COS(unit) - 1; 10020 } else { 10021 from_cos = to_cos = cosq; 10022 } 10023 10024 for (ci = from_cos; ci <= to_cos; ci++) { 10025 if (!IS_CPU_PORT(unit, local_port)) { 10026 BCM_IF_ERROR_RETURN 10027 (_bcm_mn_cosq_index_resolve 10028 (unit, port, ci, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_UCAST, 10029 &local_port, &startq, &numq)); 10030 for (i = 0; i < numq; i++) { 10031 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10032 BCM_IF_ERROR_RETURN 10033 (counter_get(unit, local_port, 10034 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT_UC, 10035 startq + i, &value64)); 10036 COMPILER_64_ADD_64(sum, value64); 10037 } 10038 } 10039 BCM_IF_ERROR_RETURN 10040 (_bcm_mn_cosq_index_resolve 10041 (unit, port, ci, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_MCAST, 10042 &local_port, &startq, &numq)); 10043 for (i = 0; i < numq; i++) { 10044 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10045 BCM_IF_ERROR_RETURN 10046 (counter_get(unit, local_port, 10047 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT, 10048 startq + i, &value64)); 10049 COMPILER_64_ADD_64(sum, value64); 10050 } 10051 } 10052 *value = sum; 10053 } 10054 break; 10055 case bcmCosqStatOutBytes: 10056 if (BCM_GPORT_IS_SCHEDULER(port)) { 10057 BCM_IF_ERROR_RETURN 10058 (_bcm_mn_cosq_node_get(unit, port, 0, NULL, 10059 &local_port, NULL, &node)); 10060 10061 if (cosq == BCM_COS_INVALID) { 10062 node = node->child; 10063 if (node){ 10064 COMPILER_64_ZERO(value64); 10065 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_stat_get(unit, port, 10066 node, sync_mode, &value64,SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE_UC, 10067 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE)); 10068 *value = value64; 10069 break; 10070 } 10071 } 10072 10073 BCM_IF_ERROR_RETURN( 10074 _bcm_mn_cosq_child_node_at_input(node, cosq, &node)); 10075 port = node->gport; 10076 } 10077 10078 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) { 10079 BCM_IF_ERROR_RETURN 10080 (_bcm_mn_cosq_node_get(unit, port, 0, NULL , 10081 &local_port, NULL, &node)); 10082 port_info = &mmu_info->port_info[local_port]; 10083 if (node->hw_index < port_info->uc_base || 10084 node->hw_index >= port_info->uc_limit) { 10085 BCM_IF_ERROR_RETURN 10086 (counter_get(unit, node->hw_index, 10087 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE, 0, 10088 value)); 10089 } else { 10090 10091 BCM_IF_ERROR_RETURN 10092 (_bcm_mn_cosq_index_resolve 10093 (unit, port, cosq, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_UCAST, 10094 &local_port, &startq, NULL)); 10095 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10096 BCM_IF_ERROR_RETURN 10097 (counter_get(unit, local_port, 10098 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE_UC, startq, 10099 value)); 10100 } 10101 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 10102 BCM_IF_ERROR_RETURN 10103 (_bcm_mn_cosq_index_resolve 10104 (unit, port, cosq, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_MCAST, 10105 &local_port, &startq, NULL)); 10106 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10107 BCM_IF_ERROR_RETURN 10108 (counter_get(unit, local_port, 10109 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE, startq, 10110 value)); 10111 } else { 10112 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_localport_resolve(unit, port, &local_port)); 10113 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_port_has_ets(unit, local_port)); 10114 COMPILER_64_ZERO(sum); 10115 if (cosq == BCM_COS_INVALID) { 10116 from_cos = 0; 10117 to_cos = (IS_CPU_PORT(unit, local_port)) ? 10118 NUM_CPU_COSQ(unit) - 1 : _MN_NUM_COS(unit) - 1; 10119 } else { 10120 from_cos = to_cos = cosq; 10121 } 10122 10123 for (ci = from_cos; ci <= to_cos; ci++) { 10124 if (!IS_CPU_PORT(unit, local_port)) { 10125 BCM_IF_ERROR_RETURN 10126 (_bcm_mn_cosq_index_resolve 10127 (unit, port, ci, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_UCAST, 10128 &local_port, &startq, &numq)); 10129 for (i = 0; i < numq; i++) { 10130 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10131 BCM_IF_ERROR_RETURN 10132 (counter_get(unit, local_port, 10133 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE_UC, 10134 startq + i, &value64)); 10135 COMPILER_64_ADD_64(sum, value64); 10136 } 10137 } 10138 BCM_IF_ERROR_RETURN 10139 (_bcm_mn_cosq_index_resolve 10140 (unit, port, ci, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_MCAST, 10141 &local_port, &startq, &numq)); 10142 for (i = 0; i < numq; i++) { 10143 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10144 BCM_IF_ERROR_RETURN 10145 (counter_get(unit, local_port, 10146 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE, 10147 startq + i, &value64)); 10148 COMPILER_64_ADD_64(sum, value64); 10149 } 10150 } 10151 *value = sum; 10152 } 10153 break; 10154 case bcmCosqStatIeee8021CnCpTransmittedCnms: 10155 BCM_IF_ERROR_RETURN 10156 (_bcm_mn_cosq_index_resolve 10157 (unit, port, cosq, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_UCAST, 10158 &local_port, &startq, NULL)); 10159 BCM_IF_ERROR_RETURN 10160 (counter_get(unit, local_port, 10161 SOC_COUNTER_NON_DMA_MMU_QCN_CNM, startq, value)); 10162 break; 10163 case bcmCosqStatIngressPortPoolSharedBytesPeak: 10164 10165 COMPILER_64_ZERO(sum); 10166 BCM_IF_ERROR_RETURN 10167 (_bcm_mn_cosq_ingress_sp_get(unit, port, cosq, 10168 &start_hw_index, &end_hw_index)); 10169 10170 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_localport_resolve(unit, port, &local_port)); 10171 for (i = start_hw_index; i <= end_hw_index; i++) { 10172 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10173 BCM_IF_ERROR_RETURN 10174 (counter_get(unit, local_port, 10175 SOC_COUNTER_NON_DMA_POOL_PEAK, 10176 i, &value64)); 10177 COMPILER_64_ADD_64(sum, value64); 10178 } 10179 10180 COMPILER_64_UMUL_32(sum, _BCM_MN_BYTES_PER_CELL); 10181 *value = sum; 10182 break; 10183 case bcmCosqStatIngressPortPoolSharedBytesCurrent: 10184 10185 BCM_IF_ERROR_RETURN 10186 (_bcm_mn_cosq_ingress_sp_get(unit, port, cosq, 10187 &start_hw_index, &end_hw_index)); 10188 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_localport_resolve(unit, port, &local_port)); 10189 10190 COMPILER_64_ZERO(sum); 10191 for (i = start_hw_index; i <= end_hw_index; i++) { 10192 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10193 BCM_IF_ERROR_RETURN 10194 (counter_get(unit, local_port, 10195 SOC_COUNTER_NON_DMA_POOL_CURRENT, 10196 i, &value64)); 10197 COMPILER_64_ADD_64(sum, value64); 10198 } 10199 10200 COMPILER_64_UMUL_32(sum, _BCM_MN_BYTES_PER_CELL); 10201 *value = sum; 10202 break; 10203 10204 case bcmCosqStatIngressPortPGMinBytesPeak: 10205 10206 BCM_IF_ERROR_RETURN 10207 (_bcm_mn_cosq_ingress_pg_get(unit, port, cosq, 10208 &start_hw_index, &end_hw_index)); 10209 COMPILER_64_ZERO(sum); 10210 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_localport_resolve(unit, port, &local_port)); 10211 10212 for (i = start_hw_index; i <= end_hw_index; i++) { 10213 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10214 BCM_IF_ERROR_RETURN 10215 (counter_get(unit, local_port, 10216 SOC_COUNTER_NON_DMA_PG_MIN_PEAK, 10217 i, &value64)); 10218 COMPILER_64_ADD_64(sum, value64); 10219 } 10220 10221 COMPILER_64_UMUL_32(sum, _BCM_MN_BYTES_PER_CELL); 10222 *value = sum; 10223 break; 10224 case bcmCosqStatIngressPortPGMinBytesCurrent: 10225 10226 BCM_IF_ERROR_RETURN 10227 (_bcm_mn_cosq_ingress_pg_get(unit, port, cosq, 10228 &start_hw_index, &end_hw_index)); 10229 COMPILER_64_ZERO(sum); 10230 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_localport_resolve(unit, port, &local_port)); 10231 10232 for (i = start_hw_index; i <= end_hw_index; i++) { 10233 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10234 BCM_IF_ERROR_RETURN 10235 (counter_get(unit, local_port, 10236 SOC_COUNTER_NON_DMA_PG_MIN_CURRENT, 10237 i, &value64)); 10238 COMPILER_64_ADD_64(sum, value64); 10239 } 10240 10241 COMPILER_64_UMUL_32(sum, _BCM_MN_BYTES_PER_CELL); 10242 *value = sum; 10243 break; 10244 10245 case bcmCosqStatIngressPortPGSharedBytesPeak: 10246 10247 BCM_IF_ERROR_RETURN 10248 (_bcm_mn_cosq_ingress_pg_get(unit, port, cosq, 10249 &start_hw_index, &end_hw_index)); 10250 COMPILER_64_ZERO(sum); 10251 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_localport_resolve(unit, port, &local_port)); 10252 10253 for (i = start_hw_index; i <= end_hw_index; i++) { 10254 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10255 BCM_IF_ERROR_RETURN 10256 (counter_get(unit, local_port, 10257 SOC_COUNTER_NON_DMA_PG_SHARED_PEAK, 10258 i, &value64)); 10259 COMPILER_64_ADD_64(sum, value64); 10260 } 10261 10262 COMPILER_64_UMUL_32(sum, _BCM_MN_BYTES_PER_CELL); 10263 *value = sum; 10264 break; 10265 10266 case bcmCosqStatIngressPortPGSharedBytesCurrent: 10267 10268 BCM_IF_ERROR_RETURN 10269 (_bcm_mn_cosq_ingress_pg_get(unit, port, cosq, 10270 &start_hw_index, &end_hw_index)); 10271 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_localport_resolve(unit, port, &local_port)); 10272 COMPILER_64_ZERO(sum); 10273 10274 for (i = start_hw_index; i <= end_hw_index; i++) { 10275 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10276 BCM_IF_ERROR_RETURN 10277 (counter_get(unit, local_port, 10278 SOC_COUNTER_NON_DMA_PG_SHARED_CURRENT, 10279 i, &value64)); 10280 COMPILER_64_ADD_64(sum, value64); 10281 } 10282 COMPILER_64_UMUL_32(sum, _BCM_MN_BYTES_PER_CELL); 10283 *value = sum; 10284 10285 break; 10286 10287 case bcmCosqStatIngressPortPGHeadroomBytesPeak: 10288 10289 BCM_IF_ERROR_RETURN 10290 (_bcm_mn_cosq_ingress_pg_get(unit, port, cosq, 10291 &start_hw_index, &end_hw_index)); 10292 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_localport_resolve(unit, port, &local_port)); 10293 COMPILER_64_ZERO(sum); 10294 10295 for (i = start_hw_index; i <= end_hw_index; i++) { 10296 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10297 BCM_IF_ERROR_RETURN 10298 (counter_get(unit, local_port, 10299 SOC_COUNTER_NON_DMA_PG_HDRM_PEAK, 10300 i, &value64)); 10301 COMPILER_64_ADD_64(sum, value64); 10302 } 10303 COMPILER_64_UMUL_32(sum, _BCM_MN_BYTES_PER_CELL); 10304 *value = sum; 10305 10306 break; 10307 10308 case bcmCosqStatIngressPortPGHeadroomBytesCurrent: 10309 10310 BCM_IF_ERROR_RETURN 10311 (_bcm_mn_cosq_ingress_pg_get(unit, port, cosq, 10312 &start_hw_index, &end_hw_index)); 10313 10314 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_localport_resolve(unit, port, &local_port)); 10315 COMPILER_64_ZERO(sum); 10316 for (i = start_hw_index; i <= end_hw_index; i++) { 10317 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10318 BCM_IF_ERROR_RETURN 10319 (counter_get(unit, local_port, 10320 SOC_COUNTER_NON_DMA_PG_HDRM_CURRENT, 10321 i, &value64)); 10322 COMPILER_64_ADD_64(sum, value64); 10323 } 10324 COMPILER_64_UMUL_32(sum, _BCM_MN_BYTES_PER_CELL); 10325 *value = sum; 10326 10327 break; 10328 10329 case bcmCosqStatEgressMCQueueBytesPeak: 10330 if (BCM_GPORT_IS_SCHEDULER(port)) { 10331 if (cosq == BCM_COS_INVALID ) 10332 { 10333 return BCM_E_PARAM; 10334 } 10335 BCM_IF_ERROR_RETURN 10336 (_bcm_mn_cosq_node_get(unit, port, 0, NULL, 10337 &local_port, NULL, &node)); 10338 10339 BCM_IF_ERROR_RETURN( 10340 _bcm_mn_cosq_child_node_at_input(node, cosq, &node)); 10341 if (node->level != SOC_MONTEREY_NODE_LVL_L2) { 10342 return BCM_E_PARAM; 10343 } 10344 port = node->gport; 10345 } 10346 10347 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) { 10348 return BCM_E_PARAM; 10349 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 10350 BCM_IF_ERROR_RETURN 10351 (_bcm_mn_cosq_index_resolve 10352 (unit, port, 0, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_MCAST, 10353 &local_port, &startq, NULL)); 10354 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10355 BCM_IF_ERROR_RETURN 10356 (counter_get(unit, local_port, 10357 SOC_COUNTER_NON_DMA_QUEUE_PEAK, startq, 10358 value)); 10359 COMPILER_64_UMUL_32(*value, _BCM_MN_BYTES_PER_CELL); 10360 } else { 10361 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_localport_resolve(unit, port, &local_port)); 10362 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_port_has_ets(unit, port)); 10363 COMPILER_64_ZERO(sum); 10364 if (cosq == BCM_COS_INVALID) { 10365 from_cos = to_cos = 0; 10366 } else { 10367 from_cos = to_cos = cosq; 10368 } 10369 10370 for (ci = from_cos; ci <= to_cos; ci++) { 10371 BCM_IF_ERROR_RETURN 10372 (_bcm_mn_cosq_index_resolve 10373 (unit, port, ci, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_MCAST, 10374 &local_port, &startq, &numq)); 10375 for (i = 0; i < numq; i++) { 10376 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10377 BCM_IF_ERROR_RETURN 10378 (counter_get(unit, local_port, 10379 SOC_COUNTER_NON_DMA_QUEUE_PEAK, 10380 startq + i, &value64)); 10381 COMPILER_64_ADD_64(sum, value64); 10382 } 10383 } 10384 COMPILER_64_UMUL_32(sum, _BCM_MN_BYTES_PER_CELL); 10385 *value = sum; 10386 } 10387 break; 10388 case bcmCosqStatEgressMCQueueBytesCurrent: 10389 if (BCM_GPORT_IS_SCHEDULER(port)) { 10390 BCM_IF_ERROR_RETURN 10391 (_bcm_mn_cosq_node_get(unit, port, 0, NULL, 10392 &local_port, NULL, &node)); 10393 if (cosq == BCM_COS_INVALID) { 10394 return BCM_E_PARAM; 10395 } 10396 BCM_IF_ERROR_RETURN( 10397 _bcm_mn_cosq_child_node_at_input(node, cosq, &node)); 10398 if (node->level != SOC_MONTEREY_NODE_LVL_L2) { 10399 return BCM_E_PARAM; 10400 } 10401 port = node->gport; 10402 } 10403 10404 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) { 10405 return BCM_E_PARAM; 10406 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 10407 BCM_IF_ERROR_RETURN 10408 (_bcm_mn_cosq_index_resolve 10409 (unit, port, 0, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_MCAST, 10410 &local_port, &startq, NULL)); 10411 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10412 BCM_IF_ERROR_RETURN 10413 (counter_get(unit, local_port, 10414 SOC_COUNTER_NON_DMA_QUEUE_CURRENT, startq, 10415 value)); 10416 COMPILER_64_UMUL_32(*value, _BCM_MN_BYTES_PER_CELL); 10417 } else { 10418 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_localport_resolve(unit, port, &local_port)); 10419 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_port_has_ets(unit, port)); 10420 COMPILER_64_ZERO(sum); 10421 if (cosq == BCM_COS_INVALID) { 10422 from_cos = 0; 10423 to_cos = (IS_CPU_PORT(unit, local_port)) ? 10424 NUM_CPU_COSQ(unit) - 1 : _MN_NUM_COS(unit) - 1; 10425 } else { 10426 from_cos = to_cos = cosq; 10427 } 10428 10429 for (ci = from_cos; ci <= to_cos; ci++) { 10430 BCM_IF_ERROR_RETURN 10431 (_bcm_mn_cosq_index_resolve 10432 (unit, port, ci, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_MCAST, 10433 &local_port, &startq, &numq)); 10434 for (i = 0; i < numq; i++) { 10435 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10436 BCM_IF_ERROR_RETURN 10437 (counter_get(unit, local_port, 10438 SOC_COUNTER_NON_DMA_QUEUE_CURRENT, 10439 startq + i, &value64)); 10440 COMPILER_64_ADD_64(sum, value64); 10441 } 10442 } 10443 COMPILER_64_UMUL_32(sum, _BCM_MN_BYTES_PER_CELL); 10444 *value = sum; 10445 } 10446 break; 10447 10448 case bcmCosqStatEgressUCQueueBytesPeak: 10449 if (BCM_GPORT_IS_SCHEDULER(port)) { 10450 BCM_IF_ERROR_RETURN 10451 (_bcm_mn_cosq_node_get(unit, port, 0, NULL, 10452 &local_port, NULL, &node)); 10453 if (cosq == BCM_COS_INVALID) { 10454 return BCM_E_PARAM; 10455 } 10456 BCM_IF_ERROR_RETURN( 10457 _bcm_mn_cosq_child_node_at_input(node, cosq, &node)); 10458 if (node->level != SOC_MONTEREY_NODE_LVL_L2) { 10459 return BCM_E_PARAM; 10460 } 10461 port = node->gport; 10462 } 10463 10464 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) { 10465 BCM_IF_ERROR_RETURN 10466 (_bcm_mn_cosq_index_resolve 10467 (unit, port, 0, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_UCAST, 10468 &local_port, &startq, NULL)); 10469 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10470 BCM_IF_ERROR_RETURN 10471 (counter_get(unit, local_port, 10472 SOC_COUNTER_NON_DMA_UC_QUEUE_PEAK, startq, 10473 value)); 10474 COMPILER_64_UMUL_32(*value, _BCM_MN_BYTES_PER_CELL); 10475 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 10476 return BCM_E_PARAM; 10477 } else { 10478 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_localport_resolve(unit, port, &local_port)); 10479 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_port_has_ets(unit, port)); 10480 COMPILER_64_ZERO(sum); 10481 if (cosq == BCM_COS_INVALID) { 10482 from_cos = to_cos = 0; 10483 } else { 10484 from_cos = to_cos = cosq; 10485 } 10486 10487 if (IS_CPU_PORT(unit, local_port)) { 10488 return BCM_E_PARAM; 10489 } 10490 for (ci = from_cos; ci <= to_cos; ci++) { 10491 BCM_IF_ERROR_RETURN 10492 (_bcm_mn_cosq_index_resolve 10493 (unit, port, ci, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_UCAST, 10494 &local_port, &startq, &numq)); 10495 for (i = 0; i < numq; i++) { 10496 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10497 BCM_IF_ERROR_RETURN 10498 (counter_get(unit, local_port, 10499 SOC_COUNTER_NON_DMA_UC_QUEUE_PEAK, 10500 startq + i, &value64)); 10501 COMPILER_64_ADD_64(sum, value64); 10502 } 10503 } 10504 COMPILER_64_UMUL_32(sum, _BCM_MN_BYTES_PER_CELL); 10505 *value = sum; 10506 } 10507 break; 10508 case bcmCosqStatEgressUCQueueBytesCurrent: 10509 if (BCM_GPORT_IS_SCHEDULER(port)) { 10510 BCM_IF_ERROR_RETURN 10511 (_bcm_mn_cosq_node_get(unit, port, 0, NULL, 10512 &local_port, NULL, &node)); 10513 10514 if (cosq == BCM_COS_INVALID) { 10515 return BCM_E_PARAM; 10516 } 10517 BCM_IF_ERROR_RETURN( 10518 _bcm_mn_cosq_child_node_at_input(node, cosq, &node)); 10519 if (node->level != SOC_MONTEREY_NODE_LVL_L2) { 10520 return BCM_E_PARAM; 10521 } 10522 port = node->gport; 10523 } 10524 10525 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) { 10526 BCM_IF_ERROR_RETURN 10527 (_bcm_mn_cosq_index_resolve 10528 (unit, port, 0, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_UCAST, 10529 &local_port, &startq, NULL)); 10530 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10531 BCM_IF_ERROR_RETURN 10532 (counter_get(unit, local_port, 10533 SOC_COUNTER_NON_DMA_UC_QUEUE_CURRENT, startq, 10534 value)); 10535 COMPILER_64_UMUL_32(*value, _BCM_MN_BYTES_PER_CELL); 10536 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 10537 return BCM_E_PARAM; 10538 } else { 10539 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_localport_resolve(unit, port, &local_port)); 10540 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_port_has_ets(unit, port)); 10541 10542 if (IS_CPU_PORT(unit, local_port)) { 10543 return BCM_E_PARAM; 10544 } 10545 COMPILER_64_ZERO(sum); 10546 if (cosq == BCM_COS_INVALID) { 10547 from_cos = 0; 10548 to_cos = (IS_CPU_PORT(unit, local_port)) ? 10549 NUM_CPU_COSQ(unit) - 1 : _MN_NUM_COS(unit) - 1; 10550 } else { 10551 from_cos = to_cos = cosq; 10552 } 10553 10554 for (ci = from_cos; ci <= to_cos; ci++) { 10555 BCM_IF_ERROR_RETURN 10556 (_bcm_mn_cosq_index_resolve 10557 (unit, port, ci, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_UCAST, 10558 &local_port, &startq, &numq)); 10559 for (i = 0; i < numq; i++) { 10560 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10561 BCM_IF_ERROR_RETURN 10562 (counter_get(unit, local_port, 10563 SOC_COUNTER_NON_DMA_UC_QUEUE_CURRENT, 10564 startq + i, &value64)); 10565 COMPILER_64_ADD_64(sum, value64); 10566 } 10567 } 10568 COMPILER_64_UMUL_32(sum, _BCM_MN_BYTES_PER_CELL); 10569 *value = sum; 10570 } 10571 break; 10572 10573 case bcmCosqStatGlobalHeadroomBytes0Peak: 10574 BCM_IF_ERROR_RETURN 10575 (counter_get(unit, -1, 10576 SOC_COUNTER_NON_DMA_COSQ_GLOBAL_HDR_COUNT_X_PEAK, 10577 0, value)); 10578 COMPILER_64_UMUL_32(*value, _BCM_MN_BYTES_PER_CELL); 10579 break; 10580 case bcmCosqStatGlobalHeadroomBytes0Current: 10581 BCM_IF_ERROR_RETURN 10582 (counter_get(unit, -1, 10583 SOC_COUNTER_NON_DMA_COSQ_GLOBAL_HDR_COUNT_X_CURRENT, 10584 0, value)); 10585 COMPILER_64_UMUL_32(*value, _BCM_MN_BYTES_PER_CELL); 10586 break; 10587 case bcmCosqStatGlobalHeadroomBytes1Peak: 10588 BCM_IF_ERROR_RETURN 10589 (counter_get(unit, -1, 10590 SOC_COUNTER_NON_DMA_COSQ_GLOBAL_HDR_COUNT_Y_PEAK, 10591 0, value)); 10592 COMPILER_64_UMUL_32(*value, _BCM_MN_BYTES_PER_CELL); 10593 break; 10594 case bcmCosqStatGlobalHeadroomBytes1Current: 10595 BCM_IF_ERROR_RETURN 10596 (counter_get(unit, -1, 10597 SOC_COUNTER_NON_DMA_COSQ_GLOBAL_HDR_COUNT_Y_CURRENT, 10598 0, value)); 10599 COMPILER_64_UMUL_32(*value, _BCM_MN_BYTES_PER_CELL); 10600 break; 10601 case bcmCosqStatHighPriDroppedPackets: 10602 case bcmCosqStatOBMLossyHighPriDroppedPackets: 10603 case bcmCosqStatLowPriDroppedPackets: 10604 case bcmCosqStatOBMLossyLowPriDroppedPackets: 10605 case bcmCosqStatHighPriDroppedBytes: 10606 case bcmCosqStatOBMLossyHighPriDroppedBytes: 10607 case bcmCosqStatLowPriDroppedBytes: 10608 case bcmCosqStatOBMLossyLowPriDroppedBytes: 10609 case bcmCosqStatOBMLossless0DroppedPackets: 10610 case bcmCosqStatOBMLossless1DroppedPackets: 10611 case bcmCosqStatOBMLossless0DroppedBytes: 10612 case bcmCosqStatOBMLossless1DroppedBytes: 10613 case bcmCosqStatOBMLossless0EnqueuedPackets: 10614 case bcmCosqStatOBMLossless0EnqueuedBytes: 10615 case bcmCosqStatOBMLossless1EnqueuedPackets: 10616 case bcmCosqStatOBMLossless1EnqueuedBytes: 10617 case bcmCosqStatOBMLossyHighPriEnqueuedPackets: 10618 case bcmCosqStatOBMLossyHighPriEnqueuedBytes: 10619 case bcmCosqStatOBMLossyLowPriEnqueuedPackets: 10620 case bcmCosqStatOBMLossyLowPriEnqueuedBytes: 10621 case bcmCosqStatOBMExpressEnqueuedPackets: 10622 case bcmCosqStatOBMExpressEnqueuedBytes: 10623 case bcmCosqStatOBMExpressDroppedPackets: 10624 case bcmCosqStatOBMExpressDroppedBytes: 10625 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 10626 BCM_GPORT_IS_SCHEDULER(port) || 10627 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 10628 return BCM_E_PARAM; 10629 } 10630 BCM_IF_ERROR_RETURN( 10631 _bcm_mn_cosq_localport_resolve(unit, port, &local_port)); 10632 if ((stat == bcmCosqStatHighPriDroppedPackets) || 10633 (stat == bcmCosqStatOBMLossyHighPriDroppedPackets)) { 10634 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM_LOSSY_HI; 10635 } else if ((stat == bcmCosqStatLowPriDroppedPackets) || 10636 (stat == bcmCosqStatOBMLossyLowPriDroppedPackets)) { 10637 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM_LOSSY_LO; 10638 } else if ((stat == bcmCosqStatHighPriDroppedBytes) || 10639 (stat == bcmCosqStatOBMLossyHighPriDroppedBytes)) { 10640 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM_LOSSY_HI; 10641 } else if ((stat == bcmCosqStatLowPriDroppedBytes) || 10642 (stat == bcmCosqStatOBMLossyLowPriDroppedBytes)) { 10643 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM_LOSSY_LO; 10644 } else if (stat == bcmCosqStatOBMLossless0DroppedPackets) { 10645 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM_LOSSLESS0; 10646 } else if (stat == bcmCosqStatOBMLossless1DroppedPackets) { 10647 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM_LOSSLESS1; 10648 } else if (stat == bcmCosqStatOBMLossless0DroppedBytes) { 10649 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM_LOSSLESS0; 10650 } else if (stat == bcmCosqStatOBMLossless1DroppedBytes) { 10651 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM_LOSSLESS1; 10652 } else if (stat == bcmCosqStatOBMLossless0EnqueuedPackets) { 10653 ctr_reg = SOC_COUNTER_NON_DMA_PORT_ENQUEUE_PKT_OBM_LOSSLESS0; 10654 } else if (stat == bcmCosqStatOBMLossless0EnqueuedBytes) { 10655 ctr_reg = SOC_COUNTER_NON_DMA_PORT_ENQUEUE_BYTE_OBM_LOSSLESS0; 10656 } else if (stat == bcmCosqStatOBMLossless1EnqueuedPackets) { 10657 ctr_reg = SOC_COUNTER_NON_DMA_PORT_ENQUEUE_PKT_OBM_LOSSLESS1; 10658 } else if (stat == bcmCosqStatOBMLossless1EnqueuedBytes) { 10659 ctr_reg = SOC_COUNTER_NON_DMA_PORT_ENQUEUE_BYTE_OBM_LOSSLESS1; 10660 } else if (stat == bcmCosqStatOBMLossyHighPriEnqueuedPackets) { 10661 ctr_reg = SOC_COUNTER_NON_DMA_PORT_ENQUEUE_PKT_OBM_LOSSY_HI; 10662 } else if (stat == bcmCosqStatOBMLossyHighPriEnqueuedBytes) { 10663 ctr_reg = SOC_COUNTER_NON_DMA_PORT_ENQUEUE_BYTE_OBM_LOSSY_HI; 10664 } else if (stat == bcmCosqStatOBMLossyLowPriEnqueuedPackets) { 10665 ctr_reg = SOC_COUNTER_NON_DMA_PORT_ENQUEUE_PKT_OBM_LOSSY_LO; 10666 } else if (stat == bcmCosqStatOBMLossyLowPriEnqueuedBytes) { 10667 ctr_reg = SOC_COUNTER_NON_DMA_PORT_ENQUEUE_BYTE_OBM_LOSSY_LO; 10668 } else if (stat == bcmCosqStatOBMExpressEnqueuedPackets) { 10669 ctr_reg = SOC_COUNTER_NON_DMA_PORT_ENQUEUE_PKT_OBM_EXPRESS; 10670 } else if (stat == bcmCosqStatOBMExpressEnqueuedBytes) { 10671 ctr_reg = SOC_COUNTER_NON_DMA_PORT_ENQUEUE_BYTE_OBM_EXPRESS; 10672 } else if (stat == bcmCosqStatOBMExpressDroppedPackets) { 10673 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM_EXPRESS; 10674 } else { /*if (stat == bcmCosqStatOBMExpressDroppedBytes) */ 10675 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM_EXPRESS; 10676 } 10677 ctrl_info.instance_type = SOC_CTR_INSTANCE_TYPE_PORT; 10678 ctrl_info.instance = local_port; 10679 BCM_IF_ERROR_RETURN 10680 (soc_counter_generic_get(unit, ctr_reg, ctrl_info, 0, 10681 0, value)); 10682 break; 10683 default: 10684 return BCM_E_PARAM; 10685 } 10686 10687 return BCM_E_NONE; 10688 } 10689 10690 /* 10691 * Function: 10692 * _bcm_mn_cosq_quantize_table_set 10693 * Purpose: 10694 * Generate quantized feedback lookup table 10695 * Parameters: 10696 * unit - (IN) unit number 10697 * profile_index - (IN) profile index 10698 * weight_code - (IN) weight encoding 10699 * set_point - (IN) queue size set point 10700 * active_offset - (OUT) most significant non-zero bit position 10701 * Returns: 10702 * BCM_E_XXX 10703 * Notes: 10704 * The formular to quantize feedback value is: 10705 * quantized_feedbad = celling(feedback / max_feedback * 63) 10706 * where max_feedback = (2 * cpW + 1) * cpQsp 10707 * cpW is feedback weight 10708 * cpQsp is queue size set point 10709 */ 10710 STATIC int 10711 _bcm_mn_cosq_quantize_table_set(int unit, int profile_index, int weight_code, 10712 int set_point, int *active_offset) 10713 { 10714 int ref_count; 10715 int weight_x_4, feedback, max_feedback, quantized_feedback, shift; 10716 int base_index, index; 10717 10718 /* weight = 2 ** (weight_code - 2) e.g. 0 for 1/4, 1 for 1/2, ... */ 10719 weight_x_4 = 1 << weight_code; 10720 max_feedback = ((2 * weight_x_4 + 4) * set_point + 3) / 4; 10721 shift = 0; 10722 while ((max_feedback >> shift) > 127) { 10723 shift++; 10724 } 10725 10726 BCM_IF_ERROR_RETURN 10727 (soc_profile_reg_ref_count_get(unit, _bcm_mn_feedback_profile[unit], 10728 profile_index, &ref_count)); 10729 10730 /* 10731 * Hardware use lookup table to find quantized feedback in order to avoid 10732 * division, use most significant 7-bit of feedback value as lookup table 10733 * index to find quantized_feedback value 10734 */ 10735 if (ref_count == 1) { 10736 base_index = profile_index << 7; 10737 for (index = 0; index < 128; index++) { 10738 feedback = index << shift; 10739 if (feedback > max_feedback) { 10740 quantized_feedback = 63; 10741 } else { 10742 quantized_feedback = (feedback * 63 + max_feedback - 1) / 10743 max_feedback; 10744 } 10745 BCM_IF_ERROR_RETURN 10746 (soc_mem_field32_modify(unit, MMU_QCN_QFBTBm, 10747 base_index + index, CPQ_QNTZFBf, 10748 quantized_feedback)); 10749 } 10750 } 10751 10752 *active_offset = shift + 6; 10753 10754 return BCM_E_NONE; 10755 } 10756 10757 10758 STATIC int 10759 _bcm_mn_cosq_sample_int_table_set(int unit, int min, int max, 10760 uint32 *profile_index) 10761 { 10762 mmu_qcn_sitb_entry_t sitb_entries[64]; 10763 void *entries[1]; 10764 int i, j, center, inc, value, index; 10765 10766 sal_memset(sitb_entries, 0, sizeof(sitb_entries)); 10767 entries[0] = &sitb_entries; 10768 for (i = 0; i < 8; i++) { 10769 center = max - (max - min) * i / 7; 10770 inc = (max - min) / 7 / 8; 10771 for (j = 0; j < 8; j++, inc = -inc) { 10772 index = i * 8 + j; 10773 value = center + (j + 1) / 2 * inc; 10774 if (value > 255) { 10775 value = 255; 10776 } else if (value < 1) { 10777 value = 1; 10778 } 10779 soc_mem_field32_set(unit, MMU_QCN_SITBm, &sitb_entries[index], 10780 CPQ_SIf, value); 10781 } 10782 } 10783 10784 return soc_profile_mem_add(unit, _bcm_mn_sample_int_profile[unit], entries, 10785 64, (uint32 *)profile_index); 10786 } 10787 10788 /* 10789 * Function: 10790 * bcm_mn_cosq_congestion_queue_set 10791 * Purpose: 10792 * Enable/Disable a cos queue as congestion managed queue 10793 * Parameters: 10794 * unit - (IN) unit number 10795 * port - (IN) port number or GPORT identifier 10796 * cosq - (IN) COS queue number 10797 * index - (IN) congestion managed queue index 10798 * Returns: 10799 * BCM_E_XXX 10800 */ 10801 int 10802 bcm_mn_cosq_congestion_queue_set(int unit, bcm_port_t port, 10803 bcm_cos_queue_t cosq, int index) 10804 { 10805 bcm_port_t local_port; 10806 uint32 rval; 10807 uint64 rval64, *rval64s[1]; 10808 mmu_qcn_enable_entry_t enable_entry; 10809 int active_offset, qindex; 10810 uint32 profile_index, sample_profile_index; 10811 int weight_code, set_point; 10812 soc_mem_t mem; 10813 int maxindex = 0 ; 10814 if (cosq < 0 || cosq >= _MN_NUM_COS(unit)) { 10815 return BCM_E_PARAM; 10816 } 10817 10818 if ((index < -1) || (index >= _BCM_MN_NUM_L2_UC_LEAVES)) { 10819 return BCM_E_PARAM; 10820 } 10821 10822 BCM_IF_ERROR_RETURN 10823 (_bcm_mn_cosq_index_resolve(unit, port, cosq, 10824 _BCM_MN_COSQ_INDEX_STYLE_QCN, 10825 &local_port, &qindex, NULL)); 10826 10827 mem = MMU_QCN_ENABLE_0m; 10828 maxindex = soc_mem_index_count(unit, mem); 10829 if ((qindex < -1) || (qindex >= maxindex)) { 10830 return BCM_E_PARAM; 10831 } 10832 10833 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ANY, 10834 qindex, &enable_entry)); 10835 if (index == -1) { 10836 if (!soc_mem_field32_get(unit, mem, &enable_entry, CPQ_ENf)) { 10837 return BCM_E_NONE; 10838 } 10839 10840 index = soc_mem_field32_get(unit, mem, &enable_entry, CPQ_PROFILE_INDEXf); 10841 soc_mem_field32_set(unit, mem, &enable_entry, CPQ_ENf, 0); 10842 BCM_IF_ERROR_RETURN 10843 (soc_mem_write(unit, mem, MEM_BLOCK_ANY, qindex, &enable_entry)); 10844 10845 profile_index = soc_mem_field32_get(unit, mem, &enable_entry, EQTB_INDEXf); 10846 10847 BCM_IF_ERROR_RETURN 10848 (soc_profile_reg_delete(unit, _bcm_mn_feedback_profile[unit], 10849 profile_index)); 10850 10851 profile_index = 10852 soc_mem_field32_get(unit, mem, &enable_entry, SITB_SELf); 10853 10854 BCM_IF_ERROR_RETURN 10855 (soc_profile_mem_delete(unit, _bcm_mn_sample_int_profile[unit], 10856 profile_index * 64)); 10857 } else { 10858 if (soc_mem_field32_get(unit, mem, &enable_entry, CPQ_ENf)) { 10859 return BCM_E_BUSY; 10860 } 10861 10862 /* Use hardware reset value as default quantize setting */ 10863 weight_code = 3; 10864 set_point = 0x96; 10865 rval = 0; 10866 soc_reg_field_set(unit, MMU_QCN_CPQ_SEQr, &rval, CPWf, weight_code); 10867 soc_reg_field_set(unit, MMU_QCN_CPQ_SEQr, &rval, CPQEQf, set_point); 10868 COMPILER_64_SET(rval64, 0, rval); 10869 rval64s[0] = &rval64; 10870 BCM_IF_ERROR_RETURN 10871 (soc_profile_reg_add(unit, _bcm_mn_feedback_profile[unit], 10872 rval64s, 1, (uint32 *)&profile_index)); 10873 10874 /* Update quantized feedback calculation lookup table */ 10875 BCM_IF_ERROR_RETURN 10876 (_bcm_mn_cosq_quantize_table_set(unit, profile_index, weight_code, 10877 set_point, &active_offset)); 10878 10879 /* Pick some sample interval */ 10880 BCM_IF_ERROR_RETURN 10881 (_bcm_mn_cosq_sample_int_table_set(unit, 13, 127, 10882 &sample_profile_index)); 10883 10884 soc_mem_field32_set(unit, mem, &enable_entry, 10885 QNTZ_ACT_OFFSETf, active_offset); 10886 10887 soc_mem_field32_set(unit, mem, &enable_entry, 10888 SITB_SELf, sample_profile_index/64); 10889 10890 soc_mem_field32_set(unit, mem, &enable_entry, EQTB_INDEXf, 10891 profile_index); 10892 10893 soc_mem_field32_set(unit, mem, &enable_entry, CPQ_IDf, index); 10894 10895 soc_mem_field32_set(unit, mem, &enable_entry, CPQ_ENf, 1); 10896 10897 BCM_IF_ERROR_RETURN 10898 (soc_mem_write(unit, mem, MEM_BLOCK_ANY, qindex, &enable_entry)); 10899 } 10900 10901 return BCM_E_NONE; 10902 } 10903 10904 /* 10905 * Function: 10906 * bcm_mn_cosq_congestion_queue_get 10907 * Purpose: 10908 * Get congestion managed queue index of the specified cos queue 10909 * Parameters: 10910 * unit - (IN) unit number 10911 * port - (IN) port number or GPORT identifier 10912 * cosq - (IN) COS queue number 10913 * index - (OUT) congestion managed queue index 10914 * Returns: 10915 * BCM_E_XXX 10916 */ 10917 int 10918 bcm_mn_cosq_congestion_queue_get(int unit, bcm_port_t port, 10919 bcm_cos_queue_t cosq, int *index) 10920 { 10921 bcm_port_t local_port; 10922 int qindex; 10923 mmu_qcn_enable_entry_t entry; 10924 soc_mem_t mem; 10925 int maxindex = 0; 10926 if (cosq < 0 || cosq >= _MN_NUM_COS(unit)) { 10927 return BCM_E_PARAM; 10928 } 10929 10930 if (index == NULL) { 10931 return BCM_E_PARAM; 10932 } 10933 10934 BCM_IF_ERROR_RETURN 10935 (_bcm_mn_cosq_index_resolve(unit, port, cosq, 10936 _BCM_MN_COSQ_INDEX_STYLE_QCN, 10937 &local_port, &qindex, NULL)); 10938 10939 mem = MMU_QCN_ENABLE_0m; 10940 maxindex = soc_mem_index_count(unit, mem); 10941 if ((qindex < -1) || (qindex >= maxindex)) { 10942 return BCM_E_PARAM; 10943 } 10944 10945 BCM_IF_ERROR_RETURN 10946 (soc_mem_read(unit, mem, MEM_BLOCK_ANY, qindex, &entry)); 10947 if (soc_mem_field32_get(unit, mem, &entry, CPQ_ENf)) { 10948 *index = soc_mem_field32_get(unit, mem, &entry, CPQ_IDf); 10949 } else { 10950 *index = -1; 10951 } 10952 10953 return BCM_E_NONE; 10954 } 10955 10956 /* 10957 * Function: 10958 * bcm_mn_cosq_congestion_quantize_set 10959 * Purpose: 10960 * Set quantized congestion feedback algorithm parameters 10961 * Parameters: 10962 * unit - (IN) unit number 10963 * port - (IN) port number or GPORT identifier 10964 * cosq - (IN) COS queue number 10965 * weight_code - (IN) weight encoding (use -1 for unchange) 10966 * set_point - (IN) queue size set point (use -1 for unchange) 10967 * Returns: 10968 * BCM_E_XXX 10969 */ 10970 int 10971 bcm_mn_cosq_congestion_quantize_set(int unit, bcm_port_t port, 10972 bcm_cos_queue_t cosq, int weight_code, 10973 int set_point) 10974 { 10975 bcm_port_t local_port; 10976 uint32 rval; 10977 uint64 rval64, *rval64s[1]; 10978 mmu_qcn_enable_entry_t enable_entry; 10979 int cpq_index, active_offset, qindex; 10980 uint32 profile_index, old_profile_index; 10981 soc_mem_t mem; 10982 int maxindex = 0; 10983 if (cosq < 0 || cosq >= _MN_NUM_COS(unit)) { 10984 return BCM_E_PARAM; 10985 } 10986 10987 10988 mem = MMU_QCN_ENABLE_0m; 10989 10990 BCM_IF_ERROR_RETURN 10991 (bcm_mn_cosq_congestion_queue_get(unit, port, cosq, &cpq_index)); 10992 if (cpq_index == -1) { 10993 /* The cosq specified is not enabled as congestion managed queue */ 10994 return BCM_E_PARAM; 10995 } 10996 10997 BCM_IF_ERROR_RETURN 10998 (_bcm_mn_cosq_index_resolve(unit, port, cosq, 10999 _BCM_MN_COSQ_INDEX_STYLE_QCN, &local_port, &qindex, NULL)); 11000 11001 maxindex = soc_mem_index_count(unit, mem); 11002 if ((qindex < -1) || (qindex >= maxindex)) { 11003 return BCM_E_PARAM; 11004 } 11005 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ANY, qindex, &enable_entry)); 11006 old_profile_index = 11007 soc_mem_field32_get(unit, mem, &enable_entry, EQTB_INDEXf); 11008 11009 BCM_IF_ERROR_RETURN(READ_MMU_QCN_CPQ_SEQr(unit, old_profile_index, &rval)); 11010 if (weight_code == -1) { 11011 weight_code = soc_reg_field_get(unit, MMU_QCN_CPQ_SEQr, rval, CPWf); 11012 } else { 11013 if (weight_code < 0 || weight_code > 7) { 11014 return BCM_E_PARAM; 11015 } 11016 soc_reg_field_set(unit, MMU_QCN_CPQ_SEQr, &rval, CPWf, weight_code); 11017 } 11018 if (set_point == -1) { 11019 set_point = soc_reg_field_get(unit, MMU_QCN_CPQ_SEQr, rval, CPQEQf); 11020 } else { 11021 if (set_point < 0 || set_point > 0xffff) { 11022 return BCM_E_PARAM; 11023 } 11024 soc_reg_field_set(unit, MMU_QCN_CPQ_SEQr, &rval, CPQEQf, set_point); 11025 } 11026 COMPILER_64_SET(rval64, 0, rval); 11027 rval64s[0] = &rval64; 11028 /* Add new feedback parameter profile */ 11029 BCM_IF_ERROR_RETURN 11030 (soc_profile_reg_add(unit, _bcm_mn_feedback_profile[unit], rval64s, 11031 1, (uint32 *)&profile_index)); 11032 /* Delete original feedback parameter profile */ 11033 BCM_IF_ERROR_RETURN 11034 (soc_profile_reg_delete(unit, _bcm_mn_feedback_profile[unit], 11035 old_profile_index)); 11036 11037 /* Update quantized feedback calculation lookup table */ 11038 BCM_IF_ERROR_RETURN 11039 (_bcm_mn_cosq_quantize_table_set(unit, profile_index, weight_code, 11040 set_point, &active_offset)); 11041 11042 soc_mem_field32_set(unit, mem, &enable_entry, 11043 QNTZ_ACT_OFFSETf, active_offset); 11044 soc_mem_field32_set(unit, mem, &enable_entry, 11045 EQTB_INDEXf, profile_index); 11046 BCM_IF_ERROR_RETURN 11047 (soc_mem_write(unit, mem, MEM_BLOCK_ANY, qindex, 11048 &enable_entry)); 11049 11050 return BCM_E_NONE; 11051 } 11052 11053 /* 11054 * Function: 11055 * bcm_mn_cosq_congestion_quantize_get 11056 * Purpose: 11057 * Get quantized congestion feedback algorithm parameters 11058 * Parameters: 11059 * unit - (IN) unit number 11060 * port - (IN) port number or GPORT identifier 11061 * cosq - (IN) COS queue number 11062 * weight_code - (OUT) weight encoding 11063 * set_point - (OUT) queue size set point 11064 * Returns: 11065 * BCM_E_XXX 11066 */ 11067 int 11068 bcm_mn_cosq_congestion_quantize_get(int unit, bcm_port_t port, 11069 bcm_cos_queue_t cosq, int *weight_code, 11070 int *set_point) 11071 { 11072 bcm_port_t local_port; 11073 int cpq_index, profile_index, qindex; 11074 uint32 rval; 11075 mmu_qcn_enable_entry_t enable_entry; 11076 soc_mem_t mem; 11077 int maxindex = 0; 11078 11079 BCM_IF_ERROR_RETURN 11080 (bcm_mn_cosq_congestion_queue_get(unit, port, cosq, &cpq_index)); 11081 if (cpq_index == -1) { 11082 /* The cosq specified is not enabled as congestion managed queue */ 11083 return BCM_E_PARAM; 11084 } 11085 11086 BCM_IF_ERROR_RETURN 11087 (_bcm_mn_cosq_index_resolve(unit, port, cosq, 11088 _BCM_MN_COSQ_INDEX_STYLE_QCN, 11089 &local_port, &qindex, NULL)); 11090 11091 mem = MMU_QCN_ENABLE_0m; 11092 maxindex = soc_mem_index_count(unit, mem); 11093 if ((qindex < -1) || (qindex >= maxindex)) { 11094 return BCM_E_PARAM; 11095 } 11096 11097 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, 11098 MEM_BLOCK_ANY, qindex, &enable_entry)); 11099 profile_index = 11100 soc_mem_field32_get(unit, mem, &enable_entry, EQTB_INDEXf); 11101 11102 BCM_IF_ERROR_RETURN(READ_MMU_QCN_CPQ_SEQr(unit, profile_index, &rval)); 11103 if (weight_code != NULL) { 11104 *weight_code = soc_reg_field_get(unit, MMU_QCN_CPQ_SEQr, rval, CPWf); 11105 } 11106 if (set_point != NULL) { 11107 *set_point = soc_reg_field_get(unit, MMU_QCN_CPQ_SEQr, rval, CPQEQf); 11108 } 11109 11110 return BCM_E_NONE; 11111 } 11112 11113 int 11114 bcm_mn_cosq_congestion_sample_int_set(int unit, bcm_port_t port, 11115 bcm_cos_queue_t cosq, int min, int max) 11116 { 11117 bcm_port_t local_port; 11118 mmu_qcn_enable_entry_t entry; 11119 mmu_qcn_sitb_entry_t sitb_entry; 11120 int qindex; 11121 uint32 profile_index, old_profile_index; 11122 soc_mem_t mem; 11123 int maxindex = 0; 11124 BCM_IF_ERROR_RETURN 11125 (_bcm_mn_cosq_index_resolve(unit, port, cosq, 11126 _BCM_MN_COSQ_INDEX_STYLE_QCN, 11127 &local_port, &qindex, NULL)); 11128 11129 mem = MMU_QCN_ENABLE_0m; 11130 maxindex = soc_mem_index_count(unit, mem); 11131 if ((qindex < -1) || (qindex >= maxindex)) { 11132 return BCM_E_PARAM; 11133 } 11134 11135 11136 BCM_IF_ERROR_RETURN 11137 (soc_mem_read(unit, mem, MEM_BLOCK_ANY, qindex, &entry)); 11138 11139 if (!soc_mem_field32_get(unit, mem, &entry, CPQ_ENf)) { 11140 return BCM_E_PARAM; 11141 } 11142 11143 old_profile_index = 11144 soc_mem_field32_get(unit, mem, &entry, SITB_SELf); 11145 11146 if (max == -1) { 11147 BCM_IF_ERROR_RETURN(soc_mem_read(unit, MMU_QCN_SITBm, MEM_BLOCK_ANY, 11148 old_profile_index * 64, &sitb_entry)); 11149 max = soc_mem_field32_get(unit, MMU_QCN_SITBm, &sitb_entry, CPQ_SIf); 11150 } else { 11151 if (max < 1 || max > 255) { 11152 return BCM_E_PARAM; 11153 } 11154 } 11155 if (min == -1) { 11156 BCM_IF_ERROR_RETURN(soc_mem_read(unit, MMU_QCN_SITBm, MEM_BLOCK_ANY, 11157 old_profile_index * 64 + 63, 11158 &sitb_entry)); 11159 min = soc_mem_field32_get(unit, MMU_QCN_SITBm, &sitb_entry, CPQ_SIf); 11160 } else { 11161 if (min < 1 || min > 255) { 11162 return BCM_E_PARAM; 11163 } 11164 } 11165 11166 /* Add new sample interval profile */ 11167 BCM_IF_ERROR_RETURN 11168 (_bcm_mn_cosq_sample_int_table_set(unit, min, max, &profile_index)); 11169 11170 /* Delete original sample interval profile */ 11171 BCM_IF_ERROR_RETURN 11172 (soc_profile_mem_delete(unit, _bcm_mn_sample_int_profile[unit], 11173 old_profile_index * 64)); 11174 11175 soc_mem_field32_set(unit, mem, &entry, SITB_SELf, 11176 profile_index / 64); 11177 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ANY, 11178 qindex, &entry)); 11179 return BCM_E_NONE; 11180 } 11181 11182 int 11183 bcm_mn_cosq_congestion_sample_int_get(int unit, bcm_port_t port, 11184 bcm_cos_queue_t cosq, int *min, int *max) 11185 { 11186 bcm_port_t local_port; 11187 mmu_qcn_enable_entry_t entry; 11188 mmu_qcn_sitb_entry_t sitb_entry; 11189 int qindex; 11190 uint32 old_profile_index; 11191 soc_mem_t mem; 11192 int maxindex = 0 ; 11193 11194 BCM_IF_ERROR_RETURN 11195 (_bcm_mn_cosq_index_resolve(unit, port, cosq, 11196 _BCM_MN_COSQ_INDEX_STYLE_QCN, 11197 &local_port, &qindex, NULL)); 11198 11199 mem = MMU_QCN_ENABLE_0m; 11200 maxindex = soc_mem_index_count(unit, mem); 11201 if ((qindex < -1) || (qindex >= maxindex)) { 11202 return BCM_E_PARAM; 11203 } 11204 11205 BCM_IF_ERROR_RETURN 11206 (soc_mem_read(unit, mem, MEM_BLOCK_ANY, qindex, &entry)); 11207 11208 if (!soc_mem_field32_get(unit, mem, &entry, CPQ_ENf)) { 11209 return BCM_E_PARAM; 11210 } 11211 11212 old_profile_index = 11213 soc_mem_field32_get(unit, mem, &entry, SITB_SELf); 11214 11215 if (max) { 11216 BCM_IF_ERROR_RETURN(soc_mem_read(unit, MMU_QCN_SITBm, MEM_BLOCK_ANY, 11217 old_profile_index * 64, &sitb_entry)); 11218 *max = soc_mem_field32_get(unit, MMU_QCN_SITBm, &sitb_entry, CPQ_SIf); 11219 } 11220 11221 if (min) { 11222 BCM_IF_ERROR_RETURN(soc_mem_read(unit, MMU_QCN_SITBm, MEM_BLOCK_ANY, 11223 old_profile_index * 64 + 63, 11224 &sitb_entry)); 11225 *min = soc_mem_field32_get(unit, MMU_QCN_SITBm, &sitb_entry, CPQ_SIf); 11226 } 11227 11228 return BCM_E_NONE; 11229 } 11230 11231 STATIC int 11232 _bcm_mn_cosq_ing_pool_set(int unit, bcm_gport_t gport, bcm_cos_queue_t pri_grp, 11233 bcm_cosq_control_t type, int arg) 11234 { 11235 int local_port; 11236 uint32 rval; 11237 static const soc_field_t prigroup_spid_field[] = { 11238 PG0_SPIDf, PG1_SPIDf, PG2_SPIDf, PG3_SPIDf, 11239 PG4_SPIDf, PG5_SPIDf, PG6_SPIDf, PG7_SPIDf 11240 }; 11241 if(( arg < 0 ) || (arg > 3 )) { 11242 return BCM_E_PARAM; 11243 } 11244 11245 BCM_IF_ERROR_RETURN 11246 (_bcm_mn_cosq_localport_resolve(unit, gport, &local_port)); 11247 11248 if (!SOC_PORT_VALID(unit, local_port)) { 11249 return BCM_E_PORT; 11250 } 11251 11252 if ((pri_grp < 0) || (pri_grp >= 8)) { 11253 return BCM_E_PARAM; 11254 } 11255 11256 SOC_IF_ERROR_RETURN(READ_THDI_PORT_PG_SPIDr(unit, local_port, &rval)); 11257 soc_reg_field_set(unit, THDI_PORT_PG_SPIDr, &rval, 11258 prigroup_spid_field[pri_grp],arg); 11259 BCM_IF_ERROR_RETURN(WRITE_THDI_PORT_PG_SPIDr(unit, local_port, rval)); 11260 return BCM_E_NONE; 11261 } 11262 11263 STATIC int 11264 _bcm_mn_cosq_ing_pool_get(int unit, bcm_gport_t gport, 11265 bcm_cos_queue_t pri_grp, 11266 bcm_cosq_control_t type, int *arg) 11267 { 11268 int pool_start_idx = 0, pool_end_idx =0; 11269 BCM_IF_ERROR_RETURN( 11270 _bcm_mn_cosq_ingress_sp_get( 11271 unit, gport, pri_grp, &pool_start_idx, &pool_end_idx)); 11272 *arg = pool_start_idx; 11273 return BCM_E_NONE; 11274 } 11275 11276 /* 11277 * Function: 11278 * _bcm_mn_cosq_port_qnum_get 11279 * Purpose: 11280 * Get the hw queue number used to tx packets on respective Queue 11281 * Parameters: 11282 * unit - (IN) unit number 11283 * port - (IN) port number or GPORT identifier 11284 * cosq - (IN) COS queue number 11285 * type - (IN) unicast/multicast queue indicator 11286 * arg - (out) hw queue number 11287 * Returns: 11288 * BCM_E_XXX 11289 */ 11290 STATIC int 11291 _bcm_mn_cosq_port_qnum_get(int unit, bcm_gport_t gport, 11292 bcm_cos_queue_t cosq, bcm_cosq_control_t type, int *arg) 11293 { 11294 bcm_port_t local_port; 11295 int hw_index; 11296 int uc; 11297 int qnum; 11298 int id, startq, numq; 11299 _bcm_mn_cosq_node_t *node; 11300 soc_info_t *si = &SOC_INFO(unit); 11301 11302 if (!arg) { 11303 return BCM_E_PARAM; 11304 } 11305 11306 if (cosq <= -1) { 11307 return BCM_E_PARAM; 11308 } else { 11309 startq = cosq; 11310 numq = 1; 11311 } 11312 11313 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 11314 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 11315 BCM_IF_ERROR_RETURN 11316 (_bcm_mn_cosq_node_get(unit, gport, cosq, NULL, &local_port, &id, 11317 &node)); 11318 if (node->attached_to_input < 0) { /* Not resolved yet */ 11319 return BCM_E_NOT_FOUND; 11320 } 11321 11322 startq = 0; 11323 } else { 11324 /* optionally validate port */ 11325 BCM_IF_ERROR_RETURN 11326 (_bcm_mn_cosq_localport_resolve(unit, gport, &local_port)); 11327 if (local_port < 0) { 11328 return BCM_E_PORT; 11329 } 11330 node = NULL; 11331 numq = (IS_CPU_PORT(unit, local_port)) ? 11332 NUM_CPU_COSQ(unit) : NUM_COS(unit); 11333 } 11334 11335 if (startq >= numq) { 11336 return BCM_E_PARAM; 11337 } 11338 11339 uc =(type == bcmCosqControlPortQueueUcast) ? 1 : 0; 11340 11341 if (node) { 11342 hw_index = node->hw_index; 11343 } else { 11344 hw_index = soc_monterey_l2_hw_index(unit, 11345 si->port_uc_cosq_base[local_port] + startq, uc); 11346 } 11347 11348 qnum = soc_monterey_hw_index_logical_num(unit,local_port,hw_index,uc); 11349 *arg = soc_monterey_logical_qnum_hw_qnum(unit,local_port,qnum,uc); 11350 11351 return BCM_E_NONE; 11352 } 11353 11354 STATIC int 11355 _bcm_mn_cosq_egr_pool_set(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 11356 bcm_cosq_control_t type, int arg) 11357 { 11358 bcm_port_t local_port; 11359 int startq, pool, midx; 11360 uint32 max_val; 11361 uint32 entry[SOC_MAX_MEM_WORDS]; 11362 uint32 entry2[SOC_MAX_MEM_WORDS]; 11363 soc_mem_t mem = INVALIDm, mem2 = INVALIDm; 11364 soc_field_t fld_limit = INVALIDf; 11365 int granularity = 1; 11366 11367 if ((arg < 0) || (cosq < 0)) { 11368 return BCM_E_PARAM; 11369 } 11370 11371 BCM_IF_ERROR_RETURN 11372 (_bcm_mn_cosq_index_resolve(unit, gport, cosq, 11373 _BCM_MN_COSQ_INDEX_STYLE_EGR_POOL, 11374 &local_port, &pool, NULL)); 11375 11376 mem = MMU_THDM_DB_PORTSP_CONFIG_0m; 11377 11378 if (type == bcmCosqControlEgressPoolLimitEnable) { 11379 midx = SOC_MONTEREY_MMU_PIPED_MEM_INDEX(unit, local_port, mem, pool); 11380 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, 11381 midx, entry)); 11382 11383 soc_mem_field32_set(unit, mem, entry, SHARED_LIMIT_ENABLEf, !!arg); 11384 11385 return soc_mem_write(unit, mem, MEM_BLOCK_ALL, midx, entry); 11386 } 11387 if((type == bcmCosqControlEgressPool) || (type == bcmCosqControlUCEgressPool) || 11388 (type == bcmCosqControlMCEgressPool)) { 11389 if(( arg < 0 ) || (arg > 3 )) { 11390 return BCM_E_PARAM; 11391 } 11392 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 11393 if (type != bcmCosqControlEgressPool) { 11394 return BCM_E_PARAM; 11395 } 11396 /* regular unicast queue */ 11397 BCM_IF_ERROR_RETURN 11398 (_bcm_mn_cosq_index_resolve(unit, gport, cosq, 11399 _BCM_MN_COSQ_INDEX_STYLE_UCAST_QUEUE, 11400 &local_port, &startq, NULL)); 11401 mem = MMU_THDU_XPIPE_Q_TO_QGRP_MAPm; 11402 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 11403 if (type != bcmCosqControlEgressPool) { 11404 return BCM_E_PARAM; 11405 } 11406 BCM_IF_ERROR_RETURN 11407 (_bcm_mn_cosq_index_resolve(unit, gport, cosq, 11408 _BCM_MN_COSQ_INDEX_STYLE_MCAST_QUEUE, 11409 &local_port, &startq, NULL)); 11410 startq -= _BCM_MN_NUM_L2_UC_LEAVES; /* MC queues comes after UC queues */ 11411 mem = MMU_THDM_MCQE_QUEUE_CONFIG_0m; 11412 mem2 = MMU_THDM_DB_QUEUE_CONFIG_0m; 11413 } else { 11414 if (type == bcmCosqControlUCEgressPool) { 11415 BCM_IF_ERROR_RETURN 11416 (_bcm_mn_cosq_index_resolve(unit, gport, cosq, 11417 _BCM_MN_COSQ_INDEX_STYLE_UCAST_QUEUE, 11418 &local_port, &startq, NULL)); 11419 mem = MMU_THDU_XPIPE_Q_TO_QGRP_MAPm; 11420 } else { 11421 BCM_IF_ERROR_RETURN 11422 (_bcm_mn_cosq_index_resolve(unit, gport, cosq, 11423 _BCM_MN_COSQ_INDEX_STYLE_MCAST_QUEUE, 11424 &local_port, &startq, NULL)); 11425 startq -= _BCM_MN_NUM_L2_UC_LEAVES_PER_PIPE; 11426 /* MC queues comes after UC queues */ 11427 mem = MMU_THDM_MCQE_QUEUE_CONFIG_0m; 11428 mem2 = MMU_THDM_DB_QUEUE_CONFIG_0m; 11429 } 11430 } 11431 11432 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 11433 soc_mem_field32_set(unit, mem, entry, Q_SPIDf, arg); 11434 11435 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 11436 if (mem2 != INVALIDm) { 11437 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem2, MEM_BLOCK_ALL, startq, entry2)); 11438 soc_mem_field32_set(unit, mem2, entry2, Q_SPIDf, arg); 11439 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem2, MEM_BLOCK_ALL, startq, entry2)); 11440 } 11441 return BCM_E_NONE; 11442 } 11443 11444 arg = arg / _BCM_MN_BYTES_PER_CELL; 11445 11446 /* per service pool settings */ 11447 if (type == bcmCosqControlEgressPoolSharedLimitBytes || 11448 type == bcmCosqControlEgressPoolResumeLimitBytes || 11449 type == bcmCosqControlEgressPoolYellowSharedLimitBytes || 11450 type == bcmCosqControlEgressPoolYellowResumeLimitBytes || 11451 type == bcmCosqControlEgressPoolRedSharedLimitBytes || 11452 type == bcmCosqControlEgressPoolRedResumeLimitBytes) { 11453 uint32 rval; 11454 soc_reg_t reg; 11455 switch (type) { 11456 case bcmCosqControlEgressPoolSharedLimitBytes: 11457 reg = MMU_THDM_DB_POOL_SHARED_LIMITr; 11458 fld_limit = SHARED_LIMITf; 11459 granularity = 1; 11460 break; 11461 case bcmCosqControlEgressPoolResumeLimitBytes: 11462 reg = MMU_THDM_DB_POOL_RESUME_LIMITr; 11463 fld_limit = RESUME_LIMITf; 11464 granularity = 8; 11465 break; 11466 case bcmCosqControlEgressPoolYellowSharedLimitBytes: 11467 reg = MMU_THDM_DB_POOL_YELLOW_SHARED_LIMITr; 11468 fld_limit = YELLOW_SHARED_LIMITf; 11469 granularity = 8; 11470 break; 11471 case bcmCosqControlEgressPoolYellowResumeLimitBytes: 11472 reg = MMU_THDM_DB_POOL_YELLOW_RESUME_LIMITr; 11473 fld_limit = YELLOW_RESUME_LIMITf; 11474 granularity = 8; 11475 break; 11476 case bcmCosqControlEgressPoolRedSharedLimitBytes: 11477 reg = MMU_THDM_DB_POOL_RED_SHARED_LIMITr; 11478 fld_limit = RED_SHARED_LIMITf; 11479 granularity = 8; 11480 break; 11481 case bcmCosqControlEgressPoolRedResumeLimitBytes: 11482 reg = MMU_THDM_DB_POOL_RED_RESUME_LIMITr; 11483 fld_limit = RED_RESUME_LIMITf; 11484 granularity = 8; 11485 break; 11486 /* coverity[dead_error_begin : FALSE] */ 11487 default: 11488 return BCM_E_UNAVAIL; 11489 } 11490 11491 BCM_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, pool, &rval)); 11492 11493 /* Check for min/max values */ 11494 max_val = (1 << soc_reg_field_length(unit, reg, fld_limit)) - 1; 11495 if ((arg < 0) || ((arg/granularity) > max_val)) { 11496 return BCM_E_PARAM; 11497 } else { 11498 soc_reg_field_set(unit, reg, &rval, fld_limit, (arg/granularity)); 11499 } 11500 11501 BCM_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, pool, rval)); 11502 11503 return BCM_E_NONE; 11504 } 11505 11506 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 11507 BCM_IF_ERROR_RETURN 11508 (_bcm_mn_cosq_index_resolve(unit, gport, cosq, 11509 _BCM_MN_COSQ_INDEX_STYLE_UCAST_QUEUE, 11510 &local_port, &startq, NULL)); 11511 mem = MMU_THDU_XPIPE_CONFIG_QUEUEm; 11512 mem2 = MMU_THDU_XPIPE_Q_TO_QGRP_MAPm; 11513 11514 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 11515 BCM_IF_ERROR_RETURN 11516 (_bcm_mn_cosq_index_resolve(unit, gport, cosq, 11517 _BCM_MN_COSQ_INDEX_STYLE_MCAST_QUEUE, 11518 &local_port, &startq, NULL)); 11519 mem = MMU_THDM_DB_QUEUE_CONFIG_0m; 11520 startq -= _BCM_MN_NUM_L2_UC_LEAVES; /* MC queues comes after UC queues */ 11521 } else { 11522 if (soc_property_get(unit, spn_PORT_UC_MC_ACCOUNTING_COMBINE, 0) == 0) { 11523 /* Need to have the UC_MC_Combine config enabled */ 11524 return BCM_E_PARAM; 11525 } 11526 mem = MMU_THDM_DB_PORTSP_CONFIG_0m; 11527 startq = SOC_MONTEREY_MMU_PIPED_MEM_INDEX(unit, local_port, mem, pool); 11528 } 11529 11530 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 11531 11532 if (mem2 != INVALIDm) { 11533 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem2, MEM_BLOCK_ALL, startq, entry2)); 11534 } 11535 11536 switch (type) { 11537 case bcmCosqControlEgressPoolLimitBytes: 11538 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 11539 fld_limit = Q_SHARED_LIMIT_CELLf; 11540 11541 if (mem2 != INVALIDm) { 11542 soc_mem_field32_set(unit, mem2, entry2, Q_LIMIT_ENABLEf, 1); 11543 } 11544 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 11545 fld_limit = Q_SHARED_LIMITf; 11546 soc_mem_field32_set(unit, mem, entry, Q_LIMIT_ENABLEf, 1); 11547 } else { 11548 fld_limit = SHARED_LIMITf; 11549 soc_mem_field32_set(unit, mem, entry, SHARED_LIMIT_ENABLEf, 1); 11550 } 11551 granularity = 1; 11552 break; 11553 case bcmCosqControlEgressPoolYellowLimitBytes: 11554 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 11555 fld_limit = LIMIT_YELLOW_CELLf; 11556 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 11557 fld_limit = YELLOW_SHARED_LIMITf; 11558 } else { 11559 fld_limit = YELLOW_SHARED_LIMITf; 11560 } 11561 granularity = 8; 11562 break; 11563 case bcmCosqControlEgressPoolRedLimitBytes: 11564 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 11565 fld_limit = LIMIT_RED_CELLf; 11566 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 11567 fld_limit = RED_SHARED_LIMITf; 11568 } else { 11569 fld_limit = RED_SHARED_LIMITf; 11570 } 11571 granularity = 8; 11572 break; 11573 default: 11574 return BCM_E_UNAVAIL; 11575 } 11576 11577 /* Check for min/max values */ 11578 max_val = (1 << soc_mem_field_length(unit, mem, fld_limit)) - 1; 11579 if ((arg < 0) || ((arg/granularity) > max_val)) { 11580 return BCM_E_PARAM; 11581 } else { 11582 soc_mem_field32_set(unit, mem, entry, fld_limit, (arg/granularity)); 11583 } 11584 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 11585 11586 if (mem2 != INVALIDm) { 11587 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem2, MEM_BLOCK_ALL, startq, entry2)); 11588 } 11589 return BCM_E_NONE; 11590 } 11591 11592 11593 11594 STATIC int 11595 _bcm_mn_cosq_egr_port_pool_set(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 11596 bcm_cosq_control_t type, int arg) 11597 { 11598 bcm_port_t local_port; 11599 uint32 max_val; 11600 uint32 entry[SOC_MAX_MEM_WORDS]; 11601 soc_mem_t mem = INVALIDm; 11602 soc_field_t fld_limit = INVALIDf; 11603 int granularity = 1; 11604 int pool, midx; 11605 11606 if (arg < 0) { 11607 return BCM_E_PARAM; 11608 } 11609 11610 BCM_IF_ERROR_RETURN 11611 (_bcm_mn_cosq_index_resolve(unit, gport, cosq, 11612 _BCM_MN_COSQ_INDEX_STYLE_EGR_POOL, 11613 &local_port, &pool, NULL)); 11614 mem = MMU_THDU_XPIPE_CONFIG_PORTm; 11615 midx = SOC_MONTEREY_MMU_PIPED_MEM_INDEX(unit, local_port, mem, pool); 11616 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, entry)); 11617 11618 switch (type) { 11619 case bcmCosqControlEgressPortPoolYellowLimitBytes: 11620 fld_limit = YELLOW_LIMITf; 11621 granularity = 8; 11622 break; 11623 case bcmCosqControlEgressPortPoolRedLimitBytes: 11624 fld_limit = RED_LIMITf; 11625 granularity = 8; 11626 break; 11627 default: 11628 return BCM_E_UNAVAIL; 11629 } 11630 11631 arg = arg / _BCM_MN_BYTES_PER_CELL; 11632 11633 /* Check for min/max values */ 11634 max_val = (1 << soc_mem_field_length(unit, mem, fld_limit)) - 1; 11635 if ((arg < 0) || ((arg/granularity) > max_val)) { 11636 return BCM_E_PARAM; 11637 } else { 11638 soc_mem_field32_set(unit, mem, entry, fld_limit, (arg/granularity)); 11639 } 11640 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, midx, entry)); 11641 11642 return BCM_E_NONE; 11643 } 11644 11645 11646 STATIC int 11647 _bcm_mn_cosq_egr_pool_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 11648 bcm_cosq_control_t type, int *arg) 11649 { 11650 bcm_port_t local_port; 11651 int startq, pool, midx; 11652 uint32 entry[SOC_MAX_MEM_WORDS]; 11653 soc_mem_t mem; 11654 int granularity = 1; 11655 11656 if ((!arg) || (cosq < 0)) { 11657 return BCM_E_PARAM; 11658 } 11659 11660 if (type == bcmCosqControlUCEgressPool) { 11661 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 11662 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) || 11663 BCM_GPORT_IS_SCHEDULER(gport)) { 11664 return BCM_E_PARAM; 11665 } 11666 11667 BCM_IF_ERROR_RETURN 11668 (_bcm_mn_cosq_index_resolve(unit, gport, cosq, 11669 _BCM_MN_COSQ_INDEX_STYLE_UC_EGR_POOL, 11670 &local_port, &pool, NULL)); 11671 *arg = pool; 11672 return BCM_E_NONE; 11673 } else { 11674 if (type == bcmCosqControlMCEgressPool) { 11675 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 11676 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) || 11677 BCM_GPORT_IS_SCHEDULER(gport)) { 11678 return BCM_E_PARAM; 11679 } 11680 } 11681 BCM_IF_ERROR_RETURN 11682 (_bcm_mn_cosq_index_resolve(unit, gport, cosq, 11683 _BCM_MN_COSQ_INDEX_STYLE_EGR_POOL, 11684 &local_port, &pool, NULL)); 11685 if (type == bcmCosqControlMCEgressPool || 11686 type == bcmCosqControlEgressPool) { 11687 *arg = pool; 11688 return BCM_E_NONE; 11689 } 11690 } 11691 11692 /* per service pool settings */ 11693 if (type == bcmCosqControlEgressPoolSharedLimitBytes || 11694 type == bcmCosqControlEgressPoolResumeLimitBytes || 11695 type == bcmCosqControlEgressPoolYellowSharedLimitBytes || 11696 type == bcmCosqControlEgressPoolYellowResumeLimitBytes || 11697 type == bcmCosqControlEgressPoolRedSharedLimitBytes || 11698 type == bcmCosqControlEgressPoolRedResumeLimitBytes) { 11699 uint32 rval; 11700 soc_reg_t reg; 11701 soc_field_t fld_limit = INVALIDf; 11702 switch (type) { 11703 case bcmCosqControlEgressPoolSharedLimitBytes: 11704 reg = MMU_THDM_DB_POOL_SHARED_LIMITr; 11705 fld_limit = SHARED_LIMITf; 11706 granularity = 1; 11707 break; 11708 case bcmCosqControlEgressPoolResumeLimitBytes: 11709 reg = MMU_THDM_DB_POOL_RESUME_LIMITr; 11710 fld_limit = RESUME_LIMITf; 11711 granularity = 8; 11712 break; 11713 case bcmCosqControlEgressPoolYellowSharedLimitBytes: 11714 reg = MMU_THDM_DB_POOL_YELLOW_SHARED_LIMITr; 11715 fld_limit = YELLOW_SHARED_LIMITf; 11716 granularity = 8; 11717 break; 11718 case bcmCosqControlEgressPoolYellowResumeLimitBytes: 11719 reg = MMU_THDM_DB_POOL_YELLOW_RESUME_LIMITr; 11720 fld_limit = YELLOW_RESUME_LIMITf; 11721 granularity = 8; 11722 break; 11723 case bcmCosqControlEgressPoolRedSharedLimitBytes: 11724 reg = MMU_THDM_DB_POOL_RED_SHARED_LIMITr; 11725 fld_limit = RED_SHARED_LIMITf; 11726 granularity = 8; 11727 break; 11728 case bcmCosqControlEgressPoolRedResumeLimitBytes: 11729 reg = MMU_THDM_DB_POOL_RED_RESUME_LIMITr; 11730 fld_limit = RED_RESUME_LIMITf; 11731 granularity = 8; 11732 break; 11733 /* coverity[dead_error_begin] */ 11734 default: 11735 return BCM_E_UNAVAIL; 11736 } 11737 11738 BCM_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, pool, &rval)); 11739 11740 *arg = soc_reg_field_get(unit, reg, rval, fld_limit); 11741 *arg = (*arg) * granularity * _BCM_MN_BYTES_PER_CELL; 11742 11743 return BCM_E_NONE; 11744 } 11745 mem = MMU_THDM_DB_PORTSP_CONFIG_0m; 11746 11747 if (type == bcmCosqControlEgressPoolLimitEnable) { 11748 midx = SOC_MONTEREY_MMU_PIPED_MEM_INDEX(unit, local_port, mem, pool); 11749 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, 11750 midx, entry)); 11751 11752 *arg = soc_mem_field32_get(unit, mem, entry, SHARED_LIMIT_ENABLEf); 11753 return BCM_E_NONE; 11754 } 11755 11756 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 11757 BCM_IF_ERROR_RETURN 11758 (_bcm_mn_cosq_index_resolve(unit, gport, cosq, 11759 _BCM_MN_COSQ_INDEX_STYLE_UCAST_QUEUE, 11760 &local_port, &startq, NULL)); 11761 mem = MMU_THDU_XPIPE_CONFIG_QUEUEm; 11762 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 11763 BCM_IF_ERROR_RETURN 11764 (_bcm_mn_cosq_index_resolve(unit, gport, cosq, 11765 _BCM_MN_COSQ_INDEX_STYLE_MCAST_QUEUE, 11766 &local_port, &startq, NULL)); 11767 mem = MMU_THDM_DB_QUEUE_CONFIG_0m; 11768 startq -= _BCM_MN_NUM_L2_UC_LEAVES; /* MC queues comes after UC queues */ 11769 } else { 11770 if (soc_property_get(unit, spn_PORT_UC_MC_ACCOUNTING_COMBINE, 0) == 0) { 11771 /* Need to have the UC_MC_Combine config enabled */ 11772 return BCM_E_PARAM; 11773 } 11774 mem = MMU_THDM_DB_PORTSP_CONFIG_0m; 11775 startq = SOC_MONTEREY_MMU_PIPED_MEM_INDEX(unit, local_port, mem, pool); 11776 } 11777 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, 11778 startq, entry)); 11779 11780 switch (type) { 11781 11782 case bcmCosqControlEgressPoolLimitBytes: 11783 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 11784 *arg = soc_mem_field32_get(unit, mem, entry, Q_SHARED_LIMIT_CELLf); 11785 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 11786 *arg = soc_mem_field32_get(unit, mem, entry, Q_SHARED_LIMITf); 11787 } else { 11788 *arg = soc_mem_field32_get(unit, mem, entry, SHARED_LIMITf); 11789 } 11790 granularity = 1; 11791 break; 11792 case bcmCosqControlEgressPoolYellowLimitBytes: 11793 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 11794 *arg = soc_mem_field32_get(unit, mem, entry, LIMIT_YELLOW_CELLf); 11795 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 11796 *arg = soc_mem_field32_get(unit, mem, entry, YELLOW_SHARED_LIMITf); 11797 } else { 11798 *arg = soc_mem_field32_get(unit, mem, entry, YELLOW_SHARED_LIMITf); 11799 } 11800 granularity = 8; 11801 break; 11802 case bcmCosqControlEgressPoolRedLimitBytes: 11803 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 11804 *arg = soc_mem_field32_get(unit, mem, entry, LIMIT_RED_CELLf); 11805 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 11806 *arg = soc_mem_field32_get(unit, mem, entry, RED_SHARED_LIMITf); 11807 } else { 11808 *arg = soc_mem_field32_get(unit, mem, entry, RED_SHARED_LIMITf); 11809 } 11810 granularity = 8; 11811 break; 11812 default: 11813 return BCM_E_UNAVAIL; 11814 } 11815 *arg = (*arg) * granularity * _BCM_MN_BYTES_PER_CELL; 11816 return BCM_E_NONE; 11817 } 11818 11819 11820 STATIC int 11821 _bcm_mn_cosq_egr_port_pool_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 11822 bcm_cosq_control_t type, int *arg) 11823 { 11824 bcm_port_t local_port; 11825 uint32 entry[SOC_MAX_MEM_WORDS]; 11826 soc_mem_t mem = INVALIDm; 11827 int granularity = 1; 11828 int pool, midx; 11829 11830 if (!arg) { 11831 return BCM_E_PARAM; 11832 } 11833 11834 11835 BCM_IF_ERROR_RETURN 11836 (_bcm_mn_cosq_index_resolve(unit, gport, cosq, 11837 _BCM_MN_COSQ_INDEX_STYLE_EGR_POOL, 11838 &local_port, &pool, NULL)); 11839 mem = MMU_THDU_XPIPE_CONFIG_PORTm; 11840 midx = SOC_MONTEREY_MMU_PIPED_MEM_INDEX(unit, local_port, mem, pool); 11841 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, entry)); 11842 11843 switch (type) { 11844 case bcmCosqControlEgressPortPoolYellowLimitBytes: 11845 *arg = soc_mem_field32_get(unit, mem, entry, YELLOW_LIMITf); 11846 granularity = 8; 11847 break; 11848 case bcmCosqControlEgressPortPoolRedLimitBytes: 11849 *arg = soc_mem_field32_get(unit, mem, entry, RED_LIMITf); 11850 granularity = 8; 11851 break; 11852 default: 11853 return BCM_E_UNAVAIL; 11854 } 11855 11856 11857 *arg = (*arg) * granularity * _BCM_MN_BYTES_PER_CELL; 11858 return BCM_E_NONE; 11859 } 11860 11861 11862 11863 STATIC int 11864 _bcm_mn_cosq_egr_queue_set(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 11865 bcm_cosq_control_t type, int arg) 11866 { 11867 bcm_port_t local_port; 11868 int startq; 11869 uint32 max_val, rval = 0; 11870 uint32 shared_size, spid; 11871 uint32 entry[SOC_MAX_MEM_WORDS]; 11872 uint32 entry2[SOC_MAX_MEM_WORDS]; 11873 soc_mem_t mem = INVALIDm, mem2 = INVALIDm; 11874 soc_field_t fld_limit = INVALIDf; 11875 soc_field_t fld_sp = INVALIDf; 11876 int granularity = 1; 11877 int from_cos, to_cos, ci; 11878 int cur_val, rv, post_update, limit = 0; 11879 _bcm_mn_mmu_info_t *mmu_info = _bcm_mn_mmu_info[unit]; 11880 11881 if (arg < 0) { 11882 return BCM_E_PARAM; 11883 } 11884 11885 arg /= _BCM_MN_BYTES_PER_CELL; 11886 11887 if ((type == bcmCosqControlEgressUCQueueMinLimitBytes) || 11888 (type == bcmCosqControlEgressUCQueueSharedLimitBytes)) { 11889 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 11890 BCM_IF_ERROR_RETURN 11891 (_bcm_mn_cosq_index_resolve(unit, gport, cosq, 11892 _BCM_MN_COSQ_INDEX_STYLE_UCAST_QUEUE, 11893 &local_port, &startq, NULL)); 11894 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 11895 return BCM_E_PARAM; 11896 } 11897 else { 11898 if (cosq == BCM_COS_INVALID) { 11899 from_cos = to_cos = 0; 11900 } else { 11901 from_cos = to_cos = cosq; 11902 } 11903 11904 BCM_IF_ERROR_RETURN 11905 (_bcm_mn_cosq_localport_resolve(unit, gport, &local_port)); 11906 if (local_port < 0) { 11907 return BCM_E_PORT; 11908 } 11909 for (ci = from_cos; ci <= to_cos; ci++) { 11910 BCM_IF_ERROR_RETURN 11911 (_bcm_mn_cosq_index_resolve 11912 (unit, local_port, ci, _BCM_MN_COSQ_INDEX_STYLE_UCAST_QUEUE, 11913 NULL, &startq, NULL)); 11914 } 11915 } 11916 mem = MMU_THDU_XPIPE_CONFIG_QUEUEm; 11917 11918 mem2 = MMU_THDU_XPIPE_Q_TO_QGRP_MAPm; 11919 11920 fld_sp = Q_SPIDf; 11921 } else if ((type == bcmCosqControlEgressMCQueueMinLimitBytes) || 11922 (type == bcmCosqControlEgressMCQueueSharedLimitBytes)) { 11923 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 11924 return BCM_E_PARAM; 11925 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 11926 BCM_IF_ERROR_RETURN 11927 (_bcm_mn_cosq_index_resolve(unit, gport, cosq, 11928 _BCM_MN_COSQ_INDEX_STYLE_MCAST_QUEUE, 11929 &local_port, &startq, NULL)); 11930 } 11931 else { 11932 if (cosq == BCM_COS_INVALID) { 11933 from_cos = to_cos = 0; 11934 } else { 11935 from_cos = to_cos = cosq; 11936 } 11937 11938 BCM_IF_ERROR_RETURN 11939 (_bcm_mn_cosq_localport_resolve(unit, gport, &local_port)); 11940 if (local_port < 0) { 11941 return BCM_E_PORT; 11942 } 11943 for (ci = from_cos; ci <= to_cos; ci++) { 11944 BCM_IF_ERROR_RETURN 11945 (_bcm_mn_cosq_index_resolve 11946 (unit, local_port, ci, _BCM_MN_COSQ_INDEX_STYLE_MCAST_QUEUE, 11947 NULL, &startq, NULL)); 11948 } 11949 } 11950 mem = MMU_THDM_DB_QUEUE_CONFIG_0m; 11951 mem2 = MMU_THDM_MCQE_QUEUE_CONFIG_0m; 11952 fld_sp = Q_SPIDf; 11953 startq -= _BCM_MN_NUM_L2_UC_LEAVES; /* MC queues comes after UC queues */ 11954 } else { 11955 return BCM_E_PARAM; 11956 } 11957 11958 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 11959 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem2, MEM_BLOCK_ALL, startq, entry2)); 11960 11961 switch (type) { 11962 case bcmCosqControlEgressUCQueueSharedLimitBytes: 11963 fld_limit = Q_SHARED_LIMIT_CELLf; 11964 11965 if (mem2 != INVALIDm) { 11966 soc_mem_field32_set(unit, mem2, entry2, Q_LIMIT_ENABLEf, 1); 11967 } 11968 11969 /* Set MMU_THDU_XPIPE_Q_TO_QGRP_MAP.DISABLE_QUEUING to 1 when both MIN 11970 * and SHARED LIMIT are 0. Set it to 0 when either MIN or SHARED LIMIT 11971 * is non-zero. 11972 */ 11973 limit = soc_mem_field32_get(unit, mem, entry, Q_MIN_LIMIT_CELLf); 11974 if (arg == 0 && limit == 0) { 11975 soc_mem_field32_set(unit, mem2, entry2, DISABLE_QUEUINGf, 1); 11976 } else if (arg != 0 || limit != 0) { 11977 soc_mem_field32_set(unit, mem2, entry2, DISABLE_QUEUINGf, 0); 11978 } 11979 spid = soc_mem_field32_get(unit, mem2, entry2, fld_sp); 11980 granularity = 1; 11981 break; 11982 case bcmCosqControlEgressMCQueueSharedLimitBytes: 11983 fld_limit = Q_SHARED_LIMITf; 11984 soc_mem_field32_set(unit, mem, entry, Q_LIMIT_ENABLEf, 1); 11985 11986 /* Config LIMIT in THDO_MC_QE: in 4-enties granularity */ 11987 granularity = 4; 11988 soc_mem_field32_set(unit, mem2, entry2, fld_limit, (arg/granularity)); 11989 soc_mem_field32_set(unit, mem2, entry2, Q_LIMIT_ENABLEf, 1); 11990 spid = soc_mem_field32_get(unit, mem, entry, fld_sp); 11991 granularity = 1; 11992 break; 11993 case bcmCosqControlEgressUCQueueMinLimitBytes: 11994 fld_limit = Q_MIN_LIMIT_CELLf; 11995 11996 /* Set MMU_THDU_XPIPE_Q_TO_QGRP_MAP.DISABLE_QUEUING to 1 when both MIN 11997 * and SHARED LIMIT are 0. Set it to 0 when either MIN or SHARED LIMIT is non-zero 11998 */ 11999 limit = soc_mem_field32_get(unit, mem, entry, Q_SHARED_LIMIT_CELLf); 12000 if (arg == 0 && limit == 0) { 12001 soc_mem_field32_set(unit, mem2, entry2, DISABLE_QUEUINGf, 1); 12002 } else if (arg != 0 || limit != 0) { 12003 soc_mem_field32_set(unit, mem2, entry2, DISABLE_QUEUINGf, 0); 12004 } 12005 spid = soc_mem_field32_get(unit, mem2, entry2, fld_sp); 12006 granularity = 1; 12007 break; 12008 case bcmCosqControlEgressMCQueueMinLimitBytes: 12009 fld_limit = Q_MIN_LIMITf; 12010 12011 /* Config LIMIT in THDO_MC_QE: in 4-enties granularity */ 12012 granularity = 4; 12013 soc_mem_field32_set(unit, mem2, entry2, fld_limit, (arg/granularity)); 12014 spid = soc_mem_field32_get(unit, mem, entry, fld_sp); 12015 granularity = 1; 12016 break; 12017 default: 12018 return BCM_E_UNAVAIL; 12019 } 12020 12021 /* Recalculate Shared Values if Min Changed */ 12022 SOC_IF_ERROR_RETURN(READ_MMU_THDM_DB_POOL_SHARED_LIMITr(unit, spid, &rval)); 12023 shared_size = soc_reg_field_get(unit, MMU_THDM_DB_POOL_SHARED_LIMITr, rval, SHARED_LIMITf); 12024 cur_val = soc_mem_field32_get(unit, mem, entry, fld_limit); 12025 12026 if ((arg / granularity) > cur_val) { 12027 /* New Min Val > Cur Min Val 12028 * So reduce the Shared values first and then 12029 * Increase the Min Value for given resource 12030 */ 12031 post_update = 0; 12032 } else if ((arg / granularity) < cur_val) { 12033 /* New Min Val < Cur Min Val 12034 * So reduce the Min values first and then 12035 * Increase Shared values everywhere 12036 */ 12037 post_update = 1; 12038 } else { 12039 return BCM_E_NONE; 12040 } 12041 12042 if (!post_update && 12043 ((type == bcmCosqControlEgressUCQueueMinLimitBytes) || 12044 (type == bcmCosqControlEgressMCQueueMinLimitBytes))) { 12045 int delta = 0; /* In Cells */ 12046 delta = ((arg / granularity) - cur_val) * granularity; 12047 if (delta > shared_size) { 12048 return BCM_E_RESOURCE; 12049 } 12050 rv = soc_monterey_mmu_config_res_limits_update(unit,spid, 12051 shared_size - delta, 1); 12052 if (rv < 0) { 12053 return rv; 12054 } 12055 mmu_info->curr_shared_limit = shared_size - delta; 12056 } 12057 12058 12059 /* Check for min/max values */ 12060 max_val = (1 << soc_mem_field_length(unit, mem, fld_limit)) - 1; 12061 if ((arg < 0) || ((arg/granularity) > max_val)) { 12062 return BCM_E_PARAM; 12063 } else { 12064 /* Get the latest entry data and update. */ 12065 SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, 12066 startq, entry)); 12067 soc_mem_field32_set(unit, mem, entry, fld_limit, (arg/granularity)); 12068 } 12069 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 12070 12071 if (mem2 != INVALIDm) { 12072 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem2, MEM_BLOCK_ALL, startq, entry2)); 12073 } 12074 12075 if (post_update && 12076 ((type == bcmCosqControlEgressUCQueueMinLimitBytes) || 12077 (type == bcmCosqControlEgressMCQueueMinLimitBytes))) { 12078 int delta = 0; 12079 delta = (cur_val - (arg / granularity)) * granularity; 12080 rv = soc_monterey_mmu_config_res_limits_update(unit,spid, 12081 shared_size + delta, 0); 12082 if (rv < 0) { 12083 return rv; 12084 } 12085 mmu_info->curr_shared_limit = shared_size + delta; 12086 } 12087 12088 return BCM_E_NONE; 12089 } 12090 12091 STATIC int 12092 _bcm_mn_cosq_egr_queue_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 12093 bcm_cosq_control_t type, int *arg) 12094 { 12095 bcm_port_t local_port; 12096 int startq; 12097 uint32 entry[SOC_MAX_MEM_WORDS]; 12098 soc_mem_t mem = INVALIDm; 12099 soc_field_t fld_limit = INVALIDf; 12100 int granularity = 1; 12101 int from_cos, to_cos, ci; 12102 12103 if (!arg) { 12104 return BCM_E_PARAM; 12105 } 12106 12107 if ((type == bcmCosqControlEgressUCQueueMinLimitBytes) || 12108 (type == bcmCosqControlEgressUCQueueSharedLimitBytes)) { 12109 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 12110 BCM_IF_ERROR_RETURN 12111 (_bcm_mn_cosq_index_resolve(unit, gport, cosq, 12112 _BCM_MN_COSQ_INDEX_STYLE_UCAST_QUEUE, 12113 &local_port, &startq, NULL)); 12114 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 12115 return BCM_E_PARAM; 12116 } 12117 else { 12118 if (cosq == BCM_COS_INVALID) { 12119 from_cos = to_cos = 0; 12120 } else { 12121 from_cos = to_cos = cosq; 12122 } 12123 12124 BCM_IF_ERROR_RETURN 12125 (_bcm_mn_cosq_localport_resolve(unit, gport, &local_port)); 12126 if (local_port < 0) { 12127 return BCM_E_PORT; 12128 } 12129 for (ci = from_cos; ci <= to_cos; ci++) { 12130 BCM_IF_ERROR_RETURN 12131 (_bcm_mn_cosq_index_resolve 12132 (unit, local_port, ci, _BCM_MN_COSQ_INDEX_STYLE_UCAST_QUEUE, 12133 NULL, &startq, NULL)); 12134 } 12135 } 12136 mem = MMU_THDU_XPIPE_CONFIG_QUEUEm; 12137 } else if ((type == bcmCosqControlEgressMCQueueMinLimitBytes) || 12138 (type == bcmCosqControlEgressMCQueueSharedLimitBytes)) { 12139 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 12140 return BCM_E_PARAM; 12141 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 12142 BCM_IF_ERROR_RETURN 12143 (_bcm_mn_cosq_index_resolve(unit, gport, cosq, 12144 _BCM_MN_COSQ_INDEX_STYLE_MCAST_QUEUE, 12145 &local_port, &startq, NULL)); 12146 } 12147 else { 12148 if (cosq == BCM_COS_INVALID) { 12149 from_cos = to_cos = 0; 12150 } else { 12151 from_cos = to_cos = cosq; 12152 } 12153 12154 BCM_IF_ERROR_RETURN 12155 (_bcm_mn_cosq_localport_resolve(unit, gport, &local_port)); 12156 if (local_port < 0) { 12157 return BCM_E_PORT; 12158 } 12159 for (ci = from_cos; ci <= to_cos; ci++) { 12160 BCM_IF_ERROR_RETURN 12161 (_bcm_mn_cosq_index_resolve 12162 (unit, local_port, ci, _BCM_MN_COSQ_INDEX_STYLE_MCAST_QUEUE, 12163 NULL, &startq, NULL)); 12164 } 12165 } 12166 mem = MMU_THDM_DB_QUEUE_CONFIG_0m; 12167 startq -= _BCM_MN_NUM_L2_UC_LEAVES; /* MC queues comes after UC queues */ 12168 } else { 12169 return BCM_E_PARAM; 12170 } 12171 12172 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, 12173 startq, entry)); 12174 12175 switch (type) { 12176 case bcmCosqControlEgressUCQueueSharedLimitBytes: 12177 fld_limit = Q_SHARED_LIMIT_CELLf; 12178 granularity = 1; 12179 break; 12180 case bcmCosqControlEgressMCQueueSharedLimitBytes: 12181 fld_limit = Q_SHARED_LIMITf; 12182 granularity = 1; 12183 break; 12184 case bcmCosqControlEgressUCQueueMinLimitBytes: 12185 fld_limit = Q_MIN_LIMIT_CELLf; 12186 granularity = 1; 12187 break; 12188 case bcmCosqControlEgressMCQueueMinLimitBytes: 12189 fld_limit = Q_MIN_LIMITf; 12190 granularity = 1; 12191 break; 12192 default: 12193 return BCM_E_UNAVAIL; 12194 } 12195 *arg = soc_mem_field32_get(unit, mem, entry, fld_limit); 12196 *arg = (*arg) * granularity * _BCM_MN_BYTES_PER_CELL; 12197 return BCM_E_NONE; 12198 } 12199 12200 STATIC int 12201 _bcm_mn_cosq_ing_res_set(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 12202 bcm_cosq_control_t type, int arg) 12203 { 12204 bcm_port_t local_port; 12205 int midx; 12206 uint32 max_val, rval; 12207 uint32 entry[SOC_MAX_MEM_WORDS]; 12208 soc_mem_t mem = INVALIDm; 12209 soc_field_t fld_limit = INVALIDf; 12210 soc_reg_t reg = INVALIDr; 12211 int port_pg, port_pg_pool, granularity = 1; 12212 static const soc_reg_t prigroup_reg[] = { 12213 THDI_PORT_PRI_GRP0r, THDI_PORT_PRI_GRP1r 12214 }; 12215 static const soc_field_t prigroup_field[] = { 12216 PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf, 12217 PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf, 12218 PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf, 12219 PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf 12220 }; 12221 static const soc_field_t prigroup_spid_field[] = { 12222 PG0_SPIDf, PG1_SPIDf, PG2_SPIDf, PG3_SPIDf, 12223 PG4_SPIDf, PG5_SPIDf, PG6_SPIDf, PG7_SPIDf 12224 }; 12225 12226 if (cosq > 15 || cosq < 0) { 12227 /* Error. Input pri > Max Pri_Grp */ 12228 return BCM_E_PARAM; 12229 } 12230 12231 if (arg < 0) { 12232 return BCM_E_PARAM; 12233 } 12234 12235 arg /= _BCM_MN_BYTES_PER_CELL; 12236 BCM_IF_ERROR_RETURN 12237 (_bcm_mn_cosq_localport_resolve(unit, gport, &local_port)); 12238 if (local_port < 0) { 12239 return BCM_E_PORT; 12240 } 12241 12242 /* get PG for port using Port+Cos */ 12243 if (cosq < 8) { 12244 reg = prigroup_reg[0]; 12245 } else { 12246 reg = prigroup_reg[1]; 12247 } 12248 12249 SOC_IF_ERROR_RETURN 12250 (soc_reg32_get(unit, reg, local_port, 0, &rval)); 12251 port_pg = soc_reg_field_get(unit, reg, rval, prigroup_field[cosq]); 12252 12253 12254 if ((type == bcmCosqControlIngressPortPGSharedLimitBytes) || 12255 (type == bcmCosqControlIngressPortPGMinLimitBytes) || 12256 (type == bcmCosqControlIngressPortPGHeadroomLimitBytes) || 12257 (type == bcmCosqControlIngressPortPGResetFloorBytes)) { 12258 mem = THDI_PORT_PG_CONFIG_Xm; 12259 /* get index for Port-PG */ 12260 midx = SOC_MONTEREY_MMU_PIPED_MEM_INDEX(unit, local_port, mem, port_pg); 12261 12262 } else if ((type == bcmCosqControlIngressPortPoolMaxLimitBytes) || 12263 (type == bcmCosqControlIngressPortPoolMinLimitBytes)) { 12264 reg = THDI_PORT_PG_SPIDr; 12265 12266 SOC_IF_ERROR_RETURN 12267 (soc_reg32_get(unit, reg, local_port, 0, &rval)); 12268 port_pg_pool = soc_reg_field_get(unit, reg, rval, prigroup_spid_field[port_pg]); 12269 12270 mem = THDI_PORT_SP_CONFIG_Xm; 12271 /* get index for Port-SP */ 12272 midx = SOC_MONTEREY_MMU_PIPED_MEM_INDEX(unit, local_port, mem, port_pg_pool); 12273 } else { 12274 return BCM_E_UNAVAIL; 12275 } 12276 12277 if (midx < 0) { 12278 return BCM_E_PARAM; 12279 } 12280 12281 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, entry)); 12282 12283 switch (type) { 12284 case bcmCosqControlIngressPortPGSharedLimitBytes: 12285 fld_limit = PG_SHARED_LIMITf; 12286 granularity = 1; 12287 break; 12288 case bcmCosqControlIngressPortPoolMaxLimitBytes: 12289 fld_limit = PORT_SP_MAX_LIMITf; 12290 granularity = 1; 12291 break; 12292 case bcmCosqControlIngressPortPGMinLimitBytes: 12293 fld_limit = PG_MIN_LIMITf; 12294 granularity = 1; 12295 break; 12296 case bcmCosqControlIngressPortPoolMinLimitBytes: 12297 fld_limit = PORT_SP_MIN_LIMITf; 12298 granularity = 1; 12299 break; 12300 case bcmCosqControlIngressPortPGHeadroomLimitBytes: 12301 fld_limit = PG_HDRM_LIMITf; 12302 granularity = 1; 12303 break; 12304 case bcmCosqControlIngressPortPGResetFloorBytes: 12305 fld_limit = PG_RESET_FLOORf; 12306 granularity = 1; 12307 break; 12308 /* coverity[dead_error_begin] */ 12309 default: 12310 return BCM_E_UNAVAIL; 12311 } 12312 12313 /* Check for min/max values */ 12314 max_val = (1 << soc_mem_field_length(unit, mem, fld_limit)) - 1; 12315 if ((arg < 0) || ((arg/granularity) > max_val)) { 12316 return BCM_E_PARAM; 12317 } else { 12318 soc_mem_field32_set(unit, mem, entry, fld_limit, (arg/granularity)); 12319 } 12320 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, midx, entry)); 12321 12322 return BCM_E_NONE; 12323 } 12324 12325 STATIC int 12326 _bcm_mn_cosq_state_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 12327 bcm_cosq_control_t type, int *arg) 12328 { 12329 bcm_port_t local_port; 12330 uint32 rval, state , mask = 1 , bitno = 0; 12331 static const soc_field_t pool_field[] = { 12332 POOL_0f, POOL_1f, POOL_2f, POOL_3f }; 12333 int start_pool_idx = 0,end_pool_idx = 0; 12334 if (!arg) { 12335 return BCM_E_PARAM; 12336 } 12337 switch (type) { 12338 case bcmCosqControlSPPortLimitState: 12339 case bcmCosqControlPoolRedDropState: 12340 case bcmCosqControlPoolYellowDropState: 12341 case bcmCosqControlPoolGreenDropState: 12342 BCM_IF_ERROR_RETURN 12343 (_bcm_mn_cosq_localport_resolve(unit, gport, &local_port)); 12344 12345 if (!SOC_PORT_VALID(unit, local_port)) { 12346 return BCM_E_PORT; 12347 } 12348 BCM_IF_ERROR_RETURN (_bcm_mn_cosq_egress_sp_get(unit, gport, cosq, &start_pool_idx, 12349 &end_pool_idx)); 12350 bitno = start_pool_idx; 12351 break; 12352 12353 case bcmCosqControlPGPortLimitState: 12354 case bcmCosqControlPGPortXoffState: 12355 BCM_IF_ERROR_RETURN 12356 (_bcm_mn_cosq_localport_resolve(unit, gport, &local_port)); 12357 12358 if (!SOC_PORT_VALID(unit, local_port)) { 12359 return BCM_E_PORT; 12360 } 12361 if ((cosq < 0 ) || (cosq > 7)) { 12362 return BCM_E_PARAM; 12363 } 12364 bitno = cosq; 12365 break; 12366 default: 12367 return BCM_E_PARAM; 12368 } 12369 switch (type) { 12370 case bcmCosqControlSPPortLimitState: 12371 SOC_IF_ERROR_RETURN( 12372 READ_THDI_PORT_LIMIT_STATESr(unit, local_port, &rval)); 12373 state = soc_reg_field_get(unit, THDI_PORT_LIMIT_STATESr, rval, 12374 SP_LIMIT_STATEf); 12375 break; 12376 case bcmCosqControlPGPortLimitState: 12377 SOC_IF_ERROR_RETURN( 12378 READ_THDI_PORT_LIMIT_STATESr(unit, local_port, &rval)); 12379 state = soc_reg_field_get(unit, THDI_PORT_LIMIT_STATESr, rval, 12380 PG_LIMIT_STATEf); 12381 break; 12382 case bcmCosqControlPGPortXoffState: 12383 SOC_IF_ERROR_RETURN( 12384 READ_THDI_FLOW_CONTROL_XOFF_STATEr(unit, local_port, &rval)); 12385 state = soc_reg_field_get(unit, THDI_FLOW_CONTROL_XOFF_STATEr, rval, 12386 PG_BMPf); 12387 break; 12388 case bcmCosqControlPoolRedDropState: 12389 SOC_IF_ERROR_RETURN( 12390 READ_THDI_POOL_DROP_STATEr(unit, &rval)); 12391 state = soc_reg_field_get(unit, THDI_POOL_DROP_STATEr, rval, 12392 pool_field[start_pool_idx]); 12393 bitno = 2; 12394 break; 12395 case bcmCosqControlPoolYellowDropState: 12396 SOC_IF_ERROR_RETURN( 12397 READ_THDI_POOL_DROP_STATEr(unit, &rval)); 12398 state = soc_reg_field_get(unit, THDI_POOL_DROP_STATEr, rval, 12399 pool_field[start_pool_idx]); 12400 bitno = 1; 12401 break; 12402 case bcmCosqControlPoolGreenDropState: 12403 SOC_IF_ERROR_RETURN( 12404 READ_THDI_POOL_DROP_STATEr(unit, &rval)); 12405 state = soc_reg_field_get(unit, THDI_POOL_DROP_STATEr, rval, 12406 pool_field[start_pool_idx]); 12407 bitno = 0; 12408 break; 12409 /* coverity[dead_error_begin] */ 12410 default : 12411 return BCM_E_PARAM; 12412 } 12413 mask = mask<<bitno; 12414 state = state & mask ; 12415 if (state) { 12416 *arg = 1 ; 12417 } else { 12418 *arg = 0 ; 12419 } 12420 return BCM_E_NONE; 12421 } 12422 12423 STATIC int 12424 _bcm_mn_cosq_ing_res_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 12425 bcm_cosq_control_t type, int *arg) 12426 { 12427 bcm_port_t local_port; 12428 uint32 rval; 12429 uint32 entry[SOC_MAX_MEM_WORDS]; 12430 soc_mem_t mem = INVALIDm; 12431 soc_field_t fld_limit = INVALIDf; 12432 soc_reg_t reg = INVALIDr; 12433 int midx, port_pg, port_pg_pool, granularity = 1; 12434 static const soc_reg_t prigroup_reg[] = { 12435 THDI_PORT_PRI_GRP0r, THDI_PORT_PRI_GRP1r 12436 }; 12437 static const soc_field_t prigroup_field[] = { 12438 PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf, 12439 PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf, 12440 PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf, 12441 PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf 12442 }; 12443 static const soc_field_t prigroup_spid_field[] = { 12444 PG0_SPIDf, PG1_SPIDf, PG2_SPIDf, PG3_SPIDf, 12445 PG4_SPIDf, PG5_SPIDf, PG6_SPIDf, PG7_SPIDf 12446 }; 12447 12448 if (cosq > 15 || cosq < 0) { 12449 /* Error. Input pri > Max Pri_Grp */ 12450 return BCM_E_PARAM; 12451 } 12452 if (!arg) { 12453 return BCM_E_PARAM; 12454 } 12455 12456 BCM_IF_ERROR_RETURN 12457 (_bcm_mn_cosq_localport_resolve(unit, gport, &local_port)); 12458 if (local_port < 0) { 12459 return BCM_E_PORT; 12460 } 12461 12462 /* get PG for port using Port+Cos */ 12463 if (cosq < 8) { 12464 reg = prigroup_reg[0]; 12465 } else { 12466 reg = prigroup_reg[1]; 12467 } 12468 12469 SOC_IF_ERROR_RETURN 12470 (soc_reg32_get(unit, reg, local_port, 0, &rval)); 12471 port_pg = soc_reg_field_get(unit, reg, rval, prigroup_field[cosq]); 12472 12473 12474 if ((type == bcmCosqControlIngressPortPGSharedLimitBytes) || 12475 (type == bcmCosqControlIngressPortPGMinLimitBytes) || 12476 (type == bcmCosqControlIngressPortPGHeadroomLimitBytes)|| 12477 (type == bcmCosqControlIngressPortPGResetFloorBytes)) { 12478 mem = THDI_PORT_PG_CONFIG_Xm; 12479 /* get index for Port-PG */ 12480 midx = SOC_MONTEREY_MMU_PIPED_MEM_INDEX(unit, local_port, mem, port_pg); 12481 } else if ((type == bcmCosqControlIngressPortPoolMaxLimitBytes) || 12482 (type == bcmCosqControlIngressPortPoolMinLimitBytes)) { 12483 reg = THDI_PORT_PG_SPIDr; 12484 12485 SOC_IF_ERROR_RETURN 12486 (soc_reg32_get(unit, reg, local_port, 0, &rval)); 12487 port_pg_pool = soc_reg_field_get(unit, reg, rval, prigroup_spid_field[port_pg]); 12488 12489 mem = THDI_PORT_SP_CONFIG_Xm; 12490 /* get index for Port-SP */ 12491 midx = SOC_MONTEREY_MMU_PIPED_MEM_INDEX(unit, local_port, mem, port_pg_pool); 12492 } else { 12493 return BCM_E_UNAVAIL; 12494 } 12495 12496 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, entry)); 12497 12498 switch (type) { 12499 case bcmCosqControlIngressPortPGSharedLimitBytes: 12500 fld_limit = PG_SHARED_LIMITf; 12501 granularity = 1; 12502 break; 12503 case bcmCosqControlIngressPortPoolMaxLimitBytes: 12504 fld_limit = PORT_SP_MAX_LIMITf; 12505 granularity = 1; 12506 break; 12507 case bcmCosqControlIngressPortPGMinLimitBytes: 12508 fld_limit = PG_MIN_LIMITf; 12509 granularity = 1; 12510 break; 12511 case bcmCosqControlIngressPortPoolMinLimitBytes: 12512 fld_limit = PORT_SP_MIN_LIMITf; 12513 granularity = 1; 12514 break; 12515 case bcmCosqControlIngressPortPGHeadroomLimitBytes: 12516 fld_limit = PG_HDRM_LIMITf; 12517 granularity =1; 12518 break; 12519 case bcmCosqControlIngressPortPGResetFloorBytes: 12520 fld_limit = PG_RESET_FLOORf; 12521 granularity =1; 12522 break; 12523 /* coverity[dead_error_begin] */ 12524 default: 12525 return BCM_E_UNAVAIL; 12526 } 12527 12528 *arg = soc_mem_field32_get(unit, mem, entry, fld_limit); 12529 *arg = (*arg) * granularity * _BCM_MN_BYTES_PER_CELL; 12530 return BCM_E_NONE; 12531 } 12532 12533 12534 12535 /* 12536 * This function is used to get ingress pool 12537 * limit given Ingress [Port, Priority] 12538 */ 12539 STATIC int 12540 _bcm_mn_cosq_ing_res_limit_get(int unit, bcm_gport_t gport, bcm_cos_t cosq, 12541 bcm_cosq_control_t type, int *arg) 12542 { 12543 bcm_port_t local_port; 12544 uint32 rval; 12545 soc_reg_t reg = INVALIDr; 12546 int port_pg, port_pg_pool; 12547 static const soc_reg_t prigroup_reg[] = { 12548 THDI_PORT_PRI_GRP0r, THDI_PORT_PRI_GRP1r 12549 }; 12550 static const soc_field_t prigroup_field[] = { 12551 PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf, 12552 PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf, 12553 PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf, 12554 PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf 12555 }; 12556 static const soc_field_t prigroup_spid_field[] = { 12557 PG0_SPIDf, PG1_SPIDf, PG2_SPIDf, PG3_SPIDf, 12558 PG4_SPIDf, PG5_SPIDf, PG6_SPIDf, PG7_SPIDf 12559 }; 12560 12561 if (cosq > 15 || cosq < 0) { 12562 /* Error. Input pri > Max Pri_Grp */ 12563 return BCM_E_PARAM; 12564 } 12565 if (!arg) { 12566 return BCM_E_PARAM; 12567 } 12568 12569 BCM_IF_ERROR_RETURN 12570 (_bcm_mn_cosq_localport_resolve(unit, gport, &local_port)); 12571 if (local_port < 0) { 12572 return BCM_E_PORT; 12573 } 12574 12575 /* get PG for port using Port+Cos */ 12576 if (cosq < 8) { 12577 reg = prigroup_reg[0]; 12578 } else { 12579 reg = prigroup_reg[1]; 12580 } 12581 12582 SOC_IF_ERROR_RETURN 12583 (soc_reg32_get(unit, reg, local_port, 0, &rval)); 12584 port_pg = soc_reg_field_get(unit, reg, rval, prigroup_field[cosq]); 12585 12586 12587 if (type == bcmCosqControlIngressPoolLimitBytes) { 12588 reg = THDI_PORT_PG_SPIDr; 12589 12590 SOC_IF_ERROR_RETURN 12591 (soc_reg32_get(unit, reg, local_port, 0, &rval)); 12592 port_pg_pool = soc_reg_field_get(unit, reg, rval, prigroup_spid_field[port_pg]); 12593 12594 SOC_IF_ERROR_RETURN 12595 (READ_THDI_BUFFER_CELL_LIMIT_SPr(unit, port_pg_pool, &rval)); 12596 *arg = soc_reg_field_get(unit, THDI_BUFFER_CELL_LIMIT_SPr, rval, LIMITf); 12597 } else { 12598 return BCM_E_PARAM; 12599 } 12600 12601 *arg = (*arg) * _BCM_MN_BYTES_PER_CELL; 12602 12603 return BCM_E_NONE; 12604 } 12605 12606 /* 12607 * This function is used to set ingress pool 12608 * limit given Ingress [Port, Priority] 12609 */ 12610 STATIC int 12611 _bcm_mn_cosq_ing_res_limit_set(int unit, bcm_gport_t gport, bcm_cos_t cosq, 12612 bcm_cosq_control_t type, int arg) 12613 { 12614 bcm_port_t local_port; 12615 uint32 max_val, rval; 12616 soc_reg_t reg = INVALIDr; 12617 int port_pg, port_pg_pool; 12618 static const soc_reg_t prigroup_reg[] = { 12619 THDI_PORT_PRI_GRP0r, THDI_PORT_PRI_GRP1r 12620 }; 12621 static const soc_field_t prigroup_field[] = { 12622 PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf, 12623 PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf, 12624 PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf, 12625 PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf 12626 }; 12627 static const soc_field_t prigroup_spid_field[] = { 12628 PG0_SPIDf, PG1_SPIDf, PG2_SPIDf, PG3_SPIDf, 12629 PG4_SPIDf, PG5_SPIDf, PG6_SPIDf, PG7_SPIDf 12630 }; 12631 12632 if (cosq > 15 || cosq < 0) { 12633 /* Error. Input pri > Max Pri_Grp */ 12634 return BCM_E_PARAM; 12635 } 12636 12637 if (arg < 0) { 12638 return BCM_E_PARAM; 12639 } 12640 12641 arg /= _BCM_MN_BYTES_PER_CELL; 12642 BCM_IF_ERROR_RETURN 12643 (_bcm_mn_cosq_localport_resolve(unit, gport, &local_port)); 12644 if (local_port < 0) { 12645 return BCM_E_PORT; 12646 } 12647 12648 /* get PG for port using Port+Cos */ 12649 if (cosq < 8) { 12650 reg = prigroup_reg[0]; 12651 } else { 12652 reg = prigroup_reg[1]; 12653 } 12654 12655 SOC_IF_ERROR_RETURN 12656 (soc_reg32_get(unit, reg, local_port, 0, &rval)); 12657 port_pg = soc_reg_field_get(unit, reg, rval, prigroup_field[cosq]); 12658 12659 if (type == bcmCosqControlIngressPoolLimitBytes) { 12660 reg = THDI_PORT_PG_SPIDr; 12661 12662 SOC_IF_ERROR_RETURN 12663 (soc_reg32_get(unit, reg, local_port, 0, &rval)); 12664 port_pg_pool = soc_reg_field_get(unit, reg, rval, prigroup_spid_field[port_pg]); 12665 12666 rval = 0; 12667 SOC_IF_ERROR_RETURN(READ_THDI_BUFFER_CELL_LIMIT_SPr(unit, port_pg_pool, &rval)); 12668 /* Check for min/max values */ 12669 max_val = (1 << soc_reg_field_length(unit, THDI_BUFFER_CELL_LIMIT_SPr, LIMITf)) - 1; 12670 if ((arg < 0) || (arg > max_val)) { 12671 return BCM_E_PARAM; 12672 } else { 12673 soc_reg_field_set(unit, THDI_BUFFER_CELL_LIMIT_SPr, &rval, LIMITf, arg); 12674 } 12675 12676 SOC_IF_ERROR_RETURN(WRITE_THDI_BUFFER_CELL_LIMIT_SPr(unit, port_pg_pool, rval)); 12677 } else { 12678 return BCM_E_PARAM; 12679 } 12680 12681 return BCM_E_NONE; 12682 } 12683 12684 STATIC int 12685 _bcm_mn_cosq_ef_op_at_index(int unit, int port, int hw_index, _bcm_cosq_op_t op, 12686 int *ef_val) 12687 { 12688 uint32 entry[SOC_MAX_MEM_WORDS]; 12689 soc_monterey_sched_type_t sched_type; 12690 soc_mem_t mem; 12691 12692 sched_type = _soc_monterey_port_sched_type_get(unit, port); 12693 12694 if (sched_type == SOC_MONTEREY_SCHED_LLS) { 12695 mem = _SOC_MONTEREY_NODE_PARENT_MEM(unit, port, SOC_MONTEREY_NODE_LVL_L2); 12696 SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, hw_index, &entry)); 12697 12698 if (op == _BCM_COSQ_OP_GET) { 12699 *ef_val = soc_mem_field32_get(unit, mem, &entry, C_EFf); 12700 } else { 12701 soc_mem_field32_set(unit, mem, &entry, C_EFf, *ef_val); 12702 SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, 12703 hw_index, &entry)); 12704 } 12705 } else { 12706 return BCM_E_UNAVAIL; 12707 } 12708 12709 return BCM_E_NONE; 12710 } 12711 12712 STATIC int 12713 _bcm_mn_cosq_ef_op(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, int *arg, 12714 _bcm_cosq_op_t op) 12715 { 12716 _bcm_mn_cosq_node_t *node; 12717 bcm_port_t local_port; 12718 int index, numq, from_cos, to_cos, ci; 12719 12720 if (BCM_GPORT_IS_SCHEDULER(gport)) { 12721 BCM_IF_ERROR_RETURN 12722 (_bcm_mn_cosq_node_get(unit, gport, 0, NULL, 12723 &local_port, NULL, &node)); 12724 BCM_IF_ERROR_RETURN( 12725 _bcm_mn_cosq_child_node_at_input(node, cosq, &node)); 12726 gport = node->gport; 12727 cosq = 0; 12728 } 12729 12730 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 12731 BCM_IF_ERROR_RETURN 12732 (_bcm_mn_cosq_index_resolve 12733 (unit, gport, cosq, _BCM_MN_COSQ_INDEX_STYLE_UCAST_QUEUE, 12734 &local_port, &index, NULL)); 12735 return _bcm_mn_cosq_ef_op_at_index(unit, local_port, index, op, arg); 12736 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 12737 BCM_IF_ERROR_RETURN 12738 (_bcm_mn_cosq_index_resolve 12739 (unit, gport, cosq, _BCM_MN_COSQ_INDEX_STYLE_MCAST_QUEUE, 12740 &local_port, &index, NULL)); 12741 return _bcm_mn_cosq_ef_op_at_index(unit, local_port, index, op, arg); 12742 } else if (BCM_GPORT_IS_SCHEDULER(gport)) { 12743 return BCM_E_PARAM; 12744 } else { 12745 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_port_has_ets(unit, local_port)); 12746 if (cosq == BCM_COS_INVALID) { 12747 from_cos = 0; 12748 to_cos = _MN_NUM_COS(unit) - 1; 12749 } else { 12750 from_cos = to_cos = cosq; 12751 } 12752 for (ci = from_cos; ci <= to_cos; ci++) { 12753 BCM_IF_ERROR_RETURN 12754 (_bcm_mn_cosq_index_resolve 12755 (unit, gport, ci, _BCM_MN_COSQ_INDEX_STYLE_UCAST_QUEUE, 12756 &local_port, &index, &numq)); 12757 12758 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_ef_op_at_index(unit, 12759 local_port, index, op, arg)); 12760 if (op == _BCM_COSQ_OP_GET) { 12761 return BCM_E_NONE; 12762 } 12763 12764 BCM_IF_ERROR_RETURN 12765 (_bcm_mn_cosq_index_resolve 12766 (unit, gport, ci, _BCM_MN_COSQ_INDEX_STYLE_MCAST_QUEUE, 12767 &local_port, &index, &numq)); 12768 12769 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_ef_op_at_index(unit, 12770 local_port, index, op, arg)); 12771 } 12772 } 12773 return BCM_E_NONE; 12774 } 12775 STATIC int 12776 _bcm_mn_cosq_qcn_proxy_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 12777 bcm_cosq_control_t type, int *arg) 12778 { 12779 int local_port; 12780 uint32 rval; 12781 12782 BCM_IF_ERROR_RETURN 12783 (_bcm_mn_cosq_localport_resolve(unit, gport, &local_port)); 12784 12785 BCM_IF_ERROR_RETURN(READ_QCN_CNM_PRP_CTRLr(unit, local_port, &rval)); 12786 *arg = soc_reg_field_get(unit, QCN_CNM_PRP_CTRLr, rval, ENABLEf); 12787 12788 return BCM_E_NONE; 12789 } 12790 12791 STATIC int 12792 _bcm_mn_cosq_qcn_proxy_set(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 12793 bcm_cosq_control_t type, int arg) 12794 { 12795 int local_port; 12796 uint32 rval; 12797 12798 BCM_IF_ERROR_RETURN 12799 (_bcm_mn_cosq_localport_resolve(unit, gport, &local_port)); 12800 12801 BCM_IF_ERROR_RETURN(READ_QCN_CNM_PRP_CTRLr(unit, local_port, &rval)); 12802 soc_reg_field_set(unit, QCN_CNM_PRP_CTRLr, &rval, ENABLEf, !!arg); 12803 soc_reg_field_set(unit, QCN_CNM_PRP_CTRLr, &rval, PRIORITY_BMAPf, 0xff); 12804 BCM_IF_ERROR_RETURN(WRITE_QCN_CNM_PRP_CTRLr(unit, local_port, rval)); 12805 return BCM_E_NONE; 12806 } 12807 12808 STATIC int 12809 _bcm_mn_cosq_alpha_set(int unit, 12810 bcm_gport_t gport, bcm_cos_queue_t cosq, 12811 bcm_cosq_control_drop_limit_alpha_value_t arg) 12812 { 12813 bcm_port_t local_port; 12814 int startq; 12815 int midx; 12816 uint32 rval; 12817 uint32 entry[SOC_MAX_MEM_WORDS]; 12818 uint32 entry2[SOC_MAX_MEM_WORDS]; 12819 soc_mem_t mem = INVALIDm, mem2 = INVALIDm; 12820 int alpha; 12821 int dynamic_thresh_mode; 12822 soc_reg_t reg = INVALIDr; 12823 int port_pg; 12824 static const soc_reg_t prigroup_reg[] = { 12825 THDI_PORT_PRI_GRP0r, THDI_PORT_PRI_GRP1r 12826 }; 12827 static const soc_field_t prigroup_field[] = { 12828 PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf, 12829 PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf, 12830 PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf, 12831 PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf 12832 }; 12833 12834 switch(arg) { 12835 case bcmCosqControlDropLimitAlpha_1_128: 12836 alpha = SOC_MONTEREY_COSQ_DROP_LIMIT_ALPHA_1_128; 12837 break; 12838 case bcmCosqControlDropLimitAlpha_1_64: 12839 alpha = SOC_MONTEREY_COSQ_DROP_LIMIT_ALPHA_1_64; 12840 break; 12841 case bcmCosqControlDropLimitAlpha_1_32: 12842 alpha = SOC_MONTEREY_COSQ_DROP_LIMIT_ALPHA_1_32; 12843 break; 12844 case bcmCosqControlDropLimitAlpha_1_16: 12845 alpha = SOC_MONTEREY_COSQ_DROP_LIMIT_ALPHA_1_16; 12846 break; 12847 case bcmCosqControlDropLimitAlpha_1_8: 12848 alpha = SOC_MONTEREY_COSQ_DROP_LIMIT_ALPHA_1_8; 12849 break; 12850 case bcmCosqControlDropLimitAlpha_1_4: 12851 alpha = SOC_MONTEREY_COSQ_DROP_LIMIT_ALPHA_1_4; 12852 break; 12853 case bcmCosqControlDropLimitAlpha_1_2: 12854 alpha = SOC_MONTEREY_COSQ_DROP_LIMIT_ALPHA_1_2; 12855 break; 12856 case bcmCosqControlDropLimitAlpha_1: 12857 alpha = SOC_MONTEREY_COSQ_DROP_LIMIT_ALPHA_1; 12858 break; 12859 case bcmCosqControlDropLimitAlpha_2: 12860 alpha = SOC_MONTEREY_COSQ_DROP_LIMIT_ALPHA_2; 12861 break; 12862 case bcmCosqControlDropLimitAlpha_4: 12863 alpha = SOC_MONTEREY_COSQ_DROP_LIMIT_ALPHA_4; 12864 break; 12865 case bcmCosqControlDropLimitAlpha_8: 12866 alpha = SOC_MONTEREY_COSQ_DROP_LIMIT_ALPHA_8; 12867 break; 12868 default: 12869 return BCM_E_PARAM; 12870 } 12871 12872 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 12873 BCM_IF_ERROR_RETURN 12874 (_bcm_mn_cosq_dynamic_thresh_enable_get(unit, gport, cosq, 12875 bcmCosqControlEgressUCSharedDynamicEnable, 12876 &dynamic_thresh_mode)); 12877 if (!dynamic_thresh_mode){ 12878 return BCM_E_CONFIG; 12879 } 12880 12881 BCM_IF_ERROR_RETURN 12882 (_bcm_mn_cosq_index_resolve(unit, gport, cosq, 12883 _BCM_MN_COSQ_INDEX_STYLE_UCAST_QUEUE, 12884 &local_port, &startq, NULL)); 12885 mem = MMU_THDU_XPIPE_CONFIG_QUEUEm; 12886 12887 BCM_IF_ERROR_RETURN 12888 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 12889 soc_mem_field32_set(unit, mem, entry, 12890 Q_SHARED_ALPHA_CELLf, alpha); 12891 SOC_IF_ERROR_RETURN 12892 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 12893 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 12894 BCM_IF_ERROR_RETURN 12895 (_bcm_mn_cosq_dynamic_thresh_enable_get(unit, gport, cosq, 12896 bcmCosqControlEgressMCSharedDynamicEnable, 12897 &dynamic_thresh_mode)); 12898 if (!dynamic_thresh_mode){ 12899 return BCM_E_CONFIG; 12900 } 12901 12902 BCM_IF_ERROR_RETURN 12903 (_bcm_mn_cosq_index_resolve(unit, gport, cosq, 12904 _BCM_MN_COSQ_INDEX_STYLE_MCAST_QUEUE, 12905 &local_port, &startq, NULL)); 12906 mem = MMU_THDM_DB_QUEUE_CONFIG_0m; 12907 mem2 = MMU_THDM_MCQE_QUEUE_CONFIG_0m; 12908 12909 startq -= _BCM_MN_NUM_L2_UC_LEAVES; /* MC queues comes after UC queues */ 12910 BCM_IF_ERROR_RETURN 12911 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 12912 soc_mem_field32_set(unit, mem, entry, Q_SHARED_ALPHAf, alpha); 12913 SOC_IF_ERROR_RETURN 12914 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 12915 12916 BCM_IF_ERROR_RETURN 12917 (soc_mem_read(unit, mem2, MEM_BLOCK_ALL, startq, entry2)); 12918 soc_mem_field32_set(unit, mem2, entry2, Q_SHARED_ALPHAf, alpha); 12919 SOC_IF_ERROR_RETURN 12920 (soc_mem_write(unit, mem2, MEM_BLOCK_ALL, startq, entry2)); 12921 } else { 12922 BCM_IF_ERROR_RETURN 12923 (_bcm_mn_cosq_dynamic_thresh_enable_get(unit, gport, cosq, 12924 bcmCosqControlIngressPortPGSharedDynamicEnable, 12925 &dynamic_thresh_mode)); 12926 if (!dynamic_thresh_mode){ 12927 return BCM_E_CONFIG; 12928 } 12929 12930 BCM_IF_ERROR_RETURN 12931 (_bcm_mn_cosq_localport_resolve(unit, gport, &local_port)); 12932 if (local_port < 0) { 12933 return BCM_E_PORT; 12934 } 12935 12936 /* get PG for port using Port+Cos */ 12937 if (cosq < 8) { 12938 reg = prigroup_reg[0]; 12939 } else { 12940 reg = prigroup_reg[1]; 12941 } 12942 12943 SOC_IF_ERROR_RETURN 12944 (soc_reg32_get(unit, reg, local_port, 0, &rval)); 12945 port_pg = soc_reg_field_get(unit, reg, rval, prigroup_field[cosq]); 12946 mem = THDI_PORT_PG_CONFIG_Xm; 12947 /* get index for Port-PG */ 12948 midx = SOC_MONTEREY_MMU_PIPED_MEM_INDEX(unit, local_port, mem, port_pg); 12949 BCM_IF_ERROR_RETURN 12950 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, entry)); 12951 soc_mem_field32_set(unit, mem, entry, 12952 PG_SHARED_LIMITf, alpha); 12953 SOC_IF_ERROR_RETURN 12954 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, midx, entry)); 12955 } 12956 12957 return BCM_E_NONE; 12958 } 12959 12960 12961 STATIC int 12962 _bcm_mn_cosq_alpha_get(int unit, 12963 bcm_gport_t gport, bcm_cos_queue_t cosq, 12964 bcm_cosq_control_drop_limit_alpha_value_t *arg) 12965 { 12966 bcm_port_t local_port; 12967 int startq; 12968 int midx; 12969 uint32 rval; 12970 uint32 entry[SOC_MAX_MEM_WORDS]; 12971 soc_mem_t mem = INVALIDm; 12972 int alpha; 12973 int dynamic_thresh_mode; 12974 soc_reg_t reg = INVALIDr; 12975 int port_pg; 12976 static const soc_reg_t prigroup_reg[] = { 12977 THDI_PORT_PRI_GRP0r, THDI_PORT_PRI_GRP1r 12978 }; 12979 static const soc_field_t prigroup_field[] = { 12980 PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf, 12981 PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf, 12982 PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf, 12983 PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf 12984 }; 12985 12986 if (!arg) { 12987 return BCM_E_PARAM; 12988 } 12989 12990 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 12991 BCM_IF_ERROR_RETURN 12992 (_bcm_mn_cosq_dynamic_thresh_enable_get(unit, gport, cosq, 12993 bcmCosqControlEgressUCSharedDynamicEnable, 12994 &dynamic_thresh_mode)); 12995 if (!dynamic_thresh_mode){ 12996 return BCM_E_CONFIG; 12997 } 12998 12999 BCM_IF_ERROR_RETURN 13000 (_bcm_mn_cosq_index_resolve(unit, gport, cosq, 13001 _BCM_MN_COSQ_INDEX_STYLE_UCAST_QUEUE, 13002 &local_port, &startq, NULL)); 13003 mem = MMU_THDU_XPIPE_CONFIG_QUEUEm; 13004 13005 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, 13006 startq, entry)); 13007 alpha = soc_mem_field32_get(unit, mem, entry, Q_SHARED_ALPHA_CELLf); 13008 13009 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 13010 BCM_IF_ERROR_RETURN 13011 (_bcm_mn_cosq_dynamic_thresh_enable_get(unit, gport, cosq, 13012 bcmCosqControlEgressMCSharedDynamicEnable, 13013 &dynamic_thresh_mode)); 13014 if (!dynamic_thresh_mode){ 13015 return BCM_E_CONFIG; 13016 } 13017 13018 BCM_IF_ERROR_RETURN 13019 (_bcm_mn_cosq_index_resolve(unit, gport, cosq, 13020 _BCM_MN_COSQ_INDEX_STYLE_MCAST_QUEUE, 13021 &local_port, &startq, NULL)); 13022 mem = MMU_THDM_DB_QUEUE_CONFIG_0m; 13023 13024 startq -= _BCM_MN_NUM_L2_UC_LEAVES; /* MC queues comes after UC queues */ 13025 BCM_IF_ERROR_RETURN 13026 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 13027 alpha = soc_mem_field32_get(unit, mem, entry, Q_SHARED_ALPHAf); 13028 13029 } else { 13030 BCM_IF_ERROR_RETURN 13031 (_bcm_mn_cosq_dynamic_thresh_enable_get(unit, gport, cosq, 13032 bcmCosqControlIngressPortPGSharedDynamicEnable, 13033 &dynamic_thresh_mode)); 13034 if (!dynamic_thresh_mode){ 13035 return BCM_E_CONFIG; 13036 } 13037 13038 BCM_IF_ERROR_RETURN 13039 (_bcm_mn_cosq_localport_resolve(unit, gport, &local_port)); 13040 if (local_port < 0) { 13041 return BCM_E_PORT; 13042 } 13043 13044 /* get PG for port using Port+Cos */ 13045 if (cosq < 8) { 13046 reg = prigroup_reg[0]; 13047 } else { 13048 reg = prigroup_reg[1]; 13049 } 13050 13051 SOC_IF_ERROR_RETURN 13052 (soc_reg32_get(unit, reg, local_port, 0, &rval)); 13053 port_pg = soc_reg_field_get(unit, reg, rval, prigroup_field[cosq]); 13054 mem = THDI_PORT_PG_CONFIG_Xm; 13055 /* get index for Port-PG */ 13056 midx = SOC_MONTEREY_MMU_PIPED_MEM_INDEX(unit, local_port, mem, port_pg); 13057 13058 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, 13059 midx, entry)); 13060 alpha = soc_mem_field32_get(unit, mem, entry, PG_SHARED_LIMITf); 13061 13062 } 13063 13064 switch(alpha) { 13065 case SOC_MONTEREY_COSQ_DROP_LIMIT_ALPHA_1_128: 13066 *arg = bcmCosqControlDropLimitAlpha_1_128; 13067 break; 13068 case SOC_MONTEREY_COSQ_DROP_LIMIT_ALPHA_1_64: 13069 *arg = bcmCosqControlDropLimitAlpha_1_64; 13070 break; 13071 case SOC_MONTEREY_COSQ_DROP_LIMIT_ALPHA_1_32: 13072 *arg = bcmCosqControlDropLimitAlpha_1_32; 13073 break; 13074 case SOC_MONTEREY_COSQ_DROP_LIMIT_ALPHA_1_16: 13075 *arg = bcmCosqControlDropLimitAlpha_1_16; 13076 break; 13077 case SOC_MONTEREY_COSQ_DROP_LIMIT_ALPHA_1_8: 13078 *arg = bcmCosqControlDropLimitAlpha_1_8; 13079 break; 13080 case SOC_MONTEREY_COSQ_DROP_LIMIT_ALPHA_1_4: 13081 *arg = bcmCosqControlDropLimitAlpha_1_4; 13082 break; 13083 case SOC_MONTEREY_COSQ_DROP_LIMIT_ALPHA_1_2: 13084 *arg = bcmCosqControlDropLimitAlpha_1_2; 13085 break; 13086 case SOC_MONTEREY_COSQ_DROP_LIMIT_ALPHA_1: 13087 *arg = bcmCosqControlDropLimitAlpha_1; 13088 break; 13089 case SOC_MONTEREY_COSQ_DROP_LIMIT_ALPHA_2: 13090 *arg = bcmCosqControlDropLimitAlpha_2; 13091 break; 13092 case SOC_MONTEREY_COSQ_DROP_LIMIT_ALPHA_4: 13093 *arg = bcmCosqControlDropLimitAlpha_4; 13094 break; 13095 case SOC_MONTEREY_COSQ_DROP_LIMIT_ALPHA_8: 13096 *arg = bcmCosqControlDropLimitAlpha_8; 13097 break; 13098 default: 13099 return BCM_E_PARAM; 13100 } 13101 13102 return BCM_E_NONE; 13103 } 13104 13105 STATIC int 13106 _bcm_mn_cosq_dynamic_thresh_enable_set(int unit, 13107 bcm_gport_t gport, bcm_cos_queue_t cosq, 13108 bcm_cosq_control_t type, int arg) 13109 { 13110 bcm_port_t local_port; 13111 int startq; 13112 int from_cos = 0, to_cos = 0; 13113 13114 int ci; 13115 int midx; 13116 uint32 rval; 13117 uint32 entry[SOC_MAX_MEM_WORDS]; 13118 uint32 entry2[SOC_MAX_MEM_WORDS]; 13119 soc_mem_t mem = INVALIDm, mem2 = INVALIDm; 13120 soc_reg_t reg = INVALIDr; 13121 int port_pg; 13122 static const soc_reg_t prigroup_reg[] = { 13123 THDI_PORT_PRI_GRP0r, THDI_PORT_PRI_GRP1r 13124 }; 13125 static const soc_field_t prigroup_field[] = { 13126 PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf, 13127 PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf, 13128 PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf, 13129 PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf 13130 }; 13131 13132 if ((cosq < 0) || (cosq > 15)){ 13133 return BCM_E_PARAM; 13134 } 13135 13136 13137 if (type == bcmCosqControlIngressPortPGSharedDynamicEnable) { 13138 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 13139 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 13140 return BCM_E_PARAM; 13141 } 13142 13143 BCM_IF_ERROR_RETURN 13144 (_bcm_mn_cosq_localport_resolve(unit, gport, &local_port)); 13145 if (local_port < 0) { 13146 return BCM_E_PORT; 13147 } 13148 13149 /* get PG for port using Port+Cos */ 13150 if (cosq < 8) { 13151 reg = prigroup_reg[0]; 13152 } else { 13153 reg = prigroup_reg[1]; 13154 } 13155 13156 SOC_IF_ERROR_RETURN 13157 (soc_reg32_get(unit, reg, local_port, 0, &rval)); 13158 port_pg = soc_reg_field_get(unit, reg, rval, prigroup_field[cosq]); 13159 mem = THDI_PORT_PG_CONFIG_Xm; 13160 /* get index for Port-PG */ 13161 midx = SOC_MONTEREY_MMU_PIPED_MEM_INDEX(unit, local_port, mem, port_pg); 13162 BCM_IF_ERROR_RETURN 13163 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, entry)); 13164 soc_mem_field32_set(unit, mem, entry, 13165 PG_SHARED_DYNAMICf, arg ? 1 : 0); 13166 /* Set default alpha value*/ 13167 if (arg) { 13168 soc_mem_field32_set(unit, mem, entry, 13169 PG_SHARED_LIMITf, bcmCosqControlDropLimitAlpha_1_128); 13170 } 13171 SOC_IF_ERROR_RETURN 13172 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, midx, entry)); 13173 } else if (type == bcmCosqControlEgressUCSharedDynamicEnable) { 13174 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 13175 BCM_IF_ERROR_RETURN 13176 (_bcm_mn_cosq_index_resolve(unit, gport, cosq, 13177 _BCM_MN_COSQ_INDEX_STYLE_UCAST_QUEUE, 13178 &local_port, &startq, NULL)); 13179 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 13180 return BCM_E_PARAM; 13181 } else { 13182 from_cos = to_cos = cosq; 13183 13184 BCM_IF_ERROR_RETURN 13185 (_bcm_mn_cosq_localport_resolve(unit, gport, &local_port)); 13186 if (local_port < 0) { 13187 return BCM_E_PORT; 13188 } 13189 for (ci = from_cos; ci <= to_cos; ci++) { 13190 BCM_IF_ERROR_RETURN 13191 (_bcm_mn_cosq_index_resolve(unit, local_port, ci, 13192 _BCM_MN_COSQ_INDEX_STYLE_UCAST_QUEUE, 13193 NULL, &startq, NULL)); 13194 13195 } 13196 } 13197 mem = MMU_THDU_XPIPE_CONFIG_QUEUEm; 13198 13199 BCM_IF_ERROR_RETURN 13200 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 13201 soc_mem_field32_set(unit, mem, entry, 13202 Q_LIMIT_DYNAMIC_CELLf, arg ? 1 : 0); 13203 /* Set default alpha value*/ 13204 if (arg) { 13205 soc_mem_field32_set(unit, mem, entry, 13206 Q_SHARED_ALPHA_CELLf, bcmCosqControlDropLimitAlpha_1_128); 13207 } 13208 SOC_IF_ERROR_RETURN 13209 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 13210 } else if (type == bcmCosqControlEgressMCSharedDynamicEnable) { 13211 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 13212 return BCM_E_PARAM; 13213 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 13214 BCM_IF_ERROR_RETURN 13215 (_bcm_mn_cosq_index_resolve(unit, gport, cosq, 13216 _BCM_MN_COSQ_INDEX_STYLE_MCAST_QUEUE, 13217 &local_port, &startq, NULL)); 13218 } 13219 else { 13220 from_cos = to_cos = cosq; 13221 13222 BCM_IF_ERROR_RETURN 13223 (_bcm_mn_cosq_localport_resolve(unit, gport, &local_port)); 13224 if (local_port < 0) { 13225 return BCM_E_PORT; 13226 } 13227 for (ci = from_cos; ci <= to_cos; ci++) { 13228 BCM_IF_ERROR_RETURN 13229 (_bcm_mn_cosq_index_resolve(unit, local_port, ci, 13230 _BCM_MN_COSQ_INDEX_STYLE_MCAST_QUEUE, 13231 NULL, &startq, NULL)); 13232 13233 } 13234 } 13235 13236 mem = MMU_THDM_DB_QUEUE_CONFIG_0m; 13237 mem2 = MMU_THDM_MCQE_QUEUE_CONFIG_0m; 13238 13239 startq -= _BCM_MN_NUM_L2_UC_LEAVES; /* MC queues comes after UC queues */ 13240 BCM_IF_ERROR_RETURN 13241 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 13242 soc_mem_field32_set(unit, mem, entry, Q_LIMIT_DYNAMICf, arg ? 1 : 0); 13243 /* Set default alpha value*/ 13244 if (arg) { 13245 soc_mem_field32_set(unit, mem, entry, 13246 Q_SHARED_ALPHAf, bcmCosqControlDropLimitAlpha_1_128); 13247 } 13248 SOC_IF_ERROR_RETURN 13249 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 13250 13251 BCM_IF_ERROR_RETURN 13252 (soc_mem_read(unit, mem2, MEM_BLOCK_ALL, startq, entry2)); 13253 soc_mem_field32_set(unit, mem2, entry2, Q_LIMIT_DYNAMICf, arg ? 1 : 0); 13254 /* Set default alpha value*/ 13255 if (arg) { 13256 soc_mem_field32_set(unit, mem2, entry2, 13257 Q_SHARED_ALPHAf, bcmCosqControlDropLimitAlpha_1_128); 13258 } 13259 SOC_IF_ERROR_RETURN 13260 (soc_mem_write(unit, mem2, MEM_BLOCK_ALL, startq, entry2)); 13261 13262 } else { 13263 return BCM_E_PARAM; 13264 } 13265 13266 return BCM_E_NONE; 13267 } 13268 13269 STATIC int 13270 _bcm_mn_cosq_dynamic_thresh_enable_get(int unit, 13271 bcm_gport_t gport, bcm_cos_queue_t cosq, 13272 bcm_cosq_control_t type, int *arg) 13273 { 13274 bcm_port_t local_port; 13275 int startq; 13276 int from_cos = 0, to_cos = 0; 13277 int ci; 13278 int midx; 13279 uint32 rval; 13280 uint32 entry[SOC_MAX_MEM_WORDS]; 13281 soc_mem_t mem = INVALIDm; 13282 soc_reg_t reg = INVALIDr; 13283 int port_pg; 13284 static const soc_reg_t prigroup_reg[] = { 13285 THDI_PORT_PRI_GRP0r, THDI_PORT_PRI_GRP1r 13286 }; 13287 static const soc_field_t prigroup_field[] = { 13288 PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf, 13289 PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf, 13290 PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf, 13291 PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf 13292 }; 13293 13294 if (!arg) { 13295 return BCM_E_PARAM; 13296 } 13297 13298 if ((cosq < 0) || (cosq > 15)){ 13299 return BCM_E_PARAM; 13300 } 13301 13302 if (type == bcmCosqControlIngressPortPGSharedDynamicEnable) { 13303 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 13304 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 13305 return BCM_E_PARAM; 13306 } 13307 BCM_IF_ERROR_RETURN 13308 (_bcm_mn_cosq_localport_resolve(unit, gport, &local_port)); 13309 if (local_port < 0) { 13310 return BCM_E_PORT; 13311 } 13312 13313 /* get PG for port using Port+Cos */ 13314 if (cosq < 8) { 13315 reg = prigroup_reg[0]; 13316 } else { 13317 reg = prigroup_reg[1]; 13318 } 13319 13320 SOC_IF_ERROR_RETURN 13321 (soc_reg32_get(unit, reg, local_port, 0, &rval)); 13322 port_pg = soc_reg_field_get(unit, reg, rval, prigroup_field[cosq]); 13323 mem = THDI_PORT_PG_CONFIG_Xm; 13324 /* get index for Port-PG */ 13325 midx = SOC_MONTEREY_MMU_PIPED_MEM_INDEX(unit, local_port, mem, port_pg); 13326 13327 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, 13328 midx, entry)); 13329 *arg = soc_mem_field32_get(unit, mem, entry, PG_SHARED_DYNAMICf); 13330 13331 } else if (type == bcmCosqControlEgressUCSharedDynamicEnable) { 13332 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 13333 BCM_IF_ERROR_RETURN 13334 (_bcm_mn_cosq_index_resolve(unit, gport, cosq, 13335 _BCM_MN_COSQ_INDEX_STYLE_UCAST_QUEUE, 13336 &local_port, &startq, NULL)); 13337 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 13338 return BCM_E_PARAM; 13339 } else { 13340 from_cos = to_cos = cosq; 13341 BCM_IF_ERROR_RETURN 13342 (_bcm_mn_cosq_localport_resolve(unit, gport, &local_port)); 13343 if (local_port < 0) { 13344 return BCM_E_PORT; 13345 } 13346 for (ci = from_cos; ci <= to_cos; ci++) { 13347 BCM_IF_ERROR_RETURN 13348 (_bcm_mn_cosq_index_resolve(unit, local_port, ci, 13349 _BCM_MN_COSQ_INDEX_STYLE_UCAST_QUEUE, 13350 NULL, &startq, NULL)); 13351 } 13352 } 13353 mem = MMU_THDU_XPIPE_CONFIG_QUEUEm; 13354 13355 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, 13356 startq, entry)); 13357 *arg = soc_mem_field32_get(unit, mem, entry, Q_LIMIT_DYNAMIC_CELLf); 13358 } else if (type == bcmCosqControlEgressMCSharedDynamicEnable) { 13359 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 13360 return BCM_E_PARAM; 13361 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 13362 BCM_IF_ERROR_RETURN 13363 (_bcm_mn_cosq_index_resolve(unit, gport, cosq, 13364 _BCM_MN_COSQ_INDEX_STYLE_MCAST_QUEUE, 13365 &local_port, &startq, NULL)); 13366 } 13367 else { 13368 from_cos = to_cos = cosq; 13369 BCM_IF_ERROR_RETURN 13370 (_bcm_mn_cosq_localport_resolve(unit, gport, &local_port)); 13371 if (local_port < 0) { 13372 return BCM_E_PORT; 13373 } 13374 for (ci = from_cos; ci <= to_cos; ci++) { 13375 BCM_IF_ERROR_RETURN 13376 (_bcm_mn_cosq_index_resolve(unit, local_port, ci, 13377 _BCM_MN_COSQ_INDEX_STYLE_MCAST_QUEUE, 13378 NULL, &startq, NULL)); 13379 } 13380 } 13381 mem = MMU_THDM_DB_QUEUE_CONFIG_0m; 13382 13383 startq -= _BCM_MN_NUM_L2_UC_LEAVES; /* MC queues comes after UC queues */ 13384 BCM_IF_ERROR_RETURN 13385 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 13386 *arg = soc_mem_field32_get(unit, mem, entry, Q_LIMIT_DYNAMICf); 13387 } else { 13388 return BCM_E_PARAM; 13389 } 13390 13391 return BCM_E_NONE; 13392 } 13393 13394 STATIC int 13395 _bcm_mn_cosq_egr_queue_limit_enable_set(int unit, bcm_gport_t gport, 13396 bcm_cos_queue_t cosq, 13397 bcm_cosq_control_t type, 13398 int arg) 13399 { 13400 bcm_port_t local_port; 13401 int startq; 13402 uint32 entry[SOC_MAX_MEM_WORDS]; 13403 soc_mem_t mem = INVALIDm; 13404 int enable; 13405 13406 if (arg < 0) { 13407 return BCM_E_PARAM; 13408 } 13409 13410 arg = arg ? 1 : 0; 13411 13412 if (type == bcmCosqControlEgressUCQueueLimitEnable) { 13413 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 13414 BCM_IF_ERROR_RETURN 13415 (_bcm_mn_cosq_index_resolve(unit, gport, cosq, 13416 _BCM_MN_COSQ_INDEX_STYLE_UCAST_QUEUE, 13417 &local_port, &startq, NULL)); 13418 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 13419 return BCM_E_PARAM; 13420 } else { 13421 if (cosq < 0) { 13422 return BCM_E_PARAM; 13423 } 13424 BCM_IF_ERROR_RETURN 13425 (_bcm_mn_cosq_localport_resolve(unit, gport, &local_port)); 13426 if (local_port < 0) { 13427 return BCM_E_PORT; 13428 } 13429 BCM_IF_ERROR_RETURN 13430 (_bcm_mn_cosq_index_resolve 13431 (unit, local_port, cosq, _BCM_MN_COSQ_INDEX_STYLE_UCAST_QUEUE, 13432 NULL, &startq, NULL)); 13433 } 13434 13435 mem = MMU_THDU_XPIPE_Q_TO_QGRP_MAPm; 13436 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 13437 enable = soc_mem_field32_get(unit, mem, entry, Q_LIMIT_ENABLEf); 13438 if (enable != arg) { 13439 soc_mem_field32_set(unit, mem, entry, Q_LIMIT_ENABLEf, arg); 13440 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 13441 } 13442 }else if (type == bcmCosqControlEgressMCQueueLimitEnable) { 13443 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 13444 return BCM_E_PARAM; 13445 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 13446 BCM_IF_ERROR_RETURN 13447 (_bcm_mn_cosq_index_resolve(unit, gport, cosq, 13448 _BCM_MN_COSQ_INDEX_STYLE_MCAST_QUEUE, 13449 &local_port, &startq, NULL)); 13450 } else { 13451 if (cosq < 0) { 13452 return BCM_E_PARAM; 13453 } 13454 BCM_IF_ERROR_RETURN 13455 (_bcm_mn_cosq_localport_resolve(unit, gport, &local_port)); 13456 if (local_port < 0) { 13457 return BCM_E_PORT; 13458 } 13459 BCM_IF_ERROR_RETURN 13460 (_bcm_mn_cosq_index_resolve(unit, local_port, cosq, 13461 _BCM_MN_COSQ_INDEX_STYLE_MCAST_QUEUE, 13462 NULL, &startq, NULL)); 13463 } 13464 startq -= _BCM_MN_NUM_L2_UC_LEAVES; /* MC queues comes after UC queues */ 13465 13466 mem = MMU_THDM_MCQE_QUEUE_CONFIG_0m; 13467 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 13468 enable = soc_mem_field32_get(unit, mem, entry, Q_LIMIT_ENABLEf); 13469 if (enable != arg) { 13470 soc_mem_field32_set(unit, mem, entry, Q_LIMIT_ENABLEf, arg); 13471 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 13472 } 13473 13474 mem = MMU_THDM_DB_QUEUE_CONFIG_0m; 13475 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 13476 enable = soc_mem_field32_get(unit, mem, entry, Q_LIMIT_ENABLEf); 13477 if (enable != arg) { 13478 soc_mem_field32_set(unit, mem, entry, Q_LIMIT_ENABLEf, arg); 13479 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 13480 } 13481 } else { 13482 return BCM_E_PARAM; 13483 } 13484 13485 return BCM_E_NONE; 13486 } 13487 13488 STATIC int 13489 _bcm_mn_cosq_egr_queue_limit_enable_get(int unit, bcm_gport_t gport, 13490 bcm_cos_queue_t cosq, 13491 bcm_cosq_control_t type, 13492 int *arg) 13493 { 13494 bcm_port_t local_port; 13495 int startq; 13496 uint32 entry[SOC_MAX_MEM_WORDS]; 13497 soc_mem_t mem = INVALIDm; 13498 13499 if (type == bcmCosqControlEgressUCQueueLimitEnable) { 13500 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 13501 BCM_IF_ERROR_RETURN 13502 (_bcm_mn_cosq_index_resolve(unit, gport, cosq, 13503 _BCM_MN_COSQ_INDEX_STYLE_UCAST_QUEUE, 13504 &local_port, &startq, NULL)); 13505 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 13506 return BCM_E_PARAM; 13507 } else { 13508 if (cosq < 0) { 13509 return BCM_E_PARAM; 13510 } 13511 BCM_IF_ERROR_RETURN 13512 (_bcm_mn_cosq_localport_resolve(unit, gport, &local_port)); 13513 if (local_port < 0) { 13514 return BCM_E_PORT; 13515 } 13516 BCM_IF_ERROR_RETURN 13517 (_bcm_mn_cosq_index_resolve 13518 (unit, local_port, cosq, _BCM_MN_COSQ_INDEX_STYLE_UCAST_QUEUE, 13519 NULL, &startq, NULL)); 13520 } 13521 13522 mem = MMU_THDU_XPIPE_Q_TO_QGRP_MAPm; 13523 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 13524 *arg = soc_mem_field32_get(unit, mem, entry, Q_LIMIT_ENABLEf); 13525 }else if (type == bcmCosqControlEgressMCQueueLimitEnable) { 13526 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 13527 return BCM_E_PARAM; 13528 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 13529 BCM_IF_ERROR_RETURN 13530 (_bcm_mn_cosq_index_resolve(unit, gport, cosq, 13531 _BCM_MN_COSQ_INDEX_STYLE_MCAST_QUEUE, 13532 &local_port, &startq, NULL)); 13533 } else { 13534 if (cosq < 0) { 13535 return BCM_E_PARAM; 13536 } 13537 BCM_IF_ERROR_RETURN 13538 (_bcm_mn_cosq_localport_resolve(unit, gport, &local_port)); 13539 if (local_port < 0) { 13540 return BCM_E_PORT; 13541 } 13542 BCM_IF_ERROR_RETURN 13543 (_bcm_mn_cosq_index_resolve 13544 (unit, local_port, cosq, _BCM_MN_COSQ_INDEX_STYLE_MCAST_QUEUE, 13545 NULL, &startq, NULL)); 13546 } 13547 mem = MMU_THDM_MCQE_QUEUE_CONFIG_0m; 13548 startq -= _BCM_MN_NUM_L2_UC_LEAVES; /* MC queues comes after UC queues */ 13549 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 13550 *arg = soc_mem_field32_get(unit, mem, entry, Q_LIMIT_ENABLEf); 13551 } else { 13552 return BCM_E_PARAM; 13553 } 13554 13555 return BCM_E_NONE; 13556 } 13557 STATIC 13558 int _bcm_mn_cosq_obm_threshold_get_reg_field(bcm_cos_queue_t cosq, 13559 bcm_cosq_control_t type, 13560 int *reg_index, soc_field_t *field) 13561 { 13562 13563 switch (cosq) { 13564 case BCM_COSQ_OBM_CLASS_LOSSLESS0: 13565 *reg_index = 0; 13566 *field = LOSSLESS0_DISCARDf; 13567 break; 13568 case BCM_COSQ_OBM_CLASS_LOSSLESS1: 13569 *reg_index = 0; 13570 *field = LOSSLESS1_DISCARDf; 13571 break; 13572 case BCM_COSQ_OBM_CLASS_LOSSY_LOW: 13573 *reg_index = 0; 13574 *field = LOSSY_LOW_PRIf; 13575 break; 13576 case BCM_COSQ_OBM_CLASS_LOSSY: 13577 *reg_index = 0; 13578 if (type == bcmCosqControlObmDiscardLimit) { 13579 *field = LOSSY_DISCARDf; 13580 } else { /*type must be bcmCosqControlObmMinLimit */ 13581 *field = LOSSY_MINf; 13582 } 13583 break; 13584 case BCM_COSQ_OBM_CLASS_EXPRESS: 13585 *reg_index = 1; 13586 *field = EXPRESS_DISCARDf; 13587 break; 13588 case BCM_COSQ_OBM_CLASS_ALL: 13589 *reg_index = 1; 13590 *field = DISCARD_LIMITf; 13591 break; 13592 default: 13593 return BCM_E_PARAM; 13594 } 13595 return BCM_E_NONE; 13596 } 13597 STATIC 13598 int _bcm_mn_cosq_obm_threshold_set_get(int unit, bcm_gport_t gport, 13599 bcm_cos_queue_t cosq, 13600 bcm_cosq_control_t type, 13601 int *arg, int set) 13602 { 13603 soc_info_t *si; 13604 int pgw, pgw_inst, subport, obm; 13605 int phy_port; 13606 bcm_port_t port; 13607 int reg_index; 13608 soc_reg_t reg; 13609 soc_field_t field; 13610 uint64 rval64; 13611 13612 static const soc_reg_t obm_threshold_regs[2][8] = { 13613 {IDB_OBM0_THRESHOLD_0r, IDB_OBM1_THRESHOLD_0r, 13614 IDB_OBM2_THRESHOLD_0r, IDB_OBM3_THRESHOLD_0r, 13615 IDB_OBM4_THRESHOLD_0r, IDB_OBM5_THRESHOLD_0r, 13616 IDB_OBM6_THRESHOLD_0r, IDB_OBM7_THRESHOLD_0r}, 13617 13618 {IDB_OBM0_THRESHOLD_1r, IDB_OBM1_THRESHOLD_1r, 13619 IDB_OBM2_THRESHOLD_1r, IDB_OBM3_THRESHOLD_1r, 13620 IDB_OBM4_THRESHOLD_1r, IDB_OBM5_THRESHOLD_1r, 13621 IDB_OBM6_THRESHOLD_1r, IDB_OBM7_THRESHOLD_1r} 13622 }; 13623 13624 si = &SOC_INFO(unit); 13625 BCM_IF_ERROR_RETURN(bcm_esw_port_local_get(unit, gport, &port)); 13626 phy_port = si->port_l2p_mapping[port]; 13627 13628 if (phy_port == -1) { 13629 return BCM_E_PARAM; 13630 } 13631 13632 if (IS_CPU_PORT(unit, port) || IS_LB_PORT(unit, port) 13633 || IS_MACSEC_PORT(unit, port)) { 13634 /* nothing to do for non-idb ports */ 13635 return BCM_E_NONE; 13636 } 13637 obm = si->port_serdes[port]; 13638 obm %= MONTEREY_TSCS_PER_PGW; 13639 pgw = si->port_group[port]; 13640 pgw_inst = (pgw | SOC_REG_ADDR_INSTANCE_MASK); 13641 subport = (phy_port - 1) % MONTEREY_PORTS_PER_TSC; 13642 13643 BCM_IF_ERROR_RETURN 13644 (_bcm_mn_cosq_obm_threshold_get_reg_field(cosq, type, 13645 ®_index, &field)); 13646 13647 if (type == bcmCosqControlObmDiscardLimit) { 13648 if ((cosq < BCM_COSQ_OBM_CLASS_LOSSLESS0) || 13649 (cosq > BCM_COSQ_OBM_CLASS_ALL)) { 13650 return BCM_E_PARAM; 13651 } 13652 } else if (cosq == bcmCosqControlObmMinLimit) { 13653 if (cosq != BCM_COSQ_OBM_CLASS_LOSSY) { 13654 return BCM_E_PARAM; 13655 } 13656 } 13657 COMPILER_64_ZERO(rval64); 13658 reg = obm_threshold_regs[reg_index][obm]; 13659 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, pgw_inst, subport, &rval64)); 13660 if (set) { 13661 soc_reg64_field32_set(unit, reg, &rval64, field, *arg & 0x7ff); 13662 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, pgw_inst, subport, rval64)); 13663 } else { 13664 *arg = soc_reg64_field32_get(unit, reg, rval64, field); 13665 } 13666 return BCM_E_NONE; 13667 } 13668 int 13669 bcm_mn_cosq_control_set(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 13670 bcm_cosq_control_t type, int arg) 13671 { 13672 switch (type) { 13673 case bcmCosqControlEgressPool: 13674 case bcmCosqControlEgressPoolLimitBytes: 13675 case bcmCosqControlEgressPoolYellowLimitBytes: 13676 case bcmCosqControlEgressPoolRedLimitBytes: 13677 case bcmCosqControlEgressPoolLimitEnable: 13678 case bcmCosqControlUCEgressPool: 13679 case bcmCosqControlMCEgressPool: 13680 case bcmCosqControlEgressPoolSharedLimitBytes: 13681 case bcmCosqControlEgressPoolResumeLimitBytes: 13682 case bcmCosqControlEgressPoolYellowSharedLimitBytes: 13683 case bcmCosqControlEgressPoolYellowResumeLimitBytes: 13684 case bcmCosqControlEgressPoolRedSharedLimitBytes: 13685 case bcmCosqControlEgressPoolRedResumeLimitBytes: 13686 return _bcm_mn_cosq_egr_pool_set(unit, gport, cosq, type, arg); 13687 case bcmCosqControlEfPropagation: 13688 return _bcm_mn_cosq_ef_op(unit, gport, cosq, &arg, _BCM_COSQ_OP_SET); 13689 case bcmCosqControlCongestionProxy: 13690 return _bcm_mn_cosq_qcn_proxy_set(unit, gport, cosq, type, arg); 13691 case bcmCosqControlEgressUCQueueSharedLimitBytes: 13692 case bcmCosqControlEgressMCQueueSharedLimitBytes: 13693 case bcmCosqControlEgressUCQueueMinLimitBytes: 13694 case bcmCosqControlEgressMCQueueMinLimitBytes: 13695 return _bcm_mn_cosq_egr_queue_set(unit, gport, cosq, type, arg); 13696 case bcmCosqControlIngressPortPGSharedLimitBytes: 13697 case bcmCosqControlIngressPortPoolMaxLimitBytes: 13698 case bcmCosqControlIngressPortPGMinLimitBytes: 13699 case bcmCosqControlIngressPortPoolMinLimitBytes: 13700 case bcmCosqControlIngressPortPGHeadroomLimitBytes: 13701 case bcmCosqControlIngressPortPGResetFloorBytes: 13702 return _bcm_mn_cosq_ing_res_set(unit, gport, cosq, type, arg); 13703 case bcmCosqControlIngressPoolLimitBytes: 13704 return _bcm_mn_cosq_ing_res_limit_set(unit, gport, cosq, type, arg); 13705 case bcmCosqControlIngressPool: 13706 return _bcm_mn_cosq_ing_pool_set(unit, gport, cosq, type, arg); 13707 case bcmCosqControlDropLimitAlpha: 13708 return _bcm_mn_cosq_alpha_set(unit, gport, cosq, 13709 (bcm_cosq_control_drop_limit_alpha_value_t)arg); 13710 case bcmCosqControlIngressPortPGSharedDynamicEnable: 13711 case bcmCosqControlEgressUCSharedDynamicEnable: 13712 case bcmCosqControlEgressMCSharedDynamicEnable: 13713 return _bcm_mn_cosq_dynamic_thresh_enable_set(unit, gport, cosq, 13714 type, arg); 13715 case bcmCosqControlEgressPortPoolYellowLimitBytes: 13716 case bcmCosqControlEgressPortPoolRedLimitBytes: 13717 return _bcm_mn_cosq_egr_port_pool_set(unit, gport, cosq, type, arg); 13718 case bcmCosqControlEgressUCQueueLimitEnable: 13719 case bcmCosqControlEgressMCQueueLimitEnable: 13720 return _bcm_mn_cosq_egr_queue_limit_enable_set(unit, gport, cosq, type, arg); 13721 case bcmCosqControlObmDiscardLimit: 13722 case bcmCosqControlObmMinLimit: 13723 return _bcm_mn_cosq_obm_threshold_set_get(unit, gport, cosq, type, &arg, 1); 13724 default: 13725 break; 13726 } 13727 13728 return BCM_E_UNAVAIL; 13729 } 13730 13731 int 13732 bcm_mn_cosq_control_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 13733 bcm_cosq_control_t type, int *arg) 13734 { 13735 switch (type) { 13736 case bcmCosqControlEgressPool: 13737 case bcmCosqControlEgressPoolLimitBytes: 13738 case bcmCosqControlEgressPoolYellowLimitBytes: 13739 case bcmCosqControlEgressPoolRedLimitBytes: 13740 case bcmCosqControlEgressPoolLimitEnable: 13741 case bcmCosqControlUCEgressPool: 13742 case bcmCosqControlMCEgressPool: 13743 case bcmCosqControlEgressPoolSharedLimitBytes: 13744 case bcmCosqControlEgressPoolResumeLimitBytes: 13745 case bcmCosqControlEgressPoolYellowSharedLimitBytes: 13746 case bcmCosqControlEgressPoolYellowResumeLimitBytes: 13747 case bcmCosqControlEgressPoolRedSharedLimitBytes: 13748 case bcmCosqControlEgressPoolRedResumeLimitBytes: 13749 return _bcm_mn_cosq_egr_pool_get(unit, gport, cosq, type, arg); 13750 case bcmCosqControlEfPropagation: 13751 return _bcm_mn_cosq_ef_op(unit, gport, cosq, arg, _BCM_COSQ_OP_GET); 13752 case bcmCosqControlEgressUCQueueSharedLimitBytes: 13753 case bcmCosqControlEgressMCQueueSharedLimitBytes: 13754 case bcmCosqControlEgressUCQueueMinLimitBytes: 13755 case bcmCosqControlEgressMCQueueMinLimitBytes: 13756 return _bcm_mn_cosq_egr_queue_get(unit, gport, cosq, type, arg); 13757 case bcmCosqControlIngressPortPGSharedLimitBytes: 13758 case bcmCosqControlIngressPortPoolMaxLimitBytes: 13759 case bcmCosqControlIngressPortPGMinLimitBytes: 13760 case bcmCosqControlIngressPortPoolMinLimitBytes: 13761 case bcmCosqControlIngressPortPGHeadroomLimitBytes: 13762 case bcmCosqControlIngressPortPGResetFloorBytes: 13763 return _bcm_mn_cosq_ing_res_get(unit, gport, cosq, type, arg); 13764 case bcmCosqControlIngressPoolLimitBytes: 13765 return _bcm_mn_cosq_ing_res_limit_get(unit, gport, cosq, type, arg); 13766 case bcmCosqControlSPPortLimitState: 13767 case bcmCosqControlPGPortLimitState: 13768 case bcmCosqControlPGPortXoffState: 13769 case bcmCosqControlPoolRedDropState: 13770 case bcmCosqControlPoolYellowDropState: 13771 case bcmCosqControlPoolGreenDropState: 13772 return _bcm_mn_cosq_state_get(unit, gport, cosq, type, arg); 13773 case bcmCosqControlIngressPool: 13774 return _bcm_mn_cosq_ing_pool_get(unit, gport, cosq, type, arg); 13775 case bcmCosqControlDropLimitAlpha: 13776 return _bcm_mn_cosq_alpha_get(unit, gport, cosq, 13777 (bcm_cosq_control_drop_limit_alpha_value_t *)arg); 13778 case bcmCosqControlIngressPortPGSharedDynamicEnable: 13779 case bcmCosqControlEgressUCSharedDynamicEnable: 13780 case bcmCosqControlEgressMCSharedDynamicEnable: 13781 return _bcm_mn_cosq_dynamic_thresh_enable_get(unit, gport, cosq, 13782 type, arg); 13783 case bcmCosqControlPortQueueUcast: 13784 case bcmCosqControlPortQueueMcast: 13785 return _bcm_mn_cosq_port_qnum_get(unit, gport, cosq, type, arg); 13786 case bcmCosqControlEgressPortPoolYellowLimitBytes: 13787 case bcmCosqControlEgressPortPoolRedLimitBytes: 13788 return _bcm_mn_cosq_egr_port_pool_get(unit, gport, cosq, type, arg); 13789 case bcmCosqControlEgressUCQueueLimitEnable: 13790 case bcmCosqControlEgressMCQueueLimitEnable: 13791 return _bcm_mn_cosq_egr_queue_limit_enable_get(unit, gport, cosq, type, arg); 13792 case bcmCosqControlCongestionProxy: 13793 return _bcm_mn_cosq_qcn_proxy_get(unit, gport, cosq, type, arg); 13794 case bcmCosqControlObmDiscardLimit: 13795 case bcmCosqControlObmMinLimit: 13796 return _bcm_mn_cosq_obm_threshold_set_get(unit, gport, cosq, type, arg, 0); 13797 default: 13798 break; 13799 } 13800 13801 return BCM_E_UNAVAIL; 13802 } 13803 13804 int 13805 bcm_mn_cosq_service_pool_set( 13806 int unit, 13807 bcm_service_pool_id_t id, 13808 bcm_cosq_service_pool_t cosq_service_pool) 13809 { 13810 uint32 rval; 13811 soc_field_t fld_enable = INVALIDf; 13812 static const soc_field_t color_enable_fields[] = { 13813 PORTSP_COLOR_LIMIT_ENABLE_0f, PORTSP_COLOR_LIMIT_ENABLE_1f, 13814 PORTSP_COLOR_LIMIT_ENABLE_2f, PORTSP_COLOR_LIMIT_ENABLE_3f 13815 }; 13816 13817 if (id < 0 || (id > _MN_NUM_SERVICE_POOL - 1)) { 13818 return BCM_E_PARAM; 13819 } 13820 13821 SOC_IF_ERROR_RETURN(READ_MMU_THDM_DB_DEVICE_THR_CONFIGr(unit, &rval)); 13822 switch (cosq_service_pool.type) { 13823 case bcmCosqServicePoolPortColorAware: 13824 fld_enable = color_enable_fields[id]; 13825 break; 13826 default: 13827 return BCM_E_PARAM; 13828 } 13829 13830 soc_reg_field_set(unit, MMU_THDM_DB_DEVICE_THR_CONFIGr, &rval, 13831 fld_enable, cosq_service_pool.enabled ? 1 : 0); 13832 SOC_IF_ERROR_RETURN(WRITE_MMU_THDM_DB_DEVICE_THR_CONFIGr(unit, rval)); 13833 return BCM_E_NONE; 13834 } 13835 13836 13837 int 13838 bcm_mn_cosq_service_pool_get( 13839 int unit, 13840 bcm_service_pool_id_t id, 13841 bcm_cosq_service_pool_t *cosq_service_pool) 13842 { 13843 uint32 rval; 13844 soc_field_t fld_enable = INVALIDf; 13845 static const soc_field_t color_enable_fields[] = { 13846 PORTSP_COLOR_LIMIT_ENABLE_0f, PORTSP_COLOR_LIMIT_ENABLE_1f, 13847 PORTSP_COLOR_LIMIT_ENABLE_2f, PORTSP_COLOR_LIMIT_ENABLE_3f 13848 }; 13849 13850 if (cosq_service_pool == NULL) { 13851 return BCM_E_PARAM; 13852 } 13853 13854 if (id < 0 || (id > _MN_NUM_SERVICE_POOL - 1)) { 13855 return BCM_E_PARAM; 13856 } 13857 13858 SOC_IF_ERROR_RETURN(READ_MMU_THDM_DB_DEVICE_THR_CONFIGr(unit, &rval)); 13859 switch (cosq_service_pool->type) { 13860 case bcmCosqServicePoolPortColorAware: 13861 fld_enable = color_enable_fields[id]; 13862 break; 13863 default: 13864 return BCM_E_PARAM; 13865 } 13866 13867 cosq_service_pool->enabled = soc_reg_field_get(unit, MMU_THDM_DB_DEVICE_THR_CONFIGr, rval, 13868 fld_enable); 13869 return BCM_E_NONE; 13870 } 13871 13872 /* 13873 * Function: 13874 * bcm_mn_cosq_gport_bandwidth_set 13875 * Purpose: 13876 * Configure COS queue bandwidth control 13877 * Parameters: 13878 * unit - (IN) unit number 13879 * gport - (IN) GPORT identifier 13880 * cosq - (IN) COS queue to configure, -1 for all COS queues 13881 * kbits_sec_min - (IN) minimum bandwidth, kbits/sec 13882 * kbits_sec_max - (IN) maximum bandwidth, kbits/sec 13883 * flags - (IN) BCM_COSQ_BW_* 13884 * Returns: 13885 * BCM_E_XXX 13886 */ 13887 int 13888 bcm_mn_cosq_gport_bandwidth_set(int unit, bcm_gport_t gport, 13889 bcm_cos_queue_t cosq, uint32 kbits_sec_min, 13890 uint32 kbits_sec_max, uint32 flags) 13891 { 13892 int i, start_cos, end_cos, local_port; 13893 _bcm_mn_cosq_node_t *node; 13894 uint32 burst_min, burst_max; 13895 13896 if (cosq <= -1) { 13897 if (BCM_GPORT_IS_SET(gport)) { 13898 BCM_IF_ERROR_RETURN 13899 (_bcm_mn_cosq_node_get(unit, gport, 0, NULL, 13900 NULL, NULL, &node)); 13901 start_cos = 0; 13902 if (node->numq == -1) { 13903 end_cos = 0; 13904 } else { 13905 end_cos = node->numq - 1; 13906 } 13907 } else { 13908 start_cos = 0; 13909 end_cos = _MN_NUM_COS(unit) - 1; 13910 } 13911 } else { 13912 start_cos = end_cos = cosq; 13913 } 13914 13915 if(_BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, gport)){ 13916 BCM_IF_ERROR_RETURN( 13917 _bcmi_coe_subport_physical_port_get(unit, gport, &local_port)); 13918 } else { 13919 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_localport_resolve(unit, gport, &local_port)); 13920 } 13921 burst_min = (kbits_sec_min > 0) ? 13922 _bcm_td_default_burst_size(unit, local_port, kbits_sec_min) : 0; 13923 13924 burst_max = (kbits_sec_max > 0) ? 13925 _bcm_td_default_burst_size(unit, local_port, kbits_sec_max) : 0; 13926 13927 for (i = start_cos; i <= end_cos; i++) { 13928 BCM_IF_ERROR_RETURN 13929 (_bcm_mn_cosq_bucket_set(unit, gport, i, kbits_sec_min, 13930 kbits_sec_max, burst_min, burst_max, flags)); 13931 } 13932 13933 return BCM_E_NONE; 13934 } 13935 13936 /* 13937 * Function: 13938 * bcm_mn_cosq_gport_bandwidth_get 13939 * Purpose: 13940 * Get COS queue bandwidth control configuration 13941 * Parameters: 13942 * unit - (IN) unit number 13943 * gport - (IN) GPORT identifier 13944 * cosq - (IN) COS queue to get, -1 for any COS queue 13945 * kbits_sec_min - (OUT) minimum bandwidth, kbits/sec 13946 * kbits_sec_max - (OUT) maximum bandwidth, kbits/sec 13947 * flags - (OUT) BCM_COSQ_BW_* 13948 * Returns: 13949 * BCM_E_XXX 13950 */ 13951 int 13952 bcm_mn_cosq_gport_bandwidth_get(int unit, bcm_gport_t gport, 13953 bcm_cos_queue_t cosq, uint32 *kbits_sec_min, 13954 uint32 *kbits_sec_max, uint32 *flags) 13955 { 13956 uint32 kbits_sec_burst; 13957 13958 if (cosq == -1) { 13959 return BCM_E_PARAM; 13960 } 13961 13962 BCM_IF_ERROR_RETURN 13963 (_bcm_mn_cosq_bucket_get(unit, gport, cosq, 13964 kbits_sec_min, kbits_sec_max, 13965 &kbits_sec_burst, &kbits_sec_burst, flags)); 13966 return BCM_E_NONE; 13967 } 13968 13969 /* 13970 * Function: 13971 * bcm_mn_cosq_gport_bandwidth_burst_set 13972 * Purpose: 13973 * Configure COS queue bandwidth burst setting 13974 * Parameters: 13975 * unit - (IN) unit number 13976 * gport - (IN) GPORT identifier 13977 * cosq - (IN) COS queue to configure, -1 for all COS queues 13978 * kbits_burst - (IN) maximum burst, kbits 13979 * Returns: 13980 * BCM_E_XXX 13981 */ 13982 int 13983 bcm_mn_cosq_gport_bandwidth_burst_set(int unit, bcm_gport_t gport, 13984 bcm_cos_queue_t cosq, 13985 uint32 kbits_burst_min, 13986 uint32 kbits_burst_max) 13987 { 13988 int i, start_cos, end_cos; 13989 uint32 kbits_sec_min = 0; 13990 uint32 kbits_sec_max = 0; 13991 uint32 kbits_sec_burst = 0; 13992 uint32 flags = 0; 13993 _bcm_mn_cosq_node_t *node; 13994 13995 if (cosq < -1) { 13996 return BCM_E_PARAM; 13997 } 13998 13999 if (cosq == -1) { 14000 if (BCM_GPORT_IS_SET(gport) && 14001 !(_BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, gport))) { 14002 BCM_IF_ERROR_RETURN 14003 (_bcm_mn_cosq_node_get(unit, gport, 0, NULL, 14004 NULL, NULL, &node)); 14005 start_cos = 0; 14006 end_cos = node->numq - 1; 14007 } else { 14008 start_cos = 0; 14009 end_cos = _MN_NUM_COS(unit) - 1; 14010 } 14011 } else { 14012 start_cos = end_cos = cosq; 14013 } 14014 14015 for (i = start_cos; i <= end_cos; i++) { 14016 BCM_IF_ERROR_RETURN 14017 (_bcm_mn_cosq_bucket_get(unit, gport, i, &kbits_sec_min, 14018 &kbits_sec_max, &kbits_sec_burst, 14019 &kbits_sec_burst, &flags)); 14020 BCM_IF_ERROR_RETURN 14021 (_bcm_mn_cosq_bucket_set(unit, gport, i, kbits_sec_min, 14022 kbits_sec_max, kbits_burst_min, 14023 kbits_burst_max, flags)); 14024 } 14025 14026 return BCM_E_NONE; 14027 } 14028 14029 /* 14030 * Function: 14031 * bcm_mn_cosq_gport_bandwidth_burst_get 14032 * Purpose: 14033 * Get COS queue bandwidth burst setting 14034 * Parameters: 14035 * unit - (IN) unit number 14036 * gport - (IN) GPORT identifier 14037 * cosq - (IN) COS queue to get, -1 for any queue 14038 * kbits_burst - (OUT) maximum burst, kbits 14039 * Returns: 14040 * BCM_E_XXX 14041 */ 14042 int 14043 bcm_mn_cosq_gport_bandwidth_burst_get(int unit, bcm_gport_t gport, 14044 bcm_cos_queue_t cosq, 14045 uint32 *kbits_burst_min, 14046 uint32 *kbits_burst_max) 14047 { 14048 uint32 kbits_sec_min, kbits_sec_max, flags; 14049 14050 if (cosq < -1) { 14051 return BCM_E_PARAM; 14052 } 14053 14054 BCM_IF_ERROR_RETURN 14055 (_bcm_mn_cosq_bucket_get(unit, gport, cosq == -1 ? 0 : cosq, 14056 &kbits_sec_min, &kbits_sec_max, kbits_burst_min, 14057 kbits_burst_max, &flags)); 14058 14059 return BCM_E_NONE; 14060 } 14061 14062 /* 14063 * Function: 14064 * bcm_mn_cosq_gport_sched_set 14065 * Purpose: 14066 * Configure COS queue scheduler setting 14067 * Parameters: 14068 * unit - (IN) unit number 14069 * gport - (IN) GPORT identifier 14070 * cosq - (IN) COS queue to configure, -1 for all COS queues 14071 * mode - (IN) Scheduling mode, one of BCM_COSQ_xxx 14072 * weight - (IN) queue weight 14073 * Returns: 14074 * BCM_E_XXX 14075 */ 14076 int 14077 bcm_mn_cosq_gport_sched_set(int unit, bcm_gport_t gport, 14078 bcm_cos_queue_t cosq, int mode, int weight) 14079 { 14080 int rv, numq, i, count; 14081 14082 if (cosq == -1) { 14083 BCM_IF_ERROR_RETURN 14084 (_bcm_mn_cosq_index_resolve(unit, gport, cosq, 14085 _BCM_MN_COSQ_INDEX_STYLE_SCHEDULER, 14086 NULL, NULL, &numq)); 14087 cosq = 0; 14088 } else { 14089 numq = 1; 14090 } 14091 14092 count = 0; 14093 for (i = 0; i < numq; i++) { 14094 rv = _bcm_mn_cosq_sched_set(unit, gport, cosq + i, mode, weight); 14095 if (rv == BCM_E_NOT_FOUND) { 14096 continue; 14097 } else if (BCM_FAILURE(rv)) { 14098 return rv; 14099 } else { 14100 count++; 14101 } 14102 } 14103 14104 return count > 0 ? BCM_E_NONE : BCM_E_NOT_FOUND; 14105 } 14106 14107 /* 14108 * Function: 14109 * bcm_mn_cosq_gport_sched_get 14110 * Purpose: 14111 * Get COS queue scheduler setting 14112 * Parameters: 14113 * unit - (IN) unit number 14114 * gport - (IN) GPORT identifier 14115 * cosq - (IN) COS queue to get, -1 for any queue 14116 * mode - (OUT) Scheduling mode, one of BCM_COSQ_xxx 14117 * weight - (OUT) queue weight 14118 * Returns: 14119 * BCM_E_XXX 14120 */ 14121 int 14122 bcm_mn_cosq_gport_sched_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 14123 int *mode, int *weight) 14124 { 14125 int rv, numq, i; 14126 14127 if (cosq == -1) { 14128 BCM_IF_ERROR_RETURN 14129 (_bcm_mn_cosq_index_resolve(unit, gport, 0, 14130 _BCM_MN_COSQ_INDEX_STYLE_SCHEDULER, 14131 NULL, NULL, &numq)); 14132 cosq = 0; 14133 } else { 14134 numq = 1; 14135 } 14136 14137 for (i = 0; i < numq; i++) { 14138 rv = _bcm_mn_cosq_sched_get(unit, gport, cosq + i, mode, weight); 14139 if (rv == BCM_E_NOT_FOUND) { 14140 continue; 14141 } else { 14142 return rv; 14143 } 14144 } 14145 14146 return BCM_E_NOT_FOUND; 14147 } 14148 14149 /* 14150 * Function: 14151 * bcm_mn_cosq_gport_discard_set 14152 * Purpose: 14153 * Configure port WRED setting 14154 * Parameters: 14155 * unit - (IN) unit number 14156 * port - (IN) GPORT identifier 14157 * cosq - (IN) COS queue to configure, -1 for all COS queues 14158 * discard - (IN) discard settings 14159 * Returns: 14160 * BCM_E_XXX 14161 */ 14162 int 14163 bcm_mn_cosq_gport_discard_set(int unit, bcm_gport_t gport, 14164 bcm_cos_queue_t cosq, 14165 bcm_cosq_gport_discard_t *discard) 14166 { 14167 uint32 min_thresh, max_thresh, flags = 0; 14168 int cell_size, cell_field_max, local_port; 14169 14170 /*check for valid port */ 14171 if (gport != -1) { 14172 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_localport_resolve(unit, 14173 gport, 14174 &local_port)); 14175 if (IS_CPU_PORT(unit, local_port) || 14176 IS_LB_PORT(unit, local_port) || 14177 IS_MACSEC_PORT(unit, local_port)) { 14178 return BCM_E_PORT; 14179 } 14180 } 14181 /* refresh_time from 1 to 7 be set the same as default 8,so the reasonable 14182 range of refresh_time is from 1 to 512 */ 14183 if (discard == NULL || 14184 discard->gain < 0 || discard->gain > 15 || 14185 discard->drop_probability < 0 || discard->drop_probability > 100 || 14186 discard->refresh_time <= 0 || discard->refresh_time > 512) { 14187 return BCM_E_PARAM; 14188 } 14189 if ((discard->min_thresh < 0) || 14190 (discard->max_thresh < 0) || 14191 (discard->min_thresh > discard->max_thresh)) { 14192 return BCM_E_PARAM; 14193 } 14194 14195 cell_size = _BCM_MN_BYTES_PER_CELL; 14196 cell_field_max = AP_CELL_FIELD_MAX; 14197 14198 min_thresh = discard->min_thresh; 14199 max_thresh = discard->max_thresh; 14200 if (discard->flags & BCM_COSQ_DISCARD_BYTES) { 14201 /* Convert bytes to cells */ 14202 min_thresh += (cell_size - 1); 14203 min_thresh /= cell_size; 14204 14205 max_thresh += (cell_size - 1); 14206 max_thresh /= cell_size; 14207 14208 if ((min_thresh > cell_field_max) || 14209 (max_thresh > cell_field_max)) { 14210 return BCM_E_PARAM; 14211 } 14212 } else { 14213 /* Packet mode not supported */ 14214 return BCM_E_PARAM; 14215 } 14216 14217 /* Min equals Max is an invalid config except 14218 * in case of default (ResetVal) 14219 */ 14220 if ((min_thresh == max_thresh) && 14221 (min_thresh != AP_CELL_FIELD_MAX)) { 14222 return BCM_E_PARAM; 14223 } 14224 14225 14226 BCM_IF_ERROR_RETURN 14227 (_bcm_mn_cosq_wred_set(unit, gport, cosq, discard->flags, 14228 min_thresh, max_thresh, 14229 discard->drop_probability, discard->gain, 14230 FALSE, flags,discard->refresh_time)); 14231 14232 return BCM_E_NONE; 14233 } 14234 14235 /* 14236 * Function: 14237 * bcm_mn_cosq_gport_discard_get 14238 * Purpose: 14239 * Get port WRED setting 14240 * Parameters: 14241 * unit - (IN) unit number 14242 * port - (IN) GPORT identifier 14243 * cosq - (IN) COS queue to get, -1 for any queue 14244 * discard - (OUT) discard settings 14245 * Returns: 14246 * BCM_E_XXX 14247 */ 14248 int 14249 bcm_mn_cosq_gport_discard_get(int unit, bcm_gport_t gport, 14250 bcm_cos_queue_t cosq, 14251 bcm_cosq_gport_discard_t *discard) 14252 { 14253 uint32 min_thresh, max_thresh; 14254 int local_port; 14255 14256 /*check for valid port */ 14257 if (gport != -1) { 14258 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_localport_resolve(unit, 14259 gport, 14260 &local_port)); 14261 if (IS_CPU_PORT(unit, local_port) || 14262 IS_LB_PORT(unit, local_port) || 14263 IS_MACSEC_PORT(unit, local_port)) { 14264 return BCM_E_PORT; 14265 } 14266 } 14267 if (discard == NULL) { 14268 return BCM_E_PARAM; 14269 } 14270 14271 BCM_IF_ERROR_RETURN 14272 (_bcm_mn_cosq_wred_get(unit, gport, cosq == -1 ? 0 : cosq, 14273 &discard->flags, &min_thresh, &max_thresh, 14274 &discard->drop_probability, &discard->gain, 14275 0,&discard->refresh_time)); 14276 14277 /* Convert number of cells to number of bytes */ 14278 discard->min_thresh = min_thresh * _BCM_MN_BYTES_PER_CELL; 14279 discard->max_thresh = max_thresh * _BCM_MN_BYTES_PER_CELL; 14280 14281 return BCM_E_NONE; 14282 } 14283 14284 /* 14285 * Function: 14286 * bcm_mn_cosq_subport_flow_control_set 14287 * Purpose: 14288 * Set a port or node (L0, L1, L2) to flow control when 14289 * a CoE control frame is received on a subtended port. 14290 * Parameters: 14291 * unit - (IN) Unit number. 14292 * subport - (IN) Subtended port 14293 * sched_port - (IN) Node (Port, L0, L1, L2) to flow control 14294 * Returns: 14295 * BCM_E_xxx 14296 * Notes: 14297 */ 14298 int 14299 bcm_mn_cosq_subport_flow_control_set( 14300 int unit, 14301 bcm_gport_t subport, 14302 bcm_gport_t sched_port) 14303 { 14304 #ifdef BCM_HGPROXY_COE_SUPPORT 14305 uint16 coe_fc_index ; 14306 uint32 rval; 14307 bcm_gport_t subport_id, resolved_port; 14308 _bcm_mn_cosq_node_t *node; 14309 int hw_index, rv, logical_hw_index; 14310 soc_monterey_node_lvl_e level; 14311 subport_tag_sgpp_map_entry_t entry; 14312 bcm_port_t phy_port, mmu_port; 14313 soc_info_t *si; 14314 _bcm_mn_fc_type_t fct; 14315 int s1_level = 0; 14316 int index = 0 ; 14317 int cos = 0 ; 14318 14319 /* Find subport id from port to index into SUBPORT_TAG_SGPP_MAP */ 14320 BCM_IF_ERROR_RETURN(_bcmi_coe_subport_tcam_idx_get(unit, subport, &subport_id)); 14321 14322 /* From sched_port, need to find if it's port, L0, L1, or L2 */ 14323 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_node_get(unit, sched_port, 0, NULL, NULL, NULL, &node)); 14324 14325 BCM_IF_ERROR_RETURN 14326 (_bcmi_coe_subport_physical_port_get(unit, subport, &resolved_port)); 14327 /* Port, L0, L1, or L2 from node */ 14328 level = node->level; 14329 14330 /* index into L0, L1, or L2 */ 14331 hw_index = node->hw_index; 14332 14333 /* row and column are used to index in to the FC State Table, which is 4 bits wide */ 14334 14335 /* Get the port associated with the passed in gport */ 14336 if (resolved_port < 0) { 14337 return BCM_E_PORT; 14338 } 14339 14340 si = &SOC_INFO(unit); 14341 /* Getting MMU port. Used to disable cut through for it at the end as well as 14342 to index into MMU_INTFI_PORT_COEFC_TB if we're setting flow control for port */ 14343 phy_port = si->port_l2p_mapping[resolved_port]; 14344 mmu_port = si->port_p2m_mapping[phy_port]; 14345 if (IS_MN_HSP_PORT( unit, resolved_port )) { 14346 /* SC/QM L1/L2 nodes do not support FC. 14347 * Hence, L1/L2 indices 8, 9, 18, 19 ... should not be configured 14348 * for FC. 14349 * similarly the last L0 of the HSP port does not support flow control 14350 */ 14351 if (level == SOC_MONTEREY_NODE_LVL_L0) { 14352 if ((hw_index % 5) > 3) { 14353 return BCM_E_PARAM; 14354 } 14355 cos = hw_index % 5; 14356 } else { 14357 if ((hw_index % 10) > 7) { 14358 return BCM_E_PARAM; 14359 } 14360 cos = ((hw_index % 10) % 4); 14361 } 14362 } else { 14363 cos = hw_index % 4 ; 14364 } 14365 switch(level) { 14366 case SOC_MONTEREY_NODE_LVL_ROOT: 14367 /* At the port level we have to do it a bit different since it's indexing into 14368 MMU_INTFI_PORT_COEFC_TB, which is a 128 entry x 1 bit table with each entry signifying 14369 an MMU Port 14370 */ 14371 index = hw_index; 14372 break; 14373 case SOC_MONTEREY_NODE_LVL_L0: 14374 14375 if (IS_MN_HSP_PORT( unit, resolved_port )) { 14376 /* The last L0 does not support FC and so each index in fc_st_tbl represents 14377 * 5 l0 nodes instead of 4 the last 1 is masked by the hardware 14378 */ 14379 index = hw_index / 5; 14380 break; 14381 } else { 14382 index = hw_index / 4; 14383 } 14384 case SOC_MONTEREY_NODE_LVL_L1: 14385 case SOC_MONTEREY_NODE_LVL_L2: 14386 if (IS_MN_HSP_PORT( unit, resolved_port )) { 14387 /* FC not supported on last two L1/L2 nodes The hardwate internally adjusts the value 14388 * say index 24 which for non hsp port will result in index 6 will result in 5 for HSP 14389 */ 14390 index = mmu_port * 2 + 14391 (((hw_index % 10) >= 4)? 1 : 0); 14392 } else { 14393 index = hw_index / 4; 14394 } 14395 break; 14396 case SOC_MONTEREY_NODE_LVL_S1: 14397 index = hw_index / 4; 14398 break; 14399 default: 14400 return BCM_E_PARAM; 14401 14402 } 14403 if ( level == SOC_MONTEREY_NODE_LVL_S1) 14404 { 14405 s1_level = 1; 14406 14407 } 14408 if (level) { 14409 level--;/* reducing one level for S1*/ 14410 } 14411 /* set coe_fc_index for us to program into the register */ 14412 coe_fc_index = ((s1_level << 15) | (index << 4)| cos << 2 | (level)); 14413 14414 /* Program SUBPORT_TAG_SGPP_MAP with the subport as the index and 14415 COE_FC_INDEX as the data */ 14416 rv = READ_SUBPORT_TAG_SGPP_MAPm(unit, 14417 MEM_BLOCK_ANY, subport_id, &entry); 14418 if (SOC_SUCCESS(rv)) { 14419 soc_SUBPORT_TAG_SGPP_MAPm_field32_set(unit, 14420 (uint32 *)&entry, COE_FC_INDEXf, coe_fc_index); 14421 } 14422 WRITE_SUBPORT_TAG_SGPP_MAPm(unit, MEM_BLOCK_ANY, subport_id, &entry); 14423 14424 /* Program FC Map Table to select FC State Table (vs PFC State Table) for the node */ 14425 fct = _BCM_MN_COSQ_FC_E2ECC; 14426 14427 logical_hw_index = hw_index / 4 ; 14428 14429 /* To pass the proper FC STATE Table entries, we're modifying the FC MAP Table, one of its 14430 4 indexes, with the appropriate row in the FC STATE Table. FC MAP Table at index 0 14431 will handle the rows 0-3 of FC STATE Table, at index 1 will handle rows 4-7 of the 14432 FC STATE Table, and so on. 14433 14434 resolved_port is passed so that the function will know which pipe to use (X or Y). 14435 fct will select FC STATE Table on the mux so that PFC STATE Table won't be selected. 14436 logical_hw_index is passed in this first time so that a proper row index for the FC STATE Table will be selected. 14437 node->hw_index is passed in a second time because the proper FC MAP Table index will be calculated. 14438 node->level is passed in so that the function will know with FC MAP Table (L0, L1, L2) to use. 14439 */ 14440 if(level != SOC_MONTEREY_NODE_LVL_ROOT) { 14441 BCM_IF_ERROR_RETURN(_bcm_mn_map_fc_status_to_node(unit, resolved_port, fct, logical_hw_index, 14442 0 , node->hw_index, node->level)); 14443 } 14444 14445 /* Disable Cut-Through for the port specified or L0/L1/L2 node associated with it */ 14446 BCM_IF_ERROR_RETURN(READ_ASF_PORT_CFGr(unit, resolved_port, &rval)); 14447 soc_reg_field_set(unit, ASF_PORT_CFGr, &rval, UC_ASF_ENABLEf, 0); 14448 soc_reg_field_set(unit, ASF_PORT_CFGr, &rval, MC_ASF_ENABLEf, 0); 14449 BCM_IF_ERROR_RETURN(WRITE_ASF_PORT_CFGr(unit, resolved_port, rval)); 14450 14451 return BCM_E_NONE; 14452 #else 14453 return BCM_E_UNAVAIL; 14454 #endif /* BCM_HGPROXY_COE_SUPPORT */ 14455 } 14456 14457 int 14458 bcm_mn_cosq_subport_flow_control_get( 14459 int unit, 14460 bcm_gport_t subport, 14461 bcm_gport_t * sched_port) 14462 { 14463 #ifdef BCM_HGPROXY_COE_SUPPORT 14464 int level, i; 14465 int hw_index = 0; 14466 uint16 coe_fc_index = 0; 14467 bcm_gport_t subport_id; 14468 _bcm_mn_cosq_node_t * node; 14469 _bcm_mn_mmu_info_t * mmu_info; 14470 subport_tag_sgpp_map_entry_t entry; 14471 int s1_level ; 14472 int index = 0; 14473 int cos = 0 ; 14474 int resolved_port = 0; 14475 int mmu_port = 0; 14476 int phy_port = 0; 14477 soc_info_t *si; 14478 /* Find subport id from port to index into SUBPORT_TAG_SGPP_MAP */ 14479 BCM_IF_ERROR_RETURN(_bcmi_coe_subport_tcam_idx_get(unit, subport, &subport_id)); 14480 14481 14482 BCM_IF_ERROR_RETURN( 14483 _bcmi_coe_subport_physical_port_get(unit, subport, &resolved_port)); 14484 si = &SOC_INFO(unit); 14485 /* Getting MMU port. Used to disable cut through for it at the end as well as 14486 to index into MMU_INTFI_PORT_COEFC_TB if we're setting flow control for port */ 14487 phy_port = si->port_l2p_mapping[resolved_port]; 14488 mmu_port = si->port_p2m_mapping[phy_port]; 14489 BCM_IF_ERROR_RETURN(READ_SUBPORT_TAG_SGPP_MAPm(unit, 14490 MEM_BLOCK_ANY, subport_id, &entry)); 14491 coe_fc_index = soc_SUBPORT_TAG_SGPP_MAPm_field32_get(unit, 14492 (uint32 *)&entry, COE_FC_INDEXf); 14493 14494 14495 level = coe_fc_index & 0x3; 14496 cos = (coe_fc_index >> 2) & 0x3; 14497 index = (coe_fc_index >> 4) & 0x7FF; 14498 s1_level = (coe_fc_index >>15) ; 14499 if((level) || (s1_level)) { 14500 level++;/*This is needed as we decrement while storing*/ 14501 } 14502 switch(level) { 14503 case SOC_MONTEREY_NODE_LVL_ROOT: 14504 /* At the port level we have to do it a bit different since it's indexing into 14505 MMU_INTFI_PORT_COEFC_TB, which is a 128 entry x 1 bit table with each entry signifying 14506 an MMU Port 14507 */ 14508 hw_index = index; 14509 break; 14510 case SOC_MONTEREY_NODE_LVL_L0: 14511 if (IS_MN_HSP_PORT( unit, resolved_port )) { 14512 hw_index = index * 5 + cos ; 14513 } else { 14514 hw_index = index * 4 + cos ; 14515 } 14516 break; 14517 case SOC_MONTEREY_NODE_LVL_L1: 14518 case SOC_MONTEREY_NODE_LVL_L2: 14519 /* FC not supported on last two L1/L2 nodes The hardwate internally adjusts the value 14520 * say index 24 which for non hsp port will result in index 6 will result in 5 for HSP 14521 */ 14522 if (IS_MN_HSP_PORT( unit, resolved_port )) { 14523 hw_index = (mmu_port * 10) + ((index % 2)? 4: 0) + cos ; 14524 } else { 14525 hw_index = index * 4 + cos ; 14526 } 14527 break; 14528 case SOC_MONTEREY_NODE_LVL_S1: 14529 hw_index = index * 4 + cos ; 14530 break; 14531 /* 14532 * COVERITY 14533 * 14534 * This default is unreachable but needed for some compiler. 14535 */ 14536 /* coverity[dead_error_begin] */ 14537 default: 14538 return BCM_E_PARAM; 14539 14540 } 14541 /* calculate the hw_index */ 14542 14543 mmu_info = _bcm_mn_mmu_info[unit]; 14544 14545 if (!mmu_info) { 14546 return BCM_E_INIT; 14547 } 14548 14549 14550 /* Fetch the node based upon level and hw_index */ 14551 switch(level) { 14552 /* port, L0, and L1 are all scheduling nodes */ 14553 case SOC_MONTEREY_NODE_LVL_L0: 14554 case SOC_MONTEREY_NODE_LVL_ROOT: 14555 case SOC_MONTEREY_NODE_LVL_L1: 14556 case SOC_MONTEREY_NODE_LVL_S1: 14557 for(i = 0; i < _BCM_MN_NUM_TOTAL_SCHEDULERS; i++) { 14558 node = &mmu_info->sched_node[i]; 14559 if(node->level == level) { 14560 if(node->hw_index == hw_index) { 14561 *sched_port = node->gport; 14562 return BCM_E_NONE; 14563 } 14564 } 14565 } 14566 break; 14567 case SOC_MONTEREY_NODE_LVL_L2: 14568 for(i = 0; i < _BCM_MN_NUM_L2_UC_LEAVES; i++) { 14569 node = &mmu_info->queue_node[i]; 14570 if(node->level == level) { 14571 if(node->hw_index == hw_index) { 14572 *sched_port = node->gport; 14573 return BCM_E_NONE; 14574 } 14575 } 14576 } 14577 break; 14578 /* Intentional process */ 14579 /* coverity[dead_error_begin] */ 14580 default: 14581 return BCM_E_PARAM; 14582 } 14583 /* not found */ 14584 return BCM_E_PARAM; 14585 #else 14586 return BCM_E_UNAVAIL; 14587 #endif /* BCM_HGPROXY_COE_SUPPORT */ 14588 } 14589 14590 int 14591 _bcm_mn_cosq_port_safc_get(int unit, bcm_port_t port, 14592 int cur_class, 14593 bcm_gport_t *gport, int gport_count, 14594 int *actual_gport_count) 14595 { 14596 _bcm_mn_cosq_node_t *node; 14597 bcm_port_t local_port; 14598 int hw_cosq, count = 0; 14599 uint32 profile_index; 14600 uint64 rval64[16], *rval64s[1], rval, index_map; 14601 uint32 tmp32, bmp; 14602 _bcm_mn_mmu_info_t *mmu_info; 14603 int phy_port, mmu_port; 14604 soc_info_t *si; 14605 soc_reg_t reg; 14606 int mc_index = 0; 14607 int mcq_offset = 0; 14608 _bcm_mn_pipe_resources_t *res; 14609 _bcm_mn_cosq_port_info_t *port_info; 14610 static const soc_reg_t llfc_cfgr[] = { 14611 PORT_PFC_CFG0r, PORT_PFC_CFG1r, PORT_PFC_CFG2r 14612 }; 14613 static const soc_field_t self[] = { 14614 SEL0f, SEL1f, SEL2f, SEL3f 14615 }; 14616 int j, inv_mapped, hw_index, eindex; 14617 soc_mem_t mem; 14618 uint32 map_entry[SOC_MAX_MEM_WORDS]; 14619 14620 14621 if (gport == NULL || gport_count <= 0 || actual_gport_count == NULL) { 14622 return BCM_E_PARAM; 14623 } 14624 14625 BCM_IF_ERROR_RETURN 14626 (_bcm_mn_cosq_localport_resolve(unit, port, &local_port)); 14627 14628 14629 si = &SOC_INFO(unit); 14630 mmu_info = _bcm_mn_mmu_info[unit]; 14631 res = _BCM_MN_PRESOURCES(mmu_info, 0); 14632 phy_port = si->port_l2p_mapping[local_port]; 14633 mmu_port = si->port_p2m_mapping[phy_port]; 14634 port_info = &mmu_info->port_info[local_port]; 14635 14636 rval64s[0] = rval64; 14637 reg = llfc_cfgr[mmu_port/32]; 14638 BCM_IF_ERROR_RETURN(soc_reg64_get(unit, reg, REG_PORT_ANY, 0, &rval)); 14639 14640 index_map = soc_reg64_field_get(unit, reg, rval, PROFILE_INDEXf); 14641 COMPILER_64_SHR(index_map, ((mmu_port % 32) * 2)); 14642 COMPILER_64_TO_32_LO(tmp32, index_map); 14643 profile_index = (tmp32 & 3)*16; 14644 14645 BCM_IF_ERROR_RETURN 14646 (soc_profile_reg_get(unit, _bcm_mn_llfc_profile[unit], 14647 profile_index, 16, rval64s)); 14648 14649 bmp = soc_reg64_field32_get(unit, PRIO2COS_PROFILEr, rval64[cur_class], 14650 COS_BMPf); 14651 for (hw_cosq = 0; hw_cosq < _BCM_MN_NUM_SAFC_CLASS ; hw_cosq++) { 14652 if (!(bmp & (1 << hw_cosq))) { 14653 continue; 14654 } 14655 if (_bcm_mn_cosq_port_has_ets(unit, local_port)) { 14656 inv_mapped = 0; 14657 for (j = _BCM_MN_NUM_PORT_SCHEDULERS; 14658 j < _BCM_MN_NUM_TOTAL_SCHEDULERS; j++) { 14659 node = &mmu_info->sched_node[j]; 14660 if ((!node->in_use) || (node->local_port != local_port) || 14661 (node->hw_cosq != hw_cosq)) { 14662 continue; 14663 } 14664 14665 hw_index = (node->hw_index / 16); 14666 eindex = (node->hw_index % 16)/4; 14667 if (node->level == SOC_MONTEREY_NODE_LVL_L0) { 14668 mem = MMU_INTFI_XPIPE_FC_MAP_TBL0m; 14669 } else if (node->level == SOC_MONTEREY_NODE_LVL_L1) { 14670 mem = MMU_INTFI_XPIPE_FC_MAP_TBL1m; 14671 } else { 14672 continue; 14673 } 14674 14675 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, 14676 MEM_BLOCK_ALL, hw_index, &map_entry)); 14677 /* coverity[overrun-local : FALSE] */ 14678 if (soc_mem_field32_get(unit, mem, &map_entry, self[eindex])) { 14679 if (gport_count > 0) { 14680 gport[count] = node->gport; 14681 } 14682 count++; 14683 if ((count == gport_count) && (gport_count > 0)) { 14684 inv_mapped = 1; 14685 break; 14686 } 14687 } 14688 } 14689 14690 for (j = port_info->uc_base; 14691 inv_mapped==0 && (j < port_info->uc_limit); j++) { 14692 node = &res->p_queue_node[j]; 14693 if ((!node->in_use) || (node->local_port != local_port)) { 14694 continue; 14695 } 14696 if (node->hw_cosq != hw_cosq) { 14697 continue; 14698 } 14699 mem = MMU_INTFI_XPIPE_FC_MAP_TBL2m ; 14700 hw_index = (node->hw_index / 16); 14701 eindex = (node->hw_index % 16)/4; 14702 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, 14703 MEM_BLOCK_ALL, hw_index, &map_entry)); 14704 14705 /* coverity[overrun-local : FALSE] */ 14706 if (soc_mem_field32_get(unit, mem, &map_entry, self[eindex])) { 14707 if (gport_count > 0) { 14708 gport[count] = node->gport; 14709 } 14710 count++; 14711 if ((count == gport_count) && (gport_count > 0)) { 14712 inv_mapped = 1; 14713 break; 14714 } 14715 } 14716 } 14717 for (j = port_info->mc_base; 14718 inv_mapped==0 && (j < port_info->mc_limit); j++) { 14719 mc_index = soc_monterey_l2_hw_index(unit, j, 0); 14720 node = &res->p_queue_node[mc_index]; 14721 if ((!node->in_use) || (node->local_port != local_port)) { 14722 continue; 14723 } 14724 if (node->hw_cosq != hw_cosq) { 14725 continue; 14726 } 14727 mem = MMU_INTFI_XPIPE_FC_MAP_TBL2m ; 14728 mcq_offset = node->hw_index % _BCM_MN_NUM_L2_UC_LEAVES_PER_PIPE; 14729 if (((mcq_offset % 10) > 7) ) { 14730 /* FC support only for Q0-7 */ 14731 continue; 14732 } 14733 hw_index = node->hw_index - (mcq_offset * 2 / 10); 14734 hw_index /= 16; 14735 eindex = (mcq_offset % 10)/4; 14736 eindex += ((mcq_offset /10) % 2) ? 0 : 2; 14737 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, 14738 MEM_BLOCK_ALL, hw_index, &map_entry)); 14739 14740 /* coverity[overrun-local : FALSE] */ 14741 if (soc_mem_field32_get(unit, mem, &map_entry, self[eindex])) { 14742 if (gport_count > 0) { 14743 gport[count] = node->gport; 14744 } 14745 count++; 14746 if ((count == gport_count) && (gport_count > 0)) { 14747 break; 14748 } 14749 } 14750 } 14751 } else { 14752 if (gport_count > 0) { 14753 gport[count++] = hw_cosq; 14754 } 14755 } 14756 if (count == gport_count) { 14757 break; 14758 } 14759 } 14760 14761 if (count == 0) { 14762 return BCM_E_NOT_FOUND; 14763 } 14764 *actual_gport_count = count; 14765 return BCM_E_NONE; 14766 } 14767 14768 14769 /* 14770 * Function: 14771 * bcm_mn_cosq_safc_class_mapping_set 14772 * Purpose: 14773 * Set SAFC mapping for port. 14774 * SAFC class is mapped to cosq or scheduler node gports. 14775 * Parameters: 14776 * unit - (IN) unit number 14777 * port - (IN) port number 14778 * array_count - (IN) count of mapping 14779 * mapping_array - (IN) mappings 14780 * Returns: 14781 * BCM_E_XXX 14782 */ 14783 int 14784 _bcm_mn_cosq_safc_class_mapping_set(int unit, bcm_gport_t port, 14785 int array_count, 14786 bcm_cosq_safc_class_mapping_t *mapping_array) 14787 { 14788 int index, count; 14789 int cur_class = 0; 14790 int safc_class[_BCM_MN_NUM_SAFC_CLASS]; 14791 bcm_gport_t cur_gport = 0; 14792 uint32 cos_bmp[_BCM_MN_NUM_SAFC_CLASS] = {0}; 14793 bcm_port_t local_port = -1; 14794 14795 BCM_IF_ERROR_RETURN 14796 (_bcm_mn_cosq_localport_resolve(unit, port, &local_port)); 14797 14798 if (local_port < 0) { 14799 return BCM_E_PORT; 14800 } 14801 14802 if (IS_CPU_PORT(unit, local_port)) { 14803 return BCM_E_PARAM; 14804 } 14805 14806 if ((array_count < 0) || (array_count > _BCM_MN_NUM_SAFC_CLASS)) { 14807 return BCM_E_PARAM; 14808 } 14809 14810 if (mapping_array == NULL) { 14811 return BCM_E_PARAM; 14812 } 14813 if (!IS_HG_PORT(unit, local_port)) { 14814 return BCM_E_PARAM; 14815 } 14816 14817 for (count = 0; count < array_count; count++) { 14818 cur_class = mapping_array[count].class_id; 14819 if ((cur_class < 0) || (cur_class >= _BCM_MN_NUM_SAFC_CLASS)) { 14820 return BCM_E_PARAM; 14821 } else { 14822 cos_bmp[cur_class] = 0; 14823 } 14824 14825 for (index = 0; index < BCM_COSQ_SAFC_GPORT_COUNT; index++) { 14826 cur_gport = mapping_array[count].gport_list[index]; 14827 if (cur_gport == BCM_GPORT_INVALID) { 14828 break; 14829 } 14830 14831 if ((BCM_GPORT_IS_UCAST_QUEUE_GROUP(cur_gport)) || 14832 (BCM_GPORT_IS_MCAST_QUEUE_GROUP(cur_gport))) { 14833 BCM_IF_ERROR_RETURN 14834 (_bcm_mn_fc_status_map_gport(unit, local_port, cur_gport, 14835 _BCM_MN_COSQ_FC_SAFC, 14836 &cos_bmp[cur_class])); 14837 } else { 14838 return BCM_E_PARAM; 14839 } 14840 } 14841 } 14842 14843 for (index = 0; index < _BCM_MN_NUM_SAFC_CLASS; index++) { 14844 safc_class[index] = index; 14845 } 14846 BCM_IF_ERROR_RETURN(_bcm_mn_port_fc_profile_set(unit, local_port, 14847 _BCM_COSQ_OP_SET, _BCM_MN_NUM_SAFC_CLASS, safc_class, cos_bmp)); 14848 14849 return BCM_E_NONE; 14850 } 14851 14852 /* 14853 * Function: 14854 * bcm_mn_cosq_safc_class_mapping_get 14855 * Purpose: 14856 * Get SAFC mapping for port. 14857 * Retrieves cosq or scheduler node gports 14858 * associated to SAFC classes. 14859 * Parameters: 14860 * unit - (IN) unit number 14861 * port - (IN) port number 14862 * array_max - (IN) max retrieve count 14863 * mapping_array - (OUT) mappings 14864 * array_count - (OUT) retrieved mapping count 14865 * Returns: 14866 * BCM_E_XXX 14867 */ 14868 int 14869 _bcm_mn_cosq_safc_class_mapping_get(int unit, bcm_gport_t port, 14870 int array_max, 14871 bcm_cosq_safc_class_mapping_t *mapping_array, 14872 int *array_count) 14873 { 14874 int rv = 0; 14875 int cur_class = 0; 14876 int actual_gport_count, class_count = 0; 14877 bcm_port_t local_port = -1; 14878 14879 BCM_IF_ERROR_RETURN 14880 (_bcm_mn_cosq_localport_resolve(unit, port, &local_port)); 14881 14882 if (local_port < 0) { 14883 return BCM_E_PORT; 14884 } 14885 14886 if (IS_CPU_PORT(unit, local_port)) { 14887 return BCM_E_PARAM; 14888 } 14889 if (!IS_HG_PORT(unit, local_port)) { 14890 return BCM_E_PARAM; 14891 } 14892 14893 if (((mapping_array == NULL) && (array_max > 0)) || 14894 ((mapping_array != NULL) && (array_max <= 0)) || 14895 (array_count == NULL)) { 14896 return BCM_E_PARAM; 14897 } 14898 14899 if (array_max <= 0) { 14900 *array_count = _BCM_MN_NUM_SAFC_CLASS; 14901 return BCM_E_NONE; 14902 } 14903 14904 for (cur_class = 0; cur_class < _BCM_MN_NUM_SAFC_CLASS; cur_class++) { 14905 actual_gport_count = 0; 14906 rv = _bcm_mn_cosq_port_safc_get(unit, port, cur_class, 14907 mapping_array[cur_class].gport_list, 14908 BCM_COSQ_SAFC_GPORT_COUNT, &actual_gport_count); 14909 14910 if (rv == BCM_E_NONE) { 14911 mapping_array[cur_class].class_id = cur_class; 14912 if (actual_gport_count < BCM_COSQ_SAFC_GPORT_COUNT) { 14913 mapping_array[cur_class].gport_list[actual_gport_count] = 14914 BCM_GPORT_INVALID; 14915 } 14916 class_count++; 14917 } else if (rv == BCM_E_NOT_FOUND) { 14918 return rv; 14919 } 14920 14921 if (class_count == array_max) { 14922 break; 14923 } 14924 } 14925 14926 *array_count = class_count; 14927 if (class_count == 0) { 14928 return BCM_E_NOT_FOUND; 14929 } 14930 14931 return BCM_E_NONE; 14932 } 14933 14934 int 14935 _bcm_mn_cosq_pfc_class_resolve(bcm_switch_control_t sctype, int *type, 14936 int *class) 14937 { 14938 switch (sctype) { 14939 case bcmSwitchPFCClass7Queue: 14940 case bcmSwitchPFCClass6Queue: 14941 case bcmSwitchPFCClass5Queue: 14942 case bcmSwitchPFCClass4Queue: 14943 case bcmSwitchPFCClass3Queue: 14944 case bcmSwitchPFCClass2Queue: 14945 case bcmSwitchPFCClass1Queue: 14946 case bcmSwitchPFCClass0Queue: 14947 *type = _BCM_MN_COSQ_TYPE_UCAST; 14948 break; 14949 case bcmSwitchPFCClass7McastQueue: 14950 case bcmSwitchPFCClass6McastQueue: 14951 case bcmSwitchPFCClass5McastQueue: 14952 case bcmSwitchPFCClass4McastQueue: 14953 case bcmSwitchPFCClass3McastQueue: 14954 case bcmSwitchPFCClass2McastQueue: 14955 case bcmSwitchPFCClass1McastQueue: 14956 case bcmSwitchPFCClass0McastQueue: 14957 *type = _BCM_MN_COSQ_TYPE_MCAST; 14958 break; 14959 case bcmSwitchPFCClass7DestmodQueue: 14960 case bcmSwitchPFCClass6DestmodQueue: 14961 case bcmSwitchPFCClass5DestmodQueue: 14962 case bcmSwitchPFCClass4DestmodQueue: 14963 case bcmSwitchPFCClass3DestmodQueue: 14964 case bcmSwitchPFCClass2DestmodQueue: 14965 case bcmSwitchPFCClass1DestmodQueue: 14966 case bcmSwitchPFCClass0DestmodQueue: 14967 *type = _BCM_MN_COSQ_TYPE_EXT_UCAST; 14968 break; 14969 default: 14970 return BCM_E_PARAM; 14971 } 14972 14973 switch (sctype) { 14974 case bcmSwitchPFCClass7Queue: 14975 case bcmSwitchPFCClass7McastQueue: 14976 case bcmSwitchPFCClass7DestmodQueue: 14977 *class = 7; 14978 break; 14979 case bcmSwitchPFCClass6Queue: 14980 case bcmSwitchPFCClass6McastQueue: 14981 case bcmSwitchPFCClass6DestmodQueue: 14982 *class = 6; 14983 break; 14984 case bcmSwitchPFCClass5Queue: 14985 case bcmSwitchPFCClass5McastQueue: 14986 case bcmSwitchPFCClass5DestmodQueue: 14987 *class = 5; 14988 break; 14989 case bcmSwitchPFCClass4Queue: 14990 case bcmSwitchPFCClass4McastQueue: 14991 case bcmSwitchPFCClass4DestmodQueue: 14992 *class = 4; 14993 break; 14994 case bcmSwitchPFCClass3Queue: 14995 case bcmSwitchPFCClass3McastQueue: 14996 case bcmSwitchPFCClass3DestmodQueue: 14997 *class = 3; 14998 break; 14999 case bcmSwitchPFCClass2Queue: 15000 case bcmSwitchPFCClass2McastQueue: 15001 case bcmSwitchPFCClass2DestmodQueue: 15002 *class = 2; 15003 break; 15004 case bcmSwitchPFCClass1Queue: 15005 case bcmSwitchPFCClass1McastQueue: 15006 case bcmSwitchPFCClass1DestmodQueue: 15007 *class = 1; 15008 break; 15009 case bcmSwitchPFCClass0Queue: 15010 case bcmSwitchPFCClass0McastQueue: 15011 case bcmSwitchPFCClass0DestmodQueue: 15012 *class = 0; 15013 break; 15014 /* 15015 * COVERITY 15016 * 15017 * This default is unreachable but needed for some compiler. 15018 */ 15019 /* coverity[dead_error_begin] */ 15020 default: 15021 return BCM_E_INTERNAL; 15022 } 15023 return BCM_E_NONE; 15024 } 15025 15026 STATIC int 15027 _bcm_mn_clear_fc_status_to_node(int unit, int port) 15028 { 15029 uint32 map_entry[SOC_MAX_MEM_WORDS]; 15030 static const soc_field_t self[]={ 15031 SEL0f, SEL1f, SEL2f, SEL3f 15032 }; 15033 static const soc_field_t indexf[] = { 15034 INDEX0f, INDEX1f, INDEX2f, INDEX3f 15035 }; 15036 static const soc_mem_t memx[] = { 15037 MMU_INTFI_XPIPE_FC_MAP_TBS1m, 15038 MMU_INTFI_XPIPE_FC_MAP_TBL0m, 15039 MMU_INTFI_XPIPE_FC_MAP_TBL1m, 15040 MMU_INTFI_XPIPE_FC_MAP_TBL2m 15041 }; 15042 uint32 s_value, i_value; 15043 int base, table, index, count, field; 15044 int mmu_port, phy_port, update; 15045 15046 soc_info_t *soc_info; 15047 soc_info = &SOC_INFO(unit); 15048 15049 phy_port = soc_info->port_l2p_mapping[port]; 15050 mmu_port = soc_info->port_p2m_mapping[phy_port]; 15051 base = mmu_port * 4; 15052 for (table = 0; table < COUNTOF(memx); table++){ 15053 count = soc_mem_index_count(unit, memx[table]); 15054 for (index = 0; index < count; index++){ 15055 update = 0; 15056 SOC_IF_ERROR_RETURN(soc_mem_read(unit, memx[table], 15057 MEM_BLOCK_ALL, index, &map_entry)); 15058 for (field = 0; field < COUNTOF(indexf); field++){ 15059 s_value = soc_mem_field32_get(unit, memx[table], 15060 &map_entry, self[field]); 15061 i_value = soc_mem_field32_get(unit, memx[table], 15062 &map_entry, indexf[field]); 15063 15064 if (s_value && (i_value >= base) && (i_value < (base + 4))) { 15065 soc_mem_field32_set(unit, memx[table], 15066 &map_entry, self[field], 0); 15067 soc_mem_field32_set(unit, memx[table], 15068 &map_entry, indexf[field], 0); 15069 update = 1; 15070 } 15071 } 15072 if (update){ 15073 SOC_IF_ERROR_RETURN(soc_mem_write(unit, memx[table], 15074 MEM_BLOCK_ALL, index, &map_entry)); 15075 } 15076 } 15077 } 15078 return BCM_E_NONE; 15079 } 15080 15081 15082 STATIC int 15083 _bcm_mn_map_fc_status_to_node(int unit, int port, _bcm_mn_fc_type_t fct, 15084 int spad_offset, int cosq, uint32 hw_index, int level) 15085 { 15086 int map_entry_index, eindex, pfc; 15087 uint32 map_entry[SOC_MAX_MEM_WORDS]; 15088 static const soc_field_t self[] = { 15089 SEL0f, SEL1f, SEL2f, SEL3f 15090 }; 15091 static const soc_field_t indexf[] = { 15092 INDEX0f, INDEX1f, INDEX2f, INDEX3f 15093 }; 15094 static const soc_mem_t memx[] = { 15095 INVALIDm, 15096 MMU_INTFI_XPIPE_FC_MAP_TBS1m, 15097 MMU_INTFI_XPIPE_FC_MAP_TBL0m, 15098 MMU_INTFI_XPIPE_FC_MAP_TBL1m, 15099 MMU_INTFI_XPIPE_FC_MAP_TBL2m 15100 }; 15101 soc_mem_t mem; 15102 int port_num = 0; 15103 int map_entry_index_num = 0; 15104 15105 if ((fct == _BCM_MN_COSQ_FC_PFC) || 15106 (fct == _BCM_MN_COSQ_FC_SAFC)) { 15107 pfc = 1; 15108 } else { 15109 pfc = 0; 15110 } 15111 mem = memx[level]; 15112 if (mem == INVALIDm) { 15113 return BCM_E_PARAM; 15114 } 15115 15116 /* FC_MAP_TBL[Level] has 4 Index[0-3], whose values become Index to PFC_ST_TBL. 15117 * Each Index of PFC_ST_TBL can point to congestion state of 4 Qs. 15118 * Hence each Entry of FC_MAP_TBL can refer to 16 Qs. 15119 * 15120 * NOTE: Index of FC_MAP_TBL CANNOT be used to point to Qs/Nodes belonging 15121 * to Different Ports. 15122 */ 15123 if (hw_index < _BCM_MN_NUM_L2_UC_LEAVES_PER_PIPE ) { 15124 /* UC queue */ 15125 if (IS_MN_HSP_PORT( unit, port )) { 15126 if (level == SOC_MONTEREY_NODE_LVL_L0) { 15127 /* SC/QM L0 nodes do not support FC. 15128 * Hence, L0 indices 4, 9, 14, 19 ... should not be configured 15129 * for FC. 15130 */ 15131 if ((hw_index % 5) > 3) { 15132 return BCM_E_PARAM; 15133 } 15134 /* Since 5th L0 index is not FC mapped, each Entry of 15135 * FC_MAP_TBL can refer to 20 L0 nodes with each field mapped 15136 * to first 4 L0 of each port. 15137 */ 15138 map_entry_index = hw_index / 20; 15139 eindex = (hw_index % 20) / 5; 15140 } else { 15141 /* SC/QM L1/L2 nodes do not support FC. 15142 * Hence, L1/L2 indices 8, 9, 18, 19 ... should not be configured 15143 * for FC. 15144 */ 15145 if ((hw_index % 10) > 7) { 15146 return BCM_E_PARAM; 15147 } 15148 /* A 2 bit shift occurs in HW for HSP ports to align with multiple of 8. 15149 * Thus 10-17 becomes 8-15, etc. 15150 */ 15151 port_num = hw_index / 10; 15152 map_entry_index_num = port_num * 2 + (((hw_index % 10) >= 4)? 1 : 0); 15153 map_entry_index = map_entry_index_num / 4; /* each entry contains 4 indexes */ 15154 eindex = map_entry_index_num & 0x3; 15155 } 15156 } else { 15157 map_entry_index = hw_index/16; 15158 eindex = (hw_index % 16) / 4; 15159 } 15160 } else { 15161 /* MC queue - Index Calculation 15162 * PFC can work only on 8 out of 10 MC queues of each port. 15163 * So in FC_MAP_TBL2, each Port will use only 2 Index(4 Qs each) for 15164 * MC Qs. 15165 * MC queue base starts at 16384, 16384/16 = 1024 15166 * Hence MC Qs starts at = Map_Tbl2_Idx[92] and Index2. 15167 */ 15168 int mcq_offset = hw_index % _BCM_MN_NUM_L2_UC_LEAVES_PER_PIPE; 15169 15170 if (((mcq_offset % 10) > 7) || (level != SOC_MONTEREY_NODE_LVL_L2)) { 15171 /* FC support only for Q0-7 */ 15172 return BCM_E_INTERNAL; 15173 } 15174 map_entry_index = hw_index - (mcq_offset * 2 / 10); 15175 map_entry_index /= 16; 15176 eindex = (mcq_offset % 10)/4; 15177 eindex += ((mcq_offset /10) % 2) ? 0 : 2; 15178 15179 } 15180 BCM_IF_ERROR_RETURN 15181 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, map_entry_index, &map_entry)); 15182 /* coverity[overrun-local : FALSE] */ 15183 soc_mem_field32_set(unit, mem, &map_entry, 15184 indexf[eindex], spad_offset + cosq/4); 15185 /* coverity[overrun-local : FALSE] */ 15186 soc_mem_field32_set(unit, mem, &map_entry, self[eindex], !!pfc); 15187 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, 15188 MEM_BLOCK_ALL, map_entry_index, &map_entry)); 15189 return BCM_E_NONE; 15190 } 15191 15192 15193 /* 15194 * Function: 15195 * _bcm_mn_fc_status_map_gport 15196 * Purpose: 15197 * Set mapping in FC_MAP_TBL for gport, and update cos_bmp with gport cosq. 15198 * Parameters: 15199 * unit - (IN) unit number 15200 * port - (IN) port number 15201 * gport - (IN) gport to be mapped 15202 * fct - (IN) FC type 15203 * cos_map - (OUT) hw_cosq of gport 15204 * Returns: 15205 * BCM_E_XXX 15206 */ 15207 STATIC int 15208 _bcm_mn_fc_status_map_gport(int unit, int port, 15209 bcm_gport_t gport, _bcm_mn_fc_type_t fct, uint32 *cos_bmp) 15210 { 15211 int hw_index, hw_index1; 15212 int hw_cosq, hw_cosq1; 15213 int id, lvl; 15214 int pipe, mmu_port, phy_port; 15215 bcm_port_t local_port, resolved_port; 15216 _bcm_mn_cosq_node_t *node; 15217 _bcm_mn_pipe_resources_t *res; 15218 _bcm_mn_cosq_port_info_t *port_info; 15219 soc_info_t *si; 15220 _bcm_mn_mmu_info_t *mmu_info; 15221 15222 BCM_IF_ERROR_RETURN 15223 (_bcm_mn_cosq_localport_resolve(unit, port, &local_port)); 15224 15225 si = &SOC_INFO(unit); 15226 phy_port = si->port_l2p_mapping[local_port]; 15227 mmu_port = si->port_p2m_mapping[phy_port]; 15228 15229 mmu_info = _bcm_mn_mmu_info[unit]; 15230 port_info = &mmu_info->port_info[local_port]; 15231 pipe = _BCM_MN_PORT_TO_PIPE(unit, local_port); 15232 res = _BCM_MN_PRESOURCES(mmu_info, pipe); 15233 15234 hw_index = hw_index1 = -1; 15235 hw_cosq = hw_cosq1 = -1; 15236 if (BCM_GPORT_IS_SET(gport)) { 15237 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_node_get(unit, gport, 15238 0, NULL, &resolved_port, &id, &node)); 15239 hw_index = node->hw_index; 15240 hw_cosq = node->hw_cosq; 15241 lvl = node->level; 15242 } else { 15243 if (_bcm_mn_cosq_port_has_ets(unit, local_port)) { 15244 hw_cosq = gport; 15245 node = &res->p_queue_node[port_info->uc_base + hw_cosq]; 15246 hw_index = node->hw_index; 15247 node = &res->p_mc_queue_node[port_info->mc_base + hw_cosq]; 15248 hw_index1 = node->hw_index; 15249 hw_cosq1 = hw_cosq; 15250 lvl = SOC_MONTEREY_NODE_LVL_L2; 15251 } else { 15252 lvl = SOC_MONTEREY_NODE_LVL_L1; 15253 /* gport[] represnts the physical Cos value */ 15254 hw_cosq = gport; 15255 BCM_IF_ERROR_RETURN(soc_monterey_sched_hw_index_get(unit, local_port, 15256 SOC_MONTEREY_NODE_LVL_L1, hw_cosq, &hw_index)); 15257 } 15258 } 15259 BCM_IF_ERROR_RETURN( 15260 _bcm_mn_map_fc_status_to_node(unit, local_port, fct, 15261 mmu_port*4, hw_cosq, hw_index, lvl)); 15262 if (cos_bmp != NULL) { 15263 *cos_bmp |= 1 << hw_cosq; 15264 } 15265 if (hw_cosq1 >= 0) { 15266 BCM_IF_ERROR_RETURN( 15267 _bcm_mn_map_fc_status_to_node(unit, local_port, fct, 15268 mmu_port*4, hw_cosq1, hw_index1, lvl)); 15269 if (cos_bmp != NULL) { 15270 *cos_bmp |= 1 << hw_cosq1; 15271 } 15272 } 15273 15274 return BCM_E_NONE; 15275 } 15276 15277 15278 /* 15279 * Function: 15280 * _bcm_mn_port_fc_profile_set 15281 * Purpose: 15282 * Set PFC mapping profile for port. Updates PRIO2COS_PROFILE & PORT_PFC_CFG. 15283 * Parameters: 15284 * unit - (IN) unit number 15285 * port - (IN) port number 15286 * op - (IN) operation type 15287 * entry_cnt - (IN) count of bmp 15288 * pfc_class - (IN) class list 15289 * cos_bmp - (IN) bmp list 15290 * Returns: 15291 * BCM_E_XXX 15292 */ 15293 STATIC int 15294 _bcm_mn_port_fc_profile_set(int unit, int port, _bcm_cosq_op_t op, 15295 int entry_cnt, int *pfc_class, uint32 *cos_bmp) 15296 { 15297 soc_reg_t reg; 15298 bcm_port_t local_port; 15299 int rv, entry, cur_class; 15300 int mmu_port, phy_port; 15301 uint32 profile_index, old_profile_index; 15302 uint32 fval, tmp32, cur_bmp; 15303 uint64 rval64[16], tmp, *rval64s[1], rval, index_map; 15304 soc_info_t *si; 15305 static const soc_reg_t llfc_cfgr[] = { 15306 PORT_PFC_CFG0r, PORT_PFC_CFG1r, PORT_PFC_CFG2r 15307 }; 15308 15309 if (pfc_class == NULL) { 15310 return BCM_E_PARAM; 15311 } 15312 if (cos_bmp == NULL) { 15313 return BCM_E_PARAM; 15314 } 15315 if ((entry_cnt < 0 ) || (entry_cnt > _BCM_MN_NUM_SAFC_CLASS)) { 15316 return BCM_E_PARAM; 15317 } 15318 15319 BCM_IF_ERROR_RETURN( 15320 _bcm_mn_cosq_localport_resolve(unit, port, &local_port)); 15321 15322 si = &SOC_INFO(unit); 15323 phy_port = si->port_l2p_mapping[local_port]; 15324 mmu_port = si->port_p2m_mapping[phy_port]; 15325 15326 reg = llfc_cfgr[mmu_port/32]; 15327 rval64s[0] = rval64; 15328 BCM_IF_ERROR_RETURN(soc_reg64_get(unit, reg, 0, 0, &rval)); 15329 15330 index_map = soc_reg64_field_get(unit, reg, rval, PROFILE_INDEXf); 15331 COMPILER_64_SHR(index_map, ((mmu_port % 32) * 2)); 15332 COMPILER_64_TO_32_LO(tmp32, index_map); 15333 old_profile_index = (tmp32 & 3)*16; 15334 BCM_IF_ERROR_RETURN 15335 (soc_profile_reg_get(unit, _bcm_mn_llfc_profile[unit], 15336 old_profile_index, 16, rval64s)); 15337 15338 for (entry = 0; entry < entry_cnt; entry++) { 15339 cur_class = pfc_class[entry]; 15340 cur_bmp = cos_bmp[entry]; 15341 if (op == _BCM_COSQ_OP_SET) { 15342 soc_reg64_field32_set(unit, PRIO2COS_PROFILEr, &rval64[cur_class], 15343 COS_BMPf, cur_bmp); 15344 } else { 15345 if (cur_bmp != 0) { 15346 fval = soc_reg64_field32_get(unit, PRIO2COS_PROFILEr, 15347 rval64[cur_class], COS_BMPf); 15348 if (op == _BCM_COSQ_OP_ADD) { 15349 fval |= cur_bmp; 15350 } else { /* _BCM_COSQ_OP_DELETE */ 15351 fval &= ~cur_bmp; 15352 } 15353 soc_reg64_field32_set(unit, PRIO2COS_PROFILEr, 15354 &rval64[cur_class], COS_BMPf, fval); 15355 } 15356 } 15357 } 15358 15359 BCM_IF_ERROR_RETURN 15360 (soc_profile_reg_delete(unit, _bcm_mn_llfc_profile[unit], 15361 old_profile_index)); 15362 15363 rv = soc_profile_reg_add(unit, _bcm_mn_llfc_profile[unit], rval64s, 15364 16, &profile_index); 15365 if (SOC_FAILURE(rv)) { 15366 BCM_IF_ERROR_RETURN 15367 (soc_profile_reg_reference(unit, _bcm_mn_llfc_profile[unit], 15368 old_profile_index, 16)); 15369 return rv; 15370 } 15371 15372 15373 index_map = soc_reg64_field_get(unit, reg, rval, PROFILE_INDEXf); 15374 15375 COMPILER_64_SET(tmp, 0, 3); 15376 COMPILER_64_SHL(tmp, (mmu_port % 32) * 2); 15377 COMPILER_64_NOT(tmp); 15378 COMPILER_64_AND(index_map, tmp); 15379 COMPILER_64_SET(tmp, 0, profile_index/16); 15380 COMPILER_64_SHL(tmp, (mmu_port % 32) * 2); 15381 COMPILER_64_OR(index_map, tmp); 15382 15383 soc_reg64_field_set(unit, reg, &rval, PROFILE_INDEXf, 15384 index_map); 15385 15386 BCM_IF_ERROR_RETURN(soc_reg64_set(unit, reg, 0, 0, rval)); 15387 return BCM_E_NONE; 15388 } 15389 /* 15390 * Function: 15391 * _bcm_mn_fc_map_gport_check 15392 * Purpose: 15393 * Validate if a gport can be mapped to a port's PFC/FC status. 15394 * Parameters: 15395 * unit - (IN) unit number 15396 * port - (IN) port number 15397 * gport - (IN) gport that will be mapped 15398 * Returns: 15399 * BCM_E_XXX 15400 */ 15401 STATIC int 15402 _bcm_mn_fc_map_gport_check(int unit, 15403 bcm_gport_t port, 15404 bcm_gport_t gport) 15405 { 15406 bcm_port_t local_port = -1, resolved_port; 15407 int hw_cosq, pipe; 15408 _bcm_mn_pipe_resources_t *res; 15409 _bcm_mn_cosq_port_info_t *port_info; 15410 _bcm_mn_mmu_info_t *mmu_info; 15411 _bcm_mn_cosq_node_t *node; 15412 15413 BCM_IF_ERROR_RETURN 15414 (_bcm_mn_cosq_localport_resolve(unit, port, &local_port)); 15415 15416 if (local_port < 0) { 15417 return BCM_E_PORT; 15418 } 15419 15420 mmu_info = _bcm_mn_mmu_info[unit]; 15421 port_info = &mmu_info->port_info[local_port]; 15422 pipe = _BCM_MN_PORT_TO_PIPE(unit, local_port); 15423 res = _BCM_MN_PRESOURCES(mmu_info, pipe); 15424 15425 hw_cosq = -1; 15426 if (BCM_GPORT_IS_SET(gport)) { 15427 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_node_get(unit, gport, 15428 0, NULL, &resolved_port, NULL, &node)); 15429 if (!((node->type == _BCM_MN_NODE_UCAST) || 15430 (node->type == _BCM_MN_NODE_MCAST) || 15431 (node->type == _BCM_MN_NODE_SCHEDULER))) { 15432 return BCM_E_PARAM; 15433 } 15434 if (resolved_port != local_port) { 15435 return BCM_E_PARAM; 15436 } 15437 hw_cosq = node->hw_cosq; 15438 } else { 15439 hw_cosq = gport; 15440 if (_bcm_mn_cosq_port_has_ets(unit, local_port)) { 15441 node = &res->p_queue_node[port_info->uc_base + hw_cosq]; 15442 if ((!node->in_use) || (node->attached_to_input == -1)) { 15443 return BCM_E_PARAM; 15444 } 15445 node = &res->p_mc_queue_node[port_info->mc_base + hw_cosq]; 15446 if ((!node->in_use) || (node->attached_to_input == -1)) { 15447 return BCM_E_PARAM; 15448 } 15449 } 15450 } 15451 if ((hw_cosq < 0) || (hw_cosq >= _MN_NUM_INTERNAL_PRI)) { 15452 return BCM_E_PARAM; 15453 } 15454 15455 return BCM_E_NONE; 15456 } 15457 15458 /* 15459 * Function: 15460 * _bcm_mn_pfc_class_mapping_check 15461 * Purpose: 15462 * Validate param of bcm_cosq_pfc_class_mapping_t. 15463 * Parameters: 15464 * unit - (IN) unit number 15465 * port - (IN) port number 15466 * array_count - (IN) count of mapping array 15467 * mapping_array - (IN) mapping array list 15468 * Returns: 15469 * BCM_E_XXX 15470 */ 15471 STATIC int 15472 _bcm_mn_pfc_class_mapping_check(int unit, 15473 bcm_gport_t port, 15474 int array_count, 15475 bcm_cosq_pfc_class_mapping_t *mapping_array) 15476 { 15477 int count, index, cur_class; 15478 bcm_gport_t cur_gport = 0; 15479 15480 if (mapping_array == NULL) { 15481 return BCM_E_PARAM; 15482 } 15483 15484 for (count = 0; count < array_count; count++) { 15485 cur_class = mapping_array[count].class_id; 15486 if ((cur_class < 0) || (cur_class >= _BCM_MN_NUM_PFC_CLASS)) { 15487 return BCM_E_PARAM; 15488 } 15489 15490 for (index = 0; index < BCM_COSQ_PFC_GPORT_COUNT; index++) { 15491 cur_gport = mapping_array[count].gport_list[index]; 15492 if (cur_gport == BCM_GPORT_INVALID) { 15493 break; 15494 } 15495 BCM_IF_ERROR_RETURN(_bcm_mn_fc_map_gport_check(unit, 15496 port, cur_gport)); 15497 } 15498 } 15499 15500 return BCM_E_NONE; 15501 } 15502 15503 15504 int 15505 bcm_mn_cosq_port_pfc_op(int unit, bcm_port_t port, 15506 bcm_switch_control_t sctype, _bcm_cosq_op_t op, 15507 bcm_gport_t *gport, int gport_count) 15508 { 15509 _bcm_mn_cosq_node_t *node; 15510 bcm_port_t local_port, resolved_port; 15511 int rv, type, class = -1, id, index, hw_cosq ; 15512 uint32 profile_index, old_profile_index; 15513 uint64 rval64[16], tmp, *rval64s[1], rval, index_map; 15514 uint32 fval, cos_bmp, tmp32; 15515 int hw_index; 15516 _bcm_mn_mmu_info_t *mmu_info; 15517 _bcm_mn_pipe_resources_t *res; 15518 _bcm_mn_cosq_port_info_t *port_info; 15519 soc_reg_t reg; 15520 int phy_port, mmu_port, lvl, pipe; 15521 soc_info_t *si; 15522 static const soc_reg_t llfc_cfgr[] = { 15523 PORT_PFC_CFG0r, PORT_PFC_CFG1r, PORT_PFC_CFG2r 15524 }; 15525 15526 if (gport_count < 0) { 15527 return BCM_E_PARAM; 15528 } 15529 15530 BCM_IF_ERROR_RETURN 15531 (_bcm_mn_cosq_localport_resolve(unit, port, &local_port)); 15532 15533 15534 for (index = 0; index < gport_count; index++) { 15535 BCM_IF_ERROR_RETURN(_bcm_mn_fc_map_gport_check(unit,port, gport[index])); 15536 } 15537 15538 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_pfc_class_resolve(sctype, &type, &class)); 15539 15540 si = &SOC_INFO(unit); 15541 phy_port = si->port_l2p_mapping[local_port]; 15542 mmu_port = si->port_p2m_mapping[phy_port]; 15543 15544 mmu_info = _bcm_mn_mmu_info[unit]; 15545 port_info = &mmu_info->port_info[local_port]; 15546 pipe = _BCM_MN_PORT_TO_PIPE(unit, local_port); 15547 res = _BCM_MN_PRESOURCES(mmu_info, pipe); 15548 15549 cos_bmp = 0; 15550 for (index = 0; index < gport_count; index++) { 15551 hw_index = -1; 15552 hw_cosq = -1; 15553 if (BCM_GPORT_IS_SET(gport[index])) { 15554 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_node_get(unit, gport[index], 15555 0, NULL, &resolved_port, &id, &node)); 15556 hw_index = node->hw_index; 15557 hw_cosq = node->hw_cosq; 15558 lvl = node->level; 15559 } else { 15560 hw_cosq = gport[index]; 15561 node = &res->p_queue_node[port_info->uc_base + hw_cosq]; 15562 node = node->parent; 15563 hw_index = node->hw_index; 15564 lvl = SOC_MONTEREY_NODE_LVL_L1; 15565 } 15566 if ((hw_cosq < 0) || (hw_cosq > 15)) { 15567 return BCM_E_PARAM; 15568 } 15569 BCM_IF_ERROR_RETURN( 15570 _bcm_mn_map_fc_status_to_node(unit, local_port, 15571 (op == _BCM_COSQ_OP_CLEAR) ? 0 : _BCM_MN_COSQ_FC_PFC, 15572 mmu_port*4, hw_cosq, hw_index, lvl)); 15573 cos_bmp |= 1 << hw_cosq; 15574 } 15575 15576 if (op == _BCM_COSQ_OP_CLEAR) { 15577 cos_bmp = (1 << _MN_NUM_INTERNAL_PRI) - 1; 15578 } 15579 15580 reg = llfc_cfgr[mmu_port/32]; 15581 rval64s[0] = rval64; 15582 BCM_IF_ERROR_RETURN(soc_reg64_get(unit, reg, 0, 0, &rval)); 15583 if (op == _BCM_COSQ_OP_SET || cos_bmp != 0) { 15584 index_map = soc_reg64_field_get(unit, reg, rval, PROFILE_INDEXf); 15585 COMPILER_64_SHR(index_map, ((mmu_port % 32) * 2)); 15586 COMPILER_64_TO_32_LO(tmp32, index_map); 15587 old_profile_index = (tmp32 & 3)*16; 15588 BCM_IF_ERROR_RETURN 15589 (soc_profile_reg_get(unit, _bcm_mn_llfc_profile[unit], 15590 old_profile_index, 16, rval64s)); 15591 if (op == _BCM_COSQ_OP_SET) { 15592 soc_reg64_field32_set(unit, PRIO2COS_PROFILEr, &rval64[class], 15593 COS_BMPf, cos_bmp); 15594 } else if (cos_bmp != 0) { 15595 fval = soc_reg64_field32_get(unit, PRIO2COS_PROFILEr, rval64[class], 15596 COS_BMPf); 15597 if (op == _BCM_COSQ_OP_ADD) { 15598 fval |= cos_bmp; 15599 } else { /* _BCM_COSQ_OP_DELETE */ 15600 fval &= ~cos_bmp; 15601 } 15602 soc_reg64_field32_set(unit, PRIO2COS_PROFILEr, &rval64[class], 15603 COS_BMPf, fval); 15604 } 15605 15606 BCM_IF_ERROR_RETURN 15607 (soc_profile_reg_delete(unit, _bcm_mn_llfc_profile[unit], 15608 old_profile_index)); 15609 rv = soc_profile_reg_add(unit, _bcm_mn_llfc_profile[unit], rval64s, 15610 16, &profile_index); 15611 if (rv < 0) { 15612 BCM_IF_ERROR_RETURN 15613 (soc_profile_reg_reference(unit, _bcm_mn_llfc_profile[unit], 15614 old_profile_index, 16)); 15615 return rv; 15616 } 15617 15618 index_map = soc_reg64_field_get(unit, reg, rval, PROFILE_INDEXf); 15619 15620 COMPILER_64_SET(tmp, 0, 3); 15621 COMPILER_64_SHL(tmp, (mmu_port % 32) * 2); 15622 COMPILER_64_NOT(tmp); 15623 COMPILER_64_AND(index_map, tmp); 15624 COMPILER_64_SET(tmp, 0, profile_index/16); 15625 COMPILER_64_SHL(tmp, (mmu_port % 32) * 2); 15626 COMPILER_64_OR(index_map, tmp); 15627 15628 soc_reg64_field_set(unit, reg, &rval, PROFILE_INDEXf, 15629 index_map); 15630 15631 } 15632 15633 BCM_IF_ERROR_RETURN(soc_reg64_set(unit, reg, 0, 0, rval)); 15634 return BCM_E_NONE; 15635 } 15636 15637 int 15638 bcm_mn_cosq_port_pfc_get(int unit, bcm_port_t port, 15639 bcm_switch_control_t sctype, 15640 bcm_gport_t *gport, int gport_count, 15641 int *actual_gport_count) 15642 { 15643 _bcm_mn_cosq_node_t *node; 15644 bcm_port_t local_port; 15645 int type = -1, class = -1, hw_cosq, count = 0; 15646 uint32 profile_index; 15647 uint64 rval64[16], *rval64s[1], rval, index_map; 15648 uint32 tmp32, bmp, bmp_len; 15649 _bcm_mn_mmu_info_t *mmu_info; 15650 int phy_port, mmu_port; 15651 soc_info_t *si; 15652 soc_reg_t reg; 15653 int mc_index = 0 ; 15654 int mcq_offset = 0 ; 15655 _bcm_mn_pipe_resources_t *res; 15656 _bcm_mn_cosq_port_info_t *port_info; 15657 static const soc_reg_t llfc_cfgr[] = { 15658 PORT_PFC_CFG0r, PORT_PFC_CFG1r, PORT_PFC_CFG2r 15659 }; 15660 static const soc_field_t self[] = { 15661 SEL0f, SEL1f, SEL2f, SEL3f 15662 }; 15663 int j, inv_mapped, hw_index, eindex; 15664 soc_mem_t mem; 15665 uint32 map_entry[SOC_MAX_MEM_WORDS]; 15666 int port_num = 0 ; 15667 15668 if (((gport == NULL) && (gport_count > 0)) || actual_gport_count == NULL) { 15669 return BCM_E_PARAM; 15670 } 15671 15672 BCM_IF_ERROR_RETURN 15673 (_bcm_mn_cosq_localport_resolve(unit, port, &local_port)); 15674 15675 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_pfc_class_resolve(sctype, &type, &class)); 15676 15677 si = &SOC_INFO(unit); 15678 mmu_info = _bcm_mn_mmu_info[unit]; 15679 res = _BCM_MN_PRESOURCES(mmu_info, 0); 15680 phy_port = si->port_l2p_mapping[local_port]; 15681 mmu_port = si->port_p2m_mapping[phy_port]; 15682 port_info = &mmu_info->port_info[local_port]; 15683 15684 rval64s[0] = rval64; 15685 reg = llfc_cfgr[mmu_port/32]; 15686 BCM_IF_ERROR_RETURN(soc_reg64_get(unit, reg, REG_PORT_ANY, 0, &rval)); 15687 15688 index_map = soc_reg64_field_get(unit, reg, rval, PROFILE_INDEXf); 15689 COMPILER_64_SHR(index_map, ((mmu_port % 32) * 2)); 15690 COMPILER_64_TO_32_LO(tmp32, index_map); 15691 profile_index = (tmp32 & 3)*16; 15692 15693 BCM_IF_ERROR_RETURN 15694 (soc_profile_reg_get(unit, _bcm_mn_llfc_profile[unit], 15695 profile_index, 16, rval64s)); 15696 15697 bmp = soc_reg64_field32_get(unit, PRIO2COS_PROFILEr, rval64[class], 15698 COS_BMPf); 15699 bmp_len = soc_reg_field_length(unit, PRIO2COS_PROFILEr, COS_BMPf); 15700 for (hw_cosq = 0; hw_cosq < bmp_len; hw_cosq++) { 15701 if (!(bmp & (1 << hw_cosq))) { 15702 continue; 15703 } 15704 if (_bcm_mn_cosq_port_has_ets(unit, local_port)) { 15705 inv_mapped = 0; 15706 for (j = _BCM_MN_NUM_PORT_SCHEDULERS; 15707 j < _BCM_MN_NUM_TOTAL_SCHEDULERS; j++) { 15708 node = &mmu_info->sched_node[j]; 15709 if ((!node->in_use) || (node->local_port != local_port) || 15710 (node->hw_cosq != hw_cosq)) { 15711 continue; 15712 } 15713 15714 hw_index = (node->hw_index / 16); 15715 eindex = (node->hw_index % 16)/4; 15716 if (node->level == SOC_MONTEREY_NODE_LVL_L0) { 15717 mem = MMU_INTFI_XPIPE_FC_MAP_TBL0m; 15718 } else if (node->level == SOC_MONTEREY_NODE_LVL_L1) { 15719 mem = MMU_INTFI_XPIPE_FC_MAP_TBL1m; 15720 } else { 15721 continue; 15722 } 15723 15724 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, 15725 MEM_BLOCK_ALL, hw_index, &map_entry)); 15726 15727 /* coverity[overrun-local : FALSE] */ 15728 if (soc_mem_field32_get(unit, mem, &map_entry, self[eindex])) { 15729 if (gport_count > 0) { 15730 gport[count] = node->gport; 15731 } 15732 count++; 15733 if ((count == gport_count) && (gport_count > 0)) { 15734 inv_mapped = 1; 15735 break; 15736 } 15737 } 15738 } 15739 15740 for (j = port_info->uc_base; 15741 inv_mapped==0 && (j < port_info->uc_limit); j++) { 15742 node = &res->p_queue_node[j]; 15743 if ((!node->in_use) || (node->local_port != local_port)) { 15744 continue; 15745 } 15746 if (node->hw_cosq != hw_cosq) { 15747 continue; 15748 } 15749 mem = MMU_INTFI_XPIPE_FC_MAP_TBL2m ; 15750 if (IS_MN_HSP_PORT(unit,port)) { 15751 hw_index = node->hw_index; 15752 if ((hw_index % 10) > 7) { 15753 /* FC support only for Q0-7 */ 15754 break; 15755 } 15756 port_num = hw_index / 10; 15757 hw_index = port_num * 2 + 15758 (((hw_index % 10) >= 4)? 1 : 0); 15759 eindex = hw_index & 0x3; 15760 hw_index = hw_index / 4; /* each entry contains 4 indexes */ 15761 } else 15762 { 15763 hw_index = (node->hw_index / 16); 15764 eindex = (node->hw_index % 16)/4; 15765 } 15766 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, 15767 MEM_BLOCK_ALL, hw_index, &map_entry)); 15768 15769 /* coverity[overrun-local : FALSE] */ 15770 if (soc_mem_field32_get(unit, mem, &map_entry, self[eindex])) { 15771 if (gport_count > 0) { 15772 gport[count] = node->gport; 15773 } 15774 count++ ; 15775 if ((count == gport_count) && (gport_count > 0)) { 15776 inv_mapped = 1; 15777 break; 15778 } 15779 } 15780 } 15781 for (j = port_info->mc_base; 15782 inv_mapped==0 && (j < port_info->mc_limit); j++) { 15783 mc_index = soc_monterey_l2_hw_index(unit, j, 0); 15784 node = &res->p_queue_node[mc_index]; 15785 if ((!node->in_use) || (node->local_port != local_port)) { 15786 continue; 15787 } 15788 if (node->hw_cosq != hw_cosq) { 15789 continue; 15790 } 15791 mem = MMU_INTFI_XPIPE_FC_MAP_TBL2m ; 15792 mcq_offset = node->hw_index % _BCM_MN_NUM_L2_UC_LEAVES_PER_PIPE; 15793 if (((mcq_offset % 10) > 7) ) { 15794 /* FC support only for Q0-7 */ 15795 continue; 15796 } 15797 hw_index = node->hw_index - (mcq_offset * 2 / 10); 15798 hw_index /= 16; 15799 eindex = (mcq_offset % 10)/4; 15800 eindex += ((mcq_offset /10) % 2) ? 0 : 2; 15801 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, 15802 MEM_BLOCK_ALL, hw_index, &map_entry)); 15803 15804 /* coverity[overrun-local : FALSE] */ 15805 if (soc_mem_field32_get(unit, mem, &map_entry, self[eindex])) { 15806 if (gport_count > 0) { 15807 gport[count] = node->gport; 15808 } 15809 count++; 15810 if ((count == gport_count) && (gport_count > 0)) { 15811 /* coverity[assigned_value : FALSE] */ 15812 inv_mapped = 1; 15813 break; 15814 } 15815 } 15816 } 15817 } else { 15818 if (gport_count > 0) { 15819 gport[count++] = hw_cosq; 15820 } 15821 } 15822 if (count == gport_count) { 15823 break; 15824 } 15825 } 15826 15827 if (count == 0) { 15828 return BCM_E_NOT_FOUND; 15829 } 15830 *actual_gport_count = count; 15831 return BCM_E_NONE; 15832 } 15833 15834 /* 15835 * Function: 15836 * bcm_mn_cosq_pfc_class_mapping_set 15837 * Purpose: 15838 * Set PFC mapping for port. PFC class is mapped to cosq or scheduler node gports. 15839 * Parameters: 15840 * unit - (IN) unit number 15841 * port - (IN) port number 15842 * array_count - (IN) count of mapping 15843 * mapping_array - (IN) mappings 15844 * Returns: 15845 * BCM_E_XXX 15846 */ 15847 int 15848 _bcm_mn_cosq_pfc_class_mapping_set(int unit, 15849 bcm_gport_t port, 15850 int array_count, 15851 bcm_cosq_pfc_class_mapping_t *mapping_array) 15852 { 15853 int index, count; 15854 int cur_class = 0, pfc_class[_BCM_MN_NUM_PFC_CLASS]; 15855 bcm_gport_t cur_gport = 0; 15856 uint32 cos_bmp[_BCM_MN_NUM_PFC_CLASS]; 15857 int local_port = 0 ; 15858 15859 BCM_IF_ERROR_RETURN 15860 (_bcm_mn_cosq_localport_resolve(unit, port, &local_port)); 15861 15862 if (local_port < 0) { 15863 return BCM_E_PORT; 15864 } 15865 15866 if (IS_CPU_PORT(unit, local_port)) { 15867 return BCM_E_PARAM; 15868 } 15869 if ((array_count < 0) || (array_count > _BCM_MN_NUM_PFC_CLASS)) { 15870 return BCM_E_PARAM; 15871 } 15872 if (mapping_array == NULL) { 15873 return BCM_E_PARAM; 15874 } 15875 15876 BCM_IF_ERROR_RETURN( _bcm_mn_pfc_class_mapping_check(unit,port, 15877 array_count,mapping_array)); 15878 _bcm_mn_clear_fc_status_to_node(unit, port); 15879 15880 sal_memset(cos_bmp, 0, sizeof(cos_bmp)); 15881 15882 for (count = 0; count < array_count; count++) { 15883 cur_class = mapping_array[count].class_id; 15884 15885 for (index = 0; index < BCM_COSQ_PFC_GPORT_COUNT; index++) { 15886 cur_gport = mapping_array[count].gport_list[index]; 15887 if (cur_gport == BCM_GPORT_INVALID) { 15888 break; 15889 } 15890 15891 BCM_IF_ERROR_RETURN(_bcm_mn_fc_status_map_gport(unit, port, 15892 cur_gport, _BCM_MN_COSQ_FC_PFC, &cos_bmp[cur_class])); 15893 } 15894 } 15895 15896 for (index = 0; index < _BCM_MN_NUM_PFC_CLASS; index++) { 15897 pfc_class[index] = index; 15898 } 15899 BCM_IF_ERROR_RETURN(_bcm_mn_port_fc_profile_set(unit, port, 15900 _BCM_COSQ_OP_SET, _BCM_MN_NUM_PFC_CLASS, pfc_class, cos_bmp)); 15901 15902 return BCM_E_NONE; 15903 } 15904 15905 int 15906 _bcm_mn_cosq_pfc_class_mapping_get(int unit, 15907 bcm_gport_t port, 15908 int array_max, 15909 int *array_count, 15910 bcm_cosq_pfc_class_mapping_t *mapping_array) 15911 { 15912 int rv = 0; 15913 int cur_class = 0; 15914 int actual_gport_count, class_count = 0; 15915 int local_port = 0 ; 15916 bcm_switch_control_t sc[] = { bcmSwitchPFCClass0Queue, 15917 bcmSwitchPFCClass1Queue, 15918 bcmSwitchPFCClass2Queue, 15919 bcmSwitchPFCClass3Queue, 15920 bcmSwitchPFCClass4Queue, 15921 bcmSwitchPFCClass5Queue, 15922 bcmSwitchPFCClass6Queue, 15923 bcmSwitchPFCClass7Queue 15924 }; 15925 15926 BCM_IF_ERROR_RETURN 15927 (_bcm_mn_cosq_localport_resolve(unit, port, &local_port)); 15928 15929 if (local_port < 0) { 15930 return BCM_E_PORT; 15931 } 15932 15933 if (IS_CPU_PORT(unit, local_port)) { 15934 return BCM_E_PARAM; 15935 } 15936 if ((mapping_array == NULL) && (array_max > 0)) { 15937 return BCM_E_PARAM; 15938 } 15939 if (array_count == NULL) { 15940 return BCM_E_PARAM; 15941 } 15942 15943 if (array_max <= 0) { 15944 *array_count = _BCM_MN_NUM_PFC_CLASS; 15945 return BCM_E_NONE; 15946 } 15947 15948 for (cur_class = 0; cur_class < _BCM_MN_NUM_PFC_CLASS; cur_class++) { 15949 actual_gport_count = 0; 15950 rv = bcm_mn_cosq_port_pfc_get(unit, port, sc[cur_class], 15951 mapping_array[class_count].gport_list, 15952 BCM_COSQ_PFC_GPORT_COUNT, &actual_gport_count); 15953 if (rv == BCM_E_NONE) { 15954 mapping_array[class_count].class_id = cur_class; 15955 if (actual_gport_count < BCM_COSQ_PFC_GPORT_COUNT) { 15956 mapping_array[class_count].gport_list[actual_gport_count] = 15957 BCM_GPORT_INVALID; 15958 } 15959 class_count++; 15960 } else if (rv != BCM_E_NOT_FOUND) { 15961 return rv; 15962 } 15963 15964 if (class_count == array_max) { 15965 break; 15966 } 15967 } 15968 15969 *array_count = class_count; 15970 if (class_count == 0) { 15971 return BCM_E_NOT_FOUND; 15972 } 15973 return BCM_E_NONE; 15974 } 15975 15976 /* 15977 * Function: 15978 * bcm_mn_port_priority_group_mapping_set 15979 * Purpose: 15980 * Assign a Priority Group for the input priority. 15981 * Parameters: 15982 * unit - (IN) device id. 15983 * gport - (IN) generic port. 15984 * prio - (IN) input priority. 15985 * priority_group - (IN) PG ID that the input priority mapped to. 15986 * Returns: 15987 * BCM_E_XXX 15988 */ 15989 int 15990 bcm_mn_port_priority_group_mapping_set(int unit, bcm_gport_t gport, 15991 int prio, int priority_group) 15992 { 15993 bcm_port_t port; 15994 uint32 value; 15995 int field_count; 15996 soc_field_t fields_0[]={PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf, 15997 PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf}; 15998 soc_field_t fields_1[]={PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf, 15999 PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf}; 16000 16001 if (!soc_feature(unit, soc_feature_priority_flow_control)) { 16002 return BCM_E_UNAVAIL; 16003 } 16004 /* PFC : 0-7, SAFC : 0-15. Taking the larger range for comparison */ 16005 if ((prio < AP_SAFC_INPUT_PRIORITY_MIN) || 16006 (prio > AP_SAFC_INPUT_PRIORITY_MAX)) { 16007 return BCM_E_PARAM; 16008 } 16009 16010 if ((priority_group < AP_PRIOROTY_GROUP_ID_MIN) || 16011 (priority_group > AP_PRIOROTY_GROUP_ID_MAX)) { 16012 return BCM_E_PARAM; 16013 } 16014 16015 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_localport_resolve(unit, gport, &port)); 16016 if (!SOC_PORT_VALID(unit, port)) { 16017 return BCM_E_PORT; 16018 } 16019 field_count = COUNTOF(fields_0); 16020 if (prio < field_count) { 16021 /* input priority 0~7 */ 16022 BCM_IF_ERROR_RETURN(READ_THDI_PORT_PRI_GRP0r(unit, port, &value)); 16023 soc_reg_field_set(unit, THDI_PORT_PRI_GRP0r, &value, 16024 fields_0[prio], priority_group); 16025 BCM_IF_ERROR_RETURN(WRITE_THDI_PORT_PRI_GRP0r(unit, port, value)); 16026 } else { 16027 /* input priority 8~15 */ 16028 BCM_IF_ERROR_RETURN(READ_THDI_PORT_PRI_GRP1r(unit, port, &value)); 16029 soc_reg_field_set(unit, THDI_PORT_PRI_GRP1r, &value, 16030 fields_1[prio - field_count], priority_group); 16031 BCM_IF_ERROR_RETURN(WRITE_THDI_PORT_PRI_GRP1r(unit, port, value)); 16032 } 16033 16034 return BCM_E_NONE; 16035 } 16036 16037 /* 16038 * Function: 16039 * bcm_mn_port_priority_group_mapping_get 16040 * Purpose: 16041 * Get the assigned Priority Group ID of the input priority. 16042 * Parameters: 16043 * unit - (IN) device id. 16044 * gport - (IN) generic port. 16045 * prio - (IN) input priority. 16046 * priority_group - (OUT) PG ID that the input priority mapped to. 16047 * Returns: 16048 * BCM_E_XXX 16049 */ 16050 16051 int 16052 bcm_mn_port_priority_group_mapping_get(int unit, bcm_gport_t gport, 16053 int prio, int *priority_group) 16054 { 16055 bcm_port_t port; 16056 uint32 value; 16057 int field_count; 16058 soc_field_t fields_0[]={PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf, 16059 PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf}; 16060 soc_field_t fields_1[]={PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf, 16061 PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf}; 16062 16063 if (!soc_feature(unit, soc_feature_priority_flow_control)) { 16064 return BCM_E_UNAVAIL; 16065 } 16066 if (priority_group == NULL) { 16067 return BCM_E_PARAM; 16068 } 16069 /* PFC : 0-7, SAFC : 0-15. Taking the larger range for comparison */ 16070 if ((prio < AP_SAFC_INPUT_PRIORITY_MIN) || 16071 (prio > AP_SAFC_INPUT_PRIORITY_MAX)) { 16072 return BCM_E_PARAM; 16073 } 16074 16075 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_localport_resolve(unit, gport, &port)); 16076 if (!SOC_PORT_VALID(unit, port)) { 16077 return BCM_E_PORT; 16078 } 16079 field_count = COUNTOF(fields_0); 16080 if (prio < field_count) { 16081 /* input priority 0~7 */ 16082 BCM_IF_ERROR_RETURN(READ_THDI_PORT_PRI_GRP0r(unit, port, &value)); 16083 *priority_group = soc_reg_field_get(unit, THDI_PORT_PRI_GRP0r, 16084 value, fields_0[prio]); 16085 } else { 16086 /* input priority 8~15 */ 16087 BCM_IF_ERROR_RETURN(READ_THDI_PORT_PRI_GRP1r(unit, port, &value)); 16088 *priority_group = soc_reg_field_get(unit, THDI_PORT_PRI_GRP1r, 16089 value, 16090 fields_1[prio - field_count]); 16091 } 16092 16093 return BCM_E_NONE; 16094 } 16095 16096 16097 int 16098 bcm_mn_cosq_drop_status_enable_set(int unit, bcm_port_t port, int enable) 16099 { 16100 _bcm_mn_mmu_info_t *mmu_info; 16101 uint32 rval; 16102 16103 if ((mmu_info = _bcm_mn_mmu_info[unit]) == NULL) { 16104 return BCM_E_INIT; 16105 } 16106 16107 BCM_IF_ERROR_RETURN(READ_MMU_THDM_DB_QUEUE_E2E_DS_EN_0r(unit, port, &rval)); 16108 soc_reg_field_set(unit, MMU_THDM_DB_QUEUE_E2E_DS_EN_0r, &rval, Q_COS_E2E_DS_ENf, 16109 0xff); 16110 BCM_IF_ERROR_RETURN(WRITE_MMU_THDM_DB_QUEUE_E2E_DS_EN_0r(unit, port, rval)); 16111 16112 BCM_IF_ERROR_RETURN(READ_OP_THDU_CONFIGr(unit, &rval)); 16113 soc_reg_field_set(unit, OP_THDU_CONFIGr, &rval, EARLY_E2E_SELECTf, 16114 enable ? 1 : 0); 16115 BCM_IF_ERROR_RETURN(WRITE_OP_THDU_CONFIGr(unit, rval)); 16116 16117 return BCM_E_NONE; 16118 } 16119 16120 STATIC int 16121 _bcm_mn_voq_min_hw_index(int unit, bcm_port_t port, 16122 bcm_module_t modid, 16123 bcm_port_t remote_port, 16124 int *q_offset) 16125 { 16126 int i, hw_index_base = -1, pipe; 16127 _bcm_mn_cosq_node_t *node; 16128 _bcm_mn_pipe_resources_t *res; 16129 _bcm_mn_mmu_info_t *mmu_info; 16130 16131 mmu_info = _bcm_mn_mmu_info[unit]; 16132 pipe = _BCM_MN_PORT_TO_PIPE(unit, port); 16133 res = _BCM_MN_PRESOURCES(mmu_info, pipe); 16134 16135 for (i = res->num_base_queues; i < _BCM_MN_NUM_L2_UC_LEAVES_PER_PIPE; i++) { 16136 node = &res->p_queue_node[i]; 16137 if ((node->in_use == FALSE) || (node->hw_index == -1) || 16138 (node->type != _BCM_MN_NODE_VOQ)) { 16139 continue; 16140 } 16141 16142 if (((modid == -1) ? 1 : (node->remote_modid == modid)) && 16143 (node->remote_port == remote_port) && 16144 ((port == -1) ? 1 : (port == node->local_port))) { 16145 if (hw_index_base == -1) { 16146 hw_index_base = node->hw_index; 16147 break; 16148 } 16149 } 16150 } 16151 16152 if (hw_index_base != -1) { 16153 *q_offset = hw_index_base & ~7; 16154 return BCM_E_NONE; 16155 } 16156 16157 return BCM_E_NOT_FOUND; 16158 } 16159 16160 STATIC int 16161 _bcm_mn_voq_base_node_get(int unit, bcm_port_t port, 16162 int modid, 16163 _bcm_mn_cosq_node_t **base_node) 16164 { 16165 int i, pipe; 16166 _bcm_mn_pipe_resources_t *res; 16167 _bcm_mn_mmu_info_t *mmu_info; 16168 _bcm_mn_cosq_node_t *node; 16169 16170 mmu_info = _bcm_mn_mmu_info[unit]; 16171 pipe = _BCM_MN_PORT_TO_PIPE(unit, port); 16172 res = _BCM_MN_PRESOURCES(mmu_info, pipe); 16173 for ( i = res->num_base_queues ; 16174 i < _BCM_MN_NUM_L2_UC_LEAVES_PER_PIPE ; i++) { 16175 node = &res->p_queue_node[i]; 16176 if ((node->in_use == FALSE) || (node->hw_index == -1)) { 16177 continue; 16178 } 16179 if (node->remote_modid == modid) { 16180 *base_node = node ; 16181 break; 16182 } 16183 } 16184 return BCM_E_NONE; 16185 } 16186 16187 STATIC int 16188 _bcm_mn_voq_next_base_node_get(int unit, bcm_port_t port, 16189 int modid, 16190 _bcm_mn_cosq_node_t **base_node) 16191 { 16192 int i, pipe; 16193 _bcm_mn_pipe_resources_t *res; 16194 _bcm_mn_mmu_info_t *mmu_info; 16195 _bcm_mn_cosq_node_t *node; 16196 int found = FALSE; 16197 16198 mmu_info = _bcm_mn_mmu_info[unit]; 16199 pipe = _BCM_MN_PORT_TO_PIPE(unit, port); 16200 for (pipe = _MN_XPIPE ; pipe < _MN_NUM_PIPES ; pipe++) { 16201 res = _BCM_MN_PRESOURCES(mmu_info, pipe); 16202 for ( i = res->num_base_queues ; 16203 i < _BCM_MN_NUM_L2_UC_LEAVES_PER_PIPE ; i++) { 16204 node = &res->p_queue_node[i]; 16205 if ((node->in_use == FALSE) || (node->hw_index == -1)) { 16206 continue; 16207 } 16208 if (node->remote_modid == modid) { 16209 if ( found == TRUE) { 16210 *base_node = node; 16211 break; 16212 } 16213 found = TRUE; 16214 } 16215 } 16216 } 16217 return BCM_E_NONE; 16218 } 16219 16220 STATIC int 16221 _bcm_mn_port_voq_base_set(int unit, bcm_port_t local_port, int base) 16222 { 16223 uint64 rval; 16224 16225 BCM_IF_ERROR_RETURN(READ_ING_COS_MODE_64r(unit, local_port, &rval)); 16226 soc_reg64_field32_set(unit, ING_COS_MODE_64r, &rval, BASE_QUEUE_NUM_1f, base); 16227 BCM_IF_ERROR_RETURN(WRITE_ING_COS_MODE_64r(unit, local_port, rval)); 16228 return BCM_E_NONE; 16229 } 16230 16231 STATIC int 16232 _bcm_mn_port_voq_base_get(int unit, bcm_port_t local_port, int *base) 16233 { 16234 uint64 rval; 16235 16236 BCM_IF_ERROR_RETURN(READ_ING_COS_MODE_64r(unit, local_port, &rval)); 16237 if (soc_reg64_field32_get(unit, ING_COS_MODE_64r, rval, QUEUE_MODEf) == 1) { 16238 *base = soc_reg64_field32_get(unit, ING_COS_MODE_64r, rval, 16239 BASE_QUEUE_NUM_1f); 16240 return BCM_E_NONE; 16241 } 16242 16243 BCM_IF_ERROR_RETURN( 16244 _bcm_mn_voq_min_hw_index(unit, local_port, -1, -1, base)); 16245 16246 return BCM_E_NONE; 16247 } 16248 16249 STATIC int 16250 _bcm_mn_resolve_dmvoq_hw_index(int unit, _bcm_mn_cosq_node_t *node, 16251 int cosq, bcm_module_t modid, bcm_port_t local_port) 16252 { 16253 int try, preffered_offset = -1, alloc_size; 16254 int from_offset, max_offset, port, rv, q_base, port_voq_base, pipe; 16255 _bcm_mn_pipe_resources_t *res; 16256 _bcm_mn_mmu_info_t *mmu_info; 16257 16258 mmu_info = _bcm_mn_mmu_info[unit]; 16259 pipe = _BCM_MN_PORT_TO_PIPE(unit, local_port); 16260 res = _BCM_MN_PRESOURCES(mmu_info, pipe); 16261 16262 from_offset = res->num_base_queues; 16263 max_offset = _BCM_MN_NUM_L2_UC_LEAVES_PER_PIPE; 16264 alloc_size = _MN_NUM_COS(unit); 16265 16266 for (try = 0; try < 2; try++) { 16267 PBMP_HG_ITER(unit, port) { 16268 if ((try == 1) && (port == local_port)) { 16269 continue; 16270 } 16271 16272 if ((try == 0) && (port != local_port)) { 16273 continue; 16274 } 16275 16276 rv = _bcm_mn_voq_min_hw_index(unit, port, modid, -1, &q_base); 16277 if (!rv) { 16278 if (port == local_port) { 16279 /* Found VOQ for the same port/dest modid */ 16280 node->hw_index = q_base + cosq; 16281 return BCM_E_NONE; 16282 } else if (modid == -1) { 16283 rv = _bcm_mn_port_voq_base_get(unit, port, &port_voq_base); 16284 if (rv) { 16285 continue; 16286 } 16287 preffered_offset = q_base - port_voq_base; 16288 rv = _bcm_mn_port_voq_base_get(unit, local_port, 16289 &port_voq_base); 16290 if (rv) { 16291 /* No VOQ on the port yet */ 16292 alloc_size += preffered_offset; 16293 } else { 16294 /* port has already VOQs */ 16295 from_offset = port_voq_base + preffered_offset; 16296 } 16297 break; 16298 } 16299 } 16300 } 16301 if (preffered_offset != -1) { 16302 break; 16303 } 16304 } 16305 if (modid == -1) { 16306 /* Alloc hw index. */ 16307 rv = _bcm_mn_node_index_get(res->l2_queue_list.bits, 16308 from_offset, max_offset, 16309 alloc_size, _MN_NUM_COS(unit), &q_base); 16310 if (rv) { 16311 return BCM_E_RESOURCE; 16312 } 16313 16314 if (_bcm_mn_port_voq_base_get(unit, local_port, &port_voq_base)) { 16315 _bcm_mn_port_voq_base_set(unit, local_port, q_base); 16316 } 16317 q_base = q_base + alloc_size - _MN_NUM_COS(unit); 16318 node->hw_index = q_base + cosq; 16319 node->hw_cosq = node->hw_index % _MN_NUM_COS(unit); 16320 node->remote_modid = modid; 16321 _bcm_mn_node_index_set(&res->l2_queue_list, q_base, _MN_NUM_COS(unit)); 16322 } else { 16323 BCM_IF_ERROR_RETURN( 16324 _bcm_mn_voq_min_hw_index(unit, local_port, -1, -1, &port_voq_base)); 16325 16326 if (port_voq_base == node->hw_index) { 16327 _bcm_mn_port_voq_base_set(unit, local_port, node->hw_index); 16328 } 16329 node->remote_modid = modid; 16330 rv = BCM_E_NONE; 16331 } 16332 return rv; 16333 } 16334 16335 typedef struct _bcm_mn_voq_info_s { 16336 int valid; 16337 _bcm_mn_cosq_node_t *node; 16338 bcm_module_t remote_modid; 16339 bcm_port_t remote_port; 16340 bcm_port_t local_port; 16341 int hw_cosq; 16342 int hw_index; 16343 } _bcm_mn_voq_info_t; 16344 16345 STATIC int 16346 _bcm_mn_cosq_sort_voq_list(void *a, void *b) 16347 { 16348 _bcm_mn_voq_info_t *va, *vb; 16349 int sa, sb; 16350 16351 va = (_bcm_mn_voq_info_t*)a; 16352 vb = (_bcm_mn_voq_info_t*)b; 16353 16354 sa = (va->remote_modid << 19) | (va->remote_port << 11) | 16355 (va->local_port << 3) | (va->hw_cosq); 16356 16357 sb = (vb->remote_modid << 19) | (vb->remote_port << 11) | 16358 (vb->local_port << 3) | (vb->hw_cosq); 16359 16360 return sa - sb; 16361 } 16362 16363 STATIC int 16364 _bcm_mn_get_queue_skip_count_on_cos(uint32 cbmp, int cur_cos, int next_cos) 16365 { 16366 int i,skip = 0; 16367 16368 if ((next_cos >= 4) && (cur_cos/4 != next_cos/4)) { 16369 cur_cos = -1; 16370 next_cos -= 4; 16371 } 16372 16373 for (i = cur_cos + 1; i < next_cos; i++) { 16374 if (cbmp & (1 << i)) { 16375 skip += 1; 16376 } 16377 } 16378 return skip; 16379 } 16380 16381 STATIC int 16382 _bcm_mn_msg_buf_get(int unit, bcm_port_t srcid) 16383 { 16384 int ii, hole = -1; 16385 uint32 rval, csrc; 16386 16387 for (ii = 0; ii < 16; ii++) { 16388 BCM_IF_ERROR_RETURN(READ_BUF_CFGr(unit, ii, &rval)); 16389 if (srcid == (csrc = soc_reg_field_get(unit, BUF_CFGr, rval, SRC_IDf))) { 16390 return ii; 16391 } 16392 if ((hole == -1) && (csrc == 0)) { 16393 hole = ii; 16394 } 16395 } 16396 16397 if (hole == -1) { 16398 return BCM_E_RESOURCE; 16399 } 16400 16401 rval = 0; 16402 soc_reg_field_set(unit, BUF_CFGr, &rval, SRC_IDf, srcid); 16403 BCM_IF_ERROR_RETURN(WRITE_BUF_CFGr(unit, hole, rval)); 16404 16405 return hole; 16406 } 16407 16408 STATIC int 16409 _bcm_mn_gport_dpvoq_config_set(int unit, bcm_gport_t gport, 16410 bcm_cos_queue_t cosq, 16411 bcm_module_t remote_modid, 16412 bcm_port_t remote_port) 16413 { 16414 uint32 profile = 0xFFFFFFFF; 16415 _bcm_mn_cosq_node_t *node; 16416 bcm_port_t local_port; 16417 uint32 cng_offset; 16418 uint8 cbmp = 0, nib_cbmp = 0; 16419 _bcm_mn_mmu_info_t *mmu_info; 16420 _bcm_mn_voq_info_t *plist = NULL, *vlist = NULL; 16421 int pcount, ii, vcount = 0; 16422 voq_port_map_entry_t *voq_port_map_entries = NULL; 16423 int rv = BCM_E_NONE, mod_base = 0, num_cos = 0, dm = -1; 16424 voq_mod_map_entry_t voq_mod_map; 16425 void *entries[1]; 16426 int cng_bytes_per_e2ecc_msg = 64; 16427 int p2ioff[128], ioff, port, skip, *dm2off, count, pipe; 16428 _bcm_mn_pipe_resources_t *res; 16429 voq_cos_map_entry_t voq_cos_map; 16430 int priority = 0; 16431 int rp, port_q_base = 0; 16432 int base_tbl_entry = 0, intf_index = -1; 16433 uint64 rval64; 16434 soc_info_t *si; 16435 int phy_port, mmu_port; 16436 16437 if ((cosq < 0) || (cosq > _MN_NUM_COS(unit))) { 16438 return BCM_E_PARAM; 16439 } 16440 16441 if ((mmu_info = _bcm_mn_mmu_info[unit]) == NULL) { 16442 return BCM_E_INIT; 16443 } 16444 16445 BCM_IF_ERROR_RETURN 16446 (_bcm_mn_cosq_node_get(unit, gport, 0, NULL, &local_port, NULL, &node)); 16447 16448 pipe = _BCM_MN_PORT_TO_PIPE(unit, local_port); 16449 res = _BCM_MN_PRESOURCES(mmu_info, pipe); 16450 16451 node->remote_modid = remote_modid; 16452 node->remote_port = remote_port; 16453 node->hw_cosq = cosq; 16454 16455 dm2off = sal_alloc(sizeof(int) * 256, "voq_vlist"); 16456 if (!dm2off) { 16457 return BCM_E_MEMORY; 16458 } 16459 sal_memset(dm2off, 0, sizeof(int)*256); 16460 16461 /* alloc temp vlist */ 16462 vlist = sal_alloc(sizeof(_bcm_mn_voq_info_t) * _BCM_MN_NUM_L2_UC_LEAVES, "voq_vlist"); 16463 if (!vlist) { 16464 sal_free(dm2off); 16465 return BCM_E_MEMORY; 16466 } 16467 sal_memset(vlist, 0, sizeof(_bcm_mn_voq_info_t)*_BCM_MN_NUM_L2_UC_LEAVES); 16468 16469 for (ii = 0; ii < _BCM_MN_NUM_L2_UC_LEAVES; ii++) { 16470 node = &res->p_queue_node[ii]; 16471 if ((node->remote_modid == -1) || (node->remote_port == -1)) { 16472 continue; 16473 } 16474 vlist[vcount].remote_modid = node->remote_modid; 16475 vlist[vcount].remote_port = node->remote_port; 16476 vlist[vcount].local_port = node->local_port; 16477 vlist[vcount].hw_cosq = node->hw_cosq; 16478 vlist[vcount].node = node; 16479 vcount += 1; 16480 } 16481 16482 /* Sort the nodes */ 16483 _shr_sort(vlist, vcount, sizeof(_bcm_mn_voq_info_t), 16484 _bcm_mn_cosq_sort_voq_list); 16485 16486 for (ii = 0; ii < 128; ii++) { 16487 p2ioff[ii] = -1; 16488 } 16489 16490 si = &SOC_INFO(unit); 16491 PBMP_HG_ITER(unit, port) { 16492 /* For DPVOQ, SRC_ID should be the mmu_port number */ 16493 phy_port = si->port_l2p_mapping[port]; 16494 mmu_port = si->port_p2m_mapping[phy_port]; 16495 ioff = _bcm_mn_msg_buf_get(unit, mmu_port); 16496 p2ioff[port] = ioff; 16497 } 16498 16499 for (ii = 0; ii < vcount; ii++) { 16500 cbmp |= 1 << vlist[ii].hw_cosq; 16501 } 16502 16503 nib_cbmp = (cbmp >> 4) | (cbmp & 0xf); 16504 16505 for (ii = 0; ii < 4; ii++) { 16506 if ((1 << ii) & nib_cbmp) { 16507 num_cos += 1; 16508 } 16509 } 16510 16511 for (count = 1, ii = 0; ii < vcount; ii++) { 16512 if (dm2off[vlist[ii].remote_modid]==0) { 16513 dm2off[vlist[ii].remote_modid] = count; 16514 } 16515 } 16516 16517 plist = sal_alloc(sizeof(_bcm_mn_voq_info_t) * _BCM_MN_NUM_L2_UC_LEAVES, "voq_vlist"); 16518 if (!plist) { 16519 sal_free(dm2off); 16520 sal_free(vlist); 16521 return BCM_E_MEMORY; 16522 } 16523 sal_memset(plist, 0, sizeof(_bcm_mn_voq_info_t) * _BCM_MN_NUM_L2_UC_LEAVES); 16524 16525 for (pcount = 0, ii = 0; ii < vcount; ii++) { 16526 if (pcount % 4) { 16527 if ((plist[pcount - 1].remote_modid != vlist[ii].remote_modid) || 16528 (plist[pcount - 1].remote_port != vlist[ii].remote_port)) { 16529 pcount = (pcount + 3) & ~3; 16530 } else if (plist[pcount - 1].local_port != vlist[ii].local_port) { 16531 skip = (p2ioff[vlist[ii].local_port] - 16532 p2ioff[plist[pcount - 1].local_port] - 1) * num_cos; 16533 skip += _bcm_mn_get_queue_skip_count_on_cos(nib_cbmp, 16534 plist[pcount - 1].hw_cosq, 16535 vlist[ii].hw_cosq); 16536 if (skip >= 4) { 16537 pcount = ((pcount + 3) & ~3) + (skip % 4); 16538 } else { 16539 pcount += skip; 16540 } 16541 } else if ((vlist[ii].hw_cosq - plist[pcount - 1].hw_cosq) > 1) { 16542 if (plist[pcount - 1].hw_cosq/4 != vlist[ii].hw_cosq/4) { 16543 pcount = (pcount + 3) & ~3; 16544 } 16545 pcount += _bcm_mn_get_queue_skip_count_on_cos(nib_cbmp, 16546 plist[pcount - 1].hw_cosq, 16547 vlist[ii].hw_cosq); 16548 } 16549 } else { 16550 pcount += _bcm_mn_get_queue_skip_count_on_cos(nib_cbmp, -1, 16551 vlist[ii].hw_cosq); 16552 } 16553 16554 plist[pcount].valid = 1; 16555 plist[pcount].local_port = vlist[ii].local_port; 16556 plist[pcount].remote_modid = vlist[ii].remote_modid; 16557 plist[pcount].remote_port = vlist[ii].remote_port; 16558 plist[pcount].hw_cosq = vlist[ii].hw_cosq; 16559 plist[pcount].node = vlist[ii].node; 16560 16561 #ifdef DEBUG_MN_COSQ 16562 LOG_CLI((BSL_META_U(unit, 16563 "DPVOQ DM=%d DP=%d LocalPort=%d COS=%d HWIndex=%d\n"), 16564 plist[pcount].remote_modid, 16565 plist[pcount].remote_port, 16566 plist[pcount].local_port, 16567 plist[pcount].hw_cosq, 16568 plist[pcount].node->hw_index)); 16569 #endif 16570 pcount += 1; 16571 } 16572 16573 /* program the voq port profiles. */ 16574 voq_port_map_entries = sal_alloc(sizeof(voq_port_map_entry_t)*128, 16575 "voq port map entries"); 16576 if (!voq_port_map_entries) { 16577 goto fail; 16578 } 16579 sal_memset(voq_port_map_entries, 0, sizeof(voq_port_map_entry_t)*128); 16580 16581 entries[0] = voq_port_map_entries; 16582 dm = -1; 16583 rp = -1; 16584 for (ii = 0; ii <= pcount; ii++) { 16585 if (plist[ii].valid == 1) { 16586 rv = READ_ING_COS_MODE_64r(unit, plist[ii].local_port, &rval64); 16587 if (rv) { 16588 goto fail; 16589 } 16590 port_q_base = soc_reg64_field32_get(unit, ING_COS_MODE_64r, rval64, 16591 BASE_QUEUE_NUM_1f); 16592 } 16593 16594 if ((ii == pcount) || 16595 ((dm != -1) && (plist[ii].valid) && 16596 (plist[ii].remote_modid != dm))) { 16597 16598 rv = READ_VOQ_MOD_MAPm(unit, MEM_BLOCK_ALL, dm, &voq_mod_map); 16599 if (rv) { 16600 goto fail; 16601 } 16602 if (soc_mem_field32_get(unit, VOQ_MOD_MAPm, 16603 &voq_mod_map, VOQ_VALIDf)) { 16604 profile = soc_mem_field32_get(unit, VOQ_MOD_MAPm, 16605 &voq_mod_map, VOQ_MOD_PORT_PROFILE_INDEXf); 16606 16607 rv = soc_profile_mem_delete(unit, 16608 _bcm_mn_voq_port_map_profile[unit], profile*128); 16609 if (rv) { 16610 goto fail; 16611 } 16612 } 16613 rv = soc_profile_mem_add(unit, 16614 _bcm_mn_voq_port_map_profile[unit], 16615 entries, 128, &profile); 16616 if (rv) { 16617 goto fail; 16618 } 16619 16620 soc_mem_field32_set(unit, VOQ_MOD_MAPm, &voq_mod_map, 16621 VOQ_MOD_PORT_PROFILE_INDEXf, profile/128); 16622 soc_mem_field32_set(unit, VOQ_MOD_MAPm, &voq_mod_map, 16623 VOQ_VALIDf, 1); 16624 soc_mem_field32_set(unit, VOQ_MOD_MAPm, &voq_mod_map, 16625 VOQ_MOD_OFFSETf, mod_base); 16626 soc_mem_field32_set(unit, VOQ_MOD_MAPm, &voq_mod_map, 16627 VOQ_MOD_USE_PORTf, 1); 16628 rv = soc_mem_write(unit, VOQ_MOD_MAPm, MEM_BLOCK_ALL, 16629 dm, &voq_mod_map); 16630 if (rv) { 16631 goto fail; 16632 } 16633 16634 sal_memset(voq_port_map_entries, 0, sizeof(voq_port_map_entry_t)*128); 16635 16636 if (ii != pcount) { 16637 if (plist[ii].node) { 16638 mod_base = (plist[ii].node->hw_index & ~3) - port_q_base; 16639 } 16640 } 16641 } 16642 16643 if (ii == pcount) { 16644 break; 16645 } 16646 16647 if (plist[ii].valid == 0) { 16648 continue; 16649 } 16650 16651 if (dm == -1) { 16652 if (plist[ii].node) { 16653 mod_base = (plist[ii].node->hw_index & ~3) - port_q_base; 16654 } 16655 } 16656 16657 dm = plist[ii].remote_modid; 16658 16659 if ((rp == -1) || 16660 (rp != plist[ii].remote_port)) { 16661 rp = plist[ii].remote_port; 16662 soc_mem_field32_set(unit, VOQ_PORT_MAPm, 16663 &voq_port_map_entries[plist[ii].remote_port], 16664 VOQ_PORT_OFFSETf, 16665 (plist[ii].node->hw_index - mod_base - port_q_base) & 0x3fff); 16666 } 16667 } 16668 16669 for (priority = 0; priority < 16; priority++) { 16670 rv = READ_VOQ_COS_MAPm(unit, MEM_BLOCK_ALL, priority, &voq_cos_map); 16671 if (rv) { 16672 goto fail; 16673 } 16674 16675 /* Setting the VOQ_PORT_BASE_SELECT, 16676 so that BASE_QUEUE_NUM_1 is used for queue 16677 calculation */ 16678 16679 soc_mem_field32_set(unit, VOQ_COS_MAPm, 16680 &voq_cos_map, VOQ_PORT_BASE_SELECTf, pcount ? 1 : 0); 16681 soc_mem_field32_set(unit, VOQ_COS_MAPm, 16682 &voq_cos_map, VOQ_COS_USE_MODf, pcount ? 1 : 0); 16683 soc_mem_field32_set(unit, VOQ_COS_MAPm, 16684 &voq_cos_map, VOQ_COS_USE_PORTf, pcount ? 1 : 0); 16685 16686 rv = soc_mem_write(unit, VOQ_COS_MAPm, MEM_BLOCK_ANY, priority, 16687 &voq_cos_map); 16688 if (rv) { 16689 goto fail; 16690 } 16691 } 16692 16693 dm = -1; 16694 for (ii = 0; ii < pcount; ii += 1) { 16695 if (plist[ii].valid == 0) { 16696 continue; 16697 } 16698 phy_port = si->port_l2p_mapping[plist[ii].local_port]; 16699 mmu_port = si->port_p2m_mapping[phy_port]; 16700 16701 cng_offset = (dm2off[plist[ii].remote_modid] - 1) * 16702 cng_bytes_per_e2ecc_msg; 16703 16704 /* 16705 * Base index table addr = {< interface number>,BUF_CFG<interface number>__PROFILE_ID} 16706 * If incoming message mmu port number matches say interface 4's SRC_ID, 16707 * then it will address base_index_table as {0, BUF_CFG4_PROFILE_ID}. 16708 * Since profile_id is 2 bits, we index base_index_table in multiple of 4. 16709 */ 16710 16711 intf_index = _bcm_mn_msg_buf_get(unit, mmu_port); 16712 if (intf_index < 0) { 16713 return BCM_E_INTERNAL; 16714 } 16715 16716 BCM_IF_ERROR_RETURN 16717 (soc_mem_read(unit, MMU_INTFI_BASE_INDEX_TBLm, 16718 MEM_BLOCK_ALL, intf_index * 4, &base_tbl_entry)); 16719 16720 soc_mem_field32_set(unit, MMU_INTFI_BASE_INDEX_TBLm, &base_tbl_entry, 16721 BASE_ADDRf, cng_offset); 16722 soc_mem_field32_set(unit, MMU_INTFI_BASE_INDEX_TBLm, &base_tbl_entry, 16723 ENf, 2); 16724 16725 BCM_IF_ERROR_RETURN(soc_mem_write(unit, MMU_INTFI_BASE_INDEX_TBLm, 16726 MEM_BLOCK_ALL, intf_index * 4, &base_tbl_entry)); 16727 16728 /* Each byte of message should correspond to 2 entries in FC_ST_TBL2. 16729 * Hence port * 2. 16730 */ 16731 _bcm_mn_map_fc_status_to_node(unit, 16732 plist[ii].local_port, 16733 _BCM_MN_COSQ_FC_E2ECC, 16734 cng_offset + (plist[ii].remote_port * 2), 16735 plist[ii].hw_cosq, 16736 plist[ii].node->hw_index, 16737 SOC_MONTEREY_NODE_LVL_L2); 16738 } 16739 16740 fail: 16741 if (vlist) { 16742 sal_free(vlist); 16743 } 16744 16745 if (plist) { 16746 sal_free(plist); 16747 } 16748 16749 if (dm2off) { 16750 sal_free(dm2off); 16751 } 16752 16753 if (voq_port_map_entries) { 16754 sal_free(voq_port_map_entries); 16755 } 16756 16757 if (rv) { 16758 node->remote_modid = -1; 16759 node->remote_port = -1; 16760 } 16761 return rv; 16762 } 16763 16764 STATIC int 16765 _bcm_mn_gport_dmvoq_config_set(int unit, bcm_gport_t gport, 16766 bcm_cos_queue_t cosq, 16767 bcm_module_t fabric_modid, 16768 bcm_module_t dest_modid, 16769 bcm_port_t fabric_port) 16770 { 16771 int port_voq_base, intf_index; 16772 _bcm_mn_cosq_node_t *node; 16773 _bcm_mn_cosq_node_t *base_node = NULL; 16774 bcm_port_t local_port; 16775 voq_mod_map_entry_t voq_mod_map_entry; 16776 mmu_intfi_offset_map_tbl_entry_t offset_map_tbl_entry; 16777 mmu_intfi_base_index_tbl_entry_t base_tbl_entry; 16778 uint32 cng_offset = 0; 16779 _bcm_mn_mmu_info_t *mmu_info; 16780 int fabric_port_count, count = 0; 16781 int map_offset = 0; 16782 int port = 0; 16783 16784 if ((mmu_info = _bcm_mn_mmu_info[unit]) == NULL) { 16785 return BCM_E_INIT; 16786 } 16787 16788 if (fabric_modid >= 64) { 16789 return BCM_E_PARAM; 16790 } 16791 16792 BCM_IF_ERROR_RETURN 16793 (_bcm_mn_cosq_node_get(unit, gport, 0, NULL, &local_port, NULL, &node)); 16794 16795 if (!node) { 16796 return BCM_E_NOT_FOUND; 16797 } 16798 16799 BCM_IF_ERROR_RETURN(_bcm_mn_resolve_dmvoq_hw_index(unit, node, cosq, 16800 dest_modid, local_port)); 16801 BCM_IF_ERROR_RETURN(_bcm_mn_voq_base_node_get( 16802 unit, local_port, dest_modid, &base_node)); 16803 if (base_node == NULL) { 16804 base_node = node ; 16805 } 16806 BCM_PBMP_COUNT(base_node->fabric_pbmp, fabric_port_count); 16807 if (fabric_port_count == 0) { 16808 map_offset = mmu_info->curr_merger_index; 16809 if (map_offset >= soc_mem_index_count(unit, MMU_INTFI_MERGE_ST_TBLm)) { 16810 return BCM_E_RESOURCE; 16811 } 16812 } else { 16813 BCM_PBMP_ITER(base_node->fabric_pbmp, port) { 16814 BCM_IF_ERROR_RETURN(soc_mem_read(unit, MMU_INTFI_OFFSET_MAP_TBLm, 16815 MEM_BLOCK_ALL, 16816 port * 2, &offset_map_tbl_entry)); 16817 map_offset = soc_mem_field32_get(unit, MMU_INTFI_OFFSET_MAP_TBLm, 16818 &offset_map_tbl_entry, 16819 MAP_OFFSETf); 16820 break; 16821 } 16822 } 16823 if (!BCM_PBMP_MEMBER(base_node->fabric_pbmp, fabric_port)) { 16824 if (map_offset == mmu_info->curr_merger_index ) { 16825 mmu_info->curr_merger_index += 2; 16826 } 16827 16828 BCM_PBMP_PORT_ADD (base_node->fabric_pbmp, fabric_port); 16829 BCM_PBMP_COUNT(base_node->fabric_pbmp, fabric_port_count); 16830 BCM_PBMP_ITER(base_node->fabric_pbmp, port) { 16831 count++; 16832 BCM_IF_ERROR_RETURN(soc_mem_read(unit, MMU_INTFI_OFFSET_MAP_TBLm, 16833 MEM_BLOCK_ALL, 16834 port * 2, &offset_map_tbl_entry)); 16835 soc_mem_field32_set(unit, MMU_INTFI_OFFSET_MAP_TBLm, 16836 &offset_map_tbl_entry, 16837 MAP_OFFSETf, map_offset); 16838 soc_mem_field32_set(unit, MMU_INTFI_OFFSET_MAP_TBLm, 16839 &offset_map_tbl_entry, 16840 LASTf, count < fabric_port_count ? 0 : 1 ); 16841 BCM_IF_ERROR_RETURN(soc_mem_write(unit, MMU_INTFI_OFFSET_MAP_TBLm, 16842 MEM_BLOCK_ALL, 16843 port * 2, &offset_map_tbl_entry)); 16844 16845 BCM_IF_ERROR_RETURN(soc_mem_read(unit, MMU_INTFI_OFFSET_MAP_TBLm, 16846 MEM_BLOCK_ALL, 16847 (port * 2) + 1, &offset_map_tbl_entry)); 16848 soc_mem_field32_set(unit, MMU_INTFI_OFFSET_MAP_TBLm, 16849 &offset_map_tbl_entry, 16850 MAP_OFFSETf, map_offset + 1); 16851 soc_mem_field32_set(unit, MMU_INTFI_OFFSET_MAP_TBLm, 16852 &offset_map_tbl_entry, 16853 LASTf, count < fabric_port_count ? 0 : 1 ); 16854 BCM_IF_ERROR_RETURN(soc_mem_write(unit, MMU_INTFI_OFFSET_MAP_TBLm, 16855 MEM_BLOCK_ALL, 16856 (port * 2) + 1, &offset_map_tbl_entry)); 16857 } 16858 } 16859 16860 BCM_IF_ERROR_RETURN(soc_mem_read(unit, VOQ_MOD_MAPm, MEM_BLOCK_ALL, 16861 dest_modid, &voq_mod_map_entry)); 16862 BCM_IF_ERROR_RETURN(_bcm_mn_port_voq_base_get(unit, local_port, 16863 &port_voq_base)); 16864 soc_mem_field32_set(unit, VOQ_MOD_MAPm, &voq_mod_map_entry, 16865 VOQ_VALIDf, 1); 16866 soc_mem_field32_set(unit, VOQ_MOD_MAPm, &voq_mod_map_entry, 16867 VOQ_MOD_OFFSETf, ((node->hw_index & ~7) - port_voq_base)); 16868 16869 BCM_IF_ERROR_RETURN( 16870 soc_mem_write(unit, VOQ_MOD_MAPm, MEM_BLOCK_ALL, dest_modid, 16871 &voq_mod_map_entry)); 16872 16873 intf_index = _bcm_mn_msg_buf_get(unit, fabric_modid); 16874 if (intf_index < 0) { 16875 return BCM_E_INTERNAL; 16876 } 16877 16878 cng_offset = intf_index * 64 * 2; 16879 16880 BCM_IF_ERROR_RETURN 16881 (soc_mem_read(unit, MMU_INTFI_BASE_INDEX_TBLm, 16882 MEM_BLOCK_ALL, fabric_modid, &base_tbl_entry)); 16883 16884 soc_mem_field32_set(unit, MMU_INTFI_BASE_INDEX_TBLm, &base_tbl_entry, 16885 BASE_ADDRf, cng_offset); 16886 soc_mem_field32_set(unit, MMU_INTFI_BASE_INDEX_TBLm, &base_tbl_entry, 16887 ENf, 2); 16888 16889 BCM_IF_ERROR_RETURN(soc_mem_write(unit, MMU_INTFI_BASE_INDEX_TBLm, 16890 MEM_BLOCK_ALL, fabric_modid, &base_tbl_entry)); 16891 16892 /* set the mapping from congestion bits in flow control table 16893 * to corresponding cosq. */ 16894 BCM_IF_ERROR_RETURN(_bcm_mn_map_fc_status_to_node(unit, local_port, 16895 _BCM_MN_COSQ_FC_VOQFC, cng_offset + map_offset, 16896 cosq, node->hw_index, SOC_MONTEREY_NODE_LVL_L2)); 16897 16898 #ifdef DEBUG_MN_COSQ 16899 LOG_CLI((BSL_META_U(unit, 16900 "Gport=0x%08x hw_index=%d cosq=%d\n"), 16901 gport, node->hw_index, cosq)); 16902 #endif 16903 16904 return BCM_E_NONE; 16905 } 16906 16907 int bcm_mn_cosq_gport_congestion_config_set(int unit, bcm_gport_t gport, 16908 bcm_cos_queue_t cosq, 16909 bcm_cosq_congestion_info_t *config) 16910 { 16911 _bcm_mn_mmu_info_t *mmu_info; 16912 16913 if (!config) { 16914 return BCM_E_PARAM; 16915 } 16916 16917 if ((mmu_info = _bcm_mn_mmu_info[unit]) == NULL) { 16918 return BCM_E_INIT; 16919 } 16920 16921 /* determine if this gport is DPVOQ or DMVOQ */ 16922 if ((config->fabric_port != -1) && (config->dest_modid != -1)) { 16923 return _bcm_mn_gport_dmvoq_config_set(unit, gport, cosq, 16924 config->fabric_modid, 16925 config->dest_modid, 16926 config->fabric_port); 16927 } else if ((config->dest_modid != -1) && (config->dest_port != -1)) { 16928 return _bcm_mn_gport_dpvoq_config_set(unit, gport, cosq, 16929 config->dest_modid, 16930 config->dest_port); 16931 } 16932 16933 return BCM_E_PARAM; 16934 } 16935 16936 int bcm_mn_cosq_gport_congestion_config_get(int unit, bcm_gport_t port, 16937 bcm_cos_queue_t cosq, 16938 bcm_cosq_congestion_info_t *config) 16939 { 16940 _bcm_mn_mmu_info_t *mmu_info; 16941 bcm_port_t local_port; 16942 _bcm_mn_cosq_node_t *node; 16943 16944 if (!config) { 16945 return BCM_E_PARAM; 16946 } 16947 16948 if ((mmu_info = _bcm_mn_mmu_info[unit]) == NULL) { 16949 return BCM_E_INIT; 16950 } 16951 16952 BCM_IF_ERROR_RETURN 16953 (_bcm_mn_cosq_node_get(unit, port, 0, NULL, &local_port, NULL, &node)); 16954 16955 16956 if (!node) { 16957 return BCM_E_NOT_FOUND; 16958 } 16959 16960 config->dest_modid = node->remote_modid; 16961 config->dest_port = node->remote_port; 16962 16963 return BCM_E_NONE; 16964 } 16965 16966 16967 16968 int bcm_mn_cosq_bst_profile_set(int unit, 16969 bcm_gport_t port, 16970 bcm_cos_queue_t cosq, 16971 bcm_bst_stat_id_t bid, 16972 bcm_cosq_bst_profile_t *profile) 16973 { 16974 BCM_IF_ERROR_RETURN(_bcm_bst_cmn_profile_set 16975 (unit, port, cosq, BCM_BST_DUP_XPE, bid, profile)); 16976 return BCM_E_NONE; 16977 } 16978 16979 int bcm_mn_cosq_bst_profile_get(int unit, 16980 bcm_gport_t port, 16981 bcm_cos_queue_t cosq, 16982 bcm_bst_stat_id_t bid, 16983 bcm_cosq_bst_profile_t *profile) 16984 { 16985 BCM_IF_ERROR_RETURN(_bcm_bst_cmn_profile_get 16986 (unit, port, cosq, BCM_BST_DUP_XPE, bid, profile)); 16987 return BCM_E_NONE; 16988 } 16989 16990 int bcm_mn_cosq_bst_stat_get(int unit, 16991 bcm_gport_t port, 16992 bcm_cos_queue_t cosq, 16993 bcm_bst_stat_id_t bid, 16994 uint32 options, 16995 uint64 *pvalue) 16996 { 16997 return _bcm_bst_cmn_stat_get(unit, port, cosq,-1, bid, options, pvalue); 16998 } 16999 17000 int bcm_mn_cosq_bst_stat_multi_get(int unit, 17001 bcm_gport_t port, 17002 bcm_cos_queue_t cosq, 17003 uint32 options, 17004 int max_values, 17005 bcm_bst_stat_id_t *id_list, 17006 uint64 *pvalues) 17007 { 17008 return _bcm_bst_cmn_stat_multi_get(unit, port, cosq, options, max_values, 17009 id_list, pvalues); 17010 } 17011 17012 int bcm_mn_cosq_bst_stat_clear(int unit, bcm_gport_t port, 17013 bcm_cos_queue_t cosq, bcm_bst_stat_id_t bid) 17014 { 17015 return _bcm_bst_cmn_stat_clear(unit, port, cosq, bid); 17016 } 17017 17018 int bcm_mn_cosq_bst_stat_sync(int unit, bcm_bst_stat_id_t bid) 17019 { 17020 return _bcm_bst_cmn_stat_sync(unit, bid); 17021 } 17022 17023 17024 /* 17025 * Function: 17026 * _bcm_mn_cosq_endpoint_l2_create 17027 * Purpose: 17028 * Create a L2 endpoint. 17029 * Parameters: 17030 * unit - (IN) Unit number. 17031 * endpoint_id - (IN) Endpoint ID 17032 * vlan - (IN) VLAN 17033 * mac - (IN) MAC address 17034 * Returns: 17035 * BCM_E_xxx 17036 */ 17037 STATIC int 17038 _bcm_mn_cosq_endpoint_l2_create( 17039 int unit, 17040 int endpoint_id, 17041 bcm_vlan_t vlan, 17042 bcm_mac_t mac) 17043 { 17044 int rv; 17045 bcm_l2_addr_t l2addr; 17046 l2_endpoint_id_entry_t l2_endpoint_entry; 17047 int vfi; 17048 17049 /* Make sure (vlan, mac) entry is already in L2 table */ 17050 rv = bcm_esw_l2_addr_get(unit, mac, vlan, &l2addr); 17051 if (rv == BCM_E_NOT_FOUND) { 17052 /* The (vlan, mac) entry needs to be added to L2 table 17053 * before configuring it for endpoint queuing. 17054 */ 17055 return BCM_E_CONFIG; 17056 } else if (BCM_FAILURE(rv)) { 17057 return rv; 17058 } 17059 17060 /* Add (vlan, mac) entry to L2_ENDPOINT_ID table */ 17061 sal_memcpy(&l2_endpoint_entry, soc_mem_entry_null(unit, L2_ENDPOINT_IDm), 17062 sizeof(l2_endpoint_id_entry_t)); 17063 soc_L2_ENDPOINT_IDm_field32_set(unit, &l2_endpoint_entry, VALIDf, 1); 17064 if (_BCM_MPLS_VPN_IS_VPLS(vlan)) { 17065 _BCM_MPLS_VPN_GET(vfi, _BCM_MPLS_VPN_TYPE_VPLS, vlan); 17066 soc_L2_ENDPOINT_IDm_field32_set(unit, &l2_endpoint_entry, L2__VFIf, 17067 vfi); 17068 soc_L2_ENDPOINT_IDm_field32_set(unit, &l2_endpoint_entry, KEY_TYPEf, 17069 TD2_L2_HASH_KEY_TYPE_VFI); 17070 } else if (_BCM_IS_MIM_VPN(vlan)) { 17071 _BCM_MIM_VPN_GET(vfi, _BCM_MIM_VPN_TYPE_MIM, vlan); 17072 soc_L2_ENDPOINT_IDm_field32_set(unit, &l2_endpoint_entry, L2__VFIf, 17073 vfi); 17074 soc_L2_ENDPOINT_IDm_field32_set(unit, &l2_endpoint_entry, KEY_TYPEf, 17075 TD2_L2_HASH_KEY_TYPE_VFI); 17076 } else { 17077 VLAN_CHK_ID(unit, vlan); 17078 soc_L2_ENDPOINT_IDm_field32_set(unit, &l2_endpoint_entry, L2__VLAN_IDf, 17079 vlan); 17080 soc_L2_ENDPOINT_IDm_field32_set(unit, &l2_endpoint_entry, KEY_TYPEf, 17081 TD2_L2_HASH_KEY_TYPE_BRIDGE); 17082 } 17083 soc_L2_ENDPOINT_IDm_mac_addr_set(unit, &l2_endpoint_entry, L2__MAC_ADDRf, 17084 mac); 17085 soc_L2_ENDPOINT_IDm_field32_set(unit, &l2_endpoint_entry, EH_TAG_TYPEf, 2); 17086 soc_L2_ENDPOINT_IDm_field32_set(unit, &l2_endpoint_entry, EH_QUEUE_TAGf, 17087 endpoint_id); 17088 SOC_IF_ERROR_RETURN(soc_mem_insert(unit, L2_ENDPOINT_IDm, MEM_BLOCK_ANY, 17089 &l2_endpoint_entry)); 17090 17091 return BCM_E_NONE; 17092 } 17093 17094 /* 17095 * Function: 17096 * _bcm_mn_cosq_endpoint_l2_destroy 17097 * Purpose: 17098 * Destroy a L2 endpoint. 17099 * Parameters: 17100 * unit - (IN) Unit number. 17101 * vlan - (IN) VLAN 17102 * mac - (IN) MAC address 17103 * Returns: 17104 * BCM_E_xxx 17105 */ 17106 STATIC int 17107 _bcm_mn_cosq_endpoint_l2_destroy( 17108 int unit, 17109 bcm_vlan_t vlan, 17110 bcm_mac_t mac) 17111 { 17112 l2_endpoint_id_entry_t l2_endpoint_entry; 17113 int vfi; 17114 17115 /* Delete (vlan, mac) entry from L2_ENDPOINT_ID table */ 17116 sal_memcpy(&l2_endpoint_entry, soc_mem_entry_null(unit, L2_ENDPOINT_IDm), 17117 sizeof(l2_endpoint_id_entry_t)); 17118 if (_BCM_MPLS_VPN_IS_VPLS(vlan)) { 17119 _BCM_MPLS_VPN_GET(vfi, _BCM_MPLS_VPN_TYPE_VPLS, vlan); 17120 soc_L2_ENDPOINT_IDm_field32_set(unit, &l2_endpoint_entry, L2__VFIf, 17121 vfi); 17122 soc_L2_ENDPOINT_IDm_field32_set(unit, &l2_endpoint_entry, KEY_TYPEf, 17123 TD2_L2_HASH_KEY_TYPE_VFI); 17124 } else if (_BCM_IS_MIM_VPN(vlan)) { 17125 _BCM_MIM_VPN_GET(vfi, _BCM_MIM_VPN_TYPE_MIM, vlan); 17126 soc_L2_ENDPOINT_IDm_field32_set(unit, &l2_endpoint_entry, L2__VFIf, 17127 vfi); 17128 soc_L2_ENDPOINT_IDm_field32_set(unit, &l2_endpoint_entry, KEY_TYPEf, 17129 TD2_L2_HASH_KEY_TYPE_VFI); 17130 } else { 17131 VLAN_CHK_ID(unit, vlan); 17132 soc_L2_ENDPOINT_IDm_field32_set(unit, &l2_endpoint_entry, L2__VLAN_IDf, 17133 vlan); 17134 soc_L2_ENDPOINT_IDm_field32_set(unit, &l2_endpoint_entry, KEY_TYPEf, 17135 TD2_L2_HASH_KEY_TYPE_BRIDGE); 17136 } 17137 soc_L2_ENDPOINT_IDm_mac_addr_set(unit, &l2_endpoint_entry, L2__MAC_ADDRf, 17138 mac); 17139 SOC_IF_ERROR_RETURN(soc_mem_delete(unit, L2_ENDPOINT_IDm, MEM_BLOCK_ANY, 17140 &l2_endpoint_entry)); 17141 17142 return BCM_E_NONE; 17143 } 17144 17145 #ifdef INCLUDE_L3 17146 /* 17147 * Function: 17148 * _bcm_mn_cosq_endpoint_ip4_create 17149 * Purpose: 17150 * Create an IPv4 endpoint. 17151 * Parameters: 17152 * unit - (IN) Unit number. 17153 * endpoint_id - (IN) Endpoint ID 17154 * vrf - (IN) Virtual router instance 17155 * ip_addr - (IN) IPv4 address 17156 * Returns: 17157 * BCM_E_xxx 17158 */ 17159 STATIC int 17160 _bcm_mn_cosq_endpoint_ip4_create( 17161 int unit, 17162 int endpoint_id, 17163 bcm_vrf_t vrf, 17164 bcm_ip_t ip_addr) 17165 { 17166 int rv; 17167 _bcm_l3_cfg_t l3cfg; 17168 17169 if ((vrf > SOC_VRF_MAX(unit)) || 17170 (vrf < BCM_L3_VRF_DEFAULT)) { 17171 return BCM_E_PARAM; 17172 } 17173 17174 L3_LOCK(unit); 17175 17176 /* Make sure (vrf, ip_addr) entry is already in L3 host table */ 17177 sal_memset(&l3cfg, 0, sizeof(_bcm_l3_cfg_t)); 17178 l3cfg.l3c_vrf = vrf; 17179 l3cfg.l3c_ip_addr = ip_addr; 17180 rv = mbcm_driver[unit]->mbcm_l3_ip4_get(unit, &l3cfg); 17181 if (rv == BCM_E_NOT_FOUND) { 17182 /* The (vrf, ip_addr) entry needs to be added to L3 table 17183 * before configuring it for endpoint queuing. 17184 */ 17185 L3_UNLOCK(unit); 17186 return BCM_E_CONFIG; 17187 } else if (BCM_FAILURE(rv)) { 17188 L3_UNLOCK(unit); 17189 return rv; 17190 } 17191 17192 if (l3cfg.l3c_eh_q_tag_type != 0) { 17193 /* A queue tag has already been configured for this L3 entry. */ 17194 L3_UNLOCK(unit); 17195 return BCM_E_EXISTS; 17196 } 17197 17198 /* Replace (vrf, ip_addr) entry's endpoint_id */ 17199 l3cfg.l3c_flags |= BCM_L3_REPLACE; 17200 l3cfg.l3c_eh_q_tag_type = 2; 17201 l3cfg.l3c_eh_q_tag = endpoint_id; 17202 rv = mbcm_driver[unit]->mbcm_l3_ip4_replace(unit, &l3cfg); 17203 if (BCM_FAILURE(rv)) { 17204 L3_UNLOCK(unit); 17205 return rv; 17206 } 17207 17208 L3_UNLOCK(unit); 17209 17210 return rv; 17211 } 17212 17213 /* 17214 * Function: 17215 * _bcm_mn_cosq_endpoint_ip4_destroy 17216 * Purpose: 17217 * Destroy an IPv4 endpoint. 17218 * Parameters: 17219 * unit - (IN) Unit number. 17220 * vrf - (IN) Virtual router instance 17221 * ip_addr - (IN) IPv4 address 17222 * Returns: 17223 * BCM_E_xxx 17224 */ 17225 STATIC int 17226 _bcm_mn_cosq_endpoint_ip4_destroy( 17227 int unit, 17228 bcm_vrf_t vrf, 17229 bcm_ip_t ip_addr) 17230 { 17231 int rv; 17232 _bcm_l3_cfg_t l3cfg; 17233 17234 if ((vrf > SOC_VRF_MAX(unit)) || 17235 (vrf < BCM_L3_VRF_DEFAULT)) { 17236 return BCM_E_PARAM; 17237 } 17238 17239 L3_LOCK(unit); 17240 17241 /* Get (vrf, ip_addr) entry */ 17242 sal_memset(&l3cfg, 0, sizeof(_bcm_l3_cfg_t)); 17243 l3cfg.l3c_vrf = vrf; 17244 l3cfg.l3c_ip_addr = ip_addr; 17245 rv = mbcm_driver[unit]->mbcm_l3_ip4_get(unit, &l3cfg); 17246 if (BCM_FAILURE(rv)) { 17247 L3_UNLOCK(unit); 17248 return rv; 17249 } 17250 17251 /* Delete (vrf, ip_addr) entry's endpoint_id */ 17252 l3cfg.l3c_flags |= BCM_L3_REPLACE; 17253 l3cfg.l3c_eh_q_tag_type = 0; 17254 l3cfg.l3c_eh_q_tag = 0; 17255 rv = mbcm_driver[unit]->mbcm_l3_ip4_replace(unit, &l3cfg); 17256 if (BCM_FAILURE(rv)) { 17257 L3_UNLOCK(unit); 17258 return rv; 17259 } 17260 17261 L3_UNLOCK(unit); 17262 17263 return rv; 17264 } 17265 17266 /* 17267 * Function: 17268 * _bcm_mn_cosq_endpoint_ip6_create 17269 * Purpose: 17270 * Create an IPv6 endpoint. 17271 * Parameters: 17272 * unit - (IN) Unit number. 17273 * endpoint_id - (IN) Endpoint ID 17274 * vrf - (IN) Virtual router instance 17275 * ip6_addr - (IN) IPv6 address 17276 * Returns: 17277 * BCM_E_xxx 17278 */ 17279 STATIC int 17280 _bcm_mn_cosq_endpoint_ip6_create( 17281 int unit, 17282 int endpoint_id, 17283 bcm_vrf_t vrf, 17284 bcm_ip6_t ip6_addr) 17285 { 17286 int rv; 17287 _bcm_l3_cfg_t l3cfg; 17288 17289 if ((vrf > SOC_VRF_MAX(unit)) || 17290 (vrf < BCM_L3_VRF_DEFAULT)) { 17291 return BCM_E_PARAM; 17292 } 17293 17294 L3_LOCK(unit); 17295 17296 /* Make sure (vrf, ip6_addr) entry is already in L3 host table */ 17297 sal_memset(&l3cfg, 0, sizeof(_bcm_l3_cfg_t)); 17298 l3cfg.l3c_flags = BCM_L3_IP6; 17299 l3cfg.l3c_vrf = vrf; 17300 sal_memcpy(l3cfg.l3c_ip6, ip6_addr, BCM_IP6_ADDRLEN); 17301 rv = mbcm_driver[unit]->mbcm_l3_ip6_get(unit, &l3cfg); 17302 if (rv == BCM_E_NOT_FOUND) { 17303 /* The (vrf, ip6_addr) entry needs to be added to L3 table 17304 * before configuring it for endpoint queuing. 17305 */ 17306 L3_UNLOCK(unit); 17307 return BCM_E_CONFIG; 17308 } else if (BCM_FAILURE(rv)) { 17309 L3_UNLOCK(unit); 17310 return rv; 17311 } 17312 17313 if (l3cfg.l3c_eh_q_tag_type != 0) { 17314 /* A queue tag has already been configured for this L3 entry. */ 17315 L3_UNLOCK(unit); 17316 return BCM_E_EXISTS; 17317 } 17318 17319 /* Replace (vrf, ip_addr) entry's endpoint_id */ 17320 l3cfg.l3c_flags |= BCM_L3_REPLACE; 17321 l3cfg.l3c_eh_q_tag_type = 2; 17322 l3cfg.l3c_eh_q_tag = endpoint_id; 17323 rv = mbcm_driver[unit]->mbcm_l3_ip6_replace(unit, &l3cfg); 17324 if (BCM_FAILURE(rv)) { 17325 L3_UNLOCK(unit); 17326 return rv; 17327 } 17328 17329 L3_UNLOCK(unit); 17330 17331 return rv; 17332 } 17333 17334 /* 17335 * Function: 17336 * _bcm_mn_cosq_endpoint_ip6_destroy 17337 * Purpose: 17338 * Destroy an IPv6 endpoint. 17339 * Parameters: 17340 * unit - (IN) Unit number. 17341 * vrf - (IN) Virtual router instance 17342 * ip6_addr - (IN) IPv6 address 17343 * Returns: 17344 * BCM_E_xxx 17345 */ 17346 STATIC int 17347 _bcm_mn_cosq_endpoint_ip6_destroy( 17348 int unit, 17349 bcm_vrf_t vrf, 17350 bcm_ip6_t ip6_addr) 17351 { 17352 int rv; 17353 _bcm_l3_cfg_t l3cfg; 17354 17355 if ((vrf > SOC_VRF_MAX(unit)) || 17356 (vrf < BCM_L3_VRF_DEFAULT)) { 17357 return BCM_E_PARAM; 17358 } 17359 17360 L3_LOCK(unit); 17361 17362 /* Get (vrf, ip6_addr) entry */ 17363 sal_memset(&l3cfg, 0, sizeof(_bcm_l3_cfg_t)); 17364 l3cfg.l3c_flags = BCM_L3_IP6; 17365 l3cfg.l3c_vrf = vrf; 17366 sal_memcpy(l3cfg.l3c_ip6, ip6_addr, BCM_IP6_ADDRLEN); 17367 rv = mbcm_driver[unit]->mbcm_l3_ip6_get(unit, &l3cfg); 17368 if (BCM_FAILURE(rv)) { 17369 L3_UNLOCK(unit); 17370 return rv; 17371 } 17372 17373 /* Delete (vrf, ip_addr) entry's endpoint_id */ 17374 l3cfg.l3c_flags |= BCM_L3_REPLACE; 17375 l3cfg.l3c_eh_q_tag_type = 0; 17376 l3cfg.l3c_eh_q_tag = 0; 17377 rv = mbcm_driver[unit]->mbcm_l3_ip6_replace(unit, &l3cfg); 17378 if (BCM_FAILURE(rv)) { 17379 L3_UNLOCK(unit); 17380 return rv; 17381 } 17382 17383 L3_UNLOCK(unit); 17384 17385 return rv; 17386 } 17387 17388 #endif /* INCLUDE_L3 */ 17389 17390 /* 17391 * Function: 17392 * _bcm_mn_cosq_endpoint_gport_create 17393 * Purpose: 17394 * Create a GPORT endpoint. 17395 * Parameters: 17396 * unit - (IN) Unit number. 17397 * endpoint_id - (IN) Endpoint ID 17398 * gport - (IN) GPORT ID 17399 * Returns: 17400 * BCM_E_xxx 17401 */ 17402 STATIC int 17403 _bcm_mn_cosq_endpoint_gport_create( 17404 int unit, 17405 int endpoint_id, 17406 bcm_gport_t gport) 17407 { 17408 int vp; 17409 ing_dvp_table_entry_t dvp_entry; 17410 int nh_index; 17411 ing_l3_next_hop_entry_t nh_entry; 17412 int eh_tag_type; 17413 17414 /* Get virtual port value */ 17415 if (BCM_GPORT_IS_VLAN_PORT(gport)) { 17416 vp = BCM_GPORT_VLAN_PORT_ID_GET(gport); 17417 #if defined(INCLUDE_L3) 17418 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeVlan)) { 17419 /* VP is not configured yet */ 17420 return BCM_E_CONFIG; 17421 } 17422 #endif 17423 } else if (BCM_GPORT_IS_NIV_PORT(gport)) { 17424 vp = BCM_GPORT_NIV_PORT_ID_GET(gport); 17425 #if defined(INCLUDE_L3) 17426 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeNiv)) { 17427 /* VP is not configured yet */ 17428 return BCM_E_CONFIG; 17429 } 17430 #endif 17431 } else { 17432 return BCM_E_PARAM; 17433 } 17434 17435 /* Get VP's next hop index */ 17436 BCM_IF_ERROR_RETURN 17437 (READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp_entry)); 17438 nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp_entry, 17439 NEXT_HOP_INDEXf); 17440 17441 /* Set endpoint ID in next hop entry */ 17442 BCM_IF_ERROR_RETURN 17443 (READ_ING_L3_NEXT_HOPm(unit, MEM_BLOCK_ANY, nh_index, &nh_entry)); 17444 eh_tag_type = soc_ING_L3_NEXT_HOPm_field32_get(unit, &nh_entry, 17445 EH_TAG_TYPEf); 17446 if (eh_tag_type != 0) { 17447 /* A queue tag has already been configured for this next hop entry. */ 17448 return BCM_E_EXISTS; 17449 } 17450 soc_ING_L3_NEXT_HOPm_field32_set(unit, &nh_entry, EH_TAG_TYPEf, 2); 17451 soc_ING_L3_NEXT_HOPm_field32_set(unit, &nh_entry, EH_QUEUE_TAGf, endpoint_id); 17452 BCM_IF_ERROR_RETURN 17453 (WRITE_ING_L3_NEXT_HOPm(unit, MEM_BLOCK_ALL, nh_index, &nh_entry)); 17454 17455 return BCM_E_NONE; 17456 } 17457 17458 /* 17459 * Function: 17460 * _bcm_mn_cosq_endpoint_gport_destroy 17461 * Purpose: 17462 * Destroy a GPORT endpoint. 17463 * Parameters: 17464 * unit - (IN) Unit number. 17465 * gport - (IN) GPORT ID 17466 * Returns: 17467 * BCM_E_xxx 17468 */ 17469 STATIC int 17470 _bcm_mn_cosq_endpoint_gport_destroy( 17471 int unit, 17472 bcm_gport_t gport) 17473 { 17474 int vp; 17475 ing_dvp_table_entry_t dvp_entry; 17476 int nh_index; 17477 ing_l3_next_hop_entry_t nh_entry; 17478 17479 /* Get virtual port value */ 17480 if (BCM_GPORT_IS_VLAN_PORT(gport)) { 17481 vp = BCM_GPORT_VLAN_PORT_ID_GET(gport); 17482 #if defined(INCLUDE_L3) 17483 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeVlan)) { 17484 /* VP is not configured yet */ 17485 return BCM_E_CONFIG; 17486 } 17487 #endif 17488 } else if (BCM_GPORT_IS_NIV_PORT(gport)) { 17489 vp = BCM_GPORT_NIV_PORT_ID_GET(gport); 17490 #if defined(INCLUDE_L3) 17491 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeNiv)) { 17492 /* VP is not configured yet */ 17493 return BCM_E_CONFIG; 17494 } 17495 #endif 17496 } else { 17497 return BCM_E_PARAM; 17498 } 17499 17500 /* Get VP's next hop index */ 17501 BCM_IF_ERROR_RETURN 17502 (READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp_entry)); 17503 nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp_entry, 17504 NEXT_HOP_INDEXf); 17505 17506 /* Delete endpoint ID in next hop entry */ 17507 BCM_IF_ERROR_RETURN 17508 (READ_ING_L3_NEXT_HOPm(unit, MEM_BLOCK_ANY, nh_index, &nh_entry)); 17509 soc_ING_L3_NEXT_HOPm_field32_set(unit, &nh_entry, EH_TAG_TYPEf, 0); 17510 soc_ING_L3_NEXT_HOPm_field32_set(unit, &nh_entry, EH_QUEUE_TAGf, 0); 17511 BCM_IF_ERROR_RETURN 17512 (WRITE_ING_L3_NEXT_HOPm(unit, MEM_BLOCK_ALL, nh_index, &nh_entry)); 17513 17514 return BCM_E_NONE; 17515 } 17516 17517 /* 17518 * Function: 17519 * bcm_mn_cosq_endpoint_create 17520 * Purpose: 17521 * Create an endpoint. 17522 * Parameters: 17523 * unit - (IN) Unit number. 17524 * classifier - (IN) Classifier attributes 17525 * classifier_id - (IN/OUT) Classifier ID 17526 * Returns: 17527 * BCM_E_xxx 17528 */ 17529 int 17530 bcm_mn_cosq_endpoint_create( 17531 int unit, 17532 bcm_cosq_classifier_t *classifier, 17533 int *classifier_id) 17534 { 17535 int endpoint_id = 0; 17536 int i; 17537 17538 if (NULL == classifier || NULL == classifier_id) { 17539 return BCM_E_PARAM; 17540 } 17541 17542 if (classifier->flags & BCM_COSQ_CLASSIFIER_WITH_ID) { 17543 if (!_BCM_COSQ_CLASSIFIER_IS_ENDPOINT(*classifier_id)) { 17544 return BCM_E_PARAM; 17545 } 17546 endpoint_id = _BCM_COSQ_CLASSIFIER_ENDPOINT_GET(*classifier_id); 17547 if (endpoint_id >= _BCM_MN_NUM_ENDPOINT(unit)) { 17548 return BCM_E_PARAM; 17549 } 17550 if (_BCM_MN_ENDPOINT_IS_USED(unit, endpoint_id)) { 17551 return BCM_E_EXISTS; 17552 } 17553 } else { 17554 /* Get a free endpoint ID */ 17555 for (i = 0; i < _BCM_MN_NUM_ENDPOINT(unit); i++) { 17556 if (!_BCM_MN_ENDPOINT_IS_USED(unit, i)) { 17557 endpoint_id = i; 17558 break; 17559 } 17560 } 17561 if (i == _BCM_MN_NUM_ENDPOINT(unit)) { 17562 /* No available endpoint ID */ 17563 return BCM_E_RESOURCE; 17564 } 17565 } 17566 _BCM_MN_ENDPOINT(unit, endpoint_id) = sal_alloc( 17567 sizeof(_bcm_mn_endpoint_t), "Endpoint Info"); 17568 if (NULL == _BCM_MN_ENDPOINT(unit, endpoint_id)) { 17569 return BCM_E_MEMORY; 17570 } 17571 sal_memset(_BCM_MN_ENDPOINT(unit, endpoint_id), 0, 17572 sizeof(_bcm_mn_endpoint_t)); 17573 17574 if (classifier->flags & BCM_COSQ_CLASSIFIER_L2) { 17575 _BCM_MN_ENDPOINT(unit, endpoint_id)->flags = BCM_COSQ_CLASSIFIER_L2; 17576 _BCM_MN_ENDPOINT(unit, endpoint_id)->vlan = classifier->vlan; 17577 sal_memcpy(_BCM_MN_ENDPOINT(unit, endpoint_id)->mac, classifier->mac, 17578 sizeof(bcm_mac_t)); 17579 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_endpoint_l2_create(unit, 17580 endpoint_id, classifier->vlan, classifier->mac)); 17581 } else if (classifier->flags & BCM_COSQ_CLASSIFIER_L3) { 17582 #if defined(INCLUDE_L3) 17583 _BCM_MN_ENDPOINT(unit, endpoint_id)->flags = BCM_COSQ_CLASSIFIER_L3; 17584 _BCM_MN_ENDPOINT(unit, endpoint_id)->vrf = classifier->vrf; 17585 if (classifier->flags & BCM_COSQ_CLASSIFIER_IP6) { 17586 _BCM_MN_ENDPOINT(unit, endpoint_id)->flags |= BCM_COSQ_CLASSIFIER_IP6; 17587 sal_memcpy(_BCM_MN_ENDPOINT(unit, endpoint_id)->ip6_addr, 17588 classifier->ip6_addr, BCM_IP6_ADDRLEN); 17589 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_endpoint_ip6_create(unit, 17590 endpoint_id, classifier->vrf, classifier->ip6_addr)); 17591 } else { 17592 _BCM_MN_ENDPOINT(unit, endpoint_id)->ip_addr = classifier->ip_addr; 17593 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_endpoint_ip4_create(unit, 17594 endpoint_id, classifier->vrf, classifier->ip_addr)); 17595 } 17596 #endif /* INCLUDE_L3 */ 17597 } else if (classifier->flags & BCM_COSQ_CLASSIFIER_GPORT) { 17598 _BCM_MN_ENDPOINT(unit, endpoint_id)->flags = BCM_COSQ_CLASSIFIER_GPORT; 17599 _BCM_MN_ENDPOINT(unit, endpoint_id)->gport = classifier->gport; 17600 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_endpoint_gport_create(unit, 17601 endpoint_id, classifier->gport)); 17602 } else { 17603 return BCM_E_PARAM; 17604 } 17605 17606 _BCM_COSQ_CLASSIFIER_ENDPOINT_SET(*classifier_id, endpoint_id); 17607 17608 return BCM_E_NONE; 17609 } 17610 17611 /* 17612 * Function: 17613 * bcm_mn_cosq_endpoint_destroy 17614 * Purpose: 17615 * Destroy an endpoint. 17616 * Parameters: 17617 * unit - (IN) Unit number. 17618 * classifier_id - (IN) Classifier ID 17619 * Returns: 17620 * BCM_E_xxx 17621 */ 17622 int 17623 bcm_mn_cosq_endpoint_destroy( 17624 int unit, 17625 int classifier_id) 17626 { 17627 int endpoint_id; 17628 17629 if (!_BCM_COSQ_CLASSIFIER_IS_ENDPOINT(classifier_id)) { 17630 return BCM_E_PARAM; 17631 } 17632 endpoint_id = _BCM_COSQ_CLASSIFIER_ENDPOINT_GET(classifier_id); 17633 if (endpoint_id >= _BCM_MN_NUM_ENDPOINT(unit)) { 17634 return BCM_E_PARAM; 17635 } 17636 if (!_BCM_MN_ENDPOINT_IS_USED(unit, endpoint_id)) { 17637 return BCM_E_NOT_FOUND; 17638 } 17639 17640 if (_BCM_MN_ENDPOINT(unit, endpoint_id)->flags & 17641 BCM_COSQ_CLASSIFIER_L2) { 17642 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_endpoint_l2_destroy(unit, 17643 _BCM_MN_ENDPOINT(unit, endpoint_id)->vlan, 17644 _BCM_MN_ENDPOINT(unit, endpoint_id)->mac)); 17645 } else if (_BCM_MN_ENDPOINT(unit, endpoint_id)->flags & 17646 BCM_COSQ_CLASSIFIER_L3) { 17647 #if defined(INCLUDE_L3) 17648 if (_BCM_MN_ENDPOINT(unit, endpoint_id)->flags & 17649 BCM_COSQ_CLASSIFIER_IP6) { 17650 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_endpoint_ip6_destroy(unit, 17651 _BCM_MN_ENDPOINT(unit, endpoint_id)->vrf, 17652 _BCM_MN_ENDPOINT(unit, endpoint_id)->ip6_addr)); 17653 } else { 17654 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_endpoint_ip4_destroy(unit, 17655 _BCM_MN_ENDPOINT(unit, endpoint_id)->vrf, 17656 _BCM_MN_ENDPOINT(unit, endpoint_id)->ip_addr)); 17657 } 17658 #endif 17659 } else if (_BCM_MN_ENDPOINT(unit, endpoint_id)->flags & 17660 BCM_COSQ_CLASSIFIER_GPORT) { 17661 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_endpoint_gport_destroy(unit, 17662 _BCM_MN_ENDPOINT(unit, endpoint_id)->gport)); 17663 } else { 17664 return BCM_E_INTERNAL; 17665 } 17666 17667 sal_free(_BCM_MN_ENDPOINT(unit, endpoint_id)); 17668 _BCM_MN_ENDPOINT(unit, endpoint_id) = NULL; 17669 17670 return BCM_E_NONE; 17671 } 17672 17673 /* 17674 * Function: 17675 * bcm_mn_cosq_endpoint_get 17676 * Purpose: 17677 * Get info about an endpoint. 17678 * Parameters: 17679 * unit - (IN) Unit number. 17680 * classifier_id - (IN) Classifier ID 17681 * classifier - (OUT) Classifier info 17682 * Returns: 17683 * BCM_E_xxx 17684 */ 17685 int 17686 bcm_mn_cosq_endpoint_get( 17687 int unit, 17688 int classifier_id, 17689 bcm_cosq_classifier_t *classifier) 17690 { 17691 int endpoint_id; 17692 17693 if (!_BCM_COSQ_CLASSIFIER_IS_ENDPOINT(classifier_id)) { 17694 return BCM_E_PARAM; 17695 } 17696 endpoint_id = _BCM_COSQ_CLASSIFIER_ENDPOINT_GET(classifier_id); 17697 if (endpoint_id >= _BCM_MN_NUM_ENDPOINT(unit)) { 17698 return BCM_E_PARAM; 17699 } 17700 if (!_BCM_MN_ENDPOINT_IS_USED(unit, endpoint_id)) { 17701 return BCM_E_NOT_FOUND; 17702 } 17703 17704 classifier->flags = _BCM_MN_ENDPOINT(unit, endpoint_id)->flags; 17705 classifier->vlan = _BCM_MN_ENDPOINT(unit, endpoint_id)->vlan; 17706 sal_memcpy(classifier->mac, _BCM_MN_ENDPOINT(unit, endpoint_id)->mac, 17707 sizeof(bcm_mac_t)); 17708 classifier->vrf = _BCM_MN_ENDPOINT(unit, endpoint_id)->vrf; 17709 classifier->ip_addr = _BCM_MN_ENDPOINT(unit, endpoint_id)->ip_addr; 17710 sal_memcpy(classifier->ip6_addr, 17711 _BCM_MN_ENDPOINT(unit, endpoint_id)->ip6_addr, BCM_IP6_ADDRLEN); 17712 classifier->gport = _BCM_MN_ENDPOINT(unit, endpoint_id)->gport; 17713 17714 return BCM_E_NONE; 17715 } 17716 /* 17717 * Function: 17718 * bcm_mn_cosq_endpoint_map_set 17719 * Purpose: 17720 * Set the mapping from port, classifier, and multiple internal priorities 17721 * to multiple COS queues in a queue group. 17722 * Parameters: 17723 * unit - (IN) Unit number. 17724 * port - (IN) local port ID 17725 * classifier_id - (IN) Classifier ID 17726 * queue_group - (IN) Base queue ID 17727 * array_count - (IN) Number of elements in priority_array and 17728 * cosq_array 17729 * priority_array - (IN) Array of internal priorities 17730 * cosq_array - (IN) Array of COS queues 17731 * Returns: 17732 * BCM_E_xxx 17733 */ 17734 int 17735 bcm_mn_cosq_endpoint_map_set( 17736 int unit, 17737 bcm_port_t port, 17738 int classifier_id, 17739 bcm_gport_t queue_group, 17740 int array_count, 17741 bcm_cos_t *priority_array, 17742 bcm_cos_queue_t *cosq_array) 17743 { 17744 int rv = BCM_E_NONE; 17745 int endpoint_id; 17746 int qid; 17747 int num_entries_per_profile; 17748 int alloc_size; 17749 endpoint_cos_map_entry_t *entry_array = NULL; 17750 void *entries[1]; 17751 endpoint_queue_map_entry_t qmap_key, qmap_data, qmap_entry; 17752 int qmap_index; 17753 int old_profile_index, new_profile_index; 17754 int old_qid; 17755 int i; 17756 int priority; 17757 uint64 rval64; 17758 uint32 endpoint_cos_map_prof_idx; 17759 if (!_BCM_COSQ_CLASSIFIER_IS_ENDPOINT(classifier_id)) { 17760 return BCM_E_PARAM; 17761 } 17762 endpoint_id = _BCM_COSQ_CLASSIFIER_ENDPOINT_GET(classifier_id); 17763 if (endpoint_id >= _BCM_MN_NUM_ENDPOINT(unit)) { 17764 return BCM_E_PARAM; 17765 } 17766 if (!_BCM_MN_ENDPOINT_IS_USED(unit, endpoint_id)) { 17767 return BCM_E_PARAM; 17768 } 17769 17770 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(queue_group)) { 17771 qid = BCM_GPORT_UCAST_QUEUE_GROUP_QID_GET(queue_group); 17772 } else { 17773 return BCM_E_PARAM; 17774 } 17775 17776 /* Allocate an Endpoint CoS Map profile */ 17777 num_entries_per_profile = 16; 17778 alloc_size = sizeof(endpoint_cos_map_entry_t) * num_entries_per_profile; 17779 entry_array = sal_alloc(alloc_size, "Endpoint CoS Map Profile"); 17780 if (NULL == entry_array) { 17781 return BCM_E_MEMORY; 17782 } 17783 sal_memset(entry_array, 0, alloc_size); 17784 17785 /* Search Endpoint Queue Map table */ 17786 sal_memcpy(&qmap_key, soc_mem_entry_null(unit, 17787 ENDPOINT_QUEUE_MAPm), sizeof(endpoint_queue_map_entry_t)); 17788 soc_ENDPOINT_QUEUE_MAPm_field32_set(unit, &qmap_key, KEY_TYPEf, 0); 17789 soc_ENDPOINT_QUEUE_MAPm_field32_set(unit, &qmap_key, DEST_PORTf, port); 17790 soc_ENDPOINT_QUEUE_MAPm_field32_set(unit, &qmap_key, EH_QUEUE_TAGf, 17791 endpoint_id); 17792 rv = soc_mem_search(unit, ENDPOINT_QUEUE_MAPm, MEM_BLOCK_ANY, 17793 &qmap_index, &qmap_key, &qmap_data, 0); 17794 if (rv == SOC_E_NOT_FOUND) { 17795 old_profile_index = -1; 17796 } else if (rv == SOC_E_NONE) { 17797 /* Existing entry found. Compare base queue ID and extract 17798 * old Endpoint CoS Map profile. 17799 */ 17800 old_qid = soc_ENDPOINT_QUEUE_MAPm_field32_get(unit, 17801 &qmap_data, ENDPOINT_QUEUE_BASEf); 17802 if (old_qid != qid) { 17803 /* The classifier is already mapped to another queue group */ 17804 sal_free(entry_array); 17805 return BCM_E_EXISTS; 17806 } 17807 endpoint_cos_map_prof_idx = soc_ENDPOINT_QUEUE_MAPm_field32_get(unit, 17808 &qmap_data, ENDPOINT_COS_MAP_PROFILE_INDEXf); 17809 entries[0] = entry_array; 17810 /* 17811 * The index of ENDPOINT_COS_MAP = 17812 * ENDPOINT_COS_MAP_PROFILE_INDEX * 16 + INT_PRI 17813 */ 17814 old_profile_index = endpoint_cos_map_prof_idx * num_entries_per_profile; 17815 rv = soc_profile_mem_get(unit, _BCM_MN_ENDPOINT_COS_MAP_PROFILE(unit), 17816 old_profile_index, num_entries_per_profile, entries); 17817 if (SOC_FAILURE(rv)) { 17818 sal_free(entry_array); 17819 return rv; 17820 } 17821 } else { 17822 sal_free(entry_array); 17823 return rv; 17824 } 17825 17826 /* Construct or modify Endpoint CoS Map profile and add it */ 17827 for (i = 0; i < array_count; i++) { 17828 priority = priority_array[i]; 17829 if ((priority < 0) || (priority >= 16)) { 17830 sal_free(entry_array); 17831 return BCM_E_PARAM; 17832 } 17833 soc_ENDPOINT_COS_MAPm_field32_set(unit, &entry_array[priority], 17834 ENDPOINT_COS_OFFSETf, cosq_array[i]); 17835 } 17836 entries[0] = entry_array; 17837 rv = soc_profile_mem_add(unit, _BCM_MN_ENDPOINT_COS_MAP_PROFILE(unit), 17838 entries, num_entries_per_profile, (uint32 *)&new_profile_index); 17839 sal_free(entry_array); 17840 if (SOC_FAILURE(rv)) { 17841 return rv; 17842 } 17843 17844 /* Insert or replace Endpoint Queue Map entry */ 17845 sal_memcpy(&qmap_entry, &qmap_key, sizeof(endpoint_queue_map_entry_t)); 17846 soc_ENDPOINT_QUEUE_MAPm_field32_set(unit, &qmap_entry, VALIDf, 1); 17847 soc_ENDPOINT_QUEUE_MAPm_field32_set(unit, &qmap_entry, 17848 ENDPOINT_QUEUE_BASEf, qid); 17849 endpoint_cos_map_prof_idx = new_profile_index / num_entries_per_profile; 17850 soc_ENDPOINT_QUEUE_MAPm_field32_set(unit, &qmap_entry, 17851 ENDPOINT_COS_MAP_PROFILE_INDEXf, endpoint_cos_map_prof_idx); 17852 rv = soc_mem_insert(unit, ENDPOINT_QUEUE_MAPm, MEM_BLOCK_ALL, &qmap_entry); 17853 if (SOC_FAILURE(rv) && rv != SOC_E_EXISTS) { 17854 return rv; 17855 } 17856 17857 /* Delete old Endpoint CoS Map profile */ 17858 if (old_profile_index != -1) { 17859 SOC_IF_ERROR_RETURN 17860 (soc_profile_mem_delete(unit, 17861 _BCM_MN_ENDPOINT_COS_MAP_PROFILE(unit), 17862 old_profile_index)); 17863 } 17864 17865 /* Set port's queuing mode to be endpoint queuing */ 17866 SOC_IF_ERROR_RETURN(READ_ING_COS_MODE_64r(unit, port, &rval64)); 17867 if (4 != soc_reg64_field32_get(unit, ING_COS_MODE_64r, rval64, 17868 QUEUE_MODEf)) { 17869 soc_reg64_field32_set(unit, ING_COS_MODE_64r, &rval64, QUEUE_MODEf, 4); 17870 SOC_IF_ERROR_RETURN(WRITE_ING_COS_MODE_64r(unit, port, rval64)); 17871 } 17872 17873 return rv; 17874 } 17875 17876 /* 17877 * Function: 17878 * bcm_mn_cosq_endpoint_map_get 17879 * Purpose: 17880 * Get the mapping from port, classifier, and multiple internal priorities 17881 * to multiple COS queues in a queue group. 17882 * Parameters: 17883 * unit - (IN) Unit number. 17884 * port - (IN) Local port ID 17885 * classifier_id - (IN) Classifier ID 17886 * queue_group - (OUT) Queue group 17887 * array_max - (IN) Size of priority_array and cosq_array 17888 * priority_array - (IN) Array of internal priorities 17889 * cosq_array - (OUT) Array of COS queues 17890 * array_count - (OUT) Size of cosq_array 17891 * Returns: 17892 * BCM_E_xxx 17893 */ 17894 int 17895 bcm_mn_cosq_endpoint_map_get( 17896 int unit, 17897 bcm_port_t port, 17898 int classifier_id, 17899 bcm_gport_t *queue_group, 17900 int array_max, 17901 bcm_cos_t *priority_array, 17902 bcm_cos_queue_t *cosq_array, 17903 int *array_count) 17904 { 17905 int rv = BCM_E_NONE; 17906 int endpoint_id; 17907 endpoint_queue_map_entry_t qmap_key, qmap_data; 17908 int qmap_index; 17909 int qid; 17910 int num_entries_per_profile; 17911 int alloc_size; 17912 endpoint_cos_map_entry_t *entry_array = NULL; 17913 void *entries[1]; 17914 int profile_index; 17915 int i; 17916 int priority; 17917 uint32 endpoint_cos_map_prof_idx; 17918 17919 if (!_BCM_COSQ_CLASSIFIER_IS_ENDPOINT(classifier_id)) { 17920 return BCM_E_PARAM; 17921 } 17922 endpoint_id = _BCM_COSQ_CLASSIFIER_ENDPOINT_GET(classifier_id); 17923 if (endpoint_id >= _BCM_MN_NUM_ENDPOINT(unit)) { 17924 return BCM_E_PARAM; 17925 } 17926 if (!_BCM_MN_ENDPOINT_IS_USED(unit, endpoint_id)) { 17927 return BCM_E_PARAM; 17928 } 17929 17930 /* Search Endpoint Queue Map table */ 17931 sal_memcpy(&qmap_key, soc_mem_entry_null(unit, 17932 ENDPOINT_QUEUE_MAPm), sizeof(endpoint_queue_map_entry_t)); 17933 soc_ENDPOINT_QUEUE_MAPm_field32_set(unit, &qmap_key, KEY_TYPEf, 0); 17934 soc_ENDPOINT_QUEUE_MAPm_field32_set(unit, &qmap_key, DEST_PORTf, port); 17935 soc_ENDPOINT_QUEUE_MAPm_field32_set(unit, &qmap_key, EH_QUEUE_TAGf, 17936 endpoint_id); 17937 SOC_IF_ERROR_RETURN(soc_mem_search(unit, ENDPOINT_QUEUE_MAPm, MEM_BLOCK_ANY, 17938 &qmap_index, &qmap_key, &qmap_data, 0)); 17939 17940 /* Get queue group */ 17941 qid = soc_ENDPOINT_QUEUE_MAPm_field32_get(unit, &qmap_data, 17942 ENDPOINT_QUEUE_BASEf); 17943 BCM_GPORT_UCAST_QUEUE_GROUP_SYSQID_SET(*queue_group, port, qid); 17944 17945 /* Get Endpoint CoS Map profile */ 17946 num_entries_per_profile = 16; 17947 alloc_size = sizeof(endpoint_cos_map_entry_t) * num_entries_per_profile; 17948 entry_array = sal_alloc(alloc_size, "Endpoint CoS Map Profile"); 17949 if (NULL == entry_array) { 17950 return BCM_E_MEMORY; 17951 } 17952 sal_memset(entry_array, 0, alloc_size); 17953 entries[0] = entry_array; 17954 endpoint_cos_map_prof_idx = soc_ENDPOINT_QUEUE_MAPm_field32_get(unit, &qmap_data, 17955 ENDPOINT_COS_MAP_PROFILE_INDEXf); 17956 /* 17957 * The index of ENDPOINT_COS_MAP = 17958 * ENDPOINT_COS_MAP_PROFILE_INDEX * 16 + INT_PRI 17959 */ 17960 profile_index = endpoint_cos_map_prof_idx * num_entries_per_profile; 17961 rv = soc_profile_mem_get(unit, _BCM_MN_ENDPOINT_COS_MAP_PROFILE(unit), 17962 profile_index, num_entries_per_profile, entries); 17963 if (SOC_FAILURE(rv)) { 17964 sal_free(entry_array); 17965 return rv; 17966 } 17967 17968 /* Get internal priority to CoS mapping */ 17969 if (array_max == 0) { 17970 if (NULL != array_count) { 17971 *array_count = num_entries_per_profile; 17972 } 17973 } else { 17974 *array_count = 0; 17975 for (i = 0; i < array_max; i++) { 17976 priority = priority_array[i]; 17977 if (priority >= 16 || priority < 0) { 17978 sal_free(entry_array); 17979 return BCM_E_PARAM; 17980 } 17981 cosq_array[i] = soc_ENDPOINT_COS_MAPm_field32_get(unit, 17982 &entry_array[priority], ENDPOINT_COS_OFFSETf); 17983 (*array_count)++; 17984 } 17985 } 17986 17987 sal_free(entry_array); 17988 return rv; 17989 } 17990 17991 /* 17992 * Function: 17993 * bcm_mn_cosq_endpoint_map_clear 17994 * Purpose: 17995 * Clear the mapping from port, classifier, and internal priorities 17996 * to COS queues in a queue group. 17997 * Parameters: 17998 * unit - (IN) Unit number. 17999 * port - (IN) Local port ID 18000 * classifier_id - (IN) Classifier ID 18001 * Returns: 18002 * BCM_E_xxx 18003 */ 18004 int 18005 bcm_mn_cosq_endpoint_map_clear( 18006 int unit, 18007 bcm_gport_t port, 18008 int classifier_id) 18009 { 18010 int endpoint_id; 18011 endpoint_queue_map_entry_t qmap_key, qmap_data; 18012 int profile_index; 18013 int num_entries_per_set = 16; 18014 18015 if (!_BCM_COSQ_CLASSIFIER_IS_ENDPOINT(classifier_id)) { 18016 return BCM_E_PARAM; 18017 } 18018 endpoint_id = _BCM_COSQ_CLASSIFIER_ENDPOINT_GET(classifier_id); 18019 if (endpoint_id >= _BCM_MN_NUM_ENDPOINT(unit)) { 18020 return BCM_E_PARAM; 18021 } 18022 if (!_BCM_MN_ENDPOINT_IS_USED(unit, endpoint_id)) { 18023 return BCM_E_PARAM; 18024 } 18025 18026 /* Delete (port, endpoint_id) entry from Endpoint Queue Map table */ 18027 sal_memcpy(&qmap_key, soc_mem_entry_null(unit, 18028 ENDPOINT_QUEUE_MAPm), sizeof(endpoint_queue_map_entry_t)); 18029 soc_ENDPOINT_QUEUE_MAPm_field32_set(unit, &qmap_key, KEY_TYPEf, 0); 18030 soc_ENDPOINT_QUEUE_MAPm_field32_set(unit, &qmap_key, DEST_PORTf, port); 18031 soc_ENDPOINT_QUEUE_MAPm_field32_set(unit, &qmap_key, EH_QUEUE_TAGf, 18032 endpoint_id); 18033 SOC_IF_ERROR_RETURN(soc_mem_delete_return_old(unit, ENDPOINT_QUEUE_MAPm, 18034 MEM_BLOCK_ALL, &qmap_key, &qmap_data)); 18035 18036 /* Delete priority to CoS mapping profile */ 18037 profile_index = soc_ENDPOINT_QUEUE_MAPm_field32_get(unit, &qmap_data, 18038 ENDPOINT_COS_MAP_PROFILE_INDEXf); 18039 profile_index = profile_index * num_entries_per_set; 18040 SOC_IF_ERROR_RETURN(soc_profile_mem_delete(unit, 18041 _BCM_MN_ENDPOINT_COS_MAP_PROFILE(unit), profile_index)); 18042 18043 return BCM_E_NONE; 18044 } 18045 18046 /* 18047 * Function: 18048 * bcm_mn_cosq_field_classifier_get 18049 * Purpose: 18050 * Get classifier type information. 18051 * Parameters: 18052 * unit - (IN) Unit number. 18053 * classifier_id - (IN) Classifier ID 18054 * classifier - (OUT) Classifier info 18055 * Returns: 18056 * BCM_E_xxx 18057 */ 18058 int 18059 bcm_mn_cosq_field_classifier_get( 18060 int unit, 18061 int classifier_id, 18062 bcm_cosq_classifier_t *classifier) 18063 { 18064 if (classifier == NULL) { 18065 return BCM_E_PARAM; 18066 } 18067 sal_memset(classifier, 0, sizeof(bcm_cosq_classifier_t)); 18068 18069 if (_BCM_COSQ_CLASSIFIER_IS_FIELD(classifier_id)) { 18070 classifier->flags |= BCM_COSQ_CLASSIFIER_FIELD; 18071 } 18072 18073 return BCM_E_NONE; 18074 } 18075 18076 18077 18078 /* 18079 * Function: 18080 * bcm_mn_cosq_field_classifier_id_create 18081 * Purpose: 18082 * Create a cosq classifier. 18083 * Parameters: 18084 * unit - (IN) Unit number. 18085 * classifier - (IN) Classifier attributes 18086 * classifier_id - (OUT) Classifier ID 18087 * Returns: 18088 * BCM_E_xxx 18089 */ 18090 int 18091 bcm_mn_cosq_field_classifier_id_create( 18092 int unit, 18093 bcm_cosq_classifier_t *classifier, 18094 int *classifier_id) 18095 { 18096 int rv; 18097 int ref_count = 0; 18098 int ent_per_set = _MN_NUM_INTERNAL_PRI; 18099 int i; 18100 18101 if (NULL == classifier || NULL == classifier_id) { 18102 return BCM_E_PARAM; 18103 } 18104 18105 for (i = 0; i < SOC_MEM_SIZE(unit, IFP_COS_MAPm); i += ent_per_set) { 18106 rv = soc_profile_mem_ref_count_get( 18107 unit, _bcm_mn_ifp_cos_map_profile[unit], i, &ref_count); 18108 if (SOC_FAILURE(rv)) { 18109 return rv; 18110 } 18111 if (0 == ref_count) { 18112 break; 18113 } 18114 } 18115 18116 if (i >= SOC_MEM_SIZE(unit, IFP_COS_MAPm) && ref_count != 0) { 18117 *classifier_id = 0; 18118 return BCM_E_RESOURCE; 18119 } 18120 18121 _BCM_COSQ_CLASSIFIER_FIELD_SET(*classifier_id, (i / ent_per_set)); 18122 18123 return BCM_E_NONE; 18124 } 18125 18126 18127 /* 18128 * Function: 18129 * bcm_mn_cosq_field_classifier_map_set 18130 * Purpose: 18131 * Set internal priority to ingress field processor CoS queue 18132 * override mapping. 18133 * Parameters: 18134 * unit - (IN) Unit number. 18135 * classifier_id - (IN) Classifier ID 18136 * count - (IN) Number of elements in priority_array and 18137 * cosq_array 18138 * priority_array - (IN) Array of internal priorities 18139 * cosq_array - (IN) Array of COS queues 18140 * Returns: 18141 * BCM_E_xxx 18142 */ 18143 int 18144 bcm_mn_cosq_field_classifier_map_set( 18145 int unit, 18146 int classifier_id, 18147 int count, 18148 bcm_cos_t *priority_array, 18149 bcm_cos_queue_t *cosq_array) 18150 { 18151 int rv; 18152 int i; 18153 int max_entries = _MN_NUM_INTERNAL_PRI; 18154 uint32 index; 18155 void *entries[1]; 18156 ifp_cos_map_entry_t ent_buf[_MN_NUM_INTERNAL_PRI]; 18157 int ref_count = 0; 18158 /* Input parameter check. */ 18159 if (!_BCM_COSQ_CLASSIFIER_IS_FIELD(classifier_id)) { 18160 return BCM_E_PARAM; 18161 } 18162 18163 if (NULL == priority_array || NULL == cosq_array) { 18164 return BCM_E_PARAM; 18165 } 18166 18167 if (count > max_entries) { 18168 return BCM_E_PARAM; 18169 } 18170 18171 sal_memset(ent_buf, 0, sizeof(ifp_cos_map_entry_t) * max_entries); 18172 entries[0] = ent_buf; 18173 18174 for (i = 0; i < count; i++) { 18175 if (priority_array[i] < max_entries) { 18176 if (cosq_array[i] >= _BCM_MN_NUM_L2_LEAVES_PER_PIPE) { 18177 return BCM_E_PARAM; 18178 } 18179 soc_mem_field32_set(unit, IFP_COS_MAPm, &ent_buf[priority_array[i]], 18180 IFP_COSf, cosq_array[i]); 18181 } 18182 } 18183 18184 index = _BCM_COSQ_CLASSIFIER_FIELD_GET(classifier_id); 18185 SOC_IF_ERROR_RETURN( 18186 soc_profile_mem_ref_count_get(unit, _bcm_mn_ifp_cos_map_profile[unit], 18187 index * max_entries, &ref_count)); 18188 18189 if (ref_count == 0) { 18190 rv = soc_profile_mem_add(unit, _bcm_mn_ifp_cos_map_profile[unit], 18191 entries, max_entries, &index); 18192 } else { 18193 rv = soc_profile_mem_set(unit, _bcm_mn_ifp_cos_map_profile[unit], 18194 entries, index * max_entries); 18195 if (rv == SOC_E_NONE) { 18196 /* decrease the profile ref_count increased by mem_set */ 18197 rv = soc_profile_mem_delete(unit, 18198 _bcm_mn_ifp_cos_map_profile[unit], 18199 index * max_entries); 18200 } 18201 } 18202 return rv; 18203 } 18204 18205 18206 /* 18207 * Function: 18208 * bcm_mn_cosq_field_classifier_map_get 18209 * Purpose: 18210 * Get internal priority to ingress field processor CoS queue 18211 * override mapping information. 18212 * Parameters: 18213 * unit - (IN) Unit number. 18214 * classifier_id - (IN) Classifier ID 18215 * array_max - (IN) Size of priority_array and cosq_array 18216 * priority_array - (IN) Array of internal priorities 18217 * cosq_array - (OUT) Array of COS queues 18218 * array_count - (OUT) Size of cosq_array 18219 * Returns: 18220 * BCM_E_xxx 18221 */ 18222 int 18223 bcm_mn_cosq_field_classifier_map_get( 18224 int unit, 18225 int classifier_id, 18226 int array_max, 18227 bcm_cos_t *priority_array, 18228 bcm_cos_queue_t *cosq_array, 18229 int *array_count) 18230 { 18231 int rv; 18232 int i; 18233 int ent_per_set = _MN_NUM_INTERNAL_PRI; 18234 uint32 index; 18235 void *entries[1]; 18236 ifp_cos_map_entry_t ent_buf[_MN_NUM_INTERNAL_PRI]; 18237 18238 /* Input parameter check. */ 18239 if (NULL == priority_array || NULL == cosq_array || NULL == array_count) { 18240 return BCM_E_PARAM; 18241 } 18242 18243 sal_memset(ent_buf, 0, sizeof(ifp_cos_map_entry_t) * ent_per_set); 18244 entries[0] = ent_buf; 18245 18246 /* Get profile table entry set base index. */ 18247 index = _BCM_COSQ_CLASSIFIER_FIELD_GET(classifier_id); 18248 18249 /* Read out entries from profile table into allocated buffer. */ 18250 rv = soc_profile_mem_get(unit, _bcm_mn_ifp_cos_map_profile[unit], 18251 index * ent_per_set, ent_per_set, entries); 18252 if (SOC_FAILURE(rv)) { 18253 return rv; 18254 } 18255 18256 *array_count = array_max > ent_per_set ? ent_per_set : array_max; 18257 18258 /* Copy values into API OUT parameters. */ 18259 for (i = 0; i < *array_count; i++) { 18260 if (priority_array[i] >= _MN_NUM_INTERNAL_PRI) { 18261 return BCM_E_PARAM; 18262 } 18263 cosq_array[i] = soc_mem_field32_get(unit, IFP_COS_MAPm, 18264 &ent_buf[priority_array[i]], 18265 IFP_COSf); 18266 } 18267 18268 return BCM_E_NONE; 18269 } 18270 18271 18272 /* 18273 * Function: 18274 * bcm_mn_cosq_field_classifier_map_clear 18275 * Purpose: 18276 * Delete an internal priority to ingress field processor CoS queue 18277 * override mapping profile set. 18278 * Parameters: 18279 * unit - (IN) Unit number. 18280 * classifier_id - (IN) Classifier ID 18281 * Returns: 18282 * BCM_E_xxx 18283 */ 18284 int 18285 bcm_mn_cosq_field_classifier_map_clear(int unit, int classifier_id) 18286 { 18287 int ent_per_set = _MN_NUM_INTERNAL_PRI; 18288 uint32 index; 18289 18290 /* Get profile table entry set base index. */ 18291 index = _BCM_COSQ_CLASSIFIER_FIELD_GET(classifier_id); 18292 18293 /* Delete the profile entries set. */ 18294 SOC_IF_ERROR_RETURN 18295 (soc_profile_mem_delete(unit, 18296 _bcm_mn_ifp_cos_map_profile[unit], 18297 index * ent_per_set)); 18298 return BCM_E_NONE; 18299 } 18300 18301 18302 /* 18303 * Function: 18304 * bcm_mn_cosq_field_classifier_id_destroy 18305 * Purpose: 18306 * Free resource associated with this field classifier id. 18307 * Parameters: 18308 * unit - (IN) Unit number. 18309 * classifier_id - (IN) Classifier ID 18310 * Returns: 18311 * BCM_E_xxx 18312 */ 18313 int 18314 bcm_mn_cosq_field_classifier_id_destroy(int unit, int classifier_id) 18315 { 18316 return BCM_E_NONE; 18317 } 18318 18319 18320 /* 18321 * Function: 18322 * bcm_td_cosq_cpu_cosq_enable_set 18323 * Purpose: 18324 * To enable/disable Rx of packets on the specified CPU cosq. 18325 * Parameters: 18326 * unit - (IN) Unit number. 18327 * cosq - (IN) CPU Cosq ID 18328 * enable - (IN) Enable/Disable 18329 * Returns: 18330 * BCM_E_xxx 18331 */ 18332 int 18333 bcm_mn_cosq_cpu_cosq_enable_set( 18334 int unit, 18335 bcm_cos_queue_t cosq, 18336 int enable) 18337 { 18338 uint32 entry[SOC_MAX_MEM_WORDS]; 18339 int i, index, enable_status; 18340 _bcm_mn_cosq_cpu_cosq_config_t *cpu_cosq; 18341 soc_info_t *si; 18342 soc_mem_t thdm_mem[] = { 18343 MMU_THDM_DB_QUEUE_CONFIG_0m, 18344 MMU_THDM_MCQE_QUEUE_CONFIG_0m 18345 }; 18346 18347 si = &SOC_INFO(unit); 18348 18349 if ((cosq < 0) || (cosq >= si->num_cpu_cosq)) { 18350 return BCM_E_PARAM; 18351 } 18352 18353 cpu_cosq = _bcm_mn_cosq_cpu_cosq_config[unit][cosq]; 18354 18355 if (!cpu_cosq) { 18356 return BCM_E_INTERNAL; 18357 } 18358 if (enable) { 18359 enable = 1; 18360 } 18361 18362 BCM_IF_ERROR_RETURN(bcm_mn_cosq_cpu_cosq_enable_get(unit, cosq, &enable_status)); 18363 if (enable == enable_status) { 18364 return BCM_E_NONE; 18365 } 18366 18367 index = _BCM_MN_CPU_COSQ_START + cosq; 18368 18369 for (i = 0; i < 2; i++) { 18370 BCM_IF_ERROR_RETURN 18371 (soc_mem_read(unit, thdm_mem[i], MEM_BLOCK_ALL, index, &entry)); 18372 18373 if (enable) { 18374 soc_mem_field32_set(unit, thdm_mem[i], &entry, 18375 Q_MIN_LIMITf, cpu_cosq->q_min_limit[i]); 18376 soc_mem_field32_set(unit, thdm_mem[i], &entry, 18377 Q_SHARED_LIMITf, cpu_cosq->q_shared_limit[i]); 18378 } 18379 else { 18380 cpu_cosq->q_min_limit[i] = soc_mem_field32_get(unit, 18381 thdm_mem[i], 18382 &entry, 18383 Q_MIN_LIMITf); 18384 cpu_cosq->q_shared_limit[i] = soc_mem_field32_get(unit, 18385 thdm_mem[i], 18386 &entry, 18387 Q_SHARED_LIMITf); 18388 cpu_cosq->q_limit_dynamic[i] = soc_mem_field32_get(unit, 18389 thdm_mem[i], 18390 &entry, 18391 Q_LIMIT_DYNAMICf); 18392 cpu_cosq->q_limit_enable[i] = soc_mem_field32_get(unit, 18393 thdm_mem[i], 18394 &entry, 18395 Q_LIMIT_ENABLEf); 18396 cpu_cosq->q_color_limit_enable[i] = soc_mem_field32_get(unit, 18397 thdm_mem[i], &entry, 18398 Q_COLOR_LIMIT_ENABLEf); 18399 soc_mem_field32_set(unit, thdm_mem[i], &entry, Q_MIN_LIMITf, 0); 18400 soc_mem_field32_set(unit, thdm_mem[i], &entry, Q_SHARED_LIMITf, 0); 18401 } 18402 soc_mem_field32_set(unit, thdm_mem[i], &entry, 18403 Q_LIMIT_DYNAMICf, enable ? cpu_cosq->q_limit_dynamic[i] : 0); 18404 soc_mem_field32_set(unit, thdm_mem[i], &entry, 18405 Q_LIMIT_ENABLEf, enable ? cpu_cosq->q_limit_enable[i] : 1); 18406 soc_mem_field32_set(unit, thdm_mem[i], &entry, 18407 Q_COLOR_LIMIT_ENABLEf, enable ? cpu_cosq->q_color_limit_enable[i] : 1); 18408 cpu_cosq->enable = enable; 18409 BCM_IF_ERROR_RETURN( 18410 soc_mem_write(unit, thdm_mem[i], MEM_BLOCK_ALL, index, &entry)); 18411 } 18412 18413 return BCM_E_NONE; 18414 } 18415 18416 /* 18417 * Function: 18418 * bcm_mn_cosq_cpu_cosq_enable_get 18419 * Purpose: 18420 * To get enable/disable status on Rx of packets on the specified CPU cosq. 18421 * Parameters: 18422 * unit - (IN) Unit number. 18423 * cosq - (IN) CPU Cosq ID 18424 * enable - (OUT) Enable/Disable 18425 * Returns: 18426 * BCM_E_xxx 18427 */ 18428 int 18429 bcm_mn_cosq_cpu_cosq_enable_get( 18430 int unit, 18431 bcm_cos_queue_t cosq, 18432 int *enable) 18433 { 18434 _bcm_mn_cosq_cpu_cosq_config_t *cpu_cosq; 18435 soc_field_t dynamic_enable; 18436 soc_info_t *si; 18437 int index, hw_enable; 18438 uint32 entry[SOC_MAX_MEM_WORDS]; 18439 soc_field_t min_limit, shared_limit, limit_enable; 18440 soc_mem_t thd_mem = MMU_THDM_DB_QUEUE_CONFIG_0m; 18441 18442 si = &SOC_INFO(unit); 18443 18444 if ((cosq < 0) || (cosq >= si->num_cpu_cosq)) { 18445 return BCM_E_PARAM; 18446 } 18447 18448 cpu_cosq = _bcm_mn_cosq_cpu_cosq_config[unit][cosq]; 18449 18450 if (!cpu_cosq) { 18451 return BCM_E_INTERNAL; 18452 } 18453 18454 index = _BCM_MN_CPU_COSQ_START + cosq; 18455 hw_enable = 1; 18456 18457 /*sync up software record with hardware status*/ 18458 BCM_IF_ERROR_RETURN(soc_mem_read(unit, thd_mem, MEM_BLOCK_ALL, 18459 index, &entry)); 18460 min_limit = soc_mem_field32_get( unit, thd_mem, &entry, 18461 Q_MIN_LIMITf); 18462 shared_limit = soc_mem_field32_get(unit, thd_mem, &entry, 18463 Q_SHARED_LIMITf); 18464 limit_enable = soc_mem_field32_get(unit, thd_mem, &entry, 18465 Q_LIMIT_ENABLEf); 18466 18467 dynamic_enable = soc_mem_field32_get(unit, thd_mem, &entry, 18468 Q_LIMIT_DYNAMICf); 18469 if (limit_enable && (dynamic_enable == 0)&& 18470 (min_limit == 0) && (shared_limit == 0)) { 18471 hw_enable = 0; 18472 } 18473 cpu_cosq->enable = hw_enable; 18474 18475 *enable = cpu_cosq->enable; 18476 return BCM_E_NONE; 18477 } 18478 18479 /* 18480 * Function: 18481 * bcm_mn_cosq_flex_port_configure 18482 * Purpose 18483 * Delete old default tree and create new tree as per the port type 18484 * Reconfigure all the queues of the port and configure the oversub config 18485 * if required 18486 * Parameters: 18487 * unit - (IN) Unit number. 18488 * old_port_list - (IN) List old ports getting deleted 18489 * num_of_old_ports - (IN) Number of old ports getting deleted 18490 * new_port_list - (IN) List new ports getting added 18491 * num_of_new_ports - (IN) Number of new ports getting added 18492 * num_port_flags - (IN) new ports flags 18493 * Returns: 18494 * BCM_E_xxx 18495 */ 18496 int 18497 bcm_mn_cosq_flex_port_update( 18498 int unit, 18499 bcm_port_t port, int enable) 18500 { 18501 18502 _bcm_mn_mmu_info_t *mmu_info; 18503 soc_info_t *si; 18504 int numq; 18505 int qnum = 0 ; 18506 _bcm_mn_pipe_resources_t *res; 18507 int phy_port,mmu_port; 18508 int id; 18509 uint64 rval64; 18510 int pipe; 18511 18512 si = &SOC_INFO(unit); 18513 mmu_info = _bcm_mn_mmu_info[unit]; 18514 phy_port = si->port_l2p_mapping[port]; 18515 mmu_port = si->port_p2m_mapping[phy_port]; 18516 /* root node */ 18517 numq = soc_property_port_get(unit, port, spn_LLS_NUM_L2UC, 16); 18518 if (numq < 10 || numq > 16) { 18519 numq = 10; 18520 } 18521 numq = (numq + 3) & ~3; 18522 18523 pipe = _BCM_MN_PORT_TO_PIPE(unit, port); 18524 res = _BCM_MN_PRESOURCES(mmu_info, pipe); 18525 if (enable) { 18526 if(IS_MN_HSP_PORT(unit, port)) { 18527 si->port_num_cosq[port] = 10; 18528 si->port_cosq_base[port] = mmu_port * si->port_num_cosq[port]; 18529 si->port_num_uc_cosq[port] = 10; 18530 si->port_uc_cosq_base[port] = mmu_port * si->port_num_cosq[port]; 18531 } else { 18532 BCM_IF_ERROR_RETURN( 18533 _bcm_mn_node_index_get(res->l2_queue_list.bits, 0, 18534 mmu_info->num_l2_queues, numq, 18535 8, &id)); 18536 _bcm_mn_node_index_set(&res->l2_queue_list, id, numq); 18537 si->port_num_cosq[port] = 10; 18538 si->port_cosq_base[port] = (mmu_port * si->port_num_cosq[port]); 18539 si->port_num_uc_cosq[port] = numq; 18540 si->port_uc_cosq_base[port] = id; 18541 18542 } 18543 18544 mmu_info->port_info[port].resources = &mmu_info->pipe_resources[pipe]; 18545 mmu_info->port_info[port].mc_base = si->port_cosq_base[port]; 18546 mmu_info->port_info[port].mc_limit = si->port_cosq_base[port] + 18547 si->port_num_cosq[port]; 18548 mmu_info->port_info[port].uc_base = si->port_uc_cosq_base[port]; 18549 mmu_info->port_info[port].uc_limit = si->port_uc_cosq_base[port] + 18550 si->port_num_uc_cosq[port]; 18551 COMPILER_64_ZERO(rval64); 18552 if(IS_MN_HSP_PORT(unit, port)) { 18553 SOC_IF_ERROR_RETURN(soc_monterey_sched_hw_index_get(unit, 18554 port, SOC_MONTEREY_NODE_LVL_L1, 0, &qnum)); 18555 } else { 18556 qnum = soc_monterey_logical_qnum_hw_qnum(unit, port, 18557 si->port_uc_cosq_base[port], 1); 18558 } 18559 soc_reg64_field32_set(unit, ING_COS_MODE_64r, 18560 &rval64, BASE_QUEUE_NUM_0f, qnum); 18561 soc_reg64_field32_set(unit, ING_COS_MODE_64r, 18562 &rval64, BASE_QUEUE_NUM_1f, qnum); 18563 BCM_IF_ERROR_RETURN(soc_reg_set(unit, ING_COS_MODE_64r, port, 0, rval64)); 18564 18565 } else { 18566 if(IS_MN_HSP_PORT(unit, port)) { 18567 si->port_num_cosq[port] = -1; 18568 si->port_cosq_base[port] = -1; 18569 si->port_num_uc_cosq[port] = -1; 18570 si->port_uc_cosq_base[port] = -1; 18571 } else { 18572 _bcm_mn_node_index_clear(&res->l2_queue_list, 18573 si->port_uc_cosq_base[port], numq); 18574 si->port_num_cosq[port] = -1; 18575 si->port_cosq_base[port] = -1; 18576 si->port_num_uc_cosq[port] = -1; 18577 si->port_uc_cosq_base[port] = -1; 18578 18579 } 18580 18581 COMPILER_64_ZERO(rval64); 18582 mmu_info->port_info[port].resources = &mmu_info->pipe_resources[pipe]; 18583 mmu_info->port_info[port].mc_base = si->port_cosq_base[port]; 18584 mmu_info->port_info[port].mc_limit = si->port_cosq_base[port] + 18585 si->port_num_cosq[port]; 18586 mmu_info->port_info[port].uc_base = si->port_uc_cosq_base[port]; 18587 mmu_info->port_info[port].uc_limit = si->port_uc_cosq_base[port] + 18588 si->port_num_uc_cosq[port]; 18589 soc_reg64_field32_set(unit, ING_COS_MODE_64r, 18590 &rval64, BASE_QUEUE_NUM_0f, 0); 18591 soc_reg64_field32_set(unit, ING_COS_MODE_64r, 18592 &rval64, BASE_QUEUE_NUM_1f, 0); 18593 BCM_IF_ERROR_RETURN(soc_reg_set(unit, ING_COS_MODE_64r, port, 0, rval64)); 18594 18595 18596 } 18597 return BCM_E_NONE; 18598 18599 } 18600 18601 int 18602 _bcm_mn_cosq_gport_dump_subtree( int unit, bcm_gport_t gport) 18603 { 18604 _bcm_mn_cosq_node_t *node; 18605 int num_spri = 0, first_child = 0, first_mc_child; 18606 uint32 ucmap, spmap; 18607 soc_monterey_sched_mode_e sched_mode; 18608 int wt = 0; 18609 char *lvl_name[] = { "Root", "S1", "L0", "L1", "L2" }; 18610 char *sched_modes[] = {"X", "SP", "WRR", "WDRR"}; 18611 18612 18613 BCM_IF_ERROR_RETURN 18614 (_bcm_mn_cosq_node_get(unit, gport, 0, NULL, NULL, NULL, &node)); 18615 18616 if (( node->level != SOC_MONTEREY_NODE_LVL_ROOT) && 18617 (node->level != SOC_MONTEREY_NODE_LVL_L2)) { 18618 BCM_IF_ERROR_RETURN( 18619 soc_monterey_cosq_get_sched_child_config(unit, node->local_port, 18620 node->level, 18621 node->hw_index, 18622 &num_spri, &first_child, 18623 &first_mc_child, &ucmap, &spmap)); 18624 } 18625 sched_mode = 0; 18626 if (node->level != SOC_MONTEREY_NODE_LVL_ROOT) { 18627 SOC_IF_ERROR_RETURN( 18628 soc_monterey_cosq_get_sched_mode(unit, node->local_port, node->level, 18629 node->hw_index, &sched_mode, &wt)); 18630 } 18631 if (node->level == SOC_MONTEREY_NODE_LVL_ROOT) { 18632 if (soc_feature(unit, soc_feature_mmu_hqos_four_level)) 18633 { 18634 LOG_CLI((BSL_META_U(unit, 18635 " %s.%d : INDEX=%d NUM_SPRI=0 FC=0 MODE=X Wt=0\n"), 18636 lvl_name[node->level], 18637 node->attached_to_input, 18638 _soc_monterey_root_scheduler_index(unit, node->local_port))); 18639 } 18640 } else if (node->level == SOC_MONTEREY_NODE_LVL_S1) { 18641 if (soc_feature(unit, soc_feature_mmu_hqos_four_level)) 18642 { 18643 LOG_CLI((BSL_META_U(unit, 18644 " %s.%d : INDEX=%d NUM_SPRI=%d FC=%d MODE=%s Wt=%d\n"), 18645 lvl_name[node->level], 18646 node->attached_to_input, 18647 node->hw_index, 18648 num_spri, first_child, 18649 sched_modes[sched_mode], 18650 wt)); 18651 } else 18652 { 18653 LOG_CLI((BSL_META_U(unit, 18654 " %s.%d : INDEX=%d NUM_SPRI=%d FC=%d MODE=%s Wt=%d\n"), 18655 lvl_name[node->level - 1], 18656 node->attached_to_input, 18657 node->hw_index, 18658 num_spri, first_child, 18659 sched_modes[sched_mode], 18660 wt)); 18661 } 18662 18663 } else if (node->level == SOC_MONTEREY_NODE_LVL_L0) { 18664 LOG_CLI((BSL_META_U(unit, 18665 " %s.%d : INDEX=%d NUM_SPRI=%d FC=%d MODE=%s Wt=%d\n"), 18666 lvl_name[node->level], 18667 node->attached_to_input, 18668 node->hw_index, 18669 num_spri, first_child, 18670 sched_modes[sched_mode], 18671 wt)); 18672 18673 } else if (node->level == SOC_MONTEREY_NODE_LVL_L1) { 18674 LOG_CLI((BSL_META_U(unit, 18675 " %s.%d : INDEX=%d NUM_SP=%d FC=%d " 18676 "FMC=%d UCMAP=0x%08x MODE=%s WT=%d\n"), 18677 lvl_name[node->level], 18678 node->attached_to_input, 18679 node->hw_index, 18680 num_spri, 18681 first_child, 18682 first_mc_child, 18683 ucmap, 18684 sched_modes[sched_mode], 18685 wt)); 18686 } else { 18687 LOG_CLI((BSL_META_U(unit, 18688 " %s.%s : INDEX=%d MODE=%s Wt=%d\n"), 18689 lvl_name[node->level], 18690 node->hw_index < 16384 ? "uc" : "mc", 18691 node->hw_index, 18692 sched_modes[sched_mode], 18693 wt)); 18694 } 18695 18696 if (node->child != NULL) { 18697 _bcm_mn_cosq_gport_dump_subtree(unit, node->child->gport); 18698 } 18699 18700 18701 if (node->sibling != NULL) { 18702 _bcm_mn_cosq_gport_dump_subtree(unit, node->sibling->gport); 18703 } 18704 18705 return SOC_E_NONE; 18706 } 18707 18708 /* 18709 * Function: 18710 * bcm_mn_cosq_service_classifier_id_create 18711 * Purpose: 18712 * Create an endpoint. 18713 * Parameters: 18714 * unit - (IN) Unit number. 18715 * classifier - (IN) Classifier attributes 18716 * classifier_id - (OUT) Classifier ID 18717 * Returns: 18718 * BCM_E_xxx 18719 */ 18720 int 18721 bcm_mn_cosq_service_classifier_id_create( 18722 int unit, 18723 bcm_cosq_classifier_t *classifier, 18724 int *classifier_id) 18725 { 18726 if (NULL == classifier || NULL == classifier_id) { 18727 return BCM_E_PARAM; 18728 } 18729 18730 _BCM_COSQ_CLASSIFIER_SERVICE_SET(*classifier_id, classifier->vlan); 18731 return BCM_E_NONE; 18732 } 18733 18734 /* 18735 * Function: 18736 * bcm_mn_cosq_service_classifier_id_destroy 18737 * Purpose: 18738 * free resource associated with this service classifier id. 18739 * Parameters: 18740 * unit - (IN) Unit number. 18741 * classifier_id - (IN) Classifier ID 18742 * Returns: 18743 * BCM_E_xxx 18744 */ 18745 int 18746 bcm_mn_cosq_service_classifier_id_destroy( 18747 int unit, 18748 int classifier_id) 18749 { 18750 return BCM_E_NONE; 18751 } 18752 18753 /* 18754 * Function: 18755 * bcm_mn_cosq_service_classifier_get 18756 * Purpose: 18757 * Get info about an endpoint. 18758 * Parameters: 18759 * unit - (IN) Unit number. 18760 * classifier_id - (IN) Classifier ID 18761 * classifier - (OUT) Classifier info 18762 * Returns: 18763 * BCM_E_xxx 18764 */ 18765 int 18766 bcm_mn_cosq_service_classifier_get( 18767 int unit, 18768 int classifier_id, 18769 bcm_cosq_classifier_t *classifier) 18770 { 18771 int val = 0; 18772 18773 sal_memset(classifier, 0, sizeof(bcm_cosq_classifier_t)); 18774 18775 val = _BCM_COSQ_CLASSIFIER_SERVICE_GET(classifier_id); 18776 18777 if (val > BCM_VLAN_MAX) { 18778 /* VFI classifier */ 18779 classifier->flags = BCM_COSQ_CLASSIFIER_VFI; 18780 classifier->vfi_index = val - BCM_VLAN_MAX - 1; 18781 } else { 18782 classifier->flags = BCM_COSQ_CLASSIFIER_VLAN; 18783 classifier->vlan = val; 18784 } 18785 return BCM_E_NONE; 18786 } 18787 18788 /* 18789 * Function: 18790 * bcm_mn_cosq_service_map_set 18791 * Purpose: 18792 * Set the mapping from port, classifier, and multiple internal priorities 18793 * to multiple COS queues in a queue group. 18794 * Parameters: 18795 * unit - (IN) Unit number. 18796 * port - (IN) local port ID 18797 * classifier_id - (IN) Classifier ID 18798 * queue_group - (IN) Base queue ID 18799 * array_count - (IN) Number of elements in priority_array and 18800 * cosq_array 18801 * priority_array - (IN) Array of internal priorities 18802 * cosq_array - (IN) Array of COS queues 18803 * Returns: 18804 * BCM_E_xxx 18805 */ 18806 int 18807 bcm_mn_cosq_service_map_set( 18808 int unit, 18809 bcm_port_t port, 18810 int classifier_id, 18811 bcm_gport_t queue_group, 18812 int array_count, 18813 bcm_cos_t *priority_array, 18814 bcm_cos_queue_t *cosq_array) 18815 { 18816 service_queue_map_entry_t sqm; 18817 service_port_map_entry_t *spm = NULL; 18818 service_cos_map_entry_t *scm = NULL; 18819 void *spm_entries[1]; 18820 void *scm_entries[1]; 18821 int rv = BCM_E_NONE; 18822 int i, j, numq, alloc_size, exists = 0; 18823 int local_port, vid, qid, cos_offset = 0; 18824 int port_offset, port_offset_old; 18825 int qptr_old, qptr_new; 18826 uint32 scm_idx, spm_idx, spm_idx_old = 0; 18827 _bcm_mn_cosq_node_t *node; 18828 soc_profile_mem_t *spm_profile_mem, *scm_profile_mem; 18829 /* 18830 * The port_offset= 0 is treated as the invalid offset so that 18831 * the ports without being service map set can be recognized easily by software. 18832 * Accordingly, The valid port_offset needs to be at least 1 for a given port. 18833 * the queue base to be written into SERVICE_QUEUE_PTRf will 18834 * be (the actual base - 1). 18835 */ 18836 #define VALID_PORT_OFFSET_MIN 1 18837 18838 if (!_BCM_COSQ_CLASSIFIER_IS_SERVICE(classifier_id)) { 18839 return BCM_E_PARAM; 18840 } 18841 18842 /* index above 4K is for VFI */ 18843 vid = _BCM_COSQ_CLASSIFIER_SERVICE_GET(classifier_id); 18844 if (vid < 0 || vid >= SOC_MEM_SIZE(unit, SERVICE_QUEUE_MAPm)) { 18845 return BCM_E_PARAM; 18846 } 18847 18848 if (array_count > _MN_SCM_ENTRIES_PER_SET) { 18849 return BCM_E_PARAM; 18850 } 18851 scm_profile_mem = _bcm_mn_service_cos_map_profile[unit]; 18852 spm_profile_mem = _bcm_mn_service_port_map_profile[unit]; 18853 18854 BCM_IF_ERROR_RETURN( 18855 _bcm_mn_cosq_node_get(unit, queue_group, 0, NULL, 18856 &local_port, &qid, &node)); 18857 if (node->attached_to_input < 0) { 18858 return BCM_E_PARAM; 18859 } 18860 numq = node->parent->numq; 18861 qid = node->hw_index; 18862 18863 for (i = 0; i < array_count; i++) { 18864 if (cosq_array[i] >= numq) { 18865 return BCM_E_PARAM; 18866 } 18867 } 18868 18869 sal_memset(&sqm, 0, sizeof(service_queue_map_entry_t)); 18870 SOC_IF_ERROR_RETURN( 18871 soc_mem_read(unit, SERVICE_QUEUE_MAPm, MEM_BLOCK_ANY, (int)vid, &sqm)); 18872 18873 if (soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, &sqm, VALIDf)) { 18874 exists = 1; 18875 } else { 18876 exists = 0; 18877 } 18878 18879 alloc_size = sizeof(service_port_map_entry_t) * _MN_SPM_ENTRIES_PER_SET; 18880 spm = sal_alloc(alloc_size, "SERVICE_PORT_MAP temp Mem"); 18881 if (spm == NULL) { 18882 rv = BCM_E_MEMORY; 18883 goto cleanup; 18884 } 18885 sal_memset(spm, 0, alloc_size); 18886 spm_entries[0] = spm; 18887 18888 alloc_size = sizeof(service_cos_map_entry_t) * _MN_SCM_ENTRIES_PER_SET; 18889 scm = sal_alloc(alloc_size, "SERVICE_COS_MAP temp Mem"); 18890 if (scm == NULL) { 18891 rv = BCM_E_MEMORY; 18892 goto cleanup; 18893 } 18894 sal_memset(scm, 0, alloc_size); 18895 scm_entries[0] = scm; 18896 18897 /* 1. program the SERVICE_COS_MAPm. */ 18898 if (!exists) { 18899 for (i = 0; i < array_count; i++) { 18900 if (priority_array[i] < _MN_SCM_ENTRIES_PER_SET) { 18901 soc_mem_field32_set(unit, SERVICE_COS_MAPm, 18902 &scm[priority_array[i]], 18903 SERVICE_COS_OFFSETf, cosq_array[i]); 18904 } 18905 } 18906 18907 rv = soc_profile_mem_add(unit, scm_profile_mem, scm_entries, 18908 _MN_SCM_ENTRIES_PER_SET, &scm_idx); 18909 if (rv != SOC_E_NONE) { 18910 goto cleanup; 18911 } 18912 } else { 18913 /* 18914 * only one service_cos_map profile is allowed per vlan/vfi. 18915 * If the subsequent profile doesn't match the existing one, 18916 * it will be treated as an error. 18917 */ 18918 scm_idx = _MN_SCM_ENTRIES_PER_SET * 18919 soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, &sqm, 18920 SERVICE_COS_PROFILE_INDEXf); 18921 rv = soc_profile_mem_get(unit, scm_profile_mem, scm_idx, 18922 _MN_SCM_ENTRIES_PER_SET, scm_entries); 18923 if (rv != SOC_E_NONE) { 18924 goto cleanup; 18925 } 18926 18927 for (i = 0; i < array_count; i++) { 18928 cos_offset = soc_mem_field32_get(unit, SERVICE_COS_MAPm, 18929 &scm[priority_array[i]], 18930 SERVICE_COS_OFFSETf); 18931 if (cosq_array[i] != cos_offset) { 18932 rv = BCM_E_PARAM; 18933 goto cleanup; 18934 } 18935 } 18936 18937 for (i = 0; i < _MN_SCM_ENTRIES_PER_SET; i++) { 18938 for (j = 0; j < array_count; j++) { 18939 if (i == priority_array[j]) { 18940 break; 18941 } 18942 } 18943 /* for priorities not in priority_array, the cosq should be 0 */ 18944 if (j == array_count) { 18945 cos_offset = soc_mem_field32_get(unit, SERVICE_COS_MAPm, 18946 &scm[i],SERVICE_COS_OFFSETf); 18947 if (cos_offset) { 18948 rv = BCM_E_PARAM; 18949 goto cleanup; 18950 } 18951 } 18952 } 18953 } 18954 18955 /* 2. program the SERVICE_PORT_MAPm. */ 18956 if (!exists) { 18957 port_offset = VALID_PORT_OFFSET_MIN; 18958 soc_mem_field32_set(unit, SERVICE_PORT_MAPm, &spm[local_port], 18959 SERVICE_PORT_OFFSETf, port_offset); 18960 } else { 18961 spm_idx_old = _MN_SPM_ENTRIES_PER_SET * 18962 soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, &sqm, 18963 SERVICE_PORT_PROFILE_INDEXf); 18964 rv = soc_profile_mem_get(unit, spm_profile_mem, spm_idx_old, 18965 _MN_SPM_ENTRIES_PER_SET, spm_entries); 18966 if (!(rv == SOC_E_NOT_FOUND || rv == SOC_E_NONE)) { 18967 goto cleanup; 18968 } 18969 18970 qptr_old = soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, 18971 &sqm, SERVICE_QUEUE_PTRf); 18972 if (qid <= qptr_old) { 18973 qptr_new = qid - VALID_PORT_OFFSET_MIN; 18974 for (i = 0; i < _MN_SPM_ENTRIES_PER_SET; i++) { 18975 port_offset_old = soc_mem_field32_get(unit, SERVICE_PORT_MAPm, 18976 &spm[i], 18977 SERVICE_PORT_OFFSETf); 18978 if (i == local_port) { 18979 port_offset = VALID_PORT_OFFSET_MIN; 18980 } else if (!port_offset_old) { 18981 /* 18982 * For the old port_offsets with 0, 18983 * the new port_offsest are still 0. 18984 */ 18985 continue; 18986 } else { 18987 port_offset = qptr_old + port_offset_old - qptr_new; 18988 } 18989 soc_mem_field32_set(unit, SERVICE_PORT_MAPm, &spm[i], 18990 SERVICE_PORT_OFFSETf, port_offset); 18991 } 18992 } else { 18993 port_offset = qid - qptr_old; 18994 soc_mem_field32_set(unit, SERVICE_PORT_MAPm, &spm[local_port], 18995 SERVICE_PORT_OFFSETf, port_offset); 18996 } 18997 } 18998 rv = soc_profile_mem_add(unit, spm_profile_mem, 18999 spm_entries, _MN_SPM_ENTRIES_PER_SET, &spm_idx); 19000 if (rv != SOC_E_NONE) { 19001 goto cleanup; 19002 } 19003 19004 /* 3. program the SERVICE_QUEUE_MAPm */ 19005 if (!exists) { 19006 qptr_new = qid - VALID_PORT_OFFSET_MIN; 19007 } else { 19008 qptr_old = soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, 19009 &sqm, SERVICE_QUEUE_PTRf); 19010 if (qid <= qptr_old) { 19011 qptr_new = qid - VALID_PORT_OFFSET_MIN; 19012 } else { 19013 qptr_new = qptr_old; 19014 } 19015 } 19016 19017 soc_mem_field32_set(unit, SERVICE_QUEUE_MAPm, &sqm, 19018 SERVICE_QUEUE_PTRf, qptr_new); 19019 soc_mem_field32_set(unit, SERVICE_QUEUE_MAPm, &sqm, 19020 SERVICE_COS_PROFILE_INDEXf, 19021 scm_idx / _MN_SCM_ENTRIES_PER_SET); 19022 soc_mem_field32_set(unit, SERVICE_QUEUE_MAPm, &sqm, 19023 SERVICE_PORT_PROFILE_INDEXf, 19024 spm_idx / _MN_SPM_ENTRIES_PER_SET); 19025 /* use port indexed and cos indexed for this base queue */ 19026 soc_mem_field32_set(unit, SERVICE_QUEUE_MAPm, &sqm, 19027 SERVICE_QUEUE_MODELf, 3); 19028 soc_mem_field32_set(unit, SERVICE_QUEUE_MAPm, &sqm, VALIDf, 1); 19029 19030 rv = soc_mem_write(unit, SERVICE_QUEUE_MAPm, MEM_BLOCK_ALL, (int)vid, &sqm); 19031 19032 if (exists) { 19033 if (spm_idx_old != spm_idx) { 19034 rv = soc_profile_mem_delete(unit, spm_profile_mem, spm_idx_old); 19035 } 19036 } 19037 19038 cleanup: 19039 if (spm != NULL) { 19040 sal_free(spm); 19041 } 19042 if (scm != NULL) { 19043 sal_free(scm); 19044 } 19045 return rv; 19046 } 19047 19048 /* 19049 * Function: 19050 * bcm_mn_cosq_service_map_get 19051 * Purpose: 19052 * Get the mapping from port, classifier, and multiple internal priorities 19053 * to multiple COS queues in a queue group. 19054 * Parameters: 19055 * unit - (IN) Unit number. 19056 * port - (IN) Local port ID 19057 * classifier_id - (IN) Classifier ID 19058 * queue_group - (OUT) Queue group 19059 * array_max - (IN) Size of priority_array and cosq_array 19060 * priority_array - (IN) Array of internal priorities 19061 * cosq_array - (OUT) Array of COS queues 19062 * array_count - (OUT) Size of cosq_array 19063 * Returns: 19064 * BCM_E_xxx 19065 */ 19066 int 19067 bcm_mn_cosq_service_map_get( 19068 int unit, 19069 bcm_port_t port, 19070 int classifier_id, 19071 bcm_gport_t *queue_group, 19072 int array_max, 19073 bcm_cos_t *priority_array, 19074 bcm_cos_queue_t *cosq_array, 19075 int *array_count) 19076 { 19077 int alloc_size, port_offset, i, vid, qptr; 19078 int spm_index, scm_index; 19079 int rv = BCM_E_NONE; 19080 void *spm_entries[1]; 19081 void *scm_entries[1]; 19082 service_queue_map_entry_t sqm; 19083 service_port_map_entry_t *spm; 19084 service_cos_map_entry_t *scm; 19085 soc_profile_mem_t *spm_profile_mem, *scm_profile_mem; 19086 19087 if (priority_array == NULL || cosq_array == NULL || 19088 array_count == NULL || queue_group == NULL) { 19089 return BCM_E_PARAM; 19090 } 19091 19092 if (!_BCM_COSQ_CLASSIFIER_IS_SERVICE(classifier_id)) { 19093 return BCM_E_PARAM; 19094 } 19095 19096 /* index above 4K is for VFI */ 19097 vid = _BCM_COSQ_CLASSIFIER_SERVICE_GET(classifier_id); 19098 if (vid < 0 || vid >= SOC_MEM_SIZE(unit, SERVICE_QUEUE_MAPm)) { 19099 return BCM_E_PARAM; 19100 } 19101 19102 scm_profile_mem = _bcm_mn_service_cos_map_profile[unit]; 19103 spm_profile_mem = _bcm_mn_service_port_map_profile[unit]; 19104 19105 SOC_IF_ERROR_RETURN( 19106 soc_mem_read(unit, SERVICE_QUEUE_MAPm, MEM_BLOCK_ANY, (int)vid, &sqm)); 19107 19108 if (!soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, &sqm, VALIDf)) { 19109 return BCM_E_CONFIG; 19110 } 19111 19112 qptr = soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, 19113 &sqm, SERVICE_QUEUE_PTRf); 19114 spm_index = _MN_SPM_ENTRIES_PER_SET * 19115 soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, &sqm, 19116 SERVICE_PORT_PROFILE_INDEXf); 19117 scm_index = _MN_SCM_ENTRIES_PER_SET * 19118 soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, &sqm, 19119 SERVICE_COS_PROFILE_INDEXf); 19120 19121 alloc_size = sizeof(service_port_map_entry_t) * _MN_SPM_ENTRIES_PER_SET; 19122 spm = sal_alloc(alloc_size, "SERVICE_PORT_MAP temp Mem"); 19123 if (spm == NULL) { 19124 return BCM_E_MEMORY; 19125 } 19126 sal_memset(spm, 0, alloc_size); 19127 spm_entries[0] = spm; 19128 19129 alloc_size = sizeof(service_cos_map_entry_t) * _MN_SCM_ENTRIES_PER_SET; 19130 scm = sal_alloc(alloc_size, "SERVICE_COS_MAP temp Mem"); 19131 if (scm == NULL) { 19132 goto cleaup; 19133 } 19134 sal_memset(scm, 0, alloc_size); 19135 scm_entries[0] = scm; 19136 19137 rv = soc_profile_mem_get(unit, spm_profile_mem, 19138 spm_index, _MN_SPM_ENTRIES_PER_SET, spm_entries); 19139 if (!(rv == SOC_E_NOT_FOUND || rv == SOC_E_NONE)) { 19140 goto cleaup; 19141 } 19142 19143 rv = soc_profile_mem_get(unit, scm_profile_mem, 19144 scm_index, _MN_SCM_ENTRIES_PER_SET, scm_entries); 19145 if (!(rv == SOC_E_NOT_FOUND || rv == SOC_E_NONE)) { 19146 goto cleaup; 19147 } 19148 19149 port_offset = soc_mem_field32_get(unit, SERVICE_PORT_MAPm, 19150 &spm[port], SERVICE_PORT_OFFSETf); 19151 if (port_offset == 0) { 19152 rv = BCM_E_NOT_FOUND; 19153 goto cleaup; 19154 } 19155 BCM_GPORT_UCAST_QUEUE_GROUP_SYSQID_SET(*queue_group, port, 19156 (port_offset + qptr)); 19157 19158 *array_count = array_max > _MN_SCM_ENTRIES_PER_SET ? 19159 _MN_SCM_ENTRIES_PER_SET : array_max; 19160 for (i = 0; i < *array_count; i++) { 19161 if (priority_array[i] >= _MN_SCM_ENTRIES_PER_SET) { 19162 rv = BCM_E_PARAM; 19163 goto cleaup; 19164 } 19165 cosq_array[i] = soc_mem_field32_get(unit, SERVICE_COS_MAPm, 19166 &scm[priority_array[i]], 19167 SERVICE_COS_OFFSETf); 19168 } 19169 19170 cleaup: 19171 if (spm != NULL) { 19172 sal_free(spm); 19173 } 19174 if (scm != NULL) { 19175 sal_free(scm); 19176 } 19177 return rv; 19178 } 19179 19180 /* 19181 * Function: 19182 * bcm_mn_cosq_service_map_clear 19183 * Purpose: 19184 * Clear the mapping from port, classifier, and internal priorities 19185 * to COS queues in a queue group. 19186 * Parameters: 19187 * unit - (IN) Unit number. 19188 * port - (IN) Local port ID 19189 * classifier_id - (IN) Classifier ID 19190 * Returns: 19191 * BCM_E_xxx 19192 */ 19193 int 19194 bcm_mn_cosq_service_map_clear( 19195 int unit, 19196 bcm_gport_t port, 19197 int classifier_id) 19198 { 19199 int i, alloc_size, vid, classifier_in_use; 19200 int rv = BCM_E_NONE; 19201 int scm_index; 19202 uint32 spm_index, spm_index_new; 19203 void *spm_entries[1]; 19204 service_port_map_entry_t *spm; 19205 service_queue_map_entry_t sqm; 19206 soc_profile_mem_t *spm_profile_mem, *scm_profile_mem; 19207 19208 if (!_BCM_COSQ_CLASSIFIER_IS_SERVICE(classifier_id)) { 19209 return BCM_E_PARAM; 19210 } 19211 19212 /* index above 4K is for VFI */ 19213 vid = _BCM_COSQ_CLASSIFIER_SERVICE_GET(classifier_id); 19214 if (vid < 0 || vid >= SOC_MEM_SIZE(unit, SERVICE_QUEUE_MAPm)) { 19215 return BCM_E_PARAM; 19216 } 19217 19218 scm_profile_mem = _bcm_mn_service_cos_map_profile[unit]; 19219 spm_profile_mem = _bcm_mn_service_port_map_profile[unit]; 19220 19221 SOC_IF_ERROR_RETURN( 19222 soc_mem_read(unit, SERVICE_QUEUE_MAPm, MEM_BLOCK_ANY, (int)vid, &sqm)); 19223 19224 if (!soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, &sqm, VALIDf)) { 19225 return BCM_E_NONE; 19226 } 19227 19228 /* 1. program the SERVICE_PORT_MAPm. */ 19229 alloc_size = sizeof(service_port_map_entry_t) * _MN_SPM_ENTRIES_PER_SET; 19230 spm = sal_alloc(alloc_size, "SERVICE_PORT_MAP temp Mem"); 19231 if (spm == NULL) { 19232 return BCM_E_MEMORY; 19233 } 19234 sal_memset(spm, 0, alloc_size); 19235 spm_entries[0] = spm; 19236 19237 spm_index = _MN_SPM_ENTRIES_PER_SET * 19238 soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, &sqm, 19239 SERVICE_PORT_PROFILE_INDEXf); 19240 rv = soc_profile_mem_get(unit, spm_profile_mem, 19241 spm_index, _MN_SPM_ENTRIES_PER_SET, spm_entries); 19242 if (!(rv == SOC_E_NOT_FOUND || rv == SOC_E_NONE)) { 19243 goto cleanup; 19244 } 19245 19246 soc_mem_field32_set(unit, SERVICE_PORT_MAPm, 19247 &spm[port], SERVICE_PORT_OFFSETf, 0); 19248 classifier_in_use = 0; 19249 for (i = 0; i < _MN_SPM_ENTRIES_PER_SET; i++) { 19250 if (soc_mem_field32_get(unit, SERVICE_PORT_MAPm, 19251 &spm[i], SERVICE_PORT_OFFSETf)) { 19252 classifier_in_use = 1; 19253 break; 19254 } 19255 } 19256 19257 rv = soc_profile_mem_delete(unit, spm_profile_mem, spm_index); 19258 if (rv != SOC_E_NONE) { 19259 goto cleanup; 19260 } 19261 19262 if (classifier_in_use) { 19263 rv = soc_profile_mem_add(unit, spm_profile_mem, 19264 spm_entries, _MN_SPM_ENTRIES_PER_SET, 19265 &spm_index_new); 19266 if (rv != SOC_E_NONE) { 19267 goto cleanup; 19268 } 19269 } 19270 19271 /* 2. program the SERVICE_COS_MAPm. */ 19272 if (!classifier_in_use) { 19273 scm_index = _MN_SCM_ENTRIES_PER_SET * 19274 soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, &sqm, 19275 SERVICE_COS_PROFILE_INDEXf); 19276 rv = soc_profile_mem_delete(unit, scm_profile_mem, scm_index); 19277 if (rv != SOC_E_NONE) { 19278 goto cleanup; 19279 } 19280 } 19281 19282 /* 3. program the SERVICE_QUEUE_MAPm. */ 19283 if (classifier_in_use) { 19284 soc_mem_field32_set(unit, SERVICE_QUEUE_MAPm, &sqm, 19285 SERVICE_PORT_PROFILE_INDEXf, 19286 spm_index_new / _MN_SPM_ENTRIES_PER_SET); 19287 } else { 19288 sal_memset(&sqm,0, sizeof(service_queue_map_entry_t)); 19289 } 19290 19291 rv = soc_mem_write(unit, SERVICE_QUEUE_MAPm, MEM_BLOCK_ALL, 19292 (int)vid, &sqm); 19293 19294 cleanup: 19295 if (spm != NULL) { 19296 sal_free(spm); 19297 } 19298 return rv; 19299 } 19300 19301 /******************************************************************/ 19302 /* OBM CLASSIFIER START */ 19303 /******************************************************************/ 19304 19305 /* 19306 * Function: 19307 * bcm_mn_switch_obm_dscp_classifier_mapping_multi_set 19308 * Purpose: 19309 * Set the mapping of bcm_obm_code_point to bcm_obm_priority 19310 * for multiple entries of dscp classifier type. 19311 * Parameters: 19312 * unit - (IN) Unit number. 19313 * phy_port - (IN) Physical port. 19314 * pgw - (IN) PGW index (0 0r 1). 19315 * array_count - (IN) Number of dscp entries. 19316 * switch_obm_classifier - (IN) Array of dscp entries. 19317 * Returns: 19318 * BCM_E_xxx 19319 */ 19320 19321 STATIC 19322 int bcm_mn_switch_obm_dscp_classifier_mapping_multi_set( 19323 int unit, 19324 int phy_port, 19325 int pgw, 19326 int array_count, 19327 bcm_switch_obm_classifier_t *switch_obm_classifier) 19328 { 19329 int i, code_point, ob_priority; 19330 int entry_index[4], shadow_base_index; 19331 idb_obm0_dscp_map_port0_entry_t entry[4]; 19332 bcm_switch_obm_classifier_t *classifier_ptr = NULL; 19333 soc_mem_t mem; 19334 19335 static const soc_mem_t obm_dscp_map_port_mem[] = { 19336 IDB_OBM0_DSCP_MAP_PORT0m, IDB_OBM0_DSCP_MAP_PORT1m, 19337 IDB_OBM0_DSCP_MAP_PORT2m, IDB_OBM0_DSCP_MAP_PORT3m, 19338 IDB_OBM1_DSCP_MAP_PORT0m, IDB_OBM1_DSCP_MAP_PORT1m, 19339 IDB_OBM1_DSCP_MAP_PORT2m, IDB_OBM1_DSCP_MAP_PORT3m, 19340 IDB_OBM2_DSCP_MAP_PORT0m, IDB_OBM2_DSCP_MAP_PORT1m, 19341 IDB_OBM2_DSCP_MAP_PORT2m, IDB_OBM2_DSCP_MAP_PORT3m, 19342 IDB_OBM3_DSCP_MAP_PORT0m, IDB_OBM3_DSCP_MAP_PORT1m, 19343 IDB_OBM3_DSCP_MAP_PORT2m, IDB_OBM3_DSCP_MAP_PORT3m, 19344 IDB_OBM4_DSCP_MAP_PORT0m, IDB_OBM4_DSCP_MAP_PORT1m, 19345 IDB_OBM4_DSCP_MAP_PORT2m, IDB_OBM4_DSCP_MAP_PORT3m, 19346 IDB_OBM5_DSCP_MAP_PORT0m, IDB_OBM5_DSCP_MAP_PORT1m, 19347 IDB_OBM5_DSCP_MAP_PORT2m, IDB_OBM5_DSCP_MAP_PORT3m, 19348 IDB_OBM6_DSCP_MAP_PORT0m, IDB_OBM6_DSCP_MAP_PORT1m, 19349 IDB_OBM6_DSCP_MAP_PORT2m, IDB_OBM6_DSCP_MAP_PORT3m, 19350 IDB_OBM7_DSCP_MAP_PORT0m, IDB_OBM7_DSCP_MAP_PORT1m, 19351 IDB_OBM7_DSCP_MAP_PORT2m, IDB_OBM7_DSCP_MAP_PORT3m 19352 }; 19353 static const soc_field_t offset_ob_prio[] = { 19354 OFFSET0_OB_PRIORITYf, OFFSET1_OB_PRIORITYf, OFFSET2_OB_PRIORITYf, 19355 OFFSET3_OB_PRIORITYf, OFFSET4_OB_PRIORITYf, OFFSET5_OB_PRIORITYf, 19356 OFFSET6_OB_PRIORITYf, OFFSET7_OB_PRIORITYf, OFFSET8_OB_PRIORITYf, 19357 OFFSET9_OB_PRIORITYf, OFFSET10_OB_PRIORITYf, OFFSET11_OB_PRIORITYf, 19358 OFFSET12_OB_PRIORITYf, OFFSET13_OB_PRIORITYf, OFFSET14_OB_PRIORITYf, 19359 OFFSET15_OB_PRIORITYf 19360 }; 19361 19362 mem = obm_dscp_map_port_mem[(phy_port - 1) % _MN_PORTS_PER_PGW]; 19363 shadow_base_index = pgw * soc_mem_index_count(unit, mem); 19364 for (i = 0; i < 4; i++) { 19365 entry_index[i] = 0; 19366 sal_memset(&entry[i], 0, sizeof(entry[i])); 19367 SOC_IF_ERROR_RETURN(soc_monterey_shadow_entry_get(unit, mem, 19368 shadow_base_index + i, &entry[i])); 19369 } 19370 19371 for (i = 0; i < array_count; i++) { 19372 classifier_ptr = switch_obm_classifier + i; 19373 code_point = classifier_ptr->obm_code_point; 19374 ob_priority = classifier_ptr->obm_priority; 19375 if (code_point < BCM_OBM_DSCP_CHUNK_SIZE) { 19376 soc_mem_field32_set(unit, mem, &entry[0], 19377 offset_ob_prio[code_point], ob_priority); 19378 entry_index[0] = 1; 19379 } else if (code_point < 2 * BCM_OBM_DSCP_CHUNK_SIZE ) { 19380 soc_mem_field32_set(unit, mem, &entry[1], 19381 offset_ob_prio[code_point % BCM_OBM_DSCP_CHUNK_SIZE], 19382 ob_priority); 19383 entry_index[1] = 1; 19384 } else if (code_point < 3 * BCM_OBM_DSCP_CHUNK_SIZE) { 19385 soc_mem_field32_set(unit, mem, &entry[2], 19386 offset_ob_prio[code_point % BCM_OBM_DSCP_CHUNK_SIZE], 19387 ob_priority); 19388 entry_index[2] = 1; 19389 } else { 19390 soc_mem_field32_set(unit, mem, &entry[3], 19391 offset_ob_prio[code_point % BCM_OBM_DSCP_CHUNK_SIZE], 19392 ob_priority); 19393 entry_index[3] = 1; 19394 } 19395 } 19396 for (i = 0; i < 4; i++) { 19397 if (entry_index[i]) { 19398 SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem, PGW_CL_BLOCK(unit, pgw), 19399 i, &entry[i])); 19400 SOC_IF_ERROR_RETURN(soc_monterey_shadow_entry_set(unit, mem, 19401 shadow_base_index + i, &entry[i])); 19402 } 19403 } 19404 return BCM_E_NONE; 19405 19406 } 19407 /* 19408 * Function: 19409 * bcm_mn_switch_obm_dscp_classifier_mapping_multi_get 19410 * Purpose: 19411 * Set the mapping of bcm_obm_code_point to bcm_obm_priority 19412 * for multiple entries of dscp classifier type. 19413 * Parameters: 19414 * unit - (IN) Unit number. 19415 * phy_port - (IN) Physical port. 19416 * pgw - (IN) PGW index (0 0r 1). 19417 * array_max - (IN) Maximum number of entries. 19418 * switch_obm_classifier - (IN/OUT) Array of dscp entries. 19419 * array_count - (OUT) Number of dscp entries. 19420 * Returns: 19421 * BCM_E_xxx 19422 */ 19423 STATIC 19424 int bcm_mn_switch_obm_dscp_classifier_mapping_multi_get( 19425 int unit, 19426 int phy_port, 19427 int pgw, 19428 int array_max, 19429 bcm_switch_obm_classifier_t *switch_obm_classifier, 19430 int *array_count) 19431 { 19432 int i, code_point, ob_priority, shadow_base_index; 19433 idb_obm0_dscp_map_port0_entry_t entry[4]; 19434 bcm_switch_obm_classifier_t *classifier_ptr = NULL; 19435 soc_mem_t mem; 19436 19437 static const soc_mem_t obm_dscp_map_port_mem[] = { 19438 IDB_OBM0_DSCP_MAP_PORT0m, IDB_OBM0_DSCP_MAP_PORT1m, 19439 IDB_OBM0_DSCP_MAP_PORT2m, IDB_OBM0_DSCP_MAP_PORT3m, 19440 IDB_OBM1_DSCP_MAP_PORT0m, IDB_OBM1_DSCP_MAP_PORT1m, 19441 IDB_OBM1_DSCP_MAP_PORT2m, IDB_OBM1_DSCP_MAP_PORT3m, 19442 IDB_OBM2_DSCP_MAP_PORT0m, IDB_OBM2_DSCP_MAP_PORT1m, 19443 IDB_OBM2_DSCP_MAP_PORT2m, IDB_OBM2_DSCP_MAP_PORT3m, 19444 IDB_OBM3_DSCP_MAP_PORT0m, IDB_OBM3_DSCP_MAP_PORT1m, 19445 IDB_OBM3_DSCP_MAP_PORT2m, IDB_OBM3_DSCP_MAP_PORT3m, 19446 IDB_OBM4_DSCP_MAP_PORT0m, IDB_OBM4_DSCP_MAP_PORT1m, 19447 IDB_OBM4_DSCP_MAP_PORT2m, IDB_OBM4_DSCP_MAP_PORT3m, 19448 IDB_OBM5_DSCP_MAP_PORT0m, IDB_OBM5_DSCP_MAP_PORT1m, 19449 IDB_OBM5_DSCP_MAP_PORT2m, IDB_OBM5_DSCP_MAP_PORT3m, 19450 IDB_OBM6_DSCP_MAP_PORT0m, IDB_OBM6_DSCP_MAP_PORT1m, 19451 IDB_OBM6_DSCP_MAP_PORT2m, IDB_OBM6_DSCP_MAP_PORT3m, 19452 IDB_OBM7_DSCP_MAP_PORT0m, IDB_OBM7_DSCP_MAP_PORT1m, 19453 IDB_OBM7_DSCP_MAP_PORT2m, IDB_OBM7_DSCP_MAP_PORT3m 19454 }; 19455 static const soc_field_t offset_ob_prio[] = { 19456 OFFSET0_OB_PRIORITYf, OFFSET1_OB_PRIORITYf, OFFSET2_OB_PRIORITYf, 19457 OFFSET3_OB_PRIORITYf, OFFSET4_OB_PRIORITYf, OFFSET5_OB_PRIORITYf, 19458 OFFSET6_OB_PRIORITYf, OFFSET7_OB_PRIORITYf, OFFSET8_OB_PRIORITYf, 19459 OFFSET9_OB_PRIORITYf, OFFSET10_OB_PRIORITYf, OFFSET11_OB_PRIORITYf, 19460 OFFSET12_OB_PRIORITYf, OFFSET13_OB_PRIORITYf, OFFSET14_OB_PRIORITYf, 19461 OFFSET15_OB_PRIORITYf 19462 }; 19463 19464 mem = obm_dscp_map_port_mem[(phy_port - 1) % _MN_PORTS_PER_PGW]; 19465 shadow_base_index = pgw * soc_mem_index_count(unit, mem); 19466 for (i = 0; i < 4; i++) { 19467 sal_memset(&entry[i], 0, sizeof(entry[i])); 19468 SOC_IF_ERROR_RETURN(soc_monterey_shadow_entry_get(unit, mem, 19469 shadow_base_index + i, &entry[i])); 19470 } 19471 19472 for (i = 0; i < *array_count; i++) { 19473 classifier_ptr = switch_obm_classifier + i; 19474 code_point = classifier_ptr->obm_code_point; 19475 if (code_point < BCM_OBM_DSCP_CHUNK_SIZE) { 19476 ob_priority = soc_mem_field32_get(unit, mem, &entry[0], 19477 offset_ob_prio[code_point]); 19478 } else if (code_point < 2 * BCM_OBM_DSCP_CHUNK_SIZE) { 19479 ob_priority = soc_mem_field32_get(unit, mem, &entry[1], 19480 offset_ob_prio[code_point % BCM_OBM_DSCP_CHUNK_SIZE]); 19481 } else if (code_point < 3 * BCM_OBM_DSCP_CHUNK_SIZE) { 19482 ob_priority = soc_mem_field32_get(unit, mem, &entry[2], 19483 offset_ob_prio[code_point % BCM_OBM_DSCP_CHUNK_SIZE]); 19484 } else { 19485 ob_priority = soc_mem_field32_get(unit, mem, &entry[3], 19486 offset_ob_prio[code_point % BCM_OBM_DSCP_CHUNK_SIZE]); 19487 } 19488 classifier_ptr->obm_priority = ob_priority; 19489 } 19490 return BCM_E_NONE; 19491 19492 } 19493 19494 /* 19495 * Function: 19496 * bcm_mn_switch_obm_mpls_classifier_mapping_multi_set 19497 * Purpose: 19498 * Set the mapping of bcm_obm_code_point to bcm_obm_priority 19499 * for multiple entries of mpls classifier type. 19500 * Parameters: 19501 * unit - (IN) Unit number. 19502 * phy_port - (IN) Physical port. 19503 * pgw - (IN) PGW index (0 0r 1). 19504 * array_count - (IN) Number of mpls entries. 19505 * switch_obm_classifier - (IN) Array of mpls entries. 19506 * Returns: 19507 * BCM_E_xxx 19508 */ 19509 STATIC 19510 int bcm_mn_switch_obm_mpls_classifier_mapping_multi_set( 19511 int unit, 19512 int phy_port, 19513 int pgw, 19514 int array_count, 19515 bcm_switch_obm_classifier_t *switch_obm_classifier) 19516 { 19517 int i, code_point, ob_priority; 19518 idb_obm0_mpls_map_port0_entry_t entry; 19519 bcm_switch_obm_classifier_t *classifier_ptr = NULL; 19520 soc_mem_t mem; 19521 19522 static const soc_mem_t obm_mpls_map_port_mem[] = { 19523 IDB_OBM0_MPLS_MAP_PORT0m, IDB_OBM0_MPLS_MAP_PORT1m, 19524 IDB_OBM0_MPLS_MAP_PORT2m, IDB_OBM0_MPLS_MAP_PORT3m, 19525 IDB_OBM1_MPLS_MAP_PORT0m, IDB_OBM1_MPLS_MAP_PORT1m, 19526 IDB_OBM1_MPLS_MAP_PORT2m, IDB_OBM1_MPLS_MAP_PORT3m, 19527 IDB_OBM2_MPLS_MAP_PORT0m, IDB_OBM2_MPLS_MAP_PORT1m, 19528 IDB_OBM2_MPLS_MAP_PORT2m, IDB_OBM2_MPLS_MAP_PORT3m, 19529 IDB_OBM3_MPLS_MAP_PORT0m, IDB_OBM3_MPLS_MAP_PORT1m, 19530 IDB_OBM3_MPLS_MAP_PORT2m, IDB_OBM3_MPLS_MAP_PORT3m, 19531 IDB_OBM4_MPLS_MAP_PORT0m, IDB_OBM4_MPLS_MAP_PORT1m, 19532 IDB_OBM4_MPLS_MAP_PORT2m, IDB_OBM4_MPLS_MAP_PORT3m, 19533 IDB_OBM5_MPLS_MAP_PORT0m, IDB_OBM5_MPLS_MAP_PORT1m, 19534 IDB_OBM5_MPLS_MAP_PORT2m, IDB_OBM5_MPLS_MAP_PORT3m, 19535 IDB_OBM6_MPLS_MAP_PORT0m, IDB_OBM6_MPLS_MAP_PORT1m, 19536 IDB_OBM6_MPLS_MAP_PORT2m, IDB_OBM6_MPLS_MAP_PORT3m, 19537 IDB_OBM7_MPLS_MAP_PORT0m, IDB_OBM7_MPLS_MAP_PORT1m, 19538 IDB_OBM7_MPLS_MAP_PORT2m, IDB_OBM7_MPLS_MAP_PORT3m 19539 }; 19540 static const soc_field_t offset_ob_prio[] = { 19541 OFFSET0_OB_PRIORITYf, OFFSET1_OB_PRIORITYf, 19542 OFFSET2_OB_PRIORITYf, OFFSET3_OB_PRIORITYf, 19543 OFFSET4_OB_PRIORITYf, OFFSET5_OB_PRIORITYf, 19544 OFFSET6_OB_PRIORITYf, OFFSET7_OB_PRIORITYf 19545 }; 19546 19547 mem = obm_mpls_map_port_mem[(phy_port - 1) % _MN_PORTS_PER_PGW]; 19548 sal_memset(&entry, 0, sizeof(entry)); 19549 SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, 19550 PGW_CL_BLOCK(unit, pgw), 0, &entry)); 19551 19552 for (i = 0; i < array_count; i++) { 19553 classifier_ptr = switch_obm_classifier + i; 19554 code_point = classifier_ptr->obm_code_point; 19555 ob_priority = classifier_ptr->obm_priority; 19556 soc_mem_field32_set(unit, mem, &entry, 19557 offset_ob_prio[code_point % 8], ob_priority); 19558 } 19559 SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem, 19560 PGW_CL_BLOCK(unit, pgw), 0, &entry)); 19561 return BCM_E_NONE; 19562 } 19563 19564 /* 19565 * Function: 19566 * bcm_mn_switch_obm_mpls_classifier_mapping_multi_get 19567 * Purpose: 19568 * Get the mapping of bcm_obm_code_point to bcm_obm_priority 19569 * for multiple entries of mpls classifier type. 19570 * Parameters: 19571 * unit - (IN) Unit number. 19572 * phy_port - (IN) Physical port. 19573 * pgw - (IN) PGW index (0 0r 1). 19574 * array_max - (IN) Maximum number of entries. 19575 * switch_obm_classifier - (IN/OUT) Array of mpls entries. 19576 * array_count - (OUT) Number of dscp entries. 19577 * Returns: 19578 * BCM_E_xxx 19579 */ 19580 19581 STATIC 19582 int bcm_mn_switch_obm_mpls_classifier_mapping_multi_get( 19583 int unit, 19584 int phy_port, 19585 int pgw, 19586 int array_max, 19587 bcm_switch_obm_classifier_t *switch_obm_classifier, 19588 int *array_count) 19589 { 19590 int i, code_point, ob_priority; 19591 idb_obm0_mpls_map_port0_entry_t entry; 19592 bcm_switch_obm_classifier_t *classifier_ptr = NULL; 19593 soc_mem_t mem; 19594 19595 static const soc_mem_t obm_mpls_map_port_mem[] = { 19596 IDB_OBM0_MPLS_MAP_PORT0m, IDB_OBM0_MPLS_MAP_PORT1m, 19597 IDB_OBM0_MPLS_MAP_PORT2m, IDB_OBM0_MPLS_MAP_PORT3m, 19598 IDB_OBM1_MPLS_MAP_PORT0m, IDB_OBM1_MPLS_MAP_PORT1m, 19599 IDB_OBM1_MPLS_MAP_PORT2m, IDB_OBM1_MPLS_MAP_PORT3m, 19600 IDB_OBM2_MPLS_MAP_PORT0m, IDB_OBM2_MPLS_MAP_PORT1m, 19601 IDB_OBM2_MPLS_MAP_PORT2m, IDB_OBM2_MPLS_MAP_PORT3m, 19602 IDB_OBM3_MPLS_MAP_PORT0m, IDB_OBM3_MPLS_MAP_PORT1m, 19603 IDB_OBM3_MPLS_MAP_PORT2m, IDB_OBM3_MPLS_MAP_PORT3m, 19604 IDB_OBM4_MPLS_MAP_PORT0m, IDB_OBM4_MPLS_MAP_PORT1m, 19605 IDB_OBM4_MPLS_MAP_PORT2m, IDB_OBM4_MPLS_MAP_PORT3m, 19606 IDB_OBM5_MPLS_MAP_PORT0m, IDB_OBM5_MPLS_MAP_PORT1m, 19607 IDB_OBM5_MPLS_MAP_PORT2m, IDB_OBM5_MPLS_MAP_PORT3m, 19608 IDB_OBM6_MPLS_MAP_PORT0m, IDB_OBM6_MPLS_MAP_PORT1m, 19609 IDB_OBM6_MPLS_MAP_PORT2m, IDB_OBM6_MPLS_MAP_PORT3m, 19610 IDB_OBM7_MPLS_MAP_PORT0m, IDB_OBM7_MPLS_MAP_PORT1m, 19611 IDB_OBM7_MPLS_MAP_PORT2m, IDB_OBM7_MPLS_MAP_PORT3m 19612 }; 19613 static const soc_field_t offset_ob_prio[] = { 19614 OFFSET0_OB_PRIORITYf, OFFSET1_OB_PRIORITYf, 19615 OFFSET2_OB_PRIORITYf, OFFSET3_OB_PRIORITYf, 19616 OFFSET4_OB_PRIORITYf, OFFSET5_OB_PRIORITYf, 19617 OFFSET6_OB_PRIORITYf, OFFSET7_OB_PRIORITYf 19618 }; 19619 19620 mem = obm_mpls_map_port_mem[(phy_port - 1) % _MN_PORTS_PER_PGW]; 19621 sal_memset(&entry, 0, sizeof(entry)); 19622 SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, 19623 PGW_CL_BLOCK(unit, pgw), 0, &entry)); 19624 19625 for (i = 0; i < *array_count; i++) { 19626 classifier_ptr = switch_obm_classifier + i; 19627 code_point = classifier_ptr->obm_code_point; 19628 ob_priority = soc_mem_field32_get(unit, mem, &entry, 19629 offset_ob_prio[code_point]); 19630 classifier_ptr->obm_priority = ob_priority; 19631 } 19632 return BCM_E_NONE; 19633 } 19634 19635 /* 19636 * Function: 19637 * bcm_mn_switch_obm_etag_classifier_mapping_multi_set 19638 * Purpose: 19639 * Set the mapping of bcm_obm_code_point to bcm_obm_priority 19640 * for multiple entries of etag classifier type. 19641 * Parameters: 19642 * unit - (IN) Unit number. 19643 * phy_port - (IN) Physical port. 19644 * pgw - (IN) PGW index (0 0r 1). 19645 * array_count - (IN) Number of etag entries. 19646 * switch_obm_classifier - (IN) Array of etag entries. 19647 * Returns: 19648 * BCM_E_xxx 19649 */ 19650 19651 STATIC 19652 int bcm_mn_switch_obm_etag_classifier_mapping_multi_set( 19653 int unit, 19654 int phy_port, 19655 int pgw, 19656 int array_count, 19657 bcm_switch_obm_classifier_t *switch_obm_classifier) 19658 { 19659 int i, code_point, ob_priority; 19660 idb_obm0_etag_map_port0_entry_t entry; 19661 bcm_switch_obm_classifier_t *classifier_ptr = NULL; 19662 soc_mem_t mem; 19663 19664 static const soc_mem_t obm_etag_map_port_mem[] = { 19665 IDB_OBM0_ETAG_MAP_PORT0m, IDB_OBM0_ETAG_MAP_PORT1m, 19666 IDB_OBM0_ETAG_MAP_PORT2m, IDB_OBM0_ETAG_MAP_PORT3m, 19667 IDB_OBM1_ETAG_MAP_PORT0m, IDB_OBM1_ETAG_MAP_PORT1m, 19668 IDB_OBM1_ETAG_MAP_PORT2m, IDB_OBM1_ETAG_MAP_PORT3m, 19669 IDB_OBM2_ETAG_MAP_PORT0m, IDB_OBM2_ETAG_MAP_PORT1m, 19670 IDB_OBM2_ETAG_MAP_PORT2m, IDB_OBM2_ETAG_MAP_PORT3m, 19671 IDB_OBM3_ETAG_MAP_PORT0m, IDB_OBM3_ETAG_MAP_PORT1m, 19672 IDB_OBM3_ETAG_MAP_PORT2m, IDB_OBM3_ETAG_MAP_PORT3m, 19673 IDB_OBM4_ETAG_MAP_PORT0m, IDB_OBM4_ETAG_MAP_PORT1m, 19674 IDB_OBM4_ETAG_MAP_PORT2m, IDB_OBM4_ETAG_MAP_PORT3m, 19675 IDB_OBM5_ETAG_MAP_PORT0m, IDB_OBM5_ETAG_MAP_PORT1m, 19676 IDB_OBM5_ETAG_MAP_PORT2m, IDB_OBM5_ETAG_MAP_PORT3m, 19677 IDB_OBM6_ETAG_MAP_PORT0m, IDB_OBM6_ETAG_MAP_PORT1m, 19678 IDB_OBM6_ETAG_MAP_PORT2m, IDB_OBM6_ETAG_MAP_PORT3m, 19679 IDB_OBM7_ETAG_MAP_PORT0m, IDB_OBM7_ETAG_MAP_PORT1m, 19680 IDB_OBM7_ETAG_MAP_PORT2m, IDB_OBM7_ETAG_MAP_PORT3m 19681 }; 19682 19683 static const soc_field_t offset_ob_prio[] = { 19684 OFFSET0_OB_PRIORITYf, OFFSET1_OB_PRIORITYf, 19685 OFFSET2_OB_PRIORITYf, OFFSET3_OB_PRIORITYf, 19686 OFFSET4_OB_PRIORITYf, OFFSET5_OB_PRIORITYf, 19687 OFFSET6_OB_PRIORITYf, OFFSET7_OB_PRIORITYf 19688 }; 19689 19690 mem = obm_etag_map_port_mem[(phy_port - 1) % _MN_PORTS_PER_PGW]; 19691 sal_memset(&entry, 0, sizeof(entry)); 19692 SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, 19693 PGW_CL_BLOCK(unit, pgw), 0, &entry)); 19694 19695 for (i = 0; i < array_count; i++) { 19696 classifier_ptr = switch_obm_classifier + i; 19697 code_point = classifier_ptr->obm_code_point; 19698 ob_priority = classifier_ptr->obm_priority; 19699 soc_mem_field32_set(unit, mem, &entry, 19700 offset_ob_prio[code_point], ob_priority); 19701 } 19702 SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem, 19703 PGW_CL_BLOCK(unit, pgw), 0, &entry)); 19704 return BCM_E_NONE; 19705 } 19706 19707 /* 19708 * Function: 19709 * bcm_mn_switch_obm_etag_classifier_mapping_multi_get 19710 * Purpose: 19711 * Set the mapping of bcm_obm_code_point to bcm_obm_priority 19712 * for multiple entries of etag classifier type. 19713 * Parameters: 19714 * unit - (IN) Unit number. 19715 * phy_port - (IN) Physical port. 19716 * pgw - (IN) PGW index (0 0r 1). 19717 * array_max - (IN) Maximum number of entries. 19718 * switch_obm_classifier - (IN/OUT) Array of etag entries. 19719 * array_count - (OUT) Number of etag entries. 19720 * Returns: 19721 * BCM_E_xxx 19722 */ 19723 19724 STATIC 19725 int bcm_mn_switch_obm_etag_classifier_mapping_multi_get( 19726 int unit, 19727 int phy_port, 19728 int pgw, 19729 int array_max, 19730 bcm_switch_obm_classifier_t *switch_obm_classifier, 19731 int *array_count) 19732 { 19733 int i, code_point, ob_priority; 19734 idb_obm0_etag_map_port0_entry_t entry; 19735 bcm_switch_obm_classifier_t *classifier_ptr = NULL; 19736 soc_mem_t mem; 19737 19738 static const soc_mem_t obm_etag_map_port_mem[] = { 19739 IDB_OBM0_ETAG_MAP_PORT0m, IDB_OBM0_ETAG_MAP_PORT1m, 19740 IDB_OBM0_ETAG_MAP_PORT2m, IDB_OBM0_ETAG_MAP_PORT3m, 19741 IDB_OBM1_ETAG_MAP_PORT0m, IDB_OBM1_ETAG_MAP_PORT1m, 19742 IDB_OBM1_ETAG_MAP_PORT2m, IDB_OBM1_ETAG_MAP_PORT3m, 19743 IDB_OBM2_ETAG_MAP_PORT0m, IDB_OBM2_ETAG_MAP_PORT1m, 19744 IDB_OBM2_ETAG_MAP_PORT2m, IDB_OBM2_ETAG_MAP_PORT3m, 19745 IDB_OBM3_ETAG_MAP_PORT0m, IDB_OBM3_ETAG_MAP_PORT1m, 19746 IDB_OBM3_ETAG_MAP_PORT2m, IDB_OBM3_ETAG_MAP_PORT3m, 19747 IDB_OBM4_ETAG_MAP_PORT0m, IDB_OBM4_ETAG_MAP_PORT1m, 19748 IDB_OBM4_ETAG_MAP_PORT2m, IDB_OBM4_ETAG_MAP_PORT3m, 19749 IDB_OBM5_ETAG_MAP_PORT0m, IDB_OBM5_ETAG_MAP_PORT1m, 19750 IDB_OBM5_ETAG_MAP_PORT2m, IDB_OBM5_ETAG_MAP_PORT3m, 19751 IDB_OBM6_ETAG_MAP_PORT0m, IDB_OBM6_ETAG_MAP_PORT1m, 19752 IDB_OBM6_ETAG_MAP_PORT2m, IDB_OBM6_ETAG_MAP_PORT3m, 19753 IDB_OBM7_ETAG_MAP_PORT0m, IDB_OBM7_ETAG_MAP_PORT1m, 19754 IDB_OBM7_ETAG_MAP_PORT2m, IDB_OBM7_ETAG_MAP_PORT3m 19755 }; 19756 19757 static const soc_field_t offset_ob_prio[] = { 19758 OFFSET0_OB_PRIORITYf, OFFSET1_OB_PRIORITYf, 19759 OFFSET2_OB_PRIORITYf, OFFSET3_OB_PRIORITYf, 19760 OFFSET4_OB_PRIORITYf, OFFSET5_OB_PRIORITYf, 19761 OFFSET6_OB_PRIORITYf, OFFSET7_OB_PRIORITYf 19762 }; 19763 19764 mem = obm_etag_map_port_mem[(phy_port - 1) % _MN_PORTS_PER_PGW]; 19765 sal_memset(&entry, 0, sizeof(entry)); 19766 SOC_IF_ERROR_RETURN(soc_mem_read(unit, 19767 mem, PGW_CL_BLOCK(unit, pgw), 0, &entry)); 19768 19769 for (i = 0; i < *array_count; i++) { 19770 classifier_ptr = switch_obm_classifier + i; 19771 code_point = classifier_ptr->obm_code_point; 19772 ob_priority = soc_mem_field32_get(unit, mem, &entry, 19773 offset_ob_prio[code_point]); 19774 classifier_ptr->obm_priority = ob_priority; 19775 } 19776 return BCM_E_NONE; 19777 } 19778 19779 /* 19780 * Function: 19781 * bcm_mn_switch_obm_vlan_classifier_mapping_multi_set 19782 * Purpose: 19783 * Set the mapping of bcm_obm_code_point to bcm_obm_priority 19784 * for multiple entries of vlan classifier type. 19785 * Parameters: 19786 * unit - (IN) Unit number. 19787 * phy_port - (IN) Physical port. 19788 * pgw - (IN) PGW index (0 0r 1). 19789 * array_count - (IN) Number of vlan entries. 19790 * switch_obm_classifier - (IN) Array of vlan entries. 19791 * Returns: 19792 * BCM_E_xxx 19793 */ 19794 19795 STATIC 19796 int bcm_mn_switch_obm_vlan_classifier_mapping_multi_set( 19797 int unit, 19798 int phy_port, 19799 int pgw, 19800 int array_count, 19801 bcm_switch_obm_classifier_t *switch_obm_classifier) 19802 { 19803 int i, code_point, ob_priority; 19804 idb_obm0_pri_map_port0_entry_t entry; 19805 bcm_switch_obm_classifier_t *classifier_ptr = NULL; 19806 soc_mem_t mem; 19807 19808 static const soc_mem_t obm_pri_map_port_mem[] = { 19809 IDB_OBM0_PRI_MAP_PORT0m, IDB_OBM0_PRI_MAP_PORT1m, 19810 IDB_OBM0_PRI_MAP_PORT2m, IDB_OBM0_PRI_MAP_PORT3m, 19811 IDB_OBM1_PRI_MAP_PORT0m, IDB_OBM1_PRI_MAP_PORT1m, 19812 IDB_OBM1_PRI_MAP_PORT2m, IDB_OBM1_PRI_MAP_PORT3m, 19813 IDB_OBM2_PRI_MAP_PORT0m, IDB_OBM2_PRI_MAP_PORT1m, 19814 IDB_OBM2_PRI_MAP_PORT2m, IDB_OBM2_PRI_MAP_PORT3m, 19815 IDB_OBM3_PRI_MAP_PORT0m, IDB_OBM3_PRI_MAP_PORT1m, 19816 IDB_OBM3_PRI_MAP_PORT2m, IDB_OBM3_PRI_MAP_PORT3m, 19817 IDB_OBM4_PRI_MAP_PORT0m, IDB_OBM4_PRI_MAP_PORT1m, 19818 IDB_OBM4_PRI_MAP_PORT2m, IDB_OBM4_PRI_MAP_PORT3m, 19819 IDB_OBM5_PRI_MAP_PORT0m, IDB_OBM5_PRI_MAP_PORT1m, 19820 IDB_OBM5_PRI_MAP_PORT2m, IDB_OBM5_PRI_MAP_PORT3m, 19821 IDB_OBM6_PRI_MAP_PORT0m, IDB_OBM6_PRI_MAP_PORT1m, 19822 IDB_OBM6_PRI_MAP_PORT2m, IDB_OBM6_PRI_MAP_PORT3m, 19823 IDB_OBM7_PRI_MAP_PORT0m, IDB_OBM7_PRI_MAP_PORT1m, 19824 IDB_OBM7_PRI_MAP_PORT2m, IDB_OBM7_PRI_MAP_PORT3m 19825 }; 19826 19827 static const soc_field_t offset_ob_prio[] = { 19828 OFFSET0_OB_PRIORITYf, OFFSET1_OB_PRIORITYf, 19829 OFFSET2_OB_PRIORITYf, OFFSET3_OB_PRIORITYf, 19830 OFFSET4_OB_PRIORITYf, OFFSET5_OB_PRIORITYf, 19831 OFFSET6_OB_PRIORITYf, OFFSET7_OB_PRIORITYf 19832 }; 19833 19834 mem = obm_pri_map_port_mem[(phy_port - 1) % _MN_PORTS_PER_PGW]; 19835 sal_memset(&entry, 0, sizeof(entry)); 19836 SOC_IF_ERROR_RETURN(soc_mem_read(unit, 19837 mem, PGW_CL_BLOCK(unit, pgw), 0, &entry)); 19838 19839 for (i = 0; i < array_count; i++) { 19840 classifier_ptr = switch_obm_classifier + i; 19841 code_point = classifier_ptr->obm_code_point; 19842 ob_priority = classifier_ptr->obm_priority; 19843 soc_mem_field32_set(unit, mem, &entry, 19844 offset_ob_prio[code_point], ob_priority); 19845 } 19846 SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem, 19847 PGW_CL_BLOCK(unit, pgw), 0, &entry)); 19848 return BCM_E_NONE; 19849 } 19850 19851 /* 19852 * Function: 19853 * bcm_mn_switch_obm_vlan_classifier_mapping_multi_get 19854 * Purpose: 19855 * Set the mapping of bcm_obm_code_point to bcm_obm_priority 19856 * for multiple entries of vlan classifier type. 19857 * Parameters: 19858 * unit - (IN) Unit number. 19859 * phy_port - (IN) Physical port. 19860 * pgw - (IN) PGW index (0 0r 1). 19861 * array_max - (IN) Maximum number of entries. 19862 * switch_obm_classifier - (IN/OUT) Array of vlan entries. 19863 * array_count - (OUT) Number of vlan entries. 19864 * Returns: 19865 * BCM_E_xxx 19866 */ 19867 STATIC 19868 int bcm_mn_switch_obm_vlan_classifier_mapping_multi_get( 19869 int unit, 19870 int phy_port, 19871 int pgw, 19872 int array_max, 19873 bcm_switch_obm_classifier_t *switch_obm_classifier, 19874 int *array_count) 19875 { 19876 int i, code_point, ob_priority; 19877 idb_obm0_pri_map_port0_entry_t entry; 19878 bcm_switch_obm_classifier_t *classifier_ptr = NULL; 19879 soc_mem_t mem; 19880 19881 static const soc_mem_t obm_pri_map_port_mem[] = { 19882 IDB_OBM0_PRI_MAP_PORT0m, IDB_OBM0_PRI_MAP_PORT1m, 19883 IDB_OBM0_PRI_MAP_PORT2m, IDB_OBM0_PRI_MAP_PORT3m, 19884 IDB_OBM1_PRI_MAP_PORT0m, IDB_OBM1_PRI_MAP_PORT1m, 19885 IDB_OBM1_PRI_MAP_PORT2m, IDB_OBM1_PRI_MAP_PORT3m, 19886 IDB_OBM2_PRI_MAP_PORT0m, IDB_OBM2_PRI_MAP_PORT1m, 19887 IDB_OBM2_PRI_MAP_PORT2m, IDB_OBM2_PRI_MAP_PORT3m, 19888 IDB_OBM3_PRI_MAP_PORT0m, IDB_OBM3_PRI_MAP_PORT1m, 19889 IDB_OBM3_PRI_MAP_PORT2m, IDB_OBM3_PRI_MAP_PORT3m, 19890 IDB_OBM4_PRI_MAP_PORT0m, IDB_OBM4_PRI_MAP_PORT1m, 19891 IDB_OBM4_PRI_MAP_PORT2m, IDB_OBM4_PRI_MAP_PORT3m, 19892 IDB_OBM5_PRI_MAP_PORT0m, IDB_OBM5_PRI_MAP_PORT1m, 19893 IDB_OBM5_PRI_MAP_PORT2m, IDB_OBM5_PRI_MAP_PORT3m, 19894 IDB_OBM6_PRI_MAP_PORT0m, IDB_OBM6_PRI_MAP_PORT1m, 19895 IDB_OBM6_PRI_MAP_PORT2m, IDB_OBM6_PRI_MAP_PORT3m, 19896 IDB_OBM7_PRI_MAP_PORT0m, IDB_OBM7_PRI_MAP_PORT1m, 19897 IDB_OBM7_PRI_MAP_PORT2m, IDB_OBM7_PRI_MAP_PORT3m 19898 }; 19899 19900 static const soc_field_t offset_ob_prio[] = { 19901 OFFSET0_OB_PRIORITYf, OFFSET1_OB_PRIORITYf, 19902 OFFSET2_OB_PRIORITYf, OFFSET3_OB_PRIORITYf, 19903 OFFSET4_OB_PRIORITYf, OFFSET5_OB_PRIORITYf, 19904 OFFSET6_OB_PRIORITYf, OFFSET7_OB_PRIORITYf 19905 }; 19906 19907 mem = obm_pri_map_port_mem[(phy_port - 1) % _MN_PORTS_PER_PGW]; 19908 sal_memset(&entry, 0, sizeof(entry)); 19909 SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, 19910 PGW_CL_BLOCK(unit, pgw), 0, &entry)); 19911 19912 for (i = 0; i < *array_count; i++) { 19913 classifier_ptr = switch_obm_classifier + i; 19914 code_point = classifier_ptr->obm_code_point; 19915 ob_priority = soc_mem_field32_get(unit, mem, &entry, 19916 offset_ob_prio[code_point]); 19917 classifier_ptr->obm_priority = ob_priority; 19918 } 19919 return BCM_E_NONE; 19920 } 19921 19922 /* 19923 * Function: 19924 * bcm_mn_switch_obm_higig2_classifier_mapping_multi_set 19925 * Purpose: 19926 * Set the mapping of bcm_obm_code_point to bcm_obm_priority 19927 * for multiple entries of higig2 classifier type. 19928 * Parameters: 19929 * unit - (IN) Unit number. 19930 * phy_port - (IN) Physical port. 19931 * pgw - (IN) PGW index (0 0r 1). 19932 * array_count - (IN) Number of higig2 entries. 19933 * switch_obm_classifier - (IN) Array of higig2 entries. 19934 * Returns: 19935 * BCM_E_xxx 19936 */ 19937 STATIC 19938 int bcm_mn_switch_obm_higig2_classifier_mapping_multi_set( 19939 int unit, 19940 int phy_port, 19941 int pgw, 19942 int array_count, 19943 bcm_switch_obm_classifier_t *switch_obm_classifier) 19944 { 19945 int i, code_point, ob_priority; 19946 idb_obm0_pri_map_port0_entry_t entry; 19947 bcm_switch_obm_classifier_t *classifier_ptr = NULL; 19948 soc_mem_t mem; 19949 19950 static const soc_mem_t obm_pri_map_port_mem[] = { 19951 IDB_OBM0_PRI_MAP_PORT0m, IDB_OBM0_PRI_MAP_PORT1m, 19952 IDB_OBM0_PRI_MAP_PORT2m, IDB_OBM0_PRI_MAP_PORT3m, 19953 IDB_OBM1_PRI_MAP_PORT0m, IDB_OBM1_PRI_MAP_PORT1m, 19954 IDB_OBM1_PRI_MAP_PORT2m, IDB_OBM1_PRI_MAP_PORT3m, 19955 IDB_OBM2_PRI_MAP_PORT0m, IDB_OBM2_PRI_MAP_PORT1m, 19956 IDB_OBM2_PRI_MAP_PORT2m, IDB_OBM2_PRI_MAP_PORT3m, 19957 IDB_OBM3_PRI_MAP_PORT0m, IDB_OBM3_PRI_MAP_PORT1m, 19958 IDB_OBM3_PRI_MAP_PORT2m, IDB_OBM3_PRI_MAP_PORT3m, 19959 IDB_OBM4_PRI_MAP_PORT0m, IDB_OBM4_PRI_MAP_PORT1m, 19960 IDB_OBM4_PRI_MAP_PORT2m, IDB_OBM4_PRI_MAP_PORT3m, 19961 IDB_OBM5_PRI_MAP_PORT0m, IDB_OBM5_PRI_MAP_PORT1m, 19962 IDB_OBM5_PRI_MAP_PORT2m, IDB_OBM5_PRI_MAP_PORT3m, 19963 IDB_OBM6_PRI_MAP_PORT0m, IDB_OBM6_PRI_MAP_PORT1m, 19964 IDB_OBM6_PRI_MAP_PORT2m, IDB_OBM6_PRI_MAP_PORT3m, 19965 IDB_OBM7_PRI_MAP_PORT0m, IDB_OBM7_PRI_MAP_PORT1m, 19966 IDB_OBM7_PRI_MAP_PORT2m, IDB_OBM7_PRI_MAP_PORT3m 19967 }; 19968 19969 static const soc_field_t offset_ob_prio[] = { 19970 OFFSET0_OB_PRIORITYf, OFFSET1_OB_PRIORITYf, OFFSET2_OB_PRIORITYf, 19971 OFFSET3_OB_PRIORITYf, OFFSET4_OB_PRIORITYf, OFFSET5_OB_PRIORITYf, 19972 OFFSET6_OB_PRIORITYf, OFFSET7_OB_PRIORITYf, OFFSET8_OB_PRIORITYf, 19973 OFFSET9_OB_PRIORITYf, OFFSET10_OB_PRIORITYf, OFFSET11_OB_PRIORITYf, 19974 OFFSET12_OB_PRIORITYf, OFFSET13_OB_PRIORITYf, OFFSET14_OB_PRIORITYf, 19975 OFFSET15_OB_PRIORITYf 19976 }; 19977 19978 mem = obm_pri_map_port_mem[(phy_port - 1) % _MN_PORTS_PER_PGW]; 19979 sal_memset(&entry, 0, sizeof(entry)); 19980 SOC_IF_ERROR_RETURN(soc_monterey_shadow_entry_get(unit, mem, pgw, &entry)); 19981 19982 for (i = 0; i < array_count; i++) { 19983 classifier_ptr = switch_obm_classifier + i; 19984 code_point = classifier_ptr->obm_code_point; 19985 ob_priority = classifier_ptr->obm_priority; 19986 soc_mem_field32_set(unit, mem, &entry, 19987 offset_ob_prio[code_point], ob_priority); 19988 } 19989 SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem, 19990 PGW_CL_BLOCK(unit, pgw), 0, &entry)); 19991 SOC_IF_ERROR_RETURN(soc_monterey_shadow_entry_set(unit, mem, pgw, &entry)); 19992 return BCM_E_NONE; 19993 } 19994 19995 /* 19996 * Function: 19997 * bcm_mn_switch_obm_higig2_classifier_mapping_multi_get 19998 * Purpose: 19999 * Set the mapping of bcm_obm_code_point to bcm_obm_priority 20000 * for multiple entries of higig2 classifier type. 20001 * Parameters: 20002 * unit - (IN) Unit number. 20003 * phy_port - (IN) Physical port. 20004 * pgw - (IN) PGW index (0 0r 1). 20005 * array_max - (IN) Maximum number of entries. 20006 * switch_obm_classifier - (IN/OUT) Array of higig2 entries. 20007 * array_count - (OUT) Number of higig2 entries. 20008 * Returns: 20009 * BCM_E_xxx 20010 */ 20011 20012 STATIC 20013 int bcm_mn_switch_obm_higig2_classifier_mapping_multi_get( 20014 int unit, 20015 int phy_port, 20016 int pgw, 20017 int array_max, 20018 bcm_switch_obm_classifier_t *switch_obm_classifier, 20019 int *array_count) 20020 { 20021 int i, code_point, ob_priority; 20022 idb_obm0_pri_map_port0_entry_t entry; 20023 bcm_switch_obm_classifier_t *classifier_ptr = NULL; 20024 soc_mem_t mem; 20025 20026 static const soc_mem_t obm_pri_map_port_mem[] = { 20027 IDB_OBM0_PRI_MAP_PORT0m, IDB_OBM0_PRI_MAP_PORT1m, 20028 IDB_OBM0_PRI_MAP_PORT2m, IDB_OBM0_PRI_MAP_PORT3m, 20029 IDB_OBM1_PRI_MAP_PORT0m, IDB_OBM1_PRI_MAP_PORT1m, 20030 IDB_OBM1_PRI_MAP_PORT2m, IDB_OBM1_PRI_MAP_PORT3m, 20031 IDB_OBM2_PRI_MAP_PORT0m, IDB_OBM2_PRI_MAP_PORT1m, 20032 IDB_OBM2_PRI_MAP_PORT2m, IDB_OBM2_PRI_MAP_PORT3m, 20033 IDB_OBM3_PRI_MAP_PORT0m, IDB_OBM3_PRI_MAP_PORT1m, 20034 IDB_OBM3_PRI_MAP_PORT2m, IDB_OBM3_PRI_MAP_PORT3m, 20035 IDB_OBM4_PRI_MAP_PORT0m, IDB_OBM4_PRI_MAP_PORT1m, 20036 IDB_OBM4_PRI_MAP_PORT2m, IDB_OBM4_PRI_MAP_PORT3m, 20037 IDB_OBM5_PRI_MAP_PORT0m, IDB_OBM5_PRI_MAP_PORT1m, 20038 IDB_OBM5_PRI_MAP_PORT2m, IDB_OBM5_PRI_MAP_PORT3m, 20039 IDB_OBM6_PRI_MAP_PORT0m, IDB_OBM6_PRI_MAP_PORT1m, 20040 IDB_OBM6_PRI_MAP_PORT2m, IDB_OBM6_PRI_MAP_PORT3m, 20041 IDB_OBM7_PRI_MAP_PORT0m, IDB_OBM7_PRI_MAP_PORT1m, 20042 IDB_OBM7_PRI_MAP_PORT2m, IDB_OBM7_PRI_MAP_PORT3m 20043 }; 20044 20045 static const soc_field_t offset_ob_prio[] = { 20046 OFFSET0_OB_PRIORITYf, OFFSET1_OB_PRIORITYf, OFFSET2_OB_PRIORITYf, 20047 OFFSET3_OB_PRIORITYf, OFFSET4_OB_PRIORITYf, OFFSET5_OB_PRIORITYf, 20048 OFFSET6_OB_PRIORITYf, OFFSET7_OB_PRIORITYf, OFFSET8_OB_PRIORITYf, 20049 OFFSET9_OB_PRIORITYf, OFFSET10_OB_PRIORITYf, OFFSET11_OB_PRIORITYf, 20050 OFFSET12_OB_PRIORITYf, OFFSET13_OB_PRIORITYf, OFFSET14_OB_PRIORITYf, 20051 OFFSET15_OB_PRIORITYf 20052 }; 20053 20054 mem = obm_pri_map_port_mem[(phy_port - 1) % _MN_PORTS_PER_PGW]; 20055 sal_memset(&entry, 0, sizeof(entry)); 20056 SOC_IF_ERROR_RETURN(soc_monterey_shadow_entry_get(unit, mem, pgw, &entry)); 20057 20058 for (i = 0; i < *array_count; i++) { 20059 classifier_ptr = switch_obm_classifier + i; 20060 code_point = classifier_ptr->obm_code_point; 20061 ob_priority = soc_mem_field32_get(unit, mem, &entry, 20062 offset_ob_prio[code_point]); 20063 classifier_ptr->obm_priority = ob_priority; 20064 } 20065 return BCM_E_NONE; 20066 } 20067 /* 20068 * Function: 20069 * bcm_mn_switch_obm_field_classifier_mapping_multi_set 20070 * Purpose: 20071 * Match based on destination_mac, destination_mac_mask, 20072 * ethertype and ethertype_mask and assign bcm_obm_priority. 20073 * for multiple entries of mpls classifier type. 20074 * Parameters: 20075 * unit - (IN) Unit number. 20076 * phy_port - (IN) Physical port. 20077 * pgw - (IN) PGW index (0 0r 1). 20078 * array_count - (IN) Number of field entries. 20079 * switch_obm_classifier - (IN) Array of field entries. 20080 * Returns: 20081 * BCM_E_xxx 20082 */ 20083 STATIC 20084 int bcm_mn_switch_obm_field_classifier_mapping_multi_set( 20085 int unit, 20086 int phy_port, 20087 int pgw, 20088 int array_count, 20089 bcm_switch_obm_classifier_t *switch_obm_classifier) 20090 { 20091 uint64 rval64; 20092 uint32 rval_hi, rval_lo; 20093 bcm_switch_obm_classifier_t *classifier_ptr = NULL; 20094 soc_reg_t reg; 20095 int i, pgw_inst, enable = 0; 20096 20097 static const soc_reg_t obm_proto_control0_regs[] = { 20098 IDB_OBM0_PROTOCOL_CONTROL_0r, IDB_OBM1_PROTOCOL_CONTROL_0r, 20099 IDB_OBM2_PROTOCOL_CONTROL_0r, IDB_OBM3_PROTOCOL_CONTROL_0r, 20100 IDB_OBM4_PROTOCOL_CONTROL_0r, IDB_OBM5_PROTOCOL_CONTROL_0r, 20101 IDB_OBM6_PROTOCOL_CONTROL_0r, IDB_OBM7_PROTOCOL_CONTROL_0r 20102 }; 20103 static const soc_reg_t obm_proto_control1_regs[] = { 20104 IDB_OBM0_PROTOCOL_CONTROL_1r, IDB_OBM1_PROTOCOL_CONTROL_1r, 20105 IDB_OBM2_PROTOCOL_CONTROL_1r, IDB_OBM3_PROTOCOL_CONTROL_1r, 20106 IDB_OBM4_PROTOCOL_CONTROL_1r, IDB_OBM5_PROTOCOL_CONTROL_1r, 20107 IDB_OBM6_PROTOCOL_CONTROL_1r, IDB_OBM7_PROTOCOL_CONTROL_1r 20108 }; 20109 static const soc_reg_t obm_proto_control2_regs[] = { 20110 IDB_OBM0_PROTOCOL_CONTROL_2r, IDB_OBM1_PROTOCOL_CONTROL_2r, 20111 IDB_OBM2_PROTOCOL_CONTROL_2r, IDB_OBM3_PROTOCOL_CONTROL_2r, 20112 IDB_OBM4_PROTOCOL_CONTROL_2r, IDB_OBM5_PROTOCOL_CONTROL_2r, 20113 IDB_OBM6_PROTOCOL_CONTROL_2r, IDB_OBM7_PROTOCOL_CONTROL_2r 20114 }; 20115 20116 pgw_inst = (pgw | SOC_REG_ADDR_INSTANCE_MASK); 20117 20118 for (i = 0; i < array_count; i++) { 20119 classifier_ptr = switch_obm_classifier + i; 20120 20121 reg = obm_proto_control0_regs[((phy_port - 1) % _MN_PORTS_PER_PGW) / 4]; 20122 COMPILER_64_ZERO(rval64); 20123 COMPILER_64_TO_32_HI(rval_hi, rval64); 20124 COMPILER_64_TO_32_LO(rval_lo, rval64); 20125 rval_hi |= ((classifier_ptr->obm_destination_mac[0] & 0xff) << 8); 20126 rval_hi |= (classifier_ptr->obm_destination_mac[1] & 0xff); 20127 rval_lo |= ((classifier_ptr->obm_destination_mac[2] & 0xff) << 24); 20128 rval_lo |= ((classifier_ptr->obm_destination_mac[3] & 0xff) << 16); 20129 rval_lo |= ((classifier_ptr->obm_destination_mac[4] & 0xff) << 8); 20130 rval_lo |= (classifier_ptr->obm_destination_mac[5] & 0xff); 20131 COMPILER_64_SET(rval64, rval_hi, rval_lo); 20132 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, 20133 pgw_inst, i, rval64)); 20134 20135 reg = obm_proto_control1_regs[((phy_port - 1) % _MN_PORTS_PER_PGW) / 4]; 20136 COMPILER_64_ZERO(rval64); 20137 COMPILER_64_TO_32_HI(rval_hi, rval64); 20138 COMPILER_64_TO_32_LO(rval_lo, rval64); 20139 rval_hi |= ((classifier_ptr->obm_destination_mac_mask[0] & 0xff) << 8); 20140 rval_hi |= (classifier_ptr->obm_destination_mac_mask[1] & 0xff); 20141 rval_lo |= ((classifier_ptr->obm_destination_mac_mask[2] & 0xff) << 24); 20142 rval_lo |= ((classifier_ptr->obm_destination_mac_mask[3] & 0xff) << 16); 20143 rval_lo |= ((classifier_ptr->obm_destination_mac_mask[4] & 0xff) << 8); 20144 rval_lo |= (classifier_ptr->obm_destination_mac_mask[5] & 0xff); 20145 COMPILER_64_SET(rval64, rval_hi, rval_lo); 20146 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, 20147 pgw_inst, i, rval64)); 20148 reg = obm_proto_control2_regs[((phy_port - 1) % _MN_PORTS_PER_PGW) / 4]; 20149 COMPILER_64_ZERO(rval64); 20150 COMPILER_64_TO_32_HI(rval_hi, rval64); 20151 COMPILER_64_TO_32_LO(rval_lo, rval64); 20152 rval_lo |= (classifier_ptr->obm_ethertype & 0xffff); 20153 rval_lo |= ((classifier_ptr->obm_ethertype_mask & 0xffff) << 16); 20154 rval_hi |= (classifier_ptr->obm_priority & 0x7); 20155 20156 /* check if configuration is to enable or disable */ 20157 enable |= classifier_ptr->obm_destination_mac[0]; 20158 enable |= classifier_ptr->obm_destination_mac[1]; 20159 enable |= classifier_ptr->obm_destination_mac[2]; 20160 enable |= classifier_ptr->obm_destination_mac[3]; 20161 enable |= classifier_ptr->obm_destination_mac[4]; 20162 enable |= classifier_ptr->obm_destination_mac[5]; 20163 enable |= classifier_ptr->obm_destination_mac_mask[0]; 20164 enable |= classifier_ptr->obm_destination_mac_mask[1]; 20165 enable |= classifier_ptr->obm_destination_mac_mask[2]; 20166 enable |= classifier_ptr->obm_destination_mac_mask[3]; 20167 enable |= classifier_ptr->obm_destination_mac_mask[4]; 20168 enable |= classifier_ptr->obm_destination_mac_mask[5]; 20169 enable |= classifier_ptr->obm_ethertype; 20170 enable |= classifier_ptr->obm_ethertype_mask; 20171 enable |= classifier_ptr->obm_priority; 20172 20173 rval_hi |= ((enable ? 1 : 0) << 3); 20174 COMPILER_64_SET(rval64, rval_hi, rval_lo); 20175 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, 20176 pgw_inst, i, rval64)); 20177 } 20178 return BCM_E_NONE; 20179 } 20180 20181 /* 20182 * Function: 20183 * bcm_mn_switch_obm_field_classifier_mapping_multi_get 20184 * Purpose: 20185 * Get the mapping of bcm_obm_priority for a given 20186 * destination_mac, destination_mac_mask, ethertype and 20187 * ethertype mask for multiple entries of field classifier type. 20188 * Parameters: 20189 * unit - (IN) Unit number. 20190 * phy_port - (IN) Physical port. 20191 * pgw - (IN) PGW index (0 0r 1). 20192 * array_max - (IN) Maximum number of entries. 20193 * switch_obm_classifier - (IN/OUT) Array of field entries. 20194 * array_count - (OUT) Number of field entries. 20195 * Returns: 20196 * BCM_E_xxx 20197 */ 20198 20199 STATIC 20200 int bcm_mn_switch_obm_field_classifier_mapping_multi_get( 20201 int unit, 20202 int phy_port, 20203 int pgw, 20204 int array_max, 20205 bcm_switch_obm_classifier_t *switch_obm_classifier, 20206 int *array_count) 20207 { 20208 uint64 rval64; 20209 uint32 rval_hi, rval_lo; 20210 bcm_switch_obm_classifier_t *classifier_ptr = NULL; 20211 soc_reg_t reg; 20212 int i, pgw_inst; 20213 20214 static const soc_reg_t obm_proto_control0_regs[] = { 20215 IDB_OBM0_PROTOCOL_CONTROL_0r, IDB_OBM1_PROTOCOL_CONTROL_0r, 20216 IDB_OBM2_PROTOCOL_CONTROL_0r, IDB_OBM3_PROTOCOL_CONTROL_0r, 20217 IDB_OBM4_PROTOCOL_CONTROL_0r, IDB_OBM5_PROTOCOL_CONTROL_0r, 20218 IDB_OBM6_PROTOCOL_CONTROL_0r, IDB_OBM7_PROTOCOL_CONTROL_0r 20219 }; 20220 static const soc_reg_t obm_proto_control1_regs[] = { 20221 IDB_OBM0_PROTOCOL_CONTROL_1r, IDB_OBM1_PROTOCOL_CONTROL_1r, 20222 IDB_OBM2_PROTOCOL_CONTROL_1r, IDB_OBM3_PROTOCOL_CONTROL_1r, 20223 IDB_OBM4_PROTOCOL_CONTROL_1r, IDB_OBM5_PROTOCOL_CONTROL_1r, 20224 IDB_OBM6_PROTOCOL_CONTROL_1r, IDB_OBM7_PROTOCOL_CONTROL_1r 20225 }; 20226 static const soc_reg_t obm_proto_control2_regs[] = { 20227 IDB_OBM0_PROTOCOL_CONTROL_2r, IDB_OBM1_PROTOCOL_CONTROL_2r, 20228 IDB_OBM2_PROTOCOL_CONTROL_2r, IDB_OBM3_PROTOCOL_CONTROL_2r, 20229 IDB_OBM4_PROTOCOL_CONTROL_2r, IDB_OBM5_PROTOCOL_CONTROL_2r, 20230 IDB_OBM6_PROTOCOL_CONTROL_2r, IDB_OBM7_PROTOCOL_CONTROL_2r 20231 }; 20232 20233 pgw_inst = (pgw | SOC_REG_ADDR_INSTANCE_MASK); 20234 20235 /* Do validation of params */ 20236 if (array_max > BCM_OBM_CLASSIFIER_NUM_ENTRY_FIELD) { 20237 *array_count = BCM_OBM_CLASSIFIER_NUM_ENTRY_FIELD; 20238 } else { 20239 *array_count = array_max; 20240 } 20241 20242 for (i = 0; i < *array_count; i++) { 20243 classifier_ptr = switch_obm_classifier + i; 20244 20245 reg = obm_proto_control0_regs[((phy_port - 1) % _MN_PORTS_PER_PGW) / 4]; 20246 COMPILER_64_ZERO(rval64); 20247 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, 20248 pgw_inst, i, &rval64)); 20249 COMPILER_64_TO_32_HI(rval_hi, rval64); 20250 COMPILER_64_TO_32_LO(rval_lo, rval64); 20251 classifier_ptr->obm_destination_mac[0] = (rval_hi >> 8) & 0xff; 20252 classifier_ptr->obm_destination_mac[1] = rval_hi & 0xff; 20253 classifier_ptr->obm_destination_mac[2] = (rval_lo >> 24) & 0xff; 20254 classifier_ptr->obm_destination_mac[3] = (rval_lo >> 16) & 0xff; 20255 classifier_ptr->obm_destination_mac[4] = (rval_lo >> 8) & 0xff; 20256 classifier_ptr->obm_destination_mac[5] = rval_lo & 0xff; 20257 20258 reg = obm_proto_control1_regs[((phy_port - 1) % _MN_PORTS_PER_PGW) / 4]; 20259 COMPILER_64_ZERO(rval64); 20260 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, 20261 pgw_inst, i, &rval64)); 20262 COMPILER_64_TO_32_HI(rval_hi, rval64); 20263 COMPILER_64_TO_32_LO(rval_lo, rval64); 20264 classifier_ptr->obm_destination_mac_mask[0] = (rval_hi >> 8) & 0xff; 20265 classifier_ptr->obm_destination_mac_mask[1] = rval_hi & 0xff; 20266 classifier_ptr->obm_destination_mac_mask[2] = (rval_lo >> 24) & 0xff; 20267 classifier_ptr->obm_destination_mac_mask[3] = (rval_lo >> 16) & 0xff; 20268 classifier_ptr->obm_destination_mac_mask[4] = (rval_lo >> 8) & 0xff; 20269 classifier_ptr->obm_destination_mac_mask[5] = rval_lo & 0xff; 20270 20271 reg = obm_proto_control2_regs[((phy_port - 1) % _MN_PORTS_PER_PGW) / 4]; 20272 COMPILER_64_ZERO(rval64); 20273 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, 20274 pgw_inst, i, &rval64)); 20275 COMPILER_64_TO_32_HI(rval_hi, rval64); 20276 COMPILER_64_TO_32_LO(rval_lo, rval64); 20277 classifier_ptr->obm_ethertype = rval_lo & 0xffff; 20278 classifier_ptr->obm_ethertype_mask = (rval_lo >>16) & 0xffff; 20279 classifier_ptr->obm_priority = rval_hi & 0x7; 20280 } 20281 return BCM_E_NONE; 20282 } 20283 20284 /* 20285 * Function: 20286 * bcm_mn_switch_obm_classifier_validate 20287 * Purpose: 20288 * Internal function for validation of config params. 20289 * Parameters: 20290 * unit - (IN) Unit number. 20291 * port - (IN) phyical port. 20292 * switch_obm_classifier_type- (IN) type of switch_obm_classifier. 20293 * array_count - (IN) Number of elements in switch_obm_classifier. 20294 * switch_obm_classifier - (IN) Array of bcm_switch_obm_classifier_t. 20295 * Returns: 20296 * BCM_E_xxx 20297 */ 20298 20299 STATIC 20300 int bcm_mn_switch_obm_classifier_validate( 20301 int unit, 20302 bcm_port_t port, 20303 bcm_switch_obm_classifier_type_t switch_obm_classifier_type, 20304 int *array_count, 20305 bcm_switch_obm_classifier_t *switch_obm_classifier, 20306 int set) 20307 { 20308 soc_pbmp_t pbmp_xport_roe_backplane; 20309 soc_pbmp_t pbmp_xport_roe_mcu; 20310 int i, max_count; 20311 bcm_switch_obm_classifier_t *classifier_ptr = NULL; 20312 20313 SOC_PBMP_CLEAR(pbmp_xport_roe_backplane); 20314 SOC_PBMP_CLEAR(pbmp_xport_roe_mcu); 20315 20316 pbmp_xport_roe_backplane = soc_property_get_pbmp_default(unit, 20317 spn_PBMP_XPORT_ROE_BACKPLANE, 20318 pbmp_xport_roe_backplane); 20319 pbmp_xport_roe_mcu = soc_property_get_pbmp_default(unit, 20320 spn_PBMP_XPORT_ROE_MCU, 20321 pbmp_xport_roe_mcu); 20322 20323 if ((port <= 0) || (port > 64)) { 20324 LOG_ERROR(BSL_LS_BCM_COMMON, 20325 (BSL_META_U(unit, 20326 "ERROR: Invalid port %d\n"), port)); 20327 return BCM_E_PORT; 20328 } 20329 20330 if (IS_HG_PORT(unit, port)) { 20331 if (switch_obm_classifier_type == bcmSwitchObmClassifierVlan) { 20332 LOG_ERROR(BSL_LS_BCM_COMMON, 20333 (BSL_META_U(unit, 20334 "ERROR: OBM Vlan classifier not allowed on Higig" 20335 " port %d\n"), port)); 20336 return BCM_E_PARAM; 20337 } 20338 } else { 20339 if (switch_obm_classifier_type == bcmSwitchObmClassifierHigig2) { 20340 LOG_ERROR(BSL_LS_BCM_COMMON, 20341 (BSL_META_U(unit, 20342 "ERROR: OBM Higig2 classifier not allowed on non Higig" 20343 " port %d\n"), port)); 20344 return BCM_E_PARAM; 20345 } 20346 } 20347 switch (switch_obm_classifier_type) { 20348 case bcmSwitchObmClassifierDscp: 20349 max_count = BCM_OBM_CLASSIFIER_NUM_ENTRY_DSCP; 20350 break; 20351 case bcmSwitchObmClassifierMpls: 20352 max_count = BCM_OBM_CLASSIFIER_NUM_ENTRY_MPLS; 20353 break; 20354 case bcmSwitchObmClassifierEtag: 20355 max_count = BCM_OBM_CLASSIFIER_NUM_ENTRY_ETAG; 20356 break; 20357 case bcmSwitchObmClassifierVlan: 20358 max_count = BCM_OBM_CLASSIFIER_NUM_ENTRY_VLAN; 20359 break; 20360 case bcmSwitchObmClassifierHigig2: 20361 max_count = BCM_OBM_CLASSIFIER_NUM_ENTRY_HIGIG2; 20362 break; 20363 case bcmSwitchObmClassifierField: 20364 max_count = BCM_OBM_CLASSIFIER_NUM_ENTRY_FIELD; 20365 break; 20366 default: 20367 LOG_ERROR(BSL_LS_BCM_COMMON, 20368 (BSL_META_U(unit, 20369 "ERROR: switch_obm_classifier_type is not correct on" 20370 " port %d\n"), port)); 20371 return BCM_E_PARAM; 20372 } 20373 /* For get API array count may be more than max_count */ 20374 if (*array_count > max_count) { 20375 if (set) { 20376 return BCM_E_PARAM; 20377 } else { 20378 *array_count = max_count; 20379 } 20380 } 20381 for (i = 0; i < *array_count; i++) { 20382 classifier_ptr = switch_obm_classifier + i; 20383 if (switch_obm_classifier_type != bcmSwitchObmClassifierField) { 20384 if (classifier_ptr->obm_code_point >= max_count) { 20385 LOG_ERROR(BSL_LS_BCM_COMMON, 20386 (BSL_META_U(unit, 20387 "ERROR: Invalid obm_code_point configured on" 20388 " port %d\n"), port)); 20389 return BCM_E_PARAM; 20390 } 20391 } 20392 if (set) { 20393 if (classifier_ptr->obm_priority > BCM_OBM_PRIORITY_MAX) { 20394 LOG_ERROR(BSL_LS_BCM_COMMON, 20395 (BSL_META_U(unit, 20396 "ERROR: Invalid obm_priority configured on" 20397 " port %d\n"), port)); 20398 return BCM_E_PARAM; 20399 } 20400 if (SOC_PBMP_MEMBER(pbmp_xport_roe_backplane, port) && 20401 ((classifier_ptr->obm_priority == 20402 BCM_SWITCH_OBM_PRIORITY_LOSSLESS0) || 20403 (classifier_ptr->obm_priority == 20404 BCM_SWITCH_OBM_PRIORITY_LOSSLESS1))) { 20405 LOG_ERROR(BSL_LS_BCM_COMMON, 20406 (BSL_META_U(unit, 20407 "ERROR: Lossless obm_priority configured on" 20408 " port %d\n"), port)); 20409 return BCM_E_PARAM; 20410 } else if (SOC_PBMP_MEMBER(pbmp_xport_roe_mcu, port) && 20411 (classifier_ptr->obm_priority == 20412 BCM_SWITCH_OBM_PRIORITY_EXPRESS)) { 20413 LOG_ERROR(BSL_LS_BCM_COMMON, 20414 (BSL_META_U(unit, 20415 "ERROR: Express obm_priority not allowed on" 20416 " port %d\n"), port)); 20417 return BCM_E_PARAM; 20418 } 20419 } 20420 } 20421 return BCM_E_NONE; 20422 } 20423 /* 20424 * Function: 20425 * bcm_mn_switch_obm_classifier_mapping_multi_set 20426 * Purpose: 20427 * Set the mapping of bcm_obm_code_point to bcm_obm_priority 20428 * for multiple entries of same type of classifier. Maximum 20429 * number of entries to be programmed are different depending 20430 * type of classifier. For type bcmSwitchObmClassifierField 20431 * bcm_obm_code_point will not be used and mapping will happen 20432 * based on destination_mac/mask and ethertype/mask. 20433 * Parameters: 20434 * unit - (IN) Unit number. 20435 * gport - (IN) gport for a given port. 20436 * switch_obm_classifier_type - (IN) type of switch_obm_classifier. 20437 * array_count - (IN) Number of elements in switch_obm_classifier. 20438 * switch_obm_classifier - (IN) Array of bcm_switch_obm_classifier_t. 20439 * Returns: 20440 * BCM_E_xxx 20441 */ 20442 20443 int 20444 bcm_mn_switch_obm_classifier_mapping_multi_set( 20445 int unit, 20446 bcm_gport_t gport, 20447 bcm_switch_obm_classifier_type_t switch_obm_classifier_type, 20448 int array_count, 20449 bcm_switch_obm_classifier_t *switch_obm_classifier) 20450 { 20451 soc_info_t *si; 20452 int pgw; 20453 int phy_port; 20454 bcm_port_t port; 20455 20456 20457 si = &SOC_INFO(unit); 20458 BCM_IF_ERROR_RETURN(bcm_esw_port_local_get(unit, gport, &port)); 20459 phy_port = si->port_l2p_mapping[port]; 20460 pgw = si->port_group[port]; 20461 20462 /* Validate port and classifier compatibility */ 20463 BCM_IF_ERROR_RETURN( 20464 bcm_mn_switch_obm_classifier_validate(unit, 20465 port, 20466 switch_obm_classifier_type, 20467 &array_count, 20468 switch_obm_classifier, 20469 1)); 20470 20471 switch (switch_obm_classifier_type) { 20472 case bcmSwitchObmClassifierDscp: 20473 BCM_IF_ERROR_RETURN( 20474 bcm_mn_switch_obm_dscp_classifier_mapping_multi_set( 20475 unit, 20476 phy_port, 20477 pgw, 20478 array_count, 20479 switch_obm_classifier)); 20480 break; 20481 case bcmSwitchObmClassifierMpls: 20482 BCM_IF_ERROR_RETURN( 20483 bcm_mn_switch_obm_mpls_classifier_mapping_multi_set( 20484 unit, 20485 phy_port, 20486 pgw, 20487 array_count, 20488 switch_obm_classifier)); 20489 break; 20490 case bcmSwitchObmClassifierEtag: 20491 BCM_IF_ERROR_RETURN( 20492 bcm_mn_switch_obm_etag_classifier_mapping_multi_set( 20493 unit, 20494 phy_port, 20495 pgw, 20496 array_count, 20497 switch_obm_classifier)); 20498 break; 20499 case bcmSwitchObmClassifierVlan: 20500 BCM_IF_ERROR_RETURN( 20501 bcm_mn_switch_obm_vlan_classifier_mapping_multi_set( 20502 unit, 20503 phy_port, 20504 pgw, 20505 array_count, 20506 switch_obm_classifier)); 20507 break; 20508 case bcmSwitchObmClassifierHigig2: 20509 BCM_IF_ERROR_RETURN( 20510 bcm_mn_switch_obm_higig2_classifier_mapping_multi_set( 20511 unit, 20512 phy_port, 20513 pgw, 20514 array_count, 20515 switch_obm_classifier)); 20516 break; 20517 case bcmSwitchObmClassifierField: 20518 BCM_IF_ERROR_RETURN( 20519 bcm_mn_switch_obm_field_classifier_mapping_multi_set( 20520 unit, 20521 phy_port, 20522 pgw, 20523 array_count, 20524 switch_obm_classifier)); 20525 break; 20526 20527 default: 20528 return BCM_E_PARAM; 20529 } 20530 return BCM_E_NONE; 20531 } 20532 20533 /* 20534 * Function: 20535 * bcm_mn_switch_obm_classifier_mapping_multi_get 20536 * Purpose: 20537 * Get the mapping of bcm_obm_code_point to bcm_obm_priority 20538 * for multiple entries of same type of classifier. Maximum 20539 * number of entries to be programmed are different depending 20540 * type of classifier. For type bcmSwitchObmClassifierField 20541 * bcm_obm_code_point will not be used and mapping will happen 20542 * based on destination_mac/mask and ethertype/mask. 20543 * Parameters: 20544 * unit - (IN) Unit number. 20545 * gport - (IN) gport for a given port. 20546 * switch_obm_classifier_type - (IN) type of switch_obm_classifier. 20547 * array_max - (IN) Maximum number of elements in switch_obm_classifier. 20548 * switch_obm_classifier - (IN/OUT) Array of bcm_switch_obm_classifier_t. 20549 * array_count - (OUT) Number of elements in switch_obm_classifier. 20550 * Returns: 20551 * BCM_E_xxx 20552 */ 20553 20554 int 20555 bcm_mn_switch_obm_classifier_mapping_multi_get( 20556 int unit, 20557 bcm_gport_t gport, 20558 bcm_switch_obm_classifier_type_t switch_obm_classifier_type, 20559 int array_max, 20560 bcm_switch_obm_classifier_t *switch_obm_classifier, 20561 int *array_count) 20562 20563 { 20564 soc_info_t *si; 20565 int pgw; 20566 int phy_port; 20567 bcm_port_t port; 20568 20569 si = &SOC_INFO(unit); 20570 BCM_IF_ERROR_RETURN(bcm_esw_port_local_get(unit, gport, &port)); 20571 phy_port = si->port_l2p_mapping[port]; 20572 pgw = si->port_group[port]; 20573 20574 /* Validate port and classifier compatibility */ 20575 *array_count = array_max; 20576 BCM_IF_ERROR_RETURN( 20577 bcm_mn_switch_obm_classifier_validate(unit, 20578 port, 20579 switch_obm_classifier_type, 20580 array_count, 20581 switch_obm_classifier, 20582 0)); 20583 switch (switch_obm_classifier_type) { 20584 case bcmSwitchObmClassifierDscp: 20585 BCM_IF_ERROR_RETURN( 20586 bcm_mn_switch_obm_dscp_classifier_mapping_multi_get( 20587 unit, 20588 phy_port, 20589 pgw, 20590 array_max, 20591 switch_obm_classifier, 20592 array_count)); 20593 break; 20594 case bcmSwitchObmClassifierMpls: 20595 BCM_IF_ERROR_RETURN( 20596 bcm_mn_switch_obm_mpls_classifier_mapping_multi_get( 20597 unit, 20598 phy_port, 20599 pgw, 20600 array_max, 20601 switch_obm_classifier, 20602 array_count)); 20603 break; 20604 case bcmSwitchObmClassifierEtag: 20605 BCM_IF_ERROR_RETURN( 20606 bcm_mn_switch_obm_etag_classifier_mapping_multi_get( 20607 unit, 20608 phy_port, 20609 pgw, 20610 array_max, 20611 switch_obm_classifier, 20612 array_count)); 20613 break; 20614 case bcmSwitchObmClassifierVlan: 20615 BCM_IF_ERROR_RETURN( 20616 bcm_mn_switch_obm_vlan_classifier_mapping_multi_get( 20617 unit, 20618 phy_port, 20619 pgw, 20620 array_max, 20621 switch_obm_classifier, 20622 array_count)); 20623 break; 20624 case bcmSwitchObmClassifierHigig2: 20625 BCM_IF_ERROR_RETURN( 20626 bcm_mn_switch_obm_higig2_classifier_mapping_multi_get( 20627 unit, 20628 phy_port, 20629 pgw, 20630 array_max, 20631 switch_obm_classifier, 20632 array_count)); 20633 break; 20634 case bcmSwitchObmClassifierField: 20635 BCM_IF_ERROR_RETURN( 20636 bcm_mn_switch_obm_field_classifier_mapping_multi_get( 20637 unit, 20638 phy_port, 20639 pgw, 20640 array_max, 20641 switch_obm_classifier, 20642 array_count)); 20643 break; 20644 20645 default: 20646 return BCM_E_PARAM; 20647 } 20648 return BCM_E_NONE; 20649 } 20650 /* 20651 * Function: 20652 * bcm_mn_obm_classifier_port_control_set 20653 * Description: 20654 * Internal function to Enable/Disable specified 20655 * OBM port feature and congigure ethertype. 20656 * Parameters: 20657 * unit - Device number 20658 * port - Port number 20659 * type - Enum value of the OBM feature 20660 * value - value to be set 20661 * Return Value: 20662 * BCM_E_XXXX 20663 */ 20664 int 20665 bcm_mn_obm_classifier_port_control_set(int unit, 20666 bcm_port_t port, 20667 bcm_port_control_t type, 20668 int value) 20669 { 20670 soc_info_t *si; 20671 int pgw, pgw_inst, subport, obm; 20672 int phy_port; 20673 soc_reg_t reg; 20674 soc_field_t field; 20675 int vntag = 0, port_control = 0, val, class_select = 0; 20676 uint32 rval32; 20677 uint64 rval64; 20678 20679 static const soc_reg_t obm_port_config_regs[] = { 20680 IDB_OBM0_PORT_CONFIGr, IDB_OBM1_PORT_CONFIGr, 20681 IDB_OBM2_PORT_CONFIGr, IDB_OBM3_PORT_CONFIGr, 20682 IDB_OBM4_PORT_CONFIGr, IDB_OBM5_PORT_CONFIGr, 20683 IDB_OBM6_PORT_CONFIGr, IDB_OBM7_PORT_CONFIGr 20684 }; 20685 20686 static const soc_reg_t obm_niv_ethertype_config_regs[] = { 20687 IDB_OBM0_NIV_ETHERTYPEr, IDB_OBM1_NIV_ETHERTYPEr, 20688 IDB_OBM2_NIV_ETHERTYPEr, IDB_OBM3_NIV_ETHERTYPEr, 20689 IDB_OBM4_NIV_ETHERTYPEr, IDB_OBM5_NIV_ETHERTYPEr, 20690 IDB_OBM6_NIV_ETHERTYPEr, IDB_OBM7_NIV_ETHERTYPEr 20691 }; 20692 20693 static const soc_reg_t obm_pe_ethertype_config_regs[] = { 20694 IDB_OBM0_PE_ETHERTYPEr, IDB_OBM1_PE_ETHERTYPEr, 20695 IDB_OBM2_PE_ETHERTYPEr, IDB_OBM3_PE_ETHERTYPEr, 20696 IDB_OBM4_PE_ETHERTYPEr, IDB_OBM5_PE_ETHERTYPEr, 20697 IDB_OBM6_PE_ETHERTYPEr, IDB_OBM7_PE_ETHERTYPEr 20698 }; 20699 20700 si = &SOC_INFO(unit); 20701 /* Add check on ports */ 20702 obm = si->port_serdes[port]; 20703 obm %= _MN_TSCS_PER_PGW; 20704 phy_port = si->port_l2p_mapping[port]; 20705 20706 if (IS_CPU_PORT(unit, port) || IS_LB_PORT(unit, port) || 20707 IS_MACSEC_PORT(unit, port)) { 20708 /* Do not allow programming on non-idb ports */ 20709 return BCM_E_PARAM; 20710 } 20711 20712 20713 pgw = si->port_group[port]; 20714 pgw_inst = (pgw | SOC_REG_ADDR_INSTANCE_MASK); 20715 subport = (phy_port - 1) % _MN_PORTS_PER_TSC; 20716 20717 switch (type) { 20718 case bcmPortControlObmClassifierPriority: 20719 port_control = 1; 20720 field = PORT_PRIf; 20721 val = value & 0x7; 20722 break; 20723 case bcmPortControlObmClassifierEnableDscp: 20724 port_control = 1; 20725 field = TRUST_DSCPf; 20726 val = value & 0x1; 20727 break; 20728 case bcmPortControlObmClassifierEnableMpls: 20729 port_control = 1; 20730 field = TRUST_MPLSf; 20731 val = value & 0x1; 20732 break; 20733 case bcmPortControlObmClassifierEnableEtag: 20734 port_control = 1; 20735 field = PHB_FROM_ETAGf; 20736 val = value & 0x1; 20737 break; 20738 case bcmPortControlObmClassifierEtagEthertype: 20739 field = ETHERTYPEf; 20740 val = value & 0xffff; 20741 break; 20742 case bcmPortControlObmClassifierVntagEthertype: 20743 vntag = 1; 20744 field = ETHERTYPEf; 20745 val = value & 0xffff; 20746 break; 20747 case bcmPortControlObmClassifierInternal: 20748 class_select = 1; 20749 break; 20750 default: 20751 return BCM_E_PARAM; 20752 } 20753 if (class_select == 1) { 20754 COMPILER_64_ZERO(rval64); 20755 SOC_IF_ERROR_RETURN(READ_PGW_OBM_PARSING_CONTROLr(unit, port ,&rval64)); 20756 soc_reg64_field32_set(unit, PGW_OBM_PARSING_CONTROLr, 20757 &rval64, USE_PM_PREEMPT_INPUTf , !value); 20758 SOC_IF_ERROR_RETURN(WRITE_PGW_OBM_PARSING_CONTROLr(unit, port, rval64)); 20759 } else if (port_control == 1) { 20760 reg = obm_port_config_regs[obm]; 20761 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, pgw_inst, subport, &rval32)); 20762 soc_reg_field_set(unit, reg, &rval32, field, val); 20763 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, pgw_inst, subport, rval32)); 20764 } else if (vntag == 1) { 20765 reg = obm_niv_ethertype_config_regs[obm]; 20766 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, pgw_inst, subport, &rval32)); 20767 soc_reg_field_set(unit, reg, &rval32, field, val); 20768 soc_reg_field_set(unit, reg, &rval32, ENABLEf, val ? 1 : 0); 20769 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, pgw_inst, subport, rval32)); 20770 } else { 20771 reg = obm_pe_ethertype_config_regs[obm]; 20772 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, pgw_inst, subport, &rval32)); 20773 soc_reg_field_set(unit, reg, &rval32, field, val); 20774 soc_reg_field_set(unit, reg, &rval32, ENABLEf, val ? 1 : 0); 20775 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, pgw_inst, subport, rval32)); 20776 } 20777 return BCM_E_NONE; 20778 } 20779 /* 20780 * Function: 20781 * bcm_mn_obm_classifier_port_control_get 20782 * Description: 20783 * Internal function to get value specified 20784 * OBM port feature and congigure ethertype. 20785 * Parameters: 20786 * unit - Device number 20787 * port - Port number 20788 * type - Enum value of the OBM feature 20789 * value - value to get 20790 * Return Value: 20791 * BCM_E_XXXX 20792 */ 20793 int 20794 bcm_mn_obm_classifier_port_control_get(int unit, 20795 bcm_port_t port, 20796 bcm_port_control_t type, 20797 int *value) 20798 { 20799 soc_info_t *si; 20800 int pgw, pgw_inst, subport, obm; 20801 int phy_port; 20802 soc_reg_t reg; 20803 soc_field_t field; 20804 int vntag = 0, port_control = 0, val, class_select = 0; 20805 uint32 rval32; 20806 uint64 rval64; 20807 20808 static const soc_reg_t obm_port_config_regs[] = { 20809 IDB_OBM0_PORT_CONFIGr, IDB_OBM1_PORT_CONFIGr, 20810 IDB_OBM2_PORT_CONFIGr, IDB_OBM3_PORT_CONFIGr, 20811 IDB_OBM4_PORT_CONFIGr, IDB_OBM5_PORT_CONFIGr, 20812 IDB_OBM6_PORT_CONFIGr, IDB_OBM7_PORT_CONFIGr 20813 }; 20814 20815 static const soc_reg_t obm_niv_ethertype_config_regs[] = { 20816 IDB_OBM0_NIV_ETHERTYPEr, IDB_OBM1_NIV_ETHERTYPEr, 20817 IDB_OBM2_NIV_ETHERTYPEr, IDB_OBM3_NIV_ETHERTYPEr, 20818 IDB_OBM4_NIV_ETHERTYPEr, IDB_OBM5_NIV_ETHERTYPEr, 20819 IDB_OBM6_NIV_ETHERTYPEr, IDB_OBM7_NIV_ETHERTYPEr 20820 }; 20821 20822 static const soc_reg_t obm_pe_ethertype_config_regs[] = { 20823 IDB_OBM0_PE_ETHERTYPEr, IDB_OBM1_PE_ETHERTYPEr, 20824 IDB_OBM2_PE_ETHERTYPEr, IDB_OBM3_PE_ETHERTYPEr, 20825 IDB_OBM4_PE_ETHERTYPEr, IDB_OBM5_PE_ETHERTYPEr, 20826 IDB_OBM6_PE_ETHERTYPEr, IDB_OBM7_PE_ETHERTYPEr 20827 }; 20828 20829 si = &SOC_INFO(unit); 20830 /* Add check on ports */ 20831 obm = si->port_serdes[port]; 20832 obm %= _MN_TSCS_PER_PGW; 20833 20834 phy_port = si->port_l2p_mapping[port]; 20835 20836 if (IS_CPU_PORT(unit, port) || IS_LB_PORT(unit, port) || 20837 IS_MACSEC_PORT(unit, port)) { 20838 /* Do not allow programming on non-idb ports */ 20839 return BCM_E_PARAM; 20840 } 20841 20842 20843 pgw = si->port_group[port]; 20844 pgw_inst = (pgw | SOC_REG_ADDR_INSTANCE_MASK); 20845 subport = (phy_port - 1) % _MN_PORTS_PER_TSC; 20846 20847 switch (type) { 20848 case bcmPortControlObmClassifierPriority: 20849 port_control = 1; 20850 field = PORT_PRIf; 20851 break; 20852 case bcmPortControlObmClassifierEnableDscp: 20853 port_control = 1; 20854 field = TRUST_DSCPf; 20855 break; 20856 case bcmPortControlObmClassifierEnableMpls: 20857 port_control = 1; 20858 field = TRUST_MPLSf; 20859 break; 20860 case bcmPortControlObmClassifierEnableEtag: 20861 port_control = 1; 20862 field = PHB_FROM_ETAGf; 20863 break; 20864 case bcmPortControlObmClassifierEtagEthertype: 20865 field = ETHERTYPEf; 20866 break; 20867 case bcmPortControlObmClassifierVntagEthertype: 20868 vntag = 1; 20869 field = ETHERTYPEf; 20870 break; 20871 case bcmPortControlObmClassifierInternal: 20872 class_select = 1; 20873 break; 20874 default: 20875 return BCM_E_PARAM; 20876 } 20877 if (class_select == 1) { 20878 COMPILER_64_ZERO(rval64); 20879 SOC_IF_ERROR_RETURN(READ_PGW_OBM_PARSING_CONTROLr(unit, port ,&rval64)); 20880 val = !soc_reg64_field32_get(unit, PGW_OBM_PARSING_CONTROLr, 20881 rval64, USE_PM_PREEMPT_INPUTf); 20882 } else if (port_control == 1) { 20883 reg = obm_port_config_regs[obm]; 20884 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, pgw_inst, subport, &rval32)); 20885 val = soc_reg_field_get(unit, reg, rval32, field); 20886 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, pgw_inst, subport, rval32)); 20887 } else if (vntag == 1) { 20888 reg = obm_niv_ethertype_config_regs[obm]; 20889 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, pgw_inst, subport, &rval32)); 20890 val = soc_reg_field_get(unit, reg, rval32, field); 20891 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, pgw_inst, subport, rval32)); 20892 } else { 20893 reg = obm_pe_ethertype_config_regs[obm]; 20894 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, pgw_inst, subport, &rval32)); 20895 val = soc_reg_field_get(unit, reg, rval32, field); 20896 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, pgw_inst, subport, rval32)); 20897 } 20898 *value = val; 20899 return BCM_E_NONE; 20900 } 20901 20902 /* 20903 * Function: 20904 * bcm_mn_obm_interrupt_port_control_get 20905 * Description: 20906 * Internal function to get if obm interrupt is enabled 20907 * Parameters: 20908 * unit - Device number 20909 * port - Port number 20910 * type - Enum value of the OBM Interrupt type 20911 * value - value to get 20912 * Return Value: 20913 * BCM_E_XXXX 20914 */ 20915 int 20916 bcm_mn_obm_interrupt_port_control_get(int unit, 20917 bcm_port_t port, 20918 bcm_port_control_t type, 20919 int *value) 20920 { 20921 soc_info_t *si; 20922 uint32 temp = 0 ; 20923 uint64 rval64; 20924 soc_reg_t reg; 20925 soc_field_t field; 20926 int pgw = 0 , pgw_inst = 0 , obm = 0; 20927 int phy_port =0 ; 20928 si = &SOC_INFO(unit); 20929 /* Add check on ports */ 20930 obm = si->port_serdes[port]; 20931 obm %= _MN_TSCS_PER_PGW; 20932 20933 phy_port = si->port_l2p_mapping[port]; 20934 20935 if (IS_CPU_PORT(unit, port) || IS_LB_PORT(unit, port) || 20936 IS_MACSEC_PORT(unit, port)) { 20937 /* Do not allow programming on non-idb ports */ 20938 return BCM_E_PARAM; 20939 } 20940 20941 if (phy_port > 32 ) { 20942 phy_port = phy_port - 32; 20943 } 20944 pgw = si->port_group[port]; 20945 pgw_inst = (pgw | SOC_REG_ADDR_INSTANCE_MASK); 20946 switch (type) { 20947 case bcmPortControlObmInterruptTypeDropPreempt: 20948 reg = PGW_OBM_DROP_STATUS_ENABLEr; 20949 field = PREEMPT_DROP_ERR_ENf; 20950 break; 20951 20952 case bcmPortControlObmInterruptTypeOverflowPreempt: 20953 reg = PGW_CA_OVERFLOW_STATUS_ENABLEr; 20954 field = CA_PREEMPT_OVERFLOW_ENf; 20955 break; 20956 20957 case bcmPortControlObmInterruptTypeDropExpress: 20958 reg = PGW_OBM_DROP_STATUS_ENABLEr; 20959 field = EXP_DROP_ERR_ENf; 20960 break; 20961 20962 case bcmPortControlObmInterruptTypeOverflowExpress: 20963 reg = PGW_CA_OVERFLOW_STATUS_ENABLEr; 20964 field = CA_EXP_OVERFLOW_ENf; 20965 break; 20966 default: 20967 return BCM_E_NOT_FOUND; 20968 } 20969 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, pgw_inst, 0, &rval64)); 20970 temp =soc_reg64_field32_get(unit, reg, rval64, field); 20971 *value= (temp & (1<<(phy_port-1)))?1:0; 20972 20973 return BCM_E_NONE; 20974 } 20975 /* 20976 * Function: 20977 * bcm_mn_obm_interrupt_port_control_set 20978 * Description: 20979 * Internal function to get if obm interrupt is enabled 20980 * Parameters: 20981 * unit - Device number 20982 * port - Port number 20983 * type - Enum value of the OBM Interrupt type 20984 * value - value to get 20985 * Return Value: 20986 * BCM_E_XXXX 20987 */ 20988 int 20989 bcm_mn_obm_interrupt_port_control_set(int unit, 20990 bcm_port_t port, 20991 bcm_port_control_t type, 20992 int value) 20993 { 20994 soc_info_t *si; 20995 uint32 temp = 0 ; 20996 uint64 rval64; 20997 soc_reg_t reg; 20998 soc_field_t field; 20999 int pgw = 0, pgw_inst = 0 , obm = 0 ; 21000 int phy_port = 0 ; 21001 si = &SOC_INFO(unit); 21002 /* Add check on ports */ 21003 obm = si->port_serdes[port]; 21004 obm %= _MN_TSCS_PER_PGW; 21005 phy_port = si->port_l2p_mapping[port]; 21006 21007 if (IS_CPU_PORT(unit, port) || IS_LB_PORT(unit, port) || 21008 IS_MACSEC_PORT(unit, port)) { 21009 /* Do not allow programming on non obm ports */ 21010 return BCM_E_PARAM; 21011 } 21012 21013 21014 pgw = si->port_group[port]; 21015 pgw_inst = (pgw | SOC_REG_ADDR_INSTANCE_MASK); 21016 switch (type) { 21017 case bcmPortControlObmInterruptTypeDropPreempt: 21018 reg = PGW_OBM_DROP_STATUS_ENABLEr; 21019 field = PREEMPT_DROP_ERR_ENf; 21020 break; 21021 21022 case bcmPortControlObmInterruptTypeOverflowPreempt: 21023 reg = PGW_CA_OVERFLOW_STATUS_ENABLEr; 21024 field = CA_PREEMPT_OVERFLOW_ENf; 21025 break; 21026 21027 case bcmPortControlObmInterruptTypeDropExpress: 21028 reg = PGW_OBM_DROP_STATUS_ENABLEr; 21029 field =EXP_DROP_ERR_ENf; 21030 break; 21031 21032 case bcmPortControlObmInterruptTypeOverflowExpress: 21033 reg = PGW_CA_OVERFLOW_STATUS_ENABLEr; 21034 field = CA_EXP_OVERFLOW_ENf; 21035 21036 break; 21037 default: 21038 return BCM_E_NOT_FOUND; 21039 21040 } 21041 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, pgw_inst, 0,&rval64)); 21042 temp = soc_reg64_field32_get(unit, reg, rval64, field); 21043 if (phy_port > 32 ) { 21044 phy_port = phy_port - 32; 21045 } 21046 if (value) { 21047 temp = temp | (1<<(phy_port - 1)); 21048 } else { 21049 temp = temp & ~(1<<(phy_port - 1)); 21050 } 21051 soc_reg64_field32_set(unit, reg, &rval64, field,temp); 21052 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg,pgw_inst,0,rval64)); 21053 return BCM_E_NONE ; 21054 } 21055 21056 21057 21058 #endif /* defined(BCM_MONTEREY_SUPPORT) */