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


      1 
      2 /*
      3  * 
      4  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      5  * 
      6  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      7  *
      8  * COS Queue Management
      9  * Purpose: API to set different cosq, priorities, and scheduler registers.
     10  */
     11 #include <shared/bsl.h>
     12 #include <soc/defs.h>
     13 #include <sal/core/libc.h>
     14 #if defined(BCM_TRIDENT2_SUPPORT)
     15 #include <soc/drv.h>
     16 #include <soc/scache.h>
     17 #include <soc/profile_mem.h>
     18 #include <soc/l3x.h>
     19 #include <soc/macutil.h>
     20 
     21 #include <soc/esw/portctrl.h>
     22 #include <soc/trident2.h>
     23 #include <soc/td2_td2p.h>
     24 
     25 #include <bcm/error.h>
     26 #include <bcm/cosq.h>
     27 #include <bcm_int/esw/mbcm.h>
     28 #include <bcm_int/esw/stack.h>
     29 #include <bcm_int/esw/cosq.h>
     30 #include <bcm_int/esw/rx.h>
     31 #include <bcm_int/esw/virtual.h>
     32 #include <bcm_int/esw/trident2.h>
     33 #include <bcm_int/esw/trident2plus.h>
     34 #include <bcm_int/esw/subport.h>
     35 #include <bcm_int/esw/xgs5.h>
     36 #include <bcm_int/esw/trx.h>
     37 
     38 #include <bcm_int/esw_dispatch.h>
     39 
     40 #include <bcm_int/bst.h>
     41 
     42 #ifdef BCM_WARM_BOOT_SUPPORT
     43 #include <bcm_int/esw/switch.h>
     44 #endif /* BCM_WARM_BOOT_SUPPORT */
     45 
     46 #define TD2_CELL_FIELD_MAX       0x1ffff
     47 
     48 /* MMU cell size in bytes */
     49 #define _BCM_TD2_BYTES_PER_CELL            208   /* bytes */
     50 #define _BCM_TD2_BYTES_TO_CELLS(_byte_)  \
     51     (((_byte_) + _BCM_TD2_BYTES_PER_CELL - 1) / _BCM_TD2_BYTES_PER_CELL)
     52 
     53 #define _BCM_TD2_NUM_PORT_SCHEDULERS              106
     54 #define _BCM_TD2_NUM_L0_SCHEDULER_PER_PIPE        265
     55 #define _BCM_TD2_NUM_L0_SCHEDULER                 _BCM_TD2_NUM_L0_SCHEDULER_PER_PIPE * 2
     56 #define _BCM_TD2_NUM_L1_SCHEDULER_PER_PIPE        (1024 - 4) /* Reserved for default val */
     57 #define _BCM_TD2_NUM_L1_SCHEDULER                 _BCM_TD2_NUM_L1_SCHEDULER_PER_PIPE * 2
     58 #define _BCM_TD2_NUM_L2_UC_LEAVES_PER_PIPE        (1480 - 4) /* Reserved for default val */
     59 #define _BCM_TD2_NUM_L2_UC_LEAVES                 _BCM_TD2_NUM_L2_UC_LEAVES_PER_PIPE * 2
     60 #define _BCM_TD2_NUM_L2_MC_LEAVES_PER_PIPE        568
     61 #define _BCM_TD2_NUM_L2_MC_LEAVES                 _BCM_TD2_NUM_L2_MC_LEAVES_PER_PIPE * 2
     62 #define _BCM_TD2_NUM_L2_LEAVES_PER_PIPE     (_BCM_TD2_NUM_L2_MC_LEAVES_PER_PIPE + \
     63                                              _BCM_TD2_NUM_L2_UC_LEAVES_PER_PIPE)
     64 #define _BCM_TD2_NUM_L2_LEAVES              _BCM_TD2_NUM_L2_LEAVES_PER_PIPE * 2
     65 #define _BCM_TD2_NUM_TOTAL_SCHEDULERS     (_BCM_TD2_NUM_PORT_SCHEDULERS + \
     66                                            _BCM_TD2_NUM_L0_SCHEDULER +    \
     67                                            _BCM_TD2_NUM_L1_SCHEDULER)
     68 #define _TD2_SPM_ENTRIES_PER_SET            128
     69 #define _TD2_SCM_ENTRIES_PER_SET            16
     70 /* ENDPOINT_COS_MAPm */
     71 #define _TD2_EPCM_ENTRIES_PER_SET           16
     72 /* All CPU leaves are MC and belong to X Pipe only. Ranges from 520-567.*/
     73 #define _BCM_TD2_NUM_L2_CPU_LEAVES                48 
     74 
     75 #define _TD2_NUM_COS    NUM_COS
     76 #define _TD2_NUM_INTERNAL_PRI          16
     77 
     78 /* TD2 supports eight PFC priority */
     79 #define _BCM_TD2_NUM_PFC_CLASS          8
     80 
     81 #define _BCM_TD2_COSQ_LIST_NODE_INIT(list, node)         \
     82     list[node].in_use            = FALSE;               \
     83     list[node].gport             = -1;                  \
     84     list[node].base_index        = -1;                  \
     85     list[node].numq              = 0;                   \
     86     list[node].base_size         = 0;                   \
     87     list[node].numq_expandable   = 0;                   \
     88     list[node].hw_index          = -1;                  \
     89     list[node].level             = -1;                  \
     90     list[node].attached_to_input       = -1;                  \
     91     list[node].hw_cosq           = 0;                   \
     92     list[node].node_align_value  = 1;                   \
     93     list[node].remote_modid      = -1;                  \
     94     list[node].remote_port       = -1;                  \
     95     BCM_PBMP_CLEAR(list[node].fabric_pbmp);              \
     96     list[node].local_port        = -1;                  \
     97     list[node].parent            = NULL;                \
     98     list[node].sibling           = NULL;                \
     99     list[node].child             = NULL;
    100 
    101 #define _BCM_TD2_COSQ_NODE_INIT(node)                    \
    102     node->in_use            = FALSE;                    \
    103     node->gport             = -1;                       \
    104     node->base_index        = -1;                       \
    105     node->numq              = 0;                        \
    106     node->base_size         = 0;                        \
    107     node->numq_expandable   = 0;                        \
    108     node->hw_index          = -1;                       \
    109     node->level             = -1;                       \
    110     node->attached_to_input = -1;                       \
    111     node->hw_cosq           = 0;                        \
    112     node->node_align_value  = 1;                        \
    113     node->remote_modid      = -1;                       \
    114     node->remote_port       = -1;                       \
    115     BCM_PBMP_CLEAR(node->fabric_pbmp);              \
    116     node->local_port        = -1;                       \
    117     node->parent            = NULL;                     \
    118     node->sibling           = NULL;                     \
    119     node->child             = NULL;
    120 
    121 typedef enum {
    122     _BCM_TD2_COSQ_FC_PAUSE = 0,
    123     _BCM_TD2_COSQ_FC_PFC,
    124     _BCM_TD2_COSQ_FC_VOQFC,
    125     _BCM_TD2_COSQ_FC_E2ECC
    126 } _bcm_td2_fc_type_t;
    127 
    128 typedef enum {
    129     _BCM_TD2_NODE_UNKNOWN = 0,
    130     _BCM_TD2_NODE_UCAST,
    131     _BCM_TD2_NODE_MCAST,
    132     _BCM_TD2_NODE_VOQ,
    133     _BCM_TD2_NODE_VLAN_UCAST,
    134     _BCM_TD2_NODE_VM_UCAST,
    135     _BCM_TD2_NODE_SERVICE_UCAST,
    136     _BCM_TD2_NODE_SCHEDULER
    137 } _bcm_td2_node_type_e;
    138 
    139 typedef struct _bcm_td2_cosq_node_s {
    140     struct _bcm_td2_cosq_node_s *parent;
    141     struct _bcm_td2_cosq_node_s *sibling;
    142     struct _bcm_td2_cosq_node_s *child;
    143     bcm_gport_t gport;
    144     int in_use;
    145     int base_index;
    146     uint16 numq_expandable;
    147     uint16 base_size;
    148     int numq;
    149     int hw_index;
    150     soc_td2_node_lvl_e level;
    151     _bcm_td2_node_type_e    type;
    152     int attached_to_input;
    153     int hw_cosq;
    154     int node_align_value;
    155 
    156     /* DPVOQ specific information */
    157     bcm_port_t   local_port;
    158     bcm_module_t remote_modid;
    159     bcm_port_t   remote_port;
    160     bcm_pbmp_t   fabric_pbmp;
    161 }_bcm_td2_cosq_node_t;
    162 
    163 typedef struct _bcm_td2_cosq_list_s {
    164     int count;
    165     SHR_BITDCL *bits;
    166 }_bcm_td2_cosq_list_t;
    167 
    168 #define _BCM_TD2_HSP_PORT_MAX_L0    5
    169 #define _BCM_TD2_HSP_PORT_MAX_L1    10
    170 #define _BCM_TD2_HSP_PORT_MAX_L2    2
    171 #define _BCM_TD2_HSP_PORT_MAX_COS   8
    172 
    173 #define _BCM_TD2_MAX_PORT   106
    174 
    175 #define _BCM_TD2_ROOT_SCHED_INDEX(u,mmu_port)       \
    176                 ((mmu_port >= 64) ? (mmu_port - 64) : (mmu_port))
    177 
    178 #define _BCM_TD2_HSP_L0_INDEX(u,mmu_port,cosq)       \
    179  ((((mmu_port >= 64) ? (mmu_port - 64) : (mmu_port)) * _BCM_TD2_HSP_PORT_MAX_L0) +\
    180   (cosq))
    181 
    182 #define _BCM_TD2_HSP_L1_INDEX(u,mmu_port,cosq)       \
    183  ((((mmu_port >= 64) ? (mmu_port - 64) : (mmu_port)) * _BCM_TD2_HSP_PORT_MAX_L1) +\
    184   (cosq))
    185 
    186 
    187 typedef struct _bcm_td2_pipe_resources_s {
    188     int num_base_queues;   /* Number of classical queues */
    189 
    190     _bcm_td2_cosq_list_t ext_qlist;      /* list of extended queues */
    191     _bcm_td2_cosq_list_t l0_sched_list;  /* list of l0 sched nodes */
    192     _bcm_td2_cosq_list_t l1_sched_list;  /* list of l1 sched nodes */
    193 
    194     _bcm_td2_cosq_node_t *p_queue_node;
    195     _bcm_td2_cosq_node_t *p_mc_queue_node;
    196 } _bcm_td2_pipe_resources_t;
    197 
    198 typedef struct _bcm_td2_cosq_port_info_s {
    199     int mc_base;
    200     int mc_limit;
    201     int uc_base;
    202     int uc_limit;
    203     int eq_base;
    204     int eq_limit;
    205     _bcm_td2_pipe_resources_t *resources;
    206 } _bcm_td2_cosq_port_info_t;
    207 
    208 typedef struct _bcm_td2_cosq_cpu_cosq_config_s {
    209     /* All MC queues have DB and MCQE space */
    210     int enable;
    211     int q_min_limit[2];
    212     int q_shared_limit[2];
    213     uint8 q_limit_dynamic[2];
    214     uint8 q_limit_enable[2];
    215 } _bcm_td2_cosq_cpu_cosq_config_t;
    216 
    217 #define _TD2_XPIPE  0
    218 #define _TD2_YPIPE  1
    219 #define _TD2_NUM_PIPES  2
    220 
    221 #define _BCM_TD2_PORT_TO_PIPE(u, p) \
    222    (SOC_PBMP_MEMBER(SOC_INFO(unit).xpipe_pbm, (p)) ? _TD2_XPIPE : _TD2_YPIPE)
    223 
    224 typedef struct _bcm_td2_mmu_info_s {
    225 
    226     _bcm_td2_cosq_node_t sched_node[_BCM_TD2_NUM_TOTAL_SCHEDULERS]; /* sched nodes */
    227     _bcm_td2_cosq_node_t queue_node[_BCM_TD2_NUM_L2_UC_LEAVES];    /* queue nodes */
    228     _bcm_td2_cosq_node_t mc_queue_node[_BCM_TD2_NUM_L2_MC_LEAVES]; /* queue nodes */
    229     _bcm_td2_cosq_port_info_t port_info[_BCM_TD2_MAX_PORT];
    230     
    231     _bcm_td2_pipe_resources_t   pipe_resources[_TD2_NUM_PIPES];
    232     
    233     int     ets_mode;
    234     int     curr_shared_limit;
    235     int     curr_merger_index;
    236 }_bcm_td2_mmu_info_t;
    237 
    238 /* Node hardware index alignment. */
    239 #define _BCM_TD2_START_INDEX_ALIGN_DEFAULT   1
    240 #define _BCM_TD2_START_INDEX_ALIGN_PFC       4
    241 
    242 #define _TD2_NUM_TIME_DOMAIN    4
    243 
    244 typedef struct _bcm_td2_cosq_time_info_s {
    245     soc_field_t field;
    246     uint32 ref_count;   
    247 } _bcm_td2_cosq_time_info_t;
    248 
    249 /* WRED can be enabled at per UC queue / queue group/ port / service pool basis
    250 MMU_WRED_AVG_QSIZE_X/Y_PIPE used entry:2 * (1480 + 128 + 208 + 4) = 3640
    251 1479 ~ 0: Unicast Queue
    252 1487 ~ 1480: Not used.
    253 1615 ~ 1488: Queue Group per PIPE
    254 1823 ~ 1616: Port Service Pool (Port 0 to 52)
    255 1839 ~ 1824: Not used.
    256 1843 ~ 1840: Global Service Pool
    257 */
    258 STATIC _bcm_td2_cosq_time_info_t time_domain[_TD2_NUM_TIME_DOMAIN] = {
    259     {TIME_0f, 3640}, /* Default all entries are pointing to TIME_0 */
    260     {TIME_1f, 0},
    261     {TIME_2f, 0},
    262     {TIME_3f, 0}
    263 };
    264 
    265 #define _TD2_NUM_SERVICE_POOL    4
    266 
    267 #define _BCM_TD2_PRESOURCES(mi, p)  (&(mi)->pipe_resources[(p)])
    268 
    269 STATIC _bcm_td2_mmu_info_t *_bcm_td2_mmu_info[BCM_MAX_NUM_UNITS];  /* MMU info */
    270 
    271 STATIC soc_profile_mem_t *_bcm_td2_wred_profile[_TD2_NUM_PIPES][BCM_MAX_NUM_UNITS];
    272 STATIC soc_profile_mem_t *_bcm_td2_cos_map_profile[BCM_MAX_NUM_UNITS];
    273 STATIC soc_profile_mem_t *_bcm_td2_sample_int_profile[BCM_MAX_NUM_UNITS];
    274 STATIC soc_profile_reg_t *_bcm_td2_feedback_profile[BCM_MAX_NUM_UNITS];
    275 STATIC soc_profile_reg_t *_bcm_td2_llfc_profile[BCM_MAX_NUM_UNITS];
    276 STATIC soc_profile_mem_t *_bcm_td2_voq_port_map_profile[BCM_MAX_NUM_UNITS];
    277 static soc_profile_mem_t *_bcm_td2_ifp_cos_map_profile[BCM_MAX_NUM_UNITS];
    278 STATIC soc_profile_mem_t *_bcm_td2_service_port_map_profile[BCM_MAX_NUM_UNITS];
    279 STATIC soc_profile_mem_t *_bcm_td2_service_cos_map_profile[BCM_MAX_NUM_UNITS];
    280 
    281 STATIC _bcm_td2_cosq_cpu_cosq_config_t *_bcm_td2_cosq_cpu_cosq_config[BCM_MAX_NUM_UNITS][_BCM_TD2_NUM_L2_CPU_LEAVES];
    282 
    283 STATIC int bcm_td2p_cosq_rx_chan_l0_map[BCM_RX_CHANNELS] =
    284                                          {-1, 259, 260, 261};
    285 STATIC int bcm_td2p_cmic_to_mmu_cosmask_map[_TD2PLUS_COSQ_NUM_CPU_L0_NODES] =
    286                                          {58, 59, 60, 61, 62, 63};
    287 
    288 STATIC int
    289 _bcm_td2_node_index_set(_bcm_td2_cosq_list_t *list, int start, int range);
    290 
    291 STATIC int _bcm_td2_voq_next_base_node_get(int unit, bcm_port_t port, 
    292         int modid,
    293         _bcm_td2_cosq_node_t **base_node);
    294 STATIC int
    295 _bcm_td2_cosq_mapping_set(int unit, bcm_port_t ing_port, bcm_cos_t priority,
    296                          uint32 flags, bcm_gport_t gport, bcm_cos_queue_t cosq);
    297 STATIC int
    298 _bcm_td2_cosq_set_scheduler_states(int unit, bcm_port_t port, int busy);
    299 
    300 typedef enum {
    301     _BCM_TD2_COSQ_TYPE_UCAST,
    302     _BCM_TD2_COSQ_TYPE_MCAST,
    303     _BCM_TD2_COSQ_TYPE_EXT_UCAST
    304 } _bcm_td2_cosq_type_t;
    305 
    306 #define IS_TD2_HSP_PORT(u,p)   \
    307     ((_soc_trident2_port_sched_type_get((u),(p)) == SOC_TD2_SCHED_HSP) ? 1 : 0)
    308 
    309 typedef struct _bcm_td2_endpoint_s {
    310     uint32 flags;       /* BCM_COSQ_CLASSIFIER_xxx flags */
    311     bcm_vlan_t vlan;    /* VLAN */
    312     bcm_mac_t mac;      /* MAC address */
    313     bcm_vrf_t vrf;      /* Virtual Router Instance */
    314     bcm_ip_t ip_addr;   /* IPv4 address */
    315     bcm_ip6_t ip6_addr; /* IPv6 address */
    316     bcm_gport_t gport;  /* GPORT ID */
    317     bcm_if_t egress_if; /* Egress object */
    318 } _bcm_td2_endpoint_t;
    319 
    320 typedef struct _bcm_td2_endpoint_queuing_info_s {
    321     int num_endpoint; /* Number of endpoints */
    322     _bcm_td2_endpoint_t **ptr_array; /* Array of pointers to endpoints */
    323     soc_profile_mem_t *cos_map_profile; /* Internal priority to CoS queue
    324                                            mapping profile */
    325 } _bcm_td2_endpoint_queuing_info_t;
    326 
    327 STATIC int 
    328 _bcm_td2_cosq_egress_sp_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 
    329                         int *p_pool_start, int *p_pool_end);
    330 
    331 STATIC _bcm_td2_endpoint_queuing_info_t *_bcm_td2_endpoint_queuing_info[BCM_MAX_NUM_UNITS];
    332 
    333 STATIC int
    334 _bcm_td2_cosq_dynamic_thresh_enable_get(int unit, 
    335                         bcm_gport_t gport, bcm_cos_queue_t cosq, 
    336                         bcm_cosq_control_t type, int *arg);
    337 
    338 STATIC int 
    339 _bcm_td2_cosq_node_get(int unit, bcm_gport_t gport,
    340     bcm_cos_queue_t cosq,bcm_module_t *modid, bcm_port_t *port,
    341     int *id, _bcm_td2_cosq_node_t **node);
    342 
    343 STATIC int
    344 _bcm_td2_cosq_sched_parent_child_set(int unit, int port, int level,
    345                                      int sched_index, int child_index,
    346                                      soc_td2_sched_mode_e sched_mode, 
    347                                      int weight, _bcm_td2_cosq_node_t *node);
    348 
    349 #define _BCM_TD2_NUM_ENDPOINT(unit) \
    350     (_bcm_td2_endpoint_queuing_info[unit]->num_endpoint)
    351     
    352 #define _BCM_TD2_ENDPOINT(unit, id) \
    353     (_bcm_td2_endpoint_queuing_info[unit]->ptr_array[id])
    354 
    355 #define _BCM_TD2_ENDPOINT_IS_USED(unit, id) \
    356     (_bcm_td2_endpoint_queuing_info[unit]->ptr_array[id] != NULL)
    357 
    358 #define _BCM_TD2_ENDPOINT_COS_MAP_PROFILE(unit) \
    359     (_bcm_td2_endpoint_queuing_info[unit]->cos_map_profile)
    360 
    361 #ifdef BCM_WARM_BOOT_SUPPORT
    362 
    363 #define BCM_WB_VERSION_1_0                SOC_SCACHE_VERSION(1,0)
    364 #define BCM_WB_VERSION_1_1                SOC_SCACHE_VERSION(1,1)
    365 #define BCM_WB_VERSION_1_2                SOC_SCACHE_VERSION(1,2)
    366 #define BCM_WB_VERSION_1_3                SOC_SCACHE_VERSION(1,3)
    367 #define BCM_WB_VERSION_1_4                SOC_SCACHE_VERSION(1,4)
    368 #define BCM_WB_VERSION_1_5                SOC_SCACHE_VERSION(1,5)
    369 #define BCM_WB_VERSION_1_6                SOC_SCACHE_VERSION(1,6)
    370 #define BCM_WB_VERSION_1_7                SOC_SCACHE_VERSION(1,7)
    371 
    372 #define BCM_WB_DEFAULT_VERSION            BCM_WB_VERSION_1_7
    373 
    374 STATIC int
    375 _bcm_td2_cosq_wb_alloc(int unit)
    376 {
    377     _bcm_td2_mmu_info_t *mmu_info;
    378     soc_scache_handle_t scache_handle;
    379     uint8 *scache_ptr;
    380     int rv, alloc_size, node_list_sizes[3], ii, jj;
    381     uint32 shadow_size = 0;
    382     
    383     mmu_info = _bcm_td2_mmu_info[unit];
    384 
    385     if (!mmu_info) {
    386         return BCM_E_INIT;
    387     }
    388     if ((SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit))) { 
    389         /* COSQ warmboot requires extended scache support i.e. level2 warmboot*/  
    390         return BCM_E_NONE;
    391     }
    392 
    393     node_list_sizes[0] = _BCM_TD2_NUM_L2_UC_LEAVES;
    394     node_list_sizes[1] = _BCM_TD2_NUM_L2_MC_LEAVES;
    395     node_list_sizes[2] = _BCM_TD2_NUM_TOTAL_SCHEDULERS;
    396 
    397     alloc_size = 0;
    398     for(ii = 0; ii < 3; ii++) {
    399         alloc_size += sizeof(uint32);
    400         for(jj = 0; jj < node_list_sizes[ii]; jj++) {
    401             alloc_size += 4 * sizeof(uint32);
    402         }
    403     }
    404 
    405     /* Size of  TIME_DOMAINr field and count reference */
    406     alloc_size += _TD2_NUM_TIME_DOMAIN * sizeof(_bcm_td2_cosq_time_info_t);
    407 
    408     soc_trident2_fc_map_shadow_size_get(unit, &shadow_size);
    409     alloc_size += shadow_size;
    410 
    411     /* added in BCM_WB_VERSION_1_1
    412      * to sync _bcm_td2_mmu_info[unit]->hw_cosq/attached_to_input/
    413      * type/numq_expandable/numq/base_index/base_size
    414      */
    415     for (ii = 0; ii < 3; ii++) {
    416         for (jj = 0; jj < node_list_sizes[ii]; jj++) {
    417             alloc_size += 2 * sizeof(uint32);
    418         }
    419     }
    420 
    421     /* added in BCM_WB_VERSION_1_1
    422      * to sync _bcm_td2_mmu_info[unit]->ets_mode/curr_shared_limit
    423      */
    424     alloc_size += 2 * sizeof(int);
    425 
    426     /* added in BCM_WB_VERSION_1_2
    427      * to sync the reference count of IFP_COS_MAPm 
    428      */
    429     alloc_size += (SOC_MEM_SIZE(unit,IFP_COS_MAPm) / _TD2_NUM_INTERNAL_PRI) *
    430                   sizeof(uint16);
    431 
    432     alloc_size += sizeof(uint16) * SOC_MEM_SIZE(unit, SERVICE_COS_MAPm) /
    433                   _TD2_SCM_ENTRIES_PER_SET;
    434     alloc_size += sizeof(uint16) * SOC_MEM_SIZE(unit, SERVICE_PORT_MAPm) /
    435                   _TD2_SPM_ENTRIES_PER_SET;
    436 
    437     BCM_IF_ERROR_RETURN(soc_td2_mmu_traffic_ctrl_size(unit, &alloc_size));
    438 
    439     /*
    440      * Added in BCM_WB_VERSION_1_5
    441      * Sync num_cos value
    442      */
    443     alloc_size += sizeof(int);
    444 
    445     /*
    446      * Added in BCM_WB_VERSION_1_6
    447      * to sync _bcm_td2_mmu_info[unit]->curr_merger_index/node->fabric_pbmp
    448      */
    449     alloc_size += sizeof(int);  /* to sync sizeof(bcm_pbmp_t) */
    450     for(ii = 0; ii < 3; ii++) {
    451         alloc_size += (node_list_sizes[ii] * sizeof(bcm_pbmp_t));
    452     }
    453     alloc_size += sizeof(int);
    454 
    455     /*
    456      * Added in BCM_WB_VERSION_1_7
    457      * to sync _bcm_td2_endpoint_queuing_info[unit]->ptr_array[id]
    458      */
    459      if (soc_feature(unit, soc_feature_endpoint_queuing)) {
    460          alloc_size += ((_BCM_TD2_NUM_ENDPOINT(unit) - 1) *
    461                         (sizeof(uint32) + sizeof(bcm_vrf_t) + sizeof(bcm_ip6_t)));
    462          alloc_size += sizeof(uint16) * SOC_MEM_SIZE(unit, ENDPOINT_COS_MAPm) /
    463                   _TD2_EPCM_ENTRIES_PER_SET;
    464      }
    465 
    466     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_COSQ, 0);
    467 
    468     rv = _bcm_esw_scache_ptr_get(unit, scache_handle, TRUE, alloc_size,
    469                                  &scache_ptr, BCM_WB_DEFAULT_VERSION, NULL);
    470     if (rv == BCM_E_NOT_FOUND) {
    471         rv = BCM_E_NONE;
    472     }
    473 
    474     return rv;
    475 }
    476 
    477 #define _BCM_TD2_WB_NTYPE_UCAST 0
    478 #define _BCM_TD2_WB_NTYPE_MCAST 1
    479 #define _BCM_TD2_WB_NTYPE_SCHED 2
    480 
    481 #define _BCM_TD2_WB_SET_NODE_W1(ntype,nid,sz,parentid,pipe)    \
    482     (((ntype & 3)) | \
    483      (((sz) & 7) << 2) | \
    484      (((nid) & 0x1fff) << 5) | \
    485      (((parentid) & 0xfff) << 18) | ((pipe) & 1) << 31)
    486 
    487 #define _BCM_TD2_WB_GET_NODE_ID_W1(w1) (((w1) >> 5) & 0x1fff)
    488 
    489 #define _BCM_TD2_WB_GET_NODE_TYPE_W1(w1) ((w1) & 3)
    490 
    491 #define _BCM_TD2_WB_GET_NODE_SIZE_W1(w1) (((w1) >> 2) & 7)
    492 
    493 #define _BCM_TD2_WB_GET_NODE_PARENT_W1(w1) (((w1) >> 18) & 0xfff)
    494 
    495 #define _BCM_TD2_WB_GET_PIPE_W1(w1) (((w1) >> 31) & 1)
    496 
    497 /* 12 bit hw index, 11 bit sibling, 3 bit hw cosq */
    498 /* Encoding node_align_value in 1 bit 0->1, 1->4 */
    499 #define _BCM_TD2_WB_SET_NODE_W2(hwindex,hwcosq,cosq,lvl,align)    \
    500     ((((hwindex) & 0x1fff)) | (((hwcosq) & 0xf) << 13) | \
    501         (((cosq) & 0xf) << 17) | (((lvl) & 0x7) << 21) | \
    502         (((align) & 0x1) << 24))
    503 
    504 #define _BCM_TD2_WB_GET_NODE_HW_INDEX_W2(w1) ((w1) & 0x1fff)
    505 
    506 #define _BCM_TD2_WB_GET_NODE_HW_COSQ_W2(w1) (((w1) >> 13) & 0xf)
    507 
    508 #define _BCM_TD2_WB_GET_NODE_COSQATTT_W2(w1) (((w1) >> 17) & 0xf)
    509 
    510 #define _BCM_TD2_WB_GET_NODE_LEVEL_W2(w1) (((w1) >> 21) & 0x7)
    511 
    512 #define _BCM_TD2_WB_GET_ALIGN_W2(w1) (((w1) >> 24) & 0x1)
    513 
    514 #define _BCM_TD2_WB_SET_NODE_W3(gport)    (gport)
    515 
    516 #define _BCM_TD2_WB_SET_NODE_W4(remote_modid,remote_port,voq_cosq)    \
    517     ((((remote_modid) & 0x1ff)) | \
    518      (((remote_port) & 0x1ff) << 9) | \
    519      (((voq_cosq) & 0xf) << 18))
    520 
    521 #define _BCM_TD2_WB_GET_NODE_DEST_MODID_W4(w1) ((w1) & 0x1ff)
    522 
    523 #define _BCM_TD2_WB_GET_NODE_DEST_PORT_W4(w1) (((w1) >> 9) & 0x1ff)
    524 
    525 #define _BCM_TD2_WB_GET_NODE_VOQ_COSQ_W4(w1) (((w1) >> 18) & 0xf)
    526 
    527 #define _BCM_TD2_WB_SET_NODE_W5(expand,type,cosq,hw_cosq)    \
    528     (((expand) & 0x7) | (((type) & 0x1f) << 3) | \
    529     (((cosq) & 0xfff) << 8)  | (((hw_cosq) & 0xfff) << 20))
    530 
    531 #define _BCM_TD2_WB_GET_EXPAND_W5(w1) ((w1) & 0x7)
    532 
    533 #define _BCM_TD2_WB_TYPE_W5(w1) (((w1) >> 3) & 0x1f)
    534 
    535 #define _BCM_TD2_WB_COSQ_W5(w1) (((w1) >> 8) & 0xfff)
    536 
    537 #define _BCM_TD2_WB_HW_COSQ_W5(w1) (((w1) >> 20) & 0xfff)
    538 
    539 #define _BCM_TD2_WB_SET_NODE_W6(base_size,base_index,numq)    \
    540     (((base_size) & 0x3ff) | (((base_index) & 0x7ff) << 10) | \
    541     (((numq) & 0x7ff) << 21))
    542 
    543 #define _BCM_TD2_WB_GET_BASE_SIZE_W6(w1) ((w1) & 0x3ff)
    544 
    545 #define _BCM_TD2_WB_GET_BASE_INDEX_W6(w1) (((w1) >> 10) & 0x7ff)
    546 
    547 #define _BCM_TD2_WB_GET_NUMQ_W6(w1) (((w1) >> 21) & 0x7ff)
    548 
    549 
    550 #define _BCM_TD2_NODE_ID(np,np0) (np - np0)
    551 
    552 /*
    553  * Function:
    554  *      bcm_td2_cosq_endpoint_recover
    555  * Purpose:
    556  *      Recover endpoint info from scache.
    557  * Parameters:
    558  *      unit       - (IN)     StrataSwitch unit #
    559  *      scache_ptr - (IN/OUT) Scache pointer
    560  * Returns:
    561  *      BCM_E_xxx
    562  */
    563 STATIC int
    564 bcm_td2_cosq_endpoint_recover(int unit, uint8 **scache_ptr)
    565 {
    566     int entry_size;
    567     int flags;
    568     int ii;
    569     int profile_num;
    570     soc_profile_mem_t *profile_mem;
    571     uint16 *u16_scache_ptr;
    572     int    ref_count;
    573 
    574     entry_size = sizeof(uint32) + sizeof(bcm_vrf_t) + sizeof(bcm_ip6_t);
    575     /* entry 0 was reserved and is not synced. */
    576     for (ii = 1; ii < _BCM_TD2_NUM_ENDPOINT(unit); ii++) {
    577         sal_memcpy(&flags, (*scache_ptr), sizeof(uint32));
    578 
    579         if ((flags & BCM_COSQ_CLASSIFIER_L2) ||
    580             (flags & BCM_COSQ_CLASSIFIER_L3) ||
    581             (flags & BCM_COSQ_CLASSIFIER_GPORT) || 
    582             (flags & BCM_COSQ_CLASSIFIER_L3_EGRESS)) {
    583             _BCM_TD2_ENDPOINT(unit, ii) = sal_alloc(
    584                 sizeof(_bcm_td2_endpoint_t), "Endpoint Info");
    585             if (_BCM_TD2_ENDPOINT(unit, ii) == NULL) {
    586                 return BCM_E_MEMORY;
    587             }
    588             sal_memset(_BCM_TD2_ENDPOINT(unit, ii), 0,
    589                        sizeof(_bcm_td2_endpoint_t));
    590             _BCM_TD2_ENDPOINT(unit, ii)->flags = flags;
    591             if (flags & BCM_COSQ_CLASSIFIER_L2) {
    592                 (*scache_ptr) += sizeof(uint32);
    593                 sal_memcpy(&(_BCM_TD2_ENDPOINT(unit, ii)->vlan),
    594                            (*scache_ptr), sizeof(bcm_vlan_t));
    595                 (*scache_ptr) += sizeof(bcm_vlan_t);
    596                 sal_memcpy(_BCM_TD2_ENDPOINT(unit, ii)->mac, (*scache_ptr),
    597                            sizeof(bcm_mac_t));
    598                 (*scache_ptr) += (entry_size - sizeof(uint32) -
    599                                   sizeof(bcm_vlan_t));
    600             } else if (flags & BCM_COSQ_CLASSIFIER_L3) {
    601                 (*scache_ptr) += sizeof(uint32);
    602                 sal_memcpy(&(_BCM_TD2_ENDPOINT(unit, ii)->vrf),
    603                            (*scache_ptr), sizeof(bcm_vrf_t));
    604                 (*scache_ptr) += sizeof(bcm_vrf_t);
    605                 if (flags & BCM_COSQ_CLASSIFIER_IP6) {
    606                     sal_memcpy(_BCM_TD2_ENDPOINT(unit, ii)->ip6_addr, (*scache_ptr),
    607                                sizeof(bcm_ip6_t));
    608                 } else {
    609                     sal_memcpy(&(_BCM_TD2_ENDPOINT(unit, ii)->ip_addr), (*scache_ptr),
    610                                sizeof(bcm_ip_t));
    611                 }
    612                 (*scache_ptr) += (entry_size - sizeof(uint32) -
    613                                   sizeof(bcm_vrf_t));
    614             } else if (flags & BCM_COSQ_CLASSIFIER_L3_EGRESS) {
    615                 (*scache_ptr) += sizeof(uint32);
    616                 sal_memcpy(&(_BCM_TD2_ENDPOINT(unit, ii)->egress_if),
    617                            (*scache_ptr), sizeof(bcm_if_t));
    618                 (*scache_ptr) += (entry_size - sizeof(uint32));
    619             } else {
    620                 (*scache_ptr) += sizeof(uint32);
    621                 sal_memcpy(&(_BCM_TD2_ENDPOINT(unit, ii)->gport),
    622                            (*scache_ptr), sizeof(bcm_gport_t));
    623                 (*scache_ptr) += (entry_size - sizeof(uint32));
    624             }
    625         } else {
    626             (*scache_ptr) += entry_size;
    627         }
    628     }
    629 
    630     profile_mem = _BCM_TD2_ENDPOINT_COS_MAP_PROFILE(unit);
    631     profile_num = SOC_MEM_SIZE(unit, ENDPOINT_COS_MAPm) / _TD2_EPCM_ENTRIES_PER_SET;
    632     u16_scache_ptr = (uint16 *)(*scache_ptr);
    633 
    634     for (ii = 0; ii < profile_num; ii++) {
    635         for (ref_count = 0; ref_count < *u16_scache_ptr; ref_count++) {
    636             SOC_IF_ERROR_RETURN(
    637                 soc_profile_mem_reference(unit, profile_mem,
    638                                           ii * _TD2_EPCM_ENTRIES_PER_SET,
    639                                           _TD2_EPCM_ENTRIES_PER_SET));
    640         }
    641         u16_scache_ptr++;
    642     }
    643 
    644     *scache_ptr = (uint8 *)(u16_scache_ptr);
    645 
    646     return BCM_E_NONE;
    647 }
    648 
    649 int
    650 bcm_td2_cosq_reinit(int unit)
    651 {
    652     soc_scache_handle_t scache_handle;
    653     uint8 *scache_ptr;
    654     uint32 *u32_scache_ptr, *u32_base_ptr, *u32_base_ptr_1, wval, fval;
    655     uint16 *u16_scache_ptr = NULL;
    656     _bcm_td2_cosq_node_t *node;
    657     bcm_port_t port;
    658     int rv, ii, jj, set_index;
    659     _bcm_td2_cosq_node_t *nodes[3];
    660     int xnode_id, stable_size, node_size, count, pipe, profile_index;
    661     _bcm_td2_mmu_info_t *mmu_info;
    662     uint32 entry[SOC_MAX_MEM_WORDS];
    663     soc_profile_mem_t *profile_mem;
    664     _bcm_td2_pipe_resources_t *res;
    665     soc_mem_t mem;
    666     mmu_wred_config_entry_t qentry;
    667     int alloc_size;
    668     int incr_size = 0;
    669     uint16 recovered_ver = 0;
    670     int    node_list_sizes[3];
    671     int index=0;
    672     bcm_pbmp_t all_pbmp;
    673     soc_profile_reg_t *profile_reg;
    674     soc_info_t *si;
    675     bcm_port_t phy_port, mmu_port;
    676     soc_reg_t reg;
    677 	uint32 tmp32, scache_pbmp_size, pbmp_restore_size;
    678     uint64 rval, index_map;
    679     static const soc_reg_t llfc_cfgr[] = {
    680             PORT_PFC_CFG0r, PORT_PFC_CFG1r, PORT_PFC_CFG2r, PORT_PFC_CFG3r
    681     };
    682     int num;
    683     _bcm_td2_cosq_time_info_t tmp_timedomain;
    684     uint8 *u8_scache_ptr = NULL;
    685 
    686     si = &SOC_INFO(unit);
    687 
    688     SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size));
    689     if ((stable_size == 0) || (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit))) { 
    690         /* COSQ warmboot requires extended scache support i.e. level2 warmboot*/  
    691         return BCM_E_NONE;
    692     }
    693 
    694     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_COSQ, 0);
    695     rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 0, &scache_ptr,
    696                                  BCM_WB_DEFAULT_VERSION, &recovered_ver);
    697     if (BCM_FAILURE(rv)) {
    698         return rv;
    699     }
    700 
    701     mmu_info = _bcm_td2_mmu_info[unit];
    702 
    703     if (!mmu_info) {
    704         return BCM_E_INIT;
    705     }
    706 
    707     u32_scache_ptr = (uint32*) scache_ptr;
    708 
    709     nodes[0] = &mmu_info->queue_node[0];
    710     nodes[1] = &mmu_info->mc_queue_node[0];
    711     nodes[2] = &mmu_info->sched_node[0];
    712 
    713     u32_base_ptr = u32_scache_ptr;
    714     u32_base_ptr_1 = u32_scache_ptr;
    715     for(ii = 0; ii < 3; ii++) {
    716         count = *u32_scache_ptr;
    717         u32_scache_ptr++;
    718         for(jj = 0; jj < count; jj++) {
    719             wval = *u32_scache_ptr;
    720             u32_scache_ptr++;
    721             xnode_id = _BCM_TD2_WB_GET_NODE_ID_W1(wval);
    722             node = nodes[ii] + xnode_id;
    723             node->in_use = TRUE;
    724             node->numq = 1;
    725             node_size = _BCM_TD2_WB_GET_NODE_SIZE_W1(wval);
    726             fval =  _BCM_TD2_WB_GET_NODE_PARENT_W1(wval);
    727             if (fval & 0x800) {
    728             } else {
    729                 node->parent = &mmu_info->sched_node[fval];
    730                 if (node->parent->child) {
    731                     node->sibling = node->parent->child;
    732                 }
    733                 node->parent->child = node;
    734             }
    735 
    736             pipe = _BCM_TD2_WB_GET_PIPE_W1(wval);
    737             res = _BCM_TD2_PRESOURCES(mmu_info, pipe);
    738 
    739             wval = *u32_scache_ptr;
    740             u32_scache_ptr++;
    741             
    742             fval = _BCM_TD2_WB_GET_NODE_HW_INDEX_W2(wval);
    743             if (fval & 0x1000) {
    744                 node->hw_index = -1;
    745             } else {
    746                 node->hw_index = fval;
    747             }
    748 
    749             fval = _BCM_TD2_WB_GET_NODE_HW_COSQ_W2(wval);
    750             if (fval & 8) {
    751                 node->hw_cosq = -1;
    752             } else {
    753                 node->hw_cosq = fval;
    754             }
    755 
    756             fval = _BCM_TD2_WB_GET_NODE_COSQATTT_W2(wval);
    757             if (fval & 8) {
    758                 node->attached_to_input = -1;
    759             } else {
    760                 node->attached_to_input = fval;
    761             }
    762 
    763             node->level = _BCM_TD2_WB_GET_NODE_LEVEL_W2(wval);
    764 
    765             node->node_align_value = (_BCM_TD2_WB_GET_ALIGN_W2(wval) ? \
    766                                       _BCM_TD2_START_INDEX_ALIGN_PFC : \
    767                                       _BCM_TD2_START_INDEX_ALIGN_DEFAULT);
    768 
    769             wval = *u32_scache_ptr;
    770             u32_scache_ptr++;
    771             node->gport = wval;
    772             /*
    773              * Not checking the return value intentionally
    774              * to take care of warmboot case.
    775              */
    776             /* coverity[unchecked_value] */
    777             /* coverity[check_return] */
    778             _bcm_td2_cosq_node_get(unit, node->gport, 0, NULL,
    779                 &node->local_port, NULL, NULL);
    780 
    781             if (node->hw_index != -1) {
    782                 if (node->level == SOC_TD2_NODE_LVL_L0) {
    783                     _bcm_td2_node_index_set(&res->l0_sched_list, 
    784                                             node->hw_index, 1);
    785                 } else if (node->level == SOC_TD2_NODE_LVL_L1) {
    786                     _bcm_td2_node_index_set(&res->l1_sched_list, 
    787                                             node->hw_index, 1);
    788                 } else if (node->level == SOC_TD2_NODE_LVL_L2) {
    789                     _bcm_td2_node_index_set(&res->ext_qlist,
    790                                             node->hw_index, 1);
    791                 }
    792             }
    793 
    794             if (node_size > 3) {
    795                 wval = *u32_scache_ptr;
    796                 u32_scache_ptr++;
    797     
    798                 fval = _BCM_TD2_WB_GET_NODE_DEST_MODID_W4(wval);
    799                 if (fval & 0x100) {
    800                     node->remote_modid = -1;
    801                 } else {
    802                     node->remote_modid = fval;
    803                 }
    804 
    805                 fval = _BCM_TD2_WB_GET_NODE_DEST_PORT_W4(wval);
    806                 if (fval & 0x100) {
    807                     node->remote_port = -1;
    808                 } else {
    809                     node->remote_port = fval;
    810                 }
    811 
    812                 fval = _BCM_TD2_WB_GET_NODE_VOQ_COSQ_W4(wval);
    813                 if (fval & 0xf) {
    814                     node->hw_cosq = -1;
    815                 } else {
    816                     node->hw_cosq = fval;
    817                 }
    818             }
    819         }
    820     }
    821 
    822     /* Recovery TIME_DOMAINr field and count reference
    823      * Do not overwrite time_domian[i].field data,
    824      * TIME_0/1/2/3f(file value) itself can be changed during version update
    825      * Just update time_domain[i].ref_count */
    826     for (ii = 0; ii <  _TD2_NUM_TIME_DOMAIN; ii++) {
    827         sal_memset(&tmp_timedomain, 0, sizeof(tmp_timedomain));
    828         alloc_size =  sizeof(_bcm_td2_cosq_time_info_t);
    829         sal_memcpy(&tmp_timedomain, u32_scache_ptr, alloc_size);
    830         time_domain[ii].ref_count = tmp_timedomain.ref_count;
    831         u32_scache_ptr += alloc_size / sizeof(uint32);
    832     }
    833     soc_trident2_fc_map_shadow_load(unit, &u32_scache_ptr);
    834 
    835     node_list_sizes[0] = _BCM_TD2_NUM_L2_UC_LEAVES;
    836     node_list_sizes[1] = _BCM_TD2_NUM_L2_MC_LEAVES;
    837     node_list_sizes[2] = _BCM_TD2_NUM_TOTAL_SCHEDULERS;
    838     /* 1.In the vesion before BCM_WB_VERSION_1_1, the node->attached_to_input/
    839      * hw_cosq/numq were synced/recovered incorrectly(The range of them were
    840      * incorrect).
    841      * 2.The node->base_inde/base_size/_bcm_td2_mmu_info[unit]->ets_mode/
    842      * curr_shared_limit were not synced/recovered in the version before
    843      * BCM_WB_VERSION_1_1.
    844      */
    845     if (recovered_ver >= BCM_WB_VERSION_1_1) {
    846         for (ii = 0; ii < 3; ii++) {
    847             count = *u32_base_ptr++;
    848             for (jj = 0; jj < count; jj++) {
    849                 wval = *u32_base_ptr++;
    850                 xnode_id = _BCM_TD2_WB_GET_NODE_ID_W1(wval);
    851                 node = nodes[ii] + xnode_id;
    852                 node_size = _BCM_TD2_WB_GET_NODE_SIZE_W1(wval);
    853     
    854                 wval = *u32_scache_ptr++;
    855                 node->numq_expandable = _BCM_TD2_WB_GET_EXPAND_W5(wval);
    856                 node->type = _BCM_TD2_WB_TYPE_W5(wval);
    857     
    858                 fval = _BCM_TD2_WB_COSQ_W5(wval);
    859                 if (fval & 0x800) {
    860                     node->attached_to_input = -1;
    861                 } else {
    862                     node->attached_to_input = fval;
    863                 }
    864     
    865                 fval = _BCM_TD2_WB_HW_COSQ_W5(wval);
    866                 if (fval & 0x800) {
    867                     node->hw_cosq = -1;
    868                 } else {
    869                     node->hw_cosq = fval;
    870                 }
    871     
    872                 wval = *u32_scache_ptr++;
    873                 node->base_size = _BCM_TD2_WB_GET_BASE_SIZE_W6(wval);
    874                 fval = _BCM_TD2_WB_GET_NUMQ_W6(wval);
    875                 if (fval & 0x600) {
    876                     node->numq = -1;
    877                 } else {
    878                     node->numq = fval;
    879                 }
    880                 fval = _BCM_TD2_WB_GET_BASE_INDEX_W6(wval);
    881                 if (fval & 0x400) {
    882                     node->base_index = -1;
    883                 } else {
    884                     node->base_index = fval;
    885                 }
    886     
    887                 u32_base_ptr += 2;
    888                 if (node_size > 3) {
    889                     u32_base_ptr++;
    890                 }
    891             }
    892         }
    893     
    894         mmu_info->ets_mode = *u32_scache_ptr++;
    895         mmu_info->curr_shared_limit = *u32_scache_ptr++;
    896     } else {
    897         /* added in BCM_WB_VERSION_1_1
    898          * to sync _bcm_td2_mmu_info[unit]->hw_cosq/attached_to_input/
    899          * type/numq_expandable/numq/base_index/base_size
    900          */
    901         for (ii = 0; ii < 3; ii++) {
    902             for (jj = 0; jj < node_list_sizes[ii]; jj++) {
    903                 incr_size += 2 * sizeof(uint32);
    904             }
    905         }
    906 
    907         /* added in BCM_WB_VERSION_1_1
    908          * to sync _bcm_td2_mmu_info[unit]->ets_mode/curr_shared_limit
    909          */
    910         incr_size += 2 * sizeof(int);
    911     }
    912 
    913     if (recovered_ver >= BCM_WB_VERSION_1_2) {
    914         /* Update IFP_COS_MAP memory profile reference counter */
    915         profile_mem = _bcm_td2_ifp_cos_map_profile[unit];
    916         num = SOC_MEM_SIZE(unit,IFP_COS_MAPm) / _TD2_NUM_INTERNAL_PRI;
    917         u16_scache_ptr = (uint16 *)u32_scache_ptr;
    918         for (ii = 0; ii < num; ii++) {
    919             for (jj = 0; jj < *u16_scache_ptr; jj++) {
    920                 SOC_IF_ERROR_RETURN(
    921                     soc_profile_mem_reference(unit, profile_mem,
    922                                               ii * _TD2_NUM_INTERNAL_PRI,
    923                                               _TD2_NUM_INTERNAL_PRI));
    924             }
    925             u16_scache_ptr++;
    926         }
    927     } else {
    928         incr_size +=
    929             (SOC_MEM_SIZE(unit,IFP_COS_MAPm) / _TD2_NUM_INTERNAL_PRI) * 
    930              sizeof(uint16);
    931     }
    932 
    933     if (recovered_ver >= BCM_WB_VERSION_1_3) {
    934         profile_mem = _bcm_td2_service_cos_map_profile[unit];
    935         num = SOC_MEM_SIZE(unit, SERVICE_COS_MAPm) / _TD2_SCM_ENTRIES_PER_SET;
    936         for (ii = 0; ii < num; ii++) {
    937             for (jj = 0; jj < *u16_scache_ptr; jj++) {
    938                 SOC_IF_ERROR_RETURN(
    939                     soc_profile_mem_reference(unit, profile_mem,
    940                                               ii * _TD2_SCM_ENTRIES_PER_SET,
    941                                               _TD2_SCM_ENTRIES_PER_SET));
    942             }
    943             u16_scache_ptr++;
    944         }
    945 
    946         profile_mem = _bcm_td2_service_port_map_profile[unit];
    947         num = SOC_MEM_SIZE(unit, SERVICE_PORT_MAPm) / _TD2_SPM_ENTRIES_PER_SET;
    948         for (ii = 0; ii < num; ii++) {
    949             for (jj = 0; jj < *u16_scache_ptr; jj++) {
    950                 SOC_IF_ERROR_RETURN(
    951                     soc_profile_mem_reference(unit, profile_mem,
    952                                               ii * _TD2_SPM_ENTRIES_PER_SET,
    953                                               _TD2_SPM_ENTRIES_PER_SET));
    954             }
    955             u16_scache_ptr++;
    956         }
    957     } else {
    958         incr_size += sizeof(uint16) * SOC_MEM_SIZE(unit, SERVICE_COS_MAPm) /
    959                      _TD2_SCM_ENTRIES_PER_SET;
    960         incr_size += sizeof(uint16) * SOC_MEM_SIZE(unit, SERVICE_PORT_MAPm) /
    961                      _TD2_SPM_ENTRIES_PER_SET;
    962     }
    963 
    964     if (recovered_ver >= BCM_WB_VERSION_1_4) {
    965         u8_scache_ptr = (uint8 *)u16_scache_ptr;
    966         BCM_IF_ERROR_RETURN(soc_td2_mmu_traffic_ctrl_wb_restore(unit, &u8_scache_ptr));
    967     } else {
    968         BCM_IF_ERROR_RETURN(soc_td2_mmu_traffic_ctrl_size(unit, &incr_size));
    969     }
    970 
    971     /* Retriving num_cos value */
    972     if (recovered_ver >= BCM_WB_VERSION_1_5) {
    973         u32_scache_ptr = (uint32 *) u8_scache_ptr;
    974         NUM_COS(unit) = *u32_scache_ptr++;
    975     } else {
    976         incr_size += sizeof(int);
    977     }
    978 
    979     /* Retriving node->fabric_pbmp & mmu_info->curr_merger_index value */
    980     if (recovered_ver >= BCM_WB_VERSION_1_6) {
    981         scache_pbmp_size = *u32_scache_ptr++;
    982         u8_scache_ptr = (uint8 *)u32_scache_ptr;
    983         pbmp_restore_size = (scache_pbmp_size < sizeof(bcm_pbmp_t))? \
    984                             scache_pbmp_size : sizeof(bcm_pbmp_t);
    985         for (ii = 0; ii < 3; ii++) {
    986             count = *u32_base_ptr_1++;
    987             for (jj = 0; jj < count; jj++) {
    988                 wval = *u32_base_ptr_1++;
    989                 xnode_id = _BCM_TD2_WB_GET_NODE_ID_W1(wval);
    990                 node = nodes[ii] + xnode_id;
    991                 node_size = _BCM_TD2_WB_GET_NODE_SIZE_W1(wval);
    992     
    993                 sal_memcpy(&node->fabric_pbmp, u8_scache_ptr,
    994                            pbmp_restore_size);
    995                 u8_scache_ptr += scache_pbmp_size;
    996     
    997                 u32_base_ptr_1 += 2;
    998                 if (node_size > 3) {
    999                     u32_base_ptr_1++;
   1000                 }
   1001             }
   1002         }
   1003         u32_scache_ptr = (uint32 *)u8_scache_ptr;
   1004         mmu_info->curr_merger_index = *u32_scache_ptr++;
   1005     } else {
   1006         incr_size += sizeof(int);
   1007         for(ii = 0; ii < 3; ii++) {
   1008             incr_size += (node_list_sizes[ii] * sizeof(bcm_pbmp_t));
   1009         }
   1010         incr_size += sizeof(int);
   1011     }
   1012 
   1013     /* BCM_WB_VERSION_1_7 Sync endpoint info.
   1014      * In order to save scache, each entry size is fixed.
   1015      * entry_size = sizeof(uint32)+ sizeof(bcm_vrf_t) + sizeof(bcm_ip6_t).
   1016      * entry 0 was reserved and is not synced.
   1017      */
   1018     if (recovered_ver >= BCM_WB_VERSION_1_7) {
   1019         if (soc_feature(unit, soc_feature_endpoint_queuing)) {
   1020             u8_scache_ptr = (uint8 *)u32_scache_ptr;
   1021             BCM_IF_ERROR_RETURN(
   1022                 bcm_td2_cosq_endpoint_recover(unit, &u8_scache_ptr));
   1023         }
   1024     } else {
   1025         if (soc_feature(unit, soc_feature_endpoint_queuing)) {
   1026             incr_size += ((_BCM_TD2_NUM_ENDPOINT(unit) - 1) *
   1027                           (sizeof(uint32) + sizeof(bcm_vrf_t) + sizeof(bcm_ip6_t)));
   1028             incr_size += sizeof(uint16) * SOC_MEM_SIZE(unit, ENDPOINT_COS_MAPm) /
   1029                          _TD2_EPCM_ENTRIES_PER_SET;
   1030         }
   1031     }
   1032 
   1033     if (incr_size > 0) {
   1034         BCM_IF_ERROR_RETURN(
   1035             soc_scache_realloc(unit, scache_handle, incr_size));
   1036     }
   1037 
   1038     /* Update reference counts for DSCP_TABLE profile*/
   1039     BCM_PBMP_CLEAR(all_pbmp);
   1040     BCM_PBMP_ASSIGN(all_pbmp, PBMP_ALL(unit));
   1041 
   1042     PBMP_ITER(all_pbmp, port) {
   1043         if (IS_LB_PORT(unit, port)) {
   1044             /* Loopback port base starts from 64 */
   1045             continue;
   1046         }
   1047         SOC_IF_ERROR_RETURN(soc_mem_read(unit, PORT_TABm, MEM_BLOCK_ALL,
   1048                                           port, &entry));
   1049         index = soc_mem_field32_get(unit, PORT_TABm, &entry, TRUST_DSCP_PTRf);
   1050 
   1051         SOC_IF_ERROR_RETURN(_bcm_dscp_table_entry_reference(unit, index * 64,
   1052                                                             64));
   1053     }
   1054 
   1055     /* Update PORT_COS_MAP memory profile reference counter */
   1056     profile_mem = _bcm_td2_cos_map_profile[unit];
   1057     PBMP_ALL_ITER(unit, port) {
   1058         if (IS_LB_PORT(unit, port)) {
   1059             continue;
   1060         }
   1061         SOC_IF_ERROR_RETURN
   1062             (soc_mem_read(unit, COS_MAP_SELm, MEM_BLOCK_ALL, port, &entry));
   1063         set_index = soc_mem_field32_get(unit, COS_MAP_SELm, &entry, SELECTf);
   1064         SOC_IF_ERROR_RETURN
   1065             (soc_profile_mem_reference(unit, profile_mem, set_index * 16, 16));
   1066     }
   1067     if (SOC_INFO(unit).cpu_hg_index != -1) {
   1068         SOC_IF_ERROR_RETURN(soc_mem_read(unit, COS_MAP_SELm, MEM_BLOCK_ALL,
   1069                                          SOC_INFO(unit).cpu_hg_index, &entry));
   1070         set_index = soc_mem_field32_get(unit, COS_MAP_SELm, &entry, SELECTf);
   1071         SOC_IF_ERROR_RETURN
   1072             (soc_profile_mem_reference(unit, profile_mem, set_index * 16, 16));
   1073     }
   1074 
   1075     for (pipe = 0; pipe < 2; pipe++) {
   1076         mem = (pipe == _TD2_XPIPE) ? 
   1077                     MMU_WRED_CONFIG_X_PIPEm : MMU_WRED_CONFIG_Y_PIPEm;
   1078         for (ii = soc_mem_index_min(unit, mem);
   1079              ii <= soc_mem_index_max(unit, mem); ii++) {
   1080             BCM_IF_ERROR_RETURN(
   1081                   soc_mem_read(unit, mem, MEM_BLOCK_ALL, ii, &qentry));
   1082              
   1083             profile_index = soc_mem_field32_get(unit, mem, &qentry, PROFILE_INDEXf);
   1084              
   1085             BCM_IF_ERROR_RETURN
   1086                 (soc_profile_mem_reference(unit, _bcm_td2_wred_profile[pipe][unit],
   1087                                            profile_index, 1));
   1088         }
   1089     }
   1090 
   1091     /* Update PRIO2COS_LLFC register profile reference counter */
   1092     profile_reg = _bcm_td2_llfc_profile[unit];
   1093     PBMP_PORT_ITER(unit, port) {
   1094         phy_port = si->port_l2p_mapping[port];
   1095         mmu_port = si->port_p2m_mapping[phy_port];
   1096         if (mmu_port == -1) {
   1097             continue;
   1098         }
   1099         reg = llfc_cfgr[mmu_port/32];
   1100         BCM_IF_ERROR_RETURN(soc_reg64_get(unit, reg, 0, 0, &rval));
   1101 
   1102         index_map = soc_reg64_field_get(unit, reg, rval, PROFILE_INDEXf);
   1103         COMPILER_64_SHR(index_map, ((mmu_port % 32) * 2));
   1104         COMPILER_64_TO_32_LO(tmp32, index_map);
   1105         set_index = (tmp32 & 3);
   1106         SOC_IF_ERROR_RETURN
   1107             (soc_profile_reg_reference(unit, profile_reg, set_index * 16, 16));
   1108     }
   1109     
   1110     return BCM_E_NONE;
   1111 }
   1112 
   1113 /*
   1114  * Function:
   1115  *      bcm_td2_cosq_endpoint_sync
   1116  * Purpose:
   1117  *      Sync endpoint info to scache.
   1118  * Parameters:
   1119  *      unit       - (IN)     StrataSwitch unit #
   1120  *      scache_ptr - (IN/OUT) Scache pointer
   1121  * Returns:
   1122  *      BCM_E_xxx
   1123  */
   1124 STATIC int
   1125 bcm_td2_cosq_endpoint_sync(int unit, uint8 **scache_ptr)
   1126 {
   1127     uint32 endpoint_flags, entry_size;
   1128     int ii;
   1129     int profile_num;
   1130     soc_profile_mem_t *profile_mem;
   1131     uint16 *u16_scache_ptr;
   1132     int ref_count;
   1133     int rv = BCM_E_NONE;
   1134 
   1135     /* entry 0 was reserved and is not synced. */
   1136     entry_size = sizeof(uint32)+ sizeof(bcm_vrf_t) + sizeof(bcm_ip6_t);
   1137     for (ii = 1; ii < _BCM_TD2_NUM_ENDPOINT(unit); ii++) {
   1138         if (_BCM_TD2_ENDPOINT_IS_USED(unit, ii)) {
   1139             endpoint_flags = _BCM_TD2_ENDPOINT(unit, ii)->flags;
   1140             if (endpoint_flags & BCM_COSQ_CLASSIFIER_L2) {
   1141                 sal_memcpy((*scache_ptr), &endpoint_flags, sizeof(uint32));
   1142                 (*scache_ptr) += sizeof(uint32);
   1143                 sal_memcpy((*scache_ptr), &(_BCM_TD2_ENDPOINT(unit, ii)->vlan),
   1144                            sizeof(bcm_vlan_t));
   1145                 (*scache_ptr) += sizeof(bcm_vlan_t);
   1146                 sal_memcpy((*scache_ptr), _BCM_TD2_ENDPOINT(unit, ii)->mac,
   1147                            sizeof(bcm_mac_t));
   1148                 (*scache_ptr) += (entry_size - sizeof(uint32) - sizeof(bcm_vlan_t));
   1149             } else if (endpoint_flags & BCM_COSQ_CLASSIFIER_L3) {
   1150                 sal_memcpy((*scache_ptr), &endpoint_flags, sizeof(uint32));
   1151                 (*scache_ptr) += sizeof(uint32);
   1152                 sal_memcpy((*scache_ptr), &(_BCM_TD2_ENDPOINT(unit, ii)->vrf),
   1153                            sizeof(bcm_vrf_t));
   1154                 (*scache_ptr) += sizeof(bcm_vrf_t);
   1155                 if (endpoint_flags & BCM_COSQ_CLASSIFIER_IP6) {
   1156                     sal_memcpy((*scache_ptr),
   1157                                _BCM_TD2_ENDPOINT(unit, ii)->ip6_addr,
   1158                                sizeof(bcm_ip6_t));
   1159                 } else {
   1160                     sal_memcpy((*scache_ptr),
   1161                                &(_BCM_TD2_ENDPOINT(unit, ii)->ip_addr),
   1162                                sizeof(bcm_ip_t));
   1163                 }
   1164                 (*scache_ptr) += (entry_size - sizeof(uint32) - sizeof(bcm_vrf_t));
   1165             } else if (endpoint_flags & BCM_COSQ_CLASSIFIER_GPORT) {
   1166                 sal_memcpy((*scache_ptr), &endpoint_flags, sizeof(uint32));
   1167                 (*scache_ptr) += sizeof(uint32);
   1168                 sal_memcpy((*scache_ptr), &(_BCM_TD2_ENDPOINT(unit, ii)->gport),
   1169                            sizeof(bcm_gport_t));
   1170                 (*scache_ptr) += (entry_size - sizeof(uint32));
   1171             } else if (endpoint_flags & BCM_COSQ_CLASSIFIER_L3_EGRESS) {
   1172                 sal_memcpy((*scache_ptr), &endpoint_flags, sizeof(uint32));
   1173                 (*scache_ptr) += sizeof(uint32);
   1174                 sal_memcpy((*scache_ptr), &(_BCM_TD2_ENDPOINT(unit, ii)->egress_if),
   1175                            sizeof(bcm_if_t));
   1176                 (*scache_ptr) += (entry_size - sizeof(uint32));
   1177             } else {
   1178                 return BCM_E_INTERNAL;
   1179             }
   1180         } else {
   1181             sal_memset((*scache_ptr), 0, entry_size);
   1182             (*scache_ptr) += entry_size;
   1183         }
   1184     }
   1185 
   1186     u16_scache_ptr = (uint16 *)(*scache_ptr);
   1187 
   1188     profile_num = SOC_MEM_SIZE(unit, ENDPOINT_COS_MAPm) /
   1189                   _TD2_EPCM_ENTRIES_PER_SET;
   1190     profile_mem = _BCM_TD2_ENDPOINT_COS_MAP_PROFILE(unit);
   1191     for (ii = 0; ii < profile_num; ii++) {
   1192         ref_count = 0;
   1193         rv = soc_profile_mem_ref_count_get(
   1194                  unit, profile_mem, ii * _TD2_EPCM_ENTRIES_PER_SET, &ref_count);
   1195         if (!(rv == SOC_E_NOT_FOUND || rv == SOC_E_NONE)) {
   1196             return rv;
   1197         }
   1198         *u16_scache_ptr++ = (uint16)(ref_count & 0xffff);
   1199     }
   1200     *scache_ptr = (uint8 *)u16_scache_ptr;
   1201 
   1202     return BCM_E_NONE;
   1203 }
   1204 
   1205 int
   1206 bcm_td2_cosq_sync(int unit)
   1207 {
   1208     soc_scache_handle_t scache_handle;
   1209     uint8 *scache_ptr, *u8_scache_ptr;
   1210     uint32 *u32_scache_ptr;
   1211     uint16 *u16_scache_ptr;
   1212     _bcm_td2_cosq_node_t *node;
   1213     int node_list_sizes[3], ii, jj, cosq;
   1214     _bcm_td2_cosq_node_t *nodes[3];
   1215     int xnode_id, node_size, count, pipe;
   1216     uint32 *psize;
   1217     _bcm_td2_mmu_info_t *mmu_info;
   1218     int alloc_size;
   1219     int rv = BCM_E_NONE;
   1220     int ref_count;
   1221     int profile_num;
   1222     soc_profile_mem_t *profile_mem;
   1223 
   1224     mmu_info = _bcm_td2_mmu_info[unit];
   1225 
   1226     if (!mmu_info) {
   1227         return BCM_E_INIT;
   1228     }
   1229     if ((SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit))) { 
   1230         /* COSQ warmboot requires extended scache support i.e. level2 warmboot*/  
   1231         return BCM_E_NONE;
   1232     }
   1233     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_COSQ, 0);
   1234     BCM_IF_ERROR_RETURN
   1235         (_bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 0,
   1236                                  &scache_ptr, BCM_WB_DEFAULT_VERSION, NULL));
   1237 
   1238     u32_scache_ptr = (uint32*) scache_ptr;
   1239 
   1240     nodes[0] = &mmu_info->queue_node[0];
   1241     node_list_sizes[0] = _BCM_TD2_NUM_L2_UC_LEAVES;
   1242     nodes[1] = &mmu_info->mc_queue_node[0];
   1243     node_list_sizes[1] = _BCM_TD2_NUM_L2_MC_LEAVES;
   1244     nodes[2] = &mmu_info->sched_node[0];
   1245     node_list_sizes[2] = _BCM_TD2_NUM_TOTAL_SCHEDULERS;
   1246 
   1247     for(ii = 0; ii < 3; ii++) {
   1248         psize = u32_scache_ptr++;
   1249         for(count = 0, jj = 0; jj < node_list_sizes[ii]; jj++) {
   1250             node = nodes[ii] + jj;
   1251             if (node->in_use == FALSE) {
   1252                 continue;
   1253             }
   1254             count += 1;
   1255             node_size = 3;
   1256             if ((node->remote_modid != -1) || (node->remote_port != -1) ||
   1257                 (node->hw_cosq != -1)) {
   1258                 node_size += 1;
   1259             }
   1260             
   1261             if (node->parent == NULL) {
   1262                 xnode_id = 0x800;
   1263             } else {
   1264                 xnode_id = _BCM_TD2_NODE_ID(node->parent, mmu_info->sched_node);
   1265             }
   1266 
   1267             pipe = _BCM_TD2_PORT_TO_PIPE(unit, node->local_port);
   1268 
   1269             *u32_scache_ptr++ = _BCM_TD2_WB_SET_NODE_W1(ii, jj, node_size, xnode_id, pipe);
   1270             cosq = ((node->attached_to_input == -1) ? 0x8 : node->attached_to_input);
   1271 
   1272             *u32_scache_ptr++ = _BCM_TD2_WB_SET_NODE_W2(
   1273                    (node->hw_index == -1) ? 0x1000 : node->hw_index,
   1274                     ((node->hw_cosq == -1) ? 8 : node->hw_cosq), cosq, node->level,
   1275                     ((node->node_align_value == _BCM_TD2_START_INDEX_ALIGN_PFC) ? 1 : 0));
   1276 
   1277             *u32_scache_ptr++ = _BCM_TD2_WB_SET_NODE_W3(node->gport);
   1278 
   1279             if ((node->remote_modid != -1) || (node->remote_port != -1) ||
   1280                 (node->hw_cosq != -1)) {
   1281                 node_size += 1;
   1282                 *u32_scache_ptr++ = _BCM_TD2_WB_SET_NODE_W4(
   1283                     (node->remote_modid == -1) ? 0x100 : node->remote_modid,
   1284                     (node->remote_port == -1) ? 0x100 : node->remote_port,
   1285                     (node->hw_cosq == -1) ? 0x8 : node->hw_cosq);
   1286             }
   1287         }
   1288         *psize = count;
   1289     }
   1290     
   1291     /* Sync TIME_DOMAINr field and count reference */
   1292     alloc_size = _TD2_NUM_TIME_DOMAIN * sizeof(_bcm_td2_cosq_time_info_t);
   1293     sal_memcpy(u32_scache_ptr, &time_domain[0], alloc_size);
   1294     u32_scache_ptr += alloc_size / sizeof(uint32);
   1295     soc_trident2_fc_map_shadow_sync(unit, &u32_scache_ptr);
   1296 
   1297     for (ii = 0; ii < 3; ii++) {
   1298         for (count = 0, jj = 0; jj < node_list_sizes[ii]; jj++) {
   1299             node = nodes[ii] + jj;
   1300             if (node->in_use == FALSE) {
   1301                 continue;
   1302             }
   1303 
   1304             *u32_scache_ptr++ = _BCM_TD2_WB_SET_NODE_W5(
   1305                 (node->numq_expandable), (node->type),
   1306                 ((node->attached_to_input == -1) ? 0x800 : 
   1307                                              node->attached_to_input),
   1308                 ((node->hw_cosq == -1) ? 0x800 : node->hw_cosq));
   1309 
   1310             *u32_scache_ptr++ = _BCM_TD2_WB_SET_NODE_W6(
   1311                 (node->base_size),
   1312                 ((node->base_index == -1 ) ? 0x400 : node->base_index),
   1313                 ((node->numq == -1 ) ? 0x600 : node->numq));
   1314         }
   1315     }
   1316     
   1317     *u32_scache_ptr++ = mmu_info->ets_mode;
   1318     *u32_scache_ptr++ = mmu_info->curr_shared_limit;
   1319 
   1320     u16_scache_ptr = (uint16 *)u32_scache_ptr;
   1321     for (ii = 0; 
   1322          ii < (SOC_MEM_SIZE(unit, IFP_COS_MAPm) / _TD2_NUM_INTERNAL_PRI);
   1323          ii++) {
   1324         rv = soc_profile_mem_ref_count_get(unit, 
   1325                                            _bcm_td2_ifp_cos_map_profile[unit],
   1326                                            ii * _TD2_NUM_INTERNAL_PRI,
   1327                                            &ref_count);
   1328         if (!(rv == SOC_E_NOT_FOUND || rv == SOC_E_NONE)) {
   1329             return rv;
   1330         }
   1331         *u16_scache_ptr++ = (uint16)(ref_count & 0xffff);
   1332     }
   1333 
   1334     profile_num = SOC_MEM_SIZE(unit, SERVICE_COS_MAPm) /
   1335                   _TD2_SCM_ENTRIES_PER_SET;
   1336     profile_mem = _bcm_td2_service_cos_map_profile[unit];
   1337     for (ii = 0; ii < profile_num; ii++) {
   1338         ref_count = 0;
   1339         rv = soc_profile_mem_ref_count_get(
   1340                  unit, profile_mem, ii * _TD2_SCM_ENTRIES_PER_SET, &ref_count);
   1341         if (!(rv == SOC_E_NOT_FOUND || rv == SOC_E_NONE)) {
   1342             return rv;
   1343         }
   1344         *u16_scache_ptr++ = (uint16)(ref_count & 0xffff);
   1345     }
   1346 
   1347     profile_num = SOC_MEM_SIZE(unit, SERVICE_PORT_MAPm) /
   1348                   _TD2_SPM_ENTRIES_PER_SET;
   1349     profile_mem = _bcm_td2_service_port_map_profile[unit];
   1350     for (ii = 0; ii < profile_num; ii++) {
   1351         ref_count = 0;
   1352         rv = soc_profile_mem_ref_count_get(
   1353                  unit, profile_mem, ii * _TD2_SPM_ENTRIES_PER_SET, &ref_count);
   1354         if (!(rv == SOC_E_NOT_FOUND || rv == SOC_E_NONE)) {
   1355             return rv;
   1356         }
   1357         *u16_scache_ptr++ = (uint16)(ref_count & 0xffff);
   1358     }
   1359     
   1360     scache_ptr = (uint8 *)u16_scache_ptr;
   1361     
   1362     BCM_IF_ERROR_RETURN(soc_td2_mmu_traffic_ctrl_wb_sync(unit, &scache_ptr));
   1363 
   1364     u32_scache_ptr = (uint32 *) scache_ptr;
   1365     *u32_scache_ptr++ = NUM_COS(unit);
   1366     scache_ptr = (uint8*)u32_scache_ptr;
   1367 
   1368     /* BCM_WB_VERSION_1_6: Sync DMVOQ fabric parameter & curr_merger_index. */
   1369     *u32_scache_ptr++ = sizeof(bcm_pbmp_t);
   1370     u8_scache_ptr = (uint8 *)u32_scache_ptr;
   1371     for (ii = 0; ii < 3; ii++) {
   1372         for (count = 0, jj = 0; jj < node_list_sizes[ii]; jj++) {
   1373             node = nodes[ii] + jj;
   1374             if (node->in_use == FALSE) {
   1375                 continue;
   1376             }
   1377             sal_memcpy(u8_scache_ptr, &node->fabric_pbmp, sizeof(bcm_pbmp_t));
   1378             u8_scache_ptr += sizeof(bcm_pbmp_t);
   1379         }
   1380     }
   1381     u32_scache_ptr = (uint32 *)u8_scache_ptr;
   1382     *u32_scache_ptr++ = mmu_info->curr_merger_index;
   1383 
   1384     /* BCM_WB_VERSION_1_7 Sync endpoint info.
   1385      * In order to save scache, each entry size is fixed.
   1386      * entry_size = sizeof(uint32)+ sizeof(bcm_vrf_t) + sizeof(bcm_ip6_t).
   1387      * entry 0 was reserved and is not synced.
   1388      */
   1389     if (soc_feature(unit, soc_feature_endpoint_queuing)) {
   1390         u8_scache_ptr = (uint8 *)u32_scache_ptr;
   1391         BCM_IF_ERROR_RETURN(
   1392             bcm_td2_cosq_endpoint_sync(unit, &u8_scache_ptr));
   1393     }
   1394 
   1395     return BCM_E_NONE;
   1396 }
   1397 
   1398 #endif /* BCM_WARM_BOOT_SUPPORT */
   1399 
   1400 #ifndef BCM_SW_STATE_DUMP_DISABLE
   1401 STATIC char*
   1402 _bcm_td2_cosq_node_lvl_str(soc_td2_node_lvl_e lvl)
   1403 {
   1404     switch(lvl) {
   1405         case SOC_TD2_NODE_LVL_ROOT:
   1406             return "Root";
   1407             break;
   1408         case SOC_TD2_NODE_LVL_L0:
   1409             return " L0";
   1410             break;
   1411         case SOC_TD2_NODE_LVL_L1:
   1412             return "  L1";
   1413             break;
   1414         case SOC_TD2_NODE_LVL_L2:
   1415             return "   Q";
   1416             break;
   1417         case SOC_TD2_NODE_LVL_MAX:
   1418             break;
   1419     }
   1420     return "";
   1421 }
   1422 
   1423 STATIC void
   1424 _bcm_td2_cosq_dump_node(_bcm_td2_cosq_node_t *node, int loff)
   1425 {
   1426     LOG_CLI((BSL_META("%s.%d index=%d cosq=%d gport=0x%08x numq=%d\n"),
   1427                 _bcm_td2_cosq_node_lvl_str(node->level),
   1428                         loff,
   1429                         node->hw_index,
   1430                         node->attached_to_input,
   1431                         node->gport,
   1432                         node->numq));
   1433 
   1434     if (node->child) {
   1435         _bcm_td2_cosq_dump_node(node->child, 0);
   1436     }
   1437 
   1438     if (node->sibling) {
   1439         _bcm_td2_cosq_dump_node(node->sibling, loff+1);
   1440     }
   1441 }
   1442 
   1443 STATIC void
   1444 _bcm_td2_cosq_port_sw_dump(int unit, bcm_port_t port)
   1445 {
   1446     _bcm_td2_mmu_info_t *mmu_info;
   1447     int phy_port, mmu_port;
   1448     soc_info_t *si;
   1449     bcm_port_t local_port;
   1450     int rv;
   1451     _bcm_td2_cosq_node_t *node = NULL;
   1452 
   1453     si = &SOC_INFO(unit);
   1454     mmu_info = _bcm_td2_mmu_info[unit];
   1455 
   1456     phy_port = si->port_l2p_mapping[port];
   1457 
   1458     if (phy_port == -1) {
   1459         return;
   1460     }
   1461 
   1462     mmu_port = si->port_p2m_mapping[phy_port];
   1463 
   1464     if (mmu_port == -1) {
   1465         return;
   1466     }
   1467 
   1468     rv = _bcm_td2_cosq_localport_resolve(unit, port, &local_port);
   1469     if (BCM_FAILURE(rv) || (local_port < 0)) {
   1470         return;
   1471     }
   1472     node = &mmu_info->sched_node[local_port];
   1473 
   1474     if (node == NULL) {
   1475         return;
   1476     }
   1477 
   1478     LOG_CLI((BSL_META("Logical Port: %d, Physical Port: %d\n"),
   1479                         port,
   1480                         phy_port));
   1481 
   1482     _bcm_td2_cosq_dump_node(node, 0);
   1483 
   1484     return;
   1485 }
   1486 #endif /* BCM_SW_STATE_DUMP_DISABLEP */
   1487 
   1488 /*
   1489  * Function:
   1490  *     bcm_td2_cosq_sw_dump
   1491  * Purpose:
   1492  *     Displays COS Queue information maintained by software.
   1493  * Parameters:
   1494  *     unit - Device unit number
   1495  * Returns:
   1496  *     None
   1497  */
   1498 void
   1499 bcm_td2_cosq_sw_dump(int unit)
   1500 {
   1501 #ifndef BCM_SW_STATE_DUMP_DISABLE
   1502     bcm_port_t port;
   1503 
   1504     PBMP_ALL_ITER(unit, port) {
   1505         _bcm_td2_cosq_port_sw_dump(unit, port);
   1506     }
   1507 #endif
   1508     return;
   1509 }
   1510 
   1511 /*
   1512  * Function:
   1513  *     _bcm_td2_cosq_localport_resolve
   1514  * Purpose:
   1515  *     Resolve GRPOT if it is a local port
   1516  * Parameters:
   1517  *     unit       - (IN) unit number
   1518  *     gport      - (IN) GPORT identifier
   1519  *     local_port - (OUT) local port number
   1520  * Returns:
   1521  *     BCM_E_XXX
   1522  */
   1523 int
   1524 _bcm_td2_cosq_localport_resolve(int unit, bcm_gport_t gport,
   1525                                bcm_port_t *local_port)
   1526 {
   1527     bcm_module_t module;
   1528     bcm_port_t port;
   1529     bcm_trunk_t trunk;
   1530     int id, result;
   1531 
   1532     if (!BCM_GPORT_IS_SET(gport)) {
   1533         if (!SOC_PORT_VALID(unit, gport)) {
   1534             return BCM_E_PORT;
   1535         }
   1536         *local_port = gport;
   1537         return BCM_E_NONE;
   1538     }
   1539 
   1540     BCM_IF_ERROR_RETURN
   1541         (_bcm_esw_gport_resolve(unit, gport, &module, &port, &trunk, &id));
   1542 
   1543     BCM_IF_ERROR_RETURN(_bcm_esw_modid_is_local(unit, module, &result));
   1544     if (result == FALSE) {
   1545         return BCM_E_PARAM;
   1546     }
   1547 
   1548     *local_port = port;
   1549 
   1550     return BCM_E_NONE;
   1551 }
   1552 
   1553 STATIC int
   1554 _bcm_td2_cosq_port_has_ets(int unit, bcm_port_t port)
   1555 {
   1556     _bcm_td2_mmu_info_t *mmu_info = _bcm_td2_mmu_info[unit];
   1557     return mmu_info->ets_mode;
   1558 }
   1559 
   1560 /*
   1561  * Function:
   1562  *     _bcm_td2_node_index_get
   1563  * Purpose:
   1564  *     Allocate free index from the given list
   1565  * Parameters:
   1566  *     list       - (IN) bit list
   1567  *     start      - (IN) start index
   1568  *     end        - (IN) end index
   1569  *     qset       - (IN) size of queue set
   1570  *     range      - (IN) range bits
   1571  *     id         - (OUT) start index
   1572  * Returns:
   1573  *     BCM_E_XXX
   1574  */
   1575 STATIC int
   1576 _bcm_td2_node_index_get(SHR_BITDCL *list, int start, int end,
   1577                        int count, int align, int *id)
   1578 {
   1579     int i, j, range_empty;
   1580 
   1581     *id = -1;
   1582 
   1583     if ((align <= 0) || (count == 0)) {
   1584         return BCM_E_PARAM;
   1585     }
   1586 
   1587     if (start & (align - 1)) {
   1588         start = (start + align - 1) & ~(align - 1);
   1589     }
   1590 
   1591     end = end - align + 1;
   1592 
   1593     for (i = start; i < end; i += align) {
   1594         range_empty = 1;
   1595         if ((i + count) <= end){
   1596             for (j = i; j < (i + count); j++) {
   1597                 if (SHR_BITGET(list, j) != 0) {
   1598                     range_empty = 0;
   1599                     break;
   1600                 }
   1601             }
   1602 
   1603             if (range_empty) {
   1604                 *id = i;
   1605                 return BCM_E_NONE;
   1606             }
   1607         } else {
   1608             return BCM_E_RESOURCE;
   1609         }
   1610     }
   1611     return BCM_E_RESOURCE;
   1612 }
   1613 
   1614 /*
   1615  * Function:
   1616  *     _bcm_td2_node_index_set
   1617  * Purpose:
   1618  *     Mark indices as allocated
   1619  * Parameters:
   1620  *     list       - (IN) bit list
   1621  *     start      - (IN) start index
   1622  *     range      - (IN) range bits
   1623  * Returns:
   1624  *     BCM_E_XXX
   1625  */
   1626 STATIC int
   1627 _bcm_td2_node_index_set(_bcm_td2_cosq_list_t *list, int start, int range)
   1628 {
   1629     if (range == 0) {
   1630         return BCM_E_NONE;
   1631     }
   1632     if ((start < 0) ||
   1633         (range < 0) ||
   1634         ((start + range) > list->count)) {
   1635         return BCM_E_INTERNAL;
   1636     }
   1637     SHR_BITSET_RANGE(list->bits, start, range);
   1638 
   1639     return BCM_E_NONE;
   1640 }
   1641 
   1642 /*
   1643  * Function:
   1644  *     _bcm_td2_node_index_clear
   1645  * Purpose:
   1646  *     Mark indices as free
   1647  * Parameters:
   1648  *     list       - (IN) bit list
   1649  *     start      - (IN) start index
   1650  *     range      - (IN) range bits
   1651  * Returns:
   1652  *     BCM_E_XXX
   1653  */
   1654 STATIC int
   1655 _bcm_td2_node_index_clear(_bcm_td2_cosq_list_t *list, int start, int range)
   1656 {
   1657     if (range == 0) {
   1658         return BCM_E_NONE;
   1659     }
   1660     if ((start < 0) ||
   1661         (range < 0) ||
   1662         ((start + range) > list->count)) {
   1663         return BCM_E_INTERNAL;
   1664     }
   1665     SHR_BITCLR_RANGE(list->bits, start, range);
   1666 
   1667     return BCM_E_NONE;
   1668 }
   1669 
   1670 /*
   1671  * Function:
   1672  *     _bcm_td2_cosq_alloc_clear
   1673  * Purpose:
   1674  *     Allocate cosq memory and clear
   1675  * Parameters:
   1676  *     size       - (IN) size of memory required
   1677  *     description- (IN) description about the structure
   1678  * Returns:
   1679  *     BCM_E_XXX
   1680  */
   1681 STATIC void *
   1682 _bcm_td2_cosq_alloc_clear(void *cp, unsigned int size, char *description)
   1683 {
   1684     void *block_p;
   1685 
   1686     block_p = (cp) ? cp : sal_alloc(size, description);
   1687 
   1688     if (block_p != NULL) {
   1689         sal_memset(block_p, 0, size);
   1690     }
   1691 
   1692     return block_p;
   1693 }
   1694 
   1695 /*
   1696  * Function:
   1697  *     _bcm_td2_cosq_free_memory
   1698  * Purpose:
   1699  *     Free memory allocated for mmu info members
   1700  * Parameters:
   1701  *     mmu_info       - (IN) MMU info pointer
   1702  * Returns:
   1703  *     BCM_E_XXX
   1704  */
   1705 STATIC void
   1706 _bcm_td2_cosq_free_memory(_bcm_td2_mmu_info_t *mmu_info_p)
   1707 {
   1708     int pipe;
   1709     _bcm_td2_pipe_resources_t *res;
   1710 
   1711     if (mmu_info_p == NULL) {
   1712         return;
   1713     }
   1714     for (pipe = _TD2_XPIPE; pipe <= _TD2_YPIPE; pipe++) {
   1715         res = _BCM_TD2_PRESOURCES(mmu_info_p, pipe);
   1716         if (res->ext_qlist.bits != NULL) {
   1717             sal_free(res->ext_qlist.bits);
   1718             res->ext_qlist.bits = NULL;
   1719         }
   1720         if (res->l0_sched_list.bits != NULL) {
   1721             sal_free(res->l0_sched_list.bits);
   1722             res->l0_sched_list.bits = NULL;
   1723         }
   1724         if (res->l1_sched_list.bits != NULL) {
   1725             sal_free(res->l1_sched_list.bits);
   1726             res->l1_sched_list.bits = NULL;
   1727         }
   1728     }
   1729 }
   1730 
   1731 /*
   1732  * Function:
   1733  *     _bcm_td2_cosq_node_get
   1734  * Purpose:
   1735  *     Get internal information of queue group or scheduler type GPORT
   1736  * Parameters:
   1737  *     unit       - (IN) unit number
   1738  *     gport      - (IN) queue group/scheduler GPORT identifier
   1739  *     modid      - (OUT) module identifier
   1740  *     port       - (OUT) port number
   1741  *     id         - (OUT) queue group or scheduler identifier
   1742  *     node       - (OUT) node structure for the specified GPORT
   1743  * Returns:
   1744  *     BCM_E_XXX
   1745  */
   1746 STATIC int
   1747 _bcm_td2_cosq_node_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
   1748                        bcm_module_t *modid, bcm_port_t *port, 
   1749                        int *id, _bcm_td2_cosq_node_t **node)
   1750 {
   1751     _bcm_td2_mmu_info_t *mmu_info;
   1752     _bcm_td2_cosq_node_t *node_base = NULL;
   1753     bcm_module_t modid_out = 0;
   1754     bcm_port_t port_out = 0;
   1755     uint32 encap_id = -1;
   1756     int index;
   1757 
   1758     if ((mmu_info = _bcm_td2_mmu_info[unit]) == NULL) {
   1759         return BCM_E_INIT;
   1760     }
   1761 
   1762     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   1763         BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid_out));
   1764         port_out = BCM_GPORT_UCAST_QUEUE_GROUP_SYSPORTID_GET(gport);
   1765     } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   1766         BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid_out));
   1767         port_out = BCM_GPORT_MCAST_QUEUE_GROUP_SYSPORTID_GET(gport);
   1768     } else if (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport)) {
   1769         BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid_out));
   1770         port_out = (gport >> 16) & 0xff;
   1771     } else if (BCM_GPORT_IS_SCHEDULER(gport)) {
   1772         BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid_out));
   1773         port_out = BCM_GPORT_SCHEDULER_GET(gport) & 0xff;
   1774     } else if (BCM_GPORT_IS_LOCAL(gport)) {
   1775         encap_id = BCM_GPORT_LOCAL_GET(gport);
   1776         port_out = encap_id;
   1777     } else if (BCM_GPORT_IS_MODPORT(gport)) {
   1778         modid_out = SOC_GPORT_MODPORT_MODID_GET(gport);
   1779         port_out = SOC_GPORT_MODPORT_PORT_GET(gport);
   1780         encap_id = port_out;
   1781     } else {
   1782         return BCM_E_PORT;
   1783     }
   1784 
   1785     if (!SOC_PORT_VALID(unit, port_out)) {
   1786         return BCM_E_PORT;
   1787     }
   1788 
   1789     if (port != NULL) {
   1790         *port = port_out;
   1791     }
   1792 
   1793     if (!_bcm_td2_cosq_port_has_ets(unit, port_out)) {
   1794         return BCM_E_NOT_FOUND;
   1795     }
   1796 
   1797     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   1798         encap_id = BCM_GPORT_UCAST_QUEUE_GROUP_QID_GET(gport);
   1799         index = encap_id;
   1800         node_base = mmu_info->queue_node;
   1801     } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   1802         encap_id = BCM_GPORT_MCAST_QUEUE_GROUP_QID_GET(gport);
   1803         index = encap_id;
   1804         node_base = mmu_info->mc_queue_node;
   1805     } else if (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport)) {
   1806         encap_id = BCM_GPORT_UCAST_SUBSCRIBER_QUEUE_GROUP_QID_GET(gport);
   1807         index = encap_id;
   1808         node_base = mmu_info->queue_node;
   1809     } else if (BCM_GPORT_IS_SCHEDULER(gport)) {
   1810         encap_id = (BCM_GPORT_SCHEDULER_GET(gport) >> 8) & 0x3fff;
   1811         index = encap_id;
   1812         node_base = mmu_info->sched_node;
   1813     } else {
   1814         index = encap_id;
   1815         node_base = mmu_info->sched_node;
   1816     }
   1817 
   1818     if (index < 0) {
   1819         return BCM_E_NOT_FOUND;
   1820     }
   1821 
   1822     if (node_base[index].numq == 0) {
   1823         return BCM_E_NOT_FOUND;
   1824     }
   1825 
   1826     if (modid != NULL) {
   1827         *modid = modid_out;
   1828     }
   1829     if (id != NULL) {
   1830         *id = encap_id;
   1831     }
   1832     if (node != NULL) {
   1833         *node = &node_base[index];
   1834         if (*node) {
   1835             _bcm_td2_cosq_node_t *tmp_node;
   1836             tmp_node = *node;
   1837             if (tmp_node->type == _BCM_TD2_NODE_SERVICE_UCAST) {
   1838                 *node = &node_base[index + cosq];
   1839                 if (id != NULL) {
   1840                     *id = tmp_node->hw_index;
   1841                 }
   1842             }
   1843         }
   1844  
   1845     }
   1846 
   1847     return BCM_E_NONE;
   1848 }
   1849 
   1850 int
   1851 _bcm_td2_cosq_port_resolve(int unit, bcm_gport_t gport, bcm_module_t *modid,
   1852                           bcm_port_t *port, bcm_trunk_t *trunk_id, int *id,
   1853                           int *qnum)
   1854 {
   1855     _bcm_td2_cosq_node_t *node;
   1856 
   1857     BCM_IF_ERROR_RETURN
   1858         (_bcm_td2_cosq_node_get(unit, gport, 0, modid, port, id, &node));
   1859     *trunk_id = -1;
   1860 
   1861     if (qnum) {
   1862         if (node->hw_index == -1) {
   1863             return BCM_E_PARAM;
   1864         }
   1865         *qnum = node->hw_index;
   1866     }
   1867 
   1868     return BCM_E_NONE;
   1869 }
   1870 
   1871 /*
   1872  * Function:
   1873  *     _bcm_td2_cosq_gport_traverse
   1874  * Purpose:
   1875  *     Walks through the valid COSQ GPORTs and calls
   1876  *     the user supplied callback function for each entry.
   1877  * Parameters:
   1878  *     unit       - (IN) unit number
   1879  *     gport      - (IN)
   1880  *     cb         - (IN) Callback function.
   1881  *     user_data  - (IN) User data to be passed to callback function
   1882  * Returns:
   1883  *     BCM_E_NONE - Success.
   1884  *     BCM_E_XXX
   1885  */
   1886 int
   1887 _bcm_td2_cosq_gport_traverse(int unit, bcm_gport_t gport,
   1888                             bcm_cosq_gport_traverse_cb cb,
   1889                             void *user_data)
   1890 {
   1891     _bcm_td2_cosq_node_t *node;
   1892     uint32 flags = BCM_COSQ_GPORT_SCHEDULER;
   1893     int rv = BCM_E_NONE;
   1894 
   1895     BCM_IF_ERROR_RETURN
   1896         (_bcm_td2_cosq_node_get(unit, gport, 0, NULL, NULL, NULL, &node));
   1897 
   1898     if (node != NULL) {
   1899         if (node->level == SOC_TD2_NODE_LVL_L2) {
   1900             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(node->gport)) {
   1901                 flags = BCM_COSQ_GPORT_UCAST_QUEUE_GROUP;
   1902             } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(node->gport)) {
   1903                 flags = BCM_COSQ_GPORT_MCAST_QUEUE_GROUP;
   1904             }
   1905         } else {
   1906             flags = BCM_COSQ_GPORT_SCHEDULER;
   1907             if (node->node_align_value == _BCM_TD2_START_INDEX_ALIGN_PFC) {
   1908                 flags |= BCM_COSQ_GPORT_SCHEDULER_PFC_ALIGN;
   1909             }
   1910         }
   1911         rv = cb(unit, gport, node->numq, flags,
   1912                   node->gport, user_data);
   1913        if (BCM_FAILURE(rv)) {
   1914 #ifdef BCM_CB_ABORT_ON_ERR
   1915            if (SOC_CB_ABORT_ON_ERR(unit)) {
   1916                return rv;
   1917            }
   1918 #endif
   1919        }
   1920     } else {
   1921             return BCM_E_NONE;
   1922     }
   1923 
   1924     if (node->sibling != NULL) {
   1925         _bcm_td2_cosq_gport_traverse(unit, node->sibling->gport, cb, user_data);
   1926     }
   1927 
   1928     if (node->child != NULL) {
   1929         _bcm_td2_cosq_gport_traverse(unit, node->child->gport, cb, user_data);
   1930     }
   1931 
   1932     return BCM_E_NONE;
   1933 }
   1934 
   1935 STATIC int
   1936 _bcm_td2_cosq_child_node_at_input(_bcm_td2_cosq_node_t *node, int cosq,
   1937                                   _bcm_td2_cosq_node_t **child_node)
   1938 {
   1939     _bcm_td2_cosq_node_t *cur_node;
   1940 
   1941     for (cur_node = node->child; cur_node; cur_node = cur_node->sibling) {
   1942         if (cur_node->attached_to_input == cosq) {
   1943             break;
   1944         }
   1945     }
   1946     if (!cur_node) {
   1947         return BCM_E_NOT_FOUND;
   1948     }
   1949 
   1950     *child_node = cur_node;
   1951 
   1952     return BCM_E_NONE;
   1953 }
   1954 
   1955 STATIC int
   1956 _bcm_td2_cosq_l2_gport(int unit, int port, int cosq,
   1957                        _bcm_td2_node_type_e type, bcm_gport_t *gport,
   1958                        _bcm_td2_cosq_node_t **p_node)
   1959 {
   1960     int i, max;
   1961     _bcm_td2_cosq_node_t *node, *fnode;
   1962     _bcm_td2_mmu_info_t *mmu_info;
   1963     _bcm_td2_cosq_port_info_t *port_info;
   1964     _bcm_td2_pipe_resources_t *res;
   1965 
   1966     mmu_info = _bcm_td2_mmu_info[unit];
   1967     port_info = &mmu_info->port_info[port];
   1968     res = port_info->resources;
   1969     
   1970     max  = 0;
   1971     if ((type == _BCM_TD2_NODE_UCAST) || (type == _BCM_TD2_NODE_VOQ) ||
   1972         (type == _BCM_TD2_NODE_VLAN_UCAST) || (type == _BCM_TD2_NODE_VM_UCAST) ||
   1973          (type == _BCM_TD2_NODE_SERVICE_UCAST)) {
   1974         max = _BCM_TD2_NUM_L2_UC_LEAVES;
   1975         fnode = &res->p_queue_node[0];
   1976     } else if (type == _BCM_TD2_NODE_MCAST) {
   1977         max = _BCM_TD2_NUM_L2_MC_LEAVES;
   1978         fnode = &res->p_mc_queue_node[0];
   1979     } else {
   1980         return BCM_E_PARAM;
   1981     }
   1982 
   1983     for (i = 0; i < max; i++) {
   1984         node = fnode + i;
   1985         if (node->in_use && (node->local_port == port) &&
   1986             (node->type == type) && (node->hw_cosq == cosq)) {
   1987             if (gport) {
   1988                 *gport = node->gport;
   1989             }
   1990             if (p_node) {
   1991                 *p_node = node;
   1992             }
   1993             return BCM_E_NONE;
   1994         }
   1995     }
   1996     return BCM_E_NOT_FOUND;
   1997 }
   1998 
   1999 /*
   2000  * Function:
   2001  *     _bcm_td2_cosq_index_resolve
   2002  * Purpose:
   2003  *     Find hardware index for the given port/cosq
   2004  * Parameters:
   2005  *     unit       - (IN) unit number
   2006  *     port       - (IN) port number or GPORT identifier
   2007  *     cosq       - (IN) COS queue number
   2008  *     style      - (IN) index style (_BCM_KA_COSQ_INDEX_STYLE_XXX)
   2009  *     local_port - (OUT) local port number
   2010  *     index      - (OUT) result index
   2011  *     count      - (OUT) number of index
   2012  * Returns:
   2013  *     BCM_E_XXX
   2014  */
   2015 int
   2016 _bcm_td2_cosq_index_resolve(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 
   2017                            _bcm_td2_cosq_index_style_t style,                 
   2018                            bcm_port_t *local_port, int *index, int *count)
   2019 {
   2020     _bcm_td2_cosq_node_t *node, *cur_node;
   2021     bcm_port_t resolved_port;
   2022     int resolved_index = -1;
   2023     int id, startq, numq;
   2024     soc_info_t *si;
   2025     int phy_port, mmu_port, mmu_port_pipe_off;
   2026     uint32 entry0[SOC_MAX_MEM_WORDS];
   2027     soc_mem_t mem;
   2028 
   2029     si = &SOC_INFO(unit);
   2030 
   2031     if (cosq < -1) {
   2032         return BCM_E_PARAM;
   2033     } else if (cosq == -1) {
   2034         startq = 0;
   2035         numq = NUM_COS(unit);
   2036     } else {
   2037         startq = cosq;
   2038         numq = 1;
   2039     }
   2040 
   2041     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 
   2042         BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) ||
   2043         BCM_GPORT_IS_SCHEDULER(port)) {
   2044         BCM_IF_ERROR_RETURN
   2045             (_bcm_td2_cosq_node_get(unit, port, cosq, NULL, &resolved_port, &id,
   2046                                    &node));
   2047         if (node->attached_to_input < 0) { /* Not resolved yet */
   2048             return BCM_E_NOT_FOUND;
   2049         }
   2050         numq = (node->numq != -1) ? node->numq : 64;
   2051     } else {
   2052         /* optionally validate port */
   2053         BCM_IF_ERROR_RETURN
   2054             (_bcm_td2_cosq_localport_resolve(unit, port, &resolved_port));
   2055         if (resolved_port < 0) {
   2056             return BCM_E_PORT;
   2057         }
   2058         node = NULL;
   2059         numq = (IS_CPU_PORT(unit, resolved_port)) ? NUM_CPU_COSQ(unit) : NUM_COS(unit);
   2060     }
   2061 
   2062     if (startq >= numq) {
   2063         return BCM_E_PARAM;
   2064     }
   2065 
   2066     phy_port = si->port_l2p_mapping[resolved_port];
   2067     mmu_port = si->port_p2m_mapping[phy_port];
   2068     mmu_port_pipe_off = (mmu_port >= 64) ? mmu_port - 64 : mmu_port;
   2069 
   2070     if ((node == NULL) && (BCM_GPORT_IS_MODPORT(port)) &&
   2071         (_bcm_td2_cosq_port_has_ets(unit, resolved_port))) {
   2072         BCM_IF_ERROR_RETURN(_bcm_td2_cosq_node_get(unit, port, 0, 
   2073                                                     NULL, NULL, NULL, &node));
   2074     }
   2075     
   2076     switch (style) {
   2077     case _BCM_TD2_COSQ_INDEX_STYLE_BUCKET:
   2078         if (node != NULL) {
   2079             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) {
   2080                 resolved_index = node->hw_index;
   2081             } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
   2082                 resolved_index = node->hw_index;
   2083             } else if (BCM_GPORT_IS_SCHEDULER(port) || BCM_GPORT_IS_MODPORT(port)) {
   2084                 /* resolve the child attached to input cosq */
   2085                 BCM_IF_ERROR_RETURN(
   2086                    _bcm_td2_cosq_child_node_at_input(node, startq, &cur_node));
   2087                 resolved_index = cur_node->hw_index;
   2088             } else {
   2089                 return BCM_E_PARAM;
   2090             }
   2091         } else { /* node == NULL */
   2092             if (_bcm_td2_cosq_port_has_ets(unit, resolved_port)) {
   2093                 LOG_ERROR(BSL_LS_BCM_COSQ,
   2094                     (BSL_META_U(unit, "Not a GPORT type port in ETS mode.\n")));
   2095                 return BCM_E_PARAM;
   2096             }
   2097             if (IS_CPU_PORT(unit, resolved_port)) {
   2098                 resolved_index = SOC_INFO(unit).port_cosq_base[resolved_port] +
   2099                                  startq;
   2100                 resolved_index = soc_td2_l2_hw_index(unit, resolved_index, 0);
   2101             } else {
   2102                 BCM_IF_ERROR_RETURN(soc_td2_sched_hw_index_get(unit, 
   2103                                      resolved_port, SOC_TD2_NODE_LVL_L1, 
   2104                                      startq, &resolved_index));
   2105             }
   2106         }
   2107         break;
   2108 
   2109     case _BCM_TD2_COSQ_INDEX_STYLE_QCN:
   2110         if (node != NULL) {
   2111             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) {
   2112                 resolved_index = node->hw_index;
   2113             } else {
   2114                 return BCM_E_PARAM;
   2115             }
   2116         } else { /* node == NULL */
   2117             BCM_IF_ERROR_RETURN(_bcm_td2_cosq_port_has_ets(unit, resolved_port));
   2118             if (IS_CPU_PORT(unit, resolved_port)) {
   2119                 return BCM_E_PARAM;
   2120             } else {
   2121                 resolved_index = soc_td2_l2_hw_index(unit,
   2122                 si->port_uc_cosq_base[resolved_port] + startq, 1);
   2123             }
   2124         }
   2125         break;
   2126 
   2127     case _BCM_TD2_COSQ_INDEX_STYLE_WRED:
   2128         if (node != NULL) {
   2129             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) {
   2130                 resolved_index = node->hw_index + startq;
   2131             } else if (BCM_GPORT_IS_SCHEDULER(port)) {
   2132                 BCM_IF_ERROR_RETURN(
   2133                    _bcm_td2_cosq_child_node_at_input(node, startq, &cur_node));
   2134                 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(cur_node->gport)) {
   2135                     resolved_index = cur_node->hw_index;
   2136                 } else {
   2137                     return BCM_E_PARAM;
   2138                 }
   2139             } else if (BCM_GPORT_IS_MODPORT(port)) {
   2140                 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_l2_gport(unit, node->local_port, 
   2141                                    startq, _BCM_TD2_NODE_UCAST, NULL, &cur_node));
   2142                 resolved_index = cur_node->hw_index;
   2143             } else {
   2144                 return BCM_E_PARAM;
   2145             }
   2146         } else { /* node == NULL */
   2147             BCM_IF_ERROR_RETURN(_bcm_td2_cosq_port_has_ets(unit, resolved_port));
   2148             resolved_index = soc_td2_l2_hw_index(unit,
   2149                 si->port_uc_cosq_base[resolved_port] + startq, 1);
   2150             numq = 1;
   2151         }
   2152         break;
   2153 
   2154     case _BCM_TD2_COSQ_INDEX_STYLE_WRED_PORT:
   2155         resolved_index = 1616 + (mmu_port_pipe_off*4);
   2156         numq = 4;
   2157         break;
   2158 
   2159     case _BCM_TD2_COSQ_INDEX_STYLE_WRED_POOL:
   2160         if ((node != NULL) && (!BCM_GPORT_IS_MODPORT(port))) {
   2161             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) {
   2162                     /* regular unicast queue */
   2163                 resolved_index = soc_td2_l2_hw_index(unit, node->hw_index + startq, 1);
   2164             } else {
   2165                 return BCM_E_PARAM;
   2166             }
   2167         } else { /* node == NULL */
   2168             numq = si->port_num_uc_cosq[resolved_port];
   2169             if (startq >= numq) {
   2170                 return BCM_E_PARAM;
   2171             }
   2172             resolved_index = soc_td2_l2_hw_index(unit,
   2173                     si->port_uc_cosq_base[resolved_port] + startq, 1);
   2174         }
   2175         mem = SOC_TD2_PMEM(unit, resolved_port,
   2176                 MMU_THDU_XPIPE_Q_TO_QGRP_MAPm, MMU_THDU_YPIPE_Q_TO_QGRP_MAPm);
   2177         SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, resolved_index,
   2178                             entry0));
   2179 
   2180         resolved_index = soc_mem_field32_get(unit, mem, entry0, Q_SPIDf);
   2181 
   2182         break;
   2183 
   2184     case _BCM_TD2_COSQ_INDEX_STYLE_SCHEDULER:
   2185         if (node != NULL) {
   2186             if (!BCM_GPORT_IS_SCHEDULER(port)) {
   2187                 return BCM_E_PARAM;
   2188             }
   2189             BCM_IF_ERROR_RETURN(
   2190                 _bcm_td2_cosq_child_node_at_input(node, startq, &cur_node));
   2191             resolved_index = cur_node->hw_index;
   2192         } else { /* node == NULL */
   2193             BCM_IF_ERROR_RETURN(_bcm_td2_cosq_port_has_ets(unit, resolved_port));
   2194             if (IS_CPU_PORT(unit, resolved_port)) {
   2195                 resolved_index = soc_td2_l2_hw_index(unit,
   2196                 si->port_cosq_base[resolved_port] + startq, 0);
   2197             } else {
   2198                 BCM_IF_ERROR_RETURN(soc_td2_sched_hw_index_get(unit, 
   2199                                     resolved_port, SOC_TD2_NODE_LVL_L1, startq, 
   2200                                     &resolved_index));
   2201             }
   2202         }
   2203         break;
   2204 
   2205     case _BCM_TD2_COSQ_INDEX_STYLE_COS:
   2206         if (node) {
   2207             if ((BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) ||
   2208                 (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port))) {
   2209                 resolved_index = node->hw_cosq;
   2210             } else if (BCM_GPORT_IS_SCHEDULER(port)) {
   2211                 BCM_IF_ERROR_RETURN(
   2212                    _bcm_td2_cosq_child_node_at_input(node, startq, &cur_node));
   2213                 if (BCM_GPORT_IS_SCHEDULER(cur_node->gport)) {
   2214                     return BCM_E_PARAM;
   2215                 }
   2216                 resolved_index = cur_node->hw_cosq;
   2217             }
   2218         } else {
   2219             BCM_IF_ERROR_RETURN(_bcm_td2_cosq_port_has_ets(unit, resolved_port));
   2220             resolved_index = startq;
   2221         }
   2222         break;
   2223 
   2224     case _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE:
   2225     case _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE_GROUP:
   2226         if (IS_CPU_PORT(unit, resolved_port) ||
   2227             IS_LB_PORT(unit, resolved_port)) {
   2228             return BCM_E_PARAM;
   2229         }
   2230         if (node) {
   2231             resolved_index = node->hw_index + startq;
   2232             numq = 1;
   2233         } else {
   2234             /* Not support -1 for queue group index resolving, as group may not consecutive */
   2235             if ((cosq == -1) &&
   2236                 (style == _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE_GROUP)) {
   2237                 return BCM_E_PARAM;
   2238             }
   2239             BCM_IF_ERROR_RETURN(_bcm_td2_cosq_port_has_ets(unit, resolved_port));
   2240             numq = 1;
   2241             resolved_index = soc_td2_l2_hw_index(unit,
   2242                 si->port_uc_cosq_base[resolved_port] + startq, 1);
   2243         }
   2244         if (style == _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE_GROUP) {
   2245             mem = SOC_TD2_PMEM(unit, resolved_port, MMU_THDU_XPIPE_Q_TO_QGRP_MAPm,
   2246                                            MMU_THDU_YPIPE_Q_TO_QGRP_MAPm);
   2247             SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL,
   2248                                              resolved_index, entry0));
   2249             if (soc_mem_field32_get(unit, mem, entry0, QGROUP_VALIDf)) {
   2250                 resolved_index = soc_mem_field32_get(unit, mem, entry0, QGROUPf);
   2251             } else {
   2252                 return BCM_E_NOT_FOUND;
   2253             }
   2254         }
   2255         break;
   2256 
   2257     case _BCM_TD2_COSQ_INDEX_STYLE_MCAST_QUEUE:
   2258         if (node) {
   2259             resolved_index = node->hw_index + startq;
   2260             numq = 1;
   2261         } else {
   2262             BCM_IF_ERROR_RETURN(_bcm_td2_cosq_port_has_ets(unit, resolved_port));
   2263             numq = 1;
   2264             resolved_index = soc_td2_l2_hw_index(unit, 
   2265                 si->port_cosq_base[resolved_port] + startq, 0);
   2266         }
   2267         break;
   2268 
   2269     case _BCM_TD2_COSQ_INDEX_STYLE_EGR_POOL:
   2270         if ((node != NULL) && (!BCM_GPORT_IS_MODPORT(port))) {
   2271             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) {
   2272                     /* regular unicast queue */
   2273                 resolved_index = soc_td2_l2_hw_index(unit, node->hw_index + startq, 1);
   2274                 mem = SOC_TD2_PMEM(unit, resolved_port, 
   2275                         MMU_THDU_XPIPE_Q_TO_QGRP_MAPm, MMU_THDU_YPIPE_Q_TO_QGRP_MAPm);
   2276             } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
   2277                 resolved_index = soc_td2_l2_hw_index(unit,
   2278                     si->port_cosq_base[resolved_port] + startq, 0) - 1480;
   2279                 mem = SOC_TD2_PMEM(unit, resolved_port, 
   2280                         MMU_THDM_MCQE_QUEUE_CONFIG_0m, MMU_THDM_MCQE_QUEUE_CONFIG_1m);
   2281             } else { /* scheduler */
   2282                 return BCM_E_PARAM;
   2283             }
   2284         } else { /* node == NULL */
   2285             numq = si->port_num_cosq[resolved_port];
   2286             if (startq >= numq) {
   2287                 return BCM_E_PARAM;
   2288             }
   2289             resolved_index = soc_td2_l2_hw_index(unit, 
   2290                     si->port_cosq_base[resolved_port] + startq, 0) - 1480;
   2291             mem = SOC_TD2_PMEM(unit, resolved_port, 
   2292                     MMU_THDM_MCQE_QUEUE_CONFIG_0m, MMU_THDM_MCQE_QUEUE_CONFIG_1m);
   2293         }
   2294 
   2295         SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, resolved_index,
   2296                             entry0));
   2297 
   2298         resolved_index = soc_mem_field32_get(unit, mem, entry0, Q_SPIDf);
   2299 
   2300         break;
   2301 
   2302     case _BCM_TD2_COSQ_INDEX_STYLE_UC_EGR_POOL:
   2303         if (IS_CPU_PORT(unit, resolved_port) ||
   2304             IS_LB_PORT(unit, resolved_port)) {
   2305             return BCM_E_PARAM;
   2306         }
   2307 
   2308         numq = si->port_num_uc_cosq[resolved_port];
   2309         if (startq >= numq) {
   2310             return BCM_E_PARAM;
   2311         }
   2312 
   2313         resolved_index = soc_td2_l2_hw_index(unit,
   2314                 si->port_uc_cosq_base[resolved_port] + startq, 1);
   2315         mem = SOC_TD2_PMEM(unit, resolved_port, 
   2316                 MMU_THDU_XPIPE_Q_TO_QGRP_MAPm, MMU_THDU_YPIPE_Q_TO_QGRP_MAPm);
   2317 
   2318         SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, resolved_index,
   2319                             entry0));
   2320 
   2321         resolved_index = soc_mem_field32_get(unit, mem, entry0, Q_SPIDf);
   2322         break;
   2323 
   2324     case _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_UCAST:
   2325         if (node) {
   2326             resolved_index = node->hw_index + startq;
   2327             resolved_index -= soc_td2_l2_hw_index(unit,
   2328                 si->port_uc_cosq_base[resolved_port], 1);
   2329             numq = 1;
   2330         } else {
   2331             BCM_IF_ERROR_RETURN(_bcm_td2_cosq_port_has_ets(unit, resolved_port));
   2332             numq = 1;
   2333             resolved_index = startq;
   2334         }
   2335         break;
   2336 
   2337     case _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_MCAST:
   2338         if (node) {
   2339             resolved_index = node->hw_index + startq;
   2340             resolved_index -= soc_td2_l2_hw_index(unit,
   2341                 si->port_cosq_base[resolved_port], 0);
   2342             numq = 1;
   2343         } else {
   2344             BCM_IF_ERROR_RETURN(_bcm_td2_cosq_port_has_ets(unit, resolved_port));
   2345             numq = 1;
   2346             resolved_index = startq;
   2347         }
   2348         break;
   2349 
   2350     default:
   2351         return BCM_E_INTERNAL;
   2352     }
   2353 
   2354     if (local_port != NULL) {
   2355         *local_port = resolved_port;
   2356     }
   2357     if (index != NULL) {
   2358         *index = resolved_index;
   2359     }
   2360     if (count != NULL) {
   2361         *count = (cosq == -1) ? numq : 1;
   2362     }
   2363 
   2364     return BCM_E_NONE;
   2365 }
   2366 
   2367 STATIC int _bcm_td2_cosq_min_child_index(_bcm_td2_cosq_node_t *child, int lvl, int uc)
   2368 {
   2369     int min_index = -1;
   2370 
   2371     if ((lvl == SOC_TD2_NODE_LVL_L2) && (uc)) {
   2372         while (child) {
   2373             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(child->gport)) {
   2374                 if (min_index == -1) {
   2375                     min_index = child->hw_index;
   2376                 }
   2377                 
   2378                 if (child->hw_index < min_index) {
   2379                     min_index = child->hw_index;
   2380                 }
   2381             }
   2382             child = child->sibling;
   2383         }
   2384     } else if ((lvl == SOC_TD2_NODE_LVL_L2) && (!uc)) {
   2385         while (child) {
   2386             if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(child->gport)) {
   2387                 if (min_index == -1) {
   2388                     min_index = child->hw_index;
   2389                 }
   2390                 
   2391                 if (child->hw_index < min_index) {
   2392                     min_index = child->hw_index;
   2393                 }
   2394             }
   2395             child = child->sibling;
   2396         }
   2397     } else {
   2398         while (child) {
   2399             if (min_index == -1) {
   2400                 min_index = child->hw_index;
   2401             }
   2402             
   2403             if (child->hw_index < min_index) {
   2404                 min_index = child->hw_index;
   2405             }
   2406             child = child->sibling;
   2407         }
   2408     }
   2409 
   2410     return min_index;
   2411 }
   2412 
   2413 STATIC int
   2414 _bcm_td2_child_state_check(int unit, bcm_port_t gport,
   2415                            bcm_cos_queue_t cosq, int ets_mode)
   2416 {
   2417     _bcm_td2_cosq_node_t *node, *child_node = NULL;
   2418     bcm_port_t local_port;
   2419     int level, sch_index, empty = 0;
   2420     int rv = BCM_E_NONE;
   2421     soc_timeout_t timeout;
   2422     uint32 timeout_val;
   2423     uint32 entry[SOC_MAX_MEM_WORDS];
   2424     soc_mem_t mem = INVALIDm;
   2425     static const soc_mem_t memx[] = {
   2426         INVALIDm,
   2427         ES_PIPE0_LLS_L0_CHILD_STATE1m,
   2428         ES_PIPE0_LLS_L1_CHILD_STATE1m,
   2429         ES_PIPE0_LLS_L2_CHILD_STATE1m
   2430     };
   2431     static const soc_mem_t memy[] = {
   2432         INVALIDm,
   2433         ES_PIPE1_LLS_L0_CHILD_STATE1m,
   2434         ES_PIPE1_LLS_L1_CHILD_STATE1m,
   2435         ES_PIPE1_LLS_L2_CHILD_STATE1m
   2436     };
   2437 
   2438     /* Timeout val = Static for now. Need to quantify the max wait time */
   2439     timeout_val = 2000000;
   2440 
   2441     BCM_IF_ERROR_RETURN
   2442         (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port));
   2443 
   2444     if (ets_mode & (!IS_TD2_HSP_PORT(unit, local_port))) {
   2445         BCM_IF_ERROR_RETURN
   2446             (_bcm_td2_cosq_node_get(unit, gport, 0, NULL,
   2447                                     &local_port, NULL, &node));
   2448 
   2449         /* Get the Child node for the Given Gport */
   2450         rv = _bcm_td2_cosq_child_node_at_input(node, cosq, &child_node);
   2451 
   2452         if ((!child_node) || (rv == BCM_E_NOT_FOUND)) {
   2453             /* No Child present */
   2454             return BCM_E_NONE;
   2455         }
   2456 
   2457         BCM_IF_ERROR_RETURN
   2458             (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port));
   2459 
   2460         level = child_node->level;
   2461         sch_index = child_node->hw_index;
   2462 
   2463         /* Child State Check is NOT necessary for Non-L0/L1/L2 levels */
   2464         if ((level < SOC_TD2_NODE_LVL_L0) || (level > SOC_TD2_NODE_LVL_L2)) {
   2465             /* Sanity for Node's level should be done in the caller */
   2466             return BCM_E_NONE;
   2467         }
   2468 
   2469         mem = SOC_TD2_PMEM(unit, local_port, memx[level], memy[level]); 
   2470 
   2471         if (mem == INVALIDm) {
   2472             return BCM_E_INTERNAL;
   2473         }
   2474 
   2475         soc_timeout_init(&timeout, timeout_val, 0);
   2476 
   2477         for(;;) {
   2478             BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL,
   2479                                              sch_index, entry));
   2480             empty = 0;
   2481             if (soc_timeout_check(&timeout)) {
   2482                 LOG_ERROR(BSL_LS_BCM_COMMON,
   2483                           (BSL_META_U(unit,
   2484                                       "ERROR: Timeout during Child lists Not zero\n")));
   2485                 return BCM_E_BUSY;
   2486             }
   2487             empty += soc_mem_field32_get(unit, mem, &entry, C_ON_ACTIVE_LISTf);
   2488             empty += soc_mem_field32_get(unit, mem, &entry, C_ON_MIN_LISTf);
   2489             empty += soc_mem_field32_get(unit, mem, &entry, C_NOT_EMPTYf);
   2490 
   2491             if (!empty) {
   2492                 break;
   2493             }
   2494         }
   2495     } else {
   2496         /* TBD: Need to implement for Non-ETS mode */
   2497         return BCM_E_NONE;
   2498     }
   2499 
   2500     return BCM_E_NONE;
   2501 }
   2502 
   2503 
   2504 STATIC int
   2505 _bcm_td2_cosq_node_queue_state_check(int unit, 
   2506         _bcm_td2_cosq_node_t *node, int ets_mode)
   2507 {
   2508     int cosq = 0;
   2509     
   2510     if (node == NULL) {
   2511         return BCM_E_PARAM;
   2512     }
   2513 
   2514     for (cosq = 0; cosq < node->numq; cosq++) {
   2515         BCM_IF_ERROR_RETURN
   2516             (_bcm_td2_child_state_check(unit, node->gport,
   2517                                           cosq, ets_mode));
   2518     }
   2519 
   2520     if ((node->level <= SOC_TD2_NODE_LVL_L1) &&
   2521         (node->child != NULL)) {
   2522         BCM_IF_ERROR_RETURN
   2523             (_bcm_td2_cosq_node_queue_state_check(unit,
   2524                                  node->child,ets_mode));
   2525     }
   2526         
   2527     if (node->sibling != NULL) {
   2528 
   2529         BCM_IF_ERROR_RETURN
   2530             (_bcm_td2_cosq_node_queue_state_check(unit,
   2531                                node->sibling,ets_mode));
   2532     }
   2533 
   2534     return BCM_E_NONE;
   2535 }
   2536 
   2537 int 
   2538 _bcm_td2_cosq_port_queue_state_check(int unit, bcm_port_t gport)
   2539 {
   2540     bcm_port_t local_port;
   2541     int   ets_mode;
   2542     _bcm_td2_cosq_node_t *node;
   2543 
   2544     BCM_IF_ERROR_RETURN
   2545         (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port));
   2546     ets_mode = _bcm_td2_cosq_port_has_ets(unit, local_port);
   2547     if (!ets_mode) {
   2548         return BCM_E_NONE;
   2549     }
   2550     
   2551     BCM_IF_ERROR_RETURN
   2552         (bcm_esw_port_gport_get(unit, local_port,
   2553                                          &gport));
   2554 
   2555     BCM_IF_ERROR_RETURN
   2556         (_bcm_td2_cosq_node_get(unit, gport, 0, NULL, 
   2557                                   NULL, NULL, &node));
   2558     
   2559     BCM_IF_ERROR_RETURN
   2560         (_bcm_td2_cosq_node_queue_state_check(unit,
   2561                                     node,ets_mode));
   2562     return BCM_E_NONE;
   2563 }
   2564 
   2565 /*
   2566  * Function:
   2567  *     _bcm_td2_dynamic_sched_update_begin
   2568  * Purpose:
   2569  *     Set settings to enable Dynamic Sched update.
   2570  * Parameters:
   2571  *     unit       - (IN) unit number
   2572  *     port       - (IN) Port
   2573  * Returns:
   2574  *     BCM_E_XXX
   2575  */
   2576 STATIC int
   2577 _bcm_td2_dynamic_sched_update_begin(int unit, bcm_port_t gport,
   2578                                     bcm_cos_queue_t cosq)
   2579 {
   2580     int ets_mode = 0;
   2581     int rv = BCM_E_NONE;
   2582     bcm_port_t local_port;
   2583 
   2584     if (SAL_BOOT_SIMULATION) {
   2585        return BCM_E_NONE;
   2586     }
   2587 
   2588     BCM_IF_ERROR_RETURN
   2589         (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port));
   2590 
   2591     SOC_IF_ERROR_RETURN(
   2592         soc_td2_port_traffic_egr_enable_set(unit, local_port, 0));
   2593 
   2594     /* CPU port and loopback port need no cell drain to happen */
   2595     if (!IS_CPU_PORT(unit, local_port) && !IS_LB_PORT(unit, local_port)) {
   2596         /* Drain the cells assoiciated to the port */
   2597         _bcm_td2_port_drain_cells(unit, local_port);
   2598     }
   2599 
   2600     ets_mode = _bcm_td2_cosq_port_has_ets(unit, local_port);
   2601     /* Poll Child state to verify if Child is still in Parent list */
   2602     rv = _bcm_td2_child_state_check(unit, gport, cosq, ets_mode);
   2603     if (rv != BCM_E_NONE) {
   2604         /* Logging the Error. Not stopping the flow for now. */
   2605         LOG_ERROR(BSL_LS_BCM_COMMON,
   2606                   (BSL_META_U(unit,
   2607                               "ERROR: During Child State Check(rv %d)\n"),
   2608                    rv));
   2609     }
   2610     return BCM_E_NONE;
   2611 }
   2612 
   2613 STATIC int
   2614 _bcm_td2_dynamic_sched_reset_thd(int unit, bcm_port_t gport,
   2615                                  bcm_cos_queue_t cosq, int ets_mode)
   2616 {
   2617     _bcm_td2_cosq_node_t *node, *child_node = NULL;
   2618     bcm_port_t local_port;
   2619     int level, sch_index;
   2620     int rv = BCM_E_NONE;
   2621     uint32 entry[SOC_MAX_MEM_WORDS];
   2622     soc_mem_t mem = INVALIDm;
   2623     static const soc_mem_t memx[] = {
   2624         INVALIDm,
   2625         MMU_MTRO_L0_MEM_0m,
   2626         MMU_MTRO_L1_MEM_0m,
   2627         MMU_MTRO_L2_MEM_0m
   2628     };
   2629     static const soc_mem_t memy[] = {
   2630         INVALIDm,
   2631         MMU_MTRO_L0_MEM_1m,
   2632         MMU_MTRO_L1_MEM_1m,
   2633         MMU_MTRO_L2_MEM_1m
   2634     };
   2635 
   2636     BCM_IF_ERROR_RETURN
   2637         (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port));
   2638 
   2639     if (ets_mode & (!IS_TD2_HSP_PORT(unit, local_port))) {
   2640         uint32 min_thd = 0;
   2641         uint32 max_thd = 0;
   2642 
   2643         BCM_IF_ERROR_RETURN
   2644             (_bcm_td2_cosq_node_get(unit, gport, 0, NULL,
   2645                                     &local_port, NULL, &node));
   2646 
   2647         /* Get the Child node for the Given Gport */
   2648         rv = _bcm_td2_cosq_child_node_at_input(node, cosq, &child_node);
   2649 
   2650         if ((!child_node) || (rv == BCM_E_NOT_FOUND)) {
   2651             /* No Child present */
   2652             return BCM_E_INTERNAL;
   2653         }
   2654 
   2655         BCM_IF_ERROR_RETURN
   2656             (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port));
   2657 
   2658         level = child_node->level;
   2659         sch_index = child_node->hw_index;
   2660 
   2661         /* Child State Check is NOT necessary for Non-L0/L1/L2 levels */
   2662         if ((level < SOC_TD2_NODE_LVL_L0) || (level > SOC_TD2_NODE_LVL_L2)) {
   2663             /* Sanity for Node's level should be done in the caller */
   2664             return BCM_E_NONE;
   2665         }
   2666 
   2667         mem = SOC_TD2_PMEM(unit, local_port, memx[level], memy[level]); 
   2668 
   2669         if (mem == INVALIDm) {
   2670             return BCM_E_INTERNAL;
   2671         }
   2672 
   2673         SOC_EGRESS_METERING_LOCK(unit);
   2674         rv = soc_mem_read(unit, mem, MEM_BLOCK_ALL,
   2675                                          sch_index, entry);
   2676         if (rv != BCM_E_NONE) {
   2677             SOC_EGRESS_METERING_UNLOCK(unit);
   2678             return rv;
   2679         }
   2680         min_thd = soc_mem_field32_get(unit, mem, &entry, MIN_THD_SELf);
   2681         max_thd = soc_mem_field32_get(unit, mem, &entry, MAX_THD_SELf);
   2682 
   2683         if (min_thd || max_thd) {
   2684             /* Set Min_Thd of the node to 0 in MTRO_CONFIG_xxx_MEM */
   2685             soc_mem_field32_set(unit, mem, entry, MIN_THD_SELf, 0);
   2686             soc_mem_field32_set(unit, mem, entry, MAX_THD_SELf, 0);
   2687             rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL,
   2688                                               sch_index, entry);
   2689             if (rv != BCM_E_NONE) {
   2690                 SOC_EGRESS_METERING_UNLOCK(unit);
   2691                 return rv;
   2692             }
   2693 
   2694             /* A uSec delay */
   2695             sal_usleep(1);
   2696             /* Reset MIN_THD value back to original one.
   2697              * This step is to activate the MIN_THD to LLS.
   2698              */
   2699             soc_mem_field32_set(unit, mem, entry, MIN_THD_SELf, min_thd);
   2700             soc_mem_field32_set(unit, mem, entry, MAX_THD_SELf, max_thd);
   2701             rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL,
   2702                                               sch_index, entry);
   2703             if (rv != BCM_E_NONE) {
   2704                 SOC_EGRESS_METERING_UNLOCK(unit);
   2705                 return rv;
   2706             }
   2707         }
   2708         SOC_EGRESS_METERING_UNLOCK(unit);
   2709     } else {
   2710         /* TBD: Need to implement for Non-ETS mode */
   2711         return BCM_E_NONE;
   2712     }
   2713 
   2714     return BCM_E_NONE;
   2715 }
   2716 
   2717 /*
   2718  * Function:
   2719  *     _bcm_td2_dynamic_sched_update_end
   2720  * Purpose:
   2721  *     Reset settings back to original state after Dynamic Sched update is complete.
   2722  * Parameters:
   2723  *     unit       - (IN) unit number
   2724  *     port       - (IN) Port
   2725  * Returns:
   2726  *     BCM_E_XXX
   2727  */
   2728 STATIC int
   2729 _bcm_td2_dynamic_sched_update_end(int unit, bcm_port_t gport,
   2730                                   bcm_cos_queue_t cosq)
   2731 {
   2732     int ets_mode = 0;
   2733     bcm_port_t local_port;
   2734     int rv = BCM_E_NONE;
   2735 
   2736     if (SAL_BOOT_SIMULATION) {
   2737        return BCM_E_NONE;
   2738     }
   2739 
   2740     BCM_IF_ERROR_RETURN
   2741         (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port));
   2742 
   2743     ets_mode = _bcm_td2_cosq_port_has_ets(unit, local_port);
   2744     /* Reset MIN_THD for the respective Node/Queue */
   2745     rv = _bcm_td2_dynamic_sched_reset_thd(unit, gport, cosq, ets_mode); 
   2746     if (rv != BCM_E_NONE) {
   2747         /* Logging the Error. Not stopping the flow for now. */
   2748         LOG_ERROR(BSL_LS_BCM_COMMON,
   2749                   (BSL_META_U(unit,
   2750                               "ERROR: During Reset MIN_THD process(rv %d)\n"),
   2751                    rv));
   2752     }
   2753     
   2754     SOC_IF_ERROR_RETURN(
   2755         soc_td2_port_traffic_egr_enable_set(unit, local_port, 1));
   2756 
   2757     return BCM_E_NONE;
   2758 
   2759 }
   2760 
   2761 STATIC int
   2762 _bcm_td2_attach_node_in_hw(int unit, _bcm_td2_cosq_node_t *node)
   2763 {
   2764     int local_port, fc = 0, fmc = 0;
   2765     _bcm_td2_cosq_node_t *child_node;
   2766     int num_spri = 0, first_sp_child = 0, first_sp_mc_child = 0;
   2767     uint32 ucmap = 0, spmap = 0;
   2768     soc_trident2_sched_type_t sched_type;
   2769 
   2770     local_port = node->local_port;
   2771 
   2772     if (node->level == SOC_TD2_NODE_LVL_ROOT) {
   2773         return 0;
   2774     } else if (node->level == SOC_TD2_NODE_LVL_L2) {
   2775         fc = _bcm_td2_cosq_min_child_index(node->parent->child, SOC_TD2_NODE_LVL_L2, 1);
   2776         if (fc < 0) {
   2777             fc = 0;
   2778         }
   2779         fmc = _bcm_td2_cosq_min_child_index(node->parent->child, SOC_TD2_NODE_LVL_L2, 0);
   2780         if (fmc < 0) {
   2781             fmc = 1480;
   2782         }
   2783     } else {
   2784         fc = _bcm_td2_cosq_min_child_index(node->parent->child, node->level, 0);
   2785         fmc = 0;
   2786     }
   2787 
   2788     /* If node is scheduler, reset the scheduler and attach it to the parent.*/
   2789     BCM_IF_ERROR_RETURN(
   2790         soc_td2_cosq_set_sched_parent(unit, local_port, node->level, 
   2791                                       node->hw_index, node->parent->hw_index));
   2792 
   2793     sched_type = _soc_trident2_port_sched_type_get(unit, local_port);
   2794 
   2795     if (sched_type == SOC_TD2_SCHED_LLS) {
   2796         /* Get num_spri and ucmap config from parent node. */
   2797         BCM_IF_ERROR_RETURN(
   2798             soc_td2_cosq_get_sched_child_config(unit, local_port,
   2799                                                 node->parent->level,
   2800                                                 node->parent->hw_index,
   2801                                                 &num_spri, &first_sp_child,
   2802                                                 &first_sp_mc_child, &ucmap,
   2803                                                 &spmap));
   2804 
   2805         /*
   2806          * If there is no SP child under a schedule node, fc of this node will
   2807          * be set to the index of min child.
   2808          * Else, fc of this node will be set to the index of first SP child.
   2809          */
   2810         if (num_spri == 0) {
   2811             if (fc != first_sp_child && fc == node->hw_index) {
   2812                 first_sp_child = fc;
   2813             }
   2814 
   2815             if (node->level == SOC_TD2_NODE_LVL_L2 && fmc != first_sp_mc_child
   2816                                       && fmc == node->hw_index) {
   2817                 first_sp_mc_child = fmc;
   2818             }
   2819         }
   2820 
   2821         /* Retain the num_spri only if the current node is NOT the first_sp_child */
   2822         if (first_sp_child == node->hw_index ||
   2823             first_sp_mc_child == node->hw_index) {
   2824             num_spri = 0;
   2825             ucmap = 0;
   2826         }
   2827 
   2828         /* set the node by default in WRR mode with wt=1 */
   2829         BCM_IF_ERROR_RETURN(soc_td2_cosq_set_sched_config(unit,
   2830                             local_port, node->parent->level,
   2831                             node->parent->hw_index, node->hw_index,
   2832                             num_spri, first_sp_child, first_sp_mc_child, ucmap,
   2833                             0, SOC_TD2_SCHED_MODE_WRR, 1));
   2834     }
   2835 
   2836 
   2837     if (node->child) {
   2838         child_node = node->child;
   2839         while (child_node) {
   2840             BCM_IF_ERROR_RETURN(_bcm_td2_attach_node_in_hw(unit, child_node));
   2841             child_node = child_node->sibling;
   2842         }
   2843     }
   2844 
   2845     return BCM_E_NONE;
   2846 }
   2847 
   2848 STATIC int
   2849 _bcm_td2_cosq_hsp_port_count_per_pipe_get(int unit, int pipe)
   2850 {
   2851     bcm_port_t port;
   2852     int count = 0;
   2853 #ifdef BCM_TRIDENT2PLUS_SUPPORT
   2854     if(SOC_IS_TD2P_TT2P(unit)) {
   2855         BCM_IF_ERROR_RETURN(
   2856                 soc_td2p_num_hsp_reserved_per_pipe(unit, pipe, &count));
   2857     } else
   2858 #endif
   2859     {
   2860         PBMP_ALL_ITER(unit, port) {
   2861             if (IS_TD2_HSP_PORT(unit, port) && 
   2862                 pipe == _BCM_TD2_PORT_TO_PIPE(unit, port)) {
   2863                 count++;
   2864             }
   2865         }
   2866     }
   2867     return count;
   2868 }
   2869 
   2870 /*
   2871  * Function:
   2872  *     _bcm_td2_cosq_node_resolve
   2873  * Purpose:
   2874  *     Resolve queue number in the specified scheduler tree and its subtree
   2875  * Parameters:
   2876  *     unit       - (IN) unit number
   2877  *     node       - (IN) node structure for the specified scheduler node
   2878  *     cosq       - (IN) COS queue to attach to
   2879  * Returns:
   2880  *     BCM_E_XXX
   2881  */
   2882 STATIC int
   2883 _bcm_td2_cosq_node_resolve(int unit, _bcm_td2_cosq_node_t *node,
   2884                           bcm_cos_queue_t cosq)
   2885 {
   2886     _bcm_td2_cosq_node_t *cur_node, *parent;
   2887     _bcm_td2_cosq_port_info_t *port_info;
   2888     _bcm_td2_pipe_resources_t * res;
   2889     _bcm_td2_mmu_info_t *mmu_info;
   2890     _bcm_td2_cosq_list_t *list;
   2891     int numq, id, ii, rv, max_cosq = -1;
   2892     int valid_index_lo, valid_index_hi;
   2893     bcm_port_t port;
   2894     int phy_port, mmu_port;
   2895     int pipe;
   2896     int old_base_index = -1;
   2897     int old_base_size = -1;
   2898     /* An array was used to find first free slot in L0/L1/L2 table
   2899        So choose the one of the longest length of the three table */
   2900     SHR_BIT_DCL_CLR_NAME(map, 1480);
   2901 
   2902     if ((parent = node->parent) == NULL) {
   2903         /* Not attached, should never happen */
   2904         return BCM_E_NOT_FOUND;
   2905     }
   2906 
   2907     if (parent->numq == 0 || parent->numq < -1) {
   2908         return BCM_E_PARAM;
   2909     }
   2910 
   2911     port = node->local_port;
   2912 
   2913     if (parent->numq != -1) {
   2914         /* find the current attached_to_input usage */
   2915         for (cur_node = parent->child; cur_node != NULL;
   2916              cur_node = cur_node->sibling) {
   2917             if (cur_node->attached_to_input >= 0) {
   2918                 SHR_BITSET(map, cur_node->attached_to_input);
   2919             }
   2920         }
   2921 
   2922         if (cosq < 0) {
   2923             for (ii = 0; ii < parent->numq; ii++) {
   2924                 if (!SHR_BITGET(map, ii)) {
   2925                     node->attached_to_input = ii;
   2926                     cosq = ii;
   2927                     break;
   2928                 }
   2929             }
   2930             if (ii == parent->numq) {
   2931                 return BCM_E_PARAM;
   2932             }
   2933         } else {
   2934             if (SHR_BITGET(map, cosq)) {
   2935                 return BCM_E_EXISTS;
   2936             }
   2937             node->attached_to_input = cosq;
   2938         }
   2939     } else if (parent->numq == -1) {
   2940         for (cur_node = parent->child; cur_node != NULL;
   2941              cur_node = cur_node->sibling) {
   2942             if (cur_node->attached_to_input >= 0) {
   2943                 SHR_BITSET(map, cur_node->attached_to_input);
   2944                 max_cosq = (cur_node->attached_to_input > max_cosq)? \
   2945                            cur_node->attached_to_input : max_cosq;
   2946             }
   2947         }
   2948         if (cosq >= 0) {
   2949             if (SHR_BITGET(map, cosq)) {
   2950                 return BCM_E_EXISTS;
   2951             }
   2952         } else {
   2953             /* Attach anywhere. find first free slot */
   2954             for (ii = 0; ii < 1480; ii++) {
   2955                 if (!SHR_BITGET(map, ii)) {
   2956                     cosq = ii;
   2957                     break;
   2958                 }
   2959             }
   2960             if (cosq < 0) { /* No available slot. */
   2961                 return BCM_E_FULL;
   2962             }
   2963         }
   2964         node->attached_to_input = cosq;
   2965         max_cosq = (node->attached_to_input > max_cosq)? \
   2966                    node->attached_to_input : max_cosq;
   2967     }
   2968 
   2969     mmu_info = _bcm_td2_mmu_info[unit];
   2970     port_info = &mmu_info->port_info[port];
   2971     res = port_info->resources;
   2972     numq = (parent->numq == -1) ? (max_cosq + 1) : parent->numq;
   2973     phy_port = SOC_INFO(unit).port_l2p_mapping[port];
   2974     mmu_port = SOC_INFO(unit).port_p2m_mapping[phy_port];
   2975     pipe = _BCM_TD2_PORT_TO_PIPE(unit, port);
   2976 
   2977     switch (parent->level) {
   2978         case SOC_TD2_NODE_LVL_ROOT:
   2979             list = &res->l0_sched_list;
   2980             if ((parent->numq == -1) && parent->base_index >= 0 &&
   2981                 parent->base_size != numq) {
   2982                 old_base_index = parent->base_index;
   2983                 old_base_size = parent->base_size;
   2984                 _bcm_td2_node_index_clear(list, parent->base_index,
   2985                                           parent->base_size);
   2986                 parent->base_index = -1;
   2987             }
   2988 
   2989             if (parent->base_index < 0) {
   2990                 if (IS_CPU_PORT(unit, port)) {
   2991                     valid_index_lo = (SOC_IS_TD2P_TT2P(unit)?259:261);
   2992                     valid_index_hi = _BCM_TD2_NUM_L0_SCHEDULER_PER_PIPE;
   2993                 } else if (IS_TD2_HSP_PORT(unit, port)) {
   2994                     valid_index_lo = _BCM_TD2_HSP_L0_INDEX(unit, mmu_port, 0);
   2995                     valid_index_hi = _BCM_TD2_HSP_L0_INDEX(unit, (mmu_port + 1),
   2996                                                            0);
   2997                 } else {
   2998                     valid_index_lo = _bcm_td2_cosq_hsp_port_count_per_pipe_get(unit, pipe) * 
   2999                                      _BCM_TD2_HSP_PORT_MAX_L0;
   3000                     /* upper 4 L0 nodes reserverd for cpu */
   3001                     valid_index_hi = (SOC_IS_TD2P_TT2P(unit)?259:261);
   3002                 }
   3003 
   3004                 if (IS_CPU_PORT(unit, port) ||
   3005                     IS_TD2_HSP_PORT(unit, port)) {
   3006                     rv = _bcm_td2_node_index_get(list->bits, valid_index_lo, 
   3007                                                valid_index_hi, numq, 1, &id);
   3008                 } else {
   3009                     rv = _bcm_td2_node_index_get(list->bits, valid_index_lo, 
   3010                                                  valid_index_hi, numq,
   3011                                                  node->node_align_value, &id);
   3012                 }
   3013                 if (rv) {
   3014                     parent->base_index = old_base_index;
   3015                     _bcm_td2_node_index_set(list, old_base_index,
   3016                                               old_base_size);
   3017                     return rv;
   3018                 }
   3019 
   3020                 _bcm_td2_node_index_set(list, id, numq);
   3021                 parent->base_index = id;
   3022                 node->hw_index = parent->base_index + node->attached_to_input;
   3023                 parent->base_size = numq;
   3024                 if (parent->base_index != old_base_index){
   3025                     for (id = old_base_index;
   3026                          id < old_base_index + old_base_size;
   3027                          id++) {
   3028                         BCM_IF_ERROR_RETURN(soc_td2_cosq_set_sched_parent(unit,
   3029                                 port, node->level, id,
   3030                                 _soc_td2_invalid_parent_index(unit, node->level)));
   3031                     }
   3032                 }
   3033                 for (cur_node = parent->child; cur_node;
   3034                      cur_node = cur_node->sibling) {
   3035                     if (cur_node->attached_to_input >= 0) {
   3036                         cur_node->hw_index = parent->base_index +
   3037                                              cur_node->attached_to_input;
   3038                         BCM_IF_ERROR_RETURN(
   3039                             _bcm_td2_attach_node_in_hw(unit, cur_node));
   3040                     }
   3041                 }
   3042             } else {
   3043                 node->hw_index = parent->base_index + node->attached_to_input;
   3044             }
   3045             node->hw_cosq = node->attached_to_input;
   3046 
   3047             break;
   3048 
   3049         case SOC_TD2_NODE_LVL_L0:
   3050             list = &res->l1_sched_list;
   3051             if (IS_TD2_HSP_PORT(unit, port)) {
   3052                 if (node->attached_to_input >= _BCM_TD2_HSP_PORT_MAX_L1) {
   3053                     return BCM_E_PARAM;
   3054                 }
   3055 
   3056                 if ((parent->hw_index % _BCM_TD2_HSP_PORT_MAX_L0) == 0) {
   3057                     /* L0.0 could only be attached by MC nodes */
   3058                     if (node->type == _BCM_TD2_NODE_MCAST) {
   3059                         uint32 rval = 0;
   3060                         uint32 mc_group_mode = 0;
   3061                         SOC_IF_ERROR_RETURN(
   3062                             READ_HSP_SCHED_PORT_CONFIGr(unit, port, &rval));
   3063                         mc_group_mode  = soc_reg_field_get(
   3064                                             unit, HSP_SCHED_PORT_CONFIGr, 
   3065                                             rval, MC_GROUP_MODEf);
   3066                         /* check mc group mode and the node offset */
   3067                         if ((!mc_group_mode) ||
   3068                             ((node->hw_index % _BCM_TD2_HSP_PORT_MAX_L1) >=
   3069                              _BCM_TD2_HSP_PORT_MAX_COS)) {
   3070                             return BCM_E_PARAM;
   3071                         }
   3072                         break;
   3073                     } else {
   3074                         return BCM_E_PARAM;
   3075                     }
   3076                 }
   3077 
   3078                 BCM_IF_ERROR_RETURN(_bcm_td2_node_index_get(list->bits, 
   3079                                     _BCM_TD2_HSP_PORT_MAX_L1 * (mmu_port & 0x3f), 
   3080                                     (_BCM_TD2_HSP_PORT_MAX_L1) * ((mmu_port & 0x3f) + 1),
   3081                                     1, 1, &id));
   3082                 if (parent->base_index == -1) {
   3083                     parent->base_index = id;
   3084                 }
   3085                 node->hw_index = id;
   3086 
   3087                 if ((node->hw_index % _BCM_TD2_HSP_PORT_MAX_L1) >= 8) {
   3088                     if ((parent->hw_index % _BCM_TD2_HSP_PORT_MAX_L0) != 4) {
   3089                         return BCM_E_PARAM;
   3090                     }
   3091                 } else {
   3092                     if ((parent->hw_index % _BCM_TD2_HSP_PORT_MAX_L0) == 4) {
   3093                         return BCM_E_PARAM;
   3094                     }
   3095                 }
   3096                 _bcm_td2_node_index_set(list, id, 1);
   3097             } else {
   3098                 /* Delete current COSQs if numq needs to be expanded. */
   3099                 if ((parent->base_index >= 0) &&
   3100                     (parent->numq == -1) && (cosq == max_cosq)) {
   3101                     old_base_index = parent->base_index;
   3102                     old_base_size = parent->base_size;
   3103                     _bcm_td2_node_index_clear(list, parent->base_index,
   3104                                               parent->base_size);
   3105                     parent->base_index = -1;
   3106                 }
   3107                 if (parent->base_index < 0) {
   3108                     rv = _bcm_td2_node_index_get(list->bits,
   3109                                                 _BCM_TD2_HSP_PORT_MAX_L1 * _bcm_td2_cosq_hsp_port_count_per_pipe_get(unit, pipe), 
   3110                                                 _BCM_TD2_NUM_L1_SCHEDULER_PER_PIPE, 
   3111                                                 numq, node->node_align_value, &id);
   3112                     if (rv) {
   3113                         _bcm_td2_node_index_set(list, old_base_index,
   3114                                                   old_base_size);
   3115                         return rv;
   3116                     }
   3117                     _bcm_td2_node_index_set(list, id, numq);
   3118                     parent->base_size = numq;
   3119                     parent->base_index = id;
   3120                     node->hw_index = parent->base_index + node->attached_to_input;
   3121                     if (parent->base_index != old_base_index){
   3122                         for (id = old_base_index;
   3123                              id < old_base_index + old_base_size;
   3124                              id++) {
   3125                             BCM_IF_ERROR_RETURN(soc_td2_cosq_set_sched_parent(unit,
   3126                                     port, node->level, id,
   3127                                     _soc_td2_invalid_parent_index(unit, node->level)));
   3128                         }
   3129                     }
   3130                     for (cur_node = parent->child; cur_node;
   3131                          cur_node = cur_node->sibling) {
   3132                         if (cur_node->attached_to_input >= 0) {
   3133                             cur_node->hw_index = parent->base_index +
   3134                                                  cur_node->attached_to_input;
   3135                             BCM_IF_ERROR_RETURN(
   3136                                 _bcm_td2_attach_node_in_hw(unit, cur_node));
   3137                         }
   3138                     }
   3139                 } else {
   3140                     node->hw_index = parent->base_index + node->attached_to_input;
   3141                 }
   3142             }
   3143             node->hw_cosq = node->attached_to_input;
   3144 
   3145             break;
   3146 
   3147         case SOC_TD2_NODE_LVL_L1:
   3148             if (IS_TD2_HSP_PORT(unit, port)) {
   3149                 uint32     rval = 0;
   3150                 uint32     mc_group_mode = 0;
   3151                 SOC_IF_ERROR_RETURN(
   3152                     READ_HSP_SCHED_PORT_CONFIGr(unit, port, &rval));
   3153                 mc_group_mode  = soc_reg_field_get(unit, HSP_SCHED_PORT_CONFIGr,
   3154                                                    rval, MC_GROUP_MODEf);
   3155                 if (mc_group_mode &&
   3156                     ((node->hw_index % _BCM_TD2_HSP_PORT_MAX_L1) <
   3157                      _BCM_TD2_HSP_PORT_MAX_COS)) {
   3158                     if (node->attached_to_input >= 1) {
   3159                         return BCM_E_PARAM;
   3160                     }
   3161                     if (node->type == _BCM_TD2_NODE_MCAST) {
   3162                         return BCM_E_PARAM;
   3163                     }
   3164                 } else {
   3165                     if (node->attached_to_input >= _BCM_TD2_HSP_PORT_MAX_L2) {
   3166                         return BCM_E_PARAM;
   3167                     }
   3168                     if ((node->sibling) &&
   3169                         (node->type == node->sibling->type)) {
   3170                         return BCM_E_PARAM;
   3171                     }
   3172                 }
   3173             }
   3174             if ((node->hw_index == -1) && 
   3175                     (node->type != _BCM_TD2_NODE_VOQ)) {
   3176                 return BCM_E_PARAM;
   3177             } else if (node->type == _BCM_TD2_NODE_VOQ) {
   3178                 if (parent->base_index < 0) {
   3179                     BCM_IF_ERROR_RETURN(
   3180                             _bcm_td2_node_index_get(res->ext_qlist.bits,
   3181                                 res->num_base_queues,
   3182                                _BCM_TD2_NUM_L2_UC_LEAVES_PER_PIPE  , 
   3183                                _TD2_NUM_COS(unit), 
   3184                                 _TD2_NUM_COS(unit), &id));
   3185                     /* The following logic is to make sure the id is always
   3186                      *  multiple of 8 
   3187                      */
   3188                     while ( id % 8 != 0) {
   3189                         id = ((id + 8) & 0xfffffff8);
   3190                         if (id >  _BCM_TD2_NUM_L2_UC_LEAVES_PER_PIPE ) {
   3191                             return BCM_E_RESOURCE;
   3192                         }
   3193                         BCM_IF_ERROR_RETURN(
   3194                                 _bcm_td2_node_index_get(res->ext_qlist.bits, id,
   3195                                     _BCM_TD2_NUM_L2_UC_LEAVES_PER_PIPE, 
   3196                                     NUM_COS(unit), 
   3197                                     NUM_COS(unit), &id));
   3198                     }
   3199                     _bcm_td2_node_index_set(&res->ext_qlist, id, 
   3200                             _TD2_NUM_COS(unit));
   3201                     parent->base_index = id ;
   3202                     node->hw_index = parent->base_index;
   3203                     node->hw_cosq = node->hw_index % NUM_COS(unit);
   3204                 } else {
   3205                     node->hw_index = parent->base_index + 
   3206                         node->attached_to_input;
   3207                     node->hw_cosq = node->hw_index % NUM_COS(unit);
   3208                 }
   3209             }
   3210             break;
   3211 
   3212         case SOC_TD2_NODE_LVL_L2:
   3213             /* passthru */
   3214         default:
   3215             return BCM_E_PARAM;
   3216 
   3217     }
   3218 
   3219     BCM_IF_ERROR_RETURN(_bcm_td2_attach_node_in_hw(unit, node));
   3220     return BCM_E_NONE;
   3221 }
   3222 
   3223 STATIC int
   3224 _bcm_td2_detach_node_in_hw(int unit, _bcm_td2_cosq_node_t *node)
   3225 {
   3226     int local_port;
   3227 
   3228     local_port = node->local_port;
   3229 
   3230     if (!IS_TD2_HSP_PORT(unit, local_port)) {
   3231         BCM_IF_ERROR_RETURN(_bcm_td2_cosq_sched_parent_child_set(unit,
   3232                             local_port, node->parent->level,
   3233                             node->parent->hw_index, node->hw_index, 
   3234                             SOC_TD2_SCHED_MODE_WRR, 1, node));
   3235     }
   3236     
   3237     return BCM_E_NONE;
   3238 }
   3239 
   3240 /*
   3241  * Function:
   3242  *     _bcm_td2_cosq_node_unresolve
   3243  * Purpose:
   3244  *     Unresolve queue number in the specified scheduler tree and its subtree
   3245  * Parameters:
   3246  *     unit       - (IN) unit number
   3247  *     node       - (IN) node structure for the specified scheduler node
   3248  *     cosq       - (IN) COS queue to attach to
   3249  * Returns:
   3250  *     BCM_E_XXX
   3251  */
   3252 STATIC int
   3253 _bcm_td2_cosq_node_unresolve(int unit, _bcm_td2_cosq_node_t *node, 
   3254                              bcm_cos_queue_t cosq)
   3255 {
   3256     _bcm_td2_cosq_node_t *parent;
   3257     _bcm_td2_mmu_info_t *mmu_info;
   3258     _bcm_td2_pipe_resources_t * res;
   3259     _bcm_td2_cosq_port_info_t *port_info;
   3260     _bcm_td2_cosq_list_t *list;
   3261     int numq = 1, port;
   3262 
   3263     if (node->attached_to_input < 0) {
   3264         /* Has been unresolved already */
   3265         return BCM_E_NONE;
   3266     }
   3267 
   3268     parent = node->parent;
   3269 
   3270     if (!parent) {
   3271         return BCM_E_PARAM;
   3272     }
   3273 
   3274     mmu_info = _bcm_td2_mmu_info[unit];
   3275 
   3276     BCM_IF_ERROR_RETURN
   3277         (_bcm_td2_cosq_node_get(unit, node->gport, 0, NULL, &port, NULL, NULL));
   3278 
   3279     port_info = &mmu_info->port_info[port];
   3280     res = port_info->resources;
   3281 
   3282     list = NULL;
   3283 
   3284     switch (parent->level) {
   3285         case SOC_TD2_NODE_LVL_ROOT:
   3286             break;
   3287 
   3288         case SOC_TD2_NODE_LVL_L0:
   3289             if (IS_TD2_HSP_PORT(unit, port) &&
   3290                 (node->type != _BCM_TD2_NODE_MCAST)) {    /* L0.0 of HSP port. */
   3291                 list = &res->l1_sched_list;
   3292             }
   3293             break;
   3294 
   3295         case SOC_TD2_NODE_LVL_L1:
   3296             break;
   3297 
   3298         case SOC_TD2_NODE_LVL_L2:
   3299             /* passthru */
   3300         default:
   3301             return BCM_E_PARAM;
   3302 
   3303     }
   3304 
   3305     BCM_IF_ERROR_RETURN(_bcm_td2_detach_node_in_hw(unit, node));
   3306     
   3307     if (list) {
   3308         _bcm_td2_node_index_clear(list, node->hw_index, numq);
   3309     }
   3310     node->attached_to_input = -1;
   3311     
   3312     return BCM_E_NONE;
   3313 }
   3314 
   3315 typedef struct _bcm_td2p_lls_info_s {
   3316     int child_lvl; /* level of the node */
   3317     int child_hw_index; /* hw index of the node */
   3318     int node_count[SOC_TD2_NODE_LVL_MAX]; /* total number of nodes in the lls */
   3319     int count[SOC_TD2_NODE_LVL_MAX]; /* number of nodes in each level */
   3320     int offset[SOC_TD2_NODE_LVL_MAX]; /* index of the starting node at each level */
   3321    
   3322     int kbit_max; /* max speed for the node */
   3323     int kbit_min; /* min speed for the node */
   3324     uint32  *mtro_entries; /* entries to maintain mmu mtro level mem */
   3325     int mtro_restore; /*indicate available data in mtro_entries*/
   3326 } _bcm_td2p_lls_info_t;
   3327 
   3328 /*
   3329  * Function:
   3330  *     _bcm_td2_lls_node_count
   3331  * Purpose:
   3332  *     This function counts the number of nodes at a particular level
   3333  * Parameters:
   3334  *     unit       - (IN) unit number
   3335  *     port       - (IN) local port number 
   3336  *     level      - (IN) level of the node in LLS
   3337  *     hw_index   - (IN) h/w index of the node
   3338  *     cookie     - (IN) state of the LLS structure  
   3339  */
   3340 STATIC int _bcm_td2_lls_node_count(int unit, int port, int level, 
   3341                                    int hw_index, void *cookie)
   3342 {
   3343     _bcm_td2p_lls_info_t *i_lls_tree = (_bcm_td2p_lls_info_t *) cookie;
   3344     i_lls_tree->node_count[level] += 1;
   3345     return 0;
   3346 }
   3347 
   3348 /*
   3349  * Function:
   3350  *     _bcm_td2_lls_shapers_init
   3351  * Purpose:
   3352  *     This function reset MTRO shapers so that each node can only schedule upto
   3353  *     the max rate.
   3354  * Parameters:
   3355  *     unit       - (IN) unit number
   3356  */
   3357 STATIC int
   3358 _bcm_td2_lls_shapers_init(int unit)
   3359 {
   3360     uint8 *mbuf = NULL;
   3361     int table, alloc_size, rv = SOC_E_NONE;
   3362     soc_mem_t config_mem;
   3363     static const soc_mem_t mem[] = {
   3364         MMU_MTRO_L0_MEM_0m,
   3365         MMU_MTRO_L1_MEM_0m,
   3366         MMU_MTRO_L2_MEM_0m,
   3367         MMU_MTRO_L0_MEM_1m,
   3368         MMU_MTRO_L1_MEM_1m,
   3369         MMU_MTRO_L2_MEM_1m
   3370     };
   3371 
   3372     for (table = 0; table < COUNTOF(mem); table++) {
   3373         config_mem = mem[table];
   3374         alloc_size = SOC_MEM_TABLE_BYTES(unit, config_mem);
   3375         mbuf = soc_cm_salloc(unit, alloc_size, "MMU_MTRO entries");
   3376         if (NULL == mbuf) {
   3377             return BCM_E_MEMORY;
   3378         }
   3379         sal_memset(mbuf, 0, alloc_size);
   3380         rv = soc_mem_write_range(unit, config_mem, MEM_BLOCK_ANY,
   3381                                  soc_mem_index_min(unit, config_mem),
   3382                                  soc_mem_index_max(unit, config_mem),
   3383                                  mbuf);
   3384         soc_cm_sfree(unit, mbuf);
   3385         mbuf = NULL;
   3386         if (SOC_FAILURE(rv)) {
   3387             return rv;
   3388         }
   3389     }
   3390 
   3391     return BCM_E_NONE;
   3392 }
   3393 
   3394 /*
   3395  * Function:
   3396  *     _bcm_td2_lls_shapers_remove
   3397  * Purpose:
   3398  *     This function removes shapers on the nodes by setting them 
   3399  *     to the max rate and setting min to 0  so that each node can only schedule upto
   3400  *     the max rate. It also calculates the leaky bucket parameters based on 
   3401  *     the kbit max
   3402  * Parameters:
   3403  *     unit       - (IN) unit number
   3404  *     port       - (IN) local port number 
   3405  *     level      - (IN) level of the node in LLS
   3406  *     hw_index   - (IN) h/w index of the node
   3407  *     cookie     - (IN) state of the LLS structure  
   3408  */
   3409 STATIC int _bcm_td2_lls_shapers_remove(int unit, int port, int level, 
   3410                                        int hw_index, void *cookie)
   3411 {
   3412     _bcm_td2p_lls_info_t *i_lls_tree = (_bcm_td2p_lls_info_t *) cookie;
   3413     soc_mem_t config_mem;
   3414     uint32  *p_entry;
   3415     uint32 entry[SOC_MAX_MEM_WORDS];
   3416     int index, kbit_max, kbit_min;
   3417     uint32 meter_flags;
   3418     uint32 bucketsize_max, granularity_max, refresh_rate_max,
   3419            refresh_bitsize = 0, bucket_bitsize = 0;
   3420 
   3421     static const soc_mem_t memx[] = {
   3422         INVALIDm,
   3423         MMU_MTRO_L0_MEM_0m,
   3424         MMU_MTRO_L1_MEM_0m,
   3425         MMU_MTRO_L2_MEM_0m
   3426     };
   3427 
   3428     static const soc_mem_t memy[] = {
   3429         INVALIDm,
   3430         MMU_MTRO_L0_MEM_1m,
   3431         MMU_MTRO_L1_MEM_1m,
   3432         MMU_MTRO_L2_MEM_1m
   3433     };
   3434  
   3435     if (level == SOC_TD2_NODE_LVL_MAX) {
   3436         return SOC_E_PARAM;
   3437     }
   3438 
   3439     if (i_lls_tree->child_lvl != level) {
   3440         return BCM_E_NONE;
   3441     }
   3442 
   3443     config_mem = SOC_TD2_PMEM(unit, port, memx[level], memy[level]);
   3444 
   3445     if (config_mem ==  INVALIDm) {
   3446         return BCM_E_PARAM;
   3447     }
   3448 
   3449     index = i_lls_tree->offset[level] + i_lls_tree->count[level];
   3450     p_entry = &i_lls_tree->mtro_entries[index * SOC_MAX_MEM_WORDS];
   3451     
   3452     if (*p_entry == 0) {
   3453         SOC_IF_ERROR_RETURN(soc_mem_read(unit, config_mem, MEM_BLOCK_ALL, hw_index,
   3454                                          p_entry));
   3455         i_lls_tree->mtro_restore = TRUE;
   3456     }
   3457 
   3458     sal_memset(entry, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS);
   3459     
   3460             
   3461     meter_flags = 0;
   3462 
   3463     refresh_bitsize = soc_mem_field_length(unit, config_mem, MAX_REFRESHf);
   3464     bucket_bitsize = soc_mem_field_length(unit, config_mem, MAX_THD_SELf);
   3465 
   3466     /* Setting the max metering configuration */
   3467     kbit_max = i_lls_tree->kbit_max;
   3468     BCM_IF_ERROR_RETURN
   3469         (_bcm_td_rate_to_bucket_encoding(unit, kbit_max, kbit_max,
   3470                                        meter_flags, refresh_bitsize,
   3471                                        bucket_bitsize, &refresh_rate_max,
   3472                                        &bucketsize_max, &granularity_max));
   3473 
   3474     soc_mem_field32_set(unit, config_mem, entry, MAX_METER_GRANf,
   3475                         granularity_max);
   3476     soc_mem_field32_set(unit, config_mem, entry, MAX_REFRESHf,
   3477                         refresh_rate_max);
   3478     soc_mem_field32_set(unit, config_mem, entry, MAX_THD_SELf, 
   3479                         bucketsize_max);
   3480 
   3481     
   3482     /* Setting the min metering configuration */
   3483     kbit_min = i_lls_tree->kbit_min;
   3484     BCM_IF_ERROR_RETURN
   3485         (_bcm_td_rate_to_bucket_encoding(unit, kbit_min, kbit_min,
   3486                                        meter_flags, refresh_bitsize,
   3487                                        bucket_bitsize, &refresh_rate_max,
   3488                                        &bucketsize_max, &granularity_max));
   3489 
   3490     soc_mem_field32_set(unit, config_mem, entry, MIN_METER_GRANf,
   3491                         granularity_max);
   3492     soc_mem_field32_set(unit, config_mem, entry, MIN_REFRESHf,
   3493                         refresh_rate_max);
   3494     soc_mem_field32_set(unit, config_mem, entry, MIN_THD_SELf, 
   3495                         bucketsize_max);
   3496 
   3497     BCM_IF_ERROR_RETURN
   3498         (soc_mem_write(unit, config_mem, MEM_BLOCK_ALL, hw_index, entry));
   3499   
   3500     sal_usleep(100); 
   3501     i_lls_tree->count[level] += 1;
   3502     return 0;
   3503 }
   3504 
   3505 /*
   3506  * Function:
   3507  *     _bcm_td2_lls_shapers_restore
   3508  * Purpose:
   3509  *     This function restores the shapers on the nodes  
   3510  * Parameters:
   3511  *     unit       - (IN) unit number
   3512  *     port       - (IN) local port number 
   3513  *     level      - (IN) level of the node in LLS
   3514  *     hw_index   - (IN) h/w index of the node
   3515  *     cookie     - (IN) state of the LLS structure  
   3516  */
   3517 STATIC int _bcm_td2_lls_shapers_restore(int unit, int port, int level, 
   3518                                         int hw_index, void *cookie)
   3519 {
   3520     _bcm_td2p_lls_info_t *i_lls_tree = (_bcm_td2p_lls_info_t *) cookie;
   3521     soc_mem_t config_mem;
   3522     uint32  *p_entry;
   3523     int index;
   3524     uint32 entry[SOC_MAX_MEM_WORDS];    
   3525 
   3526     static const soc_mem_t memx[] = {
   3527         INVALIDm,
   3528         MMU_MTRO_L0_MEM_0m,
   3529         MMU_MTRO_L1_MEM_0m,
   3530         MMU_MTRO_L2_MEM_0m
   3531     };
   3532 
   3533      static const soc_mem_t memy[] = {
   3534         INVALIDm,
   3535         MMU_MTRO_L0_MEM_1m,
   3536         MMU_MTRO_L1_MEM_1m,
   3537         MMU_MTRO_L2_MEM_1m
   3538     };
   3539 
   3540     if (level == SOC_TD2_NODE_LVL_MAX) {
   3541         return SOC_E_PARAM;
   3542     }
   3543 
   3544     config_mem = SOC_TD2_PMEM(unit, port, memx[level], memy[level]);
   3545 
   3546     if (i_lls_tree->child_lvl  != level) {
   3547         return BCM_E_NONE;
   3548     }
   3549 
   3550     if (config_mem == INVALIDm) {
   3551         return BCM_E_PARAM;
   3552     }
   3553 
   3554 
   3555     sal_memset(entry, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS);
   3556 
   3557     soc_mem_field32_set(unit, config_mem, entry, MIN_REFRESHf,
   3558                         500);
   3559     soc_mem_field32_set(unit, config_mem, entry, MIN_THD_SELf,
   3560                         3);
   3561  
   3562     SOC_IF_ERROR_RETURN
   3563         (soc_mem_write(unit, config_mem, MEM_BLOCK_ALL, hw_index, entry));
   3564 
   3565     sal_usleep(100);
   3566 
   3567     index = i_lls_tree->offset[level] + i_lls_tree->count[level];
   3568     if (i_lls_tree->mtro_entries != NULL) {
   3569         p_entry = &i_lls_tree->mtro_entries[index * SOC_MAX_MEM_WORDS];
   3570 
   3571         if (i_lls_tree->mtro_restore == TRUE) {
   3572             SOC_IF_ERROR_RETURN(soc_mem_write(unit, config_mem, MEM_BLOCK_ALL,
   3573                                               hw_index, p_entry));
   3574         }
   3575     }
   3576     i_lls_tree->count[level] += 1;
   3577 
   3578     return 0;
   3579 }
   3580 
   3581 /*
   3582  * Function:
   3583  *     _bcm_td2_num_ones
   3584  * Purpose:
   3585  *     This function calculates the numbers of 1s in the binary format
   3586  *     of the number 
   3587  * Parameters:
   3588  *     m       - (IN) number
   3589  * Returns:
   3590  *     The number of 1s in the binary format of the number
   3591  */
   3592 STATIC uint32 
   3593 _bcm_td2_num_ones(uint32 m)
   3594 {
   3595     uint32 i = 0;
   3596 
   3597     while (m) {
   3598         m &= m - 1;
   3599         i +=  1;
   3600     }
   3601     return i;
   3602 }
   3603 
   3604 /*
   3605  * Function:
   3606  *     _bcm_td2plus_compute_lls_config
   3607  * Purpose:
   3608  *     This function computes the LLS configuration at each level
   3609  * Parameters:
   3610  *     unit              - (IN) unit number
   3611  *     port              - (IN) local port number 
   3612  *     level             - (IN) level of the node in LLS
   3613  *     first_sp_child    - (OUT) first sp child 
   3614  *     first_sp_mc_child - (OUT) first so multicast child
   3615  *     ucmap             - (OUT) unicast node map
   3616  *     spmap             - (OUT) SPRI node map
   3617  *     child_index       - (IN) index of the child node
   3618  *     cur_mode          - (IN) current schedling mode of the node  
   3619  *     mode              - (IN) new scheduling mode of the node
   3620  *     max_children      - (IN) maximum number of children in the level
   3621  * Returns:
   3622  *     BCM_E_XXX
   3623  */
   3624 STATIC int
   3625 _bcm_td2plus_compute_lls_config (int unit, int port, int level, 
   3626                                  int *first_sp_child, 
   3627                                  int *first_sp_mc_child,
   3628                                  int *num_spri,
   3629                                  uint32 *ucmap, 
   3630                                  uint32 *spmap, 
   3631                                  int child_index, 
   3632                                  soc_td2_sched_mode_e cur_mode,
   3633                                  soc_td2_sched_mode_e mode,
   3634                                  int max_children)
   3635 {
   3636     uint32 ucm = 0, mcm = 0, cur_spmap, cur_num_spri, lucmap = 0;
   3637     int ii, *pfc, uc, mc, fc, oc, *use_fc;
   3638 
   3639     cur_num_spri = _bcm_td2_num_ones(*spmap);
   3640     cur_spmap = *spmap;
   3641 
   3642     if (level == SOC_TD2_NODE_LVL_L1) {
   3643         if (IS_CPU_PORT(unit, port)) {
   3644             use_fc = first_sp_mc_child;
   3645         } else {
   3646             use_fc = (child_index >= 1480) ? first_sp_mc_child : first_sp_child;
   3647         }
   3648     } else {
   3649         use_fc = first_sp_child;
   3650     }
   3651     
   3652     if (cur_num_spri == 0) {
   3653         *ucmap = 0;
   3654         *spmap = 0;
   3655     }
   3656 
   3657     if (mode == SOC_TD2_SCHED_MODE_STRICT) {
   3658         if (child_index > *use_fc) {
   3659             if ((child_index - *use_fc) >= max_children && cur_num_spri > 0) {
   3660                  return BCM_E_UNAVAIL;
   3661             }
   3662         } else if (child_index < *use_fc) {
   3663             return BCM_E_UNAVAIL;
   3664         }
   3665     }
   3666  
   3667     if (level == SOC_TD2_NODE_LVL_L1) {
   3668         for (mcm = 0, mc = 0, ucm = 0, uc = 0, ii = 0; ii < 8; ii++) {
   3669             if (*ucmap & (1 << ii)) {
   3670                 mcm |= (cur_spmap & (1 << ii)) ? (1 << mc) : 0;
   3671                 mc += 1;
   3672             } else {
   3673                 ucm |= (cur_spmap & (1 << ii)) ? (1 << uc) : 0;
   3674                 uc += 1;
   3675             }
   3676         }
   3677 
   3678         if (child_index < 1480) {
   3679             fc = *first_sp_child;
   3680             oc =  _bcm_td2_num_ones(ucm);
   3681             BCM_IF_ERROR_RETURN(_bcm_td2plus_compute_lls_config(unit, port,
   3682                         level - 1, &fc, NULL, &oc, &lucmap, &ucm, child_index, 
   3683                         cur_mode, mode, 8));
   3684         } else {
   3685             fc = *first_sp_mc_child;
   3686             oc =  _bcm_td2_num_ones(mcm);
   3687             BCM_IF_ERROR_RETURN(_bcm_td2plus_compute_lls_config(unit, port,
   3688                     level - 1, &fc, NULL, &oc, &lucmap, &mcm, 
   3689                     child_index, cur_mode, mode, 8));
   3690         }
   3691         
   3692         cur_spmap = 0;
   3693         *ucmap = 0;
   3694         for (fc = 0, ii = 0; ii < 8; ii++) {
   3695             if (ucm) {
   3696                 cur_spmap |= (ucm & (1 << ii)) ? 1 << fc : 0;
   3697                 fc += 1;
   3698                 ucm &= ~(1 << ii);
   3699             }
   3700             
   3701             if (mcm) {
   3702                 cur_spmap |= (mcm & (1 << ii)) ? 1 << fc : 0;
   3703                 *ucmap |= 1 << fc;
   3704                 fc += 1;
   3705                 mcm &= ~(1 << ii);
   3706             }
   3707 
   3708             if (fc > max_children) {
   3709                 return BCM_E_PARAM;
   3710             }
   3711 
   3712             if ((mcm == 0) && (ucm == 0)) {
   3713                 break;
   3714             }
   3715         }
   3716 
   3717     } else {
   3718         pfc = first_sp_child;
   3719         if (mode == SOC_TD2_SCHED_MODE_STRICT) {
   3720             if (*pfc > child_index) {
   3721                 cur_spmap <<= (*pfc - child_index);
   3722                 cur_spmap |= 1;
   3723                 *pfc = child_index;
   3724                 *num_spri += 1;
   3725             } else {
   3726                 if (((1 << (child_index - *pfc)) & cur_spmap) == 0) {
   3727                     cur_spmap |= 1 << (child_index - *pfc);
   3728                     *num_spri += 1;
   3729                 }
   3730             }
   3731         } else {
   3732             if (1 << (child_index - *pfc) & cur_spmap) {
   3733                 cur_spmap &= ~(1 << (child_index - *pfc));
   3734                 *num_spri -= 1;
   3735             }
   3736         }
   3737     }
   3738 
   3739     *num_spri = _bcm_td2_num_ones(cur_spmap);
   3740 
   3741     *spmap = cur_spmap;
   3742 
   3743     return BCM_E_NONE;
   3744 }
   3745 
   3746 /*
   3747  * Function:
   3748  *     _bcm_td2_compute_lls_config
   3749  * Purpose:
   3750  *     This function computes the LLS configuration at each level
   3751  * Parameters:
   3752  *     unit              - (IN) unit number
   3753  *     port              - (IN) local port number 
   3754  *     level             - (IN) level of the node in LLS
   3755  *     first_sp_child    - (OUT) first sp child 
   3756  *     first_sp_mc_child - (OUT) first so multicast child
   3757  *     ucmap             - (OUT) unicast node map
   3758  *     spmap             - (OUT) SPRI node map
   3759  *     child_index       - (IN) index of the child node
   3760  *     cur_mode          - (IN) current schedling mode of the node  
   3761  *     mode              - (IN) new scheduling mode of the node
   3762  *     max_children      - (IN) maximum number of children in the level
   3763  * Returns:
   3764  *     BCM_E_XXX
   3765  */
   3766 STATIC int
   3767 _bcm_td2_compute_lls_config(int unit, int port, int level, 
   3768                             int *first_sp_child, 
   3769                             int *first_sp_mc_child,
   3770                             int *num_spri,
   3771                             uint32 *ucmap, 
   3772                             uint32 *spmap, 
   3773                             int child_index, 
   3774                             soc_td2_sched_mode_e cur_mode,
   3775                             soc_td2_sched_mode_e mode)
   3776 {
   3777     if (!soc_feature(unit, soc_feature_vector_based_spri)) {
   3778         return BCM_E_UNAVAIL;
   3779     }
   3780 
   3781     if (((cur_mode != SOC_TD2_SCHED_MODE_STRICT) &&
   3782         (mode != SOC_TD2_SCHED_MODE_STRICT)) ||
   3783        ((cur_mode == SOC_TD2_SCHED_MODE_STRICT) && 
   3784         (mode == SOC_TD2_SCHED_MODE_STRICT))) {
   3785         return BCM_E_NONE;
   3786     }
   3787 
   3788     return _bcm_td2plus_compute_lls_config(unit, port, level, first_sp_child,
   3789                                           first_sp_mc_child, num_spri,
   3790                                           ucmap, spmap, child_index,
   3791                                           cur_mode, mode, 8);
   3792 }
   3793 
   3794 STATIC int
   3795 _bcm_td2_cosq_traverse_lls_tree(int unit, int port, _bcm_td2_cosq_node_t *node,
   3796                                 _soc_td2_lls_traverse_cb cb, void *cookie)
   3797 {
   3798     if (node->child) {
   3799         BCM_IF_ERROR_RETURN(_bcm_td2_cosq_traverse_lls_tree(unit, port, 
   3800                                                             node->child,
   3801                                                             cb, cookie));
   3802     }
   3803 
   3804     if (node->sibling) {
   3805         BCM_IF_ERROR_RETURN(_bcm_td2_cosq_traverse_lls_tree(unit, port, 
   3806                                                 node->sibling, cb, cookie));
   3807     }
   3808 
   3809     if (node->level != SOC_TD2_NODE_LVL_ROOT) {
   3810         BCM_IF_ERROR_RETURN(cb(unit, port, node->level, node->hw_index, cookie));
   3811     }
   3812     
   3813     return BCM_E_NONE;
   3814 }
   3815 
   3816 /*
   3817  * Function:
   3818  *     _bcm_td2_adjust_lls_bw
   3819  * Purpose:
   3820  *     This function adjusts the bandwidth at the level in which the node is
   3821  *     being switched so that each node gets sufficient bandwidth to do the
   3822  *     switchover.
   3823  * Parameters:
   3824  *     unit              - (IN) unit number
   3825  *     port              - (IN) local port number 
   3826  *     node              - (IN) cosq node structure
   3827  *     child_lvl         - (IN) level of the child node
   3828  *     child_hw_index    - (IN) h/w index of the child node
   3829  *     start             - (IN) flag  
   3830  *     i_lls_tree        - (OUT) LLS info 
   3831  * Returns:
   3832  *     BCM_E_XXX
   3833  */
   3834 STATIC int
   3835 _bcm_td2_adjust_lls_bw(int unit, bcm_port_t port, _bcm_td2_cosq_node_t *node, 
   3836                        int child_lvl, int child_hw_index, int start, 
   3837                        _bcm_td2p_lls_info_t *i_lls_tree)
   3838 {
   3839     int rv = BCM_E_NONE, count, mem_size, ii, speed, jj;
   3840     soc_info_t *si;
   3841     
   3842     if (!soc_feature(unit, soc_feature_vector_based_spri)) {
   3843         return BCM_E_NONE;
   3844     }
   3845     
   3846     if (start) {
   3847         
   3848         sal_memset(i_lls_tree, 0, sizeof(_bcm_td2p_lls_info_t));
   3849         i_lls_tree->child_lvl = child_lvl;
   3850         i_lls_tree->child_hw_index = child_hw_index;
   3851 
   3852         if (node) {
   3853 
   3854             /* get to top node */
   3855             while(node->parent) { node = node->parent; }
   3856 
   3857             BCM_IF_ERROR_RETURN(_bcm_td2_cosq_traverse_lls_tree(unit, port,
   3858                                 node,_bcm_td2_lls_node_count, i_lls_tree));
   3859         } else {
   3860             BCM_IF_ERROR_RETURN(soc_td2_port_lls_traverse(unit, port,
   3861                                       _bcm_td2_lls_node_count, i_lls_tree));
   3862         }          
   3863 
   3864         for (count = 0, ii = 0; ii < SOC_TD2_NODE_LVL_MAX; ii++) {
   3865             count += i_lls_tree->node_count[ii];
   3866             for (jj = ii - 1; jj >= 0; jj--) {
   3867                 i_lls_tree->offset[ii] += i_lls_tree->node_count[jj];
   3868             }
   3869         }
   3870         
   3871         if (count == 0) {
   3872             return BCM_E_INIT;
   3873         }
   3874         
   3875         mem_size = sizeof(uint32)*SOC_MAX_MEM_WORDS*count;
   3876         i_lls_tree->mtro_entries = sal_alloc(mem_size, "lls_war_buf");
   3877         
   3878         if (port != CMIC_PORT(unit)) {
   3879             rv = soc_esw_portctrl_speed_get(unit, port, &speed);
   3880             if (rv == BCM_E_UNAVAIL) {
   3881                 si = &SOC_INFO(unit);
   3882                 speed = si->port_speed_max[port];
   3883             }
   3884         } else {
   3885             speed = 10000;
   3886         }
   3887         i_lls_tree->kbit_min = 0;
   3888         i_lls_tree->kbit_max = ((speed)/10)/i_lls_tree->node_count[child_lvl];
   3889 
   3890         for (count = 0, ii = 0; ii < SOC_TD2_NODE_LVL_MAX; ii++) {
   3891             i_lls_tree->count[ii] = 0;
   3892         }
   3893  
   3894         sal_memset(i_lls_tree->mtro_entries, 0, mem_size);
   3895         i_lls_tree->mtro_restore = FALSE;
   3896 
   3897         if (node) {
   3898 
   3899             /* get to top node */
   3900             while(node->parent) { node = node->parent; }
   3901 
   3902             BCM_IF_ERROR_RETURN(_bcm_td2_cosq_traverse_lls_tree(unit, port, node,
   3903                                     _bcm_td2_lls_shapers_remove, i_lls_tree));
   3904         } else {
   3905             BCM_IF_ERROR_RETURN(soc_td2_port_lls_traverse(unit, port,
   3906                                     _bcm_td2_lls_shapers_remove, i_lls_tree));
   3907         }
   3908     } else {
   3909         for (count = 0, ii = 0; ii < SOC_TD2_NODE_LVL_MAX; ii++) {
   3910             i_lls_tree->count[ii] = 0;
   3911         }
   3912 
   3913         if (node) {
   3914             /* get to top node */
   3915             while(node->parent) { node = node->parent; }
   3916 
   3917             rv = _bcm_td2_cosq_traverse_lls_tree(unit, port, node,
   3918                                     _bcm_td2_lls_shapers_restore, i_lls_tree);
   3919         } else {
   3920             rv = soc_td2_port_lls_traverse(unit, port,
   3921                                     _bcm_td2_lls_shapers_restore, i_lls_tree);
   3922         }
   3923        
   3924        if (i_lls_tree->mtro_entries) {
   3925             sal_free(i_lls_tree->mtro_entries);
   3926             i_lls_tree->mtro_entries = NULL;
   3927        }
   3928     }
   3929 
   3930     return rv;
   3931 }
   3932 
   3933 /*
   3934  * Function:
   3935  *     _bcm_td2_port_enqueue_set
   3936  * Purpose:
   3937  *     Enable or Disable the enqueing the packets to the port
   3938  * Parameters:
   3939  *     unit       - (IN) unit number
   3940  *     gport      - (IN) gport of the port 
   3941  *     enable     - (IN) TRUE to enable
   3942  *                      FALSE to disable
   3943  * Returns:
   3944  *     BCM_E_XXX
   3945  */
   3946 
   3947 int
   3948 _bcm_td2_port_enqueue_set(int unit, bcm_port_t gport, int enable)
   3949 {
   3950     bcm_port_t local_port;
   3951    
   3952     BCM_IF_ERROR_RETURN
   3953         (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port));
   3954 
   3955     SOC_IF_ERROR_RETURN(
   3956         soc_td2_port_mmu_tx_enable_set(unit, local_port, enable));
   3957     SOC_IF_ERROR_RETURN(
   3958         soc_td2_mmu_rx_enable_set(unit, local_port, enable));
   3959 
   3960     return BCM_E_NONE;
   3961 }
   3962 /*
   3963  * Function:
   3964  *     _bcm_td2_port_enqueue_get
   3965  * Purpose:
   3966  *      Getting the enqueing state of the port 
   3967  * Parameters:
   3968  *     unit       - (IN) unit number
   3969  *     gport      - (IN) gport of the port 
   3970  *     enable     - (IN) TRUE to enable
   3971  *                      FALSE to disable
   3972  * Returns:
   3973  *     BCM_E_XXX
   3974  */
   3975 
   3976 int
   3977 _bcm_td2_port_enqueue_get(int unit, bcm_port_t gport,
   3978                           int *enable)
   3979 {
   3980     uint64 rval64;
   3981     int mmu_port, phy_port, i;
   3982     int rv = BCM_E_NONE;
   3983     bcm_port_t local_port;
   3984     soc_info_t *si;
   3985     soc_reg_t reg_tmp;
   3986     soc_reg_t reg[3][2] = {
   3987         {
   3988             THDU_OUTPUT_PORT_RX_ENABLE0_64r,
   3989             THDU_OUTPUT_PORT_RX_ENABLE1_64r
   3990         },
   3991         {
   3992             MMU_THDM_DB_PORTSP_RX_ENABLE0_64r,
   3993             MMU_THDM_DB_PORTSP_RX_ENABLE1_64r
   3994         },
   3995         {
   3996             MMU_THDM_MCQE_PORTSP_RX_ENABLE0_64r,
   3997             MMU_THDM_MCQE_PORTSP_RX_ENABLE1_64r
   3998         }
   3999     };
   4000     int max_reg = 3;
   4001 
   4002     BCM_IF_ERROR_RETURN
   4003         (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port));
   4004 
   4005     si = &SOC_INFO(unit);
   4006 
   4007     phy_port = si->port_l2p_mapping[local_port];
   4008     mmu_port = si->port_p2m_mapping[phy_port];
   4009 
   4010     COMPILER_64_ZERO(rval64);
   4011 
   4012     /* Disable enqueue to the port */
   4013     for (i = 0; i < max_reg; i++) {
   4014         reg_tmp = SOC_TD2_PREG(unit, local_port, reg[i][0], reg[i][1]);
   4015 
   4016         SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg_tmp, REG_PORT_ANY, 0, &rval64));
   4017 
   4018         mmu_port &= 0x3f;
   4019         if (COMPILER_64_BITTEST(rval64 , mmu_port)) {
   4020             *enable = TRUE;
   4021         } else {
   4022             *enable = FALSE;
   4023         }
   4024     }
   4025     return rv;
   4026 }
   4027 
   4028 /*
   4029  * Function:
   4030  *     bcm_td2_lb_lls_init
   4031  * Purpose:
   4032  *     Construct cosq hierarchy for Loopback port in ETS mode
   4033  * Parameters:
   4034  *     unit  - (IN) unit number
   4035  * Returns:
   4036  *     BCM_E_XXX
   4037  */
   4038 STATIC int
   4039 bcm_td2_lb_lls_init(int unit)
   4040 {
   4041     soc_port_t local_port;
   4042     _bcm_td2_mmu_info_t *mmu_info;
   4043     _bcm_td2_cosq_node_t *node = NULL;
   4044     _bcm_td2_cosq_port_info_t *port_info;
   4045     _bcm_td2_pipe_resources_t *res;
   4046     bcm_gport_t gport, gport_l0, gport_l1[9], gport_l2[9];
   4047     int phy_port, mmu_port;
   4048     uint32 sched_encap;
   4049     int id, pipe, cos;
   4050     int l1_node_cnt = 9;
   4051     int l2_node_cnt = 9;    /* 8 MCQs + 1 QCN queue */
   4052 
   4053     mmu_info = _bcm_td2_mmu_info[unit];
   4054     if(mmu_info == NULL) {
   4055         return BCM_E_INIT;
   4056     }
   4057 
   4058     /* coverity[illegal_address: FALSE] */
   4059     SOC_PBMP_ITER(PBMP_LB(unit), local_port) {
   4060         if (local_port >= _BCM_TD2_MAX_PORT) {
   4061             return BCM_E_INTERNAL;
   4062         }
   4063         port_info = &mmu_info->port_info[local_port];
   4064         pipe = _BCM_TD2_PORT_TO_PIPE(unit, local_port);
   4065         res = _BCM_TD2_PRESOURCES(mmu_info, pipe);
   4066 
   4067         /* Root node*/
   4068         node = &mmu_info->sched_node[local_port];
   4069         sched_encap = (local_port << 8) | local_port;
   4070         BCM_GPORT_SCHEDULER_SET(gport, sched_encap);
   4071         node->gport = gport;
   4072         node->level = SOC_TD2_NODE_LVL_ROOT;
   4073         node->type = _BCM_TD2_NODE_SCHEDULER;
   4074         phy_port = SOC_INFO(unit).port_l2p_mapping[local_port];
   4075         mmu_port = SOC_INFO(unit).port_p2m_mapping[phy_port];
   4076         node->hw_index = mmu_port % 64;
   4077         node->numq = 1;
   4078         node->local_port = local_port;
   4079         node->in_use = TRUE;
   4080         node->attached_to_input = 0;
   4081 
   4082         /* L0.0 node */
   4083         node = NULL;
   4084         for (id = _BCM_TD2_NUM_PORT_SCHEDULERS;
   4085              id < _BCM_TD2_NUM_TOTAL_SCHEDULERS; id++) {
   4086             if (mmu_info->sched_node[id].in_use == FALSE) {
   4087                 node = &mmu_info->sched_node[id];
   4088                 node->in_use = TRUE;
   4089                 break;
   4090             }
   4091         }
   4092         if (!node) {
   4093             return BCM_E_RESOURCE;
   4094         }
   4095 
   4096         node = &mmu_info->sched_node[id];
   4097         sched_encap = (id << 8) | local_port;
   4098         BCM_GPORT_SCHEDULER_SET(gport_l0, sched_encap);
   4099         node->gport = gport_l0;
   4100         node->numq = l1_node_cnt;
   4101         node->local_port = local_port;
   4102         node->type = _BCM_TD2_NODE_SCHEDULER;
   4103         node->attached_to_input = -1;
   4104 
   4105         /* Attach to Root node */
   4106         BCM_IF_ERROR_RETURN
   4107             (bcm_td2_cosq_gport_attach(unit, gport_l0, gport, 0));
   4108 
   4109         /* L1.0 ~ L1.8 node */
   4110         for (cos = 0; cos < l1_node_cnt; cos++) {
   4111             node = NULL;
   4112             for (id = _BCM_TD2_NUM_PORT_SCHEDULERS;
   4113                  id < _BCM_TD2_NUM_TOTAL_SCHEDULERS; id++) {
   4114                 if (mmu_info->sched_node[id].in_use == FALSE) {
   4115                     node = &mmu_info->sched_node[id];
   4116                     node->in_use = TRUE;
   4117                     break;
   4118                 }
   4119             }
   4120             if (!node) {
   4121                 return BCM_E_RESOURCE;
   4122             }
   4123 
   4124             node = &mmu_info->sched_node[id];
   4125             sched_encap = (id << 8) | local_port;
   4126             BCM_GPORT_SCHEDULER_SET(gport_l1[cos], sched_encap);
   4127             node->gport = gport_l1[cos];
   4128             node->numq = 1;
   4129             node->local_port = local_port;
   4130             node->type = _BCM_TD2_NODE_SCHEDULER;
   4131             node->attached_to_input = -1;
   4132 
   4133             /* Attach to L0 node */
   4134             BCM_IF_ERROR_RETURN
   4135                 (bcm_td2_cosq_gport_attach(unit, gport_l1[cos], gport_l0, cos));
   4136         }
   4137 
   4138         /* L2 mc queue & QCN queue */
   4139         for (cos = 0; cos < l2_node_cnt; cos++) {
   4140             for (id = port_info->mc_base; id < port_info->mc_limit; id++) {
   4141                 if (res->p_mc_queue_node[id].numq == 0) {
   4142                     break;
   4143                 }
   4144             }
   4145 
   4146             if (id == port_info->mc_limit) {
   4147                 return BCM_E_RESOURCE;
   4148             }
   4149 
   4150             /* set index bits */
   4151             BCM_GPORT_MCAST_QUEUE_GROUP_SYSQID_SET(gport_l2[cos], local_port, id);
   4152             node = &res->p_mc_queue_node[id];
   4153             node->gport = gport_l2[cos];
   4154             node->numq = 1;
   4155             node->level = SOC_TD2_NODE_LVL_L2;
   4156             node->type = _BCM_TD2_NODE_MCAST;
   4157             node->hw_cosq = id - port_info->mc_base;
   4158             node->hw_index = soc_td2_l2_hw_index(unit, id, 0);
   4159             node->local_port = local_port;
   4160             node->remote_modid = -1;
   4161             node->remote_port  = -1;
   4162             node->in_use = TRUE;
   4163 
   4164             /* Attach to L1 node */
   4165             BCM_IF_ERROR_RETURN
   4166                 (bcm_td2_cosq_gport_attach(unit, gport_l2[cos],
   4167                                            gport_l1[cos], 0));
   4168          }
   4169 
   4170     }
   4171 
   4172     return BCM_E_NONE;
   4173 }
   4174 /*
   4175  * Function:
   4176  *     bcm_td2_cosq_hw_idx_get
   4177  * Purpose:
   4178  *     Get cosq hardware index
   4179  * Returns:
   4180  *     BCM_E_XXX
   4181  */
   4182 
   4183 int
   4184 _bcm_td2_cosq_hw_idx_get(int unit, int max_count, bcm_gport_t *port, int *hw_idx, int* count)
   4185 {
   4186     _bcm_td2_mmu_info_t *mmu_info;
   4187     _bcm_td2_pipe_resources_t *res;
   4188     int pipe = 0, qmax, qmin, id, i = 0;
   4189     if (port == NULL || hw_idx == NULL || count == NULL) {
   4190         return BCM_E_PARAM;
   4191     }
   4192 
   4193     mmu_info = _bcm_td2_mmu_info[unit];
   4194     for (pipe = 0; pipe < 2; pipe++) {
   4195         res = _BCM_TD2_PRESOURCES(mmu_info, pipe);
   4196         qmax = (pipe + 1) * _BCM_TD2_NUM_L2_UC_LEAVES_PER_PIPE;
   4197         qmin = res->num_base_queues +
   4198                        (pipe * _BCM_TD2_NUM_L2_UC_LEAVES_PER_PIPE);
   4199         for (id = qmin; id < qmax; id++) {
   4200             if (res->p_queue_node[id].numq == 0 ||
   4201                 res->p_queue_node[id].level != SOC_TD2_NODE_LVL_L2) {
   4202                 continue;
   4203             }
   4204             if (i >= max_count) {
   4205                 return BCM_E_CONFIG;
   4206             }
   4207             /*for Y pipe, uc queue starts at hw_idx 2048*/
   4208             hw_idx[i] = res->p_queue_node[id].hw_index + pipe * 2048;
   4209             port[i] = res->p_queue_node[id].local_port;
   4210             i++;
   4211         }
   4212     }
   4213     *count = i;
   4214     return BCM_E_NONE;
   4215  }
   4216 
   4217 /*
   4218  * Function:
   4219  *     bcm_td2_cosq_gport_add
   4220  * Purpose:
   4221  *     Create a cosq gport structure
   4222  * Parameters:
   4223  *     unit  - (IN) unit number
   4224  *     port  - (IN) port number
   4225  *     numq  - (IN) number of COS queues
   4226  *     flags - (IN) flags (BCM_COSQ_GPORT_XXX)
   4227  *     gport - (OUT) GPORT identifier
   4228  * Returns:
   4229  *     BCM_E_XXX
   4230  */
   4231 int
   4232 bcm_td2_cosq_gport_add(int unit, bcm_gport_t port, int numq, uint32 flags,
   4233                       bcm_gport_t *gport)
   4234 {
   4235     _bcm_td2_mmu_info_t *mmu_info;
   4236     _bcm_td2_cosq_node_t *node = NULL;
   4237     _bcm_td2_cosq_port_info_t *port_info;
   4238     uint32 sched_encap;
   4239     _bcm_td2_pipe_resources_t *res;
   4240     int phy_port, mmu_port, local_port;
   4241     int id, ii, q_base, pipe, qmin, qmax;
   4242     bcm_gport_t tmp_gport;
   4243 
   4244     LOG_INFO(BSL_LS_BCM_COSQ,
   4245              (BSL_META_U(unit,
   4246                          "bcm_td2_cosq_gport_add: unit=%d port=0x%x numq=%d flags=0x%x\n"),
   4247               unit, port, numq, flags));
   4248     
   4249     if (!soc_feature(unit, soc_feature_ets)) {
   4250         return BCM_E_UNAVAIL;
   4251     }
   4252 
   4253     if (gport == NULL) {
   4254         return BCM_E_PARAM;
   4255     }
   4256 
   4257     if (_bcm_td2_mmu_info[unit] == NULL) {
   4258         return BCM_E_INIT;
   4259     }
   4260 
   4261     BCM_IF_ERROR_RETURN
   4262         (_bcm_td2_cosq_localport_resolve(unit, port, &local_port));
   4263 
   4264     if (local_port < 0) {
   4265         return BCM_E_PORT;
   4266     }
   4267 
   4268     /* Check Alignment request is not for unsupported type */
   4269     if (flags & BCM_COSQ_GPORT_SCHEDULER_PFC_ALIGN) {
   4270         if (!(flags == (BCM_COSQ_GPORT_SCHEDULER |
   4271                         BCM_COSQ_GPORT_SCHEDULER_PFC_ALIGN))) {
   4272             return BCM_E_PARAM;
   4273         }
   4274     }
   4275 
   4276     mmu_info = _bcm_td2_mmu_info[unit];
   4277 
   4278     port_info = &mmu_info->port_info[local_port];
   4279     pipe = _BCM_TD2_PORT_TO_PIPE(unit, local_port);
   4280     res = _BCM_TD2_PRESOURCES(mmu_info, pipe);
   4281 
   4282     if (!mmu_info->ets_mode) {
   4283 
   4284         /* cleanup the default lls setup */
   4285         SOC_IF_ERROR_RETURN(soc_td2_lls_reset(unit));
   4286 
   4287         mmu_info->ets_mode = 1;
   4288 
   4289         BCM_IF_ERROR_RETURN(bcm_td2_lb_lls_init(unit));
   4290     }
   4291 
   4292     switch (flags) {
   4293     case BCM_COSQ_GPORT_UCAST_QUEUE_GROUP:
   4294         if (numq != 1) {
   4295             return BCM_E_PARAM;
   4296         }
   4297 
   4298         if (IS_CPU_PORT(unit, local_port)) {
   4299             return BCM_E_PARAM;
   4300         }
   4301 
   4302         for (id = port_info->uc_base; id < port_info->uc_limit; id++) {
   4303             if (res->p_queue_node[id].numq == 0) {
   4304                 break;
   4305             }
   4306         }
   4307 
   4308         qmax = (pipe + 1) * _BCM_TD2_NUM_L2_UC_LEAVES_PER_PIPE;
   4309         if (id == port_info->uc_limit) {
   4310             if (IS_TD2_HSP_PORT(unit, local_port)) {
   4311                 return BCM_E_RESOURCE;
   4312             }
   4313             qmin = res->num_base_queues +
   4314                    (pipe * _BCM_TD2_NUM_L2_UC_LEAVES_PER_PIPE);
   4315             for (id = qmin; id < qmax; id++) {
   4316                 if (res->p_queue_node[id].numq == 0) {
   4317                     break;
   4318                 }
   4319             }
   4320         }
   4321 
   4322         if (id == qmax) {
   4323             return BCM_E_RESOURCE;
   4324         }
   4325 
   4326         BCM_GPORT_UCAST_QUEUE_GROUP_SYSQID_SET(*gport, local_port, id);
   4327         node = &res->p_queue_node[id];
   4328         node->gport = *gport;
   4329         node->numq = numq;
   4330         node->level = SOC_TD2_NODE_LVL_L2;
   4331         node->hw_cosq = id - port_info->uc_base;
   4332         node->hw_index = soc_td2_l2_hw_index(unit, id, 1);
   4333         node->local_port = local_port;
   4334         node->remote_modid = -1;
   4335         node->remote_port  = -1;
   4336         node->type = _BCM_TD2_NODE_UCAST;
   4337         node->in_use = TRUE;
   4338         break;
   4339 
   4340     case BCM_COSQ_GPORT_SUBSCRIBER:
   4341     case BCM_COSQ_GPORT_VIRTUAL_PORT:
   4342     case BCM_COSQ_GPORT_VLAN_UCAST_QUEUE_GROUP:
   4343         if (IS_TD2_HSP_PORT(unit, local_port)) {
   4344             return BCM_E_PARAM;
   4345         }
   4346         /* Service Queueing are outside default queues. Hence NO alignment
   4347          * required.
   4348          */
   4349         BCM_IF_ERROR_RETURN(
   4350             _bcm_td2_node_index_get(res->ext_qlist.bits, res->num_base_queues,
   4351                                      _BCM_TD2_NUM_L2_UC_LEAVES_PER_PIPE, numq, 
   4352                                      1, &q_base));
   4353 
   4354         _bcm_td2_node_index_set(&res->ext_qlist, q_base, numq);
   4355         qmin = res->num_base_queues + (pipe * _BCM_TD2_NUM_L2_UC_LEAVES_PER_PIPE);
   4356         qmax = (pipe + 1) * _BCM_TD2_NUM_L2_UC_LEAVES_PER_PIPE;
   4357 
   4358         for (ii = 0, id = qmin; id < qmax; id++) {
   4359             if (res->p_queue_node[id].numq > 0) {
   4360                 ii = 0;
   4361             } else {
   4362                 ii += 1;
   4363 
   4364                 if (ii == numq) {
   4365                     break;
   4366                 }
   4367             }
   4368         }
   4369 
   4370         if (ii != numq) {
   4371             return BCM_E_RESOURCE;
   4372         }
   4373 
   4374         id = id - (numq - 1);
   4375 
   4376         for (ii = 0; ii < numq; ii++, id++) {
   4377             BCM_GPORT_UCAST_QUEUE_GROUP_SYSQID_SET(tmp_gport, local_port, id);
   4378             node= &res->p_queue_node[id];
   4379             node->gport = tmp_gport;
   4380             node->numq = numq - ii;
   4381             node->level = SOC_TD2_NODE_LVL_L2;
   4382             node->type = (flags == BCM_COSQ_GPORT_VIRTUAL_PORT) ?
   4383                             _BCM_TD2_NODE_VM_UCAST : _BCM_TD2_NODE_SERVICE_UCAST;
   4384             node->hw_index = q_base + ii;
   4385             /* by default assign the cosq on order of order of alocation,
   4386              * can be overriddedn by cos_mapping_set */
   4387             node->hw_cosq = ii;
   4388             node->local_port = local_port;
   4389             node->remote_modid = -1;
   4390             node->remote_port  = -1;
   4391             node->in_use = TRUE;
   4392 
   4393             if (ii == 0) {
   4394                 *gport = tmp_gport;
   4395             }
   4396         }
   4397         break;
   4398 
   4399     case BCM_COSQ_GPORT_DESTMOD_UCAST_QUEUE_GROUP:
   4400         if (numq != 1) {
   4401             return BCM_E_PARAM;
   4402         }
   4403 
   4404         if (!IS_HG_PORT(unit, local_port)) {
   4405             return BCM_E_PORT;
   4406         }
   4407 
   4408     qmin = res->num_base_queues + (pipe * _BCM_TD2_NUM_L2_UC_LEAVES_PER_PIPE);
   4409     qmax = (pipe + 1) * _BCM_TD2_NUM_L2_UC_LEAVES_PER_PIPE;
   4410         for (id = qmin; id < qmax; id++) {
   4411             if (res->p_queue_node[id].numq == 0) {
   4412                 break;
   4413             }
   4414         }
   4415 
   4416         if (id >= qmax) {
   4417             return BCM_E_RESOURCE;
   4418         }
   4419 
   4420         BCM_GPORT_UCAST_QUEUE_GROUP_SYSQID_SET(*gport, local_port, id);
   4421         node = &res->p_queue_node[id];
   4422         node->gport = *gport;
   4423         node->numq = numq;
   4424         node->level = SOC_TD2_NODE_LVL_L2;
   4425         node->type = _BCM_TD2_NODE_VOQ;
   4426         node->hw_index = -1;
   4427         /* by default assign the cosq on order of order of alocation,
   4428          * can be overriddedn by cos_mapping_set */
   4429         node->hw_cosq = -1;
   4430         node->local_port = local_port;
   4431         node->remote_modid = -1;
   4432         node->remote_port  = -1;
   4433         node->in_use = TRUE;
   4434         break;
   4435 
   4436     case BCM_COSQ_GPORT_MCAST_QUEUE_GROUP:
   4437         if (numq != 1) {
   4438             return BCM_E_PARAM;
   4439         }
   4440 
   4441         for (id = port_info->mc_base; id < port_info->mc_limit; id++) {
   4442             if (res->p_mc_queue_node[id].numq == 0) {
   4443                 break;
   4444             }
   4445         }
   4446         
   4447         if (id == port_info->mc_limit) {
   4448             return BCM_E_RESOURCE;
   4449         }            
   4450 
   4451         /* set index bits */
   4452         BCM_GPORT_MCAST_QUEUE_GROUP_SYSQID_SET(*gport, local_port, id);
   4453         node = &res->p_mc_queue_node[id];
   4454         node->gport = *gport;
   4455         node->numq = numq;
   4456         node->level = SOC_TD2_NODE_LVL_L2;
   4457         node->type = _BCM_TD2_NODE_MCAST;
   4458         node->hw_cosq = id - port_info->mc_base;
   4459         node->hw_index = soc_td2_l2_hw_index(unit, id, 0);
   4460         node->local_port = local_port;
   4461         node->remote_modid = -1;
   4462         node->remote_port  = -1;
   4463         node->in_use = TRUE;
   4464         break;
   4465 
   4466     case BCM_COSQ_GPORT_SCHEDULER:
   4467     case BCM_COSQ_GPORT_SCHEDULER | BCM_COSQ_GPORT_SCHEDULER_PFC_ALIGN:
   4468         if (numq < -1) {
   4469             return BCM_E_PARAM;
   4470         }
   4471         for (id = _BCM_TD2_NUM_PORT_SCHEDULERS;
   4472              id < _BCM_TD2_NUM_TOTAL_SCHEDULERS; id++) {
   4473             if (mmu_info->sched_node[id].in_use == FALSE) {
   4474                 node = &mmu_info->sched_node[id];
   4475                 node->in_use = TRUE;
   4476                 break;
   4477             }
   4478         }
   4479         if (!node) {
   4480             return BCM_E_RESOURCE;
   4481         }
   4482 
   4483         node = &mmu_info->sched_node[id];
   4484         sched_encap = (id << 8) | local_port;
   4485         BCM_GPORT_SCHEDULER_SET(*gport, sched_encap);
   4486         node->gport = *gport;
   4487         node->numq = numq;
   4488         node->local_port = local_port;
   4489         node->type = _BCM_TD2_NODE_SCHEDULER;
   4490         node->attached_to_input = -1;
   4491         if (flags & BCM_COSQ_GPORT_SCHEDULER_PFC_ALIGN) {
   4492             node->node_align_value = _BCM_TD2_START_INDEX_ALIGN_PFC;
   4493         } else {
   4494             node->node_align_value = _BCM_TD2_START_INDEX_ALIGN_DEFAULT;
   4495         }
   4496         break;
   4497 
   4498     case BCM_COSQ_GPORT_WITH_ID:
   4499     case 0:
   4500         if (numq < -1) {
   4501             return BCM_E_PARAM;
   4502         }
   4503 
   4504         /* this is a port level scheduler */
   4505         id = local_port;
   4506 
   4507         if ( id < 0 || id >= _BCM_TD2_NUM_PORT_SCHEDULERS) {
   4508             return BCM_E_PARAM;
   4509         }
   4510 
   4511         if (numq >= _BCM_TD2_NUM_L0_SCHEDULER_PER_PIPE) {
   4512             return BCM_E_RESOURCE;
   4513         }
   4514 
   4515         node = &mmu_info->sched_node[id];
   4516         sched_encap = (id << 8) | local_port;
   4517         BCM_GPORT_SCHEDULER_SET(*gport, sched_encap);
   4518         node->gport = *gport;
   4519         node->level = SOC_TD2_NODE_LVL_ROOT;
   4520         node->type = _BCM_TD2_NODE_SCHEDULER;
   4521         phy_port = SOC_INFO(unit).port_l2p_mapping[local_port];
   4522         mmu_port = SOC_INFO(unit).port_p2m_mapping[phy_port];
   4523         node->hw_index = mmu_port % 64;
   4524 
   4525         if (IS_TD2_HSP_PORT(unit, local_port)) {
   4526             /* free any schedulers in use by legacy setup */
   4527             BCM_IF_ERROR_RETURN(_bcm_td2_cosq_set_scheduler_states(unit, local_port, 0));
   4528             BCM_IF_ERROR_RETURN(soc_td2_lls_port_uninit(unit, local_port));
   4529         }
   4530 
   4531         if (IS_TD2_HSP_PORT(unit, local_port)) {
   4532             node->numq = _BCM_TD2_HSP_PORT_MAX_L0;
   4533         } else {
   4534             node->numq = numq;
   4535         }
   4536         node->local_port = local_port;
   4537         node->in_use = TRUE;
   4538         node->attached_to_input = 0;
   4539         break;
   4540 
   4541     default:
   4542         return BCM_E_PARAM;
   4543     }
   4544 
   4545     LOG_INFO(BSL_LS_BCM_COSQ,
   4546              (BSL_META_U(unit,
   4547                          "                       gport=0x%x\n"),
   4548               *gport));
   4549 
   4550     return BCM_E_NONE;
   4551 }
   4552 
   4553 /*
   4554  * Function:
   4555  *     bcm_td2_cosq_gport_detach
   4556  * Purpose:
   4557  *     Detach sched_port from the specified index (cosq) of input_port
   4558  * Parameters:
   4559  *     unit       - (IN) unit number
   4560  *     sched_port - (IN) scheduler GPORT identifier
   4561  *     input_port - (IN) GPORT to detach from
   4562  *     cosq       - (IN) COS queue to detach from
   4563  * Returns:
   4564  *     BCM_E_XXX
   4565  */
   4566 int
   4567 bcm_td2_cosq_gport_detach(int unit, bcm_gport_t sched_gport,
   4568                          bcm_gport_t input_gport, bcm_cos_queue_t cosq)
   4569 {
   4570     _bcm_td2_cosq_node_t *sched_node, *input_node = NULL, *prev_node;
   4571     bcm_port_t sched_port, input_port = -1;
   4572     _bcm_td2_cosq_node_t *parent;
   4573     _bcm_td2_cosq_list_t *list;
   4574     _bcm_td2_mmu_info_t *mmu_info;
   4575     _bcm_td2_pipe_resources_t * res;
   4576     _bcm_td2_cosq_port_info_t *port_info;
   4577     int start = 0, end = 0, q_base, hw_index;
   4578 
   4579     if (_bcm_td2_mmu_info[unit] == NULL) {
   4580         return BCM_E_INIT;
   4581     }
   4582 
   4583     if ((BCM_GPORT_IS_UCAST_QUEUE_GROUP(input_gport)) ||
   4584         (BCM_GPORT_IS_MCAST_QUEUE_GROUP(input_gport))) {
   4585         return BCM_E_PARAM;
   4586     }
   4587 
   4588     BCM_IF_ERROR_RETURN
   4589         (_bcm_td2_cosq_node_get(unit, sched_gport, 0, NULL, &sched_port, NULL,
   4590                                &sched_node));
   4591 
   4592     if (sched_node->attached_to_input < 0) {
   4593         /* Not attached yet */
   4594         return BCM_E_PORT;
   4595     }
   4596 
   4597     if (input_gport != BCM_GPORT_INVALID) {
   4598         if (BCM_GPORT_IS_SCHEDULER(input_gport) || 
   4599             BCM_GPORT_IS_MODPORT(input_gport)   || 
   4600             BCM_GPORT_IS_LOCAL(input_gport)) {
   4601                BCM_IF_ERROR_RETURN
   4602                 (_bcm_td2_cosq_node_get(unit, input_gport, 0, NULL, 
   4603                                     &input_port, NULL, &input_node));
   4604         } else {
   4605             if (!(BCM_GPORT_IS_SCHEDULER(sched_gport) || 
   4606                   BCM_GPORT_IS_UCAST_QUEUE_GROUP(sched_gport) ||
   4607                   BCM_GPORT_IS_MCAST_QUEUE_GROUP(sched_gport))) {
   4608                 return BCM_E_PARAM;
   4609             }
   4610             else {
   4611                 BCM_IF_ERROR_RETURN
   4612                 (_bcm_td2_cosq_localport_resolve(unit, input_gport,
   4613                                                 &input_port));
   4614                 input_node = NULL;
   4615             }
   4616         }
   4617     }
   4618 
   4619     if (input_port == -1) {
   4620         return BCM_E_PORT;
   4621     }
   4622 
   4623     mmu_info = _bcm_td2_mmu_info[unit];
   4624     port_info = &mmu_info->port_info[input_port];
   4625     res = port_info->resources;
   4626 
   4627     if (sched_port != input_port) {
   4628         return BCM_E_PORT;
   4629     }
   4630 
   4631     if (sched_node->parent != input_node) {
   4632         return BCM_E_PORT;
   4633     }
   4634 
   4635     if ((cosq < -1) || 
   4636         (input_node && (input_node->numq != -1) && (cosq >= input_node->numq))) {
   4637         return BCM_E_PARAM;
   4638     }
   4639 
   4640      if (cosq != -1) {
   4641         if (sched_node->attached_to_input != cosq) {
   4642             return BCM_E_PARAM;
   4643         }
   4644     }
   4645 
   4646     if (sched_node->type == _BCM_TD2_NODE_SERVICE_UCAST) {
   4647         end = sched_node->numq;
   4648     } else {
   4649         end = 1;
   4650     }
   4651 
   4652     for (start = 0; start < end; start++) {
   4653         /* unresolve the node - delete this node from parent's child list */
   4654         BCM_IF_ERROR_RETURN(_bcm_td2_cosq_node_unresolve(unit, sched_node, cosq));
   4655         
   4656         BCM_IF_ERROR_RETURN(
   4657             soc_td2_cosq_set_sched_parent(unit, input_port, 
   4658                         sched_node->level, sched_node->hw_index, 
   4659                         _soc_td2_invalid_parent_index(unit, sched_node->level)));
   4660 
   4661         /* now remove from the sw tree */
   4662         if (sched_node->parent != NULL) {
   4663             parent = sched_node->parent;
   4664             if (sched_node->parent->child == sched_node) {
   4665                 sched_node->parent->child = sched_node->sibling;
   4666             } else {
   4667                 prev_node = sched_node->parent->child;
   4668                 while (prev_node != NULL && prev_node->sibling != sched_node) {
   4669                     prev_node = prev_node->sibling;
   4670                 }
   4671                 if (prev_node == NULL) {
   4672                     return BCM_E_INTERNAL;
   4673                 }
   4674                 prev_node->sibling = sched_node->sibling;
   4675             }
   4676             sched_node->parent = NULL;
   4677             sched_node->sibling = NULL;
   4678             sched_node->attached_to_input = -1;
   4679             if (0 == start) {
   4680                 hw_index = sched_node->hw_index;
   4681                 q_base = hw_index;
   4682                 if ((sched_node->type == _BCM_TD2_NODE_VM_UCAST) || 
   4683                     (sched_node->type == _BCM_TD2_NODE_SERVICE_UCAST)) { 
   4684                         BCM_IF_ERROR_RETURN(
   4685                             _bcm_td2_node_index_clear(&res->ext_qlist, 
   4686                                                       q_base, sched_node->numq)); 
   4687                 }
   4688             }
   4689 
   4690             if (parent->child == NULL) {
   4691                 list = NULL;
   4692                 switch (parent->level) {
   4693                     case SOC_TD2_NODE_LVL_ROOT:
   4694                         list = &res->l0_sched_list;
   4695                         sched_node->hw_index = -1;
   4696                         break;
   4697                     case SOC_TD2_NODE_LVL_L0:
   4698                         list = &res->l1_sched_list;
   4699                         sched_node->hw_index = -1;
   4700                         break;
   4701                     case SOC_TD2_NODE_LVL_L1:
   4702                         if (sched_node->type == _BCM_TD2_NODE_VOQ) {
   4703                             list = &res->ext_qlist;
   4704                         }
   4705                         break;
   4706                     default:
   4707                         break;
   4708                 }
   4709 
   4710                 if (list) {
   4711                     BCM_IF_ERROR_RETURN(_bcm_td2_node_index_clear(list, 
   4712                                 parent->base_index, parent->base_size));
   4713                     parent->base_index = -1;
   4714                     parent->base_size  = 0;
   4715                 }
   4716             }
   4717         }
   4718         if ((sched_node->type == _BCM_TD2_NODE_SERVICE_UCAST) && 
   4719             ((start + 1) < end)){
   4720             BCM_IF_ERROR_RETURN
   4721                 (_bcm_td2_cosq_node_get(unit, sched_gport, start + 1, NULL,
   4722                                         &sched_port, NULL, &sched_node));
   4723             if (!sched_node) {
   4724                 return BCM_E_NOT_FOUND;
   4725             }
   4726         }
   4727     }
   4728 
   4729     LOG_INFO(BSL_LS_BCM_COSQ,
   4730              (BSL_META_U(unit,
   4731                          "                         hw_cosq=%d\n"),
   4732               sched_node->attached_to_input));
   4733 
   4734     return BCM_E_NONE;
   4735 }
   4736 
   4737 STATIC int
   4738 _bcm_td2_cosq_gport_delete_all(int unit, bcm_gport_t gport)
   4739 {
   4740     _bcm_td2_cosq_node_t *node, *tnode, *base_node;
   4741     int ii, local_port, phy_port, mmu_port, hw_index;
   4742     _bcm_td2_mmu_info_t *mmu_info;
   4743     soc_info_t *si;
   4744 
   4745     LOG_INFO(BSL_LS_BCM_COSQ,
   4746              (BSL_META_U(unit,
   4747                          "bcm_td2_cosq_gport_delete_all: unit=%d gport=0x%x\n"),
   4748               unit, gport));
   4749 
   4750     node = NULL;
   4751     base_node= NULL;
   4752 
   4753     if (!soc_feature(unit, soc_feature_ets)) {
   4754         return BCM_E_UNAVAIL;
   4755     }
   4756 
   4757     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 
   4758         BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) ||
   4759         BCM_GPORT_IS_SCHEDULER(gport)) {
   4760         BCM_IF_ERROR_RETURN
   4761             (_bcm_td2_cosq_node_get(unit, gport, 0, NULL, &local_port, NULL, &node));
   4762     } else {
   4763         local_port = (BCM_GPORT_IS_LOCAL(gport)) ?
   4764           BCM_GPORT_LOCAL_GET(gport) : BCM_GPORT_MODPORT_PORT_GET(gport);
   4765 
   4766         if (!SOC_PORT_VALID(unit, local_port)) {
   4767             return BCM_E_PORT;
   4768         }
   4769        
   4770         mmu_info = _bcm_td2_mmu_info[unit];
   4771         si = &SOC_INFO(unit);
   4772         phy_port = si->port_l2p_mapping[local_port];
   4773         mmu_port = si->port_p2m_mapping[phy_port];
   4774         hw_index = _BCM_TD2_ROOT_SCHED_INDEX(unit, mmu_port);
   4775 
   4776         for (ii = 0; ii < _BCM_TD2_NUM_TOTAL_SCHEDULERS; ii++) {
   4777             tnode = &mmu_info->sched_node[ii];
   4778             if (tnode->in_use == FALSE) {
   4779                 continue;
   4780             }
   4781             if ((tnode->level == SOC_TD2_NODE_LVL_ROOT) &&
   4782                 (tnode->hw_index == hw_index) && 
   4783                 (tnode->local_port == local_port)) {   
   4784                 /* check both mmu_port(unique only within a pipe)
   4785                    and local_port(unique witin system) to get the 
   4786                    correct node */
   4787                 node = tnode;
   4788                 break;
   4789             }
   4790         }
   4791         if (node == NULL) {
   4792             return BCM_E_NONE;
   4793         }
   4794     }
   4795 
   4796     if (node->child != NULL) {
   4797         BCM_IF_ERROR_RETURN(_bcm_td2_cosq_gport_delete_all(unit, node->child->gport));
   4798     }
   4799 
   4800     if (node->sibling != NULL) {
   4801         BCM_IF_ERROR_RETURN(_bcm_td2_cosq_gport_delete_all(unit, node->sibling->gport));
   4802     }
   4803 
   4804     if (node->level != SOC_TD2_NODE_LVL_ROOT && node->attached_to_input >= 0) {
   4805         BCM_IF_ERROR_RETURN
   4806             (bcm_td2_cosq_gport_detach(unit, node->gport, 
   4807                                 node->parent->gport, node->attached_to_input));
   4808     }
   4809     if ((node->type == _BCM_TD2_NODE_VOQ) && 
   4810             (node->remote_modid > 0)) {
   4811         _bcm_td2_voq_next_base_node_get (unit, local_port,
   4812                 node->remote_modid, &base_node);
   4813         if (base_node != NULL) {
   4814             BCM_PBMP_ASSIGN(base_node->fabric_pbmp,
   4815                     node->fabric_pbmp);
   4816         }
   4817     }
   4818 
   4819     _BCM_TD2_COSQ_NODE_INIT(node);
   4820     return BCM_E_NONE;
   4821 }
   4822 
   4823 /*
   4824  * Function:
   4825  *     bcm_td2_cosq_gport_delete
   4826  * Purpose:
   4827  *     Destroy a cosq gport structure
   4828  * Parameters:
   4829  *     unit  - (IN) unit number
   4830  *     gport - (IN) GPORT identifier
   4831  * Returns:
   4832  *     BCM_E_XXX
   4833  */
   4834 int
   4835 bcm_td2_cosq_gport_delete(int unit, bcm_gport_t gport)
   4836 {
   4837     _bcm_td2_cosq_node_t *node, *tnode, *base_node;
   4838     int ii, local_port, phy_port, mmu_port, hw_index;
   4839     _bcm_td2_mmu_info_t *mmu_info;
   4840     soc_info_t *si;
   4841 
   4842     LOG_INFO(BSL_LS_BCM_COSQ,
   4843              (BSL_META_U(unit,
   4844                          "bcm_td2_cosq_gport_delete: unit=%d gport=0x%x\n"),
   4845               unit, gport));
   4846 
   4847     node = NULL;
   4848     base_node= NULL;
   4849 
   4850     if (!soc_feature(unit, soc_feature_ets)) {
   4851         return BCM_E_UNAVAIL;
   4852     }
   4853 
   4854     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 
   4855         BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) ||
   4856         BCM_GPORT_IS_SCHEDULER(gport)) {
   4857         BCM_IF_ERROR_RETURN
   4858             (_bcm_td2_cosq_node_get(unit, gport, 0, NULL, &local_port, NULL, &node));
   4859     } else {
   4860         local_port = (BCM_GPORT_IS_LOCAL(gport)) ?
   4861           BCM_GPORT_LOCAL_GET(gport) : BCM_GPORT_MODPORT_PORT_GET(gport);
   4862 
   4863         if (!SOC_PORT_VALID(unit, local_port)) {
   4864             return BCM_E_PORT;
   4865         }
   4866        
   4867         mmu_info = _bcm_td2_mmu_info[unit];
   4868         si = &SOC_INFO(unit);
   4869         phy_port = si->port_l2p_mapping[local_port];
   4870         mmu_port = si->port_p2m_mapping[phy_port];
   4871         hw_index = _BCM_TD2_ROOT_SCHED_INDEX(unit, mmu_port);
   4872 
   4873         for (ii = 0; ii < _BCM_TD2_NUM_TOTAL_SCHEDULERS; ii++) {
   4874             tnode = &mmu_info->sched_node[ii];
   4875             if (tnode->in_use == FALSE) {
   4876                 continue;
   4877             }
   4878             if ((tnode->level == SOC_TD2_NODE_LVL_ROOT) &&
   4879                 (tnode->hw_index == hw_index) && 
   4880                 (tnode->local_port == local_port)) {   
   4881                 /* check both mmu_port(unique only within a pipe)
   4882                    and local_port(unique witin system) to get the 
   4883                    correct node */
   4884                 node = tnode;
   4885                 break;
   4886             }
   4887         }
   4888         if (node == NULL) {
   4889             return BCM_E_NONE;
   4890         }
   4891     }
   4892 
   4893     if (node->child != NULL) {
   4894         BCM_IF_ERROR_RETURN(_bcm_td2_cosq_gport_delete_all(unit, node->child->gport));
   4895     }
   4896 
   4897     if (node->level != SOC_TD2_NODE_LVL_ROOT && node->attached_to_input >= 0) {
   4898         BCM_IF_ERROR_RETURN
   4899             (bcm_td2_cosq_gport_detach(unit, node->gport, 
   4900                                 node->parent->gport, node->attached_to_input));
   4901     }
   4902     if ((node->type == _BCM_TD2_NODE_VOQ) && 
   4903             (node->remote_modid > 0)) {
   4904         _bcm_td2_voq_next_base_node_get (unit, local_port,
   4905                 node->remote_modid, &base_node);
   4906         if (base_node != NULL) {
   4907             BCM_PBMP_ASSIGN(base_node->fabric_pbmp,
   4908                     node->fabric_pbmp);
   4909         }
   4910     }
   4911 
   4912     _BCM_TD2_COSQ_NODE_INIT(node);
   4913     return BCM_E_NONE;
   4914 }
   4915 
   4916 /*
   4917  * Function:
   4918  *     bcm_td2_cosq_gport_get
   4919  * Purpose:
   4920  *     Get a cosq gport structure
   4921  * Parameters:
   4922  *     unit  - (IN) unit number
   4923  *     gport - (IN) GPORT identifier
   4924  *     port  - (OUT) port number
   4925  *     numq  - (OUT) number of COS queues
   4926  *     flags - (OUT) flags (BCM_COSQ_GPORT_XXX)
   4927  * Returns:
   4928  *     BCM_E_XXX
   4929  */
   4930 int
   4931 bcm_td2_cosq_gport_get(int unit, bcm_gport_t gport, bcm_gport_t *port,
   4932                       int *numq, uint32 *flags)
   4933 {
   4934     _bcm_td2_cosq_node_t *node;
   4935     bcm_module_t modid;
   4936     bcm_port_t local_port;
   4937     int id;
   4938     _bcm_gport_dest_t dest;
   4939 
   4940     if (port == NULL || numq == NULL || flags == NULL) {
   4941         return BCM_E_PARAM;
   4942     }
   4943 
   4944     LOG_INFO(BSL_LS_BCM_COSQ,
   4945              (BSL_META_U(unit,
   4946                          "bcm_td2_cosq_gport_get: unit=%d gport=0x%x\n"),
   4947               unit, gport));
   4948 
   4949     BCM_IF_ERROR_RETURN
   4950         (_bcm_td2_cosq_node_get(unit, gport, 0, NULL, &local_port, &id, &node));
   4951 
   4952     if (SOC_USE_GPORT(unit)) {
   4953         BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid));
   4954         dest.gport_type = _SHR_GPORT_TYPE_MODPORT;
   4955         dest.modid = modid;
   4956         dest.port = local_port;
   4957         BCM_IF_ERROR_RETURN(_bcm_esw_gport_construct(unit, &dest, port));
   4958     } else {
   4959         *port = local_port;
   4960     }
   4961 
   4962     *numq = node->numq;
   4963 
   4964     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   4965         if (node->type == _BCM_TD2_NODE_SERVICE_UCAST) {
   4966             *flags = BCM_COSQ_GPORT_VLAN_UCAST_QUEUE_GROUP;
   4967         } else if (node->type == _BCM_TD2_NODE_VM_UCAST) {
   4968             *flags = BCM_COSQ_GPORT_VIRTUAL_PORT;
   4969         } else if (node->type == _BCM_TD2_NODE_VOQ) {
   4970             *flags = BCM_COSQ_GPORT_DESTMOD_UCAST_QUEUE_GROUP;
   4971         } else {
   4972             *flags = BCM_COSQ_GPORT_UCAST_QUEUE_GROUP;
   4973         }
   4974     } else if (BCM_GPORT_IS_SCHEDULER(gport)) {
   4975         *flags = BCM_COSQ_GPORT_SCHEDULER;
   4976         if (node->node_align_value == _BCM_TD2_START_INDEX_ALIGN_PFC) {
   4977             *flags |= BCM_COSQ_GPORT_SCHEDULER_PFC_ALIGN;
   4978         }
   4979     } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   4980         *flags = BCM_COSQ_GPORT_MCAST_QUEUE_GROUP;
   4981     } else {
   4982         *flags = 0;
   4983     }
   4984 
   4985     LOG_INFO(BSL_LS_BCM_COSQ,
   4986              (BSL_META_U(unit,
   4987                          "                       port=0x%x numq=%d flags=0x%x\n"),
   4988               *port, *numq, *flags));
   4989 
   4990     return BCM_E_NONE;
   4991 }
   4992 
   4993 /*
   4994  * Function:
   4995  *     bcm_td2_cosq_gport_traverse
   4996  * Purpose:
   4997  *     Walks through the valid COSQ GPORTs and calls
   4998  *     the user supplied callback function for each entry.
   4999  * Parameters:
   5000  *     unit       - (IN) unit number
   5001  *     trav_fn    - (IN) Callback function.
   5002  *     user_data  - (IN) User data to be passed to callback function
   5003  * Returns:
   5004  *     BCM_E_NONE - Success.
   5005  *     BCM_E_XXX
   5006  */
   5007 int
   5008 bcm_td2_cosq_gport_traverse(int unit, bcm_cosq_gport_traverse_cb cb,
   5009                            void *user_data)
   5010 {
   5011     _bcm_td2_cosq_node_t *port_info;
   5012     _bcm_td2_mmu_info_t *mmu_info;
   5013     bcm_module_t my_modid, modid_out;
   5014     bcm_port_t port, port_out;
   5015 
   5016     if (_bcm_td2_mmu_info[unit] == NULL) {
   5017         return BCM_E_INIT;
   5018     }
   5019     mmu_info = _bcm_td2_mmu_info[unit];
   5020 
   5021     BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_modid));
   5022     PBMP_ALL_ITER(unit, port) {
   5023         BCM_IF_ERROR_RETURN
   5024             (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET,
   5025                                     my_modid, port, &modid_out, &port_out));
   5026 
   5027         /* root node */
   5028         port_info = &mmu_info->sched_node[port_out];
   5029 
   5030         if (port_info->gport >= 0) {
   5031             _bcm_td2_cosq_gport_traverse(unit, port_info->gport, cb, user_data);
   5032         }
   5033       }
   5034 
   5035     return BCM_E_NONE;
   5036 }
   5037 
   5038 /*
   5039  * Function:
   5040  *     bcm_td2_cosq_gport_attach
   5041  * Purpose:
   5042  *     Attach sched_port to the specified index (cosq) of input_port
   5043  * Parameters:
   5044  *     unit       - (IN) unit number
   5045  *     sched_port - (IN) scheduler GPORT identifier
   5046  *     input_port - (IN) GPORT to attach to
   5047  *     cosq       - (IN) COS queue to attach to (-1 for first available cosq)
   5048  * Returns:
   5049  *     BCM_E_XXX
   5050  */
   5051 int
   5052 bcm_td2_cosq_gport_attach(int unit, bcm_gport_t gport, 
   5053                            bcm_gport_t to_gport, 
   5054                            bcm_cos_queue_t to_cosq)
   5055 {
   5056     _bcm_td2_mmu_info_t *mmu_info;
   5057     _bcm_td2_cosq_node_t *node, *to_node;
   5058     bcm_port_t port, to_port, local_port, mmu_port;
   5059     int rv, tmp;
   5060 
   5061     if ((mmu_info = _bcm_td2_mmu_info[unit]) == NULL) {
   5062         return BCM_E_INIT;
   5063     }
   5064 
   5065     if ((BCM_GPORT_IS_UCAST_QUEUE_GROUP(to_gport)) ||
   5066         (BCM_GPORT_IS_MCAST_QUEUE_GROUP(to_gport)) ||
   5067         (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(to_gport))) {
   5068         return BCM_E_PARAM;
   5069     }
   5070 
   5071     if(!(BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
   5072          BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) ||
   5073          BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport) ||
   5074          BCM_GPORT_IS_SCHEDULER(gport))) {
   5075         return BCM_E_PORT;
   5076     }
   5077 
   5078     BCM_IF_ERROR_RETURN
   5079         (_bcm_td2_cosq_node_get(unit, gport, 0, NULL, &port, NULL, &node));
   5080 
   5081     if (node->attached_to_input >= 0) {
   5082         /* Has already attached */
   5083         return BCM_E_EXISTS;
   5084     }
   5085     tmp = node->attached_to_input;
   5086 
   5087     if (BCM_GPORT_IS_SCHEDULER(to_gport)) {
   5088 
   5089         BCM_IF_ERROR_RETURN
   5090             (_bcm_td2_cosq_node_get(unit, to_gport, 0, NULL, &to_port, NULL,
   5091                                    &to_node));
   5092 
   5093     } else {
   5094 
   5095         BCM_IF_ERROR_RETURN
   5096             (_bcm_td2_cosq_localport_resolve(unit, to_gport, &to_port));
   5097 
   5098         to_node = &mmu_info->sched_node[to_port];
   5099     }
   5100 
   5101     if (port != to_port) {
   5102         return BCM_E_PORT;
   5103     }
   5104 
   5105     mmu_port = SOC_TD2_MMU_PORT(unit, port);
   5106     
   5107     /* Identify the levels of schedulers
   5108      * to_port == phy_port && gport == scheduler => gport = L0
   5109      * to_port == schduler && gport == scheduler => to_port = L0 and port = L1
   5110      * to_port == scheduler && port == queue_group => to_port = L1 and port = L2
   5111      */
   5112     if (to_node != NULL) {
   5113         if (((to_node->level == SOC_TD2_NODE_LVL_ROOT) && (to_cosq >= 265)) ||
   5114              ((to_node->level == SOC_TD2_NODE_LVL_L0) && (to_cosq >= 1024)) ||
   5115              ((to_node->level == SOC_TD2_NODE_LVL_L1) && (to_cosq >= 1480))) {
   5116             return BCM_E_RESOURCE;
   5117         }
   5118 
   5119         if (!BCM_GPORT_IS_SCHEDULER(to_gport)) {
   5120             if ((to_node->numq == 0) || (to_node->numq_expandable)) {
   5121                 local_port = (BCM_GPORT_IS_LOCAL(to_gport)) ?
   5122                               BCM_GPORT_LOCAL_GET(to_gport) :
   5123                               BCM_GPORT_MODPORT_PORT_GET(to_gport);
   5124 
   5125                 if (!SOC_PORT_VALID(unit, local_port)) {
   5126                     return BCM_E_PORT;
   5127                 }
   5128                 to_node->in_use = TRUE;
   5129                 to_node->local_port = port;
   5130                 if (IS_TD2_HSP_PORT(unit, local_port)) {
   5131                     to_node->base_index = _BCM_TD2_HSP_L0_INDEX(unit, mmu_port, 0);
   5132                     to_node->numq = _BCM_TD2_HSP_PORT_MAX_L0;
   5133                 } else {
   5134                     to_node->gport = to_gport;
   5135                     to_node->hw_index = _BCM_TD2_ROOT_SCHED_INDEX(unit, mmu_port);
   5136                     to_node->level = SOC_TD2_NODE_LVL_ROOT;
   5137                     to_node->attached_to_input = 0;
   5138                     to_node->numq_expandable = 1;
   5139                     if (to_cosq == -1) {
   5140                         to_node->numq += 1;
   5141                     } else {
   5142                         if (to_cosq >= to_node->numq) {
   5143                             to_node->numq = to_cosq + 1;
   5144                         }
   5145                     }
   5146                 }
   5147             }
   5148 
   5149             if (!BCM_GPORT_IS_SCHEDULER(gport)) {
   5150 
   5151                 return BCM_E_PARAM;
   5152             }
   5153 
   5154             node->level = SOC_TD2_NODE_LVL_L0;
   5155         } else {
   5156              if (to_node->level == SOC_TD2_NODE_LVL_ROOT) {
   5157                  node->level = SOC_TD2_NODE_LVL_L0;
   5158              }
   5159 
   5160              if ((to_node->level == -1)) {
   5161                  to_node->level = (BCM_GPORT_IS_SCHEDULER(gport)) ?
   5162                      SOC_TD2_NODE_LVL_L0 : SOC_TD2_NODE_LVL_L1;
   5163              }
   5164 
   5165              if (node->level == -1) {
   5166                  node->level = 
   5167                      (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
   5168                       BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) ||
   5169                       BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport)) ?
   5170                      SOC_TD2_NODE_LVL_L2 : SOC_TD2_NODE_LVL_L1;
   5171              }
   5172         }
   5173     } else {
   5174         return BCM_E_NOT_FOUND;
   5175     }
   5176 
   5177     if ((to_cosq < -1) || ((to_node->numq != -1) && (to_cosq >= to_node->numq))) {
   5178 
   5179         return BCM_E_PARAM;
   5180     }
   5181 
   5182     if (BCM_GPORT_IS_SCHEDULER(to_gport) || BCM_GPORT_IS_LOCAL(to_gport) ||
   5183         BCM_GPORT_IS_MODPORT(to_gport)) {
   5184         int start = 0, end = 0;
   5185         if (to_node->attached_to_input < 0) {
   5186             /* dont allow to attach to a node that has already attached */
   5187 
   5188             return BCM_E_PARAM;
   5189         }
   5190 
   5191         if (node->type == _BCM_TD2_NODE_SERVICE_UCAST) {
   5192             end = node->numq;
   5193         } else {
   5194             end = 1;
   5195         }
   5196 
   5197         for (start = 0; start < end; start++) {
   5198             node->parent = to_node;
   5199             node->sibling = to_node->child;
   5200             to_node->child = node;
   5201             /* resolve the nodes */
   5202             rv = _bcm_td2_cosq_node_resolve(unit, node, to_cosq + start);
   5203             if (BCM_FAILURE(rv)) {
   5204                 to_node->child = node->sibling;
   5205                 node->parent = NULL;
   5206                 node->attached_to_input = tmp;
   5207                 return rv;
   5208             }
   5209             LOG_INFO(BSL_LS_BCM_COSQ,
   5210                      (BSL_META_U(unit,
   5211                                  "                         hw_cosq=%d\n"),
   5212                       node->attached_to_input));
   5213 
   5214             if ((node->type == _BCM_TD2_NODE_SERVICE_UCAST) && 
   5215                 ((start + 1) < end)){
   5216 
   5217                 BCM_IF_ERROR_RETURN
   5218                     (_bcm_td2_cosq_node_get(unit, gport, start + 1, NULL,
   5219                                             &port, NULL, &node));
   5220 
   5221                 if (!node) {
   5222                     return BCM_E_NOT_FOUND;
   5223                 }
   5224             }
   5225         }
   5226  
   5227     } else {
   5228             return BCM_E_PORT;
   5229     }
   5230 
   5231     return BCM_E_NONE;
   5232 }
   5233 
   5234 /*
   5235  * Function:
   5236  *     bcm_td2_cosq_gport_attach_get
   5237  * Purpose:
   5238  *     Get attached status of a scheduler port
   5239  * Parameters:
   5240  *     unit       - (IN) unit number
   5241  *     sched_port - (IN) scheduler GPORT identifier
   5242  *     input_port - (OUT) GPORT to attach to
   5243  *     cosq       - (OUT) COS queue to attached to
   5244  * Returns:
   5245  *     BCM_E_XXX
   5246  * Notes:
   5247  */
   5248 int
   5249 bcm_td2_cosq_gport_attach_get(int unit, bcm_gport_t sched_gport,
   5250                              bcm_gport_t *input_gport, bcm_cos_queue_t *cosq)
   5251 {
   5252     _bcm_td2_cosq_node_t *sched_node;
   5253     bcm_module_t modid, modid_out;
   5254     bcm_port_t port, port_out;
   5255 
   5256     if (input_gport == NULL || cosq == NULL) {
   5257         return BCM_E_PARAM;
   5258     }
   5259 
   5260     BCM_IF_ERROR_RETURN
   5261         (_bcm_td2_cosq_node_get(unit, sched_gport, 0, &modid, &port, NULL,
   5262                                &sched_node));
   5263 
   5264     if (sched_node->attached_to_input < 0) {
   5265         /* Not attached yet */
   5266         return BCM_E_NOT_FOUND;
   5267     }
   5268 
   5269     if (sched_node->parent != NULL) { /* sched_node is not an S1 scheduler */
   5270         *input_gport = sched_node->parent->gport;
   5271     } else {  /* sched_node is an S1 scheduler */
   5272         BCM_IF_ERROR_RETURN
   5273             (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, modid, port,
   5274                                     &modid_out, &port_out));
   5275         BCM_GPORT_MODPORT_SET(*input_gport, modid_out, port_out);
   5276     }
   5277     *cosq = sched_node->attached_to_input;
   5278 
   5279     return BCM_E_NONE;
   5280 }
   5281 
   5282 /*
   5283  * Function:
   5284  *      bcm_td2_cosq_gport_child_get
   5285  * Purpose:
   5286  *      Get the child node GPORT atatched to N-th index (cosq)
   5287  *      of the scheduler GPORT.
   5288  * Parameters:
   5289  *      unit       - (IN)  Unit number.
   5290  *      in_gport   - (IN)  Scheduler GPORT ID.
   5291  *      cosq       - (IN)  COS queue attached to.
   5292  *      out_gport  - (OUT) child GPORT ID.
   5293  * Returns:
   5294  *      BCM_E_XXX
   5295  * Notes:
   5296  */
   5297 int
   5298 bcm_td2_cosq_gport_child_get(int unit, bcm_gport_t in_gport,
   5299                             bcm_cos_queue_t cosq,
   5300                             bcm_gport_t *out_gport)
   5301 {
   5302     _bcm_td2_cosq_node_t *in_node = NULL;
   5303     _bcm_td2_cosq_node_t *cur_node = NULL;
   5304     _bcm_td2_cosq_node_t *tmp_node = NULL;
   5305     bcm_module_t modid;
   5306     bcm_port_t port;
   5307 
   5308     if (out_gport == NULL) {
   5309         return BCM_E_PARAM;
   5310     }
   5311 
   5312     /* get the child of the input gport node
   5313      * at an index of cosq
   5314      */
   5315 
   5316     if ((cosq < 0) || ( cosq >= 64)) {
   5317         return BCM_E_PARAM;
   5318     }
   5319 
   5320     BCM_IF_ERROR_RETURN
   5321         (_bcm_td2_cosq_node_get(unit, in_gport, 0, &modid, &port, NULL,
   5322                                &in_node));
   5323     if ((in_node->child == NULL) && (in_node->level == SOC_TD2_NODE_LVL_L2)) {
   5324        return BCM_E_PARAM;
   5325     }
   5326 
   5327     for (cur_node = in_node->child; cur_node != NULL;
   5328          cur_node = cur_node->sibling) {
   5329         if (cur_node->attached_to_input == cosq) {
   5330            tmp_node = cur_node;
   5331            break;
   5332         }
   5333     }
   5334     if (tmp_node == NULL) {
   5335         return BCM_E_NOT_FOUND;
   5336     }
   5337     *out_gport = tmp_node->gport;
   5338 
   5339     return BCM_E_NONE;
   5340 }
   5341 
   5342 /*
   5343  *  Convert HW drop probability to percent value
   5344  */
   5345 STATIC int
   5346 _bcm_td2_hw_drop_prob_to_percent[] = {
   5347     0,     /* 0  */
   5348     1,     /* 1  */
   5349     2,     /* 2  */
   5350     3,     /* 3  */
   5351     4,     /* 4  */
   5352     5,     /* 5  */
   5353     6,     /* 6  */
   5354     7,     /* 7  */
   5355     8,     /* 8  */
   5356     9,     /* 9  */
   5357     10,    /* 10 */
   5358     25,    /* 11 */
   5359     50,    /* 12 */
   5360     75,    /* 13 */
   5361     100,   /* 14 */
   5362     -1     /* 15 */
   5363 };
   5364 
   5365 STATIC int
   5366 _bcm_td2_percent_to_drop_prob(int percent)
   5367 {
   5368    int i;
   5369 
   5370    for (i = 14; i > 0 ; i--) {
   5371       if (percent >= _bcm_td2_hw_drop_prob_to_percent[i]) {
   5372           break;
   5373       }
   5374    }
   5375    return i;
   5376 }
   5377 
   5378 STATIC int
   5379 _bcm_td2_drop_prob_to_percent(int drop_prob) {
   5380    return (_bcm_td2_hw_drop_prob_to_percent[drop_prob]);
   5381 }
   5382 
   5383 /*
   5384  * index: degree, value: contangent(degree) * 100
   5385  * max value is 0xffff (16-bit) at 0 degree
   5386  */
   5387 STATIC int
   5388 _bcm_td2_cotangent_lookup_table[] =
   5389 {
   5390     /*  0.. 5 */  65535, 5728, 2863, 1908, 1430, 1143,
   5391     /*  6..11 */    951,  814,  711,  631,  567,  514,
   5392     /* 12..17 */    470,  433,  401,  373,  348,  327,
   5393     /* 18..23 */    307,  290,  274,  260,  247,  235,
   5394     /* 24..29 */    224,  214,  205,  196,  188,  180,
   5395     /* 30..35 */    173,  166,  160,  153,  148,  142,
   5396     /* 36..41 */    137,  132,  127,  123,  119,  115,
   5397     /* 42..47 */    111,  107,  103,  100,   96,   93,
   5398     /* 48..53 */     90,   86,   83,   80,   78,   75,
   5399     /* 54..59 */     72,   70,   67,   64,   62,   60,
   5400     /* 60..65 */     57,   55,   53,   50,   48,   46,
   5401     /* 66..71 */     44,   42,   40,   38,   36,   34,
   5402     /* 72..77 */     32,   30,   28,   26,   24,   23,
   5403     /* 78..83 */     21,   19,   17,   15,   14,   12,
   5404     /* 84..89 */     10,    8,    6,    5,    3,    1,
   5405     /* 90     */      0
   5406 };
   5407 
   5408 /*
   5409  * Given a slope (angle in degrees) from 0 to 90, return the number of cells
   5410  * in the range from 0% drop probability to 100% drop probability.
   5411  */
   5412 STATIC int
   5413 _bcm_td2_angle_to_cells(int angle)
   5414 {
   5415     return (_bcm_td2_cotangent_lookup_table[angle]);
   5416 }
   5417 
   5418 /*
   5419  * Given a number of packets in the range from 0% drop probability
   5420  * to 100% drop probability, return the slope (angle in degrees).
   5421  */
   5422 STATIC int
   5423 _bcm_td2_cells_to_angle(int packets)
   5424 {
   5425     int angle;
   5426 
   5427     for (angle = 90; angle >= 0 ; angle--) {
   5428         if (packets <= _bcm_td2_cotangent_lookup_table[angle]) {
   5429             break;
   5430         }
   5431     }
   5432     return angle;
   5433 }
   5434 
   5435 /*
   5436  * Function:
   5437  *     _bcm_td2_cosq_bucket_set
   5438  * Purpose:
   5439  *     Configure COS queue bandwidth control bucket
   5440  * Parameters:
   5441  *     unit          - (IN) unit number
   5442  *     port          - (IN) port number or GPORT identifier
   5443  *     cosq          - (IN) COS queue number
   5444  *     min_quantum   - (IN) kbps or packet/second
   5445  *     max_quantum   - (IN) kbps or packet/second
   5446  *     burst_quantum - (IN) kbps or packet/second
   5447  *     flags         - (IN)
   5448  * Returns:
   5449  *     BCM_E_XXX
   5450  * Notes:
   5451  *     If port is any form of local port, cosq is the hardware queue index.
   5452  */
   5453 STATIC int
   5454 _bcm_td2_cosq_bucket_set(int unit, bcm_gport_t port, bcm_cos_queue_t cosq,
   5455                         uint32 min_quantum, uint32 max_quantum,
   5456                         uint32 kbits_burst_min, uint32 kbits_burst_max, 
   5457                         uint32 flags)
   5458 {
   5459     _bcm_td2_cosq_node_t *node = NULL;
   5460     int rv = BCM_E_NONE;
   5461     bcm_port_t local_port;
   5462     int index;
   5463     uint32 rval;
   5464     uint32 meter_flags;
   5465     uint32 bucketsize_max, bucketsize_min;
   5466     uint32 granularity_max, granularity_min;
   5467     uint32 refresh_rate_max, refresh_rate_min;
   5468     int refresh_bitsize = 0, bucket_bitsize = 0;
   5469     soc_mem_t config_mem = INVALIDm;
   5470     uint32 entry[SOC_MAX_MEM_WORDS];
   5471 
   5472     /* caller should resolve the cosq. */
   5473     if (cosq < 0) {
   5474         if (cosq == -1) {
   5475             /* caller needs to resolve the wild card value (-1) */
   5476             return BCM_E_INTERNAL;
   5477         } else { /* reject all other negative value */
   5478             return BCM_E_PARAM;
   5479         }
   5480     }
   5481 
   5482     BCM_IF_ERROR_RETURN
   5483         (_bcm_td2_cosq_index_resolve(unit, port, cosq,
   5484                                     _BCM_TD2_COSQ_INDEX_STYLE_BUCKET,
   5485                                     &local_port, &index, NULL));
   5486 
   5487     if (BCM_GPORT_IS_SET(port) && 
   5488         ((BCM_GPORT_IS_SCHEDULER(port)) ||
   5489           BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
   5490           BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) ||
   5491           BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port))) {
   5492 
   5493         BCM_IF_ERROR_RETURN
   5494             (_bcm_td2_cosq_node_get(unit, port, cosq, NULL, 
   5495                                     NULL, NULL, &node));
   5496     }
   5497 
   5498     if (node) {
   5499         if (BCM_GPORT_IS_SCHEDULER(port)) {
   5500             if (node->level == SOC_TD2_NODE_LVL_ROOT) {
   5501                 config_mem = SOC_TD2_PMEM(unit, local_port, 
   5502                                       MMU_MTRO_L0_MEM_0m, MMU_MTRO_L0_MEM_1m);
   5503             } else if (node->level == SOC_TD2_NODE_LVL_L0) {
   5504                 uint32 mc_group_mode = 0;
   5505                 if (IS_TD2_HSP_PORT(unit, local_port)) {
   5506                     SOC_IF_ERROR_RETURN(
   5507                             READ_HSP_SCHED_PORT_CONFIGr(unit,
   5508                                 local_port, &rval));
   5509                     mc_group_mode  = soc_reg_field_get(unit,
   5510                                                        HSP_SCHED_PORT_CONFIGr,
   5511                                                        rval, MC_GROUP_MODEf);
   5512                 }
   5513                 if (mc_group_mode) {
   5514                     config_mem = SOC_TD2_PMEM(unit, local_port, 
   5515                                               MMU_MTRO_L2_MEM_0m,
   5516                                               MMU_MTRO_L2_MEM_1m);
   5517                 } else {
   5518                     config_mem = SOC_TD2_PMEM(unit, local_port, 
   5519                                               MMU_MTRO_L1_MEM_0m,
   5520                                               MMU_MTRO_L1_MEM_1m);
   5521                 }
   5522             } else if (node->level == SOC_TD2_NODE_LVL_L1) {
   5523                 config_mem = SOC_TD2_PMEM(unit, local_port, 
   5524                                       MMU_MTRO_L2_MEM_0m, MMU_MTRO_L2_MEM_1m);
   5525             } else {
   5526                 return BCM_E_PARAM;
   5527             }
   5528         } else if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
   5529                    BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
   5530             config_mem = SOC_TD2_PMEM(unit, local_port, 
   5531                                       MMU_MTRO_L2_MEM_0m, MMU_MTRO_L2_MEM_1m);
   5532         } else {
   5533             return BCM_E_PARAM;
   5534         }
   5535     } else {
   5536         if (IS_CPU_PORT(unit, local_port)) {
   5537             config_mem = SOC_TD2_PMEM(unit, local_port, 
   5538                                       MMU_MTRO_L2_MEM_0m, MMU_MTRO_L2_MEM_1m);
   5539         } else {
   5540             config_mem = SOC_TD2_PMEM(unit, local_port, 
   5541                                       MMU_MTRO_L1_MEM_0m, MMU_MTRO_L1_MEM_1m);
   5542         }
   5543     }
   5544 
   5545 
   5546     meter_flags = flags & BCM_COSQ_BW_PACKET_MODE ?
   5547                             _BCM_TD_METER_FLAG_PACKET_MODE : 0;
   5548     BCM_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, &rval));
   5549     if (soc_reg_field_get(unit, MISCCONFIGr, rval, ITU_MODE_SELf)) {
   5550         meter_flags |= _BCM_TD_METER_FLAG_NON_LINEAR;
   5551     }
   5552 
   5553     refresh_bitsize = soc_mem_field_length(unit, config_mem, MAX_REFRESHf);
   5554     bucket_bitsize = soc_mem_field_length(unit, config_mem, MAX_THD_SELf);
   5555 
   5556     BCM_IF_ERROR_RETURN
   5557         (_bcm_td_rate_to_bucket_encoding(unit, max_quantum, kbits_burst_max,
   5558                                            meter_flags, refresh_bitsize,
   5559                                            bucket_bitsize, &refresh_rate_max,
   5560                                            &bucketsize_max, &granularity_max));
   5561 
   5562     BCM_IF_ERROR_RETURN
   5563         (_bcm_td_rate_to_bucket_encoding(unit, min_quantum, kbits_burst_min,
   5564                                            meter_flags, refresh_bitsize,
   5565                                            bucket_bitsize, &refresh_rate_min,
   5566                                            &bucketsize_min, &granularity_min));
   5567 
   5568     sal_memset(entry, 0, sizeof(uint32)*SOC_MAX_MEM_WORDS);
   5569     soc_mem_field32_set(unit, config_mem, &entry, MAX_METER_GRANf, granularity_max);
   5570     soc_mem_field32_set(unit, config_mem, &entry, MAX_REFRESHf, refresh_rate_max);
   5571     soc_mem_field32_set(unit, config_mem, &entry, MAX_THD_SELf, bucketsize_max);
   5572 
   5573     soc_mem_field32_set(unit, config_mem, &entry, MIN_METER_GRANf, granularity_min);
   5574     soc_mem_field32_set(unit, config_mem, &entry, MIN_REFRESHf, refresh_rate_min);
   5575     soc_mem_field32_set(unit, config_mem, &entry, MIN_THD_SELf, bucketsize_min);
   5576 
   5577     soc_mem_field32_set(unit, config_mem, &entry, SHAPER_CONTROLf,
   5578                         (flags & BCM_COSQ_BW_PACKET_MODE) ? 1 : 0);
   5579     soc_mem_field32_set(unit, config_mem, &entry, EAV_ENABLEf,
   5580                         (flags & BCM_COSQ_BW_EAV_MODE) ? 1 : 0);
   5581 
   5582     SOC_EGRESS_METERING_LOCK(unit);
   5583     rv = soc_mem_write(unit, config_mem, MEM_BLOCK_ALL, index, &entry);
   5584     SOC_EGRESS_METERING_UNLOCK(unit);
   5585 
   5586     return rv;
   5587 }
   5588 
   5589 /*
   5590  * Function:
   5591  *     _bcm_td2_cosq_bucket_get
   5592  * Purpose:
   5593  *     Get COS queue bandwidth control bucket setting
   5594  * Parameters:
   5595  *     unit          - (IN) unit number
   5596  *     port          - (IN) port number or GPORT identifier
   5597  *     cosq          - (IN) COS queue number
   5598  *     min_quantum   - (OUT) kbps or packet/second
   5599  *     max_quantum   - (OUT) kbps or packet/second
   5600  *     burst_quantum - (OUT) kbps or packet/second
   5601  *     flags         - (IN)
   5602  * Returns:
   5603  *     BCM_E_XXX
   5604  * Notes:
   5605  *     If port is any form of local port, cosq is the hardware queue index.
   5606  */
   5607 STATIC int
   5608 _bcm_td2_cosq_bucket_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   5609                         uint32 *min_quantum, uint32 *max_quantum,
   5610                         uint32 *kbits_burst_min, uint32 *kbits_burst_max,
   5611                         uint32 *flags)
   5612 {
   5613     _bcm_td2_cosq_node_t *node = NULL;
   5614     int rv = BCM_E_NONE;
   5615     bcm_port_t local_port;
   5616     int index;
   5617     uint32 rval;
   5618     uint32 refresh_rate, bucketsize, granularity, meter_flags;
   5619     soc_mem_t config_mem = INVALIDm;
   5620     uint32 entry[SOC_MAX_MEM_WORDS];
   5621 
   5622     if (cosq < 0) {
   5623         if (cosq == -1) {
   5624             /* caller needs to resolve the wild card value (-1) */
   5625             return BCM_E_INTERNAL;
   5626         } else { /* reject all other negative value */
   5627             return BCM_E_PARAM;
   5628         }
   5629     }
   5630 
   5631     BCM_IF_ERROR_RETURN
   5632         (_bcm_td2_cosq_index_resolve(unit, port, cosq,
   5633                                     _BCM_TD2_COSQ_INDEX_STYLE_BUCKET,
   5634                                     &local_port, &index, NULL));
   5635 
   5636     if (BCM_GPORT_IS_SET(port) && 
   5637         ((BCM_GPORT_IS_SCHEDULER(port)) ||
   5638           BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
   5639           BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) ||
   5640           BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port))) {
   5641 
   5642         BCM_IF_ERROR_RETURN
   5643             (_bcm_td2_cosq_node_get(unit, port, cosq, NULL, 
   5644                                     &local_port, NULL, &node));
   5645     }
   5646 
   5647     if (node) {
   5648         if (BCM_GPORT_IS_SCHEDULER(port)) {
   5649             if (node->level == SOC_TD2_NODE_LVL_ROOT) {
   5650                 config_mem = SOC_TD2_PMEM(unit, local_port, 
   5651                                       MMU_MTRO_L0_MEM_0m, MMU_MTRO_L0_MEM_1m);
   5652             } else if (node->level == SOC_TD2_NODE_LVL_L0) {
   5653                 uint32 mc_group_mode = 0;
   5654                 if (IS_TD2_HSP_PORT(unit, local_port)) {
   5655                     SOC_IF_ERROR_RETURN(
   5656                             READ_HSP_SCHED_PORT_CONFIGr(unit,
   5657                                 local_port, &rval));
   5658                     mc_group_mode  = soc_reg_field_get(unit,
   5659                                                        HSP_SCHED_PORT_CONFIGr,
   5660                                                        rval, MC_GROUP_MODEf);
   5661                 }
   5662                 if (mc_group_mode) {
   5663                     config_mem = SOC_TD2_PMEM(unit, local_port, 
   5664                                               MMU_MTRO_L2_MEM_0m,
   5665                                               MMU_MTRO_L2_MEM_1m);
   5666                 } else {
   5667                     config_mem = SOC_TD2_PMEM(unit, local_port, 
   5668                                               MMU_MTRO_L1_MEM_0m,
   5669                                               MMU_MTRO_L1_MEM_1m);
   5670                 }
   5671             } else if (node->level == SOC_TD2_NODE_LVL_L1) {
   5672                 config_mem = SOC_TD2_PMEM(unit, local_port, 
   5673                                       MMU_MTRO_L2_MEM_0m, MMU_MTRO_L2_MEM_1m);
   5674             } else {
   5675                 return BCM_E_PARAM;
   5676             }
   5677         } else if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
   5678                    BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
   5679             config_mem = SOC_TD2_PMEM(unit, local_port, 
   5680                                       MMU_MTRO_L2_MEM_0m, MMU_MTRO_L2_MEM_1m);
   5681         } else {
   5682             return BCM_E_PARAM;
   5683         }
   5684     } else {
   5685         if (IS_CPU_PORT(unit, local_port)) {
   5686             config_mem = SOC_TD2_PMEM(unit, local_port, 
   5687                                       MMU_MTRO_L2_MEM_0m, MMU_MTRO_L2_MEM_1m);
   5688         } else {
   5689             config_mem = SOC_TD2_PMEM(unit, local_port, 
   5690                                       MMU_MTRO_L1_MEM_0m, MMU_MTRO_L1_MEM_1m);
   5691         }
   5692     }
   5693 
   5694     if (min_quantum == NULL || max_quantum == NULL || 
   5695         kbits_burst_max == NULL || kbits_burst_min == NULL) {
   5696         return BCM_E_PARAM;
   5697     }
   5698 
   5699     SOC_EGRESS_METERING_LOCK(unit);
   5700     rv = soc_mem_read(unit, config_mem, MEM_BLOCK_ALL, index, &entry);
   5701     SOC_EGRESS_METERING_UNLOCK(unit);
   5702     if (rv != BCM_E_NONE) {
   5703         return rv;
   5704     }
   5705 
   5706     meter_flags = 0;
   5707     *flags = 0;
   5708     BCM_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, &rval));
   5709     if (soc_reg_field_get(unit, MISCCONFIGr, rval, ITU_MODE_SELf)) {
   5710         meter_flags |= _BCM_TD_METER_FLAG_NON_LINEAR;
   5711     }
   5712     if (soc_mem_field32_get(unit, config_mem, &entry, SHAPER_CONTROLf)) {
   5713         meter_flags |= _BCM_TD_METER_FLAG_PACKET_MODE;
   5714         *flags |= BCM_COSQ_BW_PACKET_MODE;
   5715     }
   5716     if (soc_mem_field32_get(unit, config_mem, &entry, EAV_ENABLEf)) {
   5717         *flags |= BCM_COSQ_BW_EAV_MODE;
   5718     }
   5719 
   5720     granularity = soc_mem_field32_get(unit, config_mem, &entry, MAX_METER_GRANf);
   5721     refresh_rate = soc_mem_field32_get(unit, config_mem, &entry, MAX_REFRESHf);
   5722     bucketsize = soc_mem_field32_get(unit, config_mem, &entry, MAX_THD_SELf);
   5723     BCM_IF_ERROR_RETURN
   5724         (_bcm_td_bucket_encoding_to_rate(unit, refresh_rate, bucketsize,
   5725                                            granularity, meter_flags,
   5726                                            max_quantum, kbits_burst_max));
   5727 
   5728     granularity = soc_mem_field32_get(unit, config_mem, &entry, MIN_METER_GRANf);
   5729     refresh_rate = soc_mem_field32_get(unit, config_mem, &entry, MIN_REFRESHf);
   5730     bucketsize = soc_mem_field32_get(unit, config_mem, &entry, MIN_THD_SELf);
   5731     BCM_IF_ERROR_RETURN
   5732         (_bcm_td_bucket_encoding_to_rate(unit, refresh_rate, bucketsize,
   5733                                            granularity, meter_flags,
   5734                                            min_quantum, kbits_burst_min));
   5735     return BCM_E_NONE;
   5736 }
   5737 
   5738 
   5739 
   5740 STATIC int
   5741 _bcm_td2_cosq_time_domain_get(int unit, int time_id, int *time_value)
   5742 {
   5743     uint32 rval;
   5744 
   5745     if (time_id < 0 || time_id > _TD2_NUM_TIME_DOMAIN - 1) {
   5746         return SOC_E_PARAM;
   5747     }
   5748 
   5749     if (time_value == NULL) {
   5750         return SOC_E_PARAM;
   5751     }
   5752 
   5753     rval = 0;
   5754     SOC_IF_ERROR_RETURN(READ_TIME_DOMAINr(unit, &rval));
   5755     *time_value = soc_reg_field_get(unit, TIME_DOMAINr, rval, 
   5756                                       time_domain[time_id].field);
   5757 
   5758     return SOC_E_NONE;
   5759 }
   5760 
   5761 
   5762 
   5763 
   5764 STATIC int
   5765 _bcm_td2_cosq_time_domain_set(int unit, int time_value, int *time_id)
   5766 {
   5767     uint32 rval;
   5768     int rv = SOC_E_NONE;
   5769     int id;
   5770 
   5771     if (time_value < 0 || time_value > 63) {
   5772         return SOC_E_PARAM;
   5773     }
   5774 
   5775     rval = 0;
   5776     SOC_IF_ERROR_RETURN(READ_TIME_DOMAINr(unit, &rval));
   5777     for (id = 0; id < _TD2_NUM_TIME_DOMAIN; id++) {/* Find a unset field from  TIME_0 to TIME_3 */
   5778         if (!time_domain[id].ref_count) {
   5779             soc_reg_field_set(unit, TIME_DOMAINr, &rval, time_domain[id].field, 
   5780                                 time_value);
   5781             time_domain[id].ref_count++;
   5782             break;
   5783         }
   5784     }
   5785     
   5786     if(id == _TD2_NUM_TIME_DOMAIN){/* No field in TIME_DOMAINr is free,return ERR*/
   5787         rv = BCM_E_RESOURCE;
   5788     }
   5789 
   5790     if(time_id){
   5791         *time_id = id;
   5792     }
   5793         
   5794     SOC_IF_ERROR_RETURN(WRITE_TIME_DOMAINr(unit, rval));
   5795     return rv;
   5796 }
   5797 
   5798 STATIC int
   5799 _bcm_td2_cosq_wred_index_resolve(int unit, bcm_port_t port,
   5800                       bcm_cos_queue_t cosq, uint32 flags, uint32 lflags,
   5801                       bcm_port_t *local_port, int *index_start, int *index_end,
   5802                       int *port_id, int *pool_id)
   5803 {
   5804     int index;
   5805     int to_index = -1;
   5806     int start_pool_idx;
   5807     soc_info_t *si;
   5808     int phy_port, mmu_port = 0;
   5809     int service_pool = 0;
   5810     bcm_port_t local_p = -1;
   5811 
   5812     if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
   5813         return BCM_E_PARAM;
   5814     }
   5815     
   5816     if((lflags & BCM_COSQ_DISCARD_DEVICE) || (flags & BCM_COSQ_DISCARD_DEVICE)) {
   5817         if ((port == -1) || (cosq == -1)) {
   5818             index = 1840;
   5819             to_index = index + 3;
   5820         } else {
   5821             BCM_IF_ERROR_RETURN
   5822                 (_bcm_td2_cosq_index_resolve(unit, port, cosq,
   5823                                              _BCM_TD2_COSQ_INDEX_STYLE_WRED_POOL,
   5824                                              NULL, &start_pool_idx, NULL));
   5825             index = to_index = 1840 + start_pool_idx;
   5826         }
   5827     } else {
   5828         if((lflags & BCM_COSQ_DISCARD_PORT) || (flags & BCM_COSQ_DISCARD_PORT)) {
   5829             if (port == -1) {
   5830                 return BCM_E_PARAM;
   5831             }
   5832             BCM_IF_ERROR_RETURN
   5833                 (_bcm_td2_cosq_index_resolve(unit, port, cosq,
   5834                                             _BCM_TD2_COSQ_INDEX_STYLE_WRED_PORT,
   5835                                             &local_p, &index, NULL));
   5836             if (cosq != -1) {
   5837                 BCM_IF_ERROR_RETURN
   5838                     (_bcm_td2_cosq_index_resolve(unit, port, cosq,
   5839                                                  _BCM_TD2_COSQ_INDEX_STYLE_WRED_POOL,
   5840                                                  NULL, &start_pool_idx, NULL));
   5841                 index = to_index = index + start_pool_idx;
   5842             } else {
   5843                 to_index = index + 3;
   5844             }
   5845         } else {
   5846             BCM_IF_ERROR_RETURN
   5847                 (_bcm_td2_cosq_index_resolve(unit, port, cosq == -1 ? 0:cosq,
   5848                                      _BCM_TD2_COSQ_INDEX_STYLE_WRED,
   5849                                      &local_p, &index, NULL));
   5850 
   5851             si = &SOC_INFO(unit);
   5852             phy_port = si->port_l2p_mapping[local_p];
   5853             mmu_port = si->port_p2m_mapping[phy_port];
   5854             mmu_port = (mmu_port >= 64) ? (mmu_port - 64) : (mmu_port);
   5855 
   5856             BCM_IF_ERROR_RETURN
   5857                 (_bcm_td2_cosq_index_resolve(unit, port, cosq == -1 ? 0:cosq,
   5858                                              _BCM_TD2_COSQ_INDEX_STYLE_WRED_POOL,
   5859                                              NULL, &start_pool_idx, NULL));
   5860             service_pool = start_pool_idx;
   5861 
   5862             if (cosq == -1) {
   5863                 to_index = index + NUM_COS(unit) - 1;
   5864             } else {
   5865                 to_index = index;
   5866             }
   5867         }
   5868     }
   5869 
   5870     if (index < 0) {
   5871         return BCM_E_PARAM;
   5872     }
   5873 
   5874     if (local_port != NULL) {
   5875         *local_port = local_p;
   5876     }
   5877     if (index_start != NULL) {
   5878         *index_start = index;
   5879     }
   5880     if (index_end != NULL) {
   5881         *index_end = to_index;
   5882     }
   5883     if (port_id != NULL) {
   5884         *port_id = mmu_port;
   5885     }
   5886     if (pool_id != NULL) {
   5887         *pool_id = service_pool;
   5888     }
   5889 
   5890     return BCM_E_NONE;
   5891 }
   5892 
   5893 /*
   5894  * Function:
   5895  *     _bcm_td2_cosq_wred_set
   5896  * Purpose:
   5897  *     Configure unicast queue WRED setting
   5898  * Parameters:
   5899  *     unit                - (IN) unit number
   5900  *     port                - (IN) port number or GPORT identifier
   5901  *     cosq                - (IN) COS queue number
   5902  *     flags               - (IN) BCM_COSQ_DISCARD_XXX
   5903  *     min_thresh          - (IN)
   5904  *     max_thresh          - (IN)
   5905  *     drop_probablity     - (IN)
   5906  *     gain                - (IN)
   5907  *     ignore_enable_flags - (IN)
   5908  * Returns:
   5909  *     BCM_E_XXX
   5910  * Notes:
   5911  *     If port is any form of local port, cosq is the hardware queue index.
   5912  */
   5913 STATIC int
   5914 _bcm_td2_cosq_wred_set(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   5915                       uint32 flags, uint32 min_thresh, uint32 max_thresh,
   5916                       int drop_probability, int gain, int ignore_enable_flags,
   5917                       uint32 lflags,int refresh_time)
   5918 {
   5919     soc_mem_t wred_mem;
   5920     bcm_port_t local_port = -1;
   5921     int index;
   5922     uint32 profile_index, old_profile_index;
   5923     mmu_wred_drop_curve_profile_0_entry_t entry_tcp_green;
   5924     mmu_wred_drop_curve_profile_1_entry_t entry_tcp_yellow;
   5925     mmu_wred_drop_curve_profile_2_entry_t entry_tcp_red;
   5926     mmu_wred_drop_curve_profile_3_entry_t entry_nontcp_green;
   5927     mmu_wred_drop_curve_profile_4_entry_t entry_nontcp_yellow;
   5928     mmu_wred_drop_curve_profile_5_entry_t entry_nontcp_red;
   5929     mmu_wred_config_entry_t qentry;
   5930     void *entries[6];
   5931     soc_mem_t mems[6];
   5932     int rate, i, pipe, fpipe, tpipe, jj, to_index = -1, exists = 0;
   5933     int time_id,time,old_time,current_time_sel;
   5934     int port_id = 0;
   5935     int pool_id = 0;
   5936     int rv = SOC_E_NONE;
   5937     static soc_mem_t wred_mems[2][6] = {
   5938         {
   5939         MMU_WRED_DROP_CURVE_PROFILE_0_X_PIPEm, 
   5940         MMU_WRED_DROP_CURVE_PROFILE_1_X_PIPEm,
   5941         MMU_WRED_DROP_CURVE_PROFILE_2_X_PIPEm, 
   5942         MMU_WRED_DROP_CURVE_PROFILE_3_X_PIPEm,
   5943         MMU_WRED_DROP_CURVE_PROFILE_4_X_PIPEm, 
   5944         MMU_WRED_DROP_CURVE_PROFILE_5_X_PIPEm
   5945         },
   5946         {
   5947         MMU_WRED_DROP_CURVE_PROFILE_0_Y_PIPEm, 
   5948         MMU_WRED_DROP_CURVE_PROFILE_1_Y_PIPEm,
   5949         MMU_WRED_DROP_CURVE_PROFILE_2_Y_PIPEm, 
   5950         MMU_WRED_DROP_CURVE_PROFILE_3_Y_PIPEm,
   5951         MMU_WRED_DROP_CURVE_PROFILE_4_Y_PIPEm, 
   5952         MMU_WRED_DROP_CURVE_PROFILE_5_Y_PIPEm
   5953         }
   5954     };
   5955 
   5956     BCM_IF_ERROR_RETURN(_bcm_td2_cosq_wred_index_resolve(unit, port, cosq,
   5957                             flags, lflags, &local_port, &index, &to_index,
   5958                             &port_id, &pool_id));
   5959 
   5960     if (local_port >= 0) {
   5961         fpipe = tpipe = _BCM_TD2_PORT_TO_PIPE(unit, local_port);
   5962     } else {
   5963         fpipe = _TD2_XPIPE;
   5964         tpipe = _TD2_YPIPE;
   5965     }
   5966 
   5967     /* WRED doesn't work on CPU/LB Ports */
   5968     if (IS_LB_PORT(unit, local_port) || IS_CPU_PORT(unit, local_port)) {
   5969         return BCM_E_PORT;
   5970     }
   5971 
   5972     for (pipe = fpipe; pipe <= tpipe; pipe++) {
   5973       for(jj = index; jj <= to_index; jj++) {
   5974         wred_mem = (pipe == _TD2_XPIPE) ? 
   5975                     MMU_WRED_CONFIG_X_PIPEm : MMU_WRED_CONFIG_Y_PIPEm;
   5976 
   5977         BCM_IF_ERROR_RETURN
   5978             (soc_mem_read(unit, wred_mem, MEM_BLOCK_ALL, jj, &qentry));
   5979 
   5980         old_profile_index = 0xffffffff;
   5981         if (flags & (BCM_COSQ_DISCARD_NONTCP | BCM_COSQ_DISCARD_COLOR_ALL |
   5982                      BCM_COSQ_DISCARD_TCP)) {
   5983             old_profile_index = soc_mem_field32_get(unit, wred_mem, 
   5984                                                     &qentry, PROFILE_INDEXf);
   5985             entries[0] = &entry_tcp_green;
   5986             entries[1] = &entry_tcp_yellow;
   5987             entries[2] = &entry_tcp_red;
   5988             entries[3] = &entry_nontcp_green;
   5989             entries[4] = &entry_nontcp_yellow;
   5990             entries[5] = &entry_nontcp_red;
   5991             BCM_IF_ERROR_RETURN
   5992                 (soc_profile_mem_get(unit, _bcm_td2_wred_profile[pipe][unit],
   5993                                      old_profile_index, 1, entries));
   5994 
   5995             for (i = 0; i < 6; i++) {
   5996                 mems[i] = INVALIDm;
   5997             }
   5998             if (!(flags & (BCM_COSQ_DISCARD_COLOR_GREEN |
   5999                            BCM_COSQ_DISCARD_COLOR_YELLOW |
   6000                            BCM_COSQ_DISCARD_COLOR_RED))) {
   6001                 flags |= BCM_COSQ_DISCARD_COLOR_ALL;
   6002             }
   6003             if (!(flags & BCM_COSQ_DISCARD_NONTCP) || (flags & BCM_COSQ_DISCARD_TCP)) {
   6004                 if (flags & BCM_COSQ_DISCARD_COLOR_GREEN) {
   6005                     mems[0] = (pipe == _TD2_XPIPE) ? 
   6006                             MMU_WRED_DROP_CURVE_PROFILE_0_X_PIPEm : 
   6007                             MMU_WRED_DROP_CURVE_PROFILE_0_Y_PIPEm;
   6008                 }
   6009                 if (flags & BCM_COSQ_DISCARD_COLOR_YELLOW) {
   6010                     mems[1] = (pipe == _TD2_XPIPE) ? 
   6011                             MMU_WRED_DROP_CURVE_PROFILE_1_X_PIPEm : 
   6012                             MMU_WRED_DROP_CURVE_PROFILE_1_Y_PIPEm;
   6013                 }
   6014                 if (flags & BCM_COSQ_DISCARD_COLOR_RED) {
   6015                     mems[2] = (pipe == _TD2_XPIPE) ? 
   6016                             MMU_WRED_DROP_CURVE_PROFILE_2_X_PIPEm : 
   6017                             MMU_WRED_DROP_CURVE_PROFILE_2_Y_PIPEm;
   6018                 }
   6019             }
   6020             if (flags & BCM_COSQ_DISCARD_NONTCP) {
   6021                 if (flags & BCM_COSQ_DISCARD_COLOR_GREEN) {
   6022                     mems[3] = (pipe == _TD2_XPIPE) ? 
   6023                             MMU_WRED_DROP_CURVE_PROFILE_3_X_PIPEm : 
   6024                             MMU_WRED_DROP_CURVE_PROFILE_3_Y_PIPEm;
   6025                 }
   6026                 if (flags & BCM_COSQ_DISCARD_COLOR_YELLOW) {
   6027                     mems[4] = (pipe == _TD2_XPIPE) ? 
   6028                             MMU_WRED_DROP_CURVE_PROFILE_4_X_PIPEm : 
   6029                             MMU_WRED_DROP_CURVE_PROFILE_4_Y_PIPEm;
   6030                 }
   6031                 if (flags & BCM_COSQ_DISCARD_COLOR_RED) {
   6032                     mems[5] = (pipe == _TD2_XPIPE) ? 
   6033                             MMU_WRED_DROP_CURVE_PROFILE_5_X_PIPEm : 
   6034                             MMU_WRED_DROP_CURVE_PROFILE_5_Y_PIPEm;
   6035                 }
   6036             }
   6037             rate = _bcm_td2_percent_to_drop_prob(drop_probability);
   6038             for (i = 0; i < 6; i++) {
   6039                 exists = 0;
   6040                 if ((soc_mem_field32_get(unit, wred_mems[pipe][i], entries[i], 
   6041                               MIN_THDf) != 0x1ffff) && (mems[i] == INVALIDm)) {
   6042                     mems[i] = wred_mems[pipe][i];
   6043                     exists = 1;
   6044                 } else {
   6045                     soc_mem_field32_set(unit, wred_mems[pipe][i], entries[i], 
   6046                             MIN_THDf, (mems[i] == INVALIDm) ? 0x1ffff : min_thresh);
   6047                 }
   6048 
   6049                 if ((soc_mem_field32_get(unit, wred_mems[pipe][i], entries[i], 
   6050                         MAX_THDf) != 0x1ffff) && ((mems[i] == INVALIDm) || exists)) {
   6051                     mems[i] = wred_mems[pipe][i];
   6052                     exists = 1;
   6053                 } else {
   6054                     soc_mem_field32_set(unit, wred_mems[pipe][i], entries[i], 
   6055                             MAX_THDf, (mems[i] == INVALIDm) ? 0x1ffff :max_thresh);
   6056                 }
   6057 
   6058                 if (!exists) {
   6059                     soc_mem_field32_set(unit, wred_mems[pipe][i], entries[i], 
   6060                         MAX_DROP_RATEf, (mems[i] == INVALIDm) ? 0 : rate);
   6061                 }
   6062             }
   6063 
   6064             BCM_IF_ERROR_RETURN
   6065                 (soc_profile_mem_add(unit, _bcm_td2_wred_profile[pipe][unit], 
   6066                                                  entries, 1, &profile_index));
   6067             soc_mem_field32_set(unit, wred_mem, &qentry, PROFILE_INDEXf, profile_index);
   6068             soc_mem_field32_set(unit, wred_mem, &qentry, WEIGHTf, gain);
   6069         }
   6070 
   6071         /* Some APIs only modify profiles */
   6072         if (!ignore_enable_flags) {
   6073             soc_mem_field32_set(unit, wred_mem, &qentry, CAP_AVERAGEf,
   6074                               flags & BCM_COSQ_DISCARD_CAP_AVERAGE ? 1 : 0);
   6075             soc_mem_field32_set(unit, wred_mem, &qentry, WRED_ENf,
   6076                               flags & BCM_COSQ_DISCARD_ENABLE ? 1 : 0);
   6077             soc_mem_field32_set(unit, wred_mem, &qentry, ECN_MARKING_ENf,
   6078                               flags & BCM_COSQ_DISCARD_MARK_CONGESTION ?  1 : 0);
   6079             soc_mem_field32_set(unit, wred_mem, &qentry, PORTIDf,
   6080                               port_id ?  port_id : 0);
   6081             soc_mem_field32_set(unit, wred_mem, &qentry, SPIDf,
   6082                               pool_id ?  pool_id : 0);
   6083         }
   6084 
   6085         current_time_sel = soc_mem_field32_get(unit, wred_mem, &qentry, TIME_DOMAIN_SELf);
   6086         time = (refresh_time + 7) / 8 - 1; /* Round it up to avoid negative value */
   6087         exists = 0;
   6088         /* If the time value exist, update reference count only */
   6089         for (time_id = 0; time_id < _TD2_NUM_TIME_DOMAIN; time_id++) {
   6090             BCM_IF_ERROR_RETURN
   6091                 (_bcm_td2_cosq_time_domain_get(unit, time_id, &old_time));
   6092             if (time == old_time) {
   6093                 /* Only set exist flag if this entry reference count already update,
   6094                               otherwise update reference count */
   6095                 if(time_id != current_time_sel){ 
   6096                     soc_mem_field32_set(unit, wred_mem, &qentry, TIME_DOMAIN_SELf, 
   6097                                           time_id);
   6098                     time_domain[time_id].ref_count++;
   6099                     time_domain[current_time_sel].ref_count--;
   6100                 }
   6101                 exists = 1;
   6102                 break;
   6103             }
   6104         }
   6105 
   6106         if(!exists){
   6107             rv = _bcm_td2_cosq_time_domain_set(unit, time, &time_id);
   6108             if(rv == SOC_E_NONE){
   6109                 soc_mem_field32_set(unit, wred_mem, &qentry, TIME_DOMAIN_SELf, 
   6110                                       time_id);
   6111                 time_domain[current_time_sel].ref_count--;
   6112             } else {
   6113                 return rv;
   6114             }
   6115         }
   6116         
   6117         BCM_IF_ERROR_RETURN(
   6118               soc_mem_write(unit, wred_mem, MEM_BLOCK_ALL, jj, &qentry));
   6119 
   6120         if (old_profile_index != 0xffffffff) {
   6121             SOC_IF_ERROR_RETURN
   6122                 (soc_profile_mem_delete(unit, _bcm_td2_wred_profile[pipe][unit],
   6123                                         old_profile_index));
   6124         }
   6125       }
   6126     }
   6127 
   6128     return rv;
   6129 }
   6130 
   6131 /*
   6132  * Function:
   6133  *     _bcm_td2_cosq_wred_get
   6134  * Purpose:
   6135  *     Get unicast queue WRED setting
   6136  * Parameters:
   6137  *     unit                - (IN) unit number
   6138  *     port                - (IN) port number or GPORT identifier
   6139  *     cosq                - (IN) COS queue number
   6140  *     flags               - (IN/OUT) BCM_COSQ_DISCARD_XXX
   6141  *     min_thresh          - (OUT)
   6142  *     max_thresh          - (OUT)
   6143  *     drop_probablity     - (OUT)
   6144  *     gain                - (OUT)
   6145  * Returns:
   6146  *     BCM_E_XXX
   6147  * Notes:
   6148  *     If port is any form of local port, cosq is the hardware queue index.
   6149  */
   6150 STATIC int
   6151 _bcm_td2_cosq_wred_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   6152                       uint32 *flags, uint32 *min_thresh, uint32 *max_thresh,
   6153                       int *drop_probability, int *gain, uint32 lflags,int *refresh_time)
   6154 {
   6155     bcm_port_t local_port = -1;
   6156     int index, profile_index;
   6157     mmu_wred_drop_curve_profile_0_entry_t entry_tcp_green;
   6158     mmu_wred_drop_curve_profile_1_entry_t entry_tcp_yellow;
   6159     mmu_wred_drop_curve_profile_2_entry_t entry_tcp_red;
   6160     mmu_wred_drop_curve_profile_3_entry_t entry_nontcp_green;
   6161     mmu_wred_drop_curve_profile_4_entry_t entry_nontcp_yellow;
   6162     mmu_wred_drop_curve_profile_5_entry_t entry_nontcp_red;
   6163     void *entries[6];
   6164     void *entry_p;
   6165     soc_mem_t mem;
   6166     soc_mem_t wred_mem = 0;
   6167     mmu_wred_config_entry_t qentry;
   6168     int rate, pipe,time_id,time;
   6169 
   6170 
   6171     BCM_IF_ERROR_RETURN(_bcm_td2_cosq_wred_index_resolve(unit, port, cosq,
   6172                             *flags, lflags, &local_port, &index, NULL, NULL, NULL));
   6173 
   6174     if (local_port < 0) {
   6175         /*
   6176          *  local_port is -1, when flag is BCM_COSQ_DISCARD_DEVICE and port = -1 
   6177          *  global config is set in both X_PIPE and Y_PIPE, since there are identical
   6178          *  just read the config of X PIPE should be sufficient
   6179          */
   6180         pipe = _TD2_XPIPE;
   6181     } else {
   6182         pipe = _BCM_TD2_PORT_TO_PIPE(unit, local_port);
   6183     }
   6184 
   6185     /* WRED doesn't work on CPU/LB Ports */
   6186     if (IS_LB_PORT(unit, local_port) || IS_CPU_PORT(unit, local_port)) {
   6187         return BCM_E_PORT;
   6188     }
   6189 
   6190     wred_mem = (pipe == _TD2_XPIPE) ? MMU_WRED_CONFIG_X_PIPEm : MMU_WRED_CONFIG_Y_PIPEm;
   6191 
   6192     BCM_IF_ERROR_RETURN
   6193         (soc_mem_read(unit, wred_mem, MEM_BLOCK_ALL, index, &qentry));
   6194     profile_index = soc_mem_field32_get(unit, wred_mem,
   6195                                         &qentry, PROFILE_INDEXf);
   6196 
   6197     if (!(*flags & BCM_COSQ_DISCARD_NONTCP)) {
   6198         if (*flags & BCM_COSQ_DISCARD_COLOR_GREEN) {
   6199             mem = (pipe == _TD2_XPIPE) ? MMU_WRED_DROP_CURVE_PROFILE_0_X_PIPEm :
   6200                                          MMU_WRED_DROP_CURVE_PROFILE_0_Y_PIPEm;
   6201             entry_p = &entry_tcp_green;
   6202         } else if (*flags & BCM_COSQ_DISCARD_COLOR_YELLOW) {
   6203             mem = (pipe == _TD2_XPIPE) ? MMU_WRED_DROP_CURVE_PROFILE_1_X_PIPEm :
   6204                                          MMU_WRED_DROP_CURVE_PROFILE_1_Y_PIPEm;
   6205             entry_p = &entry_tcp_yellow;
   6206         } else if (*flags & BCM_COSQ_DISCARD_COLOR_RED) {
   6207             mem = (pipe == _TD2_XPIPE) ? MMU_WRED_DROP_CURVE_PROFILE_2_X_PIPEm :
   6208                                          MMU_WRED_DROP_CURVE_PROFILE_2_Y_PIPEm;
   6209             entry_p = &entry_tcp_red;
   6210         } else {
   6211             mem = (pipe == _TD2_XPIPE) ? MMU_WRED_DROP_CURVE_PROFILE_0_X_PIPEm :
   6212                                          MMU_WRED_DROP_CURVE_PROFILE_0_Y_PIPEm;
   6213            entry_p = &entry_tcp_green;
   6214         }
   6215     } else {
   6216         if (*flags & BCM_COSQ_DISCARD_COLOR_GREEN) {
   6217             mem = (pipe == _TD2_XPIPE) ? MMU_WRED_DROP_CURVE_PROFILE_3_X_PIPEm :
   6218                                          MMU_WRED_DROP_CURVE_PROFILE_3_Y_PIPEm;
   6219             entry_p = &entry_nontcp_green;
   6220         } else if (*flags & BCM_COSQ_DISCARD_COLOR_YELLOW) {
   6221             mem = (pipe == _TD2_XPIPE) ? MMU_WRED_DROP_CURVE_PROFILE_4_X_PIPEm :
   6222                                          MMU_WRED_DROP_CURVE_PROFILE_4_Y_PIPEm;
   6223             entry_p = &entry_nontcp_yellow;
   6224         } else if (*flags & BCM_COSQ_DISCARD_COLOR_RED) {
   6225             mem = (pipe == _TD2_XPIPE) ? MMU_WRED_DROP_CURVE_PROFILE_5_X_PIPEm :
   6226                                          MMU_WRED_DROP_CURVE_PROFILE_5_Y_PIPEm;
   6227             entry_p = &entry_nontcp_red;
   6228         } else {
   6229             mem = (pipe == _TD2_XPIPE) ? MMU_WRED_DROP_CURVE_PROFILE_3_X_PIPEm :
   6230                                          MMU_WRED_DROP_CURVE_PROFILE_3_Y_PIPEm;
   6231             entry_p = &entry_nontcp_green;
   6232         }
   6233     }
   6234 
   6235     entries[0] = &entry_tcp_green;
   6236     entries[1] = &entry_tcp_yellow;
   6237     entries[2] = &entry_tcp_red;
   6238     entries[3] = &entry_nontcp_green;
   6239     entries[4] = &entry_nontcp_yellow;
   6240     entries[5] = &entry_nontcp_red;
   6241     BCM_IF_ERROR_RETURN
   6242         (soc_profile_mem_get(unit, _bcm_td2_wred_profile[pipe][unit],
   6243                              profile_index, 1, entries));
   6244     if (min_thresh != NULL) {
   6245         *min_thresh = soc_mem_field32_get(unit, mem, entry_p, MIN_THDf);
   6246     }
   6247     if (max_thresh != NULL) {
   6248         *max_thresh = soc_mem_field32_get(unit, mem, entry_p, MAX_THDf);
   6249     }
   6250     if (drop_probability != NULL) {
   6251         rate = soc_mem_field32_get(unit, mem, entry_p, MAX_DROP_RATEf);
   6252         *drop_probability = _bcm_td2_drop_prob_to_percent(rate);
   6253     }
   6254 
   6255     if (gain) {
   6256         *gain = soc_mem_field32_get(unit, wred_mem, &qentry, WEIGHTf);
   6257     }
   6258 
   6259     if (refresh_time) {
   6260         time_id = soc_mem_field32_get(unit, wred_mem, &qentry, TIME_DOMAIN_SELf);
   6261         BCM_IF_ERROR_RETURN
   6262             (_bcm_td2_cosq_time_domain_get(unit,time_id,&time));
   6263         *refresh_time = (time + 1) * 8;
   6264     }
   6265 
   6266     *flags &= ~(BCM_COSQ_DISCARD_CAP_AVERAGE | BCM_COSQ_DISCARD_ENABLE);
   6267     if (soc_mem_field32_get(unit, wred_mem, &qentry, CAP_AVERAGEf)) {
   6268         *flags |= BCM_COSQ_DISCARD_CAP_AVERAGE;
   6269     }
   6270     if (soc_mem_field32_get(unit, wred_mem, &qentry, WRED_ENf)) {
   6271         *flags |= BCM_COSQ_DISCARD_ENABLE;
   6272     }
   6273     if (soc_mem_field32_get(unit, wred_mem, &qentry, ECN_MARKING_ENf)) {
   6274         *flags |= BCM_COSQ_DISCARD_MARK_CONGESTION;
   6275     }
   6276     return BCM_E_NONE;
   6277 }
   6278 
   6279 STATIC int
   6280 _bcm_td2_decode_sp_masks(int num_sp, uint32 ucmap, uint32 *umap, int *numuc,
   6281                             uint32 *mmap, int *nummc)
   6282 {
   6283     int i, uindex, mindex;
   6284     uint32 tmp_umap = 0, tmp_mmap = 0;
   6285     
   6286     mindex = uindex = 0;
   6287 
   6288     for (i = 0; i < num_sp; i++) {
   6289         if (ucmap & (1 << i)) {
   6290             /* MC */
   6291             tmp_mmap |= 1 << mindex;
   6292             mindex += 1;
   6293         } else {
   6294             /* UC */
   6295             tmp_umap |= 1 << uindex;
   6296             uindex += 1;
   6297         }
   6298     }
   6299 
   6300     if (numuc) {
   6301         *numuc = uindex;
   6302     }
   6303 
   6304     if (umap) {
   6305         *umap = tmp_umap;
   6306     }
   6307 
   6308     if (mmap) {
   6309         *mmap = tmp_mmap;
   6310     }
   6311 
   6312     if (nummc) {
   6313         *nummc = mindex;
   6314     }
   6315 
   6316     return 0;
   6317 }
   6318 
   6319 STATIC int
   6320 _bcm_td2_sched_check_constraints(int unit, int level, 
   6321                                  int *first_sp_child, 
   6322                                  int *first_sp_mc_child,
   6323                                  int *num_spri,
   6324                                  uint32 *ucmap, 
   6325                                  int child_index, 
   6326                                  soc_td2_sched_mode_e cur_mode,
   6327                                  soc_td2_sched_mode_e mode)
   6328 {
   6329     int cur_first_child;
   6330     int cur_num_spri;
   6331     int cur_ucmap;
   6332     int diff;
   6333 
   6334     uint32 umap = 0, mmap = 0;
   6335     int  numuc = 0, nummc = 0;
   6336     uint32 pnumn = 0;
   6337 
   6338     if (((cur_mode != SOC_TD2_SCHED_MODE_STRICT) &&
   6339         (mode != SOC_TD2_SCHED_MODE_STRICT)) ||
   6340        ((cur_mode == SOC_TD2_SCHED_MODE_STRICT) && 
   6341         (mode == SOC_TD2_SCHED_MODE_STRICT))) {
   6342         return BCM_E_NONE;
   6343     }
   6344 
   6345     cur_num_spri = *num_spri;
   6346     cur_ucmap = *ucmap;
   6347   
   6348     if (level == SOC_TD2_NODE_LVL_L1) {
   6349         _bcm_td2_decode_sp_masks(cur_num_spri, cur_ucmap, &umap, 
   6350                                             &numuc, &mmap, &nummc);
   6351         if (child_index < 1480) {
   6352             /* UC */
   6353             pnumn = numuc;
   6354             cur_num_spri = numuc;
   6355             cur_first_child = *first_sp_child;
   6356         } else {
   6357             /* MC */
   6358             pnumn = nummc;
   6359             cur_num_spri = nummc;
   6360             cur_first_child = *first_sp_mc_child;
   6361         }
   6362     } else {
   6363         pnumn = cur_num_spri;
   6364         cur_first_child = *first_sp_child;
   6365     }
   6366 
   6367     if (cur_mode == SOC_TD2_SCHED_MODE_STRICT) {
   6368         if ((child_index == cur_first_child) && (pnumn > 1)) {
   6369             /* First SP node changed. Hence increment first_sp to next node */
   6370             if (level == SOC_TD2_NODE_LVL_L1) {
   6371                 if (child_index < 1480) {
   6372                     *first_sp_child = *first_sp_child + 1;
   6373                 } else {
   6374                     *first_sp_mc_child = *first_sp_mc_child + 1;
   6375                 }
   6376             } else {
   6377                 *first_sp_child = *first_sp_child + 1;
   6378             }
   6379         } else if (child_index != (cur_first_child + pnumn - 1)) {
   6380             /* this node is not in the middle of SP nodes */
   6381             return BCM_E_UNAVAIL;
   6382         }
   6383 
   6384         cur_num_spri -= 1;
   6385         pnumn -= 1;
   6386 
   6387         if (level == SOC_TD2_NODE_LVL_L1) {
   6388             if (child_index < 1480) {
   6389                 *num_spri = pnumn + nummc;
   6390             } else {
   6391                 *num_spri = pnumn + numuc;
   6392                 *ucmap >>= 1;
   6393             }
   6394         } else {
   6395             *num_spri = cur_num_spri;
   6396             *ucmap = cur_num_spri ? (1 << cur_num_spri) -1 : 0;
   6397         }
   6398         if (*num_spri == 0) {
   6399             *ucmap = 0;
   6400         }
   6401     } else {
   6402         if (cur_num_spri) {         
   6403             if (cur_num_spri >=  8) {
   6404                 return BCM_E_PARAM;
   6405             } else {
   6406                 /* adding new sp */
   6407                 if (child_index >= cur_first_child) {
   6408                     diff = child_index - cur_first_child;
   6409                     if (diff != cur_num_spri) {
   6410                         return BCM_E_UNAVAIL;
   6411                     }
   6412                 } else {
   6413                     /* Setting of SP node prior to the current first SP child,
   6414                      * need to make sure SP nodes are contiguous.
   6415                      */
   6416                     if ((child_index + 1) != cur_first_child) {
   6417                         return BCM_E_UNAVAIL;
   6418                     }
   6419                     if (level == SOC_TD2_NODE_LVL_L1) {
   6420                         if (child_index < 1480) {
   6421                             *first_sp_child = child_index;
   6422                         } else {
   6423                             *first_sp_mc_child = child_index;
   6424                         }
   6425                     } else {
   6426                         *first_sp_child = child_index;
   6427                     }
   6428                 }
   6429 
   6430                 if (level == SOC_TD2_NODE_LVL_L1) {
   6431                     if (child_index < 1480) {
   6432                         pnumn += 1;
   6433                         *num_spri = pnumn + nummc;
   6434                     } else {
   6435                         pnumn += 1;
   6436                         *num_spri = pnumn + numuc;
   6437                         *ucmap = ((*ucmap ) << 1) + 1;
   6438                     }
   6439                 } else {
   6440                     pnumn += 1;
   6441                     *num_spri = pnumn;
   6442                     *ucmap = (1 << pnumn) - 1;
   6443                 }
   6444             }
   6445         } else {
   6446             *num_spri = 1;
   6447             *ucmap = 1;
   6448             if (level == SOC_TD2_NODE_LVL_L1) {
   6449                 if (child_index < 1480) {
   6450                     *first_sp_child = child_index;
   6451                     *ucmap = 0;
   6452                 } else {
   6453                     *first_sp_mc_child = child_index;
   6454                 }
   6455             } else {
   6456                 *first_sp_child = child_index;
   6457             }
   6458         }
   6459     }
   6460     return BCM_E_NONE;
   6461 }
   6462 
   6463 STATIC int
   6464 _bcm_td2_cosq_sched_parent_child_set(int unit, int port, int level,
   6465                                      int sched_index, int child_index,
   6466                                      soc_td2_sched_mode_e sched_mode, 
   6467                                      int weight, _bcm_td2_cosq_node_t *child_node)
   6468 {
   6469     int wt, num_spri, first_sp_child, first_sp_mc_child;
   6470     uint32 ucmap = 0, spmap = 0;
   6471     soc_td2_sched_mode_e cur_sched_mode;
   6472     _bcm_td2p_lls_info_t lls_tree_info;
   6473     int rv;
   6474 
   6475     BCM_IF_ERROR_RETURN(soc_td2_cosq_get_sched_config(unit, port, level,
   6476                 sched_index, child_index, &num_spri, &first_sp_child,
   6477                 &first_sp_mc_child, &ucmap, &spmap, &cur_sched_mode, 
   6478                 &wt));    
   6479     /* If the dynamic switchover feature is enabled, then compute the LLS 
   6480        configuration and adjust the bandwidth at the level such that each 
   6481        node has sufficient bandwidth to perform the switchover. Also set
   6482        the new scheduler config based on the request */ 
   6483     if (soc_feature(unit, soc_feature_vector_based_spri)) {
   6484         
   6485         if ((rv = _bcm_td2_compute_lls_config(unit, port, level, &first_sp_child, 
   6486                     &first_sp_mc_child, &num_spri, 
   6487                     &ucmap, &spmap, child_index, 
   6488                     cur_sched_mode, sched_mode))) {
   6489             return rv;
   6490         }
   6491 
   6492         if (cur_sched_mode != sched_mode) {
   6493             SOC_EGRESS_METERING_LOCK(unit);
   6494             if ((rv = _bcm_td2_adjust_lls_bw(unit, port, child_node,
   6495                           level + 1, child_index, 1, &lls_tree_info))){
   6496                 goto restore;
   6497             }
   6498         }
   6499 
   6500         if ((rv = soc_td2_cosq_set_sched_config(unit, port, level,
   6501                     sched_index, child_index,
   6502                     num_spri, first_sp_child,
   6503                     first_sp_mc_child, ucmap,
   6504                     spmap, sched_mode, weight))){
   6505             goto restore;
   6506         }
   6507 
   6508         if (cur_sched_mode != sched_mode) {
   6509             goto restore;
   6510         }
   6511 
   6512     } else {
   6513         if (_bcm_td2_sched_check_constraints(unit, level, &first_sp_child, 
   6514                     &first_sp_mc_child, &num_spri, &ucmap,
   6515                     child_index, cur_sched_mode, sched_mode)) {
   6516             return BCM_E_UNAVAIL;
   6517         }
   6518 
   6519         BCM_IF_ERROR_RETURN(soc_td2_cosq_set_sched_config(unit, port, level,
   6520                     sched_index, child_index, num_spri, first_sp_child,
   6521                     first_sp_mc_child, ucmap, spmap, sched_mode, weight));
   6522 
   6523     }
   6524 
   6525     return BCM_E_NONE;
   6526 
   6527 /* If there is an error during the switchover process, then restore the 
   6528    bandwidth to the previous state */
   6529 restore:
   6530     if (cur_sched_mode != sched_mode) {
   6531         rv = _bcm_td2_adjust_lls_bw(unit, port, child_node,
   6532                                     level + 1,
   6533                                     child_index,
   6534                                     0, &lls_tree_info);
   6535         SOC_EGRESS_METERING_UNLOCK(unit);
   6536     }
   6537     return rv;
   6538 
   6539 }
   6540 
   6541 /*
   6542  * Function:
   6543  *     _bcm_td2_cosq_sched_get
   6544  * Purpose:
   6545  *     Get scheduling mode setting
   6546  * Parameters:
   6547  *     unit                - (IN) unit number
   6548  *     port                - (IN) port number or GPORT identifier
   6549  *     cosq                - (IN) COS queue number
   6550  *     mode                - (OUT) scheduling mode (BCM_COSQ_XXX)
   6551  *     num_weights         - (IN) number of entries in weights array
   6552  *     weights             - (OUT) weights array
   6553  * Returns:
   6554  *     BCM_E_XXX
   6555  */
   6556 STATIC int
   6557 _bcm_td2_cosq_sched_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   6558                        int *mode, int *weight)
   6559 {
   6560     _bcm_td2_cosq_node_t *node, *child_node;
   6561     bcm_port_t local_port;
   6562     int sch_index, lvl = SOC_TD2_NODE_LVL_L1, numq;
   6563     soc_td2_sched_mode_e    sched_mode;
   6564     _bcm_td2_mmu_info_t *mmu_info;
   6565 
   6566     if ((mmu_info = _bcm_td2_mmu_info[unit]) == NULL) {
   6567         return BCM_E_INIT;
   6568     }
   6569 
   6570     if (cosq < 0) {
   6571         if (cosq == -1) {
   6572             /* caller needs to resolve the wild card value (-1) */
   6573             return BCM_E_INTERNAL;
   6574         } else { /* reject all other negative value */
   6575             return BCM_E_PARAM;
   6576         }
   6577     }
   6578 
   6579     BCM_IF_ERROR_RETURN
   6580         (_bcm_td2_cosq_localport_resolve(unit, port, &local_port));
   6581 
   6582     if (_bcm_td2_cosq_port_has_ets(unit, local_port) && BCM_GPORT_IS_SET(port)) {
   6583         BCM_IF_ERROR_RETURN
   6584           (_bcm_td2_cosq_node_get(unit, port, 0, NULL, &local_port, NULL, &node));
   6585         sch_index = node->hw_index;
   6586         numq = node->numq;
   6587         if ((numq != -1) && (cosq >= numq)) {
   6588             return BCM_E_PARAM;
   6589         }
   6590 
   6591         BCM_IF_ERROR_RETURN(
   6592             _bcm_td2_cosq_child_node_at_input(node, cosq, &child_node));
   6593         lvl = child_node->level;
   6594         sch_index = child_node->hw_index;
   6595     } else {
   6596         numq = (IS_CPU_PORT(unit, local_port)) ? SOC_INFO(unit).num_cpu_cosq : NUM_COS(unit);
   6597 
   6598         if (cosq >= numq) {
   6599             return BCM_E_PARAM;
   6600         }
   6601 
   6602         lvl = (IS_CPU_PORT(unit, local_port)) ? 
   6603                             SOC_TD2_NODE_LVL_L2 : SOC_TD2_NODE_LVL_L1;
   6604 
   6605         BCM_IF_ERROR_RETURN(_bcm_td2_cosq_index_resolve(unit, local_port, cosq,
   6606                    _BCM_TD2_COSQ_INDEX_STYLE_SCHEDULER, NULL, &sch_index, NULL));
   6607 
   6608     }
   6609 
   6610     BCM_IF_ERROR_RETURN(
   6611             soc_td2_cosq_get_sched_mode(unit, local_port, lvl, sch_index,
   6612                             &sched_mode, weight));
   6613 
   6614     switch(sched_mode) {
   6615         case SOC_TD2_SCHED_MODE_STRICT:
   6616             *mode = BCM_COSQ_STRICT;
   6617         break;
   6618         case SOC_TD2_SCHED_MODE_WRR:
   6619             *mode = BCM_COSQ_WEIGHTED_ROUND_ROBIN;
   6620         break;
   6621         case SOC_TD2_SCHED_MODE_WDRR:
   6622             *mode = BCM_COSQ_DEFICIT_ROUND_ROBIN;
   6623         break;
   6624         default:
   6625             return BCM_E_INTERNAL;
   6626         break;
   6627     }
   6628     return BCM_E_NONE;
   6629 }
   6630 
   6631 
   6632 /*
   6633  * Function:
   6634  *     _bcm_td2_cosq_sched_set
   6635  * Purpose:
   6636  *     Set scheduling mode
   6637  * Parameters:
   6638  *     unit                - (IN) unit number
   6639  *     port                - (IN) port number or GPORT identifier
   6640  *     cosq                - (IN) COS queue number
   6641  *     mode                - (IN) scheduling mode (BCM_COSQ_XXX)
   6642  *     num_weights         - (IN) number of entries in weights array
   6643  *     weights             - (IN) weights array
   6644  * Returns:
   6645  *     BCM_E_XXX
   6646  */
   6647 STATIC int
   6648 _bcm_td2_cosq_sched_set(int unit, bcm_port_t gport, bcm_cos_queue_t cosq,
   6649                         int mode, int weight)
   6650 {
   6651     _bcm_td2_cosq_node_t *node = NULL, *child_node;
   6652     bcm_port_t local_port;
   6653     int sch_index, lvl = SOC_TD2_NODE_LVL_L0, cpu_l0_index;
   6654     int numq, lwts = 1, child_index, cpu_l1_index, roff = 0;
   6655     soc_td2_sched_mode_e sched_mode;
   6656     int rv = BCM_E_NONE;
   6657     int     cur_mode, cur_weight, new_mode;
   6658     /* 1 - indicates dynamic change allowed without emptying the queue. */
   6659     int     dynamic_change = 0;
   6660     void *setting = NULL;
   6661 
   6662     if (cosq < 0) {
   6663         if (cosq == -1) {
   6664             /* caller needs to resolve the wild card value (-1) */
   6665             return BCM_E_INTERNAL;
   6666         } else { /* reject all other negative value */
   6667             return BCM_E_PARAM;
   6668         }
   6669     }
   6670 
   6671     if ((weight < 0) || (weight > 127)) {
   6672         return BCM_E_PARAM;
   6673     }
   6674 
   6675     switch(mode) {
   6676         case BCM_COSQ_STRICT:
   6677             sched_mode = SOC_TD2_SCHED_MODE_STRICT;
   6678             lwts = 0;
   6679         break;
   6680         case BCM_COSQ_ROUND_ROBIN:
   6681             sched_mode = SOC_TD2_SCHED_MODE_WRR;
   6682             lwts = 1;
   6683         break;
   6684         case BCM_COSQ_WEIGHTED_ROUND_ROBIN:
   6685             sched_mode = SOC_TD2_SCHED_MODE_WRR;
   6686             lwts = weight;
   6687         break;
   6688         case BCM_COSQ_DEFICIT_ROUND_ROBIN:
   6689             sched_mode = SOC_TD2_SCHED_MODE_WDRR;
   6690             lwts = weight;
   6691         break;
   6692         default:
   6693             return BCM_E_PARAM;
   6694     }
   6695 
   6696     if ( lwts == 0) {
   6697         sched_mode = SOC_TD2_SCHED_MODE_STRICT;
   6698     }
   6699 
   6700     BCM_IF_ERROR_RETURN
   6701         (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port));
   6702 
   6703     BCM_IF_ERROR_RETURN
   6704         (_bcm_td2_cosq_sched_get(unit, gport, cosq, &cur_mode, &cur_weight));
   6705     
   6706     new_mode = (weight == 0) ? BCM_COSQ_STRICT : mode;
   6707     
   6708     /*The weight for both WDRR and WRR schemes can be changed dynamically.*/
   6709     if ((cur_mode == new_mode) && 
   6710         (new_mode != BCM_COSQ_STRICT)){
   6711         dynamic_change = 1;
   6712     } else {
   6713         dynamic_change = 0;
   6714     }
   6715 
   6716     if (!dynamic_change) {
   6717         /* don't apply it for TD2+ if dynamic scheduling feature is enabled*/
   6718         if (!soc_feature(unit, soc_feature_vector_based_spri)) {
   6719             BCM_IF_ERROR_RETURN
   6720                 (_bcm_td2_dynamic_sched_update_begin(unit, gport, cosq));
   6721         }
   6722 
   6723     }
   6724 
   6725     if (_bcm_td2_cosq_port_has_ets(unit, local_port)) {
   6726         rv = _bcm_td2_cosq_node_get(unit, gport, 0, NULL, &local_port, NULL, &node);
   6727         if (BCM_SUCCESS(rv)) {
   6728             numq = node->numq;
   6729             /* HSP/LLS - child node at cosq index of parent gport
   6730              * is resloved to set it's schedule mode and weight
   6731              */
   6732             rv = _bcm_td2_cosq_child_node_at_input(node, cosq, &child_node);
   6733             if (BCM_SUCCESS(rv)) {
   6734                 child_index = child_node->hw_index;
   6735                 if (IS_TD2_HSP_PORT(unit, local_port)) {
   6736                     rv = soc_td2_cosq_set_sched_mode(unit, local_port,
   6737                                  child_node->level, child_node->hw_index, sched_mode, lwts);
   6738                 } else {
   6739                     BCM_IF_ERROR_RETURN(_soc_egress_metering_freeze(unit,
   6740                                                         local_port, &setting));
   6741                     rv = _bcm_td2_cosq_sched_parent_child_set(unit,
   6742                           local_port, node->level, node->hw_index,
   6743                           child_node->hw_index, sched_mode, lwts, child_node);
   6744                     BCM_IF_ERROR_RETURN(_soc_egress_metering_thaw(unit,
   6745                                                         local_port, setting));
   6746                 }
   6747             }
   6748         }
   6749     } else {
   6750         numq = (IS_CPU_PORT(unit, local_port)) ? SOC_INFO(unit).num_cpu_cosq : NUM_COS(unit);
   6751 
   6752         if (cosq >= numq) {
   6753             rv = BCM_E_PARAM;
   6754         }
   6755 
   6756         if (BCM_SUCCESS(rv)) {
   6757             if (IS_CPU_PORT(unit, local_port)) {
   6758                 lvl = SOC_TD2_NODE_LVL_L1;
   6759                 roff = cosq/8;
   6760             } else if (IS_TD2_HSP_PORT(unit, local_port)) {
   6761                 lvl = SOC_TD2_NODE_LVL_L0;
   6762                 roff = 1;
   6763             } else {
   6764                 lvl = SOC_TD2_NODE_LVL_L0;
   6765             }
   6766 
   6767             rv = soc_td2_sched_hw_index_get(unit, local_port, 
   6768                                             lvl, roff, &sch_index);
   6769         }
   6770         if (BCM_SUCCESS(rv)) {
   6771             rv = _bcm_td2_cosq_index_resolve(unit, local_port, cosq,
   6772                    _BCM_TD2_COSQ_INDEX_STYLE_SCHEDULER, NULL, &child_index, NULL);
   6773         } 
   6774         
   6775         if (BCM_SUCCESS(rv)) {
   6776             if (IS_TD2_HSP_PORT(unit, local_port)) {
   6777                 rv = soc_td2_cosq_set_sched_mode(unit, local_port,
   6778                                                  SOC_TD2_NODE_LVL_L1,
   6779                                                  child_index, 
   6780                                                  sched_mode, lwts);
   6781             } else {
   6782                 if (IS_CPU_PORT(unit, local_port)) {
   6783                     /* set the L0.0 index as parent, L0.(cosq/8) as child in 
   6784                     * schduling mode */
   6785                     rv = soc_td2_sched_hw_index_get(unit, local_port, 
   6786                                      SOC_TD2_NODE_LVL_L0, 0, &cpu_l0_index);
   6787                     if (BCM_SUCCESS(rv)) {
   6788                         rv = soc_td2_sched_hw_index_get(unit, local_port, 
   6789                                     SOC_TD2_NODE_LVL_L1, cosq/8, &cpu_l1_index);
   6790                     }
   6791                     if (BCM_SUCCESS(rv)) {
   6792                         BCM_IF_ERROR_RETURN(_soc_egress_metering_freeze(unit,
   6793                                                             local_port, &setting));
   6794                         rv = _bcm_td2_cosq_sched_parent_child_set(unit, 
   6795                                   local_port, SOC_TD2_NODE_LVL_L0, cpu_l0_index, 
   6796                                   cpu_l1_index, sched_mode, 1, NULL);
   6797                         BCM_IF_ERROR_RETURN(_soc_egress_metering_thaw(unit,
   6798                                                             local_port, setting));
   6799                     }
   6800                 }
   6801                 if (BCM_SUCCESS(rv)) {
   6802                     BCM_IF_ERROR_RETURN(_soc_egress_metering_freeze(unit,
   6803                                                         local_port, &setting));
   6804                     rv = _bcm_td2_cosq_sched_parent_child_set(unit, local_port,
   6805                             lvl, sch_index, child_index, sched_mode, lwts, NULL);
   6806                     BCM_IF_ERROR_RETURN(_soc_egress_metering_thaw(unit,
   6807                                                         local_port, setting));
   6808                 }
   6809             }
   6810         }
   6811     }
   6812 
   6813     if (!dynamic_change) {
   6814         /* don't apply it for TD2+ if dynamic scheduling feature is enabled*/
   6815         if (!soc_feature(unit, soc_feature_vector_based_spri)) {
   6816             BCM_IF_ERROR_RETURN
   6817                 (_bcm_td2_dynamic_sched_update_end(unit, gport, cosq));
   6818         } 
   6819     }
   6820 
   6821     return rv;
   6822 }
   6823 
   6824 
   6825 /*
   6826  * Function:
   6827  *     bcm_td2_cosq_detach
   6828  * Purpose:
   6829  *     Discard all COS schedule/mapping state.
   6830  * Parameters:
   6831  *     unit - unit number
   6832  * Returns:
   6833  *     BCM_E_XXX
   6834  */
   6835 int
   6836 bcm_td2_cosq_detach(int unit, int software_state_only)
   6837 {
   6838     int i, pipe;
   6839     soc_info_t *si;
   6840 
   6841     si = &SOC_INFO(unit);
   6842 
   6843     (void) _bcm_bst_detach(unit);
   6844 
   6845     if (NULL != _bcm_td2_endpoint_queuing_info[unit]) {
   6846         if (NULL != _bcm_td2_endpoint_queuing_info[unit]->ptr_array) {
   6847             for (i = 0; i < _BCM_TD2_NUM_ENDPOINT(unit); i++) {
   6848                 if (_BCM_TD2_ENDPOINT_IS_USED(unit, i)) {
   6849                     sal_free(_BCM_TD2_ENDPOINT(unit, i));
   6850                     _BCM_TD2_ENDPOINT(unit, i) = NULL;
   6851                 }
   6852             }
   6853             sal_free(_bcm_td2_endpoint_queuing_info[unit]->ptr_array);
   6854             _bcm_td2_endpoint_queuing_info[unit]->ptr_array = NULL;
   6855         }
   6856         if (NULL != _bcm_td2_endpoint_queuing_info[unit]->cos_map_profile) {
   6857             (void) soc_profile_mem_destroy(unit,
   6858                        _bcm_td2_endpoint_queuing_info[unit]->cos_map_profile);
   6859             sal_free(_bcm_td2_endpoint_queuing_info[unit]->cos_map_profile);
   6860             _bcm_td2_endpoint_queuing_info[unit]->cos_map_profile = NULL;
   6861         }
   6862         sal_free(_bcm_td2_endpoint_queuing_info[unit]);
   6863         _bcm_td2_endpoint_queuing_info[unit] = NULL;
   6864     }
   6865 
   6866     /* Cleanup profile for PORT_COS_MAP table */
   6867     if (_bcm_td2_cos_map_profile[unit] != NULL) {
   6868         SOC_IF_ERROR_RETURN(soc_profile_mem_destroy(unit,
   6869                                 _bcm_td2_cos_map_profile[unit]));
   6870         sal_free(_bcm_td2_cos_map_profile[unit]);
   6871         _bcm_td2_cos_map_profile[unit] = NULL;
   6872     }
   6873 
   6874     /* Cleanup profile for IFP_COS_MAP table. */
   6875     if (_bcm_td2_ifp_cos_map_profile[unit] != NULL) {
   6876         SOC_IF_ERROR_RETURN(soc_profile_mem_destroy(unit,
   6877                                 _bcm_td2_ifp_cos_map_profile[unit]));
   6878         sal_free(_bcm_td2_ifp_cos_map_profile[unit]);
   6879         _bcm_td2_ifp_cos_map_profile[unit] = NULL;
   6880     }
   6881 
   6882     /* Cleanup profile for SERVICE_COS_MAP table */
   6883     if (_bcm_td2_service_cos_map_profile[unit] != NULL) {
   6884         SOC_IF_ERROR_RETURN(soc_profile_mem_destroy(unit,
   6885                                 _bcm_td2_service_cos_map_profile[unit]));
   6886         sal_free(_bcm_td2_service_cos_map_profile[unit]);
   6887         _bcm_td2_service_cos_map_profile[unit] = NULL;
   6888     }
   6889 
   6890     /* Cleanup profile for SERVICE_PORT_MAP table */
   6891     if (_bcm_td2_service_port_map_profile[unit] != NULL) {
   6892         SOC_IF_ERROR_RETURN(soc_profile_mem_destroy(unit,
   6893                                 _bcm_td2_service_port_map_profile[unit]));
   6894         sal_free(_bcm_td2_service_port_map_profile[unit]);
   6895         _bcm_td2_service_port_map_profile[unit] = NULL;
   6896     }
   6897 
   6898     /* Cleanup profile for MMU_QCN_SITB table */
   6899     if (_bcm_td2_sample_int_profile[unit] != NULL) {
   6900         SOC_IF_ERROR_RETURN(soc_profile_mem_destroy(unit,
   6901                                  _bcm_td2_sample_int_profile[unit]));
   6902         sal_free(_bcm_td2_sample_int_profile[unit]);
   6903         _bcm_td2_sample_int_profile[unit] = NULL;
   6904     }
   6905 
   6906     /* Cleanup profile for MMU_QCN_CPQ_SEQ register */
   6907     if (_bcm_td2_feedback_profile[unit] != NULL) {
   6908         SOC_IF_ERROR_RETURN(soc_profile_reg_destroy(unit,
   6909                                 _bcm_td2_feedback_profile[unit]));
   6910         sal_free(_bcm_td2_feedback_profile[unit]);
   6911         _bcm_td2_feedback_profile[unit] = NULL;
   6912     }
   6913 
   6914     /* Cleanup profile for PRIO2COS_LLFC register */
   6915     if (_bcm_td2_llfc_profile[unit] != NULL) {
   6916         SOC_IF_ERROR_RETURN(soc_profile_reg_destroy(unit,
   6917                                 _bcm_td2_llfc_profile[unit]));
   6918         sal_free(_bcm_td2_llfc_profile[unit]);
   6919         _bcm_td2_llfc_profile[unit] = NULL;
   6920     }
   6921 
   6922     /* Cleanup profile for VOQ_MOD_MAP table */
   6923     if (_bcm_td2_voq_port_map_profile[unit] != NULL) {
   6924         SOC_IF_ERROR_RETURN(soc_profile_mem_destroy(unit,
   6925                                 _bcm_td2_voq_port_map_profile[unit]));
   6926         sal_free(_bcm_td2_voq_port_map_profile[unit]);
   6927         _bcm_td2_voq_port_map_profile[unit] = NULL;
   6928     }
   6929 
   6930     for (pipe = _TD2_XPIPE; pipe <= _TD2_YPIPE; pipe++) {
   6931         /* Cleanup profile for MMU_WRED_DROP_CURVE_PROFILE_x/y tables */
   6932         if (_bcm_td2_wred_profile[pipe][unit] != NULL) {
   6933             SOC_IF_ERROR_RETURN(soc_profile_mem_destroy(unit,
   6934                                     _bcm_td2_wred_profile[pipe][unit]));
   6935             sal_free(_bcm_td2_wred_profile[pipe][unit]);
   6936             _bcm_td2_wred_profile[pipe][unit] = NULL;
   6937         }
   6938     }
   6939 
   6940     for (i = 0; i < si->num_cpu_cosq; i++) {
   6941         if (_bcm_td2_cosq_cpu_cosq_config[unit][i] != NULL) {
   6942             sal_free(_bcm_td2_cosq_cpu_cosq_config[unit][i]);
   6943             _bcm_td2_cosq_cpu_cosq_config[unit][i] = NULL;
   6944         }
   6945     }
   6946 
   6947     if (_bcm_td2_mmu_info[unit] != NULL) {
   6948         _bcm_td2_cosq_free_memory(_bcm_td2_mmu_info[unit]);
   6949         sal_free(_bcm_td2_mmu_info[unit]);
   6950         _bcm_td2_mmu_info[unit] = NULL;
   6951     }
   6952 
   6953     soc_trident2_fc_map_shadow_free(unit);
   6954     return BCM_E_NONE;
   6955 }
   6956 
   6957 /*
   6958  * Function:
   6959  *     bcm_td2_cosq_config_set
   6960  * Purpose:
   6961  *     Set the number of COS queues
   6962  * Parameters:
   6963  *     unit - unit number
   6964  *     numq - number of COS queues (1-8).
   6965  * Returns:
   6966  *     BCM_E_XXX
   6967  */
   6968 int
   6969 bcm_td2_cosq_config_set(int unit, int numq)
   6970 {
   6971     port_cos_map_entry_t cos_map_entries[16];
   6972     port_cos_map_entry_t hg_cos_map_entries[16];
   6973     void *entries[1], *hg_entries[1];
   6974     uint32 index, hg_index;
   6975     int count, hg_count;
   6976     bcm_port_t port;
   6977     int cos, prio;
   6978     uint32 i;
   6979     voq_cos_map_entry_t voq_cos_map;
   6980     int ref_count;
   6981     int cpu_hg_index = 0;
   6982 
   6983     if (numq < 1 || numq > 8) {
   6984         return BCM_E_PARAM;
   6985     }
   6986 
   6987     /* clear out old profiles. */
   6988     index = 0;
   6989     while (index < soc_mem_index_count(unit, PORT_COS_MAPm)) {
   6990         BCM_IF_ERROR_RETURN(soc_profile_mem_ref_count_get(unit,
   6991                                       _bcm_td2_cos_map_profile[unit],
   6992                                       index, &ref_count));
   6993         if (ref_count > 0) {
   6994             while (ref_count) {
   6995                 BCM_IF_ERROR_RETURN(soc_profile_mem_delete(unit, 
   6996                                  _bcm_td2_cos_map_profile[unit], index));
   6997                 ref_count -= 1;
   6998             }
   6999         }
   7000         index += 16;
   7001     }
   7002 
   7003     /* Distribute first 8 internal priority levels into the specified number
   7004      * of cosq, map remaining internal priority levels to highest priority
   7005      * cosq */
   7006     sal_memset(cos_map_entries, 0, sizeof(cos_map_entries));
   7007     entries[0] = &cos_map_entries;
   7008     hg_entries[0] = &hg_cos_map_entries;
   7009     prio = 0;
   7010     for (cos = 0; cos < numq; cos++) {
   7011         for (i = 8 / numq + (cos < 8 % numq ? 1 : 0); i > 0; i--) {
   7012             soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio],
   7013                                 UC_COS1f, cos);
   7014             soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio],
   7015                                 MC_COS1f, cos);
   7016             soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio],
   7017                                 HG_COSf, cos);
   7018             soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio],
   7019                                 RQE_Q_NUMf, cos);
   7020             prio++;
   7021         }
   7022     }
   7023     for (prio = 8; prio < 16; prio++) {
   7024         soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio],
   7025                             UC_COS1f, numq - 1);
   7026         soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio],
   7027                             MC_COS1f, numq - 1);
   7028         soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio],
   7029                             HG_COSf, numq - 1);
   7030         soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio],
   7031                             RQE_Q_NUMf, numq - 1);
   7032     }
   7033 
   7034     /* Map internal priority levels to CPU CoS queues */
   7035     BCM_IF_ERROR_RETURN(_bcm_esw_cpu_cosq_mapping_default_set(unit, numq));
   7036 
   7037 #ifdef BCM_COSQ_HIGIG_MAP_DISABLE
   7038     /* Use identical mapping for Higig port */
   7039     sal_memset(hg_cos_map_entries, 0, sizeof(hg_cos_map_entries));
   7040     prio = 0;
   7041     for (prio = 0; prio < 8; prio++) {
   7042         soc_mem_field32_set(unit, PORT_COS_MAPm, &hg_cos_map_entries[prio],
   7043                             UC_COS1f, prio);
   7044         soc_mem_field32_set(unit, PORT_COS_MAPm, &hg_cos_map_entries[prio],
   7045                             MC_COS1f, prio);
   7046         soc_mem_field32_set(unit, PORT_COS_MAPm, &hg_cos_map_entries[prio],
   7047                             RQE_Q_NUMf, prio);
   7048     }
   7049     for (prio = 8; prio < 13; prio++) {
   7050         soc_mem_field32_set(unit, PORT_COS_MAPm, &hg_cos_map_entries[prio],
   7051                             UC_COS1f, 7);
   7052         soc_mem_field32_set(unit, PORT_COS_MAPm, &hg_cos_map_entries[prio],
   7053                             MC_COS1f, 7);
   7054         soc_mem_field32_set(unit, PORT_COS_MAPm, &hg_cos_map_entries[prio],
   7055                             RQE_Q_NUMf, 7);
   7056     }
   7057 #else /* BCM_COSQ_HIGIG_MAP_DISABLE */
   7058     sal_memcpy(hg_cos_map_entries, cos_map_entries, sizeof(cos_map_entries));
   7059 #endif /* !BCM_COSQ_HIGIG_MAP_DISABLE */
   7060 
   7061     BCM_IF_ERROR_RETURN
   7062         (soc_profile_mem_add(unit, _bcm_td2_cos_map_profile[unit], 
   7063                                             entries, 16, &index));
   7064     soc_mem_field32_set(unit, PORT_COS_MAPm, &hg_cos_map_entries[14],
   7065                                HG_COSf, 8);
   7066     soc_mem_field32_set(unit, PORT_COS_MAPm, &hg_cos_map_entries[15],
   7067                                HG_COSf, 9);
   7068 
   7069     BCM_IF_ERROR_RETURN
   7070         (soc_profile_mem_add(unit, _bcm_td2_cos_map_profile[unit], 
   7071                                             hg_entries, 16, &hg_index));
   7072     count = 0;
   7073     hg_count = 0;
   7074     PBMP_ALL_ITER(unit, port) {
   7075         if (IS_LB_PORT(unit, port)) {
   7076             continue;
   7077         }
   7078         
   7079         if (IS_HG_PORT(unit, port)) {
   7080             BCM_IF_ERROR_RETURN
   7081                 (soc_mem_field32_modify(unit, COS_MAP_SELm, port, SELECTf,
   7082                                         hg_index / 16));
   7083             hg_count++;
   7084         } else {
   7085             BCM_IF_ERROR_RETURN
   7086                 (soc_mem_field32_modify(unit, COS_MAP_SELm, port, SELECTf,
   7087                                         index / 16));
   7088             count++;
   7089         }
   7090     }
   7091     cpu_hg_index = SOC_INFO(unit).cpu_hg_index;
   7092     if (cpu_hg_index != -1) {
   7093         BCM_IF_ERROR_RETURN
   7094             (soc_mem_field32_modify(unit, COS_MAP_SELm,
   7095                 cpu_hg_index, SELECTf, index / 16));
   7096         count++;
   7097     }
   7098 
   7099     for (i = 1; i < count; i++) {
   7100         soc_profile_mem_reference(unit, _bcm_td2_cos_map_profile[unit], index, 0);
   7101     }
   7102     for (i = 1; i < hg_count; i++) {
   7103         soc_profile_mem_reference(unit, _bcm_td2_cos_map_profile[unit],
   7104                                   hg_index, 0);
   7105     }
   7106     /* Delete the default higig cos map profile for the non-higig system */
   7107     if (hg_count == 0) {
   7108         BCM_IF_ERROR_RETURN(
   7109             soc_profile_mem_delete(unit, _bcm_td2_cos_map_profile[unit],
   7110                                    hg_index));
   7111     }
   7112 
   7113     sal_memset(&voq_cos_map, 0, sizeof(voq_cos_map));
   7114     for (cos = 0; cos < numq; cos++) {
   7115         for (i = 8 / numq + (i < 8 % numq ? 1 : 0); i > 0; i--) {
   7116             soc_mem_field32_set(unit, VOQ_COS_MAPm, &voq_cos_map, VOQ_COS_OFFSETf, cos);
   7117             BCM_IF_ERROR_RETURN(
   7118                 soc_mem_write(unit, VOQ_COS_MAPm, MEM_BLOCK_ANY, cos,
   7119                           &voq_cos_map));
   7120             prio++;
   7121         }
   7122     }
   7123     for (prio = 8; prio < 16; prio++) {
   7124         soc_mem_field32_set(unit, VOQ_COS_MAPm, &voq_cos_map, VOQ_COS_OFFSETf, numq - 1);
   7125         BCM_IF_ERROR_RETURN(
   7126                 soc_mem_write(unit, VOQ_COS_MAPm, MEM_BLOCK_ANY, prio,
   7127                           &voq_cos_map));
   7128     }
   7129 
   7130     _TD2_NUM_COS(unit) = numq;
   7131 
   7132     return BCM_E_NONE;
   7133 }
   7134 
   7135 #ifdef BCM_TRIDENT2PLUS_SUPPORT
   7136 /*
   7137  * Function:
   7138  *     bcm_td2p_port_cosq_config_set
   7139  * Purpose:
   7140  *     called during flexport during port attach/detach
   7141  *     to update the cos_map profile for the port
   7142  * Parameters:
   7143  *     unit   - unit number
   7144  *     port   - port number
   7145  *     enable - add/delete
   7146  * Returns:
   7147  *     BCM_E_XXX
   7148  */
   7149 int
   7150 bcm_td2p_port_cosq_config_set(int unit, bcm_port_t  port, int enable)
   7151 {
   7152     port_cos_map_entry_t cos_map_entries[16];
   7153     port_cos_map_entry_t hg_cos_map_entries[16];
   7154     cos_map_sel_entry_t cos_map_sel_entry;
   7155     void *entries[1], *hg_entries[1];
   7156     uint32 index,  old_index, hg_index;
   7157     int cos, prio, numq, rv;
   7158     uint32 i;
   7159 
   7160     numq = _TD2_NUM_COS(unit);
   7161 
   7162     sal_memset(cos_map_entries, 0, sizeof(cos_map_entries));
   7163     entries[0] = &cos_map_entries;
   7164     hg_entries[0] = &hg_cos_map_entries;
   7165     prio = 0;
   7166     if (enable) {
   7167         for (cos = 0; cos < numq; cos++) {
   7168             for (i = 8 / numq + (cos < 8 % numq ? 1 : 0); i > 0; i--) {
   7169                 soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio],
   7170                         UC_COS1f, cos);
   7171                 soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio],
   7172                         MC_COS1f, cos);
   7173                 soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio],
   7174                         HG_COSf, cos);
   7175                 soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio],
   7176                         RQE_Q_NUMf, cos);
   7177                 prio++;
   7178             }
   7179         }
   7180         for (prio = 8; prio < 16; prio++) {
   7181             soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio],
   7182                     UC_COS1f, numq - 1);
   7183             soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio],
   7184                     MC_COS1f, numq - 1);
   7185             soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio],
   7186                     HG_COSf, numq - 1);
   7187             soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio],
   7188                     RQE_Q_NUMf, numq - 1);
   7189         }
   7190 
   7191 
   7192 #ifdef BCM_COSQ_HIGIG_MAP_DISABLE
   7193         /* Use identical mapping for Higig port */
   7194         sal_memset(hg_cos_map_entries, 0, sizeof(hg_cos_map_entries));
   7195         prio = 0;
   7196         for (prio = 0; prio < 8; prio++) {
   7197             soc_mem_field32_set(unit, PORT_COS_MAPm, &hg_cos_map_entries[prio],
   7198                     UC_COS1f, prio);
   7199             soc_mem_field32_set(unit, PORT_COS_MAPm, &hg_cos_map_entries[prio],
   7200                     MC_COS1f, prio);
   7201             soc_mem_field32_set(unit, PORT_COS_MAPm, &hg_cos_map_entries[prio],
   7202                     RQE_Q_NUMf, prio);
   7203         }
   7204         for (prio = 8; prio < 13; prio++) {
   7205             soc_mem_field32_set(unit, PORT_COS_MAPm, &hg_cos_map_entries[prio],
   7206                     UC_COS1f, 7);
   7207             soc_mem_field32_set(unit, PORT_COS_MAPm, &hg_cos_map_entries[prio],
   7208                     MC_COS1f, 7);
   7209             soc_mem_field32_set(unit, PORT_COS_MAPm, &hg_cos_map_entries[prio],
   7210                     RQE_Q_NUMf, 7);
   7211         }
   7212 #else /* BCM_COSQ_HIGIG_MAP_DISABLE */
   7213         sal_memcpy(hg_cos_map_entries, cos_map_entries, sizeof(cos_map_entries));
   7214 #endif /* !BCM_COSQ_HIGIG_MAP_DISABLE */
   7215         soc_mem_field32_set(unit, PORT_COS_MAPm, &hg_cos_map_entries[14],
   7216                 HG_COSf, 8);
   7217         soc_mem_field32_set(unit, PORT_COS_MAPm, &hg_cos_map_entries[15],
   7218                 HG_COSf, 9);
   7219 
   7220         if (IS_HG_PORT(unit, port)) {
   7221             soc_mem_lock(unit, PORT_COS_MAPm);
   7222 
   7223             rv  =  soc_profile_mem_add(unit, _bcm_td2_cos_map_profile[unit],
   7224                     hg_entries, 16, &hg_index);
   7225 
   7226             soc_mem_unlock(unit, PORT_COS_MAPm);
   7227             if (BCM_FAILURE(rv)) {
   7228                 return rv;
   7229             }
   7230             BCM_IF_ERROR_RETURN
   7231                 (soc_mem_field32_modify(unit, COS_MAP_SELm, port, SELECTf,
   7232                                         hg_index / 16));
   7233         } else {
   7234             soc_mem_lock(unit, PORT_COS_MAPm);
   7235 
   7236             rv =  soc_profile_mem_add(unit, _bcm_td2_cos_map_profile[unit],
   7237                     entries, 16, &index);
   7238 
   7239             soc_mem_unlock(unit, PORT_COS_MAPm);
   7240             if (BCM_FAILURE(rv)) {
   7241                 return rv;
   7242             }
   7243             BCM_IF_ERROR_RETURN
   7244                 (soc_mem_field32_modify(unit, COS_MAP_SELm, port, SELECTf,
   7245                                         index / 16));
   7246         }
   7247 
   7248     } else {
   7249         BCM_IF_ERROR_RETURN
   7250             (READ_COS_MAP_SELm(unit, MEM_BLOCK_ANY, port,
   7251                                &cos_map_sel_entry));
   7252         old_index = soc_mem_field32_get(unit, COS_MAP_SELm, &cos_map_sel_entry,
   7253                 SELECTf);
   7254         old_index *= 16;
   7255 
   7256         soc_mem_lock(unit, PORT_COS_MAPm);
   7257 
   7258         rv = soc_profile_mem_delete(unit, _bcm_td2_cos_map_profile[unit],
   7259                 old_index);
   7260 
   7261         soc_mem_unlock(unit, PORT_COS_MAPm);
   7262         if (BCM_FAILURE(rv)) {
   7263             return rv;
   7264         }
   7265     }
   7266     return BCM_E_NONE;
   7267 }
   7268 #endif
   7269 
   7270 STATIC int 
   7271 _bcm_td2_cosq_egress_sp_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 
   7272                         int *p_pool_start, int *p_pool_end)
   7273 {
   7274     int local_port;
   7275     int pool;
   7276     if (cosq == BCM_COS_INVALID) {
   7277         *p_pool_start = 0;
   7278         *p_pool_end = 3;
   7279         return BCM_E_NONE;
   7280     }
   7281 
   7282     BCM_IF_ERROR_RETURN
   7283         (_bcm_td2_cosq_index_resolve(unit, gport, cosq,
   7284                                      _BCM_TD2_COSQ_INDEX_STYLE_EGR_POOL,
   7285                                      &local_port, &pool, NULL));
   7286 
   7287     *p_pool_start = *p_pool_end = pool;
   7288     return BCM_E_NONE;
   7289 }
   7290 
   7291 STATIC int 
   7292 _bcm_td2_cosq_ingress_sp_get(int unit, bcm_gport_t gport, bcm_cos_queue_t pri_grp, 
   7293                          int *p_pool_start, int *p_pool_end)
   7294 {
   7295     int local_port;
   7296     uint32 rval, pool;
   7297     static const soc_field_t prigroup_spid_field[] = {
   7298         PG0_SPIDf, PG1_SPIDf, PG2_SPIDf, PG3_SPIDf,
   7299         PG4_SPIDf, PG5_SPIDf, PG6_SPIDf, PG7_SPIDf
   7300     };
   7301     
   7302     if (pri_grp == BCM_COS_INVALID) {
   7303         *p_pool_start = 0;
   7304         *p_pool_end = 3;
   7305         return BCM_E_NONE;
   7306     }
   7307 
   7308     BCM_IF_ERROR_RETURN
   7309             (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port));
   7310 
   7311     if (!SOC_PORT_VALID(unit, local_port)) {
   7312         return BCM_E_PORT;
   7313     }
   7314 
   7315     if ((pri_grp < 0) || (pri_grp >= 8)) {
   7316         return BCM_E_PARAM;
   7317     }
   7318 
   7319     SOC_IF_ERROR_RETURN(READ_THDI_PORT_PG_SPIDr(unit, local_port, &rval));
   7320     pool = soc_reg_field_get(unit, THDI_PORT_PG_SPIDr, rval, 
   7321                                 prigroup_spid_field[pri_grp]);
   7322     
   7323     *p_pool_start = *p_pool_end = pool;
   7324     return BCM_E_NONE;
   7325 }
   7326 
   7327 STATIC int 
   7328 _bcm_td2_cosq_ingress_pg_get(int unit, bcm_gport_t gport, bcm_cos_queue_t pri, 
   7329                          int *p_pg_start, int *p_pg_end)
   7330 {
   7331     bcm_port_t local_port;
   7332     uint32  rval,pool;
   7333     soc_reg_t reg = INVALIDr;
   7334     static const soc_reg_t prigroup_reg[] = {
   7335         THDI_PORT_PRI_GRP0r, THDI_PORT_PRI_GRP1r
   7336     };
   7337     static const soc_field_t prigroup_field[] = {
   7338         PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf,
   7339         PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf,
   7340         PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf,
   7341         PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf
   7342     };
   7343 
   7344     if (pri == BCM_COS_INVALID) {
   7345         *p_pg_start = 0;
   7346         *p_pg_end = 7;
   7347         return BCM_E_NONE;
   7348     }
   7349 
   7350     BCM_IF_ERROR_RETURN
   7351             (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port));
   7352 
   7353     if (!SOC_PORT_VALID(unit, local_port)) {
   7354         return BCM_E_PORT;
   7355     }
   7356 
   7357     if (pri > 15) {
   7358         return BCM_E_PARAM;
   7359     }
   7360        /* get PG for port using Port+Cos */
   7361     if (pri < 8) {
   7362         reg = prigroup_reg[0];
   7363     } else {
   7364         reg = prigroup_reg[1];
   7365     }
   7366 
   7367     SOC_IF_ERROR_RETURN
   7368         (soc_reg32_get(unit, reg, local_port, 0, &rval));
   7369         pool = soc_reg_field_get(unit, reg, rval, prigroup_field[pri]);
   7370 
   7371     *p_pg_start = *p_pg_end = pool;
   7372     return BCM_E_NONE;
   7373 }
   7374 
   7375 
   7376 STATIC _bcm_bst_cb_ret_t
   7377 _bcm_td2_bst_index_resolve(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
   7378                     bcm_bst_stat_id_t bid, int *pipe, int *start_hw_index, 
   7379                     int *end_hw_index, int *rcb_data, void **cb_data, int *bcm_rv)
   7380 {
   7381     int phy_port, mmu_port, local_port;
   7382     _bcm_td2_cosq_node_t *node = NULL;
   7383     soc_info_t *si;
   7384     uint32 rval = 0;
   7385     int pool_idx;
   7386 
   7387     *bcm_rv = BCM_E_NONE;
   7388 
   7389 #define _BST_IF_ERROR_GOTO_EXIT(op) \
   7390     do { int __rv__; if ((__rv__ = (op)) < 0) { goto error_exit; } } while(0)
   7391 
   7392     _BST_IF_ERROR_GOTO_EXIT
   7393             (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port));
   7394 
   7395     si = &SOC_INFO(unit);
   7396     phy_port = si->port_l2p_mapping[local_port];
   7397     mmu_port = si->port_p2m_mapping[phy_port];
   7398 
   7399     *pipe = (mmu_port < 64) ? 0 : 1;
   7400 
   7401     if (bid == bcmBstStatIdDevice) {
   7402         *start_hw_index = *end_hw_index = 0;
   7403         *bcm_rv = BCM_E_NONE;
   7404         return _BCM_BST_RV_OK;
   7405     }
   7406 
   7407     if (bid == bcmBstStatIdEgrPool) {
   7408         /* Egress Unicast Pool */
   7409         if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   7410             goto error_exit;
   7411         }        
   7412         _BST_IF_ERROR_GOTO_EXIT(_bcm_td2_cosq_egress_sp_get(unit, gport, cosq, 
   7413                                     start_hw_index, end_hw_index));
   7414         return _BCM_BST_RV_OK;
   7415     } else if (bid == bcmBstStatIdEgrMCastPool) {
   7416         /* Egress Multicast Pool */
   7417         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   7418             goto error_exit;
   7419         }
   7420         _BST_IF_ERROR_GOTO_EXIT(_bcm_td2_cosq_egress_sp_get(unit, gport, cosq, 
   7421                                     start_hw_index, end_hw_index));
   7422         return _BCM_BST_RV_OK;        
   7423     } else if (bid == bcmBstStatIdIngPool) {
   7424         /* ingress pool */
   7425         _BST_IF_ERROR_GOTO_EXIT(_bcm_td2_cosq_ingress_sp_get(unit, gport, cosq, 
   7426                                     start_hw_index, end_hw_index));
   7427         return _BCM_BST_RV_OK;
   7428     } else if (bid == bcmBstStatIdRQEPool) {
   7429         /* RQE pool */
   7430         if (cosq == BCM_COS_INVALID) {
   7431             *start_hw_index = 0;
   7432             *end_hw_index = _TD2_MMU_NUM_POOL - 1;
   7433         }else if ((cosq < 0) || (cosq >= _TD2_MMU_NUM_RQE_QUEUES)) {
   7434             return BCM_E_PARAM;
   7435         } else {
   7436             SOC_IF_ERROR_RETURN
   7437                 (READ_MMU_THDR_DB_CONFIG1_PRIQr(unit, cosq, &rval));
   7438 
   7439             pool_idx = soc_reg_field_get(unit, MMU_THDR_DB_CONFIG1_PRIQr, rval,
   7440                                                SPIDf);
   7441             *start_hw_index = *end_hw_index = pool_idx;
   7442         }
   7443         return _BCM_BST_RV_OK;
   7444     } else if (bid == bcmBstStatIdRQEQueue) {
   7445         /* RQE queue */
   7446         if (cosq == BCM_COS_INVALID) {
   7447             *start_hw_index = 0;
   7448             *end_hw_index = _TD2_MMU_NUM_RQE_QUEUES - 1;
   7449         }else if ((cosq < 0) || (cosq >= _TD2_MMU_NUM_RQE_QUEUES)) {
   7450             return BCM_E_PARAM;
   7451         } else {
   7452             *start_hw_index = *end_hw_index = cosq;
   7453         }
   7454         return _BCM_BST_RV_OK;
   7455     } else if (bid == bcmBstStatIdUCQueueGroup) {
   7456         /* unicast queue group */
   7457         _BST_IF_ERROR_GOTO_EXIT(_bcm_td2_cosq_index_resolve(unit,
   7458               gport, cosq, _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE_GROUP,
   7459               NULL, start_hw_index, NULL));
   7460         *end_hw_index = *start_hw_index;
   7461         return _BCM_BST_RV_OK;
   7462     }
   7463 
   7464     if (bid == bcmBstStatIdPortPool) {
   7465         /* ingress pool */
   7466         _BST_IF_ERROR_GOTO_EXIT(
   7467                 _bcm_td2_cosq_ingress_sp_get(unit, gport, cosq, 
   7468                                     start_hw_index, end_hw_index));
   7469         *start_hw_index = ((mmu_port & 0x3f) * 4) + *start_hw_index;
   7470         *end_hw_index = ((mmu_port & 0x3f) * 4) + *end_hw_index;
   7471     } else if ((bid == bcmBstStatIdPriGroupShared) || 
   7472                (bid == bcmBstStatIdPriGroupHeadroom)) {
   7473         /* ingress pool */
   7474         _BST_IF_ERROR_GOTO_EXIT(
   7475                 _bcm_td2_cosq_ingress_pg_get(unit, gport, cosq, 
   7476                                     start_hw_index, end_hw_index));
   7477         *start_hw_index = ((mmu_port & 0x3f) * 8) + *start_hw_index;
   7478         *end_hw_index = ((mmu_port & 0x3f) * 8) + *end_hw_index;
   7479     } else if (bid == bcmBstStatIdEgrPortPoolSharedUcast ||
   7480                bid == bcmBstStatIdEgrPortPoolSharedMcast) {
   7481         /* egress pool */
   7482         _BST_IF_ERROR_GOTO_EXIT(
   7483                 _bcm_td2_cosq_egress_sp_get(unit, gport, cosq,
   7484                                             start_hw_index, end_hw_index));
   7485         *start_hw_index = ((mmu_port & 0x3f) * 4) + *start_hw_index;
   7486         *end_hw_index = ((mmu_port & 0x3f) * 4) + *end_hw_index;
   7487     } else {
   7488         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   7489             if (bid != bcmBstStatIdUcast) {
   7490                 goto error_exit;
   7491             }
   7492             _BST_IF_ERROR_GOTO_EXIT
   7493                 (_bcm_td2_cosq_node_get(unit, gport, 0, NULL, 
   7494                                         &local_port, NULL, &node));
   7495             if (!node) {
   7496                 goto error_exit;
   7497             }
   7498             *start_hw_index = *end_hw_index = node->hw_index;
   7499         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   7500             if (bid != bcmBstStatIdMcast) {
   7501                 goto error_exit;
   7502             }
   7503             _BST_IF_ERROR_GOTO_EXIT
   7504                 (_bcm_td2_cosq_node_get(unit, gport, 0, NULL, 
   7505                                         &local_port, NULL, &node));
   7506             if (!node) {
   7507                 goto error_exit;
   7508             }
   7509             *start_hw_index = *end_hw_index = node->hw_index - 1480;
   7510         } else { 
   7511             _BST_IF_ERROR_GOTO_EXIT(_bcm_td2_cosq_port_has_ets(unit, local_port));
   7512             
   7513             if (cosq < 0) {
   7514                 if (bid == bcmBstStatIdUcast) {
   7515                     _BST_IF_ERROR_GOTO_EXIT(_bcm_td2_cosq_index_resolve(unit, 
   7516                           local_port, 0, _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE, 
   7517                           NULL, start_hw_index, NULL));
   7518 
   7519                     _BST_IF_ERROR_GOTO_EXIT(_bcm_td2_cosq_index_resolve(unit, 
   7520                           local_port, NUM_COS(unit) - 1, 
   7521                           _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE, 
   7522                           NULL, end_hw_index, NULL));
   7523 
   7524                 } else {
   7525                     _BST_IF_ERROR_GOTO_EXIT(_bcm_td2_cosq_index_resolve(unit, 
   7526                           local_port, 0, _BCM_TD2_COSQ_INDEX_STYLE_MCAST_QUEUE, 
   7527                           NULL, start_hw_index, NULL));
   7528                     *start_hw_index -= 1480;
   7529 
   7530                     _BST_IF_ERROR_GOTO_EXIT(_bcm_td2_cosq_index_resolve(unit, 
   7531                           local_port, NUM_COS(unit) - 1, 
   7532                           _BCM_TD2_COSQ_INDEX_STYLE_MCAST_QUEUE, 
   7533                           NULL, end_hw_index, NULL));
   7534                     *end_hw_index -= 1480;
   7535                 }
   7536             } else {
   7537                 if (bid == bcmBstStatIdUcast) {
   7538                     _BST_IF_ERROR_GOTO_EXIT(_bcm_td2_cosq_index_resolve(unit, 
   7539                           local_port, cosq, _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE, 
   7540                           NULL, start_hw_index, NULL));
   7541                     *end_hw_index = *start_hw_index;
   7542                 } else {
   7543                     _BST_IF_ERROR_GOTO_EXIT(_bcm_td2_cosq_index_resolve(unit, 
   7544                           local_port, cosq, _BCM_TD2_COSQ_INDEX_STYLE_MCAST_QUEUE, 
   7545                           NULL, start_hw_index, NULL));
   7546                     *start_hw_index -= 1480;
   7547                     *end_hw_index = *start_hw_index;
   7548                 }
   7549             } /* if (cosq < 0) */
   7550         } /* if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { */
   7551     } /* if (bid == bcmBstStatIdPortPool) { */
   7552    
   7553     *bcm_rv = BCM_E_NONE;
   7554     return _BCM_BST_RV_OK;
   7555 
   7556 error_exit:
   7557     *bcm_rv = BCM_E_PARAM;
   7558     return _BCM_BST_RV_ERROR;
   7559 }
   7560 
   7561 STATIC int
   7562 _bcm_td2_cosq_set_scheduler_states(int unit, bcm_port_t port, int busy)
   7563 {
   7564     int lvl, lvl_offset, hw_index, rv;
   7565     _bcm_td2_mmu_info_t *mmu_info;
   7566     _bcm_td2_pipe_resources_t *res;
   7567     _bcm_td2_cosq_list_t *list;
   7568 
   7569     mmu_info = _bcm_td2_mmu_info[unit];
   7570     res = _BCM_TD2_PRESOURCES(mmu_info, _BCM_TD2_PORT_TO_PIPE(unit, port));
   7571 
   7572     for (lvl = SOC_TD2_NODE_LVL_L0; lvl <= SOC_TD2_NODE_LVL_L1; lvl++) {
   7573         lvl_offset = 0;
   7574 
   7575         list = NULL;
   7576         if (lvl == SOC_TD2_NODE_LVL_L0) {
   7577             list = &res->l0_sched_list;
   7578         } else if (lvl == SOC_TD2_NODE_LVL_L1) {
   7579             list = &res->l1_sched_list;
   7580         }
   7581 
   7582         if (!list) {
   7583             continue;
   7584         }
   7585         while ((rv = soc_td2_sched_hw_index_get(unit, port, lvl, 
   7586                                    lvl_offset, &hw_index)) == SOC_E_NONE) {
   7587         if (busy) {
   7588                 _bcm_td2_node_index_set(list, hw_index, 1);
   7589         } else {
   7590                 _bcm_td2_node_index_clear(list, hw_index, 1);
   7591         }
   7592             lvl_offset += 1;
   7593         }
   7594     }
   7595     return BCM_E_NONE;
   7596 }
   7597 
   7598 STATIC int
   7599 _bcm_td2_cosq_bst_map_resource_to_gport_cos(int unit, bcm_bst_stat_id_t bid, int port, 
   7600                          int index, bcm_gport_t *gport, bcm_cos_t *cosq)
   7601 {
   7602     soc_info_t *si;
   7603     _bcm_td2_cosq_node_t *node;
   7604     _bcm_td2_mmu_info_t *mmu_info;
   7605     _bcm_td2_pipe_resources_t   *pres;
   7606     int ii, pipe;
   7607     int phy_port, mmu_port, hw_index;
   7608     _bcm_bst_resource_info_t *resInfo;
   7609     int pipe_offset = 0;
   7610 
   7611     if (port == -2) {
   7612         pipe = _TD2_YPIPE;
   7613     } else {
   7614         pipe = _TD2_XPIPE;
   7615     }
   7616 
   7617     resInfo = _BCM_BST_RESOURCE(unit, bid);
   7618     pipe_offset = (resInfo->index_max / NUM_PIPE(unit)) * pipe;
   7619     mmu_info = _bcm_td2_mmu_info[unit];
   7620     pres = _BCM_TD2_PRESOURCES(mmu_info, pipe);
   7621     si = &SOC_INFO(unit);
   7622 
   7623     switch (bid) {
   7624     case bcmBstStatIdDevice:
   7625         *gport = -1;
   7626         *cosq = BCM_COS_INVALID;
   7627         break;
   7628 
   7629     case bcmBstStatIdIngPool:
   7630     case bcmBstStatIdEgrPool:
   7631     case bcmBstStatIdEgrMCastPool:
   7632     case bcmBstStatIdRQEPool:
   7633         *gport = -1;
   7634         *cosq = index;
   7635         break;
   7636 
   7637     case bcmBstStatIdRQEQueue:
   7638         *gport = -1;
   7639         *cosq = index % _TD2_MMU_NUM_RQE_QUEUES;
   7640         break;
   7641 
   7642     case bcmBstStatIdUCQueueGroup:
   7643         *gport = index;
   7644         *cosq =  -1;
   7645         break;
   7646 
   7647     case bcmBstStatIdPortPool:
   7648     case bcmBstStatIdEgrPortPoolSharedUcast:
   7649     case bcmBstStatIdEgrPortPoolSharedMcast:
   7650         mmu_port= (index - pipe_offset)/4;
   7651         if (pipe == _TD2_YPIPE) {
   7652             mmu_port = mmu_port + 64;
   7653         }
   7654         phy_port = si->port_m2p_mapping[mmu_port];
   7655         *gport = si->port_p2l_mapping[phy_port];
   7656         *cosq = index % 4;
   7657         break;
   7658 
   7659     case bcmBstStatIdPriGroupHeadroom:
   7660     case bcmBstStatIdPriGroupShared:
   7661         mmu_port= (index - pipe_offset)/8;
   7662         if (pipe == _TD2_YPIPE) {
   7663             mmu_port = mmu_port + 64;
   7664         }
   7665         phy_port = si->port_m2p_mapping[mmu_port];
   7666         *gport = si->port_p2l_mapping[phy_port];
   7667         *cosq = index % 8;
   7668         break;
   7669  
   7670     case bcmBstStatIdMcast:
   7671         pipe = _TD2_XPIPE;
   7672         if (index >= 568) {
   7673             pipe = _TD2_YPIPE;
   7674         }
   7675         hw_index = soc_td2_l2_hw_index(unit, index, 0);
   7676 
   7677         if (mmu_info->ets_mode) {
   7678             for (ii = 0; ii < _BCM_TD2_NUM_L2_MC_LEAVES; ii++) {
   7679                 node = &pres->p_mc_queue_node[ii];
   7680                 if (node->in_use == TRUE) {
   7681                     phy_port = si->port_l2p_mapping[node->local_port];
   7682                     mmu_port = si->port_p2m_mapping[phy_port];
   7683 
   7684                     if (((pipe == _TD2_YPIPE) && mmu_port < 64) ||
   7685                         ((pipe == _TD2_XPIPE) && mmu_port > 64)) {
   7686                         continue;
   7687                     }
   7688 
   7689                     if (node->hw_index == hw_index) {
   7690                         *gport = node->gport;
   7691                         *cosq = 0;
   7692                         break;
   7693                     }
   7694                 }
   7695             }
   7696         } else {
   7697             int port_mc_base = 0;
   7698             int port_num_mc = 0;
   7699             PBMP_ALL_ITER(unit, port) {
   7700                 phy_port = si->port_l2p_mapping[port];
   7701                 mmu_port = si->port_p2m_mapping[phy_port];
   7702 
   7703                 if (((pipe == _TD2_YPIPE) && mmu_port < 64) ||
   7704                     ((pipe == _TD2_XPIPE) && mmu_port > 64)) {
   7705                     continue;
   7706                 }
   7707                 if (IS_LB_PORT(unit, port)) {
   7708                     continue;
   7709                 }
   7710 
   7711                 port_num_mc = si->port_num_cosq[port];
   7712                 port_mc_base = si->port_cosq_base[port];
   7713 
   7714                 if ((index >= port_mc_base) &&
   7715                     (index < port_mc_base + port_num_mc)) {
   7716                     *gport = port;
   7717                     *cosq = index - port_mc_base;
   7718                     break;
   7719                 }
   7720             }
   7721         }
   7722         break;
   7723 
   7724     case bcmBstStatIdUcast:
   7725         pipe = _TD2_XPIPE;
   7726         if (index >= 1480) {
   7727             pipe = _TD2_YPIPE;
   7728         }
   7729         hw_index = soc_td2_l2_hw_index(unit, index, 1);
   7730 
   7731         if (mmu_info->ets_mode) {
   7732             for (ii = 0; ii < _BCM_TD2_NUM_L2_UC_LEAVES; ii++) {
   7733                 node = &pres->p_queue_node[ii];
   7734                 if (node->in_use == TRUE) {
   7735                     phy_port = si->port_l2p_mapping[node->local_port];
   7736                     mmu_port = si->port_p2m_mapping[phy_port];
   7737 
   7738                     if (((pipe == _TD2_YPIPE) && mmu_port < 64) ||
   7739                         ((pipe == _TD2_XPIPE) && mmu_port > 64)) {
   7740                         continue;
   7741                     }
   7742 
   7743                     if (node->hw_index == hw_index) { 
   7744                         *gport = node->gport;
   7745                         *cosq = 0;
   7746                         break;
   7747                     }
   7748                 }
   7749             }
   7750         } else {
   7751             int port_uc_base = 0;
   7752             int port_num_uc = 0;
   7753             PBMP_ALL_ITER(unit, port) {
   7754                 phy_port = si->port_l2p_mapping[port];
   7755                 mmu_port = si->port_p2m_mapping[phy_port];
   7756 
   7757                 if (((pipe == _TD2_YPIPE) && mmu_port < 64) ||
   7758                     ((pipe == _TD2_XPIPE) && mmu_port > 64)) {
   7759                     continue;
   7760                 }
   7761                 if (IS_LB_PORT(unit, port)) {
   7762                     continue;
   7763                 }
   7764 
   7765                 port_num_uc = si->port_num_uc_cosq[port];
   7766                 port_uc_base = si->port_uc_cosq_base[port];
   7767 
   7768                 if ((index >= port_uc_base) &&
   7769                     (index < port_uc_base + port_num_uc)) {
   7770                     *gport = port;
   7771                     *cosq = index - port_uc_base;
   7772                     break;
   7773                 }
   7774             }
   7775         }
   7776         break;
   7777     default:
   7778         break;
   7779     }
   7780 
   7781     return BCM_E_NONE;
   7782 }
   7783 #ifdef BCM_TRIDENT2PLUS_SUPPORT
   7784 /*
   7785  * Function:
   7786  *     _bcm_td2p_update_base_queue_num
   7787  * Purpose:
   7788  *     After flexing, update the base queue numbers in the _bcm_td2_mmu_info_t
   7789  *     structure and update the associated registers between base
   7790  *     queues and logical ports.
   7791  * Parameters:
   7792  *     unit             - (IN) unit number
   7793  *     nport            - (IN) number of entries in flexport_data
   7794  *     ports            - (IN) contains the ports for what new
   7795  *                             ports are being added via flexport
   7796  *                             and need queues updated so we only touch those.
   7797  * Returns:
   7798  *     BCM_E_XXX
   7799  */
   7800 STATIC int
   7801 _bcm_td2p_update_base_queue_num(int unit, int nport, int * ports)
   7802 {
   7803     uint64 rval64;
   7804     int qnum, pipe, i;
   7805     soc_info_t *si;
   7806     bcm_port_t port;
   7807     _bcm_td2_mmu_info_t *mmu_info;
   7808 #ifdef BCM_TRIDENT2PLUS_SUPPORT
   7809     int phy_port, mmu_port;
   7810 #endif
   7811 
   7812     si = &SOC_INFO(unit);
   7813 
   7814     COMPILER_64_ZERO(rval64);
   7815 
   7816     /* This info needs to be updated when flexport occurs.
   7817        Set this information based upon bcm_td2_cosq_init.*/
   7818     mmu_info = _bcm_td2_mmu_info[unit];
   7819     mmu_info->pipe_resources[_TD2_XPIPE].num_base_queues = 0;
   7820     mmu_info->pipe_resources[_TD2_YPIPE].num_base_queues = 0;
   7821 
   7822     /* assign queues to ports */
   7823     PBMP_ALL_ITER(unit, port) {
   7824         if (IS_CPU_PORT(unit, port) || IS_LB_PORT(unit, port)) {
   7825             continue;
   7826         }
   7827         pipe = _BCM_TD2_PORT_TO_PIPE(unit, port);
   7828         mmu_info->port_info[port].resources = &mmu_info->pipe_resources[pipe];
   7829 #ifdef BCM_TRIDENT2PLUS_SUPPORT
   7830         /* This needs to be done for Trident 2+ since queues are no longer
   7831            based upon a running number but are instead indexed by MMU Port
   7832            number.  Example: If MMU port 0 and 1 are using VBS, they'll only
   7833            use queues 0-9 and 10-19.  If MMU port 2 is LLS, it will start
   7834            at queue 24 rather than 20.  We need to add this total to
   7835            port_num_uc_cosq so that the device won't think it has overrun
   7836            its queues. */
   7837         if (SOC_IS_TD2P_TT2P(unit)) {
   7838             phy_port = si->port_l2p_mapping[port];
   7839             mmu_port = si->port_p2m_mapping[phy_port];
   7840 
   7841             /* Make sure num_base_queues accounts for not only the port's
   7842                base queue, but all the queues assigned to it as well */
   7843             if (mmu_info->port_info[port].resources->num_base_queues <
   7844                 ((mmu_port%64) + 1) * si->port_num_uc_cosq[port]) {
   7845                 mmu_info->port_info[port].resources->num_base_queues = 
   7846                     ((mmu_port%64) + 1) * si->port_num_uc_cosq[port];
   7847             }
   7848         } else 
   7849 #endif
   7850         {
   7851             mmu_info->port_info[port].resources->num_base_queues +=
   7852                                                 si->port_num_uc_cosq[port];
   7853         }
   7854         
   7855         /* iterate through the newly flexed ports and only update those. */
   7856         for (i = 0; i < nport; i++) {
   7857             if (port == ports[i]) {
   7858                 break;
   7859             }
   7860         }
   7861         if (i != nport) {
   7862             mmu_info->port_info[port].mc_base = si->port_cosq_base[port];
   7863             mmu_info->port_info[port].mc_limit = si->port_cosq_base[port] +
   7864                                                     si->port_num_cosq[port];
   7865 
   7866             mmu_info->port_info[port].uc_base = si->port_uc_cosq_base[port];
   7867             mmu_info->port_info[port].uc_limit = si->port_uc_cosq_base[port] +
   7868                                                     si->port_num_uc_cosq[port];
   7869 
   7870             if (!SOC_WARM_BOOT(unit)) {
   7871                 COMPILER_64_ZERO(rval64);
   7872                 qnum = soc_td2_logical_qnum_hw_qnum(unit, port,
   7873                                                 si->port_uc_cosq_base[port], 1);
   7874                 soc_reg64_field32_set(unit, ING_COS_MODE_64r,
   7875                                                 &rval64, BASE_QUEUE_NUM_0f, qnum);
   7876                 soc_reg64_field32_set(unit, ING_COS_MODE_64r,
   7877                                                 &rval64, BASE_QUEUE_NUM_1f, qnum);
   7878                 BCM_IF_ERROR_RETURN(soc_reg_set(unit, ING_COS_MODE_64r, port, 0, rval64));
   7879             }
   7880         }
   7881     }
   7882 
   7883     return BCM_E_NONE;
   7884 }
   7885 
   7886 /*
   7887  * Function:
   7888  *     _bcm_td2p_set_flexport_port_q_cb
   7889  * Purpose:
   7890  *     Set the callback for updating the logical port to queue association.
   7891  * Parameters:
   7892  *     unit - unit number
   7893  * Returns:
   7894  *     BCM_E_XXX
   7895  */
   7896 
   7897 STATIC int
   7898 _bcm_td2p_set_flexport_port_q_cb(int unit)
   7899 {
   7900     BCM_IF_ERROR_RETURN(
   7901        soc_td2p_set_flexport_port_q_callback(unit, 
   7902                                              _bcm_td2p_update_base_queue_num));
   7903     return BCM_E_NONE;
   7904 }
   7905 
   7906 /*
   7907  * Function:
   7908  *     _bcm_td2p_set_ets_mode_q_cb
   7909  * Purpose:
   7910  *     Set the callback for checking ets mode
   7911  * Parameters:
   7912  *     unit - unit number
   7913  * Returns:
   7914  *     BCM_E_XXX
   7915  */
   7916 
   7917 STATIC int
   7918 _bcm_td2p_set_ets_mode_q_cb(int unit)
   7919 {
   7920     BCM_IF_ERROR_RETURN(
   7921        soc_td2p_set_ets_mode_q_callback(unit, 
   7922                                              _bcm_td2_cosq_port_has_ets));
   7923     return BCM_E_NONE;
   7924 }
   7925 #endif
   7926 
   7927 /*
   7928  * Function:
   7929  *     bcm_td2_cosq_init
   7930  * Purpose:
   7931  *     Initialize (clear) all COS schedule/mapping state.
   7932  * Parameters:
   7933  *     unit - unit number
   7934  * Returns:
   7935  *     BCM_E_XXX
   7936  */
   7937 int
   7938 bcm_td2_cosq_init(int unit)
   7939 {
   7940     int numq, alloc_size, phy_port, mmu_port, ii, index;
   7941     soc_info_t *si;
   7942     bcm_port_t port;
   7943     soc_reg_t mem;
   7944     soc_reg_t reg;
   7945     static soc_mem_t wred_mems[2][6] = {
   7946         {
   7947         MMU_WRED_DROP_CURVE_PROFILE_0_X_PIPEm, 
   7948         MMU_WRED_DROP_CURVE_PROFILE_1_X_PIPEm,
   7949         MMU_WRED_DROP_CURVE_PROFILE_2_X_PIPEm, 
   7950         MMU_WRED_DROP_CURVE_PROFILE_3_X_PIPEm,
   7951         MMU_WRED_DROP_CURVE_PROFILE_4_X_PIPEm, 
   7952         MMU_WRED_DROP_CURVE_PROFILE_5_X_PIPEm
   7953         },
   7954         {
   7955         MMU_WRED_DROP_CURVE_PROFILE_0_Y_PIPEm, 
   7956         MMU_WRED_DROP_CURVE_PROFILE_1_Y_PIPEm,
   7957         MMU_WRED_DROP_CURVE_PROFILE_2_Y_PIPEm, 
   7958         MMU_WRED_DROP_CURVE_PROFILE_3_Y_PIPEm,
   7959         MMU_WRED_DROP_CURVE_PROFILE_4_Y_PIPEm, 
   7960         MMU_WRED_DROP_CURVE_PROFILE_5_Y_PIPEm
   7961         }
   7962     };
   7963 
   7964     int entry_words[6], pipe;
   7965     mmu_wred_drop_curve_profile_0_entry_t entry_tcp_green;
   7966     mmu_wred_drop_curve_profile_1_entry_t entry_tcp_yellow;
   7967     mmu_wred_drop_curve_profile_2_entry_t entry_tcp_red;
   7968     mmu_wred_drop_curve_profile_3_entry_t entry_nontcp_green;
   7969     mmu_wred_drop_curve_profile_4_entry_t entry_nontcp_yellow;
   7970     mmu_wred_drop_curve_profile_5_entry_t entry_nontcp_red;
   7971     void *entries[6];
   7972     uint32 profile_index;
   7973     _bcm_td2_mmu_info_t *mmu_info;
   7974     int i, qnum, wred_prof_count, endpoint_num;
   7975     _bcm_bst_device_handlers_t bst_callbks;
   7976     _bcm_td2_pipe_resources_t   *pres;
   7977     uint64 rval64;
   7978     _bcm_td2_cosq_list_t *list = NULL;
   7979 
   7980     if (!SOC_WARM_BOOT(unit)) {    /* Cold Boot */
   7981         BCM_IF_ERROR_RETURN (bcm_td2_cosq_detach(unit, 0));
   7982     }
   7983 
   7984     si = &SOC_INFO(unit);
   7985 
   7986     numq = soc_property_get(unit, spn_BCM_NUM_COS, BCM_COS_DEFAULT);
   7987 
   7988     if (numq < 1) {
   7989         numq = 1;
   7990     } else if (numq > 8) {
   7991         numq = 8;
   7992     }
   7993 
   7994     NUM_COS(unit) = numq;
   7995     soc_trident2_fc_map_shadow_create(unit);
   7996 
   7997 
   7998     /* Create profile for PORT_COS_MAP table */
   7999     if (_bcm_td2_cos_map_profile[unit] == NULL) {
   8000         _bcm_td2_cos_map_profile[unit] = sal_alloc(sizeof(soc_profile_mem_t),
   8001                                                   "COS_MAP Profile Mem");
   8002         if (_bcm_td2_cos_map_profile[unit] == NULL) {
   8003             return BCM_E_MEMORY;
   8004         }
   8005         soc_profile_mem_t_init(_bcm_td2_cos_map_profile[unit]);
   8006     }
   8007     mem = PORT_COS_MAPm;
   8008     entry_words[0] = sizeof(port_cos_map_entry_t) / sizeof(uint32);
   8009     BCM_IF_ERROR_RETURN(soc_profile_mem_create(unit, &mem, entry_words, 1,
   8010                                                _bcm_td2_cos_map_profile[unit]));
   8011 
   8012     /* Create profile for IFP_COS_MAP table. */
   8013     if (_bcm_td2_ifp_cos_map_profile[unit] == NULL) {
   8014         _bcm_td2_ifp_cos_map_profile[unit]
   8015             = sal_alloc(sizeof(soc_profile_mem_t), "IFP_COS_MAP Profile Mem");
   8016         if (_bcm_td2_ifp_cos_map_profile[unit] == NULL) {
   8017             return BCM_E_MEMORY;
   8018         }
   8019         soc_profile_mem_t_init(_bcm_td2_ifp_cos_map_profile[unit]);
   8020     }
   8021     mem = IFP_COS_MAPm;
   8022     entry_words[0] = sizeof(ifp_cos_map_entry_t) / sizeof(uint32);
   8023     SOC_IF_ERROR_RETURN
   8024         (soc_profile_mem_create(unit, &mem, entry_words, 1,
   8025                                 _bcm_td2_ifp_cos_map_profile[unit]));
   8026 
   8027     /* Create profile for SERVICE_COS_MAP table */
   8028     if (_bcm_td2_service_cos_map_profile[unit] == NULL) {
   8029         alloc_size = sizeof(soc_profile_mem_t);
   8030         _bcm_td2_service_cos_map_profile[unit] = sal_alloc(alloc_size,
   8031                                                            "SERVICE_COS_MAP");
   8032         if (_bcm_td2_service_cos_map_profile[unit] == NULL) {
   8033             return BCM_E_MEMORY;
   8034         }
   8035         soc_profile_mem_t_init(_bcm_td2_service_cos_map_profile[unit]);
   8036     }
   8037     mem = SERVICE_COS_MAPm;
   8038     entry_words[0] = sizeof(service_cos_map_entry_t) / sizeof(uint32);
   8039     SOC_IF_ERROR_RETURN(
   8040         soc_profile_mem_create(unit, &mem, entry_words, 1,
   8041                                _bcm_td2_service_cos_map_profile[unit]));
   8042 
   8043     /* Create profile for SERVICE_PORT_MAP table */
   8044     if (_bcm_td2_service_port_map_profile[unit] == NULL) {
   8045         alloc_size = sizeof(soc_profile_mem_t);
   8046         _bcm_td2_service_port_map_profile[unit] = sal_alloc(alloc_size,
   8047                                                             "SERVICE_PORT_MAP");
   8048         if (_bcm_td2_service_port_map_profile[unit] == NULL) {
   8049             return BCM_E_MEMORY;
   8050         }
   8051         soc_profile_mem_t_init(_bcm_td2_service_port_map_profile[unit]);
   8052     }
   8053 
   8054     mem = SERVICE_PORT_MAPm;
   8055     entry_words[0] = sizeof(service_port_map_entry_t) / sizeof(uint32);
   8056     SOC_IF_ERROR_RETURN(
   8057         soc_profile_mem_create(unit, &mem, entry_words, 1,
   8058                                _bcm_td2_service_port_map_profile[unit]));
   8059 
   8060     /* Create profile for MMU_QCN_SITB table */
   8061     if (_bcm_td2_sample_int_profile[unit] == NULL) {
   8062         _bcm_td2_sample_int_profile[unit] =
   8063             sal_alloc(sizeof(soc_profile_mem_t), "QCN sample Int Profile Mem");
   8064         if (_bcm_td2_sample_int_profile[unit] == NULL) {
   8065             return BCM_E_MEMORY;
   8066         }
   8067         soc_profile_mem_t_init(_bcm_td2_sample_int_profile[unit]);
   8068     }
   8069     mem = MMU_QCN_SITBm;
   8070     entry_words[0] = sizeof(mmu_qcn_sitb_entry_t) / sizeof(uint32);
   8071     BCM_IF_ERROR_RETURN
   8072         (soc_profile_mem_create(unit, &mem, entry_words, 1,
   8073                                 _bcm_td2_sample_int_profile[unit]));
   8074 
   8075     /* Create profile for MMU_QCN_CPQ_SEQ register */
   8076     if (_bcm_td2_feedback_profile[unit] == NULL) {
   8077         _bcm_td2_feedback_profile[unit] =
   8078             sal_alloc(sizeof(soc_profile_reg_t), "QCN Feedback Profile Reg");
   8079         if (_bcm_td2_feedback_profile[unit] == NULL) {
   8080             return BCM_E_MEMORY;
   8081         }
   8082         soc_profile_reg_t_init(_bcm_td2_feedback_profile[unit]);
   8083     }
   8084     reg = MMU_QCN_CPQ_SEQr;
   8085     BCM_IF_ERROR_RETURN
   8086         (soc_profile_reg_create(unit, &reg, 1,
   8087                                 _bcm_td2_feedback_profile[unit]));
   8088 
   8089     /* Create profile for PRIO2COS_LLFC register */
   8090     if (_bcm_td2_llfc_profile[unit] == NULL) {
   8091         _bcm_td2_llfc_profile[unit] =
   8092             sal_alloc(sizeof(soc_profile_reg_t), "PRIO2COS_LLFC Profile Reg");
   8093         if (_bcm_td2_llfc_profile[unit] == NULL) {
   8094             return BCM_E_MEMORY;
   8095         }
   8096         soc_profile_reg_t_init(_bcm_td2_llfc_profile[unit]);
   8097     }
   8098     reg = PRIO2COS_PROFILEr;
   8099     BCM_IF_ERROR_RETURN
   8100         (soc_profile_reg_create(unit, &reg, 1, _bcm_td2_llfc_profile[unit]));
   8101 
   8102     /* Create profile for VOQ_MOD_MAP table */
   8103     if (_bcm_td2_voq_port_map_profile[unit] == NULL) {
   8104         _bcm_td2_voq_port_map_profile[unit] = sal_alloc(sizeof(soc_profile_mem_t),
   8105                                                   "VOQ_PORT_MAP Profile Mem");
   8106         if (_bcm_td2_voq_port_map_profile[unit] == NULL) {
   8107             return BCM_E_MEMORY;
   8108         }
   8109         soc_profile_mem_t_init(_bcm_td2_voq_port_map_profile[unit]);
   8110     }
   8111     mem = VOQ_PORT_MAPm;
   8112     entry_words[0] = sizeof(voq_port_map_entry_t) / sizeof(uint32);
   8113     BCM_IF_ERROR_RETURN(soc_profile_mem_create(unit, &mem, entry_words, 1,
   8114                                            _bcm_td2_voq_port_map_profile[unit]));
   8115 
   8116     for (pipe = _TD2_XPIPE; pipe <= _TD2_YPIPE; pipe++) {
   8117         /* Create profile for MMU_WRED_DROP_CURVE_PROFILE_x tables */
   8118         if (_bcm_td2_wred_profile[pipe][unit] == NULL) {
   8119             _bcm_td2_wred_profile[pipe][unit] =
   8120                     sal_alloc(sizeof(soc_profile_mem_t), "WRED Profile Mem");
   8121             if (_bcm_td2_wred_profile[pipe][unit] == NULL) {
   8122                 return BCM_E_MEMORY;
   8123             }
   8124             soc_profile_mem_t_init(_bcm_td2_wred_profile[pipe][unit]);
   8125         }
   8126 
   8127         entry_words[0] =
   8128             sizeof(mmu_wred_drop_curve_profile_0_entry_t) / sizeof(uint32);
   8129         entry_words[1] =
   8130             sizeof(mmu_wred_drop_curve_profile_1_entry_t) / sizeof(uint32);
   8131         entry_words[2] =
   8132             sizeof(mmu_wred_drop_curve_profile_2_entry_t) / sizeof(uint32);
   8133         entry_words[3] =
   8134             sizeof(mmu_wred_drop_curve_profile_3_entry_t) / sizeof(uint32);
   8135         entry_words[4] =
   8136             sizeof(mmu_wred_drop_curve_profile_4_entry_t) / sizeof(uint32);
   8137         entry_words[5] =
   8138             sizeof(mmu_wred_drop_curve_profile_5_entry_t) / sizeof(uint32);
   8139         BCM_IF_ERROR_RETURN
   8140             (soc_profile_mem_create(unit, wred_mems[pipe], entry_words, 6,
   8141                                     _bcm_td2_wred_profile[pipe][unit]));
   8142     }
   8143 
   8144     alloc_size = sizeof(_bcm_td2_mmu_info_t) * 1;
   8145     if (_bcm_td2_mmu_info[unit] == NULL) {
   8146         _bcm_td2_mmu_info[unit] =
   8147             sal_alloc(alloc_size, "_bcm_td2_mmu_info");
   8148 
   8149         if (_bcm_td2_mmu_info[unit] == NULL) {
   8150             return BCM_E_MEMORY;
   8151         }
   8152 
   8153         sal_memset(_bcm_td2_mmu_info[unit], 0, alloc_size);
   8154     }
   8155 
   8156     mmu_info = _bcm_td2_mmu_info[unit];
   8157     mmu_info->ets_mode = 0;
   8158     mmu_info->pipe_resources[_TD2_XPIPE].num_base_queues = 0;
   8159     mmu_info->pipe_resources[_TD2_YPIPE].num_base_queues = 0;
   8160 
   8161     /* assign queues to ports */
   8162     PBMP_ALL_ITER(unit, port) {
   8163     pipe = _BCM_TD2_PORT_TO_PIPE(unit, port);
   8164         mmu_info->port_info[port].resources = &mmu_info->pipe_resources[pipe];
   8165         mmu_info->port_info[port].mc_base = si->port_cosq_base[port];
   8166         mmu_info->port_info[port].mc_limit = si->port_cosq_base[port] + 
   8167                                                 si->port_num_cosq[port];
   8168 
   8169         mmu_info->port_info[port].uc_base = si->port_uc_cosq_base[port];
   8170         mmu_info->port_info[port].uc_limit = si->port_uc_cosq_base[port] + 
   8171                                                 si->port_num_uc_cosq[port];
   8172 #ifdef BCM_TRIDENT2PLUS_SUPPORT
   8173         /* This needs to be done for Trident 2+ since queues are no longer
   8174            based upon a running number but are instead indexed by MMU Port
   8175            number.  Example: If MMU port 0 and 1 are using VBS, they'll only
   8176            use queues 0-9 and 10-19.  If MMU port 2 is LLS, it will start
   8177            at queue 24 rather than 20.  We need to add this total to
   8178            port_num_uc_cosq so that the device won't think it has overrun
   8179            its queues. */
   8180         if (SOC_IS_TD2P_TT2P(unit)) {
   8181            phy_port = si->port_l2p_mapping[port];
   8182            mmu_port = si->port_p2m_mapping[phy_port];
   8183 
   8184            if (mmu_info->port_info[port].resources->num_base_queues < 
   8185                (mmu_port%64) * si->port_num_uc_cosq[port]) {
   8186               mmu_info->port_info[port].resources->num_base_queues = 
   8187                  (mmu_port%64) * si->port_num_uc_cosq[port];
   8188            }
   8189 
   8190            mmu_info->port_info[port].resources->num_base_queues +=
   8191                                                   si->port_num_uc_cosq[port];
   8192         } else 
   8193 #endif
   8194         {
   8195             mmu_info->port_info[port].resources->num_base_queues +=
   8196                                                 si->port_num_uc_cosq[port];
   8197         }
   8198         if (!SOC_WARM_BOOT(unit)) {
   8199             COMPILER_64_ZERO(rval64);
   8200             qnum = soc_td2_logical_qnum_hw_qnum(unit, port, 
   8201                                             si->port_uc_cosq_base[port], 1);
   8202             soc_reg64_field32_set(unit, ING_COS_MODE_64r, 
   8203                                             &rval64, BASE_QUEUE_NUM_0f, qnum);
   8204             soc_reg64_field32_set(unit, ING_COS_MODE_64r, 
   8205                                             &rval64, BASE_QUEUE_NUM_1f, qnum);
   8206             BCM_IF_ERROR_RETURN(soc_reg_set(unit, ING_COS_MODE_64r, port, 0, rval64));
   8207         }
   8208     }
   8209 #ifdef BCM_TRIDENT2PLUS_SUPPORT
   8210     if (SOC_IS_TD2P_TT2P(unit)) {
   8211         BCM_IF_ERROR_RETURN(_bcm_td2p_set_flexport_port_q_cb(unit));
   8212         BCM_IF_ERROR_RETURN(_bcm_td2p_set_ets_mode_q_cb(unit));
   8213     }
   8214 #endif
   8215 
   8216     for (i = 0; i < si->num_cpu_cosq; i++) {
   8217         if (_bcm_td2_cosq_cpu_cosq_config[unit][i] == NULL) {
   8218             _bcm_td2_cosq_cpu_cosq_config[unit][i] =
   8219                 sal_alloc(sizeof(_bcm_td2_cosq_cpu_cosq_config_t), "CPU Cosq Config");
   8220 
   8221             if (_bcm_td2_cosq_cpu_cosq_config[unit][i] == NULL) {
   8222                 return BCM_E_MEMORY;
   8223             }
   8224             sal_memset(_bcm_td2_cosq_cpu_cosq_config[unit][i], 0,
   8225                        sizeof(_bcm_td2_cosq_cpu_cosq_config_t));
   8226             _bcm_td2_cosq_cpu_cosq_config[unit][i]->enable = 1;
   8227         }
   8228     }
   8229 
   8230     if (soc_feature(unit, soc_feature_endpoint_queuing)) {
   8231         if (_bcm_td2_endpoint_queuing_info[unit] == NULL) {
   8232             _bcm_td2_endpoint_queuing_info[unit] =
   8233                 sal_alloc(sizeof(_bcm_td2_endpoint_queuing_info_t),
   8234                         "Endpoint Queuing Info");
   8235             if (_bcm_td2_endpoint_queuing_info[unit] == NULL) {
   8236                 return BCM_E_MEMORY;
   8237             }
   8238         }
   8239         sal_memset(_bcm_td2_endpoint_queuing_info[unit], 0,
   8240                 sizeof(_bcm_td2_endpoint_queuing_info_t));
   8241 
   8242         /* The maximum number of endpoints is limited to 2^14,
   8243          * since the endpoint ID field is limited to 14 bits in
   8244          * Higig2 header.
   8245          */
   8246         endpoint_num = (1U << 14);
   8247         _bcm_td2_endpoint_queuing_info[unit]->ptr_array = sal_alloc(
   8248                 endpoint_num * sizeof(_bcm_td2_endpoint_t *),
   8249                 "Endpoint Pointer Array");
   8250         if (_bcm_td2_endpoint_queuing_info[unit]->ptr_array == NULL) {
   8251             return BCM_E_MEMORY;
   8252         }
   8253         sal_memset(_bcm_td2_endpoint_queuing_info[unit]->ptr_array, 0,
   8254                 endpoint_num * sizeof(_bcm_td2_endpoint_t *));
   8255         _BCM_TD2_NUM_ENDPOINT(unit) = endpoint_num;
   8256         /* Reserve endpoint 0 */
   8257         _bcm_td2_endpoint_queuing_info[unit]->ptr_array[0] =
   8258             sal_alloc(sizeof(_bcm_td2_endpoint_t), "Endpoint Info");
   8259         if (_bcm_td2_endpoint_queuing_info[unit]->ptr_array[0] == NULL) {
   8260             return BCM_E_MEMORY;
   8261         }
   8262 
   8263         sal_memset(_bcm_td2_endpoint_queuing_info[unit]->ptr_array[0], 0,
   8264                    sizeof(_bcm_td2_endpoint_t));
   8265 
   8266         _bcm_td2_endpoint_queuing_info[unit]->cos_map_profile = sal_alloc(
   8267                 sizeof(soc_profile_mem_t), "Priority to CoS Map Profile");
   8268         if (_bcm_td2_endpoint_queuing_info[unit]->cos_map_profile == NULL) {
   8269             return BCM_E_MEMORY;
   8270         }
   8271         soc_profile_mem_t_init
   8272             (_bcm_td2_endpoint_queuing_info[unit]->cos_map_profile);
   8273         mem = ENDPOINT_COS_MAPm;
   8274         entry_words[0] = sizeof(endpoint_cos_map_entry_t) / sizeof(uint32);
   8275         SOC_IF_ERROR_RETURN(soc_profile_mem_create(unit, &mem, entry_words, 1,
   8276                     _bcm_td2_endpoint_queuing_info[unit]->cos_map_profile));
   8277     }
   8278 
   8279     for (pipe = _TD2_XPIPE; pipe <= _TD2_YPIPE; pipe++) {
   8280         pres = _BCM_TD2_PRESOURCES(mmu_info, pipe);
   8281         pres->p_queue_node = &mmu_info->queue_node[0];
   8282         pres->p_mc_queue_node = &mmu_info->mc_queue_node[0];
   8283         pres->ext_qlist.count = _BCM_TD2_NUM_L2_UC_LEAVES_PER_PIPE;
   8284         pres->ext_qlist.bits = _bcm_td2_cosq_alloc_clear(
   8285                 pres->ext_qlist.bits,
   8286                 SHR_BITALLOCSIZE(pres->ext_qlist.count), 
   8287                                     "ext_qlist");
   8288         if (pres->ext_qlist.bits == NULL) {
   8289             _bcm_td2_cosq_free_memory(mmu_info);
   8290             return BCM_E_MEMORY;
   8291         }
   8292 
   8293         pres->l0_sched_list.count =
   8294             soc_mem_index_count(unit, ES_PIPE0_LLS_L0_PARENTm);
   8295         pres->l0_sched_list.bits = _bcm_td2_cosq_alloc_clear(
   8296                 pres->l0_sched_list.bits,
   8297                 SHR_BITALLOCSIZE(pres->l0_sched_list.count),
   8298                                     "l0_sched_list");
   8299         if (pres->l0_sched_list.bits == NULL) {
   8300             _bcm_td2_cosq_free_memory(mmu_info);
   8301             return BCM_E_MEMORY;
   8302         }
   8303 
   8304         pres->l1_sched_list.count =
   8305             soc_mem_index_count(unit, ES_PIPE0_LLS_L1_PARENTm);
   8306         pres->l1_sched_list.bits = _bcm_td2_cosq_alloc_clear(
   8307                 pres->l1_sched_list.bits,
   8308                 SHR_BITALLOCSIZE(pres->l1_sched_list.count),
   8309                                     "l1_sched_list");
   8310         if (pres->l1_sched_list.bits == NULL) {
   8311             _bcm_td2_cosq_free_memory(mmu_info);
   8312             return BCM_E_MEMORY;
   8313         }
   8314     }
   8315 
   8316     for (i = 0; i < _BCM_TD2_NUM_TOTAL_SCHEDULERS; i++) {
   8317         _BCM_TD2_COSQ_LIST_NODE_INIT(mmu_info->sched_node, i);
   8318     }
   8319 
   8320     for (i = 0; i < _BCM_TD2_NUM_L2_UC_LEAVES; i++) {
   8321         _BCM_TD2_COSQ_LIST_NODE_INIT(mmu_info->queue_node, i);
   8322     }
   8323 
   8324     for (i = 0; i < _BCM_TD2_NUM_L2_MC_LEAVES; i++) {
   8325         _BCM_TD2_COSQ_LIST_NODE_INIT(mmu_info->mc_queue_node, i);
   8326     }
   8327 
   8328     for (pipe = _TD2_XPIPE; pipe <= _TD2_YPIPE; pipe++) {
   8329         pres = _BCM_TD2_PRESOURCES(mmu_info, pipe);
   8330         for (i = SOC_TD2_NODE_LVL_L1; i <= SOC_TD2_NODE_LVL_L2; i++) {
   8331             index = _soc_td2_invalid_parent_index(unit, i);
   8332             if (i == SOC_TD2_NODE_LVL_L1) {
   8333                 list = &pres->l0_sched_list;
   8334             } else if (i == SOC_TD2_NODE_LVL_L2) {
   8335                 list = &pres->l1_sched_list;
   8336             } else {
   8337                 continue;
   8338             }
   8339             if (index >= 0) {
   8340                 _bcm_td2_node_index_set(list, index, 1);
   8341             }
   8342         }
   8343     }
   8344 
   8345     /* reserve the resources for HSP ports */
   8346     PBMP_ALL_ITER(unit, port) {
   8347         if (IS_TD2_HSP_PORT(unit, port)) {
   8348             phy_port = si->port_l2p_mapping[port];
   8349             mmu_port = si->port_p2m_mapping[phy_port];
   8350 
   8351             pres = _BCM_TD2_PRESOURCES(mmu_info, (mmu_port >= 64) ? 1 : 0);
   8352             _bcm_td2_node_index_set(&pres->l0_sched_list, (mmu_port & 0x3f)*5, 5);
   8353             _bcm_td2_node_index_set(&pres->l1_sched_list, (mmu_port & 0x3f)*10, 10);
   8354         }
   8355     }
   8356 
   8357     sal_memset(&bst_callbks, 0, sizeof(_bcm_bst_device_handlers_t));
   8358     bst_callbks.resolve_index = &_bcm_td2_bst_index_resolve;
   8359     bst_callbks.reverse_resolve_index = &_bcm_td2_cosq_bst_map_resource_to_gport_cos;
   8360     BCM_IF_ERROR_RETURN(_bcm_bst_attach(unit, &bst_callbks));
   8361 
   8362 #ifdef BCM_WARM_BOOT_SUPPORT
   8363     if (SOC_WARM_BOOT(unit)) {
   8364         return bcm_td2_cosq_reinit(unit);
   8365     } else {
   8366         BCM_IF_ERROR_RETURN(_bcm_td2_cosq_wb_alloc(unit));
   8367     }
   8368 #endif /* BCM_WARM_BOOT_SUPPORT */
   8369 
   8370     /* Add default entries for PORT_COS_MAP memory profile */
   8371     BCM_IF_ERROR_RETURN(bcm_td2_cosq_config_set(unit, numq));
   8372 
   8373     for (pipe = _TD2_XPIPE; pipe <= _TD2_YPIPE; pipe++) {
   8374         /* Add default entries for MMU_WRED_DROP_CURVE_PROFILE_x memory profile */
   8375         sal_memset(&entry_tcp_green, 0, sizeof(entry_tcp_green));
   8376         sal_memset(&entry_tcp_yellow,0, sizeof(entry_tcp_yellow));
   8377         sal_memset(&entry_tcp_red, 0, sizeof(entry_tcp_red));
   8378         sal_memset(&entry_nontcp_green, 0, sizeof(entry_nontcp_green));
   8379         sal_memset(&entry_nontcp_yellow, 0, sizeof(entry_nontcp_yellow));
   8380         sal_memset(&entry_nontcp_red, 0, sizeof(entry_nontcp_red));
   8381         entries[0] = &entry_tcp_green;
   8382         entries[1] = &entry_tcp_yellow;
   8383         entries[2] = &entry_tcp_red;
   8384         entries[3] = &entry_nontcp_green;
   8385         entries[4] = &entry_nontcp_yellow;
   8386         entries[5] = &entry_nontcp_red;
   8387         for (ii = 0; ii < 6; ii++) {
   8388             soc_mem_field32_set(unit, wred_mems[pipe][ii], entries[ii], 
   8389                                 MIN_THDf, 0x1ffff);
   8390             soc_mem_field32_set(unit, wred_mems[pipe][ii], entries[ii], 
   8391                                 MAX_THDf, 0x1ffff);
   8392         }
   8393         profile_index = 0xffffffff;
   8394     wred_prof_count = soc_mem_index_count(unit, MMU_WRED_CONFIG_X_PIPEm);
   8395     while(wred_prof_count) {
   8396             if (profile_index == 0xffffffff) {
   8397                 BCM_IF_ERROR_RETURN
   8398                     (soc_profile_mem_add(unit, 
   8399                                     _bcm_td2_wred_profile[pipe][unit],
   8400                                     entries, 1, &profile_index));
   8401             } else {
   8402                 BCM_IF_ERROR_RETURN
   8403                     (soc_profile_mem_reference(unit,
   8404                                    _bcm_td2_wred_profile[pipe][unit],
   8405                                    profile_index, 0));
   8406             }
   8407         wred_prof_count -= 1;
   8408         }
   8409     }
   8410 
   8411     /* Add default entries for PRIO2COS_PROFILE register profile */
   8412     PBMP_PORT_ITER(unit, port) {
   8413         BCM_IF_ERROR_RETURN
   8414             (bcm_td2_cosq_default_llfc_profile_attach(unit, port));
   8415     }
   8416 
   8417     if (!mmu_info->curr_shared_limit) {
   8418         BCM_IF_ERROR_RETURN(soc_td2_mmu_get_shared_size(unit,
   8419                                             &mmu_info->curr_shared_limit));
   8420     }
   8421     /* Starting the curr_merger_index from 2,
   8422      *  since 0 is configured in all the FC_MAP_TBL2 by default,
   8423      *  so it might effect the traffic of other queues
   8424      */
   8425     mmu_info->curr_merger_index = 2;
   8426     /* Reset shapers. */
   8427     BCM_IF_ERROR_RETURN(_bcm_td2_lls_shapers_init(unit));
   8428 
   8429     /* reset time_domain ref_count so that entries can be added upon
   8430      * rc */
   8431     time_domain[0].ref_count = 3640;
   8432     time_domain[1].ref_count = 0;
   8433     time_domain[2].ref_count = 0;
   8434     time_domain[3].ref_count = 0;
   8435 
   8436     return BCM_E_NONE;
   8437 }
   8438 
   8439 
   8440 /*
   8441  * Function:
   8442  *     bcm_td2_cosq_config_get
   8443  * Purpose:
   8444  *     Get the number of cos queues
   8445  * Parameters:
   8446  *     unit - unit number
   8447  *     numq - (Output) number of cosq
   8448  * Returns:
   8449  *     BCM_E_XXX
   8450  */
   8451 int
   8452 bcm_td2_cosq_config_get(int unit, int *numq)
   8453 {
   8454     if (numq != NULL) {
   8455         *numq = _TD2_NUM_COS(unit);
   8456     }
   8457 
   8458     return BCM_E_NONE;
   8459 }
   8460 
   8461 /*
   8462  * Function:
   8463  *     _bcm_td2_cosq_mapping_set
   8464  * Purpose:
   8465  *     Set COS queue for the specified priority of an ingress port
   8466  * Parameters:
   8467  *     unit     - (IN) unit number
   8468  *     ing_port - (IN) ingress port
   8469  *     gport    - (IN) queue group GPORT identifier
   8470  *     priority - (IN) priority value to map
   8471  *     flags    - (IN) BCM_COSQ_GPORT_XXX_QUEUE_GROUP
   8472  *     gport    - (IN) queue group GPORT identifier
   8473  *     cosq     - (IN) COS queue number
   8474  * Returns:
   8475  *     BCM_E_XXX
   8476  */
   8477 STATIC int
   8478 _bcm_td2_cosq_mapping_set(int unit, bcm_port_t ing_port, bcm_cos_t priority,
   8479                          uint32 flags, bcm_gport_t gport, bcm_cos_queue_t cosq)
   8480 {
   8481     bcm_port_t local_port, outport = -1;
   8482     bcm_cos_queue_t hw_cosq;
   8483     soc_field_t field = INVALIDf, field2 = INVALIDf, field3 = INVALIDf;
   8484     cos_map_sel_entry_t cos_map_sel_entry;
   8485     port_cos_map_entry_t cos_map_entries[16];
   8486     void *entries[1];
   8487     uint32 old_index, new_index;
   8488     voq_cos_map_entry_t voq_cos_map;
   8489     _bcm_td2_cosq_node_t *node;
   8490     _bcm_td2_mmu_info_t *mmu_info;
   8491     _bcm_td2_pipe_resources_t *res = NULL;
   8492     int rv, pipe = -1;
   8493     int valid = 0;
   8494 
   8495     if (priority < 0 || priority >= 16) {
   8496         return BCM_E_PARAM;
   8497     }
   8498 
   8499     BCM_IF_ERROR_RETURN
   8500         (_bcm_td2_cosq_localport_resolve(unit, ing_port, &local_port));
   8501 
   8502     if (gport != -1) {
   8503         BCM_IF_ERROR_RETURN(_bcm_td2_cosq_localport_resolve(unit, gport, &outport));
   8504         mmu_info = _bcm_td2_mmu_info[unit];
   8505         pipe = _BCM_TD2_PORT_TO_PIPE(unit, outport);
   8506         res = _BCM_TD2_PRESOURCES(mmu_info, pipe);
   8507     }
   8508 
   8509     switch (flags) {
   8510     case BCM_COSQ_GPORT_UCAST_QUEUE_GROUP:
   8511         if (gport == -1) {
   8512             hw_cosq = cosq;
   8513         } else {
   8514             if (!BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   8515                 return BCM_E_PARAM;
   8516             }
   8517             BCM_IF_ERROR_RETURN
   8518                 (_bcm_td2_cosq_index_resolve
   8519                  (unit, gport, cosq, _BCM_TD2_COSQ_INDEX_STYLE_COS,
   8520                   NULL, &hw_cosq, NULL));
   8521 
   8522             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   8523                 BCM_IF_ERROR_RETURN(_bcm_td2_cosq_node_get(unit, gport, cosq, NULL, 
   8524                                         NULL, NULL, &node));
   8525                 if (node->hw_index >= (res->num_base_queues + 
   8526                                    (pipe * _BCM_TD2_NUM_L2_UC_LEAVES_PER_PIPE))) {
   8527                     return BCM_E_PARAM;
   8528                 }
   8529             }
   8530         }
   8531         if ((outport != -1) && (IS_HG_PORT(unit, outport))) {
   8532             field = HG_COSf;
   8533         } else {
   8534             field = UC_COS1f;
   8535         }
   8536         break;
   8537     case BCM_COSQ_GPORT_MCAST_QUEUE_GROUP:
   8538         if (gport == -1) {
   8539             hw_cosq = cosq;
   8540         } else {
   8541             if (!BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   8542                 return BCM_E_PARAM;
   8543             }
   8544             BCM_IF_ERROR_RETURN
   8545                 (_bcm_td2_cosq_index_resolve
   8546                  (unit, gport, cosq, _BCM_TD2_COSQ_INDEX_STYLE_COS,
   8547                   NULL, &hw_cosq, NULL));
   8548         }
   8549         field = MC_COS1f;
   8550         field2 = RQE_Q_NUMf;
   8551         break;
   8552     case BCM_COSQ_GPORT_UCAST_QUEUE_GROUP | BCM_COSQ_GPORT_MCAST_QUEUE_GROUP:
   8553         if (gport == -1) {
   8554             hw_cosq = cosq;
   8555         } else {
   8556             return BCM_E_PARAM;
   8557         }
   8558         field = UC_COS1f;
   8559         field2 = MC_COS1f;
   8560         field3 = RQE_Q_NUMf;
   8561         break;
   8562     case BCM_COSQ_GPORT_DESTMOD_UCAST_QUEUE_GROUP:
   8563         if (gport == -1) {
   8564             hw_cosq = cosq;
   8565         } else {
   8566             BCM_IF_ERROR_RETURN
   8567                 (_bcm_td2_cosq_index_resolve
   8568                  (unit, gport, cosq, _BCM_TD2_COSQ_INDEX_STYLE_COS,
   8569                   NULL, &hw_cosq, NULL));
   8570         }
   8571 
   8572         BCM_IF_ERROR_RETURN(
   8573             READ_VOQ_COS_MAPm(unit, MEM_BLOCK_ALL, priority, &voq_cos_map));
   8574         valid = soc_mem_field32_get(unit, VOQ_COS_MAPm, &voq_cos_map,
   8575                                     VOQ_COS_USE_MODf);
   8576         
   8577         /* Setting the  VOQ_PORT_BASE_SELECT,
   8578            so that BASE_QUEUE_NUM_1 is used for queue
   8579            calculation */
   8580 
   8581         soc_mem_field32_set(unit, VOQ_COS_MAPm, 
   8582                 &voq_cos_map, VOQ_PORT_BASE_SELECTf, 1);
   8583         soc_mem_field32_set(unit, VOQ_COS_MAPm, 
   8584                             &voq_cos_map, VOQ_COS_USE_MODf, 1);
   8585  
   8586         if (valid && (soc_mem_field32_get(unit, VOQ_COS_MAPm, &voq_cos_map, 
   8587                         VOQ_COS_OFFSETf) != hw_cosq)) {
   8588             soc_mem_field32_set(unit, VOQ_COS_MAPm, 
   8589                     &voq_cos_map, VOQ_COS_OFFSETf, hw_cosq);
   8590         }
   8591         BCM_IF_ERROR_RETURN(
   8592                 soc_mem_write(unit, VOQ_COS_MAPm, MEM_BLOCK_ANY, priority,
   8593                     &voq_cos_map));
   8594         return BCM_E_NONE;
   8595         break;
   8596     default:
   8597         return BCM_E_PARAM;
   8598     }
   8599 
   8600     entries[0] = &cos_map_entries;
   8601 
   8602     if (hw_cosq < 0 || hw_cosq >= 16) {
   8603         return BCM_E_PARAM;
   8604     }
   8605 
   8606     BCM_IF_ERROR_RETURN
   8607         (READ_COS_MAP_SELm(unit, MEM_BLOCK_ANY, local_port,
   8608                            &cos_map_sel_entry));
   8609     old_index = soc_mem_field32_get(unit, COS_MAP_SELm, &cos_map_sel_entry,
   8610                                     SELECTf);
   8611     old_index *= 16;
   8612 
   8613     BCM_IF_ERROR_RETURN
   8614         (soc_profile_mem_get(unit, _bcm_td2_cos_map_profile[unit],
   8615                              old_index, 16, entries));
   8616     soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[priority], field,
   8617                         hw_cosq);
   8618     if (field2 != INVALIDf) {
   8619         soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[priority],
   8620                             field2,hw_cosq);
   8621     }
   8622     if (field3 != INVALIDf) {
   8623         soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[priority],
   8624                             field3,hw_cosq);
   8625     }
   8626     
   8627     soc_mem_lock(unit, PORT_COS_MAPm);
   8628 
   8629     rv = soc_profile_mem_delete(unit, _bcm_td2_cos_map_profile[unit],
   8630                                 old_index);
   8631     if (BCM_FAILURE(rv)) {
   8632         soc_mem_unlock(unit, PORT_COS_MAPm);
   8633         return rv;
   8634     }
   8635 
   8636     rv = soc_profile_mem_add(unit, _bcm_td2_cos_map_profile[unit], entries,
   8637                              16, &new_index);
   8638 
   8639     soc_mem_unlock(unit, PORT_COS_MAPm);
   8640 
   8641     if (BCM_FAILURE(rv)) {
   8642         return rv;
   8643     }
   8644 
   8645     soc_mem_field32_set(unit, COS_MAP_SELm, &cos_map_sel_entry, SELECTf,
   8646                         new_index / 16);
   8647     BCM_IF_ERROR_RETURN
   8648         (WRITE_COS_MAP_SELm(unit, MEM_BLOCK_ANY, local_port,
   8649                             &cos_map_sel_entry));
   8650 
   8651 #ifndef BCM_COSQ_HIGIG_MAP_DISABLE
   8652     if (IS_CPU_PORT(unit, local_port)) {
   8653         BCM_IF_ERROR_RETURN
   8654             (soc_mem_field32_modify(unit, COS_MAP_SELm,
   8655                                     SOC_INFO(unit).cpu_hg_index, SELECTf,
   8656                                     new_index / 16));
   8657     }
   8658 #endif /* BCM_COSQ_HIGIG_MAP_DISABLE */
   8659 
   8660     return BCM_E_NONE;
   8661 }
   8662 
   8663 /*
   8664  * Function:
   8665  *     bcm_td2_cosq_mapping_set
   8666  * Purpose:
   8667  *     Set which cosq a given priority should fall into
   8668  * Parameters:
   8669  *     unit     - (IN) unit number
   8670  *     gport    - (IN) queue group GPORT identifier
   8671  *     priority - (IN) priority value to map
   8672  *     cosq     - (IN) COS queue to map to
   8673  * Returns:
   8674  *     BCM_E_XXX
   8675  */
   8676 
   8677 int
   8678 bcm_td2_cosq_mapping_set(int unit, bcm_port_t port, bcm_cos_t priority,
   8679                          bcm_cos_queue_t cosq)
   8680 {
   8681     bcm_pbmp_t pbmp;
   8682     bcm_port_t local_port;
   8683 
   8684     BCM_PBMP_CLEAR(pbmp);
   8685 
   8686     if (port == -1) {
   8687         BCM_PBMP_ASSIGN(pbmp, PBMP_ALL(unit));
   8688     } else {
   8689         if (BCM_GPORT_IS_SET(port)) {
   8690             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
   8691                 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) ||
   8692                 BCM_GPORT_IS_SCHEDULER(port)) {
   8693                 return BCM_E_PARAM;
   8694             } else if (BCM_GPORT_IS_LOCAL(port)) {
   8695                 local_port = BCM_GPORT_LOCAL_GET(port);
   8696             } else if (BCM_GPORT_IS_MODPORT(port)) {
   8697                 BCM_IF_ERROR_RETURN(
   8698                     bcm_esw_port_local_get(unit, port, &local_port));
   8699             } else {
   8700                 return BCM_E_PARAM;
   8701             }
   8702         } else {
   8703             local_port = port;
   8704         }
   8705 
   8706         if (!SOC_PORT_VALID(unit, local_port)) {
   8707             return BCM_E_PORT;
   8708         }
   8709 
   8710         BCM_PBMP_PORT_ADD(pbmp, local_port);
   8711     }
   8712 
   8713     PBMP_ITER(pbmp, local_port) {
   8714         BCM_IF_ERROR_RETURN(_bcm_td2_cosq_port_has_ets(unit, local_port));
   8715     }
   8716 
   8717     if ((cosq < 0) || (cosq >= _TD2_NUM_COS(unit))) {
   8718         return BCM_E_PARAM;
   8719     }
   8720 
   8721     PBMP_ITER(pbmp, local_port) {
   8722         if (IS_LB_PORT(unit, local_port)) {
   8723             continue;
   8724         }
   8725 
   8726         /* If no ETS/gport, map the int prio symmetrically for ucast and
   8727          * mcast */
   8728         BCM_IF_ERROR_RETURN(_bcm_td2_cosq_mapping_set(unit, local_port, 
   8729                                     priority,
   8730                                     BCM_COSQ_GPORT_UCAST_QUEUE_GROUP |
   8731                                     BCM_COSQ_GPORT_MCAST_QUEUE_GROUP,
   8732                                     -1, cosq));
   8733     }
   8734 
   8735     return BCM_E_NONE;
   8736 }
   8737 
   8738 /*
   8739  * Function:
   8740  *     bcm_td2_cosq_mapping_get
   8741  * Purpose:
   8742  *     Determine which COS queue a given priority currently maps to.
   8743  * Parameters:
   8744  *     unit     - (IN) unit number
   8745  *     gport    - (IN) queue group GPORT identifier
   8746  *     priority - (IN) priority value to map
   8747  *     cosq     - (OUT) COS queue to map to
   8748  * Returns:
   8749  *     BCM_E_XXX
   8750  */
   8751 int
   8752 _bcm_td2_cosq_mapping_get(int unit, bcm_port_t ing_port, bcm_cos_t priority,
   8753                           uint32 flags, bcm_gport_t *gport,
   8754                           bcm_cos_queue_t *cosq)
   8755 {
   8756     _bcm_td2_mmu_info_t *mmu_info;
   8757     _bcm_td2_pipe_resources_t *res;
   8758     _bcm_td2_cosq_port_info_t *port_info;
   8759     _bcm_td2_cosq_node_t *node;
   8760     bcm_port_t local_port;
   8761     bcm_cos_queue_t hw_cosq = BCM_COS_INVALID;
   8762     int index, ii;
   8763     cos_map_sel_entry_t cos_map_sel_entry;
   8764     voq_cos_map_entry_t voq_cos_map;
   8765     void *entry_p;
   8766     int ets_mode;
   8767 
   8768     if (priority < 0 || priority >= 16) {
   8769         return BCM_E_PARAM;
   8770     }
   8771 
   8772     if (flags != BCM_COSQ_GPORT_UCAST_QUEUE_GROUP &&
   8773         flags != BCM_COSQ_GPORT_MCAST_QUEUE_GROUP &&
   8774         flags != BCM_COSQ_GPORT_DESTMOD_UCAST_QUEUE_GROUP) {
   8775         return BCM_E_PARAM;
   8776     }
   8777 
   8778     BCM_IF_ERROR_RETURN
   8779         (_bcm_td2_cosq_localport_resolve(unit, ing_port, &local_port));
   8780 
   8781     if (gport) {
   8782         *gport = BCM_GPORT_INVALID;
   8783     }
   8784 
   8785     *cosq = BCM_COS_INVALID;
   8786 
   8787     if (local_port == CMIC_PORT(unit)) {
   8788         /* CPU has two indices: 
   8789         *  index_0 for Eth packet and index_106 for HiGig packet.
   8790         *  Getting cos mapping from index_106 instead of index_0,
   8791         *  although they are identical. Because previous version only write 
   8792         *  index_106. Keep this for warmboot backward compatability.
   8793         */
   8794         BCM_IF_ERROR_RETURN
   8795             (READ_COS_MAP_SELm(unit, MEM_BLOCK_ANY, SOC_INFO(unit).cpu_hg_index,
   8796                                &cos_map_sel_entry));
   8797     } else {
   8798         BCM_IF_ERROR_RETURN
   8799             (READ_COS_MAP_SELm(unit, MEM_BLOCK_ANY, local_port,
   8800                                &cos_map_sel_entry));
   8801     }
   8802     index = soc_mem_field32_get(unit, COS_MAP_SELm, &cos_map_sel_entry,
   8803                                 SELECTf);
   8804     index *= 16;
   8805 
   8806     entry_p = SOC_PROFILE_MEM_ENTRY(unit, _bcm_td2_cos_map_profile[unit],
   8807                                     port_cos_map_entry_t *,
   8808                                     index + priority);
   8809 
   8810     mmu_info = _bcm_td2_mmu_info[unit];
   8811     port_info = &mmu_info->port_info[local_port];
   8812     res = _BCM_TD2_PRESOURCES(mmu_info, _BCM_TD2_PORT_TO_PIPE(unit, local_port));
   8813     ets_mode = _bcm_td2_cosq_port_has_ets(unit, local_port);
   8814 
   8815     switch (flags) {
   8816     case BCM_COSQ_GPORT_UCAST_QUEUE_GROUP:
   8817         hw_cosq = soc_mem_field32_get(unit, PORT_COS_MAPm, entry_p, UC_COS1f);
   8818         if ((IS_CPU_PORT(unit, local_port) == FALSE) && gport && ets_mode) {
   8819             for (ii = port_info->uc_base; ii < port_info->uc_limit; ii++) {
   8820                 node = &mmu_info->queue_node[ii];
   8821                 if (node->numq > 0 && node->hw_cosq == hw_cosq) {
   8822                     *gport = node->gport;
   8823                     *cosq = 0;
   8824                     break;
   8825                 }
   8826             }
   8827             if (ii == port_info->uc_limit) {
   8828                 return BCM_E_NOT_FOUND;
   8829             }
   8830         }
   8831         break;
   8832     case BCM_COSQ_GPORT_MCAST_QUEUE_GROUP:
   8833         hw_cosq = soc_mem_field32_get(unit, PORT_COS_MAPm, entry_p, MC_COS1f);
   8834         if (gport && ets_mode) {
   8835             for (ii = port_info->mc_base; ii < port_info->mc_limit; ii++) {
   8836                 node = &mmu_info->mc_queue_node[ii];
   8837                 if (node->numq > 0 && node->hw_cosq == hw_cosq) {
   8838                     *gport = node->gport;
   8839                     *cosq = 0;
   8840                     break;
   8841                 }
   8842             }
   8843             if (ii == port_info->mc_limit) {
   8844                 return BCM_E_NOT_FOUND;
   8845             }
   8846         }
   8847         break;
   8848 
   8849     case BCM_COSQ_GPORT_DESTMOD_UCAST_QUEUE_GROUP:
   8850         BCM_IF_ERROR_RETURN(
   8851             READ_VOQ_COS_MAPm(unit, MEM_BLOCK_ALL, priority, &voq_cos_map));
   8852         hw_cosq = soc_mem_field32_get(unit, VOQ_COS_MAPm, 
   8853                                         &voq_cos_map, VOQ_COS_OFFSETf);
   8854         if (gport && ets_mode) {
   8855             for (ii = res->num_base_queues; ii < _BCM_TD2_NUM_L2_UC_LEAVES; ii++) {
   8856                 node = &mmu_info->queue_node[ii];
   8857                 
   8858                 if (node->numq > 0 && node->hw_cosq == hw_cosq) {
   8859                     *gport = node->gport;
   8860                     break;
   8861                 }
   8862             }
   8863             if (ii == _BCM_TD2_NUM_L2_UC_LEAVES) {
   8864                 return BCM_E_NOT_FOUND;
   8865             } 
   8866         }
   8867         break;
   8868     }
   8869 
   8870     *cosq = hw_cosq;
   8871 
   8872     if (((gport &&
   8873         (*gport == BCM_GPORT_INVALID) && (*cosq == BCM_COS_INVALID))) ||
   8874         (*cosq == BCM_COS_INVALID)) {
   8875         return BCM_E_NOT_FOUND;
   8876     }
   8877 
   8878     return BCM_E_NONE;
   8879 }
   8880 
   8881 int
   8882 bcm_td2_cosq_mapping_get(int unit, bcm_port_t port, bcm_cos_t priority,
   8883                         bcm_cos_queue_t *cosq)
   8884 {
   8885     bcm_port_t local_port;
   8886     bcm_pbmp_t pbmp;
   8887 
   8888     BCM_PBMP_CLEAR(pbmp);
   8889 
   8890     if (port == -1) {
   8891         BCM_PBMP_ASSIGN(pbmp, PBMP_ALL(unit));
   8892     } else {
   8893         if (BCM_GPORT_IS_SET(port)) {
   8894             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
   8895                 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) ||
   8896                 BCM_GPORT_IS_SCHEDULER(port)) {
   8897                 return BCM_E_PARAM;
   8898             } else if (BCM_GPORT_IS_LOCAL(port)) {
   8899                 local_port = BCM_GPORT_LOCAL_GET(port);
   8900             } else if (BCM_GPORT_IS_MODPORT(port)) {
   8901                 BCM_IF_ERROR_RETURN(
   8902                     bcm_esw_port_local_get(unit, port, &local_port));
   8903             } else {
   8904                 return BCM_E_PARAM;
   8905             }
   8906         } else {
   8907             local_port = port;
   8908         }
   8909 
   8910         if (!SOC_PORT_VALID(unit, local_port)) {
   8911             return BCM_E_PORT;
   8912         }
   8913 
   8914         BCM_PBMP_PORT_ADD(pbmp, local_port);
   8915     }
   8916 
   8917     PBMP_ITER(pbmp, local_port) {
   8918         if (IS_LB_PORT(unit, local_port)) {
   8919             continue;
   8920         }
   8921 
   8922         BCM_IF_ERROR_RETURN(_bcm_td2_cosq_mapping_get(unit, local_port, 
   8923                  priority, BCM_COSQ_GPORT_UCAST_QUEUE_GROUP, NULL, cosq));
   8924         break;
   8925     }    
   8926     return BCM_E_NONE;
   8927 }
   8928 
   8929 int
   8930 bcm_td2_cosq_gport_mapping_set(int unit, bcm_port_t ing_port,
   8931                               bcm_cos_t int_pri, uint32 flags,
   8932                               bcm_gport_t gport, bcm_cos_queue_t cosq)
   8933 {
   8934     return _bcm_td2_cosq_mapping_set(unit, ing_port, int_pri, flags, gport,
   8935                                     cosq);
   8936 }
   8937 
   8938 int
   8939 bcm_td2_cosq_gport_mapping_get(int unit, bcm_port_t ing_port,
   8940                               bcm_cos_t int_pri, uint32 flags,
   8941                               bcm_gport_t *gport, bcm_cos_queue_t *cosq)
   8942 {
   8943     if (gport == NULL || cosq == NULL) {
   8944         return BCM_E_PARAM;
   8945     }
   8946 
   8947     return _bcm_td2_cosq_mapping_get(unit, ing_port, int_pri, flags, gport,
   8948                                     cosq);
   8949 }
   8950 
   8951 /*
   8952  * Function:
   8953  *     bcm_td2_cosq_port_sched_set
   8954  * Purpose:
   8955  *     Set up class-of-service policy and corresponding weights and delay
   8956  * Parameters:
   8957  *     unit    - (IN) unit number
   8958  *     pbm     - (IN) port bitmap
   8959  *     mode    - (IN) Scheduling mode (BCM_COSQ_xxx)
   8960  *     weights - (IN) Weights for each COS queue
   8961  *     delay   - This parameter is not used
   8962  * Returns:
   8963  *     BCM_E_XXX
   8964  */
   8965 int
   8966 bcm_td2_cosq_port_sched_set(int unit, bcm_pbmp_t pbm,
   8967                            int mode, const int *weights, int delay)
   8968 {
   8969     bcm_port_t port;
   8970     int        num_weights, i;
   8971     int        cur_mode, cur_weight; 
   8972     int        reset_mode = BCM_COSQ_WEIGHTED_ROUND_ROBIN; 
   8973 
   8974     num_weights = _TD2_NUM_COS(unit);
   8975     BCM_PBMP_ITER(pbm, port) {
   8976         /*WRR mode is a property per port, 
   8977          * so just get cosq=0 schedule mode*/
   8978         BCM_IF_ERROR_RETURN
   8979             (_bcm_td2_cosq_sched_get(unit, port, 0,
   8980                                      &cur_mode, &cur_weight));
   8981         if (cur_mode == BCM_COSQ_STRICT) {
   8982             reset_mode = BCM_COSQ_WEIGHTED_ROUND_ROBIN;
   8983         } else {
   8984             reset_mode = cur_mode;
   8985         }
   8986         
   8987         /* Schedule mode switch need base on default wrr mode */        
   8988         for (i = 0; i < num_weights; i++) {
   8989             BCM_IF_ERROR_RETURN
   8990                 (_bcm_td2_cosq_sched_set(unit, port, i, 
   8991                                          reset_mode, 1));
   8992         }
   8993 
   8994         for (i = 0; i < num_weights; i++) {         
   8995             BCM_IF_ERROR_RETURN
   8996                 (_bcm_td2_cosq_sched_set(unit, port, i, mode, weights[i]));
   8997             
   8998         }
   8999     }
   9000 
   9001     return BCM_E_NONE;
   9002 }
   9003 
   9004 /*
   9005  * Function:
   9006  *     bcm_td2_cosq_port_sched_get
   9007  * Purpose:
   9008  *     Retrieve class-of-service policy and corresponding weights and delay
   9009  * Parameters:
   9010  *     unit     - (IN) unit number
   9011  *     pbm      - (IN) port bitmap
   9012  *     mode     - (OUT) Scheduling mode (BCM_COSQ_XXX)
   9013  *     weights  - (OUT) Weights for each COS queue
   9014  *     delay    - This parameter is not used
   9015  * Returns:
   9016  *     BCM_E_XXX
   9017  */
   9018 int
   9019 bcm_td2_cosq_port_sched_get(int unit, bcm_pbmp_t pbm,
   9020                            int *mode, int *weights, int *delay)
   9021 {
   9022     bcm_port_t port;
   9023     int i, num_weights;
   9024 
   9025     BCM_PBMP_ITER(pbm, port) {
   9026         /* coverity[illegal_address : FALSE] */
   9027         if (IS_CPU_PORT(unit, port) && SOC_PBMP_NEQ(pbm, PBMP_CMIC(unit))) {
   9028             continue;
   9029         }
   9030         num_weights = _TD2_NUM_COS(unit);
   9031         for (i = 0; i < num_weights; i++) {
   9032             BCM_IF_ERROR_RETURN(
   9033                 _bcm_td2_cosq_sched_get(unit, port, i, mode, &weights[i]));
   9034         }
   9035     }
   9036 
   9037     return BCM_E_NONE;
   9038 }
   9039 
   9040 /*
   9041  * Function:
   9042  *     bcm_td2_cosq_sched_weight_max_get
   9043  * Purpose:
   9044  *     Retrieve maximum weights for given COS policy
   9045  * Parameters:
   9046  *     unit    - (IN) unit number
   9047  *     mode    - (IN) Scheduling mode (BCM_COSQ_xxx)
   9048  *     weight_max - (OUT) Maximum weight for COS queue.
   9049  * Returns:
   9050  *     BCM_E_XXX
   9051  */
   9052 int
   9053 bcm_td2_cosq_sched_weight_max_get(int unit, int mode, int *weight_max)
   9054 {
   9055     switch (mode) {
   9056     case BCM_COSQ_STRICT:
   9057         *weight_max = BCM_COSQ_WEIGHT_STRICT;
   9058         break;
   9059     case BCM_COSQ_ROUND_ROBIN:
   9060     case BCM_COSQ_WEIGHTED_ROUND_ROBIN:
   9061     case BCM_COSQ_DEFICIT_ROUND_ROBIN:
   9062         /* TD2 - weights can be calculated based on LLS/HSP based 
   9063          * scheduling type associated to the port, in either case 
   9064          * the maximum weight can be 127  
   9065          */ 
   9066         *weight_max = 
   9067             (1 << soc_reg_field_length(unit, HSP_SCHED_L0_NODE_WEIGHTr, 
   9068                                         WEIGHTf)) - 1; 
   9069         break;
   9070     default:
   9071         return BCM_E_PARAM;
   9072     }
   9073 
   9074     return BCM_E_NONE;
   9075 }
   9076 
   9077 /*
   9078  * Function:
   9079  *     bcm_td2_cosq_bandwidth_set
   9080  * Purpose:
   9081  *     Configure COS queue bandwidth control
   9082  * Parameters:
   9083  *     unit          - (IN) unit number
   9084  *     port          - (IN) port number or GPORT identifier
   9085  *     cosq          - (IN) COS queue number
   9086  *     min_quantum   - (IN)
   9087  *     max_quantum   - (IN)
   9088  *     burst_quantum - (IN)
   9089  *     flags         - (IN)
   9090  * Returns:
   9091  *     BCM_E_XXX
   9092  * Notes:
   9093  *     If port is any form of local port, cosq is the hardware queue index.
   9094  */
   9095 int
   9096 bcm_td2_cosq_port_bandwidth_set(int unit, bcm_port_t port,
   9097                                bcm_cos_queue_t cosq,
   9098                                uint32 min_quantum, uint32 max_quantum,
   9099                                uint32 burst_quantum, uint32 flags)
   9100 {
   9101     uint32 burst_min, burst_max;
   9102 
   9103     if (cosq < 0) {
   9104         return BCM_E_PARAM;
   9105     }
   9106 
   9107     burst_min = (min_quantum > 0) ?
   9108           _bcm_td_default_burst_size(unit, port, min_quantum) : 0;
   9109 
   9110     burst_max = (max_quantum > 0) ?
   9111           _bcm_td_default_burst_size(unit, port, max_quantum) : 0;
   9112 
   9113     return _bcm_td2_cosq_bucket_set(unit, port, cosq, min_quantum, max_quantum,
   9114                                     burst_min, burst_max, flags);
   9115 }
   9116 
   9117 /*
   9118  * Function:
   9119  *     bcm_td2_cosq_bandwidth_get
   9120  * Purpose:
   9121  *     Get COS queue bandwidth control configuration
   9122  * Parameters:
   9123  *     unit          - (IN) unit number
   9124  *     port          - (IN) port number or GPORT identifier
   9125  *     cosq          - (IN) COS queue number
   9126  *     min_quantum   - (OUT)
   9127  *     max_quantum   - (OUT)
   9128  *     burst_quantum - (OUT)
   9129  *     flags         - (OUT)
   9130  * Returns:
   9131  *     BCM_E_XXX
   9132  * Notes:
   9133  *     If port is any form of local port, cosq is the hardware queue index.
   9134  */
   9135 int
   9136 bcm_td2_cosq_port_bandwidth_get(int unit, bcm_port_t port,
   9137                                bcm_cos_queue_t cosq,
   9138                                uint32 *min_quantum, uint32 *max_quantum,
   9139                                uint32 *burst_quantum, uint32 *flags)
   9140 {
   9141     uint32 kbit_burst_min;
   9142 
   9143     if (cosq < -1) {
   9144         return BCM_E_PARAM;
   9145     }
   9146 
   9147     BCM_IF_ERROR_RETURN(_bcm_td2_cosq_bucket_get(unit, port, cosq,
   9148                         min_quantum, max_quantum, &kbit_burst_min,
   9149                         burst_quantum, flags));
   9150     return BCM_E_NONE;
   9151 }
   9152 
   9153 int
   9154 bcm_td2_cosq_port_pps_set(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   9155                          int pps)
   9156 {
   9157     uint32 min, max, burst, burst_min, flags;
   9158     bcm_port_t  local_port =  port;
   9159     
   9160     if (!IS_CPU_PORT(unit, port)) {
   9161         return BCM_E_PORT;
   9162     } else if (cosq < 0 || cosq >= NUM_CPU_COSQ(unit)) {
   9163         return BCM_E_PARAM;
   9164     }
   9165 
   9166     if (_bcm_td2_cosq_port_has_ets(unit, port)) {
   9167         BCM_IF_ERROR_RETURN(_bcm_td2_cosq_l2_gport(unit, port, cosq, 
   9168                                             _BCM_TD2_NODE_MCAST, &port, NULL));
   9169         cosq = 0;
   9170     }
   9171 
   9172     BCM_IF_ERROR_RETURN
   9173         (_bcm_td2_cosq_bucket_get(unit, port, cosq, &min, &max, &burst_min,
   9174                                     &burst, &flags));
   9175 
   9176     min = pps;
   9177     burst_min = (min > 0) ?
   9178           _bcm_td_default_burst_size(unit, local_port, min) : 0;
   9179     burst = burst_min;        
   9180 
   9181     return _bcm_td2_cosq_bucket_set(unit, port, cosq, min, pps, burst_min, burst,
   9182                                     flags | BCM_COSQ_BW_PACKET_MODE);
   9183 }
   9184 
   9185 int
   9186 bcm_td2_cosq_port_pps_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   9187                          int *pps)
   9188 {
   9189     uint32 min, max, burst, flags;
   9190 
   9191     if (!IS_CPU_PORT(unit, port)) {
   9192         return BCM_E_PORT;
   9193     } else if (cosq < 0 || cosq >= NUM_CPU_COSQ(unit)) {
   9194         return BCM_E_PARAM;
   9195     }
   9196 
   9197     if (_bcm_td2_cosq_port_has_ets(unit, port)) {
   9198         BCM_IF_ERROR_RETURN(_bcm_td2_cosq_l2_gport(unit, port, cosq,
   9199                                           _BCM_TD2_NODE_MCAST, &port, NULL));
   9200         cosq = 0;
   9201     }
   9202 
   9203     BCM_IF_ERROR_RETURN
   9204         (_bcm_td2_cosq_bucket_get(unit, port, cosq, &min, &max, &burst, &burst,
   9205                                   &flags));
   9206     *pps = max;
   9207 
   9208     return BCM_E_NONE;
   9209 }
   9210 
   9211 int
   9212 bcm_td2_cosq_port_burst_set(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   9213                            int burst)
   9214 {
   9215     uint32 min, max, cur_burst, flags;
   9216 
   9217     if (!IS_CPU_PORT(unit, port)) {
   9218         return BCM_E_PORT;
   9219     } else if (cosq < 0 || cosq >= NUM_CPU_COSQ(unit)) {
   9220         return BCM_E_PARAM;
   9221     }
   9222 
   9223     if (_bcm_td2_cosq_port_has_ets(unit, port)) {
   9224         BCM_IF_ERROR_RETURN(_bcm_td2_cosq_l2_gport(unit, port, cosq,
   9225                                                 _BCM_TD2_NODE_MCAST, &port, NULL));
   9226         cosq = 0;
   9227     }
   9228 
   9229     BCM_IF_ERROR_RETURN
   9230         (_bcm_td2_cosq_bucket_get(unit, port, cosq, &min, &max, &cur_burst,
   9231                                   &cur_burst, &flags));
   9232 
   9233     /* Replace the current BURST setting, keep PPS the same */
   9234     return _bcm_td2_cosq_bucket_set(unit, port, cosq, min, max, burst, burst,
   9235                                     flags | BCM_COSQ_BW_PACKET_MODE);
   9236 }
   9237 
   9238 int
   9239 bcm_td2_cosq_port_burst_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   9240                            int *burst)
   9241 {
   9242     uint32 min, max, cur_burst, cur_burst_min, flags;
   9243 
   9244     if (!IS_CPU_PORT(unit, port)) {
   9245         return BCM_E_PORT;
   9246     } else if (cosq < 0 || cosq >= NUM_CPU_COSQ(unit)) {
   9247         return BCM_E_PARAM;
   9248     }
   9249 
   9250     if (_bcm_td2_cosq_port_has_ets(unit, port)) {
   9251         BCM_IF_ERROR_RETURN(_bcm_td2_cosq_l2_gport(unit, port, cosq, 
   9252                                             _BCM_TD2_NODE_MCAST, &port, NULL));
   9253         cosq = 0;
   9254     }
   9255 
   9256     BCM_IF_ERROR_RETURN
   9257         (_bcm_td2_cosq_bucket_get(unit, port, cosq, &min, &max, 
   9258                                   &cur_burst_min, &cur_burst, &flags));
   9259     *burst = cur_burst;
   9260 
   9261     return BCM_E_NONE;
   9262 }
   9263 
   9264 int
   9265 bcm_td2_cosq_discard_set(int unit, uint32 flags)
   9266 {
   9267     bcm_port_t port;
   9268     _bcm_td2_mmu_info_t *mmu_info;
   9269 
   9270     if ((mmu_info = _bcm_td2_mmu_info[unit]) == NULL) {
   9271         return BCM_E_INIT;
   9272     }
   9273     
   9274     if (flags & ~(BCM_COSQ_DISCARD_TCP |
   9275                   BCM_COSQ_DISCARD_NONTCP |
   9276                   BCM_COSQ_DISCARD_COLOR_ALL |
   9277                   BCM_COSQ_DISCARD_COLOR_GREEN |
   9278                   BCM_COSQ_DISCARD_COLOR_YELLOW |
   9279                   BCM_COSQ_DISCARD_COLOR_RED |
   9280                   BCM_COSQ_DISCARD_CAP_AVERAGE |
   9281                   BCM_COSQ_DISCARD_ENABLE |
   9282                   BCM_COSQ_DISCARD_MARK_CONGESTION)) {
   9283         return BCM_E_PARAM;
   9284     }
   9285 
   9286     flags &= ~(BCM_COSQ_DISCARD_NONTCP | BCM_COSQ_DISCARD_COLOR_ALL);
   9287 
   9288     PBMP_PORT_ITER(unit, port) {
   9289         BCM_IF_ERROR_RETURN
   9290             (_bcm_td2_cosq_wred_set(unit, port, 0, flags, 0, 0, 0, 0,
   9291                                     FALSE, BCM_COSQ_DISCARD_PORT,8));
   9292     }
   9293 
   9294     return BCM_E_NONE;
   9295 }
   9296 
   9297 int
   9298 bcm_td2_cosq_discard_get(int unit, uint32 *flags)
   9299 {
   9300     bcm_port_t port;
   9301 
   9302     PBMP_PORT_ITER(unit, port) {
   9303         *flags = 0;
   9304         /* use setting from hardware cosq index 0 of the first port */
   9305         return _bcm_td2_cosq_wred_get(unit, port, 0, flags, NULL, NULL, NULL,
   9306                                      NULL, BCM_COSQ_DISCARD_PORT,NULL);
   9307     }
   9308 
   9309     return BCM_E_NOT_FOUND;
   9310 }
   9311 
   9312 /*
   9313  * Function:
   9314  *     bcm_td2_cosq_discard_port_set
   9315  * Purpose:
   9316  *     Configure port WRED setting
   9317  * Parameters:
   9318  *     unit          - (IN) unit number
   9319  *     port          - (IN) port number or GPORT identifier
   9320  *     cosq          - (IN) COS queue number
   9321  *     color         - (IN)
   9322  *     drop_start    - (IN)
   9323  *     drop_slot     - (IN)
   9324  *     average_time  - (IN)
   9325  * Returns:
   9326  *     BCM_E_XXX
   9327  * Notes:
   9328  *     If port is any form of local port, cosq is the hardware queue index.
   9329  */
   9330 int
   9331 bcm_td2_cosq_discard_port_set(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   9332                              uint32 color, int drop_start, int drop_slope,
   9333                              int average_time)
   9334 {
   9335     bcm_port_t local_port;
   9336     bcm_pbmp_t pbmp;
   9337     int gain;
   9338     uint32 min_thresh, max_thresh, shared_limit;
   9339     uint32 rval, bits, flags = 0;
   9340     int numq, i;
   9341 
   9342     if (drop_start < 0 || drop_start > 100 ||
   9343         drop_slope < 0 || drop_slope > 90) {
   9344         return BCM_E_PARAM;
   9345     }
   9346 
   9347     /*
   9348      * average queue size is reculated every 8us, the formula is
   9349      * avg_qsize(t + 1) =
   9350      *     avg_qsize(t) + (cur_qsize - avg_qsize(t)) / (2 ** gain)
   9351      * gain = log2(average_time / 8)
   9352      */
   9353     bits = (average_time / 8) & 0xffff;
   9354     if (bits != 0) {
   9355         bits |= bits >> 1;
   9356         bits |= bits >> 2;
   9357         bits |= bits >> 4;
   9358         bits |= bits >> 8;
   9359         gain = _shr_popcount(bits) - 1;
   9360     } else {
   9361         gain = 0;
   9362     }
   9363 
   9364     /*
   9365      * per-port cell limit may be disabled.
   9366      * per-port per-cos cell limit may be set to use dynamic method.
   9367      * therefore drop_start percentage is based on per-device total shared
   9368      * cells.
   9369      */
   9370     BCM_IF_ERROR_RETURN(READ_MMU_THDM_DB_POOL_SHARED_LIMITr(unit, 0, &rval));
   9371     shared_limit = soc_reg_field_get(unit, MMU_THDM_DB_POOL_SHARED_LIMITr,
   9372                                      rval, SHARED_LIMITf);
   9373     min_thresh = ((drop_start * shared_limit) + (100 - 1)) / 100;
   9374 
   9375     /* Calculate the max threshold. For a given slope (angle in
   9376      * degrees), determine how many packets are in the range from
   9377      * 0% drop probability to 100% drop probability. Add that
   9378      * number to the min_treshold to the the max_threshold.
   9379      */
   9380     max_thresh = min_thresh + _bcm_td2_angle_to_cells(drop_slope);
   9381     if (max_thresh > TD2_CELL_FIELD_MAX) {
   9382         max_thresh = TD2_CELL_FIELD_MAX;
   9383     }
   9384 
   9385     if (BCM_GPORT_IS_SET(port)) {
   9386         numq = 1;
   9387         for (i = 0; i < numq; i++) {
   9388             BCM_IF_ERROR_RETURN
   9389                 (_bcm_td2_cosq_wred_set(unit, port, cosq + i, color,
   9390                                        min_thresh, max_thresh, 100, gain,
   9391                                        TRUE, flags,8));
   9392         }
   9393     } else {
   9394         if (port == -1) {
   9395             BCM_PBMP_ASSIGN(pbmp, PBMP_PORT_ALL(unit));
   9396         } else if (!SOC_PORT_VALID(unit, port)) {
   9397             return BCM_E_PORT;
   9398         } else {
   9399             BCM_PBMP_PORT_SET(pbmp, port);
   9400         }
   9401 
   9402         BCM_PBMP_ITER(pbmp, local_port) {
   9403             numq = 1;
   9404             for (i = 0; i < numq; i++) {
   9405                 BCM_IF_ERROR_RETURN
   9406                     (_bcm_td2_cosq_wred_set(unit, local_port, cosq + i,
   9407                                            color, min_thresh, max_thresh, 100,
   9408                                            gain, TRUE, 0,8));
   9409             }
   9410         }
   9411     }
   9412 
   9413     return BCM_E_NONE;
   9414 }
   9415 
   9416 /*
   9417  * Function:
   9418  *     bcm_td2_cosq_discard_port_get
   9419  * Purpose:
   9420  *     Get port WRED setting
   9421  * Parameters:
   9422  *     unit          - (IN) unit number
   9423  *     port          - (IN) port number or GPORT identifier
   9424  *     cosq          - (IN) COS queue number
   9425  *     color         - (OUT)
   9426  *     drop_start    - (OUT)
   9427  *     drop_slot     - (OUT)
   9428  *     average_time  - (OUT)
   9429  * Returns:
   9430  *     BCM_E_XXX
   9431  * Notes:
   9432  *     If port is any form of local port, cosq is the hardware queue index.
   9433  */
   9434 int
   9435 bcm_td2_cosq_discard_port_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   9436                              uint32 color, int *drop_start, int *drop_slope,
   9437                              int *average_time)
   9438 {
   9439     bcm_port_t local_port;
   9440     bcm_pbmp_t pbmp;
   9441     int gain, drop_prob;
   9442     int refresh_time = 0;
   9443     uint32 min_thresh, max_thresh, shared_limit;
   9444     uint32 rval;
   9445 
   9446     if (drop_start == NULL || drop_slope == NULL || average_time == NULL) {
   9447         return BCM_E_PARAM;
   9448     }
   9449 
   9450     if (BCM_GPORT_IS_SET(port)) {
   9451         local_port = port;
   9452     } else {
   9453         if (port == -1) {
   9454             BCM_PBMP_ASSIGN(pbmp, PBMP_PORT_ALL(unit));
   9455         } else if (!SOC_PORT_VALID(unit, port)) {
   9456             return BCM_E_PORT;
   9457         } else {
   9458             BCM_PBMP_PORT_SET(pbmp, port);
   9459         }
   9460         BCM_PBMP_ITER(pbmp, local_port) {
   9461             break;
   9462         }
   9463     }
   9464 
   9465     BCM_IF_ERROR_RETURN
   9466         (_bcm_td2_cosq_wred_get(unit, local_port, cosq == -1 ? 0 : cosq,
   9467                                &color, &min_thresh, &max_thresh, &drop_prob,
   9468                                &gain, 0, &refresh_time));
   9469 
   9470     /*
   9471      * average queue size is reculated every 8us, the formula is
   9472      * avg_qsize(t + 1) =
   9473      *     avg_qsize(t) + (cur_qsize - avg_qsize(t)) / (2 ** gain)
   9474      */
   9475     *average_time = (1 << gain) * refresh_time;
   9476 
   9477     BCM_IF_ERROR_RETURN(READ_MMU_THDM_DB_POOL_SHARED_LIMITr(unit, 0, &rval));
   9478     shared_limit = soc_reg_field_get(unit, MMU_THDM_DB_POOL_SHARED_LIMITr,
   9479                                      rval, SHARED_LIMITf);
   9480     if (min_thresh > shared_limit) {
   9481         min_thresh = shared_limit;
   9482     }
   9483 
   9484     if (max_thresh > shared_limit) {
   9485         max_thresh = shared_limit;
   9486     }
   9487 
   9488     *drop_start = min_thresh * 100 / shared_limit;
   9489 
   9490     /* Calculate the slope using the min and max threshold.
   9491      * The angle is calculated knowing drop probability at min
   9492      * threshold is 0% and drop probability at max threshold is 100%.
   9493      */
   9494     *drop_slope = _bcm_td2_cells_to_angle(max_thresh - min_thresh);
   9495 
   9496     return BCM_E_NONE;
   9497 }
   9498 
   9499 STATIC int
   9500 _bcm_td2_distribute_u64(uint64 value, uint64 *l, uint64 *r)
   9501 {
   9502     uint64 tmp, tmp1;
   9503 
   9504     tmp = value;
   9505     COMPILER_64_SHR(tmp, 1);
   9506     *l = tmp;
   9507 
   9508     COMPILER_64_SET(tmp1, 0, 1);
   9509     COMPILER_64_AND(tmp1, value);
   9510     COMPILER_64_ADD_64(tmp1, tmp);
   9511     *r = tmp1;
   9512     return 0;
   9513 }
   9514 
   9515 STATIC int
   9516 _port_l2c_mapping(int unit, bcm_port_t port, bcm_cosq_stat_t stat, int *xlp_port)
   9517 {
   9518     soc_info_t *si;
   9519     soc_port_t phy_port;
   9520     int i, xlp_blk, xlp_bindex = -1, pgw_blk, pgw_bindex = -1; 
   9521 
   9522     si = &SOC_INFO(unit);
   9523 
   9524     phy_port = si->port_l2p_mapping[port];
   9525     for (i = 0; i < SOC_DRIVER(unit)->port_num_blktype; i++) {
   9526         xlp_blk = SOC_PORT_IDX_BLOCK(unit, phy_port, i);
   9527         xlp_bindex = SOC_PORT_IDX_BINDEX(unit, phy_port, i);
   9528         if (SOC_BLOCK_INFO(unit, xlp_blk).type == SOC_BLK_XLPORT) {
   9529             break;
   9530         }
   9531     }
   9532     for (i = 0; i < SOC_DRIVER(unit)->port_num_blktype; i++) {
   9533         pgw_blk = SOC_PORT_IDX_BLOCK(unit, phy_port, i);
   9534         pgw_bindex = SOC_PORT_IDX_BINDEX(unit, phy_port, i);
   9535         if (SOC_BLOCK_INFO(unit, pgw_blk).type == SOC_BLK_PGW_CL) {
   9536             break;
   9537         }
   9538     }
   9539     *xlp_port = xlp_bindex;
   9540 
   9541     if(stat == bcmCosqStatHighPriDroppedPackets){
   9542         switch (pgw_bindex % 16) {
   9543         case 0:
   9544         case 1:  
   9545         case 2:
   9546         case 3:
   9547             return SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM0_HIGH_PRI;
   9548         case 4:
   9549         case 5:
   9550         case 6:
   9551         case 7:
   9552             return SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM1_HIGH_PRI;
   9553         case 8:
   9554         case 9:  
   9555         case 10:
   9556         case 11:
   9557             return SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM2_HIGH_PRI;
   9558         case 12:
   9559         case 13:  
   9560         case 14:
   9561         case 15:
   9562             return SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM3_HIGH_PRI;
   9563         default:
   9564             return SOC_E_INTERNAL;
   9565         }
   9566     }
   9567         
   9568     if(stat == bcmCosqStatLowPriDroppedPackets){
   9569         switch (pgw_bindex % 16) {
   9570         case 0:
   9571         case 1:  
   9572         case 2:
   9573         case 3:
   9574             return SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM0_LOW_PRI;
   9575         case 4:
   9576         case 5:
   9577         case 6:
   9578         case 7:
   9579             return SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM1_LOW_PRI;
   9580         case 8:
   9581         case 9:  
   9582         case 10:
   9583         case 11:
   9584             return SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM2_LOW_PRI;
   9585         case 12:
   9586         case 13:  
   9587         case 14:
   9588         case 15:
   9589             return SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM3_LOW_PRI;
   9590         default:
   9591             return SOC_E_INTERNAL;
   9592         }
   9593     }
   9594 
   9595     if(stat == bcmCosqStatHighPriDroppedBytes){
   9596         switch (pgw_bindex % 16) {
   9597         case 0:
   9598         case 1:  
   9599         case 2:
   9600         case 3:
   9601             return SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM0_HIGH_PRI;
   9602         case 4:
   9603         case 5:
   9604         case 6:
   9605         case 7:
   9606             return SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM1_HIGH_PRI;
   9607         case 8:
   9608         case 9:  
   9609         case 10:
   9610         case 11:
   9611             return SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM2_HIGH_PRI;
   9612         case 12:
   9613         case 13:  
   9614         case 14:
   9615         case 15:
   9616             return SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM3_HIGH_PRI;
   9617         default:
   9618             return SOC_E_INTERNAL;
   9619         }
   9620     }
   9621 
   9622     if(stat == bcmCosqStatLowPriDroppedBytes){
   9623         switch (pgw_bindex % 16) {
   9624         case 0:
   9625         case 1:  
   9626         case 2:
   9627         case 3:
   9628             return SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM0_LOW_PRI;
   9629         case 4:
   9630         case 5:
   9631         case 6:
   9632         case 7:
   9633             return SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM1_LOW_PRI;
   9634         case 8:
   9635         case 9:  
   9636         case 10:
   9637         case 11:
   9638             return SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM2_LOW_PRI;
   9639         case 12:
   9640         case 13:  
   9641         case 14:
   9642         case 15:
   9643             return SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM3_LOW_PRI;
   9644         default:
   9645             return SOC_E_INTERNAL;
   9646         }
   9647     }
   9648 
   9649     return SOC_E_INTERNAL;
   9650 }
   9651 
   9652 int
   9653 bcm_td2_cosq_stat_set(int unit, bcm_gport_t port, bcm_cos_queue_t cosq,
   9654                      bcm_cosq_stat_t stat, uint64 value)
   9655 {
   9656     _bcm_td2_cosq_node_t *node;
   9657     bcm_port_t local_port;
   9658     int startq, numq, i, from_cos, to_cos, ci;
   9659     uint64  l, r;
   9660     soc_counter_non_dma_id_t id;
   9661     int xlp_port;
   9662 
   9663     if (cosq < -1) {
   9664         return BCM_E_PARAM;
   9665     }
   9666     _bcm_td2_distribute_u64(value, &l, &r);
   9667 
   9668     switch (stat) {
   9669     case bcmCosqStatDroppedPackets:
   9670         if (BCM_GPORT_IS_SCHEDULER(port)) {
   9671             BCM_IF_ERROR_RETURN
   9672                 (_bcm_td2_cosq_node_get(unit, port, 0, NULL, 
   9673                                         &local_port, NULL, &node));
   9674             BCM_IF_ERROR_RETURN(
   9675                    _bcm_td2_cosq_child_node_at_input(node, cosq, &node));
   9676             port = node->gport;
   9677         }
   9678 
   9679         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) {
   9680             BCM_IF_ERROR_RETURN
   9681                 (_bcm_td2_cosq_node_get(unit, port, 0, NULL,
   9682                                         &local_port, NULL, &node));
   9683             if ((node->type == _BCM_TD2_NODE_VM_UCAST) ||
   9684                 (node->type == _BCM_TD2_NODE_SERVICE_UCAST)) {
   9685                 /* coverity[NEGATIVE_RETURNS: FALSE] */
   9686                 BCM_IF_ERROR_RETURN
   9687                     (soc_counter_set(unit, local_port,
   9688                                      SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_EXT, node->hw_index,
   9689                                      value));
   9690             } else {
   9691                 BCM_IF_ERROR_RETURN
   9692                     (_bcm_td2_cosq_index_resolve
   9693                      (unit, port, cosq, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_UCAST,
   9694                       &local_port, &startq, NULL));
   9695                 /* coverity[NEGATIVE_RETURNS: FALSE] */
   9696                 BCM_IF_ERROR_RETURN
   9697                     (soc_counter_set(unit, local_port,
   9698                                      SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_UC, startq,
   9699                                      value));
   9700             }
   9701         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
   9702             BCM_IF_ERROR_RETURN
   9703                 (_bcm_td2_cosq_index_resolve
   9704                  (unit, port, cosq, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_MCAST,
   9705                   &local_port, &startq, NULL));
   9706             /* coverity[NEGATIVE_RETURNS: FALSE] */
   9707             BCM_IF_ERROR_RETURN
   9708                 (soc_counter_set(unit, local_port,
   9709                              SOC_COUNTER_NON_DMA_COSQ_DROP_PKT, startq,
   9710                                  value));
   9711         } else {
   9712             BCM_IF_ERROR_RETURN(_bcm_td2_cosq_localport_resolve(unit, port, &local_port));
   9713             BCM_IF_ERROR_RETURN(_bcm_td2_cosq_port_has_ets(unit, local_port));
   9714             if (cosq == BCM_COS_INVALID) {
   9715                 from_cos = to_cos = 0;
   9716             } else {
   9717                 from_cos = to_cos = cosq;
   9718             }
   9719             for (ci = from_cos; ci <= to_cos; ci++) {
   9720                 if (!IS_CPU_PORT(unit, local_port)) {
   9721                     BCM_IF_ERROR_RETURN
   9722                         (_bcm_td2_cosq_index_resolve
   9723                          (unit, port, ci, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_UCAST,
   9724                           &local_port, &startq, &numq));
   9725                     for (i = 0; i < numq; i++) {
   9726                     /* coverity[NEGATIVE_RETURNS: FALSE] */
   9727                       BCM_IF_ERROR_RETURN
   9728                            (soc_counter_set(unit, local_port,
   9729                                            SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_UC,
   9730                                          startq + i, l));
   9731                     }
   9732                 }
   9733                 BCM_IF_ERROR_RETURN
   9734                     (_bcm_td2_cosq_index_resolve
   9735                      (unit, port, ci, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_MCAST,
   9736                       &local_port, &startq, &numq));
   9737                 for (i = 0; i < numq; i++) {
   9738                     BCM_IF_ERROR_RETURN
   9739                         (soc_counter_set(unit, local_port,
   9740                                          SOC_COUNTER_NON_DMA_COSQ_DROP_PKT,
   9741                                          startq + i , r));
   9742                 }
   9743             }
   9744         }
   9745         break;
   9746     case bcmCosqStatDroppedBytes:
   9747         if (BCM_GPORT_IS_SCHEDULER(port)) {
   9748             BCM_IF_ERROR_RETURN
   9749                 (_bcm_td2_cosq_node_get(unit, port, 0, NULL, 
   9750                                         &local_port, NULL, &node));
   9751             BCM_IF_ERROR_RETURN(
   9752                    _bcm_td2_cosq_child_node_at_input(node, cosq, &node));
   9753             port = node->gport;
   9754         }
   9755 
   9756         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) {
   9757             BCM_IF_ERROR_RETURN
   9758                 (_bcm_td2_cosq_node_get(unit, port, 0, NULL,
   9759                                         &local_port, NULL, &node));
   9760             if ((node->type == _BCM_TD2_NODE_VM_UCAST) ||
   9761                 (node->type == _BCM_TD2_NODE_SERVICE_UCAST)) {
   9762                 /* coverity[NEGATIVE_RETURNS: FALSE] */
   9763                 BCM_IF_ERROR_RETURN
   9764                     (soc_counter_set(unit, local_port,
   9765                                      SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE_EXT, node->hw_index,
   9766                                      value));
   9767             } else {
   9768                 BCM_IF_ERROR_RETURN
   9769                     (_bcm_td2_cosq_index_resolve
   9770                      (unit, port, cosq, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_UCAST,
   9771                       &local_port, &startq, NULL));
   9772                 /* coverity[NEGATIVE_RETURNS: FALSE] */
   9773                 BCM_IF_ERROR_RETURN
   9774                     (soc_counter_set(unit, local_port,
   9775                                      SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE_UC, startq,
   9776                                      value));
   9777             }
   9778         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
   9779             BCM_IF_ERROR_RETURN
   9780                 (_bcm_td2_cosq_index_resolve
   9781                  (unit, port, cosq, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_MCAST,
   9782                   &local_port, &startq, NULL));
   9783             /* coverity[NEGATIVE_RETURNS: FALSE] */
   9784             BCM_IF_ERROR_RETURN
   9785                 (soc_counter_set(unit, local_port,
   9786                    SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE, startq , value));
   9787         } else {
   9788             BCM_IF_ERROR_RETURN(_bcm_td2_cosq_localport_resolve(unit, port, &local_port));
   9789             BCM_IF_ERROR_RETURN(_bcm_td2_cosq_port_has_ets(unit, local_port));
   9790             if (cosq == BCM_COS_INVALID) {
   9791                 from_cos = to_cos = 0;
   9792             } else {
   9793                 from_cos = to_cos = cosq;
   9794             }
   9795             for (ci = from_cos; ci <= to_cos; ci++) {
   9796                 if (!IS_CPU_PORT(unit, local_port)) {
   9797                     BCM_IF_ERROR_RETURN
   9798                        (_bcm_td2_cosq_index_resolve
   9799                         (unit, port, ci, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_UCAST,
   9800                          &local_port, &startq, &numq));
   9801                     for (i = 0; i < numq; i++) {
   9802                     /* coverity[NEGATIVE_RETURNS: FALSE] */
   9803                        BCM_IF_ERROR_RETURN
   9804                         (soc_counter_set(unit, local_port,
   9805                                          SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE_UC,
   9806                                          startq + i, l));
   9807                     }
   9808                 }
   9809                 BCM_IF_ERROR_RETURN
   9810                     (_bcm_td2_cosq_index_resolve
   9811                      (unit, port, ci, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_MCAST,
   9812                       &local_port, &startq, &numq));
   9813                 for (i = 0; i < numq; i++) {
   9814                     BCM_IF_ERROR_RETURN
   9815                         (soc_counter_set(unit, local_port,
   9816                            SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE,
   9817                                          startq + i , r));
   9818                 }
   9819             }
   9820         }
   9821         break;
   9822     case bcmCosqStatYellowCongestionDroppedPackets:
   9823         if (cosq != BCM_COS_INVALID) {
   9824             return BCM_E_UNAVAIL;
   9825         }
   9826         BCM_IF_ERROR_RETURN
   9827             (_bcm_td2_cosq_localport_resolve(unit, port, &local_port));
   9828         BCM_IF_ERROR_RETURN
   9829             (soc_counter_set(unit, local_port,
   9830                              SOC_COUNTER_NON_DMA_PORT_DROP_PKT_YELLOW, 0,
   9831                              value));
   9832         break;
   9833     case bcmCosqStatRedCongestionDroppedPackets:
   9834         if (cosq != BCM_COS_INVALID) {
   9835             return BCM_E_UNAVAIL;
   9836         }
   9837         BCM_IF_ERROR_RETURN
   9838             (_bcm_td2_cosq_localport_resolve(unit, port, &local_port));
   9839         BCM_IF_ERROR_RETURN
   9840             (soc_counter_set(unit, local_port,
   9841                              SOC_COUNTER_NON_DMA_PORT_DROP_PKT_RED, 0,
   9842                              value));
   9843         break;
   9844     case bcmCosqStatGreenDiscardDroppedPackets:
   9845         if (cosq != BCM_COS_INVALID) {
   9846             return BCM_E_UNAVAIL;
   9847         }
   9848         BCM_IF_ERROR_RETURN
   9849             (_bcm_td2_cosq_localport_resolve(unit, port, &local_port));
   9850         BCM_IF_ERROR_RETURN
   9851             (soc_counter_set(unit, local_port,
   9852                              SOC_COUNTER_NON_DMA_PORT_WRED_PKT_GREEN, 0,
   9853                              value));
   9854         break;
   9855     case bcmCosqStatYellowDiscardDroppedPackets:
   9856         if (cosq != BCM_COS_INVALID) {
   9857             return BCM_E_UNAVAIL;
   9858         }
   9859         BCM_IF_ERROR_RETURN
   9860             (_bcm_td2_cosq_localport_resolve(unit, port, &local_port));
   9861         BCM_IF_ERROR_RETURN
   9862             (soc_counter_set(unit, local_port,
   9863                              SOC_COUNTER_NON_DMA_PORT_WRED_PKT_YELLOW, 0,
   9864                              value));
   9865         break;
   9866     case bcmCosqStatRedDiscardDroppedPackets:
   9867         if (cosq != BCM_COS_INVALID) {
   9868             return BCM_E_UNAVAIL;
   9869         }
   9870         BCM_IF_ERROR_RETURN
   9871             (_bcm_td2_cosq_localport_resolve(unit, port, &local_port));
   9872         BCM_IF_ERROR_RETURN
   9873             (soc_counter_set(unit, local_port,
   9874                              SOC_COUNTER_NON_DMA_PORT_WRED_PKT_RED, 0, value));
   9875         break;
   9876     case bcmCosqStatOutPackets:
   9877         if (BCM_GPORT_IS_SCHEDULER(port)) {
   9878             BCM_IF_ERROR_RETURN
   9879                 (_bcm_td2_cosq_node_get(unit, port, 0, NULL, 
   9880                                         &local_port, NULL, &node));
   9881             BCM_IF_ERROR_RETURN(
   9882                    _bcm_td2_cosq_child_node_at_input(node, cosq, &node));
   9883             port = node->gport;
   9884         }
   9885 
   9886         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) {
   9887             BCM_IF_ERROR_RETURN
   9888                 (_bcm_td2_cosq_node_get(unit, port, 0, NULL,
   9889                                         &local_port, NULL, &node));
   9890             if ((node->type == _BCM_TD2_NODE_VM_UCAST) ||
   9891                 (node->type == _BCM_TD2_NODE_SERVICE_UCAST)) {
   9892                 /* coverity[NEGATIVE_RETURNS: FALSE] */
   9893                 BCM_IF_ERROR_RETURN
   9894                     (soc_counter_set(unit, local_port,
   9895                                      SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT_EXT, node->hw_index,
   9896                                      value));
   9897             } else {
   9898                 BCM_IF_ERROR_RETURN
   9899                     (_bcm_td2_cosq_index_resolve
   9900                      (unit, port, cosq, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_UCAST,
   9901                       &local_port, &startq, NULL));
   9902                 /* coverity[NEGATIVE_RETURNS: FALSE] */
   9903                 BCM_IF_ERROR_RETURN
   9904                     (soc_counter_set(unit, local_port,
   9905                                      SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT_UC, startq,
   9906                                      value));
   9907             }
   9908         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
   9909             BCM_IF_ERROR_RETURN
   9910                 (_bcm_td2_cosq_index_resolve
   9911                  (unit, port, cosq, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_MCAST,
   9912                   &local_port, &startq, NULL));
   9913             /* coverity[NEGATIVE_RETURNS: FALSE] */
   9914             BCM_IF_ERROR_RETURN
   9915                 (soc_counter_set(unit, local_port,
   9916                                  SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT, startq,
   9917                                  value));
   9918         } else {
   9919             BCM_IF_ERROR_RETURN(_bcm_td2_cosq_localport_resolve(unit, port, &local_port));
   9920             BCM_IF_ERROR_RETURN(_bcm_td2_cosq_port_has_ets(unit, local_port));
   9921             if (cosq == BCM_COS_INVALID) {
   9922                 from_cos = to_cos = 0;
   9923             } else {
   9924                 from_cos = to_cos = cosq;
   9925             }
   9926             for (ci = from_cos; ci <= to_cos; ci++) {
   9927                 if (!IS_CPU_PORT(unit, local_port)) {
   9928                     BCM_IF_ERROR_RETURN
   9929                         (_bcm_td2_cosq_index_resolve
   9930                             (unit, port, ci, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_UCAST,
   9931                              &local_port, &startq, &numq));
   9932                     for (i = 0; i < numq; i++) {
   9933                         /* coverity[NEGATIVE_RETURNS: FALSE] */
   9934                         BCM_IF_ERROR_RETURN
   9935                             (soc_counter_set(unit, local_port,
   9936                                              SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT_UC,
   9937                                              startq + i, l));
   9938                     }
   9939                 }
   9940                 BCM_IF_ERROR_RETURN
   9941                     (_bcm_td2_cosq_index_resolve
   9942                      (unit, port, ci, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_MCAST,
   9943                       &local_port, &startq, &numq));
   9944                 for (i = 0; i < numq; i++) {
   9945                     BCM_IF_ERROR_RETURN
   9946                         (soc_counter_set(unit, local_port,
   9947                                          SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT,
   9948                                          startq + i, r));
   9949                 }
   9950             }
   9951         }
   9952         break;
   9953     case bcmCosqStatOutBytes:
   9954         if (BCM_GPORT_IS_SCHEDULER(port)) {
   9955             BCM_IF_ERROR_RETURN
   9956                 (_bcm_td2_cosq_node_get(unit, port, 0, NULL, 
   9957                                         &local_port, NULL, &node));
   9958             BCM_IF_ERROR_RETURN(
   9959                    _bcm_td2_cosq_child_node_at_input(node, cosq, &node));
   9960             port = node->gport;
   9961         }
   9962 
   9963         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) {
   9964             BCM_IF_ERROR_RETURN
   9965                 (_bcm_td2_cosq_node_get(unit, port, 0, NULL,
   9966                                         &local_port, NULL, &node));
   9967             if ((node->type == _BCM_TD2_NODE_VM_UCAST) ||
   9968                 (node->type == _BCM_TD2_NODE_SERVICE_UCAST)) {
   9969                 /* coverity[NEGATIVE_RETURNS: FALSE] */
   9970                 BCM_IF_ERROR_RETURN
   9971                     (soc_counter_set(unit, local_port,
   9972                                      SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE_EXT, node->hw_index,
   9973                                      value));
   9974             } else {
   9975                 BCM_IF_ERROR_RETURN
   9976                     (_bcm_td2_cosq_index_resolve
   9977                      (unit, port, cosq, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_UCAST,
   9978                       &local_port, &startq, NULL));
   9979                 /* coverity[NEGATIVE_RETURNS: FALSE] */
   9980                 BCM_IF_ERROR_RETURN
   9981                     (soc_counter_set(unit, local_port,
   9982                                      SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE_UC, startq,
   9983                                      value));
   9984             }
   9985         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
   9986             BCM_IF_ERROR_RETURN
   9987                 (_bcm_td2_cosq_index_resolve
   9988                  (unit, port, cosq, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_MCAST,
   9989                   &local_port, &startq, NULL));
   9990             /* coverity[NEGATIVE_RETURNS: FALSE] */
   9991             BCM_IF_ERROR_RETURN
   9992                 (soc_counter_set(unit, local_port,
   9993                                  SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE, startq,
   9994                                  value));
   9995         } else {
   9996             BCM_IF_ERROR_RETURN(_bcm_td2_cosq_localport_resolve(unit, port, &local_port));
   9997             BCM_IF_ERROR_RETURN(_bcm_td2_cosq_port_has_ets(unit, local_port));
   9998             if (cosq == BCM_COS_INVALID) {
   9999                 from_cos = to_cos = 0;
  10000             } else {
  10001                 from_cos = to_cos = cosq;
  10002             }
  10003             for (ci = from_cos; ci <= to_cos; ci++) {
  10004                 if (!IS_CPU_PORT(unit, local_port)) {
  10005                     BCM_IF_ERROR_RETURN
  10006                         (_bcm_td2_cosq_index_resolve
  10007                             (unit, port, ci, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_UCAST,
  10008                              &local_port, &startq, &numq));
  10009                     for (i = 0; i < numq; i++) {
  10010                         /* coverity[NEGATIVE_RETURNS: FALSE] */
  10011                         BCM_IF_ERROR_RETURN
  10012                             (soc_counter_set(unit, local_port,
  10013                                              SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE_UC,
  10014                                              startq + i, l));
  10015                     }
  10016                 }
  10017                 BCM_IF_ERROR_RETURN
  10018                     (_bcm_td2_cosq_index_resolve
  10019                      (unit, port, ci, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_MCAST,
  10020                       &local_port, &startq, &numq));
  10021                 for (i = 0; i < numq; i++) {
  10022                     BCM_IF_ERROR_RETURN
  10023                         (soc_counter_set(unit, local_port,
  10024                                          SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE,
  10025                                          startq + i, r));
  10026                 }
  10027             }
  10028         }
  10029         break;
  10030     case bcmCosqStatUCOutPackets:
  10031     case bcmCosqStatUCOutBytes:
  10032         if (BCM_GPORT_IS_SCHEDULER(port)) {
  10033             BCM_IF_ERROR_RETURN
  10034                 (_bcm_td2_cosq_node_get(unit, port, 0, NULL,
  10035                                         &local_port, NULL, &node));
  10036             BCM_IF_ERROR_RETURN(
  10037                    _bcm_td2_cosq_child_node_at_input(node, cosq, &node));
  10038             port = node->gport;
  10039         }
  10040 
  10041         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) {
  10042             soc_reg_t ctr_reg_uc;
  10043             BCM_IF_ERROR_RETURN
  10044                 (_bcm_td2_cosq_node_get(unit, port, 0, NULL,
  10045                                         &local_port, NULL, &node));
  10046             if ((node->type == _BCM_TD2_NODE_VM_UCAST) ||
  10047                 (node->type == _BCM_TD2_NODE_SERVICE_UCAST)) {
  10048                 ctr_reg_uc = (stat == bcmCosqStatUCOutPackets) ?
  10049                      SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT_EXT :
  10050                      SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE_EXT;
  10051                 /* coverity[NEGATIVE_RETURNS: FALSE] */
  10052                 BCM_IF_ERROR_RETURN
  10053                     (soc_counter_set(unit, local_port, ctr_reg_uc, node->hw_index, value));
  10054             } else {
  10055                 ctr_reg_uc = (stat == bcmCosqStatUCOutPackets) ?
  10056                      SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT_UC :
  10057                      SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE_UC;
  10058                 BCM_IF_ERROR_RETURN
  10059                     (_bcm_td2_cosq_index_resolve
  10060                      (unit, port, cosq, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_UCAST,
  10061                       &local_port, &startq, NULL));
  10062                 /* coverity[NEGATIVE_RETURNS: FALSE] */
  10063                 BCM_IF_ERROR_RETURN
  10064                     (soc_counter_set(unit, local_port, ctr_reg_uc, startq, value));
  10065             }
  10066         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
  10067             return BCM_E_PARAM;
  10068         } else {
  10069             soc_reg_t ctr_reg_uc;
  10070             ctr_reg_uc = (stat == bcmCosqStatUCOutPackets) ?
  10071                  SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT_UC :
  10072                  SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE_UC;
  10073             BCM_IF_ERROR_RETURN(_bcm_td2_cosq_localport_resolve(unit, port, &local_port));
  10074             BCM_IF_ERROR_RETURN(_bcm_td2_cosq_port_has_ets(unit, local_port));
  10075             if (cosq == BCM_COS_INVALID) {
  10076                 from_cos = to_cos = 0;
  10077             } else {
  10078                 from_cos = to_cos = cosq;
  10079             }
  10080             for (ci = from_cos; ci <= to_cos; ci++) {
  10081                 if (!IS_CPU_PORT(unit, local_port)) {
  10082                     BCM_IF_ERROR_RETURN
  10083                         (_bcm_td2_cosq_index_resolve
  10084                             (unit, port, ci, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_UCAST,
  10085                              &local_port, &startq, &numq));
  10086                     for (i = 0; i < numq; i++) {
  10087                         /* coverity[NEGATIVE_RETURNS: FALSE] */
  10088                         BCM_IF_ERROR_RETURN
  10089                             (soc_counter_set(unit, local_port, ctr_reg_uc, startq + i, value));
  10090                     }
  10091                 }
  10092             }
  10093         }
  10094         break;
  10095     case bcmCosqStatMCOutPackets:
  10096     case bcmCosqStatMCOutBytes:
  10097         if (BCM_GPORT_IS_SCHEDULER(port)) {
  10098             BCM_IF_ERROR_RETURN
  10099                 (_bcm_td2_cosq_node_get(unit, port, 0, NULL,
  10100                                         &local_port, NULL, &node));
  10101             BCM_IF_ERROR_RETURN(
  10102                    _bcm_td2_cosq_child_node_at_input(node, cosq, &node));
  10103             port = node->gport;
  10104         }
  10105 
  10106         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) {
  10107             return BCM_E_PARAM;
  10108         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
  10109             soc_reg_t ctr_reg_mc = (stat == bcmCosqStatMCOutPackets) ?
  10110                  SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT :
  10111                  SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE;
  10112             BCM_IF_ERROR_RETURN
  10113                 (_bcm_td2_cosq_index_resolve
  10114                  (unit, port, cosq, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_MCAST,
  10115                   &local_port, &startq, NULL));
  10116             /* coverity[NEGATIVE_RETURNS: FALSE] */
  10117             BCM_IF_ERROR_RETURN
  10118                 (soc_counter_set(unit, local_port, ctr_reg_mc, startq, value));
  10119         } else {
  10120             soc_reg_t ctr_reg_mc = (stat == bcmCosqStatMCOutPackets) ?
  10121                  SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT :
  10122                  SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE;
  10123             BCM_IF_ERROR_RETURN(_bcm_td2_cosq_localport_resolve(unit, port, &local_port));
  10124             BCM_IF_ERROR_RETURN(_bcm_td2_cosq_port_has_ets(unit, local_port));
  10125             if (cosq == BCM_COS_INVALID) {
  10126                 from_cos = to_cos = 0;
  10127             } else {
  10128                 from_cos = to_cos = cosq;
  10129             }
  10130             for (ci = from_cos; ci <= to_cos; ci++) {
  10131                 BCM_IF_ERROR_RETURN
  10132                     (_bcm_td2_cosq_index_resolve
  10133                      (unit, port, ci, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_MCAST,
  10134                       &local_port, &startq, &numq));
  10135                 for (i = 0; i < numq; i++) {
  10136                     BCM_IF_ERROR_RETURN
  10137                         (soc_counter_set(unit, local_port, ctr_reg_mc, startq + i, value));
  10138                 }
  10139             }
  10140         }
  10141         break;
  10142     case bcmCosqStatIeee8021CnCpTransmittedCnms:
  10143         BCM_IF_ERROR_RETURN
  10144             (_bcm_td2_cosq_index_resolve
  10145                 (unit, port, cosq, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_UCAST,
  10146                  &local_port, &startq, NULL));        
  10147         BCM_IF_ERROR_RETURN
  10148             (soc_counter_set(unit, local_port,
  10149                              SOC_COUNTER_NON_DMA_MMU_QCN_CNM, startq, value));
  10150         break;
  10151     case bcmCosqStatHighPriDroppedPackets:
  10152         if (cosq != BCM_COS_INVALID) {
  10153             return BCM_E_UNAVAIL;
  10154         }
  10155         BCM_IF_ERROR_RETURN
  10156             (_bcm_td2_cosq_localport_resolve(unit, port, &local_port));
  10157         BCM_IF_ERROR_RETURN
  10158             (id = _port_l2c_mapping(unit,local_port,bcmCosqStatHighPriDroppedPackets,&xlp_port));
  10159         BCM_IF_ERROR_RETURN
  10160             (soc_counter_set(unit, local_port, id, xlp_port, value));
  10161         break;
  10162     case bcmCosqStatLowPriDroppedPackets:
  10163         if (cosq != BCM_COS_INVALID) {
  10164             return BCM_E_UNAVAIL;
  10165         }
  10166         
  10167         BCM_IF_ERROR_RETURN
  10168             (_bcm_td2_cosq_localport_resolve(unit, port, &local_port));
  10169         BCM_IF_ERROR_RETURN
  10170             (id = _port_l2c_mapping(unit,local_port,bcmCosqStatLowPriDroppedPackets,&xlp_port));
  10171         BCM_IF_ERROR_RETURN
  10172             (soc_counter_set(unit, local_port, id, xlp_port, value));
  10173         break;
  10174     case bcmCosqStatHighPriDroppedBytes:
  10175         if (cosq != BCM_COS_INVALID) {
  10176             return BCM_E_UNAVAIL;
  10177         }
  10178         
  10179         BCM_IF_ERROR_RETURN
  10180             (_bcm_td2_cosq_localport_resolve(unit, port, &local_port));
  10181         BCM_IF_ERROR_RETURN
  10182             (id = _port_l2c_mapping(unit,local_port,bcmCosqStatHighPriDroppedBytes,&xlp_port));
  10183         BCM_IF_ERROR_RETURN
  10184             (soc_counter_set(unit, local_port, id, xlp_port, value));
  10185         break;
  10186     case bcmCosqStatLowPriDroppedBytes:
  10187         if (cosq != BCM_COS_INVALID) {
  10188             return BCM_E_UNAVAIL;
  10189         }
  10190         
  10191         BCM_IF_ERROR_RETURN
  10192             (_bcm_td2_cosq_localport_resolve(unit, port, &local_port));
  10193         BCM_IF_ERROR_RETURN
  10194             (id = _port_l2c_mapping(unit,local_port,bcmCosqStatLowPriDroppedBytes,&xlp_port));
  10195         BCM_IF_ERROR_RETURN
  10196             (soc_counter_set(unit, local_port, id, xlp_port, value));
  10197         break;
  10198     default:
  10199         return BCM_E_PARAM;
  10200     }
  10201 
  10202     return BCM_E_NONE;
  10203 }
  10204 
  10205 int
  10206 bcm_td2_cosq_stat_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
  10207                      bcm_cosq_stat_t stat, int sync_mode, uint64 *value)
  10208 {
  10209     _bcm_td2_cosq_node_t *node;
  10210     bcm_port_t local_port;
  10211     int startq, numq, i, from_cos, to_cos, ci, start_hw_index, end_hw_index;
  10212     uint64 sum, value64;
  10213     uint32 sum32, value32;
  10214     soc_counter_non_dma_id_t id;
  10215     int xlp_port;
  10216     int (*counter_get) (int , soc_port_t , soc_reg_t , int , uint64 *);
  10217     int pool, midx, valid;
  10218     uint32 entry[SOC_MAX_MEM_WORDS], rval;
  10219     soc_mem_t mem = INVALIDm;
  10220     soc_field_t field = INVALIDf;
  10221 
  10222     if ((value == NULL) || (cosq < -1)) {
  10223         return BCM_E_PARAM;
  10224     }
  10225 
  10226     /*
  10227      * if sync-mode is set, update the software cached counter value, 
  10228      * with the hardware count and then retrieve the count.
  10229      * else return the software cache counter value.
  10230      */
  10231     counter_get = (sync_mode == 1)? soc_counter_sync_get: soc_counter_get;
  10232     COMPILER_64_ZERO(*value);
  10233     value32 = 0;
  10234 
  10235     switch (stat) {
  10236     case bcmCosqStatDroppedPackets:
  10237         if (BCM_GPORT_IS_SCHEDULER(port)) {
  10238             BCM_IF_ERROR_RETURN
  10239                 (_bcm_td2_cosq_node_get(unit, port, 0, NULL, 
  10240                                         &local_port, NULL, &node));
  10241             BCM_IF_ERROR_RETURN(
  10242                    _bcm_td2_cosq_child_node_at_input(node, cosq, &node));
  10243             port = node->gport;
  10244         }
  10245 
  10246         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) {
  10247             BCM_IF_ERROR_RETURN
  10248                 (_bcm_td2_cosq_node_get(unit, port, 0, NULL,
  10249                                         &local_port, NULL, &node));
  10250             if ((node->type == _BCM_TD2_NODE_VM_UCAST) ||
  10251                 (node->type == _BCM_TD2_NODE_SERVICE_UCAST)) {
  10252                 /* coverity[NEGATIVE_RETURNS: FALSE] */
  10253                 BCM_IF_ERROR_RETURN
  10254                     (counter_get(unit, local_port,
  10255                                      SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_EXT, node->hw_index,
  10256                                      value));
  10257             } else {
  10258                 BCM_IF_ERROR_RETURN
  10259                     (_bcm_td2_cosq_index_resolve
  10260                      (unit, port, cosq, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_UCAST,
  10261                       &local_port, &startq, NULL));
  10262                 /* coverity[NEGATIVE_RETURNS: FALSE] */
  10263                 BCM_IF_ERROR_RETURN
  10264                     (counter_get(unit, local_port,
  10265                                 SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_UC, startq,
  10266                                      value));
  10267             }
  10268         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
  10269             BCM_IF_ERROR_RETURN
  10270                 (_bcm_td2_cosq_index_resolve
  10271                  (unit, port, cosq, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_MCAST,
  10272                   &local_port, &startq, NULL));
  10273             /* coverity[NEGATIVE_RETURNS: FALSE] */
  10274             BCM_IF_ERROR_RETURN
  10275                 (counter_get(unit, local_port,
  10276                     SOC_COUNTER_NON_DMA_COSQ_DROP_PKT, startq, value));
  10277         } else {
  10278             BCM_IF_ERROR_RETURN(_bcm_td2_cosq_localport_resolve(unit, port, &local_port));
  10279             BCM_IF_ERROR_RETURN(_bcm_td2_cosq_port_has_ets(unit, local_port));
  10280             COMPILER_64_ZERO(sum);
  10281             if (cosq == BCM_COS_INVALID) {
  10282                 from_cos = 0;
  10283                 to_cos = (IS_CPU_PORT(unit, local_port)) ? 
  10284                             NUM_CPU_COSQ(unit) - 1 : _TD2_NUM_COS(unit) - 1;
  10285             } else {
  10286                 from_cos = to_cos = cosq;
  10287             }
  10288             for (ci = from_cos; ci <= to_cos; ci++) {
  10289                 if (!IS_CPU_PORT(unit, local_port)) {
  10290                     BCM_IF_ERROR_RETURN
  10291                     (_bcm_td2_cosq_index_resolve
  10292                      (unit, port, ci, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_UCAST,
  10293                       &local_port, &startq, &numq));
  10294                     for (i = 0; i < numq; i++) {
  10295                     /* coverity[NEGATIVE_RETURNS: FALSE] */
  10296                          BCM_IF_ERROR_RETURN
  10297                             (counter_get(unit, local_port,
  10298                                          SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_UC,
  10299                                          startq + i, &value64));
  10300                          COMPILER_64_ADD_64(sum, value64);
  10301                     }
  10302                 }
  10303                 BCM_IF_ERROR_RETURN
  10304                   (_bcm_td2_cosq_index_resolve
  10305                      (unit, port, ci, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_MCAST,
  10306                       &local_port, &startq, &numq));
  10307 
  10308                 for (i = 0; i < numq; i++) {
  10309                     /* coverity[NEGATIVE_RETURNS: FALSE] */
  10310                     BCM_IF_ERROR_RETURN
  10311                         (counter_get(unit, local_port,
  10312                                          SOC_COUNTER_NON_DMA_COSQ_DROP_PKT,
  10313                                          startq + i, &value64));
  10314                     COMPILER_64_ADD_64(sum, value64);
  10315                 }
  10316             }
  10317             *value = sum;
  10318         }
  10319         break;
  10320     case bcmCosqStatDroppedBytes:
  10321         if (BCM_GPORT_IS_SCHEDULER(port)) {
  10322             BCM_IF_ERROR_RETURN
  10323                 (_bcm_td2_cosq_node_get(unit, port, 0, NULL, 
  10324                                         &local_port, NULL, &node));
  10325             BCM_IF_ERROR_RETURN(
  10326                    _bcm_td2_cosq_child_node_at_input(node, cosq, &node));
  10327             port = node->gport;
  10328         }
  10329 
  10330         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) {
  10331             BCM_IF_ERROR_RETURN
  10332                 (_bcm_td2_cosq_node_get(unit, port, 0, NULL,
  10333                                         &local_port, NULL, &node));
  10334             if ((node->type == _BCM_TD2_NODE_VM_UCAST) ||
  10335                 (node->type == _BCM_TD2_NODE_SERVICE_UCAST)) {
  10336                 /* coverity[NEGATIVE_RETURNS: FALSE] */
  10337                 BCM_IF_ERROR_RETURN
  10338                     (counter_get(unit, local_port,
  10339                                      SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE_EXT, node->hw_index,
  10340                                      value));
  10341             } else {
  10342                 BCM_IF_ERROR_RETURN
  10343                     (_bcm_td2_cosq_index_resolve
  10344                      (unit, port, cosq, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_UCAST,
  10345                       &local_port, &startq, NULL));
  10346                 /* coverity[NEGATIVE_RETURNS: FALSE] */
  10347                 BCM_IF_ERROR_RETURN
  10348                     (counter_get(unit, local_port,
  10349                                      SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE_UC, startq,
  10350                                      value));
  10351             }
  10352         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
  10353             BCM_IF_ERROR_RETURN
  10354                 (_bcm_td2_cosq_index_resolve
  10355                  (unit, port, cosq, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_MCAST,
  10356                   &local_port, &startq, NULL));
  10357             /* coverity[NEGATIVE_RETURNS: FALSE] */
  10358             BCM_IF_ERROR_RETURN
  10359                 (counter_get(unit, local_port,
  10360                   SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE, startq, value));
  10361         } else {
  10362             BCM_IF_ERROR_RETURN(_bcm_td2_cosq_localport_resolve(unit, port, &local_port));
  10363             BCM_IF_ERROR_RETURN(_bcm_td2_cosq_port_has_ets(unit, local_port));
  10364             COMPILER_64_ZERO(sum);
  10365             if (cosq == BCM_COS_INVALID) {
  10366                 from_cos = 0;
  10367                 to_cos = (IS_CPU_PORT(unit, local_port)) ? 
  10368                             NUM_CPU_COSQ(unit) - 1 : _TD2_NUM_COS(unit) - 1;
  10369             } else {
  10370                 from_cos = to_cos = cosq;
  10371             }
  10372             for (ci = from_cos; ci <= to_cos; ci++) {
  10373                 if (!IS_CPU_PORT(unit, local_port)) {
  10374                     BCM_IF_ERROR_RETURN
  10375                        (_bcm_td2_cosq_index_resolve
  10376                        (unit, port, ci, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_UCAST,
  10377                         &local_port, &startq, &numq));
  10378                     for (i = 0; i < numq; i++) {
  10379                      /* coverity[NEGATIVE_RETURNS: FALSE] */
  10380                         BCM_IF_ERROR_RETURN
  10381                           (counter_get(unit, local_port,
  10382                                          SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE_UC,
  10383                                          startq + i, &value64));
  10384                         COMPILER_64_ADD_64(sum, value64);
  10385                     }
  10386                 }
  10387                 BCM_IF_ERROR_RETURN
  10388                     (_bcm_td2_cosq_index_resolve
  10389                      (unit, port, ci, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_MCAST,
  10390                       &local_port, &startq, &numq));
  10391                 for (i = 0; i < numq; i++) {
  10392                     BCM_IF_ERROR_RETURN
  10393                         (counter_get(unit, local_port,
  10394                                          SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE,
  10395                                          startq + i, &value64));
  10396                     COMPILER_64_ADD_64(sum, value64);
  10397                 }
  10398             }
  10399             *value = sum;
  10400         }
  10401         break;
  10402     case bcmCosqStatYellowCongestionDroppedPackets:
  10403         if (cosq != BCM_COS_INVALID) {
  10404             return BCM_E_UNAVAIL;
  10405         }
  10406         BCM_IF_ERROR_RETURN
  10407             (_bcm_td2_cosq_localport_resolve(unit, port, &local_port));
  10408         BCM_IF_ERROR_RETURN
  10409             (counter_get(unit, local_port,
  10410                              SOC_COUNTER_NON_DMA_PORT_DROP_PKT_YELLOW, 0,
  10411                              value));
  10412         break;
  10413     case bcmCosqStatRedCongestionDroppedPackets:
  10414         if (cosq != BCM_COS_INVALID) {
  10415             return BCM_E_UNAVAIL;
  10416         }
  10417         BCM_IF_ERROR_RETURN
  10418             (_bcm_td2_cosq_localport_resolve(unit, port, &local_port));
  10419         BCM_IF_ERROR_RETURN
  10420             (counter_get(unit, local_port,
  10421                              SOC_COUNTER_NON_DMA_PORT_DROP_PKT_RED, 0,
  10422                              value));
  10423         break;
  10424     case bcmCosqStatGreenDiscardDroppedPackets:
  10425         if (cosq != BCM_COS_INVALID) {
  10426             return BCM_E_UNAVAIL;
  10427         }
  10428         BCM_IF_ERROR_RETURN
  10429             (_bcm_td2_cosq_localport_resolve(unit, port, &local_port));
  10430         BCM_IF_ERROR_RETURN
  10431             (counter_get(unit, local_port,
  10432                              SOC_COUNTER_NON_DMA_PORT_WRED_PKT_GREEN, 0,
  10433                              value));
  10434         break;
  10435     case bcmCosqStatYellowDiscardDroppedPackets:
  10436         if (cosq != BCM_COS_INVALID) {
  10437             return BCM_E_UNAVAIL;
  10438         }
  10439         BCM_IF_ERROR_RETURN
  10440             (_bcm_td2_cosq_localport_resolve(unit, port, &local_port));
  10441         BCM_IF_ERROR_RETURN
  10442             (counter_get(unit, local_port,
  10443                              SOC_COUNTER_NON_DMA_PORT_WRED_PKT_YELLOW, 0,
  10444                              value));
  10445         break;
  10446     case bcmCosqStatRedDiscardDroppedPackets:
  10447         if (cosq != BCM_COS_INVALID) {
  10448             return BCM_E_UNAVAIL;
  10449         }
  10450         BCM_IF_ERROR_RETURN
  10451             (_bcm_td2_cosq_localport_resolve(unit, port, &local_port));
  10452         BCM_IF_ERROR_RETURN
  10453             (counter_get(unit, local_port,
  10454                              SOC_COUNTER_NON_DMA_PORT_WRED_PKT_RED, 0, value));
  10455         break;
  10456     case bcmCosqStatOutPackets:
  10457         if (BCM_GPORT_IS_SCHEDULER(port)) {
  10458             BCM_IF_ERROR_RETURN
  10459                 (_bcm_td2_cosq_node_get(unit, port, 0, NULL, 
  10460                                         &local_port, NULL, &node));
  10461             BCM_IF_ERROR_RETURN(
  10462                    _bcm_td2_cosq_child_node_at_input(node, cosq, &node));
  10463             port = node->gport;
  10464         }
  10465 
  10466         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) {
  10467             BCM_IF_ERROR_RETURN
  10468                 (_bcm_td2_cosq_node_get(unit, port, 0, NULL,
  10469                                         &local_port, NULL, &node));
  10470             if ((node->type == _BCM_TD2_NODE_VM_UCAST) ||
  10471                 (node->type == _BCM_TD2_NODE_SERVICE_UCAST)) {
  10472                 /* coverity[NEGATIVE_RETURNS: FALSE] */
  10473                 BCM_IF_ERROR_RETURN
  10474                     (counter_get(unit, local_port,
  10475                                      SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT_EXT, node->hw_index,
  10476                                      value));
  10477 
  10478             } else {
  10479                 BCM_IF_ERROR_RETURN
  10480                     (_bcm_td2_cosq_index_resolve
  10481                      (unit, port, cosq, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_UCAST,
  10482                       &local_port, &startq, NULL));
  10483                 /* coverity[NEGATIVE_RETURNS: FALSE] */
  10484                 BCM_IF_ERROR_RETURN
  10485                     (counter_get(unit, local_port,
  10486                                      SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT_UC, startq,
  10487                                      value));
  10488             }
  10489         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
  10490             BCM_IF_ERROR_RETURN
  10491                 (_bcm_td2_cosq_index_resolve
  10492                  (unit, port, cosq, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_MCAST,
  10493                   &local_port, &startq, NULL));
  10494             /* coverity[NEGATIVE_RETURNS: FALSE] */
  10495             BCM_IF_ERROR_RETURN
  10496                 (counter_get(unit, local_port,
  10497                                  SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT, startq,
  10498                                  value));
  10499         } else {
  10500             BCM_IF_ERROR_RETURN(_bcm_td2_cosq_localport_resolve(unit, port, &local_port));
  10501             BCM_IF_ERROR_RETURN(_bcm_td2_cosq_port_has_ets(unit, local_port));
  10502             COMPILER_64_ZERO(sum);
  10503             if (cosq == BCM_COS_INVALID) {
  10504                 from_cos = 0;
  10505                 to_cos = (IS_CPU_PORT(unit, local_port)) ? 
  10506                             NUM_CPU_COSQ(unit) - 1 : _TD2_NUM_COS(unit) - 1;
  10507             } else {
  10508                 from_cos = to_cos = cosq;
  10509             }
  10510 
  10511             for (ci = from_cos; ci <= to_cos; ci++) {
  10512                 if (!IS_CPU_PORT(unit, local_port)) {
  10513                     BCM_IF_ERROR_RETURN
  10514                         (_bcm_td2_cosq_index_resolve
  10515                             (unit, port, ci, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_UCAST,
  10516                              &local_port, &startq, &numq));
  10517                     for (i = 0; i < numq; i++) {
  10518                         /* coverity[NEGATIVE_RETURNS: FALSE] */
  10519                         BCM_IF_ERROR_RETURN
  10520                             (counter_get(unit, local_port,
  10521                                              SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT_UC,
  10522                                              startq + i, &value64));
  10523                         COMPILER_64_ADD_64(sum, value64);
  10524                     }
  10525                 }
  10526                 BCM_IF_ERROR_RETURN
  10527                     (_bcm_td2_cosq_index_resolve
  10528                      (unit, port, ci, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_MCAST,
  10529                       &local_port, &startq, &numq));
  10530                 for (i = 0; i < numq; i++) {
  10531                     /* coverity[NEGATIVE_RETURNS: FALSE] */
  10532                     BCM_IF_ERROR_RETURN
  10533                         (counter_get(unit, local_port,
  10534                                          SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT,
  10535                                          startq + i, &value64));
  10536                     COMPILER_64_ADD_64(sum, value64);
  10537                 }
  10538             }
  10539             *value = sum;
  10540         }
  10541         break;
  10542     case bcmCosqStatOutBytes:
  10543         if (BCM_GPORT_IS_SCHEDULER(port)) {
  10544             BCM_IF_ERROR_RETURN
  10545                 (_bcm_td2_cosq_node_get(unit, port, 0, NULL, 
  10546                                         &local_port, NULL, &node));
  10547             BCM_IF_ERROR_RETURN(
  10548                    _bcm_td2_cosq_child_node_at_input(node, cosq, &node));
  10549             port = node->gport;
  10550         }
  10551 
  10552         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) {
  10553             BCM_IF_ERROR_RETURN
  10554                 (_bcm_td2_cosq_node_get(unit, port, 0, NULL,
  10555                                         &local_port, NULL, &node));
  10556             if ((node->type == _BCM_TD2_NODE_VM_UCAST) ||
  10557                 (node->type == _BCM_TD2_NODE_SERVICE_UCAST)) {
  10558                 /* coverity[NEGATIVE_RETURNS: FALSE] */
  10559                 BCM_IF_ERROR_RETURN
  10560                     (counter_get(unit, local_port,
  10561                                      SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE_EXT, node->hw_index,
  10562                                      value));
  10563 
  10564             } else {
  10565                 BCM_IF_ERROR_RETURN
  10566                     (_bcm_td2_cosq_index_resolve
  10567                      (unit, port, cosq, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_UCAST,
  10568                       &local_port, &startq, NULL));
  10569                 /* coverity[NEGATIVE_RETURNS: FALSE] */
  10570                 BCM_IF_ERROR_RETURN
  10571                     (counter_get(unit, local_port,
  10572                                      SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE_UC, startq,
  10573                                      value));
  10574             }
  10575         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
  10576             BCM_IF_ERROR_RETURN
  10577                 (_bcm_td2_cosq_index_resolve
  10578                  (unit, port, cosq, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_MCAST,
  10579                   &local_port, &startq, NULL));
  10580             /* coverity[NEGATIVE_RETURNS: FALSE] */
  10581             BCM_IF_ERROR_RETURN
  10582                 (counter_get(unit, local_port,
  10583                                  SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE, startq,
  10584                                  value));
  10585         } else {
  10586             BCM_IF_ERROR_RETURN(_bcm_td2_cosq_localport_resolve(unit, port, &local_port));
  10587             BCM_IF_ERROR_RETURN(_bcm_td2_cosq_port_has_ets(unit, local_port));
  10588             COMPILER_64_ZERO(sum);
  10589             if (cosq == BCM_COS_INVALID) {
  10590                 from_cos = 0;
  10591                 to_cos = (IS_CPU_PORT(unit, local_port)) ? 
  10592                             NUM_CPU_COSQ(unit) - 1 : _TD2_NUM_COS(unit) - 1;
  10593             } else {
  10594                 from_cos = to_cos = cosq;
  10595             }
  10596 
  10597             for (ci = from_cos; ci <= to_cos; ci++) {
  10598                 if (!IS_CPU_PORT(unit, local_port)) {
  10599                     BCM_IF_ERROR_RETURN
  10600                         (_bcm_td2_cosq_index_resolve
  10601                             (unit, port, ci, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_UCAST,
  10602                             &local_port, &startq, &numq));
  10603                     for (i = 0; i < numq; i++) {
  10604                         /* coverity[NEGATIVE_RETURNS: FALSE] */
  10605                         BCM_IF_ERROR_RETURN
  10606                             (counter_get(unit, local_port,
  10607                                              SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE_UC,
  10608                                              startq + i, &value64));
  10609                         COMPILER_64_ADD_64(sum, value64);
  10610                     }
  10611                 }
  10612                 BCM_IF_ERROR_RETURN
  10613                     (_bcm_td2_cosq_index_resolve
  10614                      (unit, port, ci, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_MCAST,
  10615                       &local_port, &startq, &numq));
  10616                 for (i = 0; i < numq; i++) {
  10617                     /* coverity[NEGATIVE_RETURNS: FALSE] */
  10618                     BCM_IF_ERROR_RETURN
  10619                         (counter_get(unit, local_port,
  10620                                          SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE,
  10621                                          startq + i, &value64));
  10622                     COMPILER_64_ADD_64(sum, value64);
  10623                 }
  10624             }
  10625             *value = sum;
  10626         }
  10627         break;
  10628     case bcmCosqStatUCOutPackets:
  10629     case bcmCosqStatUCOutBytes:
  10630         if (BCM_GPORT_IS_SCHEDULER(port)) {
  10631             BCM_IF_ERROR_RETURN
  10632                 (_bcm_td2_cosq_node_get(unit, port, 0, NULL,
  10633                                         &local_port, NULL, &node));
  10634             BCM_IF_ERROR_RETURN(
  10635                    _bcm_td2_cosq_child_node_at_input(node, cosq, &node));
  10636             port = node->gport;
  10637         }
  10638 
  10639         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) {
  10640             BCM_IF_ERROR_RETURN
  10641                 (_bcm_td2_cosq_node_get(unit, port, 0, NULL,
  10642                                         &local_port, NULL, &node));
  10643             if ((node->type == _BCM_TD2_NODE_VM_UCAST) ||
  10644                 (node->type == _BCM_TD2_NODE_SERVICE_UCAST)) {
  10645                 soc_reg_t ctr_reg_uc = (stat == bcmCosqStatUCOutPackets) ?
  10646                      SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT_EXT :
  10647                      SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE_EXT;
  10648                 /* coverity[NEGATIVE_RETURNS: FALSE] */
  10649                 BCM_IF_ERROR_RETURN
  10650                     (counter_get(unit, local_port, ctr_reg_uc, node->hw_index, value));
  10651 
  10652             } else {
  10653                 soc_reg_t ctr_reg_uc = (stat == bcmCosqStatUCOutPackets) ?
  10654                      SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT_UC :
  10655                      SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE_UC;
  10656                 BCM_IF_ERROR_RETURN
  10657                     (_bcm_td2_cosq_index_resolve
  10658                      (unit, port, cosq, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_UCAST,
  10659                       &local_port, &startq, NULL));
  10660                 /* coverity[NEGATIVE_RETURNS: FALSE] */
  10661                 BCM_IF_ERROR_RETURN
  10662                     (counter_get(unit, local_port, ctr_reg_uc, startq, value));
  10663             }
  10664         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
  10665             return BCM_E_PARAM;
  10666         } else {
  10667             soc_reg_t ctr_reg_uc = (stat == bcmCosqStatUCOutPackets) ?
  10668                  SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT_UC :
  10669                  SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE_UC;
  10670             BCM_IF_ERROR_RETURN(_bcm_td2_cosq_localport_resolve(unit, port, &local_port));
  10671             BCM_IF_ERROR_RETURN(_bcm_td2_cosq_port_has_ets(unit, local_port));
  10672             COMPILER_64_ZERO(sum);
  10673             if (cosq == BCM_COS_INVALID) {
  10674                 from_cos = 0;
  10675                 to_cos = (IS_CPU_PORT(unit, local_port)) ?
  10676                             NUM_CPU_COSQ(unit) - 1 : _TD2_NUM_COS(unit) - 1;
  10677             } else {
  10678                 from_cos = to_cos = cosq;
  10679             }
  10680 
  10681             for (ci = from_cos; ci <= to_cos; ci++) {
  10682                 if (!IS_CPU_PORT(unit, local_port)) {
  10683                     BCM_IF_ERROR_RETURN
  10684                         (_bcm_td2_cosq_index_resolve
  10685                             (unit, port, ci, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_UCAST,
  10686                             &local_port, &startq, &numq));
  10687                     for (i = 0; i < numq; i++) {
  10688                         /* coverity[NEGATIVE_RETURNS: FALSE] */
  10689                         BCM_IF_ERROR_RETURN
  10690                             (counter_get(unit, local_port, ctr_reg_uc, startq + i, &value64));
  10691                         COMPILER_64_ADD_64(sum, value64);
  10692                     }
  10693                 }
  10694             }
  10695             *value = sum;
  10696         }
  10697         break;
  10698     case bcmCosqStatMCOutPackets:
  10699     case bcmCosqStatMCOutBytes:
  10700         if (BCM_GPORT_IS_SCHEDULER(port)) {
  10701             BCM_IF_ERROR_RETURN
  10702                 (_bcm_td2_cosq_node_get(unit, port, 0, NULL,
  10703                                         &local_port, NULL, &node));
  10704             BCM_IF_ERROR_RETURN(
  10705                    _bcm_td2_cosq_child_node_at_input(node, cosq, &node));
  10706             port = node->gport;
  10707         }
  10708 
  10709         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) {
  10710           return BCM_E_PARAM;
  10711         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
  10712             soc_reg_t ctr_reg_mc = ( stat == bcmCosqStatMCOutPackets ) ?
  10713                  SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT :
  10714                  SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE;
  10715             BCM_IF_ERROR_RETURN
  10716                 (_bcm_td2_cosq_index_resolve
  10717                  (unit, port, cosq, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_MCAST,
  10718                   &local_port, &startq, NULL));
  10719             /* coverity[NEGATIVE_RETURNS: FALSE] */
  10720             BCM_IF_ERROR_RETURN
  10721                 (counter_get(unit, local_port, ctr_reg_mc, startq, value));
  10722         } else {
  10723             soc_reg_t ctr_reg_mc = ( stat == bcmCosqStatMCOutPackets ) ?
  10724                  SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT :
  10725                  SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE;
  10726             BCM_IF_ERROR_RETURN(_bcm_td2_cosq_localport_resolve(unit, port, &local_port));
  10727             BCM_IF_ERROR_RETURN(_bcm_td2_cosq_port_has_ets(unit, local_port));
  10728             COMPILER_64_ZERO(sum);
  10729             if (cosq == BCM_COS_INVALID) {
  10730                 from_cos = 0;
  10731                 to_cos = (IS_CPU_PORT(unit, local_port)) ?
  10732                             NUM_CPU_COSQ(unit) - 1 : _TD2_NUM_COS(unit) - 1;
  10733             } else {
  10734                 from_cos = to_cos = cosq;
  10735             }
  10736 
  10737             for (ci = from_cos; ci <= to_cos; ci++) {
  10738                 BCM_IF_ERROR_RETURN
  10739                     (_bcm_td2_cosq_index_resolve
  10740                      (unit, port, ci, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_MCAST,
  10741                       &local_port, &startq, &numq));
  10742                 for (i = 0; i < numq; i++) {
  10743                     /* coverity[NEGATIVE_RETURNS: FALSE] */
  10744                     BCM_IF_ERROR_RETURN
  10745                         (counter_get(unit, local_port, ctr_reg_mc, startq + i, &value64));
  10746                     COMPILER_64_ADD_64(sum, value64);
  10747                 }
  10748             }
  10749             *value = sum;
  10750         }
  10751         break;
  10752     case bcmCosqStatIeee8021CnCpTransmittedCnms:
  10753         BCM_IF_ERROR_RETURN
  10754             (_bcm_td2_cosq_index_resolve
  10755                 (unit, port, cosq, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_UCAST,
  10756                  &local_port, &startq, NULL));  
  10757         BCM_IF_ERROR_RETURN
  10758             (counter_get(unit, local_port,
  10759                              SOC_COUNTER_NON_DMA_MMU_QCN_CNM, startq, value));
  10760         break;
  10761     case bcmCosqStatIngressPortPoolSharedBytesPeak:
  10762 
  10763         COMPILER_64_ZERO(sum);
  10764         BCM_IF_ERROR_RETURN
  10765             (_bcm_td2_cosq_ingress_sp_get(unit, port, cosq, 
  10766                                     &start_hw_index, &end_hw_index));
  10767 
  10768         BCM_IF_ERROR_RETURN(_bcm_td2_cosq_localport_resolve(unit, port, &local_port));
  10769         for (i = start_hw_index; i <= end_hw_index; i++) {
  10770                         /* coverity[NEGATIVE_RETURNS: FALSE] */
  10771             BCM_IF_ERROR_RETURN
  10772                     (counter_get(unit, local_port,
  10773                                              SOC_COUNTER_NON_DMA_POOL_PEAK,
  10774                                              i, &value64));
  10775             COMPILER_64_ADD_64(sum, value64);
  10776         }
  10777 
  10778         COMPILER_64_UMUL_32(sum, _BCM_TD2_BYTES_PER_CELL);
  10779         *value = sum;
  10780         break;
  10781     case bcmCosqStatIngressPortPoolSharedBytesCurrent:
  10782 
  10783         BCM_IF_ERROR_RETURN
  10784             (_bcm_td2_cosq_ingress_sp_get(unit, port, cosq, 
  10785                                     &start_hw_index, &end_hw_index));
  10786         BCM_IF_ERROR_RETURN(_bcm_td2_cosq_localport_resolve(unit, port, &local_port));
  10787 
  10788         COMPILER_64_ZERO(sum);
  10789         for (i = start_hw_index; i <= end_hw_index; i++) {
  10790                         /* coverity[NEGATIVE_RETURNS: FALSE] */
  10791             BCM_IF_ERROR_RETURN
  10792                  (counter_get(unit, local_port,
  10793                                              SOC_COUNTER_NON_DMA_POOL_CURRENT,
  10794                                              i, &value64));
  10795            COMPILER_64_ADD_64(sum, value64);
  10796         }
  10797 
  10798         COMPILER_64_UMUL_32(sum, _BCM_TD2_BYTES_PER_CELL);
  10799         *value = sum;
  10800         break;
  10801 
  10802     case bcmCosqStatIngressPortPGMinBytesPeak:
  10803 
  10804         BCM_IF_ERROR_RETURN
  10805             (_bcm_td2_cosq_ingress_pg_get(unit, port, cosq, 
  10806                                     &start_hw_index, &end_hw_index));
  10807         COMPILER_64_ZERO(sum);
  10808         BCM_IF_ERROR_RETURN(_bcm_td2_cosq_localport_resolve(unit, port, &local_port));
  10809 
  10810         for (i = start_hw_index; i <= end_hw_index; i++) {
  10811                         /* coverity[NEGATIVE_RETURNS: FALSE] */
  10812             BCM_IF_ERROR_RETURN
  10813                 (counter_get(unit, local_port,
  10814                                              SOC_COUNTER_NON_DMA_PG_MIN_PEAK,
  10815                                              i, &value64));
  10816             COMPILER_64_ADD_64(sum, value64);
  10817           }
  10818 
  10819         COMPILER_64_UMUL_32(sum, _BCM_TD2_BYTES_PER_CELL);
  10820         *value = sum;
  10821         break;
  10822     case bcmCosqStatIngressPortPGMinBytesCurrent:
  10823 
  10824         BCM_IF_ERROR_RETURN
  10825             (_bcm_td2_cosq_ingress_pg_get(unit, port, cosq,
  10826                                     &start_hw_index, &end_hw_index));
  10827         COMPILER_64_ZERO(sum);
  10828         BCM_IF_ERROR_RETURN(_bcm_td2_cosq_localport_resolve(unit, port, &local_port));
  10829 
  10830         for (i = start_hw_index; i <= end_hw_index; i++) {
  10831                         /* coverity[NEGATIVE_RETURNS: FALSE] */
  10832             BCM_IF_ERROR_RETURN
  10833                  (counter_get(unit, local_port,
  10834                                              SOC_COUNTER_NON_DMA_PG_MIN_CURRENT,
  10835                                              i, &value64));
  10836             COMPILER_64_ADD_64(sum, value64);
  10837         }
  10838 
  10839         COMPILER_64_UMUL_32(sum, _BCM_TD2_BYTES_PER_CELL);
  10840         *value = sum;
  10841         break;     
  10842 
  10843     case bcmCosqStatIngressPortPGSharedBytesPeak:
  10844 
  10845         BCM_IF_ERROR_RETURN
  10846            (_bcm_td2_cosq_ingress_pg_get(unit, port, cosq,
  10847                                     &start_hw_index, &end_hw_index));
  10848         COMPILER_64_ZERO(sum);
  10849         BCM_IF_ERROR_RETURN(_bcm_td2_cosq_localport_resolve(unit, port, &local_port));
  10850 
  10851         for (i = start_hw_index; i <= end_hw_index; i++) {
  10852                         /* coverity[NEGATIVE_RETURNS: FALSE] */
  10853             BCM_IF_ERROR_RETURN
  10854                 (counter_get(unit, local_port,
  10855                                              SOC_COUNTER_NON_DMA_PG_SHARED_PEAK,
  10856                                              i, &value64));
  10857             COMPILER_64_ADD_64(sum, value64);
  10858         }
  10859 
  10860         COMPILER_64_UMUL_32(sum, _BCM_TD2_BYTES_PER_CELL);
  10861         *value = sum;
  10862         break;
  10863 
  10864     case bcmCosqStatIngressPortPGSharedBytesCurrent:
  10865 
  10866         BCM_IF_ERROR_RETURN
  10867             (_bcm_td2_cosq_ingress_pg_get(unit, port, cosq,
  10868                                     &start_hw_index, &end_hw_index));
  10869         BCM_IF_ERROR_RETURN(_bcm_td2_cosq_localport_resolve(unit, port, &local_port));
  10870         COMPILER_64_ZERO(sum);
  10871 
  10872         for (i = start_hw_index; i <= end_hw_index; i++) {
  10873                         /* coverity[NEGATIVE_RETURNS: FALSE] */
  10874             BCM_IF_ERROR_RETURN
  10875                 (counter_get(unit, local_port,
  10876                                           SOC_COUNTER_NON_DMA_PG_SHARED_CURRENT,
  10877                                              i, &value64));
  10878             COMPILER_64_ADD_64(sum, value64);
  10879         }
  10880         COMPILER_64_UMUL_32(sum, _BCM_TD2_BYTES_PER_CELL);
  10881         *value = sum;
  10882 
  10883         break;
  10884 
  10885     case bcmCosqStatIngressPortPGHeadroomBytesPeak:
  10886 
  10887         BCM_IF_ERROR_RETURN
  10888                (_bcm_td2_cosq_ingress_pg_get(unit, port, cosq,
  10889                                     &start_hw_index, &end_hw_index));
  10890         BCM_IF_ERROR_RETURN(_bcm_td2_cosq_localport_resolve(unit, port, &local_port));
  10891         COMPILER_64_ZERO(sum);
  10892 
  10893         for (i = start_hw_index; i <= end_hw_index; i++) {
  10894                         /* coverity[NEGATIVE_RETURNS: FALSE] */
  10895             BCM_IF_ERROR_RETURN
  10896                 (counter_get(unit, local_port,
  10897                                        SOC_COUNTER_NON_DMA_PG_HDRM_PEAK,
  10898                                        i, &value64));
  10899             COMPILER_64_ADD_64(sum, value64);
  10900         }
  10901         COMPILER_64_UMUL_32(sum, _BCM_TD2_BYTES_PER_CELL);
  10902         *value = sum;
  10903 
  10904         break;
  10905 
  10906     case bcmCosqStatIngressPortPGHeadroomBytesCurrent:
  10907 
  10908         BCM_IF_ERROR_RETURN
  10909             (_bcm_td2_cosq_ingress_pg_get(unit, port, cosq,
  10910                                     &start_hw_index, &end_hw_index));
  10911 
  10912         BCM_IF_ERROR_RETURN(_bcm_td2_cosq_localport_resolve(unit, port, &local_port));
  10913         COMPILER_64_ZERO(sum);
  10914         for (i = start_hw_index; i <= end_hw_index; i++) {
  10915                         /* coverity[NEGATIVE_RETURNS: FALSE] */
  10916             BCM_IF_ERROR_RETURN
  10917                  (counter_get(unit, local_port,
  10918                             SOC_COUNTER_NON_DMA_PG_HDRM_CURRENT,
  10919                                 i, &value64));
  10920             COMPILER_64_ADD_64(sum, value64);
  10921         }
  10922         COMPILER_64_UMUL_32(sum, _BCM_TD2_BYTES_PER_CELL);
  10923         *value = sum;
  10924 
  10925         break;
  10926 
  10927     case bcmCosqStatEgressMCQueueBytesPeak:
  10928         if (BCM_GPORT_IS_SCHEDULER(port)) {
  10929             BCM_IF_ERROR_RETURN
  10930                 (_bcm_td2_cosq_node_get(unit, port, 0, NULL, 
  10931                                         &local_port, NULL, &node));
  10932             if (node->level != SOC_TD2_NODE_LVL_ROOT) {
  10933                 return BCM_E_PARAM;
  10934             }
  10935 
  10936             BCM_IF_ERROR_RETURN(
  10937                    _bcm_td2_cosq_child_node_at_input(node, cosq, &node));
  10938             port = node->gport;
  10939         }
  10940 
  10941         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) {
  10942             return BCM_E_PARAM;
  10943         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
  10944             BCM_IF_ERROR_RETURN
  10945                 (_bcm_td2_cosq_index_resolve
  10946                  (unit, port, cosq, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_MCAST,
  10947                   &local_port, &startq, NULL));
  10948             /* coverity[NEGATIVE_RETURNS: FALSE] */
  10949             BCM_IF_ERROR_RETURN
  10950                 (counter_get(unit, local_port,
  10951                                  SOC_COUNTER_NON_DMA_QUEUE_PEAK, startq,
  10952                                  value));
  10953             COMPILER_64_UMUL_32(*value, _BCM_TD2_BYTES_PER_CELL);
  10954         } else {
  10955             BCM_IF_ERROR_RETURN(_bcm_td2_cosq_localport_resolve(unit, port, &local_port));
  10956             BCM_IF_ERROR_RETURN(_bcm_td2_cosq_port_has_ets(unit, port));
  10957             COMPILER_64_ZERO(sum);
  10958             if (cosq == BCM_COS_INVALID) {
  10959                 from_cos = 0;
  10960                 to_cos = (IS_CPU_PORT(unit, local_port)) ?
  10961                             NUM_CPU_COSQ(unit) - 1 : _TD2_NUM_COS(unit) - 1;
  10962             } else {
  10963                 from_cos = to_cos = cosq;
  10964             }
  10965 
  10966             for (ci = from_cos; ci <= to_cos; ci++) {
  10967                     BCM_IF_ERROR_RETURN
  10968                         (_bcm_td2_cosq_index_resolve
  10969                             (unit, port, ci, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_MCAST,
  10970                              &local_port, &startq, &numq));
  10971                     for (i = 0; i < numq; i++) {
  10972                         /* coverity[NEGATIVE_RETURNS: FALSE] */
  10973                         BCM_IF_ERROR_RETURN
  10974                             (counter_get(unit, local_port,
  10975                                              SOC_COUNTER_NON_DMA_QUEUE_PEAK,
  10976                                              startq + i, &value64));
  10977                         COMPILER_64_ADD_64(sum, value64);
  10978                     }
  10979             }
  10980             COMPILER_64_UMUL_32(sum, _BCM_TD2_BYTES_PER_CELL);
  10981             *value = sum;
  10982         }
  10983         break;
  10984 
  10985     case bcmCosqStatEgressUCQueueBytesPeak:
  10986         if (BCM_GPORT_IS_SCHEDULER(port)) {
  10987             BCM_IF_ERROR_RETURN
  10988                 (_bcm_td2_cosq_node_get(unit, port, 0, NULL, 
  10989                                         &local_port, NULL, &node));
  10990             if (node->level != SOC_TD2_NODE_LVL_ROOT) {
  10991                 return BCM_E_PARAM;
  10992             }
  10993 
  10994             BCM_IF_ERROR_RETURN(
  10995                    _bcm_td2_cosq_child_node_at_input(node, cosq, &node));
  10996             port = node->gport;
  10997         }
  10998 
  10999         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) {
  11000             BCM_IF_ERROR_RETURN
  11001                 (_bcm_td2_cosq_index_resolve
  11002                  (unit, port, cosq, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_UCAST,
  11003                   &local_port, &startq, NULL));
  11004             /* coverity[NEGATIVE_RETURNS: FALSE] */
  11005             BCM_IF_ERROR_RETURN
  11006                 (counter_get(unit, local_port,
  11007                                  SOC_COUNTER_NON_DMA_UC_QUEUE_PEAK, startq,
  11008                                  value));
  11009             COMPILER_64_UMUL_32(*value, _BCM_TD2_BYTES_PER_CELL);
  11010         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
  11011             return BCM_E_PARAM;
  11012         } else {
  11013             BCM_IF_ERROR_RETURN(_bcm_td2_cosq_localport_resolve(unit, port, &local_port));
  11014             BCM_IF_ERROR_RETURN(_bcm_td2_cosq_port_has_ets(unit, port));
  11015             COMPILER_64_ZERO(sum);
  11016             if (cosq == BCM_COS_INVALID) {
  11017                 from_cos = 0;
  11018                 to_cos = (IS_CPU_PORT(unit, local_port)) ?
  11019                             NUM_CPU_COSQ(unit) - 1 : _TD2_NUM_COS(unit) - 1;
  11020             } else {
  11021                 from_cos = to_cos = cosq;
  11022             }
  11023 
  11024             if (IS_CPU_PORT(unit, local_port)) {
  11025                 return BCM_E_PARAM;
  11026             }
  11027             for (ci = from_cos; ci <= to_cos; ci++) {
  11028                 BCM_IF_ERROR_RETURN
  11029                       (_bcm_td2_cosq_index_resolve
  11030                             (unit, port, ci, _BCM_TD2_COSQ_INDEX_STYLE_EGR_PERQ_UCAST,
  11031                              &local_port, &startq, &numq));
  11032                 for (i = 0; i < numq; i++) {
  11033                         /* coverity[NEGATIVE_RETURNS: FALSE] */
  11034                      BCM_IF_ERROR_RETURN
  11035                             (counter_get(unit, local_port,
  11036                                              SOC_COUNTER_NON_DMA_UC_QUEUE_PEAK,
  11037                                              startq + i, &value64));
  11038                      COMPILER_64_ADD_64(sum, value64);
  11039                 }
  11040             }
  11041             COMPILER_64_UMUL_32(sum, _BCM_TD2_BYTES_PER_CELL);
  11042             *value = sum;
  11043         }
  11044         break;
  11045 
  11046     case bcmCosqStatHighPriDroppedPackets:
  11047         if (cosq != BCM_COS_INVALID) {
  11048             return BCM_E_UNAVAIL;
  11049         }
  11050         BCM_IF_ERROR_RETURN
  11051             (_bcm_td2_cosq_localport_resolve(unit, port, &local_port));
  11052         BCM_IF_ERROR_RETURN
  11053             (id = _port_l2c_mapping(unit,local_port,bcmCosqStatHighPriDroppedPackets,&xlp_port));
  11054         BCM_IF_ERROR_RETURN
  11055             (counter_get(unit, local_port, id, xlp_port, value));
  11056         break;
  11057     case bcmCosqStatLowPriDroppedPackets:
  11058         if (cosq != BCM_COS_INVALID) {
  11059             return BCM_E_UNAVAIL;
  11060         }
  11061         
  11062         BCM_IF_ERROR_RETURN
  11063             (_bcm_td2_cosq_localport_resolve(unit, port, &local_port));
  11064         BCM_IF_ERROR_RETURN
  11065             (id = _port_l2c_mapping(unit,local_port,bcmCosqStatLowPriDroppedPackets,&xlp_port));
  11066         BCM_IF_ERROR_RETURN
  11067             (counter_get(unit, local_port, id, xlp_port, value));
  11068         break;
  11069     case bcmCosqStatHighPriDroppedBytes:
  11070         if (cosq != BCM_COS_INVALID) {
  11071             return BCM_E_UNAVAIL;
  11072         }
  11073         
  11074         BCM_IF_ERROR_RETURN
  11075             (_bcm_td2_cosq_localport_resolve(unit, port, &local_port));
  11076         BCM_IF_ERROR_RETURN
  11077             (id = _port_l2c_mapping(unit,local_port,bcmCosqStatHighPriDroppedBytes,&xlp_port));
  11078         BCM_IF_ERROR_RETURN
  11079             (counter_get(unit, local_port, id, xlp_port, value));
  11080         break;
  11081     case bcmCosqStatLowPriDroppedBytes:
  11082         if (cosq != BCM_COS_INVALID) {
  11083             return BCM_E_UNAVAIL;
  11084         }
  11085         
  11086         BCM_IF_ERROR_RETURN
  11087             (_bcm_td2_cosq_localport_resolve(unit, port, &local_port));
  11088         BCM_IF_ERROR_RETURN
  11089             (id = _port_l2c_mapping(unit,local_port,bcmCosqStatLowPriDroppedBytes,&xlp_port));
  11090         BCM_IF_ERROR_RETURN
  11091             (counter_get(unit, local_port, id, xlp_port, value));
  11092         break;
  11093     case bcmCosqStatGlobalHeadroomBytes0Peak:
  11094         BCM_IF_ERROR_RETURN
  11095             (counter_get(unit, -1,
  11096                              SOC_COUNTER_NON_DMA_COSQ_GLOBAL_HDR_COUNT_X_PEAK,
  11097                              0, value));
  11098         COMPILER_64_UMUL_32(*value, _BCM_TD2_BYTES_PER_CELL);
  11099         break;
  11100     case bcmCosqStatGlobalHeadroomBytes0Current:
  11101         BCM_IF_ERROR_RETURN
  11102             (counter_get(unit, -1,
  11103                              SOC_COUNTER_NON_DMA_COSQ_GLOBAL_HDR_COUNT_X_CURRENT,
  11104                              0, value));
  11105         COMPILER_64_UMUL_32(*value, _BCM_TD2_BYTES_PER_CELL);
  11106         break;
  11107     case bcmCosqStatGlobalHeadroomBytes1Peak:
  11108          BCM_IF_ERROR_RETURN
  11109             (counter_get(unit, -1,
  11110                              SOC_COUNTER_NON_DMA_COSQ_GLOBAL_HDR_COUNT_Y_PEAK,
  11111                             0, value));
  11112         COMPILER_64_UMUL_32(*value, _BCM_TD2_BYTES_PER_CELL);
  11113         break;
  11114     case bcmCosqStatGlobalHeadroomBytes1Current:
  11115         BCM_IF_ERROR_RETURN
  11116             (counter_get(unit, -1,
  11117                              SOC_COUNTER_NON_DMA_COSQ_GLOBAL_HDR_COUNT_Y_CURRENT,
  11118                              0, value));
  11119         COMPILER_64_UMUL_32(*value, _BCM_TD2_BYTES_PER_CELL);
  11120         break;
  11121 
  11122     case bcmCosqStatEgressPortPoolTotalBytesCurrent:
  11123         if (cosq != BCM_COS_INVALID) {
  11124             return BCM_E_UNAVAIL;
  11125         }
  11126         BCM_IF_ERROR_RETURN
  11127             (_bcm_td2_cosq_localport_resolve(unit, port, &local_port));
  11128         BCM_IF_ERROR_RETURN
  11129             (soc_reg32_get(unit, MMU_THDM_DB_PORTSP_TOTAL_COUNTr, local_port, 0, &rval));
  11130         value32 = soc_reg_field_get(unit, MMU_THDM_DB_PORTSP_TOTAL_COUNTr, rval, COUNTf);
  11131         COMPILER_64_ADD_32(*value, value32);
  11132         COMPILER_64_UMUL_32(*value, _BCM_TD2_BYTES_PER_CELL);
  11133         break;
  11134 
  11135     case bcmCosqStatEgressPortPoolSharedBytesCurrent:
  11136         BCM_IF_ERROR_RETURN
  11137             (_bcm_td2_cosq_index_resolve(unit, port, cosq,
  11138                                         _BCM_TD2_COSQ_INDEX_STYLE_EGR_POOL,
  11139                                         &local_port, &pool, NULL));
  11140         BCM_IF_ERROR_RETURN
  11141             (soc_reg32_get(unit, MMU_THDM_DB_PORTSP_SHARED_COUNTr, local_port, pool, &rval));
  11142         value32 = soc_reg_field_get(unit, MMU_THDM_DB_PORTSP_SHARED_COUNTr, rval, COUNTf);
  11143         COMPILER_64_ADD_32(*value, value32);
  11144         COMPILER_64_UMUL_32(*value, _BCM_TD2_BYTES_PER_CELL);
  11145         break;
  11146 
  11147     case bcmCosqStatEgressMCQueueMinBytesCurrent:
  11148     case bcmCosqStatEgressMCQueueBytesCurrent:
  11149         if (stat == bcmCosqStatEgressMCQueueMinBytesCurrent) {
  11150             field = MIN_COUNTf;
  11151         } else if (stat == bcmCosqStatEgressMCQueueBytesCurrent) {
  11152             field = SHARED_COUNTf;
  11153         }
  11154         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) {
  11155             return BCM_E_PARAM;
  11156         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
  11157             BCM_IF_ERROR_RETURN
  11158                 (_bcm_td2_cosq_index_resolve(unit, port, cosq,
  11159                                              _BCM_TD2_COSQ_INDEX_STYLE_MCAST_QUEUE,
  11160                                              &local_port, &startq, NULL));
  11161 
  11162             mem = SOC_TD2_PMEM(unit, local_port, MMU_THDM_DB_QUEUE_COUNT_0m,
  11163                                MMU_THDM_DB_QUEUE_COUNT_1m);
  11164             startq -= 1480; /* MC queues comes after UC queues */
  11165 
  11166             BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL,
  11167                                      startq, entry));
  11168             value32 = soc_mem_field32_get(unit, mem, entry,  field);
  11169             COMPILER_64_ADD_32(*value, value32);
  11170             COMPILER_64_UMUL_32(*value, _BCM_TD2_BYTES_PER_CELL);
  11171         } else {
  11172             BCM_IF_ERROR_RETURN(_bcm_td2_cosq_localport_resolve(unit, port, &local_port));
  11173             BCM_IF_ERROR_RETURN(_bcm_td2_cosq_port_has_ets(unit, port));
  11174             COMPILER_64_ZERO(sum);
  11175             sum32 =0;
  11176             if (cosq == BCM_COS_INVALID) {
  11177                 from_cos = 0;
  11178                 to_cos = (IS_CPU_PORT(unit, local_port)) ?
  11179                             NUM_CPU_COSQ(unit) - 1 : _TD2_NUM_COS(unit) - 1;
  11180             } else {
  11181                 from_cos = to_cos = cosq;
  11182             }
  11183 
  11184             if (local_port < 0) {
  11185                 return BCM_E_PORT;
  11186             }
  11187 
  11188             mem = SOC_TD2_PMEM(unit, local_port, MMU_THDM_DB_QUEUE_COUNT_0m,
  11189                                MMU_THDM_DB_QUEUE_COUNT_1m);
  11190 
  11191             for (ci = from_cos; ci <= to_cos; ci++) {
  11192                 BCM_IF_ERROR_RETURN
  11193                     (_bcm_td2_cosq_index_resolve
  11194                      (unit, local_port, ci, _BCM_TD2_COSQ_INDEX_STYLE_MCAST_QUEUE,
  11195                       NULL, &startq, NULL));
  11196                 startq -= 1480; /* MC queues comes after UC queues */
  11197                 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL,
  11198                                          startq, entry));
  11199                 sum32 += soc_mem_field32_get(unit, mem, entry, field);
  11200             }
  11201             COMPILER_64_ADD_32(sum, sum32);
  11202             COMPILER_64_UMUL_32(sum, _BCM_TD2_BYTES_PER_CELL);
  11203             *value = sum;
  11204         }
  11205         break;
  11206 
  11207     case bcmCosqStatEgressUCQueuePortBytesCurrent:
  11208         BCM_IF_ERROR_RETURN
  11209             (_bcm_td2_cosq_index_resolve(unit, port, cosq,
  11210                                          _BCM_TD2_COSQ_INDEX_STYLE_UC_EGR_POOL,
  11211                                          &local_port, &pool, NULL));
  11212 
  11213         mem = SOC_TD2_PMEM(unit, local_port, MMU_THDU_XPIPE_COUNTER_PORTm,
  11214                    MMU_THDU_YPIPE_COUNTER_PORTm);
  11215 
  11216         midx = SOC_TD2_MMU_PIPED_MEM_INDEX(unit, local_port, mem, pool);
  11217 
  11218         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL,
  11219                                  midx, entry));
  11220         value32 = soc_mem_field32_get(unit, mem, entry, SHARED_COUNTf);
  11221 
  11222         COMPILER_64_ADD_32(*value, value32);
  11223         COMPILER_64_UMUL_32(*value, _BCM_TD2_BYTES_PER_CELL);
  11224         break;
  11225 
  11226     case bcmCosqStatEgressQgroupMinBytesCurrent:
  11227     case bcmCosqStatEgressQgroupBytesCurrent:
  11228         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) {
  11229             BCM_IF_ERROR_RETURN
  11230                 (_bcm_td2_cosq_index_resolve(unit, port, cosq,
  11231                                              _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE,
  11232                                              &local_port, &startq, NULL));
  11233         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
  11234             return BCM_E_PARAM;
  11235         } else {
  11236             BCM_IF_ERROR_RETURN
  11237                 (_bcm_td2_cosq_localport_resolve(unit, port, &local_port));
  11238             if (local_port < 0) {
  11239                 return BCM_E_PORT;
  11240             }
  11241             BCM_IF_ERROR_RETURN
  11242                 (_bcm_td2_cosq_index_resolve(unit, local_port, cosq,
  11243                                              _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE,
  11244                                              NULL, &startq, NULL));
  11245         }
  11246 
  11247         mem = SOC_TD2_PMEM(unit, local_port, MMU_THDU_XPIPE_Q_TO_QGRP_MAPm,
  11248                            MMU_THDU_YPIPE_Q_TO_QGRP_MAPm);
  11249         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  11250         valid = soc_mem_field32_get(unit, mem, entry, QGROUP_VALIDf);
  11251         if (!valid) {
  11252             LOG_INFO(BSL_LS_BCM_COSQ,
  11253                      (BSL_META_U(unit,
  11254                      "UCQ doesn't associate with a queue group!\n")));
  11255             return BCM_E_UNAVAIL;
  11256         }
  11257 
  11258         startq = soc_mem_field32_get(unit, mem, entry, QGROUPf);
  11259 
  11260         mem = SOC_TD2_PMEM(unit, local_port, MMU_THDU_XPIPE_COUNTER_QGROUPm,
  11261                            MMU_THDU_YPIPE_COUNTER_QGROUPm);
  11262         if (stat == bcmCosqStatEgressQgroupMinBytesCurrent) {
  11263             field = MIN_COUNTf;
  11264         } else if (stat == bcmCosqStatEgressQgroupBytesCurrent) {
  11265             field = SHARED_COUNTf;
  11266         }
  11267 
  11268         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  11269         value32 = soc_mem_field32_get(unit, mem, entry, field);
  11270 
  11271         COMPILER_64_ADD_32(*value, value32);
  11272         COMPILER_64_UMUL_32(*value, _BCM_TD2_BYTES_PER_CELL);
  11273         break;
  11274 
  11275     case bcmCosqStatEgressUCQueueMinBytesCurrent:
  11276     case bcmCosqStatEgressUCQueueBytesCurrent:
  11277         if (stat == bcmCosqStatEgressUCQueueMinBytesCurrent) {
  11278             field = MIN_COUNTf;
  11279         } else if (stat == bcmCosqStatEgressUCQueueBytesCurrent) {
  11280             field = SHARED_COUNTf;
  11281         }
  11282         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) {
  11283             BCM_IF_ERROR_RETURN
  11284                 (_bcm_td2_cosq_index_resolve(unit, port, cosq,
  11285                                              _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE,
  11286                                              &local_port, &startq, NULL));
  11287 
  11288             mem = SOC_TD2_PMEM(unit, local_port, MMU_THDU_XPIPE_COUNTER_QUEUEm,
  11289                        MMU_THDU_YPIPE_COUNTER_QUEUEm);
  11290             BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL,
  11291                                      startq, entry));
  11292             value32 = soc_mem_field32_get(unit, mem, entry, field);
  11293             COMPILER_64_ADD_32(*value, value32);
  11294             COMPILER_64_UMUL_32(*value, _BCM_TD2_BYTES_PER_CELL);
  11295         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
  11296             return BCM_E_PARAM;
  11297         } else {
  11298             BCM_IF_ERROR_RETURN(_bcm_td2_cosq_localport_resolve(unit, port, &local_port));
  11299             BCM_IF_ERROR_RETURN(_bcm_td2_cosq_port_has_ets(unit, port));
  11300 
  11301             if (IS_CPU_PORT(unit, local_port)) {
  11302                 return BCM_E_PARAM;
  11303             }
  11304             COMPILER_64_ZERO(sum);
  11305             sum32 =0;
  11306             if (cosq == BCM_COS_INVALID) {
  11307                 from_cos = 0;
  11308                 to_cos = (IS_CPU_PORT(unit, local_port)) ?
  11309                             NUM_CPU_COSQ(unit) - 1 : _TD2_NUM_COS(unit) - 1;
  11310             } else {
  11311                 from_cos = to_cos = cosq;
  11312             }
  11313 
  11314             if (local_port < 0) {
  11315                 return BCM_E_PORT;
  11316             }
  11317             mem = SOC_TD2_PMEM(unit, local_port, MMU_THDU_XPIPE_COUNTER_QUEUEm,
  11318                                MMU_THDU_YPIPE_COUNTER_QUEUEm);
  11319             for (ci = from_cos; ci <= to_cos; ci++) {
  11320                 BCM_IF_ERROR_RETURN
  11321                     (_bcm_td2_cosq_index_resolve
  11322                      (unit, local_port, ci, _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE,
  11323                       NULL, &startq, NULL));
  11324                 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL,
  11325                                          startq, entry));
  11326                 sum32 += soc_mem_field32_get(unit, mem, entry, field);
  11327             }
  11328             COMPILER_64_ADD_32(sum, sum32);
  11329             COMPILER_64_UMUL_32(sum, _BCM_TD2_BYTES_PER_CELL);
  11330             *value = sum;
  11331         }
  11332         break;
  11333 
  11334     default:
  11335         return BCM_E_PARAM;
  11336     }
  11337 
  11338     return BCM_E_NONE;
  11339 }
  11340 
  11341 /*
  11342  * Function:
  11343  *     _bcm_td2_cosq_quantize_table_set
  11344  * Purpose:
  11345  *     Generate quantized feedback lookup table
  11346  * Parameters:
  11347  *     unit          - (IN) unit number
  11348  *     profile_index - (IN) profile index
  11349  *     weight_code   - (IN) weight encoding
  11350  *     set_point     - (IN) queue size set point
  11351  *     active_offset - (OUT) most significant non-zero bit position
  11352  * Returns:
  11353  *     BCM_E_XXX
  11354  * Notes:
  11355  *     The formular to quantize feedback value is:
  11356  *     quantized_feedbad = celling(feedback / max_feedback * 63)
  11357  *         where max_feedback = (2 * cpW + 1) * cpQsp
  11358  *         cpW is feedback weight
  11359  *         cpQsp is queue size set point
  11360  */
  11361 STATIC int
  11362 _bcm_td2_cosq_quantize_table_set(int unit, int profile_index, int weight_code,
  11363                                 int set_point, int *active_offset)
  11364 {
  11365     int ref_count;
  11366     int weight_x_4, feedback, max_feedback, quantized_feedback, shift;
  11367     int base_index, index;
  11368 
  11369     /* weight = 2 ** (weight_code - 2) e.g. 0 for 1/4, 1 for 1/2, ...  */
  11370     weight_x_4 = 1 << weight_code;
  11371     max_feedback = ((2 * weight_x_4 + 4) * set_point + 3) / 4;
  11372     shift = 0;
  11373     while ((max_feedback >> shift) > 127) {
  11374         shift++;
  11375     }
  11376 
  11377     BCM_IF_ERROR_RETURN
  11378         (soc_profile_reg_ref_count_get(unit, _bcm_td2_feedback_profile[unit],
  11379                                        profile_index, &ref_count));
  11380 
  11381     /*
  11382      * Hardware use lookup table to find quantized feedback in order to avoid
  11383      * division, use most significant 7-bit of feedback value as lookup table
  11384      * index to find quantized_feedback value
  11385      */
  11386     if (ref_count == 1) {
  11387         base_index = profile_index << 7;
  11388         for (index = 0; index < 128; index++) {
  11389             feedback = index << shift;
  11390             if (feedback > max_feedback) {
  11391                 quantized_feedback = 63;
  11392             } else {
  11393                 quantized_feedback = (feedback * 63 + max_feedback - 1) /
  11394                     max_feedback;
  11395             }
  11396             BCM_IF_ERROR_RETURN
  11397                 (soc_mem_field32_modify(unit, MMU_QCN_QFBTBm,
  11398                                         base_index  + index, CPQ_QNTZFBf,
  11399                                         quantized_feedback));
  11400         }
  11401     }
  11402 
  11403     *active_offset = shift + 6;
  11404 
  11405     return BCM_E_NONE;
  11406 }
  11407 
  11408 
  11409 STATIC int
  11410 _bcm_td2_cosq_sample_int_table_set(int unit, int min, int max,
  11411                                   uint32 *profile_index)
  11412 {
  11413     mmu_qcn_sitb_entry_t sitb_entries[64];
  11414     void *entries[1];
  11415     int i, j, center, inc, value, index;
  11416 
  11417     sal_memset(sitb_entries, 0, sizeof(sitb_entries));
  11418     entries[0] = &sitb_entries;
  11419     for (i = 0; i < 8; i++) {
  11420         center = max - (max - min) * i / 7;
  11421         inc = (max - min) / 7 / 8;
  11422         for (j = 0; j < 8; j++, inc = -inc) {
  11423             index = i * 8 + j;
  11424             value = center + (j + 1) / 2 * inc;
  11425             if (value > 255) {
  11426                 value = 255;
  11427             } else if (value < 1) {
  11428                 value = 1;
  11429             }
  11430             soc_mem_field32_set(unit, MMU_QCN_SITBm, &sitb_entries[index],
  11431                                 CPQ_SIf, value);
  11432         }
  11433     }
  11434 
  11435     return soc_profile_mem_add(unit, _bcm_td2_sample_int_profile[unit], entries,
  11436                                64, (uint32 *)profile_index);
  11437 }
  11438 
  11439 /*
  11440  * Function:
  11441  *     bcm_td2_cosq_congestion_queue_set
  11442  * Purpose:
  11443  *     Enable/Disable a cos queue as congestion managed queue
  11444  * Parameters:
  11445  *     unit          - (IN) unit number
  11446  *     port          - (IN) port number or GPORT identifier
  11447  *     cosq          - (IN) COS queue number
  11448  *     index         - (IN) congestion managed queue index
  11449  * Returns:
  11450  *     BCM_E_XXX
  11451  */
  11452 int
  11453 bcm_td2_cosq_congestion_queue_set(int unit, bcm_port_t port,
  11454                                  bcm_cos_queue_t cosq, int index)
  11455 {
  11456     bcm_port_t local_port;
  11457     uint32 rval;
  11458     uint64 rval64, *rval64s[1];
  11459     mmu_qcn_enable_entry_t enable_entry;
  11460     int active_offset, qindex;
  11461     uint32 profile_index, sample_profile_index;
  11462     int weight_code, set_point;
  11463     soc_mem_t mem;
  11464     int pipe;
  11465 
  11466     if (cosq < 0 || cosq >= _TD2_NUM_COS(unit)) {
  11467         return BCM_E_PARAM;
  11468     }
  11469 
  11470     if ((index < -1) || (index >= 1480)) {
  11471         return BCM_E_PARAM;
  11472     }
  11473 
  11474     BCM_IF_ERROR_RETURN
  11475         (_bcm_td2_cosq_index_resolve(unit, port, cosq,
  11476                                     _BCM_TD2_COSQ_INDEX_STYLE_QCN,
  11477                                     &local_port, &qindex, NULL));
  11478     
  11479     pipe = _BCM_TD2_PORT_TO_PIPE(unit, local_port);
  11480     if (pipe) {
  11481         mem = MMU_QCN_ENABLE_1m;    
  11482     } else {
  11483         mem = MMU_QCN_ENABLE_0m;
  11484     }
  11485     
  11486 
  11487     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ANY, 
  11488                         qindex, &enable_entry));
  11489     if (index == -1) {
  11490         if (!soc_mem_field32_get(unit, mem, &enable_entry, CPQ_ENf)) {
  11491             return BCM_E_NONE;
  11492         }
  11493 
  11494         index = soc_mem_field32_get(unit, mem, &enable_entry, CPQ_PROFILE_INDEXf);
  11495         soc_mem_field32_set(unit, mem, &enable_entry, CPQ_ENf, 0);
  11496         BCM_IF_ERROR_RETURN
  11497             (soc_mem_write(unit, mem, MEM_BLOCK_ANY, qindex, &enable_entry));
  11498 
  11499         profile_index = soc_mem_field32_get(unit, mem, &enable_entry, EQTB_INDEXf);
  11500 
  11501         BCM_IF_ERROR_RETURN
  11502             (soc_profile_reg_delete(unit, _bcm_td2_feedback_profile[unit],
  11503                                     profile_index));
  11504 
  11505         profile_index =
  11506             soc_mem_field32_get(unit, mem, &enable_entry, SITB_SELf);
  11507 
  11508         BCM_IF_ERROR_RETURN
  11509             (soc_profile_mem_delete(unit, _bcm_td2_sample_int_profile[unit],
  11510                                 profile_index * 64));
  11511     } else {
  11512         if (soc_mem_field32_get(unit, mem, &enable_entry, CPQ_ENf)) {
  11513             return BCM_E_BUSY;
  11514         }
  11515 
  11516         /* Use hardware reset value as default quantize setting */
  11517         weight_code = 3;
  11518         set_point = 0x96;
  11519         rval = 0;
  11520         soc_reg_field_set(unit, MMU_QCN_CPQ_SEQr, &rval, CPWf, weight_code);
  11521         soc_reg_field_set(unit, MMU_QCN_CPQ_SEQr, &rval, CPQEQf, set_point);
  11522         COMPILER_64_SET(rval64, 0, rval);
  11523         rval64s[0] = &rval64;
  11524         BCM_IF_ERROR_RETURN
  11525             (soc_profile_reg_add(unit, _bcm_td2_feedback_profile[unit],
  11526                                  rval64s, 1, (uint32 *)&profile_index));
  11527 
  11528         /* Update quantized feedback calculation lookup table */
  11529         BCM_IF_ERROR_RETURN
  11530             (_bcm_td2_cosq_quantize_table_set(unit, profile_index, weight_code,
  11531                                              set_point, &active_offset));
  11532 
  11533         /* Pick some sample interval */
  11534         BCM_IF_ERROR_RETURN
  11535             (_bcm_td2_cosq_sample_int_table_set(unit, 13, 127,
  11536                                                &sample_profile_index));
  11537 
  11538         soc_mem_field32_set(unit, mem, &enable_entry,
  11539                             QNTZ_ACT_OFFSETf, active_offset);
  11540 
  11541         soc_mem_field32_set(unit, mem, &enable_entry,
  11542                             SITB_SELf, sample_profile_index/64);
  11543 
  11544         soc_mem_field32_set(unit, mem, &enable_entry, EQTB_INDEXf, 
  11545                             profile_index);
  11546 
  11547         soc_mem_field32_set(unit, mem, &enable_entry, CPQ_IDf, index);
  11548 
  11549         soc_mem_field32_set(unit, mem, &enable_entry, CPQ_ENf, 1);
  11550 
  11551         BCM_IF_ERROR_RETURN
  11552             (soc_mem_write(unit, mem, MEM_BLOCK_ANY, qindex, &enable_entry));
  11553     }
  11554 
  11555     return BCM_E_NONE;
  11556 }
  11557 
  11558 /*
  11559  * Function:
  11560  *     bcm_td2_cosq_congestion_queue_get
  11561  * Purpose:
  11562  *     Get congestion managed queue index of the specified cos queue
  11563  * Parameters:
  11564  *     unit          - (IN) unit number
  11565  *     port          - (IN) port number or GPORT identifier
  11566  *     cosq          - (IN) COS queue number
  11567  *     index         - (OUT) congestion managed queue index
  11568  * Returns:
  11569  *     BCM_E_XXX
  11570  */
  11571 int
  11572 bcm_td2_cosq_congestion_queue_get(int unit, bcm_port_t port,
  11573                                  bcm_cos_queue_t cosq, int *index)
  11574 {
  11575     bcm_port_t local_port;
  11576     int qindex;
  11577     mmu_qcn_enable_entry_t entry;
  11578     soc_mem_t mem;
  11579     int pipe;
  11580 
  11581     if (cosq < 0 || cosq >= _TD2_NUM_COS(unit)) {
  11582         return BCM_E_PARAM;
  11583     }
  11584     
  11585     if (index == NULL) {
  11586         return BCM_E_PARAM;
  11587     }
  11588 
  11589     BCM_IF_ERROR_RETURN
  11590         (_bcm_td2_cosq_index_resolve(unit, port, cosq,
  11591                                     _BCM_TD2_COSQ_INDEX_STYLE_QCN,
  11592                                     &local_port, &qindex, NULL));
  11593 
  11594     pipe = _BCM_TD2_PORT_TO_PIPE(unit, local_port);
  11595     if (pipe) {
  11596         mem = MMU_QCN_ENABLE_1m;
  11597     } else {
  11598         mem = MMU_QCN_ENABLE_0m;
  11599     }
  11600 
  11601     
  11602     
  11603     BCM_IF_ERROR_RETURN
  11604         (soc_mem_read(unit, mem, MEM_BLOCK_ANY, qindex, &entry));
  11605     if (soc_mem_field32_get(unit, mem, &entry, CPQ_ENf)) {
  11606         *index = soc_mem_field32_get(unit, mem, &entry, CPQ_IDf);
  11607     } else {
  11608         *index = -1;
  11609     }
  11610 
  11611     return BCM_E_NONE;
  11612 }
  11613 
  11614 /*
  11615  * Function:
  11616  *     bcm_td2_cosq_congestion_quantize_set
  11617  * Purpose:
  11618  *     Set quantized congestion feedback algorithm parameters
  11619  * Parameters:
  11620  *     unit          - (IN) unit number
  11621  *     port          - (IN) port number or GPORT identifier
  11622  *     cosq          - (IN) COS queue number
  11623  *     weight_code   - (IN) weight encoding (use -1 for unchange)
  11624  *     set_point     - (IN) queue size set point (use -1 for unchange)
  11625  * Returns:
  11626  *     BCM_E_XXX
  11627  */
  11628 int
  11629 bcm_td2_cosq_congestion_quantize_set(int unit, bcm_port_t port,
  11630                                     bcm_cos_queue_t cosq, int weight_code,
  11631                                     int set_point)
  11632 {
  11633     bcm_port_t local_port;
  11634     uint32 rval;
  11635     uint64 rval64, *rval64s[1];
  11636     mmu_qcn_enable_entry_t enable_entry;
  11637     int cpq_index, active_offset, qindex;
  11638     uint32 profile_index, old_profile_index;
  11639     soc_mem_t mem;
  11640     int pipe;
  11641 
  11642     if (cosq < 0 || cosq >= _TD2_NUM_COS(unit)) {
  11643         return BCM_E_PARAM;
  11644     }
  11645 
  11646     BCM_IF_ERROR_RETURN
  11647         (_bcm_td2_cosq_index_resolve(unit, port, cosq,
  11648                                     _BCM_TD2_COSQ_INDEX_STYLE_QCN,
  11649                                     &local_port, &qindex, NULL));
  11650     
  11651     pipe = _BCM_TD2_PORT_TO_PIPE(unit, local_port);
  11652     if (pipe) {
  11653         mem = MMU_QCN_ENABLE_1m;
  11654     } else {
  11655         mem = MMU_QCN_ENABLE_0m;
  11656     }
  11657 
  11658     BCM_IF_ERROR_RETURN
  11659         (bcm_td2_cosq_congestion_queue_get(unit, port, cosq, &cpq_index));
  11660     if (cpq_index == -1) {
  11661         /* The cosq specified is not enabled as congestion managed queue */
  11662         return BCM_E_PARAM;
  11663     }
  11664 
  11665     BCM_IF_ERROR_RETURN
  11666         (_bcm_td2_cosq_index_resolve(unit, port, cosq, 
  11667                 _BCM_TD2_COSQ_INDEX_STYLE_QCN, &local_port, &qindex, NULL));
  11668 
  11669     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ANY, qindex, &enable_entry));
  11670     old_profile_index =
  11671         soc_mem_field32_get(unit, mem, &enable_entry, EQTB_INDEXf);
  11672 
  11673     BCM_IF_ERROR_RETURN(READ_MMU_QCN_CPQ_SEQr(unit, old_profile_index, &rval));
  11674     if (weight_code == -1) {
  11675         weight_code = soc_reg_field_get(unit, MMU_QCN_CPQ_SEQr, rval, CPWf);
  11676     } else {
  11677         if (weight_code < 0 || weight_code > 7) {
  11678             return BCM_E_PARAM;
  11679         }
  11680         soc_reg_field_set(unit, MMU_QCN_CPQ_SEQr, &rval, CPWf, weight_code);
  11681     }
  11682     if (set_point == -1) {
  11683         set_point = soc_reg_field_get(unit, MMU_QCN_CPQ_SEQr, rval, CPQEQf);
  11684     } else {
  11685         if (set_point < 0 || set_point > 0xffff) {
  11686             return BCM_E_PARAM;
  11687         }
  11688         soc_reg_field_set(unit, MMU_QCN_CPQ_SEQr, &rval, CPQEQf, set_point);
  11689     }
  11690     COMPILER_64_SET(rval64, 0, rval);
  11691     rval64s[0] = &rval64;
  11692     /* Add new feedback parameter profile */
  11693     BCM_IF_ERROR_RETURN
  11694         (soc_profile_reg_add(unit, _bcm_td2_feedback_profile[unit], rval64s,
  11695                              1, (uint32 *)&profile_index));
  11696     /* Delete original feedback parameter profile */
  11697     BCM_IF_ERROR_RETURN
  11698         (soc_profile_reg_delete(unit, _bcm_td2_feedback_profile[unit],
  11699                                 old_profile_index));
  11700 
  11701     /* Update quantized feedback calculation lookup table */
  11702     BCM_IF_ERROR_RETURN
  11703         (_bcm_td2_cosq_quantize_table_set(unit, profile_index, weight_code,
  11704                                          set_point, &active_offset));
  11705 
  11706     soc_mem_field32_set(unit, mem, &enable_entry,
  11707                             QNTZ_ACT_OFFSETf, active_offset);
  11708     soc_mem_field32_set(unit, mem, &enable_entry,
  11709                             EQTB_INDEXf, profile_index);
  11710     BCM_IF_ERROR_RETURN
  11711             (soc_mem_write(unit, mem, MEM_BLOCK_ANY, qindex,
  11712                            &enable_entry));
  11713 
  11714     return BCM_E_NONE;
  11715 }
  11716 
  11717 /*
  11718  * Function:
  11719  *     bcm_td2_cosq_congestion_quantize_get
  11720  * Purpose:
  11721  *     Get quantized congestion feedback algorithm parameters
  11722  * Parameters:
  11723  *     unit          - (IN) unit number
  11724  *     port          - (IN) port number or GPORT identifier
  11725  *     cosq          - (IN) COS queue number
  11726  *     weight_code   - (OUT) weight encoding
  11727  *     set_point     - (OUT) queue size set point
  11728  * Returns:
  11729  *     BCM_E_XXX
  11730  */
  11731 int
  11732 bcm_td2_cosq_congestion_quantize_get(int unit, bcm_port_t port,
  11733                                     bcm_cos_queue_t cosq, int *weight_code,
  11734                                     int *set_point)
  11735 {
  11736     bcm_port_t local_port;
  11737     int cpq_index, profile_index, qindex;
  11738     uint32 rval;
  11739     mmu_qcn_enable_entry_t enable_entry;
  11740     soc_mem_t mem;
  11741     int pipe;
  11742 
  11743     BCM_IF_ERROR_RETURN
  11744         (bcm_td2_cosq_congestion_queue_get(unit, port, cosq, &cpq_index));
  11745     if (cpq_index == -1) {
  11746         /* The cosq specified is not enabled as congestion managed queue */
  11747         return BCM_E_PARAM;
  11748     }
  11749 
  11750     BCM_IF_ERROR_RETURN
  11751         (_bcm_td2_cosq_index_resolve(unit, port, cosq,
  11752                                     _BCM_TD2_COSQ_INDEX_STYLE_QCN,
  11753                                     &local_port, &qindex, NULL));
  11754     
  11755     pipe = _BCM_TD2_PORT_TO_PIPE(unit, local_port);
  11756     if (pipe) {
  11757         mem = MMU_QCN_ENABLE_1m;
  11758     } else {
  11759         mem = MMU_QCN_ENABLE_0m;
  11760     }
  11761 
  11762     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem,
  11763                                      MEM_BLOCK_ANY, qindex, &enable_entry));
  11764 
  11765     profile_index =
  11766         soc_mem_field32_get(unit, mem, &enable_entry, EQTB_INDEXf);
  11767 
  11768     BCM_IF_ERROR_RETURN(READ_MMU_QCN_CPQ_SEQr(unit, profile_index, &rval));
  11769     if (weight_code != NULL) {
  11770         *weight_code = soc_reg_field_get(unit, MMU_QCN_CPQ_SEQr, rval, CPWf);
  11771     }
  11772     if (set_point != NULL) {
  11773         *set_point = soc_reg_field_get(unit, MMU_QCN_CPQ_SEQr, rval, CPQEQf);
  11774     }
  11775 
  11776     return BCM_E_NONE;
  11777 }
  11778 
  11779 int
  11780 bcm_td2_cosq_congestion_sample_int_set(int unit, bcm_port_t port,
  11781                                       bcm_cos_queue_t cosq, int min, int max)
  11782 {
  11783     bcm_port_t local_port;
  11784     mmu_qcn_enable_entry_t entry;
  11785     mmu_qcn_sitb_entry_t sitb_entry;
  11786     int qindex;
  11787     uint32 profile_index, old_profile_index;
  11788     soc_mem_t mem;
  11789     int pipe;
  11790 
  11791     BCM_IF_ERROR_RETURN
  11792         (_bcm_td2_cosq_index_resolve(unit, port, cosq,
  11793                                     _BCM_TD2_COSQ_INDEX_STYLE_QCN,
  11794                                     &local_port, &qindex, NULL));
  11795 
  11796     pipe = _BCM_TD2_PORT_TO_PIPE(unit, local_port);
  11797     if (pipe) {
  11798         mem = MMU_QCN_ENABLE_1m;
  11799     } else {
  11800         mem = MMU_QCN_ENABLE_0m;
  11801     }
  11802 
  11803 
  11804     BCM_IF_ERROR_RETURN
  11805         (soc_mem_read(unit, mem, MEM_BLOCK_ANY, qindex, &entry));
  11806 
  11807     if (!soc_mem_field32_get(unit, mem, &entry, CPQ_ENf)) {
  11808         return BCM_E_PARAM;
  11809     }
  11810 
  11811     old_profile_index =
  11812         soc_mem_field32_get(unit, mem, &entry, SITB_SELf);
  11813 
  11814     if (max == -1) {
  11815         BCM_IF_ERROR_RETURN(soc_mem_read(unit, MMU_QCN_SITBm, MEM_BLOCK_ANY,
  11816                                          old_profile_index * 64, &sitb_entry));
  11817         max = soc_mem_field32_get(unit, MMU_QCN_SITBm, &sitb_entry, CPQ_SIf);
  11818     } else {
  11819         if (max < 1 || max > 255) {
  11820             return BCM_E_PARAM;
  11821         }
  11822     }
  11823     if (min == -1) {
  11824         BCM_IF_ERROR_RETURN(soc_mem_read(unit, MMU_QCN_SITBm, MEM_BLOCK_ANY,
  11825                                          old_profile_index * 64 + 63,
  11826                                          &sitb_entry));
  11827         min = soc_mem_field32_get(unit, MMU_QCN_SITBm, &sitb_entry, CPQ_SIf);
  11828     } else {
  11829         if (min < 1 || min > 255) {
  11830             return BCM_E_PARAM;
  11831         }
  11832     }
  11833 
  11834     /* Add new sample interval profile */
  11835     BCM_IF_ERROR_RETURN
  11836         (_bcm_td2_cosq_sample_int_table_set(unit, min, max, &profile_index));
  11837 
  11838     /* Delete original sample interval profile */
  11839     BCM_IF_ERROR_RETURN
  11840         (soc_profile_mem_delete(unit, _bcm_td2_sample_int_profile[unit],
  11841                                 old_profile_index * 64));
  11842 
  11843     soc_mem_field32_set(unit, mem, &entry, SITB_SELf, 
  11844                         profile_index / 64);
  11845     BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ANY,
  11846                                       qindex, &entry));
  11847     return BCM_E_NONE;
  11848 }
  11849 
  11850 int
  11851 bcm_td2_cosq_congestion_sample_int_get(int unit, bcm_port_t port,
  11852                                       bcm_cos_queue_t cosq, int *min, int *max)
  11853 {
  11854     bcm_port_t local_port;
  11855     mmu_qcn_enable_entry_t entry;
  11856     mmu_qcn_sitb_entry_t sitb_entry;
  11857     int qindex;
  11858     uint32 old_profile_index;
  11859     soc_mem_t mem;
  11860     int pipe;
  11861 
  11862     BCM_IF_ERROR_RETURN
  11863         (_bcm_td2_cosq_index_resolve(unit, port, cosq,
  11864                                     _BCM_TD2_COSQ_INDEX_STYLE_QCN,
  11865                                     &local_port, &qindex, NULL));
  11866     
  11867     pipe = _BCM_TD2_PORT_TO_PIPE(unit, local_port);
  11868     if (pipe) {
  11869         mem = MMU_QCN_ENABLE_1m;
  11870     } else {
  11871         mem = MMU_QCN_ENABLE_0m;
  11872     }
  11873     
  11874     BCM_IF_ERROR_RETURN
  11875         (soc_mem_read(unit, mem, MEM_BLOCK_ANY, qindex, &entry));
  11876 
  11877     if (!soc_mem_field32_get(unit, mem, &entry, CPQ_ENf)) {
  11878         return BCM_E_PARAM;
  11879     }
  11880 
  11881     old_profile_index =
  11882     soc_mem_field32_get(unit, mem, &entry, SITB_SELf);
  11883 
  11884     if (max) {
  11885         BCM_IF_ERROR_RETURN(soc_mem_read(unit, MMU_QCN_SITBm, MEM_BLOCK_ANY,
  11886                                      old_profile_index * 64, &sitb_entry));
  11887         *max = soc_mem_field32_get(unit, MMU_QCN_SITBm, &sitb_entry, CPQ_SIf);
  11888     }
  11889 
  11890     if (min) {
  11891         BCM_IF_ERROR_RETURN(soc_mem_read(unit, MMU_QCN_SITBm, MEM_BLOCK_ANY,
  11892                                      old_profile_index * 64 + 63,
  11893                                      &sitb_entry));
  11894         *min = soc_mem_field32_get(unit, MMU_QCN_SITBm, &sitb_entry, CPQ_SIf);
  11895     }
  11896 
  11897     return BCM_E_NONE;
  11898 }
  11899 
  11900 STATIC int
  11901 _bcm_td2_cosq_ing_pool_set(int unit, bcm_gport_t gport, bcm_cos_queue_t pri_grp,
  11902         bcm_cosq_control_t type, int arg)
  11903 {
  11904     int local_port;
  11905     uint32 rval;
  11906     static const soc_field_t prigroup_spid_field[] = {
  11907         PG0_SPIDf, PG1_SPIDf, PG2_SPIDf, PG3_SPIDf,
  11908         PG4_SPIDf, PG5_SPIDf, PG6_SPIDf, PG7_SPIDf
  11909     };
  11910     if(( arg < 0 ) || (arg > 3 )) {
  11911             return BCM_E_PARAM;
  11912     }
  11913       
  11914     BCM_IF_ERROR_RETURN
  11915             (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port));
  11916 
  11917     if (!SOC_PORT_VALID(unit, local_port)) {
  11918         return BCM_E_PORT;
  11919     }
  11920     /* coverity fix : pri_grp can take value from 0 to 7 */  
  11921     if ((pri_grp < 0) || (pri_grp >= 8)) {
  11922         return BCM_E_PARAM;
  11923     }
  11924 
  11925     SOC_IF_ERROR_RETURN(READ_THDI_PORT_PG_SPIDr(unit, local_port, &rval));
  11926     soc_reg_field_set(unit, THDI_PORT_PG_SPIDr, &rval, 
  11927                                 prigroup_spid_field[pri_grp],arg);
  11928     BCM_IF_ERROR_RETURN(WRITE_THDI_PORT_PG_SPIDr(unit, local_port, rval));
  11929     return BCM_E_NONE;
  11930 }
  11931 
  11932 STATIC int
  11933 _bcm_td2_cosq_ing_pool_get(int unit, bcm_gport_t gport,
  11934         bcm_cos_queue_t pri_grp,
  11935         bcm_cosq_control_t type, int *arg)
  11936 {
  11937     int pool_start_idx = 0, pool_end_idx =0;
  11938     BCM_IF_ERROR_RETURN(
  11939             _bcm_td2_cosq_ingress_sp_get(
  11940                 unit, gport, pri_grp, &pool_start_idx, &pool_end_idx));
  11941     *arg = pool_start_idx;
  11942     return BCM_E_NONE;
  11943 }
  11944 
  11945  /*
  11946  * Function:
  11947  *     _bcm_td2_cosq_port_qnum_get
  11948  * Purpose:
  11949  *     Get the hw queue number used to tx packets on respective Queue
  11950  * Parameters:
  11951  *     unit          - (IN) unit number
  11952  *     port          - (IN) port number or GPORT identifier
  11953  *     cosq          - (IN) COS queue number
  11954  *     type          - (IN) unicast/multicast queue indicator
  11955  *     arg           - (out) hw queue number
  11956  * Returns:
  11957  *     BCM_E_XXX
  11958  */
  11959 STATIC int
  11960 _bcm_td2_cosq_port_qnum_get(int unit, bcm_gport_t gport,
  11961         bcm_cos_queue_t cosq, bcm_cosq_control_t type, int *arg)
  11962 {
  11963     bcm_port_t local_port;
  11964     int hw_index;
  11965     int uc;
  11966     int qnum;
  11967     int id, startq, numq;
  11968     _bcm_td2_cosq_node_t *node;
  11969     soc_info_t *si = &SOC_INFO(unit);
  11970 
  11971     if (!arg) {
  11972         return BCM_E_PARAM;
  11973     }
  11974 
  11975     if (cosq <= -1) {
  11976         return BCM_E_PARAM;
  11977     } else {
  11978         startq = cosq;
  11979         numq = 1;
  11980     }
  11981 
  11982     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
  11983         BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  11984         BCM_IF_ERROR_RETURN
  11985             (_bcm_td2_cosq_node_get(unit, gport, cosq, NULL, &local_port, &id,
  11986                                    &node));
  11987         if (node->attached_to_input < 0) { /* Not resolved yet */
  11988             return BCM_E_NOT_FOUND;
  11989         }
  11990 
  11991         startq = 0;
  11992     } else {
  11993         /* optionally validate port */
  11994         BCM_IF_ERROR_RETURN
  11995             (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port));
  11996         if (local_port < 0) {
  11997             return BCM_E_PORT;
  11998         }
  11999         node = NULL;
  12000         numq = (IS_CPU_PORT(unit, local_port)) ?
  12001                                 NUM_CPU_COSQ(unit) : NUM_COS(unit);
  12002     }
  12003 
  12004     if (startq >= numq) {
  12005         return BCM_E_PARAM;
  12006     }
  12007 
  12008     uc =(type == bcmCosqControlPortQueueUcast) ? 1 : 0;
  12009 
  12010     if (node) {
  12011         hw_index = node->hw_index;
  12012     } else {
  12013         hw_index = soc_td2_l2_hw_index(unit,
  12014             si->port_uc_cosq_base[local_port] + startq, uc);
  12015     }
  12016 
  12017     qnum = soc_td2_hw_index_logical_num(unit,local_port,hw_index,uc);
  12018     *arg = soc_td2_logical_qnum_hw_qnum(unit,local_port,qnum,uc);
  12019 
  12020     return BCM_E_NONE;
  12021 }
  12022 
  12023 STATIC int
  12024 _bcm_td2_cosq_egr_pool_set(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
  12025                           bcm_cosq_control_t type, int arg)
  12026 {
  12027     bcm_port_t local_port;
  12028     int startq, pool, midx;
  12029     uint32 max_val;
  12030     uint32 entry[SOC_MAX_MEM_WORDS];
  12031     uint32 entry2[SOC_MAX_MEM_WORDS];
  12032     soc_mem_t mem = INVALIDm, mem2 = INVALIDm;
  12033     soc_field_t fld_limit = INVALIDf;
  12034     int granularity = 1;
  12035 
  12036     if ((arg < 0) || (cosq < 0)) {
  12037         return BCM_E_PARAM;
  12038     }
  12039 
  12040     BCM_IF_ERROR_RETURN
  12041         (_bcm_td2_cosq_index_resolve(unit, gport, cosq,
  12042                                     _BCM_TD2_COSQ_INDEX_STYLE_EGR_POOL,
  12043                                     &local_port, &pool, NULL));
  12044 
  12045     mem = SOC_TD2_PMEM(unit, local_port, MMU_THDM_DB_PORTSP_CONFIG_0m, 
  12046                                          MMU_THDM_DB_PORTSP_CONFIG_1m);
  12047 
  12048     if (type == bcmCosqControlEgressPoolLimitEnable) {
  12049         midx = SOC_TD2_MMU_PIPED_MEM_INDEX(unit, local_port, mem, pool);
  12050         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL,
  12051                             midx, entry));
  12052 
  12053         soc_mem_field32_set(unit, mem, entry, SHARED_LIMIT_ENABLEf, !!arg);
  12054 
  12055         return soc_mem_write(unit, mem, MEM_BLOCK_ALL, midx, entry);
  12056     }
  12057     if (type == bcmCosqControlEgressPool || type == bcmCosqControlUCEgressPool ||
  12058         type == bcmCosqControlMCEgressPool) {
  12059         if(( arg < 0 ) || (arg > 3 )) {
  12060             return BCM_E_PARAM;
  12061         }
  12062         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  12063             if (type != bcmCosqControlEgressPool) {
  12064                 return BCM_E_PARAM;
  12065             }
  12066             /* regular unicast queue */
  12067             BCM_IF_ERROR_RETURN
  12068                 (_bcm_td2_cosq_index_resolve(unit, gport, cosq,
  12069                                              _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE,
  12070                                              &local_port, &startq, NULL));
  12071             mem = SOC_TD2_PMEM(unit, local_port, 
  12072                     MMU_THDU_XPIPE_Q_TO_QGRP_MAPm, MMU_THDU_YPIPE_Q_TO_QGRP_MAPm);
  12073         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  12074             if (type != bcmCosqControlEgressPool) {
  12075                 return BCM_E_PARAM;
  12076             }
  12077             BCM_IF_ERROR_RETURN
  12078                 (_bcm_td2_cosq_index_resolve(unit, gport, cosq,
  12079                                              _BCM_TD2_COSQ_INDEX_STYLE_MCAST_QUEUE,
  12080                                              &local_port, &startq, NULL));
  12081             startq -= 1480; /* MC queues comes after UC queues */
  12082             mem = SOC_TD2_PMEM(unit, local_port, 
  12083                     MMU_THDM_MCQE_QUEUE_CONFIG_0m, MMU_THDM_MCQE_QUEUE_CONFIG_1m);
  12084             mem2 = SOC_TD2_PMEM(unit, local_port, 
  12085                     MMU_THDM_DB_QUEUE_CONFIG_0m, MMU_THDM_DB_QUEUE_CONFIG_1m);
  12086         } else  { /* local port */
  12087             if (BCM_GPORT_IS_SCHEDULER(gport) &&
  12088                 (type != bcmCosqControlEgressPool)) {
  12089                 return BCM_E_PARAM;
  12090             }
  12091             if (type == bcmCosqControlUCEgressPool) {
  12092                 BCM_IF_ERROR_RETURN
  12093                     (_bcm_td2_cosq_index_resolve(unit, gport, cosq,
  12094                                              _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE,
  12095                                              &local_port, &startq, NULL));
  12096                 mem = SOC_TD2_PMEM(unit, local_port, 
  12097                                    MMU_THDU_XPIPE_Q_TO_QGRP_MAPm, 
  12098                                    MMU_THDU_YPIPE_Q_TO_QGRP_MAPm);
  12099             } else {
  12100                 BCM_IF_ERROR_RETURN
  12101                     (_bcm_td2_cosq_index_resolve(unit, gport, cosq,
  12102                                              _BCM_TD2_COSQ_INDEX_STYLE_MCAST_QUEUE,
  12103                                              &local_port, &startq, NULL));
  12104                 startq -= 1480; /* MC queues comes after UC queues */
  12105                 mem = SOC_TD2_PMEM(unit, local_port, 
  12106                                    MMU_THDM_MCQE_QUEUE_CONFIG_0m, 
  12107                                    MMU_THDM_MCQE_QUEUE_CONFIG_1m);
  12108                 mem2 = SOC_TD2_PMEM(unit, local_port, 
  12109                                     MMU_THDM_DB_QUEUE_CONFIG_0m, 
  12110                                     MMU_THDM_DB_QUEUE_CONFIG_1m);
  12111             }
  12112         }
  12113 
  12114         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  12115         soc_mem_field32_set(unit, mem, entry, Q_SPIDf, arg);
  12116 
  12117         BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry));
  12118         if (mem2 != INVALIDm) {
  12119             BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem2, MEM_BLOCK_ALL, startq, entry2));
  12120             soc_mem_field32_set(unit, mem2, entry2, Q_SPIDf, arg);
  12121             BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem2, MEM_BLOCK_ALL, startq, entry2));
  12122         }
  12123         return BCM_E_NONE;
  12124     }
  12125 
  12126     arg = arg / _BCM_TD2_BYTES_PER_CELL;
  12127 
  12128     /* per service pool settings */
  12129     if (type == bcmCosqControlEgressPoolSharedLimitBytes || 
  12130         type == bcmCosqControlEgressPoolResumeLimitBytes ||
  12131         type == bcmCosqControlEgressPoolYellowSharedLimitBytes || 
  12132         type == bcmCosqControlEgressPoolYellowResumeLimitBytes ||
  12133         type == bcmCosqControlEgressPoolRedSharedLimitBytes ||
  12134         type == bcmCosqControlEgressPoolRedResumeLimitBytes) {
  12135         uint32 rval;
  12136         soc_reg_t reg;
  12137         switch (type) {
  12138         case bcmCosqControlEgressPoolSharedLimitBytes:
  12139             reg = MMU_THDM_DB_POOL_SHARED_LIMITr;    
  12140             fld_limit = SHARED_LIMITf;
  12141             granularity = 1;
  12142             break;
  12143         case bcmCosqControlEgressPoolResumeLimitBytes:
  12144             reg = MMU_THDM_DB_POOL_RESUME_LIMITr;    
  12145             fld_limit = RESUME_LIMITf;
  12146             granularity = 8;
  12147             break;
  12148         case bcmCosqControlEgressPoolYellowSharedLimitBytes:
  12149             reg = MMU_THDM_DB_POOL_YELLOW_SHARED_LIMITr;    
  12150             fld_limit = YELLOW_SHARED_LIMITf;
  12151             granularity = 8;
  12152             break;
  12153         case bcmCosqControlEgressPoolYellowResumeLimitBytes:
  12154             reg = MMU_THDM_DB_POOL_YELLOW_RESUME_LIMITr;    
  12155             fld_limit = YELLOW_RESUME_LIMITf;
  12156             granularity = 8;
  12157             break;
  12158         case bcmCosqControlEgressPoolRedSharedLimitBytes:
  12159             reg = MMU_THDM_DB_POOL_RED_SHARED_LIMITr;    
  12160             fld_limit = RED_SHARED_LIMITf;
  12161             granularity = 8;
  12162             break;
  12163         case bcmCosqControlEgressPoolRedResumeLimitBytes:
  12164             reg = MMU_THDM_DB_POOL_RED_RESUME_LIMITr;    
  12165             fld_limit = RED_RESUME_LIMITf;
  12166             granularity = 8;
  12167             break;
  12168         /*
  12169          * COVERITY
  12170          *
  12171          * This default is unreachable but needed for some compiler.
  12172          */
  12173         /* coverity[dead_error_begin] */
  12174         default:
  12175             return BCM_E_UNAVAIL;
  12176         }
  12177         
  12178         BCM_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, pool, &rval));
  12179         
  12180         /* Check for min/max values */
  12181         max_val = (1 << soc_reg_field_length(unit, reg, fld_limit)) - 1;
  12182         if ((arg < 0) || ((arg/granularity) > max_val)) {
  12183             return BCM_E_PARAM;
  12184         } else {
  12185             soc_reg_field_set(unit, reg, &rval, fld_limit, (arg/granularity));
  12186         }
  12187         
  12188         BCM_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, pool, rval));
  12189 
  12190         return BCM_E_NONE;
  12191     }
  12192 
  12193     /* per port settings */
  12194     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  12195         BCM_IF_ERROR_RETURN
  12196             (_bcm_td2_cosq_index_resolve(unit, gport, cosq,
  12197                                          _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE,
  12198                                          &local_port, &startq, NULL));
  12199         mem = SOC_TD2_PMEM(unit, local_port, MMU_THDU_XPIPE_CONFIG_QUEUEm,
  12200                            MMU_THDU_YPIPE_CONFIG_QUEUEm);
  12201 
  12202         mem2 = SOC_TD2_PMEM(unit, local_port, MMU_THDU_XPIPE_Q_TO_QGRP_MAPm, 
  12203                             MMU_THDU_YPIPE_Q_TO_QGRP_MAPm);
  12204     } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  12205         BCM_IF_ERROR_RETURN
  12206             (_bcm_td2_cosq_index_resolve(unit, gport, cosq,
  12207                                          _BCM_TD2_COSQ_INDEX_STYLE_MCAST_QUEUE,
  12208                                          &local_port, &startq, NULL));
  12209         mem = SOC_TD2_PMEM(unit, local_port, MMU_THDM_DB_QUEUE_CONFIG_0m, 
  12210                            MMU_THDM_DB_QUEUE_CONFIG_1m);
  12211         startq -= 1480; /* MC queues comes after UC queues */
  12212     } else {
  12213         if (soc_property_get(unit, spn_PORT_UC_MC_ACCOUNTING_COMBINE, 0) == 0) {
  12214             /* Need to have the UC_MC_Combine config enabled */
  12215             return BCM_E_PARAM;
  12216         }
  12217         mem = SOC_TD2_PMEM(unit, local_port, MMU_THDM_DB_PORTSP_CONFIG_0m, 
  12218                            MMU_THDM_DB_PORTSP_CONFIG_1m);
  12219         startq = SOC_TD2_MMU_PIPED_MEM_INDEX(unit, local_port, mem, pool);
  12220     }
  12221 
  12222     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  12223 
  12224     if (mem2 != INVALIDm) {
  12225         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem2, MEM_BLOCK_ALL, startq, entry2));
  12226     }
  12227 
  12228     switch (type) {
  12229     case bcmCosqControlEgressPoolLimitBytes:
  12230         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  12231             fld_limit = Q_SHARED_LIMIT_CELLf;
  12232 
  12233             if (mem2 != INVALIDm) {
  12234                 soc_mem_field32_set(unit, mem2, entry2, Q_LIMIT_ENABLEf, 1);
  12235             }
  12236         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  12237             fld_limit = Q_SHARED_LIMITf;
  12238             soc_mem_field32_set(unit, mem, entry, Q_LIMIT_ENABLEf, 1);
  12239         } else {
  12240             fld_limit = SHARED_LIMITf;
  12241             soc_mem_field32_set(unit, mem, entry, SHARED_LIMIT_ENABLEf, 1);
  12242         }
  12243         granularity = 1;
  12244         break;
  12245     case bcmCosqControlEgressPoolYellowLimitBytes:
  12246         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  12247             fld_limit = LIMIT_YELLOW_CELLf;
  12248         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  12249             fld_limit = YELLOW_SHARED_LIMITf;
  12250         } else {
  12251             fld_limit = YELLOW_SHARED_LIMITf;
  12252         }
  12253         granularity = 8;
  12254         break;
  12255     case bcmCosqControlEgressPoolRedLimitBytes:
  12256         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  12257             fld_limit = LIMIT_RED_CELLf;
  12258         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  12259             fld_limit = RED_SHARED_LIMITf;
  12260         } else {
  12261             fld_limit = RED_SHARED_LIMITf;
  12262         }
  12263         granularity = 8;
  12264         break;
  12265     default:
  12266         return BCM_E_UNAVAIL;
  12267     }
  12268 
  12269     /* Check for min/max values */
  12270     max_val = (1 << soc_mem_field_length(unit, mem, fld_limit)) - 1;
  12271     if ((arg < 0) || ((arg/granularity) > max_val)) {
  12272         return BCM_E_PARAM;
  12273     } else {
  12274         soc_mem_field32_set(unit, mem, entry, fld_limit, (arg/granularity));
  12275     }
  12276     BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry));
  12277 
  12278     if (mem2 != INVALIDm) {
  12279         BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem2, MEM_BLOCK_ALL, startq, entry2));
  12280     }
  12281     return BCM_E_NONE;
  12282 }
  12283 
  12284 
  12285 
  12286 STATIC int
  12287 _bcm_td2_cosq_egr_port_pool_set(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
  12288                           bcm_cosq_control_t type, int arg)
  12289 {
  12290     bcm_port_t local_port;
  12291     uint32 max_val;
  12292     uint32 entry[SOC_MAX_MEM_WORDS];
  12293     soc_mem_t mem = INVALIDm;
  12294     soc_field_t fld_limit = INVALIDf;
  12295     int granularity = 1;
  12296     int pool, midx;
  12297 
  12298     if (arg < 0) {
  12299         return BCM_E_PARAM;
  12300     }
  12301 
  12302     BCM_IF_ERROR_RETURN
  12303         (_bcm_td2_cosq_index_resolve(unit, gport, cosq,
  12304                                     _BCM_TD2_COSQ_INDEX_STYLE_EGR_POOL,
  12305                                     &local_port, &pool, NULL));
  12306     mem = SOC_TD2_PMEM(unit, local_port, MMU_THDU_XPIPE_CONFIG_PORTm,
  12307                                          MMU_THDU_YPIPE_CONFIG_PORTm);
  12308     midx = SOC_TD2_MMU_PIPED_MEM_INDEX(unit, local_port, mem, pool);
  12309     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, entry));
  12310 
  12311     switch (type) {
  12312     case bcmCosqControlEgressPortPoolYellowLimitBytes:
  12313         fld_limit = YELLOW_LIMITf;
  12314         granularity = 8;
  12315         break;
  12316     case bcmCosqControlEgressPortPoolRedLimitBytes:
  12317         fld_limit = RED_LIMITf;
  12318         granularity = 8;
  12319         break;
  12320     default:
  12321         return BCM_E_UNAVAIL;
  12322     }
  12323 
  12324     arg = arg / _BCM_TD2_BYTES_PER_CELL;
  12325 
  12326     /* Check for min/max values */
  12327     max_val = (1 << soc_mem_field_length(unit, mem, fld_limit)) - 1;
  12328     if ((arg < 0) || ((arg/granularity) > max_val)) {
  12329         return BCM_E_PARAM;
  12330     } else {
  12331         soc_mem_field32_set(unit, mem, entry, fld_limit, (arg/granularity));
  12332     }
  12333     BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, midx, entry));
  12334 
  12335     return BCM_E_NONE;
  12336 }
  12337 
  12338 
  12339 STATIC int
  12340 _bcm_td2_cosq_egr_pool_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
  12341                           bcm_cosq_control_t type, int *arg)
  12342 {
  12343     bcm_port_t local_port;
  12344     int startq, pool, midx;
  12345     uint32 entry[SOC_MAX_MEM_WORDS];
  12346     soc_mem_t mem;
  12347     int granularity = 1;
  12348 
  12349     if ((!arg) || (cosq < 0)){
  12350         return BCM_E_PARAM;
  12351     }
  12352     
  12353     if (type == bcmCosqControlUCEgressPool) {
  12354         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 
  12355             BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) ||
  12356             BCM_GPORT_IS_SCHEDULER(gport)) {
  12357             return BCM_E_PARAM;
  12358         }
  12359 
  12360         BCM_IF_ERROR_RETURN
  12361             (_bcm_td2_cosq_index_resolve(unit, gport, cosq,
  12362                                          _BCM_TD2_COSQ_INDEX_STYLE_UC_EGR_POOL,
  12363                                          &local_port, &pool, NULL));
  12364         *arg = pool;
  12365         return BCM_E_NONE;
  12366     } else {
  12367         if (type == bcmCosqControlMCEgressPool) {
  12368             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 
  12369                 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) ||
  12370                 BCM_GPORT_IS_SCHEDULER(gport)) {
  12371                 return BCM_E_PARAM;
  12372             }
  12373         }
  12374         BCM_IF_ERROR_RETURN
  12375             (_bcm_td2_cosq_index_resolve(unit, gport, cosq,
  12376                                          _BCM_TD2_COSQ_INDEX_STYLE_EGR_POOL,
  12377                                          &local_port, &pool, NULL));
  12378         if (type == bcmCosqControlMCEgressPool ||
  12379             type == bcmCosqControlEgressPool) {
  12380             *arg = pool;
  12381             return BCM_E_NONE;
  12382         }
  12383     }
  12384     
  12385     /* per service pool settings */
  12386     if (type == bcmCosqControlEgressPoolSharedLimitBytes || 
  12387         type == bcmCosqControlEgressPoolResumeLimitBytes ||
  12388         type == bcmCosqControlEgressPoolYellowSharedLimitBytes || 
  12389         type == bcmCosqControlEgressPoolYellowResumeLimitBytes ||
  12390         type == bcmCosqControlEgressPoolRedSharedLimitBytes ||
  12391         type == bcmCosqControlEgressPoolRedResumeLimitBytes) {
  12392         uint32 rval;
  12393         soc_reg_t reg;
  12394         soc_field_t fld_limit = INVALIDf;
  12395         switch (type) {
  12396         case bcmCosqControlEgressPoolSharedLimitBytes:
  12397             reg = MMU_THDM_DB_POOL_SHARED_LIMITr;    
  12398             fld_limit = SHARED_LIMITf;
  12399             granularity = 1;
  12400             break;
  12401         case bcmCosqControlEgressPoolResumeLimitBytes:
  12402             reg = MMU_THDM_DB_POOL_RESUME_LIMITr;    
  12403             fld_limit = RESUME_LIMITf;
  12404             granularity = 8;
  12405             break;
  12406         case bcmCosqControlEgressPoolYellowSharedLimitBytes:
  12407             reg = MMU_THDM_DB_POOL_YELLOW_SHARED_LIMITr;    
  12408             fld_limit = YELLOW_SHARED_LIMITf;
  12409             granularity = 8;
  12410             break;
  12411         case bcmCosqControlEgressPoolYellowResumeLimitBytes:
  12412             reg = MMU_THDM_DB_POOL_YELLOW_RESUME_LIMITr;    
  12413             fld_limit = YELLOW_RESUME_LIMITf;
  12414             granularity = 8;
  12415             break;
  12416         case bcmCosqControlEgressPoolRedSharedLimitBytes:
  12417             reg = MMU_THDM_DB_POOL_RED_SHARED_LIMITr;    
  12418             fld_limit = RED_SHARED_LIMITf;
  12419             granularity = 8;
  12420             break;
  12421         case bcmCosqControlEgressPoolRedResumeLimitBytes:
  12422             reg = MMU_THDM_DB_POOL_RED_RESUME_LIMITr;    
  12423             fld_limit = RED_RESUME_LIMITf;
  12424             granularity = 8;
  12425             break;
  12426         /* coverity[dead_error_begin] */
  12427         default:
  12428             return BCM_E_UNAVAIL;
  12429         }
  12430 
  12431         BCM_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, pool, &rval));
  12432 
  12433         *arg = soc_reg_field_get(unit, reg, rval, fld_limit);
  12434         *arg = (*arg) * granularity * _BCM_TD2_BYTES_PER_CELL;
  12435 
  12436         return BCM_E_NONE;
  12437     }
  12438 
  12439     mem = SOC_TD2_PMEM(unit, local_port, MMU_THDM_DB_PORTSP_CONFIG_0m, 
  12440                                          MMU_THDM_DB_PORTSP_CONFIG_1m);
  12441 
  12442     if (type == bcmCosqControlEgressPoolLimitEnable) {
  12443         midx = SOC_TD2_MMU_PIPED_MEM_INDEX(unit, local_port, mem, pool);
  12444         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL,
  12445                                  midx, entry));
  12446 
  12447         *arg = soc_mem_field32_get(unit, mem, entry, SHARED_LIMIT_ENABLEf);
  12448         return BCM_E_NONE;
  12449     }
  12450 
  12451     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  12452         BCM_IF_ERROR_RETURN
  12453             (_bcm_td2_cosq_index_resolve(unit, gport, cosq,
  12454                                          _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE,
  12455                                          &local_port, &startq, NULL));
  12456         mem = SOC_TD2_PMEM(unit, local_port, MMU_THDU_XPIPE_CONFIG_QUEUEm,
  12457                            MMU_THDU_YPIPE_CONFIG_QUEUEm);
  12458     } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  12459         BCM_IF_ERROR_RETURN
  12460             (_bcm_td2_cosq_index_resolve(unit, gport, cosq,
  12461                                          _BCM_TD2_COSQ_INDEX_STYLE_MCAST_QUEUE,
  12462                                          &local_port, &startq, NULL));
  12463         mem = SOC_TD2_PMEM(unit, local_port, MMU_THDM_DB_QUEUE_CONFIG_0m, 
  12464                            MMU_THDM_DB_QUEUE_CONFIG_1m);
  12465         startq -= 1480; /* MC queues comes after UC queues */
  12466     } else {
  12467         if (soc_property_get(unit, spn_PORT_UC_MC_ACCOUNTING_COMBINE, 0) == 0) {
  12468             /* Need to have the UC_MC_Combine config enabled */
  12469             return BCM_E_PARAM;
  12470         }
  12471         mem = SOC_TD2_PMEM(unit, local_port, MMU_THDM_DB_PORTSP_CONFIG_0m,
  12472                            MMU_THDM_DB_PORTSP_CONFIG_1m);
  12473         startq = SOC_TD2_MMU_PIPED_MEM_INDEX(unit, local_port, mem, pool);
  12474     }
  12475     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL,
  12476                              startq, entry));
  12477 
  12478     switch (type) {
  12479     case bcmCosqControlEgressPoolLimitBytes:
  12480         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  12481             *arg = soc_mem_field32_get(unit, mem, entry, Q_SHARED_LIMIT_CELLf);
  12482         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  12483             *arg = soc_mem_field32_get(unit, mem, entry, Q_SHARED_LIMITf);
  12484         } else {
  12485             *arg = soc_mem_field32_get(unit, mem, entry, SHARED_LIMITf);
  12486         }
  12487         granularity = 1;
  12488         break;
  12489     case bcmCosqControlEgressPoolYellowLimitBytes:
  12490         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  12491             *arg = soc_mem_field32_get(unit, mem, entry, LIMIT_YELLOW_CELLf);
  12492         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  12493             *arg = soc_mem_field32_get(unit, mem, entry, YELLOW_SHARED_LIMITf);
  12494         } else {
  12495             *arg = soc_mem_field32_get(unit, mem, entry, YELLOW_SHARED_LIMITf);
  12496         }
  12497         granularity = 8;
  12498         break;
  12499     case bcmCosqControlEgressPoolRedLimitBytes:
  12500         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  12501             *arg = soc_mem_field32_get(unit, mem, entry, LIMIT_RED_CELLf);
  12502         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  12503             *arg = soc_mem_field32_get(unit, mem, entry, RED_SHARED_LIMITf);
  12504         } else {
  12505             *arg = soc_mem_field32_get(unit, mem, entry, RED_SHARED_LIMITf);
  12506         }
  12507         granularity = 8;
  12508         break;
  12509     default:
  12510         return BCM_E_UNAVAIL;
  12511     }
  12512     *arg = (*arg) * granularity * _BCM_TD2_BYTES_PER_CELL;
  12513     return BCM_E_NONE;
  12514 }
  12515 
  12516 
  12517 STATIC int
  12518 _bcm_td2_cosq_egr_port_pool_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
  12519                           bcm_cosq_control_t type, int *arg)
  12520 {
  12521     bcm_port_t local_port;
  12522     uint32 entry[SOC_MAX_MEM_WORDS];
  12523     soc_mem_t mem = INVALIDm;
  12524     int granularity = 1;
  12525     int pool, midx;
  12526     
  12527     if (!arg) {
  12528         return BCM_E_PARAM;
  12529     }
  12530 
  12531     BCM_IF_ERROR_RETURN
  12532         (_bcm_td2_cosq_index_resolve(unit, gport, cosq,
  12533                                     _BCM_TD2_COSQ_INDEX_STYLE_EGR_POOL,
  12534                                     &local_port, &pool, NULL));
  12535     mem = SOC_TD2_PMEM(unit, local_port, MMU_THDU_XPIPE_CONFIG_PORTm,
  12536                                          MMU_THDU_YPIPE_CONFIG_PORTm);
  12537     midx = SOC_TD2_MMU_PIPED_MEM_INDEX(unit, local_port, mem, pool);
  12538     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, entry));
  12539 
  12540     switch (type) {
  12541     case bcmCosqControlEgressPortPoolYellowLimitBytes:
  12542         *arg = soc_mem_field32_get(unit, mem, entry, YELLOW_LIMITf);
  12543         granularity = 8;
  12544         break;
  12545     case bcmCosqControlEgressPortPoolRedLimitBytes:
  12546 		*arg = soc_mem_field32_get(unit, mem, entry, RED_LIMITf);
  12547         granularity = 8;
  12548         break;
  12549     default:
  12550         return BCM_E_UNAVAIL;
  12551     }
  12552 
  12553 	
  12554     *arg = (*arg) * granularity * _BCM_TD2_BYTES_PER_CELL;
  12555     return BCM_E_NONE;
  12556 }
  12557 
  12558 
  12559 
  12560 STATIC int
  12561 _bcm_td2_cosq_egr_queue_set(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
  12562                             bcm_cosq_control_t type, int arg)
  12563 {
  12564     bcm_port_t local_port;
  12565     int startq;
  12566     uint32 max_val, rval = 0;
  12567     uint32 shared_size, spid;
  12568     uint32 entry[SOC_MAX_MEM_WORDS];
  12569     uint32 entry2[SOC_MAX_MEM_WORDS];
  12570     soc_mem_t mem = INVALIDm, mem2 = INVALIDm;
  12571     soc_field_t fld_limit = INVALIDf;
  12572     soc_field_t fld_sp = INVALIDf;
  12573     int granularity = 1;
  12574     int from_cos, to_cos, ci;
  12575     int cur_val, rv, post_update;
  12576     int limit;
  12577 
  12578     if (arg < 0) {
  12579         return BCM_E_PARAM;
  12580     }
  12581 
  12582     arg /= _BCM_TD2_BYTES_PER_CELL;
  12583 
  12584     if ((type == bcmCosqControlEgressUCQueueMinLimitBytes) ||
  12585         (type == bcmCosqControlEgressUCQueueSharedLimitBytes)) {
  12586         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  12587             BCM_IF_ERROR_RETURN
  12588                 (_bcm_td2_cosq_index_resolve(unit, gport, cosq,
  12589                                              _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE,
  12590                                              &local_port, &startq, NULL));
  12591         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  12592             return BCM_E_PARAM;
  12593         }
  12594         else {
  12595             if (cosq == BCM_COS_INVALID) {
  12596                 from_cos = to_cos = 0;
  12597             } else {
  12598                 from_cos = to_cos = cosq;
  12599             }
  12600 
  12601             BCM_IF_ERROR_RETURN
  12602                 (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port));
  12603             if (local_port < 0) {
  12604                 return BCM_E_PORT;
  12605             }
  12606             for (ci = from_cos; ci <= to_cos; ci++) {
  12607                 BCM_IF_ERROR_RETURN
  12608                     (_bcm_td2_cosq_index_resolve
  12609                      (unit, local_port, ci, _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE,
  12610                       NULL, &startq, NULL));
  12611             }
  12612         }
  12613         mem = SOC_TD2_PMEM(unit, local_port, MMU_THDU_XPIPE_CONFIG_QUEUEm,
  12614                            MMU_THDU_YPIPE_CONFIG_QUEUEm);
  12615 
  12616         mem2 = SOC_TD2_PMEM(unit, local_port, MMU_THDU_XPIPE_Q_TO_QGRP_MAPm, 
  12617                             MMU_THDU_YPIPE_Q_TO_QGRP_MAPm);
  12618         fld_sp = Q_SPIDf;
  12619     } else if ((type == bcmCosqControlEgressMCQueueMinLimitBytes) ||
  12620                (type == bcmCosqControlEgressMCQueueSharedLimitBytes)) {
  12621         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  12622             return BCM_E_PARAM;
  12623         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  12624             BCM_IF_ERROR_RETURN
  12625                 (_bcm_td2_cosq_index_resolve(unit, gport, cosq,
  12626                                              _BCM_TD2_COSQ_INDEX_STYLE_MCAST_QUEUE,
  12627                                              &local_port, &startq, NULL));
  12628         }
  12629         else {
  12630             if (cosq == BCM_COS_INVALID) {
  12631                 from_cos = to_cos = 0;
  12632             } else {
  12633                 from_cos = to_cos = cosq;
  12634             }
  12635 
  12636             BCM_IF_ERROR_RETURN
  12637                 (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port));
  12638             if (local_port < 0) {
  12639                 return BCM_E_PORT;
  12640             }
  12641             for (ci = from_cos; ci <= to_cos; ci++) {
  12642                 BCM_IF_ERROR_RETURN
  12643                     (_bcm_td2_cosq_index_resolve
  12644                      (unit, local_port, ci, _BCM_TD2_COSQ_INDEX_STYLE_MCAST_QUEUE,
  12645                       NULL, &startq, NULL));
  12646             }
  12647         }
  12648         mem = SOC_TD2_PMEM(unit, local_port, MMU_THDM_DB_QUEUE_CONFIG_0m,
  12649                            MMU_THDM_DB_QUEUE_CONFIG_1m);
  12650         mem2 = SOC_TD2_PMEM(unit, local_port, MMU_THDM_MCQE_QUEUE_CONFIG_0m,
  12651                             MMU_THDM_MCQE_QUEUE_CONFIG_1m);
  12652         fld_sp = Q_SPIDf;
  12653         startq -= 1480; /* MC queues comes after UC queues */
  12654     } else {
  12655         return BCM_E_PARAM;
  12656     }
  12657 
  12658     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  12659     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem2, MEM_BLOCK_ALL, startq, entry2));
  12660 
  12661     switch (type) {
  12662     case bcmCosqControlEgressUCQueueSharedLimitBytes:
  12663         fld_limit = Q_SHARED_LIMIT_CELLf;
  12664 
  12665         soc_mem_field32_set(unit, mem2, entry2, Q_LIMIT_ENABLEf, 1);
  12666 
  12667         /* Set MMU_THDU_XPIPE_Q_TO_QGRP_MAP.DISABLE_QUEUING to 1 when both MIN
  12668          * and SHARED LIMIT are 0. Set it to 0 when either MIN or SHARED LIMIT
  12669          * is non-zero.
  12670          */
  12671         limit = soc_mem_field32_get(unit, mem, entry, Q_MIN_LIMIT_CELLf);
  12672         if (arg == 0 && limit == 0) {
  12673             soc_mem_field32_set(unit, mem2, entry2, DISABLE_QUEUINGf, 1);
  12674         } else if (arg != 0 || limit != 0) {
  12675             soc_mem_field32_set(unit, mem2, entry2, DISABLE_QUEUINGf, 0);
  12676         }
  12677         spid = soc_mem_field32_get(unit, mem2, entry2, fld_sp);
  12678         granularity = 1;
  12679         break;
  12680     case bcmCosqControlEgressMCQueueSharedLimitBytes:
  12681         fld_limit = Q_SHARED_LIMITf;
  12682         soc_mem_field32_set(unit, mem, entry, Q_LIMIT_ENABLEf, 1);
  12683 
  12684         /* Config LIMIT in THDO_MC_QE: in 4-enties granularity */
  12685         granularity = 4;
  12686         soc_mem_field32_set(unit, mem2, entry2, fld_limit, (arg/granularity));
  12687         soc_mem_field32_set(unit, mem2, entry2, Q_LIMIT_ENABLEf, 1);
  12688         spid = soc_mem_field32_get(unit, mem, entry, fld_sp);
  12689         granularity = 1;
  12690         break;
  12691     case bcmCosqControlEgressUCQueueMinLimitBytes:
  12692         fld_limit = Q_MIN_LIMIT_CELLf;
  12693 
  12694         /* Set MMU_THDU_XPIPE_Q_TO_QGRP_MAP.DISABLE_QUEUING to 1 when both MIN
  12695                 * and SHARED LIMIT are 0. Set it to 0 when either MIN or SHARED LIMIT is non-zero
  12696                 */
  12697         limit = soc_mem_field32_get(unit, mem, entry, Q_SHARED_LIMIT_CELLf);
  12698         if (arg == 0 && limit == 0) {
  12699             soc_mem_field32_set(unit, mem2, entry2, DISABLE_QUEUINGf, 1);
  12700         } else if (arg != 0 || limit != 0) {
  12701             soc_mem_field32_set(unit, mem2, entry2, DISABLE_QUEUINGf, 0);
  12702         }
  12703         spid = soc_mem_field32_get(unit, mem2, entry2, fld_sp);
  12704         granularity = 1;
  12705         break;
  12706     case bcmCosqControlEgressMCQueueMinLimitBytes:
  12707         fld_limit = Q_MIN_LIMITf;
  12708 
  12709         /* Config LIMIT in THDO_MC_QE: in 4-enties granularity */
  12710         granularity = 4;
  12711         soc_mem_field32_set(unit, mem2, entry2, fld_limit, (arg/granularity));
  12712         spid = soc_mem_field32_get(unit, mem, entry, fld_sp);
  12713         granularity = 1;
  12714         break;
  12715     default:
  12716         return BCM_E_UNAVAIL;
  12717     }
  12718 
  12719     BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry));
  12720 
  12721     BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem2, MEM_BLOCK_ALL, startq, entry2));
  12722 
  12723 
  12724     /* Recalculate Shared Values if Min Changed */
  12725     SOC_IF_ERROR_RETURN(READ_MMU_THDM_DB_POOL_SHARED_LIMITr(unit, spid, &rval));
  12726     shared_size = soc_reg_field_get(unit, MMU_THDM_DB_POOL_SHARED_LIMITr,
  12727                                     rval, SHARED_LIMITf);
  12728     cur_val = soc_mem_field32_get(unit, mem, entry, fld_limit);
  12729         
  12730     if ((arg / granularity) > cur_val) {
  12731         /* New Min Val > Cur Min Val
  12732          * So reduce the Shared values first and then 
  12733          * Increase the Min Value for given resource
  12734          */
  12735         post_update = 0;
  12736     } else if ((arg / granularity) < cur_val) {
  12737         /* New Min Val < Cur Min Val
  12738          * So reduce the Min values first and then 
  12739          * Increase Shared values everywhere
  12740          */
  12741         post_update = 1;
  12742     } else {
  12743         return BCM_E_NONE;
  12744     }
  12745  
  12746     if (!post_update &&
  12747         ((type == bcmCosqControlEgressUCQueueMinLimitBytes) ||
  12748          (type == bcmCosqControlEgressMCQueueMinLimitBytes))) {
  12749         int delta = 0; /* In Cells */
  12750         delta = ((arg / granularity) - cur_val) * granularity;
  12751         if (delta > shared_size) {
  12752             return BCM_E_RESOURCE;
  12753         }
  12754         rv = soc_td2_mmu_config_res_limits_update(unit, spid,
  12755                                                   shared_size - delta, 1);
  12756         if (rv < 0) { 
  12757             return rv;
  12758         }
  12759     }
  12760 
  12761 
  12762     /* Check for min/max values */
  12763     max_val = (1 << soc_mem_field_length(unit, mem, fld_limit)) - 1;
  12764     if ((arg < 0) || ((arg/granularity) > max_val)) {
  12765         return BCM_E_PARAM;
  12766     } else {
  12767         /* Get the latest entry data and update. */
  12768         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL,
  12769                                          startq, entry));
  12770         soc_mem_field32_set(unit, mem, entry, fld_limit, (arg/granularity));
  12771         BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry));
  12772     }
  12773 
  12774     if (post_update && 
  12775         ((type == bcmCosqControlEgressUCQueueMinLimitBytes) ||
  12776          (type == bcmCosqControlEgressMCQueueMinLimitBytes))) {
  12777         int delta = 0;
  12778         delta = (cur_val - (arg / granularity)) * granularity;
  12779         rv = soc_td2_mmu_config_res_limits_update(unit, spid,
  12780                                                   shared_size + delta, 0);
  12781         if (rv < 0) { 
  12782             return rv;
  12783         }
  12784     }
  12785 
  12786     return BCM_E_NONE;
  12787 }
  12788 
  12789 STATIC int
  12790 _bcm_td2_cosq_egr_queue_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
  12791                             bcm_cosq_control_t type, int *arg)
  12792 {
  12793     bcm_port_t local_port;
  12794     int startq;
  12795     uint32 entry[SOC_MAX_MEM_WORDS];
  12796     soc_mem_t mem = INVALIDm;
  12797     soc_field_t fld_limit = INVALIDf;
  12798     int granularity = 1;
  12799     int from_cos, to_cos, ci;
  12800 
  12801     if (!arg) {
  12802         return BCM_E_PARAM;
  12803     }
  12804 
  12805     if ((type == bcmCosqControlEgressUCQueueMinLimitBytes) ||
  12806         (type == bcmCosqControlEgressUCQueueSharedLimitBytes)) {
  12807         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  12808             BCM_IF_ERROR_RETURN
  12809                 (_bcm_td2_cosq_index_resolve(unit, gport, cosq,
  12810                                              _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE,
  12811                                              &local_port, &startq, NULL));
  12812         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  12813             return BCM_E_PARAM;
  12814         }
  12815         else {
  12816             if (cosq == BCM_COS_INVALID) {
  12817                 from_cos = to_cos = 0;
  12818             } else {
  12819                 from_cos = to_cos = cosq;
  12820             }
  12821 
  12822             BCM_IF_ERROR_RETURN
  12823                 (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port));
  12824             if (local_port < 0) {
  12825                 return BCM_E_PORT;
  12826             }
  12827             for (ci = from_cos; ci <= to_cos; ci++) {
  12828                 BCM_IF_ERROR_RETURN
  12829                     (_bcm_td2_cosq_index_resolve
  12830                      (unit, local_port, ci, _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE,
  12831                       NULL, &startq, NULL));
  12832             }
  12833         }
  12834         mem = SOC_TD2_PMEM(unit, local_port, MMU_THDU_XPIPE_CONFIG_QUEUEm,
  12835                            MMU_THDU_YPIPE_CONFIG_QUEUEm);
  12836     } else if ((type == bcmCosqControlEgressMCQueueMinLimitBytes) ||
  12837                (type == bcmCosqControlEgressMCQueueSharedLimitBytes)) {
  12838         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  12839             return BCM_E_PARAM;
  12840         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  12841             BCM_IF_ERROR_RETURN
  12842                 (_bcm_td2_cosq_index_resolve(unit, gport, cosq,
  12843                                              _BCM_TD2_COSQ_INDEX_STYLE_MCAST_QUEUE,
  12844                                              &local_port, &startq, NULL));
  12845         }
  12846         else {
  12847             if (cosq == BCM_COS_INVALID) {
  12848                 from_cos = to_cos = 0;
  12849             } else {
  12850                 from_cos = to_cos = cosq;
  12851             }
  12852 
  12853             BCM_IF_ERROR_RETURN
  12854                 (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port));
  12855             if (local_port < 0) {
  12856                 return BCM_E_PORT;
  12857             }
  12858             for (ci = from_cos; ci <= to_cos; ci++) {
  12859                 BCM_IF_ERROR_RETURN
  12860                     (_bcm_td2_cosq_index_resolve
  12861                      (unit, local_port, ci, _BCM_TD2_COSQ_INDEX_STYLE_MCAST_QUEUE,
  12862                       NULL, &startq, NULL));
  12863             }
  12864         }
  12865         mem = SOC_TD2_PMEM(unit, local_port, MMU_THDM_DB_QUEUE_CONFIG_0m, 
  12866                            MMU_THDM_DB_QUEUE_CONFIG_1m);
  12867         startq -= 1480; /* MC queues comes after UC queues */
  12868     } else {
  12869         return BCM_E_PARAM;
  12870     }
  12871 
  12872     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL,
  12873                              startq, entry));
  12874 
  12875     switch (type) {
  12876     case bcmCosqControlEgressUCQueueSharedLimitBytes:
  12877         fld_limit = Q_SHARED_LIMIT_CELLf;
  12878         granularity = 1;
  12879         break;
  12880     case bcmCosqControlEgressMCQueueSharedLimitBytes:
  12881         fld_limit = Q_SHARED_LIMITf;
  12882         granularity = 1;
  12883         break;
  12884     case bcmCosqControlEgressUCQueueMinLimitBytes:
  12885         fld_limit = Q_MIN_LIMIT_CELLf;
  12886         granularity = 1;
  12887         break;
  12888     case bcmCosqControlEgressMCQueueMinLimitBytes:
  12889         fld_limit = Q_MIN_LIMITf;
  12890         granularity = 1;
  12891         break;
  12892     default:
  12893         return BCM_E_UNAVAIL;
  12894     }
  12895     *arg = soc_mem_field32_get(unit, mem, entry, fld_limit);
  12896     *arg = (*arg) * granularity * _BCM_TD2_BYTES_PER_CELL;
  12897     return BCM_E_NONE;
  12898 }
  12899 
  12900 STATIC int
  12901 _bcm_td2_cosq_ing_res_set(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
  12902                           bcm_cosq_control_t type, int arg)
  12903 {
  12904     bcm_port_t local_port;
  12905     int midx;
  12906     uint32 max_val, rval;
  12907     uint32 entry[SOC_MAX_MEM_WORDS];
  12908     soc_mem_t mem = INVALIDm;
  12909     soc_field_t fld_limit = INVALIDf;
  12910     soc_reg_t reg = INVALIDr;
  12911     int port_pg, port_pg_pool, granularity = 1;
  12912     static const soc_reg_t prigroup_reg[] = {
  12913         THDI_PORT_PRI_GRP0r, THDI_PORT_PRI_GRP1r
  12914     };
  12915     static const soc_field_t prigroup_field[] = {
  12916         PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf,
  12917         PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf,
  12918         PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf,
  12919         PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf
  12920     };
  12921     static const soc_field_t prigroup_spid_field[] = {
  12922         PG0_SPIDf, PG1_SPIDf, PG2_SPIDf, PG3_SPIDf,
  12923         PG4_SPIDf, PG5_SPIDf, PG6_SPIDf, PG7_SPIDf
  12924     };
  12925 
  12926     if (cosq > 15 || cosq < 0) {
  12927         /* Error. Input pri > Max Pri_Grp */
  12928         return BCM_E_PARAM;
  12929     }
  12930 
  12931     if (arg < 0) {
  12932         return BCM_E_PARAM;
  12933     }
  12934 
  12935     arg /= _BCM_TD2_BYTES_PER_CELL;
  12936     BCM_IF_ERROR_RETURN
  12937         (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port));
  12938     if (local_port < 0) {
  12939         return BCM_E_PORT;
  12940     }
  12941 
  12942     /* get PG for port using Port+Cos */
  12943     if (cosq < 8) {
  12944         reg = prigroup_reg[0];
  12945     } else {
  12946         reg = prigroup_reg[1];
  12947     }
  12948 
  12949     SOC_IF_ERROR_RETURN
  12950         (soc_reg32_get(unit, reg, local_port, 0, &rval));
  12951     port_pg = soc_reg_field_get(unit, reg, rval, prigroup_field[cosq]);
  12952 
  12953  
  12954     if ((type == bcmCosqControlIngressPortPGSharedLimitBytes) ||
  12955         (type == bcmCosqControlIngressPortPGMinLimitBytes)||
  12956         (type == bcmCosqControlIngressPortPGHeadroomLimitBytes)||
  12957         (type == bcmCosqControlIngressPortPGResetFloorBytes)) {
  12958         mem = SOC_TD2_PMEM(unit, local_port, THDI_PORT_PG_CONFIG_Xm,
  12959                                              THDI_PORT_PG_CONFIG_Ym);
  12960         /* get index for Port-PG */
  12961         midx = SOC_TD2_MMU_PIPED_MEM_INDEX(unit, local_port, mem, port_pg);
  12962         
  12963     } else if ((type == bcmCosqControlIngressPortPoolMaxLimitBytes) ||
  12964                (type == bcmCosqControlIngressPortPoolMinLimitBytes)) {
  12965         reg = THDI_PORT_PG_SPIDr;
  12966 
  12967         SOC_IF_ERROR_RETURN
  12968             (soc_reg32_get(unit, reg, local_port, 0, &rval));
  12969         port_pg_pool = soc_reg_field_get(unit, reg, rval, prigroup_spid_field[port_pg]);
  12970 
  12971         mem = SOC_TD2_PMEM(unit, local_port, THDI_PORT_SP_CONFIG_Xm,
  12972                                              THDI_PORT_SP_CONFIG_Ym);
  12973         /* get index for Port-SP */
  12974         midx = SOC_TD2_MMU_PIPED_MEM_INDEX(unit, local_port, mem, port_pg_pool);
  12975     } else {
  12976         return BCM_E_UNAVAIL;
  12977     }
  12978 
  12979     if (midx < 0) {
  12980         return BCM_E_PARAM;
  12981     }
  12982 
  12983     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, entry));
  12984 
  12985     switch (type) {
  12986     case bcmCosqControlIngressPortPGSharedLimitBytes:
  12987         fld_limit = PG_SHARED_LIMITf;
  12988         granularity = 1;
  12989         break;
  12990     case bcmCosqControlIngressPortPoolMaxLimitBytes:
  12991         fld_limit = PORT_SP_MAX_LIMITf;
  12992         granularity = 1;
  12993         break;
  12994     case bcmCosqControlIngressPortPGMinLimitBytes:
  12995         fld_limit = PG_MIN_LIMITf;
  12996         granularity = 1;
  12997         break;
  12998     case bcmCosqControlIngressPortPoolMinLimitBytes:
  12999         fld_limit = PORT_SP_MIN_LIMITf;
  13000         granularity = 1;
  13001         break;
  13002     case bcmCosqControlIngressPortPGHeadroomLimitBytes:
  13003         fld_limit = PG_HDRM_LIMITf;
  13004         granularity = 1;
  13005         break;
  13006     case bcmCosqControlIngressPortPGResetFloorBytes:
  13007         fld_limit = PG_RESET_FLOORf;
  13008         granularity = 1;
  13009         break;
  13010     /* coverity[dead_error_begin] */
  13011     default:
  13012         return BCM_E_UNAVAIL;
  13013     }
  13014 
  13015     /* Check for min/max values */
  13016     max_val = (1 << soc_mem_field_length(unit, mem, fld_limit)) - 1;
  13017     if ((arg < 0) || ((arg/granularity) > max_val)) {
  13018         return BCM_E_PARAM;
  13019     } else {
  13020         soc_mem_field32_set(unit, mem, entry, fld_limit, (arg/granularity));
  13021     }
  13022     BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, midx, entry));
  13023 
  13024     return BCM_E_NONE;
  13025 }
  13026 
  13027 STATIC int
  13028 _bcm_td2_cosq_state_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
  13029                           bcm_cosq_control_t type, int *arg)
  13030 {
  13031     bcm_port_t local_port;
  13032     uint32 rval, state , mask = 1 , bitno = 0;
  13033     static const soc_field_t pool_field[] = {
  13034         POOL_0f, POOL_1f, POOL_2f, POOL_3f }; 
  13035     int start_pool_idx = 0,end_pool_idx = 0;    
  13036     if (!arg) {
  13037         return BCM_E_PARAM;
  13038     }
  13039     switch (type) {
  13040         case bcmCosqControlSPPortLimitState:
  13041         case bcmCosqControlPoolRedDropState:
  13042         case bcmCosqControlPoolYellowDropState:
  13043         case bcmCosqControlPoolGreenDropState:
  13044             BCM_IF_ERROR_RETURN
  13045                 (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port));
  13046 
  13047             if (!SOC_PORT_VALID(unit, local_port)) {
  13048                 return BCM_E_PORT;
  13049             }
  13050             BCM_IF_ERROR_RETURN (_bcm_td2_cosq_egress_sp_get(unit, gport, cosq, &start_pool_idx, 
  13051                         &end_pool_idx)); 
  13052             bitno = start_pool_idx; 
  13053             break;
  13054    
  13055         case bcmCosqControlPGPortLimitState:
  13056         case bcmCosqControlPGPortXoffState:
  13057             BCM_IF_ERROR_RETURN
  13058                 (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port));
  13059 
  13060             if (!SOC_PORT_VALID(unit, local_port)) {
  13061                 return BCM_E_PORT;
  13062             }
  13063             if ((cosq < 0 ) || (cosq > 7)) {
  13064                 return BCM_E_PARAM;
  13065             }
  13066             bitno = cosq;
  13067             break;
  13068         default:
  13069             return BCM_E_PARAM;
  13070     }
  13071     switch (type) {
  13072         case bcmCosqControlSPPortLimitState:
  13073             SOC_IF_ERROR_RETURN(
  13074                     READ_THDI_PORT_LIMIT_STATESr(unit, local_port, &rval));
  13075             state = soc_reg_field_get(unit, THDI_PORT_LIMIT_STATESr, rval,
  13076                     SP_LIMIT_STATEf);
  13077             break;
  13078         case bcmCosqControlPGPortLimitState:
  13079             SOC_IF_ERROR_RETURN(
  13080                     READ_THDI_PORT_LIMIT_STATESr(unit, local_port, &rval));
  13081             state = soc_reg_field_get(unit, THDI_PORT_LIMIT_STATESr, rval,
  13082                     PG_LIMIT_STATEf);
  13083             break;
  13084         case bcmCosqControlPGPortXoffState:
  13085             SOC_IF_ERROR_RETURN(
  13086                     READ_THDI_FLOW_CONTROL_XOFF_STATEr(unit, local_port, &rval));
  13087             state = soc_reg_field_get(unit, THDI_FLOW_CONTROL_XOFF_STATEr, rval,
  13088                     PG_BMPf);
  13089             break;
  13090         case bcmCosqControlPoolRedDropState:
  13091             SOC_IF_ERROR_RETURN(
  13092                     READ_THDI_POOL_DROP_STATEr(unit, &rval));
  13093             state = soc_reg_field_get(unit, THDI_POOL_DROP_STATEr, rval,
  13094                     pool_field[start_pool_idx]);
  13095             bitno = 2;
  13096             break;
  13097         case bcmCosqControlPoolYellowDropState:
  13098             SOC_IF_ERROR_RETURN(
  13099                     READ_THDI_POOL_DROP_STATEr(unit, &rval));
  13100             state = soc_reg_field_get(unit, THDI_POOL_DROP_STATEr, rval,
  13101                     pool_field[start_pool_idx]);
  13102             bitno = 1;
  13103             break;
  13104         case bcmCosqControlPoolGreenDropState:
  13105             SOC_IF_ERROR_RETURN(
  13106                     READ_THDI_POOL_DROP_STATEr(unit, &rval));
  13107             state = soc_reg_field_get(unit, THDI_POOL_DROP_STATEr, rval,
  13108                     pool_field[start_pool_idx]);
  13109             bitno = 0;
  13110             break;
  13111         /*
  13112          * COVERITY
  13113          *
  13114          * This default is unreachable but needed for some compiler. 
  13115          */ 
  13116         /* coverity[dead_error_begin] */
  13117         default :
  13118             return BCM_E_PARAM;
  13119     }
  13120     mask = mask<<bitno; 
  13121     state = state & mask ;
  13122     if (state) {
  13123         *arg = 1 ;
  13124     } else {
  13125         *arg = 0 ;
  13126     }
  13127     return BCM_E_NONE;
  13128 }
  13129 
  13130 STATIC int
  13131 _bcm_td2_cosq_ing_res_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
  13132                           bcm_cosq_control_t type, int *arg)
  13133 {
  13134     bcm_port_t local_port;
  13135     uint32 rval;
  13136     uint32 entry[SOC_MAX_MEM_WORDS];
  13137     soc_mem_t mem = INVALIDm;
  13138     soc_field_t fld_limit = INVALIDf;
  13139     soc_reg_t reg = INVALIDr;
  13140     int midx, port_pg, port_pg_pool, granularity = 1;
  13141     static const soc_reg_t prigroup_reg[] = {
  13142         THDI_PORT_PRI_GRP0r, THDI_PORT_PRI_GRP1r
  13143     };
  13144     static const soc_field_t prigroup_field[] = {
  13145         PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf,
  13146         PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf,
  13147         PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf,
  13148         PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf
  13149     };
  13150     static const soc_field_t prigroup_spid_field[] = {
  13151         PG0_SPIDf, PG1_SPIDf, PG2_SPIDf, PG3_SPIDf,
  13152         PG4_SPIDf, PG5_SPIDf, PG6_SPIDf, PG7_SPIDf
  13153     };
  13154 
  13155     if (cosq > 15 || cosq < 0) {
  13156         /* Error. Input pri > Max Pri_Grp */
  13157         return BCM_E_PARAM;
  13158     }
  13159     if (!arg) {
  13160         return BCM_E_PARAM;
  13161     }
  13162 
  13163     BCM_IF_ERROR_RETURN
  13164         (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port));
  13165     if (local_port < 0) {
  13166         return BCM_E_PORT;
  13167     }
  13168 
  13169     /* get PG for port using Port+Cos */
  13170     if (cosq < 8) {
  13171         reg = prigroup_reg[0];
  13172     } else {
  13173         reg = prigroup_reg[1];
  13174     }
  13175 
  13176     SOC_IF_ERROR_RETURN
  13177         (soc_reg32_get(unit, reg, local_port, 0, &rval));
  13178     port_pg = soc_reg_field_get(unit, reg, rval, prigroup_field[cosq]);
  13179 
  13180  
  13181     if ((type == bcmCosqControlIngressPortPGSharedLimitBytes) ||
  13182         (type == bcmCosqControlIngressPortPGMinLimitBytes)||
  13183         (type == bcmCosqControlIngressPortPGHeadroomLimitBytes)||
  13184         (type == bcmCosqControlIngressPortPGResetFloorBytes)) {
  13185         mem = SOC_TD2_PMEM(unit, local_port, THDI_PORT_PG_CONFIG_Xm,
  13186                                              THDI_PORT_PG_CONFIG_Ym);
  13187         /* get index for Port-PG */
  13188         midx = SOC_TD2_MMU_PIPED_MEM_INDEX(unit, local_port, mem, port_pg);
  13189     } else if ((type == bcmCosqControlIngressPortPoolMaxLimitBytes) ||
  13190                (type == bcmCosqControlIngressPortPoolMinLimitBytes)) {
  13191         reg = THDI_PORT_PG_SPIDr;
  13192 
  13193         SOC_IF_ERROR_RETURN
  13194             (soc_reg32_get(unit, reg, local_port, 0, &rval));
  13195         port_pg_pool = soc_reg_field_get(unit, reg, rval, prigroup_spid_field[port_pg]);
  13196 
  13197         mem = SOC_TD2_PMEM(unit, local_port, THDI_PORT_SP_CONFIG_Xm,
  13198                                              THDI_PORT_SP_CONFIG_Ym);
  13199         /* get index for Port-SP */
  13200         midx = SOC_TD2_MMU_PIPED_MEM_INDEX(unit, local_port, mem, port_pg_pool);
  13201     } else {
  13202         return BCM_E_UNAVAIL;
  13203     }
  13204 
  13205     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, entry));
  13206 
  13207     switch (type) {
  13208     case bcmCosqControlIngressPortPGSharedLimitBytes:
  13209         fld_limit = PG_SHARED_LIMITf;
  13210         granularity = 1;
  13211         break;
  13212     case bcmCosqControlIngressPortPoolMaxLimitBytes:
  13213         fld_limit = PORT_SP_MAX_LIMITf;
  13214         granularity = 1;
  13215         break;
  13216     case bcmCosqControlIngressPortPGMinLimitBytes:
  13217         fld_limit = PG_MIN_LIMITf;
  13218         granularity = 1;
  13219         break;
  13220     case bcmCosqControlIngressPortPoolMinLimitBytes:
  13221         fld_limit = PORT_SP_MIN_LIMITf;
  13222         granularity = 1;
  13223         break;
  13224     case bcmCosqControlIngressPortPGHeadroomLimitBytes:
  13225         fld_limit = PG_HDRM_LIMITf;
  13226         granularity = 1;
  13227         break;
  13228     case bcmCosqControlIngressPortPGResetFloorBytes:
  13229         fld_limit = PG_RESET_FLOORf;
  13230         granularity = 1;
  13231         break;
  13232     /* coverity[dead_error_begin] */
  13233     default:
  13234         return BCM_E_UNAVAIL;
  13235     }
  13236 
  13237     *arg = soc_mem_field32_get(unit, mem, entry, fld_limit);
  13238     *arg = (*arg) * granularity * _BCM_TD2_BYTES_PER_CELL;
  13239     return BCM_E_NONE;
  13240 }
  13241 
  13242 /*
  13243  * This function is used to get ingress pool
  13244  * limit given Ingress [Port, Priority]
  13245  */
  13246 STATIC int
  13247 _bcm_td2_cosq_ing_res_limit_get(int unit, bcm_gport_t gport, bcm_cos_t cosq,
  13248                                bcm_cosq_control_t type, int *arg)
  13249 {
  13250     bcm_port_t local_port;
  13251     uint32 rval;
  13252     soc_reg_t reg = INVALIDr;
  13253     int port_pg, port_pg_pool;
  13254     static const soc_reg_t prigroup_reg[] = {
  13255        THDI_PORT_PRI_GRP0r, THDI_PORT_PRI_GRP1r
  13256     };
  13257     static const soc_field_t prigroup_field[] = {
  13258        PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf,
  13259        PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf,
  13260        PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf,
  13261        PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf
  13262     };
  13263     static const soc_field_t prigroup_spid_field[] = {
  13264        PG0_SPIDf, PG1_SPIDf, PG2_SPIDf, PG3_SPIDf,
  13265        PG4_SPIDf, PG5_SPIDf, PG6_SPIDf, PG7_SPIDf
  13266     };
  13267 
  13268     if (cosq > 15 || cosq < 0) {
  13269        /* Error. Input pri > Max Pri_Grp */
  13270        return BCM_E_PARAM;
  13271     }
  13272     if (!arg) {
  13273        return BCM_E_PARAM;
  13274     }
  13275 
  13276     BCM_IF_ERROR_RETURN
  13277        (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port));
  13278     if (local_port < 0) {
  13279        return BCM_E_PORT;
  13280     }
  13281     
  13282     /* get PG for port using Port+Cos */
  13283     if (cosq < 8) {
  13284         reg = prigroup_reg[0];
  13285     } else {
  13286         reg = prigroup_reg[1];
  13287     }
  13288 
  13289     SOC_IF_ERROR_RETURN
  13290        (soc_reg32_get(unit, reg, local_port, 0, &rval));
  13291     port_pg = soc_reg_field_get(unit, reg, rval, prigroup_field[cosq]);
  13292 
  13293 
  13294     if (type == bcmCosqControlIngressPoolLimitBytes) {
  13295         reg = THDI_PORT_PG_SPIDr;
  13296 
  13297         SOC_IF_ERROR_RETURN
  13298             (soc_reg32_get(unit, reg, local_port, 0, &rval));
  13299         port_pg_pool = soc_reg_field_get(unit, reg, rval, prigroup_spid_field[port_pg]);
  13300 
  13301         SOC_IF_ERROR_RETURN
  13302             (READ_THDI_BUFFER_CELL_LIMIT_SPr(unit, port_pg_pool, &rval));
  13303         *arg = soc_reg_field_get(unit, THDI_BUFFER_CELL_LIMIT_SPr, rval, LIMITf);
  13304     } else {
  13305         return BCM_E_PARAM;
  13306     }
  13307 
  13308     *arg = (*arg) * _BCM_TD2_BYTES_PER_CELL;
  13309 
  13310     return BCM_E_NONE;
  13311 }
  13312 
  13313 /*
  13314  * This function is used to set ingress pool
  13315  * limit given Ingress [Port, Priority]
  13316  */
  13317 STATIC int
  13318 _bcm_td2_cosq_ing_res_limit_set(int unit, bcm_gport_t gport, bcm_cos_t cosq,
  13319                                bcm_cosq_control_t type, int arg)
  13320 {
  13321     bcm_port_t local_port;
  13322     uint32 max_val, rval;
  13323     soc_reg_t reg = INVALIDr;
  13324     int port_pg, port_pg_pool;
  13325     static const soc_reg_t prigroup_reg[] = {
  13326         THDI_PORT_PRI_GRP0r, THDI_PORT_PRI_GRP1r
  13327     };
  13328     static const soc_field_t prigroup_field[] = {
  13329         PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf,
  13330         PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf,
  13331         PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf,
  13332         PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf
  13333     };
  13334     static const soc_field_t prigroup_spid_field[] = {
  13335         PG0_SPIDf, PG1_SPIDf, PG2_SPIDf, PG3_SPIDf,
  13336         PG4_SPIDf, PG5_SPIDf, PG6_SPIDf, PG7_SPIDf
  13337     };
  13338 
  13339     if (cosq > 15 || cosq < 0) {
  13340         /* Error. Input pri > Max Pri_Grp */
  13341         return BCM_E_PARAM;
  13342     }
  13343 
  13344     if (arg < 0) {
  13345         return BCM_E_PARAM;
  13346     }
  13347 
  13348     arg /= _BCM_TD2_BYTES_PER_CELL;
  13349     BCM_IF_ERROR_RETURN
  13350         (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port));
  13351     if (local_port < 0) {
  13352         return BCM_E_PORT;
  13353     }
  13354 
  13355     /* get PG for port using Port+Cos */
  13356     if (cosq < 8) {
  13357         reg = prigroup_reg[0];
  13358     } else {
  13359         reg = prigroup_reg[1];
  13360     }
  13361 
  13362     SOC_IF_ERROR_RETURN
  13363         (soc_reg32_get(unit, reg, local_port, 0, &rval));
  13364     port_pg = soc_reg_field_get(unit, reg, rval, prigroup_field[cosq]);
  13365 
  13366     if (type == bcmCosqControlIngressPoolLimitBytes) {
  13367         reg = THDI_PORT_PG_SPIDr;
  13368 
  13369         SOC_IF_ERROR_RETURN
  13370             (soc_reg32_get(unit, reg, local_port, 0, &rval));
  13371         port_pg_pool = soc_reg_field_get(unit, reg, rval, prigroup_spid_field[port_pg]);
  13372         
  13373         rval = 0;
  13374         SOC_IF_ERROR_RETURN(READ_THDI_BUFFER_CELL_LIMIT_SPr(unit, port_pg_pool, &rval));
  13375         /* Check for min/max values */
  13376         max_val = (1 << soc_reg_field_length(unit, THDI_BUFFER_CELL_LIMIT_SPr, LIMITf)) - 1;
  13377         if ((arg < 0) || (arg > max_val)) {
  13378             return BCM_E_PARAM;
  13379         } else {
  13380             soc_reg_field_set(unit, THDI_BUFFER_CELL_LIMIT_SPr, &rval, LIMITf, arg);
  13381         }
  13382         
  13383         SOC_IF_ERROR_RETURN(WRITE_THDI_BUFFER_CELL_LIMIT_SPr(unit, port_pg_pool, rval));
  13384     } else {
  13385         return BCM_E_PARAM;
  13386     }
  13387 
  13388     return BCM_E_NONE;
  13389 }
  13390 
  13391 
  13392 STATIC int
  13393 _bcm_td2_cosq_ef_op_at_index(int unit, int port, int hw_index, _bcm_cosq_op_t op, 
  13394                              int *ef_val)
  13395 {
  13396     uint32 entry[SOC_MAX_MEM_WORDS];
  13397     soc_trident2_sched_type_t sched_type;
  13398     soc_mem_t mem;
  13399 
  13400     sched_type = _soc_trident2_port_sched_type_get(unit, port);
  13401 
  13402     if (sched_type == SOC_TD2_SCHED_LLS) {
  13403         mem = _SOC_TD2_NODE_PARENT_MEM(unit, port, SOC_TD2_NODE_LVL_L2);
  13404         SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, hw_index, &entry));
  13405 
  13406         if (op == _BCM_COSQ_OP_GET) {
  13407             *ef_val = soc_mem_field32_get(unit, mem, &entry, C_EFf);
  13408         } else {
  13409             soc_mem_field32_set(unit, mem, &entry, C_EFf, *ef_val);
  13410             SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, 
  13411                                 hw_index, &entry));
  13412         }
  13413     } else {
  13414         return BCM_E_UNAVAIL;
  13415     }
  13416    
  13417     return BCM_E_NONE;
  13418 }
  13419 
  13420 STATIC int
  13421 _bcm_td2_cosq_ef_op(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, int *arg,
  13422                     _bcm_cosq_op_t op)
  13423 {
  13424     _bcm_td2_cosq_node_t *node;
  13425     bcm_port_t local_port;
  13426     int index, numq, from_cos, to_cos, ci;
  13427 
  13428     if (BCM_GPORT_IS_SCHEDULER(gport)) {
  13429         BCM_IF_ERROR_RETURN
  13430             (_bcm_td2_cosq_node_get(unit, gport, 0, NULL, 
  13431                                     &local_port, NULL, &node));
  13432         BCM_IF_ERROR_RETURN(
  13433                _bcm_td2_cosq_child_node_at_input(node, cosq, &node));
  13434         gport = node->gport;
  13435         cosq = 0;
  13436     }
  13437 
  13438     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  13439         BCM_IF_ERROR_RETURN
  13440             (_bcm_td2_cosq_index_resolve
  13441              (unit, gport, cosq, _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE,
  13442               &local_port, &index, NULL));
  13443         return _bcm_td2_cosq_ef_op_at_index(unit, local_port, index, op, arg);
  13444     } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  13445         BCM_IF_ERROR_RETURN
  13446             (_bcm_td2_cosq_index_resolve
  13447              (unit, gport, cosq, _BCM_TD2_COSQ_INDEX_STYLE_MCAST_QUEUE,
  13448               &local_port, &index, NULL));
  13449         return _bcm_td2_cosq_ef_op_at_index(unit, local_port, index, op, arg);
  13450     } else if (BCM_GPORT_IS_SCHEDULER(gport)) {
  13451         return BCM_E_PARAM;
  13452     } else {
  13453         BCM_IF_ERROR_RETURN(_bcm_td2_cosq_port_has_ets(unit, local_port));
  13454         if (cosq == BCM_COS_INVALID) {
  13455             from_cos = 0;
  13456             to_cos = _TD2_NUM_COS(unit) - 1;
  13457         } else {
  13458             from_cos = to_cos = cosq;
  13459         }
  13460         for (ci = from_cos; ci <= to_cos; ci++) {
  13461             BCM_IF_ERROR_RETURN
  13462                 (_bcm_td2_cosq_index_resolve
  13463                  (unit, gport, ci, _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE,
  13464                   &local_port, &index, &numq));
  13465 
  13466             BCM_IF_ERROR_RETURN(_bcm_td2_cosq_ef_op_at_index(unit, 
  13467                                 local_port, index, op, arg));
  13468             if (op == _BCM_COSQ_OP_GET) {
  13469                 return BCM_E_NONE;
  13470             }
  13471 
  13472             BCM_IF_ERROR_RETURN
  13473                 (_bcm_td2_cosq_index_resolve
  13474                  (unit, gport, ci, _BCM_TD2_COSQ_INDEX_STYLE_MCAST_QUEUE,
  13475                   &local_port, &index, &numq));
  13476 
  13477             BCM_IF_ERROR_RETURN(_bcm_td2_cosq_ef_op_at_index(unit, 
  13478                                 local_port, index, op, arg));
  13479         }
  13480     }
  13481     return BCM_E_NONE;
  13482 }
  13483     
  13484 STATIC int
  13485 _bcm_td2_cosq_qcn_proxy_set(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 
  13486                             bcm_cosq_control_t type, int arg)
  13487 {
  13488     int local_port;
  13489     uint32 rval;
  13490     
  13491     BCM_IF_ERROR_RETURN
  13492         (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port));
  13493     
  13494     BCM_IF_ERROR_RETURN(READ_QCN_CNM_PRP_CTRLr(unit, local_port, &rval));
  13495     soc_reg_field_set(unit, QCN_CNM_PRP_CTRLr, &rval, ENABLEf, !!arg);
  13496     soc_reg_field_set(unit, QCN_CNM_PRP_CTRLr, &rval, PRIORITY_BMAPf, 0xff);
  13497     BCM_IF_ERROR_RETURN(WRITE_QCN_CNM_PRP_CTRLr(unit, local_port, rval));
  13498     return BCM_E_NONE;
  13499 }
  13500 
  13501 STATIC int
  13502 _bcm_td2_cosq_qcn_proxy_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
  13503                             bcm_cosq_control_t type, int *arg)
  13504 {
  13505     int local_port;
  13506     uint32 rval;
  13507 
  13508     BCM_IF_ERROR_RETURN
  13509         (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port));
  13510 
  13511     BCM_IF_ERROR_RETURN(READ_QCN_CNM_PRP_CTRLr(unit, local_port, &rval));
  13512     *arg = soc_reg_field_get(unit, QCN_CNM_PRP_CTRLr, rval, ENABLEf);
  13513 
  13514     return BCM_E_NONE;
  13515 }
  13516 
  13517 STATIC int
  13518 _bcm_td2_cosq_alpha_bcm_to_soc(int unit,
  13519     bcm_cosq_control_drop_limit_alpha_value_t arg,
  13520     soc_td2_drop_limit_alpha_value_t *val)
  13521 {
  13522     if (!val) {
  13523         return BCM_E_PARAM;
  13524     }
  13525 
  13526     switch(arg) {
  13527     case bcmCosqControlDropLimitAlpha_1_128:
  13528         *val = SOC_TD2_COSQ_DROP_LIMIT_ALPHA_1_128;
  13529         break;
  13530     case bcmCosqControlDropLimitAlpha_1_64:
  13531         *val = SOC_TD2_COSQ_DROP_LIMIT_ALPHA_1_64;
  13532         break;
  13533     case bcmCosqControlDropLimitAlpha_1_32:
  13534         *val = SOC_TD2_COSQ_DROP_LIMIT_ALPHA_1_32;
  13535         break;
  13536     case bcmCosqControlDropLimitAlpha_1_16:
  13537         *val = SOC_TD2_COSQ_DROP_LIMIT_ALPHA_1_16;
  13538         break;
  13539     case bcmCosqControlDropLimitAlpha_1_8:
  13540         *val = SOC_TD2_COSQ_DROP_LIMIT_ALPHA_1_8;
  13541         break;
  13542     case bcmCosqControlDropLimitAlpha_1_4:
  13543         *val = SOC_TD2_COSQ_DROP_LIMIT_ALPHA_1_4;
  13544         break;
  13545     case bcmCosqControlDropLimitAlpha_1_2:
  13546         *val = SOC_TD2_COSQ_DROP_LIMIT_ALPHA_1_2;
  13547         break;
  13548     case bcmCosqControlDropLimitAlpha_1:
  13549         *val = SOC_TD2_COSQ_DROP_LIMIT_ALPHA_1;
  13550         break;
  13551     case bcmCosqControlDropLimitAlpha_2:
  13552         *val = SOC_TD2_COSQ_DROP_LIMIT_ALPHA_2;
  13553         break;
  13554     case bcmCosqControlDropLimitAlpha_4:
  13555         *val = SOC_TD2_COSQ_DROP_LIMIT_ALPHA_4;
  13556         break;
  13557     case bcmCosqControlDropLimitAlpha_8:
  13558         *val = SOC_TD2_COSQ_DROP_LIMIT_ALPHA_8;
  13559         break;
  13560     default:
  13561         return BCM_E_PARAM;
  13562     }
  13563     
  13564     return BCM_E_NONE;
  13565 }
  13566 
  13567 STATIC int
  13568 _bcm_td2_cosq_alpha_soc_to_bcm(int unit,
  13569     soc_td2_drop_limit_alpha_value_t arg,
  13570     bcm_cosq_control_drop_limit_alpha_value_t *val)
  13571 {
  13572     if (!val) {
  13573         return BCM_E_PARAM;
  13574     }
  13575 
  13576     switch(arg) {
  13577     case SOC_TD2_COSQ_DROP_LIMIT_ALPHA_1_128:
  13578         *val = bcmCosqControlDropLimitAlpha_1_128;
  13579         break;
  13580     case SOC_TD2_COSQ_DROP_LIMIT_ALPHA_1_64:
  13581         *val = bcmCosqControlDropLimitAlpha_1_64;
  13582         break;
  13583     case SOC_TD2_COSQ_DROP_LIMIT_ALPHA_1_32:
  13584         *val = bcmCosqControlDropLimitAlpha_1_32;
  13585         break;
  13586     case SOC_TD2_COSQ_DROP_LIMIT_ALPHA_1_16:
  13587         *val = bcmCosqControlDropLimitAlpha_1_16;
  13588         break;
  13589     case SOC_TD2_COSQ_DROP_LIMIT_ALPHA_1_8:
  13590         *val = bcmCosqControlDropLimitAlpha_1_8;
  13591         break;
  13592     case SOC_TD2_COSQ_DROP_LIMIT_ALPHA_1_4:
  13593         *val = bcmCosqControlDropLimitAlpha_1_4;
  13594         break;
  13595     case SOC_TD2_COSQ_DROP_LIMIT_ALPHA_1_2:
  13596         *val = bcmCosqControlDropLimitAlpha_1_2;
  13597         break;
  13598     case SOC_TD2_COSQ_DROP_LIMIT_ALPHA_1:
  13599         *val = bcmCosqControlDropLimitAlpha_1;
  13600         break;
  13601     case SOC_TD2_COSQ_DROP_LIMIT_ALPHA_2:
  13602         *val = bcmCosqControlDropLimitAlpha_2;
  13603         break;
  13604     case SOC_TD2_COSQ_DROP_LIMIT_ALPHA_4:
  13605         *val = bcmCosqControlDropLimitAlpha_4;
  13606         break;
  13607     case SOC_TD2_COSQ_DROP_LIMIT_ALPHA_8:
  13608         *val = bcmCosqControlDropLimitAlpha_8;
  13609         break;
  13610     default:
  13611         return BCM_E_PARAM;
  13612     }
  13613     
  13614     return BCM_E_NONE;
  13615 }
  13616 
  13617 STATIC int
  13618 _bcm_td2_cosq_alpha_set(int unit,
  13619                         bcm_gport_t gport, bcm_cos_queue_t cosq,
  13620                         bcm_cosq_control_drop_limit_alpha_value_t arg)
  13621 {
  13622     bcm_port_t local_port;
  13623     int startq;
  13624     int midx;
  13625     uint32 rval, alpha;
  13626     uint32 entry[SOC_MAX_MEM_WORDS];
  13627     uint32 entry2[SOC_MAX_MEM_WORDS];
  13628     soc_mem_t mem = INVALIDm, mem2 = INVALIDm;
  13629     int dynamic_thresh_mode;
  13630     soc_reg_t reg = INVALIDr;
  13631     int port_pg;
  13632     soc_td2_drop_limit_alpha_value_t aget;
  13633     static const soc_reg_t prigroup_reg[] = {
  13634         THDI_PORT_PRI_GRP0r, THDI_PORT_PRI_GRP1r
  13635     };
  13636     static const soc_field_t prigroup_field[] = {
  13637         PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf,
  13638         PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf,
  13639         PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf,
  13640         PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf
  13641     };      
  13642 
  13643     BCM_IF_ERROR_RETURN(
  13644         _bcm_td2_cosq_alpha_bcm_to_soc(unit, arg, &aget));
  13645     alpha = (uint32)aget;
  13646 
  13647     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  13648         BCM_IF_ERROR_RETURN
  13649                 (_bcm_td2_cosq_dynamic_thresh_enable_get(unit, gport, cosq, 
  13650                                    bcmCosqControlEgressUCSharedDynamicEnable, 
  13651                                    &dynamic_thresh_mode));
  13652         if (!dynamic_thresh_mode){
  13653             return BCM_E_CONFIG;
  13654         } 
  13655         
  13656         BCM_IF_ERROR_RETURN
  13657             (_bcm_td2_cosq_index_resolve(unit, gport, cosq,
  13658                                      _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE,
  13659                                      &local_port, &startq, NULL));
  13660         mem = SOC_TD2_PMEM(unit, local_port, MMU_THDU_XPIPE_CONFIG_QUEUEm, 
  13661                            MMU_THDU_YPIPE_CONFIG_QUEUEm);
  13662         
  13663         BCM_IF_ERROR_RETURN
  13664             (soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  13665         soc_mem_field32_set(unit, mem, entry, 
  13666                             Q_SHARED_ALPHA_CELLf, alpha);
  13667         SOC_IF_ERROR_RETURN
  13668             (soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry));                 
  13669     } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  13670         BCM_IF_ERROR_RETURN
  13671                 (_bcm_td2_cosq_dynamic_thresh_enable_get(unit, gport, cosq, 
  13672                                    bcmCosqControlEgressMCSharedDynamicEnable, 
  13673                                    &dynamic_thresh_mode));
  13674         if (!dynamic_thresh_mode){
  13675             return BCM_E_CONFIG;
  13676         }
  13677         
  13678         BCM_IF_ERROR_RETURN
  13679             (_bcm_td2_cosq_index_resolve(unit, gport, cosq,
  13680                                      _BCM_TD2_COSQ_INDEX_STYLE_MCAST_QUEUE,
  13681                                      &local_port, &startq, NULL));
  13682         mem = SOC_TD2_PMEM(unit, local_port, MMU_THDM_DB_QUEUE_CONFIG_0m, 
  13683                                            MMU_THDM_DB_QUEUE_CONFIG_1m);
  13684         mem2 = SOC_TD2_PMEM(unit, local_port, MMU_THDM_MCQE_QUEUE_CONFIG_0m, 
  13685                                            MMU_THDM_MCQE_QUEUE_CONFIG_1m);
  13686 
  13687         startq -= 1480; /* MC queues comes after UC queues */
  13688         BCM_IF_ERROR_RETURN
  13689             (soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  13690         soc_mem_field32_set(unit, mem, entry, Q_SHARED_ALPHAf, alpha);
  13691         SOC_IF_ERROR_RETURN
  13692             (soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry));    
  13693 
  13694         BCM_IF_ERROR_RETURN
  13695             (soc_mem_read(unit, mem2, MEM_BLOCK_ALL, startq, entry2));
  13696         soc_mem_field32_set(unit, mem2, entry2, Q_SHARED_ALPHAf, alpha);
  13697         SOC_IF_ERROR_RETURN
  13698             (soc_mem_write(unit, mem2, MEM_BLOCK_ALL, startq, entry2));              
  13699     } else {
  13700         if (cosq > 15 || cosq < 0) {
  13701             return BCM_E_PARAM;
  13702         }
  13703 
  13704         BCM_IF_ERROR_RETURN
  13705                 (_bcm_td2_cosq_dynamic_thresh_enable_get(unit, gport, cosq,
  13706                                    bcmCosqControlIngressPortPGSharedDynamicEnable,
  13707                                    &dynamic_thresh_mode));
  13708         if (!dynamic_thresh_mode){
  13709             return BCM_E_CONFIG;
  13710         }
  13711 
  13712         BCM_IF_ERROR_RETURN
  13713             (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port));
  13714         if (local_port < 0) {
  13715             return BCM_E_PORT;
  13716         }
  13717 
  13718         /* get PG for port using Port+Cos */
  13719         if (cosq < 8) {
  13720             reg = prigroup_reg[0];
  13721         } else {
  13722             reg = prigroup_reg[1];
  13723         }
  13724 
  13725         SOC_IF_ERROR_RETURN
  13726             (soc_reg32_get(unit, reg, local_port, 0, &rval));
  13727         port_pg = soc_reg_field_get(unit, reg, rval, prigroup_field[cosq]);
  13728         mem = SOC_TD2_PMEM(unit, local_port, THDI_PORT_PG_CONFIG_Xm,
  13729                                              THDI_PORT_PG_CONFIG_Ym);
  13730         /* get index for Port-PG */
  13731         midx = SOC_TD2_MMU_PIPED_MEM_INDEX(unit, local_port, mem, port_pg);
  13732         BCM_IF_ERROR_RETURN
  13733             (soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, entry));
  13734         soc_mem_field32_set(unit, mem, entry, 
  13735                             PG_SHARED_LIMITf, alpha);
  13736         SOC_IF_ERROR_RETURN
  13737             (soc_mem_write(unit, mem, MEM_BLOCK_ALL, midx, entry)); 
  13738     } 
  13739     
  13740     return BCM_E_NONE;
  13741 }
  13742 
  13743 
  13744 STATIC int
  13745 _bcm_td2_cosq_alpha_get(int unit,
  13746                         bcm_gport_t gport, bcm_cos_queue_t cosq,
  13747                         bcm_cosq_control_drop_limit_alpha_value_t *arg)
  13748 {
  13749     bcm_port_t local_port;
  13750     int startq;
  13751     int midx;
  13752     uint32 rval;
  13753     uint32 entry[SOC_MAX_MEM_WORDS];
  13754     soc_mem_t mem = INVALIDm;
  13755     int alpha;
  13756     int dynamic_thresh_mode;
  13757     soc_reg_t reg = INVALIDr;
  13758     int port_pg;
  13759     static const soc_reg_t prigroup_reg[] = {
  13760         THDI_PORT_PRI_GRP0r, THDI_PORT_PRI_GRP1r
  13761     };
  13762     static const soc_field_t prigroup_field[] = {
  13763         PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf,
  13764         PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf,
  13765         PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf,
  13766         PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf
  13767     };      
  13768 
  13769     if (!arg) {
  13770         return BCM_E_PARAM;
  13771     }
  13772 
  13773     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  13774         BCM_IF_ERROR_RETURN
  13775                 (_bcm_td2_cosq_dynamic_thresh_enable_get(unit, gport, cosq, 
  13776                                    bcmCosqControlEgressUCSharedDynamicEnable, 
  13777                                    &dynamic_thresh_mode));
  13778         if (!dynamic_thresh_mode){
  13779             return BCM_E_CONFIG;
  13780         }
  13781         
  13782         BCM_IF_ERROR_RETURN
  13783             (_bcm_td2_cosq_index_resolve(unit, gport, cosq,
  13784                                      _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE,
  13785                                      &local_port, &startq, NULL));
  13786         mem = SOC_TD2_PMEM(unit, local_port, MMU_THDU_XPIPE_CONFIG_QUEUEm, 
  13787                            MMU_THDU_YPIPE_CONFIG_QUEUEm);
  13788         
  13789         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL,
  13790                                  startq, entry));
  13791         alpha = soc_mem_field32_get(unit, mem, entry, Q_SHARED_ALPHA_CELLf);  
  13792     
  13793     } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  13794         BCM_IF_ERROR_RETURN
  13795                 (_bcm_td2_cosq_dynamic_thresh_enable_get(unit, gport, cosq, 
  13796                                    bcmCosqControlEgressMCSharedDynamicEnable, 
  13797                                    &dynamic_thresh_mode));
  13798         if (!dynamic_thresh_mode){
  13799             return BCM_E_CONFIG;
  13800         }
  13801         
  13802         BCM_IF_ERROR_RETURN
  13803             (_bcm_td2_cosq_index_resolve(unit, gport, cosq,
  13804                                      _BCM_TD2_COSQ_INDEX_STYLE_MCAST_QUEUE,
  13805                                      &local_port, &startq, NULL));
  13806         mem = SOC_TD2_PMEM(unit, local_port, MMU_THDM_DB_QUEUE_CONFIG_0m, 
  13807                                            MMU_THDM_DB_QUEUE_CONFIG_1m);
  13808 
  13809         startq -= 1480; /* MC queues comes after UC queues */
  13810         BCM_IF_ERROR_RETURN
  13811             (soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  13812         alpha = soc_mem_field32_get(unit, mem, entry, Q_SHARED_ALPHAf);        
  13813            
  13814     } else {
  13815         if (cosq > 15 || cosq < 0) {
  13816             return BCM_E_PARAM;
  13817         }
  13818 
  13819         BCM_IF_ERROR_RETURN
  13820                 (_bcm_td2_cosq_dynamic_thresh_enable_get(unit, gport, cosq, 
  13821                                    bcmCosqControlIngressPortPGSharedDynamicEnable, 
  13822                                    &dynamic_thresh_mode));
  13823         if (!dynamic_thresh_mode){
  13824             return BCM_E_CONFIG;
  13825         }
  13826         
  13827         BCM_IF_ERROR_RETURN
  13828             (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port));
  13829         if (local_port < 0) {
  13830             return BCM_E_PORT;
  13831         }
  13832 
  13833         /* get PG for port using Port+Cos */
  13834         if (cosq < 8) {
  13835             reg = prigroup_reg[0];
  13836         } else {
  13837             reg = prigroup_reg[1];
  13838         }
  13839 
  13840         SOC_IF_ERROR_RETURN
  13841             (soc_reg32_get(unit, reg, local_port, 0, &rval));
  13842         port_pg = soc_reg_field_get(unit, reg, rval, prigroup_field[cosq]);
  13843         mem = SOC_TD2_PMEM(unit, local_port, THDI_PORT_PG_CONFIG_Xm,
  13844                                              THDI_PORT_PG_CONFIG_Ym);
  13845         /* get index for Port-PG */
  13846         midx = SOC_TD2_MMU_PIPED_MEM_INDEX(unit, local_port, mem, port_pg);
  13847 
  13848         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL,
  13849                                  midx, entry));
  13850         alpha = soc_mem_field32_get(unit, mem, entry, PG_SHARED_LIMITf);  
  13851         
  13852     }
  13853 
  13854     BCM_IF_ERROR_RETURN(
  13855         _bcm_td2_cosq_alpha_soc_to_bcm(unit,
  13856             (soc_td2_drop_limit_alpha_value_t)alpha, arg));
  13857 
  13858     return BCM_E_NONE;
  13859 }
  13860 
  13861 STATIC int
  13862 _bcm_td2_cosq_dynamic_thresh_enable_set(int unit, 
  13863                         bcm_gport_t gport, bcm_cos_queue_t cosq,
  13864                         bcm_cosq_control_t type, int arg)
  13865 {
  13866     bcm_port_t local_port;
  13867     int startq;
  13868     int from_cos, to_cos, ci;      
  13869     int midx; 
  13870     uint32 rval;     
  13871     uint32 entry[SOC_MAX_MEM_WORDS];
  13872     uint32 entry2[SOC_MAX_MEM_WORDS];
  13873     soc_mem_t mem = INVALIDm, mem2 = INVALIDm;
  13874     soc_reg_t reg = INVALIDr;
  13875     int port_pg;
  13876     static const soc_reg_t prigroup_reg[] = {
  13877         THDI_PORT_PRI_GRP0r, THDI_PORT_PRI_GRP1r
  13878     };
  13879     static const soc_field_t prigroup_field[] = {
  13880         PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf,
  13881         PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf,
  13882         PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf,
  13883         PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf
  13884     };    
  13885 
  13886     
  13887     if (type == bcmCosqControlIngressPortPGSharedDynamicEnable) {
  13888         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
  13889             BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  13890             return BCM_E_PARAM;
  13891         }
  13892 
  13893         BCM_IF_ERROR_RETURN
  13894             (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port));
  13895         if (local_port < 0) {
  13896             return BCM_E_PORT;
  13897         }
  13898         if ((cosq < 0) || (cosq >= _TD2_NUM_INTERNAL_PRI)) {
  13899             return BCM_E_PARAM;
  13900         }
  13901 
  13902         /* get PG for port using Port+Cos */
  13903         if (cosq < 8) {
  13904             reg = prigroup_reg[0];
  13905         } else {
  13906             reg = prigroup_reg[1];
  13907         }
  13908 
  13909         SOC_IF_ERROR_RETURN
  13910             (soc_reg32_get(unit, reg, local_port, 0, &rval));
  13911         port_pg = soc_reg_field_get(unit, reg, rval, prigroup_field[cosq]);
  13912         mem = SOC_TD2_PMEM(unit, local_port, THDI_PORT_PG_CONFIG_Xm,
  13913                                              THDI_PORT_PG_CONFIG_Ym);
  13914         /* get index for Port-PG */
  13915         midx = SOC_TD2_MMU_PIPED_MEM_INDEX(unit, local_port, mem, port_pg);
  13916         BCM_IF_ERROR_RETURN
  13917             (soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, entry));
  13918         soc_mem_field32_set(unit, mem, entry, 
  13919                             PG_SHARED_DYNAMICf, arg ? 1 : 0);
  13920         /* Set default alpha value*/
  13921         if (arg) {
  13922             soc_mem_field32_set(unit, mem, entry,
  13923                                 PG_SHARED_LIMITf, bcmCosqControlDropLimitAlpha_1_128);
  13924         }
  13925 
  13926         SOC_IF_ERROR_RETURN
  13927             (soc_mem_write(unit, mem, MEM_BLOCK_ALL, midx, entry));           
  13928     } else if (type == bcmCosqControlEgressUCSharedDynamicEnable) {
  13929         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  13930             BCM_IF_ERROR_RETURN
  13931                 (_bcm_td2_cosq_index_resolve(unit, gport, cosq,
  13932                                          _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE,
  13933                                          &local_port, &startq, NULL));
  13934         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  13935             return BCM_E_PARAM;
  13936         } else {
  13937             if (cosq == BCM_COS_INVALID) {
  13938                 from_cos = to_cos = 0;
  13939             } else {
  13940                 from_cos = to_cos = cosq;
  13941             }
  13942 
  13943             BCM_IF_ERROR_RETURN
  13944                 (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port));
  13945             if (local_port < 0) {
  13946                 return BCM_E_PORT;
  13947             }
  13948             for (ci = from_cos; ci <= to_cos; ci++) {
  13949                 BCM_IF_ERROR_RETURN
  13950                     (_bcm_td2_cosq_index_resolve(unit, local_port, ci,
  13951                           _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE,
  13952                           NULL, &startq, NULL));
  13953                 
  13954             }
  13955         }
  13956         mem = SOC_TD2_PMEM(unit, local_port, MMU_THDU_XPIPE_CONFIG_QUEUEm, 
  13957                            MMU_THDU_YPIPE_CONFIG_QUEUEm);
  13958         
  13959         BCM_IF_ERROR_RETURN
  13960             (soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  13961         soc_mem_field32_set(unit, mem, entry, 
  13962                             Q_LIMIT_DYNAMIC_CELLf, arg ? 1 : 0);
  13963         /* Set default alpha value*/
  13964         if (arg) {
  13965             soc_mem_field32_set(unit, mem, entry,
  13966                                 Q_SHARED_ALPHA_CELLf, bcmCosqControlDropLimitAlpha_1_128);
  13967         }
  13968 
  13969         SOC_IF_ERROR_RETURN
  13970             (soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry));         
  13971     } else if (type == bcmCosqControlEgressMCSharedDynamicEnable) {
  13972         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  13973             return BCM_E_PARAM;
  13974         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  13975             BCM_IF_ERROR_RETURN
  13976                 (_bcm_td2_cosq_index_resolve(unit, gport, cosq,
  13977                                          _BCM_TD2_COSQ_INDEX_STYLE_MCAST_QUEUE,
  13978                                          &local_port, &startq, NULL));
  13979         }
  13980         else {
  13981             if (cosq == BCM_COS_INVALID) {
  13982                 from_cos = to_cos = 0;
  13983             } else {
  13984                 from_cos = to_cos = cosq;
  13985             }
  13986 
  13987             BCM_IF_ERROR_RETURN
  13988                 (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port));
  13989             if (local_port < 0) {
  13990                 return BCM_E_PORT;
  13991             }
  13992             for (ci = from_cos; ci <= to_cos; ci++) {
  13993                 BCM_IF_ERROR_RETURN
  13994                     (_bcm_td2_cosq_index_resolve(unit, local_port, ci,
  13995                                          _BCM_TD2_COSQ_INDEX_STYLE_MCAST_QUEUE,
  13996                                          NULL, &startq, NULL));
  13997               
  13998             }
  13999         }
  14000         
  14001         mem = SOC_TD2_PMEM(unit, local_port, MMU_THDM_DB_QUEUE_CONFIG_0m, 
  14002                                            MMU_THDM_DB_QUEUE_CONFIG_1m);
  14003         mem2 = SOC_TD2_PMEM(unit, local_port, MMU_THDM_MCQE_QUEUE_CONFIG_0m, 
  14004                                            MMU_THDM_MCQE_QUEUE_CONFIG_1m);
  14005 
  14006         startq -= 1480; /* MC queues comes after UC queues */
  14007         BCM_IF_ERROR_RETURN
  14008             (soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  14009         soc_mem_field32_set(unit, mem, entry, Q_LIMIT_DYNAMICf, arg ? 1 : 0);
  14010         /* Set default alpha value*/
  14011         if (arg) {
  14012             soc_mem_field32_set(unit, mem, entry,
  14013                                 Q_SHARED_ALPHAf, bcmCosqControlDropLimitAlpha_1_128);
  14014         }
  14015 
  14016         SOC_IF_ERROR_RETURN
  14017             (soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry));    
  14018 
  14019         BCM_IF_ERROR_RETURN
  14020             (soc_mem_read(unit, mem2, MEM_BLOCK_ALL, startq, entry2));
  14021         soc_mem_field32_set(unit, mem2, entry2, Q_LIMIT_DYNAMICf, arg ? 1 : 0);
  14022         /* Set default alpha value*/
  14023         if (arg) {
  14024             soc_mem_field32_set(unit, mem2, entry2,
  14025                                 Q_SHARED_ALPHAf, bcmCosqControlDropLimitAlpha_1_128);
  14026         }
  14027 
  14028         SOC_IF_ERROR_RETURN
  14029             (soc_mem_write(unit, mem2, MEM_BLOCK_ALL, startq, entry2));         
  14030        
  14031     } else {
  14032         return BCM_E_PARAM;
  14033     }
  14034 
  14035     return BCM_E_NONE;
  14036 }
  14037 
  14038 STATIC int
  14039 _bcm_td2_cosq_dynamic_thresh_enable_get(int unit, 
  14040                         bcm_gport_t gport, bcm_cos_queue_t cosq, 
  14041                         bcm_cosq_control_t type, int *arg)
  14042 {
  14043     bcm_port_t local_port;
  14044     int startq;
  14045     int from_cos, to_cos, ci;   
  14046     int midx;  
  14047     uint32 rval;      
  14048     uint32 entry[SOC_MAX_MEM_WORDS];
  14049     soc_mem_t mem = INVALIDm;
  14050     soc_reg_t reg = INVALIDr;
  14051     int port_pg;
  14052     static const soc_reg_t prigroup_reg[] = {
  14053         THDI_PORT_PRI_GRP0r, THDI_PORT_PRI_GRP1r
  14054     };
  14055     static const soc_field_t prigroup_field[] = {
  14056         PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf,
  14057         PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf,
  14058         PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf,
  14059         PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf
  14060     };    
  14061 
  14062     if (!arg) {
  14063         return BCM_E_PARAM;
  14064     }
  14065 
  14066     if (type == bcmCosqControlIngressPortPGSharedDynamicEnable) {
  14067         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
  14068             BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  14069             return BCM_E_PARAM;
  14070         }
  14071 
  14072         BCM_IF_ERROR_RETURN
  14073             (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port));
  14074         if (local_port < 0) {
  14075             return BCM_E_PORT;
  14076         }
  14077         if ((cosq < 0) || (cosq >= _TD2_NUM_INTERNAL_PRI)) {
  14078             return BCM_E_PARAM;
  14079         }
  14080 
  14081         /* get PG for port using Port+Cos */
  14082         if (cosq < 8) {
  14083             reg = prigroup_reg[0];
  14084         } else {
  14085             reg = prigroup_reg[1];
  14086         }
  14087 
  14088         SOC_IF_ERROR_RETURN
  14089             (soc_reg32_get(unit, reg, local_port, 0, &rval));
  14090         port_pg = soc_reg_field_get(unit, reg, rval, prigroup_field[cosq]);
  14091         mem = SOC_TD2_PMEM(unit, local_port, THDI_PORT_PG_CONFIG_Xm,
  14092                                              THDI_PORT_PG_CONFIG_Ym);
  14093         /* get index for Port-PG */
  14094         midx = SOC_TD2_MMU_PIPED_MEM_INDEX(unit, local_port, mem, port_pg);
  14095 
  14096         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL,
  14097                                  midx, entry));
  14098         *arg = soc_mem_field32_get(unit, mem, entry, PG_SHARED_DYNAMICf);  
  14099         
  14100     } else if (type == bcmCosqControlEgressUCSharedDynamicEnable) {
  14101         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  14102             BCM_IF_ERROR_RETURN
  14103                 (_bcm_td2_cosq_index_resolve(unit, gport, cosq,
  14104                                          _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE,
  14105                                          &local_port, &startq, NULL));
  14106         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  14107             return BCM_E_PARAM;
  14108         } else {
  14109             if (cosq == BCM_COS_INVALID) {
  14110                 from_cos = to_cos = 0;
  14111             } else {
  14112                 from_cos = to_cos = cosq;
  14113             }
  14114 
  14115             BCM_IF_ERROR_RETURN
  14116                 (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port));
  14117             if (local_port < 0) {
  14118                 return BCM_E_PORT;
  14119             }
  14120             for (ci = from_cos; ci <= to_cos; ci++) {
  14121                 BCM_IF_ERROR_RETURN
  14122                     (_bcm_td2_cosq_index_resolve(unit, local_port, ci,
  14123                           _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE,
  14124                           NULL, &startq, NULL));
  14125             }
  14126         }
  14127         mem = SOC_TD2_PMEM(unit, local_port, MMU_THDU_XPIPE_CONFIG_QUEUEm, 
  14128                            MMU_THDU_YPIPE_CONFIG_QUEUEm);
  14129         
  14130         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL,
  14131                                  startq, entry));
  14132         *arg = soc_mem_field32_get(unit, mem, entry, Q_LIMIT_DYNAMIC_CELLf);        
  14133     } else if (type == bcmCosqControlEgressMCSharedDynamicEnable) {
  14134         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  14135             return BCM_E_PARAM;
  14136         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  14137             BCM_IF_ERROR_RETURN
  14138                 (_bcm_td2_cosq_index_resolve(unit, gport, cosq,
  14139                                          _BCM_TD2_COSQ_INDEX_STYLE_MCAST_QUEUE,
  14140                                          &local_port, &startq, NULL));
  14141         }
  14142         else {
  14143             if (cosq == BCM_COS_INVALID) {
  14144                 from_cos = to_cos = 0;
  14145             } else {
  14146                 from_cos = to_cos = cosq;
  14147             }
  14148 
  14149             BCM_IF_ERROR_RETURN
  14150                 (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port));
  14151             if (local_port < 0) {
  14152                 return BCM_E_PORT;
  14153             }
  14154             for (ci = from_cos; ci <= to_cos; ci++) {
  14155                 BCM_IF_ERROR_RETURN
  14156                     (_bcm_td2_cosq_index_resolve(unit, local_port, ci,
  14157                                          _BCM_TD2_COSQ_INDEX_STYLE_MCAST_QUEUE,
  14158                                          NULL, &startq, NULL));
  14159             }
  14160         }
  14161         mem = SOC_TD2_PMEM(unit, local_port, MMU_THDM_DB_QUEUE_CONFIG_0m, 
  14162                                            MMU_THDM_DB_QUEUE_CONFIG_1m);
  14163 
  14164         startq -= 1480; /* MC queues comes after UC queues */
  14165         BCM_IF_ERROR_RETURN
  14166             (soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  14167         *arg = soc_mem_field32_get(unit, mem, entry, Q_LIMIT_DYNAMICf);         
  14168     } else {
  14169         return BCM_E_PARAM;
  14170     }
  14171     
  14172     return BCM_E_NONE;
  14173 }
  14174 
  14175 STATIC int
  14176 _bcm_td2_cosq_egr_queue_limit_enable_set(int unit, bcm_gport_t gport,
  14177                                                  bcm_cos_queue_t cosq,
  14178                                                  bcm_cosq_control_t type,
  14179                                                  int arg)
  14180 {
  14181     bcm_port_t local_port;
  14182     int startq;
  14183     uint32 entry[SOC_MAX_MEM_WORDS];
  14184     soc_mem_t mem = INVALIDm;
  14185     int enable;
  14186     soc_field_t field_name = INVALIDf;
  14187 
  14188     if (arg < 0) {
  14189         return BCM_E_PARAM;
  14190     }
  14191 
  14192     arg = arg ? 1 : 0;
  14193 
  14194     if ((type == bcmCosqControlEgressUCQueueLimitEnable) ||
  14195         (type == bcmCosqControlEgressUCQueueColorLimitEnable)) {
  14196         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  14197             BCM_IF_ERROR_RETURN
  14198                 (_bcm_td2_cosq_index_resolve(unit, gport, cosq,
  14199                                              _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE,
  14200                                              &local_port, &startq, NULL));
  14201         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  14202             return BCM_E_PARAM;
  14203         } else {
  14204             if (cosq < 0) {
  14205                 return BCM_E_PARAM;
  14206             }
  14207             BCM_IF_ERROR_RETURN
  14208                 (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port));
  14209             if (local_port < 0) {
  14210                 return BCM_E_PORT;
  14211             }
  14212             BCM_IF_ERROR_RETURN
  14213                 (_bcm_td2_cosq_index_resolve
  14214                  (unit, local_port, cosq, _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE,
  14215                   NULL, &startq, NULL));
  14216         }
  14217 
  14218         mem = SOC_TD2_PMEM(unit, local_port, MMU_THDU_XPIPE_Q_TO_QGRP_MAPm,
  14219                         MMU_THDU_YPIPE_Q_TO_QGRP_MAPm);
  14220         if (type == bcmCosqControlEgressUCQueueLimitEnable) {
  14221             field_name = Q_LIMIT_ENABLEf;
  14222         } else if (type == bcmCosqControlEgressUCQueueColorLimitEnable) {
  14223             field_name = Q_COLOR_ENABLE_CELLf;
  14224         }
  14225         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  14226         enable = soc_mem_field32_get(unit, mem, entry, field_name);
  14227         if (enable != arg) {
  14228             soc_mem_field32_set(unit, mem, entry, field_name, arg);
  14229             BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry));
  14230         }
  14231     }else if ((type == bcmCosqControlEgressMCQueueLimitEnable) ||
  14232         (type == bcmCosqControlEgressMCQueueColorLimitEnable)) {
  14233         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  14234             return BCM_E_PARAM;
  14235         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  14236             BCM_IF_ERROR_RETURN
  14237                 (_bcm_td2_cosq_index_resolve(unit, gport, cosq,
  14238                                              _BCM_TD2_COSQ_INDEX_STYLE_MCAST_QUEUE,
  14239                                              &local_port, &startq, NULL));
  14240         } else {
  14241             if (cosq < 0) {
  14242                 return BCM_E_PARAM;
  14243             }
  14244             BCM_IF_ERROR_RETURN
  14245                 (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port));
  14246             if (local_port < 0) {
  14247                 return BCM_E_PORT;
  14248             }
  14249             BCM_IF_ERROR_RETURN
  14250                 (_bcm_td2_cosq_index_resolve(unit, local_port, cosq,
  14251                                             _BCM_TD2_COSQ_INDEX_STYLE_MCAST_QUEUE,
  14252                                             NULL, &startq, NULL));
  14253         }
  14254         startq -= 1480; /* MC queues comes after UC queues */
  14255 
  14256         mem = SOC_TD2_PMEM(unit, local_port, MMU_THDM_MCQE_QUEUE_CONFIG_0m,
  14257                            MMU_THDM_MCQE_QUEUE_CONFIG_1m);
  14258         if (type == bcmCosqControlEgressMCQueueLimitEnable) {
  14259             field_name = Q_LIMIT_ENABLEf;
  14260         } else if (type == bcmCosqControlEgressMCQueueColorLimitEnable) {
  14261             field_name = Q_COLOR_LIMIT_ENABLEf;
  14262         }
  14263         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  14264         enable = soc_mem_field32_get(unit, mem, entry, field_name);
  14265         if (enable != arg) {
  14266             soc_mem_field32_set(unit, mem, entry, field_name, arg);
  14267             BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry));
  14268         }
  14269 
  14270         mem = SOC_TD2_PMEM(unit, local_port, MMU_THDM_DB_QUEUE_CONFIG_0m,
  14271                            MMU_THDM_DB_QUEUE_CONFIG_1m);
  14272         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  14273         enable = soc_mem_field32_get(unit, mem, entry, field_name);
  14274         if (enable != arg) {
  14275             soc_mem_field32_set(unit, mem, entry, field_name, arg);
  14276             BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry));
  14277         }
  14278     } else {
  14279         return BCM_E_PARAM;
  14280     }
  14281 
  14282     return BCM_E_NONE;
  14283 }
  14284 
  14285 STATIC int
  14286 _bcm_td2_cosq_egr_queue_limit_enable_get(int unit, bcm_gport_t gport,
  14287                                                 bcm_cos_queue_t cosq,
  14288                                                 bcm_cosq_control_t type,
  14289                                                 int *arg)
  14290 {
  14291     bcm_port_t local_port;
  14292     int startq;
  14293     uint32 entry[SOC_MAX_MEM_WORDS];
  14294     soc_mem_t mem = INVALIDm;
  14295     soc_field_t field_name = INVALIDf;
  14296 
  14297     if ((type == bcmCosqControlEgressUCQueueLimitEnable) ||
  14298         (type == bcmCosqControlEgressUCQueueColorLimitEnable)) {
  14299         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  14300             BCM_IF_ERROR_RETURN
  14301                 (_bcm_td2_cosq_index_resolve(unit, gport, cosq,
  14302                                           _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE,
  14303                                           &local_port, &startq, NULL));
  14304         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  14305             return BCM_E_PARAM;
  14306         } else {
  14307             if (cosq < 0) {
  14308                 return BCM_E_PARAM;
  14309             }
  14310             BCM_IF_ERROR_RETURN
  14311                 (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port));
  14312             if (local_port < 0) {
  14313                 return BCM_E_PORT;
  14314             }
  14315             BCM_IF_ERROR_RETURN
  14316                 (_bcm_td2_cosq_index_resolve
  14317                     (unit, local_port, cosq, _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE,
  14318                     NULL, &startq, NULL));
  14319         }
  14320 
  14321         mem = SOC_TD2_PMEM(unit, local_port, MMU_THDU_XPIPE_Q_TO_QGRP_MAPm, 
  14322                  MMU_THDU_YPIPE_Q_TO_QGRP_MAPm);
  14323         if (type == bcmCosqControlEgressUCQueueLimitEnable) {
  14324             field_name = Q_LIMIT_ENABLEf;
  14325         } else if (type == bcmCosqControlEgressUCQueueColorLimitEnable) {
  14326             field_name = Q_COLOR_ENABLE_CELLf;
  14327         }
  14328         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  14329         *arg = soc_mem_field32_get(unit, mem, entry, field_name);
  14330     }else if ((type == bcmCosqControlEgressMCQueueLimitEnable) ||
  14331                (type == bcmCosqControlEgressMCQueueColorLimitEnable)) {
  14332         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  14333             return BCM_E_PARAM;
  14334         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  14335             BCM_IF_ERROR_RETURN
  14336                 (_bcm_td2_cosq_index_resolve(unit, gport, cosq,
  14337                 _BCM_TD2_COSQ_INDEX_STYLE_MCAST_QUEUE,
  14338                 &local_port, &startq, NULL));
  14339         } else {
  14340             if (cosq < 0) {
  14341                 return BCM_E_PARAM;
  14342             }
  14343             BCM_IF_ERROR_RETURN
  14344                 (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port));
  14345             if (local_port < 0) {
  14346                 return BCM_E_PORT;
  14347             }
  14348             BCM_IF_ERROR_RETURN
  14349                 (_bcm_td2_cosq_index_resolve
  14350                 (unit, local_port, cosq, _BCM_TD2_COSQ_INDEX_STYLE_MCAST_QUEUE,
  14351                 NULL, &startq, NULL));
  14352         }
  14353         mem = SOC_TD2_PMEM(unit, local_port, MMU_THDM_MCQE_QUEUE_CONFIG_0m, 
  14354                         MMU_THDM_MCQE_QUEUE_CONFIG_1m);
  14355         if (type == bcmCosqControlEgressMCQueueLimitEnable) {
  14356            field_name = Q_LIMIT_ENABLEf;
  14357         } else if (type == bcmCosqControlEgressMCQueueColorLimitEnable) {
  14358            field_name = Q_COLOR_LIMIT_ENABLEf;
  14359         }
  14360         startq -= 1480; /* MC queues comes after UC queues */
  14361         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  14362         *arg = soc_mem_field32_get(unit, mem, entry, field_name);
  14363     } else {
  14364         return BCM_E_PARAM;
  14365     }
  14366 
  14367     return BCM_E_NONE;
  14368 }
  14369 
  14370 STATIC int
  14371 _bcm_td2_cosq_qgroup_limit_enable_set(int unit, bcm_gport_t gport,
  14372                                                  bcm_cos_queue_t cosq,
  14373                                                  bcm_cosq_control_t type,
  14374                                                  int arg)
  14375 {
  14376     bcm_port_t local_port;
  14377     int startq;
  14378     uint32 entry[SOC_MAX_MEM_WORDS], valid;
  14379     soc_mem_t mem = INVALIDm;
  14380     soc_field_t field = INVALIDf;
  14381 
  14382     if (arg < 0) {
  14383         return BCM_E_PARAM;
  14384     }
  14385 
  14386     arg = arg ? 1 : 0;
  14387 
  14388     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  14389         BCM_IF_ERROR_RETURN
  14390             (_bcm_td2_cosq_index_resolve(unit, gport, cosq,
  14391                                          _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE,
  14392                                          &local_port, &startq, NULL));
  14393     } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  14394         return BCM_E_PARAM;
  14395     } else {
  14396         if (cosq < -1) {
  14397             return BCM_E_PARAM;
  14398         }
  14399         BCM_IF_ERROR_RETURN
  14400             (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port));
  14401         if (local_port < 0) {
  14402             return BCM_E_PORT;
  14403         }
  14404         BCM_IF_ERROR_RETURN
  14405             (_bcm_td2_cosq_index_resolve(unit, local_port, cosq,
  14406                                          _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE,
  14407                                          NULL, &startq, NULL));
  14408     }
  14409 
  14410     mem = SOC_TD2_PMEM(unit, local_port, MMU_THDU_XPIPE_Q_TO_QGRP_MAPm,
  14411                        MMU_THDU_YPIPE_Q_TO_QGRP_MAPm);
  14412     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  14413     valid = soc_mem_field32_get(unit, mem, entry, QGROUP_VALIDf);
  14414     if (!valid) {
  14415         LOG_INFO(BSL_LS_BCM_COSQ,
  14416                  (BSL_META_U(unit,
  14417                  "UCQ doesn't associate with a queue group!\n")));
  14418         return BCM_E_UNAVAIL;
  14419     }
  14420 
  14421     if (type == bcmCosqControlEgressUCQueueGroupMinEnable) {
  14422         field = USE_QGROUP_MINf;
  14423     } else if (type == bcmCosqControlEgressUCQueueGroupSharedLimitEnable) {
  14424         field = QGROUP_LIMIT_ENABLEf;
  14425     } else if (type == bcmCosqControlEgressUCQueueGroupSharedDynamicEnable) {
  14426         startq = soc_mem_field32_get(unit, mem, entry, QGROUPf);
  14427 
  14428         mem = SOC_TD2_PMEM(unit, local_port, MMU_THDU_XPIPE_CONFIG_QGROUPm,
  14429                            MMU_THDU_YPIPE_CONFIG_QGROUPm);
  14430         field = Q_LIMIT_DYNAMIC_CELLf;
  14431     } else {
  14432         return BCM_E_PARAM;
  14433     }
  14434 
  14435     if ((mem != INVALIDm) && (field != INVALIDf)) {
  14436         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  14437         soc_mem_field32_set(unit, mem, entry, field, arg);
  14438         BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry));
  14439     }
  14440 
  14441     return BCM_E_NONE;
  14442 }
  14443 
  14444 STATIC int
  14445 _bcm_td2_cosq_qgroup_limit_enable_get(int unit, bcm_gport_t gport,
  14446                                                 bcm_cos_queue_t cosq,
  14447                                                 bcm_cosq_control_t type,
  14448                                                 int *arg)
  14449 {
  14450     bcm_port_t local_port;
  14451     int startq;
  14452     uint32 entry[SOC_MAX_MEM_WORDS], valid;
  14453     soc_mem_t mem = INVALIDm;
  14454     soc_field_t field = INVALIDf;
  14455 
  14456     if (!arg) {
  14457         return BCM_E_PARAM;
  14458     }
  14459 
  14460     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  14461         BCM_IF_ERROR_RETURN
  14462             (_bcm_td2_cosq_index_resolve(unit, gport, cosq,
  14463                                          _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE,
  14464                                          &local_port, &startq, NULL));
  14465     } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  14466         return BCM_E_PARAM;
  14467     } else {
  14468         if (cosq < -1) {
  14469             return BCM_E_PARAM;
  14470         }
  14471         BCM_IF_ERROR_RETURN
  14472             (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port));
  14473         if (local_port < 0) {
  14474             return BCM_E_PORT;
  14475         }
  14476         BCM_IF_ERROR_RETURN
  14477             (_bcm_td2_cosq_index_resolve(unit, local_port, cosq,
  14478                                          _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE,
  14479                                          NULL, &startq, NULL));
  14480     }
  14481 
  14482     mem = SOC_TD2_PMEM(unit, local_port, MMU_THDU_XPIPE_Q_TO_QGRP_MAPm,
  14483                        MMU_THDU_YPIPE_Q_TO_QGRP_MAPm);
  14484     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  14485     valid = soc_mem_field32_get(unit, mem, entry, QGROUP_VALIDf);
  14486     if (!valid) {
  14487         LOG_INFO(BSL_LS_BCM_COSQ,
  14488                  (BSL_META_U(unit,
  14489                  "UCQ doesn't associate with a queue group!\n")));
  14490         return BCM_E_UNAVAIL;
  14491     }
  14492 
  14493     if (type == bcmCosqControlEgressUCQueueGroupMinEnable) {
  14494         field = USE_QGROUP_MINf;
  14495     } else if (type == bcmCosqControlEgressUCQueueGroupSharedLimitEnable) {
  14496         field = QGROUP_LIMIT_ENABLEf;
  14497     } else if (type == bcmCosqControlEgressUCQueueGroupSharedDynamicEnable) {
  14498         startq = soc_mem_field32_get(unit, mem, entry, QGROUPf);
  14499 
  14500         mem = SOC_TD2_PMEM(unit, local_port, MMU_THDU_XPIPE_CONFIG_QGROUPm,
  14501                            MMU_THDU_YPIPE_CONFIG_QGROUPm);
  14502         field = Q_LIMIT_DYNAMIC_CELLf;
  14503     } else {
  14504         return BCM_E_PARAM;
  14505     }
  14506 
  14507     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  14508     *arg = soc_mem_field32_get(unit, mem, entry, field);
  14509 
  14510     return BCM_E_NONE;
  14511 }
  14512 
  14513 STATIC int
  14514 _bcm_td2_cosq_qgroup_limit_set(int unit, bcm_gport_t gport,
  14515                                bcm_cos_queue_t cosq,
  14516                                bcm_cosq_control_t type,
  14517                                int arg)
  14518 {
  14519     bcm_port_t local_port;
  14520     int startq, granularity = 1;
  14521     int cur_val, rv, post_update;
  14522     int delta = 0; /* In Cells */
  14523     uint32 entry[SOC_MAX_MEM_WORDS], valid;
  14524     uint32 shared_size, spid, max_val, rval = 0;
  14525     soc_mem_t mem = INVALIDm;
  14526     soc_field_t fld_limit = INVALIDf;
  14527 
  14528     if (arg < 0) {
  14529         return BCM_E_PARAM;
  14530     }
  14531 
  14532     arg /= _BCM_TD2_BYTES_PER_CELL;
  14533 
  14534     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  14535         BCM_IF_ERROR_RETURN
  14536             (_bcm_td2_cosq_index_resolve(unit, gport, cosq,
  14537                                          _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE,
  14538                                          &local_port, &startq, NULL));
  14539     } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  14540         return BCM_E_PARAM;
  14541     } else {
  14542         if (cosq < -1) {
  14543             return BCM_E_PARAM;
  14544         }
  14545         BCM_IF_ERROR_RETURN
  14546             (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port));
  14547         if (local_port < 0) {
  14548             return BCM_E_PORT;
  14549         }
  14550         BCM_IF_ERROR_RETURN
  14551             (_bcm_td2_cosq_index_resolve(unit, local_port, cosq,
  14552                                          _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE,
  14553                                          NULL, &startq, NULL));
  14554     }
  14555 
  14556     mem = SOC_TD2_PMEM(unit, local_port, MMU_THDU_XPIPE_Q_TO_QGRP_MAPm,
  14557                        MMU_THDU_YPIPE_Q_TO_QGRP_MAPm);
  14558     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  14559     spid = soc_mem_field32_get(unit, mem, entry, Q_SPIDf);
  14560     valid = soc_mem_field32_get(unit, mem, entry, QGROUP_VALIDf);
  14561     if (!valid) {
  14562         LOG_INFO(BSL_LS_BCM_COSQ,
  14563                  (BSL_META_U(unit,
  14564                  "UCQ doesn't associate with a queue group!\n")));
  14565         return BCM_E_UNAVAIL;
  14566     }
  14567 
  14568     startq = soc_mem_field32_get(unit, mem, entry, QGROUPf);
  14569 
  14570     mem = SOC_TD2_PMEM(unit, local_port, MMU_THDU_XPIPE_CONFIG_QGROUPm,
  14571                        MMU_THDU_YPIPE_CONFIG_QGROUPm);
  14572     if (type == bcmCosqControlEgressUCQueueGroupMinLimitBytes) {
  14573         fld_limit = Q_MIN_LIMIT_CELLf;
  14574         granularity = 1;
  14575     } else if (type == bcmCosqControlEgressUCQueueGroupSharedLimitBytes) {
  14576         fld_limit = Q_SHARED_LIMIT_CELLf;
  14577         granularity = 1;
  14578     } else {
  14579         return BCM_E_PARAM;
  14580     }
  14581 
  14582     /* Recalculate Shared Values if Min Changed */
  14583     SOC_IF_ERROR_RETURN(READ_MMU_THDM_DB_POOL_SHARED_LIMITr(unit, spid, &rval));
  14584     shared_size = soc_reg_field_get(unit, MMU_THDM_DB_POOL_SHARED_LIMITr,
  14585                                     rval, SHARED_LIMITf);
  14586     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  14587     cur_val = soc_mem_field32_get(unit, mem, entry, fld_limit);
  14588 
  14589     if ((arg / granularity) > cur_val) {
  14590         /* New Min Val > Cur Min Val
  14591          * So reduce the Shared values first and then
  14592          * Increase the Min Value for given resource
  14593          */
  14594         post_update = 0;
  14595     } else if ((arg / granularity) < cur_val) {
  14596         /* New Min Val < Cur Min Val
  14597          * So reduce the Min values first and then
  14598          * Increase Shared values everywhere
  14599          */
  14600         post_update = 1;
  14601     } else {
  14602         return BCM_E_NONE;
  14603     }
  14604 
  14605     if (!post_update &&
  14606         (type == bcmCosqControlEgressUCQueueGroupMinLimitBytes)) {
  14607         delta = ((arg / granularity) - cur_val) * granularity;
  14608         if (delta > shared_size) {
  14609             return BCM_E_RESOURCE;
  14610         }
  14611         rv = soc_td2_mmu_config_res_limits_update(unit, spid,
  14612                                                   shared_size - delta, 1);
  14613         if (rv < 0) {
  14614             return rv;
  14615         }
  14616     }
  14617 
  14618     /* Check for min/max values */
  14619     max_val = (1 << soc_mem_field_length(unit, mem, fld_limit)) - 1;
  14620     if ((arg < 0) || ((arg/granularity) > max_val)) {
  14621         return BCM_E_PARAM;
  14622     } else {
  14623         /* Get the latest entry data and update. */
  14624         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  14625         soc_mem_field32_set(unit, mem, entry, fld_limit, (arg/granularity));
  14626         BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry));
  14627     }
  14628 
  14629     if (post_update &&
  14630         (type == bcmCosqControlEgressUCQueueGroupMinLimitBytes)) {
  14631         delta = (cur_val - (arg / granularity)) * granularity;
  14632         rv = soc_td2_mmu_config_res_limits_update(unit, spid,
  14633                                                   shared_size + delta, 0);
  14634         if (rv < 0) {
  14635             return rv;
  14636         }
  14637     }
  14638 
  14639     return BCM_E_NONE;
  14640 }
  14641 
  14642 STATIC int
  14643 _bcm_td2_cosq_qgroup_limit_get(int unit, bcm_gport_t gport,
  14644                                bcm_cos_queue_t cosq,
  14645                                bcm_cosq_control_t type,
  14646                                int *arg)
  14647 {
  14648     bcm_port_t local_port;
  14649     int startq, granularity = 1;
  14650     uint32 entry[SOC_MAX_MEM_WORDS], valid;
  14651     soc_mem_t mem = INVALIDm;
  14652     soc_field_t fld_limit = INVALIDf;
  14653 
  14654     if (!arg) {
  14655         return BCM_E_PARAM;
  14656     }
  14657 
  14658     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  14659         BCM_IF_ERROR_RETURN
  14660             (_bcm_td2_cosq_index_resolve(unit, gport, cosq,
  14661                                          _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE,
  14662                                          &local_port, &startq, NULL));
  14663     } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  14664         return BCM_E_PARAM;
  14665     } else {
  14666         if (cosq < -1) {
  14667             return BCM_E_PARAM;
  14668         }
  14669         BCM_IF_ERROR_RETURN
  14670             (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port));
  14671         if (local_port < 0) {
  14672             return BCM_E_PORT;
  14673         }
  14674         BCM_IF_ERROR_RETURN
  14675             (_bcm_td2_cosq_index_resolve(unit, local_port, cosq,
  14676                                          _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE,
  14677                                          NULL, &startq, NULL));
  14678     }
  14679 
  14680     mem = SOC_TD2_PMEM(unit, local_port, MMU_THDU_XPIPE_Q_TO_QGRP_MAPm,
  14681                        MMU_THDU_YPIPE_Q_TO_QGRP_MAPm);
  14682     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  14683     valid = soc_mem_field32_get(unit, mem, entry, QGROUP_VALIDf);
  14684     if (!valid) {
  14685         LOG_INFO(BSL_LS_BCM_COSQ,
  14686                  (BSL_META_U(unit,
  14687                  "UCQ doesn't associate with a queue group!\n")));
  14688         return BCM_E_UNAVAIL;
  14689     }
  14690 
  14691     startq = soc_mem_field32_get(unit, mem, entry, QGROUPf);
  14692 
  14693     mem = SOC_TD2_PMEM(unit, local_port, MMU_THDU_XPIPE_CONFIG_QGROUPm,
  14694                        MMU_THDU_YPIPE_CONFIG_QGROUPm);
  14695     if (type == bcmCosqControlEgressUCQueueGroupMinLimitBytes) {
  14696         fld_limit = Q_MIN_LIMIT_CELLf;
  14697         granularity = 1;
  14698     } else if (type == bcmCosqControlEgressUCQueueGroupSharedLimitBytes) {
  14699         fld_limit = Q_SHARED_LIMIT_CELLf;
  14700         granularity = 1;
  14701     } else {
  14702         return BCM_E_PARAM;
  14703     }
  14704 
  14705     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  14706     *arg = soc_mem_field32_get(unit, mem, entry, fld_limit);
  14707     *arg = (*arg) * granularity * _BCM_TD2_BYTES_PER_CELL;
  14708 
  14709     return BCM_E_NONE;
  14710 }
  14711 
  14712 STATIC int
  14713 _bcm_td2_cosq_qgroup_alpha_set(int unit,
  14714                         bcm_gport_t gport, bcm_cos_queue_t cosq,
  14715                         bcm_cosq_control_drop_limit_alpha_value_t arg)
  14716 {
  14717     bcm_port_t local_port;
  14718     int startq;
  14719     uint32 entry[SOC_MAX_MEM_WORDS], valid, alpha;
  14720     uint32 dyn_mode;
  14721     soc_mem_t mem = INVALIDm;
  14722     soc_td2_drop_limit_alpha_value_t aget;
  14723 
  14724     BCM_IF_ERROR_RETURN(
  14725         _bcm_td2_cosq_alpha_bcm_to_soc(unit, arg, &aget));
  14726     alpha = (uint32)aget;
  14727 
  14728     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  14729         BCM_IF_ERROR_RETURN
  14730             (_bcm_td2_cosq_index_resolve(unit, gport, cosq,
  14731                                          _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE,
  14732                                          &local_port, &startq, NULL));
  14733     } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  14734         return BCM_E_PARAM;
  14735     } else {
  14736         if (cosq < -1) {
  14737             return BCM_E_PARAM;
  14738         }
  14739         BCM_IF_ERROR_RETURN
  14740             (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port));
  14741         if (local_port < 0) {
  14742             return BCM_E_PORT;
  14743         }
  14744         BCM_IF_ERROR_RETURN
  14745             (_bcm_td2_cosq_index_resolve(unit, local_port, cosq,
  14746                                          _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE,
  14747                                          NULL, &startq, NULL));
  14748     }
  14749 
  14750     mem = SOC_TD2_PMEM(unit, local_port, MMU_THDU_XPIPE_Q_TO_QGRP_MAPm,
  14751                        MMU_THDU_YPIPE_Q_TO_QGRP_MAPm);
  14752     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  14753     valid = soc_mem_field32_get(unit, mem, entry, QGROUP_VALIDf);
  14754     if (!valid) {
  14755         LOG_INFO(BSL_LS_BCM_COSQ,
  14756                  (BSL_META_U(unit,
  14757                  "UCQ doesn't associate with a queue group!\n")));
  14758         return BCM_E_UNAVAIL;
  14759     }
  14760 
  14761     startq = soc_mem_field32_get(unit, mem, entry, QGROUPf);
  14762     mem = SOC_TD2_PMEM(unit, local_port, MMU_THDU_XPIPE_CONFIG_QGROUPm,
  14763                        MMU_THDU_YPIPE_CONFIG_QGROUPm);
  14764 
  14765     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  14766     dyn_mode = soc_mem_field32_get(unit, mem, entry, Q_LIMIT_DYNAMIC_CELLf);
  14767     if (!dyn_mode){
  14768         return BCM_E_CONFIG;
  14769     }
  14770     soc_mem_field32_set(unit, mem, entry, Q_SHARED_ALPHA_CELLf, alpha);
  14771     BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry));
  14772 
  14773     return BCM_E_NONE;
  14774 }
  14775 
  14776 STATIC int
  14777 _bcm_td2_cosq_qgroup_alpha_get(int unit,
  14778                         bcm_gport_t gport, bcm_cos_queue_t cosq,
  14779                         bcm_cosq_control_drop_limit_alpha_value_t *arg)
  14780 {
  14781     bcm_port_t local_port;
  14782     int startq;
  14783     uint32 entry[SOC_MAX_MEM_WORDS], valid, alpha;
  14784     uint32 dyn_mode;
  14785     soc_mem_t mem = INVALIDm;
  14786 
  14787     if (!arg) {
  14788         return BCM_E_PARAM;
  14789     }
  14790 
  14791     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  14792         BCM_IF_ERROR_RETURN
  14793             (_bcm_td2_cosq_index_resolve(unit, gport, cosq,
  14794                                          _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE,
  14795                                          &local_port, &startq, NULL));
  14796     } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  14797         return BCM_E_PARAM;
  14798     } else {
  14799         if (cosq < -1) {
  14800             return BCM_E_PARAM;
  14801         }
  14802         BCM_IF_ERROR_RETURN
  14803             (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port));
  14804         if (local_port < 0) {
  14805             return BCM_E_PORT;
  14806         }
  14807         BCM_IF_ERROR_RETURN
  14808             (_bcm_td2_cosq_index_resolve(unit, local_port, cosq,
  14809                                          _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE,
  14810                                          NULL, &startq, NULL));
  14811     }
  14812 
  14813     mem = SOC_TD2_PMEM(unit, local_port, MMU_THDU_XPIPE_Q_TO_QGRP_MAPm,
  14814                        MMU_THDU_YPIPE_Q_TO_QGRP_MAPm);
  14815     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  14816     valid = soc_mem_field32_get(unit, mem, entry, QGROUP_VALIDf);
  14817     if (!valid) {
  14818         LOG_INFO(BSL_LS_BCM_COSQ,
  14819                  (BSL_META_U(unit,
  14820                  "UCQ doesn't associate with a queue group!\n")));
  14821         return BCM_E_UNAVAIL;
  14822     }
  14823 
  14824     startq = soc_mem_field32_get(unit, mem, entry, QGROUPf);
  14825     mem = SOC_TD2_PMEM(unit, local_port, MMU_THDU_XPIPE_CONFIG_QGROUPm,
  14826                        MMU_THDU_YPIPE_CONFIG_QGROUPm);
  14827 
  14828     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  14829     dyn_mode = soc_mem_field32_get(unit, mem, entry, Q_LIMIT_DYNAMIC_CELLf);
  14830     if (!dyn_mode){
  14831         return BCM_E_CONFIG;
  14832     }
  14833     alpha = soc_mem_field32_get(unit, mem, entry, Q_SHARED_ALPHA_CELLf);
  14834 
  14835     BCM_IF_ERROR_RETURN(
  14836         _bcm_td2_cosq_alpha_soc_to_bcm(unit,
  14837             (soc_td2_drop_limit_alpha_value_t)alpha, arg));
  14838 
  14839     return BCM_E_NONE;
  14840 }
  14841 
  14842 int
  14843 bcm_td2_cosq_priority_mapping_get_all(int unit, bcm_gport_t gport, int index,
  14844                                       bcm_cosq_priority_mapping_t type,
  14845                                       int pri_max, int *pri_array,
  14846                                       int *pri_count)
  14847 {
  14848     bcm_port_t port;
  14849     int i, pg, sp, count = 0;
  14850 
  14851     BCM_IF_ERROR_RETURN(_bcm_td2_cosq_localport_resolve(unit, gport, &port));
  14852     if (!SOC_PORT_VALID(unit, port)) {
  14853         return BCM_E_PORT;
  14854     }
  14855 
  14856     switch (type) {
  14857         case bcmCosqPriorityGroup:
  14858             if ((index < TD2_PRIOROTY_GROUP_ID_MIN) ||
  14859                 (index > TD2_PRIOROTY_GROUP_ID_MAX)) {
  14860                 return BCM_E_PARAM;
  14861             }
  14862             for (i = 0; i < _TD2_NUM_INTERNAL_PRI; i++) {
  14863                 BCM_IF_ERROR_RETURN
  14864                     (bcm_td2_port_priority_group_mapping_get(unit, gport,
  14865                                                         i, &pg));
  14866                 if (pg == index) {
  14867                     if (pri_max != 0 && pri_array != NULL) {
  14868                         if (count < pri_max) {
  14869                             pri_array[count] = i;
  14870                         }
  14871                     }
  14872                     count++;
  14873                 }
  14874             }
  14875             break;
  14876         case bcmCosqIngressPool:
  14877             if ((index < 0) || (index >= _TD2_NUM_SERVICE_POOL)) {
  14878                 return BCM_E_PARAM;
  14879             }
  14880             for (i = 0; i < _TD2_NUM_INTERNAL_PRI; i++) {
  14881                 BCM_IF_ERROR_RETURN
  14882                     (bcm_td2_port_priority_group_mapping_get(unit, gport,
  14883                                                         i, &pg));
  14884                 BCM_IF_ERROR_RETURN
  14885                     (_bcm_td2_cosq_ing_pool_get(unit, gport, pg,
  14886                                                bcmCosqControlIngressPool,
  14887                                                &sp));
  14888                 if (sp == index) {
  14889                     if (pri_max != 0 && pri_array != NULL) {
  14890                         if (count < pri_max) {
  14891                             pri_array[count] = i;
  14892                         }
  14893                     }
  14894                     count++;
  14895                 }
  14896             }
  14897             break;
  14898         default:
  14899             return BCM_E_UNAVAIL;
  14900     }
  14901 
  14902     if ((count < pri_max) && (pri_array != NULL)) {
  14903         for (i = count; i < pri_max; i++) {
  14904             pri_array[i] = -1;
  14905         }
  14906         *pri_count = count;
  14907     } else if (pri_max == 0) {
  14908         *pri_count = count;
  14909     } else {
  14910         *pri_count = pri_max;
  14911     }
  14912     return BCM_E_NONE;
  14913 }
  14914 
  14915 /*
  14916  * Function: _bcm_td2_cosq_egr_queue_color_limit_set
  14917  * Purpose: Set Red and Yellow color limit per queue
  14918  *          IF color mode dynamic: limit should be between 0-7
  14919  *                                 0: 100% of green threshold
  14920  *                                 1: 12.5% of green threshold
  14921  *                                 2: 25% of green threshold
  14922  *                                 3: 37.5% of green threshold
  14923  *                                 4: 50% of green threshold
  14924  *                                 5: 67.5% of green threshold
  14925  *                                 6: 75% of green threshold
  14926  *                                 7: 87.5% of green threshold
  14927  *          If color mode static: Limit is number of bytes
  14928 */
  14929 
  14930 STATIC int
  14931 _bcm_td2_cosq_egr_queue_color_limit_set(int unit, bcm_gport_t gport,
  14932                                         bcm_cos_queue_t cosq,
  14933                                         bcm_cosq_control_t type,
  14934                                         int arg)
  14935 {
  14936     bcm_port_t local_port;
  14937     int startq;
  14938     uint32 entry[SOC_MAX_MEM_WORDS];
  14939     soc_mem_t mem = INVALIDm;
  14940     soc_field_t fld_limit = INVALIDf;
  14941     int color_mode, granularity, max_val;
  14942 
  14943     if (arg < 0) {
  14944         return BCM_E_PARAM;
  14945     }
  14946     granularity = 8;
  14947 
  14948     if ((type == bcmCosqControlEgressUCQueueRedLimit) ||
  14949         (type == bcmCosqControlEgressUCQueueYellowLimit)) {
  14950         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  14951             BCM_IF_ERROR_RETURN
  14952                 (_bcm_td2_cosq_index_resolve(unit, gport, cosq,
  14953                                             _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE,
  14954                                             &local_port, &startq, NULL));
  14955         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  14956             return BCM_E_PARAM;
  14957         } else {
  14958             if (cosq < 0) {
  14959                 return BCM_E_PARAM;
  14960             }
  14961             BCM_IF_ERROR_RETURN
  14962                 (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port));
  14963             if (local_port < 0) {
  14964                 return BCM_E_PORT;
  14965             }
  14966             BCM_IF_ERROR_RETURN
  14967                 (_bcm_td2_cosq_index_resolve
  14968                  (unit, local_port, cosq, _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE,
  14969                   NULL, &startq, NULL));
  14970         }
  14971         if (type == bcmCosqControlEgressUCQueueRedLimit) {
  14972             fld_limit = LIMIT_RED_CELLf;
  14973         } else {
  14974             fld_limit = LIMIT_YELLOW_CELLf;
  14975         }
  14976         mem = SOC_TD2_PMEM(unit, local_port, MMU_THDU_XPIPE_CONFIG_QUEUEm,
  14977                            MMU_THDU_YPIPE_CONFIG_QUEUEm);
  14978         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  14979         color_mode = soc_mem_field32_get(unit, mem, entry, Q_COLOR_LIMIT_DYNAMIC_CELLf);
  14980 
  14981         if (color_mode == 1) { /* Dynamic color limit */
  14982             if (arg > 7) { /* Legal values are 0 - 7 */
  14983                 return BCM_E_PARAM;
  14984             } else {
  14985                 soc_mem_field32_set(unit, mem, entry, fld_limit, arg);
  14986             }
  14987         } else { /* Static color limit */
  14988             arg = (arg + _TD2_MMU_BYTES_PER_CELL - 1) / _TD2_MMU_BYTES_PER_CELL;
  14989 
  14990             /* Check for min/max values */
  14991             max_val = (1 << soc_mem_field_length(unit, mem, fld_limit)) - 1;
  14992             if ((arg/granularity) > max_val) {
  14993                 return BCM_E_PARAM;
  14994             } else {
  14995                 soc_mem_field32_set(unit, mem, entry, fld_limit, (arg/granularity));
  14996             }
  14997         }
  14998         BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry));
  14999     } else if ((type == bcmCosqControlEgressMCQueueRedLimit) ||
  15000                (type == bcmCosqControlEgressMCQueueYellowLimit)) {
  15001         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  15002             return BCM_E_PARAM;
  15003         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  15004             BCM_IF_ERROR_RETURN
  15005                 (_bcm_td2_cosq_index_resolve(unit, gport, cosq,
  15006                                             _BCM_TD2_COSQ_INDEX_STYLE_MCAST_QUEUE,
  15007                                             &local_port, &startq, NULL));
  15008         } else {
  15009             if (cosq < 0) {
  15010                 return BCM_E_PARAM;
  15011             }
  15012             BCM_IF_ERROR_RETURN
  15013                 (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port));
  15014             if (local_port < 0) {
  15015                 return BCM_E_PORT;
  15016             }
  15017             BCM_IF_ERROR_RETURN
  15018                 (_bcm_td2_cosq_index_resolve(unit, local_port, cosq,
  15019                                             _BCM_TD2_COSQ_INDEX_STYLE_MCAST_QUEUE,
  15020                                             NULL, &startq, NULL));
  15021         }
  15022         startq -= 1480; /* MC queues comes after UC queues */
  15023         if (type == bcmCosqControlEgressMCQueueRedLimit) {
  15024             fld_limit = RED_SHARED_LIMITf;
  15025         } else {
  15026             fld_limit = YELLOW_SHARED_LIMITf;
  15027         }
  15028         mem = SOC_TD2_PMEM(unit, local_port, MMU_THDM_DB_QUEUE_CONFIG_0m,
  15029                            MMU_THDM_DB_QUEUE_CONFIG_1m);
  15030         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  15031         color_mode = soc_mem_field32_get(unit, mem, entry, Q_COLOR_LIMIT_DYNAMICf);
  15032 
  15033         if (color_mode == 1) { /* Dynamic color limit */
  15034             if (arg > 7) { /* Legal values are 0 - 7 */
  15035                 return BCM_E_PARAM;
  15036             } else {
  15037                 soc_mem_field32_set(unit, mem, entry, fld_limit, arg);
  15038             }
  15039         } else { /* Static color limit */
  15040             arg = (arg + _TD2_MMU_BYTES_PER_CELL - 1) / _TD2_MMU_BYTES_PER_CELL;
  15041 
  15042             /* Check for min/max values */
  15043             max_val = (1 << soc_mem_field_length(unit, mem, fld_limit)) - 1;
  15044             if ((arg/granularity) > max_val) {
  15045                 return BCM_E_PARAM;
  15046             } else {
  15047                 soc_mem_field32_set(unit, mem, entry, fld_limit, (arg/granularity));
  15048             }
  15049         }
  15050         BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry));
  15051 
  15052     } else {
  15053         return BCM_E_PARAM;
  15054     }
  15055 
  15056     return BCM_E_NONE;
  15057 }
  15058 
  15059 /*
  15060  * Function: _bcm_td2_cosq_egr_queue_color_limit_get
  15061  * Purpose: Get Red and Yellow color limit per queue
  15062  * Return value: IF color mode dynamic: limit should be between 0-7
  15063  *                                 0: 100% of green threshold
  15064  *                                 1: 12.5% of green threshold
  15065  *                                 2: 25% of green threshold
  15066  *                                 3: 37.5% of green threshold
  15067  *                                 4: 50% of green threshold
  15068  *                                 5: 67.5% of green threshold
  15069  *                                 6: 75% of green threshold
  15070  *                                 7: 87.5% of green threshold
  15071  *          If color mode static: Limit is number of bytes
  15072 */
  15073 
  15074 STATIC int
  15075 _bcm_td2_cosq_egr_queue_color_limit_get(int unit, bcm_gport_t gport,
  15076                                         bcm_cos_queue_t cosq,
  15077                                         bcm_cosq_control_t type,
  15078                                         int* arg)
  15079 {
  15080     bcm_port_t local_port;
  15081     int startq;
  15082     uint32 entry[SOC_MAX_MEM_WORDS];
  15083     soc_mem_t mem = INVALIDm;
  15084     soc_field_t fld_limit = INVALIDf;
  15085     int color_mode, granularity;
  15086 
  15087     if (arg == NULL) {
  15088         return BCM_E_PARAM;
  15089     }
  15090 
  15091     granularity = 8;
  15092 
  15093     if ((type == bcmCosqControlEgressUCQueueRedLimit) ||
  15094         (type == bcmCosqControlEgressUCQueueYellowLimit)) {
  15095         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  15096             BCM_IF_ERROR_RETURN
  15097                 (_bcm_td2_cosq_index_resolve(unit, gport, cosq,
  15098                                             _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE,
  15099                                             &local_port, &startq, NULL));
  15100         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  15101             return BCM_E_PARAM;
  15102         } else {
  15103             if (cosq < 0) {
  15104                 return BCM_E_PARAM;
  15105             }
  15106             BCM_IF_ERROR_RETURN
  15107                 (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port));
  15108             if (local_port < 0) {
  15109                 return BCM_E_PORT;
  15110             }
  15111             BCM_IF_ERROR_RETURN
  15112                 (_bcm_td2_cosq_index_resolve
  15113                  (unit, local_port, cosq, _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE,
  15114                   NULL, &startq, NULL));
  15115         }
  15116 
  15117         if (type == bcmCosqControlEgressUCQueueRedLimit) {
  15118             fld_limit = LIMIT_RED_CELLf;
  15119         } else {
  15120             fld_limit = LIMIT_YELLOW_CELLf;
  15121         }
  15122         mem = SOC_TD2_PMEM(unit, local_port, MMU_THDU_XPIPE_CONFIG_QUEUEm,
  15123                            MMU_THDU_YPIPE_CONFIG_QUEUEm);
  15124         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  15125         color_mode = soc_mem_field32_get(unit, mem, entry, Q_COLOR_LIMIT_DYNAMIC_CELLf);
  15126 
  15127         if (color_mode == 1) { /* Dynamic color limit */
  15128             *arg = soc_mem_field32_get(unit, mem, entry, fld_limit);
  15129         } else { /* Static color limit */
  15130             *arg = soc_mem_field32_get(unit, mem, entry, fld_limit);
  15131             *arg = (*arg) * granularity * _TD2_MMU_BYTES_PER_CELL;
  15132         }
  15133     } else if ((type == bcmCosqControlEgressMCQueueRedLimit) ||
  15134                (type == bcmCosqControlEgressMCQueueYellowLimit)) {
  15135         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  15136             return BCM_E_PARAM;
  15137         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  15138             BCM_IF_ERROR_RETURN
  15139                 (_bcm_td2_cosq_index_resolve(unit, gport, cosq,
  15140                                             _BCM_TD2_COSQ_INDEX_STYLE_MCAST_QUEUE,
  15141                                             &local_port, &startq, NULL));
  15142         } else {
  15143             if (cosq < 0) {
  15144                 return BCM_E_PARAM;
  15145             }
  15146             BCM_IF_ERROR_RETURN
  15147                 (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port));
  15148             if (local_port < 0) {
  15149                 return BCM_E_PORT;
  15150             }
  15151             BCM_IF_ERROR_RETURN
  15152                 (_bcm_td2_cosq_index_resolve(unit, local_port, cosq,
  15153                                             _BCM_TD2_COSQ_INDEX_STYLE_MCAST_QUEUE,
  15154                                             NULL, &startq, NULL));
  15155         }
  15156         startq -= 1480; /* MC queues comes after UC queues */
  15157         if (type == bcmCosqControlEgressMCQueueRedLimit) {
  15158             fld_limit = RED_SHARED_LIMITf;
  15159         } else {
  15160             fld_limit = YELLOW_SHARED_LIMITf;
  15161         }
  15162         mem = SOC_TD2_PMEM(unit, local_port, MMU_THDM_DB_QUEUE_CONFIG_0m,
  15163                           MMU_THDM_DB_QUEUE_CONFIG_1m);
  15164         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  15165         color_mode = soc_mem_field32_get(unit, mem, entry, Q_COLOR_LIMIT_DYNAMICf);
  15166 
  15167         if (color_mode == 1) { /* Dynamic color limit */
  15168             *arg = soc_mem_field32_get(unit, mem, entry, fld_limit);
  15169         } else { /* Static color limit */
  15170             *arg = soc_mem_field32_get(unit, mem, entry, fld_limit);
  15171             *arg = (*arg) * granularity * _TD2_MMU_BYTES_PER_CELL;
  15172         }
  15173 
  15174     } else {
  15175         return BCM_E_PARAM;
  15176     }
  15177 
  15178     return BCM_E_NONE;
  15179 }
  15180 
  15181 
  15182 /*
  15183  * Function: _bcm_td2_cosq_egr_queue_color_limit_mode_set
  15184  * Purpose: Set color limit mode per queue to static (0) or
  15185  *          dynamic (1)
  15186 */
  15187 
  15188 STATIC int
  15189 _bcm_td2_cosq_egr_queue_color_limit_mode_set(int unit, bcm_gport_t gport,
  15190                                              bcm_cos_queue_t cosq,
  15191                                              bcm_cosq_control_t type,
  15192                                              int arg)
  15193 {
  15194     bcm_port_t local_port;
  15195     int startq;
  15196     uint32 entry[SOC_MAX_MEM_WORDS];
  15197     soc_mem_t mem = INVALIDm;
  15198     int enable;
  15199 
  15200     if (arg < 0) {
  15201         return BCM_E_PARAM;
  15202     }
  15203 
  15204     arg = arg ? 1 : 0;
  15205 
  15206     if (type == bcmCosqControlEgressUCQueueColorLimitDynamicEnable) {
  15207         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  15208             BCM_IF_ERROR_RETURN
  15209                 (_bcm_td2_cosq_index_resolve(unit, gport, cosq,
  15210                                             _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE,
  15211                                             &local_port, &startq, NULL));
  15212         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  15213             return BCM_E_PARAM;
  15214         } else {
  15215             if (cosq < 0) {
  15216                 return BCM_E_PARAM;
  15217             }
  15218             BCM_IF_ERROR_RETURN
  15219                 (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port));
  15220             if (local_port < 0) {
  15221                 return BCM_E_PORT;
  15222             }
  15223             BCM_IF_ERROR_RETURN
  15224                 (_bcm_td2_cosq_index_resolve
  15225                  (unit, local_port, cosq, _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE,
  15226                   NULL, &startq, NULL));
  15227         }
  15228         mem = SOC_TD2_PMEM(unit, local_port, MMU_THDU_XPIPE_CONFIG_QUEUEm,
  15229                            MMU_THDU_YPIPE_CONFIG_QUEUEm);
  15230         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  15231         enable = soc_mem_field32_get(unit, mem, entry, Q_COLOR_LIMIT_DYNAMIC_CELLf);
  15232         if (enable != arg) {
  15233             soc_mem_field32_set(unit, mem, entry, Q_COLOR_LIMIT_DYNAMIC_CELLf, arg);
  15234             /* Reset the Red and Yellow limits when color limit mode is changed */
  15235             soc_mem_field32_set(unit, mem, entry, LIMIT_RED_CELLf, 0);
  15236             soc_mem_field32_set(unit, mem, entry, LIMIT_YELLOW_CELLf, 0);
  15237             BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry));
  15238         }
  15239     } else if (type == bcmCosqControlEgressMCQueueColorLimitDynamicEnable) {
  15240         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  15241             return BCM_E_PARAM;
  15242         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  15243             BCM_IF_ERROR_RETURN
  15244                 (_bcm_td2_cosq_index_resolve(unit, gport, cosq,
  15245                                             _BCM_TD2_COSQ_INDEX_STYLE_MCAST_QUEUE,
  15246                                             &local_port, &startq, NULL));
  15247         } else {
  15248             if (cosq < 0) {
  15249                 return BCM_E_PARAM;
  15250             }
  15251             BCM_IF_ERROR_RETURN
  15252                 (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port));
  15253             if (local_port < 0) {
  15254                 return BCM_E_PORT;
  15255             }
  15256             BCM_IF_ERROR_RETURN
  15257                 (_bcm_td2_cosq_index_resolve(unit, local_port, cosq,
  15258                                             _BCM_TD2_COSQ_INDEX_STYLE_MCAST_QUEUE,
  15259                                             NULL, &startq, NULL));
  15260         }
  15261         startq -= 1480; /* MC queues comes after UC queues */
  15262         mem = SOC_TD2_PMEM(unit, local_port, MMU_THDM_DB_QUEUE_CONFIG_0m,
  15263                           MMU_THDM_DB_QUEUE_CONFIG_1m);
  15264         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  15265         enable = soc_mem_field32_get(unit, mem, entry, Q_COLOR_LIMIT_DYNAMICf);
  15266         if (enable != arg) {
  15267             soc_mem_field32_set(unit, mem, entry, Q_COLOR_LIMIT_DYNAMICf, arg);
  15268             /* Reset the Red and Yellow limits when color limit mode is changed */
  15269             soc_mem_field32_set(unit, mem, entry, RED_SHARED_LIMITf, 0);
  15270             soc_mem_field32_set(unit, mem, entry, YELLOW_SHARED_LIMITf, 0);
  15271             BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry));
  15272         }
  15273     } else {
  15274         return BCM_E_PARAM;
  15275     }
  15276 
  15277     return BCM_E_NONE;
  15278 }
  15279 
  15280 /*
  15281  * Function: _bcm_td2_cosq_egr_queue_color_limit_mode_get
  15282  * Purpose: Get color limit mode per queue.
  15283  * Returns: 0 (static) or 1 (dynamic)
  15284 */
  15285 STATIC int
  15286 _bcm_td2_cosq_egr_queue_color_limit_mode_get(int unit, bcm_gport_t gport,
  15287                                              bcm_cos_queue_t cosq,
  15288                                              bcm_cosq_control_t type,
  15289                                              int* arg)
  15290 {
  15291     bcm_port_t local_port;
  15292     int startq;
  15293     uint32 entry[SOC_MAX_MEM_WORDS];
  15294     soc_mem_t mem = INVALIDm;
  15295 
  15296     if (arg == NULL) {
  15297         return BCM_E_PARAM;
  15298     }
  15299 
  15300     if (type == bcmCosqControlEgressUCQueueColorLimitDynamicEnable) {
  15301         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  15302             BCM_IF_ERROR_RETURN
  15303                 (_bcm_td2_cosq_index_resolve(unit, gport, cosq,
  15304                                             _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE,
  15305                                             &local_port, &startq, NULL));
  15306         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  15307             return BCM_E_PARAM;
  15308         } else {
  15309             if (cosq < 0) {
  15310                 return BCM_E_PARAM;
  15311             }
  15312             BCM_IF_ERROR_RETURN
  15313                 (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port));
  15314             if (local_port < 0) {
  15315                 return BCM_E_PORT;
  15316             }
  15317             BCM_IF_ERROR_RETURN
  15318                 (_bcm_td2_cosq_index_resolve
  15319                  (unit, local_port, cosq, _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE,
  15320                   NULL, &startq, NULL));
  15321         }
  15322         mem = SOC_TD2_PMEM(unit, local_port, MMU_THDU_XPIPE_CONFIG_QUEUEm,
  15323                            MMU_THDU_YPIPE_CONFIG_QUEUEm);
  15324         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  15325         *arg = soc_mem_field32_get(unit, mem, entry, Q_COLOR_LIMIT_DYNAMIC_CELLf);
  15326     } else if (type == bcmCosqControlEgressMCQueueColorLimitDynamicEnable) {
  15327         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  15328             return BCM_E_PARAM;
  15329         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  15330             BCM_IF_ERROR_RETURN
  15331                 (_bcm_td2_cosq_index_resolve(unit, gport, cosq,
  15332                                             _BCM_TD2_COSQ_INDEX_STYLE_MCAST_QUEUE,
  15333                                             &local_port, &startq, NULL));
  15334         } else {
  15335             if (cosq < 0) {
  15336                 return BCM_E_PARAM;
  15337             }
  15338             BCM_IF_ERROR_RETURN
  15339                 (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port));
  15340             if (local_port < 0) {
  15341                 return BCM_E_PORT;
  15342             }
  15343             BCM_IF_ERROR_RETURN
  15344                 (_bcm_td2_cosq_index_resolve(unit, local_port, cosq,
  15345                                             _BCM_TD2_COSQ_INDEX_STYLE_MCAST_QUEUE,
  15346                                             NULL, &startq, NULL));
  15347         }
  15348         startq -= 1480; /* MC queues comes after UC queues */
  15349         mem = SOC_TD2_PMEM(unit, local_port, MMU_THDM_DB_QUEUE_CONFIG_0m,
  15350                           MMU_THDM_DB_QUEUE_CONFIG_1m);
  15351         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  15352         *arg = soc_mem_field32_get(unit, mem, entry, Q_COLOR_LIMIT_DYNAMICf);
  15353     } else {
  15354         return BCM_E_PARAM;
  15355     }
  15356 
  15357     return BCM_E_NONE;
  15358 }
  15359 
  15360 int
  15361 bcm_td2_cosq_control_set(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
  15362                         bcm_cosq_control_t type, int arg)
  15363 {
  15364     switch (type) {
  15365     case bcmCosqControlEgressPool:
  15366     case bcmCosqControlEgressPoolLimitBytes:
  15367     case bcmCosqControlEgressPoolYellowLimitBytes:
  15368     case bcmCosqControlEgressPoolRedLimitBytes:
  15369     case bcmCosqControlEgressPoolLimitEnable:
  15370     case bcmCosqControlUCEgressPool:
  15371     case bcmCosqControlMCEgressPool:
  15372     case bcmCosqControlEgressPoolSharedLimitBytes: 
  15373     case bcmCosqControlEgressPoolResumeLimitBytes:
  15374     case bcmCosqControlEgressPoolYellowSharedLimitBytes: 
  15375     case bcmCosqControlEgressPoolYellowResumeLimitBytes:
  15376     case bcmCosqControlEgressPoolRedSharedLimitBytes:
  15377     case bcmCosqControlEgressPoolRedResumeLimitBytes: 
  15378         return _bcm_td2_cosq_egr_pool_set(unit, gport, cosq, type, arg);
  15379     case bcmCosqControlEfPropagation:
  15380         return _bcm_td2_cosq_ef_op(unit, gport, cosq, &arg, _BCM_COSQ_OP_SET);
  15381     case bcmCosqControlCongestionProxy:
  15382         return _bcm_td2_cosq_qcn_proxy_set(unit, gport, cosq, type, arg);
  15383     case bcmCosqControlEgressUCQueueSharedLimitBytes:
  15384     case bcmCosqControlEgressMCQueueSharedLimitBytes:
  15385     case bcmCosqControlEgressUCQueueMinLimitBytes:
  15386     case bcmCosqControlEgressMCQueueMinLimitBytes:
  15387         return _bcm_td2_cosq_egr_queue_set(unit, gport, cosq, type, arg);
  15388     case bcmCosqControlIngressPortPGSharedLimitBytes:
  15389     case bcmCosqControlIngressPortPoolMaxLimitBytes:
  15390     case bcmCosqControlIngressPortPGMinLimitBytes:
  15391     case bcmCosqControlIngressPortPoolMinLimitBytes:   
  15392     case bcmCosqControlIngressPortPGHeadroomLimitBytes:
  15393     case bcmCosqControlIngressPortPGResetFloorBytes:
  15394         return _bcm_td2_cosq_ing_res_set(unit, gport, cosq, type, arg);
  15395     case bcmCosqControlIngressPoolLimitBytes: 
  15396         return _bcm_td2_cosq_ing_res_limit_set(unit, gport, cosq, type, arg);
  15397     case bcmCosqControlIngressPool:
  15398         return _bcm_td2_cosq_ing_pool_set(unit, gport, cosq, type, arg);
  15399     case bcmCosqControlDropLimitAlpha:
  15400         return _bcm_td2_cosq_alpha_set(unit, gport, cosq,
  15401                             (bcm_cosq_control_drop_limit_alpha_value_t)arg);
  15402     case bcmCosqControlIngressPortPGSharedDynamicEnable:        
  15403     case bcmCosqControlEgressUCSharedDynamicEnable:
  15404     case bcmCosqControlEgressMCSharedDynamicEnable:
  15405         return _bcm_td2_cosq_dynamic_thresh_enable_set(unit, gport, cosq, 
  15406                                                        type, arg);
  15407     case bcmCosqControlEgressPortPoolYellowLimitBytes:
  15408     case bcmCosqControlEgressPortPoolRedLimitBytes:
  15409         return _bcm_td2_cosq_egr_port_pool_set(unit, gport, cosq, type, arg);
  15410     case bcmCosqControlEgressUCQueueLimitEnable:
  15411     case bcmCosqControlEgressMCQueueLimitEnable:
  15412     case bcmCosqControlEgressMCQueueColorLimitEnable:
  15413     case bcmCosqControlEgressUCQueueColorLimitEnable:
  15414         return _bcm_td2_cosq_egr_queue_limit_enable_set(unit, gport, cosq, type, arg);
  15415     case bcmCosqControlEgressUCQueueGroupMinEnable:
  15416     case bcmCosqControlEgressUCQueueGroupSharedLimitEnable:
  15417     case bcmCosqControlEgressUCQueueGroupSharedDynamicEnable:
  15418         return _bcm_td2_cosq_qgroup_limit_enable_set(unit, gport, cosq, type, arg);
  15419     case bcmCosqControlEgressUCQueueGroupMinLimitBytes:
  15420     case bcmCosqControlEgressUCQueueGroupSharedLimitBytes:
  15421         return _bcm_td2_cosq_qgroup_limit_set(unit, gport, cosq, type, arg);
  15422     case bcmCosqControlEgressUCQueueGroupDropLimitAlpha:
  15423         return _bcm_td2_cosq_qgroup_alpha_set(unit, gport, cosq,
  15424                             (bcm_cosq_control_drop_limit_alpha_value_t)arg);
  15425     case bcmCosqControlEgressUCQueueColorLimitDynamicEnable:
  15426     case bcmCosqControlEgressMCQueueColorLimitDynamicEnable:
  15427       return _bcm_td2_cosq_egr_queue_color_limit_mode_set(unit, gport, cosq,
  15428                                                      type, arg);
  15429     case bcmCosqControlEgressUCQueueRedLimit:
  15430     case bcmCosqControlEgressUCQueueYellowLimit:
  15431     case bcmCosqControlEgressMCQueueRedLimit:
  15432     case bcmCosqControlEgressMCQueueYellowLimit:
  15433       return _bcm_td2_cosq_egr_queue_color_limit_set(unit, gport, cosq, type, arg);
  15434 
  15435     default:
  15436         break;
  15437     }
  15438 
  15439     return BCM_E_UNAVAIL;
  15440 }
  15441 
  15442 int
  15443 bcm_td2_cosq_control_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
  15444                         bcm_cosq_control_t type, int *arg)
  15445 {
  15446     switch (type) {
  15447     case bcmCosqControlEgressPool:
  15448     case bcmCosqControlEgressPoolLimitBytes:
  15449     case bcmCosqControlEgressPoolYellowLimitBytes:
  15450     case bcmCosqControlEgressPoolRedLimitBytes:
  15451     case bcmCosqControlEgressPoolLimitEnable:
  15452     case bcmCosqControlUCEgressPool:
  15453     case bcmCosqControlMCEgressPool:
  15454     case bcmCosqControlEgressPoolSharedLimitBytes: 
  15455     case bcmCosqControlEgressPoolResumeLimitBytes:
  15456     case bcmCosqControlEgressPoolYellowSharedLimitBytes: 
  15457     case bcmCosqControlEgressPoolYellowResumeLimitBytes:
  15458     case bcmCosqControlEgressPoolRedSharedLimitBytes:
  15459     case bcmCosqControlEgressPoolRedResumeLimitBytes:         
  15460         return _bcm_td2_cosq_egr_pool_get(unit, gport, cosq, type, arg);
  15461     case bcmCosqControlEfPropagation:
  15462         return _bcm_td2_cosq_ef_op(unit, gport, cosq, arg, _BCM_COSQ_OP_GET);
  15463     case bcmCosqControlCongestionProxy:
  15464         return _bcm_td2_cosq_qcn_proxy_get(unit, gport, cosq, type, arg);
  15465     case bcmCosqControlEgressUCQueueSharedLimitBytes:
  15466     case bcmCosqControlEgressMCQueueSharedLimitBytes:
  15467     case bcmCosqControlEgressUCQueueMinLimitBytes:
  15468     case bcmCosqControlEgressMCQueueMinLimitBytes:
  15469         return _bcm_td2_cosq_egr_queue_get(unit, gport, cosq, type, arg);
  15470     case bcmCosqControlIngressPortPGSharedLimitBytes:
  15471     case bcmCosqControlIngressPortPoolMaxLimitBytes:
  15472     case bcmCosqControlIngressPortPGMinLimitBytes:
  15473     case bcmCosqControlIngressPortPoolMinLimitBytes:
  15474     case bcmCosqControlIngressPortPGHeadroomLimitBytes:
  15475     case bcmCosqControlIngressPortPGResetFloorBytes:        
  15476         return _bcm_td2_cosq_ing_res_get(unit, gport, cosq, type, arg);
  15477     case bcmCosqControlIngressPoolLimitBytes: 
  15478         return _bcm_td2_cosq_ing_res_limit_get(unit, gport, cosq, type, arg);        
  15479     case bcmCosqControlSPPortLimitState:
  15480     case bcmCosqControlPGPortLimitState:
  15481     case bcmCosqControlPGPortXoffState:
  15482     case bcmCosqControlPoolRedDropState:
  15483     case bcmCosqControlPoolYellowDropState:
  15484     case bcmCosqControlPoolGreenDropState:
  15485         return _bcm_td2_cosq_state_get(unit, gport, cosq, type, arg);
  15486     case bcmCosqControlIngressPool:
  15487         return _bcm_td2_cosq_ing_pool_get(unit, gport, cosq, type, arg);
  15488     case bcmCosqControlDropLimitAlpha:
  15489         return _bcm_td2_cosq_alpha_get(unit, gport, cosq,  
  15490                             (bcm_cosq_control_drop_limit_alpha_value_t *)arg);
  15491     case bcmCosqControlIngressPortPGSharedDynamicEnable:        
  15492     case bcmCosqControlEgressUCSharedDynamicEnable:
  15493     case bcmCosqControlEgressMCSharedDynamicEnable:
  15494         return _bcm_td2_cosq_dynamic_thresh_enable_get(unit, gport, cosq, 
  15495                                                        type, arg);
  15496     case bcmCosqControlPortQueueUcast:
  15497     case bcmCosqControlPortQueueMcast:
  15498         return _bcm_td2_cosq_port_qnum_get(unit, gport, cosq, type, arg);
  15499     case bcmCosqControlEgressPortPoolYellowLimitBytes:
  15500     case bcmCosqControlEgressPortPoolRedLimitBytes:
  15501         return _bcm_td2_cosq_egr_port_pool_get(unit, gport, cosq, type, arg);
  15502     case bcmCosqControlEgressUCQueueLimitEnable:
  15503     case bcmCosqControlEgressMCQueueLimitEnable:
  15504     case bcmCosqControlEgressMCQueueColorLimitEnable:
  15505     case bcmCosqControlEgressUCQueueColorLimitEnable:
  15506         return _bcm_td2_cosq_egr_queue_limit_enable_get(unit, gport, cosq, type, arg);
  15507     case bcmCosqControlEgressUCQueueGroupMinEnable:
  15508     case bcmCosqControlEgressUCQueueGroupSharedLimitEnable:
  15509     case bcmCosqControlEgressUCQueueGroupSharedDynamicEnable:
  15510         return _bcm_td2_cosq_qgroup_limit_enable_get(unit, gport, cosq, type, arg);
  15511     case bcmCosqControlEgressUCQueueGroupMinLimitBytes:
  15512     case bcmCosqControlEgressUCQueueGroupSharedLimitBytes:
  15513         return _bcm_td2_cosq_qgroup_limit_get(unit, gport, cosq, type, arg);
  15514     case bcmCosqControlEgressUCQueueGroupDropLimitAlpha:
  15515         return _bcm_td2_cosq_qgroup_alpha_get(unit, gport, cosq,
  15516                             (bcm_cosq_control_drop_limit_alpha_value_t *)arg);
  15517     case bcmCosqControlEgressUCQueueColorLimitDynamicEnable:
  15518     case bcmCosqControlEgressMCQueueColorLimitDynamicEnable:
  15519       return _bcm_td2_cosq_egr_queue_color_limit_mode_get(unit, gport, cosq,
  15520                                                      type, arg);
  15521     case bcmCosqControlEgressUCQueueRedLimit:
  15522     case bcmCosqControlEgressUCQueueYellowLimit:
  15523     case bcmCosqControlEgressMCQueueRedLimit:
  15524     case bcmCosqControlEgressMCQueueYellowLimit:
  15525       return _bcm_td2_cosq_egr_queue_color_limit_get(unit, gport, cosq, type, arg);
  15526 
  15527     default:
  15528         break;
  15529     }
  15530 
  15531     return BCM_E_UNAVAIL;
  15532 }
  15533 
  15534 int
  15535 bcm_td2_cosq_service_pool_set(
  15536     int unit,
  15537     bcm_service_pool_id_t id,
  15538     bcm_cosq_service_pool_t cosq_service_pool)
  15539 {
  15540     uint32 rval;
  15541     soc_field_t fld_enable = INVALIDf;
  15542     static const soc_field_t pool_port_color_enable_fields[] = {
  15543         PORTSP_COLOR_LIMIT_ENABLE_0f, PORTSP_COLOR_LIMIT_ENABLE_1f, 
  15544         PORTSP_COLOR_LIMIT_ENABLE_2f, PORTSP_COLOR_LIMIT_ENABLE_3f
  15545     };
  15546     static const soc_field_t pool_color_enable_fields[] = {
  15547         POOL_COLOR_LIMIT_ENABLE_0f, POOL_COLOR_LIMIT_ENABLE_1f, 
  15548         POOL_COLOR_LIMIT_ENABLE_2f, POOL_COLOR_LIMIT_ENABLE_3f
  15549     };
  15550 
  15551     if (id < 0 || (id > _TD2_NUM_SERVICE_POOL - 1)) {
  15552         return BCM_E_PARAM;
  15553     } 
  15554 
  15555     SOC_IF_ERROR_RETURN(READ_MMU_THDM_DB_DEVICE_THR_CONFIGr(unit, &rval));
  15556     switch (cosq_service_pool.type) {
  15557     case bcmCosqServicePoolPortColorAware:
  15558         fld_enable = pool_port_color_enable_fields[id];
  15559         break;
  15560     case bcmCosqServicePoolColorAware:
  15561         fld_enable = pool_color_enable_fields[id];
  15562         break;
  15563     default:
  15564         return BCM_E_PARAM;
  15565     }
  15566 
  15567     soc_reg_field_set(unit, MMU_THDM_DB_DEVICE_THR_CONFIGr, &rval,
  15568                       fld_enable, cosq_service_pool.enabled ? 1 : 0);
  15569     SOC_IF_ERROR_RETURN(WRITE_MMU_THDM_DB_DEVICE_THR_CONFIGr(unit, rval));
  15570     return BCM_E_NONE;
  15571 }
  15572 
  15573 
  15574 int
  15575 bcm_td2_cosq_service_pool_get(
  15576     int unit,
  15577     bcm_service_pool_id_t id,
  15578     bcm_cosq_service_pool_t *cosq_service_pool)
  15579 {
  15580     uint32 rval;
  15581     soc_field_t fld_enable = INVALIDf;
  15582     static const soc_field_t pool_port_color_enable_fields[] = {
  15583         PORTSP_COLOR_LIMIT_ENABLE_0f, PORTSP_COLOR_LIMIT_ENABLE_1f, 
  15584         PORTSP_COLOR_LIMIT_ENABLE_2f, PORTSP_COLOR_LIMIT_ENABLE_3f
  15585     };
  15586     static const soc_field_t pool_color_enable_fields[] = {
  15587         POOL_COLOR_LIMIT_ENABLE_0f, POOL_COLOR_LIMIT_ENABLE_1f, 
  15588         POOL_COLOR_LIMIT_ENABLE_2f, POOL_COLOR_LIMIT_ENABLE_3f
  15589     };
  15590 
  15591     if (cosq_service_pool == NULL) {
  15592         return BCM_E_PARAM;
  15593     }
  15594 
  15595     if (id < 0 || (id > _TD2_NUM_SERVICE_POOL - 1)) {
  15596         return BCM_E_PARAM;
  15597     }
  15598 
  15599     SOC_IF_ERROR_RETURN(READ_MMU_THDM_DB_DEVICE_THR_CONFIGr(unit, &rval));
  15600     switch (cosq_service_pool->type) {
  15601     case bcmCosqServicePoolPortColorAware:
  15602         fld_enable = pool_port_color_enable_fields[id];
  15603         break;
  15604     case bcmCosqServicePoolColorAware:
  15605         fld_enable = pool_color_enable_fields[id];
  15606         break;
  15607     default:
  15608         return BCM_E_PARAM;
  15609     }
  15610 
  15611     cosq_service_pool->enabled = soc_reg_field_get(unit, MMU_THDM_DB_DEVICE_THR_CONFIGr, rval,
  15612                                                    fld_enable);
  15613     return BCM_E_NONE;
  15614 }
  15615 
  15616 
  15617 
  15618 int
  15619 _bcm_td2_cosq_gport_detach(int unit, bcm_port_t port)
  15620 {
  15621     return BCM_E_NONE;
  15622 }
  15623 
  15624 /*
  15625  * Function:
  15626  *     bcm_td2_cosq_gport_bandwidth_set
  15627  * Purpose:
  15628  *     Configure COS queue bandwidth control
  15629  * Parameters:
  15630  *     unit   - (IN) unit number
  15631  *     gport  - (IN) GPORT identifier
  15632  *     cosq   - (IN) COS queue to configure, -1 for all COS queues
  15633  *     kbits_sec_min - (IN) minimum bandwidth, kbits/sec
  15634  *     kbits_sec_max - (IN) maximum bandwidth, kbits/sec
  15635  *     flags  - (IN) BCM_COSQ_BW_*
  15636  * Returns:
  15637  *     BCM_E_XXX
  15638  */
  15639 int
  15640 bcm_td2_cosq_gport_bandwidth_set(int unit, bcm_gport_t gport,
  15641                                 bcm_cos_queue_t cosq, uint32 kbits_sec_min,
  15642                                 uint32 kbits_sec_max, uint32 flags)
  15643 {
  15644     int i, start_cos, end_cos, local_port, ets_mode;
  15645     _bcm_td2_cosq_node_t *node, *child_node;
  15646     uint32 burst_min, burst_max;
  15647     int mode = 0, weight = 0, weight_sum = 0;
  15648 
  15649     if (cosq <= -1) {
  15650         if (BCM_GPORT_IS_SET(gport)) {
  15651             BCM_IF_ERROR_RETURN
  15652                 (_bcm_td2_cosq_node_get(unit, gport, 0, NULL, 
  15653                                         NULL, NULL, &node));
  15654             start_cos = 0;
  15655             end_cos = node->numq - 1;
  15656         } else {
  15657             start_cos = 0;
  15658             end_cos = _TD2_NUM_COS(unit) - 1;
  15659         }
  15660     } else {
  15661         start_cos = end_cos = cosq;
  15662     }
  15663     
  15664     BCM_IF_ERROR_RETURN(_bcm_td2_cosq_localport_resolve(unit, gport, &local_port));
  15665     ets_mode = _bcm_td2_cosq_port_has_ets(unit, local_port);
  15666     for (i = start_cos; i <= end_cos; i++) {
  15667         /* Workaround for bandwidth distriution inaccuracy when max bandwidth
  15668          * shaping is used in conjunction with round robin scheduling.
  15669          * Burst Size=SUM((RR_weights[except for Queue_i]+1))*MTU*ShapedRate/AvailableExcessBWRate
  15670          */
  15671         if (BCM_GPORT_IS_SET(gport) && ets_mode && SOC_IS_TRIDENT2(unit)) {
  15672             BCM_IF_ERROR_RETURN
  15673                 (_bcm_td2_cosq_node_get(unit, gport, 0, NULL,
  15674                                         NULL, NULL, &node));
  15675             /* SUM((RR_weights[except for Queue_i]+1)) */
  15676             for (child_node = node->child;
  15677                  child_node != NULL;
  15678                  child_node = child_node->sibling) {
  15679                 if (child_node->attached_to_input != i) {
  15680                     BCM_IF_ERROR_RETURN(
  15681                         bcm_td2_cosq_gport_sched_get(
  15682                             unit, gport, child_node->attached_to_input, &mode, &weight));
  15683                     if (mode != SOC_TD2_SCHED_MODE_STRICT) {
  15684                         weight_sum += weight + 1;
  15685                     }
  15686                 }
  15687             }
  15688         }
  15689 
  15690         burst_min = (kbits_sec_min > 0) ?
  15691               _bcm_td_default_burst_size_by_weight(
  15692                       unit, local_port, kbits_sec_min, weight_sum) : 0;
  15693 
  15694         burst_max = (kbits_sec_max > 0) ?
  15695               _bcm_td_default_burst_size_by_weight(
  15696                       unit, local_port, kbits_sec_max, weight_sum) : 0;
  15697 
  15698 
  15699         BCM_IF_ERROR_RETURN
  15700             (_bcm_td2_cosq_bucket_set(unit, gport, i, kbits_sec_min,
  15701                          kbits_sec_max, burst_min, burst_max, flags));
  15702     }
  15703 
  15704     return BCM_E_NONE;
  15705 }
  15706 
  15707 /*
  15708  * Function:
  15709  *     bcm_td2_cosq_gport_bandwidth_get
  15710  * Purpose:
  15711  *     Get COS queue bandwidth control configuration
  15712  * Parameters:
  15713  *     unit   - (IN) unit number
  15714  *     gport  - (IN) GPORT identifier
  15715  *     cosq   - (IN) COS queue to get, -1 for any COS queue
  15716  *     kbits_sec_min - (OUT) minimum bandwidth, kbits/sec
  15717  *     kbits_sec_max - (OUT) maximum bandwidth, kbits/sec
  15718  *     flags  - (OUT) BCM_COSQ_BW_*
  15719  * Returns:
  15720  *     BCM_E_XXX
  15721  */
  15722 int
  15723 bcm_td2_cosq_gport_bandwidth_get(int unit, bcm_gport_t gport,
  15724                                 bcm_cos_queue_t cosq, uint32 *kbits_sec_min,
  15725                                 uint32 *kbits_sec_max, uint32 *flags)
  15726 {
  15727     uint32 kbits_sec_burst;
  15728 
  15729     if (cosq == -1) {
  15730         return BCM_E_PARAM;
  15731     }
  15732 
  15733     BCM_IF_ERROR_RETURN
  15734         (_bcm_td2_cosq_bucket_get(unit, gport, cosq,
  15735                                  kbits_sec_min, kbits_sec_max,
  15736                                  &kbits_sec_burst, &kbits_sec_burst, flags));
  15737     return BCM_E_NONE;
  15738 }
  15739 
  15740 /*
  15741  * Function:
  15742  *     bcm_td2_cosq_gport_bandwidth_burst_set
  15743  * Purpose:
  15744  *     Configure COS queue bandwidth burst setting
  15745  * Parameters:
  15746  *      unit        - (IN) unit number
  15747  *      gport       - (IN) GPORT identifier
  15748  *      cosq        - (IN) COS queue to configure, -1 for all COS queues
  15749  *      kbits_burst - (IN) maximum burst, kbits
  15750  * Returns:
  15751  *      BCM_E_XXX
  15752  */
  15753 int
  15754 bcm_td2_cosq_gport_bandwidth_burst_set(int unit, bcm_gport_t gport,
  15755                                       bcm_cos_queue_t cosq,
  15756                                       uint32 kbits_burst_min,
  15757                                       uint32 kbits_burst_max)
  15758 {
  15759     int i, start_cos, end_cos;
  15760     uint32 kbits_sec_min, kbits_sec_max, kbits_sec_burst, flags;
  15761     _bcm_td2_cosq_node_t *node;
  15762 
  15763     if (cosq < -1) {
  15764         return BCM_E_PARAM;
  15765     }
  15766 
  15767     if (cosq == -1) {
  15768         if (BCM_GPORT_IS_SET(gport)) {
  15769             BCM_IF_ERROR_RETURN
  15770                 (_bcm_td2_cosq_node_get(unit, gport, 0, NULL, 
  15771                                         NULL, NULL, &node));
  15772             start_cos = 0;
  15773             end_cos = node->numq - 1;
  15774         } else {
  15775             start_cos = 0;
  15776             end_cos = _TD2_NUM_COS(unit) - 1;
  15777         }
  15778     } else {
  15779         start_cos = end_cos = cosq;
  15780     }
  15781 
  15782     for (i = start_cos; i <= end_cos; i++) {
  15783         BCM_IF_ERROR_RETURN
  15784             (_bcm_td2_cosq_bucket_get(unit, gport, i, &kbits_sec_min,
  15785                                      &kbits_sec_max, &kbits_sec_burst,
  15786                                      &kbits_sec_burst, &flags));
  15787         BCM_IF_ERROR_RETURN
  15788             (_bcm_td2_cosq_bucket_set(unit, gport, i, kbits_sec_min,
  15789                                      kbits_sec_max, kbits_burst_min, 
  15790                                      kbits_burst_max, flags));
  15791     }
  15792 
  15793     return BCM_E_NONE;
  15794 }
  15795 
  15796 /*
  15797  * Function:
  15798  *     bcm_td2_cosq_gport_bandwidth_burst_get
  15799  * Purpose:
  15800  *     Get COS queue bandwidth burst setting
  15801  * Parameters:
  15802  *     unit        - (IN) unit number
  15803  *     gport       - (IN) GPORT identifier
  15804  *     cosq        - (IN) COS queue to get, -1 for any queue
  15805  *     kbits_burst - (OUT) maximum burst, kbits
  15806  * Returns:
  15807  *     BCM_E_XXX
  15808  */
  15809 int
  15810 bcm_td2_cosq_gport_bandwidth_burst_get(int unit, bcm_gport_t gport,
  15811                                        bcm_cos_queue_t cosq,
  15812                                        uint32 *kbits_burst_min,
  15813                                        uint32 *kbits_burst_max)
  15814 {
  15815     uint32 kbits_sec_min, kbits_sec_max, flags;
  15816 
  15817     if (cosq < -1) {
  15818         return BCM_E_PARAM;
  15819     }
  15820 
  15821     BCM_IF_ERROR_RETURN
  15822         (_bcm_td2_cosq_bucket_get(unit, gport, cosq == -1 ? 0 : cosq,
  15823                                  &kbits_sec_min, &kbits_sec_max, kbits_burst_min,
  15824                                  kbits_burst_max, &flags));
  15825 
  15826     return BCM_E_NONE;
  15827 }
  15828 
  15829 /*
  15830  * Function:
  15831  *     bcm_td2_cosq_gport_sched_set
  15832  * Purpose:
  15833  *     Configure COS queue scheduler setting
  15834  * Parameters:
  15835  *      unit   - (IN) unit number
  15836  *      gport  - (IN) GPORT identifier
  15837  *      cosq   - (IN) COS queue to configure, -1 for all COS queues
  15838  *      mode   - (IN) Scheduling mode, one of BCM_COSQ_xxx
  15839  *      weight - (IN) queue weight
  15840  * Returns:
  15841  *      BCM_E_XXX
  15842  */
  15843 int
  15844 bcm_td2_cosq_gport_sched_set(int unit, bcm_gport_t gport,
  15845                             bcm_cos_queue_t cosq, int mode, int weight)
  15846 {
  15847     int rv, numq, i, count;
  15848 
  15849     if (cosq == -1) {
  15850         BCM_IF_ERROR_RETURN
  15851             (_bcm_td2_cosq_index_resolve(unit, gport, cosq,
  15852                                         _BCM_TD2_COSQ_INDEX_STYLE_SCHEDULER,
  15853                                         NULL, NULL, &numq));
  15854         cosq = 0;
  15855     } else {
  15856         numq = 1;
  15857     }
  15858 
  15859     count = 0;
  15860     for (i = 0; i < numq; i++) {
  15861         rv = _bcm_td2_cosq_sched_set(unit, gport, cosq + i, mode, weight);
  15862         if (rv == BCM_E_NOT_FOUND) {
  15863             continue;
  15864         } else if (BCM_FAILURE(rv)) {
  15865             return rv;
  15866         } else {
  15867             count++;
  15868         }
  15869     }
  15870 
  15871     return count > 0 ? BCM_E_NONE : BCM_E_NOT_FOUND;
  15872 }
  15873 
  15874 /*
  15875  * Function:
  15876  *     bcm_td2_cosq_gport_sched_get
  15877  * Purpose:
  15878  *     Get COS queue scheduler setting
  15879  * Parameters:
  15880  *     unit   - (IN) unit number
  15881  *     gport  - (IN) GPORT identifier
  15882  *     cosq   - (IN) COS queue to get, -1 for any queue
  15883  *     mode   - (OUT) Scheduling mode, one of BCM_COSQ_xxx
  15884  *     weight - (OUT) queue weight
  15885  * Returns:
  15886  *     BCM_E_XXX
  15887  */
  15888 int
  15889 bcm_td2_cosq_gport_sched_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
  15890                             int *mode, int *weight)
  15891 {
  15892     int rv, numq, i;
  15893 
  15894     if (cosq == -1) {
  15895         BCM_IF_ERROR_RETURN
  15896             (_bcm_td2_cosq_index_resolve(unit, gport, 0,
  15897                                         _BCM_TD2_COSQ_INDEX_STYLE_SCHEDULER,
  15898                                         NULL, NULL, &numq));
  15899         cosq = 0;
  15900     } else {
  15901         numq = 1;
  15902     }
  15903 
  15904     for (i = 0; i < numq; i++) {
  15905         rv = _bcm_td2_cosq_sched_get(unit, gport, cosq + i, mode, weight);
  15906         if (rv == BCM_E_NOT_FOUND) {
  15907             continue;
  15908         } else {
  15909             return rv;
  15910         }
  15911     }
  15912 
  15913     return BCM_E_NOT_FOUND;
  15914 }
  15915 
  15916 /*
  15917  * Function:
  15918  *     bcm_td2_cosq_gport_discard_set
  15919  * Purpose:
  15920  *     Configure port WRED setting
  15921  * Parameters:
  15922  *     unit    - (IN) unit number
  15923  *     port    - (IN) GPORT identifier
  15924  *     cosq    - (IN) COS queue to configure, -1 for all COS queues
  15925  *     discard - (IN) discard settings
  15926  * Returns:
  15927  *     BCM_E_XXX
  15928  */
  15929 int
  15930 bcm_td2_cosq_gport_discard_set(int unit, bcm_gport_t gport,
  15931                                bcm_cos_queue_t cosq,
  15932                                bcm_cosq_gport_discard_t *discard)
  15933 {
  15934     uint32 min_thresh, max_thresh, flags = 0;
  15935     int cell_size, cell_field_max;
  15936     bcm_port_t local_port = -1;
  15937 
  15938     /* refresh_time  from 1 to 7 be set the same as default 8,so the reasonable 
  15939            range of refresh_time  is from 1 to 512 */
  15940     if (discard == NULL ||
  15941         discard->gain < 0 || discard->gain > 15 ||
  15942         discard->drop_probability < 0 || discard->drop_probability > 100 ||
  15943         discard->refresh_time <= 0 || discard->refresh_time > 512 ||
  15944         (discard->min_thresh > discard->max_thresh) ||
  15945         (discard->min_thresh < 0)) {
  15946         return BCM_E_PARAM;
  15947     }
  15948 
  15949     cell_size = _BCM_TD2_BYTES_PER_CELL;
  15950     cell_field_max = TD2_CELL_FIELD_MAX;
  15951 
  15952     min_thresh = discard->min_thresh;
  15953     max_thresh = discard->max_thresh;
  15954     if (discard->flags & BCM_COSQ_DISCARD_BYTES) {
  15955         /* Convert bytes to cells */
  15956         min_thresh += (cell_size - 1);
  15957         min_thresh /= cell_size;
  15958 
  15959         max_thresh += (cell_size - 1);
  15960         max_thresh /= cell_size;
  15961 
  15962         if ((min_thresh > cell_field_max) ||
  15963             (max_thresh > cell_field_max)) {
  15964             return BCM_E_PARAM;
  15965         }
  15966     } else {
  15967         /* Packet mode not supported */
  15968         return BCM_E_PARAM;
  15969     }
  15970 
  15971     if (gport != BCM_GPORT_INVALID) {
  15972         BCM_IF_ERROR_RETURN
  15973             (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port));
  15974         if (IS_CPU_PORT(unit,local_port) || IS_LB_PORT(unit,local_port)) {
  15975             return BCM_E_PORT;
  15976         }
  15977     }
  15978 
  15979         BCM_IF_ERROR_RETURN
  15980             (_bcm_td2_cosq_wred_set(unit, gport, cosq, discard->flags,
  15981                                    min_thresh, max_thresh,
  15982                                    discard->drop_probability, discard->gain,
  15983                                    FALSE, flags,discard->refresh_time));
  15984 
  15985     return BCM_E_NONE;
  15986 }
  15987 
  15988 /*
  15989  * Function:
  15990  *     bcm_td2_cosq_gport_discard_get
  15991  * Purpose:
  15992  *     Get port WRED setting
  15993  * Parameters:
  15994  *     unit    - (IN) unit number
  15995  *     port    - (IN) GPORT identifier
  15996  *     cosq    - (IN) COS queue to get, -1 for any queue
  15997  *     discard - (OUT) discard settings
  15998  * Returns:
  15999  *     BCM_E_XXX
  16000  */
  16001 int
  16002 bcm_td2_cosq_gport_discard_get(int unit, bcm_gport_t gport,
  16003                               bcm_cos_queue_t cosq,
  16004                               bcm_cosq_gport_discard_t *discard)
  16005 {
  16006     uint32 min_thresh, max_thresh;
  16007     bcm_port_t local_port = -1;
  16008 
  16009     if (discard == NULL) {
  16010         return BCM_E_PARAM;
  16011     }
  16012 
  16013     if (discard->flags & BCM_COSQ_DISCARD_PACKETS) {
  16014         /* Packet mode not supported */
  16015         return BCM_E_PARAM;
  16016     }
  16017 
  16018     if (gport != BCM_GPORT_INVALID) {
  16019         BCM_IF_ERROR_RETURN
  16020             (_bcm_td2_cosq_localport_resolve(unit, gport, &local_port));
  16021         if (IS_CPU_PORT(unit,local_port) || IS_LB_PORT(unit,local_port)) {
  16022             return BCM_E_PORT;
  16023         }
  16024     }
  16025 
  16026     BCM_IF_ERROR_RETURN
  16027         (_bcm_td2_cosq_wred_get(unit, gport, cosq == -1 ? 0 : cosq,
  16028                                &discard->flags, &min_thresh, &max_thresh,
  16029                                &discard->drop_probability, &discard->gain, 
  16030                                0,&discard->refresh_time));
  16031 
  16032     /* Convert number of cells to number of bytes */
  16033     discard->min_thresh = min_thresh * _BCM_TD2_BYTES_PER_CELL;
  16034     discard->max_thresh = max_thresh * _BCM_TD2_BYTES_PER_CELL;
  16035 
  16036     return BCM_E_NONE;
  16037 }
  16038 
  16039 int
  16040 _bcm_td2_cosq_pfc_class_resolve(bcm_switch_control_t sctype, int *type,
  16041                                int *class)
  16042 {
  16043     switch (sctype) {
  16044     case bcmSwitchPFCClass7Queue:
  16045     case bcmSwitchPFCClass6Queue:
  16046     case bcmSwitchPFCClass5Queue:
  16047     case bcmSwitchPFCClass4Queue:
  16048     case bcmSwitchPFCClass3Queue:
  16049     case bcmSwitchPFCClass2Queue:
  16050     case bcmSwitchPFCClass1Queue:
  16051     case bcmSwitchPFCClass0Queue:
  16052         *type = _BCM_TD2_COSQ_TYPE_UCAST;
  16053         break;
  16054     case bcmSwitchPFCClass7McastQueue:
  16055     case bcmSwitchPFCClass6McastQueue:
  16056     case bcmSwitchPFCClass5McastQueue:
  16057     case bcmSwitchPFCClass4McastQueue:
  16058     case bcmSwitchPFCClass3McastQueue:
  16059     case bcmSwitchPFCClass2McastQueue:
  16060     case bcmSwitchPFCClass1McastQueue:
  16061     case bcmSwitchPFCClass0McastQueue:
  16062         *type = _BCM_TD2_COSQ_TYPE_MCAST;
  16063         break;
  16064     case bcmSwitchPFCClass7DestmodQueue:
  16065     case bcmSwitchPFCClass6DestmodQueue:
  16066     case bcmSwitchPFCClass5DestmodQueue:
  16067     case bcmSwitchPFCClass4DestmodQueue:
  16068     case bcmSwitchPFCClass3DestmodQueue:
  16069     case bcmSwitchPFCClass2DestmodQueue:
  16070     case bcmSwitchPFCClass1DestmodQueue:
  16071     case bcmSwitchPFCClass0DestmodQueue:
  16072         *type = _BCM_TD2_COSQ_TYPE_EXT_UCAST;
  16073         break;
  16074     default:
  16075         return BCM_E_PARAM;
  16076     }
  16077 
  16078     switch (sctype) {
  16079     case bcmSwitchPFCClass7Queue:
  16080     case bcmSwitchPFCClass7McastQueue:
  16081     case bcmSwitchPFCClass7DestmodQueue:
  16082         *class = 7;
  16083         break;
  16084     case bcmSwitchPFCClass6Queue:
  16085     case bcmSwitchPFCClass6McastQueue:
  16086     case bcmSwitchPFCClass6DestmodQueue:
  16087         *class = 6;
  16088         break;
  16089     case bcmSwitchPFCClass5Queue:
  16090     case bcmSwitchPFCClass5McastQueue:
  16091     case bcmSwitchPFCClass5DestmodQueue:
  16092         *class = 5;
  16093         break;
  16094     case bcmSwitchPFCClass4Queue:
  16095     case bcmSwitchPFCClass4McastQueue:
  16096     case bcmSwitchPFCClass4DestmodQueue:
  16097         *class = 4;
  16098         break;
  16099     case bcmSwitchPFCClass3Queue:
  16100     case bcmSwitchPFCClass3McastQueue:
  16101     case bcmSwitchPFCClass3DestmodQueue:
  16102         *class = 3;
  16103         break;
  16104     case bcmSwitchPFCClass2Queue:
  16105     case bcmSwitchPFCClass2McastQueue:
  16106     case bcmSwitchPFCClass2DestmodQueue:
  16107         *class = 2;
  16108         break;
  16109     case bcmSwitchPFCClass1Queue:
  16110     case bcmSwitchPFCClass1McastQueue:
  16111     case bcmSwitchPFCClass1DestmodQueue:
  16112         *class = 1;
  16113         break;
  16114     case bcmSwitchPFCClass0Queue:
  16115     case bcmSwitchPFCClass0McastQueue:
  16116     case bcmSwitchPFCClass0DestmodQueue:
  16117         *class = 0;
  16118         break;
  16119     /*
  16120      * COVERITY
  16121      *
  16122      * This default is unreachable but needed for some compiler. 
  16123      */ 
  16124     /* coverity[dead_error_begin] */
  16125     default:
  16126         return BCM_E_INTERNAL;
  16127     }
  16128     return BCM_E_NONE;
  16129 }
  16130 
  16131 /*
  16132  * Function:
  16133  *     _bcm_td2_pfc_map_index_resolve
  16134  * Purpose:
  16135  *     Resolve table index and field of MMU_INTFI_X/YPIPE_FC_MAP_TBL0/1/2.
  16136  * Parameters:
  16137  *     unit     - (IN) unit number
  16138  *     port     - (IN) port number
  16139  *     hw_index - (IN) Gport node hw_index
  16140  *     level    - (IN) Sched level
  16141  *     index    - (OUT) Resolved table index
  16142  *     field    - (OUT) Resolved index field
  16143  * Returns:
  16144  *     BCM_E_XXX
  16145  */
  16146 STATIC int
  16147 _bcm_td2_pfc_map_index_resolve(int unit, int port,
  16148                                uint32 hw_index, int level,
  16149                                int *index, int *field)
  16150 {
  16151     int map_entry_index, eindex;
  16152     int port_num = 0;
  16153     int map_entry_index_num = 0;
  16154     int mcq_offset;
  16155     uint16 dev_id;
  16156     uint8 rev_id;
  16157 
  16158     if ((index == NULL) || (field == NULL)) {
  16159         return BCM_E_PARAM;
  16160     }
  16161     if ((level != SOC_TD2_NODE_LVL_L0) &&
  16162         (level != SOC_TD2_NODE_LVL_L1) &&
  16163         (level != SOC_TD2_NODE_LVL_L2)) {
  16164         return BCM_E_PARAM;
  16165     }
  16166 
  16167    /* FC_MAP_TBL[Level] has 4 Index[0-3], whose values become Index to PFC_ST_TBL.
  16168     * Each Index of PFC_ST_TBL can point to congestion state of 4 Qs. 
  16169     * Hence each Entry of FC_MAP_TBL can refer to 16 Qs.
  16170     *
  16171     * NOTE: Index of FC_MAP_TBL CANNOT be used to point to Qs/Nodes belonging
  16172     *       to Different Ports.
  16173     */
  16174     if (level == SOC_TD2_NODE_LVL_L0) {
  16175         if (IS_TD2_HSP_PORT(unit, port)) {
  16176             if ((hw_index % _BCM_TD2_HSP_PORT_MAX_L0) > 3) {
  16177                 return BCM_E_UNAVAIL;
  16178             }
  16179             port_num = hw_index / _BCM_TD2_HSP_PORT_MAX_L0;
  16180 
  16181             map_entry_index_num = port_num;
  16182             /* each entry contains 4 indices */
  16183             map_entry_index = map_entry_index_num / 4;
  16184             eindex = map_entry_index_num & 0x3;
  16185         } else {
  16186             map_entry_index = hw_index/16;
  16187             eindex = (hw_index % 16) / 4;
  16188         }
  16189     } else if (level == SOC_TD2_NODE_LVL_L1) {
  16190         if (IS_TD2_HSP_PORT(unit, port)) {
  16191             if ((hw_index % _BCM_TD2_HSP_PORT_MAX_L1) > 7) {
  16192                 return BCM_E_UNAVAIL;
  16193             }
  16194             port_num = hw_index / _BCM_TD2_HSP_PORT_MAX_L1;
  16195             soc_cm_get_id_otp(unit, &dev_id, &rev_id);
  16196             if ((dev_id == BCM56850_DEVICE_ID) &&
  16197                 (rev_id <= BCM56850_A1_REV_ID)) {
  16198             /* A0 & A1: even port takes 2 entries, odd port takes 3 entries. */
  16199                 map_entry_index_num = (port_num * 2) + port_num / 2;
  16200                 if (port_num % 2) {
  16201                     map_entry_index_num += ((hw_index % 10) + 2) / 4;
  16202                 } else {
  16203                     map_entry_index_num += ((hw_index % 10) >= 4)? 1 : 0;
  16204                 }
  16205             } else {
  16206                 map_entry_index_num = port_num * 2 +
  16207                                       (((hw_index % 10) >= 4)? 1 : 0);
  16208             }
  16209             map_entry_index = map_entry_index_num / 4;
  16210             eindex = map_entry_index_num & 0x3;
  16211         } else {
  16212             map_entry_index = hw_index/16;
  16213             eindex = (hw_index % 16) / 4;
  16214         }
  16215     } else {
  16216         if (hw_index < 1480) {
  16217         /* UC queue */
  16218             if (IS_TD2_HSP_PORT(unit, port)) {
  16219                 if ((hw_index % 10) > 7) {
  16220                     return BCM_E_UNAVAIL;
  16221                 }
  16222                 port_num = hw_index / 10;
  16223                 map_entry_index_num = port_num * 2 +
  16224                                       (((hw_index % 10) >= 4)? 1 : 0);
  16225                 map_entry_index = map_entry_index_num / 4;
  16226                 eindex = map_entry_index_num & 0x3;
  16227             } else {
  16228                 map_entry_index = hw_index/16;
  16229                 eindex = (hw_index % 16) / 4;
  16230             }
  16231         } else {
  16232         /* MC queue - Index Calculation
  16233          *   PFC can work only on 8 out of 10 MC queues of each port.
  16234          *   So in FC_MAP_TBL2, each Port will use only 2 Index(4 Qs each) for
  16235          *   MC Qs.
  16236          *   MC queue base starts at 1480, 1480/16 = 92.5 
  16237          *   Hence MC Qs starts at = Map_Tbl2_Idx[92] and Index2.
  16238          */
  16239             mcq_offset = hw_index % 1480;
  16240             if ((mcq_offset % 10) > 7) {
  16241                 /* FC support only for Q0-7 */
  16242                 return BCM_E_INTERNAL;
  16243             }
  16244             map_entry_index = hw_index - (mcq_offset * 2 / 10);
  16245             map_entry_index /= 16;
  16246             eindex = (mcq_offset % 10)/4;
  16247             eindex += ((mcq_offset /10) % 2) ? 0 : 2;
  16248         }
  16249     }
  16250 
  16251     *index = map_entry_index;
  16252     *field = eindex;
  16253     return BCM_E_NONE;
  16254 }
  16255 
  16256 STATIC int
  16257 _bcm_td2_map_fc_status_to_node(int unit, int port, _bcm_td2_fc_type_t fct,
  16258                     int spad_offset, int cosq, uint32 hw_index, int level)
  16259 {
  16260     int map_entry_index, eindex, pipe, pfc;
  16261     uint32 map_entry[SOC_MAX_MEM_WORDS];
  16262     static const soc_field_t self[] = {
  16263         SEL0f, SEL1f, SEL2f, SEL3f
  16264     };
  16265     static const soc_field_t indexf[] = {
  16266         INDEX0f, INDEX1f, INDEX2f, INDEX3f
  16267     };
  16268     static const soc_mem_t memx[] = {
  16269         INVALIDm,
  16270         MMU_INTFI_XPIPE_FC_MAP_TBL0m,
  16271         MMU_INTFI_XPIPE_FC_MAP_TBL1m,
  16272         MMU_INTFI_XPIPE_FC_MAP_TBL2m
  16273     };
  16274     static const soc_mem_t memy[] = {
  16275         INVALIDm,
  16276         MMU_INTFI_YPIPE_FC_MAP_TBL0m,
  16277         MMU_INTFI_YPIPE_FC_MAP_TBL1m,
  16278         MMU_INTFI_YPIPE_FC_MAP_TBL2m
  16279     };
  16280     soc_mem_t mem;
  16281     int port_num = 0;
  16282     uint16 dev_id;
  16283     uint8 rev_id;
  16284 
  16285     pfc = (fct == _BCM_TD2_COSQ_FC_PFC) ? 1 : 0;
  16286     pipe = _BCM_TD2_PORT_TO_PIPE(unit, port);
  16287     mem = (pipe == _TD2_XPIPE) ? memx[level] : memy[level];
  16288     if (mem ==  INVALIDm) {
  16289         return BCM_E_PARAM;
  16290     }
  16291 
  16292     if (IS_TD2_HSP_PORT(unit, port)) {
  16293         port_num = hw_index / 10;
  16294         soc_cm_get_id_otp(unit, &dev_id, &rev_id);
  16295         if ((dev_id == BCM56850_DEVICE_ID) &&
  16296             (rev_id <= BCM56850_A1_REV_ID) &&
  16297             ((level == SOC_TD2_NODE_LVL_L1) ||
  16298              (level == SOC_TD2_NODE_LVL_L2))) {
  16299             if (port_num % 2) {
  16300                 cosq += 2;
  16301             }
  16302         }
  16303     }
  16304 
  16305     BCM_IF_ERROR_RETURN(_bcm_td2_pfc_map_index_resolve(unit, port,
  16306                             hw_index, level, &map_entry_index, &eindex));
  16307         BCM_IF_ERROR_RETURN
  16308             (soc_mem_read(unit, mem, MEM_BLOCK_ALL, map_entry_index, &map_entry));
  16309         /* coverity[overrun-local : FALSE] */
  16310         soc_mem_field32_set(unit, mem, &map_entry, 
  16311                             indexf[eindex], spad_offset + cosq/4);
  16312         /* coverity[overrun-local : FALSE] */
  16313         soc_mem_field32_set(unit, mem, &map_entry, self[eindex], !!pfc);
  16314         BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem,
  16315                             MEM_BLOCK_ALL, map_entry_index, &map_entry));
  16316     return BCM_E_NONE;
  16317 }
  16318 
  16319 /*
  16320  * Function:
  16321  *     _bcm_td2_clear_fc_status_to_node
  16322  * Purpose:
  16323  *     Clear MMU_INTFI_PIPE_FC_MAP_TBL setting of a port.
  16324  * Parameters:
  16325  *     unit       - (IN) unit number
  16326  *     port       - (IN) port number
  16327  * Returns:
  16328  *     BCM_E_XXX
  16329  */
  16330 STATIC int
  16331 _bcm_td2_clear_fc_status_to_node(int unit, int port)
  16332 {
  16333     uint32 map_entry[SOC_MAX_MEM_WORDS], i_value, s_value;
  16334     static const soc_field_t self[] = {
  16335         SEL0f, SEL1f, SEL2f, SEL3f
  16336     };
  16337     static const soc_field_t indexf[] = {
  16338         INDEX0f, INDEX1f, INDEX2f, INDEX3f
  16339     };
  16340     static const soc_mem_t memx[] = {
  16341         MMU_INTFI_XPIPE_FC_MAP_TBL0m,
  16342         MMU_INTFI_XPIPE_FC_MAP_TBL1m,
  16343         MMU_INTFI_XPIPE_FC_MAP_TBL2m
  16344     };
  16345     static const soc_mem_t memy[] = {
  16346         MMU_INTFI_YPIPE_FC_MAP_TBL0m,
  16347         MMU_INTFI_YPIPE_FC_MAP_TBL1m,
  16348         MMU_INTFI_YPIPE_FC_MAP_TBL2m
  16349     };
  16350     static const soc_mem_t *mem;
  16351     int base, table, index, count, field;
  16352     int mmu_port, phy_port, update;
  16353     bcm_port_t local_port;
  16354     soc_info_t *si;
  16355 
  16356     BCM_IF_ERROR_RETURN
  16357         (_bcm_td2_cosq_localport_resolve(unit, port, &local_port));
  16358 
  16359     si = &SOC_INFO(unit);
  16360     phy_port = si->port_l2p_mapping[local_port];
  16361     mmu_port = si->port_p2m_mapping[phy_port];
  16362     mem = (mmu_port < SOC_TD2_NUM_MMU_PORTS_PER_PIPE)? memx : memy;
  16363 
  16364     base = mmu_port * 4;
  16365     for (table = 0; table < COUNTOF(memx); table++) {
  16366         count = soc_mem_index_count(unit, mem[table]);
  16367         for (index = 0; index < count; index++) {
  16368             update = 0;
  16369             SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem[table],
  16370                 MEM_BLOCK_ALL, index, &map_entry));
  16371             for (field = 0; field < COUNTOF(indexf); field++) {
  16372                 s_value = soc_mem_field32_get(unit, mem[table],
  16373                                               &map_entry, self[field]);
  16374                 i_value = soc_mem_field32_get(unit, mem[table],
  16375                                               &map_entry, indexf[field]);
  16376                 if (s_value && (i_value >= base) && (i_value < (base + 4))) {
  16377                     soc_mem_field32_set(unit, mem[table],
  16378                                         &map_entry, self[field], 0);
  16379                     soc_mem_field32_set(unit, mem[table],
  16380                                         &map_entry, indexf[field], 0);
  16381                     update = 1;
  16382                 }
  16383             }
  16384             if (update) {
  16385                 SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem[table],
  16386                     MEM_BLOCK_ALL, index, &map_entry));
  16387             }
  16388         }
  16389     }
  16390 
  16391     return BCM_E_NONE;
  16392 }
  16393 
  16394 /*
  16395  * Function:
  16396  *     _bcm_td2_fc_status_map_gport
  16397  * Purpose:
  16398  *     Set mapping in FC_MAP_TBL for gport, and update cos_bmp with gport cosq.
  16399  * Parameters:
  16400  *     unit       - (IN) unit number
  16401  *     port       - (IN) port number
  16402  *     gport      - (IN) gport to be mapped
  16403  *     fct        - (IN) FC type 
  16404  *     cos_map    - (OUT) hw_cosq of gport
  16405  * Returns:
  16406  *     BCM_E_XXX
  16407  * Note:
  16408  *     This function assumes gport has been validated by
  16409  *     "_bcm_td2_fc_map_gport_check".
  16410  */
  16411 STATIC int
  16412 _bcm_td2_fc_status_map_gport(int unit, int port, 
  16413                 bcm_gport_t gport, _bcm_td2_fc_type_t fct, uint32 *cos_bmp)
  16414 {
  16415     int hw_index, hw_index1;
  16416     int hw_cosq, hw_cosq1;
  16417     int id, lvl;
  16418     int pipe, mmu_port, phy_port;
  16419     bcm_port_t local_port, resolved_port;
  16420     _bcm_td2_cosq_node_t *node;
  16421     _bcm_td2_pipe_resources_t *res;
  16422     _bcm_td2_cosq_port_info_t *port_info;
  16423     soc_info_t *si;
  16424     _bcm_td2_mmu_info_t *mmu_info;
  16425 
  16426     BCM_IF_ERROR_RETURN
  16427         (_bcm_td2_cosq_localport_resolve(unit, port, &local_port));
  16428 
  16429     si = &SOC_INFO(unit);
  16430     phy_port = si->port_l2p_mapping[local_port];
  16431     mmu_port = si->port_p2m_mapping[phy_port];
  16432 
  16433     mmu_info = _bcm_td2_mmu_info[unit];
  16434     port_info = &mmu_info->port_info[local_port];
  16435     pipe = _BCM_TD2_PORT_TO_PIPE(unit, local_port);
  16436     res = _BCM_TD2_PRESOURCES(mmu_info, pipe);
  16437     
  16438     hw_index = hw_index1 = -1;
  16439     hw_cosq = hw_cosq1 = -1;
  16440     if (BCM_GPORT_IS_SET(gport)) {
  16441         BCM_IF_ERROR_RETURN(_bcm_td2_cosq_node_get(unit, gport, 
  16442                             0, NULL, &resolved_port, &id, &node));
  16443         hw_index = node->hw_index;
  16444         hw_cosq = node->hw_cosq;
  16445         lvl = node->level;
  16446     } else {
  16447         if (_bcm_td2_cosq_port_has_ets(unit, local_port)) {
  16448             hw_cosq = gport;
  16449             node = &res->p_queue_node[port_info->uc_base + hw_cosq];
  16450             hw_index = node->hw_index;
  16451             
  16452             node = &res->p_mc_queue_node[port_info->mc_base + hw_cosq];
  16453             hw_index1 = node->hw_index;
  16454             hw_cosq1 = hw_cosq;
  16455             lvl = SOC_TD2_NODE_LVL_L2;
  16456         } else {
  16457             lvl = SOC_TD2_NODE_LVL_L1;
  16458             /* gport[] represnts the physical Cos value */
  16459             hw_cosq = gport;
  16460             BCM_IF_ERROR_RETURN(soc_td2_sched_hw_index_get(unit, local_port, 
  16461             SOC_TD2_NODE_LVL_L1, hw_cosq, &hw_index));
  16462         }
  16463     }
  16464 
  16465     BCM_IF_ERROR_RETURN(
  16466         _bcm_td2_map_fc_status_to_node(unit, local_port, fct,
  16467                                        mmu_port*4, hw_cosq, hw_index, lvl));
  16468     if (cos_bmp != NULL) {
  16469         *cos_bmp |= 1 << hw_cosq;
  16470     }
  16471     
  16472     if (hw_cosq1 >= 0) {
  16473         BCM_IF_ERROR_RETURN(
  16474             _bcm_td2_map_fc_status_to_node(unit, local_port, fct,
  16475                                        mmu_port*4, hw_cosq1, hw_index1, lvl));
  16476         if (cos_bmp != NULL) {
  16477             *cos_bmp |= 1 << hw_cosq1;
  16478         }
  16479     }
  16480 
  16481     return BCM_E_NONE;
  16482 }
  16483 
  16484 /*
  16485  * Function:
  16486  *     bcm_td2_cosq_default_llfc_profile_attach
  16487  * Purpose:
  16488  *     Add default entries for PRIO2COS_PROFILE register profile
  16489  * Parameters:
  16490  *     unit    - (IN) unit number
  16491  *     port    - (IN) port number
  16492  * Returns:
  16493  *     BCM_E_XXX
  16494  */
  16495 int
  16496 bcm_td2_cosq_default_llfc_profile_attach(int unit, int port)
  16497 {
  16498     soc_reg_t   reg;
  16499     soc_info_t *si;
  16500     bcm_port_t local_port;
  16501     int mmu_port, phy_port;
  16502     uint32 profile_index;
  16503     uint64 tmp, rval, index_map;
  16504     uint64 rval64s[16], *prval64s[1];
  16505     static const soc_reg_t llfc_cfgr[] = {
  16506         PORT_PFC_CFG0r, PORT_PFC_CFG1r, PORT_PFC_CFG2r, PORT_PFC_CFG3r
  16507     };
  16508 
  16509     BCM_IF_ERROR_RETURN(
  16510         _bcm_td2_cosq_localport_resolve(unit, port, &local_port));
  16511 
  16512     si = &SOC_INFO(unit);
  16513     phy_port = si->port_l2p_mapping[local_port];
  16514     mmu_port = si->port_p2m_mapping[phy_port];
  16515     reg = llfc_cfgr[mmu_port/32];
  16516 
  16517     /* Add default entries for PRIO2COS_PROFILE register profile */
  16518     sal_memset(rval64s, 0, sizeof(rval64s));
  16519     prval64s[0] = rval64s;
  16520 
  16521     BCM_IF_ERROR_RETURN
  16522             (soc_profile_reg_add(unit, _bcm_td2_llfc_profile[unit],
  16523                                  prval64s, 16, &profile_index));
  16524 
  16525     BCM_IF_ERROR_RETURN(soc_reg64_get(unit, reg, 0, 0, &rval));
  16526     index_map = soc_reg64_field_get(unit, reg, rval, PROFILE_INDEXf);
  16527 
  16528     COMPILER_64_SET(tmp, 0, 3);
  16529     COMPILER_64_SHL(tmp, (mmu_port % 32) * 2);
  16530     COMPILER_64_NOT(tmp);
  16531     COMPILER_64_AND(index_map, tmp);
  16532     COMPILER_64_SET(tmp, 0, profile_index/16);
  16533     COMPILER_64_SHL(tmp, (mmu_port % 32) * 2);
  16534     COMPILER_64_OR(index_map, tmp);
  16535 
  16536     soc_reg64_field_set(unit, reg, &rval, PROFILE_INDEXf,
  16537                         index_map);
  16538 
  16539     BCM_IF_ERROR_RETURN(soc_reg64_set(unit, reg, 0, 0, rval));
  16540 
  16541     return BCM_E_NONE;
  16542 }
  16543 
  16544 /*
  16545  * Function:
  16546  *     bcm_td2_cosq_llfc_profile_detach
  16547  * Purpose:
  16548  *     Delete old entries for PRIO2COS_PROFILE register profile
  16549  * Parameters:
  16550  *     unit    - (IN) unit number
  16551  *     port    - (IN) port number
  16552  * Returns:
  16553  *     BCM_E_XXX
  16554  */
  16555 int
  16556 bcm_td2_cosq_llfc_profile_detach(int unit, int port)
  16557 {
  16558     soc_reg_t   reg;
  16559     bcm_port_t local_port;
  16560     int mmu_port, phy_port;
  16561     uint32 old_profile_index;
  16562     uint32 tmp32;
  16563     uint64 rval, index_map;
  16564     soc_info_t *si;
  16565     static const soc_reg_t llfc_cfgr[] = {
  16566         PORT_PFC_CFG0r, PORT_PFC_CFG1r, PORT_PFC_CFG2r, PORT_PFC_CFG3r
  16567     };
  16568 
  16569     BCM_IF_ERROR_RETURN(
  16570         _bcm_td2_cosq_localport_resolve(unit, port, &local_port));
  16571 
  16572     si = &SOC_INFO(unit);
  16573     phy_port = si->port_l2p_mapping[local_port];
  16574     mmu_port = si->port_p2m_mapping[phy_port];
  16575 
  16576     reg = llfc_cfgr[mmu_port/32];
  16577     BCM_IF_ERROR_RETURN(soc_reg64_get(unit, reg, 0, 0, &rval));
  16578 
  16579     index_map = soc_reg64_field_get(unit, reg, rval, PROFILE_INDEXf);
  16580     COMPILER_64_SHR(index_map, ((mmu_port % 32) * 2));
  16581     COMPILER_64_TO_32_LO(tmp32, index_map);
  16582     old_profile_index = (tmp32 & 3)*16;
  16583 
  16584     BCM_IF_ERROR_RETURN
  16585         (soc_profile_reg_delete(unit, _bcm_td2_llfc_profile[unit],
  16586                                 old_profile_index));
  16587 
  16588     return BCM_E_NONE;
  16589 }
  16590 
  16591 /*
  16592  * Function:
  16593  *     _bcm_td2_port_pfc_profile_set
  16594  * Purpose:
  16595  *     Set PFC mapping profile for port. Updates PRIO2COS_PROFILE & PORT_PFC_CFG.
  16596  * Parameters:
  16597  *     unit       - (IN) unit number
  16598  *     port       - (IN) port number
  16599  *     op         - (IN) operation type
  16600  *     entry_cnt  - (IN) count of bmp 
  16601  *     pfc_class  - (IN) class list
  16602  *     cos_bmp    - (IN) bmp list
  16603  * Returns:
  16604  *     BCM_E_XXX
  16605  */
  16606 STATIC int
  16607 _bcm_td2_port_pfc_profile_set(int unit, int port, _bcm_cosq_op_t op,
  16608                               int entry_cnt, int *pfc_class, uint32 *cos_bmp)
  16609 {
  16610     soc_reg_t   reg;
  16611     bcm_port_t local_port;
  16612     int rv, entry, cur_class;
  16613     int mmu_port, phy_port, p_mmu_port;
  16614     uint16 dev_id;
  16615     uint8  rev_id;
  16616     uint32 profile_index, old_profile_index;
  16617     uint32 fval, tmp32, cur_bmp;
  16618     uint64 rval64[16], tmp, *rval64s[1], rval, index_map;
  16619     soc_info_t *si;
  16620     static const soc_reg_t llfc_cfgr[] = {
  16621         PORT_PFC_CFG0r, PORT_PFC_CFG1r, PORT_PFC_CFG2r, PORT_PFC_CFG3r
  16622     };
  16623 
  16624     if (pfc_class == NULL) {
  16625         return BCM_E_PARAM;
  16626     }
  16627     if (cos_bmp == NULL) {
  16628         return BCM_E_PARAM;
  16629     }
  16630     if ((entry_cnt < 0 ) || (entry_cnt > _BCM_TD2_NUM_PFC_CLASS)) {
  16631         return BCM_E_PARAM;
  16632     }
  16633     
  16634     BCM_IF_ERROR_RETURN(
  16635         _bcm_td2_cosq_localport_resolve(unit, port, &local_port));
  16636 
  16637     si = &SOC_INFO(unit);
  16638     phy_port = si->port_l2p_mapping[local_port];
  16639     mmu_port = si->port_p2m_mapping[phy_port];
  16640     
  16641     reg = llfc_cfgr[mmu_port/32];
  16642     rval64s[0] = rval64;
  16643     BCM_IF_ERROR_RETURN(soc_reg64_get(unit, reg, 0, 0, &rval));
  16644     
  16645     index_map = soc_reg64_field_get(unit, reg, rval, PROFILE_INDEXf);
  16646     COMPILER_64_SHR(index_map, ((mmu_port % 32) * 2));
  16647     COMPILER_64_TO_32_LO(tmp32, index_map);
  16648     old_profile_index = (tmp32 & 3)*16;
  16649     BCM_IF_ERROR_RETURN
  16650         (soc_profile_reg_get(unit, _bcm_td2_llfc_profile[unit],
  16651                              old_profile_index, 16, rval64s));
  16652 
  16653     for (entry = 0; entry < entry_cnt; entry++) {
  16654         cur_class = pfc_class[entry];
  16655         cur_bmp = cos_bmp[entry];
  16656         /* A0 & A1: odd HSP port bitmap needs shifting 2 bits to left. */
  16657         if (IS_TD2_HSP_PORT(unit, local_port)) {
  16658             soc_cm_get_id_otp(unit, &dev_id, &rev_id);
  16659             p_mmu_port = _BCM_TD2_ROOT_SCHED_INDEX(unit, mmu_port);
  16660             if ((dev_id == BCM56850_DEVICE_ID) &&
  16661                 (rev_id <= BCM56850_A1_REV_ID) &&
  16662                 (p_mmu_port % 2)) {
  16663                 cur_bmp = cur_bmp << 2;
  16664             }
  16665         }
  16666         if (op == _BCM_COSQ_OP_SET) {
  16667             soc_reg64_field32_set(unit, PRIO2COS_PROFILEr, &rval64[cur_class],
  16668                                   COS_BMPf, cur_bmp);
  16669         } else {
  16670             if (cur_bmp != 0) {
  16671                 fval = soc_reg64_field32_get(unit, PRIO2COS_PROFILEr,
  16672                                              rval64[cur_class], COS_BMPf);
  16673                 if (op == _BCM_COSQ_OP_ADD) {
  16674                     fval |= cur_bmp;
  16675                 } else { /* _BCM_COSQ_OP_DELETE */
  16676                     fval &= ~cur_bmp;
  16677                 }
  16678                 soc_reg64_field32_set(unit, PRIO2COS_PROFILEr,
  16679                                       &rval64[cur_class], COS_BMPf, fval);
  16680             }
  16681         }
  16682     }
  16683     
  16684     BCM_IF_ERROR_RETURN
  16685         (soc_profile_reg_delete(unit, _bcm_td2_llfc_profile[unit],
  16686                                 old_profile_index));
  16687 
  16688     rv = soc_profile_reg_add(unit, _bcm_td2_llfc_profile[unit], rval64s,
  16689                              16, &profile_index);
  16690     if (SOC_FAILURE(rv)) {
  16691         BCM_IF_ERROR_RETURN
  16692             (soc_profile_reg_reference(unit, _bcm_td2_llfc_profile[unit],
  16693                                        old_profile_index, 16));
  16694         return rv;
  16695     }
  16696 
  16697 
  16698     index_map = soc_reg64_field_get(unit, reg, rval, PROFILE_INDEXf);
  16699 
  16700     COMPILER_64_SET(tmp, 0, 3);
  16701     COMPILER_64_SHL(tmp, (mmu_port % 32) * 2);
  16702     COMPILER_64_NOT(tmp);
  16703     COMPILER_64_AND(index_map, tmp);
  16704     COMPILER_64_SET(tmp, 0, profile_index/16);
  16705     COMPILER_64_SHL(tmp, (mmu_port % 32) * 2);
  16706     COMPILER_64_OR(index_map, tmp);
  16707     
  16708     soc_reg64_field_set(unit, reg, &rval, PROFILE_INDEXf,
  16709                         index_map);
  16710 
  16711     BCM_IF_ERROR_RETURN(soc_reg64_set(unit, reg, 0, 0, rval));
  16712 
  16713     return BCM_E_NONE;
  16714 }
  16715 
  16716 /*
  16717  * Function:
  16718  *     _bcm_td2_fc_map_gport_check
  16719  * Purpose:
  16720  *     Validate if a gport can be mapped to a port's PFC/FC status.
  16721  * Parameters:
  16722  *     unit             - (IN) unit number
  16723  *     port             - (IN) port number
  16724  *     gport            - (IN) gport that will be mapped
  16725  * Returns:
  16726  *     BCM_E_XXX
  16727  */
  16728 STATIC int
  16729 _bcm_td2_fc_map_gport_check(int unit,
  16730     bcm_gport_t port,
  16731     bcm_gport_t gport)
  16732 {
  16733     bcm_port_t local_port = -1, resolved_port;
  16734     int hw_cosq, pipe;
  16735     _bcm_td2_pipe_resources_t *res;
  16736     _bcm_td2_cosq_port_info_t *port_info;
  16737     _bcm_td2_mmu_info_t *mmu_info;
  16738     _bcm_td2_cosq_node_t *node;
  16739 
  16740     BCM_IF_ERROR_RETURN
  16741         (_bcm_td2_cosq_localport_resolve(unit, port, &local_port));
  16742 
  16743     if (local_port < 0) {
  16744         return BCM_E_PORT;
  16745     }
  16746 
  16747     mmu_info = _bcm_td2_mmu_info[unit];
  16748     port_info = &mmu_info->port_info[local_port];
  16749     pipe = _BCM_TD2_PORT_TO_PIPE(unit, local_port);
  16750     res = _BCM_TD2_PRESOURCES(mmu_info, pipe);
  16751     
  16752     hw_cosq = -1;
  16753     if (BCM_GPORT_IS_SET(gport)) {
  16754         BCM_IF_ERROR_RETURN(_bcm_td2_cosq_node_get(unit, gport, 
  16755                             0, NULL, &resolved_port, NULL, &node));
  16756         if (!((node->type == _BCM_TD2_NODE_UCAST) ||
  16757               (node->type == _BCM_TD2_NODE_MCAST) ||
  16758               (node->type == _BCM_TD2_NODE_SCHEDULER))) {
  16759             return BCM_E_PARAM;
  16760         }
  16761         if ((node->type == _BCM_TD2_NODE_SCHEDULER) &&
  16762             (node->node_align_value != _BCM_TD2_START_INDEX_ALIGN_PFC) &&
  16763             (node->level != SOC_TD2_NODE_LVL_ROOT)) {
  16764             LOG_ERROR(BSL_LS_BCM_COSQ,
  16765                       (BSL_META_U(unit,
  16766                       "Gport without BCM_COSQ_GPORT_SCHEDULER_PFC_ALIGN!\n")));
  16767             return BCM_E_PARAM;
  16768         }
  16769         if (resolved_port != local_port) {
  16770             return BCM_E_PARAM;
  16771         }
  16772         hw_cosq = node->hw_cosq;
  16773     } else {
  16774         hw_cosq = gport;
  16775         if (_bcm_td2_cosq_port_has_ets(unit, local_port)) {
  16776             node = &res->p_queue_node[port_info->uc_base + hw_cosq];
  16777             if ((!node->in_use) || (node->attached_to_input == -1)) {
  16778                 return BCM_E_PARAM;
  16779             }
  16780             node = &res->p_mc_queue_node[port_info->mc_base + hw_cosq];
  16781             if ((!node->in_use) || (node->attached_to_input == -1)) {
  16782                 return BCM_E_PARAM;
  16783             }
  16784         }
  16785     }
  16786     if ((hw_cosq < 0) || (hw_cosq >= _TD2_NUM_INTERNAL_PRI)) {
  16787         return BCM_E_PARAM;
  16788     }
  16789 
  16790     return BCM_E_NONE;
  16791 }
  16792 
  16793 /*
  16794  * Function:
  16795  *     _bcm_td2_pfc_class_mapping_check
  16796  * Purpose:
  16797  *     Validate param of bcm_cosq_pfc_class_mapping_t.
  16798  * Parameters:
  16799  *     unit             - (IN) unit number
  16800  *     port             - (IN) port number
  16801  *     array_count      - (IN) count of mapping array
  16802  *     mapping_array    - (IN) mapping array list
  16803  * Returns:
  16804  *     BCM_E_XXX
  16805  */
  16806 STATIC int
  16807 _bcm_td2_pfc_class_mapping_check(int unit,
  16808     bcm_gport_t port,
  16809     int array_count,
  16810     bcm_cosq_pfc_class_mapping_t *mapping_array)
  16811 {
  16812     int count, index, cur_class;
  16813     bcm_gport_t cur_gport = 0;
  16814 
  16815     if (mapping_array == NULL) {
  16816         return BCM_E_PARAM;
  16817     }
  16818     
  16819     for (count = 0; count < array_count; count++) {
  16820         cur_class = mapping_array[count].class_id;
  16821         if ((cur_class < 0) || (cur_class >= _BCM_TD2_NUM_PFC_CLASS)) {
  16822             return BCM_E_PARAM;
  16823         }
  16824         
  16825         for (index = 0; index < BCM_COSQ_PFC_GPORT_COUNT; index++) {
  16826             cur_gport = mapping_array[count].gport_list[index];
  16827             if (cur_gport == BCM_GPORT_INVALID) {
  16828                 break;
  16829             }
  16830             BCM_IF_ERROR_RETURN(_bcm_td2_fc_map_gport_check(unit,
  16831                                                             port, cur_gport));
  16832         }
  16833     }
  16834 
  16835     return BCM_E_NONE;
  16836 }
  16837 
  16838 int
  16839 bcm_td2_cosq_port_pfc_op(int unit, bcm_port_t port,
  16840                          bcm_switch_control_t sctype, _bcm_cosq_op_t op,
  16841                          bcm_gport_t *gport, int gport_count)
  16842 {
  16843     int type, class = -1, index;
  16844     uint32 cos_bmp;
  16845     _bcm_td2_fc_type_t fct;
  16846 
  16847     if (gport_count < 0) {
  16848         return BCM_E_PARAM;
  16849     }
  16850     for (index = 0; index < gport_count; index++) {
  16851         BCM_IF_ERROR_RETURN(_bcm_td2_fc_map_gport_check(unit,
  16852                                                         port, gport[index]));
  16853     }
  16854 
  16855     BCM_IF_ERROR_RETURN(_bcm_td2_cosq_pfc_class_resolve(sctype, &type, &class));
  16856 
  16857     cos_bmp = 0;
  16858     fct = (op == _BCM_COSQ_OP_CLEAR)? 0 : _BCM_TD2_COSQ_FC_PFC;
  16859     for (index = 0; index < gport_count; index++) {
  16860         BCM_IF_ERROR_RETURN(
  16861             _bcm_td2_fc_status_map_gport(unit, port, gport[index],
  16862                                          fct, &cos_bmp));
  16863     }
  16864 
  16865     if (op == _BCM_COSQ_OP_CLEAR) {
  16866         cos_bmp = (1 << _TD2_NUM_INTERNAL_PRI) - 1;
  16867     }
  16868 
  16869     BCM_IF_ERROR_RETURN(_bcm_td2_port_pfc_profile_set(unit, port, op,
  16870                                                       1, &class, &cos_bmp));
  16871     
  16872     return BCM_E_NONE;
  16873 }
  16874 
  16875 int
  16876 bcm_td2_cosq_port_pfc_get(int unit, bcm_port_t port,
  16877                          bcm_switch_control_t sctype,
  16878                          bcm_gport_t *gport, int gport_count,
  16879                          int *actual_gport_count)
  16880 {
  16881     _bcm_td2_cosq_node_t *node;
  16882     bcm_port_t local_port;
  16883     int type = -1, class = -1, hw_cosq, count = 0;
  16884     uint32 profile_index;
  16885     uint64 rval64[16], *rval64s[1], rval, index_map;
  16886     uint32 tmp32, bmp, bmp_len;
  16887     _bcm_td2_mmu_info_t *mmu_info;
  16888     int phy_port, mmu_port, p_mmu_port;
  16889     soc_info_t *si;
  16890     soc_reg_t   reg;
  16891     _bcm_td2_pipe_resources_t *res;
  16892     _bcm_td2_cosq_port_info_t *port_info;
  16893     static const soc_reg_t llfc_cfgr[] = {
  16894         PORT_PFC_CFG0r, PORT_PFC_CFG1r, PORT_PFC_CFG2r, PORT_PFC_CFG3r
  16895     };
  16896     static const soc_field_t self[] = {
  16897         SEL0f, SEL1f, SEL2f, SEL3f
  16898     };
  16899     int j, finished = 0, hw_index, pipe, eindex;
  16900     soc_mem_t mem;
  16901     uint32 map_entry[SOC_MAX_MEM_WORDS];
  16902     uint16 dev_id;
  16903     uint8 rev_id;
  16904 
  16905     if (IS_CPU_PORT(unit, port)) {
  16906         return BCM_E_PORT;
  16907     }
  16908 
  16909     if ((gport == NULL) && (gport_count > 0)) {
  16910         return BCM_E_PARAM;
  16911     }
  16912     
  16913     if (actual_gport_count == NULL) {
  16914         return BCM_E_PARAM;
  16915     }
  16916 
  16917     BCM_IF_ERROR_RETURN
  16918         (_bcm_td2_cosq_localport_resolve(unit, port, &local_port));
  16919 
  16920     BCM_IF_ERROR_RETURN(_bcm_td2_cosq_pfc_class_resolve(sctype, &type, &class));
  16921 
  16922     si = &SOC_INFO(unit);
  16923     mmu_info = _bcm_td2_mmu_info[unit];
  16924     pipe = _BCM_TD2_PORT_TO_PIPE(unit, local_port);
  16925     res = _BCM_TD2_PRESOURCES(mmu_info, pipe);
  16926     phy_port = si->port_l2p_mapping[local_port];
  16927     mmu_port = si->port_p2m_mapping[phy_port];
  16928     port_info = &mmu_info->port_info[local_port];
  16929 
  16930     rval64s[0] = rval64;
  16931     reg = llfc_cfgr[mmu_port/32];
  16932     BCM_IF_ERROR_RETURN(soc_reg64_get(unit, reg, REG_PORT_ANY, 0, &rval));
  16933 
  16934     index_map = soc_reg64_field_get(unit, reg, rval, PROFILE_INDEXf);
  16935     COMPILER_64_SHR(index_map, ((mmu_port % 32) * 2));
  16936     COMPILER_64_TO_32_LO(tmp32, index_map);
  16937     profile_index = (tmp32 & 3)*16;
  16938 
  16939     BCM_IF_ERROR_RETURN
  16940         (soc_profile_reg_get(unit, _bcm_td2_llfc_profile[unit],
  16941                              profile_index, 16, rval64s));
  16942 
  16943     bmp = soc_reg64_field32_get(unit, PRIO2COS_PROFILEr, rval64[class],
  16944                                 COS_BMPf);
  16945     bmp_len = soc_reg_field_length(unit, PRIO2COS_PROFILEr, COS_BMPf);
  16946     /* A0 & A1: odd HSP port bitmap has been shifted 2 bits to left. */
  16947     if (IS_TD2_HSP_PORT(unit, port)) {
  16948         soc_cm_get_id_otp(unit, &dev_id, &rev_id);
  16949         p_mmu_port = _BCM_TD2_ROOT_SCHED_INDEX(unit, mmu_port);
  16950         if ((dev_id == BCM56850_DEVICE_ID) &&
  16951             (rev_id <= BCM56850_A1_REV_ID) &&
  16952             (p_mmu_port % 2)) {
  16953             bmp = bmp >> 2;
  16954         }
  16955     }
  16956     for (hw_cosq = 0; hw_cosq < bmp_len; hw_cosq++) {
  16957         if (!(bmp & (1 << hw_cosq))) {
  16958             continue;
  16959         }
  16960         if (_bcm_td2_cosq_port_has_ets(unit, local_port)) {
  16961             for (j = _BCM_TD2_NUM_PORT_SCHEDULERS; 
  16962                  j < _BCM_TD2_NUM_TOTAL_SCHEDULERS; j++) {
  16963                 node = &mmu_info->sched_node[j];
  16964                 if ((!node->in_use) || (node->local_port != local_port) ||
  16965                     (node->hw_cosq != hw_cosq)) {
  16966                     continue;
  16967                 }
  16968 
  16969                 if (node->level == SOC_TD2_NODE_LVL_L0) {
  16970                     mem = (pipe == _TD2_XPIPE) ? MMU_INTFI_XPIPE_FC_MAP_TBL0m :
  16971                                                  MMU_INTFI_YPIPE_FC_MAP_TBL0m;
  16972                 } else if (node->level == SOC_TD2_NODE_LVL_L1) {
  16973                     mem = (pipe == _TD2_XPIPE) ? MMU_INTFI_XPIPE_FC_MAP_TBL1m :
  16974                                                  MMU_INTFI_YPIPE_FC_MAP_TBL1m;
  16975                 } else {
  16976                     continue;
  16977                 }
  16978                 BCM_IF_ERROR_RETURN(_bcm_td2_pfc_map_index_resolve(unit, port,
  16979                     node->hw_index, node->level, &hw_index, &eindex));
  16980                 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, 
  16981                     MEM_BLOCK_ALL, hw_index, &map_entry));
  16982 
  16983                 if (soc_mem_field32_get(unit, mem, &map_entry, self[eindex])) {
  16984                     if (gport_count > 0) {
  16985                         gport[count] = node->gport;
  16986                     }
  16987                     count++;
  16988                     if ((count == gport_count) && (gport_count > 0)) {
  16989                         finished = 1;
  16990                         break;
  16991                     }
  16992                 }
  16993             }
  16994 
  16995             for (j = port_info->uc_base; 
  16996                  (finished == 0) && (j < port_info->uc_limit); j++) {
  16997                 node = &res->p_queue_node[j];
  16998                 if ((!node->in_use) || (node->local_port != local_port)) {
  16999                     continue;
  17000                 }
  17001                 if (node->hw_cosq != hw_cosq) {
  17002                     continue;
  17003                 }
  17004                 mem = (pipe == _TD2_XPIPE) ? MMU_INTFI_XPIPE_FC_MAP_TBL2m :
  17005                                              MMU_INTFI_YPIPE_FC_MAP_TBL2m;
  17006                 BCM_IF_ERROR_RETURN(_bcm_td2_pfc_map_index_resolve(unit, port,
  17007                     node->hw_index, node->level, &hw_index, &eindex));
  17008                 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, 
  17009                     MEM_BLOCK_ALL, hw_index, &map_entry));
  17010 
  17011                 if (soc_mem_field32_get(unit, mem, &map_entry, self[eindex])) {
  17012                     if (gport_count > 0) {
  17013                         gport[count] = node->gport;
  17014                     }
  17015                     count++;
  17016                     if ((count == gport_count) && (gport_count > 0)) {
  17017                         finished = 1;
  17018                         break;
  17019                     }
  17020                 }
  17021             }
  17022             for (j = port_info->mc_base; 
  17023                  (finished == 0) && (j < port_info->mc_limit); j++) {
  17024                 node = &res->p_mc_queue_node[j];
  17025                 if ((!node->in_use) || (node->local_port != local_port)) {
  17026                     continue;
  17027                 }
  17028                 if (node->hw_cosq != hw_cosq) {
  17029                     continue;
  17030                 }
  17031                 mem = (pipe == _TD2_XPIPE) ? MMU_INTFI_XPIPE_FC_MAP_TBL2m :
  17032                                              MMU_INTFI_YPIPE_FC_MAP_TBL2m;
  17033                 BCM_IF_ERROR_RETURN(_bcm_td2_pfc_map_index_resolve(unit, port,
  17034                     node->hw_index, node->level, &hw_index, &eindex));
  17035                 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, 
  17036                     MEM_BLOCK_ALL, hw_index, &map_entry));
  17037                 /* coverity[overrun-local : FALSE] */
  17038                 if (soc_mem_field32_get(unit, mem, &map_entry, self[eindex])) {
  17039                     if (gport_count > 0) {
  17040                         gport[count] = node->gport;
  17041                     }
  17042                     count++;
  17043                     if ((count == gport_count) && (gport_count > 0)) {
  17044                         break;
  17045                     }
  17046                 }
  17047             }
  17048         } else {
  17049             if (gport_count > 0) {
  17050                 gport[count] = hw_cosq;
  17051             }
  17052             count++;
  17053         }
  17054         if ((count == gport_count) && (gport_count > 0)) {
  17055             break;
  17056         }
  17057     }
  17058 
  17059     if (count == 0) {
  17060         return BCM_E_NOT_FOUND;
  17061     }
  17062     *actual_gport_count = count;
  17063     return BCM_E_NONE;
  17064 }
  17065 
  17066 /*
  17067  * Function:
  17068  *     bcm_td2_cosq_pfc_class_mapping_set
  17069  * Purpose:
  17070  *     Set PFC mapping for port. PFC class is mapped to cosq or scheduler node gports.
  17071  * Parameters:
  17072  *     unit             - (IN) unit number
  17073  *     port             - (IN) port number
  17074  *     array_count      - (IN) count of mapping
  17075  *     mapping_array    - (IN) mappings 
  17076  * Returns:
  17077  *     BCM_E_XXX
  17078  */
  17079 int
  17080 bcm_td2_cosq_pfc_class_mapping_set(int unit,
  17081     bcm_gport_t port,
  17082     int array_count,
  17083     bcm_cosq_pfc_class_mapping_t *mapping_array)
  17084 {
  17085     int index, count;
  17086     int cur_class = 0, pfc_class[_BCM_TD2_NUM_PFC_CLASS];
  17087     bcm_gport_t cur_gport = 0;
  17088     uint32 cos_bmp[_BCM_TD2_NUM_PFC_CLASS];
  17089 
  17090 
  17091     if ((array_count < 0) || (array_count > _BCM_TD2_NUM_PFC_CLASS)) {
  17092         return BCM_E_PARAM;
  17093     }
  17094     if (mapping_array == NULL) {
  17095         return BCM_E_PARAM;
  17096     }
  17097     BCM_IF_ERROR_RETURN(_bcm_td2_pfc_class_mapping_check(unit, port,
  17098         array_count, mapping_array));
  17099 
  17100     (void) _bcm_td2_clear_fc_status_to_node(unit, port);
  17101     sal_memset(cos_bmp, 0, sizeof(cos_bmp));
  17102     for (count = 0; count < array_count; count++) {
  17103         cur_class = mapping_array[count].class_id;
  17104         
  17105         for (index = 0; index < BCM_COSQ_PFC_GPORT_COUNT; index++) {
  17106             cur_gport = mapping_array[count].gport_list[index];
  17107             if (cur_gport == BCM_GPORT_INVALID) {
  17108                 break;
  17109             }
  17110             
  17111             BCM_IF_ERROR_RETURN(_bcm_td2_fc_status_map_gport(unit, port, 
  17112                 cur_gport, _BCM_TD2_COSQ_FC_PFC, &cos_bmp[cur_class]));
  17113         }
  17114     }
  17115 
  17116     for (index = 0; index < _BCM_TD2_NUM_PFC_CLASS; index++) {
  17117         pfc_class[index] = index;
  17118     }
  17119     BCM_IF_ERROR_RETURN(_bcm_td2_port_pfc_profile_set(unit, port,
  17120         _BCM_COSQ_OP_SET, _BCM_TD2_NUM_PFC_CLASS, pfc_class, cos_bmp));
  17121     
  17122     return BCM_E_NONE;
  17123 }
  17124 
  17125 /*
  17126  * Function:
  17127  *     bcm_td2_cosq_pfc_class_mapping_get
  17128  * Purpose:
  17129  *     Get PFC mapping for port.
  17130  *     Retrieves cosq or scheduler node gports
  17131  *     associated to PFC classes.
  17132  * Parameters:
  17133  *     unit             - (IN) unit number
  17134  *     port             - (IN) port number
  17135  *     array_max        - (IN) max retrieve count
  17136  *     mapping_array    - (OUT) mappings
  17137  *     array_count      - (OUT) retrieved mapping count
  17138  * Returns:
  17139  *     BCM_E_XXX
  17140  */
  17141 int
  17142 bcm_td2_cosq_pfc_class_mapping_get(int unit,
  17143     bcm_gport_t port,
  17144     int array_max,
  17145     bcm_cosq_pfc_class_mapping_t *mapping_array,
  17146     int *array_count)
  17147 {
  17148     int rv = 0;
  17149     int cur_class = 0;
  17150     int actual_gport_count, class_count = 0;
  17151     bcm_switch_control_t sc[] = { bcmSwitchPFCClass0Queue,
  17152                                   bcmSwitchPFCClass1Queue,
  17153                                   bcmSwitchPFCClass2Queue,
  17154                                   bcmSwitchPFCClass3Queue,
  17155                                   bcmSwitchPFCClass4Queue,
  17156                                   bcmSwitchPFCClass5Queue,
  17157                                   bcmSwitchPFCClass6Queue,
  17158                                   bcmSwitchPFCClass7Queue
  17159                                 };
  17160 
  17161     if ((mapping_array == NULL) && (array_max > 0)) {
  17162         return BCM_E_PARAM;
  17163     }
  17164     if (array_count == NULL) {
  17165         return BCM_E_PARAM;
  17166     }
  17167 
  17168     for (cur_class = 0; cur_class < _BCM_TD2_NUM_PFC_CLASS; cur_class++) {
  17169         actual_gport_count = 0;
  17170         if (array_max > 0) {
  17171             rv = bcm_td2_cosq_port_pfc_get(unit, port, sc[cur_class],
  17172                         mapping_array[class_count].gport_list,
  17173                         BCM_COSQ_PFC_GPORT_COUNT, &actual_gport_count);
  17174         } else {
  17175             rv = bcm_td2_cosq_port_pfc_get(unit, port, sc[cur_class],
  17176                          NULL, -1, &actual_gport_count);
  17177         }
  17178         if (rv == BCM_E_NONE) {
  17179             if (array_max > 0) {
  17180                 mapping_array[class_count].class_id = cur_class;
  17181                 if (actual_gport_count < BCM_COSQ_PFC_GPORT_COUNT) {
  17182                     mapping_array[class_count].gport_list[actual_gport_count] = 
  17183                                                              BCM_GPORT_INVALID;
  17184                 }
  17185             }
  17186             class_count++;
  17187         } else if (rv != BCM_E_NOT_FOUND) {
  17188             return rv;
  17189         }
  17190 
  17191         if ((class_count == array_max) && (array_max > 0)) {
  17192             break;
  17193         }
  17194     }
  17195 
  17196     *array_count = class_count;
  17197     if (class_count == 0) {
  17198         return BCM_E_NOT_FOUND;
  17199     }
  17200     
  17201     return BCM_E_NONE;
  17202 }
  17203 
  17204 /*
  17205  * Function:
  17206  *      bcm_td2_port_priority_group_mapping_set
  17207  * Purpose:
  17208  *      Assign a Priority Group for the input priority.
  17209  * Parameters:
  17210  *      unit       - (IN) device id.
  17211  *      gport     - (IN) generic port.
  17212  *      prio       - (IN) input priority.
  17213  *      priority_group  - (IN) PG ID that the input priority mapped to.
  17214  * Returns:
  17215  *      BCM_E_XXX
  17216  */
  17217 int
  17218 bcm_td2_port_priority_group_mapping_set(int unit, bcm_gport_t gport,
  17219                                         int prio, int priority_group)
  17220 {
  17221     bcm_port_t port;
  17222     uint32 value;
  17223     int field_count;
  17224     soc_field_t fields_0[]={PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf,
  17225                             PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf};
  17226     soc_field_t fields_1[]={PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf,
  17227                             PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf};
  17228 
  17229     if (!soc_feature(unit, soc_feature_priority_flow_control)) {
  17230         return BCM_E_UNAVAIL;
  17231     }
  17232     /* PFC : 0-7, SAFC : 0-15. Taking the larger range for comparison */
  17233     if ((prio < TD2_SAFC_INPUT_PRIORITY_MIN) || 
  17234         (prio > TD2_SAFC_INPUT_PRIORITY_MAX)) {
  17235         return BCM_E_PARAM;
  17236     }
  17237 
  17238     if ((priority_group < TD2_PRIOROTY_GROUP_ID_MIN) || 
  17239         (priority_group > TD2_PRIOROTY_GROUP_ID_MAX)) {
  17240         return BCM_E_PARAM;
  17241     }
  17242 
  17243     BCM_IF_ERROR_RETURN(_bcm_td2_cosq_localport_resolve(unit, gport, &port));
  17244     if (!SOC_PORT_VALID(unit, port)) {
  17245         return BCM_E_PORT;
  17246     }
  17247     field_count = COUNTOF(fields_0);
  17248     if (prio < field_count) {
  17249         /* input priority 0~7 */
  17250         BCM_IF_ERROR_RETURN(READ_THDI_PORT_PRI_GRP0r(unit, port, &value));
  17251         soc_reg_field_set(unit, THDI_PORT_PRI_GRP0r, &value, 
  17252                           fields_0[prio], priority_group);
  17253         BCM_IF_ERROR_RETURN(WRITE_THDI_PORT_PRI_GRP0r(unit, port, value));
  17254     } else {
  17255         /* input priority 8~15 */
  17256         BCM_IF_ERROR_RETURN(READ_THDI_PORT_PRI_GRP1r(unit, port, &value));
  17257         soc_reg_field_set(unit, THDI_PORT_PRI_GRP1r, &value, 
  17258                           fields_1[prio - field_count], priority_group);
  17259         BCM_IF_ERROR_RETURN(WRITE_THDI_PORT_PRI_GRP1r(unit, port, value));
  17260     }
  17261 
  17262     return BCM_E_NONE;
  17263 }
  17264 
  17265 /*
  17266  * Function:
  17267  *      bcm_td2_port_priority_group_mapping_get
  17268  * Purpose:
  17269  *      Get the assigned Priority Group ID of the input priority.
  17270  * Parameters:
  17271  *      unit       - (IN) device id.
  17272  *      gport     - (IN) generic port.
  17273  *      prio       - (IN) input priority.
  17274  *      priority_group  - (OUT) PG ID that the input priority mapped to.
  17275  * Returns:
  17276  *      BCM_E_XXX
  17277  */
  17278 int
  17279 bcm_td2_port_priority_group_mapping_get(int unit, bcm_gport_t gport,
  17280                                         int prio, int *priority_group)
  17281 {
  17282     bcm_port_t port;
  17283     uint32 value;
  17284     int field_count;
  17285     soc_field_t fields_0[]={PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf,
  17286                             PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf};
  17287     soc_field_t fields_1[]={PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf,
  17288                             PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf};
  17289 
  17290     if (!soc_feature(unit, soc_feature_priority_flow_control)) {
  17291         return BCM_E_UNAVAIL;
  17292     }
  17293     if (priority_group == NULL) {
  17294         return BCM_E_PARAM;
  17295     }
  17296     /* PFC : 0-7, SAFC : 0-15. Taking the larger range for comparison */
  17297     if ((prio < TD2_SAFC_INPUT_PRIORITY_MIN) || 
  17298         (prio > TD2_SAFC_INPUT_PRIORITY_MAX)) {
  17299         return BCM_E_PARAM;
  17300     }
  17301 
  17302     BCM_IF_ERROR_RETURN(_bcm_td2_cosq_localport_resolve(unit, gport, &port));
  17303     if (!SOC_PORT_VALID(unit, port)) {
  17304         return BCM_E_PORT;
  17305     }
  17306     field_count = COUNTOF(fields_0);
  17307     if (prio < field_count) {
  17308         /* input priority 0~7 */
  17309         BCM_IF_ERROR_RETURN(READ_THDI_PORT_PRI_GRP0r(unit, port, &value));
  17310         *priority_group = soc_reg_field_get(unit, THDI_PORT_PRI_GRP0r,
  17311                                             value, fields_0[prio]);
  17312     } else {
  17313         /* input priority 8~15 */
  17314         BCM_IF_ERROR_RETURN(READ_THDI_PORT_PRI_GRP1r(unit, port, &value));
  17315         *priority_group = soc_reg_field_get(unit, THDI_PORT_PRI_GRP1r,
  17316                                             value, 
  17317                                             fields_1[prio - field_count]);
  17318     }
  17319 
  17320     return BCM_E_NONE;
  17321 }
  17322 
  17323 /*
  17324  * Function:
  17325  *      bcm_td2_port_priority_group_config_set
  17326  * Purpose:
  17327  *      Set the port priority group configuration.
  17328  * Parameters:
  17329  *      unit       - (IN) device id.
  17330  *      gport     - (IN) generic port.
  17331  *      priority_group - (IN) priority group id.
  17332  *      prigrp_config  - (IN) structure describes port PG configuration.
  17333  * Returns:
  17334  *      BCM_E_XXX
  17335  */
  17336 int
  17337 bcm_td2_port_priority_group_config_set(int unit, bcm_gport_t gport,
  17338     int priority_group, bcm_port_priority_group_config_t *prigrp_config)
  17339 {
  17340     bcm_port_t port;
  17341     uint32 rval, pri_bmp;
  17342 
  17343     if (!soc_feature(unit, soc_feature_priority_flow_control)) {
  17344         return BCM_E_UNAVAIL;
  17345     }
  17346     if ((priority_group < TD2_PRIOROTY_GROUP_ID_MIN) || 
  17347         (priority_group > TD2_PRIOROTY_GROUP_ID_MAX)) {
  17348         return BCM_E_PARAM;
  17349     }
  17350     if (prigrp_config == NULL) {
  17351         return BCM_E_PARAM;
  17352     }
  17353     if (prigrp_config->shared_pool_xoff_enable ||
  17354         prigrp_config->shared_pool_discard_enable ||
  17355         prigrp_config->priority_enable_vector_mask) {
  17356         return BCM_E_UNAVAIL;
  17357     }
  17358     BCM_IF_ERROR_RETURN(_bcm_td2_cosq_localport_resolve(unit, gport, &port));
  17359     if (!SOC_PORT_VALID(unit, port)) {
  17360         return BCM_E_PORT;
  17361     }
  17362 
  17363     SOC_IF_ERROR_RETURN(READ_THDI_INPUT_PORT_XON_ENABLESr(unit, port, &rval));
  17364     pri_bmp = soc_reg_field_get(unit, THDI_INPUT_PORT_XON_ENABLESr, rval,
  17365                                 PORT_PRI_XON_ENABLEf);
  17366 
  17367     if (prigrp_config->pfc_transmit_enable) {
  17368         pri_bmp |= (1 << priority_group);
  17369     } else {
  17370         pri_bmp &= ~(1 << priority_group);
  17371     }
  17372     /* To cover higher 8 PFC classes that have no corresponding PG. */
  17373     if ((pri_bmp & 0xff) == 0) {
  17374         pri_bmp = 0;
  17375     }
  17376     
  17377     BCM_IF_ERROR_RETURN(_bcm_sc_tr_port_pfc_tx_set(unit, port, pri_bmp));
  17378 
  17379     return BCM_E_NONE;
  17380 }
  17381 
  17382 /*
  17383  * Function:
  17384  *      bcm_td2_port_priority_group_config_get
  17385  * Purpose:
  17386  *      Get the port priority group configuration.
  17387  * Parameters:
  17388  *      unit       - (IN) device id.
  17389  *      gport     - (IN) generic port.
  17390  *      priority_group - (IN) priority group id.
  17391  *      prigrp_config  - (OUT) structure describes port PG configuration.
  17392  * Returns:
  17393  *      BCM_E_XXX
  17394  */
  17395 int
  17396 bcm_td2_port_priority_group_config_get(int unit, bcm_gport_t gport,
  17397     int priority_group, bcm_port_priority_group_config_t *prigrp_config)
  17398 {
  17399     bcm_port_t port;
  17400     uint32 rval, pri_bmp;
  17401 
  17402     if (!soc_feature(unit, soc_feature_priority_flow_control)) {
  17403         return BCM_E_UNAVAIL;
  17404     }
  17405     if ((priority_group < TD2_PRIOROTY_GROUP_ID_MIN) || 
  17406         (priority_group > TD2_PRIOROTY_GROUP_ID_MAX)) {
  17407         return BCM_E_PARAM;
  17408     }
  17409     if (prigrp_config == NULL) {
  17410         return BCM_E_PARAM;
  17411     }
  17412 
  17413     BCM_IF_ERROR_RETURN(_bcm_td2_cosq_localport_resolve(unit, gport, &port));
  17414     if (!SOC_PORT_VALID(unit, port)) {
  17415         return BCM_E_PORT;
  17416     }
  17417 
  17418     SOC_IF_ERROR_RETURN(READ_THDI_INPUT_PORT_XON_ENABLESr(unit, port, &rval));
  17419     pri_bmp = soc_reg_field_get(unit, THDI_INPUT_PORT_XON_ENABLESr, rval,
  17420                                 PORT_PRI_XON_ENABLEf);
  17421     if (pri_bmp & (1U << priority_group)) {
  17422         prigrp_config->pfc_transmit_enable = 1;
  17423     } else {
  17424         prigrp_config->pfc_transmit_enable = 0;
  17425     }
  17426 
  17427     return BCM_E_NONE;
  17428 }
  17429 
  17430 /*
  17431  * Function:
  17432  *      bcm_td2p_cosq_subport_flow_control_set
  17433  * Purpose:
  17434  *      Set a port or node (L0, L1, L2) to flow control when
  17435  *      a CoE control frame is received on a subtended port.
  17436  * Parameters:
  17437  *      unit            - (IN) Unit number.
  17438  *      subport            - (IN) Subtended port
  17439  *      sched_port      - (IN) Node (Port, L0, L1, L2) to flow control 
  17440  * Returns:
  17441  *      BCM_E_xxx
  17442  * Notes:
  17443  */
  17444 int
  17445 bcm_td2p_cosq_subport_flow_control_set(
  17446     int unit, 
  17447     bcm_gport_t subport, 
  17448     bcm_gport_t sched_port)
  17449 {
  17450 #ifdef BCM_HGPROXY_COE_SUPPORT 
  17451     uint16 coe_fc_index, row, column;
  17452     uint32 rval;
  17453     bcm_gport_t subport_id, resolved_port;
  17454     _bcm_td2_cosq_node_t *node; 
  17455     int hw_index, rv, pipe;
  17456     soc_td2_node_lvl_e level;
  17457     subport_tag_sgpp_map_entry_t entry;
  17458     bcm_port_t phy_port, mmu_port;
  17459     soc_info_t *si;
  17460     _bcm_td2_fc_type_t fct;
  17461 
  17462     /* Find subport id from port to index into SUBPORT_TAG_SGPP_MAP */
  17463     BCM_IF_ERROR_RETURN(_bcmi_coe_subport_tcam_idx_get(unit, subport, &subport_id));
  17464 
  17465     /* From sched_port, need to find if it's port, L0, L1, or L2 */
  17466     BCM_IF_ERROR_RETURN(_bcm_td2_cosq_node_get(unit, sched_port, 0, NULL, NULL, NULL, &node));
  17467 
  17468     /* Port, L0, L1, or L2 from node */
  17469     level = node->level;
  17470 
  17471     /* index into L0, L1, or L2 */
  17472     hw_index = node->hw_index;
  17473 
  17474     /* Get the port associated with the passed in gport */
  17475     BCM_IF_ERROR_RETURN
  17476         (_bcm_td2_cosq_localport_resolve(unit, sched_port, &resolved_port));
  17477     if (resolved_port < 0) {
  17478         return BCM_E_PORT;
  17479     }
  17480 
  17481     pipe = _BCM_TD2_PORT_TO_PIPE(unit, resolved_port);
  17482 
  17483 
  17484     si = &SOC_INFO(unit);
  17485 
  17486     /* Getting MMU port.  Used to disable cut through for it at the end as well as
  17487        to index into MMU_INTFI_PORT_COEFC_TB if we're setting flow control for port */
  17488     phy_port = si->port_l2p_mapping[resolved_port];
  17489     mmu_port = si->port_p2m_mapping[phy_port];
  17490 
  17491     if (IS_TD2_HSP_PORT( unit, resolved_port )) {
  17492         /* SC/QM L1/L2 nodes do not support FC.
  17493         * Hence, L1/L2 indices 8, 9, 18, 19 ... should not be configured
  17494         * for FC.
  17495         * similarly the last L0 of the HSP port does not support flow control
  17496         */
  17497         if (level == SOC_TD2_NODE_LVL_L0) {
  17498             if ((hw_index % 5) > 3) {
  17499                  return BCM_E_PARAM;
  17500             }
  17501             column = hw_index % 5;
  17502         } else  { 
  17503             if ((hw_index % 10) > 7) {
  17504                  return BCM_E_PARAM;
  17505             }
  17506             column = ((hw_index % 10) % 4);
  17507         }
  17508     } else { 
  17509          column = hw_index % 4 ;
  17510     }
  17511 
  17512     /* Checking valid reference to address for each entry of FC_STATE tables per
  17513        MMU - INTFI Table 1-9.  We also need to offset the hw_index properly per pipe.
  17514        We are dividing the FC STATE tables in half with the X Pipe taking the lower half
  17515        and the Y Pipe taking the upper half, hence 134/2, 256/2, 1024/2. */
  17516     switch(level) {
  17517         case SOC_TD2_NODE_LVL_ROOT:
  17518             /* At the port level we have to do it a bit different since it's indexing into
  17519                MMU_INTFI_PORT_COEFC_TB, which is a 128 entry x 1 bit table with each entry signifying
  17520                an MMU Port, so we need to use the MMU Port number as the row. Column we don't care
  17521                for. */
  17522             row = mmu_port;
  17523             column = 0;
  17524 
  17525             if ( (row > 52 && row < 64) || (row > 116) ) {
  17526                 return BCM_E_PARAM;
  17527             }
  17528             break;
  17529         case SOC_TD2_NODE_LVL_L0:
  17530             if (IS_TD2_HSP_PORT( unit, resolved_port )) {
  17531                 /* The last L0 does not support  FC and so each index in fc_st_tbl represents
  17532                  * 5 l0 nodes instead of 4 the last 1 is masked by the hardware
  17533                  */ 
  17534                 row = hw_index / 5;
  17535             } else { 
  17536                 row = hw_index / 4; 
  17537             }
  17538 
  17539             if(pipe == _TD2_YPIPE) {
  17540                 row += 134/2;
  17541             }
  17542             if (row > 133) {
  17543                 return BCM_E_PARAM;
  17544             }
  17545             break;
  17546     case SOC_TD2_NODE_LVL_L1:
  17547 
  17548         if (IS_TD2_HSP_PORT( unit, resolved_port )) {
  17549             /* FC not supported on last two L1/L2 nodes The hardware internally adjusts the value 
  17550              * say index 24 which for non hsp port will result in index 6 will result in 5 for HSP
  17551              */   
  17552             row = mmu_port * 2 + 
  17553               (((hw_index % 10) >= 4)? 1 : 0);
  17554         } else { 
  17555             row = hw_index / 4; 
  17556         }
  17557             if(pipe == _TD2_YPIPE) {
  17558                 row += 512/2;
  17559             }
  17560             if (row > 511) {
  17561                 return BCM_E_PARAM;
  17562             }
  17563 
  17564             break;
  17565         case SOC_TD2_NODE_LVL_L2:
  17566             if (IS_TD2_HSP_PORT( unit, resolved_port )) {
  17567                /* FC not supported on last two L1/L2 nodes The hardware internally adjusts the value 
  17568                 * say index 24 which for non hsp port will result in index 6 will result in 5 for HSP
  17569                 */   
  17570                 row = mmu_port * 2 + 
  17571                       (((hw_index % 10) >= 4)? 1 : 0);
  17572             } else { 
  17573                row = hw_index / 4; 
  17574             }
  17575             if(pipe == _TD2_YPIPE) {
  17576                 row += 1024/2;
  17577             }
  17578             if (row > 1023) {
  17579                 return BCM_E_PARAM;
  17580             }
  17581             break;
  17582         default:
  17583             return BCM_E_PARAM;
  17584 
  17585     }
  17586 
  17587     /* Column is only 4 bits wide */
  17588     if (column > 3) {
  17589         return BCM_E_PARAM;
  17590     }
  17591 
  17592     /* set coe_fc_index for us to program into the register */
  17593     coe_fc_index = (row << 5) |     /* row bits 15:5 */
  17594                    (column << 2) |  /* column bits 4:2 */
  17595                    (level);         /* type bits 1:0 */
  17596 
  17597     /* Program SUBPORT_TAG_SGPP_MAP with the subport as the index and
  17598        COE_FC_INDEX as the data */
  17599     rv = READ_SUBPORT_TAG_SGPP_MAPm(unit,
  17600              MEM_BLOCK_ANY, subport_id, &entry);
  17601     if (SOC_SUCCESS(rv)) {
  17602         soc_SUBPORT_TAG_SGPP_MAPm_field32_set(unit,
  17603                                              (uint32 *)&entry, COE_FC_INDEXf, coe_fc_index);
  17604     }
  17605     WRITE_SUBPORT_TAG_SGPP_MAPm(unit, MEM_BLOCK_ANY, subport_id, &entry);
  17606 
  17607     /* Program FC Map Table to select FC State Table (vs PFC State Table) for the node */
  17608     fct = _BCM_TD2_COSQ_FC_E2ECC;
  17609 
  17610     /* To pass the proper FC STATE Table entries, we're modifying the FC MAP Table, one of its
  17611        4 indexes, with the appropriate row in the FC STATE Table. FC MAP Table at index 0
  17612        will handle the rows 0-3 of FC STATE Table, at index 1 will handle rows 4-7 of the
  17613        FC STATE Table, and so on.
  17614      
  17615        resolved_port is passed so that the function will know which pipe to use (X or Y).
  17616        fct will select FC STATE Table on the mux so that PFC STATE Table won't be selected.
  17617        row is passed in this first time so that a proper row index for the FC STATE Table will be selected.
  17618        node->hw_index is passed in because the proper FC MAP Table index will be calculated.
  17619        node->level is passed in so that the function will know with FC MAP Table (L0, L1, L2) to use.
  17620        */
  17621     if(level != SOC_TD2_NODE_LVL_ROOT) {
  17622         BCM_IF_ERROR_RETURN(_bcm_td2_map_fc_status_to_node(unit, resolved_port, fct, row, 
  17623                                                            0, node->hw_index, node->level));
  17624     }
  17625 
  17626     /* Disable Cut-Through for the port specified or L0/L1/L2 node associated with it */
  17627     BCM_IF_ERROR_RETURN(READ_ASF_PORT_CFGr(unit, mmu_port, &rval));
  17628     soc_reg_field_set(unit, ASF_PORT_CFGr, &rval, UC_ASF_ENABLEf, 0);
  17629     soc_reg_field_set(unit, ASF_PORT_CFGr, &rval, MC_ASF_ENABLEf, 0);
  17630     BCM_IF_ERROR_RETURN(WRITE_ASF_PORT_CFGr(unit, mmu_port, rval));
  17631 
  17632     return BCM_E_NONE;
  17633 #else
  17634     return BCM_E_UNAVAIL;
  17635 #endif /* BCM_HGPROXY_COE_SUPPORT */
  17636 }
  17637 
  17638 int
  17639 bcm_td2p_cosq_subport_flow_control_get(
  17640     int unit, 
  17641     bcm_gport_t subport, 
  17642     bcm_gport_t * sched_port)
  17643 {
  17644 #ifdef BCM_HGPROXY_COE_SUPPORT 
  17645     int row, column, level, hw_index, i, temp_pipe, coe_fc_index = 0;
  17646     int pipe = _TD2_XPIPE;
  17647     bcm_gport_t subport_id;
  17648     _bcm_td2_cosq_node_t * node;
  17649     _bcm_td2_mmu_info_t * mmu_info;
  17650     subport_tag_sgpp_map_entry_t entry;
  17651 
  17652     int resolved_port = 0;
  17653     int mmu_port = 0;
  17654     int phy_port = 0;
  17655     soc_info_t *si;
  17656 
  17657     /* Find subport id from port to index into SUBPORT_TAG_SGPP_MAP */
  17658     BCM_IF_ERROR_RETURN(_bcmi_coe_subport_tcam_idx_get(unit, subport, &subport_id));
  17659 
  17660     BCM_IF_ERROR_RETURN(
  17661     _bcmi_coe_subport_physical_port_get(unit, subport, &resolved_port));
  17662     si = &SOC_INFO(unit);
  17663     /* Getting MMU port.  Used to disable cut through for it at the end as well as
  17664        to index into MMU_INTFI_PORT_COEFC_TB if we're setting flow control for port */
  17665     phy_port = si->port_l2p_mapping[resolved_port];
  17666     mmu_port = si->port_p2m_mapping[phy_port];
  17667 
  17668     BCM_IF_ERROR_RETURN(READ_SUBPORT_TAG_SGPP_MAPm(unit,
  17669              MEM_BLOCK_ANY, subport_id, &entry));
  17670     coe_fc_index = soc_SUBPORT_TAG_SGPP_MAPm_field32_get(unit,
  17671                                              (uint32 *)&entry, COE_FC_INDEXf);
  17672 
  17673     level = coe_fc_index & 0x3;
  17674     column = (coe_fc_index >> 2) & 0x7;
  17675     row = (coe_fc_index >> 5);
  17676 
  17677     /* Get the proper row to calculate hw_index because this could be in either pipe.
  17678        We are dividing the FC STATE tables in half with the X Pipe taking the lower half
  17679        and the Y Pipe taking the upper half, hence 134/2, 256/2, 1024/2. */
  17680     switch(level) {
  17681         case SOC_TD2_NODE_LVL_ROOT:
  17682             if(row >= 64) {
  17683                 row -= 64;
  17684                 pipe = _TD2_YPIPE;
  17685             }
  17686 
  17687             hw_index = row;
  17688 
  17689             break;
  17690         case SOC_TD2_NODE_LVL_L0:
  17691             if(row >= 134/2) {
  17692                 pipe = _TD2_YPIPE;
  17693                 row -= 134/2;
  17694             }
  17695             if (row > 133) {
  17696                 return BCM_E_PARAM;
  17697             }
  17698 
  17699             if (IS_TD2_HSP_PORT( unit, resolved_port )) {
  17700                 hw_index = row * 5 + column ; 
  17701             } else {  
  17702                 hw_index = row * 4 + column ; 
  17703             }
  17704 
  17705             break;
  17706         case SOC_TD2_NODE_LVL_L1:
  17707             if(row >= 512/2) {
  17708                 pipe = _TD2_YPIPE;
  17709                 row -= 512/2;
  17710             }
  17711             if (row > 511) {
  17712                 return BCM_E_PARAM;
  17713             }        
  17714             /* FC not supported on last two L1/L2 nodes The hardware internally adjusts the value 
  17715             * say index 24 which for non hsp port will result in index 6 will result in 5 for HSP
  17716             */   
  17717             if (IS_TD2_HSP_PORT( unit, resolved_port )) {
  17718                 hw_index = ((mmu_port%_TD2_PORTS_PER_PIPE) * 10) + ((row % 2)? 4: 0) + column ; 
  17719             } else {  
  17720                 hw_index = row * 4 + column ; 
  17721             }
  17722             break;
  17723         case SOC_TD2_NODE_LVL_L2:
  17724             if(row >= 1024/2) {
  17725                 pipe = _TD2_YPIPE;
  17726                 row -= 1024/2;
  17727             }
  17728             if (row > 1023) {
  17729                 return BCM_E_PARAM;
  17730             }
  17731 
  17732             /* FC not supported on last two L1/L2 nodes The hardware internally adjusts the value 
  17733             * say index 24 which for non hsp port will result in index 6 will result in 5 for HSP
  17734             */   
  17735             if (IS_TD2_HSP_PORT( unit, resolved_port )) {
  17736                 hw_index = ((mmu_port%_TD2_PORTS_PER_PIPE) * 10) + ((row % 2)? 4: 0) + column ; 
  17737             } else {  
  17738                 hw_index = row * 4 + column ; 
  17739             }
  17740             break;
  17741         /*
  17742          * COVERITY
  17743          *
  17744          * This default is unreachable but needed for some compiler. 
  17745          */ 
  17746         /* coverity[dead_error_begin] */
  17747         default:
  17748             return BCM_E_PARAM;
  17749 
  17750     }
  17751 
  17752     mmu_info = _bcm_td2_mmu_info[unit];
  17753 
  17754     if (!mmu_info) {
  17755         return BCM_E_INIT;
  17756     }
  17757 
  17758     /* Fetch the node based upon level and hw_index */
  17759     switch(level) {
  17760         /* port, L0, and L1 are all scheduling nodes */
  17761         case SOC_TD2_NODE_LVL_ROOT:
  17762         case SOC_TD2_NODE_LVL_L0:
  17763         case SOC_TD2_NODE_LVL_L1:
  17764             for(i = 0; i < _BCM_TD2_NUM_TOTAL_SCHEDULERS; i++) {
  17765                 node = &mmu_info->sched_node[i];
  17766                 if(node->level == level) {
  17767                     if(node->hw_index == hw_index) {
  17768                         /* if the hw_index matches, check the pipe. Must pass in local port */
  17769                         temp_pipe = _BCM_TD2_PORT_TO_PIPE(unit, node->local_port);
  17770 
  17771                         /* if the pipe matches too, we've found the associated gport */
  17772                         if(pipe == temp_pipe) {
  17773                             *sched_port = node->gport;
  17774                             return BCM_E_NONE;
  17775                         }
  17776                     }
  17777                 }
  17778             }
  17779             break;
  17780         case SOC_TD2_NODE_LVL_L2:
  17781             for(i = 0; i < _BCM_TD2_NUM_L2_UC_LEAVES; i++) {
  17782                 node = &mmu_info->queue_node[i];
  17783                 if(node->level == level) {
  17784                     if(node->hw_index == hw_index) {
  17785                         /* if the hw_index matches, check the pipe */
  17786                         temp_pipe = _BCM_TD2_PORT_TO_PIPE(unit, node->local_port);
  17787 
  17788                         /* if the pipe matches too, we've found the associated gport */
  17789                         if(pipe == temp_pipe) {
  17790                             *sched_port = node->gport;
  17791                             return BCM_E_NONE;
  17792                         }
  17793                     }
  17794                 }
  17795             }
  17796             break;
  17797         /* Intentional process */
  17798         /* coverity[dead_error_begin] */
  17799         default:
  17800             return BCM_E_PARAM;
  17801 
  17802     }
  17803 
  17804     /* not found */
  17805     return BCM_E_PARAM;
  17806 #else
  17807     return BCM_E_UNAVAIL;
  17808 #endif /* BCM_HGPROXY_COE_SUPPORT */
  17809 }
  17810 
  17811 int
  17812 bcm_td2_cosq_drop_status_enable_set(int unit, bcm_port_t port, int enable)
  17813 {
  17814     _bcm_td2_mmu_info_t *mmu_info;
  17815     soc_info_t *si;
  17816     int count, idx, pipe, base;
  17817     uint32 rval;
  17818     _bcm_td2_cosq_node_t *node;
  17819     _bcm_td2_pipe_resources_t *res;
  17820     soc_mem_t mem;
  17821     soc_reg_t reg;
  17822     uint32 entry[SOC_MAX_MEM_WORDS];
  17823     uint32 e2ecc_ds_config;
  17824 #ifdef BCM_TRIDENT2PLUS_SUPPORT
  17825     uint32 qgroup_valid;
  17826 #endif
  17827 
  17828     if ((mmu_info = _bcm_td2_mmu_info[unit]) == NULL) {
  17829         return BCM_E_INIT;
  17830     }
  17831 
  17832     si = &SOC_INFO(unit);
  17833 
  17834     mem = SOC_TD2_PMEM(unit, port, MMU_THDM_DB_QUEUE_CONFIG_0m, 
  17835                                    MMU_THDM_DB_QUEUE_CONFIG_1m);
  17836     reg = SOC_TD2_PREG(unit, port, MMU_THDM_DB_QUEUE_E2E_DS_EN_0r,
  17837                                    MMU_THDM_DB_QUEUE_E2E_DS_EN_1r);
  17838 
  17839 
  17840     count = si->port_num_cosq[port];
  17841     SOC_IF_ERROR_RETURN(_bcm_td2_cosq_index_resolve
  17842                  (unit, port, 0, _BCM_TD2_COSQ_INDEX_STYLE_MCAST_QUEUE,
  17843                   &port, &base, NULL));
  17844 
  17845     for (idx = 0; idx < count; idx++) {
  17846         if ( SOC_REG_IS_VALID(unit, reg) ) {
  17847             SOC_IF_ERROR_RETURN (
  17848                 soc_reg_field32_modify(unit, reg, port,
  17849                                        Q_COS_E2E_DS_ENf, enable));
  17850         } else {
  17851             SOC_IF_ERROR_RETURN (
  17852                 soc_mem_field32_modify(unit, mem, base + idx - 1480,
  17853                                         Q_E2E_DS_ENf, enable));
  17854         }
  17855     }
  17856 
  17857     mem = SOC_TD2_PMEM(unit, port, MMU_THDU_XPIPE_Q_TO_QGRP_MAPm, 
  17858                                    MMU_THDU_YPIPE_Q_TO_QGRP_MAPm);
  17859     SOC_IF_ERROR_RETURN(_bcm_td2_cosq_index_resolve
  17860                  (unit, port, 0, _BCM_TD2_COSQ_INDEX_STYLE_UCAST_QUEUE,
  17861                   &port, &base, NULL));
  17862     count = si->port_num_uc_cosq[port];
  17863     for (idx = 0; idx < count; idx++) {
  17864         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, base + idx, entry));
  17865         soc_mem_field32_set(unit, mem, entry, Q_E2E_DS_EN_CELLf, !!enable);
  17866         e2ecc_ds_config = 1;
  17867 #ifdef BCM_TRIDENT2PLUS_SUPPORT
  17868         if (SOC_IS_TRIDENT2PLUS(unit)) {
  17869             if (IS_TD2_HSP_PORT(unit, port)) {
  17870                 qgroup_valid = soc_mem_field32_get(unit, mem, entry, QGROUP_VALIDf);
  17871                 if ((idx < 8) && (qgroup_valid == 0)) {
  17872                     /* If HSP port does not use qgroup for its lower 8 queues */
  17873                     e2ecc_ds_config = 2;
  17874                 }
  17875             }
  17876         }
  17877 #endif
  17878         soc_mem_field32_set(unit, mem, entry, Q_E2ECC_DS_CONFIGf, e2ecc_ds_config);
  17879         BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, base + idx, entry));
  17880     }
  17881 
  17882     pipe = _BCM_TD2_PORT_TO_PIPE(unit, port);
  17883     res = _BCM_TD2_PRESOURCES(mmu_info, pipe);
  17884     for (idx = res->num_base_queues; idx < _BCM_TD2_NUM_L2_UC_LEAVES; idx++) {
  17885         node = &res->p_queue_node[idx];
  17886         if ((node->in_use == TRUE) && (node->local_port == port)) {
  17887             BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, node->hw_index, entry));
  17888             soc_mem_field32_set(unit, mem, entry, Q_E2E_DS_EN_CELLf, !!enable);
  17889             soc_mem_field32_set(unit, mem, entry, Q_E2ECC_DS_CONFIGf, 1);
  17890             BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, node->hw_index, entry));
  17891         }
  17892     }
  17893 
  17894     BCM_IF_ERROR_RETURN(READ_OP_THDU_CONFIGr(unit, &rval));
  17895     soc_reg_field_set(unit, OP_THDU_CONFIGr, &rval, EARLY_E2E_SELECTf,
  17896                       enable ? 1 : 0);
  17897     BCM_IF_ERROR_RETURN(WRITE_OP_THDU_CONFIGr(unit, rval));
  17898 
  17899     return BCM_E_NONE;
  17900 }
  17901 
  17902 STATIC int
  17903 _bcm_td2_voq_min_hw_index(int unit, bcm_port_t port, 
  17904                           bcm_module_t modid, 
  17905                           bcm_port_t remote_port,
  17906                           int *q_offset)
  17907 {
  17908     int i, hw_index_base = -1, pipe;
  17909     _bcm_td2_cosq_node_t *node;
  17910     _bcm_td2_pipe_resources_t *res;
  17911     _bcm_td2_mmu_info_t *mmu_info;
  17912     int qmin, qmax;
  17913 
  17914     mmu_info = _bcm_td2_mmu_info[unit];
  17915     pipe = _BCM_TD2_PORT_TO_PIPE(unit, port);
  17916     res = _BCM_TD2_PRESOURCES(mmu_info, pipe);
  17917     qmin = res->num_base_queues + (pipe * _BCM_TD2_NUM_L2_UC_LEAVES_PER_PIPE);
  17918     qmax = (pipe + 1) * _BCM_TD2_NUM_L2_UC_LEAVES_PER_PIPE;
  17919  
  17920     for (i = qmin; i < qmax; i++) {
  17921         node = &res->p_queue_node[i];
  17922         if ((node->in_use == FALSE) || (node->hw_index == -1)) {
  17923             continue;
  17924         }
  17925 
  17926         if (((modid == -1) ? 1 : (node->remote_modid == modid)) && 
  17927             (node->remote_port == remote_port) &&
  17928             ((port == -1) ? 1 : (port == node->local_port))) {
  17929             if (hw_index_base == -1) {
  17930                 hw_index_base = node->hw_index;
  17931                 break;
  17932             }
  17933         }
  17934     }
  17935    
  17936     if (hw_index_base != -1) {
  17937         *q_offset = hw_index_base & ~7;
  17938         return BCM_E_NONE;
  17939     }
  17940 
  17941     return BCM_E_NOT_FOUND;
  17942 }
  17943 
  17944 STATIC int
  17945 _bcm_td2_voq_base_node_get(int unit, bcm_port_t port, 
  17946         int modid,
  17947         _bcm_td2_cosq_node_t **base_node)
  17948 {
  17949     int i,  pipe;
  17950     _bcm_td2_pipe_resources_t *res;
  17951     _bcm_td2_mmu_info_t *mmu_info;
  17952     _bcm_td2_cosq_node_t *node;
  17953     int qmin, qmax;
  17954 
  17955     mmu_info = _bcm_td2_mmu_info[unit];
  17956     pipe = _BCM_TD2_PORT_TO_PIPE(unit, port);
  17957     for (pipe = _TD2_XPIPE ; pipe < _TD2_NUM_PIPES ; pipe++) { 
  17958         res = _BCM_TD2_PRESOURCES(mmu_info, pipe);
  17959         qmin = res->num_base_queues + (pipe * _BCM_TD2_NUM_L2_UC_LEAVES_PER_PIPE);
  17960         qmax = (pipe + 1) * _BCM_TD2_NUM_L2_UC_LEAVES_PER_PIPE;
  17961         for ( i  = qmin; 
  17962                 i < qmax ; i++) {
  17963             node = &res->p_queue_node[i];
  17964             if ((node->in_use == FALSE) || (node->hw_index == -1)) {
  17965                 continue;
  17966             }
  17967             if (node->remote_modid == modid) {
  17968                 *base_node = node ;
  17969                 break;
  17970             }
  17971         }
  17972     }
  17973     return BCM_E_NONE;
  17974 }
  17975 
  17976 STATIC int
  17977 _bcm_td2_voq_next_base_node_get(int unit, bcm_port_t port, 
  17978         int modid,
  17979         _bcm_td2_cosq_node_t **base_node)
  17980 {
  17981     int i,  pipe, qmin, qmax;
  17982     _bcm_td2_pipe_resources_t *res;
  17983     _bcm_td2_mmu_info_t *mmu_info;
  17984     _bcm_td2_cosq_node_t *node;
  17985     int found = FALSE;
  17986 
  17987     mmu_info = _bcm_td2_mmu_info[unit];
  17988     pipe = _BCM_TD2_PORT_TO_PIPE(unit, port);
  17989     for (pipe = _TD2_XPIPE ; pipe < _TD2_NUM_PIPES ; pipe++) { 
  17990         res = _BCM_TD2_PRESOURCES(mmu_info, pipe);
  17991         qmin = res->num_base_queues + (pipe * _BCM_TD2_NUM_L2_UC_LEAVES_PER_PIPE);
  17992         qmax = (pipe + 1) * _BCM_TD2_NUM_L2_UC_LEAVES_PER_PIPE;
  17993         for ( i  = qmin ;
  17994                 i < qmax ; i++) {
  17995             node = &res->p_queue_node[i];
  17996             if ((node->in_use == FALSE) || (node->hw_index == -1)) {
  17997                 continue;
  17998             }
  17999             if (node->remote_modid == modid) {
  18000                 if ( found == TRUE) {
  18001                     *base_node = node;
  18002                     break;
  18003                 }
  18004                 found = TRUE;
  18005             }
  18006         }
  18007     }
  18008     return BCM_E_NONE;
  18009 }
  18010 
  18011 STATIC int
  18012 _bcm_td2_port_voq_base_set(int unit, bcm_port_t local_port, int base)
  18013 {
  18014     uint64 rval;
  18015     int pipe;
  18016     
  18017     pipe = _BCM_TD2_PORT_TO_PIPE(unit, local_port);
  18018     BCM_IF_ERROR_RETURN(READ_ING_COS_MODE_64r(unit, local_port, &rval));
  18019     soc_reg64_field32_set(unit, ING_COS_MODE_64r, &rval, BASE_QUEUE_NUM_1f,
  18020             pipe == _TD2_XPIPE ? base : base + 2048);
  18021     BCM_IF_ERROR_RETURN(WRITE_ING_COS_MODE_64r(unit, local_port, rval));
  18022     return BCM_E_NONE;
  18023 }
  18024 
  18025 STATIC int
  18026 _bcm_td2_port_voq_base_get(int unit, bcm_port_t local_port, int *base)
  18027 {
  18028     uint64 rval;
  18029     int pipe;
  18030 
  18031     pipe = _BCM_TD2_PORT_TO_PIPE(unit, local_port);
  18032     BCM_IF_ERROR_RETURN(READ_ING_COS_MODE_64r(unit, local_port, &rval));
  18033     if (soc_reg64_field32_get(unit, ING_COS_MODE_64r, rval, QUEUE_MODEf) == 1) {
  18034         *base = soc_reg64_field32_get(unit, ING_COS_MODE_64r, rval, 
  18035                                   BASE_QUEUE_NUM_1f);
  18036         if (pipe == _TD2_YPIPE) {
  18037             *base -= 2048;
  18038         }
  18039  
  18040         return BCM_E_NONE;
  18041     }
  18042 
  18043     BCM_IF_ERROR_RETURN(
  18044         _bcm_td2_voq_min_hw_index(unit, local_port, -1, -1, base));
  18045 
  18046     return BCM_E_NONE;
  18047 }
  18048 
  18049 STATIC int
  18050 _bcm_td2_resolve_dmvoq_hw_index(int unit, _bcm_td2_cosq_node_t *node, 
  18051                     int cosq, bcm_module_t modid, bcm_port_t local_port)
  18052 {
  18053     int try, preffered_offset = -1, alloc_size;
  18054     int from_offset, max_offset,  port, rv, q_base, port_voq_base, pipe;
  18055     _bcm_td2_pipe_resources_t *res;
  18056     _bcm_td2_mmu_info_t *mmu_info;
  18057 
  18058     mmu_info = _bcm_td2_mmu_info[unit];
  18059     pipe = _BCM_TD2_PORT_TO_PIPE(unit, local_port);
  18060     res = _BCM_TD2_PRESOURCES(mmu_info, pipe);
  18061 
  18062     from_offset  = res->num_base_queues + 
  18063         (pipe * _BCM_TD2_NUM_L2_UC_LEAVES_PER_PIPE);
  18064     max_offset = (pipe + 1) * _BCM_TD2_NUM_L2_UC_LEAVES_PER_PIPE;
  18065     alloc_size = _TD2_NUM_COS(unit);
  18066 
  18067     for (try = 0; try < 2; try++) {
  18068         PBMP_HG_ITER(unit, port) {
  18069             if ((try == 1) && (port == local_port)) {
  18070                 continue;
  18071             }
  18072             
  18073             if ((try == 0) && (port != local_port)) {
  18074                 continue;
  18075            }
  18076 
  18077             rv = _bcm_td2_voq_min_hw_index(unit, port, modid, -1, &q_base);
  18078             if (!rv) {
  18079                 if (port == local_port) {
  18080                     /* Found VOQ for the same port/dest modid */
  18081                     node->hw_index = q_base + cosq;
  18082                     return BCM_E_NONE;
  18083                 } else if (modid == -1) {
  18084                     rv = _bcm_td2_port_voq_base_get(unit, port, &port_voq_base);
  18085                     if (rv) {
  18086                         continue;
  18087                     }
  18088                     preffered_offset = q_base - port_voq_base;
  18089                     rv = _bcm_td2_port_voq_base_get(unit, local_port, 
  18090                                                     &port_voq_base);
  18091                     if (rv) {
  18092                         /* No VOQ on the port yet */
  18093                         alloc_size += preffered_offset;
  18094                     } else {
  18095                         /* port has already VOQs */
  18096                         from_offset = port_voq_base + preffered_offset;
  18097                     }
  18098                     break;
  18099                 }
  18100             }
  18101         }
  18102         if (preffered_offset != -1) {
  18103             break;
  18104         }
  18105     }
  18106     if (modid == -1) {
  18107         /* Alloc hw index. */
  18108         rv = _bcm_td2_node_index_get(res->ext_qlist.bits, 
  18109                 from_offset, max_offset, 
  18110                 alloc_size, _TD2_NUM_COS(unit), &q_base);
  18111         if (rv) {
  18112             return BCM_E_RESOURCE;
  18113         }
  18114 
  18115         if (_bcm_td2_port_voq_base_get(unit, local_port, &port_voq_base)) {
  18116             _bcm_td2_port_voq_base_set(unit, local_port, q_base);
  18117         }
  18118         q_base = q_base + alloc_size - _TD2_NUM_COS(unit);
  18119         node->hw_index = q_base + cosq;
  18120         node->hw_cosq = node->hw_index % _TD2_NUM_COS(unit);
  18121         node->remote_modid = modid;
  18122         _bcm_td2_node_index_set(&res->ext_qlist, q_base, _TD2_NUM_COS(unit));
  18123     } else {
  18124         _bcm_td2_port_voq_base_set(unit, local_port, node->hw_index);
  18125         node->remote_modid = modid;
  18126         rv = BCM_E_NONE;
  18127     }
  18128     return rv;
  18129 }
  18130 
  18131 typedef struct _bcm_td2_voq_info_s {
  18132     int          valid;
  18133     _bcm_td2_cosq_node_t *node;
  18134     bcm_module_t remote_modid;
  18135     bcm_port_t   remote_port;
  18136     bcm_port_t   local_port;
  18137     int          hw_cosq;
  18138     int          hw_index;
  18139 } _bcm_td2_voq_info_t;
  18140 
  18141 STATIC int
  18142 _bcm_td2_cosq_sort_voq_list(void *a, void *b)
  18143 {
  18144     _bcm_td2_voq_info_t *va, *vb;
  18145     int sa, sb;
  18146 
  18147     va = (_bcm_td2_voq_info_t*)a;
  18148     vb = (_bcm_td2_voq_info_t*)b;
  18149     
  18150     sa = (va->remote_modid << 19) | (va->remote_port << 11) |
  18151          (va->local_port << 3) | (va->hw_cosq);
  18152 
  18153     sb = (vb->remote_modid << 19) | (vb->remote_port << 11) |
  18154          (vb->local_port << 3) | (vb->hw_cosq);
  18155 
  18156     return sa - sb;
  18157 }
  18158     
  18159 STATIC int
  18160 _bcm_td2_get_queue_skip_count_on_cos(uint32 cbmp, int cur_cos, int next_cos)
  18161 {
  18162     int i,skip = 0;
  18163 
  18164     if ((next_cos >= 4) && (cur_cos/4 != next_cos/4)) {
  18165         cur_cos = -1;
  18166         next_cos -= 4;
  18167     }
  18168     
  18169     for (i = cur_cos + 1; i < next_cos; i++) {
  18170         if (cbmp & (1 << i)) {
  18171             skip += 1;
  18172         }
  18173     }
  18174     return skip;
  18175 }
  18176 
  18177 STATIC int
  18178 _bcm_td2_msg_buf_get(int unit, bcm_port_t srcid)
  18179 {
  18180     int ii, hole = -1;
  18181     uint32 rval, csrc;
  18182 
  18183     for (ii = 0; ii < 16; ii++) {
  18184         BCM_IF_ERROR_RETURN(READ_BUF_CFGr(unit, ii, &rval));
  18185         if (srcid == (csrc = soc_reg_field_get(unit, BUF_CFGr, rval, SRC_IDf))) {
  18186             return ii;
  18187         }
  18188         if ((hole == -1) && (csrc == 0)) {
  18189             hole = ii;
  18190         }
  18191     }
  18192 
  18193     if (hole == -1) {
  18194         return BCM_E_RESOURCE;
  18195     }
  18196    
  18197     rval = 0;
  18198     soc_reg_field_set(unit, BUF_CFGr, &rval, SRC_IDf, srcid);
  18199     BCM_IF_ERROR_RETURN(WRITE_BUF_CFGr(unit, hole, rval));
  18200     
  18201     return hole;
  18202 }
  18203 
  18204 STATIC int
  18205 _bcm_td2_gport_dpvoq_config_set(int unit, bcm_gport_t gport, 
  18206                                 bcm_cos_queue_t cosq,
  18207                                 bcm_module_t remote_modid,
  18208                                 bcm_port_t remote_port)
  18209 {
  18210     uint32 profile = 0xFFFFFFFF;
  18211     _bcm_td2_cosq_node_t *node;
  18212     bcm_port_t local_port;
  18213     uint32 cng_offset;
  18214     uint8 cbmp = 0, nib_cbmp = 0;
  18215     _bcm_td2_mmu_info_t *mmu_info;
  18216     _bcm_td2_voq_info_t *plist = NULL, *vlist = NULL;
  18217     int pcount, ii, vcount = 0;
  18218     voq_port_map_entry_t *voq_port_map_entries = NULL;
  18219     int rv = BCM_E_NONE, mod_base = 0, num_cos = 0, dm = -1, eq_base;
  18220     voq_mod_map_entry_t voq_mod_map;
  18221     void *entries[1];
  18222     int cng_bytes_per_e2ecc_msg = 32;
  18223     int p2ioff[64], ioff, port, skip, *dm2off, count, pipe;
  18224     _bcm_td2_pipe_resources_t *res;
  18225 
  18226     if ((cosq < 0) || (cosq > _TD2_NUM_COS(unit))) {
  18227         return BCM_E_PARAM;
  18228     }
  18229 
  18230     if ((mmu_info = _bcm_td2_mmu_info[unit]) == NULL) {
  18231         return BCM_E_INIT;
  18232     }
  18233 
  18234     BCM_IF_ERROR_RETURN
  18235       (_bcm_td2_cosq_node_get(unit, gport, 0, NULL, &local_port, NULL, &node));
  18236 
  18237     pipe = _BCM_TD2_PORT_TO_PIPE(unit, local_port);
  18238     res = _BCM_TD2_PRESOURCES(mmu_info, pipe);
  18239 
  18240     eq_base = (res->num_base_queues + 7) & ~7;
  18241     
  18242     node->remote_modid = remote_modid;
  18243     node->remote_port = remote_port;
  18244     node->hw_cosq = cosq;
  18245 
  18246     dm2off = sal_alloc(sizeof(int) * 256, "voq_vlist");
  18247     if (!dm2off) {
  18248         return BCM_E_MEMORY;
  18249     }
  18250     sal_memset(dm2off, 0, sizeof(int)*256);
  18251 
  18252     /* alloc temp vlist */
  18253     vlist = sal_alloc(sizeof(_bcm_td2_voq_info_t) * 1480, "voq_vlist");
  18254     if (!vlist) {
  18255         sal_free(dm2off);
  18256         return BCM_E_MEMORY;
  18257     }
  18258     sal_memset(vlist, 0, sizeof(_bcm_td2_voq_info_t)*1480);
  18259 
  18260     for (ii = 0; ii < _BCM_TD2_NUM_L2_UC_LEAVES; ii++) {
  18261         node = &res->p_queue_node[ii];
  18262         if ((node->remote_modid == -1) || (node->remote_port == -1)) {
  18263             continue;
  18264         }
  18265         vlist[vcount].remote_modid = node->remote_modid;
  18266         vlist[vcount].remote_port  = node->remote_port; 
  18267         vlist[vcount].local_port   = node->local_port;
  18268         vlist[vcount].hw_cosq     = node->hw_cosq; 
  18269         vlist[vcount].node         = node;
  18270         vcount += 1;
  18271     }
  18272 
  18273     /* Sort the nodes */
  18274     _shr_sort(vlist, vcount, sizeof(_bcm_td2_voq_info_t), 
  18275                 _bcm_td2_cosq_sort_voq_list);
  18276 
  18277     for (ii = 0; ii < 64; ii++) {
  18278         p2ioff[ii] = -1;
  18279     }
  18280     
  18281     PBMP_HG_ITER(unit, port) {
  18282         ioff = _bcm_td2_msg_buf_get(unit, port);
  18283         p2ioff[port] = ioff;
  18284     }
  18285 
  18286     for (ii = 0; ii < vcount; ii++) {
  18287         cbmp |= 1 << vlist[ii].hw_cosq;
  18288     }
  18289 
  18290     nib_cbmp = (cbmp >> 4) | (cbmp & 0xf);
  18291 
  18292     for (ii = 0; ii < 4; ii++) {
  18293         if ((1 << ii) & nib_cbmp) {
  18294             num_cos += 1;
  18295         }
  18296     }
  18297 
  18298     for (count = 1, ii = 0; ii < vcount; ii++) {
  18299         if (dm2off[vlist[ii].remote_modid]==0) {
  18300             dm2off[vlist[ii].remote_modid] = count;
  18301         }
  18302     }
  18303 
  18304     plist = sal_alloc(sizeof(_bcm_td2_voq_info_t) * 1480, "voq_vlist");
  18305     if (!plist) {
  18306         sal_free(dm2off);
  18307         sal_free(vlist);
  18308         return BCM_E_MEMORY;
  18309     }
  18310     sal_memset(plist, 0, sizeof(_bcm_td2_voq_info_t)*1480);
  18311 
  18312     for (pcount = 0, ii = 0; ii < vcount; ii++) {
  18313         if (pcount % 4) {
  18314             if ((plist[pcount - 1].remote_modid != vlist[ii].remote_modid) ||
  18315                 (plist[pcount - 1].remote_port != vlist[ii].remote_port)) {
  18316                 pcount = (pcount + 3) & ~3;
  18317             } else if (plist[pcount - 1].local_port != vlist[ii].local_port) {
  18318                 skip = (p2ioff[vlist[ii].local_port] - 
  18319                             p2ioff[plist[pcount - 1].local_port] - 1) * num_cos;
  18320                 skip +=  _bcm_td2_get_queue_skip_count_on_cos(nib_cbmp, 
  18321                                         plist[pcount - 1].hw_cosq,
  18322                                         vlist[ii].hw_cosq);
  18323                 if (skip >= 4) {
  18324                     pcount = ((pcount + 3) & ~3) + (skip % 4);
  18325                 } else {
  18326                     pcount += skip;
  18327                 }
  18328             } else if ((vlist[ii].hw_cosq - plist[pcount - 1].hw_cosq) > 1) {
  18329                 if (plist[pcount - 1].hw_cosq/4 != vlist[ii].hw_cosq/4) {
  18330                     pcount = (pcount + 3) & ~3;
  18331                 }
  18332                 pcount += _bcm_td2_get_queue_skip_count_on_cos(nib_cbmp, 
  18333                                         plist[pcount - 1].hw_cosq,
  18334                                         vlist[ii].hw_cosq);
  18335             }
  18336         } else {
  18337             pcount += _bcm_td2_get_queue_skip_count_on_cos(nib_cbmp, -1,
  18338                                                     vlist[ii].hw_cosq);
  18339         }
  18340        
  18341         plist[pcount].valid = 1;
  18342         plist[pcount].local_port = vlist[ii].local_port;
  18343         plist[pcount].remote_modid = vlist[ii].remote_modid;
  18344         plist[pcount].remote_port = vlist[ii].remote_port;
  18345         plist[pcount].hw_cosq = vlist[ii].hw_cosq;
  18346         plist[pcount].node = vlist[ii].node;
  18347         vlist[ii].node->hw_index = pcount + eq_base;
  18348         
  18349         #ifdef DEBUG_TD2_COSQ
  18350           LOG_CLI((BSL_META_U(unit,
  18351                               "DPVOQ DM=%d DP=%d LocalPort=%d COS=%d HWIndex=%d\n"),
  18352                    plist[pcount].remote_modid,
  18353                    plist[pcount].remote_port,
  18354                    plist[pcount].local_port,
  18355                    plist[pcount].hw_cosq,
  18356                    plist[pcount].node->hw_index));
  18357         #endif
  18358         pcount += 1;
  18359     }
  18360 
  18361     /* program the voq port profiles. */
  18362     voq_port_map_entries = sal_alloc(sizeof(voq_port_map_entry_t)*128, 
  18363                                         "voq port map entries");
  18364     if (!voq_port_map_entries) {
  18365         goto fail;
  18366     }
  18367     sal_memset(voq_port_map_entries, 0, sizeof(voq_port_map_entry_t)*128);
  18368 
  18369     entries[0] = voq_port_map_entries;
  18370     dm = -1;
  18371     for (ii = 0; ii <= pcount; ii++) {
  18372         if ((ii == pcount) ||
  18373             ((dm != -1) && (plist[ii - 1].remote_modid != dm))) {
  18374             
  18375             rv = READ_VOQ_MOD_MAPm(unit, MEM_BLOCK_ALL, dm, &voq_mod_map);
  18376             if (rv) {
  18377                 goto fail;
  18378             }     
  18379             if (soc_mem_field32_get(unit, VOQ_MOD_MAPm, 
  18380                                                 &voq_mod_map, VOQ_VALIDf)) {
  18381                 profile = soc_mem_field32_get(unit, VOQ_MOD_MAPm, 
  18382                               &voq_mod_map, VOQ_MOD_PORT_PROFILE_INDEXf);
  18383                 
  18384                 rv = soc_profile_mem_delete(unit, 
  18385                             _bcm_td2_voq_port_map_profile[unit], profile*128);
  18386                 if (rv) {
  18387                     goto fail;
  18388                 }
  18389             }
  18390             rv = soc_profile_mem_add(unit, 
  18391                                 _bcm_td2_voq_port_map_profile[unit], 
  18392                                 entries, 128, &profile);
  18393             if (rv) {
  18394                 goto fail;
  18395             }
  18396            
  18397             soc_mem_field32_set(unit, VOQ_MOD_MAPm, &voq_mod_map, 
  18398                                 VOQ_MOD_PORT_PROFILE_INDEXf, profile/128);
  18399             soc_mem_field32_set(unit, VOQ_MOD_MAPm, &voq_mod_map, 
  18400                                 VOQ_VALIDf, 1);
  18401             soc_mem_field32_set(unit, VOQ_MOD_MAPm, &voq_mod_map, 
  18402                                 VOQ_MOD_OFFSETf, mod_base);
  18403             rv = soc_mem_write(unit, VOQ_MOD_MAPm, MEM_BLOCK_ALL, 
  18404                                dm, &voq_mod_map);
  18405             if (rv) {
  18406                 goto fail;
  18407             }
  18408             sal_memset(voq_port_map_entries, 0, sizeof(voq_port_map_entry_t)*128);
  18409             if (ii != pcount) {
  18410                 mod_base = plist[ii].hw_index & ~3;
  18411                 dm = plist[ii].remote_modid;
  18412             }
  18413         }
  18414 
  18415         if (ii == pcount) {
  18416             break;
  18417         }
  18418 
  18419         if (plist[ii].valid == 0) {
  18420             continue;
  18421         }
  18422 
  18423         dm = plist[ii].remote_modid;
  18424         soc_mem_field32_set(unit, VOQ_PORT_MAPm, 
  18425                             &voq_port_map_entries[plist[ii].remote_port], 
  18426                             VOQ_PORT_OFFSETf, 
  18427                             plist[ii].node->hw_index - mod_base);
  18428     }
  18429 
  18430     dm = -1;
  18431     for (ii = 0; ii < pcount; ii += 1) {
  18432         if (plist[ii].valid == 0) {
  18433             continue;
  18434         }
  18435 
  18436         cng_offset = (dm2off[plist[ii].remote_modid] - 1) * 
  18437                         cng_bytes_per_e2ecc_msg;
  18438 
  18439         _bcm_td2_map_fc_status_to_node(unit, 
  18440                                        local_port,
  18441                                        _BCM_TD2_COSQ_FC_E2ECC,
  18442                                        cng_offset + plist[ii].remote_port, 
  18443                                        plist[ii].hw_cosq,
  18444                                        plist[ii].node->hw_index,
  18445                                        SOC_TD2_NODE_LVL_L2);
  18446     }
  18447    
  18448 fail:
  18449     if (vlist) {
  18450         sal_free(vlist);
  18451     }
  18452 
  18453     if (plist) {
  18454         sal_free(plist);
  18455     }
  18456 
  18457     if (dm2off) {
  18458         sal_free(dm2off);
  18459     }
  18460     
  18461     if (voq_port_map_entries) {
  18462         sal_free(voq_port_map_entries);
  18463     }
  18464 
  18465     if (rv) {
  18466         node->remote_modid = -1;
  18467         node->remote_port = -1;
  18468     }
  18469     return rv;
  18470 }
  18471 
  18472 STATIC int
  18473 _bcm_td2_gport_dmvoq_config_set(int unit, bcm_gport_t gport, 
  18474                                 bcm_cos_queue_t cosq,
  18475                                 bcm_module_t fabric_modid, 
  18476                                 bcm_module_t dest_modid,
  18477                                 bcm_port_t fabric_port)
  18478 {
  18479     int intf_index;
  18480     _bcm_td2_cosq_node_t *node;
  18481     _bcm_td2_cosq_node_t *base_node = NULL;
  18482     bcm_port_t local_port;
  18483     voq_mod_map_entry_t voq_mod_map_entry;
  18484     mmu_intfi_offset_map_tbl_entry_t offset_map_tbl_entry;
  18485     mmu_intfi_base_index_tbl_entry_t base_tbl_entry;
  18486     uint32 cng_offset = 0;
  18487     _bcm_td2_mmu_info_t *mmu_info;
  18488     int fabric_port_count, count = 0;
  18489     int map_offset = 0;
  18490     int port = 0;
  18491 
  18492     if ((mmu_info = _bcm_td2_mmu_info[unit]) == NULL) {
  18493         return BCM_E_INIT;
  18494     }
  18495 
  18496     if (fabric_modid >= 64) {
  18497         return BCM_E_PARAM;
  18498     }
  18499 
  18500     BCM_IF_ERROR_RETURN
  18501       (_bcm_td2_cosq_node_get(unit, gport, 0, NULL, &local_port, NULL, &node));
  18502 
  18503     if (!node) {
  18504         return BCM_E_NOT_FOUND;
  18505     }
  18506 
  18507     BCM_IF_ERROR_RETURN(_bcm_td2_resolve_dmvoq_hw_index(unit, node, cosq,
  18508                 dest_modid, local_port));
  18509     BCM_IF_ERROR_RETURN(_bcm_td2_voq_base_node_get(
  18510                 unit, local_port, dest_modid, &base_node));
  18511     if (base_node == NULL) {
  18512         base_node = node ;
  18513     }
  18514     BCM_PBMP_COUNT(base_node->fabric_pbmp, fabric_port_count);
  18515     if (fabric_port_count == 0) {
  18516         map_offset = mmu_info->curr_merger_index;
  18517         if (map_offset >= soc_mem_index_count(unit, MMU_INTFI_MERGE_ST_TBLm)) {
  18518             return BCM_E_RESOURCE;
  18519         }
  18520     } else {
  18521         BCM_PBMP_ITER(base_node->fabric_pbmp, port) {
  18522             BCM_IF_ERROR_RETURN(soc_mem_read(unit, MMU_INTFI_OFFSET_MAP_TBLm, 
  18523                         MEM_BLOCK_ALL, 
  18524                         port * 2, &offset_map_tbl_entry));
  18525             map_offset = soc_mem_field32_get(unit, MMU_INTFI_OFFSET_MAP_TBLm,
  18526                     &offset_map_tbl_entry,
  18527                     MAP_OFFSETf);
  18528             break;
  18529         }
  18530     }
  18531     if (!BCM_PBMP_MEMBER(base_node->fabric_pbmp, fabric_port)) {
  18532         if (map_offset == mmu_info->curr_merger_index ) {
  18533             mmu_info->curr_merger_index += 2;
  18534         }
  18535 
  18536         BCM_PBMP_PORT_ADD (base_node->fabric_pbmp, fabric_port);
  18537         BCM_PBMP_COUNT(base_node->fabric_pbmp, fabric_port_count);
  18538         BCM_PBMP_ITER(base_node->fabric_pbmp, port) {
  18539             count++;
  18540             BCM_IF_ERROR_RETURN(soc_mem_read(unit, MMU_INTFI_OFFSET_MAP_TBLm, 
  18541                         MEM_BLOCK_ALL, 
  18542                         port * 2, &offset_map_tbl_entry));
  18543             soc_mem_field32_set(unit, MMU_INTFI_OFFSET_MAP_TBLm, 
  18544                     &offset_map_tbl_entry,
  18545                     MAP_OFFSETf, map_offset);
  18546             soc_mem_field32_set(unit, MMU_INTFI_OFFSET_MAP_TBLm, 
  18547                     &offset_map_tbl_entry,
  18548                     LASTf, count < fabric_port_count ? 0 : 1 );
  18549             BCM_IF_ERROR_RETURN(soc_mem_write(unit, MMU_INTFI_OFFSET_MAP_TBLm, 
  18550                         MEM_BLOCK_ALL, 
  18551                         port * 2, &offset_map_tbl_entry));
  18552 
  18553             BCM_IF_ERROR_RETURN(soc_mem_read(unit, MMU_INTFI_OFFSET_MAP_TBLm, 
  18554                         MEM_BLOCK_ALL, 
  18555                         (port * 2) + 1, &offset_map_tbl_entry));
  18556             soc_mem_field32_set(unit, MMU_INTFI_OFFSET_MAP_TBLm, 
  18557                     &offset_map_tbl_entry,
  18558                     MAP_OFFSETf, map_offset + 1);
  18559             soc_mem_field32_set(unit, MMU_INTFI_OFFSET_MAP_TBLm, 
  18560                     &offset_map_tbl_entry,
  18561                     LASTf, count < fabric_port_count ? 0 : 1 );
  18562             BCM_IF_ERROR_RETURN(soc_mem_write(unit, MMU_INTFI_OFFSET_MAP_TBLm, 
  18563                         MEM_BLOCK_ALL, 
  18564                         (port * 2) + 1, &offset_map_tbl_entry));
  18565         }
  18566     }
  18567 
  18568     BCM_IF_ERROR_RETURN(soc_mem_read(unit, VOQ_MOD_MAPm, MEM_BLOCK_ALL, 
  18569                 dest_modid, &voq_mod_map_entry));
  18570     soc_mem_field32_set(unit, VOQ_MOD_MAPm, &voq_mod_map_entry,
  18571             VOQ_VALIDf, 1);
  18572 
  18573     soc_mem_field32_set(unit, VOQ_MOD_MAPm, &voq_mod_map_entry,
  18574             VOQ_MOD_OFFSETf, 0);
  18575 
  18576     BCM_IF_ERROR_RETURN(
  18577             soc_mem_write(unit, VOQ_MOD_MAPm, MEM_BLOCK_ALL, dest_modid, 
  18578                 &voq_mod_map_entry));
  18579 
  18580     intf_index = _bcm_td2_msg_buf_get(unit, fabric_modid);
  18581     if (intf_index < 0) {
  18582         return BCM_E_INTERNAL;
  18583     }
  18584 
  18585     cng_offset = intf_index * 64 * 2;
  18586 
  18587     BCM_IF_ERROR_RETURN
  18588         (soc_mem_read(unit, MMU_INTFI_BASE_INDEX_TBLm, 
  18589                       MEM_BLOCK_ALL, fabric_modid, &base_tbl_entry));
  18590     
  18591     soc_mem_field32_set(unit, MMU_INTFI_BASE_INDEX_TBLm, &base_tbl_entry, 
  18592             BASE_ADDRf, cng_offset);
  18593     soc_mem_field32_set(unit, MMU_INTFI_BASE_INDEX_TBLm, &base_tbl_entry, 
  18594             ENf, 2);
  18595 
  18596     BCM_IF_ERROR_RETURN(soc_mem_write(unit, MMU_INTFI_BASE_INDEX_TBLm,
  18597                 MEM_BLOCK_ALL, fabric_modid, &base_tbl_entry));
  18598 
  18599     /* set the mapping from congestion bits in flow control table
  18600      * to corresponding cosq. */
  18601     BCM_IF_ERROR_RETURN(_bcm_td2_map_fc_status_to_node(unit, local_port,
  18602                 _BCM_TD2_COSQ_FC_VOQFC, cng_offset + map_offset, 
  18603                 cosq, node->hw_index, SOC_TD2_NODE_LVL_L2));
  18604 
  18605     #ifdef DEBUG_TD2_COSQ
  18606     LOG_CLI((BSL_META_U(unit,
  18607                         "Gport=0x%08x hw_index=%d cosq=%d\n"),
  18608              gport, node->hw_index, cosq));
  18609     #endif
  18610 
  18611     return BCM_E_NONE;
  18612 }
  18613 
  18614 int bcm_td2_cosq_gport_congestion_config_set(int unit, bcm_gport_t gport, 
  18615                                          bcm_cos_queue_t cosq, 
  18616                                          bcm_cosq_congestion_info_t *config)
  18617 {
  18618     _bcm_td2_mmu_info_t *mmu_info;
  18619 
  18620     if (!config) {
  18621         return BCM_E_PARAM;
  18622     }
  18623 
  18624     if ((mmu_info = _bcm_td2_mmu_info[unit]) == NULL) {
  18625         return BCM_E_INIT;
  18626     }
  18627 
  18628     /* determine if this gport is DPVOQ or DMVOQ */
  18629     if ((config->fabric_port != -1) && (config->dest_modid != -1)) {
  18630         return _bcm_td2_gport_dmvoq_config_set(unit, gport, cosq, 
  18631                                                config->fabric_modid,
  18632                                                config->dest_modid,
  18633                                                config->fabric_port);
  18634     } else if ((config->dest_modid != -1) && (config->dest_port != -1)) {
  18635         return _bcm_td2_gport_dpvoq_config_set(unit, gport, cosq, 
  18636                                                config->dest_modid,
  18637                                                config->dest_port);
  18638     }
  18639     
  18640     return BCM_E_PARAM;
  18641 }
  18642 
  18643 int bcm_td2_cosq_gport_congestion_config_get(int unit, bcm_gport_t port, 
  18644                                          bcm_cos_queue_t cosq, 
  18645                                          bcm_cosq_congestion_info_t *config)
  18646 {
  18647     _bcm_td2_mmu_info_t *mmu_info;
  18648     bcm_port_t local_port;
  18649     _bcm_td2_cosq_node_t *node;
  18650 
  18651     if (!config) {
  18652         return BCM_E_PARAM;
  18653     }
  18654 
  18655     if ((mmu_info = _bcm_td2_mmu_info[unit]) == NULL) {
  18656         return BCM_E_INIT;
  18657     }
  18658 
  18659     BCM_IF_ERROR_RETURN
  18660       (_bcm_td2_cosq_node_get(unit, port, 0, NULL, &local_port, NULL, &node));
  18661 
  18662 
  18663     if (!node) {
  18664         return BCM_E_NOT_FOUND;
  18665     }
  18666 
  18667     config->dest_modid = node->remote_modid;
  18668     config->dest_port = node->remote_port;
  18669 
  18670     return BCM_E_NONE;
  18671 }
  18672 
  18673 
  18674 
  18675 int bcm_td2_cosq_bst_profile_set(int unit, 
  18676                                  bcm_gport_t port, 
  18677                                  bcm_cos_queue_t cosq, 
  18678                                  bcm_bst_stat_id_t bid,
  18679                                  bcm_cosq_bst_profile_t *profile)
  18680 {
  18681     BCM_IF_ERROR_RETURN(_bcm_bst_cmn_profile_set
  18682         (unit, port, cosq, BCM_BST_DUP_XPE, bid, profile));
  18683     return BCM_E_NONE;
  18684 }
  18685 
  18686 int bcm_td2_cosq_bst_profile_get(int unit, 
  18687                                  bcm_gport_t port, 
  18688                                  bcm_cos_queue_t cosq, 
  18689                                  bcm_bst_stat_id_t bid,
  18690                                  bcm_cosq_bst_profile_t *profile)
  18691 {
  18692     BCM_IF_ERROR_RETURN(_bcm_bst_cmn_profile_get
  18693         (unit, port, cosq, BCM_BST_DUP_XPE, bid, profile));
  18694     return BCM_E_NONE;
  18695 }
  18696 
  18697 int bcm_td2_cosq_bst_stat_get(int unit, 
  18698                               bcm_gport_t port, 
  18699                               bcm_cos_queue_t cosq, 
  18700                               bcm_bst_stat_id_t bid, 
  18701                               uint32 options,
  18702                               uint64 *pvalue)
  18703 {
  18704     return _bcm_bst_cmn_stat_get(unit, port, cosq, -1, bid, options, pvalue);
  18705 }
  18706 
  18707 int bcm_td2_cosq_bst_stat_multi_get(int unit,
  18708                                 bcm_gport_t port,
  18709                                 bcm_cos_queue_t cosq,
  18710                                 uint32 options,
  18711                                 int max_values,
  18712                                 bcm_bst_stat_id_t *id_list,
  18713                                 uint64 *pvalues)
  18714 {
  18715     return _bcm_bst_cmn_stat_multi_get(unit, port, cosq, options, max_values, 
  18716                                     id_list, pvalues);
  18717 }
  18718 
  18719 int bcm_td2_cosq_bst_stat_clear(int unit, bcm_gport_t port, 
  18720                             bcm_cos_queue_t cosq, bcm_bst_stat_id_t bid)
  18721 {
  18722     return _bcm_bst_cmn_stat_clear(unit, port, cosq, bid);
  18723 }
  18724 
  18725 int bcm_td2_cosq_bst_stat_sync(int unit, bcm_bst_stat_id_t bid)
  18726 {
  18727     return _bcm_bst_cmn_stat_sync(unit, bid);
  18728 }
  18729 
  18730 
  18731 /*
  18732  * Function:
  18733  *      _bcm_td2_cosq_endpoint_l2_create
  18734  * Purpose:
  18735  *      Create a L2 endpoint.
  18736  * Parameters:
  18737  *      unit        - (IN) Unit number.
  18738  *      endpoint_id - (IN) Endpoint ID
  18739  *      vlan        - (IN) VLAN
  18740  *      mac         - (IN) MAC address
  18741  * Returns:
  18742  *      BCM_E_xxx
  18743  */
  18744 STATIC int
  18745 _bcm_td2_cosq_endpoint_l2_create(
  18746     int unit, 
  18747     int endpoint_id,
  18748     bcm_vlan_t vlan,
  18749     bcm_mac_t mac)
  18750 {
  18751     int rv;
  18752     bcm_l2_addr_t l2addr;
  18753     l2_endpoint_id_entry_t l2_endpoint_entry;
  18754     int vfi;
  18755 
  18756     /* Make sure (vlan, mac) entry is already in L2 table */
  18757     rv = bcm_esw_l2_addr_get(unit, mac, vlan, &l2addr);
  18758     if (rv == BCM_E_NOT_FOUND) {
  18759         /* The (vlan, mac) entry needs to be added to L2 table
  18760          * before configuring it for endpoint queuing.
  18761          */
  18762         return BCM_E_CONFIG;
  18763     } else if (BCM_FAILURE(rv)) {
  18764         return rv;
  18765     }
  18766 
  18767     /* Add (vlan, mac) entry to L2_ENDPOINT_ID table */
  18768     sal_memcpy(&l2_endpoint_entry, soc_mem_entry_null(unit, L2_ENDPOINT_IDm),
  18769             sizeof(l2_endpoint_id_entry_t));
  18770     soc_L2_ENDPOINT_IDm_field32_set(unit, &l2_endpoint_entry, VALIDf, 1);
  18771     if (_BCM_MPLS_VPN_IS_VPLS(vlan)) {
  18772         _BCM_MPLS_VPN_GET(vfi, _BCM_MPLS_VPN_TYPE_VPLS, vlan);
  18773         soc_L2_ENDPOINT_IDm_field32_set(unit, &l2_endpoint_entry, L2__VFIf,
  18774                 vfi);
  18775         soc_L2_ENDPOINT_IDm_field32_set(unit, &l2_endpoint_entry, KEY_TYPEf,
  18776                 TD2_L2_HASH_KEY_TYPE_VFI);
  18777     } else if (_BCM_IS_MIM_VPN(vlan)) {
  18778         _BCM_MIM_VPN_GET(vfi, _BCM_MIM_VPN_TYPE_MIM, vlan);
  18779         soc_L2_ENDPOINT_IDm_field32_set(unit, &l2_endpoint_entry, L2__VFIf,
  18780                 vfi);
  18781         soc_L2_ENDPOINT_IDm_field32_set(unit, &l2_endpoint_entry, KEY_TYPEf,
  18782                 TD2_L2_HASH_KEY_TYPE_VFI);
  18783     } else {
  18784         VLAN_CHK_ID(unit, vlan);
  18785         soc_L2_ENDPOINT_IDm_field32_set(unit, &l2_endpoint_entry, L2__VLAN_IDf,
  18786                 vlan);
  18787         soc_L2_ENDPOINT_IDm_field32_set(unit, &l2_endpoint_entry, KEY_TYPEf,
  18788                 TD2_L2_HASH_KEY_TYPE_BRIDGE);
  18789     }
  18790     soc_L2_ENDPOINT_IDm_mac_addr_set(unit, &l2_endpoint_entry, L2__MAC_ADDRf,
  18791             mac);
  18792     soc_L2_ENDPOINT_IDm_field32_set(unit, &l2_endpoint_entry, EH_TAG_TYPEf, 2);
  18793     soc_L2_ENDPOINT_IDm_field32_set(unit, &l2_endpoint_entry, EH_QUEUE_TAGf,
  18794             endpoint_id);
  18795     SOC_IF_ERROR_RETURN(soc_mem_insert(unit, L2_ENDPOINT_IDm, MEM_BLOCK_ANY,
  18796                 &l2_endpoint_entry));
  18797 
  18798     return BCM_E_NONE;
  18799 }
  18800 
  18801 /*
  18802  * Function:
  18803  *      _bcm_td2_cosq_endpoint_l2_destroy
  18804  * Purpose:
  18805  *      Destroy a L2 endpoint.
  18806  * Parameters:
  18807  *      unit        - (IN) Unit number.
  18808  *      vlan        - (IN) VLAN
  18809  *      mac         - (IN) MAC address
  18810  * Returns:
  18811  *      BCM_E_xxx
  18812  */
  18813 STATIC int
  18814 _bcm_td2_cosq_endpoint_l2_destroy(
  18815     int unit, 
  18816     bcm_vlan_t vlan,
  18817     bcm_mac_t mac)
  18818 {
  18819     l2_endpoint_id_entry_t l2_endpoint_entry;
  18820     int vfi;
  18821 
  18822     /* Delete (vlan, mac) entry from L2_ENDPOINT_ID table */
  18823     sal_memcpy(&l2_endpoint_entry, soc_mem_entry_null(unit, L2_ENDPOINT_IDm),
  18824             sizeof(l2_endpoint_id_entry_t));
  18825     if (_BCM_MPLS_VPN_IS_VPLS(vlan)) {
  18826         _BCM_MPLS_VPN_GET(vfi, _BCM_MPLS_VPN_TYPE_VPLS, vlan);
  18827         soc_L2_ENDPOINT_IDm_field32_set(unit, &l2_endpoint_entry, L2__VFIf,
  18828                 vfi);
  18829         soc_L2_ENDPOINT_IDm_field32_set(unit, &l2_endpoint_entry, KEY_TYPEf,
  18830                 TD2_L2_HASH_KEY_TYPE_VFI);
  18831     } else if (_BCM_IS_MIM_VPN(vlan)) {
  18832         _BCM_MIM_VPN_GET(vfi, _BCM_MIM_VPN_TYPE_MIM, vlan);
  18833         soc_L2_ENDPOINT_IDm_field32_set(unit, &l2_endpoint_entry, L2__VFIf,
  18834                 vfi);
  18835         soc_L2_ENDPOINT_IDm_field32_set(unit, &l2_endpoint_entry, KEY_TYPEf,
  18836                 TD2_L2_HASH_KEY_TYPE_VFI);
  18837     } else {
  18838         VLAN_CHK_ID(unit, vlan);
  18839         soc_L2_ENDPOINT_IDm_field32_set(unit, &l2_endpoint_entry, L2__VLAN_IDf,
  18840                 vlan);
  18841         soc_L2_ENDPOINT_IDm_field32_set(unit, &l2_endpoint_entry, KEY_TYPEf,
  18842                 TD2_L2_HASH_KEY_TYPE_BRIDGE);
  18843     }
  18844     soc_L2_ENDPOINT_IDm_mac_addr_set(unit, &l2_endpoint_entry, L2__MAC_ADDRf,
  18845             mac);
  18846     SOC_IF_ERROR_RETURN(soc_mem_delete(unit, L2_ENDPOINT_IDm, MEM_BLOCK_ANY,
  18847                 &l2_endpoint_entry));
  18848 
  18849     return BCM_E_NONE;
  18850 }
  18851 
  18852 #ifdef INCLUDE_L3
  18853 /*
  18854  * Function:
  18855  *      _bcm_td2_cosq_endpoint_ip4_create
  18856  * Purpose:
  18857  *      Create an IPv4 endpoint.
  18858  * Parameters:
  18859  *      unit        - (IN) Unit number.
  18860  *      endpoint_id - (IN) Endpoint ID
  18861  *      vrf         - (IN) Virtual router instance
  18862  *      ip_addr     - (IN) IPv4 address
  18863  * Returns:
  18864  *      BCM_E_xxx
  18865  */
  18866 STATIC int
  18867 _bcm_td2_cosq_endpoint_ip4_create(
  18868     int unit, 
  18869     int endpoint_id,
  18870     bcm_vrf_t vrf,
  18871     bcm_ip_t ip_addr)
  18872 {
  18873     int rv;
  18874     _bcm_l3_cfg_t l3cfg;
  18875 
  18876     if ((vrf > SOC_VRF_MAX(unit)) || 
  18877         (vrf < BCM_L3_VRF_DEFAULT)) {
  18878         return BCM_E_PARAM;
  18879     }
  18880 
  18881     L3_LOCK(unit);
  18882 
  18883     /* Make sure (vrf, ip_addr) entry is already in L3 host table */
  18884     sal_memset(&l3cfg, 0, sizeof(_bcm_l3_cfg_t));
  18885     l3cfg.l3c_vrf = vrf;
  18886     l3cfg.l3c_ip_addr = ip_addr;
  18887     rv = mbcm_driver[unit]->mbcm_l3_ip4_get(unit, &l3cfg);
  18888     if (rv == BCM_E_NOT_FOUND) {
  18889         /* The (vrf, ip_addr) entry needs to be added to L3 table
  18890          * before configuring it for endpoint queuing.
  18891          */
  18892         L3_UNLOCK(unit);
  18893         return BCM_E_CONFIG;
  18894     } else if (BCM_FAILURE(rv)) {
  18895         L3_UNLOCK(unit);
  18896         return rv;
  18897     } else {
  18898         /* Make sure the L3 ENTRY is in extender view */
  18899         if (!BCM_TD2_L3_USE_EMBEDDED_NEXT_HOP(unit, l3cfg.l3c_intf, 
  18900                                               BCM_XGS3_L3_INVALID_INDEX)) {
  18901             L3_UNLOCK(unit);
  18902             return BCM_E_CONFIG;
  18903         }
  18904     }
  18905 
  18906     if (l3cfg.l3c_eh_q_tag_type != 0) {
  18907         /* A queue tag has already been configured for this L3 entry. */
  18908         L3_UNLOCK(unit);
  18909         return BCM_E_EXISTS;
  18910     }
  18911 
  18912     /* Replace (vrf, ip_addr) entry's endpoint_id */
  18913     l3cfg.l3c_flags |= BCM_L3_REPLACE;
  18914     l3cfg.l3c_eh_q_tag_type = 2;
  18915     l3cfg.l3c_eh_q_tag = endpoint_id;
  18916     rv = mbcm_driver[unit]->mbcm_l3_ip4_replace(unit, &l3cfg);
  18917     if (BCM_FAILURE(rv)) {
  18918         L3_UNLOCK(unit);
  18919         return rv;
  18920     }
  18921 
  18922     L3_UNLOCK(unit);
  18923 
  18924     return rv;
  18925 }
  18926 
  18927 /*
  18928  * Function:
  18929  *      _bcm_td2_cosq_endpoint_ip4_destroy
  18930  * Purpose:
  18931  *      Destroy an IPv4 endpoint.
  18932  * Parameters:
  18933  *      unit        - (IN) Unit number.
  18934  *      vrf         - (IN) Virtual router instance
  18935  *      ip_addr     - (IN) IPv4 address
  18936  * Returns:
  18937  *      BCM_E_xxx
  18938  */
  18939 STATIC int
  18940 _bcm_td2_cosq_endpoint_ip4_destroy(
  18941     int unit, 
  18942     bcm_vrf_t vrf,
  18943     bcm_ip_t ip_addr)
  18944 {
  18945     int rv;
  18946     _bcm_l3_cfg_t l3cfg;
  18947 
  18948     if ((vrf > SOC_VRF_MAX(unit)) || 
  18949         (vrf < BCM_L3_VRF_DEFAULT)) {
  18950         return BCM_E_PARAM;
  18951     }
  18952 
  18953     L3_LOCK(unit);
  18954 
  18955     /* Get (vrf, ip_addr) entry */
  18956     sal_memset(&l3cfg, 0, sizeof(_bcm_l3_cfg_t));
  18957     l3cfg.l3c_vrf = vrf;
  18958     l3cfg.l3c_ip_addr = ip_addr;
  18959     rv = mbcm_driver[unit]->mbcm_l3_ip4_get(unit, &l3cfg);
  18960     if (BCM_FAILURE(rv)) {
  18961         L3_UNLOCK(unit);
  18962         return rv;
  18963     } else {
  18964         /* Make sure the L3 ENTRY is in extender view */
  18965         if (!BCM_TD2_L3_USE_EMBEDDED_NEXT_HOP(unit, l3cfg.l3c_intf, 
  18966                                               BCM_XGS3_L3_INVALID_INDEX)) {
  18967             L3_UNLOCK(unit);
  18968             return BCM_E_CONFIG;
  18969         }
  18970     }
  18971 
  18972     /* Delete (vrf, ip_addr) entry's endpoint_id */
  18973     l3cfg.l3c_flags |= BCM_L3_REPLACE;
  18974     l3cfg.l3c_eh_q_tag_type = 0;
  18975     l3cfg.l3c_eh_q_tag = 0;
  18976     rv = mbcm_driver[unit]->mbcm_l3_ip4_replace(unit, &l3cfg);
  18977     if (BCM_FAILURE(rv)) {
  18978         L3_UNLOCK(unit);
  18979         return rv;
  18980     }
  18981 
  18982     L3_UNLOCK(unit);
  18983 
  18984     return rv;
  18985 }
  18986 
  18987 /*
  18988  * Function:
  18989  *      _bcm_td2_cosq_endpoint_ip6_create
  18990  * Purpose:
  18991  *      Create an IPv6 endpoint.
  18992  * Parameters:
  18993  *      unit        - (IN) Unit number.
  18994  *      endpoint_id - (IN) Endpoint ID
  18995  *      vrf         - (IN) Virtual router instance
  18996  *      ip6_addr    - (IN) IPv6 address
  18997  * Returns:
  18998  *      BCM_E_xxx
  18999  */
  19000 STATIC int
  19001 _bcm_td2_cosq_endpoint_ip6_create(
  19002     int unit, 
  19003     int endpoint_id,
  19004     bcm_vrf_t vrf,
  19005     bcm_ip6_t ip6_addr)
  19006 {
  19007     int rv;
  19008     _bcm_l3_cfg_t l3cfg;
  19009 
  19010     if ((vrf > SOC_VRF_MAX(unit)) || 
  19011         (vrf < BCM_L3_VRF_DEFAULT)) {
  19012         return BCM_E_PARAM;
  19013     }
  19014 
  19015     L3_LOCK(unit);
  19016 
  19017     /* Make sure (vrf, ip6_addr) entry is already in L3 host table */
  19018     sal_memset(&l3cfg, 0, sizeof(_bcm_l3_cfg_t));
  19019     l3cfg.l3c_flags = BCM_L3_IP6;
  19020     l3cfg.l3c_vrf = vrf;
  19021     sal_memcpy(l3cfg.l3c_ip6, ip6_addr, BCM_IP6_ADDRLEN);
  19022     rv = mbcm_driver[unit]->mbcm_l3_ip6_get(unit, &l3cfg);
  19023     if (rv == BCM_E_NOT_FOUND) {
  19024         /* The (vrf, ip6_addr) entry needs to be added to L3 table
  19025          * before configuring it for endpoint queuing.
  19026          */
  19027         L3_UNLOCK(unit);
  19028         return BCM_E_CONFIG;
  19029     } else if (BCM_FAILURE(rv)) {
  19030         L3_UNLOCK(unit);
  19031         return rv;
  19032     } else {
  19033         /* Make sure the L3 ENTRY is in extender view */
  19034         if (!BCM_TD2_L3_USE_EMBEDDED_NEXT_HOP(unit, l3cfg.l3c_intf, 
  19035                                               BCM_XGS3_L3_INVALID_INDEX)) {
  19036             L3_UNLOCK(unit);
  19037             return BCM_E_CONFIG;
  19038         }
  19039     }
  19040 
  19041     if (l3cfg.l3c_eh_q_tag_type != 0) {
  19042         /* A queue tag has already been configured for this L3 entry. */
  19043         L3_UNLOCK(unit);
  19044         return BCM_E_EXISTS;
  19045     }
  19046 
  19047     /* Replace (vrf, ip_addr) entry's endpoint_id */
  19048     l3cfg.l3c_flags |= BCM_L3_REPLACE;
  19049     l3cfg.l3c_eh_q_tag_type = 2;
  19050     l3cfg.l3c_eh_q_tag = endpoint_id;
  19051     rv = mbcm_driver[unit]->mbcm_l3_ip6_replace(unit, &l3cfg);
  19052     if (BCM_FAILURE(rv)) {
  19053         L3_UNLOCK(unit);
  19054         return rv;
  19055     }
  19056 
  19057     L3_UNLOCK(unit);
  19058 
  19059     return rv;
  19060 }
  19061 
  19062 /*
  19063  * Function:
  19064  *      _bcm_td2_cosq_endpoint_ip6_destroy
  19065  * Purpose:
  19066  *      Destroy an IPv6 endpoint.
  19067  * Parameters:
  19068  *      unit        - (IN) Unit number.
  19069  *      vrf         - (IN) Virtual router instance
  19070  *      ip6_addr    - (IN) IPv6 address
  19071  * Returns:
  19072  *      BCM_E_xxx
  19073  */
  19074 STATIC int
  19075 _bcm_td2_cosq_endpoint_ip6_destroy(
  19076     int unit, 
  19077     bcm_vrf_t vrf,
  19078     bcm_ip6_t ip6_addr)
  19079 {
  19080     int rv;
  19081     _bcm_l3_cfg_t l3cfg;
  19082 
  19083     if ((vrf > SOC_VRF_MAX(unit)) || 
  19084         (vrf < BCM_L3_VRF_DEFAULT)) {
  19085         return BCM_E_PARAM;
  19086     }
  19087 
  19088     L3_LOCK(unit);
  19089 
  19090     /* Get (vrf, ip6_addr) entry */
  19091     sal_memset(&l3cfg, 0, sizeof(_bcm_l3_cfg_t));
  19092     l3cfg.l3c_flags = BCM_L3_IP6;
  19093     l3cfg.l3c_vrf = vrf;
  19094     sal_memcpy(l3cfg.l3c_ip6, ip6_addr, BCM_IP6_ADDRLEN);
  19095     rv = mbcm_driver[unit]->mbcm_l3_ip6_get(unit, &l3cfg);
  19096     if (BCM_FAILURE(rv)) {
  19097         L3_UNLOCK(unit);
  19098         return rv;
  19099     } else {
  19100         /* Make sure the L3 ENTRY is in extender view */
  19101         if (!BCM_TD2_L3_USE_EMBEDDED_NEXT_HOP(unit, l3cfg.l3c_intf, 
  19102                                               BCM_XGS3_L3_INVALID_INDEX)) {
  19103             L3_UNLOCK(unit);
  19104             return BCM_E_CONFIG;
  19105         }
  19106     }
  19107 
  19108     /* Delete (vrf, ip_addr) entry's endpoint_id */
  19109     l3cfg.l3c_flags |= BCM_L3_REPLACE;
  19110     l3cfg.l3c_eh_q_tag_type = 0;
  19111     l3cfg.l3c_eh_q_tag = 0;
  19112     rv = mbcm_driver[unit]->mbcm_l3_ip6_replace(unit, &l3cfg);
  19113     if (BCM_FAILURE(rv)) {
  19114         L3_UNLOCK(unit);
  19115         return rv;
  19116     }
  19117 
  19118     L3_UNLOCK(unit);
  19119 
  19120     return rv;
  19121 }
  19122 
  19123 
  19124 /*
  19125  * Function:
  19126  *      _bcm_td2_cosq_endpoint_L3_egress_create
  19127  * Purpose:
  19128  *      Create a L3 egress endpoint.
  19129  * Parameters:
  19130  *      unit        - (IN) Unit number.
  19131  *      endpoint_id - (IN) Endpoint ID
  19132  *      egress_if   - (IN) egress object ID 
  19133  * Returns:
  19134  *      BCM_E_xxx
  19135  */
  19136 STATIC int
  19137 _bcm_td2_cosq_endpoint_l3_egress_create(
  19138     int unit, 
  19139     int endpoint_id,
  19140     bcm_if_t egress_if)
  19141 {    
  19142     int nh_index;
  19143     ing_l3_next_hop_entry_t nh_entry;
  19144     int eh_tag_type;
  19145     if (!BCM_XGS3_L3_EGRESS_IDX_VALID(unit, egress_if)) {
  19146         return BCM_E_PARAM;
  19147     }
  19148     nh_index = egress_if - BCM_XGS3_EGRESS_IDX_MIN(unit);
  19149     /* Set endpoint ID in next hop entry */
  19150     BCM_IF_ERROR_RETURN
  19151         (READ_ING_L3_NEXT_HOPm(unit, MEM_BLOCK_ANY, nh_index, &nh_entry));
  19152     eh_tag_type = soc_ING_L3_NEXT_HOPm_field32_get(unit, &nh_entry,
  19153             EH_TAG_TYPEf);
  19154     if (eh_tag_type != 0) {
  19155         /* A queue tag has already been configured for this next hop entry. */
  19156         return BCM_E_EXISTS;
  19157     }
  19158     soc_ING_L3_NEXT_HOPm_field32_set(unit, &nh_entry, EH_TAG_TYPEf, 2);
  19159     soc_ING_L3_NEXT_HOPm_field32_set(unit, &nh_entry, EH_QUEUE_TAGf, endpoint_id);
  19160     BCM_IF_ERROR_RETURN
  19161         (WRITE_ING_L3_NEXT_HOPm(unit, MEM_BLOCK_ALL, nh_index, &nh_entry));
  19162     return BCM_E_NONE;
  19163 }
  19164 
  19165 /*
  19166  * Function:
  19167  *      _bcm_td2_cosq_endpoint_gport_destroy
  19168  * Purpose:
  19169  *      Destroy a GPORT endpoint.
  19170  * Parameters:
  19171  *      unit        - (IN) Unit number.
  19172  *      egress_if   - (IN) Egress object.
  19173  * Returns:
  19174  *      BCM_E_xxx
  19175  */
  19176 STATIC int
  19177 _bcm_td2_cosq_endpoint_l3_egress_destroy(
  19178     int unit, 
  19179     bcm_if_t egress_if)
  19180 {    
  19181     int nh_index;
  19182     ing_l3_next_hop_entry_t nh_entry;
  19183     if (!BCM_XGS3_L3_EGRESS_IDX_VALID(unit, egress_if)) {
  19184         return BCM_E_PARAM;
  19185     }
  19186     nh_index = egress_if - BCM_XGS3_EGRESS_IDX_MIN(unit);
  19187     /* Set endpoint ID in next hop entry */
  19188     BCM_IF_ERROR_RETURN
  19189         (READ_ING_L3_NEXT_HOPm(unit, MEM_BLOCK_ANY, nh_index, &nh_entry));
  19190     soc_ING_L3_NEXT_HOPm_field32_set(unit, &nh_entry, EH_TAG_TYPEf, 0);
  19191     soc_ING_L3_NEXT_HOPm_field32_set(unit, &nh_entry, EH_QUEUE_TAGf, 0);
  19192     BCM_IF_ERROR_RETURN
  19193         (WRITE_ING_L3_NEXT_HOPm(unit, MEM_BLOCK_ALL, nh_index, &nh_entry));
  19194     return BCM_E_NONE;
  19195 }
  19196 
  19197 #endif /* INCLUDE_L3 */
  19198 
  19199 /*
  19200  * Function:
  19201  *      _bcm_td2_cosq_endpoint_gport_create
  19202  * Purpose:
  19203  *      Create a GPORT endpoint.
  19204  * Parameters:
  19205  *      unit        - (IN) Unit number.
  19206  *      endpoint_id - (IN) Endpoint ID
  19207  *      gport       - (IN) GPORT ID 
  19208  * Returns:
  19209  *      BCM_E_xxx
  19210  */
  19211 STATIC int
  19212 _bcm_td2_cosq_endpoint_gport_create(
  19213     int unit, 
  19214     int endpoint_id,
  19215     bcm_gport_t gport)
  19216 {
  19217     int vp;
  19218     ing_dvp_table_entry_t dvp_entry;
  19219     int nh_index;
  19220     ing_l3_next_hop_entry_t nh_entry;
  19221     int eh_tag_type;
  19222 
  19223     /* Get virtual port value */
  19224     if (BCM_GPORT_IS_VLAN_PORT(gport)) {
  19225         vp = BCM_GPORT_VLAN_PORT_ID_GET(gport);
  19226 #if defined(INCLUDE_L3)
  19227         if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeVlan)) {
  19228             /* VP is not configured yet */
  19229             return BCM_E_CONFIG;
  19230         }
  19231 #endif
  19232     } else if (BCM_GPORT_IS_NIV_PORT(gport)) {
  19233         vp = BCM_GPORT_NIV_PORT_ID_GET(gport);
  19234 #if defined(INCLUDE_L3)
  19235         if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeNiv)) {
  19236             /* VP is not configured yet */
  19237             return BCM_E_CONFIG;
  19238         }
  19239 #endif
  19240     } else if (BCM_GPORT_IS_MPLS_PORT(gport)) {
  19241         vp = BCM_GPORT_MPLS_PORT_ID_GET(gport);
  19242 #if defined(INCLUDE_L3)
  19243         if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) {
  19244             /* VP is not configured yet */
  19245             return BCM_E_CONFIG;
  19246         }
  19247 #endif
  19248     } else {
  19249        return BCM_E_PARAM;
  19250     } 
  19251 
  19252     /* Get VP's next hop index */
  19253     BCM_IF_ERROR_RETURN
  19254         (READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp_entry));
  19255     nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp_entry,
  19256             NEXT_HOP_INDEXf);
  19257 
  19258     /* Set endpoint ID in next hop entry */
  19259     BCM_IF_ERROR_RETURN
  19260         (READ_ING_L3_NEXT_HOPm(unit, MEM_BLOCK_ANY, nh_index, &nh_entry));
  19261     eh_tag_type = soc_ING_L3_NEXT_HOPm_field32_get(unit, &nh_entry,
  19262             EH_TAG_TYPEf);
  19263     if (eh_tag_type != 0) {
  19264         /* A queue tag has already been configured for this next hop entry. */
  19265         return BCM_E_EXISTS;
  19266     }
  19267     soc_ING_L3_NEXT_HOPm_field32_set(unit, &nh_entry, EH_TAG_TYPEf, 2);
  19268     soc_ING_L3_NEXT_HOPm_field32_set(unit, &nh_entry, EH_QUEUE_TAGf, endpoint_id);
  19269     BCM_IF_ERROR_RETURN
  19270         (WRITE_ING_L3_NEXT_HOPm(unit, MEM_BLOCK_ALL, nh_index, &nh_entry));
  19271 
  19272     return BCM_E_NONE;
  19273 }
  19274 
  19275 /*
  19276  * Function:
  19277  *      _bcm_td2_cosq_endpoint_gport_destroy
  19278  * Purpose:
  19279  *      Destroy a GPORT endpoint.
  19280  * Parameters:
  19281  *      unit        - (IN) Unit number.
  19282  *      gport       - (IN) GPORT ID 
  19283  * Returns:
  19284  *      BCM_E_xxx
  19285  */
  19286 STATIC int
  19287 _bcm_td2_cosq_endpoint_gport_destroy(
  19288     int unit, 
  19289     bcm_gport_t gport)
  19290 {
  19291     int vp;
  19292     ing_dvp_table_entry_t dvp_entry;
  19293     int nh_index;
  19294     ing_l3_next_hop_entry_t nh_entry;
  19295 
  19296     /* Get virtual port value */
  19297     if (BCM_GPORT_IS_VLAN_PORT(gport)) {
  19298         vp = BCM_GPORT_VLAN_PORT_ID_GET(gport);
  19299 #if defined(INCLUDE_L3)
  19300         if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeVlan)) {
  19301             /* VP is not configured yet */
  19302             return BCM_E_CONFIG;
  19303         }
  19304 #endif
  19305     } else if (BCM_GPORT_IS_NIV_PORT(gport)) {
  19306         vp = BCM_GPORT_NIV_PORT_ID_GET(gport);
  19307 #if defined(INCLUDE_L3)
  19308         if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeNiv)) {
  19309             /* VP is not configured yet */
  19310             return BCM_E_CONFIG;
  19311         }
  19312 #endif
  19313     } else if (BCM_GPORT_IS_MPLS_PORT(gport)) {
  19314         vp = BCM_GPORT_MPLS_PORT_ID_GET(gport);
  19315 #if defined(INCLUDE_L3)
  19316         if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) {
  19317             /* VP is not configured yet */
  19318             return BCM_E_CONFIG;
  19319         }
  19320 #endif
  19321     } else {
  19322        return BCM_E_PARAM;
  19323     } 
  19324 
  19325     /* Get VP's next hop index */
  19326     BCM_IF_ERROR_RETURN
  19327         (READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp_entry));
  19328     nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp_entry,
  19329             NEXT_HOP_INDEXf);
  19330 
  19331     /* Delete endpoint ID in next hop entry */
  19332     BCM_IF_ERROR_RETURN
  19333         (READ_ING_L3_NEXT_HOPm(unit, MEM_BLOCK_ANY, nh_index, &nh_entry));
  19334     soc_ING_L3_NEXT_HOPm_field32_set(unit, &nh_entry, EH_TAG_TYPEf, 0);
  19335     soc_ING_L3_NEXT_HOPm_field32_set(unit, &nh_entry, EH_QUEUE_TAGf, 0);
  19336     BCM_IF_ERROR_RETURN
  19337         (WRITE_ING_L3_NEXT_HOPm(unit, MEM_BLOCK_ALL, nh_index, &nh_entry));
  19338 
  19339     return BCM_E_NONE;
  19340 }
  19341 
  19342 /*
  19343  * Function:
  19344  *      bcm_td2_cosq_endpoint_create
  19345  * Purpose:
  19346  *      Create an endpoint.
  19347  * Parameters:
  19348  *      unit          - (IN) Unit number.
  19349  *      classifier    - (IN) Classifier attributes
  19350  *      classifier_id - (IN/OUT) Classifier ID
  19351  * Returns:
  19352  *      BCM_E_xxx
  19353  */
  19354 int
  19355 bcm_td2_cosq_endpoint_create(
  19356     int unit, 
  19357     bcm_cosq_classifier_t *classifier, 
  19358     int *classifier_id)
  19359 {
  19360     int endpoint_id = 0;
  19361     int i;
  19362 
  19363     if (NULL == classifier || NULL == classifier_id) {
  19364         return BCM_E_PARAM;
  19365     }
  19366 
  19367     if (classifier->flags & BCM_COSQ_CLASSIFIER_WITH_ID) {
  19368         if (!_BCM_COSQ_CLASSIFIER_IS_ENDPOINT(*classifier_id)) {
  19369             return BCM_E_PARAM;
  19370         }
  19371         endpoint_id = _BCM_COSQ_CLASSIFIER_ENDPOINT_GET(*classifier_id);
  19372         if (endpoint_id >= _BCM_TD2_NUM_ENDPOINT(unit)) {
  19373             return BCM_E_PARAM;
  19374         }
  19375         if (_BCM_TD2_ENDPOINT_IS_USED(unit, endpoint_id)) {
  19376             return BCM_E_EXISTS;
  19377         }
  19378     } else {
  19379         /* Get a free endpoint ID */
  19380         for (i = 0; i < _BCM_TD2_NUM_ENDPOINT(unit); i++) {
  19381             if (!_BCM_TD2_ENDPOINT_IS_USED(unit, i)) {
  19382                 endpoint_id = i;
  19383                 break;
  19384             }
  19385         }
  19386         if (i == _BCM_TD2_NUM_ENDPOINT(unit)) {
  19387             /* No available endpoint ID */
  19388             return BCM_E_RESOURCE;
  19389         }
  19390     }
  19391     _BCM_TD2_ENDPOINT(unit, endpoint_id) = sal_alloc(
  19392             sizeof(_bcm_td2_endpoint_t), "Endpoint Info");
  19393     if (NULL == _BCM_TD2_ENDPOINT(unit, endpoint_id)) {
  19394         return BCM_E_MEMORY;
  19395     }
  19396     sal_memset(_BCM_TD2_ENDPOINT(unit, endpoint_id), 0,
  19397             sizeof(_bcm_td2_endpoint_t));
  19398 
  19399     if (classifier->flags & BCM_COSQ_CLASSIFIER_L2) {
  19400         _BCM_TD2_ENDPOINT(unit, endpoint_id)->flags = BCM_COSQ_CLASSIFIER_L2;
  19401         _BCM_TD2_ENDPOINT(unit, endpoint_id)->vlan = classifier->vlan;
  19402         sal_memcpy(_BCM_TD2_ENDPOINT(unit, endpoint_id)->mac, classifier->mac,
  19403                 sizeof(bcm_mac_t));
  19404         BCM_IF_ERROR_RETURN(_bcm_td2_cosq_endpoint_l2_create(unit,
  19405                     endpoint_id, classifier->vlan, classifier->mac));
  19406     } else if (classifier->flags & BCM_COSQ_CLASSIFIER_L3) {
  19407 #if defined(INCLUDE_L3)
  19408         _BCM_TD2_ENDPOINT(unit, endpoint_id)->flags = BCM_COSQ_CLASSIFIER_L3;
  19409         _BCM_TD2_ENDPOINT(unit, endpoint_id)->vrf = classifier->vrf;
  19410         if (classifier->flags & BCM_COSQ_CLASSIFIER_IP6) {
  19411             _BCM_TD2_ENDPOINT(unit, endpoint_id)->flags |= BCM_COSQ_CLASSIFIER_IP6;
  19412             sal_memcpy(_BCM_TD2_ENDPOINT(unit, endpoint_id)->ip6_addr,
  19413                     classifier->ip6_addr, BCM_IP6_ADDRLEN);
  19414             BCM_IF_ERROR_RETURN(_bcm_td2_cosq_endpoint_ip6_create(unit,
  19415                         endpoint_id, classifier->vrf, classifier->ip6_addr));
  19416         } else {
  19417             _BCM_TD2_ENDPOINT(unit, endpoint_id)->ip_addr = classifier->ip_addr;
  19418             BCM_IF_ERROR_RETURN(_bcm_td2_cosq_endpoint_ip4_create(unit,
  19419                         endpoint_id, classifier->vrf, classifier->ip_addr));
  19420         }
  19421 #endif /* INCLUDE_L3 */
  19422     } else if (classifier->flags & BCM_COSQ_CLASSIFIER_GPORT) {
  19423         _BCM_TD2_ENDPOINT(unit, endpoint_id)->flags = BCM_COSQ_CLASSIFIER_GPORT;
  19424         _BCM_TD2_ENDPOINT(unit, endpoint_id)->gport = classifier->gport;
  19425         BCM_IF_ERROR_RETURN(_bcm_td2_cosq_endpoint_gport_create(unit,
  19426                     endpoint_id, classifier->gport));
  19427     } else if (classifier->flags & BCM_COSQ_CLASSIFIER_L3_EGRESS) {
  19428 #if defined(INCLUDE_L3)
  19429         _BCM_TD2_ENDPOINT(unit, endpoint_id)->flags = BCM_COSQ_CLASSIFIER_L3_EGRESS;
  19430         _BCM_TD2_ENDPOINT(unit, endpoint_id)->egress_if = classifier->egress_if;
  19431         BCM_IF_ERROR_RETURN(_bcm_td2_cosq_endpoint_l3_egress_create(unit,
  19432                     endpoint_id, classifier->egress_if));
  19433 #endif /* INCLUDE_L3 */
  19434     } else {
  19435         return BCM_E_PARAM;
  19436     }
  19437 
  19438     _BCM_COSQ_CLASSIFIER_ENDPOINT_SET(*classifier_id, endpoint_id);
  19439 
  19440     return BCM_E_NONE;
  19441 }
  19442 
  19443 /*
  19444  * Function:
  19445  *      bcm_td2_cosq_endpoint_destroy
  19446  * Purpose:
  19447  *      Destroy an endpoint.
  19448  * Parameters:
  19449  *      unit          - (IN) Unit number.
  19450  *      classifier_id - (IN) Classifier ID
  19451  * Returns:
  19452  *      BCM_E_xxx
  19453  */
  19454 int
  19455 bcm_td2_cosq_endpoint_destroy(
  19456     int unit, 
  19457     int classifier_id)
  19458 {
  19459     int endpoint_id;
  19460 
  19461     if (!_BCM_COSQ_CLASSIFIER_IS_ENDPOINT(classifier_id)) {
  19462         return BCM_E_PARAM;
  19463     }
  19464     endpoint_id = _BCM_COSQ_CLASSIFIER_ENDPOINT_GET(classifier_id);
  19465     if (endpoint_id >= _BCM_TD2_NUM_ENDPOINT(unit)) {
  19466         return BCM_E_PARAM;
  19467     }
  19468     if (!_BCM_TD2_ENDPOINT_IS_USED(unit, endpoint_id)) {
  19469         return BCM_E_NOT_FOUND;
  19470     }
  19471 
  19472     if (_BCM_TD2_ENDPOINT(unit, endpoint_id)->flags &
  19473             BCM_COSQ_CLASSIFIER_L2) {
  19474         BCM_IF_ERROR_RETURN(_bcm_td2_cosq_endpoint_l2_destroy(unit,
  19475                     _BCM_TD2_ENDPOINT(unit, endpoint_id)->vlan,
  19476                     _BCM_TD2_ENDPOINT(unit, endpoint_id)->mac));
  19477     } else if (_BCM_TD2_ENDPOINT(unit, endpoint_id)->flags &
  19478             BCM_COSQ_CLASSIFIER_L3) {
  19479 #if defined(INCLUDE_L3)
  19480         if (_BCM_TD2_ENDPOINT(unit, endpoint_id)->flags &
  19481                 BCM_COSQ_CLASSIFIER_IP6) {
  19482             BCM_IF_ERROR_RETURN(_bcm_td2_cosq_endpoint_ip6_destroy(unit,
  19483                         _BCM_TD2_ENDPOINT(unit, endpoint_id)->vrf,
  19484                         _BCM_TD2_ENDPOINT(unit, endpoint_id)->ip6_addr));
  19485         } else {
  19486             BCM_IF_ERROR_RETURN(_bcm_td2_cosq_endpoint_ip4_destroy(unit,
  19487                         _BCM_TD2_ENDPOINT(unit, endpoint_id)->vrf,
  19488                         _BCM_TD2_ENDPOINT(unit, endpoint_id)->ip_addr));
  19489         }
  19490 #endif
  19491     } else if (_BCM_TD2_ENDPOINT(unit, endpoint_id)->flags &
  19492             BCM_COSQ_CLASSIFIER_GPORT) {
  19493         BCM_IF_ERROR_RETURN(_bcm_td2_cosq_endpoint_gport_destroy(unit,
  19494                     _BCM_TD2_ENDPOINT(unit, endpoint_id)->gport));
  19495     } else if (_BCM_TD2_ENDPOINT(unit, endpoint_id)->flags &
  19496                BCM_COSQ_CLASSIFIER_L3_EGRESS) {
  19497 #if defined(INCLUDE_L3)
  19498         BCM_IF_ERROR_RETURN(
  19499             _bcm_td2_cosq_endpoint_l3_egress_destroy(
  19500                 unit, _BCM_TD2_ENDPOINT(unit, endpoint_id)->egress_if));
  19501 #endif
  19502     } else {
  19503         return BCM_E_INTERNAL;
  19504     }
  19505 
  19506     sal_free(_BCM_TD2_ENDPOINT(unit, endpoint_id));
  19507     _BCM_TD2_ENDPOINT(unit, endpoint_id) = NULL;
  19508 
  19509     return BCM_E_NONE;
  19510 }
  19511 
  19512 /*
  19513  * Function:
  19514  *      bcm_td2_cosq_endpoint_get
  19515  * Purpose:
  19516  *      Get info about an endpoint.
  19517  * Parameters:
  19518  *      unit          - (IN) Unit number.
  19519  *      classifier_id - (IN) Classifier ID
  19520  *      classifier    - (OUT) Classifier info
  19521  * Returns:
  19522  *      BCM_E_xxx
  19523  */
  19524 int
  19525 bcm_td2_cosq_endpoint_get(
  19526     int unit, 
  19527     int classifier_id,
  19528     bcm_cosq_classifier_t *classifier)
  19529 {
  19530     int endpoint_id;
  19531 
  19532     if (!_BCM_COSQ_CLASSIFIER_IS_ENDPOINT(classifier_id)) {
  19533         return BCM_E_PARAM;
  19534     }
  19535     endpoint_id = _BCM_COSQ_CLASSIFIER_ENDPOINT_GET(classifier_id);
  19536     if (endpoint_id >= _BCM_TD2_NUM_ENDPOINT(unit)) {
  19537         return BCM_E_PARAM;
  19538     }
  19539     if (!_BCM_TD2_ENDPOINT_IS_USED(unit, endpoint_id)) {
  19540         return BCM_E_NOT_FOUND;
  19541     }
  19542 
  19543     classifier->flags = _BCM_TD2_ENDPOINT(unit, endpoint_id)->flags;
  19544     classifier->vlan = _BCM_TD2_ENDPOINT(unit, endpoint_id)->vlan;
  19545     sal_memcpy(classifier->mac, _BCM_TD2_ENDPOINT(unit, endpoint_id)->mac,
  19546             sizeof(bcm_mac_t));
  19547     classifier->vrf = _BCM_TD2_ENDPOINT(unit, endpoint_id)->vrf;
  19548     classifier->ip_addr = _BCM_TD2_ENDPOINT(unit, endpoint_id)->ip_addr;
  19549     sal_memcpy(classifier->ip6_addr,
  19550             _BCM_TD2_ENDPOINT(unit, endpoint_id)->ip6_addr, BCM_IP6_ADDRLEN);
  19551     classifier->gport = _BCM_TD2_ENDPOINT(unit, endpoint_id)->gport;
  19552     classifier->egress_if = _BCM_TD2_ENDPOINT(unit, endpoint_id)->egress_if;
  19553     return BCM_E_NONE;
  19554 }
  19555 
  19556 /*
  19557  * Function:
  19558  *      bcm_td2_cosq_endpoint_map_set
  19559  * Purpose:
  19560  *      Set the mapping from port, classifier, and multiple internal priorities
  19561  *      to multiple COS queues in a queue group.
  19562  * Parameters:
  19563  *      unit           - (IN) Unit number.
  19564  *      port           - (IN) local port ID
  19565  *      classifier_id  - (IN) Classifier ID
  19566  *      queue_group    - (IN) Base queue ID
  19567  *      array_count    - (IN) Number of elements in priority_array and
  19568  *                            cosq_array
  19569  *      priority_array - (IN) Array of internal priorities
  19570  *      cosq_array     - (IN) Array of COS queues
  19571  * Returns:
  19572  *      BCM_E_xxx
  19573  */
  19574 int
  19575 bcm_td2_cosq_endpoint_map_set(
  19576     int unit, 
  19577     bcm_port_t port, 
  19578     int classifier_id, 
  19579     bcm_gport_t queue_group, 
  19580     int array_count, 
  19581     bcm_cos_t *priority_array, 
  19582     bcm_cos_queue_t *cosq_array)
  19583 {
  19584     int rv = BCM_E_NONE;
  19585     int endpoint_id;
  19586     int qid;
  19587     int num_entries_per_profile;
  19588     int alloc_size;
  19589     endpoint_cos_map_entry_t *entry_array = NULL;
  19590     void *entries[1];
  19591     endpoint_queue_map_entry_t qmap_key, qmap_data, qmap_entry;
  19592     int qmap_index;
  19593     int old_profile_index, new_profile_index;
  19594     int endpoint_cos_map_prof_idx;
  19595     int old_qid;
  19596     int i;
  19597     int priority;
  19598     uint64 rval64;
  19599 
  19600     if (!_BCM_COSQ_CLASSIFIER_IS_ENDPOINT(classifier_id)) {
  19601         return BCM_E_PARAM;
  19602     }
  19603     endpoint_id = _BCM_COSQ_CLASSIFIER_ENDPOINT_GET(classifier_id);
  19604     if (endpoint_id >= _BCM_TD2_NUM_ENDPOINT(unit)) {
  19605         return BCM_E_PARAM;
  19606     }
  19607     if (!_BCM_TD2_ENDPOINT_IS_USED(unit, endpoint_id)) {
  19608         return BCM_E_PARAM;
  19609     }
  19610 
  19611     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(queue_group)) {
  19612         int pipe;
  19613         _bcm_td2_cosq_node_t *node;
  19614 
  19615         BCM_IF_ERROR_RETURN(_bcm_td2_cosq_node_get(unit, queue_group, 0, NULL,
  19616                                                    NULL, NULL, &node));
  19617         if (port != node->local_port) {
  19618             return BCM_E_PARAM;
  19619         }
  19620         pipe = _BCM_TD2_PORT_TO_PIPE(unit, port);
  19621         qid  = (pipe == _TD2_XPIPE)? node->hw_index: node->hw_index + 2048;
  19622     } else {
  19623         return BCM_E_PARAM;
  19624     }
  19625 
  19626     /* Allocate an Endpoint CoS Map profile */
  19627     num_entries_per_profile = _TD2_EPCM_ENTRIES_PER_SET;
  19628     alloc_size = sizeof(endpoint_cos_map_entry_t) * num_entries_per_profile;
  19629     entry_array = sal_alloc(alloc_size, "Endpoint CoS Map Profile");
  19630     if (NULL == entry_array) {
  19631         return BCM_E_MEMORY;
  19632     }
  19633     sal_memset(entry_array, 0, alloc_size);
  19634 
  19635     /* Search Endpoint Queue Map table */
  19636     sal_memcpy(&qmap_key, soc_mem_entry_null(unit,
  19637                 ENDPOINT_QUEUE_MAPm), sizeof(endpoint_queue_map_entry_t));
  19638     soc_ENDPOINT_QUEUE_MAPm_field32_set(unit, &qmap_key, KEY_TYPEf, 0);
  19639     soc_ENDPOINT_QUEUE_MAPm_field32_set(unit, &qmap_key, DEST_PORTf, port);
  19640     soc_ENDPOINT_QUEUE_MAPm_field32_set(unit, &qmap_key, EH_QUEUE_TAGf,
  19641             endpoint_id);
  19642     rv = soc_mem_search(unit, ENDPOINT_QUEUE_MAPm, MEM_BLOCK_ANY,
  19643             &qmap_index, &qmap_key, &qmap_data, 0);
  19644     if (rv == SOC_E_NOT_FOUND) {
  19645         old_profile_index = -1;
  19646     } else if (rv == SOC_E_NONE) {
  19647         /* Existing entry found. Compare base queue ID and extract
  19648          * old Endpoint CoS Map profile.
  19649          */
  19650         old_qid = soc_ENDPOINT_QUEUE_MAPm_field32_get(unit,
  19651                 &qmap_data, ENDPOINT_QUEUE_BASEf);
  19652         if (old_qid != qid) {
  19653             /* The classifier is already mapped to another queue group */
  19654             sal_free(entry_array);
  19655             return BCM_E_EXISTS;
  19656         }
  19657         endpoint_cos_map_prof_idx = soc_ENDPOINT_QUEUE_MAPm_field32_get(unit,
  19658                 &qmap_data, ENDPOINT_COS_MAP_PROFILE_INDEXf);
  19659         entries[0] = entry_array;
  19660         /* 
  19661          * The index of ENDPOINT_COS_MAP = 
  19662          * ENDPOINT_COS_MAP_PROFILE_INDEX * 16 + INT_PRI
  19663          */
  19664         old_profile_index = endpoint_cos_map_prof_idx * num_entries_per_profile;
  19665         rv = soc_profile_mem_get(unit, _BCM_TD2_ENDPOINT_COS_MAP_PROFILE(unit),
  19666                 old_profile_index, num_entries_per_profile, entries);
  19667         if (SOC_FAILURE(rv)) {
  19668             sal_free(entry_array);
  19669             return rv;
  19670         }
  19671     } else {
  19672         sal_free(entry_array);
  19673         return rv;
  19674     }
  19675 
  19676     /* Construct or modify Endpoint CoS Map profile and add it */
  19677     for (i = 0; i < array_count; i++) {
  19678         priority = priority_array[i];
  19679         if (priority < 0 || priority >= 16) {
  19680             sal_free(entry_array);
  19681             return BCM_E_PARAM;
  19682         }
  19683         soc_ENDPOINT_COS_MAPm_field32_set(unit, &entry_array[priority],
  19684                 ENDPOINT_COS_OFFSETf, cosq_array[i]);
  19685     }
  19686     entries[0] = entry_array;
  19687     rv = soc_profile_mem_add(unit, _BCM_TD2_ENDPOINT_COS_MAP_PROFILE(unit),
  19688             entries, num_entries_per_profile, (uint32 *)&new_profile_index);
  19689     sal_free(entry_array);
  19690     if (SOC_FAILURE(rv)) {
  19691         return rv;
  19692     }
  19693 
  19694     /* Insert or replace Endpoint Queue Map entry */
  19695     sal_memcpy(&qmap_entry, &qmap_key, sizeof(endpoint_queue_map_entry_t));
  19696     soc_ENDPOINT_QUEUE_MAPm_field32_set(unit, &qmap_entry, VALIDf, 1);
  19697     soc_ENDPOINT_QUEUE_MAPm_field32_set(unit, &qmap_entry,
  19698             ENDPOINT_QUEUE_BASEf, qid);
  19699     endpoint_cos_map_prof_idx = new_profile_index / num_entries_per_profile;
  19700     soc_ENDPOINT_QUEUE_MAPm_field32_set(unit, &qmap_entry,
  19701             ENDPOINT_COS_MAP_PROFILE_INDEXf, endpoint_cos_map_prof_idx);
  19702     rv = soc_mem_insert(unit, ENDPOINT_QUEUE_MAPm, MEM_BLOCK_ALL, &qmap_entry);
  19703     if (SOC_FAILURE(rv) && rv != SOC_E_EXISTS) {
  19704         return rv;
  19705     }
  19706 
  19707     /* Delete old Endpoint CoS Map profile */
  19708     if (old_profile_index != -1) {
  19709         SOC_IF_ERROR_RETURN
  19710             (soc_profile_mem_delete(unit,
  19711                                     _BCM_TD2_ENDPOINT_COS_MAP_PROFILE(unit),
  19712                                     old_profile_index));
  19713     }
  19714 
  19715     /* Set port's queuing mode to be endpoint queuing */
  19716     SOC_IF_ERROR_RETURN(READ_ING_COS_MODE_64r(unit, port, &rval64));
  19717     if (4 != soc_reg64_field32_get(unit, ING_COS_MODE_64r, rval64,
  19718                 QUEUE_MODEf)) {
  19719         soc_reg64_field32_set(unit, ING_COS_MODE_64r, &rval64, QUEUE_MODEf, 4);
  19720         SOC_IF_ERROR_RETURN(WRITE_ING_COS_MODE_64r(unit, port, rval64));
  19721     }
  19722 
  19723     return rv;
  19724 }
  19725 
  19726 /*
  19727  * Function:
  19728  *      bcm_td2_cosq_endpoint_map_get
  19729  * Purpose:
  19730  *      Get the mapping from port, classifier, and multiple internal priorities
  19731  *      to multiple COS queues in a queue group.
  19732  * Parameters:
  19733  *      unit           - (IN) Unit number.
  19734  *      port           - (IN) Local port ID
  19735  *      classifier_id  - (IN) Classifier ID
  19736  *      queue_group    - (OUT) Queue group
  19737  *      array_max      - (IN) Size of priority_array and cosq_array
  19738  *      priority_array - (IN) Array of internal priorities
  19739  *      cosq_array     - (OUT) Array of COS queues
  19740  *      array_count    - (OUT) Size of cosq_array
  19741  * Returns:
  19742  *      BCM_E_xxx
  19743  */
  19744 int
  19745 bcm_td2_cosq_endpoint_map_get(
  19746     int unit, 
  19747     bcm_port_t port, 
  19748     int classifier_id, 
  19749     bcm_gport_t *queue_group, 
  19750     int array_max, 
  19751     bcm_cos_t *priority_array, 
  19752     bcm_cos_queue_t *cosq_array, 
  19753     int *array_count)
  19754 {
  19755     int rv = BCM_E_NONE;
  19756     int endpoint_id;
  19757     endpoint_queue_map_entry_t qmap_key, qmap_data;
  19758     int qmap_index;
  19759     int qid;
  19760     int num_entries_per_profile;
  19761     int alloc_size;
  19762     endpoint_cos_map_entry_t *entry_array = NULL;
  19763     void *entries[1];
  19764     int profile_index;
  19765     int endpoint_cos_map_prof_idx;
  19766     int i;
  19767     int priority;
  19768     int pipe, hw_index, qmin, qmax;
  19769     _bcm_td2_pipe_resources_t *res = NULL;
  19770 
  19771     if (!_BCM_COSQ_CLASSIFIER_IS_ENDPOINT(classifier_id)) {
  19772         return BCM_E_PARAM;
  19773     }
  19774     endpoint_id = _BCM_COSQ_CLASSIFIER_ENDPOINT_GET(classifier_id);
  19775     if (endpoint_id >= _BCM_TD2_NUM_ENDPOINT(unit)) {
  19776         return BCM_E_PARAM;
  19777     }
  19778     if (!_BCM_TD2_ENDPOINT_IS_USED(unit, endpoint_id)) {
  19779         return BCM_E_PARAM;
  19780     }
  19781 
  19782     /* Search Endpoint Queue Map table */
  19783     sal_memcpy(&qmap_key, soc_mem_entry_null(unit,
  19784                 ENDPOINT_QUEUE_MAPm), sizeof(endpoint_queue_map_entry_t));
  19785     soc_ENDPOINT_QUEUE_MAPm_field32_set(unit, &qmap_key, KEY_TYPEf, 0);
  19786     soc_ENDPOINT_QUEUE_MAPm_field32_set(unit, &qmap_key, DEST_PORTf, port);
  19787     soc_ENDPOINT_QUEUE_MAPm_field32_set(unit, &qmap_key, EH_QUEUE_TAGf,
  19788             endpoint_id);
  19789     SOC_IF_ERROR_RETURN(soc_mem_search(unit, ENDPOINT_QUEUE_MAPm, MEM_BLOCK_ANY,
  19790                 &qmap_index, &qmap_key, &qmap_data, 0));
  19791 
  19792     /* Get queue group */
  19793     qid = soc_ENDPOINT_QUEUE_MAPm_field32_get(unit, &qmap_data,
  19794             ENDPOINT_QUEUE_BASEf);
  19795     pipe = _BCM_TD2_PORT_TO_PIPE(unit, port);
  19796     res = _BCM_TD2_PRESOURCES(_bcm_td2_mmu_info[unit], pipe);
  19797     hw_index = (pipe == _TD2_XPIPE)? qid: qid - 2048;
  19798 
  19799     qmin = res->num_base_queues + (pipe * _BCM_TD2_NUM_L2_UC_LEAVES_PER_PIPE);
  19800     qmax = (pipe + 1) * _BCM_TD2_NUM_L2_UC_LEAVES_PER_PIPE;
  19801 
  19802     for (i = qmin; i < qmax; i++) {
  19803         if ((res->p_queue_node[i].local_port == port) &&
  19804             (res->p_queue_node[i].hw_index == hw_index)) {
  19805             *queue_group = res->p_queue_node[i].gport;
  19806             break;
  19807         }
  19808     }
  19809 
  19810     if (i == qmax) {
  19811         return BCM_E_NOT_FOUND;
  19812     }
  19813 
  19814     /* Get Endpoint CoS Map profile */
  19815     num_entries_per_profile = _TD2_EPCM_ENTRIES_PER_SET;
  19816     alloc_size = sizeof(endpoint_cos_map_entry_t) * num_entries_per_profile;
  19817     entry_array = sal_alloc(alloc_size, "Endpoint CoS Map Profile");
  19818     if (NULL == entry_array) {
  19819         return BCM_E_MEMORY;
  19820     }
  19821     sal_memset(entry_array, 0, alloc_size);
  19822     entries[0] = entry_array;
  19823     endpoint_cos_map_prof_idx = soc_ENDPOINT_QUEUE_MAPm_field32_get(unit, &qmap_data,
  19824             ENDPOINT_COS_MAP_PROFILE_INDEXf);
  19825     /* 
  19826      * The index of ENDPOINT_COS_MAP = 
  19827      * ENDPOINT_COS_MAP_PROFILE_INDEX * 16 + INT_PRI
  19828      */
  19829     profile_index = endpoint_cos_map_prof_idx * num_entries_per_profile;
  19830     rv = soc_profile_mem_get(unit, _BCM_TD2_ENDPOINT_COS_MAP_PROFILE(unit),
  19831             profile_index, num_entries_per_profile, entries);
  19832     if (SOC_FAILURE(rv)) {
  19833         sal_free(entry_array);
  19834         return rv;
  19835     }
  19836 
  19837     /* Get internal priority to CoS mapping */
  19838     if (array_max == 0) {
  19839         if (NULL != array_count) {
  19840             *array_count = num_entries_per_profile;
  19841         }
  19842     } else {
  19843         *array_count = 0;
  19844         for (i = 0; i < array_max; i++) {
  19845             priority = priority_array[i];
  19846             if (priority < 0 || priority >= 16) {
  19847                 sal_free(entry_array);
  19848                 return BCM_E_PARAM;
  19849             }
  19850             cosq_array[i] = soc_ENDPOINT_COS_MAPm_field32_get(unit,
  19851                     &entry_array[priority], ENDPOINT_COS_OFFSETf);
  19852             (*array_count)++;
  19853         }
  19854     }
  19855 
  19856     sal_free(entry_array);
  19857     return rv;
  19858 }
  19859 
  19860 /*
  19861  * Function:
  19862  *      bcm_td2_cosq_endpoint_map_clear
  19863  * Purpose:
  19864  *      Clear the mapping from port, classifier, and internal priorities
  19865  *      to COS queues in a queue group.
  19866  * Parameters:
  19867  *      unit          - (IN) Unit number.
  19868  *      port          - (IN) Local port ID
  19869  *      classifier_id - (IN) Classifier ID
  19870  * Returns:
  19871  *      BCM_E_xxx
  19872  */
  19873 int
  19874 bcm_td2_cosq_endpoint_map_clear(
  19875     int unit, 
  19876     bcm_gport_t port, 
  19877     int classifier_id)
  19878 {
  19879     int endpoint_id;
  19880     endpoint_queue_map_entry_t qmap_key, qmap_data;
  19881     int profile_index;
  19882     int endpoint_cos_map_prof_idx;
  19883 
  19884     if (!_BCM_COSQ_CLASSIFIER_IS_ENDPOINT(classifier_id)) {
  19885         return BCM_E_PARAM;
  19886     }
  19887     endpoint_id = _BCM_COSQ_CLASSIFIER_ENDPOINT_GET(classifier_id);
  19888     if (endpoint_id >= _BCM_TD2_NUM_ENDPOINT(unit)) {
  19889         return BCM_E_PARAM;
  19890     }
  19891     if (!_BCM_TD2_ENDPOINT_IS_USED(unit, endpoint_id)) {
  19892         return BCM_E_PARAM;
  19893     }
  19894 
  19895     /* Delete (port, endpoint_id) entry from Endpoint Queue Map table */
  19896     sal_memcpy(&qmap_key, soc_mem_entry_null(unit,
  19897                 ENDPOINT_QUEUE_MAPm), sizeof(endpoint_queue_map_entry_t));
  19898     soc_ENDPOINT_QUEUE_MAPm_field32_set(unit, &qmap_key, KEY_TYPEf, 0);
  19899     soc_ENDPOINT_QUEUE_MAPm_field32_set(unit, &qmap_key, DEST_PORTf, port);
  19900     soc_ENDPOINT_QUEUE_MAPm_field32_set(unit, &qmap_key, EH_QUEUE_TAGf,
  19901             endpoint_id);
  19902     SOC_IF_ERROR_RETURN(soc_mem_delete_return_old(unit, ENDPOINT_QUEUE_MAPm,
  19903                 MEM_BLOCK_ALL, &qmap_key, &qmap_data));
  19904 
  19905     /* Delete priority to CoS mapping profile */
  19906     endpoint_cos_map_prof_idx = soc_ENDPOINT_QUEUE_MAPm_field32_get(unit, &qmap_data,
  19907             ENDPOINT_COS_MAP_PROFILE_INDEXf);
  19908     /* 
  19909      * The index of ENDPOINT_COS_MAP = 
  19910      * ENDPOINT_COS_MAP_PROFILE_INDEX * 16 + INT_PRI
  19911      */
  19912     profile_index = endpoint_cos_map_prof_idx * 16;
  19913     SOC_IF_ERROR_RETURN(soc_profile_mem_delete(unit,
  19914                 _BCM_TD2_ENDPOINT_COS_MAP_PROFILE(unit), profile_index));
  19915 
  19916     return BCM_E_NONE;
  19917 }
  19918 
  19919 /*
  19920  * Function:
  19921  *      bcm_td2_cosq_field_classifier_get
  19922  * Purpose:
  19923  *      Get classifier type information.
  19924  * Parameters:
  19925  *      unit          - (IN) Unit number.
  19926  *      classifier_id - (IN) Classifier ID
  19927  *      classifier    - (OUT) Classifier info
  19928  * Returns:
  19929  *      BCM_E_xxx
  19930  */
  19931 int
  19932 bcm_td2_cosq_field_classifier_get(
  19933     int unit,    
  19934     int classifier_id,
  19935     bcm_cosq_classifier_t *classifier)
  19936 {
  19937     if (classifier == NULL) {
  19938         return BCM_E_PARAM;
  19939     }
  19940     sal_memset(classifier, 0, sizeof(bcm_cosq_classifier_t));
  19941 
  19942     if (_BCM_COSQ_CLASSIFIER_IS_FIELD(classifier_id)) {
  19943         classifier->flags |= BCM_COSQ_CLASSIFIER_FIELD;
  19944     }
  19945 
  19946     return BCM_E_NONE;
  19947 }
  19948 
  19949 
  19950 
  19951 /*
  19952  * Function:
  19953  *      bcm_td2_cosq_field_classifier_id_create
  19954  * Purpose:
  19955  *      Create a cosq classifier.
  19956  * Parameters: 
  19957  *      unit          - (IN) Unit number.
  19958  *      classifier    - (IN) Classifier attributes
  19959  *      classifier_id - (OUT) Classifier ID
  19960  * Returns:
  19961  *      BCM_E_xxx
  19962  */     
  19963 int
  19964 bcm_td2_cosq_field_classifier_id_create(
  19965     int unit,
  19966     bcm_cosq_classifier_t *classifier,
  19967     int *classifier_id)
  19968 {
  19969     int rv;
  19970     int ref_count = 0;
  19971     int ent_per_set = _TD2_NUM_INTERNAL_PRI;
  19972     int i;
  19973 
  19974     if (NULL == classifier || NULL == classifier_id) {
  19975         return BCM_E_PARAM;
  19976     }
  19977 
  19978     for (i = 0; i < SOC_MEM_SIZE(unit, IFP_COS_MAPm); i += ent_per_set) {
  19979         rv = soc_profile_mem_ref_count_get(
  19980                 unit, _bcm_td2_ifp_cos_map_profile[unit], i, &ref_count);
  19981         if (SOC_FAILURE(rv)) {
  19982             return rv;
  19983         }
  19984         if (0 == ref_count) {
  19985             break;
  19986         }
  19987     }
  19988 
  19989     if (i >= SOC_MEM_SIZE(unit, IFP_COS_MAPm) && ref_count != 0) {
  19990         *classifier_id = 0;
  19991         return BCM_E_RESOURCE;
  19992     }
  19993 
  19994     _BCM_COSQ_CLASSIFIER_FIELD_SET(*classifier_id, (i / ent_per_set));
  19995 
  19996     return BCM_E_NONE;
  19997 }
  19998 
  19999 
  20000 /*
  20001  * Function:
  20002  *      bcm_td2_cosq_field_classifier_map_set
  20003  * Purpose:
  20004  *      Set internal priority to ingress field processor CoS queue
  20005  *      override mapping.
  20006  * Parameters:
  20007  *      unit           - (IN) Unit number.
  20008  *      classifier_id  - (IN) Classifier ID
  20009  *      count          - (IN) Number of elements in priority_array and
  20010  *                            cosq_array
  20011  *      priority_array - (IN) Array of internal priorities
  20012  *      cosq_array     - (IN) Array of COS queues
  20013  * Returns:
  20014  *      BCM_E_xxx
  20015  */
  20016 int
  20017 bcm_td2_cosq_field_classifier_map_set(
  20018     int unit,
  20019     int classifier_id,
  20020     int count,
  20021     bcm_cos_t *priority_array,
  20022     bcm_cos_queue_t *cosq_array)
  20023 {
  20024     int rv;
  20025     int i;
  20026     int max_entries = _TD2_NUM_INTERNAL_PRI;
  20027     uint32 index;
  20028     void *entries[1];
  20029     ifp_cos_map_entry_t ent_buf[_TD2_NUM_INTERNAL_PRI];
  20030     int field_width;
  20031     int ref_count = 0;
  20032 
  20033     /* Input parameter check. */
  20034     if (!_BCM_COSQ_CLASSIFIER_IS_FIELD(classifier_id)) {
  20035         return BCM_E_PARAM;
  20036     }
  20037 
  20038     if (NULL == priority_array || NULL == cosq_array) {
  20039         return BCM_E_PARAM;
  20040     }
  20041 
  20042     if (count > max_entries) {
  20043         return BCM_E_PARAM;
  20044     }
  20045 
  20046     field_width = soc_mem_field_length(unit, IFP_COS_MAPm, IFP_COSf);
  20047     sal_memset(ent_buf, 0, sizeof(ifp_cos_map_entry_t) * max_entries);
  20048     entries[0] = ent_buf;
  20049     
  20050     for (i = 0; i < count; i++) {
  20051         if (priority_array[i] < max_entries) {
  20052             if (cosq_array[i] >= (1 << field_width)) {
  20053                 return BCM_E_PARAM;
  20054             }
  20055             soc_mem_field32_set(unit, IFP_COS_MAPm, &ent_buf[priority_array[i]],
  20056                                 IFP_COSf, cosq_array[i]);
  20057         }
  20058     }
  20059     
  20060     index = _BCM_COSQ_CLASSIFIER_FIELD_GET(classifier_id);
  20061     SOC_IF_ERROR_RETURN(
  20062         soc_profile_mem_ref_count_get(unit, _bcm_td2_ifp_cos_map_profile[unit],
  20063                                       index * max_entries, &ref_count));
  20064 
  20065     if (ref_count == 0) {
  20066         rv = soc_profile_mem_add(unit, _bcm_td2_ifp_cos_map_profile[unit],
  20067                                  entries, max_entries, &index);
  20068     } else {
  20069         rv = soc_profile_mem_set(unit, _bcm_td2_ifp_cos_map_profile[unit],
  20070                                  entries, index * max_entries);
  20071         if (rv == SOC_E_NONE) {
  20072             /* decrease the profile ref_count increased by mem_set */
  20073             rv = soc_profile_mem_delete(unit,
  20074                                         _bcm_td2_ifp_cos_map_profile[unit],
  20075                                         index * max_entries);
  20076         }
  20077     }
  20078     return rv;
  20079 }
  20080 
  20081 
  20082 /*
  20083  * Function:
  20084  *      bcm_td2_cosq_field_classifier_map_get
  20085  * Purpose:
  20086  *      Get internal priority to ingress field processor CoS queue
  20087  *      override mapping information.
  20088  * Parameters:
  20089  *      unit           - (IN) Unit number.
  20090  *      classifier_id  - (IN) Classifier ID
  20091  *      array_max      - (IN) Size of priority_array and cosq_array
  20092  *      priority_array - (IN) Array of internal priorities
  20093  *      cosq_array     - (OUT) Array of COS queues
  20094  *      array_count    - (OUT) Size of cosq_array
  20095  * Returns:
  20096  *      BCM_E_xxx
  20097  */
  20098 int
  20099 bcm_td2_cosq_field_classifier_map_get(
  20100     int unit,
  20101     int classifier_id,
  20102     int array_max,
  20103     bcm_cos_t *priority_array,
  20104     bcm_cos_queue_t *cosq_array,
  20105     int *array_count)
  20106 {
  20107     int rv;
  20108     int i;
  20109     int ent_per_set = _TD2_NUM_INTERNAL_PRI;
  20110     uint32 index;
  20111     void *entries[1];
  20112     ifp_cos_map_entry_t ent_buf[_TD2_NUM_INTERNAL_PRI];
  20113 
  20114     /* Input parameter check. */
  20115     if (NULL == priority_array || NULL == cosq_array || NULL == array_count) {
  20116         return BCM_E_PARAM;
  20117     }
  20118 
  20119     sal_memset(ent_buf, 0, sizeof(ifp_cos_map_entry_t) * ent_per_set);
  20120     entries[0] = ent_buf;
  20121 
  20122     /* Get profile table entry set base index. */
  20123     index = _BCM_COSQ_CLASSIFIER_FIELD_GET(classifier_id);
  20124 
  20125     /* Read out entries from profile table into allocated buffer. */
  20126     rv = soc_profile_mem_get(unit, _bcm_td2_ifp_cos_map_profile[unit],
  20127                              index * ent_per_set, ent_per_set, entries);
  20128     if (SOC_FAILURE(rv)) {
  20129         return rv;
  20130     }
  20131 
  20132     *array_count = array_max > ent_per_set ? ent_per_set : array_max;
  20133 
  20134     /* Copy values into API OUT parameters. */
  20135     for (i = 0; i < *array_count; i++) {
  20136         if (priority_array[i] >= _TD2_NUM_INTERNAL_PRI) {
  20137             return BCM_E_PARAM;
  20138         }
  20139         cosq_array[i] = soc_mem_field32_get(unit, IFP_COS_MAPm,
  20140                                             &ent_buf[priority_array[i]],
  20141                                             IFP_COSf);
  20142     }
  20143 
  20144     return BCM_E_NONE;
  20145 }
  20146 
  20147 
  20148 /*
  20149  * Function:
  20150  *      bcm_td2_cosq_field_classifier_map_clear
  20151  * Purpose:
  20152  *      Delete an internal priority to ingress field processor CoS queue
  20153  *      override mapping profile set.
  20154  * Parameters:
  20155  *      unit          - (IN) Unit number.
  20156  *      classifier_id - (IN) Classifier ID
  20157  * Returns:
  20158  *      BCM_E_xxx
  20159  */
  20160 int
  20161 bcm_td2_cosq_field_classifier_map_clear(int unit, int classifier_id)
  20162 {
  20163     int ent_per_set = _TD2_NUM_INTERNAL_PRI;
  20164     uint32 index;
  20165 
  20166     /* Get profile table entry set base index. */
  20167     index = _BCM_COSQ_CLASSIFIER_FIELD_GET(classifier_id);
  20168 
  20169     /* Delete the profile entries set. */
  20170     SOC_IF_ERROR_RETURN
  20171         (soc_profile_mem_delete(unit,
  20172                                 _bcm_td2_ifp_cos_map_profile[unit],
  20173                                 index * ent_per_set));
  20174     return BCM_E_NONE;
  20175 }
  20176 
  20177 
  20178 /*
  20179  * Function:
  20180  *      bcm_td2_cosq_field_classifier_id_destroy
  20181  * Purpose:
  20182  *      Free resource associated with this field classifier id.
  20183  * Parameters:
  20184  *      unit          - (IN) Unit number.
  20185  *      classifier_id - (IN) Classifier ID
  20186  * Returns:
  20187  *      BCM_E_xxx
  20188  */
  20189 int
  20190 bcm_td2_cosq_field_classifier_id_destroy(int unit, int classifier_id)
  20191 {
  20192     return BCM_E_NONE;
  20193 }
  20194 
  20195 /*
  20196  * Function:
  20197  *      bcm_td_cosq_cpu_cosq_enable_set
  20198  * Purpose:
  20199  *      To enable/disable Rx of packets on the specified CPU cosq.
  20200  * Parameters:
  20201  *      unit          - (IN) Unit number.
  20202  *      cosq          - (IN) CPU Cosq ID
  20203  *      enable        - (IN) Enable/Disable
  20204  * Returns:
  20205  *      BCM_E_xxx
  20206  */
  20207 int
  20208 bcm_td2_cosq_cpu_cosq_enable_set(
  20209     int unit, 
  20210     bcm_cos_queue_t cosq, 
  20211     int enable)
  20212 {
  20213     uint32 entry[SOC_MAX_MEM_WORDS];
  20214     int i, index, enable_status;
  20215     _bcm_td2_cosq_cpu_cosq_config_t *cpu_cosq;
  20216     soc_info_t *si;
  20217     soc_mem_t thdm_mem[] = {
  20218         MMU_THDM_DB_QUEUE_CONFIG_0m,
  20219         MMU_THDM_MCQE_QUEUE_CONFIG_0m
  20220     };
  20221 
  20222     si = &SOC_INFO(unit);
  20223 
  20224     if ((cosq < 0) || (cosq >= si->num_cpu_cosq)) {
  20225         return BCM_E_PARAM;
  20226     }
  20227 
  20228     cpu_cosq = _bcm_td2_cosq_cpu_cosq_config[unit][cosq];
  20229 
  20230     if (!cpu_cosq) {
  20231         return BCM_E_INTERNAL;
  20232     }
  20233     if (enable) {
  20234         enable = 1;
  20235     }
  20236     BCM_IF_ERROR_RETURN(bcm_td2_cosq_cpu_cosq_enable_get(unit, cosq,
  20237                                                          &enable_status));
  20238     if (enable == enable_status) {
  20239         return BCM_E_NONE;
  20240     }
  20241 
  20242     /* CPU MC cosq's range from 520 - 568. 0-519 are MC's of Regular ports */
  20243     index = 520 + cosq;
  20244 
  20245     for (i = 0; i < 2; i++) {
  20246         BCM_IF_ERROR_RETURN
  20247             (soc_mem_read(unit, thdm_mem[i], MEM_BLOCK_ALL, index, &entry));
  20248 
  20249         if (enable) {
  20250             soc_mem_field32_set(unit, thdm_mem[i], &entry,
  20251                                 Q_MIN_LIMITf, cpu_cosq->q_min_limit[i]);
  20252             soc_mem_field32_set(unit, thdm_mem[i], &entry,
  20253                                 Q_SHARED_LIMITf, cpu_cosq->q_shared_limit[i]);
  20254         }
  20255         else {
  20256             cpu_cosq->q_min_limit[i] = soc_mem_field32_get(unit,
  20257                                                            thdm_mem[i],
  20258                                                            &entry,
  20259                                                            Q_MIN_LIMITf);
  20260             cpu_cosq->q_shared_limit[i] = soc_mem_field32_get(unit,
  20261                                                               thdm_mem[i],
  20262                                                               &entry,
  20263                                                               Q_SHARED_LIMITf);
  20264             cpu_cosq->q_limit_dynamic[i] = soc_mem_field32_get(unit,
  20265                                                                thdm_mem[i],
  20266                                                                &entry,
  20267                                                                Q_LIMIT_DYNAMICf);
  20268             cpu_cosq->q_limit_enable[i] = soc_mem_field32_get(unit,
  20269                                                               thdm_mem[i],
  20270                                                               &entry,
  20271                                                               Q_LIMIT_ENABLEf);
  20272             soc_mem_field32_set(unit, thdm_mem[i], &entry, Q_MIN_LIMITf, 0);
  20273             soc_mem_field32_set(unit, thdm_mem[i], &entry, Q_SHARED_LIMITf, 0);
  20274         }
  20275         soc_mem_field32_set(unit, thdm_mem[i], &entry,
  20276                             Q_LIMIT_DYNAMICf, enable ? cpu_cosq->q_limit_dynamic[i] : 0);
  20277         soc_mem_field32_set(unit, thdm_mem[i], &entry,
  20278                             Q_LIMIT_ENABLEf, enable ? cpu_cosq->q_limit_enable[i] : 1);
  20279         cpu_cosq->enable = enable;
  20280         BCM_IF_ERROR_RETURN(
  20281             soc_mem_write(unit, thdm_mem[i], MEM_BLOCK_ALL, index, &entry));
  20282     }
  20283 
  20284     return BCM_E_NONE;
  20285 }
  20286 
  20287 /*
  20288  * Function:
  20289  *      bcm_td_cosq_cpu_cosq_enable_get
  20290  * Purpose:
  20291  *      To get enable/disable status on Rx of packets on the specified CPU cosq.
  20292  * Parameters:
  20293  *      unit          - (IN) Unit number.
  20294  *      cosq          - (IN) CPU Cosq ID
  20295  *      enable        - (OUT) Enable/Disable
  20296  * Returns:
  20297  *      BCM_E_xxx
  20298  */
  20299 int
  20300 bcm_td2_cosq_cpu_cosq_enable_get(
  20301     int unit, 
  20302     bcm_cos_queue_t cosq, 
  20303     int *enable)
  20304 {
  20305     _bcm_td2_cosq_cpu_cosq_config_t *cpu_cosq;
  20306     soc_info_t *si;
  20307     int index, hw_enable;
  20308     uint32 entry[SOC_MAX_MEM_WORDS];
  20309     soc_field_t min_limit, shared_limit, limit_enable, dynamic_enable;
  20310     soc_mem_t thdm_mem = MMU_THDM_DB_QUEUE_CONFIG_0m;
  20311 
  20312     si = &SOC_INFO(unit);
  20313 
  20314     if ((cosq < 0) || (cosq >= si->num_cpu_cosq)) {
  20315         return BCM_E_PARAM;
  20316     }
  20317 
  20318     cpu_cosq = _bcm_td2_cosq_cpu_cosq_config[unit][cosq];
  20319     if (!cpu_cosq) {
  20320         return BCM_E_INTERNAL;
  20321     }
  20322 
  20323     /* CPU MC cosq's range from 520 - 568. 0-519 are MC's of Regular ports */
  20324     index = 520 + cosq;
  20325     hw_enable = 1;
  20326     /* Sync up software record with hardware status. */
  20327     BCM_IF_ERROR_RETURN(soc_mem_read(unit, thdm_mem, MEM_BLOCK_ALL,
  20328                                      index, &entry));
  20329     min_limit = soc_mem_field32_get(unit, thdm_mem, &entry,
  20330                                     Q_MIN_LIMITf);
  20331     shared_limit = soc_mem_field32_get(unit, thdm_mem, &entry,
  20332                                     Q_SHARED_LIMITf);
  20333     limit_enable = soc_mem_field32_get(unit, thdm_mem, &entry,
  20334                                     Q_LIMIT_ENABLEf);
  20335     dynamic_enable = soc_mem_field32_get(unit, thdm_mem, &entry,
  20336                                     Q_LIMIT_DYNAMICf);
  20337     if (limit_enable && (dynamic_enable == 0) &&
  20338         (min_limit == 0) && (shared_limit == 0)) {
  20339         hw_enable = 0;
  20340     }
  20341     cpu_cosq->enable = hw_enable;
  20342 
  20343     *enable = cpu_cosq->enable;
  20344     return BCM_E_NONE;
  20345 }
  20346 
  20347 /*
  20348  * Function:
  20349  *      bcm_td2_cosq_service_classifier_id_create
  20350  * Purpose:
  20351  *      Create an endpoint.
  20352  * Parameters:
  20353  *      unit          - (IN) Unit number.
  20354  *      classifier    - (IN) Classifier attributes
  20355  *      classifier_id - (OUT) Classifier ID
  20356  * Returns:
  20357  *      BCM_E_xxx
  20358  */
  20359 int
  20360 bcm_td2_cosq_service_classifier_id_create(
  20361     int unit,
  20362     bcm_cosq_classifier_t *classifier,
  20363     int *classifier_id)
  20364 {
  20365     if (NULL == classifier || NULL == classifier_id) {
  20366         return BCM_E_PARAM;
  20367     }
  20368 
  20369     _BCM_COSQ_CLASSIFIER_SERVICE_SET(*classifier_id, classifier->vlan);
  20370     return BCM_E_NONE;
  20371 }
  20372 
  20373 /*
  20374  * Function:
  20375  *      bcm_td2_cosq_service_classifier_id_destroy
  20376  * Purpose:
  20377  *      free resource associated with this service classifier id.
  20378  * Parameters:
  20379  *      unit          - (IN) Unit number.
  20380  *      classifier_id - (IN) Classifier ID
  20381  * Returns:
  20382  *      BCM_E_xxx
  20383  */
  20384 int
  20385 bcm_td2_cosq_service_classifier_id_destroy(
  20386     int unit,
  20387     int classifier_id)
  20388 {
  20389     return BCM_E_NONE;
  20390 }
  20391 
  20392 /*
  20393  * Function:
  20394  *      bcm_td2_cosq_service_classifier_get
  20395  * Purpose:
  20396  *      Get info about an endpoint.
  20397  * Parameters:
  20398  *      unit          - (IN) Unit number.
  20399  *      classifier_id - (IN) Classifier ID
  20400  *      classifier    - (OUT) Classifier info
  20401  * Returns:
  20402  *      BCM_E_xxx
  20403  */
  20404 int
  20405 bcm_td2_cosq_service_classifier_get(
  20406     int unit,
  20407     int classifier_id,
  20408     bcm_cosq_classifier_t *classifier)
  20409 {
  20410     int val = 0;
  20411 
  20412     sal_memset(classifier, 0, sizeof(bcm_cosq_classifier_t));
  20413 
  20414     val = _BCM_COSQ_CLASSIFIER_SERVICE_GET(classifier_id);
  20415 
  20416     if (val > BCM_VLAN_MAX) {
  20417         /* VFI classifier */
  20418         classifier->flags = BCM_COSQ_CLASSIFIER_VFI;
  20419         classifier->vfi_index = val - BCM_VLAN_MAX - 1;
  20420     } else {
  20421         classifier->flags = BCM_COSQ_CLASSIFIER_VLAN;
  20422         classifier->vlan = val;
  20423     }
  20424     return BCM_E_NONE;
  20425 }
  20426 
  20427 /*
  20428  * Function:
  20429  *      bcm_td2_cosq_service_map_set
  20430  * Purpose:
  20431  *      Set the mapping from port, classifier, and multiple internal priorities
  20432  *      to multiple COS queues in a queue group.
  20433  * Parameters:
  20434  *      unit           - (IN) Unit number.
  20435  *      port           - (IN) local port ID
  20436  *      classifier_id  - (IN) Classifier ID
  20437  *      queue_group    - (IN) Base queue ID
  20438  *      array_count    - (IN) Number of elements in priority_array and
  20439  *                            cosq_array
  20440  *      priority_array - (IN) Array of internal priorities
  20441  *      cosq_array     - (IN) Array of COS queues
  20442  * Returns:
  20443  *      BCM_E_xxx
  20444  */
  20445 int
  20446 bcm_td2_cosq_service_map_set(
  20447     int unit,
  20448     bcm_port_t port,
  20449     int classifier_id,
  20450     bcm_gport_t queue_group,
  20451     int array_count,
  20452     bcm_cos_t *priority_array,
  20453     bcm_cos_queue_t *cosq_array)
  20454 {
  20455     service_queue_map_entry_t  sqm;
  20456     service_port_map_entry_t   *spm = NULL;
  20457     service_cos_map_entry_t    *scm = NULL;
  20458     void                       *spm_entries[1];
  20459     void                       *scm_entries[1];
  20460     int                        rv = BCM_E_NONE;
  20461     int                        i, valid_cosq, alloc_size, exists = 0;
  20462     int                        local_port, vid, qid, cos_offset = 0;
  20463     int                        port_offset, port_offset_old;
  20464     int                        qptr_old, qptr_new;
  20465     int                        pipe;
  20466     uint32                     scm_idx, scm_idx_old = 0, spm_idx, spm_idx_old = 0;
  20467     _bcm_td2_cosq_node_t       *node,*cur_node;
  20468     soc_profile_mem_t          *spm_profile_mem, *scm_profile_mem;
  20469     /*
  20470      * The port_offset= 0 is treated as the invalid offset so that
  20471      * the ports without being service map set can be recognized easily by software.
  20472      * Accordingly, The valid port_offset needs to be at least 1 for a given port.
  20473      * the queue base to be written into SERVICE_QUEUE_PTRf will
  20474      * be (the actual base - 1).
  20475      */
  20476    #define VALID_PORT_OFFSET_MIN          1
  20477 
  20478     if (!_BCM_COSQ_CLASSIFIER_IS_SERVICE(classifier_id)) {
  20479         return BCM_E_PARAM;
  20480     }
  20481 
  20482     /* index above 4K is for VFI */
  20483     vid = _BCM_COSQ_CLASSIFIER_SERVICE_GET(classifier_id);
  20484     if (vid < 0 || vid >= SOC_MEM_SIZE(unit, SERVICE_QUEUE_MAPm)) {
  20485         return BCM_E_PARAM;
  20486     }
  20487 
  20488     if (array_count > _TD2_SCM_ENTRIES_PER_SET) {
  20489         return BCM_E_PARAM;
  20490     }
  20491     scm_profile_mem = _bcm_td2_service_cos_map_profile[unit];
  20492     spm_profile_mem = _bcm_td2_service_port_map_profile[unit];
  20493 
  20494     BCM_IF_ERROR_RETURN(
  20495         _bcm_td2_cosq_node_get(unit, queue_group, 0, NULL,
  20496                                &local_port, &qid, &node));
  20497     if (node->attached_to_input < 0) {
  20498         return BCM_E_PARAM;
  20499     }
  20500 
  20501     pipe = _BCM_TD2_PORT_TO_PIPE(unit, port);
  20502     qid  = (pipe == _TD2_XPIPE)? node->hw_index: node->hw_index + 2048;
  20503 
  20504     for (i = 0; i < array_count; i++) {
  20505         valid_cosq= 0;
  20506         for (cur_node = node->parent->child;
  20507              cur_node != NULL;
  20508              cur_node = cur_node->sibling) {
  20509             if (cosq_array[i] == cur_node->attached_to_input) {
  20510                 valid_cosq = 1;
  20511                 break;
  20512             }
  20513         }
  20514         if(valid_cosq == 0){
  20515             return BCM_E_PARAM;
  20516         }
  20517     }
  20518 
  20519     sal_memset(&sqm, 0, sizeof(service_queue_map_entry_t));
  20520     SOC_IF_ERROR_RETURN(
  20521         soc_mem_read(unit, SERVICE_QUEUE_MAPm, MEM_BLOCK_ANY, (int)vid, &sqm));
  20522 
  20523     if (soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, &sqm, VALIDf)) {
  20524         exists = 1;
  20525     } else {
  20526         exists = 0;
  20527     }
  20528 
  20529     alloc_size = sizeof(service_port_map_entry_t) * _TD2_SPM_ENTRIES_PER_SET;
  20530     spm = sal_alloc(alloc_size, "SERVICE_PORT_MAP temp Mem");
  20531     if (spm == NULL) {
  20532         rv = BCM_E_MEMORY;
  20533         goto cleanup;
  20534     }
  20535     sal_memset(spm, 0, alloc_size);
  20536     spm_entries[0] = spm;
  20537 
  20538     alloc_size = sizeof(service_cos_map_entry_t) * _TD2_SCM_ENTRIES_PER_SET;
  20539     scm = sal_alloc(alloc_size, "SERVICE_COS_MAP temp Mem");
  20540     if (scm == NULL) {
  20541         rv = BCM_E_MEMORY;
  20542         goto cleanup;
  20543     }
  20544     sal_memset(scm, 0, alloc_size);
  20545     scm_entries[0] = scm;
  20546 
  20547     /*  1. program the SERVICE_COS_MAPm. */
  20548     if (!exists) {
  20549         for (i = 0; i < array_count; i++) {
  20550             if (priority_array[i] < _TD2_SCM_ENTRIES_PER_SET) {
  20551                 soc_mem_field32_set(unit, SERVICE_COS_MAPm,
  20552                                     &scm[priority_array[i]],
  20553                                     SERVICE_COS_OFFSETf, cosq_array[i]);
  20554             }
  20555         }
  20556 
  20557         rv = soc_profile_mem_add(unit, scm_profile_mem, scm_entries,
  20558                                  _TD2_SCM_ENTRIES_PER_SET, &scm_idx);
  20559         if (rv != SOC_E_NONE) {
  20560             goto cleanup;
  20561         }
  20562     } else {
  20563         /*
  20564          * only one service_cos_map profile is allowed per vlan/vfi.
  20565          * If the subsequent profile doesn't match the existing one,
  20566          * Then update the old profile, the new map may be added by other port.
  20567          */
  20568         scm_idx_old = _TD2_SCM_ENTRIES_PER_SET *
  20569                   soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, &sqm,
  20570                                       SERVICE_COS_PROFILE_INDEXf);
  20571         rv = soc_profile_mem_get(unit, scm_profile_mem, scm_idx_old,
  20572                                  _TD2_SCM_ENTRIES_PER_SET, scm_entries);
  20573         if (rv != SOC_E_NONE) {
  20574             goto cleanup;
  20575         }
  20576 
  20577         for (i = 0; i < array_count; i++) {
  20578             cos_offset = soc_mem_field32_get(unit, SERVICE_COS_MAPm,
  20579                                              &scm[priority_array[i]],
  20580                                              SERVICE_COS_OFFSETf);
  20581             if (cosq_array[i] != cos_offset) {
  20582                 if (priority_array[i] < _TD2_SCM_ENTRIES_PER_SET) {
  20583                     soc_mem_field32_set(unit, SERVICE_COS_MAPm,
  20584                                         &scm[priority_array[i]],
  20585                                         SERVICE_COS_OFFSETf, cosq_array[i]);
  20586                 }
  20587             }
  20588         }
  20589 
  20590         rv = soc_profile_mem_add(unit, scm_profile_mem, scm_entries,
  20591                          _TD2_SCM_ENTRIES_PER_SET, &scm_idx);
  20592         if (rv != SOC_E_NONE) {
  20593             goto cleanup;
  20594         }
  20595 
  20596         if (scm_idx_old != scm_idx) {
  20597             rv = soc_profile_mem_delete(unit, scm_profile_mem, scm_idx_old);
  20598             if (rv != SOC_E_NONE) {
  20599                 goto cleanup;
  20600             }
  20601         }
  20602 
  20603     }
  20604 
  20605     /*  2. program the SERVICE_PORT_MAPm. */
  20606     if (!exists) {
  20607         port_offset = VALID_PORT_OFFSET_MIN;
  20608         soc_mem_field32_set(unit, SERVICE_PORT_MAPm, &spm[local_port],
  20609                             SERVICE_PORT_OFFSETf, port_offset);
  20610     } else {
  20611         spm_idx_old = _TD2_SPM_ENTRIES_PER_SET *
  20612                       soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, &sqm,
  20613                                           SERVICE_PORT_PROFILE_INDEXf);
  20614         rv = soc_profile_mem_get(unit, spm_profile_mem, spm_idx_old,
  20615                                  _TD2_SPM_ENTRIES_PER_SET, spm_entries);
  20616         if (!(rv == SOC_E_NOT_FOUND || rv == SOC_E_NONE)) {
  20617             goto cleanup;
  20618         }
  20619 
  20620         qptr_old = soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm,
  20621                                        &sqm, SERVICE_QUEUE_PTRf);
  20622         if (qid <= qptr_old) {
  20623             qptr_new = qid - VALID_PORT_OFFSET_MIN;
  20624             for (i = 0; i < _TD2_SPM_ENTRIES_PER_SET; i++) {
  20625                 port_offset_old = soc_mem_field32_get(unit, SERVICE_PORT_MAPm,
  20626                                                       &spm[i],
  20627                                                       SERVICE_PORT_OFFSETf);
  20628                 if (i == local_port) {
  20629                     port_offset = VALID_PORT_OFFSET_MIN;
  20630                 }  else if (!port_offset_old) {
  20631                     /*
  20632                      * For the old port_offsets with 0,
  20633                      * the new port_offsest are still 0.
  20634                      */
  20635                     continue;
  20636                 } else {
  20637                     port_offset = qptr_old + port_offset_old - qptr_new;
  20638                 }
  20639                 soc_mem_field32_set(unit, SERVICE_PORT_MAPm, &spm[i],
  20640                                     SERVICE_PORT_OFFSETf, port_offset);
  20641             }
  20642         } else {
  20643             port_offset = qid - qptr_old;
  20644             soc_mem_field32_set(unit, SERVICE_PORT_MAPm, &spm[local_port],
  20645                                 SERVICE_PORT_OFFSETf, port_offset);
  20646         }
  20647     }
  20648     rv = soc_profile_mem_add(unit, spm_profile_mem,
  20649                              spm_entries, _TD2_SPM_ENTRIES_PER_SET, &spm_idx);
  20650     if (rv != SOC_E_NONE) {
  20651         goto cleanup;
  20652     }
  20653 
  20654     /* 3. program the SERVICE_QUEUE_MAPm */
  20655     if (!exists) {
  20656         qptr_new = qid - VALID_PORT_OFFSET_MIN;
  20657     } else {
  20658         qptr_old = soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm,
  20659                                        &sqm, SERVICE_QUEUE_PTRf);
  20660         if (qid <= qptr_old) {
  20661             qptr_new = qid - VALID_PORT_OFFSET_MIN;
  20662         } else {
  20663             qptr_new = qptr_old;
  20664         }
  20665     }
  20666 
  20667     soc_mem_field32_set(unit, SERVICE_QUEUE_MAPm, &sqm,
  20668                         SERVICE_QUEUE_PTRf, qptr_new);
  20669     soc_mem_field32_set(unit, SERVICE_QUEUE_MAPm, &sqm,
  20670                         SERVICE_COS_PROFILE_INDEXf,
  20671                         scm_idx / _TD2_SCM_ENTRIES_PER_SET);
  20672     soc_mem_field32_set(unit, SERVICE_QUEUE_MAPm, &sqm,
  20673                         SERVICE_PORT_PROFILE_INDEXf,
  20674                         spm_idx / _TD2_SPM_ENTRIES_PER_SET);
  20675     /* use port indexed and cos indexed for this base queue */
  20676     soc_mem_field32_set(unit, SERVICE_QUEUE_MAPm, &sqm,
  20677                         SERVICE_QUEUE_MODELf, 3);
  20678     soc_mem_field32_set(unit, SERVICE_QUEUE_MAPm, &sqm, VALIDf, 1);
  20679 
  20680     rv = soc_mem_write(unit, SERVICE_QUEUE_MAPm, MEM_BLOCK_ALL, (int)vid, &sqm);
  20681 
  20682     if (exists) {
  20683         if (spm_idx_old != spm_idx) {
  20684             rv = soc_profile_mem_delete(unit, spm_profile_mem, spm_idx_old);
  20685         }
  20686     }
  20687 
  20688 cleanup:
  20689     if (spm != NULL) {
  20690         sal_free(spm);
  20691     }
  20692     if (scm != NULL) {
  20693         sal_free(scm);
  20694     }
  20695     return rv;
  20696 }
  20697 
  20698 /*
  20699  * Function:
  20700  *      bcm_td2_cosq_service_map_get
  20701  * Purpose:
  20702  *      Get the mapping from port, classifier, and multiple internal priorities
  20703  *      to multiple COS queues in a queue group.
  20704  * Parameters:
  20705  *      unit           - (IN) Unit number.
  20706  *      port           - (IN) Local port ID
  20707  *      classifier_id  - (IN) Classifier ID
  20708  *      queue_group    - (OUT) Queue group
  20709  *      array_max      - (IN) Size of priority_array and cosq_array
  20710  *      priority_array - (IN) Array of internal priorities
  20711  *      cosq_array     - (OUT) Array of COS queues
  20712  *      array_count    - (OUT) Size of cosq_array
  20713  * Returns:
  20714  *      BCM_E_xxx
  20715  */
  20716 int
  20717 bcm_td2_cosq_service_map_get(
  20718     int unit,
  20719     bcm_port_t port,
  20720     int classifier_id,
  20721     bcm_gport_t *queue_group,
  20722     int array_max,
  20723     bcm_cos_t *priority_array,
  20724     bcm_cos_queue_t *cosq_array,
  20725     int *array_count)
  20726 {
  20727     int                        alloc_size, port_offset, i, vid, qptr;
  20728     int                        spm_index, scm_index, pipe;
  20729     int                        rv = BCM_E_NONE;
  20730     void                       *spm_entries[1];
  20731     void                       *scm_entries[1];
  20732     service_queue_map_entry_t  sqm;
  20733     service_port_map_entry_t   *spm;
  20734     service_cos_map_entry_t    *scm;
  20735     soc_profile_mem_t          *spm_profile_mem, *scm_profile_mem;
  20736 
  20737     if (priority_array == NULL || cosq_array == NULL ||
  20738         array_count == NULL || queue_group == NULL) {
  20739         return BCM_E_PARAM;
  20740     }
  20741 
  20742     if (!_BCM_COSQ_CLASSIFIER_IS_SERVICE(classifier_id)) {
  20743         return BCM_E_PARAM;
  20744     }
  20745 
  20746     /* index above 4K is for VFI */
  20747     vid = _BCM_COSQ_CLASSIFIER_SERVICE_GET(classifier_id);
  20748     if (vid < 0 || vid >= SOC_MEM_SIZE(unit, SERVICE_QUEUE_MAPm)) {
  20749         return BCM_E_PARAM;
  20750     }
  20751 
  20752     scm_profile_mem = _bcm_td2_service_cos_map_profile[unit];
  20753     spm_profile_mem = _bcm_td2_service_port_map_profile[unit];
  20754 
  20755     SOC_IF_ERROR_RETURN(
  20756         soc_mem_read(unit, SERVICE_QUEUE_MAPm, MEM_BLOCK_ANY, (int)vid, &sqm));
  20757 
  20758     if (!soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, &sqm, VALIDf)) {
  20759         return BCM_E_CONFIG;
  20760     }
  20761 
  20762     qptr = soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm,
  20763                                &sqm, SERVICE_QUEUE_PTRf);
  20764     pipe = _BCM_TD2_PORT_TO_PIPE(unit, port);
  20765     qptr = (pipe == _TD2_XPIPE)? qptr: qptr - 2048;
  20766     spm_index = _TD2_SPM_ENTRIES_PER_SET *
  20767                 soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, &sqm,
  20768                                     SERVICE_PORT_PROFILE_INDEXf);
  20769     scm_index = _TD2_SCM_ENTRIES_PER_SET *
  20770                 soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, &sqm,
  20771                                SERVICE_COS_PROFILE_INDEXf);
  20772 
  20773     alloc_size = sizeof(service_port_map_entry_t) * _TD2_SPM_ENTRIES_PER_SET;
  20774     spm = sal_alloc(alloc_size, "SERVICE_PORT_MAP temp Mem");
  20775     if (spm == NULL) {
  20776         return BCM_E_MEMORY;
  20777     }
  20778     sal_memset(spm, 0, alloc_size);
  20779     spm_entries[0] = spm;
  20780 
  20781     alloc_size = sizeof(service_cos_map_entry_t) * _TD2_SCM_ENTRIES_PER_SET;
  20782     scm = sal_alloc(alloc_size, "SERVICE_COS_MAP temp Mem");
  20783     if (scm == NULL) {
  20784         goto cleaup;
  20785     }
  20786     sal_memset(scm, 0, alloc_size);
  20787     scm_entries[0] = scm;
  20788 
  20789     rv = soc_profile_mem_get(unit, spm_profile_mem,
  20790                              spm_index, _TD2_SPM_ENTRIES_PER_SET, spm_entries);
  20791     if (!(rv == SOC_E_NOT_FOUND || rv == SOC_E_NONE)) {
  20792         goto cleaup;
  20793     }
  20794 
  20795     rv = soc_profile_mem_get(unit, scm_profile_mem,
  20796                              scm_index, _TD2_SCM_ENTRIES_PER_SET, scm_entries);
  20797     if (!(rv == SOC_E_NOT_FOUND || rv == SOC_E_NONE)) {
  20798         goto cleaup;
  20799     }
  20800 
  20801     port_offset = soc_mem_field32_get(unit, SERVICE_PORT_MAPm,
  20802                                       &spm[port], SERVICE_PORT_OFFSETf);
  20803     if (port_offset == 0) {
  20804         rv = BCM_E_NOT_FOUND;
  20805         goto cleaup;
  20806     }
  20807     pipe = _BCM_TD2_PORT_TO_PIPE(unit, port);
  20808     BCM_GPORT_UCAST_QUEUE_GROUP_SYSQID_SET(*queue_group, port,
  20809         ((pipe * _BCM_TD2_NUM_L2_UC_LEAVES_PER_PIPE) + port_offset + qptr));
  20810 
  20811     *array_count = array_max > _TD2_SCM_ENTRIES_PER_SET ?
  20812                    _TD2_SCM_ENTRIES_PER_SET : array_max;
  20813     for (i = 0; i < *array_count; i++) {
  20814         if (priority_array[i] >= _TD2_SCM_ENTRIES_PER_SET) {
  20815             rv = BCM_E_PARAM;
  20816             goto cleaup;
  20817         }
  20818         cosq_array[i] = soc_mem_field32_get(unit, SERVICE_COS_MAPm,
  20819                                             &scm[priority_array[i]],
  20820                                             SERVICE_COS_OFFSETf);
  20821     }
  20822 
  20823 cleaup:
  20824     if (spm != NULL) {
  20825         sal_free(spm);
  20826     }
  20827     if (scm != NULL) {
  20828         sal_free(scm);
  20829     }
  20830     return rv;
  20831 }
  20832 
  20833 /*
  20834  * Function:
  20835  *      bcm_td2_cosq_service_map_clear
  20836  * Purpose:
  20837  *      Clear the mapping from port, classifier, and internal priorities
  20838  *      to COS queues in a queue group.
  20839  * Parameters:
  20840  *      unit          - (IN) Unit number.
  20841  *      port          - (IN) Local port ID
  20842  *      classifier_id - (IN) Classifier ID
  20843  * Returns:
  20844  *      BCM_E_xxx
  20845  */
  20846 int
  20847 bcm_td2_cosq_service_map_clear(
  20848     int unit,
  20849     bcm_gport_t port,
  20850     int classifier_id)
  20851 {
  20852     int                        i, alloc_size, vid, classifier_in_use;
  20853     int                        rv = BCM_E_NONE;
  20854     int                        scm_index;
  20855     uint32                     spm_index, spm_index_new;
  20856     void                       *spm_entries[1];
  20857     service_port_map_entry_t   *spm;
  20858     service_queue_map_entry_t  sqm;
  20859     soc_profile_mem_t          *spm_profile_mem, *scm_profile_mem;
  20860 
  20861     if (!_BCM_COSQ_CLASSIFIER_IS_SERVICE(classifier_id)) {
  20862         return BCM_E_PARAM;
  20863     }
  20864 
  20865     /* index above 4K is for VFI */
  20866     vid = _BCM_COSQ_CLASSIFIER_SERVICE_GET(classifier_id);
  20867     if (vid < 0 || vid >= SOC_MEM_SIZE(unit, SERVICE_QUEUE_MAPm)) {
  20868         return BCM_E_PARAM;
  20869     }
  20870 
  20871     scm_profile_mem = _bcm_td2_service_cos_map_profile[unit];
  20872     spm_profile_mem = _bcm_td2_service_port_map_profile[unit];
  20873 
  20874     SOC_IF_ERROR_RETURN(
  20875         soc_mem_read(unit, SERVICE_QUEUE_MAPm, MEM_BLOCK_ANY, (int)vid, &sqm));
  20876 
  20877     if (!soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, &sqm, VALIDf)) {
  20878         return BCM_E_NONE;
  20879     }
  20880 
  20881     /*  1. program the SERVICE_PORT_MAPm. */
  20882     alloc_size = sizeof(service_port_map_entry_t) * _TD2_SPM_ENTRIES_PER_SET;
  20883     spm = sal_alloc(alloc_size, "SERVICE_PORT_MAP temp Mem");
  20884     if (spm == NULL) {
  20885         return BCM_E_MEMORY;
  20886     }
  20887     sal_memset(spm, 0, alloc_size);
  20888     spm_entries[0] = spm;
  20889 
  20890     spm_index = _TD2_SPM_ENTRIES_PER_SET *
  20891                 soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, &sqm,
  20892                                     SERVICE_PORT_PROFILE_INDEXf);
  20893     rv = soc_profile_mem_get(unit, spm_profile_mem,
  20894                              spm_index, _TD2_SPM_ENTRIES_PER_SET, spm_entries);
  20895     if (!(rv == SOC_E_NOT_FOUND || rv == SOC_E_NONE)) {
  20896         goto cleanup;
  20897     }
  20898 
  20899     soc_mem_field32_set(unit, SERVICE_PORT_MAPm,
  20900                         &spm[port], SERVICE_PORT_OFFSETf, 0);
  20901     classifier_in_use = 0;
  20902     for (i = 0; i < _TD2_SPM_ENTRIES_PER_SET; i++) {
  20903         if (soc_mem_field32_get(unit, SERVICE_PORT_MAPm,
  20904                                 &spm[i], SERVICE_PORT_OFFSETf)) {
  20905             classifier_in_use = 1;
  20906             break;
  20907         }
  20908     }
  20909 
  20910     rv = soc_profile_mem_delete(unit, spm_profile_mem, spm_index);
  20911     if (rv != SOC_E_NONE) {
  20912         goto cleanup;
  20913     }
  20914 
  20915     if (classifier_in_use) {
  20916        rv = soc_profile_mem_add(unit, spm_profile_mem,
  20917                                 spm_entries, _TD2_SPM_ENTRIES_PER_SET,
  20918                                 &spm_index_new);
  20919        if (rv != SOC_E_NONE) {
  20920            goto cleanup;
  20921        }
  20922     }
  20923 
  20924     /*  2. program the SERVICE_COS_MAPm. */
  20925     if (!classifier_in_use) {
  20926         scm_index = _TD2_SCM_ENTRIES_PER_SET *
  20927                     soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, &sqm,
  20928                                         SERVICE_COS_PROFILE_INDEXf);
  20929         rv = soc_profile_mem_delete(unit, scm_profile_mem, scm_index);
  20930         if (rv != SOC_E_NONE) {
  20931             goto cleanup;
  20932         }
  20933     }
  20934 
  20935     /*  3. program the SERVICE_QUEUE_MAPm. */
  20936     if (classifier_in_use) {
  20937         soc_mem_field32_set(unit, SERVICE_QUEUE_MAPm, &sqm,
  20938                             SERVICE_PORT_PROFILE_INDEXf,
  20939                             spm_index_new / _TD2_SPM_ENTRIES_PER_SET);
  20940     } else {
  20941         sal_memset(&sqm,0, sizeof(service_queue_map_entry_t));
  20942     }
  20943 
  20944     rv =  soc_mem_write(unit, SERVICE_QUEUE_MAPm, MEM_BLOCK_ALL,
  20945                        (int)vid, &sqm);
  20946 
  20947 cleanup:
  20948     if (spm != NULL) {
  20949         sal_free(spm);
  20950     }
  20951     return rv;
  20952 }
  20953 
  20954 /*
  20955  * Function:
  20956  *     bcm_td2p_rx_queue_channel_set
  20957  * Purpose:
  20958  *     Validate if the queue id to channel id mapping
  20959  *     is in accordance with the LLS Hierarchy created
  20960  *     If queue_id is -1, find the LLS Hierarchy & program
  20961  *     CMIC accordingly
  20962  *     JIRA:- SDK-57255
  20963  * Parameters:
  20964  *     unit  - (IN) unit number
  20965  *     queue_id - CPU cos queue index (0 - (max cosq - 1))
  20966  *                                    (Negative for all)
  20967  *     chan_id - channel index (0 - (BCM_RX_CHANNELS-1))
  20968  * Returns:
  20969  *     BCM_E_XXX
  20970  */
  20971 int
  20972 bcm_td2p_rx_queue_channel_set(int unit, bcm_cos_queue_t queue_id,
  20973                               bcm_rx_chan_t chan_id)
  20974 {
  20975 #ifdef BCM_CMICM_SUPPORT
  20976     uint32 chan_off;
  20977     uint32 l0_index;
  20978     uint32 l0_hw_index;
  20979     bcm_gport_t cpu_gport;
  20980     _bcm_td2_cosq_node_t *node;
  20981     _bcm_td2_cosq_node_t *l0_node;
  20982     _bcm_td2_cosq_node_t *l1_node;
  20983     _bcm_td2_cosq_node_t *l2_queue;
  20984     bcm_port_t local_port;
  20985     int i,id = 0;
  20986     int bit = 0;
  20987     int pci_cmc = SOC_PCI_CMC(unit);
  20988     int queue_in_tree = FALSE;
  20989     bcm_cos_queue_t new_queue_id;
  20990     bcm_rx_chan_t new_chan_id;
  20991     _bcm_td2_mmu_info_t *mmu_info;
  20992 
  20993     mmu_info = _bcm_td2_mmu_info[unit];
  20994     cpu_gport = BCM_GPORT_LOCAL_CPU;
  20995 
  20996     /* Find the cosq node for cpu port */
  20997     BCM_IF_ERROR_RETURN
  20998         (_bcm_td2_cosq_localport_resolve(unit, cpu_gport, &local_port));
  20999 
  21000     /* We are passing a gport to _bcm_td2_cosq_localport_resolve
  21001      * So local_port is NOT returning gport but resolving it.
  21002      * Ignoring the coverity error
  21003  */
  21004     /* coverity[overrun-local] */
  21005     if (!IS_CPU_PORT(unit, local_port)) {
  21006         LOG_ERROR(BSL_LS_BCM_COSQ, (BSL_META_U(unit,
  21007                         "Cannot find CPU port. cpu gport 0x%x local port %d\n"),
  21008                         cpu_gport, local_port));
  21009         return BCM_E_PARAM;
  21010     }
  21011 
  21012     id = local_port;
  21013     node = &mmu_info->sched_node[id];
  21014 
  21015     SHR_BITCLR_RANGE(CPU_ARM_RSVD_QUEUE_BITMAP(unit, pci_cmc),58,6);
  21016 
  21017     if (queue_id == -1) {
  21018         /* No verification. Map all queues to corresponding channel */
  21019         /* loop through all l0 nodes */
  21020         /* 
  21021          * COVERITY
  21022          * We passed a gport to _bcm_td2_cosq_localport_resolve
  21023          * So local_port is NOT returning gport but resolving it.
  21024          * Ignoring the coverity error
  21025  */
  21026         /* coverity[overrun-local] */
  21027         l0_node = node->child;
  21028         while (l0_node) {
  21029             /* loop through all l1 nodes */
  21030             l0_hw_index = l0_node->hw_index;
  21031             new_chan_id = -1;
  21032             for (i = 0; i< BCM_RX_CHANNELS; i++) {
  21033                 if (bcm_td2p_cosq_rx_chan_l0_map[i] == l0_hw_index) {
  21034                     new_chan_id = i;
  21035                     break;
  21036                 }
  21037             }
  21038             if (new_chan_id == -1) {
  21039                 LOG_ERROR(BSL_LS_BCM_COSQ, (BSL_META_U(unit,
  21040                                 "Cannot find channel id for l0 node %d"
  21041                                 " Check the LLS hierarchy"
  21042                                 " configured on this device\n"),l0_hw_index));
  21043                 return BCM_E_PARAM;
  21044             }
  21045             SHR_BITCLR_RANGE(CPU_ARM_RSVD_QUEUE_BITMAP(unit, pci_cmc),58,6);
  21046             bit = bcm_td2p_cmic_to_mmu_cosmask_map[(l0_hw_index % SOC_TD2_COSQ_CPU_RESERVED_L0_BASE(unit))%_TD2PLUS_COSQ_NUM_CPU_L0_NODES];
  21047             LOG_INFO(BSL_LS_BCM_COSQ, (BSL_META_U(unit,
  21048                             "Setting bit %d & channel id %d"
  21049                             " configured on l0 index %d\n "),
  21050                         bit, new_chan_id, l0_hw_index));
  21051             SHR_BITSET(CPU_ARM_RSVD_QUEUE_BITMAP(unit, pci_cmc), bit);
  21052             l1_node = l0_node->child;
  21053             while (l1_node) {
  21054             /* loop through all l2 queues */
  21055                 l2_queue = l1_node->child;
  21056                 while (l2_queue) {
  21057                     /* CPU queues start from 2000 in HW. Deriving the logical cpu queue number (0 to 48) here */
  21058                     new_queue_id = (l2_queue->hw_index-2000)%NUM_CPU_ARM_COSQ(unit, pci_cmc);
  21059                     BCM_IF_ERROR_RETURN(_bcm_common_rx_queue_channel_set_helper(
  21060                                 unit,
  21061                                 new_queue_id,
  21062                                 new_chan_id,
  21063                                 pci_cmc));
  21064 
  21065                     LOG_INFO(BSL_LS_BCM_COSQ, (BSL_META_U(unit,
  21066                                     "Queue id %d & channel id %d"
  21067                                     " configured on l0 index %d\n "),
  21068                                 new_queue_id, new_chan_id, l0_hw_index));
  21069                     l2_queue = l2_queue->sibling;
  21070                 }
  21071                 l1_node = l1_node->sibling;
  21072             }
  21073             l0_node = l0_node->sibling;
  21074         }
  21075     } else {
  21076         chan_off = chan_id % BCM_RX_CHANNELS;
  21077         l0_index = bcm_td2p_cosq_rx_chan_l0_map[chan_off];
  21078         l0_node = node->child;
  21079         while (l0_node) {
  21080             if (l0_node->hw_index == l0_index) {
  21081                 break;
  21082             }
  21083             l0_node = l0_node->sibling;
  21084         }
  21085 
  21086         if (!l0_node) {
  21087             LOG_ERROR(BSL_LS_BCM_COSQ,
  21088                     (BSL_META_U(unit, "Invalid input, channel_id %d\n"), chan_id));
  21089             return BCM_E_PARAM;
  21090         }
  21091 
  21092         if (l0_node->hw_index != l0_index) {
  21093             LOG_ERROR(BSL_LS_BCM_COSQ,
  21094                     (BSL_META_U(unit, "MMU L0 node not found for this channel %d\n"), chan_id));
  21095             return BCM_E_NOT_FOUND;
  21096         }
  21097 
  21098         /* Verify if the given queue_id is in correct LLS hierarchy */
  21099         l1_node = l0_node->child;
  21100         queue_in_tree = FALSE;
  21101         while (l1_node) {
  21102             l2_queue = l1_node->child;
  21103             while (l2_queue) {
  21104                 /* CPU queues start from 2000 in HW. Deriving the logical cpu queue number (0 to 48) here */
  21105                 if (queue_id == (l2_queue->hw_index-2000)%NUM_CPU_ARM_COSQ(unit, pci_cmc)) {
  21106                     queue_in_tree = TRUE;
  21107                     break;
  21108                 }
  21109                 l2_queue = l2_queue->sibling;
  21110             }
  21111             if (queue_in_tree) {
  21112                 break;
  21113             }
  21114             l1_node = l1_node->sibling;
  21115         }
  21116 
  21117         if (!queue_in_tree) {
  21118             /* Verification failed. Throw error */
  21119             LOG_ERROR(BSL_LS_BCM_COSQ, (BSL_META_U(unit,
  21120                             "Queue id %d & channel id %d"
  21121                             " params do not match the LLS hierarchy"
  21122                             " configured on this device\n"),
  21123                         queue_id, chan_id));
  21124             return BCM_E_PARAM;
  21125         }
  21126         else {
  21127             bit = bcm_td2p_cmic_to_mmu_cosmask_map[(l0_index % SOC_TD2_COSQ_CPU_RESERVED_L0_BASE(unit))%_TD2PLUS_COSQ_NUM_CPU_L0_NODES];
  21128             LOG_INFO(BSL_LS_BCM_COSQ, (BSL_META_U(unit,
  21129                             "Setting bit %d & channel id %d"
  21130                             " configured on l0 index %d\n "),
  21131                         bit, chan_off, l0_index));
  21132             SHR_BITSET(CPU_ARM_RSVD_QUEUE_BITMAP(unit, pci_cmc), bit);
  21133             /* Verification suceeded. Program CMIC */
  21134             BCM_IF_ERROR_RETURN(_bcm_common_rx_queue_channel_set_helper(
  21135                         unit,
  21136                         queue_id,
  21137                         chan_off ,
  21138                         pci_cmc));
  21139 
  21140             LOG_INFO(BSL_LS_BCM_COSQ, (BSL_META_U(unit,
  21141                             "Queue id %d & channel id %d"
  21142                             " configured on l0 index %d\n "),
  21143                         queue_id, chan_off, l0_index));
  21144         }
  21145     }
  21146 
  21147 #endif /* CMICM Support */
  21148     return BCM_E_NONE;
  21149 }
  21150 
  21151 int
  21152 bcm_td2p_cosq_ets_mode(int unit)
  21153 {
  21154     /* second argument not being used by the function.
  21155      * passing 0 as a workaround.
  21156      * Should be passing local port for cpu port.
  21157  */
  21158     return _bcm_td2_cosq_port_has_ets(unit,0);
  21159 }
  21160 
  21161 #endif /* defined(BCM_TRIDENT2_SUPPORT) */