openbcm

Git mirror of https://github.com/Broadcom-Network-Switching-Software/OpenBCM
git clone git://git.finwo.net/mirror/broadcom/openbcm
Log | Files | Refs | README

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, &reg, 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, &reg, 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                                                   &reg_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) */