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 (745398B)


      1 /*
      2  * 
      3  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      4  * 
      5  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      6  *
      7  * COS Queue Management
      8  * Purpose: API to set different cosq, priorities, and scheduler registers.
      9  */
     10 
     11 #include <shared/bsl.h>
     12 
     13 #include <soc/defs.h>
     14 #include <sal/core/libc.h>
     15 
     16 #if defined(BCM_MONTEREY_SUPPORT)
     17 #include <soc/drv.h>
     18 #include <soc/scache.h>
     19 #include <soc/profile_mem.h>
     20 #include <soc/l3x.h>
     21 
     22 #include <soc/trident2.h>
     23 #include <soc/monterey.h>
     24 
     25 
     26 #include <bcm/error.h>
     27 #include <bcm/cosq.h>
     28 #include <bcm_int/esw/mbcm.h>
     29 #include <bcm_int/esw/stack.h>
     30 #include <bcm_int/esw/cosq.h>
     31 #include <bcm_int/esw/virtual.h>
     32 #include <bcm_int/esw/apache.h>
     33 #include <bcm_int/esw/monterey.h>
     34 #include <bcm_int/esw/oob.h>
     35 #include <bcm_int/esw/trx.h>
     36 
     37 #include <bcm_int/esw_dispatch.h>
     38 
     39 #include <bcm_int/bst.h>
     40 #include <bcm_int/common/lock.h>
     41 
     42 #include <bcm/subport.h>
     43 #include <bcm_int/esw/xgs5.h>
     44 #include <bcm_int/esw/switch.h>
     45 
     46 /* COS max value for MN is 10 */
     47 #define BCM_MN_COS_MAX  10
     48 
     49 #define AP_CELL_FIELD_MAX       0x1ffff
     50 #define _BCM_PORT_SERVICE_POOL        768 
     51 #define _BCM_WRED_GLOBAL_SERVICE_POOL 1036 
     52 #define IS_SPECIAL_PORT(unit, port) (IS_CPU_PORT(unit, port) || \
     53         IS_LB_PORT(unit, port) || IS_MACSEC_PORT(unit, port))
     54 /* MMU cell size in bytes */
     55 #define _BCM_MN_BYTES_PER_CELL            208   /* bytes */
     56 #define _BCM_MN_BYTES_TO_CELLS(_byte_)  \
     57     (((_byte_) + _BCM_MN_BYTES_PER_CELL - 1) / _BCM_MN_BYTES_PER_CELL)
     58 #define _BCM_MN_NUM_PIPES                        1 
     59 #define _BCM_MN_NUM_PORT_SCHEDULERS              76 
     60 #define _BCM_MN_NUM_S1_SCHEDULER_PER_PIPE        328 
     61 #define _BCM_MN_NUM_L0_SCHEDULER_PER_PIPE        1024  
     62 #define _BCM_MN_NUM_L0_SCHEDULER                 _BCM_MN_NUM_L0_SCHEDULER_PER_PIPE * _BCM_MN_NUM_PIPES 
     63 #define _BCM_MN_NUM_L1_SCHEDULER_PER_PIPE        4224 /* Reserved for default val */
     64 #define _BCM_MN_NUM_L1_SCHEDULER                 _BCM_MN_NUM_L1_SCHEDULER_PER_PIPE * _BCM_MN_NUM_PIPES 
     65 #define _BCM_MN_NUM_L2_UC_LEAVES_PER_PIPE        640 /* Reserved for default val */
     66 #define _BCM_MN_NUM_L2_UC_LEAVES                 _BCM_MN_NUM_L2_UC_LEAVES_PER_PIPE * _BCM_MN_NUM_PIPES 
     67 #define _BCM_MN_NUM_L2_MC_LEAVES_PER_PIPE        708  
     68 #define _BCM_MN_NUM_L2_MC_LEAVES                 _BCM_MN_NUM_L2_MC_LEAVES_PER_PIPE * _BCM_MN_NUM_PIPES 
     69 #define _BCM_MN_NUM_L2_LEAVES_PER_PIPE     (_BCM_MN_NUM_L2_MC_LEAVES_PER_PIPE + \
     70                                              _BCM_MN_NUM_L2_UC_LEAVES_PER_PIPE)
     71 #define _BCM_MN_NUM_L2_LEAVES              _BCM_MN_NUM_L2_LEAVES_PER_PIPE * _BCM_MN_NUM_PIPES 
     72 #define _BCM_MN_NUM_TOTAL_SCHEDULERS     (_BCM_MN_NUM_PORT_SCHEDULERS + \
     73                                            _BCM_MN_NUM_S1_SCHEDULER_PER_PIPE + \
     74                                            _BCM_MN_NUM_L0_SCHEDULER +    \
     75                                            _BCM_MN_NUM_L1_SCHEDULER)
     76 #define _BCM_MN_CPU_COSQ_START             660
     77 #define _MN_SPM_ENTRIES_PER_SET            128
     78 #define _MN_VPM_ENTRIES_PER_SET            128
     79 #define _MN_SCM_ENTRIES_PER_SET            16
     80 
     81 #define _BCM_MN_LLS_DYN_CHG_REG_B 0x3FFF
     82 #define _BCM_MN_LLS_DYN_CHG_REG_C 0xFFFFFFFF
     83 
     84 /* All CPU leaves Ranges from 17114-17161.*/
     85 #define _BCM_MN_NUM_L2_CPU_LEAVES                48 
     86 /* All  Lb leaves Ranges from 17104-17111.*/
     87 #define _BCM_MN_NUM_L2_LB_LEAVES                8 
     88 
     89 #define _MN_NUM_COS    NUM_COS
     90 #define _MN_NUM_INTERNAL_PRI          16
     91 
     92 #define _BCM_MN_NUM_PFC_CLASS          8
     93 #define  _BCM_MN_NUM_SAFC_CLASS        16 
     94 #define _BCM_MN_COSQ_LIST_NODE_INIT(list, node)         \
     95     list[node].in_use            = FALSE;               \
     96     list[node].gport             = -1;                  \
     97     list[node].base_index        = -1;                  \
     98     list[node].numq              = 0;                   \
     99     list[node].base_size         = 0;                   \
    100     list[node].numq_expandable   = 0;                   \
    101     list[node].hw_index          = -1;                  \
    102     list[node].level             = -1;                  \
    103     list[node].attached_to_input       = -1;                  \
    104     list[node].hw_cosq           = 0;                   \
    105     list[node].remote_modid      = -1;                  \
    106     list[node].remote_port       = -1;                  \
    107     list[node].cosq_map          = NULL;                \
    108     BCM_PBMP_CLEAR(list[node].fabric_pbmp);              \
    109     list[node].local_port        = -1;                  \
    110     list[node].parent            = NULL;                \
    111     list[node].sibling           = NULL;                \
    112     list[node].child             = NULL;                \
    113     list[node].coe_base_index = -1;                     \
    114     list[node].coe_num_l2 = 0;                          \
    115     list[node].port_gport = -1;                                
    116 
    117 #define _BCM_MN_COSQ_NODE_INIT(node)                    \
    118     node->in_use            = FALSE;                    \
    119     node->gport             = -1;                       \
    120     node->base_index        = -1;                       \
    121     node->numq              = 0;                        \
    122     node->base_size         = 0;                        \
    123     node->numq_expandable   = 0;                        \
    124     node->hw_index          = -1;                       \
    125     node->level             = -1;                       \
    126     node->attached_to_input = -1;                       \
    127     node->hw_cosq           = 0;                        \
    128     node->remote_modid      = -1;                       \
    129     node->remote_port       = -1;                       \
    130     node->cosq_map          = NULL;                \
    131     BCM_PBMP_CLEAR(node->fabric_pbmp);              \
    132     node->local_port        = -1;                       \
    133     node->parent            = NULL;                     \
    134     node->sibling           = NULL;                     \
    135     node->child             = NULL;                     \
    136     node->coe_base_index = -1;                          \
    137     node->coe_num_l2 = 0;                               \
    138     node->port_gport = -1;                                
    139 
    140 typedef enum {
    141     _BCM_MN_COSQ_FC_PAUSE = 0,
    142     _BCM_MN_COSQ_FC_PFC,
    143     _BCM_MN_COSQ_FC_VOQFC,
    144     _BCM_MN_COSQ_FC_E2ECC,
    145     _BCM_MN_COSQ_FC_SAFC
    146 } _bcm_mn_fc_type_t;
    147 
    148 typedef enum {
    149     _BCM_MN_NODE_UNKNOWN = 0,
    150     _BCM_MN_NODE_UCAST,
    151     _BCM_MN_NODE_MCAST,
    152     _BCM_MN_NODE_VOQ,
    153     _BCM_MN_NODE_VLAN_UCAST,
    154     _BCM_MN_NODE_VM_UCAST,
    155     _BCM_MN_NODE_SERVICE_UCAST,
    156     _BCM_MN_NODE_SCHEDULER
    157 } _bcm_mn_node_type_e;
    158 
    159 typedef enum {
    160     _BCM_MN_COSQ_STATE_NO_CHANGE,
    161     _BCM_MN_COSQ_STATE_DISABLE,
    162     _BCM_MN_COSQ_STATE_ENABLE,
    163     _BCM_MN_COSQ_STATE_SPRI_TO_WRR,
    164     _BCM_MN_COSQ_STATE_WRR_TO_SPRI,
    165     _BCM_MN_COSQ_STATE_MAX
    166 }_bcm_mn_cosq_state_t;
    167 
    168 typedef struct _bcm_mn_cosq_node_s {
    169     struct _bcm_mn_cosq_node_s *parent;
    170     struct _bcm_mn_cosq_node_s *sibling;
    171     struct _bcm_mn_cosq_node_s *child;
    172     bcm_gport_t gport;
    173     int in_use;
    174     int base_index;
    175     uint16 numq_expandable;
    176     uint16 base_size;
    177     int numq;
    178     int hw_index;
    179     soc_monterey_node_lvl_e level;
    180     _bcm_mn_node_type_e    type;
    181     int attached_to_input;
    182     int hw_cosq;
    183     int wrr_in_use;
    184 
    185     /* DPVOQ specific information */
    186     bcm_port_t   local_port;
    187     bcm_module_t remote_modid;
    188     bcm_port_t   remote_port;
    189     bcm_pbmp_t   fabric_pbmp;
    190     SHR_BITDCL *cosq_map;
    191     int coe_num_l2;/* Number of active l2 queues for the subport*/
    192 /*Used in S1 node to store the base index for that sub port*/
    193     int coe_base_index;
    194 /* the port gport the node was created with*/
    195     bcm_gport_t port_gport;
    196 }_bcm_mn_cosq_node_t;
    197 
    198 typedef struct _bcm_mn_lls_info_s {
    199     int child_lvl; /* level of the node */
    200     int child_hw_index; /* hw index of the node */
    201     int node_count[SOC_MONTEREY_NODE_LVL_MAX]; /* total number of nodes in the lls */
    202     int count[SOC_MONTEREY_NODE_LVL_MAX]; /* number of nodes in each level */
    203     int offset[SOC_MONTEREY_NODE_LVL_MAX]; /* index of the starting node at each level */
    204 
    205     int kbit_max; /* max speed for the node */
    206     int kbit_min; /* min speed for the node */
    207 
    208     uint32  *mtro_entries; /* entries to maintain mmu mtro level mem */
    209 } _bcm_mn_lls_info_t;
    210 
    211 typedef struct _bcm_mn_cosq_list_s {
    212     int count;
    213     SHR_BITDCL *bits;
    214 }_bcm_mn_cosq_list_t;
    215 
    216 /* Monterey CPRI and RSVD4 port HSP default shaper setting and service pool mapping */
    217 typedef struct _bcm_mn_mtro_node_info_s {
    218     uint32  mode; /* 0 for byte mode and 1 for packet mode */
    219     uint32  refresh_period;
    220     uint32  bucket_threshold;
    221     uint32  rate;
    222     int     spid;
    223 } _bcm_mn_mtro_node_info_t;
    224 
    225 /*
    226  * There are 9 nodes indexed 0-8. index 0 is for L0.1 and index
    227  * 1-7 are for L1.1 to L1.7 respectively. Index 8 is for L1.5 in
    228  * case this node is in HDLC mode instead of Ethernet mode.
    229  */
    230 
    231 #define _BCM_MN_NUM_CPRI_CONFIG_NODE   9
    232 
    233 STATIC _bcm_mn_mtro_node_info_t mtro0_max_bucket_info[_BCM_MN_NUM_CPRI_CONFIG_NODE] = {
    234              {0, 390625, 512, 1000000, 1}, {0, 390625, 256, 119940, 0},
    235              {0, 390625, 256, 119940, 0}, {0, 390625, 256, 119940, 0},
    236              {0, 390625, 256, 119940, 0}, {0, 390625, 256, 337920, 0},
    237              {0, 390625, 256, 122820, 1}, {0, 390625, 256, 32768, 1},
    238              {0, 390625, 256, 7680, 0}
    239              };
    240 STATIC _bcm_mn_mtro_node_info_t mtro1_max_bucket_info[_BCM_MN_NUM_CPRI_CONFIG_NODE] = {
    241              {0, 390625, 256, 150000, 1}, {0, 390625, 256, 98300, 0},
    242              {0, 390625, 256, 2670, 1}, {0, 390625, 256, 2670, 1},
    243              {0, 390625, 256, 2670, 1}, {0, 390625, 256, 2670, 1},
    244              {0, 390625, 256, 32768, 1}, {0, 390625, 256, 51, 1},
    245              {0, 390625, 256, 2670, 1}
    246              };
    247 
    248 #define _BCM_MN_HSP_PORT_MAX_ROOT         67
    249 #define _BCM_MN_HSP_PORT_MAX_L0           5
    250 #define _BCM_MN_HSP_PORT_MAX_L1           10
    251 #define _BCM_MN_HSP_PORT_MAX_L2           10
    252 #define _BCM_MN_HSP_PORT_MAX_L2_PER_L1    2
    253 #define _BCM_MN_HSP_PORT_MAX_COS          8
    254 
    255 #define _BCM_MN_CPU_PORT_L0_MIN    1018 
    256 #define _BCM_MN_CPU_PORT_L0_MAX    1023 
    257 #define _BCM_MN_MAX_PORT           76
    258 
    259 #define _BCM_MN_ROOT_SCHED_INDEX(u,mmu_port)       \
    260                 ((mmu_port >= 74) ? (mmu_port - 74) : (mmu_port))
    261 
    262 #define _BCM_MN_HSP_L0_INDEX(u,mmu_port,cosq)       \
    263  ((((mmu_port >= 74) ? (mmu_port - 74) : (mmu_port)) * _BCM_MN_HSP_PORT_MAX_L0) +\
    264   (cosq))
    265 
    266 #define _BCM_MN_HSP_L1_INDEX(u,mmu_port,cosq)       \
    267  ((((mmu_port >= 74) ? (mmu_port - 74) : (mmu_port)) * _BCM_MN_HSP_PORT_MAX_L1) +\
    268   (cosq))
    269 
    270 #define _BCM_MN_HSP_L2_INDEX(u,mmu_port,cosq)       \
    271  ((((mmu_port >= 74) ? (mmu_port - 74) : (mmu_port)) * _BCM_MN_HSP_PORT_MAX_L2) +\
    272   (cosq))
    273 
    274 
    275 typedef struct _bcm_mn_pipe_resources_s {
    276     int num_base_queues;   /* Number of classical queues */
    277 
    278     _bcm_mn_cosq_list_t l2_queue_list;  /* list of l2 queues */
    279     _bcm_mn_cosq_list_t hsp_l2_queue_list;  /* list of l2 queues */
    280     _bcm_mn_cosq_list_t l0_sched_list;  /* list of l0 sched nodes */
    281     _bcm_mn_cosq_list_t hsp_l0_sched_list;  /* list of l0 sched nodes */
    282     _bcm_mn_cosq_list_t cpu_l0_sched_list;  /* list of l0 sched nodes */
    283     _bcm_mn_cosq_list_t l1_sched_list;  /* list of l1 sched nodes */
    284     _bcm_mn_cosq_list_t hsp_l1_sched_list;  /* list of l1 sched nodes */
    285     _bcm_mn_cosq_list_t s1_sched_list;  /* list of s1 sched nodes */
    286 
    287     _bcm_mn_cosq_node_t *p_queue_node;
    288     _bcm_mn_cosq_node_t *p_mc_queue_node;
    289 } _bcm_mn_pipe_resources_t;
    290 
    291 typedef struct _bcm_mn_cosq_port_info_s {
    292     int mc_base;
    293     int mc_limit;
    294     int uc_base;
    295     int uc_limit;
    296     int eq_base;
    297     int eq_limit;
    298     _bcm_mn_pipe_resources_t *resources;
    299 } _bcm_mn_cosq_port_info_t;
    300 
    301 typedef struct _bcm_mn_cosq_cpu_cosq_config_s {
    302     /* All MC queues have DB and MCQE space */
    303     int enable;
    304     int q_min_limit[2];
    305     int q_shared_limit[2];
    306     uint8 q_limit_dynamic[2];
    307     uint8 q_limit_enable[2];
    308     uint8 q_color_limit_enable[2];
    309 } _bcm_mn_cosq_cpu_cosq_config_t;
    310 
    311 #define _MN_XPIPE  0
    312 #define _MN_YPIPE  1
    313 #define _MN_NUM_PIPES  1
    314 
    315 #define _BCM_MN_PORT_TO_PIPE(u, p) _MN_XPIPE 
    316 typedef struct _bcm_mn_mmu_info_s {
    317 
    318     _bcm_mn_cosq_node_t sched_node[_BCM_MN_NUM_TOTAL_SCHEDULERS]; /* sched nodes */
    319     _bcm_mn_cosq_node_t queue_node[_BCM_MN_NUM_L2_UC_LEAVES];    /* queue nodes */
    320     _bcm_mn_cosq_node_t mc_queue_node[_BCM_MN_NUM_L2_MC_LEAVES]; /* queue nodes */
    321     _bcm_mn_cosq_port_info_t port_info[_BCM_MN_MAX_PORT];
    322     
    323     _bcm_mn_pipe_resources_t   pipe_resources[_MN_NUM_PIPES];
    324     
    325     int     ets_mode;
    326     int     curr_shared_limit;
    327     int     curr_merger_index;
    328 /*  this should be programmed by reading the soc_info which will have
    329  *  the info from the software OTP 
    330  */
    331     int     num_l2_queues;
    332     int     _bcm_mn_default_lls;
    333 }_bcm_mn_mmu_info_t;
    334 
    335 #define _BCM_DEFAULT_LLS_SET(mmu_info)          \
    336     do {                                        \
    337         mmu_info->_bcm_mn_default_lls = 1;      \
    338     } while(0);
    339 
    340 #define _BCM_DEFAULT_LLS_IS_SET(mmu_info)       \
    341     (mmu_info->_bcm_mn_default_lls)
    342 
    343 #define _BCM_DEFAULT_LLS_RESET(mmu_info)        \
    344     do {                                        \
    345         mmu_info->_bcm_mn_default_lls = 0;      \
    346     } while(0);
    347 
    348 #define _BCM_MN_START_INDEX_ALIGN_PFC       4
    349 #define _BCM_MN_START_INDEX_ALIGN_DEFAULT   1
    350 #define _MN_NUM_TIME_DOMAIN    4
    351 
    352 typedef struct _bcm_mn_cosq_time_info_s {
    353     soc_field_t field;
    354     uint32 ref_count;   
    355 } _bcm_mn_cosq_time_info_t;
    356 
    357 /* WRED can be enabled at per UC queue / queue group/ port / service pool basis
    358 639 ~ 0: Unicast Queue
    359 767 - 640: Queue Group per PIPE
    360 1035 ~ 768: Port Service Pool (Port 0 to 73)
    361 1039 ~ 1036: Global Service Pool
    362 */
    363 STATIC _bcm_mn_cosq_time_info_t time_domain_mn[_MN_NUM_TIME_DOMAIN] = {
    364     {TIME_0f, 1040}, /* Default all entries are pointing to TIME_0 */
    365     {TIME_1f, 0},
    366     {TIME_2f, 0},
    367     {TIME_3f, 0}
    368 };
    369 
    370 #define _MN_NUM_SERVICE_POOL    4
    371 
    372 #define _BCM_MN_PRESOURCES(mi, p)  (&(mi)->pipe_resources[(p)])
    373 
    374 STATIC _bcm_mn_mmu_info_t *_bcm_mn_mmu_info[BCM_MAX_NUM_UNITS];  /* MMU info */
    375 
    376 STATIC soc_profile_mem_t *_bcm_mn_wred_profile[BCM_MAX_NUM_UNITS];
    377 STATIC soc_profile_mem_t *_bcm_mn_cos_map_profile[BCM_MAX_NUM_UNITS];
    378 STATIC soc_profile_mem_t *_bcm_mn_sample_int_profile[BCM_MAX_NUM_UNITS];
    379 STATIC soc_profile_reg_t *_bcm_mn_feedback_profile[BCM_MAX_NUM_UNITS];
    380 STATIC soc_profile_reg_t *_bcm_mn_llfc_profile[BCM_MAX_NUM_UNITS];
    381 STATIC soc_profile_mem_t *_bcm_mn_voq_port_map_profile[BCM_MAX_NUM_UNITS];
    382 static soc_profile_mem_t *_bcm_mn_ifp_cos_map_profile[BCM_MAX_NUM_UNITS];
    383 STATIC soc_profile_mem_t *_bcm_mn_service_port_map_profile[BCM_MAX_NUM_UNITS];
    384 STATIC soc_profile_mem_t *_bcm_mn_service_cos_map_profile[BCM_MAX_NUM_UNITS];
    385 
    386 STATIC _bcm_mn_cosq_cpu_cosq_config_t *_bcm_mn_cosq_cpu_cosq_config[BCM_MAX_NUM_UNITS][_BCM_MN_NUM_L2_CPU_LEAVES];
    387 
    388 STATIC int
    389 _bcm_mn_node_index_set(_bcm_mn_cosq_list_t *list, int start, int range);
    390 
    391 STATIC int _bcm_mn_voq_next_base_node_get(int unit, bcm_port_t port, 
    392         int modid,
    393         _bcm_mn_cosq_node_t **base_node);
    394 STATIC int
    395 _bcm_mn_cosq_mapping_set(int unit, bcm_port_t ing_port, bcm_cos_t priority,
    396                          uint32 flags, bcm_gport_t gport, bcm_cos_queue_t cosq);
    397 
    398 STATIC int
    399 _bcm_mn_map_fc_status_to_node(int unit, int port, _bcm_mn_fc_type_t fct,
    400                     int spad_offset, int cosq, uint32 hw_index, int level);
    401 STATIC int
    402 _bcm_mn_cosq_max_nodes_get(int unit, soc_monterey_node_lvl_e level,
    403                            int *id);
    404 
    405 typedef enum {
    406     _BCM_MN_COSQ_TYPE_UCAST,
    407     _BCM_MN_COSQ_TYPE_MCAST,
    408     _BCM_MN_COSQ_TYPE_EXT_UCAST
    409 } _bcm_mn_cosq_type_t;
    410 
    411 #define IS_MN_HSP_PORT(u,p)   \
    412     (SOC_IS_MONTEREY(unit) ? TRUE : \
    413     ((_soc_monterey_port_sched_type_get((u),(p)) == SOC_MONTEREY_SCHED_HSP) ? 1 : 0)) 
    414 
    415 typedef struct _bcm_mn_endpoint_s {
    416     uint32 flags;       /* BCM_COSQ_CLASSIFIER_xxx flags */
    417     bcm_vlan_t vlan;    /* VLAN */
    418     bcm_mac_t mac;      /* MAC address */
    419     bcm_vrf_t vrf;      /* Virtual Router Instance */
    420     bcm_ip_t ip_addr;   /* IPv4 address */
    421     bcm_ip6_t ip6_addr; /* IPv6 address */
    422     bcm_gport_t gport;  /* GPORT ID */
    423 } _bcm_mn_endpoint_t;
    424 
    425 typedef struct _bcm_mn_endpoint_queuing_info_s {
    426     int num_endpoint; /* Number of endpoints */
    427     _bcm_mn_endpoint_t **ptr_array; /* Array of pointers to endpoints */
    428     soc_profile_mem_t *cos_map_profile; /* Internal priority to CoS queue
    429                                            mapping profile */
    430 } _bcm_mn_endpoint_queuing_info_t;
    431 
    432 STATIC int 
    433 _bcm_mn_cosq_egress_sp_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 
    434                         int *p_pool_start, int *p_pool_end);
    435 
    436 STATIC _bcm_mn_endpoint_queuing_info_t *_bcm_mn_endpoint_queuing_info[BCM_MAX_NUM_UNITS];
    437 
    438 STATIC int
    439 _bcm_mn_cosq_dynamic_thresh_enable_get(int unit, 
    440                         bcm_gport_t gport, bcm_cos_queue_t cosq, 
    441                         bcm_cosq_control_t type, int *arg);
    442 
    443 STATIC int
    444 _bcm_mn_fc_status_map_gport(int unit, int port, 
    445                 bcm_gport_t gport, _bcm_mn_fc_type_t fct, uint32 *cos_bmp);
    446 STATIC int
    447 _bcm_mn_port_fc_profile_set(int unit, int port, _bcm_cosq_op_t op,
    448                               int entry_cnt, int *pfc_class, uint32 *cos_bmp);
    449 STATIC int 
    450 _bcm_mn_cosq_node_get(int unit, bcm_gport_t gport,
    451     bcm_cos_queue_t cosq,bcm_module_t *modid, bcm_port_t *port,
    452     int *id, _bcm_mn_cosq_node_t **node);
    453 
    454 int _bcm_mn_get_s1_node(int unit, bcm_gport_t subport,
    455                       _bcm_mn_cosq_node_t **s1_node) ;
    456 STATIC int
    457 _bcm_mn_cosq_sched_parent_child_set(int unit, int port, int level,
    458                                      int sched_index, int child_index,
    459                                      soc_monterey_sched_mode_e sched_mode, 
    460                                      int weight, _bcm_mn_cosq_node_t *child_node);
    461 #define _BCM_MN_NUM_ENDPOINT(unit) \
    462     (_bcm_mn_endpoint_queuing_info[unit]->num_endpoint)
    463     
    464 #define _BCM_MN_ENDPOINT(unit, id) \
    465     (_bcm_mn_endpoint_queuing_info[unit]->ptr_array[id])
    466 
    467 #define _BCM_MN_ENDPOINT_IS_USED(unit, id) \
    468     (_bcm_mn_endpoint_queuing_info[unit]->ptr_array[id] != NULL)
    469 
    470 #define _BCM_MN_ENDPOINT_COS_MAP_PROFILE(unit) \
    471     (_bcm_mn_endpoint_queuing_info[unit]->cos_map_profile)
    472 
    473 
    474 /*
    475  * Function:
    476  *     _bcm_mn_cosq_map_index_set
    477  * Purpose:
    478  *     Mark indices as allocated
    479  * Parameters:
    480  *     list       - (IN) bit list
    481  *     start      - (IN) start index
    482  *     range      - (IN) range bits
    483  * Returns:
    484  *     BCM_E_XXX
    485  */
    486 STATIC int
    487 _bcm_mn_cosq_map_index_set(SHR_BITDCL *list, int start, int range)
    488 {
    489     SHR_BITSET_RANGE(list, start, range);
    490     return BCM_E_NONE;
    491 }
    492 
    493 #ifdef BCM_WARM_BOOT_SUPPORT
    494 
    495 #define BCM_WB_VERSION_1_0                SOC_SCACHE_VERSION(1,0)
    496 #define BCM_WB_VERSION_1_1                SOC_SCACHE_VERSION(1,1)
    497 #define BCM_WB_VERSION_1_2                SOC_SCACHE_VERSION(1,2)
    498 
    499 #define BCM_WB_DEFAULT_VERSION            BCM_WB_VERSION_1_2
    500 
    501 STATIC int
    502 _bcm_mn_cosq_wb_alloc(int unit)
    503 {
    504     _bcm_mn_mmu_info_t *mmu_info;
    505     soc_scache_handle_t scache_handle;
    506     uint8 *scache_ptr;
    507     int rv, alloc_size, node_list_sizes[3], ii, jj;
    508     uint32 shadow_size = 0;
    509     
    510     mmu_info = _bcm_mn_mmu_info[unit];
    511 
    512     if (!mmu_info) {
    513         return BCM_E_INIT;
    514     }
    515 
    516     node_list_sizes[0] = _BCM_MN_NUM_L2_UC_LEAVES;
    517     node_list_sizes[1] = _BCM_MN_NUM_L2_MC_LEAVES;
    518     node_list_sizes[2] = _BCM_MN_NUM_TOTAL_SCHEDULERS;
    519 
    520     alloc_size = 0;
    521     for(ii = 0; ii < 3; ii++) {
    522         alloc_size += sizeof(uint32);
    523         for(jj = 0; jj < node_list_sizes[ii]; jj++) {
    524             alloc_size += 8 * sizeof(uint32);
    525         }
    526     }
    527 
    528     /* Size of  TIME_DOMAINr field and count reference */
    529     alloc_size += _MN_NUM_TIME_DOMAIN * sizeof(_bcm_mn_cosq_time_info_t);
    530 
    531     soc_monterey_shadow_size_get(unit, &shadow_size);
    532     alloc_size += shadow_size;
    533 
    534     /* added in BCM_WB_VERSION_1_1
    535      * to sync _bcm_mn_mmu_info[unit]->ets_mode/curr_shared_limit
    536      */
    537     alloc_size += 2 * sizeof(int);
    538 
    539     /* added in BCM_WB_VERSION_1_1
    540      * to sync the reference count of IFP_COS_MAPm 
    541      */
    542     alloc_size += (SOC_MEM_SIZE(unit,IFP_COS_MAPm) / _MN_NUM_INTERNAL_PRI) *
    543                   sizeof(uint16);
    544 
    545     /*
    546      * Sync num_cos value
    547      */
    548     alloc_size += sizeof(int);
    549 
    550     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_COSQ, 0);
    551 
    552     rv = _bcm_esw_scache_ptr_get(unit, scache_handle, TRUE, alloc_size,
    553                                  &scache_ptr, BCM_WB_DEFAULT_VERSION, NULL);
    554     if (rv == BCM_E_NOT_FOUND) {
    555         rv = BCM_E_NONE;
    556     }
    557 
    558     return rv;
    559 }
    560 
    561 #define _BCM_MN_WB_NTYPE_UCAST 0
    562 #define _BCM_MN_WB_NTYPE_MCAST 1
    563 #define _BCM_MN_WB_NTYPE_SCHED 2
    564 
    565 
    566 /* 2 bit node type, 15 bit nid, 15 hw cosq */
    567 #define _BCM_MN_WB_SET_NODE_W1(ntype,nid,hwcosq)    \
    568     (((ntype & 3)) | \
    569      (((nid) & 0x7fff) << 2) | \
    570      (((hwcosq) & 0x7fff) << 17))
    571 
    572 #define _BCM_MN_WB_GET_NODE_TYPE_W1(w1)     ((w1) & 3)
    573 #define _BCM_MN_WB_GET_NODE_ID_W1(w1)       (((w1) >> 2) & 0x7fff)
    574 #define _BCM_MN_WB_GET_NODE_HW_COSQ_W1(w1)  (((w1) >> 17) & 0x7fff)
    575 
    576 
    577 /* 15 bit hw index, 13 bit parent id, 3 bit level, 1 bit wrr_in_use
    578  */
    579 
    580 #define _BCM_MN_WB_SET_NODE_W2(hwindex,parentid,lvl,wrr_in_use) \
    581     ((hwindex & 0x7fff) | \
    582      ((parentid & 0x1fff) << 15) | \
    583      ((lvl & 0x7) << 28) | \
    584      ((wrr_in_use & 0x1) << 31))
    585 
    586 #define _BCM_MN_WB_GET_NODE_HW_INDEX_W2(w1)  ((w1) & 0x7fff) 
    587 #define _BCM_MN_WB_GET_NODE_PARENTID_W2(w1)  (((w1) >> 15) & 0x1fff)
    588 #define _BCM_MN_WB_GET_NODE_LEVEL_W2(w1)     (((w1) >> 28) & 0x7)
    589 #define _BCM_MN_WB_GET_NODE_WRR_IN_USE_W2(w1)   (((w1) >> 31) & 0x1)
    590 
    591 #define _BCM_MN_WB_SET_NODE_W3(gport)    (gport)
    592 #define _BCM_MN_WB_SET_NODE_W4(gport)    (gport)
    593 
    594 /* 15 bit numq, 15 bit cosq, 1 bit dmvoq_en, 1 bit coe_en
    595  */
    596 #define _BCM_MN_WB_SET_NODE_W5(numq,cosq,dmvoq_en,coe_en) \
    597     ((numq & 0x7fff) | \
    598     ((cosq & 0x7fff) << 15) | \
    599     ((dmvoq_en &0x01) << 30) | \
    600     ((coe_en & 0x01) << 31))
    601 
    602 #define _BCM_MN_WB_GET_NODE_NUMQ_W5(w1)      ((w1) & 0x7fff)
    603 #define _BCM_MN_WB_GET_NODE_COSQATTT_W5(w1)  (((w1) >> 15) & 0x7fff)
    604 #define _BCM_MN_WB_GET_NODE_DMVOQ_EN_W5(w1)  (((w1) >> 30) & 0x1)
    605 #define _BCM_MN_WB_GET_NODE_COE_EN_W5(w1)    (((w1) >> 31) & 0x1)
    606 
    607 /* 10 bit base size, 15 bit base_index, 1 bit expand, 4 bit type */
    608 #define _BCM_MN_WB_SET_NODE_W6(base_size,base_index,expand,type) \
    609     ((base_size & 0x3ff) | \
    610      ((base_index & 0x7fff) << 10) | \
    611      ((expand & 0x1) << 25) | \
    612      ((type & 0xf) << 26))
    613 
    614 #define _BCM_MN_WB_GET_BASE_SIZE_W6(w1)   ((w1) & 0x3ff)
    615 #define _BCM_MN_WB_GET_BASE_INDEX_W6(w1)  (((w1) >> 10) & 0x7fff)
    616 #define _BCM_MN_WB_GET_EXPAND_W6(w1)      (((w1) >> 25) & 0x1)
    617 #define _BCM_MN_WB_TYPE_W6(w1)            (((w1) >> 26) & 0xf)
    618 
    619 /* 9 bit remote_modid, 9 bit remote_port.
    620  * Present only if dmvoq bit is set in W6
    621  */
    622 #define _BCM_MN_WB_SET_NODE_W7(remote_modid,remote_port)    \
    623     ((((remote_modid) & 0x1ff)) | \
    624      (((remote_port) & 0x1ff) << 9))
    625 
    626 #define _BCM_MN_WB_GET_NODE_DEST_MODID_W7(w1) ((w1) & 0x1ff)
    627 #define _BCM_MN_WB_GET_NODE_DEST_PORT_W7(w1)  (((w1) >> 9) & 0x1ff)
    628 
    629 /* 14 bit coe base index, 8 bit coe_num_l2 */
    630 #define _BCM_MN_WB_SET_NODE_W8(coe_base_index, coe_num_l2) \
    631        ((coe_base_index & 0x3fff) | \
    632        ((coe_num_l2 & 0xff) << 14))
    633 
    634 #define _BCM_MN_WB_GET_COE_BASE_INDEX_W8(w1) ((w1) & 0x3fff)
    635 #define _BCM_MN_WB_GET_COE_NUM_L2_W8(w1) (((w1) >> 14) & 0xff)
    636 
    637 #define _BCM_MN_NODE_ID(np,np0) (np - np0)
    638 
    639 STATIC void *
    640 _bcm_mn_cosq_alloc_clear(void *cp, unsigned int size, char *description);
    641 
    642 
    643 STATIC int
    644 _bcm_mn_child_level_get(int unit, _bcm_mn_cosq_node_t *node , int *child_level)
    645 {
    646    
    647    if (!node) 
    648    {
    649        return BCM_E_INTERNAL;
    650    }
    651    if (node->level == SOC_MONTEREY_NODE_LVL_ROOT)
    652    {
    653        *child_level = SOC_MONTEREY_NODE_LVL_S1;
    654  
    655    }else if (node->level == SOC_MONTEREY_NODE_LVL_S1) 
    656    {
    657        *child_level = SOC_MONTEREY_NODE_LVL_L0;
    658    }else if (node->level == SOC_MONTEREY_NODE_LVL_L0) 
    659    {
    660        *child_level = SOC_MONTEREY_NODE_LVL_L1;
    661    }else if (node->level == SOC_MONTEREY_NODE_LVL_L1) 
    662    {
    663        *child_level = SOC_MONTEREY_NODE_LVL_L2;
    664    }
    665    return BCM_E_NONE; 
    666 }
    667 /*
    668  * Function:
    669  *     _bcm_mn_cosq_map_alloc_set
    670  * Purpose:
    671  *     Allocate the cosq_map bitmap and 
    672  *     restore  
    673  * Parameters:
    674  *     node       - (IN) cosq_node 
    675  * Returns:
    676  *     BCM_E_XXX
    677  */
    678 STATIC int
    679 _bcm_mn_cosq_map_alloc_set(int unit, _bcm_mn_cosq_node_t *node)
    680 {
    681     _bcm_mn_cosq_node_t *child;
    682     int alloc_size;
    683     int max_nodes = 0; 
    684     int child_level = 0;
    685     
    686     BCM_IF_ERROR_RETURN
    687     (_bcm_mn_child_level_get(unit, node, &child_level));
    688     BCM_IF_ERROR_RETURN
    689     (_bcm_mn_cosq_max_nodes_get(unit, child_level, &max_nodes)); 
    690     if (node->cosq_map == NULL) {
    691         if ( node->numq == -1 ) { 
    692              alloc_size = SHR_BITALLOCSIZE(max_nodes); 
    693         } else { 
    694              alloc_size = SHR_BITALLOCSIZE(node->numq);
    695         }
    696         node->cosq_map = _bcm_mn_cosq_alloc_clear(node->cosq_map, 
    697                                            alloc_size,
    698                                            "cosq_map");
    699         if (node->cosq_map == NULL) {
    700             return BCM_E_MEMORY;
    701         }
    702     }
    703     child = node->child;
    704     while (child != NULL) {
    705         BCM_IF_ERROR_RETURN
    706             (_bcm_mn_cosq_map_index_set(node->cosq_map, 
    707                                          child->attached_to_input, 1));
    708         child = child->sibling;
    709     }
    710 
    711     return BCM_E_NONE;
    712 }
    713 
    714 /*
    715  * Function:
    716  *     _bcm_mn_cosq_map_node_recover 
    717  * Purpose:
    718  *     Used to recover cos_map for S0,S1,L0,L1 levels   
    719  * Parameters:
    720  *     node       - (IN) cosq_node 
    721  * Returns:
    722  *     BCM_E_XXX
    723  */
    724 
    725 STATIC int
    726 _bcm_mn_cosq_map_node_recover(int unit ,_bcm_mn_cosq_node_t *node)
    727 {
    728     if (!node) {
    729         return BCM_E_NONE;
    730     }
    731     if (node->level == SOC_MONTEREY_NODE_LVL_L2) {
    732         return BCM_E_NONE;
    733     }
    734     BCM_IF_ERROR_RETURN(_bcm_mn_cosq_map_alloc_set(unit , node));
    735     BCM_IF_ERROR_RETURN(_bcm_mn_cosq_map_node_recover(unit, node->sibling));
    736     BCM_IF_ERROR_RETURN(_bcm_mn_cosq_map_node_recover(unit, node->child));
    737     return BCM_E_NONE;
    738 }
    739 int
    740 bcm_mn_cosq_reinit(int unit)
    741 {
    742     soc_scache_handle_t scache_handle;
    743     uint8 *scache_ptr;
    744     uint32 *u32_scache_ptr, wval, fval;
    745     uint16 *u16_scache_ptr;
    746     _bcm_mn_cosq_node_t *node;
    747     bcm_port_t port;
    748     int rv, ii, jj, set_index;
    749     _bcm_mn_cosq_node_t *nodes[3];
    750     int xnode_id, stable_size, count, profile_index;
    751     _bcm_mn_mmu_info_t *mmu_info;
    752     uint32 entry[SOC_MAX_MEM_WORDS];
    753     soc_profile_mem_t *profile_mem;
    754     _bcm_mn_pipe_resources_t *res;
    755     soc_mem_t mem;
    756     mmu_wred_config_entry_t qentry;
    757     int alloc_size;
    758     int additional_scache_size = 0;
    759     uint16 recovered_ver = 0;
    760     int index=0;
    761     bcm_pbmp_t all_pbmp;
    762     soc_profile_reg_t *profile_reg;
    763     soc_info_t *si;
    764     bcm_port_t phy_port, mmu_port;
    765     soc_reg_t reg;
    766 	uint32 tmp32;
    767     int dmvoq_en = 0, coe_en = 0;
    768     uint64 rval, index_map;
    769     static const soc_reg_t llfc_cfgr[] = {
    770                 PORT_PFC_CFG0r, PORT_PFC_CFG1r, PORT_PFC_CFG2r
    771     };
    772     int num;
    773     _bcm_mn_cosq_node_t *port_info;
    774 
    775     si = &SOC_INFO(unit);
    776     SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size));
    777     if ((stable_size == 0) || (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit))) { 
    778         /* COSQ warmboot requires extended scache support i.e. level2 warmboot*/  
    779         return BCM_E_NONE;
    780     }
    781 
    782     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_COSQ, 0);
    783     rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 0, &scache_ptr,
    784                                  BCM_WB_DEFAULT_VERSION, &recovered_ver);
    785     if (BCM_FAILURE(rv)) {
    786         return rv;
    787     }
    788 
    789     mmu_info = _bcm_mn_mmu_info[unit];
    790 
    791     if (!mmu_info) {
    792         return BCM_E_INIT;
    793     }
    794 
    795     res = _BCM_MN_PRESOURCES(mmu_info, _MN_XPIPE);
    796     u32_scache_ptr = (uint32*) scache_ptr;
    797 
    798     nodes[0] = &mmu_info->queue_node[0];
    799     nodes[1] = &mmu_info->mc_queue_node[0];
    800     nodes[2] = &mmu_info->sched_node[0];
    801 
    802     for(ii = 0; ii < 3; ii++) {
    803         count = *u32_scache_ptr;
    804         u32_scache_ptr++;
    805         for(jj = 0; jj < count; jj++) {
    806             wval = *u32_scache_ptr;
    807             u32_scache_ptr++;
    808             xnode_id = _BCM_MN_WB_GET_NODE_ID_W1(wval);
    809             node = nodes[ii] + xnode_id;
    810             node->in_use = TRUE;
    811             node->numq = 1;
    812             fval = _BCM_MN_WB_GET_NODE_HW_COSQ_W1(wval);
    813             node->hw_cosq = (fval == 0x7fff)? -1 : fval;
    814 
    815             wval = *u32_scache_ptr;
    816             u32_scache_ptr++;
    817             fval = _BCM_MN_WB_GET_NODE_HW_INDEX_W2(wval);
    818             node->hw_index = (fval == 0x7fff) ? -1 : fval;
    819             fval = _BCM_MN_WB_GET_NODE_PARENTID_W2(wval);
    820             if (fval == 0x1fff) {
    821                 node->parent = NULL;
    822             } else {
    823                 node->parent = &mmu_info->sched_node[fval];
    824                 if (node->parent->child) {
    825                     node->sibling = node->parent->child;
    826                 }
    827                 node->parent->child = node;
    828             }
    829             node->level = _BCM_MN_WB_GET_NODE_LEVEL_W2(wval);
    830             node->wrr_in_use = _BCM_MN_WB_GET_NODE_WRR_IN_USE_W2(wval);
    831 
    832             node->gport = *u32_scache_ptr++;
    833             node->port_gport = *u32_scache_ptr++;
    834 
    835             wval = *u32_scache_ptr;
    836             u32_scache_ptr++;
    837             node->numq = _BCM_MN_WB_GET_NODE_NUMQ_W5(wval);
    838              /* numq of -1 will be recovered as 32767 need to update back as -1  */
    839             if (node->numq == 32767)
    840             {
    841                 node->numq = -1 ;
    842             }
    843             fval = _BCM_MN_WB_GET_NODE_COSQATTT_W5(wval);
    844             node->attached_to_input = (fval == 0x7fff) ? -1 : fval;
    845             dmvoq_en = _BCM_MN_WB_GET_NODE_DMVOQ_EN_W5(wval);
    846             coe_en = _BCM_MN_WB_GET_NODE_COE_EN_W5(wval);
    847 
    848             wval = *u32_scache_ptr;
    849             u32_scache_ptr++;
    850             node->base_size = _BCM_MN_WB_GET_BASE_SIZE_W6(wval);
    851             fval = _BCM_MN_WB_GET_BASE_INDEX_W6(wval);
    852             node->base_index = (fval == 0x7fff) ? -1 : fval;
    853             node->numq_expandable = _BCM_MN_WB_GET_EXPAND_W6(wval);
    854             node->type = _BCM_MN_WB_TYPE_W6(wval);
    855 
    856             if (dmvoq_en) {
    857                 wval = *u32_scache_ptr;
    858                 u32_scache_ptr++;
    859                 fval = _BCM_MN_WB_GET_NODE_DEST_MODID_W7(wval);
    860                 node->remote_modid = (fval == 0x1ff) ? -1 : fval;
    861                 fval = _BCM_MN_WB_GET_NODE_DEST_PORT_W7(wval);
    862                 node->remote_port = (fval == 0x1ff) ? -1 : fval;
    863             }
    864 
    865             if (soc_feature(unit, soc_feature_mmu_hqos_four_level) &&
    866                 (node->level == SOC_MONTEREY_NODE_LVL_S1) &&
    867                 coe_en) {
    868                 wval = *u32_scache_ptr;
    869                 u32_scache_ptr++;
    870                 node->coe_base_index = _BCM_MN_WB_GET_COE_BASE_INDEX_W8(wval);
    871                 if (node->coe_base_index == 16383 ) 
    872                 {
    873                     node->coe_base_index = -1;
    874                 }  
    875                 node->coe_num_l2 = _BCM_MN_WB_GET_COE_NUM_L2_W8(wval);
    876             }
    877 
    878             /*
    879              * Not checking the return value intentionally
    880              * to take care of warmboot case.
    881              */
    882             /* coverity[unchecked_value] */
    883             (void)_bcm_mn_cosq_node_get(unit, node->gport, 0, NULL,
    884                 &node->local_port, NULL, NULL);
    885 
    886             if (node->hw_index != -1) {
    887                 if (node->level == SOC_MONTEREY_NODE_LVL_S1) {
    888                     _bcm_mn_node_index_set(&res->s1_sched_list, 
    889                             node->hw_index, 1);
    890                 } else if (node->level == SOC_MONTEREY_NODE_LVL_L0) {
    891                     _bcm_mn_node_index_set(&res->l0_sched_list, 
    892                             node->hw_index, 1);
    893                     if (IS_MN_HSP_PORT(unit, node->local_port)) {
    894                         _bcm_mn_node_index_set(&res->hsp_l0_sched_list, 
    895                                 node->hw_index, 1);
    896                     }
    897                     if (IS_CPU_PORT(unit, node->local_port)) {
    898                         _bcm_mn_node_index_set(&res->cpu_l0_sched_list, 
    899                                 node->hw_index - _BCM_MN_CPU_PORT_L0_MIN, 1);
    900                     }
    901                 } else if (node->level == SOC_MONTEREY_NODE_LVL_L1) {
    902                     _bcm_mn_node_index_set(&res->l1_sched_list, 
    903                             node->hw_index, 1);
    904                     if (IS_MN_HSP_PORT(unit, node->local_port)) {
    905                         _bcm_mn_node_index_set(&res->hsp_l1_sched_list, 
    906                                 node->hw_index, 1);
    907                     }
    908                 } else if (node->level == SOC_MONTEREY_NODE_LVL_L2) {
    909                     _bcm_mn_node_index_set(&res->l2_queue_list, 
    910                             node->hw_index, 1);
    911                     if (IS_MN_HSP_PORT(unit, node->local_port)) {
    912                         _bcm_mn_node_index_set(&res->hsp_l2_queue_list, 
    913                                 node->hw_index, 1);
    914                     }
    915                 }
    916             }
    917         }
    918     }
    919 
    920     BCM_PBMP_CLEAR(all_pbmp);
    921     BCM_PBMP_ASSIGN(all_pbmp, PBMP_ALL(unit));
    922 
    923     /* Restoring the cosq_map */ 
    924     PBMP_ITER(all_pbmp, port) {
    925         node = NULL;
    926 
    927         /* root node */
    928         port_info = &mmu_info->sched_node[port];
    929         if (port_info && (port_info->gport >= 0)) {
    930             SOC_IF_ERROR_RETURN (
    931                 _bcm_mn_cosq_map_node_recover(unit, port_info));
    932         }
    933     }
    934 
    935     /* Recovery TIME_DOMAINr field and count reference */
    936     alloc_size = _MN_NUM_TIME_DOMAIN * sizeof(_bcm_mn_cosq_time_info_t);
    937     sal_memcpy(&time_domain_mn[0], u32_scache_ptr, alloc_size);
    938     time_domain_mn[0].field = TIME_0f;
    939     time_domain_mn[1].field = TIME_1f;
    940     time_domain_mn[2].field = TIME_2f;
    941     time_domain_mn[3].field = TIME_3f;
    942     u32_scache_ptr += alloc_size / sizeof(uint32);
    943     soc_monterey_shadow_load(unit, &u32_scache_ptr);
    944 
    945     mmu_info->curr_shared_limit = *u32_scache_ptr++;
    946 
    947     u16_scache_ptr = (uint16 *)u32_scache_ptr;
    948 
    949     /* Update IFP_COS_MAP memory profile reference counter */
    950     profile_mem = _bcm_mn_ifp_cos_map_profile[unit];
    951     num = SOC_MEM_SIZE(unit,IFP_COS_MAPm) / _MN_NUM_INTERNAL_PRI;
    952     for (ii = 0; ii < num; ii++) {
    953         for (jj = 0; jj < *u16_scache_ptr; jj++) {
    954             SOC_IF_ERROR_RETURN(
    955                 soc_profile_mem_reference(unit, profile_mem,
    956                                             ii * _MN_NUM_INTERNAL_PRI,
    957                                             _MN_NUM_INTERNAL_PRI));
    958         }
    959         u16_scache_ptr++;
    960     }
    961 
    962     u32_scache_ptr = (uint32 *)u16_scache_ptr;
    963     NUM_COS(unit) = *u32_scache_ptr;
    964 
    965     if (additional_scache_size > 0) {
    966     /* coverity[dead_error_begin] */
    967         BCM_IF_ERROR_RETURN(
    968             soc_scache_realloc(unit, scache_handle, additional_scache_size));
    969     }
    970 
    971     /* Update reference counts for DSCP_TABLE profile*/
    972     PBMP_ITER(all_pbmp, port) {
    973         if (IS_LB_PORT(unit, port)) {
    974             /* Loopback port base starts from 64 */
    975             continue;
    976         }
    977         SOC_IF_ERROR_RETURN(soc_mem_read(unit, PORT_TABm, MEM_BLOCK_ALL,
    978                                           port, &entry));
    979         index = soc_mem_field32_get(unit, PORT_TABm, &entry, TRUST_DSCP_PTRf);
    980 
    981         SOC_IF_ERROR_RETURN(_bcm_dscp_table_entry_reference(unit, index * 64,
    982                                                             64));
    983     }
    984 
    985     /* Update PORT_COS_MAP memory profile reference counter */
    986     profile_mem = _bcm_mn_cos_map_profile[unit];
    987     PBMP_ALL_ITER(unit, port) {
    988         SOC_IF_ERROR_RETURN
    989             (soc_mem_read(unit, COS_MAP_SELm, MEM_BLOCK_ALL, port, &entry));
    990         set_index = soc_mem_field32_get(unit, COS_MAP_SELm, &entry, SELECTf);
    991         SOC_IF_ERROR_RETURN
    992             (soc_profile_mem_reference(unit, profile_mem, set_index * 16, 16));
    993     }
    994     if (SOC_INFO(unit).cpu_hg_index != -1) {
    995         SOC_IF_ERROR_RETURN(soc_mem_read(unit, COS_MAP_SELm, MEM_BLOCK_ALL,
    996                                          SOC_INFO(unit).cpu_hg_index, &entry));
    997         set_index = soc_mem_field32_get(unit, COS_MAP_SELm, &entry, SELECTf);
    998         SOC_IF_ERROR_RETURN
    999             (soc_profile_mem_reference(unit, profile_mem, set_index, 1));
   1000     }
   1001 
   1002     mem = MMU_WRED_CONFIG_X_PIPEm;
   1003     for (ii = soc_mem_index_min(unit, mem);
   1004             ii <= soc_mem_index_max(unit, mem); ii++) {
   1005         BCM_IF_ERROR_RETURN(
   1006                 soc_mem_read(unit, mem, MEM_BLOCK_ALL, ii, &qentry));
   1007             
   1008         profile_index = soc_mem_field32_get(unit, mem, &qentry, PROFILE_INDEXf);
   1009             
   1010         BCM_IF_ERROR_RETURN
   1011             (soc_profile_mem_reference(unit, _bcm_mn_wred_profile[unit],
   1012                                         profile_index, 1));
   1013     }
   1014     
   1015     profile_reg = _bcm_mn_llfc_profile[unit];
   1016     PBMP_PORT_ITER(unit, port) {
   1017         phy_port = si->port_l2p_mapping[port];
   1018         mmu_port = si->port_p2m_mapping[phy_port];
   1019         if (mmu_port == -1) {
   1020             continue;
   1021         }
   1022         reg = llfc_cfgr[mmu_port/32];
   1023         BCM_IF_ERROR_RETURN(soc_reg64_get(unit, reg, 0, 0, &rval));
   1024 
   1025         index_map = soc_reg64_field_get(unit, reg, rval, PROFILE_INDEXf);
   1026         COMPILER_64_SHR(index_map, ((mmu_port % 32) * 2));
   1027         COMPILER_64_TO_32_LO(tmp32, index_map);
   1028         set_index = (tmp32 & 3);
   1029         SOC_IF_ERROR_RETURN
   1030             (soc_profile_reg_reference(unit, profile_reg, set_index * 16, 16));
   1031     }
   1032 
   1033     return BCM_E_NONE;
   1034 }
   1035 
   1036 int
   1037 bcm_mn_cosq_sync(int unit)
   1038 {
   1039     soc_scache_handle_t scache_handle;
   1040     uint8 *scache_ptr;
   1041     uint32 *u32_scache_ptr;
   1042     uint16 *u16_scache_ptr;
   1043     _bcm_mn_cosq_node_t *node;
   1044     int node_list_sizes[3], ii, jj, cosq;
   1045     _bcm_mn_cosq_node_t *nodes[3];
   1046     int xnode_id;  /*, count, pipe; */
   1047     _bcm_mn_mmu_info_t *mmu_info;
   1048     int alloc_size;
   1049     int rv = BCM_E_NONE;
   1050     int ref_count;
   1051     int count;
   1052     int dmvoq_en = 0, coe_en = 0;
   1053     uint32 *psize;
   1054 
   1055     mmu_info = _bcm_mn_mmu_info[unit];
   1056 
   1057     if (!mmu_info) {
   1058         return BCM_E_INIT;
   1059     }
   1060 
   1061     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_COSQ, 0);
   1062     BCM_IF_ERROR_RETURN
   1063         (_bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 0,
   1064                                  &scache_ptr, BCM_WB_DEFAULT_VERSION, NULL));
   1065 
   1066     u32_scache_ptr = (uint32*) scache_ptr;
   1067 
   1068     nodes[0] = &mmu_info->queue_node[0];
   1069     node_list_sizes[0] = _BCM_MN_NUM_L2_UC_LEAVES;
   1070     nodes[1] = &mmu_info->mc_queue_node[0];
   1071     node_list_sizes[1] = _BCM_MN_NUM_L2_MC_LEAVES;
   1072     nodes[2] = &mmu_info->sched_node[0];
   1073     node_list_sizes[2] = _BCM_MN_NUM_TOTAL_SCHEDULERS;
   1074 
   1075     for(ii = 0; ii < 3; ii++) {
   1076         psize = u32_scache_ptr++;
   1077         for(count = 0, jj = 0; jj < node_list_sizes[ii]; jj++) {
   1078             node = nodes[ii] + jj;
   1079             if (node->in_use == FALSE) {
   1080                 continue;
   1081             }
   1082             dmvoq_en = 0;
   1083             coe_en = 0;
   1084             count += 1;
   1085 
   1086             if (node->parent == NULL) {
   1087                 xnode_id = 0x1fff;
   1088             } else {
   1089                 xnode_id = _BCM_MN_NODE_ID(node->parent, mmu_info->sched_node);
   1090             }
   1091             cosq = ((node->attached_to_input == -1) ? 0x7fff : node->attached_to_input);
   1092 
   1093             *u32_scache_ptr++ = _BCM_MN_WB_SET_NODE_W1(ii, jj, 
   1094                                     ((node->hw_cosq == -1) ? 0x7fff : node->hw_cosq));
   1095 
   1096             if ((node->remote_modid != -1) || (node->remote_port != -1)) {
   1097                 dmvoq_en = 1;
   1098             }
   1099             if (soc_feature(unit, soc_feature_mmu_hqos_four_level) && 
   1100                 (node->level == SOC_MONTEREY_NODE_LVL_S1)) { 
   1101                 coe_en = 1;
   1102             }
   1103 
   1104             *u32_scache_ptr++ = _BCM_MN_WB_SET_NODE_W2(
   1105                    (node->hw_index == -1) ? 0x7fff : node->hw_index, xnode_id,
   1106                     node->level, node->wrr_in_use);
   1107 
   1108             *u32_scache_ptr++ = _BCM_MN_WB_SET_NODE_W3(node->gport);
   1109             *u32_scache_ptr++ = _BCM_MN_WB_SET_NODE_W4(node->port_gport);
   1110             *u32_scache_ptr++ = _BCM_MN_WB_SET_NODE_W5(node->numq, cosq, 
   1111                                         dmvoq_en, coe_en);
   1112 
   1113             *u32_scache_ptr++ = _BCM_MN_WB_SET_NODE_W6(
   1114                                     (node->base_size),
   1115                                     ((node->base_index == -1 ) ? 0x7fff : 
   1116                                                         node->base_index),
   1117                                     (node->numq_expandable), (node->type));
   1118 
   1119             if (dmvoq_en) {
   1120                 *u32_scache_ptr++ = _BCM_MN_WB_SET_NODE_W7(
   1121                     (node->remote_modid == -1) ? 0x1ff : node->remote_modid,
   1122                     (node->remote_port == -1) ? 0x1ff : node->remote_port);
   1123             }
   1124 
   1125             if (soc_feature(unit, 
   1126                       soc_feature_mmu_hqos_four_level)) { 
   1127                 if (node->level == SOC_MONTEREY_NODE_LVL_S1) { 
   1128                     *u32_scache_ptr++ = _BCM_MN_WB_SET_NODE_W8(node->coe_base_index,
   1129                                                                   node->coe_num_l2);
   1130                 }
   1131             } 
   1132         }
   1133         *psize = count;
   1134     }
   1135     
   1136     /* Sync TIME_DOMAINr field and count reference */
   1137     alloc_size = _MN_NUM_TIME_DOMAIN * sizeof(_bcm_mn_cosq_time_info_t);
   1138     sal_memcpy(u32_scache_ptr, &time_domain_mn[0], alloc_size);
   1139     u32_scache_ptr += alloc_size / sizeof(uint32);
   1140     soc_monterey_shadow_sync(unit, &u32_scache_ptr);
   1141 
   1142     *u32_scache_ptr++ = mmu_info->curr_shared_limit;
   1143     u16_scache_ptr = (uint16 *)u32_scache_ptr;
   1144 
   1145     for (ii = 0; 
   1146          ii < (SOC_MEM_SIZE(unit, IFP_COS_MAPm) / _MN_NUM_INTERNAL_PRI);
   1147          ii++) {
   1148         rv = soc_profile_mem_ref_count_get(unit, 
   1149                                            _bcm_mn_ifp_cos_map_profile[unit],
   1150                                            ii * _MN_NUM_INTERNAL_PRI,
   1151                                            &ref_count);
   1152         if (!(rv == SOC_E_NOT_FOUND || rv == SOC_E_NONE)) {
   1153             return rv;
   1154         }
   1155         *u16_scache_ptr++ = (uint16)(ref_count & 0xffff);
   1156     }
   1157     /* Update num cosq */
   1158     u32_scache_ptr = (uint32 *)u16_scache_ptr;
   1159     *u32_scache_ptr = NUM_COS(unit);
   1160 
   1161     return BCM_E_NONE;
   1162 }
   1163 
   1164 #endif /* BCM_WARM_BOOT_SUPPORT */
   1165 
   1166 #ifndef BCM_SW_STATE_DUMP_DISABLE 
   1167 /*
   1168  * Function:
   1169  *     bcm_mn_cosq_sw_dump
   1170  * Purpose:
   1171  *     Displays COS Queue information maintained by software.
   1172  * Parameters:
   1173  *     unit - Device unit number
   1174  * Returns:
   1175  *     None
   1176  */
   1177 void
   1178 bcm_mn_cosq_sw_dump(int unit)
   1179 {
   1180 
   1181     return;
   1182 }
   1183 #endif /* BCM_SW_STATE_DUMP_DISABLE */
   1184 
   1185 /*
   1186  * Function:
   1187  *     _bcm_mn_cosq_localport_resolve
   1188  * Purpose:
   1189  *     Resolve GRPOT if it is a local port
   1190  * Parameters:
   1191  *     unit       - (IN) unit number
   1192  *     gport      - (IN) GPORT identifier
   1193  *     local_port - (OUT) local port number
   1194  * Returns:
   1195  *     BCM_E_XXX
   1196  */
   1197 int
   1198 _bcm_mn_cosq_localport_resolve(int unit, bcm_gport_t gport,
   1199                                bcm_port_t *local_port)
   1200 {
   1201     bcm_module_t module;
   1202     bcm_port_t port;
   1203     bcm_trunk_t trunk;
   1204     int id, result;
   1205 
   1206     if (!BCM_GPORT_IS_SET(gport)) {
   1207         if (!SOC_PORT_VALID(unit, gport)) {
   1208             return BCM_E_PORT;
   1209         }
   1210         *local_port = gport;
   1211         return BCM_E_NONE;
   1212     }
   1213 
   1214     BCM_IF_ERROR_RETURN
   1215         (_bcm_esw_gport_resolve(unit, gport, &module, &port, &trunk, &id));
   1216 
   1217     BCM_IF_ERROR_RETURN(_bcm_esw_modid_is_local(unit, module, &result));
   1218     if (result == FALSE) {
   1219         return BCM_E_PARAM;
   1220     }
   1221 
   1222     *local_port = port;
   1223 
   1224     return BCM_E_NONE;
   1225 }
   1226 
   1227 STATIC int
   1228 _bcm_mn_cosq_port_has_ets(int unit, bcm_port_t port)
   1229 {
   1230 /* In Apache it is always ETS mode */
   1231     return TRUE;
   1232 }
   1233 
   1234 /*
   1235  * Function:
   1236  *     _bcm_mn_node_index_get
   1237  * Purpose:
   1238  *     Allocate free index from the given list
   1239  * Parameters:
   1240  *     list       - (IN) bit list
   1241  *     start      - (IN) start index
   1242  *     end        - (IN) end index
   1243  *     count       - (IN) size of queue set
   1244  *     align      - (IN) adjusting the bits
   1245  *     id         - (OUT) start index
   1246  * Returns:
   1247  *     BCM_E_XXX
   1248  */
   1249 STATIC int
   1250 _bcm_mn_node_index_get(SHR_BITDCL *list, int start, int end,
   1251                        int count, int align, int *id)
   1252 {
   1253     int i, j, range_empty;
   1254 
   1255     *id = -1;
   1256 
   1257     if ((align <= 0) || (count == 0)) {
   1258         return BCM_E_PARAM;
   1259     }
   1260 
   1261     if (start & (align - 1)) {
   1262         start = (start + align - 1) & ~(align - 1);
   1263     }
   1264 
   1265     end = end - align + 1;
   1266 
   1267     for (i = start; i < end; i += align) {
   1268         range_empty = 1;
   1269         /* Make sure the j doesn not cross the end */
   1270         for (j = i; ((j < (i + count)) && ( j < end)); j++) {
   1271             if (SHR_BITGET(list, j) != 0) {
   1272                 range_empty = 0;
   1273                 break;
   1274             }
   1275         }
   1276 
   1277         if (range_empty) {
   1278             *id = i;
   1279             return BCM_E_NONE;
   1280         }
   1281     }
   1282     return BCM_E_RESOURCE;
   1283 }
   1284 
   1285 /*
   1286  * Function:
   1287  *     _bcm_mn_node_index_set
   1288  * Purpose:
   1289  *     Mark indices as allocated
   1290  * Parameters:
   1291  *     list       - (IN) bit list
   1292  *     start      - (IN) start index
   1293  *     range      - (IN) range bits
   1294  * Returns:
   1295  *     BCM_E_XXX
   1296  */
   1297 STATIC int
   1298 _bcm_mn_node_index_set(_bcm_mn_cosq_list_t *list, int start, int range)
   1299 {
   1300    if ( range == 0) 
   1301    {    
   1302         return BCM_E_NONE;
   1303    }  
   1304    if ((start < 0) ||
   1305         (range < 0) ||
   1306         ((start + range) > list->count)) {
   1307         return BCM_E_RESOURCE;
   1308    }
   1309 
   1310    SHR_BITSET_RANGE(list->bits, start, range);
   1311 
   1312     return BCM_E_NONE;
   1313 }
   1314 
   1315 /*
   1316  * Function:
   1317  *     _bcm_mn_node_index_clear
   1318  * Purpose:
   1319  *     Mark indices as free
   1320  * Parameters:
   1321  *     list       - (IN) bit list
   1322  *     start      - (IN) start index
   1323  *     range      - (IN) range bits
   1324  * Returns:
   1325  *     BCM_E_XXX
   1326  */
   1327 STATIC int
   1328 _bcm_mn_node_index_clear(_bcm_mn_cosq_list_t *list, int start, int range)
   1329 {    
   1330     if ( range == 0) 
   1331     {    
   1332         return BCM_E_NONE;
   1333     }  
   1334     if ((start < 0) ||
   1335         (range < 0) ||
   1336         ((start + range) > list->count)) {
   1337         return BCM_E_RESOURCE;
   1338     }
   1339 
   1340     SHR_BITCLR_RANGE(list->bits, start, range);
   1341 
   1342     return BCM_E_NONE;
   1343 }
   1344 STATIC int
   1345 _bcm_mn_cosq_max_nodes_get(int unit, soc_monterey_node_lvl_e level,
   1346                            int *id)
   1347 {
   1348     _bcm_mn_mmu_info_t *mmu_info;     
   1349     if ((mmu_info = _bcm_mn_mmu_info[unit]) == NULL) {
   1350         return BCM_E_INIT;
   1351     }
   1352     if (id == NULL) {
   1353         return BCM_E_PARAM;
   1354     }
   1355     if (level == SOC_MONTEREY_NODE_LVL_S1) {
   1356         *id = _BCM_MN_NUM_S1_SCHEDULER_PER_PIPE;
   1357     } else if (level == SOC_MONTEREY_NODE_LVL_L0) {
   1358         *id = _BCM_MN_NUM_L0_SCHEDULER_PER_PIPE;
   1359     } else if (level == SOC_MONTEREY_NODE_LVL_L1) {
   1360         *id = _BCM_MN_NUM_L1_SCHEDULER_PER_PIPE;
   1361     } else if (level == SOC_MONTEREY_NODE_LVL_L2) {
   1362         *id = mmu_info->num_l2_queues + _BCM_MN_NUM_L2_MC_LEAVES;
   1363     }
   1364     return BCM_E_NONE;
   1365 
   1366 }
   1367 /*
   1368  * Function:
   1369  *     _bcm_mn_cosq_alloc_clear
   1370  * Purpose:
   1371  *     Allocate cosq memory and clear
   1372  * Parameters:
   1373  *     size       - (IN) size of memory required
   1374  *     description- (IN) description about the structure
   1375  * Returns:
   1376  *     BCM_E_XXX
   1377  */
   1378 STATIC void *
   1379 _bcm_mn_cosq_alloc_clear(void *cp, unsigned int size, char *description)
   1380 {
   1381     void *block_p;
   1382 
   1383     block_p = (cp) ? cp : sal_alloc(size, description);
   1384 
   1385     if (block_p != NULL) {
   1386         sal_memset(block_p, 0, size);
   1387     }
   1388 
   1389     return block_p;
   1390 }
   1391 
   1392 /*
   1393  * Function:
   1394  *     _bcm_mn_cosq_free_memory
   1395  * Purpose:
   1396  *     Free memory allocated for mmu info members
   1397  * Parameters:
   1398  *     mmu_info       - (IN) MMU info pointer
   1399  * Returns:
   1400  *     BCM_E_XXX
   1401  */
   1402 STATIC void
   1403 _bcm_mn_cosq_free_memory(_bcm_mn_mmu_info_t *mmu_info_p)
   1404 {
   1405     int pipe;
   1406     _bcm_mn_pipe_resources_t *res;
   1407 
   1408 
   1409     if (mmu_info_p == NULL) {
   1410         return;
   1411     }
   1412 
   1413     for (pipe = _MN_XPIPE; pipe < _MN_YPIPE; pipe++) {
   1414         res = _BCM_MN_PRESOURCES(mmu_info_p, pipe);
   1415         if (res->l2_queue_list.bits != NULL) {
   1416             sal_free(res->l2_queue_list.bits);
   1417             res->l2_queue_list.bits = NULL;
   1418         }
   1419         if (res->l1_sched_list.bits != NULL) {
   1420             sal_free(res->l1_sched_list.bits);
   1421             res->l1_sched_list.bits = NULL;
   1422         }
   1423         if (res->l0_sched_list.bits != NULL) {
   1424             sal_free(res->l0_sched_list.bits);
   1425             res->l0_sched_list.bits = NULL;
   1426         }
   1427         if (res->cpu_l0_sched_list.bits != NULL) {
   1428             sal_free(res->cpu_l0_sched_list.bits);
   1429             res->cpu_l0_sched_list.bits = NULL;
   1430         }
   1431         if (res->hsp_l2_queue_list.bits != NULL) {
   1432             sal_free(res->hsp_l2_queue_list.bits);
   1433             res->hsp_l2_queue_list.bits = NULL;
   1434         }
   1435         if (res->hsp_l1_sched_list.bits != NULL) {
   1436             sal_free(res->hsp_l1_sched_list.bits);
   1437             res->hsp_l1_sched_list.bits = NULL;
   1438         }
   1439         if (res->hsp_l0_sched_list.bits != NULL) {
   1440             sal_free(res->hsp_l0_sched_list.bits);
   1441             res->hsp_l0_sched_list.bits = NULL;
   1442         }
   1443         if (res->s1_sched_list.bits != NULL) {
   1444             sal_free(res->s1_sched_list.bits);
   1445             res->s1_sched_list.bits = NULL;
   1446         }
   1447     }
   1448 }
   1449 
   1450 /*
   1451  * Function:
   1452  *     _bcm_mn_cosq_node_get
   1453  * Purpose:
   1454  *     Get internal information of queue group or scheduler type GPORT
   1455  * Parameters:
   1456  *     unit       - (IN) unit number
   1457  *     gport      - (IN) queue group/scheduler GPORT identifier
   1458  *     modid      - (OUT) module identifier
   1459  *     port       - (OUT) port number
   1460  *     id         - (OUT) queue group or scheduler identifier
   1461  *     node       - (OUT) node structure for the specified GPORT
   1462  * Returns:
   1463  *     BCM_E_XXX
   1464  */
   1465 STATIC int
   1466 _bcm_mn_cosq_node_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
   1467                        bcm_module_t *modid, bcm_port_t *port, 
   1468                        int *id, _bcm_mn_cosq_node_t **node)
   1469 {
   1470     _bcm_mn_mmu_info_t *mmu_info;
   1471     _bcm_mn_cosq_node_t *node_base = NULL;
   1472     bcm_module_t modid_out = 0;
   1473     bcm_port_t port_out = 0;
   1474     uint32 encap_id = -1;
   1475     int index;
   1476 
   1477     if ((mmu_info = _bcm_mn_mmu_info[unit]) == NULL) {
   1478         return BCM_E_INIT;
   1479     }
   1480 
   1481     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   1482         BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid_out));
   1483         port_out = BCM_GPORT_UCAST_QUEUE_GROUP_SYSPORTID_GET(gport);
   1484     } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   1485         BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid_out));
   1486         port_out = BCM_GPORT_MCAST_QUEUE_GROUP_SYSPORTID_GET(gport);
   1487     } else if (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport)) {
   1488         BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid_out));
   1489         port_out = (gport >> 16) & 0xff;
   1490     } else if (BCM_GPORT_IS_SCHEDULER(gport)) {
   1491         BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid_out));
   1492         port_out = BCM_GPORT_SCHEDULER_GET(gport) & 0xff;
   1493     } else if (BCM_GPORT_IS_LOCAL(gport)) {
   1494         encap_id = BCM_GPORT_LOCAL_GET(gport);
   1495         port_out = encap_id;
   1496     } else if (BCM_GPORT_IS_MODPORT(gport)) {
   1497         modid_out = SOC_GPORT_MODPORT_MODID_GET(gport);
   1498         port_out = SOC_GPORT_MODPORT_PORT_GET(gport);
   1499         encap_id = port_out;
   1500     } else {
   1501         return BCM_E_PORT;
   1502     }
   1503 
   1504     if (!SOC_PORT_VALID(unit, port_out)) {
   1505         return BCM_E_PORT;
   1506     }
   1507 
   1508     if (port != NULL) {
   1509         *port = port_out;
   1510     }
   1511 #if 0
   1512     if (!_bcm_mn_cosq_port_has_ets(unit, port_out)) {
   1513         return BCM_E_NOT_FOUND;
   1514     }
   1515 #endif
   1516 
   1517     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   1518         encap_id = BCM_GPORT_UCAST_QUEUE_GROUP_QID_GET(gport);
   1519         index = encap_id;
   1520         node_base = mmu_info->queue_node;
   1521     } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   1522         encap_id = BCM_GPORT_MCAST_QUEUE_GROUP_QID_GET(gport);
   1523         index = encap_id;
   1524         node_base = mmu_info->mc_queue_node;
   1525     } else if (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport)) {
   1526         encap_id = BCM_GPORT_UCAST_SUBSCRIBER_QUEUE_GROUP_QID_GET(gport);
   1527         index = encap_id;
   1528         node_base = mmu_info->queue_node;
   1529     } else if (BCM_GPORT_IS_SCHEDULER(gport)) {
   1530         encap_id = (BCM_GPORT_SCHEDULER_GET(gport) >> 8) & 0x3fff;
   1531         index = encap_id;
   1532         node_base = mmu_info->sched_node;
   1533     } else {
   1534         index = encap_id;
   1535         node_base = mmu_info->sched_node;
   1536     }
   1537 
   1538     if (index < 0) {
   1539         return BCM_E_NOT_FOUND;
   1540     }
   1541 
   1542     if (node_base[index].numq == 0) {
   1543         return BCM_E_NOT_FOUND;
   1544     }
   1545 
   1546     if (modid != NULL) {
   1547         *modid = modid_out;
   1548     }
   1549     if (id != NULL) {
   1550         *id = encap_id;
   1551     }
   1552     if (node != NULL) {
   1553         *node = &node_base[index];
   1554         if (*node) {
   1555             _bcm_mn_cosq_node_t *tmp_node;
   1556             tmp_node = *node;
   1557             if (tmp_node->type == _BCM_MN_NODE_SERVICE_UCAST) {
   1558                 *node = &node_base[index + cosq];
   1559                 if (id != NULL) {
   1560                     *id = tmp_node->hw_index;
   1561                 }
   1562             }
   1563         }
   1564  
   1565     }
   1566 
   1567     return BCM_E_NONE;
   1568 }
   1569 
   1570 int
   1571 _bcm_mn_cosq_port_resolve(int unit, bcm_gport_t gport, bcm_module_t *modid,
   1572                           bcm_port_t *port, bcm_trunk_t *trunk_id, int *id,
   1573                           int *qnum)
   1574 {
   1575     _bcm_mn_cosq_node_t *node;
   1576 
   1577     BCM_IF_ERROR_RETURN
   1578         (_bcm_mn_cosq_node_get(unit, gport, 0, modid, port, id, &node));
   1579     *trunk_id = -1;
   1580 
   1581     if (qnum) {
   1582         if (node->hw_index == -1) {
   1583             return BCM_E_PARAM;
   1584         }
   1585         *qnum = node->hw_index;
   1586     }
   1587 
   1588     return BCM_E_NONE;
   1589 }
   1590 
   1591 /*
   1592  * Function:
   1593  *     _bcm_mn_cosq_gport_traverse
   1594  * Purpose:
   1595  *     Walks through the valid COSQ GPORTs and calls
   1596  *     the user supplied callback function for each entry.
   1597  * Parameters:
   1598  *     unit       - (IN) unit number
   1599  *     gport      - (IN)
   1600  *     cb         - (IN) Callback function.
   1601  *     user_data  - (IN) User data to be passed to callback function
   1602  * Returns:
   1603  *     BCM_E_NONE - Success.
   1604  *     BCM_E_XXX
   1605  */
   1606 int
   1607 _bcm_mn_cosq_gport_traverse(int unit, bcm_gport_t gport,
   1608                             bcm_cosq_gport_traverse_cb cb,
   1609                             void *user_data)
   1610 {
   1611     _bcm_mn_cosq_node_t *node;
   1612     uint32 flags = BCM_COSQ_GPORT_SCHEDULER;
   1613     bcm_port_t port, port_out;
   1614     bcm_module_t modid, modid_out;
   1615     bcm_gport_t gport_out;
   1616     int rv = BCM_E_NONE;
   1617 
   1618     BCM_IF_ERROR_RETURN
   1619         (_bcm_mn_cosq_node_get(unit, gport, 0, &modid, &port, NULL, &node));
   1620 
   1621     if (node != NULL) {
   1622         if (!soc_feature(unit, soc_feature_mmu_hqos_four_level) && 
   1623             node->level == SOC_MONTEREY_NODE_LVL_ROOT) 
   1624         {
   1625             node = node->child;
   1626             if (!node) 
   1627             { 
   1628                 return BCM_E_NONE; 
   1629             }
   1630         }
   1631         if (node->level == SOC_MONTEREY_NODE_LVL_L2) {
   1632             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(node->gport)) {
   1633                 flags = BCM_COSQ_GPORT_UCAST_QUEUE_GROUP;
   1634             } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(node->gport)) {
   1635                 flags = BCM_COSQ_GPORT_MCAST_QUEUE_GROUP;
   1636             }
   1637         } else {
   1638             flags = BCM_COSQ_GPORT_SCHEDULER;
   1639         }
   1640         BCM_IF_ERROR_RETURN
   1641             (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, modid, port,
   1642                                     &modid_out, &port_out));
   1643         BCM_GPORT_MODPORT_SET(gport_out, modid_out, port_out);
   1644 
   1645         rv = cb(unit, gport_out, node->numq, flags,
   1646                   node->gport, user_data);
   1647        if (BCM_FAILURE(rv)) {
   1648 #ifdef BCM_CB_ABORT_ON_ERR
   1649            if (SOC_CB_ABORT_ON_ERR(unit)) {
   1650                return rv;
   1651            }
   1652 #endif
   1653        }
   1654     } else {
   1655             return BCM_E_NONE;
   1656     }
   1657 
   1658     if (node->sibling != NULL) {
   1659         _bcm_mn_cosq_gport_traverse(unit, node->sibling->gport, cb, user_data);
   1660     }
   1661 
   1662     if (node->child != NULL) {
   1663         _bcm_mn_cosq_gport_traverse(unit, node->child->gport, cb, user_data);
   1664     }
   1665 
   1666     return BCM_E_NONE;
   1667 }
   1668 
   1669 STATIC int
   1670 _bcm_mn_cosq_child_node_at_input(_bcm_mn_cosq_node_t *node, int cosq,
   1671                                   _bcm_mn_cosq_node_t **child_node)
   1672 {
   1673     _bcm_mn_cosq_node_t *cur_node;
   1674 
   1675     for (cur_node = node->child; cur_node; cur_node = cur_node->sibling) {
   1676         if (cur_node->attached_to_input == (cosq % _BCM_MN_HSP_PORT_MAX_COS)) {
   1677             break;
   1678         }
   1679     }
   1680     if (!cur_node) {
   1681         return BCM_E_NOT_FOUND;
   1682     }
   1683 
   1684     *child_node = cur_node;
   1685 
   1686     return BCM_E_NONE;
   1687 }
   1688 
   1689 STATIC int
   1690 _bcm_mn_cosq_l2_gport(int unit, int port, int cosq,
   1691                        _bcm_mn_node_type_e type, bcm_gport_t *gport,
   1692                        _bcm_mn_cosq_node_t **p_node)
   1693 {
   1694     int i, max;
   1695     _bcm_mn_cosq_node_t *node, *fnode;
   1696     _bcm_mn_mmu_info_t *mmu_info;
   1697     _bcm_mn_cosq_port_info_t *port_info;
   1698     _bcm_mn_pipe_resources_t *res;
   1699 
   1700     mmu_info = _bcm_mn_mmu_info[unit];
   1701     port_info = &mmu_info->port_info[port];
   1702     res = port_info->resources;
   1703     
   1704     max  = 0;
   1705     if ((type == _BCM_MN_NODE_UCAST) || (type == _BCM_MN_NODE_VOQ) ||
   1706         (type == _BCM_MN_NODE_VLAN_UCAST) || (type == _BCM_MN_NODE_VM_UCAST) ||
   1707          (type == _BCM_MN_NODE_SERVICE_UCAST)) {
   1708         max = _BCM_MN_NUM_L2_UC_LEAVES;
   1709         fnode = &res->p_queue_node[0];
   1710     } else if (type == _BCM_MN_NODE_MCAST) {
   1711         max = _BCM_MN_NUM_L2_MC_LEAVES;
   1712         fnode = &res->p_mc_queue_node[0];
   1713     } else {
   1714         return BCM_E_PARAM;
   1715     }
   1716 
   1717     for (i = 0; i < max; i++) {
   1718         node = fnode + i;
   1719         if (node->in_use && (node->local_port == port) &&
   1720             (node->type == type) && (node->hw_cosq == cosq)) {
   1721             if (gport) {
   1722                 *gport = node->gport;
   1723             }
   1724             if (p_node) {
   1725                 *p_node = node;
   1726             }
   1727             return BCM_E_NONE;
   1728         }
   1729     }
   1730     return BCM_E_NOT_FOUND;
   1731 }
   1732 
   1733 /*
   1734  * Function:
   1735  *     _bcm_mn_cosq_index_resolve
   1736  * Purpose:
   1737  *     Find hardware index for the given port/cosq
   1738  * Parameters:
   1739  *     unit       - (IN) unit number
   1740  *     port       - (IN) port number or GPORT identifier
   1741  *     cosq       - (IN) COS queue number
   1742  *     style      - (IN) index style (_BCM_KA_COSQ_INDEX_STYLE_XXX)
   1743  *     local_port - (OUT) local port number
   1744  *     index      - (OUT) result index
   1745  *     count      - (OUT) number of index
   1746  * Returns:
   1747  *     BCM_E_XXX
   1748  */
   1749 int
   1750 _bcm_mn_cosq_index_resolve(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 
   1751                            _bcm_mn_cosq_index_style_t style,                 
   1752                            bcm_port_t *local_port, int *index, int *count)
   1753 {
   1754     _bcm_mn_cosq_node_t *node, *cur_node , *s1_node;
   1755     bcm_port_t resolved_port;
   1756     int resolved_index = -1;
   1757     int id, startq, numq;
   1758     soc_info_t *si;
   1759     int phy_port, mmu_port;
   1760     uint32 entry0[SOC_MAX_MEM_WORDS];
   1761     soc_mem_t mem;
   1762     _bcm_mn_mmu_info_t *mmu_info;
   1763     si = &SOC_INFO(unit);
   1764 
   1765     mmu_info = _bcm_mn_mmu_info[unit];
   1766     if (cosq < -1) {
   1767         return BCM_E_PARAM;
   1768     } else if (cosq == -1) {
   1769         startq = 0;
   1770         numq = NUM_COS(unit);
   1771     } else {
   1772         startq = cosq;
   1773         numq = 1;
   1774     }
   1775 
   1776     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 
   1777         BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) ||
   1778         BCM_GPORT_IS_SCHEDULER(port)) {
   1779         BCM_IF_ERROR_RETURN
   1780             (_bcm_mn_cosq_node_get(unit, port, cosq, NULL, &resolved_port, &id,
   1781                                    &node));
   1782         if (node->attached_to_input < 0) { /* Not resolved yet */
   1783             return BCM_E_NOT_FOUND;
   1784         }
   1785         numq = (node->numq != -1) ? node->numq : 64;
   1786 
   1787     } else if(_BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port)){
   1788          BCM_IF_ERROR_RETURN(
   1789         _bcmi_coe_subport_physical_port_get(unit, port, &resolved_port));
   1790         BCM_IF_ERROR_RETURN
   1791              (_bcm_mn_get_s1_node(unit, port, &s1_node)); 
   1792         node =  &mmu_info->queue_node[s1_node->coe_base_index + startq ]; 
   1793         if (node->attached_to_input < 0) { /* Not resolved yet */
   1794             return BCM_E_NOT_FOUND;
   1795         }
   1796         numq =  _MN_NUM_COS(unit);
   1797     } else {
   1798         /* optionally validate port */
   1799         BCM_IF_ERROR_RETURN
   1800             (_bcm_mn_cosq_localport_resolve(unit, port, &resolved_port));
   1801         if (resolved_port < 0) {
   1802             return BCM_E_PORT;
   1803         }
   1804         node = NULL;
   1805         numq = (IS_CPU_PORT(unit, resolved_port)) ? NUM_CPU_COSQ(unit) : BCM_MN_COS_MAX;
   1806     }
   1807 
   1808     if (startq >= numq) {
   1809         return BCM_E_PARAM;
   1810     }
   1811 
   1812     phy_port = si->port_l2p_mapping[resolved_port];
   1813     mmu_port = si->port_p2m_mapping[phy_port];
   1814 
   1815     switch (style) {
   1816     case _BCM_MN_COSQ_INDEX_STYLE_BUCKET:
   1817         if (node != NULL) {
   1818             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) {
   1819                 resolved_index = node->hw_index;
   1820             } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
   1821                 resolved_index = node->hw_index;
   1822             } else if(_BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port)){
   1823                 resolved_index = node->hw_index;
   1824             } else if (BCM_GPORT_IS_SCHEDULER(port) || BCM_GPORT_IS_MODPORT(port)) {
   1825                 /* resolve the child attached to input cosq */
   1826                 BCM_IF_ERROR_RETURN(
   1827                    _bcm_mn_cosq_child_node_at_input(node, startq, &cur_node));
   1828                 resolved_index = cur_node->hw_index;
   1829             } else {
   1830                 return BCM_E_PARAM;
   1831             }
   1832         } else { /* node == NULL */
   1833             if (IS_CPU_PORT(unit, resolved_port)) {
   1834                 resolved_index = SOC_INFO(unit).port_cosq_base[resolved_port] +
   1835                                  startq;
   1836                 resolved_index = soc_monterey_l2_hw_index(unit, resolved_index, 0);
   1837             } else {
   1838                 resolved_index = soc_monterey_l2_hw_index(unit,
   1839                         si->port_uc_cosq_base[resolved_port] + startq, 1);
   1840                 if (!IS_MN_HSP_PORT(unit, resolved_port)) { 
   1841                      mem = _SOC_MONTEREY_NODE_PARENT_MEM(unit, port, SOC_MONTEREY_NODE_LVL_L2);
   1842                      SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, resolved_index, &entry0));
   1843                      resolved_index = soc_mem_field32_get(unit, mem, entry0, C_PARENTf);
   1844                 }
   1845             }
   1846         }
   1847         break;
   1848 
   1849     case _BCM_MN_COSQ_INDEX_STYLE_QCN:
   1850         if (node != NULL) {
   1851             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) {
   1852                 resolved_index = node->hw_index;
   1853             } else {
   1854                 return BCM_E_PARAM;
   1855             }
   1856         } else { /* node == NULL */
   1857             BCM_IF_ERROR_RETURN(_bcm_mn_cosq_port_has_ets(unit, resolved_port));
   1858             if (IS_CPU_PORT(unit, resolved_port)) {
   1859                 return BCM_E_PARAM;
   1860             } else {
   1861                 resolved_index = soc_monterey_l2_hw_index(unit,
   1862                 si->port_uc_cosq_base[resolved_port] + startq, 1);
   1863             }
   1864         }
   1865         break;
   1866 
   1867     case _BCM_MN_COSQ_INDEX_STYLE_WRED:
   1868         if (node != NULL) {
   1869             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) {
   1870                 resolved_index = node->hw_index + startq;
   1871             } else if (BCM_GPORT_IS_SCHEDULER(port)) {
   1872                 BCM_IF_ERROR_RETURN(
   1873                    _bcm_mn_cosq_child_node_at_input(node, startq, &cur_node));
   1874                 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(cur_node->gport)) {
   1875                     resolved_index = cur_node->hw_index;
   1876                 } else {
   1877                     return BCM_E_PARAM;
   1878                 }
   1879             } else if(_BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port)){
   1880                 resolved_index = node->hw_index ;
   1881             } else if (BCM_GPORT_IS_MODPORT(port)) {
   1882                 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_l2_gport(unit, node->local_port, 
   1883                                    startq, _BCM_MN_NODE_UCAST, NULL, &cur_node));
   1884                 resolved_index = cur_node->hw_index  ;
   1885             } else {
   1886                 return BCM_E_PARAM;
   1887             }
   1888         } else { /* node == NULL */
   1889             BCM_IF_ERROR_RETURN(_bcm_mn_cosq_port_has_ets(unit, resolved_port));
   1890             resolved_index = soc_monterey_l2_hw_index(unit,
   1891                 si->port_uc_cosq_base[resolved_port] + startq, 1);
   1892             numq = 1;
   1893         }
   1894         break;
   1895 
   1896     case _BCM_MN_COSQ_INDEX_STYLE_WRED_PORT:
   1897         resolved_index = _BCM_PORT_SERVICE_POOL + (mmu_port * 4);
   1898         numq = 4;
   1899         break;
   1900 
   1901     case _BCM_MN_COSQ_INDEX_STYLE_SCHEDULER:
   1902         if (node != NULL) {
   1903             if (!BCM_GPORT_IS_SCHEDULER(port)) {
   1904                 return BCM_E_PARAM;
   1905             }
   1906             BCM_IF_ERROR_RETURN(
   1907                 _bcm_mn_cosq_child_node_at_input(node, startq, &cur_node));
   1908             resolved_index = cur_node->hw_index;
   1909         } else { /* node == NULL */
   1910             BCM_IF_ERROR_RETURN(_bcm_mn_cosq_port_has_ets(unit, resolved_port));
   1911             if (IS_CPU_PORT(unit, resolved_port)) {
   1912                 resolved_index = soc_monterey_l2_hw_index(unit,
   1913                 si->port_cosq_base[resolved_port] + startq, 0);
   1914             } else {
   1915                 resolved_index = soc_monterey_l2_hw_index(unit,
   1916                         si->port_uc_cosq_base[resolved_port] + startq, 1);
   1917             }
   1918         }
   1919         break;
   1920 
   1921     case _BCM_MN_COSQ_INDEX_STYLE_COS:
   1922         if (node) {
   1923             if ((BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) ||
   1924                 (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port))) {
   1925                 resolved_index = node->hw_cosq;
   1926             } else if (BCM_GPORT_IS_SCHEDULER(port)) {
   1927                 BCM_IF_ERROR_RETURN(
   1928                    _bcm_mn_cosq_child_node_at_input(node, startq, &cur_node));
   1929                 if (BCM_GPORT_IS_SCHEDULER(cur_node->gport)) {
   1930                     return BCM_E_PARAM;
   1931                 }
   1932                 resolved_index = cur_node->hw_cosq;
   1933             } else if(_BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port)){
   1934                 resolved_index = node->hw_cosq ;
   1935             }
   1936         } else {
   1937             BCM_IF_ERROR_RETURN(_bcm_mn_cosq_port_has_ets(unit, resolved_port));
   1938             resolved_index = startq;
   1939         }
   1940         break;
   1941 
   1942     case _BCM_MN_COSQ_INDEX_STYLE_UCAST_QUEUE:
   1943         if (node) {
   1944             resolved_index = node->hw_index + startq;
   1945             numq = 1;
   1946         } else {
   1947             BCM_IF_ERROR_RETURN(_bcm_mn_cosq_port_has_ets(unit, resolved_port));
   1948             numq = 1;
   1949             resolved_index = soc_monterey_l2_hw_index(unit,
   1950                 si->port_uc_cosq_base[resolved_port] + startq, 1);
   1951         }
   1952         break;
   1953 
   1954     case _BCM_MN_COSQ_INDEX_STYLE_MCAST_QUEUE:
   1955         if (node) {
   1956             resolved_index = node->hw_index + startq;
   1957             numq = 1;
   1958         } else {
   1959             BCM_IF_ERROR_RETURN(_bcm_mn_cosq_port_has_ets(unit, resolved_port));
   1960             numq = 1;
   1961             resolved_index = soc_monterey_l2_hw_index(unit, 
   1962                 si->port_cosq_base[resolved_port] + startq, 0);
   1963         }
   1964         break;
   1965 
   1966     case _BCM_MN_COSQ_INDEX_STYLE_EGR_POOL:
   1967         if ((node != NULL) && (!BCM_GPORT_IS_MODPORT(port))) {
   1968             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) {
   1969                     /* regular unicast queue */
   1970                 resolved_index = soc_monterey_l2_hw_index(unit, node->hw_index + startq, 1);
   1971                 mem = MMU_THDU_XPIPE_Q_TO_QGRP_MAPm;
   1972             } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
   1973                 resolved_index = soc_monterey_l2_hw_index(unit,
   1974                     si->port_cosq_base[resolved_port] + startq, 0) -
   1975                      _BCM_MN_NUM_L2_UC_LEAVES;
   1976                 mem = MMU_THDM_MCQE_QUEUE_CONFIG_0m;
   1977             } else { /* scheduler */
   1978                 return BCM_E_PARAM;
   1979             }
   1980         } else { /* node == NULL */
   1981             if (IS_CPU_PORT(unit, resolved_port) ||
   1982                 IS_LB_PORT(unit, resolved_port)) {
   1983                 return BCM_E_PARAM;
   1984             }
   1985             numq = si->port_num_cosq[resolved_port];
   1986             if (startq >= numq) {
   1987                 return BCM_E_PARAM;
   1988             }
   1989             resolved_index = soc_monterey_l2_hw_index(unit, 
   1990 	                    si->port_cosq_base[resolved_port] + startq, 0) - 
   1991                             _BCM_MN_NUM_L2_UC_LEAVES ; 
   1992             mem = MMU_THDM_MCQE_QUEUE_CONFIG_0m;
   1993         }
   1994 
   1995         SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, resolved_index,
   1996                             entry0));
   1997 
   1998         resolved_index = soc_mem_field32_get(unit, mem, entry0, Q_SPIDf);
   1999 
   2000         break;
   2001      case _BCM_MN_COSQ_INDEX_STYLE_UC_EGR_POOL:
   2002         if (IS_CPU_PORT(unit, resolved_port) ||
   2003             IS_LB_PORT(unit, resolved_port)) {
   2004             return BCM_E_PARAM;
   2005         }
   2006 
   2007         numq = si->port_num_uc_cosq[resolved_port];
   2008         if (startq >= numq) {
   2009             return BCM_E_PARAM;
   2010         }
   2011 
   2012         resolved_index = soc_monterey_l2_hw_index(unit,
   2013                 si->port_uc_cosq_base[resolved_port] + startq, 1);
   2014         mem = MMU_THDU_XPIPE_Q_TO_QGRP_MAPm;
   2015 
   2016         SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, resolved_index,
   2017                             entry0));
   2018 
   2019         resolved_index = soc_mem_field32_get(unit, mem, entry0, Q_SPIDf);
   2020         break;
   2021 
   2022     case _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_UCAST:
   2023         if (node) {
   2024             resolved_index = node->hw_index + startq;
   2025             resolved_index -= soc_monterey_l2_hw_index(unit,
   2026                 si->port_uc_cosq_base[resolved_port], 1);
   2027             numq = 1;
   2028         } else {
   2029             BCM_IF_ERROR_RETURN(_bcm_mn_cosq_port_has_ets(unit, resolved_port));
   2030             numq = 1;
   2031             resolved_index = startq;
   2032         }
   2033         break;
   2034 
   2035     case _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_MCAST:
   2036         if (node) {
   2037             resolved_index = node->hw_index + startq;
   2038             resolved_index -= soc_monterey_l2_hw_index(unit,
   2039                 si->port_cosq_base[resolved_port], 0);
   2040             numq = 1;
   2041         } else {
   2042             BCM_IF_ERROR_RETURN(_bcm_mn_cosq_port_has_ets(unit, resolved_port));
   2043             numq = 1;
   2044             resolved_index = startq;
   2045         }
   2046         break;
   2047     case _BCM_MN_COSQ_INDEX_STYLE_UCAST_QUEUE_GROUP:
   2048         if (IS_CPU_PORT(unit, resolved_port) ||
   2049             IS_LB_PORT(unit, resolved_port)) {
   2050             return BCM_E_PARAM;
   2051         }
   2052         if (node) {
   2053             resolved_index = node->hw_index + startq;
   2054             numq = 1;
   2055         } else {
   2056             /* Not support -1 for queue group index resolving, as group may not consecutive */
   2057             if (cosq == -1) {
   2058                 return BCM_E_PARAM;
   2059             }
   2060             numq = 1;
   2061             resolved_index = si->port_uc_cosq_base[resolved_port] + startq;
   2062         }
   2063         mem = MMU_THDU_XPIPE_Q_TO_QGRP_MAPm;
   2064         SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL,
   2065                             resolved_index, entry0));
   2066         if (soc_mem_field32_get(unit, mem, entry0, QGROUP_VALIDf)) {
   2067             resolved_index = soc_mem_field32_get(unit, mem, entry0, QGROUPf);
   2068         } else {
   2069             return BCM_E_NOT_FOUND;
   2070         }
   2071         break;
   2072     default:
   2073         return BCM_E_INTERNAL;
   2074     }
   2075 
   2076     if (local_port != NULL) {
   2077         *local_port = resolved_port;
   2078     }
   2079     if (index != NULL) {
   2080         *index = resolved_index;
   2081     }
   2082     if (count != NULL) {
   2083         *count = (cosq == -1) ? numq : 1;
   2084     }
   2085 
   2086     return BCM_E_NONE;
   2087 }
   2088 
   2089 STATIC int _bcm_mn_cosq_min_child_index(_bcm_mn_cosq_node_t *child, int lvl, int uc)
   2090 {
   2091     int min_index = -1;
   2092 
   2093     if ((lvl == SOC_MONTEREY_NODE_LVL_L2) && (uc)) {
   2094         while (child) {
   2095             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(child->gport)) {
   2096                 if (min_index == -1) {
   2097                     min_index = child->hw_index;
   2098                 }
   2099                 
   2100                 if (child->hw_index < min_index) {
   2101                     min_index = child->hw_index;
   2102                 }
   2103             }
   2104             child = child->sibling;
   2105         }
   2106     } else if ((lvl == SOC_MONTEREY_NODE_LVL_L2) && (!uc)) {
   2107         while (child) {
   2108             if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(child->gport)) {
   2109                 if (min_index == -1) {
   2110                     min_index = child->hw_index;
   2111                 }
   2112                 
   2113                 if (child->hw_index < min_index) {
   2114                     min_index = child->hw_index;
   2115                 }
   2116             }
   2117             child = child->sibling;
   2118         }
   2119     } else {
   2120         while (child) {
   2121             if (min_index == -1) {
   2122                 min_index = child->hw_index;
   2123             }
   2124             
   2125             if (child->hw_index < min_index) {
   2126                 min_index = child->hw_index;
   2127             }
   2128             child = child->sibling;
   2129         }
   2130     }
   2131 
   2132     return min_index;
   2133 }
   2134 
   2135 STATIC int
   2136 _bcm_mn_child_state_check(int unit, bcm_port_t gport,
   2137                            bcm_cos_queue_t cosq, int ets_mode)
   2138 {
   2139     _bcm_mn_cosq_node_t *node, *child_node = NULL;
   2140     bcm_port_t local_port;
   2141     int level, sch_index, empty = 0;
   2142     int rv = BCM_E_NONE;
   2143     soc_timeout_t timeout;
   2144     uint32 timeout_val;
   2145     uint32 entry[SOC_MAX_MEM_WORDS];
   2146     soc_mem_t mem = INVALIDm;
   2147     static const soc_mem_t memx[] = {
   2148         INVALIDm,
   2149         LLS_L0_CHILD_STATE1m,
   2150         LLS_L1_CHILD_STATE1m,
   2151         LLS_L2_CHILD_STATE1m
   2152     };
   2153 
   2154     /* Timeout val = Static for now. Need to quantify the max wait time */
   2155     timeout_val = 2000000;
   2156 
   2157     BCM_IF_ERROR_RETURN
   2158         (_bcm_mn_cosq_localport_resolve(unit, gport, &local_port));
   2159 
   2160     if (ets_mode & (!IS_MN_HSP_PORT(unit, local_port))) {
   2161         BCM_IF_ERROR_RETURN
   2162             (_bcm_mn_cosq_node_get(unit, gport, 0, NULL,
   2163                                     &local_port, NULL, &node));
   2164 
   2165         /* Get the Child node for the Given Gport */
   2166         rv = _bcm_mn_cosq_child_node_at_input(node, cosq, &child_node);
   2167 
   2168         if ((!child_node) || (rv == BCM_E_NOT_FOUND)) {
   2169             /* No Child present */
   2170             return BCM_E_NONE;
   2171         }
   2172 
   2173         BCM_IF_ERROR_RETURN
   2174             (_bcm_mn_cosq_localport_resolve(unit, gport, &local_port));
   2175 
   2176         level = child_node->level;
   2177         sch_index = child_node->hw_index;
   2178 
   2179         /* Child State Check is NOT necessary for Non-L0/L1/L2 levels */
   2180         if ((level < SOC_MONTEREY_NODE_LVL_L0) || (level > SOC_MONTEREY_NODE_LVL_L2)) {
   2181             /* Sanity for Node's level should be done in the caller */
   2182             return BCM_E_NONE;
   2183         }
   2184 
   2185         mem = memx[level]; 
   2186 
   2187         if (mem == INVALIDm) {
   2188             return BCM_E_INTERNAL;
   2189         }
   2190 
   2191         soc_timeout_init(&timeout, timeout_val, 0);
   2192 
   2193         for(;;) {
   2194             BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL,
   2195                                              sch_index, entry));
   2196             empty = 0;
   2197             if (soc_timeout_check(&timeout)) {
   2198                 LOG_ERROR(BSL_LS_BCM_COMMON,
   2199                           (BSL_META_U(unit,
   2200                                       "ERROR: Timeout during Child lists Not zero\n")));
   2201                 return BCM_E_BUSY;
   2202             }
   2203             empty += soc_mem_field32_get(unit, mem, &entry, C_ACTIVE_0f);
   2204             empty += soc_mem_field32_get(unit, mem, &entry, C_ON_MIN_LIST_0f);
   2205             empty += soc_mem_field32_get(unit, mem, &entry, C_NOT_EMPTY_0f);
   2206 
   2207             if (!empty) {
   2208                 break;
   2209             }
   2210         }
   2211     } else {
   2212         /* TBD: Non-ETS mode not supported. May not be possible to support the same on HSP queues */
   2213         return BCM_E_NONE;
   2214     }
   2215 
   2216     return BCM_E_NONE;
   2217 }
   2218 
   2219 STATIC int
   2220 _bcm_mn_cosq_node_queue_state_check(int unit, 
   2221         _bcm_mn_cosq_node_t *node, int ets_mode)
   2222 {
   2223     int cosq = 0;
   2224     
   2225     if (node == NULL) {
   2226         return BCM_E_PARAM;
   2227     }
   2228 
   2229     for (cosq = 0; cosq < node->numq; cosq++) {
   2230         BCM_IF_ERROR_RETURN
   2231             (_bcm_mn_child_state_check(unit, node->gport,
   2232                                           cosq, ets_mode));
   2233     }
   2234 
   2235     if ((node->level <= SOC_MONTEREY_NODE_LVL_L1) &&
   2236         (node->child != NULL)) {
   2237         BCM_IF_ERROR_RETURN
   2238             (_bcm_mn_cosq_node_queue_state_check(unit,
   2239                                  node->child,ets_mode));
   2240     }
   2241         
   2242     if (node->sibling != NULL) {
   2243 
   2244         BCM_IF_ERROR_RETURN
   2245             (_bcm_mn_cosq_node_queue_state_check(unit,
   2246                                node->sibling,ets_mode));
   2247     }
   2248 
   2249     return BCM_E_NONE;
   2250 }
   2251 
   2252 int 
   2253 _bcm_mn_cosq_port_queue_state_check(int unit, bcm_port_t gport)
   2254 {
   2255     bcm_port_t local_port;
   2256     int   ets_mode;
   2257     _bcm_mn_cosq_node_t *node;
   2258 
   2259     BCM_IF_ERROR_RETURN
   2260         (_bcm_mn_cosq_localport_resolve(unit, gport, &local_port));
   2261     ets_mode = _bcm_mn_cosq_port_has_ets(unit, local_port);
   2262     if (!ets_mode) {
   2263         return BCM_E_NONE;
   2264     }
   2265     
   2266     BCM_IF_ERROR_RETURN
   2267         (bcm_esw_port_gport_get(unit, local_port,
   2268                                          &gport));
   2269 
   2270     BCM_IF_ERROR_RETURN
   2271         (_bcm_mn_cosq_node_get(unit, gport, 0, NULL, 
   2272                                   NULL, NULL, &node));
   2273     
   2274     BCM_IF_ERROR_RETURN
   2275         (_bcm_mn_cosq_node_queue_state_check(unit,
   2276                                     node,ets_mode));
   2277     return BCM_E_NONE;
   2278 }
   2279 
   2280 
   2281 /*
   2282  * Function:
   2283  * _bcm_mn_mmu_rx_enable_set
   2284  * Purpose:
   2285  *     enable/disable mmu rx traffic from the gport.
   2286  * Parameters:
   2287  *     unit       - (IN) unit number
   2288  *     gport      - (IN) GPORT identifier
   2289  *     enable     - (IN) enable/disable
   2290  * Returns:
   2291  *     BCM_E_XXX
   2292  */
   2293 STATIC int
   2294 _bcm_mn_mmu_rx_enable_set(int unit, bcm_port_t local_port,
   2295                            int enable)
   2296 {
   2297     uint32 rval;
   2298 
   2299     /* Disable/Enable INPUT_PORT_RX to the port */
   2300     SOC_IF_ERROR_RETURN
   2301         (soc_reg32_get(unit, THDI_INPUT_PORT_XON_ENABLESr,
   2302                        local_port, 0, &rval));
   2303 
   2304     if (!enable) {
   2305         soc_reg_field_set(unit, THDI_INPUT_PORT_XON_ENABLESr, &rval,
   2306                 INPUT_PORT_RX_ENABLEf,
   2307                 0);
   2308     } else {
   2309         soc_reg_field_set(unit, THDI_INPUT_PORT_XON_ENABLESr, &rval,
   2310                 INPUT_PORT_RX_ENABLEf,
   2311                 1);
   2312     }
   2313 
   2314     SOC_IF_ERROR_RETURN
   2315         (soc_reg32_set(unit, THDI_INPUT_PORT_XON_ENABLESr,
   2316                       local_port, 0, rval));
   2317 
   2318     return BCM_E_NONE;
   2319 }
   2320 
   2321 STATIC int
   2322 _bcm_mn_attach_node_in_hw(int unit, _bcm_mn_cosq_node_t *node)
   2323 {
   2324     int local_port, fc = 0, fmc = 0;
   2325     _bcm_mn_cosq_node_t *child_node;
   2326     int num_spri = 0, first_sp_child = 0, first_sp_mc_child;
   2327     uint32 ucmap = 0, spmap = 0;
   2328     soc_monterey_sched_type_t sched_type;
   2329 
   2330     local_port = node->local_port;
   2331  
   2332     if (node->level == SOC_MONTEREY_NODE_LVL_ROOT) {
   2333         return 0;
   2334     } else if (node->level == SOC_MONTEREY_NODE_LVL_L2) {
   2335         fc = _bcm_mn_cosq_min_child_index(node->parent->child, SOC_MONTEREY_NODE_LVL_L2, 1);
   2336         if (fc < 0) {
   2337             fc = 0;
   2338         }
   2339         fmc = _bcm_mn_cosq_min_child_index(node->parent->child, SOC_MONTEREY_NODE_LVL_L2, 0);
   2340         if (fmc < 0) {
   2341             fmc = _BCM_MN_NUM_L2_UC_LEAVES;
   2342         }
   2343     } else {
   2344         fc = _bcm_mn_cosq_min_child_index(node->parent->child, node->level, 0);
   2345         fmc = 0;
   2346     }
   2347 
   2348     /* If node is scheduler, reset the scheduler and attach it to the parent.*/
   2349     BCM_IF_ERROR_RETURN(
   2350         soc_monterey_cosq_set_sched_parent(unit, local_port, node->level, 
   2351                                       node->hw_index, node->parent->hw_index, 1));
   2352 
   2353     sched_type = _soc_monterey_port_sched_type_get(unit, local_port);
   2354 
   2355     if (sched_type == SOC_MONTEREY_SCHED_LLS) {
   2356         if (node->parent->level != SOC_MONTEREY_NODE_LVL_ROOT) { 
   2357             BCM_IF_ERROR_RETURN(
   2358                     soc_monterey_cosq_get_sched_child_config(unit, local_port,
   2359                         node->parent->level,
   2360                         node->parent->hw_index,
   2361                         &num_spri, &first_sp_child,
   2362                         &first_sp_mc_child, &ucmap, &spmap));
   2363         }
   2364         /* set the node by default in WRR mode with wt=1 */
   2365         BCM_IF_ERROR_RETURN(soc_monterey_cosq_set_sched_config(unit,
   2366                         local_port, node->parent->level,
   2367                         node->parent->hw_index, node->hw_index,
   2368                         num_spri, fc, fmc, ucmap, spmap,
   2369                         SOC_MONTEREY_SCHED_MODE_WRR, 1));
   2370     } 
   2371 
   2372 
   2373     if (node->child) {
   2374         child_node = node->child;
   2375         while (child_node) {
   2376             BCM_IF_ERROR_RETURN(_bcm_mn_attach_node_in_hw(unit, child_node));
   2377             child_node = child_node->sibling;
   2378         }
   2379     }
   2380 
   2381     return BCM_E_NONE;
   2382 }
   2383 /*
   2384  * Function:
   2385  *     _bcm_mn_cosq_map_index_get
   2386  * Purpose:
   2387  *     Allocate free index from the given list
   2388  * Parameters:
   2389  *     list       - (IN) bit list
   2390  *     start      - (IN) start index
   2391  *     end        - (IN) end index
   2392  *     id         - (OUT) start index
   2393  * Returns:
   2394  *     BCM_E_XXX
   2395  */
   2396 STATIC int
   2397 _bcm_mn_cosq_map_index_get(SHR_BITDCL *list, int start, int end, int *id)
   2398 {
   2399     int i;
   2400 
   2401     for (i = start; i < end; i++) {
   2402         if (SHR_BITGET(list, i) != 0) {
   2403             continue;
   2404         }
   2405         *id  =  i;
   2406         return BCM_E_NONE;
   2407     }
   2408 
   2409     return BCM_E_RESOURCE;
   2410 }
   2411 
   2412 /*
   2413  * Function:
   2414  *     _bcm_mn_cosq_map_index_clear
   2415  * Purpose:
   2416  *     Mark indices as free
   2417  * Parameters:
   2418  *     list       - (IN) bit list
   2419  *     start      - (IN) start index
   2420  *     range      - (IN) range bits
   2421  * Returns:
   2422  *     BCM_E_XXX
   2423  */
   2424 STATIC int
   2425 _bcm_mn_cosq_map_index_clear(SHR_BITDCL *list, int start, int range)
   2426 {
   2427     SHR_BITCLR_RANGE(list, start, range);
   2428     return BCM_E_NONE;
   2429 }
   2430 
   2431 /*
   2432  * Function:
   2433  *     _bcm_mn_cosq_map_index_is_set
   2434  * Purpose:
   2435  *     Check index is allocated
   2436  * Parameters:
   2437  *     list       - (IN) bit list
   2438  *     index      - (IN) index
   2439  * Returns:
   2440  *     BCM_E_XXX
   2441  */
   2442 STATIC int
   2443 _bcm_mn_cosq_map_index_is_set(SHR_BITDCL *list, int index)
   2444 {
   2445     if (SHR_BITGET(list, index) != 0) {
   2446         return TRUE;
   2447     }
   2448 
   2449     return FALSE;
   2450 }
   2451 /*
   2452  * Function:
   2453  *     _bcm_mn_cosq_node_resolve
   2454  * Purpose:
   2455  *     Resolve queue number in the specified scheduler tree and its subtree
   2456  * Parameters:
   2457  *     unit       - (IN) unit number
   2458  *     node       - (IN) node structure for the specified scheduler node
   2459  *     cosq       - (IN) COS queue to attach to
   2460  * Returns:
   2461  *     BCM_E_XXX
   2462  */
   2463 STATIC int
   2464 _bcm_mn_cosq_node_resolve(int unit, _bcm_mn_cosq_node_t *node,
   2465                           bcm_cos_queue_t cosq)
   2466 {
   2467     _bcm_mn_cosq_node_t *cur_node, *parent;
   2468     _bcm_mn_cosq_port_info_t *port_info;
   2469     _bcm_mn_pipe_resources_t * res;
   2470     _bcm_mn_mmu_info_t *mmu_info;
   2471     _bcm_mn_cosq_list_t *list;
   2472     int numq, id = -1 , prev_base = -1, rv;
   2473     int valid_index_lo, valid_index_hi;
   2474     bcm_port_t port;
   2475     int alloc_size;
   2476     int phy_port, mmu_port;
   2477     int max_nodes = 0;
   2478     uint32 rval = 0;
   2479     uint32 mc_group_mode = 0;
   2480 
   2481     if ((parent = node->parent) == NULL) {
   2482         /* Not attached, should never happen */
   2483         return BCM_E_NOT_FOUND;
   2484     }
   2485 
   2486     if (parent->numq == 0 || parent->numq < -1) {
   2487         return BCM_E_PARAM;
   2488     }
   2489 
   2490     port = node->local_port;
   2491 
   2492     BCM_IF_ERROR_RETURN
   2493         (_bcm_mn_cosq_max_nodes_get(unit, node->level, &max_nodes));
   2494     if (parent->cosq_map == NULL) {
   2495         if (parent->numq == -1) {
   2496             alloc_size = SHR_BITALLOCSIZE(max_nodes);
   2497         } else {
   2498             alloc_size = SHR_BITALLOCSIZE(parent->numq);
   2499         }
   2500         parent->cosq_map = _bcm_mn_cosq_alloc_clear(parent->cosq_map,
   2501                 alloc_size,
   2502                 "cosq_map");
   2503         if (parent->cosq_map == NULL) {
   2504             return BCM_E_MEMORY;
   2505         }
   2506     }
   2507    if (cosq < 0) {
   2508        BCM_IF_ERROR_RETURN
   2509            (_bcm_mn_cosq_map_index_get(parent->cosq_map,
   2510                                        0, 
   2511                                        parent->numq == -1 ?
   2512                                        max_nodes: parent->numq, &id));
   2513         BCM_IF_ERROR_RETURN
   2514             (_bcm_mn_cosq_map_index_set(parent->cosq_map, id, 1));
   2515         node->attached_to_input = id;
   2516     } else {
   2517         if (_bcm_mn_cosq_map_index_is_set(parent->cosq_map,
   2518                     cosq) == TRUE) {
   2519             return BCM_E_EXISTS;
   2520         }
   2521         if (cosq > ((parent->numq == -1) ? max_nodes : parent->numq)) {
   2522             return BCM_E_PARAM;
   2523         }
   2524         BCM_IF_ERROR_RETURN
   2525             (_bcm_mn_cosq_map_index_set(parent->cosq_map, cosq, 1));
   2526         node->attached_to_input = cosq;
   2527     } 
   2528 
   2529     mmu_info = _bcm_mn_mmu_info[unit];
   2530     port_info = &mmu_info->port_info[port];
   2531     res = port_info->resources;
   2532     numq = (parent->numq == -1) ? 1 : parent->numq;
   2533     phy_port = SOC_INFO(unit).port_l2p_mapping[port];
   2534     mmu_port = SOC_INFO(unit).port_p2m_mapping[phy_port];
   2535     /* On Monterey mmu_port no for CPU is 65 but use 66 for node 
   2536      * allocation and use 65 for loopback node allocation */
   2537     if (IS_CPU_PORT(unit, port)) {
   2538         mmu_port++;
   2539     } else if (IS_LB_PORT(unit, port)) {
   2540         mmu_port--;
   2541     }
   2542     switch (parent->level) {
   2543         case SOC_MONTEREY_NODE_LVL_ROOT:
   2544             list = &res->s1_sched_list;
   2545             if (IS_MN_HSP_PORT(unit, port)) {
   2546                 list = &res->hsp_l0_sched_list;
   2547             }
   2548             if (parent->numq_expandable && parent->base_index >= 0 &&
   2549                     parent->base_size != parent->numq) {
   2550                 _bcm_mn_node_index_clear(list, parent->base_index, 
   2551                         parent->base_size);
   2552                 prev_base = parent->base_index;
   2553                 parent->base_index =  -1;
   2554             }
   2555             if (IS_MN_HSP_PORT(unit, port)) {
   2556                 valid_index_lo = _BCM_MN_HSP_L0_INDEX(unit, mmu_port, 0);
   2557                 valid_index_hi = _BCM_MN_HSP_L0_INDEX(unit, (mmu_port + 1),
   2558                         0);
   2559             } else {
   2560                 valid_index_lo = 0;
   2561                 valid_index_hi = _BCM_MN_NUM_S1_SCHEDULER_PER_PIPE;
   2562             }
   2563 
   2564             if (((parent->base_index < 0) && (node->attached_to_input < numq))
   2565                         || (parent->numq == -1)) {
   2566                rv = _bcm_mn_node_index_get(list->bits, valid_index_lo, 
   2567                         valid_index_hi, numq, 1, &id);
   2568                 if (rv) {
   2569                     return rv;
   2570                 }
   2571 
   2572                 _bcm_mn_node_index_set(list, id, numq);
   2573                 if (parent->numq != -1) {
   2574                     parent->base_index = id;
   2575                     node->hw_index = parent->base_index + node->attached_to_input;
   2576                     parent->base_size = numq;
   2577                     if ((prev_base >= 0) && (prev_base != id)) {
   2578                         for (cur_node = parent->child; cur_node; 
   2579                                 cur_node = cur_node->sibling) {
   2580                             if (cur_node->attached_to_input >= 0) {
   2581                                 cur_node->hw_index = parent->base_index + 
   2582                                     cur_node->attached_to_input;
   2583                                 BCM_IF_ERROR_RETURN(_bcm_mn_attach_node_in_hw(unit, cur_node));
   2584                             }
   2585                         }
   2586                     }
   2587                 } else {
   2588                     node->hw_index = id;
   2589                 }
   2590             } else if (node->attached_to_input >= numq) {
   2591                 rv = _bcm_mn_node_index_get(list->bits, valid_index_lo, 
   2592                         valid_index_hi, 1, 1, &id);
   2593                 if (rv) {
   2594                     return rv;
   2595                 }
   2596                 _bcm_mn_node_index_set(list, id, 1);
   2597                 node->hw_index = id;
   2598 
   2599             } else {
   2600                 node->hw_index = parent->base_index + node->attached_to_input;
   2601             }
   2602             node->hw_cosq = node->attached_to_input;
   2603             node->wrr_in_use = 1;
   2604 
   2605             break;
   2606 
   2607         case SOC_MONTEREY_NODE_LVL_S1:
   2608             if (IS_MN_HSP_PORT(unit, port)) {
   2609                 return BCM_E_PARAM;
   2610             }
   2611             list = &res->l0_sched_list;
   2612             if (parent->numq_expandable && parent->base_index >= 0 &&
   2613                     parent->base_size != parent->numq) {
   2614                 _bcm_mn_node_index_clear(list, parent->base_index, 
   2615                         parent->base_size);
   2616                 prev_base = parent->base_index;
   2617                 parent->base_index =  -1;
   2618             }
   2619             valid_index_lo = 0;
   2620             valid_index_hi = _BCM_MN_NUM_L0_SCHEDULER_PER_PIPE;
   2621             if (IS_CPU_PORT(unit, port)) {
   2622                 list = &res->cpu_l0_sched_list;
   2623                 valid_index_lo = 0;
   2624                 valid_index_hi = _BCM_MN_CPU_PORT_L0_MAX - _BCM_MN_CPU_PORT_L0_MIN;
   2625             }
   2626 
   2627             if (((parent->base_index < 0) && (node->attached_to_input < numq))
   2628                         || (parent->numq == -1)) {
   2629                 if (_BCM_DEFAULT_LLS_IS_SET(mmu_info)) {
   2630                     rv = _bcm_mn_node_index_get(list->bits, valid_index_lo, 
   2631                             valid_index_hi, numq, _BCM_MN_START_INDEX_ALIGN_PFC,
   2632                             &id);
   2633                 } else {
   2634                     rv = _bcm_mn_node_index_get(list->bits, valid_index_lo, 
   2635                             valid_index_hi, numq, _BCM_MN_START_INDEX_ALIGN_DEFAULT,
   2636                             &id);
   2637                 }
   2638                 if (rv) {
   2639                     return rv;
   2640                 }
   2641 
   2642                 _bcm_mn_node_index_set(list, id, numq);
   2643                 if (IS_CPU_PORT(unit, port)) {
   2644                     id += _BCM_MN_CPU_PORT_L0_MIN; 
   2645                 }
   2646                 if (parent->numq != -1) {
   2647                     parent->base_index = id;
   2648                     node->hw_index = parent->base_index + node->attached_to_input;
   2649                     parent->base_size = numq;
   2650                     if ((prev_base >= 0) && (prev_base != id)) {
   2651                         for (cur_node = parent->child; cur_node; 
   2652                                 cur_node = cur_node->sibling) {
   2653                             if (cur_node->attached_to_input >= 0) {
   2654                                 cur_node->hw_index = parent->base_index + 
   2655                                     cur_node->attached_to_input;
   2656                                 BCM_IF_ERROR_RETURN(_bcm_mn_attach_node_in_hw(unit, cur_node));
   2657                             }
   2658                         }
   2659                     }
   2660                 } else {
   2661                     node->hw_index = id;
   2662                 }
   2663             } else if (node->attached_to_input >= numq) {
   2664                 rv = _bcm_mn_node_index_get(list->bits, valid_index_lo, 
   2665                         valid_index_hi, 1, 1, &id);
   2666                 if (rv) {
   2667                     return rv;
   2668                 }
   2669                 _bcm_mn_node_index_set(list, id, 1);
   2670                 node->hw_index = id;
   2671             } else {
   2672                 node->hw_index = parent->base_index + node->attached_to_input;
   2673             }
   2674             node->hw_cosq = node->attached_to_input;
   2675 
   2676             break;
   2677 
   2678 
   2679         case SOC_MONTEREY_NODE_LVL_L0:
   2680             if (IS_MN_HSP_PORT(unit, port)) {
   2681                 if (node->attached_to_input >= _BCM_MN_HSP_PORT_MAX_L1) {
   2682                     return BCM_E_PARAM;
   2683                 }
   2684                 
   2685                 if ((parent->hw_index % _BCM_MN_HSP_PORT_MAX_L0) == 0) {
   2686                     /* L0.0 could only be attached by MC nodes */
   2687                     if (node->type == _BCM_MN_NODE_MCAST) {
   2688                         SOC_IF_ERROR_RETURN(
   2689                             READ_HSP_SCHED_PORT_CONFIGr(unit, port, &rval));
   2690                         mc_group_mode  = soc_reg_field_get(
   2691                                             unit, HSP_SCHED_PORT_CONFIGr, 
   2692                                             rval, MC_GROUP_MODEf);
   2693                         /* check mc group mode and the node offset */
   2694                         if ((!mc_group_mode) ||
   2695                             (((node->hw_index -_BCM_MN_NUM_L2_UC_LEAVES_PER_PIPE) % _BCM_MN_HSP_PORT_MAX_L1) >=
   2696                              _BCM_MN_HSP_PORT_MAX_COS)) {
   2697                             return BCM_E_PARAM;
   2698                         }
   2699                         break;
   2700                     } else {
   2701                         if (!IS_SPECIAL_PORT(unit, port)) {
   2702                             return BCM_E_PARAM;
   2703                         }
   2704                     }
   2705                 }
   2706 
   2707                 list = &res->hsp_l1_sched_list;
   2708                 valid_index_lo = _BCM_MN_HSP_L1_INDEX(unit, mmu_port, 0);
   2709                 valid_index_hi = _BCM_MN_HSP_L1_INDEX(unit, (mmu_port + 1),
   2710                         0);
   2711                 BCM_IF_ERROR_RETURN(_bcm_mn_node_index_get(list->bits, valid_index_lo, 
   2712                             valid_index_hi, 1, 1, &id));
   2713                 if (parent->base_index == -1) {
   2714                     parent->base_index = id;
   2715                 }
   2716                 node->hw_index = id;
   2717 
   2718                 if ((node->hw_index % _BCM_MN_HSP_PORT_MAX_L1) >= 8) {
   2719                     if ((parent->hw_index % _BCM_MN_HSP_PORT_MAX_L0) != 4) {
   2720                         return BCM_E_PARAM;
   2721                     }
   2722                 } else {
   2723                     if ((parent->hw_index % _BCM_MN_HSP_PORT_MAX_L0) == 4) {
   2724                         return BCM_E_PARAM;
   2725                     }
   2726                 }
   2727                 _bcm_mn_node_index_set(list, id, 1);
   2728             } else {
   2729                 list = &res->l1_sched_list;
   2730                 if (((parent->base_index < 0) && (node->attached_to_input < numq))
   2731                         || (parent->numq == -1)) {
   2732                     if (_BCM_DEFAULT_LLS_IS_SET(mmu_info)) {
   2733                         BCM_IF_ERROR_RETURN(_bcm_mn_node_index_get(list->bits, 0, 
   2734                                     _BCM_MN_NUM_L1_SCHEDULER_PER_PIPE, numq,
   2735                                     _BCM_MN_START_INDEX_ALIGN_PFC, &id));
   2736                     } else {
   2737                         BCM_IF_ERROR_RETURN(_bcm_mn_node_index_get(list->bits, 0, 
   2738                                     _BCM_MN_NUM_L1_SCHEDULER_PER_PIPE, numq,
   2739                                     _BCM_MN_START_INDEX_ALIGN_DEFAULT, &id));
   2740                     }
   2741 
   2742                     _bcm_mn_node_index_set(list, id, numq);
   2743                     parent->base_size = numq;
   2744                     if (parent->base_index == -1) {
   2745                         parent->base_index = id;
   2746                     }
   2747                     if (parent->numq != -1) {
   2748                         node->hw_index = parent->base_index + node->attached_to_input;
   2749                     } else {
   2750                         node->hw_index = id;
   2751                     }
   2752                 } else if (node->attached_to_input >= numq) {
   2753 
   2754                     BCM_IF_ERROR_RETURN(_bcm_mn_node_index_get(list->bits, 0, 
   2755                             _BCM_MN_NUM_L1_SCHEDULER_PER_PIPE, 1, 1, &id));
   2756                     _bcm_mn_node_index_set(list, id, 1);
   2757                     node->hw_index = id;
   2758                 } else {
   2759                     node->hw_index = parent->base_index + node->attached_to_input;
   2760                 }
   2761             }
   2762             node->hw_cosq = node->attached_to_input;
   2763 
   2764             break;
   2765 
   2766         case SOC_MONTEREY_NODE_LVL_L1:
   2767             if (IS_MN_HSP_PORT(unit, port)) {
   2768                 uint32     rval = 0;
   2769                 uint32     mc_group_mode = 0;
   2770                 SOC_IF_ERROR_RETURN(
   2771                     READ_HSP_SCHED_PORT_CONFIGr(unit, port, &rval));
   2772                 mc_group_mode  = soc_reg_field_get(unit, HSP_SCHED_PORT_CONFIGr,
   2773                                                    rval, MC_GROUP_MODEf);
   2774                 if (mc_group_mode &&
   2775                     ((node->hw_index % _BCM_MN_HSP_PORT_MAX_L1) <
   2776                      _BCM_MN_HSP_PORT_MAX_COS)) {
   2777                     if (node->attached_to_input >= 1) {
   2778                         return BCM_E_PARAM;
   2779                     }
   2780                     if (node->type == _BCM_MN_NODE_MCAST) {
   2781                         return BCM_E_PARAM;
   2782                     }
   2783                 } else {
   2784                     if (!IS_SPECIAL_PORT(unit, port)) {
   2785                         if (node->attached_to_input >= _BCM_MN_HSP_PORT_MAX_L2_PER_L1) {
   2786                             return BCM_E_PARAM;
   2787                         }
   2788                         if ((node->sibling) &&
   2789                             (node->type == node->sibling->type)) {
   2790                              return BCM_E_PARAM;
   2791                         }
   2792                     }
   2793                 }
   2794             }
   2795             if ((node->hw_index == -1) && 
   2796                     (node->type != _BCM_MN_NODE_VOQ)) {
   2797                 return BCM_E_PARAM;
   2798             } else if (node->type == _BCM_MN_NODE_VOQ) {
   2799                 if (parent->base_index < 0) {
   2800                     BCM_IF_ERROR_RETURN(
   2801                             _bcm_mn_node_index_get(res->l2_queue_list.bits,
   2802                                 res->num_base_queues,
   2803                                _BCM_MN_NUM_L2_UC_LEAVES_PER_PIPE  , 
   2804                                _MN_NUM_COS(unit), 
   2805                                 _MN_NUM_COS(unit), &id));
   2806                     /* The following logic is to make sure the id is always
   2807                      *  multiple of 8 
   2808                      */
   2809                     while ( id % 8 != 0) {
   2810                         id = ((id + 8) & 0xfffffff8);
   2811                         if (id >  _BCM_MN_NUM_L2_UC_LEAVES_PER_PIPE ) {
   2812                             return BCM_E_RESOURCE;
   2813                         }
   2814                         BCM_IF_ERROR_RETURN(
   2815                                 _bcm_mn_node_index_get(res->l2_queue_list.bits, id,
   2816                                     _BCM_MN_NUM_L2_UC_LEAVES_PER_PIPE, 
   2817                                     NUM_COS(unit), 
   2818                                     NUM_COS(unit), &id));
   2819                     }
   2820                     _bcm_mn_node_index_set(&res->l2_queue_list, id, 
   2821                             (parent->numq == -1) ? _MN_NUM_COS(unit) : parent->numq);
   2822                     parent->base_index = id ;
   2823                     node->hw_index = parent->base_index;
   2824                     node->hw_cosq = node->hw_index %
   2825                                 ((parent->numq == -1) ? _MN_NUM_COS(unit) : parent->numq);
   2826                 } else {
   2827                     node->hw_index = parent->base_index + 
   2828                         node->attached_to_input;
   2829                     node->hw_cosq = node->hw_index % NUM_COS(unit);
   2830                 }
   2831             } else if((node->hw_index != -1) && (parent->base_index < 0)) {
   2832                 parent->base_index = node->hw_index;
   2833             }
   2834             break;
   2835 
   2836         case SOC_MONTEREY_NODE_LVL_L2:
   2837             /* passthru */
   2838         default:
   2839             return BCM_E_PARAM;
   2840 
   2841     }
   2842 
   2843     BCM_IF_ERROR_RETURN(_bcm_mn_attach_node_in_hw(unit, node));
   2844     return BCM_E_NONE;
   2845 }
   2846 
   2847 STATIC int
   2848 _bcm_mn_detach_node_in_hw(int unit, _bcm_mn_cosq_node_t *node)
   2849 {
   2850     int local_port;
   2851 
   2852     local_port = node->local_port;
   2853 
   2854     if (!IS_MN_HSP_PORT(unit, local_port)) {
   2855         BCM_IF_ERROR_RETURN(
   2856             _bcm_mn_cosq_sched_parent_child_set(unit,
   2857                 local_port, node->parent->level, node->parent->hw_index,
   2858                 node->hw_index, SOC_TD2_SCHED_MODE_WRR, 1, node));
   2859     }
   2860     
   2861     return BCM_E_NONE;
   2862 }
   2863 
   2864 /*
   2865  * Function:
   2866  *     _bcm_mn_cosq_clear_child_list
   2867  * Purpose:
   2868  *     Reset the child list to 0. To be called when deleting the node.
   2869  * Parameters:
   2870  *     unit       - (IN) unit number
   2871  *     node       - (IN) node structure for the specified scheduler node
   2872  * Returns:
   2873  *     BCM_E_XXX
   2874  */
   2875 STATIC int
   2876 _bcm_mn_cosq_clear_child_list(int unit, _bcm_mn_cosq_node_t *node)
   2877 {
   2878     _bcm_mn_mmu_info_t *mmu_info;
   2879     _bcm_mn_pipe_resources_t * res;
   2880     _bcm_mn_cosq_port_info_t *port_info;
   2881     _bcm_mn_cosq_list_t *list;
   2882     int start_index = 0, numq = 0;
   2883     int port;
   2884 
   2885     mmu_info = _bcm_mn_mmu_info[unit];
   2886     BCM_IF_ERROR_RETURN
   2887         (_bcm_mn_cosq_node_get(unit, node->gport, 0, NULL, &port, NULL, NULL));
   2888 
   2889     port_info = &mmu_info->port_info[port];
   2890     res = port_info->resources;
   2891 
   2892     list = NULL;
   2893     switch (node->level) {
   2894         case SOC_MONTEREY_NODE_LVL_ROOT:
   2895             if (IS_MN_HSP_PORT(unit, port)) {
   2896                 list = &res->hsp_l0_sched_list;
   2897                 start_index = node->base_index;
   2898                 numq = (node->numq == -1) ?
   2899                         _BCM_MN_HSP_PORT_MAX_L0 : node->numq;
   2900             }
   2901             break;
   2902         default:
   2903             return BCM_E_NONE;
   2904     }
   2905 
   2906     if(list){
   2907         _bcm_mn_node_index_clear(list, start_index, numq);
   2908     }
   2909     return BCM_E_NONE;
   2910 }
   2911 /*
   2912  * Function:
   2913  *     _bcm_mn_cosq_node_unresolve
   2914  * Purpose:
   2915  *     Unresolve queue number in the specified scheduler tree and its subtree
   2916  * Parameters:
   2917  *     unit       - (IN) unit number
   2918  *     node       - (IN) node structure for the specified scheduler node
   2919  *     cosq       - (IN) COS queue to attach to
   2920  * Returns:
   2921  *     BCM_E_XXX
   2922  */
   2923 STATIC int
   2924 _bcm_mn_cosq_node_unresolve(int unit, _bcm_mn_cosq_node_t *node, 
   2925                              bcm_cos_queue_t cosq)
   2926 {
   2927     _bcm_mn_cosq_node_t *parent;
   2928     _bcm_mn_mmu_info_t *mmu_info;
   2929     _bcm_mn_pipe_resources_t * res;
   2930     _bcm_mn_cosq_port_info_t *port_info;
   2931     _bcm_mn_cosq_list_t *list;
   2932     int numq = 1, port;
   2933     int hw_index;
   2934 
   2935     if (node->attached_to_input < 0) {
   2936         /* Has been unresolved already */
   2937         return BCM_E_NONE;
   2938     }
   2939 
   2940     parent = node->parent;
   2941 
   2942     if (!parent) {
   2943         return BCM_E_PARAM;
   2944     }
   2945 
   2946     mmu_info = _bcm_mn_mmu_info[unit];
   2947 
   2948     BCM_IF_ERROR_RETURN
   2949         (_bcm_mn_cosq_node_get(unit, node->gport, 0, NULL, &port, NULL, NULL));
   2950 
   2951     port_info = &mmu_info->port_info[port];
   2952     res = port_info->resources;
   2953 
   2954     list = NULL;
   2955 
   2956     switch (parent->level) {
   2957         case SOC_MONTEREY_NODE_LVL_ROOT:
   2958             if (IS_MN_HSP_PORT(unit, port)) {
   2959                 list = &res->hsp_l0_sched_list;
   2960             } else {
   2961                 list = &res->s1_sched_list;
   2962             }
   2963             break;
   2964 
   2965         case SOC_MONTEREY_NODE_LVL_S1:
   2966             if (IS_MN_HSP_PORT(unit, port)) {
   2967                 return BCM_E_PARAM;
   2968             } else if (IS_CPU_PORT(unit, port)) {
   2969                 list = &res->cpu_l0_sched_list;
   2970             } else {
   2971                 list = &res->l0_sched_list;
   2972             }
   2973             break;
   2974 
   2975         case SOC_MONTEREY_NODE_LVL_L0:
   2976             if (IS_MN_HSP_PORT(unit, port)) {
   2977                 list = &res->hsp_l1_sched_list;
   2978             } else {
   2979 
   2980                 list = &res->l1_sched_list;
   2981             }
   2982             break;
   2983 
   2984         case SOC_MONTEREY_NODE_LVL_L1:
   2985             break;
   2986 
   2987         case SOC_MONTEREY_NODE_LVL_L2:
   2988             /* passthru */
   2989         default:
   2990             return BCM_E_PARAM;
   2991 
   2992     }
   2993 
   2994     if ((list) && (node->attached_to_input >= 8)) {
   2995         hw_index = node->hw_index;
   2996         if (IS_CPU_PORT(unit, port)) {
   2997             hw_index = node->hw_index - _BCM_MN_CPU_PORT_L0_MIN;
   2998         }
   2999         _bcm_mn_node_index_clear(list, hw_index, numq);
   3000     } else if((list) && (IS_MN_HSP_PORT(unit, port))){
   3001         _bcm_mn_node_index_clear(list, node->hw_index, 1);
   3002     }
   3003     BCM_IF_ERROR_RETURN
   3004         (_bcm_mn_cosq_map_index_clear(node->parent->cosq_map,
   3005                                        node->attached_to_input , 1));
   3006     node->attached_to_input = -1;
   3007 
   3008     BCM_IF_ERROR_RETURN(_bcm_mn_detach_node_in_hw(unit, node));
   3009     return BCM_E_NONE;
   3010 }
   3011 
   3012 /*
   3013  * Function:
   3014  *     _bcm_mn_port_enqueue_set
   3015  * Purpose:
   3016  *     Enable or Disable the enqueing the packets to the port
   3017  * Parameters:
   3018  *     unit       - (IN) unit number
   3019  *     gport      - (IN) gport of the port 
   3020  *     enable     - (IN) TRUE to enable
   3021  *                      FALSE to disable
   3022  * Returns:
   3023  *     BCM_E_XXX
   3024  */
   3025 
   3026 int
   3027 _bcm_mn_port_enqueue_set(int unit, bcm_port_t gport, int enable)
   3028 {
   3029     bcm_port_t local_port;
   3030    
   3031     BCM_IF_ERROR_RETURN
   3032         (_bcm_mn_cosq_localport_resolve(unit, gport, &local_port));
   3033 
   3034     SOC_IF_ERROR_RETURN(
   3035         soc_monterey_port_mmu_tx_enable_set(unit, local_port, enable));
   3036     SOC_IF_ERROR_RETURN(
   3037         _bcm_mn_mmu_rx_enable_set(unit, local_port, enable));
   3038 
   3039     return BCM_E_NONE;
   3040 }
   3041 /*
   3042  * Function:
   3043  *     _bcm_mn_port_enqueue_get
   3044  * Purpose:
   3045  *      Getting the enqueing state of the port 
   3046  * Parameters:
   3047  *     unit       - (IN) unit number
   3048  *     gport      - (IN) gport of the port 
   3049  *     enable     - (IN) TRUE to enable
   3050  *                      FALSE to disable
   3051  * Returns:
   3052  *     BCM_E_XXX
   3053  */
   3054 
   3055 int
   3056 _bcm_mn_port_enqueue_get(int unit, bcm_port_t gport,
   3057                           int *enable)
   3058 {
   3059     uint64 rval64;
   3060     int mmu_port, phy_port, i, reg_grp = 0;
   3061     int rv = BCM_E_NONE;
   3062     bcm_port_t local_port;
   3063     soc_info_t *si;
   3064     soc_reg_t reg_tmp;
   3065     soc_reg_t reg[3][2] = {
   3066         {
   3067             THDU_OUTPUT_PORT_RX_ENABLE0_64r,
   3068             THDU_OUTPUT_PORT_RX_ENABLE1_64r
   3069         },
   3070         {
   3071             MMU_THDM_DB_PORTSP_RX_ENABLE0_64r,
   3072             MMU_THDM_DB_PORTSP_RX_ENABLE1_64r
   3073         },
   3074         {
   3075             MMU_THDM_MCQE_PORTSP_RX_ENABLE0_64r,
   3076             MMU_THDM_MCQE_PORTSP_RX_ENABLE1_64r
   3077         }
   3078     };
   3079     int max_reg = 3;
   3080 
   3081     BCM_IF_ERROR_RETURN
   3082         (_bcm_mn_cosq_localport_resolve(unit, gport, &local_port));
   3083 
   3084     si = &SOC_INFO(unit);
   3085 
   3086     phy_port = si->port_l2p_mapping[local_port];
   3087     mmu_port = si->port_p2m_mapping[phy_port];
   3088 
   3089     COMPILER_64_ZERO(rval64);
   3090     if (mmu_port  < 64 ) {
   3091         mmu_port &= 0x3f;
   3092     } else {
   3093         mmu_port &= 0xf;
   3094         reg_grp = 1;
   3095     }
   3096 
   3097     for (i = 0; i < max_reg; i++) {
   3098         reg_tmp = reg[i][reg_grp];
   3099 
   3100         SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg_tmp, REG_PORT_ANY, 0, &rval64));
   3101 
   3102         if (COMPILER_64_BITTEST(rval64 , mmu_port)) {
   3103             *enable = TRUE;
   3104         } else {
   3105             *enable = FALSE;
   3106         }
   3107     }
   3108     return rv;
   3109 }
   3110 
   3111 /*
   3112  * Function:
   3113  *       _bcm_mn_get_s1_node  
   3114  * Purpose:
   3115  *       finds the s1 node for given subport 
   3116  * Parameters:
   3117  *     unit       - (IN) unit number
   3118  *     subport      - (IN)gport of the subport 
   3119  *     s1_node     - (OUT) pointer to the s1 node 
   3120  * Returns:
   3121  *     BCM_E_XXX
   3122  */
   3123 int _bcm_mn_get_s1_node(int unit, bcm_gport_t subport,
   3124                       _bcm_mn_cosq_node_t **s1_node) 
   3125 {
   3126 
   3127    int local_port = 0;
   3128    _bcm_mn_cosq_node_t *port_node;
   3129    _bcm_mn_cosq_node_t *child_node;
   3130    _bcm_mn_mmu_info_t *mmu_info;
   3131    int s1_found = 0; 
   3132    if (!s1_node)
   3133    {
   3134        return BCM_E_INTERNAL; 
   3135    }
   3136    if (!soc_feature(unit, 
   3137                     soc_feature_mmu_hqos_four_level)) { 
   3138         return BCM_E_PARAM; 
   3139    }
   3140    mmu_info = _bcm_mn_mmu_info[unit];
   3141    if(!(BCM_GPORT_IS_SET(subport) &&
   3142       _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, subport))) {
   3143         return BCM_E_PARAM; 
   3144    }
   3145     BCM_IF_ERROR_RETURN
   3146     (_bcmi_coe_subport_physical_port_get(unit, subport, &local_port));
   3147     port_node = &mmu_info->sched_node[local_port];
   3148     if (!port_node->in_use) { 
   3149          return BCM_E_INTERNAL; 
   3150     }
   3151     child_node = port_node->child;
   3152     while (child_node) { 
   3153            if((child_node->port_gport == subport))
   3154            {
   3155                s1_found = 1 ; 
   3156                break; 
   3157            }
   3158            child_node = child_node->sibling; 
   3159     }
   3160     if (!s1_found) 
   3161     {
   3162         return BCM_E_NOT_FOUND; 
   3163     }
   3164     *s1_node = child_node; 
   3165     return BCM_E_NONE; 
   3166 }
   3167 
   3168 /*
   3169  * Function:
   3170  *       _bcm_mn_allocate_coe_queues  
   3171  * Purpose:
   3172  *        allocates deallocated l2 queues for given subport 
   3173  * Parameters:
   3174  *     unit       - (IN) unit number
   3175  *     s1_node      - (IN) subport s1 node  
   3176  *     enable     - (IN) flag to enable/disable 
   3177  * Returns:
   3178  *     BCM_E_XXX
   3179  */
   3180 int _bcm_mn_allocate_coe_queues(int unit ,_bcm_mn_cosq_node_t *s1_node,
   3181                            int enable)
   3182 {
   3183     int id = 0;
   3184     int pipe = 0 ;
   3185     _bcm_mn_pipe_resources_t *res;
   3186     _bcm_mn_mmu_info_t *mmu_info;
   3187 
   3188     mmu_info = _bcm_mn_mmu_info[unit];
   3189     pipe = 0;
   3190     res = _BCM_MN_PRESOURCES(mmu_info, pipe);
   3191 
   3192     if (enable) { 
   3193     /* The following logic is to make sure the id is always
   3194      *  multiple of 8 
   3195      */
   3196         BCM_IF_ERROR_RETURN(
   3197         _bcm_mn_node_index_get(res->l2_queue_list.bits,
   3198                                res->num_base_queues,
   3199                                _BCM_MN_NUM_L2_UC_LEAVES_PER_PIPE  , 
   3200                                _MN_NUM_COS(unit), 
   3201                                _MN_NUM_COS(unit), &id));
   3202         while (id % 8 != 0) {
   3203                id = ((id + 8) & 0xfffffff8);
   3204                if (id >  _BCM_MN_NUM_L2_UC_LEAVES_PER_PIPE ) {
   3205                    return BCM_E_RESOURCE;
   3206                }
   3207                BCM_IF_ERROR_RETURN(
   3208                _bcm_mn_node_index_get(res->l2_queue_list.bits, id,
   3209                                       _BCM_MN_NUM_L2_UC_LEAVES_PER_PIPE, 
   3210                                       NUM_COS(unit), 
   3211                                       NUM_COS(unit), &id));
   3212         }
   3213          _bcm_mn_node_index_set(&res->l2_queue_list, id, 
   3214                                 _MN_NUM_COS(unit));
   3215          s1_node->coe_base_index = id; 
   3216     } else 
   3217     {
   3218          _bcm_mn_node_index_clear(&res->l2_queue_list, id, 
   3219                                   _MN_NUM_COS(unit));
   3220          s1_node->coe_base_index = -1; 
   3221     }
   3222     return BCM_E_NONE; 
   3223 }
   3224 
   3225 /*
   3226  * Function:
   3227  *       _bcm_mn_coe_queue_offset_add  
   3228  * Purpose:
   3229  *       Programs the offset in voq_mod_map and voq_port_map table  
   3230  * Parameters:
   3231  *     unit       - (IN) unit number
   3232  *     subport      - (IN) subport gport 
   3233  *     queue_id     - (IN) base queue_id for the subport 
   3234  * Returns:
   3235  *     BCM_E_XXX
   3236  */
   3237 int _bcm_mn_coe_queue_offset_add(int unit, int queue_id,
   3238                             bcm_gport_t subport)
   3239 {
   3240     bcm_module_t modid = 0;
   3241     bcm_port_t port  = 0;
   3242     voq_port_map_entry_t *voq_port_map_entries = NULL;
   3243     voq_mod_map_entry_t voq_mod_map;
   3244     int rv = BCM_E_NONE;
   3245     void *entries[1];
   3246     int port_offset = 0 ;
   3247     int vpm_idx_old = 0 ; 
   3248     int baseq_old = 0 ; 
   3249     uint32 profile = 0 ;
   3250     bcm_trunk_t trunk_id;
   3251     int id;
   3252     int port_base = 0;
   3253     uint64 rval;
   3254     int local_port = 0 ;
   3255      BCM_IF_ERROR_RETURN(
   3256      _bcm_esw_gport_resolve(unit, subport, &modid, &port, &trunk_id, &id));
   3257      BCM_IF_ERROR_RETURN
   3258     (_bcmi_coe_subport_physical_port_get(unit, subport, &local_port));
   3259     /* program the voq port profiles. */
   3260     voq_port_map_entries = sal_alloc(sizeof(voq_port_map_entry_t)*128, 
   3261                                         "voq port map entries");
   3262     if (!voq_port_map_entries) {
   3263         goto fail;
   3264     }
   3265     sal_memset(voq_port_map_entries, 0, sizeof(voq_port_map_entry_t)*128);
   3266     entries[0] = voq_port_map_entries;
   3267     rv = READ_VOQ_MOD_MAPm(unit, MEM_BLOCK_ALL, modid, &voq_mod_map);
   3268     if (rv) {
   3269         goto fail;
   3270     }     
   3271     BCM_IF_ERROR_RETURN(READ_ING_COS_MODE_64r(unit, local_port, &rval));
   3272     port_base = soc_reg64_field32_get(unit, ING_COS_MODE_64r, rval, 
   3273                                   BASE_QUEUE_NUM_0f);
   3274     if (!soc_mem_field32_get(unit, VOQ_MOD_MAPm, 
   3275                              &voq_mod_map, VOQ_VALIDf)) {
   3276         port_offset = 1;
   3277         soc_mem_field32_set(unit, VOQ_PORT_MAPm, &voq_port_map_entries[port],
   3278                             VOQ_PORT_OFFSETf, port_offset);
   3279         soc_mem_field32_set(unit, VOQ_MOD_MAPm, &voq_mod_map, 
   3280                              VOQ_MOD_OFFSETf, queue_id - 1 - port_base );
   3281         soc_mem_field32_set(unit, VOQ_MOD_MAPm, &voq_mod_map, 
   3282                              VOQ_VALIDf, 1);
   3283     } else {
   3284         vpm_idx_old = _MN_VPM_ENTRIES_PER_SET *
   3285                       soc_mem_field32_get(unit, VOQ_MOD_MAPm, &voq_mod_map,
   3286                                           VOQ_MOD_PORT_PROFILE_INDEXf);
   3287         rv = soc_profile_mem_get(unit, _bcm_mn_voq_port_map_profile[unit], 
   3288                                  vpm_idx_old, _MN_VPM_ENTRIES_PER_SET, entries );
   3289                                  
   3290         if (!(rv == SOC_E_NOT_FOUND || rv == SOC_E_NONE)) {
   3291             goto fail;
   3292         }
   3293 
   3294         baseq_old = soc_mem_field32_get(unit, VOQ_MOD_MAPm,
   3295                                        &voq_mod_map,VOQ_MOD_OFFSETf);
   3296          
   3297         port_offset = (queue_id - baseq_old - port_base) & 0x3FFF;
   3298         soc_mem_field32_set(unit, VOQ_PORT_MAPm, &voq_port_map_entries[port],
   3299                                 VOQ_PORT_OFFSETf, port_offset);
   3300         rv =soc_profile_mem_delete(unit, _bcm_mn_voq_port_map_profile[unit], 
   3301                               vpm_idx_old); 
   3302         if (!(rv == SOC_E_NOT_FOUND || rv == SOC_E_NONE)) {
   3303             goto fail;
   3304         }
   3305     }
   3306     rv = soc_profile_mem_add(unit, 
   3307                            _bcm_mn_voq_port_map_profile[unit], 
   3308                            entries, 128, &profile);
   3309     if (rv) {
   3310         goto fail;
   3311     }
   3312            
   3313     soc_mem_field32_set(unit, VOQ_MOD_MAPm, &voq_mod_map, 
   3314                        VOQ_MOD_PORT_PROFILE_INDEXf, profile/128);
   3315     rv = soc_mem_write(unit, VOQ_MOD_MAPm, MEM_BLOCK_ALL, 
   3316                                modid, &voq_mod_map);
   3317     if (rv) {
   3318         goto fail;
   3319     }
   3320 fail : 
   3321     if (voq_port_map_entries) 
   3322     {
   3323        sal_free(voq_port_map_entries); 
   3324     }
   3325    return rv; 
   3326 }
   3327 
   3328 /*
   3329  * Function:
   3330  *       _bcm_mn_coe_queue_offset_clear  
   3331  * Purpose:
   3332  *     clears the offset in voq_mod_map and voq_port_map table for the subport  
   3333  * Parameters:
   3334  *     unit       - (IN) unit number
   3335  *     subport      - (IN) subport gport 
   3336  *     queue_id     - (IN) base queue_id for the subport 
   3337  * Returns:
   3338  *     BCM_E_XXX
   3339  */
   3340 int _bcm_mn_coe_queue_offset_clear(int unit, int queue_id,
   3341                             bcm_gport_t subport)
   3342 {
   3343 
   3344     bcm_module_t modid = 0;
   3345     bcm_port_t port  = 0;
   3346     voq_port_map_entry_t *voq_port_map_entries = NULL;
   3347     voq_mod_map_entry_t voq_mod_map;
   3348     int rv = BCM_E_NONE;
   3349     void *entries[1];
   3350     int vpm_idx_old = 0 ;
   3351     int port_offset = 0 ;
   3352     int i =0 ; 
   3353     int module_in_use = 0; 
   3354     uint32 profile = 0 ; 
   3355     bcm_trunk_t trunk_id;
   3356     int id;
   3357 
   3358      BCM_IF_ERROR_RETURN(
   3359      _bcm_esw_gport_resolve( unit, subport, &modid, &port, &trunk_id, &id));
   3360    /* program the voq port profiles. */
   3361     voq_port_map_entries = sal_alloc(sizeof(voq_port_map_entry_t)*128, 
   3362                                         "voq port map entries");
   3363     if (!voq_port_map_entries) {
   3364         goto fail;
   3365     }
   3366     sal_memset(voq_port_map_entries, 0, sizeof(voq_port_map_entry_t)*128);
   3367     entries[0] = voq_port_map_entries;
   3368     rv = READ_VOQ_MOD_MAPm(unit, MEM_BLOCK_ALL, modid, &voq_mod_map);
   3369     if (rv) {
   3370         goto fail;
   3371     }     
   3372     if (!soc_mem_field32_get(unit, VOQ_MOD_MAPm, 
   3373                              &voq_mod_map, VOQ_VALIDf)) {
   3374         rv = BCM_E_NOT_FOUND;
   3375         goto fail;
   3376     }
   3377 
   3378     vpm_idx_old = _MN_VPM_ENTRIES_PER_SET *
   3379                       soc_mem_field32_get(unit, VOQ_MOD_MAPm, &voq_mod_map,
   3380                                           VOQ_MOD_PORT_PROFILE_INDEXf);
   3381     rv = soc_profile_mem_get(unit, _bcm_mn_voq_port_map_profile[unit], 
   3382                              vpm_idx_old, _MN_VPM_ENTRIES_PER_SET, entries );
   3383                                  
   3384     if (!(rv == SOC_E_NOT_FOUND || rv == SOC_E_NONE)) {
   3385          goto fail;
   3386     }
   3387 
   3388          
   3389    
   3390     port_offset = 0;
   3391     soc_mem_field32_set(unit, VOQ_PORT_MAPm, &voq_port_map_entries[port],
   3392                                 VOQ_PORT_OFFSETf, port_offset);
   3393    rv =soc_profile_mem_delete(unit, _bcm_mn_voq_port_map_profile[unit], 
   3394                               vpm_idx_old); 
   3395    if (rv) {
   3396        goto fail;
   3397    }
   3398     
   3399    for (i = 0; i < _MN_VPM_ENTRIES_PER_SET; i++) {
   3400         if (soc_mem_field32_get(unit, VOQ_PORT_MAPm,
   3401                                 &voq_port_map_entries[i], VOQ_PORT_OFFSETf)) {
   3402             module_in_use = 1;
   3403             break;
   3404         }
   3405    }
   3406    if (module_in_use) {
   3407        rv = soc_profile_mem_add(unit, 
   3408                              _bcm_mn_voq_port_map_profile[unit], 
   3409                               entries, 128, &profile);
   3410        if (rv) {
   3411            goto fail;
   3412        }
   3413        soc_mem_field32_set(unit, VOQ_MOD_MAPm, &voq_mod_map, 
   3414                           VOQ_MOD_PORT_PROFILE_INDEXf, profile/128);
   3415    } else 
   3416    {
   3417      soc_mem_field32_set(unit, VOQ_MOD_MAPm, &voq_mod_map, 
   3418                          VOQ_VALIDf, 0);
   3419      soc_mem_field32_set(unit, VOQ_MOD_MAPm, &voq_mod_map, 
   3420                              VOQ_MOD_OFFSETf, 0 );
   3421    }
   3422 
   3423    rv = soc_mem_write(unit, VOQ_MOD_MAPm, MEM_BLOCK_ALL, 
   3424                                modid, &voq_mod_map);
   3425 fail : 
   3426    if (voq_port_map_entries) 
   3427    {
   3428         sal_free(voq_port_map_entries); 
   3429    }
   3430    return rv; 
   3431 }
   3432 
   3433 /*
   3434  * Function:
   3435  *       _bcm_mn_mmu_port_coe_control  
   3436  * Purpose:
   3437  *     Programs the ing_cos_mode to enable/disable subport in the physical port 
   3438  * Parameters:
   3439  *     unit       - (IN) unit number
   3440  *     local_port      - (IN) physical port  
   3441  *     eanble     - (IN) flag to control enable/disable 
   3442  * Returns:
   3443  *     BCM_E_XXX
   3444  */
   3445 int _bcm_mn_mmu_port_coe_control(int unit ,int local_port, int enable)
   3446 {
   3447   uint64 rval;
   3448 
   3449   BCM_IF_ERROR_RETURN(READ_ING_COS_MODE_64r(unit, local_port, &rval));
   3450   soc_reg64_field32_set(unit, ING_COS_MODE_64r, &rval, USE_MODf, enable) ;
   3451   soc_reg64_field32_set(unit, ING_COS_MODE_64r, &rval, USE_PORTf, enable) ;
   3452   BCM_IF_ERROR_RETURN(WRITE_ING_COS_MODE_64r(unit, local_port, rval));
   3453   return BCM_E_NONE;
   3454 
   3455 }
   3456 
   3457 /*
   3458  * Function:
   3459  *     bcm_mn_cosq_gport_add
   3460  * Purpose:
   3461  *     Create a cosq gport structure
   3462  * Parameters:
   3463  *     unit  - (IN) unit number
   3464  *     port  - (IN) port number
   3465  *     numq  - (IN) number of COS queues
   3466  *     flags - (IN) flags (BCM_COSQ_GPORT_XXX)
   3467  *     gport - (OUT) GPORT identifier
   3468  * Returns:
   3469  *     BCM_E_XXX
   3470  */
   3471 int
   3472 bcm_mn_cosq_gport_add(int unit, bcm_gport_t port, int numq, uint32 flags,
   3473                       bcm_gport_t *gport)
   3474 {
   3475     _bcm_mn_mmu_info_t *mmu_info;
   3476     _bcm_mn_cosq_node_t *node = NULL;
   3477     _bcm_mn_cosq_node_t *s1_node = NULL ;
   3478     _bcm_mn_cosq_port_info_t *port_info;
   3479     uint32 sched_encap;
   3480     _bcm_mn_pipe_resources_t *res;
   3481     int phy_port, mmu_port, local_port;
   3482     int id, ii, q_base, pipe, qmin, qmax;
   3483     bcm_gport_t tmp_gport;
   3484     bcm_gport_t s1_sched;
   3485 
   3486 
   3487     LOG_INFO(BSL_LS_BCM_COSQ,
   3488              (BSL_META_U(unit,
   3489                          "bcm_mn_cosq_gport_add: unit=%d port=0x%x numq=%d flags=0x%x\n"),
   3490               unit, port, numq, flags));
   3491     
   3492     if (!soc_feature(unit, soc_feature_ets)) {
   3493         return BCM_E_UNAVAIL;
   3494     }
   3495 
   3496     if (gport == NULL) {
   3497         return BCM_E_PARAM;
   3498     }
   3499 
   3500     if (_bcm_mn_mmu_info[unit] == NULL) {
   3501         return BCM_E_INIT;
   3502     }
   3503 
   3504     if (!soc_feature(unit, 
   3505                     soc_feature_mmu_hqos_four_level)) { 
   3506         if(_BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port)){
   3507            return BCM_E_UNAVAIL;
   3508         }   
   3509     }
   3510     if(_BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port)){
   3511        BCM_IF_ERROR_RETURN(
   3512         _bcmi_coe_subport_physical_port_get(unit, port, &local_port));
   3513     }  else { 
   3514     BCM_IF_ERROR_RETURN
   3515         (_bcm_mn_cosq_localport_resolve(unit, port, &local_port));
   3516     }
   3517     if (local_port < 0) {
   3518         return BCM_E_PORT;
   3519     }
   3520 
   3521     mmu_info = _bcm_mn_mmu_info[unit];
   3522 
   3523     port_info = &mmu_info->port_info[local_port];
   3524     pipe = _BCM_MN_PORT_TO_PIPE(unit, local_port);
   3525     res = _BCM_MN_PRESOURCES(mmu_info, pipe);
   3526 #if 0
   3527     if (!mmu_info->ets_mode) {
   3528         /* cleanup the default lls setup */
   3529         SOC_IF_ERROR_RETURN(soc_monterey_lls_reset(unit));
   3530         SOC_IF_ERROR_RETURN(soc_monterey_lb_lls_init(unit));
   3531         mmu_info->ets_mode = 1;
   3532     }
   3533 #endif
   3534 
   3535     switch (flags) {
   3536     case BCM_COSQ_GPORT_UCAST_QUEUE_GROUP:
   3537         if (numq != 1) {
   3538             return BCM_E_PARAM;
   3539         }
   3540 
   3541         if (IS_CPU_PORT(unit, local_port) || IS_LB_PORT(unit, local_port)) {
   3542             return BCM_E_PARAM;
   3543         }
   3544          
   3545         if (_BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port)){
   3546             BCM_IF_ERROR_RETURN(
   3547             _bcm_mn_get_s1_node( unit, port, &s1_node));
   3548             if (s1_node->coe_base_index == -1) {  
   3549                 _bcm_mn_allocate_coe_queues(unit, s1_node, 1);  
   3550                 _bcm_mn_coe_queue_offset_add(unit, s1_node->coe_base_index,
   3551                                              port);
   3552             }    
   3553             for (id = s1_node->coe_base_index; 
   3554                   id < (s1_node->coe_base_index + _MN_NUM_COS(unit)); id++) {
   3555                  if (!res->p_queue_node[id].in_use) {
   3556                      s1_node->coe_num_l2++;       
   3557                      break;
   3558                  }
   3559             }
   3560             if (id == (s1_node->coe_base_index + NUM_COS(unit)))
   3561             {
   3562                 return BCM_E_RESOURCE;       
   3563             }
   3564         } else {
   3565            for (id = port_info->uc_base; id < port_info->uc_limit; id++) {
   3566                 if (res->p_queue_node[id].numq == 0) {
   3567                     break;
   3568                 }
   3569            }
   3570            if ((id == port_info->uc_limit) && 
   3571                   (IS_MN_HSP_PORT(unit, local_port))) {
   3572                return BCM_E_RESOURCE;
   3573            }
   3574            if (id == port_info->uc_limit) {
   3575                BCM_IF_ERROR_RETURN(
   3576                     _bcm_mn_node_index_get(res->l2_queue_list.bits, 0,
   3577                         _BCM_MN_NUM_L2_UC_LEAVES_PER_PIPE, numq, 
   3578                         1, &id));
   3579 
   3580                _bcm_mn_node_index_set(&res->l2_queue_list, id, 1);
   3581            }
   3582         }
   3583 
   3584         BCM_GPORT_UCAST_QUEUE_GROUP_SYSQID_SET(*gport, local_port, id);
   3585         node = &res->p_queue_node[id];
   3586         node->gport = *gport;
   3587         node->numq = numq;
   3588         node->level = SOC_MONTEREY_NODE_LVL_L2;
   3589         if (_BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port))
   3590         {
   3591            node->hw_cosq = id - s1_node->coe_base_index;
   3592         } else
   3593         { 
   3594            node->hw_cosq = id - port_info->uc_base;
   3595         } 
   3596         if (IS_MN_HSP_PORT(unit, local_port)) {
   3597             phy_port = SOC_INFO(unit).port_l2p_mapping[local_port];
   3598             mmu_port = SOC_INFO(unit).port_p2m_mapping[phy_port];
   3599             node->hw_index = _BCM_MN_HSP_L2_INDEX(unit, mmu_port, node->hw_cosq);
   3600         } else {
   3601             node->hw_index = soc_monterey_l2_hw_index(unit, id, 1);
   3602         }
   3603         node->local_port = local_port;
   3604         node->remote_modid = -1;
   3605         node->remote_port  = -1;
   3606         node->type = _BCM_MN_NODE_UCAST;
   3607         node->in_use = TRUE;
   3608         node->port_gport = port;
   3609         break;
   3610 
   3611     case BCM_COSQ_GPORT_MCAST_QUEUE_GROUP:
   3612         if (numq != 1) {
   3613             return BCM_E_PARAM;
   3614         }
   3615 
   3616         for (id = port_info->mc_base; id < port_info->mc_limit; id++) {
   3617             if (res->p_mc_queue_node[id].numq == 0) {
   3618                 break;
   3619             }
   3620         }
   3621         
   3622         if (id == port_info->mc_limit) {
   3623             return BCM_E_RESOURCE;
   3624         }            
   3625 
   3626         /* set index bits */
   3627         BCM_GPORT_MCAST_QUEUE_GROUP_SYSQID_SET(*gport, local_port, id);
   3628         node = &res->p_mc_queue_node[id];
   3629         node->gport = *gport;
   3630         node->numq = numq;
   3631         node->level = SOC_MONTEREY_NODE_LVL_L2;
   3632         node->type = _BCM_MN_NODE_MCAST;
   3633         node->hw_cosq = id - port_info->mc_base;
   3634         if (IS_MN_HSP_PORT(unit, local_port)) {
   3635             phy_port = SOC_INFO(unit).port_l2p_mapping[local_port];
   3636             mmu_port = SOC_INFO(unit).port_p2m_mapping[phy_port];
   3637             node->hw_index = id;
   3638             node->hw_index = soc_monterey_l2_hw_index(unit, node->hw_index, 0);
   3639         } else {
   3640             node->hw_index = soc_monterey_l2_hw_index(unit, id, 0);
   3641         }
   3642         node->local_port = local_port;
   3643         node->remote_modid = -1;
   3644         node->remote_port  = -1;
   3645         node->in_use = TRUE;
   3646         node->port_gport = port;
   3647         break;
   3648 
   3649 
   3650 
   3651     case BCM_COSQ_GPORT_SUBSCRIBER:
   3652     case BCM_COSQ_GPORT_VIRTUAL_PORT:
   3653     case BCM_COSQ_GPORT_VLAN_UCAST_QUEUE_GROUP:
   3654         /* Service Queueing are outside default queues. Hence NO alignment
   3655          * required.
   3656          */
   3657         BCM_IF_ERROR_RETURN(
   3658             _bcm_mn_node_index_get(res->l2_queue_list.bits, res->num_base_queues,
   3659                                      _BCM_MN_NUM_L2_UC_LEAVES_PER_PIPE, numq, 
   3660                                      1, &q_base));
   3661 
   3662         _bcm_mn_node_index_set(&res->l2_queue_list, q_base, numq);
   3663         qmin = res->num_base_queues + (pipe * _BCM_MN_NUM_L2_UC_LEAVES_PER_PIPE);
   3664         qmax = (pipe + 1) * _BCM_MN_NUM_L2_UC_LEAVES_PER_PIPE;
   3665 
   3666         for (ii = 0, id = qmin; id < qmax; id++) {
   3667             if (res->p_queue_node[id].numq > 0) {
   3668                 ii = 0;
   3669             } else {
   3670                 ii += 1;
   3671 
   3672                 if (ii == numq) {
   3673                     break;
   3674                 }
   3675             }
   3676         }
   3677 
   3678         if (ii != numq) {
   3679             return BCM_E_RESOURCE;
   3680         }
   3681 
   3682         id = id - (numq - 1);
   3683 
   3684         for (ii = 0; ii < numq; ii++, id++) {
   3685             BCM_GPORT_UCAST_QUEUE_GROUP_SYSQID_SET(tmp_gport, local_port, id);
   3686             node= &res->p_queue_node[id];
   3687             node->gport = tmp_gport;
   3688             node->numq = numq - ii;
   3689             node->level = SOC_MONTEREY_NODE_LVL_L2;
   3690             node->type = (flags == BCM_COSQ_GPORT_VIRTUAL_PORT) ?
   3691                             _BCM_MN_NODE_VM_UCAST : _BCM_MN_NODE_SERVICE_UCAST;
   3692             node->hw_index = q_base + ii + (pipe * _BCM_MN_NUM_L2_UC_LEAVES_PER_PIPE);
   3693             /* by default assign the cosq on order of order of alocation,
   3694              * can be overriddedn by cos_mapping_set */
   3695             node->hw_cosq = ii;
   3696             node->local_port = local_port;
   3697             node->remote_modid = -1;
   3698             node->remote_port  = -1;
   3699             node->in_use = TRUE;
   3700             node->port_gport = port;
   3701             if (ii == 0) {
   3702                 *gport = tmp_gport;
   3703             }
   3704         }
   3705         break;
   3706 
   3707     case BCM_COSQ_GPORT_DESTMOD_UCAST_QUEUE_GROUP:
   3708         if (numq != 1) {
   3709             return BCM_E_PARAM;
   3710         }
   3711 
   3712         if (!IS_HG_PORT(unit, local_port)) {
   3713             return BCM_E_PORT;
   3714         }
   3715 
   3716     qmin = res->num_base_queues;
   3717     qmax = _BCM_MN_NUM_L2_UC_LEAVES_PER_PIPE;
   3718         for (id = qmin; id < qmax; id++) {
   3719             if (res->p_queue_node[id].numq == 0) {
   3720                 break;
   3721             }
   3722         }
   3723 
   3724         if (id >= qmax) {
   3725             return BCM_E_RESOURCE;
   3726         }
   3727 
   3728         BCM_GPORT_UCAST_QUEUE_GROUP_SYSQID_SET(*gport, local_port, id);
   3729         node = &res->p_queue_node[id];
   3730         node->gport = *gport;
   3731         node->numq = numq;
   3732         node->level = SOC_MONTEREY_NODE_LVL_L2;
   3733         node->type = _BCM_MN_NODE_VOQ;
   3734         node->hw_index = -1;
   3735         /* by default assign the cosq on order of order of alocation,
   3736          * can be overriddedn by cos_mapping_set */
   3737         node->hw_cosq = -1;
   3738         node->local_port = local_port;
   3739         node->remote_modid = -1;
   3740         node->remote_port  = -1;
   3741         node->in_use = TRUE;
   3742         node->port_gport = port;
   3743         break;
   3744 
   3745     case BCM_COSQ_GPORT_SCHEDULER:
   3746         if (numq < -1) {
   3747             return BCM_E_PARAM;
   3748         }
   3749         for (id = _BCM_MN_NUM_PORT_SCHEDULERS; 
   3750                 id < _BCM_MN_NUM_TOTAL_SCHEDULERS; id++) {
   3751             if (mmu_info->sched_node[id].in_use == FALSE) {
   3752                 node = &mmu_info->sched_node[id];
   3753                 node->in_use = TRUE;
   3754                 break;
   3755             }
   3756         }
   3757         if (!node) {
   3758             return BCM_E_RESOURCE;
   3759         }
   3760 
   3761         node = &mmu_info->sched_node[id];
   3762         sched_encap = (id << 8) | local_port;
   3763         BCM_GPORT_SCHEDULER_SET(*gport, sched_encap);
   3764         node->gport = *gport;
   3765         node->numq = numq;
   3766         node->local_port = local_port;
   3767         node->type = _BCM_MN_NODE_SCHEDULER;
   3768         node->attached_to_input = -1;
   3769         node->port_gport = port;
   3770         break;
   3771 
   3772     case BCM_COSQ_GPORT_WITH_ID:
   3773     case 0:
   3774         if (numq < -1) {
   3775             return BCM_E_PARAM;
   3776         }
   3777 
   3778         /* this is a port level scheduler */
   3779         id = local_port;
   3780 
   3781         if ( id < 0 || id >= _BCM_MN_NUM_PORT_SCHEDULERS) {
   3782             return BCM_E_PARAM;
   3783         }
   3784         if (IS_MN_HSP_PORT(unit, local_port)) {
   3785            if (numq > _BCM_MN_HSP_PORT_MAX_L0) {
   3786            return BCM_E_PARAM;
   3787           }
   3788         } 
   3789         node = &mmu_info->sched_node[id];
   3790         sched_encap = (id << 8) | local_port;
   3791         BCM_GPORT_SCHEDULER_SET(*gport, sched_encap);
   3792         node->gport = *gport;
   3793         node->level = SOC_MONTEREY_NODE_LVL_ROOT;
   3794         node->type = _BCM_MN_NODE_SCHEDULER;
   3795         phy_port = SOC_INFO(unit).port_l2p_mapping[local_port];
   3796         mmu_port = SOC_INFO(unit).port_p2m_mapping[phy_port];
   3797         node->hw_index = mmu_port;
   3798         if (IS_MN_HSP_PORT(unit, local_port)) {
   3799             node->numq = _BCM_MN_HSP_PORT_MAX_L0;
   3800         } else {
   3801             node->numq = -1;
   3802         }
   3803         node->local_port = local_port;
   3804         node->in_use = TRUE;
   3805         node->attached_to_input = 0;
   3806         node->port_gport = port;
   3807         if (!(soc_feature(unit,soc_feature_mmu_hqos_four_level)) && 
   3808              !(IS_MN_HSP_PORT(unit, local_port)))  
   3809         {
   3810             node->numq = 1;
   3811             BCM_IF_ERROR_RETURN
   3812             (bcm_mn_cosq_gport_add(unit, port, numq,
   3813                                    BCM_COSQ_GPORT_SCHEDULER, 
   3814                                    &s1_sched));
   3815             BCM_IF_ERROR_RETURN
   3816             (bcm_mn_cosq_gport_attach(unit, s1_sched, *gport, 0));
   3817             *gport = s1_sched ; 
   3818         }
   3819         break;
   3820 
   3821     default:
   3822         return BCM_E_PARAM;
   3823     }
   3824 
   3825     LOG_INFO(BSL_LS_BCM_COSQ,
   3826              (BSL_META_U(unit,
   3827                          "                       gport=0x%x\n"),
   3828               *gport));
   3829 
   3830     return BCM_E_NONE;
   3831 }
   3832 
   3833 /*
   3834  * Function:
   3835  *     bcm_mn_cosq_gport_detach
   3836  * Purpose:
   3837  *     Detach sched_port from the specified index (cosq) of parent_port
   3838  * Parameters:
   3839  *     unit       - (IN) unit number
   3840  *     sched_port - (IN) scheduler GPORT identifier
   3841  *     parent_port - (IN) GPORT to detach from
   3842  *     cosq       - (IN) COS queue to detach from
   3843  * Returns:
   3844  *     BCM_E_XXX
   3845  */
   3846 int
   3847 bcm_mn_cosq_gport_detach(int unit, bcm_gport_t sched_gport,
   3848                          bcm_gport_t parent_gport, bcm_cos_queue_t cosq)
   3849 {
   3850     _bcm_mn_cosq_node_t *sched_node, *parent_node = NULL, *prev_node;
   3851     _bcm_mn_cosq_node_t *child_node = NULL; 
   3852     bcm_port_t sched_port, parent_port = -1;
   3853     _bcm_mn_cosq_node_t *parent;
   3854     _bcm_mn_cosq_list_t *list = NULL;
   3855     _bcm_mn_mmu_info_t *mmu_info;
   3856     _bcm_mn_pipe_resources_t * res;
   3857     _bcm_mn_cosq_port_info_t *port_info;
   3858     int start = 0, end = 0;
   3859     int base_index;
   3860     int subport_enabled = 0 ;
   3861     int hw_index = 0 ; 
   3862     if (_bcm_mn_mmu_info[unit] == NULL) {
   3863         return BCM_E_INIT;
   3864     }
   3865 
   3866     if ((BCM_GPORT_IS_UCAST_QUEUE_GROUP(parent_gport)) ||
   3867         (BCM_GPORT_IS_MCAST_QUEUE_GROUP(parent_gport)) ||
   3868         (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(parent_gport))) {
   3869         return BCM_E_PARAM;
   3870     }
   3871 
   3872     BCM_IF_ERROR_RETURN
   3873         (_bcm_mn_cosq_node_get(unit, sched_gport, 0, NULL, &sched_port, NULL,
   3874                                &sched_node));
   3875 
   3876     if (sched_node->attached_to_input < 0) {
   3877         /* Not attached yet */
   3878         return BCM_E_PORT;
   3879     }
   3880 
   3881     if (parent_gport != BCM_GPORT_INVALID) {
   3882         if (BCM_GPORT_IS_SCHEDULER(parent_gport) || 
   3883             BCM_GPORT_IS_MODPORT(parent_gport)   || 
   3884             BCM_GPORT_IS_LOCAL(parent_gport)) {
   3885                BCM_IF_ERROR_RETURN
   3886                 (_bcm_mn_cosq_node_get(unit, parent_gport, 0, NULL, 
   3887                                     &parent_port, NULL, &parent_node));
   3888         } else {
   3889             if (!(BCM_GPORT_IS_SCHEDULER(sched_gport) || 
   3890                         BCM_GPORT_IS_UCAST_QUEUE_GROUP(sched_gport) ||
   3891                         BCM_GPORT_IS_MCAST_QUEUE_GROUP(sched_gport)) ||
   3892                     (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(parent_gport))) {
   3893                 return BCM_E_PARAM;
   3894             }
   3895             else {
   3896                 BCM_IF_ERROR_RETURN
   3897                 (_bcm_mn_cosq_localport_resolve(unit, parent_gport,
   3898                                                 &parent_port));
   3899                 parent_node = NULL;
   3900             }
   3901         }
   3902     }
   3903 
   3904     if (parent_port == -1) {
   3905         return BCM_E_PORT;
   3906     }
   3907 
   3908     mmu_info = _bcm_mn_mmu_info[unit];
   3909     port_info = &mmu_info->port_info[parent_port];
   3910     res = port_info->resources;
   3911 
   3912     if (sched_port != parent_port) {
   3913         return BCM_E_PORT;
   3914     }
   3915 
   3916     if (sched_node->parent != parent_node) {
   3917         return BCM_E_PORT;
   3918     }
   3919 
   3920     if ((cosq < -1) || 
   3921         (parent_node && (parent_node->numq != -1) && (cosq >= parent_node->numq))) {
   3922         return BCM_E_PARAM;
   3923     }
   3924 
   3925      if (cosq != -1) {
   3926         if (sched_node->attached_to_input != cosq) {
   3927             return BCM_E_PARAM;
   3928         }
   3929     }
   3930 
   3931     if (sched_node->type == _BCM_MN_NODE_SERVICE_UCAST) {
   3932         end = sched_node->numq;
   3933     } else {
   3934         end = 1;
   3935     }
   3936 
   3937     for (start = 0; start < end; start++) {
   3938         if (sched_node->parent != NULL) {
   3939             BCM_IF_ERROR_RETURN(
   3940                     soc_monterey_cosq_set_sched_parent(unit, parent_port, 
   3941                         sched_node->level, sched_node->hw_index, 
   3942                         sched_node->parent->hw_index, 0));
   3943             /* unresolve the node - delete this node from parent's child list */
   3944             BCM_IF_ERROR_RETURN(_bcm_mn_cosq_node_unresolve(unit, sched_node, cosq));
   3945 
   3946             /* now remove from the sw tree */
   3947             parent = sched_node->parent;
   3948             if (sched_node->parent->child == sched_node) {
   3949                 sched_node->parent->child = sched_node->sibling;
   3950             } else {
   3951                 prev_node = sched_node->parent->child;
   3952                 while (prev_node != NULL && prev_node->sibling != sched_node) {
   3953                     prev_node = prev_node->sibling;
   3954                 }
   3955                 if (prev_node == NULL) {
   3956                     return BCM_E_INTERNAL;
   3957                 }
   3958                 prev_node->sibling = sched_node->sibling;
   3959             }
   3960             sched_node->parent = NULL;
   3961             sched_node->sibling = NULL;
   3962             sched_node->attached_to_input = -1;
   3963             hw_index = sched_node->hw_index; 
   3964             if (!IS_MN_HSP_PORT(unit, parent_port)) {
   3965                 switch (parent->level) {
   3966                     case SOC_MONTEREY_NODE_LVL_ROOT:
   3967                         list = &res->s1_sched_list;
   3968                         sched_node->hw_index = -1;
   3969                         break;
   3970                     case SOC_MONTEREY_NODE_LVL_S1:
   3971                         if (IS_CPU_PORT(unit, parent_port)) {
   3972                             list = &res->cpu_l0_sched_list;
   3973                         } else {
   3974                             list = &res->l0_sched_list;
   3975                         }
   3976                         sched_node->hw_index = -1;
   3977                         break;
   3978                     case SOC_MONTEREY_NODE_LVL_L0:
   3979                         list = &res->l1_sched_list;
   3980                         sched_node->hw_index = -1;
   3981                         break;
   3982                     case SOC_MONTEREY_NODE_LVL_L1:
   3983                         list = &res->l2_queue_list;
   3984                         break;
   3985                     default:
   3986                         break;
   3987                 }
   3988              
   3989                 if (!BCM_GPORT_IS_MCAST_QUEUE_GROUP(sched_gport)){ 
   3990                     if (parent->numq == -1) { 
   3991                         BCM_IF_ERROR_RETURN(_bcm_mn_node_index_clear(list, 
   3992                                     hw_index, 1));
   3993                     } else if ((parent->child == NULL) &&
   3994                                (sched_node->level != SOC_MONTEREY_NODE_LVL_L2)) {
   3995                               if (list) {
   3996                                  base_index =  parent->base_index; 
   3997                                  if (IS_CPU_PORT(unit, parent_port) &&  
   3998                                      (sched_node->level == SOC_MONTEREY_NODE_LVL_L0)) {
   3999                                       base_index =  parent->base_index - _BCM_MN_CPU_PORT_L0_MIN;
   4000                                  }
   4001                                  BCM_IF_ERROR_RETURN(_bcm_mn_node_index_clear(list, 
   4002                                     base_index, parent->base_size));
   4003                               }
   4004                              list = NULL;
   4005                              parent->base_index = -1;
   4006                              parent->base_size  = 0;
   4007                    } 
   4008                 }
   4009                 /* Indexes that are allocated statically is not released to the pool*/  
   4010                 if ((sched_node->level == SOC_MONTEREY_NODE_LVL_L2) && 
   4011                         (BCM_GPORT_IS_UCAST_QUEUE_GROUP(sched_gport))){ 
   4012                     if ((sched_node->type == _BCM_MN_NODE_VOQ)) { 
   4013                         _bcm_mn_node_index_clear(list, sched_node->hw_index, 1);
   4014                         sched_node->hw_index = -1;
   4015                     }
   4016                 }
   4017             }
   4018         }
   4019         if ((sched_node->type == _BCM_MN_NODE_SERVICE_UCAST) && 
   4020             ((start + 1) < end)){
   4021             BCM_IF_ERROR_RETURN
   4022                 (_bcm_mn_cosq_node_get(unit, sched_gport, start + 1, NULL,
   4023                                         &sched_port, NULL, &sched_node));
   4024             if (!sched_node) {
   4025                 return BCM_E_NOT_FOUND;
   4026             }
   4027         }
   4028     }
   4029 
   4030     if (soc_feature(unit, 
   4031           soc_feature_mmu_hqos_four_level) &&  
   4032           sched_node->level == SOC_MONTEREY_NODE_LVL_S1) {
   4033         child_node = parent_node->child; 
   4034         while(child_node) {
   4035               if(_BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit,
   4036                  child_node->port_gport)) {
   4037                  subport_enabled = 1;    
   4038                  break; 
   4039                }
   4040                child_node = child_node->sibling;   
   4041         } 
   4042         if (!subport_enabled) { 
   4043             BCM_IF_ERROR_RETURN(
   4044                 _bcm_mn_mmu_port_coe_control(unit, 
   4045                                  sched_node->local_port, 0)); 
   4046         }
   4047     }
   4048     LOG_INFO(BSL_LS_BCM_COSQ,
   4049              (BSL_META_U(unit,
   4050                          "                         hw_cosq=%d\n"),
   4051               sched_node->attached_to_input));
   4052 
   4053     return BCM_E_NONE;
   4054 }
   4055 
   4056 /*
   4057  * Function:
   4058  *     bcm_mn_cosq_gport_delete
   4059  * Purpose:
   4060  *     Destroy a cosq gport structure
   4061  * Parameters:
   4062  *     unit  - (IN) unit number
   4063  *     gport - (IN) GPORT identifier
   4064  * Returns:
   4065  *     BCM_E_XXX
   4066  */
   4067 int
   4068 bcm_mn_cosq_gport_delete(int unit, bcm_gport_t gport)
   4069 {
   4070     _bcm_mn_cosq_node_t *node, *tnode, *base_node;
   4071     _bcm_mn_cosq_node_t * s1_node = NULL ;
   4072     int ii, local_port, phy_port, mmu_port, hw_index;
   4073     _bcm_mn_mmu_info_t *mmu_info;
   4074     soc_info_t *si;
   4075     bcm_gport_t parent_gport = 0 ;
   4076     int level = 0 ;
   4077     _bcm_mn_pipe_resources_t * res;
   4078     _bcm_mn_cosq_port_info_t *port_info;
   4079     LOG_INFO(BSL_LS_BCM_COSQ,
   4080              (BSL_META_U(unit,
   4081                          "bcm_mn_cosq_gport_delete: unit=%d gport=0x%x\n"),
   4082               unit, gport));
   4083 
   4084     node = NULL;
   4085     base_node= NULL;
   4086 
   4087     mmu_info = _bcm_mn_mmu_info[unit];
   4088     si = &SOC_INFO(unit);
   4089     if (!soc_feature(unit, soc_feature_ets)) {
   4090         return BCM_E_UNAVAIL;
   4091     }
   4092 
   4093     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 
   4094         BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) ||
   4095         (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport)) ||
   4096         BCM_GPORT_IS_SCHEDULER(gport)) {
   4097         BCM_IF_ERROR_RETURN
   4098             (_bcm_mn_cosq_node_get(unit, gport, 0, NULL, &local_port, NULL, &node));
   4099         port_info = &mmu_info->port_info[local_port];
   4100         res = port_info->resources;
   4101 
   4102     } else if(_BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, gport)) {
   4103         BCM_IF_ERROR_RETURN
   4104          (_bcm_mn_get_s1_node(unit, gport, &node));
   4105          BCM_IF_ERROR_RETURN
   4106         (_bcmi_coe_subport_physical_port_get(unit, gport, &local_port));
   4107         port_info = &mmu_info->port_info[local_port];
   4108         res = port_info->resources;
   4109 
   4110     } else {
   4111          BCM_IF_ERROR_RETURN(
   4112                 bcm_esw_port_local_get(unit, gport, &local_port));
   4113         if (local_port >= _BCM_MN_MAX_PORT) {
   4114             return BCM_E_PORT;
   4115         }
   4116        
   4117         port_info = &mmu_info->port_info[local_port];
   4118         res = port_info->resources;
   4119         phy_port = si->port_l2p_mapping[local_port];
   4120         mmu_port = si->port_p2m_mapping[phy_port];
   4121         hw_index = _BCM_MN_ROOT_SCHED_INDEX(unit, mmu_port);
   4122 
   4123         for (ii = 0; ii < _BCM_MN_NUM_TOTAL_SCHEDULERS; ii++) {
   4124             tnode = &mmu_info->sched_node[ii];
   4125             if (tnode->in_use == FALSE) {
   4126                 continue;
   4127             }
   4128             if ((tnode->level == SOC_MONTEREY_NODE_LVL_ROOT) &&
   4129                 (tnode->hw_index == hw_index) && 
   4130                 (tnode->local_port == local_port)) {   
   4131                 /* check both mmu_port(unique only within a pipe)
   4132                    and local_port(unique witin system) to get the 
   4133                    correct node */
   4134                 node = tnode;
   4135                 break;
   4136             }
   4137         }
   4138         if (node == NULL) {
   4139             return BCM_E_NONE;
   4140         }
   4141     }
   4142     if (!node->in_use) { 
   4143          return BCM_E_NONE; 
   4144     }  
   4145     level = node->level;
   4146     if (node->parent)
   4147     {
   4148         parent_gport = node->parent->gport; 
   4149     }
   4150     while(node->child != NULL) {
   4151         BCM_IF_ERROR_RETURN(bcm_mn_cosq_gport_delete(unit, node->child->gport));
   4152     }
   4153 
   4154     if (!soc_feature(unit, soc_feature_mmu_hqos_four_level) &&
   4155         (level == SOC_MONTEREY_NODE_LVL_ROOT) && (!node->in_use)) 
   4156     {
   4157         return BCM_E_NONE;  
   4158     }
   4159     if (node->level != SOC_MONTEREY_NODE_LVL_ROOT && node->attached_to_input >= 0) {
   4160         BCM_IF_ERROR_RETURN
   4161             (bcm_mn_cosq_gport_detach(unit, node->gport, 
   4162                                 node->parent->gport, node->attached_to_input));
   4163     }
   4164 
   4165 
   4166     if (soc_feature(unit, soc_feature_mmu_hqos_four_level)) { 
   4167         if ((node->level == SOC_MONTEREY_NODE_LVL_L2)  &&
   4168              _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, node->port_gport)) {
   4169              BCM_IF_ERROR_RETURN
   4170              (_bcm_mn_get_s1_node(unit, node->port_gport, &s1_node));
   4171              s1_node->coe_num_l2--;
   4172              if (!s1_node->coe_num_l2) { 
   4173                  BCM_IF_ERROR_RETURN
   4174                  (_bcm_mn_coe_queue_offset_clear(unit, s1_node->coe_base_index,
   4175                                                   node->port_gport));
   4176                   BCM_IF_ERROR_RETURN
   4177                   (_bcm_mn_allocate_coe_queues(unit, s1_node, 0));  
   4178              }
   4179         }
   4180     }     
   4181     if ((node->type == _BCM_MN_NODE_VOQ) && 
   4182             (node->remote_modid > 0)) {
   4183         _bcm_mn_voq_next_base_node_get (unit, local_port,
   4184                 node->remote_modid, &base_node);
   4185         if (base_node != NULL) {
   4186             BCM_PBMP_ASSIGN(base_node->fabric_pbmp,
   4187                     node->fabric_pbmp);
   4188         }
   4189     }
   4190     
   4191     if ((node->level == SOC_MONTEREY_NODE_LVL_L2) && 
   4192         (BCM_GPORT_IS_UCAST_QUEUE_GROUP(node->gport)) &&  
   4193                         (node->type != _BCM_MN_NODE_VOQ) && 
   4194         ((node->hw_index < port_info->uc_base) ||  
   4195                             (node->hw_index >= port_info->uc_limit)))    
   4196     {     
   4197          _bcm_mn_node_index_clear(&res->l2_queue_list, 
   4198                                   node->hw_index, 1);
   4199          node->hw_index = -1;
   4200     }
   4201    if (node->cosq_map != NULL) {
   4202        sal_free(node->cosq_map);
   4203    }
   4204    if ((!(soc_feature(unit, soc_feature_mmu_hqos_four_level)) && 
   4205        node->level == SOC_MONTEREY_NODE_LVL_S1) && parent_gport )  
   4206    { 
   4207        BCM_IF_ERROR_RETURN(bcm_mn_cosq_gport_delete(unit, parent_gport));
   4208    }
   4209     if (IS_MN_HSP_PORT(unit, local_port)) {
   4210         BCM_IF_ERROR_RETURN
   4211             (_bcm_mn_cosq_clear_child_list(unit, node));
   4212     }
   4213     _BCM_MN_COSQ_NODE_INIT(node);
   4214     return BCM_E_NONE;
   4215 }
   4216 
   4217 /*
   4218  * Function:
   4219  *     bcm_mn_cosq_gport_get
   4220  * Purpose:
   4221  *     Get a cosq gport structure
   4222  * Parameters:
   4223  *     unit  - (IN) unit number
   4224  *     gport - (IN) GPORT identifier
   4225  *     port  - (OUT) port number
   4226  *     numq  - (OUT) number of COS queues
   4227  *     flags - (OUT) flags (BCM_COSQ_GPORT_XXX)
   4228  * Returns:
   4229  *     BCM_E_XXX
   4230  */
   4231 int
   4232 bcm_mn_cosq_gport_get(int unit, bcm_gport_t gport, bcm_gport_t *port,
   4233                       int *numq, uint32 *flags)
   4234 {
   4235     _bcm_mn_cosq_node_t *node;
   4236     bcm_module_t modid;
   4237     bcm_port_t local_port;
   4238     int id;
   4239     _bcm_gport_dest_t dest;
   4240 
   4241     if (port == NULL || numq == NULL || flags == NULL) {
   4242         return BCM_E_PARAM;
   4243     }
   4244 
   4245     LOG_INFO(BSL_LS_BCM_COSQ,
   4246              (BSL_META_U(unit,
   4247                          "bcm_mn_cosq_gport_get: unit=%d gport=0x%x\n"),
   4248               unit, gport));
   4249 
   4250     BCM_IF_ERROR_RETURN
   4251         (_bcm_mn_cosq_node_get(unit, gport, 0, NULL, &local_port, &id, &node));
   4252 
   4253     if (SOC_USE_GPORT(unit)) {
   4254         BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid));
   4255         dest.gport_type = _SHR_GPORT_TYPE_MODPORT;
   4256         dest.modid = modid;
   4257         dest.port = local_port;
   4258         BCM_IF_ERROR_RETURN(_bcm_esw_gport_construct(unit, &dest, port));
   4259     } else {
   4260         *port = local_port;
   4261     }
   4262 
   4263     *numq = node->numq;
   4264 
   4265     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   4266         if (node->type == _BCM_MN_NODE_SERVICE_UCAST) {
   4267             *flags = BCM_COSQ_GPORT_VLAN_UCAST_QUEUE_GROUP;
   4268         } else if (node->type == _BCM_MN_NODE_VM_UCAST) {
   4269             *flags = BCM_COSQ_GPORT_VIRTUAL_PORT;
   4270         } else if (node->type == _BCM_MN_NODE_VOQ) {
   4271             *flags = BCM_COSQ_GPORT_DESTMOD_UCAST_QUEUE_GROUP;
   4272         } else {
   4273             *flags = BCM_COSQ_GPORT_UCAST_QUEUE_GROUP;
   4274         }
   4275     } else if (BCM_GPORT_IS_SCHEDULER(gport)) {
   4276         *flags = BCM_COSQ_GPORT_SCHEDULER;
   4277     } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   4278         *flags = BCM_COSQ_GPORT_MCAST_QUEUE_GROUP;
   4279     } else {
   4280         *flags = 0;
   4281     }
   4282 
   4283     LOG_INFO(BSL_LS_BCM_COSQ,
   4284              (BSL_META_U(unit,
   4285                          "                       port=0x%x numq=%d flags=0x%x\n"),
   4286               *port, *numq, *flags));
   4287 
   4288     return BCM_E_NONE;
   4289 }
   4290 
   4291 /*
   4292  * Function:
   4293  *     bcm_mn_cosq_gport_traverse
   4294  * Purpose:
   4295  *     Walks through the valid COSQ GPORTs and calls
   4296  *     the user supplied callback function for each entry.
   4297  * Parameters:
   4298  *     unit       - (IN) unit number
   4299  *     trav_fn    - (IN) Callback function.
   4300  *     user_data  - (IN) User data to be passed to callback function
   4301  * Returns:
   4302  *     BCM_E_NONE - Success.
   4303  *     BCM_E_XXX
   4304  */
   4305 int
   4306 bcm_mn_cosq_gport_traverse(int unit, bcm_cosq_gport_traverse_cb cb,
   4307                            void *user_data)
   4308 {
   4309     _bcm_mn_cosq_node_t *port_info;
   4310     _bcm_mn_mmu_info_t *mmu_info;
   4311     bcm_module_t my_modid, modid_out;
   4312     bcm_port_t port, port_out;
   4313 
   4314     if (_bcm_mn_mmu_info[unit] == NULL) {
   4315         return BCM_E_INIT;
   4316     }
   4317     mmu_info = _bcm_mn_mmu_info[unit];
   4318 
   4319     BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_modid));
   4320     PBMP_ALL_ITER(unit, port) {
   4321         BCM_IF_ERROR_RETURN
   4322             (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET,
   4323                                     my_modid, port, &modid_out, &port_out));
   4324 
   4325         /* root node */
   4326         port_info = &mmu_info->sched_node[port_out];
   4327 
   4328         if (port_info->gport >= 0) {
   4329             _bcm_mn_cosq_gport_traverse(unit, port_info->gport, cb, user_data);
   4330         }
   4331       }
   4332 
   4333     return BCM_E_NONE;
   4334 }
   4335 
   4336 
   4337 /*
   4338  * Function:
   4339  *     bcm_mn_cosq_gport_attach
   4340  * Purpose:
   4341  *     Attach sched_port to the specified index (cosq) of parent_port
   4342  * Parameters:
   4343  *     unit       - (IN) unit number
   4344  *     sched_port - (IN) scheduler GPORT identifier
   4345  *     parent_port - (IN) GPORT to attach to
   4346  *     cosq       - (IN) COS queue to attach to (-1 for first available cosq)
   4347  * Returns:
   4348  *     BCM_E_XXX
   4349  */
   4350 int
   4351 bcm_mn_cosq_gport_attach(int unit, bcm_gport_t gport, 
   4352                            bcm_gport_t parent_gport, 
   4353                            bcm_cos_queue_t to_cosq)
   4354 {
   4355     _bcm_mn_mmu_info_t *mmu_info;
   4356     _bcm_mn_cosq_node_t *node, *parent_node, *child_node, *s1_node;
   4357     bcm_port_t port, to_port, local_port = 0, mmu_port;
   4358     int rv, tmp;
   4359     int max_nodes = 0;
   4360     int subport_enabled = 0;
   4361     uint32 rval = 0;
   4362     uint32 mc_group_mode = 0; 
   4363     
   4364     if ((mmu_info = _bcm_mn_mmu_info[unit]) == NULL) {
   4365         return BCM_E_INIT;
   4366     }
   4367 
   4368     if ((BCM_GPORT_IS_UCAST_QUEUE_GROUP(parent_gport)) ||
   4369         (BCM_GPORT_IS_MCAST_QUEUE_GROUP(parent_gport)) ||
   4370         (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(parent_gport))) {
   4371         return BCM_E_PARAM;
   4372     }
   4373 
   4374     if(!(BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
   4375          BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) ||
   4376          BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport) ||
   4377          BCM_GPORT_IS_SCHEDULER(gport))) {
   4378         return BCM_E_PORT;
   4379     }
   4380 
   4381     BCM_IF_ERROR_RETURN
   4382         (_bcm_mn_cosq_node_get(unit, gport, 0, NULL, &port, NULL, &node));
   4383 
   4384     if (node->attached_to_input >= 0) {
   4385         /* Has already attached */
   4386         return BCM_E_EXISTS;
   4387     }
   4388     tmp = node->attached_to_input;
   4389 
   4390     if (BCM_GPORT_IS_SCHEDULER(parent_gport)) {
   4391         BCM_IF_ERROR_RETURN
   4392             (_bcm_mn_cosq_node_get(unit, parent_gport, 0, NULL, &to_port, NULL,
   4393                                    &parent_node));
   4394     } else {
   4395         BCM_IF_ERROR_RETURN
   4396             (_bcm_mn_cosq_localport_resolve(unit, parent_gport, &to_port));
   4397         parent_node = &mmu_info->sched_node[to_port];
   4398     }
   4399 
   4400     if (port != to_port) {
   4401         return BCM_E_PORT;
   4402     }
   4403     if (!parent_node)  
   4404     {
   4405         return BCM_E_NOT_FOUND; 
   4406     }
   4407 
   4408     if ((parent_node->level == SOC_MONTEREY_NODE_LVL_ROOT) && 
   4409         _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, node->port_gport))  { 
   4410         rv = _bcm_mn_get_s1_node(unit, node->port_gport, 
   4411          &s1_node);      
   4412         if( rv != BCM_E_NOT_FOUND) { 
   4413             return BCM_E_EXISTS;
   4414         }  
   4415 
   4416     }
   4417     if (parent_node->level != SOC_MONTEREY_NODE_LVL_ROOT &&
   4418         parent_node->port_gport != node->port_gport)
   4419     {
   4420         return BCM_E_PARAM;     
   4421     }
   4422     mmu_port = SOC_MONTEREY_MMU_PORT(unit, port);
   4423     
   4424     /* Identify the levels of schedulers
   4425      * parent_port == phy_port && gport == scheduler => gport = S1
   4426      * parent_port == scheduler && level = S1 && gport == scheduler => gport = L0
   4427      * parent_port == schduler && lvel = L0 && gport == scheduler => parent_port = L0 and gport = L1
   4428      * parent_port == scheduler && port == queue_group => parent_port = L1 and gport = L2
   4429      */
   4430      if (!BCM_GPORT_IS_SCHEDULER(parent_gport)) {
   4431          if ((parent_node->numq == 0) || (parent_node->numq_expandable)) {
   4432              local_port = (BCM_GPORT_IS_LOCAL(parent_gport)) ?
   4433                            BCM_GPORT_LOCAL_GET(parent_gport) :
   4434                            BCM_GPORT_MODPORT_PORT_GET(parent_gport);
   4435 
   4436              if (!SOC_PORT_VALID(unit, local_port)) {
   4437                  return BCM_E_PORT;
   4438              }
   4439              parent_node->in_use = TRUE;
   4440              parent_node->local_port = port;
   4441              if (IS_MN_HSP_PORT(unit, local_port)) {
   4442                  parent_node->base_index = _BCM_MN_HSP_L0_INDEX(unit, mmu_port, 0);
   4443                  parent_node->numq = _BCM_MN_HSP_PORT_MAX_L0;
   4444              } else {
   4445                  parent_node->gport = parent_gport;
   4446                  parent_node->hw_index = _BCM_MN_ROOT_SCHED_INDEX(unit, mmu_port);
   4447                  parent_node->level = SOC_MONTEREY_NODE_LVL_ROOT;
   4448                  parent_node->attached_to_input = 0;
   4449                  parent_node->numq_expandable = 1;
   4450                  if (to_cosq == -1) {
   4451                      parent_node->numq += 1;
   4452                  } else {
   4453                      if (to_cosq >= parent_node->numq) {
   4454                          parent_node->numq = to_cosq + 1;
   4455                      }
   4456                  }
   4457              }
   4458          }
   4459 
   4460          if (!BCM_GPORT_IS_SCHEDULER(gport)) {
   4461              return BCM_E_PARAM;
   4462          }
   4463 
   4464          if (IS_MN_HSP_PORT(unit, to_port)) {
   4465              node->level = SOC_MONTEREY_NODE_LVL_L0;
   4466          } else {
   4467              node->level = SOC_MONTEREY_NODE_LVL_S1;
   4468          } 
   4469      } else {
   4470          if (parent_node->level == SOC_MONTEREY_NODE_LVL_ROOT) {
   4471              if (IS_MN_HSP_PORT(unit, to_port)) {
   4472                  node->level = SOC_MONTEREY_NODE_LVL_L0;
   4473              } else {
   4474                  node->level = SOC_MONTEREY_NODE_LVL_S1;
   4475              }
   4476          }
   4477          if (parent_node->level == SOC_MONTEREY_NODE_LVL_S1) {
   4478              node->level = SOC_MONTEREY_NODE_LVL_L0;
   4479          }
   4480          if (parent_node->level == SOC_MONTEREY_NODE_LVL_L0) {
   4481              node->level = SOC_MONTEREY_NODE_LVL_L1;
   4482 
   4483              /*only for hsp ports with mc-group-mode enabled 2 l2 mulicast
   4484                can be attached directly to L0.0 */
   4485              if (IS_MN_HSP_PORT(unit, to_port)) {
   4486                  SOC_IF_ERROR_RETURN(
   4487                          READ_HSP_SCHED_PORT_CONFIGr(unit, to_port, &rval));
   4488                  mc_group_mode = soc_reg_field_get(unit, HSP_SCHED_PORT_CONFIGr,
   4489                          rval, MC_GROUP_MODEf);
   4490                  if ((mc_group_mode) && (parent_node->attached_to_input == 0))
   4491                      node->level = SOC_MONTEREY_NODE_LVL_L2;
   4492              } 
   4493          }
   4494          if (parent_node->level == SOC_MONTEREY_NODE_LVL_L1) {
   4495              node->level = SOC_MONTEREY_NODE_LVL_L2;
   4496          }
   4497          BCM_IF_ERROR_RETURN
   4498              (_bcm_mn_cosq_max_nodes_get(unit, node->level, &max_nodes));
   4499          if (parent_node->numq > max_nodes) {
   4500             return BCM_E_PARAM;
   4501          }
   4502     }
   4503 
   4504     if ((to_cosq < -1) || ((parent_node->numq != -1) && (to_cosq >= parent_node->numq))) {
   4505         return BCM_E_PARAM;
   4506     }
   4507 
   4508     if (BCM_GPORT_IS_SCHEDULER(parent_gport) || BCM_GPORT_IS_LOCAL(parent_gport) ||
   4509         BCM_GPORT_IS_MODPORT(parent_gport)) {
   4510         int start = 0, end = 0;
   4511         if (parent_node->attached_to_input < 0) {
   4512             /* dont allow to attach to a node that has already attached */
   4513             return BCM_E_PARAM;
   4514         }
   4515 
   4516         if (node->type == _BCM_MN_NODE_SERVICE_UCAST) {
   4517             end = node->numq;
   4518         } else {
   4519             end = 1;
   4520         }
   4521 
   4522         for (start = 0; start < end; start++) {
   4523             node->parent = parent_node;
   4524             node->sibling = parent_node->child;
   4525             parent_node->child = node;
   4526             /* resolve the nodes */
   4527             rv = _bcm_mn_cosq_node_resolve(unit, node, to_cosq + start);
   4528             if (BCM_FAILURE(rv)) {
   4529                 parent_node->child = node->sibling;
   4530                 node->parent = NULL;
   4531                 node->attached_to_input = tmp;
   4532                 return rv;
   4533             }
   4534             LOG_INFO(BSL_LS_BCM_COSQ,
   4535                      (BSL_META_U(unit,
   4536                                  "                         hw_cosq=%d\n"),
   4537                       node->attached_to_input));
   4538 
   4539             if ((node->type == _BCM_MN_NODE_SERVICE_UCAST) && 
   4540                 ((start + 1) < end)){
   4541                 BCM_IF_ERROR_RETURN
   4542                     (_bcm_mn_cosq_node_get(unit, gport, start + 1, NULL,
   4543                                             &port, NULL, &node));
   4544                 if (!node) {
   4545                     return BCM_E_NOT_FOUND;
   4546                 }
   4547             }
   4548         }
   4549         if (soc_feature(unit, 
   4550                 soc_feature_mmu_hqos_four_level) &&  
   4551                 node->level == SOC_MONTEREY_NODE_LVL_S1) {
   4552             child_node = parent_node->child; 
   4553             while(child_node) {
   4554                   if(_BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit,
   4555                      child_node->port_gport)) {
   4556                      subport_enabled++ ;
   4557                      if(subport_enabled > 1) {  
   4558                         break;   
   4559                      }   
   4560                   }
   4561                   child_node = child_node->sibling; 
   4562             }
   4563             if (subport_enabled == 1) { 
   4564                 BCM_IF_ERROR_RETURN(
   4565                 _bcm_mn_mmu_port_coe_control(unit, 
   4566                                 node->local_port, 1)); 
   4567             } 
   4568         }
   4569     } else {
   4570             return BCM_E_PORT;
   4571     }
   4572 
   4573     return BCM_E_NONE;
   4574 }
   4575 
   4576 /*
   4577  * Function:
   4578  *     bcm_mn_cosq_gport_attach_get
   4579  * Purpose:
   4580  *     Get attached status of a scheduler port
   4581  * Parameters:
   4582  *     unit       - (IN) unit number
   4583  *     sched_port - (IN) scheduler GPORT identifier
   4584  *     parent_port - (OUT) GPORT to attach to
   4585  *     cosq       - (OUT) COS queue to attached to
   4586  * Returns:
   4587  *     BCM_E_XXX
   4588  * Notes:
   4589  */
   4590 int
   4591 bcm_mn_cosq_gport_attach_get(int unit, bcm_gport_t sched_gport,
   4592                              bcm_gport_t *parent_gport, bcm_cos_queue_t *cosq)
   4593 {
   4594     _bcm_mn_cosq_node_t *sched_node;
   4595     bcm_module_t modid, modid_out;
   4596     bcm_port_t port, port_out;
   4597 
   4598     if (parent_gport == NULL || cosq == NULL) {
   4599         return BCM_E_PARAM;
   4600     }
   4601 
   4602     BCM_IF_ERROR_RETURN
   4603         (_bcm_mn_cosq_node_get(unit, sched_gport, 0, &modid, &port, NULL,
   4604                                &sched_node));
   4605 
   4606     if (sched_node->attached_to_input < 0) {
   4607         /* Not attached yet */
   4608         return BCM_E_NOT_FOUND;
   4609     }
   4610 
   4611     if (sched_node->parent != NULL) { /* sched_node is not an S1 scheduler */
   4612         *parent_gport = sched_node->parent->gport;
   4613     } else {  /* sched_node is an S1 scheduler */
   4614         BCM_IF_ERROR_RETURN
   4615             (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, modid, port,
   4616                                     &modid_out, &port_out));
   4617         BCM_GPORT_MODPORT_SET(*parent_gport, modid_out, port_out);
   4618     }
   4619     *cosq = sched_node->attached_to_input;
   4620 
   4621     return BCM_E_NONE;
   4622 }
   4623 
   4624 /*
   4625  * Function:
   4626  *      bcm_mn_cosq_gport_child_get
   4627  * Purpose:
   4628  *      Get the child node GPORT atatched to N-th index (cosq)
   4629  *      of the scheduler GPORT.
   4630  * Parameters:
   4631  *      unit       - (IN)  Unit number.
   4632  *      in_gport   - (IN)  Scheduler GPORT ID.
   4633  *      cosq       - (IN)  COS queue attached to.
   4634  *      out_gport  - (OUT) child GPORT ID.
   4635  * Returns:
   4636  *      BCM_E_XXX
   4637  * Notes:
   4638  */
   4639 int
   4640 bcm_mn_cosq_gport_child_get(int unit, bcm_gport_t in_gport,
   4641                             bcm_cos_queue_t cosq,
   4642                             bcm_gport_t *out_gport)
   4643 {
   4644     _bcm_mn_cosq_node_t *in_node = NULL;
   4645     _bcm_mn_cosq_node_t *cur_node = NULL;
   4646     _bcm_mn_cosq_node_t *tmp_node = NULL;
   4647     bcm_module_t modid;
   4648     bcm_port_t port;
   4649 
   4650     if (out_gport == NULL) {
   4651         return BCM_E_PARAM;
   4652     }
   4653 
   4654     /* get the child of the input gport node
   4655      * at an index of cosq
   4656      */
   4657 
   4658     if ((cosq < 0) || ( cosq >= 64)) {
   4659         return BCM_E_PARAM;
   4660     }
   4661 
   4662     BCM_IF_ERROR_RETURN
   4663         (_bcm_mn_cosq_node_get(unit, in_gport, 0, &modid, &port, NULL,
   4664                                &in_node));
   4665     if ((in_node->child == NULL) && (in_node->level == SOC_MONTEREY_NODE_LVL_L2)) {
   4666        return BCM_E_PARAM;
   4667     }
   4668 
   4669     for (cur_node = in_node->child; cur_node != NULL;
   4670          cur_node = cur_node->sibling) {
   4671         if (cur_node->attached_to_input == cosq) {
   4672            tmp_node = cur_node;
   4673            break;
   4674         }
   4675     }
   4676     if (tmp_node == NULL) {
   4677         return BCM_E_NOT_FOUND;
   4678     }
   4679     *out_gport = tmp_node->gport;
   4680 
   4681     return BCM_E_NONE;
   4682 }
   4683 
   4684 /*
   4685  *  Convert HW drop probability to percent value
   4686  */
   4687 STATIC int
   4688 _bcm_mn_hw_drop_prob_to_percent[] = {
   4689     0,     /* 0  */
   4690     1,     /* 1  */
   4691     2,     /* 2  */
   4692     3,     /* 3  */
   4693     4,     /* 4  */
   4694     5,     /* 5  */
   4695     6,     /* 6  */
   4696     7,     /* 7  */
   4697     8,     /* 8  */
   4698     9,     /* 9  */
   4699     10,    /* 10 */
   4700     25,    /* 11 */
   4701     50,    /* 12 */
   4702     75,    /* 13 */
   4703     100,   /* 14 */
   4704     -1     /* 15 */
   4705 };
   4706 
   4707 STATIC int
   4708 _bcm_mn_percent_to_drop_prob(int percent)
   4709 {
   4710    int i;
   4711 
   4712    for (i = 14; i > 0 ; i--) {
   4713       if (percent >= _bcm_mn_hw_drop_prob_to_percent[i]) {
   4714           break;
   4715       }
   4716    }
   4717    return i;
   4718 }
   4719 
   4720 STATIC int
   4721 _bcm_mn_drop_prob_to_percent(int drop_prob) {
   4722    return (_bcm_mn_hw_drop_prob_to_percent[drop_prob]);
   4723 }
   4724 
   4725 /*
   4726  * index: degree, value: contangent(degree) * 100
   4727  * max value is 0xffff (16-bit) at 0 degree
   4728  */
   4729 STATIC int
   4730 _bcm_mn_cotangent_lookup_table[] =
   4731 {
   4732     /*  0.. 5 */  65535, 5728, 2863, 1908, 1430, 1143,
   4733     /*  6..11 */    951,  814,  711,  631,  567,  514,
   4734     /* 12..17 */    470,  433,  401,  373,  348,  327,
   4735     /* 18..23 */    307,  290,  274,  260,  247,  235,
   4736     /* 24..29 */    224,  214,  205,  196,  188,  180,
   4737     /* 30..35 */    173,  166,  160,  153,  148,  142,
   4738     /* 36..41 */    137,  132,  127,  123,  119,  115,
   4739     /* 42..47 */    111,  107,  103,  100,   96,   93,
   4740     /* 48..53 */     90,   86,   83,   80,   78,   75,
   4741     /* 54..59 */     72,   70,   67,   64,   62,   60,
   4742     /* 60..65 */     57,   55,   53,   50,   48,   46,
   4743     /* 66..71 */     44,   42,   40,   38,   36,   34,
   4744     /* 72..77 */     32,   30,   28,   26,   24,   23,
   4745     /* 78..83 */     21,   19,   17,   15,   14,   12,
   4746     /* 84..89 */     10,    8,    6,    5,    3,    1,
   4747     /* 90     */      0
   4748 };
   4749 
   4750 /*
   4751  * Given a slope (angle in degrees) from 0 to 90, return the number of cells
   4752  * in the range from 0% drop probability to 100% drop probability.
   4753  */
   4754 STATIC int
   4755 _bcm_mn_angle_to_cells(int angle)
   4756 {
   4757     return (_bcm_mn_cotangent_lookup_table[angle]);
   4758 }
   4759 
   4760 /*
   4761  * Given a number of packets in the range from 0% drop probability
   4762  * to 100% drop probability, return the slope (angle in degrees).
   4763  */
   4764 STATIC int
   4765 _bcm_mn_cells_to_angle(int packets)
   4766 {
   4767     int angle;
   4768 
   4769     for (angle = 90; angle >= 0 ; angle--) {
   4770         if (packets <= _bcm_mn_cotangent_lookup_table[angle]) {
   4771             break;
   4772         }
   4773     }
   4774     return angle;
   4775 }
   4776 
   4777 /*
   4778  * Function:
   4779  *     _bcm_mn_cosq_bucket_set
   4780  * Purpose:
   4781  *     Configure COS queue bandwidth control bucket
   4782  * Parameters:
   4783  *     unit          - (IN) unit number
   4784  *     port          - (IN) port number or GPORT identifier
   4785  *     cosq          - (IN) COS queue number
   4786  *     min_quantum   - (IN) kbps or packet/second
   4787  *     max_quantum   - (IN) kbps or packet/second
   4788  *     burst_quantum - (IN) kbps or packet/second
   4789  *     flags         - (IN)
   4790  * Returns:
   4791  *     BCM_E_XXX
   4792  * Notes:
   4793  *     If port is any form of local port, cosq is the hardware queue index.
   4794  */
   4795 STATIC int
   4796 _bcm_mn_cosq_bucket_set(int unit, bcm_gport_t port, bcm_cos_queue_t cosq,
   4797                         uint32 min_quantum, uint32 max_quantum,
   4798                         uint32 kbits_burst_min, uint32 kbits_burst_max, 
   4799                         uint32 flags)
   4800 {
   4801     _bcm_mn_cosq_node_t *node = NULL;
   4802     bcm_port_t local_port;
   4803     int index;
   4804     uint32 rval;
   4805     uint32 meter_flags;
   4806     uint32 bucketsize_max, bucketsize_min;
   4807     uint32 granularity_max, granularity_min;
   4808     uint32 refresh_rate_max, refresh_rate_min;
   4809     int refresh_bitsize = 0, bucket_bitsize = 0;
   4810     soc_mem_t config_mem = INVALIDm;
   4811     uint32 mc_group_mode = 0;
   4812     uint32 entry[SOC_MAX_MEM_WORDS];
   4813     
   4814     /* caller should resolve the cosq. */
   4815     if (cosq < 0) {
   4816         if (cosq == -1) {
   4817             /* caller needs to resolve the wild card value (-1) */
   4818             return BCM_E_INTERNAL;
   4819         } else { /* reject all other negative value */
   4820             return BCM_E_PARAM;
   4821         }
   4822     }
   4823 
   4824     BCM_IF_ERROR_RETURN
   4825         (_bcm_mn_cosq_index_resolve(unit, port, cosq,
   4826                                     _BCM_MN_COSQ_INDEX_STYLE_BUCKET,
   4827                                     &local_port, &index, NULL));
   4828 
   4829     if (BCM_GPORT_IS_SET(port) && 
   4830         ((BCM_GPORT_IS_SCHEDULER(port)) ||
   4831           BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
   4832           BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) ||
   4833           BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port))) {
   4834 
   4835         BCM_IF_ERROR_RETURN
   4836             (_bcm_mn_cosq_node_get(unit, port, cosq, NULL, 
   4837                                     NULL, NULL, &node));
   4838         if ((node->level == SOC_MONTEREY_NODE_LVL_ROOT) &&
   4839             !IS_MN_HSP_PORT(unit, local_port) &&
   4840             (min_quantum > 0)) {
   4841             /* min shaper is not supported */
   4842             return BCM_E_PARAM;
   4843         }
   4844     }
   4845 
   4846     if (node) {
   4847         if (BCM_GPORT_IS_SCHEDULER(port) || BCM_GPORT_IS_MODPORT(port)) {
   4848             if (node->level == SOC_MONTEREY_NODE_LVL_ROOT) {
   4849                 config_mem = MMU_MTRO_L0_MEMm;
   4850             } else if (node->level == SOC_MONTEREY_NODE_LVL_L0) {
   4851                 SOC_IF_ERROR_RETURN(
   4852                     READ_HSP_SCHED_PORT_CONFIGr(unit, local_port, &rval));
   4853 
   4854                 mc_group_mode = soc_reg_field_get(unit, HSP_SCHED_PORT_CONFIGr,
   4855                                                   rval, MC_GROUP_MODEf);
   4856                 if (mc_group_mode) { 
   4857                     config_mem = MMU_MTRO_L2_MEMm;
   4858                 } else {
   4859                     config_mem = MMU_MTRO_L1_MEMm;
   4860                 }
   4861             } else if (node->level == SOC_MONTEREY_NODE_LVL_L1) {
   4862                 config_mem = MMU_MTRO_L2_MEMm;
   4863             } else {
   4864                 return BCM_E_PARAM;
   4865             }
   4866         } else if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
   4867                    BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
   4868             config_mem = MMU_MTRO_L2_MEMm;
   4869         } else {
   4870             return BCM_E_PARAM;
   4871         }
   4872     } else {
   4873         if (IS_CPU_PORT(unit, local_port)) {
   4874             config_mem = MMU_MTRO_L2_MEMm; 
   4875         } else {
   4876             config_mem = MMU_MTRO_L1_MEMm; 
   4877         }
   4878     }
   4879 
   4880     meter_flags = flags & BCM_COSQ_BW_PACKET_MODE ?
   4881                             _BCM_TD_METER_FLAG_PACKET_MODE : 0;
   4882     BCM_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, &rval));
   4883     if (soc_reg_field_get(unit, MISCCONFIGr, rval, ITU_MODE_SELf)) {
   4884         meter_flags |= _BCM_TD_METER_FLAG_NON_LINEAR;
   4885     }
   4886 
   4887     refresh_bitsize = soc_mem_field_length(unit, config_mem, MAX_REFRESHf);
   4888     bucket_bitsize = soc_mem_field_length(unit, config_mem, MAX_THD_SELf);
   4889 
   4890     BCM_IF_ERROR_RETURN
   4891         (_bcm_td_rate_to_bucket_encoding(unit, max_quantum, kbits_burst_max,
   4892                                            meter_flags, refresh_bitsize,
   4893                                            bucket_bitsize, &refresh_rate_max,
   4894                                            &bucketsize_max, &granularity_max));
   4895 
   4896     BCM_IF_ERROR_RETURN
   4897         (_bcm_td_rate_to_bucket_encoding(unit, min_quantum, kbits_burst_min,
   4898                                            meter_flags, refresh_bitsize,
   4899                                            bucket_bitsize, &refresh_rate_min,
   4900                                            &bucketsize_min, &granularity_min));
   4901 
   4902     sal_memset(entry, 0, sizeof(uint32)*SOC_MAX_MEM_WORDS);
   4903     soc_mem_field32_set(unit, config_mem, &entry, MAX_METER_GRANf, granularity_max);
   4904     soc_mem_field32_set(unit, config_mem, &entry, MAX_REFRESHf, refresh_rate_max);
   4905     soc_mem_field32_set(unit, config_mem, &entry, MAX_THD_SELf, bucketsize_max);
   4906 
   4907     soc_mem_field32_set(unit, config_mem, &entry, MIN_METER_GRANf, granularity_min);
   4908     soc_mem_field32_set(unit, config_mem, &entry, MIN_REFRESHf, refresh_rate_min);
   4909     soc_mem_field32_set(unit, config_mem, &entry, MIN_THD_SELf, bucketsize_min);
   4910 
   4911     soc_mem_field32_set(unit, config_mem, &entry, SHAPER_CONTROLf,
   4912                        (flags & BCM_COSQ_BW_PACKET_MODE) ? 1 : 0);
   4913 
   4914     soc_mem_field32_set(unit, config_mem, &entry, EAV_ENABLEf, 
   4915                          (flags & BCM_COSQ_BW_EAV_MODE) ? 1 : 0);
   4916     BCM_IF_ERROR_RETURN
   4917         (soc_mem_write(unit, config_mem, MEM_BLOCK_ALL, index, &entry));
   4918 
   4919     return BCM_E_NONE;
   4920 }
   4921 
   4922 /*
   4923  * Function:
   4924  *     _bcm_mn_cosq_bucket_get
   4925  * Purpose:
   4926  *     Get COS queue bandwidth control bucket setting
   4927  * Parameters:
   4928  *     unit          - (IN) unit number
   4929  *     port          - (IN) port number or GPORT identifier
   4930  *     cosq          - (IN) COS queue number
   4931  *     min_quantum   - (OUT) kbps or packet/second
   4932  *     max_quantum   - (OUT) kbps or packet/second
   4933  *     burst_quantum - (OUT) kbps or packet/second
   4934  *     flags         - (IN)
   4935  * Returns:
   4936  *     BCM_E_XXX
   4937  * Notes:
   4938  *     If port is any form of local port, cosq is the hardware queue index.
   4939  */
   4940 STATIC int
   4941 _bcm_mn_cosq_bucket_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   4942                         uint32 *min_quantum, uint32 *max_quantum,
   4943                         uint32 *kbits_burst_min, uint32 *kbits_burst_max,
   4944                         uint32 *flags)
   4945 {
   4946     _bcm_mn_cosq_node_t *node = NULL;
   4947     bcm_port_t local_port;
   4948     int index;
   4949     uint32 rval;
   4950     uint32 refresh_rate, bucketsize, granularity, meter_flags;
   4951     soc_mem_t config_mem = INVALIDm;
   4952     uint32 mc_group_mode = 0;
   4953     uint32 entry[SOC_MAX_MEM_WORDS];
   4954 
   4955     if (cosq < 0) {
   4956         if (cosq == -1) {
   4957             /* caller needs to resolve the wild card value (-1) */
   4958             return BCM_E_INTERNAL;
   4959         } else { /* reject all other negative value */
   4960             return BCM_E_PARAM;
   4961         }
   4962     }
   4963 
   4964     BCM_IF_ERROR_RETURN
   4965         (_bcm_mn_cosq_index_resolve(unit, port, cosq,
   4966                                     _BCM_MN_COSQ_INDEX_STYLE_BUCKET,
   4967                                     &local_port, &index, NULL));
   4968 
   4969     if (BCM_GPORT_IS_SET(port) && 
   4970         ((BCM_GPORT_IS_SCHEDULER(port)) ||
   4971           BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
   4972           BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) ||
   4973           BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port))) {
   4974 
   4975         BCM_IF_ERROR_RETURN
   4976             (_bcm_mn_cosq_node_get(unit, port, cosq, NULL, 
   4977                                     &local_port, NULL, &node));
   4978     }
   4979 
   4980     if (node) {
   4981         if (BCM_GPORT_IS_SCHEDULER(port) || BCM_GPORT_IS_MODPORT(port)) {
   4982             if (node->level == SOC_MONTEREY_NODE_LVL_ROOT) {
   4983                 config_mem = MMU_MTRO_L0_MEMm;
   4984             } else if (node->level == SOC_MONTEREY_NODE_LVL_L0) {
   4985                 SOC_IF_ERROR_RETURN(
   4986                     READ_HSP_SCHED_PORT_CONFIGr(unit,
   4987                                                 local_port, &rval));
   4988                 mc_group_mode = soc_reg_field_get(unit, HSP_SCHED_PORT_CONFIGr,
   4989                                                  rval, MC_GROUP_MODEf);
   4990                 if (mc_group_mode){
   4991                     config_mem = MMU_MTRO_L2_MEMm; 
   4992                 } else {
   4993                     config_mem = MMU_MTRO_L1_MEMm; 
   4994                 }
   4995             } else if (node->level == SOC_MONTEREY_NODE_LVL_L1) {
   4996                 config_mem = MMU_MTRO_L2_MEMm; 
   4997             } else {
   4998                 return BCM_E_PARAM;
   4999             }
   5000         } else if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
   5001                    BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
   5002             config_mem = MMU_MTRO_L2_MEMm; 
   5003         } else {
   5004             return BCM_E_PARAM;
   5005         }
   5006     } else {
   5007         if (IS_CPU_PORT(unit, local_port)) {
   5008             config_mem = MMU_MTRO_L2_MEMm;
   5009         } else {
   5010             config_mem = MMU_MTRO_L1_MEMm; 
   5011         }
   5012     }
   5013 
   5014     if (min_quantum == NULL || max_quantum == NULL || 
   5015         kbits_burst_max == NULL || kbits_burst_min == NULL) {
   5016         return BCM_E_PARAM;
   5017     }
   5018 
   5019 
   5020     BCM_IF_ERROR_RETURN
   5021         (soc_mem_read(unit, config_mem, MEM_BLOCK_ALL, index, &entry));
   5022 
   5023     meter_flags = 0;
   5024     *flags = 0;
   5025     BCM_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, &rval));
   5026     if (soc_reg_field_get(unit, MISCCONFIGr, rval, ITU_MODE_SELf)) {
   5027         meter_flags |= _BCM_TD_METER_FLAG_NON_LINEAR;
   5028     }
   5029     if (soc_mem_field32_get(unit, config_mem, &entry, SHAPER_CONTROLf)) {
   5030         meter_flags |= _BCM_TD_METER_FLAG_PACKET_MODE;
   5031         *flags |= BCM_COSQ_BW_PACKET_MODE;
   5032     }
   5033 
   5034     granularity = soc_mem_field32_get(unit, config_mem, &entry, MAX_METER_GRANf);
   5035     refresh_rate = soc_mem_field32_get(unit, config_mem, &entry, MAX_REFRESHf);
   5036     bucketsize = soc_mem_field32_get(unit, config_mem, &entry, MAX_THD_SELf);
   5037     BCM_IF_ERROR_RETURN
   5038         (_bcm_td_bucket_encoding_to_rate(unit, refresh_rate, bucketsize,
   5039                                          granularity, meter_flags,
   5040                                          max_quantum, kbits_burst_max));
   5041 
   5042     granularity = soc_mem_field32_get(unit, config_mem, &entry, MIN_METER_GRANf);
   5043     refresh_rate = soc_mem_field32_get(unit, config_mem, &entry, MIN_REFRESHf);
   5044     bucketsize = soc_mem_field32_get(unit, config_mem, &entry, MIN_THD_SELf);
   5045 
   5046     BCM_IF_ERROR_RETURN
   5047         (_bcm_td_bucket_encoding_to_rate(unit, refresh_rate, bucketsize,
   5048                                          granularity, meter_flags,
   5049                                          min_quantum, kbits_burst_min));
   5050 
   5051     if (soc_mem_field32_get(unit, config_mem, &entry, EAV_ENABLEf)) {
   5052         *flags |= BCM_COSQ_BW_EAV_MODE;
   5053     }
   5054     return BCM_E_NONE;
   5055 }
   5056 
   5057 
   5058 STATIC int
   5059 _bcm_mn_cosq_time_domain_mn_get(int unit, int time_id, int *time_value)
   5060 {
   5061     uint32 rval;
   5062 
   5063     if (time_id < 0 || time_id > _MN_NUM_TIME_DOMAIN - 1) {
   5064         return SOC_E_PARAM;
   5065     }
   5066 
   5067     if (time_value == NULL) {
   5068         return SOC_E_PARAM;
   5069     }
   5070 
   5071     rval = 0;
   5072     SOC_IF_ERROR_RETURN(READ_TIME_DOMAINr(unit, &rval));
   5073     *time_value = soc_reg_field_get(unit, TIME_DOMAINr, rval, 
   5074                                       time_domain_mn[time_id].field);
   5075 
   5076     return SOC_E_NONE;
   5077 }
   5078 
   5079 
   5080 
   5081 
   5082 STATIC int
   5083 _bcm_mn_cosq_time_domain_mn_set(int unit, int time_value, int *time_id)
   5084 {
   5085     uint32 rval;
   5086     int rv = SOC_E_NONE;
   5087     int id;
   5088 
   5089     if (time_value < 0 || time_value > 63) {
   5090         return SOC_E_PARAM;
   5091     }
   5092 
   5093     rval = 0;
   5094     SOC_IF_ERROR_RETURN(READ_TIME_DOMAINr(unit, &rval));
   5095     for (id = 0; id < _MN_NUM_TIME_DOMAIN; id++) {/* Find a unset field from  TIME_0 to TIME_3 */
   5096         if (!time_domain_mn[id].ref_count) {
   5097             soc_reg_field_set(unit, TIME_DOMAINr, &rval, time_domain_mn[id].field, 
   5098                                 time_value);
   5099             time_domain_mn[id].ref_count++;
   5100             break;
   5101         }
   5102     }
   5103     
   5104     if(id == _MN_NUM_TIME_DOMAIN){/* No field in TIME_DOMAINr is free,return ERR*/
   5105         rv = BCM_E_RESOURCE;
   5106     }
   5107 
   5108     if(time_id){
   5109         *time_id = id;
   5110     }
   5111         
   5112     SOC_IF_ERROR_RETURN(WRITE_TIME_DOMAINr(unit, rval));
   5113     return rv;
   5114 }
   5115 
   5116 STATIC int
   5117 _bcm_mn_cosq_wred_index_resolve(int unit, bcm_port_t port,
   5118                       bcm_cos_queue_t cosq, uint32 flags, uint32 lflags,
   5119                       bcm_port_t *local_port, int *index_start, int *index_end)
   5120 {
   5121     int index;
   5122     int to_index = -1;
   5123     int start_pool_idx, end_pool_idx;
   5124     bcm_port_t local_p = -1;
   5125 
   5126     if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
   5127         return BCM_E_PARAM;
   5128     }
   5129 
   5130     if((lflags & BCM_COSQ_DISCARD_DEVICE) || (flags & BCM_COSQ_DISCARD_DEVICE)) {
   5131         if((port == -1) || (cosq == -1)) {
   5132             index = _BCM_WRED_GLOBAL_SERVICE_POOL;
   5133             to_index = index + 3;
   5134         } else {
   5135             BCM_IF_ERROR_RETURN(_bcm_mn_cosq_egress_sp_get(unit, port, cosq, &start_pool_idx, 
   5136                         &end_pool_idx)); 
   5137             index = to_index = _BCM_WRED_GLOBAL_SERVICE_POOL + start_pool_idx;
   5138         }
   5139     } else {
   5140         if ((lflags & BCM_COSQ_DISCARD_PORT) || (flags & BCM_COSQ_DISCARD_PORT)) {
   5141             if (port == -1) {
   5142                 return BCM_E_PARAM;
   5143             }
   5144             BCM_IF_ERROR_RETURN
   5145                 (_bcm_mn_cosq_index_resolve(unit, port, cosq,
   5146                                              _BCM_MN_COSQ_INDEX_STYLE_WRED_PORT,
   5147                                              local_port, &index, NULL));
   5148             if (cosq != -1) {
   5149                 BCM_IF_ERROR_RETURN(_bcm_mn_cosq_egress_sp_get(unit, port, cosq, &start_pool_idx, 
   5150                             &end_pool_idx));
   5151                 index = to_index = index + start_pool_idx;
   5152             } else {
   5153                 to_index = index + 3;
   5154             }
   5155         } else {
   5156             BCM_IF_ERROR_RETURN
   5157                 (_bcm_mn_cosq_index_resolve(unit, port, cosq == -1 ? 0:cosq,
   5158                                      _BCM_MN_COSQ_INDEX_STYLE_WRED,
   5159                                      local_port, &index, NULL));
   5160 
   5161             if(cosq == -1) {
   5162                 to_index = index + NUM_COS(unit) - 1;
   5163             } else {
   5164             to_index = index;
   5165             }
   5166         }
   5167     }
   5168 
   5169     if (index < 0) {
   5170         return BCM_E_PARAM;
   5171     }
   5172 
   5173     if (local_port != NULL) {
   5174         *local_port = local_p;
   5175     }
   5176     if (index_start != NULL) {
   5177         *index_start = index;
   5178     }
   5179     if (index_end != NULL) {
   5180         *index_end = to_index;
   5181     }
   5182     
   5183     return BCM_E_NONE;
   5184 }
   5185 
   5186 /*
   5187  * Function:
   5188  *     _bcm_mn_cosq_wred_set
   5189  * Purpose:
   5190  *     Configure unicast queue WRED setting
   5191  * Parameters:
   5192  *     unit                - (IN) unit number
   5193  *     port                - (IN) port number or GPORT identifier
   5194  *     cosq                - (IN) COS queue number
   5195  *     flags               - (IN) BCM_COSQ_DISCARD_XXX
   5196  *     min_thresh          - (IN)
   5197  *     max_thresh          - (IN)
   5198  *     drop_probablity     - (IN)
   5199  *     gain                - (IN)
   5200  *     ignore_enable_flags - (IN)
   5201  * Returns:
   5202  *     BCM_E_XXX
   5203  * Notes:
   5204  *     If port is any form of local port, cosq is the hardware queue index.
   5205  */
   5206 STATIC int
   5207 _bcm_mn_cosq_wred_set(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   5208                       uint32 flags, uint32 min_thresh, uint32 max_thresh,
   5209                       int drop_probability, int gain, int ignore_enable_flags,
   5210                       uint32 lflags,int refresh_time)
   5211 {
   5212     soc_mem_t wred_mem;
   5213     bcm_port_t local_port = -1;
   5214     int index;
   5215     uint32 profile_index, old_profile_index;
   5216     mmu_wred_drop_curve_profile_0_x_pipe_entry_t profile_entry;
   5217     mmu_wred_config_entry_t qentry;
   5218     void *entries[1];
   5219     soc_field_t fields[6][3];
   5220     int rate, i, jj, to_index = -1, exists = 0;
   5221     int time_id,time,old_time,current_time_sel;
   5222     int rv = SOC_E_NONE;
   5223     uint32 rval;
   5224     static soc_field_t wred_fields[6][3] = {
   5225         {MIN_THD0f, MAX_THD0f, MAX_DROP_RATE0f},
   5226         {MIN_THD1f, MAX_THD1f, MAX_DROP_RATE1f},
   5227         {MIN_THD2f, MAX_THD2f, MAX_DROP_RATE2f},
   5228         {MIN_THD3f, MAX_THD3f, MAX_DROP_RATE3f},
   5229         {MIN_THD4f, MAX_THD4f, MAX_DROP_RATE4f},
   5230         {MIN_THD5f, MAX_THD5f, MAX_DROP_RATE5f}
   5231     };
   5232 
   5233     BCM_IF_ERROR_RETURN(_bcm_mn_cosq_wred_index_resolve(unit, port, cosq,
   5234                             flags, lflags, &local_port, &index, &to_index));
   5235 
   5236     for(jj = index; jj <= to_index; jj++) {
   5237         wred_mem = MMU_WRED_CONFIG_X_PIPEm;
   5238 
   5239         BCM_IF_ERROR_RETURN
   5240             (soc_mem_read(unit, wred_mem, MEM_BLOCK_ALL, jj, &qentry));
   5241 
   5242         old_profile_index = 0xffffffff;
   5243         if (flags & (BCM_COSQ_DISCARD_NONTCP | BCM_COSQ_DISCARD_COLOR_ALL |
   5244                      BCM_COSQ_DISCARD_TCP)) {
   5245             old_profile_index = soc_mem_field32_get(unit, wred_mem, 
   5246                                                     &qentry, PROFILE_INDEXf);
   5247             entries[0] = &profile_entry;
   5248             BCM_IF_ERROR_RETURN
   5249                 (soc_profile_mem_get(unit, _bcm_mn_wred_profile[unit],
   5250                                      old_profile_index, 1, entries));
   5251             for (i = 0; i < 6; i++) {
   5252                 fields[i][0] = INVALIDf;
   5253                 fields[i][1] = INVALIDf;
   5254                 fields[i][2] = INVALIDf;
   5255             }
   5256             if (!(flags & (BCM_COSQ_DISCARD_COLOR_GREEN |
   5257                            BCM_COSQ_DISCARD_COLOR_YELLOW |
   5258                            BCM_COSQ_DISCARD_COLOR_RED))) {
   5259                 flags |= BCM_COSQ_DISCARD_COLOR_ALL;
   5260             }
   5261             if (!(flags & BCM_COSQ_DISCARD_NONTCP) || (flags & BCM_COSQ_DISCARD_TCP)) {
   5262                 if (flags & BCM_COSQ_DISCARD_COLOR_GREEN) {
   5263                     fields[0][0] = wred_fields[0][0];
   5264                     fields[0][1] = wred_fields[0][1];
   5265                     fields[0][2] = wred_fields[0][2];
   5266                 }
   5267                 if (flags & BCM_COSQ_DISCARD_COLOR_YELLOW) {
   5268                     fields[1][0] = wred_fields[1][0];
   5269                     fields[1][1] = wred_fields[1][1];
   5270                     fields[1][2] = wred_fields[1][2]; 
   5271                 }
   5272                 if (flags & BCM_COSQ_DISCARD_COLOR_RED) {
   5273                     fields[2][0] = wred_fields[2][0];
   5274                     fields[2][1] = wred_fields[2][1];
   5275                     fields[2][2] = wred_fields[2][2]; 
   5276                 }
   5277             }
   5278             if (flags & BCM_COSQ_DISCARD_NONTCP) {
   5279                 if (flags & BCM_COSQ_DISCARD_COLOR_GREEN) {
   5280                     fields[3][0] = wred_fields[3][0];
   5281                     fields[3][1] = wred_fields[3][1];
   5282                     fields[3][2] = wred_fields[3][2]; 
   5283                 }
   5284                 if (flags & BCM_COSQ_DISCARD_COLOR_YELLOW) {
   5285                     fields[4][0] = wred_fields[4][0];
   5286                     fields[4][1] = wred_fields[4][1];
   5287                     fields[4][2] = wred_fields[4][2]; 
   5288                 }
   5289                 if (flags & BCM_COSQ_DISCARD_COLOR_RED) {
   5290                     fields[5][0] = wred_fields[5][0];
   5291                     fields[5][1] = wred_fields[5][1];
   5292                     fields[5][2] = wred_fields[5][2]; 
   5293                 }
   5294             }
   5295             rate = _bcm_mn_percent_to_drop_prob(drop_probability);
   5296             for (i = 0; i < 6; i++) {
   5297                 exists = 0;
   5298                 if ((soc_mem_field32_get(unit, MMU_WRED_DROP_CURVE_PROFILE_0_X_PIPEm, entries[0], 
   5299                                 wred_fields[i][0]) != 0x1ffff) && (fields[i][0] == INVALIDf)) {
   5300                     fields[i][0] = wred_fields[i][0];
   5301                     exists = 1;
   5302                 } else {
   5303                     soc_mem_field32_set(unit, MMU_WRED_DROP_CURVE_PROFILE_0_X_PIPEm, entries[0], 
   5304                             wred_fields[i][0], (fields[i][0] == INVALIDf) ? 0x1ffff : min_thresh);
   5305                 }
   5306                 if ((soc_mem_field32_get(unit, MMU_WRED_DROP_CURVE_PROFILE_0_X_PIPEm, entries[0],
   5307                                 wred_fields[i][1]) != 0x1ffff) && (fields[i][1] == INVALIDf)) {
   5308                     fields[i][1] = wred_fields[i][1];
   5309                     exists = 1;
   5310                 } else {
   5311                     soc_mem_field32_set(unit, MMU_WRED_DROP_CURVE_PROFILE_0_X_PIPEm, entries[0],
   5312                             wred_fields[i][1], (fields[i][1] == INVALIDf) ? 0x1ffff : max_thresh);
   5313                 }
   5314 
   5315                 if (!exists) {
   5316                     soc_mem_field32_set(unit, MMU_WRED_DROP_CURVE_PROFILE_0_X_PIPEm, entries[0], 
   5317                         wred_fields[i][2], (fields[i][2] == INVALIDf) ? 0 : rate);
   5318                 }
   5319             }
   5320             BCM_IF_ERROR_RETURN
   5321                 (soc_profile_mem_add(unit, _bcm_mn_wred_profile[unit], 
   5322                                                     entries, 1, &profile_index));
   5323             soc_mem_field32_set(unit, wred_mem, &qentry, PROFILE_INDEXf, profile_index);
   5324             soc_mem_field32_set(unit, wred_mem, &qentry, WEIGHTf, gain);
   5325         }
   5326 
   5327         /* Some APIs only modify profiles */
   5328         if (!ignore_enable_flags) {
   5329             soc_mem_field32_set(unit, wred_mem, &qentry, CAP_AVERAGEf,
   5330                                 flags & BCM_COSQ_DISCARD_CAP_AVERAGE ? 1 : 0);
   5331             soc_mem_field32_set(unit, wred_mem, &qentry, WRED_ENf,
   5332                                 flags & BCM_COSQ_DISCARD_ENABLE ? 1 : 0);
   5333             soc_mem_field32_set(unit, wred_mem, &qentry, ECN_MARKING_ENf,
   5334                                 flags & BCM_COSQ_DISCARD_MARK_CONGESTION ?  1 : 0);
   5335         }
   5336 
   5337         current_time_sel = soc_mem_field32_get(unit, wred_mem, &qentry, TIME_DOMAIN_SELf);
   5338         time = (refresh_time + 7) / 8 - 1; /* Round it up to avoid negative value */
   5339         exists = 0;
   5340         /* If the time value exist, update reference count only */
   5341         for (time_id = 0; time_id < _MN_NUM_TIME_DOMAIN; time_id++) {
   5342             BCM_IF_ERROR_RETURN
   5343                 (_bcm_mn_cosq_time_domain_mn_get(unit, time_id, &old_time));            
   5344             if (time == old_time) {
   5345                 /* Only set exist flag if this entry reference count already update,
   5346                               otherwise update reference count */
   5347                 if(time_id != current_time_sel){ 
   5348                     soc_mem_field32_set(unit, wred_mem, &qentry, TIME_DOMAIN_SELf, 
   5349                                         time_id);
   5350                     time_domain_mn[time_id].ref_count++;
   5351                     time_domain_mn[current_time_sel].ref_count--;
   5352                 }
   5353                 exists = 1;
   5354                 break;
   5355             }
   5356         }
   5357 
   5358         if(!exists){
   5359             rv = _bcm_mn_cosq_time_domain_mn_set(unit, time, &time_id);
   5360             if(rv == SOC_E_NONE){
   5361                 soc_mem_field32_set(unit, wred_mem, &qentry, TIME_DOMAIN_SELf, 
   5362                                     time_id);
   5363                 time_domain_mn[current_time_sel].ref_count--;
   5364             }
   5365         }
   5366 /*
   5367  *Disabling the wred sampling and writing to wred mem
   5368  *This was required   for an hardware bug and can be taken out for apache b0
   5369  */ 
   5370         BCM_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, &rval));
   5371         soc_reg_field_set(unit, MISCCONFIGr, &rval, REFRESH_ENf, 0);
   5372         BCM_IF_ERROR_RETURN(WRITE_MISCCONFIGr(unit, rval));  
   5373         
   5374         BCM_IF_ERROR_RETURN(
   5375               soc_mem_write(unit, wred_mem, MEM_BLOCK_ALL, jj, &qentry));
   5376 
   5377         BCM_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, &rval));
   5378         soc_reg_field_set(unit, MISCCONFIGr, &rval, REFRESH_ENf, 1);
   5379         BCM_IF_ERROR_RETURN(WRITE_MISCCONFIGr(unit, rval));  
   5380         if (old_profile_index != 0xffffffff) {
   5381             SOC_IF_ERROR_RETURN
   5382                 (soc_profile_mem_delete(unit, _bcm_mn_wred_profile[unit],
   5383                                         old_profile_index));
   5384         }
   5385     }
   5386 
   5387     return rv;
   5388 }
   5389 
   5390 /*
   5391  * Function:
   5392  *     _bcm_mn_cosq_wred_get
   5393  * Purpose:
   5394  *     Get unicast queue WRED setting
   5395  * Parameters:
   5396  *     unit                - (IN) unit number
   5397  *     port                - (IN) port number or GPORT identifier
   5398  *     cosq                - (IN) COS queue number
   5399  *     flags               - (IN/OUT) BCM_COSQ_DISCARD_XXX
   5400  *     min_thresh          - (OUT)
   5401  *     max_thresh          - (OUT)
   5402  *     drop_probablity     - (OUT)
   5403  *     gain                - (OUT)
   5404  * Returns:
   5405  *     BCM_E_XXX
   5406  * Notes:
   5407  *     If port is any form of local port, cosq is the hardware queue index.
   5408  */
   5409 STATIC int
   5410 _bcm_mn_cosq_wred_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   5411                       uint32 *flags, uint32 *min_thresh, uint32 *max_thresh,
   5412                       int *drop_probability, int *gain, uint32 lflags,int *refresh_time)
   5413 {
   5414     bcm_port_t local_port = -1;
   5415     int index, profile_index;
   5416     mmu_wred_drop_curve_profile_0_x_pipe_entry_t profile_entry;
   5417     void *entries[1];
   5418     void *entry_p;
   5419     soc_mem_t wred_mem = 0;
   5420     soc_field_t fields[3];
   5421     static soc_field_t wred_fields[6][3] = {
   5422         {MIN_THD0f, MAX_THD0f, MAX_DROP_RATE0f},
   5423         {MIN_THD1f, MAX_THD1f, MAX_DROP_RATE1f},
   5424         {MIN_THD2f, MAX_THD2f, MAX_DROP_RATE2f},
   5425         {MIN_THD3f, MAX_THD3f, MAX_DROP_RATE3f},
   5426         {MIN_THD4f, MAX_THD4f, MAX_DROP_RATE4f},
   5427         {MIN_THD5f, MAX_THD5f, MAX_DROP_RATE5f}
   5428     };
   5429     mmu_wred_config_entry_t qentry;
   5430     int rate, time_id,time;
   5431 
   5432     if ((port == -1 ) && 
   5433             !((*flags & BCM_COSQ_DISCARD_DEVICE) || (lflags & BCM_COSQ_DISCARD_DEVICE))) {
   5434         return (BCM_E_PORT); 
   5435     }
   5436 
   5437     local_port = -1; 
   5438     BCM_IF_ERROR_RETURN(_bcm_mn_cosq_wred_index_resolve(unit, port, cosq,
   5439                             *flags, lflags, &local_port, &index, NULL));
   5440 
   5441     wred_mem = MMU_WRED_CONFIG_X_PIPEm;
   5442 
   5443     BCM_IF_ERROR_RETURN
   5444         (soc_mem_read(unit, wred_mem, MEM_BLOCK_ALL, index, &qentry));
   5445     profile_index = soc_mem_field32_get(unit, wred_mem,
   5446                                         &qentry, PROFILE_INDEXf);
   5447 
   5448     if (!(*flags & BCM_COSQ_DISCARD_NONTCP)) {
   5449         if (*flags & BCM_COSQ_DISCARD_COLOR_GREEN) {
   5450             fields[0] = wred_fields[0][0];
   5451             fields[1] = wred_fields[0][1];
   5452             fields[2] = wred_fields[0][2]; 
   5453             entry_p = &profile_entry;
   5454         } else if (*flags & BCM_COSQ_DISCARD_COLOR_YELLOW) {
   5455             fields[0] = wred_fields[1][0];
   5456             fields[1] = wred_fields[1][1];
   5457             fields[2] = wred_fields[1][2]; 
   5458             entry_p = &profile_entry;
   5459         } else if (*flags & BCM_COSQ_DISCARD_COLOR_RED) {
   5460             fields[0] = wred_fields[2][0];
   5461             fields[1] = wred_fields[2][1];
   5462             fields[2] = wred_fields[2][2]; 
   5463             entry_p = &profile_entry;
   5464         } else {
   5465             fields[0] = wred_fields[0][0];
   5466             fields[1] = wred_fields[0][1];
   5467             fields[2] = wred_fields[0][2]; 
   5468             entry_p = &profile_entry;
   5469         }
   5470     } else {
   5471         if (*flags & BCM_COSQ_DISCARD_COLOR_GREEN) {
   5472             fields[0] = wred_fields[3][0];
   5473             fields[1] = wred_fields[3][1];
   5474             fields[2] = wred_fields[3][2]; 
   5475             entry_p = &profile_entry;
   5476         } else if (*flags & BCM_COSQ_DISCARD_COLOR_YELLOW) {
   5477             fields[0] = wred_fields[4][0];
   5478             fields[1] = wred_fields[4][1];
   5479             fields[2] = wred_fields[4][2]; 
   5480             entry_p = &profile_entry;
   5481         } else if (*flags & BCM_COSQ_DISCARD_COLOR_RED) {
   5482             fields[0] = wred_fields[5][0];
   5483             fields[1] = wred_fields[5][1];
   5484             fields[2] = wred_fields[5][2]; 
   5485             entry_p = &profile_entry;
   5486         } else {
   5487             fields[0] = wred_fields[3][0];
   5488             fields[1] = wred_fields[3][1];
   5489             fields[2] = wred_fields[3][2]; 
   5490             entry_p = &profile_entry;
   5491         }
   5492     }
   5493 
   5494     entries[0] = &profile_entry;
   5495     BCM_IF_ERROR_RETURN
   5496         (soc_profile_mem_get(unit, _bcm_mn_wred_profile[unit],
   5497                              profile_index, 1, entries));
   5498     if (min_thresh != NULL) {
   5499         *min_thresh = soc_mem_field32_get(unit, MMU_WRED_DROP_CURVE_PROFILE_0_X_PIPEm, entry_p, fields[0]);
   5500     }
   5501     if (max_thresh != NULL) {
   5502         *max_thresh = soc_mem_field32_get(unit, MMU_WRED_DROP_CURVE_PROFILE_0_X_PIPEm, entry_p, fields[1]);
   5503     }
   5504     if (drop_probability != NULL) {
   5505         rate = soc_mem_field32_get(unit, MMU_WRED_DROP_CURVE_PROFILE_0_X_PIPEm, entry_p, fields[2]);
   5506         *drop_probability = _bcm_mn_drop_prob_to_percent(rate);
   5507     }
   5508 
   5509     if (gain) {
   5510         *gain = soc_mem_field32_get(unit, wred_mem, &qentry, WEIGHTf);
   5511     }
   5512 
   5513     if (refresh_time) {
   5514         time_id = soc_mem_field32_get(unit, wred_mem, &qentry, TIME_DOMAIN_SELf);
   5515         BCM_IF_ERROR_RETURN
   5516             (_bcm_mn_cosq_time_domain_mn_get(unit,time_id,&time));
   5517         *refresh_time = (time + 1) * 8;
   5518     }
   5519 
   5520     *flags &= ~(BCM_COSQ_DISCARD_CAP_AVERAGE | BCM_COSQ_DISCARD_ENABLE);
   5521     if (soc_mem_field32_get(unit, wred_mem, &qentry, CAP_AVERAGEf)) {
   5522         *flags |= BCM_COSQ_DISCARD_CAP_AVERAGE;
   5523     }
   5524     if (soc_mem_field32_get(unit, wred_mem, &qentry, WRED_ENf)) {
   5525         *flags |= BCM_COSQ_DISCARD_ENABLE;
   5526     }
   5527     if (soc_mem_field32_get(unit, wred_mem, &qentry, ECN_MARKING_ENf)) {
   5528         *flags |= BCM_COSQ_DISCARD_MARK_CONGESTION;
   5529     }
   5530     return BCM_E_NONE;
   5531 }
   5532 
   5533 /*
   5534  * Function:
   5535  *     _bcm_mn_cosq_sched_get
   5536  * Purpose:
   5537  *     Get scheduling mode setting
   5538  * Parameters:
   5539  *     unit                - (IN) unit number
   5540  *     port                - (IN) port number or GPORT identifier
   5541  *     cosq                - (IN) COS queue number
   5542  *     mode                - (OUT) scheduling mode (BCM_COSQ_XXX)
   5543  *     num_weights         - (IN) number of entries in weights array
   5544  *     weights             - (OUT) weights array
   5545  * Returns:
   5546  *     BCM_E_XXX
   5547  */
   5548 STATIC int
   5549 _bcm_mn_cosq_sched_get(int unit, bcm_port_t gport, bcm_cos_queue_t cosq,
   5550                        int *mode, int *weight)
   5551 {
   5552     _bcm_mn_cosq_node_t *node, *child_node , *s1_node;
   5553     bcm_port_t local_port;
   5554     int sch_index, lvl = SOC_MONTEREY_NODE_LVL_L1;
   5555     soc_monterey_sched_mode_e    sched_mode;
   5556     int index, numq;
   5557     _bcm_mn_mmu_info_t *mmu_info;
   5558     soc_info_t *si;
   5559 
   5560     if ((mmu_info = _bcm_mn_mmu_info[unit]) == NULL) {
   5561         return BCM_E_INIT;
   5562     }
   5563 
   5564     if (cosq < 0) {
   5565         if (cosq == -1) {
   5566             /* caller needs to resolve the wild card value (-1) */
   5567             return BCM_E_INTERNAL;
   5568         } else { /* reject all other negative value */
   5569             return BCM_E_PARAM;
   5570         }
   5571     }
   5572      
   5573     if(_BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, gport)){
   5574        BCM_IF_ERROR_RETURN(
   5575         _bcmi_coe_subport_physical_port_get(unit, gport, &local_port));
   5576     }  else { 
   5577     BCM_IF_ERROR_RETURN
   5578         (_bcm_mn_cosq_localport_resolve(unit, gport, &local_port));
   5579     } 
   5580     si = &SOC_INFO(unit);
   5581     if (BCM_GPORT_IS_SCHEDULER(gport)) { /* ETS style scheduler */
   5582         BCM_IF_ERROR_RETURN
   5583             (_bcm_mn_cosq_node_get(unit, gport, 0, NULL, &local_port, NULL,
   5584                                    &node));        
   5585         if ((node->numq >= 0) && (cosq > node->numq)) {
   5586             return BCM_E_PARAM;
   5587         }
   5588         BCM_IF_ERROR_RETURN
   5589             (_bcm_mn_cosq_child_node_at_input(node, cosq, &child_node));
   5590      } else if (_BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT
   5591                 (unit, gport)) {  
   5592                 if (soc_feature(unit, 
   5593                     soc_feature_mmu_hqos_four_level)) {
   5594                     BCM_IF_ERROR_RETURN
   5595                    (_bcm_mn_get_s1_node(unit, gport, 
   5596                    &s1_node));      
   5597                    index = s1_node->coe_base_index; 
   5598                    child_node = &mmu_info->queue_node[index + cosq ];       
   5599                    if (!child_node) {
   5600                        return BCM_E_INTERNAL;
   5601                    }
   5602                    if (child_node->attached_to_input == -1) {
   5603                        return BCM_E_NOT_FOUND;
   5604                    }
   5605                    node = child_node->parent ;
   5606                    if (!node) {
   5607                        return BCM_E_INTERNAL;
   5608                    }
   5609   
   5610                 } else { 
   5611                    return BCM_E_PARAM;
   5612                 } 
   5613      } else { 
   5614             if (IS_CPU_PORT(unit, local_port)) {
   5615                 numq = SOC_INFO(unit).num_cpu_cosq;
   5616                 if (cosq >= numq) {
   5617                     return BCM_E_PARAM;
   5618                 }
   5619                 index = soc_monterey_l2_hw_index(unit,
   5620                     si->port_cosq_base[local_port] + cosq, 0);
   5621             } else {
   5622                 index = soc_monterey_l2_hw_index(unit,
   5623                     si->port_uc_cosq_base[local_port] + cosq, 1);
   5624             }
   5625             child_node = &mmu_info->queue_node[index];
   5626             if (!child_node) {
   5627                 return BCM_E_INTERNAL;
   5628             }
   5629             if (child_node->attached_to_input == -1) {
   5630                 return BCM_E_NOT_FOUND;
   5631             }
   5632             node = child_node->parent;
   5633             if (node && !IS_CPU_PORT(unit, local_port)) {
   5634                 child_node = node;
   5635                 node = node->parent;
   5636                 if (!node) {
   5637                     return BCM_E_INTERNAL;
   5638                 }
   5639                 if ((node->numq >= 0) && ((cosq % _BCM_MN_HSP_PORT_MAX_COS) > node->numq)) {
   5640                     return BCM_E_PARAM;
   5641                 }
   5642                 BCM_IF_ERROR_RETURN
   5643                     (_bcm_mn_cosq_child_node_at_input(node, cosq, 
   5644                                                 &child_node));
   5645             }
   5646     }
   5647 
   5648     if (!child_node) {
   5649         return BCM_E_INTERNAL;
   5650     }
   5651 
   5652     sch_index = child_node->hw_index;
   5653     lvl = child_node->level;
   5654 
   5655     BCM_IF_ERROR_RETURN(
   5656             soc_monterey_cosq_get_sched_mode(unit, local_port, lvl, sch_index,
   5657                             &sched_mode, weight));
   5658 
   5659     switch(sched_mode) {
   5660         case SOC_MONTEREY_SCHED_MODE_STRICT:
   5661             *mode = BCM_COSQ_STRICT;
   5662         break;
   5663         case SOC_MONTEREY_SCHED_MODE_WRR:
   5664             *mode = BCM_COSQ_WEIGHTED_ROUND_ROBIN;
   5665         break;
   5666         case SOC_MONTEREY_SCHED_MODE_WDRR:
   5667             *mode = BCM_COSQ_DEFICIT_ROUND_ROBIN;
   5668         break;
   5669         default:
   5670             return BCM_E_INTERNAL;
   5671         break;
   5672     }
   5673     return BCM_E_NONE;
   5674 }
   5675 
   5676 /*
   5677  * Function:
   5678  *     _bcm_mn_lls_node_count
   5679  * Purpose:
   5680  *     This function counts the number of nodes at a particular level
   5681  * Parameters:
   5682  *     unit       - (IN) unit number
   5683  *     port       - (IN) local port number 
   5684  *     level      - (IN) level of the node in LLS
   5685  *     hw_index   - (IN) h/w index of the node
   5686  *     cookie     - (IN) state of the LLS structure  
   5687  */
   5688 STATIC int _bcm_mn_lls_node_count(int unit, int port, int level, 
   5689                                    int hw_index, void *cookie)
   5690 {
   5691     _bcm_mn_lls_info_t *i_lls_tree = (_bcm_mn_lls_info_t *) cookie;
   5692     i_lls_tree->node_count[level] += 1;
   5693     return 0;
   5694 }
   5695 
   5696 /*
   5697  * Function:
   5698  *     _bcm_mn_num_ones
   5699  * Purpose:
   5700  *     This function calculates the numbers of 1s in the binary format
   5701  *     of the number 
   5702  * Parameters:
   5703  *     m       - (IN) number
   5704  * Returns:
   5705  *     The number of 1s in the binary format of the number
   5706  */
   5707 STATIC uint32 
   5708 _bcm_mn_num_ones(uint32 m)
   5709 {
   5710     uint32 i = 0;
   5711 
   5712     while (m) {
   5713         m &= m - 1;
   5714         i +=  1;
   5715     }
   5716     return i;
   5717 }
   5718 
   5719 STATIC int
   5720 _bcm_mn_cosq_traverse_lls_tree(int unit, int port, _bcm_mn_cosq_node_t *node,
   5721                                 _soc_monterey_lls_traverse_cb cb, void *cookie)
   5722 {
   5723     if (node->child) {
   5724         BCM_IF_ERROR_RETURN(_bcm_mn_cosq_traverse_lls_tree(unit, port, 
   5725                                                             node->child,
   5726                                                             cb, cookie));
   5727     }
   5728 
   5729     if (node->sibling) {
   5730         BCM_IF_ERROR_RETURN(_bcm_mn_cosq_traverse_lls_tree(unit, port, 
   5731                                                 node->sibling, cb, cookie));
   5732     }
   5733 
   5734     if (node->level != SOC_MONTEREY_NODE_LVL_ROOT) {
   5735         BCM_IF_ERROR_RETURN(cb(unit, port, node->level, node->hw_index, cookie));
   5736     }
   5737     
   5738     return BCM_E_NONE;
   5739 }
   5740 
   5741 /*
   5742  * Function:
   5743  *     _bcm_mn_lls_shapers_remove
   5744  * Purpose:
   5745  *     This function removes shapers on the nodes by setting them 
   5746  *     to the max rate and setting min to 0  so that each node can only schedule upto
   5747  *     the max rate. It also calculates the leaky bucket parameters based on 
   5748  *     the kbit max
   5749  * Parameters:
   5750  *     unit       - (IN) unit number
   5751  *     port       - (IN) local port number 
   5752  *     level      - (IN) level of the node in LLS
   5753  *     hw_index   - (IN) h/w index of the node
   5754  *     cookie     - (IN) state of the LLS structure  
   5755  */
   5756 STATIC int _bcm_mn_lls_shapers_remove(int unit, int port, int level, 
   5757                                        int hw_index, void *cookie)
   5758 {
   5759     _bcm_mn_lls_info_t *i_lls_tree = (_bcm_mn_lls_info_t *) cookie;
   5760     soc_mem_t config_mem;
   5761     uint32  *p_entry;
   5762     uint32 entry[SOC_MAX_MEM_WORDS];
   5763     int index, kbit_max, kbit_min;
   5764     uint32 meter_flags;
   5765     uint32 bucketsize_max, granularity_max, refresh_rate_max,
   5766            refresh_bitsize = 0, bucket_bitsize = 0;
   5767 
   5768 
   5769     if (level == SOC_MONTEREY_NODE_LVL_MAX) {
   5770         return SOC_E_PARAM;
   5771     }
   5772 
   5773     if (i_lls_tree->child_lvl != level) {
   5774         return BCM_E_NONE;
   5775     }
   5776 
   5777     if (level == SOC_MONTEREY_NODE_LVL_L0) {
   5778         config_mem = MMU_MTRO_L0_MEMm;
   5779     } else if (level == SOC_MONTEREY_NODE_LVL_L1) {
   5780         config_mem = MMU_MTRO_L1_MEMm; 
   5781     } else if (level == SOC_MONTEREY_NODE_LVL_L2) {
   5782         config_mem = MMU_MTRO_L2_MEMm;
   5783     } else {
   5784         return BCM_E_PARAM;
   5785     }
   5786 
   5787 
   5788     index = i_lls_tree->offset[level] + i_lls_tree->count[level];
   5789     p_entry = &i_lls_tree->mtro_entries[index * SOC_MAX_MEM_WORDS];
   5790     
   5791     if (*p_entry == 0) {
   5792         SOC_IF_ERROR_RETURN(soc_mem_read(unit, config_mem, MEM_BLOCK_ALL, hw_index, 
   5793                                          p_entry));
   5794     }
   5795 
   5796     sal_memset(entry, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS);
   5797     
   5798             
   5799     meter_flags = 0;
   5800 
   5801     refresh_bitsize = soc_mem_field_length(unit, config_mem, MAX_REFRESHf);
   5802     bucket_bitsize = soc_mem_field_length(unit, config_mem, MAX_THD_SELf);
   5803 
   5804     /* Setting the max metering configuration */
   5805     kbit_max = i_lls_tree->kbit_max;
   5806     BCM_IF_ERROR_RETURN
   5807         (_bcm_td_rate_to_bucket_encoding(unit, kbit_max, kbit_max,
   5808                                        meter_flags, refresh_bitsize,
   5809                                        bucket_bitsize, &refresh_rate_max,
   5810                                        &bucketsize_max, &granularity_max));
   5811 
   5812     soc_mem_field32_set(unit, config_mem, entry, MAX_METER_GRANf,
   5813                         granularity_max);
   5814     soc_mem_field32_set(unit, config_mem, entry, MAX_REFRESHf,
   5815                         refresh_rate_max);
   5816     soc_mem_field32_set(unit, config_mem, entry, MAX_THD_SELf,
   5817                         bucketsize_max);
   5818 
   5819         
   5820     /* Setting the min metering configuration */
   5821     kbit_min = i_lls_tree->kbit_min;
   5822     BCM_IF_ERROR_RETURN
   5823         (_bcm_td_rate_to_bucket_encoding(unit, kbit_min, kbit_min,
   5824                                        meter_flags, refresh_bitsize,
   5825                                        bucket_bitsize, &refresh_rate_max,
   5826                                        &bucketsize_max, &granularity_max));
   5827 
   5828     soc_mem_field32_set(unit, config_mem, entry, MIN_METER_GRANf,
   5829                         granularity_max);
   5830     soc_mem_field32_set(unit, config_mem, entry, MIN_REFRESHf,
   5831                         refresh_rate_max);
   5832     soc_mem_field32_set(unit, config_mem, entry, MIN_THD_SELf,
   5833                         bucketsize_max);
   5834 
   5835     BCM_IF_ERROR_RETURN
   5836         (soc_mem_write(unit, config_mem, MEM_BLOCK_ALL, hw_index, entry));
   5837   
   5838     sal_usleep(100); 
   5839     i_lls_tree->count[level] += 1;
   5840     return 0;
   5841 }
   5842 
   5843 /*
   5844  * Function:
   5845  *     _bcm_mn_lls_shapers_restore
   5846  * Purpose:
   5847  *     This function restores the shapers on the nodes  
   5848  * Parameters:
   5849  *     unit       - (IN) unit number
   5850  *     port       - (IN) local port number 
   5851  *     level      - (IN) level of the node in LLS
   5852  *     hw_index   - (IN) h/w index of the node
   5853  *     cookie     - (IN) state of the LLS structure  
   5854  */
   5855 STATIC int _bcm_mn_lls_shapers_restore(int unit, int port, int level, 
   5856                                         int hw_index, void *cookie)
   5857 {
   5858     _bcm_mn_lls_info_t *i_lls_tree = (_bcm_mn_lls_info_t *) cookie;
   5859     soc_mem_t config_mem;
   5860     uint32  *p_entry;
   5861     int index;
   5862     uint32 entry[SOC_MAX_MEM_WORDS];    
   5863 
   5864     if (level == SOC_MONTEREY_NODE_LVL_MAX) {
   5865         return SOC_E_PARAM;
   5866     }
   5867 
   5868     if (level == SOC_MONTEREY_NODE_LVL_L0) {
   5869         config_mem = MMU_MTRO_L0_MEMm;
   5870     } else if (level == SOC_MONTEREY_NODE_LVL_L1) {
   5871         config_mem = MMU_MTRO_L1_MEMm; 
   5872     } else if (level == SOC_MONTEREY_NODE_LVL_L2) {
   5873         config_mem = MMU_MTRO_L0_MEMm; 
   5874     } else {
   5875         return BCM_E_PARAM;
   5876     }
   5877 
   5878     if (i_lls_tree->child_lvl  != level) {
   5879         return BCM_E_NONE;
   5880     }
   5881 
   5882 
   5883 
   5884     sal_memset(entry, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS);
   5885 
   5886     soc_mem_field32_set(unit, config_mem, entry, MIN_REFRESHf,
   5887                         500);
   5888     soc_mem_field32_set(unit, config_mem, entry, MIN_THD_SELf,
   5889                         3);
   5890     
   5891     SOC_IF_ERROR_RETURN
   5892         (soc_mem_write(unit, config_mem, MEM_BLOCK_ALL, hw_index, entry));
   5893 
   5894     sal_usleep(100);
   5895 
   5896     index = i_lls_tree->offset[level] + i_lls_tree->count[level];
   5897     p_entry = &i_lls_tree->mtro_entries[index * SOC_MAX_MEM_WORDS];
   5898 
   5899     SOC_IF_ERROR_RETURN(soc_mem_write(unit, config_mem, MEM_BLOCK_ALL, 
   5900                                       hw_index, p_entry));
   5901     
   5902     i_lls_tree->count[level] += 1;
   5903 
   5904     return 0;
   5905 }
   5906 
   5907 /*
   5908  * Function:
   5909  *     _bcm_mn_adjust_lls_bw
   5910  * Purpose:
   5911  *     This function adjusts the bandwidth at the level in which the node is
   5912  *     being switched so that each node gets sufficient bandwidth to do the
   5913  *     switchover.
   5914  * Parameters:
   5915  *     unit              - (IN) unit number
   5916  *     port              - (IN) local port number 
   5917  *     node              - (IN) cosq node structure
   5918  *     child_lvl         - (IN) level of the child node
   5919  *     child_hw_index    - (IN) h/w index of the child node
   5920  *     start             - (IN) flag  
   5921  *     i_lls_tree        - (OUT) LLS info 
   5922  * Returns:
   5923  *     BCM_E_XXX
   5924  */
   5925 STATIC int
   5926 _bcm_mn_adjust_lls_bw(int unit, bcm_port_t port, _bcm_mn_cosq_node_t *node, 
   5927                        int child_lvl, int child_hw_index, int start, 
   5928                        _bcm_mn_lls_info_t *i_lls_tree)
   5929 {
   5930     int rv = BCM_E_NONE, count, mem_size, ii, speed, jj;
   5931     soc_info_t *si;
   5932     if (!soc_feature(unit, soc_feature_vector_based_spri)) {
   5933         return BCM_E_NONE;
   5934     }
   5935     
   5936     if (IS_LB_PORT(unit, port)) {
   5937         return BCM_E_NONE;
   5938     }       
   5939     if (start) {
   5940         sal_memset(i_lls_tree, 0, sizeof(_bcm_mn_lls_info_t));
   5941         i_lls_tree->child_lvl = child_lvl;
   5942         i_lls_tree->child_hw_index = child_hw_index;
   5943 
   5944         if (node) {
   5945             /* get to top node */
   5946             while(node->parent) { node = node->parent; }
   5947 
   5948             if ((rv = _bcm_mn_cosq_traverse_lls_tree(unit, port, node, 
   5949                                     _bcm_mn_lls_node_count, i_lls_tree))) {
   5950                 goto cleanup;
   5951             }
   5952         }          
   5953 
   5954         for (count = 0, ii = 0; ii < SOC_MONTEREY_NODE_LVL_MAX; ii++) {
   5955             count += i_lls_tree->node_count[ii];
   5956             for (jj = ii - 1; jj >= 0; jj--) {
   5957                 i_lls_tree->offset[ii] += i_lls_tree->node_count[jj];
   5958             }
   5959         }
   5960         
   5961         if (count == 0) {
   5962             return BCM_E_INIT;
   5963         }
   5964         
   5965         mem_size = sizeof(uint32) * SOC_MAX_MEM_WORDS * count;
   5966         i_lls_tree->mtro_entries = sal_alloc(mem_size, "lls_war_buf");
   5967 
   5968         rv = bcm_esw_port_speed_get(unit, port, &speed);
   5969         if ((rv == BCM_E_UNAVAIL) || (speed == 0)) {
   5970             si = &SOC_INFO(unit);
   5971             speed = si->port_speed_max[port];
   5972         }
   5973 
   5974         i_lls_tree->kbit_min = 0;
   5975         i_lls_tree->kbit_max = ((speed)/10)/i_lls_tree->node_count[child_lvl];
   5976 
   5977         for (count = 0, ii = 0; ii < SOC_MONTEREY_NODE_LVL_MAX; ii++) {
   5978             i_lls_tree->count[ii] = 0;
   5979         }
   5980  
   5981         sal_memset(i_lls_tree->mtro_entries, 0, mem_size);
   5982 
   5983         if (node) {
   5984 
   5985             /* get to top node */
   5986             while(node->parent) { node = node->parent; }
   5987 
   5988             if ((rv = _bcm_mn_cosq_traverse_lls_tree(unit, port, node, 
   5989                                     _bcm_mn_lls_shapers_remove, i_lls_tree))) {
   5990   
   5991                 goto cleanup;
   5992             }
   5993         }
   5994     } else {
   5995         for (count = 0, ii = 0; ii < SOC_MONTEREY_NODE_LVL_MAX; ii++) {
   5996             i_lls_tree->count[ii] = 0;
   5997         }
   5998 
   5999         if (node) {
   6000             /* get to top node */
   6001             while(node->parent) { node = node->parent; }
   6002 
   6003             if ((rv = _bcm_mn_cosq_traverse_lls_tree(unit, port, node, 
   6004                                     _bcm_mn_lls_shapers_restore, i_lls_tree))) {
   6005                 goto cleanup;
   6006             }
   6007         }
   6008        
   6009        if (i_lls_tree->mtro_entries) {
   6010             sal_free(i_lls_tree->mtro_entries);
   6011             i_lls_tree->mtro_entries = NULL;
   6012        }
   6013  
   6014     }
   6015 
   6016     return rv;
   6017 
   6018 cleanup:
   6019     /* cleanup */
   6020     if (i_lls_tree->mtro_entries) {
   6021         sal_free(i_lls_tree->mtro_entries);
   6022         i_lls_tree->mtro_entries = NULL;
   6023     }
   6024      
   6025     return rv;
   6026 }
   6027 
   6028 /*
   6029  * Function:
   6030  *     _bcm_monterey_compute_lls_config
   6031  * Purpose:
   6032  *     This function computes the LLS configuration at each level
   6033  * Parameters:
   6034  *     unit              - (IN) unit number
   6035  *     port              - (IN) local port number 
   6036  *     level             - (IN) level of the node in LLS
   6037  *     first_sp_child    - (OUT) first sp child 
   6038  *     first_sp_mc_child - (OUT) first so multicast child
   6039  *     ucmap             - (OUT) unicast node map
   6040  *     spmap             - (OUT) SPRI node map
   6041  *     child_index       - (IN) index of the child node
   6042  *     cur_mode          - (IN) current schedling mode of the node  
   6043  *     mode              - (IN) new scheduling mode of the node
   6044  *     max_children      - (IN) maximum number of children in the level
   6045  * Returns:
   6046  *     BCM_E_XXX
   6047  */
   6048 STATIC int
   6049 _bcm_monterey_compute_lls_config (int unit, int port, int level, 
   6050                                  int *first_sp_child, 
   6051                                  int *first_sp_mc_child,
   6052                                  int *num_spri,
   6053                                  uint32 *ucmap, 
   6054                                  uint32 *spmap, 
   6055                                  int child_index, 
   6056                                  soc_monterey_sched_mode_e cur_mode,
   6057                                  soc_monterey_sched_mode_e mode,
   6058                                  int max_children)
   6059 {
   6060     uint32 ucm = 0, mcm = 0, cur_spmap, cur_num_spri, lucmap = 0;
   6061     int ii, *pfc, uc, mc, fc, oc, *use_fc;
   6062 
   6063     cur_num_spri = _bcm_mn_num_ones(*spmap);
   6064     cur_spmap = *spmap;
   6065 
   6066     if (level == SOC_MONTEREY_NODE_LVL_L1) {
   6067         if (IS_CPU_PORT(unit, port)) {
   6068             use_fc = first_sp_mc_child;
   6069         } else {
   6070             use_fc = (child_index >= _BCM_MN_NUM_L2_UC_LEAVES_PER_PIPE) ? 
   6071                         first_sp_mc_child : first_sp_child;
   6072         }
   6073     } else {
   6074         use_fc = first_sp_child;
   6075     }
   6076     
   6077     if (cur_num_spri == 0) {
   6078         *ucmap = 0;
   6079         *spmap = 0;
   6080     }
   6081 
   6082     if (mode == SOC_MONTEREY_SCHED_MODE_STRICT) {
   6083         if (child_index > *use_fc) {
   6084             if ((child_index - *use_fc) >= max_children && cur_num_spri > 0) {
   6085                  return BCM_E_UNAVAIL;
   6086             }
   6087         } else if (child_index < *use_fc) {
   6088             return BCM_E_UNAVAIL;
   6089         }
   6090     }
   6091  
   6092     if (level == SOC_MONTEREY_NODE_LVL_L1) {
   6093         for (mcm = 0, mc = 0, ucm = 0, uc = 0, ii = 0; ii < 8; ii++) {
   6094             if (*ucmap & (1 << ii)) {
   6095                 mcm |= (cur_spmap & (1 << ii)) ? (1 << mc) : 0;
   6096                 mc += 1;
   6097             } else {
   6098                 ucm |= (cur_spmap & (1 << ii)) ? (1 << uc) : 0;
   6099                 uc += 1;
   6100             }
   6101         }
   6102 
   6103         if (child_index < _BCM_MN_NUM_L2_UC_LEAVES_PER_PIPE) {
   6104             fc = *first_sp_child;
   6105             oc =  _bcm_mn_num_ones(ucm);
   6106             BCM_IF_ERROR_RETURN(_bcm_monterey_compute_lls_config(unit, port,
   6107                         level - 1, &fc, NULL, &oc, &lucmap, &ucm, child_index, 
   6108                         cur_mode, mode, 8));
   6109         } else {
   6110             fc = *first_sp_mc_child;
   6111             oc =  _bcm_mn_num_ones(mcm);
   6112             BCM_IF_ERROR_RETURN(_bcm_monterey_compute_lls_config(unit, port,
   6113                     level - 1, &fc, NULL, &oc, &lucmap, &mcm, 
   6114                     child_index, cur_mode, mode, 8));
   6115         }
   6116 
   6117         cur_spmap = 0;
   6118         *ucmap = 0;
   6119         for (fc = 0, ii = 0; ii < 8; ii++) {
   6120             if (ucm) {
   6121                 cur_spmap |= (ucm & (1 << ii)) ? 1 << fc : 0;
   6122                 fc += 1;
   6123                 ucm &= ~(1 << ii);
   6124             }
   6125             
   6126             if (mcm) {
   6127                 cur_spmap |= (mcm & (1 << ii)) ? 1 << fc : 0;
   6128                 *ucmap |= 1 << fc;
   6129                 fc += 1;
   6130                 mcm &= ~(1 << ii);
   6131             }
   6132 
   6133             if (fc > max_children) {
   6134                 return BCM_E_PARAM;
   6135             }
   6136 
   6137             if ((mcm == 0) && (ucm == 0)) {
   6138                 break;
   6139             }
   6140         }
   6141 
   6142     } else {
   6143         pfc = first_sp_child;
   6144         if (mode == SOC_MONTEREY_SCHED_MODE_STRICT) {
   6145             if (*pfc > child_index) {
   6146                 cur_spmap <<= (*pfc - child_index);
   6147                 cur_spmap |= 1;
   6148                 *pfc = child_index;
   6149                 *num_spri += 1;
   6150             } else {
   6151                 if (((1 << (child_index - *pfc)) & cur_spmap) == 0) {
   6152                     cur_spmap |= 1 << (child_index - *pfc);
   6153                     *num_spri += 1;
   6154                 }
   6155             }
   6156         } else {
   6157             if (1 << (child_index - *pfc) & cur_spmap) {
   6158                 cur_spmap &= ~(1 << (child_index - *pfc));
   6159                 *num_spri -= 1;
   6160             }
   6161         }
   6162     }
   6163 
   6164     *num_spri = _bcm_mn_num_ones(cur_spmap);
   6165 
   6166     *spmap = cur_spmap;
   6167 
   6168     return BCM_E_NONE;
   6169 }
   6170 
   6171 /*
   6172  * Function:
   6173  *     _bcm_mn_compute_lls_config
   6174  * Purpose:
   6175  *     This function computes the LLS configuration at each level
   6176  * Parameters:
   6177  *     unit              - (IN) unit number
   6178  *     port              - (IN) local port number 
   6179  *     level             - (IN) level of the node in LLS
   6180  *     first_sp_child    - (OUT) first sp child 
   6181  *     first_sp_mc_child - (OUT) first so multicast child
   6182  *     ucmap             - (OUT) unicast node map
   6183  *     spmap             - (OUT) SPRI node map
   6184  *     child_index       - (IN) index of the child node
   6185  *     cur_mode          - (IN) current schedling mode of the node  
   6186  *     mode              - (IN) new scheduling mode of the node
   6187  *     max_children      - (IN) maximum number of children in the level
   6188  * Returns:
   6189  *     BCM_E_XXX
   6190  */
   6191 STATIC int
   6192 _bcm_mn_compute_lls_config(int unit, int port, int level, 
   6193                             int *first_sp_child, 
   6194                             int *first_sp_mc_child,
   6195                             int *num_spri,
   6196                             uint32 *ucmap, 
   6197                             uint32 *spmap, 
   6198                             int child_index, 
   6199                             soc_monterey_sched_mode_e cur_mode,
   6200                             soc_monterey_sched_mode_e mode)
   6201 {
   6202     if (!soc_feature(unit, soc_feature_vector_based_spri)) {
   6203         return BCM_E_UNAVAIL;
   6204     }
   6205 
   6206     if (((cur_mode != SOC_MONTEREY_SCHED_MODE_STRICT) &&
   6207         (mode != SOC_MONTEREY_SCHED_MODE_STRICT)) ||
   6208        ((cur_mode == SOC_MONTEREY_SCHED_MODE_STRICT) && 
   6209         (mode == SOC_MONTEREY_SCHED_MODE_STRICT))) {
   6210         return BCM_E_NONE;
   6211     }
   6212 
   6213     return _bcm_monterey_compute_lls_config(unit, port, level, first_sp_child,
   6214                                           first_sp_mc_child, num_spri,
   6215                                           ucmap, spmap, child_index,
   6216                                           cur_mode, mode, 8);
   6217 }
   6218 
   6219 STATIC int
   6220 _bcm_mn_cosq_sched_parent_child_set(int unit, int port, int level,
   6221                                      int sched_index, int child_index,
   6222                                      soc_monterey_sched_mode_e sched_mode, 
   6223                                      int weight, _bcm_mn_cosq_node_t *child_node)
   6224 {
   6225     int wt, num_spri, first_sp_child, first_sp_mc_child;
   6226     uint32 ucmap = 0, spmap = 0;
   6227     soc_monterey_sched_mode_e cur_sched_mode;
   6228     _bcm_mn_lls_info_t lls_tree_info;
   6229     int rv;
   6230     if (child_node == NULL) {
   6231         return BCM_E_PARAM;
   6232     }
   6233 
   6234     BCM_IF_ERROR_RETURN(soc_monterey_cosq_get_sched_config(unit, port, level,
   6235                 sched_index, child_index, &num_spri, &first_sp_child,
   6236                 &first_sp_mc_child, &ucmap, &spmap, &cur_sched_mode, 
   6237                 &wt));    
   6238     /* If the dynamic switchover feature is enabled, then compute the LLS 
   6239        configuration and adjust the bandwidth at the level such that each 
   6240        node has sufficient bandwidth to perform the switchover. Also set
   6241        the new scheduler config based on the request */ 
   6242     if (soc_feature(unit, soc_feature_vector_based_spri)) {
   6243         
   6244         if ((rv = _bcm_mn_compute_lls_config(unit, port, level, &first_sp_child, 
   6245                     &first_sp_mc_child, &num_spri, 
   6246                     &ucmap, &spmap, child_index, 
   6247                     cur_sched_mode, sched_mode))) {
   6248             return rv;
   6249         }
   6250 
   6251         if (cur_sched_mode != sched_mode) {
   6252             if ((rv = _bcm_mn_adjust_lls_bw(unit, port, child_node,
   6253                           child_node->level, child_index, 1, &lls_tree_info))){
   6254                 goto error;
   6255             }
   6256         }
   6257 
   6258         if ((rv = soc_monterey_cosq_set_sched_config(unit, port, level,
   6259                     sched_index, child_index,
   6260                     num_spri, first_sp_child,
   6261                     first_sp_mc_child, ucmap,
   6262                     spmap, sched_mode, weight))){
   6263             goto error;
   6264         }
   6265 
   6266         if (cur_sched_mode != sched_mode) {
   6267             /* restore the default bw */
   6268             BCM_IF_ERROR_RETURN(_bcm_mn_adjust_lls_bw(unit, port, child_node,
   6269                                         child_node->level,
   6270                                         child_index,
   6271                                         0, &lls_tree_info));
   6272         }
   6273     }
   6274 
   6275     return BCM_E_NONE;
   6276 
   6277 /* If there is an error during the switchover process, then restore the 
   6278    bandwidth to the previous state */
   6279 error:
   6280     if (cur_sched_mode != sched_mode) {
   6281         BCM_IF_ERROR_RETURN(_bcm_mn_adjust_lls_bw(unit, port, child_node,
   6282                             child_node->level,
   6283                             child_index,
   6284                             0, &lls_tree_info));
   6285     }
   6286     return rv;
   6287 }
   6288 
   6289 /*
   6290  * Function:
   6291  *     _bcm_mn_cosq_sched_set
   6292  * Purpose:
   6293  *     Set scheduling mode
   6294  * Parameters:
   6295  *     unit                - (IN) unit number
   6296  *     port                - (IN) port number or GPORT identifier
   6297  *     cosq                - (IN) COS queue number
   6298  *     mode                - (IN) scheduling mode (BCM_COSQ_XXX)
   6299  *     num_weights         - (IN) number of entries in weights array
   6300  *     weights             - (IN) weights array
   6301  * Returns:
   6302  *     BCM_E_XXX
   6303  */
   6304 STATIC int
   6305 _bcm_mn_cosq_sched_set(int unit, bcm_port_t gport, bcm_cos_queue_t cosq,
   6306                         int mode, int weight)
   6307 {
   6308     _bcm_mn_cosq_node_t *node = NULL, *child_node , *s1_node;
   6309     bcm_port_t local_port;
   6310     int lwts = 1, index, numq;
   6311     soc_monterey_sched_mode_e sched_mode;
   6312     _bcm_mn_mmu_info_t *mmu_info;
   6313     soc_info_t *si;
   6314     int rv = BCM_E_NONE;
   6315 
   6316     if (cosq < 0) {
   6317         if (cosq == -1) {
   6318             /* caller needs to resolve the wild card value (-1) */
   6319             return BCM_E_INTERNAL;
   6320         } else { /* reject all other negative value */
   6321             return BCM_E_PARAM;
   6322         }
   6323     }
   6324 
   6325     if ((weight < 0) || (weight > 127)) {
   6326         return BCM_E_PARAM;
   6327     }
   6328 
   6329     if(_BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, gport)){
   6330        BCM_IF_ERROR_RETURN(
   6331         _bcmi_coe_subport_physical_port_get(unit, gport, &local_port));
   6332     }  else { 
   6333     BCM_IF_ERROR_RETURN
   6334         (_bcm_mn_cosq_localport_resolve(unit, gport, &local_port));
   6335     }
   6336     si = &SOC_INFO(unit);
   6337     mmu_info = _bcm_mn_mmu_info[unit];
   6338     
   6339     switch(mode) {
   6340         case BCM_COSQ_STRICT:
   6341             sched_mode = SOC_MONTEREY_SCHED_MODE_STRICT;
   6342             lwts = 0;
   6343         break;
   6344         case BCM_COSQ_ROUND_ROBIN:
   6345             sched_mode = SOC_MONTEREY_SCHED_MODE_WRR;
   6346             lwts = 1;
   6347         break;
   6348         case BCM_COSQ_WEIGHTED_ROUND_ROBIN:
   6349             sched_mode = SOC_MONTEREY_SCHED_MODE_WRR;
   6350             lwts = weight;
   6351         break;
   6352         case BCM_COSQ_DEFICIT_ROUND_ROBIN:
   6353             sched_mode = SOC_MONTEREY_SCHED_MODE_WDRR;
   6354             lwts = weight;
   6355         break;
   6356         default:
   6357             return BCM_E_PARAM;
   6358     }
   6359 
   6360     if (lwts == 0) {
   6361         sched_mode = SOC_MONTEREY_SCHED_MODE_STRICT;
   6362     }
   6363 
   6364     if (BCM_GPORT_IS_SCHEDULER(gport)) { /* ETS style scheduler */
   6365         BCM_IF_ERROR_RETURN
   6366             (_bcm_mn_cosq_node_get(unit, gport, 0, NULL, &local_port, NULL,
   6367                                    &node));        
   6368         if ((node->numq >= 0) && (cosq > node->numq)) {
   6369             return BCM_E_PARAM;
   6370         }
   6371         BCM_IF_ERROR_RETURN
   6372             (_bcm_mn_cosq_child_node_at_input(node, cosq, &child_node));
   6373      } else if (_BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT
   6374                 (unit, gport)) {  
   6375                 if (soc_feature(unit, 
   6376                     soc_feature_mmu_hqos_four_level)) {
   6377                     BCM_IF_ERROR_RETURN
   6378                    (_bcm_mn_get_s1_node(unit, gport, 
   6379                    &s1_node));      
   6380                    index = s1_node->coe_base_index; 
   6381                    child_node = &mmu_info->queue_node[index + cosq ];       
   6382                    if (!child_node) {
   6383                        return BCM_E_INTERNAL;
   6384                    }
   6385                    if (child_node->attached_to_input == -1) {
   6386                        return BCM_E_NOT_FOUND;
   6387                    }
   6388                    node = child_node->parent ;
   6389                    if (!node) {
   6390                        return BCM_E_INTERNAL;
   6391                    }
   6392   
   6393                 } else { 
   6394                    return BCM_E_PARAM;
   6395                 } 
   6396      } else { 
   6397             if (IS_CPU_PORT(unit, local_port)) {
   6398                 numq = SOC_INFO(unit).num_cpu_cosq;
   6399                 if (cosq >= numq) {
   6400                     return BCM_E_PARAM;
   6401                 }
   6402                 index = soc_monterey_l2_hw_index(unit,
   6403                     si->port_cosq_base[local_port] + cosq, 0);
   6404             } else {   
   6405                 index = soc_monterey_l2_hw_index(unit,
   6406                     si->port_uc_cosq_base[local_port] + cosq, 1);
   6407             }
   6408 
   6409             child_node = &mmu_info->queue_node[index];
   6410             if (!child_node) {
   6411                 return BCM_E_INTERNAL;
   6412             }
   6413             if (child_node->attached_to_input == -1) {
   6414                 return BCM_E_NOT_FOUND;
   6415             }
   6416             node = child_node->parent;
   6417             if (node && !IS_CPU_PORT(unit, local_port)) {
   6418                 child_node = node;
   6419                 node = node->parent;
   6420                 if (!node) {
   6421                     return BCM_E_INTERNAL;
   6422                 }
   6423                 if ((node->numq >= 0) && ((cosq % _BCM_MN_HSP_PORT_MAX_COS) > node->numq)) {
   6424                     return BCM_E_PARAM;
   6425                 }
   6426                 BCM_IF_ERROR_RETURN
   6427                     (_bcm_mn_cosq_child_node_at_input(node, cosq, 
   6428                                                 &child_node));
   6429             }
   6430     }
   6431 
   6432     if (!node || !child_node) {
   6433         return BCM_E_INTERNAL;
   6434     }
   6435 
   6436     /* S1 is always in WRR in Apache */
   6437     if (!IS_MN_HSP_PORT(unit, local_port) &&
   6438         (soc_feature(unit, soc_feature_mmu_hqos_four_level)) &&
   6439         (node->level == SOC_MONTEREY_NODE_LVL_ROOT) &&
   6440         (mode == BCM_COSQ_STRICT)) {
   6441         return BCM_E_PARAM;
   6442     }
   6443 
   6444     if (node->attached_to_input < 0) { /* Not resolved yet */
   6445         return BCM_E_NOT_FOUND;
   6446     }
   6447 
   6448     /* HSP/LLS - child node at cosq index of parent gport
   6449         * is resloved to set it's schedule mode and weight
   6450         */
   6451     if (IS_MN_HSP_PORT(unit, local_port)) {
   6452         rv = soc_monterey_cosq_set_sched_mode(unit, local_port,
   6453                         child_node->level, child_node->hw_index, sched_mode, lwts);
   6454     } else {
   6455         BCM_IF_ERROR_RETURN(_bcm_mn_cosq_sched_parent_child_set(unit,
   6456                 local_port, node->level, node->hw_index,
   6457                 child_node->hw_index, sched_mode, lwts, child_node));
   6458         if (!BCM_GPORT_IS_SCHEDULER(gport) && 
   6459             !BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) &&
   6460             !BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) &&
   6461             node && IS_CPU_PORT(unit, local_port)) {
   6462             child_node = node;
   6463             node = node->parent;
   6464             lwts = (sched_mode == SOC_MONTEREY_SCHED_MODE_STRICT) ? 0 : 1;
   6465             BCM_IF_ERROR_RETURN(_bcm_mn_cosq_sched_parent_child_set(unit,
   6466                     local_port, node->level, node->hw_index,
   6467                     child_node->hw_index, sched_mode, lwts, child_node));
   6468         }
   6469     }
   6470 
   6471     return rv;
   6472 }
   6473 
   6474 /*
   6475  * Function:
   6476  *     bcm_mn_cosq_detach
   6477  * Purpose:
   6478  *     Discard all COS schedule/mapping state.
   6479  * Parameters:
   6480  *     unit - unit number
   6481  * Returns:
   6482  *     BCM_E_XXX
   6483  */
   6484 int
   6485 bcm_mn_cosq_detach(int unit, int software_state_only)
   6486 {
   6487     int i;
   6488     soc_info_t *si;
   6489      bcm_port_t port;
   6490      bcm_gport_t gport;
   6491 
   6492     if (!_bcm_mn_mmu_info[unit] ) {
   6493          return BCM_E_NONE; 
   6494     } 
   6495 
   6496     (void) _bcm_bst_detach(unit);
   6497 
   6498      PBMP_ALL_ITER(unit, port) {
   6499        /* need to clean the ports even in case of failure. So not checking
   6500            return value intentionally
   6501         */
   6502        /* coverity[checked_return:FALSE]*/
   6503        /* coverity[unchecked_value:FALSE] */
   6504        (void)bcm_esw_port_gport_get(unit, port, &gport);
   6505        /* coverity[checked_return:FALSE]*/
   6506        /* coverity[unchecked_value:FALSE] */
   6507        bcm_mn_cosq_gport_delete(unit, gport);
   6508     }
   6509     if (NULL != _bcm_mn_endpoint_queuing_info[unit]) {
   6510         if (NULL != _bcm_mn_endpoint_queuing_info[unit]->ptr_array) {
   6511             for (i = 0; i < _BCM_MN_NUM_ENDPOINT(unit); i++) {
   6512                 if (_BCM_MN_ENDPOINT_IS_USED(unit, i)) {
   6513                     sal_free(_BCM_MN_ENDPOINT(unit, i));
   6514                     _BCM_MN_ENDPOINT(unit, i) = NULL;
   6515                 }
   6516             }
   6517             sal_free(_bcm_mn_endpoint_queuing_info[unit]->ptr_array);
   6518             _bcm_mn_endpoint_queuing_info[unit]->ptr_array = NULL;
   6519         }
   6520         if (NULL != _bcm_mn_endpoint_queuing_info[unit]->cos_map_profile) {
   6521             soc_profile_mem_destroy(unit,
   6522                     _bcm_mn_endpoint_queuing_info[unit]->cos_map_profile);
   6523             sal_free(_bcm_mn_endpoint_queuing_info[unit]->cos_map_profile);
   6524             _bcm_mn_endpoint_queuing_info[unit]->cos_map_profile = NULL;
   6525         }
   6526         sal_free(_bcm_mn_endpoint_queuing_info[unit]);
   6527         _bcm_mn_endpoint_queuing_info[unit] = NULL;
   6528     }
   6529 
   6530     si = &SOC_INFO(unit); 
   6531     for (i = 0; i < si->num_cpu_cosq; i++) {
   6532         if (_bcm_mn_cosq_cpu_cosq_config[unit][i] != NULL) { 
   6533             sal_free(_bcm_mn_cosq_cpu_cosq_config[unit][i]);
   6534             _bcm_mn_cosq_cpu_cosq_config[unit][i] = NULL; 
   6535         }
   6536     }
   6537     if (_bcm_mn_wred_profile[unit] != NULL )
   6538     {
   6539         soc_profile_mem_destroy(unit, _bcm_mn_wred_profile[unit]);
   6540         sal_free(_bcm_mn_wred_profile[unit]);
   6541         _bcm_mn_wred_profile[unit] = NULL; 
   6542     } 
   6543     if (_bcm_mn_cos_map_profile[unit] != NULL )
   6544     {
   6545         soc_profile_mem_destroy(unit, _bcm_mn_cos_map_profile[unit]);
   6546         sal_free(_bcm_mn_cos_map_profile[unit]);
   6547         _bcm_mn_cos_map_profile[unit] = NULL;
   6548     } 
   6549     if (_bcm_mn_sample_int_profile[unit] != NULL )
   6550     {
   6551         soc_profile_mem_destroy(unit, _bcm_mn_sample_int_profile[unit]);
   6552         sal_free(_bcm_mn_sample_int_profile[unit]);
   6553         _bcm_mn_sample_int_profile[unit] = NULL;
   6554     } 
   6555     if (_bcm_mn_feedback_profile[unit] != NULL )
   6556     {
   6557         soc_profile_reg_destroy(unit, _bcm_mn_feedback_profile[unit]);
   6558         sal_free(_bcm_mn_feedback_profile[unit]);
   6559          _bcm_mn_feedback_profile[unit] = NULL ;
   6560     } 
   6561     if (_bcm_mn_llfc_profile[unit] != NULL )
   6562     {
   6563         soc_profile_reg_destroy(unit, _bcm_mn_llfc_profile[unit]);
   6564         sal_free(_bcm_mn_llfc_profile[unit]);
   6565         _bcm_mn_llfc_profile[unit] = NULL ;
   6566     } 
   6567     if (_bcm_mn_voq_port_map_profile[unit] != NULL )
   6568     {
   6569         soc_profile_mem_destroy(unit, _bcm_mn_voq_port_map_profile[unit]);
   6570         sal_free(_bcm_mn_voq_port_map_profile[unit]);
   6571         _bcm_mn_voq_port_map_profile[unit] = NULL;
   6572     } 
   6573     if (_bcm_mn_ifp_cos_map_profile[unit] != NULL )
   6574     {
   6575         soc_profile_mem_destroy(unit, _bcm_mn_ifp_cos_map_profile[unit]);
   6576         sal_free(_bcm_mn_ifp_cos_map_profile[unit]);
   6577         _bcm_mn_ifp_cos_map_profile[unit] = NULL;  
   6578     } 
   6579     if (_bcm_mn_service_port_map_profile[unit] != NULL )
   6580     {
   6581         soc_profile_mem_destroy(unit, _bcm_mn_service_port_map_profile[unit]);
   6582         sal_free(_bcm_mn_service_port_map_profile[unit]);
   6583         _bcm_mn_service_port_map_profile[unit] = NULL;
   6584     } 
   6585     if (_bcm_mn_service_cos_map_profile[unit] != NULL )
   6586     {
   6587         soc_profile_mem_destroy(unit, _bcm_mn_service_cos_map_profile[unit]);
   6588         sal_free(_bcm_mn_service_cos_map_profile[unit]);
   6589         _bcm_mn_service_cos_map_profile[unit] = NULL;  
   6590     }
   6591     if (_bcm_mn_mmu_info[unit] != NULL) {
   6592         _bcm_mn_cosq_free_memory(_bcm_mn_mmu_info[unit]);
   6593         sal_free(_bcm_mn_mmu_info[unit]);
   6594         _bcm_mn_mmu_info[unit] = NULL;
   6595     }
   6596     soc_monterey_shadow_free(unit);
   6597     return BCM_E_NONE;
   6598 }
   6599 
   6600 /*
   6601  * Function:
   6602  *     bcm_mn_cosq_config_set
   6603  * Purpose:
   6604  *     Set the number of COS queues
   6605  * Parameters:
   6606  *     unit - unit number
   6607  *     numq - number of COS queues (1-8).
   6608  * Returns:
   6609  *     BCM_E_XXX
   6610  */
   6611 int
   6612 bcm_mn_cosq_config_set(int unit, int numq)
   6613 {
   6614     port_cos_map_entry_t cos_map_entries[16];
   6615     port_cos_map_entry_t hg_cos_map_entries[16];
   6616     void *entries[1], *hg_entries[1];
   6617     uint32 index, hg_index;
   6618     int count, hg_count;
   6619     bcm_port_t port;
   6620     int cos, prio;
   6621     uint32 i;
   6622     int ref_count;
   6623     int cpu_hg_index = 0;
   6624 
   6625     if (numq < 1 || numq > BCM_MN_COS_MAX) {
   6626         return BCM_E_PARAM;
   6627     }
   6628 
   6629     /* clear out old profiles. */
   6630     index = 0;
   6631     while (index < soc_mem_index_count(unit, PORT_COS_MAPm)) {
   6632         BCM_IF_ERROR_RETURN(soc_profile_mem_ref_count_get(unit,
   6633                                       _bcm_mn_cos_map_profile[unit],
   6634                                       index, &ref_count));
   6635         if (ref_count > 0) {
   6636             while (ref_count) {
   6637                 if (!soc_profile_mem_delete(unit, _bcm_mn_cos_map_profile[unit], index)) {
   6638                     ref_count -= 1;
   6639                 }
   6640             }
   6641         }
   6642         index += 16;
   6643     }
   6644 
   6645     /* Distribute first 8 internal priority levels into the specified number
   6646      * of cosq, map remaining internal priority levels to highest priority
   6647      * cosq */
   6648     sal_memset(cos_map_entries, 0, sizeof(cos_map_entries));
   6649     entries[0] = &cos_map_entries;
   6650     hg_entries[0] = &hg_cos_map_entries;
   6651     prio = 0;
   6652     for (cos = 0; cos < numq; cos++) {
   6653         for (i = 8 / numq + (cos < 8 % numq ? 1 : 0); i > 0; i--) {
   6654             soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio],
   6655                                 UC_COS1f, cos);
   6656             soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio],
   6657                                 MC_COS1f, cos);
   6658             soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio],
   6659                                 HG_COSf, cos);
   6660             soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio],
   6661                                 RQE_Q_NUMf, cos);
   6662             prio++;
   6663         }
   6664     }
   6665     for (prio = 8; prio < 16; prio++) {
   6666         soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio],
   6667                             UC_COS1f, numq - 1);
   6668         soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio],
   6669                             MC_COS1f, numq - 1);
   6670         soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio],
   6671                             HG_COSf, numq - 1);
   6672         soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio],
   6673                             RQE_Q_NUMf, numq - 1);
   6674     }
   6675 
   6676     /* Map internal priority levels to CPU CoS queues */
   6677     BCM_IF_ERROR_RETURN(_bcm_esw_cpu_cosq_mapping_default_set(unit, numq));
   6678 
   6679 #ifdef BCM_COSQ_HIGIG_MAP_DISABLE
   6680     /* Use identical mapping for Higig port */
   6681     sal_memset(hg_cos_map_entries, 0, sizeof(hg_cos_map_entries));
   6682     prio = 0;
   6683     for (prio = 0; prio < 8; prio++) {
   6684         soc_mem_field32_set(unit, PORT_COS_MAPm, &hg_cos_map_entries[prio],
   6685                             UC_COS1f, prio);
   6686         soc_mem_field32_set(unit, PORT_COS_MAPm, &hg_cos_map_entries[prio],
   6687                             MC_COS1f, prio);
   6688         soc_mem_field32_set(unit, PORT_COS_MAPm, &hg_cos_map_entries[prio],
   6689                             RQE_Q_NUMf, prio);
   6690     }
   6691     for (prio = 8; prio < 13; prio++) {
   6692         soc_mem_field32_set(unit, PORT_COS_MAPm, &hg_cos_map_entries[prio],
   6693                             UC_COS1f, 7);
   6694         soc_mem_field32_set(unit, PORT_COS_MAPm, &hg_cos_map_entries[prio],
   6695                             MC_COS1f, 7);
   6696         soc_mem_field32_set(unit, PORT_COS_MAPm, &hg_cos_map_entries[prio],
   6697                             RQE_Q_NUMf, 7);
   6698     }
   6699 #else /* BCM_COSQ_HIGIG_MAP_DISABLE */
   6700     sal_memcpy(hg_cos_map_entries, cos_map_entries, sizeof(cos_map_entries));
   6701 #endif /* !BCM_COSQ_HIGIG_MAP_DISABLE */
   6702 
   6703     BCM_IF_ERROR_RETURN
   6704         (soc_profile_mem_add(unit, _bcm_mn_cos_map_profile[unit], 
   6705                                             entries, 16, &index));
   6706     soc_mem_field32_set(unit, PORT_COS_MAPm, &hg_cos_map_entries[14],
   6707                                HG_COSf, 8);
   6708     soc_mem_field32_set(unit, PORT_COS_MAPm, &hg_cos_map_entries[15],
   6709                                HG_COSf, 9);
   6710 
   6711     BCM_IF_ERROR_RETURN
   6712         (soc_profile_mem_add(unit, _bcm_mn_cos_map_profile[unit], 
   6713                                             hg_entries, 16, &hg_index));
   6714     count = 0;
   6715     hg_count = 0;
   6716     PBMP_ALL_ITER(unit, port) {
   6717         if (IS_LB_PORT(unit, port)) {
   6718             continue;
   6719         }
   6720         
   6721         if (IS_HG_PORT(unit, port)) {
   6722             BCM_IF_ERROR_RETURN
   6723                 (soc_mem_field32_modify(unit, COS_MAP_SELm, port, SELECTf,
   6724                                         hg_index / 16));
   6725             hg_count++;
   6726         } else {
   6727             BCM_IF_ERROR_RETURN
   6728                 (soc_mem_field32_modify(unit, COS_MAP_SELm, port, SELECTf,
   6729                                         index / 16));
   6730             count++;
   6731         }
   6732     }
   6733 
   6734     cpu_hg_index = SOC_INFO(unit).cpu_hg_index;
   6735     if (cpu_hg_index != -1) {
   6736         BCM_IF_ERROR_RETURN
   6737             (soc_mem_field32_modify(unit, COS_MAP_SELm,
   6738                 cpu_hg_index, SELECTf, index / 16));
   6739         count++;
   6740     }
   6741 
   6742     for (i = 1; i < count; i++) {
   6743         soc_profile_mem_reference(unit, _bcm_mn_cos_map_profile[unit], index, 0);
   6744     }
   6745     for (i = 1; i < hg_count; i++) {
   6746         soc_profile_mem_reference(unit, _bcm_mn_cos_map_profile[unit],
   6747                                   hg_index, 0);
   6748     }
   6749 
   6750     /* Delete the default higig cos map profile for the non-higig system */
   6751     if (hg_count == 0) {
   6752         soc_profile_mem_delete(unit, _bcm_mn_cos_map_profile[unit], hg_index);
   6753     }
   6754 
   6755     _MN_NUM_COS(unit) = numq;
   6756 
   6757     return BCM_E_NONE;
   6758 }
   6759 
   6760 STATIC int 
   6761 _bcm_mn_cosq_egress_sp_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 
   6762                         int *p_pool_start, int *p_pool_end)
   6763 {
   6764     int local_port;
   6765     int pool;
   6766     if (cosq == BCM_COS_INVALID) {
   6767         *p_pool_start = 0;
   6768         *p_pool_end = 3;
   6769         return BCM_E_NONE;
   6770     }
   6771 
   6772     BCM_IF_ERROR_RETURN
   6773         (_bcm_mn_cosq_index_resolve(unit, gport, cosq,
   6774                                      _BCM_MN_COSQ_INDEX_STYLE_EGR_POOL,
   6775                                      &local_port, &pool, NULL));
   6776 
   6777     *p_pool_start = *p_pool_end = pool;
   6778     return BCM_E_NONE;
   6779 }
   6780 
   6781 STATIC int 
   6782 _bcm_mn_cosq_ingress_sp_get(int unit, bcm_gport_t gport, bcm_cos_queue_t pri_grp, 
   6783                          int *p_pool_start, int *p_pool_end)
   6784 {
   6785     int local_port;
   6786     uint32 rval, pool;
   6787     static const soc_field_t prigroup_spid_field[] = {
   6788         PG0_SPIDf, PG1_SPIDf, PG2_SPIDf, PG3_SPIDf,
   6789         PG4_SPIDf, PG5_SPIDf, PG6_SPIDf, PG7_SPIDf
   6790     };
   6791     
   6792     if (pri_grp == BCM_COS_INVALID) {
   6793         *p_pool_start = 0;
   6794         *p_pool_end = 3;
   6795         return BCM_E_NONE;
   6796     }
   6797 
   6798     BCM_IF_ERROR_RETURN
   6799             (_bcm_mn_cosq_localport_resolve(unit, gport, &local_port));
   6800 
   6801     if (!SOC_PORT_VALID(unit, local_port)) {
   6802         return BCM_E_PORT;
   6803     }
   6804 
   6805     if ((pri_grp < 0) || (pri_grp >= 8)) {
   6806         return BCM_E_PARAM;
   6807     }
   6808 
   6809     SOC_IF_ERROR_RETURN(READ_THDI_PORT_PG_SPIDr(unit, local_port, &rval));
   6810     pool = soc_reg_field_get(unit, THDI_PORT_PG_SPIDr, rval, 
   6811                                 prigroup_spid_field[pri_grp]);
   6812     
   6813     *p_pool_start = *p_pool_end = pool;
   6814     return BCM_E_NONE;
   6815 }
   6816 
   6817 STATIC int 
   6818 _bcm_mn_cosq_ingress_pg_get(int unit, bcm_gport_t gport, bcm_cos_queue_t pri, 
   6819                          int *p_pg_start, int *p_pg_end)
   6820 {
   6821     bcm_port_t local_port;
   6822     uint32  rval,pool;
   6823     soc_reg_t reg = INVALIDr;
   6824     static const soc_reg_t prigroup_reg[] = {
   6825         THDI_PORT_PRI_GRP0r, THDI_PORT_PRI_GRP1r
   6826     };
   6827     static const soc_field_t prigroup_field[] = {
   6828         PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf,
   6829         PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf,
   6830         PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf,
   6831         PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf
   6832     };
   6833 
   6834     if (pri == BCM_COS_INVALID) {
   6835         *p_pg_start = 0;
   6836         *p_pg_end = 7;
   6837         return BCM_E_NONE;
   6838     }
   6839 
   6840     BCM_IF_ERROR_RETURN
   6841             (_bcm_mn_cosq_localport_resolve(unit, gport, &local_port));
   6842 
   6843     if (!SOC_PORT_VALID(unit, local_port)) {
   6844         return BCM_E_PORT;
   6845     }
   6846 
   6847     if (pri > 15) {
   6848         return BCM_E_PARAM;
   6849     }
   6850        /* get PG for port using Port+Cos */
   6851     if (pri < 8) {
   6852         reg = prigroup_reg[0];
   6853     } else {
   6854         reg = prigroup_reg[1];
   6855     }
   6856 
   6857     SOC_IF_ERROR_RETURN
   6858         (soc_reg32_get(unit, reg, local_port, 0, &rval));
   6859         pool = soc_reg_field_get(unit, reg, rval, prigroup_field[pri]);
   6860 
   6861     *p_pg_start = *p_pg_end = pool;
   6862     return BCM_E_NONE;
   6863 }
   6864 
   6865 
   6866 STATIC _bcm_bst_cb_ret_t
   6867 _bcm_mn_bst_index_resolve(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
   6868                     bcm_bst_stat_id_t bid, int *pipe, int *start_hw_index, 
   6869                     int *end_hw_index, int *rcb_data, void **cb_data, int *bcm_rv)
   6870 {
   6871     int phy_port, mmu_port, local_port;
   6872     _bcm_mn_cosq_node_t *node = NULL;
   6873     soc_info_t *si;
   6874     uint32 rval = 0;
   6875     int pool_idx;
   6876     *bcm_rv = BCM_E_NONE;
   6877 
   6878 #define _BST_IF_ERROR_GOTO_EXIT(op) \
   6879     do { int __rv__; if ((__rv__ = (op)) < 0) { goto error_exit; } } while(0)
   6880 
   6881     _BST_IF_ERROR_GOTO_EXIT
   6882             (_bcm_mn_cosq_localport_resolve(unit, gport, &local_port));
   6883 
   6884     si = &SOC_INFO(unit);
   6885     phy_port = si->port_l2p_mapping[local_port];
   6886     mmu_port = si->port_p2m_mapping[phy_port];
   6887 
   6888     *pipe = 0;
   6889 
   6890     if (bid == bcmBstStatIdDevice) {
   6891         *start_hw_index = *end_hw_index = 0;
   6892         *bcm_rv = BCM_E_NONE;
   6893         return _BCM_BST_RV_OK;
   6894     }
   6895 
   6896     if (bid == bcmBstStatIdEgrPool) {
   6897         /* Egress Unicast Pool */
   6898         if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   6899             goto error_exit;
   6900         }        
   6901         _BST_IF_ERROR_GOTO_EXIT(_bcm_mn_cosq_egress_sp_get(unit, gport, cosq, 
   6902                                     start_hw_index, end_hw_index));
   6903         return _BCM_BST_RV_OK;
   6904     } else if (bid == bcmBstStatIdEgrMCastPool) {
   6905         /* Egress Multicast Pool */
   6906         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   6907             goto error_exit;
   6908         }
   6909         _BST_IF_ERROR_GOTO_EXIT(_bcm_mn_cosq_egress_sp_get(unit, gport, cosq, 
   6910                                     start_hw_index, end_hw_index));
   6911         return _BCM_BST_RV_OK;         
   6912     } else if (bid == bcmBstStatIdIngPool) {
   6913         /* ingress pool */
   6914         _BST_IF_ERROR_GOTO_EXIT(_bcm_mn_cosq_ingress_sp_get(unit, gport, cosq, 
   6915                                     start_hw_index, end_hw_index));
   6916         return _BCM_BST_RV_OK;
   6917     } else if (bid == bcmBstStatIdRQEPool) {
   6918         /* RQE pool */
   6919         if (cosq == BCM_COS_INVALID) {
   6920             *start_hw_index = 0;
   6921             *end_hw_index = _MONTEREY_MMU_NUM_POOL - 1;
   6922         } else if ((cosq < 0) || (cosq >= _MONTEREY_MMU_NUM_RQE_QUEUES)) {
   6923             return BCM_E_PARAM;
   6924         } else {
   6925             SOC_IF_ERROR_RETURN
   6926                 (READ_MMU_THDR_DB_CONFIG1_PRIQr(unit, cosq, &rval));
   6927 
   6928             pool_idx = soc_reg_field_get(unit, MMU_THDR_DB_CONFIG1_PRIQr, rval,
   6929                     SPIDf);
   6930             *start_hw_index = *end_hw_index = pool_idx;
   6931         }
   6932         return _BCM_BST_RV_OK;
   6933     } else if (bid == bcmBstStatIdRQEQueue) {
   6934         /* RQE queue */
   6935         if (cosq == BCM_COS_INVALID) {
   6936             *start_hw_index = 0;
   6937             *end_hw_index = _MONTEREY_MMU_NUM_RQE_QUEUES - 1;
   6938         } else if ((cosq < 0) || (cosq >= _MONTEREY_MMU_NUM_RQE_QUEUES)) {
   6939             return BCM_E_PARAM;
   6940         } else {
   6941             *start_hw_index = *end_hw_index = cosq;
   6942         }
   6943         return _BCM_BST_RV_OK;
   6944     } else if (bid == bcmBstStatIdUCQueueGroup) {
   6945         /* unicast queue group */
   6946         BCM_IF_ERROR_RETURN(_bcm_mn_cosq_index_resolve(unit,
   6947                     gport, cosq, _BCM_MN_COSQ_INDEX_STYLE_UCAST_QUEUE_GROUP,
   6948                     NULL, start_hw_index, NULL));
   6949         *end_hw_index = *start_hw_index;
   6950         return _BCM_BST_RV_OK;
   6951     }
   6952 
   6953     if (bid == bcmBstStatIdPortPool) {
   6954         /* ingress pool */
   6955         _BST_IF_ERROR_GOTO_EXIT(
   6956                 _bcm_mn_cosq_ingress_sp_get(unit, gport, cosq, 
   6957                                     start_hw_index, end_hw_index));
   6958         *start_hw_index = ((mmu_port) * 4) + *start_hw_index;
   6959         *end_hw_index = ((mmu_port) * 4) + *end_hw_index;
   6960     } else if ((bid == bcmBstStatIdPriGroupShared) || 
   6961                (bid == bcmBstStatIdPriGroupHeadroom)) {
   6962         /* ingress pool */
   6963         _BST_IF_ERROR_GOTO_EXIT(
   6964                 _bcm_mn_cosq_ingress_pg_get(unit, gport, cosq, 
   6965                                     start_hw_index, end_hw_index));
   6966         *start_hw_index = ((mmu_port) * 8) + *start_hw_index;
   6967         *end_hw_index = ((mmu_port) * 8) + *end_hw_index;
   6968     } else {
   6969         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   6970             if (bid != bcmBstStatIdUcast) {
   6971                 goto error_exit;
   6972             }
   6973             _BST_IF_ERROR_GOTO_EXIT
   6974                 (_bcm_mn_cosq_node_get(unit, gport, 0, NULL, 
   6975                                         &local_port, NULL, &node));
   6976             if (!node) {
   6977                 goto error_exit;
   6978             }
   6979             *start_hw_index = *end_hw_index = node->hw_index;
   6980         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   6981             if (bid != bcmBstStatIdMcast) {
   6982                 goto error_exit;
   6983             }
   6984             _BST_IF_ERROR_GOTO_EXIT
   6985                 (_bcm_mn_cosq_node_get(unit, gport, 0, NULL, 
   6986                                         &local_port, NULL, &node));
   6987             if (!node) {
   6988                 goto error_exit;
   6989             }
   6990             *start_hw_index = *end_hw_index = node->hw_index - _BCM_MN_NUM_L2_UC_LEAVES;
   6991         } else { 
   6992             _BST_IF_ERROR_GOTO_EXIT(_bcm_mn_cosq_port_has_ets(unit, local_port));
   6993             
   6994             if (cosq < 0) {
   6995                 if (bid == bcmBstStatIdUcast) {
   6996                     _BST_IF_ERROR_GOTO_EXIT(_bcm_mn_cosq_index_resolve(unit, 
   6997                           local_port, 0, _BCM_MN_COSQ_INDEX_STYLE_UCAST_QUEUE, 
   6998                           NULL, start_hw_index, NULL));
   6999 
   7000                     _BST_IF_ERROR_GOTO_EXIT(_bcm_mn_cosq_index_resolve(unit, 
   7001                           local_port, BCM_MN_COS_MAX - 1, 
   7002                           _BCM_MN_COSQ_INDEX_STYLE_UCAST_QUEUE, 
   7003                           NULL, end_hw_index, NULL));
   7004 
   7005                 } else {
   7006                     _BST_IF_ERROR_GOTO_EXIT(_bcm_mn_cosq_index_resolve(unit, 
   7007                           local_port, 0, _BCM_MN_COSQ_INDEX_STYLE_MCAST_QUEUE, 
   7008                           NULL, start_hw_index, NULL));
   7009                     *start_hw_index -= _BCM_MN_NUM_L2_UC_LEAVES;
   7010 
   7011                     _BST_IF_ERROR_GOTO_EXIT(_bcm_mn_cosq_index_resolve(unit, 
   7012                           local_port, BCM_MN_COS_MAX - 1, 
   7013                           _BCM_MN_COSQ_INDEX_STYLE_MCAST_QUEUE, 
   7014                           NULL, end_hw_index, NULL));
   7015                     *end_hw_index -= _BCM_MN_NUM_L2_UC_LEAVES;
   7016                 }
   7017             } else {
   7018                 if (bid == bcmBstStatIdUcast) {
   7019                     _BST_IF_ERROR_GOTO_EXIT(_bcm_mn_cosq_index_resolve(unit, 
   7020                           local_port, cosq, _BCM_MN_COSQ_INDEX_STYLE_UCAST_QUEUE, 
   7021                           NULL, start_hw_index, NULL));
   7022                     *end_hw_index = *start_hw_index;
   7023                 } else {
   7024                     _BST_IF_ERROR_GOTO_EXIT(_bcm_mn_cosq_index_resolve(unit, 
   7025                           local_port, cosq, _BCM_MN_COSQ_INDEX_STYLE_MCAST_QUEUE, 
   7026                           NULL, start_hw_index, NULL));
   7027                     *start_hw_index -= _BCM_MN_NUM_L2_UC_LEAVES;
   7028                     *end_hw_index = *start_hw_index;
   7029                 }
   7030             } /* if (cosq < 0) */
   7031         } /* if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { */
   7032     } /* if (bid == bcmBstStatIdPortPool) { */
   7033    
   7034     *bcm_rv = BCM_E_NONE;
   7035     return _BCM_BST_RV_OK;
   7036 
   7037 error_exit:
   7038     *bcm_rv = BCM_E_PARAM;
   7039     return _BCM_BST_RV_ERROR;
   7040 }
   7041 
   7042 
   7043 
   7044 STATIC int
   7045 _bcm_mn_cosq_bst_map_resource_to_gport_cos(int unit, bcm_bst_stat_id_t bid, int port, 
   7046                          int index, bcm_gport_t *gport, bcm_cos_t *cosq)
   7047 {
   7048     soc_info_t *si;
   7049     _bcm_mn_cosq_node_t *node;
   7050     _bcm_mn_mmu_info_t *mmu_info;
   7051     _bcm_mn_pipe_resources_t   *pres;
   7052     int ii, pipe;
   7053     int hw_index, mmu_port, phy_port;
   7054 
   7055     pipe = _MN_XPIPE;
   7056     mmu_info = _bcm_mn_mmu_info[unit];
   7057     pres = _BCM_MN_PRESOURCES(mmu_info, pipe);
   7058     si = &SOC_INFO(unit);
   7059 
   7060     switch (bid) {
   7061     case bcmBstStatIdDevice:
   7062         *gport = -1;
   7063         *cosq = BCM_COS_INVALID;
   7064         break;
   7065 
   7066     case bcmBstStatIdIngPool:
   7067     case bcmBstStatIdEgrPool:
   7068     case bcmBstStatIdRQEPool:
   7069         *gport = -1;
   7070         *cosq = index;
   7071         break;
   7072 
   7073     case bcmBstStatIdRQEQueue:
   7074         *gport = -1;
   7075         *cosq = index % _MONTEREY_MMU_NUM_RQE_QUEUES;
   7076         break;
   7077 
   7078     case bcmBstStatIdUCQueueGroup:
   7079         *gport = index;
   7080         *cosq =  -1;
   7081         break;
   7082 
   7083     case bcmBstStatIdPortPool:
   7084         mmu_port = index/4;
   7085         phy_port = si->port_m2p_mapping[mmu_port];
   7086         *gport = si->port_p2l_mapping[phy_port];
   7087         *cosq = index % 4;
   7088         break;
   7089 
   7090     case bcmBstStatIdPriGroupHeadroom:
   7091     case bcmBstStatIdPriGroupShared:
   7092         mmu_port = index / 8;
   7093         phy_port = si->port_m2p_mapping[mmu_port];
   7094         *gport = si->port_p2l_mapping[phy_port];
   7095         *cosq = index % 8;
   7096         break;
   7097 
   7098     case bcmBstStatIdUcast:
   7099         pipe = _MN_XPIPE;
   7100         hw_index = soc_monterey_l2_hw_index(unit, index, 1);
   7101 
   7102         if (mmu_info->ets_mode) {
   7103             for (ii = 0; ii < _BCM_MN_NUM_L2_UC_LEAVES; ii++) {
   7104                 node = &pres->p_queue_node[ii];
   7105                 if (node->in_use == TRUE) {
   7106 
   7107                     if (node->hw_index == hw_index) { 
   7108                         *gport = node->gport;
   7109                         *cosq = 0;
   7110                         break;
   7111                     }
   7112                 }
   7113             }
   7114         } else {
   7115             int port_uc_base = 0;
   7116             int port_num_uc = 0;
   7117             PBMP_ALL_ITER(unit, port) {
   7118 
   7119                 if (IS_LB_PORT(unit, port)) {
   7120                     continue;
   7121                 }
   7122 
   7123                 port_num_uc = si->port_num_uc_cosq[port];
   7124                 port_uc_base = si->port_uc_cosq_base[port];
   7125 
   7126                 if ((index >= port_uc_base) &&
   7127                     (index < port_uc_base + port_num_uc)) {
   7128                     *gport = port;
   7129                     *cosq = index - port_uc_base;
   7130                     break;
   7131                 }
   7132             }
   7133         }
   7134         break;
   7135     case bcmBstStatIdMcast:
   7136         pipe = _MN_XPIPE;
   7137         hw_index = soc_monterey_l2_hw_index(unit, index, 0);
   7138 
   7139         if (mmu_info->ets_mode) {
   7140             for (ii = 0; ii < _BCM_MN_NUM_L2_MC_LEAVES; ii++) {
   7141                 node = &pres->p_queue_node[ii];
   7142                 if (node->in_use == TRUE) {
   7143 
   7144                     if (node->hw_index == hw_index) {
   7145                         *gport = node->gport;
   7146                         *cosq = 0;
   7147                         break;
   7148                     }
   7149                 }
   7150             }
   7151         } else {
   7152             int port_mc_base = 0;
   7153             int port_num_mc = 0;
   7154             PBMP_ALL_ITER(unit, port) {
   7155 
   7156                 port_num_mc = si->port_num_cosq[port];
   7157                 port_mc_base = si->port_cosq_base[port];
   7158 
   7159                 if ((index >= port_mc_base) &&
   7160                     (index < port_mc_base + port_num_mc)) {
   7161                     *gport = port;
   7162                     *cosq = index - port_mc_base;
   7163                     break;
   7164                 }
   7165             }
   7166         }
   7167         break;
   7168     case bcmBstStatIdEgrMCastPool:
   7169         /* MMU_THDM_DB_POOL_MC_BST_STAT only 4 indices */
   7170         *gport = -1;
   7171         *cosq = index;
   7172         break;
   7173     default:
   7174         break;
   7175     }
   7176 
   7177     return BCM_E_NONE;
   7178 }
   7179 
   7180 STATIC int
   7181 _bcm_mn_cosq_cpri_gport_init_config(int unit,
   7182                                     bcm_port_t port,
   7183                                     bcm_gport_t gport,
   7184                                     bcm_cos_queue_t cosq,
   7185                                     int index,
   7186                                     int uc_index,
   7187                                     int mc_index)
   7188 {
   7189     uint32 min_quantum;
   7190     uint32 max_quantum;
   7191     uint32 kbits_burst_min;
   7192     uint32 kbits_burst_max;
   7193     uint32 flags;
   7194     int roe_speed_rsvd4, eth_mode = 1, spid;
   7195     _bcm_mn_mtro_node_info_t *node_info;
   7196     uint32 uc_entry[SOC_MAX_MEM_WORDS];
   7197     uint32 mc_entry[SOC_MAX_MEM_WORDS];
   7198     soc_mem_t uc_mem, mc_mem;
   7199 
   7200     if ((index < 0) || (index >= _BCM_MN_NUM_CPRI_CONFIG_NODE)) {
   7201         return BCM_E_PARAM;
   7202     }
   7203     roe_speed_rsvd4 = soc_property_port_get(unit, port,
   7204                          spn_RSVD4_PORT_INIT_SPEED_ID, -1);
   7205     if (roe_speed_rsvd4 != -1) {
   7206         node_info = &mtro1_max_bucket_info[0];
   7207     } else {
   7208         node_info = &mtro0_max_bucket_info[0];
   7209         if (!eth_mode && (index == 5)) {
   7210             index = 8;
   7211         }
   7212    }
   7213    BCM_IF_ERROR_RETURN(
   7214         _bcm_mn_cosq_bucket_get(unit, gport, cosq, &min_quantum,
   7215                                 &max_quantum, &kbits_burst_min,
   7216                                 &kbits_burst_max, &flags));
   7217     /* Assign all params */
   7218     max_quantum = node_info[index].rate;
   7219     kbits_burst_max = node_info[index].bucket_threshold;
   7220     flags = node_info[index].mode;
   7221 
   7222     BCM_IF_ERROR_RETURN(
   7223         _bcm_mn_cosq_bucket_set(unit, gport, cosq, min_quantum,
   7224                                max_quantum, kbits_burst_min,
   7225                                 kbits_burst_max, flags));
   7226     spid = node_info[index].spid;
   7227     uc_mem = MMU_THDU_XPIPE_Q_TO_QGRP_MAPm;
   7228    mc_mem = MMU_THDM_MCQE_QUEUE_CONFIG_0m;
   7229 
   7230 
   7231    BCM_IF_ERROR_RETURN(soc_mem_read(unit, uc_mem, MEM_BLOCK_ALL,
   7232                                      uc_index, uc_entry));
   7233     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mc_mem, MEM_BLOCK_ALL,
   7234                                      mc_index, mc_entry));
   7235 
   7236     soc_mem_field32_set(unit, uc_mem, uc_entry, Q_SPIDf, spid);
   7237     soc_mem_field32_set(unit, mc_mem, mc_entry, Q_SPIDf, spid);
   7238 
   7239     BCM_IF_ERROR_RETURN(soc_mem_write(unit, uc_mem, MEM_BLOCK_ALL,
   7240                                       uc_index, uc_entry));
   7241     BCM_IF_ERROR_RETURN(soc_mem_write(unit, mc_mem, MEM_BLOCK_ALL,
   7242                                       mc_index, mc_entry));
   7243 
   7244     return BCM_E_NONE;
   7245 
   7246 }
   7247 
   7248 int
   7249 _bcm_mn_port_hsp_config_set(int unit, 
   7250                              bcm_port_t port) 
   7251 {
   7252     bcm_gport_t port_sched, l0_sched[5];
   7253     bcm_gport_t l1_sched[10];
   7254     bcm_gport_t uc_cosq[10], mc_cosq[10];
   7255     int i, index, cpri_port = 0, uc_index, mc_index;
   7256     uint32 num_of_l0 = 5; 
   7257     uint32 num_of_l1 = 10; 
   7258 
   7259     bcm_switch_control_t sc[] = { bcmSwitchPFCClass0Queue,
   7260                                   bcmSwitchPFCClass1Queue,
   7261                                   bcmSwitchPFCClass2Queue,
   7262                                   bcmSwitchPFCClass3Queue,
   7263                                   bcmSwitchPFCClass4Queue,
   7264                                   bcmSwitchPFCClass5Queue,
   7265                                   bcmSwitchPFCClass6Queue,
   7266                                   bcmSwitchPFCClass7Queue
   7267                                 };
   7268 
   7269     cpri_port = IS_CPRI_PORT(unit, port);
   7270     BCM_IF_ERROR_RETURN
   7271         (bcm_mn_cosq_gport_add(unit, port, num_of_l0 , 0, &port_sched));
   7272  
   7273     for (i = 0; i < num_of_l0; i++) {
   7274         BCM_IF_ERROR_RETURN
   7275             (bcm_mn_cosq_gport_add(unit, port, 8,
   7276                                    BCM_COSQ_GPORT_SCHEDULER, 
   7277                                    &l0_sched[i]));
   7278         BCM_IF_ERROR_RETURN
   7279             (bcm_mn_cosq_gport_attach(unit, l0_sched[i], port_sched, i));
   7280     }
   7281 
   7282     for (i = 0; i < num_of_l1; i++) {
   7283         BCM_IF_ERROR_RETURN
   7284             (bcm_mn_cosq_gport_add(unit, port, 2,
   7285                                    BCM_COSQ_GPORT_SCHEDULER, 
   7286                                    &l1_sched[i]));
   7287         if (cpri_port) {
   7288             index = i == 0 ? 1 : (i < 8 ? 2 : 4);
   7289         } else {
   7290             index = i < 8 ? 1 : 4;
   7291         }
   7292 
   7293         BCM_IF_ERROR_RETURN
   7294             (bcm_mn_cosq_gport_attach(unit, l1_sched[i], l0_sched[index],
   7295                                       i >= 8 ? i - 8 :i));
   7296        BCM_IF_ERROR_RETURN
   7297                 (bcm_mn_cosq_gport_sched_set(unit, l0_sched[index], (i >= 8 ? i - 8 :i),
   7298                                           BCM_COSQ_DEFICIT_ROUND_ROBIN, 1));
   7299         BCM_IF_ERROR_RETURN
   7300             (bcm_mn_cosq_gport_add(unit, port, 1, BCM_COSQ_GPORT_UCAST_QUEUE_GROUP,
   7301                                    &uc_cosq[i]));
   7302         BCM_IF_ERROR_RETURN
   7303             (bcm_mn_cosq_gport_attach(unit, uc_cosq[i], l1_sched[i], 0));
   7304         BCM_IF_ERROR_RETURN
   7305             (bcm_mn_cosq_gport_sched_set(unit, l1_sched[i], 0,
   7306                                           BCM_COSQ_DEFICIT_ROUND_ROBIN, 1));
   7307         BCM_IF_ERROR_RETURN
   7308             (bcm_mn_cosq_gport_add(unit, port, 1, BCM_COSQ_GPORT_MCAST_QUEUE_GROUP,
   7309                                    &mc_cosq[i]));
   7310         BCM_IF_ERROR_RETURN
   7311             (bcm_mn_cosq_gport_attach(unit, mc_cosq[i], l1_sched[i], 1));
   7312         BCM_IF_ERROR_RETURN
   7313             (bcm_mn_cosq_gport_sched_set(unit, l1_sched[i], 1,
   7314                                           BCM_COSQ_DEFICIT_ROUND_ROBIN, 1));
   7315     }
   7316     if (cpri_port) {
   7317         uc_index = BCM_GPORT_UCAST_QUEUE_GROUP_QID_GET(uc_cosq[0]);
   7318         mc_index = BCM_GPORT_MCAST_QUEUE_GROUP_QID_GET(mc_cosq[0]);
   7319         BCM_IF_ERROR_RETURN(
   7320             _bcm_mn_cosq_cpri_gport_init_config(unit, port, port_sched,
   7321                                                 2, 0, uc_index, mc_index));
   7322         BCM_IF_ERROR_RETURN(
   7323             bcm_esw_port_control_set(unit, port, bcmPortControlLLFCReceive, 1));
   7324         for (i = 1; i < 8; i++) {
   7325              uc_index = BCM_GPORT_UCAST_QUEUE_GROUP_QID_GET(uc_cosq[i]);
   7326              mc_index = BCM_GPORT_MCAST_QUEUE_GROUP_QID_GET(mc_cosq[i]);
   7327              BCM_IF_ERROR_RETURN(
   7328                  _bcm_mn_cosq_cpri_gport_init_config(unit, port, l0_sched[2],
   7329                                                      i, i, uc_index, mc_index));
   7330              BCM_IF_ERROR_RETURN(
   7331                  bcm_mn_cosq_port_pfc_op(unit, port, sc[i], _BCM_COSQ_OP_ADD,
   7332                                          &l1_sched[i], 1));
   7333         }
   7334     }
   7335 
   7336     return BCM_E_NONE;
   7337 }
   7338 
   7339 int 
   7340 bcm_mn_init_fc_map_tbl(int unit) 
   7341 {
   7342     int max_index;
   7343     int max_nodes; 
   7344     uint32 map_entry[SOC_MAX_MEM_WORDS];
   7345     int mem;
   7346     int index;
   7347     int field ;
   7348     static const soc_field_t indexf[] = {
   7349         INDEX0f, INDEX1f, INDEX2f, INDEX3f
   7350     };
   7351     static const soc_mem_t memx[] = {
   7352         MMU_INTFI_XPIPE_FC_MAP_TBL0m,
   7353         MMU_INTFI_XPIPE_FC_MAP_TBL1m,
   7354         MMU_INTFI_XPIPE_FC_MAP_TBL2m
   7355     };
   7356     static const soc_mem_t memy[] = {
   7357         MMU_INTFI_FC_ST_TBL0m,
   7358         MMU_INTFI_FC_ST_TBL1m,
   7359         MMU_INTFI_FC_ST_TBL2m,
   7360     };
   7361  
   7362     for ( mem = 0 ; mem < 3 ; mem++) 
   7363     { 
   7364        max_index = soc_mem_index_count(unit, memy[mem]) - 1;
   7365        max_nodes = soc_mem_index_count(unit,memx[mem]); 
   7366        for ( index = 0 ; index < max_nodes ; index++) 
   7367        {
   7368          SOC_IF_ERROR_RETURN(soc_mem_read(unit, memx[mem],
   7369                 MEM_BLOCK_ALL, index, &map_entry));
   7370          for (field = 0; field  <  COUNTOF(indexf); field++)
   7371          { 
   7372               soc_mem_field32_set(unit, memx[mem],
   7373                                    &map_entry, indexf[field], max_index);
   7374          }
   7375          SOC_IF_ERROR_RETURN(soc_mem_write(unit, memx[mem],
   7376                         MEM_BLOCK_ALL, index, &map_entry));
   7377        }
   7378      } 
   7379      return BCM_E_NONE;
   7380 }
   7381 STATIC int
   7382 _bcm_mn_cpu_port_config_set(int unit, int port)
   7383 {
   7384     bcm_gport_t port_sched, l0_sched;
   7385     bcm_gport_t l1_sched;
   7386     bcm_gport_t mc_cosq;
   7387     int i, j, k;
   7388     uint32 num_of_l0 = 5;
   7389     uint32 num_of_l1 = 1;
   7390 
   7391 
   7392     BCM_IF_ERROR_RETURN
   7393         (bcm_mn_cosq_gport_add(unit, port, num_of_l0 , 0, &port_sched));
   7394 
   7395     for (i = 0; i < num_of_l0; i++) {
   7396          if (i == 1) {
   7397              num_of_l1 = 4;
   7398          } else {
   7399              num_of_l1 = 1;
   7400          }
   7401          BCM_IF_ERROR_RETURN
   7402              (bcm_mn_cosq_gport_add(unit, port, num_of_l1,
   7403                                    BCM_COSQ_GPORT_SCHEDULER,
   7404                                    &l0_sched));
   7405          BCM_IF_ERROR_RETURN
   7406              (bcm_mn_cosq_gport_attach(unit, l0_sched, port_sched, i));
   7407          if ((i == 0) || (i == 4)) {
   7408               continue;
   7409          }
   7410          for (j = 0; j < num_of_l1; j++) {
   7411               BCM_IF_ERROR_RETURN
   7412                   (bcm_mn_cosq_gport_add(unit, port, 8,
   7413                                         BCM_COSQ_GPORT_SCHEDULER,
   7414                                         &l1_sched));
   7415               BCM_IF_ERROR_RETURN
   7416                   (bcm_mn_cosq_gport_attach(unit, l1_sched, l0_sched,
   7417                                             j));
   7418               for (k = 0; k < 8; k++) {
   7419                    BCM_IF_ERROR_RETURN
   7420                        (bcm_mn_cosq_gport_add(unit, port, 1, BCM_COSQ_GPORT_MCAST_QUEUE_GROUP,
   7421                                    &mc_cosq));
   7422                    BCM_IF_ERROR_RETURN
   7423                        (bcm_mn_cosq_gport_attach(unit, mc_cosq, l1_sched, k));
   7424              }
   7425         }
   7426     }
   7427     return BCM_E_NONE;
   7428 }
   7429 
   7430 STATIC int
   7431 _bcm_mn_lb_msec_port_config_set(int unit, int port)
   7432 {
   7433     bcm_gport_t port_sched, l0_sched[5];
   7434     bcm_gport_t l1_sched;
   7435     bcm_gport_t mc_cosq;
   7436     int i;
   7437     uint32 num_of_l0 = 5;
   7438     uint32 num_of_l1 = 10;
   7439     int index;
   7440 
   7441 
   7442     BCM_IF_ERROR_RETURN
   7443         (bcm_mn_cosq_gport_add(unit, port, num_of_l0 , 0, &port_sched));
   7444 
   7445     for (i = 0; i < num_of_l0; i++) {
   7446         BCM_IF_ERROR_RETURN
   7447             (bcm_mn_cosq_gport_add(unit, port, 8,
   7448                                    BCM_COSQ_GPORT_SCHEDULER,
   7449                                    &l0_sched[i]));
   7450         BCM_IF_ERROR_RETURN
   7451             (bcm_mn_cosq_gport_attach(unit, l0_sched[i], port_sched, i));
   7452     }
   7453 
   7454     for (i = 0; i < num_of_l1; i++) {
   7455         BCM_IF_ERROR_RETURN
   7456             (bcm_mn_cosq_gport_add(unit, port, 2,
   7457                                    BCM_COSQ_GPORT_SCHEDULER,
   7458                                    &l1_sched));
   7459         index = i < 8 ? 1 : 4;
   7460 
   7461         BCM_IF_ERROR_RETURN
   7462             (bcm_mn_cosq_gport_attach(unit, l1_sched, l0_sched[index],
   7463                                       i >= 8 ? i - 8 :i));
   7464         BCM_IF_ERROR_RETURN
   7465             (bcm_mn_cosq_gport_sched_set(unit, l0_sched[index], (i >= 8 ? i - 8 :i),
   7466                                          BCM_COSQ_DEFICIT_ROUND_ROBIN, 1));
   7467         BCM_IF_ERROR_RETURN
   7468             (bcm_mn_cosq_gport_add(unit, port, 1, BCM_COSQ_GPORT_MCAST_QUEUE_GROUP,
   7469                                    &mc_cosq));
   7470         BCM_IF_ERROR_RETURN
   7471             (bcm_mn_cosq_gport_attach(unit, mc_cosq, l1_sched, 1));
   7472     }
   7473     return BCM_E_NONE;
   7474 }
   7475 STATIC int
   7476 _bcm_mn_internal_port_config_set(int unit, int port)
   7477 {
   7478     if (IS_CPU_PORT(unit, port)) {
   7479         return _bcm_mn_cpu_port_config_set(unit, port);
   7480     } else if (IS_LB_PORT(unit, port) || IS_MACSEC_PORT(unit, port)) {
   7481         return _bcm_mn_lb_msec_port_config_set(unit, port);
   7482     } else {
   7483         return SOC_E_NONE;
   7484     }
   7485 }
   7486 
   7487 /*
   7488   * Function:
   7489   *     bcm_mn_cosq_default_llfc_profile_attach
   7490   * Purpose:
   7491   *     Add default entries for PRIO2COS_PROFILE register profile
   7492   * Parameters:
   7493   *     unit    - (IN) unit number
   7494   *     port    - (IN) port number
   7495   * Returns:
   7496   *     BCM_E_XXX
   7497   */
   7498  int
   7499  bcm_mn_cosq_default_llfc_profile_attach(int unit, int port)
   7500  {
   7501      soc_reg_t   reg;
   7502      soc_info_t *si;
   7503      bcm_port_t local_port;
   7504      int mmu_port, phy_port;
   7505      uint32 profile_index;
   7506      uint64 tmp, rval, index_map;
   7507      uint64 rval64s[16], *prval64s[1];
   7508      static const soc_reg_t llfc_cfgr[] = {
   7509          PORT_PFC_CFG0r, PORT_PFC_CFG1r, PORT_PFC_CFG2r
   7510      };
   7511  
   7512      BCM_IF_ERROR_RETURN(
   7513          _bcm_mn_cosq_localport_resolve(unit, port, &local_port));
   7514  
   7515      si = &SOC_INFO(unit);
   7516      phy_port = si->port_l2p_mapping[local_port];
   7517      mmu_port = si->port_p2m_mapping[phy_port];
   7518      reg = llfc_cfgr[mmu_port/32];
   7519 /* Add default entries for PRIO2COS_PROFILE register profile */
   7520      sal_memset(rval64s, 0, sizeof(rval64s));
   7521      prval64s[0] = rval64s;
   7522  
   7523      BCM_IF_ERROR_RETURN
   7524              (soc_profile_reg_add(unit, _bcm_mn_llfc_profile[unit],
   7525                                   prval64s, 16, &profile_index));
   7526  
   7527      BCM_IF_ERROR_RETURN(soc_reg64_get(unit, reg, 0, 0, &rval));
   7528      index_map = soc_reg64_field_get(unit, reg, rval, PROFILE_INDEXf);
   7529 
   7530      COMPILER_64_SET(tmp, 0, 3);
   7531      COMPILER_64_SHL(tmp, (mmu_port % 32) * 2);
   7532      COMPILER_64_NOT(tmp);
   7533      COMPILER_64_AND(index_map, tmp);
   7534      COMPILER_64_SET(tmp, 0, profile_index/16);
   7535      COMPILER_64_SHL(tmp, (mmu_port % 32) * 2);
   7536      COMPILER_64_OR(index_map, tmp);
   7537  
   7538      soc_reg64_field_set(unit, reg, &rval, PROFILE_INDEXf,
   7539                          index_map);
   7540  
   7541      BCM_IF_ERROR_RETURN(soc_reg64_set(unit, reg, 0, 0, rval));
   7542  
   7543      return BCM_E_NONE;
   7544  }
   7545 
   7546  /*
   7547   * Function:
   7548   *     bcm_mn_cosq_llfc_profile_detach
   7549   * Purpose:
   7550   *     Delete old entries for PRIO2COS_PROFILE register profile
   7551   * Parameters:
   7552   *     unit    - (IN) unit number
   7553   *     port    - (IN) port number
   7554   * Returns:
   7555   *     BCM_E_XXX
   7556   */
   7557  int
   7558  bcm_mn_cosq_llfc_profile_detach(int unit, int port)
   7559  {
   7560      soc_reg_t   reg;
   7561      bcm_port_t local_port;
   7562      int mmu_port, phy_port;
   7563      uint32 old_profile_index;
   7564      uint32 tmp32;
   7565      uint64 rval, index_map;
   7566      soc_info_t *si;
   7567      static const soc_reg_t llfc_cfgr[] = {
   7568         PORT_PFC_CFG0r, PORT_PFC_CFG1r, PORT_PFC_CFG2r
   7569      };
   7570  
   7571      BCM_IF_ERROR_RETURN(
   7572          _bcm_mn_cosq_localport_resolve(unit, port, &local_port));
   7573  
   7574      si = &SOC_INFO(unit);
   7575      phy_port = si->port_l2p_mapping[local_port];
   7576      mmu_port = si->port_p2m_mapping[phy_port];
   7577  
   7578       reg = llfc_cfgr[mmu_port/32];
   7579       BCM_IF_ERROR_RETURN(soc_reg64_get(unit, reg, 0, 0, &rval));
   7580       
   7581       index_map = soc_reg64_field_get(unit, reg, rval, PROFILE_INDEXf);
   7582       COMPILER_64_SHR(index_map, ((mmu_port % 32) * 2));
   7583       COMPILER_64_TO_32_LO(tmp32, index_map); 
   7584       old_profile_index = (tmp32 & 3)*16;
   7585       
   7586       BCM_IF_ERROR_RETURN
   7587           (soc_profile_reg_delete(unit, _bcm_mn_llfc_profile[unit],
   7588                                   old_profile_index));
   7589                                   
   7590       return BCM_E_NONE;
   7591   }   
   7592   
   7593 
   7594 
   7595 /*
   7596  * Function:
   7597  *     bcm_mn_cosq_init
   7598  * Purpose:
   7599  *     Initialize (clear) all COS schedule/mapping state.
   7600  * Parameters:
   7601  *     unit - unit number
   7602  * Returns:
   7603  *     BCM_E_XXX
   7604  */
   7605 int
   7606 bcm_mn_cosq_init(int unit)
   7607 {
   7608     int numq, alloc_size, ii, index;
   7609     soc_info_t *si;
   7610     bcm_port_t port;
   7611     soc_reg_t mem;
   7612     soc_reg_t reg;
   7613     int count;
   7614     static soc_field_t wred_fields[6][3] = {
   7615         {MIN_THD0f, MAX_THD0f, MAX_DROP_RATE0f},
   7616         {MIN_THD1f, MAX_THD1f, MAX_DROP_RATE1f},
   7617         {MIN_THD2f, MAX_THD2f, MAX_DROP_RATE2f},
   7618         {MIN_THD3f, MAX_THD3f, MAX_DROP_RATE3f},
   7619         {MIN_THD4f, MAX_THD4f, MAX_DROP_RATE4f},
   7620         {MIN_THD5f, MAX_THD5f, MAX_DROP_RATE5f}
   7621     };
   7622     static soc_mem_t wred_mems[1] = {
   7623         MMU_WRED_DROP_CURVE_PROFILE_0_X_PIPEm
   7624     };
   7625     int entry_words[6], pipe;
   7626     mmu_wred_drop_curve_profile_0_x_pipe_entry_t entry_tcp_green;
   7627     mmu_wred_config_entry_t qentry;
   7628     void *entries[6];
   7629     uint32 profile_index;
   7630     _bcm_mn_mmu_info_t *mmu_info;
   7631     int i, qnum, wred_prof_count;
   7632     _bcm_bst_device_handlers_t bst_callbks;
   7633     _bcm_mn_pipe_resources_t   *pres;
   7634     uint64 rval64;
   7635     _bcm_mn_cosq_list_t *list = NULL;
   7636     int baseq = 0;
   7637     int numl2uc = 0; 
   7638     int phy_port ,mmu_port ; 
   7639     uint64 rval ; 
   7640 
   7641     BCM_IF_ERROR_RETURN (bcm_mn_cosq_detach(unit, 0));
   7642 
   7643     si = &SOC_INFO(unit);
   7644 
   7645     numq = soc_property_get(unit, spn_BCM_NUM_COS, BCM_COS_DEFAULT);
   7646     NUM_COS(unit) = numq;
   7647 
   7648     if (numq < 1) {
   7649         numq = 1;
   7650     } else if (numq > BCM_MN_COS_MAX) {
   7651         numq = BCM_MN_COS_MAX;
   7652     }
   7653 
   7654     NUM_COS(unit) = numq;
   7655 
   7656     /* Create profile for PORT_COS_MAP table */
   7657     if (_bcm_mn_cos_map_profile[unit] == NULL) {
   7658         _bcm_mn_cos_map_profile[unit] = sal_alloc(sizeof(soc_profile_mem_t),
   7659                                                   "COS_MAP Profile Mem");
   7660         if (_bcm_mn_cos_map_profile[unit] == NULL) {
   7661             return BCM_E_MEMORY;
   7662         }
   7663         soc_profile_mem_t_init(_bcm_mn_cos_map_profile[unit]);
   7664     }
   7665     mem = PORT_COS_MAPm;
   7666     entry_words[0] = sizeof(port_cos_map_entry_t) / sizeof(uint32);
   7667     BCM_IF_ERROR_RETURN(soc_profile_mem_create(unit, &mem, entry_words, 1,
   7668                                                _bcm_mn_cos_map_profile[unit]));
   7669 
   7670     /* Create profile for IFP_COS_MAP table. */
   7671     if (_bcm_mn_ifp_cos_map_profile[unit] == NULL) {
   7672         _bcm_mn_ifp_cos_map_profile[unit]
   7673             = sal_alloc(sizeof(soc_profile_mem_t), "IFP_COS_MAP Profile Mem");
   7674         if (_bcm_mn_ifp_cos_map_profile[unit] == NULL) {
   7675             return BCM_E_MEMORY;
   7676         }
   7677         soc_profile_mem_t_init(_bcm_mn_ifp_cos_map_profile[unit]);
   7678     }
   7679     mem = IFP_COS_MAPm;
   7680     entry_words[0] = sizeof(ifp_cos_map_entry_t) / sizeof(uint32);
   7681     SOC_IF_ERROR_RETURN
   7682         (soc_profile_mem_create(unit, &mem, entry_words, 1,
   7683                                 _bcm_mn_ifp_cos_map_profile[unit]));
   7684 
   7685     /* Create profile for PRIO2COS_PROFILE register */
   7686     if (_bcm_mn_llfc_profile[unit] == NULL) {
   7687         _bcm_mn_llfc_profile[unit] =
   7688         sal_alloc(sizeof(soc_profile_reg_t), "PRIO2COS_LLFC Profile Reg");
   7689         if (_bcm_mn_llfc_profile[unit] == NULL) {
   7690             return BCM_E_MEMORY;
   7691         }
   7692         soc_profile_reg_t_init(_bcm_mn_llfc_profile[unit]);
   7693     }
   7694 
   7695     alloc_size = sizeof(_bcm_mn_mmu_info_t) * 1;
   7696     if (_bcm_mn_mmu_info[unit] == NULL) {
   7697         _bcm_mn_mmu_info[unit] =
   7698             sal_alloc(alloc_size, "_bcm_mn_mmu_info");
   7699 
   7700         if (_bcm_mn_mmu_info[unit] == NULL) {
   7701             return BCM_E_MEMORY;
   7702         }
   7703 
   7704         sal_memset(_bcm_mn_mmu_info[unit], 0, alloc_size);
   7705     } 
   7706     reg = PRIO2COS_PROFILEr;
   7707     BCM_IF_ERROR_RETURN
   7708          (soc_profile_reg_create(unit, &reg, 1, _bcm_mn_llfc_profile[unit]));
   7709     /* Add default entries for PRIO2COS_PROFILE register profile */
   7710     PBMP_PORT_ITER(unit, port) {
   7711          BCM_IF_ERROR_RETURN(bcm_mn_cosq_default_llfc_profile_attach(unit, port));
   7712     }
   7713     mmu_info = _bcm_mn_mmu_info[unit];
   7714     mmu_info->ets_mode = 0;
   7715     mmu_info->pipe_resources[_MN_XPIPE].num_base_queues = 0;
   7716      
   7717     if (soc_feature(unit, soc_feature_mmu_3k_uc_queue)) {
   7718        mmu_info->num_l2_queues = _BCM_MN_NUM_L2_UC_LEAVES_PER_PIPE; 
   7719     } else if (soc_feature(unit, soc_feature_mmu_1k_uc_queue)) {
   7720        mmu_info->num_l2_queues = _BCM_MN_NUM_L2_UC_LEAVES_PER_PIPE; 
   7721     } else { 
   7722        mmu_info->num_l2_queues = _BCM_MN_NUM_L2_UC_LEAVES_PER_PIPE; 
   7723     }
   7724 
   7725     for (pipe = _MN_XPIPE; pipe < _MN_YPIPE; pipe++) {
   7726         pres = _BCM_MN_PRESOURCES(mmu_info, pipe);
   7727         pres->p_queue_node = &mmu_info->queue_node[0];
   7728         pres->p_mc_queue_node = &mmu_info->mc_queue_node[0];
   7729         pres->l2_queue_list.count = mmu_info->num_l2_queues;
   7730         pres->l2_queue_list.bits = _bcm_mn_cosq_alloc_clear(
   7731                 pres->l2_queue_list.bits,
   7732                 SHR_BITALLOCSIZE(mmu_info->num_l2_queues), 
   7733                                     "l2_queue_list");
   7734         if (pres->l2_queue_list.bits == NULL) {
   7735             _bcm_mn_cosq_free_memory(mmu_info);
   7736             return BCM_E_MEMORY;
   7737         }
   7738 
   7739         pres->l0_sched_list.count = _BCM_MN_NUM_L0_SCHEDULER_PER_PIPE;
   7740         pres->l0_sched_list.bits = _bcm_mn_cosq_alloc_clear(
   7741                 pres->l0_sched_list.bits,
   7742                 SHR_BITALLOCSIZE(_BCM_MN_NUM_L0_SCHEDULER_PER_PIPE),
   7743                                     "l0_sched_list");
   7744         if (pres->l0_sched_list.bits == NULL) {
   7745             _bcm_mn_cosq_free_memory(mmu_info);
   7746             return BCM_E_MEMORY;
   7747         }
   7748 
   7749         pres->l1_sched_list.count = _BCM_MN_NUM_L1_SCHEDULER_PER_PIPE;
   7750         pres->l1_sched_list.bits = _bcm_mn_cosq_alloc_clear(
   7751                 pres->l1_sched_list.bits,
   7752                 SHR_BITALLOCSIZE(_BCM_MN_NUM_L1_SCHEDULER_PER_PIPE),
   7753                                     "l1_sched_list");
   7754         if (pres->l1_sched_list.bits == NULL) {
   7755             _bcm_mn_cosq_free_memory(mmu_info);
   7756             return BCM_E_MEMORY;
   7757         }
   7758         pres->s1_sched_list.count = _BCM_MN_NUM_S1_SCHEDULER_PER_PIPE;
   7759         pres->s1_sched_list.bits = _bcm_mn_cosq_alloc_clear(
   7760                 pres->s1_sched_list.bits,
   7761                 SHR_BITALLOCSIZE(_BCM_MN_NUM_S1_SCHEDULER_PER_PIPE),
   7762                 "s1_sched_list");
   7763         if (pres->s1_sched_list.bits == NULL) {
   7764             _bcm_mn_cosq_free_memory(mmu_info);
   7765             return BCM_E_MEMORY;
   7766         }
   7767 
   7768     }
   7769     /* assign queues to ports */
   7770     PBMP_ALL_ITER(unit, port) {
   7771         pipe = _BCM_MN_PORT_TO_PIPE(unit, port);
   7772        
   7773         if ((SOC_WARM_BOOT(unit) && !IS_LB_PORT(unit, port)) && 
   7774                           ! IS_CPU_PORT(unit, port)) {
   7775            if(IS_MN_HSP_PORT(unit, port)) {
   7776               numl2uc =  10;
   7777            } else {  
   7778               numl2uc = soc_property_port_get(unit, port, spn_LLS_NUM_L2UC, 16);
   7779            }
   7780            if (numl2uc < 10 || numl2uc > 16) {
   7781                numl2uc = 10;
   7782            }
   7783             phy_port = si->port_l2p_mapping[port];
   7784             mmu_port = si->port_p2m_mapping[phy_port];
   7785             COMPILER_64_ZERO(rval);
   7786             BCM_IF_ERROR_RETURN(READ_ING_COS_MODE_64r(unit, port, &rval));
   7787             baseq = soc_reg64_field32_get(unit, ING_COS_MODE_64r, rval, 
   7788                                   BASE_QUEUE_NUM_0f);
   7789            si->port_num_cosq[port] = 10; 
   7790            si->port_cosq_base[port] =  (mmu_port * si->port_num_cosq[port])  ;
   7791            si->port_num_uc_cosq[port] = numl2uc ;
   7792            si->port_uc_cosq_base[port] = baseq;   
   7793         }
   7794         mmu_info->port_info[port].resources = &mmu_info->pipe_resources[pipe];
   7795         mmu_info->port_info[port].mc_base = si->port_cosq_base[port];
   7796         mmu_info->port_info[port].mc_limit = si->port_cosq_base[port] + 
   7797                                                 si->port_num_cosq[port];
   7798 
   7799         mmu_info->port_info[port].uc_base = si->port_uc_cosq_base[port];
   7800         mmu_info->port_info[port].uc_limit = si->port_uc_cosq_base[port] + 
   7801                                                 si->port_num_uc_cosq[port];
   7802         if (mmu_info->port_info[port].resources->num_base_queues <
   7803                                       mmu_info->port_info[port].uc_limit) {
   7804             mmu_info->port_info[port].resources->num_base_queues =
   7805                                                  mmu_info->port_info[port].uc_limit;
   7806         } 
   7807         if (!SOC_WARM_BOOT(unit)) {
   7808             COMPILER_64_ZERO(rval64);
   7809             if(IS_MN_HSP_PORT(unit, port)) {
   7810                 SOC_IF_ERROR_RETURN(soc_monterey_sched_hw_index_get(unit,
   7811                             port, SOC_MONTEREY_NODE_LVL_L1, 0, &qnum));
   7812             } else {
   7813                 qnum = soc_monterey_logical_qnum_hw_qnum(unit, port, 
   7814                         si->port_uc_cosq_base[port], 1);
   7815             }
   7816             soc_reg64_field32_set(unit, ING_COS_MODE_64r, 
   7817                                             &rval64, BASE_QUEUE_NUM_0f, qnum);
   7818             soc_reg64_field32_set(unit, ING_COS_MODE_64r, 
   7819                                             &rval64, BASE_QUEUE_NUM_1f, qnum);
   7820             BCM_IF_ERROR_RETURN(soc_reg_set(unit, ING_COS_MODE_64r, port, 0, rval64));
   7821         }
   7822     }
   7823 
   7824 
   7825     for (i = 0; i < _BCM_MN_NUM_TOTAL_SCHEDULERS; i++) {
   7826         _BCM_MN_COSQ_LIST_NODE_INIT(mmu_info->sched_node, i);
   7827     }
   7828 
   7829     for (i = 0; i < _BCM_MN_NUM_L2_UC_LEAVES; i++) {
   7830         _BCM_MN_COSQ_LIST_NODE_INIT(mmu_info->queue_node, i);
   7831     }
   7832 
   7833     for (i = 0; i < _BCM_MN_NUM_L2_MC_LEAVES; i++) {
   7834         _BCM_MN_COSQ_LIST_NODE_INIT(mmu_info->mc_queue_node, i);
   7835     }
   7836 
   7837     for (pipe = _MN_XPIPE; pipe < _MN_YPIPE; pipe++) {
   7838         pres = _BCM_MN_PRESOURCES(mmu_info, pipe);
   7839         for (i = SOC_MONTEREY_NODE_LVL_L0; i <= SOC_MONTEREY_NODE_LVL_L2; i++) {
   7840             index = _soc_monterey_invalid_parent_index(unit, i);
   7841             if (i == SOC_MONTEREY_NODE_LVL_L0) {
   7842                 list = &pres->s1_sched_list;
   7843             } else if (i == SOC_MONTEREY_NODE_LVL_L1) {
   7844                 list = &pres->l0_sched_list;
   7845             } else if (i == SOC_MONTEREY_NODE_LVL_L2) {
   7846                 list = &pres->l1_sched_list;
   7847             } else {
   7848                 continue;
   7849             }
   7850             if (index >= 0) {
   7851                 _bcm_mn_node_index_set(list, index, 1);
   7852             }
   7853         }
   7854     }
   7855 
   7856     /* reserve the resources for HSP ports */
   7857     count = _BCM_MN_HSP_PORT_MAX_ROOT;
   7858 
   7859     for (pipe = _MN_XPIPE; pipe < _MN_YPIPE; pipe++) {
   7860         pres = _BCM_MN_PRESOURCES(mmu_info, pipe);
   7861         _bcm_mn_node_index_set(&pres->l0_sched_list, 0, 5 * count);
   7862         _bcm_mn_node_index_set(&pres->l1_sched_list, 0, 10 * count);
   7863         _bcm_mn_node_index_set(&pres->l2_queue_list, 0, 10 * count);
   7864 
   7865         pres->cpu_l0_sched_list.count = (_BCM_MN_CPU_PORT_L0_MAX - 
   7866                 _BCM_MN_CPU_PORT_L0_MIN);
   7867         pres->cpu_l0_sched_list.bits = _bcm_mn_cosq_alloc_clear(
   7868                 pres->cpu_l0_sched_list.bits,
   7869                 SHR_BITALLOCSIZE(pres->cpu_l0_sched_list.count),
   7870                 "cpu_l0_sched_list");
   7871         if (pres->cpu_l0_sched_list.bits == NULL) {
   7872             _bcm_mn_cosq_free_memory(mmu_info);
   7873             return BCM_E_MEMORY;
   7874         }
   7875         _bcm_mn_node_index_set(&pres->l0_sched_list, _BCM_MN_CPU_PORT_L0_MIN,
   7876                 pres->cpu_l0_sched_list.count);
   7877 
   7878 
   7879 
   7880 
   7881         if (count > 0) {
   7882             pres->hsp_l0_sched_list.count = 5 * count;
   7883             pres->hsp_l0_sched_list.bits = _bcm_mn_cosq_alloc_clear(
   7884                     pres->hsp_l0_sched_list.bits,
   7885                     SHR_BITALLOCSIZE(pres->hsp_l0_sched_list.count),
   7886                     "hsp_l0_sched_list");
   7887             if (pres->hsp_l0_sched_list.bits == NULL) {
   7888                 _bcm_mn_cosq_free_memory(mmu_info);
   7889                 return BCM_E_MEMORY;
   7890             }
   7891             pres->hsp_l1_sched_list.count = 10 * count;
   7892             pres->hsp_l1_sched_list.bits = _bcm_mn_cosq_alloc_clear(
   7893                     pres->hsp_l1_sched_list.bits,
   7894                     SHR_BITALLOCSIZE(pres->hsp_l1_sched_list.count),
   7895                     "hsp_l1_sched_list");
   7896             if (pres->hsp_l1_sched_list.bits == NULL) {
   7897                 _bcm_mn_cosq_free_memory(mmu_info);
   7898                 return BCM_E_MEMORY;
   7899             }
   7900             pres->hsp_l2_queue_list.count = 10 * count;
   7901             pres->hsp_l2_queue_list.bits = _bcm_mn_cosq_alloc_clear(
   7902                     pres->hsp_l2_queue_list.bits,
   7903                     SHR_BITALLOCSIZE(pres->hsp_l2_queue_list.count),
   7904                     "hsp_l2_queue_list");
   7905             if (pres->hsp_l2_queue_list.bits == NULL) {
   7906                 _bcm_mn_cosq_free_memory(mmu_info);
   7907                 return BCM_E_MEMORY;
   7908             }
   7909         }
   7910     }
   7911       
   7912     for (pipe = _MN_XPIPE; pipe < _MN_YPIPE; pipe++) {
   7913         pres = _BCM_MN_PRESOURCES(mmu_info, pipe);
   7914         PBMP_ALL_ITER(unit, port) {
   7915             _bcm_mn_node_index_set(&pres->l2_queue_list, 
   7916                     mmu_info->port_info[port].uc_base,
   7917                     si->port_num_uc_cosq[port]);
   7918         }
   7919     }
   7920 
   7921     /* Initialize oob driver */
   7922     BCM_IF_ERROR_RETURN(_bcm_oob_init(unit));
   7923         
   7924     /* Create profile for MMU_WRED_DROP_CURVE_PROFILE_x tables */
   7925     if (_bcm_mn_wred_profile[unit] == NULL) {
   7926         _bcm_mn_wred_profile[unit] = 
   7927             sal_alloc(sizeof(soc_profile_mem_t), "WRED Profile Mem");
   7928         if (_bcm_mn_wred_profile[unit] == NULL) {
   7929             return BCM_E_MEMORY;
   7930         }
   7931         soc_profile_mem_t_init(_bcm_mn_wred_profile[unit]);
   7932     }
   7933 
   7934     entry_words[0] =
   7935         sizeof(mmu_wred_drop_curve_profile_0_x_pipe_entry_t) / sizeof(uint32);
   7936     BCM_IF_ERROR_RETURN
   7937         (soc_profile_mem_create(unit, wred_mems, entry_words, 1,  
   7938                                 _bcm_mn_wred_profile[unit]));
   7939 
   7940     sal_memset(&bst_callbks, 0, sizeof(_bcm_bst_device_handlers_t));
   7941     bst_callbks.resolve_index = &_bcm_mn_bst_index_resolve;
   7942     bst_callbks.reverse_resolve_index = &_bcm_mn_cosq_bst_map_resource_to_gport_cos;
   7943     BCM_IF_ERROR_RETURN(_bcm_bst_attach(unit, &bst_callbks));
   7944 
   7945 
   7946     for (i = 0; i < si->num_cpu_cosq; i++) {
   7947         if (_bcm_mn_cosq_cpu_cosq_config[unit][i] == NULL) { 
   7948             _bcm_mn_cosq_cpu_cosq_config[unit][i] =
   7949                 sal_alloc(sizeof(_bcm_mn_cosq_cpu_cosq_config_t), "CPU Cosq Config");
   7950 
   7951             if (_bcm_mn_cosq_cpu_cosq_config[unit][i] == NULL) { 
   7952                 return BCM_E_MEMORY;
   7953             }
   7954             sal_memset(_bcm_mn_cosq_cpu_cosq_config[unit][i], 0,
   7955                        sizeof(_bcm_mn_cosq_cpu_cosq_config_t));
   7956             _bcm_mn_cosq_cpu_cosq_config[unit][i]->enable = 1;
   7957         }
   7958     }
   7959 
   7960 #ifdef BCM_WARM_BOOT_SUPPORT
   7961     if (SOC_WARM_BOOT(unit)) {
   7962         return bcm_mn_cosq_reinit(unit);
   7963     } else {
   7964         BCM_IF_ERROR_RETURN(_bcm_mn_cosq_wb_alloc(unit));
   7965     }
   7966 #endif /* BCM_WARM_BOOT_SUPPORT */
   7967     PBMP_ALL_ITER(unit, port) {
   7968         if (!IS_MN_HSP_PORT( unit, port)) {
   7969             continue;
   7970         }
   7971         if (IS_SPECIAL_PORT(unit, port)) {
   7972              SOC_IF_ERROR_RETURN(
   7973                     _bcm_mn_internal_port_config_set(unit, port));
   7974               continue;
   7975         }
   7976         BCM_IF_ERROR_RETURN (_bcm_mn_port_hsp_config_set(unit, port));
   7977     }
   7978 
   7979     sal_memset(&entry_tcp_green, 0, sizeof(entry_tcp_green));
   7980     entries[0] = &entry_tcp_green;
   7981     for (ii = 0; ii < 6; ii++) {
   7982          soc_mem_field32_set(unit, MMU_WRED_DROP_CURVE_PROFILE_0_X_PIPEm, entries[0], 
   7983                              wred_fields[ii][0], 0x1ffff);
   7984          soc_mem_field32_set(unit, MMU_WRED_DROP_CURVE_PROFILE_0_X_PIPEm, entries[0], 
   7985                              wred_fields[ii][1], 0x1ffff);
   7986     }
   7987     profile_index = 0xffffffff;
   7988     wred_prof_count = soc_mem_index_count(unit, MMU_WRED_CONFIG_X_PIPEm);
   7989     while(wred_prof_count) {
   7990           if (profile_index == 0xffffffff) {
   7991               BCM_IF_ERROR_RETURN
   7992                 (soc_profile_mem_add(unit, 
   7993                                     _bcm_mn_wred_profile[unit],
   7994                                     entries, 1, &profile_index));
   7995           } else {
   7996               BCM_IF_ERROR_RETURN
   7997                  (soc_profile_mem_reference(unit,
   7998                                             _bcm_mn_wred_profile[unit],
   7999                                             profile_index, 0));
   8000           }
   8001           wred_prof_count -= 1;
   8002  
   8003           /* During rc these entry needs to be reset */
   8004           BCM_IF_ERROR_RETURN
   8005               (soc_mem_read(unit, MMU_WRED_CONFIG_X_PIPEm, MEM_BLOCK_ALL, wred_prof_count, &qentry));
   8006           soc_mem_field32_set(unit, MMU_WRED_CONFIG_X_PIPEm, &qentry, PROFILE_INDEXf, profile_index);
   8007           soc_mem_field32_set(unit, MMU_WRED_CONFIG_X_PIPEm, &qentry, WEIGHTf, 0);
   8008           soc_mem_field32_set(unit, MMU_WRED_CONFIG_X_PIPEm, &qentry, CAP_AVERAGEf, 0);
   8009           soc_mem_field32_set(unit, MMU_WRED_CONFIG_X_PIPEm, &qentry, WRED_ENf, 0);
   8010           soc_mem_field32_set(unit, MMU_WRED_CONFIG_X_PIPEm, &qentry, ECN_MARKING_ENf, 0);
   8011           soc_mem_field32_set(unit, MMU_WRED_CONFIG_X_PIPEm, &qentry, TIME_DOMAIN_SELf, 0);
   8012           BCM_IF_ERROR_RETURN
   8013               (soc_mem_write(unit, MMU_WRED_CONFIG_X_PIPEm, MEM_BLOCK_ALL, wred_prof_count, &qentry));
   8014     }
   8015     SOC_IF_ERROR_RETURN(WRITE_TIME_DOMAINr(unit, 0));
   8016     time_domain_mn[0].ref_count = 1040;
   8017     time_domain_mn[1].ref_count = 0;
   8018     time_domain_mn[2].ref_count = 0;
   8019     time_domain_mn[3].ref_count = 0; 
   8020     /* Add default entries for PORT_COS_MAP memory profile */
   8021     BCM_IF_ERROR_RETURN(bcm_mn_cosq_config_set(unit, numq));
   8022 
   8023     /* Starting the curr_merger_index from 2,
   8024      *  since 0 is configured in all the FC_MAP_TBL2 by default,
   8025      *  so it might effect the traffic of other queues
   8026      */
   8027     mmu_info->curr_merger_index = 2;
   8028     if (!mmu_info->curr_shared_limit) {
   8029         BCM_IF_ERROR_RETURN(soc_monterey_mmu_get_shared_size(unit,
   8030                       &mmu_info->curr_shared_limit));
   8031     }
   8032     BCM_IF_ERROR_RETURN(bcm_mn_init_fc_map_tbl(unit)); 
   8033     BCM_IF_ERROR_RETURN(soc_monterey_shadow_create(unit));
   8034     return BCM_E_NONE;
   8035 }
   8036 
   8037 
   8038 /*
   8039  * Function:
   8040  *     bcm_mn_cosq_config_get
   8041  * Purpose:
   8042  *     Get the number of cos queues
   8043  * Parameters:
   8044  *     unit - unit number
   8045  *     numq - (Output) number of cosq
   8046  * Returns:
   8047  *     BCM_E_XXX
   8048  */
   8049 int
   8050 bcm_mn_cosq_config_get(int unit, int *numq)
   8051 {
   8052     if (numq != NULL) {
   8053         *numq = _MN_NUM_COS(unit);
   8054     }
   8055 
   8056     return BCM_E_NONE;
   8057 }
   8058 
   8059 /*
   8060  * Function:
   8061  *     _bcm_mn_cosq_mapping_set
   8062  * Purpose:
   8063  *     Set COS queue for the specified priority of an ingress port
   8064  * Parameters:
   8065  *     unit     - (IN) unit number
   8066  *     ing_port - (IN) ingress port
   8067  *     gport    - (IN) queue group GPORT identifier
   8068  *     priority - (IN) priority value to map
   8069  *     flags    - (IN) BCM_COSQ_GPORT_XXX_QUEUE_GROUP
   8070  *     gport    - (IN) queue group GPORT identifier
   8071  *     cosq     - (IN) COS queue number
   8072  * Returns:
   8073  *     BCM_E_XXX
   8074  */
   8075 STATIC int
   8076 _bcm_mn_cosq_mapping_set(int unit, bcm_port_t ing_port, bcm_cos_t priority,
   8077                          uint32 flags, bcm_gport_t gport, bcm_cos_queue_t cosq)
   8078 {
   8079     bcm_port_t local_port, outport = -1;
   8080     bcm_cos_queue_t hw_cosq;
   8081     soc_field_t field = INVALIDf, field2 = INVALIDf, field3 = INVALIDf;
   8082     cos_map_sel_entry_t cos_map_sel_entry;
   8083     port_cos_map_entry_t cos_map_entries[16];
   8084     void *entries[1];
   8085     uint32 old_index, new_index, max_val;
   8086     voq_cos_map_entry_t voq_cos_map;
   8087     int rv;
   8088     int valid = 0;
   8089 
   8090     if (priority < 0 || priority >= 16) {
   8091         return BCM_E_PARAM;
   8092     }
   8093 
   8094     BCM_IF_ERROR_RETURN
   8095         (_bcm_mn_cosq_localport_resolve(unit, ing_port, &local_port));
   8096 
   8097     if (gport != -1) {
   8098         BCM_IF_ERROR_RETURN(_bcm_mn_cosq_localport_resolve(unit, gport, &outport));
   8099     }
   8100 
   8101 
   8102     switch (flags) {
   8103     case BCM_COSQ_GPORT_UCAST_QUEUE_GROUP:
   8104         if (gport == -1) {
   8105             hw_cosq = cosq;
   8106         } else {
   8107             BCM_IF_ERROR_RETURN
   8108                 (_bcm_mn_cosq_index_resolve
   8109                  (unit, gport, cosq, _BCM_MN_COSQ_INDEX_STYLE_COS,
   8110                   NULL, &hw_cosq, NULL));
   8111 
   8112         }
   8113         if ((outport != -1) && (IS_HG_PORT(unit, outport))) {
   8114             field = HG_COSf;
   8115         } else {
   8116             field = UC_COS1f;
   8117         }
   8118         break;
   8119     case BCM_COSQ_GPORT_MCAST_QUEUE_GROUP:
   8120         if (gport == -1) {
   8121             hw_cosq = cosq;
   8122         } else {
   8123             BCM_IF_ERROR_RETURN
   8124                 (_bcm_mn_cosq_index_resolve
   8125                  (unit, gport, cosq, _BCM_MN_COSQ_INDEX_STYLE_COS,
   8126                   NULL, &hw_cosq, NULL));
   8127         }
   8128         field = MC_COS1f;
   8129         field2 = RQE_Q_NUMf;
   8130         break;
   8131     case BCM_COSQ_GPORT_UCAST_QUEUE_GROUP | BCM_COSQ_GPORT_MCAST_QUEUE_GROUP:
   8132         if (gport == -1) {
   8133             hw_cosq = cosq;
   8134         } else {
   8135             return BCM_E_PARAM;
   8136         }
   8137         field = UC_COS1f;
   8138         field2 = MC_COS1f;
   8139         field3 = RQE_Q_NUMf;
   8140         break;
   8141     case BCM_COSQ_GPORT_DESTMOD_UCAST_QUEUE_GROUP:
   8142         if (gport == -1) {
   8143             hw_cosq = cosq;
   8144         } else {
   8145             BCM_IF_ERROR_RETURN
   8146                 (_bcm_mn_cosq_index_resolve
   8147                  (unit, gport, cosq, _BCM_MN_COSQ_INDEX_STYLE_COS,
   8148                   NULL, &hw_cosq, NULL));
   8149         }
   8150 
   8151         BCM_IF_ERROR_RETURN(
   8152             READ_VOQ_COS_MAPm(unit, MEM_BLOCK_ALL, priority, &voq_cos_map));
   8153         valid = soc_mem_field32_get(unit, VOQ_COS_MAPm, &voq_cos_map,
   8154                                     VOQ_COS_USE_MODf);
   8155         
   8156         /* Setting the  VOQ_PORT_BASE_SELECT,
   8157            so that BASE_QUEUE_NUM_1 is used for queue
   8158            calculation */
   8159 
   8160         soc_mem_field32_set(unit, VOQ_COS_MAPm, 
   8161                 &voq_cos_map, VOQ_PORT_BASE_SELECTf, 1);
   8162         soc_mem_field32_set(unit, VOQ_COS_MAPm, 
   8163                             &voq_cos_map, VOQ_COS_USE_MODf, 1);
   8164  
   8165         if (valid && (soc_mem_field32_get(unit, VOQ_COS_MAPm, &voq_cos_map, 
   8166                         VOQ_COS_OFFSETf) != hw_cosq)) {
   8167             soc_mem_field32_set(unit, VOQ_COS_MAPm, 
   8168                     &voq_cos_map, VOQ_COS_OFFSETf, hw_cosq);
   8169         }
   8170         BCM_IF_ERROR_RETURN(
   8171                 soc_mem_write(unit, VOQ_COS_MAPm, MEM_BLOCK_ANY, priority,
   8172                     &voq_cos_map));
   8173         return BCM_E_NONE;
   8174         break;
   8175     default:
   8176         return BCM_E_PARAM;
   8177     }
   8178 
   8179     entries[0] = &cos_map_entries;
   8180 
   8181     BCM_IF_ERROR_RETURN
   8182         (READ_COS_MAP_SELm(unit, MEM_BLOCK_ANY, local_port,
   8183                            &cos_map_sel_entry));
   8184     old_index = soc_mem_field32_get(unit, COS_MAP_SELm, &cos_map_sel_entry,
   8185                                     SELECTf);
   8186     old_index *= 16;
   8187 
   8188     BCM_IF_ERROR_RETURN
   8189         (soc_profile_mem_get(unit, _bcm_mn_cos_map_profile[unit],
   8190                              old_index, 16, entries));
   8191     max_val = soc_property_port_get(unit, local_port, spn_LLS_NUM_L2UC, 16);
   8192     if (hw_cosq < 0 || hw_cosq >= max_val) {
   8193         return BCM_E_PARAM;
   8194     }
   8195 
   8196     soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[priority], field,
   8197                         hw_cosq);
   8198     if (field2 != INVALIDf) {
   8199     soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[priority],
   8200                         field2, hw_cosq);
   8201     }
   8202     if (field3 != INVALIDf) {
   8203     soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[priority],
   8204                         field3, hw_cosq);
   8205     }
   8206 
   8207     soc_mem_lock(unit, PORT_COS_MAPm);
   8208 
   8209     rv = soc_profile_mem_delete(unit, _bcm_mn_cos_map_profile[unit],
   8210                                 old_index);
   8211     if (BCM_FAILURE(rv)) {
   8212         soc_mem_unlock(unit, PORT_COS_MAPm);
   8213         return rv;
   8214     }
   8215 
   8216     rv = soc_profile_mem_add(unit, _bcm_mn_cos_map_profile[unit], entries,
   8217                              16, &new_index);
   8218 
   8219     soc_mem_unlock(unit, PORT_COS_MAPm);
   8220 
   8221     if (BCM_FAILURE(rv)) {
   8222         return rv;
   8223     }
   8224 
   8225     soc_mem_field32_set(unit, COS_MAP_SELm, &cos_map_sel_entry, SELECTf,
   8226                         new_index / 16);
   8227     BCM_IF_ERROR_RETURN
   8228         (WRITE_COS_MAP_SELm(unit, MEM_BLOCK_ANY, local_port,
   8229                             &cos_map_sel_entry));
   8230 
   8231 #ifndef BCM_COSQ_HIGIG_MAP_DISABLE
   8232     if (IS_CPU_PORT(unit, local_port)) {
   8233         BCM_IF_ERROR_RETURN
   8234             (soc_mem_field32_modify(unit, COS_MAP_SELm,
   8235                                     SOC_INFO(unit).cpu_hg_index, SELECTf,
   8236                                     new_index / 16));
   8237     }
   8238 #endif /* BCM_COSQ_HIGIG_MAP_DISABLE */
   8239 
   8240     return BCM_E_NONE;
   8241 }
   8242 
   8243 /*
   8244  * Function:
   8245  *     bcm_mn_cosq_mapping_set
   8246  * Purpose:
   8247  *     Set which cosq a given priority should fall into
   8248  * Parameters:
   8249  *     unit     - (IN) unit number
   8250  *     gport    - (IN) queue group GPORT identifier
   8251  *     priority - (IN) priority value to map
   8252  *     cosq     - (IN) COS queue to map to
   8253  * Returns:
   8254  *     BCM_E_XXX
   8255  */
   8256 
   8257 int
   8258 bcm_mn_cosq_mapping_set(int unit, bcm_port_t port, bcm_cos_t priority,
   8259                          bcm_cos_queue_t cosq)
   8260 {
   8261     bcm_pbmp_t pbmp, pbmp1;
   8262     bcm_port_t local_port;
   8263 
   8264     BCM_PBMP_CLEAR(pbmp);
   8265     BCM_PBMP_CLEAR(pbmp1);
   8266 
   8267     if (port == -1) {
   8268         BCM_PBMP_ASSIGN(pbmp, PBMP_ALL(unit));
   8269         BCM_PBMP_ASSIGN(pbmp1, PBMP_HG_ALL(unit));
   8270         BCM_PBMP_REMOVE(pbmp, pbmp1);
   8271     } else {
   8272         if (BCM_GPORT_IS_SET(port)) {
   8273             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
   8274                 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) ||
   8275                 BCM_GPORT_IS_SCHEDULER(port)) {
   8276                 return BCM_E_PARAM;
   8277             } else if (BCM_GPORT_IS_LOCAL(port)) {
   8278                 local_port = BCM_GPORT_LOCAL_GET(port);
   8279             } else if (BCM_GPORT_IS_MODPORT(port)) {
   8280                 BCM_IF_ERROR_RETURN(
   8281                     bcm_esw_port_local_get(unit, port, &local_port));
   8282             } else {
   8283                 return BCM_E_PARAM;
   8284             }
   8285         } else {
   8286             local_port = port;
   8287         }
   8288 
   8289         if (!SOC_PORT_VALID(unit, local_port)) {
   8290             return BCM_E_PORT;
   8291         }
   8292 
   8293         BCM_PBMP_PORT_ADD(pbmp, local_port);
   8294     }
   8295 
   8296     PBMP_ITER(pbmp, local_port) {
   8297         BCM_IF_ERROR_RETURN(_bcm_mn_cosq_port_has_ets(unit, local_port));
   8298     }
   8299 
   8300     if ((cosq < 0) || (cosq >= _MN_NUM_COS(unit))) {
   8301         return BCM_E_PARAM;
   8302     }
   8303 
   8304     PBMP_ITER(pbmp, local_port) {
   8305         if (IS_LB_PORT(unit, local_port)) {
   8306             continue;
   8307         }
   8308 
   8309         /* If no ETS/gport, map the int prio symmetrically for ucast and
   8310          * mcast */
   8311         BCM_IF_ERROR_RETURN(_bcm_mn_cosq_mapping_set(unit, local_port, 
   8312                                     priority,
   8313                                     BCM_COSQ_GPORT_UCAST_QUEUE_GROUP |
   8314                                     BCM_COSQ_GPORT_MCAST_QUEUE_GROUP,
   8315                                     -1, cosq));
   8316     }
   8317 
   8318     PBMP_ITER(pbmp1, local_port) {
   8319         if (IS_LB_PORT(unit, local_port)) {
   8320             continue;
   8321         }
   8322 
   8323         /* If no ETS/gport, map the int prio symmetrically for ucast and
   8324          * mcast */
   8325         BCM_IF_ERROR_RETURN(_bcm_mn_cosq_mapping_set(unit, local_port, 
   8326                                     priority,
   8327                                     BCM_COSQ_GPORT_UCAST_QUEUE_GROUP |
   8328                                     BCM_COSQ_GPORT_MCAST_QUEUE_GROUP,
   8329                                     -1, cosq));
   8330     }
   8331     return BCM_E_NONE;
   8332 }
   8333 
   8334 /*
   8335  * Function:
   8336  *     bcm_mn_cosq_mapping_get
   8337  * Purpose:
   8338  *     Determine which COS queue a given priority currently maps to.
   8339  * Parameters:
   8340  *     unit     - (IN) unit number
   8341  *     gport    - (IN) queue group GPORT identifier
   8342  *     priority - (IN) priority value to map
   8343  *     cosq     - (OUT) COS queue to map to
   8344  * Returns:
   8345  *     BCM_E_XXX
   8346  */
   8347 int
   8348 _bcm_mn_cosq_mapping_get(int unit, bcm_port_t ing_port, bcm_cos_t priority,
   8349                           uint32 flags, bcm_gport_t *gport,
   8350                           bcm_cos_queue_t *cosq)
   8351 {
   8352     _bcm_mn_mmu_info_t *mmu_info;
   8353     _bcm_mn_pipe_resources_t *res;
   8354     _bcm_mn_cosq_port_info_t *port_info;
   8355     _bcm_mn_cosq_node_t *node;
   8356     bcm_port_t local_port;
   8357     bcm_cos_queue_t hw_cosq = BCM_COS_INVALID;
   8358     int index, ii;
   8359     cos_map_sel_entry_t cos_map_sel_entry;
   8360     voq_cos_map_entry_t voq_cos_map;
   8361     void *entry_p;
   8362 
   8363     if (priority < 0 || priority >= 16) {
   8364         return BCM_E_PARAM;
   8365     }
   8366 
   8367     if (flags != BCM_COSQ_GPORT_UCAST_QUEUE_GROUP &&
   8368         flags != BCM_COSQ_GPORT_MCAST_QUEUE_GROUP &&
   8369         flags != BCM_COSQ_GPORT_DESTMOD_UCAST_QUEUE_GROUP) {
   8370         return BCM_E_PARAM;
   8371     }
   8372 
   8373     BCM_IF_ERROR_RETURN
   8374         (_bcm_mn_cosq_localport_resolve(unit, ing_port, &local_port));
   8375 
   8376     if (gport) {
   8377         *gport = BCM_GPORT_INVALID;
   8378     }
   8379 
   8380     *cosq = BCM_COS_INVALID;
   8381 
   8382      BCM_IF_ERROR_RETURN
   8383             (READ_COS_MAP_SELm(unit, MEM_BLOCK_ANY, local_port,
   8384                                &cos_map_sel_entry));
   8385     index = soc_mem_field32_get(unit, COS_MAP_SELm, &cos_map_sel_entry,
   8386                                 SELECTf);
   8387     index *= 16;
   8388 
   8389     entry_p = SOC_PROFILE_MEM_ENTRY(unit, _bcm_mn_cos_map_profile[unit],
   8390                                     port_cos_map_entry_t *,
   8391                                     index + priority);
   8392 
   8393     mmu_info = _bcm_mn_mmu_info[unit];
   8394     port_info = &mmu_info->port_info[local_port];
   8395     res = _BCM_MN_PRESOURCES(mmu_info, _BCM_MN_PORT_TO_PIPE(unit, local_port));
   8396 
   8397     switch (flags) {
   8398     case BCM_COSQ_GPORT_UCAST_QUEUE_GROUP:
   8399         hw_cosq = soc_mem_field32_get(unit, PORT_COS_MAPm, entry_p, UC_COS1f);
   8400         if ((IS_CPU_PORT(unit, local_port) == FALSE) && gport) { 
   8401             for (ii = port_info->uc_base; ii < port_info->uc_limit; ii++) {
   8402                 node = &mmu_info->queue_node[ii];
   8403                 if (node->numq > 0 && node->hw_cosq == hw_cosq) {
   8404                     *gport = node->gport;
   8405                     *cosq = 0;
   8406                     break;
   8407                 }
   8408             }
   8409             if (ii == port_info->uc_limit) {
   8410                 return BCM_E_NOT_FOUND;
   8411             }
   8412         }
   8413         break;
   8414     case BCM_COSQ_GPORT_MCAST_QUEUE_GROUP:
   8415         hw_cosq = soc_mem_field32_get(unit, PORT_COS_MAPm, entry_p, MC_COS1f);
   8416         if (gport) {
   8417             for (ii = port_info->mc_base; ii < port_info->mc_limit; ii++) {
   8418                 node = &mmu_info->mc_queue_node[ii];
   8419                 if (node->numq > 0 && node->hw_cosq == hw_cosq) {
   8420                     *gport = node->gport;
   8421                     *cosq = 0;
   8422                     break;
   8423                 }
   8424             }
   8425             if (ii == port_info->mc_limit) {
   8426                 return BCM_E_NOT_FOUND;
   8427             }
   8428         }
   8429         break;
   8430 
   8431     case BCM_COSQ_GPORT_DESTMOD_UCAST_QUEUE_GROUP:
   8432         BCM_IF_ERROR_RETURN(
   8433             READ_VOQ_COS_MAPm(unit, MEM_BLOCK_ALL, priority, &voq_cos_map));
   8434         hw_cosq = soc_mem_field32_get(unit, VOQ_COS_MAPm, 
   8435                                         &voq_cos_map, VOQ_COS_OFFSETf);
   8436         if (gport) {
   8437             for (ii = res->num_base_queues; ii < _BCM_MN_NUM_L2_UC_LEAVES; ii++) {
   8438                 node = &mmu_info->queue_node[ii];
   8439                 
   8440                 if (node->numq > 0 && node->hw_cosq == hw_cosq) {
   8441                     *gport = node->gport;
   8442                     break;
   8443                 }
   8444             }
   8445             if (ii == _BCM_MN_NUM_L2_UC_LEAVES) {
   8446                 return BCM_E_NOT_FOUND;
   8447             }
   8448         }
   8449         break;
   8450     }
   8451 
   8452     *cosq = hw_cosq;
   8453 
   8454     if (((gport &&
   8455         (*gport == BCM_GPORT_INVALID) && (*cosq == BCM_COS_INVALID))) ||
   8456         (*cosq == BCM_COS_INVALID)) {
   8457         return BCM_E_NOT_FOUND;
   8458     }
   8459 
   8460     return BCM_E_NONE;
   8461 }
   8462 
   8463 int
   8464 bcm_mn_cosq_mapping_get(int unit, bcm_port_t port, bcm_cos_t priority,
   8465                         bcm_cos_queue_t *cosq)
   8466 {
   8467     bcm_port_t local_port;
   8468     bcm_pbmp_t pbmp;
   8469 
   8470     BCM_PBMP_CLEAR(pbmp);
   8471 
   8472     if (port == -1) {
   8473         BCM_PBMP_ASSIGN(pbmp, PBMP_ALL(unit));
   8474     } else {
   8475         if (BCM_GPORT_IS_SET(port)) {
   8476             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
   8477                 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) ||
   8478                 BCM_GPORT_IS_SCHEDULER(port)) {
   8479                 return BCM_E_PARAM;
   8480             } else if (BCM_GPORT_IS_LOCAL(port)) {
   8481                 local_port = BCM_GPORT_LOCAL_GET(port);
   8482             } else if (BCM_GPORT_IS_MODPORT(port)) {
   8483                 BCM_IF_ERROR_RETURN(
   8484                     bcm_esw_port_local_get(unit, port, &local_port));
   8485             } else {
   8486                 return BCM_E_PARAM;
   8487             }
   8488         } else {
   8489             local_port = port;
   8490         }
   8491 
   8492         if (!SOC_PORT_VALID(unit, local_port)) {
   8493             return BCM_E_PORT;
   8494         }
   8495 
   8496         BCM_PBMP_PORT_ADD(pbmp, local_port);
   8497     }
   8498 
   8499     PBMP_ITER(pbmp, local_port) {
   8500         if (IS_LB_PORT(unit, local_port)) {
   8501             continue;
   8502         }
   8503 
   8504         BCM_IF_ERROR_RETURN(_bcm_mn_cosq_mapping_get(unit, local_port, 
   8505                  priority, BCM_COSQ_GPORT_UCAST_QUEUE_GROUP, NULL, cosq));
   8506         break;
   8507     }    
   8508     return BCM_E_NONE;
   8509 }
   8510 
   8511 int
   8512 bcm_mn_cosq_gport_mapping_set(int unit, bcm_port_t ing_port,
   8513                               bcm_cos_t int_pri, uint32 flags,
   8514                               bcm_gport_t gport, bcm_cos_queue_t cosq)
   8515 {
   8516     return _bcm_mn_cosq_mapping_set(unit, ing_port, int_pri, flags, gport,
   8517                                     cosq);
   8518 }
   8519 
   8520 int
   8521 bcm_mn_cosq_gport_mapping_get(int unit, bcm_port_t ing_port,
   8522                               bcm_cos_t int_pri, uint32 flags,
   8523                               bcm_gport_t *gport, bcm_cos_queue_t *cosq)
   8524 {
   8525     if (gport == NULL || cosq == NULL) {
   8526         return BCM_E_PARAM;
   8527     }
   8528 
   8529     return _bcm_mn_cosq_mapping_get(unit, ing_port, int_pri, flags, gport,
   8530                                     cosq);
   8531 }
   8532 
   8533 /*
   8534  * Function:
   8535  *     bcm_mn_cosq_port_sched_set
   8536  * Purpose:
   8537  *     Set up class-of-service policy and corresponding weights and delay
   8538  * Parameters:
   8539  *     unit    - (IN) unit number
   8540  *     pbm     - (IN) port bitmap
   8541  *     mode    - (IN) Scheduling mode (BCM_COSQ_xxx)
   8542  *     weights - (IN) Weights for each COS queue
   8543  *     delay   - This parameter is not used
   8544  * Returns:
   8545  *     BCM_E_XXX
   8546  */
   8547 int
   8548 bcm_mn_cosq_port_sched_set(int unit, bcm_pbmp_t pbm,
   8549                            int mode, const int *weights, int delay)
   8550 {
   8551     bcm_port_t port;
   8552     int        num_weights, i;
   8553     int        cur_mode, cur_weight; 
   8554     int        reset_mode = BCM_COSQ_WEIGHTED_ROUND_ROBIN; 
   8555 
   8556     num_weights = _MN_NUM_COS(unit);
   8557     BCM_PBMP_ITER(pbm, port) {
   8558         /*WRR mode is a property per port, 
   8559          * so just get cosq=0 schedule mode*/
   8560         BCM_IF_ERROR_RETURN
   8561             (_bcm_mn_cosq_sched_get(unit, port, 0,
   8562                                      &cur_mode, &cur_weight));
   8563         if (cur_mode == BCM_COSQ_STRICT) {
   8564             reset_mode = BCM_COSQ_WEIGHTED_ROUND_ROBIN;
   8565         } else {
   8566             reset_mode = cur_mode;
   8567         }
   8568         
   8569         /* Schedule mode switch need base on default wrr mode */        
   8570         for (i = 0; i < num_weights; i++) {
   8571             BCM_IF_ERROR_RETURN
   8572                 (_bcm_mn_cosq_sched_set(unit, port, i, 
   8573                                          reset_mode, 1));
   8574         }
   8575         
   8576         for (i = 0; i < num_weights; i++) {         
   8577             BCM_IF_ERROR_RETURN
   8578                 (_bcm_mn_cosq_sched_set(unit, port, i, mode, weights[i]));
   8579         }
   8580     }
   8581 
   8582     return BCM_E_NONE;
   8583 }
   8584 
   8585 /*
   8586  * Function:
   8587  *     bcm_mn_cosq_port_sched_get
   8588  * Purpose:
   8589  *     Retrieve class-of-service policy and corresponding weights and delay
   8590  * Parameters:
   8591  *     unit     - (IN) unit number
   8592  *     pbm      - (IN) port bitmap
   8593  *     mode     - (OUT) Scheduling mode (BCM_COSQ_XXX)
   8594  *     weights  - (OUT) Weights for each COS queue
   8595  *     delay    - This parameter is not used
   8596  * Returns:
   8597  *     BCM_E_XXX
   8598  */
   8599 int
   8600 bcm_mn_cosq_port_sched_get(int unit, bcm_pbmp_t pbm,
   8601                            int *mode, int *weights, int *delay)
   8602 {
   8603     bcm_port_t port;
   8604     int i, num_weights;
   8605 
   8606     BCM_PBMP_ITER(pbm, port) {
   8607         if (IS_CPU_PORT(unit, port) && SOC_PBMP_NEQ(pbm, PBMP_CMIC(unit))) {
   8608             continue;
   8609         }
   8610         num_weights = _MN_NUM_COS(unit);
   8611         for (i = 0; i < num_weights; i++) {
   8612             BCM_IF_ERROR_RETURN(
   8613                 _bcm_mn_cosq_sched_get(unit, port, i, mode, &weights[i]));
   8614         }
   8615     }
   8616 
   8617     return BCM_E_NONE;
   8618 }
   8619 
   8620 /*
   8621  * Function:
   8622  *     bcm_mn_cosq_sched_weight_max_get
   8623  * Purpose:
   8624  *     Retrieve maximum weights for given COS policy
   8625  * Parameters:
   8626  *     unit    - (IN) unit number
   8627  *     mode    - (IN) Scheduling mode (BCM_COSQ_xxx)
   8628  *     weight_max - (OUT) Maximum weight for COS queue.
   8629  * Returns:
   8630  *     BCM_E_XXX
   8631  */
   8632 int
   8633 bcm_mn_cosq_sched_weight_max_get(int unit, int mode, int *weight_max)
   8634 {
   8635     switch (mode) {
   8636     case BCM_COSQ_STRICT:
   8637         *weight_max = BCM_COSQ_WEIGHT_STRICT;
   8638         break;
   8639     case BCM_COSQ_ROUND_ROBIN:
   8640     case BCM_COSQ_WEIGHTED_ROUND_ROBIN:
   8641     case BCM_COSQ_DEFICIT_ROUND_ROBIN:
   8642         *weight_max =
   8643             (1 << soc_mem_field_length(unit, HSP_SCHED_L0_NODE_WEIGHTm,
   8644                                        L0_NODE_WEIGHTf)) - 1; 
   8645         break;
   8646     default:
   8647         return BCM_E_PARAM;
   8648     }
   8649 
   8650     return BCM_E_NONE;
   8651 }
   8652 
   8653 /*
   8654  * Function:
   8655  *     bcm_mn_cosq_bandwidth_set
   8656  * Purpose:
   8657  *     Configure COS queue bandwidth control
   8658  * Parameters:
   8659  *     unit          - (IN) unit number
   8660  *     port          - (IN) port number or GPORT identifier
   8661  *     cosq          - (IN) COS queue number
   8662  *     min_quantum   - (IN)
   8663  *     max_quantum   - (IN)
   8664  *     burst_quantum - (IN)
   8665  *     flags         - (IN)
   8666  * Returns:
   8667  *     BCM_E_XXX
   8668  * Notes:
   8669  *     If port is any form of local port, cosq is the hardware queue index.
   8670  */
   8671 int
   8672 bcm_mn_cosq_port_bandwidth_set(int unit, bcm_port_t port,
   8673                                bcm_cos_queue_t cosq,
   8674                                uint32 min_quantum, uint32 max_quantum,
   8675                                uint32 burst_quantum, uint32 flags)
   8676 {
   8677     uint32 burst_min, burst_max;
   8678 
   8679     if (cosq < 0) {
   8680         return BCM_E_PARAM;
   8681     }
   8682 
   8683     burst_min = (min_quantum > 0) ?
   8684           _bcm_td_default_burst_size(unit, port, min_quantum) : 0;
   8685 
   8686     burst_max = (max_quantum > 0) ?
   8687           _bcm_td_default_burst_size(unit, port, max_quantum) : 0;
   8688 
   8689     return _bcm_mn_cosq_bucket_set(unit, port, cosq, min_quantum, max_quantum,
   8690                                     burst_min, burst_max, flags);
   8691 }
   8692 
   8693 /*
   8694  * Function:
   8695  *     bcm_mn_cosq_bandwidth_get
   8696  * Purpose:
   8697  *     Get COS queue bandwidth control configuration
   8698  * Parameters:
   8699  *     unit          - (IN) unit number
   8700  *     port          - (IN) port number or GPORT identifier
   8701  *     cosq          - (IN) COS queue number
   8702  *     min_quantum   - (OUT)
   8703  *     max_quantum   - (OUT)
   8704  *     burst_quantum - (OUT)
   8705  *     flags         - (OUT)
   8706  * Returns:
   8707  *     BCM_E_XXX
   8708  * Notes:
   8709  *     If port is any form of local port, cosq is the hardware queue index.
   8710  */
   8711 int
   8712 bcm_mn_cosq_port_bandwidth_get(int unit, bcm_port_t port,
   8713                                bcm_cos_queue_t cosq,
   8714                                uint32 *min_quantum, uint32 *max_quantum,
   8715                                uint32 *burst_quantum, uint32 *flags)
   8716 {
   8717     uint32 kbit_burst_min;
   8718 
   8719     if (cosq < -1) {
   8720         return BCM_E_PARAM;
   8721     }
   8722 
   8723     BCM_IF_ERROR_RETURN(_bcm_mn_cosq_bucket_get(unit, port, cosq,
   8724                         min_quantum, max_quantum, &kbit_burst_min,
   8725                         burst_quantum, flags));
   8726     return BCM_E_NONE;
   8727 }
   8728 
   8729 int
   8730 bcm_mn_cosq_port_pps_set(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   8731                          int pps)
   8732 {
   8733     uint32 min, max, burst, burst_min, flags;
   8734     bcm_port_t  local_port =  port;
   8735     
   8736     if (!IS_CPU_PORT(unit, port)) {
   8737         return BCM_E_PORT;
   8738     } else if (cosq < 0 || cosq >= NUM_CPU_COSQ(unit)) {
   8739         return BCM_E_PARAM;
   8740     }
   8741 
   8742     if (_bcm_mn_cosq_port_has_ets(unit, port)) {
   8743         BCM_IF_ERROR_RETURN(_bcm_mn_cosq_l2_gport(unit, port, cosq, 
   8744                                             _BCM_MN_NODE_MCAST, &port, NULL));
   8745         cosq = 0;
   8746     }
   8747 
   8748     BCM_IF_ERROR_RETURN
   8749         (_bcm_mn_cosq_bucket_get(unit, port, cosq, &min, &max, &burst_min,
   8750                                     &burst, &flags));
   8751 
   8752     min = pps;
   8753     burst_min = (min > 0) ?
   8754           _bcm_td_default_burst_size(unit, local_port, min) : 0;
   8755     burst = burst_min;        
   8756 
   8757     return _bcm_mn_cosq_bucket_set(unit, port, cosq, min, pps, burst_min, burst,
   8758                                     flags | BCM_COSQ_BW_PACKET_MODE);
   8759 }
   8760 
   8761 int
   8762 bcm_mn_cosq_port_pps_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   8763                          int *pps)
   8764 {
   8765     uint32 min, max, burst, flags;
   8766 
   8767     if (!IS_CPU_PORT(unit, port)) {
   8768         return BCM_E_PORT;
   8769     } else if (cosq < 0 || cosq >= NUM_CPU_COSQ(unit)) {
   8770         return BCM_E_PARAM;
   8771     }
   8772 
   8773     if (_bcm_mn_cosq_port_has_ets(unit, port)) {
   8774         BCM_IF_ERROR_RETURN(_bcm_mn_cosq_l2_gport(unit, port, cosq,
   8775                                           _BCM_MN_NODE_MCAST, &port, NULL));
   8776         cosq = 0;
   8777     }
   8778 
   8779     BCM_IF_ERROR_RETURN
   8780         (_bcm_mn_cosq_bucket_get(unit, port, cosq, &min, &max, &burst, &burst,
   8781                                   &flags));
   8782     *pps = max;
   8783 
   8784     return BCM_E_NONE;
   8785 }
   8786 
   8787 int
   8788 bcm_mn_cosq_port_burst_set(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   8789                            int burst)
   8790 {
   8791     uint32 min, max, cur_burst, flags;
   8792 
   8793     if (!IS_CPU_PORT(unit, port)) {
   8794         return BCM_E_PORT;
   8795     } else if (cosq < 0 || cosq >= NUM_CPU_COSQ(unit)) {
   8796         return BCM_E_PARAM;
   8797     }
   8798 
   8799     if (_bcm_mn_cosq_port_has_ets(unit, port)) {
   8800         BCM_IF_ERROR_RETURN(_bcm_mn_cosq_l2_gport(unit, port, cosq,
   8801                                                 _BCM_MN_NODE_MCAST, &port, NULL));
   8802         cosq = 0;
   8803     }
   8804 
   8805     BCM_IF_ERROR_RETURN
   8806         (_bcm_mn_cosq_bucket_get(unit, port, cosq, &min, &max, &cur_burst,
   8807                                   &cur_burst, &flags));
   8808 
   8809     /* Replace the current BURST setting, keep PPS the same */
   8810     return _bcm_mn_cosq_bucket_set(unit, port, cosq, min, max, burst, burst,
   8811                                     flags | BCM_COSQ_BW_PACKET_MODE);
   8812 }
   8813 
   8814 int
   8815 bcm_mn_cosq_port_burst_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   8816                            int *burst)
   8817 {
   8818     uint32 min, max, cur_burst, cur_burst_min, flags;
   8819 
   8820     if (!IS_CPU_PORT(unit, port)) {
   8821         return BCM_E_PORT;
   8822     } else if (cosq < 0 || cosq >= NUM_CPU_COSQ(unit)) {
   8823         return BCM_E_PARAM;
   8824     }
   8825 
   8826     if (_bcm_mn_cosq_port_has_ets(unit, port)) {
   8827         BCM_IF_ERROR_RETURN(_bcm_mn_cosq_l2_gport(unit, port, cosq, 
   8828                                             _BCM_MN_NODE_MCAST, &port, NULL));
   8829         cosq = 0;
   8830     }
   8831 
   8832     BCM_IF_ERROR_RETURN
   8833         (_bcm_mn_cosq_bucket_get(unit, port, cosq, &min, &max, 
   8834                                   &cur_burst_min, &cur_burst, &flags));
   8835     *burst = cur_burst;
   8836 
   8837     return BCM_E_NONE;
   8838 }
   8839 
   8840 int
   8841 bcm_mn_cosq_discard_set(int unit, uint32 flags)
   8842 {
   8843     bcm_port_t port;
   8844     _bcm_mn_mmu_info_t *mmu_info;
   8845 
   8846     if ((mmu_info = _bcm_mn_mmu_info[unit]) == NULL) {
   8847         return BCM_E_INIT;
   8848     }
   8849     
   8850     flags &= ~(BCM_COSQ_DISCARD_NONTCP | BCM_COSQ_DISCARD_COLOR_ALL);
   8851 
   8852     PBMP_PORT_ITER(unit, port) {
   8853         BCM_IF_ERROR_RETURN
   8854             (_bcm_mn_cosq_wred_set(unit, port, 0, flags, 0, 0, 0, 0,
   8855                                     FALSE, BCM_COSQ_DISCARD_PORT,8));
   8856     }
   8857 
   8858     return BCM_E_NONE;
   8859 }
   8860 
   8861 int
   8862 bcm_mn_cosq_discard_get(int unit, uint32 *flags)
   8863 {
   8864     bcm_port_t port;
   8865     PBMP_PORT_ITER(unit, port) {
   8866         *flags = 0;
   8867         /* use setting from hardware cosq index 0 of the first port */
   8868         return _bcm_mn_cosq_wred_get(unit, port, 0, flags, NULL, NULL, NULL,
   8869                                      NULL, BCM_COSQ_DISCARD_PORT,NULL);
   8870     }
   8871 
   8872     return BCM_E_NOT_FOUND;
   8873 }
   8874 
   8875 /*
   8876  * Function:
   8877  *     bcm_mn_cosq_discard_port_set
   8878  * Purpose:
   8879  *     Configure port WRED setting
   8880  * Parameters:
   8881  *     unit          - (IN) unit number
   8882  *     port          - (IN) port number or GPORT identifier
   8883  *     cosq          - (IN) COS queue number
   8884  *     color         - (IN)
   8885  *     drop_start    - (IN)
   8886  *     drop_slot     - (IN)
   8887  *     average_time  - (IN)
   8888  * Returns:
   8889  *     BCM_E_XXX
   8890  * Notes:
   8891  *     If port is any form of local port, cosq is the hardware queue index.
   8892  */
   8893 int
   8894 bcm_mn_cosq_discard_port_set(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   8895                              uint32 color, int drop_start, int drop_slope,
   8896                              int average_time)
   8897 {
   8898     bcm_port_t local_port;
   8899     bcm_pbmp_t pbmp;
   8900     int gain;
   8901     uint32 min_thresh, max_thresh, shared_limit;
   8902     uint32 rval, bits, flags = 0;
   8903     int numq, i;
   8904 
   8905     if (drop_start < 0 || drop_start > 100 ||
   8906         drop_slope < 0 || drop_slope > 90) {
   8907         return BCM_E_PARAM;
   8908     }
   8909 
   8910     /*
   8911      * average queue size is reculated every 8us, the formula is
   8912      * avg_qsize(t + 1) =
   8913      *     avg_qsize(t) + (cur_qsize - avg_qsize(t)) / (2 ** gain)
   8914      * gain = log2(average_time / 8)
   8915      */
   8916     bits = (average_time / 8) & 0xffff;
   8917     if (bits != 0) {
   8918         bits |= bits >> 1;
   8919         bits |= bits >> 2;
   8920         bits |= bits >> 4;
   8921         bits |= bits >> 8;
   8922         gain = _shr_popcount(bits) - 1;
   8923     } else {
   8924         gain = 0;
   8925     }
   8926 
   8927     /*
   8928      * per-port cell limit may be disabled.
   8929      * per-port per-cos cell limit may be set to use dynamic method.
   8930      * therefore drop_start percentage is based on per-device total shared
   8931      * cells.
   8932      */
   8933     BCM_IF_ERROR_RETURN(READ_MMU_THDM_DB_POOL_SHARED_LIMITr(unit, 0, &rval));
   8934     shared_limit = soc_reg_field_get(unit, MMU_THDM_DB_POOL_SHARED_LIMITr,
   8935                                      rval, SHARED_LIMITf);
   8936     min_thresh = ((drop_start * shared_limit) + (100 - 1)) / 100;
   8937 
   8938     if ( min_thresh == shared_limit ) {
   8939        min_thresh = AP_CELL_FIELD_MAX; 
   8940     }
   8941     /* Calculate the max threshold. For a given slope (angle in
   8942      * degrees), determine how many packets are in the range from
   8943      * 0% drop probability to 100% drop probability. Add that
   8944      * number to the min_treshold to the the max_threshold.
   8945      */
   8946     max_thresh = min_thresh + _bcm_mn_angle_to_cells(drop_slope);
   8947     if (max_thresh > AP_CELL_FIELD_MAX) {
   8948         max_thresh = AP_CELL_FIELD_MAX;
   8949     }
   8950 
   8951     if (BCM_GPORT_IS_SET(port)) {
   8952         numq = 1;
   8953         for (i = 0; i < numq; i++) {
   8954             BCM_IF_ERROR_RETURN
   8955                 (_bcm_mn_cosq_wred_set(unit, port, cosq + i, color,
   8956                                        min_thresh, max_thresh, 100, gain,
   8957                                        TRUE, flags,8));
   8958         }
   8959     } else {
   8960         if (port == -1) {
   8961             BCM_PBMP_ASSIGN(pbmp, PBMP_PORT_ALL(unit));
   8962         } else if (!SOC_PORT_VALID(unit, port)) {
   8963             return BCM_E_PORT;
   8964         } else {
   8965             BCM_PBMP_PORT_SET(pbmp, port);
   8966         }
   8967 
   8968         BCM_PBMP_ITER(pbmp, local_port) {
   8969             numq = 1;
   8970             for (i = 0; i < numq; i++) {
   8971                 BCM_IF_ERROR_RETURN
   8972                     (_bcm_mn_cosq_wred_set(unit, local_port, cosq + i,
   8973                                            color, min_thresh, max_thresh, 100,
   8974                                            gain, TRUE, 0,8));
   8975             }
   8976         }
   8977     }
   8978 
   8979     return BCM_E_NONE;
   8980 }
   8981 
   8982 /*
   8983  * Function:
   8984  *     bcm_mn_cosq_discard_port_get
   8985  * Purpose:
   8986  *     Get port WRED setting
   8987  * Parameters:
   8988  *     unit          - (IN) unit number
   8989  *     port          - (IN) port number or GPORT identifier
   8990  *     cosq          - (IN) COS queue number
   8991  *     color         - (OUT)
   8992  *     drop_start    - (OUT)
   8993  *     drop_slot     - (OUT)
   8994  *     average_time  - (OUT)
   8995  * Returns:
   8996  *     BCM_E_XXX
   8997  * Notes:
   8998  *     If port is any form of local port, cosq is the hardware queue index.
   8999  */
   9000 int
   9001 bcm_mn_cosq_discard_port_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   9002                              uint32 color, int *drop_start, int *drop_slope,
   9003                              int *average_time)
   9004 {
   9005     bcm_port_t local_port;
   9006     bcm_pbmp_t pbmp;
   9007     int gain, drop_prob;
   9008     int refresh_time = 0;
   9009     uint32 min_thresh, max_thresh, shared_limit;
   9010     uint32 rval;
   9011 
   9012     if (drop_start == NULL || drop_slope == NULL || average_time == NULL) {
   9013         return BCM_E_PARAM;
   9014     }
   9015 
   9016     if (BCM_GPORT_IS_SET(port)) {
   9017         local_port = port;
   9018     } else {
   9019         if (port == -1) {
   9020             BCM_PBMP_ASSIGN(pbmp, PBMP_PORT_ALL(unit));
   9021         } else if (!SOC_PORT_VALID(unit, port)) {
   9022             return BCM_E_PORT;
   9023         } else {
   9024             BCM_PBMP_PORT_SET(pbmp, port);
   9025         }
   9026         BCM_PBMP_ITER(pbmp, local_port) {
   9027             break;
   9028         }
   9029     }
   9030 
   9031     BCM_IF_ERROR_RETURN
   9032         (_bcm_mn_cosq_wred_get(unit, local_port, cosq == -1 ? 0 : cosq,
   9033                                &color, &min_thresh, &max_thresh, &drop_prob,
   9034                                &gain, 0,&refresh_time));
   9035 
   9036     /*
   9037      * average queue size is reculated every 4us, the formula is
   9038      * avg_qsize(t + 1) =
   9039      *     avg_qsize(t) + (cur_qsize - avg_qsize(t)) / (2 ** gain)
   9040      */
   9041     *average_time = (1 << gain) * refresh_time;
   9042     BCM_IF_ERROR_RETURN(READ_MMU_THDM_DB_POOL_SHARED_LIMITr(unit, 0, &rval));
   9043     shared_limit = soc_reg_field_get(unit, MMU_THDM_DB_POOL_SHARED_LIMITr,
   9044                                      rval, SHARED_LIMITf);
   9045     if (shared_limit == 0) {
   9046         return BCM_E_RESOURCE;
   9047     }
   9048 
   9049     if (min_thresh > shared_limit) {
   9050         min_thresh = shared_limit;
   9051     }
   9052 
   9053     if (max_thresh > shared_limit) {
   9054         max_thresh = shared_limit;
   9055     }
   9056 
   9057     *drop_start = min_thresh * 100 / shared_limit;
   9058 
   9059     /* Calculate the slope using the min and max threshold.
   9060      * The angle is calculated knowing drop probability at min
   9061      * threshold is 0% and drop probability at max threshold is 100%.
   9062      */
   9063     *drop_slope = _bcm_mn_cells_to_angle(max_thresh - min_thresh);
   9064 
   9065     return BCM_E_NONE;
   9066 }
   9067 
   9068 STATIC int
   9069 _bcm_mn_distribute_u64(uint64 value, uint64 *l, uint64 *r)
   9070 {
   9071     uint64 tmp, tmp1;
   9072 
   9073     tmp = value;
   9074     COMPILER_64_SHR(tmp, 1);
   9075     *l = tmp;
   9076 
   9077     COMPILER_64_SET(tmp1, 0, 1);
   9078     COMPILER_64_AND(tmp1, value);
   9079     COMPILER_64_ADD_64(tmp1, tmp);
   9080     *r = tmp1;
   9081     return 0;
   9082 }
   9083 
   9084 
   9085 int
   9086 bcm_mn_cosq_stat_set(int unit, bcm_gport_t port, bcm_cos_queue_t cosq,
   9087                      bcm_cosq_stat_t stat, uint64 value)
   9088 {
   9089     _bcm_mn_cosq_node_t *node;
   9090     bcm_port_t local_port;
   9091     int startq, numq, i, from_cos, to_cos, ci;
   9092     uint64  l, r;
   9093     uint64  max;
   9094     soc_reg_t ctr_reg;
   9095     soc_ctr_control_info_t ctrl_info;
   9096     _bcm_mn_mmu_info_t *mmu_info;
   9097     _bcm_mn_cosq_port_info_t *port_info;
   9098 
   9099     COMPILER_64_SET(max, 0, 0xffffffff);
   9100     if ((cosq < -1) || COMPILER_64_GT(value, max)) {
   9101         return BCM_E_PARAM;
   9102     }
   9103     _bcm_mn_distribute_u64(value, &l, &r);
   9104 
   9105     mmu_info = _bcm_mn_mmu_info[unit];
   9106 
   9107     switch (stat) {
   9108     case bcmCosqStatDroppedPackets:
   9109         if (BCM_GPORT_IS_SCHEDULER(port)) {
   9110             BCM_IF_ERROR_RETURN
   9111                 (_bcm_mn_cosq_node_get(unit, port, 0, NULL, 
   9112                                         &local_port, NULL, &node));
   9113             BCM_IF_ERROR_RETURN(
   9114                    _bcm_mn_cosq_child_node_at_input(node, cosq, &node));
   9115             port = node->gport;
   9116         }
   9117 
   9118         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) {
   9119             BCM_IF_ERROR_RETURN
   9120                 (_bcm_mn_cosq_index_resolve
   9121                  (unit, port, cosq, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_UCAST,
   9122                   &local_port, &startq, NULL));
   9123             /* coverity[NEGATIVE_RETURNS: FALSE] */
   9124             BCM_IF_ERROR_RETURN
   9125                 (_bcm_mn_cosq_node_get(unit, port, 0, NULL, 
   9126                                         &local_port, NULL, &node));
   9127             port_info = &mmu_info->port_info[local_port];
   9128             if (node->hw_index < port_info->uc_base || 
   9129                     node->hw_index >= port_info->uc_limit) {
   9130                BCM_IF_ERROR_RETURN
   9131                 (soc_counter_set(unit, node->hw_index,
   9132                                  SOC_COUNTER_NON_DMA_COSQ_DROP_PKT, 0,
   9133                                  value));
   9134             } else {
   9135                BCM_IF_ERROR_RETURN
   9136                 (soc_counter_set(unit, local_port,
   9137                                  SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_UC, startq,
   9138                                  value));
   9139             }
   9140         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
   9141             BCM_IF_ERROR_RETURN
   9142                 (_bcm_mn_cosq_index_resolve
   9143                  (unit, port, cosq, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_MCAST,
   9144                   &local_port, &startq, NULL));
   9145             /* coverity[NEGATIVE_RETURNS: FALSE] */
   9146             BCM_IF_ERROR_RETURN
   9147                 (soc_counter_set(unit, local_port,
   9148                              SOC_COUNTER_NON_DMA_COSQ_DROP_PKT, startq,
   9149                                  value));
   9150         } else {
   9151             BCM_IF_ERROR_RETURN(_bcm_mn_cosq_localport_resolve(unit, port, &local_port));
   9152             BCM_IF_ERROR_RETURN(_bcm_mn_cosq_port_has_ets(unit, local_port));
   9153             if (cosq == BCM_COS_INVALID) {
   9154                 from_cos = to_cos = 0;
   9155             } else {
   9156                 from_cos = to_cos = cosq;
   9157             }
   9158             for (ci = from_cos; ci <= to_cos; ci++) {
   9159                 if (!IS_CPU_PORT(unit, local_port)) {
   9160                     BCM_IF_ERROR_RETURN
   9161                         (_bcm_mn_cosq_index_resolve
   9162                          (unit, port, ci, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_UCAST,
   9163                           &local_port, &startq, &numq));
   9164                     for (i = 0; i < numq; i++) {
   9165                     /* coverity[NEGATIVE_RETURNS: FALSE] */
   9166                       BCM_IF_ERROR_RETURN
   9167                            (soc_counter_set(unit, local_port,
   9168                                            SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_UC,
   9169                                          startq + i, l));
   9170                     }
   9171                 }
   9172                 BCM_IF_ERROR_RETURN
   9173                     (_bcm_mn_cosq_index_resolve
   9174                      (unit, port, ci, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_MCAST,
   9175                       &local_port, &startq, &numq));
   9176                 for (i = 0; i < numq; i++) {
   9177                     BCM_IF_ERROR_RETURN
   9178                         (soc_counter_set(unit, local_port,
   9179                                          SOC_COUNTER_NON_DMA_COSQ_DROP_PKT,
   9180                                          startq + i , r));
   9181                 }
   9182             }
   9183         }
   9184         break;
   9185     case bcmCosqStatDroppedBytes:
   9186         if (BCM_GPORT_IS_SCHEDULER(port)) {
   9187             BCM_IF_ERROR_RETURN
   9188                 (_bcm_mn_cosq_node_get(unit, port, 0, NULL, 
   9189                                         &local_port, NULL, &node));
   9190             BCM_IF_ERROR_RETURN(
   9191                    _bcm_mn_cosq_child_node_at_input(node, cosq, &node));
   9192             port = node->gport;
   9193         }
   9194 
   9195         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) {
   9196             BCM_IF_ERROR_RETURN
   9197                 (_bcm_mn_cosq_index_resolve
   9198                  (unit, port, cosq, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_UCAST,
   9199                   &local_port, &startq, NULL));
   9200             BCM_IF_ERROR_RETURN
   9201                 (_bcm_mn_cosq_node_get(unit, port, 0, NULL, 
   9202                                         &local_port, NULL, &node));
   9203             /* coverity[NEGATIVE_RETURNS: FALSE] */
   9204             port_info = &mmu_info->port_info[local_port];
   9205             if (node->hw_index < port_info->uc_base || 
   9206                           node->hw_index >= port_info->uc_limit) {
   9207                BCM_IF_ERROR_RETURN
   9208                 (soc_counter_set(unit, node->hw_index,
   9209                                  SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE, 0,
   9210                                  value));
   9211             } else {
   9212                BCM_IF_ERROR_RETURN
   9213                 (soc_counter_set(unit, local_port,
   9214                                  SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE_UC, startq,
   9215                                  value));
   9216             } 
   9217         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
   9218             BCM_IF_ERROR_RETURN
   9219                 (_bcm_mn_cosq_index_resolve
   9220                  (unit, port, cosq, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_MCAST,
   9221                   &local_port, &startq, NULL));
   9222             /* coverity[NEGATIVE_RETURNS: FALSE] */
   9223             BCM_IF_ERROR_RETURN
   9224                 (soc_counter_set(unit, local_port,
   9225                    SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE, startq , value));
   9226         } else {
   9227             BCM_IF_ERROR_RETURN(_bcm_mn_cosq_localport_resolve(unit, port, &local_port));
   9228             BCM_IF_ERROR_RETURN(_bcm_mn_cosq_port_has_ets(unit, local_port));
   9229             if (cosq == BCM_COS_INVALID) {
   9230                 from_cos = to_cos = 0;
   9231             } else {
   9232                 from_cos = to_cos = cosq;
   9233             }
   9234             for (ci = from_cos; ci <= to_cos; ci++) {
   9235                 if (!IS_CPU_PORT(unit, local_port)) {
   9236                     BCM_IF_ERROR_RETURN
   9237                        (_bcm_mn_cosq_index_resolve
   9238                         (unit, port, ci, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_UCAST,
   9239                          &local_port, &startq, &numq));
   9240                     for (i = 0; i < numq; i++) {
   9241                     /* coverity[NEGATIVE_RETURNS: FALSE] */
   9242                        BCM_IF_ERROR_RETURN
   9243                         (soc_counter_set(unit, local_port,
   9244                                          SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE_UC,
   9245                                          startq + i, l));
   9246                     }
   9247                 }
   9248                 BCM_IF_ERROR_RETURN
   9249                     (_bcm_mn_cosq_index_resolve
   9250                      (unit, port, ci, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_MCAST,
   9251                       &local_port, &startq, &numq));
   9252                 for (i = 0; i < numq; i++) {
   9253                     BCM_IF_ERROR_RETURN
   9254                         (soc_counter_set(unit, local_port,
   9255                            SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE,
   9256                                          startq + i , r));
   9257                 }
   9258             }
   9259         }
   9260         break;
   9261     case bcmCosqStatYellowCongestionDroppedPackets:
   9262         if (cosq != BCM_COS_INVALID) {
   9263             return BCM_E_UNAVAIL;
   9264         }
   9265         BCM_IF_ERROR_RETURN
   9266             (_bcm_mn_cosq_localport_resolve(unit, port, &local_port));
   9267         BCM_IF_ERROR_RETURN
   9268             (soc_counter_set(unit, local_port,
   9269                              SOC_COUNTER_NON_DMA_PORT_DROP_PKT_YELLOW, 0,
   9270                              value));
   9271         break;
   9272     case bcmCosqStatRedCongestionDroppedPackets:
   9273         if (cosq != BCM_COS_INVALID) {
   9274             return BCM_E_UNAVAIL;
   9275         }
   9276         BCM_IF_ERROR_RETURN
   9277             (_bcm_mn_cosq_localport_resolve(unit, port, &local_port));
   9278         BCM_IF_ERROR_RETURN
   9279             (soc_counter_set(unit, local_port,
   9280                              SOC_COUNTER_NON_DMA_PORT_DROP_PKT_RED, 0,
   9281                              value));
   9282         break;
   9283     case bcmCosqStatGreenDiscardDroppedPackets:
   9284         if (cosq != BCM_COS_INVALID) {
   9285             return BCM_E_UNAVAIL;
   9286         }
   9287         BCM_IF_ERROR_RETURN
   9288             (_bcm_mn_cosq_localport_resolve(unit, port, &local_port));
   9289         BCM_IF_ERROR_RETURN
   9290             (soc_counter_set(unit, local_port,
   9291                              SOC_COUNTER_NON_DMA_PORT_WRED_PKT_GREEN, 0,
   9292                              value));
   9293         break;
   9294     case bcmCosqStatYellowDiscardDroppedPackets:
   9295         if (cosq != BCM_COS_INVALID) {
   9296             return BCM_E_UNAVAIL;
   9297         }
   9298         BCM_IF_ERROR_RETURN
   9299             (_bcm_mn_cosq_localport_resolve(unit, port, &local_port));
   9300         BCM_IF_ERROR_RETURN
   9301             (soc_counter_set(unit, local_port,
   9302                              SOC_COUNTER_NON_DMA_PORT_WRED_PKT_YELLOW, 0,
   9303                              value));
   9304         break;
   9305     case bcmCosqStatRedDiscardDroppedPackets:
   9306         if (cosq != BCM_COS_INVALID) {
   9307             return BCM_E_UNAVAIL;
   9308         }
   9309         BCM_IF_ERROR_RETURN
   9310             (_bcm_mn_cosq_localport_resolve(unit, port, &local_port));
   9311         BCM_IF_ERROR_RETURN
   9312             (soc_counter_set(unit, local_port,
   9313                              SOC_COUNTER_NON_DMA_PORT_WRED_PKT_RED, 0, value));
   9314         break;
   9315     case bcmCosqStatOutPackets:
   9316         if (BCM_GPORT_IS_SCHEDULER(port)) {
   9317             BCM_IF_ERROR_RETURN
   9318                 (_bcm_mn_cosq_node_get(unit, port, 0, NULL, 
   9319                                         &local_port, NULL, &node));
   9320             BCM_IF_ERROR_RETURN(
   9321                    _bcm_mn_cosq_child_node_at_input(node, cosq, &node));
   9322             port = node->gport;
   9323         }
   9324 
   9325         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) {
   9326             BCM_IF_ERROR_RETURN
   9327                 (_bcm_mn_cosq_index_resolve
   9328                  (unit, port, cosq, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_UCAST,
   9329                   &local_port, &startq, NULL));
   9330             /* coverity[NEGATIVE_RETURNS: FALSE] */
   9331             BCM_IF_ERROR_RETURN
   9332                 (_bcm_mn_cosq_node_get(unit, port, 0, NULL, 
   9333                                         &local_port, NULL, &node));
   9334             port_info = &mmu_info->port_info[local_port];
   9335             if (node->hw_index < port_info->uc_base 
   9336                         || node->hw_index >= port_info->uc_limit) {
   9337               BCM_IF_ERROR_RETURN
   9338                 (soc_counter_set(unit, node->hw_index,
   9339                                  SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT, 0,
   9340                                  value));
   9341             } else {
   9342               BCM_IF_ERROR_RETURN
   9343                 (soc_counter_set(unit, local_port,
   9344                                  SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT_UC, startq,
   9345                                  value));
   9346             } 
   9347         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
   9348             BCM_IF_ERROR_RETURN
   9349                 (_bcm_mn_cosq_index_resolve
   9350                  (unit, port, cosq, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_MCAST,
   9351                   &local_port, &startq, NULL));
   9352             /* coverity[NEGATIVE_RETURNS: FALSE] */
   9353             BCM_IF_ERROR_RETURN
   9354                 (soc_counter_set(unit, local_port,
   9355                                  SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT, startq,
   9356                                  value));
   9357         } else {
   9358             BCM_IF_ERROR_RETURN(_bcm_mn_cosq_localport_resolve(unit, port, &local_port));
   9359             BCM_IF_ERROR_RETURN(_bcm_mn_cosq_port_has_ets(unit, local_port));
   9360             if (cosq == BCM_COS_INVALID) {
   9361                 from_cos = to_cos = 0;
   9362             } else {
   9363                 from_cos = to_cos = cosq;
   9364             }
   9365             for (ci = from_cos; ci <= to_cos; ci++) {
   9366                 if (!IS_CPU_PORT(unit, local_port)) {
   9367                     BCM_IF_ERROR_RETURN
   9368                         (_bcm_mn_cosq_index_resolve
   9369                             (unit, port, ci, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_UCAST,
   9370                              &local_port, &startq, &numq));
   9371                     for (i = 0; i < numq; i++) {
   9372                         /* coverity[NEGATIVE_RETURNS: FALSE] */
   9373                         BCM_IF_ERROR_RETURN
   9374                             (soc_counter_set(unit, local_port,
   9375                                              SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT_UC,
   9376                                              startq + i, l));
   9377                     }
   9378                 }
   9379                 BCM_IF_ERROR_RETURN
   9380                     (_bcm_mn_cosq_index_resolve
   9381                      (unit, port, ci, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_MCAST,
   9382                       &local_port, &startq, &numq));
   9383                 for (i = 0; i < numq; i++) {
   9384                     BCM_IF_ERROR_RETURN
   9385                         (soc_counter_set(unit, local_port,
   9386                                          SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT,
   9387                                          startq + i, r));
   9388                 }
   9389             }
   9390         }
   9391         break;
   9392     case bcmCosqStatOutBytes:
   9393         if (BCM_GPORT_IS_SCHEDULER(port)) {
   9394             BCM_IF_ERROR_RETURN
   9395                 (_bcm_mn_cosq_node_get(unit, port, 0, NULL, 
   9396                                         &local_port, NULL, &node));
   9397             BCM_IF_ERROR_RETURN(
   9398                    _bcm_mn_cosq_child_node_at_input(node, cosq, &node));
   9399             port = node->gport;
   9400         }
   9401 
   9402         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) {
   9403             BCM_IF_ERROR_RETURN
   9404                 (_bcm_mn_cosq_index_resolve
   9405                  (unit, port, cosq, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_UCAST,
   9406                   &local_port, &startq, NULL));
   9407             /* coverity[NEGATIVE_RETURNS: FALSE] */
   9408             BCM_IF_ERROR_RETURN
   9409                 (_bcm_mn_cosq_node_get(unit, port, 0, NULL, 
   9410                                         &local_port, NULL, &node));
   9411             port_info = &mmu_info->port_info[local_port];
   9412             if (node->hw_index < port_info->uc_base || 
   9413                      node->hw_index >= port_info->uc_limit) {
   9414                 BCM_IF_ERROR_RETURN
   9415                    (soc_counter_set(unit, node->hw_index,
   9416                                  SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE, 0,
   9417                                  value));
   9418             } else {
   9419                 BCM_IF_ERROR_RETURN
   9420                    (soc_counter_set(unit, local_port,
   9421                                  SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE_UC, startq,
   9422                                  value));
   9423             } 
   9424         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
   9425             BCM_IF_ERROR_RETURN
   9426                 (_bcm_mn_cosq_index_resolve
   9427                  (unit, port, cosq, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_MCAST,
   9428                   &local_port, &startq, NULL));
   9429             /* coverity[NEGATIVE_RETURNS: FALSE] */
   9430             BCM_IF_ERROR_RETURN
   9431                 (soc_counter_set(unit, local_port,
   9432                                  SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE, startq,
   9433                                  value));
   9434         } else {
   9435             BCM_IF_ERROR_RETURN(_bcm_mn_cosq_localport_resolve(unit, port, &local_port));
   9436             BCM_IF_ERROR_RETURN(_bcm_mn_cosq_port_has_ets(unit, local_port));
   9437             if (cosq == BCM_COS_INVALID) {
   9438                 from_cos = to_cos = 0;
   9439             } else {
   9440                 from_cos = to_cos = cosq;
   9441             }
   9442             for (ci = from_cos; ci <= to_cos; ci++) {
   9443                 if (!IS_CPU_PORT(unit, local_port)) {
   9444                     BCM_IF_ERROR_RETURN
   9445                         (_bcm_mn_cosq_index_resolve
   9446                             (unit, port, ci, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_UCAST,
   9447                              &local_port, &startq, &numq));
   9448                     for (i = 0; i < numq; i++) {
   9449                         /* coverity[NEGATIVE_RETURNS: FALSE] */
   9450                         BCM_IF_ERROR_RETURN
   9451                             (soc_counter_set(unit, local_port,
   9452                                              SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE_UC,
   9453                                              startq + i, l));
   9454                     }
   9455                 }
   9456                 BCM_IF_ERROR_RETURN
   9457                     (_bcm_mn_cosq_index_resolve
   9458                      (unit, port, ci, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_MCAST,
   9459                       &local_port, &startq, &numq));
   9460                 for (i = 0; i < numq; i++) {
   9461                     BCM_IF_ERROR_RETURN
   9462                         (soc_counter_set(unit, local_port,
   9463                                          SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE,
   9464                                          startq + i, r));
   9465                 }
   9466             }
   9467         }
   9468         break;
   9469     case bcmCosqStatIeee8021CnCpTransmittedCnms:
   9470         BCM_IF_ERROR_RETURN
   9471             (_bcm_mn_cosq_index_resolve
   9472                 (unit, port, cosq, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_UCAST,
   9473                  &local_port, &startq, NULL));        
   9474         BCM_IF_ERROR_RETURN
   9475             (soc_counter_set(unit, local_port,
   9476                              SOC_COUNTER_NON_DMA_MMU_QCN_CNM, startq, value));
   9477         break;
   9478     
   9479     case bcmCosqStatHighPriDroppedPackets:
   9480     case bcmCosqStatOBMLossyHighPriDroppedPackets:
   9481     case bcmCosqStatLowPriDroppedPackets:
   9482     case bcmCosqStatOBMLossyLowPriDroppedPackets:
   9483     case bcmCosqStatHighPriDroppedBytes:
   9484     case bcmCosqStatOBMLossyHighPriDroppedBytes:
   9485     case bcmCosqStatLowPriDroppedBytes:
   9486     case bcmCosqStatOBMLossyLowPriDroppedBytes:
   9487     case bcmCosqStatOBMLossless0DroppedPackets:
   9488     case bcmCosqStatOBMLossless1DroppedPackets:
   9489     case bcmCosqStatOBMLossless0DroppedBytes:
   9490     case bcmCosqStatOBMLossless1DroppedBytes:
   9491     case bcmCosqStatOBMLossless0EnqueuedPackets:
   9492     case bcmCosqStatOBMLossless0EnqueuedBytes:
   9493     case bcmCosqStatOBMLossless1EnqueuedPackets:
   9494     case bcmCosqStatOBMLossless1EnqueuedBytes:
   9495     case bcmCosqStatOBMLossyHighPriEnqueuedPackets:
   9496     case bcmCosqStatOBMLossyHighPriEnqueuedBytes:
   9497     case bcmCosqStatOBMLossyLowPriEnqueuedPackets:
   9498     case bcmCosqStatOBMLossyLowPriEnqueuedBytes:
   9499     case bcmCosqStatOBMExpressEnqueuedPackets:
   9500     case bcmCosqStatOBMExpressEnqueuedBytes:
   9501     case bcmCosqStatOBMExpressDroppedPackets:
   9502     case bcmCosqStatOBMExpressDroppedBytes:
   9503         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
   9504             BCM_GPORT_IS_SCHEDULER(port) ||
   9505             BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
   9506             return BCM_E_PARAM;
   9507         }
   9508         BCM_IF_ERROR_RETURN(
   9509             _bcm_mn_cosq_localport_resolve(unit, port, &local_port));
   9510         if ((stat == bcmCosqStatHighPriDroppedPackets) ||
   9511             (stat == bcmCosqStatOBMLossyHighPriDroppedPackets)) {
   9512             ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM_LOSSY_HI;
   9513         } else if ((stat == bcmCosqStatLowPriDroppedPackets) ||
   9514                    (stat == bcmCosqStatOBMLossyLowPriDroppedPackets)) {
   9515             ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM_LOSSY_LO;
   9516         } else if ((stat == bcmCosqStatHighPriDroppedBytes) ||
   9517                    (stat == bcmCosqStatOBMLossyHighPriDroppedBytes)) {
   9518             ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM_LOSSY_HI;
   9519         } else if ((stat == bcmCosqStatLowPriDroppedBytes) ||
   9520                    (stat == bcmCosqStatOBMLossyLowPriDroppedBytes)) {
   9521             ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM_LOSSY_LO;
   9522         } else if (stat == bcmCosqStatOBMLossless0DroppedPackets) {
   9523             ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM_LOSSLESS0;
   9524         } else if (stat == bcmCosqStatOBMLossless1DroppedPackets) {
   9525             ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM_LOSSLESS1;
   9526         } else if (stat == bcmCosqStatOBMLossless0DroppedBytes) {
   9527             ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM_LOSSLESS0;
   9528         } else if (stat == bcmCosqStatOBMLossless1DroppedBytes) {
   9529             ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM_LOSSLESS1;
   9530         } else if (stat == bcmCosqStatOBMLossless0EnqueuedPackets) {
   9531             ctr_reg = SOC_COUNTER_NON_DMA_PORT_ENQUEUE_PKT_OBM_LOSSLESS0;
   9532         } else if (stat == bcmCosqStatOBMLossless0EnqueuedBytes) {
   9533             ctr_reg = SOC_COUNTER_NON_DMA_PORT_ENQUEUE_BYTE_OBM_LOSSLESS0;
   9534         } else if (stat == bcmCosqStatOBMLossless1EnqueuedPackets) {
   9535             ctr_reg = SOC_COUNTER_NON_DMA_PORT_ENQUEUE_PKT_OBM_LOSSLESS1;
   9536         } else if (stat == bcmCosqStatOBMLossless1EnqueuedBytes) {
   9537             ctr_reg = SOC_COUNTER_NON_DMA_PORT_ENQUEUE_BYTE_OBM_LOSSLESS1;
   9538         } else if (stat == bcmCosqStatOBMLossyHighPriEnqueuedPackets) {
   9539             ctr_reg = SOC_COUNTER_NON_DMA_PORT_ENQUEUE_PKT_OBM_LOSSY_HI;
   9540         } else if (stat == bcmCosqStatOBMLossyHighPriEnqueuedBytes) {
   9541             ctr_reg = SOC_COUNTER_NON_DMA_PORT_ENQUEUE_BYTE_OBM_LOSSY_HI;
   9542         } else if (stat == bcmCosqStatOBMLossyLowPriEnqueuedPackets) {
   9543             ctr_reg = SOC_COUNTER_NON_DMA_PORT_ENQUEUE_PKT_OBM_LOSSY_LO;
   9544         } else if (stat == bcmCosqStatOBMLossyLowPriEnqueuedBytes) {
   9545             ctr_reg = SOC_COUNTER_NON_DMA_PORT_ENQUEUE_BYTE_OBM_LOSSY_LO;
   9546         } else if (stat == bcmCosqStatOBMExpressEnqueuedPackets) {
   9547             ctr_reg = SOC_COUNTER_NON_DMA_PORT_ENQUEUE_PKT_OBM_EXPRESS;
   9548         } else if (stat == bcmCosqStatOBMExpressEnqueuedBytes) {
   9549             ctr_reg = SOC_COUNTER_NON_DMA_PORT_ENQUEUE_BYTE_OBM_EXPRESS;
   9550         } else if (stat == bcmCosqStatOBMExpressDroppedPackets) {
   9551             ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM_EXPRESS;
   9552         } else { /*if (stat == bcmCosqStatOBMExpressDroppedBytes) */
   9553             ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM_EXPRESS;
   9554         }
   9555         ctrl_info.instance_type = SOC_CTR_INSTANCE_TYPE_PORT;
   9556         ctrl_info.instance = local_port;
   9557         BCM_IF_ERROR_RETURN
   9558             (soc_counter_generic_set(unit, ctr_reg, ctrl_info, 0,
   9559                                      0, value));
   9560 
   9561         break;
   9562     default:
   9563         return BCM_E_PARAM;
   9564     }
   9565 
   9566     return BCM_E_NONE;
   9567 }
   9568 
   9569 
   9570 static int 
   9571 _bcm_mn_cosq_uc_stat_get(int unit, bcm_port_t port, uint64 *value, soc_reg_t regs1,
   9572                         soc_reg_t regs2, int sync_mode, int cosq)
   9573 {
   9574     int (*counter_get) (int , soc_port_t , soc_reg_t , int , uint64 *);
   9575     bcm_port_t local_port;
   9576     _bcm_mn_cosq_node_t *node;
   9577     _bcm_mn_cosq_port_info_t *port_info;
   9578 
   9579     _bcm_mn_mmu_info_t *mmu_info;
   9580     mmu_info = _bcm_mn_mmu_info[unit];
   9581     counter_get = (sync_mode == 1)? soc_counter_sync_get: soc_counter_get;
   9582 
   9583     BCM_IF_ERROR_RETURN
   9584         (_bcm_mn_cosq_node_get(unit, port, 0, NULL, 
   9585                                &local_port, NULL, &node));
   9586     port_info = &mmu_info->port_info[local_port];
   9587     if (node->hw_index < port_info->uc_base || 
   9588             node->hw_index >= port_info->uc_limit) {
   9589         /* coverity[NEGATIVE_RETURNS: FALSE] */
   9590         BCM_IF_ERROR_RETURN
   9591             (counter_get(unit, node->hw_index,
   9592                          regs2, 0,
   9593                          value));
   9594     } else {
   9595 
   9596 
   9597         /* coverity[NEGATIVE_RETURNS: FALSE] */
   9598 
   9599         BCM_IF_ERROR_RETURN
   9600             (counter_get(unit, local_port,
   9601                          regs1, cosq,
   9602                          value));
   9603     }
   9604     return BCM_E_NONE;
   9605 }
   9606 
   9607 static int
   9608 _bcm_mn_cosq_mc_stat_get(int unit, bcm_port_t port, uint64 *value, soc_reg_t regs, 
   9609                         int sync_mode, int cosq)
   9610 {
   9611     int startq;
   9612     int (*counter_get) (int , soc_port_t , soc_reg_t , int , uint64 *);
   9613     bcm_port_t local_port;
   9614     
   9615     counter_get = (sync_mode == 1)? soc_counter_sync_get: soc_counter_get;
   9616     BCM_IF_ERROR_RETURN
   9617         (_bcm_mn_cosq_index_resolve
   9618          (unit, port, cosq, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_MCAST,
   9619           &local_port, &startq, NULL));
   9620     /* coverity[NEGATIVE_RETURNS: FALSE] */
   9621     BCM_IF_ERROR_RETURN
   9622         (counter_get(unit, local_port, regs, startq, value));
   9623     return BCM_E_NONE;
   9624 }
   9625 
   9626 
   9627 /* get the l2 queues for the scheduler node*/
   9628 STATIC int
   9629 _bcm_mn_cosq_stat_get(int unit, bcm_port_t port, _bcm_mn_cosq_node_t *node,int sync_mode, 
   9630                         uint64 *value, soc_reg_t uc_regs, soc_reg_t mc_regs)
   9631 {
   9632     uint64 sum;
   9633     uint64  value64;
   9634 
   9635     COMPILER_64_ZERO(value64);
   9636     COMPILER_64_ZERO(sum);
   9637     /*the function will be called recursively */    
   9638     if (node->level == SOC_MONTEREY_NODE_LVL_L2) {
   9639         while (node){
   9640             port = node->gport;
   9641             /*
   9642              *check if the port is uc or mc and get the stats for the needed 
   9643              *type    
   9644              */
   9645             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) {
   9646                 if (uc_regs == -1){
   9647                     return BCM_E_PARAM;
   9648                 }
   9649                 BCM_IF_ERROR_RETURN(
   9650                         _bcm_mn_cosq_uc_stat_get(unit, port, &value64, uc_regs, mc_regs,
   9651                             sync_mode, node->hw_cosq));
   9652                 COMPILER_64_ADD_64(sum, value64);
   9653             } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
   9654                 if (mc_regs == -1){
   9655                     return BCM_E_PARAM;
   9656                 }
   9657                 BCM_IF_ERROR_RETURN(
   9658                         _bcm_mn_cosq_mc_stat_get(unit, port, &value64, mc_regs, 
   9659                             sync_mode, node->hw_cosq));
   9660                 COMPILER_64_ADD_64(sum, value64);
   9661             }           
   9662             node = node->sibling;
   9663         }
   9664     }
   9665     else {
   9666         if(node->sibling){
   9667             BCM_IF_ERROR_RETURN(_bcm_mn_cosq_stat_get(unit, port, node->sibling, sync_mode, 
   9668                         value, uc_regs, mc_regs));
   9669         }
   9670         if(node->child){
   9671             BCM_IF_ERROR_RETURN(_bcm_mn_cosq_stat_get(unit, port, node->child, sync_mode, 
   9672                         value, uc_regs, mc_regs));
   9673         }
   9674     }
   9675     COMPILER_64_ADD_64(*value, sum);
   9676     return BCM_E_NONE; 
   9677 
   9678 }
   9679 
   9680 
   9681 int
   9682 bcm_mn_cosq_stat_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   9683                      bcm_cosq_stat_t stat, int sync_mode, uint64 *value)
   9684 {
   9685     _bcm_mn_cosq_node_t *node;
   9686     bcm_port_t local_port;
   9687     int startq, numq, i, from_cos, to_cos, ci, start_hw_index, end_hw_index;
   9688     uint64 sum, value64;
   9689     int (*counter_get) (int , soc_port_t , soc_reg_t , int , uint64 *);
   9690     soc_reg_t ctr_reg;
   9691     soc_ctr_control_info_t ctrl_info;
   9692     _bcm_mn_mmu_info_t *mmu_info;
   9693     _bcm_mn_cosq_port_info_t *port_info;
   9694     if ((value == NULL) || (cosq < -1)) {
   9695         return BCM_E_PARAM;
   9696     }
   9697     
   9698 
   9699     mmu_info = _bcm_mn_mmu_info[unit];
   9700 
   9701     /*
   9702      * if sync-mode is set, update the software cached counter value, 
   9703      * with the hardware count and then retrieve the count.
   9704      * else return the software cache counter value.
   9705      */
   9706     counter_get = (sync_mode == 1)? soc_counter_sync_get: soc_counter_get;
   9707 
   9708     switch (stat) {
   9709     case bcmCosqStatDroppedPackets:
   9710         
   9711         if (BCM_GPORT_IS_SCHEDULER(port)) {
   9712              BCM_IF_ERROR_RETURN
   9713                 (_bcm_mn_cosq_node_get(unit, port, 0, NULL, 
   9714                                         &local_port, NULL, &node));
   9715             
   9716              if (cosq == BCM_COS_INVALID) {
   9717                  node = node->child;
   9718                  if (node){
   9719                     COMPILER_64_ZERO(value64);
   9720                      BCM_IF_ERROR_RETURN(_bcm_mn_cosq_stat_get(unit, port, 
   9721                                  node, sync_mode, &value64,SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_UC,
   9722                                  SOC_COUNTER_NON_DMA_COSQ_DROP_PKT));
   9723                      *value = value64;
   9724                      break; 
   9725                  }
   9726              }
   9727             BCM_IF_ERROR_RETURN(
   9728                    _bcm_mn_cosq_child_node_at_input(node, cosq, &node));
   9729             port = node->gport;
   9730         }
   9731 
   9732         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) {
   9733             BCM_IF_ERROR_RETURN
   9734                 (_bcm_mn_cosq_index_resolve
   9735                  (unit, port, cosq, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_UCAST,
   9736                   &local_port, &startq, NULL));
   9737             /* coverity[NEGATIVE_RETURNS: FALSE] */
   9738             
   9739             BCM_IF_ERROR_RETURN
   9740             (_bcm_mn_cosq_node_get(unit, port, 0, NULL, 
   9741                                    &local_port, NULL, &node));
   9742             port_info = &mmu_info->port_info[local_port];
   9743             if (node->hw_index < port_info->uc_base || 
   9744                              node->hw_index >= port_info->uc_limit) 
   9745             {
   9746                   BCM_IF_ERROR_RETURN
   9747                   (counter_get(unit, node->hw_index,
   9748                             SOC_COUNTER_NON_DMA_COSQ_DROP_PKT, 0,
   9749                                  value));
   9750             } else {                                     
   9751                 BCM_IF_ERROR_RETURN
   9752                   (counter_get(unit, local_port,
   9753                             SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_UC, startq,
   9754                                  value));
   9755             }
   9756         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
   9757             BCM_IF_ERROR_RETURN
   9758                 (_bcm_mn_cosq_index_resolve
   9759                  (unit, port, cosq, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_MCAST,
   9760                   &local_port, &startq, NULL));
   9761             /* coverity[NEGATIVE_RETURNS: FALSE] */
   9762             BCM_IF_ERROR_RETURN
   9763                 (counter_get(unit, local_port,
   9764                     SOC_COUNTER_NON_DMA_COSQ_DROP_PKT, startq, value));
   9765         } else {
   9766             BCM_IF_ERROR_RETURN(_bcm_mn_cosq_localport_resolve(unit, port, &local_port));
   9767             BCM_IF_ERROR_RETURN(_bcm_mn_cosq_port_has_ets(unit, local_port));
   9768             COMPILER_64_ZERO(sum);
   9769             if (cosq == BCM_COS_INVALID) {
   9770                 from_cos = 0;
   9771                 to_cos = (IS_CPU_PORT(unit, local_port)) ? 
   9772                             NUM_CPU_COSQ(unit) - 1 : _MN_NUM_COS(unit) - 1;
   9773             } else {
   9774                 from_cos = to_cos = cosq;
   9775             }
   9776             for (ci = from_cos; ci <= to_cos; ci++) {
   9777                 if (!IS_CPU_PORT(unit, local_port)) {
   9778                     BCM_IF_ERROR_RETURN
   9779                     (_bcm_mn_cosq_index_resolve
   9780                      (unit, port, ci, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_UCAST,
   9781                       &local_port, &startq, &numq));
   9782                     for (i = 0; i < numq; i++) {
   9783                     /* coverity[NEGATIVE_RETURNS: FALSE] */
   9784                          BCM_IF_ERROR_RETURN
   9785                             (counter_get(unit, local_port,
   9786                                          SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_UC,
   9787                                          startq + i, &value64));
   9788                          COMPILER_64_ADD_64(sum, value64);
   9789                     }
   9790                 }
   9791                 BCM_IF_ERROR_RETURN
   9792                   (_bcm_mn_cosq_index_resolve
   9793                      (unit, port, ci, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_MCAST,
   9794                       &local_port, &startq, &numq));
   9795 
   9796                 for (i = 0; i < numq; i++) {
   9797                     /* coverity[NEGATIVE_RETURNS: FALSE] */
   9798                     BCM_IF_ERROR_RETURN
   9799                         (counter_get(unit, local_port,
   9800                                          SOC_COUNTER_NON_DMA_COSQ_DROP_PKT,
   9801                                          startq + i, &value64));
   9802                     COMPILER_64_ADD_64(sum, value64);
   9803                 }
   9804             }
   9805            *value = sum;
   9806         }
   9807         break;
   9808     case bcmCosqStatDroppedBytes:
   9809         if (BCM_GPORT_IS_SCHEDULER(port)) {
   9810             BCM_IF_ERROR_RETURN
   9811                 (_bcm_mn_cosq_node_get(unit, port, 0, NULL, 
   9812                                         &local_port, NULL, &node));
   9813             if (cosq == BCM_COS_INVALID) {
   9814                  node = node->child;
   9815                  if (node){
   9816                     COMPILER_64_ZERO(value64);
   9817                      BCM_IF_ERROR_RETURN(_bcm_mn_cosq_stat_get(unit, port, 
   9818                                  node, sync_mode, &value64,SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE_UC,
   9819                                  SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE));
   9820                      *value = value64;
   9821                      break; 
   9822                  }
   9823              }
   9824 
   9825                 BCM_IF_ERROR_RETURN(
   9826                    _bcm_mn_cosq_child_node_at_input(node, cosq, &node));
   9827             port = node->gport;
   9828         }
   9829 
   9830         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) {
   9831             BCM_IF_ERROR_RETURN
   9832                 (_bcm_mn_cosq_index_resolve
   9833                  (unit, port, cosq, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_UCAST,
   9834                   &local_port, &startq, NULL));
   9835             /* coverity[NEGATIVE_RETURNS: FALSE] */
   9836             BCM_IF_ERROR_RETURN
   9837             (_bcm_mn_cosq_node_get(unit, port, 0, NULL, 
   9838                                    &local_port, NULL, &node));
   9839             port_info = &mmu_info->port_info[local_port];
   9840             if (node->hw_index < port_info->uc_base || 
   9841                       node->hw_index >= port_info->uc_limit) {
   9842                 BCM_IF_ERROR_RETURN
   9843                 (counter_get(unit, node->hw_index,
   9844                                  SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE, 0,
   9845                                  value));
   9846             } else { 
   9847                 BCM_IF_ERROR_RETURN
   9848                 (counter_get(unit, local_port,
   9849                                  SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE_UC, startq,
   9850                                  value));
   9851             }
   9852         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
   9853             BCM_IF_ERROR_RETURN
   9854                 (_bcm_mn_cosq_index_resolve
   9855                  (unit, port, cosq, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_MCAST,
   9856                   &local_port, &startq, NULL));
   9857             /* coverity[NEGATIVE_RETURNS: FALSE] */
   9858             BCM_IF_ERROR_RETURN
   9859                 (counter_get(unit, local_port,
   9860                   SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE, startq, value));
   9861         } else {
   9862             BCM_IF_ERROR_RETURN(_bcm_mn_cosq_localport_resolve(unit, port, &local_port));
   9863             BCM_IF_ERROR_RETURN(_bcm_mn_cosq_port_has_ets(unit, local_port));
   9864             COMPILER_64_ZERO(sum);
   9865             if (cosq == BCM_COS_INVALID) {
   9866                 from_cos = 0;
   9867                 to_cos = (IS_CPU_PORT(unit, local_port)) ? 
   9868                             NUM_CPU_COSQ(unit) - 1 : _MN_NUM_COS(unit) - 1;
   9869             } else {
   9870                 from_cos = to_cos = cosq;
   9871             }
   9872             for (ci = from_cos; ci <= to_cos; ci++) {
   9873                 if (!IS_CPU_PORT(unit, local_port)) {
   9874                     BCM_IF_ERROR_RETURN
   9875                        (_bcm_mn_cosq_index_resolve
   9876                        (unit, port, ci, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_UCAST,
   9877                         &local_port, &startq, &numq));
   9878                     for (i = 0; i < numq; i++) {
   9879                      /* coverity[NEGATIVE_RETURNS: FALSE] */
   9880                         BCM_IF_ERROR_RETURN
   9881                           (counter_get(unit, local_port,
   9882                                          SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE_UC,
   9883                                          startq + i, &value64));
   9884                         COMPILER_64_ADD_64(sum, value64);
   9885                     }
   9886                 }
   9887                 BCM_IF_ERROR_RETURN
   9888                     (_bcm_mn_cosq_index_resolve
   9889                      (unit, port, ci, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_MCAST,
   9890                       &local_port, &startq, &numq));
   9891                 for (i = 0; i < numq; i++) {
   9892                     BCM_IF_ERROR_RETURN
   9893                         (counter_get(unit, local_port,
   9894                                          SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE,
   9895                                          startq + i, &value64));
   9896                     COMPILER_64_ADD_64(sum, value64);
   9897                 }
   9898             }
   9899             *value = sum;
   9900         }
   9901         break;
   9902     case bcmCosqStatYellowCongestionDroppedPackets:
   9903         if (cosq != BCM_COS_INVALID) {
   9904             return BCM_E_UNAVAIL;
   9905         }
   9906         BCM_IF_ERROR_RETURN
   9907             (_bcm_mn_cosq_localport_resolve(unit, port, &local_port));
   9908         BCM_IF_ERROR_RETURN
   9909             (counter_get(unit, local_port,
   9910                              SOC_COUNTER_NON_DMA_PORT_DROP_PKT_YELLOW, 0,
   9911                              value));
   9912         break;
   9913     case bcmCosqStatRedCongestionDroppedPackets:
   9914         if (cosq != BCM_COS_INVALID) {
   9915             return BCM_E_UNAVAIL;
   9916         }
   9917         BCM_IF_ERROR_RETURN
   9918             (_bcm_mn_cosq_localport_resolve(unit, port, &local_port));
   9919         BCM_IF_ERROR_RETURN
   9920             (counter_get(unit, local_port,
   9921                              SOC_COUNTER_NON_DMA_PORT_DROP_PKT_RED, 0,
   9922                              value));
   9923         break;
   9924     case bcmCosqStatGreenDiscardDroppedPackets:
   9925         if (cosq != BCM_COS_INVALID) {
   9926             return BCM_E_UNAVAIL;
   9927         }
   9928         BCM_IF_ERROR_RETURN
   9929             (_bcm_mn_cosq_localport_resolve(unit, port, &local_port));
   9930         BCM_IF_ERROR_RETURN
   9931             (counter_get(unit, local_port,
   9932                              SOC_COUNTER_NON_DMA_PORT_WRED_PKT_GREEN, 0,
   9933                              value));
   9934         break;
   9935     case bcmCosqStatYellowDiscardDroppedPackets:
   9936         if (cosq != BCM_COS_INVALID) {
   9937             return BCM_E_UNAVAIL;
   9938         }
   9939         BCM_IF_ERROR_RETURN
   9940             (_bcm_mn_cosq_localport_resolve(unit, port, &local_port));
   9941         BCM_IF_ERROR_RETURN
   9942             (counter_get(unit, local_port,
   9943                              SOC_COUNTER_NON_DMA_PORT_WRED_PKT_YELLOW, 0,
   9944                              value));
   9945         break;
   9946     case bcmCosqStatRedDiscardDroppedPackets:
   9947         if (cosq != BCM_COS_INVALID) {
   9948             return BCM_E_UNAVAIL;
   9949         }
   9950         BCM_IF_ERROR_RETURN
   9951             (_bcm_mn_cosq_localport_resolve(unit, port, &local_port));
   9952         BCM_IF_ERROR_RETURN
   9953             (counter_get(unit, local_port,
   9954                              SOC_COUNTER_NON_DMA_PORT_WRED_PKT_RED, 0, value));
   9955         break;
   9956     case bcmCosqStatOutPackets:
   9957         if (BCM_GPORT_IS_SCHEDULER(port)) {
   9958             BCM_IF_ERROR_RETURN
   9959                 (_bcm_mn_cosq_node_get(unit, port, 0, NULL, 
   9960                                         &local_port, NULL, &node));
   9961             if (cosq == BCM_COS_INVALID) {
   9962                  node = node->child;
   9963                  if (node){
   9964                     COMPILER_64_ZERO(value64);
   9965                      BCM_IF_ERROR_RETURN(_bcm_mn_cosq_stat_get(unit, port, 
   9966                                  node, sync_mode, &value64,SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT_UC,
   9967                                  SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT));
   9968                      *value = value64;
   9969                      break; 
   9970                  }
   9971              }
   9972 
   9973 
   9974             BCM_IF_ERROR_RETURN(
   9975                    _bcm_mn_cosq_child_node_at_input(node, cosq, &node));
   9976             port = node->gport;
   9977         }
   9978 
   9979         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) {
   9980             BCM_IF_ERROR_RETURN
   9981                 (_bcm_mn_cosq_node_get(unit, port, 0, NULL, 
   9982                                        &local_port, NULL, &node));
   9983             port_info = &mmu_info->port_info[local_port];
   9984             if (node->hw_index < port_info->uc_base || 
   9985                      node->hw_index >= port_info->uc_limit) {
   9986                 /* coverity[NEGATIVE_RETURNS: FALSE] */
   9987                 BCM_IF_ERROR_RETURN
   9988                     (counter_get(unit, node->hw_index,
   9989                                  SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT, 0,
   9990                                  value));
   9991             } else {
   9992 
   9993                 (_bcm_mn_cosq_index_resolve
   9994                  (unit, port, cosq, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_UCAST,
   9995                   &local_port, &startq, NULL));
   9996                 /* coverity[NEGATIVE_RETURNS: FALSE] */
   9997                 BCM_IF_ERROR_RETURN
   9998                     (counter_get(unit, local_port,
   9999                                  SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT_UC, startq,
  10000                                  value));
  10001             }
  10002         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
  10003             BCM_IF_ERROR_RETURN
  10004                 (_bcm_mn_cosq_index_resolve
  10005                  (unit, port, cosq, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_MCAST,
  10006                   &local_port, &startq, NULL));
  10007             /* coverity[NEGATIVE_RETURNS: FALSE] */
  10008             BCM_IF_ERROR_RETURN
  10009                 (counter_get(unit, local_port,
  10010                                  SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT, startq,
  10011                                  value));
  10012         } else {
  10013             BCM_IF_ERROR_RETURN(_bcm_mn_cosq_localport_resolve(unit, port, &local_port));
  10014             BCM_IF_ERROR_RETURN(_bcm_mn_cosq_port_has_ets(unit, local_port));
  10015             COMPILER_64_ZERO(sum);
  10016             if (cosq == BCM_COS_INVALID) {
  10017                 from_cos = 0;
  10018                 to_cos = (IS_CPU_PORT(unit, local_port)) ? 
  10019                             NUM_CPU_COSQ(unit) - 1 : _MN_NUM_COS(unit) - 1;
  10020             } else {
  10021                 from_cos = to_cos = cosq;
  10022             }
  10023 
  10024             for (ci = from_cos; ci <= to_cos; ci++) {
  10025                 if (!IS_CPU_PORT(unit, local_port)) {
  10026                     BCM_IF_ERROR_RETURN
  10027                         (_bcm_mn_cosq_index_resolve
  10028                             (unit, port, ci, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_UCAST,
  10029                              &local_port, &startq, &numq));
  10030                     for (i = 0; i < numq; i++) {
  10031                         /* coverity[NEGATIVE_RETURNS: FALSE] */
  10032                         BCM_IF_ERROR_RETURN
  10033                             (counter_get(unit, local_port,
  10034                                              SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT_UC,
  10035                                              startq + i, &value64));
  10036                         COMPILER_64_ADD_64(sum, value64);
  10037                     }
  10038                 }
  10039                 BCM_IF_ERROR_RETURN
  10040                     (_bcm_mn_cosq_index_resolve
  10041                      (unit, port, ci, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_MCAST,
  10042                       &local_port, &startq, &numq));
  10043                 for (i = 0; i < numq; i++) {
  10044                     /* coverity[NEGATIVE_RETURNS: FALSE] */
  10045                     BCM_IF_ERROR_RETURN
  10046                         (counter_get(unit, local_port,
  10047                                          SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT,
  10048                                          startq + i, &value64));
  10049                     COMPILER_64_ADD_64(sum, value64);
  10050                 }
  10051             }
  10052             *value = sum;
  10053         }
  10054         break;
  10055     case bcmCosqStatOutBytes:
  10056         if (BCM_GPORT_IS_SCHEDULER(port)) {
  10057             BCM_IF_ERROR_RETURN
  10058                 (_bcm_mn_cosq_node_get(unit, port, 0, NULL, 
  10059                                         &local_port, NULL, &node));
  10060             
  10061             if (cosq == BCM_COS_INVALID) {
  10062                  node = node->child;
  10063                  if (node){
  10064                     COMPILER_64_ZERO(value64);
  10065                      BCM_IF_ERROR_RETURN(_bcm_mn_cosq_stat_get(unit, port, 
  10066                                  node, sync_mode, &value64,SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE_UC,
  10067                                  SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE));
  10068                      *value = value64;
  10069                      break; 
  10070                  }
  10071              }
  10072 
  10073             BCM_IF_ERROR_RETURN(
  10074                    _bcm_mn_cosq_child_node_at_input(node, cosq, &node));
  10075             port = node->gport;
  10076         }
  10077 
  10078         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) {
  10079             BCM_IF_ERROR_RETURN
  10080                 (_bcm_mn_cosq_node_get(unit, port, 0, NULL ,
  10081                                         &local_port, NULL, &node));
  10082             port_info = &mmu_info->port_info[local_port];
  10083             if (node->hw_index < port_info->uc_base ||
  10084                           node->hw_index >= port_info->uc_limit) {
  10085                 BCM_IF_ERROR_RETURN
  10086                 (counter_get(unit, node->hw_index,
  10087                                  SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE, 0,
  10088                                  value));
  10089             } else {
  10090 
  10091             BCM_IF_ERROR_RETURN
  10092                 (_bcm_mn_cosq_index_resolve
  10093                  (unit, port, cosq, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_UCAST,
  10094                   &local_port, &startq, NULL));
  10095             /* coverity[NEGATIVE_RETURNS: FALSE] */
  10096             BCM_IF_ERROR_RETURN
  10097                 (counter_get(unit, local_port,
  10098                                  SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE_UC, startq,
  10099                                  value));
  10100             }
  10101         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
  10102             BCM_IF_ERROR_RETURN
  10103                 (_bcm_mn_cosq_index_resolve
  10104                  (unit, port, cosq, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_MCAST,
  10105                   &local_port, &startq, NULL));
  10106             /* coverity[NEGATIVE_RETURNS: FALSE] */
  10107             BCM_IF_ERROR_RETURN
  10108                 (counter_get(unit, local_port,
  10109                                  SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE, startq,
  10110                                  value));
  10111         } else {
  10112             BCM_IF_ERROR_RETURN(_bcm_mn_cosq_localport_resolve(unit, port, &local_port));
  10113             BCM_IF_ERROR_RETURN(_bcm_mn_cosq_port_has_ets(unit, local_port));
  10114             COMPILER_64_ZERO(sum);
  10115             if (cosq == BCM_COS_INVALID) {
  10116                 from_cos = 0;
  10117                 to_cos = (IS_CPU_PORT(unit, local_port)) ? 
  10118                             NUM_CPU_COSQ(unit) - 1 : _MN_NUM_COS(unit) - 1;
  10119             } else {
  10120                 from_cos = to_cos = cosq;
  10121             }
  10122 
  10123             for (ci = from_cos; ci <= to_cos; ci++) {
  10124                 if (!IS_CPU_PORT(unit, local_port)) {
  10125                     BCM_IF_ERROR_RETURN
  10126                         (_bcm_mn_cosq_index_resolve
  10127                             (unit, port, ci, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_UCAST,
  10128                             &local_port, &startq, &numq));
  10129                     for (i = 0; i < numq; i++) {
  10130                         /* coverity[NEGATIVE_RETURNS: FALSE] */
  10131                         BCM_IF_ERROR_RETURN
  10132                             (counter_get(unit, local_port,
  10133                                              SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE_UC,
  10134                                              startq + i, &value64));
  10135                         COMPILER_64_ADD_64(sum, value64);
  10136                     }
  10137                 }
  10138                 BCM_IF_ERROR_RETURN
  10139                     (_bcm_mn_cosq_index_resolve
  10140                      (unit, port, ci, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_MCAST,
  10141                       &local_port, &startq, &numq));
  10142                 for (i = 0; i < numq; i++) {
  10143                     /* coverity[NEGATIVE_RETURNS: FALSE] */
  10144                     BCM_IF_ERROR_RETURN
  10145                         (counter_get(unit, local_port,
  10146                                          SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE,
  10147                                          startq + i, &value64));
  10148                     COMPILER_64_ADD_64(sum, value64);
  10149                 }
  10150             }
  10151             *value = sum;
  10152         }
  10153         break;
  10154     case bcmCosqStatIeee8021CnCpTransmittedCnms:
  10155         BCM_IF_ERROR_RETURN
  10156             (_bcm_mn_cosq_index_resolve
  10157                 (unit, port, cosq, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_UCAST,
  10158                  &local_port, &startq, NULL));  
  10159         BCM_IF_ERROR_RETURN
  10160             (counter_get(unit, local_port,
  10161                              SOC_COUNTER_NON_DMA_MMU_QCN_CNM, startq, value));
  10162         break;
  10163     case bcmCosqStatIngressPortPoolSharedBytesPeak:
  10164 
  10165         COMPILER_64_ZERO(sum);
  10166         BCM_IF_ERROR_RETURN
  10167             (_bcm_mn_cosq_ingress_sp_get(unit, port, cosq, 
  10168                                     &start_hw_index, &end_hw_index));
  10169 
  10170         BCM_IF_ERROR_RETURN(_bcm_mn_cosq_localport_resolve(unit, port, &local_port));
  10171         for (i = start_hw_index; i <= end_hw_index; i++) {
  10172                         /* coverity[NEGATIVE_RETURNS: FALSE] */
  10173             BCM_IF_ERROR_RETURN
  10174                     (counter_get(unit, local_port,
  10175                                              SOC_COUNTER_NON_DMA_POOL_PEAK,
  10176                                              i, &value64));
  10177             COMPILER_64_ADD_64(sum, value64);
  10178         }
  10179 
  10180         COMPILER_64_UMUL_32(sum, _BCM_MN_BYTES_PER_CELL);
  10181         *value = sum;
  10182         break;
  10183     case bcmCosqStatIngressPortPoolSharedBytesCurrent:
  10184 
  10185         BCM_IF_ERROR_RETURN
  10186             (_bcm_mn_cosq_ingress_sp_get(unit, port, cosq, 
  10187                                     &start_hw_index, &end_hw_index));
  10188         BCM_IF_ERROR_RETURN(_bcm_mn_cosq_localport_resolve(unit, port, &local_port));
  10189 
  10190         COMPILER_64_ZERO(sum);
  10191         for (i = start_hw_index; i <= end_hw_index; i++) {
  10192                         /* coverity[NEGATIVE_RETURNS: FALSE] */
  10193             BCM_IF_ERROR_RETURN
  10194                  (counter_get(unit, local_port,
  10195                                              SOC_COUNTER_NON_DMA_POOL_CURRENT,
  10196                                              i, &value64));
  10197            COMPILER_64_ADD_64(sum, value64);
  10198         }
  10199 
  10200         COMPILER_64_UMUL_32(sum, _BCM_MN_BYTES_PER_CELL);
  10201         *value = sum;
  10202         break;
  10203 
  10204     case bcmCosqStatIngressPortPGMinBytesPeak:
  10205 
  10206         BCM_IF_ERROR_RETURN
  10207             (_bcm_mn_cosq_ingress_pg_get(unit, port, cosq, 
  10208                                     &start_hw_index, &end_hw_index));
  10209         COMPILER_64_ZERO(sum);
  10210         BCM_IF_ERROR_RETURN(_bcm_mn_cosq_localport_resolve(unit, port, &local_port));
  10211 
  10212         for (i = start_hw_index; i <= end_hw_index; i++) {
  10213                         /* coverity[NEGATIVE_RETURNS: FALSE] */
  10214             BCM_IF_ERROR_RETURN
  10215                 (counter_get(unit, local_port,
  10216                                              SOC_COUNTER_NON_DMA_PG_MIN_PEAK,
  10217                                              i, &value64));
  10218             COMPILER_64_ADD_64(sum, value64);
  10219           }
  10220 
  10221         COMPILER_64_UMUL_32(sum, _BCM_MN_BYTES_PER_CELL);
  10222         *value = sum;
  10223         break;
  10224     case bcmCosqStatIngressPortPGMinBytesCurrent:
  10225 
  10226         BCM_IF_ERROR_RETURN
  10227             (_bcm_mn_cosq_ingress_pg_get(unit, port, cosq,
  10228                                     &start_hw_index, &end_hw_index));
  10229         COMPILER_64_ZERO(sum);
  10230         BCM_IF_ERROR_RETURN(_bcm_mn_cosq_localport_resolve(unit, port, &local_port));
  10231 
  10232         for (i = start_hw_index; i <= end_hw_index; i++) {
  10233                         /* coverity[NEGATIVE_RETURNS: FALSE] */
  10234             BCM_IF_ERROR_RETURN
  10235                  (counter_get(unit, local_port,
  10236                                              SOC_COUNTER_NON_DMA_PG_MIN_CURRENT,
  10237                                              i, &value64));
  10238             COMPILER_64_ADD_64(sum, value64);
  10239         }
  10240 
  10241         COMPILER_64_UMUL_32(sum, _BCM_MN_BYTES_PER_CELL);
  10242         *value = sum;
  10243         break;     
  10244 
  10245     case bcmCosqStatIngressPortPGSharedBytesPeak:
  10246 
  10247         BCM_IF_ERROR_RETURN
  10248            (_bcm_mn_cosq_ingress_pg_get(unit, port, cosq,
  10249                                     &start_hw_index, &end_hw_index));
  10250         COMPILER_64_ZERO(sum);
  10251         BCM_IF_ERROR_RETURN(_bcm_mn_cosq_localport_resolve(unit, port, &local_port));
  10252 
  10253         for (i = start_hw_index; i <= end_hw_index; i++) {
  10254                         /* coverity[NEGATIVE_RETURNS: FALSE] */
  10255             BCM_IF_ERROR_RETURN
  10256                 (counter_get(unit, local_port,
  10257                                              SOC_COUNTER_NON_DMA_PG_SHARED_PEAK,
  10258                                              i, &value64));
  10259             COMPILER_64_ADD_64(sum, value64);
  10260         }
  10261 
  10262         COMPILER_64_UMUL_32(sum, _BCM_MN_BYTES_PER_CELL);
  10263         *value = sum;
  10264         break;
  10265 
  10266     case bcmCosqStatIngressPortPGSharedBytesCurrent:
  10267 
  10268         BCM_IF_ERROR_RETURN
  10269             (_bcm_mn_cosq_ingress_pg_get(unit, port, cosq,
  10270                                     &start_hw_index, &end_hw_index));
  10271         BCM_IF_ERROR_RETURN(_bcm_mn_cosq_localport_resolve(unit, port, &local_port));
  10272         COMPILER_64_ZERO(sum);
  10273 
  10274         for (i = start_hw_index; i <= end_hw_index; i++) {
  10275                         /* coverity[NEGATIVE_RETURNS: FALSE] */
  10276             BCM_IF_ERROR_RETURN
  10277                 (counter_get(unit, local_port,
  10278                                           SOC_COUNTER_NON_DMA_PG_SHARED_CURRENT,
  10279                                              i, &value64));
  10280             COMPILER_64_ADD_64(sum, value64);
  10281         }
  10282         COMPILER_64_UMUL_32(sum, _BCM_MN_BYTES_PER_CELL);
  10283         *value = sum;
  10284 
  10285         break;
  10286 
  10287     case bcmCosqStatIngressPortPGHeadroomBytesPeak:
  10288 
  10289         BCM_IF_ERROR_RETURN
  10290                (_bcm_mn_cosq_ingress_pg_get(unit, port, cosq,
  10291                                     &start_hw_index, &end_hw_index));
  10292         BCM_IF_ERROR_RETURN(_bcm_mn_cosq_localport_resolve(unit, port, &local_port));
  10293         COMPILER_64_ZERO(sum);
  10294 
  10295         for (i = start_hw_index; i <= end_hw_index; i++) {
  10296                         /* coverity[NEGATIVE_RETURNS: FALSE] */
  10297             BCM_IF_ERROR_RETURN
  10298                 (counter_get(unit, local_port,
  10299                                        SOC_COUNTER_NON_DMA_PG_HDRM_PEAK,
  10300                                        i, &value64));
  10301             COMPILER_64_ADD_64(sum, value64);
  10302         }
  10303         COMPILER_64_UMUL_32(sum, _BCM_MN_BYTES_PER_CELL);
  10304         *value = sum;
  10305 
  10306         break;
  10307 
  10308     case bcmCosqStatIngressPortPGHeadroomBytesCurrent:
  10309 
  10310         BCM_IF_ERROR_RETURN
  10311             (_bcm_mn_cosq_ingress_pg_get(unit, port, cosq,
  10312                                     &start_hw_index, &end_hw_index));
  10313 
  10314         BCM_IF_ERROR_RETURN(_bcm_mn_cosq_localport_resolve(unit, port, &local_port));
  10315         COMPILER_64_ZERO(sum);
  10316         for (i = start_hw_index; i <= end_hw_index; i++) {
  10317                         /* coverity[NEGATIVE_RETURNS: FALSE] */
  10318             BCM_IF_ERROR_RETURN
  10319                  (counter_get(unit, local_port,
  10320                             SOC_COUNTER_NON_DMA_PG_HDRM_CURRENT,
  10321                                 i, &value64));
  10322             COMPILER_64_ADD_64(sum, value64);
  10323         }
  10324         COMPILER_64_UMUL_32(sum, _BCM_MN_BYTES_PER_CELL);
  10325         *value = sum;
  10326 
  10327         break;
  10328 
  10329     case bcmCosqStatEgressMCQueueBytesPeak:
  10330         if (BCM_GPORT_IS_SCHEDULER(port)) {
  10331             if (cosq == BCM_COS_INVALID ) 
  10332             { 
  10333                  return BCM_E_PARAM; 
  10334             }  
  10335             BCM_IF_ERROR_RETURN
  10336                 (_bcm_mn_cosq_node_get(unit, port, 0, NULL, 
  10337                                         &local_port, NULL, &node));
  10338                    
  10339             BCM_IF_ERROR_RETURN(
  10340              _bcm_mn_cosq_child_node_at_input(node, cosq, &node));
  10341             if (node->level != SOC_MONTEREY_NODE_LVL_L2) {
  10342                 return BCM_E_PARAM;
  10343             }   
  10344             port = node->gport;
  10345         }
  10346 
  10347         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) {
  10348             return BCM_E_PARAM;
  10349         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
  10350             BCM_IF_ERROR_RETURN
  10351                 (_bcm_mn_cosq_index_resolve
  10352                  (unit, port, 0, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_MCAST,
  10353                   &local_port, &startq, NULL));
  10354             /* coverity[NEGATIVE_RETURNS: FALSE] */
  10355             BCM_IF_ERROR_RETURN
  10356                 (counter_get(unit, local_port,
  10357                                  SOC_COUNTER_NON_DMA_QUEUE_PEAK, startq,
  10358                                  value));
  10359             COMPILER_64_UMUL_32(*value, _BCM_MN_BYTES_PER_CELL);
  10360         } else {
  10361             BCM_IF_ERROR_RETURN(_bcm_mn_cosq_localport_resolve(unit, port, &local_port));
  10362             BCM_IF_ERROR_RETURN(_bcm_mn_cosq_port_has_ets(unit, port));
  10363             COMPILER_64_ZERO(sum);
  10364             if (cosq == BCM_COS_INVALID) {
  10365                 from_cos = to_cos = 0;
  10366             } else {
  10367                 from_cos = to_cos = cosq;
  10368             }
  10369 
  10370             for (ci = from_cos; ci <= to_cos; ci++) {
  10371                     BCM_IF_ERROR_RETURN
  10372                         (_bcm_mn_cosq_index_resolve
  10373                             (unit, port, ci, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_MCAST,
  10374                              &local_port, &startq, &numq));
  10375                     for (i = 0; i < numq; i++) {
  10376                         /* coverity[NEGATIVE_RETURNS: FALSE] */
  10377                         BCM_IF_ERROR_RETURN
  10378                             (counter_get(unit, local_port,
  10379                                              SOC_COUNTER_NON_DMA_QUEUE_PEAK,
  10380                                              startq + i, &value64));
  10381                         COMPILER_64_ADD_64(sum, value64);
  10382                     }
  10383             }
  10384             COMPILER_64_UMUL_32(sum, _BCM_MN_BYTES_PER_CELL);
  10385             *value = sum;
  10386         }
  10387         break;
  10388     case bcmCosqStatEgressMCQueueBytesCurrent:
  10389         if (BCM_GPORT_IS_SCHEDULER(port)) {
  10390             BCM_IF_ERROR_RETURN
  10391                 (_bcm_mn_cosq_node_get(unit, port, 0, NULL, 
  10392                                         &local_port, NULL, &node));
  10393            if (cosq == BCM_COS_INVALID) {
  10394                return BCM_E_PARAM;
  10395            }
  10396            BCM_IF_ERROR_RETURN(
  10397                    _bcm_mn_cosq_child_node_at_input(node, cosq, &node));
  10398            if (node->level != SOC_MONTEREY_NODE_LVL_L2) {
  10399                return BCM_E_PARAM;
  10400            }   
  10401            port = node->gport;
  10402         }
  10403 
  10404         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) {
  10405             return BCM_E_PARAM;
  10406         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
  10407             BCM_IF_ERROR_RETURN
  10408                 (_bcm_mn_cosq_index_resolve
  10409                  (unit, port, 0, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_MCAST,
  10410                   &local_port, &startq, NULL));
  10411             /* coverity[NEGATIVE_RETURNS: FALSE] */
  10412             BCM_IF_ERROR_RETURN
  10413                 (counter_get(unit, local_port,
  10414                                  SOC_COUNTER_NON_DMA_QUEUE_CURRENT, startq,
  10415                                  value));
  10416             COMPILER_64_UMUL_32(*value, _BCM_MN_BYTES_PER_CELL);
  10417         } else {
  10418             BCM_IF_ERROR_RETURN(_bcm_mn_cosq_localport_resolve(unit, port, &local_port));
  10419             BCM_IF_ERROR_RETURN(_bcm_mn_cosq_port_has_ets(unit, port));
  10420             COMPILER_64_ZERO(sum);
  10421             if (cosq == BCM_COS_INVALID) {
  10422                 from_cos = 0;
  10423                 to_cos = (IS_CPU_PORT(unit, local_port)) ? 
  10424                             NUM_CPU_COSQ(unit) - 1 : _MN_NUM_COS(unit) - 1;
  10425             } else {
  10426                 from_cos = to_cos = cosq;
  10427             }
  10428 
  10429             for (ci = from_cos; ci <= to_cos; ci++) {
  10430                  BCM_IF_ERROR_RETURN
  10431                     (_bcm_mn_cosq_index_resolve
  10432                         (unit, port, ci, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_MCAST,
  10433                         &local_port, &startq, &numq));
  10434                  for (i = 0; i < numq; i++) {
  10435                         /* coverity[NEGATIVE_RETURNS: FALSE] */
  10436                       BCM_IF_ERROR_RETURN
  10437                         (counter_get(unit, local_port,
  10438                                              SOC_COUNTER_NON_DMA_QUEUE_CURRENT,
  10439                                              startq + i, &value64));
  10440                      COMPILER_64_ADD_64(sum, value64);
  10441                 }
  10442             }
  10443             COMPILER_64_UMUL_32(sum, _BCM_MN_BYTES_PER_CELL);
  10444             *value = sum;
  10445         }
  10446         break;
  10447 
  10448     case bcmCosqStatEgressUCQueueBytesPeak:
  10449         if (BCM_GPORT_IS_SCHEDULER(port)) {
  10450             BCM_IF_ERROR_RETURN
  10451                 (_bcm_mn_cosq_node_get(unit, port, 0, NULL, 
  10452                                         &local_port, NULL, &node));
  10453            if (cosq == BCM_COS_INVALID) {
  10454                return BCM_E_PARAM;
  10455            }
  10456            BCM_IF_ERROR_RETURN(
  10457                   _bcm_mn_cosq_child_node_at_input(node, cosq, &node));
  10458            if (node->level != SOC_MONTEREY_NODE_LVL_L2) {
  10459                return BCM_E_PARAM;
  10460            }   
  10461             port = node->gport;
  10462         }
  10463 
  10464         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) {
  10465             BCM_IF_ERROR_RETURN
  10466                 (_bcm_mn_cosq_index_resolve
  10467                  (unit, port, 0, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_UCAST,
  10468                   &local_port, &startq, NULL));
  10469             /* coverity[NEGATIVE_RETURNS: FALSE] */
  10470             BCM_IF_ERROR_RETURN
  10471                 (counter_get(unit, local_port,
  10472                                  SOC_COUNTER_NON_DMA_UC_QUEUE_PEAK, startq,
  10473                                  value));
  10474             COMPILER_64_UMUL_32(*value, _BCM_MN_BYTES_PER_CELL);
  10475         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
  10476             return BCM_E_PARAM;
  10477         } else {
  10478             BCM_IF_ERROR_RETURN(_bcm_mn_cosq_localport_resolve(unit, port, &local_port));
  10479             BCM_IF_ERROR_RETURN(_bcm_mn_cosq_port_has_ets(unit, port));
  10480             COMPILER_64_ZERO(sum);
  10481             if (cosq == BCM_COS_INVALID) {
  10482                 from_cos = to_cos = 0;
  10483             } else {
  10484                 from_cos = to_cos = cosq;
  10485             }
  10486 
  10487             if (IS_CPU_PORT(unit, local_port)) {
  10488                 return BCM_E_PARAM;
  10489             }
  10490             for (ci = from_cos; ci <= to_cos; ci++) {
  10491                 BCM_IF_ERROR_RETURN
  10492                       (_bcm_mn_cosq_index_resolve
  10493                             (unit, port, ci, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_UCAST,
  10494                              &local_port, &startq, &numq));
  10495                 for (i = 0; i < numq; i++) {
  10496                         /* coverity[NEGATIVE_RETURNS: FALSE] */
  10497                      BCM_IF_ERROR_RETURN
  10498                             (counter_get(unit, local_port,
  10499                                              SOC_COUNTER_NON_DMA_UC_QUEUE_PEAK,
  10500                                              startq + i, &value64));
  10501                      COMPILER_64_ADD_64(sum, value64);
  10502                 }
  10503             }
  10504             COMPILER_64_UMUL_32(sum, _BCM_MN_BYTES_PER_CELL);
  10505             *value = sum;
  10506         }
  10507         break;
  10508     case bcmCosqStatEgressUCQueueBytesCurrent:
  10509         if (BCM_GPORT_IS_SCHEDULER(port)) {
  10510             BCM_IF_ERROR_RETURN
  10511                 (_bcm_mn_cosq_node_get(unit, port, 0, NULL, 
  10512                                        &local_port, NULL, &node));
  10513 
  10514             if (cosq == BCM_COS_INVALID) {
  10515                 return BCM_E_PARAM;
  10516             }
  10517            BCM_IF_ERROR_RETURN(
  10518                     _bcm_mn_cosq_child_node_at_input(node, cosq, &node));
  10519            if (node->level != SOC_MONTEREY_NODE_LVL_L2) {
  10520                return BCM_E_PARAM;
  10521            }   
  10522            port = node->gport;
  10523         }
  10524 
  10525         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) {
  10526             BCM_IF_ERROR_RETURN
  10527                 (_bcm_mn_cosq_index_resolve
  10528                  (unit, port, 0, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_UCAST,
  10529                   &local_port, &startq, NULL));
  10530             /* coverity[NEGATIVE_RETURNS: FALSE] */
  10531             BCM_IF_ERROR_RETURN
  10532                 (counter_get(unit, local_port,
  10533                                  SOC_COUNTER_NON_DMA_UC_QUEUE_CURRENT, startq,
  10534                                  value));
  10535             COMPILER_64_UMUL_32(*value, _BCM_MN_BYTES_PER_CELL);
  10536         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
  10537             return BCM_E_PARAM;
  10538         } else {
  10539             BCM_IF_ERROR_RETURN(_bcm_mn_cosq_localport_resolve(unit, port, &local_port));
  10540             BCM_IF_ERROR_RETURN(_bcm_mn_cosq_port_has_ets(unit, port));
  10541 
  10542             if (IS_CPU_PORT(unit, local_port)) {
  10543                 return BCM_E_PARAM;
  10544             }
  10545             COMPILER_64_ZERO(sum);
  10546             if (cosq == BCM_COS_INVALID) {
  10547                 from_cos = 0;
  10548                 to_cos = (IS_CPU_PORT(unit, local_port)) ? 
  10549                             NUM_CPU_COSQ(unit) - 1 : _MN_NUM_COS(unit) - 1;
  10550             } else {
  10551                 from_cos = to_cos = cosq;
  10552             }
  10553 
  10554             for (ci = from_cos; ci <= to_cos; ci++) {
  10555                 BCM_IF_ERROR_RETURN
  10556                         (_bcm_mn_cosq_index_resolve
  10557                             (unit, port, ci, _BCM_MN_COSQ_INDEX_STYLE_EGR_PERQ_UCAST,
  10558                              &local_port, &startq, &numq));
  10559                 for (i = 0; i < numq; i++) {
  10560                         /* coverity[NEGATIVE_RETURNS: FALSE] */
  10561                     BCM_IF_ERROR_RETURN
  10562                         (counter_get(unit, local_port,
  10563                                              SOC_COUNTER_NON_DMA_UC_QUEUE_CURRENT,
  10564                                              startq + i, &value64));
  10565                     COMPILER_64_ADD_64(sum, value64);
  10566                }
  10567             }
  10568             COMPILER_64_UMUL_32(sum, _BCM_MN_BYTES_PER_CELL);
  10569             *value = sum;
  10570         }
  10571         break;
  10572 
  10573     case bcmCosqStatGlobalHeadroomBytes0Peak:
  10574         BCM_IF_ERROR_RETURN
  10575             (counter_get(unit, -1,
  10576                              SOC_COUNTER_NON_DMA_COSQ_GLOBAL_HDR_COUNT_X_PEAK,
  10577                              0, value));
  10578         COMPILER_64_UMUL_32(*value, _BCM_MN_BYTES_PER_CELL);
  10579         break;
  10580     case bcmCosqStatGlobalHeadroomBytes0Current:
  10581         BCM_IF_ERROR_RETURN
  10582             (counter_get(unit, -1,
  10583                              SOC_COUNTER_NON_DMA_COSQ_GLOBAL_HDR_COUNT_X_CURRENT,
  10584                              0, value));
  10585         COMPILER_64_UMUL_32(*value, _BCM_MN_BYTES_PER_CELL);
  10586         break;
  10587     case bcmCosqStatGlobalHeadroomBytes1Peak:
  10588          BCM_IF_ERROR_RETURN
  10589             (counter_get(unit, -1,
  10590                              SOC_COUNTER_NON_DMA_COSQ_GLOBAL_HDR_COUNT_Y_PEAK,
  10591                             0, value));
  10592         COMPILER_64_UMUL_32(*value, _BCM_MN_BYTES_PER_CELL);
  10593         break;
  10594     case bcmCosqStatGlobalHeadroomBytes1Current:
  10595         BCM_IF_ERROR_RETURN
  10596             (counter_get(unit, -1,
  10597                              SOC_COUNTER_NON_DMA_COSQ_GLOBAL_HDR_COUNT_Y_CURRENT,
  10598                              0, value));
  10599         COMPILER_64_UMUL_32(*value, _BCM_MN_BYTES_PER_CELL);
  10600         break;
  10601     case bcmCosqStatHighPriDroppedPackets:
  10602     case bcmCosqStatOBMLossyHighPriDroppedPackets:
  10603     case bcmCosqStatLowPriDroppedPackets:
  10604     case bcmCosqStatOBMLossyLowPriDroppedPackets:
  10605     case bcmCosqStatHighPriDroppedBytes:
  10606     case bcmCosqStatOBMLossyHighPriDroppedBytes:
  10607     case bcmCosqStatLowPriDroppedBytes:
  10608     case bcmCosqStatOBMLossyLowPriDroppedBytes:
  10609     case bcmCosqStatOBMLossless0DroppedPackets:
  10610     case bcmCosqStatOBMLossless1DroppedPackets:
  10611     case bcmCosqStatOBMLossless0DroppedBytes:
  10612     case bcmCosqStatOBMLossless1DroppedBytes:
  10613     case bcmCosqStatOBMLossless0EnqueuedPackets:
  10614     case bcmCosqStatOBMLossless0EnqueuedBytes:
  10615     case bcmCosqStatOBMLossless1EnqueuedPackets:
  10616     case bcmCosqStatOBMLossless1EnqueuedBytes:
  10617     case bcmCosqStatOBMLossyHighPriEnqueuedPackets:
  10618     case bcmCosqStatOBMLossyHighPriEnqueuedBytes:
  10619     case bcmCosqStatOBMLossyLowPriEnqueuedPackets:
  10620     case bcmCosqStatOBMLossyLowPriEnqueuedBytes:
  10621     case bcmCosqStatOBMExpressEnqueuedPackets:
  10622     case bcmCosqStatOBMExpressEnqueuedBytes:
  10623     case bcmCosqStatOBMExpressDroppedPackets:
  10624     case bcmCosqStatOBMExpressDroppedBytes:
  10625         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
  10626             BCM_GPORT_IS_SCHEDULER(port) ||
  10627             BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
  10628             return BCM_E_PARAM;
  10629         }
  10630         BCM_IF_ERROR_RETURN(
  10631             _bcm_mn_cosq_localport_resolve(unit, port, &local_port));
  10632         if ((stat == bcmCosqStatHighPriDroppedPackets) ||
  10633             (stat == bcmCosqStatOBMLossyHighPriDroppedPackets)) {
  10634             ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM_LOSSY_HI;
  10635         } else if ((stat == bcmCosqStatLowPriDroppedPackets) ||
  10636                    (stat == bcmCosqStatOBMLossyLowPriDroppedPackets)) {
  10637             ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM_LOSSY_LO;
  10638         } else if ((stat == bcmCosqStatHighPriDroppedBytes) ||
  10639                    (stat == bcmCosqStatOBMLossyHighPriDroppedBytes)) {
  10640             ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM_LOSSY_HI;
  10641         } else if ((stat == bcmCosqStatLowPriDroppedBytes) ||
  10642                    (stat == bcmCosqStatOBMLossyLowPriDroppedBytes)) {
  10643             ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM_LOSSY_LO;
  10644         } else if (stat == bcmCosqStatOBMLossless0DroppedPackets) {
  10645             ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM_LOSSLESS0;
  10646         } else if (stat == bcmCosqStatOBMLossless1DroppedPackets) {
  10647             ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM_LOSSLESS1;
  10648         } else if (stat == bcmCosqStatOBMLossless0DroppedBytes) {
  10649             ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM_LOSSLESS0;
  10650         } else if (stat == bcmCosqStatOBMLossless1DroppedBytes) {
  10651             ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM_LOSSLESS1;
  10652         } else if (stat == bcmCosqStatOBMLossless0EnqueuedPackets) {
  10653             ctr_reg = SOC_COUNTER_NON_DMA_PORT_ENQUEUE_PKT_OBM_LOSSLESS0;
  10654         } else if (stat == bcmCosqStatOBMLossless0EnqueuedBytes) {
  10655             ctr_reg = SOC_COUNTER_NON_DMA_PORT_ENQUEUE_BYTE_OBM_LOSSLESS0;
  10656         } else if (stat == bcmCosqStatOBMLossless1EnqueuedPackets) {
  10657             ctr_reg = SOC_COUNTER_NON_DMA_PORT_ENQUEUE_PKT_OBM_LOSSLESS1;
  10658         } else if (stat == bcmCosqStatOBMLossless1EnqueuedBytes) {
  10659             ctr_reg = SOC_COUNTER_NON_DMA_PORT_ENQUEUE_BYTE_OBM_LOSSLESS1;
  10660         } else if (stat == bcmCosqStatOBMLossyHighPriEnqueuedPackets) {
  10661             ctr_reg = SOC_COUNTER_NON_DMA_PORT_ENQUEUE_PKT_OBM_LOSSY_HI;
  10662         } else if (stat == bcmCosqStatOBMLossyHighPriEnqueuedBytes) {
  10663             ctr_reg = SOC_COUNTER_NON_DMA_PORT_ENQUEUE_BYTE_OBM_LOSSY_HI;
  10664         } else if (stat == bcmCosqStatOBMLossyLowPriEnqueuedPackets) {
  10665             ctr_reg = SOC_COUNTER_NON_DMA_PORT_ENQUEUE_PKT_OBM_LOSSY_LO;
  10666         } else if (stat == bcmCosqStatOBMLossyLowPriEnqueuedBytes) {
  10667             ctr_reg = SOC_COUNTER_NON_DMA_PORT_ENQUEUE_BYTE_OBM_LOSSY_LO;
  10668         } else if (stat == bcmCosqStatOBMExpressEnqueuedPackets) {
  10669             ctr_reg = SOC_COUNTER_NON_DMA_PORT_ENQUEUE_PKT_OBM_EXPRESS;
  10670         } else if (stat == bcmCosqStatOBMExpressEnqueuedBytes) {
  10671             ctr_reg = SOC_COUNTER_NON_DMA_PORT_ENQUEUE_BYTE_OBM_EXPRESS;
  10672         } else if (stat == bcmCosqStatOBMExpressDroppedPackets) {
  10673             ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM_EXPRESS;
  10674         } else { /*if (stat == bcmCosqStatOBMExpressDroppedBytes) */
  10675             ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM_EXPRESS;
  10676         }
  10677         ctrl_info.instance_type = SOC_CTR_INSTANCE_TYPE_PORT;
  10678         ctrl_info.instance = local_port;
  10679         BCM_IF_ERROR_RETURN
  10680             (soc_counter_generic_get(unit, ctr_reg, ctrl_info, 0,
  10681                                      0, value));
  10682         break;
  10683     default:
  10684         return BCM_E_PARAM;
  10685     }
  10686 
  10687     return BCM_E_NONE;
  10688 }
  10689 
  10690 /*
  10691  * Function:
  10692  *     _bcm_mn_cosq_quantize_table_set
  10693  * Purpose:
  10694  *     Generate quantized feedback lookup table
  10695  * Parameters:
  10696  *     unit          - (IN) unit number
  10697  *     profile_index - (IN) profile index
  10698  *     weight_code   - (IN) weight encoding
  10699  *     set_point     - (IN) queue size set point
  10700  *     active_offset - (OUT) most significant non-zero bit position
  10701  * Returns:
  10702  *     BCM_E_XXX
  10703  * Notes:
  10704  *     The formular to quantize feedback value is:
  10705  *     quantized_feedbad = celling(feedback / max_feedback * 63)
  10706  *         where max_feedback = (2 * cpW + 1) * cpQsp
  10707  *         cpW is feedback weight
  10708  *         cpQsp is queue size set point
  10709  */
  10710 STATIC int
  10711 _bcm_mn_cosq_quantize_table_set(int unit, int profile_index, int weight_code,
  10712                                 int set_point, int *active_offset)
  10713 {
  10714     int ref_count;
  10715     int weight_x_4, feedback, max_feedback, quantized_feedback, shift;
  10716     int base_index, index;
  10717 
  10718     /* weight = 2 ** (weight_code - 2) e.g. 0 for 1/4, 1 for 1/2, ...  */
  10719     weight_x_4 = 1 << weight_code;
  10720     max_feedback = ((2 * weight_x_4 + 4) * set_point + 3) / 4;
  10721     shift = 0;
  10722     while ((max_feedback >> shift) > 127) {
  10723         shift++;
  10724     }
  10725 
  10726     BCM_IF_ERROR_RETURN
  10727         (soc_profile_reg_ref_count_get(unit, _bcm_mn_feedback_profile[unit],
  10728                                        profile_index, &ref_count));
  10729 
  10730     /*
  10731      * Hardware use lookup table to find quantized feedback in order to avoid
  10732      * division, use most significant 7-bit of feedback value as lookup table
  10733      * index to find quantized_feedback value
  10734      */
  10735     if (ref_count == 1) {
  10736         base_index = profile_index << 7;
  10737         for (index = 0; index < 128; index++) {
  10738             feedback = index << shift;
  10739             if (feedback > max_feedback) {
  10740                 quantized_feedback = 63;
  10741             } else {
  10742                 quantized_feedback = (feedback * 63 + max_feedback - 1) /
  10743                     max_feedback;
  10744             }
  10745             BCM_IF_ERROR_RETURN
  10746                 (soc_mem_field32_modify(unit, MMU_QCN_QFBTBm,
  10747                                         base_index  + index, CPQ_QNTZFBf,
  10748                                         quantized_feedback));
  10749         }
  10750     }
  10751 
  10752     *active_offset = shift + 6;
  10753 
  10754     return BCM_E_NONE;
  10755 }
  10756 
  10757 
  10758 STATIC int
  10759 _bcm_mn_cosq_sample_int_table_set(int unit, int min, int max,
  10760                                   uint32 *profile_index)
  10761 {
  10762     mmu_qcn_sitb_entry_t sitb_entries[64];
  10763     void *entries[1];
  10764     int i, j, center, inc, value, index;
  10765 
  10766     sal_memset(sitb_entries, 0, sizeof(sitb_entries));
  10767     entries[0] = &sitb_entries;
  10768     for (i = 0; i < 8; i++) {
  10769         center = max - (max - min) * i / 7;
  10770         inc = (max - min) / 7 / 8;
  10771         for (j = 0; j < 8; j++, inc = -inc) {
  10772             index = i * 8 + j;
  10773             value = center + (j + 1) / 2 * inc;
  10774             if (value > 255) {
  10775                 value = 255;
  10776             } else if (value < 1) {
  10777                 value = 1;
  10778             }
  10779             soc_mem_field32_set(unit, MMU_QCN_SITBm, &sitb_entries[index],
  10780                                 CPQ_SIf, value);
  10781         }
  10782     }
  10783 
  10784     return soc_profile_mem_add(unit, _bcm_mn_sample_int_profile[unit], entries,
  10785                                64, (uint32 *)profile_index);
  10786 }
  10787 
  10788 /*
  10789  * Function:
  10790  *     bcm_mn_cosq_congestion_queue_set
  10791  * Purpose:
  10792  *     Enable/Disable a cos queue as congestion managed queue
  10793  * Parameters:
  10794  *     unit          - (IN) unit number
  10795  *     port          - (IN) port number or GPORT identifier
  10796  *     cosq          - (IN) COS queue number
  10797  *     index         - (IN) congestion managed queue index
  10798  * Returns:
  10799  *     BCM_E_XXX
  10800  */
  10801 int
  10802 bcm_mn_cosq_congestion_queue_set(int unit, bcm_port_t port,
  10803                                  bcm_cos_queue_t cosq, int index)
  10804 {
  10805     bcm_port_t local_port;
  10806     uint32 rval;
  10807     uint64 rval64, *rval64s[1];
  10808     mmu_qcn_enable_entry_t enable_entry;
  10809     int active_offset, qindex;
  10810     uint32 profile_index, sample_profile_index;
  10811     int weight_code, set_point;
  10812     soc_mem_t mem;
  10813     int maxindex = 0 ;
  10814     if (cosq < 0 || cosq >= _MN_NUM_COS(unit)) {
  10815         return BCM_E_PARAM;
  10816     }
  10817 
  10818     if ((index < -1) || (index >= _BCM_MN_NUM_L2_UC_LEAVES)) {
  10819         return BCM_E_PARAM;
  10820     }
  10821 
  10822     BCM_IF_ERROR_RETURN
  10823         (_bcm_mn_cosq_index_resolve(unit, port, cosq,
  10824                                     _BCM_MN_COSQ_INDEX_STYLE_QCN,
  10825                                     &local_port, &qindex, NULL));
  10826     
  10827     mem = MMU_QCN_ENABLE_0m;
  10828     maxindex =  soc_mem_index_count(unit, mem); 
  10829     if ((qindex < -1) || (qindex >= maxindex)) {
  10830         return BCM_E_PARAM;
  10831     }
  10832 
  10833     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ANY, 
  10834                         qindex, &enable_entry));
  10835     if (index == -1) {
  10836         if (!soc_mem_field32_get(unit, mem, &enable_entry, CPQ_ENf)) {
  10837             return BCM_E_NONE;
  10838         }
  10839 
  10840         index = soc_mem_field32_get(unit, mem, &enable_entry, CPQ_PROFILE_INDEXf);
  10841         soc_mem_field32_set(unit, mem, &enable_entry, CPQ_ENf, 0);
  10842         BCM_IF_ERROR_RETURN
  10843             (soc_mem_write(unit, mem, MEM_BLOCK_ANY, qindex, &enable_entry));
  10844 
  10845         profile_index = soc_mem_field32_get(unit, mem, &enable_entry, EQTB_INDEXf);
  10846 
  10847         BCM_IF_ERROR_RETURN
  10848             (soc_profile_reg_delete(unit, _bcm_mn_feedback_profile[unit],
  10849                                     profile_index));
  10850 
  10851         profile_index =
  10852             soc_mem_field32_get(unit, mem, &enable_entry, SITB_SELf);
  10853 
  10854         BCM_IF_ERROR_RETURN
  10855             (soc_profile_mem_delete(unit, _bcm_mn_sample_int_profile[unit],
  10856                                 profile_index * 64));
  10857     } else {
  10858         if (soc_mem_field32_get(unit, mem, &enable_entry, CPQ_ENf)) {
  10859             return BCM_E_BUSY;
  10860         }
  10861 
  10862         /* Use hardware reset value as default quantize setting */
  10863         weight_code = 3;
  10864         set_point = 0x96;
  10865         rval = 0;
  10866         soc_reg_field_set(unit, MMU_QCN_CPQ_SEQr, &rval, CPWf, weight_code);
  10867         soc_reg_field_set(unit, MMU_QCN_CPQ_SEQr, &rval, CPQEQf, set_point);
  10868         COMPILER_64_SET(rval64, 0, rval);
  10869         rval64s[0] = &rval64;
  10870         BCM_IF_ERROR_RETURN
  10871             (soc_profile_reg_add(unit, _bcm_mn_feedback_profile[unit],
  10872                                  rval64s, 1, (uint32 *)&profile_index));
  10873 
  10874         /* Update quantized feedback calculation lookup table */
  10875         BCM_IF_ERROR_RETURN
  10876             (_bcm_mn_cosq_quantize_table_set(unit, profile_index, weight_code,
  10877                                              set_point, &active_offset));
  10878 
  10879         /* Pick some sample interval */
  10880         BCM_IF_ERROR_RETURN
  10881             (_bcm_mn_cosq_sample_int_table_set(unit, 13, 127,
  10882                                                &sample_profile_index));
  10883 
  10884         soc_mem_field32_set(unit, mem, &enable_entry,
  10885                             QNTZ_ACT_OFFSETf, active_offset);
  10886 
  10887         soc_mem_field32_set(unit, mem, &enable_entry,
  10888                             SITB_SELf, sample_profile_index/64);
  10889 
  10890         soc_mem_field32_set(unit, mem, &enable_entry, EQTB_INDEXf, 
  10891                             profile_index);
  10892 
  10893         soc_mem_field32_set(unit, mem, &enable_entry, CPQ_IDf, index);
  10894 
  10895         soc_mem_field32_set(unit, mem, &enable_entry, CPQ_ENf, 1);
  10896 
  10897         BCM_IF_ERROR_RETURN
  10898             (soc_mem_write(unit, mem, MEM_BLOCK_ANY, qindex, &enable_entry));
  10899     }
  10900 
  10901     return BCM_E_NONE;
  10902 }
  10903 
  10904 /*
  10905  * Function:
  10906  *     bcm_mn_cosq_congestion_queue_get
  10907  * Purpose:
  10908  *     Get congestion managed queue index of the specified cos queue
  10909  * Parameters:
  10910  *     unit          - (IN) unit number
  10911  *     port          - (IN) port number or GPORT identifier
  10912  *     cosq          - (IN) COS queue number
  10913  *     index         - (OUT) congestion managed queue index
  10914  * Returns:
  10915  *     BCM_E_XXX
  10916  */
  10917 int
  10918 bcm_mn_cosq_congestion_queue_get(int unit, bcm_port_t port,
  10919                                  bcm_cos_queue_t cosq, int *index)
  10920 {
  10921     bcm_port_t local_port;
  10922     int qindex;
  10923     mmu_qcn_enable_entry_t entry;
  10924     soc_mem_t mem;
  10925     int maxindex = 0;
  10926     if (cosq < 0 || cosq >= _MN_NUM_COS(unit)) {
  10927         return BCM_E_PARAM;
  10928     }
  10929     
  10930     if (index == NULL) {
  10931         return BCM_E_PARAM;
  10932     }
  10933 
  10934     BCM_IF_ERROR_RETURN
  10935         (_bcm_mn_cosq_index_resolve(unit, port, cosq,
  10936                                     _BCM_MN_COSQ_INDEX_STYLE_QCN,
  10937                                     &local_port, &qindex, NULL));
  10938 
  10939     mem = MMU_QCN_ENABLE_0m;
  10940     maxindex =  soc_mem_index_count(unit, mem); 
  10941     if ((qindex < -1) || (qindex >= maxindex)) {
  10942         return BCM_E_PARAM;
  10943     }
  10944 
  10945     BCM_IF_ERROR_RETURN
  10946         (soc_mem_read(unit, mem, MEM_BLOCK_ANY, qindex, &entry));
  10947     if (soc_mem_field32_get(unit, mem, &entry, CPQ_ENf)) {
  10948         *index = soc_mem_field32_get(unit, mem, &entry, CPQ_IDf);
  10949     } else {
  10950         *index = -1;
  10951     }
  10952 
  10953     return BCM_E_NONE;
  10954 }
  10955 
  10956 /*
  10957  * Function:
  10958  *     bcm_mn_cosq_congestion_quantize_set
  10959  * Purpose:
  10960  *     Set quantized congestion feedback algorithm parameters
  10961  * Parameters:
  10962  *     unit          - (IN) unit number
  10963  *     port          - (IN) port number or GPORT identifier
  10964  *     cosq          - (IN) COS queue number
  10965  *     weight_code   - (IN) weight encoding (use -1 for unchange)
  10966  *     set_point     - (IN) queue size set point (use -1 for unchange)
  10967  * Returns:
  10968  *     BCM_E_XXX
  10969  */
  10970 int
  10971 bcm_mn_cosq_congestion_quantize_set(int unit, bcm_port_t port,
  10972                                     bcm_cos_queue_t cosq, int weight_code,
  10973                                     int set_point)
  10974 {
  10975     bcm_port_t local_port;
  10976     uint32 rval;
  10977     uint64 rval64, *rval64s[1];
  10978     mmu_qcn_enable_entry_t enable_entry;
  10979     int cpq_index, active_offset, qindex;
  10980     uint32 profile_index, old_profile_index;
  10981     soc_mem_t mem;
  10982     int maxindex = 0;
  10983     if (cosq < 0 || cosq >= _MN_NUM_COS(unit)) {
  10984         return BCM_E_PARAM;
  10985     }
  10986 
  10987     
  10988     mem = MMU_QCN_ENABLE_0m;
  10989 
  10990     BCM_IF_ERROR_RETURN
  10991         (bcm_mn_cosq_congestion_queue_get(unit, port, cosq, &cpq_index));
  10992     if (cpq_index == -1) {
  10993         /* The cosq specified is not enabled as congestion managed queue */
  10994         return BCM_E_PARAM;
  10995     }
  10996 
  10997     BCM_IF_ERROR_RETURN
  10998         (_bcm_mn_cosq_index_resolve(unit, port, cosq, 
  10999                 _BCM_MN_COSQ_INDEX_STYLE_QCN, &local_port, &qindex, NULL));
  11000 
  11001     maxindex =  soc_mem_index_count(unit, mem); 
  11002     if ((qindex < -1) || (qindex >= maxindex)) {
  11003         return BCM_E_PARAM;
  11004     }
  11005     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ANY, qindex, &enable_entry));
  11006     old_profile_index =
  11007         soc_mem_field32_get(unit, mem, &enable_entry, EQTB_INDEXf);
  11008 
  11009     BCM_IF_ERROR_RETURN(READ_MMU_QCN_CPQ_SEQr(unit, old_profile_index, &rval));
  11010     if (weight_code == -1) {
  11011         weight_code = soc_reg_field_get(unit, MMU_QCN_CPQ_SEQr, rval, CPWf);
  11012     } else {
  11013         if (weight_code < 0 || weight_code > 7) {
  11014             return BCM_E_PARAM;
  11015         }
  11016         soc_reg_field_set(unit, MMU_QCN_CPQ_SEQr, &rval, CPWf, weight_code);
  11017     }
  11018     if (set_point == -1) {
  11019         set_point = soc_reg_field_get(unit, MMU_QCN_CPQ_SEQr, rval, CPQEQf);
  11020     } else {
  11021         if (set_point < 0 || set_point > 0xffff) {
  11022             return BCM_E_PARAM;
  11023         }
  11024         soc_reg_field_set(unit, MMU_QCN_CPQ_SEQr, &rval, CPQEQf, set_point);
  11025     }
  11026     COMPILER_64_SET(rval64, 0, rval);
  11027     rval64s[0] = &rval64;
  11028     /* Add new feedback parameter profile */
  11029     BCM_IF_ERROR_RETURN
  11030         (soc_profile_reg_add(unit, _bcm_mn_feedback_profile[unit], rval64s,
  11031                              1, (uint32 *)&profile_index));
  11032     /* Delete original feedback parameter profile */
  11033     BCM_IF_ERROR_RETURN
  11034         (soc_profile_reg_delete(unit, _bcm_mn_feedback_profile[unit],
  11035                                 old_profile_index));
  11036 
  11037     /* Update quantized feedback calculation lookup table */
  11038     BCM_IF_ERROR_RETURN
  11039         (_bcm_mn_cosq_quantize_table_set(unit, profile_index, weight_code,
  11040                                          set_point, &active_offset));
  11041 
  11042     soc_mem_field32_set(unit, mem, &enable_entry,
  11043                             QNTZ_ACT_OFFSETf, active_offset);
  11044     soc_mem_field32_set(unit, mem, &enable_entry,
  11045                             EQTB_INDEXf, profile_index);
  11046     BCM_IF_ERROR_RETURN
  11047             (soc_mem_write(unit, mem, MEM_BLOCK_ANY, qindex,
  11048                            &enable_entry));
  11049 
  11050     return BCM_E_NONE;
  11051 }
  11052 
  11053 /*
  11054  * Function:
  11055  *     bcm_mn_cosq_congestion_quantize_get
  11056  * Purpose:
  11057  *     Get quantized congestion feedback algorithm parameters
  11058  * Parameters:
  11059  *     unit          - (IN) unit number
  11060  *     port          - (IN) port number or GPORT identifier
  11061  *     cosq          - (IN) COS queue number
  11062  *     weight_code   - (OUT) weight encoding
  11063  *     set_point     - (OUT) queue size set point
  11064  * Returns:
  11065  *     BCM_E_XXX
  11066  */
  11067 int
  11068 bcm_mn_cosq_congestion_quantize_get(int unit, bcm_port_t port,
  11069                                     bcm_cos_queue_t cosq, int *weight_code,
  11070                                     int *set_point)
  11071 {
  11072     bcm_port_t local_port;
  11073     int cpq_index, profile_index, qindex;
  11074     uint32 rval;
  11075     mmu_qcn_enable_entry_t enable_entry;
  11076     soc_mem_t mem;
  11077     int maxindex = 0;
  11078 
  11079     BCM_IF_ERROR_RETURN
  11080         (bcm_mn_cosq_congestion_queue_get(unit, port, cosq, &cpq_index));
  11081     if (cpq_index == -1) {
  11082         /* The cosq specified is not enabled as congestion managed queue */
  11083         return BCM_E_PARAM;
  11084     }
  11085 
  11086     BCM_IF_ERROR_RETURN
  11087         (_bcm_mn_cosq_index_resolve(unit, port, cosq,
  11088                                     _BCM_MN_COSQ_INDEX_STYLE_QCN,
  11089                                     &local_port, &qindex, NULL));
  11090     
  11091     mem = MMU_QCN_ENABLE_0m;
  11092     maxindex =  soc_mem_index_count(unit, mem); 
  11093     if ((qindex < -1) || (qindex >= maxindex)) {
  11094         return BCM_E_PARAM;
  11095     }
  11096 
  11097     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem,
  11098                                      MEM_BLOCK_ANY, qindex, &enable_entry));
  11099     profile_index =
  11100         soc_mem_field32_get(unit, mem, &enable_entry, EQTB_INDEXf);
  11101 
  11102     BCM_IF_ERROR_RETURN(READ_MMU_QCN_CPQ_SEQr(unit, profile_index, &rval));
  11103     if (weight_code != NULL) {
  11104         *weight_code = soc_reg_field_get(unit, MMU_QCN_CPQ_SEQr, rval, CPWf);
  11105     }
  11106     if (set_point != NULL) {
  11107         *set_point = soc_reg_field_get(unit, MMU_QCN_CPQ_SEQr, rval, CPQEQf);
  11108     }
  11109 
  11110     return BCM_E_NONE;
  11111 }
  11112 
  11113 int
  11114 bcm_mn_cosq_congestion_sample_int_set(int unit, bcm_port_t port,
  11115                                       bcm_cos_queue_t cosq, int min, int max)
  11116 {
  11117     bcm_port_t local_port;
  11118     mmu_qcn_enable_entry_t entry;
  11119     mmu_qcn_sitb_entry_t sitb_entry;
  11120     int qindex;
  11121     uint32 profile_index, old_profile_index;
  11122     soc_mem_t mem;
  11123     int maxindex  = 0;
  11124     BCM_IF_ERROR_RETURN
  11125         (_bcm_mn_cosq_index_resolve(unit, port, cosq,
  11126                                     _BCM_MN_COSQ_INDEX_STYLE_QCN,
  11127                                     &local_port, &qindex, NULL));
  11128 
  11129     mem = MMU_QCN_ENABLE_0m;
  11130     maxindex =  soc_mem_index_count(unit, mem); 
  11131     if ((qindex < -1) || (qindex >= maxindex)) {
  11132         return BCM_E_PARAM;
  11133     }
  11134 
  11135 
  11136     BCM_IF_ERROR_RETURN
  11137         (soc_mem_read(unit, mem, MEM_BLOCK_ANY, qindex, &entry));
  11138 
  11139     if (!soc_mem_field32_get(unit, mem, &entry, CPQ_ENf)) {
  11140         return BCM_E_PARAM;
  11141     }
  11142 
  11143     old_profile_index =
  11144         soc_mem_field32_get(unit, mem, &entry, SITB_SELf);
  11145 
  11146     if (max == -1) {
  11147         BCM_IF_ERROR_RETURN(soc_mem_read(unit, MMU_QCN_SITBm, MEM_BLOCK_ANY,
  11148                                          old_profile_index * 64, &sitb_entry));
  11149         max = soc_mem_field32_get(unit, MMU_QCN_SITBm, &sitb_entry, CPQ_SIf);
  11150     } else {
  11151         if (max < 1 || max > 255) {
  11152             return BCM_E_PARAM;
  11153         }
  11154     }
  11155     if (min == -1) {
  11156         BCM_IF_ERROR_RETURN(soc_mem_read(unit, MMU_QCN_SITBm, MEM_BLOCK_ANY,
  11157                                          old_profile_index * 64 + 63,
  11158                                          &sitb_entry));
  11159         min = soc_mem_field32_get(unit, MMU_QCN_SITBm, &sitb_entry, CPQ_SIf);
  11160     } else {
  11161         if (min < 1 || min > 255) {
  11162             return BCM_E_PARAM;
  11163         }
  11164     }
  11165 
  11166     /* Add new sample interval profile */
  11167     BCM_IF_ERROR_RETURN
  11168         (_bcm_mn_cosq_sample_int_table_set(unit, min, max, &profile_index));
  11169 
  11170     /* Delete original sample interval profile */
  11171     BCM_IF_ERROR_RETURN
  11172         (soc_profile_mem_delete(unit, _bcm_mn_sample_int_profile[unit],
  11173                                 old_profile_index * 64));
  11174 
  11175     soc_mem_field32_set(unit, mem, &entry, SITB_SELf, 
  11176                         profile_index / 64);
  11177     BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ANY,
  11178                                       qindex, &entry));
  11179     return BCM_E_NONE;
  11180 }
  11181 
  11182 int
  11183 bcm_mn_cosq_congestion_sample_int_get(int unit, bcm_port_t port,
  11184                                       bcm_cos_queue_t cosq, int *min, int *max)
  11185 {
  11186     bcm_port_t local_port;
  11187     mmu_qcn_enable_entry_t entry;
  11188     mmu_qcn_sitb_entry_t sitb_entry;
  11189     int qindex;
  11190     uint32 old_profile_index;
  11191     soc_mem_t mem;
  11192     int maxindex = 0 ; 
  11193 
  11194     BCM_IF_ERROR_RETURN
  11195         (_bcm_mn_cosq_index_resolve(unit, port, cosq,
  11196                                     _BCM_MN_COSQ_INDEX_STYLE_QCN,
  11197                                     &local_port, &qindex, NULL));
  11198     
  11199     mem = MMU_QCN_ENABLE_0m;
  11200     maxindex =  soc_mem_index_count(unit, mem); 
  11201     if ((qindex < -1) || (qindex >= maxindex)) {
  11202         return BCM_E_PARAM;
  11203     }
  11204     
  11205     BCM_IF_ERROR_RETURN
  11206         (soc_mem_read(unit, mem, MEM_BLOCK_ANY, qindex, &entry));
  11207 
  11208     if (!soc_mem_field32_get(unit, mem, &entry, CPQ_ENf)) {
  11209         return BCM_E_PARAM;
  11210     }
  11211 
  11212     old_profile_index =
  11213     soc_mem_field32_get(unit, mem, &entry, SITB_SELf);
  11214 
  11215     if (max) {
  11216         BCM_IF_ERROR_RETURN(soc_mem_read(unit, MMU_QCN_SITBm, MEM_BLOCK_ANY,
  11217                                      old_profile_index * 64, &sitb_entry));
  11218         *max = soc_mem_field32_get(unit, MMU_QCN_SITBm, &sitb_entry, CPQ_SIf);
  11219     }
  11220 
  11221     if (min) {
  11222         BCM_IF_ERROR_RETURN(soc_mem_read(unit, MMU_QCN_SITBm, MEM_BLOCK_ANY,
  11223                                      old_profile_index * 64 + 63,
  11224                                      &sitb_entry));
  11225         *min = soc_mem_field32_get(unit, MMU_QCN_SITBm, &sitb_entry, CPQ_SIf);
  11226     }
  11227 
  11228     return BCM_E_NONE;
  11229 }
  11230 
  11231 STATIC int
  11232 _bcm_mn_cosq_ing_pool_set(int unit, bcm_gport_t gport, bcm_cos_queue_t pri_grp,
  11233         bcm_cosq_control_t type, int arg)
  11234 {
  11235     int local_port;
  11236     uint32 rval;
  11237     static const soc_field_t prigroup_spid_field[] = {
  11238         PG0_SPIDf, PG1_SPIDf, PG2_SPIDf, PG3_SPIDf,
  11239         PG4_SPIDf, PG5_SPIDf, PG6_SPIDf, PG7_SPIDf
  11240     };
  11241     if(( arg < 0 ) || (arg > 3 )) {
  11242             return BCM_E_PARAM;
  11243     }
  11244       
  11245     BCM_IF_ERROR_RETURN
  11246             (_bcm_mn_cosq_localport_resolve(unit, gport, &local_port));
  11247 
  11248     if (!SOC_PORT_VALID(unit, local_port)) {
  11249         return BCM_E_PORT;
  11250     }
  11251 
  11252     if ((pri_grp < 0) || (pri_grp >= 8)) {
  11253         return BCM_E_PARAM;
  11254     }
  11255 
  11256     SOC_IF_ERROR_RETURN(READ_THDI_PORT_PG_SPIDr(unit, local_port, &rval));
  11257     soc_reg_field_set(unit, THDI_PORT_PG_SPIDr, &rval, 
  11258                                 prigroup_spid_field[pri_grp],arg);
  11259     BCM_IF_ERROR_RETURN(WRITE_THDI_PORT_PG_SPIDr(unit, local_port, rval));
  11260     return BCM_E_NONE;
  11261 }
  11262 
  11263 STATIC int
  11264 _bcm_mn_cosq_ing_pool_get(int unit, bcm_gport_t gport,
  11265         bcm_cos_queue_t pri_grp,
  11266         bcm_cosq_control_t type, int *arg)
  11267 {
  11268     int pool_start_idx = 0, pool_end_idx =0;
  11269     BCM_IF_ERROR_RETURN(
  11270             _bcm_mn_cosq_ingress_sp_get(
  11271                 unit, gport, pri_grp, &pool_start_idx, &pool_end_idx));
  11272     *arg = pool_start_idx;
  11273     return BCM_E_NONE;
  11274 }
  11275 
  11276  /*
  11277  * Function:
  11278  *     _bcm_mn_cosq_port_qnum_get
  11279  * Purpose:
  11280  *     Get the hw queue number used to tx packets on respective Queue
  11281  * Parameters:
  11282  *     unit          - (IN) unit number
  11283  *     port          - (IN) port number or GPORT identifier
  11284  *     cosq          - (IN) COS queue number
  11285  *     type          - (IN) unicast/multicast queue indicator
  11286  *     arg           - (out) hw queue number
  11287  * Returns:
  11288  *     BCM_E_XXX
  11289  */
  11290 STATIC int
  11291 _bcm_mn_cosq_port_qnum_get(int unit, bcm_gport_t gport,
  11292         bcm_cos_queue_t cosq, bcm_cosq_control_t type, int *arg)
  11293 {
  11294     bcm_port_t local_port;
  11295     int hw_index;
  11296     int uc;
  11297     int qnum;
  11298     int id, startq, numq;
  11299     _bcm_mn_cosq_node_t *node;
  11300     soc_info_t *si = &SOC_INFO(unit);
  11301 
  11302     if (!arg) {
  11303         return BCM_E_PARAM;
  11304     }
  11305 
  11306     if (cosq <= -1) {
  11307         return BCM_E_PARAM;
  11308     } else {
  11309         startq = cosq;
  11310         numq = 1;
  11311     }
  11312 
  11313     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
  11314         BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  11315         BCM_IF_ERROR_RETURN
  11316             (_bcm_mn_cosq_node_get(unit, gport, cosq, NULL, &local_port, &id,
  11317                                    &node));
  11318         if (node->attached_to_input < 0) { /* Not resolved yet */
  11319             return BCM_E_NOT_FOUND;
  11320         }
  11321 
  11322         startq = 0;
  11323     } else {
  11324         /* optionally validate port */
  11325         BCM_IF_ERROR_RETURN
  11326             (_bcm_mn_cosq_localport_resolve(unit, gport, &local_port));
  11327         if (local_port < 0) {
  11328             return BCM_E_PORT;
  11329         }
  11330         node = NULL;
  11331         numq = (IS_CPU_PORT(unit, local_port)) ?
  11332                                 NUM_CPU_COSQ(unit) : NUM_COS(unit);
  11333     }
  11334 
  11335     if (startq >= numq) {
  11336         return BCM_E_PARAM;
  11337     }
  11338 
  11339     uc =(type == bcmCosqControlPortQueueUcast) ? 1 : 0;
  11340 
  11341     if (node) {
  11342         hw_index = node->hw_index;
  11343     } else {
  11344         hw_index = soc_monterey_l2_hw_index(unit,
  11345             si->port_uc_cosq_base[local_port] + startq, uc);
  11346     }
  11347 
  11348     qnum = soc_monterey_hw_index_logical_num(unit,local_port,hw_index,uc);
  11349     *arg = soc_monterey_logical_qnum_hw_qnum(unit,local_port,qnum,uc);
  11350 
  11351     return BCM_E_NONE;
  11352 }
  11353 
  11354 STATIC int
  11355 _bcm_mn_cosq_egr_pool_set(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
  11356                           bcm_cosq_control_t type, int arg)
  11357 {
  11358     bcm_port_t local_port;
  11359     int startq, pool, midx;
  11360     uint32 max_val;
  11361     uint32 entry[SOC_MAX_MEM_WORDS];
  11362     uint32 entry2[SOC_MAX_MEM_WORDS];
  11363     soc_mem_t mem = INVALIDm, mem2 = INVALIDm;
  11364     soc_field_t fld_limit = INVALIDf;
  11365     int granularity = 1;
  11366 
  11367     if ((arg < 0) || (cosq < 0)) {
  11368         return BCM_E_PARAM;
  11369     }
  11370 
  11371     BCM_IF_ERROR_RETURN
  11372         (_bcm_mn_cosq_index_resolve(unit, gport, cosq,
  11373                                     _BCM_MN_COSQ_INDEX_STYLE_EGR_POOL,
  11374                                     &local_port, &pool, NULL));
  11375 
  11376     mem = MMU_THDM_DB_PORTSP_CONFIG_0m;
  11377 
  11378     if (type == bcmCosqControlEgressPoolLimitEnable) {
  11379         midx = SOC_MONTEREY_MMU_PIPED_MEM_INDEX(unit, local_port, mem, pool);
  11380         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL,
  11381                             midx, entry));
  11382 
  11383         soc_mem_field32_set(unit, mem, entry, SHARED_LIMIT_ENABLEf, !!arg);
  11384 
  11385         return soc_mem_write(unit, mem, MEM_BLOCK_ALL, midx, entry);
  11386     }
  11387     if((type == bcmCosqControlEgressPool) || (type == bcmCosqControlUCEgressPool) ||
  11388         (type == bcmCosqControlMCEgressPool)) {
  11389         if(( arg < 0 ) || (arg > 3 )) {
  11390             return BCM_E_PARAM;
  11391         }
  11392         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  11393             if (type != bcmCosqControlEgressPool) {
  11394                 return BCM_E_PARAM;
  11395             }
  11396             /* regular unicast queue */
  11397             BCM_IF_ERROR_RETURN
  11398                 (_bcm_mn_cosq_index_resolve(unit, gport, cosq,
  11399                                              _BCM_MN_COSQ_INDEX_STYLE_UCAST_QUEUE,
  11400                                              &local_port, &startq, NULL));
  11401             mem = MMU_THDU_XPIPE_Q_TO_QGRP_MAPm;
  11402         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  11403             if (type != bcmCosqControlEgressPool) {
  11404                 return BCM_E_PARAM;
  11405             }
  11406             BCM_IF_ERROR_RETURN
  11407                 (_bcm_mn_cosq_index_resolve(unit, gport, cosq,
  11408                                              _BCM_MN_COSQ_INDEX_STYLE_MCAST_QUEUE,
  11409                                              &local_port, &startq, NULL));
  11410             startq -= _BCM_MN_NUM_L2_UC_LEAVES; /* MC queues comes after UC queues */
  11411             mem =  MMU_THDM_MCQE_QUEUE_CONFIG_0m;
  11412             mem2 = MMU_THDM_DB_QUEUE_CONFIG_0m;
  11413         } else  {
  11414             if (type == bcmCosqControlUCEgressPool) {
  11415                 BCM_IF_ERROR_RETURN
  11416                     (_bcm_mn_cosq_index_resolve(unit, gport, cosq,
  11417                                              _BCM_MN_COSQ_INDEX_STYLE_UCAST_QUEUE,
  11418                                              &local_port, &startq, NULL));
  11419                 mem = MMU_THDU_XPIPE_Q_TO_QGRP_MAPm;
  11420             } else {
  11421                 BCM_IF_ERROR_RETURN
  11422                     (_bcm_mn_cosq_index_resolve(unit, gport, cosq,
  11423                                              _BCM_MN_COSQ_INDEX_STYLE_MCAST_QUEUE,
  11424                                              &local_port, &startq, NULL));
  11425                 startq -= _BCM_MN_NUM_L2_UC_LEAVES_PER_PIPE;
  11426                  /* MC queues comes after UC queues */
  11427                 mem = MMU_THDM_MCQE_QUEUE_CONFIG_0m;
  11428                 mem2 = MMU_THDM_DB_QUEUE_CONFIG_0m;
  11429             }
  11430        } 
  11431 
  11432         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  11433         soc_mem_field32_set(unit, mem, entry, Q_SPIDf, arg);
  11434 
  11435         BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry));
  11436         if (mem2 != INVALIDm) {
  11437             BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem2, MEM_BLOCK_ALL, startq, entry2));
  11438             soc_mem_field32_set(unit, mem2, entry2, Q_SPIDf, arg);
  11439             BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem2, MEM_BLOCK_ALL, startq, entry2));
  11440         }
  11441         return BCM_E_NONE;
  11442     }
  11443 
  11444     arg = arg / _BCM_MN_BYTES_PER_CELL;
  11445 
  11446     /* per service pool settings */
  11447     if (type == bcmCosqControlEgressPoolSharedLimitBytes || 
  11448         type == bcmCosqControlEgressPoolResumeLimitBytes ||
  11449         type == bcmCosqControlEgressPoolYellowSharedLimitBytes || 
  11450         type == bcmCosqControlEgressPoolYellowResumeLimitBytes ||
  11451         type == bcmCosqControlEgressPoolRedSharedLimitBytes ||
  11452         type == bcmCosqControlEgressPoolRedResumeLimitBytes) {
  11453         uint32 rval;
  11454         soc_reg_t reg;
  11455         switch (type) {
  11456         case bcmCosqControlEgressPoolSharedLimitBytes:
  11457             reg = MMU_THDM_DB_POOL_SHARED_LIMITr;    
  11458             fld_limit = SHARED_LIMITf;
  11459             granularity = 1;
  11460             break;
  11461         case bcmCosqControlEgressPoolResumeLimitBytes:
  11462             reg = MMU_THDM_DB_POOL_RESUME_LIMITr;    
  11463             fld_limit = RESUME_LIMITf;
  11464             granularity = 8;
  11465             break;
  11466         case bcmCosqControlEgressPoolYellowSharedLimitBytes:
  11467             reg = MMU_THDM_DB_POOL_YELLOW_SHARED_LIMITr;    
  11468             fld_limit = YELLOW_SHARED_LIMITf;
  11469             granularity = 8;
  11470             break;
  11471         case bcmCosqControlEgressPoolYellowResumeLimitBytes:
  11472             reg = MMU_THDM_DB_POOL_YELLOW_RESUME_LIMITr;    
  11473             fld_limit = YELLOW_RESUME_LIMITf;
  11474             granularity = 8;
  11475             break;
  11476         case bcmCosqControlEgressPoolRedSharedLimitBytes:
  11477             reg = MMU_THDM_DB_POOL_RED_SHARED_LIMITr;    
  11478             fld_limit = RED_SHARED_LIMITf;
  11479             granularity = 8;
  11480             break;
  11481         case bcmCosqControlEgressPoolRedResumeLimitBytes:
  11482             reg = MMU_THDM_DB_POOL_RED_RESUME_LIMITr;    
  11483             fld_limit = RED_RESUME_LIMITf;
  11484             granularity = 8;
  11485             break;
  11486         /* coverity[dead_error_begin : FALSE] */
  11487         default:
  11488             return BCM_E_UNAVAIL;
  11489         }
  11490         
  11491         BCM_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, pool, &rval));
  11492         
  11493         /* Check for min/max values */
  11494         max_val = (1 << soc_reg_field_length(unit, reg, fld_limit)) - 1;
  11495         if ((arg < 0) || ((arg/granularity) > max_val)) {
  11496             return BCM_E_PARAM;
  11497         } else {
  11498             soc_reg_field_set(unit, reg, &rval, fld_limit, (arg/granularity));
  11499         }
  11500         
  11501         BCM_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, pool, rval));
  11502 
  11503         return BCM_E_NONE;
  11504     }
  11505 
  11506     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  11507         BCM_IF_ERROR_RETURN
  11508             (_bcm_mn_cosq_index_resolve(unit, gport, cosq,
  11509                                          _BCM_MN_COSQ_INDEX_STYLE_UCAST_QUEUE,
  11510                                          &local_port, &startq, NULL));
  11511         mem = MMU_THDU_XPIPE_CONFIG_QUEUEm;
  11512         mem2 = MMU_THDU_XPIPE_Q_TO_QGRP_MAPm;
  11513 
  11514     } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  11515         BCM_IF_ERROR_RETURN
  11516             (_bcm_mn_cosq_index_resolve(unit, gport, cosq,
  11517                                          _BCM_MN_COSQ_INDEX_STYLE_MCAST_QUEUE,
  11518                                          &local_port, &startq, NULL));
  11519         mem = MMU_THDM_DB_QUEUE_CONFIG_0m;
  11520         startq -= _BCM_MN_NUM_L2_UC_LEAVES; /* MC queues comes after UC queues */
  11521     } else {
  11522         if (soc_property_get(unit, spn_PORT_UC_MC_ACCOUNTING_COMBINE, 0) == 0) {
  11523             /* Need to have the UC_MC_Combine config enabled */
  11524             return BCM_E_PARAM;
  11525         }
  11526         mem = MMU_THDM_DB_PORTSP_CONFIG_0m;
  11527         startq = SOC_MONTEREY_MMU_PIPED_MEM_INDEX(unit, local_port, mem, pool);
  11528     }
  11529 
  11530     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  11531 
  11532     if (mem2 != INVALIDm) {
  11533         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem2, MEM_BLOCK_ALL, startq, entry2));
  11534     }
  11535 
  11536     switch (type) {
  11537     case bcmCosqControlEgressPoolLimitBytes:
  11538         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  11539             fld_limit = Q_SHARED_LIMIT_CELLf;
  11540 
  11541             if (mem2 != INVALIDm) {
  11542                 soc_mem_field32_set(unit, mem2, entry2, Q_LIMIT_ENABLEf, 1);
  11543             }
  11544         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  11545             fld_limit = Q_SHARED_LIMITf;
  11546             soc_mem_field32_set(unit, mem, entry, Q_LIMIT_ENABLEf, 1);
  11547         } else {
  11548             fld_limit = SHARED_LIMITf;
  11549             soc_mem_field32_set(unit, mem, entry, SHARED_LIMIT_ENABLEf, 1);
  11550         }
  11551         granularity = 1;
  11552         break;
  11553     case bcmCosqControlEgressPoolYellowLimitBytes:
  11554         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  11555             fld_limit = LIMIT_YELLOW_CELLf;
  11556         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  11557             fld_limit = YELLOW_SHARED_LIMITf;
  11558         } else {
  11559             fld_limit = YELLOW_SHARED_LIMITf;
  11560         }
  11561         granularity = 8;
  11562         break;
  11563     case bcmCosqControlEgressPoolRedLimitBytes:
  11564         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  11565             fld_limit = LIMIT_RED_CELLf;
  11566         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  11567             fld_limit = RED_SHARED_LIMITf;
  11568         } else {
  11569             fld_limit = RED_SHARED_LIMITf;
  11570         }
  11571         granularity = 8;
  11572         break;
  11573     default:
  11574         return BCM_E_UNAVAIL;
  11575     }
  11576 
  11577     /* Check for min/max values */
  11578     max_val = (1 << soc_mem_field_length(unit, mem, fld_limit)) - 1;
  11579     if ((arg < 0) || ((arg/granularity) > max_val)) {
  11580         return BCM_E_PARAM;
  11581     } else {
  11582         soc_mem_field32_set(unit, mem, entry, fld_limit, (arg/granularity));
  11583     }
  11584     BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry));
  11585 
  11586     if (mem2 != INVALIDm) {
  11587         BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem2, MEM_BLOCK_ALL, startq, entry2));
  11588     }
  11589     return BCM_E_NONE;
  11590 }
  11591 
  11592 
  11593 
  11594 STATIC int
  11595 _bcm_mn_cosq_egr_port_pool_set(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
  11596                           bcm_cosq_control_t type, int arg)
  11597 {
  11598     bcm_port_t local_port;
  11599     uint32 max_val;
  11600     uint32 entry[SOC_MAX_MEM_WORDS];
  11601     soc_mem_t mem = INVALIDm;
  11602     soc_field_t fld_limit = INVALIDf;
  11603     int granularity = 1;
  11604     int pool, midx;
  11605 
  11606     if (arg < 0) {
  11607         return BCM_E_PARAM;
  11608     }
  11609 
  11610     BCM_IF_ERROR_RETURN
  11611         (_bcm_mn_cosq_index_resolve(unit, gport, cosq,
  11612                                     _BCM_MN_COSQ_INDEX_STYLE_EGR_POOL,
  11613                                     &local_port, &pool, NULL));
  11614     mem = MMU_THDU_XPIPE_CONFIG_PORTm;
  11615     midx = SOC_MONTEREY_MMU_PIPED_MEM_INDEX(unit, local_port, mem, pool);
  11616     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, entry));
  11617 
  11618     switch (type) {
  11619     case bcmCosqControlEgressPortPoolYellowLimitBytes:
  11620         fld_limit = YELLOW_LIMITf;
  11621         granularity = 8;
  11622         break;
  11623     case bcmCosqControlEgressPortPoolRedLimitBytes:
  11624         fld_limit = RED_LIMITf;
  11625         granularity = 8;
  11626         break;
  11627     default:
  11628         return BCM_E_UNAVAIL;
  11629     }
  11630 
  11631     arg = arg / _BCM_MN_BYTES_PER_CELL;
  11632 
  11633     /* Check for min/max values */
  11634     max_val = (1 << soc_mem_field_length(unit, mem, fld_limit)) - 1;
  11635     if ((arg < 0) || ((arg/granularity) > max_val)) {
  11636         return BCM_E_PARAM;
  11637     } else {
  11638         soc_mem_field32_set(unit, mem, entry, fld_limit, (arg/granularity));
  11639     }
  11640     BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, midx, entry));
  11641 
  11642     return BCM_E_NONE;
  11643 }
  11644 
  11645 
  11646 STATIC int
  11647 _bcm_mn_cosq_egr_pool_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
  11648                           bcm_cosq_control_t type, int *arg)
  11649 {
  11650     bcm_port_t local_port;
  11651     int startq, pool, midx;
  11652     uint32 entry[SOC_MAX_MEM_WORDS];
  11653     soc_mem_t mem;
  11654     int granularity = 1;
  11655 
  11656     if ((!arg) || (cosq < 0))  {
  11657         return BCM_E_PARAM;
  11658     }
  11659 
  11660     if (type == bcmCosqControlUCEgressPool) {
  11661         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 
  11662             BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) ||
  11663             BCM_GPORT_IS_SCHEDULER(gport)) {
  11664             return BCM_E_PARAM;
  11665         }
  11666 
  11667         BCM_IF_ERROR_RETURN
  11668             (_bcm_mn_cosq_index_resolve(unit, gport, cosq,
  11669                                          _BCM_MN_COSQ_INDEX_STYLE_UC_EGR_POOL,
  11670                                          &local_port, &pool, NULL));
  11671         *arg = pool;
  11672         return BCM_E_NONE;
  11673     } else {
  11674         if (type == bcmCosqControlMCEgressPool) {
  11675             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 
  11676                 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) || 
  11677                 BCM_GPORT_IS_SCHEDULER(gport)) {
  11678                 return BCM_E_PARAM;
  11679             }
  11680         }
  11681         BCM_IF_ERROR_RETURN
  11682             (_bcm_mn_cosq_index_resolve(unit, gport, cosq,
  11683                                          _BCM_MN_COSQ_INDEX_STYLE_EGR_POOL,
  11684                                          &local_port, &pool, NULL));
  11685         if (type == bcmCosqControlMCEgressPool ||
  11686             type == bcmCosqControlEgressPool) {
  11687             *arg = pool;
  11688             return BCM_E_NONE;
  11689         }
  11690     }
  11691 
  11692     /* per service pool settings */
  11693     if (type == bcmCosqControlEgressPoolSharedLimitBytes || 
  11694         type == bcmCosqControlEgressPoolResumeLimitBytes ||
  11695         type == bcmCosqControlEgressPoolYellowSharedLimitBytes || 
  11696         type == bcmCosqControlEgressPoolYellowResumeLimitBytes ||
  11697         type == bcmCosqControlEgressPoolRedSharedLimitBytes ||
  11698         type == bcmCosqControlEgressPoolRedResumeLimitBytes) {
  11699         uint32 rval;
  11700         soc_reg_t reg;
  11701         soc_field_t fld_limit = INVALIDf;
  11702         switch (type) {
  11703         case bcmCosqControlEgressPoolSharedLimitBytes:
  11704             reg = MMU_THDM_DB_POOL_SHARED_LIMITr;    
  11705             fld_limit = SHARED_LIMITf;
  11706             granularity = 1;
  11707             break;
  11708         case bcmCosqControlEgressPoolResumeLimitBytes:
  11709             reg = MMU_THDM_DB_POOL_RESUME_LIMITr;    
  11710             fld_limit = RESUME_LIMITf;
  11711             granularity = 8;
  11712             break;
  11713         case bcmCosqControlEgressPoolYellowSharedLimitBytes:
  11714             reg = MMU_THDM_DB_POOL_YELLOW_SHARED_LIMITr;    
  11715             fld_limit = YELLOW_SHARED_LIMITf;
  11716             granularity = 8;
  11717             break;
  11718         case bcmCosqControlEgressPoolYellowResumeLimitBytes:
  11719             reg = MMU_THDM_DB_POOL_YELLOW_RESUME_LIMITr;    
  11720             fld_limit = YELLOW_RESUME_LIMITf;
  11721             granularity = 8;
  11722             break;
  11723         case bcmCosqControlEgressPoolRedSharedLimitBytes:
  11724             reg = MMU_THDM_DB_POOL_RED_SHARED_LIMITr;    
  11725             fld_limit = RED_SHARED_LIMITf;
  11726             granularity = 8;
  11727             break;
  11728         case bcmCosqControlEgressPoolRedResumeLimitBytes:
  11729             reg = MMU_THDM_DB_POOL_RED_RESUME_LIMITr;    
  11730             fld_limit = RED_RESUME_LIMITf;
  11731             granularity = 8;
  11732             break;
  11733         /* coverity[dead_error_begin] */
  11734         default:
  11735             return BCM_E_UNAVAIL;
  11736         }
  11737 
  11738         BCM_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, pool, &rval));
  11739 
  11740         *arg = soc_reg_field_get(unit, reg, rval, fld_limit);
  11741         *arg = (*arg) * granularity * _BCM_MN_BYTES_PER_CELL;
  11742 
  11743         return BCM_E_NONE;
  11744     }
  11745     mem = MMU_THDM_DB_PORTSP_CONFIG_0m;
  11746 
  11747     if (type == bcmCosqControlEgressPoolLimitEnable) {
  11748         midx = SOC_MONTEREY_MMU_PIPED_MEM_INDEX(unit, local_port, mem, pool);
  11749         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL,
  11750                                  midx, entry));
  11751 
  11752         *arg = soc_mem_field32_get(unit, mem, entry, SHARED_LIMIT_ENABLEf);
  11753         return BCM_E_NONE;
  11754     }
  11755 
  11756     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  11757         BCM_IF_ERROR_RETURN
  11758             (_bcm_mn_cosq_index_resolve(unit, gport, cosq,
  11759                                          _BCM_MN_COSQ_INDEX_STYLE_UCAST_QUEUE,
  11760                                          &local_port, &startq, NULL));
  11761         mem = MMU_THDU_XPIPE_CONFIG_QUEUEm;
  11762     } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  11763         BCM_IF_ERROR_RETURN
  11764             (_bcm_mn_cosq_index_resolve(unit, gport, cosq,
  11765                                          _BCM_MN_COSQ_INDEX_STYLE_MCAST_QUEUE,
  11766                                          &local_port, &startq, NULL));
  11767         mem = MMU_THDM_DB_QUEUE_CONFIG_0m;
  11768         startq -= _BCM_MN_NUM_L2_UC_LEAVES; /* MC queues comes after UC queues */
  11769     } else {
  11770         if (soc_property_get(unit, spn_PORT_UC_MC_ACCOUNTING_COMBINE, 0) == 0) {
  11771             /* Need to have the UC_MC_Combine config enabled */
  11772             return BCM_E_PARAM;
  11773         }
  11774         mem = MMU_THDM_DB_PORTSP_CONFIG_0m;
  11775         startq = SOC_MONTEREY_MMU_PIPED_MEM_INDEX(unit, local_port, mem, pool);
  11776     }
  11777     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL,
  11778                              startq, entry));
  11779 
  11780     switch (type) {
  11781 
  11782     case bcmCosqControlEgressPoolLimitBytes:
  11783         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  11784             *arg = soc_mem_field32_get(unit, mem, entry, Q_SHARED_LIMIT_CELLf);
  11785         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  11786             *arg = soc_mem_field32_get(unit, mem, entry, Q_SHARED_LIMITf);
  11787         } else {
  11788             *arg = soc_mem_field32_get(unit, mem, entry, SHARED_LIMITf);
  11789         }
  11790         granularity = 1;
  11791         break;
  11792     case bcmCosqControlEgressPoolYellowLimitBytes:
  11793         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  11794             *arg = soc_mem_field32_get(unit, mem, entry, LIMIT_YELLOW_CELLf);
  11795         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  11796             *arg = soc_mem_field32_get(unit, mem, entry, YELLOW_SHARED_LIMITf);
  11797         } else {
  11798             *arg = soc_mem_field32_get(unit, mem, entry, YELLOW_SHARED_LIMITf);
  11799         }
  11800         granularity = 8;
  11801         break;
  11802     case bcmCosqControlEgressPoolRedLimitBytes:
  11803         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  11804             *arg = soc_mem_field32_get(unit, mem, entry, LIMIT_RED_CELLf);
  11805         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  11806             *arg = soc_mem_field32_get(unit, mem, entry, RED_SHARED_LIMITf);
  11807         } else {
  11808             *arg = soc_mem_field32_get(unit, mem, entry, RED_SHARED_LIMITf);
  11809         }
  11810         granularity = 8;
  11811         break;
  11812     default:
  11813         return BCM_E_UNAVAIL;
  11814     }
  11815     *arg = (*arg) * granularity * _BCM_MN_BYTES_PER_CELL;
  11816     return BCM_E_NONE;
  11817 }
  11818 
  11819 
  11820 STATIC int
  11821 _bcm_mn_cosq_egr_port_pool_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
  11822                           bcm_cosq_control_t type, int *arg)
  11823 {
  11824     bcm_port_t local_port;
  11825     uint32 entry[SOC_MAX_MEM_WORDS];
  11826     soc_mem_t mem = INVALIDm;
  11827     int granularity = 1;
  11828     int pool, midx;
  11829     
  11830     if (!arg) {
  11831         return BCM_E_PARAM;
  11832     }
  11833 
  11834 
  11835     BCM_IF_ERROR_RETURN
  11836       (_bcm_mn_cosq_index_resolve(unit, gport, cosq,
  11837                                    _BCM_MN_COSQ_INDEX_STYLE_EGR_POOL,
  11838                                    &local_port, &pool, NULL));
  11839     mem = MMU_THDU_XPIPE_CONFIG_PORTm;
  11840     midx = SOC_MONTEREY_MMU_PIPED_MEM_INDEX(unit, local_port, mem, pool);
  11841     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, entry));
  11842 
  11843     switch (type) {
  11844     case bcmCosqControlEgressPortPoolYellowLimitBytes:
  11845         *arg = soc_mem_field32_get(unit, mem, entry, YELLOW_LIMITf);
  11846         granularity = 8;
  11847         break;
  11848     case bcmCosqControlEgressPortPoolRedLimitBytes:
  11849 		*arg = soc_mem_field32_get(unit, mem, entry, RED_LIMITf);
  11850         granularity = 8;
  11851         break;
  11852     default:
  11853         return BCM_E_UNAVAIL;
  11854     }
  11855 
  11856 	
  11857     *arg = (*arg) * granularity * _BCM_MN_BYTES_PER_CELL;
  11858     return BCM_E_NONE;
  11859 }
  11860 
  11861 
  11862 
  11863 STATIC int
  11864 _bcm_mn_cosq_egr_queue_set(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
  11865                             bcm_cosq_control_t type, int arg)
  11866 {
  11867     bcm_port_t local_port;
  11868     int startq;
  11869     uint32 max_val, rval = 0;
  11870     uint32 shared_size, spid;
  11871     uint32 entry[SOC_MAX_MEM_WORDS];
  11872     uint32 entry2[SOC_MAX_MEM_WORDS];
  11873     soc_mem_t mem = INVALIDm, mem2 = INVALIDm;
  11874     soc_field_t fld_limit = INVALIDf;
  11875     soc_field_t fld_sp = INVALIDf;
  11876     int granularity = 1;
  11877     int from_cos, to_cos, ci;
  11878     int cur_val, rv, post_update, limit = 0;
  11879     _bcm_mn_mmu_info_t *mmu_info = _bcm_mn_mmu_info[unit];
  11880 
  11881     if (arg < 0) {
  11882         return BCM_E_PARAM;
  11883     }
  11884 
  11885     arg /= _BCM_MN_BYTES_PER_CELL;
  11886 
  11887     if ((type == bcmCosqControlEgressUCQueueMinLimitBytes) ||
  11888         (type == bcmCosqControlEgressUCQueueSharedLimitBytes)) {
  11889         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  11890             BCM_IF_ERROR_RETURN
  11891                 (_bcm_mn_cosq_index_resolve(unit, gport, cosq,
  11892                                              _BCM_MN_COSQ_INDEX_STYLE_UCAST_QUEUE,
  11893                                              &local_port, &startq, NULL));
  11894         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  11895             return BCM_E_PARAM;
  11896         }
  11897         else {
  11898             if (cosq == BCM_COS_INVALID) {
  11899                 from_cos = to_cos = 0;
  11900             } else {
  11901                 from_cos = to_cos = cosq;
  11902             }
  11903 
  11904             BCM_IF_ERROR_RETURN
  11905                 (_bcm_mn_cosq_localport_resolve(unit, gport, &local_port));
  11906             if (local_port < 0) {
  11907                 return BCM_E_PORT;
  11908             }
  11909             for (ci = from_cos; ci <= to_cos; ci++) {
  11910                 BCM_IF_ERROR_RETURN
  11911                     (_bcm_mn_cosq_index_resolve
  11912                      (unit, local_port, ci, _BCM_MN_COSQ_INDEX_STYLE_UCAST_QUEUE,
  11913                       NULL, &startq, NULL));
  11914             }
  11915         }
  11916         mem = MMU_THDU_XPIPE_CONFIG_QUEUEm;
  11917 
  11918         mem2 = MMU_THDU_XPIPE_Q_TO_QGRP_MAPm;
  11919 
  11920         fld_sp = Q_SPIDf; 
  11921     } else if ((type == bcmCosqControlEgressMCQueueMinLimitBytes) ||
  11922                (type == bcmCosqControlEgressMCQueueSharedLimitBytes)) {
  11923         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  11924             return BCM_E_PARAM;
  11925         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  11926             BCM_IF_ERROR_RETURN
  11927                 (_bcm_mn_cosq_index_resolve(unit, gport, cosq,
  11928                                              _BCM_MN_COSQ_INDEX_STYLE_MCAST_QUEUE,
  11929                                              &local_port, &startq, NULL));
  11930         }
  11931         else {
  11932             if (cosq == BCM_COS_INVALID) {
  11933                 from_cos = to_cos = 0;
  11934             } else {
  11935                 from_cos = to_cos = cosq;
  11936             }
  11937 
  11938             BCM_IF_ERROR_RETURN
  11939                 (_bcm_mn_cosq_localport_resolve(unit, gport, &local_port));
  11940             if (local_port < 0) {
  11941                 return BCM_E_PORT;
  11942             }
  11943             for (ci = from_cos; ci <= to_cos; ci++) {
  11944                 BCM_IF_ERROR_RETURN
  11945                     (_bcm_mn_cosq_index_resolve
  11946                      (unit, local_port, ci, _BCM_MN_COSQ_INDEX_STYLE_MCAST_QUEUE,
  11947                       NULL, &startq, NULL));
  11948             }
  11949         }
  11950         mem = MMU_THDM_DB_QUEUE_CONFIG_0m;
  11951         mem2 = MMU_THDM_MCQE_QUEUE_CONFIG_0m;
  11952         fld_sp = Q_SPIDf;
  11953         startq -= _BCM_MN_NUM_L2_UC_LEAVES; /* MC queues comes after UC queues */
  11954     } else {
  11955         return BCM_E_PARAM;
  11956     }
  11957 
  11958     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  11959     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem2, MEM_BLOCK_ALL, startq, entry2));
  11960 
  11961     switch (type) {
  11962     case bcmCosqControlEgressUCQueueSharedLimitBytes:
  11963         fld_limit = Q_SHARED_LIMIT_CELLf;
  11964 
  11965         if (mem2 != INVALIDm) {
  11966             soc_mem_field32_set(unit, mem2, entry2, Q_LIMIT_ENABLEf, 1);
  11967         }
  11968 
  11969         /* Set MMU_THDU_XPIPE_Q_TO_QGRP_MAP.DISABLE_QUEUING to 1 when both MIN
  11970          * and SHARED LIMIT are 0. Set it to 0 when either MIN or SHARED LIMIT
  11971          * is non-zero.
  11972          */
  11973         limit = soc_mem_field32_get(unit, mem, entry, Q_MIN_LIMIT_CELLf);
  11974         if (arg == 0 && limit == 0) {
  11975             soc_mem_field32_set(unit, mem2, entry2, DISABLE_QUEUINGf, 1);
  11976         } else if (arg != 0 || limit != 0) {
  11977             soc_mem_field32_set(unit, mem2, entry2, DISABLE_QUEUINGf, 0);
  11978         }
  11979         spid = soc_mem_field32_get(unit, mem2, entry2, fld_sp);
  11980         granularity = 1;
  11981         break;
  11982     case bcmCosqControlEgressMCQueueSharedLimitBytes:
  11983         fld_limit = Q_SHARED_LIMITf;
  11984         soc_mem_field32_set(unit, mem, entry, Q_LIMIT_ENABLEf, 1);
  11985 
  11986         /* Config LIMIT in THDO_MC_QE: in 4-enties granularity */
  11987         granularity = 4;
  11988         soc_mem_field32_set(unit, mem2, entry2, fld_limit, (arg/granularity));
  11989         soc_mem_field32_set(unit, mem2, entry2, Q_LIMIT_ENABLEf, 1);
  11990         spid = soc_mem_field32_get(unit, mem, entry, fld_sp);
  11991         granularity = 1;
  11992         break;
  11993     case bcmCosqControlEgressUCQueueMinLimitBytes:
  11994         fld_limit = Q_MIN_LIMIT_CELLf;
  11995 
  11996         /* Set MMU_THDU_XPIPE_Q_TO_QGRP_MAP.DISABLE_QUEUING to 1 when both MIN
  11997                 * and SHARED LIMIT are 0. Set it to 0 when either MIN or SHARED LIMIT is non-zero
  11998                 */
  11999         limit = soc_mem_field32_get(unit, mem, entry, Q_SHARED_LIMIT_CELLf);
  12000         if (arg == 0 && limit == 0) {
  12001             soc_mem_field32_set(unit, mem2, entry2, DISABLE_QUEUINGf, 1);
  12002         } else if (arg != 0 || limit != 0) {
  12003             soc_mem_field32_set(unit, mem2, entry2, DISABLE_QUEUINGf, 0);
  12004         }
  12005         spid = soc_mem_field32_get(unit, mem2, entry2, fld_sp);
  12006         granularity = 1;
  12007         break;
  12008     case bcmCosqControlEgressMCQueueMinLimitBytes:
  12009         fld_limit = Q_MIN_LIMITf;
  12010 
  12011         /* Config LIMIT in THDO_MC_QE: in 4-enties granularity */
  12012         granularity = 4;
  12013         soc_mem_field32_set(unit, mem2, entry2, fld_limit, (arg/granularity));
  12014         spid = soc_mem_field32_get(unit, mem, entry, fld_sp);
  12015         granularity = 1;
  12016         break;
  12017     default:
  12018         return BCM_E_UNAVAIL;
  12019     }
  12020 
  12021     /* Recalculate Shared Values if Min Changed */
  12022     SOC_IF_ERROR_RETURN(READ_MMU_THDM_DB_POOL_SHARED_LIMITr(unit, spid, &rval));
  12023     shared_size = soc_reg_field_get(unit, MMU_THDM_DB_POOL_SHARED_LIMITr, rval, SHARED_LIMITf); 
  12024     cur_val = soc_mem_field32_get(unit, mem, entry, fld_limit);
  12025         
  12026     if ((arg / granularity) > cur_val) {
  12027         /* New Min Val > Cur Min Val
  12028          * So reduce the Shared values first and then 
  12029          * Increase the Min Value for given resource
  12030          */
  12031         post_update = 0;
  12032     } else if ((arg / granularity) < cur_val) {
  12033         /* New Min Val < Cur Min Val
  12034          * So reduce the Min values first and then 
  12035          * Increase Shared values everywhere
  12036          */
  12037         post_update = 1;
  12038     } else {
  12039         return BCM_E_NONE;
  12040     }
  12041  
  12042     if (!post_update &&
  12043         ((type == bcmCosqControlEgressUCQueueMinLimitBytes) ||
  12044          (type == bcmCosqControlEgressMCQueueMinLimitBytes))) {
  12045         int delta = 0; /* In Cells */
  12046         delta = ((arg / granularity) - cur_val) * granularity;
  12047         if (delta > shared_size) {
  12048             return BCM_E_RESOURCE;
  12049         }
  12050         rv = soc_monterey_mmu_config_res_limits_update(unit,spid,
  12051                                                   shared_size - delta, 1);
  12052         if (rv < 0) { 
  12053             return rv;
  12054         }
  12055         mmu_info->curr_shared_limit = shared_size - delta;
  12056     }
  12057 
  12058 
  12059     /* Check for min/max values */
  12060     max_val = (1 << soc_mem_field_length(unit, mem, fld_limit)) - 1;
  12061     if ((arg < 0) || ((arg/granularity) > max_val)) {
  12062         return BCM_E_PARAM;
  12063     } else {
  12064         /* Get the latest entry data and update. */
  12065         SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL,
  12066                                          startq, entry));
  12067         soc_mem_field32_set(unit, mem, entry, fld_limit, (arg/granularity));
  12068     }
  12069     BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry));
  12070 
  12071     if (mem2 != INVALIDm) {
  12072         BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem2, MEM_BLOCK_ALL, startq, entry2));
  12073     }
  12074 
  12075     if (post_update && 
  12076         ((type == bcmCosqControlEgressUCQueueMinLimitBytes) ||
  12077          (type == bcmCosqControlEgressMCQueueMinLimitBytes))) {
  12078         int delta = 0;
  12079         delta = (cur_val - (arg / granularity)) * granularity;
  12080         rv = soc_monterey_mmu_config_res_limits_update(unit,spid,
  12081                                                   shared_size + delta, 0);
  12082         if (rv < 0) { 
  12083             return rv;
  12084         }
  12085         mmu_info->curr_shared_limit = shared_size + delta;
  12086     }
  12087 
  12088     return BCM_E_NONE;
  12089 }
  12090 
  12091 STATIC int
  12092 _bcm_mn_cosq_egr_queue_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
  12093                             bcm_cosq_control_t type, int *arg)
  12094 {
  12095     bcm_port_t local_port;
  12096     int startq;
  12097     uint32 entry[SOC_MAX_MEM_WORDS];
  12098     soc_mem_t mem = INVALIDm;
  12099     soc_field_t fld_limit = INVALIDf;
  12100     int granularity = 1;
  12101     int from_cos, to_cos, ci;
  12102 
  12103     if (!arg) {
  12104         return BCM_E_PARAM;
  12105     }
  12106 
  12107     if ((type == bcmCosqControlEgressUCQueueMinLimitBytes) ||
  12108         (type == bcmCosqControlEgressUCQueueSharedLimitBytes)) {
  12109         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  12110             BCM_IF_ERROR_RETURN
  12111                 (_bcm_mn_cosq_index_resolve(unit, gport, cosq,
  12112                                              _BCM_MN_COSQ_INDEX_STYLE_UCAST_QUEUE,
  12113                                              &local_port, &startq, NULL));
  12114         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  12115             return BCM_E_PARAM;
  12116         }
  12117         else {
  12118             if (cosq == BCM_COS_INVALID) {
  12119                 from_cos = to_cos = 0;
  12120             } else {
  12121                 from_cos = to_cos = cosq;
  12122             }
  12123 
  12124             BCM_IF_ERROR_RETURN
  12125                 (_bcm_mn_cosq_localport_resolve(unit, gport, &local_port));
  12126             if (local_port < 0) {
  12127                 return BCM_E_PORT;
  12128             }
  12129             for (ci = from_cos; ci <= to_cos; ci++) {
  12130                 BCM_IF_ERROR_RETURN
  12131                     (_bcm_mn_cosq_index_resolve
  12132                      (unit, local_port, ci, _BCM_MN_COSQ_INDEX_STYLE_UCAST_QUEUE,
  12133                       NULL, &startq, NULL));
  12134             }
  12135         }
  12136         mem = MMU_THDU_XPIPE_CONFIG_QUEUEm;
  12137     } else if ((type == bcmCosqControlEgressMCQueueMinLimitBytes) ||
  12138                (type == bcmCosqControlEgressMCQueueSharedLimitBytes)) {
  12139         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  12140             return BCM_E_PARAM;
  12141         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  12142             BCM_IF_ERROR_RETURN
  12143                 (_bcm_mn_cosq_index_resolve(unit, gport, cosq,
  12144                                              _BCM_MN_COSQ_INDEX_STYLE_MCAST_QUEUE,
  12145                                              &local_port, &startq, NULL));
  12146         }
  12147         else {
  12148             if (cosq == BCM_COS_INVALID) {
  12149                 from_cos = to_cos = 0;
  12150             } else {
  12151                 from_cos = to_cos = cosq;
  12152             }
  12153 
  12154             BCM_IF_ERROR_RETURN
  12155                 (_bcm_mn_cosq_localport_resolve(unit, gport, &local_port));
  12156             if (local_port < 0) {
  12157                 return BCM_E_PORT;
  12158             }
  12159             for (ci = from_cos; ci <= to_cos; ci++) {
  12160                 BCM_IF_ERROR_RETURN
  12161                     (_bcm_mn_cosq_index_resolve
  12162                      (unit, local_port, ci, _BCM_MN_COSQ_INDEX_STYLE_MCAST_QUEUE,
  12163                       NULL, &startq, NULL));
  12164             }
  12165         }
  12166         mem = MMU_THDM_DB_QUEUE_CONFIG_0m;
  12167         startq -= _BCM_MN_NUM_L2_UC_LEAVES; /* MC queues comes after UC queues */
  12168     } else {
  12169         return BCM_E_PARAM;
  12170     }
  12171 
  12172     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL,
  12173                              startq, entry));
  12174 
  12175     switch (type) {
  12176     case bcmCosqControlEgressUCQueueSharedLimitBytes:
  12177         fld_limit = Q_SHARED_LIMIT_CELLf;
  12178         granularity = 1;
  12179         break;
  12180     case bcmCosqControlEgressMCQueueSharedLimitBytes:
  12181         fld_limit = Q_SHARED_LIMITf;
  12182         granularity = 1;
  12183         break;
  12184     case bcmCosqControlEgressUCQueueMinLimitBytes:
  12185         fld_limit = Q_MIN_LIMIT_CELLf;
  12186         granularity = 1;
  12187         break;
  12188     case bcmCosqControlEgressMCQueueMinLimitBytes:
  12189         fld_limit = Q_MIN_LIMITf;
  12190         granularity = 1;
  12191         break;
  12192     default:
  12193         return BCM_E_UNAVAIL;
  12194     }
  12195     *arg = soc_mem_field32_get(unit, mem, entry, fld_limit);
  12196     *arg = (*arg) * granularity * _BCM_MN_BYTES_PER_CELL;
  12197     return BCM_E_NONE;
  12198 }
  12199 
  12200 STATIC int
  12201 _bcm_mn_cosq_ing_res_set(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
  12202                           bcm_cosq_control_t type, int arg)
  12203 {
  12204     bcm_port_t local_port;
  12205     int midx;
  12206     uint32 max_val, rval;
  12207     uint32 entry[SOC_MAX_MEM_WORDS];
  12208     soc_mem_t mem = INVALIDm;
  12209     soc_field_t fld_limit = INVALIDf;
  12210     soc_reg_t reg = INVALIDr;
  12211     int port_pg, port_pg_pool, granularity = 1;
  12212     static const soc_reg_t prigroup_reg[] = {
  12213         THDI_PORT_PRI_GRP0r, THDI_PORT_PRI_GRP1r
  12214     };
  12215     static const soc_field_t prigroup_field[] = {
  12216         PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf,
  12217         PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf,
  12218         PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf,
  12219         PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf
  12220     };
  12221     static const soc_field_t prigroup_spid_field[] = {
  12222         PG0_SPIDf, PG1_SPIDf, PG2_SPIDf, PG3_SPIDf,
  12223         PG4_SPIDf, PG5_SPIDf, PG6_SPIDf, PG7_SPIDf
  12224     };
  12225 
  12226     if (cosq > 15 || cosq < 0) {
  12227         /* Error. Input pri > Max Pri_Grp */
  12228         return BCM_E_PARAM;
  12229     }
  12230 
  12231     if (arg < 0) {
  12232         return BCM_E_PARAM;
  12233     }
  12234 
  12235     arg /= _BCM_MN_BYTES_PER_CELL;
  12236     BCM_IF_ERROR_RETURN
  12237         (_bcm_mn_cosq_localport_resolve(unit, gport, &local_port));
  12238     if (local_port < 0) {
  12239         return BCM_E_PORT;
  12240     }
  12241 
  12242     /* get PG for port using Port+Cos */
  12243     if (cosq < 8) {
  12244         reg = prigroup_reg[0];
  12245     } else {
  12246         reg = prigroup_reg[1];
  12247     }
  12248 
  12249     SOC_IF_ERROR_RETURN
  12250         (soc_reg32_get(unit, reg, local_port, 0, &rval));
  12251     port_pg = soc_reg_field_get(unit, reg, rval, prigroup_field[cosq]);
  12252 
  12253  
  12254     if ((type == bcmCosqControlIngressPortPGSharedLimitBytes) ||
  12255         (type == bcmCosqControlIngressPortPGMinLimitBytes) ||
  12256         (type == bcmCosqControlIngressPortPGHeadroomLimitBytes) ||
  12257         (type == bcmCosqControlIngressPortPGResetFloorBytes)) {
  12258         mem = THDI_PORT_PG_CONFIG_Xm;
  12259         /* get index for Port-PG */
  12260         midx = SOC_MONTEREY_MMU_PIPED_MEM_INDEX(unit, local_port, mem, port_pg);
  12261         
  12262     } else if ((type == bcmCosqControlIngressPortPoolMaxLimitBytes) ||
  12263                (type == bcmCosqControlIngressPortPoolMinLimitBytes)) {
  12264         reg = THDI_PORT_PG_SPIDr;
  12265 
  12266         SOC_IF_ERROR_RETURN
  12267             (soc_reg32_get(unit, reg, local_port, 0, &rval));
  12268         port_pg_pool = soc_reg_field_get(unit, reg, rval, prigroup_spid_field[port_pg]);
  12269 
  12270         mem = THDI_PORT_SP_CONFIG_Xm;
  12271         /* get index for Port-SP */
  12272         midx = SOC_MONTEREY_MMU_PIPED_MEM_INDEX(unit, local_port, mem, port_pg_pool);
  12273     } else {
  12274         return BCM_E_UNAVAIL;
  12275     }
  12276 
  12277     if (midx < 0) {
  12278         return BCM_E_PARAM;
  12279     }
  12280 
  12281     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, entry));
  12282 
  12283     switch (type) {
  12284     case bcmCosqControlIngressPortPGSharedLimitBytes:
  12285         fld_limit = PG_SHARED_LIMITf;
  12286         granularity = 1;
  12287         break;
  12288     case bcmCosqControlIngressPortPoolMaxLimitBytes:
  12289         fld_limit = PORT_SP_MAX_LIMITf;
  12290         granularity = 1;
  12291         break;
  12292     case bcmCosqControlIngressPortPGMinLimitBytes:
  12293         fld_limit = PG_MIN_LIMITf;
  12294         granularity = 1;
  12295         break;
  12296     case bcmCosqControlIngressPortPoolMinLimitBytes:
  12297         fld_limit = PORT_SP_MIN_LIMITf;
  12298         granularity = 1;
  12299         break;
  12300     case bcmCosqControlIngressPortPGHeadroomLimitBytes:
  12301         fld_limit = PG_HDRM_LIMITf;
  12302         granularity = 1;
  12303         break;
  12304     case bcmCosqControlIngressPortPGResetFloorBytes:
  12305         fld_limit = PG_RESET_FLOORf;
  12306         granularity = 1;
  12307         break;
  12308     /* coverity[dead_error_begin] */
  12309     default:
  12310         return BCM_E_UNAVAIL;
  12311     }
  12312 
  12313     /* Check for min/max values */
  12314     max_val = (1 << soc_mem_field_length(unit, mem, fld_limit)) - 1;
  12315     if ((arg < 0) || ((arg/granularity) > max_val)) {
  12316         return BCM_E_PARAM;
  12317     } else {
  12318         soc_mem_field32_set(unit, mem, entry, fld_limit, (arg/granularity));
  12319     }
  12320     BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, midx, entry));
  12321 
  12322     return BCM_E_NONE;
  12323 }
  12324 
  12325 STATIC int
  12326 _bcm_mn_cosq_state_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
  12327                           bcm_cosq_control_t type, int *arg)
  12328 {
  12329     bcm_port_t local_port;
  12330     uint32 rval, state , mask = 1 , bitno = 0;
  12331     static const soc_field_t pool_field[] = {
  12332         POOL_0f, POOL_1f, POOL_2f, POOL_3f }; 
  12333     int start_pool_idx = 0,end_pool_idx = 0;    
  12334     if (!arg) {
  12335         return BCM_E_PARAM;
  12336     }
  12337     switch (type) {
  12338         case bcmCosqControlSPPortLimitState:
  12339         case bcmCosqControlPoolRedDropState:
  12340         case bcmCosqControlPoolYellowDropState:
  12341         case bcmCosqControlPoolGreenDropState:
  12342             BCM_IF_ERROR_RETURN
  12343                 (_bcm_mn_cosq_localport_resolve(unit, gport, &local_port));
  12344 
  12345             if (!SOC_PORT_VALID(unit, local_port)) {
  12346                 return BCM_E_PORT;
  12347             }
  12348             BCM_IF_ERROR_RETURN (_bcm_mn_cosq_egress_sp_get(unit, gport, cosq, &start_pool_idx, 
  12349                         &end_pool_idx)); 
  12350             bitno = start_pool_idx; 
  12351             break;
  12352    
  12353         case bcmCosqControlPGPortLimitState:
  12354         case bcmCosqControlPGPortXoffState:
  12355             BCM_IF_ERROR_RETURN
  12356                 (_bcm_mn_cosq_localport_resolve(unit, gport, &local_port));
  12357 
  12358             if (!SOC_PORT_VALID(unit, local_port)) {
  12359                 return BCM_E_PORT;
  12360             }
  12361             if ((cosq < 0 ) || (cosq > 7)) {
  12362                 return BCM_E_PARAM;
  12363             }
  12364             bitno = cosq;
  12365             break;
  12366         default:
  12367             return BCM_E_PARAM;
  12368     }
  12369     switch (type) {
  12370         case bcmCosqControlSPPortLimitState:
  12371             SOC_IF_ERROR_RETURN(
  12372                     READ_THDI_PORT_LIMIT_STATESr(unit, local_port, &rval));
  12373             state = soc_reg_field_get(unit, THDI_PORT_LIMIT_STATESr, rval,
  12374                     SP_LIMIT_STATEf);
  12375             break;
  12376         case bcmCosqControlPGPortLimitState:
  12377             SOC_IF_ERROR_RETURN(
  12378                     READ_THDI_PORT_LIMIT_STATESr(unit, local_port, &rval));
  12379             state = soc_reg_field_get(unit, THDI_PORT_LIMIT_STATESr, rval,
  12380                     PG_LIMIT_STATEf);
  12381             break;
  12382         case bcmCosqControlPGPortXoffState:
  12383             SOC_IF_ERROR_RETURN(
  12384                     READ_THDI_FLOW_CONTROL_XOFF_STATEr(unit, local_port, &rval));
  12385             state = soc_reg_field_get(unit, THDI_FLOW_CONTROL_XOFF_STATEr, rval,
  12386                     PG_BMPf);
  12387             break;
  12388         case bcmCosqControlPoolRedDropState:
  12389             SOC_IF_ERROR_RETURN(
  12390                     READ_THDI_POOL_DROP_STATEr(unit, &rval));
  12391             state = soc_reg_field_get(unit, THDI_POOL_DROP_STATEr, rval,
  12392                     pool_field[start_pool_idx]);
  12393             bitno = 2;
  12394             break;
  12395         case bcmCosqControlPoolYellowDropState:
  12396             SOC_IF_ERROR_RETURN(
  12397                     READ_THDI_POOL_DROP_STATEr(unit, &rval));
  12398             state = soc_reg_field_get(unit, THDI_POOL_DROP_STATEr, rval,
  12399                     pool_field[start_pool_idx]);
  12400             bitno = 1;
  12401             break;
  12402         case bcmCosqControlPoolGreenDropState:
  12403             SOC_IF_ERROR_RETURN(
  12404                     READ_THDI_POOL_DROP_STATEr(unit, &rval));
  12405             state = soc_reg_field_get(unit, THDI_POOL_DROP_STATEr, rval,
  12406                     pool_field[start_pool_idx]);
  12407             bitno = 0;
  12408             break;
  12409         /* coverity[dead_error_begin] */
  12410         default :
  12411             return BCM_E_PARAM;
  12412     }
  12413     mask = mask<<bitno; 
  12414     state = state & mask ;
  12415     if (state) {
  12416         *arg = 1 ;
  12417     } else {
  12418         *arg = 0 ;
  12419     }
  12420     return BCM_E_NONE;
  12421 }
  12422 
  12423 STATIC int
  12424 _bcm_mn_cosq_ing_res_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
  12425                           bcm_cosq_control_t type, int *arg)
  12426 {
  12427     bcm_port_t local_port;
  12428     uint32 rval;
  12429     uint32 entry[SOC_MAX_MEM_WORDS];
  12430     soc_mem_t mem = INVALIDm;
  12431     soc_field_t fld_limit = INVALIDf;
  12432     soc_reg_t reg = INVALIDr;
  12433     int midx, port_pg, port_pg_pool, granularity = 1;
  12434     static const soc_reg_t prigroup_reg[] = {
  12435         THDI_PORT_PRI_GRP0r, THDI_PORT_PRI_GRP1r
  12436     };
  12437     static const soc_field_t prigroup_field[] = {
  12438         PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf,
  12439         PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf,
  12440         PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf,
  12441         PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf
  12442     };
  12443     static const soc_field_t prigroup_spid_field[] = {
  12444         PG0_SPIDf, PG1_SPIDf, PG2_SPIDf, PG3_SPIDf,
  12445         PG4_SPIDf, PG5_SPIDf, PG6_SPIDf, PG7_SPIDf
  12446     };
  12447 
  12448     if (cosq > 15 || cosq < 0) {
  12449         /* Error. Input pri > Max Pri_Grp */
  12450         return BCM_E_PARAM;
  12451     }
  12452     if (!arg) {
  12453         return BCM_E_PARAM;
  12454     }
  12455 
  12456     BCM_IF_ERROR_RETURN
  12457         (_bcm_mn_cosq_localport_resolve(unit, gport, &local_port));
  12458     if (local_port < 0) {
  12459         return BCM_E_PORT;
  12460     }
  12461 
  12462     /* get PG for port using Port+Cos */
  12463     if (cosq < 8) {
  12464         reg = prigroup_reg[0];
  12465     } else {
  12466         reg = prigroup_reg[1];
  12467     }
  12468 
  12469     SOC_IF_ERROR_RETURN
  12470         (soc_reg32_get(unit, reg, local_port, 0, &rval));
  12471     port_pg = soc_reg_field_get(unit, reg, rval, prigroup_field[cosq]);
  12472 
  12473  
  12474     if ((type == bcmCosqControlIngressPortPGSharedLimitBytes) ||
  12475         (type == bcmCosqControlIngressPortPGMinLimitBytes) ||
  12476         (type == bcmCosqControlIngressPortPGHeadroomLimitBytes)||
  12477         (type == bcmCosqControlIngressPortPGResetFloorBytes)) {
  12478         mem = THDI_PORT_PG_CONFIG_Xm;
  12479         /* get index for Port-PG */
  12480         midx = SOC_MONTEREY_MMU_PIPED_MEM_INDEX(unit, local_port, mem, port_pg);
  12481     } else if ((type == bcmCosqControlIngressPortPoolMaxLimitBytes) ||
  12482                (type == bcmCosqControlIngressPortPoolMinLimitBytes)) {
  12483         reg = THDI_PORT_PG_SPIDr;
  12484 
  12485         SOC_IF_ERROR_RETURN
  12486             (soc_reg32_get(unit, reg, local_port, 0, &rval));
  12487         port_pg_pool = soc_reg_field_get(unit, reg, rval, prigroup_spid_field[port_pg]);
  12488 
  12489         mem = THDI_PORT_SP_CONFIG_Xm;
  12490         /* get index for Port-SP */
  12491         midx = SOC_MONTEREY_MMU_PIPED_MEM_INDEX(unit, local_port, mem, port_pg_pool);
  12492     } else {
  12493         return BCM_E_UNAVAIL;
  12494     }
  12495 
  12496     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, entry));
  12497 
  12498     switch (type) {
  12499     case bcmCosqControlIngressPortPGSharedLimitBytes:
  12500         fld_limit = PG_SHARED_LIMITf;
  12501         granularity = 1;
  12502         break;
  12503     case bcmCosqControlIngressPortPoolMaxLimitBytes:
  12504         fld_limit = PORT_SP_MAX_LIMITf;
  12505         granularity = 1;
  12506         break;
  12507     case bcmCosqControlIngressPortPGMinLimitBytes:
  12508         fld_limit = PG_MIN_LIMITf;
  12509         granularity = 1;
  12510         break;
  12511     case bcmCosqControlIngressPortPoolMinLimitBytes:
  12512         fld_limit = PORT_SP_MIN_LIMITf;
  12513         granularity = 1;
  12514         break;
  12515     case bcmCosqControlIngressPortPGHeadroomLimitBytes:
  12516         fld_limit = PG_HDRM_LIMITf;
  12517         granularity =1;
  12518         break;
  12519     case bcmCosqControlIngressPortPGResetFloorBytes:
  12520         fld_limit = PG_RESET_FLOORf;
  12521         granularity =1;
  12522         break;
  12523     /* coverity[dead_error_begin] */
  12524     default:
  12525         return BCM_E_UNAVAIL;
  12526     }
  12527 
  12528     *arg = soc_mem_field32_get(unit, mem, entry, fld_limit);
  12529     *arg = (*arg) * granularity * _BCM_MN_BYTES_PER_CELL;
  12530     return BCM_E_NONE;
  12531 }
  12532 
  12533 
  12534 
  12535 /*
  12536  * This function is used to get ingress pool
  12537  * limit given Ingress [Port, Priority]
  12538  */
  12539 STATIC int
  12540 _bcm_mn_cosq_ing_res_limit_get(int unit, bcm_gport_t gport, bcm_cos_t cosq,
  12541                                bcm_cosq_control_t type, int *arg)
  12542 {
  12543     bcm_port_t local_port;
  12544     uint32 rval;
  12545     soc_reg_t reg = INVALIDr;
  12546     int port_pg, port_pg_pool;
  12547     static const soc_reg_t prigroup_reg[] = {
  12548        THDI_PORT_PRI_GRP0r, THDI_PORT_PRI_GRP1r
  12549     };
  12550     static const soc_field_t prigroup_field[] = {
  12551        PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf,
  12552        PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf,
  12553        PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf,
  12554        PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf
  12555     };
  12556     static const soc_field_t prigroup_spid_field[] = {
  12557        PG0_SPIDf, PG1_SPIDf, PG2_SPIDf, PG3_SPIDf,
  12558        PG4_SPIDf, PG5_SPIDf, PG6_SPIDf, PG7_SPIDf
  12559     };
  12560 
  12561     if (cosq > 15 || cosq < 0) {
  12562        /* Error. Input pri > Max Pri_Grp */
  12563        return BCM_E_PARAM;
  12564     }
  12565     if (!arg) {
  12566        return BCM_E_PARAM;
  12567     }
  12568 
  12569     BCM_IF_ERROR_RETURN
  12570        (_bcm_mn_cosq_localport_resolve(unit, gport, &local_port));
  12571     if (local_port < 0) {
  12572        return BCM_E_PORT;
  12573     }
  12574     
  12575     /* get PG for port using Port+Cos */
  12576     if (cosq < 8) {
  12577         reg = prigroup_reg[0];
  12578     } else {
  12579         reg = prigroup_reg[1];
  12580     }
  12581 
  12582     SOC_IF_ERROR_RETURN
  12583        (soc_reg32_get(unit, reg, local_port, 0, &rval));
  12584     port_pg = soc_reg_field_get(unit, reg, rval, prigroup_field[cosq]);
  12585 
  12586 
  12587     if (type == bcmCosqControlIngressPoolLimitBytes) {
  12588         reg = THDI_PORT_PG_SPIDr;
  12589 
  12590         SOC_IF_ERROR_RETURN
  12591             (soc_reg32_get(unit, reg, local_port, 0, &rval));
  12592         port_pg_pool = soc_reg_field_get(unit, reg, rval, prigroup_spid_field[port_pg]);
  12593 
  12594         SOC_IF_ERROR_RETURN
  12595             (READ_THDI_BUFFER_CELL_LIMIT_SPr(unit, port_pg_pool, &rval));
  12596         *arg = soc_reg_field_get(unit, THDI_BUFFER_CELL_LIMIT_SPr, rval, LIMITf);
  12597     } else {
  12598         return BCM_E_PARAM;
  12599     }
  12600 
  12601     *arg = (*arg) * _BCM_MN_BYTES_PER_CELL;
  12602 
  12603     return BCM_E_NONE;
  12604 }
  12605 
  12606 /*
  12607  * This function is used to set ingress pool
  12608  * limit given Ingress [Port, Priority]
  12609  */
  12610 STATIC int
  12611 _bcm_mn_cosq_ing_res_limit_set(int unit, bcm_gport_t gport, bcm_cos_t cosq,
  12612                                bcm_cosq_control_t type, int arg)
  12613 {
  12614     bcm_port_t local_port;
  12615     uint32 max_val, rval;
  12616     soc_reg_t reg = INVALIDr;
  12617     int port_pg, port_pg_pool;
  12618     static const soc_reg_t prigroup_reg[] = {
  12619         THDI_PORT_PRI_GRP0r, THDI_PORT_PRI_GRP1r
  12620     };
  12621     static const soc_field_t prigroup_field[] = {
  12622         PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf,
  12623         PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf,
  12624         PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf,
  12625         PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf
  12626     };
  12627     static const soc_field_t prigroup_spid_field[] = {
  12628         PG0_SPIDf, PG1_SPIDf, PG2_SPIDf, PG3_SPIDf,
  12629         PG4_SPIDf, PG5_SPIDf, PG6_SPIDf, PG7_SPIDf
  12630     };
  12631 
  12632     if (cosq > 15 || cosq < 0) {
  12633         /* Error. Input pri > Max Pri_Grp */
  12634         return BCM_E_PARAM;
  12635     }
  12636 
  12637     if (arg < 0) {
  12638         return BCM_E_PARAM;
  12639     }
  12640 
  12641     arg /= _BCM_MN_BYTES_PER_CELL;
  12642     BCM_IF_ERROR_RETURN
  12643         (_bcm_mn_cosq_localport_resolve(unit, gport, &local_port));
  12644     if (local_port < 0) {
  12645         return BCM_E_PORT;
  12646     }
  12647 
  12648     /* get PG for port using Port+Cos */
  12649     if (cosq < 8) {
  12650         reg = prigroup_reg[0];
  12651     } else {
  12652         reg = prigroup_reg[1];
  12653     }
  12654 
  12655     SOC_IF_ERROR_RETURN
  12656         (soc_reg32_get(unit, reg, local_port, 0, &rval));
  12657     port_pg = soc_reg_field_get(unit, reg, rval, prigroup_field[cosq]);
  12658 
  12659     if (type == bcmCosqControlIngressPoolLimitBytes) {
  12660         reg = THDI_PORT_PG_SPIDr;
  12661 
  12662         SOC_IF_ERROR_RETURN
  12663             (soc_reg32_get(unit, reg, local_port, 0, &rval));
  12664         port_pg_pool = soc_reg_field_get(unit, reg, rval, prigroup_spid_field[port_pg]);
  12665         
  12666         rval = 0;
  12667         SOC_IF_ERROR_RETURN(READ_THDI_BUFFER_CELL_LIMIT_SPr(unit, port_pg_pool, &rval));
  12668         /* Check for min/max values */
  12669         max_val = (1 << soc_reg_field_length(unit, THDI_BUFFER_CELL_LIMIT_SPr, LIMITf)) - 1;
  12670         if ((arg < 0) || (arg > max_val)) {
  12671             return BCM_E_PARAM;
  12672         } else {
  12673             soc_reg_field_set(unit, THDI_BUFFER_CELL_LIMIT_SPr, &rval, LIMITf, arg);
  12674         }
  12675         
  12676         SOC_IF_ERROR_RETURN(WRITE_THDI_BUFFER_CELL_LIMIT_SPr(unit, port_pg_pool, rval));
  12677     } else {
  12678         return BCM_E_PARAM;
  12679     }
  12680 
  12681     return BCM_E_NONE;
  12682 }
  12683 
  12684 STATIC int
  12685 _bcm_mn_cosq_ef_op_at_index(int unit, int port, int hw_index, _bcm_cosq_op_t op, 
  12686                              int *ef_val)
  12687 {
  12688     uint32 entry[SOC_MAX_MEM_WORDS];
  12689     soc_monterey_sched_type_t sched_type;
  12690     soc_mem_t mem;
  12691 
  12692     sched_type = _soc_monterey_port_sched_type_get(unit, port);
  12693 
  12694     if (sched_type == SOC_MONTEREY_SCHED_LLS) {
  12695         mem = _SOC_MONTEREY_NODE_PARENT_MEM(unit, port, SOC_MONTEREY_NODE_LVL_L2);
  12696         SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, hw_index, &entry));
  12697 
  12698         if (op == _BCM_COSQ_OP_GET) {
  12699             *ef_val = soc_mem_field32_get(unit, mem, &entry, C_EFf);
  12700         } else {
  12701             soc_mem_field32_set(unit, mem, &entry, C_EFf, *ef_val);
  12702             SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, 
  12703                                 hw_index, &entry));
  12704         }
  12705     } else {
  12706         return BCM_E_UNAVAIL;
  12707     }
  12708    
  12709     return BCM_E_NONE;
  12710 }
  12711 
  12712 STATIC int
  12713 _bcm_mn_cosq_ef_op(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, int *arg,
  12714                     _bcm_cosq_op_t op)
  12715 {
  12716     _bcm_mn_cosq_node_t *node;
  12717     bcm_port_t local_port;
  12718     int index, numq, from_cos, to_cos, ci;
  12719 
  12720     if (BCM_GPORT_IS_SCHEDULER(gport)) {
  12721         BCM_IF_ERROR_RETURN
  12722             (_bcm_mn_cosq_node_get(unit, gport, 0, NULL, 
  12723                                     &local_port, NULL, &node));
  12724         BCM_IF_ERROR_RETURN(
  12725                _bcm_mn_cosq_child_node_at_input(node, cosq, &node));
  12726         gport = node->gport;
  12727         cosq = 0;
  12728     }
  12729 
  12730     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  12731         BCM_IF_ERROR_RETURN
  12732             (_bcm_mn_cosq_index_resolve
  12733              (unit, gport, cosq, _BCM_MN_COSQ_INDEX_STYLE_UCAST_QUEUE,
  12734               &local_port, &index, NULL));
  12735         return _bcm_mn_cosq_ef_op_at_index(unit, local_port, index, op, arg);
  12736     } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  12737         BCM_IF_ERROR_RETURN
  12738             (_bcm_mn_cosq_index_resolve
  12739              (unit, gport, cosq, _BCM_MN_COSQ_INDEX_STYLE_MCAST_QUEUE,
  12740               &local_port, &index, NULL));
  12741         return _bcm_mn_cosq_ef_op_at_index(unit, local_port, index, op, arg);
  12742     } else if (BCM_GPORT_IS_SCHEDULER(gport)) {
  12743         return BCM_E_PARAM;
  12744     } else {
  12745         BCM_IF_ERROR_RETURN(_bcm_mn_cosq_port_has_ets(unit, local_port));
  12746         if (cosq == BCM_COS_INVALID) {
  12747             from_cos = 0;
  12748             to_cos = _MN_NUM_COS(unit) - 1;
  12749         } else {
  12750             from_cos = to_cos = cosq;
  12751         }
  12752         for (ci = from_cos; ci <= to_cos; ci++) {
  12753             BCM_IF_ERROR_RETURN
  12754                 (_bcm_mn_cosq_index_resolve
  12755                  (unit, gport, ci, _BCM_MN_COSQ_INDEX_STYLE_UCAST_QUEUE,
  12756                   &local_port, &index, &numq));
  12757 
  12758             BCM_IF_ERROR_RETURN(_bcm_mn_cosq_ef_op_at_index(unit, 
  12759                                 local_port, index, op, arg));
  12760             if (op == _BCM_COSQ_OP_GET) {
  12761                 return BCM_E_NONE;
  12762             }
  12763 
  12764             BCM_IF_ERROR_RETURN
  12765                 (_bcm_mn_cosq_index_resolve
  12766                  (unit, gport, ci, _BCM_MN_COSQ_INDEX_STYLE_MCAST_QUEUE,
  12767                   &local_port, &index, &numq));
  12768 
  12769             BCM_IF_ERROR_RETURN(_bcm_mn_cosq_ef_op_at_index(unit, 
  12770                                 local_port, index, op, arg));
  12771         }
  12772     }
  12773     return BCM_E_NONE;
  12774 }
  12775 STATIC int
  12776 _bcm_mn_cosq_qcn_proxy_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
  12777                             bcm_cosq_control_t type, int *arg)
  12778 {
  12779     int local_port;
  12780     uint32 rval;
  12781 
  12782     BCM_IF_ERROR_RETURN
  12783         (_bcm_mn_cosq_localport_resolve(unit, gport, &local_port));
  12784 
  12785     BCM_IF_ERROR_RETURN(READ_QCN_CNM_PRP_CTRLr(unit, local_port, &rval));
  12786     *arg = soc_reg_field_get(unit, QCN_CNM_PRP_CTRLr, rval, ENABLEf);
  12787 
  12788     return BCM_E_NONE;
  12789 }
  12790     
  12791 STATIC int
  12792 _bcm_mn_cosq_qcn_proxy_set(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 
  12793                             bcm_cosq_control_t type, int arg)
  12794 {
  12795     int local_port;
  12796     uint32 rval;
  12797     
  12798     BCM_IF_ERROR_RETURN
  12799         (_bcm_mn_cosq_localport_resolve(unit, gport, &local_port));
  12800     
  12801     BCM_IF_ERROR_RETURN(READ_QCN_CNM_PRP_CTRLr(unit, local_port, &rval));
  12802     soc_reg_field_set(unit, QCN_CNM_PRP_CTRLr, &rval, ENABLEf, !!arg);
  12803     soc_reg_field_set(unit, QCN_CNM_PRP_CTRLr, &rval, PRIORITY_BMAPf, 0xff);
  12804     BCM_IF_ERROR_RETURN(WRITE_QCN_CNM_PRP_CTRLr(unit, local_port, rval));
  12805     return BCM_E_NONE;
  12806 }
  12807 
  12808 STATIC int
  12809 _bcm_mn_cosq_alpha_set(int unit, 
  12810                         bcm_gport_t gport, bcm_cos_queue_t cosq,
  12811                         bcm_cosq_control_drop_limit_alpha_value_t arg)
  12812 {
  12813     bcm_port_t local_port;
  12814     int startq;
  12815     int midx; 
  12816     uint32 rval;     
  12817     uint32 entry[SOC_MAX_MEM_WORDS];
  12818     uint32 entry2[SOC_MAX_MEM_WORDS];
  12819     soc_mem_t mem = INVALIDm, mem2 = INVALIDm;
  12820     int alpha;
  12821     int dynamic_thresh_mode;    
  12822     soc_reg_t reg = INVALIDr;
  12823     int port_pg;
  12824     static const soc_reg_t prigroup_reg[] = {
  12825         THDI_PORT_PRI_GRP0r, THDI_PORT_PRI_GRP1r
  12826     };
  12827     static const soc_field_t prigroup_field[] = {
  12828         PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf,
  12829         PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf,
  12830         PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf,
  12831         PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf
  12832     };      
  12833 
  12834     switch(arg) {
  12835     case bcmCosqControlDropLimitAlpha_1_128:
  12836         alpha = SOC_MONTEREY_COSQ_DROP_LIMIT_ALPHA_1_128;
  12837         break;
  12838     case bcmCosqControlDropLimitAlpha_1_64:
  12839         alpha = SOC_MONTEREY_COSQ_DROP_LIMIT_ALPHA_1_64;
  12840         break;
  12841     case bcmCosqControlDropLimitAlpha_1_32:
  12842         alpha = SOC_MONTEREY_COSQ_DROP_LIMIT_ALPHA_1_32;
  12843         break;
  12844     case bcmCosqControlDropLimitAlpha_1_16:
  12845         alpha = SOC_MONTEREY_COSQ_DROP_LIMIT_ALPHA_1_16;
  12846         break;
  12847     case bcmCosqControlDropLimitAlpha_1_8:
  12848         alpha = SOC_MONTEREY_COSQ_DROP_LIMIT_ALPHA_1_8;
  12849         break;
  12850     case bcmCosqControlDropLimitAlpha_1_4:
  12851         alpha = SOC_MONTEREY_COSQ_DROP_LIMIT_ALPHA_1_4;
  12852         break;
  12853     case bcmCosqControlDropLimitAlpha_1_2:
  12854         alpha = SOC_MONTEREY_COSQ_DROP_LIMIT_ALPHA_1_2;
  12855         break;
  12856     case bcmCosqControlDropLimitAlpha_1:
  12857         alpha = SOC_MONTEREY_COSQ_DROP_LIMIT_ALPHA_1;
  12858         break;   
  12859     case bcmCosqControlDropLimitAlpha_2:
  12860         alpha = SOC_MONTEREY_COSQ_DROP_LIMIT_ALPHA_2;
  12861         break;
  12862     case bcmCosqControlDropLimitAlpha_4:
  12863         alpha = SOC_MONTEREY_COSQ_DROP_LIMIT_ALPHA_4;
  12864         break;
  12865     case bcmCosqControlDropLimitAlpha_8:
  12866         alpha = SOC_MONTEREY_COSQ_DROP_LIMIT_ALPHA_8;
  12867         break;         
  12868     default:
  12869         return BCM_E_PARAM;          
  12870     }
  12871 
  12872     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  12873         BCM_IF_ERROR_RETURN
  12874                 (_bcm_mn_cosq_dynamic_thresh_enable_get(unit, gport, cosq, 
  12875                                    bcmCosqControlEgressUCSharedDynamicEnable, 
  12876                                    &dynamic_thresh_mode));
  12877         if (!dynamic_thresh_mode){
  12878             return BCM_E_CONFIG;
  12879         } 
  12880         
  12881         BCM_IF_ERROR_RETURN
  12882             (_bcm_mn_cosq_index_resolve(unit, gport, cosq,
  12883                                      _BCM_MN_COSQ_INDEX_STYLE_UCAST_QUEUE,
  12884                                      &local_port, &startq, NULL));
  12885         mem = MMU_THDU_XPIPE_CONFIG_QUEUEm;
  12886         
  12887         BCM_IF_ERROR_RETURN
  12888             (soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  12889         soc_mem_field32_set(unit, mem, entry, 
  12890                             Q_SHARED_ALPHA_CELLf, alpha);
  12891         SOC_IF_ERROR_RETURN
  12892             (soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry));                 
  12893     } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  12894         BCM_IF_ERROR_RETURN
  12895                 (_bcm_mn_cosq_dynamic_thresh_enable_get(unit, gport, cosq, 
  12896                                    bcmCosqControlEgressMCSharedDynamicEnable, 
  12897                                    &dynamic_thresh_mode));
  12898         if (!dynamic_thresh_mode){
  12899             return BCM_E_CONFIG;
  12900         }
  12901         
  12902         BCM_IF_ERROR_RETURN
  12903             (_bcm_mn_cosq_index_resolve(unit, gport, cosq,
  12904                                      _BCM_MN_COSQ_INDEX_STYLE_MCAST_QUEUE,
  12905                                      &local_port, &startq, NULL));
  12906         mem =  MMU_THDM_DB_QUEUE_CONFIG_0m; 
  12907         mem2 = MMU_THDM_MCQE_QUEUE_CONFIG_0m;
  12908 
  12909         startq -= _BCM_MN_NUM_L2_UC_LEAVES; /* MC queues comes after UC queues */
  12910         BCM_IF_ERROR_RETURN
  12911             (soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  12912         soc_mem_field32_set(unit, mem, entry, Q_SHARED_ALPHAf, alpha);
  12913         SOC_IF_ERROR_RETURN
  12914             (soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry));    
  12915 
  12916         BCM_IF_ERROR_RETURN
  12917             (soc_mem_read(unit, mem2, MEM_BLOCK_ALL, startq, entry2));
  12918         soc_mem_field32_set(unit, mem2, entry2, Q_SHARED_ALPHAf, alpha);
  12919         SOC_IF_ERROR_RETURN
  12920             (soc_mem_write(unit, mem2, MEM_BLOCK_ALL, startq, entry2));              
  12921     } else {
  12922         BCM_IF_ERROR_RETURN
  12923                 (_bcm_mn_cosq_dynamic_thresh_enable_get(unit, gport, cosq,
  12924                                    bcmCosqControlIngressPortPGSharedDynamicEnable,
  12925                                    &dynamic_thresh_mode));
  12926         if (!dynamic_thresh_mode){
  12927             return BCM_E_CONFIG;
  12928         }
  12929 
  12930         BCM_IF_ERROR_RETURN
  12931             (_bcm_mn_cosq_localport_resolve(unit, gport, &local_port));
  12932         if (local_port < 0) {
  12933             return BCM_E_PORT;
  12934         }
  12935 
  12936         /* get PG for port using Port+Cos */
  12937         if (cosq < 8) {
  12938             reg = prigroup_reg[0];
  12939         } else {
  12940             reg = prigroup_reg[1];
  12941         }
  12942 
  12943         SOC_IF_ERROR_RETURN
  12944             (soc_reg32_get(unit, reg, local_port, 0, &rval));
  12945         port_pg = soc_reg_field_get(unit, reg, rval, prigroup_field[cosq]);
  12946         mem = THDI_PORT_PG_CONFIG_Xm;
  12947         /* get index for Port-PG */
  12948         midx = SOC_MONTEREY_MMU_PIPED_MEM_INDEX(unit, local_port, mem, port_pg);
  12949         BCM_IF_ERROR_RETURN
  12950             (soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, entry));
  12951         soc_mem_field32_set(unit, mem, entry, 
  12952                             PG_SHARED_LIMITf, alpha);
  12953         SOC_IF_ERROR_RETURN
  12954             (soc_mem_write(unit, mem, MEM_BLOCK_ALL, midx, entry)); 
  12955     } 
  12956     
  12957     return BCM_E_NONE;
  12958 }
  12959 
  12960 
  12961 STATIC int
  12962 _bcm_mn_cosq_alpha_get(int unit, 
  12963                         bcm_gport_t gport, bcm_cos_queue_t cosq, 
  12964                         bcm_cosq_control_drop_limit_alpha_value_t *arg)
  12965 {
  12966     bcm_port_t local_port;
  12967     int startq;
  12968     int midx;  
  12969     uint32 rval;     
  12970     uint32 entry[SOC_MAX_MEM_WORDS];
  12971     soc_mem_t mem = INVALIDm;    
  12972     int alpha;
  12973     int dynamic_thresh_mode;    
  12974     soc_reg_t reg = INVALIDr;
  12975     int port_pg;
  12976     static const soc_reg_t prigroup_reg[] = {
  12977         THDI_PORT_PRI_GRP0r, THDI_PORT_PRI_GRP1r
  12978     };
  12979     static const soc_field_t prigroup_field[] = {
  12980         PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf,
  12981         PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf,
  12982         PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf,
  12983         PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf
  12984     };      
  12985 
  12986     if (!arg) {
  12987         return BCM_E_PARAM;
  12988     }
  12989 
  12990     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  12991         BCM_IF_ERROR_RETURN
  12992                 (_bcm_mn_cosq_dynamic_thresh_enable_get(unit, gport, cosq, 
  12993                                    bcmCosqControlEgressUCSharedDynamicEnable, 
  12994                                    &dynamic_thresh_mode));
  12995         if (!dynamic_thresh_mode){
  12996             return BCM_E_CONFIG;
  12997         }
  12998         
  12999         BCM_IF_ERROR_RETURN
  13000             (_bcm_mn_cosq_index_resolve(unit, gport, cosq,
  13001                                      _BCM_MN_COSQ_INDEX_STYLE_UCAST_QUEUE,
  13002                                      &local_port, &startq, NULL));
  13003         mem = MMU_THDU_XPIPE_CONFIG_QUEUEm;
  13004 
  13005         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL,
  13006                                  startq, entry));
  13007         alpha = soc_mem_field32_get(unit, mem, entry, Q_SHARED_ALPHA_CELLf);  
  13008     
  13009     } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  13010         BCM_IF_ERROR_RETURN
  13011                 (_bcm_mn_cosq_dynamic_thresh_enable_get(unit, gport, cosq, 
  13012                                    bcmCosqControlEgressMCSharedDynamicEnable, 
  13013                                    &dynamic_thresh_mode));
  13014         if (!dynamic_thresh_mode){
  13015             return BCM_E_CONFIG;
  13016         }
  13017         
  13018         BCM_IF_ERROR_RETURN
  13019             (_bcm_mn_cosq_index_resolve(unit, gport, cosq,
  13020                                      _BCM_MN_COSQ_INDEX_STYLE_MCAST_QUEUE,
  13021                                      &local_port, &startq, NULL));
  13022         mem = MMU_THDM_DB_QUEUE_CONFIG_0m;
  13023 
  13024         startq -= _BCM_MN_NUM_L2_UC_LEAVES; /* MC queues comes after UC queues */
  13025         BCM_IF_ERROR_RETURN
  13026             (soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  13027         alpha = soc_mem_field32_get(unit, mem, entry, Q_SHARED_ALPHAf);        
  13028            
  13029     } else {
  13030         BCM_IF_ERROR_RETURN
  13031                 (_bcm_mn_cosq_dynamic_thresh_enable_get(unit, gport, cosq, 
  13032                                    bcmCosqControlIngressPortPGSharedDynamicEnable, 
  13033                                    &dynamic_thresh_mode));
  13034         if (!dynamic_thresh_mode){
  13035             return BCM_E_CONFIG;
  13036         }
  13037         
  13038         BCM_IF_ERROR_RETURN
  13039             (_bcm_mn_cosq_localport_resolve(unit, gport, &local_port));
  13040         if (local_port < 0) {
  13041             return BCM_E_PORT;
  13042         }
  13043 
  13044         /* get PG for port using Port+Cos */
  13045         if (cosq < 8) {
  13046             reg = prigroup_reg[0];
  13047         } else {
  13048             reg = prigroup_reg[1];
  13049         }
  13050 
  13051         SOC_IF_ERROR_RETURN
  13052             (soc_reg32_get(unit, reg, local_port, 0, &rval));
  13053         port_pg = soc_reg_field_get(unit, reg, rval, prigroup_field[cosq]);
  13054         mem = THDI_PORT_PG_CONFIG_Xm;
  13055         /* get index for Port-PG */
  13056         midx = SOC_MONTEREY_MMU_PIPED_MEM_INDEX(unit, local_port, mem, port_pg);
  13057 
  13058         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL,
  13059                                  midx, entry));
  13060         alpha = soc_mem_field32_get(unit, mem, entry, PG_SHARED_LIMITf);  
  13061         
  13062     } 
  13063 
  13064     switch(alpha) {
  13065     case SOC_MONTEREY_COSQ_DROP_LIMIT_ALPHA_1_128:
  13066         *arg = bcmCosqControlDropLimitAlpha_1_128;
  13067         break;
  13068     case SOC_MONTEREY_COSQ_DROP_LIMIT_ALPHA_1_64:
  13069         *arg = bcmCosqControlDropLimitAlpha_1_64;
  13070         break;
  13071     case SOC_MONTEREY_COSQ_DROP_LIMIT_ALPHA_1_32:
  13072         *arg = bcmCosqControlDropLimitAlpha_1_32;
  13073         break;
  13074     case SOC_MONTEREY_COSQ_DROP_LIMIT_ALPHA_1_16:
  13075         *arg = bcmCosqControlDropLimitAlpha_1_16;
  13076         break;
  13077     case SOC_MONTEREY_COSQ_DROP_LIMIT_ALPHA_1_8:
  13078         *arg = bcmCosqControlDropLimitAlpha_1_8;
  13079         break;
  13080     case SOC_MONTEREY_COSQ_DROP_LIMIT_ALPHA_1_4:
  13081         *arg = bcmCosqControlDropLimitAlpha_1_4;
  13082         break;
  13083     case SOC_MONTEREY_COSQ_DROP_LIMIT_ALPHA_1_2:
  13084         *arg = bcmCosqControlDropLimitAlpha_1_2;
  13085         break;
  13086     case SOC_MONTEREY_COSQ_DROP_LIMIT_ALPHA_1:
  13087         *arg = bcmCosqControlDropLimitAlpha_1;
  13088         break;   
  13089     case SOC_MONTEREY_COSQ_DROP_LIMIT_ALPHA_2:
  13090         *arg = bcmCosqControlDropLimitAlpha_2;
  13091         break;
  13092     case SOC_MONTEREY_COSQ_DROP_LIMIT_ALPHA_4:
  13093         *arg = bcmCosqControlDropLimitAlpha_4;
  13094         break;
  13095     case SOC_MONTEREY_COSQ_DROP_LIMIT_ALPHA_8:
  13096         *arg = bcmCosqControlDropLimitAlpha_8;
  13097         break;         
  13098     default:
  13099         return BCM_E_PARAM;          
  13100     }
  13101     
  13102     return BCM_E_NONE;
  13103 }
  13104 
  13105 STATIC int
  13106 _bcm_mn_cosq_dynamic_thresh_enable_set(int unit, 
  13107                         bcm_gport_t gport, bcm_cos_queue_t cosq,
  13108                         bcm_cosq_control_t type, int arg)
  13109 {
  13110     bcm_port_t local_port;
  13111     int startq;
  13112     int from_cos = 0, to_cos = 0; 
  13113     
  13114     int ci;     
  13115     int midx; 
  13116     uint32 rval;     
  13117     uint32 entry[SOC_MAX_MEM_WORDS];
  13118     uint32 entry2[SOC_MAX_MEM_WORDS];
  13119     soc_mem_t mem = INVALIDm, mem2 = INVALIDm;
  13120     soc_reg_t reg = INVALIDr;
  13121     int port_pg;
  13122     static const soc_reg_t prigroup_reg[] = {
  13123         THDI_PORT_PRI_GRP0r, THDI_PORT_PRI_GRP1r
  13124     };
  13125     static const soc_field_t prigroup_field[] = {
  13126         PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf,
  13127         PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf,
  13128         PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf,
  13129         PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf
  13130     };    
  13131 
  13132     if ((cosq < 0) || (cosq > 15)){
  13133         return BCM_E_PARAM;
  13134     }   
  13135 
  13136  
  13137     if (type == bcmCosqControlIngressPortPGSharedDynamicEnable) {
  13138         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
  13139             BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  13140             return BCM_E_PARAM;
  13141         }
  13142 
  13143         BCM_IF_ERROR_RETURN
  13144             (_bcm_mn_cosq_localport_resolve(unit, gport, &local_port));
  13145         if (local_port < 0) {
  13146             return BCM_E_PORT;
  13147         }
  13148 
  13149         /* get PG for port using Port+Cos */
  13150         if (cosq < 8) {
  13151             reg = prigroup_reg[0];
  13152         } else {
  13153             reg = prigroup_reg[1];
  13154         }
  13155 
  13156         SOC_IF_ERROR_RETURN
  13157             (soc_reg32_get(unit, reg, local_port, 0, &rval));
  13158         port_pg = soc_reg_field_get(unit, reg, rval, prigroup_field[cosq]);
  13159         mem = THDI_PORT_PG_CONFIG_Xm;
  13160         /* get index for Port-PG */
  13161         midx = SOC_MONTEREY_MMU_PIPED_MEM_INDEX(unit, local_port, mem, port_pg);
  13162         BCM_IF_ERROR_RETURN
  13163             (soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, entry));
  13164         soc_mem_field32_set(unit, mem, entry, 
  13165                             PG_SHARED_DYNAMICf, arg ? 1 : 0);
  13166         /* Set default alpha value*/
  13167         if (arg) {
  13168             soc_mem_field32_set(unit, mem, entry,
  13169                                 PG_SHARED_LIMITf, bcmCosqControlDropLimitAlpha_1_128);
  13170         }
  13171         SOC_IF_ERROR_RETURN
  13172             (soc_mem_write(unit, mem, MEM_BLOCK_ALL, midx, entry));           
  13173     } else if (type == bcmCosqControlEgressUCSharedDynamicEnable) {
  13174         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  13175             BCM_IF_ERROR_RETURN
  13176                 (_bcm_mn_cosq_index_resolve(unit, gport, cosq,
  13177                                          _BCM_MN_COSQ_INDEX_STYLE_UCAST_QUEUE,
  13178                                          &local_port, &startq, NULL));
  13179         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  13180             return BCM_E_PARAM;
  13181         } else {
  13182             from_cos = to_cos = cosq;
  13183 
  13184             BCM_IF_ERROR_RETURN
  13185                 (_bcm_mn_cosq_localport_resolve(unit, gport, &local_port));
  13186             if (local_port < 0) {
  13187                 return BCM_E_PORT;
  13188             }
  13189             for (ci = from_cos; ci <= to_cos; ci++) {
  13190                 BCM_IF_ERROR_RETURN
  13191                     (_bcm_mn_cosq_index_resolve(unit, local_port, ci,
  13192                           _BCM_MN_COSQ_INDEX_STYLE_UCAST_QUEUE,
  13193                           NULL, &startq, NULL));
  13194                 
  13195             }
  13196         }
  13197         mem = MMU_THDU_XPIPE_CONFIG_QUEUEm; 
  13198         
  13199         BCM_IF_ERROR_RETURN
  13200             (soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  13201         soc_mem_field32_set(unit, mem, entry, 
  13202                             Q_LIMIT_DYNAMIC_CELLf, arg ? 1 : 0);
  13203         /* Set default alpha value*/
  13204         if (arg) {
  13205             soc_mem_field32_set(unit, mem, entry,
  13206                                 Q_SHARED_ALPHA_CELLf, bcmCosqControlDropLimitAlpha_1_128);
  13207         }
  13208         SOC_IF_ERROR_RETURN
  13209             (soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry));         
  13210     } else if (type == bcmCosqControlEgressMCSharedDynamicEnable) {
  13211         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  13212             return BCM_E_PARAM;
  13213         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  13214             BCM_IF_ERROR_RETURN
  13215                 (_bcm_mn_cosq_index_resolve(unit, gport, cosq,
  13216                                          _BCM_MN_COSQ_INDEX_STYLE_MCAST_QUEUE,
  13217                                          &local_port, &startq, NULL));
  13218         }
  13219         else {
  13220             from_cos = to_cos = cosq;
  13221 
  13222             BCM_IF_ERROR_RETURN
  13223                 (_bcm_mn_cosq_localport_resolve(unit, gport, &local_port));
  13224             if (local_port < 0) {
  13225                 return BCM_E_PORT;
  13226             }
  13227             for (ci = from_cos; ci <= to_cos; ci++) {
  13228                 BCM_IF_ERROR_RETURN
  13229                     (_bcm_mn_cosq_index_resolve(unit, local_port, ci,
  13230                                          _BCM_MN_COSQ_INDEX_STYLE_MCAST_QUEUE,
  13231                                          NULL, &startq, NULL));
  13232               
  13233             }
  13234         }
  13235         
  13236         mem = MMU_THDM_DB_QUEUE_CONFIG_0m; 
  13237         mem2 = MMU_THDM_MCQE_QUEUE_CONFIG_0m; 
  13238 
  13239         startq -= _BCM_MN_NUM_L2_UC_LEAVES; /* MC queues comes after UC queues */
  13240         BCM_IF_ERROR_RETURN
  13241             (soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  13242         soc_mem_field32_set(unit, mem, entry, Q_LIMIT_DYNAMICf, arg ? 1 : 0);
  13243         /* Set default alpha value*/
  13244         if (arg) {
  13245             soc_mem_field32_set(unit, mem, entry,
  13246                                 Q_SHARED_ALPHAf, bcmCosqControlDropLimitAlpha_1_128);
  13247         }
  13248         SOC_IF_ERROR_RETURN
  13249             (soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry));    
  13250 
  13251         BCM_IF_ERROR_RETURN
  13252             (soc_mem_read(unit, mem2, MEM_BLOCK_ALL, startq, entry2));
  13253         soc_mem_field32_set(unit, mem2, entry2, Q_LIMIT_DYNAMICf, arg ? 1 : 0);
  13254         /* Set default alpha value*/
  13255         if (arg) {
  13256             soc_mem_field32_set(unit, mem2, entry2,
  13257                                 Q_SHARED_ALPHAf, bcmCosqControlDropLimitAlpha_1_128);
  13258         }
  13259         SOC_IF_ERROR_RETURN
  13260             (soc_mem_write(unit, mem2, MEM_BLOCK_ALL, startq, entry2));         
  13261        
  13262     } else {
  13263         return BCM_E_PARAM;
  13264     }
  13265 
  13266     return BCM_E_NONE;
  13267 }
  13268 
  13269 STATIC int
  13270 _bcm_mn_cosq_dynamic_thresh_enable_get(int unit, 
  13271                         bcm_gport_t gport, bcm_cos_queue_t cosq, 
  13272                         bcm_cosq_control_t type, int *arg)
  13273 {
  13274     bcm_port_t local_port;
  13275     int startq;
  13276     int from_cos = 0, to_cos = 0; 
  13277     int ci;   
  13278     int midx;  
  13279     uint32 rval;      
  13280     uint32 entry[SOC_MAX_MEM_WORDS];
  13281     soc_mem_t mem = INVALIDm;
  13282     soc_reg_t reg = INVALIDr;
  13283     int port_pg;
  13284     static const soc_reg_t prigroup_reg[] = {
  13285         THDI_PORT_PRI_GRP0r, THDI_PORT_PRI_GRP1r
  13286     };
  13287     static const soc_field_t prigroup_field[] = {
  13288         PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf,
  13289         PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf,
  13290         PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf,
  13291         PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf
  13292     };    
  13293 
  13294     if (!arg) {
  13295         return BCM_E_PARAM;
  13296     }
  13297 
  13298     if ((cosq < 0) || (cosq > 15)){
  13299         return BCM_E_PARAM;
  13300     }
  13301 
  13302     if (type == bcmCosqControlIngressPortPGSharedDynamicEnable) {
  13303         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
  13304             BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  13305             return BCM_E_PARAM;
  13306         }
  13307         BCM_IF_ERROR_RETURN
  13308             (_bcm_mn_cosq_localport_resolve(unit, gport, &local_port));
  13309         if (local_port < 0) {
  13310             return BCM_E_PORT;
  13311         }
  13312 
  13313         /* get PG for port using Port+Cos */
  13314         if (cosq < 8) {
  13315             reg = prigroup_reg[0];
  13316         } else {
  13317             reg = prigroup_reg[1];
  13318         }
  13319 
  13320         SOC_IF_ERROR_RETURN
  13321             (soc_reg32_get(unit, reg, local_port, 0, &rval));
  13322         port_pg = soc_reg_field_get(unit, reg, rval, prigroup_field[cosq]);
  13323         mem = THDI_PORT_PG_CONFIG_Xm;
  13324         /* get index for Port-PG */
  13325         midx = SOC_MONTEREY_MMU_PIPED_MEM_INDEX(unit, local_port, mem, port_pg);
  13326 
  13327         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL,
  13328                                  midx, entry));
  13329         *arg = soc_mem_field32_get(unit, mem, entry, PG_SHARED_DYNAMICf);  
  13330         
  13331     } else if (type == bcmCosqControlEgressUCSharedDynamicEnable) {
  13332         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  13333             BCM_IF_ERROR_RETURN
  13334                 (_bcm_mn_cosq_index_resolve(unit, gport, cosq,
  13335                                          _BCM_MN_COSQ_INDEX_STYLE_UCAST_QUEUE,
  13336                                          &local_port, &startq, NULL));
  13337         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  13338             return BCM_E_PARAM;
  13339         } else {
  13340             from_cos = to_cos = cosq;
  13341             BCM_IF_ERROR_RETURN
  13342                 (_bcm_mn_cosq_localport_resolve(unit, gport, &local_port));
  13343             if (local_port < 0) {
  13344                 return BCM_E_PORT;
  13345             }
  13346             for (ci = from_cos; ci <= to_cos; ci++) {
  13347                 BCM_IF_ERROR_RETURN
  13348                     (_bcm_mn_cosq_index_resolve(unit, local_port, ci,
  13349                           _BCM_MN_COSQ_INDEX_STYLE_UCAST_QUEUE,
  13350                           NULL, &startq, NULL));
  13351             }
  13352         }
  13353         mem = MMU_THDU_XPIPE_CONFIG_QUEUEm; 
  13354 
  13355         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL,
  13356                                  startq, entry));
  13357         *arg = soc_mem_field32_get(unit, mem, entry, Q_LIMIT_DYNAMIC_CELLf);        
  13358     } else if (type == bcmCosqControlEgressMCSharedDynamicEnable) {
  13359         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  13360             return BCM_E_PARAM;
  13361         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  13362             BCM_IF_ERROR_RETURN
  13363                 (_bcm_mn_cosq_index_resolve(unit, gport, cosq,
  13364                                          _BCM_MN_COSQ_INDEX_STYLE_MCAST_QUEUE,
  13365                                          &local_port, &startq, NULL));
  13366         }
  13367         else {
  13368             from_cos = to_cos = cosq;
  13369             BCM_IF_ERROR_RETURN
  13370                 (_bcm_mn_cosq_localport_resolve(unit, gport, &local_port));
  13371             if (local_port < 0) {
  13372                 return BCM_E_PORT;
  13373             }
  13374             for (ci = from_cos; ci <= to_cos; ci++) {
  13375                 BCM_IF_ERROR_RETURN
  13376                     (_bcm_mn_cosq_index_resolve(unit, local_port, ci,
  13377                                          _BCM_MN_COSQ_INDEX_STYLE_MCAST_QUEUE,
  13378                                          NULL, &startq, NULL));
  13379             }
  13380         }
  13381         mem = MMU_THDM_DB_QUEUE_CONFIG_0m; 
  13382 
  13383         startq -= _BCM_MN_NUM_L2_UC_LEAVES; /* MC queues comes after UC queues */
  13384         BCM_IF_ERROR_RETURN
  13385             (soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  13386         *arg = soc_mem_field32_get(unit, mem, entry, Q_LIMIT_DYNAMICf);
  13387     } else {
  13388         return BCM_E_PARAM;
  13389     }
  13390 
  13391     return BCM_E_NONE;
  13392 }
  13393 
  13394 STATIC int
  13395 _bcm_mn_cosq_egr_queue_limit_enable_set(int unit, bcm_gport_t gport,
  13396                                                  bcm_cos_queue_t cosq,
  13397                                                  bcm_cosq_control_t type,
  13398                                                  int arg)
  13399 {
  13400     bcm_port_t local_port;
  13401     int startq;
  13402     uint32 entry[SOC_MAX_MEM_WORDS];
  13403     soc_mem_t mem = INVALIDm;
  13404     int enable;
  13405 
  13406     if (arg < 0) {
  13407         return BCM_E_PARAM;
  13408     }
  13409 
  13410     arg = arg ? 1 : 0;
  13411 
  13412     if (type == bcmCosqControlEgressUCQueueLimitEnable) {
  13413         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  13414             BCM_IF_ERROR_RETURN
  13415                 (_bcm_mn_cosq_index_resolve(unit, gport, cosq,
  13416                                              _BCM_MN_COSQ_INDEX_STYLE_UCAST_QUEUE,
  13417                                              &local_port, &startq, NULL));
  13418         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  13419             return BCM_E_PARAM;
  13420         } else {
  13421             if (cosq < 0) {
  13422                 return BCM_E_PARAM;
  13423             }
  13424             BCM_IF_ERROR_RETURN
  13425                 (_bcm_mn_cosq_localport_resolve(unit, gport, &local_port));
  13426             if (local_port < 0) {
  13427                 return BCM_E_PORT;
  13428             }
  13429             BCM_IF_ERROR_RETURN
  13430                 (_bcm_mn_cosq_index_resolve
  13431                  (unit, local_port, cosq, _BCM_MN_COSQ_INDEX_STYLE_UCAST_QUEUE,
  13432                   NULL, &startq, NULL));
  13433         }
  13434 
  13435         mem = MMU_THDU_XPIPE_Q_TO_QGRP_MAPm;
  13436         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  13437         enable = soc_mem_field32_get(unit, mem, entry, Q_LIMIT_ENABLEf);
  13438         if (enable != arg) {
  13439             soc_mem_field32_set(unit, mem, entry, Q_LIMIT_ENABLEf, arg);
  13440             BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry));
  13441         }
  13442     }else if (type == bcmCosqControlEgressMCQueueLimitEnable) {
  13443         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  13444             return BCM_E_PARAM;
  13445         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  13446             BCM_IF_ERROR_RETURN
  13447                 (_bcm_mn_cosq_index_resolve(unit, gport, cosq,
  13448                                              _BCM_MN_COSQ_INDEX_STYLE_MCAST_QUEUE,
  13449                                              &local_port, &startq, NULL));
  13450         } else {
  13451             if (cosq < 0) {
  13452                 return BCM_E_PARAM;
  13453             }
  13454             BCM_IF_ERROR_RETURN
  13455                 (_bcm_mn_cosq_localport_resolve(unit, gport, &local_port));
  13456             if (local_port < 0) {
  13457                 return BCM_E_PORT;
  13458             }
  13459             BCM_IF_ERROR_RETURN
  13460                 (_bcm_mn_cosq_index_resolve(unit, local_port, cosq,
  13461                                             _BCM_MN_COSQ_INDEX_STYLE_MCAST_QUEUE,
  13462                                             NULL, &startq, NULL));
  13463         }
  13464         startq -= _BCM_MN_NUM_L2_UC_LEAVES; /* MC queues comes after UC queues */
  13465 
  13466         mem = MMU_THDM_MCQE_QUEUE_CONFIG_0m;
  13467         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  13468         enable = soc_mem_field32_get(unit, mem, entry, Q_LIMIT_ENABLEf);
  13469         if (enable != arg) {
  13470             soc_mem_field32_set(unit, mem, entry, Q_LIMIT_ENABLEf, arg);
  13471             BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry));
  13472         }
  13473 
  13474         mem = MMU_THDM_DB_QUEUE_CONFIG_0m;
  13475         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  13476         enable = soc_mem_field32_get(unit, mem, entry, Q_LIMIT_ENABLEf);
  13477         if (enable != arg) {
  13478             soc_mem_field32_set(unit, mem, entry, Q_LIMIT_ENABLEf, arg);
  13479             BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry));
  13480         }
  13481     } else {
  13482         return BCM_E_PARAM;
  13483     }
  13484 
  13485     return BCM_E_NONE;
  13486 }
  13487 
  13488 STATIC int
  13489 _bcm_mn_cosq_egr_queue_limit_enable_get(int unit, bcm_gport_t gport,
  13490                                                 bcm_cos_queue_t cosq,
  13491                                                 bcm_cosq_control_t type,
  13492                                                 int *arg)
  13493 {
  13494     bcm_port_t local_port;
  13495     int startq;
  13496     uint32 entry[SOC_MAX_MEM_WORDS];
  13497     soc_mem_t mem = INVALIDm;
  13498 
  13499     if (type == bcmCosqControlEgressUCQueueLimitEnable) {
  13500         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  13501             BCM_IF_ERROR_RETURN
  13502                 (_bcm_mn_cosq_index_resolve(unit, gport, cosq,
  13503                                           _BCM_MN_COSQ_INDEX_STYLE_UCAST_QUEUE,
  13504                                           &local_port, &startq, NULL));
  13505         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  13506             return BCM_E_PARAM;
  13507         } else {
  13508             if (cosq < 0) {
  13509                 return BCM_E_PARAM;
  13510             }
  13511             BCM_IF_ERROR_RETURN
  13512                 (_bcm_mn_cosq_localport_resolve(unit, gport, &local_port));
  13513             if (local_port < 0) {
  13514                 return BCM_E_PORT;
  13515             }
  13516             BCM_IF_ERROR_RETURN
  13517                 (_bcm_mn_cosq_index_resolve
  13518                     (unit, local_port, cosq, _BCM_MN_COSQ_INDEX_STYLE_UCAST_QUEUE,
  13519                     NULL, &startq, NULL));
  13520         }
  13521 
  13522         mem = MMU_THDU_XPIPE_Q_TO_QGRP_MAPm;
  13523         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  13524         *arg = soc_mem_field32_get(unit, mem, entry, Q_LIMIT_ENABLEf);
  13525     }else if (type == bcmCosqControlEgressMCQueueLimitEnable) {
  13526         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  13527             return BCM_E_PARAM;
  13528         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  13529             BCM_IF_ERROR_RETURN
  13530                 (_bcm_mn_cosq_index_resolve(unit, gport, cosq,
  13531                 _BCM_MN_COSQ_INDEX_STYLE_MCAST_QUEUE,
  13532                 &local_port, &startq, NULL));
  13533         } else {
  13534             if (cosq < 0) {
  13535                 return BCM_E_PARAM;
  13536             }
  13537             BCM_IF_ERROR_RETURN
  13538                 (_bcm_mn_cosq_localport_resolve(unit, gport, &local_port));
  13539             if (local_port < 0) {
  13540                 return BCM_E_PORT;
  13541             }
  13542             BCM_IF_ERROR_RETURN
  13543                 (_bcm_mn_cosq_index_resolve
  13544                 (unit, local_port, cosq, _BCM_MN_COSQ_INDEX_STYLE_MCAST_QUEUE,
  13545                 NULL, &startq, NULL));
  13546         }
  13547         mem = MMU_THDM_MCQE_QUEUE_CONFIG_0m;
  13548         startq -= _BCM_MN_NUM_L2_UC_LEAVES; /* MC queues comes after UC queues */
  13549         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  13550         *arg = soc_mem_field32_get(unit, mem, entry, Q_LIMIT_ENABLEf);
  13551     } else {
  13552         return BCM_E_PARAM;
  13553     }
  13554 
  13555     return BCM_E_NONE;
  13556 }
  13557 STATIC
  13558 int _bcm_mn_cosq_obm_threshold_get_reg_field(bcm_cos_queue_t cosq,
  13559                                              bcm_cosq_control_t type,
  13560                                              int *reg_index, soc_field_t *field)
  13561 {
  13562 
  13563     switch (cosq) {
  13564     case BCM_COSQ_OBM_CLASS_LOSSLESS0:
  13565         *reg_index = 0;
  13566         *field = LOSSLESS0_DISCARDf;
  13567         break;
  13568     case BCM_COSQ_OBM_CLASS_LOSSLESS1:
  13569         *reg_index = 0;
  13570         *field = LOSSLESS1_DISCARDf;
  13571         break;
  13572     case BCM_COSQ_OBM_CLASS_LOSSY_LOW:
  13573         *reg_index = 0;
  13574         *field = LOSSY_LOW_PRIf;
  13575         break;
  13576     case BCM_COSQ_OBM_CLASS_LOSSY:
  13577         *reg_index = 0;
  13578         if (type == bcmCosqControlObmDiscardLimit) {
  13579             *field = LOSSY_DISCARDf;
  13580         } else { /*type must be bcmCosqControlObmMinLimit */
  13581             *field = LOSSY_MINf;
  13582         }
  13583         break;
  13584     case BCM_COSQ_OBM_CLASS_EXPRESS:
  13585         *reg_index = 1;
  13586         *field = EXPRESS_DISCARDf;
  13587         break;
  13588     case BCM_COSQ_OBM_CLASS_ALL:
  13589         *reg_index = 1;
  13590         *field = DISCARD_LIMITf;
  13591         break;
  13592     default:
  13593         return BCM_E_PARAM;
  13594     }
  13595     return BCM_E_NONE;
  13596 }
  13597 STATIC
  13598 int _bcm_mn_cosq_obm_threshold_set_get(int unit, bcm_gport_t gport,
  13599                                        bcm_cos_queue_t cosq,
  13600                                        bcm_cosq_control_t type,
  13601                                        int *arg, int set)
  13602 {
  13603     soc_info_t *si;
  13604     int pgw, pgw_inst, subport, obm;
  13605     int phy_port;
  13606     bcm_port_t port;
  13607     int reg_index;
  13608     soc_reg_t reg;
  13609     soc_field_t field;
  13610     uint64 rval64;
  13611 
  13612     static const soc_reg_t obm_threshold_regs[2][8] = {
  13613         {IDB_OBM0_THRESHOLD_0r, IDB_OBM1_THRESHOLD_0r,
  13614         IDB_OBM2_THRESHOLD_0r, IDB_OBM3_THRESHOLD_0r,
  13615         IDB_OBM4_THRESHOLD_0r, IDB_OBM5_THRESHOLD_0r,
  13616         IDB_OBM6_THRESHOLD_0r, IDB_OBM7_THRESHOLD_0r},
  13617 
  13618         {IDB_OBM0_THRESHOLD_1r, IDB_OBM1_THRESHOLD_1r,
  13619         IDB_OBM2_THRESHOLD_1r, IDB_OBM3_THRESHOLD_1r,
  13620         IDB_OBM4_THRESHOLD_1r, IDB_OBM5_THRESHOLD_1r,
  13621         IDB_OBM6_THRESHOLD_1r, IDB_OBM7_THRESHOLD_1r}
  13622     };
  13623 
  13624     si = &SOC_INFO(unit);
  13625     BCM_IF_ERROR_RETURN(bcm_esw_port_local_get(unit, gport, &port));
  13626     phy_port = si->port_l2p_mapping[port];
  13627 
  13628     if (phy_port == -1) {
  13629         return BCM_E_PARAM;
  13630     }
  13631 
  13632     if (IS_CPU_PORT(unit, port) || IS_LB_PORT(unit, port)
  13633         || IS_MACSEC_PORT(unit, port)) {
  13634         /*  nothing to do for non-idb ports */
  13635         return BCM_E_NONE;
  13636     }
  13637     obm = si->port_serdes[port];
  13638     obm %= MONTEREY_TSCS_PER_PGW;
  13639     pgw = si->port_group[port];
  13640     pgw_inst = (pgw | SOC_REG_ADDR_INSTANCE_MASK);
  13641     subport = (phy_port - 1) % MONTEREY_PORTS_PER_TSC;
  13642 
  13643     BCM_IF_ERROR_RETURN
  13644         (_bcm_mn_cosq_obm_threshold_get_reg_field(cosq, type,
  13645                                                   &reg_index, &field));
  13646 
  13647     if (type == bcmCosqControlObmDiscardLimit) {
  13648         if ((cosq < BCM_COSQ_OBM_CLASS_LOSSLESS0) ||
  13649             (cosq > BCM_COSQ_OBM_CLASS_ALL)) {
  13650             return BCM_E_PARAM;
  13651         }
  13652     } else if (cosq == bcmCosqControlObmMinLimit) {
  13653         if (cosq != BCM_COSQ_OBM_CLASS_LOSSY) {
  13654             return BCM_E_PARAM;
  13655         }
  13656     }
  13657     COMPILER_64_ZERO(rval64);
  13658     reg = obm_threshold_regs[reg_index][obm];
  13659     SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, pgw_inst, subport, &rval64));
  13660     if (set) {
  13661         soc_reg64_field32_set(unit, reg, &rval64, field, *arg & 0x7ff);
  13662         SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, pgw_inst, subport, rval64));
  13663     } else {
  13664         *arg = soc_reg64_field32_get(unit, reg, rval64, field);
  13665     }
  13666     return BCM_E_NONE;
  13667 }
  13668 int
  13669 bcm_mn_cosq_control_set(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
  13670                         bcm_cosq_control_t type, int arg)
  13671 {
  13672     switch (type) {
  13673     case bcmCosqControlEgressPool:
  13674     case bcmCosqControlEgressPoolLimitBytes:
  13675     case bcmCosqControlEgressPoolYellowLimitBytes:
  13676     case bcmCosqControlEgressPoolRedLimitBytes:
  13677     case bcmCosqControlEgressPoolLimitEnable:
  13678     case bcmCosqControlUCEgressPool:
  13679     case bcmCosqControlMCEgressPool:
  13680     case bcmCosqControlEgressPoolSharedLimitBytes:
  13681     case bcmCosqControlEgressPoolResumeLimitBytes:
  13682     case bcmCosqControlEgressPoolYellowSharedLimitBytes:
  13683     case bcmCosqControlEgressPoolYellowResumeLimitBytes:
  13684     case bcmCosqControlEgressPoolRedSharedLimitBytes:
  13685     case bcmCosqControlEgressPoolRedResumeLimitBytes:
  13686         return _bcm_mn_cosq_egr_pool_set(unit, gport, cosq, type, arg);
  13687     case bcmCosqControlEfPropagation:
  13688         return _bcm_mn_cosq_ef_op(unit, gport, cosq, &arg, _BCM_COSQ_OP_SET);
  13689     case bcmCosqControlCongestionProxy:
  13690         return _bcm_mn_cosq_qcn_proxy_set(unit, gport, cosq, type, arg);
  13691     case bcmCosqControlEgressUCQueueSharedLimitBytes:
  13692     case bcmCosqControlEgressMCQueueSharedLimitBytes:
  13693     case bcmCosqControlEgressUCQueueMinLimitBytes:
  13694     case bcmCosqControlEgressMCQueueMinLimitBytes:
  13695         return _bcm_mn_cosq_egr_queue_set(unit, gport, cosq, type, arg);
  13696     case bcmCosqControlIngressPortPGSharedLimitBytes:
  13697     case bcmCosqControlIngressPortPoolMaxLimitBytes:
  13698     case bcmCosqControlIngressPortPGMinLimitBytes:
  13699     case bcmCosqControlIngressPortPoolMinLimitBytes:
  13700     case bcmCosqControlIngressPortPGHeadroomLimitBytes:
  13701     case bcmCosqControlIngressPortPGResetFloorBytes:
  13702         return _bcm_mn_cosq_ing_res_set(unit, gport, cosq, type, arg);
  13703     case bcmCosqControlIngressPoolLimitBytes:
  13704         return _bcm_mn_cosq_ing_res_limit_set(unit, gport, cosq, type, arg);
  13705     case bcmCosqControlIngressPool:
  13706         return _bcm_mn_cosq_ing_pool_set(unit, gport, cosq, type, arg);
  13707     case bcmCosqControlDropLimitAlpha:
  13708         return _bcm_mn_cosq_alpha_set(unit, gport, cosq,
  13709                             (bcm_cosq_control_drop_limit_alpha_value_t)arg);
  13710     case bcmCosqControlIngressPortPGSharedDynamicEnable:        
  13711     case bcmCosqControlEgressUCSharedDynamicEnable:
  13712     case bcmCosqControlEgressMCSharedDynamicEnable:
  13713         return _bcm_mn_cosq_dynamic_thresh_enable_set(unit, gport, cosq, 
  13714                                                        type, arg);
  13715     case bcmCosqControlEgressPortPoolYellowLimitBytes:
  13716     case bcmCosqControlEgressPortPoolRedLimitBytes:
  13717         return _bcm_mn_cosq_egr_port_pool_set(unit, gport, cosq, type, arg);
  13718     case bcmCosqControlEgressUCQueueLimitEnable:
  13719     case bcmCosqControlEgressMCQueueLimitEnable:
  13720         return _bcm_mn_cosq_egr_queue_limit_enable_set(unit, gport, cosq, type, arg);
  13721     case bcmCosqControlObmDiscardLimit:
  13722     case bcmCosqControlObmMinLimit:
  13723         return _bcm_mn_cosq_obm_threshold_set_get(unit, gport, cosq, type, &arg, 1);
  13724     default:
  13725         break;
  13726     }
  13727 
  13728     return BCM_E_UNAVAIL;
  13729 }
  13730 
  13731 int
  13732 bcm_mn_cosq_control_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
  13733                         bcm_cosq_control_t type, int *arg)
  13734 {
  13735     switch (type) {
  13736     case bcmCosqControlEgressPool:
  13737     case bcmCosqControlEgressPoolLimitBytes:
  13738     case bcmCosqControlEgressPoolYellowLimitBytes:
  13739     case bcmCosqControlEgressPoolRedLimitBytes:
  13740     case bcmCosqControlEgressPoolLimitEnable:
  13741     case bcmCosqControlUCEgressPool:
  13742     case bcmCosqControlMCEgressPool:
  13743     case bcmCosqControlEgressPoolSharedLimitBytes:
  13744     case bcmCosqControlEgressPoolResumeLimitBytes:
  13745     case bcmCosqControlEgressPoolYellowSharedLimitBytes:
  13746     case bcmCosqControlEgressPoolYellowResumeLimitBytes:
  13747     case bcmCosqControlEgressPoolRedSharedLimitBytes:
  13748     case bcmCosqControlEgressPoolRedResumeLimitBytes:
  13749         return _bcm_mn_cosq_egr_pool_get(unit, gport, cosq, type, arg);
  13750     case bcmCosqControlEfPropagation:
  13751         return _bcm_mn_cosq_ef_op(unit, gport, cosq, arg, _BCM_COSQ_OP_GET);
  13752     case bcmCosqControlEgressUCQueueSharedLimitBytes:
  13753     case bcmCosqControlEgressMCQueueSharedLimitBytes:
  13754     case bcmCosqControlEgressUCQueueMinLimitBytes:
  13755     case bcmCosqControlEgressMCQueueMinLimitBytes:
  13756         return _bcm_mn_cosq_egr_queue_get(unit, gport, cosq, type, arg);
  13757     case bcmCosqControlIngressPortPGSharedLimitBytes:
  13758     case bcmCosqControlIngressPortPoolMaxLimitBytes:
  13759     case bcmCosqControlIngressPortPGMinLimitBytes:
  13760     case bcmCosqControlIngressPortPoolMinLimitBytes:
  13761     case bcmCosqControlIngressPortPGHeadroomLimitBytes:
  13762     case bcmCosqControlIngressPortPGResetFloorBytes:
  13763         return _bcm_mn_cosq_ing_res_get(unit, gport, cosq, type, arg);
  13764     case bcmCosqControlIngressPoolLimitBytes:   
  13765         return _bcm_mn_cosq_ing_res_limit_get(unit, gport, cosq, type, arg);
  13766     case bcmCosqControlSPPortLimitState:
  13767     case bcmCosqControlPGPortLimitState:
  13768     case bcmCosqControlPGPortXoffState:
  13769     case bcmCosqControlPoolRedDropState:
  13770     case bcmCosqControlPoolYellowDropState:
  13771     case bcmCosqControlPoolGreenDropState:
  13772         return _bcm_mn_cosq_state_get(unit, gport, cosq, type, arg);
  13773     case bcmCosqControlIngressPool:
  13774         return _bcm_mn_cosq_ing_pool_get(unit, gport, cosq, type, arg);
  13775     case bcmCosqControlDropLimitAlpha:
  13776         return _bcm_mn_cosq_alpha_get(unit, gport, cosq,  
  13777                             (bcm_cosq_control_drop_limit_alpha_value_t *)arg);
  13778     case bcmCosqControlIngressPortPGSharedDynamicEnable:        
  13779     case bcmCosqControlEgressUCSharedDynamicEnable:
  13780     case bcmCosqControlEgressMCSharedDynamicEnable:
  13781         return _bcm_mn_cosq_dynamic_thresh_enable_get(unit, gport, cosq, 
  13782                                                        type, arg);
  13783     case bcmCosqControlPortQueueUcast:
  13784     case bcmCosqControlPortQueueMcast:
  13785         return _bcm_mn_cosq_port_qnum_get(unit, gport, cosq, type, arg);
  13786     case bcmCosqControlEgressPortPoolYellowLimitBytes:
  13787     case bcmCosqControlEgressPortPoolRedLimitBytes:
  13788         return _bcm_mn_cosq_egr_port_pool_get(unit, gport, cosq, type, arg);
  13789     case bcmCosqControlEgressUCQueueLimitEnable:
  13790     case bcmCosqControlEgressMCQueueLimitEnable:
  13791         return _bcm_mn_cosq_egr_queue_limit_enable_get(unit, gport, cosq, type, arg);
  13792     case bcmCosqControlCongestionProxy:
  13793         return _bcm_mn_cosq_qcn_proxy_get(unit, gport, cosq, type, arg);
  13794     case bcmCosqControlObmDiscardLimit:
  13795     case bcmCosqControlObmMinLimit:
  13796         return _bcm_mn_cosq_obm_threshold_set_get(unit, gport, cosq, type, arg, 0);
  13797     default:
  13798         break;
  13799     }
  13800 
  13801     return BCM_E_UNAVAIL;
  13802 }
  13803 
  13804 int
  13805 bcm_mn_cosq_service_pool_set(
  13806     int unit,
  13807     bcm_service_pool_id_t id,
  13808     bcm_cosq_service_pool_t cosq_service_pool)
  13809 {
  13810     uint32 rval;
  13811     soc_field_t fld_enable = INVALIDf;
  13812     static const soc_field_t color_enable_fields[] = {
  13813         PORTSP_COLOR_LIMIT_ENABLE_0f, PORTSP_COLOR_LIMIT_ENABLE_1f, 
  13814         PORTSP_COLOR_LIMIT_ENABLE_2f, PORTSP_COLOR_LIMIT_ENABLE_3f
  13815     };
  13816 
  13817     if (id < 0 || (id > _MN_NUM_SERVICE_POOL - 1)) {
  13818         return BCM_E_PARAM;
  13819     } 
  13820 
  13821     SOC_IF_ERROR_RETURN(READ_MMU_THDM_DB_DEVICE_THR_CONFIGr(unit, &rval));
  13822     switch (cosq_service_pool.type) {
  13823     case bcmCosqServicePoolPortColorAware:
  13824         fld_enable = color_enable_fields[id];
  13825         break;
  13826     default:
  13827         return BCM_E_PARAM;
  13828     }
  13829 
  13830     soc_reg_field_set(unit, MMU_THDM_DB_DEVICE_THR_CONFIGr, &rval,
  13831                       fld_enable, cosq_service_pool.enabled ? 1 : 0);
  13832     SOC_IF_ERROR_RETURN(WRITE_MMU_THDM_DB_DEVICE_THR_CONFIGr(unit, rval));
  13833     return BCM_E_NONE;
  13834 }
  13835 
  13836 
  13837 int
  13838 bcm_mn_cosq_service_pool_get(
  13839     int unit,
  13840     bcm_service_pool_id_t id,
  13841     bcm_cosq_service_pool_t *cosq_service_pool)
  13842 {
  13843     uint32 rval;
  13844     soc_field_t fld_enable = INVALIDf;
  13845     static const soc_field_t color_enable_fields[] = {
  13846         PORTSP_COLOR_LIMIT_ENABLE_0f, PORTSP_COLOR_LIMIT_ENABLE_1f, 
  13847         PORTSP_COLOR_LIMIT_ENABLE_2f, PORTSP_COLOR_LIMIT_ENABLE_3f
  13848     };
  13849 
  13850     if (cosq_service_pool == NULL) {
  13851         return BCM_E_PARAM;
  13852     }
  13853 
  13854     if (id < 0 || (id > _MN_NUM_SERVICE_POOL - 1)) {
  13855         return BCM_E_PARAM;
  13856     }
  13857 
  13858     SOC_IF_ERROR_RETURN(READ_MMU_THDM_DB_DEVICE_THR_CONFIGr(unit, &rval));
  13859     switch (cosq_service_pool->type) {
  13860     case bcmCosqServicePoolPortColorAware:
  13861         fld_enable = color_enable_fields[id];
  13862         break;
  13863     default:
  13864         return BCM_E_PARAM;
  13865     }
  13866 
  13867     cosq_service_pool->enabled = soc_reg_field_get(unit, MMU_THDM_DB_DEVICE_THR_CONFIGr, rval,
  13868                                                    fld_enable);
  13869     return BCM_E_NONE;
  13870 }
  13871 
  13872 /*
  13873  * Function:
  13874  *     bcm_mn_cosq_gport_bandwidth_set
  13875  * Purpose:
  13876  *     Configure COS queue bandwidth control
  13877  * Parameters:
  13878  *     unit   - (IN) unit number
  13879  *     gport  - (IN) GPORT identifier
  13880  *     cosq   - (IN) COS queue to configure, -1 for all COS queues
  13881  *     kbits_sec_min - (IN) minimum bandwidth, kbits/sec
  13882  *     kbits_sec_max - (IN) maximum bandwidth, kbits/sec
  13883  *     flags  - (IN) BCM_COSQ_BW_*
  13884  * Returns:
  13885  *     BCM_E_XXX
  13886  */
  13887 int
  13888 bcm_mn_cosq_gport_bandwidth_set(int unit, bcm_gport_t gport,
  13889                                 bcm_cos_queue_t cosq, uint32 kbits_sec_min,
  13890                                 uint32 kbits_sec_max, uint32 flags)
  13891 {
  13892     int i, start_cos, end_cos, local_port;
  13893     _bcm_mn_cosq_node_t *node;
  13894     uint32 burst_min, burst_max;
  13895 
  13896     if (cosq <= -1) {
  13897         if (BCM_GPORT_IS_SET(gport)) {
  13898             BCM_IF_ERROR_RETURN
  13899                 (_bcm_mn_cosq_node_get(unit, gport, 0, NULL, 
  13900                                         NULL, NULL, &node));
  13901             start_cos = 0;
  13902             if (node->numq == -1) {
  13903                 end_cos = 0;
  13904             } else {
  13905                 end_cos = node->numq - 1;
  13906             }
  13907         } else {
  13908             start_cos = 0;
  13909             end_cos = _MN_NUM_COS(unit) - 1;
  13910         }
  13911     } else {
  13912         start_cos = end_cos = cosq;
  13913     }
  13914      
  13915     if(_BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, gport)){
  13916        BCM_IF_ERROR_RETURN(
  13917         _bcmi_coe_subport_physical_port_get(unit, gport, &local_port));
  13918     }  else { 
  13919        BCM_IF_ERROR_RETURN(_bcm_mn_cosq_localport_resolve(unit, gport, &local_port));
  13920     } 
  13921     burst_min = (kbits_sec_min > 0) ?
  13922           _bcm_td_default_burst_size(unit, local_port, kbits_sec_min) : 0;
  13923 
  13924     burst_max = (kbits_sec_max > 0) ?
  13925           _bcm_td_default_burst_size(unit, local_port, kbits_sec_max) : 0;
  13926 
  13927     for (i = start_cos; i <= end_cos; i++) {
  13928         BCM_IF_ERROR_RETURN
  13929             (_bcm_mn_cosq_bucket_set(unit, gport, i, kbits_sec_min,
  13930                          kbits_sec_max, burst_min, burst_max, flags));
  13931     }
  13932 
  13933     return BCM_E_NONE;
  13934 }
  13935 
  13936 /*
  13937  * Function:
  13938  *     bcm_mn_cosq_gport_bandwidth_get
  13939  * Purpose:
  13940  *     Get COS queue bandwidth control configuration
  13941  * Parameters:
  13942  *     unit   - (IN) unit number
  13943  *     gport  - (IN) GPORT identifier
  13944  *     cosq   - (IN) COS queue to get, -1 for any COS queue
  13945  *     kbits_sec_min - (OUT) minimum bandwidth, kbits/sec
  13946  *     kbits_sec_max - (OUT) maximum bandwidth, kbits/sec
  13947  *     flags  - (OUT) BCM_COSQ_BW_*
  13948  * Returns:
  13949  *     BCM_E_XXX
  13950  */
  13951 int
  13952 bcm_mn_cosq_gport_bandwidth_get(int unit, bcm_gport_t gport,
  13953                                 bcm_cos_queue_t cosq, uint32 *kbits_sec_min,
  13954                                 uint32 *kbits_sec_max, uint32 *flags)
  13955 {
  13956     uint32 kbits_sec_burst;
  13957 
  13958     if (cosq == -1) {
  13959         return BCM_E_PARAM;
  13960     }
  13961 
  13962     BCM_IF_ERROR_RETURN
  13963         (_bcm_mn_cosq_bucket_get(unit, gport, cosq,
  13964                                  kbits_sec_min, kbits_sec_max,
  13965                                  &kbits_sec_burst, &kbits_sec_burst, flags));
  13966     return BCM_E_NONE;
  13967 }
  13968 
  13969 /*
  13970  * Function:
  13971  *     bcm_mn_cosq_gport_bandwidth_burst_set
  13972  * Purpose:
  13973  *     Configure COS queue bandwidth burst setting
  13974  * Parameters:
  13975  *      unit        - (IN) unit number
  13976  *      gport       - (IN) GPORT identifier
  13977  *      cosq        - (IN) COS queue to configure, -1 for all COS queues
  13978  *      kbits_burst - (IN) maximum burst, kbits
  13979  * Returns:
  13980  *      BCM_E_XXX
  13981  */
  13982 int
  13983 bcm_mn_cosq_gport_bandwidth_burst_set(int unit, bcm_gport_t gport,
  13984                                       bcm_cos_queue_t cosq,
  13985                                       uint32 kbits_burst_min,
  13986                                       uint32 kbits_burst_max)
  13987 {
  13988     int i, start_cos, end_cos;
  13989     uint32 kbits_sec_min = 0; 
  13990     uint32 kbits_sec_max = 0;
  13991     uint32 kbits_sec_burst = 0;
  13992     uint32 flags = 0;
  13993     _bcm_mn_cosq_node_t *node;
  13994 
  13995     if (cosq < -1) {
  13996         return BCM_E_PARAM;
  13997     }
  13998 
  13999     if (cosq == -1) {
  14000         if (BCM_GPORT_IS_SET(gport) && 
  14001              !(_BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, gport))) {
  14002             BCM_IF_ERROR_RETURN
  14003                 (_bcm_mn_cosq_node_get(unit, gport, 0, NULL, 
  14004                                         NULL, NULL, &node));
  14005             start_cos = 0;
  14006             end_cos = node->numq - 1;
  14007         } else {
  14008             start_cos = 0;
  14009             end_cos = _MN_NUM_COS(unit) - 1;
  14010         }
  14011     } else {
  14012         start_cos = end_cos = cosq;
  14013     }
  14014 
  14015     for (i = start_cos; i <= end_cos; i++) {
  14016         BCM_IF_ERROR_RETURN
  14017             (_bcm_mn_cosq_bucket_get(unit, gport, i, &kbits_sec_min,
  14018                                      &kbits_sec_max, &kbits_sec_burst,
  14019                                      &kbits_sec_burst, &flags));
  14020         BCM_IF_ERROR_RETURN
  14021             (_bcm_mn_cosq_bucket_set(unit, gport, i, kbits_sec_min,
  14022                                      kbits_sec_max, kbits_burst_min, 
  14023                                      kbits_burst_max, flags));
  14024     }
  14025 
  14026     return BCM_E_NONE;
  14027 }
  14028 
  14029 /*
  14030  * Function:
  14031  *     bcm_mn_cosq_gport_bandwidth_burst_get
  14032  * Purpose:
  14033  *     Get COS queue bandwidth burst setting
  14034  * Parameters:
  14035  *     unit        - (IN) unit number
  14036  *     gport       - (IN) GPORT identifier
  14037  *     cosq        - (IN) COS queue to get, -1 for any queue
  14038  *     kbits_burst - (OUT) maximum burst, kbits
  14039  * Returns:
  14040  *     BCM_E_XXX
  14041  */
  14042 int
  14043 bcm_mn_cosq_gport_bandwidth_burst_get(int unit, bcm_gport_t gport,
  14044                                        bcm_cos_queue_t cosq,
  14045                                        uint32 *kbits_burst_min,
  14046                                        uint32 *kbits_burst_max)
  14047 {
  14048     uint32 kbits_sec_min, kbits_sec_max, flags;
  14049 
  14050     if (cosq < -1) {
  14051         return BCM_E_PARAM;
  14052     }
  14053 
  14054     BCM_IF_ERROR_RETURN
  14055         (_bcm_mn_cosq_bucket_get(unit, gport, cosq == -1 ? 0 : cosq,
  14056                                  &kbits_sec_min, &kbits_sec_max, kbits_burst_min,
  14057                                  kbits_burst_max, &flags));
  14058 
  14059     return BCM_E_NONE;
  14060 }
  14061 
  14062 /*
  14063  * Function:
  14064  *     bcm_mn_cosq_gport_sched_set
  14065  * Purpose:
  14066  *     Configure COS queue scheduler setting
  14067  * Parameters:
  14068  *      unit   - (IN) unit number
  14069  *      gport  - (IN) GPORT identifier
  14070  *      cosq   - (IN) COS queue to configure, -1 for all COS queues
  14071  *      mode   - (IN) Scheduling mode, one of BCM_COSQ_xxx
  14072  *      weight - (IN) queue weight
  14073  * Returns:
  14074  *      BCM_E_XXX
  14075  */
  14076 int
  14077 bcm_mn_cosq_gport_sched_set(int unit, bcm_gport_t gport,
  14078                             bcm_cos_queue_t cosq, int mode, int weight)
  14079 {
  14080     int rv, numq, i, count;
  14081 
  14082     if (cosq == -1) {
  14083         BCM_IF_ERROR_RETURN
  14084             (_bcm_mn_cosq_index_resolve(unit, gport, cosq,
  14085                                         _BCM_MN_COSQ_INDEX_STYLE_SCHEDULER,
  14086                                         NULL, NULL, &numq));
  14087         cosq = 0;
  14088     } else {
  14089         numq = 1;
  14090     }
  14091 
  14092     count = 0;
  14093     for (i = 0; i < numq; i++) {
  14094         rv = _bcm_mn_cosq_sched_set(unit, gport, cosq + i, mode, weight);
  14095         if (rv == BCM_E_NOT_FOUND) {
  14096             continue;
  14097         } else if (BCM_FAILURE(rv)) {
  14098             return rv;
  14099         } else {
  14100             count++;
  14101         }
  14102     }
  14103 
  14104     return count > 0 ? BCM_E_NONE : BCM_E_NOT_FOUND;
  14105 }
  14106 
  14107 /*
  14108  * Function:
  14109  *     bcm_mn_cosq_gport_sched_get
  14110  * Purpose:
  14111  *     Get COS queue scheduler setting
  14112  * Parameters:
  14113  *     unit   - (IN) unit number
  14114  *     gport  - (IN) GPORT identifier
  14115  *     cosq   - (IN) COS queue to get, -1 for any queue
  14116  *     mode   - (OUT) Scheduling mode, one of BCM_COSQ_xxx
  14117  *     weight - (OUT) queue weight
  14118  * Returns:
  14119  *     BCM_E_XXX
  14120  */
  14121 int
  14122 bcm_mn_cosq_gport_sched_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
  14123                             int *mode, int *weight)
  14124 {
  14125     int rv, numq, i;
  14126 
  14127     if (cosq == -1) {
  14128         BCM_IF_ERROR_RETURN
  14129             (_bcm_mn_cosq_index_resolve(unit, gport, 0,
  14130                                         _BCM_MN_COSQ_INDEX_STYLE_SCHEDULER,
  14131                                         NULL, NULL, &numq));
  14132         cosq = 0;
  14133     } else {
  14134         numq = 1;
  14135     }
  14136 
  14137     for (i = 0; i < numq; i++) {
  14138         rv = _bcm_mn_cosq_sched_get(unit, gport, cosq + i, mode, weight);
  14139         if (rv == BCM_E_NOT_FOUND) {
  14140             continue;
  14141         } else {
  14142             return rv;
  14143         }
  14144     }
  14145 
  14146     return BCM_E_NOT_FOUND;
  14147 }
  14148 
  14149 /*
  14150  * Function:
  14151  *     bcm_mn_cosq_gport_discard_set
  14152  * Purpose:
  14153  *     Configure port WRED setting
  14154  * Parameters:
  14155  *     unit    - (IN) unit number
  14156  *     port    - (IN) GPORT identifier
  14157  *     cosq    - (IN) COS queue to configure, -1 for all COS queues
  14158  *     discard - (IN) discard settings
  14159  * Returns:
  14160  *     BCM_E_XXX
  14161  */
  14162 int
  14163 bcm_mn_cosq_gport_discard_set(int unit, bcm_gport_t gport,
  14164                                bcm_cos_queue_t cosq,
  14165                                bcm_cosq_gport_discard_t *discard)
  14166 {
  14167     uint32 min_thresh, max_thresh, flags = 0;
  14168     int cell_size, cell_field_max, local_port;
  14169 
  14170     /*check for valid port */
  14171     if (gport != -1) {
  14172         BCM_IF_ERROR_RETURN(_bcm_mn_cosq_localport_resolve(unit, 
  14173                                                            gport, 
  14174                                                            &local_port));
  14175         if (IS_CPU_PORT(unit, local_port) || 
  14176             IS_LB_PORT(unit, local_port) || 
  14177             IS_MACSEC_PORT(unit, local_port)) {
  14178             return BCM_E_PORT;
  14179         }
  14180     }
  14181     /* refresh_time  from 1 to 7 be set the same as default 8,so the reasonable 
  14182            range of refresh_time  is from 1 to 512 */
  14183     if (discard == NULL ||
  14184         discard->gain < 0 || discard->gain > 15 ||
  14185         discard->drop_probability < 0 || discard->drop_probability > 100 ||
  14186         discard->refresh_time <= 0 || discard->refresh_time > 512) {
  14187         return BCM_E_PARAM;
  14188     }
  14189     if ((discard->min_thresh < 0) ||
  14190         (discard->max_thresh < 0) ||
  14191         (discard->min_thresh > discard->max_thresh)) {
  14192         return BCM_E_PARAM;
  14193     }
  14194 
  14195     cell_size = _BCM_MN_BYTES_PER_CELL;
  14196     cell_field_max = AP_CELL_FIELD_MAX;
  14197 
  14198     min_thresh = discard->min_thresh;
  14199     max_thresh = discard->max_thresh;
  14200     if (discard->flags & BCM_COSQ_DISCARD_BYTES) {
  14201         /* Convert bytes to cells */
  14202         min_thresh += (cell_size - 1);
  14203         min_thresh /= cell_size;
  14204 
  14205         max_thresh += (cell_size - 1);
  14206         max_thresh /= cell_size;
  14207 
  14208         if ((min_thresh > cell_field_max) ||
  14209             (max_thresh > cell_field_max)) {
  14210             return BCM_E_PARAM;
  14211         }
  14212     } else {
  14213         /* Packet mode not supported */
  14214         return BCM_E_PARAM;
  14215     }
  14216 
  14217     /* Min equals Max is an invalid config except
  14218      * in case of default (ResetVal)
  14219      */
  14220     if ((min_thresh == max_thresh) &&
  14221         (min_thresh != AP_CELL_FIELD_MAX)) {
  14222         return BCM_E_PARAM;
  14223     }
  14224 
  14225   
  14226         BCM_IF_ERROR_RETURN
  14227             (_bcm_mn_cosq_wred_set(unit, gport, cosq, discard->flags,
  14228                                    min_thresh, max_thresh,
  14229                                    discard->drop_probability, discard->gain,
  14230                                    FALSE, flags,discard->refresh_time));
  14231 
  14232     return BCM_E_NONE;
  14233 }
  14234 
  14235 /*
  14236  * Function:
  14237  *     bcm_mn_cosq_gport_discard_get
  14238  * Purpose:
  14239  *     Get port WRED setting
  14240  * Parameters:
  14241  *     unit    - (IN) unit number
  14242  *     port    - (IN) GPORT identifier
  14243  *     cosq    - (IN) COS queue to get, -1 for any queue
  14244  *     discard - (OUT) discard settings
  14245  * Returns:
  14246  *     BCM_E_XXX
  14247  */
  14248 int
  14249 bcm_mn_cosq_gport_discard_get(int unit, bcm_gport_t gport,
  14250                               bcm_cos_queue_t cosq,
  14251                               bcm_cosq_gport_discard_t *discard)
  14252 {
  14253     uint32 min_thresh, max_thresh;
  14254     int local_port;
  14255 
  14256     /*check for valid port */
  14257     if (gport != -1) {
  14258         BCM_IF_ERROR_RETURN(_bcm_mn_cosq_localport_resolve(unit,
  14259                                                            gport,
  14260                                                            &local_port));
  14261         if (IS_CPU_PORT(unit, local_port) ||
  14262             IS_LB_PORT(unit, local_port) ||
  14263             IS_MACSEC_PORT(unit, local_port)) {
  14264             return BCM_E_PORT;
  14265         }
  14266     }
  14267     if (discard == NULL) {
  14268         return BCM_E_PARAM;
  14269     }
  14270 
  14271     BCM_IF_ERROR_RETURN
  14272         (_bcm_mn_cosq_wred_get(unit, gport, cosq == -1 ? 0 : cosq,
  14273                                &discard->flags, &min_thresh, &max_thresh,
  14274                                &discard->drop_probability, &discard->gain, 
  14275                                0,&discard->refresh_time));
  14276 
  14277     /* Convert number of cells to number of bytes */
  14278     discard->min_thresh = min_thresh * _BCM_MN_BYTES_PER_CELL;
  14279     discard->max_thresh = max_thresh * _BCM_MN_BYTES_PER_CELL;
  14280 
  14281     return BCM_E_NONE;
  14282 }
  14283 
  14284 /*
  14285  * Function:
  14286  *      bcm_mn_cosq_subport_flow_control_set
  14287  * Purpose:
  14288  *      Set a port or node (L0, L1, L2) to flow control when
  14289  *      a CoE control frame is received on a subtended port.
  14290  * Parameters:
  14291  *      unit            - (IN) Unit number.
  14292  *      subport            - (IN) Subtended port
  14293  *      sched_port      - (IN) Node (Port, L0, L1, L2) to flow control 
  14294  * Returns:
  14295  *      BCM_E_xxx
  14296  * Notes:
  14297  */
  14298 int
  14299 bcm_mn_cosq_subport_flow_control_set(
  14300     int unit, 
  14301     bcm_gport_t subport, 
  14302     bcm_gport_t sched_port)
  14303 {
  14304 #ifdef BCM_HGPROXY_COE_SUPPORT 
  14305     uint16 coe_fc_index ;
  14306     uint32 rval;
  14307     bcm_gport_t subport_id, resolved_port;
  14308     _bcm_mn_cosq_node_t *node; 
  14309     int hw_index, rv, logical_hw_index;
  14310     soc_monterey_node_lvl_e level;
  14311     subport_tag_sgpp_map_entry_t entry;
  14312     bcm_port_t phy_port, mmu_port;
  14313     soc_info_t *si;
  14314     _bcm_mn_fc_type_t fct;
  14315     int s1_level = 0;
  14316     int index = 0 ;
  14317     int cos = 0 ;
  14318 
  14319     /* Find subport id from port to index into SUBPORT_TAG_SGPP_MAP */
  14320     BCM_IF_ERROR_RETURN(_bcmi_coe_subport_tcam_idx_get(unit, subport, &subport_id));
  14321 
  14322     /* From sched_port, need to find if it's port, L0, L1, or L2 */
  14323     BCM_IF_ERROR_RETURN(_bcm_mn_cosq_node_get(unit, sched_port, 0, NULL, NULL, NULL, &node));
  14324 
  14325     BCM_IF_ERROR_RETURN
  14326     (_bcmi_coe_subport_physical_port_get(unit, subport, &resolved_port));
  14327     /* Port, L0, L1, or L2 from node */
  14328     level = node->level;
  14329 
  14330     /* index into L0, L1, or L2 */
  14331     hw_index = node->hw_index;
  14332 
  14333     /* row and column are used to index in to the FC State Table, which is 4 bits wide */
  14334 
  14335     /* Get the port associated with the passed in gport */
  14336     if (resolved_port < 0) {
  14337         return BCM_E_PORT;
  14338     }
  14339 
  14340     si = &SOC_INFO(unit);
  14341     /* Getting MMU port.  Used to disable cut through for it at the end as well as
  14342        to index into MMU_INTFI_PORT_COEFC_TB if we're setting flow control for port */
  14343     phy_port = si->port_l2p_mapping[resolved_port];
  14344     mmu_port = si->port_p2m_mapping[phy_port];
  14345     if (IS_MN_HSP_PORT( unit, resolved_port )) {
  14346      /* SC/QM L1/L2 nodes do not support FC.
  14347       * Hence, L1/L2 indices 8, 9, 18, 19 ... should not be configured
  14348       * for FC.
  14349       * similarly the last L0 of the HSP port does not support flow control
  14350       */
  14351         if (level == SOC_MONTEREY_NODE_LVL_L0) {
  14352             if ((hw_index % 5) > 3) {
  14353                  return BCM_E_PARAM;
  14354             }
  14355             cos = hw_index % 5;
  14356         } else  { 
  14357             if ((hw_index % 10) > 7) {
  14358                  return BCM_E_PARAM;
  14359             }
  14360             cos = ((hw_index % 10) % 4);
  14361         }
  14362     } else { 
  14363          cos = hw_index % 4 ;
  14364     }
  14365     switch(level) {
  14366         case SOC_MONTEREY_NODE_LVL_ROOT:
  14367             /* At the port level we have to do it a bit different since it's indexing into
  14368                MMU_INTFI_PORT_COEFC_TB, which is a 128 entry x 1 bit table with each entry signifying
  14369                an MMU Port 
  14370             */
  14371              index = hw_index; 
  14372              break;
  14373         case SOC_MONTEREY_NODE_LVL_L0:
  14374 
  14375              if (IS_MN_HSP_PORT( unit, resolved_port )) {
  14376         /* The last L0 does not support  FC and so each index in fc_st_tbl represents
  14377          * 5 l0 nodes instead of 4 the last 1 is masked by the hardware
  14378          */ 
  14379                   index = hw_index / 5;
  14380                   break;  
  14381              } else { 
  14382                  index = hw_index / 4; 
  14383              }
  14384         case SOC_MONTEREY_NODE_LVL_L1:
  14385         case SOC_MONTEREY_NODE_LVL_L2:
  14386              if (IS_MN_HSP_PORT( unit, resolved_port )) {
  14387         /* FC not supported on last two L1/L2 nodes The hardwate internally adjusts the value 
  14388          * say index 24 which for non hsp port will result in index 6 will result in 5 for HSP
  14389          */   
  14390                  index = mmu_port * 2 + 
  14391                    (((hw_index % 10) >= 4)? 1 : 0);
  14392              } else { 
  14393                 index = hw_index / 4; 
  14394              }
  14395              break; 
  14396         case SOC_MONTEREY_NODE_LVL_S1:
  14397              index = hw_index / 4; 
  14398              break; 
  14399         default:
  14400             return BCM_E_PARAM;
  14401 
  14402     }
  14403     if ( level == SOC_MONTEREY_NODE_LVL_S1) 
  14404     {
  14405          s1_level = 1;   
  14406 
  14407     }
  14408     if (level)  {
  14409         level--;/* reducing one level for S1*/
  14410     } 
  14411     /* set coe_fc_index for us to program into the register */
  14412     coe_fc_index = ((s1_level << 15) | (index << 4)| cos << 2 | (level)); 
  14413 
  14414     /* Program SUBPORT_TAG_SGPP_MAP with the subport as the index and
  14415        COE_FC_INDEX as the data */
  14416     rv = READ_SUBPORT_TAG_SGPP_MAPm(unit,
  14417              MEM_BLOCK_ANY, subport_id, &entry);
  14418     if (SOC_SUCCESS(rv)) {
  14419         soc_SUBPORT_TAG_SGPP_MAPm_field32_set(unit,
  14420                                              (uint32 *)&entry, COE_FC_INDEXf, coe_fc_index);
  14421     }
  14422     WRITE_SUBPORT_TAG_SGPP_MAPm(unit, MEM_BLOCK_ANY, subport_id, &entry);
  14423 
  14424     /* Program FC Map Table to select FC State Table (vs PFC State Table) for the node */
  14425     fct = _BCM_MN_COSQ_FC_E2ECC;
  14426 
  14427     logical_hw_index = hw_index / 4  ;
  14428 
  14429     /* To pass the proper FC STATE Table entries, we're modifying the FC MAP Table, one of its
  14430        4 indexes, with the appropriate row in the FC STATE Table. FC MAP Table at index 0
  14431        will handle the rows 0-3 of FC STATE Table, at index 1 will handle rows 4-7 of the
  14432        FC STATE Table, and so on.
  14433      
  14434        resolved_port is passed so that the function will know which pipe to use (X or Y).
  14435        fct will select FC STATE Table on the mux so that PFC STATE Table won't be selected.
  14436        logical_hw_index is passed in this first time so that a proper row index for the FC STATE Table will be selected.
  14437        node->hw_index is passed in a second time because the proper FC MAP Table index will be calculated.
  14438        node->level is passed in so that the function will know with FC MAP Table (L0, L1, L2) to use.
  14439        */
  14440     if(level != SOC_MONTEREY_NODE_LVL_ROOT) {
  14441         BCM_IF_ERROR_RETURN(_bcm_mn_map_fc_status_to_node(unit, resolved_port, fct, logical_hw_index, 
  14442                                                            0 , node->hw_index, node->level));
  14443     }
  14444 
  14445     /* Disable Cut-Through for the port specified or L0/L1/L2 node associated with it */
  14446     BCM_IF_ERROR_RETURN(READ_ASF_PORT_CFGr(unit, resolved_port, &rval));
  14447     soc_reg_field_set(unit, ASF_PORT_CFGr, &rval, UC_ASF_ENABLEf, 0);
  14448     soc_reg_field_set(unit, ASF_PORT_CFGr, &rval, MC_ASF_ENABLEf, 0);
  14449     BCM_IF_ERROR_RETURN(WRITE_ASF_PORT_CFGr(unit, resolved_port, rval));
  14450 
  14451     return BCM_E_NONE;
  14452 #else
  14453     return BCM_E_UNAVAIL;
  14454 #endif /* BCM_HGPROXY_COE_SUPPORT */
  14455 }
  14456 
  14457 int
  14458 bcm_mn_cosq_subport_flow_control_get(
  14459     int unit, 
  14460     bcm_gport_t subport, 
  14461     bcm_gport_t * sched_port)
  14462 {
  14463 #ifdef BCM_HGPROXY_COE_SUPPORT 
  14464     int  level, i;
  14465     int hw_index = 0;
  14466     uint16 coe_fc_index = 0; 
  14467     bcm_gport_t subport_id;
  14468     _bcm_mn_cosq_node_t * node;
  14469     _bcm_mn_mmu_info_t * mmu_info;
  14470     subport_tag_sgpp_map_entry_t entry;
  14471     int s1_level ; 
  14472     int index = 0;
  14473     int cos = 0 ;
  14474     int resolved_port = 0;
  14475     int mmu_port = 0;
  14476     int phy_port = 0;
  14477     soc_info_t *si;
  14478     /* Find subport id from port to index into SUBPORT_TAG_SGPP_MAP */
  14479     BCM_IF_ERROR_RETURN(_bcmi_coe_subport_tcam_idx_get(unit, subport, &subport_id));
  14480 
  14481 
  14482     BCM_IF_ERROR_RETURN(
  14483     _bcmi_coe_subport_physical_port_get(unit, subport, &resolved_port));
  14484     si = &SOC_INFO(unit);
  14485     /* Getting MMU port.  Used to disable cut through for it at the end as well as
  14486        to index into MMU_INTFI_PORT_COEFC_TB if we're setting flow control for port */
  14487     phy_port = si->port_l2p_mapping[resolved_port];
  14488     mmu_port = si->port_p2m_mapping[phy_port];
  14489     BCM_IF_ERROR_RETURN(READ_SUBPORT_TAG_SGPP_MAPm(unit,
  14490              MEM_BLOCK_ANY, subport_id, &entry));
  14491     coe_fc_index = soc_SUBPORT_TAG_SGPP_MAPm_field32_get(unit,
  14492                                              (uint32 *)&entry, COE_FC_INDEXf);
  14493 
  14494 
  14495     level = coe_fc_index & 0x3;
  14496     cos = (coe_fc_index >> 2) & 0x3;
  14497     index = (coe_fc_index >> 4) & 0x7FF; 
  14498     s1_level = (coe_fc_index >>15) ; 
  14499     if((level) || (s1_level))  { 
  14500         level++;/*This is needed as we decrement while storing*/ 
  14501     }
  14502     switch(level) {
  14503         case SOC_MONTEREY_NODE_LVL_ROOT:
  14504             /* At the port level we have to do it a bit different since it's indexing into
  14505                MMU_INTFI_PORT_COEFC_TB, which is a 128 entry x 1 bit table with each entry signifying
  14506                an MMU Port 
  14507             */
  14508              hw_index = index; 
  14509              break; 
  14510         case SOC_MONTEREY_NODE_LVL_L0:
  14511               if (IS_MN_HSP_PORT( unit, resolved_port )) {
  14512                   hw_index = index * 5 + cos ; 
  14513               } else {  
  14514                   hw_index = index * 4 + cos ; 
  14515               }
  14516               break; 
  14517         case SOC_MONTEREY_NODE_LVL_L1:
  14518         case SOC_MONTEREY_NODE_LVL_L2:
  14519         /* FC not supported on last two L1/L2 nodes The hardwate internally adjusts the value 
  14520          * say index 24 which for non hsp port will result in index 6 will result in 5 for HSP
  14521          */   
  14522               if (IS_MN_HSP_PORT( unit, resolved_port )) {
  14523                   hw_index = (mmu_port * 10) + ((index % 2)? 4: 0) + cos ; 
  14524               } else {  
  14525                   hw_index = index * 4 + cos ; 
  14526               }
  14527               break; 
  14528         case SOC_MONTEREY_NODE_LVL_S1:
  14529              hw_index = index * 4 + cos ; 
  14530             break;
  14531         /*
  14532          * COVERITY
  14533          *
  14534          * This default is unreachable but needed for some compiler. 
  14535          */ 
  14536         /* coverity[dead_error_begin] */
  14537         default:
  14538             return BCM_E_PARAM;
  14539 
  14540     }
  14541     /* calculate the hw_index */
  14542 
  14543     mmu_info = _bcm_mn_mmu_info[unit];
  14544 
  14545     if (!mmu_info) {
  14546         return BCM_E_INIT;
  14547     }
  14548 
  14549 
  14550     /* Fetch the node based upon level and hw_index */
  14551     switch(level) {
  14552         /* port, L0, and L1 are all scheduling nodes */
  14553         case SOC_MONTEREY_NODE_LVL_L0:
  14554         case SOC_MONTEREY_NODE_LVL_ROOT:
  14555         case SOC_MONTEREY_NODE_LVL_L1:
  14556         case SOC_MONTEREY_NODE_LVL_S1:
  14557             for(i = 0; i < _BCM_MN_NUM_TOTAL_SCHEDULERS; i++) {
  14558                 node = &mmu_info->sched_node[i];
  14559                 if(node->level == level) {
  14560                     if(node->hw_index == hw_index) {
  14561                        *sched_port = node->gport;
  14562                        return BCM_E_NONE;
  14563                     }
  14564                 }
  14565             }
  14566             break;
  14567         case SOC_MONTEREY_NODE_LVL_L2:
  14568             for(i = 0; i < _BCM_MN_NUM_L2_UC_LEAVES; i++) {
  14569                 node = &mmu_info->queue_node[i];
  14570                 if(node->level == level) {
  14571                     if(node->hw_index == hw_index) {
  14572                        *sched_port = node->gport;
  14573                        return BCM_E_NONE;
  14574                     }
  14575                 }
  14576             }
  14577             break;
  14578         /* Intentional process */
  14579         /* coverity[dead_error_begin] */
  14580         default:
  14581             return BCM_E_PARAM;
  14582     }
  14583     /* not found */
  14584     return BCM_E_PARAM;
  14585 #else
  14586     return BCM_E_UNAVAIL;
  14587 #endif /* BCM_HGPROXY_COE_SUPPORT */
  14588 }
  14589 
  14590 int
  14591 _bcm_mn_cosq_port_safc_get(int unit, bcm_port_t port,
  14592                          int cur_class,
  14593                          bcm_gport_t *gport, int gport_count,
  14594                          int *actual_gport_count)
  14595 {
  14596     _bcm_mn_cosq_node_t *node;
  14597     bcm_port_t local_port;
  14598     int   hw_cosq, count = 0;
  14599     uint32 profile_index;
  14600     uint64 rval64[16], *rval64s[1], rval, index_map;
  14601     uint32 tmp32, bmp;
  14602     _bcm_mn_mmu_info_t *mmu_info;
  14603     int phy_port, mmu_port;
  14604     soc_info_t *si;
  14605     soc_reg_t   reg;
  14606     int mc_index = 0;
  14607     int mcq_offset = 0; 
  14608     _bcm_mn_pipe_resources_t *res;
  14609     _bcm_mn_cosq_port_info_t *port_info;
  14610     static const soc_reg_t llfc_cfgr[] = {
  14611         PORT_PFC_CFG0r, PORT_PFC_CFG1r, PORT_PFC_CFG2r
  14612     };
  14613     static const soc_field_t self[] = {
  14614         SEL0f, SEL1f, SEL2f, SEL3f
  14615     };
  14616     int j, inv_mapped, hw_index, eindex;
  14617     soc_mem_t mem;
  14618     uint32 map_entry[SOC_MAX_MEM_WORDS];
  14619 
  14620 
  14621     if (gport == NULL || gport_count <= 0 || actual_gport_count == NULL) {
  14622         return BCM_E_PARAM;
  14623     }
  14624 
  14625     BCM_IF_ERROR_RETURN
  14626         (_bcm_mn_cosq_localport_resolve(unit, port, &local_port));
  14627 
  14628 
  14629     si = &SOC_INFO(unit);
  14630     mmu_info = _bcm_mn_mmu_info[unit];
  14631     res = _BCM_MN_PRESOURCES(mmu_info, 0);
  14632     phy_port = si->port_l2p_mapping[local_port];
  14633     mmu_port = si->port_p2m_mapping[phy_port];
  14634     port_info = &mmu_info->port_info[local_port];
  14635 
  14636     rval64s[0] = rval64;
  14637     reg = llfc_cfgr[mmu_port/32];
  14638     BCM_IF_ERROR_RETURN(soc_reg64_get(unit, reg, REG_PORT_ANY, 0, &rval));
  14639 
  14640     index_map = soc_reg64_field_get(unit, reg, rval, PROFILE_INDEXf);
  14641     COMPILER_64_SHR(index_map, ((mmu_port % 32) * 2));
  14642     COMPILER_64_TO_32_LO(tmp32, index_map);
  14643     profile_index = (tmp32 & 3)*16;
  14644 
  14645     BCM_IF_ERROR_RETURN
  14646         (soc_profile_reg_get(unit, _bcm_mn_llfc_profile[unit],
  14647                              profile_index, 16, rval64s));
  14648 
  14649     bmp = soc_reg64_field32_get(unit, PRIO2COS_PROFILEr, rval64[cur_class],
  14650                                 COS_BMPf);
  14651     for (hw_cosq = 0; hw_cosq < _BCM_MN_NUM_SAFC_CLASS ; hw_cosq++) {
  14652         if (!(bmp & (1 << hw_cosq))) {
  14653             continue;
  14654         }
  14655         if (_bcm_mn_cosq_port_has_ets(unit, local_port)) {
  14656             inv_mapped = 0;
  14657             for (j = _BCM_MN_NUM_PORT_SCHEDULERS; 
  14658                  j < _BCM_MN_NUM_TOTAL_SCHEDULERS; j++) {
  14659                 node = &mmu_info->sched_node[j];
  14660                 if ((!node->in_use) || (node->local_port != local_port) ||
  14661                     (node->hw_cosq != hw_cosq)) {
  14662                     continue;
  14663                 }
  14664 
  14665                 hw_index = (node->hw_index / 16);
  14666                 eindex = (node->hw_index % 16)/4;
  14667                 if (node->level == SOC_MONTEREY_NODE_LVL_L0) {
  14668                     mem = MMU_INTFI_XPIPE_FC_MAP_TBL0m;
  14669                 } else if (node->level == SOC_MONTEREY_NODE_LVL_L1) {
  14670                     mem = MMU_INTFI_XPIPE_FC_MAP_TBL1m;
  14671                 } else {
  14672                     continue;
  14673                 }
  14674 
  14675                 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, 
  14676                         MEM_BLOCK_ALL, hw_index, &map_entry));
  14677                  /* coverity[overrun-local : FALSE] */
  14678                 if (soc_mem_field32_get(unit, mem, &map_entry, self[eindex])) {
  14679                     if (gport_count > 0) {
  14680                         gport[count] = node->gport;
  14681                     }
  14682                     count++;
  14683                     if ((count == gport_count) && (gport_count > 0)) {
  14684                          inv_mapped = 1;
  14685                          break;
  14686                     }
  14687                 }
  14688             }
  14689 
  14690             for (j = port_info->uc_base; 
  14691                  inv_mapped==0 && (j < port_info->uc_limit); j++) {
  14692                 node = &res->p_queue_node[j];
  14693                 if ((!node->in_use) || (node->local_port != local_port)) {
  14694                     continue;
  14695                 }
  14696                 if (node->hw_cosq != hw_cosq) {
  14697                     continue;
  14698                 }
  14699                 mem =   MMU_INTFI_XPIPE_FC_MAP_TBL2m ;
  14700                 hw_index = (node->hw_index / 16);
  14701                 eindex = (node->hw_index % 16)/4;
  14702                 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, 
  14703                         MEM_BLOCK_ALL, hw_index, &map_entry));
  14704 
  14705                  /* coverity[overrun-local : FALSE] */
  14706                 if (soc_mem_field32_get(unit, mem, &map_entry, self[eindex])) {
  14707                     if (gport_count > 0) {
  14708                         gport[count] = node->gport;
  14709                     }
  14710                     count++;
  14711                     if ((count == gport_count) && (gport_count > 0)) {
  14712                          inv_mapped = 1;
  14713                          break;
  14714                     }
  14715                 }
  14716             }
  14717             for (j = port_info->mc_base; 
  14718                  inv_mapped==0 && (j < port_info->mc_limit); j++) {
  14719                 mc_index = soc_monterey_l2_hw_index(unit, j, 0);
  14720                 node = &res->p_queue_node[mc_index];
  14721                 if ((!node->in_use) || (node->local_port != local_port)) {
  14722                     continue;
  14723                 }
  14724                 if (node->hw_cosq != hw_cosq) {
  14725                     continue;
  14726                 }
  14727                 mem =   MMU_INTFI_XPIPE_FC_MAP_TBL2m ;
  14728                 mcq_offset = node->hw_index % _BCM_MN_NUM_L2_UC_LEAVES_PER_PIPE;
  14729                 if (((mcq_offset % 10) > 7) ) {
  14730                      /* FC support only for Q0-7 */
  14731                       continue; 
  14732                 }
  14733                 hw_index = node->hw_index - (mcq_offset * 2 / 10);
  14734                 hw_index /= 16;
  14735                 eindex = (mcq_offset % 10)/4;
  14736                 eindex += ((mcq_offset /10) % 2) ? 0 : 2;
  14737                 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, 
  14738                         MEM_BLOCK_ALL, hw_index, &map_entry));
  14739 
  14740                  /* coverity[overrun-local : FALSE] */
  14741                 if (soc_mem_field32_get(unit, mem, &map_entry, self[eindex])) {
  14742                     if (gport_count > 0) {
  14743                         gport[count] = node->gport;
  14744                     }
  14745                     count++;
  14746                     if ((count == gport_count) && (gport_count > 0)) {
  14747                          break;
  14748                     }
  14749                 }
  14750             }
  14751         } else {
  14752             if (gport_count > 0) {
  14753                 gport[count++] = hw_cosq;
  14754             } 
  14755         }
  14756         if (count == gport_count) {
  14757             break;
  14758         }
  14759     }
  14760 
  14761     if (count == 0) {
  14762         return BCM_E_NOT_FOUND;
  14763     }
  14764     *actual_gport_count = count;
  14765     return BCM_E_NONE;
  14766 }
  14767 
  14768 
  14769 /*
  14770  * Function:
  14771  *     bcm_mn_cosq_safc_class_mapping_set
  14772  * Purpose:
  14773  *     Set SAFC mapping for port.
  14774  *     SAFC class is mapped to cosq or scheduler node gports.
  14775  * Parameters:
  14776  *     unit             - (IN) unit number
  14777  *     port             - (IN) port number
  14778  *     array_count      - (IN) count of mapping
  14779  *     mapping_array    - (IN) mappings
  14780  * Returns:
  14781  *     BCM_E_XXX
  14782  */
  14783 int
  14784 _bcm_mn_cosq_safc_class_mapping_set(int unit, bcm_gport_t port,
  14785                                    int array_count,
  14786                                    bcm_cosq_safc_class_mapping_t *mapping_array)
  14787 {
  14788     int index, count;
  14789     int cur_class = 0;
  14790     int safc_class[_BCM_MN_NUM_SAFC_CLASS];
  14791     bcm_gport_t cur_gport = 0;
  14792     uint32 cos_bmp[_BCM_MN_NUM_SAFC_CLASS] = {0};
  14793     bcm_port_t local_port = -1;
  14794 
  14795     BCM_IF_ERROR_RETURN
  14796         (_bcm_mn_cosq_localport_resolve(unit, port, &local_port));
  14797 
  14798     if (local_port < 0) {
  14799         return BCM_E_PORT;
  14800     }
  14801 
  14802     if (IS_CPU_PORT(unit, local_port)) {
  14803         return BCM_E_PARAM;
  14804     }
  14805 
  14806     if ((array_count < 0) || (array_count > _BCM_MN_NUM_SAFC_CLASS)) {
  14807         return BCM_E_PARAM;
  14808     }
  14809 
  14810     if (mapping_array == NULL) {
  14811         return BCM_E_PARAM;
  14812     }
  14813     if (!IS_HG_PORT(unit, local_port)) {
  14814         return BCM_E_PARAM;
  14815     } 
  14816 
  14817     for (count = 0; count < array_count; count++) {
  14818         cur_class = mapping_array[count].class_id;
  14819         if ((cur_class < 0) || (cur_class >= _BCM_MN_NUM_SAFC_CLASS)) {
  14820             return BCM_E_PARAM;
  14821         } else {
  14822            cos_bmp[cur_class] = 0;
  14823         }
  14824 
  14825         for (index = 0; index < BCM_COSQ_SAFC_GPORT_COUNT; index++) {
  14826             cur_gport = mapping_array[count].gport_list[index];
  14827             if (cur_gport == BCM_GPORT_INVALID) {
  14828                 break;
  14829             }
  14830 
  14831             if ((BCM_GPORT_IS_UCAST_QUEUE_GROUP(cur_gport)) ||
  14832                 (BCM_GPORT_IS_MCAST_QUEUE_GROUP(cur_gport))) {
  14833                 BCM_IF_ERROR_RETURN
  14834                     (_bcm_mn_fc_status_map_gport(unit, local_port, cur_gport,
  14835                                                  _BCM_MN_COSQ_FC_SAFC, 
  14836                                                  &cos_bmp[cur_class]));
  14837             } else {
  14838                 return BCM_E_PARAM;
  14839             }
  14840         }
  14841     }
  14842 
  14843     for (index = 0; index < _BCM_MN_NUM_SAFC_CLASS; index++) {
  14844         safc_class[index] = index;
  14845     }
  14846     BCM_IF_ERROR_RETURN(_bcm_mn_port_fc_profile_set(unit, local_port,
  14847         _BCM_COSQ_OP_SET, _BCM_MN_NUM_SAFC_CLASS, safc_class, cos_bmp));
  14848 
  14849     return BCM_E_NONE;
  14850 }
  14851 
  14852 /*
  14853  * Function:
  14854  *     bcm_mn_cosq_safc_class_mapping_get
  14855  * Purpose:
  14856  *     Get SAFC mapping for port.
  14857  *     Retrieves cosq or scheduler node gports
  14858  *     associated to SAFC classes.
  14859  * Parameters:
  14860  *     unit             - (IN) unit number
  14861  *     port             - (IN) port number
  14862  *     array_max        - (IN) max retrieve count
  14863  *     mapping_array    - (OUT) mappings
  14864  *     array_count      - (OUT) retrieved mapping count
  14865  * Returns:
  14866  *     BCM_E_XXX
  14867  */
  14868 int
  14869 _bcm_mn_cosq_safc_class_mapping_get(int unit, bcm_gport_t port,
  14870                                    int array_max,
  14871                                    bcm_cosq_safc_class_mapping_t *mapping_array,
  14872                                    int *array_count)
  14873 {
  14874     int rv = 0;
  14875     int cur_class = 0;
  14876     int actual_gport_count, class_count = 0;
  14877     bcm_port_t local_port = -1;
  14878 
  14879     BCM_IF_ERROR_RETURN
  14880         (_bcm_mn_cosq_localport_resolve(unit, port, &local_port));
  14881 
  14882     if (local_port < 0) {
  14883         return BCM_E_PORT;
  14884     }
  14885 
  14886     if (IS_CPU_PORT(unit, local_port)) {
  14887         return BCM_E_PARAM;
  14888     }
  14889     if (!IS_HG_PORT(unit, local_port)) {
  14890         return BCM_E_PARAM;
  14891     }
  14892 
  14893     if (((mapping_array == NULL) && (array_max > 0)) ||
  14894         ((mapping_array != NULL) && (array_max <= 0)) ||
  14895         (array_count == NULL)) {
  14896         return BCM_E_PARAM;
  14897     }
  14898 
  14899     if (array_max <= 0) {
  14900         *array_count = _BCM_MN_NUM_SAFC_CLASS;
  14901         return BCM_E_NONE;
  14902     }
  14903 
  14904     for (cur_class = 0; cur_class < _BCM_MN_NUM_SAFC_CLASS; cur_class++) {
  14905         actual_gport_count = 0;
  14906         rv = _bcm_mn_cosq_port_safc_get(unit, port, cur_class,
  14907                         mapping_array[cur_class].gport_list,
  14908                         BCM_COSQ_SAFC_GPORT_COUNT, &actual_gport_count);
  14909 
  14910         if (rv == BCM_E_NONE) {
  14911             mapping_array[cur_class].class_id = cur_class;
  14912             if (actual_gport_count < BCM_COSQ_SAFC_GPORT_COUNT) {
  14913                 mapping_array[cur_class].gport_list[actual_gport_count] =
  14914                                                         BCM_GPORT_INVALID;
  14915             }
  14916             class_count++;
  14917         } else if (rv == BCM_E_NOT_FOUND) {
  14918             return rv;
  14919         }
  14920 
  14921         if (class_count == array_max) {
  14922             break;
  14923         }
  14924     }
  14925 
  14926     *array_count = class_count;
  14927     if (class_count == 0) {
  14928         return BCM_E_NOT_FOUND;
  14929     }
  14930 
  14931     return BCM_E_NONE;
  14932 }
  14933 
  14934 int
  14935 _bcm_mn_cosq_pfc_class_resolve(bcm_switch_control_t sctype, int *type,
  14936                                int *class)
  14937 {
  14938     switch (sctype) {
  14939     case bcmSwitchPFCClass7Queue:
  14940     case bcmSwitchPFCClass6Queue:
  14941     case bcmSwitchPFCClass5Queue:
  14942     case bcmSwitchPFCClass4Queue:
  14943     case bcmSwitchPFCClass3Queue:
  14944     case bcmSwitchPFCClass2Queue:
  14945     case bcmSwitchPFCClass1Queue:
  14946     case bcmSwitchPFCClass0Queue:
  14947         *type = _BCM_MN_COSQ_TYPE_UCAST;
  14948         break;
  14949     case bcmSwitchPFCClass7McastQueue:
  14950     case bcmSwitchPFCClass6McastQueue:
  14951     case bcmSwitchPFCClass5McastQueue:
  14952     case bcmSwitchPFCClass4McastQueue:
  14953     case bcmSwitchPFCClass3McastQueue:
  14954     case bcmSwitchPFCClass2McastQueue:
  14955     case bcmSwitchPFCClass1McastQueue:
  14956     case bcmSwitchPFCClass0McastQueue:
  14957         *type = _BCM_MN_COSQ_TYPE_MCAST;
  14958         break;
  14959     case bcmSwitchPFCClass7DestmodQueue:
  14960     case bcmSwitchPFCClass6DestmodQueue:
  14961     case bcmSwitchPFCClass5DestmodQueue:
  14962     case bcmSwitchPFCClass4DestmodQueue:
  14963     case bcmSwitchPFCClass3DestmodQueue:
  14964     case bcmSwitchPFCClass2DestmodQueue:
  14965     case bcmSwitchPFCClass1DestmodQueue:
  14966     case bcmSwitchPFCClass0DestmodQueue:
  14967         *type = _BCM_MN_COSQ_TYPE_EXT_UCAST;
  14968         break;
  14969     default:
  14970         return BCM_E_PARAM;
  14971     }
  14972 
  14973     switch (sctype) {
  14974     case bcmSwitchPFCClass7Queue:
  14975     case bcmSwitchPFCClass7McastQueue:
  14976     case bcmSwitchPFCClass7DestmodQueue:
  14977         *class = 7;
  14978         break;
  14979     case bcmSwitchPFCClass6Queue:
  14980     case bcmSwitchPFCClass6McastQueue:
  14981     case bcmSwitchPFCClass6DestmodQueue:
  14982         *class = 6;
  14983         break;
  14984     case bcmSwitchPFCClass5Queue:
  14985     case bcmSwitchPFCClass5McastQueue:
  14986     case bcmSwitchPFCClass5DestmodQueue:
  14987         *class = 5;
  14988         break;
  14989     case bcmSwitchPFCClass4Queue:
  14990     case bcmSwitchPFCClass4McastQueue:
  14991     case bcmSwitchPFCClass4DestmodQueue:
  14992         *class = 4;
  14993         break;
  14994     case bcmSwitchPFCClass3Queue:
  14995     case bcmSwitchPFCClass3McastQueue:
  14996     case bcmSwitchPFCClass3DestmodQueue:
  14997         *class = 3;
  14998         break;
  14999     case bcmSwitchPFCClass2Queue:
  15000     case bcmSwitchPFCClass2McastQueue:
  15001     case bcmSwitchPFCClass2DestmodQueue:
  15002         *class = 2;
  15003         break;
  15004     case bcmSwitchPFCClass1Queue:
  15005     case bcmSwitchPFCClass1McastQueue:
  15006     case bcmSwitchPFCClass1DestmodQueue:
  15007         *class = 1;
  15008         break;
  15009     case bcmSwitchPFCClass0Queue:
  15010     case bcmSwitchPFCClass0McastQueue:
  15011     case bcmSwitchPFCClass0DestmodQueue:
  15012         *class = 0;
  15013         break;
  15014     /*
  15015      * COVERITY
  15016      *
  15017      * This default is unreachable but needed for some compiler. 
  15018      */ 
  15019     /* coverity[dead_error_begin] */
  15020     default:
  15021         return BCM_E_INTERNAL;
  15022     }
  15023     return BCM_E_NONE;
  15024 }
  15025 
  15026 STATIC int
  15027 _bcm_mn_clear_fc_status_to_node(int unit, int port)
  15028 { 
  15029     uint32 map_entry[SOC_MAX_MEM_WORDS];
  15030     static const soc_field_t self[]={
  15031         SEL0f, SEL1f, SEL2f, SEL3f
  15032     };
  15033     static const soc_field_t indexf[] = {
  15034         INDEX0f, INDEX1f, INDEX2f, INDEX3f
  15035     };
  15036     static const soc_mem_t memx[] = {
  15037         MMU_INTFI_XPIPE_FC_MAP_TBS1m,
  15038         MMU_INTFI_XPIPE_FC_MAP_TBL0m,
  15039         MMU_INTFI_XPIPE_FC_MAP_TBL1m,
  15040         MMU_INTFI_XPIPE_FC_MAP_TBL2m
  15041     };
  15042     uint32 s_value, i_value;
  15043     int base, table, index, count, field;
  15044     int mmu_port, phy_port, update;
  15045 
  15046     soc_info_t *soc_info;
  15047     soc_info = &SOC_INFO(unit);
  15048 
  15049     phy_port = soc_info->port_l2p_mapping[port];
  15050     mmu_port = soc_info->port_p2m_mapping[phy_port];
  15051     base = mmu_port * 4;
  15052     for (table = 0; table < COUNTOF(memx); table++){
  15053         count = soc_mem_index_count(unit, memx[table]);
  15054         for (index = 0; index < count; index++){
  15055             update = 0;
  15056             SOC_IF_ERROR_RETURN(soc_mem_read(unit, memx[table],
  15057                     MEM_BLOCK_ALL, index, &map_entry));         
  15058             for (field = 0; field  <  COUNTOF(indexf); field++){
  15059                 s_value =  soc_mem_field32_get(unit, memx[table],
  15060                                     &map_entry, self[field]);
  15061                 i_value =  soc_mem_field32_get(unit, memx[table],
  15062                                     &map_entry, indexf[field]);
  15063 
  15064                 if (s_value && (i_value >= base) && (i_value < (base + 4))) {
  15065                     soc_mem_field32_set(unit, memx[table],
  15066                                         &map_entry, self[field], 0);
  15067                     soc_mem_field32_set(unit, memx[table],
  15068                                         &map_entry, indexf[field], 0);
  15069                     update = 1;
  15070                 }
  15071             }
  15072             if (update){
  15073                 SOC_IF_ERROR_RETURN(soc_mem_write(unit, memx[table],
  15074                         MEM_BLOCK_ALL, index, &map_entry));
  15075             }
  15076         }    
  15077     }
  15078     return BCM_E_NONE;
  15079 }
  15080 
  15081 
  15082 STATIC int
  15083 _bcm_mn_map_fc_status_to_node(int unit, int port, _bcm_mn_fc_type_t fct,
  15084                     int spad_offset, int cosq, uint32 hw_index, int level)
  15085 {
  15086     int map_entry_index, eindex, pfc;
  15087     uint32 map_entry[SOC_MAX_MEM_WORDS];
  15088     static const soc_field_t self[] = {
  15089         SEL0f, SEL1f, SEL2f, SEL3f
  15090     };
  15091     static const soc_field_t indexf[] = {
  15092         INDEX0f, INDEX1f, INDEX2f, INDEX3f
  15093     };
  15094     static const soc_mem_t memx[] = {
  15095         INVALIDm,
  15096         MMU_INTFI_XPIPE_FC_MAP_TBS1m,
  15097         MMU_INTFI_XPIPE_FC_MAP_TBL0m,
  15098         MMU_INTFI_XPIPE_FC_MAP_TBL1m,
  15099         MMU_INTFI_XPIPE_FC_MAP_TBL2m
  15100     };
  15101     soc_mem_t mem;
  15102     int port_num = 0;
  15103     int map_entry_index_num = 0;
  15104     
  15105     if ((fct == _BCM_MN_COSQ_FC_PFC) ||
  15106         (fct == _BCM_MN_COSQ_FC_SAFC)) {
  15107         pfc = 1;
  15108     } else {
  15109         pfc = 0;
  15110     }
  15111     mem =  memx[level]; 
  15112     if (mem ==  INVALIDm) {
  15113         return BCM_E_PARAM;
  15114     }
  15115     
  15116     /* FC_MAP_TBL[Level] has 4 Index[0-3], whose values become Index to PFC_ST_TBL.
  15117      * Each Index of PFC_ST_TBL can point to congestion state of 4 Qs. 
  15118      * Hence each Entry of FC_MAP_TBL can refer to 16 Qs.
  15119      *
  15120      * NOTE: Index of FC_MAP_TBL CANNOT be used to point to Qs/Nodes belonging
  15121      *       to Different Ports.
  15122      */
  15123     if (hw_index < _BCM_MN_NUM_L2_UC_LEAVES_PER_PIPE ) {
  15124         /* UC queue */
  15125         if (IS_MN_HSP_PORT( unit, port )) {
  15126             if (level == SOC_MONTEREY_NODE_LVL_L0) {
  15127                 /* SC/QM L0 nodes do not support FC.
  15128                  * Hence, L0 indices 4, 9, 14, 19 ... should not be configured
  15129                  * for FC.
  15130                  */
  15131                 if ((hw_index % 5) > 3) {
  15132                     return BCM_E_PARAM;
  15133                 }
  15134                 /* Since 5th L0 index is not FC mapped, each Entry of
  15135                  * FC_MAP_TBL can refer to 20 L0 nodes with each field mapped
  15136                  * to first 4 L0 of each port.
  15137                  */
  15138                 map_entry_index = hw_index / 20;
  15139                 eindex = (hw_index % 20) / 5;
  15140             } else {
  15141                 /* SC/QM L1/L2 nodes do not support FC.
  15142                  * Hence, L1/L2 indices 8, 9, 18, 19 ... should not be configured
  15143                  * for FC.
  15144                  */
  15145                 if ((hw_index % 10) > 7) {
  15146                     return BCM_E_PARAM;
  15147                 }
  15148                 /* A 2 bit shift occurs in HW for HSP ports to align with multiple of 8.
  15149                  * Thus 10-17 becomes 8-15, etc.
  15150                  */
  15151                 port_num = hw_index / 10;
  15152                 map_entry_index_num = port_num * 2 + (((hw_index % 10) >= 4)? 1 : 0);
  15153                 map_entry_index = map_entry_index_num / 4; /* each entry contains 4 indexes */
  15154                 eindex = map_entry_index_num & 0x3;
  15155             }
  15156         } else {
  15157             map_entry_index = hw_index/16;
  15158             eindex = (hw_index % 16) / 4;
  15159         }
  15160     } else {
  15161         /* MC queue - Index Calculation
  15162          *   PFC can work only on 8 out of 10 MC queues of each port.
  15163          *   So in FC_MAP_TBL2, each Port will use only 2 Index(4 Qs each) for
  15164          *   MC Qs.
  15165          *   MC queue base starts at 16384, 16384/16 =  1024
  15166          *   Hence MC Qs starts at = Map_Tbl2_Idx[92] and Index2.
  15167          */
  15168         int mcq_offset = hw_index % _BCM_MN_NUM_L2_UC_LEAVES_PER_PIPE;
  15169 
  15170         if (((mcq_offset % 10) > 7) || (level != SOC_MONTEREY_NODE_LVL_L2)) {
  15171             /* FC support only for Q0-7 */
  15172             return BCM_E_INTERNAL;
  15173         }
  15174         map_entry_index = hw_index - (mcq_offset * 2 / 10);
  15175         map_entry_index /= 16;
  15176         eindex = (mcq_offset % 10)/4;
  15177         eindex += ((mcq_offset /10) % 2) ? 0 : 2;
  15178 
  15179     }
  15180     BCM_IF_ERROR_RETURN
  15181         (soc_mem_read(unit, mem, MEM_BLOCK_ALL, map_entry_index, &map_entry));
  15182     /* coverity[overrun-local : FALSE] */
  15183     soc_mem_field32_set(unit, mem, &map_entry, 
  15184                         indexf[eindex], spad_offset + cosq/4);
  15185     /* coverity[overrun-local : FALSE] */
  15186     soc_mem_field32_set(unit, mem, &map_entry, self[eindex], !!pfc);
  15187     BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem,
  15188                         MEM_BLOCK_ALL, map_entry_index, &map_entry));
  15189     return BCM_E_NONE;
  15190 }
  15191 
  15192 
  15193 /*
  15194  * Function:
  15195  *     _bcm_mn_fc_status_map_gport
  15196  * Purpose:
  15197  *     Set mapping in FC_MAP_TBL for gport, and update cos_bmp with gport cosq.
  15198  * Parameters:
  15199  *     unit       - (IN) unit number
  15200  *     port       - (IN) port number
  15201  *     gport      - (IN) gport to be mapped
  15202  *     fct        - (IN) FC type 
  15203  *     cos_map    - (OUT) hw_cosq of gport
  15204  * Returns:
  15205  *     BCM_E_XXX
  15206  */
  15207 STATIC int
  15208 _bcm_mn_fc_status_map_gport(int unit, int port, 
  15209                 bcm_gport_t gport, _bcm_mn_fc_type_t fct, uint32 *cos_bmp)
  15210 {
  15211     int hw_index, hw_index1;
  15212     int hw_cosq, hw_cosq1;
  15213     int id, lvl;
  15214     int pipe, mmu_port, phy_port;
  15215     bcm_port_t local_port, resolved_port;
  15216     _bcm_mn_cosq_node_t *node;
  15217     _bcm_mn_pipe_resources_t *res;
  15218     _bcm_mn_cosq_port_info_t *port_info;
  15219     soc_info_t *si;
  15220     _bcm_mn_mmu_info_t *mmu_info;
  15221 
  15222     BCM_IF_ERROR_RETURN
  15223         (_bcm_mn_cosq_localport_resolve(unit, port, &local_port));
  15224 
  15225     si = &SOC_INFO(unit);
  15226     phy_port = si->port_l2p_mapping[local_port];
  15227     mmu_port = si->port_p2m_mapping[phy_port];
  15228 
  15229     mmu_info = _bcm_mn_mmu_info[unit];
  15230     port_info = &mmu_info->port_info[local_port];
  15231     pipe = _BCM_MN_PORT_TO_PIPE(unit, local_port);
  15232     res = _BCM_MN_PRESOURCES(mmu_info, pipe);
  15233     
  15234     hw_index = hw_index1 = -1;
  15235     hw_cosq = hw_cosq1 = -1;
  15236     if (BCM_GPORT_IS_SET(gport)) {
  15237         BCM_IF_ERROR_RETURN(_bcm_mn_cosq_node_get(unit, gport, 
  15238                             0, NULL, &resolved_port, &id, &node));
  15239         hw_index = node->hw_index;
  15240         hw_cosq = node->hw_cosq;
  15241         lvl = node->level;
  15242     } else {
  15243         if (_bcm_mn_cosq_port_has_ets(unit, local_port)) {
  15244             hw_cosq = gport;
  15245             node = &res->p_queue_node[port_info->uc_base + hw_cosq];
  15246             hw_index = node->hw_index;
  15247             node = &res->p_mc_queue_node[port_info->mc_base + hw_cosq];
  15248             hw_index1 = node->hw_index;
  15249             hw_cosq1 = hw_cosq;
  15250             lvl = SOC_MONTEREY_NODE_LVL_L2;
  15251         } else {
  15252             lvl = SOC_MONTEREY_NODE_LVL_L1;
  15253             /* gport[] represnts the physical Cos value */
  15254             hw_cosq = gport;
  15255             BCM_IF_ERROR_RETURN(soc_monterey_sched_hw_index_get(unit, local_port, 
  15256                                 SOC_MONTEREY_NODE_LVL_L1, hw_cosq, &hw_index));
  15257         }
  15258     }
  15259     BCM_IF_ERROR_RETURN(
  15260         _bcm_mn_map_fc_status_to_node(unit, local_port, fct,
  15261                                        mmu_port*4, hw_cosq, hw_index, lvl));
  15262     if (cos_bmp != NULL) {
  15263         *cos_bmp |= 1 << hw_cosq;
  15264     }
  15265     if (hw_cosq1 >= 0) {
  15266         BCM_IF_ERROR_RETURN(
  15267             _bcm_mn_map_fc_status_to_node(unit, local_port, fct,
  15268                                        mmu_port*4, hw_cosq1, hw_index1, lvl));
  15269         if (cos_bmp != NULL) {
  15270             *cos_bmp |= 1 << hw_cosq1;
  15271         }
  15272     }
  15273 
  15274     return BCM_E_NONE;
  15275 }
  15276 
  15277 
  15278 /*
  15279  * Function:
  15280  *     _bcm_mn_port_fc_profile_set
  15281  * Purpose:
  15282  *     Set PFC mapping profile for port. Updates PRIO2COS_PROFILE & PORT_PFC_CFG.
  15283  * Parameters:
  15284  *     unit       - (IN) unit number
  15285  *     port       - (IN) port number
  15286  *     op         - (IN) operation type
  15287  *     entry_cnt  - (IN) count of bmp 
  15288  *     pfc_class  - (IN) class list
  15289  *     cos_bmp    - (IN) bmp list
  15290  * Returns:
  15291  *     BCM_E_XXX
  15292  */
  15293 STATIC int
  15294 _bcm_mn_port_fc_profile_set(int unit, int port, _bcm_cosq_op_t op,
  15295                               int entry_cnt, int *pfc_class, uint32 *cos_bmp)
  15296 {
  15297     soc_reg_t   reg;
  15298     bcm_port_t local_port;
  15299     int rv, entry, cur_class;
  15300     int mmu_port, phy_port;
  15301     uint32 profile_index, old_profile_index;
  15302     uint32 fval, tmp32, cur_bmp;
  15303     uint64 rval64[16], tmp, *rval64s[1], rval, index_map;
  15304     soc_info_t *si;
  15305     static const soc_reg_t llfc_cfgr[] = {
  15306         PORT_PFC_CFG0r, PORT_PFC_CFG1r, PORT_PFC_CFG2r
  15307     };
  15308 
  15309     if (pfc_class == NULL) {
  15310         return BCM_E_PARAM;
  15311     }
  15312     if (cos_bmp == NULL) {
  15313         return BCM_E_PARAM;
  15314     }
  15315     if ((entry_cnt < 0 ) || (entry_cnt > _BCM_MN_NUM_SAFC_CLASS)) {
  15316         return BCM_E_PARAM;
  15317     }
  15318     
  15319     BCM_IF_ERROR_RETURN(
  15320         _bcm_mn_cosq_localport_resolve(unit, port, &local_port));
  15321 
  15322     si = &SOC_INFO(unit);
  15323     phy_port = si->port_l2p_mapping[local_port];
  15324     mmu_port = si->port_p2m_mapping[phy_port];
  15325     
  15326     reg = llfc_cfgr[mmu_port/32];
  15327     rval64s[0] = rval64;
  15328     BCM_IF_ERROR_RETURN(soc_reg64_get(unit, reg, 0, 0, &rval));
  15329     
  15330     index_map = soc_reg64_field_get(unit, reg, rval, PROFILE_INDEXf);
  15331     COMPILER_64_SHR(index_map, ((mmu_port % 32) * 2));
  15332     COMPILER_64_TO_32_LO(tmp32, index_map);
  15333     old_profile_index = (tmp32 & 3)*16;
  15334     BCM_IF_ERROR_RETURN
  15335         (soc_profile_reg_get(unit, _bcm_mn_llfc_profile[unit],
  15336                              old_profile_index, 16, rval64s));
  15337 
  15338     for (entry = 0; entry < entry_cnt; entry++) {
  15339         cur_class = pfc_class[entry];
  15340         cur_bmp = cos_bmp[entry];
  15341         if (op == _BCM_COSQ_OP_SET) {
  15342             soc_reg64_field32_set(unit, PRIO2COS_PROFILEr, &rval64[cur_class],
  15343                                   COS_BMPf, cur_bmp);
  15344         } else {
  15345             if (cur_bmp != 0) {
  15346                 fval = soc_reg64_field32_get(unit, PRIO2COS_PROFILEr,
  15347                                              rval64[cur_class], COS_BMPf);
  15348                 if (op == _BCM_COSQ_OP_ADD) {
  15349                     fval |= cur_bmp;
  15350                 } else { /* _BCM_COSQ_OP_DELETE */
  15351                     fval &= ~cur_bmp;
  15352                 }
  15353                 soc_reg64_field32_set(unit, PRIO2COS_PROFILEr,
  15354                                       &rval64[cur_class], COS_BMPf, fval);
  15355             }
  15356         }
  15357     }
  15358     
  15359     BCM_IF_ERROR_RETURN
  15360         (soc_profile_reg_delete(unit, _bcm_mn_llfc_profile[unit],
  15361                                 old_profile_index));
  15362 
  15363     rv = soc_profile_reg_add(unit, _bcm_mn_llfc_profile[unit], rval64s,
  15364                              16, &profile_index);
  15365     if (SOC_FAILURE(rv)) {
  15366         BCM_IF_ERROR_RETURN
  15367             (soc_profile_reg_reference(unit, _bcm_mn_llfc_profile[unit],
  15368                                        old_profile_index, 16));
  15369         return rv;
  15370     }
  15371 
  15372 
  15373     index_map = soc_reg64_field_get(unit, reg, rval, PROFILE_INDEXf);
  15374 
  15375     COMPILER_64_SET(tmp, 0, 3);
  15376     COMPILER_64_SHL(tmp, (mmu_port % 32) * 2);
  15377     COMPILER_64_NOT(tmp);
  15378     COMPILER_64_AND(index_map, tmp);
  15379     COMPILER_64_SET(tmp, 0, profile_index/16);
  15380     COMPILER_64_SHL(tmp, (mmu_port % 32) * 2);
  15381     COMPILER_64_OR(index_map, tmp);
  15382     
  15383     soc_reg64_field_set(unit, reg, &rval, PROFILE_INDEXf,
  15384                         index_map);
  15385 
  15386     BCM_IF_ERROR_RETURN(soc_reg64_set(unit, reg, 0, 0, rval));
  15387     return BCM_E_NONE;
  15388 }
  15389 /*
  15390  * Function:
  15391  *     _bcm_mn_fc_map_gport_check
  15392  * Purpose:
  15393  *     Validate if a gport can be mapped to a port's PFC/FC status.
  15394  * Parameters:
  15395  *     unit             - (IN) unit number
  15396  *     port             - (IN) port number
  15397  *     gport            - (IN) gport that will be mapped
  15398  * Returns:
  15399  *     BCM_E_XXX
  15400  */
  15401 STATIC int
  15402 _bcm_mn_fc_map_gport_check(int unit,
  15403     bcm_gport_t port,
  15404     bcm_gport_t gport)
  15405 {
  15406     bcm_port_t local_port = -1, resolved_port;
  15407     int hw_cosq, pipe;
  15408     _bcm_mn_pipe_resources_t *res;
  15409     _bcm_mn_cosq_port_info_t *port_info;
  15410     _bcm_mn_mmu_info_t *mmu_info;
  15411     _bcm_mn_cosq_node_t *node;
  15412 
  15413     BCM_IF_ERROR_RETURN
  15414         (_bcm_mn_cosq_localport_resolve(unit, port, &local_port));
  15415 
  15416     if (local_port < 0) {
  15417         return BCM_E_PORT;
  15418     }
  15419 
  15420     mmu_info = _bcm_mn_mmu_info[unit];
  15421     port_info = &mmu_info->port_info[local_port];
  15422     pipe = _BCM_MN_PORT_TO_PIPE(unit, local_port);
  15423     res = _BCM_MN_PRESOURCES(mmu_info, pipe);
  15424     
  15425     hw_cosq = -1;
  15426     if (BCM_GPORT_IS_SET(gport)) {
  15427         BCM_IF_ERROR_RETURN(_bcm_mn_cosq_node_get(unit, gport, 
  15428                             0, NULL, &resolved_port, NULL, &node));
  15429         if (!((node->type == _BCM_MN_NODE_UCAST) ||
  15430               (node->type == _BCM_MN_NODE_MCAST) ||
  15431               (node->type == _BCM_MN_NODE_SCHEDULER))) {
  15432             return BCM_E_PARAM;
  15433         }
  15434         if (resolved_port != local_port) {
  15435             return BCM_E_PARAM;
  15436         }
  15437         hw_cosq = node->hw_cosq;
  15438     } else {
  15439         hw_cosq = gport;
  15440         if (_bcm_mn_cosq_port_has_ets(unit, local_port)) {
  15441             node = &res->p_queue_node[port_info->uc_base + hw_cosq];
  15442             if ((!node->in_use) || (node->attached_to_input == -1)) {
  15443                 return BCM_E_PARAM;
  15444             }
  15445             node = &res->p_mc_queue_node[port_info->mc_base + hw_cosq];
  15446             if ((!node->in_use) || (node->attached_to_input == -1)) {
  15447                 return BCM_E_PARAM;
  15448             }
  15449         }
  15450     }
  15451     if ((hw_cosq < 0) || (hw_cosq >= _MN_NUM_INTERNAL_PRI)) {
  15452         return BCM_E_PARAM;
  15453     }
  15454 
  15455     return BCM_E_NONE;
  15456 }
  15457 
  15458 /*
  15459  * Function:
  15460  *     _bcm_mn_pfc_class_mapping_check
  15461  * Purpose:
  15462  *     Validate param of bcm_cosq_pfc_class_mapping_t.
  15463  * Parameters:
  15464  *     unit             - (IN) unit number
  15465  *     port             - (IN) port number
  15466  *     array_count      - (IN) count of mapping array
  15467  *     mapping_array    - (IN) mapping array list
  15468  * Returns:
  15469  *     BCM_E_XXX
  15470  */
  15471 STATIC int
  15472 _bcm_mn_pfc_class_mapping_check(int unit,
  15473     bcm_gport_t port,
  15474     int array_count,
  15475     bcm_cosq_pfc_class_mapping_t *mapping_array)
  15476 {
  15477     int count, index, cur_class;
  15478     bcm_gport_t cur_gport = 0;
  15479 
  15480     if (mapping_array == NULL) {
  15481         return BCM_E_PARAM;
  15482     }
  15483     
  15484     for (count = 0; count < array_count; count++) {
  15485         cur_class = mapping_array[count].class_id;
  15486         if ((cur_class < 0) || (cur_class >= _BCM_MN_NUM_PFC_CLASS)) {
  15487             return BCM_E_PARAM;
  15488         }
  15489         
  15490         for (index = 0; index < BCM_COSQ_PFC_GPORT_COUNT; index++) {
  15491             cur_gport = mapping_array[count].gport_list[index];
  15492             if (cur_gport == BCM_GPORT_INVALID) {
  15493                 break;
  15494             }
  15495             BCM_IF_ERROR_RETURN(_bcm_mn_fc_map_gport_check(unit,
  15496                                                             port, cur_gport));
  15497         }
  15498     }
  15499 
  15500     return BCM_E_NONE;
  15501 }
  15502 
  15503 
  15504 int
  15505 bcm_mn_cosq_port_pfc_op(int unit, bcm_port_t port,
  15506                         bcm_switch_control_t sctype, _bcm_cosq_op_t op,
  15507                         bcm_gport_t *gport, int gport_count)
  15508 {
  15509     _bcm_mn_cosq_node_t *node;
  15510     bcm_port_t local_port, resolved_port;
  15511     int rv, type, class = -1, id, index, hw_cosq ;
  15512     uint32 profile_index, old_profile_index;
  15513     uint64 rval64[16], tmp, *rval64s[1], rval, index_map;
  15514     uint32 fval, cos_bmp, tmp32;
  15515     int hw_index;
  15516     _bcm_mn_mmu_info_t *mmu_info;
  15517     _bcm_mn_pipe_resources_t *res;
  15518     _bcm_mn_cosq_port_info_t *port_info;
  15519     soc_reg_t   reg;
  15520     int phy_port, mmu_port, lvl, pipe;
  15521     soc_info_t *si;
  15522     static const soc_reg_t llfc_cfgr[] = {
  15523         PORT_PFC_CFG0r, PORT_PFC_CFG1r, PORT_PFC_CFG2r 
  15524     };
  15525 
  15526     if (gport_count < 0) {
  15527         return BCM_E_PARAM;
  15528     }
  15529 
  15530     BCM_IF_ERROR_RETURN
  15531         (_bcm_mn_cosq_localport_resolve(unit, port, &local_port));
  15532 
  15533 
  15534     for (index = 0; index < gport_count; index++) {
  15535         BCM_IF_ERROR_RETURN(_bcm_mn_fc_map_gport_check(unit,port, gport[index]));
  15536     }
  15537 
  15538     BCM_IF_ERROR_RETURN(_bcm_mn_cosq_pfc_class_resolve(sctype, &type, &class));
  15539 
  15540     si = &SOC_INFO(unit);
  15541     phy_port = si->port_l2p_mapping[local_port];
  15542     mmu_port = si->port_p2m_mapping[phy_port];
  15543 
  15544     mmu_info = _bcm_mn_mmu_info[unit];
  15545     port_info = &mmu_info->port_info[local_port];
  15546     pipe = _BCM_MN_PORT_TO_PIPE(unit, local_port);
  15547     res = _BCM_MN_PRESOURCES(mmu_info, pipe);
  15548 
  15549     cos_bmp = 0;
  15550     for (index = 0; index < gport_count; index++) {
  15551         hw_index =  -1;
  15552         hw_cosq =  -1;
  15553         if (BCM_GPORT_IS_SET(gport[index])) {
  15554             BCM_IF_ERROR_RETURN(_bcm_mn_cosq_node_get(unit, gport[index], 
  15555                                 0, NULL, &resolved_port, &id, &node));
  15556             hw_index = node->hw_index;
  15557             hw_cosq = node->hw_cosq;
  15558             lvl = node->level;
  15559         } else {
  15560             hw_cosq = gport[index];
  15561             node = &res->p_queue_node[port_info->uc_base + hw_cosq];
  15562             node = node->parent; 
  15563             hw_index = node->hw_index;
  15564             lvl = SOC_MONTEREY_NODE_LVL_L1;
  15565         }
  15566         if ((hw_cosq < 0) || (hw_cosq > 15)) {
  15567             return BCM_E_PARAM;
  15568         }
  15569         BCM_IF_ERROR_RETURN(
  15570             _bcm_mn_map_fc_status_to_node(unit, local_port,
  15571                             (op == _BCM_COSQ_OP_CLEAR) ? 0 : _BCM_MN_COSQ_FC_PFC,
  15572                                            mmu_port*4, hw_cosq, hw_index, lvl));
  15573         cos_bmp |= 1 << hw_cosq;
  15574     }
  15575 
  15576     if (op == _BCM_COSQ_OP_CLEAR) {
  15577         cos_bmp = (1 << _MN_NUM_INTERNAL_PRI) - 1;
  15578     }
  15579 
  15580     reg = llfc_cfgr[mmu_port/32];
  15581     rval64s[0] = rval64;
  15582     BCM_IF_ERROR_RETURN(soc_reg64_get(unit, reg, 0, 0, &rval));
  15583     if (op == _BCM_COSQ_OP_SET || cos_bmp != 0) {
  15584         index_map = soc_reg64_field_get(unit, reg, rval, PROFILE_INDEXf);
  15585         COMPILER_64_SHR(index_map, ((mmu_port % 32) * 2));
  15586         COMPILER_64_TO_32_LO(tmp32, index_map);
  15587         old_profile_index = (tmp32 & 3)*16;
  15588         BCM_IF_ERROR_RETURN
  15589             (soc_profile_reg_get(unit, _bcm_mn_llfc_profile[unit],
  15590                                  old_profile_index, 16, rval64s));
  15591         if (op == _BCM_COSQ_OP_SET) {
  15592             soc_reg64_field32_set(unit, PRIO2COS_PROFILEr, &rval64[class],
  15593                                   COS_BMPf, cos_bmp);
  15594         } else if (cos_bmp != 0) {
  15595             fval = soc_reg64_field32_get(unit, PRIO2COS_PROFILEr, rval64[class],
  15596                                          COS_BMPf);
  15597             if (op == _BCM_COSQ_OP_ADD) {
  15598                 fval |= cos_bmp;
  15599             } else { /* _BCM_COSQ_OP_DELETE */
  15600                 fval &= ~cos_bmp;
  15601             }
  15602             soc_reg64_field32_set(unit, PRIO2COS_PROFILEr, &rval64[class],
  15603                                   COS_BMPf, fval);
  15604         }
  15605         
  15606         BCM_IF_ERROR_RETURN
  15607             (soc_profile_reg_delete(unit, _bcm_mn_llfc_profile[unit],
  15608                                     old_profile_index));
  15609         rv = soc_profile_reg_add(unit, _bcm_mn_llfc_profile[unit], rval64s,
  15610                                  16, &profile_index);
  15611         if (rv < 0) {
  15612             BCM_IF_ERROR_RETURN
  15613                 (soc_profile_reg_reference(unit, _bcm_mn_llfc_profile[unit],
  15614                                         old_profile_index, 16));
  15615             return rv;
  15616         }
  15617 
  15618         index_map = soc_reg64_field_get(unit, reg, rval, PROFILE_INDEXf);
  15619 
  15620         COMPILER_64_SET(tmp, 0, 3);
  15621         COMPILER_64_SHL(tmp, (mmu_port % 32) * 2);
  15622         COMPILER_64_NOT(tmp);
  15623         COMPILER_64_AND(index_map, tmp);
  15624         COMPILER_64_SET(tmp, 0, profile_index/16);
  15625         COMPILER_64_SHL(tmp, (mmu_port % 32) * 2);
  15626         COMPILER_64_OR(index_map, tmp);
  15627         
  15628         soc_reg64_field_set(unit, reg, &rval, PROFILE_INDEXf,
  15629                             index_map);
  15630 
  15631     }
  15632 
  15633     BCM_IF_ERROR_RETURN(soc_reg64_set(unit, reg, 0, 0, rval));
  15634     return BCM_E_NONE;
  15635 }
  15636 
  15637 int
  15638 bcm_mn_cosq_port_pfc_get(int unit, bcm_port_t port,
  15639                          bcm_switch_control_t sctype,
  15640                          bcm_gport_t *gport, int gport_count,
  15641                          int *actual_gport_count)
  15642 {
  15643     _bcm_mn_cosq_node_t *node;
  15644     bcm_port_t local_port;
  15645     int type = -1, class = -1, hw_cosq, count = 0;
  15646     uint32 profile_index;
  15647     uint64 rval64[16], *rval64s[1], rval, index_map;
  15648     uint32 tmp32, bmp, bmp_len;
  15649     _bcm_mn_mmu_info_t *mmu_info;
  15650     int phy_port, mmu_port;
  15651     soc_info_t *si;
  15652     soc_reg_t   reg;
  15653     int mc_index = 0 ;
  15654     int mcq_offset = 0 ;
  15655     _bcm_mn_pipe_resources_t *res;
  15656     _bcm_mn_cosq_port_info_t *port_info;
  15657     static const soc_reg_t llfc_cfgr[] = {
  15658         PORT_PFC_CFG0r, PORT_PFC_CFG1r, PORT_PFC_CFG2r
  15659     };
  15660     static const soc_field_t self[] = {
  15661         SEL0f, SEL1f, SEL2f, SEL3f
  15662     };
  15663     int j, inv_mapped, hw_index, eindex;
  15664     soc_mem_t mem;
  15665     uint32 map_entry[SOC_MAX_MEM_WORDS];
  15666     int port_num = 0 ;
  15667 
  15668     if (((gport == NULL) && (gport_count > 0)) || actual_gport_count == NULL) {
  15669         return BCM_E_PARAM;
  15670     }
  15671 
  15672     BCM_IF_ERROR_RETURN
  15673         (_bcm_mn_cosq_localport_resolve(unit, port, &local_port));
  15674 
  15675     BCM_IF_ERROR_RETURN(_bcm_mn_cosq_pfc_class_resolve(sctype, &type, &class));
  15676 
  15677     si = &SOC_INFO(unit);
  15678     mmu_info = _bcm_mn_mmu_info[unit];
  15679     res = _BCM_MN_PRESOURCES(mmu_info, 0);
  15680     phy_port = si->port_l2p_mapping[local_port];
  15681     mmu_port = si->port_p2m_mapping[phy_port];
  15682     port_info = &mmu_info->port_info[local_port];
  15683 
  15684     rval64s[0] = rval64;
  15685     reg = llfc_cfgr[mmu_port/32];
  15686     BCM_IF_ERROR_RETURN(soc_reg64_get(unit, reg, REG_PORT_ANY, 0, &rval));
  15687 
  15688     index_map = soc_reg64_field_get(unit, reg, rval, PROFILE_INDEXf);
  15689     COMPILER_64_SHR(index_map, ((mmu_port % 32) * 2));
  15690     COMPILER_64_TO_32_LO(tmp32, index_map);
  15691     profile_index = (tmp32 & 3)*16;
  15692 
  15693     BCM_IF_ERROR_RETURN
  15694         (soc_profile_reg_get(unit, _bcm_mn_llfc_profile[unit],
  15695                              profile_index, 16, rval64s));
  15696 
  15697     bmp = soc_reg64_field32_get(unit, PRIO2COS_PROFILEr, rval64[class],
  15698                                 COS_BMPf);
  15699     bmp_len = soc_reg_field_length(unit, PRIO2COS_PROFILEr, COS_BMPf);
  15700     for (hw_cosq = 0; hw_cosq < bmp_len; hw_cosq++) {
  15701         if (!(bmp & (1 << hw_cosq))) {
  15702             continue;
  15703         }
  15704         if (_bcm_mn_cosq_port_has_ets(unit, local_port)) {
  15705             inv_mapped = 0;
  15706             for (j = _BCM_MN_NUM_PORT_SCHEDULERS; 
  15707                  j < _BCM_MN_NUM_TOTAL_SCHEDULERS; j++) {
  15708                 node = &mmu_info->sched_node[j];
  15709                 if ((!node->in_use) || (node->local_port != local_port) ||
  15710                     (node->hw_cosq != hw_cosq)) {
  15711                     continue;
  15712                 }
  15713 
  15714                 hw_index = (node->hw_index / 16);
  15715                 eindex = (node->hw_index % 16)/4;
  15716                 if (node->level == SOC_MONTEREY_NODE_LVL_L0) {
  15717                     mem = MMU_INTFI_XPIPE_FC_MAP_TBL0m;
  15718                 } else if (node->level == SOC_MONTEREY_NODE_LVL_L1) {
  15719                     mem = MMU_INTFI_XPIPE_FC_MAP_TBL1m;
  15720                 } else {
  15721                     continue;
  15722                 }
  15723 
  15724                 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, 
  15725                         MEM_BLOCK_ALL, hw_index, &map_entry));
  15726 
  15727                  /* coverity[overrun-local : FALSE] */
  15728                 if (soc_mem_field32_get(unit, mem, &map_entry, self[eindex])) {
  15729                     if (gport_count > 0) {
  15730                         gport[count] = node->gport;
  15731                     }
  15732                     count++;
  15733                     if ((count == gport_count) && (gport_count > 0)) {
  15734                          inv_mapped = 1;
  15735                          break;
  15736                     }
  15737                 }
  15738             }
  15739 
  15740             for (j = port_info->uc_base; 
  15741                  inv_mapped==0 && (j < port_info->uc_limit); j++) {
  15742                 node = &res->p_queue_node[j];
  15743                 if ((!node->in_use) || (node->local_port != local_port)) {
  15744                     continue;
  15745                 }
  15746                 if (node->hw_cosq != hw_cosq) {
  15747                     continue;
  15748                 }
  15749                 mem =   MMU_INTFI_XPIPE_FC_MAP_TBL2m ;
  15750                if (IS_MN_HSP_PORT(unit,port)) {
  15751                    hw_index = node->hw_index;
  15752                    if ((hw_index % 10) > 7) {
  15753                         /* FC support only for Q0-7 */
  15754                          break;
  15755                     } 
  15756                     port_num = hw_index / 10;
  15757                     hw_index = port_num * 2 +
  15758                                 (((hw_index % 10) >= 4)? 1 : 0);
  15759                     eindex = hw_index & 0x3;
  15760                     hw_index = hw_index / 4; /* each entry contains 4 indexes */
  15761                } else 
  15762                { 
  15763                       hw_index = (node->hw_index / 16);
  15764                       eindex = (node->hw_index % 16)/4;
  15765                }
  15766                 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, 
  15767                         MEM_BLOCK_ALL, hw_index, &map_entry));
  15768 
  15769                  /* coverity[overrun-local : FALSE] */
  15770                 if (soc_mem_field32_get(unit, mem, &map_entry, self[eindex])) {
  15771                     if (gport_count > 0) {   
  15772                         gport[count] = node->gport;
  15773                     } 
  15774                     count++ ; 
  15775                     if ((count == gport_count) && (gport_count > 0)) {
  15776                          inv_mapped = 1;
  15777                          break;
  15778                     }  
  15779                 }
  15780             }
  15781             for (j = port_info->mc_base; 
  15782                 inv_mapped==0 && (j < port_info->mc_limit); j++) {
  15783                 mc_index = soc_monterey_l2_hw_index(unit, j, 0);
  15784                 node = &res->p_queue_node[mc_index];
  15785                 if ((!node->in_use) || (node->local_port != local_port)) {
  15786                     continue;
  15787                 }
  15788                 if (node->hw_cosq != hw_cosq) {
  15789                     continue;
  15790                 }
  15791                 mem =   MMU_INTFI_XPIPE_FC_MAP_TBL2m ;
  15792                 mcq_offset = node->hw_index % _BCM_MN_NUM_L2_UC_LEAVES_PER_PIPE;
  15793                 if (((mcq_offset % 10) > 7) ) {
  15794                      /* FC support only for Q0-7 */
  15795                       continue; 
  15796                 }
  15797                 hw_index = node->hw_index - (mcq_offset * 2 / 10);
  15798                 hw_index /= 16;
  15799                 eindex = (mcq_offset % 10)/4;
  15800                 eindex += ((mcq_offset /10) % 2) ? 0 : 2;
  15801                 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, 
  15802                         MEM_BLOCK_ALL, hw_index, &map_entry));
  15803 
  15804                  /* coverity[overrun-local : FALSE] */
  15805                 if (soc_mem_field32_get(unit, mem, &map_entry, self[eindex])) {
  15806                     if (gport_count > 0) {
  15807                         gport[count] = node->gport;
  15808                     }
  15809                     count++;
  15810                     if ((count == gport_count) && (gport_count > 0)) {
  15811                         /* coverity[assigned_value : FALSE] */                        
  15812                         inv_mapped = 1;
  15813                         break;
  15814                     }
  15815                 }
  15816             }
  15817         } else {
  15818             if (gport_count > 0) {
  15819                 gport[count++] = hw_cosq;
  15820             } 
  15821         }
  15822         if (count == gport_count) {
  15823             break;
  15824         }
  15825     }
  15826 
  15827     if (count == 0) {
  15828         return BCM_E_NOT_FOUND;
  15829     }
  15830     *actual_gport_count = count;
  15831     return BCM_E_NONE;
  15832 }
  15833 
  15834 /*
  15835  * Function:
  15836  *     bcm_mn_cosq_pfc_class_mapping_set
  15837  * Purpose:
  15838  *     Set PFC mapping for port. PFC class is mapped to cosq or scheduler node gports.
  15839  * Parameters:
  15840  *     unit             - (IN) unit number
  15841  *     port             - (IN) port number
  15842  *     array_count      - (IN) count of mapping
  15843  *     mapping_array    - (IN) mappings 
  15844  * Returns:
  15845  *     BCM_E_XXX
  15846  */
  15847 int
  15848 _bcm_mn_cosq_pfc_class_mapping_set(int unit,
  15849     bcm_gport_t port,
  15850     int array_count,
  15851     bcm_cosq_pfc_class_mapping_t *mapping_array)
  15852 {
  15853     int index, count;
  15854     int cur_class = 0, pfc_class[_BCM_MN_NUM_PFC_CLASS];
  15855     bcm_gport_t cur_gport = 0;
  15856     uint32 cos_bmp[_BCM_MN_NUM_PFC_CLASS];
  15857     int local_port = 0 ;
  15858 
  15859     BCM_IF_ERROR_RETURN
  15860         (_bcm_mn_cosq_localport_resolve(unit, port, &local_port));
  15861 
  15862     if (local_port < 0) {
  15863         return BCM_E_PORT;
  15864     }
  15865 
  15866     if (IS_CPU_PORT(unit, local_port)) {
  15867         return BCM_E_PARAM;
  15868     }
  15869     if ((array_count < 0) || (array_count > _BCM_MN_NUM_PFC_CLASS)) {
  15870         return BCM_E_PARAM;
  15871     }
  15872     if (mapping_array == NULL) {
  15873         return BCM_E_PARAM;
  15874     }
  15875 
  15876     BCM_IF_ERROR_RETURN( _bcm_mn_pfc_class_mapping_check(unit,port, 
  15877                         array_count,mapping_array));
  15878     _bcm_mn_clear_fc_status_to_node(unit, port);
  15879 
  15880     sal_memset(cos_bmp, 0, sizeof(cos_bmp));
  15881 
  15882     for (count = 0; count < array_count; count++) {
  15883         cur_class = mapping_array[count].class_id;
  15884         
  15885         for (index = 0; index < BCM_COSQ_PFC_GPORT_COUNT; index++) {
  15886             cur_gport = mapping_array[count].gport_list[index];
  15887             if (cur_gport == BCM_GPORT_INVALID) {
  15888                 break;
  15889             }
  15890             
  15891             BCM_IF_ERROR_RETURN(_bcm_mn_fc_status_map_gport(unit, port, 
  15892                 cur_gport, _BCM_MN_COSQ_FC_PFC, &cos_bmp[cur_class]));
  15893         }
  15894     }
  15895 
  15896     for (index = 0; index < _BCM_MN_NUM_PFC_CLASS; index++) {
  15897         pfc_class[index] = index;
  15898     }
  15899     BCM_IF_ERROR_RETURN(_bcm_mn_port_fc_profile_set(unit, port,
  15900         _BCM_COSQ_OP_SET, _BCM_MN_NUM_PFC_CLASS, pfc_class, cos_bmp));
  15901     
  15902     return BCM_E_NONE;
  15903 }
  15904 
  15905 int
  15906 _bcm_mn_cosq_pfc_class_mapping_get(int unit,
  15907     bcm_gport_t port,
  15908     int array_max,
  15909     int *array_count,
  15910     bcm_cosq_pfc_class_mapping_t *mapping_array)
  15911 {
  15912     int rv = 0;
  15913     int cur_class = 0;
  15914     int actual_gport_count, class_count = 0;
  15915     int local_port = 0 ;
  15916     bcm_switch_control_t sc[] = { bcmSwitchPFCClass0Queue,
  15917                                   bcmSwitchPFCClass1Queue,
  15918                                   bcmSwitchPFCClass2Queue,
  15919                                   bcmSwitchPFCClass3Queue,
  15920                                   bcmSwitchPFCClass4Queue,
  15921                                   bcmSwitchPFCClass5Queue,
  15922                                   bcmSwitchPFCClass6Queue,
  15923                                   bcmSwitchPFCClass7Queue
  15924                                 };
  15925 
  15926     BCM_IF_ERROR_RETURN
  15927         (_bcm_mn_cosq_localport_resolve(unit, port, &local_port));
  15928 
  15929     if (local_port < 0) {
  15930         return BCM_E_PORT;
  15931     }
  15932 
  15933     if (IS_CPU_PORT(unit, local_port)) {
  15934         return BCM_E_PARAM;
  15935     }
  15936     if ((mapping_array == NULL) && (array_max > 0)) {
  15937         return BCM_E_PARAM;
  15938     }
  15939     if (array_count == NULL) {
  15940         return BCM_E_PARAM;
  15941     }
  15942     
  15943     if (array_max <= 0) {
  15944         *array_count = _BCM_MN_NUM_PFC_CLASS;
  15945         return BCM_E_NONE;
  15946     }
  15947 
  15948     for (cur_class = 0; cur_class < _BCM_MN_NUM_PFC_CLASS; cur_class++) {
  15949         actual_gport_count = 0;
  15950         rv = bcm_mn_cosq_port_pfc_get(unit, port, sc[cur_class],
  15951                     mapping_array[class_count].gport_list,
  15952                     BCM_COSQ_PFC_GPORT_COUNT, &actual_gport_count);
  15953         if (rv == BCM_E_NONE) {
  15954             mapping_array[class_count].class_id = cur_class;
  15955             if (actual_gport_count < BCM_COSQ_PFC_GPORT_COUNT) {
  15956                 mapping_array[class_count].gport_list[actual_gport_count] =
  15957                                                       BCM_GPORT_INVALID;
  15958             }
  15959             class_count++;
  15960         } else if (rv != BCM_E_NOT_FOUND) {
  15961             return rv;
  15962         }
  15963 
  15964         if (class_count == array_max) {
  15965             break;
  15966         }
  15967     }
  15968 
  15969     *array_count = class_count;
  15970     if (class_count == 0) {
  15971         return BCM_E_NOT_FOUND;
  15972     }
  15973     return BCM_E_NONE;
  15974 }
  15975 
  15976 /*
  15977  * Function:
  15978  *      bcm_mn_port_priority_group_mapping_set
  15979  * Purpose:
  15980  *      Assign a Priority Group for the input priority.
  15981  * Parameters:
  15982  *      unit       - (IN) device id.
  15983  *      gport     - (IN) generic port.
  15984  *      prio       - (IN) input priority.
  15985  *      priority_group  - (IN) PG ID that the input priority mapped to.
  15986  * Returns:
  15987  *      BCM_E_XXX
  15988  */
  15989 int
  15990 bcm_mn_port_priority_group_mapping_set(int unit, bcm_gport_t gport,
  15991                                         int prio, int priority_group)
  15992 {
  15993     bcm_port_t port;
  15994     uint32 value;
  15995     int field_count;
  15996     soc_field_t fields_0[]={PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf,
  15997         PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf};
  15998     soc_field_t fields_1[]={PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf,
  15999         PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf};
  16000 
  16001     if (!soc_feature(unit, soc_feature_priority_flow_control)) {
  16002         return BCM_E_UNAVAIL;
  16003     }
  16004     /* PFC : 0-7, SAFC : 0-15. Taking the larger range for comparison */
  16005     if ((prio < AP_SAFC_INPUT_PRIORITY_MIN) ||
  16006             (prio > AP_SAFC_INPUT_PRIORITY_MAX)) {
  16007         return BCM_E_PARAM;
  16008     }
  16009 
  16010     if ((priority_group < AP_PRIOROTY_GROUP_ID_MIN) ||
  16011             (priority_group > AP_PRIOROTY_GROUP_ID_MAX)) {
  16012         return BCM_E_PARAM;
  16013     }
  16014 
  16015     BCM_IF_ERROR_RETURN(_bcm_mn_cosq_localport_resolve(unit, gport, &port));
  16016     if (!SOC_PORT_VALID(unit, port)) {
  16017         return BCM_E_PORT;
  16018     }
  16019     field_count = COUNTOF(fields_0);
  16020     if (prio < field_count) {
  16021         /* input priority 0~7 */
  16022         BCM_IF_ERROR_RETURN(READ_THDI_PORT_PRI_GRP0r(unit, port, &value));
  16023         soc_reg_field_set(unit, THDI_PORT_PRI_GRP0r, &value,
  16024                 fields_0[prio], priority_group);
  16025         BCM_IF_ERROR_RETURN(WRITE_THDI_PORT_PRI_GRP0r(unit, port, value));
  16026     } else {
  16027         /* input priority 8~15 */
  16028         BCM_IF_ERROR_RETURN(READ_THDI_PORT_PRI_GRP1r(unit, port, &value));
  16029         soc_reg_field_set(unit, THDI_PORT_PRI_GRP1r, &value,
  16030                 fields_1[prio - field_count], priority_group);
  16031         BCM_IF_ERROR_RETURN(WRITE_THDI_PORT_PRI_GRP1r(unit, port, value));
  16032     }
  16033 
  16034     return BCM_E_NONE;
  16035 }
  16036 
  16037 /*
  16038  * Function:
  16039  *      bcm_mn_port_priority_group_mapping_get
  16040  * Purpose:
  16041  *      Get the assigned Priority Group ID of the input priority.
  16042  * Parameters:
  16043  *      unit       - (IN) device id.
  16044  *      gport     - (IN) generic port.
  16045  *      prio       - (IN) input priority.
  16046  *      priority_group  - (OUT) PG ID that the input priority mapped to.
  16047  * Returns:
  16048  *      BCM_E_XXX
  16049  */
  16050 
  16051 int
  16052 bcm_mn_port_priority_group_mapping_get(int unit, bcm_gport_t gport,
  16053                                         int prio, int *priority_group)
  16054 {
  16055     bcm_port_t port;
  16056     uint32 value;
  16057     int field_count;
  16058     soc_field_t fields_0[]={PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf,
  16059         PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf};
  16060     soc_field_t fields_1[]={PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf,
  16061         PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf};
  16062 
  16063     if (!soc_feature(unit, soc_feature_priority_flow_control)) {
  16064         return BCM_E_UNAVAIL;
  16065     }
  16066     if (priority_group == NULL) {
  16067         return BCM_E_PARAM;
  16068     }
  16069     /* PFC : 0-7, SAFC : 0-15. Taking the larger range for comparison */
  16070     if ((prio < AP_SAFC_INPUT_PRIORITY_MIN) ||
  16071             (prio > AP_SAFC_INPUT_PRIORITY_MAX)) {
  16072         return BCM_E_PARAM;
  16073     }
  16074 
  16075     BCM_IF_ERROR_RETURN(_bcm_mn_cosq_localport_resolve(unit, gport, &port));
  16076     if (!SOC_PORT_VALID(unit, port)) {
  16077         return BCM_E_PORT;
  16078     }
  16079     field_count = COUNTOF(fields_0);
  16080     if (prio < field_count) {
  16081         /* input priority 0~7 */
  16082         BCM_IF_ERROR_RETURN(READ_THDI_PORT_PRI_GRP0r(unit, port, &value));
  16083         *priority_group = soc_reg_field_get(unit, THDI_PORT_PRI_GRP0r,
  16084                 value, fields_0[prio]);
  16085     } else {
  16086         /* input priority 8~15 */
  16087         BCM_IF_ERROR_RETURN(READ_THDI_PORT_PRI_GRP1r(unit, port, &value));
  16088         *priority_group = soc_reg_field_get(unit, THDI_PORT_PRI_GRP1r,
  16089                 value,
  16090                 fields_1[prio - field_count]);
  16091     }
  16092 
  16093     return BCM_E_NONE;
  16094 }
  16095 
  16096 
  16097 int
  16098 bcm_mn_cosq_drop_status_enable_set(int unit, bcm_port_t port, int enable)
  16099 {
  16100     _bcm_mn_mmu_info_t *mmu_info;
  16101     uint32 rval;
  16102 
  16103     if ((mmu_info = _bcm_mn_mmu_info[unit]) == NULL) {
  16104         return BCM_E_INIT;
  16105     }
  16106 
  16107     BCM_IF_ERROR_RETURN(READ_MMU_THDM_DB_QUEUE_E2E_DS_EN_0r(unit, port, &rval));
  16108     soc_reg_field_set(unit, MMU_THDM_DB_QUEUE_E2E_DS_EN_0r, &rval, Q_COS_E2E_DS_ENf,
  16109                       0xff);
  16110     BCM_IF_ERROR_RETURN(WRITE_MMU_THDM_DB_QUEUE_E2E_DS_EN_0r(unit, port,  rval));
  16111 
  16112     BCM_IF_ERROR_RETURN(READ_OP_THDU_CONFIGr(unit, &rval));
  16113     soc_reg_field_set(unit, OP_THDU_CONFIGr, &rval, EARLY_E2E_SELECTf,
  16114                       enable ? 1 : 0);
  16115     BCM_IF_ERROR_RETURN(WRITE_OP_THDU_CONFIGr(unit, rval));
  16116 
  16117     return BCM_E_NONE;
  16118 }
  16119 
  16120 STATIC int
  16121 _bcm_mn_voq_min_hw_index(int unit, bcm_port_t port, 
  16122                           bcm_module_t modid, 
  16123                           bcm_port_t remote_port,
  16124                           int *q_offset)
  16125 {
  16126     int i, hw_index_base = -1, pipe;
  16127     _bcm_mn_cosq_node_t *node;
  16128     _bcm_mn_pipe_resources_t *res;
  16129     _bcm_mn_mmu_info_t *mmu_info;
  16130 
  16131     mmu_info = _bcm_mn_mmu_info[unit];
  16132     pipe = _BCM_MN_PORT_TO_PIPE(unit, port);
  16133     res = _BCM_MN_PRESOURCES(mmu_info, pipe);
  16134 
  16135     for (i = res->num_base_queues; i < _BCM_MN_NUM_L2_UC_LEAVES_PER_PIPE; i++) {
  16136         node = &res->p_queue_node[i];
  16137         if ((node->in_use == FALSE) || (node->hw_index == -1) || 
  16138                             (node->type != _BCM_MN_NODE_VOQ)) {
  16139             continue;
  16140         }
  16141 
  16142         if (((modid == -1) ? 1 : (node->remote_modid == modid)) && 
  16143             (node->remote_port == remote_port) &&
  16144             ((port == -1) ? 1 : (port == node->local_port))) {
  16145             if (hw_index_base == -1) {
  16146                 hw_index_base = node->hw_index;
  16147                 break;
  16148             }
  16149         }
  16150     }
  16151    
  16152     if (hw_index_base != -1) {
  16153         *q_offset = hw_index_base & ~7;
  16154         return BCM_E_NONE;
  16155     }
  16156 
  16157     return BCM_E_NOT_FOUND;
  16158 }
  16159 
  16160 STATIC int
  16161 _bcm_mn_voq_base_node_get(int unit, bcm_port_t port, 
  16162         int modid,
  16163         _bcm_mn_cosq_node_t **base_node)
  16164 {
  16165     int i,  pipe;
  16166     _bcm_mn_pipe_resources_t *res;
  16167     _bcm_mn_mmu_info_t *mmu_info;
  16168     _bcm_mn_cosq_node_t *node;
  16169 
  16170     mmu_info = _bcm_mn_mmu_info[unit];
  16171     pipe = _BCM_MN_PORT_TO_PIPE(unit, port);
  16172     res = _BCM_MN_PRESOURCES(mmu_info, pipe);
  16173     for ( i  = res->num_base_queues ; 
  16174             i < _BCM_MN_NUM_L2_UC_LEAVES_PER_PIPE ; i++) {
  16175         node = &res->p_queue_node[i];
  16176         if ((node->in_use == FALSE) || (node->hw_index == -1)) {
  16177             continue;
  16178         }
  16179         if (node->remote_modid == modid) {
  16180             *base_node = node ;
  16181             break;
  16182         }
  16183     }
  16184     return BCM_E_NONE;
  16185 }
  16186 
  16187 STATIC int
  16188 _bcm_mn_voq_next_base_node_get(int unit, bcm_port_t port, 
  16189         int modid,
  16190         _bcm_mn_cosq_node_t **base_node)
  16191 {
  16192     int i,  pipe;
  16193     _bcm_mn_pipe_resources_t *res;
  16194     _bcm_mn_mmu_info_t *mmu_info;
  16195     _bcm_mn_cosq_node_t *node;
  16196     int found = FALSE;
  16197 
  16198     mmu_info = _bcm_mn_mmu_info[unit];
  16199     pipe = _BCM_MN_PORT_TO_PIPE(unit, port);
  16200     for (pipe = _MN_XPIPE ; pipe < _MN_NUM_PIPES ; pipe++) { 
  16201         res = _BCM_MN_PRESOURCES(mmu_info, pipe);
  16202         for ( i  = res->num_base_queues ;
  16203                 i < _BCM_MN_NUM_L2_UC_LEAVES_PER_PIPE ; i++) {
  16204             node = &res->p_queue_node[i];
  16205             if ((node->in_use == FALSE) || (node->hw_index == -1)) {
  16206                 continue;
  16207             }
  16208             if (node->remote_modid == modid) {
  16209                 if ( found == TRUE) {
  16210                     *base_node = node;
  16211                     break;
  16212                 }
  16213                 found = TRUE;
  16214             }
  16215         }
  16216     }
  16217     return BCM_E_NONE;
  16218 }
  16219 
  16220 STATIC int
  16221 _bcm_mn_port_voq_base_set(int unit, bcm_port_t local_port, int base)
  16222 {
  16223     uint64 rval;
  16224 
  16225     BCM_IF_ERROR_RETURN(READ_ING_COS_MODE_64r(unit, local_port, &rval));
  16226     soc_reg64_field32_set(unit, ING_COS_MODE_64r, &rval, BASE_QUEUE_NUM_1f, base);
  16227     BCM_IF_ERROR_RETURN(WRITE_ING_COS_MODE_64r(unit, local_port, rval));
  16228     return BCM_E_NONE;
  16229 }
  16230 
  16231 STATIC int
  16232 _bcm_mn_port_voq_base_get(int unit, bcm_port_t local_port, int *base)
  16233 {
  16234     uint64 rval;
  16235 
  16236     BCM_IF_ERROR_RETURN(READ_ING_COS_MODE_64r(unit, local_port, &rval));
  16237     if (soc_reg64_field32_get(unit, ING_COS_MODE_64r, rval, QUEUE_MODEf) == 1) {
  16238         *base = soc_reg64_field32_get(unit, ING_COS_MODE_64r, rval, 
  16239                                   BASE_QUEUE_NUM_1f);
  16240         return BCM_E_NONE;
  16241     }
  16242 
  16243     BCM_IF_ERROR_RETURN(
  16244         _bcm_mn_voq_min_hw_index(unit, local_port, -1, -1, base));
  16245 
  16246     return BCM_E_NONE;
  16247 }
  16248 
  16249 STATIC int
  16250 _bcm_mn_resolve_dmvoq_hw_index(int unit, _bcm_mn_cosq_node_t *node, 
  16251                     int cosq, bcm_module_t modid, bcm_port_t local_port)
  16252 {
  16253     int try, preffered_offset = -1, alloc_size;
  16254     int from_offset, max_offset,  port, rv, q_base, port_voq_base, pipe;
  16255     _bcm_mn_pipe_resources_t *res;
  16256     _bcm_mn_mmu_info_t *mmu_info;
  16257 
  16258     mmu_info = _bcm_mn_mmu_info[unit];
  16259     pipe = _BCM_MN_PORT_TO_PIPE(unit, local_port);
  16260     res = _BCM_MN_PRESOURCES(mmu_info, pipe);
  16261 
  16262     from_offset  = res->num_base_queues;
  16263     max_offset = _BCM_MN_NUM_L2_UC_LEAVES_PER_PIPE;
  16264     alloc_size = _MN_NUM_COS(unit);
  16265 
  16266     for (try = 0; try < 2; try++) {
  16267         PBMP_HG_ITER(unit, port) {
  16268             if ((try == 1) && (port == local_port)) {
  16269                 continue;
  16270             }
  16271             
  16272             if ((try == 0) && (port != local_port)) {
  16273                 continue;
  16274            }
  16275 
  16276             rv = _bcm_mn_voq_min_hw_index(unit, port, modid, -1, &q_base);
  16277             if (!rv) {
  16278                 if (port == local_port) {
  16279                     /* Found VOQ for the same port/dest modid */
  16280                     node->hw_index = q_base + cosq;
  16281                     return BCM_E_NONE;
  16282                 } else if (modid == -1) {
  16283                     rv = _bcm_mn_port_voq_base_get(unit, port, &port_voq_base);
  16284                     if (rv) {
  16285                         continue;
  16286                     }
  16287                     preffered_offset = q_base - port_voq_base;
  16288                     rv = _bcm_mn_port_voq_base_get(unit, local_port, 
  16289                                                     &port_voq_base);
  16290                     if (rv) {
  16291                         /* No VOQ on the port yet */
  16292                         alloc_size += preffered_offset;
  16293                     } else {
  16294                         /* port has already VOQs */
  16295                         from_offset = port_voq_base + preffered_offset;
  16296                     }
  16297                     break;
  16298                 }
  16299             }
  16300         }
  16301         if (preffered_offset != -1) {
  16302             break;
  16303         }
  16304     }
  16305     if (modid == -1) {
  16306         /* Alloc hw index. */
  16307         rv = _bcm_mn_node_index_get(res->l2_queue_list.bits, 
  16308                 from_offset, max_offset, 
  16309                 alloc_size, _MN_NUM_COS(unit), &q_base);
  16310         if (rv) {
  16311             return BCM_E_RESOURCE;
  16312         }
  16313 
  16314         if (_bcm_mn_port_voq_base_get(unit, local_port, &port_voq_base)) {
  16315             _bcm_mn_port_voq_base_set(unit, local_port, q_base);
  16316         }
  16317         q_base = q_base + alloc_size - _MN_NUM_COS(unit);
  16318         node->hw_index = q_base + cosq;
  16319         node->hw_cosq = node->hw_index % _MN_NUM_COS(unit);
  16320         node->remote_modid = modid;
  16321         _bcm_mn_node_index_set(&res->l2_queue_list, q_base, _MN_NUM_COS(unit));
  16322     } else {
  16323         BCM_IF_ERROR_RETURN(
  16324                 _bcm_mn_voq_min_hw_index(unit, local_port, -1, -1, &port_voq_base));
  16325 
  16326         if (port_voq_base == node->hw_index) {
  16327             _bcm_mn_port_voq_base_set(unit, local_port, node->hw_index);
  16328         }
  16329         node->remote_modid = modid;
  16330         rv = BCM_E_NONE;
  16331     }
  16332     return rv;
  16333 }
  16334 
  16335 typedef struct _bcm_mn_voq_info_s {
  16336     int          valid;
  16337     _bcm_mn_cosq_node_t *node;
  16338     bcm_module_t remote_modid;
  16339     bcm_port_t   remote_port;
  16340     bcm_port_t   local_port;
  16341     int          hw_cosq;
  16342     int          hw_index;
  16343 } _bcm_mn_voq_info_t;
  16344 
  16345 STATIC int
  16346 _bcm_mn_cosq_sort_voq_list(void *a, void *b)
  16347 {
  16348     _bcm_mn_voq_info_t *va, *vb;
  16349     int sa, sb;
  16350 
  16351     va = (_bcm_mn_voq_info_t*)a;
  16352     vb = (_bcm_mn_voq_info_t*)b;
  16353     
  16354     sa = (va->remote_modid << 19) | (va->remote_port << 11) |
  16355          (va->local_port << 3) | (va->hw_cosq);
  16356 
  16357     sb = (vb->remote_modid << 19) | (vb->remote_port << 11) |
  16358          (vb->local_port << 3) | (vb->hw_cosq);
  16359 
  16360     return sa - sb;
  16361 }
  16362     
  16363 STATIC int
  16364 _bcm_mn_get_queue_skip_count_on_cos(uint32 cbmp, int cur_cos, int next_cos)
  16365 {
  16366     int i,skip = 0;
  16367 
  16368     if ((next_cos >= 4) && (cur_cos/4 != next_cos/4)) {
  16369         cur_cos = -1;
  16370         next_cos -= 4;
  16371     }
  16372     
  16373     for (i = cur_cos + 1; i < next_cos; i++) {
  16374         if (cbmp & (1 << i)) {
  16375             skip += 1;
  16376         }
  16377     }
  16378     return skip;
  16379 }
  16380 
  16381 STATIC int
  16382 _bcm_mn_msg_buf_get(int unit, bcm_port_t srcid)
  16383 {
  16384     int ii, hole = -1;
  16385     uint32 rval, csrc;
  16386 
  16387     for (ii = 0; ii < 16; ii++) {
  16388         BCM_IF_ERROR_RETURN(READ_BUF_CFGr(unit, ii, &rval));
  16389         if (srcid == (csrc = soc_reg_field_get(unit, BUF_CFGr, rval, SRC_IDf))) {
  16390             return ii;
  16391         }
  16392         if ((hole == -1) && (csrc == 0)) {
  16393             hole = ii;
  16394         }
  16395     }
  16396 
  16397     if (hole == -1) {
  16398         return BCM_E_RESOURCE;
  16399     }
  16400    
  16401     rval = 0;
  16402     soc_reg_field_set(unit, BUF_CFGr, &rval, SRC_IDf, srcid);
  16403     BCM_IF_ERROR_RETURN(WRITE_BUF_CFGr(unit, hole, rval));
  16404     
  16405     return hole;
  16406 }
  16407 
  16408 STATIC int
  16409 _bcm_mn_gport_dpvoq_config_set(int unit, bcm_gport_t gport, 
  16410                                 bcm_cos_queue_t cosq,
  16411                                 bcm_module_t remote_modid,
  16412                                 bcm_port_t remote_port)
  16413 {
  16414     uint32 profile = 0xFFFFFFFF;
  16415     _bcm_mn_cosq_node_t *node;
  16416     bcm_port_t local_port;
  16417     uint32 cng_offset;
  16418     uint8 cbmp = 0, nib_cbmp = 0;
  16419     _bcm_mn_mmu_info_t *mmu_info;
  16420     _bcm_mn_voq_info_t *plist = NULL, *vlist = NULL;
  16421     int pcount, ii, vcount = 0;
  16422     voq_port_map_entry_t *voq_port_map_entries = NULL;
  16423     int rv = BCM_E_NONE, mod_base = 0, num_cos = 0, dm = -1;
  16424     voq_mod_map_entry_t voq_mod_map;
  16425     void *entries[1];
  16426     int cng_bytes_per_e2ecc_msg = 64;
  16427     int p2ioff[128], ioff, port, skip, *dm2off, count, pipe;
  16428     _bcm_mn_pipe_resources_t *res;
  16429     voq_cos_map_entry_t voq_cos_map;
  16430     int priority = 0;
  16431     int rp, port_q_base = 0;
  16432     int base_tbl_entry = 0, intf_index = -1;
  16433     uint64 rval64;
  16434     soc_info_t *si;
  16435     int phy_port, mmu_port;
  16436 
  16437     if ((cosq < 0) || (cosq > _MN_NUM_COS(unit))) {
  16438         return BCM_E_PARAM;
  16439     }
  16440 
  16441     if ((mmu_info = _bcm_mn_mmu_info[unit]) == NULL) {
  16442         return BCM_E_INIT;
  16443     }
  16444 
  16445     BCM_IF_ERROR_RETURN
  16446       (_bcm_mn_cosq_node_get(unit, gport, 0, NULL, &local_port, NULL, &node));
  16447 
  16448     pipe = _BCM_MN_PORT_TO_PIPE(unit, local_port);
  16449     res = _BCM_MN_PRESOURCES(mmu_info, pipe);
  16450 
  16451     node->remote_modid = remote_modid;
  16452     node->remote_port = remote_port;
  16453     node->hw_cosq = cosq;
  16454 
  16455     dm2off = sal_alloc(sizeof(int) * 256, "voq_vlist");
  16456     if (!dm2off) {
  16457         return BCM_E_MEMORY;
  16458     }
  16459     sal_memset(dm2off, 0, sizeof(int)*256);
  16460 
  16461     /* alloc temp vlist */
  16462     vlist = sal_alloc(sizeof(_bcm_mn_voq_info_t) * _BCM_MN_NUM_L2_UC_LEAVES, "voq_vlist");
  16463     if (!vlist) {
  16464         sal_free(dm2off);
  16465         return BCM_E_MEMORY;
  16466     }
  16467     sal_memset(vlist, 0, sizeof(_bcm_mn_voq_info_t)*_BCM_MN_NUM_L2_UC_LEAVES);
  16468 
  16469     for (ii = 0; ii < _BCM_MN_NUM_L2_UC_LEAVES; ii++) {
  16470         node = &res->p_queue_node[ii];
  16471         if ((node->remote_modid == -1) || (node->remote_port == -1)) {
  16472             continue;
  16473         }
  16474         vlist[vcount].remote_modid = node->remote_modid;
  16475         vlist[vcount].remote_port  = node->remote_port; 
  16476         vlist[vcount].local_port   = node->local_port;
  16477         vlist[vcount].hw_cosq     = node->hw_cosq; 
  16478         vlist[vcount].node         = node;
  16479         vcount += 1;
  16480     }
  16481 
  16482     /* Sort the nodes */
  16483     _shr_sort(vlist, vcount, sizeof(_bcm_mn_voq_info_t), 
  16484                 _bcm_mn_cosq_sort_voq_list);
  16485 
  16486     for (ii = 0; ii < 128; ii++) {
  16487         p2ioff[ii] = -1;
  16488     }
  16489     
  16490     si = &SOC_INFO(unit);
  16491     PBMP_HG_ITER(unit, port) {
  16492         /* For DPVOQ, SRC_ID should be the mmu_port number */
  16493         phy_port = si->port_l2p_mapping[port];
  16494         mmu_port = si->port_p2m_mapping[phy_port];
  16495         ioff = _bcm_mn_msg_buf_get(unit, mmu_port);
  16496         p2ioff[port] = ioff;
  16497     }
  16498 
  16499     for (ii = 0; ii < vcount; ii++) {
  16500         cbmp |= 1 << vlist[ii].hw_cosq;
  16501     }
  16502 
  16503     nib_cbmp = (cbmp >> 4) | (cbmp & 0xf);
  16504 
  16505     for (ii = 0; ii < 4; ii++) {
  16506         if ((1 << ii) & nib_cbmp) {
  16507             num_cos += 1;
  16508         }
  16509     }
  16510 
  16511     for (count = 1, ii = 0; ii < vcount; ii++) {
  16512         if (dm2off[vlist[ii].remote_modid]==0) {
  16513             dm2off[vlist[ii].remote_modid] = count;
  16514         }
  16515     }
  16516 
  16517     plist = sal_alloc(sizeof(_bcm_mn_voq_info_t) * _BCM_MN_NUM_L2_UC_LEAVES, "voq_vlist");
  16518     if (!plist) {
  16519         sal_free(dm2off);
  16520         sal_free(vlist);
  16521         return BCM_E_MEMORY;
  16522     }
  16523     sal_memset(plist, 0, sizeof(_bcm_mn_voq_info_t) * _BCM_MN_NUM_L2_UC_LEAVES);
  16524 
  16525     for (pcount = 0, ii = 0; ii < vcount; ii++) {
  16526         if (pcount % 4) {
  16527             if ((plist[pcount - 1].remote_modid != vlist[ii].remote_modid) ||
  16528                 (plist[pcount - 1].remote_port != vlist[ii].remote_port)) {
  16529                 pcount = (pcount + 3) & ~3;
  16530             } else if (plist[pcount - 1].local_port != vlist[ii].local_port) {
  16531                 skip = (p2ioff[vlist[ii].local_port] - 
  16532                             p2ioff[plist[pcount - 1].local_port] - 1) * num_cos;
  16533                 skip +=  _bcm_mn_get_queue_skip_count_on_cos(nib_cbmp, 
  16534                                         plist[pcount - 1].hw_cosq,
  16535                                         vlist[ii].hw_cosq);
  16536                 if (skip >= 4) {
  16537                     pcount = ((pcount + 3) & ~3) + (skip % 4);
  16538                 } else {
  16539                     pcount += skip;
  16540                 }
  16541             } else if ((vlist[ii].hw_cosq - plist[pcount - 1].hw_cosq) > 1) {
  16542                 if (plist[pcount - 1].hw_cosq/4 != vlist[ii].hw_cosq/4) {
  16543                     pcount = (pcount + 3) & ~3;
  16544                 }
  16545                 pcount += _bcm_mn_get_queue_skip_count_on_cos(nib_cbmp, 
  16546                                         plist[pcount - 1].hw_cosq,
  16547                                         vlist[ii].hw_cosq);
  16548             }
  16549         } else {
  16550             pcount += _bcm_mn_get_queue_skip_count_on_cos(nib_cbmp, -1,
  16551                                                     vlist[ii].hw_cosq);
  16552         }
  16553        
  16554         plist[pcount].valid = 1;
  16555         plist[pcount].local_port = vlist[ii].local_port;
  16556         plist[pcount].remote_modid = vlist[ii].remote_modid;
  16557         plist[pcount].remote_port = vlist[ii].remote_port;
  16558         plist[pcount].hw_cosq = vlist[ii].hw_cosq;
  16559         plist[pcount].node = vlist[ii].node;
  16560         
  16561         #ifdef DEBUG_MN_COSQ
  16562           LOG_CLI((BSL_META_U(unit,
  16563                               "DPVOQ DM=%d DP=%d LocalPort=%d COS=%d HWIndex=%d\n"),
  16564                    plist[pcount].remote_modid,
  16565                    plist[pcount].remote_port,
  16566                    plist[pcount].local_port,
  16567                    plist[pcount].hw_cosq,
  16568                    plist[pcount].node->hw_index));
  16569         #endif
  16570         pcount += 1;
  16571     }
  16572 
  16573     /* program the voq port profiles. */
  16574     voq_port_map_entries = sal_alloc(sizeof(voq_port_map_entry_t)*128, 
  16575                                         "voq port map entries");
  16576     if (!voq_port_map_entries) {
  16577         goto fail;
  16578     }
  16579     sal_memset(voq_port_map_entries, 0, sizeof(voq_port_map_entry_t)*128);
  16580 
  16581     entries[0] = voq_port_map_entries;
  16582     dm = -1;
  16583     rp = -1;
  16584     for (ii = 0; ii <= pcount; ii++) {
  16585         if (plist[ii].valid == 1) {
  16586             rv = READ_ING_COS_MODE_64r(unit, plist[ii].local_port, &rval64);
  16587             if (rv) {
  16588                 goto fail;
  16589             }
  16590             port_q_base = soc_reg64_field32_get(unit, ING_COS_MODE_64r, rval64,
  16591                                 BASE_QUEUE_NUM_1f);
  16592         }
  16593 
  16594         if ((ii == pcount) ||
  16595             ((dm != -1) && (plist[ii].valid) &&
  16596             (plist[ii].remote_modid != dm))) {
  16597             
  16598             rv = READ_VOQ_MOD_MAPm(unit, MEM_BLOCK_ALL, dm, &voq_mod_map);
  16599             if (rv) {
  16600                 goto fail;
  16601             }     
  16602             if (soc_mem_field32_get(unit, VOQ_MOD_MAPm, 
  16603                                                 &voq_mod_map, VOQ_VALIDf)) {
  16604                 profile = soc_mem_field32_get(unit, VOQ_MOD_MAPm, 
  16605                               &voq_mod_map, VOQ_MOD_PORT_PROFILE_INDEXf);
  16606                 
  16607                 rv = soc_profile_mem_delete(unit, 
  16608                             _bcm_mn_voq_port_map_profile[unit], profile*128);
  16609                 if (rv) {
  16610                     goto fail;
  16611                 }
  16612             }
  16613             rv = soc_profile_mem_add(unit, 
  16614                                 _bcm_mn_voq_port_map_profile[unit], 
  16615                                 entries, 128, &profile);
  16616             if (rv) {
  16617                 goto fail;
  16618             }
  16619 
  16620             soc_mem_field32_set(unit, VOQ_MOD_MAPm, &voq_mod_map, 
  16621                                 VOQ_MOD_PORT_PROFILE_INDEXf, profile/128);
  16622             soc_mem_field32_set(unit, VOQ_MOD_MAPm, &voq_mod_map, 
  16623                                 VOQ_VALIDf, 1);
  16624             soc_mem_field32_set(unit, VOQ_MOD_MAPm, &voq_mod_map, 
  16625                                 VOQ_MOD_OFFSETf, mod_base);
  16626             soc_mem_field32_set(unit, VOQ_MOD_MAPm, &voq_mod_map, 
  16627                                 VOQ_MOD_USE_PORTf, 1);
  16628             rv = soc_mem_write(unit, VOQ_MOD_MAPm, MEM_BLOCK_ALL, 
  16629                                dm, &voq_mod_map);
  16630             if (rv) {
  16631                 goto fail;
  16632             }
  16633 
  16634             sal_memset(voq_port_map_entries, 0, sizeof(voq_port_map_entry_t)*128);
  16635 
  16636             if (ii != pcount) {
  16637                 if (plist[ii].node) {
  16638                     mod_base = (plist[ii].node->hw_index & ~3) - port_q_base;
  16639                 }
  16640             }
  16641         }
  16642 
  16643         if (ii == pcount) {
  16644             break;
  16645         }
  16646 
  16647         if (plist[ii].valid == 0) {
  16648             continue;
  16649         }
  16650 
  16651         if (dm == -1) {
  16652             if (plist[ii].node) {
  16653                 mod_base = (plist[ii].node->hw_index & ~3) - port_q_base;
  16654             }
  16655         }
  16656 
  16657         dm = plist[ii].remote_modid;
  16658 
  16659         if ((rp == -1) || 
  16660             (rp != plist[ii].remote_port)) {
  16661             rp = plist[ii].remote_port;
  16662             soc_mem_field32_set(unit, VOQ_PORT_MAPm, 
  16663                                 &voq_port_map_entries[plist[ii].remote_port], 
  16664                                 VOQ_PORT_OFFSETf, 
  16665                                 (plist[ii].node->hw_index - mod_base - port_q_base) & 0x3fff);
  16666         }
  16667     }
  16668 
  16669     for (priority = 0; priority < 16; priority++) {
  16670         rv = READ_VOQ_COS_MAPm(unit, MEM_BLOCK_ALL, priority, &voq_cos_map);
  16671         if (rv) {
  16672             goto fail;
  16673         }
  16674         
  16675         /* Setting the  VOQ_PORT_BASE_SELECT,
  16676            so that BASE_QUEUE_NUM_1 is used for queue
  16677            calculation */
  16678 
  16679         soc_mem_field32_set(unit, VOQ_COS_MAPm, 
  16680                 &voq_cos_map, VOQ_PORT_BASE_SELECTf, pcount ? 1 : 0);
  16681         soc_mem_field32_set(unit, VOQ_COS_MAPm, 
  16682                             &voq_cos_map, VOQ_COS_USE_MODf, pcount ? 1 : 0);
  16683         soc_mem_field32_set(unit, VOQ_COS_MAPm, 
  16684                             &voq_cos_map, VOQ_COS_USE_PORTf, pcount ? 1 : 0);
  16685  
  16686         rv = soc_mem_write(unit, VOQ_COS_MAPm, MEM_BLOCK_ANY, priority,
  16687                     &voq_cos_map);
  16688         if (rv) {
  16689             goto fail;
  16690         }
  16691     }
  16692 
  16693     dm = -1;
  16694     for (ii = 0; ii < pcount; ii += 1) {
  16695         if (plist[ii].valid == 0) {
  16696             continue;
  16697         }
  16698         phy_port = si->port_l2p_mapping[plist[ii].local_port];
  16699         mmu_port = si->port_p2m_mapping[phy_port];
  16700 
  16701         cng_offset = (dm2off[plist[ii].remote_modid] - 1) * 
  16702                         cng_bytes_per_e2ecc_msg;
  16703 
  16704         /*
  16705          * Base index table addr = {< interface number>,BUF_CFG<interface number>__PROFILE_ID}
  16706          * If incoming message mmu port number matches say interface 4's SRC_ID,
  16707          * then it will address base_index_table as {0, BUF_CFG4_PROFILE_ID}.
  16708          * Since profile_id is 2 bits, we index base_index_table in multiple of 4.
  16709          */
  16710 
  16711         intf_index = _bcm_mn_msg_buf_get(unit, mmu_port);
  16712         if (intf_index < 0) {
  16713             return BCM_E_INTERNAL;
  16714         }
  16715 
  16716         BCM_IF_ERROR_RETURN
  16717             (soc_mem_read(unit, MMU_INTFI_BASE_INDEX_TBLm, 
  16718                         MEM_BLOCK_ALL, intf_index * 4, &base_tbl_entry));
  16719         
  16720         soc_mem_field32_set(unit, MMU_INTFI_BASE_INDEX_TBLm, &base_tbl_entry, 
  16721                 BASE_ADDRf, cng_offset);
  16722         soc_mem_field32_set(unit, MMU_INTFI_BASE_INDEX_TBLm, &base_tbl_entry, 
  16723                 ENf, 2);
  16724 
  16725         BCM_IF_ERROR_RETURN(soc_mem_write(unit, MMU_INTFI_BASE_INDEX_TBLm,
  16726                     MEM_BLOCK_ALL, intf_index * 4, &base_tbl_entry));
  16727 
  16728         /* Each byte of message should correspond to 2 entries in FC_ST_TBL2.
  16729          * Hence port * 2.
  16730          */
  16731         _bcm_mn_map_fc_status_to_node(unit, 
  16732                                        plist[ii].local_port,
  16733                                        _BCM_MN_COSQ_FC_E2ECC,
  16734                                        cng_offset + (plist[ii].remote_port * 2), 
  16735                                        plist[ii].hw_cosq,
  16736                                        plist[ii].node->hw_index,
  16737                                        SOC_MONTEREY_NODE_LVL_L2);
  16738     }
  16739    
  16740 fail:
  16741     if (vlist) {
  16742         sal_free(vlist);
  16743     }
  16744 
  16745     if (plist) {
  16746         sal_free(plist);
  16747     }
  16748 
  16749     if (dm2off) {
  16750         sal_free(dm2off);
  16751     }
  16752     
  16753     if (voq_port_map_entries) {
  16754         sal_free(voq_port_map_entries);
  16755     }
  16756 
  16757     if (rv) {
  16758         node->remote_modid = -1;
  16759         node->remote_port = -1;
  16760     }
  16761     return rv;
  16762 }
  16763 
  16764 STATIC int
  16765 _bcm_mn_gport_dmvoq_config_set(int unit, bcm_gport_t gport, 
  16766                                 bcm_cos_queue_t cosq,
  16767                                 bcm_module_t fabric_modid, 
  16768                                 bcm_module_t dest_modid,
  16769                                 bcm_port_t fabric_port)
  16770 {
  16771     int port_voq_base, intf_index;
  16772     _bcm_mn_cosq_node_t *node;
  16773     _bcm_mn_cosq_node_t *base_node = NULL;
  16774     bcm_port_t local_port;
  16775     voq_mod_map_entry_t voq_mod_map_entry;
  16776     mmu_intfi_offset_map_tbl_entry_t offset_map_tbl_entry;
  16777     mmu_intfi_base_index_tbl_entry_t base_tbl_entry;
  16778     uint32 cng_offset = 0;
  16779     _bcm_mn_mmu_info_t *mmu_info;
  16780     int fabric_port_count, count = 0;
  16781     int map_offset = 0;
  16782     int port = 0;
  16783 
  16784     if ((mmu_info = _bcm_mn_mmu_info[unit]) == NULL) {
  16785         return BCM_E_INIT;
  16786     }
  16787 
  16788     if (fabric_modid >= 64) {
  16789         return BCM_E_PARAM;
  16790     }
  16791 
  16792     BCM_IF_ERROR_RETURN
  16793       (_bcm_mn_cosq_node_get(unit, gport, 0, NULL, &local_port, NULL, &node));
  16794 
  16795     if (!node) {
  16796         return BCM_E_NOT_FOUND;
  16797     }
  16798 
  16799     BCM_IF_ERROR_RETURN(_bcm_mn_resolve_dmvoq_hw_index(unit, node, cosq,
  16800                 dest_modid, local_port));
  16801     BCM_IF_ERROR_RETURN(_bcm_mn_voq_base_node_get(
  16802                 unit, local_port, dest_modid, &base_node));
  16803     if (base_node == NULL) {
  16804         base_node = node ;
  16805     }
  16806     BCM_PBMP_COUNT(base_node->fabric_pbmp, fabric_port_count);
  16807     if (fabric_port_count == 0) {
  16808         map_offset = mmu_info->curr_merger_index;
  16809         if (map_offset >= soc_mem_index_count(unit, MMU_INTFI_MERGE_ST_TBLm)) {
  16810             return BCM_E_RESOURCE;
  16811         }
  16812     } else {
  16813         BCM_PBMP_ITER(base_node->fabric_pbmp, port) {
  16814             BCM_IF_ERROR_RETURN(soc_mem_read(unit, MMU_INTFI_OFFSET_MAP_TBLm, 
  16815                         MEM_BLOCK_ALL, 
  16816                         port * 2, &offset_map_tbl_entry));
  16817             map_offset = soc_mem_field32_get(unit, MMU_INTFI_OFFSET_MAP_TBLm,
  16818                     &offset_map_tbl_entry,
  16819                     MAP_OFFSETf);
  16820             break;
  16821         }
  16822     }
  16823     if (!BCM_PBMP_MEMBER(base_node->fabric_pbmp, fabric_port)) {
  16824         if (map_offset == mmu_info->curr_merger_index ) {
  16825             mmu_info->curr_merger_index += 2;
  16826         }
  16827 
  16828         BCM_PBMP_PORT_ADD (base_node->fabric_pbmp, fabric_port);
  16829         BCM_PBMP_COUNT(base_node->fabric_pbmp, fabric_port_count);
  16830         BCM_PBMP_ITER(base_node->fabric_pbmp, port) {
  16831             count++;
  16832             BCM_IF_ERROR_RETURN(soc_mem_read(unit, MMU_INTFI_OFFSET_MAP_TBLm, 
  16833                         MEM_BLOCK_ALL, 
  16834                         port * 2, &offset_map_tbl_entry));
  16835             soc_mem_field32_set(unit, MMU_INTFI_OFFSET_MAP_TBLm, 
  16836                     &offset_map_tbl_entry,
  16837                     MAP_OFFSETf, map_offset);
  16838             soc_mem_field32_set(unit, MMU_INTFI_OFFSET_MAP_TBLm, 
  16839                     &offset_map_tbl_entry,
  16840                     LASTf, count < fabric_port_count ? 0 : 1 );
  16841             BCM_IF_ERROR_RETURN(soc_mem_write(unit, MMU_INTFI_OFFSET_MAP_TBLm, 
  16842                         MEM_BLOCK_ALL, 
  16843                         port * 2, &offset_map_tbl_entry));
  16844 
  16845             BCM_IF_ERROR_RETURN(soc_mem_read(unit, MMU_INTFI_OFFSET_MAP_TBLm, 
  16846                         MEM_BLOCK_ALL, 
  16847                         (port * 2) + 1, &offset_map_tbl_entry));
  16848             soc_mem_field32_set(unit, MMU_INTFI_OFFSET_MAP_TBLm, 
  16849                     &offset_map_tbl_entry,
  16850                     MAP_OFFSETf, map_offset + 1);
  16851             soc_mem_field32_set(unit, MMU_INTFI_OFFSET_MAP_TBLm, 
  16852                     &offset_map_tbl_entry,
  16853                     LASTf, count < fabric_port_count ? 0 : 1 );
  16854             BCM_IF_ERROR_RETURN(soc_mem_write(unit, MMU_INTFI_OFFSET_MAP_TBLm, 
  16855                         MEM_BLOCK_ALL, 
  16856                         (port * 2) + 1, &offset_map_tbl_entry));
  16857         }
  16858     }
  16859 
  16860     BCM_IF_ERROR_RETURN(soc_mem_read(unit, VOQ_MOD_MAPm, MEM_BLOCK_ALL, 
  16861                 dest_modid, &voq_mod_map_entry));
  16862     BCM_IF_ERROR_RETURN(_bcm_mn_port_voq_base_get(unit, local_port, 
  16863                 &port_voq_base));
  16864     soc_mem_field32_set(unit, VOQ_MOD_MAPm, &voq_mod_map_entry,
  16865             VOQ_VALIDf, 1);
  16866     soc_mem_field32_set(unit, VOQ_MOD_MAPm, &voq_mod_map_entry,
  16867                     VOQ_MOD_OFFSETf, ((node->hw_index & ~7) - port_voq_base));
  16868 
  16869     BCM_IF_ERROR_RETURN(
  16870             soc_mem_write(unit, VOQ_MOD_MAPm, MEM_BLOCK_ALL, dest_modid, 
  16871                 &voq_mod_map_entry));
  16872 
  16873     intf_index = _bcm_mn_msg_buf_get(unit, fabric_modid);
  16874     if (intf_index < 0) {
  16875         return BCM_E_INTERNAL;
  16876     }
  16877 
  16878     cng_offset = intf_index * 64 * 2;
  16879 
  16880     BCM_IF_ERROR_RETURN
  16881         (soc_mem_read(unit, MMU_INTFI_BASE_INDEX_TBLm, 
  16882                       MEM_BLOCK_ALL, fabric_modid, &base_tbl_entry));
  16883     
  16884     soc_mem_field32_set(unit, MMU_INTFI_BASE_INDEX_TBLm, &base_tbl_entry, 
  16885             BASE_ADDRf, cng_offset);
  16886     soc_mem_field32_set(unit, MMU_INTFI_BASE_INDEX_TBLm, &base_tbl_entry, 
  16887             ENf, 2);
  16888 
  16889     BCM_IF_ERROR_RETURN(soc_mem_write(unit, MMU_INTFI_BASE_INDEX_TBLm,
  16890                 MEM_BLOCK_ALL, fabric_modid, &base_tbl_entry));
  16891 
  16892     /* set the mapping from congestion bits in flow control table
  16893      * to corresponding cosq. */
  16894     BCM_IF_ERROR_RETURN(_bcm_mn_map_fc_status_to_node(unit, local_port,
  16895                 _BCM_MN_COSQ_FC_VOQFC, cng_offset + map_offset, 
  16896                 cosq, node->hw_index, SOC_MONTEREY_NODE_LVL_L2));
  16897 
  16898     #ifdef DEBUG_MN_COSQ
  16899     LOG_CLI((BSL_META_U(unit,
  16900                         "Gport=0x%08x hw_index=%d cosq=%d\n"),
  16901              gport, node->hw_index, cosq));
  16902     #endif
  16903 
  16904     return BCM_E_NONE;
  16905 }
  16906 
  16907 int bcm_mn_cosq_gport_congestion_config_set(int unit, bcm_gport_t gport, 
  16908                                          bcm_cos_queue_t cosq, 
  16909                                          bcm_cosq_congestion_info_t *config)
  16910 {
  16911     _bcm_mn_mmu_info_t *mmu_info;
  16912 
  16913     if (!config) {
  16914         return BCM_E_PARAM;
  16915     }
  16916 
  16917     if ((mmu_info = _bcm_mn_mmu_info[unit]) == NULL) {
  16918         return BCM_E_INIT;
  16919     }
  16920 
  16921     /* determine if this gport is DPVOQ or DMVOQ */
  16922     if ((config->fabric_port != -1) && (config->dest_modid != -1)) {
  16923         return _bcm_mn_gport_dmvoq_config_set(unit, gport, cosq, 
  16924                                                config->fabric_modid,
  16925                                                config->dest_modid,
  16926                                                config->fabric_port);
  16927     } else if ((config->dest_modid != -1) && (config->dest_port != -1)) {
  16928         return _bcm_mn_gport_dpvoq_config_set(unit, gport, cosq, 
  16929                                                config->dest_modid,
  16930                                                config->dest_port);
  16931     }
  16932     
  16933     return BCM_E_PARAM;
  16934 }
  16935 
  16936 int bcm_mn_cosq_gport_congestion_config_get(int unit, bcm_gport_t port, 
  16937                                          bcm_cos_queue_t cosq, 
  16938                                          bcm_cosq_congestion_info_t *config)
  16939 {
  16940     _bcm_mn_mmu_info_t *mmu_info;
  16941     bcm_port_t local_port;
  16942     _bcm_mn_cosq_node_t *node;
  16943 
  16944     if (!config) {
  16945         return BCM_E_PARAM;
  16946     }
  16947 
  16948     if ((mmu_info = _bcm_mn_mmu_info[unit]) == NULL) {
  16949         return BCM_E_INIT;
  16950     }
  16951 
  16952     BCM_IF_ERROR_RETURN
  16953       (_bcm_mn_cosq_node_get(unit, port, 0, NULL, &local_port, NULL, &node));
  16954 
  16955 
  16956     if (!node) {
  16957         return BCM_E_NOT_FOUND;
  16958     }
  16959 
  16960     config->dest_modid = node->remote_modid;
  16961     config->dest_port = node->remote_port;
  16962 
  16963     return BCM_E_NONE;
  16964 }
  16965 
  16966 
  16967 
  16968 int bcm_mn_cosq_bst_profile_set(int unit, 
  16969                                  bcm_gport_t port, 
  16970                                  bcm_cos_queue_t cosq, 
  16971                                  bcm_bst_stat_id_t bid,
  16972                                  bcm_cosq_bst_profile_t *profile)
  16973 {
  16974     BCM_IF_ERROR_RETURN(_bcm_bst_cmn_profile_set
  16975         (unit, port, cosq, BCM_BST_DUP_XPE, bid, profile));
  16976     return BCM_E_NONE;
  16977 }
  16978 
  16979 int bcm_mn_cosq_bst_profile_get(int unit, 
  16980                                  bcm_gport_t port, 
  16981                                  bcm_cos_queue_t cosq, 
  16982                                  bcm_bst_stat_id_t bid,
  16983                                  bcm_cosq_bst_profile_t *profile)
  16984 {
  16985     BCM_IF_ERROR_RETURN(_bcm_bst_cmn_profile_get
  16986         (unit, port, cosq, BCM_BST_DUP_XPE, bid, profile));
  16987     return BCM_E_NONE;
  16988 }
  16989 
  16990 int bcm_mn_cosq_bst_stat_get(int unit, 
  16991                               bcm_gport_t port, 
  16992                               bcm_cos_queue_t cosq, 
  16993                               bcm_bst_stat_id_t bid, 
  16994                               uint32 options,
  16995                               uint64 *pvalue)
  16996 {
  16997     return _bcm_bst_cmn_stat_get(unit, port, cosq,-1,  bid, options, pvalue);
  16998 }
  16999 
  17000 int bcm_mn_cosq_bst_stat_multi_get(int unit,
  17001                                 bcm_gport_t port,
  17002                                 bcm_cos_queue_t cosq,
  17003                                 uint32 options,
  17004                                 int max_values,
  17005                                 bcm_bst_stat_id_t *id_list,
  17006                                 uint64 *pvalues)
  17007 {
  17008     return _bcm_bst_cmn_stat_multi_get(unit, port, cosq, options, max_values, 
  17009                                     id_list, pvalues);
  17010 }
  17011 
  17012 int bcm_mn_cosq_bst_stat_clear(int unit, bcm_gport_t port, 
  17013                             bcm_cos_queue_t cosq, bcm_bst_stat_id_t bid)
  17014 {
  17015     return _bcm_bst_cmn_stat_clear(unit, port, cosq, bid);
  17016 }
  17017 
  17018 int bcm_mn_cosq_bst_stat_sync(int unit, bcm_bst_stat_id_t bid)
  17019 {
  17020     return _bcm_bst_cmn_stat_sync(unit, bid);
  17021 }
  17022 
  17023 
  17024 /*
  17025  * Function:
  17026  *      _bcm_mn_cosq_endpoint_l2_create
  17027  * Purpose:
  17028  *      Create a L2 endpoint.
  17029  * Parameters:
  17030  *      unit        - (IN) Unit number.
  17031  *      endpoint_id - (IN) Endpoint ID
  17032  *      vlan        - (IN) VLAN
  17033  *      mac         - (IN) MAC address
  17034  * Returns:
  17035  *      BCM_E_xxx
  17036  */
  17037 STATIC int
  17038 _bcm_mn_cosq_endpoint_l2_create(
  17039     int unit, 
  17040     int endpoint_id,
  17041     bcm_vlan_t vlan,
  17042     bcm_mac_t mac)
  17043 {
  17044     int rv;
  17045     bcm_l2_addr_t l2addr;
  17046     l2_endpoint_id_entry_t l2_endpoint_entry;
  17047     int vfi;
  17048 
  17049     /* Make sure (vlan, mac) entry is already in L2 table */
  17050     rv = bcm_esw_l2_addr_get(unit, mac, vlan, &l2addr);
  17051     if (rv == BCM_E_NOT_FOUND) {
  17052         /* The (vlan, mac) entry needs to be added to L2 table
  17053          * before configuring it for endpoint queuing.
  17054          */
  17055         return BCM_E_CONFIG;
  17056     } else if (BCM_FAILURE(rv)) {
  17057         return rv;
  17058     }
  17059 
  17060     /* Add (vlan, mac) entry to L2_ENDPOINT_ID table */
  17061     sal_memcpy(&l2_endpoint_entry, soc_mem_entry_null(unit, L2_ENDPOINT_IDm),
  17062             sizeof(l2_endpoint_id_entry_t));
  17063     soc_L2_ENDPOINT_IDm_field32_set(unit, &l2_endpoint_entry, VALIDf, 1);
  17064     if (_BCM_MPLS_VPN_IS_VPLS(vlan)) {
  17065         _BCM_MPLS_VPN_GET(vfi, _BCM_MPLS_VPN_TYPE_VPLS, vlan);
  17066         soc_L2_ENDPOINT_IDm_field32_set(unit, &l2_endpoint_entry, L2__VFIf,
  17067                 vfi);
  17068         soc_L2_ENDPOINT_IDm_field32_set(unit, &l2_endpoint_entry, KEY_TYPEf,
  17069                 TD2_L2_HASH_KEY_TYPE_VFI);
  17070     } else if (_BCM_IS_MIM_VPN(vlan)) {
  17071         _BCM_MIM_VPN_GET(vfi, _BCM_MIM_VPN_TYPE_MIM, vlan);
  17072         soc_L2_ENDPOINT_IDm_field32_set(unit, &l2_endpoint_entry, L2__VFIf,
  17073                 vfi);
  17074         soc_L2_ENDPOINT_IDm_field32_set(unit, &l2_endpoint_entry, KEY_TYPEf,
  17075                 TD2_L2_HASH_KEY_TYPE_VFI);
  17076     } else {
  17077         VLAN_CHK_ID(unit, vlan);
  17078         soc_L2_ENDPOINT_IDm_field32_set(unit, &l2_endpoint_entry, L2__VLAN_IDf,
  17079                 vlan);
  17080         soc_L2_ENDPOINT_IDm_field32_set(unit, &l2_endpoint_entry, KEY_TYPEf,
  17081                 TD2_L2_HASH_KEY_TYPE_BRIDGE);
  17082     }
  17083     soc_L2_ENDPOINT_IDm_mac_addr_set(unit, &l2_endpoint_entry, L2__MAC_ADDRf,
  17084             mac);
  17085     soc_L2_ENDPOINT_IDm_field32_set(unit, &l2_endpoint_entry, EH_TAG_TYPEf, 2);
  17086     soc_L2_ENDPOINT_IDm_field32_set(unit, &l2_endpoint_entry, EH_QUEUE_TAGf,
  17087             endpoint_id);
  17088     SOC_IF_ERROR_RETURN(soc_mem_insert(unit, L2_ENDPOINT_IDm, MEM_BLOCK_ANY,
  17089                 &l2_endpoint_entry));
  17090 
  17091     return BCM_E_NONE;
  17092 }
  17093 
  17094 /*
  17095  * Function:
  17096  *      _bcm_mn_cosq_endpoint_l2_destroy
  17097  * Purpose:
  17098  *      Destroy a L2 endpoint.
  17099  * Parameters:
  17100  *      unit        - (IN) Unit number.
  17101  *      vlan        - (IN) VLAN
  17102  *      mac         - (IN) MAC address
  17103  * Returns:
  17104  *      BCM_E_xxx
  17105  */
  17106 STATIC int
  17107 _bcm_mn_cosq_endpoint_l2_destroy(
  17108     int unit, 
  17109     bcm_vlan_t vlan,
  17110     bcm_mac_t mac)
  17111 {
  17112     l2_endpoint_id_entry_t l2_endpoint_entry;
  17113     int vfi;
  17114 
  17115     /* Delete (vlan, mac) entry from L2_ENDPOINT_ID table */
  17116     sal_memcpy(&l2_endpoint_entry, soc_mem_entry_null(unit, L2_ENDPOINT_IDm),
  17117             sizeof(l2_endpoint_id_entry_t));
  17118     if (_BCM_MPLS_VPN_IS_VPLS(vlan)) {
  17119         _BCM_MPLS_VPN_GET(vfi, _BCM_MPLS_VPN_TYPE_VPLS, vlan);
  17120         soc_L2_ENDPOINT_IDm_field32_set(unit, &l2_endpoint_entry, L2__VFIf,
  17121                 vfi);
  17122         soc_L2_ENDPOINT_IDm_field32_set(unit, &l2_endpoint_entry, KEY_TYPEf,
  17123                 TD2_L2_HASH_KEY_TYPE_VFI);
  17124     } else if (_BCM_IS_MIM_VPN(vlan)) {
  17125         _BCM_MIM_VPN_GET(vfi, _BCM_MIM_VPN_TYPE_MIM, vlan);
  17126         soc_L2_ENDPOINT_IDm_field32_set(unit, &l2_endpoint_entry, L2__VFIf,
  17127                 vfi);
  17128         soc_L2_ENDPOINT_IDm_field32_set(unit, &l2_endpoint_entry, KEY_TYPEf,
  17129                 TD2_L2_HASH_KEY_TYPE_VFI);
  17130     } else {
  17131         VLAN_CHK_ID(unit, vlan);
  17132         soc_L2_ENDPOINT_IDm_field32_set(unit, &l2_endpoint_entry, L2__VLAN_IDf,
  17133                 vlan);
  17134         soc_L2_ENDPOINT_IDm_field32_set(unit, &l2_endpoint_entry, KEY_TYPEf,
  17135                 TD2_L2_HASH_KEY_TYPE_BRIDGE);
  17136     }
  17137     soc_L2_ENDPOINT_IDm_mac_addr_set(unit, &l2_endpoint_entry, L2__MAC_ADDRf,
  17138             mac);
  17139     SOC_IF_ERROR_RETURN(soc_mem_delete(unit, L2_ENDPOINT_IDm, MEM_BLOCK_ANY,
  17140                 &l2_endpoint_entry));
  17141 
  17142     return BCM_E_NONE;
  17143 }
  17144 
  17145 #ifdef INCLUDE_L3
  17146 /*
  17147  * Function:
  17148  *      _bcm_mn_cosq_endpoint_ip4_create
  17149  * Purpose:
  17150  *      Create an IPv4 endpoint.
  17151  * Parameters:
  17152  *      unit        - (IN) Unit number.
  17153  *      endpoint_id - (IN) Endpoint ID
  17154  *      vrf         - (IN) Virtual router instance
  17155  *      ip_addr     - (IN) IPv4 address
  17156  * Returns:
  17157  *      BCM_E_xxx
  17158  */
  17159 STATIC int
  17160 _bcm_mn_cosq_endpoint_ip4_create(
  17161     int unit, 
  17162     int endpoint_id,
  17163     bcm_vrf_t vrf,
  17164     bcm_ip_t ip_addr)
  17165 {
  17166     int rv;
  17167     _bcm_l3_cfg_t l3cfg;
  17168 
  17169     if ((vrf > SOC_VRF_MAX(unit)) || 
  17170         (vrf < BCM_L3_VRF_DEFAULT)) {
  17171         return BCM_E_PARAM;
  17172     }
  17173 
  17174     L3_LOCK(unit);
  17175 
  17176     /* Make sure (vrf, ip_addr) entry is already in L3 host table */
  17177     sal_memset(&l3cfg, 0, sizeof(_bcm_l3_cfg_t));
  17178     l3cfg.l3c_vrf = vrf;
  17179     l3cfg.l3c_ip_addr = ip_addr;
  17180     rv = mbcm_driver[unit]->mbcm_l3_ip4_get(unit, &l3cfg);
  17181     if (rv == BCM_E_NOT_FOUND) {
  17182         /* The (vrf, ip_addr) entry needs to be added to L3 table
  17183          * before configuring it for endpoint queuing.
  17184          */
  17185         L3_UNLOCK(unit);
  17186         return BCM_E_CONFIG;
  17187     } else if (BCM_FAILURE(rv)) {
  17188         L3_UNLOCK(unit);
  17189         return rv;
  17190     }
  17191 
  17192     if (l3cfg.l3c_eh_q_tag_type != 0) {
  17193         /* A queue tag has already been configured for this L3 entry. */
  17194         L3_UNLOCK(unit);
  17195         return BCM_E_EXISTS;
  17196     }
  17197 
  17198     /* Replace (vrf, ip_addr) entry's endpoint_id */
  17199     l3cfg.l3c_flags |= BCM_L3_REPLACE;
  17200     l3cfg.l3c_eh_q_tag_type = 2;
  17201     l3cfg.l3c_eh_q_tag = endpoint_id;
  17202     rv = mbcm_driver[unit]->mbcm_l3_ip4_replace(unit, &l3cfg);
  17203     if (BCM_FAILURE(rv)) {
  17204         L3_UNLOCK(unit);
  17205         return rv;
  17206     }
  17207 
  17208     L3_UNLOCK(unit);
  17209 
  17210     return rv;
  17211 }
  17212 
  17213 /*
  17214  * Function:
  17215  *      _bcm_mn_cosq_endpoint_ip4_destroy
  17216  * Purpose:
  17217  *      Destroy an IPv4 endpoint.
  17218  * Parameters:
  17219  *      unit        - (IN) Unit number.
  17220  *      vrf         - (IN) Virtual router instance
  17221  *      ip_addr     - (IN) IPv4 address
  17222  * Returns:
  17223  *      BCM_E_xxx
  17224  */
  17225 STATIC int
  17226 _bcm_mn_cosq_endpoint_ip4_destroy(
  17227     int unit, 
  17228     bcm_vrf_t vrf,
  17229     bcm_ip_t ip_addr)
  17230 {
  17231     int rv;
  17232     _bcm_l3_cfg_t l3cfg;
  17233 
  17234     if ((vrf > SOC_VRF_MAX(unit)) || 
  17235         (vrf < BCM_L3_VRF_DEFAULT)) {
  17236         return BCM_E_PARAM;
  17237     }
  17238 
  17239     L3_LOCK(unit);
  17240 
  17241     /* Get (vrf, ip_addr) entry */
  17242     sal_memset(&l3cfg, 0, sizeof(_bcm_l3_cfg_t));
  17243     l3cfg.l3c_vrf = vrf;
  17244     l3cfg.l3c_ip_addr = ip_addr;
  17245     rv = mbcm_driver[unit]->mbcm_l3_ip4_get(unit, &l3cfg);
  17246     if (BCM_FAILURE(rv)) {
  17247         L3_UNLOCK(unit);
  17248         return rv;
  17249     }
  17250 
  17251     /* Delete (vrf, ip_addr) entry's endpoint_id */
  17252     l3cfg.l3c_flags |= BCM_L3_REPLACE;
  17253     l3cfg.l3c_eh_q_tag_type = 0;
  17254     l3cfg.l3c_eh_q_tag = 0;
  17255     rv = mbcm_driver[unit]->mbcm_l3_ip4_replace(unit, &l3cfg);
  17256     if (BCM_FAILURE(rv)) {
  17257         L3_UNLOCK(unit);
  17258         return rv;
  17259     }
  17260 
  17261     L3_UNLOCK(unit);
  17262 
  17263     return rv;
  17264 }
  17265 
  17266 /*
  17267  * Function:
  17268  *      _bcm_mn_cosq_endpoint_ip6_create
  17269  * Purpose:
  17270  *      Create an IPv6 endpoint.
  17271  * Parameters:
  17272  *      unit        - (IN) Unit number.
  17273  *      endpoint_id - (IN) Endpoint ID
  17274  *      vrf         - (IN) Virtual router instance
  17275  *      ip6_addr    - (IN) IPv6 address
  17276  * Returns:
  17277  *      BCM_E_xxx
  17278  */
  17279 STATIC int
  17280 _bcm_mn_cosq_endpoint_ip6_create(
  17281     int unit, 
  17282     int endpoint_id,
  17283     bcm_vrf_t vrf,
  17284     bcm_ip6_t ip6_addr)
  17285 {
  17286     int rv;
  17287     _bcm_l3_cfg_t l3cfg;
  17288 
  17289     if ((vrf > SOC_VRF_MAX(unit)) || 
  17290         (vrf < BCM_L3_VRF_DEFAULT)) {
  17291         return BCM_E_PARAM;
  17292     }
  17293 
  17294     L3_LOCK(unit);
  17295 
  17296     /* Make sure (vrf, ip6_addr) entry is already in L3 host table */
  17297     sal_memset(&l3cfg, 0, sizeof(_bcm_l3_cfg_t));
  17298     l3cfg.l3c_flags = BCM_L3_IP6;
  17299     l3cfg.l3c_vrf = vrf;
  17300     sal_memcpy(l3cfg.l3c_ip6, ip6_addr, BCM_IP6_ADDRLEN);
  17301     rv = mbcm_driver[unit]->mbcm_l3_ip6_get(unit, &l3cfg);
  17302     if (rv == BCM_E_NOT_FOUND) {
  17303         /* The (vrf, ip6_addr) entry needs to be added to L3 table
  17304          * before configuring it for endpoint queuing.
  17305          */
  17306         L3_UNLOCK(unit);
  17307         return BCM_E_CONFIG;
  17308     } else if (BCM_FAILURE(rv)) {
  17309         L3_UNLOCK(unit);
  17310         return rv;
  17311     }
  17312 
  17313     if (l3cfg.l3c_eh_q_tag_type != 0) {
  17314         /* A queue tag has already been configured for this L3 entry. */
  17315         L3_UNLOCK(unit);
  17316         return BCM_E_EXISTS;
  17317     }
  17318 
  17319     /* Replace (vrf, ip_addr) entry's endpoint_id */
  17320     l3cfg.l3c_flags |= BCM_L3_REPLACE;
  17321     l3cfg.l3c_eh_q_tag_type = 2;
  17322     l3cfg.l3c_eh_q_tag = endpoint_id;
  17323     rv = mbcm_driver[unit]->mbcm_l3_ip6_replace(unit, &l3cfg);
  17324     if (BCM_FAILURE(rv)) {
  17325         L3_UNLOCK(unit);
  17326         return rv;
  17327     }
  17328 
  17329     L3_UNLOCK(unit);
  17330 
  17331     return rv;
  17332 }
  17333 
  17334 /*
  17335  * Function:
  17336  *      _bcm_mn_cosq_endpoint_ip6_destroy
  17337  * Purpose:
  17338  *      Destroy an IPv6 endpoint.
  17339  * Parameters:
  17340  *      unit        - (IN) Unit number.
  17341  *      vrf         - (IN) Virtual router instance
  17342  *      ip6_addr    - (IN) IPv6 address
  17343  * Returns:
  17344  *      BCM_E_xxx
  17345  */
  17346 STATIC int
  17347 _bcm_mn_cosq_endpoint_ip6_destroy(
  17348     int unit, 
  17349     bcm_vrf_t vrf,
  17350     bcm_ip6_t ip6_addr)
  17351 {
  17352     int rv;
  17353     _bcm_l3_cfg_t l3cfg;
  17354 
  17355     if ((vrf > SOC_VRF_MAX(unit)) || 
  17356         (vrf < BCM_L3_VRF_DEFAULT)) {
  17357         return BCM_E_PARAM;
  17358     }
  17359 
  17360     L3_LOCK(unit);
  17361 
  17362     /* Get (vrf, ip6_addr) entry */
  17363     sal_memset(&l3cfg, 0, sizeof(_bcm_l3_cfg_t));
  17364     l3cfg.l3c_flags = BCM_L3_IP6;
  17365     l3cfg.l3c_vrf = vrf;
  17366     sal_memcpy(l3cfg.l3c_ip6, ip6_addr, BCM_IP6_ADDRLEN);
  17367     rv = mbcm_driver[unit]->mbcm_l3_ip6_get(unit, &l3cfg);
  17368     if (BCM_FAILURE(rv)) {
  17369         L3_UNLOCK(unit);
  17370         return rv;
  17371     }
  17372 
  17373     /* Delete (vrf, ip_addr) entry's endpoint_id */
  17374     l3cfg.l3c_flags |= BCM_L3_REPLACE;
  17375     l3cfg.l3c_eh_q_tag_type = 0;
  17376     l3cfg.l3c_eh_q_tag = 0;
  17377     rv = mbcm_driver[unit]->mbcm_l3_ip6_replace(unit, &l3cfg);
  17378     if (BCM_FAILURE(rv)) {
  17379         L3_UNLOCK(unit);
  17380         return rv;
  17381     }
  17382 
  17383     L3_UNLOCK(unit);
  17384 
  17385     return rv;
  17386 }
  17387 
  17388 #endif /* INCLUDE_L3 */
  17389 
  17390 /*
  17391  * Function:
  17392  *      _bcm_mn_cosq_endpoint_gport_create
  17393  * Purpose:
  17394  *      Create a GPORT endpoint.
  17395  * Parameters:
  17396  *      unit        - (IN) Unit number.
  17397  *      endpoint_id - (IN) Endpoint ID
  17398  *      gport       - (IN) GPORT ID 
  17399  * Returns:
  17400  *      BCM_E_xxx
  17401  */
  17402 STATIC int
  17403 _bcm_mn_cosq_endpoint_gport_create(
  17404     int unit, 
  17405     int endpoint_id,
  17406     bcm_gport_t gport)
  17407 {
  17408     int vp;
  17409     ing_dvp_table_entry_t dvp_entry;
  17410     int nh_index;
  17411     ing_l3_next_hop_entry_t nh_entry;
  17412     int eh_tag_type;
  17413 
  17414     /* Get virtual port value */
  17415     if (BCM_GPORT_IS_VLAN_PORT(gport)) {
  17416         vp = BCM_GPORT_VLAN_PORT_ID_GET(gport);
  17417 #if defined(INCLUDE_L3)
  17418         if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeVlan)) {
  17419             /* VP is not configured yet */
  17420             return BCM_E_CONFIG;
  17421         }
  17422 #endif
  17423     } else if (BCM_GPORT_IS_NIV_PORT(gport)) {
  17424         vp = BCM_GPORT_NIV_PORT_ID_GET(gport);
  17425 #if defined(INCLUDE_L3)
  17426         if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeNiv)) {
  17427             /* VP is not configured yet */
  17428             return BCM_E_CONFIG;
  17429         }
  17430 #endif
  17431     } else {
  17432        return BCM_E_PARAM;
  17433     } 
  17434 
  17435     /* Get VP's next hop index */
  17436     BCM_IF_ERROR_RETURN
  17437         (READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp_entry));
  17438     nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp_entry,
  17439             NEXT_HOP_INDEXf);
  17440 
  17441     /* Set endpoint ID in next hop entry */
  17442     BCM_IF_ERROR_RETURN
  17443         (READ_ING_L3_NEXT_HOPm(unit, MEM_BLOCK_ANY, nh_index, &nh_entry));
  17444     eh_tag_type = soc_ING_L3_NEXT_HOPm_field32_get(unit, &nh_entry,
  17445             EH_TAG_TYPEf);
  17446     if (eh_tag_type != 0) {
  17447         /* A queue tag has already been configured for this next hop entry. */
  17448         return BCM_E_EXISTS;
  17449     }
  17450     soc_ING_L3_NEXT_HOPm_field32_set(unit, &nh_entry, EH_TAG_TYPEf, 2);
  17451     soc_ING_L3_NEXT_HOPm_field32_set(unit, &nh_entry, EH_QUEUE_TAGf, endpoint_id);
  17452     BCM_IF_ERROR_RETURN
  17453         (WRITE_ING_L3_NEXT_HOPm(unit, MEM_BLOCK_ALL, nh_index, &nh_entry));
  17454 
  17455     return BCM_E_NONE;
  17456 }
  17457 
  17458 /*
  17459  * Function:
  17460  *      _bcm_mn_cosq_endpoint_gport_destroy
  17461  * Purpose:
  17462  *      Destroy a GPORT endpoint.
  17463  * Parameters:
  17464  *      unit        - (IN) Unit number.
  17465  *      gport       - (IN) GPORT ID 
  17466  * Returns:
  17467  *      BCM_E_xxx
  17468  */
  17469 STATIC int
  17470 _bcm_mn_cosq_endpoint_gport_destroy(
  17471     int unit, 
  17472     bcm_gport_t gport)
  17473 {
  17474     int vp;
  17475     ing_dvp_table_entry_t dvp_entry;
  17476     int nh_index;
  17477     ing_l3_next_hop_entry_t nh_entry;
  17478 
  17479     /* Get virtual port value */
  17480     if (BCM_GPORT_IS_VLAN_PORT(gport)) {
  17481         vp = BCM_GPORT_VLAN_PORT_ID_GET(gport);
  17482 #if defined(INCLUDE_L3)
  17483         if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeVlan)) {
  17484             /* VP is not configured yet */
  17485             return BCM_E_CONFIG;
  17486         }
  17487 #endif
  17488     } else if (BCM_GPORT_IS_NIV_PORT(gport)) {
  17489         vp = BCM_GPORT_NIV_PORT_ID_GET(gport);
  17490 #if defined(INCLUDE_L3)
  17491         if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeNiv)) {
  17492             /* VP is not configured yet */
  17493             return BCM_E_CONFIG;
  17494         }
  17495 #endif
  17496     } else {
  17497        return BCM_E_PARAM;
  17498     } 
  17499 
  17500     /* Get VP's next hop index */
  17501     BCM_IF_ERROR_RETURN
  17502         (READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp_entry));
  17503     nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp_entry,
  17504             NEXT_HOP_INDEXf);
  17505 
  17506     /* Delete endpoint ID in next hop entry */
  17507     BCM_IF_ERROR_RETURN
  17508         (READ_ING_L3_NEXT_HOPm(unit, MEM_BLOCK_ANY, nh_index, &nh_entry));
  17509     soc_ING_L3_NEXT_HOPm_field32_set(unit, &nh_entry, EH_TAG_TYPEf, 0);
  17510     soc_ING_L3_NEXT_HOPm_field32_set(unit, &nh_entry, EH_QUEUE_TAGf, 0);
  17511     BCM_IF_ERROR_RETURN
  17512         (WRITE_ING_L3_NEXT_HOPm(unit, MEM_BLOCK_ALL, nh_index, &nh_entry));
  17513 
  17514     return BCM_E_NONE;
  17515 }
  17516 
  17517 /*
  17518  * Function:
  17519  *      bcm_mn_cosq_endpoint_create
  17520  * Purpose:
  17521  *      Create an endpoint.
  17522  * Parameters:
  17523  *      unit          - (IN) Unit number.
  17524  *      classifier    - (IN) Classifier attributes
  17525  *      classifier_id - (IN/OUT) Classifier ID
  17526  * Returns:
  17527  *      BCM_E_xxx
  17528  */
  17529 int
  17530 bcm_mn_cosq_endpoint_create(
  17531     int unit, 
  17532     bcm_cosq_classifier_t *classifier, 
  17533     int *classifier_id)
  17534 {
  17535     int endpoint_id = 0;
  17536     int i;
  17537 
  17538     if (NULL == classifier || NULL == classifier_id) {
  17539         return BCM_E_PARAM;
  17540     }
  17541 
  17542     if (classifier->flags & BCM_COSQ_CLASSIFIER_WITH_ID) {
  17543         if (!_BCM_COSQ_CLASSIFIER_IS_ENDPOINT(*classifier_id)) {
  17544             return BCM_E_PARAM;
  17545         }
  17546         endpoint_id = _BCM_COSQ_CLASSIFIER_ENDPOINT_GET(*classifier_id);
  17547         if (endpoint_id >= _BCM_MN_NUM_ENDPOINT(unit)) {
  17548             return BCM_E_PARAM;
  17549         }
  17550         if (_BCM_MN_ENDPOINT_IS_USED(unit, endpoint_id)) {
  17551             return BCM_E_EXISTS;
  17552         }
  17553     } else {
  17554         /* Get a free endpoint ID */
  17555         for (i = 0; i < _BCM_MN_NUM_ENDPOINT(unit); i++) {
  17556             if (!_BCM_MN_ENDPOINT_IS_USED(unit, i)) {
  17557                 endpoint_id = i;
  17558                 break;
  17559             }
  17560         }
  17561         if (i == _BCM_MN_NUM_ENDPOINT(unit)) {
  17562             /* No available endpoint ID */
  17563             return BCM_E_RESOURCE;
  17564         }
  17565     }
  17566     _BCM_MN_ENDPOINT(unit, endpoint_id) = sal_alloc(
  17567             sizeof(_bcm_mn_endpoint_t), "Endpoint Info");
  17568     if (NULL == _BCM_MN_ENDPOINT(unit, endpoint_id)) {
  17569         return BCM_E_MEMORY;
  17570     }
  17571     sal_memset(_BCM_MN_ENDPOINT(unit, endpoint_id), 0,
  17572             sizeof(_bcm_mn_endpoint_t));
  17573 
  17574     if (classifier->flags & BCM_COSQ_CLASSIFIER_L2) {
  17575         _BCM_MN_ENDPOINT(unit, endpoint_id)->flags = BCM_COSQ_CLASSIFIER_L2;
  17576         _BCM_MN_ENDPOINT(unit, endpoint_id)->vlan = classifier->vlan;
  17577         sal_memcpy(_BCM_MN_ENDPOINT(unit, endpoint_id)->mac, classifier->mac,
  17578                 sizeof(bcm_mac_t));
  17579         BCM_IF_ERROR_RETURN(_bcm_mn_cosq_endpoint_l2_create(unit,
  17580                     endpoint_id, classifier->vlan, classifier->mac));
  17581     } else if (classifier->flags & BCM_COSQ_CLASSIFIER_L3) {
  17582 #if defined(INCLUDE_L3)
  17583         _BCM_MN_ENDPOINT(unit, endpoint_id)->flags = BCM_COSQ_CLASSIFIER_L3;
  17584         _BCM_MN_ENDPOINT(unit, endpoint_id)->vrf = classifier->vrf;
  17585         if (classifier->flags & BCM_COSQ_CLASSIFIER_IP6) {
  17586             _BCM_MN_ENDPOINT(unit, endpoint_id)->flags |= BCM_COSQ_CLASSIFIER_IP6;
  17587             sal_memcpy(_BCM_MN_ENDPOINT(unit, endpoint_id)->ip6_addr,
  17588                     classifier->ip6_addr, BCM_IP6_ADDRLEN);
  17589             BCM_IF_ERROR_RETURN(_bcm_mn_cosq_endpoint_ip6_create(unit,
  17590                         endpoint_id, classifier->vrf, classifier->ip6_addr));
  17591         } else {
  17592             _BCM_MN_ENDPOINT(unit, endpoint_id)->ip_addr = classifier->ip_addr;
  17593             BCM_IF_ERROR_RETURN(_bcm_mn_cosq_endpoint_ip4_create(unit,
  17594                         endpoint_id, classifier->vrf, classifier->ip_addr));
  17595         }
  17596 #endif /* INCLUDE_L3 */
  17597     } else if (classifier->flags & BCM_COSQ_CLASSIFIER_GPORT) {
  17598         _BCM_MN_ENDPOINT(unit, endpoint_id)->flags = BCM_COSQ_CLASSIFIER_GPORT;
  17599         _BCM_MN_ENDPOINT(unit, endpoint_id)->gport = classifier->gport;
  17600         BCM_IF_ERROR_RETURN(_bcm_mn_cosq_endpoint_gport_create(unit,
  17601                     endpoint_id, classifier->gport));
  17602     } else {
  17603         return BCM_E_PARAM;
  17604     }
  17605 
  17606     _BCM_COSQ_CLASSIFIER_ENDPOINT_SET(*classifier_id, endpoint_id);
  17607 
  17608     return BCM_E_NONE;
  17609 }
  17610 
  17611 /*
  17612  * Function:
  17613  *      bcm_mn_cosq_endpoint_destroy
  17614  * Purpose:
  17615  *      Destroy an endpoint.
  17616  * Parameters:
  17617  *      unit          - (IN) Unit number.
  17618  *      classifier_id - (IN) Classifier ID
  17619  * Returns:
  17620  *      BCM_E_xxx
  17621  */
  17622 int
  17623 bcm_mn_cosq_endpoint_destroy(
  17624     int unit, 
  17625     int classifier_id)
  17626 {
  17627     int endpoint_id;
  17628 
  17629     if (!_BCM_COSQ_CLASSIFIER_IS_ENDPOINT(classifier_id)) {
  17630         return BCM_E_PARAM;
  17631     }
  17632     endpoint_id = _BCM_COSQ_CLASSIFIER_ENDPOINT_GET(classifier_id);
  17633     if (endpoint_id >= _BCM_MN_NUM_ENDPOINT(unit)) {
  17634         return BCM_E_PARAM;
  17635     }
  17636     if (!_BCM_MN_ENDPOINT_IS_USED(unit, endpoint_id)) {
  17637         return BCM_E_NOT_FOUND;
  17638     }
  17639 
  17640     if (_BCM_MN_ENDPOINT(unit, endpoint_id)->flags &
  17641             BCM_COSQ_CLASSIFIER_L2) {
  17642         BCM_IF_ERROR_RETURN(_bcm_mn_cosq_endpoint_l2_destroy(unit,
  17643                     _BCM_MN_ENDPOINT(unit, endpoint_id)->vlan,
  17644                     _BCM_MN_ENDPOINT(unit, endpoint_id)->mac));
  17645     } else if (_BCM_MN_ENDPOINT(unit, endpoint_id)->flags &
  17646             BCM_COSQ_CLASSIFIER_L3) {
  17647 #if defined(INCLUDE_L3)
  17648         if (_BCM_MN_ENDPOINT(unit, endpoint_id)->flags &
  17649                 BCM_COSQ_CLASSIFIER_IP6) {
  17650             BCM_IF_ERROR_RETURN(_bcm_mn_cosq_endpoint_ip6_destroy(unit,
  17651                         _BCM_MN_ENDPOINT(unit, endpoint_id)->vrf,
  17652                         _BCM_MN_ENDPOINT(unit, endpoint_id)->ip6_addr));
  17653         } else {
  17654             BCM_IF_ERROR_RETURN(_bcm_mn_cosq_endpoint_ip4_destroy(unit,
  17655                         _BCM_MN_ENDPOINT(unit, endpoint_id)->vrf,
  17656                         _BCM_MN_ENDPOINT(unit, endpoint_id)->ip_addr));
  17657         }
  17658 #endif
  17659     } else if (_BCM_MN_ENDPOINT(unit, endpoint_id)->flags &
  17660             BCM_COSQ_CLASSIFIER_GPORT) {
  17661         BCM_IF_ERROR_RETURN(_bcm_mn_cosq_endpoint_gport_destroy(unit,
  17662                     _BCM_MN_ENDPOINT(unit, endpoint_id)->gport));
  17663     } else {
  17664         return BCM_E_INTERNAL;
  17665     }
  17666 
  17667     sal_free(_BCM_MN_ENDPOINT(unit, endpoint_id));
  17668     _BCM_MN_ENDPOINT(unit, endpoint_id) = NULL;
  17669 
  17670     return BCM_E_NONE;
  17671 }
  17672 
  17673 /*
  17674  * Function:
  17675  *      bcm_mn_cosq_endpoint_get
  17676  * Purpose:
  17677  *      Get info about an endpoint.
  17678  * Parameters:
  17679  *      unit          - (IN) Unit number.
  17680  *      classifier_id - (IN) Classifier ID
  17681  *      classifier    - (OUT) Classifier info
  17682  * Returns:
  17683  *      BCM_E_xxx
  17684  */
  17685 int
  17686 bcm_mn_cosq_endpoint_get(
  17687     int unit, 
  17688     int classifier_id,
  17689     bcm_cosq_classifier_t *classifier)
  17690 {
  17691     int endpoint_id;
  17692 
  17693     if (!_BCM_COSQ_CLASSIFIER_IS_ENDPOINT(classifier_id)) {
  17694         return BCM_E_PARAM;
  17695     }
  17696     endpoint_id = _BCM_COSQ_CLASSIFIER_ENDPOINT_GET(classifier_id);
  17697     if (endpoint_id >= _BCM_MN_NUM_ENDPOINT(unit)) {
  17698         return BCM_E_PARAM;
  17699     }
  17700     if (!_BCM_MN_ENDPOINT_IS_USED(unit, endpoint_id)) {
  17701         return BCM_E_NOT_FOUND;
  17702     }
  17703 
  17704     classifier->flags = _BCM_MN_ENDPOINT(unit, endpoint_id)->flags;
  17705     classifier->vlan = _BCM_MN_ENDPOINT(unit, endpoint_id)->vlan;
  17706     sal_memcpy(classifier->mac, _BCM_MN_ENDPOINT(unit, endpoint_id)->mac,
  17707             sizeof(bcm_mac_t));
  17708     classifier->vrf = _BCM_MN_ENDPOINT(unit, endpoint_id)->vrf;
  17709     classifier->ip_addr = _BCM_MN_ENDPOINT(unit, endpoint_id)->ip_addr;
  17710     sal_memcpy(classifier->ip6_addr,
  17711             _BCM_MN_ENDPOINT(unit, endpoint_id)->ip6_addr, BCM_IP6_ADDRLEN);
  17712     classifier->gport = _BCM_MN_ENDPOINT(unit, endpoint_id)->gport;
  17713    
  17714     return BCM_E_NONE;
  17715 }
  17716 /*
  17717  * Function:
  17718  *      bcm_mn_cosq_endpoint_map_set
  17719  * Purpose:
  17720  *      Set the mapping from port, classifier, and multiple internal priorities
  17721  *      to multiple COS queues in a queue group.
  17722  * Parameters:
  17723  *      unit           - (IN) Unit number.
  17724  *      port           - (IN) local port ID
  17725  *      classifier_id  - (IN) Classifier ID
  17726  *      queue_group    - (IN) Base queue ID
  17727  *      array_count    - (IN) Number of elements in priority_array and
  17728  *                            cosq_array
  17729  *      priority_array - (IN) Array of internal priorities
  17730  *      cosq_array     - (IN) Array of COS queues
  17731  * Returns:
  17732  *      BCM_E_xxx
  17733  */
  17734 int
  17735 bcm_mn_cosq_endpoint_map_set(
  17736     int unit, 
  17737     bcm_port_t port, 
  17738     int classifier_id, 
  17739     bcm_gport_t queue_group, 
  17740     int array_count, 
  17741     bcm_cos_t *priority_array, 
  17742     bcm_cos_queue_t *cosq_array)
  17743 {
  17744     int rv = BCM_E_NONE;
  17745     int endpoint_id;
  17746     int qid;
  17747     int num_entries_per_profile;
  17748     int alloc_size;
  17749     endpoint_cos_map_entry_t *entry_array = NULL;
  17750     void *entries[1];
  17751     endpoint_queue_map_entry_t qmap_key, qmap_data, qmap_entry;
  17752     int qmap_index;
  17753     int old_profile_index, new_profile_index;
  17754     int old_qid;
  17755     int i;
  17756     int priority;
  17757     uint64 rval64;
  17758     uint32 endpoint_cos_map_prof_idx;
  17759     if (!_BCM_COSQ_CLASSIFIER_IS_ENDPOINT(classifier_id)) {
  17760         return BCM_E_PARAM;
  17761     }
  17762     endpoint_id = _BCM_COSQ_CLASSIFIER_ENDPOINT_GET(classifier_id);
  17763     if (endpoint_id >= _BCM_MN_NUM_ENDPOINT(unit)) {
  17764         return BCM_E_PARAM;
  17765     }
  17766     if (!_BCM_MN_ENDPOINT_IS_USED(unit, endpoint_id)) {
  17767         return BCM_E_PARAM;
  17768     }
  17769 
  17770     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(queue_group)) {
  17771         qid = BCM_GPORT_UCAST_QUEUE_GROUP_QID_GET(queue_group);
  17772     } else {
  17773         return BCM_E_PARAM;
  17774     }
  17775 
  17776     /* Allocate an Endpoint CoS Map profile */
  17777     num_entries_per_profile = 16;
  17778     alloc_size = sizeof(endpoint_cos_map_entry_t) * num_entries_per_profile;
  17779     entry_array = sal_alloc(alloc_size, "Endpoint CoS Map Profile");
  17780     if (NULL == entry_array) {
  17781         return BCM_E_MEMORY;
  17782     }
  17783     sal_memset(entry_array, 0, alloc_size);
  17784 
  17785     /* Search Endpoint Queue Map table */
  17786     sal_memcpy(&qmap_key, soc_mem_entry_null(unit,
  17787                 ENDPOINT_QUEUE_MAPm), sizeof(endpoint_queue_map_entry_t));
  17788     soc_ENDPOINT_QUEUE_MAPm_field32_set(unit, &qmap_key, KEY_TYPEf, 0);
  17789     soc_ENDPOINT_QUEUE_MAPm_field32_set(unit, &qmap_key, DEST_PORTf, port);
  17790     soc_ENDPOINT_QUEUE_MAPm_field32_set(unit, &qmap_key, EH_QUEUE_TAGf,
  17791             endpoint_id);
  17792     rv = soc_mem_search(unit, ENDPOINT_QUEUE_MAPm, MEM_BLOCK_ANY,
  17793             &qmap_index, &qmap_key, &qmap_data, 0);
  17794     if (rv == SOC_E_NOT_FOUND) {
  17795         old_profile_index = -1;
  17796     } else if (rv == SOC_E_NONE) {
  17797         /* Existing entry found. Compare base queue ID and extract
  17798          * old Endpoint CoS Map profile.
  17799          */
  17800         old_qid = soc_ENDPOINT_QUEUE_MAPm_field32_get(unit,
  17801                 &qmap_data, ENDPOINT_QUEUE_BASEf);
  17802         if (old_qid != qid) {
  17803             /* The classifier is already mapped to another queue group */
  17804             sal_free(entry_array);
  17805             return BCM_E_EXISTS;
  17806         }
  17807         endpoint_cos_map_prof_idx = soc_ENDPOINT_QUEUE_MAPm_field32_get(unit,
  17808                 &qmap_data, ENDPOINT_COS_MAP_PROFILE_INDEXf);
  17809         entries[0] = entry_array;
  17810         /* 
  17811          * The index of ENDPOINT_COS_MAP = 
  17812          * ENDPOINT_COS_MAP_PROFILE_INDEX * 16 + INT_PRI
  17813          */
  17814         old_profile_index = endpoint_cos_map_prof_idx * num_entries_per_profile;
  17815         rv = soc_profile_mem_get(unit, _BCM_MN_ENDPOINT_COS_MAP_PROFILE(unit),
  17816                 old_profile_index, num_entries_per_profile, entries);
  17817         if (SOC_FAILURE(rv)) {
  17818             sal_free(entry_array);
  17819             return rv;
  17820         }
  17821     } else {
  17822         sal_free(entry_array);
  17823         return rv;
  17824     }
  17825 
  17826     /* Construct or modify Endpoint CoS Map profile and add it */
  17827     for (i = 0; i < array_count; i++) {
  17828         priority = priority_array[i];
  17829         if ((priority < 0) || (priority >= 16)) {
  17830             sal_free(entry_array);
  17831             return BCM_E_PARAM;
  17832         }
  17833         soc_ENDPOINT_COS_MAPm_field32_set(unit, &entry_array[priority],
  17834                 ENDPOINT_COS_OFFSETf, cosq_array[i]);
  17835     }
  17836     entries[0] = entry_array;
  17837     rv = soc_profile_mem_add(unit, _BCM_MN_ENDPOINT_COS_MAP_PROFILE(unit),
  17838             entries, num_entries_per_profile, (uint32 *)&new_profile_index);
  17839     sal_free(entry_array);
  17840     if (SOC_FAILURE(rv)) {
  17841         return rv;
  17842     }
  17843 
  17844     /* Insert or replace Endpoint Queue Map entry */
  17845     sal_memcpy(&qmap_entry, &qmap_key, sizeof(endpoint_queue_map_entry_t));
  17846     soc_ENDPOINT_QUEUE_MAPm_field32_set(unit, &qmap_entry, VALIDf, 1);
  17847     soc_ENDPOINT_QUEUE_MAPm_field32_set(unit, &qmap_entry,
  17848             ENDPOINT_QUEUE_BASEf, qid);
  17849     endpoint_cos_map_prof_idx = new_profile_index / num_entries_per_profile;
  17850     soc_ENDPOINT_QUEUE_MAPm_field32_set(unit, &qmap_entry,
  17851             ENDPOINT_COS_MAP_PROFILE_INDEXf, endpoint_cos_map_prof_idx);
  17852     rv = soc_mem_insert(unit, ENDPOINT_QUEUE_MAPm, MEM_BLOCK_ALL, &qmap_entry);
  17853     if (SOC_FAILURE(rv) && rv != SOC_E_EXISTS) {
  17854         return rv;
  17855     }
  17856 
  17857     /* Delete old Endpoint CoS Map profile */
  17858     if (old_profile_index != -1) {
  17859         SOC_IF_ERROR_RETURN
  17860             (soc_profile_mem_delete(unit,
  17861                                     _BCM_MN_ENDPOINT_COS_MAP_PROFILE(unit),
  17862                                     old_profile_index));
  17863     }
  17864 
  17865     /* Set port's queuing mode to be endpoint queuing */
  17866     SOC_IF_ERROR_RETURN(READ_ING_COS_MODE_64r(unit, port, &rval64));
  17867     if (4 != soc_reg64_field32_get(unit, ING_COS_MODE_64r, rval64,
  17868                 QUEUE_MODEf)) {
  17869         soc_reg64_field32_set(unit, ING_COS_MODE_64r, &rval64, QUEUE_MODEf, 4);
  17870         SOC_IF_ERROR_RETURN(WRITE_ING_COS_MODE_64r(unit, port, rval64));
  17871     }
  17872 
  17873     return rv;
  17874 }
  17875 
  17876 /*
  17877  * Function:
  17878  *      bcm_mn_cosq_endpoint_map_get
  17879  * Purpose:
  17880  *      Get the mapping from port, classifier, and multiple internal priorities
  17881  *      to multiple COS queues in a queue group.
  17882  * Parameters:
  17883  *      unit           - (IN) Unit number.
  17884  *      port           - (IN) Local port ID
  17885  *      classifier_id  - (IN) Classifier ID
  17886  *      queue_group    - (OUT) Queue group
  17887  *      array_max      - (IN) Size of priority_array and cosq_array
  17888  *      priority_array - (IN) Array of internal priorities
  17889  *      cosq_array     - (OUT) Array of COS queues
  17890  *      array_count    - (OUT) Size of cosq_array
  17891  * Returns:
  17892  *      BCM_E_xxx
  17893  */
  17894 int
  17895 bcm_mn_cosq_endpoint_map_get(
  17896     int unit, 
  17897     bcm_port_t port, 
  17898     int classifier_id, 
  17899     bcm_gport_t *queue_group, 
  17900     int array_max, 
  17901     bcm_cos_t *priority_array, 
  17902     bcm_cos_queue_t *cosq_array, 
  17903     int *array_count)
  17904 {
  17905     int rv = BCM_E_NONE;
  17906     int endpoint_id;
  17907     endpoint_queue_map_entry_t qmap_key, qmap_data;
  17908     int qmap_index;
  17909     int qid;
  17910     int num_entries_per_profile;
  17911     int alloc_size;
  17912     endpoint_cos_map_entry_t *entry_array = NULL;
  17913     void *entries[1];
  17914     int profile_index;
  17915     int i;
  17916     int priority;
  17917     uint32 endpoint_cos_map_prof_idx;
  17918 
  17919     if (!_BCM_COSQ_CLASSIFIER_IS_ENDPOINT(classifier_id)) {
  17920         return BCM_E_PARAM;
  17921     }
  17922     endpoint_id = _BCM_COSQ_CLASSIFIER_ENDPOINT_GET(classifier_id);
  17923     if (endpoint_id >= _BCM_MN_NUM_ENDPOINT(unit)) {
  17924         return BCM_E_PARAM;
  17925     }
  17926     if (!_BCM_MN_ENDPOINT_IS_USED(unit, endpoint_id)) {
  17927         return BCM_E_PARAM;
  17928     }
  17929 
  17930     /* Search Endpoint Queue Map table */
  17931     sal_memcpy(&qmap_key, soc_mem_entry_null(unit,
  17932                 ENDPOINT_QUEUE_MAPm), sizeof(endpoint_queue_map_entry_t));
  17933     soc_ENDPOINT_QUEUE_MAPm_field32_set(unit, &qmap_key, KEY_TYPEf, 0);
  17934     soc_ENDPOINT_QUEUE_MAPm_field32_set(unit, &qmap_key, DEST_PORTf, port);
  17935     soc_ENDPOINT_QUEUE_MAPm_field32_set(unit, &qmap_key, EH_QUEUE_TAGf,
  17936             endpoint_id);
  17937     SOC_IF_ERROR_RETURN(soc_mem_search(unit, ENDPOINT_QUEUE_MAPm, MEM_BLOCK_ANY,
  17938                 &qmap_index, &qmap_key, &qmap_data, 0));
  17939 
  17940     /* Get queue group */
  17941     qid = soc_ENDPOINT_QUEUE_MAPm_field32_get(unit, &qmap_data,
  17942             ENDPOINT_QUEUE_BASEf);
  17943     BCM_GPORT_UCAST_QUEUE_GROUP_SYSQID_SET(*queue_group, port, qid);
  17944 
  17945     /* Get Endpoint CoS Map profile */
  17946     num_entries_per_profile = 16;
  17947     alloc_size = sizeof(endpoint_cos_map_entry_t) * num_entries_per_profile;
  17948     entry_array = sal_alloc(alloc_size, "Endpoint CoS Map Profile");
  17949     if (NULL == entry_array) {
  17950         return BCM_E_MEMORY;
  17951     }
  17952     sal_memset(entry_array, 0, alloc_size);
  17953     entries[0] = entry_array;
  17954     endpoint_cos_map_prof_idx = soc_ENDPOINT_QUEUE_MAPm_field32_get(unit, &qmap_data,
  17955             ENDPOINT_COS_MAP_PROFILE_INDEXf);
  17956     /*
  17957      * The index of ENDPOINT_COS_MAP =
  17958      * ENDPOINT_COS_MAP_PROFILE_INDEX * 16 + INT_PRI
  17959      */
  17960     profile_index = endpoint_cos_map_prof_idx * num_entries_per_profile;
  17961     rv = soc_profile_mem_get(unit, _BCM_MN_ENDPOINT_COS_MAP_PROFILE(unit),
  17962             profile_index, num_entries_per_profile, entries);
  17963     if (SOC_FAILURE(rv)) {
  17964         sal_free(entry_array);
  17965         return rv;
  17966     }
  17967 
  17968     /* Get internal priority to CoS mapping */
  17969     if (array_max == 0) {
  17970         if (NULL != array_count) {
  17971             *array_count = num_entries_per_profile;
  17972         }
  17973     } else {
  17974         *array_count = 0;
  17975         for (i = 0; i < array_max; i++) {
  17976             priority = priority_array[i];
  17977             if (priority >= 16 || priority < 0) {
  17978                 sal_free(entry_array);
  17979                 return BCM_E_PARAM;
  17980             }
  17981             cosq_array[i] = soc_ENDPOINT_COS_MAPm_field32_get(unit,
  17982                     &entry_array[priority], ENDPOINT_COS_OFFSETf);
  17983             (*array_count)++;
  17984         }
  17985     }
  17986 
  17987     sal_free(entry_array);
  17988     return rv;
  17989 }
  17990 
  17991 /*
  17992  * Function:
  17993  *      bcm_mn_cosq_endpoint_map_clear
  17994  * Purpose:
  17995  *      Clear the mapping from port, classifier, and internal priorities
  17996  *      to COS queues in a queue group.
  17997  * Parameters:
  17998  *      unit          - (IN) Unit number.
  17999  *      port          - (IN) Local port ID
  18000  *      classifier_id - (IN) Classifier ID
  18001  * Returns:
  18002  *      BCM_E_xxx
  18003  */
  18004 int
  18005 bcm_mn_cosq_endpoint_map_clear(
  18006     int unit, 
  18007     bcm_gport_t port, 
  18008     int classifier_id)
  18009 {
  18010     int endpoint_id;
  18011     endpoint_queue_map_entry_t qmap_key, qmap_data;
  18012     int profile_index;
  18013     int num_entries_per_set = 16; 
  18014 
  18015     if (!_BCM_COSQ_CLASSIFIER_IS_ENDPOINT(classifier_id)) {
  18016         return BCM_E_PARAM;
  18017     }
  18018     endpoint_id = _BCM_COSQ_CLASSIFIER_ENDPOINT_GET(classifier_id);
  18019     if (endpoint_id >= _BCM_MN_NUM_ENDPOINT(unit)) {
  18020         return BCM_E_PARAM;
  18021     }
  18022     if (!_BCM_MN_ENDPOINT_IS_USED(unit, endpoint_id)) {
  18023         return BCM_E_PARAM;
  18024     }
  18025 
  18026     /* Delete (port, endpoint_id) entry from Endpoint Queue Map table */
  18027     sal_memcpy(&qmap_key, soc_mem_entry_null(unit,
  18028                 ENDPOINT_QUEUE_MAPm), sizeof(endpoint_queue_map_entry_t));
  18029     soc_ENDPOINT_QUEUE_MAPm_field32_set(unit, &qmap_key, KEY_TYPEf, 0);
  18030     soc_ENDPOINT_QUEUE_MAPm_field32_set(unit, &qmap_key, DEST_PORTf, port);
  18031     soc_ENDPOINT_QUEUE_MAPm_field32_set(unit, &qmap_key, EH_QUEUE_TAGf,
  18032             endpoint_id);
  18033     SOC_IF_ERROR_RETURN(soc_mem_delete_return_old(unit, ENDPOINT_QUEUE_MAPm,
  18034                 MEM_BLOCK_ALL, &qmap_key, &qmap_data));
  18035 
  18036     /* Delete priority to CoS mapping profile */
  18037     profile_index = soc_ENDPOINT_QUEUE_MAPm_field32_get(unit, &qmap_data,
  18038             ENDPOINT_COS_MAP_PROFILE_INDEXf);
  18039     profile_index = profile_index * num_entries_per_set; 
  18040     SOC_IF_ERROR_RETURN(soc_profile_mem_delete(unit,
  18041                 _BCM_MN_ENDPOINT_COS_MAP_PROFILE(unit), profile_index));
  18042 
  18043     return BCM_E_NONE;
  18044 }
  18045 
  18046 /*
  18047  * Function:
  18048  *      bcm_mn_cosq_field_classifier_get
  18049  * Purpose:
  18050  *      Get classifier type information.
  18051  * Parameters:
  18052  *      unit          - (IN) Unit number.
  18053  *      classifier_id - (IN) Classifier ID
  18054  *      classifier    - (OUT) Classifier info
  18055  * Returns:
  18056  *      BCM_E_xxx
  18057  */
  18058 int
  18059 bcm_mn_cosq_field_classifier_get(
  18060     int unit,    
  18061     int classifier_id,
  18062     bcm_cosq_classifier_t *classifier)
  18063 {
  18064     if (classifier == NULL) {
  18065         return BCM_E_PARAM;
  18066     }
  18067     sal_memset(classifier, 0, sizeof(bcm_cosq_classifier_t));
  18068 
  18069     if (_BCM_COSQ_CLASSIFIER_IS_FIELD(classifier_id)) {
  18070         classifier->flags |= BCM_COSQ_CLASSIFIER_FIELD;
  18071     }
  18072 
  18073     return BCM_E_NONE;
  18074 }
  18075 
  18076 
  18077 
  18078 /*
  18079  * Function:
  18080  *      bcm_mn_cosq_field_classifier_id_create
  18081  * Purpose:
  18082  *      Create a cosq classifier.
  18083  * Parameters: 
  18084  *      unit          - (IN) Unit number.
  18085  *      classifier    - (IN) Classifier attributes
  18086  *      classifier_id - (OUT) Classifier ID
  18087  * Returns:
  18088  *      BCM_E_xxx
  18089  */     
  18090 int
  18091 bcm_mn_cosq_field_classifier_id_create(
  18092     int unit,
  18093     bcm_cosq_classifier_t *classifier,
  18094     int *classifier_id)
  18095 {
  18096     int rv;
  18097     int ref_count = 0;
  18098     int ent_per_set = _MN_NUM_INTERNAL_PRI;
  18099     int i;
  18100 
  18101     if (NULL == classifier || NULL == classifier_id) {
  18102         return BCM_E_PARAM;
  18103     }
  18104 
  18105     for (i = 0; i < SOC_MEM_SIZE(unit, IFP_COS_MAPm); i += ent_per_set) {
  18106         rv = soc_profile_mem_ref_count_get(
  18107                 unit, _bcm_mn_ifp_cos_map_profile[unit], i, &ref_count);
  18108         if (SOC_FAILURE(rv)) {
  18109             return rv;
  18110         }
  18111         if (0 == ref_count) {
  18112             break;
  18113         }
  18114     }
  18115 
  18116     if (i >= SOC_MEM_SIZE(unit, IFP_COS_MAPm) && ref_count != 0) {
  18117         *classifier_id = 0;
  18118         return BCM_E_RESOURCE;
  18119     }
  18120 
  18121     _BCM_COSQ_CLASSIFIER_FIELD_SET(*classifier_id, (i / ent_per_set));
  18122 
  18123     return BCM_E_NONE;
  18124 }
  18125 
  18126 
  18127 /*
  18128  * Function:
  18129  *      bcm_mn_cosq_field_classifier_map_set
  18130  * Purpose:
  18131  *      Set internal priority to ingress field processor CoS queue
  18132  *      override mapping.
  18133  * Parameters:
  18134  *      unit           - (IN) Unit number.
  18135  *      classifier_id  - (IN) Classifier ID
  18136  *      count          - (IN) Number of elements in priority_array and
  18137  *                            cosq_array
  18138  *      priority_array - (IN) Array of internal priorities
  18139  *      cosq_array     - (IN) Array of COS queues
  18140  * Returns:
  18141  *      BCM_E_xxx
  18142  */
  18143 int
  18144 bcm_mn_cosq_field_classifier_map_set(
  18145     int unit,
  18146     int classifier_id,
  18147     int count,
  18148     bcm_cos_t *priority_array,
  18149     bcm_cos_queue_t *cosq_array)
  18150 {
  18151     int rv;
  18152     int i;
  18153     int max_entries = _MN_NUM_INTERNAL_PRI;
  18154     uint32 index;
  18155     void *entries[1];
  18156     ifp_cos_map_entry_t ent_buf[_MN_NUM_INTERNAL_PRI];
  18157     int ref_count = 0;
  18158     /* Input parameter check. */
  18159     if (!_BCM_COSQ_CLASSIFIER_IS_FIELD(classifier_id)) {
  18160         return BCM_E_PARAM;
  18161     }
  18162 
  18163     if (NULL == priority_array || NULL == cosq_array) {
  18164         return BCM_E_PARAM;
  18165     }
  18166 
  18167     if (count > max_entries) {
  18168         return BCM_E_PARAM;
  18169     }
  18170 
  18171     sal_memset(ent_buf, 0, sizeof(ifp_cos_map_entry_t) * max_entries);
  18172     entries[0] = ent_buf;
  18173     
  18174     for (i = 0; i < count; i++) {
  18175         if (priority_array[i] < max_entries) {
  18176             if (cosq_array[i] >= _BCM_MN_NUM_L2_LEAVES_PER_PIPE) {
  18177                 return BCM_E_PARAM;
  18178             }
  18179             soc_mem_field32_set(unit, IFP_COS_MAPm, &ent_buf[priority_array[i]],
  18180                                 IFP_COSf, cosq_array[i]);
  18181         }
  18182     }
  18183     
  18184     index = _BCM_COSQ_CLASSIFIER_FIELD_GET(classifier_id);
  18185     SOC_IF_ERROR_RETURN(
  18186         soc_profile_mem_ref_count_get(unit, _bcm_mn_ifp_cos_map_profile[unit],
  18187                                       index * max_entries, &ref_count));
  18188      
  18189     if (ref_count == 0) {
  18190         rv = soc_profile_mem_add(unit, _bcm_mn_ifp_cos_map_profile[unit],
  18191                                  entries, max_entries, &index);
  18192     } else {
  18193         rv = soc_profile_mem_set(unit, _bcm_mn_ifp_cos_map_profile[unit],
  18194                                  entries, index * max_entries);
  18195         if (rv == SOC_E_NONE) {
  18196             /* decrease the profile ref_count increased by mem_set */
  18197             rv = soc_profile_mem_delete(unit,
  18198                                         _bcm_mn_ifp_cos_map_profile[unit],
  18199                                         index * max_entries);
  18200         }
  18201     }
  18202     return rv;
  18203 }
  18204 
  18205 
  18206 /*
  18207  * Function:
  18208  *      bcm_mn_cosq_field_classifier_map_get
  18209  * Purpose:
  18210  *      Get internal priority to ingress field processor CoS queue
  18211  *      override mapping information.
  18212  * Parameters:
  18213  *      unit           - (IN) Unit number.
  18214  *      classifier_id  - (IN) Classifier ID
  18215  *      array_max      - (IN) Size of priority_array and cosq_array
  18216  *      priority_array - (IN) Array of internal priorities
  18217  *      cosq_array     - (OUT) Array of COS queues
  18218  *      array_count    - (OUT) Size of cosq_array
  18219  * Returns:
  18220  *      BCM_E_xxx
  18221  */
  18222 int
  18223 bcm_mn_cosq_field_classifier_map_get(
  18224     int unit,
  18225     int classifier_id,
  18226     int array_max,
  18227     bcm_cos_t *priority_array,
  18228     bcm_cos_queue_t *cosq_array,
  18229     int *array_count)
  18230 {
  18231     int rv;
  18232     int i;
  18233     int ent_per_set = _MN_NUM_INTERNAL_PRI;
  18234     uint32 index;
  18235     void *entries[1];
  18236     ifp_cos_map_entry_t ent_buf[_MN_NUM_INTERNAL_PRI];
  18237 
  18238     /* Input parameter check. */
  18239     if (NULL == priority_array || NULL == cosq_array || NULL == array_count) {
  18240         return BCM_E_PARAM;
  18241     }
  18242 
  18243     sal_memset(ent_buf, 0, sizeof(ifp_cos_map_entry_t) * ent_per_set);
  18244     entries[0] = ent_buf;
  18245 
  18246     /* Get profile table entry set base index. */
  18247     index = _BCM_COSQ_CLASSIFIER_FIELD_GET(classifier_id);
  18248 
  18249     /* Read out entries from profile table into allocated buffer. */
  18250     rv = soc_profile_mem_get(unit, _bcm_mn_ifp_cos_map_profile[unit],
  18251                              index * ent_per_set, ent_per_set, entries);
  18252     if (SOC_FAILURE(rv)) {
  18253         return rv;
  18254     }
  18255 
  18256     *array_count = array_max > ent_per_set ? ent_per_set : array_max;
  18257 
  18258     /* Copy values into API OUT parameters. */
  18259     for (i = 0; i < *array_count; i++) {
  18260         if (priority_array[i] >= _MN_NUM_INTERNAL_PRI) {
  18261             return BCM_E_PARAM;
  18262         }
  18263         cosq_array[i] = soc_mem_field32_get(unit, IFP_COS_MAPm,
  18264                                             &ent_buf[priority_array[i]],
  18265                                             IFP_COSf);
  18266     }
  18267 
  18268     return BCM_E_NONE;
  18269 }
  18270 
  18271 
  18272 /*
  18273  * Function:
  18274  *      bcm_mn_cosq_field_classifier_map_clear
  18275  * Purpose:
  18276  *      Delete an internal priority to ingress field processor CoS queue
  18277  *      override mapping profile set.
  18278  * Parameters:
  18279  *      unit          - (IN) Unit number.
  18280  *      classifier_id - (IN) Classifier ID
  18281  * Returns:
  18282  *      BCM_E_xxx
  18283  */
  18284 int
  18285 bcm_mn_cosq_field_classifier_map_clear(int unit, int classifier_id)
  18286 {
  18287     int ent_per_set = _MN_NUM_INTERNAL_PRI;
  18288     uint32 index;
  18289 
  18290     /* Get profile table entry set base index. */
  18291     index = _BCM_COSQ_CLASSIFIER_FIELD_GET(classifier_id);
  18292 
  18293     /* Delete the profile entries set. */
  18294     SOC_IF_ERROR_RETURN
  18295         (soc_profile_mem_delete(unit,
  18296                                 _bcm_mn_ifp_cos_map_profile[unit],
  18297                                 index * ent_per_set));
  18298     return BCM_E_NONE;
  18299 }
  18300 
  18301 
  18302 /*
  18303  * Function:
  18304  *      bcm_mn_cosq_field_classifier_id_destroy
  18305  * Purpose:
  18306  *      Free resource associated with this field classifier id.
  18307  * Parameters:
  18308  *      unit          - (IN) Unit number.
  18309  *      classifier_id - (IN) Classifier ID
  18310  * Returns:
  18311  *      BCM_E_xxx
  18312  */
  18313 int
  18314 bcm_mn_cosq_field_classifier_id_destroy(int unit, int classifier_id)
  18315 {
  18316     return BCM_E_NONE;
  18317 }
  18318 
  18319 
  18320 /*
  18321  * Function:
  18322  *      bcm_td_cosq_cpu_cosq_enable_set
  18323  * Purpose:
  18324  *      To enable/disable Rx of packets on the specified CPU cosq.
  18325  * Parameters:
  18326  *      unit          - (IN) Unit number.
  18327  *      cosq          - (IN) CPU Cosq ID
  18328  *      enable        - (IN) Enable/Disable
  18329  * Returns:
  18330  *      BCM_E_xxx
  18331  */
  18332 int
  18333 bcm_mn_cosq_cpu_cosq_enable_set(
  18334     int unit, 
  18335     bcm_cos_queue_t cosq, 
  18336     int enable)
  18337 {
  18338     uint32 entry[SOC_MAX_MEM_WORDS];
  18339     int i, index, enable_status;
  18340     _bcm_mn_cosq_cpu_cosq_config_t *cpu_cosq;
  18341     soc_info_t *si;
  18342     soc_mem_t thdm_mem[] = {
  18343         MMU_THDM_DB_QUEUE_CONFIG_0m,
  18344         MMU_THDM_MCQE_QUEUE_CONFIG_0m
  18345     };
  18346 
  18347     si = &SOC_INFO(unit);
  18348 
  18349     if ((cosq < 0) || (cosq >= si->num_cpu_cosq)) {
  18350         return BCM_E_PARAM;
  18351     }
  18352 
  18353     cpu_cosq = _bcm_mn_cosq_cpu_cosq_config[unit][cosq];
  18354 
  18355     if (!cpu_cosq) {
  18356         return BCM_E_INTERNAL;
  18357     }
  18358     if (enable) {
  18359         enable = 1;
  18360     } 
  18361 
  18362     BCM_IF_ERROR_RETURN(bcm_mn_cosq_cpu_cosq_enable_get(unit, cosq, &enable_status));
  18363     if (enable == enable_status) {
  18364         return BCM_E_NONE;
  18365     }
  18366 
  18367     index = _BCM_MN_CPU_COSQ_START + cosq; 
  18368 
  18369     for (i = 0; i < 2; i++) {
  18370         BCM_IF_ERROR_RETURN
  18371             (soc_mem_read(unit, thdm_mem[i], MEM_BLOCK_ALL, index, &entry));
  18372 
  18373         if (enable) {
  18374             soc_mem_field32_set(unit, thdm_mem[i], &entry,
  18375                                 Q_MIN_LIMITf, cpu_cosq->q_min_limit[i]);
  18376             soc_mem_field32_set(unit, thdm_mem[i], &entry,
  18377                                 Q_SHARED_LIMITf, cpu_cosq->q_shared_limit[i]);
  18378         }
  18379         else {
  18380             cpu_cosq->q_min_limit[i] = soc_mem_field32_get(unit,
  18381                                                            thdm_mem[i],
  18382                                                            &entry,
  18383                                                            Q_MIN_LIMITf);
  18384             cpu_cosq->q_shared_limit[i] = soc_mem_field32_get(unit,
  18385                                                               thdm_mem[i],
  18386                                                               &entry,
  18387                                                               Q_SHARED_LIMITf);
  18388             cpu_cosq->q_limit_dynamic[i] = soc_mem_field32_get(unit,
  18389                                                                thdm_mem[i],
  18390                                                                &entry,
  18391                                                                Q_LIMIT_DYNAMICf);
  18392             cpu_cosq->q_limit_enable[i] = soc_mem_field32_get(unit,
  18393                                                               thdm_mem[i],
  18394                                                               &entry,
  18395                                                               Q_LIMIT_ENABLEf);
  18396             cpu_cosq->q_color_limit_enable[i] = soc_mem_field32_get(unit,
  18397                                                               thdm_mem[i], &entry,
  18398                                                               Q_COLOR_LIMIT_ENABLEf);  
  18399             soc_mem_field32_set(unit, thdm_mem[i], &entry, Q_MIN_LIMITf, 0);
  18400             soc_mem_field32_set(unit, thdm_mem[i], &entry, Q_SHARED_LIMITf, 0);
  18401         }
  18402         soc_mem_field32_set(unit, thdm_mem[i], &entry,
  18403                             Q_LIMIT_DYNAMICf, enable ? cpu_cosq->q_limit_dynamic[i] : 0);
  18404         soc_mem_field32_set(unit, thdm_mem[i], &entry,
  18405                             Q_LIMIT_ENABLEf, enable ? cpu_cosq->q_limit_enable[i] : 1);
  18406         soc_mem_field32_set(unit, thdm_mem[i], &entry,
  18407                             Q_COLOR_LIMIT_ENABLEf, enable ? cpu_cosq->q_color_limit_enable[i] : 1);
  18408         cpu_cosq->enable = enable;
  18409         BCM_IF_ERROR_RETURN(
  18410             soc_mem_write(unit, thdm_mem[i], MEM_BLOCK_ALL, index, &entry));
  18411     }
  18412 
  18413     return BCM_E_NONE;
  18414 }
  18415 
  18416 /*
  18417  * Function:
  18418  *      bcm_mn_cosq_cpu_cosq_enable_get
  18419  * Purpose:
  18420  *      To get enable/disable status on Rx of packets on the specified CPU cosq.
  18421  * Parameters:
  18422  *      unit          - (IN) Unit number.
  18423  *      cosq          - (IN) CPU Cosq ID
  18424  *      enable        - (OUT) Enable/Disable
  18425  * Returns:
  18426  *      BCM_E_xxx
  18427  */
  18428 int
  18429 bcm_mn_cosq_cpu_cosq_enable_get(
  18430     int unit, 
  18431     bcm_cos_queue_t cosq, 
  18432     int *enable)
  18433 {
  18434     _bcm_mn_cosq_cpu_cosq_config_t *cpu_cosq;
  18435     soc_field_t dynamic_enable;
  18436     soc_info_t *si;
  18437     int index, hw_enable;
  18438     uint32 entry[SOC_MAX_MEM_WORDS];
  18439     soc_field_t min_limit, shared_limit, limit_enable;
  18440     soc_mem_t thd_mem = MMU_THDM_DB_QUEUE_CONFIG_0m;
  18441 
  18442     si = &SOC_INFO(unit);
  18443 
  18444     if ((cosq < 0) || (cosq >= si->num_cpu_cosq)) {
  18445         return BCM_E_PARAM;
  18446     }
  18447 
  18448     cpu_cosq = _bcm_mn_cosq_cpu_cosq_config[unit][cosq];
  18449 
  18450     if (!cpu_cosq) {
  18451         return BCM_E_INTERNAL;
  18452     }
  18453 
  18454     index = _BCM_MN_CPU_COSQ_START + cosq;
  18455     hw_enable = 1;
  18456 
  18457     /*sync up software record with hardware status*/
  18458     BCM_IF_ERROR_RETURN(soc_mem_read(unit, thd_mem, MEM_BLOCK_ALL, 
  18459                         index, &entry));
  18460     min_limit = soc_mem_field32_get( unit, thd_mem, &entry, 
  18461                         Q_MIN_LIMITf); 
  18462     shared_limit = soc_mem_field32_get(unit, thd_mem, &entry, 
  18463                         Q_SHARED_LIMITf);
  18464     limit_enable = soc_mem_field32_get(unit, thd_mem, &entry, 
  18465                         Q_LIMIT_ENABLEf);
  18466 
  18467     dynamic_enable = soc_mem_field32_get(unit, thd_mem, &entry,
  18468                         Q_LIMIT_DYNAMICf);
  18469     if (limit_enable && (dynamic_enable == 0)&&
  18470         (min_limit == 0) && (shared_limit == 0)) {
  18471         hw_enable = 0;
  18472     }
  18473     cpu_cosq->enable = hw_enable;
  18474 
  18475     *enable = cpu_cosq->enable;
  18476     return BCM_E_NONE;
  18477 }
  18478 
  18479 /*
  18480  * Function:
  18481  *      bcm_mn_cosq_flex_port_configure
  18482  * Purpose
  18483  *  Delete old default tree and create new tree as per the port type
  18484  *  Reconfigure all the queues of the port and configure the oversub config 
  18485  *  if required
  18486  * Parameters:
  18487  *      unit              -   (IN) Unit number.
  18488  *      old_port_list     -   (IN) List old ports getting deleted 
  18489  *      num_of_old_ports  -   (IN) Number of old ports getting deleted 
  18490  *      new_port_list     -   (IN) List new ports getting added 
  18491  *      num_of_new_ports  -   (IN) Number of new ports getting added 
  18492  *      num_port_flags    -   (IN) new ports flags 
  18493  * Returns:
  18494  *      BCM_E_xxx
  18495  */
  18496 int
  18497 bcm_mn_cosq_flex_port_update(
  18498         int unit,
  18499         bcm_port_t port, int enable) 
  18500 {
  18501 
  18502     _bcm_mn_mmu_info_t *mmu_info;
  18503     soc_info_t *si;
  18504     int numq; 
  18505     int qnum = 0 ;
  18506     _bcm_mn_pipe_resources_t *res; 
  18507     int phy_port,mmu_port;
  18508     int id; 
  18509     uint64 rval64;
  18510     int pipe;
  18511 
  18512     si = &SOC_INFO(unit);
  18513     mmu_info = _bcm_mn_mmu_info[unit];
  18514     phy_port = si->port_l2p_mapping[port];
  18515     mmu_port = si->port_p2m_mapping[phy_port];
  18516     /* root node */
  18517     numq = soc_property_port_get(unit, port, spn_LLS_NUM_L2UC, 16);
  18518     if (numq < 10 || numq > 16) {
  18519         numq = 10;
  18520     }
  18521     numq = (numq + 3) & ~3;
  18522 
  18523     pipe = _BCM_MN_PORT_TO_PIPE(unit, port);
  18524     res = _BCM_MN_PRESOURCES(mmu_info, pipe);
  18525     if (enable) { 
  18526         if(IS_MN_HSP_PORT(unit, port)) {
  18527            si->port_num_cosq[port] = 10;
  18528            si->port_cosq_base[port] = mmu_port * si->port_num_cosq[port];
  18529            si->port_num_uc_cosq[port] = 10;
  18530            si->port_uc_cosq_base[port] = mmu_port * si->port_num_cosq[port]; 
  18531         } else { 
  18532            BCM_IF_ERROR_RETURN(
  18533             _bcm_mn_node_index_get(res->l2_queue_list.bits, 0,
  18534                      mmu_info->num_l2_queues, numq, 
  18535                      8, &id));
  18536            _bcm_mn_node_index_set(&res->l2_queue_list, id, numq);
  18537            si->port_num_cosq[port] = 10; 
  18538            si->port_cosq_base[port] =  (mmu_port * si->port_num_cosq[port]);
  18539            si->port_num_uc_cosq[port] = numq;
  18540            si->port_uc_cosq_base[port] = id;   
  18541 
  18542         }
  18543 
  18544         mmu_info->port_info[port].resources = &mmu_info->pipe_resources[pipe];
  18545         mmu_info->port_info[port].mc_base = si->port_cosq_base[port];
  18546         mmu_info->port_info[port].mc_limit = si->port_cosq_base[port] + 
  18547                                              si->port_num_cosq[port];
  18548         mmu_info->port_info[port].uc_base = si->port_uc_cosq_base[port];
  18549         mmu_info->port_info[port].uc_limit = si->port_uc_cosq_base[port] + 
  18550                                              si->port_num_uc_cosq[port];
  18551         COMPILER_64_ZERO(rval64);
  18552         if(IS_MN_HSP_PORT(unit, port)) {
  18553            SOC_IF_ERROR_RETURN(soc_monterey_sched_hw_index_get(unit,
  18554                        port, SOC_MONTEREY_NODE_LVL_L1, 0, &qnum));
  18555         } else {
  18556             qnum = soc_monterey_logical_qnum_hw_qnum(unit, port,
  18557                      si->port_uc_cosq_base[port], 1);
  18558         }
  18559         soc_reg64_field32_set(unit, ING_COS_MODE_64r,
  18560                                           &rval64, BASE_QUEUE_NUM_0f, qnum);
  18561          soc_reg64_field32_set(unit, ING_COS_MODE_64r,
  18562                                           &rval64, BASE_QUEUE_NUM_1f, qnum);
  18563          BCM_IF_ERROR_RETURN(soc_reg_set(unit, ING_COS_MODE_64r, port, 0, rval64));
  18564 
  18565    } else { 
  18566         if(IS_MN_HSP_PORT(unit, port)) {
  18567            si->port_num_cosq[port] = -1;
  18568            si->port_cosq_base[port] = -1;
  18569            si->port_num_uc_cosq[port] = -1;
  18570            si->port_uc_cosq_base[port] = -1; 
  18571         } else { 
  18572            _bcm_mn_node_index_clear(&res->l2_queue_list, 
  18573                               si->port_uc_cosq_base[port], numq);
  18574            si->port_num_cosq[port] = -1; 
  18575            si->port_cosq_base[port] =  -1;
  18576            si->port_num_uc_cosq[port] = -1;
  18577            si->port_uc_cosq_base[port] = -1; 
  18578 
  18579         }
  18580 
  18581         COMPILER_64_ZERO(rval64);
  18582         mmu_info->port_info[port].resources = &mmu_info->pipe_resources[pipe];
  18583         mmu_info->port_info[port].mc_base = si->port_cosq_base[port];
  18584         mmu_info->port_info[port].mc_limit = si->port_cosq_base[port] + 
  18585                                              si->port_num_cosq[port];
  18586         mmu_info->port_info[port].uc_base = si->port_uc_cosq_base[port];
  18587         mmu_info->port_info[port].uc_limit = si->port_uc_cosq_base[port] + 
  18588                                              si->port_num_uc_cosq[port];
  18589         soc_reg64_field32_set(unit, ING_COS_MODE_64r,
  18590                                      &rval64, BASE_QUEUE_NUM_0f, 0);
  18591         soc_reg64_field32_set(unit, ING_COS_MODE_64r,
  18592                                      &rval64, BASE_QUEUE_NUM_1f, 0);
  18593         BCM_IF_ERROR_RETURN(soc_reg_set(unit, ING_COS_MODE_64r, port, 0, rval64));
  18594 
  18595 
  18596    }  
  18597    return BCM_E_NONE; 
  18598 
  18599 }
  18600 
  18601 int
  18602 _bcm_mn_cosq_gport_dump_subtree( int unit, bcm_gport_t gport)
  18603 {
  18604     _bcm_mn_cosq_node_t *node;
  18605     int num_spri = 0, first_child = 0, first_mc_child;
  18606     uint32 ucmap, spmap;
  18607     soc_monterey_sched_mode_e sched_mode;
  18608     int wt = 0;
  18609     char *lvl_name[] = { "Root", "S1",  "L0", "L1", "L2" };
  18610     char *sched_modes[] = {"X", "SP", "WRR", "WDRR"};
  18611 
  18612 
  18613     BCM_IF_ERROR_RETURN
  18614         (_bcm_mn_cosq_node_get(unit, gport, 0, NULL, NULL, NULL, &node));
  18615 
  18616    if (( node->level != SOC_MONTEREY_NODE_LVL_ROOT) && 
  18617            (node->level != SOC_MONTEREY_NODE_LVL_L2)) {
  18618         BCM_IF_ERROR_RETURN(
  18619                 soc_monterey_cosq_get_sched_child_config(unit, node->local_port,
  18620                     node->level,
  18621                     node->hw_index,
  18622                     &num_spri, &first_child,
  18623                     &first_mc_child, &ucmap, &spmap));
  18624     }
  18625     sched_mode = 0;
  18626     if (node->level != SOC_MONTEREY_NODE_LVL_ROOT) { 
  18627         SOC_IF_ERROR_RETURN(
  18628                 soc_monterey_cosq_get_sched_mode(unit, node->local_port, node->level, 
  18629                     node->hw_index, &sched_mode, &wt));
  18630     }
  18631     if (node->level == SOC_MONTEREY_NODE_LVL_ROOT) {
  18632         if (soc_feature(unit, soc_feature_mmu_hqos_four_level)) 
  18633         {
  18634              LOG_CLI((BSL_META_U(unit,
  18635                       "  %s.%d : INDEX=%d NUM_SPRI=0 FC=0 MODE=X Wt=0\n"),
  18636                       lvl_name[node->level], 
  18637                       node->attached_to_input,
  18638                       _soc_monterey_root_scheduler_index(unit, node->local_port)));
  18639         }
  18640     } else if (node->level == SOC_MONTEREY_NODE_LVL_S1) {
  18641         if (soc_feature(unit, soc_feature_mmu_hqos_four_level)) 
  18642         {
  18643             LOG_CLI((BSL_META_U(unit,
  18644                      "    %s.%d : INDEX=%d NUM_SPRI=%d FC=%d MODE=%s Wt=%d\n"),
  18645                     lvl_name[node->level], 
  18646                     node->attached_to_input, 
  18647                     node->hw_index, 
  18648                     num_spri, first_child,
  18649                     sched_modes[sched_mode],
  18650                     wt));
  18651          } else 
  18652          {
  18653             LOG_CLI((BSL_META_U(unit,
  18654                      "    %s.%d : INDEX=%d NUM_SPRI=%d FC=%d MODE=%s Wt=%d\n"),
  18655                     lvl_name[node->level - 1], 
  18656                     node->attached_to_input, 
  18657                     node->hw_index, 
  18658                     num_spri, first_child,
  18659                     sched_modes[sched_mode],
  18660                     wt));
  18661          } 
  18662 
  18663     } else if (node->level == SOC_MONTEREY_NODE_LVL_L0) {
  18664        LOG_CLI((BSL_META_U(unit,
  18665                         "      %s.%d : INDEX=%d NUM_SPRI=%d FC=%d MODE=%s Wt=%d\n"),
  18666                     lvl_name[node->level], 
  18667                     node->attached_to_input, 
  18668                     node->hw_index, 
  18669                     num_spri, first_child,
  18670                     sched_modes[sched_mode],
  18671                     wt));
  18672 
  18673     } else if (node->level == SOC_MONTEREY_NODE_LVL_L1) {
  18674         LOG_CLI((BSL_META_U(unit,
  18675                         "        %s.%d : INDEX=%d NUM_SP=%d FC=%d "
  18676                         "FMC=%d UCMAP=0x%08x MODE=%s WT=%d\n"),
  18677                     lvl_name[node->level], 
  18678                     node->attached_to_input, 
  18679                     node->hw_index, 
  18680                     num_spri, 
  18681                     first_child, 
  18682                     first_mc_child, 
  18683                     ucmap, 
  18684                     sched_modes[sched_mode],
  18685                     wt));
  18686     } else {
  18687         LOG_CLI((BSL_META_U(unit,
  18688                         "         %s.%s : INDEX=%d MODE=%s Wt=%d\n"),
  18689                     lvl_name[node->level],
  18690                     node->hw_index < 16384 ? "uc" : "mc",
  18691                     node->hw_index, 
  18692                     sched_modes[sched_mode],
  18693                     wt));
  18694     }
  18695 
  18696     if (node->child != NULL) {
  18697         _bcm_mn_cosq_gport_dump_subtree(unit, node->child->gport);
  18698     }
  18699 
  18700 
  18701     if (node->sibling != NULL)  {
  18702         _bcm_mn_cosq_gport_dump_subtree(unit, node->sibling->gport);
  18703     }
  18704 
  18705     return SOC_E_NONE;
  18706 }
  18707 
  18708 /*
  18709  * Function:
  18710  *      bcm_mn_cosq_service_classifier_id_create
  18711  * Purpose:
  18712  *      Create an endpoint.
  18713  * Parameters:
  18714  *      unit          - (IN) Unit number.
  18715  *      classifier    - (IN) Classifier attributes
  18716  *      classifier_id - (OUT) Classifier ID
  18717  * Returns:
  18718  *      BCM_E_xxx
  18719  */
  18720 int
  18721 bcm_mn_cosq_service_classifier_id_create(
  18722     int unit,
  18723     bcm_cosq_classifier_t *classifier,
  18724     int *classifier_id)
  18725 {
  18726     if (NULL == classifier || NULL == classifier_id) {
  18727         return BCM_E_PARAM;
  18728     }
  18729 
  18730     _BCM_COSQ_CLASSIFIER_SERVICE_SET(*classifier_id, classifier->vlan);
  18731     return BCM_E_NONE;
  18732 }
  18733 
  18734 /*
  18735  * Function:
  18736  *      bcm_mn_cosq_service_classifier_id_destroy
  18737  * Purpose:
  18738  *      free resource associated with this service classifier id.
  18739  * Parameters:
  18740  *      unit          - (IN) Unit number.
  18741  *      classifier_id - (IN) Classifier ID
  18742  * Returns:
  18743  *      BCM_E_xxx
  18744  */
  18745 int
  18746 bcm_mn_cosq_service_classifier_id_destroy(
  18747     int unit,
  18748     int classifier_id)
  18749 {
  18750     return BCM_E_NONE;
  18751 }
  18752 
  18753 /*
  18754  * Function:
  18755  *      bcm_mn_cosq_service_classifier_get
  18756  * Purpose:
  18757  *      Get info about an endpoint.
  18758  * Parameters:
  18759  *      unit          - (IN) Unit number.
  18760  *      classifier_id - (IN) Classifier ID
  18761  *      classifier    - (OUT) Classifier info
  18762  * Returns:
  18763  *      BCM_E_xxx
  18764  */
  18765 int
  18766 bcm_mn_cosq_service_classifier_get(
  18767     int unit,
  18768     int classifier_id,
  18769     bcm_cosq_classifier_t *classifier)
  18770 {
  18771     int val = 0;
  18772 
  18773     sal_memset(classifier, 0, sizeof(bcm_cosq_classifier_t));
  18774 
  18775     val = _BCM_COSQ_CLASSIFIER_SERVICE_GET(classifier_id);
  18776 
  18777     if (val > BCM_VLAN_MAX) {
  18778         /* VFI classifier */
  18779         classifier->flags = BCM_COSQ_CLASSIFIER_VFI;
  18780         classifier->vfi_index = val - BCM_VLAN_MAX - 1;
  18781     } else {
  18782         classifier->flags = BCM_COSQ_CLASSIFIER_VLAN;
  18783         classifier->vlan = val;
  18784     }
  18785     return BCM_E_NONE;
  18786 }
  18787 
  18788 /*
  18789  * Function:
  18790  *      bcm_mn_cosq_service_map_set
  18791  * Purpose:
  18792  *      Set the mapping from port, classifier, and multiple internal priorities
  18793  *      to multiple COS queues in a queue group.
  18794  * Parameters:
  18795  *      unit           - (IN) Unit number.
  18796  *      port           - (IN) local port ID
  18797  *      classifier_id  - (IN) Classifier ID
  18798  *      queue_group    - (IN) Base queue ID
  18799  *      array_count    - (IN) Number of elements in priority_array and
  18800  *                            cosq_array
  18801  *      priority_array - (IN) Array of internal priorities
  18802  *      cosq_array     - (IN) Array of COS queues
  18803  * Returns:
  18804  *      BCM_E_xxx
  18805  */
  18806 int
  18807 bcm_mn_cosq_service_map_set(
  18808     int unit,
  18809     bcm_port_t port,
  18810     int classifier_id,
  18811     bcm_gport_t queue_group,
  18812     int array_count,
  18813     bcm_cos_t *priority_array,
  18814     bcm_cos_queue_t *cosq_array)
  18815 {
  18816     service_queue_map_entry_t  sqm;
  18817     service_port_map_entry_t   *spm = NULL;
  18818     service_cos_map_entry_t    *scm = NULL;
  18819     void                       *spm_entries[1];
  18820     void                       *scm_entries[1];
  18821     int                        rv = BCM_E_NONE;
  18822     int                        i, j, numq, alloc_size, exists = 0;
  18823     int                        local_port, vid, qid, cos_offset = 0;
  18824     int                        port_offset, port_offset_old;
  18825     int                        qptr_old, qptr_new;
  18826     uint32                     scm_idx, spm_idx, spm_idx_old = 0;
  18827     _bcm_mn_cosq_node_t       *node;
  18828     soc_profile_mem_t          *spm_profile_mem, *scm_profile_mem;
  18829     /*
  18830      * The port_offset= 0 is treated as the invalid offset so that
  18831      * the ports without being service map set can be recognized easily by software.
  18832      * Accordingly, The valid port_offset needs to be at least 1 for a given port.
  18833      * the queue base to be written into SERVICE_QUEUE_PTRf will
  18834      * be (the actual base - 1).
  18835      */
  18836    #define VALID_PORT_OFFSET_MIN          1
  18837 
  18838     if (!_BCM_COSQ_CLASSIFIER_IS_SERVICE(classifier_id)) {
  18839         return BCM_E_PARAM;
  18840     }
  18841 
  18842     /* index above 4K is for VFI */
  18843     vid = _BCM_COSQ_CLASSIFIER_SERVICE_GET(classifier_id);
  18844     if (vid < 0 || vid >= SOC_MEM_SIZE(unit, SERVICE_QUEUE_MAPm)) {
  18845         return BCM_E_PARAM;
  18846     }
  18847 
  18848     if (array_count > _MN_SCM_ENTRIES_PER_SET) {
  18849         return BCM_E_PARAM;
  18850     }
  18851     scm_profile_mem = _bcm_mn_service_cos_map_profile[unit];
  18852     spm_profile_mem = _bcm_mn_service_port_map_profile[unit];
  18853 
  18854     BCM_IF_ERROR_RETURN(
  18855         _bcm_mn_cosq_node_get(unit, queue_group, 0, NULL,
  18856                                &local_port, &qid, &node));
  18857     if (node->attached_to_input < 0) {
  18858         return BCM_E_PARAM;
  18859     }
  18860     numq = node->parent->numq;
  18861     qid = node->hw_index;
  18862 
  18863     for (i = 0; i < array_count; i++) {
  18864         if (cosq_array[i] >= numq) {
  18865             return BCM_E_PARAM;
  18866         }
  18867     }
  18868 
  18869     sal_memset(&sqm, 0, sizeof(service_queue_map_entry_t));
  18870     SOC_IF_ERROR_RETURN(
  18871         soc_mem_read(unit, SERVICE_QUEUE_MAPm, MEM_BLOCK_ANY, (int)vid, &sqm));
  18872 
  18873     if (soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, &sqm, VALIDf)) {
  18874         exists = 1;
  18875     } else {
  18876         exists = 0;
  18877     }
  18878 
  18879     alloc_size = sizeof(service_port_map_entry_t) * _MN_SPM_ENTRIES_PER_SET;
  18880     spm = sal_alloc(alloc_size, "SERVICE_PORT_MAP temp Mem");
  18881     if (spm == NULL) {
  18882         rv = BCM_E_MEMORY;
  18883         goto cleanup;
  18884     }
  18885     sal_memset(spm, 0, alloc_size);
  18886     spm_entries[0] = spm;
  18887 
  18888     alloc_size = sizeof(service_cos_map_entry_t) * _MN_SCM_ENTRIES_PER_SET;
  18889     scm = sal_alloc(alloc_size, "SERVICE_COS_MAP temp Mem");
  18890     if (scm == NULL) {
  18891         rv = BCM_E_MEMORY;
  18892         goto cleanup;
  18893     }
  18894     sal_memset(scm, 0, alloc_size);
  18895     scm_entries[0] = scm;
  18896 
  18897     /*  1. program the SERVICE_COS_MAPm. */
  18898     if (!exists) {
  18899         for (i = 0; i < array_count; i++) {
  18900             if (priority_array[i] < _MN_SCM_ENTRIES_PER_SET) {
  18901                 soc_mem_field32_set(unit, SERVICE_COS_MAPm,
  18902                                     &scm[priority_array[i]],
  18903                                     SERVICE_COS_OFFSETf, cosq_array[i]);
  18904             }
  18905         }
  18906 
  18907         rv = soc_profile_mem_add(unit, scm_profile_mem, scm_entries,
  18908                                  _MN_SCM_ENTRIES_PER_SET, &scm_idx);
  18909         if (rv != SOC_E_NONE) {
  18910             goto cleanup;
  18911         }
  18912     } else {
  18913         /*
  18914          * only one service_cos_map profile is allowed per vlan/vfi.
  18915          * If the subsequent profile doesn't match the existing one,
  18916          * it will be treated as an error.
  18917          */
  18918         scm_idx = _MN_SCM_ENTRIES_PER_SET *
  18919                   soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, &sqm,
  18920                                       SERVICE_COS_PROFILE_INDEXf);
  18921         rv = soc_profile_mem_get(unit, scm_profile_mem, scm_idx,
  18922                                  _MN_SCM_ENTRIES_PER_SET, scm_entries);
  18923         if (rv != SOC_E_NONE) {
  18924             goto cleanup;
  18925         }
  18926 
  18927         for (i = 0; i < array_count; i++) {
  18928             cos_offset = soc_mem_field32_get(unit, SERVICE_COS_MAPm,
  18929                                              &scm[priority_array[i]],
  18930                                              SERVICE_COS_OFFSETf);
  18931             if (cosq_array[i] != cos_offset) {
  18932                 rv = BCM_E_PARAM;
  18933                 goto cleanup;
  18934             }
  18935         }
  18936 
  18937         for (i = 0; i < _MN_SCM_ENTRIES_PER_SET; i++) {
  18938             for (j = 0; j < array_count; j++) {
  18939                 if (i == priority_array[j]) {
  18940                     break;
  18941                 }
  18942             }
  18943             /* for priorities not in priority_array, the cosq should be 0 */
  18944             if (j == array_count) {
  18945                 cos_offset = soc_mem_field32_get(unit, SERVICE_COS_MAPm,
  18946                                                  &scm[i],SERVICE_COS_OFFSETf);
  18947                 if (cos_offset) {
  18948                     rv = BCM_E_PARAM;
  18949                     goto cleanup;
  18950                 }
  18951             }
  18952         }
  18953     }
  18954 
  18955     /*  2. program the SERVICE_PORT_MAPm. */
  18956     if (!exists) {
  18957         port_offset = VALID_PORT_OFFSET_MIN;
  18958         soc_mem_field32_set(unit, SERVICE_PORT_MAPm, &spm[local_port],
  18959                             SERVICE_PORT_OFFSETf, port_offset);
  18960     } else {
  18961         spm_idx_old = _MN_SPM_ENTRIES_PER_SET *
  18962                       soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, &sqm,
  18963                                           SERVICE_PORT_PROFILE_INDEXf);
  18964         rv = soc_profile_mem_get(unit, spm_profile_mem, spm_idx_old,
  18965                                  _MN_SPM_ENTRIES_PER_SET, spm_entries);
  18966         if (!(rv == SOC_E_NOT_FOUND || rv == SOC_E_NONE)) {
  18967             goto cleanup;
  18968         }
  18969 
  18970         qptr_old = soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm,
  18971                                        &sqm, SERVICE_QUEUE_PTRf);
  18972         if (qid <= qptr_old) {
  18973             qptr_new = qid - VALID_PORT_OFFSET_MIN;
  18974             for (i = 0; i < _MN_SPM_ENTRIES_PER_SET; i++) {
  18975                 port_offset_old = soc_mem_field32_get(unit, SERVICE_PORT_MAPm,
  18976                                                       &spm[i],
  18977                                                       SERVICE_PORT_OFFSETf);
  18978                 if (i == local_port) {
  18979                     port_offset = VALID_PORT_OFFSET_MIN;
  18980                 }  else if (!port_offset_old) {
  18981                     /*
  18982                      * For the old port_offsets with 0,
  18983                      * the new port_offsest are still 0.
  18984                      */
  18985                     continue;
  18986                 } else {
  18987                     port_offset = qptr_old + port_offset_old - qptr_new;
  18988                 }
  18989                 soc_mem_field32_set(unit, SERVICE_PORT_MAPm, &spm[i],
  18990                                     SERVICE_PORT_OFFSETf, port_offset);
  18991             }
  18992         } else {
  18993             port_offset = qid - qptr_old;
  18994             soc_mem_field32_set(unit, SERVICE_PORT_MAPm, &spm[local_port],
  18995                                 SERVICE_PORT_OFFSETf, port_offset);
  18996         }
  18997     }
  18998     rv = soc_profile_mem_add(unit, spm_profile_mem,
  18999                              spm_entries, _MN_SPM_ENTRIES_PER_SET, &spm_idx);
  19000     if (rv != SOC_E_NONE) {
  19001         goto cleanup;
  19002     }
  19003 
  19004     /* 3. program the SERVICE_QUEUE_MAPm */
  19005     if (!exists) {
  19006         qptr_new = qid - VALID_PORT_OFFSET_MIN;
  19007     } else {
  19008         qptr_old = soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm,
  19009                                        &sqm, SERVICE_QUEUE_PTRf);
  19010         if (qid <= qptr_old) {
  19011             qptr_new = qid - VALID_PORT_OFFSET_MIN;
  19012         } else {
  19013             qptr_new = qptr_old;
  19014         }
  19015     }
  19016 
  19017     soc_mem_field32_set(unit, SERVICE_QUEUE_MAPm, &sqm,
  19018                         SERVICE_QUEUE_PTRf, qptr_new);
  19019     soc_mem_field32_set(unit, SERVICE_QUEUE_MAPm, &sqm,
  19020                         SERVICE_COS_PROFILE_INDEXf,
  19021                         scm_idx / _MN_SCM_ENTRIES_PER_SET);
  19022     soc_mem_field32_set(unit, SERVICE_QUEUE_MAPm, &sqm,
  19023                         SERVICE_PORT_PROFILE_INDEXf,
  19024                         spm_idx / _MN_SPM_ENTRIES_PER_SET);
  19025     /* use port indexed and cos indexed for this base queue */
  19026     soc_mem_field32_set(unit, SERVICE_QUEUE_MAPm, &sqm,
  19027                         SERVICE_QUEUE_MODELf, 3);
  19028     soc_mem_field32_set(unit, SERVICE_QUEUE_MAPm, &sqm, VALIDf, 1);
  19029 
  19030     rv = soc_mem_write(unit, SERVICE_QUEUE_MAPm, MEM_BLOCK_ALL, (int)vid, &sqm);
  19031 
  19032     if (exists) {
  19033         if (spm_idx_old != spm_idx) {
  19034             rv = soc_profile_mem_delete(unit, spm_profile_mem, spm_idx_old);
  19035         }
  19036     }
  19037 
  19038 cleanup:
  19039     if (spm != NULL) {
  19040         sal_free(spm);
  19041     }
  19042     if (scm != NULL) {
  19043         sal_free(scm);
  19044     }
  19045     return rv;
  19046 }
  19047 
  19048 /*
  19049  * Function:
  19050  *      bcm_mn_cosq_service_map_get
  19051  * Purpose:
  19052  *      Get the mapping from port, classifier, and multiple internal priorities
  19053  *      to multiple COS queues in a queue group.
  19054  * Parameters:
  19055  *      unit           - (IN) Unit number.
  19056  *      port           - (IN) Local port ID
  19057  *      classifier_id  - (IN) Classifier ID
  19058  *      queue_group    - (OUT) Queue group
  19059  *      array_max      - (IN) Size of priority_array and cosq_array
  19060  *      priority_array - (IN) Array of internal priorities
  19061  *      cosq_array     - (OUT) Array of COS queues
  19062  *      array_count    - (OUT) Size of cosq_array
  19063  * Returns:
  19064  *      BCM_E_xxx
  19065  */
  19066 int
  19067 bcm_mn_cosq_service_map_get(
  19068     int unit,
  19069     bcm_port_t port,
  19070     int classifier_id,
  19071     bcm_gport_t *queue_group,
  19072     int array_max,
  19073     bcm_cos_t *priority_array,
  19074     bcm_cos_queue_t *cosq_array,
  19075     int *array_count)
  19076 {
  19077     int                        alloc_size, port_offset, i, vid, qptr;
  19078     int                        spm_index, scm_index;
  19079     int                        rv = BCM_E_NONE;
  19080     void                       *spm_entries[1];
  19081     void                       *scm_entries[1];
  19082     service_queue_map_entry_t  sqm;
  19083     service_port_map_entry_t   *spm;
  19084     service_cos_map_entry_t    *scm;
  19085     soc_profile_mem_t          *spm_profile_mem, *scm_profile_mem;
  19086 
  19087     if (priority_array == NULL || cosq_array == NULL ||
  19088         array_count == NULL || queue_group == NULL) {
  19089         return BCM_E_PARAM;
  19090     }
  19091 
  19092     if (!_BCM_COSQ_CLASSIFIER_IS_SERVICE(classifier_id)) {
  19093         return BCM_E_PARAM;
  19094     }
  19095 
  19096     /* index above 4K is for VFI */
  19097     vid = _BCM_COSQ_CLASSIFIER_SERVICE_GET(classifier_id);
  19098     if (vid < 0 || vid >= SOC_MEM_SIZE(unit, SERVICE_QUEUE_MAPm)) {
  19099         return BCM_E_PARAM;
  19100     }
  19101 
  19102     scm_profile_mem = _bcm_mn_service_cos_map_profile[unit];
  19103     spm_profile_mem = _bcm_mn_service_port_map_profile[unit];
  19104 
  19105     SOC_IF_ERROR_RETURN(
  19106         soc_mem_read(unit, SERVICE_QUEUE_MAPm, MEM_BLOCK_ANY, (int)vid, &sqm));
  19107 
  19108     if (!soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, &sqm, VALIDf)) {
  19109         return BCM_E_CONFIG;
  19110     }
  19111 
  19112     qptr = soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm,
  19113                                &sqm, SERVICE_QUEUE_PTRf);
  19114     spm_index = _MN_SPM_ENTRIES_PER_SET *
  19115                 soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, &sqm,
  19116                                     SERVICE_PORT_PROFILE_INDEXf);
  19117     scm_index = _MN_SCM_ENTRIES_PER_SET *
  19118                 soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, &sqm,
  19119                                SERVICE_COS_PROFILE_INDEXf);
  19120 
  19121     alloc_size = sizeof(service_port_map_entry_t) * _MN_SPM_ENTRIES_PER_SET;
  19122     spm = sal_alloc(alloc_size, "SERVICE_PORT_MAP temp Mem");
  19123     if (spm == NULL) {
  19124         return BCM_E_MEMORY;
  19125     }
  19126     sal_memset(spm, 0, alloc_size);
  19127     spm_entries[0] = spm;
  19128 
  19129     alloc_size = sizeof(service_cos_map_entry_t) * _MN_SCM_ENTRIES_PER_SET;
  19130     scm = sal_alloc(alloc_size, "SERVICE_COS_MAP temp Mem");
  19131     if (scm == NULL) {
  19132         goto cleaup;
  19133     }
  19134     sal_memset(scm, 0, alloc_size);
  19135     scm_entries[0] = scm;
  19136 
  19137     rv = soc_profile_mem_get(unit, spm_profile_mem,
  19138                              spm_index, _MN_SPM_ENTRIES_PER_SET, spm_entries);
  19139     if (!(rv == SOC_E_NOT_FOUND || rv == SOC_E_NONE)) {
  19140         goto cleaup;
  19141     }
  19142 
  19143     rv = soc_profile_mem_get(unit, scm_profile_mem,
  19144                              scm_index, _MN_SCM_ENTRIES_PER_SET, scm_entries);
  19145     if (!(rv == SOC_E_NOT_FOUND || rv == SOC_E_NONE)) {
  19146         goto cleaup;
  19147     }
  19148 
  19149     port_offset = soc_mem_field32_get(unit, SERVICE_PORT_MAPm,
  19150                                       &spm[port], SERVICE_PORT_OFFSETf);
  19151     if (port_offset == 0) {
  19152         rv = BCM_E_NOT_FOUND;
  19153         goto cleaup;
  19154     }
  19155     BCM_GPORT_UCAST_QUEUE_GROUP_SYSQID_SET(*queue_group, port,
  19156                                            (port_offset + qptr));
  19157 
  19158     *array_count = array_max > _MN_SCM_ENTRIES_PER_SET ?
  19159                    _MN_SCM_ENTRIES_PER_SET : array_max;
  19160     for (i = 0; i < *array_count; i++) {
  19161         if (priority_array[i] >= _MN_SCM_ENTRIES_PER_SET) {
  19162             rv = BCM_E_PARAM;
  19163             goto cleaup;
  19164         }
  19165         cosq_array[i] = soc_mem_field32_get(unit, SERVICE_COS_MAPm,
  19166                                             &scm[priority_array[i]],
  19167                                             SERVICE_COS_OFFSETf);
  19168     }
  19169 
  19170 cleaup:
  19171     if (spm != NULL) {
  19172         sal_free(spm);
  19173     }
  19174     if (scm != NULL) {
  19175         sal_free(scm);
  19176     }
  19177     return rv;
  19178 }
  19179 
  19180 /*
  19181  * Function:
  19182  *      bcm_mn_cosq_service_map_clear
  19183  * Purpose:
  19184  *      Clear the mapping from port, classifier, and internal priorities
  19185  *      to COS queues in a queue group.
  19186  * Parameters:
  19187  *      unit          - (IN) Unit number.
  19188  *      port          - (IN) Local port ID
  19189  *      classifier_id - (IN) Classifier ID
  19190  * Returns:
  19191  *      BCM_E_xxx
  19192  */
  19193 int
  19194 bcm_mn_cosq_service_map_clear(
  19195     int unit,
  19196     bcm_gport_t port,
  19197     int classifier_id)
  19198 {
  19199     int                        i, alloc_size, vid, classifier_in_use;
  19200     int                        rv = BCM_E_NONE;
  19201     int                        scm_index;
  19202     uint32                     spm_index, spm_index_new;
  19203     void                       *spm_entries[1];
  19204     service_port_map_entry_t   *spm;
  19205     service_queue_map_entry_t  sqm;
  19206     soc_profile_mem_t          *spm_profile_mem, *scm_profile_mem;
  19207 
  19208     if (!_BCM_COSQ_CLASSIFIER_IS_SERVICE(classifier_id)) {
  19209         return BCM_E_PARAM;
  19210     }
  19211 
  19212     /* index above 4K is for VFI */
  19213     vid = _BCM_COSQ_CLASSIFIER_SERVICE_GET(classifier_id);
  19214     if (vid < 0 || vid >= SOC_MEM_SIZE(unit, SERVICE_QUEUE_MAPm)) {
  19215         return BCM_E_PARAM;
  19216     }
  19217 
  19218     scm_profile_mem = _bcm_mn_service_cos_map_profile[unit];
  19219     spm_profile_mem = _bcm_mn_service_port_map_profile[unit];
  19220 
  19221     SOC_IF_ERROR_RETURN(
  19222         soc_mem_read(unit, SERVICE_QUEUE_MAPm, MEM_BLOCK_ANY, (int)vid, &sqm));
  19223 
  19224     if (!soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, &sqm, VALIDf)) {
  19225         return BCM_E_NONE;
  19226     }
  19227 
  19228     /*  1. program the SERVICE_PORT_MAPm. */
  19229     alloc_size = sizeof(service_port_map_entry_t) * _MN_SPM_ENTRIES_PER_SET;
  19230     spm = sal_alloc(alloc_size, "SERVICE_PORT_MAP temp Mem");
  19231     if (spm == NULL) {
  19232         return BCM_E_MEMORY;
  19233     }
  19234     sal_memset(spm, 0, alloc_size);
  19235     spm_entries[0] = spm;
  19236 
  19237     spm_index = _MN_SPM_ENTRIES_PER_SET *
  19238                 soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, &sqm,
  19239                                     SERVICE_PORT_PROFILE_INDEXf);
  19240     rv = soc_profile_mem_get(unit, spm_profile_mem,
  19241                              spm_index, _MN_SPM_ENTRIES_PER_SET, spm_entries);
  19242     if (!(rv == SOC_E_NOT_FOUND || rv == SOC_E_NONE)) {
  19243         goto cleanup;
  19244     }
  19245 
  19246     soc_mem_field32_set(unit, SERVICE_PORT_MAPm,
  19247                         &spm[port], SERVICE_PORT_OFFSETf, 0);
  19248     classifier_in_use = 0;
  19249     for (i = 0; i < _MN_SPM_ENTRIES_PER_SET; i++) {
  19250         if (soc_mem_field32_get(unit, SERVICE_PORT_MAPm,
  19251                                 &spm[i], SERVICE_PORT_OFFSETf)) {
  19252             classifier_in_use = 1;
  19253             break;
  19254         }
  19255     }
  19256 
  19257     rv = soc_profile_mem_delete(unit, spm_profile_mem, spm_index);
  19258     if (rv != SOC_E_NONE) {
  19259         goto cleanup;
  19260     }
  19261 
  19262     if (classifier_in_use) {
  19263        rv = soc_profile_mem_add(unit, spm_profile_mem,
  19264                                 spm_entries, _MN_SPM_ENTRIES_PER_SET,
  19265                                 &spm_index_new);
  19266        if (rv != SOC_E_NONE) {
  19267            goto cleanup;
  19268        }
  19269     }
  19270 
  19271     /*  2. program the SERVICE_COS_MAPm. */
  19272     if (!classifier_in_use) {
  19273         scm_index = _MN_SCM_ENTRIES_PER_SET *
  19274                     soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, &sqm,
  19275                                         SERVICE_COS_PROFILE_INDEXf);
  19276         rv = soc_profile_mem_delete(unit, scm_profile_mem, scm_index);
  19277         if (rv != SOC_E_NONE) {
  19278             goto cleanup;
  19279         }
  19280     }
  19281 
  19282     /*  3. program the SERVICE_QUEUE_MAPm. */
  19283     if (classifier_in_use) {
  19284         soc_mem_field32_set(unit, SERVICE_QUEUE_MAPm, &sqm,
  19285                             SERVICE_PORT_PROFILE_INDEXf,
  19286                             spm_index_new / _MN_SPM_ENTRIES_PER_SET);
  19287     } else {
  19288         sal_memset(&sqm,0, sizeof(service_queue_map_entry_t));
  19289     }
  19290 
  19291     rv =  soc_mem_write(unit, SERVICE_QUEUE_MAPm, MEM_BLOCK_ALL,
  19292                        (int)vid, &sqm);
  19293 
  19294 cleanup:
  19295     if (spm != NULL) {
  19296         sal_free(spm);
  19297     }
  19298     return rv;
  19299 }
  19300 
  19301 /******************************************************************/
  19302 /*                         OBM CLASSIFIER  START                  */
  19303 /******************************************************************/
  19304 
  19305 /*
  19306  * Function:
  19307  *      bcm_mn_switch_obm_dscp_classifier_mapping_multi_set
  19308  * Purpose:
  19309  *      Set the mapping of bcm_obm_code_point to bcm_obm_priority
  19310  *      for multiple entries of dscp classifier type.
  19311  * Parameters:
  19312  *      unit                     - (IN) Unit number.
  19313  *      phy_port                 - (IN) Physical port.
  19314  *      pgw                      - (IN) PGW index (0 0r 1).
  19315  *      array_count              - (IN) Number of dscp entries.
  19316  *      switch_obm_classifier    - (IN) Array of dscp entries.
  19317  * Returns:
  19318  *      BCM_E_xxx
  19319  */
  19320 
  19321 STATIC
  19322 int bcm_mn_switch_obm_dscp_classifier_mapping_multi_set(
  19323                  int unit,
  19324                  int phy_port,
  19325                  int pgw,
  19326                  int array_count,
  19327                  bcm_switch_obm_classifier_t *switch_obm_classifier)
  19328 {
  19329     int                             i, code_point, ob_priority;
  19330     int                             entry_index[4], shadow_base_index;
  19331     idb_obm0_dscp_map_port0_entry_t entry[4];
  19332     bcm_switch_obm_classifier_t     *classifier_ptr = NULL;
  19333     soc_mem_t                       mem;
  19334 
  19335     static const soc_mem_t obm_dscp_map_port_mem[] = {
  19336         IDB_OBM0_DSCP_MAP_PORT0m, IDB_OBM0_DSCP_MAP_PORT1m,
  19337         IDB_OBM0_DSCP_MAP_PORT2m, IDB_OBM0_DSCP_MAP_PORT3m,
  19338         IDB_OBM1_DSCP_MAP_PORT0m, IDB_OBM1_DSCP_MAP_PORT1m,
  19339         IDB_OBM1_DSCP_MAP_PORT2m, IDB_OBM1_DSCP_MAP_PORT3m,
  19340         IDB_OBM2_DSCP_MAP_PORT0m, IDB_OBM2_DSCP_MAP_PORT1m,
  19341         IDB_OBM2_DSCP_MAP_PORT2m, IDB_OBM2_DSCP_MAP_PORT3m,
  19342         IDB_OBM3_DSCP_MAP_PORT0m, IDB_OBM3_DSCP_MAP_PORT1m,
  19343         IDB_OBM3_DSCP_MAP_PORT2m, IDB_OBM3_DSCP_MAP_PORT3m,
  19344         IDB_OBM4_DSCP_MAP_PORT0m, IDB_OBM4_DSCP_MAP_PORT1m,
  19345         IDB_OBM4_DSCP_MAP_PORT2m, IDB_OBM4_DSCP_MAP_PORT3m,
  19346         IDB_OBM5_DSCP_MAP_PORT0m, IDB_OBM5_DSCP_MAP_PORT1m,
  19347         IDB_OBM5_DSCP_MAP_PORT2m, IDB_OBM5_DSCP_MAP_PORT3m,
  19348         IDB_OBM6_DSCP_MAP_PORT0m, IDB_OBM6_DSCP_MAP_PORT1m,
  19349         IDB_OBM6_DSCP_MAP_PORT2m, IDB_OBM6_DSCP_MAP_PORT3m,
  19350         IDB_OBM7_DSCP_MAP_PORT0m, IDB_OBM7_DSCP_MAP_PORT1m,
  19351         IDB_OBM7_DSCP_MAP_PORT2m, IDB_OBM7_DSCP_MAP_PORT3m
  19352     };
  19353     static const soc_field_t offset_ob_prio[] = {
  19354         OFFSET0_OB_PRIORITYf, OFFSET1_OB_PRIORITYf, OFFSET2_OB_PRIORITYf,
  19355         OFFSET3_OB_PRIORITYf, OFFSET4_OB_PRIORITYf, OFFSET5_OB_PRIORITYf,
  19356         OFFSET6_OB_PRIORITYf, OFFSET7_OB_PRIORITYf, OFFSET8_OB_PRIORITYf,
  19357         OFFSET9_OB_PRIORITYf, OFFSET10_OB_PRIORITYf, OFFSET11_OB_PRIORITYf,
  19358         OFFSET12_OB_PRIORITYf, OFFSET13_OB_PRIORITYf, OFFSET14_OB_PRIORITYf,
  19359         OFFSET15_OB_PRIORITYf
  19360     };
  19361 
  19362     mem = obm_dscp_map_port_mem[(phy_port - 1) % _MN_PORTS_PER_PGW];
  19363     shadow_base_index = pgw * soc_mem_index_count(unit, mem);
  19364     for (i = 0; i < 4; i++) {
  19365          entry_index[i] = 0;
  19366          sal_memset(&entry[i], 0, sizeof(entry[i]));
  19367          SOC_IF_ERROR_RETURN(soc_monterey_shadow_entry_get(unit, mem,
  19368                              shadow_base_index + i, &entry[i]));
  19369     }
  19370 
  19371     for (i = 0; i < array_count; i++) {
  19372          classifier_ptr = switch_obm_classifier + i;
  19373          code_point = classifier_ptr->obm_code_point;
  19374          ob_priority = classifier_ptr->obm_priority;
  19375          if (code_point < BCM_OBM_DSCP_CHUNK_SIZE) {
  19376              soc_mem_field32_set(unit, mem, &entry[0],
  19377                                  offset_ob_prio[code_point], ob_priority);
  19378              entry_index[0] = 1;
  19379          } else if (code_point < 2 * BCM_OBM_DSCP_CHUNK_SIZE ) {
  19380              soc_mem_field32_set(unit, mem, &entry[1],
  19381                                  offset_ob_prio[code_point % BCM_OBM_DSCP_CHUNK_SIZE],
  19382                                  ob_priority);
  19383             entry_index[1] = 1;
  19384          } else if (code_point < 3 * BCM_OBM_DSCP_CHUNK_SIZE) {
  19385              soc_mem_field32_set(unit, mem, &entry[2],
  19386                                  offset_ob_prio[code_point % BCM_OBM_DSCP_CHUNK_SIZE],
  19387                                  ob_priority);
  19388              entry_index[2] = 1;
  19389          } else {
  19390              soc_mem_field32_set(unit, mem, &entry[3],
  19391                                  offset_ob_prio[code_point % BCM_OBM_DSCP_CHUNK_SIZE],
  19392                                  ob_priority);
  19393              entry_index[3] = 1;
  19394          }
  19395     }
  19396     for (i = 0; i < 4; i++) {
  19397          if (entry_index[i]) {
  19398              SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem, PGW_CL_BLOCK(unit, pgw),
  19399                                                i, &entry[i]));
  19400              SOC_IF_ERROR_RETURN(soc_monterey_shadow_entry_set(unit, mem,
  19401                                  shadow_base_index + i, &entry[i]));
  19402          }
  19403     }
  19404     return BCM_E_NONE;
  19405 
  19406 }
  19407 /*
  19408  * Function:
  19409  *      bcm_mn_switch_obm_dscp_classifier_mapping_multi_get
  19410  * Purpose:
  19411  *      Set the mapping of bcm_obm_code_point to bcm_obm_priority
  19412  *      for multiple entries of dscp classifier type.
  19413  * Parameters:
  19414  *      unit                     - (IN) Unit number.
  19415  *      phy_port                 - (IN) Physical port.
  19416  *      pgw                      - (IN) PGW index (0 0r 1).
  19417  *      array_max                - (IN) Maximum number of entries.
  19418  *      switch_obm_classifier    - (IN/OUT) Array of dscp entries.
  19419  *      array_count              - (OUT) Number of dscp entries.
  19420  * Returns:
  19421  *      BCM_E_xxx
  19422  */
  19423 STATIC
  19424 int bcm_mn_switch_obm_dscp_classifier_mapping_multi_get(
  19425                  int unit,
  19426                  int phy_port,
  19427                  int pgw,
  19428                  int array_max,
  19429                  bcm_switch_obm_classifier_t *switch_obm_classifier,
  19430                  int *array_count)
  19431 {
  19432     int                             i, code_point, ob_priority, shadow_base_index;
  19433     idb_obm0_dscp_map_port0_entry_t entry[4];
  19434     bcm_switch_obm_classifier_t     *classifier_ptr = NULL;
  19435     soc_mem_t                       mem;
  19436 
  19437     static const soc_mem_t obm_dscp_map_port_mem[] = {
  19438         IDB_OBM0_DSCP_MAP_PORT0m, IDB_OBM0_DSCP_MAP_PORT1m,
  19439         IDB_OBM0_DSCP_MAP_PORT2m, IDB_OBM0_DSCP_MAP_PORT3m,
  19440         IDB_OBM1_DSCP_MAP_PORT0m, IDB_OBM1_DSCP_MAP_PORT1m,
  19441         IDB_OBM1_DSCP_MAP_PORT2m, IDB_OBM1_DSCP_MAP_PORT3m,
  19442         IDB_OBM2_DSCP_MAP_PORT0m, IDB_OBM2_DSCP_MAP_PORT1m,
  19443         IDB_OBM2_DSCP_MAP_PORT2m, IDB_OBM2_DSCP_MAP_PORT3m,
  19444         IDB_OBM3_DSCP_MAP_PORT0m, IDB_OBM3_DSCP_MAP_PORT1m,
  19445         IDB_OBM3_DSCP_MAP_PORT2m, IDB_OBM3_DSCP_MAP_PORT3m,
  19446         IDB_OBM4_DSCP_MAP_PORT0m, IDB_OBM4_DSCP_MAP_PORT1m,
  19447         IDB_OBM4_DSCP_MAP_PORT2m, IDB_OBM4_DSCP_MAP_PORT3m,
  19448         IDB_OBM5_DSCP_MAP_PORT0m, IDB_OBM5_DSCP_MAP_PORT1m,
  19449         IDB_OBM5_DSCP_MAP_PORT2m, IDB_OBM5_DSCP_MAP_PORT3m,
  19450         IDB_OBM6_DSCP_MAP_PORT0m, IDB_OBM6_DSCP_MAP_PORT1m,
  19451         IDB_OBM6_DSCP_MAP_PORT2m, IDB_OBM6_DSCP_MAP_PORT3m,
  19452         IDB_OBM7_DSCP_MAP_PORT0m, IDB_OBM7_DSCP_MAP_PORT1m,
  19453         IDB_OBM7_DSCP_MAP_PORT2m, IDB_OBM7_DSCP_MAP_PORT3m
  19454     };
  19455     static const soc_field_t offset_ob_prio[] = {
  19456         OFFSET0_OB_PRIORITYf, OFFSET1_OB_PRIORITYf, OFFSET2_OB_PRIORITYf,
  19457         OFFSET3_OB_PRIORITYf, OFFSET4_OB_PRIORITYf, OFFSET5_OB_PRIORITYf,
  19458         OFFSET6_OB_PRIORITYf, OFFSET7_OB_PRIORITYf, OFFSET8_OB_PRIORITYf,
  19459         OFFSET9_OB_PRIORITYf, OFFSET10_OB_PRIORITYf, OFFSET11_OB_PRIORITYf,
  19460         OFFSET12_OB_PRIORITYf, OFFSET13_OB_PRIORITYf, OFFSET14_OB_PRIORITYf,
  19461         OFFSET15_OB_PRIORITYf
  19462     };
  19463 
  19464     mem = obm_dscp_map_port_mem[(phy_port - 1) % _MN_PORTS_PER_PGW];
  19465     shadow_base_index = pgw * soc_mem_index_count(unit, mem);
  19466     for (i = 0; i < 4; i++) {
  19467          sal_memset(&entry[i], 0, sizeof(entry[i]));
  19468          SOC_IF_ERROR_RETURN(soc_monterey_shadow_entry_get(unit, mem,
  19469                              shadow_base_index + i, &entry[i]));
  19470     }
  19471 
  19472     for (i = 0; i < *array_count; i++) {
  19473          classifier_ptr = switch_obm_classifier + i;
  19474          code_point = classifier_ptr->obm_code_point;
  19475          if (code_point < BCM_OBM_DSCP_CHUNK_SIZE) {
  19476              ob_priority = soc_mem_field32_get(unit, mem, &entry[0],
  19477                                                offset_ob_prio[code_point]);
  19478          } else if (code_point < 2 * BCM_OBM_DSCP_CHUNK_SIZE) {
  19479              ob_priority = soc_mem_field32_get(unit, mem, &entry[1],
  19480                           offset_ob_prio[code_point % BCM_OBM_DSCP_CHUNK_SIZE]);
  19481          } else if (code_point < 3 * BCM_OBM_DSCP_CHUNK_SIZE) {
  19482              ob_priority = soc_mem_field32_get(unit, mem, &entry[2],
  19483                           offset_ob_prio[code_point % BCM_OBM_DSCP_CHUNK_SIZE]);
  19484          } else {
  19485              ob_priority = soc_mem_field32_get(unit, mem, &entry[3],
  19486                           offset_ob_prio[code_point % BCM_OBM_DSCP_CHUNK_SIZE]);
  19487         }
  19488         classifier_ptr->obm_priority = ob_priority;
  19489    }
  19490    return BCM_E_NONE;
  19491 
  19492 }
  19493 
  19494 /*
  19495  * Function:
  19496  *      bcm_mn_switch_obm_mpls_classifier_mapping_multi_set
  19497  * Purpose:
  19498  *      Set the mapping of bcm_obm_code_point to bcm_obm_priority
  19499  *      for multiple entries of mpls classifier type.
  19500  * Parameters:
  19501  *      unit                     - (IN) Unit number.
  19502  *      phy_port                 - (IN) Physical port.
  19503  *      pgw                      - (IN) PGW index (0 0r 1).
  19504  *      array_count              - (IN) Number of mpls entries.
  19505  *      switch_obm_classifier    - (IN) Array of mpls entries.
  19506  * Returns:
  19507  *      BCM_E_xxx
  19508  */
  19509 STATIC
  19510 int bcm_mn_switch_obm_mpls_classifier_mapping_multi_set(
  19511                  int unit,
  19512                  int phy_port,
  19513                  int pgw,
  19514                  int array_count,
  19515                  bcm_switch_obm_classifier_t *switch_obm_classifier)
  19516 {
  19517     int                             i, code_point, ob_priority;
  19518     idb_obm0_mpls_map_port0_entry_t entry;
  19519     bcm_switch_obm_classifier_t     *classifier_ptr = NULL;
  19520     soc_mem_t                       mem;
  19521 
  19522     static const soc_mem_t obm_mpls_map_port_mem[] = {
  19523         IDB_OBM0_MPLS_MAP_PORT0m, IDB_OBM0_MPLS_MAP_PORT1m,
  19524         IDB_OBM0_MPLS_MAP_PORT2m, IDB_OBM0_MPLS_MAP_PORT3m,
  19525         IDB_OBM1_MPLS_MAP_PORT0m, IDB_OBM1_MPLS_MAP_PORT1m,
  19526         IDB_OBM1_MPLS_MAP_PORT2m, IDB_OBM1_MPLS_MAP_PORT3m,
  19527         IDB_OBM2_MPLS_MAP_PORT0m, IDB_OBM2_MPLS_MAP_PORT1m,
  19528         IDB_OBM2_MPLS_MAP_PORT2m, IDB_OBM2_MPLS_MAP_PORT3m,
  19529         IDB_OBM3_MPLS_MAP_PORT0m, IDB_OBM3_MPLS_MAP_PORT1m,
  19530         IDB_OBM3_MPLS_MAP_PORT2m, IDB_OBM3_MPLS_MAP_PORT3m,
  19531         IDB_OBM4_MPLS_MAP_PORT0m, IDB_OBM4_MPLS_MAP_PORT1m,
  19532         IDB_OBM4_MPLS_MAP_PORT2m, IDB_OBM4_MPLS_MAP_PORT3m,
  19533         IDB_OBM5_MPLS_MAP_PORT0m, IDB_OBM5_MPLS_MAP_PORT1m,
  19534         IDB_OBM5_MPLS_MAP_PORT2m, IDB_OBM5_MPLS_MAP_PORT3m,
  19535         IDB_OBM6_MPLS_MAP_PORT0m, IDB_OBM6_MPLS_MAP_PORT1m,
  19536         IDB_OBM6_MPLS_MAP_PORT2m, IDB_OBM6_MPLS_MAP_PORT3m,
  19537         IDB_OBM7_MPLS_MAP_PORT0m, IDB_OBM7_MPLS_MAP_PORT1m,
  19538         IDB_OBM7_MPLS_MAP_PORT2m, IDB_OBM7_MPLS_MAP_PORT3m
  19539     };
  19540     static const soc_field_t offset_ob_prio[] = {
  19541         OFFSET0_OB_PRIORITYf, OFFSET1_OB_PRIORITYf,
  19542         OFFSET2_OB_PRIORITYf, OFFSET3_OB_PRIORITYf,
  19543         OFFSET4_OB_PRIORITYf, OFFSET5_OB_PRIORITYf,
  19544         OFFSET6_OB_PRIORITYf, OFFSET7_OB_PRIORITYf
  19545     };
  19546 
  19547     mem = obm_mpls_map_port_mem[(phy_port - 1) % _MN_PORTS_PER_PGW];
  19548     sal_memset(&entry, 0, sizeof(entry));
  19549     SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem,
  19550                                      PGW_CL_BLOCK(unit, pgw), 0, &entry));
  19551 
  19552     for (i = 0; i < array_count; i++) {
  19553          classifier_ptr = switch_obm_classifier + i;
  19554          code_point = classifier_ptr->obm_code_point;
  19555          ob_priority = classifier_ptr->obm_priority;
  19556          soc_mem_field32_set(unit, mem, &entry,
  19557                              offset_ob_prio[code_point % 8], ob_priority);
  19558     }
  19559     SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem,
  19560                                       PGW_CL_BLOCK(unit, pgw), 0, &entry));
  19561     return BCM_E_NONE;
  19562 }
  19563 
  19564 /*
  19565  * Function:
  19566  *      bcm_mn_switch_obm_mpls_classifier_mapping_multi_get
  19567  * Purpose:
  19568  *      Get the mapping of bcm_obm_code_point to bcm_obm_priority
  19569  *      for multiple entries of mpls classifier type.
  19570  * Parameters:
  19571  *      unit                     - (IN) Unit number.
  19572  *      phy_port                 - (IN) Physical port.
  19573  *      pgw                      - (IN) PGW index (0 0r 1).
  19574  *      array_max                - (IN) Maximum number of entries.
  19575  *      switch_obm_classifier    - (IN/OUT) Array of mpls entries.
  19576  *      array_count              - (OUT) Number of dscp entries.
  19577  * Returns:
  19578  *      BCM_E_xxx
  19579  */
  19580 
  19581 STATIC
  19582 int bcm_mn_switch_obm_mpls_classifier_mapping_multi_get(
  19583                  int unit,
  19584                  int phy_port,
  19585                  int pgw,
  19586                  int array_max,
  19587                  bcm_switch_obm_classifier_t *switch_obm_classifier,
  19588                  int *array_count)
  19589 {
  19590     int                             i, code_point, ob_priority;
  19591     idb_obm0_mpls_map_port0_entry_t entry;
  19592     bcm_switch_obm_classifier_t     *classifier_ptr = NULL;
  19593     soc_mem_t                       mem;
  19594 
  19595     static const soc_mem_t obm_mpls_map_port_mem[] = {
  19596         IDB_OBM0_MPLS_MAP_PORT0m, IDB_OBM0_MPLS_MAP_PORT1m,
  19597         IDB_OBM0_MPLS_MAP_PORT2m, IDB_OBM0_MPLS_MAP_PORT3m,
  19598         IDB_OBM1_MPLS_MAP_PORT0m, IDB_OBM1_MPLS_MAP_PORT1m,
  19599         IDB_OBM1_MPLS_MAP_PORT2m, IDB_OBM1_MPLS_MAP_PORT3m,
  19600         IDB_OBM2_MPLS_MAP_PORT0m, IDB_OBM2_MPLS_MAP_PORT1m,
  19601         IDB_OBM2_MPLS_MAP_PORT2m, IDB_OBM2_MPLS_MAP_PORT3m,
  19602         IDB_OBM3_MPLS_MAP_PORT0m, IDB_OBM3_MPLS_MAP_PORT1m,
  19603         IDB_OBM3_MPLS_MAP_PORT2m, IDB_OBM3_MPLS_MAP_PORT3m,
  19604         IDB_OBM4_MPLS_MAP_PORT0m, IDB_OBM4_MPLS_MAP_PORT1m,
  19605         IDB_OBM4_MPLS_MAP_PORT2m, IDB_OBM4_MPLS_MAP_PORT3m,
  19606         IDB_OBM5_MPLS_MAP_PORT0m, IDB_OBM5_MPLS_MAP_PORT1m,
  19607         IDB_OBM5_MPLS_MAP_PORT2m, IDB_OBM5_MPLS_MAP_PORT3m,
  19608         IDB_OBM6_MPLS_MAP_PORT0m, IDB_OBM6_MPLS_MAP_PORT1m,
  19609         IDB_OBM6_MPLS_MAP_PORT2m, IDB_OBM6_MPLS_MAP_PORT3m,
  19610         IDB_OBM7_MPLS_MAP_PORT0m, IDB_OBM7_MPLS_MAP_PORT1m,
  19611         IDB_OBM7_MPLS_MAP_PORT2m, IDB_OBM7_MPLS_MAP_PORT3m
  19612     };
  19613     static const soc_field_t offset_ob_prio[] = {
  19614         OFFSET0_OB_PRIORITYf, OFFSET1_OB_PRIORITYf,
  19615         OFFSET2_OB_PRIORITYf, OFFSET3_OB_PRIORITYf,
  19616         OFFSET4_OB_PRIORITYf, OFFSET5_OB_PRIORITYf,
  19617         OFFSET6_OB_PRIORITYf, OFFSET7_OB_PRIORITYf
  19618     };
  19619 
  19620     mem = obm_mpls_map_port_mem[(phy_port - 1) % _MN_PORTS_PER_PGW];
  19621     sal_memset(&entry, 0, sizeof(entry));
  19622     SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem,
  19623                                      PGW_CL_BLOCK(unit, pgw), 0, &entry));
  19624 
  19625     for (i = 0; i < *array_count; i++) {
  19626          classifier_ptr = switch_obm_classifier + i;
  19627          code_point = classifier_ptr->obm_code_point;
  19628          ob_priority = soc_mem_field32_get(unit, mem, &entry,
  19629                                            offset_ob_prio[code_point]);
  19630          classifier_ptr->obm_priority = ob_priority;
  19631     }
  19632     return BCM_E_NONE;
  19633 }
  19634 
  19635 /*
  19636  * Function:
  19637  *      bcm_mn_switch_obm_etag_classifier_mapping_multi_set
  19638  * Purpose:
  19639  *      Set the mapping of bcm_obm_code_point to bcm_obm_priority
  19640  *      for multiple entries of etag classifier type.
  19641  * Parameters:
  19642  *      unit                     - (IN) Unit number.
  19643  *      phy_port                 - (IN) Physical port.
  19644  *      pgw                      - (IN) PGW index (0 0r 1).
  19645  *      array_count              - (IN) Number of etag entries.
  19646  *      switch_obm_classifier    - (IN) Array of etag entries.
  19647  * Returns:
  19648  *      BCM_E_xxx
  19649  */
  19650 
  19651 STATIC
  19652 int bcm_mn_switch_obm_etag_classifier_mapping_multi_set(
  19653                  int unit,
  19654                  int phy_port,
  19655                  int pgw,
  19656                  int array_count,
  19657                  bcm_switch_obm_classifier_t *switch_obm_classifier)
  19658 {
  19659     int                             i, code_point, ob_priority;
  19660     idb_obm0_etag_map_port0_entry_t entry;
  19661     bcm_switch_obm_classifier_t     *classifier_ptr = NULL;
  19662     soc_mem_t                       mem;
  19663 
  19664     static const soc_mem_t obm_etag_map_port_mem[] = {
  19665         IDB_OBM0_ETAG_MAP_PORT0m, IDB_OBM0_ETAG_MAP_PORT1m,
  19666         IDB_OBM0_ETAG_MAP_PORT2m, IDB_OBM0_ETAG_MAP_PORT3m,
  19667         IDB_OBM1_ETAG_MAP_PORT0m, IDB_OBM1_ETAG_MAP_PORT1m,
  19668         IDB_OBM1_ETAG_MAP_PORT2m, IDB_OBM1_ETAG_MAP_PORT3m,
  19669         IDB_OBM2_ETAG_MAP_PORT0m, IDB_OBM2_ETAG_MAP_PORT1m,
  19670         IDB_OBM2_ETAG_MAP_PORT2m, IDB_OBM2_ETAG_MAP_PORT3m,
  19671         IDB_OBM3_ETAG_MAP_PORT0m, IDB_OBM3_ETAG_MAP_PORT1m,
  19672         IDB_OBM3_ETAG_MAP_PORT2m, IDB_OBM3_ETAG_MAP_PORT3m,
  19673         IDB_OBM4_ETAG_MAP_PORT0m, IDB_OBM4_ETAG_MAP_PORT1m,
  19674         IDB_OBM4_ETAG_MAP_PORT2m, IDB_OBM4_ETAG_MAP_PORT3m,
  19675         IDB_OBM5_ETAG_MAP_PORT0m, IDB_OBM5_ETAG_MAP_PORT1m,
  19676         IDB_OBM5_ETAG_MAP_PORT2m, IDB_OBM5_ETAG_MAP_PORT3m,
  19677         IDB_OBM6_ETAG_MAP_PORT0m, IDB_OBM6_ETAG_MAP_PORT1m,
  19678         IDB_OBM6_ETAG_MAP_PORT2m, IDB_OBM6_ETAG_MAP_PORT3m,
  19679         IDB_OBM7_ETAG_MAP_PORT0m, IDB_OBM7_ETAG_MAP_PORT1m,
  19680         IDB_OBM7_ETAG_MAP_PORT2m, IDB_OBM7_ETAG_MAP_PORT3m
  19681     };
  19682 
  19683     static const soc_field_t offset_ob_prio[] = {
  19684         OFFSET0_OB_PRIORITYf, OFFSET1_OB_PRIORITYf,
  19685         OFFSET2_OB_PRIORITYf, OFFSET3_OB_PRIORITYf,
  19686         OFFSET4_OB_PRIORITYf, OFFSET5_OB_PRIORITYf,
  19687         OFFSET6_OB_PRIORITYf, OFFSET7_OB_PRIORITYf
  19688     };
  19689 
  19690     mem = obm_etag_map_port_mem[(phy_port - 1) % _MN_PORTS_PER_PGW];
  19691     sal_memset(&entry, 0, sizeof(entry));
  19692     SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem,
  19693                                      PGW_CL_BLOCK(unit, pgw), 0, &entry));
  19694 
  19695     for (i = 0; i < array_count; i++) {
  19696          classifier_ptr = switch_obm_classifier + i;
  19697          code_point = classifier_ptr->obm_code_point;
  19698          ob_priority = classifier_ptr->obm_priority;
  19699          soc_mem_field32_set(unit, mem, &entry,
  19700                              offset_ob_prio[code_point], ob_priority);
  19701     }
  19702     SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem,
  19703                                       PGW_CL_BLOCK(unit, pgw), 0, &entry));
  19704     return BCM_E_NONE;
  19705 }
  19706 
  19707 /*
  19708  * Function:
  19709  *      bcm_mn_switch_obm_etag_classifier_mapping_multi_get
  19710  * Purpose:
  19711  *      Set the mapping of bcm_obm_code_point to bcm_obm_priority
  19712  *      for multiple entries of etag classifier type.
  19713  * Parameters:
  19714  *      unit                     - (IN) Unit number.
  19715  *      phy_port                 - (IN) Physical port.
  19716  *      pgw                      - (IN) PGW index (0 0r 1).
  19717  *      array_max                - (IN) Maximum number of entries.
  19718  *      switch_obm_classifier    - (IN/OUT) Array of etag entries.
  19719  *      array_count              - (OUT) Number of etag entries.
  19720  * Returns:
  19721  *      BCM_E_xxx
  19722  */
  19723 
  19724 STATIC
  19725 int bcm_mn_switch_obm_etag_classifier_mapping_multi_get(
  19726                  int unit,
  19727                  int phy_port,
  19728                  int pgw,
  19729                  int array_max,
  19730                  bcm_switch_obm_classifier_t *switch_obm_classifier,
  19731                  int *array_count)
  19732 {
  19733     int                             i, code_point, ob_priority;
  19734     idb_obm0_etag_map_port0_entry_t entry;
  19735     bcm_switch_obm_classifier_t     *classifier_ptr = NULL;
  19736     soc_mem_t                       mem;
  19737 
  19738     static const soc_mem_t obm_etag_map_port_mem[] = {
  19739         IDB_OBM0_ETAG_MAP_PORT0m, IDB_OBM0_ETAG_MAP_PORT1m,
  19740         IDB_OBM0_ETAG_MAP_PORT2m, IDB_OBM0_ETAG_MAP_PORT3m,
  19741         IDB_OBM1_ETAG_MAP_PORT0m, IDB_OBM1_ETAG_MAP_PORT1m,
  19742         IDB_OBM1_ETAG_MAP_PORT2m, IDB_OBM1_ETAG_MAP_PORT3m,
  19743         IDB_OBM2_ETAG_MAP_PORT0m, IDB_OBM2_ETAG_MAP_PORT1m,
  19744         IDB_OBM2_ETAG_MAP_PORT2m, IDB_OBM2_ETAG_MAP_PORT3m,
  19745         IDB_OBM3_ETAG_MAP_PORT0m, IDB_OBM3_ETAG_MAP_PORT1m,
  19746         IDB_OBM3_ETAG_MAP_PORT2m, IDB_OBM3_ETAG_MAP_PORT3m,
  19747         IDB_OBM4_ETAG_MAP_PORT0m, IDB_OBM4_ETAG_MAP_PORT1m,
  19748         IDB_OBM4_ETAG_MAP_PORT2m, IDB_OBM4_ETAG_MAP_PORT3m,
  19749         IDB_OBM5_ETAG_MAP_PORT0m, IDB_OBM5_ETAG_MAP_PORT1m,
  19750         IDB_OBM5_ETAG_MAP_PORT2m, IDB_OBM5_ETAG_MAP_PORT3m,
  19751         IDB_OBM6_ETAG_MAP_PORT0m, IDB_OBM6_ETAG_MAP_PORT1m,
  19752         IDB_OBM6_ETAG_MAP_PORT2m, IDB_OBM6_ETAG_MAP_PORT3m,
  19753         IDB_OBM7_ETAG_MAP_PORT0m, IDB_OBM7_ETAG_MAP_PORT1m,
  19754         IDB_OBM7_ETAG_MAP_PORT2m, IDB_OBM7_ETAG_MAP_PORT3m
  19755     };
  19756 
  19757     static const soc_field_t offset_ob_prio[] = {
  19758         OFFSET0_OB_PRIORITYf, OFFSET1_OB_PRIORITYf,
  19759         OFFSET2_OB_PRIORITYf, OFFSET3_OB_PRIORITYf,
  19760         OFFSET4_OB_PRIORITYf, OFFSET5_OB_PRIORITYf,
  19761         OFFSET6_OB_PRIORITYf, OFFSET7_OB_PRIORITYf
  19762     };
  19763 
  19764     mem = obm_etag_map_port_mem[(phy_port - 1) % _MN_PORTS_PER_PGW];
  19765     sal_memset(&entry, 0, sizeof(entry));
  19766     SOC_IF_ERROR_RETURN(soc_mem_read(unit,
  19767                                      mem, PGW_CL_BLOCK(unit, pgw), 0, &entry));
  19768 
  19769     for (i = 0; i < *array_count; i++) {
  19770          classifier_ptr = switch_obm_classifier + i;
  19771          code_point = classifier_ptr->obm_code_point;
  19772          ob_priority = soc_mem_field32_get(unit, mem, &entry,
  19773                                            offset_ob_prio[code_point]);
  19774          classifier_ptr->obm_priority = ob_priority;
  19775     }
  19776     return BCM_E_NONE;
  19777 }
  19778 
  19779 /*
  19780  * Function:
  19781  *      bcm_mn_switch_obm_vlan_classifier_mapping_multi_set
  19782  * Purpose:
  19783  *      Set the mapping of bcm_obm_code_point to bcm_obm_priority
  19784  *      for multiple entries of vlan classifier type.
  19785  * Parameters:
  19786  *      unit                     - (IN) Unit number.
  19787  *      phy_port                 - (IN) Physical port.
  19788  *      pgw                      - (IN) PGW index (0 0r 1).
  19789  *      array_count              - (IN) Number of vlan entries.
  19790  *      switch_obm_classifier    - (IN) Array of vlan entries.
  19791  * Returns:
  19792  *      BCM_E_xxx
  19793  */
  19794 
  19795 STATIC
  19796 int bcm_mn_switch_obm_vlan_classifier_mapping_multi_set(
  19797                  int unit,
  19798                  int phy_port,
  19799                  int pgw,
  19800                  int array_count,
  19801                  bcm_switch_obm_classifier_t *switch_obm_classifier)
  19802 {
  19803     int                            i, code_point, ob_priority;
  19804     idb_obm0_pri_map_port0_entry_t entry;
  19805     bcm_switch_obm_classifier_t    *classifier_ptr = NULL;
  19806     soc_mem_t                      mem;
  19807 
  19808     static const soc_mem_t obm_pri_map_port_mem[] = {
  19809         IDB_OBM0_PRI_MAP_PORT0m, IDB_OBM0_PRI_MAP_PORT1m,
  19810         IDB_OBM0_PRI_MAP_PORT2m, IDB_OBM0_PRI_MAP_PORT3m,
  19811         IDB_OBM1_PRI_MAP_PORT0m, IDB_OBM1_PRI_MAP_PORT1m,
  19812         IDB_OBM1_PRI_MAP_PORT2m, IDB_OBM1_PRI_MAP_PORT3m,
  19813         IDB_OBM2_PRI_MAP_PORT0m, IDB_OBM2_PRI_MAP_PORT1m,
  19814         IDB_OBM2_PRI_MAP_PORT2m, IDB_OBM2_PRI_MAP_PORT3m,
  19815         IDB_OBM3_PRI_MAP_PORT0m, IDB_OBM3_PRI_MAP_PORT1m,
  19816         IDB_OBM3_PRI_MAP_PORT2m, IDB_OBM3_PRI_MAP_PORT3m,
  19817         IDB_OBM4_PRI_MAP_PORT0m, IDB_OBM4_PRI_MAP_PORT1m,
  19818         IDB_OBM4_PRI_MAP_PORT2m, IDB_OBM4_PRI_MAP_PORT3m,
  19819         IDB_OBM5_PRI_MAP_PORT0m, IDB_OBM5_PRI_MAP_PORT1m,
  19820         IDB_OBM5_PRI_MAP_PORT2m, IDB_OBM5_PRI_MAP_PORT3m,
  19821         IDB_OBM6_PRI_MAP_PORT0m, IDB_OBM6_PRI_MAP_PORT1m,
  19822         IDB_OBM6_PRI_MAP_PORT2m, IDB_OBM6_PRI_MAP_PORT3m,
  19823         IDB_OBM7_PRI_MAP_PORT0m, IDB_OBM7_PRI_MAP_PORT1m,
  19824         IDB_OBM7_PRI_MAP_PORT2m, IDB_OBM7_PRI_MAP_PORT3m
  19825     };
  19826 
  19827     static const soc_field_t offset_ob_prio[] = {
  19828         OFFSET0_OB_PRIORITYf, OFFSET1_OB_PRIORITYf,
  19829         OFFSET2_OB_PRIORITYf, OFFSET3_OB_PRIORITYf,
  19830         OFFSET4_OB_PRIORITYf, OFFSET5_OB_PRIORITYf,
  19831         OFFSET6_OB_PRIORITYf, OFFSET7_OB_PRIORITYf
  19832     };
  19833 
  19834     mem = obm_pri_map_port_mem[(phy_port - 1) % _MN_PORTS_PER_PGW];
  19835     sal_memset(&entry, 0, sizeof(entry));
  19836     SOC_IF_ERROR_RETURN(soc_mem_read(unit,
  19837                                      mem, PGW_CL_BLOCK(unit, pgw), 0, &entry));
  19838 
  19839     for (i = 0; i < array_count; i++) {
  19840          classifier_ptr = switch_obm_classifier + i;
  19841          code_point = classifier_ptr->obm_code_point;
  19842          ob_priority = classifier_ptr->obm_priority;
  19843          soc_mem_field32_set(unit, mem, &entry,
  19844                              offset_ob_prio[code_point], ob_priority);
  19845     }
  19846     SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem,
  19847                                       PGW_CL_BLOCK(unit, pgw), 0, &entry));
  19848     return BCM_E_NONE;
  19849 }
  19850 
  19851 /*
  19852  * Function:
  19853  *      bcm_mn_switch_obm_vlan_classifier_mapping_multi_get
  19854  * Purpose:
  19855  *      Set the mapping of bcm_obm_code_point to bcm_obm_priority
  19856  *      for multiple entries of vlan classifier type.
  19857  * Parameters:
  19858  *      unit                     - (IN) Unit number.
  19859  *      phy_port                 - (IN) Physical port.
  19860  *      pgw                      - (IN) PGW index (0 0r 1).
  19861  *      array_max                - (IN) Maximum number of entries.
  19862  *      switch_obm_classifier    - (IN/OUT) Array of vlan entries.
  19863  *      array_count              - (OUT) Number of vlan entries.
  19864  * Returns:
  19865  *      BCM_E_xxx
  19866  */
  19867 STATIC
  19868 int bcm_mn_switch_obm_vlan_classifier_mapping_multi_get(
  19869                  int unit,
  19870                  int phy_port,
  19871                  int pgw,
  19872                  int array_max,
  19873                  bcm_switch_obm_classifier_t *switch_obm_classifier,
  19874                  int *array_count)
  19875 {
  19876     int                            i, code_point, ob_priority;
  19877     idb_obm0_pri_map_port0_entry_t entry;
  19878     bcm_switch_obm_classifier_t    *classifier_ptr = NULL;
  19879     soc_mem_t                      mem;
  19880 
  19881     static const soc_mem_t obm_pri_map_port_mem[] = {
  19882         IDB_OBM0_PRI_MAP_PORT0m, IDB_OBM0_PRI_MAP_PORT1m,
  19883         IDB_OBM0_PRI_MAP_PORT2m, IDB_OBM0_PRI_MAP_PORT3m,
  19884         IDB_OBM1_PRI_MAP_PORT0m, IDB_OBM1_PRI_MAP_PORT1m,
  19885         IDB_OBM1_PRI_MAP_PORT2m, IDB_OBM1_PRI_MAP_PORT3m,
  19886         IDB_OBM2_PRI_MAP_PORT0m, IDB_OBM2_PRI_MAP_PORT1m,
  19887         IDB_OBM2_PRI_MAP_PORT2m, IDB_OBM2_PRI_MAP_PORT3m,
  19888         IDB_OBM3_PRI_MAP_PORT0m, IDB_OBM3_PRI_MAP_PORT1m,
  19889         IDB_OBM3_PRI_MAP_PORT2m, IDB_OBM3_PRI_MAP_PORT3m,
  19890         IDB_OBM4_PRI_MAP_PORT0m, IDB_OBM4_PRI_MAP_PORT1m,
  19891         IDB_OBM4_PRI_MAP_PORT2m, IDB_OBM4_PRI_MAP_PORT3m,
  19892         IDB_OBM5_PRI_MAP_PORT0m, IDB_OBM5_PRI_MAP_PORT1m,
  19893         IDB_OBM5_PRI_MAP_PORT2m, IDB_OBM5_PRI_MAP_PORT3m,
  19894         IDB_OBM6_PRI_MAP_PORT0m, IDB_OBM6_PRI_MAP_PORT1m,
  19895         IDB_OBM6_PRI_MAP_PORT2m, IDB_OBM6_PRI_MAP_PORT3m,
  19896         IDB_OBM7_PRI_MAP_PORT0m, IDB_OBM7_PRI_MAP_PORT1m,
  19897         IDB_OBM7_PRI_MAP_PORT2m, IDB_OBM7_PRI_MAP_PORT3m
  19898     };
  19899 
  19900     static const soc_field_t offset_ob_prio[] = {
  19901         OFFSET0_OB_PRIORITYf, OFFSET1_OB_PRIORITYf,
  19902         OFFSET2_OB_PRIORITYf, OFFSET3_OB_PRIORITYf,
  19903         OFFSET4_OB_PRIORITYf, OFFSET5_OB_PRIORITYf,
  19904         OFFSET6_OB_PRIORITYf, OFFSET7_OB_PRIORITYf
  19905     };
  19906 
  19907     mem = obm_pri_map_port_mem[(phy_port - 1) % _MN_PORTS_PER_PGW];
  19908     sal_memset(&entry, 0, sizeof(entry));
  19909     SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem,
  19910                                      PGW_CL_BLOCK(unit, pgw), 0, &entry));
  19911 
  19912     for (i = 0; i < *array_count; i++) {
  19913          classifier_ptr = switch_obm_classifier + i;
  19914          code_point = classifier_ptr->obm_code_point;
  19915          ob_priority = soc_mem_field32_get(unit, mem, &entry,
  19916                                            offset_ob_prio[code_point]);
  19917          classifier_ptr->obm_priority = ob_priority;
  19918     }
  19919     return BCM_E_NONE;
  19920 }
  19921 
  19922 /*
  19923  * Function:
  19924  *      bcm_mn_switch_obm_higig2_classifier_mapping_multi_set
  19925  * Purpose:
  19926  *      Set the mapping of bcm_obm_code_point to bcm_obm_priority
  19927  *      for multiple entries of higig2 classifier type.
  19928  * Parameters:
  19929  *      unit                     - (IN) Unit number.
  19930  *      phy_port                 - (IN) Physical port.
  19931  *      pgw                      - (IN) PGW index (0 0r 1).
  19932  *      array_count              - (IN) Number of higig2 entries.
  19933  *      switch_obm_classifier    - (IN) Array of higig2 entries.
  19934  * Returns:
  19935  *      BCM_E_xxx
  19936  */
  19937 STATIC
  19938 int bcm_mn_switch_obm_higig2_classifier_mapping_multi_set(
  19939                  int unit,
  19940                  int phy_port,
  19941                  int pgw,
  19942                  int array_count,
  19943                  bcm_switch_obm_classifier_t *switch_obm_classifier)
  19944 {
  19945     int                            i, code_point, ob_priority;
  19946     idb_obm0_pri_map_port0_entry_t entry;
  19947     bcm_switch_obm_classifier_t    *classifier_ptr = NULL;
  19948     soc_mem_t                      mem;
  19949 
  19950     static const soc_mem_t obm_pri_map_port_mem[] = {
  19951         IDB_OBM0_PRI_MAP_PORT0m, IDB_OBM0_PRI_MAP_PORT1m,
  19952         IDB_OBM0_PRI_MAP_PORT2m, IDB_OBM0_PRI_MAP_PORT3m,
  19953         IDB_OBM1_PRI_MAP_PORT0m, IDB_OBM1_PRI_MAP_PORT1m,
  19954         IDB_OBM1_PRI_MAP_PORT2m, IDB_OBM1_PRI_MAP_PORT3m,
  19955         IDB_OBM2_PRI_MAP_PORT0m, IDB_OBM2_PRI_MAP_PORT1m,
  19956         IDB_OBM2_PRI_MAP_PORT2m, IDB_OBM2_PRI_MAP_PORT3m,
  19957         IDB_OBM3_PRI_MAP_PORT0m, IDB_OBM3_PRI_MAP_PORT1m,
  19958         IDB_OBM3_PRI_MAP_PORT2m, IDB_OBM3_PRI_MAP_PORT3m,
  19959         IDB_OBM4_PRI_MAP_PORT0m, IDB_OBM4_PRI_MAP_PORT1m,
  19960         IDB_OBM4_PRI_MAP_PORT2m, IDB_OBM4_PRI_MAP_PORT3m,
  19961         IDB_OBM5_PRI_MAP_PORT0m, IDB_OBM5_PRI_MAP_PORT1m,
  19962         IDB_OBM5_PRI_MAP_PORT2m, IDB_OBM5_PRI_MAP_PORT3m,
  19963         IDB_OBM6_PRI_MAP_PORT0m, IDB_OBM6_PRI_MAP_PORT1m,
  19964         IDB_OBM6_PRI_MAP_PORT2m, IDB_OBM6_PRI_MAP_PORT3m,
  19965         IDB_OBM7_PRI_MAP_PORT0m, IDB_OBM7_PRI_MAP_PORT1m,
  19966         IDB_OBM7_PRI_MAP_PORT2m, IDB_OBM7_PRI_MAP_PORT3m
  19967     };
  19968 
  19969     static const soc_field_t offset_ob_prio[] = {
  19970         OFFSET0_OB_PRIORITYf, OFFSET1_OB_PRIORITYf, OFFSET2_OB_PRIORITYf,
  19971         OFFSET3_OB_PRIORITYf, OFFSET4_OB_PRIORITYf, OFFSET5_OB_PRIORITYf,
  19972         OFFSET6_OB_PRIORITYf, OFFSET7_OB_PRIORITYf, OFFSET8_OB_PRIORITYf,
  19973         OFFSET9_OB_PRIORITYf, OFFSET10_OB_PRIORITYf, OFFSET11_OB_PRIORITYf,
  19974         OFFSET12_OB_PRIORITYf, OFFSET13_OB_PRIORITYf, OFFSET14_OB_PRIORITYf,
  19975         OFFSET15_OB_PRIORITYf
  19976     };
  19977 
  19978     mem = obm_pri_map_port_mem[(phy_port - 1) % _MN_PORTS_PER_PGW];
  19979     sal_memset(&entry, 0, sizeof(entry));
  19980     SOC_IF_ERROR_RETURN(soc_monterey_shadow_entry_get(unit, mem, pgw, &entry));
  19981 
  19982     for (i = 0; i < array_count; i++) {
  19983          classifier_ptr = switch_obm_classifier + i;
  19984          code_point = classifier_ptr->obm_code_point;
  19985          ob_priority = classifier_ptr->obm_priority;
  19986          soc_mem_field32_set(unit, mem, &entry,
  19987                              offset_ob_prio[code_point], ob_priority);
  19988     }
  19989     SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem,
  19990                                       PGW_CL_BLOCK(unit, pgw), 0, &entry));
  19991     SOC_IF_ERROR_RETURN(soc_monterey_shadow_entry_set(unit, mem, pgw, &entry));
  19992     return BCM_E_NONE;
  19993 }
  19994 
  19995 /*
  19996  * Function:
  19997  *      bcm_mn_switch_obm_higig2_classifier_mapping_multi_get
  19998  * Purpose:
  19999  *      Set the mapping of bcm_obm_code_point to bcm_obm_priority
  20000  *      for multiple entries of higig2 classifier type.
  20001  * Parameters:
  20002  *      unit                     - (IN) Unit number.
  20003  *      phy_port                 - (IN) Physical port.
  20004  *      pgw                      - (IN) PGW index (0 0r 1).
  20005  *      array_max                - (IN) Maximum number of entries.
  20006  *      switch_obm_classifier    - (IN/OUT) Array of higig2 entries.
  20007  *      array_count              - (OUT) Number of higig2 entries.
  20008  * Returns:
  20009  *      BCM_E_xxx
  20010  */
  20011 
  20012 STATIC
  20013 int bcm_mn_switch_obm_higig2_classifier_mapping_multi_get(
  20014                  int unit,
  20015                  int phy_port,
  20016                  int pgw,
  20017                  int array_max,
  20018                  bcm_switch_obm_classifier_t *switch_obm_classifier,
  20019                  int *array_count)
  20020 {
  20021     int                            i, code_point, ob_priority;
  20022     idb_obm0_pri_map_port0_entry_t entry;
  20023     bcm_switch_obm_classifier_t    *classifier_ptr = NULL;
  20024     soc_mem_t                      mem;
  20025 
  20026     static const soc_mem_t obm_pri_map_port_mem[] = {
  20027         IDB_OBM0_PRI_MAP_PORT0m, IDB_OBM0_PRI_MAP_PORT1m,
  20028         IDB_OBM0_PRI_MAP_PORT2m, IDB_OBM0_PRI_MAP_PORT3m,
  20029         IDB_OBM1_PRI_MAP_PORT0m, IDB_OBM1_PRI_MAP_PORT1m,
  20030         IDB_OBM1_PRI_MAP_PORT2m, IDB_OBM1_PRI_MAP_PORT3m,
  20031         IDB_OBM2_PRI_MAP_PORT0m, IDB_OBM2_PRI_MAP_PORT1m,
  20032         IDB_OBM2_PRI_MAP_PORT2m, IDB_OBM2_PRI_MAP_PORT3m,
  20033         IDB_OBM3_PRI_MAP_PORT0m, IDB_OBM3_PRI_MAP_PORT1m,
  20034         IDB_OBM3_PRI_MAP_PORT2m, IDB_OBM3_PRI_MAP_PORT3m,
  20035         IDB_OBM4_PRI_MAP_PORT0m, IDB_OBM4_PRI_MAP_PORT1m,
  20036         IDB_OBM4_PRI_MAP_PORT2m, IDB_OBM4_PRI_MAP_PORT3m,
  20037         IDB_OBM5_PRI_MAP_PORT0m, IDB_OBM5_PRI_MAP_PORT1m,
  20038         IDB_OBM5_PRI_MAP_PORT2m, IDB_OBM5_PRI_MAP_PORT3m,
  20039         IDB_OBM6_PRI_MAP_PORT0m, IDB_OBM6_PRI_MAP_PORT1m,
  20040         IDB_OBM6_PRI_MAP_PORT2m, IDB_OBM6_PRI_MAP_PORT3m,
  20041         IDB_OBM7_PRI_MAP_PORT0m, IDB_OBM7_PRI_MAP_PORT1m,
  20042         IDB_OBM7_PRI_MAP_PORT2m, IDB_OBM7_PRI_MAP_PORT3m
  20043     };
  20044 
  20045     static const soc_field_t offset_ob_prio[] = {
  20046         OFFSET0_OB_PRIORITYf, OFFSET1_OB_PRIORITYf, OFFSET2_OB_PRIORITYf,
  20047         OFFSET3_OB_PRIORITYf, OFFSET4_OB_PRIORITYf, OFFSET5_OB_PRIORITYf,
  20048         OFFSET6_OB_PRIORITYf, OFFSET7_OB_PRIORITYf, OFFSET8_OB_PRIORITYf,
  20049         OFFSET9_OB_PRIORITYf, OFFSET10_OB_PRIORITYf, OFFSET11_OB_PRIORITYf,
  20050         OFFSET12_OB_PRIORITYf, OFFSET13_OB_PRIORITYf, OFFSET14_OB_PRIORITYf,
  20051         OFFSET15_OB_PRIORITYf
  20052     };
  20053 
  20054     mem = obm_pri_map_port_mem[(phy_port - 1) % _MN_PORTS_PER_PGW];
  20055     sal_memset(&entry, 0, sizeof(entry));
  20056     SOC_IF_ERROR_RETURN(soc_monterey_shadow_entry_get(unit, mem, pgw, &entry));
  20057 
  20058     for (i = 0; i < *array_count; i++) {
  20059          classifier_ptr = switch_obm_classifier + i;
  20060          code_point = classifier_ptr->obm_code_point;
  20061          ob_priority = soc_mem_field32_get(unit, mem, &entry,
  20062                                            offset_ob_prio[code_point]);
  20063          classifier_ptr->obm_priority = ob_priority;
  20064     }
  20065     return BCM_E_NONE;
  20066 }
  20067 /*
  20068  * Function:
  20069  *      bcm_mn_switch_obm_field_classifier_mapping_multi_set
  20070  * Purpose:
  20071  *      Match based on destination_mac, destination_mac_mask,
  20072  *      ethertype and ethertype_mask and assign bcm_obm_priority.
  20073  *      for multiple entries of mpls classifier type.
  20074  * Parameters:
  20075  *      unit                     - (IN) Unit number.
  20076  *      phy_port                 - (IN) Physical port.
  20077  *      pgw                      - (IN) PGW index (0 0r 1).
  20078  *      array_count              - (IN) Number of field entries.
  20079  *      switch_obm_classifier    - (IN) Array of field entries.
  20080  * Returns:
  20081  *      BCM_E_xxx
  20082  */
  20083 STATIC
  20084 int bcm_mn_switch_obm_field_classifier_mapping_multi_set(
  20085                  int unit,
  20086                  int phy_port,
  20087                  int pgw,
  20088                  int array_count,
  20089                  bcm_switch_obm_classifier_t *switch_obm_classifier)
  20090 {
  20091     uint64                       rval64;
  20092     uint32                       rval_hi, rval_lo;
  20093     bcm_switch_obm_classifier_t  *classifier_ptr = NULL;
  20094     soc_reg_t                    reg;
  20095     int                          i, pgw_inst, enable = 0;
  20096 
  20097     static const soc_reg_t obm_proto_control0_regs[] = {
  20098         IDB_OBM0_PROTOCOL_CONTROL_0r, IDB_OBM1_PROTOCOL_CONTROL_0r,
  20099         IDB_OBM2_PROTOCOL_CONTROL_0r, IDB_OBM3_PROTOCOL_CONTROL_0r,
  20100         IDB_OBM4_PROTOCOL_CONTROL_0r, IDB_OBM5_PROTOCOL_CONTROL_0r,
  20101         IDB_OBM6_PROTOCOL_CONTROL_0r, IDB_OBM7_PROTOCOL_CONTROL_0r
  20102     };
  20103     static const soc_reg_t obm_proto_control1_regs[] = {
  20104         IDB_OBM0_PROTOCOL_CONTROL_1r, IDB_OBM1_PROTOCOL_CONTROL_1r,
  20105         IDB_OBM2_PROTOCOL_CONTROL_1r, IDB_OBM3_PROTOCOL_CONTROL_1r,
  20106         IDB_OBM4_PROTOCOL_CONTROL_1r, IDB_OBM5_PROTOCOL_CONTROL_1r,
  20107         IDB_OBM6_PROTOCOL_CONTROL_1r, IDB_OBM7_PROTOCOL_CONTROL_1r
  20108     };
  20109     static const soc_reg_t obm_proto_control2_regs[] = {
  20110         IDB_OBM0_PROTOCOL_CONTROL_2r, IDB_OBM1_PROTOCOL_CONTROL_2r,
  20111         IDB_OBM2_PROTOCOL_CONTROL_2r, IDB_OBM3_PROTOCOL_CONTROL_2r,
  20112         IDB_OBM4_PROTOCOL_CONTROL_2r, IDB_OBM5_PROTOCOL_CONTROL_2r,
  20113         IDB_OBM6_PROTOCOL_CONTROL_2r, IDB_OBM7_PROTOCOL_CONTROL_2r
  20114     };
  20115 
  20116     pgw_inst = (pgw | SOC_REG_ADDR_INSTANCE_MASK);
  20117 
  20118     for (i = 0; i < array_count; i++) {
  20119         classifier_ptr = switch_obm_classifier + i;
  20120 
  20121         reg = obm_proto_control0_regs[((phy_port - 1) % _MN_PORTS_PER_PGW) / 4];
  20122         COMPILER_64_ZERO(rval64);
  20123         COMPILER_64_TO_32_HI(rval_hi, rval64);
  20124         COMPILER_64_TO_32_LO(rval_lo, rval64);
  20125         rval_hi |= ((classifier_ptr->obm_destination_mac[0] & 0xff) << 8);
  20126         rval_hi |= (classifier_ptr->obm_destination_mac[1] & 0xff);
  20127         rval_lo |= ((classifier_ptr->obm_destination_mac[2] & 0xff) << 24);
  20128         rval_lo |= ((classifier_ptr->obm_destination_mac[3] & 0xff) << 16);
  20129         rval_lo |= ((classifier_ptr->obm_destination_mac[4] & 0xff) << 8);
  20130         rval_lo |= (classifier_ptr->obm_destination_mac[5] & 0xff);
  20131         COMPILER_64_SET(rval64, rval_hi, rval_lo);
  20132         SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg,
  20133                                         pgw_inst, i, rval64));
  20134 
  20135         reg = obm_proto_control1_regs[((phy_port - 1) % _MN_PORTS_PER_PGW) / 4];
  20136         COMPILER_64_ZERO(rval64);
  20137         COMPILER_64_TO_32_HI(rval_hi, rval64);
  20138         COMPILER_64_TO_32_LO(rval_lo, rval64);
  20139         rval_hi |= ((classifier_ptr->obm_destination_mac_mask[0] & 0xff) << 8);
  20140         rval_hi |= (classifier_ptr->obm_destination_mac_mask[1] & 0xff);
  20141         rval_lo |= ((classifier_ptr->obm_destination_mac_mask[2] & 0xff) << 24);
  20142         rval_lo |= ((classifier_ptr->obm_destination_mac_mask[3] & 0xff) << 16);
  20143         rval_lo |= ((classifier_ptr->obm_destination_mac_mask[4] & 0xff) << 8);
  20144         rval_lo |= (classifier_ptr->obm_destination_mac_mask[5] & 0xff);
  20145         COMPILER_64_SET(rval64, rval_hi, rval_lo);
  20146         SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg,
  20147                                         pgw_inst, i, rval64));
  20148         reg = obm_proto_control2_regs[((phy_port - 1) % _MN_PORTS_PER_PGW) / 4];
  20149         COMPILER_64_ZERO(rval64);
  20150         COMPILER_64_TO_32_HI(rval_hi, rval64);
  20151         COMPILER_64_TO_32_LO(rval_lo, rval64);
  20152         rval_lo |= (classifier_ptr->obm_ethertype & 0xffff);
  20153         rval_lo |= ((classifier_ptr->obm_ethertype_mask & 0xffff) << 16);
  20154         rval_hi |= (classifier_ptr->obm_priority & 0x7);
  20155 
  20156         /* check if configuration is to enable or disable */
  20157         enable |= classifier_ptr->obm_destination_mac[0];
  20158         enable |= classifier_ptr->obm_destination_mac[1];
  20159         enable |= classifier_ptr->obm_destination_mac[2];
  20160         enable |= classifier_ptr->obm_destination_mac[3];
  20161         enable |= classifier_ptr->obm_destination_mac[4];
  20162         enable |= classifier_ptr->obm_destination_mac[5];
  20163         enable |= classifier_ptr->obm_destination_mac_mask[0];
  20164         enable |= classifier_ptr->obm_destination_mac_mask[1];
  20165         enable |= classifier_ptr->obm_destination_mac_mask[2];
  20166         enable |= classifier_ptr->obm_destination_mac_mask[3];
  20167         enable |= classifier_ptr->obm_destination_mac_mask[4];
  20168         enable |= classifier_ptr->obm_destination_mac_mask[5];
  20169         enable |= classifier_ptr->obm_ethertype;
  20170         enable |= classifier_ptr->obm_ethertype_mask;
  20171         enable |= classifier_ptr->obm_priority;
  20172 
  20173         rval_hi |= ((enable ? 1 : 0) << 3);
  20174         COMPILER_64_SET(rval64, rval_hi, rval_lo);
  20175         SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg,
  20176                                         pgw_inst, i, rval64));
  20177    }
  20178    return BCM_E_NONE;
  20179 }
  20180 
  20181 /*
  20182  * Function:
  20183  *      bcm_mn_switch_obm_field_classifier_mapping_multi_get
  20184  * Purpose:
  20185  *      Get the mapping of bcm_obm_priority for a given
  20186  *      destination_mac, destination_mac_mask, ethertype and
  20187  *      ethertype mask for multiple entries of field classifier type.
  20188  * Parameters:
  20189  *      unit                     - (IN) Unit number.
  20190  *      phy_port                 - (IN) Physical port.
  20191  *      pgw                      - (IN) PGW index (0 0r 1).
  20192  *      array_max                - (IN) Maximum number of entries.
  20193  *      switch_obm_classifier    - (IN/OUT) Array of field entries.
  20194  *      array_count              - (OUT) Number of field entries.
  20195  * Returns:
  20196  *      BCM_E_xxx
  20197  */
  20198 
  20199 STATIC
  20200 int bcm_mn_switch_obm_field_classifier_mapping_multi_get(
  20201                  int unit,
  20202                  int phy_port,
  20203                  int pgw,
  20204                  int array_max,
  20205                  bcm_switch_obm_classifier_t *switch_obm_classifier,
  20206                  int *array_count)
  20207 {
  20208     uint64                       rval64;
  20209     uint32                       rval_hi, rval_lo;
  20210     bcm_switch_obm_classifier_t  *classifier_ptr = NULL;
  20211     soc_reg_t                    reg;
  20212     int                          i, pgw_inst;
  20213 
  20214     static const soc_reg_t obm_proto_control0_regs[] = {
  20215         IDB_OBM0_PROTOCOL_CONTROL_0r, IDB_OBM1_PROTOCOL_CONTROL_0r,
  20216         IDB_OBM2_PROTOCOL_CONTROL_0r, IDB_OBM3_PROTOCOL_CONTROL_0r,
  20217         IDB_OBM4_PROTOCOL_CONTROL_0r, IDB_OBM5_PROTOCOL_CONTROL_0r,
  20218         IDB_OBM6_PROTOCOL_CONTROL_0r, IDB_OBM7_PROTOCOL_CONTROL_0r
  20219     };
  20220     static const soc_reg_t obm_proto_control1_regs[] = {
  20221         IDB_OBM0_PROTOCOL_CONTROL_1r, IDB_OBM1_PROTOCOL_CONTROL_1r,
  20222         IDB_OBM2_PROTOCOL_CONTROL_1r, IDB_OBM3_PROTOCOL_CONTROL_1r,
  20223         IDB_OBM4_PROTOCOL_CONTROL_1r, IDB_OBM5_PROTOCOL_CONTROL_1r,
  20224         IDB_OBM6_PROTOCOL_CONTROL_1r, IDB_OBM7_PROTOCOL_CONTROL_1r
  20225     };
  20226     static const soc_reg_t obm_proto_control2_regs[] = {
  20227         IDB_OBM0_PROTOCOL_CONTROL_2r, IDB_OBM1_PROTOCOL_CONTROL_2r,
  20228         IDB_OBM2_PROTOCOL_CONTROL_2r, IDB_OBM3_PROTOCOL_CONTROL_2r,
  20229         IDB_OBM4_PROTOCOL_CONTROL_2r, IDB_OBM5_PROTOCOL_CONTROL_2r,
  20230         IDB_OBM6_PROTOCOL_CONTROL_2r, IDB_OBM7_PROTOCOL_CONTROL_2r
  20231     };
  20232 
  20233     pgw_inst = (pgw | SOC_REG_ADDR_INSTANCE_MASK);
  20234 
  20235     /* Do validation of params */
  20236     if (array_max > BCM_OBM_CLASSIFIER_NUM_ENTRY_FIELD) {
  20237         *array_count = BCM_OBM_CLASSIFIER_NUM_ENTRY_FIELD;
  20238     } else {
  20239         *array_count = array_max;
  20240     }
  20241 
  20242     for (i = 0; i < *array_count; i++) {
  20243         classifier_ptr = switch_obm_classifier + i;
  20244 
  20245         reg = obm_proto_control0_regs[((phy_port - 1) % _MN_PORTS_PER_PGW) / 4];
  20246         COMPILER_64_ZERO(rval64);
  20247         SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg,
  20248                                         pgw_inst, i, &rval64));
  20249         COMPILER_64_TO_32_HI(rval_hi, rval64);
  20250         COMPILER_64_TO_32_LO(rval_lo, rval64);
  20251         classifier_ptr->obm_destination_mac[0] = (rval_hi >> 8) & 0xff;
  20252         classifier_ptr->obm_destination_mac[1] = rval_hi & 0xff;
  20253         classifier_ptr->obm_destination_mac[2] = (rval_lo >> 24) & 0xff;
  20254         classifier_ptr->obm_destination_mac[3] = (rval_lo >> 16) & 0xff;
  20255         classifier_ptr->obm_destination_mac[4] = (rval_lo >> 8) & 0xff;
  20256         classifier_ptr->obm_destination_mac[5] = rval_lo & 0xff;
  20257 
  20258         reg = obm_proto_control1_regs[((phy_port - 1) % _MN_PORTS_PER_PGW) / 4];
  20259         COMPILER_64_ZERO(rval64);
  20260         SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg,
  20261                                         pgw_inst, i, &rval64));
  20262         COMPILER_64_TO_32_HI(rval_hi, rval64);
  20263         COMPILER_64_TO_32_LO(rval_lo, rval64);
  20264         classifier_ptr->obm_destination_mac_mask[0] = (rval_hi >> 8) & 0xff;
  20265         classifier_ptr->obm_destination_mac_mask[1] = rval_hi & 0xff;
  20266         classifier_ptr->obm_destination_mac_mask[2] = (rval_lo >> 24) & 0xff;
  20267         classifier_ptr->obm_destination_mac_mask[3] = (rval_lo >> 16) & 0xff;
  20268         classifier_ptr->obm_destination_mac_mask[4] = (rval_lo >> 8) & 0xff;
  20269         classifier_ptr->obm_destination_mac_mask[5] = rval_lo & 0xff;
  20270 
  20271         reg = obm_proto_control2_regs[((phy_port - 1) % _MN_PORTS_PER_PGW) / 4];
  20272         COMPILER_64_ZERO(rval64);
  20273         SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg,
  20274                                         pgw_inst, i, &rval64));
  20275         COMPILER_64_TO_32_HI(rval_hi, rval64);
  20276         COMPILER_64_TO_32_LO(rval_lo, rval64);
  20277         classifier_ptr->obm_ethertype = rval_lo & 0xffff;
  20278         classifier_ptr->obm_ethertype_mask = (rval_lo >>16) & 0xffff;
  20279         classifier_ptr->obm_priority = rval_hi & 0x7;
  20280    }
  20281    return BCM_E_NONE;
  20282 }
  20283 
  20284 /*
  20285  * Function:
  20286  *      bcm_mn_switch_obm_classifier_validate
  20287  * Purpose:
  20288  *      Internal function for validation of config params.
  20289  * Parameters:
  20290  *      unit                      - (IN) Unit number.
  20291  *      port                      - (IN) phyical port.
  20292  *      switch_obm_classifier_type- (IN) type of switch_obm_classifier.
  20293  *      array_count               - (IN) Number of elements in switch_obm_classifier.
  20294  *      switch_obm_classifier     - (IN) Array of bcm_switch_obm_classifier_t.
  20295  * Returns:
  20296  *      BCM_E_xxx
  20297  */
  20298 
  20299 STATIC
  20300 int bcm_mn_switch_obm_classifier_validate(
  20301     int unit,
  20302     bcm_port_t port,
  20303     bcm_switch_obm_classifier_type_t switch_obm_classifier_type,
  20304     int *array_count,
  20305     bcm_switch_obm_classifier_t *switch_obm_classifier,
  20306     int set)
  20307 {
  20308     soc_pbmp_t                   pbmp_xport_roe_backplane;
  20309     soc_pbmp_t                   pbmp_xport_roe_mcu;
  20310     int                          i, max_count;
  20311     bcm_switch_obm_classifier_t  *classifier_ptr = NULL;
  20312 
  20313     SOC_PBMP_CLEAR(pbmp_xport_roe_backplane);
  20314     SOC_PBMP_CLEAR(pbmp_xport_roe_mcu);
  20315 
  20316     pbmp_xport_roe_backplane = soc_property_get_pbmp_default(unit,
  20317                                spn_PBMP_XPORT_ROE_BACKPLANE,
  20318                                pbmp_xport_roe_backplane);
  20319     pbmp_xport_roe_mcu = soc_property_get_pbmp_default(unit,
  20320                          spn_PBMP_XPORT_ROE_MCU,
  20321                          pbmp_xport_roe_mcu);
  20322 
  20323     if ((port <= 0) || (port > 64)) {
  20324         LOG_ERROR(BSL_LS_BCM_COMMON,
  20325                  (BSL_META_U(unit,
  20326                  "ERROR: Invalid port %d\n"), port));
  20327         return BCM_E_PORT;
  20328     }
  20329 
  20330     if (IS_HG_PORT(unit, port)) {
  20331         if (switch_obm_classifier_type == bcmSwitchObmClassifierVlan) {
  20332             LOG_ERROR(BSL_LS_BCM_COMMON,
  20333                      (BSL_META_U(unit,
  20334                      "ERROR: OBM Vlan classifier not allowed on Higig"
  20335                      " port %d\n"), port));
  20336             return BCM_E_PARAM;
  20337         }
  20338     } else {
  20339         if (switch_obm_classifier_type == bcmSwitchObmClassifierHigig2) {
  20340             LOG_ERROR(BSL_LS_BCM_COMMON,
  20341                      (BSL_META_U(unit,
  20342                      "ERROR: OBM Higig2 classifier not allowed on non Higig"
  20343                      " port %d\n"), port));
  20344             return BCM_E_PARAM;
  20345         }
  20346     }
  20347     switch (switch_obm_classifier_type) {
  20348         case bcmSwitchObmClassifierDscp:
  20349             max_count = BCM_OBM_CLASSIFIER_NUM_ENTRY_DSCP;
  20350             break;
  20351         case bcmSwitchObmClassifierMpls:
  20352             max_count = BCM_OBM_CLASSIFIER_NUM_ENTRY_MPLS;
  20353             break;
  20354         case bcmSwitchObmClassifierEtag:
  20355             max_count = BCM_OBM_CLASSIFIER_NUM_ENTRY_ETAG;
  20356             break;
  20357         case bcmSwitchObmClassifierVlan:
  20358             max_count = BCM_OBM_CLASSIFIER_NUM_ENTRY_VLAN;
  20359             break;
  20360         case bcmSwitchObmClassifierHigig2:
  20361             max_count = BCM_OBM_CLASSIFIER_NUM_ENTRY_HIGIG2;
  20362             break;
  20363         case bcmSwitchObmClassifierField:
  20364             max_count = BCM_OBM_CLASSIFIER_NUM_ENTRY_FIELD;
  20365             break;
  20366         default:
  20367             LOG_ERROR(BSL_LS_BCM_COMMON,
  20368                      (BSL_META_U(unit,
  20369                      "ERROR: switch_obm_classifier_type is not correct on"
  20370                      " port %d\n"), port));
  20371             return BCM_E_PARAM;
  20372     }
  20373     /* For get API array count may be more than max_count */
  20374     if (*array_count > max_count) {
  20375         if (set) {
  20376             return BCM_E_PARAM;
  20377         } else {
  20378             *array_count = max_count;
  20379         }
  20380     }
  20381     for (i = 0; i < *array_count; i++) {
  20382          classifier_ptr = switch_obm_classifier + i;
  20383          if (switch_obm_classifier_type != bcmSwitchObmClassifierField) {
  20384              if (classifier_ptr->obm_code_point >= max_count) {
  20385                  LOG_ERROR(BSL_LS_BCM_COMMON,
  20386                           (BSL_META_U(unit,
  20387                           "ERROR: Invalid obm_code_point configured on"
  20388                           " port %d\n"), port));
  20389                  return BCM_E_PARAM;
  20390              }
  20391          }
  20392          if (set) {
  20393              if (classifier_ptr->obm_priority > BCM_OBM_PRIORITY_MAX) {
  20394                  LOG_ERROR(BSL_LS_BCM_COMMON,
  20395                           (BSL_META_U(unit,
  20396                           "ERROR: Invalid obm_priority configured on"
  20397                           " port %d\n"), port));
  20398                  return BCM_E_PARAM;
  20399              }
  20400              if (SOC_PBMP_MEMBER(pbmp_xport_roe_backplane, port) &&
  20401                  ((classifier_ptr->obm_priority ==
  20402                  BCM_SWITCH_OBM_PRIORITY_LOSSLESS0) ||
  20403                  (classifier_ptr->obm_priority ==
  20404                  BCM_SWITCH_OBM_PRIORITY_LOSSLESS1))) {
  20405                  LOG_ERROR(BSL_LS_BCM_COMMON,
  20406                           (BSL_META_U(unit,
  20407                           "ERROR: Lossless obm_priority configured on"
  20408                           " port %d\n"), port));
  20409                           return BCM_E_PARAM;
  20410              } else if (SOC_PBMP_MEMBER(pbmp_xport_roe_mcu, port) &&
  20411                  (classifier_ptr->obm_priority ==
  20412                  BCM_SWITCH_OBM_PRIORITY_EXPRESS)) {
  20413                  LOG_ERROR(BSL_LS_BCM_COMMON,
  20414                           (BSL_META_U(unit,
  20415                           "ERROR: Express obm_priority not allowed on"
  20416                           " port %d\n"), port));
  20417                           return BCM_E_PARAM;
  20418              }
  20419         }
  20420     }
  20421     return BCM_E_NONE;
  20422 }
  20423 /*
  20424  * Function:
  20425  *      bcm_mn_switch_obm_classifier_mapping_multi_set
  20426  * Purpose:
  20427  *      Set the mapping of bcm_obm_code_point to bcm_obm_priority
  20428  *      for multiple entries of same type of classifier.  Maximum
  20429  *      number of entries to be programmed are different depending
  20430  *      type of classifier. For type bcmSwitchObmClassifierField
  20431  *      bcm_obm_code_point will not be used and mapping will happen
  20432  *      based on destination_mac/mask and ethertype/mask.
  20433  * Parameters:
  20434  *      unit                       - (IN) Unit number.
  20435  *      gport                      - (IN) gport for a given port.
  20436  *      switch_obm_classifier_type - (IN) type of switch_obm_classifier.
  20437  *      array_count                - (IN) Number of elements in switch_obm_classifier.
  20438  *      switch_obm_classifier      - (IN) Array of bcm_switch_obm_classifier_t.
  20439  * Returns:
  20440  *      BCM_E_xxx
  20441  */
  20442 
  20443 int
  20444 bcm_mn_switch_obm_classifier_mapping_multi_set(
  20445     int unit,
  20446     bcm_gport_t gport,
  20447     bcm_switch_obm_classifier_type_t switch_obm_classifier_type,
  20448     int array_count,
  20449     bcm_switch_obm_classifier_t  *switch_obm_classifier)
  20450 {
  20451     soc_info_t *si;
  20452     int pgw;
  20453     int phy_port;
  20454     bcm_port_t port;
  20455 
  20456 
  20457     si = &SOC_INFO(unit);
  20458     BCM_IF_ERROR_RETURN(bcm_esw_port_local_get(unit, gport, &port));
  20459     phy_port = si->port_l2p_mapping[port];
  20460     pgw = si->port_group[port];
  20461 
  20462     /* Validate port and classifier compatibility */
  20463     BCM_IF_ERROR_RETURN(
  20464        bcm_mn_switch_obm_classifier_validate(unit,
  20465                                              port,
  20466                                              switch_obm_classifier_type,
  20467                                              &array_count,
  20468                                              switch_obm_classifier,
  20469                                              1));
  20470 
  20471     switch (switch_obm_classifier_type) {
  20472         case bcmSwitchObmClassifierDscp:
  20473             BCM_IF_ERROR_RETURN(
  20474             bcm_mn_switch_obm_dscp_classifier_mapping_multi_set(
  20475                                              unit,
  20476                                              phy_port,
  20477                                              pgw,
  20478                                              array_count,
  20479                                              switch_obm_classifier));
  20480             break;
  20481         case bcmSwitchObmClassifierMpls:
  20482             BCM_IF_ERROR_RETURN(
  20483             bcm_mn_switch_obm_mpls_classifier_mapping_multi_set(
  20484                                              unit,
  20485                                              phy_port,
  20486                                              pgw,
  20487                                              array_count,
  20488                                              switch_obm_classifier));
  20489             break;
  20490         case bcmSwitchObmClassifierEtag:
  20491             BCM_IF_ERROR_RETURN(
  20492             bcm_mn_switch_obm_etag_classifier_mapping_multi_set(
  20493                                              unit,
  20494                                              phy_port,
  20495                                              pgw,
  20496                                              array_count,
  20497                                              switch_obm_classifier));
  20498             break;
  20499         case bcmSwitchObmClassifierVlan:
  20500             BCM_IF_ERROR_RETURN(
  20501             bcm_mn_switch_obm_vlan_classifier_mapping_multi_set(
  20502                                              unit,
  20503                                              phy_port,
  20504                                              pgw,
  20505                                              array_count,
  20506                                              switch_obm_classifier));
  20507             break;
  20508         case bcmSwitchObmClassifierHigig2:
  20509             BCM_IF_ERROR_RETURN(
  20510             bcm_mn_switch_obm_higig2_classifier_mapping_multi_set(
  20511                                               unit,
  20512                                               phy_port,
  20513                                               pgw,
  20514                                               array_count,
  20515                                               switch_obm_classifier));
  20516             break;
  20517         case bcmSwitchObmClassifierField:
  20518             BCM_IF_ERROR_RETURN(
  20519             bcm_mn_switch_obm_field_classifier_mapping_multi_set(
  20520                                               unit,
  20521                                               phy_port,
  20522                                               pgw,
  20523                                               array_count,
  20524                                               switch_obm_classifier));
  20525             break;
  20526 
  20527         default:
  20528             return BCM_E_PARAM;
  20529     }
  20530     return BCM_E_NONE;
  20531 }
  20532 
  20533 /*
  20534  * Function:
  20535  *      bcm_mn_switch_obm_classifier_mapping_multi_get
  20536  * Purpose:
  20537  *      Get the mapping of bcm_obm_code_point to bcm_obm_priority
  20538  *      for multiple entries of same type of classifier.  Maximum
  20539  *      number of entries to be programmed are different depending
  20540  *      type of classifier. For type bcmSwitchObmClassifierField
  20541  *      bcm_obm_code_point will not be used and mapping will happen
  20542  *      based on destination_mac/mask and ethertype/mask.
  20543  * Parameters:
  20544  *      unit                       - (IN) Unit number.
  20545  *      gport                      - (IN) gport for a given port.
  20546  *      switch_obm_classifier_type - (IN) type of switch_obm_classifier.
  20547  *      array_max                  - (IN) Maximum number of elements in switch_obm_classifier.
  20548  *      switch_obm_classifier      - (IN/OUT) Array of bcm_switch_obm_classifier_t.
  20549  *      array_count                - (OUT) Number of elements in switch_obm_classifier.
  20550  * Returns:
  20551  *      BCM_E_xxx
  20552  */
  20553 
  20554 int
  20555 bcm_mn_switch_obm_classifier_mapping_multi_get(
  20556     int unit,
  20557     bcm_gport_t gport,
  20558     bcm_switch_obm_classifier_type_t switch_obm_classifier_type,
  20559     int array_max,
  20560     bcm_switch_obm_classifier_t    *switch_obm_classifier,
  20561     int *array_count)
  20562 
  20563 {
  20564     soc_info_t *si;
  20565     int pgw;
  20566     int phy_port;
  20567     bcm_port_t port;
  20568 
  20569     si = &SOC_INFO(unit);
  20570     BCM_IF_ERROR_RETURN(bcm_esw_port_local_get(unit, gport, &port));
  20571     phy_port = si->port_l2p_mapping[port];
  20572     pgw = si->port_group[port];
  20573 
  20574     /* Validate port and classifier compatibility */
  20575     *array_count = array_max;
  20576     BCM_IF_ERROR_RETURN(
  20577        bcm_mn_switch_obm_classifier_validate(unit,
  20578                                              port,
  20579                                              switch_obm_classifier_type,
  20580                                              array_count,
  20581                                              switch_obm_classifier,
  20582                                              0));
  20583     switch (switch_obm_classifier_type) {
  20584         case bcmSwitchObmClassifierDscp:
  20585             BCM_IF_ERROR_RETURN(
  20586             bcm_mn_switch_obm_dscp_classifier_mapping_multi_get(
  20587                                              unit,
  20588                                              phy_port,
  20589                                              pgw,
  20590                                              array_max,
  20591                                              switch_obm_classifier,
  20592                                              array_count));
  20593             break;
  20594         case bcmSwitchObmClassifierMpls:
  20595             BCM_IF_ERROR_RETURN(
  20596             bcm_mn_switch_obm_mpls_classifier_mapping_multi_get(
  20597                                              unit,
  20598                                              phy_port,
  20599                                              pgw,
  20600                                              array_max,
  20601                                              switch_obm_classifier,
  20602                                              array_count));
  20603             break;
  20604         case bcmSwitchObmClassifierEtag:
  20605             BCM_IF_ERROR_RETURN(
  20606             bcm_mn_switch_obm_etag_classifier_mapping_multi_get(
  20607                                              unit,
  20608                                              phy_port,
  20609                                              pgw,
  20610                                              array_max,
  20611                                              switch_obm_classifier,
  20612                                              array_count));
  20613             break;
  20614         case bcmSwitchObmClassifierVlan:
  20615             BCM_IF_ERROR_RETURN(
  20616             bcm_mn_switch_obm_vlan_classifier_mapping_multi_get(
  20617                                              unit,
  20618                                              phy_port,
  20619                                              pgw,
  20620                                              array_max,
  20621                                              switch_obm_classifier,
  20622                                              array_count));
  20623             break;
  20624         case bcmSwitchObmClassifierHigig2:
  20625             BCM_IF_ERROR_RETURN(
  20626             bcm_mn_switch_obm_higig2_classifier_mapping_multi_get(
  20627                                                unit,
  20628                                                phy_port,
  20629                                                pgw,
  20630                                                array_max,
  20631                                                switch_obm_classifier,
  20632                                                array_count));
  20633             break;
  20634         case bcmSwitchObmClassifierField:
  20635             BCM_IF_ERROR_RETURN(
  20636             bcm_mn_switch_obm_field_classifier_mapping_multi_get(
  20637                                               unit,
  20638                                               phy_port,
  20639                                               pgw,
  20640                                               array_max,
  20641                                               switch_obm_classifier,
  20642                                               array_count));
  20643             break;
  20644 
  20645         default:
  20646             return BCM_E_PARAM;
  20647     }
  20648     return BCM_E_NONE;
  20649 }
  20650 /*
  20651  * Function:
  20652  *      bcm_mn_obm_classifier_port_control_set
  20653  * Description:
  20654  *      Internal function to Enable/Disable specified
  20655  *      OBM port feature and congigure ethertype.
  20656  * Parameters:
  20657  *      unit - Device number
  20658  *      port - Port number
  20659  *      type - Enum value of the OBM feature
  20660  *      value - value to be set
  20661  * Return Value:
  20662  *      BCM_E_XXXX
  20663  */
  20664 int
  20665 bcm_mn_obm_classifier_port_control_set(int unit,
  20666                                        bcm_port_t port,
  20667                                        bcm_port_control_t type,
  20668                                        int value)
  20669 {
  20670     soc_info_t *si;
  20671     int pgw, pgw_inst, subport, obm;
  20672     int phy_port;
  20673     soc_reg_t  reg;
  20674     soc_field_t field;
  20675     int vntag = 0, port_control = 0, val, class_select = 0;
  20676     uint32 rval32;
  20677     uint64 rval64;
  20678 
  20679     static const soc_reg_t obm_port_config_regs[] = {
  20680         IDB_OBM0_PORT_CONFIGr, IDB_OBM1_PORT_CONFIGr,
  20681         IDB_OBM2_PORT_CONFIGr, IDB_OBM3_PORT_CONFIGr,
  20682         IDB_OBM4_PORT_CONFIGr, IDB_OBM5_PORT_CONFIGr,
  20683         IDB_OBM6_PORT_CONFIGr, IDB_OBM7_PORT_CONFIGr
  20684     };
  20685 
  20686     static const soc_reg_t obm_niv_ethertype_config_regs[] = {
  20687         IDB_OBM0_NIV_ETHERTYPEr, IDB_OBM1_NIV_ETHERTYPEr,
  20688         IDB_OBM2_NIV_ETHERTYPEr, IDB_OBM3_NIV_ETHERTYPEr,
  20689         IDB_OBM4_NIV_ETHERTYPEr, IDB_OBM5_NIV_ETHERTYPEr,
  20690         IDB_OBM6_NIV_ETHERTYPEr, IDB_OBM7_NIV_ETHERTYPEr
  20691     };
  20692 
  20693     static const soc_reg_t obm_pe_ethertype_config_regs[] = {
  20694         IDB_OBM0_PE_ETHERTYPEr, IDB_OBM1_PE_ETHERTYPEr,
  20695         IDB_OBM2_PE_ETHERTYPEr, IDB_OBM3_PE_ETHERTYPEr,
  20696         IDB_OBM4_PE_ETHERTYPEr, IDB_OBM5_PE_ETHERTYPEr,
  20697         IDB_OBM6_PE_ETHERTYPEr, IDB_OBM7_PE_ETHERTYPEr
  20698     };
  20699 
  20700     si = &SOC_INFO(unit);
  20701     /* Add check on ports */
  20702     obm = si->port_serdes[port];
  20703     obm %= _MN_TSCS_PER_PGW;
  20704     phy_port = si->port_l2p_mapping[port];
  20705 
  20706     if (IS_CPU_PORT(unit, port) || IS_LB_PORT(unit, port) ||
  20707         IS_MACSEC_PORT(unit, port)) {
  20708         /*  Do not allow programming on non-idb ports */
  20709         return BCM_E_PARAM;
  20710     }
  20711 
  20712 
  20713     pgw = si->port_group[port];
  20714     pgw_inst = (pgw | SOC_REG_ADDR_INSTANCE_MASK);
  20715     subport = (phy_port - 1) % _MN_PORTS_PER_TSC;
  20716 
  20717     switch (type) {
  20718         case bcmPortControlObmClassifierPriority:
  20719           port_control = 1;
  20720           field = PORT_PRIf;
  20721           val = value & 0x7;
  20722           break;
  20723         case bcmPortControlObmClassifierEnableDscp:
  20724           port_control = 1;
  20725           field = TRUST_DSCPf;
  20726           val = value & 0x1;
  20727           break;
  20728         case bcmPortControlObmClassifierEnableMpls:
  20729           port_control = 1;
  20730           field = TRUST_MPLSf;
  20731           val = value & 0x1;
  20732           break;
  20733         case bcmPortControlObmClassifierEnableEtag:
  20734           port_control = 1;
  20735           field = PHB_FROM_ETAGf;
  20736           val = value & 0x1;
  20737           break;
  20738         case bcmPortControlObmClassifierEtagEthertype:
  20739           field = ETHERTYPEf;
  20740           val = value & 0xffff;
  20741           break;
  20742         case bcmPortControlObmClassifierVntagEthertype:
  20743           vntag = 1;
  20744           field = ETHERTYPEf;
  20745           val = value & 0xffff;
  20746           break;
  20747         case bcmPortControlObmClassifierInternal:
  20748           class_select = 1;
  20749           break;
  20750         default:
  20751           return BCM_E_PARAM;
  20752      }
  20753      if (class_select == 1) {
  20754          COMPILER_64_ZERO(rval64);
  20755          SOC_IF_ERROR_RETURN(READ_PGW_OBM_PARSING_CONTROLr(unit, port ,&rval64));
  20756          soc_reg64_field32_set(unit, PGW_OBM_PARSING_CONTROLr,
  20757                                &rval64, USE_PM_PREEMPT_INPUTf , !value);
  20758          SOC_IF_ERROR_RETURN(WRITE_PGW_OBM_PARSING_CONTROLr(unit, port, rval64));
  20759      } else if (port_control == 1) {
  20760          reg = obm_port_config_regs[obm];
  20761          SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, pgw_inst, subport, &rval32));
  20762          soc_reg_field_set(unit, reg, &rval32, field, val);
  20763          SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, pgw_inst, subport, rval32));
  20764      } else if (vntag == 1) {
  20765          reg = obm_niv_ethertype_config_regs[obm];
  20766          SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, pgw_inst, subport, &rval32));
  20767          soc_reg_field_set(unit, reg, &rval32, field, val);
  20768          soc_reg_field_set(unit, reg, &rval32, ENABLEf, val ? 1 : 0);
  20769          SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, pgw_inst, subport, rval32));
  20770      } else {
  20771          reg = obm_pe_ethertype_config_regs[obm];
  20772          SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, pgw_inst, subport, &rval32));
  20773          soc_reg_field_set(unit, reg, &rval32, field, val);
  20774          soc_reg_field_set(unit, reg, &rval32, ENABLEf, val ? 1 : 0);
  20775          SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, pgw_inst, subport, rval32));
  20776      }
  20777      return BCM_E_NONE;
  20778 }
  20779 /*
  20780  * Function:
  20781  *      bcm_mn_obm_classifier_port_control_get
  20782  * Description:
  20783  *      Internal function to  get value specified
  20784  *      OBM port feature and congigure ethertype.
  20785  * Parameters:
  20786  *      unit - Device number
  20787  *      port - Port number
  20788  *      type - Enum value of the OBM feature
  20789  *      value - value to get
  20790  * Return Value:
  20791  *      BCM_E_XXXX
  20792  */
  20793 int
  20794 bcm_mn_obm_classifier_port_control_get(int unit,
  20795                                        bcm_port_t port,
  20796                                        bcm_port_control_t type,
  20797                                        int *value)
  20798 {
  20799     soc_info_t *si;
  20800     int pgw, pgw_inst, subport, obm;
  20801     int phy_port;
  20802     soc_reg_t  reg;
  20803     soc_field_t field;
  20804     int vntag = 0, port_control = 0, val, class_select = 0;
  20805     uint32 rval32;
  20806     uint64 rval64;
  20807 
  20808     static const soc_reg_t obm_port_config_regs[] = {
  20809         IDB_OBM0_PORT_CONFIGr, IDB_OBM1_PORT_CONFIGr,
  20810         IDB_OBM2_PORT_CONFIGr, IDB_OBM3_PORT_CONFIGr,
  20811         IDB_OBM4_PORT_CONFIGr, IDB_OBM5_PORT_CONFIGr,
  20812         IDB_OBM6_PORT_CONFIGr, IDB_OBM7_PORT_CONFIGr
  20813     };
  20814 
  20815     static const soc_reg_t obm_niv_ethertype_config_regs[] = {
  20816         IDB_OBM0_NIV_ETHERTYPEr, IDB_OBM1_NIV_ETHERTYPEr,
  20817         IDB_OBM2_NIV_ETHERTYPEr, IDB_OBM3_NIV_ETHERTYPEr,
  20818         IDB_OBM4_NIV_ETHERTYPEr, IDB_OBM5_NIV_ETHERTYPEr,
  20819         IDB_OBM6_NIV_ETHERTYPEr, IDB_OBM7_NIV_ETHERTYPEr
  20820     };
  20821 
  20822     static const soc_reg_t obm_pe_ethertype_config_regs[] = {
  20823         IDB_OBM0_PE_ETHERTYPEr, IDB_OBM1_PE_ETHERTYPEr,
  20824         IDB_OBM2_PE_ETHERTYPEr, IDB_OBM3_PE_ETHERTYPEr,
  20825         IDB_OBM4_PE_ETHERTYPEr, IDB_OBM5_PE_ETHERTYPEr,
  20826         IDB_OBM6_PE_ETHERTYPEr, IDB_OBM7_PE_ETHERTYPEr
  20827     };
  20828 
  20829     si = &SOC_INFO(unit);
  20830     /* Add check on ports */
  20831     obm = si->port_serdes[port];
  20832     obm %= _MN_TSCS_PER_PGW;
  20833 
  20834     phy_port = si->port_l2p_mapping[port];
  20835 
  20836     if (IS_CPU_PORT(unit, port) || IS_LB_PORT(unit, port) ||
  20837         IS_MACSEC_PORT(unit, port)) {
  20838         /*  Do not allow programming on non-idb ports */
  20839         return BCM_E_PARAM;
  20840     }
  20841 
  20842 
  20843     pgw = si->port_group[port];
  20844     pgw_inst = (pgw | SOC_REG_ADDR_INSTANCE_MASK);
  20845     subport = (phy_port - 1) % _MN_PORTS_PER_TSC;
  20846 
  20847     switch (type) {
  20848         case bcmPortControlObmClassifierPriority:
  20849           port_control = 1;
  20850           field = PORT_PRIf;
  20851           break;
  20852         case bcmPortControlObmClassifierEnableDscp:
  20853           port_control = 1;
  20854           field = TRUST_DSCPf;
  20855           break;
  20856         case bcmPortControlObmClassifierEnableMpls:
  20857           port_control = 1;
  20858           field = TRUST_MPLSf;
  20859           break;
  20860         case bcmPortControlObmClassifierEnableEtag:
  20861           port_control = 1;
  20862           field = PHB_FROM_ETAGf;
  20863           break;
  20864         case bcmPortControlObmClassifierEtagEthertype:
  20865           field = ETHERTYPEf;
  20866           break;
  20867         case bcmPortControlObmClassifierVntagEthertype:
  20868           vntag = 1;
  20869           field = ETHERTYPEf;
  20870           break;
  20871         case bcmPortControlObmClassifierInternal:
  20872           class_select = 1;
  20873           break;
  20874         default:
  20875           return BCM_E_PARAM;
  20876      }
  20877      if (class_select == 1) {
  20878          COMPILER_64_ZERO(rval64);
  20879          SOC_IF_ERROR_RETURN(READ_PGW_OBM_PARSING_CONTROLr(unit, port ,&rval64));
  20880          val = !soc_reg64_field32_get(unit, PGW_OBM_PARSING_CONTROLr,
  20881                                       rval64, USE_PM_PREEMPT_INPUTf);
  20882      } else if (port_control == 1) {
  20883          reg = obm_port_config_regs[obm];
  20884          SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, pgw_inst, subport, &rval32));
  20885          val = soc_reg_field_get(unit, reg, rval32, field);
  20886          SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, pgw_inst, subport, rval32));
  20887      } else if (vntag == 1) {
  20888          reg = obm_niv_ethertype_config_regs[obm];
  20889          SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, pgw_inst, subport, &rval32));
  20890          val = soc_reg_field_get(unit, reg, rval32, field);
  20891          SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, pgw_inst, subport, rval32));
  20892      } else {
  20893          reg = obm_pe_ethertype_config_regs[obm];
  20894          SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, pgw_inst, subport, &rval32));
  20895          val = soc_reg_field_get(unit, reg, rval32, field);
  20896          SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, pgw_inst, subport, rval32));
  20897      }
  20898      *value = val;
  20899      return BCM_E_NONE;
  20900 }
  20901 
  20902 /*
  20903  * Function:
  20904  * bcm_mn_obm_interrupt_port_control_get
  20905  * Description:
  20906  *      Internal function to  get if obm interrupt is enabled 
  20907  * Parameters:
  20908  *      unit - Device number
  20909  *      port - Port number
  20910  *      type - Enum value of the OBM  Interrupt type
  20911  *      value - value to get
  20912  * Return Value:
  20913  *      BCM_E_XXXX
  20914  */
  20915 int
  20916 bcm_mn_obm_interrupt_port_control_get(int unit,
  20917                                        bcm_port_t port,
  20918                                        bcm_port_control_t type,
  20919                                        int *value)
  20920 {
  20921     soc_info_t *si;
  20922     uint32 temp = 0  ;
  20923     uint64 rval64;
  20924     soc_reg_t  reg;
  20925     soc_field_t field;
  20926     int pgw = 0 , pgw_inst = 0 , obm = 0; 
  20927     int phy_port  =0 ;
  20928     si = &SOC_INFO(unit);
  20929     /* Add check on ports */
  20930     obm = si->port_serdes[port];
  20931     obm %= _MN_TSCS_PER_PGW;
  20932 
  20933     phy_port = si->port_l2p_mapping[port];
  20934 
  20935     if (IS_CPU_PORT(unit, port) || IS_LB_PORT(unit, port) ||
  20936         IS_MACSEC_PORT(unit, port)) {
  20937         /*  Do not allow programming on non-idb ports */
  20938         return BCM_E_PARAM;
  20939     }
  20940 
  20941     if (phy_port > 32 ) { 
  20942         phy_port = phy_port - 32; 
  20943     } 
  20944     pgw = si->port_group[port];
  20945     pgw_inst = (pgw | SOC_REG_ADDR_INSTANCE_MASK);
  20946     switch (type) {
  20947         case bcmPortControlObmInterruptTypeDropPreempt:
  20948           reg = PGW_OBM_DROP_STATUS_ENABLEr; 
  20949           field = PREEMPT_DROP_ERR_ENf;
  20950           break;
  20951 
  20952         case   bcmPortControlObmInterruptTypeOverflowPreempt:
  20953           reg = PGW_CA_OVERFLOW_STATUS_ENABLEr;
  20954           field = CA_PREEMPT_OVERFLOW_ENf;
  20955           break;
  20956 
  20957         case bcmPortControlObmInterruptTypeDropExpress: 
  20958           reg = PGW_OBM_DROP_STATUS_ENABLEr; 
  20959           field = EXP_DROP_ERR_ENf;
  20960           break;
  20961 
  20962         case bcmPortControlObmInterruptTypeOverflowExpress:
  20963           reg = PGW_CA_OVERFLOW_STATUS_ENABLEr;
  20964           field = CA_EXP_OVERFLOW_ENf;
  20965           break;
  20966         default:
  20967         return BCM_E_NOT_FOUND;
  20968     }
  20969          SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, pgw_inst, 0, &rval64));
  20970          temp =soc_reg64_field32_get(unit, reg, rval64, field);
  20971          *value= (temp & (1<<(phy_port-1)))?1:0;  
  20972    
  20973      return BCM_E_NONE;
  20974 }
  20975 /*
  20976  * Function:
  20977  * bcm_mn_obm_interrupt_port_control_set
  20978  * Description:
  20979  *      Internal function to  get if obm interrupt is enabled 
  20980  * Parameters:
  20981  *      unit - Device number
  20982  *      port - Port number
  20983  *      type - Enum value of the OBM  Interrupt type
  20984  *      value - value to get
  20985  * Return Value:
  20986  *      BCM_E_XXXX
  20987  */
  20988 int
  20989 bcm_mn_obm_interrupt_port_control_set(int unit,
  20990                                        bcm_port_t port,
  20991                                        bcm_port_control_t type,
  20992                                        int value)
  20993 {
  20994     soc_info_t *si;
  20995     uint32 temp = 0 ;
  20996     uint64 rval64;
  20997     soc_reg_t  reg;
  20998     soc_field_t field;
  20999     int pgw = 0, pgw_inst = 0 , obm = 0 ; 
  21000     int phy_port = 0 ;
  21001     si = &SOC_INFO(unit);
  21002     /* Add check on ports */
  21003     obm = si->port_serdes[port];
  21004     obm %= _MN_TSCS_PER_PGW;
  21005     phy_port = si->port_l2p_mapping[port];
  21006 
  21007     if (IS_CPU_PORT(unit, port) || IS_LB_PORT(unit, port) ||
  21008         IS_MACSEC_PORT(unit, port)) {
  21009         /*  Do not allow programming on non obm  ports */
  21010         return BCM_E_PARAM;
  21011     }
  21012 
  21013 
  21014     pgw = si->port_group[port];
  21015     pgw_inst = (pgw | SOC_REG_ADDR_INSTANCE_MASK);
  21016     switch (type) {
  21017         case bcmPortControlObmInterruptTypeDropPreempt:
  21018           reg = PGW_OBM_DROP_STATUS_ENABLEr; 
  21019           field = PREEMPT_DROP_ERR_ENf;
  21020           break;
  21021 
  21022         case   bcmPortControlObmInterruptTypeOverflowPreempt:
  21023           reg = PGW_CA_OVERFLOW_STATUS_ENABLEr;
  21024           field = CA_PREEMPT_OVERFLOW_ENf;
  21025           break;
  21026 
  21027         case bcmPortControlObmInterruptTypeDropExpress: 
  21028           reg = PGW_OBM_DROP_STATUS_ENABLEr; 
  21029           field =EXP_DROP_ERR_ENf;
  21030           break;
  21031 
  21032         case bcmPortControlObmInterruptTypeOverflowExpress:
  21033           reg = PGW_CA_OVERFLOW_STATUS_ENABLEr;
  21034           field = CA_EXP_OVERFLOW_ENf;
  21035 
  21036           break;
  21037         default:  
  21038         return BCM_E_NOT_FOUND; 
  21039 
  21040       } 
  21041       SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, pgw_inst, 0,&rval64));
  21042       temp = soc_reg64_field32_get(unit, reg, rval64, field);
  21043      if (phy_port > 32 ) { 
  21044         phy_port = phy_port - 32; 
  21045      } 
  21046      if (value) {        
  21047       temp = temp | (1<<(phy_port - 1));  
  21048      } else { 
  21049       temp = temp & ~(1<<(phy_port - 1));  
  21050      }
  21051     soc_reg64_field32_set(unit, reg, &rval64, field,temp);
  21052     SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg,pgw_inst,0,rval64));
  21053      return BCM_E_NONE ;
  21054 }
  21055 
  21056 
  21057 
  21058 #endif /* defined(BCM_MONTEREY_SUPPORT) */