cosq.c (802541B)
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_APACHE_SUPPORT) 17 #include <soc/drv.h> 18 #include <soc/scache.h> 19 #include <soc/profile_mem.h> 20 #include <soc/l3x.h> 21 #include <soc/macutil.h> 22 23 #include <soc/trident2.h> 24 #include <soc/apache.h> 25 26 27 #include <bcm/error.h> 28 #include <bcm/cosq.h> 29 #include <bcm_int/esw/mbcm.h> 30 #include <bcm_int/esw/stack.h> 31 #include <bcm_int/esw/cosq.h> 32 #include <bcm_int/esw/virtual.h> 33 #include <bcm_int/esw/apache.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 #ifdef BCM_WARM_BOOT_SUPPORT 45 #include <bcm_int/esw/switch.h> 46 #endif /* BCM_WARM_BOOT_SUPPORT */ 47 #define AP_CELL_FIELD_MAX 0x1ffff 48 #define _BCM_PORT_SERVICE_POOL 20480 49 #define _BCM_WRED_GLOBAL_SERVICE_POOL 20776 50 51 /* MMU cell size in bytes */ 52 #define _BCM_AP_BYTES_PER_CELL 208 /* bytes */ 53 #define _BCM_AP_BYTES_TO_CELLS(_byte_) \ 54 (((_byte_) + _BCM_AP_BYTES_PER_CELL - 1) / _BCM_AP_BYTES_PER_CELL) 55 #define _BCM_AP_NUM_PIPES 1 56 #define _BCM_AP_NUM_PORT_SCHEDULERS 76 57 #define _BCM_AP_NUM_S1_SCHEDULER_PER_PIPE 328 58 #define _BCM_AP_NUM_L0_SCHEDULER_PER_PIPE 1024 59 #define _BCM_AP_NUM_L0_SCHEDULER _BCM_AP_NUM_L0_SCHEDULER_PER_PIPE * _BCM_AP_NUM_PIPES 60 #define _BCM_AP_NUM_L1_SCHEDULER_PER_PIPE 4224 /* Reserved for default val */ 61 #define _BCM_AP_NUM_L1_SCHEDULER _BCM_AP_NUM_L1_SCHEDULER_PER_PIPE * _BCM_AP_NUM_PIPES 62 #define _BCM_AP_NUM_L2_UC_LEAVES_PER_PIPE 16384 /* Reserved for default val */ 63 #define _BCM_AP_NUM_L2_UC_LEAVES _BCM_AP_NUM_L2_UC_LEAVES_PER_PIPE * _BCM_AP_NUM_PIPES 64 #define _BCM_AP_NUM_L2_MC_LEAVES_PER_PIPE 778 65 #define _BCM_AP_NUM_L2_MC_LEAVES _BCM_AP_NUM_L2_MC_LEAVES_PER_PIPE * _BCM_AP_NUM_PIPES 66 #define _BCM_AP_NUM_L2_LEAVES_PER_PIPE (_BCM_AP_NUM_L2_MC_LEAVES_PER_PIPE + \ 67 _BCM_AP_NUM_L2_UC_LEAVES_PER_PIPE) 68 #define _BCM_AP_NUM_L2_LEAVES _BCM_AP_NUM_L2_LEAVES_PER_PIPE * _BCM_AP_NUM_PIPES 69 #define _BCM_AP_NUM_TOTAL_SCHEDULERS (_BCM_AP_NUM_PORT_SCHEDULERS + \ 70 _BCM_AP_NUM_S1_SCHEDULER_PER_PIPE + \ 71 _BCM_AP_NUM_L0_SCHEDULER + \ 72 _BCM_AP_NUM_L1_SCHEDULER) 73 #define _AP_SPM_ENTRIES_PER_SET 128 74 #define _AP_VPM_ENTRIES_PER_SET 128 75 #define _AP_SCM_ENTRIES_PER_SET 16 76 77 #define _BCM_AP_LLS_DYN_CHG_REG_B 0x3FFF 78 #define _BCM_AP_LLS_DYN_CHG_REG_C 0xFFFFFFFF 79 80 /* All CPU leaves Ranges from 17114-17161.*/ 81 #define _BCM_AP_NUM_L2_CPU_LEAVES 48 82 /* All Lb leaves Ranges from 17104-17111.*/ 83 #define _BCM_AP_NUM_L2_LB_LEAVES 8 84 85 #define _AP_NUM_COS NUM_COS 86 #define _AP_NUM_INTERNAL_PRI 16 87 88 #define _BCM_AP_NUM_PFC_CLASS 8 89 #define _BCM_AP_NUM_SAFC_CLASS 16 90 #define _BCM_AP_COSQ_LIST_NODE_INIT(list, node) \ 91 list[node].in_use = FALSE; \ 92 list[node].gport = -1; \ 93 list[node].base_index = -1; \ 94 list[node].numq = 0; \ 95 list[node].base_size = 0; \ 96 list[node].numq_expandable = 0; \ 97 list[node].hw_index = -1; \ 98 list[node].level = -1; \ 99 list[node].attached_to_input = -1; \ 100 list[node].hw_cosq = 0; \ 101 list[node].node_align_value = 0; \ 102 list[node].remote_modid = -1; \ 103 list[node].remote_port = -1; \ 104 list[node].cosq_map = NULL; \ 105 BCM_PBMP_CLEAR(list[node].fabric_pbmp); \ 106 list[node].local_port = -1; \ 107 list[node].parent = NULL; \ 108 list[node].sibling = NULL; \ 109 list[node].child = NULL; \ 110 list[node].coe_base_index = -1; \ 111 list[node].coe_num_l2 = 0; \ 112 list[node].port_gport = -1; 113 114 #define _BCM_AP_COSQ_NODE_INIT(node) \ 115 node->in_use = FALSE; \ 116 node->gport = -1; \ 117 node->base_index = -1; \ 118 node->numq = 0; \ 119 node->base_size = 0; \ 120 node->numq_expandable = 0; \ 121 node->hw_index = -1; \ 122 node->level = -1; \ 123 node->attached_to_input = -1; \ 124 node->hw_cosq = 0; \ 125 node->node_align_value = 0; \ 126 node->remote_modid = -1; \ 127 node->remote_port = -1; \ 128 node->cosq_map = NULL; \ 129 BCM_PBMP_CLEAR(node->fabric_pbmp); \ 130 node->local_port = -1; \ 131 node->parent = NULL; \ 132 node->sibling = NULL; \ 133 node->child = NULL; \ 134 node->coe_base_index = -1; \ 135 node->coe_num_l2 = 0; \ 136 node->port_gport = -1; 137 138 typedef enum { 139 _BCM_AP_COSQ_FC_PAUSE = 0, 140 _BCM_AP_COSQ_FC_PFC, 141 _BCM_AP_COSQ_FC_VOQFC, 142 _BCM_AP_COSQ_FC_E2ECC, 143 _BCM_AP_COSQ_FC_SAFC 144 } _bcm_ap_fc_type_t; 145 146 typedef enum { 147 _BCM_AP_NODE_UNKNOWN = 0, 148 _BCM_AP_NODE_UCAST, 149 _BCM_AP_NODE_MCAST, 150 _BCM_AP_NODE_VOQ, 151 _BCM_AP_NODE_VLAN_UCAST, 152 _BCM_AP_NODE_VM_UCAST, 153 _BCM_AP_NODE_SERVICE_UCAST, 154 _BCM_AP_NODE_SCHEDULER 155 } _bcm_ap_node_type_e; 156 157 typedef enum { 158 _BCM_AP_COSQ_STATE_NO_CHANGE, 159 _BCM_AP_COSQ_STATE_DISABLE, 160 _BCM_AP_COSQ_STATE_ENABLE, 161 _BCM_AP_COSQ_STATE_SPRI_TO_WRR, 162 _BCM_AP_COSQ_STATE_WRR_TO_SPRI, 163 _BCM_AP_COSQ_STATE_MAX 164 }_bcm_ap_cosq_state_t; 165 166 typedef struct _bcm_ap_cosq_node_s { 167 struct _bcm_ap_cosq_node_s *parent; 168 struct _bcm_ap_cosq_node_s *sibling; 169 struct _bcm_ap_cosq_node_s *child; 170 bcm_gport_t gport; 171 int in_use; 172 int base_index; 173 uint16 numq_expandable; 174 uint16 base_size; 175 int numq; 176 int hw_index; 177 soc_apache_node_lvl_e level; 178 _bcm_ap_node_type_e type; 179 int attached_to_input; 180 int hw_cosq; 181 int wrr_in_use; 182 int node_align_value; 183 184 /* DPVOQ specific information */ 185 bcm_port_t local_port; 186 bcm_module_t remote_modid; 187 bcm_port_t remote_port; 188 bcm_pbmp_t fabric_pbmp; 189 SHR_BITDCL *cosq_map; 190 int coe_num_l2;/* Number of active l2 queues for the subport*/ 191 /*Used in S1 node to store the base index for that sub port*/ 192 int coe_base_index; 193 /* the port gport the node was created with*/ 194 bcm_gport_t port_gport; 195 }_bcm_ap_cosq_node_t; 196 197 typedef struct _bcm_ap_lls_info_s { 198 int child_lvl; /* level of the node */ 199 int child_hw_index; /* hw index of the node */ 200 int node_count[SOC_APACHE_NODE_LVL_MAX]; /* total number of nodes in the lls */ 201 int count[SOC_APACHE_NODE_LVL_MAX]; /* number of nodes in each level */ 202 int offset[SOC_APACHE_NODE_LVL_MAX]; /* index of the starting node at each level */ 203 204 int kbit_max; /* max speed for the node */ 205 int kbit_min; /* min speed for the node */ 206 207 uint32 *mtro_entries; /* entries to maintain mmu mtro level mem */ 208 } _bcm_ap_lls_info_t; 209 210 typedef struct _bcm_ap_cosq_list_s { 211 int count; 212 SHR_BITDCL *bits; 213 }_bcm_ap_cosq_list_t; 214 215 #define _BCM_AP_HSP_PORT_MAX_ROOT 16 216 #define _BCM_AP_HSP_PORT_MAX_L0 5 217 #define _BCM_AP_HSP_PORT_MAX_L1 10 218 #define _BCM_AP_HSP_PORT_MAX_L2 10 219 #define _BCM_AP_HSP_PORT_MAX_L2_PER_L1 2 220 #define _BCM_AP_HSP_PORT_MAX_COS 8 221 222 #define _BCM_AP_CPU_PORT_L0_MIN 1018 223 #define _BCM_AP_CPU_PORT_L0_MAX 1023 224 #define _BCM_AP_MAX_PORT 76 225 226 #define _BCM_AP_ROOT_SCHED_INDEX(u,mmu_port) \ 227 ((mmu_port >= 74) ? (mmu_port - 74) : (mmu_port)) 228 229 #define _BCM_AP_HSP_L0_INDEX(u,mmu_port,cosq) \ 230 ((((mmu_port >= 74) ? (mmu_port - 74) : (mmu_port)) * _BCM_AP_HSP_PORT_MAX_L0) +\ 231 (cosq)) 232 233 #define _BCM_AP_HSP_L1_INDEX(u,mmu_port,cosq) \ 234 ((((mmu_port >= 74) ? (mmu_port - 74) : (mmu_port)) * _BCM_AP_HSP_PORT_MAX_L1) +\ 235 (cosq)) 236 237 #define _BCM_AP_HSP_L2_INDEX(u,mmu_port,cosq) \ 238 ((((mmu_port >= 74) ? (mmu_port - 74) : (mmu_port)) * _BCM_AP_HSP_PORT_MAX_L2) +\ 239 (cosq)) 240 241 242 typedef struct _bcm_ap_pipe_resources_s { 243 int num_base_queues; /* Number of classical queues */ 244 245 _bcm_ap_cosq_list_t l2_queue_list; /* list of l2 queues */ 246 _bcm_ap_cosq_list_t hsp_l2_queue_list; /* list of l2 queues */ 247 _bcm_ap_cosq_list_t l0_sched_list; /* list of l0 sched nodes */ 248 _bcm_ap_cosq_list_t hsp_l0_sched_list; /* list of l0 sched nodes */ 249 _bcm_ap_cosq_list_t cpu_l0_sched_list; /* list of l0 sched nodes */ 250 _bcm_ap_cosq_list_t l1_sched_list; /* list of l1 sched nodes */ 251 _bcm_ap_cosq_list_t hsp_l1_sched_list; /* list of l1 sched nodes */ 252 _bcm_ap_cosq_list_t s1_sched_list; /* list of s1 sched nodes */ 253 254 _bcm_ap_cosq_node_t *p_queue_node; 255 _bcm_ap_cosq_node_t *p_mc_queue_node; 256 } _bcm_ap_pipe_resources_t; 257 258 typedef struct _bcm_ap_cosq_port_info_s { 259 int mc_base; 260 int mc_limit; 261 int uc_base; 262 int uc_limit; 263 int eq_base; 264 int eq_limit; 265 _bcm_ap_pipe_resources_t *resources; 266 } _bcm_ap_cosq_port_info_t; 267 268 typedef struct _bcm_ap_cosq_cpu_cosq_config_s { 269 /* All MC queues have DB and MCQE space */ 270 int enable; 271 int q_min_limit[2]; 272 int q_shared_limit[2]; 273 uint8 q_limit_dynamic[2]; 274 uint8 q_limit_enable[2]; 275 uint8 q_color_limit_enable[2]; 276 } _bcm_ap_cosq_cpu_cosq_config_t; 277 278 #define _AP_XPIPE 0 279 #define _AP_YPIPE 1 280 #define _AP_NUM_PIPES 1 281 282 #define _BCM_AP_PORT_TO_PIPE(u, p) _AP_XPIPE 283 284 typedef struct _bcm_ap_mmu_info_s { 285 286 _bcm_ap_cosq_node_t sched_node[_BCM_AP_NUM_TOTAL_SCHEDULERS]; /* sched nodes */ 287 _bcm_ap_cosq_node_t queue_node[_BCM_AP_NUM_L2_UC_LEAVES]; /* queue nodes */ 288 _bcm_ap_cosq_node_t mc_queue_node[_BCM_AP_NUM_L2_MC_LEAVES]; /* queue nodes */ 289 _bcm_ap_cosq_port_info_t port_info[_BCM_AP_MAX_PORT]; 290 291 _bcm_ap_pipe_resources_t pipe_resources[_AP_NUM_PIPES]; 292 293 int ets_mode; 294 int curr_shared_limit; 295 int curr_merger_index; 296 /* this should be programmed by reading the soc_info which will have 297 * the info from the software OTP 298 */ 299 int num_l2_queues; 300 int _bcm_ap_default_lls; 301 }_bcm_ap_mmu_info_t; 302 303 #define _BCM_DEFAULT_LLS_SET(mmu_info) \ 304 do { \ 305 mmu_info->_bcm_ap_default_lls = 1; \ 306 } while(0); 307 308 #define _BCM_DEFAULT_LLS_IS_SET(mmu_info) \ 309 (mmu_info->_bcm_ap_default_lls) 310 311 #define _BCM_DEFAULT_LLS_RESET(mmu_info) \ 312 do { \ 313 mmu_info->_bcm_ap_default_lls = 0; \ 314 } while(0); 315 316 #define _BCM_AP_START_INDEX_ALIGN_PFC 4 317 #define _BCM_AP_START_INDEX_ALIGN_DEFAULT 1 318 #define _AP_NUM_TIME_DOMAIN 4 319 320 typedef struct _bcm_ap_cosq_time_info_s { 321 soc_field_t field; 322 uint32 ref_count; 323 } _bcm_ap_cosq_time_info_t; 324 325 /* WRED can be enabled at per UC queue / queue group/ port / service pool basis 326 MMU_WRED_AVG_QSIZE_X_PIPE used entry: (16384 + 4096 + 296 + 4) = 20780 327 16383 ~ 0: Unicast Queue 328 20479 ~ 16384: Queue Group per PIPE 329 20775 ~ 20480: Port Service Pool (Port 0 to 73) 330 20779 ~ 20776: Global Service Pool 331 */ 332 STATIC _bcm_ap_cosq_time_info_t time_domain1[BCM_MAX_NUM_UNITS][_AP_NUM_TIME_DOMAIN]; 333 334 #define _AP_NUM_SERVICE_POOL 4 335 336 #define _BCM_AP_PRESOURCES(mi, p) (&(mi)->pipe_resources[(p)]) 337 338 STATIC _bcm_ap_mmu_info_t *_bcm_ap_mmu_info[BCM_MAX_NUM_UNITS]; /* MMU info */ 339 340 STATIC soc_profile_mem_t *_bcm_ap_wred_profile[BCM_MAX_NUM_UNITS]; 341 STATIC soc_profile_mem_t *_bcm_ap_cos_map_profile[BCM_MAX_NUM_UNITS]; 342 STATIC soc_profile_mem_t *_bcm_ap_sample_int_profile[BCM_MAX_NUM_UNITS]; 343 STATIC soc_profile_reg_t *_bcm_ap_feedback_profile[BCM_MAX_NUM_UNITS]; 344 STATIC soc_profile_reg_t *_bcm_ap_llfc_profile[BCM_MAX_NUM_UNITS]; 345 STATIC soc_profile_mem_t *_bcm_ap_voq_port_map_profile[BCM_MAX_NUM_UNITS]; 346 static soc_profile_mem_t *_bcm_ap_ifp_cos_map_profile[BCM_MAX_NUM_UNITS]; 347 STATIC soc_profile_mem_t *_bcm_ap_service_port_map_profile[BCM_MAX_NUM_UNITS]; 348 STATIC soc_profile_mem_t *_bcm_ap_service_cos_map_profile[BCM_MAX_NUM_UNITS]; 349 350 STATIC _bcm_ap_cosq_cpu_cosq_config_t *_bcm_ap_cosq_cpu_cosq_config[BCM_MAX_NUM_UNITS][_BCM_AP_NUM_L2_CPU_LEAVES]; 351 352 STATIC int 353 _bcm_ap_node_index_set(_bcm_ap_cosq_list_t *list, int start, int range); 354 355 STATIC int _bcm_ap_voq_next_base_node_get(int unit, bcm_port_t port, 356 int modid, 357 _bcm_ap_cosq_node_t **base_node); 358 STATIC int 359 _bcm_ap_cosq_mapping_set(int unit, bcm_port_t ing_port, bcm_cos_t priority, 360 uint32 flags, bcm_gport_t gport, bcm_cos_queue_t cosq); 361 362 STATIC int 363 _bcm_ap_map_fc_status_to_node(int unit, int port, _bcm_ap_fc_type_t fct, 364 int spad_offset, int cosq, uint32 hw_index, int level); 365 STATIC int 366 _bcm_ap_cosq_max_nodes_get(int unit, soc_apache_node_lvl_e level, 367 int *id); 368 369 typedef enum { 370 _BCM_AP_COSQ_TYPE_UCAST, 371 _BCM_AP_COSQ_TYPE_MCAST, 372 _BCM_AP_COSQ_TYPE_EXT_UCAST 373 } _bcm_ap_cosq_type_t; 374 375 #define IS_AP_HSP_PORT(u,p) \ 376 ((_soc_apache_port_sched_type_get((u),(p)) == SOC_APACHE_SCHED_HSP) ? 1 : 0) 377 378 typedef struct _bcm_ap_endpoint_s { 379 uint32 flags; /* BCM_COSQ_CLASSIFIER_xxx flags */ 380 bcm_vlan_t vlan; /* VLAN */ 381 bcm_mac_t mac; /* MAC address */ 382 bcm_vrf_t vrf; /* Virtual Router Instance */ 383 bcm_ip_t ip_addr; /* IPv4 address */ 384 bcm_ip6_t ip6_addr; /* IPv6 address */ 385 bcm_gport_t gport; /* GPORT ID */ 386 } _bcm_ap_endpoint_t; 387 388 typedef struct _bcm_ap_endpoint_queuing_info_s { 389 int num_endpoint; /* Number of endpoints */ 390 _bcm_ap_endpoint_t **ptr_array; /* Array of pointers to endpoints */ 391 soc_profile_mem_t *cos_map_profile; /* Internal priority to CoS queue 392 mapping profile */ 393 } _bcm_ap_endpoint_queuing_info_t; 394 395 STATIC int 396 _bcm_ap_cosq_egress_sp_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 397 int *p_pool_start, int *p_pool_end); 398 399 STATIC _bcm_ap_endpoint_queuing_info_t *_bcm_ap_endpoint_queuing_info[BCM_MAX_NUM_UNITS]; 400 401 STATIC int 402 _bcm_ap_cosq_dynamic_thresh_enable_get(int unit, 403 bcm_gport_t gport, bcm_cos_queue_t cosq, 404 bcm_cosq_control_t type, int *arg); 405 406 STATIC int 407 _bcm_ap_fc_status_map_gport(int unit, int port, 408 bcm_gport_t gport, _bcm_ap_fc_type_t fct, uint32 *cos_bmp); 409 STATIC int 410 _bcm_ap_port_fc_profile_set(int unit, int port, _bcm_cosq_op_t op, 411 int entry_cnt, int *pfc_class, uint32 *cos_bmp); 412 STATIC int 413 _bcm_ap_cosq_node_get(int unit, bcm_gport_t gport, 414 bcm_cos_queue_t cosq,bcm_module_t *modid, bcm_port_t *port, 415 int *id, _bcm_ap_cosq_node_t **node); 416 417 int _bcm_ap_get_s1_node(int unit, bcm_gport_t subport, 418 _bcm_ap_cosq_node_t **s1_node) ; 419 STATIC int 420 _bcm_ap_cosq_sched_parent_child_set(int unit, int port, int level, 421 int sched_index, int child_index, 422 soc_apache_sched_mode_e sched_mode, 423 int weight, _bcm_ap_cosq_node_t *child_node); 424 #define _BCM_AP_NUM_ENDPOINT(unit) \ 425 (_bcm_ap_endpoint_queuing_info[unit]->num_endpoint) 426 427 #define _BCM_AP_ENDPOINT(unit, id) \ 428 (_bcm_ap_endpoint_queuing_info[unit]->ptr_array[id]) 429 430 #define _BCM_AP_ENDPOINT_IS_USED(unit, id) \ 431 (_bcm_ap_endpoint_queuing_info[unit]->ptr_array[id] != NULL) 432 433 #define _BCM_AP_ENDPOINT_COS_MAP_PROFILE(unit) \ 434 (_bcm_ap_endpoint_queuing_info[unit]->cos_map_profile) 435 436 437 /* 438 * Function: 439 * _bcm_ap_cosq_map_index_set 440 * Purpose: 441 * Mark indices as allocated 442 * Parameters: 443 * list - (IN) bit list 444 * start - (IN) start index 445 * range - (IN) range bits 446 * Returns: 447 * BCM_E_XXX 448 */ 449 STATIC int 450 _bcm_ap_cosq_map_index_set(SHR_BITDCL *list, int start, int range) 451 { 452 SHR_BITSET_RANGE(list, start, range); 453 return BCM_E_NONE; 454 } 455 456 #ifdef BCM_WARM_BOOT_SUPPORT 457 458 #define BCM_WB_VERSION_1_0 SOC_SCACHE_VERSION(1,0) 459 #define BCM_WB_VERSION_1_1 SOC_SCACHE_VERSION(1,1) 460 #define BCM_WB_VERSION_1_2 SOC_SCACHE_VERSION(1,2) 461 462 #define BCM_WB_DEFAULT_VERSION BCM_WB_VERSION_1_2 463 464 STATIC int 465 _bcm_ap_cosq_wb_alloc(int unit) 466 { 467 _bcm_ap_mmu_info_t *mmu_info; 468 soc_scache_handle_t scache_handle; 469 uint8 *scache_ptr; 470 int rv, alloc_size, node_list_sizes[3], ii, jj; 471 uint32 shadow_size = 0; 472 473 mmu_info = _bcm_ap_mmu_info[unit]; 474 475 if (!mmu_info) { 476 return BCM_E_INIT; 477 } 478 479 node_list_sizes[0] = _BCM_AP_NUM_L2_UC_LEAVES; 480 node_list_sizes[1] = _BCM_AP_NUM_L2_MC_LEAVES; 481 node_list_sizes[2] = _BCM_AP_NUM_TOTAL_SCHEDULERS; 482 483 alloc_size = 0; 484 for(ii = 0; ii < 3; ii++) { 485 alloc_size += sizeof(uint32); 486 for(jj = 0; jj < node_list_sizes[ii]; jj++) { 487 alloc_size += 8 * sizeof(uint32); 488 } 489 } 490 491 /* Size of TIME_DOMAINr field and count reference */ 492 alloc_size += _AP_NUM_TIME_DOMAIN * sizeof(_bcm_ap_cosq_time_info_t); 493 494 soc_apache_fc_map_shadow_size_get(unit, &shadow_size); 495 alloc_size += shadow_size; 496 497 /* added in BCM_WB_VERSION_1_1 498 * to sync _bcm_ap_mmu_info[unit]->ets_mode/curr_shared_limit 499 */ 500 alloc_size += 2 * sizeof(int); 501 502 /* added in BCM_WB_VERSION_1_1 503 * to sync the reference count of IFP_COS_MAPm 504 */ 505 alloc_size += (SOC_MEM_SIZE(unit,IFP_COS_MAPm) / _AP_NUM_INTERNAL_PRI) * 506 sizeof(uint16); 507 508 alloc_size += sizeof(uint16) * SOC_MEM_SIZE(unit, SERVICE_COS_MAPm) / 509 _AP_SCM_ENTRIES_PER_SET; 510 alloc_size += sizeof(uint16) * SOC_MEM_SIZE(unit, SERVICE_PORT_MAPm) / 511 _AP_SPM_ENTRIES_PER_SET; 512 513 alloc_size += sizeof(uint16) * SOC_MEM_SIZE(unit, VOQ_PORT_MAPm) / 514 _AP_VPM_ENTRIES_PER_SET; 515 /* 516 * Sync num_cos value 517 */ 518 alloc_size += sizeof(int); 519 520 /* 521 * Added in BCM_WB_VERSION_1_1 to sync _bcm_ap_endpoint_queueing_info 522 */ 523 if (soc_feature(unit, soc_feature_endpoint_queuing)) { 524 alloc_size += ((_BCM_AP_NUM_ENDPOINT(unit) - 1 ) * 525 (sizeof(uint32) + sizeof(bcm_vrf_t) + sizeof(bcm_ip6_t))); 526 527 /* Added in BCM_WB_VERSION_1_2 to sync ENDPOINT_COS_MAP memory profile */ 528 alloc_size += (SOC_MEM_SIZE(unit, ENDPOINT_COS_MAPm) / _AP_NUM_INTERNAL_PRI) * 529 sizeof(uint16); 530 } 531 532 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_COSQ, 0); 533 534 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, TRUE, alloc_size, 535 &scache_ptr, BCM_WB_DEFAULT_VERSION, NULL); 536 if (rv == BCM_E_NOT_FOUND) { 537 rv = BCM_E_NONE; 538 } 539 540 return rv; 541 } 542 543 #define _BCM_AP_WB_NTYPE_UCAST 0 544 #define _BCM_AP_WB_NTYPE_MCAST 1 545 #define _BCM_AP_WB_NTYPE_SCHED 2 546 547 548 /* 2 bit node type, 15 bit nid, 15 hw cosq */ 549 #define _BCM_AP_WB_SET_NODE_W1(ntype,nid,hwcosq) \ 550 (((ntype & 3)) | \ 551 (((nid) & 0x7fff) << 2) | \ 552 (((hwcosq) & 0x7fff) << 17)) 553 554 #define _BCM_AP_WB_GET_NODE_TYPE_W1(w1) ((w1) & 3) 555 #define _BCM_AP_WB_GET_NODE_ID_W1(w1) (((w1) >> 2) & 0x7fff) 556 #define _BCM_AP_WB_GET_NODE_HW_COSQ_W1(w1) (((w1) >> 17) & 0x7fff) 557 558 559 /* 15 bit hw index, 13 bit parent id, 3 bit level, 1 bit wrr_in_use 560 */ 561 562 #define _BCM_AP_WB_SET_NODE_W2(hwindex,parentid,lvl,wrr_in_use) \ 563 ((hwindex & 0x7fff) | \ 564 ((parentid & 0x1fff) << 15) | \ 565 ((lvl & 0x7) << 28) | \ 566 ((wrr_in_use & 0x1) << 31)) 567 568 #define _BCM_AP_WB_GET_NODE_HW_INDEX_W2(w1) ((w1) & 0x7fff) 569 #define _BCM_AP_WB_GET_NODE_PARENTID_W2(w1) (((w1) >> 15) & 0x1fff) 570 #define _BCM_AP_WB_GET_NODE_LEVEL_W2(w1) (((w1) >> 28) & 0x7) 571 #define _BCM_AP_WB_GET_NODE_WRR_IN_USE_W2(w1) (((w1) >> 31) & 0x1) 572 573 #define _BCM_AP_WB_SET_NODE_W3(gport) (gport) 574 #define _BCM_AP_WB_SET_NODE_W4(gport) (gport) 575 576 /* 15 bit numq, 15 bit cosq, 1 bit dmvoq_en, 1 bit coe_en 577 */ 578 #define _BCM_AP_WB_SET_NODE_W5(numq,cosq,dmvoq_en,coe_en) \ 579 ((numq & 0x7fff) | \ 580 ((cosq & 0x7fff) << 15) | \ 581 ((dmvoq_en &0x01) << 30) | \ 582 ((coe_en & 0x01) << 31)) 583 584 #define _BCM_AP_WB_GET_NODE_NUMQ_W5(w1) ((w1) & 0x7fff) 585 #define _BCM_AP_WB_GET_NODE_COSQATTT_W5(w1) (((w1) >> 15) & 0x7fff) 586 #define _BCM_AP_WB_GET_NODE_DMVOQ_EN_W5(w1) (((w1) >> 30) & 0x1) 587 #define _BCM_AP_WB_GET_NODE_COE_EN_W5(w1) (((w1) >> 31) & 0x1) 588 589 /* 10 bit base size, 15 bit base_index, 1 bit expand, 4 bit type */ 590 /* Encoding node_align_value in 1 bit 0->0, 1->4 */ 591 #define _BCM_AP_WB_SET_NODE_W6(base_size,base_index,expand,type, align) \ 592 ((base_size & 0x3ff) | \ 593 ((base_index & 0x7fff) << 10) | \ 594 ((expand & 0x1) << 25) | \ 595 ((type & 0xf) << 26) | \ 596 ((align & 0x1) << 30)) 597 598 #define _BCM_AP_WB_GET_BASE_SIZE_W6(w1) ((w1) & 0x3ff) 599 #define _BCM_AP_WB_GET_BASE_INDEX_W6(w1) (((w1) >> 10) & 0x7fff) 600 #define _BCM_AP_WB_GET_EXPAND_W6(w1) (((w1) >> 25) & 0x1) 601 #define _BCM_AP_WB_TYPE_W6(w1) (((w1) >> 26) & 0xf) 602 #define _BCM_AP_WB_GET_ALIGN_W6(w1) (((w1) >> 30) & 0x1) 603 604 /* 9 bit remote_modid, 9 bit remote_port. 605 * Present only if dmvoq bit is set in W6 606 */ 607 #define _BCM_AP_WB_SET_NODE_W7(remote_modid,remote_port) \ 608 ((((remote_modid) & 0x1ff)) | \ 609 (((remote_port) & 0x1ff) << 9)) 610 611 #define _BCM_AP_WB_GET_NODE_DEST_MODID_W7(w1) ((w1) & 0x1ff) 612 #define _BCM_AP_WB_GET_NODE_DEST_PORT_W7(w1) (((w1) >> 9) & 0x1ff) 613 614 /* 14 bit coe base index, 8 bit coe_num_l2 */ 615 #define _BCM_AP_WB_SET_NODE_W8(coe_base_index, coe_num_l2) \ 616 ((coe_base_index & 0x3fff) | \ 617 ((coe_num_l2 & 0xff) << 14)) 618 619 #define _BCM_AP_WB_GET_COE_BASE_INDEX_W8(w1) ((w1) & 0x3fff) 620 #define _BCM_AP_WB_GET_COE_NUM_L2_W8(w1) (((w1) >> 14) & 0xff) 621 622 #define _BCM_AP_NODE_ID(np,np0) (np - np0) 623 624 STATIC void * 625 _bcm_ap_cosq_alloc_clear(void *cp, unsigned int size, char *description); 626 627 628 STATIC int 629 _bcm_ap_child_level_get(int unit, _bcm_ap_cosq_node_t *node , int *child_level) 630 { 631 632 if (!node) 633 { 634 return BCM_E_INTERNAL; 635 } 636 if (node->level == SOC_APACHE_NODE_LVL_ROOT) 637 { 638 *child_level = SOC_APACHE_NODE_LVL_S1; 639 640 }else if (node->level == SOC_APACHE_NODE_LVL_S1) 641 { 642 *child_level = SOC_APACHE_NODE_LVL_L0; 643 }else if (node->level == SOC_APACHE_NODE_LVL_L0) 644 { 645 *child_level = SOC_APACHE_NODE_LVL_L1; 646 }else if (node->level == SOC_APACHE_NODE_LVL_L1) 647 { 648 *child_level = SOC_APACHE_NODE_LVL_L2; 649 } 650 return BCM_E_NONE; 651 } 652 /* 653 * Function: 654 * _bcm_ap_cosq_map_alloc_set 655 * Purpose: 656 * Allocate the cosq_map bitmap and 657 * restore 658 * Parameters: 659 * node - (IN) cosq_node 660 * Returns: 661 * BCM_E_XXX 662 */ 663 STATIC int 664 _bcm_ap_cosq_map_alloc_set(int unit, _bcm_ap_cosq_node_t *node) 665 { 666 _bcm_ap_cosq_node_t *child; 667 int alloc_size; 668 int max_nodes = 0; 669 int child_level = 0; 670 671 BCM_IF_ERROR_RETURN 672 (_bcm_ap_child_level_get(unit, node, &child_level)); 673 BCM_IF_ERROR_RETURN 674 (_bcm_ap_cosq_max_nodes_get(unit, child_level, &max_nodes)); 675 if (node->cosq_map == NULL) { 676 if ( node->numq == -1 ) { 677 alloc_size = SHR_BITALLOCSIZE(max_nodes); 678 } else { 679 alloc_size = SHR_BITALLOCSIZE(node->numq); 680 } 681 node->cosq_map = _bcm_ap_cosq_alloc_clear(node->cosq_map, 682 alloc_size, 683 "cosq_map"); 684 if (node->cosq_map == NULL) { 685 return BCM_E_MEMORY; 686 } 687 } 688 child = node->child; 689 while (child != NULL) { 690 BCM_IF_ERROR_RETURN 691 (_bcm_ap_cosq_map_index_set(node->cosq_map, 692 child->attached_to_input, 1)); 693 child = child->sibling; 694 } 695 696 return BCM_E_NONE; 697 } 698 699 /* 700 * Function: 701 * _bcm_ap_cosq_map_node_recover 702 * Purpose: 703 * Used to recover cos_map for S0,S1,L0,L1 levels 704 * Parameters: 705 * node - (IN) cosq_node 706 * Returns: 707 * BCM_E_XXX 708 */ 709 710 STATIC int 711 _bcm_ap_cosq_map_node_recover(int unit ,_bcm_ap_cosq_node_t *node) 712 { 713 if (!node) { 714 return BCM_E_NONE; 715 } 716 if (node->level == SOC_APACHE_NODE_LVL_L2) { 717 return BCM_E_NONE; 718 } 719 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_map_alloc_set(unit , node)); 720 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_map_node_recover(unit, node->sibling)); 721 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_map_node_recover(unit, node->child)); 722 return BCM_E_NONE; 723 } 724 /* 725 * Function : 726 * bcm_ap_cosq_endpoint_recover 727 * Purpose : 728 * Recover endpoint info from scache 729 * Parameters: 730 * unit -(IN) unit number 731 * scache_ptr -(IN/OUT)scache pointer 732 * Returns: 733 * BCM_E_XXX 734 */ 735 STATIC int 736 bcm_ap_cosq_endpoint_recover(int unit, uint8 **scache_ptr) 737 { 738 int entry_size; 739 int flags; 740 int ii; 741 742 entry_size = sizeof(uint32) + sizeof(bcm_vrf_t) + sizeof(bcm_ip6_t); 743 /* entry 0 was reserved and is not synced. */ 744 for (ii = 1; ii < _BCM_AP_NUM_ENDPOINT(unit); ii++) { 745 sal_memcpy(&flags, (*scache_ptr), sizeof(uint32)); 746 747 if ((flags & BCM_COSQ_CLASSIFIER_L2) || 748 (flags & BCM_COSQ_CLASSIFIER_L3) || 749 (flags & BCM_COSQ_CLASSIFIER_GPORT)) { 750 _BCM_AP_ENDPOINT(unit, ii) = sal_alloc( 751 sizeof(_bcm_ap_endpoint_t), "Endpoint Info"); 752 if (_BCM_AP_ENDPOINT(unit, ii) == NULL) { 753 return BCM_E_MEMORY; 754 } 755 sal_memset(_BCM_AP_ENDPOINT(unit, ii), 0, 756 sizeof(_bcm_ap_endpoint_t)); 757 _BCM_AP_ENDPOINT(unit, ii)->flags = flags; 758 if (flags & BCM_COSQ_CLASSIFIER_L2) { 759 (*scache_ptr) += sizeof(uint32); 760 sal_memcpy(&(_BCM_AP_ENDPOINT(unit, ii)->vlan), 761 (*scache_ptr), sizeof(bcm_vlan_t)); 762 (*scache_ptr) += sizeof(bcm_vlan_t); 763 sal_memcpy(_BCM_AP_ENDPOINT(unit, ii)->mac, (*scache_ptr), 764 sizeof(bcm_mac_t)); 765 (*scache_ptr) += (entry_size - sizeof(uint32) - 766 sizeof(bcm_vlan_t)); 767 } else if (flags & BCM_COSQ_CLASSIFIER_L3) { 768 (*scache_ptr) += sizeof(uint32); 769 sal_memcpy(&(_BCM_AP_ENDPOINT(unit, ii)->vrf), 770 (*scache_ptr), sizeof(bcm_vrf_t)); 771 (*scache_ptr) += sizeof(bcm_vrf_t); 772 if (flags & BCM_COSQ_CLASSIFIER_IP6) { 773 sal_memcpy(_BCM_AP_ENDPOINT(unit, ii)->ip6_addr, (*scache_ptr), 774 sizeof(bcm_ip6_t)); 775 } else { 776 sal_memcpy(&(_BCM_AP_ENDPOINT(unit, ii)->ip_addr), (*scache_ptr), 777 sizeof(bcm_ip_t)); 778 } 779 (*scache_ptr) += (entry_size - sizeof(uint32) - 780 sizeof(bcm_vrf_t)); 781 } else { 782 (*scache_ptr) += sizeof(uint32); 783 sal_memcpy(&(_BCM_AP_ENDPOINT(unit, ii)->gport), 784 (*scache_ptr), sizeof(bcm_gport_t)); 785 (*scache_ptr) += (entry_size - sizeof(uint32)); 786 } 787 } else { 788 (*scache_ptr) += entry_size; 789 } 790 } 791 792 return BCM_E_NONE; 793 } 794 795 int 796 bcm_ap_cosq_reinit(int unit) 797 { 798 soc_scache_handle_t scache_handle; 799 uint8 *scache_ptr; 800 uint32 *u32_scache_ptr, wval, fval; 801 uint16 *u16_scache_ptr; 802 _bcm_ap_cosq_node_t *node; 803 bcm_port_t port; 804 int rv, ii, jj, set_index; 805 _bcm_ap_cosq_node_t *nodes[3]; 806 int xnode_id, stable_size, count, profile_index; 807 _bcm_ap_mmu_info_t *mmu_info; 808 uint32 entry[SOC_MAX_MEM_WORDS]; 809 soc_profile_mem_t *profile_mem; 810 _bcm_ap_pipe_resources_t *res; 811 soc_mem_t mem; 812 mmu_wred_config_entry_t qentry; 813 int alloc_size; 814 int additional_scache_size = 0; 815 uint16 recovered_ver = 0; 816 int index=0; 817 bcm_pbmp_t all_pbmp; 818 soc_profile_reg_t *profile_reg; 819 soc_info_t *si; 820 bcm_port_t phy_port, mmu_port; 821 soc_reg_t reg; 822 uint32 tmp32; 823 int dmvoq_en = 0, coe_en = 0; 824 uint64 rval, index_map; 825 static const soc_reg_t llfc_cfgr[] = { 826 PORT_PFC_CFG0r, PORT_PFC_CFG1r, PORT_PFC_CFG2r 827 }; 828 int num; 829 _bcm_ap_cosq_node_t *port_info; 830 831 si = &SOC_INFO(unit); 832 SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size)); 833 if ((stable_size == 0) || (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit))) { 834 /* COSQ warmboot requires extended scache support i.e. level2 warmboot*/ 835 return BCM_E_NONE; 836 } 837 838 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_COSQ, 0); 839 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 0, &scache_ptr, 840 BCM_WB_DEFAULT_VERSION, &recovered_ver); 841 if (BCM_FAILURE(rv)) { 842 return rv; 843 } 844 845 mmu_info = _bcm_ap_mmu_info[unit]; 846 847 if (!mmu_info) { 848 return BCM_E_INIT; 849 } 850 851 res = _BCM_AP_PRESOURCES(mmu_info, _AP_XPIPE); 852 u32_scache_ptr = (uint32*) scache_ptr; 853 854 nodes[0] = &mmu_info->queue_node[0]; 855 nodes[1] = &mmu_info->mc_queue_node[0]; 856 nodes[2] = &mmu_info->sched_node[0]; 857 858 for(ii = 0; ii < 3; ii++) { 859 count = *u32_scache_ptr; 860 u32_scache_ptr++; 861 for(jj = 0; jj < count; jj++) { 862 wval = *u32_scache_ptr; 863 u32_scache_ptr++; 864 xnode_id = _BCM_AP_WB_GET_NODE_ID_W1(wval); 865 node = nodes[ii] + xnode_id; 866 node->in_use = TRUE; 867 node->numq = 1; 868 fval = _BCM_AP_WB_GET_NODE_HW_COSQ_W1(wval); 869 node->hw_cosq = (fval == 0x7fff)? -1 : fval; 870 871 wval = *u32_scache_ptr; 872 u32_scache_ptr++; 873 fval = _BCM_AP_WB_GET_NODE_HW_INDEX_W2(wval); 874 node->hw_index = (fval == 0x7fff) ? -1 : fval; 875 fval = _BCM_AP_WB_GET_NODE_PARENTID_W2(wval); 876 if (fval == 0x1fff) { 877 node->parent = NULL; 878 } else { 879 node->parent = &mmu_info->sched_node[fval]; 880 if (node->parent->child) { 881 node->sibling = node->parent->child; 882 } 883 node->parent->child = node; 884 } 885 node->level = _BCM_AP_WB_GET_NODE_LEVEL_W2(wval); 886 node->wrr_in_use = _BCM_AP_WB_GET_NODE_WRR_IN_USE_W2(wval); 887 888 node->gport = *u32_scache_ptr++; 889 node->port_gport = *u32_scache_ptr++; 890 891 wval = *u32_scache_ptr; 892 u32_scache_ptr++; 893 node->numq = _BCM_AP_WB_GET_NODE_NUMQ_W5(wval); 894 /* numq of -1 will be recovered as 32767 need to update back as -1 */ 895 if (node->numq == 32767) 896 { 897 node->numq = -1 ; 898 } 899 fval = _BCM_AP_WB_GET_NODE_COSQATTT_W5(wval); 900 node->attached_to_input = (fval == 0x7fff) ? -1 : fval; 901 dmvoq_en = _BCM_AP_WB_GET_NODE_DMVOQ_EN_W5(wval); 902 coe_en = _BCM_AP_WB_GET_NODE_COE_EN_W5(wval); 903 904 wval = *u32_scache_ptr; 905 u32_scache_ptr++; 906 node->base_size = _BCM_AP_WB_GET_BASE_SIZE_W6(wval); 907 fval = _BCM_AP_WB_GET_BASE_INDEX_W6(wval); 908 node->base_index = (fval == 0x7fff) ? -1 : fval; 909 node->numq_expandable = _BCM_AP_WB_GET_EXPAND_W6(wval); 910 node->type = _BCM_AP_WB_TYPE_W6(wval); 911 node->node_align_value = (_BCM_AP_WB_GET_ALIGN_W6(wval) ? 4 : 0); 912 913 if (dmvoq_en) { 914 wval = *u32_scache_ptr; 915 u32_scache_ptr++; 916 fval = _BCM_AP_WB_GET_NODE_DEST_MODID_W7(wval); 917 node->remote_modid = (fval == 0x1ff) ? -1 : fval; 918 fval = _BCM_AP_WB_GET_NODE_DEST_PORT_W7(wval); 919 node->remote_port = (fval == 0x1ff) ? -1 : fval; 920 } 921 922 if (soc_feature(unit, soc_feature_mmu_hqos_four_level) && 923 (node->level == SOC_APACHE_NODE_LVL_S1) && 924 coe_en) { 925 wval = *u32_scache_ptr; 926 u32_scache_ptr++; 927 node->coe_base_index = _BCM_AP_WB_GET_COE_BASE_INDEX_W8(wval); 928 if (node->coe_base_index == 16383 ) 929 { 930 node->coe_base_index = -1; 931 } 932 node->coe_num_l2 = _BCM_AP_WB_GET_COE_NUM_L2_W8(wval); 933 } 934 935 /* 936 * Not checking the return value intentionally 937 * to take care of warmboot case. 938 */ 939 /* coverity[unchecked_value] */ 940 _bcm_ap_cosq_node_get(unit, node->gport, 0, NULL, 941 &node->local_port, NULL, NULL); 942 943 if (node->hw_index != -1) { 944 if (node->level == SOC_APACHE_NODE_LVL_S1) { 945 _bcm_ap_node_index_set(&res->s1_sched_list, 946 node->hw_index, 1); 947 } else if (node->level == SOC_APACHE_NODE_LVL_L0) { 948 _bcm_ap_node_index_set(&res->l0_sched_list, 949 node->hw_index, 1); 950 if (IS_AP_HSP_PORT(unit, node->local_port)) { 951 _bcm_ap_node_index_set(&res->hsp_l0_sched_list, 952 node->hw_index, 1); 953 } 954 if (IS_CPU_PORT(unit, node->local_port)) { 955 _bcm_ap_node_index_set(&res->cpu_l0_sched_list, 956 node->hw_index - _BCM_AP_CPU_PORT_L0_MIN, 1); 957 } 958 } else if (node->level == SOC_APACHE_NODE_LVL_L1) { 959 _bcm_ap_node_index_set(&res->l1_sched_list, 960 node->hw_index, 1); 961 if (IS_AP_HSP_PORT(unit, node->local_port)) { 962 _bcm_ap_node_index_set(&res->hsp_l1_sched_list, 963 node->hw_index, 1); 964 } 965 } else if (node->level == SOC_APACHE_NODE_LVL_L2) { 966 _bcm_ap_node_index_set(&res->l2_queue_list, 967 node->hw_index, 1); 968 if (IS_AP_HSP_PORT(unit, node->local_port)) { 969 _bcm_ap_node_index_set(&res->hsp_l2_queue_list, 970 node->hw_index, 1); 971 } 972 } 973 } 974 } 975 } 976 977 BCM_PBMP_CLEAR(all_pbmp); 978 BCM_PBMP_ASSIGN(all_pbmp, PBMP_ALL(unit)); 979 980 /* Restoring the cosq_map */ 981 PBMP_ITER(all_pbmp, port) { 982 node = NULL; 983 984 /* root node */ 985 port_info = &mmu_info->sched_node[port]; 986 if (port_info && (port_info->gport >= 0)) { 987 SOC_IF_ERROR_RETURN ( 988 _bcm_ap_cosq_map_node_recover(unit, port_info)); 989 } 990 } 991 992 /* Recovery TIME_DOMAINr field and count reference */ 993 alloc_size = _AP_NUM_TIME_DOMAIN * sizeof(_bcm_ap_cosq_time_info_t); 994 sal_memcpy(&time_domain1[unit][0], u32_scache_ptr, alloc_size); 995 time_domain1[unit][0].field = TIME_0f; 996 time_domain1[unit][1].field = TIME_1f; 997 time_domain1[unit][2].field = TIME_2f; 998 time_domain1[unit][3].field = TIME_3f; 999 u32_scache_ptr += alloc_size / sizeof(uint32); 1000 soc_apache_fc_map_shadow_load(unit, &u32_scache_ptr); 1001 1002 mmu_info->curr_shared_limit = *u32_scache_ptr++; 1003 1004 u16_scache_ptr = (uint16 *)u32_scache_ptr; 1005 1006 /* Update IFP_COS_MAP memory profile reference counter */ 1007 profile_mem = _bcm_ap_ifp_cos_map_profile[unit]; 1008 num = SOC_MEM_SIZE(unit,IFP_COS_MAPm) / _AP_NUM_INTERNAL_PRI; 1009 for (ii = 0; ii < num; ii++) { 1010 for (jj = 0; jj < *u16_scache_ptr; jj++) { 1011 SOC_IF_ERROR_RETURN( 1012 soc_profile_mem_reference(unit, profile_mem, 1013 ii * _AP_NUM_INTERNAL_PRI, 1014 _AP_NUM_INTERNAL_PRI)); 1015 } 1016 u16_scache_ptr++; 1017 } 1018 1019 profile_mem = _bcm_ap_service_cos_map_profile[unit]; 1020 num = SOC_MEM_SIZE(unit, SERVICE_COS_MAPm) / _AP_SCM_ENTRIES_PER_SET; 1021 for (ii = 0; ii < num; ii++) { 1022 for (jj = 0; jj < *u16_scache_ptr; jj++) { 1023 SOC_IF_ERROR_RETURN( 1024 soc_profile_mem_reference(unit, profile_mem, 1025 ii * _AP_SCM_ENTRIES_PER_SET, 1026 _AP_SCM_ENTRIES_PER_SET)); 1027 } 1028 u16_scache_ptr++; 1029 } 1030 1031 profile_mem = _bcm_ap_service_port_map_profile[unit]; 1032 num = SOC_MEM_SIZE(unit, SERVICE_PORT_MAPm) / _AP_SPM_ENTRIES_PER_SET; 1033 for (ii = 0; ii < num; ii++) { 1034 for (jj = 0; jj < *u16_scache_ptr; jj++) { 1035 SOC_IF_ERROR_RETURN( 1036 soc_profile_mem_reference(unit, profile_mem, 1037 ii * _AP_SPM_ENTRIES_PER_SET, 1038 _AP_SPM_ENTRIES_PER_SET)); 1039 } 1040 u16_scache_ptr++; 1041 } 1042 1043 profile_mem = _bcm_ap_voq_port_map_profile[unit]; 1044 num = SOC_MEM_SIZE(unit,VOQ_PORT_MAPm) / _AP_VPM_ENTRIES_PER_SET; 1045 for (ii = 0; ii < num; ii++) { 1046 for (jj = 0; jj < *u16_scache_ptr; jj++) { 1047 SOC_IF_ERROR_RETURN( 1048 soc_profile_mem_reference(unit, profile_mem, 1049 ii * _AP_VPM_ENTRIES_PER_SET, 1050 _AP_VPM_ENTRIES_PER_SET)); 1051 } 1052 u16_scache_ptr++; 1053 } 1054 1055 u32_scache_ptr = (uint32 *)u16_scache_ptr; 1056 NUM_COS(unit) = *u32_scache_ptr++; 1057 scache_ptr = (uint8*)u32_scache_ptr; 1058 1059 /* 1060 * BCM_WB_VERSION_1_1 sync endpoint info 1061 */ 1062 if (recovered_ver >= BCM_WB_VERSION_1_1) { 1063 if (soc_feature(unit, soc_feature_endpoint_queuing)) { 1064 scache_ptr = (uint8 *)u32_scache_ptr; 1065 BCM_IF_ERROR_RETURN( 1066 bcm_ap_cosq_endpoint_recover(unit, &scache_ptr)); 1067 } 1068 } else { 1069 if (soc_feature(unit, soc_feature_endpoint_queuing)) { 1070 additional_scache_size += ((_BCM_AP_NUM_ENDPOINT(unit) - 1)* 1071 (sizeof(uint32) + sizeof(bcm_vrf_t)+ sizeof(bcm_ip6_t))); 1072 } 1073 } 1074 1075 if (recovered_ver >= BCM_WB_VERSION_1_2) { 1076 if (soc_feature(unit, soc_feature_endpoint_queuing)) { 1077 u16_scache_ptr = (uint16 *)scache_ptr; 1078 /* 1079 * BCM_WB_VERSION_1_2 1080 * Update ENDPOINT_COS_MAP memory profile reference counter 1081 */ 1082 profile_mem = _bcm_ap_endpoint_queuing_info[unit]->cos_map_profile; 1083 num = SOC_MEM_SIZE(unit, ENDPOINT_COS_MAPm) / _AP_NUM_INTERNAL_PRI; 1084 for (ii = 0; ii < num; ii++) { 1085 for (jj = 0; jj < *u16_scache_ptr; jj++) { 1086 SOC_IF_ERROR_RETURN(soc_profile_mem_reference(unit, profile_mem, 1087 ii * _AP_NUM_INTERNAL_PRI, 1088 _AP_NUM_INTERNAL_PRI)); 1089 } 1090 u16_scache_ptr++; 1091 } 1092 } 1093 } else { 1094 if (soc_feature(unit, soc_feature_endpoint_queuing)) { 1095 additional_scache_size += (SOC_MEM_SIZE(unit, ENDPOINT_COS_MAPm) / _AP_NUM_INTERNAL_PRI) * 1096 sizeof(uint16); 1097 } 1098 } 1099 1100 if (additional_scache_size > 0) { 1101 /* coverity[dead_error_begin] */ 1102 BCM_IF_ERROR_RETURN( 1103 soc_scache_realloc(unit, scache_handle, additional_scache_size)); 1104 } 1105 1106 /* Update reference counts for DSCP_TABLE profile*/ 1107 PBMP_ITER(all_pbmp, port) { 1108 if (IS_LB_PORT(unit, port)) { 1109 /* Loopback port base starts from 64 */ 1110 continue; 1111 } 1112 SOC_IF_ERROR_RETURN(soc_mem_read(unit, PORT_TABm, MEM_BLOCK_ALL, 1113 port, &entry)); 1114 index = soc_mem_field32_get(unit, PORT_TABm, &entry, TRUST_DSCP_PTRf); 1115 1116 SOC_IF_ERROR_RETURN(_bcm_dscp_table_entry_reference(unit, index * 64, 1117 64)); 1118 } 1119 1120 /* Update PORT_COS_MAP memory profile reference counter */ 1121 profile_mem = _bcm_ap_cos_map_profile[unit]; 1122 PBMP_ALL_ITER(unit, port) { 1123 SOC_IF_ERROR_RETURN 1124 (soc_mem_read(unit, COS_MAP_SELm, MEM_BLOCK_ALL, port, &entry)); 1125 set_index = soc_mem_field32_get(unit, COS_MAP_SELm, &entry, SELECTf); 1126 SOC_IF_ERROR_RETURN 1127 (soc_profile_mem_reference(unit, profile_mem, set_index * 16, 16)); 1128 } 1129 if (SOC_INFO(unit).cpu_hg_index != -1) { 1130 SOC_IF_ERROR_RETURN(soc_mem_read(unit, COS_MAP_SELm, MEM_BLOCK_ALL, 1131 SOC_INFO(unit).cpu_hg_index, &entry)); 1132 set_index = soc_mem_field32_get(unit, COS_MAP_SELm, &entry, SELECTf); 1133 SOC_IF_ERROR_RETURN 1134 (soc_profile_mem_reference(unit, profile_mem, set_index, 1)); 1135 } 1136 1137 mem = MMU_WRED_CONFIG_X_PIPEm; 1138 for (ii = soc_mem_index_min(unit, mem); 1139 ii <= soc_mem_index_max(unit, mem); ii++) { 1140 BCM_IF_ERROR_RETURN( 1141 soc_mem_read(unit, mem, MEM_BLOCK_ALL, ii, &qentry)); 1142 1143 profile_index = soc_mem_field32_get(unit, mem, &qentry, PROFILE_INDEXf); 1144 1145 BCM_IF_ERROR_RETURN 1146 (soc_profile_mem_reference(unit, _bcm_ap_wred_profile[unit], 1147 profile_index, 1)); 1148 } 1149 1150 profile_reg = _bcm_ap_llfc_profile[unit]; 1151 PBMP_PORT_ITER(unit, port) { 1152 phy_port = si->port_l2p_mapping[port]; 1153 mmu_port = si->port_p2m_mapping[phy_port]; 1154 if (mmu_port == -1) { 1155 continue; 1156 } 1157 reg = llfc_cfgr[mmu_port/32]; 1158 BCM_IF_ERROR_RETURN(soc_reg64_get(unit, reg, 0, 0, &rval)); 1159 1160 index_map = soc_reg64_field_get(unit, reg, rval, PROFILE_INDEXf); 1161 COMPILER_64_SHR(index_map, ((mmu_port % 32) * 2)); 1162 COMPILER_64_TO_32_LO(tmp32, index_map); 1163 set_index = (tmp32 & 3); 1164 SOC_IF_ERROR_RETURN 1165 (soc_profile_reg_reference(unit, profile_reg, set_index * 16, 16)); 1166 } 1167 1168 return BCM_E_NONE; 1169 } 1170 1171 /* 1172 * Function : 1173 * bcm_ap_cosq_endpoint_sync 1174 * Purpose : 1175 * Sync endpoint info to scache 1176 * Parameters: 1177 * unit -(IN) unit number 1178 * scache_ptr-(IN/OUT) scache pointer 1179 * Returns: 1180 * BCM_E_XXX 1181 */ 1182 STATIC int 1183 bcm_ap_cosq_endpoint_sync(int unit, uint8 **scache_ptr) 1184 { 1185 uint32 endpoint_flags, entry_size; 1186 int ii; 1187 1188 /* entry 0 was reserved and is not synced. */ 1189 entry_size = sizeof(uint32)+ sizeof(bcm_vrf_t) + sizeof(bcm_ip6_t); 1190 for (ii = 1; ii < _BCM_AP_NUM_ENDPOINT(unit); ii++) { 1191 if (_BCM_AP_ENDPOINT_IS_USED(unit, ii)) { 1192 endpoint_flags = _BCM_AP_ENDPOINT(unit, ii)->flags; 1193 if (endpoint_flags & BCM_COSQ_CLASSIFIER_L2) { 1194 sal_memcpy((*scache_ptr), &endpoint_flags, sizeof(uint32)); 1195 (*scache_ptr) += sizeof(uint32); 1196 sal_memcpy((*scache_ptr), &(_BCM_AP_ENDPOINT(unit, ii)->vlan), 1197 sizeof(bcm_vlan_t)); 1198 (*scache_ptr) += sizeof(bcm_vlan_t); 1199 sal_memcpy((*scache_ptr), _BCM_AP_ENDPOINT(unit, ii)->mac, 1200 sizeof(bcm_mac_t)); 1201 (*scache_ptr) += (entry_size - sizeof(uint32) - sizeof(bcm_vlan_t)); 1202 } else if (endpoint_flags & BCM_COSQ_CLASSIFIER_L3) { 1203 sal_memcpy((*scache_ptr), &endpoint_flags, sizeof(uint32)); 1204 (*scache_ptr) += sizeof(uint32); 1205 sal_memcpy((*scache_ptr), &(_BCM_AP_ENDPOINT(unit, ii)->vrf), 1206 sizeof(bcm_vrf_t)); 1207 (*scache_ptr) += sizeof(bcm_vrf_t); 1208 if (endpoint_flags & BCM_COSQ_CLASSIFIER_IP6) { 1209 sal_memcpy((*scache_ptr), 1210 _BCM_AP_ENDPOINT(unit, ii)->ip6_addr, 1211 sizeof(bcm_ip6_t)); 1212 } else { 1213 sal_memcpy((*scache_ptr), 1214 &(_BCM_AP_ENDPOINT(unit, ii)->ip_addr), 1215 sizeof(bcm_ip_t)); 1216 } 1217 (*scache_ptr) += (entry_size - sizeof(uint32) - sizeof(bcm_vrf_t)); 1218 } else if (endpoint_flags & BCM_COSQ_CLASSIFIER_GPORT) { 1219 sal_memcpy((*scache_ptr), &endpoint_flags, sizeof(uint32)); 1220 (*scache_ptr) += sizeof(uint32); 1221 sal_memcpy((*scache_ptr), &(_BCM_AP_ENDPOINT(unit, ii)->gport), 1222 sizeof(bcm_gport_t)); 1223 (*scache_ptr) += (entry_size - sizeof(uint32)); 1224 } else { 1225 return BCM_E_INTERNAL; 1226 } 1227 } else { 1228 sal_memset((*scache_ptr), 0, entry_size); 1229 (*scache_ptr) += entry_size; 1230 } 1231 } 1232 1233 return BCM_E_NONE; 1234 } 1235 1236 1237 int 1238 bcm_ap_cosq_sync(int unit) 1239 { 1240 soc_scache_handle_t scache_handle; 1241 uint8 *scache_ptr; 1242 uint32 *u32_scache_ptr; 1243 uint16 *u16_scache_ptr; 1244 _bcm_ap_cosq_node_t *node; 1245 int node_list_sizes[3], ii, jj, cosq; 1246 _bcm_ap_cosq_node_t *nodes[3]; 1247 int xnode_id; /*, count, pipe; */ 1248 _bcm_ap_mmu_info_t *mmu_info; 1249 int alloc_size; 1250 int rv = BCM_E_NONE; 1251 int ref_count; 1252 int profile_num, count; 1253 soc_profile_mem_t *profile_mem; 1254 int dmvoq_en = 0, coe_en = 0; 1255 uint32 *psize; 1256 1257 mmu_info = _bcm_ap_mmu_info[unit]; 1258 1259 if (!mmu_info) { 1260 return BCM_E_INIT; 1261 } 1262 1263 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_COSQ, 0); 1264 BCM_IF_ERROR_RETURN 1265 (_bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 0, 1266 &scache_ptr, BCM_WB_DEFAULT_VERSION, NULL)); 1267 1268 u32_scache_ptr = (uint32*) scache_ptr; 1269 1270 nodes[0] = &mmu_info->queue_node[0]; 1271 node_list_sizes[0] = _BCM_AP_NUM_L2_UC_LEAVES; 1272 nodes[1] = &mmu_info->mc_queue_node[0]; 1273 node_list_sizes[1] = _BCM_AP_NUM_L2_MC_LEAVES; 1274 nodes[2] = &mmu_info->sched_node[0]; 1275 node_list_sizes[2] = _BCM_AP_NUM_TOTAL_SCHEDULERS; 1276 1277 for(ii = 0; ii < 3; ii++) { 1278 psize = u32_scache_ptr++; 1279 for(count = 0, jj = 0; jj < node_list_sizes[ii]; jj++) { 1280 node = nodes[ii] + jj; 1281 if (node->in_use == FALSE) { 1282 continue; 1283 } 1284 dmvoq_en = 0; 1285 coe_en = 0; 1286 count += 1; 1287 1288 if (node->parent == NULL) { 1289 xnode_id = 0x1fff; 1290 } else { 1291 xnode_id = _BCM_AP_NODE_ID(node->parent, mmu_info->sched_node); 1292 } 1293 cosq = ((node->attached_to_input == -1) ? 0x7fff : node->attached_to_input); 1294 1295 *u32_scache_ptr++ = _BCM_AP_WB_SET_NODE_W1(ii, jj, 1296 ((node->hw_cosq == -1) ? 0x7fff : node->hw_cosq)); 1297 1298 if ((node->remote_modid != -1) || (node->remote_port != -1)) { 1299 dmvoq_en = 1; 1300 } 1301 if (soc_feature(unit, soc_feature_mmu_hqos_four_level) && 1302 (node->level == SOC_APACHE_NODE_LVL_S1)) { 1303 coe_en = 1; 1304 } 1305 1306 *u32_scache_ptr++ = _BCM_AP_WB_SET_NODE_W2( 1307 (node->hw_index == -1) ? 0x7fff : node->hw_index, xnode_id, 1308 node->level, node->wrr_in_use); 1309 1310 *u32_scache_ptr++ = _BCM_AP_WB_SET_NODE_W3(node->gport); 1311 *u32_scache_ptr++ = _BCM_AP_WB_SET_NODE_W4(node->port_gport); 1312 *u32_scache_ptr++ = _BCM_AP_WB_SET_NODE_W5(node->numq, cosq, 1313 dmvoq_en, coe_en); 1314 1315 *u32_scache_ptr++ = _BCM_AP_WB_SET_NODE_W6( 1316 (node->base_size), 1317 ((node->base_index == -1 ) ? 0x7fff : 1318 node->base_index), 1319 (node->numq_expandable), (node->type), 1320 ((node->node_align_value) ? 1 : 0)); 1321 1322 if (dmvoq_en) { 1323 *u32_scache_ptr++ = _BCM_AP_WB_SET_NODE_W7( 1324 (node->remote_modid == -1) ? 0x1ff : node->remote_modid, 1325 (node->remote_port == -1) ? 0x1ff : node->remote_port); 1326 } 1327 1328 if (soc_feature(unit, 1329 soc_feature_mmu_hqos_four_level)) { 1330 if (node->level == SOC_APACHE_NODE_LVL_S1) { 1331 *u32_scache_ptr++ = _BCM_AP_WB_SET_NODE_W8(node->coe_base_index, 1332 node->coe_num_l2); 1333 } 1334 } 1335 } 1336 *psize = count; 1337 } 1338 1339 /* Sync TIME_DOMAINr field and count reference */ 1340 alloc_size = _AP_NUM_TIME_DOMAIN * sizeof(_bcm_ap_cosq_time_info_t); 1341 sal_memcpy(u32_scache_ptr, &time_domain1[unit][0], alloc_size); 1342 u32_scache_ptr += alloc_size / sizeof(uint32); 1343 soc_apache_fc_map_shadow_sync(unit, &u32_scache_ptr); 1344 1345 *u32_scache_ptr++ = mmu_info->curr_shared_limit; 1346 u16_scache_ptr = (uint16 *)u32_scache_ptr; 1347 1348 for (ii = 0; 1349 ii < (SOC_MEM_SIZE(unit, IFP_COS_MAPm) / _AP_NUM_INTERNAL_PRI); 1350 ii++) { 1351 rv = soc_profile_mem_ref_count_get(unit, 1352 _bcm_ap_ifp_cos_map_profile[unit], 1353 ii * _AP_NUM_INTERNAL_PRI, 1354 &ref_count); 1355 if (!(rv == SOC_E_NOT_FOUND || rv == SOC_E_NONE)) { 1356 return rv; 1357 } 1358 *u16_scache_ptr++ = (uint16)(ref_count & 0xffff); 1359 } 1360 1361 profile_num = SOC_MEM_SIZE(unit, SERVICE_COS_MAPm) / 1362 _AP_SCM_ENTRIES_PER_SET; 1363 profile_mem = _bcm_ap_service_cos_map_profile[unit]; 1364 for (ii = 0; ii < profile_num; ii++) { 1365 ref_count = 0; 1366 rv = soc_profile_mem_ref_count_get( 1367 unit, profile_mem, ii * _AP_SCM_ENTRIES_PER_SET, &ref_count); 1368 if (!(rv == SOC_E_NOT_FOUND || rv == SOC_E_NONE)) { 1369 return rv; 1370 } 1371 *u16_scache_ptr++ = (uint16)(ref_count & 0xffff); 1372 } 1373 1374 profile_num = SOC_MEM_SIZE(unit, SERVICE_PORT_MAPm) / 1375 _AP_SPM_ENTRIES_PER_SET; 1376 profile_mem = _bcm_ap_service_port_map_profile[unit]; 1377 for (ii = 0; ii < profile_num; ii++) { 1378 ref_count = 0; 1379 rv = soc_profile_mem_ref_count_get( 1380 unit, profile_mem, ii * _AP_SPM_ENTRIES_PER_SET, &ref_count); 1381 if (!(rv == SOC_E_NOT_FOUND || rv == SOC_E_NONE)) { 1382 return rv; 1383 } 1384 *u16_scache_ptr++ = (uint16)(ref_count & 0xffff); 1385 } 1386 1387 profile_num = SOC_MEM_SIZE(unit, VOQ_PORT_MAPm) / 1388 _AP_SPM_ENTRIES_PER_SET; 1389 profile_mem = _bcm_ap_voq_port_map_profile[unit]; 1390 for (ii = 0; ii < profile_num; ii++) { 1391 ref_count = 0; 1392 rv = soc_profile_mem_ref_count_get( 1393 unit, profile_mem, ii * _AP_VPM_ENTRIES_PER_SET, &ref_count); 1394 if (!(rv == SOC_E_NOT_FOUND || rv == SOC_E_NONE)) { 1395 return rv; 1396 } 1397 *u16_scache_ptr++ = (uint16)(ref_count & 0xffff); 1398 } 1399 u32_scache_ptr = (uint32 *)u16_scache_ptr; 1400 1401 *u32_scache_ptr++ = NUM_COS(unit); 1402 scache_ptr = (uint8*)u32_scache_ptr; 1403 1404 /* 1405 * BCM_WB_VERSION_1_1 sync endpoint info. 1406 */ 1407 if (soc_feature(unit, soc_feature_endpoint_queuing)) { 1408 scache_ptr = (uint8 *)u32_scache_ptr; 1409 BCM_IF_ERROR_RETURN( 1410 bcm_ap_cosq_endpoint_sync(unit, &scache_ptr)); 1411 1412 u16_scache_ptr = (uint16 *)scache_ptr; 1413 /* BCM_WB_VERSION_1_2 sync ENPOINT_COS_MAP memory profile */ 1414 profile_mem = _bcm_ap_endpoint_queuing_info[unit]->cos_map_profile; 1415 profile_num = (SOC_MEM_SIZE(unit, ENDPOINT_COS_MAPm) / _AP_NUM_INTERNAL_PRI); 1416 for (ii = 0; ii < profile_num; ii++) { 1417 rv = soc_profile_mem_ref_count_get(unit, profile_mem, 1418 ii * _AP_NUM_INTERNAL_PRI, &ref_count); 1419 if (!(rv == SOC_E_NOT_FOUND || rv == SOC_E_NONE)) { 1420 return rv; 1421 } 1422 *u16_scache_ptr++ = (uint16)(ref_count & 0xffff); 1423 } 1424 } 1425 return BCM_E_NONE; 1426 } 1427 1428 #endif /* BCM_WARM_BOOT_SUPPORT */ 1429 1430 #ifndef BCM_SW_STATE_DUMP_DISABLE 1431 /* 1432 * Function: 1433 * bcm_ap_cosq_sw_dump 1434 * Purpose: 1435 * Displays COS Queue information maintained by software. 1436 * Parameters: 1437 * unit - Device unit number 1438 * Returns: 1439 * None 1440 */ 1441 void 1442 bcm_ap_cosq_sw_dump(int unit) 1443 { 1444 1445 return; 1446 } 1447 #endif /* BCM_SW_STATE_DUMP_DISABLE */ 1448 1449 /* 1450 * Function: 1451 * _bcm_ap_cosq_localport_resolve 1452 * Purpose: 1453 * Resolve GRPOT if it is a local port 1454 * Parameters: 1455 * unit - (IN) unit number 1456 * gport - (IN) GPORT identifier 1457 * local_port - (OUT) local port number 1458 * Returns: 1459 * BCM_E_XXX 1460 */ 1461 int 1462 _bcm_ap_cosq_localport_resolve(int unit, bcm_gport_t gport, 1463 bcm_port_t *local_port) 1464 { 1465 bcm_module_t module; 1466 bcm_port_t port; 1467 bcm_trunk_t trunk; 1468 int id, result; 1469 1470 if (!BCM_GPORT_IS_SET(gport)) { 1471 if (!SOC_PORT_VALID(unit, gport)) { 1472 return BCM_E_PORT; 1473 } 1474 *local_port = gport; 1475 return BCM_E_NONE; 1476 } 1477 1478 BCM_IF_ERROR_RETURN 1479 (_bcm_esw_gport_resolve(unit, gport, &module, &port, &trunk, &id)); 1480 1481 BCM_IF_ERROR_RETURN(_bcm_esw_modid_is_local(unit, module, &result)); 1482 if (result == FALSE) { 1483 return BCM_E_PARAM; 1484 } 1485 1486 *local_port = port; 1487 1488 return BCM_E_NONE; 1489 } 1490 1491 STATIC int 1492 _bcm_ap_cosq_port_has_ets(int unit, bcm_port_t port) 1493 { 1494 /* In Apache it is always ETS mode */ 1495 return TRUE; 1496 } 1497 1498 /* 1499 * Function: 1500 * _bcm_ap_node_index_get 1501 * Purpose: 1502 * Allocate free index from the given list 1503 * Parameters: 1504 * list - (IN) bit list 1505 * start - (IN) start index 1506 * end - (IN) end index 1507 * count - (IN) size of queue set 1508 * align - (IN) adjusting the bits 1509 * id - (OUT) start index 1510 * Returns: 1511 * BCM_E_XXX 1512 */ 1513 STATIC int 1514 _bcm_ap_node_index_get(SHR_BITDCL *list, int start, int end, 1515 int count, int align, int *id) 1516 { 1517 int i, j, range_empty; 1518 1519 *id = -1; 1520 1521 if ((align <= 0) || (count == 0)) { 1522 return BCM_E_PARAM; 1523 } 1524 1525 if (start & (align - 1)) { 1526 start = (start + align - 1) & ~(align - 1); 1527 } 1528 1529 end = end - align + 1; 1530 1531 for (i = start; i < end; i += align) { 1532 range_empty = 1; 1533 /* Make sure the j doesn not cross the end */ 1534 for (j = i; ((j < (i + count)) && ( j < end)); j++) { 1535 if (SHR_BITGET(list, j) != 0) { 1536 range_empty = 0; 1537 break; 1538 } 1539 } 1540 1541 if (range_empty) { 1542 *id = i; 1543 return BCM_E_NONE; 1544 } 1545 } 1546 return BCM_E_RESOURCE; 1547 } 1548 1549 /* 1550 * Function: 1551 * _bcm_ap_node_index_set 1552 * Purpose: 1553 * Mark indices as allocated 1554 * Parameters: 1555 * list - (IN) bit list 1556 * start - (IN) start index 1557 * range - (IN) range bits 1558 * Returns: 1559 * BCM_E_XXX 1560 */ 1561 STATIC int 1562 _bcm_ap_node_index_set(_bcm_ap_cosq_list_t *list, int start, int range) 1563 { 1564 if ( range == 0) 1565 { 1566 return BCM_E_NONE; 1567 } 1568 if ((start < 0) || 1569 (range < 0) || 1570 ((start + range) > list->count)) { 1571 return BCM_E_RESOURCE; 1572 } 1573 1574 SHR_BITSET_RANGE(list->bits, start, range); 1575 1576 return BCM_E_NONE; 1577 } 1578 1579 /* 1580 * Function: 1581 * _bcm_ap_node_index_clear 1582 * Purpose: 1583 * Mark indices as free 1584 * Parameters: 1585 * list - (IN) bit list 1586 * start - (IN) start index 1587 * range - (IN) range bits 1588 * Returns: 1589 * BCM_E_XXX 1590 */ 1591 STATIC int 1592 _bcm_ap_node_index_clear(_bcm_ap_cosq_list_t *list, int start, int range) 1593 { 1594 if ( range == 0) 1595 { 1596 return BCM_E_NONE; 1597 } 1598 if ((start < 0) || 1599 (range < 0) || 1600 ((start + range) > list->count)) { 1601 return BCM_E_RESOURCE; 1602 } 1603 1604 SHR_BITCLR_RANGE(list->bits, start, range); 1605 1606 return BCM_E_NONE; 1607 } 1608 STATIC int 1609 _bcm_ap_cosq_max_nodes_get(int unit, soc_apache_node_lvl_e level, 1610 int *id) 1611 { 1612 _bcm_ap_mmu_info_t *mmu_info; 1613 if ((mmu_info = _bcm_ap_mmu_info[unit]) == NULL) { 1614 return BCM_E_INIT; 1615 } 1616 if (id == NULL) { 1617 return BCM_E_PARAM; 1618 } 1619 if (level == SOC_APACHE_NODE_LVL_S1) { 1620 *id = _BCM_AP_NUM_S1_SCHEDULER_PER_PIPE; 1621 } else if (level == SOC_APACHE_NODE_LVL_L0) { 1622 *id = _BCM_AP_NUM_L0_SCHEDULER_PER_PIPE; 1623 } else if (level == SOC_APACHE_NODE_LVL_L1) { 1624 *id = _BCM_AP_NUM_L1_SCHEDULER_PER_PIPE; 1625 } else if (level == SOC_APACHE_NODE_LVL_L2) { 1626 *id = mmu_info->num_l2_queues + _BCM_AP_NUM_L2_MC_LEAVES; 1627 } 1628 return BCM_E_NONE; 1629 1630 } 1631 /* 1632 * Function: 1633 * _bcm_ap_cosq_alloc_clear 1634 * Purpose: 1635 * Allocate cosq memory and clear 1636 * Parameters: 1637 * size - (IN) size of memory required 1638 * description- (IN) description about the structure 1639 * Returns: 1640 * BCM_E_XXX 1641 */ 1642 STATIC void * 1643 _bcm_ap_cosq_alloc_clear(void *cp, unsigned int size, char *description) 1644 { 1645 void *block_p; 1646 1647 block_p = (cp) ? cp : sal_alloc(size, description); 1648 1649 if (block_p != NULL) { 1650 sal_memset(block_p, 0, size); 1651 } 1652 1653 return block_p; 1654 } 1655 1656 /* 1657 * Function: 1658 * _bcm_ap_cosq_free_memory 1659 * Purpose: 1660 * Free memory allocated for mmu info members 1661 * Parameters: 1662 * mmu_info - (IN) MMU info pointer 1663 * Returns: 1664 * BCM_E_XXX 1665 */ 1666 STATIC void 1667 _bcm_ap_cosq_free_memory(_bcm_ap_mmu_info_t *mmu_info_p) 1668 { 1669 int i; 1670 _bcm_ap_pipe_resources_t *res; 1671 1672 1673 if (mmu_info_p == NULL) { 1674 return; 1675 } 1676 1677 for (i = _AP_XPIPE; i < _AP_YPIPE; i++) { 1678 res = _BCM_AP_PRESOURCES(mmu_info_p, i); 1679 if (res->l2_queue_list.bits != NULL) { 1680 sal_free(res->l2_queue_list.bits); 1681 res->l2_queue_list.bits = NULL; 1682 } 1683 if (res->l1_sched_list.bits != NULL) { 1684 sal_free(res->l1_sched_list.bits); 1685 res->l1_sched_list.bits = NULL; 1686 } 1687 if (res->l0_sched_list.bits != NULL) { 1688 sal_free(res->l0_sched_list.bits); 1689 res->l0_sched_list.bits = NULL; 1690 } 1691 if (res->cpu_l0_sched_list.bits != NULL) { 1692 sal_free(res->cpu_l0_sched_list.bits); 1693 res->cpu_l0_sched_list.bits = NULL; 1694 } 1695 if (res->hsp_l2_queue_list.bits != NULL) { 1696 sal_free(res->hsp_l2_queue_list.bits); 1697 res->hsp_l2_queue_list.bits = NULL; 1698 } 1699 if (res->hsp_l1_sched_list.bits != NULL) { 1700 sal_free(res->hsp_l1_sched_list.bits); 1701 res->hsp_l1_sched_list.bits = NULL; 1702 } 1703 if (res->hsp_l0_sched_list.bits != NULL) { 1704 sal_free(res->hsp_l0_sched_list.bits); 1705 res->hsp_l0_sched_list.bits = NULL; 1706 } 1707 if (res->s1_sched_list.bits != NULL) { 1708 sal_free(res->s1_sched_list.bits); 1709 res->s1_sched_list.bits = NULL; 1710 } 1711 } 1712 1713 for (i = 0; i < _BCM_AP_NUM_TOTAL_SCHEDULERS; i++) { 1714 if (((&mmu_info_p->sched_node[i])->cosq_map) != NULL) { 1715 sal_free((&mmu_info_p->sched_node[i])->cosq_map); 1716 (&mmu_info_p->sched_node[i])->cosq_map = NULL; 1717 } 1718 } 1719 1720 for (i = 0; i < _BCM_AP_NUM_L2_UC_LEAVES; i++) { 1721 if (((&mmu_info_p->queue_node[i])->cosq_map) != NULL) { 1722 sal_free((&mmu_info_p->queue_node[i])->cosq_map); 1723 (&mmu_info_p->queue_node[i])->cosq_map = NULL; 1724 } 1725 } 1726 1727 for (i = 0; i < _BCM_AP_NUM_L2_MC_LEAVES; i++) { 1728 if (((&mmu_info_p->mc_queue_node[i])->cosq_map) != NULL) { 1729 sal_free((&mmu_info_p->mc_queue_node[i])->cosq_map); 1730 (&mmu_info_p->mc_queue_node[i])->cosq_map = NULL; 1731 } 1732 } 1733 } 1734 1735 /* 1736 * Function: 1737 * _bcm_ap_cosq_node_get 1738 * Purpose: 1739 * Get internal information of queue group or scheduler type GPORT 1740 * Parameters: 1741 * unit - (IN) unit number 1742 * gport - (IN) queue group/scheduler GPORT identifier 1743 * modid - (OUT) module identifier 1744 * port - (OUT) port number 1745 * id - (OUT) queue group or scheduler identifier 1746 * node - (OUT) node structure for the specified GPORT 1747 * Returns: 1748 * BCM_E_XXX 1749 */ 1750 STATIC int 1751 _bcm_ap_cosq_node_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 1752 bcm_module_t *modid, bcm_port_t *port, 1753 int *id, _bcm_ap_cosq_node_t **node) 1754 { 1755 _bcm_ap_mmu_info_t *mmu_info; 1756 _bcm_ap_cosq_node_t *node_base = NULL; 1757 bcm_module_t modid_out = 0; 1758 bcm_port_t port_out = 0; 1759 uint32 encap_id = -1; 1760 int index; 1761 1762 if ((mmu_info = _bcm_ap_mmu_info[unit]) == NULL) { 1763 return BCM_E_INIT; 1764 } 1765 1766 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 1767 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid_out)); 1768 port_out = BCM_GPORT_UCAST_QUEUE_GROUP_SYSPORTID_GET(gport); 1769 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 1770 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid_out)); 1771 port_out = BCM_GPORT_MCAST_QUEUE_GROUP_SYSPORTID_GET(gport); 1772 } else if (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport)) { 1773 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid_out)); 1774 port_out = (gport >> 16) & 0xff; 1775 } else if (BCM_GPORT_IS_SCHEDULER(gport)) { 1776 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid_out)); 1777 port_out = BCM_GPORT_SCHEDULER_GET(gport) & 0xff; 1778 } else if (BCM_GPORT_IS_LOCAL(gport)) { 1779 encap_id = BCM_GPORT_LOCAL_GET(gport); 1780 port_out = encap_id; 1781 } else if (BCM_GPORT_IS_MODPORT(gport)) { 1782 modid_out = SOC_GPORT_MODPORT_MODID_GET(gport); 1783 port_out = SOC_GPORT_MODPORT_PORT_GET(gport); 1784 encap_id = port_out; 1785 } else { 1786 return BCM_E_PORT; 1787 } 1788 1789 if (!SOC_PORT_VALID(unit, port_out)) { 1790 return BCM_E_PORT; 1791 } 1792 1793 if (port != NULL) { 1794 *port = port_out; 1795 } 1796 #if 0 1797 if (!_bcm_ap_cosq_port_has_ets(unit, port_out)) { 1798 return BCM_E_NOT_FOUND; 1799 } 1800 #endif 1801 1802 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 1803 encap_id = BCM_GPORT_UCAST_QUEUE_GROUP_QID_GET(gport); 1804 index = encap_id; 1805 node_base = mmu_info->queue_node; 1806 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 1807 encap_id = BCM_GPORT_MCAST_QUEUE_GROUP_QID_GET(gport); 1808 index = encap_id; 1809 node_base = mmu_info->mc_queue_node; 1810 } else if (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport)) { 1811 encap_id = BCM_GPORT_UCAST_SUBSCRIBER_QUEUE_GROUP_QID_GET(gport); 1812 index = encap_id; 1813 node_base = mmu_info->queue_node; 1814 } else if (BCM_GPORT_IS_SCHEDULER(gport)) { 1815 encap_id = (BCM_GPORT_SCHEDULER_GET(gport) >> 8) & 0x3fff; 1816 index = encap_id; 1817 node_base = mmu_info->sched_node; 1818 } else { 1819 index = encap_id; 1820 node_base = mmu_info->sched_node; 1821 } 1822 1823 if (index < 0) { 1824 return BCM_E_NOT_FOUND; 1825 } 1826 1827 if (node_base[index].numq == 0) { 1828 return BCM_E_NOT_FOUND; 1829 } 1830 1831 if (modid != NULL) { 1832 *modid = modid_out; 1833 } 1834 if (id != NULL) { 1835 *id = encap_id; 1836 } 1837 if (node != NULL) { 1838 *node = &node_base[index]; 1839 if (*node) { 1840 _bcm_ap_cosq_node_t *tmp_node; 1841 tmp_node = *node; 1842 if (tmp_node->type == _BCM_AP_NODE_SERVICE_UCAST) { 1843 *node = &node_base[index + cosq]; 1844 if (id != NULL) { 1845 *id = tmp_node->hw_index; 1846 } 1847 } 1848 } 1849 1850 } 1851 1852 return BCM_E_NONE; 1853 } 1854 1855 int 1856 _bcm_ap_cosq_port_resolve(int unit, bcm_gport_t gport, bcm_module_t *modid, 1857 bcm_port_t *port, bcm_trunk_t *trunk_id, int *id, 1858 int *qnum) 1859 { 1860 _bcm_ap_cosq_node_t *node; 1861 1862 BCM_IF_ERROR_RETURN 1863 (_bcm_ap_cosq_node_get(unit, gport, 0, modid, port, id, &node)); 1864 *trunk_id = -1; 1865 1866 if (qnum) { 1867 if (node->hw_index == -1) { 1868 return BCM_E_PARAM; 1869 } 1870 *qnum = node->hw_index; 1871 } 1872 1873 return BCM_E_NONE; 1874 } 1875 1876 /* 1877 * Function: 1878 * _bcm_ap_cosq_gport_traverse 1879 * Purpose: 1880 * Walks through the valid COSQ GPORTs and calls 1881 * the user supplied callback function for each entry. 1882 * Parameters: 1883 * unit - (IN) unit number 1884 * gport - (IN) 1885 * cb - (IN) Callback function. 1886 * user_data - (IN) User data to be passed to callback function 1887 * Returns: 1888 * BCM_E_NONE - Success. 1889 * BCM_E_XXX 1890 */ 1891 int 1892 _bcm_ap_cosq_gport_traverse(int unit, bcm_gport_t gport, 1893 bcm_cosq_gport_traverse_cb cb, 1894 void *user_data) 1895 { 1896 _bcm_ap_cosq_node_t *node; 1897 uint32 flags = BCM_COSQ_GPORT_SCHEDULER; 1898 bcm_port_t port, port_out; 1899 bcm_module_t modid, modid_out; 1900 bcm_gport_t gport_out; 1901 int rv = BCM_E_NONE; 1902 1903 BCM_IF_ERROR_RETURN 1904 (_bcm_ap_cosq_node_get(unit, gport, 0, &modid, &port, NULL, &node)); 1905 1906 if (node != NULL) { 1907 if (!soc_feature(unit, soc_feature_mmu_hqos_four_level) && 1908 node->level == SOC_APACHE_NODE_LVL_ROOT) 1909 { 1910 node = node->child; 1911 if (!node) 1912 { 1913 return BCM_E_NONE; 1914 } 1915 } 1916 if (node->level == SOC_APACHE_NODE_LVL_L2) { 1917 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(node->gport)) { 1918 flags = BCM_COSQ_GPORT_UCAST_QUEUE_GROUP; 1919 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(node->gport)) { 1920 flags = BCM_COSQ_GPORT_MCAST_QUEUE_GROUP; 1921 } 1922 } else { 1923 flags = BCM_COSQ_GPORT_SCHEDULER; 1924 } 1925 BCM_IF_ERROR_RETURN 1926 (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, modid, port, 1927 &modid_out, &port_out)); 1928 BCM_GPORT_MODPORT_SET(gport_out, modid_out, port_out); 1929 1930 rv = cb(unit, gport_out, node->numq, flags, 1931 node->gport, user_data); 1932 if (BCM_FAILURE(rv)) { 1933 #ifdef BCM_CB_ABORT_ON_ERR 1934 if (SOC_CB_ABORT_ON_ERR(unit)) { 1935 return rv; 1936 } 1937 #endif 1938 } 1939 } else { 1940 return BCM_E_NONE; 1941 } 1942 1943 if (node->sibling != NULL) { 1944 _bcm_ap_cosq_gport_traverse(unit, node->sibling->gport, cb, user_data); 1945 } 1946 1947 if (node->child != NULL) { 1948 _bcm_ap_cosq_gport_traverse(unit, node->child->gport, cb, user_data); 1949 } 1950 1951 return BCM_E_NONE; 1952 } 1953 1954 STATIC int 1955 _bcm_ap_cosq_child_node_at_input(_bcm_ap_cosq_node_t *node, int cosq, 1956 _bcm_ap_cosq_node_t **child_node) 1957 { 1958 _bcm_ap_cosq_node_t *cur_node; 1959 1960 for (cur_node = node->child; cur_node; cur_node = cur_node->sibling) { 1961 if (cur_node->attached_to_input == cosq) { 1962 break; 1963 } 1964 } 1965 if (!cur_node) { 1966 return BCM_E_NOT_FOUND; 1967 } 1968 1969 *child_node = cur_node; 1970 1971 return BCM_E_NONE; 1972 } 1973 1974 STATIC int 1975 _bcm_ap_cosq_l2_gport(int unit, int port, int cosq, 1976 _bcm_ap_node_type_e type, bcm_gport_t *gport, 1977 _bcm_ap_cosq_node_t **p_node) 1978 { 1979 int i, max; 1980 _bcm_ap_cosq_node_t *node, *fnode; 1981 _bcm_ap_mmu_info_t *mmu_info; 1982 _bcm_ap_cosq_port_info_t *port_info; 1983 _bcm_ap_pipe_resources_t *res; 1984 1985 mmu_info = _bcm_ap_mmu_info[unit]; 1986 port_info = &mmu_info->port_info[port]; 1987 res = port_info->resources; 1988 1989 max = 0; 1990 if ((type == _BCM_AP_NODE_UCAST) || (type == _BCM_AP_NODE_VOQ) || 1991 (type == _BCM_AP_NODE_VLAN_UCAST) || (type == _BCM_AP_NODE_VM_UCAST) || 1992 (type == _BCM_AP_NODE_SERVICE_UCAST)) { 1993 max = _BCM_AP_NUM_L2_UC_LEAVES; 1994 fnode = &res->p_queue_node[0]; 1995 } else if (type == _BCM_AP_NODE_MCAST) { 1996 max = _BCM_AP_NUM_L2_MC_LEAVES; 1997 fnode = &res->p_mc_queue_node[0]; 1998 } else { 1999 return BCM_E_PARAM; 2000 } 2001 2002 for (i = 0; i < max; i++) { 2003 node = fnode + i; 2004 if (node->in_use && (node->local_port == port) && 2005 (node->type == type) && (node->hw_cosq == cosq)) { 2006 if (gport) { 2007 *gport = node->gport; 2008 } 2009 if (p_node) { 2010 *p_node = node; 2011 } 2012 return BCM_E_NONE; 2013 } 2014 } 2015 return BCM_E_NOT_FOUND; 2016 } 2017 2018 /* 2019 * Function: 2020 * _bcm_ap_cosq_index_resolve 2021 * Purpose: 2022 * Find hardware index for the given port/cosq 2023 * Parameters: 2024 * unit - (IN) unit number 2025 * port - (IN) port number or GPORT identifier 2026 * cosq - (IN) COS queue number 2027 * style - (IN) index style (_BCM_KA_COSQ_INDEX_STYLE_XXX) 2028 * local_port - (OUT) local port number 2029 * index - (OUT) result index 2030 * count - (OUT) number of index 2031 * Returns: 2032 * BCM_E_XXX 2033 */ 2034 int 2035 _bcm_ap_cosq_index_resolve(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 2036 _bcm_ap_cosq_index_style_t style, 2037 bcm_port_t *local_port, int *index, int *count) 2038 { 2039 _bcm_ap_cosq_node_t *node, *cur_node , *s1_node; 2040 bcm_port_t resolved_port; 2041 int resolved_index = -1; 2042 int id, startq, numq; 2043 soc_info_t *si; 2044 int phy_port, mmu_port; 2045 uint32 entry0[SOC_MAX_MEM_WORDS]; 2046 soc_mem_t mem; 2047 _bcm_ap_mmu_info_t *mmu_info; 2048 si = &SOC_INFO(unit); 2049 2050 mmu_info = _bcm_ap_mmu_info[unit]; 2051 if (cosq < -1) { 2052 return BCM_E_PARAM; 2053 } else if (cosq == -1) { 2054 startq = 0; 2055 numq = NUM_COS(unit); 2056 } else { 2057 startq = cosq; 2058 numq = 1; 2059 } 2060 2061 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 2062 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) || 2063 BCM_GPORT_IS_SCHEDULER(port)) { 2064 BCM_IF_ERROR_RETURN 2065 (_bcm_ap_cosq_node_get(unit, port, cosq, NULL, &resolved_port, &id, 2066 &node)); 2067 if (node->attached_to_input < 0) { /* Not resolved yet */ 2068 return BCM_E_NOT_FOUND; 2069 } 2070 numq = (node->numq != -1) ? node->numq : 64; 2071 2072 } else if(_BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port)){ 2073 BCM_IF_ERROR_RETURN( 2074 _bcmi_coe_subport_physical_port_get(unit, port, &resolved_port)); 2075 BCM_IF_ERROR_RETURN 2076 (_bcm_ap_get_s1_node(unit, port, &s1_node)); 2077 node = &mmu_info->queue_node[s1_node->coe_base_index + startq ]; 2078 if (node->attached_to_input < 0) { /* Not resolved yet */ 2079 return BCM_E_NOT_FOUND; 2080 } 2081 numq = _AP_NUM_COS(unit); 2082 } else { 2083 /* optionally validate port */ 2084 BCM_IF_ERROR_RETURN 2085 (_bcm_ap_cosq_localport_resolve(unit, port, &resolved_port)); 2086 if (resolved_port < 0) { 2087 return BCM_E_PORT; 2088 } 2089 node = NULL; 2090 numq = (IS_CPU_PORT(unit, resolved_port)) ? NUM_CPU_COSQ(unit) : NUM_COS(unit); 2091 } 2092 2093 if (startq >= numq) { 2094 return BCM_E_PARAM; 2095 } 2096 2097 phy_port = si->port_l2p_mapping[resolved_port]; 2098 mmu_port = si->port_p2m_mapping[phy_port]; 2099 2100 switch (style) { 2101 case _BCM_AP_COSQ_INDEX_STYLE_BUCKET: 2102 if (node != NULL) { 2103 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) { 2104 resolved_index = node->hw_index; 2105 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 2106 resolved_index = node->hw_index; 2107 } else if(_BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port)){ 2108 resolved_index = node->hw_index; 2109 } else if (BCM_GPORT_IS_SCHEDULER(port) || BCM_GPORT_IS_MODPORT(port)) { 2110 /* resolve the child attached to input cosq */ 2111 BCM_IF_ERROR_RETURN( 2112 _bcm_ap_cosq_child_node_at_input(node, startq, &cur_node)); 2113 resolved_index = cur_node->hw_index; 2114 } else { 2115 return BCM_E_PARAM; 2116 } 2117 } else { /* node == NULL */ 2118 if (IS_CPU_PORT(unit, resolved_port)) { 2119 resolved_index = SOC_INFO(unit).port_cosq_base[resolved_port] + 2120 startq; 2121 resolved_index = soc_apache_l2_hw_index(unit, resolved_index, 0); 2122 } else { 2123 resolved_index = soc_apache_l2_hw_index(unit, 2124 si->port_uc_cosq_base[resolved_port] + startq, 1); 2125 if (!IS_AP_HSP_PORT(unit, resolved_port)) { 2126 mem = _SOC_APACHE_NODE_PARENT_MEM(unit, port, SOC_APACHE_NODE_LVL_L2); 2127 SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, resolved_index, &entry0)); 2128 resolved_index = soc_mem_field32_get(unit, mem, entry0, C_PARENTf); 2129 } 2130 } 2131 } 2132 break; 2133 2134 case _BCM_AP_COSQ_INDEX_STYLE_QCN: 2135 if (node != NULL) { 2136 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) { 2137 resolved_index = node->hw_index; 2138 } else { 2139 return BCM_E_PARAM; 2140 } 2141 } else { /* node == NULL */ 2142 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_port_has_ets(unit, resolved_port)); 2143 if (IS_CPU_PORT(unit, resolved_port)) { 2144 return BCM_E_PARAM; 2145 } else { 2146 resolved_index = soc_apache_l2_hw_index(unit, 2147 si->port_uc_cosq_base[resolved_port] + startq, 1); 2148 } 2149 } 2150 break; 2151 2152 case _BCM_AP_COSQ_INDEX_STYLE_WRED: 2153 if (node != NULL) { 2154 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) { 2155 resolved_index = node->hw_index + startq; 2156 } else if (BCM_GPORT_IS_SCHEDULER(port)) { 2157 BCM_IF_ERROR_RETURN( 2158 _bcm_ap_cosq_child_node_at_input(node, startq, &cur_node)); 2159 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(cur_node->gport)) { 2160 resolved_index = cur_node->hw_index; 2161 } else { 2162 return BCM_E_PARAM; 2163 } 2164 } else if(_BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port)){ 2165 resolved_index = node->hw_index ; 2166 } else if (BCM_GPORT_IS_MODPORT(port)) { 2167 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_l2_gport(unit, node->local_port, 2168 startq, _BCM_AP_NODE_UCAST, NULL, &cur_node)); 2169 resolved_index = cur_node->hw_index ; 2170 } else { 2171 return BCM_E_PARAM; 2172 } 2173 } else { /* node == NULL */ 2174 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_port_has_ets(unit, resolved_port)); 2175 resolved_index = soc_apache_l2_hw_index(unit, 2176 si->port_uc_cosq_base[resolved_port] + startq, 1); 2177 numq = 1; 2178 } 2179 break; 2180 2181 case _BCM_AP_COSQ_INDEX_STYLE_WRED_PORT: 2182 resolved_index = _BCM_PORT_SERVICE_POOL + (mmu_port * 4); 2183 numq = 4; 2184 break; 2185 2186 case _BCM_AP_COSQ_INDEX_STYLE_WRED_POOL: 2187 if ((node != NULL) && (!BCM_GPORT_IS_MODPORT(port))) { 2188 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) { 2189 /* regular unicast queue */ 2190 resolved_index = soc_apache_l2_hw_index(unit, node->hw_index + startq, 1); 2191 } else { 2192 return BCM_E_PARAM; 2193 } 2194 } else { /* node == NULL */ 2195 numq = si->port_num_uc_cosq[resolved_port]; 2196 if (startq >= numq) { 2197 return BCM_E_PARAM; 2198 } 2199 resolved_index = soc_td2_l2_hw_index(unit, 2200 si->port_uc_cosq_base[resolved_port] + startq, 1); 2201 } 2202 mem = MMU_THDU_XPIPE_Q_TO_QGRP_MAPm; 2203 SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, resolved_index, 2204 entry0)); 2205 2206 resolved_index = soc_mem_field32_get(unit, mem, entry0, Q_SPIDf); 2207 2208 break; 2209 2210 case _BCM_AP_COSQ_INDEX_STYLE_SCHEDULER: 2211 if (node != NULL) { 2212 if (!BCM_GPORT_IS_SCHEDULER(port)) { 2213 return BCM_E_PARAM; 2214 } 2215 BCM_IF_ERROR_RETURN( 2216 _bcm_ap_cosq_child_node_at_input(node, startq, &cur_node)); 2217 resolved_index = cur_node->hw_index; 2218 } else { /* node == NULL */ 2219 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_port_has_ets(unit, resolved_port)); 2220 if (IS_CPU_PORT(unit, resolved_port)) { 2221 resolved_index = soc_apache_l2_hw_index(unit, 2222 si->port_cosq_base[resolved_port] + startq, 0); 2223 } else { 2224 resolved_index = soc_apache_l2_hw_index(unit, 2225 si->port_uc_cosq_base[resolved_port] + startq, 1); 2226 } 2227 } 2228 break; 2229 2230 case _BCM_AP_COSQ_INDEX_STYLE_COS: 2231 if (node) { 2232 if ((BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) || 2233 (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port))) { 2234 resolved_index = node->hw_cosq; 2235 } else if (BCM_GPORT_IS_SCHEDULER(port)) { 2236 BCM_IF_ERROR_RETURN( 2237 _bcm_ap_cosq_child_node_at_input(node, startq, &cur_node)); 2238 if (BCM_GPORT_IS_SCHEDULER(cur_node->gport)) { 2239 return BCM_E_PARAM; 2240 } 2241 resolved_index = cur_node->hw_cosq; 2242 } else if(_BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port)){ 2243 resolved_index = node->hw_cosq ; 2244 } 2245 } else { 2246 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_port_has_ets(unit, resolved_port)); 2247 resolved_index = startq; 2248 } 2249 break; 2250 2251 case _BCM_AP_COSQ_INDEX_STYLE_UCAST_QUEUE: 2252 case _BCM_AP_COSQ_INDEX_STYLE_UCAST_QUEUE_GROUP: 2253 if (IS_CPU_PORT(unit, resolved_port) || 2254 IS_LB_PORT(unit, resolved_port)) { 2255 return BCM_E_PARAM; 2256 } 2257 if (node) { 2258 resolved_index = node->hw_index + startq; 2259 numq = 1; 2260 } else { 2261 /* Not support -1 for queue group index resolving, as group may not consecutive */ 2262 if ((cosq == -1) && 2263 (style == _BCM_AP_COSQ_INDEX_STYLE_UCAST_QUEUE_GROUP)) { 2264 return BCM_E_PARAM; 2265 } 2266 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_port_has_ets(unit, resolved_port)); 2267 numq = 1; 2268 resolved_index = soc_apache_l2_hw_index(unit, 2269 si->port_uc_cosq_base[resolved_port] + startq, 1); 2270 } 2271 if (style == _BCM_AP_COSQ_INDEX_STYLE_UCAST_QUEUE_GROUP) { 2272 mem = MMU_THDU_XPIPE_Q_TO_QGRP_MAPm; 2273 SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, 2274 resolved_index, entry0)); 2275 if (soc_mem_field32_get(unit, mem, entry0, QGROUP_VALIDf)) { 2276 resolved_index = soc_mem_field32_get(unit, mem, entry0, QGROUPf); 2277 } else { 2278 return BCM_E_NOT_FOUND; 2279 } 2280 } 2281 break; 2282 2283 case _BCM_AP_COSQ_INDEX_STYLE_MCAST_QUEUE: 2284 if (node) { 2285 resolved_index = node->hw_index + startq; 2286 numq = 1; 2287 } else { 2288 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_port_has_ets(unit, resolved_port)); 2289 numq = 1; 2290 resolved_index = soc_apache_l2_hw_index(unit, 2291 si->port_cosq_base[resolved_port] + startq, 0); 2292 } 2293 break; 2294 2295 case _BCM_AP_COSQ_INDEX_STYLE_EGR_POOL: 2296 if ((node != NULL) && (!BCM_GPORT_IS_MODPORT(port))) { 2297 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) { 2298 /* regular unicast queue */ 2299 resolved_index = soc_apache_l2_hw_index(unit, node->hw_index + startq, 1); 2300 mem = MMU_THDU_XPIPE_Q_TO_QGRP_MAPm; 2301 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 2302 resolved_index = soc_apache_l2_hw_index(unit, 2303 si->port_cosq_base[resolved_port] + startq, 0) - 2304 _BCM_AP_NUM_L2_UC_LEAVES; 2305 mem = MMU_THDM_MCQE_QUEUE_CONFIG_0m; 2306 } else { /* scheduler */ 2307 return BCM_E_PARAM; 2308 } 2309 } else { /* node == NULL */ 2310 numq = si->port_num_cosq[resolved_port]; 2311 if (startq >= numq) { 2312 return BCM_E_PARAM; 2313 } 2314 resolved_index = soc_apache_l2_hw_index(unit, 2315 si->port_cosq_base[resolved_port] + startq, 0) - 2316 _BCM_AP_NUM_L2_UC_LEAVES ; 2317 mem = MMU_THDM_MCQE_QUEUE_CONFIG_0m; 2318 } 2319 2320 SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, resolved_index, 2321 entry0)); 2322 2323 resolved_index = soc_mem_field32_get(unit, mem, entry0, Q_SPIDf); 2324 2325 break; 2326 case _BCM_AP_COSQ_INDEX_STYLE_UC_EGR_POOL: 2327 if (IS_CPU_PORT(unit, resolved_port) || 2328 IS_LB_PORT(unit, resolved_port)) { 2329 return BCM_E_PARAM; 2330 } 2331 2332 numq = si->port_num_uc_cosq[resolved_port]; 2333 if (startq >= numq) { 2334 return BCM_E_PARAM; 2335 } 2336 2337 resolved_index = soc_apache_l2_hw_index(unit, 2338 si->port_uc_cosq_base[resolved_port] + startq, 1); 2339 mem = MMU_THDU_XPIPE_Q_TO_QGRP_MAPm; 2340 2341 SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, resolved_index, 2342 entry0)); 2343 2344 resolved_index = soc_mem_field32_get(unit, mem, entry0, Q_SPIDf); 2345 break; 2346 2347 case _BCM_AP_COSQ_INDEX_STYLE_EGR_PERQ_UCAST: 2348 if (node) { 2349 resolved_index = node->hw_index + startq; 2350 resolved_index -= soc_apache_l2_hw_index(unit, 2351 si->port_uc_cosq_base[resolved_port], 1); 2352 numq = 1; 2353 } else { 2354 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_port_has_ets(unit, resolved_port)); 2355 numq = 1; 2356 resolved_index = startq; 2357 } 2358 break; 2359 2360 case _BCM_AP_COSQ_INDEX_STYLE_EGR_PERQ_MCAST: 2361 if (node) { 2362 resolved_index = node->hw_index + startq; 2363 resolved_index -= soc_apache_l2_hw_index(unit, 2364 si->port_cosq_base[resolved_port], 0); 2365 numq = 1; 2366 } else { 2367 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_port_has_ets(unit, resolved_port)); 2368 numq = 1; 2369 resolved_index = startq; 2370 } 2371 break; 2372 2373 default: 2374 return BCM_E_INTERNAL; 2375 } 2376 2377 if (local_port != NULL) { 2378 *local_port = resolved_port; 2379 } 2380 if (index != NULL) { 2381 *index = resolved_index; 2382 } 2383 if (count != NULL) { 2384 *count = (cosq == -1) ? numq : 1; 2385 } 2386 2387 return BCM_E_NONE; 2388 } 2389 2390 STATIC int _bcm_ap_cosq_min_child_index(_bcm_ap_cosq_node_t *child, int lvl, int uc) 2391 { 2392 int min_index = -1; 2393 2394 if ((lvl == SOC_APACHE_NODE_LVL_L2) && (uc)) { 2395 while (child) { 2396 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(child->gport)) { 2397 if (min_index == -1) { 2398 min_index = child->hw_index; 2399 } 2400 2401 if (child->hw_index < min_index) { 2402 min_index = child->hw_index; 2403 } 2404 } 2405 child = child->sibling; 2406 } 2407 } else if ((lvl == SOC_APACHE_NODE_LVL_L2) && (!uc)) { 2408 while (child) { 2409 if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(child->gport)) { 2410 if (min_index == -1) { 2411 min_index = child->hw_index; 2412 } 2413 2414 if (child->hw_index < min_index) { 2415 min_index = child->hw_index; 2416 } 2417 } 2418 child = child->sibling; 2419 } 2420 } else { 2421 while (child) { 2422 if (min_index == -1) { 2423 min_index = child->hw_index; 2424 } 2425 2426 if (child->hw_index < min_index) { 2427 min_index = child->hw_index; 2428 } 2429 child = child->sibling; 2430 } 2431 } 2432 2433 return min_index; 2434 } 2435 2436 STATIC int 2437 _bcm_ap_child_state_check(int unit, bcm_port_t gport, 2438 bcm_cos_queue_t cosq, int ets_mode) 2439 { 2440 _bcm_ap_cosq_node_t *node, *child_node = NULL; 2441 bcm_port_t local_port; 2442 int level, sch_index, empty = 0; 2443 int rv = BCM_E_NONE; 2444 soc_timeout_t timeout; 2445 uint32 timeout_val; 2446 uint32 entry[SOC_MAX_MEM_WORDS]; 2447 soc_mem_t mem = INVALIDm; 2448 static const soc_mem_t memx[] = { 2449 INVALIDm, 2450 LLS_L0_CHILD_STATE1m, 2451 LLS_L1_CHILD_STATE1m, 2452 LLS_L2_CHILD_STATE1m 2453 }; 2454 2455 /* Timeout val = Static for now. Need to quantify the max wait time */ 2456 timeout_val = 2000000; 2457 2458 BCM_IF_ERROR_RETURN 2459 (_bcm_ap_cosq_localport_resolve(unit, gport, &local_port)); 2460 2461 if (ets_mode & (!IS_AP_HSP_PORT(unit, local_port))) { 2462 BCM_IF_ERROR_RETURN 2463 (_bcm_ap_cosq_node_get(unit, gport, 0, NULL, 2464 &local_port, NULL, &node)); 2465 2466 /* Get the Child node for the Given Gport */ 2467 rv = _bcm_ap_cosq_child_node_at_input(node, cosq, &child_node); 2468 2469 if ((!child_node) || (rv == BCM_E_NOT_FOUND)) { 2470 /* No Child present */ 2471 return BCM_E_NONE; 2472 } 2473 2474 BCM_IF_ERROR_RETURN 2475 (_bcm_ap_cosq_localport_resolve(unit, gport, &local_port)); 2476 2477 level = child_node->level; 2478 sch_index = child_node->hw_index; 2479 2480 /* Child State Check is NOT necessary for Non-L0/L1/L2 levels */ 2481 if ((level < SOC_APACHE_NODE_LVL_L0) || (level > SOC_APACHE_NODE_LVL_L2)) { 2482 /* Sanity for Node's level should be done in the caller */ 2483 return BCM_E_NONE; 2484 } 2485 2486 mem = memx[level]; 2487 2488 if (mem == INVALIDm) { 2489 return BCM_E_INTERNAL; 2490 } 2491 2492 soc_timeout_init(&timeout, timeout_val, 0); 2493 2494 for(;;) { 2495 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, 2496 sch_index, entry)); 2497 empty = 0; 2498 if (soc_timeout_check(&timeout)) { 2499 LOG_ERROR(BSL_LS_BCM_COMMON, 2500 (BSL_META_U(unit, 2501 "ERROR: Timeout during Child lists Not zero\n"))); 2502 return BCM_E_BUSY; 2503 } 2504 empty += soc_mem_field32_get(unit, mem, &entry, C_ACTIVE_0f); 2505 empty += soc_mem_field32_get(unit, mem, &entry, C_ON_MIN_LIST_0f); 2506 empty += soc_mem_field32_get(unit, mem, &entry, C_NOT_EMPTY_0f); 2507 2508 if (!empty) { 2509 break; 2510 } 2511 } 2512 } else { 2513 /* TBD: Non-ETS mode not supported. May not be possible to support the same on HSP queues */ 2514 return BCM_E_NONE; 2515 } 2516 2517 return BCM_E_NONE; 2518 } 2519 2520 STATIC int 2521 _bcm_ap_cosq_node_queue_state_check(int unit, 2522 _bcm_ap_cosq_node_t *node, int ets_mode) 2523 { 2524 int cosq = 0; 2525 2526 if (node == NULL) { 2527 return BCM_E_PARAM; 2528 } 2529 2530 for (cosq = 0; cosq < node->numq; cosq++) { 2531 BCM_IF_ERROR_RETURN 2532 (_bcm_ap_child_state_check(unit, node->gport, 2533 cosq, ets_mode)); 2534 } 2535 2536 if ((node->level <= SOC_APACHE_NODE_LVL_L1) && 2537 (node->child != NULL)) { 2538 BCM_IF_ERROR_RETURN 2539 (_bcm_ap_cosq_node_queue_state_check(unit, 2540 node->child,ets_mode)); 2541 } 2542 2543 if (node->sibling != NULL) { 2544 2545 BCM_IF_ERROR_RETURN 2546 (_bcm_ap_cosq_node_queue_state_check(unit, 2547 node->sibling,ets_mode)); 2548 } 2549 2550 return BCM_E_NONE; 2551 } 2552 2553 int 2554 _bcm_ap_cosq_port_queue_state_check(int unit, bcm_port_t gport) 2555 { 2556 bcm_port_t local_port; 2557 int ets_mode; 2558 _bcm_ap_cosq_node_t *node; 2559 2560 BCM_IF_ERROR_RETURN 2561 (_bcm_ap_cosq_localport_resolve(unit, gport, &local_port)); 2562 ets_mode = _bcm_ap_cosq_port_has_ets(unit, local_port); 2563 if (!ets_mode) { 2564 return BCM_E_NONE; 2565 } 2566 2567 BCM_IF_ERROR_RETURN 2568 (bcm_esw_port_gport_get(unit, local_port, 2569 &gport)); 2570 2571 BCM_IF_ERROR_RETURN 2572 (_bcm_ap_cosq_node_get(unit, gport, 0, NULL, 2573 NULL, NULL, &node)); 2574 2575 BCM_IF_ERROR_RETURN 2576 (_bcm_ap_cosq_node_queue_state_check(unit, 2577 node,ets_mode)); 2578 return BCM_E_NONE; 2579 } 2580 2581 2582 /* 2583 * Function: 2584 * _bcm_ap_mmu_rx_enable_set 2585 * Purpose: 2586 * enable/disable mmu rx traffic from the gport. 2587 * Parameters: 2588 * unit - (IN) unit number 2589 * gport - (IN) GPORT identifier 2590 * enable - (IN) enable/disable 2591 * Returns: 2592 * BCM_E_XXX 2593 */ 2594 STATIC int 2595 _bcm_ap_mmu_rx_enable_set(int unit, bcm_port_t local_port, 2596 int enable) 2597 { 2598 uint32 rval; 2599 2600 /* Disable/Enable INPUT_PORT_RX to the port */ 2601 SOC_IF_ERROR_RETURN 2602 (soc_reg32_get(unit, THDI_INPUT_PORT_XON_ENABLESr, 2603 local_port, 0, &rval)); 2604 2605 if (!enable) { 2606 soc_reg_field_set(unit, THDI_INPUT_PORT_XON_ENABLESr, &rval, 2607 INPUT_PORT_RX_ENABLEf, 2608 0); 2609 } else { 2610 soc_reg_field_set(unit, THDI_INPUT_PORT_XON_ENABLESr, &rval, 2611 INPUT_PORT_RX_ENABLEf, 2612 1); 2613 } 2614 2615 SOC_IF_ERROR_RETURN 2616 (soc_reg32_set(unit, THDI_INPUT_PORT_XON_ENABLESr, 2617 local_port, 0, rval)); 2618 2619 return BCM_E_NONE; 2620 } 2621 2622 STATIC int 2623 _bcm_ap_attach_node_in_hw(int unit, _bcm_ap_cosq_node_t *node) 2624 { 2625 int local_port, fc = 0, fmc = 0; 2626 _bcm_ap_cosq_node_t *child_node; 2627 int num_spri = 0, first_sp_child = 0, first_sp_mc_child; 2628 uint32 ucmap = 0, spmap = 0; 2629 soc_apache_sched_type_t sched_type; 2630 2631 local_port = node->local_port; 2632 2633 if (node->level == SOC_APACHE_NODE_LVL_ROOT) { 2634 return 0; 2635 } else if (node->level == SOC_APACHE_NODE_LVL_L2) { 2636 fc = _bcm_ap_cosq_min_child_index(node->parent->child, SOC_APACHE_NODE_LVL_L2, 1); 2637 if (fc < 0) { 2638 fc = 0; 2639 } 2640 fmc = _bcm_ap_cosq_min_child_index(node->parent->child, SOC_APACHE_NODE_LVL_L2, 0); 2641 if (fmc < 0) { 2642 fmc = _BCM_AP_NUM_L2_UC_LEAVES; 2643 } 2644 } else { 2645 fc = _bcm_ap_cosq_min_child_index(node->parent->child, node->level, 0); 2646 fmc = 0; 2647 } 2648 2649 /* If node is scheduler, reset the scheduler and attach it to the parent.*/ 2650 BCM_IF_ERROR_RETURN( 2651 soc_apache_cosq_set_sched_parent(unit, local_port, node->level, 2652 node->hw_index, node->parent->hw_index, 1)); 2653 2654 sched_type = _soc_apache_port_sched_type_get(unit, local_port); 2655 2656 if (sched_type == SOC_APACHE_SCHED_LLS) { 2657 if (node->parent->level != SOC_APACHE_NODE_LVL_ROOT) { 2658 BCM_IF_ERROR_RETURN( 2659 soc_apache_cosq_get_sched_child_config(unit, local_port, 2660 node->parent->level, 2661 node->parent->hw_index, 2662 &num_spri, &first_sp_child, 2663 &first_sp_mc_child, &ucmap, &spmap)); 2664 } 2665 /* set the node by default in WRR mode with wt=1 */ 2666 BCM_IF_ERROR_RETURN(soc_apache_cosq_set_sched_config(unit, 2667 local_port, node->parent->level, 2668 node->parent->hw_index, node->hw_index, 2669 num_spri, fc, fmc, ucmap, spmap, 2670 SOC_APACHE_SCHED_MODE_WRR, 1)); 2671 } 2672 2673 2674 if (node->child) { 2675 child_node = node->child; 2676 while (child_node) { 2677 BCM_IF_ERROR_RETURN(_bcm_ap_attach_node_in_hw(unit, child_node)); 2678 child_node = child_node->sibling; 2679 } 2680 } 2681 2682 return BCM_E_NONE; 2683 } 2684 /* 2685 * Function: 2686 * _bcm_ap_cosq_map_index_get 2687 * Purpose: 2688 * Allocate free index from the given list 2689 * Parameters: 2690 * list - (IN) bit list 2691 * start - (IN) start index 2692 * end - (IN) end index 2693 * id - (OUT) start index 2694 * Returns: 2695 * BCM_E_XXX 2696 */ 2697 STATIC int 2698 _bcm_ap_cosq_map_index_get(SHR_BITDCL *list, int start, int end, int *id) 2699 { 2700 int i; 2701 2702 for (i = start; i < end; i++) { 2703 if (SHR_BITGET(list, i) != 0) { 2704 continue; 2705 } 2706 *id = i; 2707 return BCM_E_NONE; 2708 } 2709 2710 return BCM_E_RESOURCE; 2711 } 2712 2713 /* 2714 * Function: 2715 * _bcm_ap_cosq_map_index_clear 2716 * Purpose: 2717 * Mark indices as free 2718 * Parameters: 2719 * list - (IN) bit list 2720 * start - (IN) start index 2721 * range - (IN) range bits 2722 * Returns: 2723 * BCM_E_XXX 2724 */ 2725 STATIC int 2726 _bcm_ap_cosq_map_index_clear(SHR_BITDCL *list, int start, int range) 2727 { 2728 SHR_BITCLR_RANGE(list, start, range); 2729 return BCM_E_NONE; 2730 } 2731 2732 /* 2733 * Function: 2734 * _bcm_ap_cosq_map_index_is_set 2735 * Purpose: 2736 * Check index is allocated 2737 * Parameters: 2738 * list - (IN) bit list 2739 * index - (IN) index 2740 * Returns: 2741 * BCM_E_XXX 2742 */ 2743 STATIC int 2744 _bcm_ap_cosq_map_index_is_set(SHR_BITDCL *list, int index) 2745 { 2746 if (SHR_BITGET(list, index) != 0) { 2747 return TRUE; 2748 } 2749 2750 return FALSE; 2751 } 2752 /* 2753 * Function: 2754 * _bcm_ap_cosq_node_resolve 2755 * Purpose: 2756 * Resolve queue number in the specified scheduler tree and its subtree 2757 * Parameters: 2758 * unit - (IN) unit number 2759 * node - (IN) node structure for the specified scheduler node 2760 * cosq - (IN) COS queue to attach to 2761 * Returns: 2762 * BCM_E_XXX 2763 */ 2764 STATIC int 2765 _bcm_ap_cosq_node_resolve(int unit, _bcm_ap_cosq_node_t *node, 2766 bcm_cos_queue_t cosq) 2767 { 2768 _bcm_ap_cosq_node_t *cur_node, *parent; 2769 _bcm_ap_cosq_port_info_t *port_info; 2770 _bcm_ap_pipe_resources_t * res; 2771 _bcm_ap_mmu_info_t *mmu_info; 2772 _bcm_ap_cosq_list_t *list; 2773 int numq, id = -1 , prev_base = -1, rv; 2774 int valid_index_lo, valid_index_hi; 2775 bcm_port_t port; 2776 int alloc_size; 2777 int phy_port, mmu_port; 2778 int max_nodes = 0; 2779 uint32 rval = 0; 2780 uint32 mc_group_mode = 0; 2781 2782 if ((parent = node->parent) == NULL) { 2783 /* Not attached, should never happen */ 2784 return BCM_E_NOT_FOUND; 2785 } 2786 2787 if (parent->numq == 0 || parent->numq < -1) { 2788 return BCM_E_PARAM; 2789 } 2790 2791 port = node->local_port; 2792 2793 BCM_IF_ERROR_RETURN 2794 (_bcm_ap_cosq_max_nodes_get(unit, node->level, &max_nodes)); 2795 if (parent->cosq_map == NULL) { 2796 if (parent->numq == -1) { 2797 alloc_size = SHR_BITALLOCSIZE(max_nodes); 2798 } else { 2799 alloc_size = SHR_BITALLOCSIZE(parent->numq); 2800 } 2801 parent->cosq_map = _bcm_ap_cosq_alloc_clear(parent->cosq_map, 2802 alloc_size, 2803 "cosq_map"); 2804 if (parent->cosq_map == NULL) { 2805 return BCM_E_MEMORY; 2806 } 2807 } 2808 if (cosq < 0) { 2809 BCM_IF_ERROR_RETURN 2810 (_bcm_ap_cosq_map_index_get(parent->cosq_map, 2811 0, 2812 parent->numq == -1 ? 2813 max_nodes: parent->numq, &id)); 2814 BCM_IF_ERROR_RETURN 2815 (_bcm_ap_cosq_map_index_set(parent->cosq_map, id, 1)); 2816 node->attached_to_input = id; 2817 } else { 2818 if (_bcm_ap_cosq_map_index_is_set(parent->cosq_map, 2819 cosq) == TRUE) { 2820 return BCM_E_EXISTS; 2821 } 2822 if (cosq > ((parent->numq == -1) ? max_nodes : parent->numq)) { 2823 return BCM_E_PARAM; 2824 } 2825 BCM_IF_ERROR_RETURN 2826 (_bcm_ap_cosq_map_index_set(parent->cosq_map, cosq, 1)); 2827 node->attached_to_input = cosq; 2828 } 2829 2830 mmu_info = _bcm_ap_mmu_info[unit]; 2831 port_info = &mmu_info->port_info[port]; 2832 res = port_info->resources; 2833 numq = (parent->numq == -1) ? 1 : parent->numq; 2834 phy_port = SOC_INFO(unit).port_l2p_mapping[port]; 2835 mmu_port = SOC_INFO(unit).port_p2m_mapping[phy_port]; 2836 2837 switch (parent->level) { 2838 case SOC_APACHE_NODE_LVL_ROOT: 2839 list = &res->s1_sched_list; 2840 if (IS_AP_HSP_PORT(unit, port)) { 2841 list = &res->hsp_l0_sched_list; 2842 } 2843 if (parent->numq_expandable && parent->base_index >= 0 && 2844 parent->base_size != parent->numq) { 2845 _bcm_ap_node_index_clear(list, parent->base_index, 2846 parent->base_size); 2847 prev_base = parent->base_index; 2848 parent->base_index = -1; 2849 } 2850 if (IS_AP_HSP_PORT(unit, port)) { 2851 valid_index_lo = _BCM_AP_HSP_L0_INDEX(unit, mmu_port, 0); 2852 valid_index_hi = _BCM_AP_HSP_L0_INDEX(unit, (mmu_port + 1), 2853 0); 2854 } else { 2855 valid_index_lo = 0; 2856 valid_index_hi = _BCM_AP_NUM_S1_SCHEDULER_PER_PIPE; 2857 } 2858 2859 if (((parent->base_index < 0) && (node->attached_to_input < numq)) 2860 || (parent->numq == -1)) { 2861 rv = _bcm_ap_node_index_get(list->bits, valid_index_lo, 2862 valid_index_hi, numq, 1, &id); 2863 if (rv) { 2864 return rv; 2865 } 2866 2867 _bcm_ap_node_index_set(list, id, numq); 2868 if (parent->numq != -1) { 2869 parent->base_index = id; 2870 node->hw_index = parent->base_index + node->attached_to_input; 2871 parent->base_size = numq; 2872 if ((prev_base >= 0) && (prev_base != id)) { 2873 for (cur_node = parent->child; cur_node; 2874 cur_node = cur_node->sibling) { 2875 if (cur_node->attached_to_input >= 0) { 2876 cur_node->hw_index = parent->base_index + 2877 cur_node->attached_to_input; 2878 BCM_IF_ERROR_RETURN(_bcm_ap_attach_node_in_hw(unit, cur_node)); 2879 } 2880 } 2881 } 2882 } else { 2883 node->hw_index = id; 2884 } 2885 } else if (node->attached_to_input >= numq) { 2886 rv = _bcm_ap_node_index_get(list->bits, valid_index_lo, 2887 valid_index_hi, 1, 1, &id); 2888 if (rv) { 2889 return rv; 2890 } 2891 _bcm_ap_node_index_set(list, id, 1); 2892 node->hw_index = id; 2893 2894 } else { 2895 node->hw_index = parent->base_index + node->attached_to_input; 2896 } 2897 node->hw_cosq = node->attached_to_input; 2898 node->wrr_in_use = 1; 2899 2900 break; 2901 2902 case SOC_APACHE_NODE_LVL_S1: 2903 if (IS_AP_HSP_PORT(unit, port)) { 2904 return BCM_E_PARAM; 2905 } 2906 list = &res->l0_sched_list; 2907 if (parent->numq_expandable && parent->base_index >= 0 && 2908 parent->base_size != parent->numq) { 2909 _bcm_ap_node_index_clear(list, parent->base_index, 2910 parent->base_size); 2911 prev_base = parent->base_index; 2912 parent->base_index = -1; 2913 } 2914 valid_index_lo = 0; 2915 valid_index_hi = _BCM_AP_NUM_L0_SCHEDULER_PER_PIPE; 2916 if (IS_CPU_PORT(unit, port)) { 2917 list = &res->cpu_l0_sched_list; 2918 valid_index_lo = 0; 2919 valid_index_hi = _BCM_AP_CPU_PORT_L0_MAX - _BCM_AP_CPU_PORT_L0_MIN; 2920 } 2921 2922 if (((parent->base_index < 0) && (node->attached_to_input < numq)) 2923 || (parent->numq == -1)) { 2924 if (_BCM_DEFAULT_LLS_IS_SET(mmu_info)) { 2925 rv = _bcm_ap_node_index_get(list->bits, valid_index_lo, 2926 valid_index_hi, numq, _BCM_AP_START_INDEX_ALIGN_PFC, 2927 &id); 2928 } else if (node->node_align_value) { 2929 rv = _bcm_ap_node_index_get(list->bits, valid_index_lo, 2930 valid_index_hi, numq, node->node_align_value, 2931 &id); 2932 } else { 2933 rv = _bcm_ap_node_index_get(list->bits, valid_index_lo, 2934 valid_index_hi, numq, _BCM_AP_START_INDEX_ALIGN_DEFAULT, 2935 &id); 2936 } 2937 if (rv) { 2938 return rv; 2939 } 2940 2941 _bcm_ap_node_index_set(list, id, numq); 2942 if (IS_CPU_PORT(unit, port)) { 2943 id += _BCM_AP_CPU_PORT_L0_MIN; 2944 } 2945 if (parent->numq != -1) { 2946 parent->base_index = id; 2947 node->hw_index = parent->base_index + node->attached_to_input; 2948 parent->base_size = numq; 2949 if ((prev_base >= 0) && (prev_base != id)) { 2950 for (cur_node = parent->child; cur_node; 2951 cur_node = cur_node->sibling) { 2952 if (cur_node->attached_to_input >= 0) { 2953 cur_node->hw_index = parent->base_index + 2954 cur_node->attached_to_input; 2955 BCM_IF_ERROR_RETURN(_bcm_ap_attach_node_in_hw(unit, cur_node)); 2956 } 2957 } 2958 } 2959 } else { 2960 node->hw_index = id; 2961 } 2962 } else if (node->attached_to_input >= numq) { 2963 rv = _bcm_ap_node_index_get(list->bits, valid_index_lo, 2964 valid_index_hi, 1, 1, &id); 2965 if (rv) { 2966 return rv; 2967 } 2968 _bcm_ap_node_index_set(list, id, 1); 2969 node->hw_index = id; 2970 } else { 2971 node->hw_index = parent->base_index + node->attached_to_input; 2972 } 2973 node->hw_cosq = node->attached_to_input; 2974 2975 break; 2976 2977 2978 case SOC_APACHE_NODE_LVL_L0: 2979 if (IS_AP_HSP_PORT(unit, port)) { 2980 if (node->attached_to_input >= _BCM_AP_HSP_PORT_MAX_L1) { 2981 return BCM_E_PARAM; 2982 } 2983 2984 if ((parent->hw_index % _BCM_AP_HSP_PORT_MAX_L0) == 0) { 2985 /* L0.0 could only be attached by MC nodes */ 2986 if (node->type == _BCM_AP_NODE_MCAST) { 2987 SOC_IF_ERROR_RETURN( 2988 READ_HSP_SCHED_PORT_CONFIGr(unit, port, &rval)); 2989 mc_group_mode = soc_reg_field_get( 2990 unit, HSP_SCHED_PORT_CONFIGr, 2991 rval, MC_GROUP_MODEf); 2992 /* check mc group mode and the node offset */ 2993 if ((!mc_group_mode) || 2994 (((node->hw_index -_BCM_AP_NUM_L2_UC_LEAVES_PER_PIPE) % _BCM_AP_HSP_PORT_MAX_L1) >= 2995 _BCM_AP_HSP_PORT_MAX_COS)) { 2996 return BCM_E_PARAM; 2997 } 2998 break; 2999 } else { 3000 return BCM_E_PARAM; 3001 } 3002 } 3003 3004 list = &res->hsp_l1_sched_list; 3005 valid_index_lo = _BCM_AP_HSP_L1_INDEX(unit, mmu_port, 0); 3006 valid_index_hi = _BCM_AP_HSP_L1_INDEX(unit, (mmu_port + 1), 3007 0); 3008 BCM_IF_ERROR_RETURN(_bcm_ap_node_index_get(list->bits, valid_index_lo, 3009 valid_index_hi, 1, 1, &id)); 3010 if (parent->base_index == -1) { 3011 parent->base_index = id; 3012 } 3013 node->hw_index = id; 3014 3015 if ((node->hw_index % _BCM_AP_HSP_PORT_MAX_L1) >= 8) { 3016 if ((parent->hw_index % _BCM_AP_HSP_PORT_MAX_L0) != 4) { 3017 return BCM_E_PARAM; 3018 } 3019 } else { 3020 if ((parent->hw_index % _BCM_AP_HSP_PORT_MAX_L0) == 4) { 3021 return BCM_E_PARAM; 3022 } 3023 } 3024 _bcm_ap_node_index_set(list, id, 1); 3025 } else { 3026 list = &res->l1_sched_list; 3027 if (((parent->base_index < 0) && (node->attached_to_input < numq)) 3028 || (parent->numq == -1)) { 3029 if (_BCM_DEFAULT_LLS_IS_SET(mmu_info)) { 3030 BCM_IF_ERROR_RETURN(_bcm_ap_node_index_get(list->bits, 0, 3031 _BCM_AP_NUM_L1_SCHEDULER_PER_PIPE, numq, 3032 _BCM_AP_START_INDEX_ALIGN_PFC, &id)); 3033 } else if (node->node_align_value) { 3034 BCM_IF_ERROR_RETURN(_bcm_ap_node_index_get(list->bits, 0, 3035 _BCM_AP_NUM_L1_SCHEDULER_PER_PIPE, numq, 3036 node->node_align_value, &id)); 3037 } else { 3038 BCM_IF_ERROR_RETURN(_bcm_ap_node_index_get(list->bits, 0, 3039 _BCM_AP_NUM_L1_SCHEDULER_PER_PIPE, numq, 3040 _BCM_AP_START_INDEX_ALIGN_DEFAULT, &id)); 3041 } 3042 3043 _bcm_ap_node_index_set(list, id, numq); 3044 parent->base_size = numq; 3045 if (parent->base_index == -1) { 3046 parent->base_index = id; 3047 } 3048 if (parent->numq != -1) { 3049 node->hw_index = parent->base_index + node->attached_to_input; 3050 } else { 3051 node->hw_index = id; 3052 } 3053 } else if (node->attached_to_input >= numq) { 3054 3055 BCM_IF_ERROR_RETURN(_bcm_ap_node_index_get(list->bits, 0, 3056 _BCM_AP_NUM_L1_SCHEDULER_PER_PIPE, 1, 1, &id)); 3057 _bcm_ap_node_index_set(list, id, 1); 3058 node->hw_index = id; 3059 } else { 3060 node->hw_index = parent->base_index + node->attached_to_input; 3061 } 3062 } 3063 node->hw_cosq = node->attached_to_input; 3064 3065 break; 3066 3067 case SOC_APACHE_NODE_LVL_L1: 3068 if (IS_AP_HSP_PORT(unit, port)) { 3069 uint32 rval = 0; 3070 uint32 mc_group_mode = 0; 3071 int qnum; 3072 SOC_IF_ERROR_RETURN( 3073 READ_HSP_SCHED_PORT_CONFIGr(unit, port, &rval)); 3074 mc_group_mode = soc_reg_field_get(unit, HSP_SCHED_PORT_CONFIGr, 3075 rval, MC_GROUP_MODEf); 3076 qnum = (node->hw_index > _BCM_AP_NUM_L2_UC_LEAVES_PER_PIPE) ? 3077 (node->hw_index - _BCM_AP_NUM_L2_UC_LEAVES_PER_PIPE) : node->hw_index; 3078 if (mc_group_mode && 3079 ((qnum % _BCM_AP_HSP_PORT_MAX_L1) < _BCM_AP_HSP_PORT_MAX_COS)) { 3080 if (node->attached_to_input >= 1) { 3081 return BCM_E_PARAM; 3082 } 3083 if (node->type == _BCM_AP_NODE_MCAST) { 3084 return BCM_E_PARAM; 3085 } 3086 } else { 3087 if (node->attached_to_input >= _BCM_AP_HSP_PORT_MAX_L2_PER_L1) { 3088 return BCM_E_PARAM; 3089 } 3090 if ((node->sibling) && 3091 (node->type == node->sibling->type)) { 3092 return BCM_E_PARAM; 3093 } 3094 } 3095 } 3096 if ((node->hw_index == -1) && 3097 (node->type != _BCM_AP_NODE_VOQ)) { 3098 return BCM_E_PARAM; 3099 } else if (node->type == _BCM_AP_NODE_VOQ) { 3100 if (parent->base_index < 0) { 3101 BCM_IF_ERROR_RETURN( 3102 _bcm_ap_node_index_get(res->l2_queue_list.bits, 3103 res->num_base_queues, 3104 _BCM_AP_NUM_L2_UC_LEAVES_PER_PIPE , 3105 _AP_NUM_COS(unit), 3106 _AP_NUM_COS(unit), &id)); 3107 /* The following logic is to make sure the id is always 3108 * multiple of 8 3109 */ 3110 while ( id % 8 != 0) { 3111 id = ((id + 8) & 0xfffffff8); 3112 if (id > _BCM_AP_NUM_L2_UC_LEAVES_PER_PIPE ) { 3113 return BCM_E_RESOURCE; 3114 } 3115 BCM_IF_ERROR_RETURN( 3116 _bcm_ap_node_index_get(res->l2_queue_list.bits, id, 3117 _BCM_AP_NUM_L2_UC_LEAVES_PER_PIPE, 3118 NUM_COS(unit), 3119 NUM_COS(unit), &id)); 3120 } 3121 _bcm_ap_node_index_set(&res->l2_queue_list, id, 3122 (parent->numq == -1) ? _AP_NUM_COS(unit) : parent->numq); 3123 parent->base_index = id ; 3124 node->hw_index = parent->base_index; 3125 node->hw_cosq = node->hw_index % 3126 ((parent->numq == -1) ? _AP_NUM_COS(unit) : parent->numq); 3127 } else { 3128 node->hw_index = parent->base_index + 3129 node->attached_to_input; 3130 node->hw_cosq = node->hw_index % NUM_COS(unit); 3131 } 3132 } else if((node->hw_index != -1) && (parent->base_index < 0)) { 3133 parent->base_index = node->hw_index; 3134 } 3135 break; 3136 3137 case SOC_APACHE_NODE_LVL_L2: 3138 /* passthru */ 3139 default: 3140 return BCM_E_PARAM; 3141 3142 } 3143 3144 BCM_IF_ERROR_RETURN(_bcm_ap_attach_node_in_hw(unit, node)); 3145 return BCM_E_NONE; 3146 } 3147 3148 STATIC int 3149 _bcm_ap_detach_node_in_hw(int unit, _bcm_ap_cosq_node_t *node) 3150 { 3151 int local_port; 3152 3153 local_port = node->local_port; 3154 3155 if (!IS_AP_HSP_PORT(unit, local_port)) { 3156 BCM_IF_ERROR_RETURN( 3157 _bcm_ap_cosq_sched_parent_child_set(unit, 3158 local_port, node->parent->level, node->parent->hw_index, 3159 node->hw_index, SOC_TD2_SCHED_MODE_WRR, 1, node)); 3160 } 3161 3162 return BCM_E_NONE; 3163 } 3164 3165 /* 3166 * Function: 3167 * _bcm_ap_cosq_clear_child_list 3168 * Purpose: 3169 * Reset the child list to 0. To be called when deleting the node. 3170 * Parameters: 3171 * unit - (IN) unit number 3172 * node - (IN) node structure for the specified scheduler node 3173 * Returns: 3174 * BCM_E_XXX 3175 */ 3176 STATIC int 3177 _bcm_ap_cosq_clear_child_list(int unit, _bcm_ap_cosq_node_t *node) 3178 { 3179 _bcm_ap_mmu_info_t *mmu_info; 3180 _bcm_ap_pipe_resources_t * res; 3181 _bcm_ap_cosq_port_info_t *port_info; 3182 _bcm_ap_cosq_list_t *list; 3183 int start_index = 0, numq = 0; 3184 int port; 3185 3186 mmu_info = _bcm_ap_mmu_info[unit]; 3187 BCM_IF_ERROR_RETURN 3188 (_bcm_ap_cosq_node_get(unit, node->gport, 0, NULL, &port, NULL, NULL)); 3189 3190 port_info = &mmu_info->port_info[port]; 3191 res = port_info->resources; 3192 3193 list = NULL; 3194 switch (node->level) { 3195 case SOC_APACHE_NODE_LVL_ROOT: 3196 if (IS_AP_HSP_PORT(unit, port)) { 3197 list = &res->hsp_l0_sched_list; 3198 start_index = node->base_index; 3199 numq = (node->numq == -1) ? 3200 _BCM_AP_HSP_PORT_MAX_L0 : node->numq; 3201 } 3202 break; 3203 default: 3204 return BCM_E_NONE; 3205 } 3206 3207 if(list){ 3208 _bcm_ap_node_index_clear(list, start_index, numq); 3209 } 3210 return BCM_E_NONE; 3211 } 3212 /* 3213 * Function: 3214 * _bcm_ap_cosq_node_unresolve 3215 * Purpose: 3216 * Unresolve queue number in the specified scheduler tree and its subtree 3217 * Parameters: 3218 * unit - (IN) unit number 3219 * node - (IN) node structure for the specified scheduler node 3220 * cosq - (IN) COS queue to attach to 3221 * Returns: 3222 * BCM_E_XXX 3223 */ 3224 STATIC int 3225 _bcm_ap_cosq_node_unresolve(int unit, _bcm_ap_cosq_node_t *node, 3226 bcm_cos_queue_t cosq) 3227 { 3228 _bcm_ap_cosq_node_t *parent; 3229 _bcm_ap_mmu_info_t *mmu_info; 3230 _bcm_ap_pipe_resources_t * res; 3231 _bcm_ap_cosq_port_info_t *port_info; 3232 _bcm_ap_cosq_list_t *list; 3233 int numq = 1, port; 3234 int hw_index; 3235 3236 if (node->attached_to_input < 0) { 3237 /* Has been unresolved already */ 3238 return BCM_E_NONE; 3239 } 3240 3241 parent = node->parent; 3242 3243 if (!parent) { 3244 return BCM_E_PARAM; 3245 } 3246 3247 mmu_info = _bcm_ap_mmu_info[unit]; 3248 3249 BCM_IF_ERROR_RETURN 3250 (_bcm_ap_cosq_node_get(unit, node->gport, 0, NULL, &port, NULL, NULL)); 3251 3252 port_info = &mmu_info->port_info[port]; 3253 res = port_info->resources; 3254 3255 list = NULL; 3256 3257 switch (parent->level) { 3258 case SOC_APACHE_NODE_LVL_ROOT: 3259 if (IS_AP_HSP_PORT(unit, port)) { 3260 list = &res->hsp_l0_sched_list; 3261 } else { 3262 list = &res->s1_sched_list; 3263 } 3264 break; 3265 3266 case SOC_APACHE_NODE_LVL_S1: 3267 if (IS_AP_HSP_PORT(unit, port)) { 3268 return BCM_E_PARAM; 3269 } else if (IS_CPU_PORT(unit, port)) { 3270 list = &res->cpu_l0_sched_list; 3271 } else { 3272 list = &res->l0_sched_list; 3273 } 3274 break; 3275 3276 case SOC_APACHE_NODE_LVL_L0: 3277 if (IS_AP_HSP_PORT(unit, port)) { 3278 list = &res->hsp_l1_sched_list; 3279 } else { 3280 3281 list = &res->l1_sched_list; 3282 } 3283 break; 3284 3285 case SOC_APACHE_NODE_LVL_L1: 3286 break; 3287 3288 case SOC_APACHE_NODE_LVL_L2: 3289 /* passthru */ 3290 default: 3291 return BCM_E_PARAM; 3292 3293 } 3294 3295 if ((list) && (node->attached_to_input >= 8)) { 3296 hw_index = node->hw_index; 3297 if (IS_CPU_PORT(unit, port)) { 3298 hw_index = node->hw_index - _BCM_AP_CPU_PORT_L0_MIN; 3299 } 3300 _bcm_ap_node_index_clear(list, hw_index, numq); 3301 } else if((list) && (IS_AP_HSP_PORT(unit, port))){ 3302 _bcm_ap_node_index_clear(list, node->hw_index, 1); 3303 } 3304 BCM_IF_ERROR_RETURN 3305 (_bcm_ap_cosq_map_index_clear(node->parent->cosq_map, 3306 node->attached_to_input , 1)); 3307 node->attached_to_input = -1; 3308 3309 BCM_IF_ERROR_RETURN(_bcm_ap_detach_node_in_hw(unit, node)); 3310 return BCM_E_NONE; 3311 } 3312 3313 /* 3314 * Function: 3315 * _bcm_ap_port_enqueue_set 3316 * Purpose: 3317 * Enable or Disable the enqueing the packets to the port 3318 * Parameters: 3319 * unit - (IN) unit number 3320 * gport - (IN) gport of the port 3321 * enable - (IN) TRUE to enable 3322 * FALSE to disable 3323 * Returns: 3324 * BCM_E_XXX 3325 */ 3326 3327 int 3328 _bcm_ap_port_enqueue_set(int unit, bcm_port_t gport, int enable) 3329 { 3330 bcm_port_t local_port; 3331 3332 BCM_IF_ERROR_RETURN 3333 (_bcm_ap_cosq_localport_resolve(unit, gport, &local_port)); 3334 3335 SOC_IF_ERROR_RETURN( 3336 soc_apache_port_mmu_tx_enable_set(unit, local_port, enable)); 3337 SOC_IF_ERROR_RETURN( 3338 _bcm_ap_mmu_rx_enable_set(unit, local_port, enable)); 3339 3340 return BCM_E_NONE; 3341 } 3342 /* 3343 * Function: 3344 * _bcm_ap_port_enqueue_get 3345 * Purpose: 3346 * Getting the enqueing state of the port 3347 * Parameters: 3348 * unit - (IN) unit number 3349 * gport - (IN) gport of the port 3350 * enable - (IN) TRUE to enable 3351 * FALSE to disable 3352 * Returns: 3353 * BCM_E_XXX 3354 */ 3355 3356 int 3357 _bcm_ap_port_enqueue_get(int unit, bcm_port_t gport, 3358 int *enable) 3359 { 3360 uint64 rval64; 3361 int mmu_port, phy_port, i, reg_grp = 0; 3362 int rv = BCM_E_NONE; 3363 bcm_port_t local_port; 3364 soc_info_t *si; 3365 soc_reg_t reg_tmp; 3366 soc_reg_t reg[3][2] = { 3367 { 3368 THDU_OUTPUT_PORT_RX_ENABLE0_64r, 3369 THDU_OUTPUT_PORT_RX_ENABLE1_64r 3370 }, 3371 { 3372 MMU_THDM_DB_PORTSP_RX_ENABLE0_64r, 3373 MMU_THDM_DB_PORTSP_RX_ENABLE1_64r 3374 }, 3375 { 3376 MMU_THDM_MCQE_PORTSP_RX_ENABLE0_64r, 3377 MMU_THDM_MCQE_PORTSP_RX_ENABLE1_64r 3378 } 3379 }; 3380 int max_reg = 3; 3381 3382 BCM_IF_ERROR_RETURN 3383 (_bcm_ap_cosq_localport_resolve(unit, gport, &local_port)); 3384 3385 si = &SOC_INFO(unit); 3386 3387 phy_port = si->port_l2p_mapping[local_port]; 3388 mmu_port = si->port_p2m_mapping[phy_port]; 3389 3390 COMPILER_64_ZERO(rval64); 3391 if (mmu_port < 64 ) { 3392 mmu_port &= 0x3f; 3393 } else { 3394 mmu_port &= 0xf; 3395 reg_grp = 1; 3396 } 3397 3398 for (i = 0; i < max_reg; i++) { 3399 reg_tmp = reg[i][reg_grp]; 3400 3401 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg_tmp, REG_PORT_ANY, 0, &rval64)); 3402 3403 if (COMPILER_64_BITTEST(rval64 , mmu_port)) { 3404 *enable = TRUE; 3405 } else { 3406 *enable = FALSE; 3407 } 3408 } 3409 return rv; 3410 } 3411 3412 /* 3413 * Function: 3414 * _bcm_ap_get_s1_node 3415 * Purpose: 3416 * finds the s1 node for given subport 3417 * Parameters: 3418 * unit - (IN) unit number 3419 * subport - (IN)gport of the subport 3420 * s1_node - (OUT) pointer to the s1 node 3421 * Returns: 3422 * BCM_E_XXX 3423 */ 3424 int _bcm_ap_get_s1_node(int unit, bcm_gport_t subport, 3425 _bcm_ap_cosq_node_t **s1_node) 3426 { 3427 3428 int local_port = 0; 3429 _bcm_ap_cosq_node_t *port_node; 3430 _bcm_ap_cosq_node_t *child_node; 3431 _bcm_ap_mmu_info_t *mmu_info; 3432 int s1_found = 0; 3433 if (!s1_node) 3434 { 3435 return BCM_E_INTERNAL; 3436 } 3437 if (!soc_feature(unit, 3438 soc_feature_mmu_hqos_four_level)) { 3439 return BCM_E_PARAM; 3440 } 3441 mmu_info = _bcm_ap_mmu_info[unit]; 3442 if(!(BCM_GPORT_IS_SET(subport) && 3443 _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, subport))) { 3444 return BCM_E_PARAM; 3445 } 3446 BCM_IF_ERROR_RETURN 3447 (_bcmi_coe_subport_physical_port_get(unit, subport, &local_port)); 3448 port_node = &mmu_info->sched_node[local_port]; 3449 if (!port_node->in_use) { 3450 return BCM_E_INTERNAL; 3451 } 3452 child_node = port_node->child; 3453 while (child_node) { 3454 if((child_node->port_gport == subport)) 3455 { 3456 s1_found = 1 ; 3457 break; 3458 } 3459 child_node = child_node->sibling; 3460 } 3461 if (!s1_found) 3462 { 3463 return BCM_E_NOT_FOUND; 3464 } 3465 *s1_node = child_node; 3466 return BCM_E_NONE; 3467 } 3468 3469 /* 3470 * Function: 3471 * _bcm_ap_allocate_coe_queues 3472 * Purpose: 3473 * allocates deallocated l2 queues for given subport 3474 * Parameters: 3475 * unit - (IN) unit number 3476 * s1_node - (IN) subport s1 node 3477 * enable - (IN) flag to enable/disable 3478 * Returns: 3479 * BCM_E_XXX 3480 */ 3481 int _bcm_ap_allocate_coe_queues(int unit ,_bcm_ap_cosq_node_t *s1_node, 3482 int enable) 3483 { 3484 int id = 0; 3485 int pipe = 0 ; 3486 _bcm_ap_pipe_resources_t *res; 3487 _bcm_ap_mmu_info_t *mmu_info; 3488 3489 mmu_info = _bcm_ap_mmu_info[unit]; 3490 pipe = 0; 3491 res = _BCM_AP_PRESOURCES(mmu_info, pipe); 3492 3493 if (enable) { 3494 /* The following logic is to make sure the id is always 3495 * multiple of 8 3496 */ 3497 BCM_IF_ERROR_RETURN( 3498 _bcm_ap_node_index_get(res->l2_queue_list.bits, 3499 res->num_base_queues, 3500 _BCM_AP_NUM_L2_UC_LEAVES_PER_PIPE , 3501 _AP_NUM_COS(unit), 3502 _AP_NUM_COS(unit), &id)); 3503 while (id % 8 != 0) { 3504 id = ((id + 8) & 0xfffffff8); 3505 if (id > _BCM_AP_NUM_L2_UC_LEAVES_PER_PIPE ) { 3506 return BCM_E_RESOURCE; 3507 } 3508 BCM_IF_ERROR_RETURN( 3509 _bcm_ap_node_index_get(res->l2_queue_list.bits, id, 3510 _BCM_AP_NUM_L2_UC_LEAVES_PER_PIPE, 3511 NUM_COS(unit), 3512 NUM_COS(unit), &id)); 3513 } 3514 _bcm_ap_node_index_set(&res->l2_queue_list, id, 3515 _AP_NUM_COS(unit)); 3516 s1_node->coe_base_index = id; 3517 } else 3518 { 3519 _bcm_ap_node_index_clear(&res->l2_queue_list, id, 3520 _AP_NUM_COS(unit)); 3521 s1_node->coe_base_index = -1; 3522 } 3523 return BCM_E_NONE; 3524 } 3525 3526 /* 3527 * Function: 3528 * _bcm_ap_coe_queue_offset_add 3529 * Purpose: 3530 * Programs the offset in voq_mod_map and voq_port_map table 3531 * Parameters: 3532 * unit - (IN) unit number 3533 * subport - (IN) subport gport 3534 * queue_id - (IN) base queue_id for the subport 3535 * Returns: 3536 * BCM_E_XXX 3537 */ 3538 int _bcm_ap_coe_queue_offset_add(int unit, int queue_id, 3539 bcm_gport_t subport) 3540 { 3541 bcm_module_t modid = 0; 3542 bcm_port_t port = 0; 3543 voq_port_map_entry_t *voq_port_map_entries = NULL; 3544 voq_mod_map_entry_t voq_mod_map; 3545 int rv = BCM_E_NONE; 3546 void *entries[1]; 3547 int port_offset = 0 ; 3548 int vpm_idx_old = 0 ; 3549 int baseq_old = 0 ; 3550 uint32 profile = 0 ; 3551 bcm_trunk_t trunk_id; 3552 int id; 3553 int port_base = 0; 3554 uint64 rval; 3555 int local_port = 0 ; 3556 BCM_IF_ERROR_RETURN( 3557 _bcm_esw_gport_resolve(unit, subport, &modid, &port, &trunk_id, &id)); 3558 BCM_IF_ERROR_RETURN 3559 (_bcmi_coe_subport_physical_port_get(unit, subport, &local_port)); 3560 /* program the voq port profiles. */ 3561 voq_port_map_entries = sal_alloc(sizeof(voq_port_map_entry_t)*128, 3562 "voq port map entries"); 3563 if (!voq_port_map_entries) { 3564 goto fail; 3565 } 3566 sal_memset(voq_port_map_entries, 0, sizeof(voq_port_map_entry_t)*128); 3567 entries[0] = voq_port_map_entries; 3568 rv = READ_VOQ_MOD_MAPm(unit, MEM_BLOCK_ALL, modid, &voq_mod_map); 3569 if (rv) { 3570 goto fail; 3571 } 3572 BCM_IF_ERROR_RETURN(READ_ING_COS_MODE_64r(unit, local_port, &rval)); 3573 port_base = soc_reg64_field32_get(unit, ING_COS_MODE_64r, rval, 3574 BASE_QUEUE_NUM_0f); 3575 if (!soc_mem_field32_get(unit, VOQ_MOD_MAPm, 3576 &voq_mod_map, VOQ_VALIDf)) { 3577 port_offset = 1; 3578 soc_mem_field32_set(unit, VOQ_PORT_MAPm, &voq_port_map_entries[port], 3579 VOQ_PORT_OFFSETf, port_offset); 3580 soc_mem_field32_set(unit, VOQ_MOD_MAPm, &voq_mod_map, 3581 VOQ_MOD_OFFSETf, queue_id - 1 - port_base ); 3582 soc_mem_field32_set(unit, VOQ_MOD_MAPm, &voq_mod_map, 3583 VOQ_VALIDf, 1); 3584 } else { 3585 vpm_idx_old = _AP_VPM_ENTRIES_PER_SET * 3586 soc_mem_field32_get(unit, VOQ_MOD_MAPm, &voq_mod_map, 3587 VOQ_MOD_PORT_PROFILE_INDEXf); 3588 rv = soc_profile_mem_get(unit, _bcm_ap_voq_port_map_profile[unit], 3589 vpm_idx_old, _AP_VPM_ENTRIES_PER_SET, entries ); 3590 3591 if (!(rv == SOC_E_NOT_FOUND || rv == SOC_E_NONE)) { 3592 goto fail; 3593 } 3594 3595 baseq_old = soc_mem_field32_get(unit, VOQ_MOD_MAPm, 3596 &voq_mod_map,VOQ_MOD_OFFSETf); 3597 3598 port_offset = (queue_id - baseq_old - port_base) & 0x3FFF; 3599 soc_mem_field32_set(unit, VOQ_PORT_MAPm, &voq_port_map_entries[port], 3600 VOQ_PORT_OFFSETf, port_offset); 3601 rv =soc_profile_mem_delete(unit, _bcm_ap_voq_port_map_profile[unit], 3602 vpm_idx_old); 3603 if (!(rv == SOC_E_NOT_FOUND || rv == SOC_E_NONE)) { 3604 goto fail; 3605 } 3606 } 3607 rv = soc_profile_mem_add(unit, 3608 _bcm_ap_voq_port_map_profile[unit], 3609 entries, 128, &profile); 3610 if (rv) { 3611 goto fail; 3612 } 3613 3614 soc_mem_field32_set(unit, VOQ_MOD_MAPm, &voq_mod_map, 3615 VOQ_MOD_PORT_PROFILE_INDEXf, profile/128); 3616 rv = soc_mem_write(unit, VOQ_MOD_MAPm, MEM_BLOCK_ALL, 3617 modid, &voq_mod_map); 3618 if (rv) { 3619 goto fail; 3620 } 3621 fail : 3622 if (voq_port_map_entries) 3623 { 3624 sal_free(voq_port_map_entries); 3625 } 3626 return rv; 3627 } 3628 3629 /* 3630 * Function: 3631 * _bcm_ap_coe_queue_offset_clear 3632 * Purpose: 3633 * clears the offset in voq_mod_map and voq_port_map table for the subport 3634 * Parameters: 3635 * unit - (IN) unit number 3636 * subport - (IN) subport gport 3637 * queue_id - (IN) base queue_id for the subport 3638 * Returns: 3639 * BCM_E_XXX 3640 */ 3641 int _bcm_ap_coe_queue_offset_clear(int unit, int queue_id, 3642 bcm_gport_t subport) 3643 { 3644 3645 bcm_module_t modid = 0; 3646 bcm_port_t port = 0; 3647 voq_port_map_entry_t *voq_port_map_entries = NULL; 3648 voq_mod_map_entry_t voq_mod_map; 3649 int rv = BCM_E_NONE; 3650 void *entries[1]; 3651 int vpm_idx_old = 0 ; 3652 int port_offset = 0 ; 3653 int i =0 ; 3654 int module_in_use = 0; 3655 uint32 profile = 0 ; 3656 bcm_trunk_t trunk_id; 3657 int id; 3658 3659 BCM_IF_ERROR_RETURN( 3660 _bcm_esw_gport_resolve( unit, subport, &modid, &port, &trunk_id, &id)); 3661 /* program the voq port profiles. */ 3662 voq_port_map_entries = sal_alloc(sizeof(voq_port_map_entry_t)*128, 3663 "voq port map entries"); 3664 if (!voq_port_map_entries) { 3665 goto fail; 3666 } 3667 sal_memset(voq_port_map_entries, 0, sizeof(voq_port_map_entry_t)*128); 3668 entries[0] = voq_port_map_entries; 3669 rv = READ_VOQ_MOD_MAPm(unit, MEM_BLOCK_ALL, modid, &voq_mod_map); 3670 if (rv) { 3671 goto fail; 3672 } 3673 if (!soc_mem_field32_get(unit, VOQ_MOD_MAPm, 3674 &voq_mod_map, VOQ_VALIDf)) { 3675 rv = BCM_E_NOT_FOUND; 3676 goto fail; 3677 } 3678 3679 vpm_idx_old = _AP_VPM_ENTRIES_PER_SET * 3680 soc_mem_field32_get(unit, VOQ_MOD_MAPm, &voq_mod_map, 3681 VOQ_MOD_PORT_PROFILE_INDEXf); 3682 rv = soc_profile_mem_get(unit, _bcm_ap_voq_port_map_profile[unit], 3683 vpm_idx_old, _AP_VPM_ENTRIES_PER_SET, entries ); 3684 3685 if (!(rv == SOC_E_NOT_FOUND || rv == SOC_E_NONE)) { 3686 goto fail; 3687 } 3688 3689 3690 3691 port_offset = 0; 3692 soc_mem_field32_set(unit, VOQ_PORT_MAPm, &voq_port_map_entries[port], 3693 VOQ_PORT_OFFSETf, port_offset); 3694 rv =soc_profile_mem_delete(unit, _bcm_ap_voq_port_map_profile[unit], 3695 vpm_idx_old); 3696 if (rv) { 3697 goto fail; 3698 } 3699 3700 for (i = 0; i < _AP_VPM_ENTRIES_PER_SET; i++) { 3701 if (soc_mem_field32_get(unit, VOQ_PORT_MAPm, 3702 &voq_port_map_entries[i], VOQ_PORT_OFFSETf)) { 3703 module_in_use = 1; 3704 break; 3705 } 3706 } 3707 if (module_in_use) { 3708 rv = soc_profile_mem_add(unit, 3709 _bcm_ap_voq_port_map_profile[unit], 3710 entries, 128, &profile); 3711 if (rv) { 3712 goto fail; 3713 } 3714 soc_mem_field32_set(unit, VOQ_MOD_MAPm, &voq_mod_map, 3715 VOQ_MOD_PORT_PROFILE_INDEXf, profile/128); 3716 } else 3717 { 3718 soc_mem_field32_set(unit, VOQ_MOD_MAPm, &voq_mod_map, 3719 VOQ_VALIDf, 0); 3720 soc_mem_field32_set(unit, VOQ_MOD_MAPm, &voq_mod_map, 3721 VOQ_MOD_OFFSETf, 0 ); 3722 } 3723 3724 rv = soc_mem_write(unit, VOQ_MOD_MAPm, MEM_BLOCK_ALL, 3725 modid, &voq_mod_map); 3726 fail : 3727 if (voq_port_map_entries) 3728 { 3729 sal_free(voq_port_map_entries); 3730 } 3731 return rv; 3732 } 3733 3734 /* 3735 * Function: 3736 * _bcm_ap_mmu_port_coe_control 3737 * Purpose: 3738 * Programs the ing_cos_mode to enable/disable subport in the physical port 3739 * Parameters: 3740 * unit - (IN) unit number 3741 * local_port - (IN) physical port 3742 * eanble - (IN) flag to control enable/disable 3743 * Returns: 3744 * BCM_E_XXX 3745 */ 3746 int _bcm_ap_mmu_port_coe_control(int unit ,int local_port, int enable) 3747 { 3748 uint64 rval; 3749 3750 BCM_IF_ERROR_RETURN(READ_ING_COS_MODE_64r(unit, local_port, &rval)); 3751 soc_reg64_field32_set(unit, ING_COS_MODE_64r, &rval, USE_MODf, enable) ; 3752 soc_reg64_field32_set(unit, ING_COS_MODE_64r, &rval, USE_PORTf, enable) ; 3753 BCM_IF_ERROR_RETURN(WRITE_ING_COS_MODE_64r(unit, local_port, rval)); 3754 return BCM_E_NONE; 3755 3756 } 3757 3758 /* 3759 * Function: 3760 * bcm_ap_cosq_gport_add 3761 * Purpose: 3762 * Create a cosq gport structure 3763 * Parameters: 3764 * unit - (IN) unit number 3765 * port - (IN) port number 3766 * numq - (IN) number of COS queues 3767 * flags - (IN) flags (BCM_COSQ_GPORT_XXX) 3768 * gport - (OUT) GPORT identifier 3769 * Returns: 3770 * BCM_E_XXX 3771 */ 3772 int 3773 bcm_ap_cosq_gport_add(int unit, bcm_gport_t port, int numq, uint32 flags, 3774 bcm_gport_t *gport) 3775 { 3776 _bcm_ap_mmu_info_t *mmu_info; 3777 _bcm_ap_cosq_node_t *node = NULL; 3778 _bcm_ap_cosq_node_t *s1_node = NULL ; 3779 _bcm_ap_cosq_port_info_t *port_info; 3780 uint32 sched_encap; 3781 _bcm_ap_pipe_resources_t *res; 3782 int phy_port, mmu_port, local_port; 3783 int id, ii, q_base, pipe, qmin, qmax; 3784 bcm_gport_t tmp_gport; 3785 bcm_gport_t s1_sched; 3786 3787 3788 LOG_INFO(BSL_LS_BCM_COSQ, 3789 (BSL_META_U(unit, 3790 "bcm_ap_cosq_gport_add: unit=%d port=0x%x numq=%d flags=0x%x\n"), 3791 unit, port, numq, flags)); 3792 3793 if (!soc_feature(unit, soc_feature_ets)) { 3794 return BCM_E_UNAVAIL; 3795 } 3796 3797 if (gport == NULL) { 3798 return BCM_E_PARAM; 3799 } 3800 3801 if (_bcm_ap_mmu_info[unit] == NULL) { 3802 return BCM_E_INIT; 3803 } 3804 3805 if (!soc_feature(unit, 3806 soc_feature_mmu_hqos_four_level)) { 3807 if(_BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port)){ 3808 return BCM_E_UNAVAIL; 3809 } 3810 } 3811 if(_BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port)){ 3812 BCM_IF_ERROR_RETURN( 3813 _bcmi_coe_subport_physical_port_get(unit, port, &local_port)); 3814 } else { 3815 BCM_IF_ERROR_RETURN 3816 (_bcm_ap_cosq_localport_resolve(unit, port, &local_port)); 3817 } 3818 if (local_port < 0) { 3819 return BCM_E_PORT; 3820 } 3821 3822 mmu_info = _bcm_ap_mmu_info[unit]; 3823 3824 port_info = &mmu_info->port_info[local_port]; 3825 pipe = _BCM_AP_PORT_TO_PIPE(unit, local_port); 3826 res = _BCM_AP_PRESOURCES(mmu_info, pipe); 3827 #if 0 3828 if (!mmu_info->ets_mode) { 3829 /* cleanup the default lls setup */ 3830 SOC_IF_ERROR_RETURN(soc_apache_lls_reset(unit)); 3831 SOC_IF_ERROR_RETURN(soc_apache_lb_lls_init(unit)); 3832 mmu_info->ets_mode = 1; 3833 } 3834 #endif 3835 /* Check Alignment request is not for unsupported type */ 3836 if (flags & BCM_COSQ_GPORT_SCHEDULER_PFC_ALIGN) { 3837 if (!(flags == (BCM_COSQ_GPORT_SCHEDULER | BCM_COSQ_GPORT_SCHEDULER_PFC_ALIGN))) { 3838 return BCM_E_PARAM; 3839 } 3840 } 3841 3842 switch (flags) { 3843 case BCM_COSQ_GPORT_UCAST_QUEUE_GROUP: 3844 if (numq != 1) { 3845 return BCM_E_PARAM; 3846 } 3847 3848 if (IS_CPU_PORT(unit, local_port) || IS_LB_PORT(unit, local_port)) { 3849 return BCM_E_PARAM; 3850 } 3851 3852 if (_BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port)){ 3853 BCM_IF_ERROR_RETURN( 3854 _bcm_ap_get_s1_node( unit, port, &s1_node)); 3855 if (s1_node->coe_base_index == -1) { 3856 _bcm_ap_allocate_coe_queues(unit, s1_node, 1); 3857 _bcm_ap_coe_queue_offset_add(unit, s1_node->coe_base_index, 3858 port); 3859 } 3860 for (id = s1_node->coe_base_index; 3861 id < (s1_node->coe_base_index + _AP_NUM_COS(unit)); id++) { 3862 if (!res->p_queue_node[id].in_use) { 3863 s1_node->coe_num_l2++; 3864 break; 3865 } 3866 } 3867 if (id == (s1_node->coe_base_index + NUM_COS(unit))) 3868 { 3869 return BCM_E_RESOURCE; 3870 } 3871 } else { 3872 for (id = port_info->uc_base; id < port_info->uc_limit; id++) { 3873 if (res->p_queue_node[id].numq == 0) { 3874 break; 3875 } 3876 } 3877 if ((id == port_info->uc_limit) && 3878 (IS_AP_HSP_PORT(unit, local_port))) { 3879 return BCM_E_RESOURCE; 3880 } 3881 if (id == port_info->uc_limit) { 3882 BCM_IF_ERROR_RETURN( 3883 _bcm_ap_node_index_get(res->l2_queue_list.bits, 0, 3884 _BCM_AP_NUM_L2_UC_LEAVES_PER_PIPE, numq, 3885 1, &id)); 3886 3887 _bcm_ap_node_index_set(&res->l2_queue_list, id, 1); 3888 } 3889 } 3890 3891 BCM_GPORT_UCAST_QUEUE_GROUP_SYSQID_SET(*gport, local_port, id); 3892 node = &res->p_queue_node[id]; 3893 node->gport = *gport; 3894 node->numq = numq; 3895 node->level = SOC_APACHE_NODE_LVL_L2; 3896 if (_BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port)) 3897 { 3898 node->hw_cosq = id - s1_node->coe_base_index; 3899 } else 3900 { 3901 node->hw_cosq = id - port_info->uc_base; 3902 } 3903 if (IS_AP_HSP_PORT(unit, local_port)) { 3904 phy_port = SOC_INFO(unit).port_l2p_mapping[local_port]; 3905 mmu_port = SOC_INFO(unit).port_p2m_mapping[phy_port]; 3906 node->hw_index = _BCM_AP_HSP_L2_INDEX(unit, mmu_port, node->hw_cosq); 3907 } else { 3908 node->hw_index = soc_apache_l2_hw_index(unit, id, 1); 3909 } 3910 node->local_port = local_port; 3911 node->remote_modid = -1; 3912 node->remote_port = -1; 3913 node->type = _BCM_AP_NODE_UCAST; 3914 node->in_use = TRUE; 3915 node->port_gport = port; 3916 break; 3917 3918 case BCM_COSQ_GPORT_MCAST_QUEUE_GROUP: 3919 if (numq != 1) { 3920 return BCM_E_PARAM; 3921 } 3922 3923 for (id = port_info->mc_base; id < port_info->mc_limit; id++) { 3924 if (res->p_mc_queue_node[id].numq == 0) { 3925 break; 3926 } 3927 } 3928 3929 if (id == port_info->mc_limit) { 3930 return BCM_E_RESOURCE; 3931 } 3932 3933 /* set index bits */ 3934 BCM_GPORT_MCAST_QUEUE_GROUP_SYSQID_SET(*gport, local_port, id); 3935 node = &res->p_mc_queue_node[id]; 3936 node->gport = *gport; 3937 node->numq = numq; 3938 node->level = SOC_APACHE_NODE_LVL_L2; 3939 node->type = _BCM_AP_NODE_MCAST; 3940 node->hw_cosq = id - port_info->mc_base; 3941 if (IS_AP_HSP_PORT(unit, local_port)) { 3942 phy_port = SOC_INFO(unit).port_l2p_mapping[local_port]; 3943 mmu_port = SOC_INFO(unit).port_p2m_mapping[phy_port]; 3944 node->hw_index = _BCM_AP_HSP_L2_INDEX(unit, mmu_port, node->hw_cosq); 3945 node->hw_index = soc_apache_l2_hw_index(unit, node->hw_index, 0); 3946 } else { 3947 node->hw_index = soc_apache_l2_hw_index(unit, id, 0); 3948 } 3949 node->local_port = local_port; 3950 node->remote_modid = -1; 3951 node->remote_port = -1; 3952 node->in_use = TRUE; 3953 node->port_gport = port; 3954 break; 3955 3956 3957 3958 case BCM_COSQ_GPORT_SUBSCRIBER: 3959 case BCM_COSQ_GPORT_VIRTUAL_PORT: 3960 case BCM_COSQ_GPORT_VLAN_UCAST_QUEUE_GROUP: 3961 /* Service Queueing are outside default queues. Hence NO alignment 3962 * required. 3963 */ 3964 BCM_IF_ERROR_RETURN( 3965 _bcm_ap_node_index_get(res->l2_queue_list.bits, res->num_base_queues, 3966 _BCM_AP_NUM_L2_UC_LEAVES_PER_PIPE, numq, 3967 1, &q_base)); 3968 3969 _bcm_ap_node_index_set(&res->l2_queue_list, q_base, numq); 3970 qmin = res->num_base_queues + (pipe * _BCM_AP_NUM_L2_UC_LEAVES_PER_PIPE); 3971 qmax = (pipe + 1) * _BCM_AP_NUM_L2_UC_LEAVES_PER_PIPE; 3972 3973 id = q_base; 3974 3975 for (ii = 0; ii < numq; ii++, id++) { 3976 BCM_GPORT_UCAST_QUEUE_GROUP_SYSQID_SET(tmp_gport, local_port, id); 3977 node= &res->p_queue_node[id]; 3978 node->gport = tmp_gport; 3979 node->numq = numq - ii; 3980 node->level = SOC_APACHE_NODE_LVL_L2; 3981 node->type = (flags == BCM_COSQ_GPORT_VIRTUAL_PORT) ? 3982 _BCM_AP_NODE_VM_UCAST : _BCM_AP_NODE_SERVICE_UCAST; 3983 node->hw_index = q_base + ii + (pipe * _BCM_AP_NUM_L2_UC_LEAVES_PER_PIPE); 3984 /* by default assign the cosq on order of order of alocation, 3985 * can be overriddedn by cos_mapping_set */ 3986 node->hw_cosq = ii; 3987 node->local_port = local_port; 3988 node->remote_modid = -1; 3989 node->remote_port = -1; 3990 node->in_use = TRUE; 3991 node->port_gport = port; 3992 if (ii == 0) { 3993 *gport = tmp_gport; 3994 } 3995 } 3996 break; 3997 3998 case BCM_COSQ_GPORT_DESTMOD_UCAST_QUEUE_GROUP: 3999 if (numq != 1) { 4000 return BCM_E_PARAM; 4001 } 4002 4003 if (!IS_HG_PORT(unit, local_port)) { 4004 return BCM_E_PORT; 4005 } 4006 4007 qmin = res->num_base_queues; 4008 qmax = _BCM_AP_NUM_L2_UC_LEAVES_PER_PIPE; 4009 for (id = qmin; id < qmax; id++) { 4010 if (res->p_queue_node[id].numq == 0) { 4011 break; 4012 } 4013 } 4014 4015 if (id >= qmax) { 4016 return BCM_E_RESOURCE; 4017 } 4018 4019 BCM_GPORT_UCAST_QUEUE_GROUP_SYSQID_SET(*gport, local_port, id); 4020 node = &res->p_queue_node[id]; 4021 node->gport = *gport; 4022 node->numq = numq; 4023 node->level = SOC_APACHE_NODE_LVL_L2; 4024 node->type = _BCM_AP_NODE_VOQ; 4025 node->hw_index = -1; 4026 /* by default assign the cosq on order of order of alocation, 4027 * can be overriddedn by cos_mapping_set */ 4028 node->hw_cosq = -1; 4029 node->local_port = local_port; 4030 node->remote_modid = -1; 4031 node->remote_port = -1; 4032 node->in_use = TRUE; 4033 node->port_gport = port; 4034 break; 4035 4036 case BCM_COSQ_GPORT_SCHEDULER: 4037 case BCM_COSQ_GPORT_SCHEDULER | BCM_COSQ_GPORT_SCHEDULER_PFC_ALIGN: 4038 if (numq < -1) { 4039 return BCM_E_PARAM; 4040 } 4041 for (id = _BCM_AP_NUM_PORT_SCHEDULERS; 4042 id < _BCM_AP_NUM_TOTAL_SCHEDULERS; id++) { 4043 if (mmu_info->sched_node[id].in_use == FALSE) { 4044 node = &mmu_info->sched_node[id]; 4045 node->in_use = TRUE; 4046 break; 4047 } 4048 } 4049 if (!node) { 4050 return BCM_E_RESOURCE; 4051 } 4052 4053 node = &mmu_info->sched_node[id]; 4054 sched_encap = (id << 8) | local_port; 4055 BCM_GPORT_SCHEDULER_SET(*gport, sched_encap); 4056 node->gport = *gport; 4057 node->numq = numq; 4058 node->local_port = local_port; 4059 node->type = _BCM_AP_NODE_SCHEDULER; 4060 node->attached_to_input = -1; 4061 node->port_gport = port; 4062 if (flags & BCM_COSQ_GPORT_SCHEDULER_PFC_ALIGN) { 4063 node->node_align_value = _BCM_AP_START_INDEX_ALIGN_PFC; 4064 } 4065 break; 4066 4067 case BCM_COSQ_GPORT_WITH_ID: 4068 case 0: 4069 if (numq < -1) { 4070 return BCM_E_PARAM; 4071 } 4072 4073 /* this is a port level scheduler */ 4074 id = local_port; 4075 4076 if ( id < 0 || id >= _BCM_AP_NUM_PORT_SCHEDULERS) { 4077 return BCM_E_PARAM; 4078 } 4079 if (IS_AP_HSP_PORT(unit, local_port)) { 4080 if (numq > _BCM_AP_HSP_PORT_MAX_L0) { 4081 return BCM_E_PARAM; 4082 } 4083 } 4084 node = &mmu_info->sched_node[id]; 4085 sched_encap = (id << 8) | local_port; 4086 BCM_GPORT_SCHEDULER_SET(*gport, sched_encap); 4087 node->gport = *gport; 4088 node->level = SOC_APACHE_NODE_LVL_ROOT; 4089 node->type = _BCM_AP_NODE_SCHEDULER; 4090 phy_port = SOC_INFO(unit).port_l2p_mapping[local_port]; 4091 mmu_port = SOC_INFO(unit).port_p2m_mapping[phy_port]; 4092 node->hw_index = mmu_port; 4093 if (IS_AP_HSP_PORT(unit, local_port)) { 4094 node->numq = _BCM_AP_HSP_PORT_MAX_L0; 4095 } else { 4096 node->numq = -1; 4097 } 4098 node->local_port = local_port; 4099 node->in_use = TRUE; 4100 node->attached_to_input = 0; 4101 node->port_gport = port; 4102 if (!(soc_feature(unit,soc_feature_mmu_hqos_four_level)) && 4103 !(IS_AP_HSP_PORT(unit, local_port))) 4104 { 4105 node->numq = 1; 4106 BCM_IF_ERROR_RETURN 4107 (bcm_ap_cosq_gport_add(unit, port, numq, 4108 BCM_COSQ_GPORT_SCHEDULER, 4109 &s1_sched)); 4110 BCM_IF_ERROR_RETURN 4111 (bcm_ap_cosq_gport_attach(unit, s1_sched, *gport, 0)); 4112 *gport = s1_sched ; 4113 } 4114 break; 4115 4116 default: 4117 return BCM_E_PARAM; 4118 } 4119 4120 LOG_INFO(BSL_LS_BCM_COSQ, 4121 (BSL_META_U(unit, 4122 " gport=0x%x\n"), 4123 *gport)); 4124 4125 return BCM_E_NONE; 4126 } 4127 4128 /* 4129 * Function: 4130 * bcm_ap_cosq_gport_detach 4131 * Purpose: 4132 * Detach sched_port from the specified index (cosq) of parent_port 4133 * Parameters: 4134 * unit - (IN) unit number 4135 * sched_port - (IN) scheduler GPORT identifier 4136 * parent_port - (IN) GPORT to detach from 4137 * cosq - (IN) COS queue to detach from 4138 * Returns: 4139 * BCM_E_XXX 4140 */ 4141 int 4142 bcm_ap_cosq_gport_detach(int unit, bcm_gport_t sched_gport, 4143 bcm_gport_t parent_gport, bcm_cos_queue_t cosq) 4144 { 4145 _bcm_ap_cosq_node_t *sched_node, *parent_node = NULL, *prev_node; 4146 _bcm_ap_cosq_node_t *child_node = NULL; 4147 bcm_port_t sched_port, parent_port = -1; 4148 _bcm_ap_cosq_node_t *parent; 4149 _bcm_ap_cosq_list_t *list = NULL; 4150 _bcm_ap_mmu_info_t *mmu_info; 4151 _bcm_ap_pipe_resources_t * res; 4152 _bcm_ap_cosq_port_info_t *port_info; 4153 int start = 0, end = 0; 4154 int base_index; 4155 int subport_enabled = 0 ; 4156 int hw_index = 0 ; 4157 if (_bcm_ap_mmu_info[unit] == NULL) { 4158 return BCM_E_INIT; 4159 } 4160 4161 if ((BCM_GPORT_IS_UCAST_QUEUE_GROUP(parent_gport)) || 4162 (BCM_GPORT_IS_MCAST_QUEUE_GROUP(parent_gport)) || 4163 (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(parent_gport))) { 4164 return BCM_E_PARAM; 4165 } 4166 4167 BCM_IF_ERROR_RETURN 4168 (_bcm_ap_cosq_node_get(unit, sched_gport, 0, NULL, &sched_port, NULL, 4169 &sched_node)); 4170 4171 if (sched_node->attached_to_input < 0) { 4172 /* Not attached yet */ 4173 return BCM_E_PORT; 4174 } 4175 4176 if (parent_gport != BCM_GPORT_INVALID) { 4177 if (BCM_GPORT_IS_SCHEDULER(parent_gport) || 4178 BCM_GPORT_IS_MODPORT(parent_gport) || 4179 BCM_GPORT_IS_LOCAL(parent_gport)) { 4180 BCM_IF_ERROR_RETURN 4181 (_bcm_ap_cosq_node_get(unit, parent_gport, 0, NULL, 4182 &parent_port, NULL, &parent_node)); 4183 } else { 4184 if (!(BCM_GPORT_IS_SCHEDULER(sched_gport) || 4185 BCM_GPORT_IS_UCAST_QUEUE_GROUP(sched_gport) || 4186 BCM_GPORT_IS_MCAST_QUEUE_GROUP(sched_gport)) || 4187 (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(parent_gport))) { 4188 return BCM_E_PARAM; 4189 } 4190 else { 4191 BCM_IF_ERROR_RETURN 4192 (_bcm_ap_cosq_localport_resolve(unit, parent_gport, 4193 &parent_port)); 4194 parent_node = NULL; 4195 } 4196 } 4197 } 4198 4199 if (parent_port == -1) { 4200 return BCM_E_PORT; 4201 } 4202 4203 mmu_info = _bcm_ap_mmu_info[unit]; 4204 port_info = &mmu_info->port_info[parent_port]; 4205 res = port_info->resources; 4206 4207 if (sched_port != parent_port) { 4208 return BCM_E_PORT; 4209 } 4210 4211 if (sched_node->parent != parent_node) { 4212 return BCM_E_PORT; 4213 } 4214 4215 if ((cosq < -1) || 4216 (parent_node && (parent_node->numq != -1) && (cosq >= parent_node->numq))) { 4217 return BCM_E_PARAM; 4218 } 4219 4220 if (cosq != -1) { 4221 if (sched_node->attached_to_input != cosq) { 4222 return BCM_E_PARAM; 4223 } 4224 } 4225 4226 if (sched_node->type == _BCM_AP_NODE_SERVICE_UCAST) { 4227 end = sched_node->numq; 4228 } else { 4229 end = 1; 4230 } 4231 4232 for (start = 0; start < end; start++) { 4233 if (sched_node->parent != NULL) { 4234 BCM_IF_ERROR_RETURN( 4235 soc_apache_cosq_set_sched_parent(unit, parent_port, 4236 sched_node->level, sched_node->hw_index, 4237 sched_node->parent->hw_index, 0)); 4238 /* unresolve the node - delete this node from parent's child list */ 4239 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_node_unresolve(unit, sched_node, cosq)); 4240 4241 /* now remove from the sw tree */ 4242 parent = sched_node->parent; 4243 if (sched_node->parent->child == sched_node) { 4244 sched_node->parent->child = sched_node->sibling; 4245 } else { 4246 prev_node = sched_node->parent->child; 4247 while (prev_node != NULL && prev_node->sibling != sched_node) { 4248 prev_node = prev_node->sibling; 4249 } 4250 if (prev_node == NULL) { 4251 return BCM_E_INTERNAL; 4252 } 4253 prev_node->sibling = sched_node->sibling; 4254 } 4255 sched_node->parent = NULL; 4256 sched_node->sibling = NULL; 4257 sched_node->attached_to_input = -1; 4258 hw_index = sched_node->hw_index; 4259 if (!IS_AP_HSP_PORT(unit, parent_port)) { 4260 switch (parent->level) { 4261 case SOC_APACHE_NODE_LVL_ROOT: 4262 list = &res->s1_sched_list; 4263 sched_node->hw_index = -1; 4264 break; 4265 case SOC_APACHE_NODE_LVL_S1: 4266 if (IS_CPU_PORT(unit, parent_port)) { 4267 list = &res->cpu_l0_sched_list; 4268 } else { 4269 list = &res->l0_sched_list; 4270 } 4271 sched_node->hw_index = -1; 4272 break; 4273 case SOC_APACHE_NODE_LVL_L0: 4274 list = &res->l1_sched_list; 4275 sched_node->hw_index = -1; 4276 break; 4277 case SOC_APACHE_NODE_LVL_L1: 4278 list = &res->l2_queue_list; 4279 break; 4280 default: 4281 break; 4282 } 4283 4284 if (!BCM_GPORT_IS_MCAST_QUEUE_GROUP(sched_gport)){ 4285 if (parent->numq == -1) { 4286 BCM_IF_ERROR_RETURN(_bcm_ap_node_index_clear(list, 4287 hw_index, 1)); 4288 } else if ((parent->child == NULL) && 4289 (sched_node->level != SOC_APACHE_NODE_LVL_L2)) { 4290 if (list) { 4291 base_index = parent->base_index; 4292 if (IS_CPU_PORT(unit, parent_port) && 4293 (sched_node->level == SOC_APACHE_NODE_LVL_L0)) { 4294 base_index = parent->base_index - _BCM_AP_CPU_PORT_L0_MIN; 4295 } 4296 BCM_IF_ERROR_RETURN(_bcm_ap_node_index_clear(list, 4297 base_index, parent->base_size)); 4298 } 4299 list = NULL; 4300 parent->base_index = -1; 4301 parent->base_size = 0; 4302 } 4303 } 4304 /* Indexes that are allocated statically is not released to the pool*/ 4305 if ((sched_node->level == SOC_APACHE_NODE_LVL_L2) && 4306 (BCM_GPORT_IS_UCAST_QUEUE_GROUP(sched_gport))){ 4307 if ((sched_node->type == _BCM_AP_NODE_VOQ)) { 4308 _bcm_ap_node_index_clear(list, sched_node->hw_index, 1); 4309 sched_node->hw_index = -1; 4310 } 4311 } 4312 } 4313 } 4314 if ((sched_node->type == _BCM_AP_NODE_SERVICE_UCAST) && 4315 ((start + 1) < end)){ 4316 BCM_IF_ERROR_RETURN 4317 (_bcm_ap_cosq_node_get(unit, sched_gport, start + 1, NULL, 4318 &sched_port, NULL, &sched_node)); 4319 if (!sched_node) { 4320 return BCM_E_NOT_FOUND; 4321 } 4322 } 4323 } 4324 4325 if (soc_feature(unit, 4326 soc_feature_mmu_hqos_four_level) && 4327 sched_node->level == SOC_APACHE_NODE_LVL_S1) { 4328 child_node = parent_node->child; 4329 while(child_node) { 4330 if(_BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, 4331 child_node->port_gport)) { 4332 subport_enabled = 1; 4333 break; 4334 } 4335 child_node = child_node->sibling; 4336 } 4337 if (!subport_enabled) { 4338 BCM_IF_ERROR_RETURN( 4339 _bcm_ap_mmu_port_coe_control(unit, 4340 sched_node->local_port, 0)); 4341 } 4342 } 4343 LOG_INFO(BSL_LS_BCM_COSQ, 4344 (BSL_META_U(unit, 4345 " hw_cosq=%d\n"), 4346 sched_node->attached_to_input)); 4347 4348 return BCM_E_NONE; 4349 } 4350 4351 /* 4352 * Function: 4353 * bcm_ap_cosq_gport_delete 4354 * Purpose: 4355 * Destroy a cosq gport structure 4356 * Parameters: 4357 * unit - (IN) unit number 4358 * gport - (IN) GPORT identifier 4359 * Returns: 4360 * BCM_E_XXX 4361 */ 4362 int 4363 bcm_ap_cosq_gport_delete(int unit, bcm_gport_t gport) 4364 { 4365 _bcm_ap_cosq_node_t *node, *tnode, *base_node; 4366 _bcm_ap_cosq_node_t * s1_node = NULL ; 4367 int ii, local_port, phy_port, mmu_port, hw_index; 4368 _bcm_ap_mmu_info_t *mmu_info; 4369 soc_info_t *si; 4370 bcm_gport_t parent_gport = 0 ; 4371 int level = 0 ; 4372 _bcm_ap_pipe_resources_t * res; 4373 _bcm_ap_cosq_port_info_t *port_info; 4374 LOG_INFO(BSL_LS_BCM_COSQ, 4375 (BSL_META_U(unit, 4376 "bcm_ap_cosq_gport_delete: unit=%d gport=0x%x\n"), 4377 unit, gport)); 4378 4379 node = NULL; 4380 base_node= NULL; 4381 4382 mmu_info = _bcm_ap_mmu_info[unit]; 4383 si = &SOC_INFO(unit); 4384 if (!soc_feature(unit, soc_feature_ets)) { 4385 return BCM_E_UNAVAIL; 4386 } 4387 4388 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 4389 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) || 4390 (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport)) || 4391 BCM_GPORT_IS_SCHEDULER(gport)) { 4392 BCM_IF_ERROR_RETURN 4393 (_bcm_ap_cosq_node_get(unit, gport, 0, NULL, &local_port, NULL, &node)); 4394 port_info = &mmu_info->port_info[local_port]; 4395 res = port_info->resources; 4396 4397 } else if(_BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, gport)) { 4398 BCM_IF_ERROR_RETURN 4399 (_bcm_ap_get_s1_node(unit, gport, &node)); 4400 BCM_IF_ERROR_RETURN 4401 (_bcmi_coe_subport_physical_port_get(unit, gport, &local_port)); 4402 port_info = &mmu_info->port_info[local_port]; 4403 res = port_info->resources; 4404 4405 } else { 4406 BCM_IF_ERROR_RETURN( 4407 bcm_esw_port_local_get(unit, gport, &local_port)); 4408 if (local_port >= _BCM_AP_MAX_PORT) { 4409 return BCM_E_PORT; 4410 } 4411 4412 port_info = &mmu_info->port_info[local_port]; 4413 res = port_info->resources; 4414 phy_port = si->port_l2p_mapping[local_port]; 4415 mmu_port = si->port_p2m_mapping[phy_port]; 4416 hw_index = _BCM_AP_ROOT_SCHED_INDEX(unit, mmu_port); 4417 4418 for (ii = 0; ii < _BCM_AP_NUM_TOTAL_SCHEDULERS; ii++) { 4419 tnode = &mmu_info->sched_node[ii]; 4420 if (tnode->in_use == FALSE) { 4421 continue; 4422 } 4423 if ((tnode->level == SOC_APACHE_NODE_LVL_ROOT) && 4424 (tnode->hw_index == hw_index) && 4425 (tnode->local_port == local_port)) { 4426 /* check both mmu_port(unique only within a pipe) 4427 and local_port(unique witin system) to get the 4428 correct node */ 4429 node = tnode; 4430 break; 4431 } 4432 } 4433 if (node == NULL) { 4434 return BCM_E_NONE; 4435 } 4436 } 4437 if (!node->in_use) { 4438 return BCM_E_NONE; 4439 } 4440 level = node->level; 4441 if (node->parent) 4442 { 4443 parent_gport = node->parent->gport; 4444 } 4445 while(node->child != NULL) { 4446 BCM_IF_ERROR_RETURN(bcm_ap_cosq_gport_delete(unit, node->child->gport)); 4447 } 4448 4449 if (!soc_feature(unit, soc_feature_mmu_hqos_four_level) && 4450 (level == SOC_APACHE_NODE_LVL_ROOT) && (!node->in_use)) 4451 { 4452 return BCM_E_NONE; 4453 } 4454 if (node->level != SOC_APACHE_NODE_LVL_ROOT && node->attached_to_input >= 0) { 4455 BCM_IF_ERROR_RETURN 4456 (bcm_ap_cosq_gport_detach(unit, node->gport, 4457 node->parent->gport, node->attached_to_input)); 4458 } 4459 4460 4461 if (soc_feature(unit, soc_feature_mmu_hqos_four_level)) { 4462 if ((node->level == SOC_APACHE_NODE_LVL_L2) && 4463 _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, node->port_gport)) { 4464 BCM_IF_ERROR_RETURN 4465 (_bcm_ap_get_s1_node(unit, node->port_gport, &s1_node)); 4466 s1_node->coe_num_l2--; 4467 if (!s1_node->coe_num_l2) { 4468 BCM_IF_ERROR_RETURN 4469 (_bcm_ap_coe_queue_offset_clear(unit, s1_node->coe_base_index, 4470 node->port_gport)); 4471 BCM_IF_ERROR_RETURN 4472 (_bcm_ap_allocate_coe_queues(unit, s1_node, 0)); 4473 } 4474 } 4475 } 4476 if ((node->type == _BCM_AP_NODE_VOQ) && 4477 (node->remote_modid > 0)) { 4478 _bcm_ap_voq_next_base_node_get (unit, local_port, 4479 node->remote_modid, &base_node); 4480 if (base_node != NULL) { 4481 BCM_PBMP_ASSIGN(base_node->fabric_pbmp, 4482 node->fabric_pbmp); 4483 } 4484 } 4485 4486 if ((node->level == SOC_APACHE_NODE_LVL_L2) && 4487 (BCM_GPORT_IS_UCAST_QUEUE_GROUP(node->gport)) && 4488 (node->type != _BCM_AP_NODE_VOQ) && 4489 ((node->hw_index < port_info->uc_base) || 4490 (node->hw_index >= port_info->uc_limit))) 4491 { 4492 _bcm_ap_node_index_clear(&res->l2_queue_list, 4493 node->hw_index, 1); 4494 node->hw_index = -1; 4495 } 4496 if (node->cosq_map != NULL) { 4497 sal_free(node->cosq_map); 4498 } 4499 if ((!(soc_feature(unit, soc_feature_mmu_hqos_four_level)) && 4500 node->level == SOC_APACHE_NODE_LVL_S1) && parent_gport ) 4501 { 4502 BCM_IF_ERROR_RETURN(bcm_ap_cosq_gport_delete(unit, parent_gport)); 4503 } 4504 if (IS_AP_HSP_PORT(unit, local_port)) { 4505 BCM_IF_ERROR_RETURN 4506 (_bcm_ap_cosq_clear_child_list(unit, node)); 4507 } 4508 _BCM_AP_COSQ_NODE_INIT(node); 4509 return BCM_E_NONE; 4510 } 4511 4512 /* 4513 * Function: 4514 * bcm_ap_cosq_gport_get 4515 * Purpose: 4516 * Get a cosq gport structure 4517 * Parameters: 4518 * unit - (IN) unit number 4519 * gport - (IN) GPORT identifier 4520 * port - (OUT) port number 4521 * numq - (OUT) number of COS queues 4522 * flags - (OUT) flags (BCM_COSQ_GPORT_XXX) 4523 * Returns: 4524 * BCM_E_XXX 4525 */ 4526 int 4527 bcm_ap_cosq_gport_get(int unit, bcm_gport_t gport, bcm_gport_t *port, 4528 int *numq, uint32 *flags) 4529 { 4530 _bcm_ap_cosq_node_t *node; 4531 bcm_module_t modid; 4532 bcm_port_t local_port; 4533 int id; 4534 _bcm_gport_dest_t dest; 4535 4536 if (port == NULL || numq == NULL || flags == NULL) { 4537 return BCM_E_PARAM; 4538 } 4539 4540 LOG_INFO(BSL_LS_BCM_COSQ, 4541 (BSL_META_U(unit, 4542 "bcm_ap_cosq_gport_get: unit=%d gport=0x%x\n"), 4543 unit, gport)); 4544 4545 BCM_IF_ERROR_RETURN 4546 (_bcm_ap_cosq_node_get(unit, gport, 0, NULL, &local_port, &id, &node)); 4547 4548 if (SOC_USE_GPORT(unit)) { 4549 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid)); 4550 dest.gport_type = _SHR_GPORT_TYPE_MODPORT; 4551 dest.modid = modid; 4552 dest.port = local_port; 4553 BCM_IF_ERROR_RETURN(_bcm_esw_gport_construct(unit, &dest, port)); 4554 } else { 4555 *port = local_port; 4556 } 4557 4558 *numq = node->numq; 4559 4560 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 4561 if (node->type == _BCM_AP_NODE_SERVICE_UCAST) { 4562 *flags = BCM_COSQ_GPORT_VLAN_UCAST_QUEUE_GROUP; 4563 } else if (node->type == _BCM_AP_NODE_VM_UCAST) { 4564 *flags = BCM_COSQ_GPORT_VIRTUAL_PORT; 4565 } else if (node->type == _BCM_AP_NODE_VOQ) { 4566 *flags = BCM_COSQ_GPORT_DESTMOD_UCAST_QUEUE_GROUP; 4567 } else { 4568 *flags = BCM_COSQ_GPORT_UCAST_QUEUE_GROUP; 4569 } 4570 } else if (BCM_GPORT_IS_SCHEDULER(gport)) { 4571 *flags = BCM_COSQ_GPORT_SCHEDULER; 4572 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 4573 *flags = BCM_COSQ_GPORT_MCAST_QUEUE_GROUP; 4574 } else { 4575 *flags = 0; 4576 } 4577 4578 LOG_INFO(BSL_LS_BCM_COSQ, 4579 (BSL_META_U(unit, 4580 " port=0x%x numq=%d flags=0x%x\n"), 4581 *port, *numq, *flags)); 4582 4583 return BCM_E_NONE; 4584 } 4585 4586 /* 4587 * Function: 4588 * bcm_ap_cosq_gport_traverse 4589 * Purpose: 4590 * Walks through the valid COSQ GPORTs and calls 4591 * the user supplied callback function for each entry. 4592 * Parameters: 4593 * unit - (IN) unit number 4594 * trav_fn - (IN) Callback function. 4595 * user_data - (IN) User data to be passed to callback function 4596 * Returns: 4597 * BCM_E_NONE - Success. 4598 * BCM_E_XXX 4599 */ 4600 int 4601 bcm_ap_cosq_gport_traverse(int unit, bcm_cosq_gport_traverse_cb cb, 4602 void *user_data) 4603 { 4604 _bcm_ap_cosq_node_t *port_info; 4605 _bcm_ap_mmu_info_t *mmu_info; 4606 bcm_module_t my_modid, modid_out; 4607 bcm_port_t port, port_out; 4608 4609 if (_bcm_ap_mmu_info[unit] == NULL) { 4610 return BCM_E_INIT; 4611 } 4612 mmu_info = _bcm_ap_mmu_info[unit]; 4613 4614 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_modid)); 4615 PBMP_ALL_ITER(unit, port) { 4616 BCM_IF_ERROR_RETURN 4617 (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, 4618 my_modid, port, &modid_out, &port_out)); 4619 4620 /* root node */ 4621 port_info = &mmu_info->sched_node[port_out]; 4622 4623 if (port_info->gport >= 0) { 4624 _bcm_ap_cosq_gport_traverse(unit, port_info->gport, cb, user_data); 4625 } 4626 } 4627 4628 return BCM_E_NONE; 4629 } 4630 4631 4632 /* 4633 * Function: 4634 * bcm_ap_cosq_gport_attach 4635 * Purpose: 4636 * Attach sched_port to the specified index (cosq) of parent_port 4637 * Parameters: 4638 * unit - (IN) unit number 4639 * sched_port - (IN) scheduler GPORT identifier 4640 * parent_port - (IN) GPORT to attach to 4641 * cosq - (IN) COS queue to attach to (-1 for first available cosq) 4642 * Returns: 4643 * BCM_E_XXX 4644 */ 4645 int 4646 bcm_ap_cosq_gport_attach(int unit, bcm_gport_t gport, 4647 bcm_gport_t parent_gport, 4648 bcm_cos_queue_t to_cosq) 4649 { 4650 _bcm_ap_mmu_info_t *mmu_info; 4651 _bcm_ap_cosq_node_t *node, *parent_node, *child_node, *s1_node; 4652 bcm_port_t port, to_port, local_port = 0, mmu_port; 4653 int rv, tmp; 4654 int max_nodes = 0; 4655 int subport_enabled = 0; 4656 uint32 rval = 0; 4657 uint32 mc_group_mode = 0; 4658 4659 if ((mmu_info = _bcm_ap_mmu_info[unit]) == NULL) { 4660 return BCM_E_INIT; 4661 } 4662 4663 if ((BCM_GPORT_IS_UCAST_QUEUE_GROUP(parent_gport)) || 4664 (BCM_GPORT_IS_MCAST_QUEUE_GROUP(parent_gport)) || 4665 (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(parent_gport))) { 4666 return BCM_E_PARAM; 4667 } 4668 4669 if(!(BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 4670 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) || 4671 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport) || 4672 BCM_GPORT_IS_SCHEDULER(gport))) { 4673 return BCM_E_PORT; 4674 } 4675 4676 BCM_IF_ERROR_RETURN 4677 (_bcm_ap_cosq_node_get(unit, gport, 0, NULL, &port, NULL, &node)); 4678 4679 if (node->attached_to_input >= 0) { 4680 /* Has already attached */ 4681 return BCM_E_EXISTS; 4682 } 4683 tmp = node->attached_to_input; 4684 4685 if (BCM_GPORT_IS_SCHEDULER(parent_gport)) { 4686 BCM_IF_ERROR_RETURN 4687 (_bcm_ap_cosq_node_get(unit, parent_gport, 0, NULL, &to_port, NULL, 4688 &parent_node)); 4689 } else { 4690 BCM_IF_ERROR_RETURN 4691 (_bcm_ap_cosq_localport_resolve(unit, parent_gport, &to_port)); 4692 parent_node = &mmu_info->sched_node[to_port]; 4693 } 4694 4695 if (port != to_port) { 4696 return BCM_E_PORT; 4697 } 4698 if (!parent_node) 4699 { 4700 return BCM_E_NOT_FOUND; 4701 } 4702 4703 if ((parent_node->level == SOC_APACHE_NODE_LVL_ROOT) && 4704 _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, node->port_gport)) { 4705 rv = _bcm_ap_get_s1_node(unit, node->port_gport, 4706 &s1_node); 4707 if( rv != BCM_E_NOT_FOUND) { 4708 return BCM_E_EXISTS; 4709 } 4710 4711 } 4712 if (parent_node->level != SOC_APACHE_NODE_LVL_ROOT && 4713 parent_node->port_gport != node->port_gport) 4714 { 4715 return BCM_E_PARAM; 4716 } 4717 mmu_port = SOC_APACHE_MMU_PORT(unit, port); 4718 4719 /* Identify the levels of schedulers 4720 * parent_port == phy_port && gport == scheduler => gport = S1 4721 * parent_port == scheduler && level = S1 && gport == scheduler => gport = L0 4722 * parent_port == schduler && lvel = L0 && gport == scheduler => parent_port = L0 and gport = L1 4723 * parent_port == scheduler && port == queue_group => parent_port = L1 and gport = L2 4724 */ 4725 if (!BCM_GPORT_IS_SCHEDULER(parent_gport)) { 4726 if ((parent_node->numq == 0) || (parent_node->numq_expandable)) { 4727 local_port = (BCM_GPORT_IS_LOCAL(parent_gport)) ? 4728 BCM_GPORT_LOCAL_GET(parent_gport) : 4729 BCM_GPORT_MODPORT_PORT_GET(parent_gport); 4730 4731 if (!SOC_PORT_VALID(unit, local_port)) { 4732 return BCM_E_PORT; 4733 } 4734 parent_node->in_use = TRUE; 4735 parent_node->local_port = port; 4736 if (IS_AP_HSP_PORT(unit, local_port)) { 4737 parent_node->base_index = _BCM_AP_HSP_L0_INDEX(unit, mmu_port, 0); 4738 parent_node->numq = _BCM_AP_HSP_PORT_MAX_L0; 4739 } else { 4740 parent_node->gport = parent_gport; 4741 parent_node->hw_index = _BCM_AP_ROOT_SCHED_INDEX(unit, mmu_port); 4742 parent_node->level = SOC_APACHE_NODE_LVL_ROOT; 4743 parent_node->attached_to_input = 0; 4744 parent_node->numq_expandable = 1; 4745 if (to_cosq == -1) { 4746 parent_node->numq += 1; 4747 } else { 4748 if (to_cosq >= parent_node->numq) { 4749 parent_node->numq = to_cosq + 1; 4750 } 4751 } 4752 } 4753 } 4754 4755 if (!BCM_GPORT_IS_SCHEDULER(gport)) { 4756 return BCM_E_PARAM; 4757 } 4758 4759 if (IS_AP_HSP_PORT(unit, to_port)) { 4760 node->level = SOC_APACHE_NODE_LVL_L0; 4761 } else { 4762 node->level = SOC_APACHE_NODE_LVL_S1; 4763 } 4764 } else { 4765 if (parent_node->level == SOC_APACHE_NODE_LVL_ROOT) { 4766 if (IS_AP_HSP_PORT(unit, to_port)) { 4767 node->level = SOC_APACHE_NODE_LVL_L0; 4768 } else { 4769 node->level = SOC_APACHE_NODE_LVL_S1; 4770 } 4771 } 4772 if (parent_node->level == SOC_APACHE_NODE_LVL_S1) { 4773 node->level = SOC_APACHE_NODE_LVL_L0; 4774 } 4775 if (parent_node->level == SOC_APACHE_NODE_LVL_L0) { 4776 node->level = SOC_APACHE_NODE_LVL_L1; 4777 4778 /*only for hsp ports with mc-group-mode enabled 2 l2 mulicast 4779 can be attached directly to L0.0 */ 4780 if (IS_AP_HSP_PORT(unit, to_port)) { 4781 SOC_IF_ERROR_RETURN( 4782 READ_HSP_SCHED_PORT_CONFIGr(unit, to_port, &rval)); 4783 mc_group_mode = soc_reg_field_get(unit, HSP_SCHED_PORT_CONFIGr, 4784 rval, MC_GROUP_MODEf); 4785 if ((mc_group_mode) && (parent_node->attached_to_input == 0)) 4786 node->level = SOC_APACHE_NODE_LVL_L2; 4787 } 4788 } 4789 if (parent_node->level == SOC_APACHE_NODE_LVL_L1) { 4790 node->level = SOC_APACHE_NODE_LVL_L2; 4791 } 4792 BCM_IF_ERROR_RETURN 4793 (_bcm_ap_cosq_max_nodes_get(unit, node->level, &max_nodes)); 4794 if (parent_node->numq > max_nodes) { 4795 return BCM_E_PARAM; 4796 } 4797 } 4798 4799 if ((to_cosq < -1) || ((parent_node->numq != -1) && (to_cosq >= parent_node->numq))) { 4800 return BCM_E_PARAM; 4801 } 4802 4803 if (BCM_GPORT_IS_SCHEDULER(parent_gport) || BCM_GPORT_IS_LOCAL(parent_gport) || 4804 BCM_GPORT_IS_MODPORT(parent_gport)) { 4805 int start = 0, end = 0; 4806 if (parent_node->attached_to_input < 0) { 4807 /* dont allow to attach to a node that has already attached */ 4808 return BCM_E_PARAM; 4809 } 4810 4811 if (node->type == _BCM_AP_NODE_SERVICE_UCAST) { 4812 end = node->numq; 4813 } else { 4814 end = 1; 4815 } 4816 4817 for (start = 0; start < end; start++) { 4818 node->parent = parent_node; 4819 node->sibling = parent_node->child; 4820 parent_node->child = node; 4821 /* resolve the nodes */ 4822 rv = _bcm_ap_cosq_node_resolve(unit, node, to_cosq + start); 4823 if (BCM_FAILURE(rv)) { 4824 parent_node->child = node->sibling; 4825 node->parent = NULL; 4826 node->attached_to_input = tmp; 4827 return rv; 4828 } 4829 LOG_INFO(BSL_LS_BCM_COSQ, 4830 (BSL_META_U(unit, 4831 " hw_cosq=%d\n"), 4832 node->attached_to_input)); 4833 4834 if ((node->type == _BCM_AP_NODE_SERVICE_UCAST) && 4835 ((start + 1) < end)){ 4836 BCM_IF_ERROR_RETURN 4837 (_bcm_ap_cosq_node_get(unit, gport, start + 1, NULL, 4838 &port, NULL, &node)); 4839 if (!node) { 4840 return BCM_E_NOT_FOUND; 4841 } 4842 } 4843 } 4844 if (soc_feature(unit, 4845 soc_feature_mmu_hqos_four_level) && 4846 node->level == SOC_APACHE_NODE_LVL_S1) { 4847 child_node = parent_node->child; 4848 while(child_node) { 4849 if(_BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, 4850 child_node->port_gport)) { 4851 subport_enabled++ ; 4852 if(subport_enabled > 1) { 4853 break; 4854 } 4855 } 4856 child_node = child_node->sibling; 4857 } 4858 if (subport_enabled == 1) { 4859 BCM_IF_ERROR_RETURN( 4860 _bcm_ap_mmu_port_coe_control(unit, 4861 node->local_port, 1)); 4862 } 4863 } 4864 } else { 4865 return BCM_E_PORT; 4866 } 4867 4868 return BCM_E_NONE; 4869 } 4870 4871 /* 4872 * Function: 4873 * bcm_ap_cosq_gport_attach_get 4874 * Purpose: 4875 * Get attached status of a scheduler port 4876 * Parameters: 4877 * unit - (IN) unit number 4878 * sched_port - (IN) scheduler GPORT identifier 4879 * parent_port - (OUT) GPORT to attach to 4880 * cosq - (OUT) COS queue to attached to 4881 * Returns: 4882 * BCM_E_XXX 4883 * Notes: 4884 */ 4885 int 4886 bcm_ap_cosq_gport_attach_get(int unit, bcm_gport_t sched_gport, 4887 bcm_gport_t *parent_gport, bcm_cos_queue_t *cosq) 4888 { 4889 _bcm_ap_cosq_node_t *sched_node; 4890 bcm_module_t modid, modid_out; 4891 bcm_port_t port, port_out; 4892 4893 if (parent_gport == NULL || cosq == NULL) { 4894 return BCM_E_PARAM; 4895 } 4896 4897 BCM_IF_ERROR_RETURN 4898 (_bcm_ap_cosq_node_get(unit, sched_gport, 0, &modid, &port, NULL, 4899 &sched_node)); 4900 4901 if (sched_node->attached_to_input < 0) { 4902 /* Not attached yet */ 4903 return BCM_E_NOT_FOUND; 4904 } 4905 4906 if (sched_node->parent != NULL) { /* sched_node is not an S1 scheduler */ 4907 *parent_gport = sched_node->parent->gport; 4908 } else { /* sched_node is an S1 scheduler */ 4909 BCM_IF_ERROR_RETURN 4910 (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, modid, port, 4911 &modid_out, &port_out)); 4912 BCM_GPORT_MODPORT_SET(*parent_gport, modid_out, port_out); 4913 } 4914 *cosq = sched_node->attached_to_input; 4915 4916 return BCM_E_NONE; 4917 } 4918 4919 /* 4920 * Function: 4921 * bcm_ap_cosq_gport_child_get 4922 * Purpose: 4923 * Get the child node GPORT atatched to N-th index (cosq) 4924 * of the scheduler GPORT. 4925 * Parameters: 4926 * unit - (IN) Unit number. 4927 * in_gport - (IN) Scheduler GPORT ID. 4928 * cosq - (IN) COS queue attached to. 4929 * out_gport - (OUT) child GPORT ID. 4930 * Returns: 4931 * BCM_E_XXX 4932 * Notes: 4933 */ 4934 int 4935 bcm_ap_cosq_gport_child_get(int unit, bcm_gport_t in_gport, 4936 bcm_cos_queue_t cosq, 4937 bcm_gport_t *out_gport) 4938 { 4939 _bcm_ap_cosq_node_t *in_node = NULL; 4940 _bcm_ap_cosq_node_t *cur_node = NULL; 4941 _bcm_ap_cosq_node_t *tmp_node = NULL; 4942 bcm_module_t modid; 4943 bcm_port_t port; 4944 bcm_port_t local_port; 4945 4946 if (out_gport == NULL) { 4947 return BCM_E_PARAM; 4948 } 4949 4950 /* get the child of the input gport node 4951 * at an index of cosq 4952 */ 4953 4954 if ((cosq < 0) || ( cosq >= 64)) { 4955 return BCM_E_PARAM; 4956 } 4957 4958 BCM_IF_ERROR_RETURN 4959 (_bcm_ap_cosq_node_get(unit, in_gport, 0, &modid, &port, NULL, 4960 &in_node)); 4961 if ((in_node->child == NULL) && (in_node->level == SOC_APACHE_NODE_LVL_L2)) { 4962 return BCM_E_PARAM; 4963 } 4964 4965 if (soc_feature(unit, soc_feature_mmu_hqos_four_level)) 4966 { 4967 cur_node = in_node->child; 4968 } else { 4969 BCM_IF_ERROR_RETURN 4970 (_bcm_ap_cosq_localport_resolve(unit,in_gport, &local_port)); 4971 if ( (in_node->level == SOC_APACHE_NODE_LVL_ROOT) && !IS_AP_HSP_PORT(unit, local_port) ) { 4972 if ((in_node->child == NULL) || (in_node->child->child == NULL) ) { 4973 return BCM_E_PARAM; 4974 } 4975 cur_node = in_node->child->child; 4976 } else { 4977 cur_node = in_node->child; 4978 } 4979 } 4980 for (; cur_node != NULL; cur_node = cur_node->sibling) { 4981 if (cur_node->attached_to_input == cosq) { 4982 tmp_node = cur_node; 4983 break; 4984 } 4985 } 4986 4987 if (tmp_node == NULL) { 4988 return BCM_E_NOT_FOUND; 4989 } 4990 *out_gport = tmp_node->gport; 4991 4992 return BCM_E_NONE; 4993 } 4994 4995 /* 4996 * Convert HW drop probability to percent value 4997 */ 4998 STATIC int 4999 _bcm_ap_hw_drop_prob_to_percent[] = { 5000 0, /* 0 */ 5001 1, /* 1 */ 5002 2, /* 2 */ 5003 3, /* 3 */ 5004 4, /* 4 */ 5005 5, /* 5 */ 5006 6, /* 6 */ 5007 7, /* 7 */ 5008 8, /* 8 */ 5009 9, /* 9 */ 5010 10, /* 10 */ 5011 25, /* 11 */ 5012 50, /* 12 */ 5013 75, /* 13 */ 5014 100, /* 14 */ 5015 -1 /* 15 */ 5016 }; 5017 5018 STATIC int 5019 _bcm_ap_percent_to_drop_prob(int percent) 5020 { 5021 int i; 5022 5023 for (i = 14; i > 0 ; i--) { 5024 if (percent >= _bcm_ap_hw_drop_prob_to_percent[i]) { 5025 break; 5026 } 5027 } 5028 return i; 5029 } 5030 5031 STATIC int 5032 _bcm_ap_drop_prob_to_percent(int drop_prob) { 5033 return (_bcm_ap_hw_drop_prob_to_percent[drop_prob]); 5034 } 5035 5036 /* 5037 * index: degree, value: contangent(degree) * 100 5038 * max value is 0xffff (16-bit) at 0 degree 5039 */ 5040 STATIC int 5041 _bcm_ap_cotangent_lookup_table[] = 5042 { 5043 /* 0.. 5 */ 65535, 5728, 2863, 1908, 1430, 1143, 5044 /* 6..11 */ 951, 814, 711, 631, 567, 514, 5045 /* 12..17 */ 470, 433, 401, 373, 348, 327, 5046 /* 18..23 */ 307, 290, 274, 260, 247, 235, 5047 /* 24..29 */ 224, 214, 205, 196, 188, 180, 5048 /* 30..35 */ 173, 166, 160, 153, 148, 142, 5049 /* 36..41 */ 137, 132, 127, 123, 119, 115, 5050 /* 42..47 */ 111, 107, 103, 100, 96, 93, 5051 /* 48..53 */ 90, 86, 83, 80, 78, 75, 5052 /* 54..59 */ 72, 70, 67, 64, 62, 60, 5053 /* 60..65 */ 57, 55, 53, 50, 48, 46, 5054 /* 66..71 */ 44, 42, 40, 38, 36, 34, 5055 /* 72..77 */ 32, 30, 28, 26, 24, 23, 5056 /* 78..83 */ 21, 19, 17, 15, 14, 12, 5057 /* 84..89 */ 10, 8, 6, 5, 3, 1, 5058 /* 90 */ 0 5059 }; 5060 5061 /* 5062 * Given a slope (angle in degrees) from 0 to 90, return the number of cells 5063 * in the range from 0% drop probability to 100% drop probability. 5064 */ 5065 STATIC int 5066 _bcm_ap_angle_to_cells(int angle) 5067 { 5068 return (_bcm_ap_cotangent_lookup_table[angle]); 5069 } 5070 5071 /* 5072 * Given a number of packets in the range from 0% drop probability 5073 * to 100% drop probability, return the slope (angle in degrees). 5074 */ 5075 STATIC int 5076 _bcm_ap_cells_to_angle(int packets) 5077 { 5078 int angle; 5079 5080 for (angle = 90; angle >= 0 ; angle--) { 5081 if (packets <= _bcm_ap_cotangent_lookup_table[angle]) { 5082 break; 5083 } 5084 } 5085 return angle; 5086 } 5087 5088 /* 5089 * Function: 5090 * _bcm_ap_cosq_bucket_set 5091 * Purpose: 5092 * Configure COS queue bandwidth control bucket 5093 * Parameters: 5094 * unit - (IN) unit number 5095 * port - (IN) port number or GPORT identifier 5096 * cosq - (IN) COS queue number 5097 * min_quantum - (IN) kbps or packet/second 5098 * max_quantum - (IN) kbps or packet/second 5099 * burst_quantum - (IN) kbps or packet/second 5100 * flags - (IN) 5101 * Returns: 5102 * BCM_E_XXX 5103 * Notes: 5104 * If port is any form of local port, cosq is the hardware queue index. 5105 */ 5106 STATIC int 5107 _bcm_ap_cosq_bucket_set(int unit, bcm_gport_t port, bcm_cos_queue_t cosq, 5108 uint32 min_quantum, uint32 max_quantum, 5109 uint32 kbits_burst_min, uint32 kbits_burst_max, 5110 uint32 flags) 5111 { 5112 _bcm_ap_cosq_node_t *node = NULL; 5113 bcm_port_t local_port; 5114 int index; 5115 uint32 rval; 5116 uint32 meter_flags; 5117 uint32 bucketsize_max, bucketsize_min; 5118 uint32 granularity_max, granularity_min; 5119 uint32 refresh_rate_max, refresh_rate_min; 5120 int refresh_bitsize = 0, bucket_bitsize = 0; 5121 soc_mem_t config_mem = INVALIDm; 5122 uint32 mc_group_mode = 0; 5123 int max_l1_table = 2,max_l2_table = 8; 5124 uint32 entry[SOC_MAX_MEM_WORDS]; 5125 soc_mem_t mtro_l1[] = { MMU_MTRO_L1_MEM_0m, 5126 MMU_MTRO_L1_MEM_1m }; 5127 soc_mem_t mtro_l2[] = { MMU_MTRO_L2_MEM_0m, 5128 MMU_MTRO_L2_MEM_1m, 5129 MMU_MTRO_L2_MEM_2m, 5130 MMU_MTRO_L2_MEM_3m, 5131 MMU_MTRO_L2_MEM_4m, 5132 MMU_MTRO_L2_MEM_5m, 5133 MMU_MTRO_L2_MEM_6m, 5134 MMU_MTRO_L2_MEM_7m }; 5135 5136 /* caller should resolve the cosq. */ 5137 if (cosq < 0) { 5138 if (cosq == -1) { 5139 /* caller needs to resolve the wild card value (-1) */ 5140 return BCM_E_INTERNAL; 5141 } else { /* reject all other negative value */ 5142 return BCM_E_PARAM; 5143 } 5144 } 5145 5146 BCM_IF_ERROR_RETURN 5147 (_bcm_ap_cosq_index_resolve(unit, port, cosq, 5148 _BCM_AP_COSQ_INDEX_STYLE_BUCKET, 5149 &local_port, &index, NULL)); 5150 5151 if (BCM_GPORT_IS_SET(port) && 5152 ((BCM_GPORT_IS_SCHEDULER(port)) || 5153 BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 5154 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) || 5155 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port))) { 5156 5157 BCM_IF_ERROR_RETURN 5158 (_bcm_ap_cosq_node_get(unit, port, cosq, NULL, 5159 NULL, NULL, &node)); 5160 if ((node->level == SOC_APACHE_NODE_LVL_ROOT) && 5161 !IS_AP_HSP_PORT(unit, local_port) && 5162 (min_quantum > 0)) { 5163 /* min shaper is not supported */ 5164 return BCM_E_PARAM; 5165 } 5166 } 5167 5168 if (node) { 5169 if (BCM_GPORT_IS_SCHEDULER(port) || BCM_GPORT_IS_MODPORT(port)) { 5170 if (node->level == SOC_APACHE_NODE_LVL_ROOT) { 5171 if (IS_AP_HSP_PORT(unit, local_port)) { 5172 config_mem = MMU_MTRO_L0_MEM_0m; 5173 } else { 5174 config_mem = MMU_MTRO_S1_MEM_0m; 5175 } 5176 } else if (node->level == SOC_APACHE_NODE_LVL_S1) { 5177 config_mem = MMU_MTRO_L0_MEM_0m; 5178 } else if (node->level == SOC_APACHE_NODE_LVL_L0) { 5179 if (IS_AP_HSP_PORT(unit, local_port)){ 5180 SOC_IF_ERROR_RETURN( 5181 READ_HSP_SCHED_PORT_CONFIGr(unit, local_port, &rval)); 5182 5183 mc_group_mode = soc_reg_field_get(unit, HSP_SCHED_PORT_CONFIGr, 5184 rval, MC_GROUP_MODEf); 5185 } 5186 if (mc_group_mode) { 5187 config_mem = mtro_l2[index % max_l2_table]; 5188 index /= max_l2_table; 5189 } 5190 else { 5191 config_mem = mtro_l1[index % max_l1_table]; 5192 index /= max_l1_table; 5193 } 5194 } else if (node->level == SOC_APACHE_NODE_LVL_L1) { 5195 config_mem = mtro_l2[index % max_l2_table ]; 5196 index /= max_l2_table; 5197 } else { 5198 return BCM_E_PARAM; 5199 } 5200 } else if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 5201 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 5202 config_mem = mtro_l2[index % max_l2_table]; 5203 index /= max_l2_table; 5204 } else { 5205 return BCM_E_PARAM; 5206 } 5207 } else { 5208 if (IS_CPU_PORT(unit, local_port)) { 5209 config_mem = mtro_l2[index % max_l2_table]; 5210 index /= max_l2_table; 5211 } else if (_BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT 5212 (unit, port)) 5213 { 5214 config_mem = mtro_l2[index % max_l2_table]; 5215 index /= max_l2_table; 5216 } else { 5217 config_mem = mtro_l1[index % max_l1_table]; 5218 index /= max_l1_table; 5219 } 5220 } 5221 5222 meter_flags = flags & BCM_COSQ_BW_PACKET_MODE ? 5223 _BCM_TD_METER_FLAG_PACKET_MODE : 0; 5224 BCM_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, &rval)); 5225 if (soc_reg_field_get(unit, MISCCONFIGr, rval, ITU_MODE_SELf)) { 5226 meter_flags |= _BCM_TD_METER_FLAG_NON_LINEAR; 5227 } 5228 5229 if (config_mem == MMU_MTRO_S1_MEM_0m) { 5230 refresh_bitsize = soc_mem_field_length(unit, config_mem, REFRESHf); 5231 bucket_bitsize = soc_mem_field_length(unit, config_mem, THD_SELf); 5232 } else { 5233 refresh_bitsize = soc_mem_field_length(unit, config_mem, MAX_REFRESHf); 5234 bucket_bitsize = soc_mem_field_length(unit, config_mem, MAX_THD_SELf); 5235 } 5236 5237 BCM_IF_ERROR_RETURN 5238 (_bcm_td_rate_to_bucket_encoding(unit, max_quantum, kbits_burst_max, 5239 meter_flags, refresh_bitsize, 5240 bucket_bitsize, &refresh_rate_max, 5241 &bucketsize_max, &granularity_max)); 5242 5243 BCM_IF_ERROR_RETURN 5244 (_bcm_td_rate_to_bucket_encoding(unit, min_quantum, kbits_burst_min, 5245 meter_flags, refresh_bitsize, 5246 bucket_bitsize, &refresh_rate_min, 5247 &bucketsize_min, &granularity_min)); 5248 5249 sal_memset(entry, 0, sizeof(uint32)*SOC_MAX_MEM_WORDS); 5250 if (config_mem == MMU_MTRO_S1_MEM_0m) { 5251 soc_mem_field32_set(unit, config_mem, &entry, METER_GRANf, granularity_max); 5252 soc_mem_field32_set(unit, config_mem, &entry, REFRESHf, refresh_rate_max); 5253 soc_mem_field32_set(unit, config_mem, &entry, THD_SELf, bucketsize_max); 5254 } else { 5255 soc_mem_field32_set(unit, config_mem, &entry, MAX_METER_GRANf, granularity_max); 5256 soc_mem_field32_set(unit, config_mem, &entry, MAX_REFRESHf, refresh_rate_max); 5257 soc_mem_field32_set(unit, config_mem, &entry, MAX_THD_SELf, bucketsize_max); 5258 5259 soc_mem_field32_set(unit, config_mem, &entry, MIN_METER_GRANf, granularity_min); 5260 soc_mem_field32_set(unit, config_mem, &entry, MIN_REFRESHf, refresh_rate_min); 5261 soc_mem_field32_set(unit, config_mem, &entry, MIN_THD_SELf, bucketsize_min); 5262 5263 soc_mem_field32_set(unit, config_mem, &entry, SHAPER_CONTROLf, 5264 (flags & BCM_COSQ_BW_PACKET_MODE) ? 1 : 0); 5265 } 5266 5267 soc_mem_field32_set(unit, config_mem, &entry, EAV_ENABLEf, 5268 (flags & BCM_COSQ_BW_EAV_MODE) ? 1 : 0); 5269 BCM_IF_ERROR_RETURN 5270 (soc_mem_write(unit, config_mem, MEM_BLOCK_ALL, index, &entry)); 5271 5272 return BCM_E_NONE; 5273 } 5274 5275 /* 5276 * Function: 5277 * _bcm_ap_cosq_bucket_get 5278 * Purpose: 5279 * Get COS queue bandwidth control bucket setting 5280 * Parameters: 5281 * unit - (IN) unit number 5282 * port - (IN) port number or GPORT identifier 5283 * cosq - (IN) COS queue number 5284 * min_quantum - (OUT) kbps or packet/second 5285 * max_quantum - (OUT) kbps or packet/second 5286 * burst_quantum - (OUT) kbps or packet/second 5287 * flags - (IN) 5288 * Returns: 5289 * BCM_E_XXX 5290 * Notes: 5291 * If port is any form of local port, cosq is the hardware queue index. 5292 */ 5293 STATIC int 5294 _bcm_ap_cosq_bucket_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 5295 uint32 *min_quantum, uint32 *max_quantum, 5296 uint32 *kbits_burst_min, uint32 *kbits_burst_max, 5297 uint32 *flags) 5298 { 5299 _bcm_ap_cosq_node_t *node = NULL; 5300 bcm_port_t local_port; 5301 int index; 5302 uint32 rval; 5303 uint32 refresh_rate, bucketsize, granularity, meter_flags; 5304 soc_mem_t config_mem = INVALIDm; 5305 uint32 mc_group_mode = 0; 5306 uint32 entry[SOC_MAX_MEM_WORDS]; 5307 int max_l1_table = 2,max_l2_table = 8; 5308 soc_mem_t mtro_l1[] = { MMU_MTRO_L1_MEM_0m, 5309 MMU_MTRO_L1_MEM_1m }; 5310 soc_mem_t mtro_l2[] = { MMU_MTRO_L2_MEM_0m, 5311 MMU_MTRO_L2_MEM_1m, 5312 MMU_MTRO_L2_MEM_2m, 5313 MMU_MTRO_L2_MEM_3m, 5314 MMU_MTRO_L2_MEM_4m, 5315 MMU_MTRO_L2_MEM_5m, 5316 MMU_MTRO_L2_MEM_6m, 5317 MMU_MTRO_L2_MEM_7m }; 5318 5319 if (cosq < 0) { 5320 if (cosq == -1) { 5321 /* caller needs to resolve the wild card value (-1) */ 5322 return BCM_E_INTERNAL; 5323 } else { /* reject all other negative value */ 5324 return BCM_E_PARAM; 5325 } 5326 } 5327 5328 BCM_IF_ERROR_RETURN 5329 (_bcm_ap_cosq_index_resolve(unit, port, cosq, 5330 _BCM_AP_COSQ_INDEX_STYLE_BUCKET, 5331 &local_port, &index, NULL)); 5332 5333 if (BCM_GPORT_IS_SET(port) && 5334 ((BCM_GPORT_IS_SCHEDULER(port)) || 5335 BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 5336 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) || 5337 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port))) { 5338 5339 BCM_IF_ERROR_RETURN 5340 (_bcm_ap_cosq_node_get(unit, port, cosq, NULL, 5341 &local_port, NULL, &node)); 5342 } 5343 5344 if (node) { 5345 if (BCM_GPORT_IS_SCHEDULER(port) || BCM_GPORT_IS_MODPORT(port)) { 5346 if (node->level == SOC_APACHE_NODE_LVL_ROOT) { 5347 if (IS_AP_HSP_PORT(unit, local_port)) { 5348 config_mem = MMU_MTRO_L0_MEM_0m; 5349 } else { 5350 config_mem = MMU_MTRO_S1_MEM_0m; 5351 } 5352 } else if (node->level == SOC_APACHE_NODE_LVL_S1) { 5353 config_mem = MMU_MTRO_L0_MEM_0m; 5354 } else if (node->level == SOC_APACHE_NODE_LVL_L0) { 5355 if (IS_AP_HSP_PORT(unit, local_port)) { 5356 SOC_IF_ERROR_RETURN( 5357 READ_HSP_SCHED_PORT_CONFIGr(unit, 5358 local_port, &rval)); 5359 mc_group_mode = soc_reg_field_get(unit, HSP_SCHED_PORT_CONFIGr, 5360 rval, MC_GROUP_MODEf); 5361 } 5362 if (mc_group_mode){ 5363 config_mem = mtro_l2[index % max_l2_table ]; 5364 index /= max_l2_table; 5365 } else { 5366 config_mem = mtro_l1[index % max_l1_table]; 5367 index /= max_l1_table; 5368 } 5369 } else if (node->level == SOC_APACHE_NODE_LVL_L1) { 5370 config_mem = mtro_l2[index % max_l2_table ]; 5371 index /= max_l2_table; 5372 } else { 5373 return BCM_E_PARAM; 5374 } 5375 } else if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 5376 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 5377 config_mem = mtro_l2[index % max_l2_table]; 5378 index /= max_l2_table; 5379 } else { 5380 return BCM_E_PARAM; 5381 } 5382 } else { 5383 if (IS_CPU_PORT(unit, local_port)) { 5384 config_mem = mtro_l2[index % max_l2_table]; 5385 index /= max_l2_table; 5386 } else if (_BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT 5387 (unit, port)) 5388 { 5389 config_mem = mtro_l2[index % max_l2_table]; 5390 index /= max_l2_table; 5391 } else { 5392 config_mem = mtro_l1[index % max_l1_table ]; 5393 index /= max_l1_table; 5394 } 5395 } 5396 5397 if (min_quantum == NULL || max_quantum == NULL || 5398 kbits_burst_max == NULL || kbits_burst_min == NULL) { 5399 return BCM_E_PARAM; 5400 } 5401 5402 5403 BCM_IF_ERROR_RETURN 5404 (soc_mem_read(unit, config_mem, MEM_BLOCK_ALL, index, &entry)); 5405 5406 meter_flags = 0; 5407 *flags = 0; 5408 BCM_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, &rval)); 5409 if (soc_reg_field_get(unit, MISCCONFIGr, rval, ITU_MODE_SELf)) { 5410 meter_flags |= _BCM_TD_METER_FLAG_NON_LINEAR; 5411 } 5412 if (config_mem == MMU_MTRO_S1_MEM_0m) { 5413 if (soc_mem_field32_get(unit, config_mem, &entry, MODEf)) { 5414 meter_flags |= _BCM_TD_METER_FLAG_PACKET_MODE; 5415 *flags |= BCM_COSQ_BW_PACKET_MODE; 5416 } 5417 } else { 5418 if (soc_mem_field32_get(unit, config_mem, &entry, SHAPER_CONTROLf)) { 5419 meter_flags |= _BCM_TD_METER_FLAG_PACKET_MODE; 5420 *flags |= BCM_COSQ_BW_PACKET_MODE; 5421 } 5422 } 5423 5424 if (config_mem == MMU_MTRO_S1_MEM_0m) { 5425 granularity = soc_mem_field32_get(unit, config_mem, &entry, METER_GRANf); 5426 refresh_rate = soc_mem_field32_get(unit, config_mem, &entry, REFRESHf); 5427 bucketsize = soc_mem_field32_get(unit, config_mem, &entry, THD_SELf); 5428 } else { 5429 granularity = soc_mem_field32_get(unit, config_mem, &entry, MAX_METER_GRANf); 5430 refresh_rate = soc_mem_field32_get(unit, config_mem, &entry, MAX_REFRESHf); 5431 bucketsize = soc_mem_field32_get(unit, config_mem, &entry, MAX_THD_SELf); 5432 } 5433 BCM_IF_ERROR_RETURN 5434 (_bcm_td_bucket_encoding_to_rate(unit, refresh_rate, bucketsize, 5435 granularity, meter_flags, 5436 max_quantum, kbits_burst_max)); 5437 5438 if (config_mem != MMU_MTRO_S1_MEM_0m) { 5439 granularity = soc_mem_field32_get(unit, config_mem, &entry, MIN_METER_GRANf); 5440 refresh_rate = soc_mem_field32_get(unit, config_mem, &entry, MIN_REFRESHf); 5441 bucketsize = soc_mem_field32_get(unit, config_mem, &entry, MIN_THD_SELf); 5442 5443 BCM_IF_ERROR_RETURN 5444 (_bcm_td_bucket_encoding_to_rate(unit, refresh_rate, bucketsize, 5445 granularity, meter_flags, 5446 min_quantum, kbits_burst_min)); 5447 } 5448 5449 if (soc_mem_field32_get(unit, config_mem, &entry, EAV_ENABLEf)) { 5450 *flags |= BCM_COSQ_BW_EAV_MODE; 5451 } 5452 return BCM_E_NONE; 5453 } 5454 5455 5456 STATIC int 5457 _bcm_ap_cosq_time_domain_get(int unit, int time_id, int *time_value) 5458 { 5459 uint32 rval; 5460 5461 if (time_id < 0 || time_id > _AP_NUM_TIME_DOMAIN - 1) { 5462 return SOC_E_PARAM; 5463 } 5464 5465 if (time_value == NULL) { 5466 return SOC_E_PARAM; 5467 } 5468 5469 rval = 0; 5470 SOC_IF_ERROR_RETURN(READ_TIME_DOMAINr(unit, &rval)); 5471 *time_value = soc_reg_field_get(unit, TIME_DOMAINr, rval, 5472 time_domain1[unit][time_id].field); 5473 5474 return SOC_E_NONE; 5475 } 5476 5477 5478 5479 5480 STATIC int 5481 _bcm_ap_cosq_time_domain_set(int unit, int time_value, int *time_id) 5482 { 5483 uint32 rval; 5484 int rv = SOC_E_NONE; 5485 int id; 5486 5487 if (time_value < 0 || time_value > 63) { 5488 return SOC_E_PARAM; 5489 } 5490 5491 rval = 0; 5492 SOC_IF_ERROR_RETURN(READ_TIME_DOMAINr(unit, &rval)); 5493 for (id = 0; id < _AP_NUM_TIME_DOMAIN; id++) {/* Find a unset field from TIME_0 to TIME_3 */ 5494 if (!time_domain1[unit][id].ref_count) { 5495 soc_reg_field_set(unit, TIME_DOMAINr, &rval, time_domain1[unit][id].field, 5496 time_value); 5497 time_domain1[unit][id].ref_count++; 5498 break; 5499 } 5500 } 5501 5502 if(id == _AP_NUM_TIME_DOMAIN){/* No field in TIME_DOMAINr is free,return ERR*/ 5503 rv = BCM_E_RESOURCE; 5504 } 5505 5506 if(time_id){ 5507 *time_id = id; 5508 } 5509 5510 SOC_IF_ERROR_RETURN(WRITE_TIME_DOMAINr(unit, rval)); 5511 return rv; 5512 } 5513 5514 STATIC int 5515 _bcm_ap_cosq_wred_index_resolve(int unit, bcm_port_t port, 5516 bcm_cos_queue_t cosq, uint32 flags, uint32 lflags, 5517 bcm_port_t *local_port, int *index_start, int *index_end, 5518 int *port_id, int *pool_id) 5519 { 5520 int index; 5521 int to_index = -1; 5522 int start_pool_idx; 5523 soc_info_t *si; 5524 int phy_port, mmu_port = 0; 5525 int service_pool = 0; 5526 bcm_port_t local_p = -1; 5527 5528 if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 5529 return BCM_E_PARAM; 5530 } 5531 5532 if((lflags & BCM_COSQ_DISCARD_DEVICE) || (flags & BCM_COSQ_DISCARD_DEVICE)) { 5533 if((port == -1) || (cosq == -1)) { 5534 index = _BCM_WRED_GLOBAL_SERVICE_POOL; 5535 to_index = index + 3; 5536 } else { 5537 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_index_resolve(unit, port, cosq, 5538 _BCM_AP_COSQ_INDEX_STYLE_WRED_POOL, 5539 NULL, &start_pool_idx, NULL)); 5540 index = to_index = _BCM_WRED_GLOBAL_SERVICE_POOL + start_pool_idx; 5541 } 5542 } else { 5543 if ((lflags & BCM_COSQ_DISCARD_PORT) || (flags & BCM_COSQ_DISCARD_PORT)) { 5544 if (port == -1) { 5545 return BCM_E_PARAM; 5546 } 5547 BCM_IF_ERROR_RETURN 5548 (_bcm_ap_cosq_index_resolve(unit, port, cosq, 5549 _BCM_AP_COSQ_INDEX_STYLE_WRED_PORT, 5550 local_port, &index, NULL)); 5551 if (cosq != -1) { 5552 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_index_resolve(unit, port, cosq, 5553 _BCM_AP_COSQ_INDEX_STYLE_WRED_POOL, 5554 NULL, &start_pool_idx, NULL)); 5555 index = to_index = index + start_pool_idx; 5556 } else { 5557 to_index = index + 3; 5558 } 5559 } else { 5560 BCM_IF_ERROR_RETURN 5561 (_bcm_ap_cosq_index_resolve(unit, port, cosq == -1 ? 0:cosq, 5562 _BCM_AP_COSQ_INDEX_STYLE_WRED, 5563 &local_p, &index, NULL)); 5564 5565 si = &SOC_INFO(unit); 5566 phy_port = si->port_l2p_mapping[local_p]; 5567 mmu_port = si->port_p2m_mapping[phy_port]; 5568 5569 BCM_IF_ERROR_RETURN 5570 (_bcm_ap_cosq_index_resolve(unit, port, cosq == -1 ? 0:cosq, 5571 _BCM_AP_COSQ_INDEX_STYLE_WRED_POOL, 5572 NULL, &start_pool_idx, NULL)); 5573 service_pool = start_pool_idx; 5574 5575 if(cosq == -1) { 5576 to_index = index + NUM_COS(unit) - 1; 5577 } else { 5578 to_index = index; 5579 } 5580 } 5581 } 5582 5583 if (index < 0) { 5584 return BCM_E_PARAM; 5585 } 5586 5587 if (local_port != NULL) { 5588 *local_port = local_p; 5589 } 5590 if (index_start != NULL) { 5591 *index_start = index; 5592 } 5593 if (index_end != NULL) { 5594 *index_end = to_index; 5595 } 5596 if (port_id != NULL) { 5597 *port_id = mmu_port; 5598 } 5599 if (pool_id != NULL) { 5600 *pool_id = service_pool; 5601 } 5602 5603 return BCM_E_NONE; 5604 } 5605 5606 /* 5607 * Function: 5608 * _bcm_ap_cosq_wred_set 5609 * Purpose: 5610 * Configure unicast queue WRED setting 5611 * Parameters: 5612 * unit - (IN) unit number 5613 * port - (IN) port number or GPORT identifier 5614 * cosq - (IN) COS queue number 5615 * flags - (IN) BCM_COSQ_DISCARD_XXX 5616 * min_thresh - (IN) 5617 * max_thresh - (IN) 5618 * drop_probablity - (IN) 5619 * gain - (IN) 5620 * ignore_enable_flags - (IN) 5621 * Returns: 5622 * BCM_E_XXX 5623 * Notes: 5624 * If port is any form of local port, cosq is the hardware queue index. 5625 */ 5626 STATIC int 5627 _bcm_ap_cosq_wred_set(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 5628 uint32 flags, uint32 min_thresh, uint32 max_thresh, 5629 int drop_probability, int gain, int ignore_enable_flags, 5630 uint32 lflags,int refresh_time) 5631 { 5632 soc_mem_t wred_mem; 5633 bcm_port_t local_port = -1; 5634 int index; 5635 uint32 profile_index, old_profile_index; 5636 mmu_wred_drop_curve_profile_0_entry_t entry_tcp_green; 5637 mmu_wred_drop_curve_profile_1_entry_t entry_tcp_yellow; 5638 mmu_wred_drop_curve_profile_2_entry_t entry_tcp_red; 5639 mmu_wred_drop_curve_profile_3_entry_t entry_nontcp_green; 5640 mmu_wred_drop_curve_profile_4_entry_t entry_nontcp_yellow; 5641 mmu_wred_drop_curve_profile_5_entry_t entry_nontcp_red; 5642 mmu_wred_config_entry_t qentry; 5643 void *entries[6]; 5644 soc_mem_t mems[6]; 5645 int rate, i, jj, to_index = -1, exists = 0; 5646 int time_id,time,old_time,current_time_sel; 5647 int port_id = 0, pool_id = 0; 5648 int rv = SOC_E_NONE; 5649 uint32 rval; 5650 static soc_mem_t wred_mems[6] = { 5651 MMU_WRED_DROP_CURVE_PROFILE_0_X_PIPEm, 5652 MMU_WRED_DROP_CURVE_PROFILE_1_X_PIPEm, 5653 MMU_WRED_DROP_CURVE_PROFILE_2_X_PIPEm, 5654 MMU_WRED_DROP_CURVE_PROFILE_3_X_PIPEm, 5655 MMU_WRED_DROP_CURVE_PROFILE_4_X_PIPEm, 5656 MMU_WRED_DROP_CURVE_PROFILE_5_X_PIPEm 5657 }; 5658 5659 5660 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_wred_index_resolve(unit, port, cosq, 5661 flags, lflags, &local_port, &index, &to_index, 5662 &port_id, &pool_id)); 5663 5664 /* WRED doesn't work on CPU/LB Ports */ 5665 if (IS_LB_PORT(unit, local_port) || IS_CPU_PORT(unit, local_port)) { 5666 return BCM_E_PORT; 5667 } 5668 5669 for(jj = index; jj <= to_index; jj++) { 5670 wred_mem = MMU_WRED_CONFIG_X_PIPEm; 5671 5672 BCM_IF_ERROR_RETURN 5673 (soc_mem_read(unit, wred_mem, MEM_BLOCK_ALL, jj, &qentry)); 5674 5675 old_profile_index = 0xffffffff; 5676 if (flags & (BCM_COSQ_DISCARD_NONTCP | BCM_COSQ_DISCARD_COLOR_ALL | 5677 BCM_COSQ_DISCARD_TCP)) { 5678 old_profile_index = soc_mem_field32_get(unit, wred_mem, 5679 &qentry, PROFILE_INDEXf); 5680 entries[0] = &entry_tcp_green; 5681 entries[1] = &entry_tcp_yellow; 5682 entries[2] = &entry_tcp_red; 5683 entries[3] = &entry_nontcp_green; 5684 entries[4] = &entry_nontcp_yellow; 5685 entries[5] = &entry_nontcp_red; 5686 BCM_IF_ERROR_RETURN 5687 (soc_profile_mem_get(unit, _bcm_ap_wred_profile[unit], 5688 old_profile_index, 1, entries)); 5689 for (i = 0; i < 6; i++) { 5690 mems[i] = INVALIDm; 5691 } 5692 if (!(flags & (BCM_COSQ_DISCARD_COLOR_GREEN | 5693 BCM_COSQ_DISCARD_COLOR_YELLOW | 5694 BCM_COSQ_DISCARD_COLOR_RED))) { 5695 flags |= BCM_COSQ_DISCARD_COLOR_ALL; 5696 } 5697 if (!(flags & BCM_COSQ_DISCARD_NONTCP) || (flags & BCM_COSQ_DISCARD_TCP)) { 5698 if (flags & BCM_COSQ_DISCARD_COLOR_GREEN) { 5699 mems[0] = MMU_WRED_DROP_CURVE_PROFILE_0_X_PIPEm; 5700 } 5701 if (flags & BCM_COSQ_DISCARD_COLOR_YELLOW) { 5702 mems[1] = MMU_WRED_DROP_CURVE_PROFILE_1_X_PIPEm; 5703 } 5704 if (flags & BCM_COSQ_DISCARD_COLOR_RED) { 5705 mems[2] = MMU_WRED_DROP_CURVE_PROFILE_2_X_PIPEm; 5706 } 5707 } 5708 if (flags & BCM_COSQ_DISCARD_NONTCP) { 5709 if (flags & BCM_COSQ_DISCARD_COLOR_GREEN) { 5710 mems[3] = MMU_WRED_DROP_CURVE_PROFILE_3_X_PIPEm; 5711 } 5712 if (flags & BCM_COSQ_DISCARD_COLOR_YELLOW) { 5713 mems[4] = MMU_WRED_DROP_CURVE_PROFILE_4_X_PIPEm; 5714 } 5715 if (flags & BCM_COSQ_DISCARD_COLOR_RED) { 5716 mems[5] = MMU_WRED_DROP_CURVE_PROFILE_5_X_PIPEm; 5717 } 5718 } 5719 rate = _bcm_ap_percent_to_drop_prob(drop_probability); 5720 for (i = 0; i < 6; i++) { 5721 exists = 0; 5722 if ((soc_mem_field32_get(unit, wred_mems[i], entries[i], 5723 MIN_THDf) != 0x1ffff) && (mems[i] == INVALIDm)) { 5724 mems[i] = wred_mems[i]; 5725 exists = 1; 5726 } else { 5727 soc_mem_field32_set(unit, wred_mems[i], entries[i], 5728 MIN_THDf, (mems[i] == INVALIDm) ? 0x1ffff : min_thresh); 5729 } 5730 5731 if ((soc_mem_field32_get(unit, wred_mems[i], entries[i], 5732 MAX_THDf) != 0x1ffff) && ((mems[i] == INVALIDm) || exists)) { 5733 mems[i] = wred_mems[i]; 5734 exists = 1; 5735 } else { 5736 soc_mem_field32_set(unit, wred_mems[i], entries[i], 5737 MAX_THDf, (mems[i] == INVALIDm) ? 0x1ffff :max_thresh); 5738 } 5739 5740 if (!exists) { 5741 soc_mem_field32_set(unit, wred_mems[i], entries[i], 5742 MAX_DROP_RATEf, (mems[i] == INVALIDm) ? 0 : rate); 5743 } 5744 } 5745 BCM_IF_ERROR_RETURN 5746 (soc_profile_mem_add(unit, _bcm_ap_wred_profile[unit], 5747 entries, 1, &profile_index)); 5748 soc_mem_field32_set(unit, wred_mem, &qentry, PROFILE_INDEXf, profile_index); 5749 soc_mem_field32_set(unit, wred_mem, &qentry, WEIGHTf, gain); 5750 } 5751 5752 /* Some APIs only modify profiles */ 5753 if (!ignore_enable_flags) { 5754 soc_mem_field32_set(unit, wred_mem, &qentry, CAP_AVERAGEf, 5755 flags & BCM_COSQ_DISCARD_CAP_AVERAGE ? 1 : 0); 5756 soc_mem_field32_set(unit, wred_mem, &qentry, WRED_ENf, 5757 flags & BCM_COSQ_DISCARD_ENABLE ? 1 : 0); 5758 soc_mem_field32_set(unit, wred_mem, &qentry, ECN_MARKING_ENf, 5759 flags & BCM_COSQ_DISCARD_MARK_CONGESTION ? 1 : 0); 5760 soc_mem_field32_set(unit, wred_mem, &qentry, PORTIDf, 5761 port_id ? port_id : 0); 5762 soc_mem_field32_set(unit, wred_mem, &qentry, SPIDf, 5763 pool_id ? pool_id : 0); 5764 } 5765 5766 current_time_sel = soc_mem_field32_get(unit, wred_mem, &qentry, TIME_DOMAIN_SELf); 5767 time = (refresh_time + 7) / 8 - 1; /* Round it up to avoid negative value */ 5768 exists = 0; 5769 /* If the time value exist, update reference count only */ 5770 for (time_id = 0; time_id < _AP_NUM_TIME_DOMAIN; time_id++) { 5771 BCM_IF_ERROR_RETURN 5772 (_bcm_ap_cosq_time_domain_get(unit, time_id, &old_time)); 5773 if (time == old_time) { 5774 /* Only set exist flag if this entry reference count already update, 5775 otherwise update reference count */ 5776 if(time_id != current_time_sel){ 5777 soc_mem_field32_set(unit, wred_mem, &qentry, TIME_DOMAIN_SELf, 5778 time_id); 5779 time_domain1[unit][time_id].ref_count++; 5780 time_domain1[unit][current_time_sel].ref_count--; 5781 } 5782 exists = 1; 5783 break; 5784 } 5785 } 5786 5787 if(!exists){ 5788 rv = _bcm_ap_cosq_time_domain_set(unit, time, &time_id); 5789 if(rv == SOC_E_NONE){ 5790 soc_mem_field32_set(unit, wred_mem, &qentry, TIME_DOMAIN_SELf, 5791 time_id); 5792 time_domain1[unit][current_time_sel].ref_count--; 5793 } else { 5794 return rv; 5795 } 5796 } 5797 /* 5798 *Disabling the wred sampling and writing to wred mem 5799 *This was required for an hardware bug and can be taken out for apache b0 5800 */ 5801 BCM_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, &rval)); 5802 soc_reg_field_set(unit, MISCCONFIGr, &rval, REFRESH_ENf, 0); 5803 BCM_IF_ERROR_RETURN(WRITE_MISCCONFIGr(unit, rval)); 5804 5805 BCM_IF_ERROR_RETURN( 5806 soc_mem_write(unit, wred_mem, MEM_BLOCK_ALL, jj, &qentry)); 5807 5808 BCM_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, &rval)); 5809 soc_reg_field_set(unit, MISCCONFIGr, &rval, REFRESH_ENf, 1); 5810 BCM_IF_ERROR_RETURN(WRITE_MISCCONFIGr(unit, rval)); 5811 5812 if (old_profile_index != 0xffffffff) { 5813 SOC_IF_ERROR_RETURN 5814 (soc_profile_mem_delete(unit, _bcm_ap_wred_profile[unit], 5815 old_profile_index)); 5816 } 5817 } 5818 5819 return rv; 5820 } 5821 5822 /* 5823 * Function: 5824 * _bcm_ap_cosq_wred_get 5825 * Purpose: 5826 * Get unicast queue WRED setting 5827 * Parameters: 5828 * unit - (IN) unit number 5829 * port - (IN) port number or GPORT identifier 5830 * cosq - (IN) COS queue number 5831 * flags - (IN/OUT) BCM_COSQ_DISCARD_XXX 5832 * min_thresh - (OUT) 5833 * max_thresh - (OUT) 5834 * drop_probablity - (OUT) 5835 * gain - (OUT) 5836 * Returns: 5837 * BCM_E_XXX 5838 * Notes: 5839 * If port is any form of local port, cosq is the hardware queue index. 5840 */ 5841 STATIC int 5842 _bcm_ap_cosq_wred_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 5843 uint32 *flags, uint32 *min_thresh, uint32 *max_thresh, 5844 int *drop_probability, int *gain, uint32 lflags,int *refresh_time) 5845 { 5846 bcm_port_t local_port = -1; 5847 int index, profile_index; 5848 mmu_wred_drop_curve_profile_0_entry_t entry_tcp_green; 5849 mmu_wred_drop_curve_profile_1_entry_t entry_tcp_yellow; 5850 mmu_wred_drop_curve_profile_2_entry_t entry_tcp_red; 5851 mmu_wred_drop_curve_profile_3_entry_t entry_nontcp_green; 5852 mmu_wred_drop_curve_profile_4_entry_t entry_nontcp_yellow; 5853 mmu_wred_drop_curve_profile_5_entry_t entry_nontcp_red; 5854 void *entries[6]; 5855 void *entry_p; 5856 soc_mem_t mem; 5857 soc_mem_t wred_mem = 0; 5858 mmu_wred_config_entry_t qentry; 5859 int rate, time_id,time; 5860 5861 5862 if ((port == -1 ) && 5863 !((*flags & BCM_COSQ_DISCARD_DEVICE) || (lflags & BCM_COSQ_DISCARD_DEVICE))) { 5864 return (BCM_E_PORT); 5865 } 5866 5867 local_port = -1; 5868 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_wred_index_resolve(unit, port, cosq, 5869 *flags, lflags, &local_port, &index, NULL, NULL, NULL)); 5870 5871 /* WRED doesn't work on CPU/LB Ports */ 5872 if (IS_LB_PORT(unit, local_port) || IS_CPU_PORT(unit, local_port)) { 5873 return BCM_E_PORT; 5874 } 5875 wred_mem = MMU_WRED_CONFIG_X_PIPEm; 5876 5877 BCM_IF_ERROR_RETURN 5878 (soc_mem_read(unit, wred_mem, MEM_BLOCK_ALL, index, &qentry)); 5879 profile_index = soc_mem_field32_get(unit, wred_mem, 5880 &qentry, PROFILE_INDEXf); 5881 5882 if (!(*flags & BCM_COSQ_DISCARD_NONTCP)) { 5883 if (*flags & BCM_COSQ_DISCARD_COLOR_GREEN) { 5884 mem = MMU_WRED_DROP_CURVE_PROFILE_0_X_PIPEm; 5885 entry_p = &entry_tcp_green; 5886 } else if (*flags & BCM_COSQ_DISCARD_COLOR_YELLOW) { 5887 mem = MMU_WRED_DROP_CURVE_PROFILE_1_X_PIPEm; 5888 entry_p = &entry_tcp_yellow; 5889 } else if (*flags & BCM_COSQ_DISCARD_COLOR_RED) { 5890 mem = MMU_WRED_DROP_CURVE_PROFILE_2_X_PIPEm; 5891 entry_p = &entry_tcp_red; 5892 } else { 5893 mem = MMU_WRED_DROP_CURVE_PROFILE_0_X_PIPEm; 5894 entry_p = &entry_tcp_green; 5895 } 5896 } else { 5897 if (*flags & BCM_COSQ_DISCARD_COLOR_GREEN) { 5898 mem = MMU_WRED_DROP_CURVE_PROFILE_3_X_PIPEm; 5899 entry_p = &entry_nontcp_green; 5900 } else if (*flags & BCM_COSQ_DISCARD_COLOR_YELLOW) { 5901 mem = MMU_WRED_DROP_CURVE_PROFILE_4_X_PIPEm; 5902 entry_p = &entry_nontcp_yellow; 5903 } else if (*flags & BCM_COSQ_DISCARD_COLOR_RED) { 5904 mem = MMU_WRED_DROP_CURVE_PROFILE_5_X_PIPEm; 5905 entry_p = &entry_nontcp_red; 5906 } else { 5907 mem = MMU_WRED_DROP_CURVE_PROFILE_3_X_PIPEm; 5908 entry_p = &entry_nontcp_green; 5909 } 5910 } 5911 5912 entries[0] = &entry_tcp_green; 5913 entries[1] = &entry_tcp_yellow; 5914 entries[2] = &entry_tcp_red; 5915 entries[3] = &entry_nontcp_green; 5916 entries[4] = &entry_nontcp_yellow; 5917 entries[5] = &entry_nontcp_red; 5918 BCM_IF_ERROR_RETURN 5919 (soc_profile_mem_get(unit, _bcm_ap_wred_profile[unit], 5920 profile_index, 1, entries)); 5921 if (min_thresh != NULL) { 5922 *min_thresh = soc_mem_field32_get(unit, mem, entry_p, MIN_THDf); 5923 } 5924 if (max_thresh != NULL) { 5925 *max_thresh = soc_mem_field32_get(unit, mem, entry_p, MAX_THDf); 5926 } 5927 if (drop_probability != NULL) { 5928 rate = soc_mem_field32_get(unit, mem, entry_p, MAX_DROP_RATEf); 5929 *drop_probability = _bcm_ap_drop_prob_to_percent(rate); 5930 } 5931 5932 if (gain) { 5933 *gain = soc_mem_field32_get(unit, wred_mem, &qentry, WEIGHTf); 5934 } 5935 5936 if (refresh_time) { 5937 time_id = soc_mem_field32_get(unit, wred_mem, &qentry, TIME_DOMAIN_SELf); 5938 BCM_IF_ERROR_RETURN 5939 (_bcm_ap_cosq_time_domain_get(unit,time_id,&time)); 5940 *refresh_time = (time + 1) * 8; 5941 } 5942 5943 *flags &= ~(BCM_COSQ_DISCARD_CAP_AVERAGE | BCM_COSQ_DISCARD_ENABLE); 5944 if (soc_mem_field32_get(unit, wred_mem, &qentry, CAP_AVERAGEf)) { 5945 *flags |= BCM_COSQ_DISCARD_CAP_AVERAGE; 5946 } 5947 if (soc_mem_field32_get(unit, wred_mem, &qentry, WRED_ENf)) { 5948 *flags |= BCM_COSQ_DISCARD_ENABLE; 5949 } 5950 if (soc_mem_field32_get(unit, wred_mem, &qentry, ECN_MARKING_ENf)) { 5951 *flags |= BCM_COSQ_DISCARD_MARK_CONGESTION; 5952 } 5953 return BCM_E_NONE; 5954 } 5955 5956 /* 5957 * Function: 5958 * _bcm_ap_cosq_sched_get 5959 * Purpose: 5960 * Get scheduling mode setting 5961 * Parameters: 5962 * unit - (IN) unit number 5963 * port - (IN) port number or GPORT identifier 5964 * cosq - (IN) COS queue number 5965 * mode - (OUT) scheduling mode (BCM_COSQ_XXX) 5966 * num_weights - (IN) number of entries in weights array 5967 * weights - (OUT) weights array 5968 * Returns: 5969 * BCM_E_XXX 5970 */ 5971 STATIC int 5972 _bcm_ap_cosq_sched_get(int unit, bcm_port_t gport, bcm_cos_queue_t cosq, 5973 int *mode, int *weight) 5974 { 5975 _bcm_ap_cosq_node_t *node, *child_node , *s1_node; 5976 bcm_port_t local_port; 5977 int sch_index, lvl = SOC_APACHE_NODE_LVL_L1; 5978 soc_apache_sched_mode_e sched_mode; 5979 int index, numq; 5980 _bcm_ap_mmu_info_t *mmu_info; 5981 soc_info_t *si; 5982 5983 if ((mmu_info = _bcm_ap_mmu_info[unit]) == NULL) { 5984 return BCM_E_INIT; 5985 } 5986 5987 if (cosq < 0) { 5988 if (cosq == -1) { 5989 /* caller needs to resolve the wild card value (-1) */ 5990 return BCM_E_INTERNAL; 5991 } else { /* reject all other negative value */ 5992 return BCM_E_PARAM; 5993 } 5994 } 5995 5996 if(_BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, gport)){ 5997 BCM_IF_ERROR_RETURN( 5998 _bcmi_coe_subport_physical_port_get(unit, gport, &local_port)); 5999 } else { 6000 BCM_IF_ERROR_RETURN 6001 (_bcm_ap_cosq_localport_resolve(unit, gport, &local_port)); 6002 } 6003 si = &SOC_INFO(unit); 6004 if (BCM_GPORT_IS_SCHEDULER(gport)) { /* ETS style scheduler */ 6005 BCM_IF_ERROR_RETURN 6006 (_bcm_ap_cosq_node_get(unit, gport, 0, NULL, &local_port, NULL, 6007 &node)); 6008 if ((node->numq >= 0) && (cosq > node->numq)) { 6009 return BCM_E_PARAM; 6010 } 6011 BCM_IF_ERROR_RETURN 6012 (_bcm_ap_cosq_child_node_at_input(node, cosq, &child_node)); 6013 } else if (_BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT 6014 (unit, gport)) { 6015 if (soc_feature(unit, 6016 soc_feature_mmu_hqos_four_level)) { 6017 BCM_IF_ERROR_RETURN 6018 (_bcm_ap_get_s1_node(unit, gport, 6019 &s1_node)); 6020 index = s1_node->coe_base_index; 6021 child_node = &mmu_info->queue_node[index + cosq ]; 6022 if (!child_node) { 6023 return BCM_E_INTERNAL; 6024 } 6025 if (child_node->attached_to_input == -1) { 6026 return BCM_E_NOT_FOUND; 6027 } 6028 node = child_node->parent ; 6029 if (!node) { 6030 return BCM_E_INTERNAL; 6031 } 6032 6033 } else { 6034 return BCM_E_PARAM; 6035 } 6036 } else { 6037 if (IS_CPU_PORT(unit, local_port)) { 6038 numq = SOC_INFO(unit).num_cpu_cosq; 6039 if (cosq >= numq) { 6040 return BCM_E_PARAM; 6041 } 6042 index = soc_apache_l2_hw_index(unit, 6043 si->port_cosq_base[local_port] + cosq, 0); 6044 } else { 6045 index = soc_apache_l2_hw_index(unit, 6046 si->port_uc_cosq_base[local_port], 1); 6047 } 6048 6049 child_node = &mmu_info->queue_node[index]; 6050 if (!child_node) { 6051 return BCM_E_INTERNAL; 6052 } 6053 if (child_node->attached_to_input == -1) { 6054 return BCM_E_NOT_FOUND; 6055 } 6056 node = child_node->parent; 6057 if (node && !IS_CPU_PORT(unit, local_port)) { 6058 child_node = node; 6059 node = node->parent; 6060 if (!node) { 6061 return BCM_E_INTERNAL; 6062 } 6063 if ((node->numq >= 0) && (cosq > node->numq)) { 6064 return BCM_E_PARAM; 6065 } 6066 BCM_IF_ERROR_RETURN 6067 (_bcm_ap_cosq_child_node_at_input(node, cosq, 6068 &child_node)); 6069 } 6070 } 6071 6072 if (!child_node) { 6073 return BCM_E_INTERNAL; 6074 } 6075 6076 sch_index = child_node->hw_index; 6077 lvl = child_node->level; 6078 6079 BCM_IF_ERROR_RETURN( 6080 soc_apache_cosq_get_sched_mode(unit, local_port, lvl, sch_index, 6081 &sched_mode, weight)); 6082 6083 switch(sched_mode) { 6084 case SOC_APACHE_SCHED_MODE_STRICT: 6085 *mode = BCM_COSQ_STRICT; 6086 break; 6087 case SOC_APACHE_SCHED_MODE_WRR: 6088 *mode = BCM_COSQ_WEIGHTED_ROUND_ROBIN; 6089 break; 6090 case SOC_APACHE_SCHED_MODE_WDRR: 6091 *mode = BCM_COSQ_DEFICIT_ROUND_ROBIN; 6092 break; 6093 default: 6094 return BCM_E_INTERNAL; 6095 break; 6096 } 6097 return BCM_E_NONE; 6098 } 6099 6100 /* 6101 * Function: 6102 * _bcm_ap_lls_node_count 6103 * Purpose: 6104 * This function counts the number of nodes at a particular level 6105 * Parameters: 6106 * unit - (IN) unit number 6107 * port - (IN) local port number 6108 * level - (IN) level of the node in LLS 6109 * hw_index - (IN) h/w index of the node 6110 * cookie - (IN) state of the LLS structure 6111 */ 6112 STATIC int _bcm_ap_lls_node_count(int unit, int port, int level, 6113 int hw_index, void *cookie) 6114 { 6115 _bcm_ap_lls_info_t *i_lls_tree = (_bcm_ap_lls_info_t *) cookie; 6116 i_lls_tree->node_count[level] += 1; 6117 return 0; 6118 } 6119 6120 /* 6121 * Function: 6122 * _bcm_ap_num_ones 6123 * Purpose: 6124 * This function calculates the numbers of 1s in the binary format 6125 * of the number 6126 * Parameters: 6127 * m - (IN) number 6128 * Returns: 6129 * The number of 1s in the binary format of the number 6130 */ 6131 STATIC uint32 6132 _bcm_ap_num_ones(uint32 m) 6133 { 6134 uint32 i = 0; 6135 6136 while (m) { 6137 m &= m - 1; 6138 i += 1; 6139 } 6140 return i; 6141 } 6142 6143 STATIC int 6144 _bcm_ap_cosq_traverse_lls_tree(int unit, int port, _bcm_ap_cosq_node_t *node, 6145 _soc_apache_lls_traverse_cb cb, void *cookie) 6146 { 6147 if (node->child) { 6148 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_traverse_lls_tree(unit, port, 6149 node->child, 6150 cb, cookie)); 6151 } 6152 6153 if (node->sibling) { 6154 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_traverse_lls_tree(unit, port, 6155 node->sibling, cb, cookie)); 6156 } 6157 6158 if (node->level != SOC_APACHE_NODE_LVL_ROOT) { 6159 BCM_IF_ERROR_RETURN(cb(unit, port, node->level, node->hw_index, cookie)); 6160 } 6161 6162 return BCM_E_NONE; 6163 } 6164 6165 /* 6166 * Function: 6167 * _bcm_ap_lls_shapers_remove 6168 * Purpose: 6169 * This function removes shapers on the nodes by setting them 6170 * to the max rate and setting min to 0 so that each node can only schedule upto 6171 * the max rate. It also calculates the leaky bucket parameters based on 6172 * the kbit max 6173 * Parameters: 6174 * unit - (IN) unit number 6175 * port - (IN) local port number 6176 * level - (IN) level of the node in LLS 6177 * hw_index - (IN) h/w index of the node 6178 * cookie - (IN) state of the LLS structure 6179 */ 6180 STATIC int _bcm_ap_lls_shapers_remove(int unit, int port, int level, 6181 int hw_index, void *cookie) 6182 { 6183 _bcm_ap_lls_info_t *i_lls_tree = (_bcm_ap_lls_info_t *) cookie; 6184 soc_mem_t config_mem; 6185 uint32 *p_entry; 6186 uint32 entry[SOC_MAX_MEM_WORDS]; 6187 int index, kbit_max, kbit_min; 6188 uint32 meter_flags; 6189 int max_l1_table = 2 ,max_l2_table = 8 ; 6190 uint32 bucketsize_max, granularity_max, refresh_rate_max, 6191 refresh_bitsize = 0, bucket_bitsize = 0; 6192 6193 soc_mem_t mtro_l1[] = { MMU_MTRO_L1_MEM_0m, 6194 MMU_MTRO_L1_MEM_1m }; 6195 soc_mem_t mtro_l2[] = { MMU_MTRO_L2_MEM_0m, 6196 MMU_MTRO_L2_MEM_1m, 6197 MMU_MTRO_L2_MEM_2m, 6198 MMU_MTRO_L2_MEM_3m, 6199 MMU_MTRO_L2_MEM_4m, 6200 MMU_MTRO_L2_MEM_5m, 6201 MMU_MTRO_L2_MEM_6m, 6202 MMU_MTRO_L2_MEM_7m }; 6203 6204 if (level == SOC_APACHE_NODE_LVL_MAX) { 6205 return SOC_E_PARAM; 6206 } 6207 6208 if (i_lls_tree->child_lvl != level) { 6209 return BCM_E_NONE; 6210 } 6211 6212 if (level == SOC_APACHE_NODE_LVL_S1) { 6213 config_mem = MMU_MTRO_S1_MEM_0m; 6214 } else if (level == SOC_APACHE_NODE_LVL_L0) { 6215 config_mem = MMU_MTRO_L0_MEM_0m; 6216 } else if (level == SOC_APACHE_NODE_LVL_L1) { 6217 config_mem = mtro_l1[hw_index % max_l1_table]; 6218 hw_index /= max_l1_table; 6219 } else if (level == SOC_APACHE_NODE_LVL_L2) { 6220 config_mem = mtro_l2[hw_index % max_l2_table]; 6221 hw_index /= max_l2_table; 6222 } else { 6223 return BCM_E_PARAM; 6224 } 6225 6226 if (config_mem == INVALIDm) { 6227 return BCM_E_PARAM; 6228 } 6229 6230 index = i_lls_tree->offset[level] + i_lls_tree->count[level]; 6231 p_entry = &i_lls_tree->mtro_entries[index * SOC_MAX_MEM_WORDS]; 6232 6233 if (*p_entry == 0) { 6234 SOC_IF_ERROR_RETURN(soc_mem_read(unit, config_mem, MEM_BLOCK_ALL, hw_index, 6235 p_entry)); 6236 } 6237 6238 sal_memset(entry, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS); 6239 6240 6241 meter_flags = 0; 6242 6243 if (config_mem == MMU_MTRO_S1_MEM_0m) { 6244 refresh_bitsize = soc_mem_field_length(unit, config_mem, REFRESHf); 6245 bucket_bitsize = soc_mem_field_length(unit, config_mem, THD_SELf); 6246 } else { 6247 refresh_bitsize = soc_mem_field_length(unit, config_mem, MAX_REFRESHf); 6248 bucket_bitsize = soc_mem_field_length(unit, config_mem, MAX_THD_SELf); 6249 } 6250 6251 /* Setting the max metering configuration */ 6252 kbit_max = i_lls_tree->kbit_max; 6253 BCM_IF_ERROR_RETURN 6254 (_bcm_td_rate_to_bucket_encoding(unit, kbit_max, kbit_max, 6255 meter_flags, refresh_bitsize, 6256 bucket_bitsize, &refresh_rate_max, 6257 &bucketsize_max, &granularity_max)); 6258 6259 if (config_mem == MMU_MTRO_S1_MEM_0m) { 6260 soc_mem_field32_set(unit, config_mem, entry, METER_GRANf, 6261 granularity_max); 6262 soc_mem_field32_set(unit, config_mem, entry, REFRESHf, 6263 refresh_rate_max); 6264 soc_mem_field32_set(unit, config_mem, entry, THD_SELf, 6265 bucketsize_max); 6266 } else { 6267 soc_mem_field32_set(unit, config_mem, entry, MAX_METER_GRANf, 6268 granularity_max); 6269 soc_mem_field32_set(unit, config_mem, entry, MAX_REFRESHf, 6270 refresh_rate_max); 6271 soc_mem_field32_set(unit, config_mem, entry, MAX_THD_SELf, 6272 bucketsize_max); 6273 6274 6275 /* Setting the min metering configuration */ 6276 kbit_min = i_lls_tree->kbit_min; 6277 BCM_IF_ERROR_RETURN 6278 (_bcm_td_rate_to_bucket_encoding(unit, kbit_min, kbit_min, 6279 meter_flags, refresh_bitsize, 6280 bucket_bitsize, &refresh_rate_max, 6281 &bucketsize_max, &granularity_max)); 6282 6283 soc_mem_field32_set(unit, config_mem, entry, MIN_METER_GRANf, 6284 granularity_max); 6285 soc_mem_field32_set(unit, config_mem, entry, MIN_REFRESHf, 6286 refresh_rate_max); 6287 soc_mem_field32_set(unit, config_mem, entry, MIN_THD_SELf, 6288 bucketsize_max); 6289 } 6290 6291 BCM_IF_ERROR_RETURN 6292 (soc_mem_write(unit, config_mem, MEM_BLOCK_ALL, hw_index, entry)); 6293 6294 sal_usleep(100); 6295 i_lls_tree->count[level] += 1; 6296 return 0; 6297 } 6298 6299 /* 6300 * Function: 6301 * _bcm_ap_lls_shapers_restore 6302 * Purpose: 6303 * This function restores the shapers on the nodes 6304 * Parameters: 6305 * unit - (IN) unit number 6306 * port - (IN) local port number 6307 * level - (IN) level of the node in LLS 6308 * hw_index - (IN) h/w index of the node 6309 * cookie - (IN) state of the LLS structure 6310 */ 6311 STATIC int _bcm_ap_lls_shapers_restore(int unit, int port, int level, 6312 int hw_index, void *cookie) 6313 { 6314 _bcm_ap_lls_info_t *i_lls_tree = (_bcm_ap_lls_info_t *) cookie; 6315 soc_mem_t config_mem; 6316 uint32 *p_entry; 6317 int index; 6318 int max_l1_table = 2, max_l2_table = 8; 6319 uint32 entry[SOC_MAX_MEM_WORDS]; 6320 6321 soc_mem_t mtro_l1[] = { MMU_MTRO_L1_MEM_0m, 6322 MMU_MTRO_L1_MEM_1m }; 6323 soc_mem_t mtro_l2[] = { MMU_MTRO_L2_MEM_0m, 6324 MMU_MTRO_L2_MEM_1m, 6325 MMU_MTRO_L2_MEM_2m, 6326 MMU_MTRO_L2_MEM_3m, 6327 MMU_MTRO_L2_MEM_4m, 6328 MMU_MTRO_L2_MEM_5m, 6329 MMU_MTRO_L2_MEM_6m, 6330 MMU_MTRO_L2_MEM_7m }; 6331 6332 if (level == SOC_APACHE_NODE_LVL_MAX) { 6333 return SOC_E_PARAM; 6334 } 6335 6336 if (level == SOC_APACHE_NODE_LVL_S1) { 6337 config_mem = MMU_MTRO_S1_MEM_0m; 6338 } else if (level == SOC_APACHE_NODE_LVL_L0) { 6339 config_mem = MMU_MTRO_L0_MEM_0m; 6340 } else if (level == SOC_APACHE_NODE_LVL_L1) { 6341 config_mem = mtro_l1[hw_index % max_l1_table]; 6342 hw_index /= max_l1_table; 6343 } else if (level == SOC_APACHE_NODE_LVL_L2) { 6344 config_mem = mtro_l2[hw_index % max_l2_table]; 6345 hw_index /= max_l2_table; 6346 } else { 6347 return BCM_E_PARAM; 6348 } 6349 6350 if (i_lls_tree->child_lvl != level) { 6351 return BCM_E_NONE; 6352 } 6353 6354 if (config_mem == INVALIDm) { 6355 return BCM_E_PARAM; 6356 } 6357 6358 6359 if (config_mem != MMU_MTRO_S1_MEM_0m) { 6360 sal_memset(entry, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS); 6361 6362 soc_mem_field32_set(unit, config_mem, entry, MIN_REFRESHf, 6363 500); 6364 soc_mem_field32_set(unit, config_mem, entry, MIN_THD_SELf, 6365 3); 6366 6367 SOC_IF_ERROR_RETURN 6368 (soc_mem_write(unit, config_mem, MEM_BLOCK_ALL, hw_index, entry)); 6369 6370 sal_usleep(100); 6371 } 6372 6373 index = i_lls_tree->offset[level] + i_lls_tree->count[level]; 6374 p_entry = &i_lls_tree->mtro_entries[index * SOC_MAX_MEM_WORDS]; 6375 6376 SOC_IF_ERROR_RETURN(soc_mem_write(unit, config_mem, MEM_BLOCK_ALL, 6377 hw_index, p_entry)); 6378 6379 i_lls_tree->count[level] += 1; 6380 6381 return 0; 6382 } 6383 6384 /* 6385 * Function: 6386 * _bcm_ap_adjust_lls_bw 6387 * Purpose: 6388 * This function adjusts the bandwidth at the level in which the node is 6389 * being switched so that each node gets sufficient bandwidth to do the 6390 * switchover. 6391 * Parameters: 6392 * unit - (IN) unit number 6393 * port - (IN) local port number 6394 * node - (IN) cosq node structure 6395 * child_lvl - (IN) level of the child node 6396 * child_hw_index - (IN) h/w index of the child node 6397 * start - (IN) flag 6398 * i_lls_tree - (OUT) LLS info 6399 * Returns: 6400 * BCM_E_XXX 6401 */ 6402 STATIC int 6403 _bcm_ap_adjust_lls_bw(int unit, bcm_port_t port, _bcm_ap_cosq_node_t *node, 6404 int child_lvl, int child_hw_index, int start, 6405 _bcm_ap_lls_info_t *i_lls_tree) 6406 { 6407 int rv = BCM_E_NONE, count, mem_size, ii, speed, jj; 6408 soc_info_t *si; 6409 if (!soc_feature(unit, soc_feature_vector_based_spri)) { 6410 return BCM_E_NONE; 6411 } 6412 6413 if (IS_LB_PORT(unit, port)) { 6414 return BCM_E_NONE; 6415 } 6416 if (start) { 6417 sal_memset(i_lls_tree, 0, sizeof(_bcm_ap_lls_info_t)); 6418 i_lls_tree->child_lvl = child_lvl; 6419 i_lls_tree->child_hw_index = child_hw_index; 6420 6421 if (node) { 6422 /* get to top node */ 6423 while(node->parent) { node = node->parent; } 6424 6425 if ((rv = _bcm_ap_cosq_traverse_lls_tree(unit, port, node, 6426 _bcm_ap_lls_node_count, i_lls_tree))) { 6427 goto cleanup; 6428 } 6429 } 6430 6431 for (count = 0, ii = 0; ii < SOC_APACHE_NODE_LVL_MAX; ii++) { 6432 count += i_lls_tree->node_count[ii]; 6433 for (jj = ii - 1; jj >= 0; jj--) { 6434 i_lls_tree->offset[ii] += i_lls_tree->node_count[jj]; 6435 } 6436 } 6437 6438 if (count == 0) { 6439 return BCM_E_INIT; 6440 } 6441 6442 mem_size = sizeof(uint32) * SOC_MAX_MEM_WORDS * count; 6443 i_lls_tree->mtro_entries = sal_alloc(mem_size, "lls_war_buf"); 6444 6445 si = &SOC_INFO(unit); 6446 speed = si->port_speed_max[port]; 6447 6448 i_lls_tree->kbit_min = 0; 6449 i_lls_tree->kbit_max = ((speed)/10)/i_lls_tree->node_count[child_lvl]; 6450 6451 for (count = 0, ii = 0; ii < SOC_APACHE_NODE_LVL_MAX; ii++) { 6452 i_lls_tree->count[ii] = 0; 6453 } 6454 6455 sal_memset(i_lls_tree->mtro_entries, 0, mem_size); 6456 6457 if (node) { 6458 6459 /* get to top node */ 6460 while(node->parent) { node = node->parent; } 6461 6462 if ((rv = _bcm_ap_cosq_traverse_lls_tree(unit, port, node, 6463 _bcm_ap_lls_shapers_remove, i_lls_tree))) { 6464 6465 goto cleanup; 6466 } 6467 } 6468 } else { 6469 for (count = 0, ii = 0; ii < SOC_APACHE_NODE_LVL_MAX; ii++) { 6470 i_lls_tree->count[ii] = 0; 6471 } 6472 6473 if (node) { 6474 /* get to top node */ 6475 while(node->parent) { node = node->parent; } 6476 6477 if ((rv = _bcm_ap_cosq_traverse_lls_tree(unit, port, node, 6478 _bcm_ap_lls_shapers_restore, i_lls_tree))) { 6479 goto cleanup; 6480 } 6481 } 6482 6483 if (i_lls_tree->mtro_entries) { 6484 sal_free(i_lls_tree->mtro_entries); 6485 i_lls_tree->mtro_entries = NULL; 6486 } 6487 6488 } 6489 6490 return rv; 6491 6492 cleanup: 6493 /* cleanup */ 6494 if (i_lls_tree->mtro_entries) { 6495 sal_free(i_lls_tree->mtro_entries); 6496 i_lls_tree->mtro_entries = NULL; 6497 } 6498 6499 return rv; 6500 } 6501 6502 /* 6503 * Function: 6504 * _bcm_apache_compute_lls_config 6505 * Purpose: 6506 * This function computes the LLS configuration at each level 6507 * Parameters: 6508 * unit - (IN) unit number 6509 * port - (IN) local port number 6510 * level - (IN) level of the node in LLS 6511 * first_sp_child - (OUT) first sp child 6512 * first_sp_mc_child - (OUT) first so multicast child 6513 * ucmap - (OUT) unicast node map 6514 * spmap - (OUT) SPRI node map 6515 * child_index - (IN) index of the child node 6516 * cur_mode - (IN) current schedling mode of the node 6517 * mode - (IN) new scheduling mode of the node 6518 * max_children - (IN) maximum number of children in the level 6519 * Returns: 6520 * BCM_E_XXX 6521 */ 6522 STATIC int 6523 _bcm_apache_compute_lls_config (int unit, int port, int level, 6524 int *first_sp_child, 6525 int *first_sp_mc_child, 6526 int *num_spri, 6527 uint32 *ucmap, 6528 uint32 *spmap, 6529 int child_index, 6530 soc_apache_sched_mode_e cur_mode, 6531 soc_apache_sched_mode_e mode, 6532 int max_children) 6533 { 6534 uint32 ucm = 0, mcm = 0, cur_spmap, cur_num_spri, lucmap = 0; 6535 int ii, *pfc, uc, mc, fc, oc, *use_fc; 6536 6537 cur_num_spri = _bcm_ap_num_ones(*spmap); 6538 cur_spmap = *spmap; 6539 6540 if (level == SOC_APACHE_NODE_LVL_L1) { 6541 if (IS_CPU_PORT(unit, port)) { 6542 use_fc = first_sp_mc_child; 6543 } else { 6544 use_fc = (child_index >= _BCM_AP_NUM_L2_UC_LEAVES_PER_PIPE) ? 6545 first_sp_mc_child : first_sp_child; 6546 } 6547 } else { 6548 use_fc = first_sp_child; 6549 } 6550 6551 if (cur_num_spri == 0) { 6552 *ucmap = 0; 6553 *spmap = 0; 6554 } 6555 6556 if (mode == SOC_APACHE_SCHED_MODE_STRICT) { 6557 if (child_index > *use_fc) { 6558 if ((child_index - *use_fc) >= max_children && cur_num_spri > 0) { 6559 return BCM_E_UNAVAIL; 6560 } 6561 } else if (child_index < *use_fc) { 6562 return BCM_E_UNAVAIL; 6563 } 6564 } 6565 6566 if (level == SOC_APACHE_NODE_LVL_L1) { 6567 for (mcm = 0, mc = 0, ucm = 0, uc = 0, ii = 0; ii < 8; ii++) { 6568 if (*ucmap & (1 << ii)) { 6569 mcm |= (cur_spmap & (1 << ii)) ? (1 << mc) : 0; 6570 mc += 1; 6571 } else { 6572 ucm |= (cur_spmap & (1 << ii)) ? (1 << uc) : 0; 6573 uc += 1; 6574 } 6575 } 6576 6577 if (child_index < _BCM_AP_NUM_L2_UC_LEAVES_PER_PIPE) { 6578 fc = *first_sp_child; 6579 oc = _bcm_ap_num_ones(ucm); 6580 BCM_IF_ERROR_RETURN(_bcm_apache_compute_lls_config(unit, port, 6581 level - 1, &fc, NULL, &oc, &lucmap, &ucm, child_index, 6582 cur_mode, mode, 8)); 6583 } else { 6584 fc = *first_sp_mc_child; 6585 oc = _bcm_ap_num_ones(mcm); 6586 BCM_IF_ERROR_RETURN(_bcm_apache_compute_lls_config(unit, port, 6587 level - 1, &fc, NULL, &oc, &lucmap, &mcm, 6588 child_index, cur_mode, mode, 8)); 6589 } 6590 6591 cur_spmap = 0; 6592 *ucmap = 0; 6593 for (fc = 0, ii = 0; ii < 8; ii++) { 6594 if (ucm) { 6595 cur_spmap |= (ucm & (1 << ii)) ? 1 << fc : 0; 6596 fc += 1; 6597 ucm &= ~(1 << ii); 6598 } 6599 6600 if (mcm) { 6601 cur_spmap |= (mcm & (1 << ii)) ? 1 << fc : 0; 6602 *ucmap |= 1 << fc; 6603 fc += 1; 6604 mcm &= ~(1 << ii); 6605 } 6606 6607 if (fc > max_children) { 6608 return BCM_E_PARAM; 6609 } 6610 6611 if ((mcm == 0) && (ucm == 0)) { 6612 break; 6613 } 6614 } 6615 6616 } else { 6617 pfc = first_sp_child; 6618 if (mode == SOC_APACHE_SCHED_MODE_STRICT) { 6619 if (*pfc > child_index) { 6620 cur_spmap <<= (*pfc - child_index); 6621 cur_spmap |= 1; 6622 *pfc = child_index; 6623 *num_spri += 1; 6624 } else { 6625 if (((1 << (child_index - *pfc)) & cur_spmap) == 0) { 6626 cur_spmap |= 1 << (child_index - *pfc); 6627 *num_spri += 1; 6628 } 6629 } 6630 } else { 6631 if (1 << (child_index - *pfc) & cur_spmap) { 6632 cur_spmap &= ~(1 << (child_index - *pfc)); 6633 *num_spri -= 1; 6634 } 6635 } 6636 } 6637 6638 *num_spri = _bcm_ap_num_ones(cur_spmap); 6639 6640 *spmap = cur_spmap; 6641 6642 return BCM_E_NONE; 6643 } 6644 6645 /* 6646 * Function: 6647 * _bcm_ap_compute_lls_config 6648 * Purpose: 6649 * This function computes the LLS configuration at each level 6650 * Parameters: 6651 * unit - (IN) unit number 6652 * port - (IN) local port number 6653 * level - (IN) level of the node in LLS 6654 * first_sp_child - (OUT) first sp child 6655 * first_sp_mc_child - (OUT) first so multicast child 6656 * ucmap - (OUT) unicast node map 6657 * spmap - (OUT) SPRI node map 6658 * child_index - (IN) index of the child node 6659 * cur_mode - (IN) current schedling mode of the node 6660 * mode - (IN) new scheduling mode of the node 6661 * max_children - (IN) maximum number of children in the level 6662 * Returns: 6663 * BCM_E_XXX 6664 */ 6665 STATIC int 6666 _bcm_ap_compute_lls_config(int unit, int port, int level, 6667 int *first_sp_child, 6668 int *first_sp_mc_child, 6669 int *num_spri, 6670 uint32 *ucmap, 6671 uint32 *spmap, 6672 int child_index, 6673 soc_apache_sched_mode_e cur_mode, 6674 soc_apache_sched_mode_e mode) 6675 { 6676 if (!soc_feature(unit, soc_feature_vector_based_spri)) { 6677 return BCM_E_UNAVAIL; 6678 } 6679 6680 if (((cur_mode != SOC_APACHE_SCHED_MODE_STRICT) && 6681 (mode != SOC_APACHE_SCHED_MODE_STRICT)) || 6682 ((cur_mode == SOC_APACHE_SCHED_MODE_STRICT) && 6683 (mode == SOC_APACHE_SCHED_MODE_STRICT))) { 6684 return BCM_E_NONE; 6685 } 6686 6687 return _bcm_apache_compute_lls_config(unit, port, level, first_sp_child, 6688 first_sp_mc_child, num_spri, 6689 ucmap, spmap, child_index, 6690 cur_mode, mode, 8); 6691 } 6692 6693 STATIC int 6694 _bcm_ap_cosq_sched_parent_child_set(int unit, int port, int level, 6695 int sched_index, int child_index, 6696 soc_apache_sched_mode_e sched_mode, 6697 int weight, _bcm_ap_cosq_node_t *child_node) 6698 { 6699 int wt, num_spri, first_sp_child, first_sp_mc_child; 6700 uint32 ucmap = 0, spmap = 0; 6701 soc_apache_sched_mode_e cur_sched_mode; 6702 _bcm_ap_lls_info_t lls_tree_info; 6703 int rv = 0, rv1 = 0, child_level; 6704 if (child_node == NULL) { 6705 return BCM_E_PARAM; 6706 } 6707 6708 BCM_IF_ERROR_RETURN(soc_apache_cosq_get_sched_config(unit, port, level, 6709 sched_index, child_index, &num_spri, &first_sp_child, 6710 &first_sp_mc_child, &ucmap, &spmap, &cur_sched_mode, 6711 &wt)); 6712 /* If the dynamic switchover feature is enabled, then compute the LLS 6713 configuration and adjust the bandwidth at the level such that each 6714 node has sufficient bandwidth to perform the switchover. Also set 6715 the new scheduler config based on the request */ 6716 if (soc_feature(unit, soc_feature_vector_based_spri)) { 6717 if(((cur_sched_mode == SOC_APACHE_SCHED_MODE_WRR) && 6718 (sched_mode == SOC_APACHE_SCHED_MODE_WRR)) || 6719 ((cur_sched_mode == SOC_APACHE_SCHED_MODE_WDRR) && 6720 (sched_mode == SOC_APACHE_SCHED_MODE_WDRR))) { 6721 if (child_index >= 0) { 6722 soc_apache_get_child_type(unit, port, level, &child_level); 6723 SOC_IF_ERROR_RETURN(soc_apache_cosq_set_sched_mode(unit, port, 6724 child_level, 6725 child_index, sched_mode, weight)); 6726 } 6727 } else { 6728 if ((rv = _bcm_ap_compute_lls_config(unit, port, level, &first_sp_child, 6729 &first_sp_mc_child, &num_spri, 6730 &ucmap, &spmap, child_index, 6731 cur_sched_mode, sched_mode))) { 6732 return rv; 6733 } 6734 if (cur_sched_mode != sched_mode) { 6735 SOC_EGRESS_METERING_LOCK(unit); 6736 if ((rv = _bcm_ap_adjust_lls_bw(unit, port, child_node, 6737 child_node->level, child_index, 1, &lls_tree_info))){ 6738 goto error; 6739 } 6740 } 6741 if ((rv = soc_apache_cosq_set_sched_config(unit, port, level, 6742 sched_index, child_index, 6743 num_spri, first_sp_child, 6744 first_sp_mc_child, ucmap, 6745 spmap, sched_mode, weight))){ 6746 goto error; 6747 } 6748 } 6749 if (cur_sched_mode != sched_mode) { 6750 /* restore the default bw */ 6751 goto error; 6752 } 6753 } 6754 6755 return BCM_E_NONE; 6756 6757 /* If there is an error during the switchover process, then restore the 6758 bandwidth to the previous state */ 6759 error: 6760 if (cur_sched_mode != sched_mode) { 6761 rv1 = _bcm_ap_adjust_lls_bw(unit, port, child_node, 6762 child_node->level, 6763 child_index, 6764 0, &lls_tree_info); 6765 SOC_EGRESS_METERING_UNLOCK(unit); 6766 if (rv1) { 6767 return rv1; 6768 } 6769 } 6770 return rv; 6771 } 6772 6773 /* 6774 * Function: 6775 * _bcm_ap_cosq_sched_set 6776 * Purpose: 6777 * Set scheduling mode 6778 * Parameters: 6779 * unit - (IN) unit number 6780 * port - (IN) port number or GPORT identifier 6781 * cosq - (IN) COS queue number 6782 * mode - (IN) scheduling mode (BCM_COSQ_XXX) 6783 * num_weights - (IN) number of entries in weights array 6784 * weights - (IN) weights array 6785 * Returns: 6786 * BCM_E_XXX 6787 */ 6788 STATIC int 6789 _bcm_ap_cosq_sched_set(int unit, bcm_port_t gport, bcm_cos_queue_t cosq, 6790 int mode, int weight) 6791 { 6792 _bcm_ap_cosq_node_t *node = NULL, *child_node , *s1_node; 6793 bcm_port_t local_port; 6794 int lwts = 1, index, numq; 6795 soc_apache_sched_mode_e sched_mode; 6796 _bcm_ap_mmu_info_t *mmu_info; 6797 soc_info_t *si; 6798 void *setting = NULL; 6799 int rv = BCM_E_NONE; 6800 6801 if (cosq < 0) { 6802 if (cosq == -1) { 6803 /* caller needs to resolve the wild card value (-1) */ 6804 return BCM_E_INTERNAL; 6805 } else { /* reject all other negative value */ 6806 return BCM_E_PARAM; 6807 } 6808 } 6809 6810 if ((weight < 0) || (weight > 127)) { 6811 return BCM_E_PARAM; 6812 } 6813 6814 if(_BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, gport)){ 6815 BCM_IF_ERROR_RETURN( 6816 _bcmi_coe_subport_physical_port_get(unit, gport, &local_port)); 6817 } else { 6818 BCM_IF_ERROR_RETURN 6819 (_bcm_ap_cosq_localport_resolve(unit, gport, &local_port)); 6820 } 6821 si = &SOC_INFO(unit); 6822 mmu_info = _bcm_ap_mmu_info[unit]; 6823 6824 switch(mode) { 6825 case BCM_COSQ_STRICT: 6826 sched_mode = SOC_APACHE_SCHED_MODE_STRICT; 6827 lwts = 0; 6828 break; 6829 case BCM_COSQ_ROUND_ROBIN: 6830 sched_mode = SOC_APACHE_SCHED_MODE_WRR; 6831 lwts = 1; 6832 break; 6833 case BCM_COSQ_WEIGHTED_ROUND_ROBIN: 6834 sched_mode = SOC_APACHE_SCHED_MODE_WRR; 6835 lwts = weight; 6836 break; 6837 case BCM_COSQ_DEFICIT_ROUND_ROBIN: 6838 sched_mode = SOC_APACHE_SCHED_MODE_WDRR; 6839 lwts = weight; 6840 break; 6841 default: 6842 return BCM_E_PARAM; 6843 } 6844 6845 if (lwts == 0) { 6846 sched_mode = SOC_APACHE_SCHED_MODE_STRICT; 6847 } 6848 6849 if (BCM_GPORT_IS_SCHEDULER(gport)) { /* ETS style scheduler */ 6850 BCM_IF_ERROR_RETURN 6851 (_bcm_ap_cosq_node_get(unit, gport, 0, NULL, &local_port, NULL, 6852 &node)); 6853 if ((node->numq >= 0) && (cosq > node->numq)) { 6854 return BCM_E_PARAM; 6855 } 6856 BCM_IF_ERROR_RETURN 6857 (_bcm_ap_cosq_child_node_at_input(node, cosq, &child_node)); 6858 } else if (_BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT 6859 (unit, gport)) { 6860 if (soc_feature(unit, 6861 soc_feature_mmu_hqos_four_level)) { 6862 BCM_IF_ERROR_RETURN 6863 (_bcm_ap_get_s1_node(unit, gport, 6864 &s1_node)); 6865 index = s1_node->coe_base_index; 6866 child_node = &mmu_info->queue_node[index + cosq ]; 6867 if (!child_node) { 6868 return BCM_E_INTERNAL; 6869 } 6870 if (child_node->attached_to_input == -1) { 6871 return BCM_E_NOT_FOUND; 6872 } 6873 node = child_node->parent ; 6874 if (!node) { 6875 return BCM_E_INTERNAL; 6876 } 6877 6878 } else { 6879 return BCM_E_PARAM; 6880 } 6881 } else { 6882 if (IS_CPU_PORT(unit, local_port)) { 6883 numq = SOC_INFO(unit).num_cpu_cosq; 6884 if (cosq >= numq) { 6885 return BCM_E_PARAM; 6886 } 6887 index = soc_apache_l2_hw_index(unit, 6888 si->port_cosq_base[local_port] + cosq, 0); 6889 } else { 6890 index = soc_apache_l2_hw_index(unit, 6891 si->port_uc_cosq_base[local_port], 1); 6892 } 6893 6894 child_node = &mmu_info->queue_node[index]; 6895 if (!child_node) { 6896 return BCM_E_INTERNAL; 6897 } 6898 if (child_node->attached_to_input == -1) { 6899 return BCM_E_NOT_FOUND; 6900 } 6901 node = child_node->parent; 6902 if (node && !IS_CPU_PORT(unit, local_port)) { 6903 child_node = node; 6904 node = node->parent; 6905 if (!node) { 6906 return BCM_E_INTERNAL; 6907 } 6908 if ((node->numq >= 0) && (cosq > node->numq)) { 6909 return BCM_E_PARAM; 6910 } 6911 BCM_IF_ERROR_RETURN 6912 (_bcm_ap_cosq_child_node_at_input(node, cosq, 6913 &child_node)); 6914 } 6915 } 6916 6917 if (!node || !child_node) { 6918 return BCM_E_INTERNAL; 6919 } 6920 6921 /* S1 is always in WRR in Apache */ 6922 if (!IS_AP_HSP_PORT(unit, local_port) && 6923 (soc_feature(unit, soc_feature_mmu_hqos_four_level)) && 6924 (node->level == SOC_APACHE_NODE_LVL_ROOT) && 6925 (mode == BCM_COSQ_STRICT)) { 6926 return BCM_E_PARAM; 6927 } 6928 6929 if (node->attached_to_input < 0) { /* Not resolved yet */ 6930 return BCM_E_NOT_FOUND; 6931 } 6932 6933 /* HSP/LLS - child node at cosq index of parent gport 6934 * is resloved to set it's schedule mode and weight 6935 */ 6936 if (IS_AP_HSP_PORT(unit, local_port)) { 6937 rv = soc_apache_cosq_set_sched_mode(unit, local_port, 6938 child_node->level, child_node->hw_index, sched_mode, lwts); 6939 } else { 6940 BCM_IF_ERROR_RETURN(_soc_egress_metering_freeze(unit, 6941 local_port, &setting)); 6942 rv = _bcm_ap_cosq_sched_parent_child_set(unit, 6943 local_port, node->level, node->hw_index, 6944 child_node->hw_index, sched_mode, lwts, child_node); 6945 BCM_IF_ERROR_RETURN(_soc_egress_metering_thaw(unit, local_port, setting)); 6946 if (rv < 0) { 6947 return rv; 6948 } 6949 if (!BCM_GPORT_IS_SCHEDULER(gport) && 6950 !BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) && 6951 !BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) && 6952 node && IS_CPU_PORT(unit, local_port)) { 6953 child_node = node; 6954 node = node->parent; 6955 lwts = (sched_mode == SOC_APACHE_SCHED_MODE_STRICT) ? 0 : 1; 6956 BCM_IF_ERROR_RETURN(_soc_egress_metering_freeze(unit, 6957 local_port, &setting)); 6958 rv = _bcm_ap_cosq_sched_parent_child_set(unit, 6959 local_port, node->level, node->hw_index, 6960 child_node->hw_index, sched_mode, lwts, child_node); 6961 BCM_IF_ERROR_RETURN(_soc_egress_metering_thaw(unit, local_port, setting)); 6962 if (rv < 0) { 6963 return rv; 6964 } 6965 } 6966 } 6967 6968 return rv; 6969 } 6970 6971 /* 6972 * Function: 6973 * bcm_ap_cosq_detach 6974 * Purpose: 6975 * Discard all COS schedule/mapping state. 6976 * Parameters: 6977 * unit - unit number 6978 * Returns: 6979 * BCM_E_XXX 6980 */ 6981 int 6982 bcm_ap_cosq_detach(int unit, int software_state_only) 6983 { 6984 int i; 6985 soc_info_t *si; 6986 6987 if (!_bcm_ap_mmu_info[unit] ) { 6988 return BCM_E_NONE; 6989 } 6990 6991 (void) _bcm_bst_detach(unit); 6992 6993 if (NULL != _bcm_ap_endpoint_queuing_info[unit]) { 6994 if (NULL != _bcm_ap_endpoint_queuing_info[unit]->ptr_array) { 6995 for (i = 0; i < _BCM_AP_NUM_ENDPOINT(unit); i++) { 6996 if (_BCM_AP_ENDPOINT_IS_USED(unit, i)) { 6997 sal_free(_BCM_AP_ENDPOINT(unit, i)); 6998 _BCM_AP_ENDPOINT(unit, i) = NULL; 6999 } 7000 } 7001 sal_free(_bcm_ap_endpoint_queuing_info[unit]->ptr_array); 7002 _bcm_ap_endpoint_queuing_info[unit]->ptr_array = NULL; 7003 } 7004 if (NULL != _bcm_ap_endpoint_queuing_info[unit]->cos_map_profile) { 7005 soc_profile_mem_destroy(unit, 7006 _bcm_ap_endpoint_queuing_info[unit]->cos_map_profile); 7007 sal_free(_bcm_ap_endpoint_queuing_info[unit]->cos_map_profile); 7008 _bcm_ap_endpoint_queuing_info[unit]->cos_map_profile = NULL; 7009 } 7010 sal_free(_bcm_ap_endpoint_queuing_info[unit]); 7011 _bcm_ap_endpoint_queuing_info[unit] = NULL; 7012 } 7013 7014 si = &SOC_INFO(unit); 7015 for (i = 0; i < si->num_cpu_cosq; i++) { 7016 if (_bcm_ap_cosq_cpu_cosq_config[unit][i] != NULL) { 7017 sal_free(_bcm_ap_cosq_cpu_cosq_config[unit][i]); 7018 _bcm_ap_cosq_cpu_cosq_config[unit][i] = NULL; 7019 } 7020 } 7021 if (_bcm_ap_wred_profile[unit] != NULL ) 7022 { 7023 soc_profile_mem_destroy(unit, _bcm_ap_wred_profile[unit]); 7024 sal_free(_bcm_ap_wred_profile[unit]); 7025 _bcm_ap_wred_profile[unit] = NULL; 7026 } 7027 if (_bcm_ap_cos_map_profile[unit] != NULL ) 7028 { 7029 soc_profile_mem_destroy(unit, _bcm_ap_cos_map_profile[unit]); 7030 sal_free(_bcm_ap_cos_map_profile[unit]); 7031 _bcm_ap_cos_map_profile[unit] = NULL; 7032 } 7033 if (_bcm_ap_sample_int_profile[unit] != NULL ) 7034 { 7035 soc_profile_mem_destroy(unit, _bcm_ap_sample_int_profile[unit]); 7036 sal_free(_bcm_ap_sample_int_profile[unit]); 7037 _bcm_ap_sample_int_profile[unit] = NULL; 7038 } 7039 if (_bcm_ap_feedback_profile[unit] != NULL ) 7040 { 7041 soc_profile_reg_destroy(unit, _bcm_ap_feedback_profile[unit]); 7042 sal_free(_bcm_ap_feedback_profile[unit]); 7043 _bcm_ap_feedback_profile[unit] = NULL ; 7044 } 7045 if (_bcm_ap_llfc_profile[unit] != NULL ) 7046 { 7047 soc_profile_reg_destroy(unit, _bcm_ap_llfc_profile[unit]); 7048 sal_free(_bcm_ap_llfc_profile[unit]); 7049 _bcm_ap_llfc_profile[unit] = NULL ; 7050 } 7051 if (_bcm_ap_voq_port_map_profile[unit] != NULL ) 7052 { 7053 soc_profile_mem_destroy(unit, _bcm_ap_voq_port_map_profile[unit]); 7054 sal_free(_bcm_ap_voq_port_map_profile[unit]); 7055 _bcm_ap_voq_port_map_profile[unit] = NULL; 7056 } 7057 if (_bcm_ap_ifp_cos_map_profile[unit] != NULL ) 7058 { 7059 soc_profile_mem_destroy(unit, _bcm_ap_ifp_cos_map_profile[unit]); 7060 sal_free(_bcm_ap_ifp_cos_map_profile[unit]); 7061 _bcm_ap_ifp_cos_map_profile[unit] = NULL; 7062 } 7063 if (_bcm_ap_service_port_map_profile[unit] != NULL ) 7064 { 7065 soc_profile_mem_destroy(unit, _bcm_ap_service_port_map_profile[unit]); 7066 sal_free(_bcm_ap_service_port_map_profile[unit]); 7067 _bcm_ap_service_port_map_profile[unit] = NULL; 7068 } 7069 if (_bcm_ap_service_cos_map_profile[unit] != NULL ) 7070 { 7071 soc_profile_mem_destroy(unit, _bcm_ap_service_cos_map_profile[unit]); 7072 sal_free(_bcm_ap_service_cos_map_profile[unit]); 7073 _bcm_ap_service_cos_map_profile[unit] = NULL; 7074 } 7075 if (_bcm_ap_mmu_info[unit] != NULL) { 7076 _bcm_ap_cosq_free_memory(_bcm_ap_mmu_info[unit]); 7077 sal_free(_bcm_ap_mmu_info[unit]); 7078 _bcm_ap_mmu_info[unit] = NULL; 7079 } 7080 soc_apache_fc_map_shadow_free(unit); 7081 return BCM_E_NONE; 7082 } 7083 7084 /* 7085 * Function: 7086 * bcm_ap_port_cosq_config_set 7087 * Purpose: 7088 * called during flexport during port attach/detach 7089 * to update the cos_map profile for the port 7090 * Parameters: 7091 * unit - unit number 7092 * port - port number 7093 * enable - add/delete 7094 * Returns: 7095 * BCM_E_XXX 7096 */ 7097 STATIC int 7098 bcm_ap_port_cosq_config_set(int unit, bcm_port_t port, int enable) 7099 { 7100 port_cos_map_entry_t cos_map_entries[16]; 7101 port_cos_map_entry_t hg_cos_map_entries[16]; 7102 cos_map_sel_entry_t cos_map_sel_entry; 7103 void *entries[1], *hg_entries[1]; 7104 uint32 index, old_index, hg_index; 7105 int cos, prio, numq, rv; 7106 uint32 i; 7107 7108 numq = _AP_NUM_COS(unit); 7109 7110 sal_memset(cos_map_entries, 0, sizeof(cos_map_entries)); 7111 entries[0] = &cos_map_entries; 7112 hg_entries[0] = &hg_cos_map_entries; 7113 prio = 0; 7114 if (enable) { 7115 for (cos = 0; cos < numq; cos++) { 7116 for (i = 8 / numq + (cos < 8 % numq ? 1 : 0); i > 0; i--) { 7117 soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio], 7118 UC_COS1f, cos); 7119 soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio], 7120 MC_COS1f, cos); 7121 soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio], 7122 HG_COSf, cos); 7123 soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio], 7124 RQE_Q_NUMf, cos); 7125 prio++; 7126 } 7127 } 7128 for (prio = 8; prio < 16; prio++) { 7129 soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio], 7130 UC_COS1f, numq - 1); 7131 soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio], 7132 MC_COS1f, numq - 1); 7133 soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio], 7134 HG_COSf, numq - 1); 7135 soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio], 7136 RQE_Q_NUMf, numq - 1); 7137 } 7138 7139 7140 #ifdef BCM_COSQ_HIGIG_MAP_DISABLE 7141 /* Use identical mapping for Higig port */ 7142 sal_memset(hg_cos_map_entries, 0, sizeof(hg_cos_map_entries)); 7143 prio = 0; 7144 for (prio = 0; prio < 8; prio++) { 7145 soc_mem_field32_set(unit, PORT_COS_MAPm, &hg_cos_map_entries[prio], 7146 UC_COS1f, prio); 7147 soc_mem_field32_set(unit, PORT_COS_MAPm, &hg_cos_map_entries[prio], 7148 MC_COS1f, prio); 7149 soc_mem_field32_set(unit, PORT_COS_MAPm, &hg_cos_map_entries[prio], 7150 RQE_Q_NUMf, prio); 7151 } 7152 for (prio = 8; prio < 13; prio++) { 7153 soc_mem_field32_set(unit, PORT_COS_MAPm, &hg_cos_map_entries[prio], 7154 UC_COS1f, 7); 7155 soc_mem_field32_set(unit, PORT_COS_MAPm, &hg_cos_map_entries[prio], 7156 MC_COS1f, 7); 7157 soc_mem_field32_set(unit, PORT_COS_MAPm, &hg_cos_map_entries[prio], 7158 RQE_Q_NUMf, 7); 7159 } 7160 #else /* BCM_COSQ_HIGIG_MAP_DISABLE */ 7161 sal_memcpy(hg_cos_map_entries, cos_map_entries, sizeof(cos_map_entries)); 7162 #endif /* !BCM_COSQ_HIGIG_MAP_DISABLE */ 7163 soc_mem_field32_set(unit, PORT_COS_MAPm, &hg_cos_map_entries[14], 7164 HG_COSf, 8); 7165 soc_mem_field32_set(unit, PORT_COS_MAPm, &hg_cos_map_entries[15], 7166 HG_COSf, 9); 7167 7168 if (IS_HG_PORT(unit, port)) { 7169 soc_mem_lock(unit, PORT_COS_MAPm); 7170 7171 rv = soc_profile_mem_add(unit, _bcm_ap_cos_map_profile[unit], 7172 hg_entries, 16, &hg_index); 7173 7174 soc_mem_unlock(unit, PORT_COS_MAPm); 7175 if (BCM_FAILURE(rv)) { 7176 return rv; 7177 } 7178 BCM_IF_ERROR_RETURN 7179 (soc_mem_field32_modify(unit, COS_MAP_SELm, port, SELECTf, 7180 hg_index / 16)); 7181 } else { 7182 soc_mem_lock(unit, PORT_COS_MAPm); 7183 7184 rv = soc_profile_mem_add(unit, _bcm_ap_cos_map_profile[unit], 7185 entries, 16, &index); 7186 7187 soc_mem_unlock(unit, PORT_COS_MAPm); 7188 if (BCM_FAILURE(rv)) { 7189 return rv; 7190 } 7191 BCM_IF_ERROR_RETURN 7192 (soc_mem_field32_modify(unit, COS_MAP_SELm, port, SELECTf, 7193 index / 16)); 7194 } 7195 7196 } else { 7197 BCM_IF_ERROR_RETURN 7198 (READ_COS_MAP_SELm(unit, MEM_BLOCK_ANY, port, 7199 &cos_map_sel_entry)); 7200 old_index = soc_mem_field32_get(unit, COS_MAP_SELm, &cos_map_sel_entry, 7201 SELECTf); 7202 old_index *= 16; 7203 7204 soc_mem_lock(unit, PORT_COS_MAPm); 7205 7206 rv = soc_profile_mem_delete(unit, _bcm_ap_cos_map_profile[unit], 7207 old_index); 7208 7209 soc_mem_unlock(unit, PORT_COS_MAPm); 7210 if (BCM_FAILURE(rv)) { 7211 return rv; 7212 } 7213 } 7214 return BCM_E_NONE; 7215 } 7216 7217 /* 7218 * Function: 7219 * bcm_ap_cosq_config_set 7220 * Purpose: 7221 * Set the number of COS queues 7222 * Parameters: 7223 * unit - unit number 7224 * numq - number of COS queues (1-8). 7225 * Returns: 7226 * BCM_E_XXX 7227 */ 7228 int 7229 bcm_ap_cosq_config_set(int unit, int numq) 7230 { 7231 port_cos_map_entry_t cos_map_entries[16]; 7232 port_cos_map_entry_t hg_cos_map_entries[16]; 7233 void *entries[1], *hg_entries[1]; 7234 uint32 index, hg_index; 7235 bcm_port_t port; 7236 int cos, prio; 7237 uint32 i = 0; 7238 voq_cos_map_entry_t voq_cos_map; 7239 int ref_count; 7240 int cpu_hg_index = 0; 7241 7242 if (numq < 1 || numq > 8) { 7243 return BCM_E_PARAM; 7244 } 7245 7246 /* clear out old profiles. */ 7247 index = 0; 7248 while (index < soc_mem_index_count(unit, PORT_COS_MAPm)) { 7249 BCM_IF_ERROR_RETURN(soc_profile_mem_ref_count_get(unit, 7250 _bcm_ap_cos_map_profile[unit], 7251 index, &ref_count)); 7252 if (ref_count > 0) { 7253 while (ref_count) { 7254 if (!soc_profile_mem_delete(unit, _bcm_ap_cos_map_profile[unit], index)) { 7255 ref_count -= 1; 7256 } 7257 } 7258 } 7259 index += 16; 7260 } 7261 7262 /* Distribute first 8 internal priority levels into the specified number 7263 * of cosq, map remaining internal priority levels to highest priority 7264 * cosq */ 7265 sal_memset(cos_map_entries, 0, sizeof(cos_map_entries)); 7266 entries[0] = &cos_map_entries; 7267 hg_entries[0] = &hg_cos_map_entries; 7268 prio = 0; 7269 for (cos = 0; cos < numq; cos++) { 7270 for (i = 8 / numq + (cos < 8 % numq ? 1 : 0); i > 0; i--) { 7271 soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio], 7272 UC_COS1f, cos); 7273 soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio], 7274 MC_COS1f, cos); 7275 soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio], 7276 HG_COSf, cos); 7277 soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio], 7278 RQE_Q_NUMf, cos); 7279 prio++; 7280 } 7281 } 7282 for (prio = 8; prio < 16; prio++) { 7283 soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio], 7284 UC_COS1f, numq - 1); 7285 soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio], 7286 MC_COS1f, numq - 1); 7287 soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio], 7288 HG_COSf, numq - 1); 7289 soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio], 7290 RQE_Q_NUMf, numq - 1); 7291 } 7292 7293 /* Map internal priority levels to CPU CoS queues */ 7294 BCM_IF_ERROR_RETURN(_bcm_esw_cpu_cosq_mapping_default_set(unit, numq)); 7295 7296 #ifdef BCM_COSQ_HIGIG_MAP_DISABLE 7297 /* Use identical mapping for Higig port */ 7298 sal_memset(hg_cos_map_entries, 0, sizeof(hg_cos_map_entries)); 7299 prio = 0; 7300 for (prio = 0; prio < 8; prio++) { 7301 soc_mem_field32_set(unit, PORT_COS_MAPm, &hg_cos_map_entries[prio], 7302 UC_COS1f, prio); 7303 soc_mem_field32_set(unit, PORT_COS_MAPm, &hg_cos_map_entries[prio], 7304 MC_COS1f, prio); 7305 soc_mem_field32_set(unit, PORT_COS_MAPm, &hg_cos_map_entries[prio], 7306 RQE_Q_NUMf, prio); 7307 } 7308 for (prio = 8; prio < 13; prio++) { 7309 soc_mem_field32_set(unit, PORT_COS_MAPm, &hg_cos_map_entries[prio], 7310 UC_COS1f, 7); 7311 soc_mem_field32_set(unit, PORT_COS_MAPm, &hg_cos_map_entries[prio], 7312 MC_COS1f, 7); 7313 soc_mem_field32_set(unit, PORT_COS_MAPm, &hg_cos_map_entries[prio], 7314 RQE_Q_NUMf, 7); 7315 } 7316 #else /* BCM_COSQ_HIGIG_MAP_DISABLE */ 7317 sal_memcpy(hg_cos_map_entries, cos_map_entries, sizeof(cos_map_entries)); 7318 #endif /* !BCM_COSQ_HIGIG_MAP_DISABLE */ 7319 7320 soc_mem_field32_set(unit, PORT_COS_MAPm, &hg_cos_map_entries[14], 7321 HG_COSf, 8); 7322 soc_mem_field32_set(unit, PORT_COS_MAPm, &hg_cos_map_entries[15], 7323 HG_COSf, 9); 7324 7325 PBMP_ALL_ITER(unit, port) { 7326 if (IS_LB_PORT(unit, port)) { 7327 continue; 7328 } 7329 7330 if (IS_HG_PORT(unit, port)) { 7331 BCM_IF_ERROR_RETURN 7332 (soc_profile_mem_add(unit, _bcm_ap_cos_map_profile[unit], 7333 hg_entries, 16, &hg_index)); 7334 BCM_IF_ERROR_RETURN 7335 (soc_mem_field32_modify(unit, COS_MAP_SELm, port, SELECTf, 7336 hg_index / 16)); 7337 } else { 7338 BCM_IF_ERROR_RETURN 7339 (soc_profile_mem_add(unit, _bcm_ap_cos_map_profile[unit], 7340 entries, 16, &index)); 7341 BCM_IF_ERROR_RETURN 7342 (soc_mem_field32_modify(unit, COS_MAP_SELm, port, SELECTf, 7343 index / 16)); 7344 } 7345 } 7346 7347 cpu_hg_index = SOC_INFO(unit).cpu_hg_index; 7348 if (cpu_hg_index != -1) { 7349 BCM_IF_ERROR_RETURN 7350 (soc_profile_mem_add(unit, _bcm_ap_cos_map_profile[unit], 7351 entries, 16, &index)); 7352 BCM_IF_ERROR_RETURN 7353 (soc_mem_field32_modify(unit, COS_MAP_SELm, 7354 cpu_hg_index, SELECTf, index / 16)); 7355 } 7356 7357 7358 sal_memset(&voq_cos_map, 0, sizeof(voq_cos_map)); 7359 for (cos = 0; cos < numq; cos++) { 7360 for (i = 8 / numq + (i < 8 % numq ? 1 : 0); i > 0; i--) { 7361 soc_mem_field32_set(unit, VOQ_COS_MAPm, &voq_cos_map, VOQ_COS_OFFSETf, cos); 7362 BCM_IF_ERROR_RETURN( 7363 soc_mem_write(unit, VOQ_COS_MAPm, MEM_BLOCK_ANY, cos, 7364 &voq_cos_map)); 7365 prio++; 7366 } 7367 } 7368 for (prio = numq; prio < 16; prio++) { 7369 soc_mem_field32_set(unit, VOQ_COS_MAPm, &voq_cos_map, VOQ_COS_OFFSETf, numq - 1); 7370 BCM_IF_ERROR_RETURN( 7371 soc_mem_write(unit, VOQ_COS_MAPm, MEM_BLOCK_ANY, prio, 7372 &voq_cos_map)); 7373 } 7374 7375 _AP_NUM_COS(unit) = numq; 7376 7377 return BCM_E_NONE; 7378 } 7379 7380 STATIC int 7381 _bcm_ap_cosq_egress_sp_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 7382 int *p_pool_start, int *p_pool_end) 7383 { 7384 int local_port; 7385 int pool; 7386 if (cosq == BCM_COS_INVALID) { 7387 *p_pool_start = 0; 7388 *p_pool_end = 3; 7389 return BCM_E_NONE; 7390 } 7391 7392 BCM_IF_ERROR_RETURN 7393 (_bcm_ap_cosq_index_resolve(unit, gport, cosq, 7394 _BCM_AP_COSQ_INDEX_STYLE_EGR_POOL, 7395 &local_port, &pool, NULL)); 7396 7397 *p_pool_start = *p_pool_end = pool; 7398 return BCM_E_NONE; 7399 } 7400 7401 STATIC int 7402 _bcm_ap_cosq_ingress_sp_get(int unit, bcm_gport_t gport, bcm_cos_queue_t pri_grp, 7403 int *p_pool_start, int *p_pool_end) 7404 { 7405 int local_port; 7406 uint32 rval, pool; 7407 static const soc_field_t prigroup_spid_field[] = { 7408 PG0_SPIDf, PG1_SPIDf, PG2_SPIDf, PG3_SPIDf, 7409 PG4_SPIDf, PG5_SPIDf, PG6_SPIDf, PG7_SPIDf 7410 }; 7411 7412 if (pri_grp == BCM_COS_INVALID) { 7413 *p_pool_start = 0; 7414 *p_pool_end = 3; 7415 return BCM_E_NONE; 7416 } 7417 7418 BCM_IF_ERROR_RETURN 7419 (_bcm_ap_cosq_localport_resolve(unit, gport, &local_port)); 7420 7421 if (!SOC_PORT_VALID(unit, local_port)) { 7422 return BCM_E_PORT; 7423 } 7424 7425 if ((pri_grp < 0) || (pri_grp >= 8)) { 7426 return BCM_E_PARAM; 7427 } 7428 7429 SOC_IF_ERROR_RETURN(READ_THDI_PORT_PG_SPIDr(unit, local_port, &rval)); 7430 pool = soc_reg_field_get(unit, THDI_PORT_PG_SPIDr, rval, 7431 prigroup_spid_field[pri_grp]); 7432 7433 *p_pool_start = *p_pool_end = pool; 7434 return BCM_E_NONE; 7435 } 7436 7437 STATIC int 7438 _bcm_ap_cosq_ingress_pg_get(int unit, bcm_gport_t gport, bcm_cos_queue_t pri, 7439 int *p_pg_start, int *p_pg_end) 7440 { 7441 bcm_port_t local_port; 7442 uint32 rval,pool; 7443 soc_reg_t reg = INVALIDr; 7444 static const soc_reg_t prigroup_reg[] = { 7445 THDI_PORT_PRI_GRP0r, THDI_PORT_PRI_GRP1r 7446 }; 7447 static const soc_field_t prigroup_field[] = { 7448 PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf, 7449 PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf, 7450 PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf, 7451 PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf 7452 }; 7453 7454 if (pri == BCM_COS_INVALID) { 7455 *p_pg_start = 0; 7456 *p_pg_end = 7; 7457 return BCM_E_NONE; 7458 } 7459 7460 BCM_IF_ERROR_RETURN 7461 (_bcm_ap_cosq_localport_resolve(unit, gport, &local_port)); 7462 7463 if (!SOC_PORT_VALID(unit, local_port)) { 7464 return BCM_E_PORT; 7465 } 7466 7467 if (pri > 15) { 7468 return BCM_E_PARAM; 7469 } 7470 /* get PG for port using Port+Cos */ 7471 if (pri < 8) { 7472 reg = prigroup_reg[0]; 7473 } else { 7474 reg = prigroup_reg[1]; 7475 } 7476 7477 SOC_IF_ERROR_RETURN 7478 (soc_reg32_get(unit, reg, local_port, 0, &rval)); 7479 pool = soc_reg_field_get(unit, reg, rval, prigroup_field[pri]); 7480 7481 *p_pg_start = *p_pg_end = pool; 7482 return BCM_E_NONE; 7483 } 7484 7485 7486 STATIC _bcm_bst_cb_ret_t 7487 _bcm_ap_bst_index_resolve(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 7488 bcm_bst_stat_id_t bid, int *pipe, int *start_hw_index, 7489 int *end_hw_index, int *rcb_data, void **cb_data, int *bcm_rv) 7490 { 7491 int phy_port, mmu_port, local_port; 7492 _bcm_ap_cosq_node_t *node = NULL; 7493 soc_info_t *si; 7494 uint32 rval = 0; 7495 int pool_idx; 7496 7497 *bcm_rv = BCM_E_NONE; 7498 7499 #define _BST_IF_ERROR_GOTO_EXIT(op) \ 7500 do { int __rv__; if ((__rv__ = (op)) < 0) { goto error_exit; } } while(0) 7501 7502 _BST_IF_ERROR_GOTO_EXIT 7503 (_bcm_ap_cosq_localport_resolve(unit, gport, &local_port)); 7504 7505 si = &SOC_INFO(unit); 7506 phy_port = si->port_l2p_mapping[local_port]; 7507 mmu_port = si->port_p2m_mapping[phy_port]; 7508 7509 *pipe = 0; 7510 7511 if (bid == bcmBstStatIdDevice) { 7512 *start_hw_index = *end_hw_index = 0; 7513 *bcm_rv = BCM_E_NONE; 7514 return _BCM_BST_RV_OK; 7515 } 7516 7517 if (bid == bcmBstStatIdEgrPool) { 7518 /* Egress Unicast Pool */ 7519 if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 7520 goto error_exit; 7521 } 7522 _BST_IF_ERROR_GOTO_EXIT(_bcm_ap_cosq_egress_sp_get(unit, gport, cosq, 7523 start_hw_index, end_hw_index)); 7524 return _BCM_BST_RV_OK; 7525 } else if (bid == bcmBstStatIdEgrMCastPool) { 7526 /* Egress Multicast Pool */ 7527 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 7528 goto error_exit; 7529 } 7530 _BST_IF_ERROR_GOTO_EXIT(_bcm_ap_cosq_egress_sp_get(unit, gport, cosq, 7531 start_hw_index, end_hw_index)); 7532 return _BCM_BST_RV_OK; 7533 } else if (bid == bcmBstStatIdIngPool) { 7534 /* ingress pool */ 7535 _BST_IF_ERROR_GOTO_EXIT(_bcm_ap_cosq_ingress_sp_get(unit, gport, cosq, 7536 start_hw_index, end_hw_index)); 7537 return _BCM_BST_RV_OK; 7538 } else if (bid == bcmBstStatIdRQEPool) { 7539 /* RQE pool */ 7540 if (cosq == BCM_COS_INVALID) { 7541 *start_hw_index = 0; 7542 *end_hw_index = _APACHE_MMU_NUM_POOL - 1; 7543 }else if ((cosq < 0) || (cosq >= _APACHE_MMU_NUM_RQE_QUEUES)) { 7544 return BCM_E_PARAM; 7545 } else { 7546 SOC_IF_ERROR_RETURN 7547 (READ_MMU_THDR_DB_CONFIG1_PRIQr(unit, cosq, &rval)); 7548 7549 pool_idx = soc_reg_field_get(unit, MMU_THDR_DB_CONFIG1_PRIQr, rval, 7550 SPIDf); 7551 *start_hw_index = *end_hw_index = pool_idx; 7552 } 7553 return _BCM_BST_RV_OK; 7554 } else if (bid == bcmBstStatIdRQEQueue) { 7555 /* RQE queue */ 7556 if (cosq == BCM_COS_INVALID) { 7557 *start_hw_index = 0; 7558 *end_hw_index = _APACHE_MMU_NUM_RQE_QUEUES - 1; 7559 }else if ((cosq < 0) || (cosq >= _APACHE_MMU_NUM_RQE_QUEUES)) { 7560 return BCM_E_PARAM; 7561 } else { 7562 *start_hw_index = *end_hw_index = cosq; 7563 } 7564 return _BCM_BST_RV_OK; 7565 } else if (bid == bcmBstStatIdUCQueueGroup) { 7566 /* unicast queue group */ 7567 _BST_IF_ERROR_GOTO_EXIT(_bcm_ap_cosq_index_resolve(unit, 7568 gport, cosq, _BCM_AP_COSQ_INDEX_STYLE_UCAST_QUEUE_GROUP, 7569 NULL, start_hw_index, NULL)); 7570 *end_hw_index = *start_hw_index; 7571 return _BCM_BST_RV_OK; 7572 } 7573 7574 if (bid == bcmBstStatIdPortPool) { 7575 /* ingress pool */ 7576 _BST_IF_ERROR_GOTO_EXIT( 7577 _bcm_ap_cosq_ingress_sp_get(unit, gport, cosq, 7578 start_hw_index, end_hw_index)); 7579 *start_hw_index = ((mmu_port) * 4) + *start_hw_index; 7580 *end_hw_index = ((mmu_port) * 4) + *end_hw_index; 7581 } else if ((bid == bcmBstStatIdPriGroupShared) || 7582 (bid == bcmBstStatIdPriGroupHeadroom)) { 7583 /* ingress pool */ 7584 _BST_IF_ERROR_GOTO_EXIT( 7585 _bcm_ap_cosq_ingress_pg_get(unit, gport, cosq, 7586 start_hw_index, end_hw_index)); 7587 *start_hw_index = ((mmu_port) * 8) + *start_hw_index; 7588 *end_hw_index = ((mmu_port) * 8) + *end_hw_index; 7589 } else if (bid == bcmBstStatIdEgrPortPoolSharedUcast || 7590 bid == bcmBstStatIdEgrPortPoolSharedMcast) { 7591 /* egress pool */ 7592 _BST_IF_ERROR_GOTO_EXIT( 7593 _bcm_ap_cosq_egress_sp_get(unit, gport, cosq, 7594 start_hw_index, end_hw_index)); 7595 *start_hw_index = ((mmu_port & 0x3f) * _APACHE_MMU_NUM_POOL) + 7596 *start_hw_index; 7597 *end_hw_index = ((mmu_port & 0x3f) * _APACHE_MMU_NUM_POOL) + 7598 *end_hw_index; 7599 } else { 7600 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 7601 if (bid != bcmBstStatIdUcast) { 7602 goto error_exit; 7603 } 7604 _BST_IF_ERROR_GOTO_EXIT 7605 (_bcm_ap_cosq_node_get(unit, gport, 0, NULL, 7606 &local_port, NULL, &node)); 7607 if (!node) { 7608 goto error_exit; 7609 } 7610 *start_hw_index = *end_hw_index = node->hw_index; 7611 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 7612 if (bid != bcmBstStatIdMcast) { 7613 goto error_exit; 7614 } 7615 _BST_IF_ERROR_GOTO_EXIT 7616 (_bcm_ap_cosq_node_get(unit, gport, 0, NULL, 7617 &local_port, NULL, &node)); 7618 if (!node) { 7619 goto error_exit; 7620 } 7621 *start_hw_index = *end_hw_index = node->hw_index - _BCM_AP_NUM_L2_UC_LEAVES; 7622 } else { 7623 _BST_IF_ERROR_GOTO_EXIT(_bcm_ap_cosq_port_has_ets(unit, local_port)); 7624 7625 if (cosq < 0) { 7626 if (bid == bcmBstStatIdUcast) { 7627 _BST_IF_ERROR_GOTO_EXIT(_bcm_ap_cosq_index_resolve(unit, 7628 local_port, 0, _BCM_AP_COSQ_INDEX_STYLE_UCAST_QUEUE, 7629 NULL, start_hw_index, NULL)); 7630 7631 _BST_IF_ERROR_GOTO_EXIT(_bcm_ap_cosq_index_resolve(unit, 7632 local_port, NUM_COS(unit) - 1, 7633 _BCM_AP_COSQ_INDEX_STYLE_UCAST_QUEUE, 7634 NULL, end_hw_index, NULL)); 7635 7636 } else { 7637 _BST_IF_ERROR_GOTO_EXIT(_bcm_ap_cosq_index_resolve(unit, 7638 local_port, 0, _BCM_AP_COSQ_INDEX_STYLE_MCAST_QUEUE, 7639 NULL, start_hw_index, NULL)); 7640 *start_hw_index -= _BCM_AP_NUM_L2_UC_LEAVES; 7641 7642 _BST_IF_ERROR_GOTO_EXIT(_bcm_ap_cosq_index_resolve(unit, 7643 local_port, NUM_COS(unit) - 1, 7644 _BCM_AP_COSQ_INDEX_STYLE_MCAST_QUEUE, 7645 NULL, end_hw_index, NULL)); 7646 *end_hw_index -= _BCM_AP_NUM_L2_UC_LEAVES; 7647 } 7648 } else { 7649 if (bid == bcmBstStatIdUcast) { 7650 _BST_IF_ERROR_GOTO_EXIT(_bcm_ap_cosq_index_resolve(unit, 7651 local_port, cosq, _BCM_AP_COSQ_INDEX_STYLE_UCAST_QUEUE, 7652 NULL, start_hw_index, NULL)); 7653 *end_hw_index = *start_hw_index; 7654 } else { 7655 _BST_IF_ERROR_GOTO_EXIT(_bcm_ap_cosq_index_resolve(unit, 7656 local_port, cosq, _BCM_AP_COSQ_INDEX_STYLE_MCAST_QUEUE, 7657 NULL, start_hw_index, NULL)); 7658 *start_hw_index -= _BCM_AP_NUM_L2_UC_LEAVES; 7659 *end_hw_index = *start_hw_index; 7660 } 7661 } /* if (cosq < 0) */ 7662 } /* if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { */ 7663 } /* if (bid == bcmBstStatIdPortPool) { */ 7664 7665 *bcm_rv = BCM_E_NONE; 7666 return _BCM_BST_RV_OK; 7667 7668 error_exit: 7669 *bcm_rv = BCM_E_PARAM; 7670 return _BCM_BST_RV_ERROR; 7671 } 7672 7673 7674 7675 STATIC int 7676 _bcm_ap_cosq_bst_map_resource_to_gport_cos(int unit, bcm_bst_stat_id_t bid, int port, 7677 int index, bcm_gport_t *gport, bcm_cos_t *cosq) 7678 { 7679 soc_info_t *si; 7680 _bcm_ap_cosq_node_t *node; 7681 _bcm_ap_mmu_info_t *mmu_info; 7682 _bcm_ap_pipe_resources_t *pres; 7683 int ii, pipe; 7684 int hw_index, mmu_port, phy_port; 7685 7686 pipe = _AP_XPIPE; 7687 mmu_info = _bcm_ap_mmu_info[unit]; 7688 pres = _BCM_AP_PRESOURCES(mmu_info, pipe); 7689 si = &SOC_INFO(unit); 7690 7691 switch (bid) { 7692 case bcmBstStatIdDevice: 7693 *gport = -1; 7694 *cosq = BCM_COS_INVALID; 7695 break; 7696 7697 case bcmBstStatIdIngPool: 7698 case bcmBstStatIdEgrPool: 7699 case bcmBstStatIdEgrMCastPool: 7700 case bcmBstStatIdRQEPool: 7701 *gport = -1; 7702 *cosq = index; 7703 break; 7704 7705 case bcmBstStatIdRQEQueue: 7706 *gport = -1; 7707 *cosq = index % _APACHE_MMU_NUM_RQE_QUEUES; 7708 break; 7709 7710 case bcmBstStatIdUCQueueGroup: 7711 *gport = index; 7712 *cosq = -1; 7713 break; 7714 7715 case bcmBstStatIdPortPool: 7716 case bcmBstStatIdEgrPortPoolSharedUcast: 7717 case bcmBstStatIdEgrPortPoolSharedMcast: 7718 mmu_port = index/_APACHE_MMU_NUM_POOL; 7719 phy_port = si->port_m2p_mapping[mmu_port]; 7720 *gport = si->port_p2l_mapping[phy_port]; 7721 *cosq = index % _APACHE_MMU_NUM_POOL; 7722 break; 7723 7724 case bcmBstStatIdPriGroupHeadroom: 7725 case bcmBstStatIdPriGroupShared: 7726 mmu_port = index/8; 7727 phy_port = si->port_m2p_mapping[mmu_port]; 7728 *gport = si->port_p2l_mapping[phy_port]; 7729 *cosq = index % 8; 7730 break; 7731 7732 case bcmBstStatIdMcast: 7733 pipe = _AP_XPIPE; 7734 hw_index = soc_apache_l2_hw_index(unit, index, 0); 7735 7736 if (mmu_info->ets_mode) { 7737 for (ii = 0; ii < _BCM_AP_NUM_L2_MC_LEAVES; ii++) { 7738 node = &pres->p_queue_node[ii]; 7739 if (node->in_use == TRUE) { 7740 7741 if (node->hw_index == hw_index) { 7742 *gport = node->gport; 7743 *cosq = 0; 7744 break; 7745 } 7746 } 7747 } 7748 } else { 7749 int port_mc_base = 0; 7750 int port_num_mc = 0; 7751 PBMP_ALL_ITER(unit, port) { 7752 7753 if (IS_LB_PORT(unit, port)) { 7754 continue; 7755 } 7756 7757 port_num_mc = si->port_num_cosq[port]; 7758 port_mc_base = si->port_cosq_base[port]; 7759 7760 if ((index >= port_mc_base) && 7761 (index < port_mc_base + port_num_mc)) { 7762 *gport = port; 7763 *cosq = index - port_mc_base; 7764 break; 7765 } 7766 } 7767 } 7768 break; 7769 case bcmBstStatIdUcast: 7770 pipe = _AP_XPIPE; 7771 hw_index = soc_apache_l2_hw_index(unit, index, 1); 7772 7773 if (mmu_info->ets_mode) { 7774 for (ii = 0; ii < _BCM_AP_NUM_L2_UC_LEAVES; ii++) { 7775 node = &pres->p_queue_node[ii]; 7776 if (node->in_use == TRUE) { 7777 7778 if (node->hw_index == hw_index) { 7779 *gport = node->gport; 7780 *cosq = 0; 7781 break; 7782 } 7783 } 7784 } 7785 } else { 7786 int port_uc_base = 0; 7787 int port_num_uc = 0; 7788 PBMP_ALL_ITER(unit, port) { 7789 7790 if (IS_LB_PORT(unit, port)) { 7791 continue; 7792 } 7793 7794 port_num_uc = si->port_num_uc_cosq[port]; 7795 port_uc_base = si->port_uc_cosq_base[port]; 7796 7797 if ((index >= port_uc_base) && 7798 (index < port_uc_base + port_num_uc)) { 7799 *gport = port; 7800 *cosq = index - port_uc_base; 7801 break; 7802 } 7803 } 7804 } 7805 default: 7806 break; 7807 } 7808 7809 return BCM_E_NONE; 7810 } 7811 7812 STATIC int 7813 _bcm_ap_cpu_lls_config_set(int unit, int port) 7814 { 7815 bcm_gport_t port_sched, s1_sched, l0_sched; 7816 bcm_gport_t l1_sched; 7817 bcm_gport_t mc_cosq; 7818 int i, j, k, l2_offset; 7819 uint32 num_l0[3]; 7820 uint32 num_l1[3]; 7821 uint32 num_l2[3]; /* 0 = PCI ; 1 = UC0; 2 = UC1 */ 7822 _bcm_ap_mmu_info_t *mmu_info; 7823 7824 if ((mmu_info = _bcm_ap_mmu_info[unit]) == NULL) { 7825 return BCM_E_INIT; 7826 } 7827 7828 num_l2[1] = NUM_CPU_ARM_COSQ(unit, SOC_ARM_CMC(unit, 0)); 7829 num_l2[2] = NUM_CPU_ARM_COSQ(unit, SOC_ARM_CMC(unit, 1)); 7830 num_l2[0] = 48 - (num_l2[1] + num_l2[2]); 7831 7832 num_l1[0] = (num_l2[0] + 7) / 8; 7833 num_l1[1] = (num_l2[1] + 7) / 8; 7834 num_l1[2] = (num_l2[2] + 7) / 8; 7835 7836 num_l0[0] = 1; 7837 num_l0[1] = (num_l1[1] ? 1 : 0); 7838 num_l0[2] = (num_l1[2] ? 1 : 0); 7839 7840 _BCM_DEFAULT_LLS_SET(mmu_info); 7841 7842 if (soc_feature(unit, soc_feature_mmu_hqos_four_level)) { 7843 BCM_IF_ERROR_RETURN 7844 (bcm_ap_cosq_gport_add(unit, port, 1, 0, &port_sched)); 7845 7846 BCM_IF_ERROR_RETURN 7847 (bcm_ap_cosq_gport_add(unit, port, 3, 7848 BCM_COSQ_GPORT_SCHEDULER, 7849 &s1_sched)); 7850 BCM_IF_ERROR_RETURN 7851 (bcm_ap_cosq_gport_attach(unit, s1_sched, port_sched, 0)); 7852 } else { 7853 BCM_IF_ERROR_RETURN 7854 (bcm_ap_cosq_gport_add(unit, port, 3, 0, &port_sched)); 7855 } 7856 for (i = 0; i < 3; i++) { 7857 if (num_l0[i] == 0) { 7858 continue; 7859 } 7860 BCM_IF_ERROR_RETURN 7861 (bcm_ap_cosq_gport_add(unit, port, num_l1[i], 7862 BCM_COSQ_GPORT_SCHEDULER, 7863 &l0_sched)); 7864 if (soc_feature(unit, soc_feature_mmu_hqos_four_level)) { 7865 BCM_IF_ERROR_RETURN 7866 (bcm_ap_cosq_gport_attach(unit, l0_sched, s1_sched, i)); 7867 } else { 7868 BCM_IF_ERROR_RETURN 7869 (bcm_ap_cosq_gport_attach(unit, l0_sched, port_sched, i)); 7870 } 7871 for (j = 0; j < num_l1[i]; j++) { 7872 l2_offset = (num_l2[i] - (j * 8)); 7873 l2_offset = (l2_offset > 8) ? 8 : l2_offset; 7874 BCM_IF_ERROR_RETURN 7875 (bcm_ap_cosq_gport_add(unit, port, l2_offset, 7876 BCM_COSQ_GPORT_SCHEDULER, 7877 &l1_sched)); 7878 7879 BCM_IF_ERROR_RETURN 7880 (bcm_ap_cosq_gport_attach(unit, l1_sched, l0_sched, j)); 7881 7882 for (k = 0; k < l2_offset; k++) { 7883 BCM_IF_ERROR_RETURN 7884 (bcm_ap_cosq_gport_add(unit, port, 1, BCM_COSQ_GPORT_MCAST_QUEUE_GROUP, 7885 &mc_cosq)); 7886 BCM_IF_ERROR_RETURN 7887 (bcm_ap_cosq_gport_attach(unit, mc_cosq, l1_sched, k)); 7888 } 7889 } 7890 7891 } 7892 _BCM_DEFAULT_LLS_RESET(mmu_info); 7893 return BCM_E_NONE; 7894 } 7895 int 7896 _bcm_ap_port_lls_config_set(int unit, 7897 bcm_port_t port) 7898 { 7899 bcm_gport_t port_sched, s1_sched, l0_sched; 7900 bcm_gport_t l1_sched; 7901 bcm_gport_t uc_cosq, mc_cosq; 7902 int i; 7903 uint32 num_of_l1 = 10; 7904 uint32 num_of_l2_uc = 1; 7905 uint32 num_of_l2_mc = 1; 7906 int uc, mc; 7907 int skip_lls = 0; 7908 _bcm_ap_mmu_info_t *mmu_info; 7909 if ((mmu_info = _bcm_ap_mmu_info[unit]) == NULL) { 7910 return BCM_E_INIT; 7911 } 7912 7913 skip_lls = soc_ap_is_skip_default_lls_creation(unit); 7914 if (skip_lls && !IS_CPU_PORT(unit, port) && !IS_LB_PORT(unit, port)) 7915 { 7916 BCM_IF_ERROR_RETURN( 7917 _bcm_ap_port_enqueue_set(unit , port, 0)); 7918 return BCM_E_NONE; 7919 } 7920 if(IS_CPU_PORT(unit, port)) { 7921 return _bcm_ap_cpu_lls_config_set(unit, port); 7922 } 7923 if(IS_LB_PORT(unit, port)) { 7924 num_of_l1 = 9; 7925 num_of_l2_uc = 0; 7926 num_of_l2_mc = 1; 7927 } 7928 _BCM_DEFAULT_LLS_SET(mmu_info); 7929 7930 BCM_IF_ERROR_RETURN 7931 (bcm_ap_cosq_gport_add(unit, port, 1, 0, &port_sched)); 7932 7933 if (soc_feature(unit, soc_feature_mmu_hqos_four_level)) 7934 { 7935 BCM_IF_ERROR_RETURN 7936 (bcm_ap_cosq_gport_add(unit, port, 1, 7937 BCM_COSQ_GPORT_SCHEDULER, 7938 &s1_sched)); 7939 BCM_IF_ERROR_RETURN 7940 (bcm_ap_cosq_gport_attach(unit, s1_sched, port_sched, 0)); 7941 } 7942 BCM_IF_ERROR_RETURN 7943 (bcm_ap_cosq_gport_add(unit, port, num_of_l1, 7944 BCM_COSQ_GPORT_SCHEDULER, 7945 &l0_sched)); 7946 if (soc_feature(unit, soc_feature_mmu_hqos_four_level)) 7947 { 7948 BCM_IF_ERROR_RETURN 7949 (bcm_ap_cosq_gport_attach(unit, l0_sched, s1_sched, 0)); 7950 } else 7951 { 7952 BCM_IF_ERROR_RETURN 7953 (bcm_ap_cosq_gport_attach(unit, l0_sched, port_sched, 0)); 7954 } 7955 for (i = 0; i < num_of_l1; i++) { 7956 BCM_IF_ERROR_RETURN 7957 (bcm_ap_cosq_gport_add(unit, port, (num_of_l2_uc + num_of_l2_mc), 7958 BCM_COSQ_GPORT_SCHEDULER, 7959 &l1_sched)); 7960 7961 BCM_IF_ERROR_RETURN 7962 (bcm_ap_cosq_gport_attach(unit, l1_sched, l0_sched, i)); 7963 for (uc = 0; uc < num_of_l2_uc; uc++) { 7964 BCM_IF_ERROR_RETURN 7965 (bcm_ap_cosq_gport_add(unit, port, 1, BCM_COSQ_GPORT_UCAST_QUEUE_GROUP, 7966 &uc_cosq)); 7967 BCM_IF_ERROR_RETURN 7968 (bcm_ap_cosq_gport_attach(unit, uc_cosq, l1_sched, uc)); 7969 } 7970 for (mc = uc; mc < (num_of_l2_uc + num_of_l2_mc); mc++) { 7971 BCM_IF_ERROR_RETURN 7972 (bcm_ap_cosq_gport_add(unit, port, 1, BCM_COSQ_GPORT_MCAST_QUEUE_GROUP, 7973 &mc_cosq)); 7974 BCM_IF_ERROR_RETURN 7975 (bcm_ap_cosq_gport_attach(unit, mc_cosq, l1_sched, mc)); 7976 } 7977 } 7978 _BCM_DEFAULT_LLS_RESET(mmu_info); 7979 return BCM_E_NONE; 7980 } 7981 7982 int 7983 _bcm_ap_port_hsp_config_set(int unit, 7984 bcm_port_t port) 7985 { 7986 bcm_gport_t port_sched, l0_sched[5]; 7987 bcm_gport_t l1_sched; 7988 bcm_gport_t uc_cosq, mc_cosq; 7989 int i; 7990 uint32 num_of_l0 = 5; 7991 uint32 num_of_l1 = 10; 7992 int index; 7993 7994 7995 BCM_IF_ERROR_RETURN 7996 (bcm_ap_cosq_gport_add(unit, port, num_of_l0 , 0, &port_sched)); 7997 7998 for (i = 0; i < num_of_l0; i++) { 7999 BCM_IF_ERROR_RETURN 8000 (bcm_ap_cosq_gport_add(unit, port, 8, 8001 BCM_COSQ_GPORT_SCHEDULER, 8002 &l0_sched[i])); 8003 BCM_IF_ERROR_RETURN 8004 (bcm_ap_cosq_gport_attach(unit, l0_sched[i], port_sched, i)); 8005 } 8006 8007 for (i = 0; i < num_of_l1; i++) { 8008 BCM_IF_ERROR_RETURN 8009 (bcm_ap_cosq_gport_add(unit, port, 2, 8010 BCM_COSQ_GPORT_SCHEDULER, 8011 &l1_sched)); 8012 index = i < 8 ? 1 : 4; 8013 8014 BCM_IF_ERROR_RETURN 8015 (bcm_ap_cosq_gport_attach(unit, l1_sched, l0_sched[index], 8016 i >= 8 ? i - 8 :i)); 8017 BCM_IF_ERROR_RETURN 8018 (bcm_ap_cosq_gport_sched_set(unit, l0_sched[index], (i >= 8 ? i - 8 :i), 8019 BCM_COSQ_DEFICIT_ROUND_ROBIN, 1)); 8020 BCM_IF_ERROR_RETURN 8021 (bcm_ap_cosq_gport_add(unit, port, 1, BCM_COSQ_GPORT_UCAST_QUEUE_GROUP, 8022 &uc_cosq)); 8023 BCM_IF_ERROR_RETURN 8024 (bcm_ap_cosq_gport_attach(unit, uc_cosq, l1_sched, 0)); 8025 BCM_IF_ERROR_RETURN 8026 (bcm_ap_cosq_gport_add(unit, port, 1, BCM_COSQ_GPORT_MCAST_QUEUE_GROUP, 8027 &mc_cosq)); 8028 BCM_IF_ERROR_RETURN 8029 (bcm_ap_cosq_gport_attach(unit, mc_cosq, l1_sched, 1)); 8030 } 8031 return BCM_E_NONE; 8032 } 8033 8034 int 8035 bcm_ap_init_fc_map_tbl(int unit) 8036 { 8037 int max_index; 8038 int max_nodes; 8039 uint32 map_entry[SOC_MAX_MEM_WORDS]; 8040 int mem; 8041 int index; 8042 int field ; 8043 static const soc_field_t indexf[] = { 8044 INDEX0f, INDEX1f, INDEX2f, INDEX3f 8045 }; 8046 static const soc_mem_t memx[] = { 8047 MMU_INTFI_XPIPE_FC_MAP_TBL0m, 8048 MMU_INTFI_XPIPE_FC_MAP_TBL1m, 8049 MMU_INTFI_XPIPE_FC_MAP_TBL2m 8050 }; 8051 static const soc_mem_t memy[] = { 8052 MMU_INTFI_FC_ST_TBL0m, 8053 MMU_INTFI_FC_ST_TBL1m, 8054 MMU_INTFI_FC_ST_TBL2m, 8055 }; 8056 8057 for ( mem = 0 ; mem < 3 ; mem++) 8058 { 8059 max_index = soc_mem_index_count(unit, memy[mem]) - 1; 8060 max_nodes = soc_mem_index_count(unit,memx[mem]); 8061 for ( index = 0 ; index < max_nodes ; index++) 8062 { 8063 SOC_IF_ERROR_RETURN(soc_mem_read(unit, memx[mem], 8064 MEM_BLOCK_ALL, index, &map_entry)); 8065 for (field = 0; field < COUNTOF(indexf); field++) 8066 { 8067 soc_mem_field32_set(unit, memx[mem], 8068 &map_entry, indexf[field], max_index); 8069 } 8070 SOC_IF_ERROR_RETURN(soc_mem_write(unit, memx[mem], 8071 MEM_BLOCK_ALL, index, &map_entry)); 8072 } 8073 } 8074 return BCM_E_NONE; 8075 } 8076 /* 8077 * Function: 8078 * bcm_ap_cosq_init 8079 * Purpose: 8080 * Initialize (clear) all COS schedule/mapping state. 8081 * Parameters: 8082 * unit - unit number 8083 * Returns: 8084 * BCM_E_XXX 8085 */ 8086 int 8087 bcm_ap_cosq_init(int unit) 8088 { 8089 int numq, alloc_size, ii, index; 8090 soc_info_t *si; 8091 bcm_port_t port; 8092 soc_reg_t mem; 8093 soc_reg_t reg; 8094 int count; 8095 static soc_mem_t wred_mems[6] = { 8096 MMU_WRED_DROP_CURVE_PROFILE_0_X_PIPEm, 8097 MMU_WRED_DROP_CURVE_PROFILE_1_X_PIPEm, 8098 MMU_WRED_DROP_CURVE_PROFILE_2_X_PIPEm, 8099 MMU_WRED_DROP_CURVE_PROFILE_3_X_PIPEm, 8100 MMU_WRED_DROP_CURVE_PROFILE_4_X_PIPEm, 8101 MMU_WRED_DROP_CURVE_PROFILE_5_X_PIPEm 8102 }; 8103 8104 int entry_words[6], pipe; 8105 mmu_wred_drop_curve_profile_0_entry_t entry_tcp_green; 8106 mmu_wred_drop_curve_profile_1_entry_t entry_tcp_yellow; 8107 mmu_wred_drop_curve_profile_2_entry_t entry_tcp_red; 8108 mmu_wred_drop_curve_profile_3_entry_t entry_nontcp_green; 8109 mmu_wred_drop_curve_profile_4_entry_t entry_nontcp_yellow; 8110 mmu_wred_drop_curve_profile_5_entry_t entry_nontcp_red; 8111 void *entries[6]; 8112 uint32 profile_index, rval32; 8113 _bcm_ap_mmu_info_t *mmu_info; 8114 int i, qnum, wred_prof_count; 8115 _bcm_bst_device_handlers_t bst_callbks; 8116 _bcm_ap_pipe_resources_t *pres; 8117 uint64 rval64; 8118 _bcm_ap_cosq_list_t *list = NULL; 8119 int baseq = 0; 8120 int numl2uc = 0; 8121 int phy_port ,mmu_port ; 8122 uint64 rval ; 8123 8124 BCM_IF_ERROR_RETURN (bcm_ap_cosq_detach(unit, 0)); 8125 8126 si = &SOC_INFO(unit); 8127 8128 numq = soc_property_get(unit, spn_BCM_NUM_COS, BCM_COS_DEFAULT); 8129 8130 if (numq < 1) { 8131 numq = 1; 8132 } else if (numq > 8) { 8133 numq = 8; 8134 } 8135 8136 NUM_COS(unit) = numq; 8137 soc_apache_fc_map_shadow_create(unit); 8138 8139 /*Initialize time_domain1 on this unit */ 8140 time_domain1[unit][0].field = TIME_0f; 8141 time_domain1[unit][1].field = TIME_1f; 8142 time_domain1[unit][2].field = TIME_2f; 8143 time_domain1[unit][3].field = TIME_3f; 8144 time_domain1[unit][0].ref_count = 20780; 8145 time_domain1[unit][1].ref_count = 0; 8146 time_domain1[unit][2].ref_count = 0; 8147 time_domain1[unit][3].ref_count = 0; 8148 8149 /* Create profile for PORT_COS_MAP table */ 8150 if (_bcm_ap_cos_map_profile[unit] == NULL) { 8151 _bcm_ap_cos_map_profile[unit] = sal_alloc(sizeof(soc_profile_mem_t), 8152 "COS_MAP Profile Mem"); 8153 if (_bcm_ap_cos_map_profile[unit] == NULL) { 8154 return BCM_E_MEMORY; 8155 } 8156 soc_profile_mem_t_init(_bcm_ap_cos_map_profile[unit]); 8157 } 8158 mem = PORT_COS_MAPm; 8159 entry_words[0] = sizeof(port_cos_map_entry_t) / sizeof(uint32); 8160 BCM_IF_ERROR_RETURN(soc_profile_mem_create(unit, &mem, entry_words, 1, 8161 _bcm_ap_cos_map_profile[unit])); 8162 8163 /* Create profile for IFP_COS_MAP table. */ 8164 if (_bcm_ap_ifp_cos_map_profile[unit] == NULL) { 8165 _bcm_ap_ifp_cos_map_profile[unit] 8166 = sal_alloc(sizeof(soc_profile_mem_t), "IFP_COS_MAP Profile Mem"); 8167 if (_bcm_ap_ifp_cos_map_profile[unit] == NULL) { 8168 return BCM_E_MEMORY; 8169 } 8170 soc_profile_mem_t_init(_bcm_ap_ifp_cos_map_profile[unit]); 8171 } 8172 mem = IFP_COS_MAPm; 8173 entry_words[0] = sizeof(ifp_cos_map_entry_t) / sizeof(uint32); 8174 SOC_IF_ERROR_RETURN 8175 (soc_profile_mem_create(unit, &mem, entry_words, 1, 8176 _bcm_ap_ifp_cos_map_profile[unit])); 8177 8178 /* Create profile for SERVICE_COS_MAP table */ 8179 if (_bcm_ap_service_cos_map_profile[unit] == NULL) { 8180 alloc_size = sizeof(soc_profile_mem_t); 8181 _bcm_ap_service_cos_map_profile[unit] = sal_alloc(alloc_size, 8182 "SERVICE_COS_MAP"); 8183 if (_bcm_ap_service_cos_map_profile[unit] == NULL) { 8184 return BCM_E_MEMORY; 8185 } 8186 soc_profile_mem_t_init(_bcm_ap_service_cos_map_profile[unit]); 8187 } 8188 mem = SERVICE_COS_MAPm; 8189 entry_words[0] = sizeof(service_cos_map_entry_t) / sizeof(uint32); 8190 SOC_IF_ERROR_RETURN( 8191 soc_profile_mem_create(unit, &mem, entry_words, 1, 8192 _bcm_ap_service_cos_map_profile[unit])); 8193 8194 /* Create profile for SERVICE_PORT_MAP table */ 8195 if (_bcm_ap_service_port_map_profile[unit] == NULL) { 8196 alloc_size = sizeof(soc_profile_mem_t); 8197 _bcm_ap_service_port_map_profile[unit] = sal_alloc(alloc_size, 8198 "SERVICE_PORT_MAP"); 8199 if (_bcm_ap_service_port_map_profile[unit] == NULL) { 8200 return BCM_E_MEMORY; 8201 } 8202 soc_profile_mem_t_init(_bcm_ap_service_port_map_profile[unit]); 8203 } 8204 8205 mem = SERVICE_PORT_MAPm; 8206 entry_words[0] = sizeof(service_port_map_entry_t) / sizeof(uint32); 8207 SOC_IF_ERROR_RETURN( 8208 soc_profile_mem_create(unit, &mem, entry_words, 1, 8209 _bcm_ap_service_port_map_profile[unit])); 8210 8211 alloc_size = sizeof(_bcm_ap_mmu_info_t) * 1; 8212 if (_bcm_ap_mmu_info[unit] == NULL) { 8213 _bcm_ap_mmu_info[unit] = 8214 sal_alloc(alloc_size, "_bcm_ap_mmu_info"); 8215 8216 if (_bcm_ap_mmu_info[unit] == NULL) { 8217 return BCM_E_MEMORY; 8218 } 8219 8220 sal_memset(_bcm_ap_mmu_info[unit], 0, alloc_size); 8221 } 8222 8223 /* Create profile for PRIO2COS_PROFILE register */ 8224 if (_bcm_ap_llfc_profile[unit] == NULL) { 8225 _bcm_ap_llfc_profile[unit] = 8226 sal_alloc(sizeof(soc_profile_reg_t), "PRIO2COS_LLFC Profile Reg"); 8227 if (_bcm_ap_llfc_profile[unit] == NULL) { 8228 return BCM_E_MEMORY; 8229 } 8230 soc_profile_reg_t_init(_bcm_ap_llfc_profile[unit]); 8231 } 8232 reg = PRIO2COS_PROFILEr; 8233 BCM_IF_ERROR_RETURN 8234 (soc_profile_reg_create(unit, ®, 1, _bcm_ap_llfc_profile[unit])); 8235 8236 mmu_info = _bcm_ap_mmu_info[unit]; 8237 mmu_info->ets_mode = 0; 8238 mmu_info->pipe_resources[_AP_XPIPE].num_base_queues = 0; 8239 8240 if (soc_feature(unit, soc_feature_mmu_3k_uc_queue)) { 8241 mmu_info->num_l2_queues = _BCM_AP_NUM_L2_UC_LEAVES_PER_PIPE; 8242 } else if (soc_feature(unit, soc_feature_mmu_1k_uc_queue)) { 8243 mmu_info->num_l2_queues = _BCM_AP_NUM_L2_UC_LEAVES_PER_PIPE; 8244 } else { 8245 mmu_info->num_l2_queues = _BCM_AP_NUM_L2_UC_LEAVES_PER_PIPE; 8246 } 8247 8248 for (pipe = _AP_XPIPE; pipe < _AP_YPIPE; pipe++) { 8249 pres = _BCM_AP_PRESOURCES(mmu_info, pipe); 8250 pres->p_queue_node = &mmu_info->queue_node[0]; 8251 pres->p_mc_queue_node = &mmu_info->mc_queue_node[0]; 8252 pres->l2_queue_list.count = mmu_info->num_l2_queues; 8253 pres->l2_queue_list.bits = _bcm_ap_cosq_alloc_clear( 8254 pres->l2_queue_list.bits, 8255 SHR_BITALLOCSIZE(mmu_info->num_l2_queues), 8256 "l2_queue_list"); 8257 if (pres->l2_queue_list.bits == NULL) { 8258 _bcm_ap_cosq_free_memory(mmu_info); 8259 return BCM_E_MEMORY; 8260 } 8261 8262 pres->l0_sched_list.count = _BCM_AP_NUM_L0_SCHEDULER_PER_PIPE; 8263 pres->l0_sched_list.bits = _bcm_ap_cosq_alloc_clear( 8264 pres->l0_sched_list.bits, 8265 SHR_BITALLOCSIZE(_BCM_AP_NUM_L0_SCHEDULER_PER_PIPE), 8266 "l0_sched_list"); 8267 if (pres->l0_sched_list.bits == NULL) { 8268 _bcm_ap_cosq_free_memory(mmu_info); 8269 return BCM_E_MEMORY; 8270 } 8271 8272 pres->l1_sched_list.count = _BCM_AP_NUM_L1_SCHEDULER_PER_PIPE; 8273 pres->l1_sched_list.bits = _bcm_ap_cosq_alloc_clear( 8274 pres->l1_sched_list.bits, 8275 SHR_BITALLOCSIZE(_BCM_AP_NUM_L1_SCHEDULER_PER_PIPE), 8276 "l1_sched_list"); 8277 if (pres->l1_sched_list.bits == NULL) { 8278 _bcm_ap_cosq_free_memory(mmu_info); 8279 return BCM_E_MEMORY; 8280 } 8281 pres->s1_sched_list.count = _BCM_AP_NUM_S1_SCHEDULER_PER_PIPE; 8282 pres->s1_sched_list.bits = _bcm_ap_cosq_alloc_clear( 8283 pres->s1_sched_list.bits, 8284 SHR_BITALLOCSIZE(_BCM_AP_NUM_S1_SCHEDULER_PER_PIPE), 8285 "s1_sched_list"); 8286 if (pres->s1_sched_list.bits == NULL) { 8287 _bcm_ap_cosq_free_memory(mmu_info); 8288 return BCM_E_MEMORY; 8289 } 8290 8291 } 8292 /* assign queues to ports */ 8293 PBMP_ALL_ITER(unit, port) { 8294 pipe = _BCM_AP_PORT_TO_PIPE(unit, port); 8295 8296 if ((SOC_WARM_BOOT(unit) && !IS_LB_PORT(unit, port)) && 8297 ! IS_CPU_PORT(unit, port)) { 8298 numl2uc = IS_AP_HSP_PORT(unit, port) ? 10 : 16; 8299 phy_port = si->port_l2p_mapping[port]; 8300 mmu_port = si->port_p2m_mapping[phy_port]; 8301 COMPILER_64_ZERO(rval); 8302 BCM_IF_ERROR_RETURN(READ_ING_COS_MODE_64r(unit, port, &rval)); 8303 baseq = soc_reg64_field32_get(unit, ING_COS_MODE_64r, rval, 8304 BASE_QUEUE_NUM_0f); 8305 si->port_num_cosq[port] = 10; 8306 si->port_cosq_base[port] = (mmu_port * si->port_num_cosq[port]); 8307 si->port_num_uc_cosq[port] = numl2uc ; 8308 si->port_uc_cosq_base[port] = baseq; 8309 } 8310 mmu_info->port_info[port].resources = &mmu_info->pipe_resources[pipe]; 8311 mmu_info->port_info[port].mc_base = si->port_cosq_base[port]; 8312 mmu_info->port_info[port].mc_limit = si->port_cosq_base[port] + 8313 si->port_num_cosq[port]; 8314 8315 mmu_info->port_info[port].uc_base = si->port_uc_cosq_base[port]; 8316 mmu_info->port_info[port].uc_limit = si->port_uc_cosq_base[port] + 8317 si->port_num_uc_cosq[port]; 8318 if (mmu_info->port_info[port].resources->num_base_queues < 8319 mmu_info->port_info[port].uc_limit) { 8320 mmu_info->port_info[port].resources->num_base_queues = 8321 mmu_info->port_info[port].uc_limit; 8322 } 8323 if (!SOC_WARM_BOOT(unit)) { 8324 COMPILER_64_ZERO(rval64); 8325 if(IS_AP_HSP_PORT(unit, port)) { 8326 SOC_IF_ERROR_RETURN(soc_apache_sched_hw_index_get(unit, 8327 port, SOC_APACHE_NODE_LVL_L1, 0, &qnum)); 8328 } else { 8329 qnum = soc_apache_logical_qnum_hw_qnum(unit, port, 8330 si->port_uc_cosq_base[port], 1); 8331 } 8332 soc_reg64_field32_set(unit, ING_COS_MODE_64r, 8333 &rval64, BASE_QUEUE_NUM_0f, qnum); 8334 soc_reg64_field32_set(unit, ING_COS_MODE_64r, 8335 &rval64, BASE_QUEUE_NUM_1f, qnum); 8336 BCM_IF_ERROR_RETURN(soc_reg_set(unit, ING_COS_MODE_64r, port, 0, rval64)); 8337 } 8338 } 8339 8340 8341 for (i = 0; i < _BCM_AP_NUM_TOTAL_SCHEDULERS; i++) { 8342 _BCM_AP_COSQ_LIST_NODE_INIT(mmu_info->sched_node, i); 8343 } 8344 8345 for (i = 0; i < _BCM_AP_NUM_L2_UC_LEAVES; i++) { 8346 _BCM_AP_COSQ_LIST_NODE_INIT(mmu_info->queue_node, i); 8347 } 8348 8349 for (i = 0; i < _BCM_AP_NUM_L2_MC_LEAVES; i++) { 8350 _BCM_AP_COSQ_LIST_NODE_INIT(mmu_info->mc_queue_node, i); 8351 } 8352 8353 for (pipe = _AP_XPIPE; pipe < _AP_YPIPE; pipe++) { 8354 pres = _BCM_AP_PRESOURCES(mmu_info, pipe); 8355 for (i = SOC_APACHE_NODE_LVL_L0; i <= SOC_APACHE_NODE_LVL_L2; i++) { 8356 index = _soc_apache_invalid_parent_index(unit, i); 8357 if (i == SOC_APACHE_NODE_LVL_L0) { 8358 list = &pres->s1_sched_list; 8359 } else if (i == SOC_APACHE_NODE_LVL_L1) { 8360 list = &pres->l0_sched_list; 8361 } else if (i == SOC_APACHE_NODE_LVL_L2) { 8362 list = &pres->l1_sched_list; 8363 } else { 8364 continue; 8365 } 8366 if (index >= 0) { 8367 _bcm_ap_node_index_set(list, index, 1); 8368 } 8369 } 8370 } 8371 8372 /* reserve the resources for HSP ports */ 8373 count = _BCM_AP_HSP_PORT_MAX_ROOT; 8374 8375 for (pipe = _AP_XPIPE; pipe < _AP_YPIPE; pipe++) { 8376 pres = _BCM_AP_PRESOURCES(mmu_info, pipe); 8377 _bcm_ap_node_index_set(&pres->l0_sched_list, 0, 5 * count); 8378 _bcm_ap_node_index_set(&pres->l1_sched_list, 0, 10 * count); 8379 _bcm_ap_node_index_set(&pres->l2_queue_list, 0, 10 * count); 8380 8381 pres->cpu_l0_sched_list.count = (_BCM_AP_CPU_PORT_L0_MAX - 8382 _BCM_AP_CPU_PORT_L0_MIN); 8383 pres->cpu_l0_sched_list.bits = _bcm_ap_cosq_alloc_clear( 8384 pres->cpu_l0_sched_list.bits, 8385 SHR_BITALLOCSIZE(pres->cpu_l0_sched_list.count), 8386 "cpu_l0_sched_list"); 8387 if (pres->cpu_l0_sched_list.bits == NULL) { 8388 _bcm_ap_cosq_free_memory(mmu_info); 8389 return BCM_E_MEMORY; 8390 } 8391 _bcm_ap_node_index_set(&pres->l0_sched_list, _BCM_AP_CPU_PORT_L0_MIN, 8392 pres->cpu_l0_sched_list.count); 8393 8394 8395 8396 8397 if (count > 0) { 8398 pres->hsp_l0_sched_list.count = 5 * count; 8399 pres->hsp_l0_sched_list.bits = _bcm_ap_cosq_alloc_clear( 8400 pres->hsp_l0_sched_list.bits, 8401 SHR_BITALLOCSIZE(pres->hsp_l0_sched_list.count), 8402 "hsp_l0_sched_list"); 8403 if (pres->hsp_l0_sched_list.bits == NULL) { 8404 _bcm_ap_cosq_free_memory(mmu_info); 8405 return BCM_E_MEMORY; 8406 } 8407 pres->hsp_l1_sched_list.count = 10 * count; 8408 pres->hsp_l1_sched_list.bits = _bcm_ap_cosq_alloc_clear( 8409 pres->hsp_l1_sched_list.bits, 8410 SHR_BITALLOCSIZE(pres->hsp_l1_sched_list.count), 8411 "hsp_l1_sched_list"); 8412 if (pres->hsp_l1_sched_list.bits == NULL) { 8413 _bcm_ap_cosq_free_memory(mmu_info); 8414 return BCM_E_MEMORY; 8415 } 8416 pres->hsp_l2_queue_list.count = 10 * count; 8417 pres->hsp_l2_queue_list.bits = _bcm_ap_cosq_alloc_clear( 8418 pres->hsp_l2_queue_list.bits, 8419 SHR_BITALLOCSIZE(pres->hsp_l2_queue_list.count), 8420 "hsp_l2_queue_list"); 8421 if (pres->hsp_l2_queue_list.bits == NULL) { 8422 _bcm_ap_cosq_free_memory(mmu_info); 8423 return BCM_E_MEMORY; 8424 } 8425 } 8426 } 8427 8428 for (pipe = _AP_XPIPE; pipe < _AP_YPIPE; pipe++) { 8429 pres = _BCM_AP_PRESOURCES(mmu_info, pipe); 8430 PBMP_ALL_ITER(unit, port) { 8431 _bcm_ap_node_index_set(&pres->l2_queue_list, 8432 mmu_info->port_info[port].uc_base, 8433 si->port_num_uc_cosq[port]); 8434 } 8435 } 8436 8437 /* Initialize oob driver */ 8438 BCM_IF_ERROR_RETURN(_bcm_oob_init(unit)); 8439 8440 /* Create profile for MMU_WRED_DROP_CURVE_PROFILE_x tables */ 8441 if (_bcm_ap_wred_profile[unit] == NULL) { 8442 _bcm_ap_wred_profile[unit] = 8443 sal_alloc(sizeof(soc_profile_mem_t), "WRED Profile Mem"); 8444 if (_bcm_ap_wred_profile[unit] == NULL) { 8445 return BCM_E_MEMORY; 8446 } 8447 soc_profile_mem_t_init(_bcm_ap_wred_profile[unit]); 8448 } 8449 8450 entry_words[0] = 8451 sizeof(mmu_wred_drop_curve_profile_0_entry_t) / sizeof(uint32); 8452 entry_words[1] = 8453 sizeof(mmu_wred_drop_curve_profile_1_entry_t) / sizeof(uint32); 8454 entry_words[2] = 8455 sizeof(mmu_wred_drop_curve_profile_2_entry_t) / sizeof(uint32); 8456 entry_words[3] = 8457 sizeof(mmu_wred_drop_curve_profile_3_entry_t) / sizeof(uint32); 8458 entry_words[4] = 8459 sizeof(mmu_wred_drop_curve_profile_4_entry_t) / sizeof(uint32); 8460 entry_words[5] = 8461 sizeof(mmu_wred_drop_curve_profile_5_entry_t) / sizeof(uint32); 8462 BCM_IF_ERROR_RETURN 8463 (soc_profile_mem_create(unit, wred_mems, entry_words, 6, 8464 _bcm_ap_wred_profile[unit])); 8465 8466 /* Create profile for MMU_QCN_SITB table */ 8467 if (_bcm_ap_sample_int_profile[unit] == NULL) { 8468 _bcm_ap_sample_int_profile[unit] = 8469 sal_alloc(sizeof(soc_profile_mem_t), "QCN sample Int Profile Mem"); 8470 if (_bcm_ap_sample_int_profile[unit] == NULL) { 8471 return BCM_E_MEMORY; 8472 } 8473 soc_profile_mem_t_init(_bcm_ap_sample_int_profile[unit]); 8474 } 8475 mem = MMU_QCN_SITBm; 8476 entry_words[0] = sizeof(mmu_qcn_sitb_entry_t) / sizeof(uint32); 8477 BCM_IF_ERROR_RETURN 8478 (soc_profile_mem_create(unit, &mem, entry_words, 1, 8479 _bcm_ap_sample_int_profile[unit])); 8480 8481 /* Create profile for MMU_QCN_CPQ_SEQ register */ 8482 if (_bcm_ap_feedback_profile[unit] == NULL) { 8483 _bcm_ap_feedback_profile[unit] = 8484 sal_alloc(sizeof(soc_profile_reg_t), "QCN Feedback Profile Reg"); 8485 if (_bcm_ap_feedback_profile[unit] == NULL) { 8486 return BCM_E_MEMORY; 8487 } 8488 soc_profile_reg_t_init(_bcm_ap_feedback_profile[unit]); 8489 } 8490 reg = MMU_QCN_CPQ_SEQr; 8491 BCM_IF_ERROR_RETURN 8492 (soc_profile_reg_create(unit, ®, 1, 8493 _bcm_ap_feedback_profile[unit])); 8494 8495 8496 /* Create profile for VOQ_MOD_MAP table */ 8497 if (_bcm_ap_voq_port_map_profile[unit] == NULL) { 8498 _bcm_ap_voq_port_map_profile[unit] = sal_alloc(sizeof(soc_profile_mem_t), 8499 "VOQ_PORT_MAP Profile Mem"); 8500 if (_bcm_ap_voq_port_map_profile[unit] == NULL) { 8501 return BCM_E_MEMORY; 8502 } 8503 soc_profile_mem_t_init(_bcm_ap_voq_port_map_profile[unit]); 8504 } 8505 mem = VOQ_PORT_MAPm; 8506 entry_words[0] = sizeof(voq_port_map_entry_t) / sizeof(uint32); 8507 BCM_IF_ERROR_RETURN(soc_profile_mem_create(unit, &mem, entry_words, 1, 8508 _bcm_ap_voq_port_map_profile[unit])); 8509 8510 _BCM_DEFAULT_LLS_RESET(mmu_info); 8511 SOC_IF_ERROR_RETURN(READ_LLS_FC_CONFIGr(unit, &rval32)); 8512 soc_reg_field_set(unit, LLS_FC_CONFIGr, &rval32, FC_CFG_DISABLE_ALL_XOFFf, 0); 8513 SOC_IF_ERROR_RETURN(WRITE_LLS_FC_CONFIGr(unit, rval32)); 8514 8515 sal_memset(&bst_callbks, 0, sizeof(_bcm_bst_device_handlers_t)); 8516 bst_callbks.resolve_index = &_bcm_ap_bst_index_resolve; 8517 bst_callbks.reverse_resolve_index = &_bcm_ap_cosq_bst_map_resource_to_gport_cos; 8518 BCM_IF_ERROR_RETURN(_bcm_bst_attach(unit, &bst_callbks)); 8519 8520 8521 /* Endpoint queuing initialization */ 8522 if (soc_feature(unit, soc_feature_endpoint_queuing)) { 8523 if (_bcm_ap_endpoint_queuing_info[unit] == NULL) { 8524 _bcm_ap_endpoint_queuing_info[unit] = 8525 sal_alloc(sizeof(_bcm_ap_endpoint_queuing_info_t), 8526 "Endpoint Queuing Info"); 8527 if (_bcm_ap_endpoint_queuing_info[unit] == NULL) { 8528 return BCM_E_MEMORY; 8529 } 8530 sal_memset(_bcm_ap_endpoint_queuing_info[unit], 0, 8531 sizeof(_bcm_ap_endpoint_queuing_info_t)); 8532 8533 /* The maximum number of endpoints is limited to 2^14, 8534 * since the endpoint ID field is limited to 14 bits in 8535 * Higig2 header. 8536 */ 8537 _BCM_AP_NUM_ENDPOINT(unit) = 1 << 14; 8538 _bcm_ap_endpoint_queuing_info[unit]->ptr_array = sal_alloc( 8539 _BCM_AP_NUM_ENDPOINT(unit) * sizeof(_bcm_ap_endpoint_t *), 8540 "Endpoint Pointer Array"); 8541 if (_bcm_ap_endpoint_queuing_info[unit]->ptr_array == NULL) { 8542 return BCM_E_MEMORY; 8543 } 8544 sal_memset(_bcm_ap_endpoint_queuing_info[unit]->ptr_array, 0, 8545 _BCM_AP_NUM_ENDPOINT(unit) * sizeof(_bcm_ap_endpoint_t *)); 8546 8547 /* Reserve endpoint 0 */ 8548 _bcm_ap_endpoint_queuing_info[unit]->ptr_array[0] = sal_alloc( 8549 sizeof(_bcm_ap_endpoint_t), "Endpoint Info"); 8550 if (_bcm_ap_endpoint_queuing_info[unit]->ptr_array[0] == NULL) { 8551 return BCM_E_MEMORY; 8552 } 8553 sal_memset(_bcm_ap_endpoint_queuing_info[unit]->ptr_array[0], 0, 8554 sizeof(_bcm_ap_endpoint_t)); 8555 8556 8557 _bcm_ap_endpoint_queuing_info[unit]->cos_map_profile = sal_alloc( 8558 sizeof(soc_profile_mem_t), "Priority to CoS Map Profile"); 8559 if (_bcm_ap_endpoint_queuing_info[unit]->cos_map_profile == NULL) { 8560 return BCM_E_MEMORY; 8561 } 8562 soc_profile_mem_t_init 8563 (_bcm_ap_endpoint_queuing_info[unit]->cos_map_profile); 8564 mem = ENDPOINT_COS_MAPm; 8565 entry_words[0] = sizeof(endpoint_cos_map_entry_t) / sizeof(uint32); 8566 SOC_IF_ERROR_RETURN(soc_profile_mem_create(unit, &mem, entry_words, 1, 8567 _bcm_ap_endpoint_queuing_info[unit]->cos_map_profile)); 8568 } 8569 } 8570 8571 for (i = 0; i < si->num_cpu_cosq; i++) { 8572 if (_bcm_ap_cosq_cpu_cosq_config[unit][i] == NULL) { 8573 _bcm_ap_cosq_cpu_cosq_config[unit][i] = 8574 sal_alloc(sizeof(_bcm_ap_cosq_cpu_cosq_config_t), "CPU Cosq Config"); 8575 8576 if (_bcm_ap_cosq_cpu_cosq_config[unit][i] == NULL) { 8577 return BCM_E_MEMORY; 8578 } 8579 sal_memset(_bcm_ap_cosq_cpu_cosq_config[unit][i], 0, 8580 sizeof(_bcm_ap_cosq_cpu_cosq_config_t)); 8581 _bcm_ap_cosq_cpu_cosq_config[unit][i]->enable = 1; 8582 } 8583 } 8584 8585 #ifdef BCM_WARM_BOOT_SUPPORT 8586 if (SOC_WARM_BOOT(unit)) { 8587 return bcm_ap_cosq_reinit(unit); 8588 } else { 8589 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_wb_alloc(unit)); 8590 } 8591 #endif /* BCM_WARM_BOOT_SUPPORT */ 8592 PBMP_ALL_ITER(unit, port) { 8593 if ((port == 74) || IS_AP_HSP_PORT( unit, port)) { 8594 continue; 8595 } 8596 BCM_IF_ERROR_RETURN (_bcm_ap_port_lls_config_set(unit, port)); 8597 } 8598 PBMP_ALL_ITER(unit, port) { 8599 if (!IS_AP_HSP_PORT( unit, port)) { 8600 continue; 8601 } 8602 SOC_IF_ERROR_RETURN(soc_apache_cosq_enable_hsp_sched(unit,port)); 8603 BCM_IF_ERROR_RETURN (_bcm_ap_port_hsp_config_set(unit, port)); 8604 } 8605 sal_memset(&entry_tcp_green, 0, sizeof(entry_tcp_green)); 8606 sal_memset(&entry_tcp_yellow,0, sizeof(entry_tcp_yellow)); 8607 sal_memset(&entry_tcp_red, 0, sizeof(entry_tcp_red)); 8608 sal_memset(&entry_nontcp_green, 0, sizeof(entry_nontcp_green)); 8609 sal_memset(&entry_nontcp_yellow, 0, sizeof(entry_nontcp_yellow)); 8610 sal_memset(&entry_nontcp_red, 0, sizeof(entry_nontcp_red)); 8611 entries[0] = &entry_tcp_green; 8612 entries[1] = &entry_tcp_yellow; 8613 entries[2] = &entry_tcp_red; 8614 entries[3] = &entry_nontcp_green; 8615 entries[4] = &entry_nontcp_yellow; 8616 entries[5] = &entry_nontcp_red; 8617 for (ii = 0; ii < 6; ii++) { 8618 soc_mem_field32_set(unit, wred_mems[ii], entries[ii], 8619 MIN_THDf, 0x1ffff); 8620 soc_mem_field32_set(unit, wred_mems[ii], entries[ii], 8621 MAX_THDf, 0x1ffff); 8622 } 8623 profile_index = 0xffffffff; 8624 wred_prof_count = soc_mem_index_count(unit, MMU_WRED_CONFIG_X_PIPEm); 8625 while(wred_prof_count) { 8626 if (profile_index == 0xffffffff) { 8627 BCM_IF_ERROR_RETURN 8628 (soc_profile_mem_add(unit, 8629 _bcm_ap_wred_profile[unit], 8630 entries, 1, &profile_index)); 8631 } else { 8632 BCM_IF_ERROR_RETURN 8633 (soc_profile_mem_reference(unit, 8634 _bcm_ap_wred_profile[unit], 8635 profile_index, 0)); 8636 } 8637 wred_prof_count -= 1; 8638 } 8639 /* Add default entries for PRIO2COS_PROFILE register profile */ 8640 PBMP_PORT_ITER(unit, port) { 8641 BCM_IF_ERROR_RETURN(bcm_ap_cosq_default_llfc_profile_attach(unit, port)); 8642 } 8643 /* Add default entries for PORT_COS_MAP memory profile */ 8644 BCM_IF_ERROR_RETURN(bcm_ap_cosq_config_set(unit, numq)); 8645 8646 /* Starting the curr_merger_index from 2, 8647 * since 0 is configured in all the FC_MAP_TBL2 by default, 8648 * so it might effect the traffic of other queues 8649 */ 8650 mmu_info->curr_merger_index = 2; 8651 if (!mmu_info->curr_shared_limit) { 8652 BCM_IF_ERROR_RETURN(soc_apache_mmu_get_shared_size(unit, 8653 &mmu_info->curr_shared_limit)); 8654 } 8655 BCM_IF_ERROR_RETURN(bcm_ap_init_fc_map_tbl(unit)); 8656 /* reset time_domain ref_count so that entries can be added upon 8657 * rc */ 8658 time_domain1[unit][0].ref_count = 20780; 8659 time_domain1[unit][1].ref_count = 0; 8660 time_domain1[unit][2].ref_count = 0; 8661 time_domain1[unit][3].ref_count = 0; 8662 return BCM_E_NONE; 8663 } 8664 8665 8666 /* 8667 * Function: 8668 * bcm_ap_cosq_config_get 8669 * Purpose: 8670 * Get the number of cos queues 8671 * Parameters: 8672 * unit - unit number 8673 * numq - (Output) number of cosq 8674 * Returns: 8675 * BCM_E_XXX 8676 */ 8677 int 8678 bcm_ap_cosq_config_get(int unit, int *numq) 8679 { 8680 if (numq != NULL) { 8681 *numq = _AP_NUM_COS(unit); 8682 } 8683 8684 return BCM_E_NONE; 8685 } 8686 8687 /* 8688 * Function: 8689 * _bcm_ap_cosq_mapping_set 8690 * Purpose: 8691 * Set COS queue for the specified priority of an ingress port 8692 * Parameters: 8693 * unit - (IN) unit number 8694 * ing_port - (IN) ingress port 8695 * gport - (IN) queue group GPORT identifier 8696 * priority - (IN) priority value to map 8697 * flags - (IN) BCM_COSQ_GPORT_XXX_QUEUE_GROUP 8698 * gport - (IN) queue group GPORT identifier 8699 * cosq - (IN) COS queue number 8700 * Returns: 8701 * BCM_E_XXX 8702 */ 8703 STATIC int 8704 _bcm_ap_cosq_mapping_set(int unit, bcm_port_t ing_port, bcm_cos_t priority, 8705 uint32 flags, bcm_gport_t gport, bcm_cos_queue_t cosq) 8706 { 8707 bcm_port_t local_port, outport = -1; 8708 bcm_cos_queue_t hw_cosq; 8709 soc_field_t field = INVALIDf, field2 = INVALIDf, field3 = INVALIDf; 8710 cos_map_sel_entry_t cos_map_sel_entry; 8711 port_cos_map_entry_t cos_map_entries[16]; 8712 void *entries[1]; 8713 uint32 old_index, new_index, max_val; 8714 voq_cos_map_entry_t voq_cos_map; 8715 int rv; 8716 int valid = 0; 8717 8718 if (priority < 0 || priority >= 16) { 8719 return BCM_E_PARAM; 8720 } 8721 8722 BCM_IF_ERROR_RETURN 8723 (_bcm_ap_cosq_localport_resolve(unit, ing_port, &local_port)); 8724 8725 if (gport != -1) { 8726 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_localport_resolve(unit, gport, &outport)); 8727 } 8728 8729 8730 switch (flags) { 8731 case BCM_COSQ_GPORT_UCAST_QUEUE_GROUP: 8732 if (gport == -1) { 8733 hw_cosq = cosq; 8734 } else { 8735 BCM_IF_ERROR_RETURN 8736 (_bcm_ap_cosq_index_resolve 8737 (unit, gport, cosq, _BCM_AP_COSQ_INDEX_STYLE_COS, 8738 NULL, &hw_cosq, NULL)); 8739 8740 } 8741 if ((outport != -1) && (IS_HG_PORT(unit, outport))) { 8742 field = HG_COSf; 8743 } else { 8744 field = UC_COS1f; 8745 } 8746 break; 8747 case BCM_COSQ_GPORT_MCAST_QUEUE_GROUP: 8748 if (gport == -1) { 8749 hw_cosq = cosq; 8750 } else { 8751 BCM_IF_ERROR_RETURN 8752 (_bcm_ap_cosq_index_resolve 8753 (unit, gport, cosq, _BCM_AP_COSQ_INDEX_STYLE_COS, 8754 NULL, &hw_cosq, NULL)); 8755 } 8756 field = MC_COS1f; 8757 field2 = RQE_Q_NUMf; 8758 break; 8759 case BCM_COSQ_GPORT_UCAST_QUEUE_GROUP | BCM_COSQ_GPORT_MCAST_QUEUE_GROUP: 8760 if (gport == -1) { 8761 hw_cosq = cosq; 8762 } else { 8763 return BCM_E_PARAM; 8764 } 8765 field = UC_COS1f; 8766 field2 = MC_COS1f; 8767 field3 = RQE_Q_NUMf; 8768 break; 8769 case BCM_COSQ_GPORT_DESTMOD_UCAST_QUEUE_GROUP: 8770 if (gport == -1) { 8771 hw_cosq = cosq; 8772 } else { 8773 BCM_IF_ERROR_RETURN 8774 (_bcm_ap_cosq_index_resolve 8775 (unit, gport, cosq, _BCM_AP_COSQ_INDEX_STYLE_COS, 8776 NULL, &hw_cosq, NULL)); 8777 } 8778 8779 BCM_IF_ERROR_RETURN( 8780 READ_VOQ_COS_MAPm(unit, MEM_BLOCK_ALL, priority, &voq_cos_map)); 8781 valid = soc_mem_field32_get(unit, VOQ_COS_MAPm, &voq_cos_map, 8782 VOQ_COS_USE_MODf); 8783 8784 /* Setting the VOQ_PORT_BASE_SELECT, 8785 so that BASE_QUEUE_NUM_1 is used for queue 8786 calculation */ 8787 8788 soc_mem_field32_set(unit, VOQ_COS_MAPm, 8789 &voq_cos_map, VOQ_PORT_BASE_SELECTf, 1); 8790 soc_mem_field32_set(unit, VOQ_COS_MAPm, 8791 &voq_cos_map, VOQ_COS_USE_MODf, 1); 8792 8793 if (valid && (soc_mem_field32_get(unit, VOQ_COS_MAPm, &voq_cos_map, 8794 VOQ_COS_OFFSETf) != hw_cosq)) { 8795 soc_mem_field32_set(unit, VOQ_COS_MAPm, 8796 &voq_cos_map, VOQ_COS_OFFSETf, hw_cosq); 8797 } 8798 BCM_IF_ERROR_RETURN( 8799 soc_mem_write(unit, VOQ_COS_MAPm, MEM_BLOCK_ANY, priority, 8800 &voq_cos_map)); 8801 return BCM_E_NONE; 8802 break; 8803 default: 8804 return BCM_E_PARAM; 8805 } 8806 8807 entries[0] = &cos_map_entries; 8808 8809 BCM_IF_ERROR_RETURN 8810 (READ_COS_MAP_SELm(unit, MEM_BLOCK_ANY, local_port, 8811 &cos_map_sel_entry)); 8812 old_index = soc_mem_field32_get(unit, COS_MAP_SELm, &cos_map_sel_entry, 8813 SELECTf); 8814 old_index *= 16; 8815 8816 BCM_IF_ERROR_RETURN 8817 (soc_profile_mem_get(unit, _bcm_ap_cos_map_profile[unit], 8818 old_index, 16, entries)); 8819 max_val = soc_property_port_get(unit, local_port, spn_LLS_NUM_L2UC, 16); 8820 if (hw_cosq < 0 || hw_cosq >= max_val) { 8821 return BCM_E_PARAM; 8822 } 8823 8824 soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[priority], field, 8825 hw_cosq); 8826 if (field2 != INVALIDf) { 8827 soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[priority], 8828 field2, hw_cosq); 8829 } 8830 if (field3 != INVALIDf) { 8831 soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[priority], 8832 field3, hw_cosq); 8833 } 8834 8835 soc_mem_lock(unit, PORT_COS_MAPm); 8836 8837 rv = soc_profile_mem_delete(unit, _bcm_ap_cos_map_profile[unit], 8838 old_index); 8839 if (BCM_FAILURE(rv)) { 8840 soc_mem_unlock(unit, PORT_COS_MAPm); 8841 return rv; 8842 } 8843 8844 rv = soc_profile_mem_add(unit, _bcm_ap_cos_map_profile[unit], entries, 8845 16, &new_index); 8846 8847 soc_mem_unlock(unit, PORT_COS_MAPm); 8848 8849 if (BCM_FAILURE(rv)) { 8850 return rv; 8851 } 8852 8853 soc_mem_field32_set(unit, COS_MAP_SELm, &cos_map_sel_entry, SELECTf, 8854 new_index / 16); 8855 BCM_IF_ERROR_RETURN 8856 (WRITE_COS_MAP_SELm(unit, MEM_BLOCK_ANY, local_port, 8857 &cos_map_sel_entry)); 8858 8859 #ifndef BCM_COSQ_HIGIG_MAP_DISABLE 8860 if (IS_CPU_PORT(unit, local_port)) { 8861 BCM_IF_ERROR_RETURN 8862 (soc_mem_field32_modify(unit, COS_MAP_SELm, 8863 SOC_INFO(unit).cpu_hg_index, SELECTf, 8864 new_index / 16)); 8865 } 8866 #endif /* BCM_COSQ_HIGIG_MAP_DISABLE */ 8867 8868 return BCM_E_NONE; 8869 } 8870 8871 /* 8872 * Function: 8873 * bcm_ap_cosq_mapping_set 8874 * Purpose: 8875 * Set which cosq a given priority should fall into 8876 * Parameters: 8877 * unit - (IN) unit number 8878 * gport - (IN) queue group GPORT identifier 8879 * priority - (IN) priority value to map 8880 * cosq - (IN) COS queue to map to 8881 * Returns: 8882 * BCM_E_XXX 8883 */ 8884 8885 int 8886 bcm_ap_cosq_mapping_set(int unit, bcm_port_t port, bcm_cos_t priority, 8887 bcm_cos_queue_t cosq) 8888 { 8889 bcm_pbmp_t pbmp, pbmp1; 8890 bcm_port_t local_port; 8891 8892 BCM_PBMP_CLEAR(pbmp); 8893 BCM_PBMP_CLEAR(pbmp1); 8894 8895 if (port == -1) { 8896 BCM_PBMP_ASSIGN(pbmp, PBMP_ALL(unit)); 8897 BCM_PBMP_ASSIGN(pbmp1, PBMP_HG_ALL(unit)); 8898 BCM_PBMP_REMOVE(pbmp, pbmp1); 8899 } else { 8900 if (BCM_GPORT_IS_SET(port)) { 8901 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 8902 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) || 8903 BCM_GPORT_IS_SCHEDULER(port)) { 8904 return BCM_E_PARAM; 8905 } else if (BCM_GPORT_IS_LOCAL(port)) { 8906 local_port = BCM_GPORT_LOCAL_GET(port); 8907 } else if (BCM_GPORT_IS_MODPORT(port)) { 8908 BCM_IF_ERROR_RETURN( 8909 bcm_esw_port_local_get(unit, port, &local_port)); 8910 } else { 8911 return BCM_E_PARAM; 8912 } 8913 } else { 8914 local_port = port; 8915 } 8916 8917 if (!SOC_PORT_VALID(unit, local_port)) { 8918 return BCM_E_PORT; 8919 } 8920 8921 BCM_PBMP_PORT_ADD(pbmp, local_port); 8922 } 8923 8924 PBMP_ITER(pbmp, local_port) { 8925 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_port_has_ets(unit, local_port)); 8926 } 8927 8928 if ((cosq < 0) || (cosq >= _AP_NUM_COS(unit))) { 8929 return BCM_E_PARAM; 8930 } 8931 8932 PBMP_ITER(pbmp, local_port) { 8933 if (IS_LB_PORT(unit, local_port)) { 8934 continue; 8935 } 8936 8937 /* If no ETS/gport, map the int prio symmetrically for ucast and 8938 * mcast */ 8939 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_mapping_set(unit, local_port, 8940 priority, 8941 BCM_COSQ_GPORT_UCAST_QUEUE_GROUP | 8942 BCM_COSQ_GPORT_MCAST_QUEUE_GROUP, 8943 -1, cosq)); 8944 } 8945 8946 PBMP_ITER(pbmp1, local_port) { 8947 if (IS_LB_PORT(unit, local_port)) { 8948 continue; 8949 } 8950 8951 /* If no ETS/gport, map the int prio symmetrically for ucast and 8952 * mcast */ 8953 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_mapping_set(unit, local_port, 8954 priority, 8955 BCM_COSQ_GPORT_UCAST_QUEUE_GROUP | 8956 BCM_COSQ_GPORT_MCAST_QUEUE_GROUP, 8957 -1, cosq)); 8958 } 8959 return BCM_E_NONE; 8960 } 8961 8962 /* 8963 * Function: 8964 * bcm_ap_cosq_mapping_get 8965 * Purpose: 8966 * Determine which COS queue a given priority currently maps to. 8967 * Parameters: 8968 * unit - (IN) unit number 8969 * gport - (IN) queue group GPORT identifier 8970 * priority - (IN) priority value to map 8971 * cosq - (OUT) COS queue to map to 8972 * Returns: 8973 * BCM_E_XXX 8974 */ 8975 int 8976 _bcm_ap_cosq_mapping_get(int unit, bcm_port_t ing_port, bcm_cos_t priority, 8977 uint32 flags, bcm_gport_t *gport, 8978 bcm_cos_queue_t *cosq) 8979 { 8980 _bcm_ap_mmu_info_t *mmu_info; 8981 _bcm_ap_pipe_resources_t *res; 8982 _bcm_ap_cosq_port_info_t *port_info; 8983 _bcm_ap_cosq_node_t *node; 8984 bcm_port_t local_port; 8985 bcm_cos_queue_t hw_cosq = BCM_COS_INVALID; 8986 int index, ii; 8987 cos_map_sel_entry_t cos_map_sel_entry; 8988 voq_cos_map_entry_t voq_cos_map; 8989 void *entry_p; 8990 8991 if (priority < 0 || priority >= 16) { 8992 return BCM_E_PARAM; 8993 } 8994 8995 if (flags != BCM_COSQ_GPORT_UCAST_QUEUE_GROUP && 8996 flags != BCM_COSQ_GPORT_MCAST_QUEUE_GROUP && 8997 flags != BCM_COSQ_GPORT_DESTMOD_UCAST_QUEUE_GROUP) { 8998 return BCM_E_PARAM; 8999 } 9000 9001 BCM_IF_ERROR_RETURN 9002 (_bcm_ap_cosq_localport_resolve(unit, ing_port, &local_port)); 9003 9004 if (gport) { 9005 *gport = BCM_GPORT_INVALID; 9006 } 9007 9008 *cosq = BCM_COS_INVALID; 9009 9010 BCM_IF_ERROR_RETURN 9011 (READ_COS_MAP_SELm(unit, MEM_BLOCK_ANY, local_port, 9012 &cos_map_sel_entry)); 9013 index = soc_mem_field32_get(unit, COS_MAP_SELm, &cos_map_sel_entry, 9014 SELECTf); 9015 index *= 16; 9016 9017 entry_p = SOC_PROFILE_MEM_ENTRY(unit, _bcm_ap_cos_map_profile[unit], 9018 port_cos_map_entry_t *, 9019 index + priority); 9020 9021 mmu_info = _bcm_ap_mmu_info[unit]; 9022 port_info = &mmu_info->port_info[local_port]; 9023 res = _BCM_AP_PRESOURCES(mmu_info, _BCM_AP_PORT_TO_PIPE(unit, local_port)); 9024 9025 switch (flags) { 9026 case BCM_COSQ_GPORT_UCAST_QUEUE_GROUP: 9027 hw_cosq = soc_mem_field32_get(unit, PORT_COS_MAPm, entry_p, UC_COS1f); 9028 if ((IS_CPU_PORT(unit, local_port) == FALSE) && gport) { 9029 for (ii = port_info->uc_base; ii < port_info->uc_limit; ii++) { 9030 node = &mmu_info->queue_node[ii]; 9031 if (node->numq > 0 && node->hw_cosq == hw_cosq) { 9032 *gport = node->gport; 9033 *cosq = 0; 9034 break; 9035 } 9036 } 9037 if (ii == port_info->uc_limit) { 9038 return BCM_E_NOT_FOUND; 9039 } 9040 } 9041 break; 9042 case BCM_COSQ_GPORT_MCAST_QUEUE_GROUP: 9043 hw_cosq = soc_mem_field32_get(unit, PORT_COS_MAPm, entry_p, MC_COS1f); 9044 if (gport) { 9045 for (ii = port_info->mc_base; ii < port_info->mc_limit; ii++) { 9046 node = &mmu_info->mc_queue_node[ii]; 9047 if (node->numq > 0 && node->hw_cosq == hw_cosq) { 9048 *gport = node->gport; 9049 *cosq = 0; 9050 break; 9051 } 9052 } 9053 if (ii == port_info->mc_limit) { 9054 return BCM_E_NOT_FOUND; 9055 } 9056 } 9057 break; 9058 9059 case BCM_COSQ_GPORT_DESTMOD_UCAST_QUEUE_GROUP: 9060 BCM_IF_ERROR_RETURN( 9061 READ_VOQ_COS_MAPm(unit, MEM_BLOCK_ALL, priority, &voq_cos_map)); 9062 hw_cosq = soc_mem_field32_get(unit, VOQ_COS_MAPm, 9063 &voq_cos_map, VOQ_COS_OFFSETf); 9064 if (gport) { 9065 for (ii = res->num_base_queues; ii < _BCM_AP_NUM_L2_UC_LEAVES; ii++) { 9066 node = &mmu_info->queue_node[ii]; 9067 9068 if (node->numq > 0 && node->hw_cosq == hw_cosq) { 9069 *gport = node->gport; 9070 break; 9071 } 9072 } 9073 if (ii == _BCM_AP_NUM_L2_UC_LEAVES) { 9074 return BCM_E_NOT_FOUND; 9075 } 9076 } 9077 break; 9078 } 9079 9080 *cosq = hw_cosq; 9081 9082 if (((gport && 9083 (*gport == BCM_GPORT_INVALID) && (*cosq == BCM_COS_INVALID))) || 9084 (*cosq == BCM_COS_INVALID)) { 9085 return BCM_E_NOT_FOUND; 9086 } 9087 9088 return BCM_E_NONE; 9089 } 9090 9091 int 9092 bcm_ap_cosq_mapping_get(int unit, bcm_port_t port, bcm_cos_t priority, 9093 bcm_cos_queue_t *cosq) 9094 { 9095 bcm_port_t local_port; 9096 bcm_pbmp_t pbmp; 9097 9098 BCM_PBMP_CLEAR(pbmp); 9099 9100 if (port == -1) { 9101 BCM_PBMP_ASSIGN(pbmp, PBMP_ALL(unit)); 9102 } else { 9103 if (BCM_GPORT_IS_SET(port)) { 9104 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 9105 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) || 9106 BCM_GPORT_IS_SCHEDULER(port)) { 9107 return BCM_E_PARAM; 9108 } else if (BCM_GPORT_IS_LOCAL(port)) { 9109 local_port = BCM_GPORT_LOCAL_GET(port); 9110 } else if (BCM_GPORT_IS_MODPORT(port)) { 9111 BCM_IF_ERROR_RETURN( 9112 bcm_esw_port_local_get(unit, port, &local_port)); 9113 } else { 9114 return BCM_E_PARAM; 9115 } 9116 } else { 9117 local_port = port; 9118 } 9119 9120 if (!SOC_PORT_VALID(unit, local_port)) { 9121 return BCM_E_PORT; 9122 } 9123 9124 BCM_PBMP_PORT_ADD(pbmp, local_port); 9125 } 9126 9127 PBMP_ITER(pbmp, local_port) { 9128 if (IS_LB_PORT(unit, local_port)) { 9129 continue; 9130 } 9131 9132 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_mapping_get(unit, local_port, 9133 priority, BCM_COSQ_GPORT_UCAST_QUEUE_GROUP, NULL, cosq)); 9134 break; 9135 } 9136 return BCM_E_NONE; 9137 } 9138 9139 int 9140 bcm_ap_cosq_gport_mapping_set(int unit, bcm_port_t ing_port, 9141 bcm_cos_t int_pri, uint32 flags, 9142 bcm_gport_t gport, bcm_cos_queue_t cosq) 9143 { 9144 return _bcm_ap_cosq_mapping_set(unit, ing_port, int_pri, flags, gport, 9145 cosq); 9146 } 9147 9148 int 9149 bcm_ap_cosq_gport_mapping_get(int unit, bcm_port_t ing_port, 9150 bcm_cos_t int_pri, uint32 flags, 9151 bcm_gport_t *gport, bcm_cos_queue_t *cosq) 9152 { 9153 if (gport == NULL || cosq == NULL) { 9154 return BCM_E_PARAM; 9155 } 9156 9157 return _bcm_ap_cosq_mapping_get(unit, ing_port, int_pri, flags, gport, 9158 cosq); 9159 } 9160 9161 /* 9162 * Function: 9163 * bcm_ap_cosq_port_sched_set 9164 * Purpose: 9165 * Set up class-of-service policy and corresponding weights and delay 9166 * Parameters: 9167 * unit - (IN) unit number 9168 * pbm - (IN) port bitmap 9169 * mode - (IN) Scheduling mode (BCM_COSQ_xxx) 9170 * weights - (IN) Weights for each COS queue 9171 * delay - This parameter is not used 9172 * Returns: 9173 * BCM_E_XXX 9174 */ 9175 int 9176 bcm_ap_cosq_port_sched_set(int unit, bcm_pbmp_t pbm, 9177 int mode, const int *weights, int delay) 9178 { 9179 bcm_port_t port; 9180 int num_weights, i; 9181 int cur_mode, cur_weight; 9182 int reset_mode = BCM_COSQ_WEIGHTED_ROUND_ROBIN; 9183 9184 num_weights = _AP_NUM_COS(unit); 9185 BCM_PBMP_ITER(pbm, port) { 9186 /*WRR mode is a property per port, 9187 * so just get cosq=0 schedule mode*/ 9188 BCM_IF_ERROR_RETURN 9189 (_bcm_ap_cosq_sched_get(unit, port, 0, 9190 &cur_mode, &cur_weight)); 9191 if (cur_mode == BCM_COSQ_STRICT) { 9192 reset_mode = BCM_COSQ_WEIGHTED_ROUND_ROBIN; 9193 } else { 9194 reset_mode = cur_mode; 9195 } 9196 9197 /* Schedule mode switch need base on default wrr mode */ 9198 for (i = 0; i < num_weights; i++) { 9199 BCM_IF_ERROR_RETURN 9200 (_bcm_ap_cosq_sched_set(unit, port, i, 9201 reset_mode, 1)); 9202 } 9203 9204 for (i = 0; i < num_weights; i++) { 9205 BCM_IF_ERROR_RETURN 9206 (_bcm_ap_cosq_sched_set(unit, port, i, mode, weights[i])); 9207 } 9208 } 9209 9210 return BCM_E_NONE; 9211 } 9212 9213 /* 9214 * Function: 9215 * bcm_ap_cosq_port_sched_get 9216 * Purpose: 9217 * Retrieve class-of-service policy and corresponding weights and delay 9218 * Parameters: 9219 * unit - (IN) unit number 9220 * pbm - (IN) port bitmap 9221 * mode - (OUT) Scheduling mode (BCM_COSQ_XXX) 9222 * weights - (OUT) Weights for each COS queue 9223 * delay - This parameter is not used 9224 * Returns: 9225 * BCM_E_XXX 9226 */ 9227 int 9228 bcm_ap_cosq_port_sched_get(int unit, bcm_pbmp_t pbm, 9229 int *mode, int *weights, int *delay) 9230 { 9231 bcm_port_t port; 9232 int i, num_weights; 9233 9234 BCM_PBMP_ITER(pbm, port) { 9235 if (IS_CPU_PORT(unit, port) && SOC_PBMP_NEQ(pbm, PBMP_CMIC(unit))) { 9236 continue; 9237 } 9238 num_weights = _AP_NUM_COS(unit); 9239 for (i = 0; i < num_weights; i++) { 9240 BCM_IF_ERROR_RETURN( 9241 _bcm_ap_cosq_sched_get(unit, port, i, mode, &weights[i])); 9242 } 9243 } 9244 9245 return BCM_E_NONE; 9246 } 9247 9248 /* 9249 * Function: 9250 * bcm_ap_cosq_sched_weight_max_get 9251 * Purpose: 9252 * Retrieve maximum weights for given COS policy 9253 * Parameters: 9254 * unit - (IN) unit number 9255 * mode - (IN) Scheduling mode (BCM_COSQ_xxx) 9256 * weight_max - (OUT) Maximum weight for COS queue. 9257 * Returns: 9258 * BCM_E_XXX 9259 */ 9260 int 9261 bcm_ap_cosq_sched_weight_max_get(int unit, int mode, int *weight_max) 9262 { 9263 switch (mode) { 9264 case BCM_COSQ_STRICT: 9265 *weight_max = BCM_COSQ_WEIGHT_STRICT; 9266 break; 9267 case BCM_COSQ_ROUND_ROBIN: 9268 case BCM_COSQ_WEIGHTED_ROUND_ROBIN: 9269 case BCM_COSQ_DEFICIT_ROUND_ROBIN: 9270 /* AP - weights can be calculated based on LLS/HSP based 9271 * scheduling type associated to the port, in either case 9272 * the maximum weight can be 127 9273 */ 9274 *weight_max = 9275 (1 << soc_reg_field_length(unit, HSP_SCHED_L0_NODE_WEIGHTr, 9276 WEIGHTf)) - 1; 9277 break; 9278 default: 9279 return BCM_E_PARAM; 9280 } 9281 9282 return BCM_E_NONE; 9283 } 9284 9285 /* 9286 * Function: 9287 * bcm_ap_cosq_bandwidth_set 9288 * Purpose: 9289 * Configure COS queue bandwidth control 9290 * Parameters: 9291 * unit - (IN) unit number 9292 * port - (IN) port number or GPORT identifier 9293 * cosq - (IN) COS queue number 9294 * min_quantum - (IN) 9295 * max_quantum - (IN) 9296 * burst_quantum - (IN) 9297 * flags - (IN) 9298 * Returns: 9299 * BCM_E_XXX 9300 * Notes: 9301 * If port is any form of local port, cosq is the hardware queue index. 9302 */ 9303 int 9304 bcm_ap_cosq_port_bandwidth_set(int unit, bcm_port_t port, 9305 bcm_cos_queue_t cosq, 9306 uint32 min_quantum, uint32 max_quantum, 9307 uint32 burst_quantum, uint32 flags) 9308 { 9309 uint32 burst_min, burst_max; 9310 9311 if (cosq < 0) { 9312 return BCM_E_PARAM; 9313 } 9314 9315 burst_min = (min_quantum > 0) ? 9316 _bcm_td_default_burst_size(unit, port, min_quantum) : 0; 9317 9318 burst_max = (max_quantum > 0) ? 9319 _bcm_td_default_burst_size(unit, port, max_quantum) : 0; 9320 9321 return _bcm_ap_cosq_bucket_set(unit, port, cosq, min_quantum, max_quantum, 9322 burst_min, burst_max, flags); 9323 } 9324 9325 /* 9326 * Function: 9327 * bcm_ap_cosq_bandwidth_get 9328 * Purpose: 9329 * Get COS queue bandwidth control configuration 9330 * Parameters: 9331 * unit - (IN) unit number 9332 * port - (IN) port number or GPORT identifier 9333 * cosq - (IN) COS queue number 9334 * min_quantum - (OUT) 9335 * max_quantum - (OUT) 9336 * burst_quantum - (OUT) 9337 * flags - (OUT) 9338 * Returns: 9339 * BCM_E_XXX 9340 * Notes: 9341 * If port is any form of local port, cosq is the hardware queue index. 9342 */ 9343 int 9344 bcm_ap_cosq_port_bandwidth_get(int unit, bcm_port_t port, 9345 bcm_cos_queue_t cosq, 9346 uint32 *min_quantum, uint32 *max_quantum, 9347 uint32 *burst_quantum, uint32 *flags) 9348 { 9349 uint32 kbit_burst_min; 9350 9351 if (cosq < -1) { 9352 return BCM_E_PARAM; 9353 } 9354 9355 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_bucket_get(unit, port, cosq, 9356 min_quantum, max_quantum, &kbit_burst_min, 9357 burst_quantum, flags)); 9358 return BCM_E_NONE; 9359 } 9360 9361 int 9362 bcm_ap_cosq_port_pps_set(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 9363 int pps) 9364 { 9365 uint32 min, max, burst, burst_min, flags; 9366 bcm_port_t local_port = port; 9367 9368 if (!IS_CPU_PORT(unit, port)) { 9369 return BCM_E_PORT; 9370 } else if (cosq < 0 || cosq >= NUM_CPU_COSQ(unit)) { 9371 return BCM_E_PARAM; 9372 } 9373 9374 if (_bcm_ap_cosq_port_has_ets(unit, port)) { 9375 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_l2_gport(unit, port, cosq, 9376 _BCM_AP_NODE_MCAST, &port, NULL)); 9377 cosq = 0; 9378 } 9379 9380 BCM_IF_ERROR_RETURN 9381 (_bcm_ap_cosq_bucket_get(unit, port, cosq, &min, &max, &burst_min, 9382 &burst, &flags)); 9383 9384 min = pps; 9385 burst_min = (min > 0) ? 9386 _bcm_td_default_burst_size(unit, local_port, min) : 0; 9387 burst = burst_min; 9388 9389 return _bcm_ap_cosq_bucket_set(unit, port, cosq, min, pps, burst_min, burst, 9390 flags | BCM_COSQ_BW_PACKET_MODE); 9391 } 9392 9393 int 9394 bcm_ap_cosq_port_pps_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 9395 int *pps) 9396 { 9397 uint32 min, max, burst, flags; 9398 9399 if (!IS_CPU_PORT(unit, port)) { 9400 return BCM_E_PORT; 9401 } else if (cosq < 0 || cosq >= NUM_CPU_COSQ(unit)) { 9402 return BCM_E_PARAM; 9403 } 9404 9405 if (_bcm_ap_cosq_port_has_ets(unit, port)) { 9406 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_l2_gport(unit, port, cosq, 9407 _BCM_AP_NODE_MCAST, &port, NULL)); 9408 cosq = 0; 9409 } 9410 9411 BCM_IF_ERROR_RETURN 9412 (_bcm_ap_cosq_bucket_get(unit, port, cosq, &min, &max, &burst, &burst, 9413 &flags)); 9414 *pps = max; 9415 9416 return BCM_E_NONE; 9417 } 9418 9419 int 9420 bcm_ap_cosq_port_burst_set(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 9421 int burst) 9422 { 9423 uint32 min, max, cur_burst, flags; 9424 9425 if (!IS_CPU_PORT(unit, port)) { 9426 return BCM_E_PORT; 9427 } else if (cosq < 0 || cosq >= NUM_CPU_COSQ(unit)) { 9428 return BCM_E_PARAM; 9429 } 9430 9431 if (_bcm_ap_cosq_port_has_ets(unit, port)) { 9432 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_l2_gport(unit, port, cosq, 9433 _BCM_AP_NODE_MCAST, &port, NULL)); 9434 cosq = 0; 9435 } 9436 9437 BCM_IF_ERROR_RETURN 9438 (_bcm_ap_cosq_bucket_get(unit, port, cosq, &min, &max, &cur_burst, 9439 &cur_burst, &flags)); 9440 9441 /* Replace the current BURST setting, keep PPS the same */ 9442 return _bcm_ap_cosq_bucket_set(unit, port, cosq, min, max, burst, burst, 9443 flags | BCM_COSQ_BW_PACKET_MODE); 9444 } 9445 9446 int 9447 bcm_ap_cosq_port_burst_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 9448 int *burst) 9449 { 9450 uint32 min, max, cur_burst, cur_burst_min, flags; 9451 9452 if (!IS_CPU_PORT(unit, port)) { 9453 return BCM_E_PORT; 9454 } else if (cosq < 0 || cosq >= NUM_CPU_COSQ(unit)) { 9455 return BCM_E_PARAM; 9456 } 9457 9458 if (_bcm_ap_cosq_port_has_ets(unit, port)) { 9459 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_l2_gport(unit, port, cosq, 9460 _BCM_AP_NODE_MCAST, &port, NULL)); 9461 cosq = 0; 9462 } 9463 9464 BCM_IF_ERROR_RETURN 9465 (_bcm_ap_cosq_bucket_get(unit, port, cosq, &min, &max, 9466 &cur_burst_min, &cur_burst, &flags)); 9467 *burst = cur_burst; 9468 9469 return BCM_E_NONE; 9470 } 9471 9472 int 9473 bcm_ap_cosq_discard_set(int unit, uint32 flags) 9474 { 9475 bcm_port_t port; 9476 _bcm_ap_mmu_info_t *mmu_info; 9477 9478 if ((mmu_info = _bcm_ap_mmu_info[unit]) == NULL) { 9479 return BCM_E_INIT; 9480 } 9481 9482 flags &= ~(BCM_COSQ_DISCARD_NONTCP | BCM_COSQ_DISCARD_COLOR_ALL); 9483 9484 PBMP_PORT_ITER(unit, port) { 9485 BCM_IF_ERROR_RETURN 9486 (_bcm_ap_cosq_wred_set(unit, port, 0, flags, 0, 0, 0, 0, 9487 FALSE, BCM_COSQ_DISCARD_PORT,8)); 9488 } 9489 9490 return BCM_E_NONE; 9491 } 9492 9493 int 9494 bcm_ap_cosq_discard_get(int unit, uint32 *flags) 9495 { 9496 bcm_port_t port; 9497 9498 PBMP_PORT_ITER(unit, port) { 9499 *flags = 0; 9500 /* use setting from hardware cosq index 0 of the first port */ 9501 return _bcm_ap_cosq_wred_get(unit, port, 0, flags, NULL, NULL, NULL, 9502 NULL, BCM_COSQ_DISCARD_PORT,NULL); 9503 } 9504 9505 return BCM_E_NOT_FOUND; 9506 } 9507 9508 /* 9509 * Function: 9510 * bcm_ap_cosq_discard_port_set 9511 * Purpose: 9512 * Configure port WRED setting 9513 * Parameters: 9514 * unit - (IN) unit number 9515 * port - (IN) port number or GPORT identifier 9516 * cosq - (IN) COS queue number 9517 * color - (IN) 9518 * drop_start - (IN) 9519 * drop_slot - (IN) 9520 * average_time - (IN) 9521 * Returns: 9522 * BCM_E_XXX 9523 * Notes: 9524 * If port is any form of local port, cosq is the hardware queue index. 9525 */ 9526 int 9527 bcm_ap_cosq_discard_port_set(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 9528 uint32 color, int drop_start, int drop_slope, 9529 int average_time) 9530 { 9531 bcm_port_t local_port; 9532 bcm_pbmp_t pbmp; 9533 int gain; 9534 uint32 min_thresh, max_thresh, shared_limit; 9535 uint32 rval, bits, flags = 0; 9536 int numq, i; 9537 9538 if (drop_start < 0 || drop_start > 100 || 9539 drop_slope < 0 || drop_slope > 90) { 9540 return BCM_E_PARAM; 9541 } 9542 9543 /* 9544 * average queue size is reculated every 8us, the formula is 9545 * avg_qsize(t + 1) = 9546 * avg_qsize(t) + (cur_qsize - avg_qsize(t)) / (2 ** gain) 9547 * gain = log2(average_time / 8) 9548 */ 9549 bits = (average_time / 8) & 0xffff; 9550 if (bits != 0) { 9551 bits |= bits >> 1; 9552 bits |= bits >> 2; 9553 bits |= bits >> 4; 9554 bits |= bits >> 8; 9555 gain = _shr_popcount(bits) - 1; 9556 } else { 9557 gain = 0; 9558 } 9559 9560 /* 9561 * per-port cell limit may be disabled. 9562 * per-port per-cos cell limit may be set to use dynamic method. 9563 * therefore drop_start percentage is based on per-device total shared 9564 * cells. 9565 */ 9566 BCM_IF_ERROR_RETURN(READ_MMU_THDM_DB_POOL_SHARED_LIMITr(unit, 0, &rval)); 9567 shared_limit = soc_reg_field_get(unit, MMU_THDM_DB_POOL_SHARED_LIMITr, 9568 rval, SHARED_LIMITf); 9569 min_thresh = ((drop_start * shared_limit) + (100 - 1)) / 100; 9570 9571 if ( min_thresh == shared_limit ) { 9572 min_thresh = AP_CELL_FIELD_MAX; 9573 } 9574 /* Calculate the max threshold. For a given slope (angle in 9575 * degrees), determine how many packets are in the range from 9576 * 0% drop probability to 100% drop probability. Add that 9577 * number to the min_treshold to the the max_threshold. 9578 */ 9579 max_thresh = min_thresh + _bcm_ap_angle_to_cells(drop_slope); 9580 if (max_thresh > AP_CELL_FIELD_MAX) { 9581 max_thresh = AP_CELL_FIELD_MAX; 9582 } 9583 9584 if (BCM_GPORT_IS_SET(port)) { 9585 numq = 1; 9586 for (i = 0; i < numq; i++) { 9587 BCM_IF_ERROR_RETURN 9588 (_bcm_ap_cosq_wred_set(unit, port, cosq + i, color, 9589 min_thresh, max_thresh, 100, gain, 9590 TRUE, flags,8)); 9591 } 9592 } else { 9593 if (port == -1) { 9594 BCM_PBMP_ASSIGN(pbmp, PBMP_PORT_ALL(unit)); 9595 } else if (!SOC_PORT_VALID(unit, port)) { 9596 return BCM_E_PORT; 9597 } else { 9598 BCM_PBMP_PORT_SET(pbmp, port); 9599 } 9600 9601 BCM_PBMP_ITER(pbmp, local_port) { 9602 numq = 1; 9603 for (i = 0; i < numq; i++) { 9604 BCM_IF_ERROR_RETURN 9605 (_bcm_ap_cosq_wred_set(unit, local_port, cosq + i, 9606 color, min_thresh, max_thresh, 100, 9607 gain, TRUE, 0,8)); 9608 } 9609 } 9610 } 9611 9612 return BCM_E_NONE; 9613 } 9614 9615 /* 9616 * Function: 9617 * bcm_ap_cosq_discard_port_get 9618 * Purpose: 9619 * Get port WRED setting 9620 * Parameters: 9621 * unit - (IN) unit number 9622 * port - (IN) port number or GPORT identifier 9623 * cosq - (IN) COS queue number 9624 * color - (OUT) 9625 * drop_start - (OUT) 9626 * drop_slot - (OUT) 9627 * average_time - (OUT) 9628 * Returns: 9629 * BCM_E_XXX 9630 * Notes: 9631 * If port is any form of local port, cosq is the hardware queue index. 9632 */ 9633 int 9634 bcm_ap_cosq_discard_port_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 9635 uint32 color, int *drop_start, int *drop_slope, 9636 int *average_time) 9637 { 9638 bcm_port_t local_port; 9639 bcm_pbmp_t pbmp; 9640 int gain, drop_prob; 9641 int refresh_time = 0; 9642 uint32 min_thresh, max_thresh, shared_limit; 9643 uint32 rval; 9644 9645 if (drop_start == NULL || drop_slope == NULL || average_time == NULL) { 9646 return BCM_E_PARAM; 9647 } 9648 9649 if (BCM_GPORT_IS_SET(port)) { 9650 local_port = port; 9651 } else { 9652 if (port == -1) { 9653 BCM_PBMP_ASSIGN(pbmp, PBMP_PORT_ALL(unit)); 9654 } else if (!SOC_PORT_VALID(unit, port)) { 9655 return BCM_E_PORT; 9656 } else { 9657 BCM_PBMP_PORT_SET(pbmp, port); 9658 } 9659 BCM_PBMP_ITER(pbmp, local_port) { 9660 break; 9661 } 9662 } 9663 9664 BCM_IF_ERROR_RETURN 9665 (_bcm_ap_cosq_wred_get(unit, local_port, cosq == -1 ? 0 : cosq, 9666 &color, &min_thresh, &max_thresh, &drop_prob, 9667 &gain, 0,&refresh_time)); 9668 9669 /* 9670 * average queue size is reculated every 4us, the formula is 9671 * avg_qsize(t + 1) = 9672 * avg_qsize(t) + (cur_qsize - avg_qsize(t)) / (2 ** gain) 9673 */ 9674 *average_time = (1 << gain) * refresh_time; 9675 BCM_IF_ERROR_RETURN(READ_MMU_THDM_DB_POOL_SHARED_LIMITr(unit, 0, &rval)); 9676 shared_limit = soc_reg_field_get(unit, MMU_THDM_DB_POOL_SHARED_LIMITr, 9677 rval, SHARED_LIMITf); 9678 if (shared_limit == 0) { 9679 return BCM_E_RESOURCE; 9680 } 9681 9682 if (min_thresh > shared_limit) { 9683 min_thresh = shared_limit; 9684 } 9685 9686 if (max_thresh > shared_limit) { 9687 max_thresh = shared_limit; 9688 } 9689 9690 *drop_start = min_thresh * 100 / shared_limit; 9691 9692 /* Calculate the slope using the min and max threshold. 9693 * The angle is calculated knowing drop probability at min 9694 * threshold is 0% and drop probability at max threshold is 100%. 9695 */ 9696 *drop_slope = _bcm_ap_cells_to_angle(max_thresh - min_thresh); 9697 9698 return BCM_E_NONE; 9699 } 9700 9701 STATIC int 9702 _bcm_ap_distribute_u64(uint64 value, uint64 *l, uint64 *r) 9703 { 9704 uint64 tmp, tmp1; 9705 9706 tmp = value; 9707 COMPILER_64_SHR(tmp, 1); 9708 *l = tmp; 9709 9710 COMPILER_64_SET(tmp1, 0, 1); 9711 COMPILER_64_AND(tmp1, value); 9712 COMPILER_64_ADD_64(tmp1, tmp); 9713 *r = tmp1; 9714 return 0; 9715 } 9716 9717 9718 int 9719 bcm_ap_cosq_stat_set(int unit, bcm_gport_t port, bcm_cos_queue_t cosq, 9720 bcm_cosq_stat_t stat, uint64 value) 9721 { 9722 _bcm_ap_cosq_node_t *node; 9723 bcm_port_t local_port; 9724 int startq, numq, i, from_cos, to_cos, ci; 9725 uint64 l, r; 9726 uint64 max; 9727 soc_reg_t ctr_reg; 9728 soc_ctr_control_info_t ctrl_info; 9729 _bcm_ap_mmu_info_t *mmu_info; 9730 _bcm_ap_cosq_port_info_t *port_info; 9731 9732 COMPILER_64_SET(max, 0, 0xffffffff); 9733 if ((cosq < -1) || COMPILER_64_GT(value, max)) { 9734 return BCM_E_PARAM; 9735 } 9736 _bcm_ap_distribute_u64(value, &l, &r); 9737 9738 mmu_info = _bcm_ap_mmu_info[unit]; 9739 9740 switch (stat) { 9741 case bcmCosqStatDroppedPackets: 9742 if (BCM_GPORT_IS_SCHEDULER(port)) { 9743 BCM_IF_ERROR_RETURN 9744 (_bcm_ap_cosq_node_get(unit, port, 0, NULL, 9745 &local_port, NULL, &node)); 9746 BCM_IF_ERROR_RETURN( 9747 _bcm_ap_cosq_child_node_at_input(node, cosq, &node)); 9748 port = node->gport; 9749 } 9750 9751 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) { 9752 BCM_IF_ERROR_RETURN 9753 (_bcm_ap_cosq_node_get(unit, port, 0, NULL, 9754 NULL, NULL, &node)); 9755 if (node->type == _BCM_AP_NODE_VM_UCAST) { 9756 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9757 BCM_IF_ERROR_RETURN 9758 (soc_counter_set(unit, -1, 9759 SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_UC, node->hw_index, 9760 value)); 9761 } else { 9762 BCM_IF_ERROR_RETURN 9763 (_bcm_ap_cosq_index_resolve 9764 (unit, port, cosq, _BCM_AP_COSQ_INDEX_STYLE_EGR_PERQ_UCAST, 9765 &local_port, &startq, NULL)); 9766 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9767 BCM_IF_ERROR_RETURN 9768 (_bcm_ap_cosq_node_get(unit, port, 0, NULL, 9769 &local_port, NULL, &node)); 9770 port_info = &mmu_info->port_info[local_port]; 9771 if (node->hw_index < port_info->uc_base || 9772 node->hw_index >= port_info->uc_limit) { 9773 BCM_IF_ERROR_RETURN 9774 (soc_counter_set(unit, node->hw_index, 9775 SOC_COUNTER_NON_DMA_COSQ_DROP_PKT, 0, 9776 value)); 9777 } else { 9778 BCM_IF_ERROR_RETURN 9779 (soc_counter_set(unit, local_port, 9780 SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_UC, startq, 9781 value)); 9782 } 9783 } 9784 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 9785 BCM_IF_ERROR_RETURN 9786 (_bcm_ap_cosq_index_resolve 9787 (unit, port, cosq, _BCM_AP_COSQ_INDEX_STYLE_EGR_PERQ_MCAST, 9788 &local_port, &startq, NULL)); 9789 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9790 BCM_IF_ERROR_RETURN 9791 (soc_counter_set(unit, local_port, 9792 SOC_COUNTER_NON_DMA_COSQ_DROP_PKT, startq, 9793 value)); 9794 } else { 9795 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_localport_resolve(unit, port, &local_port)); 9796 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_port_has_ets(unit, local_port)); 9797 if (cosq == BCM_COS_INVALID) { 9798 from_cos = to_cos = 0; 9799 } else { 9800 from_cos = to_cos = cosq; 9801 } 9802 for (ci = from_cos; ci <= to_cos; ci++) { 9803 if (!IS_CPU_PORT(unit, local_port)) { 9804 BCM_IF_ERROR_RETURN 9805 (_bcm_ap_cosq_index_resolve 9806 (unit, port, ci, _BCM_AP_COSQ_INDEX_STYLE_EGR_PERQ_UCAST, 9807 &local_port, &startq, &numq)); 9808 for (i = 0; i < numq; i++) { 9809 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9810 BCM_IF_ERROR_RETURN 9811 (soc_counter_set(unit, local_port, 9812 SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_UC, 9813 startq + i, l)); 9814 } 9815 } 9816 BCM_IF_ERROR_RETURN 9817 (_bcm_ap_cosq_index_resolve 9818 (unit, port, ci, _BCM_AP_COSQ_INDEX_STYLE_EGR_PERQ_MCAST, 9819 &local_port, &startq, &numq)); 9820 for (i = 0; i < numq; i++) { 9821 BCM_IF_ERROR_RETURN 9822 (soc_counter_set(unit, local_port, 9823 SOC_COUNTER_NON_DMA_COSQ_DROP_PKT, 9824 startq + i , r)); 9825 } 9826 } 9827 } 9828 break; 9829 case bcmCosqStatDroppedBytes: 9830 if (BCM_GPORT_IS_SCHEDULER(port)) { 9831 BCM_IF_ERROR_RETURN 9832 (_bcm_ap_cosq_node_get(unit, port, 0, NULL, 9833 &local_port, NULL, &node)); 9834 BCM_IF_ERROR_RETURN( 9835 _bcm_ap_cosq_child_node_at_input(node, cosq, &node)); 9836 port = node->gport; 9837 } 9838 9839 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) { 9840 BCM_IF_ERROR_RETURN 9841 (_bcm_ap_cosq_node_get(unit, port, 0, NULL, 9842 NULL, NULL, &node)); 9843 if (node->type == _BCM_AP_NODE_VM_UCAST) { 9844 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9845 BCM_IF_ERROR_RETURN 9846 (soc_counter_set(unit, -1, 9847 SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE_UC, node->hw_index, 9848 value)); 9849 } else { 9850 BCM_IF_ERROR_RETURN 9851 (_bcm_ap_cosq_index_resolve 9852 (unit, port, cosq, _BCM_AP_COSQ_INDEX_STYLE_EGR_PERQ_UCAST, 9853 &local_port, &startq, NULL)); 9854 BCM_IF_ERROR_RETURN 9855 (_bcm_ap_cosq_node_get(unit, port, 0, NULL, 9856 &local_port, NULL, &node)); 9857 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9858 port_info = &mmu_info->port_info[local_port]; 9859 if (node->hw_index < port_info->uc_base || 9860 node->hw_index >= port_info->uc_limit) { 9861 BCM_IF_ERROR_RETURN 9862 (soc_counter_set(unit, node->hw_index, 9863 SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE, 0, 9864 value)); 9865 } else { 9866 BCM_IF_ERROR_RETURN 9867 (soc_counter_set(unit, local_port, 9868 SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE_UC, startq, 9869 value)); 9870 } 9871 } 9872 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 9873 BCM_IF_ERROR_RETURN 9874 (_bcm_ap_cosq_index_resolve 9875 (unit, port, cosq, _BCM_AP_COSQ_INDEX_STYLE_EGR_PERQ_MCAST, 9876 &local_port, &startq, NULL)); 9877 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9878 BCM_IF_ERROR_RETURN 9879 (soc_counter_set(unit, local_port, 9880 SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE, startq , value)); 9881 } else { 9882 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_localport_resolve(unit, port, &local_port)); 9883 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_port_has_ets(unit, local_port)); 9884 if (cosq == BCM_COS_INVALID) { 9885 from_cos = to_cos = 0; 9886 } else { 9887 from_cos = to_cos = cosq; 9888 } 9889 for (ci = from_cos; ci <= to_cos; ci++) { 9890 if (!IS_CPU_PORT(unit, local_port)) { 9891 BCM_IF_ERROR_RETURN 9892 (_bcm_ap_cosq_index_resolve 9893 (unit, port, ci, _BCM_AP_COSQ_INDEX_STYLE_EGR_PERQ_UCAST, 9894 &local_port, &startq, &numq)); 9895 for (i = 0; i < numq; i++) { 9896 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9897 BCM_IF_ERROR_RETURN 9898 (soc_counter_set(unit, local_port, 9899 SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE_UC, 9900 startq + i, l)); 9901 } 9902 } 9903 BCM_IF_ERROR_RETURN 9904 (_bcm_ap_cosq_index_resolve 9905 (unit, port, ci, _BCM_AP_COSQ_INDEX_STYLE_EGR_PERQ_MCAST, 9906 &local_port, &startq, &numq)); 9907 for (i = 0; i < numq; i++) { 9908 BCM_IF_ERROR_RETURN 9909 (soc_counter_set(unit, local_port, 9910 SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE, 9911 startq + i , r)); 9912 } 9913 } 9914 } 9915 break; 9916 case bcmCosqStatYellowCongestionDroppedPackets: 9917 if (cosq != BCM_COS_INVALID) { 9918 return BCM_E_UNAVAIL; 9919 } 9920 BCM_IF_ERROR_RETURN 9921 (_bcm_ap_cosq_localport_resolve(unit, port, &local_port)); 9922 BCM_IF_ERROR_RETURN 9923 (soc_counter_set(unit, local_port, 9924 SOC_COUNTER_NON_DMA_PORT_DROP_PKT_YELLOW, 0, 9925 value)); 9926 break; 9927 case bcmCosqStatRedCongestionDroppedPackets: 9928 if (cosq != BCM_COS_INVALID) { 9929 return BCM_E_UNAVAIL; 9930 } 9931 BCM_IF_ERROR_RETURN 9932 (_bcm_ap_cosq_localport_resolve(unit, port, &local_port)); 9933 BCM_IF_ERROR_RETURN 9934 (soc_counter_set(unit, local_port, 9935 SOC_COUNTER_NON_DMA_PORT_DROP_PKT_RED, 0, 9936 value)); 9937 break; 9938 case bcmCosqStatGreenDiscardDroppedPackets: 9939 if (cosq != BCM_COS_INVALID) { 9940 return BCM_E_UNAVAIL; 9941 } 9942 BCM_IF_ERROR_RETURN 9943 (_bcm_ap_cosq_localport_resolve(unit, port, &local_port)); 9944 BCM_IF_ERROR_RETURN 9945 (soc_counter_set(unit, local_port, 9946 SOC_COUNTER_NON_DMA_PORT_WRED_PKT_GREEN, 0, 9947 value)); 9948 break; 9949 case bcmCosqStatYellowDiscardDroppedPackets: 9950 if (cosq != BCM_COS_INVALID) { 9951 return BCM_E_UNAVAIL; 9952 } 9953 BCM_IF_ERROR_RETURN 9954 (_bcm_ap_cosq_localport_resolve(unit, port, &local_port)); 9955 BCM_IF_ERROR_RETURN 9956 (soc_counter_set(unit, local_port, 9957 SOC_COUNTER_NON_DMA_PORT_WRED_PKT_YELLOW, 0, 9958 value)); 9959 break; 9960 case bcmCosqStatRedDiscardDroppedPackets: 9961 if (cosq != BCM_COS_INVALID) { 9962 return BCM_E_UNAVAIL; 9963 } 9964 BCM_IF_ERROR_RETURN 9965 (_bcm_ap_cosq_localport_resolve(unit, port, &local_port)); 9966 BCM_IF_ERROR_RETURN 9967 (soc_counter_set(unit, local_port, 9968 SOC_COUNTER_NON_DMA_PORT_WRED_PKT_RED, 0, value)); 9969 break; 9970 case bcmCosqStatOutPackets: 9971 if (BCM_GPORT_IS_SCHEDULER(port)) { 9972 BCM_IF_ERROR_RETURN 9973 (_bcm_ap_cosq_node_get(unit, port, 0, NULL, 9974 &local_port, NULL, &node)); 9975 BCM_IF_ERROR_RETURN( 9976 _bcm_ap_cosq_child_node_at_input(node, cosq, &node)); 9977 port = node->gport; 9978 } 9979 9980 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) { 9981 BCM_IF_ERROR_RETURN 9982 (_bcm_ap_cosq_node_get(unit, port, 0, NULL, 9983 &local_port, NULL, &node)); 9984 if (node->type == _BCM_AP_NODE_VM_UCAST) { 9985 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9986 BCM_IF_ERROR_RETURN 9987 (soc_counter_set(unit, local_port, 9988 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT_EXT, node->hw_index, 9989 value)); 9990 } else { 9991 BCM_IF_ERROR_RETURN 9992 (_bcm_ap_cosq_index_resolve 9993 (unit, port, cosq, _BCM_AP_COSQ_INDEX_STYLE_EGR_PERQ_UCAST, 9994 &local_port, &startq, NULL)); 9995 /* coverity[NEGATIVE_RETURNS: FALSE] */ 9996 BCM_IF_ERROR_RETURN 9997 (_bcm_ap_cosq_node_get(unit, port, 0, NULL, 9998 &local_port, NULL, &node)); 9999 port_info = &mmu_info->port_info[local_port]; 10000 if (node->hw_index < port_info->uc_base 10001 || node->hw_index >= port_info->uc_limit) { 10002 BCM_IF_ERROR_RETURN 10003 (soc_counter_set(unit, node->hw_index, 10004 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT, 0, 10005 value)); 10006 } else { 10007 BCM_IF_ERROR_RETURN 10008 (soc_counter_set(unit, local_port, 10009 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT_UC, startq, 10010 value)); 10011 } 10012 } 10013 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 10014 BCM_IF_ERROR_RETURN 10015 (_bcm_ap_cosq_index_resolve 10016 (unit, port, cosq, _BCM_AP_COSQ_INDEX_STYLE_EGR_PERQ_MCAST, 10017 &local_port, &startq, NULL)); 10018 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10019 BCM_IF_ERROR_RETURN 10020 (soc_counter_set(unit, local_port, 10021 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT, startq, 10022 value)); 10023 } else { 10024 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_localport_resolve(unit, port, &local_port)); 10025 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_port_has_ets(unit, local_port)); 10026 if (cosq == BCM_COS_INVALID) { 10027 from_cos = to_cos = 0; 10028 } else { 10029 from_cos = to_cos = cosq; 10030 } 10031 for (ci = from_cos; ci <= to_cos; ci++) { 10032 if (!IS_CPU_PORT(unit, local_port)) { 10033 BCM_IF_ERROR_RETURN 10034 (_bcm_ap_cosq_index_resolve 10035 (unit, port, ci, _BCM_AP_COSQ_INDEX_STYLE_EGR_PERQ_UCAST, 10036 &local_port, &startq, &numq)); 10037 for (i = 0; i < numq; i++) { 10038 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10039 BCM_IF_ERROR_RETURN 10040 (soc_counter_set(unit, local_port, 10041 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT_UC, 10042 startq + i, l)); 10043 } 10044 } 10045 BCM_IF_ERROR_RETURN 10046 (_bcm_ap_cosq_index_resolve 10047 (unit, port, ci, _BCM_AP_COSQ_INDEX_STYLE_EGR_PERQ_MCAST, 10048 &local_port, &startq, &numq)); 10049 for (i = 0; i < numq; i++) { 10050 BCM_IF_ERROR_RETURN 10051 (soc_counter_set(unit, local_port, 10052 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT, 10053 startq + i, r)); 10054 } 10055 } 10056 } 10057 break; 10058 case bcmCosqStatOutBytes: 10059 if (BCM_GPORT_IS_SCHEDULER(port)) { 10060 BCM_IF_ERROR_RETURN 10061 (_bcm_ap_cosq_node_get(unit, port, 0, NULL, 10062 &local_port, NULL, &node)); 10063 BCM_IF_ERROR_RETURN( 10064 _bcm_ap_cosq_child_node_at_input(node, cosq, &node)); 10065 port = node->gport; 10066 } 10067 10068 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) { 10069 BCM_IF_ERROR_RETURN 10070 (_bcm_ap_cosq_node_get(unit, port, 0, NULL, 10071 &local_port, NULL, &node)); 10072 if (node->type == _BCM_AP_NODE_VM_UCAST) { 10073 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10074 BCM_IF_ERROR_RETURN 10075 (soc_counter_set(unit, local_port, 10076 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE_EXT, node->hw_index, 10077 value)); 10078 } else { 10079 BCM_IF_ERROR_RETURN 10080 (_bcm_ap_cosq_index_resolve 10081 (unit, port, cosq, _BCM_AP_COSQ_INDEX_STYLE_EGR_PERQ_UCAST, 10082 &local_port, &startq, NULL)); 10083 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10084 BCM_IF_ERROR_RETURN 10085 (_bcm_ap_cosq_node_get(unit, port, 0, NULL, 10086 &local_port, NULL, &node)); 10087 port_info = &mmu_info->port_info[local_port]; 10088 if (node->hw_index < port_info->uc_base || 10089 node->hw_index >= port_info->uc_limit) { 10090 BCM_IF_ERROR_RETURN 10091 (soc_counter_set(unit, node->hw_index, 10092 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE, 0, 10093 value)); 10094 } else { 10095 BCM_IF_ERROR_RETURN 10096 (soc_counter_set(unit, local_port, 10097 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE_UC, startq, 10098 value)); 10099 } 10100 } 10101 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 10102 BCM_IF_ERROR_RETURN 10103 (_bcm_ap_cosq_index_resolve 10104 (unit, port, cosq, _BCM_AP_COSQ_INDEX_STYLE_EGR_PERQ_MCAST, 10105 &local_port, &startq, NULL)); 10106 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10107 BCM_IF_ERROR_RETURN 10108 (soc_counter_set(unit, local_port, 10109 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE, startq, 10110 value)); 10111 } else { 10112 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_localport_resolve(unit, port, &local_port)); 10113 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_port_has_ets(unit, local_port)); 10114 if (cosq == BCM_COS_INVALID) { 10115 from_cos = to_cos = 0; 10116 } else { 10117 from_cos = to_cos = cosq; 10118 } 10119 for (ci = from_cos; ci <= to_cos; ci++) { 10120 if (!IS_CPU_PORT(unit, local_port)) { 10121 BCM_IF_ERROR_RETURN 10122 (_bcm_ap_cosq_index_resolve 10123 (unit, port, ci, _BCM_AP_COSQ_INDEX_STYLE_EGR_PERQ_UCAST, 10124 &local_port, &startq, &numq)); 10125 for (i = 0; i < numq; i++) { 10126 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10127 BCM_IF_ERROR_RETURN 10128 (soc_counter_set(unit, local_port, 10129 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE_UC, 10130 startq + i, l)); 10131 } 10132 } 10133 BCM_IF_ERROR_RETURN 10134 (_bcm_ap_cosq_index_resolve 10135 (unit, port, ci, _BCM_AP_COSQ_INDEX_STYLE_EGR_PERQ_MCAST, 10136 &local_port, &startq, &numq)); 10137 for (i = 0; i < numq; i++) { 10138 BCM_IF_ERROR_RETURN 10139 (soc_counter_set(unit, local_port, 10140 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE, 10141 startq + i, r)); 10142 } 10143 } 10144 } 10145 break; 10146 case bcmCosqStatIeee8021CnCpTransmittedCnms: 10147 BCM_IF_ERROR_RETURN 10148 (_bcm_ap_cosq_index_resolve 10149 (unit, port, cosq, _BCM_AP_COSQ_INDEX_STYLE_EGR_PERQ_UCAST, 10150 &local_port, &startq, NULL)); 10151 BCM_IF_ERROR_RETURN 10152 (soc_counter_set(unit, local_port, 10153 SOC_COUNTER_NON_DMA_MMU_QCN_CNM, startq, value)); 10154 break; 10155 10156 case bcmCosqStatHighPriDroppedPackets: 10157 case bcmCosqStatOBMLossyHighPriDroppedPackets: 10158 case bcmCosqStatLowPriDroppedPackets: 10159 case bcmCosqStatOBMLossyLowPriDroppedPackets: 10160 case bcmCosqStatHighPriDroppedBytes: 10161 case bcmCosqStatOBMLossyHighPriDroppedBytes: 10162 case bcmCosqStatLowPriDroppedBytes: 10163 case bcmCosqStatOBMLossyLowPriDroppedBytes: 10164 case bcmCosqStatOBMLossless0DroppedPackets: 10165 case bcmCosqStatOBMLossless1DroppedPackets: 10166 case bcmCosqStatOBMLossless0DroppedBytes: 10167 case bcmCosqStatOBMLossless1DroppedBytes: 10168 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 10169 BCM_GPORT_IS_SCHEDULER(port) || 10170 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 10171 return BCM_E_PARAM; 10172 } 10173 BCM_IF_ERROR_RETURN( 10174 _bcm_ap_cosq_localport_resolve(unit, port, &local_port)); 10175 if ((stat == bcmCosqStatHighPriDroppedPackets) || 10176 (stat == bcmCosqStatOBMLossyHighPriDroppedPackets)) { 10177 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM_LOSSY_HI; 10178 } else if ((stat == bcmCosqStatLowPriDroppedPackets) || 10179 (stat == bcmCosqStatOBMLossyLowPriDroppedPackets)) { 10180 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM_LOSSY_LO; 10181 } else if ((stat == bcmCosqStatHighPriDroppedBytes) || 10182 (stat == bcmCosqStatOBMLossyHighPriDroppedBytes)) { 10183 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM_LOSSY_HI; 10184 } else if ((stat == bcmCosqStatLowPriDroppedBytes) || 10185 (stat == bcmCosqStatOBMLossyLowPriDroppedBytes)) { 10186 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM_LOSSY_LO; 10187 } else if (stat == bcmCosqStatOBMLossless0DroppedPackets) { 10188 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM_LOSSLESS0; 10189 } else if (stat == bcmCosqStatOBMLossless1DroppedPackets) { 10190 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM_LOSSLESS1; 10191 } else if (stat == bcmCosqStatOBMLossless0DroppedBytes) { 10192 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM_LOSSLESS0; 10193 } else { /* (stat == bcmCosqStatOBMLossless1DroppedBytes) */ 10194 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM_LOSSLESS1; 10195 } 10196 ctrl_info.instance_type = SOC_CTR_INSTANCE_TYPE_PORT; 10197 ctrl_info.instance = local_port; 10198 BCM_IF_ERROR_RETURN 10199 (soc_counter_generic_set(unit, ctr_reg, ctrl_info, 0, 10200 0, value)); 10201 10202 break; 10203 default: 10204 return BCM_E_PARAM; 10205 } 10206 10207 return BCM_E_NONE; 10208 } 10209 10210 10211 static int 10212 _bcm_ap_cosq_uc_stat_get(int unit, bcm_port_t port, uint64 *value, soc_reg_t regs1, 10213 soc_reg_t regs2, int sync_mode, int cosq) 10214 { 10215 int (*counter_get) (int , soc_port_t , soc_reg_t , int , uint64 *); 10216 bcm_port_t local_port; 10217 _bcm_ap_cosq_node_t *node; 10218 _bcm_ap_cosq_port_info_t *port_info; 10219 10220 _bcm_ap_mmu_info_t *mmu_info; 10221 mmu_info = _bcm_ap_mmu_info[unit]; 10222 counter_get = (sync_mode == 1)? soc_counter_sync_get: soc_counter_get; 10223 10224 BCM_IF_ERROR_RETURN 10225 (_bcm_ap_cosq_node_get(unit, port, 0, NULL, 10226 &local_port, NULL, &node)); 10227 port_info = &mmu_info->port_info[local_port]; 10228 if (node->hw_index < port_info->uc_base || 10229 node->hw_index >= port_info->uc_limit) { 10230 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10231 BCM_IF_ERROR_RETURN 10232 (counter_get(unit, node->hw_index, 10233 regs2, 0, 10234 value)); 10235 } else { 10236 10237 10238 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10239 10240 BCM_IF_ERROR_RETURN 10241 (counter_get(unit, local_port, 10242 regs1, cosq, 10243 value)); 10244 } 10245 return BCM_E_NONE; 10246 } 10247 10248 static int 10249 _bcm_ap_cosq_mc_stat_get(int unit, bcm_port_t port, uint64 *value, soc_reg_t regs, 10250 int sync_mode, int cosq) 10251 { 10252 int startq; 10253 int (*counter_get) (int , soc_port_t , soc_reg_t , int , uint64 *); 10254 bcm_port_t local_port; 10255 10256 counter_get = (sync_mode == 1)? soc_counter_sync_get: soc_counter_get; 10257 BCM_IF_ERROR_RETURN 10258 (_bcm_ap_cosq_index_resolve 10259 (unit, port, cosq, _BCM_AP_COSQ_INDEX_STYLE_EGR_PERQ_MCAST, 10260 &local_port, &startq, NULL)); 10261 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10262 BCM_IF_ERROR_RETURN 10263 (counter_get(unit, local_port, regs, startq, value)); 10264 return BCM_E_NONE; 10265 } 10266 10267 10268 /* get the l2 queues for the scheduler node*/ 10269 STATIC int 10270 _bcm_ap_cosq_stat_get(int unit, bcm_port_t port, _bcm_ap_cosq_node_t *node,int sync_mode, 10271 uint64 *value, soc_reg_t uc_regs, soc_reg_t mc_regs) 10272 { 10273 uint64 sum; 10274 uint64 value64; 10275 10276 COMPILER_64_ZERO(value64); 10277 COMPILER_64_ZERO(sum); 10278 /*the function will be called recursively */ 10279 if (node->level == SOC_APACHE_NODE_LVL_L2) { 10280 while (node){ 10281 port = node->gport; 10282 /* 10283 *check if the port is uc or mc and get the stats for the needed 10284 *type 10285 */ 10286 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) { 10287 if (uc_regs == -1){ 10288 return BCM_E_PARAM; 10289 } 10290 BCM_IF_ERROR_RETURN( 10291 _bcm_ap_cosq_uc_stat_get(unit, port, &value64, uc_regs, mc_regs, 10292 sync_mode, node->hw_cosq)); 10293 COMPILER_64_ADD_64(sum, value64); 10294 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 10295 if (mc_regs == -1){ 10296 return BCM_E_PARAM; 10297 } 10298 BCM_IF_ERROR_RETURN( 10299 _bcm_ap_cosq_mc_stat_get(unit, port, &value64, mc_regs, 10300 sync_mode, node->hw_cosq)); 10301 COMPILER_64_ADD_64(sum, value64); 10302 } 10303 node = node->sibling; 10304 } 10305 } 10306 else { 10307 if(node->sibling){ 10308 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_stat_get(unit, port, node->sibling, sync_mode, 10309 value, uc_regs, mc_regs)); 10310 } 10311 if(node->child){ 10312 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_stat_get(unit, port, node->child, sync_mode, 10313 value, uc_regs, mc_regs)); 10314 } 10315 } 10316 COMPILER_64_ADD_64(*value, sum); 10317 return BCM_E_NONE; 10318 10319 } 10320 10321 10322 10323 int 10324 bcm_ap_cosq_stat_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 10325 bcm_cosq_stat_t stat, int sync_mode, uint64 *value) 10326 { 10327 _bcm_ap_cosq_node_t *node; 10328 bcm_port_t local_port; 10329 int startq, numq, i, from_cos, to_cos, ci, start_hw_index, end_hw_index; 10330 uint64 sum, value64; 10331 int (*counter_get) (int , soc_port_t , soc_reg_t , int , uint64 *); 10332 soc_reg_t ctr_reg; 10333 soc_ctr_control_info_t ctrl_info; 10334 _bcm_ap_mmu_info_t *mmu_info; 10335 _bcm_ap_cosq_port_info_t *port_info; 10336 if ((value == NULL) || (cosq < -1)) { 10337 return BCM_E_PARAM; 10338 } 10339 10340 10341 mmu_info = _bcm_ap_mmu_info[unit]; 10342 10343 /* 10344 * if sync-mode is set, update the software cached counter value, 10345 * with the hardware count and then retrieve the count. 10346 * else return the software cache counter value. 10347 */ 10348 counter_get = (sync_mode == 1)? soc_counter_sync_get: soc_counter_get; 10349 10350 switch (stat) { 10351 case bcmCosqStatDroppedPackets: 10352 10353 if (BCM_GPORT_IS_SCHEDULER(port)) { 10354 BCM_IF_ERROR_RETURN 10355 (_bcm_ap_cosq_node_get(unit, port, 0, NULL, 10356 &local_port, NULL, &node)); 10357 10358 if (cosq == BCM_COS_INVALID) { 10359 node = node->child; 10360 if (node){ 10361 COMPILER_64_ZERO(value64); 10362 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_stat_get(unit, port, 10363 node, sync_mode, &value64,SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_UC, 10364 SOC_COUNTER_NON_DMA_COSQ_DROP_PKT)); 10365 *value = value64; 10366 break; 10367 } 10368 } 10369 BCM_IF_ERROR_RETURN( 10370 _bcm_ap_cosq_child_node_at_input(node, cosq, &node)); 10371 port = node->gport; 10372 } 10373 10374 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) { 10375 BCM_IF_ERROR_RETURN 10376 (_bcm_ap_cosq_node_get(unit, port, 0, NULL, 10377 NULL, NULL, &node)); 10378 if (node->type == _BCM_AP_NODE_VM_UCAST) { 10379 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10380 BCM_IF_ERROR_RETURN 10381 (counter_get(unit, -1, 10382 SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_UC, node->hw_index, 10383 value)); 10384 } else { 10385 BCM_IF_ERROR_RETURN 10386 (_bcm_ap_cosq_index_resolve 10387 (unit, port, cosq, _BCM_AP_COSQ_INDEX_STYLE_EGR_PERQ_UCAST, 10388 &local_port, &startq, NULL)); 10389 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10390 10391 BCM_IF_ERROR_RETURN 10392 (_bcm_ap_cosq_node_get(unit, port, 0, NULL, 10393 &local_port, NULL, &node)); 10394 port_info = &mmu_info->port_info[local_port]; 10395 if (node->hw_index < port_info->uc_base || 10396 node->hw_index >= port_info->uc_limit) 10397 { 10398 BCM_IF_ERROR_RETURN 10399 (counter_get(unit, node->hw_index, 10400 SOC_COUNTER_NON_DMA_COSQ_DROP_PKT, 0, 10401 value)); 10402 } else { 10403 BCM_IF_ERROR_RETURN 10404 (counter_get(unit, local_port, 10405 SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_UC, startq, 10406 value)); 10407 } 10408 } 10409 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 10410 BCM_IF_ERROR_RETURN 10411 (_bcm_ap_cosq_index_resolve 10412 (unit, port, cosq, _BCM_AP_COSQ_INDEX_STYLE_EGR_PERQ_MCAST, 10413 &local_port, &startq, NULL)); 10414 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10415 BCM_IF_ERROR_RETURN 10416 (counter_get(unit, local_port, 10417 SOC_COUNTER_NON_DMA_COSQ_DROP_PKT, startq, value)); 10418 } else { 10419 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_localport_resolve(unit, port, &local_port)); 10420 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_port_has_ets(unit, local_port)); 10421 COMPILER_64_ZERO(sum); 10422 if (cosq == BCM_COS_INVALID) { 10423 from_cos = 0; 10424 to_cos = (IS_CPU_PORT(unit, local_port)) ? 10425 NUM_CPU_COSQ(unit) - 1 : _AP_NUM_COS(unit) - 1; 10426 } else { 10427 from_cos = to_cos = cosq; 10428 } 10429 for (ci = from_cos; ci <= to_cos; ci++) { 10430 if (!IS_CPU_PORT(unit, local_port)) { 10431 BCM_IF_ERROR_RETURN 10432 (_bcm_ap_cosq_index_resolve 10433 (unit, port, ci, _BCM_AP_COSQ_INDEX_STYLE_EGR_PERQ_UCAST, 10434 &local_port, &startq, &numq)); 10435 for (i = 0; i < numq; i++) { 10436 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10437 BCM_IF_ERROR_RETURN 10438 (counter_get(unit, local_port, 10439 SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_UC, 10440 startq + i, &value64)); 10441 COMPILER_64_ADD_64(sum, value64); 10442 } 10443 } 10444 BCM_IF_ERROR_RETURN 10445 (_bcm_ap_cosq_index_resolve 10446 (unit, port, ci, _BCM_AP_COSQ_INDEX_STYLE_EGR_PERQ_MCAST, 10447 &local_port, &startq, &numq)); 10448 10449 for (i = 0; i < numq; i++) { 10450 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10451 BCM_IF_ERROR_RETURN 10452 (counter_get(unit, local_port, 10453 SOC_COUNTER_NON_DMA_COSQ_DROP_PKT, 10454 startq + i, &value64)); 10455 COMPILER_64_ADD_64(sum, value64); 10456 } 10457 } 10458 *value = sum; 10459 } 10460 break; 10461 case bcmCosqStatDroppedBytes: 10462 if (BCM_GPORT_IS_SCHEDULER(port)) { 10463 BCM_IF_ERROR_RETURN 10464 (_bcm_ap_cosq_node_get(unit, port, 0, NULL, 10465 &local_port, NULL, &node)); 10466 if (cosq == BCM_COS_INVALID) { 10467 node = node->child; 10468 if (node){ 10469 COMPILER_64_ZERO(value64); 10470 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_stat_get(unit, port, 10471 node, sync_mode, &value64,SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE_UC, 10472 SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE)); 10473 *value = value64; 10474 break; 10475 } 10476 } 10477 10478 BCM_IF_ERROR_RETURN( 10479 _bcm_ap_cosq_child_node_at_input(node, cosq, &node)); 10480 port = node->gport; 10481 } 10482 10483 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) { 10484 BCM_IF_ERROR_RETURN 10485 (_bcm_ap_cosq_node_get(unit, port, 0, NULL, 10486 NULL, NULL, &node)); 10487 if (node->type == _BCM_AP_NODE_VM_UCAST) { 10488 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10489 BCM_IF_ERROR_RETURN 10490 (counter_get(unit, -1, 10491 SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE_UC, node->hw_index, 10492 value)); 10493 } else { 10494 BCM_IF_ERROR_RETURN 10495 (_bcm_ap_cosq_index_resolve 10496 (unit, port, cosq, _BCM_AP_COSQ_INDEX_STYLE_EGR_PERQ_UCAST, 10497 &local_port, &startq, NULL)); 10498 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10499 BCM_IF_ERROR_RETURN 10500 (_bcm_ap_cosq_node_get(unit, port, 0, NULL, 10501 &local_port, NULL, &node)); 10502 port_info = &mmu_info->port_info[local_port]; 10503 if (node->hw_index < port_info->uc_base || 10504 node->hw_index >= port_info->uc_limit) { 10505 BCM_IF_ERROR_RETURN 10506 (counter_get(unit, node->hw_index, 10507 SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE, 0, 10508 value)); 10509 } else { 10510 BCM_IF_ERROR_RETURN 10511 (counter_get(unit, local_port, 10512 SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE_UC, startq, 10513 value)); 10514 } 10515 } 10516 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 10517 BCM_IF_ERROR_RETURN 10518 (_bcm_ap_cosq_index_resolve 10519 (unit, port, cosq, _BCM_AP_COSQ_INDEX_STYLE_EGR_PERQ_MCAST, 10520 &local_port, &startq, NULL)); 10521 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10522 BCM_IF_ERROR_RETURN 10523 (counter_get(unit, local_port, 10524 SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE, startq, value)); 10525 } else { 10526 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_localport_resolve(unit, port, &local_port)); 10527 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_port_has_ets(unit, local_port)); 10528 COMPILER_64_ZERO(sum); 10529 if (cosq == BCM_COS_INVALID) { 10530 from_cos = 0; 10531 to_cos = (IS_CPU_PORT(unit, local_port)) ? 10532 NUM_CPU_COSQ(unit) - 1 : _AP_NUM_COS(unit) - 1; 10533 } else { 10534 from_cos = to_cos = cosq; 10535 } 10536 for (ci = from_cos; ci <= to_cos; ci++) { 10537 if (!IS_CPU_PORT(unit, local_port)) { 10538 BCM_IF_ERROR_RETURN 10539 (_bcm_ap_cosq_index_resolve 10540 (unit, port, ci, _BCM_AP_COSQ_INDEX_STYLE_EGR_PERQ_UCAST, 10541 &local_port, &startq, &numq)); 10542 for (i = 0; i < numq; i++) { 10543 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10544 BCM_IF_ERROR_RETURN 10545 (counter_get(unit, local_port, 10546 SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE_UC, 10547 startq + i, &value64)); 10548 COMPILER_64_ADD_64(sum, value64); 10549 } 10550 } 10551 BCM_IF_ERROR_RETURN 10552 (_bcm_ap_cosq_index_resolve 10553 (unit, port, ci, _BCM_AP_COSQ_INDEX_STYLE_EGR_PERQ_MCAST, 10554 &local_port, &startq, &numq)); 10555 for (i = 0; i < numq; i++) { 10556 BCM_IF_ERROR_RETURN 10557 (counter_get(unit, local_port, 10558 SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE, 10559 startq + i, &value64)); 10560 COMPILER_64_ADD_64(sum, value64); 10561 } 10562 } 10563 *value = sum; 10564 } 10565 break; 10566 case bcmCosqStatYellowCongestionDroppedPackets: 10567 if (cosq != BCM_COS_INVALID) { 10568 return BCM_E_UNAVAIL; 10569 } 10570 BCM_IF_ERROR_RETURN 10571 (_bcm_ap_cosq_localport_resolve(unit, port, &local_port)); 10572 BCM_IF_ERROR_RETURN 10573 (counter_get(unit, local_port, 10574 SOC_COUNTER_NON_DMA_PORT_DROP_PKT_YELLOW, 0, 10575 value)); 10576 break; 10577 case bcmCosqStatRedCongestionDroppedPackets: 10578 if (cosq != BCM_COS_INVALID) { 10579 return BCM_E_UNAVAIL; 10580 } 10581 BCM_IF_ERROR_RETURN 10582 (_bcm_ap_cosq_localport_resolve(unit, port, &local_port)); 10583 BCM_IF_ERROR_RETURN 10584 (counter_get(unit, local_port, 10585 SOC_COUNTER_NON_DMA_PORT_DROP_PKT_RED, 0, 10586 value)); 10587 break; 10588 case bcmCosqStatGreenDiscardDroppedPackets: 10589 if (cosq != BCM_COS_INVALID) { 10590 return BCM_E_UNAVAIL; 10591 } 10592 BCM_IF_ERROR_RETURN 10593 (_bcm_ap_cosq_localport_resolve(unit, port, &local_port)); 10594 BCM_IF_ERROR_RETURN 10595 (counter_get(unit, local_port, 10596 SOC_COUNTER_NON_DMA_PORT_WRED_PKT_GREEN, 0, 10597 value)); 10598 break; 10599 case bcmCosqStatYellowDiscardDroppedPackets: 10600 if (cosq != BCM_COS_INVALID) { 10601 return BCM_E_UNAVAIL; 10602 } 10603 BCM_IF_ERROR_RETURN 10604 (_bcm_ap_cosq_localport_resolve(unit, port, &local_port)); 10605 BCM_IF_ERROR_RETURN 10606 (counter_get(unit, local_port, 10607 SOC_COUNTER_NON_DMA_PORT_WRED_PKT_YELLOW, 0, 10608 value)); 10609 break; 10610 case bcmCosqStatRedDiscardDroppedPackets: 10611 if (cosq != BCM_COS_INVALID) { 10612 return BCM_E_UNAVAIL; 10613 } 10614 BCM_IF_ERROR_RETURN 10615 (_bcm_ap_cosq_localport_resolve(unit, port, &local_port)); 10616 BCM_IF_ERROR_RETURN 10617 (counter_get(unit, local_port, 10618 SOC_COUNTER_NON_DMA_PORT_WRED_PKT_RED, 0, value)); 10619 break; 10620 case bcmCosqStatOutPackets: 10621 if (BCM_GPORT_IS_SCHEDULER(port)) { 10622 BCM_IF_ERROR_RETURN 10623 (_bcm_ap_cosq_node_get(unit, port, 0, NULL, 10624 &local_port, NULL, &node)); 10625 if (cosq == BCM_COS_INVALID) { 10626 node = node->child; 10627 if (node){ 10628 COMPILER_64_ZERO(value64); 10629 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_stat_get(unit, port, 10630 node, sync_mode, &value64,SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT_UC, 10631 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT)); 10632 *value = value64; 10633 break; 10634 } 10635 } 10636 10637 10638 BCM_IF_ERROR_RETURN( 10639 _bcm_ap_cosq_child_node_at_input(node, cosq, &node)); 10640 port = node->gport; 10641 } 10642 10643 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) { 10644 BCM_IF_ERROR_RETURN 10645 (_bcm_ap_cosq_node_get(unit, port, 0, NULL, 10646 &local_port, NULL, &node)); 10647 port_info = &mmu_info->port_info[local_port]; 10648 if (node->hw_index < port_info->uc_base || 10649 node->hw_index >= port_info->uc_limit) { 10650 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10651 BCM_IF_ERROR_RETURN 10652 (counter_get(unit, node->hw_index, 10653 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT, 0, 10654 value)); 10655 } else if (node->type == _BCM_AP_NODE_VM_UCAST) { 10656 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10657 BCM_IF_ERROR_RETURN 10658 (counter_get(unit, local_port, 10659 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT_EXT, node->hw_index, 10660 value)); 10661 10662 } else { 10663 (_bcm_ap_cosq_index_resolve 10664 (unit, port, cosq, _BCM_AP_COSQ_INDEX_STYLE_EGR_PERQ_UCAST, 10665 &local_port, &startq, NULL)); 10666 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10667 BCM_IF_ERROR_RETURN 10668 (counter_get(unit, local_port, 10669 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT_UC, startq, 10670 value)); 10671 } 10672 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 10673 BCM_IF_ERROR_RETURN 10674 (_bcm_ap_cosq_index_resolve 10675 (unit, port, cosq, _BCM_AP_COSQ_INDEX_STYLE_EGR_PERQ_MCAST, 10676 &local_port, &startq, NULL)); 10677 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10678 BCM_IF_ERROR_RETURN 10679 (counter_get(unit, local_port, 10680 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT, startq, 10681 value)); 10682 } else { 10683 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_localport_resolve(unit, port, &local_port)); 10684 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_port_has_ets(unit, local_port)); 10685 COMPILER_64_ZERO(sum); 10686 if (cosq == BCM_COS_INVALID) { 10687 from_cos = 0; 10688 to_cos = (IS_CPU_PORT(unit, local_port)) ? 10689 NUM_CPU_COSQ(unit) - 1 : _AP_NUM_COS(unit) - 1; 10690 } else { 10691 from_cos = to_cos = cosq; 10692 } 10693 10694 for (ci = from_cos; ci <= to_cos; ci++) { 10695 if (!IS_CPU_PORT(unit, local_port)) { 10696 BCM_IF_ERROR_RETURN 10697 (_bcm_ap_cosq_index_resolve 10698 (unit, port, ci, _BCM_AP_COSQ_INDEX_STYLE_EGR_PERQ_UCAST, 10699 &local_port, &startq, &numq)); 10700 for (i = 0; i < numq; i++) { 10701 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10702 BCM_IF_ERROR_RETURN 10703 (counter_get(unit, local_port, 10704 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT_UC, 10705 startq + i, &value64)); 10706 COMPILER_64_ADD_64(sum, value64); 10707 } 10708 } 10709 BCM_IF_ERROR_RETURN 10710 (_bcm_ap_cosq_index_resolve 10711 (unit, port, ci, _BCM_AP_COSQ_INDEX_STYLE_EGR_PERQ_MCAST, 10712 &local_port, &startq, &numq)); 10713 for (i = 0; i < numq; i++) { 10714 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10715 BCM_IF_ERROR_RETURN 10716 (counter_get(unit, local_port, 10717 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT, 10718 startq + i, &value64)); 10719 COMPILER_64_ADD_64(sum, value64); 10720 } 10721 } 10722 *value = sum; 10723 } 10724 break; 10725 case bcmCosqStatOutBytes: 10726 if (BCM_GPORT_IS_SCHEDULER(port)) { 10727 BCM_IF_ERROR_RETURN 10728 (_bcm_ap_cosq_node_get(unit, port, 0, NULL, 10729 &local_port, NULL, &node)); 10730 10731 if (cosq == BCM_COS_INVALID) { 10732 node = node->child; 10733 if (node){ 10734 COMPILER_64_ZERO(value64); 10735 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_stat_get(unit, port, 10736 node, sync_mode, &value64,SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE_UC, 10737 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE)); 10738 *value = value64; 10739 break; 10740 } 10741 } 10742 10743 BCM_IF_ERROR_RETURN( 10744 _bcm_ap_cosq_child_node_at_input(node, cosq, &node)); 10745 port = node->gport; 10746 } 10747 10748 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) { 10749 BCM_IF_ERROR_RETURN 10750 (_bcm_ap_cosq_node_get(unit, port, 0, NULL , 10751 &local_port, NULL, &node)); 10752 port_info = &mmu_info->port_info[local_port]; 10753 if (node->hw_index < port_info->uc_base || 10754 node->hw_index >= port_info->uc_limit) { 10755 BCM_IF_ERROR_RETURN 10756 (counter_get(unit, node->hw_index, 10757 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE, 0, 10758 value)); 10759 } else if (node->type == _BCM_AP_NODE_VM_UCAST) { 10760 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10761 BCM_IF_ERROR_RETURN 10762 (counter_get(unit, local_port, 10763 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE_EXT, node->hw_index, 10764 value)); 10765 10766 } else { 10767 10768 BCM_IF_ERROR_RETURN 10769 (_bcm_ap_cosq_index_resolve 10770 (unit, port, cosq, _BCM_AP_COSQ_INDEX_STYLE_EGR_PERQ_UCAST, 10771 &local_port, &startq, NULL)); 10772 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10773 BCM_IF_ERROR_RETURN 10774 (counter_get(unit, local_port, 10775 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE_UC, startq, 10776 value)); 10777 } 10778 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 10779 BCM_IF_ERROR_RETURN 10780 (_bcm_ap_cosq_index_resolve 10781 (unit, port, cosq, _BCM_AP_COSQ_INDEX_STYLE_EGR_PERQ_MCAST, 10782 &local_port, &startq, NULL)); 10783 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10784 BCM_IF_ERROR_RETURN 10785 (counter_get(unit, local_port, 10786 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE, startq, 10787 value)); 10788 } else { 10789 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_localport_resolve(unit, port, &local_port)); 10790 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_port_has_ets(unit, local_port)); 10791 COMPILER_64_ZERO(sum); 10792 if (cosq == BCM_COS_INVALID) { 10793 from_cos = 0; 10794 to_cos = (IS_CPU_PORT(unit, local_port)) ? 10795 NUM_CPU_COSQ(unit) - 1 : _AP_NUM_COS(unit) - 1; 10796 } else { 10797 from_cos = to_cos = cosq; 10798 } 10799 10800 for (ci = from_cos; ci <= to_cos; ci++) { 10801 if (!IS_CPU_PORT(unit, local_port)) { 10802 BCM_IF_ERROR_RETURN 10803 (_bcm_ap_cosq_index_resolve 10804 (unit, port, ci, _BCM_AP_COSQ_INDEX_STYLE_EGR_PERQ_UCAST, 10805 &local_port, &startq, &numq)); 10806 for (i = 0; i < numq; i++) { 10807 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10808 BCM_IF_ERROR_RETURN 10809 (counter_get(unit, local_port, 10810 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE_UC, 10811 startq + i, &value64)); 10812 COMPILER_64_ADD_64(sum, value64); 10813 } 10814 } 10815 BCM_IF_ERROR_RETURN 10816 (_bcm_ap_cosq_index_resolve 10817 (unit, port, ci, _BCM_AP_COSQ_INDEX_STYLE_EGR_PERQ_MCAST, 10818 &local_port, &startq, &numq)); 10819 for (i = 0; i < numq; i++) { 10820 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10821 BCM_IF_ERROR_RETURN 10822 (counter_get(unit, local_port, 10823 SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE, 10824 startq + i, &value64)); 10825 COMPILER_64_ADD_64(sum, value64); 10826 } 10827 } 10828 *value = sum; 10829 } 10830 break; 10831 case bcmCosqStatIeee8021CnCpTransmittedCnms: 10832 BCM_IF_ERROR_RETURN 10833 (_bcm_ap_cosq_index_resolve 10834 (unit, port, cosq, _BCM_AP_COSQ_INDEX_STYLE_EGR_PERQ_UCAST, 10835 &local_port, &startq, NULL)); 10836 BCM_IF_ERROR_RETURN 10837 (counter_get(unit, local_port, 10838 SOC_COUNTER_NON_DMA_MMU_QCN_CNM, startq, value)); 10839 break; 10840 case bcmCosqStatIngressPortPoolSharedBytesPeak: 10841 10842 COMPILER_64_ZERO(sum); 10843 BCM_IF_ERROR_RETURN 10844 (_bcm_ap_cosq_ingress_sp_get(unit, port, cosq, 10845 &start_hw_index, &end_hw_index)); 10846 10847 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_localport_resolve(unit, port, &local_port)); 10848 for (i = start_hw_index; i <= end_hw_index; i++) { 10849 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10850 BCM_IF_ERROR_RETURN 10851 (counter_get(unit, local_port, 10852 SOC_COUNTER_NON_DMA_POOL_PEAK, 10853 i, &value64)); 10854 COMPILER_64_ADD_64(sum, value64); 10855 } 10856 10857 COMPILER_64_UMUL_32(sum, _BCM_AP_BYTES_PER_CELL); 10858 *value = sum; 10859 break; 10860 case bcmCosqStatIngressPortPoolSharedBytesCurrent: 10861 10862 BCM_IF_ERROR_RETURN 10863 (_bcm_ap_cosq_ingress_sp_get(unit, port, cosq, 10864 &start_hw_index, &end_hw_index)); 10865 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_localport_resolve(unit, port, &local_port)); 10866 10867 COMPILER_64_ZERO(sum); 10868 for (i = start_hw_index; i <= end_hw_index; i++) { 10869 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10870 BCM_IF_ERROR_RETURN 10871 (counter_get(unit, local_port, 10872 SOC_COUNTER_NON_DMA_POOL_CURRENT, 10873 i, &value64)); 10874 COMPILER_64_ADD_64(sum, value64); 10875 } 10876 10877 COMPILER_64_UMUL_32(sum, _BCM_AP_BYTES_PER_CELL); 10878 *value = sum; 10879 break; 10880 10881 case bcmCosqStatIngressPortPGMinBytesPeak: 10882 10883 BCM_IF_ERROR_RETURN 10884 (_bcm_ap_cosq_ingress_pg_get(unit, port, cosq, 10885 &start_hw_index, &end_hw_index)); 10886 COMPILER_64_ZERO(sum); 10887 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_localport_resolve(unit, port, &local_port)); 10888 10889 for (i = start_hw_index; i <= end_hw_index; i++) { 10890 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10891 BCM_IF_ERROR_RETURN 10892 (counter_get(unit, local_port, 10893 SOC_COUNTER_NON_DMA_PG_MIN_PEAK, 10894 i, &value64)); 10895 COMPILER_64_ADD_64(sum, value64); 10896 } 10897 10898 COMPILER_64_UMUL_32(sum, _BCM_AP_BYTES_PER_CELL); 10899 *value = sum; 10900 break; 10901 case bcmCosqStatIngressPortPGMinBytesCurrent: 10902 10903 BCM_IF_ERROR_RETURN 10904 (_bcm_ap_cosq_ingress_pg_get(unit, port, cosq, 10905 &start_hw_index, &end_hw_index)); 10906 COMPILER_64_ZERO(sum); 10907 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_localport_resolve(unit, port, &local_port)); 10908 10909 for (i = start_hw_index; i <= end_hw_index; i++) { 10910 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10911 BCM_IF_ERROR_RETURN 10912 (counter_get(unit, local_port, 10913 SOC_COUNTER_NON_DMA_PG_MIN_CURRENT, 10914 i, &value64)); 10915 COMPILER_64_ADD_64(sum, value64); 10916 } 10917 10918 COMPILER_64_UMUL_32(sum, _BCM_AP_BYTES_PER_CELL); 10919 *value = sum; 10920 break; 10921 10922 case bcmCosqStatIngressPortPGSharedBytesPeak: 10923 10924 BCM_IF_ERROR_RETURN 10925 (_bcm_ap_cosq_ingress_pg_get(unit, port, cosq, 10926 &start_hw_index, &end_hw_index)); 10927 COMPILER_64_ZERO(sum); 10928 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_localport_resolve(unit, port, &local_port)); 10929 10930 for (i = start_hw_index; i <= end_hw_index; i++) { 10931 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10932 BCM_IF_ERROR_RETURN 10933 (counter_get(unit, local_port, 10934 SOC_COUNTER_NON_DMA_PG_SHARED_PEAK, 10935 i, &value64)); 10936 COMPILER_64_ADD_64(sum, value64); 10937 } 10938 10939 COMPILER_64_UMUL_32(sum, _BCM_AP_BYTES_PER_CELL); 10940 *value = sum; 10941 break; 10942 10943 case bcmCosqStatIngressPortPGSharedBytesCurrent: 10944 10945 BCM_IF_ERROR_RETURN 10946 (_bcm_ap_cosq_ingress_pg_get(unit, port, cosq, 10947 &start_hw_index, &end_hw_index)); 10948 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_localport_resolve(unit, port, &local_port)); 10949 COMPILER_64_ZERO(sum); 10950 10951 for (i = start_hw_index; i <= end_hw_index; i++) { 10952 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10953 BCM_IF_ERROR_RETURN 10954 (counter_get(unit, local_port, 10955 SOC_COUNTER_NON_DMA_PG_SHARED_CURRENT, 10956 i, &value64)); 10957 COMPILER_64_ADD_64(sum, value64); 10958 } 10959 COMPILER_64_UMUL_32(sum, _BCM_AP_BYTES_PER_CELL); 10960 *value = sum; 10961 10962 break; 10963 10964 case bcmCosqStatIngressPortPGHeadroomBytesPeak: 10965 10966 BCM_IF_ERROR_RETURN 10967 (_bcm_ap_cosq_ingress_pg_get(unit, port, cosq, 10968 &start_hw_index, &end_hw_index)); 10969 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_localport_resolve(unit, port, &local_port)); 10970 COMPILER_64_ZERO(sum); 10971 10972 for (i = start_hw_index; i <= end_hw_index; i++) { 10973 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10974 BCM_IF_ERROR_RETURN 10975 (counter_get(unit, local_port, 10976 SOC_COUNTER_NON_DMA_PG_HDRM_PEAK, 10977 i, &value64)); 10978 COMPILER_64_ADD_64(sum, value64); 10979 } 10980 COMPILER_64_UMUL_32(sum, _BCM_AP_BYTES_PER_CELL); 10981 *value = sum; 10982 10983 break; 10984 10985 case bcmCosqStatIngressPortPGHeadroomBytesCurrent: 10986 10987 BCM_IF_ERROR_RETURN 10988 (_bcm_ap_cosq_ingress_pg_get(unit, port, cosq, 10989 &start_hw_index, &end_hw_index)); 10990 10991 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_localport_resolve(unit, port, &local_port)); 10992 COMPILER_64_ZERO(sum); 10993 for (i = start_hw_index; i <= end_hw_index; i++) { 10994 /* coverity[NEGATIVE_RETURNS: FALSE] */ 10995 BCM_IF_ERROR_RETURN 10996 (counter_get(unit, local_port, 10997 SOC_COUNTER_NON_DMA_PG_HDRM_CURRENT, 10998 i, &value64)); 10999 COMPILER_64_ADD_64(sum, value64); 11000 } 11001 COMPILER_64_UMUL_32(sum, _BCM_AP_BYTES_PER_CELL); 11002 *value = sum; 11003 11004 break; 11005 11006 case bcmCosqStatEgressMCQueueBytesPeak: 11007 if (BCM_GPORT_IS_SCHEDULER(port)) { 11008 if (cosq == BCM_COS_INVALID ) 11009 { 11010 return BCM_E_PARAM; 11011 } 11012 BCM_IF_ERROR_RETURN 11013 (_bcm_ap_cosq_node_get(unit, port, 0, NULL, 11014 &local_port, NULL, &node)); 11015 11016 BCM_IF_ERROR_RETURN( 11017 _bcm_ap_cosq_child_node_at_input(node, cosq, &node)); 11018 if (node->level != SOC_APACHE_NODE_LVL_L2) { 11019 return BCM_E_PARAM; 11020 } 11021 port = node->gport; 11022 } 11023 11024 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) { 11025 return BCM_E_PARAM; 11026 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 11027 BCM_IF_ERROR_RETURN 11028 (_bcm_ap_cosq_index_resolve 11029 (unit, port, 0, _BCM_AP_COSQ_INDEX_STYLE_EGR_PERQ_MCAST, 11030 &local_port, &startq, NULL)); 11031 /* coverity[NEGATIVE_RETURNS: FALSE] */ 11032 BCM_IF_ERROR_RETURN 11033 (counter_get(unit, local_port, 11034 SOC_COUNTER_NON_DMA_QUEUE_PEAK, startq, 11035 value)); 11036 COMPILER_64_UMUL_32(*value, _BCM_AP_BYTES_PER_CELL); 11037 } else { 11038 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_localport_resolve(unit, port, &local_port)); 11039 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_port_has_ets(unit, port)); 11040 COMPILER_64_ZERO(sum); 11041 if (cosq == BCM_COS_INVALID) { 11042 from_cos = to_cos = 0; 11043 } else { 11044 from_cos = to_cos = cosq; 11045 } 11046 11047 for (ci = from_cos; ci <= to_cos; ci++) { 11048 BCM_IF_ERROR_RETURN 11049 (_bcm_ap_cosq_index_resolve 11050 (unit, port, ci, _BCM_AP_COSQ_INDEX_STYLE_EGR_PERQ_MCAST, 11051 &local_port, &startq, &numq)); 11052 for (i = 0; i < numq; i++) { 11053 /* coverity[NEGATIVE_RETURNS: FALSE] */ 11054 BCM_IF_ERROR_RETURN 11055 (counter_get(unit, local_port, 11056 SOC_COUNTER_NON_DMA_QUEUE_PEAK, 11057 startq + i, &value64)); 11058 COMPILER_64_ADD_64(sum, value64); 11059 } 11060 } 11061 COMPILER_64_UMUL_32(sum, _BCM_AP_BYTES_PER_CELL); 11062 *value = sum; 11063 } 11064 break; 11065 case bcmCosqStatEgressMCQueueBytesCurrent: 11066 if (BCM_GPORT_IS_SCHEDULER(port)) { 11067 BCM_IF_ERROR_RETURN 11068 (_bcm_ap_cosq_node_get(unit, port, 0, NULL, 11069 &local_port, NULL, &node)); 11070 if (cosq == BCM_COS_INVALID) { 11071 return BCM_E_PARAM; 11072 } 11073 BCM_IF_ERROR_RETURN( 11074 _bcm_ap_cosq_child_node_at_input(node, cosq, &node)); 11075 if (node->level != SOC_APACHE_NODE_LVL_L2) { 11076 return BCM_E_PARAM; 11077 } 11078 port = node->gport; 11079 } 11080 11081 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) { 11082 return BCM_E_PARAM; 11083 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 11084 BCM_IF_ERROR_RETURN 11085 (_bcm_ap_cosq_index_resolve 11086 (unit, port, 0, _BCM_AP_COSQ_INDEX_STYLE_EGR_PERQ_MCAST, 11087 &local_port, &startq, NULL)); 11088 /* coverity[NEGATIVE_RETURNS: FALSE] */ 11089 BCM_IF_ERROR_RETURN 11090 (counter_get(unit, local_port, 11091 SOC_COUNTER_NON_DMA_QUEUE_CURRENT, startq, 11092 value)); 11093 COMPILER_64_UMUL_32(*value, _BCM_AP_BYTES_PER_CELL); 11094 } else { 11095 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_localport_resolve(unit, port, &local_port)); 11096 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_port_has_ets(unit, port)); 11097 COMPILER_64_ZERO(sum); 11098 if (cosq == BCM_COS_INVALID) { 11099 from_cos = 0; 11100 to_cos = (IS_CPU_PORT(unit, local_port)) ? 11101 NUM_CPU_COSQ(unit) - 1 : _AP_NUM_COS(unit) - 1; 11102 } else { 11103 from_cos = to_cos = cosq; 11104 } 11105 11106 for (ci = from_cos; ci <= to_cos; ci++) { 11107 BCM_IF_ERROR_RETURN 11108 (_bcm_ap_cosq_index_resolve 11109 (unit, port, ci, _BCM_AP_COSQ_INDEX_STYLE_EGR_PERQ_MCAST, 11110 &local_port, &startq, &numq)); 11111 for (i = 0; i < numq; i++) { 11112 /* coverity[NEGATIVE_RETURNS: FALSE] */ 11113 BCM_IF_ERROR_RETURN 11114 (counter_get(unit, local_port, 11115 SOC_COUNTER_NON_DMA_QUEUE_CURRENT, 11116 startq + i, &value64)); 11117 COMPILER_64_ADD_64(sum, value64); 11118 } 11119 } 11120 COMPILER_64_UMUL_32(sum, _BCM_AP_BYTES_PER_CELL); 11121 *value = sum; 11122 } 11123 break; 11124 11125 case bcmCosqStatEgressUCQueueBytesPeak: 11126 if (BCM_GPORT_IS_SCHEDULER(port)) { 11127 BCM_IF_ERROR_RETURN 11128 (_bcm_ap_cosq_node_get(unit, port, 0, NULL, 11129 &local_port, NULL, &node)); 11130 if (cosq == BCM_COS_INVALID) { 11131 return BCM_E_PARAM; 11132 } 11133 BCM_IF_ERROR_RETURN( 11134 _bcm_ap_cosq_child_node_at_input(node, cosq, &node)); 11135 if (node->level != SOC_APACHE_NODE_LVL_L2) { 11136 return BCM_E_PARAM; 11137 } 11138 port = node->gport; 11139 } 11140 11141 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) { 11142 BCM_IF_ERROR_RETURN 11143 (_bcm_ap_cosq_index_resolve 11144 (unit, port, 0, _BCM_AP_COSQ_INDEX_STYLE_EGR_PERQ_UCAST, 11145 &local_port, &startq, NULL)); 11146 /* coverity[NEGATIVE_RETURNS: FALSE] */ 11147 BCM_IF_ERROR_RETURN 11148 (counter_get(unit, local_port, 11149 SOC_COUNTER_NON_DMA_UC_QUEUE_PEAK, startq, 11150 value)); 11151 COMPILER_64_UMUL_32(*value, _BCM_AP_BYTES_PER_CELL); 11152 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 11153 return BCM_E_PARAM; 11154 } else { 11155 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_localport_resolve(unit, port, &local_port)); 11156 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_port_has_ets(unit, port)); 11157 COMPILER_64_ZERO(sum); 11158 if (cosq == BCM_COS_INVALID) { 11159 from_cos = to_cos = 0; 11160 } else { 11161 from_cos = to_cos = cosq; 11162 } 11163 11164 if (IS_CPU_PORT(unit, local_port)) { 11165 return BCM_E_PARAM; 11166 } 11167 for (ci = from_cos; ci <= to_cos; ci++) { 11168 BCM_IF_ERROR_RETURN 11169 (_bcm_ap_cosq_index_resolve 11170 (unit, port, ci, _BCM_AP_COSQ_INDEX_STYLE_EGR_PERQ_UCAST, 11171 &local_port, &startq, &numq)); 11172 for (i = 0; i < numq; i++) { 11173 /* coverity[NEGATIVE_RETURNS: FALSE] */ 11174 BCM_IF_ERROR_RETURN 11175 (counter_get(unit, local_port, 11176 SOC_COUNTER_NON_DMA_UC_QUEUE_PEAK, 11177 startq + i, &value64)); 11178 COMPILER_64_ADD_64(sum, value64); 11179 } 11180 } 11181 COMPILER_64_UMUL_32(sum, _BCM_AP_BYTES_PER_CELL); 11182 *value = sum; 11183 } 11184 break; 11185 case bcmCosqStatEgressUCQueueBytesCurrent: 11186 if (BCM_GPORT_IS_SCHEDULER(port)) { 11187 BCM_IF_ERROR_RETURN 11188 (_bcm_ap_cosq_node_get(unit, port, 0, NULL, 11189 &local_port, NULL, &node)); 11190 11191 if (cosq == BCM_COS_INVALID) { 11192 return BCM_E_PARAM; 11193 } 11194 BCM_IF_ERROR_RETURN( 11195 _bcm_ap_cosq_child_node_at_input(node, cosq, &node)); 11196 if (node->level != SOC_APACHE_NODE_LVL_L2) { 11197 return BCM_E_PARAM; 11198 } 11199 port = node->gport; 11200 } 11201 11202 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) { 11203 BCM_IF_ERROR_RETURN 11204 (_bcm_ap_cosq_index_resolve 11205 (unit, port, 0, _BCM_AP_COSQ_INDEX_STYLE_EGR_PERQ_UCAST, 11206 &local_port, &startq, NULL)); 11207 /* coverity[NEGATIVE_RETURNS: FALSE] */ 11208 BCM_IF_ERROR_RETURN 11209 (counter_get(unit, local_port, 11210 SOC_COUNTER_NON_DMA_UC_QUEUE_CURRENT, startq, 11211 value)); 11212 COMPILER_64_UMUL_32(*value, _BCM_AP_BYTES_PER_CELL); 11213 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 11214 return BCM_E_PARAM; 11215 } else { 11216 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_localport_resolve(unit, port, &local_port)); 11217 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_port_has_ets(unit, port)); 11218 11219 if (IS_CPU_PORT(unit, local_port)) { 11220 return BCM_E_PARAM; 11221 } 11222 COMPILER_64_ZERO(sum); 11223 if (cosq == BCM_COS_INVALID) { 11224 from_cos = 0; 11225 to_cos = (IS_CPU_PORT(unit, local_port)) ? 11226 NUM_CPU_COSQ(unit) - 1 : _AP_NUM_COS(unit) - 1; 11227 } else { 11228 from_cos = to_cos = cosq; 11229 } 11230 11231 for (ci = from_cos; ci <= to_cos; ci++) { 11232 BCM_IF_ERROR_RETURN 11233 (_bcm_ap_cosq_index_resolve 11234 (unit, port, ci, _BCM_AP_COSQ_INDEX_STYLE_EGR_PERQ_UCAST, 11235 &local_port, &startq, &numq)); 11236 for (i = 0; i < numq; i++) { 11237 /* coverity[NEGATIVE_RETURNS: FALSE] */ 11238 BCM_IF_ERROR_RETURN 11239 (counter_get(unit, local_port, 11240 SOC_COUNTER_NON_DMA_UC_QUEUE_CURRENT, 11241 startq + i, &value64)); 11242 COMPILER_64_ADD_64(sum, value64); 11243 } 11244 } 11245 COMPILER_64_UMUL_32(sum, _BCM_AP_BYTES_PER_CELL); 11246 *value = sum; 11247 } 11248 break; 11249 11250 case bcmCosqStatGlobalHeadroomBytes0Peak: 11251 BCM_IF_ERROR_RETURN 11252 (counter_get(unit, -1, 11253 SOC_COUNTER_NON_DMA_COSQ_GLOBAL_HDR_COUNT_X_PEAK, 11254 0, value)); 11255 COMPILER_64_UMUL_32(*value, _BCM_AP_BYTES_PER_CELL); 11256 break; 11257 case bcmCosqStatGlobalHeadroomBytes0Current: 11258 BCM_IF_ERROR_RETURN 11259 (counter_get(unit, -1, 11260 SOC_COUNTER_NON_DMA_COSQ_GLOBAL_HDR_COUNT_X_CURRENT, 11261 0, value)); 11262 COMPILER_64_UMUL_32(*value, _BCM_AP_BYTES_PER_CELL); 11263 break; 11264 case bcmCosqStatGlobalHeadroomBytes1Peak: 11265 BCM_IF_ERROR_RETURN 11266 (counter_get(unit, -1, 11267 SOC_COUNTER_NON_DMA_COSQ_GLOBAL_HDR_COUNT_Y_PEAK, 11268 0, value)); 11269 COMPILER_64_UMUL_32(*value, _BCM_AP_BYTES_PER_CELL); 11270 break; 11271 case bcmCosqStatGlobalHeadroomBytes1Current: 11272 BCM_IF_ERROR_RETURN 11273 (counter_get(unit, -1, 11274 SOC_COUNTER_NON_DMA_COSQ_GLOBAL_HDR_COUNT_Y_CURRENT, 11275 0, value)); 11276 COMPILER_64_UMUL_32(*value, _BCM_AP_BYTES_PER_CELL); 11277 break; 11278 case bcmCosqStatHighPriDroppedPackets: 11279 case bcmCosqStatOBMLossyHighPriDroppedPackets: 11280 case bcmCosqStatLowPriDroppedPackets: 11281 case bcmCosqStatOBMLossyLowPriDroppedPackets: 11282 case bcmCosqStatHighPriDroppedBytes: 11283 case bcmCosqStatOBMLossyHighPriDroppedBytes: 11284 case bcmCosqStatLowPriDroppedBytes: 11285 case bcmCosqStatOBMLossyLowPriDroppedBytes: 11286 case bcmCosqStatOBMLossless0DroppedPackets: 11287 case bcmCosqStatOBMLossless1DroppedPackets: 11288 case bcmCosqStatOBMLossless0DroppedBytes: 11289 case bcmCosqStatOBMLossless1DroppedBytes: 11290 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 11291 BCM_GPORT_IS_SCHEDULER(port) || 11292 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) { 11293 return BCM_E_PARAM; 11294 } 11295 BCM_IF_ERROR_RETURN( 11296 _bcm_ap_cosq_localport_resolve(unit, port, &local_port)); 11297 if ((stat == bcmCosqStatHighPriDroppedPackets) || 11298 (stat == bcmCosqStatOBMLossyHighPriDroppedPackets)) { 11299 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM_LOSSY_HI; 11300 } else if ((stat == bcmCosqStatLowPriDroppedPackets) || 11301 (stat == bcmCosqStatOBMLossyLowPriDroppedPackets)) { 11302 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM_LOSSY_LO; 11303 } else if ((stat == bcmCosqStatHighPriDroppedBytes) || 11304 (stat == bcmCosqStatOBMLossyHighPriDroppedBytes)) { 11305 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM_LOSSY_HI; 11306 } else if ((stat == bcmCosqStatLowPriDroppedBytes) || 11307 (stat == bcmCosqStatOBMLossyLowPriDroppedBytes)) { 11308 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM_LOSSY_LO; 11309 } else if (stat == bcmCosqStatOBMLossless0DroppedPackets) { 11310 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM_LOSSLESS0; 11311 } else if (stat == bcmCosqStatOBMLossless1DroppedPackets) { 11312 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM_LOSSLESS1; 11313 } else if (stat == bcmCosqStatOBMLossless0DroppedBytes) { 11314 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM_LOSSLESS0; 11315 } else { /* (stat == bcmCosqStatOBMLossless1DroppedBytes) */ 11316 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM_LOSSLESS1; 11317 } 11318 ctrl_info.instance_type = SOC_CTR_INSTANCE_TYPE_PORT; 11319 ctrl_info.instance = local_port; 11320 BCM_IF_ERROR_RETURN 11321 (soc_counter_generic_get(unit, ctr_reg, ctrl_info, 0, 11322 0, value)); 11323 break; 11324 default: 11325 return BCM_E_PARAM; 11326 } 11327 11328 return BCM_E_NONE; 11329 } 11330 11331 /* 11332 * Function: 11333 * _bcm_ap_cosq_quantize_table_set 11334 * Purpose: 11335 * Generate quantized feedback lookup table 11336 * Parameters: 11337 * unit - (IN) unit number 11338 * profile_index - (IN) profile index 11339 * weight_code - (IN) weight encoding 11340 * set_point - (IN) queue size set point 11341 * active_offset - (OUT) most significant non-zero bit position 11342 * Returns: 11343 * BCM_E_XXX 11344 * Notes: 11345 * The formular to quantize feedback value is: 11346 * quantized_feedbad = celling(feedback / max_feedback * 63) 11347 * where max_feedback = (2 * cpW + 1) * cpQsp 11348 * cpW is feedback weight 11349 * cpQsp is queue size set point 11350 */ 11351 STATIC int 11352 _bcm_ap_cosq_quantize_table_set(int unit, int profile_index, int weight_code, 11353 int set_point, int *active_offset) 11354 { 11355 int ref_count; 11356 int weight_x_4, feedback, max_feedback, quantized_feedback, shift; 11357 int base_index, index; 11358 11359 /* weight = 2 ** (weight_code - 2) e.g. 0 for 1/4, 1 for 1/2, ... */ 11360 weight_x_4 = 1 << weight_code; 11361 max_feedback = ((2 * weight_x_4 + 4) * set_point + 3) / 4; 11362 shift = 0; 11363 while ((max_feedback >> shift) > 127) { 11364 shift++; 11365 } 11366 11367 BCM_IF_ERROR_RETURN 11368 (soc_profile_reg_ref_count_get(unit, _bcm_ap_feedback_profile[unit], 11369 profile_index, &ref_count)); 11370 11371 /* 11372 * Hardware use lookup table to find quantized feedback in order to avoid 11373 * division, use most significant 7-bit of feedback value as lookup table 11374 * index to find quantized_feedback value 11375 */ 11376 if (ref_count == 1) { 11377 base_index = profile_index << 7; 11378 for (index = 0; index < 128; index++) { 11379 feedback = index << shift; 11380 if (feedback > max_feedback) { 11381 quantized_feedback = 63; 11382 } else { 11383 quantized_feedback = (feedback * 63 + max_feedback - 1) / 11384 max_feedback; 11385 } 11386 BCM_IF_ERROR_RETURN 11387 (soc_mem_field32_modify(unit, MMU_QCN_QFBTBm, 11388 base_index + index, CPQ_QNTZFBf, 11389 quantized_feedback)); 11390 } 11391 } 11392 11393 *active_offset = shift + 6; 11394 11395 return BCM_E_NONE; 11396 } 11397 11398 11399 STATIC int 11400 _bcm_ap_cosq_sample_int_table_set(int unit, int min, int max, 11401 uint32 *profile_index) 11402 { 11403 mmu_qcn_sitb_entry_t sitb_entries[64]; 11404 void *entries[1]; 11405 int i, j, center, inc, value, index; 11406 11407 sal_memset(sitb_entries, 0, sizeof(sitb_entries)); 11408 entries[0] = &sitb_entries; 11409 for (i = 0; i < 8; i++) { 11410 center = max - (max - min) * i / 7; 11411 inc = (max - min) / 7 / 8; 11412 for (j = 0; j < 8; j++, inc = -inc) { 11413 index = i * 8 + j; 11414 value = center + (j + 1) / 2 * inc; 11415 if (value > 255) { 11416 value = 255; 11417 } else if (value < 1) { 11418 value = 1; 11419 } 11420 soc_mem_field32_set(unit, MMU_QCN_SITBm, &sitb_entries[index], 11421 CPQ_SIf, value); 11422 } 11423 } 11424 11425 return soc_profile_mem_add(unit, _bcm_ap_sample_int_profile[unit], entries, 11426 64, (uint32 *)profile_index); 11427 } 11428 11429 /* 11430 * Function: 11431 * bcm_ap_cosq_congestion_queue_set 11432 * Purpose: 11433 * Enable/Disable a cos queue as congestion managed queue 11434 * Parameters: 11435 * unit - (IN) unit number 11436 * port - (IN) port number or GPORT identifier 11437 * cosq - (IN) COS queue number 11438 * index - (IN) congestion managed queue index 11439 * Returns: 11440 * BCM_E_XXX 11441 */ 11442 int 11443 bcm_ap_cosq_congestion_queue_set(int unit, bcm_port_t port, 11444 bcm_cos_queue_t cosq, int index) 11445 { 11446 bcm_port_t local_port; 11447 uint32 rval; 11448 uint64 rval64, *rval64s[1]; 11449 mmu_qcn_enable_entry_t enable_entry; 11450 int active_offset, qindex; 11451 uint32 profile_index, sample_profile_index; 11452 int weight_code, set_point; 11453 soc_mem_t mem; 11454 int maxindex = 0 ; 11455 if (cosq < 0 || cosq >= _AP_NUM_COS(unit)) { 11456 return BCM_E_PARAM; 11457 } 11458 11459 if ((index < -1) || (index >= _BCM_AP_NUM_L2_UC_LEAVES)) { 11460 return BCM_E_PARAM; 11461 } 11462 11463 BCM_IF_ERROR_RETURN 11464 (_bcm_ap_cosq_index_resolve(unit, port, cosq, 11465 _BCM_AP_COSQ_INDEX_STYLE_QCN, 11466 &local_port, &qindex, NULL)); 11467 11468 mem = MMU_QCN_ENABLE_0m; 11469 maxindex = soc_mem_index_count(unit, mem); 11470 if ((qindex < -1) || (qindex >= maxindex)) { 11471 return BCM_E_PARAM; 11472 } 11473 11474 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ANY, 11475 qindex, &enable_entry)); 11476 if (index == -1) { 11477 if (!soc_mem_field32_get(unit, mem, &enable_entry, CPQ_ENf)) { 11478 return BCM_E_NONE; 11479 } 11480 11481 index = soc_mem_field32_get(unit, mem, &enable_entry, CPQ_PROFILE_INDEXf); 11482 soc_mem_field32_set(unit, mem, &enable_entry, CPQ_ENf, 0); 11483 BCM_IF_ERROR_RETURN 11484 (soc_mem_write(unit, mem, MEM_BLOCK_ANY, qindex, &enable_entry)); 11485 11486 profile_index = soc_mem_field32_get(unit, mem, &enable_entry, EQTB_INDEXf); 11487 11488 BCM_IF_ERROR_RETURN 11489 (soc_profile_reg_delete(unit, _bcm_ap_feedback_profile[unit], 11490 profile_index)); 11491 11492 profile_index = 11493 soc_mem_field32_get(unit, mem, &enable_entry, SITB_SELf); 11494 11495 BCM_IF_ERROR_RETURN 11496 (soc_profile_mem_delete(unit, _bcm_ap_sample_int_profile[unit], 11497 profile_index * 64)); 11498 } else { 11499 if (soc_mem_field32_get(unit, mem, &enable_entry, CPQ_ENf)) { 11500 return BCM_E_BUSY; 11501 } 11502 11503 /* Use hardware reset value as default quantize setting */ 11504 weight_code = 3; 11505 set_point = 0x96; 11506 rval = 0; 11507 soc_reg_field_set(unit, MMU_QCN_CPQ_SEQr, &rval, CPWf, weight_code); 11508 soc_reg_field_set(unit, MMU_QCN_CPQ_SEQr, &rval, CPQEQf, set_point); 11509 COMPILER_64_SET(rval64, 0, rval); 11510 rval64s[0] = &rval64; 11511 BCM_IF_ERROR_RETURN 11512 (soc_profile_reg_add(unit, _bcm_ap_feedback_profile[unit], 11513 rval64s, 1, (uint32 *)&profile_index)); 11514 11515 /* Update quantized feedback calculation lookup table */ 11516 BCM_IF_ERROR_RETURN 11517 (_bcm_ap_cosq_quantize_table_set(unit, profile_index, weight_code, 11518 set_point, &active_offset)); 11519 11520 /* Pick some sample interval */ 11521 BCM_IF_ERROR_RETURN 11522 (_bcm_ap_cosq_sample_int_table_set(unit, 13, 127, 11523 &sample_profile_index)); 11524 11525 soc_mem_field32_set(unit, mem, &enable_entry, 11526 QNTZ_ACT_OFFSETf, active_offset); 11527 11528 soc_mem_field32_set(unit, mem, &enable_entry, 11529 SITB_SELf, sample_profile_index/64); 11530 11531 soc_mem_field32_set(unit, mem, &enable_entry, EQTB_INDEXf, 11532 profile_index); 11533 11534 soc_mem_field32_set(unit, mem, &enable_entry, CPQ_IDf, index); 11535 11536 soc_mem_field32_set(unit, mem, &enable_entry, CPQ_ENf, 1); 11537 11538 BCM_IF_ERROR_RETURN 11539 (soc_mem_write(unit, mem, MEM_BLOCK_ANY, qindex, &enable_entry)); 11540 } 11541 11542 return BCM_E_NONE; 11543 } 11544 11545 /* 11546 * Function: 11547 * bcm_ap_cosq_congestion_queue_get 11548 * Purpose: 11549 * Get congestion managed queue index of the specified cos queue 11550 * Parameters: 11551 * unit - (IN) unit number 11552 * port - (IN) port number or GPORT identifier 11553 * cosq - (IN) COS queue number 11554 * index - (OUT) congestion managed queue index 11555 * Returns: 11556 * BCM_E_XXX 11557 */ 11558 int 11559 bcm_ap_cosq_congestion_queue_get(int unit, bcm_port_t port, 11560 bcm_cos_queue_t cosq, int *index) 11561 { 11562 bcm_port_t local_port; 11563 int qindex; 11564 mmu_qcn_enable_entry_t entry; 11565 soc_mem_t mem; 11566 int maxindex = 0; 11567 if (cosq < 0 || cosq >= _AP_NUM_COS(unit)) { 11568 return BCM_E_PARAM; 11569 } 11570 11571 if (index == NULL) { 11572 return BCM_E_PARAM; 11573 } 11574 11575 BCM_IF_ERROR_RETURN 11576 (_bcm_ap_cosq_index_resolve(unit, port, cosq, 11577 _BCM_AP_COSQ_INDEX_STYLE_QCN, 11578 &local_port, &qindex, NULL)); 11579 11580 mem = MMU_QCN_ENABLE_0m; 11581 maxindex = soc_mem_index_count(unit, mem); 11582 if ((qindex < -1) || (qindex >= maxindex)) { 11583 return BCM_E_PARAM; 11584 } 11585 11586 BCM_IF_ERROR_RETURN 11587 (soc_mem_read(unit, mem, MEM_BLOCK_ANY, qindex, &entry)); 11588 if (soc_mem_field32_get(unit, mem, &entry, CPQ_ENf)) { 11589 *index = soc_mem_field32_get(unit, mem, &entry, CPQ_IDf); 11590 } else { 11591 *index = -1; 11592 } 11593 11594 return BCM_E_NONE; 11595 } 11596 11597 /* 11598 * Function: 11599 * bcm_ap_cosq_congestion_quantize_set 11600 * Purpose: 11601 * Set quantized congestion feedback algorithm parameters 11602 * Parameters: 11603 * unit - (IN) unit number 11604 * port - (IN) port number or GPORT identifier 11605 * cosq - (IN) COS queue number 11606 * weight_code - (IN) weight encoding (use -1 for unchange) 11607 * set_point - (IN) queue size set point (use -1 for unchange) 11608 * Returns: 11609 * BCM_E_XXX 11610 */ 11611 int 11612 bcm_ap_cosq_congestion_quantize_set(int unit, bcm_port_t port, 11613 bcm_cos_queue_t cosq, int weight_code, 11614 int set_point) 11615 { 11616 bcm_port_t local_port; 11617 uint32 rval; 11618 uint64 rval64, *rval64s[1]; 11619 mmu_qcn_enable_entry_t enable_entry; 11620 int cpq_index, active_offset, qindex; 11621 uint32 profile_index, old_profile_index; 11622 soc_mem_t mem; 11623 int maxindex = 0; 11624 if (cosq < 0 || cosq >= _AP_NUM_COS(unit)) { 11625 return BCM_E_PARAM; 11626 } 11627 11628 11629 mem = MMU_QCN_ENABLE_0m; 11630 11631 BCM_IF_ERROR_RETURN 11632 (bcm_ap_cosq_congestion_queue_get(unit, port, cosq, &cpq_index)); 11633 if (cpq_index == -1) { 11634 /* The cosq specified is not enabled as congestion managed queue */ 11635 return BCM_E_PARAM; 11636 } 11637 11638 BCM_IF_ERROR_RETURN 11639 (_bcm_ap_cosq_index_resolve(unit, port, cosq, 11640 _BCM_AP_COSQ_INDEX_STYLE_QCN, &local_port, &qindex, NULL)); 11641 11642 maxindex = soc_mem_index_count(unit, mem); 11643 if ((qindex < -1) || (qindex >= maxindex)) { 11644 return BCM_E_PARAM; 11645 } 11646 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ANY, qindex, &enable_entry)); 11647 old_profile_index = 11648 soc_mem_field32_get(unit, mem, &enable_entry, EQTB_INDEXf); 11649 11650 BCM_IF_ERROR_RETURN(READ_MMU_QCN_CPQ_SEQr(unit, old_profile_index, &rval)); 11651 if (weight_code == -1) { 11652 weight_code = soc_reg_field_get(unit, MMU_QCN_CPQ_SEQr, rval, CPWf); 11653 } else { 11654 if (weight_code < 0 || weight_code > 7) { 11655 return BCM_E_PARAM; 11656 } 11657 soc_reg_field_set(unit, MMU_QCN_CPQ_SEQr, &rval, CPWf, weight_code); 11658 } 11659 if (set_point == -1) { 11660 set_point = soc_reg_field_get(unit, MMU_QCN_CPQ_SEQr, rval, CPQEQf); 11661 } else { 11662 if (set_point < 0 || set_point > 0xffff) { 11663 return BCM_E_PARAM; 11664 } 11665 soc_reg_field_set(unit, MMU_QCN_CPQ_SEQr, &rval, CPQEQf, set_point); 11666 } 11667 COMPILER_64_SET(rval64, 0, rval); 11668 rval64s[0] = &rval64; 11669 /* Add new feedback parameter profile */ 11670 BCM_IF_ERROR_RETURN 11671 (soc_profile_reg_add(unit, _bcm_ap_feedback_profile[unit], rval64s, 11672 1, (uint32 *)&profile_index)); 11673 /* Delete original feedback parameter profile */ 11674 BCM_IF_ERROR_RETURN 11675 (soc_profile_reg_delete(unit, _bcm_ap_feedback_profile[unit], 11676 old_profile_index)); 11677 11678 /* Update quantized feedback calculation lookup table */ 11679 BCM_IF_ERROR_RETURN 11680 (_bcm_ap_cosq_quantize_table_set(unit, profile_index, weight_code, 11681 set_point, &active_offset)); 11682 11683 soc_mem_field32_set(unit, mem, &enable_entry, 11684 QNTZ_ACT_OFFSETf, active_offset); 11685 soc_mem_field32_set(unit, mem, &enable_entry, 11686 EQTB_INDEXf, profile_index); 11687 BCM_IF_ERROR_RETURN 11688 (soc_mem_write(unit, mem, MEM_BLOCK_ANY, qindex, 11689 &enable_entry)); 11690 11691 return BCM_E_NONE; 11692 } 11693 11694 /* 11695 * Function: 11696 * bcm_ap_cosq_congestion_quantize_get 11697 * Purpose: 11698 * Get quantized congestion feedback algorithm parameters 11699 * Parameters: 11700 * unit - (IN) unit number 11701 * port - (IN) port number or GPORT identifier 11702 * cosq - (IN) COS queue number 11703 * weight_code - (OUT) weight encoding 11704 * set_point - (OUT) queue size set point 11705 * Returns: 11706 * BCM_E_XXX 11707 */ 11708 int 11709 bcm_ap_cosq_congestion_quantize_get(int unit, bcm_port_t port, 11710 bcm_cos_queue_t cosq, int *weight_code, 11711 int *set_point) 11712 { 11713 bcm_port_t local_port; 11714 int cpq_index, profile_index, qindex; 11715 uint32 rval; 11716 mmu_qcn_enable_entry_t enable_entry; 11717 soc_mem_t mem; 11718 int maxindex = 0; 11719 11720 BCM_IF_ERROR_RETURN 11721 (bcm_ap_cosq_congestion_queue_get(unit, port, cosq, &cpq_index)); 11722 if (cpq_index == -1) { 11723 /* The cosq specified is not enabled as congestion managed queue */ 11724 return BCM_E_PARAM; 11725 } 11726 11727 BCM_IF_ERROR_RETURN 11728 (_bcm_ap_cosq_index_resolve(unit, port, cosq, 11729 _BCM_AP_COSQ_INDEX_STYLE_QCN, 11730 &local_port, &qindex, NULL)); 11731 11732 mem = MMU_QCN_ENABLE_0m; 11733 maxindex = soc_mem_index_count(unit, mem); 11734 if ((qindex < -1) || (qindex >= maxindex)) { 11735 return BCM_E_PARAM; 11736 } 11737 11738 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, 11739 MEM_BLOCK_ANY, qindex, &enable_entry)); 11740 profile_index = 11741 soc_mem_field32_get(unit, mem, &enable_entry, EQTB_INDEXf); 11742 11743 BCM_IF_ERROR_RETURN(READ_MMU_QCN_CPQ_SEQr(unit, profile_index, &rval)); 11744 if (weight_code != NULL) { 11745 *weight_code = soc_reg_field_get(unit, MMU_QCN_CPQ_SEQr, rval, CPWf); 11746 } 11747 if (set_point != NULL) { 11748 *set_point = soc_reg_field_get(unit, MMU_QCN_CPQ_SEQr, rval, CPQEQf); 11749 } 11750 11751 return BCM_E_NONE; 11752 } 11753 11754 int 11755 bcm_ap_cosq_congestion_sample_int_set(int unit, bcm_port_t port, 11756 bcm_cos_queue_t cosq, int min, int max) 11757 { 11758 bcm_port_t local_port; 11759 mmu_qcn_enable_entry_t entry; 11760 mmu_qcn_sitb_entry_t sitb_entry; 11761 int qindex; 11762 uint32 profile_index, old_profile_index; 11763 soc_mem_t mem; 11764 int maxindex = 0; 11765 BCM_IF_ERROR_RETURN 11766 (_bcm_ap_cosq_index_resolve(unit, port, cosq, 11767 _BCM_AP_COSQ_INDEX_STYLE_QCN, 11768 &local_port, &qindex, NULL)); 11769 11770 mem = MMU_QCN_ENABLE_0m; 11771 maxindex = soc_mem_index_count(unit, mem); 11772 if ((qindex < -1) || (qindex >= maxindex)) { 11773 return BCM_E_PARAM; 11774 } 11775 11776 11777 BCM_IF_ERROR_RETURN 11778 (soc_mem_read(unit, mem, MEM_BLOCK_ANY, qindex, &entry)); 11779 11780 if (!soc_mem_field32_get(unit, mem, &entry, CPQ_ENf)) { 11781 return BCM_E_PARAM; 11782 } 11783 11784 old_profile_index = 11785 soc_mem_field32_get(unit, mem, &entry, SITB_SELf); 11786 11787 if (max == -1) { 11788 BCM_IF_ERROR_RETURN(soc_mem_read(unit, MMU_QCN_SITBm, MEM_BLOCK_ANY, 11789 old_profile_index * 64, &sitb_entry)); 11790 max = soc_mem_field32_get(unit, MMU_QCN_SITBm, &sitb_entry, CPQ_SIf); 11791 } else { 11792 if (max < 1 || max > 255) { 11793 return BCM_E_PARAM; 11794 } 11795 } 11796 if (min == -1) { 11797 BCM_IF_ERROR_RETURN(soc_mem_read(unit, MMU_QCN_SITBm, MEM_BLOCK_ANY, 11798 old_profile_index * 64 + 63, 11799 &sitb_entry)); 11800 min = soc_mem_field32_get(unit, MMU_QCN_SITBm, &sitb_entry, CPQ_SIf); 11801 } else { 11802 if (min < 1 || min > 255) { 11803 return BCM_E_PARAM; 11804 } 11805 } 11806 11807 /* Add new sample interval profile */ 11808 BCM_IF_ERROR_RETURN 11809 (_bcm_ap_cosq_sample_int_table_set(unit, min, max, &profile_index)); 11810 11811 /* Delete original sample interval profile */ 11812 BCM_IF_ERROR_RETURN 11813 (soc_profile_mem_delete(unit, _bcm_ap_sample_int_profile[unit], 11814 old_profile_index * 64)); 11815 11816 soc_mem_field32_set(unit, mem, &entry, SITB_SELf, 11817 profile_index / 64); 11818 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ANY, 11819 qindex, &entry)); 11820 return BCM_E_NONE; 11821 } 11822 11823 int 11824 bcm_ap_cosq_congestion_sample_int_get(int unit, bcm_port_t port, 11825 bcm_cos_queue_t cosq, int *min, int *max) 11826 { 11827 bcm_port_t local_port; 11828 mmu_qcn_enable_entry_t entry; 11829 mmu_qcn_sitb_entry_t sitb_entry; 11830 int qindex; 11831 uint32 old_profile_index; 11832 soc_mem_t mem; 11833 int maxindex = 0 ; 11834 11835 BCM_IF_ERROR_RETURN 11836 (_bcm_ap_cosq_index_resolve(unit, port, cosq, 11837 _BCM_AP_COSQ_INDEX_STYLE_QCN, 11838 &local_port, &qindex, NULL)); 11839 11840 mem = MMU_QCN_ENABLE_0m; 11841 maxindex = soc_mem_index_count(unit, mem); 11842 if ((qindex < -1) || (qindex >= maxindex)) { 11843 return BCM_E_PARAM; 11844 } 11845 11846 BCM_IF_ERROR_RETURN 11847 (soc_mem_read(unit, mem, MEM_BLOCK_ANY, qindex, &entry)); 11848 11849 if (!soc_mem_field32_get(unit, mem, &entry, CPQ_ENf)) { 11850 return BCM_E_PARAM; 11851 } 11852 11853 old_profile_index = 11854 soc_mem_field32_get(unit, mem, &entry, SITB_SELf); 11855 11856 if (max) { 11857 BCM_IF_ERROR_RETURN(soc_mem_read(unit, MMU_QCN_SITBm, MEM_BLOCK_ANY, 11858 old_profile_index * 64, &sitb_entry)); 11859 *max = soc_mem_field32_get(unit, MMU_QCN_SITBm, &sitb_entry, CPQ_SIf); 11860 } 11861 11862 if (min) { 11863 BCM_IF_ERROR_RETURN(soc_mem_read(unit, MMU_QCN_SITBm, MEM_BLOCK_ANY, 11864 old_profile_index * 64 + 63, 11865 &sitb_entry)); 11866 *min = soc_mem_field32_get(unit, MMU_QCN_SITBm, &sitb_entry, CPQ_SIf); 11867 } 11868 11869 return BCM_E_NONE; 11870 } 11871 11872 STATIC int 11873 _bcm_ap_cosq_ing_pool_set(int unit, bcm_gport_t gport, bcm_cos_queue_t pri_grp, 11874 bcm_cosq_control_t type, int arg) 11875 { 11876 int local_port; 11877 uint32 rval; 11878 static const soc_field_t prigroup_spid_field[] = { 11879 PG0_SPIDf, PG1_SPIDf, PG2_SPIDf, PG3_SPIDf, 11880 PG4_SPIDf, PG5_SPIDf, PG6_SPIDf, PG7_SPIDf 11881 }; 11882 if(( arg < 0 ) || (arg > 3 )) { 11883 return BCM_E_PARAM; 11884 } 11885 11886 BCM_IF_ERROR_RETURN 11887 (_bcm_ap_cosq_localport_resolve(unit, gport, &local_port)); 11888 11889 if (!SOC_PORT_VALID(unit, local_port)) { 11890 return BCM_E_PORT; 11891 } 11892 11893 if ((pri_grp < 0) || (pri_grp >= 8)) { 11894 return BCM_E_PARAM; 11895 } 11896 11897 SOC_IF_ERROR_RETURN(READ_THDI_PORT_PG_SPIDr(unit, local_port, &rval)); 11898 soc_reg_field_set(unit, THDI_PORT_PG_SPIDr, &rval, 11899 prigroup_spid_field[pri_grp],arg); 11900 BCM_IF_ERROR_RETURN(WRITE_THDI_PORT_PG_SPIDr(unit, local_port, rval)); 11901 return BCM_E_NONE; 11902 } 11903 11904 STATIC int 11905 _bcm_ap_cosq_ing_pool_get(int unit, bcm_gport_t gport, 11906 bcm_cos_queue_t pri_grp, 11907 bcm_cosq_control_t type, int *arg) 11908 { 11909 int pool_start_idx = 0, pool_end_idx =0; 11910 BCM_IF_ERROR_RETURN( 11911 _bcm_ap_cosq_ingress_sp_get( 11912 unit, gport, pri_grp, &pool_start_idx, &pool_end_idx)); 11913 *arg = pool_start_idx; 11914 return BCM_E_NONE; 11915 } 11916 11917 /* 11918 * Function: 11919 * _bcm_ap_cosq_port_qnum_get 11920 * Purpose: 11921 * Get the hw queue number used to tx packets on respective Queue 11922 * Parameters: 11923 * unit - (IN) unit number 11924 * port - (IN) port number or GPORT identifier 11925 * cosq - (IN) COS queue number 11926 * type - (IN) unicast/multicast queue indicator 11927 * arg - (out) hw queue number 11928 * Returns: 11929 * BCM_E_XXX 11930 */ 11931 STATIC int 11932 _bcm_ap_cosq_port_qnum_get(int unit, bcm_gport_t gport, 11933 bcm_cos_queue_t cosq, bcm_cosq_control_t type, int *arg) 11934 { 11935 bcm_port_t local_port; 11936 int hw_index; 11937 int uc; 11938 int qnum; 11939 int id, startq, numq; 11940 _bcm_ap_cosq_node_t *node; 11941 soc_info_t *si = &SOC_INFO(unit); 11942 11943 if (!arg) { 11944 return BCM_E_PARAM; 11945 } 11946 11947 if (cosq <= -1) { 11948 return BCM_E_PARAM; 11949 } else { 11950 startq = cosq; 11951 numq = 1; 11952 } 11953 11954 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 11955 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 11956 BCM_IF_ERROR_RETURN 11957 (_bcm_ap_cosq_node_get(unit, gport, cosq, NULL, &local_port, &id, 11958 &node)); 11959 if (node->attached_to_input < 0) { /* Not resolved yet */ 11960 return BCM_E_NOT_FOUND; 11961 } 11962 11963 startq = 0; 11964 } else { 11965 /* optionally validate port */ 11966 BCM_IF_ERROR_RETURN 11967 (_bcm_ap_cosq_localport_resolve(unit, gport, &local_port)); 11968 if (local_port < 0) { 11969 return BCM_E_PORT; 11970 } 11971 node = NULL; 11972 numq = (IS_CPU_PORT(unit, local_port)) ? 11973 NUM_CPU_COSQ(unit) : NUM_COS(unit); 11974 } 11975 11976 if (startq >= numq) { 11977 return BCM_E_PARAM; 11978 } 11979 11980 uc =(type == bcmCosqControlPortQueueUcast) ? 1 : 0; 11981 11982 if (node) { 11983 hw_index = node->hw_index; 11984 } else { 11985 hw_index = soc_apache_l2_hw_index(unit, 11986 si->port_uc_cosq_base[local_port] + startq, uc); 11987 } 11988 11989 qnum = soc_apache_hw_index_logical_num(unit,local_port,hw_index,uc); 11990 *arg = soc_apache_logical_qnum_hw_qnum(unit,local_port,qnum,uc); 11991 11992 return BCM_E_NONE; 11993 } 11994 11995 STATIC int 11996 _bcm_ap_cosq_egr_pool_set(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 11997 bcm_cosq_control_t type, int arg) 11998 { 11999 bcm_port_t local_port; 12000 int startq, pool, midx; 12001 uint32 max_val; 12002 uint32 entry[SOC_MAX_MEM_WORDS]; 12003 uint32 entry2[SOC_MAX_MEM_WORDS]; 12004 soc_mem_t mem = INVALIDm, mem2 = INVALIDm; 12005 soc_field_t fld_limit = INVALIDf; 12006 int granularity = 1; 12007 12008 if ((arg < 0) || (cosq < 0)) { 12009 return BCM_E_PARAM; 12010 } 12011 12012 BCM_IF_ERROR_RETURN 12013 (_bcm_ap_cosq_index_resolve(unit, gport, cosq, 12014 _BCM_AP_COSQ_INDEX_STYLE_EGR_POOL, 12015 &local_port, &pool, NULL)); 12016 12017 mem = MMU_THDM_DB_PORTSP_CONFIG_0m; 12018 12019 if (type == bcmCosqControlEgressPoolLimitEnable) { 12020 midx = SOC_APACHE_MMU_PIPED_MEM_INDEX(unit, local_port, mem, pool); 12021 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, 12022 midx, entry)); 12023 12024 soc_mem_field32_set(unit, mem, entry, SHARED_LIMIT_ENABLEf, !!arg); 12025 12026 return soc_mem_write(unit, mem, MEM_BLOCK_ALL, midx, entry); 12027 } 12028 if((type == bcmCosqControlEgressPool) || (type == bcmCosqControlUCEgressPool) || 12029 (type == bcmCosqControlMCEgressPool)) { 12030 if(( arg < 0 ) || (arg > 3 )) { 12031 return BCM_E_PARAM; 12032 } 12033 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 12034 if (type != bcmCosqControlEgressPool) { 12035 return BCM_E_PARAM; 12036 } 12037 /* regular unicast queue */ 12038 BCM_IF_ERROR_RETURN 12039 (_bcm_ap_cosq_index_resolve(unit, gport, cosq, 12040 _BCM_AP_COSQ_INDEX_STYLE_UCAST_QUEUE, 12041 &local_port, &startq, NULL)); 12042 mem = MMU_THDU_XPIPE_Q_TO_QGRP_MAPm; 12043 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 12044 if (type != bcmCosqControlEgressPool) { 12045 return BCM_E_PARAM; 12046 } 12047 BCM_IF_ERROR_RETURN 12048 (_bcm_ap_cosq_index_resolve(unit, gport, cosq, 12049 _BCM_AP_COSQ_INDEX_STYLE_MCAST_QUEUE, 12050 &local_port, &startq, NULL)); 12051 startq -= _BCM_AP_NUM_L2_UC_LEAVES; /* MC queues comes after UC queues */ 12052 mem = MMU_THDM_MCQE_QUEUE_CONFIG_0m; 12053 mem2 = MMU_THDM_DB_QUEUE_CONFIG_0m; 12054 } else { 12055 if (type == bcmCosqControlUCEgressPool) { 12056 BCM_IF_ERROR_RETURN 12057 (_bcm_ap_cosq_index_resolve(unit, gport, cosq, 12058 _BCM_AP_COSQ_INDEX_STYLE_UCAST_QUEUE, 12059 &local_port, &startq, NULL)); 12060 mem = MMU_THDU_XPIPE_Q_TO_QGRP_MAPm; 12061 } else { 12062 BCM_IF_ERROR_RETURN 12063 (_bcm_ap_cosq_index_resolve(unit, gport, cosq, 12064 _BCM_AP_COSQ_INDEX_STYLE_MCAST_QUEUE, 12065 &local_port, &startq, NULL)); 12066 startq -= _BCM_AP_NUM_L2_UC_LEAVES_PER_PIPE; 12067 /* MC queues comes after UC queues */ 12068 mem = MMU_THDM_MCQE_QUEUE_CONFIG_0m; 12069 mem2 = MMU_THDM_DB_QUEUE_CONFIG_0m; 12070 } 12071 } 12072 12073 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 12074 soc_mem_field32_set(unit, mem, entry, Q_SPIDf, arg); 12075 12076 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 12077 if (mem2 != INVALIDm) { 12078 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem2, MEM_BLOCK_ALL, startq, entry2)); 12079 soc_mem_field32_set(unit, mem2, entry2, Q_SPIDf, arg); 12080 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem2, MEM_BLOCK_ALL, startq, entry2)); 12081 } 12082 return BCM_E_NONE; 12083 } 12084 12085 arg = arg / _BCM_AP_BYTES_PER_CELL; 12086 12087 /* per service pool settings */ 12088 if (type == bcmCosqControlEgressPoolSharedLimitBytes || 12089 type == bcmCosqControlEgressPoolResumeLimitBytes || 12090 type == bcmCosqControlEgressPoolYellowSharedLimitBytes || 12091 type == bcmCosqControlEgressPoolYellowResumeLimitBytes || 12092 type == bcmCosqControlEgressPoolRedSharedLimitBytes || 12093 type == bcmCosqControlEgressPoolRedResumeLimitBytes) { 12094 uint32 rval; 12095 soc_reg_t reg; 12096 switch (type) { 12097 case bcmCosqControlEgressPoolSharedLimitBytes: 12098 reg = MMU_THDM_DB_POOL_SHARED_LIMITr; 12099 fld_limit = SHARED_LIMITf; 12100 granularity = 1; 12101 break; 12102 case bcmCosqControlEgressPoolResumeLimitBytes: 12103 reg = MMU_THDM_DB_POOL_RESUME_LIMITr; 12104 fld_limit = RESUME_LIMITf; 12105 granularity = 8; 12106 break; 12107 case bcmCosqControlEgressPoolYellowSharedLimitBytes: 12108 reg = MMU_THDM_DB_POOL_YELLOW_SHARED_LIMITr; 12109 fld_limit = YELLOW_SHARED_LIMITf; 12110 granularity = 8; 12111 break; 12112 case bcmCosqControlEgressPoolYellowResumeLimitBytes: 12113 reg = MMU_THDM_DB_POOL_YELLOW_RESUME_LIMITr; 12114 fld_limit = YELLOW_RESUME_LIMITf; 12115 granularity = 8; 12116 break; 12117 case bcmCosqControlEgressPoolRedSharedLimitBytes: 12118 reg = MMU_THDM_DB_POOL_RED_SHARED_LIMITr; 12119 fld_limit = RED_SHARED_LIMITf; 12120 granularity = 8; 12121 break; 12122 case bcmCosqControlEgressPoolRedResumeLimitBytes: 12123 reg = MMU_THDM_DB_POOL_RED_RESUME_LIMITr; 12124 fld_limit = RED_RESUME_LIMITf; 12125 granularity = 8; 12126 break; 12127 /* must have default. Otherwise, compilation error */ 12128 /* coverity[dead_error_begin : FALSE] */ 12129 default: 12130 return BCM_E_UNAVAIL; 12131 } 12132 12133 BCM_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, pool, &rval)); 12134 12135 /* Check for min/max values */ 12136 max_val = (1 << soc_reg_field_length(unit, reg, fld_limit)) - 1; 12137 if ((arg < 0) || ((arg/granularity) > max_val)) { 12138 return BCM_E_PARAM; 12139 } else { 12140 soc_reg_field_set(unit, reg, &rval, fld_limit, (arg/granularity)); 12141 } 12142 12143 BCM_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, pool, rval)); 12144 12145 return BCM_E_NONE; 12146 } 12147 12148 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 12149 BCM_IF_ERROR_RETURN 12150 (_bcm_ap_cosq_index_resolve(unit, gport, cosq, 12151 _BCM_AP_COSQ_INDEX_STYLE_UCAST_QUEUE, 12152 &local_port, &startq, NULL)); 12153 mem = MMU_THDU_XPIPE_CONFIG_QUEUEm; 12154 mem2 = MMU_THDU_XPIPE_Q_TO_QGRP_MAPm; 12155 12156 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 12157 BCM_IF_ERROR_RETURN 12158 (_bcm_ap_cosq_index_resolve(unit, gport, cosq, 12159 _BCM_AP_COSQ_INDEX_STYLE_MCAST_QUEUE, 12160 &local_port, &startq, NULL)); 12161 mem = MMU_THDM_DB_QUEUE_CONFIG_0m; 12162 startq -= _BCM_AP_NUM_L2_UC_LEAVES; /* MC queues comes after UC queues */ 12163 } else { 12164 if (soc_property_get(unit, spn_PORT_UC_MC_ACCOUNTING_COMBINE, 0) == 0) { 12165 /* Need to have the UC_MC_Combine config enabled */ 12166 return BCM_E_PARAM; 12167 } 12168 mem = MMU_THDM_DB_PORTSP_CONFIG_0m; 12169 startq = SOC_APACHE_MMU_PIPED_MEM_INDEX(unit, local_port, mem, pool); 12170 } 12171 12172 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 12173 12174 if (mem2 != INVALIDm) { 12175 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem2, MEM_BLOCK_ALL, startq, entry2)); 12176 } 12177 12178 switch (type) { 12179 case bcmCosqControlEgressPoolLimitBytes: 12180 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 12181 fld_limit = Q_SHARED_LIMIT_CELLf; 12182 12183 if (mem2 != INVALIDm) { 12184 soc_mem_field32_set(unit, mem2, entry2, Q_LIMIT_ENABLEf, 1); 12185 } 12186 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 12187 fld_limit = Q_SHARED_LIMITf; 12188 soc_mem_field32_set(unit, mem, entry, Q_LIMIT_ENABLEf, 1); 12189 } else { 12190 fld_limit = SHARED_LIMITf; 12191 soc_mem_field32_set(unit, mem, entry, SHARED_LIMIT_ENABLEf, 1); 12192 } 12193 granularity = 1; 12194 break; 12195 case bcmCosqControlEgressPoolYellowLimitBytes: 12196 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 12197 fld_limit = LIMIT_YELLOW_CELLf; 12198 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 12199 fld_limit = YELLOW_SHARED_LIMITf; 12200 } else { 12201 fld_limit = YELLOW_SHARED_LIMITf; 12202 } 12203 granularity = 8; 12204 break; 12205 case bcmCosqControlEgressPoolRedLimitBytes: 12206 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 12207 fld_limit = LIMIT_RED_CELLf; 12208 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 12209 fld_limit = RED_SHARED_LIMITf; 12210 } else { 12211 fld_limit = RED_SHARED_LIMITf; 12212 } 12213 granularity = 8; 12214 break; 12215 default: 12216 return BCM_E_UNAVAIL; 12217 } 12218 12219 /* Check for min/max values */ 12220 max_val = (1 << soc_mem_field_length(unit, mem, fld_limit)) - 1; 12221 if ((arg < 0) || ((arg/granularity) > max_val)) { 12222 return BCM_E_PARAM; 12223 } else { 12224 soc_mem_field32_set(unit, mem, entry, fld_limit, (arg/granularity)); 12225 } 12226 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 12227 12228 if (mem2 != INVALIDm) { 12229 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem2, MEM_BLOCK_ALL, startq, entry2)); 12230 } 12231 return BCM_E_NONE; 12232 } 12233 12234 12235 12236 STATIC int 12237 _bcm_ap_cosq_egr_port_pool_set(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 12238 bcm_cosq_control_t type, int arg) 12239 { 12240 bcm_port_t local_port; 12241 uint32 max_val; 12242 uint32 entry[SOC_MAX_MEM_WORDS]; 12243 soc_mem_t mem = INVALIDm; 12244 soc_field_t fld_limit = INVALIDf; 12245 int granularity = 1; 12246 int pool, midx; 12247 12248 if (arg < 0) { 12249 return BCM_E_PARAM; 12250 } 12251 12252 BCM_IF_ERROR_RETURN 12253 (_bcm_ap_cosq_index_resolve(unit, gport, cosq, 12254 _BCM_AP_COSQ_INDEX_STYLE_EGR_POOL, 12255 &local_port, &pool, NULL)); 12256 mem = MMU_THDU_XPIPE_CONFIG_PORTm; 12257 midx = SOC_APACHE_MMU_PIPED_MEM_INDEX(unit, local_port, mem, pool); 12258 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, entry)); 12259 12260 switch (type) { 12261 case bcmCosqControlEgressPortPoolYellowLimitBytes: 12262 fld_limit = YELLOW_LIMITf; 12263 granularity = 8; 12264 break; 12265 case bcmCosqControlEgressPortPoolRedLimitBytes: 12266 fld_limit = RED_LIMITf; 12267 granularity = 8; 12268 break; 12269 default: 12270 return BCM_E_UNAVAIL; 12271 } 12272 12273 arg = arg / _BCM_AP_BYTES_PER_CELL; 12274 12275 /* Check for min/max values */ 12276 max_val = (1 << soc_mem_field_length(unit, mem, fld_limit)) - 1; 12277 if ((arg < 0) || ((arg/granularity) > max_val)) { 12278 return BCM_E_PARAM; 12279 } else { 12280 soc_mem_field32_set(unit, mem, entry, fld_limit, (arg/granularity)); 12281 } 12282 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, midx, entry)); 12283 12284 return BCM_E_NONE; 12285 } 12286 12287 12288 STATIC int 12289 _bcm_ap_cosq_egr_pool_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 12290 bcm_cosq_control_t type, int *arg) 12291 { 12292 bcm_port_t local_port; 12293 int startq, pool, midx; 12294 uint32 entry[SOC_MAX_MEM_WORDS]; 12295 soc_mem_t mem; 12296 int granularity = 1; 12297 12298 if ((!arg) || (cosq < 0)) { 12299 return BCM_E_PARAM; 12300 } 12301 12302 if (type == bcmCosqControlUCEgressPool) { 12303 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 12304 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) || 12305 BCM_GPORT_IS_SCHEDULER(gport)) { 12306 return BCM_E_PARAM; 12307 } 12308 12309 BCM_IF_ERROR_RETURN 12310 (_bcm_ap_cosq_index_resolve(unit, gport, cosq, 12311 _BCM_AP_COSQ_INDEX_STYLE_UC_EGR_POOL, 12312 &local_port, &pool, NULL)); 12313 *arg = pool; 12314 return BCM_E_NONE; 12315 } else { 12316 if (type == bcmCosqControlMCEgressPool) { 12317 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 12318 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) || 12319 BCM_GPORT_IS_SCHEDULER(gport)) { 12320 return BCM_E_PARAM; 12321 } 12322 } 12323 BCM_IF_ERROR_RETURN 12324 (_bcm_ap_cosq_index_resolve(unit, gport, cosq, 12325 _BCM_AP_COSQ_INDEX_STYLE_EGR_POOL, 12326 &local_port, &pool, NULL)); 12327 if (type == bcmCosqControlMCEgressPool || 12328 type == bcmCosqControlEgressPool) { 12329 *arg = pool; 12330 return BCM_E_NONE; 12331 } 12332 } 12333 12334 /* per service pool settings */ 12335 if (type == bcmCosqControlEgressPoolSharedLimitBytes || 12336 type == bcmCosqControlEgressPoolResumeLimitBytes || 12337 type == bcmCosqControlEgressPoolYellowSharedLimitBytes || 12338 type == bcmCosqControlEgressPoolYellowResumeLimitBytes || 12339 type == bcmCosqControlEgressPoolRedSharedLimitBytes || 12340 type == bcmCosqControlEgressPoolRedResumeLimitBytes) { 12341 uint32 rval; 12342 soc_reg_t reg; 12343 soc_field_t fld_limit = INVALIDf; 12344 switch (type) { 12345 case bcmCosqControlEgressPoolSharedLimitBytes: 12346 reg = MMU_THDM_DB_POOL_SHARED_LIMITr; 12347 fld_limit = SHARED_LIMITf; 12348 granularity = 1; 12349 break; 12350 case bcmCosqControlEgressPoolResumeLimitBytes: 12351 reg = MMU_THDM_DB_POOL_RESUME_LIMITr; 12352 fld_limit = RESUME_LIMITf; 12353 granularity = 8; 12354 break; 12355 case bcmCosqControlEgressPoolYellowSharedLimitBytes: 12356 reg = MMU_THDM_DB_POOL_YELLOW_SHARED_LIMITr; 12357 fld_limit = YELLOW_SHARED_LIMITf; 12358 granularity = 8; 12359 break; 12360 case bcmCosqControlEgressPoolYellowResumeLimitBytes: 12361 reg = MMU_THDM_DB_POOL_YELLOW_RESUME_LIMITr; 12362 fld_limit = YELLOW_RESUME_LIMITf; 12363 granularity = 8; 12364 break; 12365 case bcmCosqControlEgressPoolRedSharedLimitBytes: 12366 reg = MMU_THDM_DB_POOL_RED_SHARED_LIMITr; 12367 fld_limit = RED_SHARED_LIMITf; 12368 granularity = 8; 12369 break; 12370 case bcmCosqControlEgressPoolRedResumeLimitBytes: 12371 reg = MMU_THDM_DB_POOL_RED_RESUME_LIMITr; 12372 fld_limit = RED_RESUME_LIMITf; 12373 granularity = 8; 12374 break; 12375 /* coverity[dead_error_begin] */ 12376 default: 12377 return BCM_E_UNAVAIL; 12378 } 12379 12380 BCM_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, pool, &rval)); 12381 12382 *arg = soc_reg_field_get(unit, reg, rval, fld_limit); 12383 *arg = (*arg) * granularity * _BCM_AP_BYTES_PER_CELL; 12384 12385 return BCM_E_NONE; 12386 } 12387 mem = MMU_THDM_DB_PORTSP_CONFIG_0m; 12388 12389 if (type == bcmCosqControlEgressPoolLimitEnable) { 12390 midx = SOC_APACHE_MMU_PIPED_MEM_INDEX(unit, local_port, mem, pool); 12391 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, 12392 midx, entry)); 12393 12394 *arg = soc_mem_field32_get(unit, mem, entry, SHARED_LIMIT_ENABLEf); 12395 return BCM_E_NONE; 12396 } 12397 12398 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 12399 BCM_IF_ERROR_RETURN 12400 (_bcm_ap_cosq_index_resolve(unit, gport, cosq, 12401 _BCM_AP_COSQ_INDEX_STYLE_UCAST_QUEUE, 12402 &local_port, &startq, NULL)); 12403 mem = MMU_THDU_XPIPE_CONFIG_QUEUEm; 12404 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 12405 BCM_IF_ERROR_RETURN 12406 (_bcm_ap_cosq_index_resolve(unit, gport, cosq, 12407 _BCM_AP_COSQ_INDEX_STYLE_MCAST_QUEUE, 12408 &local_port, &startq, NULL)); 12409 mem = MMU_THDM_DB_QUEUE_CONFIG_0m; 12410 startq -= _BCM_AP_NUM_L2_UC_LEAVES; /* MC queues comes after UC queues */ 12411 } else { 12412 if (soc_property_get(unit, spn_PORT_UC_MC_ACCOUNTING_COMBINE, 0) == 0) { 12413 /* Need to have the UC_MC_Combine config enabled */ 12414 return BCM_E_PARAM; 12415 } 12416 mem = MMU_THDM_DB_PORTSP_CONFIG_0m; 12417 startq = SOC_APACHE_MMU_PIPED_MEM_INDEX(unit, local_port, mem, pool); 12418 } 12419 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, 12420 startq, entry)); 12421 12422 switch (type) { 12423 12424 case bcmCosqControlEgressPoolLimitBytes: 12425 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 12426 *arg = soc_mem_field32_get(unit, mem, entry, Q_SHARED_LIMIT_CELLf); 12427 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 12428 *arg = soc_mem_field32_get(unit, mem, entry, Q_SHARED_LIMITf); 12429 } else { 12430 *arg = soc_mem_field32_get(unit, mem, entry, SHARED_LIMITf); 12431 } 12432 granularity = 1; 12433 break; 12434 case bcmCosqControlEgressPoolYellowLimitBytes: 12435 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 12436 *arg = soc_mem_field32_get(unit, mem, entry, LIMIT_YELLOW_CELLf); 12437 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 12438 *arg = soc_mem_field32_get(unit, mem, entry, YELLOW_SHARED_LIMITf); 12439 } else { 12440 *arg = soc_mem_field32_get(unit, mem, entry, YELLOW_SHARED_LIMITf); 12441 } 12442 granularity = 8; 12443 break; 12444 case bcmCosqControlEgressPoolRedLimitBytes: 12445 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 12446 *arg = soc_mem_field32_get(unit, mem, entry, LIMIT_RED_CELLf); 12447 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 12448 *arg = soc_mem_field32_get(unit, mem, entry, RED_SHARED_LIMITf); 12449 } else { 12450 *arg = soc_mem_field32_get(unit, mem, entry, RED_SHARED_LIMITf); 12451 } 12452 granularity = 8; 12453 break; 12454 default: 12455 return BCM_E_UNAVAIL; 12456 } 12457 *arg = (*arg) * granularity * _BCM_AP_BYTES_PER_CELL; 12458 return BCM_E_NONE; 12459 } 12460 12461 12462 STATIC int 12463 _bcm_ap_cosq_egr_port_pool_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 12464 bcm_cosq_control_t type, int *arg) 12465 { 12466 bcm_port_t local_port; 12467 uint32 entry[SOC_MAX_MEM_WORDS]; 12468 soc_mem_t mem = INVALIDm; 12469 int granularity = 1; 12470 int pool, midx; 12471 12472 if (!arg) { 12473 return BCM_E_PARAM; 12474 } 12475 12476 12477 BCM_IF_ERROR_RETURN 12478 (_bcm_ap_cosq_index_resolve(unit, gport, cosq, 12479 _BCM_AP_COSQ_INDEX_STYLE_EGR_POOL, 12480 &local_port, &pool, NULL)); 12481 mem = MMU_THDU_XPIPE_CONFIG_PORTm; 12482 midx = SOC_APACHE_MMU_PIPED_MEM_INDEX(unit, local_port, mem, pool); 12483 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, entry)); 12484 12485 switch (type) { 12486 case bcmCosqControlEgressPortPoolYellowLimitBytes: 12487 *arg = soc_mem_field32_get(unit, mem, entry, YELLOW_LIMITf); 12488 granularity = 8; 12489 break; 12490 case bcmCosqControlEgressPortPoolRedLimitBytes: 12491 *arg = soc_mem_field32_get(unit, mem, entry, RED_LIMITf); 12492 granularity = 8; 12493 break; 12494 default: 12495 return BCM_E_UNAVAIL; 12496 } 12497 12498 12499 *arg = (*arg) * granularity * _BCM_AP_BYTES_PER_CELL; 12500 return BCM_E_NONE; 12501 } 12502 12503 12504 12505 STATIC int 12506 _bcm_ap_cosq_egr_queue_set(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 12507 bcm_cosq_control_t type, int arg) 12508 { 12509 bcm_port_t local_port; 12510 int startq; 12511 uint32 max_val, rval = 0; 12512 uint32 shared_size, spid; 12513 uint32 entry[SOC_MAX_MEM_WORDS]; 12514 uint32 entry2[SOC_MAX_MEM_WORDS]; 12515 soc_mem_t mem = INVALIDm, mem2 = INVALIDm; 12516 soc_field_t fld_limit = INVALIDf; 12517 soc_field_t fld_sp = INVALIDf; 12518 int granularity = 1; 12519 int from_cos, to_cos, ci; 12520 int cur_val, rv, post_update, limit = 0; 12521 _bcm_ap_mmu_info_t *mmu_info = _bcm_ap_mmu_info[unit]; 12522 12523 if (arg < 0) { 12524 return BCM_E_PARAM; 12525 } 12526 12527 arg /= _BCM_AP_BYTES_PER_CELL; 12528 12529 if ((type == bcmCosqControlEgressUCQueueMinLimitBytes) || 12530 (type == bcmCosqControlEgressUCQueueSharedLimitBytes)) { 12531 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 12532 BCM_IF_ERROR_RETURN 12533 (_bcm_ap_cosq_index_resolve(unit, gport, cosq, 12534 _BCM_AP_COSQ_INDEX_STYLE_UCAST_QUEUE, 12535 &local_port, &startq, NULL)); 12536 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 12537 return BCM_E_PARAM; 12538 } 12539 else { 12540 if (cosq == BCM_COS_INVALID) { 12541 from_cos = to_cos = 0; 12542 } else { 12543 from_cos = to_cos = cosq; 12544 } 12545 12546 BCM_IF_ERROR_RETURN 12547 (_bcm_ap_cosq_localport_resolve(unit, gport, &local_port)); 12548 if (local_port < 0) { 12549 return BCM_E_PORT; 12550 } 12551 for (ci = from_cos; ci <= to_cos; ci++) { 12552 BCM_IF_ERROR_RETURN 12553 (_bcm_ap_cosq_index_resolve 12554 (unit, local_port, ci, _BCM_AP_COSQ_INDEX_STYLE_UCAST_QUEUE, 12555 NULL, &startq, NULL)); 12556 } 12557 } 12558 mem = MMU_THDU_XPIPE_CONFIG_QUEUEm; 12559 12560 mem2 = MMU_THDU_XPIPE_Q_TO_QGRP_MAPm; 12561 12562 fld_sp = Q_SPIDf; 12563 } else if ((type == bcmCosqControlEgressMCQueueMinLimitBytes) || 12564 (type == bcmCosqControlEgressMCQueueSharedLimitBytes)) { 12565 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 12566 return BCM_E_PARAM; 12567 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 12568 BCM_IF_ERROR_RETURN 12569 (_bcm_ap_cosq_index_resolve(unit, gport, cosq, 12570 _BCM_AP_COSQ_INDEX_STYLE_MCAST_QUEUE, 12571 &local_port, &startq, NULL)); 12572 } 12573 else { 12574 if (cosq == BCM_COS_INVALID) { 12575 from_cos = to_cos = 0; 12576 } else { 12577 from_cos = to_cos = cosq; 12578 } 12579 12580 BCM_IF_ERROR_RETURN 12581 (_bcm_ap_cosq_localport_resolve(unit, gport, &local_port)); 12582 if (local_port < 0) { 12583 return BCM_E_PORT; 12584 } 12585 for (ci = from_cos; ci <= to_cos; ci++) { 12586 BCM_IF_ERROR_RETURN 12587 (_bcm_ap_cosq_index_resolve 12588 (unit, local_port, ci, _BCM_AP_COSQ_INDEX_STYLE_MCAST_QUEUE, 12589 NULL, &startq, NULL)); 12590 } 12591 } 12592 mem = MMU_THDM_DB_QUEUE_CONFIG_0m; 12593 mem2 = MMU_THDM_MCQE_QUEUE_CONFIG_0m; 12594 fld_sp = Q_SPIDf; 12595 startq -= _BCM_AP_NUM_L2_UC_LEAVES; /* MC queues comes after UC queues */ 12596 } else { 12597 return BCM_E_PARAM; 12598 } 12599 12600 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 12601 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem2, MEM_BLOCK_ALL, startq, entry2)); 12602 12603 switch (type) { 12604 case bcmCosqControlEgressUCQueueSharedLimitBytes: 12605 fld_limit = Q_SHARED_LIMIT_CELLf; 12606 12607 if (mem2 != INVALIDm) { 12608 soc_mem_field32_set(unit, mem2, entry2, Q_LIMIT_ENABLEf, 1); 12609 } 12610 12611 /* Set MMU_THDU_XPIPE_Q_TO_QGRP_MAP.DISABLE_QUEUING to 1 when both MIN 12612 * and SHARED LIMIT are 0. Set it to 0 when either MIN or SHARED LIMIT 12613 * is non-zero. 12614 */ 12615 limit = soc_mem_field32_get(unit, mem, entry, Q_MIN_LIMIT_CELLf); 12616 if (arg == 0 && limit == 0) { 12617 soc_mem_field32_set(unit, mem2, entry2, DISABLE_QUEUINGf, 1); 12618 } else if (arg != 0 || limit != 0) { 12619 soc_mem_field32_set(unit, mem2, entry2, DISABLE_QUEUINGf, 0); 12620 } 12621 spid = soc_mem_field32_get(unit, mem2, entry2, fld_sp); 12622 granularity = 1; 12623 break; 12624 case bcmCosqControlEgressMCQueueSharedLimitBytes: 12625 fld_limit = Q_SHARED_LIMITf; 12626 soc_mem_field32_set(unit, mem, entry, Q_LIMIT_ENABLEf, 1); 12627 12628 /* Config LIMIT in THDO_MC_QE: in 4-enties granularity */ 12629 granularity = 4; 12630 soc_mem_field32_set(unit, mem2, entry2, fld_limit, (arg/granularity)); 12631 soc_mem_field32_set(unit, mem2, entry2, Q_LIMIT_ENABLEf, 1); 12632 spid = soc_mem_field32_get(unit, mem, entry, fld_sp); 12633 granularity = 1; 12634 break; 12635 case bcmCosqControlEgressUCQueueMinLimitBytes: 12636 fld_limit = Q_MIN_LIMIT_CELLf; 12637 12638 /* Set MMU_THDU_XPIPE_Q_TO_QGRP_MAP.DISABLE_QUEUING to 1 when both MIN 12639 * and SHARED LIMIT are 0. Set it to 0 when either MIN or SHARED LIMIT is non-zero 12640 */ 12641 limit = soc_mem_field32_get(unit, mem, entry, Q_SHARED_LIMIT_CELLf); 12642 if (arg == 0 && limit == 0) { 12643 soc_mem_field32_set(unit, mem2, entry2, DISABLE_QUEUINGf, 1); 12644 } else if (arg != 0 || limit != 0) { 12645 soc_mem_field32_set(unit, mem2, entry2, DISABLE_QUEUINGf, 0); 12646 } 12647 spid = soc_mem_field32_get(unit, mem2, entry2, fld_sp); 12648 granularity = 1; 12649 break; 12650 case bcmCosqControlEgressMCQueueMinLimitBytes: 12651 fld_limit = Q_MIN_LIMITf; 12652 12653 /* Config LIMIT in THDO_MC_QE: in 4-enties granularity */ 12654 granularity = 4; 12655 soc_mem_field32_set(unit, mem2, entry2, fld_limit, (arg/granularity)); 12656 spid = soc_mem_field32_get(unit, mem, entry, fld_sp); 12657 granularity = 1; 12658 break; 12659 default: 12660 return BCM_E_UNAVAIL; 12661 } 12662 12663 /* Recalculate Shared Values if Min Changed */ 12664 SOC_IF_ERROR_RETURN(READ_MMU_THDM_DB_POOL_SHARED_LIMITr(unit, spid, &rval)); 12665 shared_size = soc_reg_field_get(unit, MMU_THDM_DB_POOL_SHARED_LIMITr, rval, SHARED_LIMITf); 12666 cur_val = soc_mem_field32_get(unit, mem, entry, fld_limit); 12667 12668 if ((arg / granularity) > cur_val) { 12669 /* New Min Val > Cur Min Val 12670 * So reduce the Shared values first and then 12671 * Increase the Min Value for given resource 12672 */ 12673 post_update = 0; 12674 } else if ((arg / granularity) < cur_val) { 12675 /* New Min Val < Cur Min Val 12676 * So reduce the Min values first and then 12677 * Increase Shared values everywhere 12678 */ 12679 post_update = 1; 12680 } else { 12681 return BCM_E_NONE; 12682 } 12683 12684 if (!post_update && 12685 ((type == bcmCosqControlEgressUCQueueMinLimitBytes) || 12686 (type == bcmCosqControlEgressMCQueueMinLimitBytes))) { 12687 int delta = 0; /* In Cells */ 12688 delta = ((arg / granularity) - cur_val) * granularity; 12689 if (delta > shared_size) { 12690 return BCM_E_RESOURCE; 12691 } 12692 rv = soc_apache_mmu_config_res_limits_update(unit,spid, 12693 shared_size - delta, 1); 12694 if (rv < 0) { 12695 return rv; 12696 } 12697 mmu_info->curr_shared_limit = shared_size - delta; 12698 } 12699 12700 12701 /* Check for min/max values */ 12702 max_val = (1 << soc_mem_field_length(unit, mem, fld_limit)) - 1; 12703 if ((arg < 0) || ((arg/granularity) > max_val)) { 12704 return BCM_E_PARAM; 12705 } else { 12706 /* Get the latest entry data and update. */ 12707 SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, 12708 startq, entry)); 12709 soc_mem_field32_set(unit, mem, entry, fld_limit, (arg/granularity)); 12710 } 12711 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 12712 12713 if (mem2 != INVALIDm) { 12714 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem2, MEM_BLOCK_ALL, startq, entry2)); 12715 } 12716 12717 if (post_update && 12718 ((type == bcmCosqControlEgressUCQueueMinLimitBytes) || 12719 (type == bcmCosqControlEgressMCQueueMinLimitBytes))) { 12720 int delta = 0; 12721 delta = (cur_val - (arg / granularity)) * granularity; 12722 rv = soc_apache_mmu_config_res_limits_update(unit,spid, 12723 shared_size + delta, 0); 12724 if (rv < 0) { 12725 return rv; 12726 } 12727 mmu_info->curr_shared_limit = shared_size + delta; 12728 } 12729 12730 return BCM_E_NONE; 12731 } 12732 12733 STATIC int 12734 _bcm_ap_cosq_egr_queue_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 12735 bcm_cosq_control_t type, int *arg) 12736 { 12737 bcm_port_t local_port; 12738 int startq; 12739 uint32 entry[SOC_MAX_MEM_WORDS]; 12740 soc_mem_t mem = INVALIDm; 12741 soc_field_t fld_limit = INVALIDf; 12742 int granularity = 1; 12743 int from_cos, to_cos, ci; 12744 12745 if (!arg) { 12746 return BCM_E_PARAM; 12747 } 12748 12749 if ((type == bcmCosqControlEgressUCQueueMinLimitBytes) || 12750 (type == bcmCosqControlEgressUCQueueSharedLimitBytes)) { 12751 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 12752 BCM_IF_ERROR_RETURN 12753 (_bcm_ap_cosq_index_resolve(unit, gport, cosq, 12754 _BCM_AP_COSQ_INDEX_STYLE_UCAST_QUEUE, 12755 &local_port, &startq, NULL)); 12756 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 12757 return BCM_E_PARAM; 12758 } 12759 else { 12760 if (cosq == BCM_COS_INVALID) { 12761 from_cos = to_cos = 0; 12762 } else { 12763 from_cos = to_cos = cosq; 12764 } 12765 12766 BCM_IF_ERROR_RETURN 12767 (_bcm_ap_cosq_localport_resolve(unit, gport, &local_port)); 12768 if (local_port < 0) { 12769 return BCM_E_PORT; 12770 } 12771 for (ci = from_cos; ci <= to_cos; ci++) { 12772 BCM_IF_ERROR_RETURN 12773 (_bcm_ap_cosq_index_resolve 12774 (unit, local_port, ci, _BCM_AP_COSQ_INDEX_STYLE_UCAST_QUEUE, 12775 NULL, &startq, NULL)); 12776 } 12777 } 12778 mem = MMU_THDU_XPIPE_CONFIG_QUEUEm; 12779 } else if ((type == bcmCosqControlEgressMCQueueMinLimitBytes) || 12780 (type == bcmCosqControlEgressMCQueueSharedLimitBytes)) { 12781 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 12782 return BCM_E_PARAM; 12783 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 12784 BCM_IF_ERROR_RETURN 12785 (_bcm_ap_cosq_index_resolve(unit, gport, cosq, 12786 _BCM_AP_COSQ_INDEX_STYLE_MCAST_QUEUE, 12787 &local_port, &startq, NULL)); 12788 } 12789 else { 12790 if (cosq == BCM_COS_INVALID) { 12791 from_cos = to_cos = 0; 12792 } else { 12793 from_cos = to_cos = cosq; 12794 } 12795 12796 BCM_IF_ERROR_RETURN 12797 (_bcm_ap_cosq_localport_resolve(unit, gport, &local_port)); 12798 if (local_port < 0) { 12799 return BCM_E_PORT; 12800 } 12801 for (ci = from_cos; ci <= to_cos; ci++) { 12802 BCM_IF_ERROR_RETURN 12803 (_bcm_ap_cosq_index_resolve 12804 (unit, local_port, ci, _BCM_AP_COSQ_INDEX_STYLE_MCAST_QUEUE, 12805 NULL, &startq, NULL)); 12806 } 12807 } 12808 mem = MMU_THDM_DB_QUEUE_CONFIG_0m; 12809 startq -= _BCM_AP_NUM_L2_UC_LEAVES; /* MC queues comes after UC queues */ 12810 } else { 12811 return BCM_E_PARAM; 12812 } 12813 12814 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, 12815 startq, entry)); 12816 12817 switch (type) { 12818 case bcmCosqControlEgressUCQueueSharedLimitBytes: 12819 fld_limit = Q_SHARED_LIMIT_CELLf; 12820 granularity = 1; 12821 break; 12822 case bcmCosqControlEgressMCQueueSharedLimitBytes: 12823 fld_limit = Q_SHARED_LIMITf; 12824 granularity = 1; 12825 break; 12826 case bcmCosqControlEgressUCQueueMinLimitBytes: 12827 fld_limit = Q_MIN_LIMIT_CELLf; 12828 granularity = 1; 12829 break; 12830 case bcmCosqControlEgressMCQueueMinLimitBytes: 12831 fld_limit = Q_MIN_LIMITf; 12832 granularity = 1; 12833 break; 12834 default: 12835 return BCM_E_UNAVAIL; 12836 } 12837 *arg = soc_mem_field32_get(unit, mem, entry, fld_limit); 12838 *arg = (*arg) * granularity * _BCM_AP_BYTES_PER_CELL; 12839 return BCM_E_NONE; 12840 } 12841 12842 STATIC int 12843 _bcm_ap_cosq_ing_res_set(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 12844 bcm_cosq_control_t type, int arg) 12845 { 12846 bcm_port_t local_port; 12847 int midx; 12848 uint32 max_val, rval; 12849 uint32 entry[SOC_MAX_MEM_WORDS]; 12850 soc_mem_t mem = INVALIDm; 12851 soc_field_t fld_limit = INVALIDf; 12852 soc_reg_t reg = INVALIDr; 12853 int port_pg, port_pg_pool, granularity = 1; 12854 static const soc_reg_t prigroup_reg[] = { 12855 THDI_PORT_PRI_GRP0r, THDI_PORT_PRI_GRP1r 12856 }; 12857 static const soc_field_t prigroup_field[] = { 12858 PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf, 12859 PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf, 12860 PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf, 12861 PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf 12862 }; 12863 static const soc_field_t prigroup_spid_field[] = { 12864 PG0_SPIDf, PG1_SPIDf, PG2_SPIDf, PG3_SPIDf, 12865 PG4_SPIDf, PG5_SPIDf, PG6_SPIDf, PG7_SPIDf 12866 }; 12867 12868 if (cosq > 15 || cosq < 0) { 12869 /* Error. Input pri > Max Pri_Grp */ 12870 return BCM_E_PARAM; 12871 } 12872 12873 if (arg < 0) { 12874 return BCM_E_PARAM; 12875 } 12876 12877 arg /= _BCM_AP_BYTES_PER_CELL; 12878 BCM_IF_ERROR_RETURN 12879 (_bcm_ap_cosq_localport_resolve(unit, gport, &local_port)); 12880 if (local_port < 0) { 12881 return BCM_E_PORT; 12882 } 12883 12884 /* get PG for port using Port+Cos */ 12885 if (cosq < 8) { 12886 reg = prigroup_reg[0]; 12887 } else { 12888 reg = prigroup_reg[1]; 12889 } 12890 12891 SOC_IF_ERROR_RETURN 12892 (soc_reg32_get(unit, reg, local_port, 0, &rval)); 12893 port_pg = soc_reg_field_get(unit, reg, rval, prigroup_field[cosq]); 12894 12895 12896 if ((type == bcmCosqControlIngressPortPGSharedLimitBytes) || 12897 (type == bcmCosqControlIngressPortPGMinLimitBytes) || 12898 (type == bcmCosqControlIngressPortPGHeadroomLimitBytes) || 12899 (type == bcmCosqControlIngressPortPGResetFloorBytes)) { 12900 mem = THDI_PORT_PG_CONFIG_Xm; 12901 /* get index for Port-PG */ 12902 midx = SOC_APACHE_MMU_PIPED_MEM_INDEX(unit, local_port, mem, port_pg); 12903 12904 } else if ((type == bcmCosqControlIngressPortPoolMaxLimitBytes) || 12905 (type == bcmCosqControlIngressPortPoolMinLimitBytes)) { 12906 reg = THDI_PORT_PG_SPIDr; 12907 12908 SOC_IF_ERROR_RETURN 12909 (soc_reg32_get(unit, reg, local_port, 0, &rval)); 12910 port_pg_pool = soc_reg_field_get(unit, reg, rval, prigroup_spid_field[port_pg]); 12911 12912 mem = THDI_PORT_SP_CONFIG_Xm; 12913 /* get index for Port-SP */ 12914 midx = SOC_APACHE_MMU_PIPED_MEM_INDEX(unit, local_port, mem, port_pg_pool); 12915 } else { 12916 return BCM_E_UNAVAIL; 12917 } 12918 12919 if (midx < 0) { 12920 return BCM_E_PARAM; 12921 } 12922 12923 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, entry)); 12924 12925 switch (type) { 12926 case bcmCosqControlIngressPortPGSharedLimitBytes: 12927 fld_limit = PG_SHARED_LIMITf; 12928 granularity = 1; 12929 break; 12930 case bcmCosqControlIngressPortPoolMaxLimitBytes: 12931 fld_limit = PORT_SP_MAX_LIMITf; 12932 granularity = 1; 12933 break; 12934 case bcmCosqControlIngressPortPGMinLimitBytes: 12935 fld_limit = PG_MIN_LIMITf; 12936 granularity = 1; 12937 break; 12938 case bcmCosqControlIngressPortPoolMinLimitBytes: 12939 fld_limit = PORT_SP_MIN_LIMITf; 12940 granularity = 1; 12941 break; 12942 case bcmCosqControlIngressPortPGHeadroomLimitBytes: 12943 fld_limit = PG_HDRM_LIMITf; 12944 granularity = 1; 12945 break; 12946 case bcmCosqControlIngressPortPGResetFloorBytes: 12947 fld_limit = PG_RESET_FLOORf; 12948 granularity = 1; 12949 break; 12950 /* coverity[dead_error_begin] */ 12951 default: 12952 return BCM_E_UNAVAIL; 12953 } 12954 12955 /* Check for min/max values */ 12956 max_val = (1 << soc_mem_field_length(unit, mem, fld_limit)) - 1; 12957 if ((arg < 0) || ((arg/granularity) > max_val)) { 12958 return BCM_E_PARAM; 12959 } else { 12960 soc_mem_field32_set(unit, mem, entry, fld_limit, (arg/granularity)); 12961 } 12962 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, midx, entry)); 12963 12964 return BCM_E_NONE; 12965 } 12966 12967 STATIC int 12968 _bcm_ap_cosq_state_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 12969 bcm_cosq_control_t type, int *arg) 12970 { 12971 bcm_port_t local_port; 12972 uint32 rval, state , mask = 1 , bitno = 0; 12973 static const soc_field_t pool_field[] = { 12974 POOL_0f, POOL_1f, POOL_2f, POOL_3f }; 12975 int start_pool_idx = 0,end_pool_idx = 0; 12976 if (!arg) { 12977 return BCM_E_PARAM; 12978 } 12979 switch (type) { 12980 case bcmCosqControlSPPortLimitState: 12981 case bcmCosqControlPoolRedDropState: 12982 case bcmCosqControlPoolYellowDropState: 12983 case bcmCosqControlPoolGreenDropState: 12984 BCM_IF_ERROR_RETURN 12985 (_bcm_ap_cosq_localport_resolve(unit, gport, &local_port)); 12986 12987 if (!SOC_PORT_VALID(unit, local_port)) { 12988 return BCM_E_PORT; 12989 } 12990 BCM_IF_ERROR_RETURN (_bcm_ap_cosq_egress_sp_get(unit, gport, cosq, &start_pool_idx, 12991 &end_pool_idx)); 12992 bitno = start_pool_idx; 12993 break; 12994 12995 case bcmCosqControlPGPortLimitState: 12996 case bcmCosqControlPGPortXoffState: 12997 BCM_IF_ERROR_RETURN 12998 (_bcm_ap_cosq_localport_resolve(unit, gport, &local_port)); 12999 13000 if (!SOC_PORT_VALID(unit, local_port)) { 13001 return BCM_E_PORT; 13002 } 13003 if ((cosq < 0 ) || (cosq > 7)) { 13004 return BCM_E_PARAM; 13005 } 13006 bitno = cosq; 13007 break; 13008 default: 13009 return BCM_E_PARAM; 13010 } 13011 switch (type) { 13012 case bcmCosqControlSPPortLimitState: 13013 SOC_IF_ERROR_RETURN( 13014 READ_THDI_PORT_LIMIT_STATESr(unit, local_port, &rval)); 13015 state = soc_reg_field_get(unit, THDI_PORT_LIMIT_STATESr, rval, 13016 SP_LIMIT_STATEf); 13017 break; 13018 case bcmCosqControlPGPortLimitState: 13019 SOC_IF_ERROR_RETURN( 13020 READ_THDI_PORT_LIMIT_STATESr(unit, local_port, &rval)); 13021 state = soc_reg_field_get(unit, THDI_PORT_LIMIT_STATESr, rval, 13022 PG_LIMIT_STATEf); 13023 break; 13024 case bcmCosqControlPGPortXoffState: 13025 SOC_IF_ERROR_RETURN( 13026 READ_THDI_FLOW_CONTROL_XOFF_STATEr(unit, local_port, &rval)); 13027 state = soc_reg_field_get(unit, THDI_FLOW_CONTROL_XOFF_STATEr, rval, 13028 PG_BMPf); 13029 break; 13030 case bcmCosqControlPoolRedDropState: 13031 SOC_IF_ERROR_RETURN( 13032 READ_THDI_POOL_DROP_STATEr(unit, &rval)); 13033 state = soc_reg_field_get(unit, THDI_POOL_DROP_STATEr, rval, 13034 pool_field[start_pool_idx]); 13035 bitno = 2; 13036 break; 13037 case bcmCosqControlPoolYellowDropState: 13038 SOC_IF_ERROR_RETURN( 13039 READ_THDI_POOL_DROP_STATEr(unit, &rval)); 13040 state = soc_reg_field_get(unit, THDI_POOL_DROP_STATEr, rval, 13041 pool_field[start_pool_idx]); 13042 bitno = 1; 13043 break; 13044 case bcmCosqControlPoolGreenDropState: 13045 SOC_IF_ERROR_RETURN( 13046 READ_THDI_POOL_DROP_STATEr(unit, &rval)); 13047 state = soc_reg_field_get(unit, THDI_POOL_DROP_STATEr, rval, 13048 pool_field[start_pool_idx]); 13049 bitno = 0; 13050 break; 13051 default : 13052 return BCM_E_PARAM; 13053 } 13054 mask = mask<<bitno; 13055 state = state & mask ; 13056 if (state) { 13057 *arg = 1 ; 13058 } else { 13059 *arg = 0 ; 13060 } 13061 return BCM_E_NONE; 13062 } 13063 13064 STATIC int 13065 _bcm_ap_cosq_ing_res_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 13066 bcm_cosq_control_t type, int *arg) 13067 { 13068 bcm_port_t local_port; 13069 uint32 rval; 13070 uint32 entry[SOC_MAX_MEM_WORDS]; 13071 soc_mem_t mem = INVALIDm; 13072 soc_field_t fld_limit = INVALIDf; 13073 soc_reg_t reg = INVALIDr; 13074 int midx, port_pg, port_pg_pool, granularity = 1; 13075 static const soc_reg_t prigroup_reg[] = { 13076 THDI_PORT_PRI_GRP0r, THDI_PORT_PRI_GRP1r 13077 }; 13078 static const soc_field_t prigroup_field[] = { 13079 PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf, 13080 PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf, 13081 PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf, 13082 PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf 13083 }; 13084 static const soc_field_t prigroup_spid_field[] = { 13085 PG0_SPIDf, PG1_SPIDf, PG2_SPIDf, PG3_SPIDf, 13086 PG4_SPIDf, PG5_SPIDf, PG6_SPIDf, PG7_SPIDf 13087 }; 13088 13089 if (cosq > 15 || cosq < 0) { 13090 /* Error. Input pri > Max Pri_Grp */ 13091 return BCM_E_PARAM; 13092 } 13093 if (!arg) { 13094 return BCM_E_PARAM; 13095 } 13096 13097 BCM_IF_ERROR_RETURN 13098 (_bcm_ap_cosq_localport_resolve(unit, gport, &local_port)); 13099 if (local_port < 0) { 13100 return BCM_E_PORT; 13101 } 13102 13103 /* get PG for port using Port+Cos */ 13104 if (cosq < 8) { 13105 reg = prigroup_reg[0]; 13106 } else { 13107 reg = prigroup_reg[1]; 13108 } 13109 13110 SOC_IF_ERROR_RETURN 13111 (soc_reg32_get(unit, reg, local_port, 0, &rval)); 13112 port_pg = soc_reg_field_get(unit, reg, rval, prigroup_field[cosq]); 13113 13114 13115 if ((type == bcmCosqControlIngressPortPGSharedLimitBytes) || 13116 (type == bcmCosqControlIngressPortPGMinLimitBytes) || 13117 (type == bcmCosqControlIngressPortPGHeadroomLimitBytes)|| 13118 (type == bcmCosqControlIngressPortPGResetFloorBytes)) { 13119 mem = THDI_PORT_PG_CONFIG_Xm; 13120 /* get index for Port-PG */ 13121 midx = SOC_APACHE_MMU_PIPED_MEM_INDEX(unit, local_port, mem, port_pg); 13122 } else if ((type == bcmCosqControlIngressPortPoolMaxLimitBytes) || 13123 (type == bcmCosqControlIngressPortPoolMinLimitBytes)) { 13124 reg = THDI_PORT_PG_SPIDr; 13125 13126 SOC_IF_ERROR_RETURN 13127 (soc_reg32_get(unit, reg, local_port, 0, &rval)); 13128 port_pg_pool = soc_reg_field_get(unit, reg, rval, prigroup_spid_field[port_pg]); 13129 13130 mem = THDI_PORT_SP_CONFIG_Xm; 13131 /* get index for Port-SP */ 13132 midx = SOC_APACHE_MMU_PIPED_MEM_INDEX(unit, local_port, mem, port_pg_pool); 13133 } else { 13134 return BCM_E_UNAVAIL; 13135 } 13136 13137 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, entry)); 13138 13139 switch (type) { 13140 case bcmCosqControlIngressPortPGSharedLimitBytes: 13141 fld_limit = PG_SHARED_LIMITf; 13142 granularity = 1; 13143 break; 13144 case bcmCosqControlIngressPortPoolMaxLimitBytes: 13145 fld_limit = PORT_SP_MAX_LIMITf; 13146 granularity = 1; 13147 break; 13148 case bcmCosqControlIngressPortPGMinLimitBytes: 13149 fld_limit = PG_MIN_LIMITf; 13150 granularity = 1; 13151 break; 13152 case bcmCosqControlIngressPortPoolMinLimitBytes: 13153 fld_limit = PORT_SP_MIN_LIMITf; 13154 granularity = 1; 13155 break; 13156 case bcmCosqControlIngressPortPGHeadroomLimitBytes: 13157 fld_limit = PG_HDRM_LIMITf; 13158 granularity =1; 13159 break; 13160 case bcmCosqControlIngressPortPGResetFloorBytes: 13161 fld_limit = PG_RESET_FLOORf; 13162 granularity =1; 13163 break; 13164 /* coverity[dead_error_begin] */ 13165 default: 13166 return BCM_E_UNAVAIL; 13167 } 13168 13169 *arg = soc_mem_field32_get(unit, mem, entry, fld_limit); 13170 *arg = (*arg) * granularity * _BCM_AP_BYTES_PER_CELL; 13171 return BCM_E_NONE; 13172 } 13173 13174 13175 13176 /* 13177 * This function is used to get ingress pool 13178 * limit given Ingress [Port, Priority] 13179 */ 13180 STATIC int 13181 _bcm_ap_cosq_ing_res_limit_get(int unit, bcm_gport_t gport, bcm_cos_t cosq, 13182 bcm_cosq_control_t type, int *arg) 13183 { 13184 bcm_port_t local_port; 13185 uint32 rval; 13186 soc_reg_t reg = INVALIDr; 13187 int port_pg, port_pg_pool; 13188 static const soc_reg_t prigroup_reg[] = { 13189 THDI_PORT_PRI_GRP0r, THDI_PORT_PRI_GRP1r 13190 }; 13191 static const soc_field_t prigroup_field[] = { 13192 PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf, 13193 PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf, 13194 PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf, 13195 PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf 13196 }; 13197 static const soc_field_t prigroup_spid_field[] = { 13198 PG0_SPIDf, PG1_SPIDf, PG2_SPIDf, PG3_SPIDf, 13199 PG4_SPIDf, PG5_SPIDf, PG6_SPIDf, PG7_SPIDf 13200 }; 13201 13202 if (cosq > 15 || cosq < 0) { 13203 /* Error. Input pri > Max Pri_Grp */ 13204 return BCM_E_PARAM; 13205 } 13206 if (!arg) { 13207 return BCM_E_PARAM; 13208 } 13209 13210 BCM_IF_ERROR_RETURN 13211 (_bcm_ap_cosq_localport_resolve(unit, gport, &local_port)); 13212 if (local_port < 0) { 13213 return BCM_E_PORT; 13214 } 13215 13216 /* get PG for port using Port+Cos */ 13217 if (cosq < 8) { 13218 reg = prigroup_reg[0]; 13219 } else { 13220 reg = prigroup_reg[1]; 13221 } 13222 13223 SOC_IF_ERROR_RETURN 13224 (soc_reg32_get(unit, reg, local_port, 0, &rval)); 13225 port_pg = soc_reg_field_get(unit, reg, rval, prigroup_field[cosq]); 13226 13227 13228 if (type == bcmCosqControlIngressPoolLimitBytes) { 13229 reg = THDI_PORT_PG_SPIDr; 13230 13231 SOC_IF_ERROR_RETURN 13232 (soc_reg32_get(unit, reg, local_port, 0, &rval)); 13233 port_pg_pool = soc_reg_field_get(unit, reg, rval, prigroup_spid_field[port_pg]); 13234 13235 SOC_IF_ERROR_RETURN 13236 (READ_THDI_BUFFER_CELL_LIMIT_SPr(unit, port_pg_pool, &rval)); 13237 *arg = soc_reg_field_get(unit, THDI_BUFFER_CELL_LIMIT_SPr, rval, LIMITf); 13238 } else { 13239 return BCM_E_PARAM; 13240 } 13241 13242 *arg = (*arg) * _BCM_AP_BYTES_PER_CELL; 13243 13244 return BCM_E_NONE; 13245 } 13246 13247 /* 13248 * This function is used to set ingress pool 13249 * limit given Ingress [Port, Priority] 13250 */ 13251 STATIC int 13252 _bcm_ap_cosq_ing_res_limit_set(int unit, bcm_gport_t gport, bcm_cos_t cosq, 13253 bcm_cosq_control_t type, int arg) 13254 { 13255 bcm_port_t local_port; 13256 uint32 max_val, rval; 13257 soc_reg_t reg = INVALIDr; 13258 int port_pg, port_pg_pool; 13259 static const soc_reg_t prigroup_reg[] = { 13260 THDI_PORT_PRI_GRP0r, THDI_PORT_PRI_GRP1r 13261 }; 13262 static const soc_field_t prigroup_field[] = { 13263 PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf, 13264 PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf, 13265 PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf, 13266 PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf 13267 }; 13268 static const soc_field_t prigroup_spid_field[] = { 13269 PG0_SPIDf, PG1_SPIDf, PG2_SPIDf, PG3_SPIDf, 13270 PG4_SPIDf, PG5_SPIDf, PG6_SPIDf, PG7_SPIDf 13271 }; 13272 13273 if (cosq > 15 || cosq < 0) { 13274 /* Error. Input pri > Max Pri_Grp */ 13275 return BCM_E_PARAM; 13276 } 13277 13278 if (arg < 0) { 13279 return BCM_E_PARAM; 13280 } 13281 13282 arg /= _BCM_AP_BYTES_PER_CELL; 13283 BCM_IF_ERROR_RETURN 13284 (_bcm_ap_cosq_localport_resolve(unit, gport, &local_port)); 13285 if (local_port < 0) { 13286 return BCM_E_PORT; 13287 } 13288 13289 /* get PG for port using Port+Cos */ 13290 if (cosq < 8) { 13291 reg = prigroup_reg[0]; 13292 } else { 13293 reg = prigroup_reg[1]; 13294 } 13295 13296 SOC_IF_ERROR_RETURN 13297 (soc_reg32_get(unit, reg, local_port, 0, &rval)); 13298 port_pg = soc_reg_field_get(unit, reg, rval, prigroup_field[cosq]); 13299 13300 if (type == bcmCosqControlIngressPoolLimitBytes) { 13301 reg = THDI_PORT_PG_SPIDr; 13302 13303 SOC_IF_ERROR_RETURN 13304 (soc_reg32_get(unit, reg, local_port, 0, &rval)); 13305 port_pg_pool = soc_reg_field_get(unit, reg, rval, prigroup_spid_field[port_pg]); 13306 13307 rval = 0; 13308 SOC_IF_ERROR_RETURN(READ_THDI_BUFFER_CELL_LIMIT_SPr(unit, port_pg_pool, &rval)); 13309 /* Check for min/max values */ 13310 max_val = (1 << soc_reg_field_length(unit, THDI_BUFFER_CELL_LIMIT_SPr, LIMITf)) - 1; 13311 if ((arg < 0) || (arg > max_val)) { 13312 return BCM_E_PARAM; 13313 } else { 13314 soc_reg_field_set(unit, THDI_BUFFER_CELL_LIMIT_SPr, &rval, LIMITf, arg); 13315 } 13316 13317 SOC_IF_ERROR_RETURN(WRITE_THDI_BUFFER_CELL_LIMIT_SPr(unit, port_pg_pool, rval)); 13318 } else { 13319 return BCM_E_PARAM; 13320 } 13321 13322 return BCM_E_NONE; 13323 } 13324 13325 STATIC int 13326 _bcm_ap_cosq_ef_op_at_index(int unit, int port, int hw_index, _bcm_cosq_op_t op, 13327 int *ef_val) 13328 { 13329 uint32 entry[SOC_MAX_MEM_WORDS]; 13330 soc_apache_sched_type_t sched_type; 13331 soc_mem_t mem; 13332 13333 sched_type = _soc_apache_port_sched_type_get(unit, port); 13334 13335 if (sched_type == SOC_APACHE_SCHED_LLS) { 13336 mem = _SOC_APACHE_NODE_PARENT_MEM(unit, port, SOC_APACHE_NODE_LVL_L2); 13337 SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, hw_index, &entry)); 13338 13339 if (op == _BCM_COSQ_OP_GET) { 13340 *ef_val = soc_mem_field32_get(unit, mem, &entry, C_EFf); 13341 } else { 13342 soc_mem_field32_set(unit, mem, &entry, C_EFf, *ef_val); 13343 SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, 13344 hw_index, &entry)); 13345 } 13346 } else { 13347 return BCM_E_UNAVAIL; 13348 } 13349 13350 return BCM_E_NONE; 13351 } 13352 13353 STATIC int 13354 _bcm_ap_cosq_ef_op(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, int *arg, 13355 _bcm_cosq_op_t op) 13356 { 13357 _bcm_ap_cosq_node_t *node; 13358 bcm_port_t local_port; 13359 int index, numq, from_cos, to_cos, ci; 13360 13361 if (BCM_GPORT_IS_SCHEDULER(gport)) { 13362 BCM_IF_ERROR_RETURN 13363 (_bcm_ap_cosq_node_get(unit, gport, 0, NULL, 13364 &local_port, NULL, &node)); 13365 BCM_IF_ERROR_RETURN( 13366 _bcm_ap_cosq_child_node_at_input(node, cosq, &node)); 13367 gport = node->gport; 13368 cosq = 0; 13369 } 13370 13371 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 13372 BCM_IF_ERROR_RETURN 13373 (_bcm_ap_cosq_index_resolve 13374 (unit, gport, cosq, _BCM_AP_COSQ_INDEX_STYLE_UCAST_QUEUE, 13375 &local_port, &index, NULL)); 13376 return _bcm_ap_cosq_ef_op_at_index(unit, local_port, index, op, arg); 13377 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 13378 BCM_IF_ERROR_RETURN 13379 (_bcm_ap_cosq_index_resolve 13380 (unit, gport, cosq, _BCM_AP_COSQ_INDEX_STYLE_MCAST_QUEUE, 13381 &local_port, &index, NULL)); 13382 return _bcm_ap_cosq_ef_op_at_index(unit, local_port, index, op, arg); 13383 } else if (BCM_GPORT_IS_SCHEDULER(gport)) { 13384 return BCM_E_PARAM; 13385 } else { 13386 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_port_has_ets(unit, local_port)); 13387 if (cosq == BCM_COS_INVALID) { 13388 from_cos = 0; 13389 to_cos = _AP_NUM_COS(unit) - 1; 13390 } else { 13391 from_cos = to_cos = cosq; 13392 } 13393 for (ci = from_cos; ci <= to_cos; ci++) { 13394 BCM_IF_ERROR_RETURN 13395 (_bcm_ap_cosq_index_resolve 13396 (unit, gport, ci, _BCM_AP_COSQ_INDEX_STYLE_UCAST_QUEUE, 13397 &local_port, &index, &numq)); 13398 13399 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_ef_op_at_index(unit, 13400 local_port, index, op, arg)); 13401 if (op == _BCM_COSQ_OP_GET) { 13402 return BCM_E_NONE; 13403 } 13404 13405 BCM_IF_ERROR_RETURN 13406 (_bcm_ap_cosq_index_resolve 13407 (unit, gport, ci, _BCM_AP_COSQ_INDEX_STYLE_MCAST_QUEUE, 13408 &local_port, &index, &numq)); 13409 13410 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_ef_op_at_index(unit, 13411 local_port, index, op, arg)); 13412 } 13413 } 13414 return BCM_E_NONE; 13415 } 13416 STATIC int 13417 _bcm_ap_cosq_qcn_proxy_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 13418 bcm_cosq_control_t type, int *arg) 13419 { 13420 int local_port; 13421 uint32 rval; 13422 13423 BCM_IF_ERROR_RETURN 13424 (_bcm_ap_cosq_localport_resolve(unit, gport, &local_port)); 13425 13426 BCM_IF_ERROR_RETURN(READ_QCN_CNM_PRP_CTRLr(unit, local_port, &rval)); 13427 *arg = soc_reg_field_get(unit, QCN_CNM_PRP_CTRLr, rval, ENABLEf); 13428 13429 return BCM_E_NONE; 13430 } 13431 13432 STATIC int 13433 _bcm_ap_cosq_qcn_proxy_set(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 13434 bcm_cosq_control_t type, int arg) 13435 { 13436 int local_port; 13437 uint32 rval; 13438 13439 BCM_IF_ERROR_RETURN 13440 (_bcm_ap_cosq_localport_resolve(unit, gport, &local_port)); 13441 13442 BCM_IF_ERROR_RETURN(READ_QCN_CNM_PRP_CTRLr(unit, local_port, &rval)); 13443 soc_reg_field_set(unit, QCN_CNM_PRP_CTRLr, &rval, ENABLEf, !!arg); 13444 soc_reg_field_set(unit, QCN_CNM_PRP_CTRLr, &rval, PRIORITY_BMAPf, 0xff); 13445 BCM_IF_ERROR_RETURN(WRITE_QCN_CNM_PRP_CTRLr(unit, local_port, rval)); 13446 return BCM_E_NONE; 13447 } 13448 13449 STATIC int 13450 _bcm_ap_cosq_alpha_set(int unit, 13451 bcm_gport_t gport, bcm_cos_queue_t cosq, 13452 bcm_cosq_control_drop_limit_alpha_value_t arg) 13453 { 13454 bcm_port_t local_port; 13455 int startq; 13456 int midx; 13457 uint32 rval; 13458 uint32 entry[SOC_MAX_MEM_WORDS]; 13459 uint32 entry2[SOC_MAX_MEM_WORDS]; 13460 soc_mem_t mem = INVALIDm, mem2 = INVALIDm; 13461 int alpha; 13462 int dynamic_thresh_mode; 13463 soc_reg_t reg = INVALIDr; 13464 int port_pg; 13465 static const soc_reg_t prigroup_reg[] = { 13466 THDI_PORT_PRI_GRP0r, THDI_PORT_PRI_GRP1r 13467 }; 13468 static const soc_field_t prigroup_field[] = { 13469 PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf, 13470 PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf, 13471 PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf, 13472 PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf 13473 }; 13474 13475 switch(arg) { 13476 case bcmCosqControlDropLimitAlpha_1_128: 13477 alpha = SOC_APACHE_COSQ_DROP_LIMIT_ALPHA_1_128; 13478 break; 13479 case bcmCosqControlDropLimitAlpha_1_64: 13480 alpha = SOC_APACHE_COSQ_DROP_LIMIT_ALPHA_1_64; 13481 break; 13482 case bcmCosqControlDropLimitAlpha_1_32: 13483 alpha = SOC_APACHE_COSQ_DROP_LIMIT_ALPHA_1_32; 13484 break; 13485 case bcmCosqControlDropLimitAlpha_1_16: 13486 alpha = SOC_APACHE_COSQ_DROP_LIMIT_ALPHA_1_16; 13487 break; 13488 case bcmCosqControlDropLimitAlpha_1_8: 13489 alpha = SOC_APACHE_COSQ_DROP_LIMIT_ALPHA_1_8; 13490 break; 13491 case bcmCosqControlDropLimitAlpha_1_4: 13492 alpha = SOC_APACHE_COSQ_DROP_LIMIT_ALPHA_1_4; 13493 break; 13494 case bcmCosqControlDropLimitAlpha_1_2: 13495 alpha = SOC_APACHE_COSQ_DROP_LIMIT_ALPHA_1_2; 13496 break; 13497 case bcmCosqControlDropLimitAlpha_1: 13498 alpha = SOC_APACHE_COSQ_DROP_LIMIT_ALPHA_1; 13499 break; 13500 case bcmCosqControlDropLimitAlpha_2: 13501 alpha = SOC_APACHE_COSQ_DROP_LIMIT_ALPHA_2; 13502 break; 13503 case bcmCosqControlDropLimitAlpha_4: 13504 alpha = SOC_APACHE_COSQ_DROP_LIMIT_ALPHA_4; 13505 break; 13506 case bcmCosqControlDropLimitAlpha_8: 13507 alpha = SOC_APACHE_COSQ_DROP_LIMIT_ALPHA_8; 13508 break; 13509 default: 13510 return BCM_E_PARAM; 13511 } 13512 13513 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 13514 BCM_IF_ERROR_RETURN 13515 (_bcm_ap_cosq_dynamic_thresh_enable_get(unit, gport, cosq, 13516 bcmCosqControlEgressUCSharedDynamicEnable, 13517 &dynamic_thresh_mode)); 13518 if (!dynamic_thresh_mode){ 13519 return BCM_E_CONFIG; 13520 } 13521 13522 BCM_IF_ERROR_RETURN 13523 (_bcm_ap_cosq_index_resolve(unit, gport, cosq, 13524 _BCM_AP_COSQ_INDEX_STYLE_UCAST_QUEUE, 13525 &local_port, &startq, NULL)); 13526 mem = MMU_THDU_XPIPE_CONFIG_QUEUEm; 13527 13528 BCM_IF_ERROR_RETURN 13529 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 13530 soc_mem_field32_set(unit, mem, entry, 13531 Q_SHARED_ALPHA_CELLf, alpha); 13532 SOC_IF_ERROR_RETURN 13533 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 13534 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 13535 BCM_IF_ERROR_RETURN 13536 (_bcm_ap_cosq_dynamic_thresh_enable_get(unit, gport, cosq, 13537 bcmCosqControlEgressMCSharedDynamicEnable, 13538 &dynamic_thresh_mode)); 13539 if (!dynamic_thresh_mode){ 13540 return BCM_E_CONFIG; 13541 } 13542 13543 BCM_IF_ERROR_RETURN 13544 (_bcm_ap_cosq_index_resolve(unit, gport, cosq, 13545 _BCM_AP_COSQ_INDEX_STYLE_MCAST_QUEUE, 13546 &local_port, &startq, NULL)); 13547 mem = MMU_THDM_DB_QUEUE_CONFIG_0m; 13548 mem2 = MMU_THDM_MCQE_QUEUE_CONFIG_0m; 13549 13550 startq -= _BCM_AP_NUM_L2_UC_LEAVES; /* MC queues comes after UC queues */ 13551 BCM_IF_ERROR_RETURN 13552 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 13553 soc_mem_field32_set(unit, mem, entry, Q_SHARED_ALPHAf, alpha); 13554 SOC_IF_ERROR_RETURN 13555 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 13556 13557 BCM_IF_ERROR_RETURN 13558 (soc_mem_read(unit, mem2, MEM_BLOCK_ALL, startq, entry2)); 13559 soc_mem_field32_set(unit, mem2, entry2, Q_SHARED_ALPHAf, alpha); 13560 SOC_IF_ERROR_RETURN 13561 (soc_mem_write(unit, mem2, MEM_BLOCK_ALL, startq, entry2)); 13562 } else { 13563 BCM_IF_ERROR_RETURN 13564 (_bcm_ap_cosq_dynamic_thresh_enable_get(unit, gport, cosq, 13565 bcmCosqControlIngressPortPGSharedDynamicEnable, 13566 &dynamic_thresh_mode)); 13567 if (!dynamic_thresh_mode){ 13568 return BCM_E_CONFIG; 13569 } 13570 13571 BCM_IF_ERROR_RETURN 13572 (_bcm_ap_cosq_localport_resolve(unit, gport, &local_port)); 13573 if (local_port < 0) { 13574 return BCM_E_PORT; 13575 } 13576 13577 /* get PG for port using Port+Cos */ 13578 if (cosq < 8) { 13579 reg = prigroup_reg[0]; 13580 } else { 13581 reg = prigroup_reg[1]; 13582 } 13583 13584 SOC_IF_ERROR_RETURN 13585 (soc_reg32_get(unit, reg, local_port, 0, &rval)); 13586 port_pg = soc_reg_field_get(unit, reg, rval, prigroup_field[cosq]); 13587 mem = THDI_PORT_PG_CONFIG_Xm; 13588 /* get index for Port-PG */ 13589 midx = SOC_APACHE_MMU_PIPED_MEM_INDEX(unit, local_port, mem, port_pg); 13590 BCM_IF_ERROR_RETURN 13591 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, entry)); 13592 soc_mem_field32_set(unit, mem, entry, 13593 PG_SHARED_LIMITf, alpha); 13594 SOC_IF_ERROR_RETURN 13595 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, midx, entry)); 13596 } 13597 13598 return BCM_E_NONE; 13599 } 13600 13601 13602 STATIC int 13603 _bcm_ap_cosq_alpha_get(int unit, 13604 bcm_gport_t gport, bcm_cos_queue_t cosq, 13605 bcm_cosq_control_drop_limit_alpha_value_t *arg) 13606 { 13607 bcm_port_t local_port; 13608 int startq; 13609 int midx; 13610 uint32 rval; 13611 uint32 entry[SOC_MAX_MEM_WORDS]; 13612 soc_mem_t mem = INVALIDm; 13613 int alpha; 13614 int dynamic_thresh_mode; 13615 soc_reg_t reg = INVALIDr; 13616 int port_pg; 13617 static const soc_reg_t prigroup_reg[] = { 13618 THDI_PORT_PRI_GRP0r, THDI_PORT_PRI_GRP1r 13619 }; 13620 static const soc_field_t prigroup_field[] = { 13621 PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf, 13622 PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf, 13623 PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf, 13624 PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf 13625 }; 13626 13627 if (!arg) { 13628 return BCM_E_PARAM; 13629 } 13630 13631 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 13632 BCM_IF_ERROR_RETURN 13633 (_bcm_ap_cosq_dynamic_thresh_enable_get(unit, gport, cosq, 13634 bcmCosqControlEgressUCSharedDynamicEnable, 13635 &dynamic_thresh_mode)); 13636 if (!dynamic_thresh_mode){ 13637 return BCM_E_CONFIG; 13638 } 13639 13640 BCM_IF_ERROR_RETURN 13641 (_bcm_ap_cosq_index_resolve(unit, gport, cosq, 13642 _BCM_AP_COSQ_INDEX_STYLE_UCAST_QUEUE, 13643 &local_port, &startq, NULL)); 13644 mem = MMU_THDU_XPIPE_CONFIG_QUEUEm; 13645 13646 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, 13647 startq, entry)); 13648 alpha = soc_mem_field32_get(unit, mem, entry, Q_SHARED_ALPHA_CELLf); 13649 13650 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 13651 BCM_IF_ERROR_RETURN 13652 (_bcm_ap_cosq_dynamic_thresh_enable_get(unit, gport, cosq, 13653 bcmCosqControlEgressMCSharedDynamicEnable, 13654 &dynamic_thresh_mode)); 13655 if (!dynamic_thresh_mode){ 13656 return BCM_E_CONFIG; 13657 } 13658 13659 BCM_IF_ERROR_RETURN 13660 (_bcm_ap_cosq_index_resolve(unit, gport, cosq, 13661 _BCM_AP_COSQ_INDEX_STYLE_MCAST_QUEUE, 13662 &local_port, &startq, NULL)); 13663 mem = MMU_THDM_DB_QUEUE_CONFIG_0m; 13664 13665 startq -= _BCM_AP_NUM_L2_UC_LEAVES; /* MC queues comes after UC queues */ 13666 BCM_IF_ERROR_RETURN 13667 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 13668 alpha = soc_mem_field32_get(unit, mem, entry, Q_SHARED_ALPHAf); 13669 13670 } else { 13671 BCM_IF_ERROR_RETURN 13672 (_bcm_ap_cosq_dynamic_thresh_enable_get(unit, gport, cosq, 13673 bcmCosqControlIngressPortPGSharedDynamicEnable, 13674 &dynamic_thresh_mode)); 13675 if (!dynamic_thresh_mode){ 13676 return BCM_E_CONFIG; 13677 } 13678 13679 BCM_IF_ERROR_RETURN 13680 (_bcm_ap_cosq_localport_resolve(unit, gport, &local_port)); 13681 if (local_port < 0) { 13682 return BCM_E_PORT; 13683 } 13684 13685 /* get PG for port using Port+Cos */ 13686 if (cosq < 8) { 13687 reg = prigroup_reg[0]; 13688 } else { 13689 reg = prigroup_reg[1]; 13690 } 13691 13692 SOC_IF_ERROR_RETURN 13693 (soc_reg32_get(unit, reg, local_port, 0, &rval)); 13694 port_pg = soc_reg_field_get(unit, reg, rval, prigroup_field[cosq]); 13695 mem = THDI_PORT_PG_CONFIG_Xm; 13696 /* get index for Port-PG */ 13697 midx = SOC_APACHE_MMU_PIPED_MEM_INDEX(unit, local_port, mem, port_pg); 13698 13699 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, 13700 midx, entry)); 13701 alpha = soc_mem_field32_get(unit, mem, entry, PG_SHARED_LIMITf); 13702 13703 } 13704 13705 switch(alpha) { 13706 case SOC_APACHE_COSQ_DROP_LIMIT_ALPHA_1_128: 13707 *arg = bcmCosqControlDropLimitAlpha_1_128; 13708 break; 13709 case SOC_APACHE_COSQ_DROP_LIMIT_ALPHA_1_64: 13710 *arg = bcmCosqControlDropLimitAlpha_1_64; 13711 break; 13712 case SOC_APACHE_COSQ_DROP_LIMIT_ALPHA_1_32: 13713 *arg = bcmCosqControlDropLimitAlpha_1_32; 13714 break; 13715 case SOC_APACHE_COSQ_DROP_LIMIT_ALPHA_1_16: 13716 *arg = bcmCosqControlDropLimitAlpha_1_16; 13717 break; 13718 case SOC_APACHE_COSQ_DROP_LIMIT_ALPHA_1_8: 13719 *arg = bcmCosqControlDropLimitAlpha_1_8; 13720 break; 13721 case SOC_APACHE_COSQ_DROP_LIMIT_ALPHA_1_4: 13722 *arg = bcmCosqControlDropLimitAlpha_1_4; 13723 break; 13724 case SOC_APACHE_COSQ_DROP_LIMIT_ALPHA_1_2: 13725 *arg = bcmCosqControlDropLimitAlpha_1_2; 13726 break; 13727 case SOC_APACHE_COSQ_DROP_LIMIT_ALPHA_1: 13728 *arg = bcmCosqControlDropLimitAlpha_1; 13729 break; 13730 case SOC_APACHE_COSQ_DROP_LIMIT_ALPHA_2: 13731 *arg = bcmCosqControlDropLimitAlpha_2; 13732 break; 13733 case SOC_APACHE_COSQ_DROP_LIMIT_ALPHA_4: 13734 *arg = bcmCosqControlDropLimitAlpha_4; 13735 break; 13736 case SOC_APACHE_COSQ_DROP_LIMIT_ALPHA_8: 13737 *arg = bcmCosqControlDropLimitAlpha_8; 13738 break; 13739 default: 13740 return BCM_E_PARAM; 13741 } 13742 13743 return BCM_E_NONE; 13744 } 13745 13746 STATIC int 13747 _bcm_ap_cosq_dynamic_thresh_enable_set(int unit, 13748 bcm_gport_t gport, bcm_cos_queue_t cosq, 13749 bcm_cosq_control_t type, int arg) 13750 { 13751 bcm_port_t local_port; 13752 int startq; 13753 int from_cos = 0, to_cos = 0; 13754 13755 int ci; 13756 int midx; 13757 uint32 rval; 13758 uint32 entry[SOC_MAX_MEM_WORDS]; 13759 uint32 entry2[SOC_MAX_MEM_WORDS]; 13760 soc_mem_t mem = INVALIDm, mem2 = INVALIDm; 13761 soc_reg_t reg = INVALIDr; 13762 int port_pg; 13763 static const soc_reg_t prigroup_reg[] = { 13764 THDI_PORT_PRI_GRP0r, THDI_PORT_PRI_GRP1r 13765 }; 13766 static const soc_field_t prigroup_field[] = { 13767 PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf, 13768 PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf, 13769 PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf, 13770 PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf 13771 }; 13772 13773 if ((cosq < 0) || (cosq > 15)){ 13774 return BCM_E_PARAM; 13775 } 13776 13777 13778 if (type == bcmCosqControlIngressPortPGSharedDynamicEnable) { 13779 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 13780 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 13781 return BCM_E_PARAM; 13782 } 13783 13784 BCM_IF_ERROR_RETURN 13785 (_bcm_ap_cosq_localport_resolve(unit, gport, &local_port)); 13786 if (local_port < 0) { 13787 return BCM_E_PORT; 13788 } 13789 13790 /* get PG for port using Port+Cos */ 13791 if (cosq < 8) { 13792 reg = prigroup_reg[0]; 13793 } else { 13794 reg = prigroup_reg[1]; 13795 } 13796 13797 SOC_IF_ERROR_RETURN 13798 (soc_reg32_get(unit, reg, local_port, 0, &rval)); 13799 port_pg = soc_reg_field_get(unit, reg, rval, prigroup_field[cosq]); 13800 mem = THDI_PORT_PG_CONFIG_Xm; 13801 /* get index for Port-PG */ 13802 midx = SOC_APACHE_MMU_PIPED_MEM_INDEX(unit, local_port, mem, port_pg); 13803 BCM_IF_ERROR_RETURN 13804 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, entry)); 13805 soc_mem_field32_set(unit, mem, entry, 13806 PG_SHARED_DYNAMICf, arg ? 1 : 0); 13807 /* Set default alpha value*/ 13808 if (arg) { 13809 soc_mem_field32_set(unit, mem, entry, 13810 PG_SHARED_LIMITf, bcmCosqControlDropLimitAlpha_1_128); 13811 } 13812 SOC_IF_ERROR_RETURN 13813 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, midx, entry)); 13814 } else if (type == bcmCosqControlEgressUCSharedDynamicEnable) { 13815 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 13816 BCM_IF_ERROR_RETURN 13817 (_bcm_ap_cosq_index_resolve(unit, gport, cosq, 13818 _BCM_AP_COSQ_INDEX_STYLE_UCAST_QUEUE, 13819 &local_port, &startq, NULL)); 13820 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 13821 return BCM_E_PARAM; 13822 } else { 13823 from_cos = to_cos = cosq; 13824 13825 BCM_IF_ERROR_RETURN 13826 (_bcm_ap_cosq_localport_resolve(unit, gport, &local_port)); 13827 if (local_port < 0) { 13828 return BCM_E_PORT; 13829 } 13830 for (ci = from_cos; ci <= to_cos; ci++) { 13831 BCM_IF_ERROR_RETURN 13832 (_bcm_ap_cosq_index_resolve(unit, local_port, ci, 13833 _BCM_AP_COSQ_INDEX_STYLE_UCAST_QUEUE, 13834 NULL, &startq, NULL)); 13835 13836 } 13837 } 13838 mem = MMU_THDU_XPIPE_CONFIG_QUEUEm; 13839 13840 BCM_IF_ERROR_RETURN 13841 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 13842 soc_mem_field32_set(unit, mem, entry, 13843 Q_LIMIT_DYNAMIC_CELLf, arg ? 1 : 0); 13844 /* Set default alpha value*/ 13845 if (arg) { 13846 soc_mem_field32_set(unit, mem, entry, 13847 Q_SHARED_ALPHA_CELLf, bcmCosqControlDropLimitAlpha_1_128); 13848 } 13849 SOC_IF_ERROR_RETURN 13850 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 13851 } else if (type == bcmCosqControlEgressMCSharedDynamicEnable) { 13852 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 13853 return BCM_E_PARAM; 13854 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 13855 BCM_IF_ERROR_RETURN 13856 (_bcm_ap_cosq_index_resolve(unit, gport, cosq, 13857 _BCM_AP_COSQ_INDEX_STYLE_MCAST_QUEUE, 13858 &local_port, &startq, NULL)); 13859 } 13860 else { 13861 from_cos = to_cos = cosq; 13862 13863 BCM_IF_ERROR_RETURN 13864 (_bcm_ap_cosq_localport_resolve(unit, gport, &local_port)); 13865 if (local_port < 0) { 13866 return BCM_E_PORT; 13867 } 13868 for (ci = from_cos; ci <= to_cos; ci++) { 13869 BCM_IF_ERROR_RETURN 13870 (_bcm_ap_cosq_index_resolve(unit, local_port, ci, 13871 _BCM_AP_COSQ_INDEX_STYLE_MCAST_QUEUE, 13872 NULL, &startq, NULL)); 13873 13874 } 13875 } 13876 13877 mem = MMU_THDM_DB_QUEUE_CONFIG_0m; 13878 mem2 = MMU_THDM_MCQE_QUEUE_CONFIG_0m; 13879 13880 startq -= _BCM_AP_NUM_L2_UC_LEAVES; /* MC queues comes after UC queues */ 13881 BCM_IF_ERROR_RETURN 13882 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 13883 soc_mem_field32_set(unit, mem, entry, Q_LIMIT_DYNAMICf, arg ? 1 : 0); 13884 /* Set default alpha value*/ 13885 if (arg) { 13886 soc_mem_field32_set(unit, mem, entry, 13887 Q_SHARED_ALPHAf, bcmCosqControlDropLimitAlpha_1_128); 13888 } 13889 SOC_IF_ERROR_RETURN 13890 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 13891 13892 BCM_IF_ERROR_RETURN 13893 (soc_mem_read(unit, mem2, MEM_BLOCK_ALL, startq, entry2)); 13894 soc_mem_field32_set(unit, mem2, entry2, Q_LIMIT_DYNAMICf, arg ? 1 : 0); 13895 /* Set default alpha value*/ 13896 if (arg) { 13897 soc_mem_field32_set(unit, mem2, entry2, 13898 Q_SHARED_ALPHAf, bcmCosqControlDropLimitAlpha_1_128); 13899 } 13900 SOC_IF_ERROR_RETURN 13901 (soc_mem_write(unit, mem2, MEM_BLOCK_ALL, startq, entry2)); 13902 13903 } else { 13904 return BCM_E_PARAM; 13905 } 13906 13907 return BCM_E_NONE; 13908 } 13909 13910 STATIC int 13911 _bcm_ap_cosq_dynamic_thresh_enable_get(int unit, 13912 bcm_gport_t gport, bcm_cos_queue_t cosq, 13913 bcm_cosq_control_t type, int *arg) 13914 { 13915 bcm_port_t local_port; 13916 int startq; 13917 int from_cos = 0, to_cos = 0; 13918 int ci; 13919 int midx; 13920 uint32 rval; 13921 uint32 entry[SOC_MAX_MEM_WORDS]; 13922 soc_mem_t mem = INVALIDm; 13923 soc_reg_t reg = INVALIDr; 13924 int port_pg; 13925 static const soc_reg_t prigroup_reg[] = { 13926 THDI_PORT_PRI_GRP0r, THDI_PORT_PRI_GRP1r 13927 }; 13928 static const soc_field_t prigroup_field[] = { 13929 PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf, 13930 PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf, 13931 PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf, 13932 PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf 13933 }; 13934 13935 if (!arg) { 13936 return BCM_E_PARAM; 13937 } 13938 13939 if ((cosq < 0) || (cosq > 15)){ 13940 return BCM_E_PARAM; 13941 } 13942 13943 if (type == bcmCosqControlIngressPortPGSharedDynamicEnable) { 13944 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 13945 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 13946 return BCM_E_PARAM; 13947 } 13948 BCM_IF_ERROR_RETURN 13949 (_bcm_ap_cosq_localport_resolve(unit, gport, &local_port)); 13950 if (local_port < 0) { 13951 return BCM_E_PORT; 13952 } 13953 13954 /* get PG for port using Port+Cos */ 13955 if (cosq < 8) { 13956 reg = prigroup_reg[0]; 13957 } else { 13958 reg = prigroup_reg[1]; 13959 } 13960 13961 SOC_IF_ERROR_RETURN 13962 (soc_reg32_get(unit, reg, local_port, 0, &rval)); 13963 port_pg = soc_reg_field_get(unit, reg, rval, prigroup_field[cosq]); 13964 mem = THDI_PORT_PG_CONFIG_Xm; 13965 /* get index for Port-PG */ 13966 midx = SOC_APACHE_MMU_PIPED_MEM_INDEX(unit, local_port, mem, port_pg); 13967 13968 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, 13969 midx, entry)); 13970 *arg = soc_mem_field32_get(unit, mem, entry, PG_SHARED_DYNAMICf); 13971 13972 } else if (type == bcmCosqControlEgressUCSharedDynamicEnable) { 13973 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 13974 BCM_IF_ERROR_RETURN 13975 (_bcm_ap_cosq_index_resolve(unit, gport, cosq, 13976 _BCM_AP_COSQ_INDEX_STYLE_UCAST_QUEUE, 13977 &local_port, &startq, NULL)); 13978 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 13979 return BCM_E_PARAM; 13980 } else { 13981 from_cos = to_cos = cosq; 13982 BCM_IF_ERROR_RETURN 13983 (_bcm_ap_cosq_localport_resolve(unit, gport, &local_port)); 13984 if (local_port < 0) { 13985 return BCM_E_PORT; 13986 } 13987 for (ci = from_cos; ci <= to_cos; ci++) { 13988 BCM_IF_ERROR_RETURN 13989 (_bcm_ap_cosq_index_resolve(unit, local_port, ci, 13990 _BCM_AP_COSQ_INDEX_STYLE_UCAST_QUEUE, 13991 NULL, &startq, NULL)); 13992 } 13993 } 13994 mem = MMU_THDU_XPIPE_CONFIG_QUEUEm; 13995 13996 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, 13997 startq, entry)); 13998 *arg = soc_mem_field32_get(unit, mem, entry, Q_LIMIT_DYNAMIC_CELLf); 13999 } else if (type == bcmCosqControlEgressMCSharedDynamicEnable) { 14000 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 14001 return BCM_E_PARAM; 14002 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 14003 BCM_IF_ERROR_RETURN 14004 (_bcm_ap_cosq_index_resolve(unit, gport, cosq, 14005 _BCM_AP_COSQ_INDEX_STYLE_MCAST_QUEUE, 14006 &local_port, &startq, NULL)); 14007 } 14008 else { 14009 from_cos = to_cos = cosq; 14010 BCM_IF_ERROR_RETURN 14011 (_bcm_ap_cosq_localport_resolve(unit, gport, &local_port)); 14012 if (local_port < 0) { 14013 return BCM_E_PORT; 14014 } 14015 for (ci = from_cos; ci <= to_cos; ci++) { 14016 BCM_IF_ERROR_RETURN 14017 (_bcm_ap_cosq_index_resolve(unit, local_port, ci, 14018 _BCM_AP_COSQ_INDEX_STYLE_MCAST_QUEUE, 14019 NULL, &startq, NULL)); 14020 } 14021 } 14022 mem = MMU_THDM_DB_QUEUE_CONFIG_0m; 14023 14024 startq -= _BCM_AP_NUM_L2_UC_LEAVES; /* MC queues comes after UC queues */ 14025 BCM_IF_ERROR_RETURN 14026 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 14027 *arg = soc_mem_field32_get(unit, mem, entry, Q_LIMIT_DYNAMICf); 14028 } else { 14029 return BCM_E_PARAM; 14030 } 14031 14032 return BCM_E_NONE; 14033 } 14034 /* 14035 * Function: _bcm_ap_cosq_egr_queue_color_limit_set 14036 * Purpose: Set Red and Yellow color limit per queue 14037 * IF color mode dynamic: limit should be between 0-7 14038 * 0: 100% of green threshold 14039 * 1: 12.5% of green threshold 14040 * 2: 25% of green threshold 14041 * 3: 37.5% of green threshold 14042 * 4: 50% of green threshold 14043 * 5: 67.5% of green threshold 14044 * 6: 75% of green threshold 14045 * 7: 87.5% of green threshold 14046 * If color mode static: Limit is number of bytes 14047 */ 14048 14049 STATIC int 14050 _bcm_ap_cosq_egr_queue_color_limit_set(int unit, bcm_gport_t gport, 14051 bcm_cos_queue_t cosq, 14052 bcm_cosq_control_t type, 14053 int arg) 14054 { 14055 bcm_port_t local_port; 14056 int startq; 14057 uint32 entry[SOC_MAX_MEM_WORDS]; 14058 soc_mem_t mem = INVALIDm; 14059 soc_field_t fld_limit = INVALIDf; 14060 int color_mode, granularity, max_val; 14061 14062 if (arg < 0) { 14063 return BCM_E_PARAM; 14064 } 14065 granularity = 8; 14066 14067 if ((type == bcmCosqControlEgressUCQueueRedLimit) || 14068 (type == bcmCosqControlEgressUCQueueYellowLimit)) { 14069 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 14070 BCM_IF_ERROR_RETURN 14071 (_bcm_ap_cosq_index_resolve(unit, gport, cosq, 14072 _BCM_AP_COSQ_INDEX_STYLE_UCAST_QUEUE, 14073 &local_port, &startq, NULL)); 14074 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 14075 return BCM_E_PARAM; 14076 } else { 14077 if (cosq < 0) { 14078 return BCM_E_PARAM; 14079 } 14080 BCM_IF_ERROR_RETURN 14081 (_bcm_ap_cosq_localport_resolve(unit, gport, &local_port)); 14082 if (local_port < 0) { 14083 return BCM_E_PORT; 14084 } 14085 BCM_IF_ERROR_RETURN 14086 (_bcm_ap_cosq_index_resolve 14087 (unit, local_port, cosq, _BCM_AP_COSQ_INDEX_STYLE_UCAST_QUEUE, 14088 NULL, &startq, NULL)); 14089 } 14090 if (type == bcmCosqControlEgressUCQueueRedLimit) { 14091 fld_limit = LIMIT_RED_CELLf; 14092 } else { 14093 fld_limit = LIMIT_YELLOW_CELLf; 14094 } 14095 mem = MMU_THDU_XPIPE_CONFIG_QUEUEm; 14096 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 14097 color_mode = soc_mem_field32_get(unit, mem, entry, Q_COLOR_LIMIT_DYNAMIC_CELLf); 14098 14099 if (color_mode == 1) { /* Dynamic color limit */ 14100 if (arg > 7) { /* Legal values are 0 - 7 */ 14101 return BCM_E_PARAM; 14102 } else { 14103 soc_mem_field32_set(unit, mem, entry, fld_limit, arg); 14104 } 14105 } else { /* Static color limit */ 14106 arg = (arg + _BCM_AP_BYTES_PER_CELL - 1) / _BCM_AP_BYTES_PER_CELL; 14107 14108 /* Check for min/max values */ 14109 max_val = (1 << soc_mem_field_length(unit, mem, fld_limit)) - 1; 14110 if ((arg < 0) || ((arg/granularity) > max_val)) { 14111 return BCM_E_PARAM; 14112 } else { 14113 soc_mem_field32_set(unit, mem, entry, fld_limit, (arg/granularity)); 14114 } 14115 } 14116 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 14117 } else if ((type == bcmCosqControlEgressMCQueueRedLimit) || 14118 (type == bcmCosqControlEgressMCQueueYellowLimit)) { 14119 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 14120 return BCM_E_PARAM; 14121 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 14122 BCM_IF_ERROR_RETURN 14123 (_bcm_ap_cosq_index_resolve(unit, gport, cosq, 14124 _BCM_AP_COSQ_INDEX_STYLE_MCAST_QUEUE, 14125 &local_port, &startq, NULL)); 14126 } else { 14127 if (cosq < 0) { 14128 return BCM_E_PARAM; 14129 } 14130 BCM_IF_ERROR_RETURN 14131 (_bcm_ap_cosq_localport_resolve(unit, gport, &local_port)); 14132 if (local_port < 0) { 14133 return BCM_E_PORT; 14134 } 14135 BCM_IF_ERROR_RETURN 14136 (_bcm_ap_cosq_index_resolve(unit, local_port, cosq, 14137 _BCM_AP_COSQ_INDEX_STYLE_MCAST_QUEUE, 14138 NULL, &startq, NULL)); 14139 } 14140 14141 if (type == bcmCosqControlEgressMCQueueRedLimit) { 14142 fld_limit = RED_SHARED_LIMITf; 14143 } else { 14144 fld_limit = YELLOW_SHARED_LIMITf; 14145 } 14146 mem = MMU_THDM_DB_QUEUE_CONFIG_0m; 14147 startq -= _BCM_AP_NUM_L2_UC_LEAVES; 14148 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 14149 color_mode = soc_mem_field32_get(unit, mem, entry, Q_COLOR_LIMIT_DYNAMICf); 14150 14151 if (color_mode == 1) { /* Dynamic color limit */ 14152 if (arg > 7) { /* Legal values are 0 - 7 */ 14153 return BCM_E_PARAM; 14154 } else { 14155 soc_mem_field32_set(unit, mem, entry, fld_limit, arg); 14156 } 14157 } else { /* Static color limit */ 14158 arg = (arg + _BCM_AP_BYTES_PER_CELL - 1) / _BCM_AP_BYTES_PER_CELL; 14159 14160 /* Check for min/max values */ 14161 max_val = (1 << soc_mem_field_length(unit, mem, fld_limit)) - 1; 14162 if ((arg < 0) || ((arg/granularity) > max_val)) { 14163 return BCM_E_PARAM; 14164 } else { 14165 soc_mem_field32_set(unit, mem, entry, fld_limit, (arg/granularity)); 14166 } 14167 } 14168 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 14169 14170 } else { 14171 return BCM_E_PARAM; 14172 } 14173 14174 return BCM_E_NONE; 14175 } 14176 14177 /* 14178 * Function: _bcm_ap_cosq_egr_queue_color_limit_get 14179 * Purpose: Get Red and Yellow color limit per queue 14180 * Return value: IF color mode dynamic: limit should be between 0-7 14181 * 0: 100% of green threshold 14182 * 1: 12.5% of green threshold 14183 * 2: 25% of green threshold 14184 * 3: 37.5% of green threshold 14185 * 4: 50% of green threshold 14186 * 5: 67.5% of green threshold 14187 * 6: 75% of green threshold 14188 * 7: 87.5% of green threshold 14189 * If color mode static: Limit is number of bytes 14190 */ 14191 14192 STATIC int 14193 _bcm_ap_cosq_egr_queue_color_limit_get(int unit, bcm_gport_t gport, 14194 bcm_cos_queue_t cosq, 14195 bcm_cosq_control_t type, 14196 int* arg) 14197 { 14198 bcm_port_t local_port; 14199 int startq; 14200 uint32 entry[SOC_MAX_MEM_WORDS]; 14201 soc_mem_t mem = INVALIDm; 14202 soc_field_t fld_limit = INVALIDf; 14203 int color_mode, granularity; 14204 14205 if (arg == NULL) { 14206 return BCM_E_PARAM; 14207 } 14208 14209 granularity = 8; 14210 14211 if ((type == bcmCosqControlEgressUCQueueRedLimit) || 14212 (type == bcmCosqControlEgressUCQueueYellowLimit)) { 14213 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 14214 BCM_IF_ERROR_RETURN 14215 (_bcm_ap_cosq_index_resolve(unit, gport, cosq, 14216 _BCM_AP_COSQ_INDEX_STYLE_UCAST_QUEUE, 14217 &local_port, &startq, NULL)); 14218 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 14219 return BCM_E_PARAM; 14220 } else { 14221 if (cosq < 0) { 14222 return BCM_E_PARAM; 14223 } 14224 BCM_IF_ERROR_RETURN 14225 (_bcm_ap_cosq_localport_resolve(unit, gport, &local_port)); 14226 if (local_port < 0) { 14227 return BCM_E_PORT; 14228 } 14229 BCM_IF_ERROR_RETURN 14230 (_bcm_ap_cosq_index_resolve 14231 (unit, local_port, cosq, _BCM_AP_COSQ_INDEX_STYLE_UCAST_QUEUE, 14232 NULL, &startq, NULL)); 14233 } 14234 14235 if (type == bcmCosqControlEgressUCQueueRedLimit) { 14236 fld_limit = LIMIT_RED_CELLf; 14237 } else { 14238 fld_limit = LIMIT_YELLOW_CELLf; 14239 } 14240 mem = MMU_THDU_XPIPE_CONFIG_QUEUEm; 14241 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 14242 color_mode = soc_mem_field32_get(unit, mem, entry, Q_COLOR_LIMIT_DYNAMIC_CELLf); 14243 14244 if (color_mode == 1) { /* Dynamic color limit */ 14245 *arg = soc_mem_field32_get(unit, mem, entry, fld_limit); 14246 } else { /* Static color limit */ 14247 *arg = soc_mem_field32_get(unit, mem, entry, fld_limit); 14248 *arg = (*arg) * granularity * _BCM_AP_BYTES_PER_CELL; 14249 } 14250 } else if ((type == bcmCosqControlEgressMCQueueRedLimit) || 14251 (type == bcmCosqControlEgressMCQueueYellowLimit)) { 14252 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 14253 return BCM_E_PARAM; 14254 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 14255 BCM_IF_ERROR_RETURN 14256 (_bcm_ap_cosq_index_resolve(unit, gport, cosq, 14257 _BCM_AP_COSQ_INDEX_STYLE_MCAST_QUEUE, 14258 &local_port, &startq, NULL)); 14259 } else { 14260 if (cosq < 0) { 14261 return BCM_E_PARAM; 14262 } 14263 BCM_IF_ERROR_RETURN 14264 (_bcm_ap_cosq_localport_resolve(unit, gport, &local_port)); 14265 if (local_port < 0) { 14266 return BCM_E_PORT; 14267 } 14268 BCM_IF_ERROR_RETURN 14269 (_bcm_ap_cosq_index_resolve(unit, local_port, cosq, 14270 _BCM_AP_COSQ_INDEX_STYLE_MCAST_QUEUE, 14271 NULL, &startq, NULL)); 14272 } 14273 14274 if (type == bcmCosqControlEgressMCQueueRedLimit) { 14275 fld_limit = RED_SHARED_LIMITf; 14276 } else { 14277 fld_limit = YELLOW_SHARED_LIMITf; 14278 } 14279 mem = MMU_THDM_DB_QUEUE_CONFIG_0m; 14280 startq -= _BCM_AP_NUM_L2_UC_LEAVES; 14281 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 14282 color_mode = soc_mem_field32_get(unit, mem, entry, Q_COLOR_LIMIT_DYNAMICf); 14283 14284 if (color_mode == 1) { /* Dynamic color limit */ 14285 *arg = soc_mem_field32_get(unit, mem, entry, fld_limit); 14286 } else { /* Static color limit */ 14287 *arg = soc_mem_field32_get(unit, mem, entry, fld_limit); 14288 *arg = (*arg) * granularity * _BCM_AP_BYTES_PER_CELL; 14289 } 14290 14291 } else { 14292 return BCM_E_PARAM; 14293 } 14294 14295 return BCM_E_NONE; 14296 } 14297 14298 14299 /* 14300 * Function: _bcm_ap_cosq_egr_queue_color_limit_mode_set 14301 * Purpose: Set color limit mode per queue to static (0) or 14302 * dynamic (1) 14303 */ 14304 14305 STATIC int 14306 _bcm_ap_cosq_egr_queue_color_limit_mode_set(int unit, bcm_gport_t gport, 14307 bcm_cos_queue_t cosq, 14308 bcm_cosq_control_t type, 14309 int arg) 14310 { 14311 bcm_port_t local_port; 14312 int startq; 14313 uint32 entry[SOC_MAX_MEM_WORDS]; 14314 soc_mem_t mem = INVALIDm; 14315 int enable; 14316 14317 if (arg < 0) { 14318 return BCM_E_PARAM; 14319 } 14320 14321 arg = arg ? 1 : 0; 14322 14323 if (type == bcmCosqControlEgressUCQueueColorLimitDynamicEnable) { 14324 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 14325 BCM_IF_ERROR_RETURN 14326 (_bcm_ap_cosq_index_resolve(unit, gport, cosq, 14327 _BCM_AP_COSQ_INDEX_STYLE_UCAST_QUEUE, 14328 &local_port, &startq, NULL)); 14329 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 14330 return BCM_E_PARAM; 14331 } else { 14332 if (cosq < 0) { 14333 return BCM_E_PARAM; 14334 } 14335 BCM_IF_ERROR_RETURN 14336 (_bcm_ap_cosq_localport_resolve(unit, gport, &local_port)); 14337 if (local_port < 0) { 14338 return BCM_E_PORT; 14339 } 14340 BCM_IF_ERROR_RETURN 14341 (_bcm_ap_cosq_index_resolve 14342 (unit, local_port, cosq, _BCM_AP_COSQ_INDEX_STYLE_UCAST_QUEUE, 14343 NULL, &startq, NULL)); 14344 } 14345 mem = MMU_THDU_XPIPE_CONFIG_QUEUEm; 14346 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 14347 enable = soc_mem_field32_get(unit, mem, entry, Q_COLOR_LIMIT_DYNAMIC_CELLf); 14348 if (enable != arg) { 14349 soc_mem_field32_set(unit, mem, entry, Q_COLOR_LIMIT_DYNAMIC_CELLf, arg); 14350 /* Reset the Red and Yellow limits when color limit mode is changed */ 14351 soc_mem_field32_set(unit, mem, entry, LIMIT_RED_CELLf, 0); 14352 soc_mem_field32_set(unit, mem, entry, LIMIT_YELLOW_CELLf, 0); 14353 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 14354 } 14355 } else if (type == bcmCosqControlEgressMCQueueColorLimitDynamicEnable) { 14356 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 14357 return BCM_E_PARAM; 14358 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 14359 BCM_IF_ERROR_RETURN 14360 (_bcm_ap_cosq_index_resolve(unit, gport, cosq, 14361 _BCM_AP_COSQ_INDEX_STYLE_MCAST_QUEUE, 14362 &local_port, &startq, NULL)); 14363 } else { 14364 if (cosq < 0) { 14365 return BCM_E_PARAM; 14366 } 14367 BCM_IF_ERROR_RETURN 14368 (_bcm_ap_cosq_localport_resolve(unit, gport, &local_port)); 14369 if (local_port < 0) { 14370 return BCM_E_PORT; 14371 } 14372 BCM_IF_ERROR_RETURN 14373 (_bcm_ap_cosq_index_resolve(unit, local_port, cosq, 14374 _BCM_AP_COSQ_INDEX_STYLE_MCAST_QUEUE, 14375 NULL, &startq, NULL)); 14376 } 14377 mem = MMU_THDM_DB_QUEUE_CONFIG_0m; 14378 startq -= _BCM_AP_NUM_L2_UC_LEAVES; 14379 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 14380 enable = soc_mem_field32_get(unit, mem, entry, Q_COLOR_LIMIT_DYNAMICf); 14381 if (enable != arg) { 14382 soc_mem_field32_set(unit, mem, entry, Q_COLOR_LIMIT_DYNAMICf, arg); 14383 /* Reset the Red and Yellow limits when color limit mode is changed */ 14384 soc_mem_field32_set(unit, mem, entry, RED_SHARED_LIMITf, 0); 14385 soc_mem_field32_set(unit, mem, entry, YELLOW_SHARED_LIMITf, 0); 14386 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 14387 } 14388 } else { 14389 return BCM_E_PARAM; 14390 } 14391 14392 return BCM_E_NONE; 14393 } 14394 14395 /* 14396 * Function: _bcm_ap_cosq_egr_queue_color_limit_mode_get 14397 * Purpose: Get color limit mode per queue. 14398 * Returns: 0 (static) or 1 (dynamic) 14399 */ 14400 STATIC int 14401 _bcm_ap_cosq_egr_queue_color_limit_mode_get(int unit, bcm_gport_t gport, 14402 bcm_cos_queue_t cosq, 14403 bcm_cosq_control_t type, 14404 int* arg) 14405 { 14406 bcm_port_t local_port; 14407 int startq; 14408 uint32 entry[SOC_MAX_MEM_WORDS]; 14409 soc_mem_t mem = INVALIDm; 14410 14411 if (arg == NULL) { 14412 return BCM_E_PARAM; 14413 } 14414 14415 if (type == bcmCosqControlEgressUCQueueColorLimitDynamicEnable) { 14416 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 14417 BCM_IF_ERROR_RETURN 14418 (_bcm_ap_cosq_index_resolve(unit, gport, cosq, 14419 _BCM_AP_COSQ_INDEX_STYLE_UCAST_QUEUE, 14420 &local_port, &startq, NULL)); 14421 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 14422 return BCM_E_PARAM; 14423 } else { 14424 if (cosq < 0) { 14425 return BCM_E_PARAM; 14426 } 14427 BCM_IF_ERROR_RETURN 14428 (_bcm_ap_cosq_localport_resolve(unit, gport, &local_port)); 14429 if (local_port < 0) { 14430 return BCM_E_PORT; 14431 } 14432 BCM_IF_ERROR_RETURN 14433 (_bcm_ap_cosq_index_resolve 14434 (unit, local_port, cosq, _BCM_AP_COSQ_INDEX_STYLE_UCAST_QUEUE, 14435 NULL, &startq, NULL)); 14436 } 14437 mem = MMU_THDU_XPIPE_CONFIG_QUEUEm; 14438 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 14439 *arg = soc_mem_field32_get(unit, mem, entry, Q_COLOR_LIMIT_DYNAMIC_CELLf); 14440 } else if (type == bcmCosqControlEgressMCQueueColorLimitDynamicEnable) { 14441 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 14442 return BCM_E_PARAM; 14443 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 14444 BCM_IF_ERROR_RETURN 14445 (_bcm_ap_cosq_index_resolve(unit, gport, cosq, 14446 _BCM_AP_COSQ_INDEX_STYLE_MCAST_QUEUE, 14447 &local_port, &startq, NULL)); 14448 } else { 14449 if (cosq < 0) { 14450 return BCM_E_PARAM; 14451 } 14452 BCM_IF_ERROR_RETURN 14453 (_bcm_ap_cosq_localport_resolve(unit, gport, &local_port)); 14454 if (local_port < 0) { 14455 return BCM_E_PORT; 14456 } 14457 BCM_IF_ERROR_RETURN 14458 (_bcm_ap_cosq_index_resolve(unit, local_port, cosq, 14459 _BCM_AP_COSQ_INDEX_STYLE_MCAST_QUEUE, 14460 NULL, &startq, NULL)); 14461 } 14462 mem = MMU_THDM_DB_QUEUE_CONFIG_0m; 14463 startq -= _BCM_AP_NUM_L2_UC_LEAVES; 14464 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 14465 *arg = soc_mem_field32_get(unit, mem, entry, Q_COLOR_LIMIT_DYNAMICf); 14466 } else { 14467 return BCM_E_PARAM; 14468 } 14469 14470 return BCM_E_NONE; 14471 } 14472 14473 STATIC int 14474 _bcm_ap_cosq_egr_queue_limit_enable_set(int unit, bcm_gport_t gport, 14475 bcm_cos_queue_t cosq, 14476 bcm_cosq_control_t type, 14477 int arg) 14478 { 14479 bcm_port_t local_port; 14480 int startq; 14481 uint32 entry[SOC_MAX_MEM_WORDS]; 14482 soc_mem_t mem = INVALIDm; 14483 soc_field_t fld_name = INVALIDf; 14484 int enable; 14485 14486 if (arg < 0) { 14487 return BCM_E_PARAM; 14488 } 14489 14490 arg = arg ? 1 : 0; 14491 14492 if ((type == bcmCosqControlEgressUCQueueLimitEnable) || 14493 (type == bcmCosqControlEgressUCQueueColorLimitEnable)) { 14494 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 14495 BCM_IF_ERROR_RETURN 14496 (_bcm_ap_cosq_index_resolve(unit, gport, cosq, 14497 _BCM_AP_COSQ_INDEX_STYLE_UCAST_QUEUE, 14498 &local_port, &startq, NULL)); 14499 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 14500 return BCM_E_PARAM; 14501 } else { 14502 if (cosq < 0) { 14503 return BCM_E_PARAM; 14504 } 14505 BCM_IF_ERROR_RETURN 14506 (_bcm_ap_cosq_localport_resolve(unit, gport, &local_port)); 14507 if (local_port < 0) { 14508 return BCM_E_PORT; 14509 } 14510 BCM_IF_ERROR_RETURN 14511 (_bcm_ap_cosq_index_resolve 14512 (unit, local_port, cosq, _BCM_AP_COSQ_INDEX_STYLE_UCAST_QUEUE, 14513 NULL, &startq, NULL)); 14514 } 14515 14516 mem = MMU_THDU_XPIPE_Q_TO_QGRP_MAPm; 14517 if (type == bcmCosqControlEgressUCQueueLimitEnable) { 14518 fld_name = Q_LIMIT_ENABLEf; 14519 } else if (type == bcmCosqControlEgressUCQueueColorLimitEnable) { 14520 fld_name = Q_COLOR_ENABLE_CELLf; 14521 } 14522 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 14523 enable = soc_mem_field32_get(unit, mem, entry, fld_name); 14524 if (enable != arg) { 14525 soc_mem_field32_set(unit, mem, entry, fld_name, arg); 14526 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 14527 } 14528 }else if (type == bcmCosqControlEgressMCQueueLimitEnable) { 14529 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 14530 return BCM_E_PARAM; 14531 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 14532 BCM_IF_ERROR_RETURN 14533 (_bcm_ap_cosq_index_resolve(unit, gport, cosq, 14534 _BCM_AP_COSQ_INDEX_STYLE_MCAST_QUEUE, 14535 &local_port, &startq, NULL)); 14536 } else { 14537 if (cosq < 0) { 14538 return BCM_E_PARAM; 14539 } 14540 BCM_IF_ERROR_RETURN 14541 (_bcm_ap_cosq_localport_resolve(unit, gport, &local_port)); 14542 if (local_port < 0) { 14543 return BCM_E_PORT; 14544 } 14545 BCM_IF_ERROR_RETURN 14546 (_bcm_ap_cosq_index_resolve(unit, local_port, cosq, 14547 _BCM_AP_COSQ_INDEX_STYLE_MCAST_QUEUE, 14548 NULL, &startq, NULL)); 14549 } 14550 startq -= _BCM_AP_NUM_L2_UC_LEAVES; /* MC queues comes after UC queues */ 14551 14552 mem = MMU_THDM_MCQE_QUEUE_CONFIG_0m; 14553 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 14554 enable = soc_mem_field32_get(unit, mem, entry, Q_LIMIT_ENABLEf); 14555 if (enable != arg) { 14556 soc_mem_field32_set(unit, mem, entry, Q_LIMIT_ENABLEf, arg); 14557 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 14558 } 14559 14560 mem = MMU_THDM_DB_QUEUE_CONFIG_0m; 14561 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 14562 enable = soc_mem_field32_get(unit, mem, entry, Q_LIMIT_ENABLEf); 14563 if (enable != arg) { 14564 soc_mem_field32_set(unit, mem, entry, Q_LIMIT_ENABLEf, arg); 14565 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 14566 } 14567 } else if (type == bcmCosqControlEgressMCQueueColorLimitEnable) { 14568 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 14569 return BCM_E_PARAM; 14570 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 14571 BCM_IF_ERROR_RETURN 14572 (_bcm_ap_cosq_index_resolve(unit, gport, cosq, 14573 _BCM_AP_COSQ_INDEX_STYLE_MCAST_QUEUE, 14574 &local_port, &startq, NULL)); 14575 } else { 14576 if (cosq < 0) { 14577 return BCM_E_PARAM; 14578 } 14579 BCM_IF_ERROR_RETURN 14580 (_bcm_ap_cosq_localport_resolve(unit, gport, &local_port)); 14581 if (local_port < 0) { 14582 return BCM_E_PORT; 14583 } 14584 BCM_IF_ERROR_RETURN 14585 (_bcm_ap_cosq_index_resolve(unit, local_port, cosq, 14586 _BCM_AP_COSQ_INDEX_STYLE_MCAST_QUEUE, 14587 NULL, &startq, NULL)); 14588 } 14589 14590 startq -= _BCM_AP_NUM_L2_UC_LEAVES; /* MC queues comes after UC queues */ 14591 14592 mem = MMU_THDM_MCQE_QUEUE_CONFIG_0m; 14593 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 14594 enable = soc_mem_field32_get(unit, mem, entry, Q_COLOR_LIMIT_ENABLEf); 14595 if (enable != arg) { 14596 soc_mem_field32_set(unit, mem, entry, Q_COLOR_LIMIT_ENABLEf, arg); 14597 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 14598 } 14599 14600 mem = MMU_THDM_DB_QUEUE_CONFIG_0m; 14601 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 14602 enable = soc_mem_field32_get(unit, mem, entry, Q_COLOR_LIMIT_ENABLEf); 14603 if (enable != arg) { 14604 soc_mem_field32_set(unit, mem, entry, Q_COLOR_LIMIT_ENABLEf, arg); 14605 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 14606 } 14607 } else { 14608 return BCM_E_PARAM; 14609 } 14610 14611 return BCM_E_NONE; 14612 } 14613 14614 /* 14615 * Function: 14616 * _bcm_ap_cosq_qgroup_limit_enable_set 14617 * Purpose: 14618 * Enable/Disable COS queue Queue group 14619 * Parameters: 14620 * unit - (IN) unit number 14621 * gport - (IN) GPORT identifier 14622 * cosq - (IN) COS queue to configure 14623 * type - (IN) Operation type 14624 * enable - (IN) Enable/Disable 14625 * Returns: 14626 * BCM_E_XXX 14627 */ 14628 STATIC int 14629 _bcm_ap_cosq_qgroup_limit_enable_set(int unit, bcm_gport_t gport, 14630 bcm_cos_queue_t cosq, bcm_cosq_control_t type, int enable) 14631 { 14632 bcm_port_t local_port; 14633 soc_mem_t mem = INVALIDm; 14634 soc_field_t field = INVALIDf; 14635 uint32 entry[SOC_MAX_MEM_WORDS]; 14636 int startq; 14637 int qgroup_valid; 14638 14639 if (!((enable == 0) || (enable == 1))) { 14640 return BCM_E_PARAM; 14641 } 14642 14643 if ((type == bcmCosqControlEgressUCQueueGroupMinEnable) || 14644 (type == bcmCosqControlEgressUCQueueGroupSharedLimitEnable) || 14645 (type == bcmCosqControlEgressUCQueueGroupSharedDynamicEnable)) { 14646 14647 /* Resolve cosq for port or take from input argument */ 14648 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 14649 BCM_IF_ERROR_RETURN 14650 (_bcm_ap_cosq_index_resolve(unit, gport, cosq, 14651 _BCM_AP_COSQ_INDEX_STYLE_UCAST_QUEUE, 14652 &local_port, &startq, NULL)); 14653 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 14654 /* Operation not valid for the multicast queue */ 14655 return BCM_E_PARAM; 14656 } else { 14657 if (cosq < -1) { 14658 return BCM_E_PARAM; 14659 } 14660 BCM_IF_ERROR_RETURN 14661 (_bcm_ap_cosq_localport_resolve(unit, gport, &local_port)); 14662 if (local_port < 0) { 14663 return BCM_E_PORT; 14664 } 14665 14666 BCM_IF_ERROR_RETURN 14667 (_bcm_ap_cosq_index_resolve(unit, local_port, cosq, 14668 _BCM_AP_COSQ_INDEX_STYLE_UCAST_QUEUE, 14669 NULL, &startq, NULL)); 14670 } /* if BCM_GPORT_IS_UCAST_QUEUE_GROUP */ 14671 14672 /* Update Table */ 14673 mem = MMU_THDU_XPIPE_Q_TO_QGRP_MAPm; 14674 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, 14675 startq, entry)); 14676 qgroup_valid = soc_mem_field32_get(unit, mem, entry, QGROUP_VALIDf); 14677 if (!qgroup_valid) { 14678 LOG_INFO(BSL_LS_BCM_COSQ, 14679 (BSL_META_U(unit, 14680 "UCQ doesn't associate with a queue group!\n"))); 14681 return BCM_E_UNAVAIL; 14682 } 14683 14684 if (type == bcmCosqControlEgressUCQueueGroupMinEnable) { 14685 field = USE_QGROUP_MINf; 14686 } else if (type == bcmCosqControlEgressUCQueueGroupSharedLimitEnable) { 14687 field = QGROUP_LIMIT_ENABLEf; 14688 } else if (type == bcmCosqControlEgressUCQueueGroupSharedDynamicEnable) { 14689 startq = soc_mem_field32_get(unit, mem, entry, QGROUPf); 14690 mem = MMU_THDU_XPIPE_CONFIG_QGROUPm; 14691 field = Q_LIMIT_DYNAMIC_CELLf; 14692 } 14693 if ((mem != INVALIDm) && (field != INVALIDf)) { 14694 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 14695 soc_mem_field32_set(unit, mem, entry, field, enable); 14696 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 14697 } 14698 } else { 14699 return BCM_E_PARAM; 14700 } /* If type */ 14701 14702 return BCM_E_NONE; 14703 } 14704 14705 /* 14706 * Function: 14707 * _bcm_ap_cosq_qgroup_limit_enable_get 14708 * Purpose: 14709 * Enable/Disable COS queue Queue group 14710 * Parameters: 14711 * unit - (IN) unit number 14712 * gport - (IN) GPORT identifier 14713 * cosq - (IN) COS queue to configure 14714 * type - (IN) Operation type 14715 * enable - (OUT) Enable/Disable status 14716 * Returns: 14717 * BCM_E_XXX 14718 */ 14719 STATIC int 14720 _bcm_ap_cosq_qgroup_limit_enable_get(int unit, bcm_gport_t gport, 14721 bcm_cos_queue_t cosq, bcm_cosq_control_t type, int *enable) 14722 { 14723 bcm_port_t local_port; 14724 soc_mem_t mem = INVALIDm; 14725 uint32 entry[SOC_MAX_MEM_WORDS], valid; 14726 int startq; 14727 soc_field_t field = INVALIDf; 14728 14729 if ((type == bcmCosqControlEgressUCQueueGroupMinEnable) || 14730 (type == bcmCosqControlEgressUCQueueGroupSharedLimitEnable) || 14731 (type == bcmCosqControlEgressUCQueueGroupSharedDynamicEnable)) { 14732 /* Resolve cosq for port or take from input argument */ 14733 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 14734 BCM_IF_ERROR_RETURN 14735 (_bcm_ap_cosq_index_resolve(unit, gport, cosq, 14736 _BCM_AP_COSQ_INDEX_STYLE_UCAST_QUEUE, 14737 &local_port, &startq, NULL)); 14738 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 14739 /* Operation not valid for the multicast queue */ 14740 return BCM_E_PARAM; 14741 } else { 14742 if (cosq < -1) { 14743 return BCM_E_PARAM; 14744 } 14745 BCM_IF_ERROR_RETURN 14746 (_bcm_ap_cosq_localport_resolve(unit, gport, &local_port)); 14747 if (local_port < 0) { 14748 return BCM_E_PORT; 14749 } 14750 14751 BCM_IF_ERROR_RETURN 14752 (_bcm_ap_cosq_index_resolve(unit, local_port, cosq, 14753 _BCM_AP_COSQ_INDEX_STYLE_UCAST_QUEUE, 14754 NULL, &startq, NULL)); 14755 } /* if BCM_GPORT_IS_UCAST_QUEUE_GROUP */ 14756 14757 /* Retireve data from the table */ 14758 mem = MMU_THDU_XPIPE_Q_TO_QGRP_MAPm; 14759 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, 14760 startq, entry)); 14761 valid = soc_mem_field32_get(unit, mem, entry, QGROUP_VALIDf); 14762 if (!valid) { 14763 LOG_INFO(BSL_LS_BCM_COSQ, 14764 (BSL_META_U(unit, 14765 "UCQ doesn't associate with a queue group!\n"))); 14766 return BCM_E_UNAVAIL; 14767 } 14768 if (type == bcmCosqControlEgressUCQueueGroupMinEnable) { 14769 field = USE_QGROUP_MINf; 14770 } else if (type == bcmCosqControlEgressUCQueueGroupSharedLimitEnable) { 14771 field = QGROUP_LIMIT_ENABLEf; 14772 } else if (type == bcmCosqControlEgressUCQueueGroupSharedDynamicEnable) { 14773 startq = soc_mem_field32_get(unit, mem, entry, QGROUPf); 14774 14775 mem = SOC_TD2_PMEM(unit, local_port, MMU_THDU_XPIPE_CONFIG_QGROUPm, 14776 MMU_THDU_YPIPE_CONFIG_QGROUPm); 14777 field = Q_LIMIT_DYNAMIC_CELLf; 14778 } 14779 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 14780 *enable = soc_mem_field32_get(unit, mem, entry, field); 14781 } else { 14782 return BCM_E_PARAM; 14783 } /* If type */ 14784 14785 return BCM_E_NONE; 14786 } 14787 14788 STATIC int 14789 _bcm_ap_cosq_egr_queue_limit_enable_get(int unit, bcm_gport_t gport, 14790 bcm_cos_queue_t cosq, 14791 bcm_cosq_control_t type, 14792 int *arg) 14793 { 14794 bcm_port_t local_port; 14795 int startq; 14796 uint32 entry[SOC_MAX_MEM_WORDS]; 14797 soc_mem_t mem = INVALIDm; 14798 soc_field_t field_name = INVALIDf; 14799 14800 if ((type == bcmCosqControlEgressUCQueueLimitEnable) || 14801 (type == bcmCosqControlEgressUCQueueColorLimitEnable)) { 14802 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 14803 BCM_IF_ERROR_RETURN 14804 (_bcm_ap_cosq_index_resolve(unit, gport, cosq, 14805 _BCM_AP_COSQ_INDEX_STYLE_UCAST_QUEUE, 14806 &local_port, &startq, NULL)); 14807 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 14808 return BCM_E_PARAM; 14809 } else { 14810 if (cosq < 0) { 14811 return BCM_E_PARAM; 14812 } 14813 BCM_IF_ERROR_RETURN 14814 (_bcm_ap_cosq_localport_resolve(unit, gport, &local_port)); 14815 if (local_port < 0) { 14816 return BCM_E_PORT; 14817 } 14818 BCM_IF_ERROR_RETURN 14819 (_bcm_ap_cosq_index_resolve 14820 (unit, local_port, cosq, _BCM_AP_COSQ_INDEX_STYLE_UCAST_QUEUE, 14821 NULL, &startq, NULL)); 14822 } 14823 14824 mem = MMU_THDU_XPIPE_Q_TO_QGRP_MAPm; 14825 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 14826 if (type == bcmCosqControlEgressUCQueueLimitEnable) { 14827 field_name = Q_LIMIT_ENABLEf; 14828 } else if (type == bcmCosqControlEgressUCQueueColorLimitEnable) { 14829 field_name = Q_COLOR_ENABLE_CELLf; 14830 } 14831 *arg = soc_mem_field32_get(unit, mem, entry, field_name); 14832 }else if ((type == bcmCosqControlEgressMCQueueLimitEnable) || 14833 (type == bcmCosqControlEgressMCQueueColorLimitEnable)) { 14834 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 14835 return BCM_E_PARAM; 14836 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 14837 BCM_IF_ERROR_RETURN 14838 (_bcm_ap_cosq_index_resolve(unit, gport, cosq, 14839 _BCM_AP_COSQ_INDEX_STYLE_MCAST_QUEUE, 14840 &local_port, &startq, NULL)); 14841 } else { 14842 if (cosq < 0) { 14843 return BCM_E_PARAM; 14844 } 14845 BCM_IF_ERROR_RETURN 14846 (_bcm_ap_cosq_localport_resolve(unit, gport, &local_port)); 14847 if (local_port < 0) { 14848 return BCM_E_PORT; 14849 } 14850 BCM_IF_ERROR_RETURN 14851 (_bcm_ap_cosq_index_resolve 14852 (unit, local_port, cosq, _BCM_AP_COSQ_INDEX_STYLE_MCAST_QUEUE, 14853 NULL, &startq, NULL)); 14854 } 14855 mem = MMU_THDM_MCQE_QUEUE_CONFIG_0m; 14856 if (type == bcmCosqControlEgressMCQueueLimitEnable) { 14857 field_name = Q_LIMIT_ENABLEf; 14858 } else if (type == bcmCosqControlEgressMCQueueColorLimitEnable) { 14859 field_name = Q_COLOR_LIMIT_ENABLEf; 14860 } 14861 startq -= _BCM_AP_NUM_L2_UC_LEAVES; /* MC queues comes after UC queues */ 14862 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 14863 *arg = soc_mem_field32_get(unit, mem, entry, field_name); 14864 } else { 14865 return BCM_E_PARAM; 14866 } 14867 14868 return BCM_E_NONE; 14869 } 14870 14871 14872 STATIC int 14873 _bcm_ap_cosq_qgroup_limit_set(int unit, bcm_gport_t gport, 14874 bcm_cos_queue_t cosq, 14875 bcm_cosq_control_t type, 14876 int arg) 14877 { 14878 bcm_port_t local_port; 14879 int startq, granularity = 1; 14880 int cur_val, rv, post_update; 14881 int delta = 0; /* In Cells */ 14882 uint32 entry[SOC_MAX_MEM_WORDS], valid; 14883 uint32 shared_size, spid, max_val, rval = 0; 14884 soc_mem_t mem = INVALIDm; 14885 soc_field_t fld_limit = INVALIDf; 14886 14887 if (arg < 0) { 14888 return BCM_E_PARAM; 14889 } 14890 14891 arg /= _BCM_AP_BYTES_PER_CELL; 14892 14893 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 14894 BCM_IF_ERROR_RETURN 14895 (_bcm_ap_cosq_index_resolve(unit, gport, cosq, 14896 _BCM_AP_COSQ_INDEX_STYLE_UCAST_QUEUE, 14897 &local_port, &startq, NULL)); 14898 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 14899 return BCM_E_PARAM; 14900 } else { 14901 if (cosq < -1) { 14902 return BCM_E_PARAM; 14903 } 14904 BCM_IF_ERROR_RETURN 14905 (_bcm_ap_cosq_localport_resolve(unit, gport, &local_port)); 14906 if (local_port < 0) { 14907 return BCM_E_PORT; 14908 } 14909 BCM_IF_ERROR_RETURN 14910 (_bcm_ap_cosq_index_resolve(unit, local_port, cosq, 14911 _BCM_AP_COSQ_INDEX_STYLE_UCAST_QUEUE, 14912 NULL, &startq, NULL)); 14913 } 14914 14915 mem = MMU_THDU_XPIPE_Q_TO_QGRP_MAPm; 14916 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 14917 spid = soc_mem_field32_get(unit, mem, entry, Q_SPIDf); 14918 valid = soc_mem_field32_get(unit, mem, entry, QGROUP_VALIDf); 14919 if (!valid) { 14920 LOG_INFO(BSL_LS_BCM_COSQ, 14921 (BSL_META_U(unit, 14922 "UCQ doesn't associate with a queue group!\n"))); 14923 return BCM_E_UNAVAIL; 14924 } 14925 14926 startq = soc_mem_field32_get(unit, mem, entry, QGROUPf); 14927 14928 mem = MMU_THDU_XPIPE_CONFIG_QGROUPm; 14929 if (type == bcmCosqControlEgressUCQueueGroupMinLimitBytes) { 14930 fld_limit = Q_MIN_LIMIT_CELLf; 14931 granularity = 1; 14932 } else if (type == bcmCosqControlEgressUCQueueGroupSharedLimitBytes) { 14933 fld_limit = Q_SHARED_LIMIT_CELLf; 14934 granularity = 1; 14935 } else { 14936 return BCM_E_PARAM; 14937 } 14938 14939 /* Recalculate Shared Values if Min Changed */ 14940 SOC_IF_ERROR_RETURN(READ_MMU_THDM_DB_POOL_SHARED_LIMITr(unit, spid, &rval)); 14941 shared_size = soc_reg_field_get(unit, MMU_THDM_DB_POOL_SHARED_LIMITr, 14942 rval, SHARED_LIMITf); 14943 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 14944 cur_val = soc_mem_field32_get(unit, mem, entry, fld_limit); 14945 14946 if ((arg / granularity) > cur_val) { 14947 /* New Min Val > Cur Min Val 14948 * So reduce the Shared values first and then 14949 * Increase the Min Value for given resource 14950 */ 14951 post_update = 0; 14952 } else if ((arg / granularity) < cur_val) { 14953 /* New Min Val < Cur Min Val 14954 * So reduce the Min values first and then 14955 * Increase Shared values everywhere 14956 */ 14957 post_update = 1; 14958 } else { 14959 return BCM_E_NONE; 14960 } 14961 14962 if (!post_update && 14963 (type == bcmCosqControlEgressUCQueueGroupMinLimitBytes)) { 14964 delta = ((arg / granularity) - cur_val) * granularity; 14965 if (delta > shared_size) { 14966 return BCM_E_RESOURCE; 14967 } 14968 rv = soc_apache_mmu_config_res_limits_update(unit, spid, 14969 shared_size - delta, 1); 14970 if (rv < 0) { 14971 return rv; 14972 } 14973 } 14974 14975 /* Check for min/max values */ 14976 max_val = (1 << soc_mem_field_length(unit, mem, fld_limit)) - 1; 14977 if ((arg < 0) || ((arg/granularity) > max_val)) { 14978 return BCM_E_PARAM; 14979 } else { 14980 /* Get the latest entry data and update. */ 14981 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 14982 soc_mem_field32_set(unit, mem, entry, fld_limit, (arg/granularity)); 14983 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry)); 14984 } 14985 14986 if (post_update && 14987 (type == bcmCosqControlEgressUCQueueGroupMinLimitBytes)) { 14988 delta = (cur_val - (arg / granularity)) * granularity; 14989 rv = soc_apache_mmu_config_res_limits_update(unit, spid, 14990 shared_size + delta, 0); 14991 if (rv < 0) { 14992 return rv; 14993 } 14994 } 14995 14996 return BCM_E_NONE; 14997 } 14998 14999 STATIC int 15000 _bcm_ap_cosq_qgroup_limit_get(int unit, bcm_gport_t gport, 15001 bcm_cos_queue_t cosq, 15002 bcm_cosq_control_t type, 15003 int *arg) 15004 { 15005 bcm_port_t local_port; 15006 int startq, granularity = 1; 15007 uint32 entry[SOC_MAX_MEM_WORDS], valid; 15008 soc_mem_t mem = INVALIDm; 15009 soc_field_t fld_limit = INVALIDf; 15010 15011 if (!arg) { 15012 return BCM_E_PARAM; 15013 } 15014 15015 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { 15016 BCM_IF_ERROR_RETURN 15017 (_bcm_ap_cosq_index_resolve(unit, gport, cosq, 15018 _BCM_AP_COSQ_INDEX_STYLE_UCAST_QUEUE, 15019 &local_port, &startq, NULL)); 15020 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) { 15021 return BCM_E_PARAM; 15022 } else { 15023 if (cosq < -1) { 15024 return BCM_E_PARAM; 15025 } 15026 BCM_IF_ERROR_RETURN 15027 (_bcm_ap_cosq_localport_resolve(unit, gport, &local_port)); 15028 if (local_port < 0) { 15029 return BCM_E_PORT; 15030 } 15031 BCM_IF_ERROR_RETURN 15032 (_bcm_ap_cosq_index_resolve(unit, local_port, cosq, 15033 _BCM_AP_COSQ_INDEX_STYLE_UCAST_QUEUE, 15034 NULL, &startq, NULL)); 15035 } 15036 15037 mem = MMU_THDU_XPIPE_Q_TO_QGRP_MAPm; 15038 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 15039 valid = soc_mem_field32_get(unit, mem, entry, QGROUP_VALIDf); 15040 if (!valid) { 15041 LOG_INFO(BSL_LS_BCM_COSQ, 15042 (BSL_META_U(unit, 15043 "UCQ doesn't associate with a queue group!\n"))); 15044 return BCM_E_UNAVAIL; 15045 } 15046 15047 startq = soc_mem_field32_get(unit, mem, entry, QGROUPf); 15048 15049 mem = MMU_THDU_XPIPE_CONFIG_QGROUPm; 15050 if (type == bcmCosqControlEgressUCQueueGroupMinLimitBytes) { 15051 fld_limit = Q_MIN_LIMIT_CELLf; 15052 granularity = 1; 15053 } else if (type == bcmCosqControlEgressUCQueueGroupSharedLimitBytes) { 15054 fld_limit = Q_SHARED_LIMIT_CELLf; 15055 granularity = 1; 15056 } else { 15057 return BCM_E_PARAM; 15058 } 15059 15060 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry)); 15061 *arg = soc_mem_field32_get(unit, mem, entry, fld_limit); 15062 *arg = (*arg) * granularity * _BCM_AP_BYTES_PER_CELL; 15063 15064 return BCM_E_NONE; 15065 } 15066 15067 STATIC 15068 int _bcm_ap_cosq_obm_threshold_get_reg_field(bcm_cos_queue_t cosq, 15069 bcm_cosq_control_t type, 15070 int *reg_index, soc_field_t *field) 15071 { 15072 15073 switch (cosq) { 15074 case BCM_COSQ_OBM_CLASS_LOSSLESS0: 15075 *reg_index = 0; 15076 *field = LOSSLESS0_DISCARDf; 15077 break; 15078 case BCM_COSQ_OBM_CLASS_LOSSLESS1: 15079 *reg_index = 0; 15080 *field = LOSSLESS1_DISCARDf; 15081 break; 15082 case BCM_COSQ_OBM_CLASS_LOSSY_LOW: 15083 *reg_index = 0; 15084 *field = LOSSY_LOW_PRIf; 15085 break; 15086 case BCM_COSQ_OBM_CLASS_LOSSY: 15087 *reg_index = 0; 15088 if (type == bcmCosqControlObmDiscardLimit) { 15089 *field = LOSSY_DISCARDf; 15090 } else { /*type must be bcmCosqControlObmMinLimit */ 15091 *field = LOSSY_MINf; 15092 } 15093 break; 15094 case BCM_COSQ_OBM_CLASS_ALL: 15095 *reg_index = 0; 15096 *field = DISCARD_LIMITf; 15097 break; 15098 default: 15099 return BCM_E_PARAM; 15100 } 15101 return BCM_E_NONE; 15102 } 15103 15104 STATIC 15105 int _bcm_ap_cosq_obm_threshold_set_get(int unit, bcm_gport_t gport, 15106 bcm_cos_queue_t cosq, 15107 bcm_cosq_control_t type, 15108 int *arg, int set) 15109 { 15110 soc_info_t *si; 15111 int pgw, pgw_inst, subport, obm; 15112 int phy_port; 15113 bcm_port_t port; 15114 int reg_index; 15115 soc_reg_t reg; 15116 soc_field_t field; 15117 uint64 rval64; 15118 15119 static const soc_reg_t obm_threshold_regs[][9] = { 15120 {IDB_OBM0_THRESHOLDr, IDB_OBM1_THRESHOLDr, 15121 IDB_OBM2_THRESHOLDr, IDB_OBM3_THRESHOLDr, 15122 IDB_OBM4_THRESHOLDr, IDB_OBM5_THRESHOLDr, 15123 IDB_OBM6_THRESHOLDr, IDB_OBM7_THRESHOLDr, 15124 IDB_OBM8_THRESHOLDr} 15125 }; 15126 15127 si = &SOC_INFO(unit); 15128 BCM_IF_ERROR_RETURN(bcm_esw_port_local_get(unit, gport, &port)); 15129 phy_port = si->port_l2p_mapping[port]; 15130 15131 if (phy_port == -1) { 15132 return BCM_E_PARAM; 15133 } 15134 15135 if (IS_CPU_PORT(unit, port) || IS_LB_PORT(unit, port)) { 15136 return BCM_E_NONE; 15137 } 15138 if (cosq == BCM_COSQ_OBM_CLASS_EXPRESS) { 15139 LOG_ERROR(BSL_LS_BCM_COMMON, 15140 (BSL_META_U(unit, 15141 "ERROR: obm class express is not supported" 15142 " port %d\n"), port)); 15143 return BCM_E_UNAVAIL; 15144 } 15145 obm = si->port_serdes[port]; 15146 obm %= _AP_TSCS_PER_PGW; 15147 pgw = si->port_group[port]; 15148 pgw_inst = (pgw | SOC_REG_ADDR_INSTANCE_MASK); 15149 subport = (phy_port - 1) % _AP_PORTS_PER_TSC; 15150 15151 BCM_IF_ERROR_RETURN 15152 (_bcm_ap_cosq_obm_threshold_get_reg_field(cosq, type, 15153 ®_index, &field)); 15154 15155 if (type == bcmCosqControlObmDiscardLimit) { 15156 if ((cosq < BCM_COSQ_OBM_CLASS_LOSSLESS0) || 15157 (cosq > BCM_COSQ_OBM_CLASS_ALL)) { 15158 return BCM_E_PARAM; 15159 } 15160 } else if (cosq == bcmCosqControlObmMinLimit) { 15161 if (cosq != BCM_COSQ_OBM_CLASS_LOSSY) { 15162 return BCM_E_PARAM; 15163 } 15164 } 15165 COMPILER_64_ZERO(rval64); 15166 reg = obm_threshold_regs[reg_index][obm]; 15167 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, pgw_inst, subport, &rval64)); 15168 if (set) { 15169 soc_reg64_field32_set(unit, reg, &rval64, field, *arg & 0x7ff); 15170 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, pgw_inst, subport, rval64)); 15171 } else { 15172 *arg = soc_reg64_field32_get(unit, reg, rval64, field); 15173 } 15174 return BCM_E_NONE; 15175 } 15176 15177 int 15178 bcm_ap_cosq_priority_mapping_get_all(int unit, bcm_gport_t gport, int index, 15179 bcm_cosq_priority_mapping_t type, 15180 int pri_max, int *pri_array, 15181 int *pri_count) 15182 { 15183 bcm_port_t port; 15184 int i, pg, sp, count = 0; 15185 15186 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_localport_resolve(unit, gport, &port)); 15187 if (!SOC_PORT_VALID(unit, port)) { 15188 return BCM_E_PORT; 15189 } 15190 15191 switch (type) { 15192 case bcmCosqPriorityGroup: 15193 if ((index < AP_PRIOROTY_GROUP_ID_MIN) || 15194 (index > AP_PRIOROTY_GROUP_ID_MAX)) { 15195 return BCM_E_PARAM; 15196 } 15197 for (i = 0; i < _AP_NUM_INTERNAL_PRI; i++) { 15198 BCM_IF_ERROR_RETURN 15199 (bcm_ap_port_priority_group_mapping_get(unit, gport, 15200 i, &pg)); 15201 if (pg == index) { 15202 if (pri_max != 0 && pri_array != NULL) { 15203 if (count < pri_max) { 15204 pri_array[count] = i; 15205 } 15206 } 15207 count++; 15208 } 15209 } 15210 break; 15211 case bcmCosqIngressPool: 15212 if ((index < 0) || (index >= _APACHE_MMU_NUM_POOL)) { 15213 return BCM_E_PARAM; 15214 } 15215 for (i = 0; i < _AP_NUM_INTERNAL_PRI; i++) { 15216 BCM_IF_ERROR_RETURN 15217 (bcm_ap_port_priority_group_mapping_get(unit, gport, 15218 i, &pg)); 15219 BCM_IF_ERROR_RETURN 15220 (_bcm_ap_cosq_ing_pool_get(unit, gport, pg, 15221 bcmCosqControlIngressPool, 15222 &sp)); 15223 if (sp == index) { 15224 if (pri_max != 0 && pri_array != NULL) { 15225 if (count < pri_max) { 15226 pri_array[count] = i; 15227 } 15228 } 15229 count++; 15230 } 15231 } 15232 break; 15233 default: 15234 return BCM_E_UNAVAIL; 15235 } 15236 15237 if ((count < pri_max) && (pri_array != NULL)) { 15238 for (i = count; i < pri_max; i++) { 15239 pri_array[i] = -1; 15240 } 15241 *pri_count = count; 15242 } else if (pri_max == 0) { 15243 *pri_count = count; 15244 } else { 15245 *pri_count = pri_max; 15246 } 15247 return BCM_E_NONE; 15248 } 15249 15250 int 15251 bcm_ap_cosq_control_set(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 15252 bcm_cosq_control_t type, int arg) 15253 { 15254 switch (type) { 15255 case bcmCosqControlEgressPool: 15256 case bcmCosqControlEgressPoolLimitBytes: 15257 case bcmCosqControlEgressPoolYellowLimitBytes: 15258 case bcmCosqControlEgressPoolRedLimitBytes: 15259 case bcmCosqControlEgressPoolLimitEnable: 15260 case bcmCosqControlUCEgressPool: 15261 case bcmCosqControlMCEgressPool: 15262 case bcmCosqControlEgressPoolSharedLimitBytes: 15263 case bcmCosqControlEgressPoolResumeLimitBytes: 15264 case bcmCosqControlEgressPoolYellowSharedLimitBytes: 15265 case bcmCosqControlEgressPoolYellowResumeLimitBytes: 15266 case bcmCosqControlEgressPoolRedSharedLimitBytes: 15267 case bcmCosqControlEgressPoolRedResumeLimitBytes: 15268 return _bcm_ap_cosq_egr_pool_set(unit, gport, cosq, type, arg); 15269 case bcmCosqControlEfPropagation: 15270 return _bcm_ap_cosq_ef_op(unit, gport, cosq, &arg, _BCM_COSQ_OP_SET); 15271 case bcmCosqControlCongestionProxy: 15272 return _bcm_ap_cosq_qcn_proxy_set(unit, gport, cosq, type, arg); 15273 case bcmCosqControlEgressUCQueueSharedLimitBytes: 15274 case bcmCosqControlEgressMCQueueSharedLimitBytes: 15275 case bcmCosqControlEgressUCQueueMinLimitBytes: 15276 case bcmCosqControlEgressMCQueueMinLimitBytes: 15277 return _bcm_ap_cosq_egr_queue_set(unit, gport, cosq, type, arg); 15278 case bcmCosqControlIngressPortPGSharedLimitBytes: 15279 case bcmCosqControlIngressPortPoolMaxLimitBytes: 15280 case bcmCosqControlIngressPortPGMinLimitBytes: 15281 case bcmCosqControlIngressPortPoolMinLimitBytes: 15282 case bcmCosqControlIngressPortPGHeadroomLimitBytes: 15283 case bcmCosqControlIngressPortPGResetFloorBytes: 15284 return _bcm_ap_cosq_ing_res_set(unit, gport, cosq, type, arg); 15285 case bcmCosqControlIngressPoolLimitBytes: 15286 return _bcm_ap_cosq_ing_res_limit_set(unit, gport, cosq, type, arg); 15287 case bcmCosqControlIngressPool: 15288 return _bcm_ap_cosq_ing_pool_set(unit, gport, cosq, type, arg); 15289 case bcmCosqControlDropLimitAlpha: 15290 return _bcm_ap_cosq_alpha_set(unit, gport, cosq, 15291 (bcm_cosq_control_drop_limit_alpha_value_t)arg); 15292 case bcmCosqControlIngressPortPGSharedDynamicEnable: 15293 case bcmCosqControlEgressUCSharedDynamicEnable: 15294 case bcmCosqControlEgressMCSharedDynamicEnable: 15295 return _bcm_ap_cosq_dynamic_thresh_enable_set(unit, gport, cosq, 15296 type, arg); 15297 case bcmCosqControlEgressPortPoolYellowLimitBytes: 15298 case bcmCosqControlEgressPortPoolRedLimitBytes: 15299 return _bcm_ap_cosq_egr_port_pool_set(unit, gport, cosq, type, arg); 15300 case bcmCosqControlEgressUCQueueLimitEnable: 15301 case bcmCosqControlEgressMCQueueLimitEnable: 15302 case bcmCosqControlEgressMCQueueColorLimitEnable: 15303 case bcmCosqControlEgressUCQueueColorLimitEnable: 15304 return _bcm_ap_cosq_egr_queue_limit_enable_set(unit, gport, cosq, type, arg); 15305 case bcmCosqControlEgressUCQueueGroupMinEnable: 15306 case bcmCosqControlEgressUCQueueGroupSharedLimitEnable: 15307 case bcmCosqControlEgressUCQueueGroupSharedDynamicEnable: 15308 return _bcm_ap_cosq_qgroup_limit_enable_set(unit, gport, cosq, type, arg); 15309 case bcmCosqControlEgressUCQueueGroupMinLimitBytes: 15310 case bcmCosqControlEgressUCQueueGroupSharedLimitBytes: 15311 return _bcm_ap_cosq_qgroup_limit_set(unit, gport, cosq, type, arg); 15312 case bcmCosqControlObmDiscardLimit: 15313 case bcmCosqControlObmMinLimit: 15314 return _bcm_ap_cosq_obm_threshold_set_get(unit, gport, cosq, type, &arg, 1); 15315 15316 case bcmCosqControlEgressUCQueueColorLimitDynamicEnable: 15317 case bcmCosqControlEgressMCQueueColorLimitDynamicEnable: 15318 return _bcm_ap_cosq_egr_queue_color_limit_mode_set(unit, gport, cosq, 15319 type, arg); 15320 case bcmCosqControlEgressUCQueueRedLimit: 15321 case bcmCosqControlEgressUCQueueYellowLimit: 15322 case bcmCosqControlEgressMCQueueRedLimit: 15323 case bcmCosqControlEgressMCQueueYellowLimit: 15324 return _bcm_ap_cosq_egr_queue_color_limit_set(unit, gport, cosq, type, arg); 15325 15326 default: 15327 break; 15328 } 15329 15330 return BCM_E_UNAVAIL; 15331 } 15332 15333 int 15334 bcm_ap_cosq_control_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 15335 bcm_cosq_control_t type, int *arg) 15336 { 15337 switch (type) { 15338 case bcmCosqControlEgressPool: 15339 case bcmCosqControlEgressPoolLimitBytes: 15340 case bcmCosqControlEgressPoolYellowLimitBytes: 15341 case bcmCosqControlEgressPoolRedLimitBytes: 15342 case bcmCosqControlEgressPoolLimitEnable: 15343 case bcmCosqControlUCEgressPool: 15344 case bcmCosqControlMCEgressPool: 15345 case bcmCosqControlEgressPoolSharedLimitBytes: 15346 case bcmCosqControlEgressPoolResumeLimitBytes: 15347 case bcmCosqControlEgressPoolYellowSharedLimitBytes: 15348 case bcmCosqControlEgressPoolYellowResumeLimitBytes: 15349 case bcmCosqControlEgressPoolRedSharedLimitBytes: 15350 case bcmCosqControlEgressPoolRedResumeLimitBytes: 15351 return _bcm_ap_cosq_egr_pool_get(unit, gport, cosq, type, arg); 15352 case bcmCosqControlEfPropagation: 15353 return _bcm_ap_cosq_ef_op(unit, gport, cosq, arg, _BCM_COSQ_OP_GET); 15354 case bcmCosqControlEgressUCQueueSharedLimitBytes: 15355 case bcmCosqControlEgressMCQueueSharedLimitBytes: 15356 case bcmCosqControlEgressUCQueueMinLimitBytes: 15357 case bcmCosqControlEgressMCQueueMinLimitBytes: 15358 return _bcm_ap_cosq_egr_queue_get(unit, gport, cosq, type, arg); 15359 case bcmCosqControlIngressPortPGSharedLimitBytes: 15360 case bcmCosqControlIngressPortPoolMaxLimitBytes: 15361 case bcmCosqControlIngressPortPGMinLimitBytes: 15362 case bcmCosqControlIngressPortPoolMinLimitBytes: 15363 case bcmCosqControlIngressPortPGHeadroomLimitBytes: 15364 case bcmCosqControlIngressPortPGResetFloorBytes: 15365 return _bcm_ap_cosq_ing_res_get(unit, gport, cosq, type, arg); 15366 case bcmCosqControlIngressPoolLimitBytes: 15367 return _bcm_ap_cosq_ing_res_limit_get(unit, gport, cosq, type, arg); 15368 case bcmCosqControlSPPortLimitState: 15369 case bcmCosqControlPGPortLimitState: 15370 case bcmCosqControlPGPortXoffState: 15371 case bcmCosqControlPoolRedDropState: 15372 case bcmCosqControlPoolYellowDropState: 15373 case bcmCosqControlPoolGreenDropState: 15374 return _bcm_ap_cosq_state_get(unit, gport, cosq, type, arg); 15375 case bcmCosqControlIngressPool: 15376 return _bcm_ap_cosq_ing_pool_get(unit, gport, cosq, type, arg); 15377 case bcmCosqControlDropLimitAlpha: 15378 return _bcm_ap_cosq_alpha_get(unit, gport, cosq, 15379 (bcm_cosq_control_drop_limit_alpha_value_t *)arg); 15380 case bcmCosqControlIngressPortPGSharedDynamicEnable: 15381 case bcmCosqControlEgressUCSharedDynamicEnable: 15382 case bcmCosqControlEgressMCSharedDynamicEnable: 15383 return _bcm_ap_cosq_dynamic_thresh_enable_get(unit, gport, cosq, 15384 type, arg); 15385 case bcmCosqControlPortQueueUcast: 15386 case bcmCosqControlPortQueueMcast: 15387 return _bcm_ap_cosq_port_qnum_get(unit, gport, cosq, type, arg); 15388 case bcmCosqControlEgressPortPoolYellowLimitBytes: 15389 case bcmCosqControlEgressPortPoolRedLimitBytes: 15390 return _bcm_ap_cosq_egr_port_pool_get(unit, gport, cosq, type, arg); 15391 case bcmCosqControlEgressUCQueueLimitEnable: 15392 case bcmCosqControlEgressMCQueueLimitEnable: 15393 case bcmCosqControlEgressMCQueueColorLimitEnable: 15394 case bcmCosqControlEgressUCQueueColorLimitEnable: 15395 return _bcm_ap_cosq_egr_queue_limit_enable_get(unit, gport, cosq, type, arg); 15396 case bcmCosqControlCongestionProxy: 15397 return _bcm_ap_cosq_qcn_proxy_get(unit, gport, cosq, type, arg); 15398 case bcmCosqControlEgressUCQueueGroupMinEnable: 15399 case bcmCosqControlEgressUCQueueGroupSharedLimitEnable: 15400 case bcmCosqControlEgressUCQueueGroupSharedDynamicEnable: 15401 return _bcm_ap_cosq_qgroup_limit_enable_get(unit, gport, cosq, type, arg); 15402 case bcmCosqControlEgressUCQueueGroupMinLimitBytes: 15403 case bcmCosqControlEgressUCQueueGroupSharedLimitBytes: 15404 return _bcm_ap_cosq_qgroup_limit_get(unit, gport, cosq, type, arg); 15405 case bcmCosqControlObmDiscardLimit: 15406 case bcmCosqControlObmMinLimit: 15407 return _bcm_ap_cosq_obm_threshold_set_get(unit, gport, cosq, type, arg, 0); 15408 case bcmCosqControlEgressUCQueueColorLimitDynamicEnable: 15409 case bcmCosqControlEgressMCQueueColorLimitDynamicEnable: 15410 return _bcm_ap_cosq_egr_queue_color_limit_mode_get(unit, gport, cosq, 15411 type, arg); 15412 case bcmCosqControlEgressUCQueueRedLimit: 15413 case bcmCosqControlEgressUCQueueYellowLimit: 15414 case bcmCosqControlEgressMCQueueRedLimit: 15415 case bcmCosqControlEgressMCQueueYellowLimit: 15416 return _bcm_ap_cosq_egr_queue_color_limit_get(unit, gport, cosq, type, arg); 15417 default: 15418 break; 15419 } 15420 15421 return BCM_E_UNAVAIL; 15422 } 15423 15424 int 15425 bcm_ap_cosq_service_pool_set( 15426 int unit, 15427 bcm_service_pool_id_t id, 15428 bcm_cosq_service_pool_t cosq_service_pool) 15429 { 15430 uint32 rval; 15431 soc_field_t fld_enable = INVALIDf; 15432 static const soc_field_t color_enable_fields[] = { 15433 PORTSP_COLOR_LIMIT_ENABLE_0f, PORTSP_COLOR_LIMIT_ENABLE_1f, 15434 PORTSP_COLOR_LIMIT_ENABLE_2f, PORTSP_COLOR_LIMIT_ENABLE_3f 15435 }; 15436 15437 if (id < 0 || (id > _AP_NUM_SERVICE_POOL - 1)) { 15438 return BCM_E_PARAM; 15439 } 15440 15441 SOC_IF_ERROR_RETURN(READ_MMU_THDM_DB_DEVICE_THR_CONFIGr(unit, &rval)); 15442 switch (cosq_service_pool.type) { 15443 case bcmCosqServicePoolPortColorAware: 15444 fld_enable = color_enable_fields[id]; 15445 break; 15446 default: 15447 return BCM_E_PARAM; 15448 } 15449 15450 soc_reg_field_set(unit, MMU_THDM_DB_DEVICE_THR_CONFIGr, &rval, 15451 fld_enable, cosq_service_pool.enabled ? 1 : 0); 15452 SOC_IF_ERROR_RETURN(WRITE_MMU_THDM_DB_DEVICE_THR_CONFIGr(unit, rval)); 15453 return BCM_E_NONE; 15454 } 15455 15456 15457 int 15458 bcm_ap_cosq_service_pool_get( 15459 int unit, 15460 bcm_service_pool_id_t id, 15461 bcm_cosq_service_pool_t *cosq_service_pool) 15462 { 15463 uint32 rval; 15464 soc_field_t fld_enable = INVALIDf; 15465 static const soc_field_t color_enable_fields[] = { 15466 PORTSP_COLOR_LIMIT_ENABLE_0f, PORTSP_COLOR_LIMIT_ENABLE_1f, 15467 PORTSP_COLOR_LIMIT_ENABLE_2f, PORTSP_COLOR_LIMIT_ENABLE_3f 15468 }; 15469 15470 if (cosq_service_pool == NULL) { 15471 return BCM_E_PARAM; 15472 } 15473 15474 if (id < 0 || (id > _AP_NUM_SERVICE_POOL - 1)) { 15475 return BCM_E_PARAM; 15476 } 15477 15478 SOC_IF_ERROR_RETURN(READ_MMU_THDM_DB_DEVICE_THR_CONFIGr(unit, &rval)); 15479 switch (cosq_service_pool->type) { 15480 case bcmCosqServicePoolPortColorAware: 15481 fld_enable = color_enable_fields[id]; 15482 break; 15483 default: 15484 return BCM_E_PARAM; 15485 } 15486 15487 cosq_service_pool->enabled = soc_reg_field_get(unit, MMU_THDM_DB_DEVICE_THR_CONFIGr, rval, 15488 fld_enable); 15489 return BCM_E_NONE; 15490 } 15491 15492 /* 15493 * Function: 15494 * bcm_ap_cosq_gport_bandwidth_set 15495 * Purpose: 15496 * Configure COS queue bandwidth control 15497 * Parameters: 15498 * unit - (IN) unit number 15499 * gport - (IN) GPORT identifier 15500 * cosq - (IN) COS queue to configure, -1 for all COS queues 15501 * kbits_sec_min - (IN) minimum bandwidth, kbits/sec 15502 * kbits_sec_max - (IN) maximum bandwidth, kbits/sec 15503 * flags - (IN) BCM_COSQ_BW_* 15504 * Returns: 15505 * BCM_E_XXX 15506 */ 15507 int 15508 bcm_ap_cosq_gport_bandwidth_set(int unit, bcm_gport_t gport, 15509 bcm_cos_queue_t cosq, uint32 kbits_sec_min, 15510 uint32 kbits_sec_max, uint32 flags) 15511 { 15512 int i, start_cos, end_cos, local_port; 15513 _bcm_ap_cosq_node_t *node; 15514 uint32 burst_min, burst_max; 15515 15516 if (cosq <= -1) { 15517 if (BCM_GPORT_IS_SET(gport)) { 15518 BCM_IF_ERROR_RETURN 15519 (_bcm_ap_cosq_node_get(unit, gport, 0, NULL, 15520 NULL, NULL, &node)); 15521 start_cos = 0; 15522 if (node->numq == -1) { 15523 end_cos = 0; 15524 } else { 15525 end_cos = node->numq - 1; 15526 } 15527 } else { 15528 start_cos = 0; 15529 end_cos = _AP_NUM_COS(unit) - 1; 15530 } 15531 } else { 15532 start_cos = end_cos = cosq; 15533 } 15534 15535 if(_BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, gport)){ 15536 BCM_IF_ERROR_RETURN( 15537 _bcmi_coe_subport_physical_port_get(unit, gport, &local_port)); 15538 } else { 15539 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_localport_resolve(unit, gport, &local_port)); 15540 } 15541 burst_min = (kbits_sec_min > 0) ? 15542 _bcm_td_default_burst_size(unit, local_port, kbits_sec_min) : 0; 15543 15544 burst_max = (kbits_sec_max > 0) ? 15545 _bcm_td_default_burst_size(unit, local_port, kbits_sec_max) : 0; 15546 15547 for (i = start_cos; i <= end_cos; i++) { 15548 BCM_IF_ERROR_RETURN 15549 (_bcm_ap_cosq_bucket_set(unit, gport, i, kbits_sec_min, 15550 kbits_sec_max, burst_min, burst_max, flags)); 15551 } 15552 15553 return BCM_E_NONE; 15554 } 15555 15556 /* 15557 * Function: 15558 * bcm_ap_cosq_gport_bandwidth_get 15559 * Purpose: 15560 * Get COS queue bandwidth control configuration 15561 * Parameters: 15562 * unit - (IN) unit number 15563 * gport - (IN) GPORT identifier 15564 * cosq - (IN) COS queue to get, -1 for any COS queue 15565 * kbits_sec_min - (OUT) minimum bandwidth, kbits/sec 15566 * kbits_sec_max - (OUT) maximum bandwidth, kbits/sec 15567 * flags - (OUT) BCM_COSQ_BW_* 15568 * Returns: 15569 * BCM_E_XXX 15570 */ 15571 int 15572 bcm_ap_cosq_gport_bandwidth_get(int unit, bcm_gport_t gport, 15573 bcm_cos_queue_t cosq, uint32 *kbits_sec_min, 15574 uint32 *kbits_sec_max, uint32 *flags) 15575 { 15576 uint32 kbits_sec_burst; 15577 15578 if (cosq == -1) { 15579 return BCM_E_PARAM; 15580 } 15581 15582 BCM_IF_ERROR_RETURN 15583 (_bcm_ap_cosq_bucket_get(unit, gport, cosq, 15584 kbits_sec_min, kbits_sec_max, 15585 &kbits_sec_burst, &kbits_sec_burst, flags)); 15586 return BCM_E_NONE; 15587 } 15588 15589 /* 15590 * Function: 15591 * bcm_ap_cosq_gport_bandwidth_burst_set 15592 * Purpose: 15593 * Configure COS queue bandwidth burst setting 15594 * Parameters: 15595 * unit - (IN) unit number 15596 * gport - (IN) GPORT identifier 15597 * cosq - (IN) COS queue to configure, -1 for all COS queues 15598 * kbits_burst - (IN) maximum burst, kbits 15599 * Returns: 15600 * BCM_E_XXX 15601 */ 15602 int 15603 bcm_ap_cosq_gport_bandwidth_burst_set(int unit, bcm_gport_t gport, 15604 bcm_cos_queue_t cosq, 15605 uint32 kbits_burst_min, 15606 uint32 kbits_burst_max) 15607 { 15608 int i, start_cos, end_cos; 15609 uint32 kbits_sec_min = 0; 15610 uint32 kbits_sec_max = 0; 15611 uint32 kbits_sec_burst = 0; 15612 uint32 flags = 0; 15613 _bcm_ap_cosq_node_t *node; 15614 15615 if (cosq < -1) { 15616 return BCM_E_PARAM; 15617 } 15618 15619 if (cosq == -1) { 15620 if (BCM_GPORT_IS_SET(gport) && 15621 !(_BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, gport))) { 15622 BCM_IF_ERROR_RETURN 15623 (_bcm_ap_cosq_node_get(unit, gport, 0, NULL, 15624 NULL, NULL, &node)); 15625 start_cos = 0; 15626 end_cos = node->numq - 1; 15627 } else { 15628 start_cos = 0; 15629 end_cos = _AP_NUM_COS(unit) - 1; 15630 } 15631 } else { 15632 start_cos = end_cos = cosq; 15633 } 15634 15635 for (i = start_cos; i <= end_cos; i++) { 15636 BCM_IF_ERROR_RETURN 15637 (_bcm_ap_cosq_bucket_get(unit, gport, i, &kbits_sec_min, 15638 &kbits_sec_max, &kbits_sec_burst, 15639 &kbits_sec_burst, &flags)); 15640 BCM_IF_ERROR_RETURN 15641 (_bcm_ap_cosq_bucket_set(unit, gport, i, kbits_sec_min, 15642 kbits_sec_max, kbits_burst_min, 15643 kbits_burst_max, flags)); 15644 } 15645 15646 return BCM_E_NONE; 15647 } 15648 15649 /* 15650 * Function: 15651 * bcm_ap_cosq_gport_bandwidth_burst_get 15652 * Purpose: 15653 * Get COS queue bandwidth burst setting 15654 * Parameters: 15655 * unit - (IN) unit number 15656 * gport - (IN) GPORT identifier 15657 * cosq - (IN) COS queue to get, -1 for any queue 15658 * kbits_burst - (OUT) maximum burst, kbits 15659 * Returns: 15660 * BCM_E_XXX 15661 */ 15662 int 15663 bcm_ap_cosq_gport_bandwidth_burst_get(int unit, bcm_gport_t gport, 15664 bcm_cos_queue_t cosq, 15665 uint32 *kbits_burst_min, 15666 uint32 *kbits_burst_max) 15667 { 15668 uint32 kbits_sec_min, kbits_sec_max, flags; 15669 15670 if (cosq < -1) { 15671 return BCM_E_PARAM; 15672 } 15673 15674 BCM_IF_ERROR_RETURN 15675 (_bcm_ap_cosq_bucket_get(unit, gport, cosq == -1 ? 0 : cosq, 15676 &kbits_sec_min, &kbits_sec_max, kbits_burst_min, 15677 kbits_burst_max, &flags)); 15678 15679 return BCM_E_NONE; 15680 } 15681 15682 /* 15683 * Function: 15684 * bcm_ap_cosq_gport_sched_set 15685 * Purpose: 15686 * Configure COS queue scheduler setting 15687 * Parameters: 15688 * unit - (IN) unit number 15689 * gport - (IN) GPORT identifier 15690 * cosq - (IN) COS queue to configure, -1 for all COS queues 15691 * mode - (IN) Scheduling mode, one of BCM_COSQ_xxx 15692 * weight - (IN) queue weight 15693 * Returns: 15694 * BCM_E_XXX 15695 */ 15696 int 15697 bcm_ap_cosq_gport_sched_set(int unit, bcm_gport_t gport, 15698 bcm_cos_queue_t cosq, int mode, int weight) 15699 { 15700 int rv, numq, i, count; 15701 15702 if (cosq == -1) { 15703 BCM_IF_ERROR_RETURN 15704 (_bcm_ap_cosq_index_resolve(unit, gport, cosq, 15705 _BCM_AP_COSQ_INDEX_STYLE_SCHEDULER, 15706 NULL, NULL, &numq)); 15707 cosq = 0; 15708 } else { 15709 numq = 1; 15710 } 15711 15712 count = 0; 15713 for (i = 0; i < numq; i++) { 15714 rv = _bcm_ap_cosq_sched_set(unit, gport, cosq + i, mode, weight); 15715 if (rv == BCM_E_NOT_FOUND) { 15716 continue; 15717 } else if (BCM_FAILURE(rv)) { 15718 return rv; 15719 } else { 15720 count++; 15721 } 15722 } 15723 15724 return count > 0 ? BCM_E_NONE : BCM_E_NOT_FOUND; 15725 } 15726 15727 /* 15728 * Function: 15729 * bcm_ap_cosq_gport_sched_get 15730 * Purpose: 15731 * Get COS queue scheduler setting 15732 * Parameters: 15733 * unit - (IN) unit number 15734 * gport - (IN) GPORT identifier 15735 * cosq - (IN) COS queue to get, -1 for any queue 15736 * mode - (OUT) Scheduling mode, one of BCM_COSQ_xxx 15737 * weight - (OUT) queue weight 15738 * Returns: 15739 * BCM_E_XXX 15740 */ 15741 int 15742 bcm_ap_cosq_gport_sched_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 15743 int *mode, int *weight) 15744 { 15745 int rv, numq, i; 15746 15747 if (cosq == -1) { 15748 BCM_IF_ERROR_RETURN 15749 (_bcm_ap_cosq_index_resolve(unit, gport, 0, 15750 _BCM_AP_COSQ_INDEX_STYLE_SCHEDULER, 15751 NULL, NULL, &numq)); 15752 cosq = 0; 15753 } else { 15754 numq = 1; 15755 } 15756 15757 for (i = 0; i < numq; i++) { 15758 rv = _bcm_ap_cosq_sched_get(unit, gport, cosq + i, mode, weight); 15759 if (rv == BCM_E_NOT_FOUND) { 15760 continue; 15761 } else { 15762 return rv; 15763 } 15764 } 15765 15766 return BCM_E_NOT_FOUND; 15767 } 15768 15769 /* 15770 * Function: 15771 * bcm_ap_cosq_gport_discard_set 15772 * Purpose: 15773 * Configure port WRED setting 15774 * Parameters: 15775 * unit - (IN) unit number 15776 * port - (IN) GPORT identifier 15777 * cosq - (IN) COS queue to configure, -1 for all COS queues 15778 * discard - (IN) discard settings 15779 * Returns: 15780 * BCM_E_XXX 15781 */ 15782 int 15783 bcm_ap_cosq_gport_discard_set(int unit, bcm_gport_t gport, 15784 bcm_cos_queue_t cosq, 15785 bcm_cosq_gport_discard_t *discard) 15786 { 15787 uint32 min_thresh, max_thresh, flags = 0; 15788 int cell_size, cell_field_max; 15789 bcm_port_t local_port = -1; 15790 15791 /* refresh_time from 1 to 7 be set the same as default 8,so the reasonable 15792 range of refresh_time is from 1 to 512 */ 15793 if (discard == NULL || 15794 discard->gain < 0 || discard->gain > 15 || 15795 discard->drop_probability < 0 || discard->drop_probability > 100 || 15796 discard->refresh_time <= 0 || discard->refresh_time > 512) { 15797 return BCM_E_PARAM; 15798 } 15799 if ((discard->min_thresh < 0) || 15800 (discard->max_thresh < 0) || 15801 (discard->min_thresh > discard->max_thresh)) { 15802 return BCM_E_PARAM; 15803 } 15804 15805 cell_size = _BCM_AP_BYTES_PER_CELL; 15806 cell_field_max = AP_CELL_FIELD_MAX; 15807 15808 min_thresh = discard->min_thresh; 15809 max_thresh = discard->max_thresh; 15810 if (discard->flags & BCM_COSQ_DISCARD_BYTES) { 15811 /* Convert bytes to cells */ 15812 min_thresh += (cell_size - 1); 15813 min_thresh /= cell_size; 15814 15815 max_thresh += (cell_size - 1); 15816 max_thresh /= cell_size; 15817 15818 if ((min_thresh > cell_field_max) || 15819 (max_thresh > cell_field_max)) { 15820 return BCM_E_PARAM; 15821 } 15822 } else { 15823 /* Packet mode not supported */ 15824 return BCM_E_PARAM; 15825 } 15826 15827 /* Min equals Max is an invalid config except 15828 * in case of default (ResetVal) 15829 */ 15830 if ((min_thresh == max_thresh) && 15831 (min_thresh != AP_CELL_FIELD_MAX)) { 15832 return BCM_E_PARAM; 15833 } 15834 15835 if (gport != BCM_GPORT_INVALID) { 15836 BCM_IF_ERROR_RETURN 15837 (_bcm_ap_cosq_localport_resolve(unit, gport, &local_port)); 15838 if (IS_CPU_PORT(unit,local_port) || IS_LB_PORT(unit,local_port)) { 15839 return BCM_E_PORT; 15840 } 15841 } 15842 15843 BCM_IF_ERROR_RETURN 15844 (_bcm_ap_cosq_wred_set(unit, gport, cosq, discard->flags, 15845 min_thresh, max_thresh, 15846 discard->drop_probability, discard->gain, 15847 FALSE, flags,discard->refresh_time)); 15848 15849 return BCM_E_NONE; 15850 } 15851 15852 /* 15853 * Function: 15854 * bcm_ap_cosq_gport_discard_get 15855 * Purpose: 15856 * Get port WRED setting 15857 * Parameters: 15858 * unit - (IN) unit number 15859 * port - (IN) GPORT identifier 15860 * cosq - (IN) COS queue to get, -1 for any queue 15861 * discard - (OUT) discard settings 15862 * Returns: 15863 * BCM_E_XXX 15864 */ 15865 int 15866 bcm_ap_cosq_gport_discard_get(int unit, bcm_gport_t gport, 15867 bcm_cos_queue_t cosq, 15868 bcm_cosq_gport_discard_t *discard) 15869 { 15870 uint32 min_thresh, max_thresh; 15871 bcm_port_t local_port = -1; 15872 15873 if (discard == NULL) { 15874 return BCM_E_PARAM; 15875 } 15876 15877 if (gport != BCM_GPORT_INVALID) { 15878 BCM_IF_ERROR_RETURN 15879 (_bcm_ap_cosq_localport_resolve(unit, gport, &local_port)); 15880 if (IS_CPU_PORT(unit,local_port) || IS_LB_PORT(unit,local_port)) { 15881 return BCM_E_PORT; 15882 } 15883 } 15884 15885 BCM_IF_ERROR_RETURN 15886 (_bcm_ap_cosq_wred_get(unit, gport, cosq == -1 ? 0 : cosq, 15887 &discard->flags, &min_thresh, &max_thresh, 15888 &discard->drop_probability, &discard->gain, 15889 0,&discard->refresh_time)); 15890 15891 /* Convert number of cells to number of bytes */ 15892 discard->min_thresh = min_thresh * _BCM_AP_BYTES_PER_CELL; 15893 discard->max_thresh = max_thresh * _BCM_AP_BYTES_PER_CELL; 15894 15895 return BCM_E_NONE; 15896 } 15897 15898 /* 15899 * Function: 15900 * bcm_ap_cosq_subport_flow_control_set 15901 * Purpose: 15902 * Set a port or node (L0, L1, L2) to flow control when 15903 * a CoE control frame is received on a subtended port. 15904 * Parameters: 15905 * unit - (IN) Unit number. 15906 * subport - (IN) Subtended port 15907 * sched_port - (IN) Node (Port, L0, L1, L2) to flow control 15908 * Returns: 15909 * BCM_E_xxx 15910 * Notes: 15911 */ 15912 int 15913 bcm_ap_cosq_subport_flow_control_set( 15914 int unit, 15915 bcm_gport_t subport, 15916 bcm_gport_t sched_port) 15917 { 15918 #ifdef BCM_HGPROXY_COE_SUPPORT 15919 uint16 coe_fc_index ; 15920 uint32 rval; 15921 bcm_gport_t subport_id, resolved_port; 15922 _bcm_ap_cosq_node_t *node; 15923 int hw_index, rv, logical_hw_index; 15924 soc_apache_node_lvl_e level; 15925 subport_tag_sgpp_map_entry_t entry; 15926 bcm_port_t phy_port, mmu_port; 15927 soc_info_t *si; 15928 _bcm_ap_fc_type_t fct; 15929 int s1_level = 0; 15930 int index = 0 ; 15931 int cos = 0 ; 15932 15933 /* Find subport id from port to index into SUBPORT_TAG_SGPP_MAP */ 15934 BCM_IF_ERROR_RETURN(_bcmi_coe_subport_tcam_idx_get(unit, subport, &subport_id)); 15935 15936 /* From sched_port, need to find if it's port, L0, L1, or L2 */ 15937 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_node_get(unit, sched_port, 0, NULL, NULL, NULL, &node)); 15938 15939 BCM_IF_ERROR_RETURN 15940 (_bcmi_coe_subport_physical_port_get(unit, subport, &resolved_port)); 15941 /* Port, L0, L1, or L2 from node */ 15942 level = node->level; 15943 15944 /* index into L0, L1, or L2 */ 15945 hw_index = node->hw_index; 15946 15947 /* row and column are used to index in to the FC State Table, which is 4 bits wide */ 15948 15949 /* Get the port associated with the passed in gport */ 15950 if (resolved_port < 0) { 15951 return BCM_E_PORT; 15952 } 15953 15954 si = &SOC_INFO(unit); 15955 /* Getting MMU port. Used to disable cut through for it at the end as well as 15956 to index into MMU_INTFI_PORT_COEFC_TB if we're setting flow control for port */ 15957 phy_port = si->port_l2p_mapping[resolved_port]; 15958 mmu_port = si->port_p2m_mapping[phy_port]; 15959 if (IS_AP_HSP_PORT( unit, resolved_port )) { 15960 /* SC/QM L1/L2 nodes do not support FC. 15961 * Hence, L1/L2 indices 8, 9, 18, 19 ... should not be configured 15962 * for FC. 15963 * similarly the last L0 of the HSP port does not support flow control 15964 */ 15965 if (level == SOC_APACHE_NODE_LVL_L0) { 15966 if ((hw_index % 5) > 3) { 15967 return BCM_E_PARAM; 15968 } 15969 cos = hw_index % 5; 15970 } else { 15971 if ((hw_index % 10) > 7) { 15972 return BCM_E_PARAM; 15973 } 15974 cos = ((hw_index % 10) % 4); 15975 } 15976 } else { 15977 cos = hw_index % 4 ; 15978 } 15979 switch(level) { 15980 case SOC_APACHE_NODE_LVL_ROOT: 15981 /* At the port level we have to do it a bit different since it's indexing into 15982 MMU_INTFI_PORT_COEFC_TB, which is a 128 entry x 1 bit table with each entry signifying 15983 an MMU Port 15984 */ 15985 index = hw_index; 15986 break; 15987 case SOC_APACHE_NODE_LVL_L0: 15988 15989 if (IS_AP_HSP_PORT( unit, resolved_port )) { 15990 /* The last L0 does not support FC and so each index in fc_st_tbl represents 15991 * 5 l0 nodes instead of 4 the last 1 is masked by the hardware 15992 */ 15993 index = hw_index / 5; 15994 break; 15995 } else { 15996 index = hw_index / 4; 15997 } 15998 case SOC_APACHE_NODE_LVL_L1: 15999 case SOC_APACHE_NODE_LVL_L2: 16000 if (IS_AP_HSP_PORT( unit, resolved_port )) { 16001 /* FC not supported on last two L1/L2 nodes The hardwate internally adjusts the value 16002 * say index 24 which for non hsp port will result in index 6 will result in 5 for HSP 16003 */ 16004 index = mmu_port * 2 + 16005 (((hw_index % 10) >= 4)? 1 : 0); 16006 } else { 16007 index = hw_index / 4; 16008 } 16009 break; 16010 case SOC_APACHE_NODE_LVL_S1: 16011 index = hw_index / 4; 16012 break; 16013 default: 16014 return BCM_E_PARAM; 16015 16016 } 16017 if ( level == SOC_APACHE_NODE_LVL_S1) 16018 { 16019 s1_level = 1; 16020 16021 } 16022 if (level) { 16023 level--;/* reducing one level for S1*/ 16024 } 16025 /* set coe_fc_index for us to program into the register */ 16026 coe_fc_index = ((s1_level << 15) | (index << 4)| cos << 2 | (level)); 16027 16028 /* Program SUBPORT_TAG_SGPP_MAP with the subport as the index and 16029 COE_FC_INDEX as the data */ 16030 rv = READ_SUBPORT_TAG_SGPP_MAPm(unit, 16031 MEM_BLOCK_ANY, subport_id, &entry); 16032 if (SOC_SUCCESS(rv)) { 16033 soc_SUBPORT_TAG_SGPP_MAPm_field32_set(unit, 16034 (uint32 *)&entry, COE_FC_INDEXf, coe_fc_index); 16035 } 16036 WRITE_SUBPORT_TAG_SGPP_MAPm(unit, MEM_BLOCK_ANY, subport_id, &entry); 16037 16038 /* Program FC Map Table to select FC State Table (vs PFC State Table) for the node */ 16039 fct = _BCM_AP_COSQ_FC_E2ECC; 16040 16041 logical_hw_index = hw_index / 4 ; 16042 16043 /* To pass the proper FC STATE Table entries, we're modifying the FC MAP Table, one of its 16044 4 indexes, with the appropriate row in the FC STATE Table. FC MAP Table at index 0 16045 will handle the rows 0-3 of FC STATE Table, at index 1 will handle rows 4-7 of the 16046 FC STATE Table, and so on. 16047 16048 resolved_port is passed so that the function will know which pipe to use (X or Y). 16049 fct will select FC STATE Table on the mux so that PFC STATE Table won't be selected. 16050 logical_hw_index is passed in this first time so that a proper row index for the FC STATE Table will be selected. 16051 node->hw_index is passed in a second time because the proper FC MAP Table index will be calculated. 16052 node->level is passed in so that the function will know with FC MAP Table (L0, L1, L2) to use. 16053 */ 16054 if(level != SOC_APACHE_NODE_LVL_ROOT) { 16055 BCM_IF_ERROR_RETURN(_bcm_ap_map_fc_status_to_node(unit, resolved_port, fct, logical_hw_index, 16056 0 , node->hw_index, node->level)); 16057 } 16058 16059 /* Disable Cut-Through for the port specified or L0/L1/L2 node associated with it */ 16060 BCM_IF_ERROR_RETURN(READ_ASF_PORT_CFGr(unit, resolved_port, &rval)); 16061 soc_reg_field_set(unit, ASF_PORT_CFGr, &rval, UC_ASF_ENABLEf, 0); 16062 soc_reg_field_set(unit, ASF_PORT_CFGr, &rval, MC_ASF_ENABLEf, 0); 16063 BCM_IF_ERROR_RETURN(WRITE_ASF_PORT_CFGr(unit, resolved_port, rval)); 16064 16065 return BCM_E_NONE; 16066 #else 16067 return BCM_E_UNAVAIL; 16068 #endif /* BCM_HGPROXY_COE_SUPPORT */ 16069 } 16070 16071 int 16072 bcm_ap_cosq_subport_flow_control_get( 16073 int unit, 16074 bcm_gport_t subport, 16075 bcm_gport_t * sched_port) 16076 { 16077 #ifdef BCM_HGPROXY_COE_SUPPORT 16078 int level, i; 16079 int hw_index = 0; 16080 uint16 coe_fc_index = 0; 16081 bcm_gport_t subport_id; 16082 _bcm_ap_cosq_node_t * node; 16083 _bcm_ap_mmu_info_t * mmu_info; 16084 subport_tag_sgpp_map_entry_t entry; 16085 int s1_level ; 16086 int index = 0; 16087 int cos = 0 ; 16088 int resolved_port = 0; 16089 int mmu_port = 0; 16090 int phy_port = 0; 16091 soc_info_t *si; 16092 /* Find subport id from port to index into SUBPORT_TAG_SGPP_MAP */ 16093 BCM_IF_ERROR_RETURN(_bcmi_coe_subport_tcam_idx_get(unit, subport, &subport_id)); 16094 16095 16096 BCM_IF_ERROR_RETURN( 16097 _bcmi_coe_subport_physical_port_get(unit, subport, &resolved_port)); 16098 si = &SOC_INFO(unit); 16099 /* Getting MMU port. Used to disable cut through for it at the end as well as 16100 to index into MMU_INTFI_PORT_COEFC_TB if we're setting flow control for port */ 16101 phy_port = si->port_l2p_mapping[resolved_port]; 16102 mmu_port = si->port_p2m_mapping[phy_port]; 16103 BCM_IF_ERROR_RETURN(READ_SUBPORT_TAG_SGPP_MAPm(unit, 16104 MEM_BLOCK_ANY, subport_id, &entry)); 16105 coe_fc_index = soc_SUBPORT_TAG_SGPP_MAPm_field32_get(unit, 16106 (uint32 *)&entry, COE_FC_INDEXf); 16107 16108 16109 level = coe_fc_index & 0x3; 16110 cos = (coe_fc_index >> 2) & 0x3; 16111 index = (coe_fc_index >> 4) & 0x7FF; 16112 s1_level = (coe_fc_index >>15) ; 16113 if((level) || (s1_level)) { 16114 level++;/*This is needed as we decrement while storing*/ 16115 } 16116 switch(level) { 16117 case SOC_APACHE_NODE_LVL_ROOT: 16118 /* At the port level we have to do it a bit different since it's indexing into 16119 MMU_INTFI_PORT_COEFC_TB, which is a 128 entry x 1 bit table with each entry signifying 16120 an MMU Port 16121 */ 16122 hw_index = index; 16123 break; 16124 case SOC_APACHE_NODE_LVL_L0: 16125 if (IS_AP_HSP_PORT( unit, resolved_port )) { 16126 hw_index = index * 5 + cos ; 16127 } else { 16128 hw_index = index * 4 + cos ; 16129 } 16130 break; 16131 case SOC_APACHE_NODE_LVL_L1: 16132 case SOC_APACHE_NODE_LVL_L2: 16133 /* FC not supported on last two L1/L2 nodes The hardwate internally adjusts the value 16134 * say index 24 which for non hsp port will result in index 6 will result in 5 for HSP 16135 */ 16136 if (IS_AP_HSP_PORT( unit, resolved_port )) { 16137 hw_index = (mmu_port * 10) + ((index % 2)? 4: 0) + cos ; 16138 } else { 16139 hw_index = index * 4 + cos ; 16140 } 16141 break; 16142 case SOC_APACHE_NODE_LVL_S1: 16143 hw_index = index * 4 + cos ; 16144 break; 16145 /* 16146 * COVERITY 16147 * 16148 * This default is unreachable but needed for some compiler. 16149 */ 16150 /* coverity[dead_error_begin] */ 16151 default: 16152 return BCM_E_PARAM; 16153 16154 } 16155 /* calculate the hw_index */ 16156 16157 mmu_info = _bcm_ap_mmu_info[unit]; 16158 16159 if (!mmu_info) { 16160 return BCM_E_INIT; 16161 } 16162 16163 16164 /* Fetch the node based upon level and hw_index */ 16165 switch(level) { 16166 /* port, L0, and L1 are all scheduling nodes */ 16167 case SOC_APACHE_NODE_LVL_L0: 16168 case SOC_APACHE_NODE_LVL_ROOT: 16169 case SOC_APACHE_NODE_LVL_L1: 16170 case SOC_APACHE_NODE_LVL_S1: 16171 for(i = 0; i < _BCM_AP_NUM_TOTAL_SCHEDULERS; i++) { 16172 node = &mmu_info->sched_node[i]; 16173 if(node->level == level) { 16174 if(node->hw_index == hw_index) { 16175 *sched_port = node->gport; 16176 return BCM_E_NONE; 16177 } 16178 } 16179 } 16180 break; 16181 case SOC_APACHE_NODE_LVL_L2: 16182 for(i = 0; i < _BCM_AP_NUM_L2_UC_LEAVES; i++) { 16183 node = &mmu_info->queue_node[i]; 16184 if(node->level == level) { 16185 if(node->hw_index == hw_index) { 16186 *sched_port = node->gport; 16187 return BCM_E_NONE; 16188 } 16189 } 16190 } 16191 break; 16192 /* Intentional process */ 16193 /* coverity[dead_error_begin] */ 16194 default: 16195 return BCM_E_PARAM; 16196 } 16197 /* not found */ 16198 return BCM_E_PARAM; 16199 #else 16200 return BCM_E_UNAVAIL; 16201 #endif /* BCM_HGPROXY_COE_SUPPORT */ 16202 } 16203 16204 int 16205 _bcm_ap_cosq_port_safc_get(int unit, bcm_port_t port, 16206 int cur_class, 16207 bcm_gport_t *gport, int gport_count, 16208 int *actual_gport_count) 16209 { 16210 _bcm_ap_cosq_node_t *node; 16211 bcm_port_t local_port; 16212 int hw_cosq, count = 0; 16213 uint32 profile_index; 16214 uint64 rval64[16], *rval64s[1], rval, index_map; 16215 uint32 tmp32, bmp; 16216 _bcm_ap_mmu_info_t *mmu_info; 16217 int phy_port, mmu_port; 16218 soc_info_t *si; 16219 soc_reg_t reg; 16220 int mc_index = 0; 16221 int mcq_offset = 0; 16222 _bcm_ap_pipe_resources_t *res; 16223 _bcm_ap_cosq_port_info_t *port_info; 16224 static const soc_reg_t llfc_cfgr[] = { 16225 PORT_PFC_CFG0r, PORT_PFC_CFG1r, PORT_PFC_CFG2r 16226 }; 16227 static const soc_field_t self[] = { 16228 SEL0f, SEL1f, SEL2f, SEL3f 16229 }; 16230 int j, inv_mapped, hw_index, eindex; 16231 soc_mem_t mem; 16232 uint32 map_entry[SOC_MAX_MEM_WORDS]; 16233 16234 16235 if (gport == NULL || gport_count <= 0 || actual_gport_count == NULL) { 16236 return BCM_E_PARAM; 16237 } 16238 16239 BCM_IF_ERROR_RETURN 16240 (_bcm_ap_cosq_localport_resolve(unit, port, &local_port)); 16241 16242 16243 si = &SOC_INFO(unit); 16244 mmu_info = _bcm_ap_mmu_info[unit]; 16245 res = _BCM_AP_PRESOURCES(mmu_info, 0); 16246 phy_port = si->port_l2p_mapping[local_port]; 16247 mmu_port = si->port_p2m_mapping[phy_port]; 16248 port_info = &mmu_info->port_info[local_port]; 16249 16250 rval64s[0] = rval64; 16251 reg = llfc_cfgr[mmu_port/32]; 16252 BCM_IF_ERROR_RETURN(soc_reg64_get(unit, reg, REG_PORT_ANY, 0, &rval)); 16253 16254 index_map = soc_reg64_field_get(unit, reg, rval, PROFILE_INDEXf); 16255 COMPILER_64_SHR(index_map, ((mmu_port % 32) * 2)); 16256 COMPILER_64_TO_32_LO(tmp32, index_map); 16257 profile_index = (tmp32 & 3)*16; 16258 16259 BCM_IF_ERROR_RETURN 16260 (soc_profile_reg_get(unit, _bcm_ap_llfc_profile[unit], 16261 profile_index, 16, rval64s)); 16262 16263 bmp = soc_reg64_field32_get(unit, PRIO2COS_PROFILEr, rval64[cur_class], 16264 COS_BMPf); 16265 for (hw_cosq = 0; hw_cosq < _BCM_AP_NUM_SAFC_CLASS ; hw_cosq++) { 16266 if (!(bmp & (1 << hw_cosq))) { 16267 continue; 16268 } 16269 if (_bcm_ap_cosq_port_has_ets(unit, local_port)) { 16270 inv_mapped = 0; 16271 for (j = _BCM_AP_NUM_PORT_SCHEDULERS; 16272 j < _BCM_AP_NUM_TOTAL_SCHEDULERS; j++) { 16273 node = &mmu_info->sched_node[j]; 16274 if ((!node->in_use) || (node->local_port != local_port) || 16275 (node->hw_cosq != hw_cosq)) { 16276 continue; 16277 } 16278 16279 hw_index = (node->hw_index / 16); 16280 eindex = (node->hw_index % 16)/4; 16281 if (node->level == SOC_APACHE_NODE_LVL_L0) { 16282 mem = MMU_INTFI_XPIPE_FC_MAP_TBL0m; 16283 } else if (node->level == SOC_APACHE_NODE_LVL_L1) { 16284 mem = MMU_INTFI_XPIPE_FC_MAP_TBL1m; 16285 } else { 16286 continue; 16287 } 16288 16289 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, 16290 MEM_BLOCK_ALL, hw_index, &map_entry)); 16291 /* coverity[overrun-local : FALSE] */ 16292 if (soc_mem_field32_get(unit, mem, &map_entry, self[eindex])) { 16293 if (gport_count > 0) { 16294 gport[count] = node->gport; 16295 } 16296 count++; 16297 if ((count == gport_count) && (gport_count > 0)) { 16298 inv_mapped = 1; 16299 break; 16300 } 16301 } 16302 } 16303 16304 for (j = port_info->uc_base; 16305 inv_mapped==0 && (j < port_info->uc_limit); j++) { 16306 node = &res->p_queue_node[j]; 16307 if ((!node->in_use) || (node->local_port != local_port)) { 16308 continue; 16309 } 16310 if (node->hw_cosq != hw_cosq) { 16311 continue; 16312 } 16313 mem = MMU_INTFI_XPIPE_FC_MAP_TBL2m ; 16314 hw_index = (node->hw_index / 16); 16315 eindex = (node->hw_index % 16)/4; 16316 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, 16317 MEM_BLOCK_ALL, hw_index, &map_entry)); 16318 16319 /* coverity[overrun-local : FALSE] */ 16320 if (soc_mem_field32_get(unit, mem, &map_entry, self[eindex])) { 16321 if (gport_count > 0) { 16322 gport[count] = node->gport; 16323 } 16324 count++; 16325 if ((count == gport_count) && (gport_count > 0)) { 16326 inv_mapped = 1; 16327 break; 16328 } 16329 } 16330 } 16331 for (j = port_info->mc_base; 16332 inv_mapped==0 && (j < port_info->mc_limit); j++) { 16333 mc_index = soc_apache_l2_hw_index(unit, j, 0); 16334 node = &res->p_queue_node[mc_index]; 16335 if ((!node->in_use) || (node->local_port != local_port)) { 16336 continue; 16337 } 16338 if (node->hw_cosq != hw_cosq) { 16339 continue; 16340 } 16341 mem = MMU_INTFI_XPIPE_FC_MAP_TBL2m ; 16342 mcq_offset = node->hw_index % _BCM_AP_NUM_L2_UC_LEAVES_PER_PIPE; 16343 if (((mcq_offset % 10) > 7) ) { 16344 /* FC support only for Q0-7 */ 16345 continue; 16346 } 16347 hw_index = node->hw_index - (mcq_offset * 2 / 10); 16348 hw_index /= 16; 16349 eindex = (mcq_offset % 10)/4; 16350 eindex += ((mcq_offset /10) % 2) ? 0 : 2; 16351 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, 16352 MEM_BLOCK_ALL, hw_index, &map_entry)); 16353 16354 /* coverity[overrun-local : FALSE] */ 16355 if (soc_mem_field32_get(unit, mem, &map_entry, self[eindex])) { 16356 if (gport_count > 0) { 16357 gport[count] = node->gport; 16358 } 16359 count++; 16360 if ((count == gport_count) && (gport_count > 0)) { 16361 break; 16362 } 16363 } 16364 } 16365 } else { 16366 if (gport_count > 0) { 16367 gport[count++] = hw_cosq; 16368 } 16369 } 16370 if (count == gport_count) { 16371 break; 16372 } 16373 } 16374 16375 if (count == 0) { 16376 return BCM_E_NOT_FOUND; 16377 } 16378 *actual_gport_count = count; 16379 return BCM_E_NONE; 16380 } 16381 16382 16383 /* 16384 * Function: 16385 * bcm_ap_cosq_safc_class_mapping_set 16386 * Purpose: 16387 * Set SAFC mapping for port. 16388 * SAFC class is mapped to cosq or scheduler node gports. 16389 * Parameters: 16390 * unit - (IN) unit number 16391 * port - (IN) port number 16392 * array_count - (IN) count of mapping 16393 * mapping_array - (IN) mappings 16394 * Returns: 16395 * BCM_E_XXX 16396 */ 16397 int 16398 _bcm_ap_cosq_safc_class_mapping_set(int unit, bcm_gport_t port, 16399 int array_count, 16400 bcm_cosq_safc_class_mapping_t *mapping_array) 16401 { 16402 int index, count; 16403 int cur_class = 0; 16404 int safc_class[_BCM_AP_NUM_SAFC_CLASS]; 16405 bcm_gport_t cur_gport = 0; 16406 uint32 cos_bmp[_BCM_AP_NUM_SAFC_CLASS] = {0}; 16407 bcm_port_t local_port = -1; 16408 16409 BCM_IF_ERROR_RETURN 16410 (_bcm_ap_cosq_localport_resolve(unit, port, &local_port)); 16411 16412 if (local_port < 0) { 16413 return BCM_E_PORT; 16414 } 16415 16416 if (IS_CPU_PORT(unit, local_port)) { 16417 return BCM_E_PARAM; 16418 } 16419 16420 if ((array_count < 0) || (array_count > _BCM_AP_NUM_SAFC_CLASS)) { 16421 return BCM_E_PARAM; 16422 } 16423 16424 if (mapping_array == NULL) { 16425 return BCM_E_PARAM; 16426 } 16427 if (!IS_HG_PORT(unit, local_port)) { 16428 return BCM_E_PARAM; 16429 } 16430 16431 for (count = 0; count < array_count; count++) { 16432 cur_class = mapping_array[count].class_id; 16433 if ((cur_class < 0) || (cur_class >= _BCM_AP_NUM_SAFC_CLASS)) { 16434 return BCM_E_PARAM; 16435 } else { 16436 cos_bmp[cur_class] = 0; 16437 } 16438 16439 for (index = 0; index < BCM_COSQ_SAFC_GPORT_COUNT; index++) { 16440 cur_gport = mapping_array[count].gport_list[index]; 16441 if (cur_gport == BCM_GPORT_INVALID) { 16442 break; 16443 } 16444 16445 if ((BCM_GPORT_IS_UCAST_QUEUE_GROUP(cur_gport)) || 16446 (BCM_GPORT_IS_MCAST_QUEUE_GROUP(cur_gport))) { 16447 BCM_IF_ERROR_RETURN 16448 (_bcm_ap_fc_status_map_gport(unit, local_port, cur_gport, 16449 _BCM_AP_COSQ_FC_SAFC, 16450 &cos_bmp[cur_class])); 16451 } else { 16452 return BCM_E_PARAM; 16453 } 16454 } 16455 } 16456 16457 for (index = 0; index < _BCM_AP_NUM_SAFC_CLASS; index++) { 16458 safc_class[index] = index; 16459 } 16460 BCM_IF_ERROR_RETURN(_bcm_ap_port_fc_profile_set(unit, local_port, 16461 _BCM_COSQ_OP_SET, _BCM_AP_NUM_SAFC_CLASS, safc_class, cos_bmp)); 16462 16463 return BCM_E_NONE; 16464 } 16465 16466 /* 16467 * Function: 16468 * bcm_ap_cosq_safc_class_mapping_get 16469 * Purpose: 16470 * Get SAFC mapping for port. 16471 * Retrieves cosq or scheduler node gports 16472 * associated to SAFC classes. 16473 * Parameters: 16474 * unit - (IN) unit number 16475 * port - (IN) port number 16476 * array_max - (IN) max retrieve count 16477 * mapping_array - (OUT) mappings 16478 * array_count - (OUT) retrieved mapping count 16479 * Returns: 16480 * BCM_E_XXX 16481 */ 16482 int 16483 _bcm_ap_cosq_safc_class_mapping_get(int unit, bcm_gport_t port, 16484 int array_max, 16485 bcm_cosq_safc_class_mapping_t *mapping_array, 16486 int *array_count) 16487 { 16488 int rv = 0; 16489 int cur_class = 0; 16490 int actual_gport_count, class_count = 0; 16491 bcm_port_t local_port = -1; 16492 16493 BCM_IF_ERROR_RETURN 16494 (_bcm_ap_cosq_localport_resolve(unit, port, &local_port)); 16495 16496 if (local_port < 0) { 16497 return BCM_E_PORT; 16498 } 16499 16500 if (IS_CPU_PORT(unit, local_port)) { 16501 return BCM_E_PARAM; 16502 } 16503 if (!IS_HG_PORT(unit, local_port)) { 16504 return BCM_E_PARAM; 16505 } 16506 16507 if (((mapping_array == NULL) && (array_max > 0)) || 16508 ((mapping_array != NULL) && (array_max <= 0)) || 16509 (array_count == NULL)) { 16510 return BCM_E_PARAM; 16511 } 16512 16513 if (array_max <= 0) { 16514 *array_count = _BCM_AP_NUM_SAFC_CLASS; 16515 return BCM_E_NONE; 16516 } 16517 16518 for (cur_class = 0; cur_class < _BCM_AP_NUM_SAFC_CLASS; cur_class++) { 16519 actual_gport_count = 0; 16520 rv = _bcm_ap_cosq_port_safc_get(unit, port, cur_class, 16521 mapping_array[cur_class].gport_list, 16522 BCM_COSQ_SAFC_GPORT_COUNT, &actual_gport_count); 16523 16524 if (rv == BCM_E_NONE) { 16525 mapping_array[cur_class].class_id = cur_class; 16526 if (actual_gport_count < BCM_COSQ_SAFC_GPORT_COUNT) { 16527 mapping_array[cur_class].gport_list[actual_gport_count] = 16528 BCM_GPORT_INVALID; 16529 } 16530 class_count++; 16531 } else if (rv == BCM_E_NOT_FOUND) { 16532 return rv; 16533 } 16534 16535 if (class_count == array_max) { 16536 break; 16537 } 16538 } 16539 16540 *array_count = class_count; 16541 if (class_count == 0) { 16542 return BCM_E_NOT_FOUND; 16543 } 16544 16545 return BCM_E_NONE; 16546 } 16547 16548 int 16549 _bcm_ap_cosq_pfc_class_resolve(bcm_switch_control_t sctype, int *type, 16550 int *class) 16551 { 16552 switch (sctype) { 16553 case bcmSwitchPFCClass7Queue: 16554 case bcmSwitchPFCClass6Queue: 16555 case bcmSwitchPFCClass5Queue: 16556 case bcmSwitchPFCClass4Queue: 16557 case bcmSwitchPFCClass3Queue: 16558 case bcmSwitchPFCClass2Queue: 16559 case bcmSwitchPFCClass1Queue: 16560 case bcmSwitchPFCClass0Queue: 16561 *type = _BCM_AP_COSQ_TYPE_UCAST; 16562 break; 16563 case bcmSwitchPFCClass7McastQueue: 16564 case bcmSwitchPFCClass6McastQueue: 16565 case bcmSwitchPFCClass5McastQueue: 16566 case bcmSwitchPFCClass4McastQueue: 16567 case bcmSwitchPFCClass3McastQueue: 16568 case bcmSwitchPFCClass2McastQueue: 16569 case bcmSwitchPFCClass1McastQueue: 16570 case bcmSwitchPFCClass0McastQueue: 16571 *type = _BCM_AP_COSQ_TYPE_MCAST; 16572 break; 16573 case bcmSwitchPFCClass7DestmodQueue: 16574 case bcmSwitchPFCClass6DestmodQueue: 16575 case bcmSwitchPFCClass5DestmodQueue: 16576 case bcmSwitchPFCClass4DestmodQueue: 16577 case bcmSwitchPFCClass3DestmodQueue: 16578 case bcmSwitchPFCClass2DestmodQueue: 16579 case bcmSwitchPFCClass1DestmodQueue: 16580 case bcmSwitchPFCClass0DestmodQueue: 16581 *type = _BCM_AP_COSQ_TYPE_EXT_UCAST; 16582 break; 16583 default: 16584 return BCM_E_PARAM; 16585 } 16586 16587 switch (sctype) { 16588 case bcmSwitchPFCClass7Queue: 16589 case bcmSwitchPFCClass7McastQueue: 16590 case bcmSwitchPFCClass7DestmodQueue: 16591 *class = 7; 16592 break; 16593 case bcmSwitchPFCClass6Queue: 16594 case bcmSwitchPFCClass6McastQueue: 16595 case bcmSwitchPFCClass6DestmodQueue: 16596 *class = 6; 16597 break; 16598 case bcmSwitchPFCClass5Queue: 16599 case bcmSwitchPFCClass5McastQueue: 16600 case bcmSwitchPFCClass5DestmodQueue: 16601 *class = 5; 16602 break; 16603 case bcmSwitchPFCClass4Queue: 16604 case bcmSwitchPFCClass4McastQueue: 16605 case bcmSwitchPFCClass4DestmodQueue: 16606 *class = 4; 16607 break; 16608 case bcmSwitchPFCClass3Queue: 16609 case bcmSwitchPFCClass3McastQueue: 16610 case bcmSwitchPFCClass3DestmodQueue: 16611 *class = 3; 16612 break; 16613 case bcmSwitchPFCClass2Queue: 16614 case bcmSwitchPFCClass2McastQueue: 16615 case bcmSwitchPFCClass2DestmodQueue: 16616 *class = 2; 16617 break; 16618 case bcmSwitchPFCClass1Queue: 16619 case bcmSwitchPFCClass1McastQueue: 16620 case bcmSwitchPFCClass1DestmodQueue: 16621 *class = 1; 16622 break; 16623 case bcmSwitchPFCClass0Queue: 16624 case bcmSwitchPFCClass0McastQueue: 16625 case bcmSwitchPFCClass0DestmodQueue: 16626 *class = 0; 16627 break; 16628 /* 16629 * COVERITY 16630 * 16631 * This default is unreachable but needed for some compiler. 16632 */ 16633 /* coverity[dead_error_begin] */ 16634 default: 16635 return BCM_E_INTERNAL; 16636 } 16637 return BCM_E_NONE; 16638 } 16639 16640 STATIC int 16641 _bcm_ap_clear_fc_status_to_node(int unit, int port) 16642 { 16643 uint32 map_entry[SOC_MAX_MEM_WORDS]; 16644 static const soc_field_t self[]={ 16645 SEL0f, SEL1f, SEL2f, SEL3f 16646 }; 16647 static const soc_field_t indexf[] = { 16648 INDEX0f, INDEX1f, INDEX2f, INDEX3f 16649 }; 16650 static const soc_mem_t memx[] = { 16651 MMU_INTFI_XPIPE_FC_MAP_TBS1m, 16652 MMU_INTFI_XPIPE_FC_MAP_TBL0m, 16653 MMU_INTFI_XPIPE_FC_MAP_TBL1m, 16654 MMU_INTFI_XPIPE_FC_MAP_TBL2m 16655 }; 16656 uint32 s_value, i_value; 16657 int base, table, index, count, field; 16658 int mmu_port, phy_port, update; 16659 16660 soc_info_t *soc_info; 16661 soc_info = &SOC_INFO(unit); 16662 16663 phy_port = soc_info->port_l2p_mapping[port]; 16664 mmu_port = soc_info->port_p2m_mapping[phy_port]; 16665 base = mmu_port * 4; 16666 for (table = 0; table < COUNTOF(memx); table++){ 16667 count = soc_mem_index_count(unit, memx[table]); 16668 for (index = 0; index < count; index++){ 16669 update = 0; 16670 SOC_IF_ERROR_RETURN(soc_mem_read(unit, memx[table], 16671 MEM_BLOCK_ALL, index, &map_entry)); 16672 for (field = 0; field < COUNTOF(indexf); field++){ 16673 s_value = soc_mem_field32_get(unit, memx[table], 16674 &map_entry, self[field]); 16675 i_value = soc_mem_field32_get(unit, memx[table], 16676 &map_entry, indexf[field]); 16677 16678 if (s_value && (i_value >= base) && (i_value < (base + 4))) { 16679 soc_mem_field32_set(unit, memx[table], 16680 &map_entry, self[field], 0); 16681 soc_mem_field32_set(unit, memx[table], 16682 &map_entry, indexf[field], 0); 16683 update = 1; 16684 } 16685 } 16686 if (update){ 16687 SOC_IF_ERROR_RETURN(soc_mem_write(unit, memx[table], 16688 MEM_BLOCK_ALL, index, &map_entry)); 16689 } 16690 } 16691 } 16692 return BCM_E_NONE; 16693 } 16694 16695 16696 STATIC int 16697 _bcm_ap_map_fc_status_to_node(int unit, int port, _bcm_ap_fc_type_t fct, 16698 int spad_offset, int cosq, uint32 hw_index, int level) 16699 { 16700 int map_entry_index, eindex, pfc; 16701 uint32 map_entry[SOC_MAX_MEM_WORDS]; 16702 static const soc_field_t self[] = { 16703 SEL0f, SEL1f, SEL2f, SEL3f 16704 }; 16705 static const soc_field_t indexf[] = { 16706 INDEX0f, INDEX1f, INDEX2f, INDEX3f 16707 }; 16708 static const soc_mem_t memx[] = { 16709 INVALIDm, 16710 MMU_INTFI_XPIPE_FC_MAP_TBS1m, 16711 MMU_INTFI_XPIPE_FC_MAP_TBL0m, 16712 MMU_INTFI_XPIPE_FC_MAP_TBL1m, 16713 MMU_INTFI_XPIPE_FC_MAP_TBL2m 16714 }; 16715 soc_mem_t mem; 16716 int port_num = 0; 16717 int map_entry_index_num = 0; 16718 16719 if ((fct == _BCM_AP_COSQ_FC_PFC) || 16720 (fct == _BCM_AP_COSQ_FC_SAFC)) { 16721 pfc = 1; 16722 } else { 16723 pfc = 0; 16724 } 16725 mem = memx[level]; 16726 if (mem == INVALIDm) { 16727 return BCM_E_PARAM; 16728 } 16729 16730 /* FC_MAP_TBL[Level] has 4 Index[0-3], whose values become Index to PFC_ST_TBL. 16731 * Each Index of PFC_ST_TBL can point to congestion state of 4 Qs. 16732 * Hence each Entry of FC_MAP_TBL can refer to 16 Qs. 16733 * 16734 * NOTE: Index of FC_MAP_TBL CANNOT be used to point to Qs/Nodes belonging 16735 * to Different Ports. 16736 */ 16737 if (hw_index < _BCM_AP_NUM_L2_UC_LEAVES_PER_PIPE ) { 16738 /* UC queue */ 16739 if (IS_AP_HSP_PORT( unit, port )) { 16740 if (level == SOC_APACHE_NODE_LVL_L0) { 16741 /* SC/QM L0 nodes do not support FC. 16742 * Hence, L0 indices 4, 9, 14, 19 ... should not be configured 16743 * for FC. 16744 */ 16745 if ((hw_index % 5) > 3) { 16746 return BCM_E_PARAM; 16747 } 16748 /* Since 5th L0 index is not FC mapped, each Entry of 16749 * FC_MAP_TBL can refer to 20 L0 nodes with each field mapped 16750 * to first 4 L0 of each port. 16751 */ 16752 map_entry_index = hw_index / 20; 16753 eindex = (hw_index % 20) / 5; 16754 } else { 16755 /* SC/QM L1/L2 nodes do not support FC. 16756 * Hence, L1/L2 indices 8, 9, 18, 19 ... should not be configured 16757 * for FC. 16758 */ 16759 if ((hw_index % 10) > 7) { 16760 return BCM_E_PARAM; 16761 } 16762 /* A 2 bit shift occurs in HW for HSP ports to align with multiple of 8. 16763 * Thus 10-17 becomes 8-15, etc. 16764 */ 16765 port_num = hw_index / 10; 16766 map_entry_index_num = port_num * 2 + (((hw_index % 10) >= 4)? 1 : 0); 16767 map_entry_index = map_entry_index_num / 4; /* each entry contains 4 indexes */ 16768 eindex = map_entry_index_num & 0x3; 16769 } 16770 } else { 16771 map_entry_index = hw_index/16; 16772 eindex = (hw_index % 16) / 4; 16773 } 16774 } else { 16775 /* MC queue - Index Calculation 16776 * PFC can work only on 8 out of 10 MC queues of each port. 16777 * So in FC_MAP_TBL2, each Port will use only 2 Index(4 Qs each) for 16778 * MC Qs. 16779 * MC queue base starts at 16384, 16384/16 = 1024 16780 * Hence MC Qs starts at = Map_Tbl2_Idx[92] and Index2. 16781 */ 16782 int mcq_offset = hw_index % _BCM_AP_NUM_L2_UC_LEAVES_PER_PIPE; 16783 16784 if (((mcq_offset % 10) > 7) || (level != SOC_APACHE_NODE_LVL_L2)) { 16785 /* FC support only for Q0-7 */ 16786 return BCM_E_INTERNAL; 16787 } 16788 map_entry_index = hw_index - (mcq_offset * 2 / 10); 16789 map_entry_index /= 16; 16790 eindex = (mcq_offset % 10)/4; 16791 eindex += ((mcq_offset /10) % 2) ? 0 : 2; 16792 16793 } 16794 BCM_IF_ERROR_RETURN 16795 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, map_entry_index, &map_entry)); 16796 /* coverity[overrun-local : FALSE] */ 16797 soc_mem_field32_set(unit, mem, &map_entry, 16798 indexf[eindex], spad_offset + cosq/4); 16799 /* coverity[overrun-local : FALSE] */ 16800 soc_mem_field32_set(unit, mem, &map_entry, self[eindex], !!pfc); 16801 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, 16802 MEM_BLOCK_ALL, map_entry_index, &map_entry)); 16803 return BCM_E_NONE; 16804 } 16805 16806 16807 /* 16808 * Function: 16809 * _bcm_ap_fc_status_map_gport 16810 * Purpose: 16811 * Set mapping in FC_MAP_TBL for gport, and update cos_bmp with gport cosq. 16812 * Parameters: 16813 * unit - (IN) unit number 16814 * port - (IN) port number 16815 * gport - (IN) gport to be mapped 16816 * fct - (IN) FC type 16817 * cos_map - (OUT) hw_cosq of gport 16818 * Returns: 16819 * BCM_E_XXX 16820 */ 16821 STATIC int 16822 _bcm_ap_fc_status_map_gport(int unit, int port, 16823 bcm_gport_t gport, _bcm_ap_fc_type_t fct, uint32 *cos_bmp) 16824 { 16825 int hw_index, hw_index1; 16826 int hw_cosq, hw_cosq1; 16827 int id, lvl; 16828 int pipe, mmu_port, phy_port; 16829 bcm_port_t local_port, resolved_port; 16830 _bcm_ap_cosq_node_t *node; 16831 _bcm_ap_pipe_resources_t *res; 16832 _bcm_ap_cosq_port_info_t *port_info; 16833 soc_info_t *si; 16834 _bcm_ap_mmu_info_t *mmu_info; 16835 16836 BCM_IF_ERROR_RETURN 16837 (_bcm_ap_cosq_localport_resolve(unit, port, &local_port)); 16838 16839 si = &SOC_INFO(unit); 16840 phy_port = si->port_l2p_mapping[local_port]; 16841 mmu_port = si->port_p2m_mapping[phy_port]; 16842 16843 mmu_info = _bcm_ap_mmu_info[unit]; 16844 port_info = &mmu_info->port_info[local_port]; 16845 pipe = _BCM_AP_PORT_TO_PIPE(unit, local_port); 16846 res = _BCM_AP_PRESOURCES(mmu_info, pipe); 16847 16848 hw_index = hw_index1 = -1; 16849 hw_cosq = hw_cosq1 = -1; 16850 if (BCM_GPORT_IS_SET(gport)) { 16851 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_node_get(unit, gport, 16852 0, NULL, &resolved_port, &id, &node)); 16853 hw_index = node->hw_index; 16854 hw_cosq = node->hw_cosq; 16855 lvl = node->level; 16856 } else { 16857 if (_bcm_ap_cosq_port_has_ets(unit, local_port)) { 16858 hw_cosq = gport; 16859 node = &res->p_queue_node[port_info->uc_base + hw_cosq]; 16860 hw_index = node->hw_index; 16861 node = &res->p_mc_queue_node[port_info->mc_base + hw_cosq]; 16862 hw_index1 = node->hw_index; 16863 hw_cosq1 = hw_cosq; 16864 lvl = SOC_APACHE_NODE_LVL_L2; 16865 } else { 16866 lvl = SOC_APACHE_NODE_LVL_L1; 16867 /* gport[] represnts the physical Cos value */ 16868 hw_cosq = gport; 16869 BCM_IF_ERROR_RETURN(soc_apache_sched_hw_index_get(unit, local_port, 16870 SOC_APACHE_NODE_LVL_L1, hw_cosq, &hw_index)); 16871 } 16872 } 16873 BCM_IF_ERROR_RETURN( 16874 _bcm_ap_map_fc_status_to_node(unit, local_port, fct, 16875 mmu_port*4, hw_cosq, hw_index, lvl)); 16876 if (cos_bmp != NULL) { 16877 *cos_bmp |= 1 << hw_cosq; 16878 } 16879 if (hw_cosq1 >= 0) { 16880 BCM_IF_ERROR_RETURN( 16881 _bcm_ap_map_fc_status_to_node(unit, local_port, fct, 16882 mmu_port*4, hw_cosq1, hw_index1, lvl)); 16883 if (cos_bmp != NULL) { 16884 *cos_bmp |= 1 << hw_cosq1; 16885 } 16886 } 16887 16888 return BCM_E_NONE; 16889 } 16890 16891 16892 /* 16893 * Function: 16894 * _bcm_ap_port_fc_profile_set 16895 * Purpose: 16896 * Set PFC mapping profile for port. Updates PRIO2COS_PROFILE & PORT_PFC_CFG. 16897 * Parameters: 16898 * unit - (IN) unit number 16899 * port - (IN) port number 16900 * op - (IN) operation type 16901 * entry_cnt - (IN) count of bmp 16902 * pfc_class - (IN) class list 16903 * cos_bmp - (IN) bmp list 16904 * Returns: 16905 * BCM_E_XXX 16906 */ 16907 STATIC int 16908 _bcm_ap_port_fc_profile_set(int unit, int port, _bcm_cosq_op_t op, 16909 int entry_cnt, int *pfc_class, uint32 *cos_bmp) 16910 { 16911 soc_reg_t reg; 16912 bcm_port_t local_port; 16913 int rv, entry, cur_class; 16914 int mmu_port, phy_port; 16915 uint32 profile_index, old_profile_index; 16916 uint32 fval, tmp32, cur_bmp; 16917 uint64 rval64[16], tmp, *rval64s[1], rval, index_map; 16918 soc_info_t *si; 16919 static const soc_reg_t llfc_cfgr[] = { 16920 PORT_PFC_CFG0r, PORT_PFC_CFG1r, PORT_PFC_CFG2r 16921 }; 16922 16923 if (pfc_class == NULL) { 16924 return BCM_E_PARAM; 16925 } 16926 if (cos_bmp == NULL) { 16927 return BCM_E_PARAM; 16928 } 16929 if ((entry_cnt < 0 ) || (entry_cnt > _BCM_AP_NUM_SAFC_CLASS)) { 16930 return BCM_E_PARAM; 16931 } 16932 16933 BCM_IF_ERROR_RETURN( 16934 _bcm_ap_cosq_localport_resolve(unit, port, &local_port)); 16935 16936 si = &SOC_INFO(unit); 16937 phy_port = si->port_l2p_mapping[local_port]; 16938 mmu_port = si->port_p2m_mapping[phy_port]; 16939 16940 reg = llfc_cfgr[mmu_port/32]; 16941 rval64s[0] = rval64; 16942 BCM_IF_ERROR_RETURN(soc_reg64_get(unit, reg, 0, 0, &rval)); 16943 16944 index_map = soc_reg64_field_get(unit, reg, rval, PROFILE_INDEXf); 16945 COMPILER_64_SHR(index_map, ((mmu_port % 32) * 2)); 16946 COMPILER_64_TO_32_LO(tmp32, index_map); 16947 old_profile_index = (tmp32 & 3)*16; 16948 BCM_IF_ERROR_RETURN 16949 (soc_profile_reg_get(unit, _bcm_ap_llfc_profile[unit], 16950 old_profile_index, 16, rval64s)); 16951 16952 for (entry = 0; entry < entry_cnt; entry++) { 16953 cur_class = pfc_class[entry]; 16954 cur_bmp = cos_bmp[entry]; 16955 if (op == _BCM_COSQ_OP_SET) { 16956 soc_reg64_field32_set(unit, PRIO2COS_PROFILEr, &rval64[cur_class], 16957 COS_BMPf, cur_bmp); 16958 } else { 16959 if (cur_bmp != 0) { 16960 fval = soc_reg64_field32_get(unit, PRIO2COS_PROFILEr, 16961 rval64[cur_class], COS_BMPf); 16962 if (op == _BCM_COSQ_OP_ADD) { 16963 fval |= cur_bmp; 16964 } else { /* _BCM_COSQ_OP_DELETE */ 16965 fval &= ~cur_bmp; 16966 } 16967 soc_reg64_field32_set(unit, PRIO2COS_PROFILEr, 16968 &rval64[cur_class], COS_BMPf, fval); 16969 } 16970 } 16971 } 16972 16973 BCM_IF_ERROR_RETURN 16974 (soc_profile_reg_delete(unit, _bcm_ap_llfc_profile[unit], 16975 old_profile_index)); 16976 16977 rv = soc_profile_reg_add(unit, _bcm_ap_llfc_profile[unit], rval64s, 16978 16, &profile_index); 16979 if (SOC_FAILURE(rv)) { 16980 BCM_IF_ERROR_RETURN 16981 (soc_profile_reg_reference(unit, _bcm_ap_llfc_profile[unit], 16982 old_profile_index, 16)); 16983 return rv; 16984 } 16985 16986 16987 index_map = soc_reg64_field_get(unit, reg, rval, PROFILE_INDEXf); 16988 16989 COMPILER_64_SET(tmp, 0, 3); 16990 COMPILER_64_SHL(tmp, (mmu_port % 32) * 2); 16991 COMPILER_64_NOT(tmp); 16992 COMPILER_64_AND(index_map, tmp); 16993 COMPILER_64_SET(tmp, 0, profile_index/16); 16994 COMPILER_64_SHL(tmp, (mmu_port % 32) * 2); 16995 COMPILER_64_OR(index_map, tmp); 16996 16997 soc_reg64_field_set(unit, reg, &rval, PROFILE_INDEXf, 16998 index_map); 16999 17000 BCM_IF_ERROR_RETURN(soc_reg64_set(unit, reg, 0, 0, rval)); 17001 return BCM_E_NONE; 17002 } 17003 /* 17004 * Function: 17005 * _bcm_ap_fc_map_gport_check 17006 * Purpose: 17007 * Validate if a gport can be mapped to a port's PFC/FC status. 17008 * Parameters: 17009 * unit - (IN) unit number 17010 * port - (IN) port number 17011 * gport - (IN) gport that will be mapped 17012 * Returns: 17013 * BCM_E_XXX 17014 */ 17015 STATIC int 17016 _bcm_ap_fc_map_gport_check(int unit, 17017 bcm_gport_t port, 17018 bcm_gport_t gport) 17019 { 17020 bcm_port_t local_port = -1, resolved_port; 17021 int hw_cosq, pipe; 17022 _bcm_ap_pipe_resources_t *res; 17023 _bcm_ap_cosq_port_info_t *port_info; 17024 _bcm_ap_mmu_info_t *mmu_info; 17025 _bcm_ap_cosq_node_t *node; 17026 17027 BCM_IF_ERROR_RETURN 17028 (_bcm_ap_cosq_localport_resolve(unit, port, &local_port)); 17029 17030 if (local_port < 0) { 17031 return BCM_E_PORT; 17032 } 17033 17034 mmu_info = _bcm_ap_mmu_info[unit]; 17035 port_info = &mmu_info->port_info[local_port]; 17036 pipe = _BCM_AP_PORT_TO_PIPE(unit, local_port); 17037 res = _BCM_AP_PRESOURCES(mmu_info, pipe); 17038 17039 hw_cosq = -1; 17040 if (BCM_GPORT_IS_SET(gport)) { 17041 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_node_get(unit, gport, 17042 0, NULL, &resolved_port, NULL, &node)); 17043 if (!((node->type == _BCM_AP_NODE_UCAST) || 17044 (node->type == _BCM_AP_NODE_MCAST) || 17045 (node->type == _BCM_AP_NODE_SCHEDULER))) { 17046 return BCM_E_PARAM; 17047 } 17048 if (resolved_port != local_port) { 17049 return BCM_E_PARAM; 17050 } 17051 hw_cosq = node->hw_cosq; 17052 } else { 17053 hw_cosq = gport; 17054 if (_bcm_ap_cosq_port_has_ets(unit, local_port)) { 17055 node = &res->p_queue_node[port_info->uc_base + hw_cosq]; 17056 if ((!node->in_use) || (node->attached_to_input == -1)) { 17057 return BCM_E_PARAM; 17058 } 17059 node = &res->p_mc_queue_node[port_info->mc_base + hw_cosq]; 17060 if ((!node->in_use) || (node->attached_to_input == -1)) { 17061 return BCM_E_PARAM; 17062 } 17063 } 17064 } 17065 if ((hw_cosq < 0) || (hw_cosq >= _AP_NUM_INTERNAL_PRI)) { 17066 return BCM_E_PARAM; 17067 } 17068 17069 return BCM_E_NONE; 17070 } 17071 17072 /* 17073 * Function: 17074 * _bcm_ap_pfc_class_mapping_check 17075 * Purpose: 17076 * Validate param of bcm_cosq_pfc_class_mapping_t. 17077 * Parameters: 17078 * unit - (IN) unit number 17079 * port - (IN) port number 17080 * array_count - (IN) count of mapping array 17081 * mapping_array - (IN) mapping array list 17082 * Returns: 17083 * BCM_E_XXX 17084 */ 17085 STATIC int 17086 _bcm_ap_pfc_class_mapping_check(int unit, 17087 bcm_gport_t port, 17088 int array_count, 17089 bcm_cosq_pfc_class_mapping_t *mapping_array) 17090 { 17091 int count, index, cur_class; 17092 bcm_gport_t cur_gport = 0; 17093 17094 if (mapping_array == NULL) { 17095 return BCM_E_PARAM; 17096 } 17097 17098 for (count = 0; count < array_count; count++) { 17099 cur_class = mapping_array[count].class_id; 17100 if ((cur_class < 0) || (cur_class >= _BCM_AP_NUM_PFC_CLASS)) { 17101 return BCM_E_PARAM; 17102 } 17103 17104 for (index = 0; index < BCM_COSQ_PFC_GPORT_COUNT; index++) { 17105 cur_gport = mapping_array[count].gport_list[index]; 17106 if (cur_gport == BCM_GPORT_INVALID) { 17107 break; 17108 } 17109 BCM_IF_ERROR_RETURN(_bcm_ap_fc_map_gport_check(unit, 17110 port, cur_gport)); 17111 } 17112 } 17113 17114 return BCM_E_NONE; 17115 } 17116 17117 17118 int 17119 bcm_ap_cosq_port_pfc_op(int unit, bcm_port_t port, 17120 bcm_switch_control_t sctype, _bcm_cosq_op_t op, 17121 bcm_gport_t *gport, int gport_count) 17122 { 17123 _bcm_ap_cosq_node_t *node; 17124 bcm_port_t local_port, resolved_port; 17125 int rv, type, class = -1, id, index, hw_cosq ; 17126 uint32 profile_index, old_profile_index; 17127 uint64 rval64[16], tmp, *rval64s[1], rval, index_map; 17128 uint32 fval, cos_bmp, tmp32; 17129 int hw_index; 17130 _bcm_ap_mmu_info_t *mmu_info; 17131 _bcm_ap_pipe_resources_t *res; 17132 _bcm_ap_cosq_port_info_t *port_info; 17133 soc_reg_t reg; 17134 int phy_port, mmu_port, lvl, pipe; 17135 soc_info_t *si; 17136 static const soc_reg_t llfc_cfgr[] = { 17137 PORT_PFC_CFG0r, PORT_PFC_CFG1r, PORT_PFC_CFG2r 17138 }; 17139 17140 if (gport_count < 0) { 17141 return BCM_E_PARAM; 17142 } 17143 17144 BCM_IF_ERROR_RETURN 17145 (_bcm_ap_cosq_localport_resolve(unit, port, &local_port)); 17146 17147 17148 for (index = 0; index < gport_count; index++) { 17149 BCM_IF_ERROR_RETURN(_bcm_ap_fc_map_gport_check(unit,port, gport[index])); 17150 } 17151 17152 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_pfc_class_resolve(sctype, &type, &class)); 17153 17154 si = &SOC_INFO(unit); 17155 phy_port = si->port_l2p_mapping[local_port]; 17156 mmu_port = si->port_p2m_mapping[phy_port]; 17157 17158 mmu_info = _bcm_ap_mmu_info[unit]; 17159 port_info = &mmu_info->port_info[local_port]; 17160 pipe = _BCM_AP_PORT_TO_PIPE(unit, local_port); 17161 res = _BCM_AP_PRESOURCES(mmu_info, pipe); 17162 17163 cos_bmp = 0; 17164 for (index = 0; index < gport_count; index++) { 17165 hw_index = -1; 17166 hw_cosq = -1; 17167 if (BCM_GPORT_IS_SET(gport[index])) { 17168 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_node_get(unit, gport[index], 17169 0, NULL, &resolved_port, &id, &node)); 17170 hw_index = node->hw_index; 17171 hw_cosq = node->hw_cosq; 17172 lvl = node->level; 17173 } else { 17174 hw_cosq = gport[index]; 17175 node = &res->p_queue_node[port_info->uc_base + hw_cosq]; 17176 node = node->parent; 17177 hw_index = node->hw_index; 17178 lvl = SOC_APACHE_NODE_LVL_L1; 17179 } 17180 if ((hw_cosq < 0) || (hw_cosq > 15)) { 17181 return BCM_E_PARAM; 17182 } 17183 BCM_IF_ERROR_RETURN( 17184 _bcm_ap_map_fc_status_to_node(unit, local_port, 17185 (op == _BCM_COSQ_OP_CLEAR) ? 0 : _BCM_AP_COSQ_FC_PFC, 17186 mmu_port*4, hw_cosq, hw_index, lvl)); 17187 cos_bmp |= 1 << hw_cosq; 17188 } 17189 17190 if (op == _BCM_COSQ_OP_CLEAR) { 17191 cos_bmp = (1 << _AP_NUM_INTERNAL_PRI) - 1; 17192 } 17193 17194 reg = llfc_cfgr[mmu_port/32]; 17195 rval64s[0] = rval64; 17196 BCM_IF_ERROR_RETURN(soc_reg64_get(unit, reg, 0, 0, &rval)); 17197 if (op == _BCM_COSQ_OP_SET || cos_bmp != 0) { 17198 index_map = soc_reg64_field_get(unit, reg, rval, PROFILE_INDEXf); 17199 COMPILER_64_SHR(index_map, ((mmu_port % 32) * 2)); 17200 COMPILER_64_TO_32_LO(tmp32, index_map); 17201 old_profile_index = (tmp32 & 3)*16; 17202 BCM_IF_ERROR_RETURN 17203 (soc_profile_reg_get(unit, _bcm_ap_llfc_profile[unit], 17204 old_profile_index, 16, rval64s)); 17205 if (op == _BCM_COSQ_OP_SET) { 17206 soc_reg64_field32_set(unit, PRIO2COS_PROFILEr, &rval64[class], 17207 COS_BMPf, cos_bmp); 17208 } else if (cos_bmp != 0) { 17209 fval = soc_reg64_field32_get(unit, PRIO2COS_PROFILEr, rval64[class], 17210 COS_BMPf); 17211 if (op == _BCM_COSQ_OP_ADD) { 17212 fval |= cos_bmp; 17213 } else { /* _BCM_COSQ_OP_DELETE */ 17214 fval &= ~cos_bmp; 17215 } 17216 soc_reg64_field32_set(unit, PRIO2COS_PROFILEr, &rval64[class], 17217 COS_BMPf, fval); 17218 } 17219 17220 BCM_IF_ERROR_RETURN 17221 (soc_profile_reg_delete(unit, _bcm_ap_llfc_profile[unit], 17222 old_profile_index)); 17223 rv = soc_profile_reg_add(unit, _bcm_ap_llfc_profile[unit], rval64s, 17224 16, &profile_index); 17225 if (rv < 0) { 17226 BCM_IF_ERROR_RETURN 17227 (soc_profile_reg_reference(unit, _bcm_ap_llfc_profile[unit], 17228 old_profile_index, 16)); 17229 return rv; 17230 } 17231 17232 index_map = soc_reg64_field_get(unit, reg, rval, PROFILE_INDEXf); 17233 17234 COMPILER_64_SET(tmp, 0, 3); 17235 COMPILER_64_SHL(tmp, (mmu_port % 32) * 2); 17236 COMPILER_64_NOT(tmp); 17237 COMPILER_64_AND(index_map, tmp); 17238 COMPILER_64_SET(tmp, 0, profile_index/16); 17239 COMPILER_64_SHL(tmp, (mmu_port % 32) * 2); 17240 COMPILER_64_OR(index_map, tmp); 17241 17242 soc_reg64_field_set(unit, reg, &rval, PROFILE_INDEXf, 17243 index_map); 17244 17245 } 17246 17247 BCM_IF_ERROR_RETURN(soc_reg64_set(unit, reg, 0, 0, rval)); 17248 return BCM_E_NONE; 17249 } 17250 17251 int 17252 bcm_ap_cosq_port_pfc_get(int unit, bcm_port_t port, 17253 bcm_switch_control_t sctype, 17254 bcm_gport_t *gport, int gport_count, 17255 int *actual_gport_count) 17256 { 17257 _bcm_ap_cosq_node_t *node; 17258 bcm_port_t local_port; 17259 int type = -1, class = -1, hw_cosq, count = 0; 17260 uint32 profile_index; 17261 uint64 rval64[16], *rval64s[1], rval, index_map; 17262 uint32 tmp32, bmp, bmp_len; 17263 _bcm_ap_mmu_info_t *mmu_info; 17264 int phy_port, mmu_port; 17265 soc_info_t *si; 17266 soc_reg_t reg; 17267 int mc_index = 0 ; 17268 int mcq_offset = 0 ; 17269 _bcm_ap_pipe_resources_t *res; 17270 _bcm_ap_cosq_port_info_t *port_info; 17271 static const soc_reg_t llfc_cfgr[] = { 17272 PORT_PFC_CFG0r, PORT_PFC_CFG1r, PORT_PFC_CFG2r 17273 }; 17274 static const soc_field_t self[] = { 17275 SEL0f, SEL1f, SEL2f, SEL3f 17276 }; 17277 int j, inv_mapped, hw_index, eindex; 17278 soc_mem_t mem; 17279 uint32 map_entry[SOC_MAX_MEM_WORDS]; 17280 int port_num = 0 ; 17281 17282 if (((gport == NULL) && (gport_count > 0)) || actual_gport_count == NULL) { 17283 return BCM_E_PARAM; 17284 } 17285 17286 BCM_IF_ERROR_RETURN 17287 (_bcm_ap_cosq_localport_resolve(unit, port, &local_port)); 17288 17289 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_pfc_class_resolve(sctype, &type, &class)); 17290 17291 si = &SOC_INFO(unit); 17292 mmu_info = _bcm_ap_mmu_info[unit]; 17293 res = _BCM_AP_PRESOURCES(mmu_info, 0); 17294 phy_port = si->port_l2p_mapping[local_port]; 17295 mmu_port = si->port_p2m_mapping[phy_port]; 17296 port_info = &mmu_info->port_info[local_port]; 17297 17298 rval64s[0] = rval64; 17299 reg = llfc_cfgr[mmu_port/32]; 17300 BCM_IF_ERROR_RETURN(soc_reg64_get(unit, reg, REG_PORT_ANY, 0, &rval)); 17301 17302 index_map = soc_reg64_field_get(unit, reg, rval, PROFILE_INDEXf); 17303 COMPILER_64_SHR(index_map, ((mmu_port % 32) * 2)); 17304 COMPILER_64_TO_32_LO(tmp32, index_map); 17305 profile_index = (tmp32 & 3)*16; 17306 17307 BCM_IF_ERROR_RETURN 17308 (soc_profile_reg_get(unit, _bcm_ap_llfc_profile[unit], 17309 profile_index, 16, rval64s)); 17310 17311 bmp = soc_reg64_field32_get(unit, PRIO2COS_PROFILEr, rval64[class], 17312 COS_BMPf); 17313 bmp_len = soc_reg_field_length(unit, PRIO2COS_PROFILEr, COS_BMPf); 17314 for (hw_cosq = 0; hw_cosq < bmp_len; hw_cosq++) { 17315 if (!(bmp & (1 << hw_cosq))) { 17316 continue; 17317 } 17318 if (_bcm_ap_cosq_port_has_ets(unit, local_port)) { 17319 inv_mapped = 0; 17320 for (j = _BCM_AP_NUM_PORT_SCHEDULERS; 17321 j < _BCM_AP_NUM_TOTAL_SCHEDULERS; j++) { 17322 node = &mmu_info->sched_node[j]; 17323 if ((!node->in_use) || (node->local_port != local_port) || 17324 (node->hw_cosq != hw_cosq)) { 17325 continue; 17326 } 17327 17328 hw_index = (node->hw_index / 16); 17329 eindex = (node->hw_index % 16)/4; 17330 if (node->level == SOC_APACHE_NODE_LVL_L0) { 17331 mem = MMU_INTFI_XPIPE_FC_MAP_TBL0m; 17332 if (IS_AP_HSP_PORT(unit, port)) { 17333 hw_index = node->hw_index; 17334 /* SC/QM L0 nodes do not support FC */ 17335 if ((hw_index % 5) > 3) { 17336 break; 17337 } 17338 /* Since 5th L0 index is not FC mapped, each Entry of 17339 * FC_MAP_TBL can refer to 20 L0 nodes with each field mapped 17340 * to first 4 L0 of each port. 17341 */ 17342 eindex = (hw_index % 20) / 5; 17343 hw_index = hw_index / 20; 17344 } 17345 } else if (node->level == SOC_APACHE_NODE_LVL_L1) { 17346 mem = MMU_INTFI_XPIPE_FC_MAP_TBL1m; 17347 if (IS_AP_HSP_PORT(unit,port)) { 17348 hw_index = node->hw_index; 17349 if ((hw_index % 10) > 7) { 17350 /* FC support only for Q0-7 */ 17351 break; 17352 } 17353 port_num = hw_index / 10; 17354 hw_index = port_num * 2 + (((hw_index % 10) >= 4)? 1 : 0); 17355 eindex = hw_index & 0x3; 17356 hw_index = hw_index / 4; /* each entry contains 4 indexes */ 17357 } 17358 } else { 17359 continue; 17360 } 17361 17362 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, 17363 MEM_BLOCK_ALL, hw_index, &map_entry)); 17364 17365 /* coverity[overrun-local : FALSE] */ 17366 if (soc_mem_field32_get(unit, mem, &map_entry, self[eindex])) { 17367 if (gport_count > 0) { 17368 gport[count] = node->gport; 17369 } 17370 count++; 17371 if ((count == gport_count) && (gport_count > 0)) { 17372 inv_mapped = 1; 17373 break; 17374 } 17375 } 17376 } 17377 17378 for (j = port_info->uc_base; 17379 inv_mapped==0 && (j < port_info->uc_limit); j++) { 17380 node = &res->p_queue_node[j]; 17381 if ((!node->in_use) || (node->local_port != local_port)) { 17382 continue; 17383 } 17384 if (node->hw_cosq != hw_cosq) { 17385 continue; 17386 } 17387 mem = MMU_INTFI_XPIPE_FC_MAP_TBL2m ; 17388 if (IS_AP_HSP_PORT(unit,port)) { 17389 hw_index = node->hw_index; 17390 if ((hw_index % 10) > 7) { 17391 /* FC support only for Q0-7 */ 17392 break; 17393 } 17394 port_num = hw_index / 10; 17395 hw_index = port_num * 2 + 17396 (((hw_index % 10) >= 4)? 1 : 0); 17397 eindex = hw_index & 0x3; 17398 hw_index = hw_index / 4; /* each entry contains 4 indexes */ 17399 } else 17400 { 17401 hw_index = (node->hw_index / 16); 17402 eindex = (node->hw_index % 16)/4; 17403 } 17404 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, 17405 MEM_BLOCK_ALL, hw_index, &map_entry)); 17406 17407 /* coverity[overrun-local : FALSE] */ 17408 if (soc_mem_field32_get(unit, mem, &map_entry, self[eindex])) { 17409 if (gport_count > 0) { 17410 gport[count] = node->gport; 17411 } 17412 count++ ; 17413 if ((count == gport_count) && (gport_count > 0)) { 17414 inv_mapped = 1; 17415 break; 17416 } 17417 } 17418 } 17419 for (j = port_info->mc_base; 17420 inv_mapped==0 && (j < port_info->mc_limit); j++) { 17421 mc_index = soc_apache_l2_hw_index(unit, j, 0); 17422 node = &res->p_queue_node[mc_index]; 17423 if ((!node->in_use) || (node->local_port != local_port)) { 17424 continue; 17425 } 17426 if (node->hw_cosq != hw_cosq) { 17427 continue; 17428 } 17429 mem = MMU_INTFI_XPIPE_FC_MAP_TBL2m ; 17430 mcq_offset = node->hw_index % _BCM_AP_NUM_L2_UC_LEAVES_PER_PIPE; 17431 if (((mcq_offset % 10) > 7) ) { 17432 /* FC support only for Q0-7 */ 17433 continue; 17434 } 17435 hw_index = node->hw_index - (mcq_offset * 2 / 10); 17436 hw_index /= 16; 17437 eindex = (mcq_offset % 10)/4; 17438 eindex += ((mcq_offset /10) % 2) ? 0 : 2; 17439 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, 17440 MEM_BLOCK_ALL, hw_index, &map_entry)); 17441 17442 /* coverity[overrun-local : FALSE] */ 17443 if (soc_mem_field32_get(unit, mem, &map_entry, self[eindex])) { 17444 if (gport_count > 0) { 17445 gport[count] = node->gport; 17446 } 17447 count++; 17448 if ((count == gport_count) && (gport_count > 0)) { 17449 /* coverity[assigned_value : FALSE] */ 17450 inv_mapped = 1; 17451 break; 17452 } 17453 } 17454 } 17455 } else { 17456 if (gport_count > 0) { 17457 gport[count++] = hw_cosq; 17458 } 17459 } 17460 if (count == gport_count) { 17461 break; 17462 } 17463 } 17464 17465 if (count == 0) { 17466 return BCM_E_NOT_FOUND; 17467 } 17468 *actual_gport_count = count; 17469 return BCM_E_NONE; 17470 } 17471 17472 /* 17473 * Function: 17474 * bcm_ap_cosq_pfc_class_mapping_set 17475 * Purpose: 17476 * Set PFC mapping for port. PFC class is mapped to cosq or scheduler node gports. 17477 * Parameters: 17478 * unit - (IN) unit number 17479 * port - (IN) port number 17480 * array_count - (IN) count of mapping 17481 * mapping_array - (IN) mappings 17482 * Returns: 17483 * BCM_E_XXX 17484 */ 17485 int 17486 _bcm_ap_cosq_pfc_class_mapping_set(int unit, 17487 bcm_gport_t port, 17488 int array_count, 17489 bcm_cosq_pfc_class_mapping_t *mapping_array) 17490 { 17491 int index, count; 17492 int cur_class = 0, pfc_class[_BCM_AP_NUM_PFC_CLASS]; 17493 bcm_gport_t cur_gport = 0; 17494 uint32 cos_bmp[_BCM_AP_NUM_PFC_CLASS]; 17495 int local_port = 0 ; 17496 17497 BCM_IF_ERROR_RETURN 17498 (_bcm_ap_cosq_localport_resolve(unit, port, &local_port)); 17499 17500 if (local_port < 0) { 17501 return BCM_E_PORT; 17502 } 17503 17504 if (IS_CPU_PORT(unit, local_port)) { 17505 return BCM_E_PARAM; 17506 } 17507 if ((array_count < 0) || (array_count > _BCM_AP_NUM_PFC_CLASS)) { 17508 return BCM_E_PARAM; 17509 } 17510 if (mapping_array == NULL) { 17511 return BCM_E_PARAM; 17512 } 17513 17514 BCM_IF_ERROR_RETURN( _bcm_ap_pfc_class_mapping_check(unit,port, 17515 array_count,mapping_array)); 17516 _bcm_ap_clear_fc_status_to_node(unit, port); 17517 17518 sal_memset(cos_bmp, 0, sizeof(cos_bmp)); 17519 17520 for (count = 0; count < array_count; count++) { 17521 cur_class = mapping_array[count].class_id; 17522 17523 for (index = 0; index < BCM_COSQ_PFC_GPORT_COUNT; index++) { 17524 cur_gport = mapping_array[count].gport_list[index]; 17525 if (cur_gport == BCM_GPORT_INVALID) { 17526 break; 17527 } 17528 17529 BCM_IF_ERROR_RETURN(_bcm_ap_fc_status_map_gport(unit, port, 17530 cur_gport, _BCM_AP_COSQ_FC_PFC, &cos_bmp[cur_class])); 17531 } 17532 } 17533 17534 for (index = 0; index < _BCM_AP_NUM_PFC_CLASS; index++) { 17535 pfc_class[index] = index; 17536 } 17537 BCM_IF_ERROR_RETURN(_bcm_ap_port_fc_profile_set(unit, port, 17538 _BCM_COSQ_OP_SET, _BCM_AP_NUM_PFC_CLASS, pfc_class, cos_bmp)); 17539 17540 return BCM_E_NONE; 17541 } 17542 17543 int 17544 _bcm_ap_cosq_pfc_class_mapping_get(int unit, 17545 bcm_gport_t port, 17546 int array_max, 17547 int *array_count, 17548 bcm_cosq_pfc_class_mapping_t *mapping_array) 17549 { 17550 int rv = 0; 17551 int cur_class = 0; 17552 int actual_gport_count, class_count = 0; 17553 int local_port = 0 ; 17554 bcm_switch_control_t sc[] = { bcmSwitchPFCClass0Queue, 17555 bcmSwitchPFCClass1Queue, 17556 bcmSwitchPFCClass2Queue, 17557 bcmSwitchPFCClass3Queue, 17558 bcmSwitchPFCClass4Queue, 17559 bcmSwitchPFCClass5Queue, 17560 bcmSwitchPFCClass6Queue, 17561 bcmSwitchPFCClass7Queue 17562 }; 17563 17564 BCM_IF_ERROR_RETURN 17565 (_bcm_ap_cosq_localport_resolve(unit, port, &local_port)); 17566 17567 if (local_port < 0) { 17568 return BCM_E_PORT; 17569 } 17570 17571 if (IS_CPU_PORT(unit, local_port)) { 17572 return BCM_E_PARAM; 17573 } 17574 if ((mapping_array == NULL) && (array_max > 0)) { 17575 return BCM_E_PARAM; 17576 } 17577 if (array_count == NULL) { 17578 return BCM_E_PARAM; 17579 } 17580 17581 for (cur_class = 0; cur_class < _BCM_AP_NUM_PFC_CLASS; cur_class++) { 17582 actual_gport_count = 0; 17583 if (array_max > 0) { 17584 rv = bcm_ap_cosq_port_pfc_get(unit, port, sc[cur_class], 17585 mapping_array[class_count].gport_list, 17586 BCM_COSQ_PFC_GPORT_COUNT, &actual_gport_count); 17587 } else { 17588 rv = bcm_ap_cosq_port_pfc_get(unit, port, sc[cur_class], 17589 NULL, -1, &actual_gport_count); 17590 } 17591 if (rv == BCM_E_NONE) { 17592 if (array_max > 0) { 17593 mapping_array[class_count].class_id = cur_class; 17594 if (actual_gport_count < BCM_COSQ_PFC_GPORT_COUNT) { 17595 mapping_array[class_count].gport_list[actual_gport_count] = 17596 BCM_GPORT_INVALID; 17597 } 17598 } 17599 class_count++; 17600 } else if (rv != BCM_E_NOT_FOUND) { 17601 return rv; 17602 } 17603 17604 if ((class_count == array_max) && (array_max > 0)) { 17605 break; 17606 } 17607 } 17608 17609 *array_count = class_count; 17610 if (class_count == 0) { 17611 return BCM_E_NOT_FOUND; 17612 } 17613 return BCM_E_NONE; 17614 } 17615 17616 /* 17617 * Function: 17618 * bcm_ap_cosq_default_llfc_profile_attach 17619 * Purpose: 17620 * Add default entries for PRIO2COS_PROFILE register profile 17621 * Parameters: 17622 * unit - (IN) unit number 17623 * port - (IN) port number 17624 * Returns: 17625 * BCM_E_XXX 17626 */ 17627 int 17628 bcm_ap_cosq_default_llfc_profile_attach(int unit, int port) 17629 { 17630 soc_reg_t reg; 17631 soc_info_t *si; 17632 bcm_port_t local_port; 17633 int mmu_port, phy_port; 17634 uint32 profile_index; 17635 uint64 tmp, rval, index_map; 17636 uint64 rval64s[16], *prval64s[1]; 17637 static const soc_reg_t llfc_cfgr[] = { 17638 PORT_PFC_CFG0r, PORT_PFC_CFG1r, PORT_PFC_CFG2r 17639 }; 17640 17641 BCM_IF_ERROR_RETURN( 17642 _bcm_ap_cosq_localport_resolve(unit, port, &local_port)); 17643 17644 si = &SOC_INFO(unit); 17645 phy_port = si->port_l2p_mapping[local_port]; 17646 mmu_port = si->port_p2m_mapping[phy_port]; 17647 reg = llfc_cfgr[mmu_port/32]; 17648 17649 /* Add default entries for PRIO2COS_PROFILE register profile */ 17650 sal_memset(rval64s, 0, sizeof(rval64s)); 17651 prval64s[0] = rval64s; 17652 17653 BCM_IF_ERROR_RETURN 17654 (soc_profile_reg_add(unit, _bcm_ap_llfc_profile[unit], 17655 prval64s, 16, &profile_index)); 17656 17657 BCM_IF_ERROR_RETURN(soc_reg64_get(unit, reg, 0, 0, &rval)); 17658 index_map = soc_reg64_field_get(unit, reg, rval, PROFILE_INDEXf); 17659 17660 COMPILER_64_SET(tmp, 0, 3); 17661 COMPILER_64_SHL(tmp, (mmu_port % 32) * 2); 17662 COMPILER_64_NOT(tmp); 17663 COMPILER_64_AND(index_map, tmp); 17664 COMPILER_64_SET(tmp, 0, profile_index/16); 17665 COMPILER_64_SHL(tmp, (mmu_port % 32) * 2); 17666 COMPILER_64_OR(index_map, tmp); 17667 17668 soc_reg64_field_set(unit, reg, &rval, PROFILE_INDEXf, 17669 index_map); 17670 17671 BCM_IF_ERROR_RETURN(soc_reg64_set(unit, reg, 0, 0, rval)); 17672 17673 return BCM_E_NONE; 17674 } 17675 17676 /* 17677 * Function: 17678 * bcm_ap_cosq_llfc_profile_detach 17679 * Purpose: 17680 * Delete old entries for PRIO2COS_PROFILE register profile 17681 * Parameters: 17682 * unit - (IN) unit number 17683 * port - (IN) port number 17684 * Returns: 17685 * BCM_E_XXX 17686 */ 17687 int 17688 bcm_ap_cosq_llfc_profile_detach(int unit, int port) 17689 { 17690 soc_reg_t reg; 17691 bcm_port_t local_port; 17692 int mmu_port, phy_port; 17693 uint32 old_profile_index; 17694 uint32 tmp32; 17695 uint64 rval, index_map; 17696 soc_info_t *si; 17697 static const soc_reg_t llfc_cfgr[] = { 17698 PORT_PFC_CFG0r, PORT_PFC_CFG1r, PORT_PFC_CFG2r 17699 }; 17700 17701 BCM_IF_ERROR_RETURN( 17702 _bcm_ap_cosq_localport_resolve(unit, port, &local_port)); 17703 17704 si = &SOC_INFO(unit); 17705 phy_port = si->port_l2p_mapping[local_port]; 17706 mmu_port = si->port_p2m_mapping[phy_port]; 17707 17708 reg = llfc_cfgr[mmu_port/32]; 17709 BCM_IF_ERROR_RETURN(soc_reg64_get(unit, reg, 0, 0, &rval)); 17710 17711 index_map = soc_reg64_field_get(unit, reg, rval, PROFILE_INDEXf); 17712 COMPILER_64_SHR(index_map, ((mmu_port % 32) * 2)); 17713 COMPILER_64_TO_32_LO(tmp32, index_map); 17714 old_profile_index = (tmp32 & 3)*16; 17715 17716 BCM_IF_ERROR_RETURN 17717 (soc_profile_reg_delete(unit, _bcm_ap_llfc_profile[unit], 17718 old_profile_index)); 17719 17720 return BCM_E_NONE; 17721 } 17722 17723 /* 17724 * Function: 17725 * bcm_ap_port_priority_group_mapping_set 17726 * Purpose: 17727 * Assign a Priority Group for the input priority. 17728 * Parameters: 17729 * unit - (IN) device id. 17730 * gport - (IN) generic port. 17731 * prio - (IN) input priority. 17732 * priority_group - (IN) PG ID that the input priority mapped to. 17733 * Returns: 17734 * BCM_E_XXX 17735 */ 17736 int 17737 bcm_ap_port_priority_group_mapping_set(int unit, bcm_gport_t gport, 17738 int prio, int priority_group) 17739 { 17740 bcm_port_t port; 17741 uint32 value; 17742 int field_count; 17743 soc_field_t fields_0[]={PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf, 17744 PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf}; 17745 soc_field_t fields_1[]={PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf, 17746 PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf}; 17747 17748 if (!soc_feature(unit, soc_feature_priority_flow_control)) { 17749 return BCM_E_UNAVAIL; 17750 } 17751 /* PFC : 0-7, SAFC : 0-15. Taking the larger range for comparison */ 17752 if ((prio < AP_SAFC_INPUT_PRIORITY_MIN) || 17753 (prio > AP_SAFC_INPUT_PRIORITY_MAX)) { 17754 return BCM_E_PARAM; 17755 } 17756 17757 if ((priority_group < AP_PRIOROTY_GROUP_ID_MIN) || 17758 (priority_group > AP_PRIOROTY_GROUP_ID_MAX)) { 17759 return BCM_E_PARAM; 17760 } 17761 17762 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_localport_resolve(unit, gport, &port)); 17763 if (!SOC_PORT_VALID(unit, port)) { 17764 return BCM_E_PORT; 17765 } 17766 field_count = COUNTOF(fields_0); 17767 if (prio < field_count) { 17768 /* input priority 0~7 */ 17769 BCM_IF_ERROR_RETURN(READ_THDI_PORT_PRI_GRP0r(unit, port, &value)); 17770 soc_reg_field_set(unit, THDI_PORT_PRI_GRP0r, &value, 17771 fields_0[prio], priority_group); 17772 BCM_IF_ERROR_RETURN(WRITE_THDI_PORT_PRI_GRP0r(unit, port, value)); 17773 } else { 17774 /* input priority 8~15 */ 17775 BCM_IF_ERROR_RETURN(READ_THDI_PORT_PRI_GRP1r(unit, port, &value)); 17776 soc_reg_field_set(unit, THDI_PORT_PRI_GRP1r, &value, 17777 fields_1[prio - field_count], priority_group); 17778 BCM_IF_ERROR_RETURN(WRITE_THDI_PORT_PRI_GRP1r(unit, port, value)); 17779 } 17780 17781 return BCM_E_NONE; 17782 } 17783 17784 /* 17785 * Function: 17786 * bcm_ap_port_priority_group_mapping_get 17787 * Purpose: 17788 * Get the assigned Priority Group ID of the input priority. 17789 * Parameters: 17790 * unit - (IN) device id. 17791 * gport - (IN) generic port. 17792 * prio - (IN) input priority. 17793 * priority_group - (OUT) PG ID that the input priority mapped to. 17794 * Returns: 17795 * BCM_E_XXX 17796 */ 17797 17798 int 17799 bcm_ap_port_priority_group_mapping_get(int unit, bcm_gport_t gport, 17800 int prio, int *priority_group) 17801 { 17802 bcm_port_t port; 17803 uint32 value; 17804 int field_count; 17805 soc_field_t fields_0[]={PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf, 17806 PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf}; 17807 soc_field_t fields_1[]={PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf, 17808 PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf}; 17809 17810 if (!soc_feature(unit, soc_feature_priority_flow_control)) { 17811 return BCM_E_UNAVAIL; 17812 } 17813 if (priority_group == NULL) { 17814 return BCM_E_PARAM; 17815 } 17816 /* PFC : 0-7, SAFC : 0-15. Taking the larger range for comparison */ 17817 if ((prio < AP_SAFC_INPUT_PRIORITY_MIN) || 17818 (prio > AP_SAFC_INPUT_PRIORITY_MAX)) { 17819 return BCM_E_PARAM; 17820 } 17821 17822 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_localport_resolve(unit, gport, &port)); 17823 if (!SOC_PORT_VALID(unit, port)) { 17824 return BCM_E_PORT; 17825 } 17826 field_count = COUNTOF(fields_0); 17827 if (prio < field_count) { 17828 /* input priority 0~7 */ 17829 BCM_IF_ERROR_RETURN(READ_THDI_PORT_PRI_GRP0r(unit, port, &value)); 17830 *priority_group = soc_reg_field_get(unit, THDI_PORT_PRI_GRP0r, 17831 value, fields_0[prio]); 17832 } else { 17833 /* input priority 8~15 */ 17834 BCM_IF_ERROR_RETURN(READ_THDI_PORT_PRI_GRP1r(unit, port, &value)); 17835 *priority_group = soc_reg_field_get(unit, THDI_PORT_PRI_GRP1r, 17836 value, 17837 fields_1[prio - field_count]); 17838 } 17839 17840 return BCM_E_NONE; 17841 } 17842 17843 17844 int 17845 bcm_ap_cosq_drop_status_enable_set(int unit, bcm_port_t port, int enable) 17846 { 17847 _bcm_ap_mmu_info_t *mmu_info; 17848 uint32 rval; 17849 17850 if ((mmu_info = _bcm_ap_mmu_info[unit]) == NULL) { 17851 return BCM_E_INIT; 17852 } 17853 17854 BCM_IF_ERROR_RETURN(READ_MMU_THDM_DB_QUEUE_E2E_DS_EN_0r(unit, port, &rval)); 17855 soc_reg_field_set(unit, MMU_THDM_DB_QUEUE_E2E_DS_EN_0r, &rval, Q_COS_E2E_DS_ENf, 17856 0xff); 17857 BCM_IF_ERROR_RETURN(WRITE_MMU_THDM_DB_QUEUE_E2E_DS_EN_0r(unit, port, rval)); 17858 17859 BCM_IF_ERROR_RETURN(READ_OP_THDU_CONFIGr(unit, &rval)); 17860 soc_reg_field_set(unit, OP_THDU_CONFIGr, &rval, EARLY_E2E_SELECTf, 17861 enable ? 1 : 0); 17862 BCM_IF_ERROR_RETURN(WRITE_OP_THDU_CONFIGr(unit, rval)); 17863 17864 return BCM_E_NONE; 17865 } 17866 17867 STATIC int 17868 _bcm_ap_voq_min_hw_index(int unit, bcm_port_t port, 17869 bcm_module_t modid, 17870 bcm_port_t remote_port, 17871 int *q_offset) 17872 { 17873 int i, hw_index_base = -1, pipe; 17874 _bcm_ap_cosq_node_t *node; 17875 _bcm_ap_pipe_resources_t *res; 17876 _bcm_ap_mmu_info_t *mmu_info; 17877 17878 mmu_info = _bcm_ap_mmu_info[unit]; 17879 pipe = _BCM_AP_PORT_TO_PIPE(unit, port); 17880 res = _BCM_AP_PRESOURCES(mmu_info, pipe); 17881 17882 for (i = res->num_base_queues; i < _BCM_AP_NUM_L2_UC_LEAVES_PER_PIPE; i++) { 17883 node = &res->p_queue_node[i]; 17884 if ((node->in_use == FALSE) || (node->hw_index == -1) || 17885 (node->type != _BCM_AP_NODE_VOQ)) { 17886 continue; 17887 } 17888 17889 if (((modid == -1) ? 1 : (node->remote_modid == modid)) && 17890 (node->remote_port == remote_port) && 17891 ((port == -1) ? 1 : (port == node->local_port))) { 17892 if (hw_index_base == -1) { 17893 hw_index_base = node->hw_index; 17894 break; 17895 } 17896 } 17897 } 17898 17899 if (hw_index_base != -1) { 17900 *q_offset = hw_index_base & ~7; 17901 return BCM_E_NONE; 17902 } 17903 17904 return BCM_E_NOT_FOUND; 17905 } 17906 17907 STATIC int 17908 _bcm_ap_voq_base_node_get(int unit, bcm_port_t port, 17909 int modid, 17910 _bcm_ap_cosq_node_t **base_node) 17911 { 17912 int i, pipe; 17913 _bcm_ap_pipe_resources_t *res; 17914 _bcm_ap_mmu_info_t *mmu_info; 17915 _bcm_ap_cosq_node_t *node; 17916 17917 mmu_info = _bcm_ap_mmu_info[unit]; 17918 pipe = _BCM_AP_PORT_TO_PIPE(unit, port); 17919 res = _BCM_AP_PRESOURCES(mmu_info, pipe); 17920 for ( i = res->num_base_queues ; 17921 i < _BCM_AP_NUM_L2_UC_LEAVES_PER_PIPE ; i++) { 17922 node = &res->p_queue_node[i]; 17923 if ((node->in_use == FALSE) || (node->hw_index == -1)) { 17924 continue; 17925 } 17926 if (node->remote_modid == modid) { 17927 *base_node = node ; 17928 break; 17929 } 17930 } 17931 return BCM_E_NONE; 17932 } 17933 17934 STATIC int 17935 _bcm_ap_voq_next_base_node_get(int unit, bcm_port_t port, 17936 int modid, 17937 _bcm_ap_cosq_node_t **base_node) 17938 { 17939 int i, pipe; 17940 _bcm_ap_pipe_resources_t *res; 17941 _bcm_ap_mmu_info_t *mmu_info; 17942 _bcm_ap_cosq_node_t *node; 17943 int found = FALSE; 17944 17945 mmu_info = _bcm_ap_mmu_info[unit]; 17946 pipe = _BCM_AP_PORT_TO_PIPE(unit, port); 17947 for (pipe = _AP_XPIPE ; pipe < _AP_NUM_PIPES ; pipe++) { 17948 res = _BCM_AP_PRESOURCES(mmu_info, pipe); 17949 for ( i = res->num_base_queues ; 17950 i < _BCM_AP_NUM_L2_UC_LEAVES_PER_PIPE ; i++) { 17951 node = &res->p_queue_node[i]; 17952 if ((node->in_use == FALSE) || (node->hw_index == -1)) { 17953 continue; 17954 } 17955 if (node->remote_modid == modid) { 17956 if ( found == TRUE) { 17957 *base_node = node; 17958 break; 17959 } 17960 found = TRUE; 17961 } 17962 } 17963 } 17964 return BCM_E_NONE; 17965 } 17966 17967 STATIC int 17968 _bcm_ap_port_voq_base_set(int unit, bcm_port_t local_port, int base) 17969 { 17970 uint64 rval; 17971 17972 BCM_IF_ERROR_RETURN(READ_ING_COS_MODE_64r(unit, local_port, &rval)); 17973 soc_reg64_field32_set(unit, ING_COS_MODE_64r, &rval, BASE_QUEUE_NUM_1f, base); 17974 BCM_IF_ERROR_RETURN(WRITE_ING_COS_MODE_64r(unit, local_port, rval)); 17975 return BCM_E_NONE; 17976 } 17977 17978 STATIC int 17979 _bcm_ap_port_voq_base_get(int unit, bcm_port_t local_port, int *base) 17980 { 17981 uint64 rval; 17982 17983 BCM_IF_ERROR_RETURN(READ_ING_COS_MODE_64r(unit, local_port, &rval)); 17984 if (soc_reg64_field32_get(unit, ING_COS_MODE_64r, rval, QUEUE_MODEf) == 1) { 17985 *base = soc_reg64_field32_get(unit, ING_COS_MODE_64r, rval, 17986 BASE_QUEUE_NUM_1f); 17987 return BCM_E_NONE; 17988 } 17989 17990 BCM_IF_ERROR_RETURN( 17991 _bcm_ap_voq_min_hw_index(unit, local_port, -1, -1, base)); 17992 17993 return BCM_E_NONE; 17994 } 17995 17996 STATIC int 17997 _bcm_ap_resolve_dmvoq_hw_index(int unit, _bcm_ap_cosq_node_t *node, 17998 int cosq, bcm_module_t modid, bcm_port_t local_port) 17999 { 18000 int try, preffered_offset = -1, alloc_size; 18001 int from_offset, max_offset, port, rv, q_base, port_voq_base, pipe; 18002 _bcm_ap_pipe_resources_t *res; 18003 _bcm_ap_mmu_info_t *mmu_info; 18004 18005 mmu_info = _bcm_ap_mmu_info[unit]; 18006 pipe = _BCM_AP_PORT_TO_PIPE(unit, local_port); 18007 res = _BCM_AP_PRESOURCES(mmu_info, pipe); 18008 18009 from_offset = res->num_base_queues; 18010 max_offset = _BCM_AP_NUM_L2_UC_LEAVES_PER_PIPE; 18011 alloc_size = _AP_NUM_COS(unit); 18012 18013 for (try = 0; try < 2; try++) { 18014 PBMP_HG_ITER(unit, port) { 18015 if ((try == 1) && (port == local_port)) { 18016 continue; 18017 } 18018 18019 if ((try == 0) && (port != local_port)) { 18020 continue; 18021 } 18022 18023 rv = _bcm_ap_voq_min_hw_index(unit, port, modid, -1, &q_base); 18024 if (!rv) { 18025 if (port == local_port) { 18026 /* Found VOQ for the same port/dest modid */ 18027 node->hw_index = q_base + cosq; 18028 return BCM_E_NONE; 18029 } else if (modid == -1) { 18030 rv = _bcm_ap_port_voq_base_get(unit, port, &port_voq_base); 18031 if (rv) { 18032 continue; 18033 } 18034 preffered_offset = q_base - port_voq_base; 18035 rv = _bcm_ap_port_voq_base_get(unit, local_port, 18036 &port_voq_base); 18037 if (rv) { 18038 /* No VOQ on the port yet */ 18039 alloc_size += preffered_offset; 18040 } else { 18041 /* port has already VOQs */ 18042 from_offset = port_voq_base + preffered_offset; 18043 } 18044 break; 18045 } 18046 } 18047 } 18048 if (preffered_offset != -1) { 18049 break; 18050 } 18051 } 18052 if (modid == -1) { 18053 /* Alloc hw index. */ 18054 rv = _bcm_ap_node_index_get(res->l2_queue_list.bits, 18055 from_offset, max_offset, 18056 alloc_size, _AP_NUM_COS(unit), &q_base); 18057 if (rv) { 18058 return BCM_E_RESOURCE; 18059 } 18060 18061 if (_bcm_ap_port_voq_base_get(unit, local_port, &port_voq_base)) { 18062 _bcm_ap_port_voq_base_set(unit, local_port, q_base); 18063 } 18064 q_base = q_base + alloc_size - _AP_NUM_COS(unit); 18065 node->hw_index = q_base + cosq; 18066 node->hw_cosq = node->hw_index % _AP_NUM_COS(unit); 18067 node->remote_modid = modid; 18068 _bcm_ap_node_index_set(&res->l2_queue_list, q_base, _AP_NUM_COS(unit)); 18069 } else { 18070 BCM_IF_ERROR_RETURN( 18071 _bcm_ap_voq_min_hw_index(unit, local_port, -1, -1, &port_voq_base)); 18072 18073 if (port_voq_base == node->hw_index) { 18074 _bcm_ap_port_voq_base_set(unit, local_port, node->hw_index); 18075 } 18076 node->remote_modid = modid; 18077 rv = BCM_E_NONE; 18078 } 18079 return rv; 18080 } 18081 18082 typedef struct _bcm_ap_voq_info_s { 18083 int valid; 18084 _bcm_ap_cosq_node_t *node; 18085 bcm_module_t remote_modid; 18086 bcm_port_t remote_port; 18087 bcm_port_t local_port; 18088 int hw_cosq; 18089 int hw_index; 18090 } _bcm_ap_voq_info_t; 18091 18092 STATIC int 18093 _bcm_ap_cosq_sort_voq_list(void *a, void *b) 18094 { 18095 _bcm_ap_voq_info_t *va, *vb; 18096 int sa, sb; 18097 18098 va = (_bcm_ap_voq_info_t*)a; 18099 vb = (_bcm_ap_voq_info_t*)b; 18100 18101 sa = (va->remote_modid << 19) | (va->remote_port << 11) | 18102 (va->local_port << 3) | (va->hw_cosq); 18103 18104 sb = (vb->remote_modid << 19) | (vb->remote_port << 11) | 18105 (vb->local_port << 3) | (vb->hw_cosq); 18106 18107 return sa - sb; 18108 } 18109 18110 STATIC int 18111 _bcm_ap_get_queue_skip_count_on_cos(uint32 cbmp, int cur_cos, int next_cos) 18112 { 18113 int i,skip = 0; 18114 18115 if ((next_cos >= 4) && (cur_cos/4 != next_cos/4)) { 18116 cur_cos = -1; 18117 next_cos -= 4; 18118 } 18119 18120 for (i = cur_cos + 1; i < next_cos; i++) { 18121 if (cbmp & (1 << i)) { 18122 skip += 1; 18123 } 18124 } 18125 return skip; 18126 } 18127 18128 STATIC int 18129 _bcm_ap_msg_buf_get(int unit, bcm_port_t srcid) 18130 { 18131 int ii, hole = -1; 18132 uint32 rval, csrc; 18133 18134 for (ii = 0; ii < 16; ii++) { 18135 BCM_IF_ERROR_RETURN(READ_BUF_CFGr(unit, ii, &rval)); 18136 if (srcid == (csrc = soc_reg_field_get(unit, BUF_CFGr, rval, SRC_IDf))) { 18137 return ii; 18138 } 18139 if ((hole == -1) && (csrc == 0)) { 18140 hole = ii; 18141 } 18142 } 18143 18144 if (hole == -1) { 18145 return BCM_E_RESOURCE; 18146 } 18147 18148 rval = 0; 18149 soc_reg_field_set(unit, BUF_CFGr, &rval, SRC_IDf, srcid); 18150 BCM_IF_ERROR_RETURN(WRITE_BUF_CFGr(unit, hole, rval)); 18151 18152 return hole; 18153 } 18154 18155 STATIC int 18156 _bcm_ap_gport_dpvoq_config_set(int unit, bcm_gport_t gport, 18157 bcm_cos_queue_t cosq, 18158 bcm_module_t remote_modid, 18159 bcm_port_t remote_port) 18160 { 18161 uint32 profile = 0xFFFFFFFF; 18162 _bcm_ap_cosq_node_t *node; 18163 bcm_port_t local_port; 18164 uint32 cng_offset; 18165 uint8 cbmp = 0, nib_cbmp = 0; 18166 _bcm_ap_mmu_info_t *mmu_info; 18167 _bcm_ap_voq_info_t *plist = NULL, *vlist = NULL; 18168 int pcount, ii, vcount = 0; 18169 voq_port_map_entry_t *voq_port_map_entries = NULL; 18170 int rv = BCM_E_NONE, mod_base = 0, num_cos = 0, dm = -1; 18171 voq_mod_map_entry_t voq_mod_map; 18172 void *entries[1]; 18173 int cng_bytes_per_e2ecc_msg = 64; 18174 int p2ioff[128], ioff, port, skip, *dm2off, count, pipe; 18175 _bcm_ap_pipe_resources_t *res; 18176 voq_cos_map_entry_t voq_cos_map; 18177 int priority = 0; 18178 int rp, port_q_base = 0; 18179 int base_tbl_entry = 0, intf_index = -1; 18180 uint64 rval64; 18181 soc_info_t *si; 18182 int phy_port, mmu_port; 18183 18184 if ((cosq < 0) || (cosq > _AP_NUM_COS(unit))) { 18185 return BCM_E_PARAM; 18186 } 18187 18188 if ((mmu_info = _bcm_ap_mmu_info[unit]) == NULL) { 18189 return BCM_E_INIT; 18190 } 18191 18192 BCM_IF_ERROR_RETURN 18193 (_bcm_ap_cosq_node_get(unit, gport, 0, NULL, &local_port, NULL, &node)); 18194 18195 pipe = _BCM_AP_PORT_TO_PIPE(unit, local_port); 18196 res = _BCM_AP_PRESOURCES(mmu_info, pipe); 18197 18198 node->remote_modid = remote_modid; 18199 node->remote_port = remote_port; 18200 node->hw_cosq = cosq; 18201 18202 dm2off = sal_alloc(sizeof(int) * 256, "voq_vlist"); 18203 if (!dm2off) { 18204 return BCM_E_MEMORY; 18205 } 18206 sal_memset(dm2off, 0, sizeof(int)*256); 18207 18208 /* alloc temp vlist */ 18209 vlist = sal_alloc(sizeof(_bcm_ap_voq_info_t) * _BCM_AP_NUM_L2_UC_LEAVES, "voq_vlist"); 18210 if (!vlist) { 18211 sal_free(dm2off); 18212 return BCM_E_MEMORY; 18213 } 18214 sal_memset(vlist, 0, sizeof(_bcm_ap_voq_info_t)*_BCM_AP_NUM_L2_UC_LEAVES); 18215 18216 for (ii = 0; ii < _BCM_AP_NUM_L2_UC_LEAVES; ii++) { 18217 node = &res->p_queue_node[ii]; 18218 if ((node->remote_modid == -1) || (node->remote_port == -1)) { 18219 continue; 18220 } 18221 vlist[vcount].remote_modid = node->remote_modid; 18222 vlist[vcount].remote_port = node->remote_port; 18223 vlist[vcount].local_port = node->local_port; 18224 vlist[vcount].hw_cosq = node->hw_cosq; 18225 vlist[vcount].node = node; 18226 vcount += 1; 18227 } 18228 18229 /* Sort the nodes */ 18230 _shr_sort(vlist, vcount, sizeof(_bcm_ap_voq_info_t), 18231 _bcm_ap_cosq_sort_voq_list); 18232 18233 for (ii = 0; ii < 128; ii++) { 18234 p2ioff[ii] = -1; 18235 } 18236 18237 si = &SOC_INFO(unit); 18238 PBMP_HG_ITER(unit, port) { 18239 /* For DPVOQ, SRC_ID should be the mmu_port number */ 18240 phy_port = si->port_l2p_mapping[port]; 18241 mmu_port = si->port_p2m_mapping[phy_port]; 18242 ioff = _bcm_ap_msg_buf_get(unit, mmu_port); 18243 p2ioff[port] = ioff; 18244 } 18245 18246 for (ii = 0; ii < vcount; ii++) { 18247 cbmp |= 1 << vlist[ii].hw_cosq; 18248 } 18249 18250 nib_cbmp = (cbmp >> 4) | (cbmp & 0xf); 18251 18252 for (ii = 0; ii < 4; ii++) { 18253 if ((1 << ii) & nib_cbmp) { 18254 num_cos += 1; 18255 } 18256 } 18257 18258 for (count = 1, ii = 0; ii < vcount; ii++) { 18259 if (dm2off[vlist[ii].remote_modid]==0) { 18260 dm2off[vlist[ii].remote_modid] = count; 18261 } 18262 } 18263 18264 plist = sal_alloc(sizeof(_bcm_ap_voq_info_t) * _BCM_AP_NUM_L2_UC_LEAVES, "voq_vlist"); 18265 if (!plist) { 18266 sal_free(dm2off); 18267 sal_free(vlist); 18268 return BCM_E_MEMORY; 18269 } 18270 sal_memset(plist, 0, sizeof(_bcm_ap_voq_info_t) * _BCM_AP_NUM_L2_UC_LEAVES); 18271 18272 for (pcount = 0, ii = 0; ii < vcount; ii++) { 18273 if (pcount % 4) { 18274 if ((plist[pcount - 1].remote_modid != vlist[ii].remote_modid) || 18275 (plist[pcount - 1].remote_port != vlist[ii].remote_port)) { 18276 pcount = (pcount + 3) & ~3; 18277 } else if (plist[pcount - 1].local_port != vlist[ii].local_port) { 18278 skip = (p2ioff[vlist[ii].local_port] - 18279 p2ioff[plist[pcount - 1].local_port] - 1) * num_cos; 18280 skip += _bcm_ap_get_queue_skip_count_on_cos(nib_cbmp, 18281 plist[pcount - 1].hw_cosq, 18282 vlist[ii].hw_cosq); 18283 if (skip >= 4) { 18284 pcount = ((pcount + 3) & ~3) + (skip % 4); 18285 } else { 18286 pcount += skip; 18287 } 18288 } else if ((vlist[ii].hw_cosq - plist[pcount - 1].hw_cosq) > 1) { 18289 if (plist[pcount - 1].hw_cosq/4 != vlist[ii].hw_cosq/4) { 18290 pcount = (pcount + 3) & ~3; 18291 } 18292 pcount += _bcm_ap_get_queue_skip_count_on_cos(nib_cbmp, 18293 plist[pcount - 1].hw_cosq, 18294 vlist[ii].hw_cosq); 18295 } 18296 } else { 18297 pcount += _bcm_ap_get_queue_skip_count_on_cos(nib_cbmp, -1, 18298 vlist[ii].hw_cosq); 18299 } 18300 18301 plist[pcount].valid = 1; 18302 plist[pcount].local_port = vlist[ii].local_port; 18303 plist[pcount].remote_modid = vlist[ii].remote_modid; 18304 plist[pcount].remote_port = vlist[ii].remote_port; 18305 plist[pcount].hw_cosq = vlist[ii].hw_cosq; 18306 plist[pcount].node = vlist[ii].node; 18307 18308 #ifdef DEBUG_AP_COSQ 18309 LOG_CLI((BSL_META_U(unit, 18310 "DPVOQ DM=%d DP=%d LocalPort=%d COS=%d HWIndex=%d\n"), 18311 plist[pcount].remote_modid, 18312 plist[pcount].remote_port, 18313 plist[pcount].local_port, 18314 plist[pcount].hw_cosq, 18315 plist[pcount].node->hw_index)); 18316 #endif 18317 pcount += 1; 18318 } 18319 18320 /* program the voq port profiles. */ 18321 voq_port_map_entries = sal_alloc(sizeof(voq_port_map_entry_t)*128, 18322 "voq port map entries"); 18323 if (!voq_port_map_entries) { 18324 goto fail; 18325 } 18326 sal_memset(voq_port_map_entries, 0, sizeof(voq_port_map_entry_t)*128); 18327 18328 entries[0] = voq_port_map_entries; 18329 dm = -1; 18330 rp = -1; 18331 for (ii = 0; ii <= pcount; ii++) { 18332 if (plist[ii].valid == 1) { 18333 rv = READ_ING_COS_MODE_64r(unit, plist[ii].local_port, &rval64); 18334 if (rv) { 18335 goto fail; 18336 } 18337 port_q_base = soc_reg64_field32_get(unit, ING_COS_MODE_64r, rval64, 18338 BASE_QUEUE_NUM_1f); 18339 } 18340 18341 if ((ii == pcount) || 18342 ((dm != -1) && (plist[ii].valid) && 18343 (plist[ii].remote_modid != dm))) { 18344 18345 rv = READ_VOQ_MOD_MAPm(unit, MEM_BLOCK_ALL, dm, &voq_mod_map); 18346 if (rv) { 18347 goto fail; 18348 } 18349 if (soc_mem_field32_get(unit, VOQ_MOD_MAPm, 18350 &voq_mod_map, VOQ_VALIDf)) { 18351 profile = soc_mem_field32_get(unit, VOQ_MOD_MAPm, 18352 &voq_mod_map, VOQ_MOD_PORT_PROFILE_INDEXf); 18353 18354 rv = soc_profile_mem_delete(unit, 18355 _bcm_ap_voq_port_map_profile[unit], profile*128); 18356 if (rv) { 18357 goto fail; 18358 } 18359 } 18360 rv = soc_profile_mem_add(unit, 18361 _bcm_ap_voq_port_map_profile[unit], 18362 entries, 128, &profile); 18363 if (rv) { 18364 goto fail; 18365 } 18366 18367 soc_mem_field32_set(unit, VOQ_MOD_MAPm, &voq_mod_map, 18368 VOQ_MOD_PORT_PROFILE_INDEXf, profile/128); 18369 soc_mem_field32_set(unit, VOQ_MOD_MAPm, &voq_mod_map, 18370 VOQ_VALIDf, 1); 18371 soc_mem_field32_set(unit, VOQ_MOD_MAPm, &voq_mod_map, 18372 VOQ_MOD_OFFSETf, mod_base); 18373 soc_mem_field32_set(unit, VOQ_MOD_MAPm, &voq_mod_map, 18374 VOQ_MOD_USE_PORTf, 1); 18375 rv = soc_mem_write(unit, VOQ_MOD_MAPm, MEM_BLOCK_ALL, 18376 dm, &voq_mod_map); 18377 if (rv) { 18378 goto fail; 18379 } 18380 18381 sal_memset(voq_port_map_entries, 0, sizeof(voq_port_map_entry_t)*128); 18382 18383 if (ii != pcount) { 18384 if (plist[ii].node) { 18385 mod_base = (plist[ii].node->hw_index & ~3) - port_q_base; 18386 } 18387 } 18388 } 18389 18390 if (ii == pcount) { 18391 break; 18392 } 18393 18394 if (plist[ii].valid == 0) { 18395 continue; 18396 } 18397 18398 if (dm == -1) { 18399 if (plist[ii].node) { 18400 mod_base = (plist[ii].node->hw_index & ~3) - port_q_base; 18401 } 18402 } 18403 18404 dm = plist[ii].remote_modid; 18405 18406 if ((rp == -1) || 18407 (rp != plist[ii].remote_port)) { 18408 rp = plist[ii].remote_port; 18409 soc_mem_field32_set(unit, VOQ_PORT_MAPm, 18410 &voq_port_map_entries[plist[ii].remote_port], 18411 VOQ_PORT_OFFSETf, 18412 (plist[ii].node->hw_index - mod_base - port_q_base) & 0x3fff); 18413 } 18414 } 18415 18416 for (priority = 0; priority < 16; priority++) { 18417 rv = READ_VOQ_COS_MAPm(unit, MEM_BLOCK_ALL, priority, &voq_cos_map); 18418 if (rv) { 18419 goto fail; 18420 } 18421 18422 /* Setting the VOQ_PORT_BASE_SELECT, 18423 so that BASE_QUEUE_NUM_1 is used for queue 18424 calculation */ 18425 18426 soc_mem_field32_set(unit, VOQ_COS_MAPm, 18427 &voq_cos_map, VOQ_PORT_BASE_SELECTf, pcount ? 1 : 0); 18428 soc_mem_field32_set(unit, VOQ_COS_MAPm, 18429 &voq_cos_map, VOQ_COS_USE_MODf, pcount ? 1 : 0); 18430 soc_mem_field32_set(unit, VOQ_COS_MAPm, 18431 &voq_cos_map, VOQ_COS_USE_PORTf, pcount ? 1 : 0); 18432 18433 rv = soc_mem_write(unit, VOQ_COS_MAPm, MEM_BLOCK_ANY, priority, 18434 &voq_cos_map); 18435 if (rv) { 18436 goto fail; 18437 } 18438 } 18439 18440 dm = -1; 18441 for (ii = 0; ii < pcount; ii += 1) { 18442 if (plist[ii].valid == 0) { 18443 continue; 18444 } 18445 phy_port = si->port_l2p_mapping[plist[ii].local_port]; 18446 mmu_port = si->port_p2m_mapping[phy_port]; 18447 18448 cng_offset = (dm2off[plist[ii].remote_modid] - 1) * 18449 cng_bytes_per_e2ecc_msg; 18450 18451 /* 18452 * Base index table addr = {< interface number>,BUF_CFG<interface number>__PROFILE_ID} 18453 * If incoming message mmu port number matches say interface 4's SRC_ID, 18454 * then it will address base_index_table as {0, BUF_CFG4_PROFILE_ID}. 18455 * Since profile_id is 2 bits, we index base_index_table in multiple of 4. 18456 */ 18457 18458 intf_index = _bcm_ap_msg_buf_get(unit, mmu_port); 18459 if (intf_index < 0) { 18460 return BCM_E_INTERNAL; 18461 } 18462 18463 BCM_IF_ERROR_RETURN 18464 (soc_mem_read(unit, MMU_INTFI_BASE_INDEX_TBLm, 18465 MEM_BLOCK_ALL, intf_index * 4, &base_tbl_entry)); 18466 18467 soc_mem_field32_set(unit, MMU_INTFI_BASE_INDEX_TBLm, &base_tbl_entry, 18468 BASE_ADDRf, cng_offset); 18469 soc_mem_field32_set(unit, MMU_INTFI_BASE_INDEX_TBLm, &base_tbl_entry, 18470 ENf, 2); 18471 18472 BCM_IF_ERROR_RETURN(soc_mem_write(unit, MMU_INTFI_BASE_INDEX_TBLm, 18473 MEM_BLOCK_ALL, intf_index * 4, &base_tbl_entry)); 18474 18475 /* Each byte of message should correspond to 2 entries in FC_ST_TBL2. 18476 * Hence port * 2. 18477 */ 18478 _bcm_ap_map_fc_status_to_node(unit, 18479 plist[ii].local_port, 18480 _BCM_AP_COSQ_FC_E2ECC, 18481 cng_offset + (plist[ii].remote_port * 2), 18482 plist[ii].hw_cosq, 18483 plist[ii].node->hw_index, 18484 SOC_APACHE_NODE_LVL_L2); 18485 } 18486 18487 fail: 18488 if (vlist) { 18489 sal_free(vlist); 18490 } 18491 18492 if (plist) { 18493 sal_free(plist); 18494 } 18495 18496 if (dm2off) { 18497 sal_free(dm2off); 18498 } 18499 18500 if (voq_port_map_entries) { 18501 sal_free(voq_port_map_entries); 18502 } 18503 18504 if (rv) { 18505 node->remote_modid = -1; 18506 node->remote_port = -1; 18507 } 18508 return rv; 18509 } 18510 18511 STATIC int 18512 _bcm_ap_gport_dmvoq_config_set(int unit, bcm_gport_t gport, 18513 bcm_cos_queue_t cosq, 18514 bcm_module_t fabric_modid, 18515 bcm_module_t dest_modid, 18516 bcm_port_t fabric_port) 18517 { 18518 int port_voq_base, intf_index; 18519 _bcm_ap_cosq_node_t *node; 18520 _bcm_ap_cosq_node_t *base_node = NULL; 18521 bcm_port_t local_port; 18522 voq_mod_map_entry_t voq_mod_map_entry; 18523 mmu_intfi_offset_map_tbl_entry_t offset_map_tbl_entry; 18524 mmu_intfi_base_index_tbl_entry_t base_tbl_entry; 18525 uint32 cng_offset = 0; 18526 _bcm_ap_mmu_info_t *mmu_info; 18527 int fabric_port_count, count = 0; 18528 int map_offset = 0; 18529 int port = 0; 18530 18531 if ((mmu_info = _bcm_ap_mmu_info[unit]) == NULL) { 18532 return BCM_E_INIT; 18533 } 18534 18535 if (fabric_modid >= 64) { 18536 return BCM_E_PARAM; 18537 } 18538 18539 BCM_IF_ERROR_RETURN 18540 (_bcm_ap_cosq_node_get(unit, gport, 0, NULL, &local_port, NULL, &node)); 18541 18542 if (!node) { 18543 return BCM_E_NOT_FOUND; 18544 } 18545 18546 BCM_IF_ERROR_RETURN(_bcm_ap_resolve_dmvoq_hw_index(unit, node, cosq, 18547 dest_modid, local_port)); 18548 BCM_IF_ERROR_RETURN(_bcm_ap_voq_base_node_get( 18549 unit, local_port, dest_modid, &base_node)); 18550 if (base_node == NULL) { 18551 base_node = node ; 18552 } 18553 BCM_PBMP_COUNT(base_node->fabric_pbmp, fabric_port_count); 18554 if (fabric_port_count == 0) { 18555 map_offset = mmu_info->curr_merger_index; 18556 if (map_offset >= soc_mem_index_count(unit, MMU_INTFI_MERGE_ST_TBLm)) { 18557 return BCM_E_RESOURCE; 18558 } 18559 } else { 18560 BCM_PBMP_ITER(base_node->fabric_pbmp, port) { 18561 BCM_IF_ERROR_RETURN(soc_mem_read(unit, MMU_INTFI_OFFSET_MAP_TBLm, 18562 MEM_BLOCK_ALL, 18563 port * 2, &offset_map_tbl_entry)); 18564 map_offset = soc_mem_field32_get(unit, MMU_INTFI_OFFSET_MAP_TBLm, 18565 &offset_map_tbl_entry, 18566 MAP_OFFSETf); 18567 break; 18568 } 18569 } 18570 if (!BCM_PBMP_MEMBER(base_node->fabric_pbmp, fabric_port)) { 18571 if (map_offset == mmu_info->curr_merger_index ) { 18572 mmu_info->curr_merger_index += 2; 18573 } 18574 18575 BCM_PBMP_PORT_ADD (base_node->fabric_pbmp, fabric_port); 18576 BCM_PBMP_COUNT(base_node->fabric_pbmp, fabric_port_count); 18577 BCM_PBMP_ITER(base_node->fabric_pbmp, port) { 18578 count++; 18579 BCM_IF_ERROR_RETURN(soc_mem_read(unit, MMU_INTFI_OFFSET_MAP_TBLm, 18580 MEM_BLOCK_ALL, 18581 port * 2, &offset_map_tbl_entry)); 18582 soc_mem_field32_set(unit, MMU_INTFI_OFFSET_MAP_TBLm, 18583 &offset_map_tbl_entry, 18584 MAP_OFFSETf, map_offset); 18585 soc_mem_field32_set(unit, MMU_INTFI_OFFSET_MAP_TBLm, 18586 &offset_map_tbl_entry, 18587 LASTf, count < fabric_port_count ? 0 : 1 ); 18588 BCM_IF_ERROR_RETURN(soc_mem_write(unit, MMU_INTFI_OFFSET_MAP_TBLm, 18589 MEM_BLOCK_ALL, 18590 port * 2, &offset_map_tbl_entry)); 18591 18592 BCM_IF_ERROR_RETURN(soc_mem_read(unit, MMU_INTFI_OFFSET_MAP_TBLm, 18593 MEM_BLOCK_ALL, 18594 (port * 2) + 1, &offset_map_tbl_entry)); 18595 soc_mem_field32_set(unit, MMU_INTFI_OFFSET_MAP_TBLm, 18596 &offset_map_tbl_entry, 18597 MAP_OFFSETf, map_offset + 1); 18598 soc_mem_field32_set(unit, MMU_INTFI_OFFSET_MAP_TBLm, 18599 &offset_map_tbl_entry, 18600 LASTf, count < fabric_port_count ? 0 : 1 ); 18601 BCM_IF_ERROR_RETURN(soc_mem_write(unit, MMU_INTFI_OFFSET_MAP_TBLm, 18602 MEM_BLOCK_ALL, 18603 (port * 2) + 1, &offset_map_tbl_entry)); 18604 } 18605 } 18606 18607 BCM_IF_ERROR_RETURN(soc_mem_read(unit, VOQ_MOD_MAPm, MEM_BLOCK_ALL, 18608 dest_modid, &voq_mod_map_entry)); 18609 BCM_IF_ERROR_RETURN(_bcm_ap_port_voq_base_get(unit, local_port, 18610 &port_voq_base)); 18611 soc_mem_field32_set(unit, VOQ_MOD_MAPm, &voq_mod_map_entry, 18612 VOQ_VALIDf, 1); 18613 soc_mem_field32_set(unit, VOQ_MOD_MAPm, &voq_mod_map_entry, 18614 VOQ_MOD_OFFSETf, ((node->hw_index & ~7) - port_voq_base)); 18615 18616 BCM_IF_ERROR_RETURN( 18617 soc_mem_write(unit, VOQ_MOD_MAPm, MEM_BLOCK_ALL, dest_modid, 18618 &voq_mod_map_entry)); 18619 18620 intf_index = _bcm_ap_msg_buf_get(unit, fabric_modid); 18621 if (intf_index < 0) { 18622 return BCM_E_INTERNAL; 18623 } 18624 18625 cng_offset = intf_index * 64 * 2; 18626 18627 BCM_IF_ERROR_RETURN 18628 (soc_mem_read(unit, MMU_INTFI_BASE_INDEX_TBLm, 18629 MEM_BLOCK_ALL, fabric_modid, &base_tbl_entry)); 18630 18631 soc_mem_field32_set(unit, MMU_INTFI_BASE_INDEX_TBLm, &base_tbl_entry, 18632 BASE_ADDRf, cng_offset); 18633 soc_mem_field32_set(unit, MMU_INTFI_BASE_INDEX_TBLm, &base_tbl_entry, 18634 ENf, 2); 18635 18636 BCM_IF_ERROR_RETURN(soc_mem_write(unit, MMU_INTFI_BASE_INDEX_TBLm, 18637 MEM_BLOCK_ALL, fabric_modid, &base_tbl_entry)); 18638 18639 /* set the mapping from congestion bits in flow control table 18640 * to corresponding cosq. */ 18641 BCM_IF_ERROR_RETURN(_bcm_ap_map_fc_status_to_node(unit, local_port, 18642 _BCM_AP_COSQ_FC_VOQFC, cng_offset + map_offset, 18643 cosq, node->hw_index, SOC_APACHE_NODE_LVL_L2)); 18644 18645 #ifdef DEBUG_AP_COSQ 18646 LOG_CLI((BSL_META_U(unit, 18647 "Gport=0x%08x hw_index=%d cosq=%d\n"), 18648 gport, node->hw_index, cosq)); 18649 #endif 18650 18651 return BCM_E_NONE; 18652 } 18653 18654 int bcm_ap_cosq_gport_congestion_config_set(int unit, bcm_gport_t gport, 18655 bcm_cos_queue_t cosq, 18656 bcm_cosq_congestion_info_t *config) 18657 { 18658 _bcm_ap_mmu_info_t *mmu_info; 18659 18660 if (!config) { 18661 return BCM_E_PARAM; 18662 } 18663 18664 if ((mmu_info = _bcm_ap_mmu_info[unit]) == NULL) { 18665 return BCM_E_INIT; 18666 } 18667 18668 /* determine if this gport is DPVOQ or DMVOQ */ 18669 if ((config->fabric_port != -1) && (config->dest_modid != -1)) { 18670 return _bcm_ap_gport_dmvoq_config_set(unit, gport, cosq, 18671 config->fabric_modid, 18672 config->dest_modid, 18673 config->fabric_port); 18674 } else if ((config->dest_modid != -1) && (config->dest_port != -1)) { 18675 return _bcm_ap_gport_dpvoq_config_set(unit, gport, cosq, 18676 config->dest_modid, 18677 config->dest_port); 18678 } 18679 18680 return BCM_E_PARAM; 18681 } 18682 18683 int bcm_ap_cosq_gport_congestion_config_get(int unit, bcm_gport_t port, 18684 bcm_cos_queue_t cosq, 18685 bcm_cosq_congestion_info_t *config) 18686 { 18687 _bcm_ap_mmu_info_t *mmu_info; 18688 bcm_port_t local_port; 18689 _bcm_ap_cosq_node_t *node; 18690 18691 if (!config) { 18692 return BCM_E_PARAM; 18693 } 18694 18695 if ((mmu_info = _bcm_ap_mmu_info[unit]) == NULL) { 18696 return BCM_E_INIT; 18697 } 18698 18699 BCM_IF_ERROR_RETURN 18700 (_bcm_ap_cosq_node_get(unit, port, 0, NULL, &local_port, NULL, &node)); 18701 18702 18703 if (!node) { 18704 return BCM_E_NOT_FOUND; 18705 } 18706 18707 config->dest_modid = node->remote_modid; 18708 config->dest_port = node->remote_port; 18709 18710 return BCM_E_NONE; 18711 } 18712 18713 18714 18715 int bcm_ap_cosq_bst_profile_set(int unit, 18716 bcm_gport_t port, 18717 bcm_cos_queue_t cosq, 18718 bcm_bst_stat_id_t bid, 18719 bcm_cosq_bst_profile_t *profile) 18720 { 18721 BCM_IF_ERROR_RETURN(_bcm_bst_cmn_profile_set 18722 (unit, port, cosq, BCM_BST_DUP_XPE, bid, profile)); 18723 return BCM_E_NONE; 18724 } 18725 18726 int bcm_ap_cosq_bst_profile_get(int unit, 18727 bcm_gport_t port, 18728 bcm_cos_queue_t cosq, 18729 bcm_bst_stat_id_t bid, 18730 bcm_cosq_bst_profile_t *profile) 18731 { 18732 BCM_IF_ERROR_RETURN(_bcm_bst_cmn_profile_get 18733 (unit, port, cosq, BCM_BST_DUP_XPE, bid, profile)); 18734 return BCM_E_NONE; 18735 } 18736 18737 int bcm_ap_cosq_bst_stat_get(int unit, 18738 bcm_gport_t port, 18739 bcm_cos_queue_t cosq, 18740 bcm_bst_stat_id_t bid, 18741 uint32 options, 18742 uint64 *pvalue) 18743 { 18744 return _bcm_bst_cmn_stat_get(unit, port, cosq, -1, bid, options, pvalue); 18745 } 18746 18747 int bcm_ap_cosq_bst_stat_multi_get(int unit, 18748 bcm_gport_t port, 18749 bcm_cos_queue_t cosq, 18750 uint32 options, 18751 int max_values, 18752 bcm_bst_stat_id_t *id_list, 18753 uint64 *pvalues) 18754 { 18755 return _bcm_bst_cmn_stat_multi_get(unit, port, cosq, options, max_values, 18756 id_list, pvalues); 18757 } 18758 18759 int bcm_ap_cosq_bst_stat_clear(int unit, bcm_gport_t port, 18760 bcm_cos_queue_t cosq, bcm_bst_stat_id_t bid) 18761 { 18762 return _bcm_bst_cmn_stat_clear(unit, port, cosq, bid); 18763 } 18764 18765 int bcm_ap_cosq_bst_stat_sync(int unit, bcm_bst_stat_id_t bid) 18766 { 18767 return _bcm_bst_cmn_stat_sync(unit, bid); 18768 } 18769 18770 18771 /* 18772 * Function: 18773 * _bcm_ap_cosq_endpoint_l2_create 18774 * Purpose: 18775 * Create a L2 endpoint. 18776 * Parameters: 18777 * unit - (IN) Unit number. 18778 * endpoint_id - (IN) Endpoint ID 18779 * vlan - (IN) VLAN 18780 * mac - (IN) MAC address 18781 * Returns: 18782 * BCM_E_xxx 18783 */ 18784 STATIC int 18785 _bcm_ap_cosq_endpoint_l2_create( 18786 int unit, 18787 int endpoint_id, 18788 bcm_vlan_t vlan, 18789 bcm_mac_t mac) 18790 { 18791 int rv; 18792 bcm_l2_addr_t l2addr; 18793 l2_endpoint_id_entry_t l2_endpoint_entry; 18794 int vfi; 18795 18796 /* Make sure (vlan, mac) entry is already in L2 table */ 18797 rv = bcm_esw_l2_addr_get(unit, mac, vlan, &l2addr); 18798 if (rv == BCM_E_NOT_FOUND) { 18799 /* The (vlan, mac) entry needs to be added to L2 table 18800 * before configuring it for endpoint queuing. 18801 */ 18802 return BCM_E_CONFIG; 18803 } else if (BCM_FAILURE(rv)) { 18804 return rv; 18805 } 18806 18807 /* Add (vlan, mac) entry to L2_ENDPOINT_ID table */ 18808 sal_memcpy(&l2_endpoint_entry, soc_mem_entry_null(unit, L2_ENDPOINT_IDm), 18809 sizeof(l2_endpoint_id_entry_t)); 18810 soc_L2_ENDPOINT_IDm_field32_set(unit, &l2_endpoint_entry, VALIDf, 1); 18811 if (_BCM_MPLS_VPN_IS_VPLS(vlan)) { 18812 _BCM_MPLS_VPN_GET(vfi, _BCM_MPLS_VPN_TYPE_VPLS, vlan); 18813 soc_L2_ENDPOINT_IDm_field32_set(unit, &l2_endpoint_entry, L2__VFIf, 18814 vfi); 18815 soc_L2_ENDPOINT_IDm_field32_set(unit, &l2_endpoint_entry, KEY_TYPEf, 18816 TD2_L2_HASH_KEY_TYPE_VFI); 18817 } else if (_BCM_IS_MIM_VPN(vlan)) { 18818 _BCM_MIM_VPN_GET(vfi, _BCM_MIM_VPN_TYPE_MIM, vlan); 18819 soc_L2_ENDPOINT_IDm_field32_set(unit, &l2_endpoint_entry, L2__VFIf, 18820 vfi); 18821 soc_L2_ENDPOINT_IDm_field32_set(unit, &l2_endpoint_entry, KEY_TYPEf, 18822 TD2_L2_HASH_KEY_TYPE_VFI); 18823 } else { 18824 VLAN_CHK_ID(unit, vlan); 18825 soc_L2_ENDPOINT_IDm_field32_set(unit, &l2_endpoint_entry, L2__VLAN_IDf, 18826 vlan); 18827 soc_L2_ENDPOINT_IDm_field32_set(unit, &l2_endpoint_entry, KEY_TYPEf, 18828 TD2_L2_HASH_KEY_TYPE_BRIDGE); 18829 } 18830 soc_L2_ENDPOINT_IDm_mac_addr_set(unit, &l2_endpoint_entry, L2__MAC_ADDRf, 18831 mac); 18832 soc_L2_ENDPOINT_IDm_field32_set(unit, &l2_endpoint_entry, EH_TAG_TYPEf, 2); 18833 soc_L2_ENDPOINT_IDm_field32_set(unit, &l2_endpoint_entry, EH_QUEUE_TAGf, 18834 endpoint_id); 18835 SOC_IF_ERROR_RETURN(soc_mem_insert(unit, L2_ENDPOINT_IDm, MEM_BLOCK_ANY, 18836 &l2_endpoint_entry)); 18837 18838 return BCM_E_NONE; 18839 } 18840 18841 /* 18842 * Function: 18843 * _bcm_ap_cosq_endpoint_l2_destroy 18844 * Purpose: 18845 * Destroy a L2 endpoint. 18846 * Parameters: 18847 * unit - (IN) Unit number. 18848 * vlan - (IN) VLAN 18849 * mac - (IN) MAC address 18850 * Returns: 18851 * BCM_E_xxx 18852 */ 18853 STATIC int 18854 _bcm_ap_cosq_endpoint_l2_destroy( 18855 int unit, 18856 bcm_vlan_t vlan, 18857 bcm_mac_t mac) 18858 { 18859 l2_endpoint_id_entry_t l2_endpoint_entry; 18860 int vfi; 18861 18862 /* Delete (vlan, mac) entry from L2_ENDPOINT_ID table */ 18863 sal_memcpy(&l2_endpoint_entry, soc_mem_entry_null(unit, L2_ENDPOINT_IDm), 18864 sizeof(l2_endpoint_id_entry_t)); 18865 if (_BCM_MPLS_VPN_IS_VPLS(vlan)) { 18866 _BCM_MPLS_VPN_GET(vfi, _BCM_MPLS_VPN_TYPE_VPLS, vlan); 18867 soc_L2_ENDPOINT_IDm_field32_set(unit, &l2_endpoint_entry, L2__VFIf, 18868 vfi); 18869 soc_L2_ENDPOINT_IDm_field32_set(unit, &l2_endpoint_entry, KEY_TYPEf, 18870 TD2_L2_HASH_KEY_TYPE_VFI); 18871 } else if (_BCM_IS_MIM_VPN(vlan)) { 18872 _BCM_MIM_VPN_GET(vfi, _BCM_MIM_VPN_TYPE_MIM, vlan); 18873 soc_L2_ENDPOINT_IDm_field32_set(unit, &l2_endpoint_entry, L2__VFIf, 18874 vfi); 18875 soc_L2_ENDPOINT_IDm_field32_set(unit, &l2_endpoint_entry, KEY_TYPEf, 18876 TD2_L2_HASH_KEY_TYPE_VFI); 18877 } else { 18878 VLAN_CHK_ID(unit, vlan); 18879 soc_L2_ENDPOINT_IDm_field32_set(unit, &l2_endpoint_entry, L2__VLAN_IDf, 18880 vlan); 18881 soc_L2_ENDPOINT_IDm_field32_set(unit, &l2_endpoint_entry, KEY_TYPEf, 18882 TD2_L2_HASH_KEY_TYPE_BRIDGE); 18883 } 18884 soc_L2_ENDPOINT_IDm_mac_addr_set(unit, &l2_endpoint_entry, L2__MAC_ADDRf, 18885 mac); 18886 SOC_IF_ERROR_RETURN(soc_mem_delete(unit, L2_ENDPOINT_IDm, MEM_BLOCK_ANY, 18887 &l2_endpoint_entry)); 18888 18889 return BCM_E_NONE; 18890 } 18891 18892 #ifdef INCLUDE_L3 18893 /* 18894 * Function: 18895 * _bcm_ap_cosq_endpoint_ip4_create 18896 * Purpose: 18897 * Create an IPv4 endpoint. 18898 * Parameters: 18899 * unit - (IN) Unit number. 18900 * endpoint_id - (IN) Endpoint ID 18901 * vrf - (IN) Virtual router instance 18902 * ip_addr - (IN) IPv4 address 18903 * Returns: 18904 * BCM_E_xxx 18905 */ 18906 STATIC int 18907 _bcm_ap_cosq_endpoint_ip4_create( 18908 int unit, 18909 int endpoint_id, 18910 bcm_vrf_t vrf, 18911 bcm_ip_t ip_addr) 18912 { 18913 int rv; 18914 _bcm_l3_cfg_t l3cfg; 18915 18916 if ((vrf > SOC_VRF_MAX(unit)) || 18917 (vrf < BCM_L3_VRF_DEFAULT)) { 18918 return BCM_E_PARAM; 18919 } 18920 18921 L3_LOCK(unit); 18922 18923 /* Make sure (vrf, ip_addr) entry is already in L3 host table */ 18924 sal_memset(&l3cfg, 0, sizeof(_bcm_l3_cfg_t)); 18925 l3cfg.l3c_vrf = vrf; 18926 l3cfg.l3c_ip_addr = ip_addr; 18927 rv = mbcm_driver[unit]->mbcm_l3_ip4_get(unit, &l3cfg); 18928 if (rv == BCM_E_NOT_FOUND) { 18929 /* The (vrf, ip_addr) entry needs to be added to L3 table 18930 * before configuring it for endpoint queuing. 18931 */ 18932 L3_UNLOCK(unit); 18933 return BCM_E_CONFIG; 18934 } else if (BCM_FAILURE(rv)) { 18935 L3_UNLOCK(unit); 18936 return rv; 18937 } 18938 18939 if (l3cfg.l3c_eh_q_tag_type != 0) { 18940 /* A queue tag has already been configured for this L3 entry. */ 18941 L3_UNLOCK(unit); 18942 return BCM_E_EXISTS; 18943 } 18944 18945 /* Replace (vrf, ip_addr) entry's endpoint_id */ 18946 l3cfg.l3c_flags |= BCM_L3_REPLACE; 18947 l3cfg.l3c_eh_q_tag_type = 2; 18948 l3cfg.l3c_eh_q_tag = endpoint_id; 18949 rv = mbcm_driver[unit]->mbcm_l3_ip4_replace(unit, &l3cfg); 18950 if (BCM_FAILURE(rv)) { 18951 L3_UNLOCK(unit); 18952 return rv; 18953 } 18954 18955 L3_UNLOCK(unit); 18956 18957 return rv; 18958 } 18959 18960 /* 18961 * Function: 18962 * _bcm_ap_cosq_endpoint_ip4_destroy 18963 * Purpose: 18964 * Destroy an IPv4 endpoint. 18965 * Parameters: 18966 * unit - (IN) Unit number. 18967 * vrf - (IN) Virtual router instance 18968 * ip_addr - (IN) IPv4 address 18969 * Returns: 18970 * BCM_E_xxx 18971 */ 18972 STATIC int 18973 _bcm_ap_cosq_endpoint_ip4_destroy( 18974 int unit, 18975 bcm_vrf_t vrf, 18976 bcm_ip_t ip_addr) 18977 { 18978 int rv; 18979 _bcm_l3_cfg_t l3cfg; 18980 18981 if ((vrf > SOC_VRF_MAX(unit)) || 18982 (vrf < BCM_L3_VRF_DEFAULT)) { 18983 return BCM_E_PARAM; 18984 } 18985 18986 L3_LOCK(unit); 18987 18988 /* Get (vrf, ip_addr) entry */ 18989 sal_memset(&l3cfg, 0, sizeof(_bcm_l3_cfg_t)); 18990 l3cfg.l3c_vrf = vrf; 18991 l3cfg.l3c_ip_addr = ip_addr; 18992 rv = mbcm_driver[unit]->mbcm_l3_ip4_get(unit, &l3cfg); 18993 if (BCM_FAILURE(rv)) { 18994 L3_UNLOCK(unit); 18995 return rv; 18996 } 18997 18998 /* Delete (vrf, ip_addr) entry's endpoint_id */ 18999 l3cfg.l3c_flags |= BCM_L3_REPLACE; 19000 l3cfg.l3c_eh_q_tag_type = 0; 19001 l3cfg.l3c_eh_q_tag = 0; 19002 rv = mbcm_driver[unit]->mbcm_l3_ip4_replace(unit, &l3cfg); 19003 if (BCM_FAILURE(rv)) { 19004 L3_UNLOCK(unit); 19005 return rv; 19006 } 19007 19008 L3_UNLOCK(unit); 19009 19010 return rv; 19011 } 19012 19013 /* 19014 * Function: 19015 * _bcm_ap_cosq_endpoint_ip6_create 19016 * Purpose: 19017 * Create an IPv6 endpoint. 19018 * Parameters: 19019 * unit - (IN) Unit number. 19020 * endpoint_id - (IN) Endpoint ID 19021 * vrf - (IN) Virtual router instance 19022 * ip6_addr - (IN) IPv6 address 19023 * Returns: 19024 * BCM_E_xxx 19025 */ 19026 STATIC int 19027 _bcm_ap_cosq_endpoint_ip6_create( 19028 int unit, 19029 int endpoint_id, 19030 bcm_vrf_t vrf, 19031 bcm_ip6_t ip6_addr) 19032 { 19033 int rv; 19034 _bcm_l3_cfg_t l3cfg; 19035 19036 if ((vrf > SOC_VRF_MAX(unit)) || 19037 (vrf < BCM_L3_VRF_DEFAULT)) { 19038 return BCM_E_PARAM; 19039 } 19040 19041 L3_LOCK(unit); 19042 19043 /* Make sure (vrf, ip6_addr) entry is already in L3 host table */ 19044 sal_memset(&l3cfg, 0, sizeof(_bcm_l3_cfg_t)); 19045 l3cfg.l3c_flags = BCM_L3_IP6; 19046 l3cfg.l3c_vrf = vrf; 19047 sal_memcpy(l3cfg.l3c_ip6, ip6_addr, BCM_IP6_ADDRLEN); 19048 rv = mbcm_driver[unit]->mbcm_l3_ip6_get(unit, &l3cfg); 19049 if (rv == BCM_E_NOT_FOUND) { 19050 /* The (vrf, ip6_addr) entry needs to be added to L3 table 19051 * before configuring it for endpoint queuing. 19052 */ 19053 L3_UNLOCK(unit); 19054 return BCM_E_CONFIG; 19055 } else if (BCM_FAILURE(rv)) { 19056 L3_UNLOCK(unit); 19057 return rv; 19058 } 19059 19060 if (l3cfg.l3c_eh_q_tag_type != 0) { 19061 /* A queue tag has already been configured for this L3 entry. */ 19062 L3_UNLOCK(unit); 19063 return BCM_E_EXISTS; 19064 } 19065 19066 /* Replace (vrf, ip_addr) entry's endpoint_id */ 19067 l3cfg.l3c_flags |= BCM_L3_REPLACE; 19068 l3cfg.l3c_eh_q_tag_type = 2; 19069 l3cfg.l3c_eh_q_tag = endpoint_id; 19070 rv = mbcm_driver[unit]->mbcm_l3_ip6_replace(unit, &l3cfg); 19071 if (BCM_FAILURE(rv)) { 19072 L3_UNLOCK(unit); 19073 return rv; 19074 } 19075 19076 L3_UNLOCK(unit); 19077 19078 return rv; 19079 } 19080 19081 /* 19082 * Function: 19083 * _bcm_ap_cosq_endpoint_ip6_destroy 19084 * Purpose: 19085 * Destroy an IPv6 endpoint. 19086 * Parameters: 19087 * unit - (IN) Unit number. 19088 * vrf - (IN) Virtual router instance 19089 * ip6_addr - (IN) IPv6 address 19090 * Returns: 19091 * BCM_E_xxx 19092 */ 19093 STATIC int 19094 _bcm_ap_cosq_endpoint_ip6_destroy( 19095 int unit, 19096 bcm_vrf_t vrf, 19097 bcm_ip6_t ip6_addr) 19098 { 19099 int rv; 19100 _bcm_l3_cfg_t l3cfg; 19101 19102 if ((vrf > SOC_VRF_MAX(unit)) || 19103 (vrf < BCM_L3_VRF_DEFAULT)) { 19104 return BCM_E_PARAM; 19105 } 19106 19107 L3_LOCK(unit); 19108 19109 /* Get (vrf, ip6_addr) entry */ 19110 sal_memset(&l3cfg, 0, sizeof(_bcm_l3_cfg_t)); 19111 l3cfg.l3c_flags = BCM_L3_IP6; 19112 l3cfg.l3c_vrf = vrf; 19113 sal_memcpy(l3cfg.l3c_ip6, ip6_addr, BCM_IP6_ADDRLEN); 19114 rv = mbcm_driver[unit]->mbcm_l3_ip6_get(unit, &l3cfg); 19115 if (BCM_FAILURE(rv)) { 19116 L3_UNLOCK(unit); 19117 return rv; 19118 } 19119 19120 /* Delete (vrf, ip_addr) entry's endpoint_id */ 19121 l3cfg.l3c_flags |= BCM_L3_REPLACE; 19122 l3cfg.l3c_eh_q_tag_type = 0; 19123 l3cfg.l3c_eh_q_tag = 0; 19124 rv = mbcm_driver[unit]->mbcm_l3_ip6_replace(unit, &l3cfg); 19125 if (BCM_FAILURE(rv)) { 19126 L3_UNLOCK(unit); 19127 return rv; 19128 } 19129 19130 L3_UNLOCK(unit); 19131 19132 return rv; 19133 } 19134 19135 #endif /* INCLUDE_L3 */ 19136 19137 /* 19138 * Function: 19139 * _bcm_ap_cosq_endpoint_gport_create 19140 * Purpose: 19141 * Create a GPORT endpoint. 19142 * Parameters: 19143 * unit - (IN) Unit number. 19144 * endpoint_id - (IN) Endpoint ID 19145 * gport - (IN) GPORT ID 19146 * Returns: 19147 * BCM_E_xxx 19148 */ 19149 STATIC int 19150 _bcm_ap_cosq_endpoint_gport_create( 19151 int unit, 19152 int endpoint_id, 19153 bcm_gport_t gport) 19154 { 19155 int vp; 19156 ing_dvp_table_entry_t dvp_entry; 19157 int nh_index; 19158 ing_l3_next_hop_entry_t nh_entry; 19159 int eh_tag_type; 19160 19161 /* Get virtual port value */ 19162 if (BCM_GPORT_IS_VLAN_PORT(gport)) { 19163 vp = BCM_GPORT_VLAN_PORT_ID_GET(gport); 19164 #if defined(INCLUDE_L3) 19165 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeVlan)) { 19166 /* VP is not configured yet */ 19167 return BCM_E_CONFIG; 19168 } 19169 #endif 19170 } else if (BCM_GPORT_IS_NIV_PORT(gport)) { 19171 vp = BCM_GPORT_NIV_PORT_ID_GET(gport); 19172 #if defined(INCLUDE_L3) 19173 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeNiv)) { 19174 /* VP is not configured yet */ 19175 return BCM_E_CONFIG; 19176 } 19177 #endif 19178 } else { 19179 return BCM_E_PARAM; 19180 } 19181 19182 /* Get VP's next hop index */ 19183 BCM_IF_ERROR_RETURN 19184 (READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp_entry)); 19185 nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp_entry, 19186 NEXT_HOP_INDEXf); 19187 19188 /* Set endpoint ID in next hop entry */ 19189 BCM_IF_ERROR_RETURN 19190 (READ_ING_L3_NEXT_HOPm(unit, MEM_BLOCK_ANY, nh_index, &nh_entry)); 19191 eh_tag_type = soc_ING_L3_NEXT_HOPm_field32_get(unit, &nh_entry, 19192 EH_TAG_TYPEf); 19193 if (eh_tag_type != 0) { 19194 /* A queue tag has already been configured for this next hop entry. */ 19195 return BCM_E_EXISTS; 19196 } 19197 soc_ING_L3_NEXT_HOPm_field32_set(unit, &nh_entry, EH_TAG_TYPEf, 2); 19198 soc_ING_L3_NEXT_HOPm_field32_set(unit, &nh_entry, EH_QUEUE_TAGf, endpoint_id); 19199 BCM_IF_ERROR_RETURN 19200 (WRITE_ING_L3_NEXT_HOPm(unit, MEM_BLOCK_ALL, nh_index, &nh_entry)); 19201 19202 return BCM_E_NONE; 19203 } 19204 19205 /* 19206 * Function: 19207 * _bcm_ap_cosq_endpoint_gport_destroy 19208 * Purpose: 19209 * Destroy a GPORT endpoint. 19210 * Parameters: 19211 * unit - (IN) Unit number. 19212 * gport - (IN) GPORT ID 19213 * Returns: 19214 * BCM_E_xxx 19215 */ 19216 STATIC int 19217 _bcm_ap_cosq_endpoint_gport_destroy( 19218 int unit, 19219 bcm_gport_t gport) 19220 { 19221 int vp; 19222 ing_dvp_table_entry_t dvp_entry; 19223 int nh_index; 19224 ing_l3_next_hop_entry_t nh_entry; 19225 19226 /* Get virtual port value */ 19227 if (BCM_GPORT_IS_VLAN_PORT(gport)) { 19228 vp = BCM_GPORT_VLAN_PORT_ID_GET(gport); 19229 #if defined(INCLUDE_L3) 19230 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeVlan)) { 19231 /* VP is not configured yet */ 19232 return BCM_E_CONFIG; 19233 } 19234 #endif 19235 } else if (BCM_GPORT_IS_NIV_PORT(gport)) { 19236 vp = BCM_GPORT_NIV_PORT_ID_GET(gport); 19237 #if defined(INCLUDE_L3) 19238 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeNiv)) { 19239 /* VP is not configured yet */ 19240 return BCM_E_CONFIG; 19241 } 19242 #endif 19243 } else { 19244 return BCM_E_PARAM; 19245 } 19246 19247 /* Get VP's next hop index */ 19248 BCM_IF_ERROR_RETURN 19249 (READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp_entry)); 19250 nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp_entry, 19251 NEXT_HOP_INDEXf); 19252 19253 /* Delete endpoint ID in next hop entry */ 19254 BCM_IF_ERROR_RETURN 19255 (READ_ING_L3_NEXT_HOPm(unit, MEM_BLOCK_ANY, nh_index, &nh_entry)); 19256 soc_ING_L3_NEXT_HOPm_field32_set(unit, &nh_entry, EH_TAG_TYPEf, 0); 19257 soc_ING_L3_NEXT_HOPm_field32_set(unit, &nh_entry, EH_QUEUE_TAGf, 0); 19258 BCM_IF_ERROR_RETURN 19259 (WRITE_ING_L3_NEXT_HOPm(unit, MEM_BLOCK_ALL, nh_index, &nh_entry)); 19260 19261 return BCM_E_NONE; 19262 } 19263 19264 /* 19265 * Function: 19266 * bcm_ap_cosq_endpoint_create 19267 * Purpose: 19268 * Create an endpoint. 19269 * Parameters: 19270 * unit - (IN) Unit number. 19271 * classifier - (IN) Classifier attributes 19272 * classifier_id - (IN/OUT) Classifier ID 19273 * Returns: 19274 * BCM_E_xxx 19275 */ 19276 int 19277 bcm_ap_cosq_endpoint_create( 19278 int unit, 19279 bcm_cosq_classifier_t *classifier, 19280 int *classifier_id) 19281 { 19282 int endpoint_id = 0; 19283 int i; 19284 19285 if (NULL == classifier || NULL == classifier_id) { 19286 return BCM_E_PARAM; 19287 } 19288 19289 if (classifier->flags & BCM_COSQ_CLASSIFIER_WITH_ID) { 19290 if (!_BCM_COSQ_CLASSIFIER_IS_ENDPOINT(*classifier_id)) { 19291 return BCM_E_PARAM; 19292 } 19293 endpoint_id = _BCM_COSQ_CLASSIFIER_ENDPOINT_GET(*classifier_id); 19294 if (endpoint_id >= _BCM_AP_NUM_ENDPOINT(unit)) { 19295 return BCM_E_PARAM; 19296 } 19297 if (_BCM_AP_ENDPOINT_IS_USED(unit, endpoint_id)) { 19298 return BCM_E_EXISTS; 19299 } 19300 } else { 19301 /* Get a free endpoint ID */ 19302 for (i = 0; i < _BCM_AP_NUM_ENDPOINT(unit); i++) { 19303 if (!_BCM_AP_ENDPOINT_IS_USED(unit, i)) { 19304 endpoint_id = i; 19305 break; 19306 } 19307 } 19308 if (i == _BCM_AP_NUM_ENDPOINT(unit)) { 19309 /* No available endpoint ID */ 19310 return BCM_E_RESOURCE; 19311 } 19312 } 19313 _BCM_AP_ENDPOINT(unit, endpoint_id) = sal_alloc( 19314 sizeof(_bcm_ap_endpoint_t), "Endpoint Info"); 19315 if (NULL == _BCM_AP_ENDPOINT(unit, endpoint_id)) { 19316 return BCM_E_MEMORY; 19317 } 19318 sal_memset(_BCM_AP_ENDPOINT(unit, endpoint_id), 0, 19319 sizeof(_bcm_ap_endpoint_t)); 19320 19321 if (classifier->flags & BCM_COSQ_CLASSIFIER_L2) { 19322 _BCM_AP_ENDPOINT(unit, endpoint_id)->flags = BCM_COSQ_CLASSIFIER_L2; 19323 _BCM_AP_ENDPOINT(unit, endpoint_id)->vlan = classifier->vlan; 19324 sal_memcpy(_BCM_AP_ENDPOINT(unit, endpoint_id)->mac, classifier->mac, 19325 sizeof(bcm_mac_t)); 19326 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_endpoint_l2_create(unit, 19327 endpoint_id, classifier->vlan, classifier->mac)); 19328 } else if (classifier->flags & BCM_COSQ_CLASSIFIER_L3) { 19329 #if defined(INCLUDE_L3) 19330 _BCM_AP_ENDPOINT(unit, endpoint_id)->flags = BCM_COSQ_CLASSIFIER_L3; 19331 _BCM_AP_ENDPOINT(unit, endpoint_id)->vrf = classifier->vrf; 19332 if (classifier->flags & BCM_COSQ_CLASSIFIER_IP6) { 19333 _BCM_AP_ENDPOINT(unit, endpoint_id)->flags |= BCM_COSQ_CLASSIFIER_IP6; 19334 sal_memcpy(_BCM_AP_ENDPOINT(unit, endpoint_id)->ip6_addr, 19335 classifier->ip6_addr, BCM_IP6_ADDRLEN); 19336 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_endpoint_ip6_create(unit, 19337 endpoint_id, classifier->vrf, classifier->ip6_addr)); 19338 } else { 19339 _BCM_AP_ENDPOINT(unit, endpoint_id)->ip_addr = classifier->ip_addr; 19340 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_endpoint_ip4_create(unit, 19341 endpoint_id, classifier->vrf, classifier->ip_addr)); 19342 } 19343 #endif /* INCLUDE_L3 */ 19344 } else if (classifier->flags & BCM_COSQ_CLASSIFIER_GPORT) { 19345 _BCM_AP_ENDPOINT(unit, endpoint_id)->flags = BCM_COSQ_CLASSIFIER_GPORT; 19346 _BCM_AP_ENDPOINT(unit, endpoint_id)->gport = classifier->gport; 19347 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_endpoint_gport_create(unit, 19348 endpoint_id, classifier->gport)); 19349 } else { 19350 return BCM_E_PARAM; 19351 } 19352 19353 _BCM_COSQ_CLASSIFIER_ENDPOINT_SET(*classifier_id, endpoint_id); 19354 19355 return BCM_E_NONE; 19356 } 19357 19358 /* 19359 * Function: 19360 * bcm_ap_cosq_endpoint_destroy 19361 * Purpose: 19362 * Destroy an endpoint. 19363 * Parameters: 19364 * unit - (IN) Unit number. 19365 * classifier_id - (IN) Classifier ID 19366 * Returns: 19367 * BCM_E_xxx 19368 */ 19369 int 19370 bcm_ap_cosq_endpoint_destroy( 19371 int unit, 19372 int classifier_id) 19373 { 19374 int endpoint_id; 19375 19376 if (!_BCM_COSQ_CLASSIFIER_IS_ENDPOINT(classifier_id)) { 19377 return BCM_E_PARAM; 19378 } 19379 endpoint_id = _BCM_COSQ_CLASSIFIER_ENDPOINT_GET(classifier_id); 19380 if (endpoint_id >= _BCM_AP_NUM_ENDPOINT(unit)) { 19381 return BCM_E_PARAM; 19382 } 19383 if (!_BCM_AP_ENDPOINT_IS_USED(unit, endpoint_id)) { 19384 return BCM_E_NOT_FOUND; 19385 } 19386 19387 if (_BCM_AP_ENDPOINT(unit, endpoint_id)->flags & 19388 BCM_COSQ_CLASSIFIER_L2) { 19389 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_endpoint_l2_destroy(unit, 19390 _BCM_AP_ENDPOINT(unit, endpoint_id)->vlan, 19391 _BCM_AP_ENDPOINT(unit, endpoint_id)->mac)); 19392 } else if (_BCM_AP_ENDPOINT(unit, endpoint_id)->flags & 19393 BCM_COSQ_CLASSIFIER_L3) { 19394 #if defined(INCLUDE_L3) 19395 if (_BCM_AP_ENDPOINT(unit, endpoint_id)->flags & 19396 BCM_COSQ_CLASSIFIER_IP6) { 19397 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_endpoint_ip6_destroy(unit, 19398 _BCM_AP_ENDPOINT(unit, endpoint_id)->vrf, 19399 _BCM_AP_ENDPOINT(unit, endpoint_id)->ip6_addr)); 19400 } else { 19401 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_endpoint_ip4_destroy(unit, 19402 _BCM_AP_ENDPOINT(unit, endpoint_id)->vrf, 19403 _BCM_AP_ENDPOINT(unit, endpoint_id)->ip_addr)); 19404 } 19405 #endif 19406 } else if (_BCM_AP_ENDPOINT(unit, endpoint_id)->flags & 19407 BCM_COSQ_CLASSIFIER_GPORT) { 19408 BCM_IF_ERROR_RETURN(_bcm_ap_cosq_endpoint_gport_destroy(unit, 19409 _BCM_AP_ENDPOINT(unit, endpoint_id)->gport)); 19410 } else { 19411 return BCM_E_INTERNAL; 19412 } 19413 19414 sal_free(_BCM_AP_ENDPOINT(unit, endpoint_id)); 19415 _BCM_AP_ENDPOINT(unit, endpoint_id) = NULL; 19416 19417 return BCM_E_NONE; 19418 } 19419 19420 /* 19421 * Function: 19422 * bcm_ap_cosq_endpoint_get 19423 * Purpose: 19424 * Get info about an endpoint. 19425 * Parameters: 19426 * unit - (IN) Unit number. 19427 * classifier_id - (IN) Classifier ID 19428 * classifier - (OUT) Classifier info 19429 * Returns: 19430 * BCM_E_xxx 19431 */ 19432 int 19433 bcm_ap_cosq_endpoint_get( 19434 int unit, 19435 int classifier_id, 19436 bcm_cosq_classifier_t *classifier) 19437 { 19438 int endpoint_id; 19439 19440 if (!_BCM_COSQ_CLASSIFIER_IS_ENDPOINT(classifier_id)) { 19441 return BCM_E_PARAM; 19442 } 19443 endpoint_id = _BCM_COSQ_CLASSIFIER_ENDPOINT_GET(classifier_id); 19444 if (endpoint_id >= _BCM_AP_NUM_ENDPOINT(unit)) { 19445 return BCM_E_PARAM; 19446 } 19447 if (!_BCM_AP_ENDPOINT_IS_USED(unit, endpoint_id)) { 19448 return BCM_E_NOT_FOUND; 19449 } 19450 19451 classifier->flags = _BCM_AP_ENDPOINT(unit, endpoint_id)->flags; 19452 classifier->vlan = _BCM_AP_ENDPOINT(unit, endpoint_id)->vlan; 19453 sal_memcpy(classifier->mac, _BCM_AP_ENDPOINT(unit, endpoint_id)->mac, 19454 sizeof(bcm_mac_t)); 19455 classifier->vrf = _BCM_AP_ENDPOINT(unit, endpoint_id)->vrf; 19456 classifier->ip_addr = _BCM_AP_ENDPOINT(unit, endpoint_id)->ip_addr; 19457 sal_memcpy(classifier->ip6_addr, 19458 _BCM_AP_ENDPOINT(unit, endpoint_id)->ip6_addr, BCM_IP6_ADDRLEN); 19459 classifier->gport = _BCM_AP_ENDPOINT(unit, endpoint_id)->gport; 19460 19461 return BCM_E_NONE; 19462 } 19463 /* 19464 * Function: 19465 * bcm_ap_cosq_endpoint_map_set 19466 * Purpose: 19467 * Set the mapping from port, classifier, and multiple internal priorities 19468 * to multiple COS queues in a queue group. 19469 * Parameters: 19470 * unit - (IN) Unit number. 19471 * port - (IN) local port ID 19472 * classifier_id - (IN) Classifier ID 19473 * queue_group - (IN) Base queue ID 19474 * array_count - (IN) Number of elements in priority_array and 19475 * cosq_array 19476 * priority_array - (IN) Array of internal priorities 19477 * cosq_array - (IN) Array of COS queues 19478 * Returns: 19479 * BCM_E_xxx 19480 */ 19481 int 19482 bcm_ap_cosq_endpoint_map_set( 19483 int unit, 19484 bcm_port_t port, 19485 int classifier_id, 19486 bcm_gport_t queue_group, 19487 int array_count, 19488 bcm_cos_t *priority_array, 19489 bcm_cos_queue_t *cosq_array) 19490 { 19491 int rv = BCM_E_NONE; 19492 int endpoint_id; 19493 int qid; 19494 int num_entries_per_profile; 19495 int alloc_size; 19496 endpoint_cos_map_entry_t *entry_array = NULL; 19497 void *entries = NULL; 19498 endpoint_queue_map_entry_t qmap_key, qmap_data, qmap_entry; 19499 int qmap_index; 19500 int old_profile_index, new_profile_index; 19501 int old_qid; 19502 int i; 19503 int priority; 19504 uint64 rval64; 19505 uint32 endpoint_cos_map_prof_idx; 19506 if (!_BCM_COSQ_CLASSIFIER_IS_ENDPOINT(classifier_id)) { 19507 return BCM_E_PARAM; 19508 } 19509 endpoint_id = _BCM_COSQ_CLASSIFIER_ENDPOINT_GET(classifier_id); 19510 if (endpoint_id >= _BCM_AP_NUM_ENDPOINT(unit)) { 19511 return BCM_E_PARAM; 19512 } 19513 if (!_BCM_AP_ENDPOINT_IS_USED(unit, endpoint_id)) { 19514 return BCM_E_PARAM; 19515 } 19516 19517 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(queue_group)) { 19518 qid = BCM_GPORT_UCAST_QUEUE_GROUP_QID_GET(queue_group); 19519 } else { 19520 return BCM_E_PARAM; 19521 } 19522 19523 /* Allocate an Endpoint CoS Map profile */ 19524 num_entries_per_profile = 16; 19525 alloc_size = sizeof(endpoint_cos_map_entry_t) * num_entries_per_profile; 19526 entry_array = sal_alloc(alloc_size, "Endpoint CoS Map Profile"); 19527 if (NULL == entry_array) { 19528 return BCM_E_MEMORY; 19529 } 19530 sal_memset(entry_array, 0, alloc_size); 19531 19532 /* Search Endpoint Queue Map table */ 19533 sal_memcpy(&qmap_key, soc_mem_entry_null(unit, 19534 ENDPOINT_QUEUE_MAPm), sizeof(endpoint_queue_map_entry_t)); 19535 soc_ENDPOINT_QUEUE_MAPm_field32_set(unit, &qmap_key, KEY_TYPEf, 0); 19536 soc_ENDPOINT_QUEUE_MAPm_field32_set(unit, &qmap_key, DEST_PORTf, port); 19537 soc_ENDPOINT_QUEUE_MAPm_field32_set(unit, &qmap_key, EH_QUEUE_TAGf, 19538 endpoint_id); 19539 rv = soc_mem_search(unit, ENDPOINT_QUEUE_MAPm, MEM_BLOCK_ANY, 19540 &qmap_index, &qmap_key, &qmap_data, 0); 19541 if (rv == SOC_E_NOT_FOUND) { 19542 old_profile_index = -1; 19543 } else if (rv == SOC_E_NONE) { 19544 /* Existing entry found. Compare base queue ID and extract 19545 * old Endpoint CoS Map profile. 19546 */ 19547 old_qid = soc_ENDPOINT_QUEUE_MAPm_field32_get(unit, 19548 &qmap_data, ENDPOINT_QUEUE_BASEf); 19549 if (old_qid != qid) { 19550 /* The classifier is already mapped to another queue group */ 19551 sal_free(entry_array); 19552 return BCM_E_EXISTS; 19553 } 19554 endpoint_cos_map_prof_idx = soc_ENDPOINT_QUEUE_MAPm_field32_get(unit, 19555 &qmap_data, ENDPOINT_COS_MAP_PROFILE_INDEXf); 19556 entries = entry_array; 19557 /* 19558 * The index of ENDPOINT_COS_MAP = 19559 * ENDPOINT_COS_MAP_PROFILE_INDEX * 16 + INT_PRI 19560 */ 19561 old_profile_index = endpoint_cos_map_prof_idx * num_entries_per_profile; 19562 rv = soc_profile_mem_get(unit, _BCM_AP_ENDPOINT_COS_MAP_PROFILE(unit), 19563 old_profile_index, num_entries_per_profile, &entries); 19564 if (SOC_FAILURE(rv)) { 19565 sal_free(entry_array); 19566 return rv; 19567 } 19568 } else { 19569 sal_free(entry_array); 19570 return rv; 19571 } 19572 19573 /* Construct or modify Endpoint CoS Map profile and add it */ 19574 for (i = 0; i < array_count; i++) { 19575 priority = priority_array[i]; 19576 if ((priority < 0) || (priority >= 16)) { 19577 sal_free(entry_array); 19578 return BCM_E_PARAM; 19579 } 19580 soc_ENDPOINT_COS_MAPm_field32_set(unit, &entry_array[priority], 19581 ENDPOINT_COS_OFFSETf, cosq_array[i]); 19582 } 19583 entries = entry_array; 19584 rv = soc_profile_mem_add(unit, _BCM_AP_ENDPOINT_COS_MAP_PROFILE(unit), 19585 &entries, num_entries_per_profile, (uint32 *)&new_profile_index); 19586 sal_free(entry_array); 19587 if (SOC_FAILURE(rv)) { 19588 return rv; 19589 } 19590 19591 /* Insert or replace Endpoint Queue Map entry */ 19592 sal_memcpy(&qmap_entry, &qmap_key, sizeof(endpoint_queue_map_entry_t)); 19593 soc_ENDPOINT_QUEUE_MAPm_field32_set(unit, &qmap_entry, VALIDf, 1); 19594 soc_ENDPOINT_QUEUE_MAPm_field32_set(unit, &qmap_entry, 19595 ENDPOINT_QUEUE_BASEf, qid); 19596 endpoint_cos_map_prof_idx = new_profile_index / num_entries_per_profile; 19597 soc_ENDPOINT_QUEUE_MAPm_field32_set(unit, &qmap_entry, 19598 ENDPOINT_COS_MAP_PROFILE_INDEXf, endpoint_cos_map_prof_idx); 19599 rv = soc_mem_insert(unit, ENDPOINT_QUEUE_MAPm, MEM_BLOCK_ALL, &qmap_entry); 19600 if (SOC_FAILURE(rv) && rv != SOC_E_EXISTS) { 19601 return rv; 19602 } 19603 19604 /* Delete old Endpoint CoS Map profile */ 19605 if (old_profile_index != -1) { 19606 SOC_IF_ERROR_RETURN 19607 (soc_profile_mem_delete(unit, 19608 _BCM_AP_ENDPOINT_COS_MAP_PROFILE(unit), 19609 old_profile_index)); 19610 } 19611 19612 /* Set port's queuing mode to be endpoint queuing */ 19613 SOC_IF_ERROR_RETURN(READ_ING_COS_MODE_64r(unit, port, &rval64)); 19614 if (4 != soc_reg64_field32_get(unit, ING_COS_MODE_64r, rval64, 19615 QUEUE_MODEf)) { 19616 soc_reg64_field32_set(unit, ING_COS_MODE_64r, &rval64, QUEUE_MODEf, 4); 19617 SOC_IF_ERROR_RETURN(WRITE_ING_COS_MODE_64r(unit, port, rval64)); 19618 } 19619 19620 return rv; 19621 } 19622 19623 /* 19624 * Function: 19625 * bcm_ap_cosq_endpoint_map_get 19626 * Purpose: 19627 * Get the mapping from port, classifier, and multiple internal priorities 19628 * to multiple COS queues in a queue group. 19629 * Parameters: 19630 * unit - (IN) Unit number. 19631 * port - (IN) Local port ID 19632 * classifier_id - (IN) Classifier ID 19633 * queue_group - (OUT) Queue group 19634 * array_max - (IN) Size of priority_array and cosq_array 19635 * priority_array - (IN) Array of internal priorities 19636 * cosq_array - (OUT) Array of COS queues 19637 * array_count - (OUT) Size of cosq_array 19638 * Returns: 19639 * BCM_E_xxx 19640 */ 19641 int 19642 bcm_ap_cosq_endpoint_map_get( 19643 int unit, 19644 bcm_port_t port, 19645 int classifier_id, 19646 bcm_gport_t *queue_group, 19647 int array_max, 19648 bcm_cos_t *priority_array, 19649 bcm_cos_queue_t *cosq_array, 19650 int *array_count) 19651 { 19652 int rv = BCM_E_NONE; 19653 int endpoint_id; 19654 endpoint_queue_map_entry_t qmap_key, qmap_data; 19655 int qmap_index; 19656 int qid; 19657 int num_entries_per_profile; 19658 int alloc_size; 19659 endpoint_cos_map_entry_t *entry_array = NULL; 19660 void *entries = NULL; 19661 int profile_index; 19662 int i; 19663 int priority; 19664 uint32 endpoint_cos_map_prof_idx; 19665 19666 if (!_BCM_COSQ_CLASSIFIER_IS_ENDPOINT(classifier_id)) { 19667 return BCM_E_PARAM; 19668 } 19669 endpoint_id = _BCM_COSQ_CLASSIFIER_ENDPOINT_GET(classifier_id); 19670 if (endpoint_id >= _BCM_AP_NUM_ENDPOINT(unit)) { 19671 return BCM_E_PARAM; 19672 } 19673 if (!_BCM_AP_ENDPOINT_IS_USED(unit, endpoint_id)) { 19674 return BCM_E_PARAM; 19675 } 19676 19677 /* Search Endpoint Queue Map table */ 19678 sal_memcpy(&qmap_key, soc_mem_entry_null(unit, 19679 ENDPOINT_QUEUE_MAPm), sizeof(endpoint_queue_map_entry_t)); 19680 soc_ENDPOINT_QUEUE_MAPm_field32_set(unit, &qmap_key, KEY_TYPEf, 0); 19681 soc_ENDPOINT_QUEUE_MAPm_field32_set(unit, &qmap_key, DEST_PORTf, port); 19682 soc_ENDPOINT_QUEUE_MAPm_field32_set(unit, &qmap_key, EH_QUEUE_TAGf, 19683 endpoint_id); 19684 SOC_IF_ERROR_RETURN(soc_mem_search(unit, ENDPOINT_QUEUE_MAPm, MEM_BLOCK_ANY, 19685 &qmap_index, &qmap_key, &qmap_data, 0)); 19686 19687 /* Get queue group */ 19688 qid = soc_ENDPOINT_QUEUE_MAPm_field32_get(unit, &qmap_data, 19689 ENDPOINT_QUEUE_BASEf); 19690 BCM_GPORT_UCAST_QUEUE_GROUP_SYSQID_SET(*queue_group, port, qid); 19691 19692 /* Get Endpoint CoS Map profile */ 19693 num_entries_per_profile = 16; 19694 alloc_size = sizeof(endpoint_cos_map_entry_t) * num_entries_per_profile; 19695 entry_array = sal_alloc(alloc_size, "Endpoint CoS Map Profile"); 19696 if (NULL == entry_array) { 19697 return BCM_E_MEMORY; 19698 } 19699 sal_memset(entry_array, 0, alloc_size); 19700 entries = entry_array; 19701 endpoint_cos_map_prof_idx = soc_ENDPOINT_QUEUE_MAPm_field32_get(unit, &qmap_data, 19702 ENDPOINT_COS_MAP_PROFILE_INDEXf); 19703 /* 19704 * The index of ENDPOINT_COS_MAP = 19705 * ENDPOINT_COS_MAP_PROFILE_INDEX * 16 + INT_PRI 19706 */ 19707 profile_index = endpoint_cos_map_prof_idx * num_entries_per_profile; 19708 rv = soc_profile_mem_get(unit, _BCM_AP_ENDPOINT_COS_MAP_PROFILE(unit), 19709 profile_index, num_entries_per_profile, &entries); 19710 if (SOC_FAILURE(rv)) { 19711 sal_free(entry_array); 19712 return rv; 19713 } 19714 19715 /* Get internal priority to CoS mapping */ 19716 if (array_max == 0) { 19717 if (NULL != array_count) { 19718 *array_count = num_entries_per_profile; 19719 } 19720 } else { 19721 *array_count = 0; 19722 for (i = 0; i < array_max; i++) { 19723 priority = priority_array[i]; 19724 if (priority >= 16 || priority < 0) { 19725 sal_free(entry_array); 19726 return BCM_E_PARAM; 19727 } 19728 cosq_array[i] = soc_ENDPOINT_COS_MAPm_field32_get(unit, 19729 &entry_array[priority], ENDPOINT_COS_OFFSETf); 19730 (*array_count)++; 19731 } 19732 } 19733 19734 sal_free(entry_array); 19735 return rv; 19736 } 19737 19738 /* 19739 * Function: 19740 * bcm_ap_cosq_endpoint_map_clear 19741 * Purpose: 19742 * Clear the mapping from port, classifier, and internal priorities 19743 * to COS queues in a queue group. 19744 * Parameters: 19745 * unit - (IN) Unit number. 19746 * port - (IN) Local port ID 19747 * classifier_id - (IN) Classifier ID 19748 * Returns: 19749 * BCM_E_xxx 19750 */ 19751 int 19752 bcm_ap_cosq_endpoint_map_clear( 19753 int unit, 19754 bcm_gport_t port, 19755 int classifier_id) 19756 { 19757 int endpoint_id; 19758 endpoint_queue_map_entry_t qmap_key, qmap_data; 19759 int profile_index; 19760 int num_entries_per_set = 16; 19761 19762 if (!_BCM_COSQ_CLASSIFIER_IS_ENDPOINT(classifier_id)) { 19763 return BCM_E_PARAM; 19764 } 19765 endpoint_id = _BCM_COSQ_CLASSIFIER_ENDPOINT_GET(classifier_id); 19766 if (endpoint_id >= _BCM_AP_NUM_ENDPOINT(unit)) { 19767 return BCM_E_PARAM; 19768 } 19769 if (!_BCM_AP_ENDPOINT_IS_USED(unit, endpoint_id)) { 19770 return BCM_E_PARAM; 19771 } 19772 19773 /* Delete (port, endpoint_id) entry from Endpoint Queue Map table */ 19774 sal_memcpy(&qmap_key, soc_mem_entry_null(unit, 19775 ENDPOINT_QUEUE_MAPm), sizeof(endpoint_queue_map_entry_t)); 19776 soc_ENDPOINT_QUEUE_MAPm_field32_set(unit, &qmap_key, KEY_TYPEf, 0); 19777 soc_ENDPOINT_QUEUE_MAPm_field32_set(unit, &qmap_key, DEST_PORTf, port); 19778 soc_ENDPOINT_QUEUE_MAPm_field32_set(unit, &qmap_key, EH_QUEUE_TAGf, 19779 endpoint_id); 19780 SOC_IF_ERROR_RETURN(soc_mem_delete_return_old(unit, ENDPOINT_QUEUE_MAPm, 19781 MEM_BLOCK_ALL, &qmap_key, &qmap_data)); 19782 19783 /* Delete priority to CoS mapping profile */ 19784 profile_index = soc_ENDPOINT_QUEUE_MAPm_field32_get(unit, &qmap_data, 19785 ENDPOINT_COS_MAP_PROFILE_INDEXf); 19786 profile_index = profile_index * num_entries_per_set; 19787 SOC_IF_ERROR_RETURN(soc_profile_mem_delete(unit, 19788 _BCM_AP_ENDPOINT_COS_MAP_PROFILE(unit), profile_index)); 19789 19790 return BCM_E_NONE; 19791 } 19792 19793 /* 19794 * Function: 19795 * bcm_ap_cosq_field_classifier_get 19796 * Purpose: 19797 * Get classifier type information. 19798 * Parameters: 19799 * unit - (IN) Unit number. 19800 * classifier_id - (IN) Classifier ID 19801 * classifier - (OUT) Classifier info 19802 * Returns: 19803 * BCM_E_xxx 19804 */ 19805 int 19806 bcm_ap_cosq_field_classifier_get( 19807 int unit, 19808 int classifier_id, 19809 bcm_cosq_classifier_t *classifier) 19810 { 19811 if (classifier == NULL) { 19812 return BCM_E_PARAM; 19813 } 19814 sal_memset(classifier, 0, sizeof(bcm_cosq_classifier_t)); 19815 19816 if (_BCM_COSQ_CLASSIFIER_IS_FIELD(classifier_id)) { 19817 classifier->flags |= BCM_COSQ_CLASSIFIER_FIELD; 19818 } 19819 19820 return BCM_E_NONE; 19821 } 19822 19823 19824 19825 /* 19826 * Function: 19827 * bcm_ap_cosq_field_classifier_id_create 19828 * Purpose: 19829 * Create a cosq classifier. 19830 * Parameters: 19831 * unit - (IN) Unit number. 19832 * classifier - (IN) Classifier attributes 19833 * classifier_id - (OUT) Classifier ID 19834 * Returns: 19835 * BCM_E_xxx 19836 */ 19837 int 19838 bcm_ap_cosq_field_classifier_id_create( 19839 int unit, 19840 bcm_cosq_classifier_t *classifier, 19841 int *classifier_id) 19842 { 19843 int rv; 19844 int ref_count = 0; 19845 int ent_per_set = _AP_NUM_INTERNAL_PRI; 19846 int i; 19847 19848 if (NULL == classifier || NULL == classifier_id) { 19849 return BCM_E_PARAM; 19850 } 19851 19852 for (i = 0; i < SOC_MEM_SIZE(unit, IFP_COS_MAPm); i += ent_per_set) { 19853 rv = soc_profile_mem_ref_count_get( 19854 unit, _bcm_ap_ifp_cos_map_profile[unit], i, &ref_count); 19855 if (SOC_FAILURE(rv)) { 19856 return rv; 19857 } 19858 if (0 == ref_count) { 19859 break; 19860 } 19861 } 19862 19863 if (i >= SOC_MEM_SIZE(unit, IFP_COS_MAPm) && ref_count != 0) { 19864 *classifier_id = 0; 19865 return BCM_E_RESOURCE; 19866 } 19867 19868 _BCM_COSQ_CLASSIFIER_FIELD_SET(*classifier_id, (i / ent_per_set)); 19869 19870 return BCM_E_NONE; 19871 } 19872 19873 19874 /* 19875 * Function: 19876 * bcm_ap_cosq_field_classifier_map_set 19877 * Purpose: 19878 * Set internal priority to ingress field processor CoS queue 19879 * override mapping. 19880 * Parameters: 19881 * unit - (IN) Unit number. 19882 * classifier_id - (IN) Classifier ID 19883 * count - (IN) Number of elements in priority_array and 19884 * cosq_array 19885 * priority_array - (IN) Array of internal priorities 19886 * cosq_array - (IN) Array of COS queues 19887 * Returns: 19888 * BCM_E_xxx 19889 */ 19890 int 19891 bcm_ap_cosq_field_classifier_map_set( 19892 int unit, 19893 int classifier_id, 19894 int count, 19895 bcm_cos_t *priority_array, 19896 bcm_cos_queue_t *cosq_array) 19897 { 19898 int rv; 19899 int i; 19900 int max_entries = _AP_NUM_INTERNAL_PRI; 19901 uint32 index; 19902 void *entries[1]; 19903 ifp_cos_map_entry_t ent_buf[_AP_NUM_INTERNAL_PRI]; 19904 int ref_count = 0; 19905 int field_width = 0 ; 19906 /* Input parameter check. */ 19907 if (!_BCM_COSQ_CLASSIFIER_IS_FIELD(classifier_id)) { 19908 return BCM_E_PARAM; 19909 } 19910 19911 if (NULL == priority_array || NULL == cosq_array) { 19912 return BCM_E_PARAM; 19913 } 19914 19915 if (count > max_entries) { 19916 return BCM_E_PARAM; 19917 } 19918 19919 field_width = soc_mem_field_length(unit, IFP_COS_MAPm, IFP_COSf); 19920 sal_memset(ent_buf, 0, sizeof(ifp_cos_map_entry_t) * max_entries); 19921 entries[0] = ent_buf; 19922 19923 for (i = 0; i < count; i++) { 19924 if (priority_array[i] < max_entries) { 19925 if (cosq_array[i] >= (1 << field_width)) { 19926 return BCM_E_PARAM; 19927 } 19928 soc_mem_field32_set(unit, IFP_COS_MAPm, &ent_buf[priority_array[i]], 19929 IFP_COSf, cosq_array[i]); 19930 } 19931 } 19932 19933 index = _BCM_COSQ_CLASSIFIER_FIELD_GET(classifier_id); 19934 SOC_IF_ERROR_RETURN( 19935 soc_profile_mem_ref_count_get(unit, _bcm_ap_ifp_cos_map_profile[unit], 19936 index * max_entries, &ref_count)); 19937 19938 if (ref_count == 0) { 19939 rv = soc_profile_mem_add(unit, _bcm_ap_ifp_cos_map_profile[unit], 19940 entries, max_entries, &index); 19941 } else { 19942 rv = soc_profile_mem_set(unit, _bcm_ap_ifp_cos_map_profile[unit], 19943 entries, index * max_entries); 19944 if (rv == SOC_E_NONE) { 19945 /* decrease the profile ref_count increased by mem_set */ 19946 rv = soc_profile_mem_delete(unit, 19947 _bcm_ap_ifp_cos_map_profile[unit], 19948 index * max_entries); 19949 } 19950 } 19951 return rv; 19952 } 19953 19954 19955 /* 19956 * Function: 19957 * bcm_ap_cosq_field_classifier_map_get 19958 * Purpose: 19959 * Get internal priority to ingress field processor CoS queue 19960 * override mapping information. 19961 * Parameters: 19962 * unit - (IN) Unit number. 19963 * classifier_id - (IN) Classifier ID 19964 * array_max - (IN) Size of priority_array and cosq_array 19965 * priority_array - (IN) Array of internal priorities 19966 * cosq_array - (OUT) Array of COS queues 19967 * array_count - (OUT) Size of cosq_array 19968 * Returns: 19969 * BCM_E_xxx 19970 */ 19971 int 19972 bcm_ap_cosq_field_classifier_map_get( 19973 int unit, 19974 int classifier_id, 19975 int array_max, 19976 bcm_cos_t *priority_array, 19977 bcm_cos_queue_t *cosq_array, 19978 int *array_count) 19979 { 19980 int rv; 19981 int i; 19982 int ent_per_set = _AP_NUM_INTERNAL_PRI; 19983 uint32 index; 19984 void *entries[1]; 19985 ifp_cos_map_entry_t ent_buf[_AP_NUM_INTERNAL_PRI]; 19986 19987 /* Input parameter check. */ 19988 if (NULL == priority_array || NULL == cosq_array || NULL == array_count) { 19989 return BCM_E_PARAM; 19990 } 19991 19992 sal_memset(ent_buf, 0, sizeof(ifp_cos_map_entry_t) * ent_per_set); 19993 entries[0] = ent_buf; 19994 19995 /* Get profile table entry set base index. */ 19996 index = _BCM_COSQ_CLASSIFIER_FIELD_GET(classifier_id); 19997 19998 /* Read out entries from profile table into allocated buffer. */ 19999 rv = soc_profile_mem_get(unit, _bcm_ap_ifp_cos_map_profile[unit], 20000 index * ent_per_set, ent_per_set, entries); 20001 if (SOC_FAILURE(rv)) { 20002 return rv; 20003 } 20004 20005 *array_count = array_max > ent_per_set ? ent_per_set : array_max; 20006 20007 /* Copy values into API OUT parameters. */ 20008 for (i = 0; i < *array_count; i++) { 20009 if (priority_array[i] >= _AP_NUM_INTERNAL_PRI) { 20010 return BCM_E_PARAM; 20011 } 20012 cosq_array[i] = soc_mem_field32_get(unit, IFP_COS_MAPm, 20013 &ent_buf[priority_array[i]], 20014 IFP_COSf); 20015 } 20016 20017 return BCM_E_NONE; 20018 } 20019 20020 20021 /* 20022 * Function: 20023 * bcm_ap_cosq_field_classifier_map_clear 20024 * Purpose: 20025 * Delete an internal priority to ingress field processor CoS queue 20026 * override mapping profile set. 20027 * Parameters: 20028 * unit - (IN) Unit number. 20029 * classifier_id - (IN) Classifier ID 20030 * Returns: 20031 * BCM_E_xxx 20032 */ 20033 int 20034 bcm_ap_cosq_field_classifier_map_clear(int unit, int classifier_id) 20035 { 20036 int ent_per_set = _AP_NUM_INTERNAL_PRI; 20037 uint32 index; 20038 20039 /* Get profile table entry set base index. */ 20040 index = _BCM_COSQ_CLASSIFIER_FIELD_GET(classifier_id); 20041 20042 /* Delete the profile entries set. */ 20043 SOC_IF_ERROR_RETURN 20044 (soc_profile_mem_delete(unit, 20045 _bcm_ap_ifp_cos_map_profile[unit], 20046 index * ent_per_set)); 20047 return BCM_E_NONE; 20048 } 20049 20050 20051 /* 20052 * Function: 20053 * bcm_ap_cosq_field_classifier_id_destroy 20054 * Purpose: 20055 * Free resource associated with this field classifier id. 20056 * Parameters: 20057 * unit - (IN) Unit number. 20058 * classifier_id - (IN) Classifier ID 20059 * Returns: 20060 * BCM_E_xxx 20061 */ 20062 int 20063 bcm_ap_cosq_field_classifier_id_destroy(int unit, int classifier_id) 20064 { 20065 return BCM_E_NONE; 20066 } 20067 20068 20069 /* 20070 * Function: 20071 * bcm_td_cosq_cpu_cosq_enable_set 20072 * Purpose: 20073 * To enable/disable Rx of packets on the specified CPU cosq. 20074 * Parameters: 20075 * unit - (IN) Unit number. 20076 * cosq - (IN) CPU Cosq ID 20077 * enable - (IN) Enable/Disable 20078 * Returns: 20079 * BCM_E_xxx 20080 */ 20081 int 20082 bcm_ap_cosq_cpu_cosq_enable_set( 20083 int unit, 20084 bcm_cos_queue_t cosq, 20085 int enable) 20086 { 20087 uint32 entry[SOC_MAX_MEM_WORDS]; 20088 int i, index, enable_status; 20089 _bcm_ap_cosq_cpu_cosq_config_t *cpu_cosq; 20090 soc_info_t *si; 20091 soc_mem_t thdm_mem[] = { 20092 MMU_THDM_DB_QUEUE_CONFIG_0m, 20093 MMU_THDM_MCQE_QUEUE_CONFIG_0m 20094 }; 20095 20096 si = &SOC_INFO(unit); 20097 20098 if ((cosq < 0) || (cosq >= si->num_cpu_cosq)) { 20099 return BCM_E_PARAM; 20100 } 20101 20102 cpu_cosq = _bcm_ap_cosq_cpu_cosq_config[unit][cosq]; 20103 20104 if (!cpu_cosq) { 20105 return BCM_E_INTERNAL; 20106 } 20107 if (enable) { 20108 enable = 1; 20109 } 20110 20111 BCM_IF_ERROR_RETURN(bcm_ap_cosq_cpu_cosq_enable_get(unit, cosq, &enable_status)); 20112 if (enable == enable_status) { 20113 return BCM_E_NONE; 20114 } 20115 20116 /* CPU MC cosq's range from 17114 - 17161. 16384 -17113 are MC's of Regular ports */ 20117 index = 730 + cosq; /* 17114-16384*/ 20118 20119 for (i = 0; i < 2; i++) { 20120 BCM_IF_ERROR_RETURN 20121 (soc_mem_read(unit, thdm_mem[i], MEM_BLOCK_ALL, index, &entry)); 20122 20123 if (enable) { 20124 soc_mem_field32_set(unit, thdm_mem[i], &entry, 20125 Q_MIN_LIMITf, cpu_cosq->q_min_limit[i]); 20126 soc_mem_field32_set(unit, thdm_mem[i], &entry, 20127 Q_SHARED_LIMITf, cpu_cosq->q_shared_limit[i]); 20128 } 20129 else { 20130 cpu_cosq->q_min_limit[i] = soc_mem_field32_get(unit, 20131 thdm_mem[i], 20132 &entry, 20133 Q_MIN_LIMITf); 20134 cpu_cosq->q_shared_limit[i] = soc_mem_field32_get(unit, 20135 thdm_mem[i], 20136 &entry, 20137 Q_SHARED_LIMITf); 20138 cpu_cosq->q_limit_dynamic[i] = soc_mem_field32_get(unit, 20139 thdm_mem[i], 20140 &entry, 20141 Q_LIMIT_DYNAMICf); 20142 cpu_cosq->q_limit_enable[i] = soc_mem_field32_get(unit, 20143 thdm_mem[i], 20144 &entry, 20145 Q_LIMIT_ENABLEf); 20146 cpu_cosq->q_color_limit_enable[i] = soc_mem_field32_get(unit, 20147 thdm_mem[i], &entry, 20148 Q_COLOR_LIMIT_ENABLEf); 20149 soc_mem_field32_set(unit, thdm_mem[i], &entry, Q_MIN_LIMITf, 0); 20150 soc_mem_field32_set(unit, thdm_mem[i], &entry, Q_SHARED_LIMITf, 0); 20151 } 20152 soc_mem_field32_set(unit, thdm_mem[i], &entry, 20153 Q_LIMIT_DYNAMICf, enable ? cpu_cosq->q_limit_dynamic[i] : 0); 20154 soc_mem_field32_set(unit, thdm_mem[i], &entry, 20155 Q_LIMIT_ENABLEf, enable ? cpu_cosq->q_limit_enable[i] : 1); 20156 soc_mem_field32_set(unit, thdm_mem[i], &entry, 20157 Q_COLOR_LIMIT_ENABLEf, enable ? cpu_cosq->q_color_limit_enable[i] : 1); 20158 cpu_cosq->enable = enable; 20159 BCM_IF_ERROR_RETURN( 20160 soc_mem_write(unit, thdm_mem[i], MEM_BLOCK_ALL, index, &entry)); 20161 } 20162 20163 return BCM_E_NONE; 20164 } 20165 20166 /* 20167 * Function: 20168 * bcm_ap_cosq_cpu_cosq_enable_get 20169 * Purpose: 20170 * To get enable/disable status on Rx of packets on the specified CPU cosq. 20171 * Parameters: 20172 * unit - (IN) Unit number. 20173 * cosq - (IN) CPU Cosq ID 20174 * enable - (OUT) Enable/Disable 20175 * Returns: 20176 * BCM_E_xxx 20177 */ 20178 int 20179 bcm_ap_cosq_cpu_cosq_enable_get( 20180 int unit, 20181 bcm_cos_queue_t cosq, 20182 int *enable) 20183 { 20184 _bcm_ap_cosq_cpu_cosq_config_t *cpu_cosq; 20185 soc_field_t dynamic_enable; 20186 soc_info_t *si; 20187 int index, hw_enable; 20188 uint32 entry[SOC_MAX_MEM_WORDS]; 20189 soc_field_t min_limit, shared_limit, limit_enable; 20190 soc_mem_t thd_mem = MMU_THDM_DB_QUEUE_CONFIG_0m; 20191 20192 si = &SOC_INFO(unit); 20193 20194 if ((cosq < 0) || (cosq >= si->num_cpu_cosq)) { 20195 return BCM_E_PARAM; 20196 } 20197 20198 cpu_cosq = _bcm_ap_cosq_cpu_cosq_config[unit][cosq]; 20199 20200 if (!cpu_cosq) { 20201 return BCM_E_INTERNAL; 20202 } 20203 20204 /* CPU MC cosq's range from 17114 - 17161. 20205 16384 -17113 are MC's of Regular ports */ 20206 index = 730 + cosq; /* 17114-16384*/ 20207 hw_enable = 1; 20208 20209 /*sync up software record with hardware status*/ 20210 BCM_IF_ERROR_RETURN(soc_mem_read(unit, thd_mem, MEM_BLOCK_ALL, 20211 index, &entry)); 20212 min_limit = soc_mem_field32_get( unit, thd_mem, &entry, 20213 Q_MIN_LIMITf); 20214 shared_limit = soc_mem_field32_get(unit, thd_mem, &entry, 20215 Q_SHARED_LIMITf); 20216 limit_enable = soc_mem_field32_get(unit, thd_mem, &entry, 20217 Q_LIMIT_ENABLEf); 20218 20219 dynamic_enable = soc_mem_field32_get(unit, thd_mem, &entry, 20220 Q_LIMIT_DYNAMICf); 20221 if (limit_enable && (dynamic_enable == 0)&& 20222 (min_limit == 0) && (shared_limit == 0)) { 20223 hw_enable = 0; 20224 } 20225 cpu_cosq->enable = hw_enable; 20226 20227 *enable = cpu_cosq->enable; 20228 return BCM_E_NONE; 20229 } 20230 20231 /* 20232 * Function: 20233 * bcm_ap_cosq_flex_port_configure 20234 * Purpose 20235 * Delete old default tree and create new tree as per the port type 20236 * Reconfigure all the queues of the port and configure the oversub config 20237 * if required 20238 * Parameters: 20239 * unit - (IN) Unit number. 20240 * old_port_list - (IN) List old ports getting deleted 20241 * num_of_old_ports - (IN) Number of old ports getting deleted 20242 * new_port_list - (IN) List new ports getting added 20243 * num_of_new_ports - (IN) Number of new ports getting added 20244 * num_port_flags - (IN) new ports flags 20245 * Returns: 20246 * BCM_E_xxx 20247 */ 20248 int 20249 bcm_ap_cosq_flex_port_update( 20250 int unit, 20251 bcm_port_t port, int enable) 20252 { 20253 20254 _bcm_ap_mmu_info_t *mmu_info; 20255 soc_info_t *si; 20256 int qnum = 0 ; 20257 _bcm_ap_pipe_resources_t *res; 20258 int phy_port,mmu_port; 20259 int id; 20260 uint64 rval64; 20261 int pipe; 20262 20263 si = &SOC_INFO(unit); 20264 mmu_info = _bcm_ap_mmu_info[unit]; 20265 phy_port = si->port_l2p_mapping[port]; 20266 mmu_port = si->port_p2m_mapping[phy_port]; 20267 20268 pipe = _BCM_AP_PORT_TO_PIPE(unit, port); 20269 res = _BCM_AP_PRESOURCES(mmu_info, pipe); 20270 if (enable) { 20271 si->port_num_cosq[port] = 10; 20272 si->port_cosq_base[port] = (mmu_port * si->port_num_cosq[port]); 20273 if(IS_AP_HSP_PORT(unit, port)) { 20274 si->port_num_uc_cosq[port] = 10; 20275 si->port_uc_cosq_base[port] = mmu_port * si->port_num_cosq[port]; 20276 } else { 20277 si->port_num_uc_cosq[port] = 16; 20278 BCM_IF_ERROR_RETURN( 20279 _bcm_ap_node_index_get(res->l2_queue_list.bits, 160, 20280 mmu_info->num_l2_queues, si->port_num_uc_cosq[port], 20281 8, &id)); 20282 _bcm_ap_node_index_set(&res->l2_queue_list, id, si->port_num_uc_cosq[port]); 20283 si->port_uc_cosq_base[port] = id; 20284 } 20285 20286 mmu_info->port_info[port].resources = &mmu_info->pipe_resources[pipe]; 20287 mmu_info->port_info[port].mc_base = si->port_cosq_base[port]; 20288 mmu_info->port_info[port].mc_limit = si->port_cosq_base[port] + 20289 si->port_num_cosq[port]; 20290 mmu_info->port_info[port].uc_base = si->port_uc_cosq_base[port]; 20291 mmu_info->port_info[port].uc_limit = si->port_uc_cosq_base[port] + 20292 si->port_num_uc_cosq[port]; 20293 COMPILER_64_ZERO(rval64); 20294 if(IS_AP_HSP_PORT(unit, port)) { 20295 SOC_IF_ERROR_RETURN(soc_apache_sched_hw_index_get(unit, 20296 port, SOC_APACHE_NODE_LVL_L1, 0, &qnum)); 20297 } else { 20298 qnum = soc_apache_logical_qnum_hw_qnum(unit, port, 20299 si->port_uc_cosq_base[port], 1); 20300 } 20301 soc_reg64_field32_set(unit, ING_COS_MODE_64r, 20302 &rval64, BASE_QUEUE_NUM_0f, qnum); 20303 soc_reg64_field32_set(unit, ING_COS_MODE_64r, 20304 &rval64, BASE_QUEUE_NUM_1f, qnum); 20305 BCM_IF_ERROR_RETURN(soc_reg_set(unit, ING_COS_MODE_64r, port, 0, rval64)); 20306 } else { 20307 if(!IS_AP_HSP_PORT(unit, port)) { 20308 _bcm_ap_node_index_clear(&res->l2_queue_list, 20309 si->port_uc_cosq_base[port], si->port_num_uc_cosq[port]); 20310 } else { 20311 /* Reset to default Mode 0 */ 20312 SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, 20313 HSP_SCHED_PORT_CONFIGr, port, MC_GROUP_MODEf, 0)); 20314 } 20315 20316 si->port_num_cosq[port] = 0; 20317 si->port_cosq_base[port] = 0; 20318 si->port_num_uc_cosq[port] = 0; 20319 si->port_uc_cosq_base[port] = 0; 20320 20321 COMPILER_64_ZERO(rval64); 20322 mmu_info->port_info[port].resources = &mmu_info->pipe_resources[pipe]; 20323 mmu_info->port_info[port].mc_base = si->port_cosq_base[port]; 20324 mmu_info->port_info[port].mc_limit = si->port_cosq_base[port] + 20325 si->port_num_cosq[port]; 20326 mmu_info->port_info[port].uc_base = si->port_uc_cosq_base[port]; 20327 mmu_info->port_info[port].uc_limit = si->port_uc_cosq_base[port] + 20328 si->port_num_uc_cosq[port]; 20329 soc_reg64_field32_set(unit, ING_COS_MODE_64r, 20330 &rval64, BASE_QUEUE_NUM_0f, 0); 20331 soc_reg64_field32_set(unit, ING_COS_MODE_64r, 20332 &rval64, BASE_QUEUE_NUM_1f, 0); 20333 BCM_IF_ERROR_RETURN(soc_reg_set(unit, ING_COS_MODE_64r, port, 0, rval64)); 20334 } 20335 20336 BCM_IF_ERROR_RETURN(bcm_ap_port_cosq_config_set(unit, port, enable)); 20337 return BCM_E_NONE; 20338 20339 } 20340 20341 int 20342 _bcm_ap_cosq_gport_dump_subtree( int unit, bcm_gport_t gport) 20343 { 20344 _bcm_ap_cosq_node_t *node; 20345 int num_spri = 0, first_child = 0, first_mc_child; 20346 uint32 ucmap, spmap; 20347 soc_apache_sched_mode_e sched_mode; 20348 int wt = 0; 20349 char *lvl_name[] = { "Root", "S1", "L0", "L1", "L2" }; 20350 char *sched_modes[] = {"X", "SP", "WRR", "WDRR"}; 20351 20352 20353 BCM_IF_ERROR_RETURN 20354 (_bcm_ap_cosq_node_get(unit, gport, 0, NULL, NULL, NULL, &node)); 20355 20356 if (( node->level != SOC_APACHE_NODE_LVL_ROOT) && 20357 (node->level != SOC_APACHE_NODE_LVL_L2)) { 20358 BCM_IF_ERROR_RETURN( 20359 soc_apache_cosq_get_sched_child_config(unit, node->local_port, 20360 node->level, 20361 node->hw_index, 20362 &num_spri, &first_child, 20363 &first_mc_child, &ucmap, &spmap)); 20364 } 20365 sched_mode = 0; 20366 if (node->level != SOC_APACHE_NODE_LVL_ROOT) { 20367 SOC_IF_ERROR_RETURN( 20368 soc_apache_cosq_get_sched_mode(unit, node->local_port, node->level, 20369 node->hw_index, &sched_mode, &wt)); 20370 } 20371 if (node->level == SOC_APACHE_NODE_LVL_ROOT) { 20372 if (soc_feature(unit, soc_feature_mmu_hqos_four_level)) 20373 { 20374 LOG_CLI((BSL_META_U(unit, 20375 " %s.%d : INDEX=%d NUM_SPRI=0 FC=0 MODE=X Wt=0\n"), 20376 lvl_name[node->level], 20377 node->attached_to_input, 20378 _soc_apache_root_scheduler_index(unit, node->local_port))); 20379 } 20380 } else if (node->level == SOC_APACHE_NODE_LVL_S1) { 20381 if (soc_feature(unit, soc_feature_mmu_hqos_four_level)) 20382 { 20383 LOG_CLI((BSL_META_U(unit, 20384 " %s.%d : INDEX=%d NUM_SPRI=%d FC=%d MODE=%s Wt=%d\n"), 20385 lvl_name[node->level], 20386 node->attached_to_input, 20387 node->hw_index, 20388 num_spri, first_child, 20389 sched_modes[sched_mode], 20390 wt)); 20391 } else 20392 { 20393 LOG_CLI((BSL_META_U(unit, 20394 " %s.%d : INDEX=%d NUM_SPRI=%d FC=%d MODE=%s Wt=%d\n"), 20395 lvl_name[node->level - 1], 20396 node->attached_to_input, 20397 node->hw_index, 20398 num_spri, first_child, 20399 sched_modes[sched_mode], 20400 wt)); 20401 } 20402 20403 } else if (node->level == SOC_APACHE_NODE_LVL_L0) { 20404 LOG_CLI((BSL_META_U(unit, 20405 " %s.%d : INDEX=%d NUM_SPRI=%d FC=%d MODE=%s Wt=%d\n"), 20406 lvl_name[node->level], 20407 node->attached_to_input, 20408 node->hw_index, 20409 num_spri, first_child, 20410 sched_modes[sched_mode], 20411 wt)); 20412 20413 } else if (node->level == SOC_APACHE_NODE_LVL_L1) { 20414 LOG_CLI((BSL_META_U(unit, 20415 " %s.%d : INDEX=%d NUM_SP=%d FC=%d " 20416 "FMC=%d UCMAP=0x%08x MODE=%s WT=%d\n"), 20417 lvl_name[node->level], 20418 node->attached_to_input, 20419 node->hw_index, 20420 num_spri, 20421 first_child, 20422 first_mc_child, 20423 ucmap, 20424 sched_modes[sched_mode], 20425 wt)); 20426 } else { 20427 LOG_CLI((BSL_META_U(unit, 20428 " %s.%s : INDEX=%d MODE=%s Wt=%d\n"), 20429 lvl_name[node->level], 20430 node->hw_index < 16384 ? "uc" : "mc", 20431 node->hw_index, 20432 sched_modes[sched_mode], 20433 wt)); 20434 } 20435 20436 if (node->child != NULL) { 20437 _bcm_ap_cosq_gport_dump_subtree(unit, node->child->gport); 20438 } 20439 20440 20441 if (node->sibling != NULL) { 20442 _bcm_ap_cosq_gport_dump_subtree(unit, node->sibling->gport); 20443 } 20444 20445 return SOC_E_NONE; 20446 } 20447 20448 int 20449 bcm_apache_dump_port_lls_sw( int unit, int port) 20450 { 20451 _bcm_ap_mmu_info_t *mmu_info; 20452 _bcm_ap_cosq_node_t *port_info; 20453 20454 if (_soc_apache_port_sched_type_get(unit, port) == SOC_APACHE_SCHED_HSP) { 20455 return SOC_E_NONE; 20456 } 20457 LOG_CLI((BSL_META_U(unit, 20458 "-------%s (LLS)------\n"), SOC_PORT_NAME(unit, (port)))); 20459 20460 mmu_info = _bcm_ap_mmu_info[unit]; 20461 20462 /* root node */ 20463 port_info = &mmu_info->sched_node[port]; 20464 20465 if (port_info->gport >= 0) { 20466 _bcm_ap_cosq_gport_dump_subtree(unit, port_info->gport); 20467 } 20468 return SOC_E_NONE; 20469 } 20470 20471 /* 20472 * Function: 20473 * bcm_ap_cosq_service_classifier_id_create 20474 * Purpose: 20475 * Create an endpoint. 20476 * Parameters: 20477 * unit - (IN) Unit number. 20478 * classifier - (IN) Classifier attributes 20479 * classifier_id - (OUT) Classifier ID 20480 * Returns: 20481 * BCM_E_xxx 20482 */ 20483 int 20484 bcm_ap_cosq_service_classifier_id_create( 20485 int unit, 20486 bcm_cosq_classifier_t *classifier, 20487 int *classifier_id) 20488 { 20489 if (NULL == classifier || NULL == classifier_id) { 20490 return BCM_E_PARAM; 20491 } 20492 20493 _BCM_COSQ_CLASSIFIER_SERVICE_SET(*classifier_id, classifier->vlan); 20494 return BCM_E_NONE; 20495 } 20496 20497 /* 20498 * Function: 20499 * bcm_ap_cosq_service_classifier_id_destroy 20500 * Purpose: 20501 * free resource associated with this service classifier id. 20502 * Parameters: 20503 * unit - (IN) Unit number. 20504 * classifier_id - (IN) Classifier ID 20505 * Returns: 20506 * BCM_E_xxx 20507 */ 20508 int 20509 bcm_ap_cosq_service_classifier_id_destroy( 20510 int unit, 20511 int classifier_id) 20512 { 20513 return BCM_E_NONE; 20514 } 20515 20516 /* 20517 * Function: 20518 * bcm_ap_cosq_service_classifier_get 20519 * Purpose: 20520 * Get info about an endpoint. 20521 * Parameters: 20522 * unit - (IN) Unit number. 20523 * classifier_id - (IN) Classifier ID 20524 * classifier - (OUT) Classifier info 20525 * Returns: 20526 * BCM_E_xxx 20527 */ 20528 int 20529 bcm_ap_cosq_service_classifier_get( 20530 int unit, 20531 int classifier_id, 20532 bcm_cosq_classifier_t *classifier) 20533 { 20534 int val = 0; 20535 20536 sal_memset(classifier, 0, sizeof(bcm_cosq_classifier_t)); 20537 20538 val = _BCM_COSQ_CLASSIFIER_SERVICE_GET(classifier_id); 20539 20540 if (val > BCM_VLAN_MAX) { 20541 /* VFI classifier */ 20542 classifier->flags = BCM_COSQ_CLASSIFIER_VFI; 20543 classifier->vfi_index = val - BCM_VLAN_MAX - 1; 20544 } else { 20545 classifier->flags = BCM_COSQ_CLASSIFIER_VLAN; 20546 classifier->vlan = val; 20547 } 20548 return BCM_E_NONE; 20549 } 20550 20551 /* 20552 * Function: 20553 * bcm_ap_cosq_service_map_set 20554 * Purpose: 20555 * Set the mapping from port, classifier, and multiple internal priorities 20556 * to multiple COS queues in a queue group. 20557 * Parameters: 20558 * unit - (IN) Unit number. 20559 * port - (IN) local port ID 20560 * classifier_id - (IN) Classifier ID 20561 * queue_group - (IN) Base queue ID 20562 * array_count - (IN) Number of elements in priority_array and 20563 * cosq_array 20564 * priority_array - (IN) Array of internal priorities 20565 * cosq_array - (IN) Array of COS queues 20566 * Returns: 20567 * BCM_E_xxx 20568 */ 20569 int 20570 bcm_ap_cosq_service_map_set( 20571 int unit, 20572 bcm_port_t port, 20573 int classifier_id, 20574 bcm_gport_t queue_group, 20575 int array_count, 20576 bcm_cos_t *priority_array, 20577 bcm_cos_queue_t *cosq_array) 20578 { 20579 service_queue_map_entry_t sqm; 20580 service_port_map_entry_t *spm = NULL; 20581 service_cos_map_entry_t *scm = NULL; 20582 void *spm_entries[1]; 20583 void *scm_entries[1]; 20584 int rv = BCM_E_NONE; 20585 int i, numq, alloc_size, exists = 0; 20586 int local_port, vid, qid, cos_offset = 0; 20587 int port_offset, port_offset_old; 20588 int qptr_old, qptr_new; 20589 uint32 scm_idx, scm_idx_old = 0, spm_idx, spm_idx_old = 0; 20590 _bcm_ap_cosq_node_t *node; 20591 soc_profile_mem_t *spm_profile_mem, *scm_profile_mem; 20592 /* 20593 * The port_offset= 0 is treated as the invalid offset so that 20594 * the ports without being service map set can be recognized easily by software. 20595 * Accordingly, The valid port_offset needs to be at least 1 for a given port. 20596 * the queue base to be written into SERVICE_QUEUE_PTRf will 20597 * be (the actual base - 1). 20598 */ 20599 #define VALID_PORT_OFFSET_MIN 1 20600 20601 if (!_BCM_COSQ_CLASSIFIER_IS_SERVICE(classifier_id)) { 20602 return BCM_E_PARAM; 20603 } 20604 20605 /* index above 4K is for VFI */ 20606 vid = _BCM_COSQ_CLASSIFIER_SERVICE_GET(classifier_id); 20607 if (vid < 0 || vid >= SOC_MEM_SIZE(unit, SERVICE_QUEUE_MAPm)) { 20608 return BCM_E_PARAM; 20609 } 20610 20611 if (array_count > _AP_SCM_ENTRIES_PER_SET) { 20612 return BCM_E_PARAM; 20613 } 20614 scm_profile_mem = _bcm_ap_service_cos_map_profile[unit]; 20615 spm_profile_mem = _bcm_ap_service_port_map_profile[unit]; 20616 20617 BCM_IF_ERROR_RETURN( 20618 _bcm_ap_cosq_node_get(unit, queue_group, 0, NULL, 20619 &local_port, &qid, &node)); 20620 if (node->attached_to_input < 0) { 20621 return BCM_E_PARAM; 20622 } 20623 numq = node->parent->numq; 20624 qid = node->hw_index; 20625 20626 for (i = 0; i < array_count; i++) { 20627 if (cosq_array[i] >= numq) { 20628 return BCM_E_PARAM; 20629 } 20630 } 20631 20632 sal_memset(&sqm, 0, sizeof(service_queue_map_entry_t)); 20633 SOC_IF_ERROR_RETURN( 20634 soc_mem_read(unit, SERVICE_QUEUE_MAPm, MEM_BLOCK_ANY, (int)vid, &sqm)); 20635 20636 if (soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, &sqm, VALIDf)) { 20637 exists = 1; 20638 } else { 20639 exists = 0; 20640 } 20641 20642 alloc_size = sizeof(service_port_map_entry_t) * _AP_SPM_ENTRIES_PER_SET; 20643 spm = sal_alloc(alloc_size, "SERVICE_PORT_MAP temp Mem"); 20644 if (spm == NULL) { 20645 rv = BCM_E_MEMORY; 20646 goto cleanup; 20647 } 20648 sal_memset(spm, 0, alloc_size); 20649 spm_entries[0] = spm; 20650 20651 alloc_size = sizeof(service_cos_map_entry_t) * _AP_SCM_ENTRIES_PER_SET; 20652 scm = sal_alloc(alloc_size, "SERVICE_COS_MAP temp Mem"); 20653 if (scm == NULL) { 20654 rv = BCM_E_MEMORY; 20655 goto cleanup; 20656 } 20657 sal_memset(scm, 0, alloc_size); 20658 scm_entries[0] = scm; 20659 20660 /* 1. program the SERVICE_COS_MAPm. */ 20661 if (!exists) { 20662 for (i = 0; i < array_count; i++) { 20663 if (priority_array[i] < _AP_SCM_ENTRIES_PER_SET) { 20664 soc_mem_field32_set(unit, SERVICE_COS_MAPm, 20665 &scm[priority_array[i]], 20666 SERVICE_COS_OFFSETf, cosq_array[i]); 20667 } 20668 } 20669 20670 rv = soc_profile_mem_add(unit, scm_profile_mem, scm_entries, 20671 _AP_SCM_ENTRIES_PER_SET, &scm_idx); 20672 if (rv != SOC_E_NONE) { 20673 goto cleanup; 20674 } 20675 } else { 20676 /* 20677 * only one service_cos_map profile is allowed per vlan/vfi. 20678 * If the subsequent profile doesn't match the existing one, 20679 * Then update the old profile, the new map may be added by other port. 20680 */ 20681 scm_idx_old = _AP_SCM_ENTRIES_PER_SET * 20682 soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, &sqm, 20683 SERVICE_COS_PROFILE_INDEXf); 20684 rv = soc_profile_mem_get(unit, scm_profile_mem, scm_idx_old, 20685 _AP_SCM_ENTRIES_PER_SET, scm_entries); 20686 if (rv != SOC_E_NONE) { 20687 goto cleanup; 20688 } 20689 20690 for (i = 0; i < array_count; i++) { 20691 cos_offset = soc_mem_field32_get(unit, SERVICE_COS_MAPm, 20692 &scm[priority_array[i]], 20693 SERVICE_COS_OFFSETf); 20694 if (cosq_array[i] != cos_offset) { 20695 if (priority_array[i] < _AP_SCM_ENTRIES_PER_SET) { 20696 soc_mem_field32_set(unit, SERVICE_COS_MAPm, 20697 &scm[priority_array[i]], 20698 SERVICE_COS_OFFSETf, cosq_array[i]); 20699 } 20700 } 20701 } 20702 20703 rv = soc_profile_mem_add(unit, scm_profile_mem, scm_entries, 20704 _AP_SCM_ENTRIES_PER_SET, &scm_idx); 20705 if (rv != SOC_E_NONE) { 20706 goto cleanup; 20707 } 20708 20709 if (scm_idx_old != scm_idx) { 20710 rv = soc_profile_mem_delete(unit, scm_profile_mem, scm_idx_old); 20711 if (rv != SOC_E_NONE) { 20712 goto cleanup; 20713 } 20714 } 20715 } 20716 20717 /* 2. program the SERVICE_PORT_MAPm. */ 20718 if (!exists) { 20719 port_offset = VALID_PORT_OFFSET_MIN; 20720 soc_mem_field32_set(unit, SERVICE_PORT_MAPm, &spm[local_port], 20721 SERVICE_PORT_OFFSETf, port_offset); 20722 } else { 20723 spm_idx_old = _AP_SPM_ENTRIES_PER_SET * 20724 soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, &sqm, 20725 SERVICE_PORT_PROFILE_INDEXf); 20726 rv = soc_profile_mem_get(unit, spm_profile_mem, spm_idx_old, 20727 _AP_SPM_ENTRIES_PER_SET, spm_entries); 20728 if (!(rv == SOC_E_NOT_FOUND || rv == SOC_E_NONE)) { 20729 goto cleanup; 20730 } 20731 20732 qptr_old = soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, 20733 &sqm, SERVICE_QUEUE_PTRf); 20734 if (qid <= qptr_old) { 20735 qptr_new = qid - VALID_PORT_OFFSET_MIN; 20736 for (i = 0; i < _AP_SPM_ENTRIES_PER_SET; i++) { 20737 port_offset_old = soc_mem_field32_get(unit, SERVICE_PORT_MAPm, 20738 &spm[i], 20739 SERVICE_PORT_OFFSETf); 20740 if (i == local_port) { 20741 port_offset = VALID_PORT_OFFSET_MIN; 20742 } else if (!port_offset_old) { 20743 /* 20744 * For the old port_offsets with 0, 20745 * the new port_offsest are still 0. 20746 */ 20747 continue; 20748 } else { 20749 port_offset = qptr_old + port_offset_old - qptr_new; 20750 } 20751 soc_mem_field32_set(unit, SERVICE_PORT_MAPm, &spm[i], 20752 SERVICE_PORT_OFFSETf, port_offset); 20753 } 20754 } else { 20755 port_offset = qid - qptr_old; 20756 soc_mem_field32_set(unit, SERVICE_PORT_MAPm, &spm[local_port], 20757 SERVICE_PORT_OFFSETf, port_offset); 20758 } 20759 } 20760 rv = soc_profile_mem_add(unit, spm_profile_mem, 20761 spm_entries, _AP_SPM_ENTRIES_PER_SET, &spm_idx); 20762 if (rv != SOC_E_NONE) { 20763 goto cleanup; 20764 } 20765 20766 /* 3. program the SERVICE_QUEUE_MAPm */ 20767 if (!exists) { 20768 qptr_new = qid - VALID_PORT_OFFSET_MIN; 20769 } else { 20770 qptr_old = soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, 20771 &sqm, SERVICE_QUEUE_PTRf); 20772 if (qid <= qptr_old) { 20773 qptr_new = qid - VALID_PORT_OFFSET_MIN; 20774 } else { 20775 qptr_new = qptr_old; 20776 } 20777 } 20778 20779 soc_mem_field32_set(unit, SERVICE_QUEUE_MAPm, &sqm, 20780 SERVICE_QUEUE_PTRf, qptr_new); 20781 soc_mem_field32_set(unit, SERVICE_QUEUE_MAPm, &sqm, 20782 SERVICE_COS_PROFILE_INDEXf, 20783 scm_idx / _AP_SCM_ENTRIES_PER_SET); 20784 soc_mem_field32_set(unit, SERVICE_QUEUE_MAPm, &sqm, 20785 SERVICE_PORT_PROFILE_INDEXf, 20786 spm_idx / _AP_SPM_ENTRIES_PER_SET); 20787 /* use port indexed and cos indexed for this base queue */ 20788 soc_mem_field32_set(unit, SERVICE_QUEUE_MAPm, &sqm, 20789 SERVICE_QUEUE_MODELf, 3); 20790 soc_mem_field32_set(unit, SERVICE_QUEUE_MAPm, &sqm, VALIDf, 1); 20791 20792 rv = soc_mem_write(unit, SERVICE_QUEUE_MAPm, MEM_BLOCK_ALL, (int)vid, &sqm); 20793 20794 if (exists) { 20795 if (spm_idx_old != spm_idx) { 20796 rv = soc_profile_mem_delete(unit, spm_profile_mem, spm_idx_old); 20797 } 20798 } 20799 20800 cleanup: 20801 if (spm != NULL) { 20802 sal_free(spm); 20803 } 20804 if (scm != NULL) { 20805 sal_free(scm); 20806 } 20807 return rv; 20808 } 20809 20810 /* 20811 * Function: 20812 * bcm_ap_cosq_service_map_get 20813 * Purpose: 20814 * Get the mapping from port, classifier, and multiple internal priorities 20815 * to multiple COS queues in a queue group. 20816 * Parameters: 20817 * unit - (IN) Unit number. 20818 * port - (IN) Local port ID 20819 * classifier_id - (IN) Classifier ID 20820 * queue_group - (OUT) Queue group 20821 * array_max - (IN) Size of priority_array and cosq_array 20822 * priority_array - (IN) Array of internal priorities 20823 * cosq_array - (OUT) Array of COS queues 20824 * array_count - (OUT) Size of cosq_array 20825 * Returns: 20826 * BCM_E_xxx 20827 */ 20828 int 20829 bcm_ap_cosq_service_map_get( 20830 int unit, 20831 bcm_port_t port, 20832 int classifier_id, 20833 bcm_gport_t *queue_group, 20834 int array_max, 20835 bcm_cos_t *priority_array, 20836 bcm_cos_queue_t *cosq_array, 20837 int *array_count) 20838 { 20839 int alloc_size, port_offset, i, vid, qptr; 20840 int spm_index, scm_index; 20841 int rv = BCM_E_NONE; 20842 void *spm_entries[1]; 20843 void *scm_entries[1]; 20844 service_queue_map_entry_t sqm; 20845 service_port_map_entry_t *spm; 20846 service_cos_map_entry_t *scm; 20847 soc_profile_mem_t *spm_profile_mem, *scm_profile_mem; 20848 20849 if (priority_array == NULL || cosq_array == NULL || 20850 array_count == NULL || queue_group == NULL) { 20851 return BCM_E_PARAM; 20852 } 20853 20854 if (!_BCM_COSQ_CLASSIFIER_IS_SERVICE(classifier_id)) { 20855 return BCM_E_PARAM; 20856 } 20857 20858 /* index above 4K is for VFI */ 20859 vid = _BCM_COSQ_CLASSIFIER_SERVICE_GET(classifier_id); 20860 if (vid < 0 || vid >= SOC_MEM_SIZE(unit, SERVICE_QUEUE_MAPm)) { 20861 return BCM_E_PARAM; 20862 } 20863 20864 scm_profile_mem = _bcm_ap_service_cos_map_profile[unit]; 20865 spm_profile_mem = _bcm_ap_service_port_map_profile[unit]; 20866 20867 SOC_IF_ERROR_RETURN( 20868 soc_mem_read(unit, SERVICE_QUEUE_MAPm, MEM_BLOCK_ANY, (int)vid, &sqm)); 20869 20870 if (!soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, &sqm, VALIDf)) { 20871 return BCM_E_CONFIG; 20872 } 20873 20874 qptr = soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, 20875 &sqm, SERVICE_QUEUE_PTRf); 20876 spm_index = _AP_SPM_ENTRIES_PER_SET * 20877 soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, &sqm, 20878 SERVICE_PORT_PROFILE_INDEXf); 20879 scm_index = _AP_SCM_ENTRIES_PER_SET * 20880 soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, &sqm, 20881 SERVICE_COS_PROFILE_INDEXf); 20882 20883 alloc_size = sizeof(service_port_map_entry_t) * _AP_SPM_ENTRIES_PER_SET; 20884 spm = sal_alloc(alloc_size, "SERVICE_PORT_MAP temp Mem"); 20885 if (spm == NULL) { 20886 return BCM_E_MEMORY; 20887 } 20888 sal_memset(spm, 0, alloc_size); 20889 spm_entries[0] = spm; 20890 20891 alloc_size = sizeof(service_cos_map_entry_t) * _AP_SCM_ENTRIES_PER_SET; 20892 scm = sal_alloc(alloc_size, "SERVICE_COS_MAP temp Mem"); 20893 if (scm == NULL) { 20894 goto cleaup; 20895 } 20896 sal_memset(scm, 0, alloc_size); 20897 scm_entries[0] = scm; 20898 20899 rv = soc_profile_mem_get(unit, spm_profile_mem, 20900 spm_index, _AP_SPM_ENTRIES_PER_SET, spm_entries); 20901 if (!(rv == SOC_E_NOT_FOUND || rv == SOC_E_NONE)) { 20902 goto cleaup; 20903 } 20904 20905 rv = soc_profile_mem_get(unit, scm_profile_mem, 20906 scm_index, _AP_SCM_ENTRIES_PER_SET, scm_entries); 20907 if (!(rv == SOC_E_NOT_FOUND || rv == SOC_E_NONE)) { 20908 goto cleaup; 20909 } 20910 20911 port_offset = soc_mem_field32_get(unit, SERVICE_PORT_MAPm, 20912 &spm[port], SERVICE_PORT_OFFSETf); 20913 if (port_offset == 0) { 20914 rv = BCM_E_NOT_FOUND; 20915 goto cleaup; 20916 } 20917 BCM_GPORT_UCAST_QUEUE_GROUP_SYSQID_SET(*queue_group, port, 20918 (port_offset + qptr)); 20919 20920 *array_count = array_max > _AP_SCM_ENTRIES_PER_SET ? 20921 _AP_SCM_ENTRIES_PER_SET : array_max; 20922 for (i = 0; i < *array_count; i++) { 20923 if (priority_array[i] >= _AP_SCM_ENTRIES_PER_SET) { 20924 rv = BCM_E_PARAM; 20925 goto cleaup; 20926 } 20927 cosq_array[i] = soc_mem_field32_get(unit, SERVICE_COS_MAPm, 20928 &scm[priority_array[i]], 20929 SERVICE_COS_OFFSETf); 20930 } 20931 20932 cleaup: 20933 if (spm != NULL) { 20934 sal_free(spm); 20935 } 20936 if (scm != NULL) { 20937 sal_free(scm); 20938 } 20939 return rv; 20940 } 20941 20942 /* 20943 * Function: 20944 * bcm_ap_cosq_service_map_clear 20945 * Purpose: 20946 * Clear the mapping from port, classifier, and internal priorities 20947 * to COS queues in a queue group. 20948 * Parameters: 20949 * unit - (IN) Unit number. 20950 * port - (IN) Local port ID 20951 * classifier_id - (IN) Classifier ID 20952 * Returns: 20953 * BCM_E_xxx 20954 */ 20955 int 20956 bcm_ap_cosq_service_map_clear( 20957 int unit, 20958 bcm_gport_t port, 20959 int classifier_id) 20960 { 20961 int i, alloc_size, vid, classifier_in_use; 20962 int rv = BCM_E_NONE; 20963 int scm_index; 20964 uint32 spm_index, spm_index_new; 20965 void *spm_entries[1]; 20966 service_port_map_entry_t *spm; 20967 service_queue_map_entry_t sqm; 20968 soc_profile_mem_t *spm_profile_mem, *scm_profile_mem; 20969 20970 if (!_BCM_COSQ_CLASSIFIER_IS_SERVICE(classifier_id)) { 20971 return BCM_E_PARAM; 20972 } 20973 20974 /* index above 4K is for VFI */ 20975 vid = _BCM_COSQ_CLASSIFIER_SERVICE_GET(classifier_id); 20976 if (vid < 0 || vid >= SOC_MEM_SIZE(unit, SERVICE_QUEUE_MAPm)) { 20977 return BCM_E_PARAM; 20978 } 20979 20980 scm_profile_mem = _bcm_ap_service_cos_map_profile[unit]; 20981 spm_profile_mem = _bcm_ap_service_port_map_profile[unit]; 20982 20983 SOC_IF_ERROR_RETURN( 20984 soc_mem_read(unit, SERVICE_QUEUE_MAPm, MEM_BLOCK_ANY, (int)vid, &sqm)); 20985 20986 if (!soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, &sqm, VALIDf)) { 20987 return BCM_E_NONE; 20988 } 20989 20990 /* 1. program the SERVICE_PORT_MAPm. */ 20991 alloc_size = sizeof(service_port_map_entry_t) * _AP_SPM_ENTRIES_PER_SET; 20992 spm = sal_alloc(alloc_size, "SERVICE_PORT_MAP temp Mem"); 20993 if (spm == NULL) { 20994 return BCM_E_MEMORY; 20995 } 20996 sal_memset(spm, 0, alloc_size); 20997 spm_entries[0] = spm; 20998 20999 spm_index = _AP_SPM_ENTRIES_PER_SET * 21000 soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, &sqm, 21001 SERVICE_PORT_PROFILE_INDEXf); 21002 rv = soc_profile_mem_get(unit, spm_profile_mem, 21003 spm_index, _AP_SPM_ENTRIES_PER_SET, spm_entries); 21004 if (!(rv == SOC_E_NOT_FOUND || rv == SOC_E_NONE)) { 21005 goto cleanup; 21006 } 21007 21008 soc_mem_field32_set(unit, SERVICE_PORT_MAPm, 21009 &spm[port], SERVICE_PORT_OFFSETf, 0); 21010 classifier_in_use = 0; 21011 for (i = 0; i < _AP_SPM_ENTRIES_PER_SET; i++) { 21012 if (soc_mem_field32_get(unit, SERVICE_PORT_MAPm, 21013 &spm[i], SERVICE_PORT_OFFSETf)) { 21014 classifier_in_use = 1; 21015 break; 21016 } 21017 } 21018 21019 rv = soc_profile_mem_delete(unit, spm_profile_mem, spm_index); 21020 if (rv != SOC_E_NONE) { 21021 goto cleanup; 21022 } 21023 21024 if (classifier_in_use) { 21025 rv = soc_profile_mem_add(unit, spm_profile_mem, 21026 spm_entries, _AP_SPM_ENTRIES_PER_SET, 21027 &spm_index_new); 21028 if (rv != SOC_E_NONE) { 21029 goto cleanup; 21030 } 21031 } 21032 21033 /* 2. program the SERVICE_COS_MAPm. */ 21034 if (!classifier_in_use) { 21035 scm_index = _AP_SCM_ENTRIES_PER_SET * 21036 soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, &sqm, 21037 SERVICE_COS_PROFILE_INDEXf); 21038 rv = soc_profile_mem_delete(unit, scm_profile_mem, scm_index); 21039 if (rv != SOC_E_NONE) { 21040 goto cleanup; 21041 } 21042 } 21043 21044 /* 3. program the SERVICE_QUEUE_MAPm. */ 21045 if (classifier_in_use) { 21046 soc_mem_field32_set(unit, SERVICE_QUEUE_MAPm, &sqm, 21047 SERVICE_PORT_PROFILE_INDEXf, 21048 spm_index_new / _AP_SPM_ENTRIES_PER_SET); 21049 } else { 21050 sal_memset(&sqm,0, sizeof(service_queue_map_entry_t)); 21051 } 21052 21053 rv = soc_mem_write(unit, SERVICE_QUEUE_MAPm, MEM_BLOCK_ALL, 21054 (int)vid, &sqm); 21055 21056 cleanup: 21057 if (spm != NULL) { 21058 sal_free(spm); 21059 } 21060 return rv; 21061 } 21062 /******************************************************************/ 21063 /* OBM CLASSIFIER START */ 21064 /******************************************************************/ 21065 21066 /* 21067 * Function: 21068 * bcm_apache_switch_obm_dscp_classifier_mapping_multi_set 21069 * Purpose: 21070 * Set the mapping of bcm_obm_code_point to bcm_obm_priority 21071 * for multiple entries of dscp classifier type. 21072 * Parameters: 21073 * unit - (IN) Unit number. 21074 * phy_port - (IN) Physical port. 21075 * pgw - (IN) PGW index (0 0r 1). 21076 * array_count - (IN) Number of dscp entries. 21077 * switch_obm_classifier - (IN) Array of dscp entries. 21078 * Returns: 21079 * BCM_E_xxx 21080 */ 21081 21082 STATIC 21083 int bcm_apache_switch_obm_dscp_classifier_mapping_multi_set( 21084 int unit, 21085 int phy_port, 21086 int pgw, 21087 int array_count, 21088 bcm_switch_obm_classifier_t *switch_obm_classifier) 21089 { 21090 int i, code_point, ob_priority; 21091 int entry_index[4]; 21092 idb_obm0_dscp_map_port0_entry_t entry[4]; 21093 bcm_switch_obm_classifier_t *classifier_ptr = NULL; 21094 soc_mem_t mem; 21095 21096 static const soc_mem_t obm_dscp_map_port_mem[] = { 21097 IDB_OBM0_DSCP_MAP_PORT0m, IDB_OBM0_DSCP_MAP_PORT1m, 21098 IDB_OBM0_DSCP_MAP_PORT2m, IDB_OBM0_DSCP_MAP_PORT3m, 21099 IDB_OBM1_DSCP_MAP_PORT0m, IDB_OBM1_DSCP_MAP_PORT1m, 21100 IDB_OBM1_DSCP_MAP_PORT2m, IDB_OBM1_DSCP_MAP_PORT3m, 21101 IDB_OBM2_DSCP_MAP_PORT0m, IDB_OBM2_DSCP_MAP_PORT1m, 21102 IDB_OBM2_DSCP_MAP_PORT2m, IDB_OBM2_DSCP_MAP_PORT3m, 21103 IDB_OBM3_DSCP_MAP_PORT0m, IDB_OBM3_DSCP_MAP_PORT1m, 21104 IDB_OBM3_DSCP_MAP_PORT2m, IDB_OBM3_DSCP_MAP_PORT3m, 21105 IDB_OBM4_DSCP_MAP_PORT0m, IDB_OBM4_DSCP_MAP_PORT1m, 21106 IDB_OBM4_DSCP_MAP_PORT2m, IDB_OBM4_DSCP_MAP_PORT3m, 21107 IDB_OBM5_DSCP_MAP_PORT0m, IDB_OBM5_DSCP_MAP_PORT1m, 21108 IDB_OBM5_DSCP_MAP_PORT2m, IDB_OBM5_DSCP_MAP_PORT3m, 21109 IDB_OBM6_DSCP_MAP_PORT0m, IDB_OBM6_DSCP_MAP_PORT1m, 21110 IDB_OBM6_DSCP_MAP_PORT2m, IDB_OBM6_DSCP_MAP_PORT3m, 21111 IDB_OBM7_DSCP_MAP_PORT0m, IDB_OBM7_DSCP_MAP_PORT1m, 21112 IDB_OBM7_DSCP_MAP_PORT2m, IDB_OBM7_DSCP_MAP_PORT3m, 21113 IDB_OBM8_DSCP_MAP_PORT0m, IDB_OBM8_DSCP_MAP_PORT1m, 21114 IDB_OBM8_DSCP_MAP_PORT2m, IDB_OBM8_DSCP_MAP_PORT3m 21115 }; 21116 static const soc_field_t offset_ob_prio[] = { 21117 OFFSET0_OB_PRIORITYf, OFFSET1_OB_PRIORITYf, OFFSET2_OB_PRIORITYf, 21118 OFFSET3_OB_PRIORITYf, OFFSET4_OB_PRIORITYf, OFFSET5_OB_PRIORITYf, 21119 OFFSET6_OB_PRIORITYf, OFFSET7_OB_PRIORITYf, OFFSET8_OB_PRIORITYf, 21120 OFFSET9_OB_PRIORITYf, OFFSET10_OB_PRIORITYf, OFFSET11_OB_PRIORITYf, 21121 OFFSET12_OB_PRIORITYf, OFFSET13_OB_PRIORITYf, OFFSET14_OB_PRIORITYf, 21122 OFFSET15_OB_PRIORITYf 21123 }; 21124 21125 mem = obm_dscp_map_port_mem[(phy_port - 1) % _AP_PORTS_PER_PGW]; 21126 for (i = 0; i < 4; i++) { 21127 entry_index[i] = 0; 21128 sal_memset(&entry[i], 0, sizeof(entry[i])); 21129 SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, 21130 PGW_CL_BLOCK(unit, pgw), i, &entry[i])); 21131 } 21132 21133 for (i = 0; i < array_count; i++) { 21134 classifier_ptr = switch_obm_classifier + i; 21135 code_point = classifier_ptr->obm_code_point; 21136 ob_priority = classifier_ptr->obm_priority; 21137 if (code_point < BCM_OBM_DSCP_CHUNK_SIZE) { 21138 soc_mem_field32_set(unit, mem, &entry[0], 21139 offset_ob_prio[code_point], ob_priority); 21140 entry_index[0] = 1; 21141 } else if (code_point < 2 * BCM_OBM_DSCP_CHUNK_SIZE ) { 21142 soc_mem_field32_set(unit, mem, &entry[1], 21143 offset_ob_prio[code_point % BCM_OBM_DSCP_CHUNK_SIZE], 21144 ob_priority); 21145 entry_index[1] = 1; 21146 } else if (code_point < 3 * BCM_OBM_DSCP_CHUNK_SIZE) { 21147 soc_mem_field32_set(unit, mem, &entry[2], 21148 offset_ob_prio[code_point % BCM_OBM_DSCP_CHUNK_SIZE], 21149 ob_priority); 21150 entry_index[2] = 1; 21151 } else { 21152 soc_mem_field32_set(unit, mem, &entry[3], 21153 offset_ob_prio[code_point % BCM_OBM_DSCP_CHUNK_SIZE], 21154 ob_priority); 21155 entry_index[3] = 1; 21156 } 21157 } 21158 for (i = 0; i < 4; i++) { 21159 if (entry_index[i]) { 21160 SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem, PGW_CL_BLOCK(unit, pgw), 21161 i, &entry[i])); 21162 } 21163 } 21164 return BCM_E_NONE; 21165 } 21166 /* 21167 * Function: 21168 * bcm_apache_switch_obm_dscp_classifier_mapping_multi_get 21169 * Purpose: 21170 * Set the mapping of bcm_obm_code_point to bcm_obm_priority 21171 * for multiple entries of dscp classifier type. 21172 * Parameters: 21173 * unit - (IN) Unit number. 21174 * phy_port - (IN) Physical port. 21175 * pgw - (IN) PGW index (0 0r 1). 21176 * array_max - (IN) Maximum number of entries. 21177 * switch_obm_classifier - (IN/OUT) Array of dscp entries. 21178 * array_count - (OUT) Number of dscp entries. 21179 * Returns: 21180 * BCM_E_xxx 21181 */ 21182 STATIC 21183 int bcm_apache_switch_obm_dscp_classifier_mapping_multi_get( 21184 int unit, 21185 int phy_port, 21186 int pgw, 21187 int array_max, 21188 bcm_switch_obm_classifier_t *switch_obm_classifier, 21189 int *array_count) 21190 { 21191 int i, code_point, ob_priority; 21192 idb_obm0_dscp_map_port0_entry_t entry[4]; 21193 bcm_switch_obm_classifier_t *classifier_ptr = NULL; 21194 soc_mem_t mem; 21195 21196 static const soc_mem_t obm_dscp_map_port_mem[] = { 21197 IDB_OBM0_DSCP_MAP_PORT0m, IDB_OBM0_DSCP_MAP_PORT1m, 21198 IDB_OBM0_DSCP_MAP_PORT2m, IDB_OBM0_DSCP_MAP_PORT3m, 21199 IDB_OBM1_DSCP_MAP_PORT0m, IDB_OBM1_DSCP_MAP_PORT1m, 21200 IDB_OBM1_DSCP_MAP_PORT2m, IDB_OBM1_DSCP_MAP_PORT3m, 21201 IDB_OBM2_DSCP_MAP_PORT0m, IDB_OBM2_DSCP_MAP_PORT1m, 21202 IDB_OBM2_DSCP_MAP_PORT2m, IDB_OBM2_DSCP_MAP_PORT3m, 21203 IDB_OBM3_DSCP_MAP_PORT0m, IDB_OBM3_DSCP_MAP_PORT1m, 21204 IDB_OBM3_DSCP_MAP_PORT2m, IDB_OBM3_DSCP_MAP_PORT3m, 21205 IDB_OBM4_DSCP_MAP_PORT0m, IDB_OBM4_DSCP_MAP_PORT1m, 21206 IDB_OBM4_DSCP_MAP_PORT2m, IDB_OBM4_DSCP_MAP_PORT3m, 21207 IDB_OBM5_DSCP_MAP_PORT0m, IDB_OBM5_DSCP_MAP_PORT1m, 21208 IDB_OBM5_DSCP_MAP_PORT2m, IDB_OBM5_DSCP_MAP_PORT3m, 21209 IDB_OBM6_DSCP_MAP_PORT0m, IDB_OBM6_DSCP_MAP_PORT1m, 21210 IDB_OBM6_DSCP_MAP_PORT2m, IDB_OBM6_DSCP_MAP_PORT3m, 21211 IDB_OBM7_DSCP_MAP_PORT0m, IDB_OBM7_DSCP_MAP_PORT1m, 21212 IDB_OBM7_DSCP_MAP_PORT0m, IDB_OBM7_DSCP_MAP_PORT1m, 21213 IDB_OBM8_DSCP_MAP_PORT2m, IDB_OBM8_DSCP_MAP_PORT3m, 21214 IDB_OBM8_DSCP_MAP_PORT2m, IDB_OBM8_DSCP_MAP_PORT3m 21215 }; 21216 static const soc_field_t offset_ob_prio[] = { 21217 OFFSET0_OB_PRIORITYf, OFFSET1_OB_PRIORITYf, OFFSET2_OB_PRIORITYf, 21218 OFFSET3_OB_PRIORITYf, OFFSET4_OB_PRIORITYf, OFFSET5_OB_PRIORITYf, 21219 OFFSET6_OB_PRIORITYf, OFFSET7_OB_PRIORITYf, OFFSET8_OB_PRIORITYf, 21220 OFFSET9_OB_PRIORITYf, OFFSET10_OB_PRIORITYf, OFFSET11_OB_PRIORITYf, 21221 OFFSET12_OB_PRIORITYf, OFFSET13_OB_PRIORITYf, OFFSET14_OB_PRIORITYf, 21222 OFFSET15_OB_PRIORITYf 21223 }; 21224 21225 mem = obm_dscp_map_port_mem[(phy_port - 1) % _AP_PORTS_PER_PGW]; 21226 for (i = 0; i < 4; i++) { 21227 sal_memset(&entry[i], 0, sizeof(entry[i])); 21228 SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, 21229 PGW_CL_BLOCK(unit, pgw), i, &entry[i])); 21230 } 21231 21232 for (i = 0; i < array_max; i++) { 21233 classifier_ptr = switch_obm_classifier + i; 21234 code_point = classifier_ptr->obm_code_point; 21235 if (code_point < BCM_OBM_DSCP_CHUNK_SIZE) { 21236 ob_priority = soc_mem_field32_get(unit, mem, &entry[0], 21237 offset_ob_prio[code_point]); 21238 } else if (code_point < 2 * BCM_OBM_DSCP_CHUNK_SIZE) { 21239 ob_priority = soc_mem_field32_get(unit, mem, &entry[1], 21240 offset_ob_prio[code_point % BCM_OBM_DSCP_CHUNK_SIZE]); 21241 } else if (code_point < 3 * BCM_OBM_DSCP_CHUNK_SIZE) { 21242 ob_priority = soc_mem_field32_get(unit, mem, &entry[2], 21243 offset_ob_prio[code_point % BCM_OBM_DSCP_CHUNK_SIZE]); 21244 } else { 21245 ob_priority = soc_mem_field32_get(unit, mem, &entry[3], 21246 offset_ob_prio[code_point % BCM_OBM_DSCP_CHUNK_SIZE]); 21247 } 21248 classifier_ptr->obm_priority = ob_priority; 21249 } 21250 return BCM_E_NONE; 21251 21252 } 21253 21254 21255 /* 21256 * Function: 21257 * bcm_apache_switch_obm_etag_classifier_mapping_multi_set 21258 * Purpose: 21259 * Set the mapping of bcm_obm_code_point to bcm_obm_priority 21260 * for multiple entries of etag classifier type. 21261 * Parameters: 21262 * unit - (IN) Unit number. 21263 * phy_port - (IN) Physical port. 21264 * pgw - (IN) PGW index (0 0r 1). 21265 * array_count - (IN) Number of etag entries. 21266 * switch_obm_classifier - (IN) Array of etag entries. 21267 * Returns: 21268 * BCM_E_xxx 21269 */ 21270 21271 STATIC 21272 int bcm_apache_switch_obm_etag_classifier_mapping_multi_set( 21273 int unit, 21274 int phy_port, 21275 int pgw, 21276 int array_count, 21277 bcm_switch_obm_classifier_t *switch_obm_classifier) 21278 { 21279 int i, code_point, ob_priority; 21280 idb_obm0_etag_map_port0_entry_t entry; 21281 bcm_switch_obm_classifier_t *classifier_ptr = NULL; 21282 soc_mem_t mem; 21283 21284 static const soc_mem_t obm_etag_map_port_mem[] = { 21285 IDB_OBM0_ETAG_MAP_PORT0m, IDB_OBM0_ETAG_MAP_PORT1m, 21286 IDB_OBM0_ETAG_MAP_PORT2m, IDB_OBM0_ETAG_MAP_PORT3m, 21287 IDB_OBM1_ETAG_MAP_PORT0m, IDB_OBM1_ETAG_MAP_PORT1m, 21288 IDB_OBM1_ETAG_MAP_PORT2m, IDB_OBM1_ETAG_MAP_PORT3m, 21289 IDB_OBM2_ETAG_MAP_PORT0m, IDB_OBM2_ETAG_MAP_PORT1m, 21290 IDB_OBM2_ETAG_MAP_PORT2m, IDB_OBM2_ETAG_MAP_PORT3m, 21291 IDB_OBM3_ETAG_MAP_PORT0m, IDB_OBM3_ETAG_MAP_PORT1m, 21292 IDB_OBM3_ETAG_MAP_PORT2m, IDB_OBM3_ETAG_MAP_PORT3m, 21293 IDB_OBM4_ETAG_MAP_PORT0m, IDB_OBM4_ETAG_MAP_PORT1m, 21294 IDB_OBM4_ETAG_MAP_PORT2m, IDB_OBM4_ETAG_MAP_PORT3m, 21295 IDB_OBM5_ETAG_MAP_PORT0m, IDB_OBM5_ETAG_MAP_PORT1m, 21296 IDB_OBM5_ETAG_MAP_PORT2m, IDB_OBM5_ETAG_MAP_PORT3m, 21297 IDB_OBM6_ETAG_MAP_PORT0m, IDB_OBM6_ETAG_MAP_PORT1m, 21298 IDB_OBM6_ETAG_MAP_PORT2m, IDB_OBM6_ETAG_MAP_PORT3m, 21299 IDB_OBM7_ETAG_MAP_PORT0m, IDB_OBM7_ETAG_MAP_PORT1m, 21300 IDB_OBM7_ETAG_MAP_PORT2m, IDB_OBM7_ETAG_MAP_PORT3m, 21301 IDB_OBM8_ETAG_MAP_PORT0m, IDB_OBM8_ETAG_MAP_PORT1m, 21302 IDB_OBM8_ETAG_MAP_PORT2m, IDB_OBM8_ETAG_MAP_PORT3m 21303 }; 21304 21305 static const soc_field_t offset_ob_prio[] = { 21306 OFFSET0_OB_PRIORITYf, OFFSET1_OB_PRIORITYf, 21307 OFFSET2_OB_PRIORITYf, OFFSET3_OB_PRIORITYf, 21308 OFFSET4_OB_PRIORITYf, OFFSET5_OB_PRIORITYf, 21309 OFFSET6_OB_PRIORITYf, OFFSET7_OB_PRIORITYf 21310 }; 21311 21312 mem = obm_etag_map_port_mem[(phy_port - 1) % _AP_PORTS_PER_PGW]; 21313 sal_memset(&entry, 0, sizeof(entry)); 21314 SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, 21315 PGW_CL_BLOCK(unit, pgw), 0, &entry)); 21316 21317 for (i = 0; i < array_count; i++) { 21318 classifier_ptr = switch_obm_classifier + i; 21319 code_point = classifier_ptr->obm_code_point; 21320 ob_priority = classifier_ptr->obm_priority; 21321 soc_mem_field32_set(unit, mem, &entry, 21322 offset_ob_prio[code_point], ob_priority); 21323 } 21324 SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem, 21325 PGW_CL_BLOCK(unit, pgw), 0, &entry)); 21326 return BCM_E_NONE; 21327 } 21328 21329 /* 21330 * Function: 21331 * bcm_apache_switch_obm_etag_classifier_mapping_multi_get 21332 * Purpose: 21333 * Set the mapping of bcm_obm_code_point to bcm_obm_priority 21334 * for multiple entries of etag classifier type. 21335 * Parameters: 21336 * unit - (IN) Unit number. 21337 * phy_port - (IN) Physical port. 21338 * pgw - (IN) PGW index (0 0r 1). 21339 * array_max - (IN) Maximum number of entries. 21340 * switch_obm_classifier - (IN/OUT) Array of etag entries. 21341 * array_count - (OUT) Number of etag entries. 21342 * Returns: 21343 * BCM_E_xxx 21344 */ 21345 21346 STATIC 21347 int bcm_apache_switch_obm_etag_classifier_mapping_multi_get( 21348 int unit, 21349 int phy_port, 21350 int pgw, 21351 int array_max, 21352 bcm_switch_obm_classifier_t *switch_obm_classifier, 21353 int *array_count) 21354 { 21355 int i, code_point, ob_priority; 21356 idb_obm0_etag_map_port0_entry_t entry; 21357 bcm_switch_obm_classifier_t *classifier_ptr = NULL; 21358 soc_mem_t mem; 21359 21360 static const soc_mem_t obm_etag_map_port_mem[] = { 21361 IDB_OBM0_ETAG_MAP_PORT0m, IDB_OBM0_ETAG_MAP_PORT1m, 21362 IDB_OBM0_ETAG_MAP_PORT2m, IDB_OBM0_ETAG_MAP_PORT3m, 21363 IDB_OBM1_ETAG_MAP_PORT0m, IDB_OBM1_ETAG_MAP_PORT1m, 21364 IDB_OBM1_ETAG_MAP_PORT2m, IDB_OBM1_ETAG_MAP_PORT3m, 21365 IDB_OBM2_ETAG_MAP_PORT0m, IDB_OBM2_ETAG_MAP_PORT1m, 21366 IDB_OBM2_ETAG_MAP_PORT2m, IDB_OBM2_ETAG_MAP_PORT3m, 21367 IDB_OBM3_ETAG_MAP_PORT0m, IDB_OBM3_ETAG_MAP_PORT1m, 21368 IDB_OBM3_ETAG_MAP_PORT2m, IDB_OBM3_ETAG_MAP_PORT3m, 21369 IDB_OBM4_ETAG_MAP_PORT0m, IDB_OBM4_ETAG_MAP_PORT1m, 21370 IDB_OBM4_ETAG_MAP_PORT2m, IDB_OBM4_ETAG_MAP_PORT3m, 21371 IDB_OBM5_ETAG_MAP_PORT0m, IDB_OBM5_ETAG_MAP_PORT1m, 21372 IDB_OBM5_ETAG_MAP_PORT2m, IDB_OBM5_ETAG_MAP_PORT3m, 21373 IDB_OBM6_ETAG_MAP_PORT0m, IDB_OBM6_ETAG_MAP_PORT1m, 21374 IDB_OBM6_ETAG_MAP_PORT2m, IDB_OBM6_ETAG_MAP_PORT3m, 21375 IDB_OBM7_ETAG_MAP_PORT0m, IDB_OBM7_ETAG_MAP_PORT1m, 21376 IDB_OBM7_ETAG_MAP_PORT2m, IDB_OBM7_ETAG_MAP_PORT3m, 21377 IDB_OBM8_ETAG_MAP_PORT0m, IDB_OBM8_ETAG_MAP_PORT1m, 21378 IDB_OBM8_ETAG_MAP_PORT2m, IDB_OBM8_ETAG_MAP_PORT3m 21379 }; 21380 21381 static const soc_field_t offset_ob_prio[] = { 21382 OFFSET0_OB_PRIORITYf, OFFSET1_OB_PRIORITYf, 21383 OFFSET2_OB_PRIORITYf, OFFSET3_OB_PRIORITYf, 21384 OFFSET4_OB_PRIORITYf, OFFSET5_OB_PRIORITYf, 21385 OFFSET6_OB_PRIORITYf, OFFSET7_OB_PRIORITYf 21386 }; 21387 21388 mem = obm_etag_map_port_mem[(phy_port - 1) % _AP_PORTS_PER_PGW]; 21389 sal_memset(&entry, 0, sizeof(entry)); 21390 SOC_IF_ERROR_RETURN(soc_mem_read(unit, 21391 mem, PGW_CL_BLOCK(unit, pgw), 0, &entry)); 21392 21393 for (i = 0; i < array_max; i++) { 21394 classifier_ptr = switch_obm_classifier + i; 21395 code_point = classifier_ptr->obm_code_point; 21396 ob_priority = soc_mem_field32_get(unit, mem, &entry, 21397 offset_ob_prio[code_point]); 21398 classifier_ptr->obm_priority = ob_priority; 21399 } 21400 return BCM_E_NONE; 21401 } 21402 21403 /* 21404 * Function: 21405 * bcm_apache_switch_obm_vlan_classifier_mapping_multi_set 21406 * Purpose: 21407 * Set the mapping of bcm_obm_code_point to bcm_obm_priority 21408 * for multiple entries of vlan classifier type. 21409 * Parameters: 21410 * unit - (IN) Unit number. 21411 * phy_port - (IN) Physical port. 21412 * pgw - (IN) PGW index (0 0r 1). 21413 * array_count - (IN) Number of vlan entries. 21414 * switch_obm_classifier - (IN) Array of vlan entries. 21415 * Returns: 21416 * BCM_E_xxx 21417 */ 21418 21419 STATIC 21420 int bcm_apache_switch_obm_vlan_classifier_mapping_multi_set( 21421 int unit, 21422 int phy_port, 21423 int pgw, 21424 int array_count, 21425 bcm_switch_obm_classifier_t *switch_obm_classifier) 21426 { 21427 int i, code_point, ob_priority; 21428 idb_obm0_pri_map_port0_entry_t entry; 21429 bcm_switch_obm_classifier_t *classifier_ptr = NULL; 21430 soc_mem_t mem; 21431 21432 static const soc_mem_t obm_pri_map_port_mem[] = { 21433 IDB_OBM0_PRI_MAP_PORT0m, IDB_OBM0_PRI_MAP_PORT1m, 21434 IDB_OBM0_PRI_MAP_PORT2m, IDB_OBM0_PRI_MAP_PORT3m, 21435 IDB_OBM1_PRI_MAP_PORT0m, IDB_OBM1_PRI_MAP_PORT1m, 21436 IDB_OBM1_PRI_MAP_PORT2m, IDB_OBM1_PRI_MAP_PORT3m, 21437 IDB_OBM2_PRI_MAP_PORT0m, IDB_OBM2_PRI_MAP_PORT1m, 21438 IDB_OBM2_PRI_MAP_PORT2m, IDB_OBM2_PRI_MAP_PORT3m, 21439 IDB_OBM3_PRI_MAP_PORT0m, IDB_OBM3_PRI_MAP_PORT1m, 21440 IDB_OBM3_PRI_MAP_PORT2m, IDB_OBM3_PRI_MAP_PORT3m, 21441 IDB_OBM4_PRI_MAP_PORT0m, IDB_OBM4_PRI_MAP_PORT1m, 21442 IDB_OBM4_PRI_MAP_PORT2m, IDB_OBM4_PRI_MAP_PORT3m, 21443 IDB_OBM5_PRI_MAP_PORT0m, IDB_OBM5_PRI_MAP_PORT1m, 21444 IDB_OBM5_PRI_MAP_PORT2m, IDB_OBM5_PRI_MAP_PORT3m, 21445 IDB_OBM6_PRI_MAP_PORT0m, IDB_OBM6_PRI_MAP_PORT1m, 21446 IDB_OBM6_PRI_MAP_PORT2m, IDB_OBM6_PRI_MAP_PORT3m, 21447 IDB_OBM7_PRI_MAP_PORT0m, IDB_OBM7_PRI_MAP_PORT1m, 21448 IDB_OBM7_PRI_MAP_PORT2m, IDB_OBM7_PRI_MAP_PORT3m, 21449 IDB_OBM8_PRI_MAP_PORT0m, IDB_OBM8_PRI_MAP_PORT1m, 21450 IDB_OBM8_PRI_MAP_PORT2m, IDB_OBM8_PRI_MAP_PORT3m 21451 }; 21452 21453 static const soc_field_t offset_ob_prio[] = { 21454 OFFSET0_OB_PRIORITYf, OFFSET1_OB_PRIORITYf, 21455 OFFSET2_OB_PRIORITYf, OFFSET3_OB_PRIORITYf, 21456 OFFSET4_OB_PRIORITYf, OFFSET5_OB_PRIORITYf, 21457 OFFSET6_OB_PRIORITYf, OFFSET7_OB_PRIORITYf 21458 }; 21459 21460 mem = obm_pri_map_port_mem[(phy_port - 1) % _AP_PORTS_PER_PGW]; 21461 sal_memset(&entry, 0, sizeof(entry)); 21462 SOC_IF_ERROR_RETURN(soc_mem_read(unit, 21463 mem, PGW_CL_BLOCK(unit, pgw), 0, &entry)); 21464 21465 for (i = 0; i < array_count; i++) { 21466 classifier_ptr = switch_obm_classifier + i; 21467 code_point = classifier_ptr->obm_code_point; 21468 ob_priority = classifier_ptr->obm_priority; 21469 soc_mem_field32_set(unit, mem, &entry, 21470 offset_ob_prio[code_point], ob_priority); 21471 } 21472 SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem, 21473 PGW_CL_BLOCK(unit, pgw), 0, &entry)); 21474 return BCM_E_NONE; 21475 } 21476 21477 /* 21478 * Function: 21479 * bcm_apache_switch_obm_vlan_classifier_mapping_multi_get 21480 * Purpose: 21481 * Set the mapping of bcm_obm_code_point to bcm_obm_priority 21482 * for multiple entries of vlan classifier type. 21483 * Parameters: 21484 * unit - (IN) Unit number. 21485 * phy_port - (IN) Physical port. 21486 * pgw - (IN) PGW index (0 0r 1). 21487 * array_max - (IN) Maximum number of entries. 21488 * switch_obm_classifier - (IN/OUT) Array of vlan entries. 21489 * array_count - (OUT) Number of vlan entries. 21490 * Returns: 21491 * BCM_E_xxx 21492 */ 21493 STATIC 21494 int bcm_apache_switch_obm_vlan_classifier_mapping_multi_get( 21495 int unit, 21496 int phy_port, 21497 int pgw, 21498 int array_max, 21499 bcm_switch_obm_classifier_t *switch_obm_classifier, 21500 int *array_count) 21501 { 21502 int i, code_point, ob_priority; 21503 idb_obm0_pri_map_port0_entry_t entry; 21504 bcm_switch_obm_classifier_t *classifier_ptr = NULL; 21505 soc_mem_t mem; 21506 21507 static const soc_mem_t obm_pri_map_port_mem[] = { 21508 IDB_OBM0_PRI_MAP_PORT0m, IDB_OBM0_PRI_MAP_PORT1m, 21509 IDB_OBM0_PRI_MAP_PORT2m, IDB_OBM0_PRI_MAP_PORT3m, 21510 IDB_OBM1_PRI_MAP_PORT0m, IDB_OBM1_PRI_MAP_PORT1m, 21511 IDB_OBM1_PRI_MAP_PORT2m, IDB_OBM1_PRI_MAP_PORT3m, 21512 IDB_OBM2_PRI_MAP_PORT0m, IDB_OBM2_PRI_MAP_PORT1m, 21513 IDB_OBM2_PRI_MAP_PORT2m, IDB_OBM2_PRI_MAP_PORT3m, 21514 IDB_OBM3_PRI_MAP_PORT0m, IDB_OBM3_PRI_MAP_PORT1m, 21515 IDB_OBM3_PRI_MAP_PORT2m, IDB_OBM3_PRI_MAP_PORT3m, 21516 IDB_OBM4_PRI_MAP_PORT0m, IDB_OBM4_PRI_MAP_PORT1m, 21517 IDB_OBM4_PRI_MAP_PORT2m, IDB_OBM4_PRI_MAP_PORT3m, 21518 IDB_OBM5_PRI_MAP_PORT0m, IDB_OBM5_PRI_MAP_PORT1m, 21519 IDB_OBM5_PRI_MAP_PORT2m, IDB_OBM5_PRI_MAP_PORT3m, 21520 IDB_OBM6_PRI_MAP_PORT0m, IDB_OBM6_PRI_MAP_PORT1m, 21521 IDB_OBM6_PRI_MAP_PORT2m, IDB_OBM6_PRI_MAP_PORT3m, 21522 IDB_OBM7_PRI_MAP_PORT0m, IDB_OBM7_PRI_MAP_PORT1m, 21523 IDB_OBM7_PRI_MAP_PORT2m, IDB_OBM7_PRI_MAP_PORT3m, 21524 IDB_OBM8_PRI_MAP_PORT0m, IDB_OBM8_PRI_MAP_PORT1m, 21525 IDB_OBM8_PRI_MAP_PORT2m, IDB_OBM8_PRI_MAP_PORT3m 21526 }; 21527 21528 static const soc_field_t offset_ob_prio[] = { 21529 OFFSET0_OB_PRIORITYf, OFFSET1_OB_PRIORITYf, 21530 OFFSET2_OB_PRIORITYf, OFFSET3_OB_PRIORITYf, 21531 OFFSET4_OB_PRIORITYf, OFFSET5_OB_PRIORITYf, 21532 OFFSET6_OB_PRIORITYf, OFFSET7_OB_PRIORITYf 21533 }; 21534 21535 mem = obm_pri_map_port_mem[(phy_port - 1) % _AP_PORTS_PER_PGW]; 21536 sal_memset(&entry, 0, sizeof(entry)); 21537 SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, 21538 PGW_CL_BLOCK(unit, pgw), 0, &entry)); 21539 21540 for (i = 0; i < array_max; i++) { 21541 classifier_ptr = switch_obm_classifier + i; 21542 code_point = classifier_ptr->obm_code_point; 21543 ob_priority = soc_mem_field32_get(unit, mem, &entry, 21544 offset_ob_prio[code_point]); 21545 classifier_ptr->obm_priority = ob_priority; 21546 } 21547 return BCM_E_NONE; 21548 } 21549 21550 /* 21551 * Function: 21552 * bcm_apache_switch_obm_higig2_classifier_mapping_multi_set 21553 * Purpose: 21554 * Set the mapping of bcm_obm_code_point to bcm_obm_priority 21555 * for multiple entries of higig2 classifier type. 21556 * Parameters: 21557 * unit - (IN) Unit number. 21558 * phy_port - (IN) Physical port. 21559 * pgw - (IN) PGW index (0 0r 1). 21560 * array_count - (IN) Number of higig2 entries. 21561 * switch_obm_classifier - (IN) Array of higig2 entries. 21562 * Returns: 21563 * BCM_E_xxx 21564 */ 21565 STATIC 21566 int bcm_apache_switch_obm_higig2_classifier_mapping_multi_set( 21567 int unit, 21568 int phy_port, 21569 int pgw, 21570 int array_count, 21571 bcm_switch_obm_classifier_t *switch_obm_classifier) 21572 { 21573 int i, code_point, ob_priority; 21574 idb_obm0_pri_map_port0_entry_t entry; 21575 bcm_switch_obm_classifier_t *classifier_ptr = NULL; 21576 soc_mem_t mem; 21577 21578 static const soc_mem_t obm_pri_map_port_mem[] = { 21579 IDB_OBM0_PRI_MAP_PORT0m, IDB_OBM0_PRI_MAP_PORT1m, 21580 IDB_OBM0_PRI_MAP_PORT2m, IDB_OBM0_PRI_MAP_PORT3m, 21581 IDB_OBM1_PRI_MAP_PORT0m, IDB_OBM1_PRI_MAP_PORT1m, 21582 IDB_OBM1_PRI_MAP_PORT2m, IDB_OBM1_PRI_MAP_PORT3m, 21583 IDB_OBM2_PRI_MAP_PORT0m, IDB_OBM2_PRI_MAP_PORT1m, 21584 IDB_OBM2_PRI_MAP_PORT2m, IDB_OBM2_PRI_MAP_PORT3m, 21585 IDB_OBM3_PRI_MAP_PORT0m, IDB_OBM3_PRI_MAP_PORT1m, 21586 IDB_OBM3_PRI_MAP_PORT2m, IDB_OBM3_PRI_MAP_PORT3m, 21587 IDB_OBM4_PRI_MAP_PORT0m, IDB_OBM4_PRI_MAP_PORT1m, 21588 IDB_OBM4_PRI_MAP_PORT2m, IDB_OBM4_PRI_MAP_PORT3m, 21589 IDB_OBM5_PRI_MAP_PORT0m, IDB_OBM5_PRI_MAP_PORT1m, 21590 IDB_OBM5_PRI_MAP_PORT2m, IDB_OBM5_PRI_MAP_PORT3m, 21591 IDB_OBM6_PRI_MAP_PORT0m, IDB_OBM6_PRI_MAP_PORT1m, 21592 IDB_OBM6_PRI_MAP_PORT2m, IDB_OBM6_PRI_MAP_PORT3m, 21593 IDB_OBM7_PRI_MAP_PORT0m, IDB_OBM7_PRI_MAP_PORT1m, 21594 IDB_OBM7_PRI_MAP_PORT2m, IDB_OBM7_PRI_MAP_PORT3m, 21595 IDB_OBM8_PRI_MAP_PORT0m, IDB_OBM8_PRI_MAP_PORT1m, 21596 IDB_OBM8_PRI_MAP_PORT2m, IDB_OBM8_PRI_MAP_PORT3m 21597 }; 21598 21599 static const soc_field_t offset_ob_prio[] = { 21600 OFFSET0_OB_PRIORITYf, OFFSET1_OB_PRIORITYf, OFFSET2_OB_PRIORITYf, 21601 OFFSET3_OB_PRIORITYf, OFFSET4_OB_PRIORITYf, OFFSET5_OB_PRIORITYf, 21602 OFFSET6_OB_PRIORITYf, OFFSET7_OB_PRIORITYf, OFFSET8_OB_PRIORITYf, 21603 OFFSET9_OB_PRIORITYf, OFFSET10_OB_PRIORITYf, OFFSET11_OB_PRIORITYf, 21604 OFFSET12_OB_PRIORITYf, OFFSET13_OB_PRIORITYf, OFFSET14_OB_PRIORITYf, 21605 OFFSET15_OB_PRIORITYf 21606 }; 21607 21608 mem = obm_pri_map_port_mem[(phy_port - 1) % _AP_PORTS_PER_PGW]; 21609 sal_memset(&entry, 0, sizeof(entry)); 21610 SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, 21611 PGW_CL_BLOCK(unit, pgw), 0, &entry)); 21612 21613 for (i = 0; i < array_count; i++) { 21614 classifier_ptr = switch_obm_classifier + i; 21615 code_point = classifier_ptr->obm_code_point; 21616 ob_priority = classifier_ptr->obm_priority; 21617 soc_mem_field32_set(unit, mem, &entry, 21618 offset_ob_prio[code_point], ob_priority); 21619 } 21620 SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem, 21621 PGW_CL_BLOCK(unit, pgw), 0, &entry)); 21622 return BCM_E_NONE; 21623 } 21624 21625 /* 21626 * Function: 21627 * bcm_apache_switch_obm_higig2_classifier_mapping_multi_get 21628 * Purpose: 21629 * Set the mapping of bcm_obm_code_point to bcm_obm_priority 21630 * for multiple entries of higig2 classifier type. 21631 * Parameters: 21632 * unit - (IN) Unit number. 21633 * phy_port - (IN) Physical port. 21634 * pgw - (IN) PGW index (0 0r 1). 21635 * array_max - (IN) Maximum number of entries. 21636 * switch_obm_classifier - (IN/OUT) Array of higig2 entries. 21637 * array_count - (OUT) Number of higig2 entries. 21638 * Returns: 21639 * BCM_E_xxx 21640 */ 21641 21642 STATIC 21643 int bcm_apache_switch_obm_higig2_classifier_mapping_multi_get( 21644 int unit, 21645 int phy_port, 21646 int pgw, 21647 int array_max, 21648 bcm_switch_obm_classifier_t *switch_obm_classifier, 21649 int *array_count) 21650 { 21651 int i, code_point, ob_priority; 21652 idb_obm0_pri_map_port0_entry_t entry; 21653 bcm_switch_obm_classifier_t *classifier_ptr = NULL; 21654 soc_mem_t mem; 21655 21656 static const soc_mem_t obm_pri_map_port_mem[] = { 21657 IDB_OBM0_PRI_MAP_PORT0m, IDB_OBM0_PRI_MAP_PORT1m, 21658 IDB_OBM0_PRI_MAP_PORT2m, IDB_OBM0_PRI_MAP_PORT3m, 21659 IDB_OBM1_PRI_MAP_PORT0m, IDB_OBM1_PRI_MAP_PORT1m, 21660 IDB_OBM1_PRI_MAP_PORT2m, IDB_OBM1_PRI_MAP_PORT3m, 21661 IDB_OBM2_PRI_MAP_PORT0m, IDB_OBM2_PRI_MAP_PORT1m, 21662 IDB_OBM2_PRI_MAP_PORT2m, IDB_OBM2_PRI_MAP_PORT3m, 21663 IDB_OBM3_PRI_MAP_PORT0m, IDB_OBM3_PRI_MAP_PORT1m, 21664 IDB_OBM3_PRI_MAP_PORT2m, IDB_OBM3_PRI_MAP_PORT3m, 21665 IDB_OBM4_PRI_MAP_PORT0m, IDB_OBM4_PRI_MAP_PORT1m, 21666 IDB_OBM4_PRI_MAP_PORT2m, IDB_OBM4_PRI_MAP_PORT3m, 21667 IDB_OBM5_PRI_MAP_PORT0m, IDB_OBM5_PRI_MAP_PORT1m, 21668 IDB_OBM5_PRI_MAP_PORT2m, IDB_OBM5_PRI_MAP_PORT3m, 21669 IDB_OBM6_PRI_MAP_PORT0m, IDB_OBM6_PRI_MAP_PORT1m, 21670 IDB_OBM6_PRI_MAP_PORT2m, IDB_OBM6_PRI_MAP_PORT3m, 21671 IDB_OBM7_PRI_MAP_PORT0m, IDB_OBM7_PRI_MAP_PORT1m, 21672 IDB_OBM7_PRI_MAP_PORT2m, IDB_OBM7_PRI_MAP_PORT3m, 21673 IDB_OBM8_PRI_MAP_PORT0m, IDB_OBM8_PRI_MAP_PORT1m, 21674 IDB_OBM8_PRI_MAP_PORT2m, IDB_OBM8_PRI_MAP_PORT3m 21675 }; 21676 21677 static const soc_field_t offset_ob_prio[] = { 21678 OFFSET0_OB_PRIORITYf, OFFSET1_OB_PRIORITYf, OFFSET2_OB_PRIORITYf, 21679 OFFSET3_OB_PRIORITYf, OFFSET4_OB_PRIORITYf, OFFSET5_OB_PRIORITYf, 21680 OFFSET6_OB_PRIORITYf, OFFSET7_OB_PRIORITYf, OFFSET8_OB_PRIORITYf, 21681 OFFSET9_OB_PRIORITYf, OFFSET10_OB_PRIORITYf, OFFSET11_OB_PRIORITYf, 21682 OFFSET12_OB_PRIORITYf, OFFSET13_OB_PRIORITYf, OFFSET14_OB_PRIORITYf, 21683 OFFSET15_OB_PRIORITYf 21684 }; 21685 21686 mem = obm_pri_map_port_mem[(phy_port - 1) % _AP_PORTS_PER_PGW]; 21687 sal_memset(&entry, 0, sizeof(entry)); 21688 SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, 21689 PGW_CL_BLOCK(unit, pgw), 0, &entry)); 21690 21691 for (i = 0; i < array_max; i++) { 21692 classifier_ptr = switch_obm_classifier + i; 21693 code_point = classifier_ptr->obm_code_point; 21694 ob_priority = soc_mem_field32_get(unit, mem, &entry, 21695 offset_ob_prio[code_point]); 21696 classifier_ptr->obm_priority = ob_priority; 21697 } 21698 return BCM_E_NONE; 21699 } 21700 /* 21701 * Function: 21702 * bcm_apache_switch_obm_field_classifier_mapping_multi_set 21703 * Purpose: 21704 * Match based on destination_mac, destination_mac_mask, 21705 * ethertype and ethertype_mask and assign bcm_obm_priority. 21706 * for multiple entries of mpls classifier type. 21707 * Parameters: 21708 * unit - (IN) Unit number. 21709 * phy_port - (IN) Physical port. 21710 * pgw - (IN) PGW index (0 0r 1). 21711 * array_count - (IN) Number of field entries. 21712 * switch_obm_classifier - (IN) Array of field entries. 21713 * Returns: 21714 * BCM_E_xxx 21715 */ 21716 STATIC 21717 int bcm_apache_switch_obm_field_classifier_mapping_multi_set( 21718 int unit, 21719 int phy_port, 21720 int pgw, 21721 int array_count, 21722 bcm_switch_obm_classifier_t *switch_obm_classifier) 21723 { 21724 uint64 rval64; 21725 uint32 rval_hi, rval_lo; 21726 bcm_switch_obm_classifier_t *classifier_ptr = NULL; 21727 soc_reg_t reg; 21728 int i, pgw_inst; 21729 21730 static const soc_reg_t obm_proto_control0_regs[] = { 21731 IDB_OBM0_PROTOCOL_CONTROL_0r, IDB_OBM1_PROTOCOL_CONTROL_0r, 21732 IDB_OBM2_PROTOCOL_CONTROL_0r, IDB_OBM3_PROTOCOL_CONTROL_0r, 21733 IDB_OBM4_PROTOCOL_CONTROL_0r, IDB_OBM5_PROTOCOL_CONTROL_0r, 21734 IDB_OBM6_PROTOCOL_CONTROL_0r, IDB_OBM7_PROTOCOL_CONTROL_0r, 21735 IDB_OBM8_PROTOCOL_CONTROL_0r 21736 }; 21737 static const soc_reg_t obm_proto_control1_regs[] = { 21738 IDB_OBM0_PROTOCOL_CONTROL_1r, IDB_OBM1_PROTOCOL_CONTROL_1r, 21739 IDB_OBM2_PROTOCOL_CONTROL_1r, IDB_OBM3_PROTOCOL_CONTROL_1r, 21740 IDB_OBM4_PROTOCOL_CONTROL_1r, IDB_OBM5_PROTOCOL_CONTROL_1r, 21741 IDB_OBM6_PROTOCOL_CONTROL_1r, IDB_OBM7_PROTOCOL_CONTROL_1r, 21742 IDB_OBM8_PROTOCOL_CONTROL_1r 21743 }; 21744 static const soc_reg_t obm_proto_control2_regs[] = { 21745 IDB_OBM0_PROTOCOL_CONTROL_2r, IDB_OBM1_PROTOCOL_CONTROL_2r, 21746 IDB_OBM2_PROTOCOL_CONTROL_2r, IDB_OBM3_PROTOCOL_CONTROL_2r, 21747 IDB_OBM4_PROTOCOL_CONTROL_2r, IDB_OBM5_PROTOCOL_CONTROL_2r, 21748 IDB_OBM6_PROTOCOL_CONTROL_2r, IDB_OBM7_PROTOCOL_CONTROL_2r, 21749 IDB_OBM8_PROTOCOL_CONTROL_2r 21750 }; 21751 21752 pgw_inst = (pgw | SOC_REG_ADDR_INSTANCE_MASK); 21753 21754 for (i = 0; i < array_count; i++) { 21755 classifier_ptr = switch_obm_classifier + i; 21756 21757 reg = obm_proto_control0_regs[((phy_port - 1) % _AP_PORTS_PER_PGW) / 4]; 21758 COMPILER_64_ZERO(rval64); 21759 COMPILER_64_TO_32_HI(rval_hi, rval64); 21760 COMPILER_64_TO_32_LO(rval_lo, rval64); 21761 rval_hi |= ((classifier_ptr->obm_destination_mac[5] & 0xff) << 8); 21762 rval_hi |= (classifier_ptr->obm_destination_mac[4] & 0xff); 21763 rval_lo |= ((classifier_ptr->obm_destination_mac[3] & 0xff) << 24); 21764 rval_lo |= ((classifier_ptr->obm_destination_mac[2] & 0xff) << 16); 21765 rval_lo |= ((classifier_ptr->obm_destination_mac[1] & 0xff) << 8); 21766 rval_lo |= (classifier_ptr->obm_destination_mac[0] & 0xff); 21767 COMPILER_64_SET(rval64, rval_hi, rval_lo); 21768 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, 21769 pgw_inst, i, rval64)); 21770 21771 reg = obm_proto_control1_regs[((phy_port - 1) % _AP_PORTS_PER_PGW) / 4]; 21772 COMPILER_64_ZERO(rval64); 21773 COMPILER_64_TO_32_HI(rval_hi, rval64); 21774 COMPILER_64_TO_32_LO(rval_lo, rval64); 21775 rval_hi |= ((classifier_ptr->obm_destination_mac_mask[5] & 0xff) << 8); 21776 rval_hi |= (classifier_ptr->obm_destination_mac_mask[4] & 0xff); 21777 rval_lo |= ((classifier_ptr->obm_destination_mac_mask[3] & 0xff) << 24); 21778 rval_lo |= ((classifier_ptr->obm_destination_mac_mask[2] & 0xff) << 16); 21779 rval_lo |= ((classifier_ptr->obm_destination_mac_mask[1] & 0xff) << 8); 21780 rval_lo |= (classifier_ptr->obm_destination_mac_mask[0] & 0xff); 21781 COMPILER_64_SET(rval64, rval_hi, rval_lo); 21782 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, 21783 pgw_inst, i, rval64)); 21784 reg = obm_proto_control2_regs[((phy_port - 1) % _AP_PORTS_PER_PGW) / 4]; 21785 COMPILER_64_ZERO(rval64); 21786 COMPILER_64_TO_32_HI(rval_hi, rval64); 21787 COMPILER_64_TO_32_LO(rval_lo, rval64); 21788 rval_lo |= (classifier_ptr->obm_ethertype & 0xffff); 21789 rval_lo |= ((classifier_ptr->obm_ethertype_mask & 0xffff) << 16); 21790 rval_hi |= (classifier_ptr->obm_priority & 0x3); 21791 rval_hi |= (0x1 << 3); 21792 COMPILER_64_SET(rval64, rval_hi, rval_lo); 21793 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, 21794 pgw_inst, i, rval64)); 21795 } 21796 return BCM_E_NONE; 21797 } 21798 21799 /* 21800 * Function: 21801 * bcm_apache_switch_obm_field_classifier_mapping_multi_get 21802 * Purpose: 21803 * Get the mapping of bcm_obm_priority for a given 21804 * destination_mac, destination_mac_mask, ethertype and 21805 * ethertype mask for multiple entries of field classifier type. 21806 * Parameters: 21807 * unit - (IN) Unit number. 21808 * phy_port - (IN) Physical port. 21809 * pgw - (IN) PGW index (0 0r 1). 21810 * array_max - (IN) Maximum number of entries. 21811 * switch_obm_classifier - (IN/OUT) Array of field entries. 21812 * array_count - (OUT) Number of field entries. 21813 * Returns: 21814 * BCM_E_xxx 21815 */ 21816 21817 STATIC 21818 int bcm_apache_switch_obm_field_classifier_mapping_multi_get( 21819 int unit, 21820 int phy_port, 21821 int pgw, 21822 int array_max, 21823 bcm_switch_obm_classifier_t *switch_obm_classifier, 21824 int *array_count) 21825 { 21826 uint64 rval64; 21827 uint32 rval_hi, rval_lo; 21828 bcm_switch_obm_classifier_t *classifier_ptr = NULL; 21829 soc_reg_t reg; 21830 int i, pgw_inst; 21831 21832 static const soc_reg_t obm_proto_control0_regs[] = { 21833 IDB_OBM0_PROTOCOL_CONTROL_0r, IDB_OBM1_PROTOCOL_CONTROL_0r, 21834 IDB_OBM2_PROTOCOL_CONTROL_0r, IDB_OBM3_PROTOCOL_CONTROL_0r, 21835 IDB_OBM4_PROTOCOL_CONTROL_0r, IDB_OBM5_PROTOCOL_CONTROL_0r, 21836 IDB_OBM6_PROTOCOL_CONTROL_0r, IDB_OBM7_PROTOCOL_CONTROL_0r, 21837 IDB_OBM8_PROTOCOL_CONTROL_0r 21838 21839 }; 21840 static const soc_reg_t obm_proto_control1_regs[] = { 21841 IDB_OBM0_PROTOCOL_CONTROL_1r, IDB_OBM1_PROTOCOL_CONTROL_1r, 21842 IDB_OBM2_PROTOCOL_CONTROL_1r, IDB_OBM3_PROTOCOL_CONTROL_1r, 21843 IDB_OBM4_PROTOCOL_CONTROL_1r, IDB_OBM5_PROTOCOL_CONTROL_1r, 21844 IDB_OBM6_PROTOCOL_CONTROL_1r, IDB_OBM7_PROTOCOL_CONTROL_1r, 21845 IDB_OBM8_PROTOCOL_CONTROL_1r 21846 }; 21847 static const soc_reg_t obm_proto_control2_regs[] = { 21848 IDB_OBM0_PROTOCOL_CONTROL_2r, IDB_OBM1_PROTOCOL_CONTROL_2r, 21849 IDB_OBM2_PROTOCOL_CONTROL_2r, IDB_OBM3_PROTOCOL_CONTROL_2r, 21850 IDB_OBM4_PROTOCOL_CONTROL_2r, IDB_OBM5_PROTOCOL_CONTROL_2r, 21851 IDB_OBM6_PROTOCOL_CONTROL_2r, IDB_OBM7_PROTOCOL_CONTROL_2r, 21852 IDB_OBM8_PROTOCOL_CONTROL_2r 21853 }; 21854 21855 pgw_inst = (pgw | SOC_REG_ADDR_INSTANCE_MASK); 21856 21857 /* Do validation of params */ 21858 if (array_max > BCM_OBM_CLASSIFIER_NUM_ENTRY_FIELD) { 21859 *array_count = BCM_OBM_CLASSIFIER_NUM_ENTRY_FIELD; 21860 } else { 21861 *array_count = array_max; 21862 } 21863 21864 for (i = 0; i < *array_count; i++) { 21865 classifier_ptr = switch_obm_classifier + i; 21866 21867 reg = obm_proto_control0_regs[((phy_port - 1) % _AP_PORTS_PER_PGW) / 4]; 21868 COMPILER_64_ZERO(rval64); 21869 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, 21870 pgw_inst, i, &rval64)); 21871 COMPILER_64_TO_32_HI(rval_hi, rval64); 21872 COMPILER_64_TO_32_LO(rval_lo, rval64); 21873 classifier_ptr->obm_destination_mac[5] = (rval_hi >> 8) & 0xff; 21874 classifier_ptr->obm_destination_mac[4] = rval_hi & 0xff; 21875 classifier_ptr->obm_destination_mac[3] = (rval_lo >> 24) & 0xff; 21876 classifier_ptr->obm_destination_mac[2] = (rval_lo >> 16) & 0xff; 21877 classifier_ptr->obm_destination_mac[1] = (rval_lo >> 8) & 0xff; 21878 classifier_ptr->obm_destination_mac[0] = rval_lo & 0xff; 21879 21880 reg = obm_proto_control1_regs[((phy_port - 1) % _AP_PORTS_PER_PGW) / 4]; 21881 COMPILER_64_ZERO(rval64); 21882 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, 21883 pgw_inst, i, &rval64)); 21884 COMPILER_64_TO_32_HI(rval_hi, rval64); 21885 COMPILER_64_TO_32_LO(rval_lo, rval64); 21886 classifier_ptr->obm_destination_mac_mask[5] = (rval_hi >> 8) & 0xff; 21887 classifier_ptr->obm_destination_mac_mask[4] = rval_hi & 0xff; 21888 classifier_ptr->obm_destination_mac_mask[3] = (rval_lo >> 24) & 0xff; 21889 classifier_ptr->obm_destination_mac_mask[2] = (rval_lo >> 16) & 0xff; 21890 classifier_ptr->obm_destination_mac_mask[1] = (rval_lo >> 8) & 0xff; 21891 classifier_ptr->obm_destination_mac_mask[0] = rval_lo & 0xff; 21892 21893 reg = obm_proto_control2_regs[((phy_port - 1) % _AP_PORTS_PER_PGW) / 4]; 21894 COMPILER_64_ZERO(rval64); 21895 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, 21896 pgw_inst, i, &rval64)); 21897 COMPILER_64_TO_32_HI(rval_hi, rval64); 21898 COMPILER_64_TO_32_LO(rval_lo, rval64); 21899 classifier_ptr->obm_ethertype = rval_lo & 0xffff; 21900 classifier_ptr->obm_ethertype_mask = (rval_lo >>16) & 0xffff; 21901 classifier_ptr->obm_priority = rval_hi & 0x3; 21902 } 21903 return BCM_E_NONE; 21904 } 21905 21906 /* 21907 * Function: 21908 * bcm_apache_switch_obm_classifier_validate 21909 * Purpose: 21910 * Internal function for validation of config params. 21911 * Parameters: 21912 * unit - (IN) Unit number. 21913 * port - (IN) phyical port. 21914 * switch_obm_classifier_type- (IN) type of switch_obm_classifier. 21915 * array_count - (IN) Number of elements in switch_obm_classifier. 21916 * switch_obm_classifier - (IN) Array of bcm_switch_obm_classifier_t. 21917 * Returns: 21918 * BCM_E_xxx 21919 */ 21920 21921 STATIC 21922 int bcm_apache_switch_obm_classifier_validate( 21923 int unit, 21924 bcm_port_t port, 21925 bcm_switch_obm_classifier_type_t switch_obm_classifier_type, 21926 int *array_count, 21927 bcm_switch_obm_classifier_t *switch_obm_classifier, 21928 int set) 21929 { 21930 int i, max_count; 21931 bcm_switch_obm_classifier_t *classifier_ptr = NULL; 21932 21933 if ((port <= 0) || (port > 72)) { 21934 LOG_ERROR(BSL_LS_BCM_COMMON, 21935 (BSL_META_U(unit, 21936 "ERROR: Invalid port %d\n"), port)); 21937 return BCM_E_PORT; 21938 } 21939 21940 if (switch_obm_classifier_type == bcmSwitchObmClassifierMpls) { 21941 LOG_ERROR(BSL_LS_BCM_COMMON, 21942 (BSL_META_U(unit, 21943 "ERROR: OBM MPLS classifier not supported" 21944 " port %d\n"), port)); 21945 return BCM_E_UNAVAIL; 21946 } 21947 21948 if (IS_HG_PORT(unit, port)) { 21949 if (switch_obm_classifier_type == bcmSwitchObmClassifierVlan) { 21950 LOG_ERROR(BSL_LS_BCM_COMMON, 21951 (BSL_META_U(unit, 21952 "ERROR: OBM Vlan classifier not allowed on Higig" 21953 " port %d\n"), port)); 21954 return BCM_E_PARAM; 21955 } 21956 } else { 21957 if (switch_obm_classifier_type == bcmSwitchObmClassifierHigig2) { 21958 LOG_ERROR(BSL_LS_BCM_COMMON, 21959 (BSL_META_U(unit, 21960 "ERROR: OBM Higig2 classifier not allowed on non Higig" 21961 " port %d\n"), port)); 21962 return BCM_E_PARAM; 21963 } 21964 } 21965 switch (switch_obm_classifier_type) { 21966 case bcmSwitchObmClassifierDscp: 21967 max_count = BCM_OBM_CLASSIFIER_NUM_ENTRY_DSCP; 21968 break; 21969 case bcmSwitchObmClassifierEtag: 21970 max_count = BCM_OBM_CLASSIFIER_NUM_ENTRY_ETAG; 21971 break; 21972 case bcmSwitchObmClassifierVlan: 21973 max_count = BCM_OBM_CLASSIFIER_NUM_ENTRY_VLAN; 21974 break; 21975 case bcmSwitchObmClassifierHigig2: 21976 max_count = BCM_OBM_CLASSIFIER_NUM_ENTRY_HIGIG2; 21977 break; 21978 case bcmSwitchObmClassifierField: 21979 max_count = BCM_OBM_CLASSIFIER_NUM_ENTRY_FIELD; 21980 break; 21981 default: 21982 LOG_ERROR(BSL_LS_BCM_COMMON, 21983 (BSL_META_U(unit, 21984 "ERROR: switch_obm_classifier_type is not correct on" 21985 " port %d\n"), port)); 21986 return BCM_E_PARAM; 21987 } 21988 /* For get API array count may be more than max_count */ 21989 if (*array_count > max_count) { 21990 if (set) { 21991 return BCM_E_PARAM; 21992 } else { 21993 *array_count = max_count; 21994 } 21995 } 21996 for (i = 0; i < *array_count; i++) { 21997 classifier_ptr = switch_obm_classifier + i; 21998 if (switch_obm_classifier_type != bcmSwitchObmClassifierField) { 21999 if (classifier_ptr->obm_code_point >= max_count) { 22000 LOG_ERROR(BSL_LS_BCM_COMMON, 22001 (BSL_META_U(unit, 22002 "ERROR: Invalid obm_code_point configured on" 22003 " port %d\n"), port)); 22004 return BCM_E_PARAM; 22005 } 22006 } 22007 if (set) { 22008 if (switch_obm_classifier_type == bcmSwitchObmClassifierMpls) { 22009 LOG_ERROR(BSL_LS_BCM_COMMON, 22010 (BSL_META_U(unit, 22011 "ERROR: Invalid obm_classifier configured on" 22012 " port %d\n"), port)); 22013 return BCM_E_PARAM; 22014 } 22015 22016 if (classifier_ptr->obm_priority > BCM_OBM_PRIORITY_MAX) { 22017 LOG_ERROR(BSL_LS_BCM_COMMON, 22018 (BSL_META_U(unit, 22019 "ERROR: Invalid obm_priority configured on" 22020 " port %d\n"), port)); 22021 return BCM_E_PARAM; 22022 } 22023 } 22024 } 22025 return BCM_E_NONE; 22026 } 22027 /* 22028 * Function: 22029 * bcm_apache_switch_obm_classifier_mapping_multi_set 22030 * Purpose: 22031 * Set the mapping of bcm_obm_code_point to bcm_obm_priority 22032 * for multiple entries of same type of classifier. Maximum 22033 * number of entries to be programmed are different depending 22034 * type of classifier. For type bcmSwitchObmClassifierField 22035 * bcm_obm_code_point will not be used and mapping will happen 22036 * based on destination_mac/mask and ethertype/mask. 22037 * Parameters: 22038 * unit - (IN) Unit number. 22039 * gport - (IN) gport for a given port. 22040 * switch_obm_classifier_type - (IN) type of switch_obm_classifier. 22041 * array_count - (IN) Number of elements in switch_obm_classifier. 22042 * switch_obm_classifier - (IN) Array of bcm_switch_obm_classifier_t. 22043 * Returns: 22044 * BCM_E_xxx 22045 */ 22046 22047 int 22048 bcm_apache_switch_obm_classifier_mapping_multi_set( 22049 int unit, 22050 bcm_gport_t gport, 22051 bcm_switch_obm_classifier_type_t switch_obm_classifier_type, 22052 int array_count, 22053 bcm_switch_obm_classifier_t *switch_obm_classifier) 22054 { 22055 soc_info_t *si; 22056 int pgw; 22057 int phy_port; 22058 bcm_port_t port; 22059 22060 22061 si = &SOC_INFO(unit); 22062 BCM_IF_ERROR_RETURN(bcm_esw_port_local_get(unit, gport, &port)); 22063 phy_port = si->port_l2p_mapping[port]; 22064 pgw = si->port_group[port]; 22065 22066 /* Validate port and classifier compatibility */ 22067 BCM_IF_ERROR_RETURN( 22068 bcm_apache_switch_obm_classifier_validate(unit, 22069 port, 22070 switch_obm_classifier_type, 22071 &array_count, 22072 switch_obm_classifier, 22073 1)); 22074 22075 switch (switch_obm_classifier_type) { 22076 case bcmSwitchObmClassifierDscp: 22077 BCM_IF_ERROR_RETURN( 22078 bcm_apache_switch_obm_dscp_classifier_mapping_multi_set( 22079 unit, 22080 phy_port, 22081 pgw, 22082 array_count, 22083 switch_obm_classifier)); 22084 break; 22085 case bcmSwitchObmClassifierEtag: 22086 BCM_IF_ERROR_RETURN( 22087 bcm_apache_switch_obm_etag_classifier_mapping_multi_set( 22088 unit, 22089 phy_port, 22090 pgw, 22091 array_count, 22092 switch_obm_classifier)); 22093 break; 22094 case bcmSwitchObmClassifierVlan: 22095 BCM_IF_ERROR_RETURN( 22096 bcm_apache_switch_obm_vlan_classifier_mapping_multi_set( 22097 unit, 22098 phy_port, 22099 pgw, 22100 array_count, 22101 switch_obm_classifier)); 22102 break; 22103 case bcmSwitchObmClassifierHigig2: 22104 BCM_IF_ERROR_RETURN( 22105 bcm_apache_switch_obm_higig2_classifier_mapping_multi_set( 22106 unit, 22107 phy_port, 22108 pgw, 22109 array_count, 22110 switch_obm_classifier)); 22111 break; 22112 case bcmSwitchObmClassifierField: 22113 BCM_IF_ERROR_RETURN( 22114 bcm_apache_switch_obm_field_classifier_mapping_multi_set( 22115 unit, 22116 phy_port, 22117 pgw, 22118 array_count, 22119 switch_obm_classifier)); 22120 break; 22121 22122 default: 22123 return BCM_E_PARAM; 22124 } 22125 return BCM_E_NONE; 22126 } 22127 22128 /* 22129 * Function: 22130 * bcm_apache_switch_obm_classifier_mapping_multi_get 22131 * Purpose: 22132 * Get the mapping of bcm_obm_code_point to bcm_obm_priority 22133 * for multiple entries of same type of classifier. Maximum 22134 * number of entries to be programmed are different depending 22135 * type of classifier. For type bcmSwitchObmClassifierField 22136 * bcm_obm_code_point will not be used and mapping will happen 22137 * based on destination_mac/mask and ethertype/mask. 22138 * Parameters: 22139 * unit - (IN) Unit number. 22140 * gport - (IN) gport for a given port. 22141 * switch_obm_classifier_type - (IN) type of switch_obm_classifier. 22142 * array_max - (IN) Maximum number of elements in switch_obm_classifier. 22143 * switch_obm_classifier - (IN/OUT) Array of bcm_switch_obm_classifier_t. 22144 * array_count - (OUT) Number of elements in switch_obm_classifier. 22145 * Returns: 22146 * BCM_E_xxx 22147 */ 22148 22149 int 22150 bcm_apache_switch_obm_classifier_mapping_multi_get( 22151 int unit, 22152 bcm_gport_t gport, 22153 bcm_switch_obm_classifier_type_t switch_obm_classifier_type, 22154 int array_max, 22155 bcm_switch_obm_classifier_t *switch_obm_classifier, 22156 int *array_count) 22157 22158 { 22159 soc_info_t *si; 22160 int pgw; 22161 int phy_port; 22162 bcm_port_t port; 22163 22164 si = &SOC_INFO(unit); 22165 BCM_IF_ERROR_RETURN(bcm_esw_port_local_get(unit, gport, &port)); 22166 phy_port = si->port_l2p_mapping[port]; 22167 pgw = si->port_group[port]; 22168 22169 /* Validate port and classifier compatibility */ 22170 BCM_IF_ERROR_RETURN( 22171 bcm_apache_switch_obm_classifier_validate(unit, 22172 port, 22173 switch_obm_classifier_type, 22174 array_count, 22175 switch_obm_classifier, 22176 0)); 22177 switch (switch_obm_classifier_type) { 22178 case bcmSwitchObmClassifierDscp: 22179 BCM_IF_ERROR_RETURN( 22180 bcm_apache_switch_obm_dscp_classifier_mapping_multi_get( 22181 unit, 22182 phy_port, 22183 pgw, 22184 array_max, 22185 switch_obm_classifier, 22186 array_count)); 22187 break; 22188 case bcmSwitchObmClassifierEtag: 22189 BCM_IF_ERROR_RETURN( 22190 bcm_apache_switch_obm_etag_classifier_mapping_multi_get( 22191 unit, 22192 phy_port, 22193 pgw, 22194 array_max, 22195 switch_obm_classifier, 22196 array_count)); 22197 break; 22198 case bcmSwitchObmClassifierVlan: 22199 BCM_IF_ERROR_RETURN( 22200 bcm_apache_switch_obm_vlan_classifier_mapping_multi_get( 22201 unit, 22202 phy_port, 22203 pgw, 22204 array_max, 22205 switch_obm_classifier, 22206 array_count)); 22207 break; 22208 case bcmSwitchObmClassifierHigig2: 22209 BCM_IF_ERROR_RETURN( 22210 bcm_apache_switch_obm_higig2_classifier_mapping_multi_get( 22211 unit, 22212 phy_port, 22213 pgw, 22214 array_max, 22215 switch_obm_classifier, 22216 array_count)); 22217 break; 22218 case bcmSwitchObmClassifierField: 22219 BCM_IF_ERROR_RETURN( 22220 bcm_apache_switch_obm_field_classifier_mapping_multi_get( 22221 unit, 22222 phy_port, 22223 pgw, 22224 array_max, 22225 switch_obm_classifier, 22226 array_count)); 22227 break; 22228 22229 default: 22230 return BCM_E_PARAM; 22231 } 22232 return BCM_E_NONE; 22233 } 22234 /* 22235 * Function: 22236 * bcm_apache_obm_classifier_port_control_set 22237 * Description: 22238 * Internal function to Enable/Disable specified 22239 * OBM port feature and congigure ethertype. 22240 * Parameters: 22241 * unit - Device number 22242 * port - Port number 22243 * type - Enum value of the OBM feature 22244 * value - value to be set 22245 * Return Value: 22246 * BCM_E_XXXX 22247 */ 22248 int 22249 bcm_apache_obm_classifier_port_control_set(int unit, 22250 bcm_port_t port, 22251 bcm_port_control_t type, 22252 int value) 22253 { 22254 soc_info_t *si; 22255 int pgw, pgw_inst, subport, obm; 22256 int phy_port; 22257 soc_reg_t reg; 22258 soc_field_t field; 22259 int vntag = 0, port_control = 0, val; 22260 uint32 rval32; 22261 22262 static const soc_reg_t obm_port_config_regs[] = { 22263 IDB_OBM0_PORT_CONFIGr, IDB_OBM1_PORT_CONFIGr, 22264 IDB_OBM2_PORT_CONFIGr, IDB_OBM3_PORT_CONFIGr, 22265 IDB_OBM4_PORT_CONFIGr, IDB_OBM5_PORT_CONFIGr, 22266 IDB_OBM6_PORT_CONFIGr, IDB_OBM7_PORT_CONFIGr, 22267 IDB_OBM8_PORT_CONFIGr 22268 }; 22269 22270 static const soc_reg_t obm_niv_ethertype_config_regs[] = { 22271 IDB_OBM0_NIV_ETHERTYPEr, IDB_OBM1_NIV_ETHERTYPEr, 22272 IDB_OBM2_NIV_ETHERTYPEr, IDB_OBM3_NIV_ETHERTYPEr, 22273 IDB_OBM4_NIV_ETHERTYPEr, IDB_OBM5_NIV_ETHERTYPEr, 22274 IDB_OBM6_NIV_ETHERTYPEr, IDB_OBM7_NIV_ETHERTYPEr, 22275 IDB_OBM8_NIV_ETHERTYPEr 22276 }; 22277 22278 static const soc_reg_t obm_pe_ethertype_config_regs[] = { 22279 IDB_OBM0_PE_ETHERTYPEr, IDB_OBM1_PE_ETHERTYPEr, 22280 IDB_OBM2_PE_ETHERTYPEr, IDB_OBM3_PE_ETHERTYPEr, 22281 IDB_OBM4_PE_ETHERTYPEr, IDB_OBM5_PE_ETHERTYPEr, 22282 IDB_OBM6_PE_ETHERTYPEr, IDB_OBM7_PE_ETHERTYPEr, 22283 IDB_OBM8_PE_ETHERTYPEr 22284 }; 22285 22286 si = &SOC_INFO(unit); 22287 /* Add check on ports */ 22288 obm = si->port_serdes[port]; 22289 obm %= _AP_TSCS_PER_PGW; 22290 phy_port = si->port_l2p_mapping[port]; 22291 22292 if (IS_CPU_PORT(unit, port) || IS_LB_PORT(unit, port)) { 22293 /* Do not allow programming on non-idb ports */ 22294 return BCM_E_PARAM; 22295 } 22296 22297 22298 pgw = si->port_group[port]; 22299 pgw_inst = (pgw | SOC_REG_ADDR_INSTANCE_MASK); 22300 subport = (phy_port - 1) % _AP_PORTS_PER_TSC; 22301 22302 switch (type) { 22303 case bcmPortControlObmClassifierPriority: 22304 port_control = 1; 22305 field = PORT_PRIf; 22306 val = value & 0x7; 22307 break; 22308 case bcmPortControlObmClassifierEnableDscp: 22309 port_control = 1; 22310 field = TRUST_DSCPf; 22311 val = value & 0x1; 22312 break; 22313 case bcmPortControlObmClassifierEnableEtag: 22314 port_control = 1; 22315 field = PHB_FROM_ETAGf; 22316 val = value & 0x1; 22317 break; 22318 case bcmPortControlObmClassifierEtagEthertype: 22319 field = ETHERTYPEf; 22320 val = value & 0xffff; 22321 break; 22322 case bcmPortControlObmClassifierVntagEthertype: 22323 vntag = 1; 22324 field = ETHERTYPEf; 22325 val = value & 0xffff; 22326 break; 22327 case bcmPortControlObmClassifierEnableMpls: 22328 return BCM_E_UNAVAIL; 22329 default: 22330 return BCM_E_PARAM; 22331 } 22332 if (port_control == 1) { 22333 reg = obm_port_config_regs[obm]; 22334 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, pgw_inst, subport, &rval32)); 22335 soc_reg_field_set(unit, reg, &rval32, field, val); 22336 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, pgw_inst, subport, rval32)); 22337 } else if (vntag == 1) { 22338 reg = obm_niv_ethertype_config_regs[obm]; 22339 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, pgw_inst, subport, &rval32)); 22340 soc_reg_field_set(unit, reg, &rval32, field, val); 22341 soc_reg_field_set(unit, reg, &rval32, ENABLEf, val ? 1 : 0); 22342 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, pgw_inst, subport, rval32)); 22343 } else { 22344 reg = obm_pe_ethertype_config_regs[obm]; 22345 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, pgw_inst, subport, &rval32)); 22346 soc_reg_field_set(unit, reg, &rval32, field, val); 22347 soc_reg_field_set(unit, reg, &rval32, ENABLEf, val ? 1 : 0); 22348 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, pgw_inst, subport, rval32)); 22349 } 22350 return BCM_E_NONE; 22351 } 22352 /* 22353 * Function: 22354 * bcm_apache_obm_classifier_port_control_get 22355 * Description: 22356 * Internal function to get value specified 22357 * OBM port feature and congigure ethertype. 22358 * Parameters: 22359 * unit - Device number 22360 * port - Port number 22361 * type - Enum value of the OBM feature 22362 * value - value to get 22363 * Return Value: 22364 * BCM_E_XXXX 22365 */ 22366 int 22367 bcm_apache_obm_classifier_port_control_get(int unit, 22368 bcm_port_t port, 22369 bcm_port_control_t type, 22370 int *value) 22371 { 22372 soc_info_t *si; 22373 int pgw, pgw_inst, subport, obm; 22374 int phy_port; 22375 soc_reg_t reg; 22376 soc_field_t field; 22377 int vntag = 0, port_control = 0, val; 22378 uint32 rval32; 22379 22380 static const soc_reg_t obm_port_config_regs[] = { 22381 IDB_OBM0_PORT_CONFIGr, IDB_OBM1_PORT_CONFIGr, 22382 IDB_OBM2_PORT_CONFIGr, IDB_OBM3_PORT_CONFIGr, 22383 IDB_OBM4_PORT_CONFIGr, IDB_OBM5_PORT_CONFIGr, 22384 IDB_OBM6_PORT_CONFIGr, IDB_OBM7_PORT_CONFIGr, 22385 IDB_OBM8_PORT_CONFIGr 22386 }; 22387 22388 static const soc_reg_t obm_niv_ethertype_config_regs[] = { 22389 IDB_OBM0_NIV_ETHERTYPEr, IDB_OBM1_NIV_ETHERTYPEr, 22390 IDB_OBM2_NIV_ETHERTYPEr, IDB_OBM3_NIV_ETHERTYPEr, 22391 IDB_OBM4_NIV_ETHERTYPEr, IDB_OBM5_NIV_ETHERTYPEr, 22392 IDB_OBM6_NIV_ETHERTYPEr, IDB_OBM7_NIV_ETHERTYPEr, 22393 IDB_OBM8_NIV_ETHERTYPEr 22394 }; 22395 22396 static const soc_reg_t obm_pe_ethertype_config_regs[] = { 22397 IDB_OBM0_PE_ETHERTYPEr, IDB_OBM1_PE_ETHERTYPEr, 22398 IDB_OBM2_PE_ETHERTYPEr, IDB_OBM3_PE_ETHERTYPEr, 22399 IDB_OBM4_PE_ETHERTYPEr, IDB_OBM5_PE_ETHERTYPEr, 22400 IDB_OBM6_PE_ETHERTYPEr, IDB_OBM7_PE_ETHERTYPEr, 22401 IDB_OBM8_PE_ETHERTYPEr 22402 }; 22403 22404 si = &SOC_INFO(unit); 22405 /* Add check on ports */ 22406 obm = si->port_serdes[port]; 22407 obm %= _AP_TSCS_PER_PGW; 22408 22409 phy_port = si->port_l2p_mapping[port]; 22410 22411 if (IS_CPU_PORT(unit, port) || IS_LB_PORT(unit, port)) { 22412 /* Do not allow programming on non-idb ports */ 22413 return BCM_E_PARAM; 22414 } 22415 22416 22417 pgw = si->port_group[port]; 22418 pgw_inst = (pgw | SOC_REG_ADDR_INSTANCE_MASK); 22419 subport = (phy_port - 1) % _AP_PORTS_PER_TSC; 22420 22421 switch (type) { 22422 case bcmPortControlObmClassifierPriority: 22423 port_control = 1; 22424 field = PORT_PRIf; 22425 break; 22426 case bcmPortControlObmClassifierEnableDscp: 22427 port_control = 1; 22428 field = TRUST_DSCPf; 22429 break; 22430 case bcmPortControlObmClassifierEnableEtag: 22431 port_control = 1; 22432 field = PHB_FROM_ETAGf; 22433 break; 22434 case bcmPortControlObmClassifierEtagEthertype: 22435 field = ETHERTYPEf; 22436 break; 22437 case bcmPortControlObmClassifierVntagEthertype: 22438 vntag = 1; 22439 field = ETHERTYPEf; 22440 break; 22441 case bcmPortControlObmClassifierEnableMpls: 22442 return BCM_E_UNAVAIL; 22443 default: 22444 return BCM_E_PARAM; 22445 } 22446 if (port_control == 1) { 22447 reg = obm_port_config_regs[obm]; 22448 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, pgw_inst, subport, &rval32)); 22449 val = soc_reg_field_get(unit, reg, rval32, field); 22450 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, pgw_inst, subport, rval32)); 22451 } else if (vntag == 1) { 22452 reg = obm_niv_ethertype_config_regs[obm]; 22453 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, pgw_inst, subport, &rval32)); 22454 val = soc_reg_field_get(unit, reg, rval32, field); 22455 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, pgw_inst, subport, rval32)); 22456 } else { 22457 reg = obm_pe_ethertype_config_regs[obm]; 22458 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, pgw_inst, subport, &rval32)); 22459 val = soc_reg_field_get(unit, reg, rval32, field); 22460 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, pgw_inst, subport, rval32)); 22461 } 22462 *value = val; 22463 return BCM_E_NONE; 22464 } 22465 22466 #endif /* defined(BCM_APACHE_SUPPORT) */