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


      1 /*
      2  * 
      3  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      4  * 
      5  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      6  *
      7  * COS Queue Management
      8  * Purpose: API to set different cosq, priorities, and scheduler registers.
      9  */
     10 
     11 #include <shared/bsl.h>
     12 
     13 #include <soc/defs.h>
     14 #include <sal/core/libc.h>
     15 #if defined(BCM_TRIUMPH3_SUPPORT)
     16 #include <soc/drv.h>
     17 #include <soc/scache.h>
     18 #include <soc/profile_mem.h>
     19 #include <soc/triumph3.h>
     20 #include <soc/phyctrl.h>
     21 #include <bcm/error.h>
     22 #include <bcm/cosq.h>
     23 #include <bcm_int/esw/mbcm.h>
     24 #include <bcm_int/esw/stack.h>
     25 #include <bcm_int/esw/cosq.h>
     26 #include <bcm_int/esw/triumph3.h>
     27 
     28 #include <bcm_int/esw_dispatch.h>
     29 
     30 #include <bcm_int/bst.h>
     31 #include <bcm_int/esw/cosq.h>
     32 
     33 #ifdef BCM_WARM_BOOT_SUPPORT
     34 #include <bcm_int/esw/switch.h>
     35 #endif /* BCM_WARM_BOOT_SUPPORT */
     36 
     37 #define TR3_CELL_FIELD_MAX       0x7fff
     38 
     39 /* MMU cell size in bytes */
     40 #define _BCM_TR3_PACKET_HEADER_BYTES       64    /* bytes */
     41 #define _BCM_TR3_DEFAULT_MTU_BYTES         1536  /* bytes */
     42 #define _BCM_TR3_TOTAL_CELLS               24576 /* 24k cells */
     43 #define _BCM_TR3_BYTES_PER_CELL            208   /* bytes */
     44 #define _BCM_TR3_BYTES_TO_CELLS(_byte_)  \
     45     (((_byte_) + _BCM_TR3_BYTES_PER_CELL - 1) / _BCM_TR3_BYTES_PER_CELL)
     46 
     47 #define _BCM_TR3_NUM_PORT_SCHEDULERS              64
     48 #define _BCM_TR3_NUM_L0_SCHEDULER                 256
     49 #define _BCM_TR3_NUM_L1_SCHEDULER                 512
     50 #define _BCM_TR3_NUM_L2_UC_LEAVES                 1024
     51 #define _BCM_TR3_NUM_L2_MC_LEAVES                 568
     52 #define _BCM_TR3_NUM_TOTAL_SCHEDULERS     (_BCM_TR3_NUM_PORT_SCHEDULERS + \
     53                                            _BCM_TR3_NUM_L0_SCHEDULER +    \
     54                                            _BCM_TR3_NUM_L1_SCHEDULER)
     55 
     56 #define _BCM_TR3_MMU_NUM_PG              8
     57 
     58 #define _BCM_TR3_COSQ_LIST_NODE_INIT(list, node)         \
     59     list[node].in_use            = FALSE;               \
     60     list[node].gport             = -1;                  \
     61     list[node].base_index        = -1;                  \
     62     list[node].numq              = 0;                   \
     63     list[node].base_size         = 0;                   \
     64     list[node].numq_expandable   = 0;                   \
     65     list[node].hw_index          = -1;                  \
     66     list[node].level             = -1;                  \
     67     list[node].attached_to_input       = -1;                  \
     68     list[node].hw_cosq           = 0;                   \
     69     list[node].remote_modid      = -1;                  \
     70     list[node].remote_port       = -1;                  \
     71     BCM_PBMP_CLEAR(list[node].fabric_pbmp);             \
     72     list[node].local_port        = -1;                  \
     73     list[node].parent            = NULL;                \
     74     list[node].sibling           = NULL;                \
     75     list[node].child             = NULL;                \
     76     list[node].type              = _BCM_TR3_NODE_UNKNOWN;
     77 
     78 #define _BCM_TR3_COSQ_NODE_INIT(node)                    \
     79     node->in_use            = FALSE;                    \
     80     node->gport             = -1;                       \
     81     node->base_index        = -1;                       \
     82     node->numq              = 0;                        \
     83     node->base_size         = 0;                        \
     84     node->numq_expandable   = 0;                        \
     85     node->hw_index          = -1;                       \
     86     node->level             = -1;                       \
     87     node->attached_to_input = -1;                       \
     88     node->hw_cosq           = 0;                        \
     89     node->remote_modid      = -1;                       \
     90     node->remote_port       = -1;                       \
     91     BCM_PBMP_CLEAR(node->fabric_pbmp);                  \
     92     node->local_port        = -1;                       \
     93     node->parent            = NULL;                     \
     94     node->sibling           = NULL;                     \
     95     node->child             = NULL;                     \
     96     node->num_child         = 0;                        \
     97     node->type              = _BCM_TR3_NODE_UNKNOWN;
     98 
     99 #define _BCM_TR3_MERGE_COLLATE(val3, val2, val1, val0)             \
    100         (val0 | ((val1 & 0xff) << 8) |                             \
    101         ((val2 & 0xff) << 16) | ((val3 & 0xff) << 24))
    102 
    103 #define _BCM_TR3_MERGE_RETRIEVE_0(val)     (val & 0xff)
    104 #define _BCM_TR3_MERGE_RETRIEVE_1(val)     ((val >> 8) & 0xff)
    105 #define _BCM_TR3_MERGE_RETRIEVE_2(val)     ((val >> 16) & 0xff)
    106 #define _BCM_TR3_MERGE_RETRIEVE_3(val)     ((val >> 24) & 0xff)
    107 
    108 /* TR3 supports eight PFC priority */
    109 #define _BCM_TR3_NUM_PFC_CLASS          8
    110 #define _TR3_NUM_INTERNAL_PRI          16
    111 
    112 typedef enum {
    113     _BCM_TR3_NODE_UNKNOWN = 0,
    114     _BCM_TR3_NODE_UCAST,
    115     _BCM_TR3_NODE_MCAST,
    116     _BCM_TR3_NODE_DMVOQ,
    117     _BCM_TR3_NODE_VLAN,
    118     _BCM_TR3_NODE_SCHEDULER
    119 } _bcm_tr3_node_type_e;
    120 
    121 typedef struct _bcm_tr3_cosq_node_s {
    122     struct _bcm_tr3_cosq_node_s *parent;
    123     struct _bcm_tr3_cosq_node_s *sibling;
    124     struct _bcm_tr3_cosq_node_s *child;
    125     bcm_gport_t gport;
    126     int in_use;
    127     int base_index;
    128     uint16 numq_expandable;
    129     uint16 base_size;
    130     int numq;
    131     int hw_index;
    132     soc_tr3_node_lvl_e level;
    133     _bcm_tr3_node_type_e type;
    134     int attached_to_input;
    135     int hw_cosq;
    136 
    137     /* DPVOQ specific information */
    138     bcm_port_t   local_port;
    139     bcm_module_t remote_modid;
    140     bcm_port_t   remote_port;
    141     int num_child;
    142     bcm_pbmp_t   fabric_pbmp;
    143 }_bcm_tr3_cosq_node_t;
    144 
    145 typedef struct _bcm_tr3_cosq_list_s {
    146     int count;
    147     SHR_BITDCL *bits;
    148 }_bcm_tr3_cosq_list_t;
    149 
    150 typedef struct {
    151     int enable;
    152     int shared_limit;
    153     int min_limit;
    154     int q_limit_dynamic;
    155 } _bcm_tr3_gport_q_disable_t;
    156 
    157 #define _BCM_TR3_MAX_PORT   SOC_MAX_NUM_PORTS
    158 
    159 #define _BCM_TR3_IS_UC_QUEUE(mmu_info,qid)   \
    160                 (((qid) < mmu_info->num_base_queues) ? 1 : 0)
    161 
    162 #define _BCM_TR3_IS_DESTMOD_QUEUE_GROUP(mmu_info, gport) \
    163            (((BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) && \
    164             ((BCM_GPORT_UCAST_QUEUE_GROUP_QID_GET(gport)) >= \
    165                                     (mmu_info)->num_base_queues)) || \
    166             (BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport) && \
    167             ((BCM_GPORT_DESTMOD_QUEUE_GROUP_QID_GET(gport)) < \
    168                                     (mmu_info)->num_dmvoq_queues)))  \
    169                                     ? 1 : 0)
    170 
    171 #define _SOC_TR3_ROOT_SCHEDULER_INDEX(u,p)   \
    172        SOC_INFO((u)).max_port_p2m_mapping[SOC_INFO((u)).port_l2p_mapping[(p)]]
    173 
    174 typedef struct _bcm_tr3_cosq_port_info_s {
    175     int mc_base;
    176     int mc_limit;
    177     int uc_base;
    178     int uc_limit;
    179     int eq_base;
    180     int eq_limit;
    181 } _bcm_tr3_cosq_port_info_t;
    182 
    183 typedef struct _bcm_tr3_mmu_info_s {
    184     int num_base_queues;   /* Number of classical queues */
    185 
    186     _bcm_tr3_cosq_list_t ext_qlist;      /* list of extended queues */
    187     _bcm_tr3_cosq_list_t dmvoq_qlist;      /* list of extended queues */
    188     _bcm_tr3_cosq_list_t l0_sched_list;  /* list of l0 sched nodes */
    189     _bcm_tr3_cosq_list_t l1_sched_list;  /* list of l1 sched nodes */
    190 
    191     _bcm_tr3_cosq_node_t sched_node[_BCM_TR3_NUM_TOTAL_SCHEDULERS]; /* sched nodes */
    192     _bcm_tr3_cosq_node_t queue_node[_BCM_TR3_NUM_L2_UC_LEAVES];    /* queue nodes */
    193     _bcm_tr3_cosq_node_t mc_queue_node[_BCM_TR3_NUM_L2_MC_LEAVES]; /* queue nodes */
    194     _bcm_tr3_cosq_port_info_t port_info[_BCM_TR3_MAX_PORT];
    195    
    196     bcm_pbmp_t                gport_unavail_pbm;
    197 
    198     int                       ets_mode;
    199     int                       curr_shared_limit;
    200     int                       curr_merger_index[4];
    201     int                       num_dmvoq_queues;  /* Number of dmvoq queues */
    202     int                       base_dmvoq_queue;  /* Base DMVOQ queue */
    203     int                       axp_ets_mode; /*ETS mode for each AXP ports*/
    204 }_bcm_tr3_mmu_info_t;
    205 
    206 static _bcm_tr3_mmu_info_t *_bcm_tr3_mmu_info[BCM_MAX_NUM_UNITS];  /* MMU info */
    207 
    208 static soc_profile_mem_t *_bcm_tr3_wred_profile[BCM_MAX_NUM_UNITS];
    209 static soc_profile_mem_t *_bcm_tr3_cos_map_profile[BCM_MAX_NUM_UNITS];
    210 static soc_profile_mem_t *_bcm_tr3_sample_int_profile[BCM_MAX_NUM_UNITS];
    211 static soc_profile_reg_t *_bcm_tr3_feedback_profile[BCM_MAX_NUM_UNITS];
    212 static soc_profile_reg_t *_bcm_tr3_llfc_profile[BCM_MAX_NUM_UNITS];
    213 static soc_profile_mem_t *_bcm_tr3_voq_port_map_profile[BCM_MAX_NUM_UNITS];
    214 static soc_profile_mem_t *_bcm_tr3_service_cos_map_profile[BCM_MAX_NUM_UNITS];
    215 static soc_profile_mem_t *_bcm_tr3_service_port_map_profile[BCM_MAX_NUM_UNITS];
    216 static soc_profile_mem_t *_bcm_tr3_ifp_cos_map_profile[BCM_MAX_NUM_UNITS];
    217 
    218 typedef enum {
    219     _BCM_TR3_COSQ_TYPE_UCAST,
    220     _BCM_TR3_COSQ_TYPE_MCAST,
    221     _BCM_TR3_COSQ_TYPE_EXT_UCAST
    222 } _bcm_tr3_cosq_type_t;
    223 
    224 #define IS_TR3_HSP_PORT(u,p)   \
    225         ((IS_CE_PORT((u),(p))) ||   \
    226         ((IS_HG_PORT((u),(p))) && (SOC_INFO((u)).port_speed_max[(p)] >= 100000)))
    227 
    228 
    229 /* Number of COSQs configured for this device */
    230 #if 0
    231 static int _bcm_tr3_num_cosq[SOC_MAX_NUM_DEVICES];
    232 #define _TR3_NUM_COS(unit)  _bcm_tr3_num_cosq[(unit)]
    233 #else
    234 #define _TR3_NUM_COS    NUM_COS
    235 #endif
    236 
    237 #define _TR3_NUM_HSP_COSQ 10
    238 #define _TR3_NUM_HG_COSQ  10
    239 
    240 STATIC int
    241 _bcm_tr3_cosq_node_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cos,
    242                        bcm_module_t *modid, bcm_port_t *port, 
    243                        int *id, _bcm_tr3_cosq_node_t **node);
    244 
    245 STATIC int
    246 _bcm_tr3_cosq_mapping_set(int unit, bcm_port_t ing_port, bcm_cos_t priority,
    247                          uint32 flags, bcm_gport_t gport, bcm_cos_queue_t cosq);
    248 
    249 STATIC int
    250 _bcm_tr3_cosq_sched_set(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
    251                        int mode, int weight, int adjust_cos);
    252 
    253 STATIC int 
    254 _bcm_tr3_cosq_egress_sp_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 
    255                         int *p_pool_start, int *p_pool_end);
    256 STATIC int
    257 _bcm_tr3_cosq_reserve_gport_resources(int unit, bcm_port_t port);
    258 
    259 STATIC int
    260 _bcm_tr3_cosq_unreserve_gport_resources(int unit, bcm_port_t port);
    261 
    262 STATIC int
    263 _bcm_tr3_node_index_set(_bcm_tr3_cosq_list_t *list, int start, int range);
    264 STATIC int
    265 _bcm_tr3_cosq_dynamic_thresh_enable_get(int unit, 
    266                         bcm_gport_t gport, bcm_cos_queue_t cosq,
    267                         bcm_cosq_control_t type, int *arg);
    268 STATIC int _bcm_tr3_voq_next_base_node_get(int unit, bcm_port_t port, 
    269         int modid,
    270         _bcm_tr3_cosq_node_t **base_node);
    271 
    272 #ifdef BCM_WARM_BOOT_SUPPORT
    273 
    274 #define BCM_WB_VERSION_1_0                SOC_SCACHE_VERSION(1,0)
    275 #define BCM_WB_VERSION_1_1                SOC_SCACHE_VERSION(1,1)
    276 #define BCM_WB_VERSION_1_2                SOC_SCACHE_VERSION(1,2)
    277 #define BCM_WB_VERSION_1_3                SOC_SCACHE_VERSION(1,3)
    278 #define BCM_WB_VERSION_1_4                SOC_SCACHE_VERSION(1,4)
    279 #define BCM_WB_VERSION_1_5                SOC_SCACHE_VERSION(1,5)
    280 #define BCM_WB_DEFAULT_VERSION            BCM_WB_VERSION_1_5
    281 
    282 #define _BCM_TR3_COSQ_WB_NUMCOSQ_MASK         0xf    /* [3:0] */
    283 #define _BCM_TR3_COSQ_WB_NUMCOSQ_SHIFT        0
    284 
    285 #define SET_FIELD(_field, _value)                       \
    286      (((_value) & _BCM_TR3_COSQ_WB_## _field## _MASK) <<  \
    287       _BCM_TR3_COSQ_WB_## _field## _SHIFT)
    288 #define GET_FIELD(_field, _byte)                        \
    289      (((_byte) >> _BCM_TR3_COSQ_WB_## _field## _SHIFT) &  \
    290      _BCM_TR3_COSQ_WB_## _field## _MASK)
    291 
    292 /*
    293  * This funtion encodes the 1 byte of the common  data to be written in to
    294  * scache.Currently only last 4 bits of the byte are used for storing
    295  * numcosq value rest can be used if necessary later.
    296  */ 
    297 STATIC void 
    298  _bcm_tr3_cosq_wb_encode_data(int unit,char *scache_ptr)
    299  {
    300      char data = 0;
    301      int numq = 0;
    302 
    303      bcm_tr3_cosq_config_get(unit,&numq);
    304      data  = SET_FIELD(NUMCOSQ, numq);
    305      *scache_ptr = data; 
    306 
    307  }
    308 
    309 STATIC int
    310 _bcm_tr3_cosq_wb_alloc(int unit)
    311 {
    312     _bcm_tr3_mmu_info_t *mmu_info;
    313     soc_scache_handle_t scache_handle;
    314     uint8 *scache_ptr;
    315     int rv, alloc_size, node_list_sizes[3], ii, jj;
    316     int qcount=0;
    317     
    318     mmu_info = _bcm_tr3_mmu_info[unit];
    319 
    320     if (!mmu_info) {
    321         return BCM_E_INIT;
    322     }
    323 
    324     node_list_sizes[0] = _BCM_TR3_NUM_L2_UC_LEAVES;
    325     node_list_sizes[1] = _BCM_TR3_NUM_L2_MC_LEAVES;
    326     node_list_sizes[2] = _BCM_TR3_NUM_TOTAL_SCHEDULERS;
    327 
    328     alloc_size = 0;
    329     for(ii = 0; ii < 3; ii++) {
    330         alloc_size += sizeof(uint32);
    331         for(jj = 0; jj < node_list_sizes[ii]; jj++) {
    332             alloc_size += 4 * sizeof(uint32);
    333         }
    334     }
    335 /* 
    336  * Allocating 1 byte of data first 4 bits will be used
    337  * for storing numcosq
    338  */
    339     alloc_size += sizeof(char); 
    340 
    341     /* Adjust the pointer to quad boundary (1byte previously+3by pad  */
    342     alloc_size += 3;
    343 
    344     /* BCM_WB_VERSION_1_2: a) Added numq */
    345     /* Each qcount is stored in 11 LSBs of 16bits in scache,
    346      * leaving 5 bits free which can be used later.
    347     */
    348     for (ii = 0; ii < 3; ii++) {
    349         for (jj = 0; jj < node_list_sizes[ii]; jj++) {
    350             qcount++;
    351         }
    352     }
    353 
    354     /* Align the mem requiremet to quad boundary. */
    355     if (qcount & 0x1) {
    356         qcount++;
    357     }
    358     alloc_size += qcount * 2;
    359 
    360     /* BCM_WB_VERSION_1_2: b) Added ets_mode. */
    361     alloc_size += 1 * sizeof(int);
    362 
    363     for (ii = 0; ii < 3; ii++) {
    364         for (jj = 0; jj < node_list_sizes[ii]; jj++) {
    365             alloc_size += sizeof(bcm_pbmp_t);
    366         }
    367     }
    368     alloc_size += sizeof(int);
    369     alloc_size += sizeof(int);
    370 
    371     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_COSQ, 0);
    372 
    373     rv = _bcm_esw_scache_ptr_get(unit, scache_handle, TRUE, alloc_size,
    374                                  &scache_ptr, BCM_WB_DEFAULT_VERSION, NULL);
    375     if (rv == BCM_E_NOT_FOUND) {
    376         rv = BCM_E_NONE;
    377     }
    378 
    379     return rv;
    380 }
    381 
    382 #define _BCM_TR3_WB_SET_NODE_W1(ntype,nid,sz,parentid,cosqatt,lvl)    \
    383     (((ntype & 3)) | \
    384      (((sz) & 7) << 2) | \
    385      (((nid) & 0x3ff) << 5) | \
    386      (((parentid) & 0x3ff) << 15) | \
    387      (((cosqatt) & 0xf) << 25) | \
    388      (((lvl) & 0x7) << 29))
    389 
    390 #define _BCM_TR3_WB_GET_NODE_ID_W1(w1) (((w1) >> 5) & 0x3ff)
    391 
    392 #define _BCM_TR3_WB_GET_NODE_TYPE_W1(w1) ((w1) & 3)
    393 
    394 #define _BCM_TR3_WB_GET_NODE_SIZE_W1(w1) (((w1) >> 2) & 7)
    395 
    396 #define _BCM_TR3_WB_GET_NODE_PARENT_W1(w1) (((w1) >> 15) & 0x3ff)
    397 
    398 #define _BCM_TR3_WB_GET_NODE_COSQATTT_W1(w1) (((w1) >> 25) & 0xf)
    399 
    400 #define _BCM_TR3_WB_GET_NODE_LEVEL_W1(w1) (((w1) >> 29) & 0x7)
    401 
    402 
    403 /* 11 bit hw index, 3 bit hw cosq, 1 bit parent high */
    404 /* Parent index requires 11 bits (10 bits + 1 for invalid bit). Since 10 bits
    405     are already stored above, the higher 1 bit is stored here */
    406 
    407 #define _BCM_TR3_WB_SET_NODE_W2(hwindex,hwcosq,parent_hi)    \
    408     ((((hwindex) & 0x7ff)) | (((hwcosq) & 0xf) << 11) | (((parent_hi) & 0x1) << 15))
    409 
    410 #define _BCM_TR3_WB_GET_NODE_HW_INDEX_W2(w1) ((w1) & 0x7ff)
    411 
    412 #define _BCM_TR3_WB_GET_NODE_HW_COSQ_W2(w1) (((w1) >> 11) & 0xf)
    413 
    414 #define _BCM_TR3_WB_GET_NODE_PARENT_HI_W2(w1) (((w1) >> 15) & 0x1)
    415 
    416 #define _BCM_TR3_WB_SET_NODE_W3(gport)    (gport)
    417 
    418 #define _BCM_TR3_WB_SET_NODE_W4(remote_modid,remote_port,voq_cosq)    \
    419     ((((remote_modid) & 0x1ff)) | \
    420      (((remote_port) & 0x1ff) << 9) | \
    421      (((voq_cosq) & 0xf) << 18))
    422 
    423 #define _BCM_TR3_WB_GET_NODE_DEST_MODID_W4(w1) ((w1) & 0x1ff)
    424 
    425 #define _BCM_TR3_WB_GET_NODE_DEST_PORT_W4(w1) (((w1) >> 9) & 0x1ff)
    426 
    427 #define _BCM_TR3_WB_GET_NODE_VOQ_COSQ_W4(w1) (((w1) >> 18) & 0xf)
    428 
    429 #define _BCM_TR3_NODE_ID(np,np0) (np - np0)
    430 
    431 int
    432 bcm_tr3_cosq_sync(int unit)
    433 {
    434     soc_scache_handle_t scache_handle;
    435     uint8 *scache_ptr,*u8_scache_ptr;
    436     uint32 *u32_scache_ptr;
    437     uint16 *u16_scache_ptr;
    438     _bcm_tr3_cosq_node_t *node;
    439     int node_list_sizes[3], ii, jj;
    440     _bcm_tr3_cosq_node_t *nodes[3];
    441     int xnode_id, xnode_id_hi, node_size, count;
    442     uint32 *psize;
    443     _bcm_tr3_mmu_info_t *mmu_info;
    444     int scache_hw_index = 0;
    445     int qcount = 0;
    446 
    447     mmu_info = _bcm_tr3_mmu_info[unit];
    448 
    449     if (!mmu_info) {
    450         return BCM_E_INIT;
    451     }
    452 
    453     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_COSQ, 0);
    454     BCM_IF_ERROR_RETURN
    455         (_bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 0,
    456                                  &scache_ptr, BCM_WB_DEFAULT_VERSION, NULL));
    457 
    458     u32_scache_ptr = (uint32*) scache_ptr;
    459 
    460     nodes[0] = &mmu_info->queue_node[0];
    461     node_list_sizes[0] = _BCM_TR3_NUM_L2_UC_LEAVES;
    462     nodes[1] = &mmu_info->mc_queue_node[0];
    463     node_list_sizes[1] = _BCM_TR3_NUM_L2_MC_LEAVES;
    464     nodes[2] = &mmu_info->sched_node[0];
    465     node_list_sizes[2] = _BCM_TR3_NUM_TOTAL_SCHEDULERS;
    466 
    467     for(ii = 0; ii < 3; ii++) {
    468         psize = u32_scache_ptr++;
    469         for(count = 0, jj = 0; jj < node_list_sizes[ii]; jj++) {
    470             node = nodes[ii] + jj;
    471             if (node->in_use == FALSE) {
    472                 continue;
    473             }
    474             count += 1;
    475             node_size = 3;
    476             if ((node->remote_modid != -1) || (node->remote_port != -1) ||
    477                 (node->hw_cosq != -1)) {
    478                 node_size += 1;
    479             }
    480             
    481             xnode_id = _BCM_TR3_NODE_ID(node->parent, mmu_info->sched_node);
    482             if (node->parent == NULL) {
    483                 xnode_id_hi = 0x1;
    484             } else {
    485                 xnode_id_hi = 0;
    486             }
    487 
    488             *u32_scache_ptr++ = _BCM_TR3_WB_SET_NODE_W1(ii, jj, node_size,
    489                                 xnode_id,
    490                 ((node->attached_to_input == -1) ? 0x8 : node->attached_to_input), 
    491                                 node->level);
    492 
    493             
    494             /* Multicast queues use indexes above 1024 */
    495             if (ii == 1) {
    496                 scache_hw_index = (node->hw_index == -1) ? 0x400 : (node->hw_index - 1024);
    497             } else {
    498                 scache_hw_index = (node->hw_index == -1) ? 0x400 : (node->hw_index);
    499             }
    500                 
    501             *u32_scache_ptr++ = _BCM_TR3_WB_SET_NODE_W2(scache_hw_index,
    502                     ((node->hw_cosq == -1) ? 8 : node->hw_cosq), xnode_id_hi);
    503 
    504             *u32_scache_ptr++ = _BCM_TR3_WB_SET_NODE_W3(node->gport);
    505 
    506             if ((node->remote_modid != -1) || (node->remote_port != -1) ||
    507                 (node->hw_cosq != -1)) {
    508                 node_size += 1;
    509                 *u32_scache_ptr++ = _BCM_TR3_WB_SET_NODE_W4(
    510                     (node->remote_modid == -1) ? 0x100 : node->remote_modid,
    511                     (node->remote_port == -1) ? 0x100 : node->remote_port,
    512                     (node->hw_cosq == -1) ? 0x8 : node->hw_cosq);
    513             }
    514         }
    515         *psize = count;
    516     }
    517 /* add numcosq info to the scache */ 
    518     _bcm_tr3_cosq_wb_encode_data( unit,(char *)u32_scache_ptr);
    519 
    520     /* Advance ptr by 4bytes, 1 for above encoding + 3 bytes for padding */
    521     u32_scache_ptr++;
    522     u16_scache_ptr = (uint16 *)u32_scache_ptr;
    523 
    524     /* BCM_WB_VERSION_1_2: Sync numq (11bits) parameter.5 MSBits free */
    525     for (ii = 0; ii < 3; ii++) {
    526         for (count = 0, jj = 0; jj < node_list_sizes[ii]; jj++) {
    527             node = nodes[ii] + jj;
    528             if (node->in_use == FALSE) {
    529                 continue;
    530             }
    531             *u16_scache_ptr++ = node->numq & 0x7ff;
    532             qcount++;
    533         }
    534     }
    535     /* Move the pointer to quad boundary */
    536     if (qcount & 0x1) {
    537         u16_scache_ptr++;
    538     }
    539 
    540     u32_scache_ptr = (uint32 *)u16_scache_ptr;
    541 
    542     /* BCM_WB_VERSION_1_2: Sync ets_mode. */
    543     *u32_scache_ptr++ = mmu_info->ets_mode;
    544 
    545     u8_scache_ptr =(uint8 *) u32_scache_ptr;
    546     /* BCM_WB_VERSION_1_4: Sync fabric parameter. */
    547     for (ii = 0; ii < 3; ii++) {
    548         for (count = 0, jj = 0; jj < node_list_sizes[ii]; jj++) {
    549             node = nodes[ii] + jj;
    550             if (node->in_use == FALSE) {
    551                 continue;
    552             }
    553             sal_memcpy(u8_scache_ptr, &node->fabric_pbmp, sizeof(bcm_pbmp_t));
    554             u8_scache_ptr += sizeof(bcm_pbmp_t);
    555         }
    556     }
    557 
    558     u32_scache_ptr = (uint32 *)u8_scache_ptr;
    559 
    560     *u32_scache_ptr++ = _BCM_TR3_MERGE_COLLATE (
    561                             mmu_info->curr_merger_index[3],
    562                             mmu_info->curr_merger_index[2],
    563                             mmu_info->curr_merger_index[1],
    564                             mmu_info->curr_merger_index[0]);
    565     /* BCM_WB_VERSION_1_5: Sync axp_ets_mode parameter. */
    566     *u32_scache_ptr++ = mmu_info->axp_ets_mode;
    567 
    568     return BCM_E_NONE;
    569 }
    570 
    571 int
    572 bcm_tr3_cosq_reinit(int unit)
    573 {
    574     soc_scache_handle_t scache_handle;
    575     uint8 *scache_ptr, *u8_scache_ptr;
    576     uint32 *u32_scache_ptr, *u32_base_ptr, *u32_base_ptr1, wval, fval;
    577     uint16 *u16_scache_ptr;
    578     _bcm_tr3_cosq_node_t *node;
    579     bcm_port_t port;
    580     int rv, ii, jj, set_index;
    581     _bcm_tr3_cosq_node_t *nodes[3];
    582     int xnode_id, stable_size, node_size, count;
    583     _bcm_tr3_mmu_info_t *mmu_info;
    584     uint32 entry[SOC_MAX_MEM_WORDS], tmp32;
    585     soc_profile_mem_t *profile_mem;
    586     soc_info_t *si;
    587     int phy_port, mmu_port, profile_index;
    588     uint64  rval64, index_map;
    589     soc_reg_t reg;
    590     mmu_wred_config_entry_t qentry;
    591     int numq = 0;
    592     uint16 recovered_ver = 0;
    593     char data;
    594     int additional_scache_size = 0;
    595     int qcount=0;
    596     int parent_id = 0;
    597     int    node_list_sizes[3];
    598     static const soc_reg_t llfc_cfgr[] = {
    599         PORT_PFC_CFG0r, PORT_PFC_CFG1r
    600     };
    601 
    602     SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size));
    603     if ((stable_size == 0) || (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit))) { 
    604         /* COSQ warmboot requires extended scache support i.e. level2 warmboot*/  
    605         return BCM_E_NONE;
    606     }
    607 
    608     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_COSQ, 0);
    609     rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 0, &scache_ptr,
    610                                  BCM_WB_DEFAULT_VERSION, &recovered_ver);
    611     if (BCM_FAILURE(rv)) {
    612         return rv;
    613     }
    614 
    615     mmu_info = _bcm_tr3_mmu_info[unit];
    616 
    617     if (!mmu_info) {
    618         return BCM_E_INIT;
    619     }
    620 
    621     si = &SOC_INFO(unit);
    622     u32_scache_ptr = (uint32*) scache_ptr;
    623 
    624     nodes[0] = &mmu_info->queue_node[0];
    625     nodes[1] = &mmu_info->mc_queue_node[0];
    626     nodes[2] = &mmu_info->sched_node[0];
    627 
    628     u32_base_ptr = u32_scache_ptr;
    629     u32_base_ptr1 = u32_scache_ptr;
    630     for(ii = 0; ii < 3; ii++) {
    631         count = *u32_scache_ptr;
    632         u32_scache_ptr++;
    633         for(jj = 0; jj < count; jj++) {
    634             wval = *u32_scache_ptr;
    635             u32_scache_ptr++;
    636             xnode_id = _BCM_TR3_WB_GET_NODE_ID_W1(wval);
    637             node = nodes[ii] + xnode_id;
    638             node->in_use = TRUE;
    639             node->numq = 1;
    640             node_size = _BCM_TR3_WB_GET_NODE_SIZE_W1(wval);
    641             fval =  _BCM_TR3_WB_GET_NODE_PARENT_W1(wval);
    642             if (recovered_ver >= BCM_WB_VERSION_1_3) {
    643                 parent_id = fval;
    644             } else {
    645                 if (fval & 0x200) {
    646                 } else {
    647                     node->parent = &mmu_info->sched_node[fval];
    648                     if (node->parent->child) {
    649                         node->sibling = node->parent->child;
    650                     }
    651                     node->parent->child = node;
    652                 }
    653             }
    654 
    655             fval = _BCM_TR3_WB_GET_NODE_COSQATTT_W1(wval);
    656             if (fval & 8) {
    657                 node->attached_to_input = -1;
    658             } else {
    659                 node->attached_to_input = fval;
    660             }
    661 
    662             node->level = _BCM_TR3_WB_GET_NODE_LEVEL_W1(wval);
    663 
    664             wval = *u32_scache_ptr;
    665             u32_scache_ptr++;
    666             
    667             fval = _BCM_TR3_WB_GET_NODE_HW_INDEX_W2(wval);
    668             if (fval & 0x400) {
    669                 node->hw_index = -1;
    670             } else {
    671                 node->hw_index = fval;
    672                 if (recovered_ver >= BCM_WB_VERSION_1_3) {
    673                     /* Multicast queues use indexes above 1024 */
    674                     if(ii == 1) {
    675                         node->hw_index = fval + 1024;
    676                     }
    677                 }
    678             }
    679 
    680             fval = _BCM_TR3_WB_GET_NODE_HW_COSQ_W2(wval);
    681             if (fval & 8) {
    682                 node->hw_cosq = -1;
    683             } else {
    684                 node->hw_cosq = fval;
    685             }
    686 
    687             if (recovered_ver >= BCM_WB_VERSION_1_3) {
    688                 /* The parent is now 11 bit and the 11th bit is
    689                  * stored separately for backward compatibility (upgrade /
    690                  * downgrade). The invalid parent id is checked for
    691                  * with 0x400.
    692                  */
    693                 fval = _BCM_TR3_WB_GET_NODE_PARENT_HI_W2(wval);
    694                 parent_id |= (fval << 10);
    695                 if (parent_id & 0x400) {
    696                 } else {
    697                     node->parent = &mmu_info->sched_node[parent_id];
    698                     if (node->parent->child) {
    699                         node->sibling = node->parent->child;
    700                     }
    701                     node->parent->child = node;
    702                 }
    703             }
    704 
    705             wval = *u32_scache_ptr;
    706             u32_scache_ptr++;
    707             node->gport = wval;
    708 
    709             /*
    710              * The function is used for getting local_port.
    711              * Return value is intentionally not checked.
    712              */
    713             (void)_bcm_tr3_cosq_node_get(unit, node->gport, 0, NULL,
    714                 &node->local_port, NULL, NULL);
    715 
    716             if (node->hw_index != -1) {
    717                 if (node->level == SOC_TR3_NODE_LVL_L0) {
    718                     _bcm_tr3_node_index_set(&mmu_info->l0_sched_list, 
    719                                             node->hw_index, 1);
    720                 } else if (node->level == SOC_TR3_NODE_LVL_L1) {
    721                     _bcm_tr3_node_index_set(&mmu_info->l1_sched_list, 
    722                                             node->hw_index, 1);
    723                 } else if (node->level == SOC_TR3_NODE_LVL_L2) {
    724                     if (_BCM_TR3_IS_DESTMOD_QUEUE_GROUP(mmu_info, node->gport)) {
    725                         if (mmu_info->num_dmvoq_queues > 0) {
    726                             _bcm_tr3_node_index_set(&mmu_info->dmvoq_qlist, 
    727                                                     node->hw_index, 1);
    728                         } else {
    729                             _bcm_tr3_node_index_set(&mmu_info->ext_qlist, 
    730                                                     node->hw_index, 1);
    731                         }
    732                     }
    733                 }
    734             }
    735 
    736             if (node_size > 3) {
    737                 wval = *u32_scache_ptr;
    738                 u32_scache_ptr++;
    739     
    740                 fval = _BCM_TR3_WB_GET_NODE_DEST_MODID_W4(wval);
    741                 if (fval & 0x100) {
    742                     node->remote_modid = -1;
    743                 } else {
    744                     node->remote_modid = fval;
    745                 }
    746 
    747                 fval = _BCM_TR3_WB_GET_NODE_DEST_PORT_W4(wval);
    748                 if (fval & 0x100) {
    749                     node->remote_port = -1;
    750                 } else {
    751                     node->remote_port = fval;
    752                 }
    753 
    754                 fval = _BCM_TR3_WB_GET_NODE_VOQ_COSQ_W4(wval);
    755                 if (fval & 0x8) {
    756                     node->hw_cosq = -1;
    757                 } else {
    758                     node->hw_cosq = fval;
    759                 }
    760             }
    761         }
    762     }
    763     if(recovered_ver >= BCM_WB_VERSION_1_1) {
    764        data=*((char *)u32_scache_ptr);
    765        numq = GET_FIELD(NUMCOSQ,data); 
    766        bcm_tr3_cosq_config_set(unit,numq);
    767     }
    768     else { 
    769        additional_scache_size = sizeof(char);  
    770     }  
    771 
    772     /* Advance ptr by 4bytes=1byte for previous encoding+3bytes of padding */
    773        u32_scache_ptr++;
    774        u16_scache_ptr = (uint16 *)u32_scache_ptr;
    775 
    776     /* BCM_WB_VERSION_1_2: Recover numq parameter. */
    777     if (recovered_ver >= BCM_WB_VERSION_1_2) {
    778         for (ii = 0; ii < 3; ii++) {
    779             count = *u32_base_ptr++;
    780             for (jj = 0; jj < count; jj++) {
    781                 wval = *u32_base_ptr++;
    782                 xnode_id = _BCM_TR3_WB_GET_NODE_ID_W1(wval);
    783                 node = nodes[ii] + xnode_id;
    784                 node_size = _BCM_TR3_WB_GET_NODE_SIZE_W1(wval);
    785 
    786                 node->numq = *u16_scache_ptr++ & 0x7ff;
    787                 qcount++;
    788 
    789                 u32_base_ptr += 2;
    790                 if (node_size > 3) {
    791                     u32_base_ptr++;
    792                 }
    793             }
    794         }
    795         /* Adjust ptr to quad boundary */
    796         if (qcount & 0x1) {
    797             u16_scache_ptr++;
    798         }
    799 
    800         u32_scache_ptr = (uint32 *)u16_scache_ptr;
    801         /* BCM_WB_VERSION_1_2: Recover ets_mode. */
    802         mmu_info->ets_mode = *u32_scache_ptr++;
    803     } else {
    804         node_list_sizes[0] = _BCM_TR3_NUM_L2_UC_LEAVES;
    805         node_list_sizes[1] = _BCM_TR3_NUM_L2_MC_LEAVES;
    806         node_list_sizes[2] = _BCM_TR3_NUM_TOTAL_SCHEDULERS;
    807 
    808         /* BCM_WB_VERSION_1_2: a) Added numq */
    809         /* Each qcount is stored in 11 LSBs of 16bits in scache,
    810          * leaving 5 bits free which can be used later.
    811         */
    812         for (ii = 0; ii < 3; ii++) {
    813             for (jj = 0; jj < node_list_sizes[ii]; jj++) {
    814                 qcount++;
    815             }
    816         }
    817 
    818         /* Align the mem requiremet to quad boundary. */
    819         if (qcount & 0x1) {
    820             qcount++;
    821         }
    822         additional_scache_size += qcount * 2;
    823 
    824         /* BCM_WB_VERSION_1_2: Added ets_mode. */
    825         additional_scache_size += 1 * sizeof(int);
    826     }
    827 
    828     /* BCM_WB_VERSION_1_4: Recover fabric parameter. */
    829     if (recovered_ver >= BCM_WB_VERSION_1_4) {
    830         u8_scache_ptr = (uint8 *)u32_scache_ptr;
    831         for (ii = 0; ii < 3; ii++) {
    832             count = *u32_base_ptr1++;
    833             for (jj = 0; jj < count; jj++) {
    834                 wval = *u32_base_ptr1++;
    835                 xnode_id = _BCM_TR3_WB_GET_NODE_ID_W1(wval);
    836                 node = nodes[ii] + xnode_id;
    837                 node_size = _BCM_TR3_WB_GET_NODE_SIZE_W1(wval);
    838 
    839                 sal_memcpy(&node->fabric_pbmp, u8_scache_ptr,
    840                             sizeof(bcm_pbmp_t));
    841                 u8_scache_ptr += sizeof(bcm_pbmp_t);
    842                 u32_base_ptr1 += 2;
    843                 if (node_size > 3) {
    844                     u32_base_ptr1++;
    845                 }
    846             }
    847         }
    848         u32_scache_ptr = (uint32 *)u8_scache_ptr;
    849         mmu_info->curr_merger_index[0] = _BCM_TR3_MERGE_RETRIEVE_0(*u32_scache_ptr);
    850         mmu_info->curr_merger_index[1] = _BCM_TR3_MERGE_RETRIEVE_1(*u32_scache_ptr);
    851         mmu_info->curr_merger_index[2] = _BCM_TR3_MERGE_RETRIEVE_2(*u32_scache_ptr);
    852         mmu_info->curr_merger_index[3] = _BCM_TR3_MERGE_RETRIEVE_3(*u32_scache_ptr);
    853         u32_scache_ptr++;
    854     } else {
    855         for (ii = 0; ii < 3; ii++) {
    856             for (jj = 0; jj < node_list_sizes[ii]; jj++) {
    857                 additional_scache_size += sizeof(bcm_pbmp_t);
    858             }
    859         }
    860         additional_scache_size++;
    861     }
    862 
    863     if (recovered_ver >= BCM_WB_VERSION_1_5) {
    864         mmu_info->axp_ets_mode = *u32_scache_ptr++;
    865     } else {
    866         additional_scache_size++;
    867     }
    868 
    869     /* Update PORT_COS_MAP memory profile reference counter */
    870     profile_mem = _bcm_tr3_cos_map_profile[unit];
    871     PBMP_ALL_ITER(unit, port) {
    872         SOC_IF_ERROR_RETURN
    873             (soc_mem_read(unit, COS_MAP_SELm, MEM_BLOCK_ALL, port, &entry));
    874         set_index = soc_mem_field32_get(unit, COS_MAP_SELm, &entry, SELECTf);
    875         SOC_IF_ERROR_RETURN
    876             (soc_profile_mem_reference(unit, profile_mem, set_index * 16, 16));
    877     }
    878     if (SOC_INFO(unit).cpu_hg_index != -1) {
    879         SOC_IF_ERROR_RETURN(soc_mem_read(unit, COS_MAP_SELm, MEM_BLOCK_ALL,
    880                                          SOC_INFO(unit).cpu_hg_index, &entry));
    881         set_index = soc_mem_field32_get(unit, COS_MAP_SELm, &entry, SELECTf);
    882         SOC_IF_ERROR_RETURN
    883             (soc_profile_mem_reference(unit, profile_mem, set_index, 1));
    884     }
    885 
    886     PBMP_ALL_ITER(unit, port) {
    887         if (IS_CPU_PORT(unit, port)) {
    888             continue;
    889         }
    890     
    891         phy_port = si->port_l2p_mapping[port];
    892         mmu_port = si->port_p2m_mapping[phy_port];
    893 
    894         reg = llfc_cfgr[mmu_port/32];
    895 
    896         BCM_IF_ERROR_RETURN(soc_reg64_get(unit, reg, 0, 0, &rval64));
    897 
    898         index_map = soc_reg64_field_get(unit, reg, rval64, PROFILE_INDEXf);
    899         COMPILER_64_SHR(index_map, ((mmu_port % 32) * 2));
    900         COMPILER_64_TO_32_LO(tmp32, index_map);
    901         set_index = (tmp32 & 3)*16;
    902 
    903         SOC_IF_ERROR_RETURN
    904             (soc_profile_reg_reference(unit, _bcm_tr3_llfc_profile[unit], 
    905                                         set_index * 16, 16));
    906     }
    907 
    908     for (ii = soc_mem_index_min(unit, MMU_WRED_CONFIGm);
    909          ii <= soc_mem_index_max(unit, MMU_WRED_CONFIGm); ii++) {
    910         BCM_IF_ERROR_RETURN(
    911               soc_mem_read(unit, MMU_WRED_CONFIGm, MEM_BLOCK_ALL, ii, &qentry));
    912          
    913         profile_index = soc_mem_field32_get(unit, MMU_WRED_CONFIGm,
    914                                         &qentry, PROFILE_INDEXf);
    915          
    916         BCM_IF_ERROR_RETURN
    917             (soc_profile_mem_reference(unit, _bcm_tr3_wred_profile[unit],
    918                                        profile_index, 1));
    919     }
    920 
    921   /* addtional space is required for scache  */
    922   if(additional_scache_size) {
    923      rv = soc_scache_realloc(unit,scache_handle,additional_scache_size); 
    924      if(BCM_FAILURE(rv)) {
    925         return rv;
    926      }
    927   }
    928     return BCM_E_NONE;
    929 }
    930 #endif /* BCM_WARM_BOOT_SUPPORT */
    931 
    932 #ifndef BCM_SW_STATE_DUMP_DISABLE
    933 STATIC char*
    934 _bcm_tr3_cosq_node_lvl_str(soc_tr3_node_lvl_e lvl)
    935 {
    936     switch(lvl) {
    937         case SOC_TR3_NODE_LVL_ROOT:
    938             return "Root";
    939         break;
    940         case SOC_TR3_NODE_LVL_L0:
    941             return " L0";
    942         break;
    943         case SOC_TR3_NODE_LVL_L1:
    944             return "  L1";
    945         break;
    946         case SOC_TR3_NODE_LVL_L2:
    947             return "   Q";
    948         break;
    949         case SOC_TR3_NODE_LVL_MAX:
    950         break;
    951     }
    952     return "";
    953 }
    954 
    955 STATIC void
    956 _bcm_tr3_cosq_dump_node(_bcm_tr3_cosq_node_t *node, int loff)
    957 {
    958     LOG_CLI((BSL_META("%s.%d index=%d cosq=%d gport=0x%08x numq=%d\n"), 
    959 _bcm_tr3_cosq_node_lvl_str(node->level),
    960              loff, node->hw_index, node->attached_to_input,
    961              node->gport, node->numq));
    962 
    963     if (node->child) {
    964         _bcm_tr3_cosq_dump_node(node->child, 0);
    965     }
    966 
    967     if (node->sibling) {
    968         _bcm_tr3_cosq_dump_node(node->sibling, loff+1);
    969     }
    970 }
    971 
    972 STATIC void
    973 _bcm_tr3_cosq_port_sw_dump(int unit, bcm_port_t port)
    974 {
    975     _bcm_tr3_mmu_info_t *mmu_info;
    976     int phy_port, mmu_port, ii;
    977     _bcm_tr3_cosq_node_t *node = NULL, *tnode;
    978     soc_info_t *si;
    979 
    980     si = &SOC_INFO(unit);
    981     mmu_info = _bcm_tr3_mmu_info[unit];
    982 
    983     phy_port = si->port_l2p_mapping[port];
    984     mmu_port = si->port_p2m_mapping[phy_port];
    985 
    986     for (ii = 0; ii < _BCM_TR3_NUM_PORT_SCHEDULERS; ii++) {
    987         tnode = &mmu_info->sched_node[ii];
    988         if (tnode->in_use == FALSE) {
    989             continue;
    990         }
    991         if ((tnode->level == SOC_TR3_NODE_LVL_ROOT) &&
    992             (tnode->hw_index == mmu_port)) {   
    993             node = tnode;
    994             break;
    995         }
    996     }
    997     if (node == NULL) {
    998         return;
    999     }
   1000 
   1001     _bcm_tr3_cosq_dump_node(node, 0);
   1002 }
   1003 
   1004 /*
   1005  * Function:
   1006  *     bcm_tr3_cosq_sw_dump
   1007  * Purpose:
   1008  *     Displays COS Queue information maintained by software.
   1009  * Parameters:
   1010  *     unit - Device unit number
   1011  * Returns:
   1012  *     None
   1013  */
   1014 void
   1015 bcm_tr3_cosq_sw_dump(int unit)
   1016 {
   1017     bcm_port_t port;
   1018 
   1019     PBMP_ALL_ITER(unit, port) {
   1020         _bcm_tr3_cosq_port_sw_dump(unit, port);
   1021     }
   1022 
   1023     return;
   1024 }
   1025 #endif /*  BCM_SW_STATE_DUMP_DISABLE */
   1026 
   1027 /*
   1028  * Function:
   1029  *     _bcm_tr3_cosq_localport_resolve
   1030  * Purpose:
   1031  *     Resolve GRPOT if it is a local port
   1032  * Parameters:
   1033  *     unit       - (IN) unit number
   1034  *     gport      - (IN) GPORT identifier
   1035  *     local_port - (OUT) local port number
   1036  * Returns:
   1037  *     BCM_E_XXX
   1038  */
   1039 int
   1040 _bcm_tr3_cosq_localport_resolve(int unit, bcm_gport_t gport,
   1041                                bcm_port_t *local_port)
   1042 {
   1043     bcm_module_t module;
   1044     bcm_port_t port;
   1045     bcm_trunk_t trunk;
   1046     int id, result;
   1047 
   1048     if (!BCM_GPORT_IS_SET(gport)) {
   1049         if (!SOC_PORT_VALID(unit, gport)) {
   1050             return BCM_E_PORT;
   1051         }
   1052         *local_port = gport;
   1053         return BCM_E_NONE;
   1054     }
   1055 
   1056     BCM_IF_ERROR_RETURN
   1057         (_bcm_esw_gport_resolve(unit, gport, &module, &port, &trunk, &id));
   1058 
   1059     BCM_IF_ERROR_RETURN(_bcm_esw_modid_is_local(unit, module, &result));
   1060     if (result == FALSE) {
   1061         return BCM_E_PARAM;
   1062     }
   1063 
   1064     *local_port = port;
   1065 
   1066     return BCM_E_NONE;
   1067 }
   1068 
   1069 STATIC int
   1070 _bcm_tr3_cosq_port_has_ets(int unit, bcm_port_t port)
   1071 {
   1072     _bcm_tr3_mmu_info_t *mmu_info = _bcm_tr3_mmu_info[unit];
   1073 
   1074     /* For HSP port we create Hierarchy internally. So return TRUE for HSP port */ 
   1075     if (IS_TR3_HSP_PORT(unit, port)) {
   1076         return 1;
   1077     }
   1078     return mmu_info->ets_mode;
   1079 }
   1080 
   1081 /*
   1082  * Function:
   1083  *     _bcm_tr3_node_index_get
   1084  * Purpose:
   1085  *     Allocate free index from the given list
   1086  * Parameters:
   1087  *     list       - (IN) bit list
   1088  *     start      - (IN) start index
   1089  *     end        - (IN) end index
   1090  *     qset       - (IN) size of queue set
   1091  *     range      - (IN) range bits
   1092  *     id         - (OUT) start index
   1093  * Returns:
   1094  *     BCM_E_XXX
   1095  */
   1096 STATIC int
   1097 _bcm_tr3_node_index_get(SHR_BITDCL *list, int start, int end,
   1098                        int count, int align, int *id)
   1099 {
   1100     int i, j, range_empty;
   1101 
   1102     *id = -1;
   1103 
   1104     if ((align <= 0) || (count == 0)) {
   1105         return BCM_E_PARAM;
   1106     }
   1107 
   1108     if (start & (align - 1)) {
   1109         start = (start + align - 1) & ~(align - 1);
   1110     }
   1111 
   1112     end = end - align + 1;
   1113 
   1114     for (i = start; i < end; i += align) {
   1115         range_empty = 1;
   1116         for (j = i; j < (i + count); j++) {
   1117             if (SHR_BITGET(list, j) != 0) {
   1118                 range_empty = 0;
   1119                 break;
   1120             }
   1121         }
   1122 
   1123         if (range_empty) {
   1124             *id = i;
   1125             return BCM_E_NONE;
   1126         }
   1127     }
   1128     return BCM_E_RESOURCE;
   1129 }
   1130 
   1131 /*
   1132  * Function:
   1133  *     _bcm_tr3_node_index_set
   1134  * Purpose:
   1135  *     Mark indices as allocated
   1136  * Parameters:
   1137  *     list       - (IN) bit list
   1138  *     start      - (IN) start index
   1139  *     range      - (IN) range bits
   1140  * Returns:
   1141  *     BCM_E_XXX
   1142  */
   1143 STATIC int
   1144 _bcm_tr3_node_index_set(_bcm_tr3_cosq_list_t *list, int start, int range)
   1145 {
   1146     list->count += range;
   1147     SHR_BITSET_RANGE(list->bits, start, range);
   1148 
   1149     return BCM_E_NONE;
   1150 }
   1151 
   1152 /*
   1153  * Function:
   1154  *     _bcm_tr3_node_index_clear
   1155  * Purpose:
   1156  *     Mark indices as free
   1157  * Parameters:
   1158  *     list       - (IN) bit list
   1159  *     start      - (IN) start index
   1160  *     range      - (IN) range bits
   1161  * Returns:
   1162  *     BCM_E_XXX
   1163  */
   1164 STATIC int
   1165 _bcm_tr3_node_index_clear(_bcm_tr3_cosq_list_t *list, int start, int range)
   1166 {
   1167     list->count -= range;
   1168     SHR_BITCLR_RANGE(list->bits, start, range);
   1169 
   1170     return BCM_E_NONE;
   1171 }
   1172 
   1173 /*
   1174  * Function:
   1175  *     _bcm_tr3_cosq_alloc_clear
   1176  * Purpose:
   1177  *     Allocate cosq memory and clear
   1178  * Parameters:
   1179  *     size       - (IN) size of memory required
   1180  *     description- (IN) description about the structure
   1181  * Returns:
   1182  *     BCM_E_XXX
   1183  */
   1184 STATIC void *
   1185 _bcm_tr3_cosq_alloc_clear(void *cp, unsigned int size, char *description)
   1186 {
   1187     void *block_p;
   1188 
   1189     block_p = (cp) ? cp : sal_alloc(size, description);
   1190 
   1191     if (block_p != NULL) {
   1192         sal_memset(block_p, 0, size);
   1193     }
   1194 
   1195     return block_p;
   1196 }
   1197 
   1198 /*
   1199  * Function:
   1200  *     _bcm_tr3_cosq_free_memory
   1201  * Purpose:
   1202  *     Free memory allocated for mmu info members
   1203  * Parameters:
   1204  *     mmu_info       - (IN) MMU info pointer
   1205  * Returns:
   1206  *     BCM_E_XXX
   1207  */
   1208 STATIC void
   1209 _bcm_tr3_cosq_free_memory(_bcm_tr3_mmu_info_t *mmu_info_p)
   1210 {
   1211     sal_free(mmu_info_p->ext_qlist.bits);
   1212     sal_free(mmu_info_p->dmvoq_qlist.bits);
   1213     sal_free(mmu_info_p->l0_sched_list.bits);
   1214     sal_free(mmu_info_p->l1_sched_list.bits);
   1215 }
   1216 
   1217 STATIC int
   1218 _bcm_tr3_higig_intf_index(int unit, bcm_port_t local_port)
   1219 {
   1220     int index = 0, port;
   1221 
   1222     PBMP_HG_ITER(unit, port) {
   1223         if (port == local_port) {
   1224             return index;
   1225         }
   1226         index += 1;
   1227     }
   1228     return -1;
   1229 }
   1230 
   1231 STATIC int
   1232 _bcm_tr3_voq_min_hw_index(int unit, bcm_port_t port, 
   1233                           bcm_module_t modid, 
   1234                           bcm_port_t remote_port,
   1235                           int *q_offset)
   1236 {
   1237     int i, hw_index_base = -1;
   1238     _bcm_tr3_cosq_node_t *node;
   1239     _bcm_tr3_mmu_info_t *mmu_info;
   1240 
   1241     mmu_info = _bcm_tr3_mmu_info[unit];
   1242 
   1243     for (i = mmu_info->num_base_queues; i < _BCM_TR3_NUM_L2_UC_LEAVES; i++) {
   1244         node = &mmu_info->queue_node[i];
   1245         if ((node->in_use == FALSE) || (node->hw_index == -1)) {
   1246             continue;
   1247         }
   1248 
   1249         if (((modid == -1) ? 1 : (node->remote_modid == modid)) && 
   1250             (node->remote_port == remote_port) &&
   1251             ((port == -1) ? 1 : (port == node->local_port))) {
   1252             if ((hw_index_base == -1) || (hw_index_base > node->hw_index)) {
   1253                 hw_index_base = node->hw_index;
   1254             }
   1255         }
   1256     }
   1257    
   1258     if (hw_index_base != -1) {
   1259         *q_offset = hw_index_base & ~7;
   1260         return BCM_E_NONE;
   1261     }
   1262 
   1263     return BCM_E_NOT_FOUND;
   1264 }
   1265 
   1266 STATIC int
   1267 _bcm_tr3_voq_base_node_get(int unit, bcm_port_t port, 
   1268         int modid,
   1269         _bcm_tr3_cosq_node_t **base_node)
   1270 {
   1271     int i;
   1272     _bcm_tr3_cosq_node_t *node;
   1273     _bcm_tr3_mmu_info_t *mmu_info;
   1274     int dmvoq_found = 0;
   1275 
   1276     mmu_info = _bcm_tr3_mmu_info[unit];
   1277 
   1278     *base_node = NULL;
   1279 
   1280     for (i = mmu_info->num_base_queues; i < _BCM_TR3_NUM_L2_UC_LEAVES; i++) {
   1281         node = &mmu_info->queue_node[i];
   1282         if ((node->in_use == FALSE) || (node->hw_index == -1)) {
   1283             continue;
   1284         }
   1285 
   1286         /*
   1287          * Identify if at least one dmvoq configuration
   1288          * is applied on this port.
   1289          */
   1290         if ((node->local_port == port) &&
   1291             (node->type == _BCM_TR3_NODE_DMVOQ) &&
   1292             (node->remote_modid != -1)) {
   1293             dmvoq_found = 1;
   1294         }
   1295 
   1296         if ((node->local_port == port) && (node->remote_modid == modid)) {
   1297             *base_node = node ;
   1298             break;
   1299         }
   1300     }
   1301     
   1302     /* No dmvoq configuration applied on this port */
   1303     if ((*base_node == NULL) && (dmvoq_found == 0)) {
   1304         return BCM_E_NOT_FOUND;
   1305     }
   1306    
   1307     return BCM_E_NONE;
   1308 }
   1309 
   1310 STATIC int
   1311 _bcm_tr3_voq_next_base_node_get(int unit, bcm_port_t port, 
   1312         int modid,
   1313         _bcm_tr3_cosq_node_t **base_node)
   1314 {
   1315 
   1316     int i;
   1317     _bcm_tr3_cosq_node_t *node;
   1318     _bcm_tr3_mmu_info_t *mmu_info;
   1319     int found = FALSE;
   1320 
   1321     mmu_info = _bcm_tr3_mmu_info[unit];
   1322 
   1323     for (i = mmu_info->num_base_queues; i < _BCM_TR3_NUM_L2_UC_LEAVES; i++) {
   1324         node = &mmu_info->queue_node[i];
   1325         if ((node->in_use == FALSE) || (node->hw_index == -1)) {
   1326             continue;
   1327         }
   1328 
   1329         if (node->remote_modid == modid) {
   1330             if ( found == TRUE) {
   1331                 *base_node = node;
   1332                 break;
   1333             }
   1334             found = TRUE;
   1335         }
   1336     }
   1337    
   1338     return BCM_E_NONE;
   1339 }
   1340 
   1341 STATIC int
   1342 _bcm_tr3_port_voq_base_set(int unit, bcm_port_t local_port, int base)
   1343 {
   1344     uint32 rval;
   1345 
   1346     BCM_IF_ERROR_RETURN(READ_ING_COS_MODEr(unit, local_port, &rval));
   1347     soc_reg_field_set(unit, ING_COS_MODEr, &rval, BASE_QUEUE_NUM_1f, base);
   1348     BCM_IF_ERROR_RETURN(WRITE_ING_COS_MODEr(unit, local_port, rval));
   1349     return BCM_E_NONE;
   1350 }
   1351 
   1352 STATIC int
   1353 _bcm_tr3_port_voq_base_get(int unit, bcm_port_t local_port, int *base)
   1354 {
   1355     uint32 rval;
   1356 
   1357     BCM_IF_ERROR_RETURN(READ_ING_COS_MODEr(unit, local_port, &rval));
   1358     if (soc_reg_field_get(unit, ING_COS_MODEr, rval, QUEUE_MODEf) == 1) {
   1359         *base = soc_reg_field_get(unit, ING_COS_MODEr, rval, 
   1360                                   BASE_QUEUE_NUM_1f);
   1361         return BCM_E_NONE;
   1362     }
   1363 
   1364     BCM_IF_ERROR_RETURN(
   1365         _bcm_tr3_voq_min_hw_index(unit, local_port, -1, -1, base));
   1366 
   1367     return BCM_E_NONE;
   1368 }
   1369 
   1370 STATIC int
   1371 _bcm_tr3_resolve_dmvoq_hw_index(int unit, _bcm_tr3_cosq_node_t *node, 
   1372                     int cosq, bcm_module_t modid, bcm_port_t local_port)
   1373 {
   1374     int try, preffered_offset = -1, alloc_size;
   1375     int from_offset, port, rv, q_base, port_voq_base;
   1376     _bcm_tr3_mmu_info_t *mmu_info;
   1377 
   1378     mmu_info = _bcm_tr3_mmu_info[unit];
   1379 
   1380     if ((modid == -1) && (mmu_info->num_dmvoq_queues > 0)) {
   1381         return BCM_E_PARAM;
   1382     }
   1383     from_offset = mmu_info->num_base_queues;
   1384     alloc_size = _TR3_NUM_COS(unit);
   1385 
   1386     for (try = 0; try < 2; try++) {
   1387         PBMP_HG_ITER(unit, port) {
   1388             if ((try == 1) && (port == local_port)) {
   1389                 continue;
   1390             }
   1391             
   1392             if ((try == 0) && (port != local_port)) {
   1393                 continue;
   1394            }
   1395 
   1396             rv = _bcm_tr3_voq_min_hw_index(unit, port, modid, -1, &q_base);
   1397             if (!rv) {
   1398                 if (port == local_port) {
   1399                     /* Found VOQ for the same port/dest modid */
   1400                     /* Assign hw_index only if it is not assigned in gport_add */
   1401                     if (node->hw_index == -1) {
   1402                         node->hw_index = q_base + cosq;
   1403                     }
   1404                     return BCM_E_NONE;
   1405                 } else if (modid == -1) {
   1406                     rv = _bcm_tr3_port_voq_base_get(unit, port, &port_voq_base);
   1407                     if (rv) {
   1408                         continue;
   1409                     }
   1410                     preffered_offset = q_base - port_voq_base;
   1411                     rv = _bcm_tr3_port_voq_base_get(unit, local_port, 
   1412                                                     &port_voq_base);
   1413                     if (rv) {
   1414                         /* No VOQ on the port yet */
   1415                         alloc_size += preffered_offset;
   1416                     } else {
   1417                         /* port has already VOQs */
   1418                         from_offset = port_voq_base + preffered_offset;
   1419                     }
   1420                     break;
   1421                 }
   1422             }
   1423         }
   1424         if (preffered_offset != -1) {
   1425             break;
   1426         }
   1427     }
   1428 
   1429     if (modid == -1) {
   1430         /* Alloc hw index. */
   1431         rv = _bcm_tr3_node_index_get(mmu_info->ext_qlist.bits, 
   1432                             from_offset, _BCM_TR3_NUM_L2_UC_LEAVES, 
   1433                             alloc_size, _TR3_NUM_COS(unit), &q_base);
   1434         if (rv) {
   1435             return BCM_E_RESOURCE;
   1436         }
   1437         
   1438         if (_bcm_tr3_port_voq_base_get(unit, local_port, &port_voq_base)) {
   1439             _bcm_tr3_port_voq_base_set(unit, local_port, q_base);
   1440         }
   1441         q_base = q_base + alloc_size - _TR3_NUM_COS(unit);
   1442         node->hw_index = q_base + cosq;
   1443         node->remote_modid = modid;
   1444         _bcm_tr3_node_index_set(&mmu_info->ext_qlist, q_base, _TR3_NUM_COS(unit));
   1445     } else {
   1446 
   1447         if (_bcm_tr3_port_voq_base_get(unit, local_port, &port_voq_base)) {
   1448             _bcm_tr3_port_voq_base_set(unit, local_port, node->hw_index); 
   1449         } else {             
   1450             _bcm_tr3_port_voq_base_set(unit, local_port, MIN(port_voq_base, node->hw_index));
   1451         }        
   1452         
   1453         node->remote_modid = modid;
   1454         rv = BCM_E_NONE;
   1455     }
   1456     return rv;
   1457 }
   1458 
   1459 typedef struct _bcm_tr3_voq_info_s {
   1460     int          valid;
   1461     _bcm_tr3_cosq_node_t *node;
   1462     bcm_module_t remote_modid;
   1463     bcm_port_t   remote_port;
   1464     bcm_port_t   local_port;
   1465     int          hw_cosq;
   1466     int          hw_index;
   1467 } _bcm_tr3_voq_info_t;
   1468 
   1469 STATIC int
   1470 _bcm_tr3_cosq_sort_voq_list(void *a, void *b)
   1471 {
   1472     _bcm_tr3_voq_info_t *va, *vb;
   1473     int sa, sb;
   1474 
   1475     va = (_bcm_tr3_voq_info_t*)a;
   1476     vb = (_bcm_tr3_voq_info_t*)b;
   1477     
   1478     sa = (va->remote_modid << 19) | (va->remote_port << 11) |
   1479          (va->local_port << 3) | (va->hw_cosq);
   1480 
   1481     sb = (vb->remote_modid << 19) | (vb->remote_port << 11) |
   1482          (vb->local_port << 3) | (vb->hw_cosq);
   1483 
   1484     return sa - sb;
   1485 }
   1486     
   1487 STATIC int
   1488 _bcm_tr3_map_fc_status_to_node(int unit, int spad_offset, int cosq,
   1489                                uint32 hw_index, int pfc, int lls_level)
   1490 {
   1491     int map_entry_index, eindex;
   1492     soc_mem_t mem;
   1493     uint32 map_entry[SOC_MAX_MEM_WORDS];
   1494     static const soc_field_t self[] = {
   1495         SEL0f, SEL1f, SEL2f, SEL3f
   1496     };
   1497     static const soc_field_t indexf[] = {
   1498         INDEX0f, INDEX1f, INDEX2f, INDEX3f
   1499     };
   1500     static const soc_reg_t mems[] = {
   1501         INVALIDm, MMU_INTFI_FC_MAP_TBL0m,
   1502         MMU_INTFI_FC_MAP_TBL1m, MMU_INTFI_FC_MAP_TBL2m
   1503     };
   1504     
   1505     mem = mems[lls_level];
   1506     if (mem == INVALIDm) {
   1507         return BCM_E_PARAM;
   1508     }
   1509     map_entry_index = hw_index/16;
   1510     eindex = (hw_index % 16)/4;
   1511 
   1512     BCM_IF_ERROR_RETURN
   1513         (soc_mem_read(unit, mem, MEM_BLOCK_ALL, map_entry_index, &map_entry));
   1514     soc_mem_field32_set(unit, mem, &map_entry, 
   1515                         indexf[eindex], spad_offset + cosq/4);
   1516     soc_mem_field32_set(unit, mem, &map_entry, self[eindex], !!pfc);
   1517     BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem,
   1518                         MEM_BLOCK_ALL, map_entry_index, &map_entry));
   1519     return BCM_E_NONE;
   1520 }
   1521 
   1522 STATIC int
   1523 _bcm_tr3_get_queue_skip_count_on_cos(uint32 cbmp, int cur_cos, int next_cos)
   1524 {
   1525     int i,skip = 0;
   1526 
   1527     if ((next_cos >= 4) && (cur_cos/4 != next_cos/4)) {
   1528         cur_cos = -1;
   1529         next_cos -= 4;
   1530     }
   1531     
   1532     for (i = cur_cos + 1; i < next_cos; i++) {
   1533         if (cbmp & (1 << i)) {
   1534             skip += 1;
   1535         }
   1536     }
   1537     return skip;
   1538 }
   1539 
   1540 STATIC int
   1541 _bcm_tr3_src_mod_id_set(int unit, bcm_port_t srcid)
   1542 {
   1543     int ii, hole = -1;
   1544     uint32 rval, csrc;
   1545 
   1546     for (ii = 0; ii < 16; ii++) {
   1547         BCM_IF_ERROR_RETURN(READ_SRC_MOD_IDr(unit, ii, &rval));
   1548         if (srcid == (csrc = soc_reg_field_get(unit, SRC_MOD_IDr, rval, SRC_MODf))) {
   1549             return ii;
   1550         }
   1551         if ((hole == -1) && (csrc == 0)) {
   1552             hole = ii;
   1553         }
   1554     }
   1555 
   1556     if (hole == -1) {
   1557         return BCM_E_RESOURCE;
   1558     }
   1559    
   1560     rval = 0;
   1561     soc_reg_field_set(unit, SRC_MOD_IDr, &rval, SRC_MODf, srcid);
   1562     soc_reg_field_set(unit, SRC_MOD_IDr, &rval, IF_IDf, (hole < 4) ? hole : 3);
   1563     BCM_IF_ERROR_RETURN(WRITE_SRC_MOD_IDr(unit, hole, rval));
   1564     
   1565     return hole;
   1566 }
   1567 
   1568 STATIC int
   1569 _bcm_tr3_gport_dpvoq_config_set(int unit, bcm_gport_t gport, 
   1570                                 bcm_cos_queue_t cosq,
   1571                                 bcm_module_t remote_modid,
   1572                                 bcm_port_t remote_port)
   1573 {
   1574     uint32 profile = 0xFFFFFFFF;
   1575     _bcm_tr3_cosq_node_t *node;
   1576     bcm_port_t local_port;
   1577     uint32 cng_offset;
   1578     uint8 cbmp = 0, nib_cbmp = 0;
   1579     _bcm_tr3_mmu_info_t *mmu_info;
   1580     _bcm_tr3_voq_info_t *plist = NULL, *vlist = NULL;
   1581     int pcount, ii, vcount = 0;
   1582     voq_port_map_entry_t *voq_port_map_entries = NULL;
   1583     int rv = BCM_E_NONE, mod_base = 0, num_cos = 0, dm = -1, eq_base;
   1584     voq_mod_map_entry_t voq_mod_map;
   1585     void *entries[1];
   1586     int cng_bytes_per_e2ecc_msg = 32;
   1587     int p2ioff[64], ioff, port, skip, *dm2off, count;
   1588 
   1589     if ((cosq < 0) || (cosq > _TR3_NUM_COS(unit))) {
   1590         return BCM_E_PARAM;
   1591     }
   1592 
   1593     if ((mmu_info = _bcm_tr3_mmu_info[unit]) == NULL) {
   1594         return BCM_E_INIT;
   1595     }
   1596 
   1597     BCM_IF_ERROR_RETURN
   1598       (_bcm_tr3_cosq_node_get(unit, gport, 0, NULL, &local_port, NULL, &node));
   1599 
   1600     eq_base = (mmu_info->num_base_queues + 7) & ~7;
   1601     
   1602     node->remote_modid = remote_modid;
   1603     node->remote_port = remote_port;
   1604     node->hw_cosq = cosq;
   1605 
   1606     dm2off = sal_alloc(sizeof(int) * 256, "voq_vlist");
   1607     if (!dm2off) {
   1608         return BCM_E_MEMORY;
   1609     }
   1610     sal_memset(dm2off, 0, sizeof(int)*256);
   1611 
   1612     /* alloc temp vlist */
   1613     vlist = sal_alloc(sizeof(_bcm_tr3_voq_info_t) * 1024, "voq_vlist");
   1614     if (!vlist) {
   1615         sal_free(dm2off);
   1616         return BCM_E_MEMORY;
   1617     }
   1618     sal_memset(vlist, 0, sizeof(_bcm_tr3_voq_info_t)*1024);
   1619 
   1620     for (ii = 0; ii < _BCM_TR3_NUM_L2_UC_LEAVES; ii++) {
   1621         node = &mmu_info->queue_node[ii];
   1622         if ((node->remote_modid == -1) || (node->remote_port == -1)) {
   1623             continue;
   1624         }
   1625         vlist[vcount].remote_modid = node->remote_modid;
   1626         vlist[vcount].remote_port  = node->remote_port; 
   1627         vlist[vcount].local_port   = node->local_port;
   1628         vlist[vcount].hw_cosq     = node->hw_cosq; 
   1629         vlist[vcount].node         = node;
   1630         vcount += 1;
   1631     }
   1632 
   1633     /* Sort the nodes */
   1634     _shr_sort(vlist, vcount, sizeof(_bcm_tr3_voq_info_t), 
   1635                 _bcm_tr3_cosq_sort_voq_list);
   1636 
   1637     for (ii = 0; ii < 64; ii++) {
   1638         p2ioff[ii] = -1;
   1639     }
   1640     
   1641     PBMP_HG_ITER(unit, port) {
   1642         ioff = _bcm_tr3_higig_intf_index(unit, port);
   1643         p2ioff[port] = ioff;
   1644     }
   1645 
   1646     for (ii = 0; ii < vcount; ii++) {
   1647         cbmp |= 1 << vlist[ii].hw_cosq;
   1648     }
   1649 
   1650     nib_cbmp = (cbmp >> 4) | (cbmp & 0xf);
   1651 
   1652     for (ii = 0; ii < 4; ii++) {
   1653         if ((1 << ii) & nib_cbmp) {
   1654             num_cos += 1;
   1655         }
   1656     }
   1657 
   1658     for (count = 1, ii = 0; ii < vcount; ii++) {
   1659         if (dm2off[vlist[ii].remote_modid]==0) {
   1660             dm2off[vlist[ii].remote_modid] = count;
   1661         }
   1662     }
   1663 
   1664     plist = sal_alloc(sizeof(_bcm_tr3_voq_info_t) * 1024, "voq_vlist");
   1665     if (!plist) {
   1666         sal_free(vlist);
   1667         sal_free(dm2off);
   1668         return BCM_E_MEMORY;
   1669     }
   1670     sal_memset(plist, 0, sizeof(_bcm_tr3_voq_info_t)*1024);
   1671 
   1672     for (pcount = 0, ii = 0; ii < vcount; ii++) {
   1673         if (pcount % 4) {
   1674             if ((plist[pcount - 1].remote_modid != vlist[ii].remote_modid) ||
   1675                 (plist[pcount - 1].remote_port != vlist[ii].remote_port)) {
   1676                 pcount = (pcount + 3) & ~3;
   1677             } else if (plist[pcount - 1].local_port != vlist[ii].local_port) {
   1678                 skip = (p2ioff[vlist[ii].local_port] - 
   1679                             p2ioff[plist[pcount - 1].local_port] - 1) * num_cos;
   1680                 skip +=  _bcm_tr3_get_queue_skip_count_on_cos(nib_cbmp, 
   1681                                         plist[pcount - 1].hw_cosq,
   1682                                         vlist[ii].hw_cosq);
   1683                 if (skip >= 4) {
   1684                     pcount = ((pcount + 3) & ~3) + (skip % 4);
   1685                 } else {
   1686                     pcount += skip;
   1687                 }
   1688             } else if ((vlist[ii].hw_cosq - plist[pcount - 1].hw_cosq) > 1) {
   1689                 if (plist[pcount - 1].hw_cosq/4 != vlist[ii].hw_cosq/4) {
   1690                     pcount = (pcount + 3) & ~3;
   1691                 }
   1692                 pcount += _bcm_tr3_get_queue_skip_count_on_cos(nib_cbmp, 
   1693                                         plist[pcount - 1].hw_cosq,
   1694                                         vlist[ii].hw_cosq);
   1695             }
   1696         } else {
   1697             pcount += _bcm_tr3_get_queue_skip_count_on_cos(nib_cbmp, -1,
   1698                                                     vlist[ii].hw_cosq);
   1699         }
   1700        
   1701         plist[pcount].valid = 1;
   1702         plist[pcount].local_port = vlist[ii].local_port;
   1703         plist[pcount].remote_modid = vlist[ii].remote_modid;
   1704         plist[pcount].remote_port = vlist[ii].remote_port;
   1705         plist[pcount].hw_cosq = vlist[ii].hw_cosq;
   1706         plist[pcount].node = vlist[ii].node;
   1707         vlist[ii].node->hw_index = pcount + eq_base;
   1708         
   1709         #ifdef DEBUG_TR3_COSQ
   1710           LOG_CLI((BSL_META_U(unit,
   1711                               "DPVOQ DM=%d DP=%d LocalPort=%d COS=%d HWIndex=%d\n"),
   1712                    plist[pcount].remote_modid,
   1713                    plist[pcount].remote_port,
   1714                    plist[pcount].local_port,
   1715                    plist[pcount].hw_cosq,
   1716                    plist[pcount].node->hw_index));
   1717         #endif
   1718         pcount += 1;
   1719     }
   1720 
   1721     /* program the voq port profiles. */
   1722     voq_port_map_entries = sal_alloc(sizeof(voq_port_map_entry_t)*128, 
   1723                                         "voq port map entries");
   1724     if (!voq_port_map_entries) {
   1725         goto fail;
   1726     }
   1727     sal_memset(voq_port_map_entries, 0, sizeof(voq_port_map_entry_t)*128);
   1728 
   1729     entries[0] = voq_port_map_entries;
   1730     dm = -1;
   1731     for (ii = 0; ii <= pcount; ii++) {
   1732         if ((ii == pcount) ||
   1733             ((dm != -1) && (plist[ii - 1].remote_modid != dm))) {
   1734             
   1735             READ_VOQ_MOD_MAPm(unit, MEM_BLOCK_ALL, dm, &voq_mod_map);
   1736             if (soc_mem_field32_get(unit, VOQ_MOD_MAPm, 
   1737                                                 &voq_mod_map, VOQ_VALIDf)) {
   1738                 profile = soc_mem_field32_get(unit, VOQ_MOD_MAPm, 
   1739                               &voq_mod_map, VOQ_MOD_PORT_PROFILE_INDEXf);
   1740                 
   1741                 rv = soc_profile_mem_delete(unit, 
   1742                             _bcm_tr3_voq_port_map_profile[unit], profile*128);
   1743                 if (rv) {
   1744                     goto fail;
   1745                 }
   1746             }
   1747             rv = soc_profile_mem_add(unit, 
   1748                                 _bcm_tr3_voq_port_map_profile[unit], 
   1749                                 entries, 128, &profile);
   1750             if (rv) {
   1751                 goto fail;
   1752             }
   1753            
   1754             soc_mem_field32_set(unit, VOQ_MOD_MAPm, &voq_mod_map, 
   1755                                 VOQ_MOD_PORT_PROFILE_INDEXf, profile/128);
   1756             soc_mem_field32_set(unit, VOQ_MOD_MAPm, &voq_mod_map, 
   1757                                 VOQ_VALIDf, 1);
   1758             soc_mem_field32_set(unit, VOQ_MOD_MAPm, &voq_mod_map, 
   1759                                 VOQ_MOD_OFFSETf, mod_base);
   1760             rv = soc_mem_write(unit, VOQ_MOD_MAPm, MEM_BLOCK_ALL, 
   1761                                dm, &voq_mod_map);
   1762             if (rv) {
   1763                 goto fail;
   1764             }
   1765             sal_memset(voq_port_map_entries, 0, sizeof(voq_port_map_entry_t)*128);
   1766             if (ii != pcount) {
   1767                 mod_base = plist[ii].hw_index & ~3;
   1768                 dm = plist[ii].remote_modid;
   1769             }
   1770         }
   1771 
   1772         if (ii == pcount) {
   1773             break;
   1774         }
   1775 
   1776         if (plist[ii].valid == 0) {
   1777             continue;
   1778         }
   1779 
   1780         dm = plist[ii].remote_modid;
   1781         soc_mem_field32_set(unit, VOQ_PORT_MAPm, 
   1782                             &voq_port_map_entries[plist[ii].remote_port], 
   1783                             VOQ_PORT_OFFSETf, 
   1784                             plist[ii].node->hw_index - mod_base);
   1785     }
   1786 
   1787     dm = -1;
   1788     for (ii = 0; ii < pcount; ii += 1) {
   1789         if (plist[ii].valid == 0) {
   1790             continue;
   1791         }
   1792 
   1793         cng_offset = (dm2off[plist[ii].remote_modid] - 1) * 
   1794                         cng_bytes_per_e2ecc_msg;
   1795 
   1796         _bcm_tr3_map_fc_status_to_node(unit, 
   1797                                        cng_offset + plist[ii].remote_port, 
   1798                                        plist[ii].hw_cosq,
   1799                                        plist[ii].node->hw_index, 0, 
   1800                                        SOC_TR3_NODE_LVL_L2);
   1801     }
   1802    
   1803 fail:
   1804     if (vlist) {
   1805         sal_free(vlist);
   1806     }
   1807 
   1808     if (plist) {
   1809         sal_free(plist);
   1810     }
   1811 
   1812     if (dm2off) {
   1813         sal_free(dm2off);
   1814     }
   1815     
   1816     if (voq_port_map_entries) {
   1817         sal_free(voq_port_map_entries);
   1818     }
   1819 
   1820     if (rv) {
   1821         node->remote_modid = -1;
   1822         node->remote_port = -1;
   1823     }
   1824     return rv;
   1825 }
   1826 
   1827 STATIC int
   1828 _bcm_tr3_gport_dmvoq_config_set(int unit, bcm_gport_t gport, 
   1829                                 bcm_cos_queue_t cosq,
   1830                                 bcm_module_t fabric_modid, 
   1831                                 bcm_module_t dest_modid,
   1832                                 bcm_port_t fabric_port)
   1833 {
   1834     int port_voq_base, intf_index;
   1835     _bcm_tr3_cosq_node_t *node;
   1836     _bcm_tr3_cosq_node_t *base_node = NULL;
   1837     bcm_port_t local_port;
   1838     voq_mod_map_entry_t voq_mod_map_entry;
   1839     mmu_intfi_offset_map_tbl_entry_t offset_map_tbl_entry;
   1840     mmu_intfi_base_index_tbl_entry_t base_tbl_entry;
   1841     uint32 cng_offset = 0;
   1842     int fabric_port_count, count = 0;
   1843     int map_offset = 0;
   1844     int port = 0;
   1845     _bcm_tr3_mmu_info_t *mmu_info;
   1846     int index;
   1847     int voq_mod_offset = -1;
   1848     int rv = BCM_E_NONE;
   1849 
   1850     if ((mmu_info = _bcm_tr3_mmu_info[unit]) == NULL) {
   1851         return BCM_E_INIT;
   1852     }
   1853 
   1854     if (fabric_modid >= 64) {
   1855         return BCM_E_PARAM;
   1856     }
   1857 
   1858     BCM_IF_ERROR_RETURN
   1859       (_bcm_tr3_cosq_node_get(unit, gport, 0, NULL, &local_port, NULL, &node));
   1860 
   1861     if (!node) {
   1862         return BCM_E_NOT_FOUND;
   1863     }
   1864 
   1865     intf_index = _bcm_tr3_src_mod_id_set(unit, fabric_modid);
   1866     if (intf_index < 0) {
   1867         return intf_index;
   1868     }
   1869 
   1870     rv = _bcm_tr3_voq_base_node_get(
   1871                 unit, local_port, dest_modid, &base_node);
   1872     if ((rv != BCM_E_NONE) && (rv != BCM_E_NOT_FOUND)) {
   1873         return rv;
   1874     }
   1875 
   1876     if (base_node == NULL) {
   1877         base_node = node ;
   1878     }
   1879 
   1880     /* This is the first dmvoq configuration on this port.
   1881      * Restart programming of offset map table from start.
   1882      */
   1883     if (rv == BCM_E_NOT_FOUND) {
   1884         mmu_info->curr_merger_index[intf_index] = 2;
   1885     }
   1886 
   1887     BCM_IF_ERROR_RETURN(_bcm_tr3_resolve_dmvoq_hw_index(unit, node, cosq,
   1888                                                   dest_modid, local_port));
   1889 
   1890     
   1891 
   1892     BCM_PBMP_COUNT(base_node->fabric_pbmp, fabric_port_count);
   1893     if (fabric_port_count == 0) {
   1894         map_offset = mmu_info->curr_merger_index[intf_index];
   1895         if (map_offset >= soc_mem_index_count(unit, MMU_INTFI_MERGE_ST_TBLm)) {
   1896             return BCM_E_RESOURCE;
   1897         }
   1898     } else {
   1899         BCM_PBMP_ITER(base_node->fabric_pbmp, port) {
   1900             index = (intf_index << 6) | (port * 2);
   1901             if (index > 255) {
   1902                 continue;
   1903             }
   1904             BCM_IF_ERROR_RETURN(soc_mem_read(unit, MMU_INTFI_OFFSET_MAP_TBLm, 
   1905                         MEM_BLOCK_ALL, 
   1906                         index, &offset_map_tbl_entry));
   1907             map_offset = soc_mem_field32_get(unit, MMU_INTFI_OFFSET_MAP_TBLm,
   1908                     &offset_map_tbl_entry,
   1909                     MAP_OFFSETf);
   1910             break;
   1911         }
   1912     }
   1913     if (!BCM_PBMP_MEMBER(base_node->fabric_pbmp, fabric_port)) {
   1914         if (map_offset == mmu_info->curr_merger_index[intf_index]) {
   1915             mmu_info->curr_merger_index[intf_index] += 2;
   1916         }
   1917 
   1918         BCM_PBMP_PORT_ADD (base_node->fabric_pbmp, fabric_port);
   1919         BCM_PBMP_COUNT(base_node->fabric_pbmp, fabric_port_count);
   1920         BCM_PBMP_ITER(base_node->fabric_pbmp, port) {
   1921             count++;
   1922             index = (intf_index << 6) | (port * 2);
   1923             if (index > 255) {
   1924                 continue;
   1925             }
   1926             BCM_IF_ERROR_RETURN(soc_mem_read(unit, MMU_INTFI_OFFSET_MAP_TBLm, 
   1927                         MEM_BLOCK_ALL, 
   1928                         index, &offset_map_tbl_entry));
   1929             soc_mem_field32_set(unit, MMU_INTFI_OFFSET_MAP_TBLm, 
   1930                     &offset_map_tbl_entry,
   1931                     MAP_OFFSETf, map_offset);
   1932             soc_mem_field32_set(unit, MMU_INTFI_OFFSET_MAP_TBLm, 
   1933                     &offset_map_tbl_entry,
   1934                     LASTf, count < fabric_port_count ? 0 : 1 );
   1935             BCM_IF_ERROR_RETURN(soc_mem_write(unit, MMU_INTFI_OFFSET_MAP_TBLm, 
   1936                         MEM_BLOCK_ALL, 
   1937                         index, &offset_map_tbl_entry));
   1938 
   1939             index = (intf_index << 6) | ((port * 2) + 1);
   1940             if (index > 255) {
   1941                 continue;
   1942             }
   1943             BCM_IF_ERROR_RETURN(soc_mem_read(unit, MMU_INTFI_OFFSET_MAP_TBLm, 
   1944                         MEM_BLOCK_ALL, 
   1945                         index, &offset_map_tbl_entry));
   1946             soc_mem_field32_set(unit, MMU_INTFI_OFFSET_MAP_TBLm, 
   1947                     &offset_map_tbl_entry,
   1948                     MAP_OFFSETf, map_offset + 1);
   1949             soc_mem_field32_set(unit, MMU_INTFI_OFFSET_MAP_TBLm, 
   1950                     &offset_map_tbl_entry,
   1951                     LASTf, count < fabric_port_count ? 0 : 1 );
   1952             BCM_IF_ERROR_RETURN(soc_mem_write(unit, MMU_INTFI_OFFSET_MAP_TBLm, 
   1953                         MEM_BLOCK_ALL, 
   1954                         index, &offset_map_tbl_entry));
   1955         }
   1956     }
   1957 
   1958     BCM_IF_ERROR_RETURN(soc_mem_read(unit, VOQ_MOD_MAPm, MEM_BLOCK_ALL, 
   1959                                     dest_modid, &voq_mod_map_entry));
   1960 
   1961     BCM_IF_ERROR_RETURN(_bcm_tr3_port_voq_base_get(unit, local_port, 
   1962                                                     &port_voq_base));
   1963     if (soc_mem_field32_get(unit, VOQ_MOD_MAPm, &voq_mod_map_entry, VOQ_VALIDf)) {
   1964         voq_mod_offset = soc_mem_field32_get(unit, VOQ_MOD_MAPm, &voq_mod_map_entry,
   1965                             VOQ_MOD_OFFSETf);
   1966     }
   1967     if ((voq_mod_offset != -1) &&
   1968                (voq_mod_offset != ((node->hw_index & ~7) - port_voq_base))) {
   1969 
   1970         /* This module offset had already been configured with a
   1971          * different value. Changing it might affect other port
   1972          * configurations.
   1973          */
   1974         return BCM_E_PARAM;
   1975     }
   1976     soc_mem_field32_set(unit, VOQ_MOD_MAPm, &voq_mod_map_entry,
   1977                     VOQ_VALIDf, 1);
   1978 
   1979     soc_mem_field32_set(unit, VOQ_MOD_MAPm, &voq_mod_map_entry,
   1980                     VOQ_MOD_OFFSETf, ((node->hw_index & ~7) - port_voq_base));
   1981 
   1982     BCM_IF_ERROR_RETURN(
   1983         soc_mem_write(unit, VOQ_MOD_MAPm, MEM_BLOCK_ALL, dest_modid, 
   1984                     &voq_mod_map_entry));
   1985 
   1986     cng_offset = intf_index * 128;
   1987 
   1988     /* set the mapping from congestion bits in flow control table
   1989      * to corresponding cosq. */
   1990     BCM_IF_ERROR_RETURN(_bcm_tr3_map_fc_status_to_node(unit,
   1991               cng_offset + map_offset, cosq, node->hw_index, 0,
   1992               SOC_TR3_NODE_LVL_L2));
   1993 
   1994 
   1995     BCM_IF_ERROR_RETURN
   1996         (soc_mem_read(unit, MMU_INTFI_BASE_INDEX_TBLm, 
   1997                       MEM_BLOCK_ALL, fabric_modid, &base_tbl_entry));
   1998     
   1999     soc_mem_field32_set(unit, MMU_INTFI_BASE_INDEX_TBLm, &base_tbl_entry, 
   2000                         BASE_ADDRf, cng_offset);
   2001     soc_mem_field32_set(unit, MMU_INTFI_BASE_INDEX_TBLm, &base_tbl_entry, 
   2002                         ENf, 2);
   2003 
   2004     BCM_IF_ERROR_RETURN(soc_mem_write(unit, MMU_INTFI_BASE_INDEX_TBLm,
   2005                         MEM_BLOCK_ALL, fabric_modid, &base_tbl_entry));
   2006 
   2007     #ifdef DEBUG_TR3_COSQ
   2008     LOG_CLI((BSL_META_U(unit,
   2009                         "Gport=0x%08x hw_index=%d cosq=%d\n"),
   2010              gport, node->hw_index, cosq));
   2011     #endif
   2012 
   2013     return BCM_E_NONE;
   2014 }
   2015 
   2016 int bcm_tr3_cosq_gport_congestion_config_set(int unit, bcm_gport_t gport, 
   2017                                          bcm_cos_queue_t cosq, 
   2018                                          bcm_cosq_congestion_info_t *config)
   2019 {
   2020     _bcm_tr3_mmu_info_t *mmu_info;
   2021 
   2022     if (!config) {
   2023         return BCM_E_PARAM;
   2024     }
   2025 
   2026     if ((mmu_info = _bcm_tr3_mmu_info[unit]) == NULL) {
   2027         return BCM_E_INIT;
   2028     }
   2029 
   2030     if (!_BCM_TR3_IS_DESTMOD_QUEUE_GROUP(mmu_info, gport)) {
   2031         return BCM_E_PARAM;
   2032     }
   2033     
   2034     /* determine if this gport is DPVOQ or DMVOQ */
   2035     if ((config->fabric_port != -1) && (config->dest_modid != -1)) {
   2036         if (config->fabric_modid == -1) {
   2037             return BCM_E_PARAM;
   2038         }
   2039         return _bcm_tr3_gport_dmvoq_config_set(unit, gport, cosq, 
   2040                                                config->fabric_modid,
   2041                                                config->dest_modid,
   2042                                                config->fabric_port);
   2043     } else if ((config->dest_modid != -1) && (config->dest_port != -1)) {
   2044         return _bcm_tr3_gport_dpvoq_config_set(unit, gport, cosq, 
   2045                                                config->dest_modid,
   2046                                                config->dest_port);
   2047     }
   2048     
   2049     return BCM_E_PARAM;
   2050 }
   2051 
   2052 int bcm_tr3_cosq_gport_congestion_config_get(int unit, bcm_gport_t port, 
   2053                                          bcm_cos_queue_t cosq, 
   2054                                          bcm_cosq_congestion_info_t *config)
   2055 {
   2056     _bcm_tr3_mmu_info_t *mmu_info;
   2057     bcm_port_t local_port;
   2058     _bcm_tr3_cosq_node_t *node;
   2059 
   2060     if (!config) {
   2061         return BCM_E_PARAM;
   2062     }
   2063 
   2064     if ((mmu_info = _bcm_tr3_mmu_info[unit]) == NULL) {
   2065         return BCM_E_INIT;
   2066     }
   2067 
   2068     if (!_BCM_TR3_IS_DESTMOD_QUEUE_GROUP(mmu_info, port)) {
   2069         return BCM_E_PARAM;
   2070     }
   2071     
   2072     BCM_IF_ERROR_RETURN
   2073       (_bcm_tr3_cosq_node_get(unit, port, 0, NULL, &local_port, NULL, &node));
   2074 
   2075 
   2076     if (!node) {
   2077         return BCM_E_NOT_FOUND;
   2078     }
   2079 
   2080     config->dest_modid = node->remote_modid;
   2081     config->dest_port = node->remote_port;
   2082 
   2083     return BCM_E_NONE;
   2084 }
   2085 
   2086 /*
   2087  * Function:
   2088  *     _bcm_tr3_cosq_node_get
   2089  * Purpose:
   2090  *     Get internal information of queue group or scheduler type GPORT
   2091  * Parameters:
   2092  *     unit       - (IN) unit number
   2093  *     gport      - (IN) queue group/scheduler GPORT identifier
   2094  *     modid      - (OUT) module identifier
   2095  *     port       - (OUT) port number
   2096  *     id         - (OUT) queue group or scheduler identifier
   2097  *     node       - (OUT) node structure for the specified GPORT
   2098  * Returns:
   2099  *     BCM_E_XXX
   2100  */
   2101 STATIC int
   2102 _bcm_tr3_cosq_node_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
   2103                        bcm_module_t *modid, bcm_port_t *port, 
   2104                        int *id, _bcm_tr3_cosq_node_t **node)
   2105 {
   2106     _bcm_tr3_mmu_info_t *mmu_info;
   2107     _bcm_tr3_cosq_node_t *node_base = NULL;
   2108     bcm_module_t modid_out = 0;
   2109     bcm_port_t port_out = 0;
   2110     uint32 encap_id = -1;
   2111     int index;
   2112 
   2113     if ((mmu_info = _bcm_tr3_mmu_info[unit]) == NULL) {
   2114         return BCM_E_INIT;
   2115     }
   2116 
   2117     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   2118         BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid_out));
   2119         port_out = BCM_GPORT_UCAST_QUEUE_GROUP_SYSPORTID_GET(gport);
   2120     } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   2121         BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid_out));
   2122         port_out = BCM_GPORT_MCAST_QUEUE_GROUP_SYSPORTID_GET(gport);
   2123     } else if (BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) {
   2124         BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid_out));
   2125         port_out = BCM_GPORT_DESTMOD_QUEUE_GROUP_SYSPORTID_GET(gport);
   2126     } else if (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport)) {
   2127         BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid_out));
   2128         port_out = (gport >> 16) & 0xff;
   2129     } else if (BCM_GPORT_IS_SCHEDULER(gport)) {
   2130         BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid_out));
   2131         port_out = BCM_GPORT_SCHEDULER_GET(gport) & 0xff;
   2132     } else if (BCM_GPORT_IS_LOCAL(gport)) {
   2133         encap_id = BCM_GPORT_LOCAL_GET(gport);
   2134         port_out = encap_id;
   2135     } else if (BCM_GPORT_IS_MODPORT(gport)) {
   2136         modid_out = SOC_GPORT_MODPORT_MODID_GET(gport);
   2137         port_out = SOC_GPORT_MODPORT_PORT_GET(gport);
   2138         encap_id = port_out;
   2139     } else {
   2140         return BCM_E_PORT;
   2141     }
   2142 
   2143     if (!SOC_PORT_VALID(unit, port_out)) {
   2144         return BCM_E_PORT;
   2145     }
   2146 
   2147     if (port != NULL) {
   2148         *port = port_out;
   2149     }
   2150 
   2151     if (!_bcm_tr3_cosq_port_has_ets(unit, port_out)) {
   2152         return BCM_E_NOT_FOUND;
   2153     }
   2154 
   2155     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   2156         encap_id = BCM_GPORT_UCAST_QUEUE_GROUP_QID_GET(gport);
   2157         index = encap_id;
   2158         node_base = mmu_info->queue_node;
   2159     } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   2160         encap_id = BCM_GPORT_MCAST_QUEUE_GROUP_QID_GET(gport);
   2161         index = encap_id;
   2162         node_base = mmu_info->mc_queue_node;
   2163     } else if (BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) {
   2164         encap_id = BCM_GPORT_DESTMOD_QUEUE_GROUP_QID_GET(gport);
   2165         index = encap_id;
   2166         if (mmu_info->num_dmvoq_queues > 0) {
   2167             index += mmu_info->base_dmvoq_queue;
   2168         }
   2169         node_base = mmu_info->queue_node;
   2170     } else if (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport)) {
   2171         encap_id = BCM_GPORT_UCAST_SUBSCRIBER_QUEUE_GROUP_QID_GET(gport);
   2172         index = encap_id;
   2173         node_base = mmu_info->queue_node;
   2174     } else if (BCM_GPORT_IS_SCHEDULER(gport)) {
   2175         encap_id = (BCM_GPORT_SCHEDULER_GET(gport) >> 8) & 0x7ff;
   2176         index = encap_id;
   2177         node_base = mmu_info->sched_node;
   2178     } else {
   2179         index = encap_id;
   2180         node_base = mmu_info->sched_node;
   2181     }
   2182 
   2183     if (index < 0) {
   2184         return BCM_E_NOT_FOUND;
   2185     }
   2186 
   2187     if (node_base[index].numq == 0) {
   2188         return BCM_E_NOT_FOUND;
   2189     }
   2190 
   2191     if (modid != NULL) {
   2192         *modid = modid_out;
   2193     }
   2194     if (id != NULL) {
   2195         *id = encap_id;
   2196     }
   2197     if (node != NULL) {
   2198         *node = &node_base[index];
   2199     }
   2200 
   2201     return BCM_E_NONE;
   2202 }
   2203 
   2204 int
   2205 _bcm_tr3_cosq_port_resolve(int unit, bcm_gport_t gport, bcm_module_t *modid,
   2206                           bcm_port_t *port, bcm_trunk_t *trunk_id, int *id,
   2207                           int *qnum)
   2208 {
   2209     _bcm_tr3_cosq_node_t *node;
   2210 
   2211     BCM_IF_ERROR_RETURN
   2212         (_bcm_tr3_cosq_node_get(unit, gport, 0, modid, port, id, &node));
   2213     *trunk_id = -1;
   2214 
   2215     if (qnum) {
   2216         if (node->hw_index == -1) {
   2217             return BCM_E_PARAM;
   2218         }
   2219         *qnum = node->hw_index;
   2220     }
   2221 
   2222     return BCM_E_NONE;
   2223 }
   2224 
   2225 /*
   2226  * Function:
   2227  *     _bcm_tr3_cosq_gport_traverse
   2228  * Purpose:
   2229  *     Walks through the valid COSQ GPORTs and calls
   2230  *     the user supplied callback function for each entry.
   2231  * Parameters:
   2232  *     unit       - (IN) unit number
   2233  *     gport      - (IN)
   2234  *     cb         - (IN) Callback function.
   2235  *     user_data  - (IN) User data to be passed to callback function
   2236  * Returns:
   2237  *     BCM_E_NONE - Success.
   2238  *     BCM_E_XXX
   2239  */
   2240 int
   2241 _bcm_tr3_cosq_gport_traverse(int unit, bcm_gport_t gport,
   2242                             bcm_cosq_gport_traverse_cb cb,
   2243                             void *user_data)
   2244 {
   2245     _bcm_tr3_mmu_info_t *mmu_info;
   2246     _bcm_tr3_cosq_node_t *node;
   2247     uint32 flags = BCM_COSQ_GPORT_SCHEDULER;
   2248     int rv = BCM_E_NONE, id;
   2249     bcm_gport_t local_gport;
   2250 
   2251     if ((mmu_info = _bcm_tr3_mmu_info[unit]) == NULL) {
   2252         return BCM_E_INIT;
   2253     }
   2254 
   2255     BCM_IF_ERROR_RETURN
   2256         (_bcm_tr3_cosq_node_get(unit, gport, 0, NULL, NULL, NULL, &node));
   2257 
   2258     if (node != NULL) {
   2259         if (node->level == SOC_TR3_NODE_LVL_L2) {
   2260             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(node->gport)) {
   2261                 id = BCM_GPORT_UCAST_QUEUE_GROUP_QID_GET(node->gport);
   2262                 if (_BCM_TR3_IS_UC_QUEUE(mmu_info, id)) {
   2263                     flags = BCM_COSQ_GPORT_UCAST_QUEUE_GROUP;
   2264                 } else if (node->type == _BCM_TR3_NODE_DMVOQ) {
   2265                     flags = BCM_COSQ_GPORT_DESTMOD_UCAST_QUEUE_GROUP;
   2266                 } else if (node->type == _BCM_TR3_NODE_VLAN) {
   2267                     flags = BCM_COSQ_GPORT_VLAN_UCAST_QUEUE_GROUP;
   2268                 }
   2269             } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(node->gport)) {
   2270                 flags = BCM_COSQ_GPORT_MCAST_QUEUE_GROUP;
   2271             } else if (BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(node->gport)) {
   2272                 flags = BCM_COSQ_GPORT_DESTMOD_UCAST_QUEUE_GROUP;
   2273             }
   2274         } else {
   2275             flags = BCM_COSQ_GPORT_SCHEDULER;
   2276         }
   2277         BCM_IF_ERROR_RETURN
   2278             (bcm_esw_port_gport_get(unit, node->local_port, &local_gport));
   2279         rv = cb(unit, local_gport, node->numq, flags,
   2280                   node->gport, user_data);
   2281        if (BCM_FAILURE(rv)) {
   2282 #ifdef BCM_CB_ABORT_ON_ERR
   2283            if (SOC_CB_ABORT_ON_ERR(unit)) {
   2284                return rv;
   2285            }
   2286 #endif
   2287        }
   2288     } else {
   2289             return BCM_E_NONE;
   2290     }
   2291 
   2292     if (node->sibling != NULL) {
   2293         _bcm_tr3_cosq_gport_traverse(unit, node->sibling->gport, cb, user_data);
   2294     }
   2295 
   2296     if (node->child != NULL) {
   2297         _bcm_tr3_cosq_gport_traverse(unit, node->child->gport, cb, user_data);
   2298     }
   2299 
   2300     return BCM_E_NONE;
   2301 }
   2302 
   2303 STATIC int
   2304 _bcm_tr3_cosq_traverse_lls_tree(int unit, int port, _bcm_tr3_cosq_node_t *node,
   2305                                 _soc_tr3_lls_traverse_cb cb, void *cookie)
   2306 {
   2307     if (node->child) {
   2308         BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_traverse_lls_tree(unit, port, node->child,
   2309                                                             cb, cookie));
   2310     }
   2311 
   2312     if (node->sibling) {
   2313         BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_traverse_lls_tree(unit, port, 
   2314                                                 node->sibling, cb, cookie));
   2315     }
   2316 
   2317     if (node->level != SOC_TR3_NODE_LVL_ROOT) {
   2318         BCM_IF_ERROR_RETURN(cb(unit, port, node->level, node->hw_index, cookie));
   2319     }
   2320     
   2321     return BCM_E_NONE;
   2322 }
   2323 
   2324 STATIC int
   2325 _bcm_tr3_cosq_child_node_at_input(_bcm_tr3_cosq_node_t *node, int cosq,
   2326                                   _bcm_tr3_cosq_node_t **child_node)
   2327 {
   2328     _bcm_tr3_cosq_node_t *cur_node;
   2329 
   2330     for (cur_node = node->child; cur_node; cur_node = cur_node->sibling) {
   2331         if (cur_node->attached_to_input == cosq) {
   2332             break;
   2333         }
   2334     }
   2335     if (!cur_node) {
   2336         return BCM_E_NOT_FOUND;
   2337     }
   2338 
   2339     *child_node = cur_node;
   2340 
   2341     return BCM_E_NONE;
   2342 }
   2343 
   2344 STATIC int
   2345 _bcm_tr3_cosq_l2_gport(int unit, int port, int cosq,
   2346                        _bcm_tr3_node_type_e type, bcm_gport_t *gport,
   2347                        _bcm_tr3_cosq_node_t **p_node)
   2348 {
   2349     int i, max;
   2350     _bcm_tr3_cosq_node_t *node, *fnode;
   2351     _bcm_tr3_mmu_info_t *mmu_info;
   2352 
   2353     mmu_info = _bcm_tr3_mmu_info[unit];
   2354     
   2355     max  = 0;
   2356     if ((type == _BCM_TR3_NODE_UCAST) || (type == _BCM_TR3_NODE_DMVOQ) ||
   2357         (type == _BCM_TR3_NODE_VLAN)) {
   2358         max = _BCM_TR3_NUM_L2_UC_LEAVES;
   2359         fnode = &mmu_info->queue_node[0];
   2360     } else if (type == _BCM_TR3_NODE_MCAST) {
   2361         max = _BCM_TR3_NUM_L2_MC_LEAVES;
   2362         fnode = &mmu_info->mc_queue_node[0];
   2363     } else {
   2364         return BCM_E_PARAM;
   2365     }
   2366 
   2367     for (i = 0; i < max; i++) {
   2368         node = fnode + i;
   2369         if (node->in_use && (node->local_port == port) &&
   2370             (node->type == type) && (node->hw_cosq == cosq)) {
   2371             if (gport) {
   2372                 *gport = node->gport;
   2373             }
   2374             if (p_node) {
   2375                 *p_node = node;
   2376             }
   2377             return BCM_E_NONE;
   2378         }
   2379     }
   2380     return BCM_E_NOT_FOUND;
   2381 }
   2382 
   2383 /*
   2384  * Function:
   2385  *     _bcm_tr3_cosq_index_resolve
   2386  * Purpose:
   2387  *     Find hardware index for the given port/cosq
   2388  * Parameters:
   2389  *     unit       - (IN) unit number
   2390  *     port       - (IN) port number or GPORT identifier
   2391  *     cosq       - (IN) COS queue number
   2392  *     style      - (IN) index style (_BCM_KA_COSQ_INDEX_STYLE_XXX)
   2393  *     local_port - (OUT) local port number
   2394  *     index      - (OUT) result index
   2395  *     count      - (OUT) number of index
   2396  * Returns:
   2397  *     BCM_E_XXX
   2398  */
   2399 int
   2400 _bcm_tr3_cosq_index_resolve(int unit, bcm_port_t port, bcm_cos_queue_t cosq, 
   2401                            _bcm_tr3_cosq_index_style_t style,                 
   2402                            bcm_port_t *local_port, int *index, int *count)
   2403 {
   2404     _bcm_tr3_cosq_node_t *node, *cur_node;
   2405     bcm_port_t resolved_port;
   2406     int resolved_index = -1;
   2407     int id, startq, numq, pool_start, pool_end, lvl;
   2408     soc_info_t *si;
   2409     int phy_port, mmu_port;
   2410 
   2411     si = &SOC_INFO(unit);
   2412 
   2413     if (cosq < -1) {
   2414         return BCM_E_PARAM;
   2415     } else if (cosq == -1) {
   2416         startq = 0;
   2417         numq = _TR3_NUM_COS(unit);
   2418     } else {
   2419         startq = cosq;
   2420         numq = 1;
   2421     }
   2422 
   2423     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) || 
   2424         BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port) ||
   2425         BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) ||
   2426         BCM_GPORT_IS_SCHEDULER(port)) {
   2427         BCM_IF_ERROR_RETURN
   2428             (_bcm_tr3_cosq_node_get(unit, port, cosq, NULL, &resolved_port, &id,
   2429                                    &node));
   2430         if (node->attached_to_input < 0) { /* Not resolved yet */
   2431             return BCM_E_PARAM;
   2432         }
   2433         numq = (node->numq != -1) ? node->numq : 64;
   2434     } else {
   2435         /* optionally validate port */
   2436         BCM_IF_ERROR_RETURN
   2437             (_bcm_tr3_cosq_localport_resolve(unit, port, &resolved_port));
   2438         if (resolved_port < 0) {
   2439             return BCM_E_PORT;
   2440         }
   2441         node = NULL;
   2442         if (IS_CPU_PORT(unit, resolved_port)) {
   2443             numq = NUM_CPU_COSQ(unit);
   2444         } else if (IS_TR3_HSP_PORT(unit, resolved_port)) {
   2445             numq = _TR3_NUM_HSP_COSQ;
   2446         } else {
   2447             numq = soc_port_hg_capable(unit, resolved_port) ? _TR3_NUM_HG_COSQ: _TR3_NUM_COS(unit);
   2448         }
   2449     }
   2450 
   2451     if (startq >= numq) {
   2452         return BCM_E_PARAM;
   2453     }
   2454 
   2455     phy_port = si->port_l2p_mapping[resolved_port];
   2456     mmu_port = si->port_p2m_mapping[phy_port];
   2457     
   2458 
   2459     if ((node == NULL) && (BCM_GPORT_IS_MODPORT(port) &&
   2460         (!IS_TR3_HSP_PORT(unit, resolved_port))) &&
   2461         (_bcm_tr3_cosq_port_has_ets(unit, resolved_port))) {
   2462         BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_node_get(unit, port, 0, 
   2463                                                     NULL, NULL, NULL, &node));
   2464     }
   2465 
   2466     switch (style) {
   2467     case _BCM_TR3_COSQ_INDEX_STYLE_BUCKET:
   2468         if (node != NULL) {
   2469             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
   2470                 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port)) {
   2471                 resolved_index = node->hw_index;
   2472             } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
   2473                 resolved_index = node->hw_index;
   2474             } else if (BCM_GPORT_IS_SCHEDULER(port) || BCM_GPORT_IS_MODPORT(port)) {
   2475                 /* resolve the child attached to input cosq */
   2476                 BCM_IF_ERROR_RETURN(
   2477                         _bcm_tr3_cosq_child_node_at_input(node, startq, &cur_node));
   2478                 if (IS_TR3_HSP_PORT(unit, resolved_port)) {
   2479                     lvl = cur_node->level;
   2480                     BCM_IF_ERROR_RETURN(soc_tr3_hsp_sched_hw_index_get(unit,
   2481                                                                        resolved_port, lvl,
   2482                                                                        node->attached_to_input,
   2483                                                                        startq, &resolved_index));
   2484                 } else {
   2485                     resolved_index = cur_node->hw_index;
   2486                 }
   2487             } else {
   2488                 return BCM_E_PARAM;
   2489             }
   2490         } else { /* node == NULL */
   2491             if (IS_CPU_PORT(unit, resolved_port)) {
   2492                 resolved_index = SOC_INFO(unit).port_cosq_base[resolved_port] +
   2493                                  startq;
   2494                 resolved_index = soc_tr3_l2_hw_index(unit, resolved_index, 0);
   2495             } else {
   2496                 if (IS_TR3_HSP_PORT(unit, resolved_port)) {
   2497                     lvl = SOC_TR3_NODE_LVL_L0; 
   2498                     if (startq >= _TR3_NUM_HSP_COSQ) {
   2499                         startq = _TR3_NUM_HSP_COSQ - 1;
   2500                     }
   2501                     BCM_IF_ERROR_RETURN(soc_tr3_hsp_sched_hw_index_get(unit,
   2502                                         resolved_port, lvl, 0,
   2503                                         startq, &resolved_index));
   2504 
   2505                 } else {
   2506                     lvl = SOC_TR3_NODE_LVL_L1; 
   2507                     BCM_IF_ERROR_RETURN(soc_tr3_sched_hw_index_get(unit, 
   2508                                         resolved_port, lvl, 
   2509                                         startq, &resolved_index));
   2510                 }
   2511            }
   2512         }
   2513         break;
   2514 
   2515     case _BCM_TR3_COSQ_INDEX_STYLE_QCN:
   2516         if (node != NULL) {
   2517             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
   2518                 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port)) {
   2519                 resolved_index = node->hw_index;
   2520             } else {
   2521                 return BCM_E_PARAM;
   2522             }
   2523         } else { /* node == NULL */
   2524             BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_port_has_ets(unit, resolved_port));
   2525             if (IS_CPU_PORT(unit, resolved_port)) {
   2526                 return BCM_E_PARAM;
   2527             } else {
   2528                 resolved_index = si->port_uc_cosq_base[resolved_port] + startq;
   2529             }
   2530         }
   2531         break;
   2532 
   2533     case _BCM_TR3_COSQ_INDEX_STYLE_WRED:
   2534         if (node != NULL) {
   2535             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
   2536                 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port)) {
   2537                 resolved_index = node->hw_index;
   2538             } else if (BCM_GPORT_IS_SCHEDULER(port)) {
   2539                 BCM_IF_ERROR_RETURN(
   2540                    _bcm_tr3_cosq_child_node_at_input(node, startq, &cur_node));
   2541                 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(cur_node->gport)) {
   2542                     resolved_index = cur_node->hw_index;
   2543                 } else {
   2544                     return BCM_E_PARAM;
   2545                 }
   2546             } else if (BCM_GPORT_IS_MODPORT(port)) {
   2547                 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_l2_gport(unit, node->local_port, 
   2548                                    startq, _BCM_TR3_NODE_UCAST, NULL, &cur_node));
   2549                 resolved_index = cur_node->hw_index;
   2550             } else {
   2551                 return BCM_E_PARAM;
   2552             }
   2553         } else { /* node == NULL */
   2554             if (IS_CPU_PORT(unit, resolved_port) ||
   2555                 IS_LB_PORT(unit, resolved_port)) {
   2556                 return BCM_E_PARAM;
   2557             }
   2558             BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_port_has_ets(unit, resolved_port));
   2559             resolved_index = si->port_uc_cosq_base[resolved_port] + startq;
   2560             numq = 1;
   2561         }
   2562         break;
   2563 
   2564     case _BCM_TR3_COSQ_INDEX_STYLE_WRED_PORT:
   2565         BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_egress_sp_get(unit, resolved_port, 
   2566                                             startq, &pool_start, &pool_end));
   2567         resolved_index = 1280 + (mmu_port*4) + pool_start;
   2568         numq = 4;
   2569         break;
   2570 
   2571     case _BCM_TR3_COSQ_INDEX_STYLE_SCHEDULER:
   2572         if (node != NULL) {
   2573             if (!BCM_GPORT_IS_SCHEDULER(port)) {
   2574                 return BCM_E_PARAM;
   2575             }
   2576             BCM_IF_ERROR_RETURN(
   2577                 _bcm_tr3_cosq_child_node_at_input(node, startq, &cur_node));
   2578             if (IS_TR3_HSP_PORT(unit, resolved_port)) {
   2579                     lvl = cur_node->level;
   2580                     BCM_IF_ERROR_RETURN(soc_tr3_hsp_sched_hw_index_get(unit,
   2581                                                                    resolved_port, lvl,
   2582                                                                    node->attached_to_input,
   2583                                                                    startq, &resolved_index));
   2584                 } else {
   2585                     resolved_index = cur_node->hw_index;
   2586                 }
   2587         } else { /* node == NULL */
   2588             BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_port_has_ets(unit, resolved_port));
   2589             if (IS_CPU_PORT(unit, resolved_port)) {
   2590                 resolved_index = 1024 + si->port_cosq_base[resolved_port] + startq;
   2591             } else {
   2592                 if (IS_TR3_HSP_PORT(unit, resolved_port)) {
   2593                     lvl = SOC_TR3_NODE_LVL_L0; 
   2594                     if (startq >= _TR3_NUM_HSP_COSQ) {
   2595                         startq = _TR3_NUM_HSP_COSQ - 1;
   2596                     }
   2597                     BCM_IF_ERROR_RETURN(soc_tr3_hsp_sched_hw_index_get(unit,
   2598                                     resolved_port, lvl, 0, startq,
   2599                                     &resolved_index));
   2600                 } else {
   2601                     lvl = SOC_TR3_NODE_LVL_L1; 
   2602                     BCM_IF_ERROR_RETURN(soc_tr3_sched_hw_index_get(unit, 
   2603                                         resolved_port, lvl, startq, 
   2604                                         &resolved_index));
   2605                     }
   2606             }
   2607         }
   2608         break;
   2609 
   2610     case _BCM_TR3_COSQ_INDEX_STYLE_COS:
   2611         if (node) {
   2612             if ((BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) ||
   2613                 (BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port)) ||
   2614                 (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port))) {
   2615                 resolved_index = node->hw_cosq;
   2616             } else if (BCM_GPORT_IS_SCHEDULER(port)) {
   2617                 BCM_IF_ERROR_RETURN(
   2618                    _bcm_tr3_cosq_child_node_at_input(node, startq, &cur_node));
   2619                 if (BCM_GPORT_IS_SCHEDULER(cur_node->gport)) {
   2620                     return BCM_E_PARAM;
   2621                 }
   2622                 resolved_index = cur_node->hw_cosq;
   2623             }
   2624         } else {
   2625             BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_port_has_ets(unit, resolved_port));
   2626             resolved_index = startq;
   2627         }
   2628         break;
   2629 
   2630     case _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE:
   2631         if (node) {
   2632             resolved_index = node->hw_index;
   2633             numq = 1;
   2634         } else {
   2635             BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_port_has_ets(unit, resolved_port));
   2636             if (IS_CPU_PORT(unit, resolved_port)) {
   2637                 numq = 0;
   2638                 resolved_index = -1;
   2639             } else {
   2640                 numq = 1;
   2641                 resolved_index = si->port_uc_cosq_base[resolved_port] + startq;
   2642             }
   2643         }
   2644         break;
   2645 
   2646     case _BCM_TR3_COSQ_INDEX_STYLE_MCAST_QUEUE:
   2647         if (node) {
   2648             resolved_index = node->hw_index;
   2649             numq = 1;
   2650         } else {
   2651             BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_port_has_ets(unit, resolved_port));
   2652             numq = 1;
   2653             resolved_index = 1024 + si->port_cosq_base[resolved_port] + startq;
   2654         }
   2655         break;
   2656 
   2657     case _BCM_TR3_COSQ_INDEX_STYLE_EGR_POOL:
   2658         if ((node != NULL) && (!BCM_GPORT_IS_MODPORT(port))) {
   2659             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
   2660                 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port)) {
   2661                     /* regular unicast queue */
   2662                 resolved_index = node->hw_index + startq;
   2663             } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
   2664                 resolved_index = node->hw_index -
   2665                 (si->port_cosq_base[resolved_port] + _BCM_TR3_NUM_L2_UC_LEAVES);
   2666             } else { /* scheduler */
   2667                 return BCM_E_PARAM;
   2668             }
   2669         } else { /* node == NULL */
   2670             numq = si->port_num_cosq[resolved_port];
   2671             if (startq >= numq) {
   2672                 return BCM_E_PARAM;
   2673             }
   2674             resolved_index = startq;
   2675         }
   2676         break;
   2677 
   2678     case _BCM_TR3_COSQ_INDEX_STYLE_EGR_PERQ_UCAST:
   2679         if (node) {
   2680             resolved_index = node->hw_index + startq;
   2681             resolved_index -= soc_tr3_l2_hw_index(unit,
   2682                 si->port_uc_cosq_base[resolved_port], 1);
   2683             numq = 1;
   2684         } else {
   2685             BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_port_has_ets(unit, resolved_port));
   2686             numq = 1;
   2687             resolved_index = startq;
   2688         }
   2689         break;
   2690 
   2691     case _BCM_TR3_COSQ_INDEX_STYLE_EGR_PERQ_MCAST:
   2692         if (node) {
   2693             resolved_index = node->hw_index + startq;
   2694             resolved_index -= soc_tr3_l2_hw_index(unit,
   2695                 si->port_cosq_base[resolved_port], 0);
   2696             numq = 1;
   2697         } else {
   2698             BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_port_has_ets(unit, resolved_port));
   2699             numq = 1;
   2700             resolved_index = startq;
   2701         }
   2702         break;
   2703 
   2704     case _BCM_TR3_COSQ_INDEX_STYLE_UC_EGR_POOL:
   2705         numq = si->port_num_uc_cosq[resolved_port];
   2706         if (startq >= numq) {
   2707                 return BCM_E_PARAM;
   2708         }
   2709         resolved_index = startq;
   2710         break;
   2711 
   2712     default:
   2713         return BCM_E_INTERNAL;
   2714     }
   2715 
   2716     if (local_port != NULL) {
   2717         *local_port = resolved_port;
   2718     }
   2719     if (index != NULL) {
   2720         *index = resolved_index;
   2721     }
   2722     if (count != NULL) {
   2723         *count = (cosq == -1) ? numq : 1;
   2724     }
   2725 
   2726     return BCM_E_NONE;
   2727 }
   2728 
   2729 STATIC int _bcm_tr3_cosq_min_child_index(_bcm_tr3_cosq_node_t *child, int lvl, int uc)
   2730 {
   2731     int min_index = -1;
   2732 
   2733     if ((lvl == SOC_TR3_NODE_LVL_L2) && (uc)) {
   2734         while (child) {
   2735             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(child->gport) ||
   2736                 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(child->gport)) {
   2737                 if (min_index == -1) {
   2738                     min_index = child->hw_index;
   2739                 }
   2740                 
   2741                 if (child->hw_index < min_index) {
   2742                     min_index = child->hw_index;
   2743                 }
   2744             }
   2745             child = child->sibling;
   2746         }
   2747     } else if ((lvl == SOC_TR3_NODE_LVL_L2) && (!uc)) {
   2748         while (child) {
   2749             if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(child->gport)) {
   2750                 if (min_index == -1) {
   2751                     min_index = child->hw_index;
   2752                 }
   2753                 
   2754                 if (child->hw_index < min_index) {
   2755                     min_index = child->hw_index;
   2756                 }
   2757             }
   2758             child = child->sibling;
   2759         }
   2760     } else {
   2761         while (child) {
   2762             if (min_index == -1) {
   2763                 min_index = child->hw_index;
   2764             }
   2765             
   2766             if (child->hw_index < min_index) {
   2767                 min_index = child->hw_index;
   2768             }
   2769             child = child->sibling;
   2770         }
   2771     }
   2772 
   2773     return min_index;
   2774 }
   2775 
   2776 STATIC int
   2777 _bcm_tr3_attach_node_in_hw(int unit, _bcm_tr3_cosq_node_t *node)
   2778 {
   2779     int local_port, fc = 0, fmc = 0, num_spri = 0;
   2780     _bcm_tr3_cosq_node_t *child_node;
   2781     uint32  spmap = 0, ucmap=0;
   2782     int weight;
   2783 
   2784     local_port = node->local_port;
   2785 
   2786     if (node->level == SOC_TR3_NODE_LVL_ROOT) {
   2787         return 0;
   2788     } else if (node->level == SOC_TR3_NODE_LVL_L2) {
   2789         fc = _bcm_tr3_cosq_min_child_index(node->parent->child, SOC_TR3_NODE_LVL_L2, 1);
   2790         if (fc < 0) {
   2791             fc = 0;
   2792         }
   2793         fmc = _bcm_tr3_cosq_min_child_index(node->parent->child, SOC_TR3_NODE_LVL_L2, 0);
   2794         if (fmc < 0) {
   2795             fmc = 1024;
   2796         }
   2797     } else {
   2798         fc = _bcm_tr3_cosq_min_child_index(node->parent->child, node->level, 0);
   2799         fmc = 0;
   2800     }
   2801 
   2802     /* If node is scheduler, reset the scheduler and attach it to the parent.*/
   2803     BCM_IF_ERROR_RETURN(
   2804         soc_tr3_cosq_set_sched_parent(unit, local_port, node->level, 
   2805                                   node->hw_index, node->parent->hw_index));
   2806 
   2807     /* retriving the strict priority bitmap */
   2808     BCM_IF_ERROR_RETURN(soc_tr3_cosq_get_sched_config(unit, 
   2809                                                       local_port, 
   2810                                                       node->parent->level,
   2811                                                       node->parent->hw_index, 
   2812                                                       node->hw_index,
   2813                                                       &num_spri,
   2814                                                       NULL,
   2815                                                       NULL,
   2816                                                       &ucmap,
   2817                                                       &spmap,
   2818                                                       NULL,
   2819                                                       &weight));
   2820 
   2821     /* set the node by default in WRR mode with wt=1 */ 
   2822     BCM_IF_ERROR_RETURN(soc_tr3_cosq_set_sched_config(unit, 
   2823                           local_port, node->parent->level,
   2824                           node->parent->hw_index, node->hw_index, 
   2825                           num_spri, fc, fmc, ucmap, spmap,
   2826                           SOC_TR3_SCHED_MODE_WRR, 1));
   2827 
   2828     if (node->child) {
   2829         child_node = node->child;
   2830         while (child_node) {
   2831             BCM_IF_ERROR_RETURN(_bcm_tr3_attach_node_in_hw(unit, child_node));
   2832             child_node = child_node->sibling;
   2833         }
   2834     }
   2835     
   2836     return BCM_E_NONE;
   2837 }
   2838 
   2839 /*
   2840  * Function:
   2841  *     _bcm_tr3_cosq_node_resolve
   2842  * Purpose:
   2843  *     Resolve queue number in the specified scheduler tree and its subtree
   2844  * Parameters:
   2845  *     unit       - (IN) unit number
   2846  *     node       - (IN) node structure for the specified scheduler node
   2847  *     cosq       - (IN) COS queue to attach to
   2848  * Returns:
   2849  *     BCM_E_XXX
   2850  */
   2851 STATIC int
   2852 _bcm_tr3_cosq_node_resolve(int unit, _bcm_tr3_cosq_node_t *node,
   2853                           bcm_cos_queue_t cosq)
   2854 {
   2855     _bcm_tr3_cosq_node_t *cur_node, *parent;
   2856     _bcm_tr3_mmu_info_t *mmu_info;
   2857     _bcm_tr3_cosq_list_t *list;
   2858     int numq, id, i, ii, prev_base = -1;
   2859     bcm_port_t port;
   2860     uint64 map, tmp_map;
   2861 
   2862     if ((parent = node->parent) == NULL) {
   2863         /* Not attached, should never happen */
   2864         return BCM_E_NOT_FOUND;
   2865     }
   2866 
   2867     if (parent->numq == 0 || parent->numq < -1) {
   2868         return BCM_E_PARAM;
   2869     }
   2870 
   2871     if (parent->numq != -1) {
   2872          /* find the current attached_to_input usage */
   2873         COMPILER_64_ZERO(map);
   2874         for (cur_node = parent->child; cur_node != NULL;
   2875              cur_node = cur_node->sibling) {
   2876             if (cur_node->attached_to_input >= 0) {
   2877                 COMPILER_64_SET(tmp_map, 0, 1);
   2878                 COMPILER_64_SHL(tmp_map, cur_node->attached_to_input);
   2879                 COMPILER_64_OR(map, tmp_map);
   2880             }
   2881         }
   2882 
   2883         if (cosq < 0) {
   2884             for (i = 0; i < parent->numq; i++) {
   2885                 if (!COMPILER_64_BITTEST(map, i)) {
   2886                     node->attached_to_input = i;
   2887                     cosq = i;
   2888                     break;
   2889                 }
   2890             }
   2891             if (i == parent->numq) {
   2892                 return BCM_E_PARAM;
   2893             }
   2894         } else {
   2895             if (COMPILER_64_BITTEST(map, cosq)) {
   2896                 return BCM_E_EXISTS;
   2897             }
   2898             node->attached_to_input = cosq;
   2899         }
   2900     } else if (parent->numq == -1) {
   2901         COMPILER_64_ZERO(map);
   2902         for (cur_node = parent->child; cur_node != NULL;
   2903              cur_node = cur_node->sibling) {
   2904             if (cur_node->attached_to_input >= 0) {
   2905                 COMPILER_64_SET(tmp_map, 0, 1);
   2906                 COMPILER_64_SHL(tmp_map, cur_node->attached_to_input);
   2907                 COMPILER_64_OR(map, tmp_map);
   2908             }
   2909         }
   2910         if (cosq >= 0) {
   2911             if (COMPILER_64_BITTEST(map, cosq)) {
   2912                 return BCM_E_EXISTS;
   2913             }
   2914         } else {
   2915             /* Attach anywhere. find first free slot */
   2916             for (ii = 0; ii < 64; ii++) {
   2917                 if (!COMPILER_64_BITTEST(map, ii)) {
   2918                     cosq = ii;
   2919                     break;
   2920                 }
   2921             }
   2922         }
   2923         node->attached_to_input = cosq;
   2924     }
   2925 
   2926     BCM_IF_ERROR_RETURN
   2927         (_bcm_tr3_cosq_node_get(unit, node->gport, 0, NULL, &port, NULL, NULL));
   2928 
   2929     mmu_info = _bcm_tr3_mmu_info[unit];
   2930     numq = (parent->numq == -1) ? 1 : parent->numq;
   2931 
   2932     switch (parent->level) {
   2933         case SOC_TR3_NODE_LVL_ROOT:
   2934             list = &mmu_info->l0_sched_list;
   2935             /* if parent node has queue number which is dynamic, 
   2936              * free the previos queues, and get the new number of queues.
   2937              * NOTE : This attach routine should not be called when live
   2938              * traffic, this should be dont in the beginning only. */
   2939             if (parent->numq_expandable && parent->base_index >= 0 &&
   2940                 parent->base_size != parent->numq) {
   2941                 _bcm_tr3_node_index_clear(list, parent->base_index, 
   2942                                           parent->base_size);
   2943                 prev_base = parent->base_index;
   2944                 parent->base_index =  -1;
   2945             }
   2946             
   2947             if ((parent->base_index < 0) || (parent->numq == -1)) {
   2948                 id = -1;
   2949                 if (IS_CPU_PORT(unit, node->local_port)) {
   2950                     BCM_IF_ERROR_RETURN(
   2951                       _bcm_tr3_node_index_get(list->bits, 0, NUM_COS(unit), 
   2952                                               numq, 1, &id));
   2953                 }
   2954                 if (id == -1) {
   2955                     BCM_IF_ERROR_RETURN(
   2956                       _bcm_tr3_node_index_get(list->bits, NUM_COS(unit), 
   2957                                     _BCM_TR3_NUM_L0_SCHEDULER, numq, 1, &id));
   2958                 }
   2959                 if ((id == -1) && (!IS_CPU_PORT(unit, node->local_port))) {
   2960                     BCM_IF_ERROR_RETURN(
   2961                       _bcm_tr3_node_index_get(list->bits, 0, NUM_COS(unit), 
   2962                                                 numq, 1, &id));
   2963                 }
   2964                 _bcm_tr3_node_index_set(list, id, numq);
   2965                 if (parent->numq != -1) {
   2966                     parent->base_index = id;
   2967                     node->hw_index = parent->base_index + node->attached_to_input;
   2968                     parent->base_size = numq;
   2969                     if ((prev_base >= 0) && (prev_base != id)) {
   2970                         for (cur_node = parent->child; cur_node; 
   2971                                                 cur_node = cur_node->sibling) {
   2972                             if (cur_node->attached_to_input >= 0) {
   2973                                 cur_node->hw_index = parent->base_index + 
   2974                                                      cur_node->attached_to_input;
   2975                                 BCM_IF_ERROR_RETURN(_bcm_tr3_attach_node_in_hw(unit, cur_node));
   2976                             }
   2977                         }
   2978                     }
   2979                 } else {
   2980                     node->hw_index = id;
   2981                 }
   2982             } else {
   2983                 node->hw_index = parent->base_index + node->attached_to_input;
   2984            }
   2985             node->hw_cosq = node->hw_index % NUM_COS(unit);
   2986 
   2987             break;
   2988 
   2989         case SOC_TR3_NODE_LVL_L0:
   2990             /* Bypass for HSP Ports as hw idx is already assined in gport_add */
   2991             if (IS_TR3_HSP_PORT(unit, node->local_port)) {
   2992                 break;
   2993             }
   2994             if ((parent->base_index < 0) || (parent->numq == -1)) {
   2995                 list = &mmu_info->l1_sched_list;
   2996                 BCM_IF_ERROR_RETURN(_bcm_tr3_node_index_get(list->bits, 0, 
   2997                                   _BCM_TR3_NUM_L1_SCHEDULER, numq, 1, &id));
   2998                 _bcm_tr3_node_index_set(list, id, numq);
   2999                 parent->base_size = numq;
   3000                 if (parent->numq != -1) {
   3001                     parent->base_index = id;
   3002                     node->hw_index = parent->base_index + node->attached_to_input;
   3003                 } else {
   3004                     node->hw_index = id;
   3005                 }
   3006             } else {
   3007                 node->hw_index = parent->base_index + node->attached_to_input;
   3008             }
   3009             node->hw_cosq = node->hw_index % NUM_COS(unit);
   3010             break;
   3011 
   3012         case SOC_TR3_NODE_LVL_L1:
   3013             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(node->gport) ||
   3014                 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(node->gport)) {
   3015                 if (node->type == _BCM_TR3_NODE_VLAN) {
   3016                     if ((parent->base_index < 0) || (parent->numq == -1)) {
   3017                         BCM_IF_ERROR_RETURN(
   3018                                 _bcm_tr3_node_index_get(mmu_info->ext_qlist.bits,
   3019                                     mmu_info->num_base_queues, _BCM_TR3_NUM_L2_UC_LEAVES,
   3020                                     numq, 1, &id));
   3021                         _bcm_tr3_node_index_set(&mmu_info->ext_qlist, id, numq);
   3022                         /* Since hardware, require continous queues only if 
   3023                            numq <= 8 */
   3024                         if ((parent->numq != -1) && (parent->numq <=8)) {
   3025                             parent->base_index = id;
   3026                             node->hw_index = id; 
   3027                         } else {
   3028                             node->hw_index = id; 
   3029                         }
   3030                     } else {
   3031                         /* Since indexes are already reserverved in the first iteration,
   3032                            just assigning the hardware index */
   3033                         if (node->hw_index < 0) {
   3034                             node->hw_index = parent->base_index + node->attached_to_input;
   3035                         }
   3036                     }
   3037                     node->hw_cosq = node->attached_to_input; 
   3038                     parent->num_child++;
   3039                 } else if (node->type == _BCM_TR3_NODE_DMVOQ) {
   3040                     if (mmu_info->num_dmvoq_queues > 0) {
   3041                         _bcm_tr3_node_index_set(&mmu_info->dmvoq_qlist, 
   3042                                     (node->hw_index - mmu_info->base_dmvoq_queue), 1);
   3043                         if (parent->base_index < 0) {
   3044                             parent->base_index = node->hw_index; 
   3045                         }
   3046                         node->hw_cosq = node->attached_to_input; 
   3047                     } else if (parent->base_index < 0) {
   3048                         BCM_IF_ERROR_RETURN(
   3049                             _bcm_tr3_node_index_get(mmu_info->ext_qlist.bits,
   3050                                 mmu_info->num_base_queues, _BCM_TR3_NUM_L2_UC_LEAVES,
   3051                                     _TR3_NUM_COS(unit), _TR3_NUM_COS(unit), &id));
   3052                         while (id % 8 != 0) {
   3053                             id = ((id + 8) & 0xfffffff8);
   3054                             if (id >  _BCM_TR3_NUM_L2_UC_LEAVES) {
   3055                                 return BCM_E_RESOURCE;
   3056                             }
   3057                             BCM_IF_ERROR_RETURN(
   3058                                 _bcm_tr3_node_index_get(mmu_info->ext_qlist.bits,
   3059                                     id, _BCM_TR3_NUM_L2_UC_LEAVES,
   3060                                     _TR3_NUM_COS(unit), _TR3_NUM_COS(unit), &id));
   3061                         }
   3062                         _bcm_tr3_node_index_set(&mmu_info->ext_qlist, id, _TR3_NUM_COS(unit));
   3063 
   3064                         parent->base_index = node->hw_index = id; 
   3065                         node->hw_cosq = node->attached_to_input; 
   3066                     } else {
   3067                         node->hw_cosq = node->attached_to_input;
   3068                         node->hw_index = parent->base_index + 
   3069                                             node->attached_to_input;
   3070                     }
   3071                     parent->num_child++;
   3072                 }
   3073             } else if (node->hw_index == -1) {
   3074                 return BCM_E_PARAM;
   3075             }
   3076             break;
   3077 
   3078         case SOC_TR3_NODE_LVL_L2:
   3079             /* passthru */
   3080         default:
   3081             return BCM_E_PARAM;
   3082 
   3083     }
   3084 
   3085     BCM_IF_ERROR_RETURN(_bcm_tr3_attach_node_in_hw(unit, node));
   3086 
   3087     #ifdef DEBUG_TR3_COSQ
   3088     LOG_CLI((BSL_META_U(unit,
   3089                         "Resolved gport: 0x%08x level:%d to hw_index=%d\n"),
   3090              node->gport, node->level, node->hw_index));
   3091     #endif
   3092 
   3093     return BCM_E_NONE;
   3094 }
   3095 
   3096 /*
   3097  * Function:
   3098  *     _bcm_tr3_cosq_node_unresolve
   3099  * Purpose:
   3100  *     Unresolve queue number in the specified scheduler tree and its subtree
   3101  * Parameters:
   3102  *     unit       - (IN) unit number
   3103  *     node       - (IN) node structure for the specified scheduler node
   3104  *     cosq       - (IN) COS queue to attach to
   3105  * Returns:
   3106  *     BCM_E_XXX
   3107  */
   3108 STATIC int
   3109 _bcm_tr3_cosq_node_unresolve(int unit, _bcm_tr3_cosq_node_t *node, 
   3110                              bcm_cos_queue_t cosq)
   3111 {
   3112     _bcm_tr3_cosq_node_t *parent;
   3113     _bcm_tr3_mmu_info_t *mmu_info;
   3114     _bcm_tr3_cosq_list_t *list;
   3115     int numq = 1;
   3116     int base_index;
   3117 
   3118     if (node->attached_to_input < 0) {
   3119         /* Has been unresolved already */
   3120         return BCM_E_NONE;
   3121     }
   3122 
   3123     parent = node->parent;
   3124 
   3125     if (!parent) {
   3126         return BCM_E_PARAM;
   3127     }
   3128 
   3129     mmu_info = _bcm_tr3_mmu_info[unit];
   3130 
   3131     list = NULL;
   3132     base_index = node->hw_index;
   3133 
   3134     switch (parent->level) {
   3135         case SOC_TR3_NODE_LVL_ROOT:
   3136             list = &mmu_info->l0_sched_list;
   3137             break;
   3138 
   3139         case SOC_TR3_NODE_LVL_L0:
   3140             list = &mmu_info->l1_sched_list;
   3141             break;
   3142 
   3143         case SOC_TR3_NODE_LVL_L1:
   3144             if ((node->type == _BCM_TR3_NODE_DMVOQ) &&
   3145                 (mmu_info->num_dmvoq_queues > 0)) {
   3146                 base_index = node->hw_index - mmu_info->base_dmvoq_queue;
   3147                 if (base_index < 0) {
   3148                     return BCM_E_INTERNAL;
   3149                 }
   3150                 list = &mmu_info->dmvoq_qlist;
   3151             } else if (node->type == _BCM_TR3_NODE_VLAN) {
   3152                 parent->num_child--;
   3153                 if ( parent->numq == -1) {
   3154                     list = &mmu_info->ext_qlist;
   3155                 } else {
   3156                     if (parent->num_child == 0) {
   3157                         base_index = parent->base_index;
   3158                         parent->base_index = -1;
   3159                         numq = parent->numq;
   3160                         list = &mmu_info->ext_qlist;
   3161                     }
   3162                 }
   3163             }
   3164             break;
   3165 
   3166         case SOC_TR3_NODE_LVL_L2:
   3167             /* passthru */
   3168         default:
   3169             return BCM_E_PARAM;
   3170 
   3171     }
   3172 
   3173     if (list) {
   3174         _bcm_tr3_node_index_clear(list, base_index, numq);
   3175     }
   3176     node->attached_to_input = -1;
   3177 
   3178     return BCM_E_NONE;
   3179 }
   3180 
   3181 static int
   3182 _bcm_tr3_axp_id_get(int unit, int local_port)
   3183 {
   3184     int axp_min, axp_max, count, id;
   3185     int port, retval = -1;
   3186     _bcm_tr3_mmu_info_t *mmu_info;
   3187 
   3188     mmu_info = _bcm_tr3_mmu_info[unit];
   3189     for (port = 0; port < 4; port++) {
   3190         if (_tr3_axp_lls_config[port].local_port != local_port) {
   3191             continue;
   3192         }
   3193         count = 0;
   3194         while (count < 3) {
   3195             axp_min = _tr3_axp_lls_config[port].base[count];
   3196             if (axp_min == -1) {
   3197                 count++;
   3198                 continue;
   3199             }
   3200             axp_max = axp_min + _tr3_axp_lls_config[port].numq[count];
   3201             for (id = axp_min; id < axp_max; id++) {
   3202                 if ((id > 1024) &&
   3203                     (mmu_info->mc_queue_node[id - 1024].numq == 0)) {
   3204                     if (retval == -1) {
   3205                         retval = (id - 1024);
   3206                     }
   3207                 }
   3208             }
   3209             count++;
   3210         }
   3211         break;
   3212     }
   3213     return retval;
   3214 }
   3215 /*
   3216  * Function:
   3217  *     bcm_tr3_cosq_gport_add
   3218  * Purpose:
   3219  *     Create a cosq gport structure
   3220  * Parameters:
   3221  *     unit  - (IN) unit number
   3222  *     port  - (IN) port number
   3223  *     numq  - (IN) number of COS queues
   3224  *     flags - (IN) flags (BCM_COSQ_GPORT_XXX)
   3225  *     gport - (OUT) GPORT identifier
   3226  * Returns:
   3227  *     BCM_E_XXX
   3228  */
   3229 int
   3230 bcm_tr3_cosq_gport_add(int unit, bcm_gport_t port, int numq, uint32 flags,
   3231                       bcm_gport_t *gport, int internal)
   3232 {
   3233     _bcm_tr3_mmu_info_t *mmu_info;
   3234     _bcm_tr3_cosq_node_t *node = NULL;
   3235     _bcm_tr3_cosq_port_info_t *port_info;
   3236     uint32 sched_encap;
   3237     int phy_port, mmu_port, local_port;
   3238     int id;
   3239     _bcm_tr3_cosq_list_t *list;
   3240     int i, index, base_index;
   3241     int axp_port_bmp = 0;
   3242     int base_axp_port = 0;
   3243 
   3244     LOG_INFO(BSL_LS_BCM_COSQ,
   3245              (BSL_META_U(unit,
   3246                          "bcm_tr3_cosq_gport_add: unit=%d port=0x%x numq=%d flags=0x%x\n"),
   3247               unit, port, numq, flags));
   3248 
   3249     if (gport == NULL) {
   3250         return BCM_E_PARAM;
   3251     }
   3252 
   3253     if (_bcm_tr3_mmu_info[unit] == NULL) {
   3254         return BCM_E_INIT;
   3255     }
   3256 
   3257     BCM_IF_ERROR_RETURN
   3258         (_bcm_tr3_cosq_localport_resolve(unit, port, &local_port));
   3259 
   3260     if (local_port < 0) {
   3261         return BCM_E_PORT;
   3262     }
   3263     if (IS_TR3_HSP_PORT(unit, local_port) && (!internal)) {
   3264         return BCM_E_PARAM;
   3265     }
   3266     mmu_info = _bcm_tr3_mmu_info[unit];
   3267     port_info = &mmu_info->port_info[local_port];
   3268 
   3269     if ((!mmu_info->ets_mode) && (!internal)) {
   3270         SOC_IF_ERROR_RETURN(soc_tr3_lls_l2_disable(unit));
   3271         SOC_IF_ERROR_RETURN(soc_tr3_lls_reset(unit));
   3272         /*
   3273          * stale bits still be set as the detach is not called
   3274          * Reset the complete list.
   3275          */
   3276         list = &mmu_info->l0_sched_list;
   3277         SOC_IF_ERROR_RETURN(
   3278            _bcm_tr3_node_index_clear(list, 0, _BCM_TR3_NUM_L0_SCHEDULER));
   3279         list = &mmu_info->l1_sched_list;
   3280         SOC_IF_ERROR_RETURN(
   3281            _bcm_tr3_node_index_clear(list, 0, _BCM_TR3_NUM_L1_SCHEDULER));
   3282         SOC_IF_ERROR_RETURN(soc_tr3_lb_lls_init(unit));
   3283         PBMP_ITER(PBMP_AXP_ALL(unit), port) {
   3284             BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_reserve_gport_resources(unit, port));
   3285         } 
   3286         PBMP_CE_ITER(unit, port) {
   3287             BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_reserve_gport_resources(unit, port));
   3288         }
   3289         /* 
   3290          * Reserve the last node as invalid.
   3291          */
   3292         for (i = SOC_TR3_NODE_LVL_L1; i <= SOC_TR3_NODE_LVL_L2; i++) {
   3293             index = _soc_tr3_invalid_parent_index(unit, i);
   3294             if (i == SOC_TR3_NODE_LVL_L1) {
   3295                 list = &mmu_info->l0_sched_list;
   3296             } else if (i == SOC_TR3_NODE_LVL_L2) {
   3297                 list = &mmu_info->l1_sched_list;
   3298             } else {
   3299                 continue;
   3300             }
   3301             if (index >= 0) {
   3302                 _bcm_tr3_node_index_set(list, index, 1);
   3303             }
   3304         }
   3305         mmu_info->ets_mode = 1;
   3306     }
   3307 
   3308     if (IS_AXP_PORT(unit, local_port)) {
   3309         PBMP_AXP_ITER(unit, base_axp_port) {
   3310             break;
   3311         }
   3312         if (local_port < base_axp_port) {
   3313             return BCM_E_INTERNAL;
   3314         }
   3315         axp_port_bmp = (1 << (local_port - base_axp_port));
   3316         if (!(mmu_info->axp_ets_mode & axp_port_bmp)) {
   3317             BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_unreserve_gport_resources(unit, local_port));
   3318             SOC_IF_ERROR_RETURN(soc_tr3_lb_lls_port_uninit(unit, local_port));
   3319             mmu_info->axp_ets_mode |= axp_port_bmp;
   3320         }
   3321     }
   3322 
   3323     if (BCM_PBMP_MEMBER(mmu_info->gport_unavail_pbm, local_port) &&
   3324         !internal) {
   3325         return BCM_E_UNAVAIL;
   3326     }
   3327     
   3328     switch (flags) {
   3329     case BCM_COSQ_GPORT_UCAST_QUEUE_GROUP:
   3330         if (numq != 1) {
   3331             return BCM_E_PARAM;
   3332         }
   3333 
   3334         if (IS_CPU_PORT(unit, local_port)) {
   3335             return BCM_E_PARAM;
   3336         }
   3337 
   3338         for (id = port_info->uc_base; id < port_info->uc_limit; id++) {
   3339             if (mmu_info->queue_node[id].numq == 0) {
   3340                 break;
   3341             }
   3342         }
   3343 
   3344         /* allocating more then num-cos uc queues */
   3345         if (id == port_info->uc_limit) {
   3346             if (mmu_info->num_dmvoq_queues > 0) {
   3347                 base_index = mmu_info->base_dmvoq_queue +
   3348                                         mmu_info->num_dmvoq_queues;
   3349             } else {
   3350                 base_index = mmu_info->num_base_queues;
   3351             }
   3352             for (id = base_index;
   3353                                 id < _BCM_TR3_NUM_L2_UC_LEAVES; id++) {
   3354                 if (mmu_info->queue_node[id].numq == 0) {
   3355                     break;
   3356                 }
   3357             }
   3358         }
   3359 
   3360         if (id == _BCM_TR3_NUM_L2_UC_LEAVES) {
   3361             return BCM_E_RESOURCE;
   3362         }
   3363 
   3364         BCM_GPORT_UCAST_QUEUE_GROUP_SYSQID_SET(*gport, local_port, id);
   3365         node = &mmu_info->queue_node[id];
   3366         node->gport = *gport;
   3367         node->numq = numq;
   3368         node->level = SOC_TR3_NODE_LVL_L2;
   3369         node->hw_cosq = id - port_info->uc_base;
   3370         node->hw_index = soc_tr3_l2_hw_index(unit, id, 1);
   3371         node->local_port = local_port;
   3372         node->remote_modid = -1;
   3373         node->remote_port  = -1;
   3374         node->type = _BCM_TR3_NODE_UCAST;
   3375         node->in_use = TRUE;
   3376         break;
   3377 
   3378     case BCM_COSQ_GPORT_VLAN_UCAST_QUEUE_GROUP:
   3379         /* Service Queueing are outside default queues. Hence NO alignment
   3380          * required.
   3381          */
   3382         if (numq != 1) {
   3383             return BCM_E_PARAM;
   3384         }
   3385         for (id = mmu_info->num_base_queues; 
   3386                 id < _BCM_TR3_NUM_L2_UC_LEAVES; id++) {
   3387             if (mmu_info->queue_node[id].numq == 0) {
   3388                 break;
   3389             }
   3390         }
   3391 
   3392         if (id >= _BCM_TR3_NUM_L2_UC_LEAVES) {
   3393             return BCM_E_RESOURCE;
   3394         }
   3395 
   3396         BCM_GPORT_UCAST_QUEUE_GROUP_SYSQID_SET(*gport, local_port, id);
   3397         node = &mmu_info->queue_node[id];
   3398         node->gport = *gport;
   3399         node->numq = numq ;
   3400         node->level = SOC_TR3_NODE_LVL_L2;
   3401         node->hw_index = -1;
   3402         node->local_port = local_port;
   3403         node->remote_modid = -1;
   3404         node->remote_port  = -1;
   3405         node->type = _BCM_TR3_NODE_VLAN;
   3406         node->in_use = TRUE;
   3407         break;
   3408 
   3409     case BCM_COSQ_GPORT_DESTMOD_UCAST_QUEUE_GROUP:
   3410         if (numq != 1) {
   3411             return BCM_E_PARAM;
   3412         }
   3413 
   3414         if (!IS_HG_PORT(unit, local_port)) {
   3415             return BCM_E_PORT;
   3416         }
   3417 
   3418         if (mmu_info->num_dmvoq_queues > 0) {
   3419             return BCM_E_PARAM;
   3420         }
   3421 
   3422         for (id = mmu_info->num_base_queues; 
   3423                             id < _BCM_TR3_NUM_L2_UC_LEAVES; id++) {
   3424             if (mmu_info->queue_node[id].numq == 0) {
   3425                 break;
   3426             }
   3427         }
   3428 
   3429         if (id >= _BCM_TR3_NUM_L2_UC_LEAVES) {
   3430             return BCM_E_RESOURCE;
   3431         }
   3432 
   3433         BCM_GPORT_UCAST_QUEUE_GROUP_SYSQID_SET(*gport, local_port, id);
   3434         node = &mmu_info->queue_node[id];
   3435         node->gport = *gport;
   3436         node->numq = 1;
   3437         node->level = SOC_TR3_NODE_LVL_L2;
   3438         node->hw_index = -1;
   3439         /* by default assign the cosq on order of order of alocation,
   3440          * can be overriddedn by cos_mapping_set */
   3441         node->hw_cosq = -1;
   3442         node->local_port = local_port;
   3443         node->remote_modid = -1;
   3444         node->remote_port  = -1;
   3445         node->in_use = TRUE;
   3446         node->type = _BCM_TR3_NODE_DMVOQ;
   3447         break;
   3448 
   3449     case (BCM_COSQ_GPORT_WITH_ID | BCM_COSQ_GPORT_DESTMOD_UCAST_QUEUE_GROUP):
   3450         if (numq != 1) {
   3451             return BCM_E_PARAM;
   3452         }
   3453 
   3454         if (!IS_HG_PORT(unit, local_port)) {
   3455             return BCM_E_PORT;
   3456         }
   3457 
   3458         id = BCM_GPORT_DESTMOD_QUEUE_GROUP_QID_GET(*gport);
   3459         if ((id >= mmu_info->num_dmvoq_queues) ||
   3460             (mmu_info->num_dmvoq_queues == 0)) {
   3461             return BCM_E_PARAM;
   3462         }
   3463         node = &mmu_info->queue_node[id + mmu_info->base_dmvoq_queue];
   3464 
   3465         node->gport = *gport;
   3466         node->numq = 1;
   3467         node->level = SOC_TR3_NODE_LVL_L2;
   3468         node->hw_index = mmu_info->base_dmvoq_queue + id;
   3469         node->hw_cosq = -1;
   3470         node->local_port = local_port;
   3471         node->remote_modid = -1;
   3472         node->remote_port  = -1;
   3473         node->in_use = TRUE;
   3474         node->type = _BCM_TR3_NODE_DMVOQ;
   3475         break;
   3476 
   3477     case BCM_COSQ_GPORT_MCAST_QUEUE_GROUP:
   3478         if (numq != 1) {
   3479             return BCM_E_PARAM;
   3480         }
   3481         id = -1;
   3482         if (IS_AXP_PORT(unit, local_port)) {
   3483             id = _bcm_tr3_axp_id_get(unit, local_port);
   3484         }
   3485 
   3486         if (id == -1) {
   3487             for (id = port_info->mc_base; id < port_info->mc_limit; id++) {
   3488                 if (mmu_info->mc_queue_node[id].numq == 0) {
   3489                     break;
   3490                 }
   3491             }
   3492             if (id == port_info->mc_limit) {
   3493                 return BCM_E_RESOURCE;
   3494             }
   3495         }
   3496 
   3497         /* set index bits */
   3498         BCM_GPORT_MCAST_QUEUE_GROUP_SYSQID_SET(*gport, local_port, id);
   3499         node = &mmu_info->mc_queue_node[id];
   3500         node->gport = *gport;
   3501         node->numq = numq;
   3502         node->level = SOC_TR3_NODE_LVL_L2;
   3503         node->hw_cosq = id - port_info->mc_base;
   3504         node->hw_index = soc_tr3_l2_hw_index(unit, id, 0);
   3505         node->local_port = local_port;
   3506         node->remote_modid = -1;
   3507         node->remote_port  = -1;
   3508         node->type = _BCM_TR3_NODE_MCAST;
   3509         node->in_use = TRUE;
   3510         break;
   3511 
   3512     case BCM_COSQ_GPORT_SCHEDULER:
   3513         /* passthru */
   3514     case BCM_COSQ_GPORT_WITH_ID:
   3515     case 0:
   3516         if (numq < -1) {
   3517             return BCM_E_PARAM;
   3518         }
   3519 
   3520         if (( flags & BCM_COSQ_GPORT_WITH_ID) || (flags == 0)) {
   3521             /* this is a port level scheduler */
   3522             id = local_port;
   3523 
   3524             if ( id < 0 || id >= _BCM_TR3_NUM_PORT_SCHEDULERS) {
   3525                 return BCM_E_PARAM;
   3526             }
   3527 
   3528             node = &mmu_info->sched_node[id];
   3529             sched_encap = (id << 8) | local_port;
   3530             BCM_GPORT_SCHEDULER_SET(*gport, sched_encap);
   3531             node->gport = *gport;
   3532             node->level = SOC_TR3_NODE_LVL_ROOT;
   3533             phy_port = SOC_INFO(unit).port_l2p_mapping[local_port];
   3534             mmu_port = SOC_INFO(unit).port_p2m_mapping[phy_port];
   3535             node->hw_index = mmu_port;
   3536             node->local_port = local_port;
   3537             node->numq = numq;
   3538             node->in_use = TRUE;
   3539             node->type = _BCM_TR3_NODE_SCHEDULER;
   3540             node->attached_to_input = 0;
   3541         } else {
   3542             for (id = _BCM_TR3_NUM_PORT_SCHEDULERS; 
   3543                  id < _BCM_TR3_NUM_TOTAL_SCHEDULERS; id++) {
   3544                 if (mmu_info->sched_node[id].in_use == FALSE) {
   3545                     node = &mmu_info->sched_node[id];
   3546                     node->in_use = TRUE;
   3547                     break;
   3548                 }
   3549             }
   3550              if (!node) {
   3551                 return BCM_E_RESOURCE;
   3552             }
   3553 
   3554             node = &mmu_info->sched_node[id];
   3555             sched_encap = (id << 8) | local_port;
   3556             BCM_GPORT_SCHEDULER_SET(*gport, sched_encap);
   3557             node->gport = *gport;
   3558             node->numq = numq;
   3559             node->local_port = local_port;
   3560             node->type = _BCM_TR3_NODE_SCHEDULER;
   3561             node->attached_to_input = -1;
   3562        }
   3563        break;
   3564 
   3565     default:
   3566         return BCM_E_PARAM;
   3567     }
   3568 
   3569     LOG_INFO(BSL_LS_BCM_COSQ,
   3570              (BSL_META_U(unit,
   3571                          "                       gport=0x%x\n"),
   3572               *gport));
   3573 
   3574     return BCM_E_NONE;
   3575 }
   3576 
   3577 int
   3578 _bcm_tr3_cosq_gport_node_disable(int unit, _bcm_tr3_cosq_node_t *node,
   3579                                uint32 disable)
   3580 {
   3581     int hw_index, disable_q = 0;
   3582     uint32 entry[SOC_MAX_MEM_WORDS];
   3583 
   3584     if (!node) {
   3585         return BCM_E_PARAM;
   3586     }
   3587     if ((node->level != SOC_TR3_NODE_LVL_L2) ||  
   3588         BCM_GPORT_IS_MCAST_QUEUE_GROUP(node->gport)) {
   3589         return BCM_E_PARAM;
   3590     }
   3591     if (node->hw_index < 0) {
   3592         return BCM_E_PARAM;
   3593     }
   3594 
   3595     hw_index = node->hw_index;
   3596 
   3597     BCM_IF_ERROR_RETURN(soc_mem_read(unit, MMU_THDO_Q_TO_QGRP_MAPm, 
   3598                         MEM_BLOCK_ANY, hw_index, &entry));
   3599     disable_q = soc_mem_field32_get(unit, MMU_THDO_Q_TO_QGRP_MAPm,
   3600                             entry, DISABLE_QUEUINGf);
   3601     if (disable) {
   3602         if (!disable_q) {
   3603             soc_mem_field32_set(unit, MMU_THDO_Q_TO_QGRP_MAPm, entry, 
   3604                                 DISABLE_QUEUINGf, 1);
   3605             BCM_IF_ERROR_RETURN(
   3606                 soc_mem_write(unit, MMU_THDO_Q_TO_QGRP_MAPm,
   3607                                 MEM_BLOCK_ALL, hw_index, entry));
   3608         }           
   3609     } else {
   3610         if (disable_q) {
   3611             soc_mem_field32_set(unit, MMU_THDO_Q_TO_QGRP_MAPm, entry, 
   3612                                 DISABLE_QUEUINGf, 0);
   3613             BCM_IF_ERROR_RETURN(
   3614                 soc_mem_write(unit, MMU_THDO_Q_TO_QGRP_MAPm,
   3615                                 MEM_BLOCK_ALL, hw_index, entry));
   3616         }
   3617     }
   3618     return BCM_E_NONE;
   3619 }
   3620 
   3621 int 
   3622 _bcm_tr3_cosq_gport_mcastq_disable(int unit, _bcm_tr3_cosq_node_t *sched_node,
   3623                                    _bcm_tr3_gport_q_disable_t *mcastq)
   3624 {
   3625     uint32 rval;
   3626 
   3627     if (!BCM_GPORT_IS_MCAST_QUEUE_GROUP(sched_node->gport)) {
   3628         return BCM_E_PARAM;
   3629     }
   3630 
   3631     if (mcastq == NULL) {
   3632         return BCM_E_PARAM;
   3633     }
   3634 
   3635     BCM_IF_ERROR_RETURN(soc_reg32_get(unit, OP_QUEUE_CONFIG_CELLr,
   3636                         sched_node->local_port, sched_node->hw_cosq, &rval));
   3637     mcastq->shared_limit = soc_reg_field_get(unit, OP_QUEUE_CONFIG_CELLr,
   3638                                              rval, Q_SHARED_LIMIT_CELLf);
   3639     mcastq->min_limit = soc_reg_field_get(unit, OP_QUEUE_CONFIG_CELLr,
   3640                                              rval, Q_MIN_CELLf);
   3641 
   3642     soc_reg_field_set(unit, OP_QUEUE_CONFIG_CELLr, &rval, Q_SHARED_LIMIT_CELLf, 0);
   3643     soc_reg_field_set(unit, OP_QUEUE_CONFIG_CELLr, &rval, Q_MIN_CELLf, 0);
   3644 
   3645     BCM_IF_ERROR_RETURN(soc_reg32_set(unit, OP_QUEUE_CONFIG_CELLr,
   3646                         sched_node->local_port, sched_node->hw_cosq, rval));
   3647 
   3648     BCM_IF_ERROR_RETURN(soc_reg32_get(unit, OP_QUEUE_CONFIG1_CELLr,
   3649                         sched_node->local_port, sched_node->hw_cosq, &rval));
   3650     mcastq->enable = soc_reg_field_get(unit, OP_QUEUE_CONFIG1_CELLr,
   3651                                              rval, Q_LIMIT_ENABLE_CELLf);
   3652     mcastq->q_limit_dynamic = soc_reg_field_get(unit, OP_QUEUE_CONFIG1_CELLr,
   3653                                                 rval, Q_LIMIT_DYNAMIC_CELLf);
   3654     soc_reg_field_set(unit, OP_QUEUE_CONFIG1_CELLr, &rval, Q_LIMIT_ENABLE_CELLf, 1);
   3655     soc_reg_field_set(unit, OP_QUEUE_CONFIG1_CELLr, &rval, Q_LIMIT_DYNAMIC_CELLf, 0);
   3656 
   3657     BCM_IF_ERROR_RETURN(soc_reg32_set(unit, OP_QUEUE_CONFIG1_CELLr,
   3658                         sched_node->local_port, sched_node->hw_cosq, rval));
   3659 
   3660     return BCM_E_NONE;
   3661 }
   3662 
   3663 int _bcm_tr3_cosq_gport_mcastq_enable(int unit, _bcm_tr3_cosq_node_t *sched_node,
   3664                                       _bcm_tr3_gport_q_disable_t *mcastq)
   3665 {
   3666     uint32 rval;
   3667     if (!BCM_GPORT_IS_MCAST_QUEUE_GROUP(sched_node->gport)) {
   3668         return BCM_E_PARAM;
   3669     }
   3670 
   3671     if (mcastq == NULL) {
   3672         return BCM_E_PARAM;
   3673     }
   3674 
   3675     BCM_IF_ERROR_RETURN(soc_reg32_get(unit, OP_QUEUE_CONFIG_CELLr,
   3676                         sched_node->local_port, sched_node->hw_cosq, &rval));
   3677 
   3678     soc_reg_field_set(unit, OP_QUEUE_CONFIG_CELLr, &rval, Q_SHARED_LIMIT_CELLf, mcastq->shared_limit);
   3679     soc_reg_field_set(unit, OP_QUEUE_CONFIG_CELLr, &rval, Q_MIN_CELLf, mcastq->min_limit);
   3680 
   3681     BCM_IF_ERROR_RETURN(soc_reg32_set(unit, OP_QUEUE_CONFIG_CELLr,
   3682                         sched_node->local_port, sched_node->hw_cosq, rval));
   3683 
   3684     BCM_IF_ERROR_RETURN(soc_reg32_get(unit, OP_QUEUE_CONFIG1_CELLr,
   3685                         sched_node->local_port, sched_node->hw_cosq, &rval));
   3686 
   3687     soc_reg_field_set(unit, OP_QUEUE_CONFIG1_CELLr, &rval, Q_LIMIT_ENABLE_CELLf, mcastq->enable);
   3688     soc_reg_field_set(unit, OP_QUEUE_CONFIG1_CELLr, &rval, Q_LIMIT_DYNAMIC_CELLf, mcastq->q_limit_dynamic);
   3689     BCM_IF_ERROR_RETURN(soc_reg32_set(unit, OP_QUEUE_CONFIG1_CELLr,
   3690                         sched_node->local_port, sched_node->hw_cosq, rval));
   3691 
   3692     return BCM_E_NONE;
   3693 }
   3694 /*
   3695  * Function:
   3696  *     bcm_tr3_cosq_gport_detach
   3697  * Purpose:
   3698  *     Detach sched_port from the specified index (cosq) of input_port
   3699  * Parameters:
   3700  *     unit       - (IN) unit number
   3701  *     sched_port - (IN) scheduler GPORT identifier
   3702  *     input_port - (IN) GPORT to detach from
   3703  *     cosq       - (IN) COS queue to detach from
   3704  * Returns:
   3705  *     BCM_E_XXX
   3706  */
   3707 int
   3708 bcm_tr3_cosq_gport_detach(int unit, bcm_gport_t sched_gport,
   3709                          bcm_gport_t input_gport, bcm_cos_queue_t cosq)
   3710 {
   3711     _bcm_tr3_cosq_node_t *sched_node, *input_node = NULL, *prev_node, *parent;
   3712     bcm_port_t sched_port, input_port;
   3713     _bcm_tr3_mmu_info_t *mmu_info;
   3714     _bcm_tr3_cosq_list_t *list;
   3715     _bcm_tr3_gport_q_disable_t mcastq;
   3716 
   3717     if ((mmu_info = _bcm_tr3_mmu_info[unit]) == NULL) {
   3718         return BCM_E_INIT;
   3719     }
   3720 
   3721     if ((BCM_GPORT_IS_UCAST_QUEUE_GROUP(input_gport)) ||
   3722         (BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(input_gport)) ||
   3723         (BCM_GPORT_IS_MCAST_QUEUE_GROUP(input_gport))) {
   3724         return BCM_E_PARAM;
   3725     }
   3726 
   3727     BCM_IF_ERROR_RETURN
   3728         (_bcm_tr3_cosq_node_get(unit, sched_gport, 0, NULL, &sched_port, NULL,
   3729                                &sched_node));
   3730 
   3731     if (sched_node->attached_to_input < 0) {
   3732         /* Not attached yet */
   3733         return BCM_E_PORT;
   3734     }
   3735 
   3736     if (input_gport != BCM_GPORT_INVALID) {
   3737         if (BCM_GPORT_IS_SCHEDULER(input_gport) || 
   3738             BCM_GPORT_IS_MODPORT(input_gport)   || 
   3739             BCM_GPORT_IS_LOCAL(input_gport)) {
   3740                BCM_IF_ERROR_RETURN
   3741                 (_bcm_tr3_cosq_node_get(unit, input_gport, 0, NULL, 
   3742                                     &input_port, NULL, &input_node));
   3743         } else {
   3744             if (!(BCM_GPORT_IS_SCHEDULER(sched_gport) || 
   3745                   BCM_GPORT_IS_UCAST_QUEUE_GROUP(sched_gport) ||
   3746                   BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(sched_gport) ||
   3747                   BCM_GPORT_IS_MCAST_QUEUE_GROUP(sched_gport))) {
   3748                 return BCM_E_PARAM;
   3749             }
   3750             else {
   3751                 BCM_IF_ERROR_RETURN
   3752                 (_bcm_tr3_cosq_localport_resolve(unit, input_gport,
   3753                                                 &input_port));
   3754                 input_node = NULL;
   3755             }
   3756         }
   3757     }
   3758 
   3759     if (sched_port != input_port) {
   3760         return BCM_E_PORT;
   3761     }
   3762 
   3763     if (sched_node->parent != input_node) {
   3764         return BCM_E_PORT;
   3765     }
   3766 
   3767     if ((cosq < -1) || 
   3768         (input_node && (input_node->numq != -1) && (cosq >= input_node->numq))) {
   3769         return BCM_E_PARAM;
   3770     }
   3771 
   3772     if (cosq != -1) {
   3773         if (sched_node->attached_to_input != cosq) {
   3774             return BCM_E_PARAM;
   3775         }
   3776     }
   3777 
   3778     if (sched_node->parent == NULL) {
   3779         return BCM_E_PARAM;
   3780     }
   3781 
   3782     if((sched_node->level == SOC_TR3_NODE_LVL_L2) &&
   3783                 BCM_GPORT_IS_MCAST_QUEUE_GROUP(sched_node->gport)) {
   3784         memset(&mcastq, 0, sizeof(_bcm_tr3_gport_q_disable_t));
   3785         if (!IS_AXP_PORT(unit, sched_port) ||
   3786             ((sched_node->hw_cosq >= 0) && (sched_node->hw_cosq < 8))) {
   3787             BCM_IF_ERROR_RETURN(
   3788                 _bcm_tr3_cosq_gport_mcastq_disable(unit, sched_node, &mcastq));
   3789         }
   3790     }
   3791 
   3792     if (soc_property_get(unit, spn_BCM5664X_WRR_GRANULARITY_1, 0)) { 
   3793         BCM_IF_ERROR_RETURN(
   3794             _bcm_tr3_cosq_sched_set(unit, sched_node->parent->gport, 
   3795                                     sched_node->attached_to_input,
   3796                                     BCM_COSQ_WEIGHTED_ROUND_ROBIN, 2, 0));
   3797     } else {
   3798         BCM_IF_ERROR_RETURN(
   3799             _bcm_tr3_cosq_sched_set(unit, sched_node->parent->gport, 
   3800                                     sched_node->attached_to_input,
   3801                                     BCM_COSQ_WEIGHTED_ROUND_ROBIN, 1, 0));
   3802      }
   3803 
   3804         BCM_IF_ERROR_RETURN(
   3805             soc_tr3_cosq_set_sched_parent(unit, input_port, 
   3806                         sched_node->level, sched_node->hw_index, 
   3807                         _soc_tr3_invalid_parent_index(unit, sched_node->level)));
   3808 
   3809         if ((sched_node->level == SOC_TR3_NODE_LVL_L2) &&  
   3810             !BCM_GPORT_IS_MCAST_QUEUE_GROUP(sched_node->gport)) {
   3811             _bcm_tr3_cosq_gport_node_disable(unit, sched_node, 1);                       
   3812         }
   3813 
   3814         /* unresolve the node - delete this node from parent's child list */
   3815         BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_node_unresolve(unit, sched_node, cosq));
   3816 
   3817         if((sched_node->level == SOC_TR3_NODE_LVL_L2) &&
   3818                   BCM_GPORT_IS_MCAST_QUEUE_GROUP(sched_node->gport)) {
   3819             if (!IS_AXP_PORT(unit, sched_port) ||
   3820                 ((sched_node->hw_cosq >= 0) && (sched_node->hw_cosq < 8))) {
   3821                 BCM_IF_ERROR_RETURN(
   3822                     _bcm_tr3_cosq_gport_mcastq_enable(unit, sched_node, &mcastq));
   3823             }
   3824         }
   3825 
   3826         /* now remove from the sw tree */
   3827         if (sched_node->parent != NULL) {
   3828             parent = sched_node->parent;
   3829             if (sched_node->parent->child == sched_node) {
   3830                 sched_node->parent->child = sched_node->sibling;
   3831             } else {
   3832                 prev_node = sched_node->parent->child;
   3833                 while (prev_node != NULL && prev_node->sibling != sched_node) {
   3834                     prev_node = prev_node->sibling;
   3835                 }
   3836                 if (prev_node == NULL) {
   3837                     return BCM_E_INTERNAL;
   3838                 }
   3839                 prev_node->sibling = sched_node->sibling;
   3840             }
   3841             sched_node->parent = NULL;
   3842             sched_node->sibling = NULL;
   3843             sched_node->attached_to_input = -1;
   3844 
   3845             if (parent->child == NULL) {
   3846                 list = NULL;
   3847                 switch (parent->level) {
   3848                     case SOC_TR3_NODE_LVL_ROOT:
   3849                         list = &mmu_info->l0_sched_list;
   3850                         break;
   3851                     case SOC_TR3_NODE_LVL_L0:
   3852                         list = &mmu_info->l1_sched_list;
   3853                         break;
   3854                     case SOC_TR3_NODE_LVL_L1:
   3855                         if ((sched_node->type == _BCM_TR3_NODE_DMVOQ) &&
   3856                             (mmu_info->num_dmvoq_queues > 0)) {
   3857                             list = &mmu_info->dmvoq_qlist;
   3858                         } else {
   3859                             list = &mmu_info->ext_qlist;
   3860                         }
   3861                     default:
   3862                         break;
   3863                 }
   3864                 if (list) {
   3865                     BCM_IF_ERROR_RETURN(_bcm_tr3_node_index_clear(list, 
   3866                                 parent->base_index, parent->base_size));
   3867                     parent->base_index = -1;
   3868                     parent->base_size  = 0;
   3869                 }
   3870             }
   3871         }
   3872 
   3873     LOG_INFO(BSL_LS_BCM_COSQ,
   3874              (BSL_META_U(unit,
   3875                          "                         hw_cosq=%d\n"),
   3876               sched_node->attached_to_input));
   3877 
   3878     return BCM_E_NONE;
   3879 }
   3880 
   3881 /*
   3882  * Function:
   3883  *     _bcm_tr3_cosq_gport_delete
   3884  * Purpose:
   3885  *     Destroy a cosq gport structure
   3886  * Parameters:
   3887  *     unit  - (IN) unit number
   3888  *     gport - (IN) GPORT identifier
   3889  *     sibling_delete   - (IN) if it is zero then don't delete sibling
   3890  * Returns:
   3891  *     BCM_E_XXX
   3892  */
   3893 STATIC int
   3894 _bcm_tr3_cosq_gport_delete(int unit, bcm_gport_t gport, int sibling_delete)
   3895 {
   3896     _bcm_tr3_cosq_node_t *node = NULL, *tnode, *base_node = NULL;
   3897     int local_port;
   3898     soc_info_t *si;
   3899     _bcm_tr3_mmu_info_t *mmu_info;
   3900     int phy_port, mmu_port, ii;
   3901 
   3902     LOG_INFO(BSL_LS_BCM_COSQ,
   3903              (BSL_META_U(unit,
   3904                          "_bcm_tr3_cosq_gport_delete: unit=%d gport=0x%x\n"),
   3905               unit, gport));
   3906 
   3907     si = &SOC_INFO(unit);
   3908 
   3909     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 
   3910         BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport) ||
   3911         BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) ||
   3912         BCM_GPORT_IS_SCHEDULER(gport)) {
   3913         BCM_IF_ERROR_RETURN
   3914             (_bcm_tr3_cosq_node_get(unit, gport, 0, NULL, &local_port, NULL, &node));
   3915     } else {
   3916         local_port = (BCM_GPORT_IS_LOCAL(gport)) ?
   3917           BCM_GPORT_LOCAL_GET(gport) : BCM_GPORT_MODPORT_PORT_GET(gport);
   3918 
   3919         if (!SOC_PORT_VALID(unit, local_port)) {
   3920             return BCM_E_PORT;
   3921         }
   3922        
   3923         mmu_info = _bcm_tr3_mmu_info[unit];
   3924         phy_port = si->port_l2p_mapping[local_port];
   3925         mmu_port = si->port_p2m_mapping[phy_port];
   3926         
   3927         for (ii = 0; ii < _BCM_TR3_NUM_PORT_SCHEDULERS; ii++) {
   3928             tnode = &mmu_info->sched_node[ii];
   3929             if (tnode->in_use == FALSE) {
   3930                 continue;
   3931             }
   3932             if ((tnode->level == SOC_TR3_NODE_LVL_ROOT) &&
   3933                 (tnode->hw_index == mmu_port)) {   
   3934                 node = tnode;
   3935                 break;
   3936             }
   3937         }
   3938         if (node == NULL) {
   3939             return BCM_E_NONE;
   3940         }
   3941     }
   3942     if (IS_TR3_HSP_PORT(unit, local_port)) {
   3943         return BCM_E_PARAM;
   3944     } 
   3945     if (node->child != NULL) {
   3946         BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_gport_delete(unit, node->child->gport, 1));
   3947     }
   3948 
   3949     if ((node->sibling != NULL) && sibling_delete) {
   3950         BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_gport_delete(unit, node->sibling->gport, 1));
   3951     }
   3952 
   3953     if (node->level != SOC_TR3_NODE_LVL_ROOT && node->attached_to_input >= 0) {
   3954         BCM_IF_ERROR_RETURN
   3955             (bcm_tr3_cosq_gport_detach(unit, node->gport, 
   3956                                 node->parent->gport, node->attached_to_input));
   3957     }
   3958 
   3959     if ((node->type == _BCM_TR3_NODE_DMVOQ) && 
   3960             (node->remote_modid > 0)) {
   3961         _bcm_tr3_voq_next_base_node_get (unit, local_port,
   3962                 node->remote_modid, &base_node);
   3963         if (base_node != NULL) {
   3964             BCM_PBMP_ASSIGN(base_node->fabric_pbmp,
   3965                     node->fabric_pbmp);
   3966         }
   3967     }
   3968 
   3969     _BCM_TR3_COSQ_NODE_INIT(node);
   3970     return BCM_E_NONE;
   3971 }
   3972 
   3973 /*
   3974  * Function:
   3975  *     bcm_tr3_cosq_gport_delete
   3976  * Purpose:
   3977  *     Destroy a cosq gport structure
   3978  * Parameters:
   3979  *     unit  - (IN) unit number
   3980  *     gport - (IN) GPORT identifier
   3981  * Returns:
   3982  *     BCM_E_XXX
   3983  */
   3984 int
   3985 bcm_tr3_cosq_gport_delete(int unit, bcm_gport_t gport)
   3986 { 
   3987    return _bcm_tr3_cosq_gport_delete(unit, gport, 0);
   3988 }
   3989 
   3990 /*
   3991  * Function:
   3992  *     bcm_tr3_cosq_gport_get
   3993  * Purpose:
   3994  *     Get a cosq gport structure
   3995  * Parameters:
   3996  *     unit  - (IN) unit number
   3997  *     gport - (IN) GPORT identifier
   3998  *     port  - (OUT) port number
   3999  *     numq  - (OUT) number of COS queues
   4000  *     flags - (OUT) flags (BCM_COSQ_GPORT_XXX)
   4001  * Returns:
   4002  *     BCM_E_XXX
   4003  */
   4004 int
   4005 bcm_tr3_cosq_gport_get(int unit, bcm_gport_t gport, bcm_gport_t *port,
   4006                       int *numq, uint32 *flags)
   4007 {
   4008     _bcm_tr3_mmu_info_t *mmu_info;
   4009     _bcm_tr3_cosq_node_t *node;
   4010     bcm_module_t modid;
   4011     bcm_port_t local_port;
   4012     int id;
   4013     _bcm_gport_dest_t dest;
   4014 
   4015     if ((mmu_info = _bcm_tr3_mmu_info[unit]) == NULL) {
   4016         return BCM_E_INIT;
   4017     }
   4018 
   4019     if (port == NULL || numq == NULL || flags == NULL) {
   4020         return BCM_E_PARAM;
   4021     }
   4022 
   4023     LOG_INFO(BSL_LS_BCM_COSQ,
   4024              (BSL_META_U(unit,
   4025                          "bcm_tr3_cosq_gport_get: unit=%d gport=0x%x\n"),
   4026               unit, gport));
   4027 
   4028     BCM_IF_ERROR_RETURN
   4029         (_bcm_tr3_cosq_node_get(unit, gport, 0, NULL, &local_port, &id, &node));
   4030 
   4031     if (SOC_USE_GPORT(unit)) {
   4032         BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid));
   4033         dest.gport_type = _SHR_GPORT_TYPE_MODPORT;
   4034         dest.modid = modid;
   4035         dest.port = local_port;
   4036         BCM_IF_ERROR_RETURN(_bcm_esw_gport_construct(unit, &dest, port));
   4037     } else {
   4038         *port = local_port;
   4039     }
   4040 
   4041     *numq = node->numq;
   4042 
   4043     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   4044         id = BCM_GPORT_UCAST_QUEUE_GROUP_QID_GET(gport);
   4045         if (_BCM_TR3_IS_UC_QUEUE(mmu_info, id)) {
   4046             *flags = BCM_COSQ_GPORT_UCAST_QUEUE_GROUP;
   4047         } else if (node->type == _BCM_TR3_NODE_DMVOQ) {
   4048             *flags = BCM_COSQ_GPORT_DESTMOD_UCAST_QUEUE_GROUP;
   4049         } else if (node->type == _BCM_TR3_NODE_VLAN) {
   4050             *flags = BCM_COSQ_GPORT_VLAN_UCAST_QUEUE_GROUP;
   4051         }
   4052     } else if (BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) {
   4053         *flags = BCM_COSQ_GPORT_DESTMOD_UCAST_QUEUE_GROUP;
   4054     } else if (BCM_GPORT_IS_SCHEDULER(gport)) {
   4055         *flags = BCM_COSQ_GPORT_SCHEDULER;
   4056     } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   4057         *flags = BCM_COSQ_GPORT_MCAST_QUEUE_GROUP;
   4058     } else {
   4059         *flags = 0;
   4060     }
   4061 
   4062     LOG_INFO(BSL_LS_BCM_COSQ,
   4063              (BSL_META_U(unit,
   4064                          "                       port=0x%x numq=%d flags=0x%x\n"),
   4065               *port, *numq, *flags));
   4066 
   4067     return BCM_E_NONE;
   4068 }
   4069 
   4070 /*
   4071  * Function:
   4072  *     bcm_tr3_cosq_gport_traverse
   4073  * Purpose:
   4074  *     Walks through the valid COSQ GPORTs and calls
   4075  *     the user supplied callback function for each entry.
   4076  * Parameters:
   4077  *     unit       - (IN) unit number
   4078  *     trav_fn    - (IN) Callback function.
   4079  *     user_data  - (IN) User data to be passed to callback function
   4080  * Returns:
   4081  *     BCM_E_NONE - Success.
   4082  *     BCM_E_XXX
   4083  */
   4084 int
   4085 bcm_tr3_cosq_gport_traverse(int unit, bcm_cosq_gport_traverse_cb cb,
   4086                            void *user_data)
   4087 {
   4088     _bcm_tr3_cosq_node_t *port_info;
   4089     _bcm_tr3_mmu_info_t *mmu_info;
   4090     bcm_module_t my_modid, modid_out;
   4091     bcm_port_t port, port_out;
   4092 
   4093     if (_bcm_tr3_mmu_info[unit] == NULL) {
   4094         return BCM_E_INIT;
   4095     }
   4096     mmu_info = _bcm_tr3_mmu_info[unit];
   4097 
   4098     BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_modid));
   4099     PBMP_ALL_ITER(unit, port) {
   4100         BCM_IF_ERROR_RETURN
   4101             (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET,
   4102                                     my_modid, port, &modid_out, &port_out));
   4103 
   4104         /* root node */
   4105         port_info = &mmu_info->sched_node[port_out];
   4106 
   4107         if (port_info->gport >= 0) {
   4108             _bcm_tr3_cosq_gport_traverse(unit, port_info->gport, cb, user_data);
   4109         }
   4110       }
   4111 
   4112     return BCM_E_NONE;
   4113 }
   4114 
   4115 /*
   4116  * Function:
   4117  *     bcm_tr3_cosq_gport_attach
   4118  * Purpose:
   4119  *     Attach sched_port to the specified index (cosq) of input_port
   4120  * Parameters:
   4121  *     unit       - (IN) unit number
   4122  *     sched_port - (IN) scheduler GPORT identifier
   4123  *     input_port - (IN) GPORT to attach to
   4124  *     cosq       - (IN) COS queue to attach to (-1 for first available cosq)
   4125  * Returns:
   4126  *     BCM_E_XXX
   4127  */
   4128 int
   4129 bcm_tr3_cosq_gport_attach(int unit, bcm_gport_t gport, 
   4130                            bcm_gport_t to_gport, 
   4131                            bcm_cos_queue_t to_cosq)
   4132 {
   4133     _bcm_tr3_mmu_info_t *mmu_info;
   4134     _bcm_tr3_cosq_node_t *node, *to_node;
   4135     bcm_port_t port, to_port, local_port = -1;
   4136     int rv;
   4137 
   4138     if ((mmu_info = _bcm_tr3_mmu_info[unit]) == NULL) {
   4139         return BCM_E_INIT;
   4140     }
   4141 
   4142     if ((BCM_GPORT_IS_UCAST_QUEUE_GROUP(to_gport)) ||
   4143         (BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(to_gport)) ||
   4144         (BCM_GPORT_IS_MCAST_QUEUE_GROUP(to_gport)) ||
   4145         (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(to_gport))) {
   4146         return BCM_E_PARAM;
   4147     }
   4148 
   4149     if(!(BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
   4150          BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) ||
   4151          BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport) ||
   4152          BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport) ||
   4153          BCM_GPORT_IS_SCHEDULER(gport))) {
   4154         return BCM_E_PORT;
   4155     }
   4156 
   4157     if (to_cosq >= 64) {
   4158         return BCM_E_RESOURCE;
   4159     }
   4160 
   4161     BCM_IF_ERROR_RETURN
   4162         (_bcm_tr3_cosq_node_get(unit, gport, 0, NULL, &port, NULL, &node));
   4163 
   4164     if (node->attached_to_input >= 0) {
   4165         /* Has already attached */
   4166         return BCM_E_EXISTS;
   4167     }
   4168 
   4169     if (BCM_GPORT_IS_SCHEDULER(to_gport)) {
   4170         BCM_IF_ERROR_RETURN
   4171             (_bcm_tr3_cosq_node_get(unit, to_gport, 0, NULL, &to_port, NULL,
   4172                                    &to_node));
   4173     } else {
   4174         BCM_IF_ERROR_RETURN
   4175             (_bcm_tr3_cosq_localport_resolve(unit, to_gport, &to_port));
   4176         to_node = &mmu_info->sched_node[to_port];
   4177     }
   4178 
   4179     if (port != to_port) {
   4180         return BCM_E_PORT;
   4181     }
   4182 
   4183     /* Identify the levels of schedulers
   4184      * to_port == phy_port && gport == scheduler => gport = L0
   4185      * to_port == schduler && gport == scheduler => to_port = L0 and port = L1
   4186      * to_port == scheduler && port == queue_group => to_port = L1 and port = L2
   4187      */
   4188     if (to_node != NULL) {
   4189         if (!BCM_GPORT_IS_SCHEDULER(to_gport)) {
   4190             if ((to_node->numq == 0) || (to_node->numq_expandable)) {
   4191                 local_port = (BCM_GPORT_IS_LOCAL(to_gport)) ?
   4192                               BCM_GPORT_LOCAL_GET(to_gport) :
   4193                               BCM_GPORT_MODPORT_PORT_GET(to_gport);
   4194                 to_node->gport = to_gport;
   4195                 to_node->hw_index = 
   4196                     SOC_INFO(unit).port_p2m_mapping[SOC_INFO(unit).port_l2p_mapping[local_port]];
   4197                 to_node->in_use = TRUE;
   4198                 to_node->level = SOC_TR3_NODE_LVL_ROOT;
   4199                 to_node->local_port = port;
   4200                 to_node->attached_to_input = 0;
   4201                 to_node->numq_expandable = 1;
   4202 
   4203                 /* How many children do we need, 1 if unknown, else 
   4204                  * take the max of to_cosq or current numq */
   4205                 if (to_cosq == -1) {
   4206                     to_node->numq += 1;
   4207                 } else {
   4208                     if (to_cosq >= to_node->numq) {
   4209                         to_node->numq = to_cosq + 1;
   4210                     }
   4211                 }
   4212             }
   4213 
   4214             if (!BCM_GPORT_IS_SCHEDULER(gport)) {
   4215                 return BCM_E_PARAM;
   4216             }
   4217 
   4218             node->level = SOC_TR3_NODE_LVL_L0;
   4219         } else {
   4220              if (to_node->level == SOC_TR3_NODE_LVL_ROOT) {
   4221                  to_node->attached_to_input = 0;
   4222                  node->level = SOC_TR3_NODE_LVL_L0;
   4223              }
   4224 
   4225              if (IS_TR3_HSP_PORT(unit, to_port)) {
   4226                  if ((to_node->level == -1)) {
   4227                      to_node->level = 
   4228                          (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
   4229                           BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) ||
   4230                           BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport)) ?
   4231                            SOC_TR3_NODE_LVL_L0 : 
   4232                            SOC_TR3_NODE_LVL_ROOT;
   4233                  }
   4234 
   4235                  if (node->level == -1) {
   4236                      node->level = 
   4237                          (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
   4238                           BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) ||
   4239                           BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport)) ?
   4240                          SOC_TR3_NODE_LVL_L2 : SOC_TR3_NODE_LVL_L0;
   4241                  }
   4242                  
   4243              } else {
   4244                  if ((to_node->level == -1)) {
   4245                      to_node->level = (BCM_GPORT_IS_SCHEDULER(gport)) ?
   4246                          SOC_TR3_NODE_LVL_L0 : SOC_TR3_NODE_LVL_L1;
   4247                  }
   4248 
   4249                  if (node->level == -1) {
   4250                      node->level = 
   4251                        (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
   4252                         BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport) ||
   4253                         BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) ||
   4254                         BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport)) ?
   4255                        SOC_TR3_NODE_LVL_L2 : SOC_TR3_NODE_LVL_L1;
   4256                  }
   4257              }
   4258         }
   4259     }
   4260 
   4261     if ((to_cosq < -1) || ((to_node->numq != -1) && (to_cosq >= to_node->numq))) {
   4262         return BCM_E_PARAM;
   4263     }
   4264     if (to_node->hw_index == -1) {
   4265         return BCM_E_PARAM;
   4266     }
   4267 
   4268     if (local_port == -1) {
   4269         if (node->local_port != -1) {
   4270             local_port = node->local_port;
   4271         } else {
   4272             BCM_IF_ERROR_RETURN
   4273                     (_bcm_tr3_cosq_localport_resolve(unit, gport, &local_port));
   4274         }         
   4275     }
   4276     if ((local_port != -1) && IS_AXP_PORT(unit, local_port)) {
   4277         if (node->level == SOC_TR3_NODE_LVL_L2) {
   4278         BCM_IF_ERROR_RETURN
   4279             (_soc_tr3_cosq_axp_node_validate(unit, local_port, node->hw_index, node->hw_cosq));
   4280         }
   4281     }
   4282 
   4283     if (BCM_GPORT_IS_SCHEDULER(to_gport) || BCM_GPORT_IS_LOCAL(to_gport) ||
   4284         BCM_GPORT_IS_MODPORT(to_gport)) {
   4285         if (to_node->attached_to_input < 0) {
   4286             /* dont allow to attach to a node that has already attached */
   4287             return BCM_E_PARAM;
   4288         }
   4289 
   4290             node->parent = to_node;
   4291             node->sibling = to_node->child;
   4292             to_node->child = node;
   4293             /* resolve the nodes */
   4294             rv = _bcm_tr3_cosq_node_resolve(unit, node, to_cosq);
   4295             if (BCM_FAILURE(rv)) {
   4296                 to_node->child = node->sibling;
   4297                 node->parent = NULL;
   4298                 return rv;
   4299             }
   4300 
   4301             if ((node->level == SOC_TR3_NODE_LVL_L2) &&
   4302                 !BCM_GPORT_IS_MCAST_QUEUE_GROUP(node->gport)) {
   4303                 _bcm_tr3_cosq_gport_node_disable(unit, node, 0);                       
   4304             }
   4305 
   4306             LOG_INFO(BSL_LS_BCM_COSQ,
   4307                      (BSL_META_U(unit,
   4308                                  "                         hw_cosq=%d\n"),
   4309                       node->attached_to_input));
   4310 
   4311     } else {
   4312             return BCM_E_PORT;
   4313     }
   4314     
   4315     return BCM_E_NONE;
   4316 }
   4317 
   4318 /*
   4319  * Function:
   4320  *     bcm_tr3_cosq_gport_attach_get
   4321  * Purpose:
   4322  *     Get attached status of a scheduler port
   4323  * Parameters:
   4324  *     unit       - (IN) unit number
   4325  *     sched_port - (IN) scheduler GPORT identifier
   4326  *     input_port - (OUT) GPORT to attach to
   4327  *     cosq       - (OUT) COS queue to attached to
   4328  * Returns:
   4329  *     BCM_E_XXX
   4330  * Notes:
   4331  */
   4332 int
   4333 bcm_tr3_cosq_gport_attach_get(int unit, bcm_gport_t sched_gport,
   4334                              bcm_gport_t *input_gport, bcm_cos_queue_t *cosq)
   4335 {
   4336     _bcm_tr3_cosq_node_t *sched_node;
   4337     bcm_module_t modid, modid_out;
   4338     bcm_port_t port, port_out;
   4339 
   4340     if (input_gport == NULL || cosq == NULL) {
   4341         return BCM_E_PARAM;
   4342     }
   4343 
   4344     BCM_IF_ERROR_RETURN
   4345         (_bcm_tr3_cosq_node_get(unit, sched_gport, 0, &modid, &port, NULL,
   4346                                &sched_node));
   4347 
   4348     if (sched_node->attached_to_input < 0) {
   4349         /* Not attached yet */
   4350         return BCM_E_NOT_FOUND;
   4351     }
   4352 
   4353     if (sched_node->parent != NULL) { /* sched_node is not an S1 scheduler */
   4354         *input_gport = sched_node->parent->gport;
   4355     } else {  /* sched_node is an S1 scheduler */
   4356         BCM_IF_ERROR_RETURN
   4357             (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, modid, port,
   4358                                     &modid_out, &port_out));
   4359         BCM_GPORT_MODPORT_SET(*input_gport, modid_out, port_out);
   4360     }
   4361     *cosq = sched_node->attached_to_input;
   4362 
   4363     return BCM_E_NONE;
   4364 }
   4365 
   4366 /*
   4367  * Function:
   4368  *      bcm_tr3_cosq_gport_child_get
   4369  * Purpose:
   4370  *      Get the child node GPORT atatched to N-th index (cosq)
   4371  *      of the scheduler GPORT.
   4372  * Parameters:
   4373  *      unit       - (IN)  Unit number.
   4374  *      in_gport   - (IN)  Scheduler GPORT ID.
   4375  *      cosq       - (IN)  COS queue attached to.
   4376  *      out_gport  - (OUT) child GPORT ID.
   4377  * Returns:
   4378  *      BCM_E_XXX
   4379  * Notes:
   4380  */
   4381 int
   4382 bcm_tr3_cosq_gport_child_get(int unit, bcm_gport_t in_gport,
   4383                             bcm_cos_queue_t cosq,
   4384                             bcm_gport_t *out_gport)
   4385 {
   4386     _bcm_tr3_cosq_node_t *in_node = NULL;
   4387     _bcm_tr3_cosq_node_t *cur_node = NULL;
   4388     _bcm_tr3_cosq_node_t *tmp_node = NULL;
   4389     bcm_module_t modid;
   4390     bcm_port_t port;
   4391 
   4392     if (out_gport == NULL) {
   4393         return BCM_E_PARAM;
   4394     }
   4395 
   4396     /* get the child of the input gport node
   4397      * at an index of cosq
   4398      */
   4399 
   4400     if ((cosq < 0) || ( cosq >= 64)) {
   4401         return BCM_E_PARAM;
   4402     }
   4403     /* Check if gport is not set  than set it */
   4404     if(!BCM_GPORT_IS_SET(in_gport)) {
   4405        BCM_IF_ERROR_RETURN(bcm_esw_port_gport_get(unit, in_gport, &in_gport));
   4406     } 
   4407     BCM_IF_ERROR_RETURN
   4408         (_bcm_tr3_cosq_node_get(unit, in_gport, 0, &modid, &port, NULL,
   4409                                &in_node));
   4410     if ((in_node->child == NULL) && (in_node->level == SOC_TR3_NODE_LVL_L2)) {
   4411        return BCM_E_PARAM;
   4412     }
   4413 
   4414     for (cur_node = in_node->child; cur_node != NULL;
   4415          cur_node = cur_node->sibling) {
   4416         if (cur_node->attached_to_input == cosq) {
   4417            tmp_node = cur_node;
   4418            break;
   4419         }
   4420     }
   4421     if (tmp_node == NULL) {
   4422         return BCM_E_NOT_FOUND;
   4423     }
   4424     *out_gport = tmp_node->gport;
   4425 
   4426     return BCM_E_NONE;
   4427 }
   4428 /*
   4429  *  Convert HW drop probability to percent value
   4430  */
   4431 static int
   4432 _bcm_tr3_hw_drop_prob_to_percent[] = {
   4433     0,     /* 0  */
   4434     1,     /* 1  */
   4435     2,     /* 2  */
   4436     3,     /* 3  */
   4437     4,     /* 4  */
   4438     5,     /* 5  */
   4439     6,     /* 6  */
   4440     7,     /* 7  */
   4441     8,     /* 8  */
   4442     9,     /* 9  */
   4443     10,    /* 10 */
   4444     25,    /* 11 */
   4445     50,    /* 12 */
   4446     75,    /* 13 */
   4447     100,   /* 14 */
   4448     -1     /* 15 */
   4449 };
   4450 
   4451 STATIC int
   4452 _bcm_tr3_percent_to_drop_prob(int percent)
   4453 {
   4454    int i;
   4455 
   4456    for (i = 14; i > 0 ; i--) {
   4457       if (percent >= _bcm_tr3_hw_drop_prob_to_percent[i]) {
   4458           break;
   4459       }
   4460    }
   4461    return i;
   4462 }
   4463 
   4464 STATIC int
   4465 _bcm_tr3_drop_prob_to_percent(int drop_prob) {
   4466    return (_bcm_tr3_hw_drop_prob_to_percent[drop_prob]);
   4467 }
   4468 
   4469 /*
   4470  * index: degree, value: contangent(degree) * 100
   4471  * max value is 0xffff (16-bit) at 0 degree
   4472  */
   4473 static int
   4474 _bcm_tr3_cotangent_lookup_table[] =
   4475 {
   4476     /*  0.. 5 */  65535, 5728, 2863, 1908, 1430, 1143,
   4477     /*  6..11 */    951,  814,  711,  631,  567,  514,
   4478     /* 12..17 */    470,  433,  401,  373,  348,  327,
   4479     /* 18..23 */    307,  290,  274,  260,  247,  235,
   4480     /* 24..29 */    224,  214,  205,  196,  188,  180,
   4481     /* 30..35 */    173,  166,  160,  153,  148,  142,
   4482     /* 36..41 */    137,  132,  127,  123,  119,  115,
   4483     /* 42..47 */    111,  107,  103,  100,   96,   93,
   4484     /* 48..53 */     90,   86,   83,   80,   78,   75,
   4485     /* 54..59 */     72,   70,   67,   64,   62,   60,
   4486     /* 60..65 */     57,   55,   53,   50,   48,   46,
   4487     /* 66..71 */     44,   42,   40,   38,   36,   34,
   4488     /* 72..77 */     32,   30,   28,   26,   24,   23,
   4489     /* 78..83 */     21,   19,   17,   15,   14,   12,
   4490     /* 84..89 */     10,    8,    6,    5,    3,    1,
   4491     /* 90     */      0
   4492 };
   4493 
   4494 /*
   4495  * Given a slope (angle in degrees) from 0 to 90, return the number of cells
   4496  * in the range from 0% drop probability to 100% drop probability.
   4497  */
   4498 STATIC int
   4499 _bcm_tr3_angle_to_cells(int angle)
   4500 {
   4501     return (_bcm_tr3_cotangent_lookup_table[angle]);
   4502 }
   4503 
   4504 /*
   4505  * Given a number of packets in the range from 0% drop probability
   4506  * to 100% drop probability, return the slope (angle in degrees).
   4507  */
   4508 STATIC int
   4509 _bcm_tr3_cells_to_angle(int packets)
   4510 {
   4511     int angle;
   4512 
   4513     for (angle = 90; angle >= 0 ; angle--) {
   4514         if (packets <= _bcm_tr3_cotangent_lookup_table[angle]) {
   4515             break;
   4516         }
   4517     }
   4518     return angle;
   4519 }
   4520 
   4521 /*
   4522  * Function:
   4523  *     _bcm_tr3_cosq_bucket_set
   4524  * Purpose:
   4525  *     Configure COS queue bandwidth control bucket
   4526  * Parameters:
   4527  *     unit          - (IN) unit number
   4528  *     port          - (IN) port number or GPORT identifier
   4529  *     cosq          - (IN) COS queue number
   4530  *     min_quantum   - (IN) kbps or packet/second
   4531  *     max_quantum   - (IN) kbps or packet/second
   4532  *     burst_quantum - (IN) kbps or packet/second
   4533  *     flags         - (IN)
   4534  * Returns:
   4535  *     BCM_E_XXX
   4536  * Notes:
   4537  *     If port is any form of local port, cosq is the hardware queue index.
   4538  */
   4539 STATIC int
   4540 _bcm_tr3_cosq_bucket_set(int unit, bcm_gport_t port, bcm_cos_queue_t cosq,
   4541                         uint32 min_quantum, uint32 max_quantum,
   4542                         uint32 kbits_burst_min, uint32 kbits_burst_max, 
   4543                         uint32 flags)
   4544 {
   4545     _bcm_tr3_cosq_node_t *node = NULL;
   4546     bcm_port_t local_port;
   4547     int index, rv;
   4548     uint32 rval;
   4549     uint32 meter_flags;
   4550     uint32 bucketsize_max, bucketsize_min;
   4551     uint32 granularity_max, granularity_min;
   4552     uint32 refresh_rate_max, refresh_rate_min;
   4553     int refresh_bitsize = 0, bucket_bitsize = 0;
   4554     soc_mem_t config_mem = INVALIDm;
   4555     uint32 entry[SOC_MAX_MEM_WORDS];
   4556 
   4557     /* caller should resolve the cosq. */
   4558     if (cosq < 0) {
   4559         if (cosq == -1) {
   4560             /* caller needs to resolve the wild card value (-1) */
   4561             return BCM_E_INTERNAL;
   4562         } else { /* reject all other negative value */
   4563             return BCM_E_PARAM;
   4564         }
   4565     }
   4566 
   4567     BCM_IF_ERROR_RETURN
   4568         (_bcm_tr3_cosq_index_resolve(unit, port, cosq,
   4569                                     _BCM_TR3_COSQ_INDEX_STYLE_BUCKET,
   4570                                     &local_port, &index, NULL));
   4571 
   4572     if (BCM_GPORT_IS_SET(port) && 
   4573         ((BCM_GPORT_IS_SCHEDULER(port)) ||
   4574           BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
   4575           BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port) ||
   4576           BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) ||
   4577           BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port))) {
   4578 
   4579         BCM_IF_ERROR_RETURN
   4580             (_bcm_tr3_cosq_node_get(unit, port, cosq, NULL, 
   4581                                     NULL, NULL, &node));
   4582     }
   4583 
   4584     if (node) {
   4585         if (BCM_GPORT_IS_SCHEDULER(port)) {
   4586             if (node->level == SOC_TR3_NODE_LVL_ROOT) {
   4587                 config_mem = MMU_MTRO_L0_MEMm;
   4588             } else if (node->level == SOC_TR3_NODE_LVL_L0) {
   4589                 if (IS_TR3_HSP_PORT(unit, local_port)) {
   4590                     config_mem = MMU_MTRO_L2_MEMm;
   4591                 } else {
   4592                     config_mem = MMU_MTRO_L1_MEMm;
   4593                 }
   4594             } else if (node->level == SOC_TR3_NODE_LVL_L1) {
   4595                 config_mem = MMU_MTRO_L2_MEMm;
   4596             } else {
   4597                 return BCM_E_PARAM;
   4598             }
   4599         } else if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
   4600                    BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port) ||
   4601                    BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
   4602             config_mem = MMU_MTRO_L2_MEMm;
   4603         } else {
   4604             return BCM_E_PARAM;
   4605         }
   4606     } else {
   4607         if (IS_CPU_PORT(unit, local_port)) {
   4608             config_mem = MMU_MTRO_L2_MEMm;
   4609         } else if (IS_TR3_HSP_PORT(unit, local_port)) {
   4610             config_mem = MMU_MTRO_L0_MEMm;
   4611         } else {
   4612             config_mem = MMU_MTRO_L1_MEMm;
   4613         }
   4614     }
   4615 
   4616     meter_flags = flags & BCM_COSQ_BW_PACKET_MODE ?
   4617                             _BCM_TD_METER_FLAG_PACKET_MODE : 0;
   4618     BCM_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, &rval));
   4619     if (soc_reg_field_get(unit, MISCCONFIGr, rval, ITU_MODE_SELf)) {
   4620         meter_flags |= _BCM_TD_METER_FLAG_NON_LINEAR;
   4621     }
   4622 
   4623     refresh_bitsize = soc_mem_field_length(unit, config_mem, MAX_REFRESHf);
   4624     bucket_bitsize = soc_mem_field_length(unit, config_mem, MAX_THD_SELf);
   4625 
   4626     BCM_IF_ERROR_RETURN
   4627         (_bcm_td_rate_to_bucket_encoding(unit, max_quantum, kbits_burst_max,
   4628                                          meter_flags, refresh_bitsize,
   4629                                          bucket_bitsize, &refresh_rate_max,
   4630                                          &bucketsize_max, &granularity_max));
   4631 
   4632     BCM_IF_ERROR_RETURN
   4633         (_bcm_td_rate_to_bucket_encoding(unit, min_quantum, kbits_burst_min,
   4634                                          meter_flags, refresh_bitsize,
   4635                                          bucket_bitsize, &refresh_rate_min,
   4636                                          &bucketsize_min, &granularity_min));
   4637 
   4638     sal_memset(entry, 0, sizeof(uint32)*SOC_MAX_MEM_WORDS);
   4639     soc_mem_field32_set(unit, config_mem, &entry, MAX_METER_GRANf, granularity_max);
   4640     soc_mem_field32_set(unit, config_mem, &entry, MAX_REFRESHf, refresh_rate_max);
   4641     soc_mem_field32_set(unit, config_mem, &entry, MAX_THD_SELf, bucketsize_max);
   4642 
   4643     soc_mem_field32_set(unit, config_mem, &entry, MIN_METER_GRANf, granularity_min);
   4644     soc_mem_field32_set(unit, config_mem, &entry, MIN_REFRESHf, refresh_rate_min);
   4645     soc_mem_field32_set(unit, config_mem, &entry, MIN_THD_SELf, bucketsize_min);
   4646 
   4647     soc_mem_field32_set(unit, config_mem, &entry, SHAPER_CONTROLf,
   4648                         (flags & BCM_COSQ_BW_PACKET_MODE) ? 1 : 0);
   4649     SOC_EGRESS_METERING_LOCK(unit);
   4650     rv = soc_mem_write(unit, config_mem, MEM_BLOCK_ALL, index, &entry);
   4651     SOC_EGRESS_METERING_UNLOCK(unit);
   4652     if (rv < 0) {
   4653         return rv;
   4654     } 
   4655     if ((node==NULL) && (!IS_CPU_PORT(unit, local_port)) &&
   4656         ((!soc_feature(unit, soc_feature_tr3_sp_vector_mask)) &&
   4657          soc_property_port_get(unit, local_port, spn_PORT_SCHED_DYNAMIC, 0))) {
   4658         if (soc_port_hg_capable(unit, port)) {
   4659             /* As the 8th index is meant for SC/QM adding offset of 9 on dyn Q's */
   4660             BCM_IF_ERROR_RETURN
   4661                 (soc_mem_write(unit, config_mem, MEM_BLOCK_ALL, index + 9, &entry));
   4662         } else {
   4663             BCM_IF_ERROR_RETURN
   4664                 (soc_mem_write(unit, config_mem, MEM_BLOCK_ALL, index + 8, &entry));
   4665         }
   4666     }
   4667 
   4668     return BCM_E_NONE;
   4669 }
   4670 
   4671 /*
   4672  * Function:
   4673  *     _bcm_tr3_cosq_bucket_get
   4674  * Purpose:
   4675  *     Get COS queue bandwidth control bucket setting
   4676  * Parameters:
   4677  *     unit          - (IN) unit number
   4678  *     port          - (IN) port number or GPORT identifier
   4679  *     cosq          - (IN) COS queue number
   4680  *     min_quantum   - (OUT) kbps or packet/second
   4681  *     max_quantum   - (OUT) kbps or packet/second
   4682  *     burst_quantum - (OUT) kbps or packet/second
   4683  *     flags         - (IN)
   4684  * Returns:
   4685  *     BCM_E_XXX
   4686  * Notes:
   4687  *     If port is any form of local port, cosq is the hardware queue index.
   4688  */
   4689 STATIC int
   4690 _bcm_tr3_cosq_bucket_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   4691                         uint32 *min_quantum, uint32 *max_quantum,
   4692                         uint32 *kbits_burst_min, uint32 *kbits_burst_max,
   4693                         uint32 *flags)
   4694 {
   4695     _bcm_tr3_cosq_node_t *node = NULL;
   4696     bcm_port_t local_port;
   4697     int index, rv;
   4698     uint32 rval;
   4699     uint32 refresh_rate, bucketsize, granularity, meter_flags;
   4700     soc_mem_t config_mem = INVALIDm;
   4701     uint32 entry[SOC_MAX_MEM_WORDS];
   4702 
   4703     if (cosq < 0) {
   4704         if (cosq == -1) {
   4705             /* caller needs to resolve the wild card value (-1) */
   4706             return BCM_E_INTERNAL;
   4707         } else { /* reject all other negative value */
   4708             return BCM_E_PARAM;
   4709         }
   4710     }
   4711 
   4712     BCM_IF_ERROR_RETURN
   4713         (_bcm_tr3_cosq_index_resolve(unit, port, cosq,
   4714                                     _BCM_TR3_COSQ_INDEX_STYLE_BUCKET,
   4715                                     &local_port, &index, NULL));
   4716 
   4717     if (BCM_GPORT_IS_SET(port) && 
   4718         ((BCM_GPORT_IS_SCHEDULER(port)) ||
   4719           BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
   4720           BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port) ||
   4721           BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) ||
   4722           BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port))) {
   4723 
   4724         BCM_IF_ERROR_RETURN
   4725             (_bcm_tr3_cosq_node_get(unit, port, cosq, NULL, 
   4726                                     &local_port, NULL, &node));
   4727     }
   4728 
   4729     if (node) {
   4730         if (BCM_GPORT_IS_SCHEDULER(port)) {
   4731             if (node->level == SOC_TR3_NODE_LVL_ROOT) {
   4732                 config_mem = MMU_MTRO_L0_MEMm;
   4733             } else if (node->level == SOC_TR3_NODE_LVL_L0) {
   4734                 if (IS_TR3_HSP_PORT(unit, local_port)) {
   4735                     config_mem = MMU_MTRO_L2_MEMm;
   4736                 } else {
   4737                     config_mem = MMU_MTRO_L1_MEMm;
   4738                 }
   4739             } else if (node->level == SOC_TR3_NODE_LVL_L1) {
   4740                 config_mem = MMU_MTRO_L2_MEMm;
   4741             } else {
   4742                 return BCM_E_PARAM;
   4743             }
   4744         } else if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
   4745                    BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port) ||
   4746                    BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
   4747             config_mem = MMU_MTRO_L2_MEMm;
   4748         } else {
   4749             return BCM_E_PARAM;
   4750         }
   4751     } else {
   4752         if (IS_CPU_PORT(unit, local_port)) {
   4753             config_mem = MMU_MTRO_L2_MEMm;
   4754         } else if (IS_TR3_HSP_PORT(unit, local_port)) {
   4755             config_mem = MMU_MTRO_L0_MEMm;
   4756         } else {
   4757             config_mem = MMU_MTRO_L1_MEMm;
   4758         }
   4759     }
   4760 
   4761     if (min_quantum == NULL || max_quantum == NULL || 
   4762         kbits_burst_max == NULL || kbits_burst_min == NULL) {
   4763         return BCM_E_PARAM;
   4764     }
   4765 
   4766     #ifdef DEBUG_TR3_COSQ
   4767     LOG_CLI((BSL_META_U(unit,
   4768                         "_bcm_tr3_cosq_bucket_get : gport=0x%08x Index : %d mem=%d\n"),
   4769              port, index, config_mem));
   4770     #endif
   4771     SOC_EGRESS_METERING_LOCK(unit);
   4772     rv = soc_mem_read(unit, config_mem, MEM_BLOCK_ALL, index, &entry);
   4773     SOC_EGRESS_METERING_UNLOCK(unit);
   4774     if (rv < 0) {
   4775         return rv;
   4776     }
   4777     meter_flags = 0;
   4778     *flags = 0;
   4779     BCM_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, &rval));
   4780     if (soc_reg_field_get(unit, MISCCONFIGr, rval, ITU_MODE_SELf)) {
   4781         meter_flags |= _BCM_TD_METER_FLAG_NON_LINEAR;
   4782     }
   4783     if (soc_mem_field32_get(unit, config_mem, &entry, SHAPER_CONTROLf)) {
   4784         meter_flags |= _BCM_TD_METER_FLAG_PACKET_MODE;
   4785         *flags |= BCM_COSQ_BW_PACKET_MODE;
   4786     }
   4787 
   4788     granularity = soc_mem_field32_get(unit, config_mem, &entry, MAX_METER_GRANf);
   4789     refresh_rate = soc_mem_field32_get(unit, config_mem, &entry, MAX_REFRESHf);
   4790     bucketsize = soc_mem_field32_get(unit, config_mem, &entry, MAX_THD_SELf);
   4791     BCM_IF_ERROR_RETURN
   4792         (_bcm_td_bucket_encoding_to_rate(unit, refresh_rate, bucketsize,
   4793                                            granularity, meter_flags,
   4794                                            max_quantum, kbits_burst_max));
   4795 
   4796     granularity = soc_mem_field32_get(unit, config_mem, &entry, MIN_METER_GRANf);
   4797     refresh_rate = soc_mem_field32_get(unit, config_mem, &entry, MIN_REFRESHf);
   4798     bucketsize = soc_mem_field32_get(unit, config_mem, &entry, MIN_THD_SELf);
   4799     BCM_IF_ERROR_RETURN
   4800         (_bcm_td_bucket_encoding_to_rate(unit, refresh_rate, bucketsize,
   4801                                            granularity, meter_flags,
   4802                                            min_quantum, kbits_burst_min));
   4803     return BCM_E_NONE;
   4804 }
   4805 
   4806 /*
   4807  * Function:
   4808  *     _bcm_tr3_cosq_wred_set
   4809  * Purpose:
   4810  *     Configure unicast queue WRED setting
   4811  * Parameters:
   4812  *     unit                - (IN) unit number
   4813  *     port                - (IN) port number or GPORT identifier
   4814  *     cosq                - (IN) COS queue number
   4815  *     flags               - (IN) BCM_COSQ_DISCARD_XXX
   4816  *     min_thresh          - (IN)
   4817  *     max_thresh          - (IN)
   4818  *     drop_probablity     - (IN)
   4819  *     gain                - (IN)
   4820  *     ignore_enable_flags - (IN)
   4821  * Returns:
   4822  *     BCM_E_XXX
   4823  * Notes:
   4824  *     If port is any form of local port, cosq is the hardware queue index.
   4825  */
   4826 STATIC int
   4827 _bcm_tr3_cosq_wred_set(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   4828                       uint32 flags, uint32 min_thresh, uint32 max_thresh,
   4829                       int drop_probability, int gain, int ignore_enable_flags,
   4830                       uint32 lflags)
   4831 {
   4832     soc_mem_t wred_mem;
   4833     bcm_port_t local_port;
   4834     int index, to_index;
   4835     uint32 profile_index, old_profile_index;
   4836     mmu_wred_drop_curve_profile_0_entry_t entry_tcp_green;
   4837     mmu_wred_drop_curve_profile_1_entry_t entry_tcp_yellow;
   4838     mmu_wred_drop_curve_profile_2_entry_t entry_tcp_red;
   4839     mmu_wred_drop_curve_profile_3_entry_t entry_nontcp_green;
   4840     mmu_wred_drop_curve_profile_4_entry_t entry_nontcp_yellow;
   4841     mmu_wred_drop_curve_profile_5_entry_t entry_nontcp_red;
   4842     mmu_wred_config_entry_t qentry;
   4843     void *entries[6];
   4844     soc_mem_t mems[6];
   4845     int rate, i, jj, exists = 0;
   4846     static soc_mem_t wred_mems[6] = {
   4847         MMU_WRED_DROP_CURVE_PROFILE_0m, MMU_WRED_DROP_CURVE_PROFILE_1m,
   4848         MMU_WRED_DROP_CURVE_PROFILE_2m, MMU_WRED_DROP_CURVE_PROFILE_3m,
   4849         MMU_WRED_DROP_CURVE_PROFILE_4m, MMU_WRED_DROP_CURVE_PROFILE_5m
   4850     };
   4851 /* For port -1 , set global wred discard profile for all ports  by 
   4852    setting for all global profile indices */
   4853 
   4854     if (((port == -1) && (flags & BCM_COSQ_DISCARD_DEVICE)) || (lflags & BCM_COSQ_DISCARD_DEVICE)) {
   4855         index = 1532;
   4856         to_index = 1535;
   4857     } else {
   4858         if (lflags & BCM_COSQ_DISCARD_PORT) {
   4859             BCM_IF_ERROR_RETURN
   4860                 (_bcm_tr3_cosq_index_resolve(unit, port, cosq,
   4861                                      _BCM_TR3_COSQ_INDEX_STYLE_WRED_PORT,
   4862                                      &local_port, &index, NULL));
   4863         } else {
   4864             BCM_IF_ERROR_RETURN
   4865                 (_bcm_tr3_cosq_index_resolve(unit, port, cosq,
   4866                                      _BCM_TR3_COSQ_INDEX_STYLE_WRED,
   4867                                      &local_port, &index, NULL));
   4868         }
   4869         to_index = index;
   4870     }
   4871 
   4872     wred_mem = MMU_WRED_CONFIGm;
   4873     
   4874     for (jj = index; jj <= to_index; jj++) {
   4875         BCM_IF_ERROR_RETURN
   4876             (soc_mem_read(unit, wred_mem, MEM_BLOCK_ALL, jj, &qentry));
   4877 
   4878         old_profile_index = 0xffffffff;
   4879         if (flags & (BCM_COSQ_DISCARD_NONTCP | BCM_COSQ_DISCARD_COLOR_ALL |
   4880                      BCM_COSQ_DISCARD_TCP)) {
   4881             old_profile_index = soc_mem_field32_get(unit, wred_mem, 
   4882                                                     &qentry, PROFILE_INDEXf);
   4883             entries[0] = &entry_tcp_green;
   4884             entries[1] = &entry_tcp_yellow;
   4885             entries[2] = &entry_tcp_red;
   4886             entries[3] = &entry_nontcp_green;
   4887             entries[4] = &entry_nontcp_yellow;
   4888             entries[5] = &entry_nontcp_red;
   4889             BCM_IF_ERROR_RETURN
   4890                 (soc_profile_mem_get(unit, _bcm_tr3_wred_profile[unit],
   4891                                      old_profile_index, 1, entries));
   4892             for (i = 0; i < 6; i++) {
   4893                 mems[i] = INVALIDm;
   4894             }
   4895             if (!(flags & (BCM_COSQ_DISCARD_COLOR_GREEN |
   4896                            BCM_COSQ_DISCARD_COLOR_YELLOW |
   4897                            BCM_COSQ_DISCARD_COLOR_RED))) {
   4898                 flags |= BCM_COSQ_DISCARD_COLOR_ALL;
   4899             }
   4900             if (!(flags & BCM_COSQ_DISCARD_NONTCP) || (flags & BCM_COSQ_DISCARD_TCP)) {
   4901                 if (flags & BCM_COSQ_DISCARD_COLOR_GREEN) {
   4902                     mems[0] = MMU_WRED_DROP_CURVE_PROFILE_0m;
   4903                 }
   4904                 if (flags & BCM_COSQ_DISCARD_COLOR_YELLOW) {
   4905                     mems[1] = MMU_WRED_DROP_CURVE_PROFILE_1m;
   4906                 }
   4907                 if (flags & BCM_COSQ_DISCARD_COLOR_RED) {
   4908                     mems[2] = MMU_WRED_DROP_CURVE_PROFILE_2m;
   4909                 }
   4910             }
   4911             if (flags & BCM_COSQ_DISCARD_NONTCP) {
   4912                 if (flags & BCM_COSQ_DISCARD_COLOR_GREEN) {
   4913                     mems[3] = MMU_WRED_DROP_CURVE_PROFILE_3m;
   4914                 }
   4915                 if (flags & BCM_COSQ_DISCARD_COLOR_YELLOW) {
   4916                     mems[4] = MMU_WRED_DROP_CURVE_PROFILE_4m;
   4917                 }
   4918                 if (flags & BCM_COSQ_DISCARD_COLOR_RED) {
   4919                     mems[5] = MMU_WRED_DROP_CURVE_PROFILE_5m;
   4920                 }
   4921             }
   4922             rate = _bcm_tr3_percent_to_drop_prob(drop_probability);
   4923             for (i = 0; i < 6; i++) {
   4924                 exists = 0;
   4925                 if ((soc_mem_field32_get(unit, wred_mems[i], entries[i], 
   4926                               MIN_THDf) != 0x7fff) && (mems[i] == INVALIDm)) {
   4927                     mems[i] = wred_mems[i];
   4928                     exists = 1;
   4929                 } else {
   4930                     soc_mem_field32_set(unit, wred_mems[i], entries[i], MIN_THDf,
   4931                                  (mems[i] == INVALIDm) ? 0x7fff : min_thresh);
   4932                 }
   4933 
   4934                 if ((soc_mem_field32_get(unit, wred_mems[i], entries[i], 
   4935                      MAX_THDf) != 0x7fff) && ((mems[i] == INVALIDm) || exists)) {
   4936                     mems[i] = wred_mems[i];
   4937                     exists = 1;
   4938                 } else {
   4939                     soc_mem_field32_set(unit, wred_mems[i], entries[i], MAX_THDf,
   4940                                  (mems[i] == INVALIDm) ? 0x7fff : max_thresh);
   4941                 }
   4942 
   4943                 if (!exists) {
   4944                     soc_mem_field32_set(unit, wred_mems[i], entries[i], MAX_DROP_RATEf,
   4945                                  (mems[i] == INVALIDm) ? 0 : rate);
   4946                 }
   4947             }
   4948 
   4949             BCM_IF_ERROR_RETURN
   4950                 (soc_profile_mem_add(unit, _bcm_tr3_wred_profile[unit], entries, 1,
   4951                                      &profile_index));
   4952             soc_mem_field32_set(unit, wred_mem, &qentry, PROFILE_INDEXf, profile_index);
   4953             soc_mem_field32_set(unit, wred_mem, &qentry, WEIGHTf, gain);
   4954         }
   4955 
   4956         /* Some APIs only modify profiles */
   4957         if (!ignore_enable_flags) {
   4958             soc_mem_field32_set(unit, wred_mem, &qentry, CAP_AVERAGEf,
   4959                               flags & BCM_COSQ_DISCARD_CAP_AVERAGE ? 1 : 0);
   4960             soc_mem_field32_set(unit, wred_mem, &qentry, WRED_ENf,
   4961                               flags & BCM_COSQ_DISCARD_ENABLE ? 1 : 0);
   4962             soc_mem_field32_set(unit, wred_mem, &qentry, ECN_MARKING_ENf,
   4963                               flags & BCM_COSQ_DISCARD_MARK_CONGESTION ?  1 : 0);
   4964         }
   4965         BCM_IF_ERROR_RETURN(
   4966               soc_mem_write(unit, wred_mem, MEM_BLOCK_ALL, jj, &qentry));
   4967 
   4968         if (old_profile_index != 0xffffffff) {
   4969 
   4970             SOC_IF_ERROR_RETURN
   4971                 (soc_profile_mem_delete(unit, _bcm_tr3_wred_profile[unit],
   4972                                         old_profile_index));
   4973         }
   4974     }
   4975 
   4976     return BCM_E_NONE;
   4977 }
   4978 
   4979 /*
   4980  * Function:
   4981  *     _bcm_tr3_cosq_wred_get
   4982  * Purpose:
   4983  *     Get unicast queue WRED setting
   4984  * Parameters:
   4985  *     unit                - (IN) unit number
   4986  *     port                - (IN) port number or GPORT identifier
   4987  *     cosq                - (IN) COS queue number
   4988  *     flags               - (IN/OUT) BCM_COSQ_DISCARD_XXX
   4989  *     min_thresh          - (OUT)
   4990  *     max_thresh          - (OUT)
   4991  *     drop_probablity     - (OUT)
   4992  *     gain                - (OUT)
   4993  * Returns:
   4994  *     BCM_E_XXX
   4995  * Notes:
   4996  *     If port is any form of local port, cosq is the hardware queue index.
   4997  */
   4998 STATIC int
   4999 _bcm_tr3_cosq_wred_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   5000                       uint32 *flags, uint32 *min_thresh, uint32 *max_thresh,
   5001                       int *drop_probability, int *gain, uint32 lflags)
   5002 {
   5003     bcm_port_t local_port;
   5004     int index, profile_index;
   5005     mmu_wred_drop_curve_profile_0_entry_t entry_tcp_green;
   5006     mmu_wred_drop_curve_profile_1_entry_t entry_tcp_yellow;
   5007     mmu_wred_drop_curve_profile_2_entry_t entry_tcp_red;
   5008     mmu_wred_drop_curve_profile_3_entry_t entry_nontcp_green;
   5009     mmu_wred_drop_curve_profile_4_entry_t entry_nontcp_yellow;
   5010     mmu_wred_drop_curve_profile_5_entry_t entry_nontcp_red;
   5011     void *entries[6];
   5012     void *entry_p;
   5013     soc_mem_t mem;
   5014     soc_mem_t wred_mem = 0;
   5015     mmu_wred_config_entry_t qentry;
   5016     int rate;
   5017 
   5018     if ((port == -1) && ((*flags & BCM_COSQ_DISCARD_DEVICE) || 
   5019                 (lflags & BCM_COSQ_DISCARD_DEVICE))) {
   5020         index = 1532;
   5021     } else {
   5022         if (lflags & BCM_COSQ_DISCARD_PORT) {
   5023             BCM_IF_ERROR_RETURN
   5024                 (_bcm_tr3_cosq_index_resolve(unit, port, cosq,
   5025                                      _BCM_TR3_COSQ_INDEX_STYLE_WRED_PORT,
   5026                                      &local_port, &index, NULL));
   5027         } else {
   5028             BCM_IF_ERROR_RETURN
   5029                 (_bcm_tr3_cosq_index_resolve(unit, port, cosq,
   5030                                      _BCM_TR3_COSQ_INDEX_STYLE_WRED,
   5031                                      &local_port, &index, NULL));
   5032         }
   5033     }
   5034 
   5035     wred_mem = MMU_WRED_CONFIGm;
   5036 
   5037     BCM_IF_ERROR_RETURN
   5038         (soc_mem_read(unit, wred_mem, MEM_BLOCK_ALL, index, &qentry));
   5039     profile_index = soc_mem_field32_get(unit, wred_mem,
   5040                                         &qentry, PROFILE_INDEXf);
   5041 
   5042     if (!(*flags & BCM_COSQ_DISCARD_NONTCP)) {
   5043         if (*flags & BCM_COSQ_DISCARD_COLOR_GREEN) {
   5044             mem = MMU_WRED_DROP_CURVE_PROFILE_0m;
   5045             entry_p = &entry_tcp_green;
   5046         } else if (*flags & BCM_COSQ_DISCARD_COLOR_YELLOW) {
   5047             mem = MMU_WRED_DROP_CURVE_PROFILE_1m;
   5048             entry_p = &entry_tcp_yellow;
   5049         } else if (*flags & BCM_COSQ_DISCARD_COLOR_RED) {
   5050             mem = MMU_WRED_DROP_CURVE_PROFILE_2m;
   5051             entry_p = &entry_tcp_red;
   5052         } else {
   5053            mem = MMU_WRED_DROP_CURVE_PROFILE_0m;
   5054            entry_p = &entry_tcp_green;
   5055         }
   5056     } else {
   5057         if (*flags & BCM_COSQ_DISCARD_COLOR_GREEN) {
   5058             mem = MMU_WRED_DROP_CURVE_PROFILE_3m;
   5059             entry_p = &entry_nontcp_green;
   5060         } else if (*flags & BCM_COSQ_DISCARD_COLOR_YELLOW) {
   5061             mem = MMU_WRED_DROP_CURVE_PROFILE_4m;
   5062             entry_p = &entry_nontcp_yellow;
   5063         } else if (*flags & BCM_COSQ_DISCARD_COLOR_RED) {
   5064             mem = MMU_WRED_DROP_CURVE_PROFILE_5m;
   5065             entry_p = &entry_nontcp_red;
   5066         } else {
   5067            mem = MMU_WRED_DROP_CURVE_PROFILE_3m;
   5068            entry_p = &entry_nontcp_green;
   5069         }
   5070     }
   5071 
   5072     entries[0] = &entry_tcp_green;
   5073     entries[1] = &entry_tcp_yellow;
   5074     entries[2] = &entry_tcp_red;
   5075     entries[3] = &entry_nontcp_green;
   5076     entries[4] = &entry_nontcp_yellow;
   5077     entries[5] = &entry_nontcp_red;
   5078     BCM_IF_ERROR_RETURN
   5079         (soc_profile_mem_get(unit, _bcm_tr3_wred_profile[unit],
   5080                              profile_index, 1, entries));
   5081     if (min_thresh != NULL) {
   5082         *min_thresh = soc_mem_field32_get(unit, mem, entry_p, MIN_THDf);
   5083     }
   5084     if (max_thresh != NULL) {
   5085         *max_thresh = soc_mem_field32_get(unit, mem, entry_p, MAX_THDf);
   5086     }
   5087     if (drop_probability != NULL) {
   5088         rate = soc_mem_field32_get(unit, mem, entry_p, MAX_DROP_RATEf);
   5089         *drop_probability = _bcm_tr3_drop_prob_to_percent(rate);
   5090     }
   5091 
   5092     if (gain) {
   5093         *gain = soc_mem_field32_get(unit, wred_mem, &qentry, WEIGHTf);
   5094     }
   5095 
   5096     *flags &= ~(BCM_COSQ_DISCARD_CAP_AVERAGE | BCM_COSQ_DISCARD_ENABLE);
   5097     if (soc_mem_field32_get(unit, wred_mem, &qentry, CAP_AVERAGEf)) {
   5098         *flags |= BCM_COSQ_DISCARD_CAP_AVERAGE;
   5099     }
   5100     if (soc_mem_field32_get(unit, wred_mem, &qentry, WRED_ENf)) {
   5101         *flags |= BCM_COSQ_DISCARD_ENABLE;
   5102     }
   5103     if (soc_mem_field32_get(unit, wred_mem, &qentry, ECN_MARKING_ENf)) {
   5104         *flags |= BCM_COSQ_DISCARD_MARK_CONGESTION;
   5105     }
   5106     return BCM_E_NONE;
   5107 }
   5108     
   5109 STATIC int
   5110 _bcm_tr3_decode_sp_masks(int num_sp, uint32 ucmap, uint32 *umap, int *numuc,
   5111                             uint32 *mmap, int *nummc)
   5112 {
   5113     int i, uindex, mindex;
   5114     uint32 tmp_umap = 0, tmp_mmap = 0;
   5115     
   5116     mindex = uindex = 0;
   5117 
   5118     for (i = 0; i < num_sp; i++) {
   5119         if (ucmap & (1 << i)) {
   5120             /* MC */
   5121             tmp_mmap |= 1 << mindex;
   5122             mindex += 1;
   5123         } else {
   5124             /* UC */
   5125             tmp_umap |= 1 << uindex;
   5126             uindex += 1;
   5127         }
   5128     }
   5129 
   5130     if (numuc) {
   5131         *numuc = uindex;
   5132     }
   5133 
   5134     if (umap) {
   5135         *umap = tmp_umap;
   5136     }
   5137 
   5138     if (mmap) {
   5139         *mmap = tmp_mmap;
   5140     }
   5141 
   5142     if (nummc) {
   5143         *nummc = mindex;
   5144     }
   5145 
   5146     return 0;
   5147 }
   5148 
   5149 STATIC uint32 _bcm_tr3_num_ones(uint32 m)
   5150 {
   5151     uint32 ii = 0;
   5152 
   5153     while (m) {
   5154         m &= m - 1;
   5155         ii +=  1;
   5156     }
   5157     return ii;
   5158 }
   5159 
   5160 
   5161 STATIC int
   5162 _bcm_tr3_compute_lls_config_b0(int unit, int port, int level, 
   5163                                  int *first_sp_child, 
   5164                                  int *first_sp_mc_child,
   5165                                  int *num_spri,
   5166                                  uint32 *ucmap, 
   5167                                  uint32 *spmap, 
   5168                                  int child_index, 
   5169                                  soc_tr3_sched_mode_e cur_mode,
   5170                                  soc_tr3_sched_mode_e mode,
   5171                                  int max_children)
   5172 {
   5173     uint32 ucm = 0, mcm = 0, cur_spmap, cur_num_spri, lucmap = 0;
   5174     int ii, *pfc, uc, mc, fc, oc, *use_fc;
   5175 
   5176     cur_num_spri = _bcm_tr3_num_ones(*spmap);
   5177     cur_spmap = *spmap;
   5178 
   5179     if (level == SOC_TR3_NODE_LVL_L1) {
   5180         if (IS_CPU_PORT(unit, port)) {
   5181             use_fc = first_sp_mc_child;
   5182         } else {
   5183             use_fc = (child_index >= 1024) ? first_sp_mc_child : first_sp_child;
   5184         }
   5185     } else {
   5186         use_fc = first_sp_child;
   5187     }
   5188     
   5189     if (cur_num_spri == 0) {
   5190         *ucmap = 0;
   5191         *spmap = 0;
   5192     }
   5193 
   5194     if (child_index > *use_fc) {
   5195         if (((child_index - *use_fc) > max_children)) {
   5196             return BCM_E_PARAM;
   5197         }
   5198     } else {
   5199         if (((*use_fc + cur_num_spri) - child_index) > max_children) {
   5200             return BCM_E_PARAM;
   5201         }
   5202     }
   5203     
   5204     if (level == SOC_TR3_NODE_LVL_L1) {
   5205         for (mcm = 0, mc = 0, ucm = 0, uc = 0, ii = 0; ii < 8; ii++) {
   5206             if (*ucmap & (1 << ii)) {
   5207                 mcm |= (cur_spmap & (1 << ii)) ? (1 << mc) : 0;
   5208                 mc += 1;
   5209             } else {
   5210                 ucm |= (cur_spmap & (1 << ii)) ? (1 << uc) : 0;
   5211                 uc += 1;
   5212             }
   5213         }
   5214 
   5215         if (child_index < 1024) {
   5216             fc = *first_sp_child;
   5217             oc =  _bcm_tr3_num_ones(ucm);
   5218             BCM_IF_ERROR_RETURN(_bcm_tr3_compute_lls_config_b0(unit, port,
   5219                         level - 1, &fc, NULL, &oc, &lucmap, &ucm, child_index, 
   5220                         cur_mode, mode, 8));
   5221         } else {
   5222             fc = *first_sp_mc_child;
   5223             oc =  _bcm_tr3_num_ones(mcm);
   5224             BCM_IF_ERROR_RETURN(_bcm_tr3_compute_lls_config_b0(unit, port,
   5225                     level - 1, &fc, NULL, &oc, &lucmap, &mcm, 
   5226                     child_index, cur_mode, mode, 8));
   5227         }
   5228 
   5229         cur_spmap = 0;
   5230         *ucmap = 0;
   5231         for (fc = 0, ii = 0; ii < 8; ii++) {
   5232             if (ucm) {
   5233                 cur_spmap |= (ucm & (1 << ii)) ? 1 << fc : 0;
   5234                 fc += 1;
   5235                 ucm &= ~(1 << ii);
   5236             }
   5237             
   5238             if (mcm) {
   5239                 cur_spmap |= (mcm & (1 << ii)) ? 1 << fc : 0;
   5240                 *ucmap |= 1 << fc;
   5241                 fc += 1;
   5242                 mcm &= ~(1 << ii);
   5243             }
   5244 
   5245             if (fc > max_children) {
   5246                 return BCM_E_PARAM;
   5247             }
   5248 
   5249             if ((mcm == 0) && (ucm == 0)) {
   5250                 break;
   5251             }
   5252         }
   5253 
   5254     } else {
   5255         pfc = first_sp_child;
   5256         if (mode == SOC_TR3_SCHED_MODE_STRICT) {
   5257             if (*pfc > child_index) {
   5258                 cur_spmap <<= (*pfc - child_index);
   5259                 cur_spmap |= 1;
   5260                 *pfc = child_index;
   5261                 *num_spri += 1;
   5262             } else {
   5263                 if (((1 << (child_index - *pfc)) & cur_spmap) == 0) {
   5264                     cur_spmap |= 1 << (child_index - *pfc);
   5265                     *num_spri += 1;
   5266                 }
   5267             }
   5268         } else {
   5269             if (1 << (child_index - *pfc) & cur_spmap) {
   5270                 cur_spmap &= ~(1 << (child_index - *pfc));
   5271                 *num_spri -= 1;
   5272             }
   5273         }
   5274     }
   5275 
   5276     *num_spri = _bcm_tr3_num_ones(cur_spmap);
   5277 
   5278     *spmap = cur_spmap;
   5279 
   5280     return BCM_E_NONE;
   5281 }
   5282 
   5283 STATIC int
   5284 _bcm_tr3_compute_lls_config(int unit, int port, int level, 
   5285                                  int *first_sp_child, 
   5286                                  int *first_sp_mc_child,
   5287                                  int *num_spri,
   5288                                  uint32 *ucmap, 
   5289                                  uint32 *spmap, 
   5290                                  int child_index, 
   5291                                  soc_tr3_sched_mode_e cur_mode,
   5292                                  soc_tr3_sched_mode_e mode)
   5293 {
   5294     int cur_first_child;
   5295     int cur_num_spri;
   5296     int cur_ucmap;
   5297     int diff;
   5298     uint32 umap = 0, mmap = 0;
   5299     int  numuc = 0, nummc = 0;
   5300     uint32 pnumn = 0;
   5301 
   5302     if (((cur_mode != SOC_TR3_SCHED_MODE_STRICT) &&
   5303         (mode != SOC_TR3_SCHED_MODE_STRICT)) ||
   5304        ((cur_mode == SOC_TR3_SCHED_MODE_STRICT) && 
   5305         (mode == SOC_TR3_SCHED_MODE_STRICT))) {
   5306         return BCM_E_NONE;
   5307     }
   5308 
   5309     if (soc_feature(unit, soc_feature_tr3_sp_vector_mask)) {
   5310         return _bcm_tr3_compute_lls_config_b0(unit, port, level, first_sp_child,
   5311                                          first_sp_mc_child, num_spri,
   5312                                          ucmap, spmap, child_index,
   5313                                          cur_mode, mode, 8);
   5314     }
   5315 
   5316     cur_num_spri = *num_spri;
   5317     cur_ucmap = *ucmap;
   5318   
   5319     if (level == SOC_TR3_NODE_LVL_L1) {
   5320         _bcm_tr3_decode_sp_masks(cur_num_spri, cur_ucmap, &umap, 
   5321                                             &numuc, &mmap, &nummc);
   5322         if (child_index < 1024) {
   5323             /* UC */
   5324             pnumn = numuc;
   5325             cur_first_child = *first_sp_child;
   5326         } else {
   5327             /* MC */
   5328             pnumn = nummc;
   5329             cur_first_child = *first_sp_mc_child;
   5330         }
   5331     } else {
   5332         pnumn = cur_num_spri;
   5333         cur_first_child = *first_sp_child;
   5334     }
   5335 
   5336     if (cur_mode == SOC_TR3_SCHED_MODE_STRICT) {
   5337         /* this node is not in the middle of SP nodes */
   5338         if (child_index != (cur_first_child + pnumn - 1)) {
   5339             return BCM_E_UNAVAIL;
   5340         }
   5341 
   5342         cur_num_spri -= 1;
   5343         pnumn -= 1;
   5344 
   5345         if (level == SOC_TR3_NODE_LVL_L1) {
   5346             if (child_index < 1024) {
   5347                 *num_spri = pnumn + nummc;
   5348                 *ucmap = 0;
   5349             } else {
   5350                 *num_spri = pnumn + numuc;
   5351                 *ucmap = (1 << (*num_spri)) - 1;
   5352             }
   5353         } else {
   5354             *num_spri = cur_num_spri;
   5355             *ucmap = cur_num_spri ? (1 << cur_num_spri) -1 : 0;
   5356         }
   5357         if (*num_spri == 0) {
   5358             *ucmap = 0;
   5359         }
   5360     } else {
   5361         if (cur_num_spri) {
   5362             /* adding new sp */
   5363             diff = child_index - cur_first_child;
   5364             if (diff != cur_num_spri) {
   5365                 return BCM_E_UNAVAIL;
   5366             }
   5367 
   5368             if (level == SOC_TR3_NODE_LVL_L1) {
   5369                 if (child_index < 1024) {
   5370                     pnumn += 1;
   5371                     *num_spri = pnumn + nummc;
   5372                     *ucmap = 0;
   5373                 } else {
   5374                     pnumn += 1;
   5375                     *num_spri = pnumn + numuc;
   5376                     *ucmap = (1 << (*num_spri)) - 1;
   5377                 }
   5378             } else {
   5379                 pnumn += 1;
   5380                 *num_spri = pnumn;
   5381                 *ucmap = (1 << pnumn) - 1;
   5382             }
   5383         } else {
   5384             /* The node must be the first wrr/wdrr children of the parent if */
   5385             /* the node scheduler change wrr/wdrr to sp on triumph3 A0&A1.   */
   5386             if (child_index != cur_first_child) {
   5387                 return BCM_E_UNAVAIL;
   5388             }
   5389             *num_spri = 1;
   5390             if (child_index < 1024) {
   5391                 *ucmap = 0;
   5392             } else {
   5393                 *ucmap = 1;
   5394                 
   5395             }
   5396             
   5397         }
   5398     }
   5399     return BCM_E_NONE;
   5400 }
   5401 
   5402 STATIC int
   5403 _bcm_tr3_cosq_dyn_move_queue(int unit, bcm_port_t local_port, 
   5404                              int cosq, int *l2_index, int numl2,
   5405                              int from_sched_idx, int to_sched_index)
   5406 {
   5407     lls_l2_parent_entry_t l2p[2];
   5408     mmu_mtro_l2_mem_entry_t mtro[2], tmp_mtro;
   5409     mmu_mtro_l1_mem_entry_t l1mtro, l1mtro_tmp;
   5410     lls_l2_child_state1_entry_t l2cse;
   5411     lls_l1_parent_state_entry_t l1pe_old;
   5412     int ii, empty_count, actives[2], sync;
   5413     uint32 rval;
   5414     int rv = BCM_E_NONE;
   5415     soc_timeout_t timeout;
   5416     uint32 timeout_val;
   5417     int rcnt = 0;
   5418 
   5419     timeout_val = soc_property_get(unit, spn_MMU_QUEUE_FLUSH_TIMEOUT, 2000000);
   5420 
   5421     for (ii = 0; ii < numl2; ii++) {
   5422         SOC_IF_ERROR_RETURN(READ_MMU_MTRO_L2_MEMm(unit, MEM_BLOCK_ANY,
   5423                                                   l2_index[ii], &mtro[ii]));
   5424         /* configure max shaper */
   5425         /* coverity[suspicious_sizeof:FALSE] */
   5426         sal_memset(&tmp_mtro, 0, sizeof(mmu_mtro_l2_mem_entry_t));
   5427         soc_mem_field32_set(unit, MMU_MTRO_L2_MEMm, &tmp_mtro, MAX_METER_GRANf, 0);
   5428         soc_mem_field32_set(unit, MMU_MTRO_L2_MEMm, &tmp_mtro, MAX_THD_SELf, 1);
   5429         soc_mem_field32_set(unit, MMU_MTRO_L2_MEMm, &tmp_mtro, MAX_REFRESHf, 0);
   5430         SOC_IF_ERROR_RETURN(WRITE_MMU_MTRO_L2_MEMm(unit, MEM_BLOCK_ANY,
   5431                                                     l2_index[ii], &tmp_mtro));
   5432         /* cache the L2 parent mem. */
   5433         SOC_IF_ERROR_RETURN(READ_LLS_L2_PARENTm(unit, MEM_BLOCK_ANY,
   5434                                                 l2_index[ii], &l2p[ii]));
   5435         soc_mem_field32_set(unit, LLS_L2_PARENTm, &l2p[ii], C_PARENTf, to_sched_index);
   5436     }
   5437 
   5438     /* give l1 a small min guarantee */
   5439     SOC_IF_ERROR_RETURN(READ_MMU_MTRO_L1_MEMm(unit, MEM_BLOCK_ANY, 
   5440                                               from_sched_idx, &l1mtro));
   5441     sal_memset(&l1mtro_tmp, 0, sizeof(sizeof(mmu_mtro_l1_mem_entry_t)));
   5442     soc_mem_field32_set(unit, MMU_MTRO_L1_MEMm, &l1mtro_tmp, MIN_METER_GRANf, 3);
   5443     soc_mem_field32_set(unit, MMU_MTRO_L1_MEMm, &l1mtro_tmp, MIN_THD_SELf, 64);
   5444     soc_mem_field32_set(unit, MMU_MTRO_L1_MEMm, &l1mtro_tmp, MIN_REFRESHf, 15625);
   5445     SOC_IF_ERROR_RETURN(WRITE_MMU_MTRO_L1_MEMm(unit, MEM_BLOCK_ANY,
   5446                                                     from_sched_idx, &l1mtro_tmp));
   5447     
   5448     soc_timeout_init(&timeout, timeout_val, 0);
   5449 
   5450     do {
   5451         empty_count = 0;
   5452         if (soc_timeout_check(&timeout)) {
   5453             LOG_ERROR(BSL_LS_BCM_COMMON,
   5454                       (BSL_META_U(unit,
   5455                                   "ERROR: timeout on L2 child c_on_active_list not zero (read count=%d)\n"),
   5456                        rcnt));
   5457             rv = BCM_E_BUSY;
   5458             goto failed;
   5459         }
   5460         for (empty_count = 0, ii = 0; ii < numl2; ii++) {
   5461             rcnt += 1;
   5462             SOC_IF_ERROR_RETURN(READ_LLS_L2_CHILD_STATE1m(unit, 
   5463                                     MEM_BLOCK_ANY, l2_index[ii], &l2cse));
   5464             if (soc_mem_field32_get(unit, LLS_L2_CHILD_STATE1m, &l2cse, 
   5465                                    C_ON_ACTIVE_LISTf)==0) {
   5466                 empty_count += 1;
   5467             } else {
   5468                 break;
   5469             }
   5470         }
   5471     } while (empty_count != numl2);
   5472 
   5473     /* change the parent */
   5474     for (ii = 0; ii < numl2; ii++) {
   5475         SOC_IF_ERROR_RETURN(
   5476           WRITE_LLS_L2_PARENTm(unit, MEM_BLOCK_ANY, l2_index[ii], &l2p[ii]));
   5477     }
   5478 
   5479     for (empty_count = 0, ii = 0; ii < numl2; ii++) {
   5480         SOC_IF_ERROR_RETURN(READ_LLS_L2_CHILD_STATE1m(unit, 
   5481                                 MEM_BLOCK_ANY, l2_index[ii], &l2cse));
   5482         actives[ii] = 0;
   5483         if (soc_mem_field32_get(unit, LLS_L2_CHILD_STATE1m, &l2cse, 
   5484                                C_ON_ACTIVE_LISTf)==0) {
   5485             empty_count += 1;
   5486         } else {
   5487             actives[ii] = 1;
   5488         }
   5489     }
   5490 
   5491     sync = 0;
   5492     if (empty_count != numl2) {
   5493         for (ii = 0; ii < numl2; ii++) {
   5494             if (actives[ii] == 0) {
   5495                 continue;
   5496             }
   5497             SOC_IF_ERROR_RETURN(READ_LLS_L1_PARENT_STATEm(unit, 
   5498                                 MEM_BLOCK_ANY, from_sched_idx, &l1pe_old));
   5499             if ((soc_mem_field32_get(unit, LLS_L1_PARENT_STATEm, &l1pe_old, 
   5500                                    P_WRR_0_NOT_EMPTYf)) ||
   5501                 (soc_mem_field32_get(unit, LLS_L1_PARENT_STATEm, &l1pe_old, 
   5502                                    P_WRR_1_NOT_EMPTYf))) {
   5503                 sync = 1;
   5504             }
   5505         }
   5506     }
   5507 
   5508     if (sync) {
   5509         empty_count = 0;
   5510         soc_timeout_init(&timeout, timeout_val, 0);
   5511         while (empty_count != numl2) {
   5512             if (soc_timeout_check(&timeout)) {
   5513                 rv = BCM_E_BUSY;
   5514                 break;
   5515             }
   5516             for (empty_count = 0, ii = 0; ii < numl2; ii++) {
   5517                 SOC_IF_ERROR_RETURN(READ_LLS_L2_CHILD_STATE1m(unit, 
   5518                                         MEM_BLOCK_ANY, l2_index[ii], &l2cse));
   5519                 if (soc_mem_field32_get(unit, LLS_L2_CHILD_STATE1m, &l2cse, 
   5520                                        C_ON_ACTIVE_LISTf)==0) {
   5521                     empty_count += 1;
   5522                 } else {
   5523                     break;
   5524                 }
   5525             }
   5526         }
   5527     }
   5528 
   5529 failed:
   5530     for (ii = 0; ii < numl2; ii++) {
   5531         SOC_IF_ERROR_RETURN(WRITE_MMU_MTRO_L2_MEMm(unit, MEM_BLOCK_ANY,
   5532                                                   l2_index[ii], &mtro[ii]));
   5533     }
   5534 
   5535     if (!rv) {
   5536         for (ii = 0; ii < numl2; ii++) {
   5537             rval = 0;
   5538             soc_reg_field_set(unit, LLS_DEBUG_INJECT_ACTIVATIONr, &rval, INJECTf, 1);
   5539             soc_reg_field_set(unit, LLS_DEBUG_INJECT_ACTIVATIONr, &rval, ENTITY_TYPEf, 1);
   5540             soc_reg_field_set(unit, LLS_DEBUG_INJECT_ACTIVATIONr, &rval, ENTITY_LEVELf, 3);
   5541             soc_reg_field_set(unit, LLS_DEBUG_INJECT_ACTIVATIONr, &rval, 
   5542                               ENTITY_IDENTIFIERf, l2_index[ii]);
   5543             SOC_IF_ERROR_RETURN(WRITE_LLS_DEBUG_INJECT_ACTIVATIONr(unit, rval));
   5544         }
   5545     }
   5546 
   5547     SOC_IF_ERROR_RETURN(WRITE_MMU_MTRO_L1_MEMm(unit, MEM_BLOCK_ANY, 
   5548                                               from_sched_idx, &l1mtro));
   5549     return rv;
   5550 }
   5551 
   5552 typedef struct _bcm_tr3_lls_info_s {
   5553     int child_lvl;
   5554     int child_hw_index;
   5555     int node_count[SOC_TR3_NODE_LVL_MAX];
   5556     int count[SOC_TR3_NODE_LVL_MAX];
   5557     int offset[SOC_TR3_NODE_LVL_MAX];
   5558    
   5559     int kbit_max;
   5560     int kbit_min;
   5561 
   5562     uint32  *mtro_entries;
   5563 } _bcm_tr3_lls_info_t;
   5564 
   5565 STATIC int _bcm_tr3_lls_node_count(int unit, int port, int level, 
   5566                                    int hw_index, void *cookie)
   5567 {
   5568     _bcm_tr3_lls_info_t *i_lls_tree = (_bcm_tr3_lls_info_t *) cookie;
   5569     i_lls_tree->node_count[level] += 1;
   5570     return 0;
   5571 }
   5572 
   5573 STATIC int _bcm_tr3_lls_shapers_remove(int unit, int port, int level, 
   5574                                        int hw_index, void *cookie)
   5575 {
   5576     _bcm_tr3_lls_info_t *i_lls_tree = (_bcm_tr3_lls_info_t *) cookie;
   5577     soc_mem_t config_mem;
   5578     uint32  *p_entry;
   5579     uint32 entry[SOC_MAX_MEM_WORDS];
   5580     int index, kbit_max;
   5581     uint32 meter_flags;
   5582     uint32 bucketsize_max, granularity_max, refresh_rate_max,
   5583            refresh_bitsize = 0, bucket_bitsize = 0;
   5584 
   5585     if (level == SOC_TR3_NODE_LVL_ROOT) {
   5586         return SOC_E_NONE;
   5587     } else if (level == SOC_TR3_NODE_LVL_L0) {
   5588         config_mem = MMU_MTRO_L0_MEMm;
   5589     } else if (level == SOC_TR3_NODE_LVL_L1) {
   5590         config_mem = MMU_MTRO_L1_MEMm;
   5591     } else if (level == SOC_TR3_NODE_LVL_L2) {
   5592         config_mem = MMU_MTRO_L2_MEMm;
   5593     } else {
   5594         return SOC_E_PARAM;
   5595     }
   5596 
   5597     index = i_lls_tree->offset[level] + i_lls_tree->count[level];
   5598     p_entry = &i_lls_tree->mtro_entries[index * SOC_MAX_MEM_WORDS];
   5599 
   5600     SOC_IF_ERROR_RETURN(soc_mem_read(unit, config_mem, MEM_BLOCK_ALL, hw_index, 
   5601                                      p_entry));
   5602     
   5603     sal_memset(entry, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS);
   5604 
   5605     if ((i_lls_tree->child_lvl == level) && 
   5606             (hw_index != i_lls_tree->child_hw_index)) {
   5607         
   5608         meter_flags = 0;
   5609 
   5610         kbit_max = i_lls_tree->kbit_max;
   5611         refresh_bitsize = soc_mem_field_length(unit, config_mem, MAX_REFRESHf);
   5612         bucket_bitsize = soc_mem_field_length(unit, config_mem, MAX_THD_SELf);
   5613 
   5614         BCM_IF_ERROR_RETURN
   5615             (_bcm_td_rate_to_bucket_encoding(unit, kbit_max, kbit_max,
   5616                                              meter_flags, refresh_bitsize,
   5617                                              bucket_bitsize, &refresh_rate_max,
   5618                                              &bucketsize_max, &granularity_max));
   5619 
   5620         sal_memset(entry, 0, sizeof(uint32)*SOC_MAX_MEM_WORDS);
   5621         soc_mem_field32_set(unit, config_mem, &entry, MAX_METER_GRANf, granularity_max);
   5622         soc_mem_field32_set(unit, config_mem, &entry, MAX_REFRESHf, refresh_rate_max);
   5623         soc_mem_field32_set(unit, config_mem, &entry, MAX_THD_SELf, bucketsize_max);
   5624 
   5625         BCM_IF_ERROR_RETURN
   5626             (soc_mem_write(unit, config_mem, MEM_BLOCK_ALL, hw_index, &entry));
   5627     
   5628     } else {
   5629         SOC_IF_ERROR_RETURN(soc_mem_write(unit, config_mem, MEM_BLOCK_ALL, 
   5630                                                     hw_index, &entry));
   5631     }
   5632 
   5633     i_lls_tree->count[level] += 1;
   5634 
   5635     return 0;
   5636 }
   5637 
   5638 STATIC int _bcm_tr3_lls_shapers_restore(int unit, int port, int level, 
   5639                                         int hw_index, void *cookie)
   5640 {
   5641     _bcm_tr3_lls_info_t *i_lls_tree = (_bcm_tr3_lls_info_t *) cookie;
   5642     soc_mem_t config_mem;
   5643     uint32  *p_entry;
   5644     int index;
   5645 
   5646     if (level == SOC_TR3_NODE_LVL_ROOT) {
   5647         return SOC_E_NONE;
   5648     } else if (level == SOC_TR3_NODE_LVL_L0) {
   5649         config_mem = MMU_MTRO_L0_MEMm;
   5650     } else if (level == SOC_TR3_NODE_LVL_L1) {
   5651         config_mem = MMU_MTRO_L1_MEMm;
   5652     } else if (level == SOC_TR3_NODE_LVL_L2) {
   5653         config_mem = MMU_MTRO_L2_MEMm;
   5654     } else {
   5655         return SOC_E_PARAM;
   5656     }
   5657 
   5658     index = i_lls_tree->offset[level] + i_lls_tree->count[level];
   5659     p_entry = &i_lls_tree->mtro_entries[index * SOC_MAX_MEM_WORDS];
   5660 
   5661     SOC_IF_ERROR_RETURN(soc_mem_write(unit, config_mem, MEM_BLOCK_ALL, 
   5662                                                     hw_index, p_entry));
   5663 
   5664     i_lls_tree->count[level] += 1;
   5665 
   5666     return 0;
   5667 }
   5668 
   5669 STATIC int
   5670 _bcm_tr3_adjust_lls_bw(int unit, bcm_port_t port, _bcm_tr3_cosq_node_t *node, 
   5671                        int child_lvl, int child_hw_index, int start, 
   5672                        _bcm_tr3_lls_info_t *i_lls_tree)
   5673 {
   5674     int rv = BCM_E_NONE, count, mem_size, ii, speed, jj;
   5675     soc_info_t *si;
   5676     
   5677     if (!soc_feature(unit, soc_feature_tr3_sp_vector_mask)) {
   5678         return BCM_E_NONE;
   5679     }
   5680     
   5681     if (start) {
   5682         sal_memset(i_lls_tree, 0, sizeof(_bcm_tr3_lls_info_t));
   5683 
   5684         i_lls_tree->child_lvl = child_lvl;
   5685         i_lls_tree->child_hw_index = child_hw_index;
   5686 
   5687         if (node) {
   5688 
   5689             /* get to top node */
   5690             while(node->parent) { node = node->parent; }
   5691 
   5692             if ((rv = _bcm_tr3_cosq_traverse_lls_tree(unit, port, node, 
   5693                                     _bcm_tr3_lls_node_count, i_lls_tree))) {
   5694                 goto error;
   5695             }
   5696         } else {
   5697             if ((rv = soc_tr3_port_lls_traverse(unit, port, 
   5698                                     _bcm_tr3_lls_node_count, i_lls_tree))) {
   5699                 goto error;
   5700             }
   5701         }
   5702 
   5703         for (count = 0, ii = 0; ii < SOC_TR3_NODE_LVL_MAX; ii++) {
   5704             count += i_lls_tree->node_count[ii];
   5705             for (jj = ii - 1; jj >= 0; jj--) {
   5706                 i_lls_tree->offset[ii] += i_lls_tree->node_count[jj];
   5707             }
   5708         }
   5709         
   5710         if (count == 0) {
   5711             return BCM_E_INIT;
   5712         }
   5713         
   5714         mem_size = sizeof(uint32)*SOC_MAX_MEM_WORDS*count;
   5715         i_lls_tree->mtro_entries = sal_alloc(mem_size, "lls_war_buf");
   5716 
   5717         rv = soc_phyctrl_speed_get(unit, port, &speed);
   5718         if (rv == BCM_E_UNAVAIL) {
   5719             si = &SOC_INFO(unit);
   5720             speed = si->port_speed_max[port];
   5721         }
   5722 
   5723         i_lls_tree->kbit_min = 0;
   5724         i_lls_tree->kbit_max = ((speed * 9)/10)/i_lls_tree->node_count[child_lvl];
   5725 
   5726         for (count = 0, ii = 0; ii < SOC_TR3_NODE_LVL_MAX; ii++) {
   5727             i_lls_tree->count[ii] = 0;
   5728         }
   5729 
   5730         sal_memset(i_lls_tree->mtro_entries, 0, mem_size);
   5731 
   5732         if (node) {
   5733 
   5734             /* get to top node */
   5735             while(node->parent) { node = node->parent; }
   5736 
   5737             if ((rv = _bcm_tr3_cosq_traverse_lls_tree(unit, port, node, 
   5738                                     _bcm_tr3_lls_shapers_remove, i_lls_tree))) {
   5739                 goto error;
   5740             }
   5741         } else {
   5742             if ((rv = soc_tr3_port_lls_traverse(unit, port, 
   5743                                     _bcm_tr3_lls_shapers_remove, i_lls_tree))) {
   5744                 goto error;
   5745             }
   5746         }
   5747 
   5748     } else {
   5749         for (count = 0, ii = 0; ii < SOC_TR3_NODE_LVL_MAX; ii++) {
   5750             i_lls_tree->count[ii] = 0;
   5751         }
   5752 
   5753         if (node) {
   5754             /* get to top node */
   5755             while(node->parent) { node = node->parent; }
   5756 
   5757             if ((rv = _bcm_tr3_cosq_traverse_lls_tree(unit, port, node, 
   5758                                     _bcm_tr3_lls_shapers_restore, i_lls_tree))) {
   5759                 goto error;
   5760             }
   5761         } else {
   5762             if ((rv = soc_tr3_port_lls_traverse(unit, port, 
   5763                                     _bcm_tr3_lls_shapers_restore, i_lls_tree))) {
   5764                 goto error;
   5765             }
   5766         }
   5767 
   5768         /* cleanup */
   5769         if (i_lls_tree->mtro_entries) {
   5770             sal_free(i_lls_tree->mtro_entries);
   5771             i_lls_tree->mtro_entries = NULL;
   5772         }
   5773     }
   5774 
   5775     return BCM_E_NONE;
   5776 
   5777 error:
   5778     /* cleanup */
   5779     if (i_lls_tree->mtro_entries) {
   5780         sal_free(i_lls_tree->mtro_entries);
   5781         i_lls_tree->mtro_entries = NULL;
   5782     }
   5783 
   5784     return rv;
   5785 }
   5786 
   5787 STATIC int
   5788 _bcm_tr3_cosq_sched_parent_child_set(int unit, int port, int level,
   5789                                      int sched_index, int child_index,
   5790                                      soc_tr3_sched_mode_e sched_mode, 
   5791                                      int weight)
   5792 {
   5793     int wt, rv = BCM_E_NONE, num_spri, first_sp_child, first_sp_mc_child;
   5794     uint32 ucmap = 0, spmap = 0, mmu_cells = 0, rval;
   5795     soc_tr3_sched_mode_e cur_sched_mode;
   5796     _bcm_tr3_lls_info_t lls_tree_info;
   5797 
   5798     SOC_IF_ERROR_RETURN(READ_OP_PORT_TOTAL_COUNT_CELLr(unit, port, &rval));
   5799     mmu_cells = soc_reg_field_get(unit, OP_PORT_TOTAL_COUNT_CELLr, rval,
   5800                                    TOTAL_COUNTf);
   5801     BCM_IF_ERROR_RETURN(soc_tr3_cosq_get_sched_config(unit, 
   5802                                                       port, 
   5803                                                       level,
   5804                                                       sched_index, 
   5805                                                       child_index,
   5806                                                       &num_spri,
   5807                                                       &first_sp_child,
   5808                                                       &first_sp_mc_child,
   5809                                                       &ucmap,
   5810                                                       &spmap,
   5811                                                       &cur_sched_mode,
   5812                                                       &wt));
   5813 
   5814     if (_bcm_tr3_compute_lls_config(unit, port,
   5815                                    level, 
   5816                                    &first_sp_child, 
   5817                                    &first_sp_mc_child, 
   5818                                    &num_spri, 
   5819                                    &ucmap, 
   5820                                    &spmap,
   5821                                    child_index, 
   5822                                    cur_sched_mode, 
   5823                                    sched_mode)) {
   5824         return BCM_E_UNAVAIL;
   5825     }
   5826     if (mmu_cells) {
   5827         SOC_EGRESS_METERING_LOCK(unit);
   5828         if ((rv = _bcm_tr3_adjust_lls_bw(unit, port, NULL,
   5829                        level + 1, child_index, 1, &lls_tree_info))) {
   5830             SOC_EGRESS_METERING_UNLOCK(unit);
   5831             goto error;
   5832         }
   5833         SOC_EGRESS_METERING_UNLOCK(unit);
   5834     }
   5835     if ((rv = soc_tr3_cosq_set_sched_config(unit, port, level,
   5836                        sched_index, child_index, num_spri, first_sp_child,
   5837                        first_sp_mc_child, ucmap, spmap, sched_mode, weight))) {
   5838         goto error;
   5839     }
   5840 
   5841 error:
   5842     if (mmu_cells) {
   5843         SOC_EGRESS_METERING_LOCK(unit);
   5844         rv = _bcm_tr3_adjust_lls_bw(unit, port, NULL,
   5845                     level + 1, child_index, 0, &lls_tree_info);
   5846         SOC_EGRESS_METERING_UNLOCK(unit);
   5847     }
   5848     return rv;
   5849 }
   5850 
   5851 /*
   5852  * Function:
   5853  *     _bcm_tr3_cosq_sched_set
   5854  * Purpose:
   5855  *     Set scheduling mode
   5856  * Parameters:
   5857  *     unit                - (IN) unit number
   5858  *     port                - (IN) port number or GPORT identifier
   5859  *     cosq                - (IN) COS queue number
   5860  *     mode                - (IN) scheduling mode (BCM_COSQ_XXX)
   5861  *     num_weights         - (IN) number of entries in weights array
   5862  *     weights             - (IN) weights array
   5863  * Returns:
   5864  *     BCM_E_XXX
   5865  */
   5866 STATIC int
   5867 _bcm_tr3_cosq_sched_set(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   5868                        int mode, int weight, int adjust_cos)
   5869 {
   5870     _bcm_tr3_cosq_node_t *node = NULL, *child_node;
   5871     bcm_port_t local_port;
   5872     int sch_index, lvl = SOC_TR3_NODE_LVL_L0, child_index;
   5873     /* , root_index; */
   5874     int numq, lwts = 1, to_sched_index, cpu_l0_index, cpu_l1_index;
   5875     soc_tr3_sched_mode_e sched_mode;
   5876     int l2_index[2], l1_base, l0_base, ii, rv, lvl_off;
   5877     uint32 entry[SOC_MAX_MEM_WORDS];
   5878     mmu_mtro_l1_mem_entry_t l1mtro[16], l1mtro_tmp;
   5879     mmu_mtro_l1_mem_entry_t l0mtro;
   5880     uint64 egrm, tmp64;
   5881     
   5882     if (cosq < 0) {
   5883         if (cosq == -1) {
   5884             /* caller needs to resolve the wild card value (-1) */
   5885             return BCM_E_INTERNAL;
   5886         } else { /* reject all other negative value */
   5887             return BCM_E_PARAM;
   5888         }
   5889     }
   5890 
   5891     if ((weight < 0) || (weight > 127)) {
   5892         return BCM_E_PARAM;
   5893     }
   5894 
   5895     switch(mode) {
   5896         case BCM_COSQ_STRICT:
   5897             sched_mode = SOC_TR3_SCHED_MODE_STRICT;
   5898         break;
   5899         case BCM_COSQ_ROUND_ROBIN:
   5900             sched_mode = SOC_TR3_SCHED_MODE_WRR;
   5901             lwts = 1;
   5902         break;
   5903         case BCM_COSQ_WEIGHTED_ROUND_ROBIN:
   5904             if (soc_property_get(unit, spn_BCM5664X_WRR_GRANULARITY_1, 0)) {
   5905                 if (weight == 1) {
   5906                     return BCM_E_PARAM;
   5907                 }
   5908             } else if (weight > 63) {
   5909                 return BCM_E_PARAM;
   5910             }
   5911             sched_mode = SOC_TR3_SCHED_MODE_WRR;
   5912             lwts = weight;
   5913         break;
   5914         case BCM_COSQ_DEFICIT_ROUND_ROBIN:
   5915             sched_mode = SOC_TR3_SCHED_MODE_WDRR;
   5916             lwts = weight;
   5917         break;
   5918         default:
   5919             return BCM_E_PARAM;
   5920     }
   5921 
   5922     if (lwts == 0) {
   5923         /* On weight 0 it should be considered as SP */ 
   5924         sched_mode = SOC_TR3_SCHED_MODE_STRICT;
   5925     }
   5926 
   5927     BCM_IF_ERROR_RETURN
   5928             (_bcm_tr3_cosq_localport_resolve(unit, port, &local_port));
   5929 
   5930     if (IS_TR3_HSP_PORT(unit, local_port)) {
   5931         /* If port is set as gport get the node and configure sched */
   5932         if (BCM_GPORT_IS_SET(port)) {
   5933  
   5934             BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_node_get(unit, port,
   5935                                                        0, NULL, &local_port, NULL, &node));
   5936             lvl = node->level;
   5937             if (lvl >= SOC_TR3_NODE_LVL_L1) {
   5938                 return BCM_E_PARAM;
   5939             }
   5940             if (lvl == SOC_TR3_NODE_LVL_L0) {
   5941                 BCM_IF_ERROR_RETURN(
   5942                     _soc_tr3_hsp_sched_weight_set(unit, local_port, 
   5943                                                   node->attached_to_input, cosq, lwts));
   5944                 BCM_IF_ERROR_RETURN(
   5945                     _soc_tr3_hsp_set_sched_config(unit, local_port, 
   5946                                                   node->attached_to_input, cosq, sched_mode));
   5947             } else {
   5948                 if (cosq >= _TR3_NUM_HSP_COSQ) {
   5949                     return BCM_E_PARAM;
   5950                 }
   5951                 BCM_IF_ERROR_RETURN(
   5952                     soc_tr3_hsp_sched_weight_set(unit, local_port, cosq, lwts, adjust_cos));
   5953                 BCM_IF_ERROR_RETURN(
   5954                     soc_tr3_hsp_set_sched_config(unit, local_port, cosq, sched_mode, adjust_cos));
   5955             }
   5956         } else {
   5957             if (cosq >= _TR3_NUM_HSP_COSQ) {
   5958                     return BCM_E_PARAM;
   5959             }
   5960             BCM_IF_ERROR_RETURN(
   5961                 soc_tr3_hsp_sched_weight_set(unit, local_port, cosq, lwts, adjust_cos));
   5962             BCM_IF_ERROR_RETURN(
   5963                 soc_tr3_hsp_set_sched_config(unit, local_port, cosq, sched_mode, adjust_cos));
   5964         } 
   5965         return BCM_E_NONE;
   5966     }
   5967 
   5968     if (_bcm_tr3_cosq_port_has_ets(unit, local_port)) {
   5969         BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_node_get(unit, port, 
   5970                                     0, NULL, &local_port, NULL, &node));
   5971         lvl = node->level;
   5972         numq = node->numq;
   5973         sch_index = node->hw_index;
   5974 
   5975         if ((node->numq > 0) && (cosq >= node->numq)) {
   5976             return BCM_E_PARAM;
   5977         }
   5978 
   5979         BCM_IF_ERROR_RETURN(
   5980             _bcm_tr3_cosq_child_node_at_input(node, cosq, &child_node));
   5981         child_index = child_node->hw_index;
   5982 
   5983         BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_sched_parent_child_set(unit, 
   5984                             local_port, node->level, node->hw_index, 
   5985                             child_node->hw_index, sched_mode, lwts));
   5986     } else {
   5987         numq = IS_CPU_PORT(unit, local_port) ? 
   5988                         SOC_INFO(unit).num_cpu_cosq : _TR3_NUM_COS(unit);
   5989 
   5990         if (cosq >= numq) {
   5991             return BCM_E_PARAM;
   5992         }
   5993 
   5994         if (!IS_CPU_PORT(unit, local_port) &&
   5995             (!soc_feature(unit, soc_feature_tr3_sp_vector_mask) &&
   5996              soc_property_port_get(unit, local_port, spn_PORT_SCHED_DYNAMIC, 0))) {
   5997 
   5998             BCM_IF_ERROR_RETURN(
   5999                 _bcm_tr3_cosq_index_resolve(unit, local_port, cosq,
   6000                    _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE, NULL, &l2_index[0], NULL));
   6001 
   6002             BCM_IF_ERROR_RETURN(
   6003                 _bcm_tr3_cosq_index_resolve(unit, local_port, cosq,
   6004                    _BCM_TR3_COSQ_INDEX_STYLE_MCAST_QUEUE, NULL, &l2_index[1], NULL));
   6005 
   6006             BCM_IF_ERROR_RETURN(soc_tr3_sched_hw_index_get(unit, local_port, 
   6007                                                            SOC_TR3_NODE_LVL_L1, 
   6008                                                            cosq, &to_sched_index));
   6009 
   6010             if (sched_mode == SOC_TR3_SCHED_MODE_STRICT) {
   6011                 to_sched_index += soc_port_hg_capable(unit, local_port) ? 9 : 8;
   6012             }
   6013 
   6014             /* current parent */
   6015             SOC_IF_ERROR_RETURN(READ_LLS_L2_PARENTm(unit, MEM_BLOCK_ANY,
   6016                                                         l2_index[0], entry));
   6017             sch_index = soc_mem_field32_get(unit, LLS_L2_PARENTm, entry, C_PARENTf);
   6018 
   6019             if (sch_index != to_sched_index) { 
   6020                 SOC_IF_ERROR_RETURN(READ_EGRMETERINGCONFIG_64r(unit, local_port, &egrm));
   6021                 COMPILER_64_ZERO(tmp64);
   6022                 SOC_IF_ERROR_RETURN(WRITE_EGRMETERINGCONFIG_64r(unit, local_port, tmp64));
   6023                 sal_memset(&l1mtro_tmp, 0, sizeof(l1mtro_tmp)); 
   6024                 BCM_IF_ERROR_RETURN(soc_tr3_sched_hw_index_get(unit, local_port, 
   6025                                                            SOC_TR3_NODE_LVL_L0, 
   6026                                                            0, &l0_base));
   6027                 SOC_EGRESS_METERING_LOCK(unit);
   6028                 rv = READ_MMU_MTRO_L0_MEMm(unit, MEM_BLOCK_ANY,
   6029                                            l0_base, &l0mtro);
   6030                 if (BCM_FAILURE(rv)) {
   6031                     SOC_EGRESS_METERING_UNLOCK(unit);
   6032                     return rv;
   6033                 }
   6034                 rv = WRITE_MMU_MTRO_L0_MEMm(unit, MEM_BLOCK_ANY,
   6035                                             l0_base, &l1mtro_tmp);
   6036                 if (BCM_FAILURE(rv)) {
   6037                     SOC_EGRESS_METERING_UNLOCK(unit);
   6038                     return rv;
   6039                 }
   6040                 SOC_EGRESS_METERING_UNLOCK(unit);
   6041 
   6042                 BCM_IF_ERROR_RETURN(soc_tr3_sched_hw_index_get(unit, local_port, 
   6043                                                            SOC_TR3_NODE_LVL_L1, 
   6044                                                            0, &l1_base));
   6045                 for (ii = 0; ii < 16; ii++) {
   6046                      SOC_EGRESS_METERING_LOCK(unit);
   6047                      rv = READ_MMU_MTRO_L1_MEMm(unit, MEM_BLOCK_ANY,
   6048                                                 l1_base + ii, &l1mtro[ii]);
   6049                      if (BCM_FAILURE(rv)) {
   6050                          SOC_EGRESS_METERING_UNLOCK(unit);
   6051                          return rv;
   6052                      }
   6053                      rv = WRITE_MMU_MTRO_L1_MEMm(unit, MEM_BLOCK_ANY, l1_base + ii,
   6054                                                  &l1mtro_tmp);
   6055                      if (BCM_FAILURE(rv)) {
   6056                          SOC_EGRESS_METERING_UNLOCK(unit);
   6057                          return rv;
   6058                      }
   6059                      SOC_EGRESS_METERING_UNLOCK(unit);
   6060                 }
   6061                 SOC_EGRESS_METERING_LOCK(unit); 
   6062                 rv = _bcm_tr3_cosq_dyn_move_queue(unit, local_port, cosq, 
   6063                                                   l2_index, 2, sch_index, to_sched_index);
   6064                 SOC_EGRESS_METERING_UNLOCK(unit);
   6065                 /* restore l1 mtros */
   6066                 for (ii = 0; ii < 16; ii++) {
   6067                     SOC_IF_ERROR_RETURN(WRITE_MMU_MTRO_L1_MEMm(unit, MEM_BLOCK_ANY, l1_base + ii,
   6068                                                                 &l1mtro[ii]));
   6069                 }
   6070                     
   6071                 SOC_IF_ERROR_RETURN(WRITE_MMU_MTRO_L0_MEMm(unit, MEM_BLOCK_ANY, 
   6072                                                           l0_base, &l0mtro));
   6073                 
   6074                 SOC_IF_ERROR_RETURN(WRITE_EGRMETERINGCONFIG_64r(unit, local_port, egrm));
   6075 
   6076                 if (rv) {
   6077                     return rv;
   6078                 }
   6079             }
   6080 
   6081             if (sched_mode != SOC_TR3_SCHED_MODE_STRICT) {
   6082                 SOC_IF_ERROR_RETURN(soc_tr3_cosq_set_sched_mode(unit, 
   6083                         local_port, SOC_TR3_NODE_LVL_L1, to_sched_index, 
   6084                         sched_mode, lwts));
   6085             }
   6086 
   6087             return SOC_E_NONE;
   6088         } else {
   6089             if (IS_CPU_PORT(unit, local_port)) {
   6090                 /* set the L0.0 index as parent, L0.(cosq/8) as child in 
   6091                  * schduling mode */
   6092                 BCM_IF_ERROR_RETURN(soc_tr3_sched_hw_index_get(unit, local_port, 
   6093                                      SOC_TR3_NODE_LVL_L0, 0, &cpu_l0_index));
   6094                 BCM_IF_ERROR_RETURN(soc_tr3_sched_hw_index_get(unit, local_port, 
   6095                                      SOC_TR3_NODE_LVL_L1, cosq/8, &cpu_l1_index));
   6096                 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_sched_parent_child_set(unit, 
   6097                                   local_port, SOC_TR3_NODE_LVL_L0, cpu_l0_index, 
   6098                                   cpu_l1_index, sched_mode, 1));
   6099             }
   6100             
   6101             lvl_off = cosq/8;
   6102             lvl = IS_CPU_PORT(unit, local_port) ? 
   6103                                 SOC_TR3_NODE_LVL_L1 : SOC_TR3_NODE_LVL_L0;
   6104 
   6105             BCM_IF_ERROR_RETURN(soc_tr3_sched_hw_index_get(unit, local_port, 
   6106                                                    lvl, lvl_off, &sch_index));
   6107 
   6108             BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_index_resolve(unit, local_port, cosq,
   6109                        _BCM_TR3_COSQ_INDEX_STYLE_SCHEDULER, NULL, &child_index, NULL));
   6110             
   6111             BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_sched_parent_child_set(unit, 
   6112                   local_port, lvl, sch_index, child_index, sched_mode, lwts));
   6113         }
   6114     }
   6115 
   6116     return BCM_E_NONE;
   6117 }
   6118 
   6119 /*
   6120  * Function:
   6121  *     _bcm_tr3_cosq_sched_get
   6122  * Purpose:
   6123  *     Get scheduling mode setting
   6124  * Parameters:
   6125  *     unit                - (IN) unit number
   6126  *     port                - (IN) port number or GPORT identifier
   6127  *     cosq                - (IN) COS queue number
   6128  *     mode                - (OUT) scheduling mode (BCM_COSQ_XXX)
   6129  *     num_weights         - (IN) number of entries in weights array
   6130  *     weights             - (OUT) weights array
   6131  * Returns:
   6132  *     BCM_E_XXX
   6133  */
   6134 STATIC int
   6135 _bcm_tr3_cosq_sched_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   6136                        int *mode, int *weight)
   6137 {
   6138     _bcm_tr3_cosq_node_t *node, *child_node;
   6139     bcm_port_t local_port;
   6140     int sch_index, lvl = SOC_TR3_NODE_LVL_L1, numq;
   6141     int child_index;
   6142     soc_tr3_sched_mode_e    sched_mode;
   6143     _bcm_tr3_mmu_info_t *mmu_info;
   6144     lls_l2_parent_entry_t l2pe;
   6145 
   6146     if ((mmu_info = _bcm_tr3_mmu_info[unit]) == NULL) {
   6147         return BCM_E_INIT;
   6148     }
   6149 
   6150     if (cosq < 0) {
   6151         if (cosq == -1) {
   6152             /* caller needs to resolve the wild card value (-1) */
   6153             return BCM_E_INTERNAL;
   6154         } else { /* reject all other negative value */
   6155             return BCM_E_PARAM;
   6156         }
   6157     }
   6158 
   6159     BCM_IF_ERROR_RETURN
   6160             (_bcm_tr3_cosq_localport_resolve(unit, port, &local_port));
   6161 
   6162     if (IS_TR3_HSP_PORT(unit, local_port)) {
   6163         if (cosq >= _TR3_NUM_HSP_COSQ) {
   6164             return BCM_E_PARAM;
   6165         }
   6166         /* Check if port is set as gport */
   6167         if (BCM_GPORT_IS_SET(port)) {
   6168              BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_node_get(unit, port,
   6169                                     0, NULL, &local_port, NULL, &node));
   6170              lvl = node->level;
   6171              if (lvl >= SOC_TR3_NODE_LVL_L1) {
   6172                  return BCM_E_PARAM;
   6173              }
   6174              if (lvl == SOC_TR3_NODE_LVL_L0) {
   6175                  BCM_IF_ERROR_RETURN(
   6176                      _soc_tr3_hsp_sched_weight_get(unit, local_port,
   6177                                                    node->attached_to_input, cosq, weight));
   6178                  BCM_IF_ERROR_RETURN(
   6179                      _soc_tr3_hsp_get_sched_config(unit, local_port,
   6180                                                    node->attached_to_input, cosq, &sched_mode));
   6181              } else {
   6182                  BCM_IF_ERROR_RETURN(
   6183                      soc_tr3_hsp_sched_weight_get(unit, local_port, cosq, weight));
   6184                  BCM_IF_ERROR_RETURN(
   6185                      soc_tr3_hsp_get_sched_config(unit, local_port, cosq, &sched_mode));
   6186              }
   6187         } else {
   6188             BCM_IF_ERROR_RETURN(
   6189                 soc_tr3_hsp_sched_weight_get(unit, local_port, cosq, weight));
   6190             BCM_IF_ERROR_RETURN(
   6191                 soc_tr3_hsp_get_sched_config(unit, local_port, cosq, &sched_mode));
   6192         }
   6193         switch (sched_mode) {
   6194             case SOC_TR3_SCHED_MODE_STRICT:
   6195                 *mode = BCM_COSQ_STRICT;
   6196                 break;
   6197             case SOC_TR3_SCHED_MODE_WRR:
   6198                 *mode = BCM_COSQ_WEIGHTED_ROUND_ROBIN;
   6199                 break;
   6200             case SOC_TR3_SCHED_MODE_WDRR:
   6201                 *mode = BCM_COSQ_DEFICIT_ROUND_ROBIN;
   6202                 break;
   6203             default:
   6204                return BCM_E_INTERNAL;
   6205         }
   6206         return BCM_E_NONE;
   6207     }
   6208 
   6209     if (_bcm_tr3_cosq_port_has_ets(unit, local_port) && BCM_GPORT_IS_SET(port)) {
   6210         BCM_IF_ERROR_RETURN
   6211           (_bcm_tr3_cosq_node_get(unit, port, 0, NULL, &local_port, NULL, &node));
   6212         sch_index = node->hw_index;
   6213         numq = node->numq;
   6214 
   6215         if ((numq > 0) && (cosq >= numq)) {
   6216             return BCM_E_PARAM;
   6217         }
   6218 
   6219         BCM_IF_ERROR_RETURN(
   6220             _bcm_tr3_cosq_child_node_at_input(node, cosq, &child_node));
   6221         lvl = child_node->level;
   6222         sch_index = child_node->hw_index;
   6223     } else {
   6224         numq = (IS_CPU_PORT(unit, local_port)) ? SOC_INFO(unit).num_cpu_cosq : _TR3_NUM_COS(unit);
   6225 
   6226         if (cosq >= numq) {
   6227             return BCM_E_PARAM;
   6228         }
   6229 
   6230         if (!IS_CPU_PORT(unit, local_port) &&
   6231             (!soc_feature(unit, soc_feature_tr3_sp_vector_mask) &&
   6232              soc_property_port_get(unit, local_port, spn_PORT_SCHED_DYNAMIC, 0))) {
   6233 
   6234             BCM_IF_ERROR_RETURN(
   6235                 _bcm_tr3_cosq_index_resolve(unit, local_port, cosq,
   6236                    _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE, NULL, &child_index, NULL));
   6237 
   6238             SOC_IF_ERROR_RETURN(READ_LLS_L2_PARENTm(unit, MEM_BLOCK_ANY,
   6239                                                         child_index, &l2pe));
   6240             sch_index = soc_mem_field32_get(unit, LLS_L2_PARENTm, &l2pe, C_PARENTf);
   6241             lvl = SOC_TR3_NODE_LVL_L1;
   6242         } else {
   6243             lvl = (IS_CPU_PORT(unit, local_port)) ? 
   6244                                 SOC_TR3_NODE_LVL_L2 : SOC_TR3_NODE_LVL_L1;
   6245             BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_index_resolve(unit, local_port, cosq,
   6246                    _BCM_TR3_COSQ_INDEX_STYLE_SCHEDULER, NULL, &sch_index, NULL));
   6247         }
   6248     }
   6249 
   6250     BCM_IF_ERROR_RETURN(
   6251             soc_tr3_cosq_get_sched_mode(unit, local_port, lvl, sch_index,
   6252                             &sched_mode, weight));
   6253 
   6254     switch(sched_mode) {
   6255         case SOC_TR3_SCHED_MODE_STRICT:
   6256             *mode = BCM_COSQ_STRICT;
   6257         break;
   6258         case SOC_TR3_SCHED_MODE_WRR:
   6259             *mode = BCM_COSQ_WEIGHTED_ROUND_ROBIN;
   6260         break;
   6261         case SOC_TR3_SCHED_MODE_WDRR:
   6262             *mode = BCM_COSQ_DEFICIT_ROUND_ROBIN;
   6263         break;
   6264         default:
   6265             return BCM_E_INTERNAL;
   6266         break;
   6267     }
   6268     
   6269     return BCM_E_NONE;
   6270 }
   6271 
   6272 /*
   6273  * Function:
   6274  *     bcm_tr3_cosq_detach
   6275  * Purpose:
   6276  *     Discard all COS schedule/mapping state.
   6277  * Parameters:
   6278  *     unit - unit number
   6279  * Returns:
   6280  *     BCM_E_XXX
   6281  */
   6282 int
   6283 bcm_tr3_cosq_detach(int unit, int software_state_only)
   6284 {
   6285     return BCM_E_NONE;
   6286 }
   6287 
   6288 /*
   6289  * Function:
   6290  *     bcm_tr3_cosq_config_set
   6291  * Purpose:
   6292  *     Set the number of COS queues
   6293  * Parameters:
   6294  *     unit - unit number
   6295  *     numq - number of COS queues (1-8).
   6296  * Returns:
   6297  *     BCM_E_XXX
   6298  */
   6299 int
   6300 bcm_tr3_cosq_config_set(int unit, int numq)
   6301 {
   6302     port_cos_map_entry_t cos_map_entries[16];
   6303     void *entries[1], *hg_entries[1];
   6304     uint32 index, hg_index;
   6305     int count, hg_count;
   6306     bcm_port_t port;
   6307     int cos, prio;
   6308     uint32 i;
   6309     int cpu_hg_index = 0;
   6310 #ifdef BCM_COSQ_HIGIG_MAP_DISABLE
   6311     port_cos_map_entry_t hg_cos_map_entries[16];
   6312 #endif
   6313     voq_cos_map_entry_t voq_cos_map;
   6314     int ref_count;
   6315 
   6316     if (numq < 1 || numq > 8) {
   6317         return BCM_E_PARAM;
   6318     }
   6319 
   6320     /* clear out old profiles. */
   6321     index = 0;
   6322     while (index < soc_mem_index_count(unit, PORT_COS_MAPm)) {
   6323         BCM_IF_ERROR_RETURN(soc_profile_mem_ref_count_get(unit,
   6324                                       _bcm_tr3_cos_map_profile[unit],
   6325                                       index, &ref_count));
   6326         if (ref_count > 0) {
   6327             while (ref_count) {
   6328                 BCM_IF_ERROR_RETURN(soc_profile_mem_delete(unit, 
   6329                                         _bcm_tr3_cos_map_profile[unit], index));
   6330                 ref_count -= 1;
   6331             }
   6332         }
   6333         index += 16;
   6334     }
   6335 
   6336     /* Distribute first 8 internal priority levels into the specified number
   6337      * of cosq, map remaining internal priority levels to highest priority
   6338      * cosq */
   6339     sal_memset(cos_map_entries, 0, sizeof(cos_map_entries));
   6340     entries[0] = &cos_map_entries;
   6341     hg_entries[0] = &cos_map_entries;
   6342     prio = 0;
   6343     for (cos = 0; cos < numq; cos++) {
   6344         for (i = 8 / numq + (cos < 8 % numq ? 1 : 0); i > 0; i--) {
   6345             soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio],
   6346                                 UC_COS1f, cos);
   6347             soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio],
   6348                                 MC_COS1f, cos);
   6349             soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio],
   6350                                 HG_COSf, cos);
   6351             prio++;
   6352         }
   6353     }
   6354     for (prio = 8; prio < 16; prio++) {
   6355         soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio], UC_COS1f,
   6356                             numq - 1);
   6357         soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio], MC_COS1f,
   6358                             numq - 1);
   6359         soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio], HG_COSf,
   6360                             numq - 1);
   6361     }
   6362 
   6363     /* Map internal priority levels to CPU CoS queues */
   6364     BCM_IF_ERROR_RETURN(_bcm_esw_cpu_cosq_mapping_default_set(unit, numq));
   6365 
   6366 #ifdef BCM_COSQ_HIGIG_MAP_DISABLE
   6367     /* Use identical mapping for Higig port */
   6368     sal_memset(hg_cos_map_entries, 0, sizeof(hg_cos_map_entries));
   6369     hg_entries[0] = &hg_cos_map_entries;
   6370     prio = 0;
   6371     for (prio = 0; prio < 8; prio++) {
   6372         soc_mem_field32_set(unit, PORT_COS_MAPm, &hg_cos_map_entries[prio],
   6373                             COSf, prio);
   6374     }
   6375     for (prio = 8; prio < 16; prio++) {
   6376         soc_mem_field32_set(unit, PORT_COS_MAPm, &hg_cos_map_entries[prio],
   6377                             COSf, 7);
   6378     }
   6379 #endif /* BCM_COSQ_HIGIG_MAP_DISABLE */
   6380 
   6381     BCM_IF_ERROR_RETURN
   6382         (soc_profile_mem_add(unit, _bcm_tr3_cos_map_profile[unit], entries, 16,
   6383                              &index));
   6384     /* for higig ports the mapping is slight different */
   6385     soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[14],
   6386                                HG_COSf, 8);
   6387     soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[15],
   6388                                HG_COSf, 9);
   6389 
   6390     BCM_IF_ERROR_RETURN
   6391         (soc_profile_mem_add(unit, _bcm_tr3_cos_map_profile[unit], hg_entries,
   6392                              16, &hg_index));
   6393     count = 0;
   6394     hg_count = 0;
   6395     PBMP_ALL_ITER(unit, port) {
   6396         if (IS_LB_PORT(unit, port)) {
   6397             continue;
   6398         }
   6399 
   6400         if (IS_HG_PORT(unit, port)) {
   6401             BCM_IF_ERROR_RETURN
   6402                 (soc_mem_field32_modify(unit, COS_MAP_SELm, port, SELECTf,
   6403                                         hg_index / 16));
   6404             hg_count++;
   6405         } else {
   6406             BCM_IF_ERROR_RETURN
   6407                 (soc_mem_field32_modify(unit, COS_MAP_SELm, port, SELECTf,
   6408                                         index / 16));
   6409             count++;
   6410         }
   6411     }
   6412     cpu_hg_index = SOC_INFO(unit).cpu_hg_index;
   6413     if (cpu_hg_index != -1) {
   6414         BCM_IF_ERROR_RETURN
   6415             (soc_mem_field32_modify(unit, COS_MAP_SELm,
   6416                 cpu_hg_index, SELECTf, index / 16));
   6417         count++;
   6418     }
   6419     for (i = 1; i < count; i++) {
   6420         soc_profile_mem_reference(unit, _bcm_tr3_cos_map_profile[unit], index,
   6421                                   0);
   6422     }
   6423     for (i = 1; i < hg_count; i++) {
   6424         soc_profile_mem_reference(unit, _bcm_tr3_cos_map_profile[unit],
   6425                                   hg_index, 0);
   6426     }
   6427 
   6428     sal_memset(&voq_cos_map, 0, sizeof(voq_cos_map));
   6429     for (cos = 0; cos < numq; cos++) {
   6430         for (i = 8 / numq + (i < 8 % numq ? 1 : 0); i > 0; i--) {
   6431             soc_mem_field32_set(unit, VOQ_COS_MAPm, &voq_cos_map, VOQ_COS_OFFSETf, cos);
   6432             BCM_IF_ERROR_RETURN(
   6433                 soc_mem_write(unit, VOQ_COS_MAPm, MEM_BLOCK_ANY, cos,
   6434                           &voq_cos_map));
   6435             prio++;
   6436         }
   6437     }
   6438     for (prio = 8; prio < 16; prio++) {
   6439         soc_mem_field32_set(unit, VOQ_COS_MAPm, &voq_cos_map, VOQ_COS_OFFSETf, numq - 1);
   6440         BCM_IF_ERROR_RETURN(
   6441                 soc_mem_write(unit, VOQ_COS_MAPm, MEM_BLOCK_ANY, prio,
   6442                           &voq_cos_map));
   6443     }
   6444 
   6445     _TR3_NUM_COS(unit) = numq;
   6446 
   6447     return BCM_E_NONE;
   6448 }
   6449 
   6450 STATIC int 
   6451 _bcm_tr3_cosq_egress_sp_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 
   6452                         int *p_pool_start, int *p_pool_end)
   6453 {
   6454     int local_port, uc, hw_index;
   6455     _bcm_tr3_cosq_node_t *node;
   6456     uint32 entry[SOC_MAX_MEM_WORDS], pool, rval;
   6457     
   6458     BCM_IF_ERROR_RETURN
   6459             (_bcm_tr3_cosq_localport_resolve(unit, gport, &local_port));
   6460 
   6461     if (!SOC_PORT_VALID(unit, local_port)) {
   6462         return BCM_E_PORT;
   6463     }
   6464 
   6465     if (cosq == BCM_COS_INVALID) {
   6466         *p_pool_start = 0;
   6467         *p_pool_end = 3;
   6468         return BCM_E_NONE;
   6469     }
   6470 
   6471     node = NULL;
   6472     if (BCM_GPORT_IS_SCHEDULER(gport)) {
   6473         BCM_IF_ERROR_RETURN(
   6474             _bcm_tr3_cosq_node_get(unit, gport, ((cosq < 0) ? 0 : cosq), 
   6475                                 NULL, &local_port, NULL, &node));
   6476         BCM_IF_ERROR_RETURN(
   6477             _bcm_tr3_cosq_child_node_at_input(node, cosq, &node));
   6478         cosq = 0;
   6479     } else if ((BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) ||
   6480                 (BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) ||
   6481                 (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport))) {
   6482         BCM_IF_ERROR_RETURN(
   6483             _bcm_tr3_cosq_node_get(unit, gport, 0, 
   6484                                 NULL, &local_port, NULL, &node));
   6485     }
   6486 
   6487     if (node) {
   6488         if (node->hw_index < 0) {
   6489             return BCM_E_PARAM;
   6490         }
   6491 
   6492         hw_index = node->hw_index;
   6493         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(node->gport) ||
   6494             BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(node->gport)) {
   6495             uc = 1;
   6496         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(node->gport)) {
   6497             uc = 0;
   6498         } else {
   6499             return BCM_E_PARAM;
   6500         }
   6501     } else {
   6502         uc = 1;
   6503         BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_index_resolve(unit, local_port, cosq, 
   6504             _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE, NULL, &hw_index, NULL));
   6505 
   6506     }
   6507 
   6508     if (uc) {
   6509         BCM_IF_ERROR_RETURN(soc_mem_read(unit, MMU_THDO_Q_TO_QGRP_MAPm,
   6510                                      MEM_BLOCK_ANY, hw_index, &entry));
   6511         pool = soc_mem_field32_get(unit, MMU_THDO_Q_TO_QGRP_MAPm, 
   6512                                    entry, Q_SPIDf);
   6513     } else {
   6514         BCM_IF_ERROR_RETURN(soc_reg32_get(unit, OP_QUEUE_CONFIG1_CELLr,
   6515                                           local_port, hw_index, &rval));
   6516         pool = soc_reg_field_get(unit, OP_QUEUE_CONFIG1_CELLr, 
   6517                                     rval, Q_SPIDf);
   6518     }
   6519     
   6520     *p_pool_start = *p_pool_end = pool;
   6521     return BCM_E_NONE;
   6522 }
   6523 
   6524 STATIC int 
   6525 _bcm_tr3_cosq_ingress_sp_get(int unit, bcm_gport_t gport, bcm_cos_queue_t pri_grp, 
   6526                          int *p_pool_start, int *p_pool_end)
   6527 {
   6528     int local_port;
   6529     uint32 rval, pool;
   6530     static const soc_field_t prigroup_spid_field[] = {
   6531         PG0_SPIDf, PG1_SPIDf, PG2_SPIDf, PG3_SPIDf,
   6532         PG4_SPIDf, PG5_SPIDf, PG6_SPIDf, PG7_SPIDf
   6533     };
   6534     
   6535     if (pri_grp == BCM_COS_INVALID) {
   6536         *p_pool_start = 0;
   6537         *p_pool_end = 3;
   6538         return BCM_E_NONE;
   6539     }
   6540 
   6541     BCM_IF_ERROR_RETURN
   6542             (_bcm_tr3_cosq_localport_resolve(unit, gport, &local_port));
   6543 
   6544     if (!SOC_PORT_VALID(unit, local_port)) {
   6545         return BCM_E_PORT;
   6546     }
   6547 
   6548     if (pri_grp >= 8) {
   6549         return BCM_E_PARAM;
   6550     }
   6551 
   6552     SOC_IF_ERROR_RETURN(READ_PORT_PG_SPIDr(unit, local_port, &rval));
   6553     pool = soc_reg_field_get(unit, PORT_PG_SPIDr, rval, 
   6554                                 prigroup_spid_field[pri_grp]);
   6555     
   6556     *p_pool_start = *p_pool_end = pool;
   6557     return BCM_E_NONE;
   6558 }
   6559 
   6560 STATIC int 
   6561 _bcm_tr3_cosq_ingress_pg_get(int unit, bcm_gport_t gport, bcm_cos_queue_t pri, 
   6562                          int *p_pg_start, int *p_pg_end)
   6563 {
   6564     bcm_port_t local_port;
   6565     uint32  rval,pool;
   6566     soc_reg_t reg = INVALIDr;
   6567     static const soc_reg_t prigroup_reg[] = {
   6568         PORT_PRI_GRP0r, PORT_PRI_GRP1r
   6569     };
   6570     static const soc_field_t prigroup_field[] = {
   6571         PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf,
   6572         PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf,
   6573         PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf,
   6574         PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf
   6575     };
   6576 
   6577     if (pri == BCM_COS_INVALID) {
   6578         *p_pg_start = 0;
   6579         *p_pg_end = 7;
   6580         return BCM_E_NONE;
   6581     }
   6582 
   6583     BCM_IF_ERROR_RETURN
   6584             (_bcm_tr3_cosq_localport_resolve(unit, gport, &local_port));
   6585 
   6586     if (!SOC_PORT_VALID(unit, local_port)) {
   6587         return BCM_E_PORT;
   6588     }
   6589 
   6590     if (pri > 15) {
   6591         return BCM_E_PARAM;
   6592     }
   6593        /* get PG for port using Port+Cos */
   6594     if (pri < 8) {
   6595         reg = prigroup_reg[0];
   6596     } else {
   6597         reg = prigroup_reg[1];
   6598     }
   6599 
   6600     SOC_IF_ERROR_RETURN
   6601         (soc_reg32_get(unit, reg, local_port, 0, &rval));
   6602         pool = soc_reg_field_get(unit, reg, rval, prigroup_field[pri]);
   6603 
   6604     *p_pg_start = *p_pg_end = pool;
   6605     return BCM_E_NONE;
   6606 }
   6607 
   6608 STATIC _bcm_bst_cb_ret_t
   6609 _bcm_tr3_bst_index_resolve(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
   6610                     bcm_bst_stat_id_t bid, int *pipe, int *start_hw_index, 
   6611                     int *end_hw_index, int *rcb_data, void **cb_data, int *bcm_rv)
   6612 {
   6613     int phy_port, mmu_port, local_port;
   6614     _bcm_tr3_cosq_node_t *node = NULL;
   6615     soc_info_t *si;
   6616     int rv;
   6617 
   6618     *bcm_rv = BCM_E_NONE;
   6619     *pipe = 0;
   6620     si = &SOC_INFO(unit);
   6621 
   6622     rv = _bcm_tr3_cosq_localport_resolve(unit, gport, &local_port);
   6623     if (BCM_FAILURE(rv)) {
   6624         goto error;
   6625     }
   6626 
   6627     if (bid == bcmBstStatIdDevice) {
   6628         *start_hw_index = *end_hw_index = 0;
   6629         *bcm_rv = BCM_E_NONE;
   6630         return _BCM_BST_RV_OK;
   6631     }
   6632 
   6633     /* only 48 CPU queues 0-47 supported for bcmBstStatIdMcast */
   6634     if (bid == bcmBstStatIdMcast) {
   6635         if (IS_CPU_PORT(unit, local_port)) {
   6636             *start_hw_index = 0;
   6637             *end_hw_index = cosq;
   6638             *bcm_rv = BCM_E_NONE;
   6639             return _BCM_BST_RV_OK;
   6640         } else {
   6641             *start_hw_index = *end_hw_index = 0;
   6642             *bcm_rv = BCM_E_PARAM;
   6643             return _BCM_BST_RV_ERROR;
   6644         }
   6645     }
   6646  
   6647     /* resolve pool */
   6648     if (bid == bcmBstStatIdEgrPool) {
   6649         if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   6650             goto error;
   6651         }
   6652         if(_bcm_tr3_cosq_egress_sp_get(unit, gport, cosq, start_hw_index, 
   6653                                                     end_hw_index)) {
   6654             goto error;
   6655         }
   6656         return _BCM_BST_RV_OK;
   6657     } else if (bid == bcmBstStatIdEgrMCastPool) {
   6658         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
   6659             BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) {
   6660             goto error;
   6661         }
   6662         if(_bcm_tr3_cosq_egress_sp_get(unit, gport, cosq, start_hw_index, 
   6663                                                     end_hw_index)) {
   6664             goto error;
   6665         }
   6666 	return _BCM_BST_RV_OK;
   6667     } else if (bid == bcmBstStatIdIngPool) {
   6668         /* ingress pool */
   6669         if (_bcm_tr3_cosq_ingress_sp_get(unit, gport, cosq, 
   6670                                     start_hw_index, end_hw_index)) {
   6671             goto error;
   6672         }
   6673         return _BCM_BST_RV_OK;
   6674     } else if ((bid == bcmBstStatIdPriGroupShared) ||
   6675             (bid == bcmBstStatIdPriGroupHeadroom)) {
   6676         if (_bcm_tr3_cosq_ingress_pg_get(unit, gport, cosq,
   6677                                     start_hw_index, end_hw_index)){
   6678             goto error;
   6679         }
   6680     }
   6681 
   6682     phy_port = si->port_l2p_mapping[local_port];
   6683     mmu_port = si->port_p2m_mapping[phy_port];
   6684 
   6685     if (bid == bcmBstStatIdPortPool) {
   6686         *start_hw_index = (mmu_port * 4) + *start_hw_index;
   6687         *end_hw_index = (mmu_port * 4) + *end_hw_index;
   6688     } else if ((bid == bcmBstStatIdPriGroupShared) || 
   6689                (bid == bcmBstStatIdPriGroupHeadroom)) {
   6690         *start_hw_index = (mmu_port * 8) + *start_hw_index;
   6691         *end_hw_index = (mmu_port * 8) + *end_hw_index;
   6692 
   6693     } else {
   6694         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
   6695             BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) {
   6696             if (bid != bcmBstStatIdUcast) {
   6697                 goto error;
   6698             }
   6699             BCM_IF_ERROR_RETURN
   6700                 (_bcm_tr3_cosq_node_get(unit, gport, 0, NULL, 
   6701                                         &local_port, NULL, &node));
   6702             if (!node) {
   6703                 goto error;
   6704             }
   6705             *start_hw_index = *end_hw_index = node->hw_index;
   6706         } else {
   6707             BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_port_has_ets(unit, local_port));
   6708             
   6709             if (cosq < 0) {
   6710                 if (bid == bcmBstStatIdUcast) {
   6711                     *start_hw_index = si->port_uc_cosq_base[local_port];
   6712                     *end_hw_index = si->port_uc_cosq_base[local_port] + 7;
   6713                 } else {
   6714                     *start_hw_index = si->port_cosq_base[local_port];
   6715                     *end_hw_index = si->port_cosq_base[local_port] + 7;
   6716                 }
   6717             } else {
   6718                 if (bid == bcmBstStatIdUcast) {
   6719                     *start_hw_index = si->port_uc_cosq_base[local_port] + cosq;
   6720                     *end_hw_index = si->port_uc_cosq_base[local_port] + cosq;
   6721                 } else {
   6722                     *start_hw_index = si->port_cosq_base[local_port] + cosq;
   6723                     *end_hw_index = si->port_cosq_base[local_port] + cosq;
   6724                 }
   6725             }
   6726         }
   6727     }
   6728    
   6729     *bcm_rv = BCM_E_NONE;
   6730     return _BCM_BST_RV_OK;
   6731 
   6732 error:
   6733     *bcm_rv = BCM_E_PARAM;
   6734     return _BCM_BST_RV_ERROR;
   6735 }
   6736 
   6737 STATIC int
   6738 _bcm_tr3_cosq_bst_map_resource_to_gport_cos(int unit, bcm_bst_stat_id_t bid, int port, 
   6739                          int index, bcm_gport_t *gport, bcm_cos_t *cosq)
   6740 {
   6741     soc_info_t *si;
   6742     _bcm_tr3_cosq_node_t *node;
   6743     _bcm_tr3_mmu_info_t *mmu_info;
   6744     int resolved = 0, ii, phy_port, mmu_port;
   6745 
   6746     mmu_info = _bcm_tr3_mmu_info[unit];
   6747     si = &SOC_INFO(unit);
   6748 
   6749     switch(bid) {
   6750         case bcmBstStatIdDevice:
   6751             *gport = -1;
   6752             *cosq = BCM_COS_INVALID;
   6753             break;
   6754 
   6755         case bcmBstStatIdIngPool:
   6756         case bcmBstStatIdEgrPool:
   6757             *gport = -1;
   6758             *cosq = index;
   6759             break;
   6760 
   6761         case bcmBstStatIdPortPool:
   6762             mmu_port= index/4;
   6763             phy_port = si->port_m2p_mapping[mmu_port];
   6764             *gport = si->port_p2l_mapping[phy_port];
   6765             *cosq = index % 4;
   6766             break;
   6767 
   6768         case bcmBstStatIdPriGroupHeadroom:
   6769         case bcmBstStatIdPriGroupShared:
   6770             mmu_port = index/8;
   6771             phy_port = si->port_m2p_mapping[mmu_port];
   6772             *gport = si->port_p2l_mapping[phy_port];
   6773             *cosq = index % 8;
   6774             break;
   6775 
   6776         case bcmBstStatIdUcast:
   6777             for (ii = mmu_info->num_base_queues; 
   6778                  ii < _BCM_TR3_NUM_L2_UC_LEAVES; ii++) {
   6779                 node = &mmu_info->queue_node[ii];
   6780                 if ((node->in_use == TRUE) && (node->hw_index == index)) {
   6781                     *gport = node->gport;
   6782                     *cosq = 0;
   6783                     resolved = 1;
   6784                     break;
   6785                 }
   6786             }
   6787 
   6788             if (!resolved) {
   6789                 for (ii = index/8; ii < 64; ii++) {
   6790                     if ((index - si->port_uc_cosq_base[ii]) < 8) {
   6791                         *gport = ii;
   6792                         *cosq = index - si->port_uc_cosq_base[ii];
   6793                         break;
   6794                     }
   6795                 }
   6796             }
   6797             break;
   6798         default:
   6799             *gport = -1;
   6800             *cosq = BCM_COS_INVALID;            
   6801             break;
   6802     }
   6803 
   6804     return BCM_E_NONE;
   6805 }
   6806 
   6807 STATIC int
   6808 _bcm_tr3_cosq_unreserve_gport_resources(int unit, bcm_port_t port)
   6809 {
   6810     int lvl, lvl_offset, hw_index, rv;
   6811     _bcm_tr3_mmu_info_t *mmu_info;
   6812     _bcm_tr3_cosq_list_t *list;
   6813 
   6814     mmu_info = _bcm_tr3_mmu_info[unit];
   6815 
   6816     for (lvl = SOC_TR3_NODE_LVL_L0; lvl <= SOC_TR3_NODE_LVL_L1; lvl++) {
   6817         lvl_offset = 0;
   6818 
   6819         list = NULL;
   6820         if (lvl == SOC_TR3_NODE_LVL_L0) {
   6821             list = &mmu_info->l0_sched_list;
   6822         } else if (lvl == SOC_TR3_NODE_LVL_L1) {
   6823             list = &mmu_info->l1_sched_list;
   6824         }
   6825 
   6826         if (!list) {
   6827             continue;
   6828         }
   6829         while ((rv = soc_tr3_sched_hw_index_get(unit, port, lvl,
   6830                                    lvl_offset, &hw_index)) == SOC_E_NONE) {
   6831             _bcm_tr3_node_index_clear(list, hw_index, 1);
   6832             lvl_offset += 1;
   6833         }
   6834     }
   6835     return BCM_E_NONE;
   6836 }
   6837 STATIC int
   6838 _bcm_tr3_cosq_reserve_gport_resources(int unit, bcm_port_t port)
   6839 {
   6840     int lvl, lvl_offset, hw_index, rv;
   6841     _bcm_tr3_mmu_info_t *mmu_info;
   6842     _bcm_tr3_cosq_list_t *list;
   6843 
   6844     mmu_info = _bcm_tr3_mmu_info[unit];
   6845 
   6846     for (lvl = SOC_TR3_NODE_LVL_L0; lvl <= SOC_TR3_NODE_LVL_L1; lvl++) {
   6847         lvl_offset = 0;
   6848 
   6849         list = NULL;
   6850         if (lvl == SOC_TR3_NODE_LVL_L0) {
   6851             list = &mmu_info->l0_sched_list;
   6852         } else if (lvl == SOC_TR3_NODE_LVL_L1) {
   6853             list = &mmu_info->l1_sched_list;
   6854         }
   6855 
   6856         if (!list) {
   6857             continue;
   6858         }
   6859         while ((rv = soc_tr3_sched_hw_index_get(unit, port, lvl, 
   6860                                    lvl_offset, &hw_index)) == SOC_E_NONE) {
   6861             _bcm_tr3_node_index_set(list, hw_index, 1);
   6862             lvl_offset += 1;
   6863         }
   6864     }
   6865     return BCM_E_NONE;
   6866 }
   6867 STATIC
   6868 int _bcm_tr3_hsp_hierarchy_setup(int unit, int port)
   6869 {
   6870     bcm_gport_t gport;
   6871     bcm_gport_t port_sched, l0_sched[_SOC_HSP_MAX_L0_NODES];
   6872     bcm_gport_t Uqueue[_SOC_HSP_NUM_UC_QUEUE];
   6873     bcm_gport_t Mqueue[_SOC_HSP_NUM_MC_QUEUE];
   6874     int cos;
   6875 
   6876     BCM_IF_ERROR_RETURN(bcm_esw_port_gport_get(unit, port, &gport));
   6877 
   6878     BCM_IF_ERROR_RETURN(bcm_tr3_cosq_gport_add(unit, gport, 10, 0, &port_sched, 1));
   6879         
   6880     for(cos = 0; cos < _SOC_HSP_MAX_L0_NODES; cos++) {
   6881         BCM_IF_ERROR_RETURN(bcm_tr3_cosq_gport_add(unit, gport, -1, 
   6882                                                    BCM_COSQ_GPORT_SCHEDULER, 
   6883                                                    &l0_sched[cos], 1));
   6884         BCM_IF_ERROR_RETURN(bcm_tr3_cosq_gport_attach(unit, l0_sched[cos], port_sched, cos));
   6885     }
   6886     for (cos = 0; cos < (_SOC_HSP_NUM_UC_QUEUE - _SOC_HSP_LAST_L0_NUM_UC_QUEUE); cos++) { 
   6887          BCM_IF_ERROR_RETURN(bcm_tr3_cosq_gport_add(unit, gport, 1, 
   6888                                                     BCM_COSQ_GPORT_UCAST_QUEUE_GROUP, 
   6889                                                     &Uqueue[cos], 1));
   6890          BCM_IF_ERROR_RETURN(bcm_tr3_cosq_gport_attach(unit, Uqueue[cos], l0_sched[cos+1], 0));
   6891     }
   6892     for (cos = 0; cos < (_SOC_HSP_NUM_MC_QUEUE - _SOC_HSP_LAST_L0_NUM_UC_QUEUE); cos++) {
   6893          BCM_IF_ERROR_RETURN(bcm_tr3_cosq_gport_add(unit, gport, 1, 
   6894                                                     BCM_COSQ_GPORT_MCAST_QUEUE_GROUP, 
   6895                                                     &Mqueue[cos], 1));
   6896          BCM_IF_ERROR_RETURN(bcm_tr3_cosq_gport_attach(unit, Mqueue[cos], l0_sched[cos+1], 1));
   6897     }
   6898     for (cos = 0; cos < _SOC_HSP_LAST_L0_NUM_UC_QUEUE; cos++) {
   6899          BCM_IF_ERROR_RETURN(bcm_tr3_cosq_gport_add(unit, gport, 1, 
   6900                                                     BCM_COSQ_GPORT_UCAST_QUEUE_GROUP, 
   6901                                                     &Uqueue[cos+8],1));
   6902          BCM_IF_ERROR_RETURN(bcm_tr3_cosq_gport_attach(unit, Uqueue[cos+8], l0_sched[9], cos));
   6903     }
   6904     for (cos = 0; cos < _SOC_HSP_LAST_L0_NUM_MC_QUEUE; cos++) {
   6905         BCM_IF_ERROR_RETURN(bcm_tr3_cosq_gport_add(unit, gport, 1, 
   6906                                                    BCM_COSQ_GPORT_MCAST_QUEUE_GROUP, 
   6907                                                    &Mqueue[cos+8], 1));
   6908         BCM_IF_ERROR_RETURN(bcm_tr3_cosq_gport_attach(unit, Mqueue[cos+8], l0_sched[9], cos+2));
   6909     }
   6910     return BCM_E_NONE;
   6911 }
   6912 /*
   6913  * Function:
   6914  *     bcm_tr3_cosq_init
   6915  * Purpose:
   6916  *     Initialize (clear) all COS schedule/mapping state.
   6917  * Parameters:
   6918  *     unit - unit number
   6919  * Returns:
   6920  *     BCM_E_XXX
   6921  */
   6922 int
   6923 bcm_tr3_cosq_init(int unit)
   6924 {
   6925     int numq, alloc_size, ii;
   6926     soc_info_t *si;
   6927     bcm_port_t port;
   6928     soc_reg_t reg;
   6929     soc_reg_t mem;
   6930     static soc_mem_t wred_mems[6] = {
   6931         MMU_WRED_DROP_CURVE_PROFILE_0m, MMU_WRED_DROP_CURVE_PROFILE_1m,
   6932         MMU_WRED_DROP_CURVE_PROFILE_2m, MMU_WRED_DROP_CURVE_PROFILE_3m,
   6933         MMU_WRED_DROP_CURVE_PROFILE_4m, MMU_WRED_DROP_CURVE_PROFILE_5m
   6934     };
   6935     int entry_words[6];
   6936     mmu_wred_drop_curve_profile_0_entry_t entry_tcp_green;
   6937     mmu_wred_drop_curve_profile_1_entry_t entry_tcp_yellow;
   6938     mmu_wred_drop_curve_profile_2_entry_t entry_tcp_red;
   6939     mmu_wred_drop_curve_profile_3_entry_t entry_nontcp_green;
   6940     mmu_wred_drop_curve_profile_4_entry_t entry_nontcp_yellow;
   6941     mmu_wred_drop_curve_profile_5_entry_t entry_nontcp_red;
   6942     void *entries[6];
   6943     uint64 rval64s[16], *prval64s[1];
   6944     uint32 rval, profile_index;
   6945     _bcm_tr3_mmu_info_t *mmu_info;
   6946     int i, wred_prof_count, index;
   6947     _bcm_bst_device_handlers_t bst_callbks;
   6948     _bcm_tr3_cosq_list_t *list = NULL;
   6949     if (!SOC_WARM_BOOT(unit)) {    /* Cold Boot */
   6950         BCM_IF_ERROR_RETURN (bcm_tr3_cosq_detach(unit, 0));
   6951     }
   6952 
   6953     si = &SOC_INFO(unit);
   6954     numq = soc_property_get(unit, spn_BCM_NUM_COS, BCM_COS_DEFAULT);
   6955     
   6956     if (numq < 1) {
   6957         numq = 1;
   6958     } else if (numq > 8) {
   6959         numq = 8;
   6960     }
   6961     _TR3_NUM_COS(unit) = numq;
   6962 
   6963     /* Create profile for PORT_COS_MAP table */
   6964     if (_bcm_tr3_cos_map_profile[unit] == NULL) {
   6965         _bcm_tr3_cos_map_profile[unit] = sal_alloc(sizeof(soc_profile_mem_t),
   6966                                                   "COS_MAP Profile Mem");
   6967         if (_bcm_tr3_cos_map_profile[unit] == NULL) {
   6968             return BCM_E_MEMORY;
   6969         }
   6970         soc_profile_mem_t_init(_bcm_tr3_cos_map_profile[unit]);
   6971     }
   6972     mem = PORT_COS_MAPm;
   6973     entry_words[0] = sizeof(port_cos_map_entry_t) / sizeof(uint32);
   6974     BCM_IF_ERROR_RETURN(soc_profile_mem_create(unit, &mem, entry_words, 1,
   6975                                                _bcm_tr3_cos_map_profile[unit]));
   6976 
   6977     /* Create profile for SERVICE_COS_MAP table */
   6978     if (_bcm_tr3_service_cos_map_profile[unit] == NULL) {
   6979         _bcm_tr3_service_cos_map_profile[unit] = sal_alloc(sizeof(soc_profile_mem_t),
   6980                                                   "SERVICE_COS_MAP Profile Mem");
   6981         if (_bcm_tr3_service_cos_map_profile[unit] == NULL) {
   6982             return BCM_E_MEMORY;
   6983         }
   6984         soc_profile_mem_t_init(_bcm_tr3_service_cos_map_profile[unit]);
   6985     }
   6986     mem = SERVICE_COS_MAPm;
   6987     entry_words[0] = sizeof(service_cos_map_entry_t) / sizeof(uint32);
   6988     BCM_IF_ERROR_RETURN(soc_profile_mem_create(unit, &mem, entry_words, 1,
   6989                                                _bcm_tr3_service_cos_map_profile[unit]));
   6990 
   6991     /* Create profile for SERVICE_PORT_MAP table */
   6992     if (_bcm_tr3_service_port_map_profile[unit] == NULL) {
   6993         _bcm_tr3_service_port_map_profile[unit] = sal_alloc(sizeof(soc_profile_mem_t),
   6994                                                   "SERVICE_PORT_MAP Profile Mem");
   6995         if (_bcm_tr3_service_port_map_profile[unit] == NULL) {
   6996             return BCM_E_MEMORY;
   6997         }
   6998         soc_profile_mem_t_init(_bcm_tr3_service_port_map_profile[unit]);
   6999     }
   7000 
   7001     /* Create profile for IFP_COS_MAP table. */
   7002     if (_bcm_tr3_ifp_cos_map_profile[unit] == NULL) {
   7003         _bcm_tr3_ifp_cos_map_profile[unit]
   7004             = sal_alloc(sizeof(soc_profile_mem_t), "IFP_COS_MAP Profile Mem");
   7005         if (_bcm_tr3_ifp_cos_map_profile[unit] == NULL) {
   7006             return BCM_E_MEMORY;
   7007         }
   7008         soc_profile_mem_t_init(_bcm_tr3_ifp_cos_map_profile[unit]);
   7009     }
   7010     mem = IFP_COS_MAPm;
   7011     entry_words[0] = sizeof(ifp_cos_map_entry_t) / sizeof(uint32);
   7012     BCM_IF_ERROR_RETURN
   7013         (soc_profile_mem_create(unit, &mem, entry_words, 1,
   7014                                 _bcm_tr3_ifp_cos_map_profile[unit]));
   7015 
   7016     mem = SERVICE_PORT_MAPm;
   7017     entry_words[0] = sizeof(service_port_map_entry_t) / sizeof(uint32);
   7018     BCM_IF_ERROR_RETURN(soc_profile_mem_create(unit, &mem, entry_words, 1,
   7019                                                _bcm_tr3_service_port_map_profile[unit]));
   7020 
   7021     alloc_size = sizeof(_bcm_tr3_mmu_info_t) * 1;
   7022     if (_bcm_tr3_mmu_info[unit] == NULL) {
   7023         _bcm_tr3_mmu_info[unit] =
   7024             sal_alloc(alloc_size, "_bcm_tr3_mmu_info");
   7025 
   7026         if (_bcm_tr3_mmu_info[unit] == NULL) {
   7027             return BCM_E_MEMORY;
   7028         }
   7029 
   7030         sal_memset(_bcm_tr3_mmu_info[unit], 0, alloc_size);
   7031     }else{
   7032     	bcm_tr3_cosq_stat_init(unit);
   7033     }
   7034 
   7035     mmu_info = _bcm_tr3_mmu_info[unit];
   7036     mmu_info->num_base_queues = 0;
   7037 
   7038     /* assign queues to ports */
   7039     PBMP_ALL_ITER(unit, port) {
   7040         mmu_info->port_info[port].mc_base = si->port_cosq_base[port];
   7041         mmu_info->port_info[port].mc_limit = si->port_cosq_base[port] + 
   7042                                                 si->port_num_cosq[port];
   7043 
   7044         mmu_info->port_info[port].uc_base = si->port_uc_cosq_base[port];;
   7045         mmu_info->port_info[port].uc_limit = si->port_uc_cosq_base[port] + 
   7046                                                 si->port_num_uc_cosq[port];
   7047         mmu_info->num_base_queues += si->port_num_uc_cosq[port];
   7048 
   7049         if (!SOC_WARM_BOOT(unit)) {
   7050             rval = 0;
   7051             soc_reg_field_set(unit, ING_COS_MODEr, &rval, BASE_QUEUE_NUM_0f,
   7052                               mmu_info->port_info[port].uc_base);
   7053             soc_reg_field_set(unit, ING_COS_MODEr, &rval, BASE_QUEUE_NUM_1f,
   7054                               mmu_info->port_info[port].uc_base);
   7055             BCM_IF_ERROR_RETURN(soc_reg32_set(unit, ING_COS_MODEr, port, 0, rval));
   7056         }
   7057     }
   7058 
   7059     mmu_info->ets_mode = 0;
   7060     mmu_info->num_dmvoq_queues = soc_property_get(unit,
   7061                                                   spn_MMU_NUM_DMVOQ_QUEUES, 0);
   7062 
   7063     if (mmu_info->num_dmvoq_queues > 0) {
   7064         mmu_info->base_dmvoq_queue =  (mmu_info->num_base_queues + 7) & 0xfffffff8;
   7065         mmu_info->dmvoq_qlist.count = mmu_info->num_dmvoq_queues;
   7066         mmu_info->dmvoq_qlist.bits = _bcm_tr3_cosq_alloc_clear(
   7067                                     mmu_info->dmvoq_qlist.bits,
   7068                                     SHR_BITALLOCSIZE(mmu_info->num_dmvoq_queues),
   7069                                     "dmvoq_qlist");
   7070         if (mmu_info->dmvoq_qlist.bits == NULL) {
   7071             _bcm_tr3_cosq_free_memory(mmu_info);
   7072             return BCM_E_MEMORY;
   7073         }
   7074     }
   7075 
   7076     mmu_info->ext_qlist.count = _BCM_TR3_NUM_L2_UC_LEAVES;
   7077     mmu_info->ext_qlist.bits = _bcm_tr3_cosq_alloc_clear(
   7078                                 mmu_info->ext_qlist.bits,
   7079       SHR_BITALLOCSIZE(_BCM_TR3_NUM_L2_UC_LEAVES), "ext_qlist");
   7080     if (mmu_info->ext_qlist.bits == NULL) {
   7081         _bcm_tr3_cosq_free_memory(mmu_info);
   7082         return BCM_E_MEMORY;
   7083     }
   7084 
   7085     mmu_info->l0_sched_list.count = _BCM_TR3_NUM_L0_SCHEDULER;
   7086     mmu_info->l0_sched_list.bits = _bcm_tr3_cosq_alloc_clear(
   7087                                     mmu_info->l0_sched_list.bits,
   7088       SHR_BITALLOCSIZE(_BCM_TR3_NUM_L0_SCHEDULER), "l0_sched_list");
   7089     if (mmu_info->l0_sched_list.bits == NULL) {
   7090         _bcm_tr3_cosq_free_memory(mmu_info);
   7091         return BCM_E_MEMORY;
   7092     }
   7093 
   7094     mmu_info->l1_sched_list.count = _BCM_TR3_NUM_L1_SCHEDULER;
   7095     mmu_info->l1_sched_list.bits = _bcm_tr3_cosq_alloc_clear(
   7096                                     mmu_info->l1_sched_list.bits,
   7097         SHR_BITALLOCSIZE(_BCM_TR3_NUM_L1_SCHEDULER), "l1_sched_list");
   7098     if (mmu_info->l1_sched_list.bits == NULL) {
   7099         _bcm_tr3_cosq_free_memory(mmu_info);
   7100         return BCM_E_MEMORY;
   7101     }
   7102 
   7103     for (i = 0; i < _BCM_TR3_NUM_TOTAL_SCHEDULERS; i++) {
   7104         _BCM_TR3_COSQ_LIST_NODE_INIT(mmu_info->sched_node, i);
   7105     }
   7106 
   7107     for (i = 0; i < _BCM_TR3_NUM_L2_UC_LEAVES; i++) {
   7108         _BCM_TR3_COSQ_LIST_NODE_INIT(mmu_info->queue_node, i);
   7109     }
   7110 
   7111     for (i = 0; i < _BCM_TR3_NUM_L2_MC_LEAVES; i++) {
   7112         _BCM_TR3_COSQ_LIST_NODE_INIT(mmu_info->mc_queue_node, i);
   7113     }
   7114 
   7115     for (i = SOC_TR3_NODE_LVL_L1; i <= SOC_TR3_NODE_LVL_L2; i++) {
   7116         index = _soc_tr3_invalid_parent_index(unit, i);
   7117         if (i == SOC_TR3_NODE_LVL_L1) {
   7118             list = &mmu_info->l0_sched_list;
   7119         } else if (i == SOC_TR3_NODE_LVL_L2) {
   7120             list = &mmu_info->l1_sched_list;
   7121         } else {
   7122             continue;
   7123         }
   7124         if (index >= 0) {
   7125             _bcm_tr3_node_index_set(list, index, 1);
   7126         }
   7127     }
   7128     if (mmu_info->num_dmvoq_queues > 0) {
   7129         BCM_IF_ERROR_RETURN
   7130         (_bcm_tr3_node_index_set(&mmu_info->ext_qlist,
   7131                                 mmu_info->base_dmvoq_queue,
   7132                                 mmu_info->num_dmvoq_queues));
   7133     }
   7134 
   7135     /* Create profile for MMU_QCN_SITB table */
   7136     if (_bcm_tr3_sample_int_profile[unit] == NULL) {
   7137         _bcm_tr3_sample_int_profile[unit] =
   7138             sal_alloc(sizeof(soc_profile_mem_t), "QCN sample Int Profile Mem");
   7139         if (_bcm_tr3_sample_int_profile[unit] == NULL) {
   7140             return BCM_E_MEMORY;
   7141         }
   7142         soc_profile_mem_t_init(_bcm_tr3_sample_int_profile[unit]);
   7143     }
   7144     mem = MMU_QCN_SITBm;
   7145     entry_words[0] = sizeof(mmu_qcn_sitb_entry_t) / sizeof(uint32);
   7146     BCM_IF_ERROR_RETURN
   7147         (soc_profile_mem_create(unit, &mem, entry_words, 1,
   7148                                 _bcm_tr3_sample_int_profile[unit]));
   7149 
   7150     /* Create profile for MMU_QCN_CPQ_SEQ register */
   7151     if (_bcm_tr3_feedback_profile[unit] == NULL) {
   7152         _bcm_tr3_feedback_profile[unit] =
   7153             sal_alloc(sizeof(soc_profile_reg_t), "QCN Feedback Profile Reg");
   7154         if (_bcm_tr3_feedback_profile[unit] == NULL) {
   7155             return BCM_E_MEMORY;
   7156         }
   7157         soc_profile_reg_t_init(_bcm_tr3_feedback_profile[unit]);
   7158     }
   7159     reg = MMU_QCN_CPQ_SEQr;
   7160     BCM_IF_ERROR_RETURN
   7161         (soc_profile_reg_create(unit, &reg, 1,
   7162                                 _bcm_tr3_feedback_profile[unit]));
   7163 
   7164     /* Create profile for PRIO2COS_LLFC register */
   7165     if (_bcm_tr3_llfc_profile[unit] == NULL) {
   7166         _bcm_tr3_llfc_profile[unit] =
   7167             sal_alloc(sizeof(soc_profile_reg_t), "PRIO2COS_LLFC Profile Reg");
   7168         if (_bcm_tr3_llfc_profile[unit] == NULL) {
   7169             return BCM_E_MEMORY;
   7170         }
   7171         soc_profile_reg_t_init(_bcm_tr3_llfc_profile[unit]);
   7172     }
   7173     reg = PRIO2COS_PROFILEr;
   7174     BCM_IF_ERROR_RETURN
   7175         (soc_profile_reg_create(unit, &reg, 1, _bcm_tr3_llfc_profile[unit]));
   7176 
   7177     /* Create profile for MMU_WRED_DROP_CURVE_PROFILE_x tables */
   7178     if (_bcm_tr3_wred_profile[unit] == NULL) {
   7179         _bcm_tr3_wred_profile[unit] = sal_alloc(sizeof(soc_profile_mem_t),
   7180                                                "WRED Profile Mem");
   7181         if (_bcm_tr3_wred_profile[unit] == NULL) {
   7182             return BCM_E_MEMORY;
   7183         }
   7184         soc_profile_mem_t_init(_bcm_tr3_wred_profile[unit]);
   7185     }
   7186 
   7187     entry_words[0] =
   7188         sizeof(mmu_wred_drop_curve_profile_0_entry_t) / sizeof(uint32);
   7189     entry_words[1] =
   7190         sizeof(mmu_wred_drop_curve_profile_1_entry_t) / sizeof(uint32);
   7191     entry_words[2] =
   7192         sizeof(mmu_wred_drop_curve_profile_2_entry_t) / sizeof(uint32);
   7193     entry_words[3] =
   7194         sizeof(mmu_wred_drop_curve_profile_3_entry_t) / sizeof(uint32);
   7195     entry_words[4] =
   7196         sizeof(mmu_wred_drop_curve_profile_4_entry_t) / sizeof(uint32);
   7197     entry_words[5] =
   7198         sizeof(mmu_wred_drop_curve_profile_5_entry_t) / sizeof(uint32);
   7199     BCM_IF_ERROR_RETURN
   7200         (soc_profile_mem_create(unit, wred_mems, entry_words, 6,
   7201                                 _bcm_tr3_wred_profile[unit]));
   7202 
   7203     /* Create profile for VOQ_MOD_MAP table */
   7204     if (_bcm_tr3_voq_port_map_profile[unit] == NULL) {
   7205         _bcm_tr3_voq_port_map_profile[unit] = sal_alloc(sizeof(soc_profile_mem_t),
   7206                                                   "VOQ_PORT_MAP Profile Mem");
   7207         if (_bcm_tr3_voq_port_map_profile[unit] == NULL) {
   7208             return BCM_E_MEMORY;
   7209         }
   7210         soc_profile_mem_t_init(_bcm_tr3_voq_port_map_profile[unit]);
   7211     }
   7212     mem = VOQ_PORT_MAPm;
   7213     entry_words[0] = sizeof(voq_port_map_entry_t) / sizeof(uint32);
   7214     BCM_IF_ERROR_RETURN(soc_profile_mem_create(unit, &mem, entry_words, 1,
   7215                                            _bcm_tr3_voq_port_map_profile[unit]));
   7216    
   7217     sal_memset(&bst_callbks, 0, sizeof(_bcm_bst_device_handlers_t));
   7218     bst_callbks.resolve_index = &_bcm_tr3_bst_index_resolve;
   7219     bst_callbks.reverse_resolve_index = &_bcm_tr3_cosq_bst_map_resource_to_gport_cos;
   7220     BCM_IF_ERROR_RETURN(_bcm_bst_attach(unit, &bst_callbks));
   7221 
   7222     /* reserve resources ie schedulers and queues which are allocated by
   7223      * soc layer and no gport support is available for the ports. */
   7224     BCM_PBMP_CLEAR(mmu_info->gport_unavail_pbm);
   7225     PBMP_CE_ITER(unit, port) {
   7226         BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_reserve_gport_resources(unit, port));
   7227         BCM_PBMP_PORT_ADD(mmu_info->gport_unavail_pbm, port);
   7228     }
   7229     
   7230     PBMP_ITER(PBMP_AXP_ALL(unit), port) {
   7231         BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_reserve_gport_resources(unit, port));
   7232     }
   7233     
   7234     if (!mmu_info->curr_shared_limit) {
   7235         BCM_IF_ERROR_RETURN(soc_tr3_mmu_get_shared_size(unit,
   7236                                             &mmu_info->curr_shared_limit));
   7237     }
   7238     mmu_info->axp_ets_mode = 0;
   7239     
   7240 #ifdef BCM_WARM_BOOT_SUPPORT
   7241     if (SOC_WARM_BOOT(unit)) {
   7242         return bcm_tr3_cosq_reinit(unit);
   7243     } else {
   7244         BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_wb_alloc(unit));
   7245     }
   7246 #endif /* BCM_WARM_BOOT_SUPPORT */
   7247     /* Setup hsp gport and software structures */
   7248     PBMP_ALL_ITER(unit, port) {
   7249         if (IS_TR3_HSP_PORT(unit, port)) {
   7250             BCM_IF_ERROR_RETURN(_bcm_tr3_hsp_hierarchy_setup(unit, port));
   7251         }
   7252     }
   7253     /* Add default entries for PORT_COS_MAP memory profile */
   7254     BCM_IF_ERROR_RETURN(bcm_tr3_cosq_config_set(unit, numq));
   7255 
   7256     /* Add default entries for PRIO2COS_PROFILE register profile */
   7257     sal_memset(rval64s, 0, sizeof(rval64s));
   7258     prval64s[0] = rval64s;
   7259     profile_index = 0xffffffff;
   7260     PBMP_PORT_ITER(unit, port) {
   7261         if (profile_index == 0xffffffff) {
   7262             BCM_IF_ERROR_RETURN
   7263                 (soc_profile_reg_add(unit, _bcm_tr3_llfc_profile[unit],
   7264                                      prval64s, 16, &profile_index));
   7265         } else {
   7266             BCM_IF_ERROR_RETURN
   7267                 (soc_profile_reg_reference(unit, _bcm_tr3_llfc_profile[unit],
   7268                                            profile_index, 0));
   7269         }
   7270     }
   7271 
   7272     /* Add default entries for MMU_WRED_DROP_CURVE_PROFILE_x memory profile */
   7273     sal_memset(&entry_tcp_green, 0, sizeof(entry_tcp_green));
   7274     sal_memset(&entry_tcp_yellow, 0, sizeof(entry_tcp_yellow));
   7275     sal_memset(&entry_tcp_red, 0, sizeof(entry_tcp_red));
   7276     sal_memset(&entry_nontcp_green, 0, sizeof(entry_nontcp_green));
   7277     sal_memset(&entry_nontcp_yellow, 0, sizeof(entry_nontcp_yellow));
   7278     sal_memset(&entry_nontcp_red, 0, sizeof(entry_nontcp_red));
   7279     entries[0] = &entry_tcp_green;
   7280     entries[1] = &entry_tcp_yellow;
   7281     entries[2] = &entry_tcp_red;
   7282     entries[3] = &entry_nontcp_green;
   7283     entries[4] = &entry_nontcp_yellow;
   7284     entries[5] = &entry_nontcp_red;
   7285     for (ii = 0; ii < 6; ii++) {
   7286         soc_mem_field32_set(unit, wred_mems[ii], entries[ii], MIN_THDf, 0x7fff);
   7287         soc_mem_field32_set(unit, wred_mems[ii], entries[ii], MAX_THDf, 0x7fff);
   7288     }
   7289     profile_index = 0xffffffff;
   7290     wred_prof_count = soc_mem_index_count(unit, MMU_WRED_CONFIGm);
   7291     while (wred_prof_count) {
   7292         if (profile_index == 0xffffffff) {
   7293             BCM_IF_ERROR_RETURN
   7294                 (soc_profile_mem_add(unit, _bcm_tr3_wred_profile[unit],
   7295                                      entries, 1, &profile_index));
   7296         } else {
   7297             BCM_IF_ERROR_RETURN
   7298                 (soc_profile_mem_reference(unit,
   7299                                            _bcm_tr3_wred_profile[unit],
   7300                                            profile_index, 0));
   7301         }
   7302         wred_prof_count -= 1;
   7303     }
   7304 
   7305     /* Starting the curr_merger_index from 2,
   7306      *  since 0 is configured in all the FC_MAP_TBL2 by default,
   7307      *  so it might effect the traffic of other queues
   7308      */
   7309     mmu_info->curr_merger_index[0] = 2;
   7310     mmu_info->curr_merger_index[1] = 2;
   7311     mmu_info->curr_merger_index[2] = 2;
   7312     mmu_info->curr_merger_index[3] = 2;
   7313     return BCM_E_NONE;
   7314 }
   7315 
   7316 
   7317 /*
   7318  * Function:
   7319  *     bcm_tr3_cosq_config_get
   7320  * Purpose:
   7321  *     Get the number of cos queues
   7322  * Parameters:
   7323  *     unit - unit number
   7324  *     numq - (Output) number of cosq
   7325  * Returns:
   7326  *     BCM_E_XXX
   7327  */
   7328 int
   7329 bcm_tr3_cosq_config_get(int unit, int *numq)
   7330 {
   7331     if (numq != NULL) {
   7332         *numq = _TR3_NUM_COS(unit);
   7333     }
   7334 
   7335     return BCM_E_NONE;
   7336 }
   7337 
   7338 /*
   7339  * Function:
   7340  *     _bcm_tr3_cosq_mapping_set
   7341  * Purpose:
   7342  *     Set COS queue for the specified priority of an ingress port
   7343  * Parameters:
   7344  *     unit     - (IN) unit number
   7345  *     ing_port - (IN) ingress port
   7346  *     gport    - (IN) queue group GPORT identifier
   7347  *     priority - (IN) priority value to map
   7348  *     flags    - (IN) BCM_COSQ_GPORT_XXX_QUEUE_GROUP
   7349  *     gport    - (IN) queue group GPORT identifier
   7350  *     cosq     - (IN) COS queue number
   7351  * Returns:
   7352  *     BCM_E_XXX
   7353  */
   7354 STATIC int
   7355 _bcm_tr3_cosq_mapping_set(int unit, bcm_port_t ing_port, bcm_cos_t priority,
   7356                          uint32 flags, bcm_gport_t gport, bcm_cos_queue_t cosq)
   7357 {
   7358     bcm_port_t local_port, outport = -1;
   7359     bcm_cos_queue_t hw_cosq;
   7360     soc_field_t field = INVALIDf, field2 = INVALIDf;
   7361     cos_map_sel_entry_t cos_map_sel_entry;
   7362     port_cos_map_entry_t cos_map_entries[16];
   7363     void *entries[1];
   7364     uint32 old_index, new_index;
   7365     voq_cos_map_entry_t voq_cos_map;
   7366     _bcm_tr3_cosq_node_t *node = NULL;
   7367     _bcm_tr3_mmu_info_t *mmu_info;
   7368     int rv;
   7369 
   7370     if (priority < 0 || priority >= 16) {
   7371         return BCM_E_PARAM;
   7372     }
   7373 
   7374     BCM_IF_ERROR_RETURN
   7375         (_bcm_tr3_cosq_localport_resolve(unit, ing_port, &local_port));
   7376 
   7377     if (gport != -1) {
   7378         BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_localport_resolve(unit, gport, &outport));
   7379     }
   7380 
   7381     mmu_info = _bcm_tr3_mmu_info[unit];
   7382 
   7383     switch (flags) {
   7384     case BCM_COSQ_GPORT_UCAST_QUEUE_GROUP:
   7385         if (gport == -1) {
   7386             hw_cosq = cosq;
   7387         } else {
   7388             BCM_IF_ERROR_RETURN
   7389                 (_bcm_tr3_cosq_index_resolve
   7390                  (unit, gport, cosq, _BCM_TR3_COSQ_INDEX_STYLE_COS,
   7391                   NULL, &hw_cosq, NULL));
   7392 
   7393             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
   7394                 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) {
   7395                 BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_node_get(unit, gport, cosq, 
   7396                                             NULL, NULL, NULL, &node));
   7397 
   7398                 if (node->hw_index >= mmu_info->num_base_queues) {
   7399                     return BCM_E_PARAM;
   7400                 }
   7401             }
   7402         }
   7403 
   7404         if ((outport != -1) && (IS_HG_PORT(unit, outport))) {
   7405             field = HG_COSf;
   7406         } else {
   7407             field = UC_COS1f;
   7408         }
   7409         break;
   7410     case BCM_COSQ_GPORT_MCAST_QUEUE_GROUP:
   7411         if (gport == -1) {
   7412             hw_cosq = cosq;
   7413         } else {
   7414             BCM_IF_ERROR_RETURN
   7415                 (_bcm_tr3_cosq_index_resolve
   7416                  (unit, gport, cosq, _BCM_TR3_COSQ_INDEX_STYLE_COS,
   7417                   NULL, &hw_cosq, NULL));
   7418         }
   7419         field = MC_COS1f;
   7420         break;
   7421     case BCM_COSQ_GPORT_UCAST_QUEUE_GROUP | BCM_COSQ_GPORT_MCAST_QUEUE_GROUP:
   7422         if (gport == -1) {
   7423             hw_cosq = cosq;
   7424         } else {
   7425             return BCM_E_PARAM;
   7426         }
   7427         field = UC_COS1f;
   7428         field2 = MC_COS1f;
   7429         break;
   7430     case BCM_COSQ_GPORT_DESTMOD_UCAST_QUEUE_GROUP:
   7431     case (BCM_COSQ_GPORT_WITH_ID | BCM_COSQ_GPORT_DESTMOD_UCAST_QUEUE_GROUP):
   7432         if (gport == -1) {
   7433             hw_cosq = cosq;
   7434         } else {
   7435             BCM_IF_ERROR_RETURN
   7436                 (_bcm_tr3_cosq_index_resolve
   7437                 (unit, gport, cosq, _BCM_TR3_COSQ_INDEX_STYLE_COS,
   7438                 NULL, &hw_cosq, NULL));
   7439         }
   7440 
   7441         BCM_IF_ERROR_RETURN(
   7442             READ_VOQ_COS_MAPm(unit, MEM_BLOCK_ALL, priority, &voq_cos_map));
   7443         soc_mem_field32_get(unit, VOQ_COS_MAPm, &voq_cos_map,
   7444                                     VOQ_COS_USE_MODf);
   7445         
   7446         /* Setting the VOQ_PORT_BASE_SELECT,
   7447            so that BASE_QUEUE_NUM_1 is used for queue
   7448            calculation */
   7449 
   7450         soc_mem_field32_set(unit, VOQ_COS_MAPm, 
   7451                 &voq_cos_map, VOQ_PORT_BASE_SELECTf, 1);
   7452         soc_mem_field32_set(unit, VOQ_COS_MAPm, 
   7453                             &voq_cos_map, VOQ_COS_USE_MODf, 1);
   7454  
   7455         if (soc_mem_field32_get(unit, VOQ_COS_MAPm, &voq_cos_map, 
   7456                                             VOQ_COS_OFFSETf) != hw_cosq) {
   7457             soc_mem_field32_set(unit, VOQ_COS_MAPm, 
   7458                                 &voq_cos_map, VOQ_COS_OFFSETf, hw_cosq);
   7459         }
   7460 
   7461         BCM_IF_ERROR_RETURN(
   7462             soc_mem_write(unit, VOQ_COS_MAPm, MEM_BLOCK_ANY, priority,
   7463                           &voq_cos_map));
   7464         return BCM_E_NONE;
   7465         break;
   7466     default:
   7467         return BCM_E_PARAM;
   7468     }
   7469 
   7470     entries[0] = &cos_map_entries;
   7471 
   7472     if (local_port == CMIC_PORT(unit)) {
   7473         local_port = SOC_INFO(unit).cpu_hg_index;
   7474     }
   7475     BCM_IF_ERROR_RETURN
   7476         (READ_COS_MAP_SELm(unit, MEM_BLOCK_ANY, local_port,
   7477                            &cos_map_sel_entry));
   7478     old_index = soc_mem_field32_get(unit, COS_MAP_SELm, &cos_map_sel_entry,
   7479                                     SELECTf);
   7480     old_index *= 16;
   7481 
   7482     BCM_IF_ERROR_RETURN
   7483         (soc_profile_mem_get(unit, _bcm_tr3_cos_map_profile[unit],
   7484                              old_index, 16, entries));
   7485     soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[priority], field,
   7486                         hw_cosq);
   7487     if (field2 != INVALIDf) {
   7488         soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[priority],
   7489                             field2,hw_cosq);
   7490     }
   7491 
   7492     soc_mem_lock(unit, PORT_COS_MAPm);
   7493 
   7494     rv = soc_profile_mem_delete(unit, _bcm_tr3_cos_map_profile[unit],
   7495                                 old_index);
   7496 
   7497     if (BCM_FAILURE(rv)) {
   7498         soc_mem_unlock(unit, PORT_COS_MAPm);
   7499         return rv;
   7500     }
   7501 
   7502     rv = soc_profile_mem_add(unit, _bcm_tr3_cos_map_profile[unit], entries,
   7503                              16, &new_index);
   7504 
   7505     if (rv == SOC_E_RESOURCE) {
   7506         (void)soc_profile_mem_reference(unit, _bcm_tr3_cos_map_profile[unit],
   7507                                         old_index, 16);
   7508     }
   7509 
   7510     soc_mem_unlock(unit, PORT_COS_MAPm);
   7511 
   7512     if (BCM_FAILURE(rv)) {
   7513         return rv;
   7514     }
   7515 
   7516     soc_mem_field32_set(unit, COS_MAP_SELm, &cos_map_sel_entry, SELECTf,
   7517                         new_index / 16);
   7518     BCM_IF_ERROR_RETURN
   7519         (WRITE_COS_MAP_SELm(unit, MEM_BLOCK_ANY, local_port,
   7520                             &cos_map_sel_entry));
   7521 
   7522 #ifndef BCM_COSQ_HIGIG_MAP_DISABLE
   7523     if (IS_CPU_PORT(unit, local_port)) {
   7524         BCM_IF_ERROR_RETURN
   7525             (soc_mem_field32_modify(unit, COS_MAP_SELm,
   7526                                     SOC_INFO(unit).cpu_hg_index, SELECTf,
   7527                                     new_index / 16));
   7528     }
   7529 #endif /* BCM_COSQ_HIGIG_MAP_DISABLE */
   7530 
   7531     return BCM_E_NONE;
   7532 }
   7533 
   7534 /*
   7535  * Function:
   7536  *     bcm_tr3_cosq_mapping_set
   7537  * Purpose:
   7538  *     Set which cosq a given priority should fall into
   7539  * Parameters:
   7540  *     unit     - (IN) unit number
   7541  *     gport    - (IN) queue group GPORT identifier
   7542  *     priority - (IN) priority value to map
   7543  *     cosq     - (IN) COS queue to map to
   7544  * Returns:
   7545  *     BCM_E_XXX
   7546  */
   7547 
   7548 int
   7549 bcm_tr3_cosq_mapping_set(int unit, bcm_port_t port, bcm_cos_t priority,
   7550                          bcm_cos_queue_t cosq)
   7551 {
   7552     bcm_port_t local_port;
   7553     bcm_pbmp_t pbmp;
   7554 
   7555     BCM_PBMP_CLEAR(pbmp);
   7556 
   7557     if (port == -1) {
   7558         BCM_PBMP_ASSIGN(pbmp, PBMP_ALL(unit));
   7559     } else {
   7560         if (BCM_GPORT_IS_SET(port)) {
   7561             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
   7562                 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port) ||
   7563                 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) ||
   7564                 BCM_GPORT_IS_SCHEDULER(port)) {
   7565                 return BCM_E_PARAM;
   7566             } else if (BCM_GPORT_IS_LOCAL(port)) {
   7567                 local_port = BCM_GPORT_LOCAL_GET(port);
   7568             } else {
   7569                 return BCM_E_PARAM;
   7570             }
   7571         } else {
   7572             local_port = port;
   7573         }
   7574 
   7575         if (!SOC_PORT_VALID(unit, local_port)) {
   7576             return BCM_E_PORT;
   7577         }
   7578 
   7579         BCM_PBMP_PORT_ADD(pbmp, local_port);
   7580     }
   7581 
   7582     PBMP_ITER(pbmp, local_port) {
   7583         if (_bcm_tr3_cosq_port_has_ets(unit, local_port))
   7584 	    return BCM_E_PARAM;
   7585     }
   7586 
   7587     if ((cosq < 0) || (cosq >= _TR3_NUM_COS(unit))) {
   7588         return BCM_E_PARAM;
   7589     }
   7590 
   7591     PBMP_ITER(pbmp, local_port) {
   7592         if (IS_LB_PORT(unit, local_port) || IS_HG_PORT(unit, local_port)) {
   7593             continue;
   7594         }
   7595 
   7596         /* If no ETS/port, map the int prio symmetrically for ucast and
   7597          * mcast */
   7598         BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_mapping_set(unit, local_port, 
   7599             priority,
   7600             BCM_COSQ_GPORT_UCAST_QUEUE_GROUP | BCM_COSQ_GPORT_MCAST_QUEUE_GROUP,
   7601             -1, cosq));
   7602     }
   7603 
   7604     PBMP_ITER(pbmp, local_port) {
   7605         if (IS_HG_PORT(unit, local_port)) {
   7606             BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_mapping_set(unit, local_port,
   7607                 priority,
   7608                 BCM_COSQ_GPORT_UCAST_QUEUE_GROUP | BCM_COSQ_GPORT_MCAST_QUEUE_GROUP,
   7609                 -1, cosq));
   7610         }
   7611     }
   7612 
   7613     return BCM_E_NONE;
   7614 }
   7615 
   7616 /*
   7617  * Function:
   7618  *     bcm_tr3_cosq_mapping_get
   7619  * Purpose:
   7620  *     Determine which COS queue a given priority currently maps to.
   7621  * Parameters:
   7622  *     unit     - (IN) unit number
   7623  *     gport    - (IN) queue group GPORT identifier
   7624  *     priority - (IN) priority value to map
   7625  *     cosq     - (OUT) COS queue to map to
   7626  * Returns:
   7627  *     BCM_E_XXX
   7628  */
   7629 int
   7630 _bcm_tr3_cosq_mapping_get(int unit, bcm_port_t ing_port, bcm_cos_t priority,
   7631                           uint32 flags, bcm_gport_t *gport,
   7632                           bcm_cos_queue_t *cosq)
   7633 {
   7634     _bcm_tr3_mmu_info_t *mmu_info;
   7635     _bcm_tr3_cosq_port_info_t *port_info;
   7636     _bcm_tr3_cosq_node_t *node;
   7637     bcm_port_t local_port;
   7638     bcm_cos_queue_t hw_cosq = BCM_COS_INVALID;
   7639     int index, ii;
   7640     cos_map_sel_entry_t cos_map_sel_entry;
   7641     voq_cos_map_entry_t voq_cos_map;
   7642     void *entry_p;
   7643 
   7644     if (priority < 0 || priority >= 16) {
   7645         return BCM_E_PARAM;
   7646     }
   7647 
   7648     if (flags != BCM_COSQ_GPORT_UCAST_QUEUE_GROUP &&
   7649         flags != BCM_COSQ_GPORT_MCAST_QUEUE_GROUP &&
   7650         flags != (BCM_COSQ_GPORT_DESTMOD_UCAST_QUEUE_GROUP |
   7651                   BCM_COSQ_GPORT_WITH_ID) &&
   7652         flags != BCM_COSQ_GPORT_DESTMOD_UCAST_QUEUE_GROUP) {
   7653         return BCM_E_PARAM;
   7654     }
   7655 
   7656     BCM_IF_ERROR_RETURN
   7657         (_bcm_tr3_cosq_localport_resolve(unit, ing_port, &local_port));
   7658 
   7659     if (gport) {
   7660         *gport = BCM_GPORT_INVALID;
   7661     }
   7662 
   7663     *cosq = BCM_COS_INVALID;
   7664 
   7665     if (local_port == CMIC_PORT(unit)) {
   7666         BCM_IF_ERROR_RETURN
   7667             (READ_COS_MAP_SELm(unit, MEM_BLOCK_ANY, SOC_INFO(unit).cpu_hg_index,
   7668                                &cos_map_sel_entry));
   7669     } else {
   7670         BCM_IF_ERROR_RETURN
   7671             (READ_COS_MAP_SELm(unit, MEM_BLOCK_ANY, local_port,
   7672                                &cos_map_sel_entry));
   7673     }
   7674     index = soc_mem_field32_get(unit, COS_MAP_SELm, &cos_map_sel_entry,
   7675                                 SELECTf);
   7676     index *= 16;
   7677 
   7678     mmu_info = _bcm_tr3_mmu_info[unit];
   7679     port_info = &mmu_info->port_info[local_port];
   7680 
   7681     switch (flags) {
   7682     case BCM_COSQ_GPORT_UCAST_QUEUE_GROUP:
   7683         entry_p = SOC_PROFILE_MEM_ENTRY(unit, _bcm_tr3_cos_map_profile[unit],
   7684                                     port_cos_map_entry_t *,
   7685                                     index + priority);
   7686 
   7687         hw_cosq = soc_mem_field32_get(unit, PORT_COS_MAPm, entry_p, UC_COS1f);
   7688         if (gport) {
   7689             for (ii = port_info->uc_base; ii < port_info->uc_limit; ii++) {
   7690                 node = &mmu_info->queue_node[ii];
   7691                 if (node->numq > 0 && node->hw_cosq == hw_cosq) {
   7692                     *gport = node->gport;
   7693                     *cosq = 0;
   7694                     break;
   7695                 }
   7696             }
   7697             if (ii == port_info->uc_limit) {
   7698                 return BCM_E_NOT_FOUND;
   7699             }
   7700         }
   7701         break;
   7702     case BCM_COSQ_GPORT_MCAST_QUEUE_GROUP:
   7703         entry_p = SOC_PROFILE_MEM_ENTRY(unit, _bcm_tr3_cos_map_profile[unit],
   7704                                     port_cos_map_entry_t *,
   7705                                     index + priority);
   7706 
   7707         hw_cosq = soc_mem_field32_get(unit, PORT_COS_MAPm, entry_p, MC_COS1f);
   7708         if (gport) {
   7709             for (ii = port_info->mc_base; ii < port_info->mc_limit; ii++) {
   7710                 node = &mmu_info->mc_queue_node[ii];
   7711                 if (node->numq > 0 && node->hw_cosq == hw_cosq) {
   7712                     *gport = node->gport;
   7713                     *cosq = 0;
   7714                     break;
   7715                 }
   7716             }
   7717             if (ii == port_info->mc_limit) {
   7718                 return BCM_E_NOT_FOUND;
   7719             }
   7720         }
   7721         break;
   7722     case BCM_COSQ_GPORT_DESTMOD_UCAST_QUEUE_GROUP:
   7723     case (BCM_COSQ_GPORT_WITH_ID | BCM_COSQ_GPORT_DESTMOD_UCAST_QUEUE_GROUP):
   7724         BCM_IF_ERROR_RETURN(
   7725             READ_VOQ_COS_MAPm(unit, MEM_BLOCK_ALL, priority, &voq_cos_map));
   7726         hw_cosq = soc_mem_field32_get(unit, VOQ_COS_MAPm, 
   7727                                         &voq_cos_map, VOQ_COS_OFFSETf);
   7728         if (gport) {
   7729             for (ii = mmu_info->num_base_queues; 
   7730                             ii < _BCM_TR3_NUM_L2_UC_LEAVES; ii++) {
   7731                 
   7732                 node = &mmu_info->queue_node[ii];
   7733                 if ((node->in_use == FALSE) || (node->local_port == local_port)) {
   7734                     continue;
   7735                 }
   7736                 
   7737                 if (node->hw_cosq == hw_cosq) {
   7738                     *gport = node->gport;
   7739                     break;
   7740                 }
   7741             }
   7742             if (ii == _BCM_TR3_NUM_L2_UC_LEAVES) {
   7743                 return BCM_E_NOT_FOUND;
   7744             }   
   7745         }
   7746         break;
   7747     /* Keeping this as safe check, keep this intentionally */
   7748     /* coverity[dead_error_begin] */
   7749     default:
   7750         break;
   7751     }
   7752 
   7753     if (gport &&
   7754         (*gport == BCM_GPORT_INVALID) && (*cosq == BCM_COS_INVALID)) {
   7755         return BCM_E_NOT_FOUND;
   7756     }
   7757 
   7758     *cosq = hw_cosq;
   7759 
   7760     return BCM_E_NONE;
   7761 }
   7762 
   7763 int
   7764 bcm_tr3_cosq_mapping_get(int unit, bcm_port_t port, bcm_cos_t priority,
   7765                         bcm_cos_queue_t *cosq)
   7766 {
   7767     bcm_port_t local_port;
   7768     bcm_pbmp_t pbmp;
   7769 
   7770     BCM_PBMP_CLEAR(pbmp);
   7771 
   7772     if (port == -1) {
   7773         BCM_PBMP_ASSIGN(pbmp, PBMP_ALL(unit));
   7774     } else {
   7775         if (BCM_GPORT_IS_SET(port)) {
   7776             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
   7777                 BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port) ||
   7778                 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) ||
   7779                 BCM_GPORT_IS_SCHEDULER(port)) {
   7780                 return BCM_E_PARAM;
   7781             } else if (BCM_GPORT_IS_LOCAL(port)) {
   7782                 local_port = BCM_GPORT_LOCAL_GET(port);
   7783             } else {
   7784                 return BCM_E_PARAM;
   7785             }
   7786         } else {
   7787             local_port = port;
   7788         }
   7789 
   7790         if (!SOC_PORT_VALID(unit, local_port)) {
   7791             return BCM_E_PORT;
   7792         }
   7793 
   7794         BCM_PBMP_PORT_ADD(pbmp, local_port);
   7795     }
   7796 
   7797     PBMP_ITER(pbmp, local_port) {
   7798         if (IS_LB_PORT(unit, local_port)) {
   7799             continue;
   7800         }
   7801 
   7802         BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_mapping_get(unit, local_port, 
   7803                  priority, BCM_COSQ_GPORT_UCAST_QUEUE_GROUP, NULL, cosq));
   7804         break;
   7805     }    
   7806 
   7807     return BCM_E_NONE;
   7808 }
   7809 
   7810 int
   7811 bcm_tr3_cosq_gport_mapping_set(int unit, bcm_port_t ing_port,
   7812                               bcm_cos_t int_pri, uint32 flags,
   7813                               bcm_gport_t gport, bcm_cos_queue_t cosq)
   7814 {
   7815     return _bcm_tr3_cosq_mapping_set(unit, ing_port, int_pri, flags, gport,
   7816                                     cosq);
   7817 }
   7818 
   7819 int
   7820 bcm_tr3_cosq_gport_mapping_get(int unit, bcm_port_t ing_port,
   7821                               bcm_cos_t int_pri, uint32 flags,
   7822                               bcm_gport_t *gport, bcm_cos_queue_t *cosq)
   7823 {
   7824     if (gport == NULL || cosq == NULL) {
   7825         return BCM_E_PARAM;
   7826     }
   7827 
   7828     return _bcm_tr3_cosq_mapping_get(unit, ing_port, int_pri, flags, gport,
   7829                                     cosq);
   7830 }
   7831 
   7832 /*
   7833  * Function:
   7834  *     bcm_tr3_cosq_port_sched_set
   7835  * Purpose:
   7836  *     Set up class-of-service policy and corresponding weights and delay
   7837  * Parameters:
   7838  *     unit    - (IN) unit number
   7839  *     pbm     - (IN) port bitmap
   7840  *     mode    - (IN) Scheduling mode (BCM_COSQ_xxx)
   7841  *     weights - (IN) Weights for each COS queue
   7842  *     delay   - This parameter is not used
   7843  * Returns:
   7844  *     BCM_E_XXX
   7845  */
   7846 int
   7847 bcm_tr3_cosq_port_sched_set(int unit, bcm_pbmp_t pbm,
   7848                            int mode, const int *weights, int delay)
   7849 {
   7850     bcm_port_t port;
   7851     int num_weights, i;
   7852 
   7853     BCM_PBMP_ITER(pbm, port) {
   7854         num_weights = _TR3_NUM_COS(unit);
   7855         if (mode == BCM_COSQ_STRICT) {
   7856             for (i = 0; i < num_weights; i++) {
   7857                 BCM_IF_ERROR_RETURN
   7858                     (_bcm_tr3_cosq_sched_set(unit, port, i, mode, weights[i], 1));
   7859             }
   7860         } else {
   7861             for (i = (num_weights-1); i >= 0; i--) {
   7862                 BCM_IF_ERROR_RETURN
   7863                     (_bcm_tr3_cosq_sched_set(unit, port, i, mode, weights[i], 1));
   7864             }
   7865         }
   7866     }
   7867 
   7868     return BCM_E_NONE;
   7869 }
   7870 
   7871 /*
   7872  * Function:
   7873  *     bcm_tr3_cosq_port_sched_get
   7874  * Purpose:
   7875  *     Retrieve class-of-service policy and corresponding weights and delay
   7876  * Parameters:
   7877  *     unit     - (IN) unit number
   7878  *     pbm      - (IN) port bitmap
   7879  *     mode     - (OUT) Scheduling mode (BCM_COSQ_XXX)
   7880  *     weights  - (OUT) Weights for each COS queue
   7881  *     delay    - This parameter is not used
   7882  * Returns:
   7883  *     BCM_E_XXX
   7884  */
   7885 int
   7886 bcm_tr3_cosq_port_sched_get(int unit, bcm_pbmp_t pbm,
   7887                            int *mode, int *weights, int *delay)
   7888 {
   7889     bcm_port_t port;
   7890     int num_weights, i;
   7891 
   7892     BCM_PBMP_ITER(pbm, port) {
   7893         num_weights = _TR3_NUM_COS(unit);
   7894         for (i = 0 ; i < num_weights; i++) {
   7895             BCM_IF_ERROR_RETURN(
   7896                 _bcm_tr3_cosq_sched_get(unit, port, i, mode, &weights[i]));
   7897         }
   7898     }
   7899 
   7900     return BCM_E_NONE;
   7901 }
   7902 
   7903 /*
   7904  * Function:
   7905  *     bcm_tr3_cosq_sched_weight_max_get
   7906  * Purpose:
   7907  *     Retrieve maximum weights for given COS policy
   7908  * Parameters:
   7909  *     unit    - (IN) unit number
   7910  *     mode    - (IN) Scheduling mode (BCM_COSQ_xxx)
   7911  *     weight_max - (OUT) Maximum weight for COS queue.
   7912  * Returns:
   7913  *     BCM_E_XXX
   7914  */
   7915 int
   7916 bcm_tr3_cosq_sched_weight_max_get(int unit, int mode, int *weight_max)
   7917 {
   7918     switch (mode) {
   7919     case BCM_COSQ_STRICT:
   7920         *weight_max = BCM_COSQ_WEIGHT_STRICT;
   7921         break;
   7922     case BCM_COSQ_ROUND_ROBIN:
   7923         *weight_max = 1;
   7924         break;
   7925     case BCM_COSQ_WEIGHTED_ROUND_ROBIN:
   7926         if (soc_property_get(unit, spn_BCM5664X_WRR_GRANULARITY_1, 0)) {
   7927             *weight_max = (1 << 7) - 1;
   7928         } else {
   7929             *weight_max = (1 << 6) - 1;
   7930         }
   7931         break;
   7932     case BCM_COSQ_DEFICIT_ROUND_ROBIN:
   7933         *weight_max = (1 << 7) - 1;
   7934         break;
   7935     default:
   7936         return BCM_E_PARAM;
   7937     }
   7938 
   7939     return BCM_E_NONE;
   7940 }
   7941 
   7942 /*
   7943  * Function:
   7944  *     bcm_tr3_cosq_bandwidth_set
   7945  * Purpose:
   7946  *     Configure COS queue bandwidth control
   7947  * Parameters:
   7948  *     unit          - (IN) unit number
   7949  *     port          - (IN) port number or GPORT identifier
   7950  *     cosq          - (IN) COS queue number
   7951  *     min_quantum   - (IN)
   7952  *     max_quantum   - (IN)
   7953  *     burst_quantum - (IN)
   7954  *     flags         - (IN)
   7955  * Returns:
   7956  *     BCM_E_XXX
   7957  * Notes:
   7958  *     If port is any form of local port, cosq is the hardware queue index.
   7959  */
   7960 int
   7961 bcm_tr3_cosq_port_bandwidth_set(int unit, bcm_port_t port,
   7962                                bcm_cos_queue_t cosq,
   7963                                uint32 min_quantum, uint32 max_quantum,
   7964                                uint32 burst_quantum, uint32 flags)
   7965 {
   7966     uint32 burst_min, burst_max;
   7967 
   7968     if (cosq < 0) {
   7969         return BCM_E_PARAM;
   7970     }
   7971 
   7972     burst_min = (min_quantum > 0) ?
   7973           _bcm_td_default_burst_size(unit, port, min_quantum) : 0;
   7974 
   7975     burst_max = (max_quantum > 0) ?
   7976           _bcm_td_default_burst_size(unit, port, max_quantum) : 0;
   7977 
   7978     return _bcm_tr3_cosq_bucket_set(unit, port, cosq, min_quantum, max_quantum,
   7979                                     burst_min, burst_max, flags);
   7980 }
   7981 
   7982 /*
   7983  * Function:
   7984  *     bcm_tr3_cosq_bandwidth_get
   7985  * Purpose:
   7986  *     Get COS queue bandwidth control configuration
   7987  * Parameters:
   7988  *     unit          - (IN) unit number
   7989  *     port          - (IN) port number or GPORT identifier
   7990  *     cosq          - (IN) COS queue number
   7991  *     min_quantum   - (OUT)
   7992  *     max_quantum   - (OUT)
   7993  *     burst_quantum - (OUT)
   7994  *     flags         - (OUT)
   7995  * Returns:
   7996  *     BCM_E_XXX
   7997  * Notes:
   7998  *     If port is any form of local port, cosq is the hardware queue index.
   7999  */
   8000 int
   8001 bcm_tr3_cosq_port_bandwidth_get(int unit, bcm_port_t port,
   8002                                bcm_cos_queue_t cosq,
   8003                                uint32 *min_quantum, uint32 *max_quantum,
   8004                                uint32 *burst_quantum, uint32 *flags)
   8005 {
   8006     uint32 kbit_burst_min;
   8007 
   8008     if (cosq < -1) {
   8009         return BCM_E_PARAM;
   8010     }
   8011 
   8012     BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_bucket_get(unit, port, cosq,
   8013                         min_quantum, max_quantum, &kbit_burst_min,
   8014                         burst_quantum, flags));
   8015     return BCM_E_NONE;
   8016 }
   8017 
   8018 int
   8019 bcm_tr3_cosq_port_pps_set(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   8020                          int pps)
   8021 {
   8022     uint32 min, max, burst, burst_min, flags;
   8023     bcm_port_t  local_port = port;
   8024     
   8025     if (!IS_CPU_PORT(unit, port)) {
   8026         return BCM_E_PORT;
   8027     } else if (cosq < 0 || cosq >= NUM_CPU_COSQ(unit)) {
   8028         return BCM_E_PARAM;
   8029     }
   8030 
   8031     if (_bcm_tr3_cosq_port_has_ets(unit, port)) {
   8032         BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_l2_gport(unit, port, cosq, 
   8033                                             _BCM_TR3_NODE_MCAST, &port, NULL));
   8034         cosq = 0;
   8035     }
   8036 
   8037     BCM_IF_ERROR_RETURN
   8038         (_bcm_tr3_cosq_bucket_get(unit, port, cosq, &min, &max, &burst_min,
   8039                                 &burst, &flags));
   8040     
   8041     min = pps;
   8042     burst_min = (min > 0) ?
   8043           _bcm_td_default_burst_size(unit, local_port, min) : 0;
   8044     burst = burst_min;
   8045 
   8046     return _bcm_tr3_cosq_bucket_set(unit, port, cosq, min, pps, burst_min, burst,
   8047                                     flags | BCM_COSQ_BW_PACKET_MODE);
   8048 }
   8049 
   8050 int
   8051 bcm_tr3_cosq_port_pps_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   8052                          int *pps)
   8053 {
   8054     uint32 min, max, burst, flags;
   8055 
   8056     if (!IS_CPU_PORT(unit, port)) {
   8057         return BCM_E_PORT;
   8058     } else if (cosq < 0 || cosq >= NUM_CPU_COSQ(unit)) {
   8059         return BCM_E_PARAM;
   8060     }
   8061 
   8062     if (_bcm_tr3_cosq_port_has_ets(unit, port)) {
   8063         BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_l2_gport(unit, port, cosq,
   8064                                           _BCM_TR3_NODE_MCAST, &port, NULL));
   8065         cosq = 0;
   8066     }
   8067 
   8068     BCM_IF_ERROR_RETURN
   8069         (_bcm_tr3_cosq_bucket_get(unit, port, cosq, &min, &max, &burst, &burst,
   8070                                   &flags));
   8071     *pps = max;
   8072 
   8073     return BCM_E_NONE;
   8074 }
   8075 
   8076 int
   8077 bcm_tr3_cosq_port_burst_set(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   8078                            int burst)
   8079 {
   8080     uint32 min, max, cur_burst, flags;
   8081 
   8082     if (!IS_CPU_PORT(unit, port)) {
   8083         return BCM_E_PORT;
   8084     } else if (cosq < 0 || cosq >= NUM_CPU_COSQ(unit)) {
   8085         return BCM_E_PARAM;
   8086     }
   8087 
   8088     if (_bcm_tr3_cosq_port_has_ets(unit, port)) {
   8089         BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_l2_gport(unit, port, cosq,
   8090                                                 _BCM_TR3_NODE_MCAST, &port, NULL));
   8091         cosq = 0;
   8092     }
   8093 
   8094     /* Get the current PPS and BURST settings */
   8095     BCM_IF_ERROR_RETURN
   8096         (_bcm_tr3_cosq_bucket_get(unit, port, cosq, &min, &max, &cur_burst,
   8097                                   &cur_burst, &flags));
   8098 
   8099     /* Replace the current BURST setting, keep PPS the same */
   8100     return _bcm_tr3_cosq_bucket_set(unit, port, cosq, min, max, burst, burst,
   8101                                     flags | BCM_COSQ_BW_PACKET_MODE);
   8102 }
   8103 
   8104 int
   8105 bcm_tr3_cosq_port_burst_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   8106                            int *burst)
   8107 {
   8108     uint32 min, max, cur_burst, cur_burst_min, flags;
   8109 
   8110     if (!IS_CPU_PORT(unit, port)) {
   8111         return BCM_E_PORT;
   8112     } else if (cosq < 0 || cosq >= NUM_CPU_COSQ(unit)) {
   8113         return BCM_E_PARAM;
   8114     }
   8115 
   8116     if (_bcm_tr3_cosq_port_has_ets(unit, port)) {
   8117         BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_l2_gport(unit, port, cosq, 
   8118                                             _BCM_TR3_NODE_MCAST, &port, NULL));
   8119         cosq = 0;
   8120     }
   8121 
   8122     BCM_IF_ERROR_RETURN
   8123         (_bcm_tr3_cosq_bucket_get(unit, port, cosq, &min, &max, 
   8124                                   &cur_burst_min, &cur_burst, &flags));
   8125     *burst = cur_burst;
   8126 
   8127     return BCM_E_NONE;
   8128 }
   8129 
   8130 int
   8131 bcm_tr3_cosq_discard_set(int unit, uint32 flags)
   8132 {
   8133     bcm_port_t port;
   8134     int pool;
   8135     _bcm_tr3_mmu_info_t *mmu_info;
   8136 
   8137     if ((mmu_info = _bcm_tr3_mmu_info[unit]) == NULL) {
   8138         return BCM_E_INIT;
   8139     }
   8140 
   8141     if (flags & ~(BCM_COSQ_DISCARD_DEVICE |
   8142                   BCM_COSQ_DISCARD_NONTCP |
   8143                   BCM_COSQ_DISCARD_COLOR_ALL |
   8144                   BCM_COSQ_DISCARD_TCP |
   8145                   BCM_COSQ_DISCARD_COLOR_GREEN |
   8146                   BCM_COSQ_DISCARD_COLOR_YELLOW |
   8147                   BCM_COSQ_DISCARD_COLOR_RED |
   8148                   BCM_COSQ_DISCARD_CAP_AVERAGE |
   8149                   BCM_COSQ_DISCARD_ENABLE |
   8150                   BCM_COSQ_DISCARD_MARK_CONGESTION)) {
   8151         return BCM_E_PARAM;
   8152     }
   8153     
   8154     flags &= ~(BCM_COSQ_DISCARD_NONTCP | BCM_COSQ_DISCARD_COLOR_ALL);
   8155 
   8156     PBMP_PORT_ITER(unit, port) {
   8157         for (pool = 0; pool < 4; pool++) {
   8158             BCM_IF_ERROR_RETURN
   8159                 (_bcm_tr3_cosq_wred_set(unit, port, pool, flags, 0, 0, 0, 0,
   8160                                         FALSE, BCM_COSQ_DISCARD_PORT));
   8161         }
   8162     }
   8163 
   8164     return BCM_E_NONE;
   8165 }
   8166 
   8167 int
   8168 bcm_tr3_cosq_discard_get(int unit, uint32 *flags)
   8169 {
   8170     bcm_port_t port;
   8171 
   8172     PBMP_PORT_ITER(unit, port) {
   8173         *flags = 0;
   8174         /* use setting from hardware cosq index 0 of the first port */
   8175         return _bcm_tr3_cosq_wred_get(unit, port, 0, flags, NULL, NULL, NULL,
   8176                                      NULL, BCM_COSQ_DISCARD_PORT);
   8177     }
   8178 
   8179     return BCM_E_NOT_FOUND;
   8180 }
   8181 
   8182 /*
   8183  * Function:
   8184  *     bcm_tr3_cosq_discard_port_set
   8185  * Purpose:
   8186  *     Configure port WRED setting
   8187  * Parameters:
   8188  *     unit          - (IN) unit number
   8189  *     port          - (IN) port number or GPORT identifier
   8190  *     cosq          - (IN) COS queue number
   8191  *     color         - (IN)
   8192  *     drop_start    - (IN)
   8193  *     drop_slot     - (IN)
   8194  *     average_time  - (IN)
   8195  * Returns:
   8196  *     BCM_E_XXX
   8197  * Notes:
   8198  *     If port is any form of local port, cosq is the hardware queue index.
   8199  */
   8200 int
   8201 bcm_tr3_cosq_discard_port_set(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   8202                              uint32 color, int drop_start, int drop_slope,
   8203                              int average_time)
   8204 {
   8205     bcm_port_t local_port;
   8206     bcm_pbmp_t pbmp;
   8207     int gain;
   8208     uint32 min_thresh, max_thresh, shared_limit;
   8209     uint32 rval, bits;
   8210     int numq, i, flags = 0;
   8211 
   8212     if (drop_start < 0 || drop_start > 100 ||
   8213         drop_slope < 0 || drop_slope > 90) {
   8214         return BCM_E_PARAM;
   8215     }
   8216 
   8217     /*
   8218      * average queue size is reculated every 8us, the formula is
   8219      * avg_qsize(t + 1) =
   8220      *     avg_qsize(t) + (cur_qsize - avg_qsize(t)) / (2 ** gain)
   8221      * gain = log2(average_time / 8)
   8222      */
   8223     bits = (average_time / 8) & 0xffff;
   8224     if (bits != 0) {
   8225         bits |= bits >> 1;
   8226         bits |= bits >> 2;
   8227         bits |= bits >> 4;
   8228         bits |= bits >> 8;
   8229         gain = _shr_popcount(bits) - 1;
   8230     } else {
   8231         gain = 0;
   8232     }
   8233 
   8234     /*
   8235      * per-port cell limit may be disabled.
   8236      * per-port per-cos cell limit may be set to use dynamic method.
   8237      * therefore drop_start percentage is based on per-device total shared
   8238      * cells.
   8239      */
   8240     BCM_IF_ERROR_RETURN(READ_OP_BUFFER_SHARED_LIMIT_CELLr(unit, &rval));
   8241     shared_limit = soc_reg_field_get(unit, OP_BUFFER_SHARED_LIMIT_CELLr,
   8242                                      rval, OP_BUFFER_SHARED_LIMIT_CELLf);
   8243     min_thresh = drop_start * shared_limit / 100;
   8244 
   8245     /* Calculate the max threshold. For a given slope (angle in
   8246      * degrees), determine how many packets are in the range from
   8247      * 0% drop probability to 100% drop probability. Add that
   8248      * number to the min_treshold to the the max_threshold.
   8249      */
   8250     max_thresh = min_thresh + _bcm_tr3_angle_to_cells(drop_slope);
   8251     if (max_thresh > TR3_CELL_FIELD_MAX) {
   8252         max_thresh = TR3_CELL_FIELD_MAX;
   8253     }
   8254 
   8255     if (BCM_GPORT_IS_SET(port)) {
   8256         if (cosq == -1) {
   8257             cosq = 0;
   8258             flags = BCM_COSQ_DISCARD_PORT;
   8259         }
   8260         numq = 1;
   8261         for (i = 0; i < numq; i++) {
   8262             BCM_IF_ERROR_RETURN
   8263                 (_bcm_tr3_cosq_wred_set(unit, port, cosq + i, color,
   8264                                        min_thresh, max_thresh, 100, gain,
   8265                                        TRUE, flags));
   8266         }
   8267     } else {
   8268         if (port == -1) {
   8269             BCM_PBMP_ASSIGN(pbmp, PBMP_PORT_ALL(unit));
   8270         } else if (!SOC_PORT_VALID(unit, port)) {
   8271             return BCM_E_PORT;
   8272         } else {
   8273             BCM_PBMP_PORT_SET(pbmp, port);
   8274         }
   8275 
   8276         BCM_PBMP_ITER(pbmp, local_port) {
   8277             if (cosq == -1) {
   8278                 BCM_IF_ERROR_RETURN
   8279                     (_bcm_tr3_cosq_index_resolve(unit, local_port, cosq,
   8280                                                 _BCM_TR3_COSQ_INDEX_STYLE_WRED,
   8281                                                 NULL, NULL, &numq));
   8282                 cosq = 0;
   8283             } else {
   8284                 numq = 1;
   8285             }
   8286             for (i = 0; i < numq; i++) {
   8287                 BCM_IF_ERROR_RETURN
   8288                     (_bcm_tr3_cosq_wred_set(unit, local_port, cosq + i,
   8289                                            color, min_thresh, max_thresh, 100,
   8290                                            gain, TRUE, 0));
   8291             }
   8292         }
   8293     }
   8294 
   8295     return BCM_E_NONE;
   8296 }
   8297 
   8298 /*
   8299  * Function:
   8300  *     bcm_tr3_cosq_discard_port_get
   8301  * Purpose:
   8302  *     Get port WRED setting
   8303  * Parameters:
   8304  *     unit          - (IN) unit number
   8305  *     port          - (IN) port number or GPORT identifier
   8306  *     cosq          - (IN) COS queue number
   8307  *     color         - (OUT)
   8308  *     drop_start    - (OUT)
   8309  *     drop_slot     - (OUT)
   8310  *     average_time  - (OUT)
   8311  * Returns:
   8312  *     BCM_E_XXX
   8313  * Notes:
   8314  *     If port is any form of local port, cosq is the hardware queue index.
   8315  */
   8316 int
   8317 bcm_tr3_cosq_discard_port_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   8318                              uint32 color, int *drop_start, int *drop_slope,
   8319                              int *average_time)
   8320 {
   8321     bcm_port_t local_port;
   8322     bcm_pbmp_t pbmp;
   8323     int gain, drop_prob;
   8324     uint32 min_thresh, max_thresh, shared_limit;
   8325     uint32 rval;
   8326 
   8327     if (drop_start == NULL || drop_slope == NULL || average_time == NULL) {
   8328         return BCM_E_PARAM;
   8329     }
   8330 
   8331     if (BCM_GPORT_IS_SET(port)) {
   8332         local_port = port;
   8333     } else {
   8334         if (port == -1) {
   8335             BCM_PBMP_ASSIGN(pbmp, PBMP_PORT_ALL(unit));
   8336         } else if (!SOC_PORT_VALID(unit, port)) {
   8337             return BCM_E_PORT;
   8338         } else {
   8339             BCM_PBMP_PORT_SET(pbmp, port);
   8340         }
   8341         BCM_PBMP_ITER(pbmp, local_port) {
   8342             break;
   8343         }
   8344     }
   8345 
   8346     BCM_IF_ERROR_RETURN
   8347         (_bcm_tr3_cosq_wred_get(unit, local_port, cosq == -1 ? 0 : cosq,
   8348                                &color, &min_thresh, &max_thresh, &drop_prob,
   8349                                &gain, 0));
   8350 
   8351     /*
   8352      * average queue size is reculated every 4us, the formula is
   8353      * avg_qsize(t + 1) =
   8354      *     avg_qsize(t) + (cur_qsize - avg_qsize(t)) / (2 ** gain)
   8355      */
   8356     *average_time = (1 << gain) * 4;
   8357 
   8358     /*
   8359      * per-port cell limit may be disabled.
   8360      * per-port per-cos cell limit may be set to use dynamic method.
   8361      * therefore drop_start percentage is based on per-device total shared
   8362      * cells.
   8363      */
   8364     BCM_IF_ERROR_RETURN(READ_OP_BUFFER_SHARED_LIMIT_CELLr(unit, &rval));
   8365     shared_limit = soc_reg_field_get(unit, OP_BUFFER_SHARED_LIMIT_CELLr,
   8366                                      rval, OP_BUFFER_SHARED_LIMIT_CELLf);
   8367 
   8368     if (min_thresh > shared_limit) {
   8369         min_thresh = shared_limit;
   8370     }
   8371 
   8372     if (max_thresh > shared_limit) {
   8373         max_thresh = shared_limit;
   8374     }
   8375 
   8376     *drop_start = min_thresh * 100 / shared_limit;
   8377 
   8378     /* Calculate the slope using the min and max threshold.
   8379      * The angle is calculated knowing drop probability at min
   8380      * threshold is 0% and drop probability at max threshold is 100%.
   8381      */
   8382     *drop_slope = _bcm_tr3_cells_to_angle(max_thresh - min_thresh);
   8383 
   8384     return BCM_E_NONE;
   8385 }
   8386 
   8387 STATIC int
   8388 _bcm_tr3_distribute_u64(uint64 value, uint64 *l, uint64 *r)
   8389 {
   8390     uint64 tmp, tmp1;
   8391 
   8392     tmp = value;
   8393     COMPILER_64_SHR(tmp, 1);
   8394     *l = tmp;
   8395 
   8396     COMPILER_64_SET(tmp1, 0, 1);
   8397     COMPILER_64_AND(tmp1, value);
   8398     COMPILER_64_ADD_64(tmp1, tmp);
   8399     *r = tmp1;
   8400     return 0;
   8401 }
   8402 
   8403 
   8404 int
   8405 bcm_tr3_cosq_node_stat_init(int unit, _bcm_tr3_cosq_node_t *node)
   8406 {
   8407 
   8408     bcm_cosq_stat_t stat;
   8409     uint64          val64;
   8410 
   8411     COMPILER_64_ZERO(val64);
   8412     
   8413     if(node->level == SOC_TR3_NODE_LVL_L2){
   8414         for (stat = bcmCosqStatDroppedPackets; stat <= bcmCosqStatOutBytes; stat++){
   8415             BCM_IF_ERROR_RETURN(bcm_tr3_cosq_stat_set(unit, node->gport, BCM_COS_INVALID, stat, val64));
   8416         }
   8417         
   8418     }
   8419     if (node->child) {
   8420         bcm_tr3_cosq_node_stat_init(unit, node->child);
   8421     }
   8422 
   8423     if (node->sibling) {
   8424         bcm_tr3_cosq_node_stat_init(unit, node->sibling);
   8425     }
   8426     return BCM_E_NONE;
   8427 }
   8428 
   8429 void
   8430 bcm_tr3_cosq_port_stat_init(int unit, bcm_port_t port)
   8431 {
   8432     _bcm_tr3_mmu_info_t *mmu_info;
   8433     int phy_port, mmu_port, ii;
   8434     _bcm_tr3_cosq_node_t *node = NULL, *tnode;
   8435     soc_info_t *si;
   8436 
   8437     si = &SOC_INFO(unit);
   8438     mmu_info = _bcm_tr3_mmu_info[unit];
   8439 
   8440     phy_port = si->port_l2p_mapping[port];
   8441     mmu_port = si->port_p2m_mapping[phy_port];
   8442 
   8443     for (ii = 0; ii < _BCM_TR3_NUM_PORT_SCHEDULERS; ii++) {
   8444         tnode = &mmu_info->sched_node[ii];
   8445         if (tnode->in_use == FALSE) {
   8446             continue;
   8447         }
   8448         if ((tnode->level == SOC_TR3_NODE_LVL_ROOT) &&
   8449             (tnode->hw_index == mmu_port)) {
   8450             node = tnode;
   8451             break;
   8452         }
   8453     }
   8454     if (node == NULL) {
   8455         return;
   8456     }
   8457 
   8458     bcm_tr3_cosq_node_stat_init(unit, node);
   8459 }
   8460 
   8461 void
   8462 bcm_tr3_cosq_stat_init(int unit)
   8463 {
   8464     bcm_port_t port;
   8465 
   8466     PBMP_ALL_ITER(unit, port) {
   8467         bcm_tr3_cosq_port_stat_init(unit, port);
   8468     }
   8469     return;
   8470 }
   8471 
   8472 
   8473 
   8474 int
   8475 bcm_tr3_cosq_stat_set(int unit, bcm_gport_t port, bcm_cos_queue_t cosq,
   8476                      bcm_cosq_stat_t stat, uint64 value)
   8477 {
   8478     _bcm_tr3_cosq_node_t *node;
   8479     bcm_port_t local_port;
   8480     int startq, numq, i, from_cos, to_cos, ci;
   8481     uint64  l, r;
   8482 
   8483     _bcm_tr3_distribute_u64(value, &l, &r);
   8484 
   8485     switch (stat) {
   8486     case bcmCosqStatDroppedPackets:
   8487         if (BCM_GPORT_IS_SCHEDULER(port)) {
   8488             BCM_IF_ERROR_RETURN
   8489                 (_bcm_tr3_cosq_node_get(unit, port, 0, NULL, 
   8490                                         &local_port, NULL, &node));
   8491             BCM_IF_ERROR_RETURN(
   8492                    _bcm_tr3_cosq_child_node_at_input(node, cosq, &node));
   8493             port = node->gport;
   8494             cosq = 0;
   8495         }
   8496 
   8497         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
   8498             BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port)) {
   8499             BCM_IF_ERROR_RETURN
   8500                 (_bcm_tr3_cosq_index_resolve
   8501                  (unit, port, cosq, _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE,
   8502                   &local_port, &startq, NULL));
   8503             /* coverity[NEGATIVE_RETURNS: FALSE] */
   8504             BCM_IF_ERROR_RETURN
   8505                 (soc_counter_set(unit, REG_PORT_ANY,
   8506                                  SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_UC, startq,
   8507                                  value));
   8508         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
   8509             BCM_IF_ERROR_RETURN
   8510                 (_bcm_tr3_cosq_index_resolve
   8511                  (unit, port, cosq, _BCM_TR3_COSQ_INDEX_STYLE_MCAST_QUEUE,
   8512                   &local_port, &startq, NULL));
   8513             /* coverity[NEGATIVE_RETURNS: FALSE] */
   8514             BCM_IF_ERROR_RETURN
   8515                 (soc_counter_set(unit, REG_PORT_ANY,
   8516                              SOC_COUNTER_NON_DMA_COSQ_DROP_PKT, startq - 1024,
   8517                                  value));
   8518         } else if (BCM_GPORT_IS_SCHEDULER(port)) {
   8519             return BCM_E_PARAM;
   8520         } else {
   8521             BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_localport_resolve(unit, port, &local_port));
   8522             BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_port_has_ets(unit, local_port));
   8523             if (cosq == BCM_COS_INVALID) {
   8524                 from_cos = to_cos = 0;
   8525             } else {
   8526                 from_cos = to_cos = cosq;
   8527             }
   8528             for (ci = from_cos; ci <= to_cos; ci++) {
   8529                 BCM_IF_ERROR_RETURN
   8530                     (_bcm_tr3_cosq_index_resolve
   8531                      (unit, port, ci, _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE,
   8532                       &local_port, &startq, &numq));
   8533                 for (i = 0; i < numq; i++) {
   8534                     /* coverity[NEGATIVE_RETURNS: FALSE] */
   8535                     BCM_IF_ERROR_RETURN
   8536                         (soc_counter_set(unit, REG_PORT_ANY,
   8537                                          SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_UC,
   8538                                          startq + i, l));
   8539                 }
   8540                 BCM_IF_ERROR_RETURN
   8541                     (_bcm_tr3_cosq_index_resolve
   8542                      (unit, port, ci, _BCM_TR3_COSQ_INDEX_STYLE_MCAST_QUEUE,
   8543                       &local_port, &startq, &numq));
   8544                 for (i = 0; i < numq; i++) {
   8545                     /* coverity[negative_returns : FALSE] */
   8546                     BCM_IF_ERROR_RETURN
   8547                         (soc_counter_set(unit, -1,
   8548                                          SOC_COUNTER_NON_DMA_COSQ_DROP_PKT,
   8549                                      startq + i - 1024, r));
   8550                 }
   8551             }
   8552         }
   8553         break;
   8554     case bcmCosqStatDroppedBytes:
   8555         if (BCM_GPORT_IS_SCHEDULER(port)) {
   8556             BCM_IF_ERROR_RETURN
   8557                 (_bcm_tr3_cosq_node_get(unit, port, 0, NULL, 
   8558                                         &local_port, NULL, &node));
   8559             BCM_IF_ERROR_RETURN(
   8560                    _bcm_tr3_cosq_child_node_at_input(node, cosq, &node));
   8561             port = node->gport;
   8562             cosq = 0;
   8563         }
   8564 
   8565         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
   8566             BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port)) {
   8567             BCM_IF_ERROR_RETURN
   8568                 (_bcm_tr3_cosq_index_resolve
   8569                  (unit, port, cosq, _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE,
   8570                   &local_port, &startq, NULL));
   8571             /* coverity[NEGATIVE_RETURNS: FALSE] */
   8572             BCM_IF_ERROR_RETURN
   8573                 (soc_counter_set(unit, REG_PORT_ANY,
   8574                                  SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE_UC, startq,
   8575                                  value));
   8576         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
   8577             BCM_IF_ERROR_RETURN
   8578                 (_bcm_tr3_cosq_index_resolve
   8579                  (unit, port, cosq, _BCM_TR3_COSQ_INDEX_STYLE_MCAST_QUEUE,
   8580                   &local_port, &startq, NULL));
   8581             /* coverity[NEGATIVE_RETURNS: FALSE] */
   8582             BCM_IF_ERROR_RETURN
   8583                 (soc_counter_set(unit, REG_PORT_ANY,
   8584                    SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE, startq - 1024, value));
   8585         } else if (BCM_GPORT_IS_SCHEDULER(port)) {
   8586             return BCM_E_PARAM;
   8587         } else {
   8588             BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_localport_resolve(unit, port, &local_port));
   8589             BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_port_has_ets(unit, local_port));
   8590             if (cosq == BCM_COS_INVALID) {
   8591                 from_cos = to_cos = 0;
   8592             } else {
   8593                 from_cos = to_cos = cosq;
   8594             }
   8595             for (ci = from_cos; ci <= to_cos; ci++) {
   8596                 BCM_IF_ERROR_RETURN
   8597                     (_bcm_tr3_cosq_index_resolve
   8598                      (unit, port, ci, _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE,
   8599                       &local_port, &startq, &numq));
   8600                 for (i = 0; i < numq; i++) {
   8601                     /* coverity[NEGATIVE_RETURNS: FALSE] */
   8602                     BCM_IF_ERROR_RETURN
   8603                         (soc_counter_set(unit, REG_PORT_ANY,
   8604                                SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE_UC, startq + i, l));
   8605                 }
   8606                 BCM_IF_ERROR_RETURN
   8607                     (_bcm_tr3_cosq_index_resolve
   8608                      (unit, port, ci, _BCM_TR3_COSQ_INDEX_STYLE_MCAST_QUEUE,
   8609                       &local_port, &startq, &numq));
   8610                 for (i = 0; i < numq; i++) {
   8611                     BCM_IF_ERROR_RETURN
   8612                         (soc_counter_set(unit, REG_PORT_ANY,
   8613                            SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE, startq + i - 1024, r));
   8614                 }
   8615             }
   8616         }
   8617         break;
   8618     case bcmCosqStatYellowCongestionDroppedPackets:
   8619         if (cosq != BCM_COS_INVALID) {
   8620             return BCM_E_UNAVAIL;
   8621         }
   8622         BCM_IF_ERROR_RETURN
   8623             (_bcm_tr3_cosq_localport_resolve(unit, port, &local_port));
   8624         BCM_IF_ERROR_RETURN
   8625             (soc_counter_set(unit, local_port,
   8626                              SOC_COUNTER_NON_DMA_PORT_DROP_PKT_YELLOW, 0,
   8627                              value));
   8628         break;
   8629     case bcmCosqStatRedCongestionDroppedPackets:
   8630         if (cosq != BCM_COS_INVALID) {
   8631             return BCM_E_UNAVAIL;
   8632         }
   8633         BCM_IF_ERROR_RETURN
   8634             (_bcm_tr3_cosq_localport_resolve(unit, port, &local_port));
   8635         BCM_IF_ERROR_RETURN
   8636             (soc_counter_set(unit, local_port,
   8637                              SOC_COUNTER_NON_DMA_PORT_DROP_PKT_RED, 0,
   8638                              value));
   8639         break;
   8640     case bcmCosqStatGreenDiscardDroppedPackets:
   8641         if (cosq != BCM_COS_INVALID) {
   8642             return BCM_E_UNAVAIL;
   8643         }
   8644         BCM_IF_ERROR_RETURN
   8645             (_bcm_tr3_cosq_localport_resolve(unit, port, &local_port));
   8646         BCM_IF_ERROR_RETURN
   8647             (soc_counter_set(unit, local_port,
   8648                              SOC_COUNTER_NON_DMA_PORT_WRED_PKT_GREEN, 0,
   8649                              value));
   8650         break;
   8651     case bcmCosqStatYellowDiscardDroppedPackets:
   8652         if (cosq != BCM_COS_INVALID) {
   8653             return BCM_E_UNAVAIL;
   8654         }
   8655         BCM_IF_ERROR_RETURN
   8656             (_bcm_tr3_cosq_localport_resolve(unit, port, &local_port));
   8657         BCM_IF_ERROR_RETURN
   8658             (soc_counter_set(unit, local_port,
   8659                              SOC_COUNTER_NON_DMA_PORT_WRED_PKT_YELLOW, 0,
   8660                              value));
   8661         break;
   8662     case bcmCosqStatRedDiscardDroppedPackets:
   8663         if (cosq != BCM_COS_INVALID) {
   8664             return BCM_E_UNAVAIL;
   8665         }
   8666         BCM_IF_ERROR_RETURN
   8667             (_bcm_tr3_cosq_localport_resolve(unit, port, &local_port));
   8668         BCM_IF_ERROR_RETURN
   8669             (soc_counter_set(unit, local_port,
   8670                              SOC_COUNTER_NON_DMA_PORT_WRED_PKT_RED, 0, value));
   8671         break;
   8672     case bcmCosqStatOutPackets:
   8673         if (BCM_GPORT_IS_SCHEDULER(port)) {
   8674             BCM_IF_ERROR_RETURN
   8675                 (_bcm_tr3_cosq_node_get(unit, port, 0, NULL, 
   8676                                         &local_port, NULL, &node));
   8677             BCM_IF_ERROR_RETURN(
   8678                    _bcm_tr3_cosq_child_node_at_input(node, cosq, &node));
   8679             port = node->gport;
   8680             cosq = 0;
   8681         }
   8682 
   8683         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
   8684             BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port)) {
   8685             BCM_IF_ERROR_RETURN
   8686                 (_bcm_tr3_cosq_index_resolve
   8687                  (unit, port, cosq, _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE,
   8688                   &local_port, &startq, NULL));
   8689             /* coverity[NEGATIVE_RETURNS: FALSE] */
   8690             BCM_IF_ERROR_RETURN
   8691                 (soc_counter_set(unit, REG_PORT_ANY,
   8692                                  SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT_UC, startq,
   8693                                  value));
   8694         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
   8695             BCM_IF_ERROR_RETURN
   8696                 (_bcm_tr3_cosq_index_resolve
   8697                  (unit, port, cosq, _BCM_TR3_COSQ_INDEX_STYLE_MCAST_QUEUE,
   8698                   &local_port, &startq, NULL));
   8699             /* coverity[NEGATIVE_RETURNS: FALSE] */
   8700             BCM_IF_ERROR_RETURN
   8701                 (soc_counter_set(unit, REG_PORT_ANY,
   8702                                  SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT, startq,
   8703                                  value));
   8704         } else if (BCM_GPORT_IS_SCHEDULER(port)) {
   8705             return BCM_E_PARAM;
   8706         } else {
   8707             BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_localport_resolve(unit, port, &local_port));
   8708             BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_port_has_ets(unit, local_port));
   8709             if (cosq == BCM_COS_INVALID) {
   8710                 from_cos = to_cos = 0;
   8711             } else {
   8712                 from_cos = to_cos = cosq;
   8713             }
   8714             for (ci = from_cos; ci <= to_cos; ci++) {
   8715                 BCM_IF_ERROR_RETURN
   8716                     (_bcm_tr3_cosq_index_resolve
   8717                      (unit, port, ci, _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE,
   8718                       &local_port, &startq, &numq));
   8719                 for (i = 0; i < numq; i++) {
   8720                     /* coverity[NEGATIVE_RETURNS: FALSE] */
   8721                     BCM_IF_ERROR_RETURN
   8722                         (soc_counter_set(unit, REG_PORT_ANY,
   8723                             SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT_UC, startq + i, l));
   8724                 }
   8725                 BCM_IF_ERROR_RETURN
   8726                     (_bcm_tr3_cosq_index_resolve
   8727                      (unit, port, ci, _BCM_TR3_COSQ_INDEX_STYLE_MCAST_QUEUE,
   8728                       &local_port, &startq, &numq));
   8729                 for (i = 0; i < numq; i++) {
   8730                     BCM_IF_ERROR_RETURN
   8731                         (soc_counter_set(unit, REG_PORT_ANY,
   8732                             SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT, startq + i, r));
   8733                 }
   8734             }
   8735         }
   8736         break;
   8737     case bcmCosqStatOutBytes:
   8738         if (BCM_GPORT_IS_SCHEDULER(port)) {
   8739             BCM_IF_ERROR_RETURN
   8740                 (_bcm_tr3_cosq_node_get(unit, port, 0, NULL, 
   8741                                         &local_port, NULL, &node));
   8742             BCM_IF_ERROR_RETURN(
   8743                    _bcm_tr3_cosq_child_node_at_input(node, cosq, &node));
   8744             port = node->gport;
   8745             cosq = 0;
   8746         }
   8747 
   8748         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
   8749             BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port)) {
   8750             BCM_IF_ERROR_RETURN
   8751                 (_bcm_tr3_cosq_index_resolve
   8752                  (unit, port, cosq, _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE,
   8753                   &local_port, &startq, NULL));
   8754             /* coverity[NEGATIVE_RETURNS: FALSE] */
   8755             BCM_IF_ERROR_RETURN
   8756                 (soc_counter_set(unit, REG_PORT_ANY,
   8757                                  SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE_UC, startq,
   8758                                  value));
   8759         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
   8760             BCM_IF_ERROR_RETURN
   8761                 (_bcm_tr3_cosq_index_resolve
   8762                  (unit, port, cosq, _BCM_TR3_COSQ_INDEX_STYLE_MCAST_QUEUE,
   8763                   &local_port, &startq, NULL));
   8764             /* coverity[NEGATIVE_RETURNS: FALSE] */
   8765             BCM_IF_ERROR_RETURN
   8766                 (soc_counter_set(unit, REG_PORT_ANY,
   8767                                  SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE, startq,
   8768                                  value));
   8769         } else if (BCM_GPORT_IS_SCHEDULER(port)) {
   8770             return BCM_E_PARAM;
   8771         } else {
   8772             BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_localport_resolve(unit, port, &local_port));
   8773             BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_port_has_ets(unit, local_port));
   8774             if (cosq == BCM_COS_INVALID) {
   8775                 from_cos = to_cos = 0;
   8776             } else {
   8777                 from_cos = to_cos = cosq;
   8778             }
   8779             for (ci = from_cos; ci <= to_cos; ci++) {
   8780                 BCM_IF_ERROR_RETURN
   8781                     (_bcm_tr3_cosq_index_resolve
   8782                      (unit, port, ci, _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE,
   8783                       &local_port, &startq, &numq));
   8784                 for (i = 0; i < numq; i++) {
   8785                     /* coverity[NEGATIVE_RETURNS: FALSE] */
   8786                     BCM_IF_ERROR_RETURN
   8787                         (soc_counter_set(unit, REG_PORT_ANY,
   8788                            SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE_UC, startq + i, l));
   8789                 }
   8790                 BCM_IF_ERROR_RETURN
   8791                     (_bcm_tr3_cosq_index_resolve
   8792                      (unit, port, ci, _BCM_TR3_COSQ_INDEX_STYLE_MCAST_QUEUE,
   8793                       &local_port, &startq, &numq));
   8794                 for (i = 0; i < numq; i++) {
   8795                     BCM_IF_ERROR_RETURN
   8796                         (soc_counter_set(unit, REG_PORT_ANY,
   8797                             SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE, startq + i, r));
   8798                 }
   8799             }
   8800         }
   8801         break;
   8802     default:
   8803         return BCM_E_PARAM;
   8804     }
   8805 
   8806     return BCM_E_NONE;
   8807 }
   8808 
   8809 int
   8810 bcm_tr3_cosq_stat_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   8811                      bcm_cosq_stat_t stat, int sync_mode, uint64 *value)
   8812 {
   8813     _bcm_tr3_cosq_node_t *node, *child_node;
   8814     bcm_port_t local_port;
   8815     int startq, numq, i, from_cos, to_cos, ci, start_hw_index, end_hw_index;
   8816     uint64 sum, value64;
   8817     int (*counter_get) (int , soc_port_t , soc_reg_t , int , uint64 *);
   8818 
   8819     if (value == NULL) {
   8820         return BCM_E_PARAM;
   8821     }
   8822 
   8823     /*
   8824      * if sync-mode is set, update the software cached counter value, 
   8825      * with the hardware count and then retrieve the count.
   8826      * else return the software cache counter value.
   8827      */
   8828     counter_get = (sync_mode == 1)? soc_counter_sync_get: soc_counter_get;
   8829 
   8830     switch (stat) {
   8831     case bcmCosqStatDroppedPackets:
   8832         if (BCM_GPORT_IS_SCHEDULER(port) && cosq==-1) {
   8833             BCM_IF_ERROR_RETURN
   8834                 (_bcm_tr3_cosq_node_get(unit, port, 0, NULL, 
   8835                                         &local_port, NULL, &node));
   8836             COMPILER_64_ZERO(sum);
   8837             from_cos = 0;
   8838             to_cos = (IS_CPU_PORT(unit, local_port)) ? 
   8839                         NUM_CPU_COSQ(unit) - 1 : _TR3_NUM_COS(unit) - 1;
   8840             for (ci = from_cos; ci <= to_cos; ci++) {
   8841                 if ((_bcm_tr3_cosq_child_node_at_input(node, ci, &child_node)) 
   8842                                             == BCM_E_NOT_FOUND) {
   8843                     continue;
   8844                 }
   8845                 port = child_node->gport;
   8846                 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
   8847                     BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port)) {
   8848                     BCM_IF_ERROR_RETURN
   8849                         (_bcm_tr3_cosq_index_resolve
   8850                         (unit, port, 0, _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE,
   8851                         &local_port, &startq, &numq));
   8852                     /* coverity[NEGATIVE_RETURNS: FALSE] */
   8853                     BCM_IF_ERROR_RETURN
   8854                         (counter_get(unit, REG_PORT_ANY,
   8855                                      SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_UC,
   8856                                      startq, &value64));
   8857                     COMPILER_64_ADD_64(sum, value64);
   8858                 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
   8859 
   8860                     BCM_IF_ERROR_RETURN
   8861                         (_bcm_tr3_cosq_index_resolve
   8862                         (unit, port, 0, _BCM_TR3_COSQ_INDEX_STYLE_MCAST_QUEUE,
   8863                         &local_port, &startq, &numq));
   8864                     /* coverity[NEGATIVE_RETURNS: FALSE] */
   8865                     BCM_IF_ERROR_RETURN
   8866                         (counter_get(unit, REG_PORT_ANY,
   8867                                      SOC_COUNTER_NON_DMA_COSQ_DROP_PKT,
   8868                                      startq - 1024, &value64));
   8869                     COMPILER_64_ADD_64(sum, value64);
   8870                 }
   8871             }
   8872             *value = sum;
   8873             break;
   8874         }
   8875         if (BCM_GPORT_IS_SCHEDULER(port)) {
   8876             BCM_IF_ERROR_RETURN
   8877                 (_bcm_tr3_cosq_node_get(unit, port, 0, NULL, 
   8878                                         &local_port, NULL, &node));
   8879             BCM_IF_ERROR_RETURN(
   8880                    _bcm_tr3_cosq_child_node_at_input(node, cosq, &node));
   8881             port = node->gport;
   8882             cosq = 0;
   8883         }
   8884 
   8885         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
   8886             BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port)) {
   8887             BCM_IF_ERROR_RETURN
   8888                 (_bcm_tr3_cosq_index_resolve
   8889                  (unit, port, cosq, _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE,
   8890                   &local_port, &startq, NULL));
   8891             /* coverity[NEGATIVE_RETURNS: FALSE] */
   8892             BCM_IF_ERROR_RETURN
   8893                 (counter_get(unit, REG_PORT_ANY,
   8894                             SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_UC, startq,
   8895                                  value));
   8896         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
   8897             BCM_IF_ERROR_RETURN
   8898                 (_bcm_tr3_cosq_index_resolve
   8899                  (unit, port, cosq, _BCM_TR3_COSQ_INDEX_STYLE_MCAST_QUEUE,
   8900                   &local_port, &startq, NULL));
   8901             /* coverity[NEGATIVE_RETURNS: FALSE] */
   8902             BCM_IF_ERROR_RETURN
   8903                 (counter_get(unit, REG_PORT_ANY,
   8904                     SOC_COUNTER_NON_DMA_COSQ_DROP_PKT, startq - 1024, value));
   8905         } else if (BCM_GPORT_IS_SCHEDULER(port)) {
   8906             return BCM_E_PARAM;
   8907         } else {
   8908             BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_localport_resolve(unit, port, &local_port));
   8909             BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_port_has_ets(unit, local_port));
   8910             COMPILER_64_ZERO(sum);
   8911             if (cosq == BCM_COS_INVALID) {
   8912                 from_cos = 0;
   8913                 to_cos = (IS_CPU_PORT(unit, local_port)) ? 
   8914                             NUM_CPU_COSQ(unit) - 1 : _TR3_NUM_COS(unit) - 1;
   8915             } else {
   8916                 from_cos = to_cos = cosq;
   8917             }
   8918             for (ci = from_cos; ci <= to_cos; ci++) {
   8919                 BCM_IF_ERROR_RETURN
   8920                     (_bcm_tr3_cosq_index_resolve
   8921                      (unit, port, ci, _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE,
   8922                       &local_port, &startq, &numq));
   8923                 for (i = 0; i < numq; i++) {
   8924                     /* coverity[NEGATIVE_RETURNS: FALSE] */
   8925                     BCM_IF_ERROR_RETURN
   8926                         (counter_get(unit, REG_PORT_ANY,
   8927                                      SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_UC,
   8928                                          startq + i, &value64));
   8929                     COMPILER_64_ADD_64(sum, value64);
   8930                 }
   8931                 BCM_IF_ERROR_RETURN
   8932                     (_bcm_tr3_cosq_index_resolve
   8933                      (unit, port, ci, _BCM_TR3_COSQ_INDEX_STYLE_MCAST_QUEUE,
   8934                       &local_port, &startq, &numq));
   8935                 for (i = 0; i < numq; i++) {
   8936                     /* coverity[NEGATIVE_RETURNS: FALSE] */
   8937                     BCM_IF_ERROR_RETURN
   8938                         (counter_get(unit, REG_PORT_ANY,
   8939                                      SOC_COUNTER_NON_DMA_COSQ_DROP_PKT,
   8940                                          startq + i - 1024, &value64));
   8941                     COMPILER_64_ADD_64(sum, value64);
   8942                 }
   8943             }
   8944             *value = sum;
   8945         }
   8946         break;
   8947     case bcmCosqStatDroppedBytes:
   8948         if (BCM_GPORT_IS_SCHEDULER(port) && cosq==-1) {
   8949             BCM_IF_ERROR_RETURN
   8950                 (_bcm_tr3_cosq_node_get(unit, port, 0, NULL, 
   8951                                         &local_port, NULL, &node));
   8952             COMPILER_64_ZERO(sum);
   8953             from_cos = 0;
   8954             to_cos = (IS_CPU_PORT(unit, local_port)) ? 
   8955                         NUM_CPU_COSQ(unit) - 1 : _TR3_NUM_COS(unit) - 1;
   8956             for (ci = from_cos; ci <= to_cos; ci++) {
   8957                 if ((_bcm_tr3_cosq_child_node_at_input(node, ci, &child_node)) 
   8958                                             == BCM_E_NOT_FOUND) {
   8959                     continue;
   8960                 }
   8961                 port = child_node->gport;
   8962                 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
   8963                     BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port)) {
   8964                     BCM_IF_ERROR_RETURN
   8965                         (_bcm_tr3_cosq_index_resolve
   8966                         (unit, port, 0, _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE,
   8967                         &local_port, &startq, &numq));
   8968                     /* coverity[NEGATIVE_RETURNS: FALSE] */
   8969                     BCM_IF_ERROR_RETURN
   8970                         (counter_get(unit, REG_PORT_ANY,
   8971                                      SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE_UC,
   8972                                      startq, &value64));
   8973                     COMPILER_64_ADD_64(sum, value64);
   8974                 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
   8975 
   8976                     BCM_IF_ERROR_RETURN
   8977                         (_bcm_tr3_cosq_index_resolve
   8978                         (unit, port, 0, _BCM_TR3_COSQ_INDEX_STYLE_MCAST_QUEUE,
   8979                         &local_port, &startq, &numq));
   8980                     /* coverity[NEGATIVE_RETURNS: FALSE] */
   8981                     BCM_IF_ERROR_RETURN
   8982                         (counter_get(unit, REG_PORT_ANY,
   8983                                      SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE,
   8984                                      startq - 1024, &value64));
   8985                     COMPILER_64_ADD_64(sum, value64);
   8986                 }
   8987             }
   8988             *value = sum;
   8989             break;
   8990         }
   8991         if (BCM_GPORT_IS_SCHEDULER(port)) {
   8992             BCM_IF_ERROR_RETURN
   8993                 (_bcm_tr3_cosq_node_get(unit, port, 0, NULL, 
   8994                                         &local_port, NULL, &node));
   8995             BCM_IF_ERROR_RETURN(
   8996                    _bcm_tr3_cosq_child_node_at_input(node, cosq, &node));
   8997             port = node->gport;
   8998             cosq = 0;
   8999         }
   9000 
   9001         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
   9002             BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port)) {
   9003             BCM_IF_ERROR_RETURN
   9004                 (_bcm_tr3_cosq_index_resolve
   9005                  (unit, port, cosq, _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE,
   9006                   &local_port, &startq, NULL));
   9007             /* coverity[NEGATIVE_RETURNS: FALSE] */
   9008             BCM_IF_ERROR_RETURN
   9009                 (counter_get(unit, REG_PORT_ANY,
   9010                              SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE_UC, startq,
   9011                              value));
   9012         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
   9013             BCM_IF_ERROR_RETURN
   9014                 (_bcm_tr3_cosq_index_resolve
   9015                  (unit, port, cosq, _BCM_TR3_COSQ_INDEX_STYLE_MCAST_QUEUE,
   9016                   &local_port, &startq, NULL));
   9017             /* coverity[NEGATIVE_RETURNS: FALSE] */
   9018             BCM_IF_ERROR_RETURN
   9019                 (counter_get(unit, REG_PORT_ANY,
   9020                              SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE, 
   9021                              startq - 1024, value));
   9022         } else if (BCM_GPORT_IS_SCHEDULER(port)) {
   9023             return BCM_E_PARAM;
   9024         } else {
   9025             BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_localport_resolve(unit, port, &local_port));
   9026             BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_port_has_ets(unit, local_port));
   9027             COMPILER_64_ZERO(sum);
   9028             if (cosq == BCM_COS_INVALID) {
   9029                 from_cos = 0;
   9030                 to_cos = (IS_CPU_PORT(unit, local_port)) ? 
   9031                             NUM_CPU_COSQ(unit) - 1 : _TR3_NUM_COS(unit) - 1;
   9032             } else {
   9033                 from_cos = to_cos = cosq;
   9034             }
   9035             for (ci = from_cos; ci <= to_cos; ci++) {
   9036                 BCM_IF_ERROR_RETURN
   9037                     (_bcm_tr3_cosq_index_resolve
   9038                      (unit, port, ci, _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE,
   9039                       &local_port, &startq, &numq));
   9040                 for (i = 0; i < numq; i++) {
   9041                     /* coverity[NEGATIVE_RETURNS: FALSE] */
   9042                     BCM_IF_ERROR_RETURN
   9043                         (counter_get(unit, REG_PORT_ANY,
   9044                                      SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE_UC,
   9045                                          startq + i, &value64));
   9046                     COMPILER_64_ADD_64(sum, value64);
   9047                 }
   9048                 BCM_IF_ERROR_RETURN
   9049                     (_bcm_tr3_cosq_index_resolve
   9050                      (unit, port, ci, _BCM_TR3_COSQ_INDEX_STYLE_MCAST_QUEUE,
   9051                       &local_port, &startq, &numq));
   9052                 for (i = 0; i < numq; i++) {
   9053                     BCM_IF_ERROR_RETURN
   9054                         (counter_get(unit, REG_PORT_ANY,
   9055                                      SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE,
   9056                                          startq + i - 1024, &value64));
   9057                     COMPILER_64_ADD_64(sum, value64);
   9058                 }
   9059             }
   9060             *value = sum;
   9061         }
   9062         break;
   9063     case bcmCosqStatYellowCongestionDroppedPackets:
   9064         if (cosq != BCM_COS_INVALID) {
   9065             return BCM_E_UNAVAIL;
   9066         }
   9067         BCM_IF_ERROR_RETURN
   9068             (_bcm_tr3_cosq_localport_resolve(unit, port, &local_port));
   9069         BCM_IF_ERROR_RETURN
   9070             (counter_get(unit, local_port,
   9071                          SOC_COUNTER_NON_DMA_PORT_DROP_PKT_YELLOW, 0,
   9072                              value));
   9073         break;
   9074     case bcmCosqStatRedCongestionDroppedPackets:
   9075         if (cosq != BCM_COS_INVALID) {
   9076             return BCM_E_UNAVAIL;
   9077         }
   9078         BCM_IF_ERROR_RETURN
   9079             (_bcm_tr3_cosq_localport_resolve(unit, port, &local_port));
   9080         BCM_IF_ERROR_RETURN
   9081             (counter_get(unit, local_port,
   9082                          SOC_COUNTER_NON_DMA_PORT_DROP_PKT_RED, 0,
   9083                              value));
   9084         break;
   9085     case bcmCosqStatGreenDiscardDroppedPackets:
   9086         if (cosq != BCM_COS_INVALID) {
   9087             return BCM_E_UNAVAIL;
   9088         }
   9089         BCM_IF_ERROR_RETURN
   9090             (_bcm_tr3_cosq_localport_resolve(unit, port, &local_port));
   9091         BCM_IF_ERROR_RETURN
   9092             (counter_get(unit, local_port,
   9093                          SOC_COUNTER_NON_DMA_PORT_WRED_PKT_GREEN, 0,
   9094                              value));
   9095         break;
   9096     case bcmCosqStatYellowDiscardDroppedPackets:
   9097         if (cosq != BCM_COS_INVALID) {
   9098             return BCM_E_UNAVAIL;
   9099         }
   9100         BCM_IF_ERROR_RETURN
   9101             (_bcm_tr3_cosq_localport_resolve(unit, port, &local_port));
   9102         BCM_IF_ERROR_RETURN
   9103             (counter_get(unit, local_port,
   9104                          SOC_COUNTER_NON_DMA_PORT_WRED_PKT_YELLOW, 0,
   9105                              value));
   9106         break;
   9107     case bcmCosqStatRedDiscardDroppedPackets:
   9108         if (cosq != BCM_COS_INVALID) {
   9109             return BCM_E_UNAVAIL;
   9110         }
   9111         BCM_IF_ERROR_RETURN
   9112             (_bcm_tr3_cosq_localport_resolve(unit, port, &local_port));
   9113         BCM_IF_ERROR_RETURN
   9114             (counter_get(unit, local_port,
   9115                          SOC_COUNTER_NON_DMA_PORT_WRED_PKT_RED, 0, value));
   9116         break;
   9117     case bcmCosqStatOutPackets:
   9118         if (BCM_GPORT_IS_SCHEDULER(port) && cosq==-1) {
   9119             BCM_IF_ERROR_RETURN
   9120                 (_bcm_tr3_cosq_node_get(unit, port, 0, NULL, 
   9121                                         &local_port, NULL, &node));
   9122             COMPILER_64_ZERO(sum);
   9123             from_cos = 0;
   9124             to_cos = (IS_CPU_PORT(unit, local_port)) ? 
   9125                         NUM_CPU_COSQ(unit) - 1 : _TR3_NUM_COS(unit) - 1;
   9126             for (ci = from_cos; ci <= to_cos; ci++) {
   9127                 if ((_bcm_tr3_cosq_child_node_at_input(node, ci, &child_node)) 
   9128                                             == BCM_E_NOT_FOUND) {
   9129                     continue;
   9130                 }
   9131                 port = child_node->gport;
   9132                 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
   9133                     BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port)) {
   9134                     BCM_IF_ERROR_RETURN
   9135                         (_bcm_tr3_cosq_index_resolve
   9136                         (unit, port, 0, _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE,
   9137                         &local_port, &startq, &numq));
   9138                     /* coverity[NEGATIVE_RETURNS: FALSE] */
   9139                     BCM_IF_ERROR_RETURN
   9140                         (counter_get(unit, REG_PORT_ANY,
   9141                                      SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT_UC,
   9142                                      startq, &value64));
   9143                     COMPILER_64_ADD_64(sum, value64);
   9144                 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
   9145 
   9146                     BCM_IF_ERROR_RETURN
   9147                         (_bcm_tr3_cosq_index_resolve
   9148                         (unit, port, 0, _BCM_TR3_COSQ_INDEX_STYLE_MCAST_QUEUE,
   9149                         &local_port, &startq, &numq));
   9150                     /* coverity[NEGATIVE_RETURNS: FALSE] */
   9151                     BCM_IF_ERROR_RETURN
   9152                         (counter_get(unit, REG_PORT_ANY,
   9153                                      SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT,
   9154                                      startq, &value64));
   9155                     COMPILER_64_ADD_64(sum, value64);
   9156                 }
   9157             }
   9158             *value = sum;
   9159             break;
   9160         }
   9161         if (BCM_GPORT_IS_SCHEDULER(port)) {
   9162             BCM_IF_ERROR_RETURN
   9163                 (_bcm_tr3_cosq_node_get(unit, port, 0, NULL, 
   9164                                         &local_port, NULL, &node));
   9165             BCM_IF_ERROR_RETURN(
   9166                    _bcm_tr3_cosq_child_node_at_input(node, cosq, &node));
   9167             port = node->gport;
   9168             cosq = 0;
   9169         }
   9170 
   9171         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
   9172             BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port)) {
   9173             BCM_IF_ERROR_RETURN
   9174                 (_bcm_tr3_cosq_index_resolve
   9175                  (unit, port, cosq, _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE,
   9176                   &local_port, &startq, NULL));
   9177             /* coverity[NEGATIVE_RETURNS: FALSE] */
   9178             BCM_IF_ERROR_RETURN
   9179                 (counter_get(unit, REG_PORT_ANY,
   9180                              SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT_UC, startq,
   9181                                  value));
   9182         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
   9183             BCM_IF_ERROR_RETURN
   9184                 (_bcm_tr3_cosq_index_resolve
   9185                  (unit, port, cosq, _BCM_TR3_COSQ_INDEX_STYLE_MCAST_QUEUE,
   9186                   &local_port, &startq, NULL));
   9187             /* coverity[NEGATIVE_RETURNS: FALSE] */
   9188             BCM_IF_ERROR_RETURN
   9189                 (counter_get(unit, REG_PORT_ANY,
   9190                              SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT, startq,
   9191                                  value));
   9192         } else if (BCM_GPORT_IS_SCHEDULER(port)) {
   9193             return BCM_E_PARAM;
   9194         } else {
   9195             BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_localport_resolve(unit, port, &local_port));
   9196             BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_port_has_ets(unit, local_port));
   9197             COMPILER_64_ZERO(sum);
   9198             if (cosq == BCM_COS_INVALID) {
   9199                 from_cos = 0;
   9200                 to_cos = (IS_CPU_PORT(unit, local_port)) ? 
   9201                             NUM_CPU_COSQ(unit) - 1 : _TR3_NUM_COS(unit) - 1;
   9202             } else {
   9203                 from_cos = to_cos = cosq;
   9204             }
   9205             for (ci = from_cos; ci <= to_cos; ci++) {
   9206                 BCM_IF_ERROR_RETURN
   9207                     (_bcm_tr3_cosq_index_resolve
   9208                      (unit, port, ci, _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE,
   9209                       &local_port, &startq, &numq));
   9210                 for (i = 0; i < numq; i++) {
   9211                     /* coverity[NEGATIVE_RETURNS: FALSE] */
   9212                     BCM_IF_ERROR_RETURN
   9213                         (counter_get(unit, REG_PORT_ANY,
   9214                                      SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT_UC,
   9215                                      startq + i, &value64));
   9216                     COMPILER_64_ADD_64(sum, value64);
   9217                 }
   9218                 BCM_IF_ERROR_RETURN
   9219                     (_bcm_tr3_cosq_index_resolve
   9220                      (unit, port, ci, _BCM_TR3_COSQ_INDEX_STYLE_MCAST_QUEUE,
   9221                       &local_port, &startq, &numq));
   9222                 for (i = 0; i < numq; i++) {
   9223                     /* coverity[NEGATIVE_RETURNS: FALSE] */
   9224                     BCM_IF_ERROR_RETURN
   9225                         (counter_get(unit, REG_PORT_ANY,
   9226                                      SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT,
   9227                                      startq + i, &value64));
   9228                     COMPILER_64_ADD_64(sum, value64);
   9229                 }
   9230             }
   9231             *value = sum;
   9232         }
   9233         break;
   9234     case bcmCosqStatOutBytes:
   9235         if (BCM_GPORT_IS_SCHEDULER(port) && cosq==-1) {
   9236             BCM_IF_ERROR_RETURN
   9237                 (_bcm_tr3_cosq_node_get(unit, port, 0, NULL, 
   9238                                         &local_port, NULL, &node));
   9239             COMPILER_64_ZERO(sum);
   9240             from_cos = 0;
   9241             to_cos = (IS_CPU_PORT(unit, local_port)) ? 
   9242                         NUM_CPU_COSQ(unit) - 1 : _TR3_NUM_COS(unit) - 1;
   9243             for (ci = from_cos; ci <= to_cos; ci++) {
   9244                 if ((_bcm_tr3_cosq_child_node_at_input(node, ci, &child_node)) 
   9245                                             == BCM_E_NOT_FOUND) {
   9246                     continue;
   9247                 }
   9248                 port = child_node->gport;
   9249                 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
   9250                     BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port)) {
   9251                     BCM_IF_ERROR_RETURN
   9252                         (_bcm_tr3_cosq_index_resolve
   9253                         (unit, port, 0, _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE,
   9254                         &local_port, &startq, &numq));
   9255                     /* coverity[NEGATIVE_RETURNS: FALSE] */
   9256                     BCM_IF_ERROR_RETURN
   9257                         (counter_get(unit, REG_PORT_ANY,
   9258                                      SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE_UC,
   9259                                      startq, &value64));
   9260                     COMPILER_64_ADD_64(sum, value64);
   9261                 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
   9262 
   9263                     BCM_IF_ERROR_RETURN
   9264                         (_bcm_tr3_cosq_index_resolve
   9265                         (unit, port, 0, _BCM_TR3_COSQ_INDEX_STYLE_MCAST_QUEUE,
   9266                         &local_port, &startq, &numq));
   9267                     /* coverity[NEGATIVE_RETURNS: FALSE] */
   9268                     BCM_IF_ERROR_RETURN
   9269                         (counter_get(unit, REG_PORT_ANY,
   9270                                      SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE,
   9271                                      startq, &value64));
   9272                     COMPILER_64_ADD_64(sum, value64);
   9273                 }
   9274             }
   9275             *value = sum;
   9276             break;
   9277         }
   9278         if (BCM_GPORT_IS_SCHEDULER(port)) {
   9279             BCM_IF_ERROR_RETURN
   9280                 (_bcm_tr3_cosq_node_get(unit, port, 0, NULL, 
   9281                                         &local_port, NULL, &node));
   9282             BCM_IF_ERROR_RETURN(
   9283                    _bcm_tr3_cosq_child_node_at_input(node, cosq, &node));
   9284             port = node->gport;
   9285             cosq = 0;
   9286         }
   9287 
   9288         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
   9289             BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port)) {
   9290             BCM_IF_ERROR_RETURN
   9291                 (_bcm_tr3_cosq_index_resolve
   9292                  (unit, port, cosq, _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE,
   9293                   &local_port, &startq, NULL));
   9294             /* coverity[NEGATIVE_RETURNS: FALSE] */
   9295             BCM_IF_ERROR_RETURN
   9296                 (counter_get(unit, REG_PORT_ANY,
   9297                              SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE_UC, startq,
   9298                              value));
   9299         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
   9300             BCM_IF_ERROR_RETURN
   9301                 (_bcm_tr3_cosq_index_resolve
   9302                  (unit, port, cosq, _BCM_TR3_COSQ_INDEX_STYLE_MCAST_QUEUE,
   9303                   &local_port, &startq, NULL));
   9304             /* coverity[NEGATIVE_RETURNS: FALSE] */
   9305             BCM_IF_ERROR_RETURN
   9306                 (counter_get(unit, REG_PORT_ANY,
   9307                              SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE, startq,
   9308                              value));
   9309         } else if (BCM_GPORT_IS_SCHEDULER(port)) {
   9310             return BCM_E_PARAM;
   9311         } else {
   9312             BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_localport_resolve(unit, port, &local_port));
   9313             BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_port_has_ets(unit, local_port));
   9314             COMPILER_64_ZERO(sum);
   9315             if (cosq == BCM_COS_INVALID) {
   9316                 from_cos = 0;
   9317                 to_cos = (IS_CPU_PORT(unit, local_port)) ? 
   9318                             NUM_CPU_COSQ(unit) - 1 : _TR3_NUM_COS(unit) - 1;
   9319             } else {
   9320                 from_cos = to_cos = cosq;
   9321             }
   9322             for (ci = from_cos; ci <= to_cos; ci++) {
   9323                 BCM_IF_ERROR_RETURN
   9324                     (_bcm_tr3_cosq_index_resolve
   9325                      (unit, port, ci, _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE,
   9326                       &local_port, &startq, &numq));
   9327                 for (i = 0; i < numq; i++) {
   9328                     /* coverity[NEGATIVE_RETURNS: FALSE] */
   9329                     BCM_IF_ERROR_RETURN
   9330                         (counter_get(unit, REG_PORT_ANY,
   9331                                      SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE_UC,
   9332                                      startq + i, &value64));
   9333                     COMPILER_64_ADD_64(sum, value64);
   9334                 }
   9335                 BCM_IF_ERROR_RETURN
   9336                     (_bcm_tr3_cosq_index_resolve
   9337                      (unit, port, ci, _BCM_TR3_COSQ_INDEX_STYLE_MCAST_QUEUE,
   9338                       &local_port, &startq, &numq));
   9339                 for (i = 0; i < numq; i++) {
   9340                     /* coverity[NEGATIVE_RETURNS: FALSE] */
   9341                     BCM_IF_ERROR_RETURN
   9342                         (counter_get(unit, REG_PORT_ANY,
   9343                                      SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE,
   9344                                      startq + i, &value64));
   9345                     COMPILER_64_ADD_64(sum, value64);
   9346                 }
   9347             }
   9348             *value = sum;
   9349         }
   9350         break;
   9351 
   9352     case bcmCosqStatIngressPortPoolSharedBytesPeak:
   9353 
   9354         COMPILER_64_ZERO(sum);
   9355         BCM_IF_ERROR_RETURN
   9356             (_bcm_tr3_cosq_ingress_sp_get(unit, port, cosq, 
   9357                                     &start_hw_index, &end_hw_index));
   9358 
   9359         BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_localport_resolve(unit, port, &local_port));
   9360         for (i = start_hw_index; i <= end_hw_index; i++) {
   9361                         /* coverity[NEGATIVE_RETURNS: FALSE] */
   9362             BCM_IF_ERROR_RETURN
   9363                     (counter_get(unit, local_port,
   9364                                              SOC_COUNTER_NON_DMA_POOL_PEAK,
   9365                                              i, &value64));
   9366             COMPILER_64_ADD_64(sum, value64);
   9367         }
   9368 
   9369         COMPILER_64_UMUL_32(sum, _BCM_TR3_BYTES_PER_CELL);
   9370         *value = sum;
   9371         break;
   9372     case bcmCosqStatIngressPortPoolSharedBytesCurrent:
   9373 
   9374         BCM_IF_ERROR_RETURN
   9375             (_bcm_tr3_cosq_ingress_sp_get(unit, port, cosq, 
   9376                                     &start_hw_index, &end_hw_index));
   9377         BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_localport_resolve(unit, port, &local_port));
   9378 
   9379         COMPILER_64_ZERO(sum);
   9380         for (i = start_hw_index; i <= end_hw_index; i++) {
   9381                         /* coverity[NEGATIVE_RETURNS: FALSE] */
   9382             BCM_IF_ERROR_RETURN
   9383                  (counter_get(unit, local_port,
   9384                                              SOC_COUNTER_NON_DMA_POOL_CURRENT,
   9385                                              i, &value64));
   9386            COMPILER_64_ADD_64(sum, value64);
   9387         }
   9388 
   9389         COMPILER_64_UMUL_32(sum, _BCM_TR3_BYTES_PER_CELL);
   9390         *value = sum;
   9391         break;
   9392 
   9393     case bcmCosqStatIngressPortPGMinBytesPeak:
   9394 
   9395         BCM_IF_ERROR_RETURN
   9396             (_bcm_tr3_cosq_ingress_pg_get(unit, port, cosq, 
   9397                                     &start_hw_index, &end_hw_index));
   9398         COMPILER_64_ZERO(sum);
   9399         BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_localport_resolve(unit, port, &local_port));
   9400 
   9401         for (i = start_hw_index; i <= end_hw_index; i++) {
   9402                         /* coverity[NEGATIVE_RETURNS: FALSE] */
   9403             BCM_IF_ERROR_RETURN
   9404                 (counter_get(unit, local_port,
   9405                                              SOC_COUNTER_NON_DMA_PG_MIN_PEAK,
   9406                                              i, &value64));
   9407             COMPILER_64_ADD_64(sum, value64);
   9408           }
   9409 
   9410         COMPILER_64_UMUL_32(sum, _BCM_TR3_BYTES_PER_CELL);
   9411         *value = sum;
   9412         break;
   9413     case bcmCosqStatIngressPortPGMinBytesCurrent:
   9414 
   9415         BCM_IF_ERROR_RETURN
   9416             (_bcm_tr3_cosq_ingress_pg_get(unit, port, cosq,
   9417                                     &start_hw_index, &end_hw_index));
   9418         COMPILER_64_ZERO(sum);
   9419         BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_localport_resolve(unit, port, &local_port));
   9420 
   9421         for (i = start_hw_index; i <= end_hw_index; i++) {
   9422                         /* coverity[NEGATIVE_RETURNS: FALSE] */
   9423             BCM_IF_ERROR_RETURN
   9424                  (counter_get(unit, local_port,
   9425                                              SOC_COUNTER_NON_DMA_PG_MIN_CURRENT,
   9426                                              i, &value64));
   9427             COMPILER_64_ADD_64(sum, value64);
   9428         }
   9429 
   9430         COMPILER_64_UMUL_32(sum, _BCM_TR3_BYTES_PER_CELL);
   9431         *value = sum;
   9432         break;     
   9433 
   9434     case bcmCosqStatIngressPortPGSharedBytesPeak:
   9435 
   9436         BCM_IF_ERROR_RETURN
   9437            (_bcm_tr3_cosq_ingress_pg_get(unit, port, cosq,
   9438                                     &start_hw_index, &end_hw_index));
   9439         COMPILER_64_ZERO(sum);
   9440         BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_localport_resolve(unit, port, &local_port));
   9441 
   9442         for (i = start_hw_index; i <= end_hw_index; i++) {
   9443                         /* coverity[NEGATIVE_RETURNS: FALSE] */
   9444             BCM_IF_ERROR_RETURN
   9445                 (counter_get(unit, local_port,
   9446                                              SOC_COUNTER_NON_DMA_PG_SHARED_PEAK,
   9447                                              i, &value64));
   9448             COMPILER_64_ADD_64(sum, value64);
   9449         }
   9450 
   9451         COMPILER_64_UMUL_32(sum, _BCM_TR3_BYTES_PER_CELL);
   9452         *value = sum;
   9453         break;
   9454 
   9455     case bcmCosqStatIngressPortPGSharedBytesCurrent:
   9456 
   9457         BCM_IF_ERROR_RETURN
   9458             (_bcm_tr3_cosq_ingress_pg_get(unit, port, cosq,
   9459                                     &start_hw_index, &end_hw_index));
   9460         BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_localport_resolve(unit, port, &local_port));
   9461         COMPILER_64_ZERO(sum);
   9462 
   9463         for (i = start_hw_index; i <= end_hw_index; i++) {
   9464                         /* coverity[NEGATIVE_RETURNS: FALSE] */
   9465             BCM_IF_ERROR_RETURN
   9466                 (counter_get(unit, local_port,
   9467                                           SOC_COUNTER_NON_DMA_PG_SHARED_CURRENT,
   9468                                              i, &value64));
   9469             COMPILER_64_ADD_64(sum, value64);
   9470         }
   9471         COMPILER_64_UMUL_32(sum, _BCM_TR3_BYTES_PER_CELL);
   9472         *value = sum;
   9473 
   9474         break;
   9475 
   9476     case bcmCosqStatIngressPortPGHeadroomBytesPeak:
   9477 
   9478         BCM_IF_ERROR_RETURN
   9479                (_bcm_tr3_cosq_ingress_pg_get(unit, port, cosq,
   9480                                     &start_hw_index, &end_hw_index));
   9481         BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_localport_resolve(unit, port, &local_port));
   9482         COMPILER_64_ZERO(sum);
   9483 
   9484         for (i = start_hw_index; i <= end_hw_index; i++) {
   9485                         /* coverity[NEGATIVE_RETURNS: FALSE] */
   9486             BCM_IF_ERROR_RETURN
   9487                 (counter_get(unit, local_port,
   9488                                        SOC_COUNTER_NON_DMA_PG_HDRM_PEAK,
   9489                                        i, &value64));
   9490             COMPILER_64_ADD_64(sum, value64);
   9491         }
   9492         COMPILER_64_UMUL_32(sum, _BCM_TR3_BYTES_PER_CELL);
   9493         *value = sum;
   9494 
   9495         break;
   9496 
   9497     case bcmCosqStatIngressPortPGHeadroomBytesCurrent:
   9498 
   9499         BCM_IF_ERROR_RETURN
   9500             (_bcm_tr3_cosq_ingress_pg_get(unit, port, cosq,
   9501                                     &start_hw_index, &end_hw_index));
   9502 
   9503         BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_localport_resolve(unit, port, &local_port));
   9504         COMPILER_64_ZERO(sum);
   9505         for (i = start_hw_index; i <= end_hw_index; i++) {
   9506                         /* coverity[NEGATIVE_RETURNS: FALSE] */
   9507             BCM_IF_ERROR_RETURN
   9508                  (counter_get(unit, local_port,
   9509                             SOC_COUNTER_NON_DMA_PG_HDRM_CURRENT,
   9510                                 i, &value64));
   9511             COMPILER_64_ADD_64(sum, value64);
   9512         }
   9513         COMPILER_64_UMUL_32(sum, _BCM_TR3_BYTES_PER_CELL);
   9514         *value = sum;
   9515 
   9516         break;
   9517     
   9518     case bcmCosqStatEgressMCQueueBytesPeak:
   9519         if (BCM_GPORT_IS_SCHEDULER(port)) {
   9520             BCM_IF_ERROR_RETURN
   9521                 (_bcm_tr3_cosq_node_get(unit, port, 0, NULL, 
   9522                                         &local_port, NULL, &node));
   9523             BCM_IF_ERROR_RETURN(
   9524                    _bcm_tr3_cosq_child_node_at_input(node, cosq, &node));
   9525             port = node->gport;
   9526         }
   9527 
   9528         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
   9529             BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port)) {
   9530             return BCM_E_PARAM;
   9531         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
   9532             BCM_IF_ERROR_RETURN
   9533                 (_bcm_tr3_cosq_index_resolve
   9534                  (unit, port, cosq, _BCM_TR3_COSQ_INDEX_STYLE_EGR_PERQ_MCAST,
   9535                   &local_port, &startq, NULL));
   9536             /* coverity[NEGATIVE_RETURNS: FALSE] */
   9537             BCM_IF_ERROR_RETURN
   9538                 (counter_get(unit, local_port,
   9539                                  SOC_COUNTER_NON_DMA_QUEUE_PEAK, startq,
   9540                                  value));
   9541             COMPILER_64_UMUL_32(*value, _BCM_TR3_BYTES_PER_CELL);
   9542         } else {
   9543             BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_localport_resolve(unit, port, &local_port));
   9544             BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_port_has_ets(unit, port));
   9545             COMPILER_64_ZERO(sum);
   9546             if (cosq == BCM_COS_INVALID) {
   9547                 from_cos = 0;
   9548                 to_cos = (IS_CPU_PORT(unit, local_port)) ? 
   9549                             NUM_CPU_COSQ(unit) - 1 : _TR3_NUM_COS(unit) - 1;
   9550             } else {
   9551                 from_cos = to_cos = cosq;
   9552             }
   9553 
   9554             for (ci = from_cos; ci <= to_cos; ci++) {
   9555                     BCM_IF_ERROR_RETURN
   9556                         (_bcm_tr3_cosq_index_resolve
   9557                             (unit, port, ci, _BCM_TR3_COSQ_INDEX_STYLE_EGR_PERQ_MCAST,
   9558                              &local_port, &startq, &numq));
   9559                     for (i = 0; i < numq; i++) {
   9560                         /* coverity[NEGATIVE_RETURNS: FALSE] */
   9561                         BCM_IF_ERROR_RETURN
   9562                             (counter_get(unit, local_port,
   9563                                              SOC_COUNTER_NON_DMA_QUEUE_PEAK,
   9564                                              startq + i, &value64));
   9565                         COMPILER_64_ADD_64(sum, value64);
   9566                     }
   9567             }
   9568             COMPILER_64_UMUL_32(sum, _BCM_TR3_BYTES_PER_CELL);
   9569             *value = sum;
   9570         }
   9571         break;
   9572     
   9573     case bcmCosqStatEgressMCQueueBytesCurrent:
   9574         if (BCM_GPORT_IS_SCHEDULER(port)) {
   9575             BCM_IF_ERROR_RETURN
   9576                 (_bcm_tr3_cosq_node_get(unit, port, 0, NULL, 
   9577                                         &local_port, NULL, &node));
   9578             BCM_IF_ERROR_RETURN(
   9579                    _bcm_tr3_cosq_child_node_at_input(node, cosq, &node));
   9580             port = node->gport;
   9581         }
   9582 
   9583         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
   9584             BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port)) {
   9585             return BCM_E_PARAM;
   9586         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
   9587             BCM_IF_ERROR_RETURN
   9588                 (_bcm_tr3_cosq_index_resolve
   9589                  (unit, port, cosq, _BCM_TR3_COSQ_INDEX_STYLE_EGR_PERQ_MCAST,
   9590                   &local_port, &startq, NULL));
   9591             /* coverity[NEGATIVE_RETURNS: FALSE] */
   9592             BCM_IF_ERROR_RETURN
   9593                 (counter_get(unit, local_port,
   9594                                  SOC_COUNTER_NON_DMA_QUEUE_CURRENT, startq,
   9595                                  value));
   9596             COMPILER_64_UMUL_32(*value, _BCM_TR3_BYTES_PER_CELL);
   9597         } else {
   9598             BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_localport_resolve(unit, port, &local_port));
   9599             BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_port_has_ets(unit, port));
   9600             COMPILER_64_ZERO(sum);
   9601             if (cosq == BCM_COS_INVALID) {
   9602                 from_cos = 0;
   9603                 to_cos = (IS_CPU_PORT(unit, local_port)) ? 
   9604                             NUM_CPU_COSQ(unit) - 1 : _TR3_NUM_COS(unit) - 1;
   9605             } else {
   9606                 from_cos = to_cos = cosq;
   9607             }
   9608 
   9609             for (ci = from_cos; ci <= to_cos; ci++) {
   9610                  BCM_IF_ERROR_RETURN
   9611                     (_bcm_tr3_cosq_index_resolve
   9612                         (unit, port, ci, _BCM_TR3_COSQ_INDEX_STYLE_EGR_PERQ_MCAST,
   9613                         &local_port, &startq, &numq));
   9614                  for (i = 0; i < numq; i++) {
   9615                         /* coverity[NEGATIVE_RETURNS: FALSE] */
   9616                       BCM_IF_ERROR_RETURN
   9617                         (counter_get(unit, local_port,
   9618                                              SOC_COUNTER_NON_DMA_QUEUE_CURRENT,
   9619                                              startq + i, &value64));
   9620                      COMPILER_64_ADD_64(sum, value64);
   9621                 }
   9622             }
   9623             COMPILER_64_UMUL_32(sum, _BCM_TR3_BYTES_PER_CELL);
   9624             *value = sum;
   9625         }
   9626         break;
   9627     
   9628     case bcmCosqStatEgressUCQueueBytesPeak:
   9629         if (BCM_GPORT_IS_SCHEDULER(port)) {
   9630             BCM_IF_ERROR_RETURN
   9631                 (_bcm_tr3_cosq_node_get(unit, port, 0, NULL, 
   9632                                         &local_port, NULL, &node));
   9633             BCM_IF_ERROR_RETURN(
   9634                    _bcm_tr3_cosq_child_node_at_input(node, cosq, &node));
   9635             port = node->gport;
   9636         }
   9637 
   9638         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
   9639             BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port)) {
   9640             BCM_IF_ERROR_RETURN
   9641                 (_bcm_tr3_cosq_index_resolve
   9642                  (unit, port, cosq, _BCM_TR3_COSQ_INDEX_STYLE_EGR_PERQ_UCAST,
   9643                   &local_port, &startq, NULL));
   9644             /* coverity[NEGATIVE_RETURNS: FALSE] */
   9645             BCM_IF_ERROR_RETURN
   9646                 (counter_get(unit, local_port,
   9647                                  SOC_COUNTER_NON_DMA_UC_QUEUE_PEAK, startq,
   9648                                  value));
   9649             COMPILER_64_UMUL_32(*value, _BCM_TR3_BYTES_PER_CELL);
   9650         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
   9651             return BCM_E_PARAM;
   9652         } else {
   9653             BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_localport_resolve(unit, port, &local_port));
   9654             BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_port_has_ets(unit, port));
   9655             COMPILER_64_ZERO(sum);
   9656             if (cosq == BCM_COS_INVALID) {
   9657                 from_cos = 0;
   9658                 to_cos = (IS_CPU_PORT(unit, local_port)) ? 
   9659                             NUM_CPU_COSQ(unit) - 1 : _TR3_NUM_COS(unit) - 1;
   9660             } else {
   9661                 from_cos = to_cos = cosq;
   9662             }
   9663 
   9664             if (IS_CPU_PORT(unit, local_port)) {
   9665                 return BCM_E_PARAM;
   9666             }
   9667             for (ci = from_cos; ci <= to_cos; ci++) {
   9668                 BCM_IF_ERROR_RETURN
   9669                       (_bcm_tr3_cosq_index_resolve
   9670                             (unit, port, ci, _BCM_TR3_COSQ_INDEX_STYLE_EGR_PERQ_UCAST,
   9671                              &local_port, &startq, &numq));
   9672                 for (i = 0; i < numq; i++) {
   9673                         /* coverity[NEGATIVE_RETURNS: FALSE] */
   9674                      BCM_IF_ERROR_RETURN
   9675                             (counter_get(unit, local_port,
   9676                                              SOC_COUNTER_NON_DMA_UC_QUEUE_PEAK,
   9677                                              startq + i, &value64));
   9678                      COMPILER_64_ADD_64(sum, value64);
   9679                 }
   9680             }
   9681             COMPILER_64_UMUL_32(sum, _BCM_TR3_BYTES_PER_CELL);
   9682             *value = sum;
   9683         }
   9684         break;
   9685 
   9686     case bcmCosqStatEgressUCQueueBytesCurrent:
   9687         if (BCM_GPORT_IS_SCHEDULER(port)) {
   9688             BCM_IF_ERROR_RETURN
   9689                 (_bcm_tr3_cosq_node_get(unit, port, 0, NULL, 
   9690                                         &local_port, NULL, &node));
   9691             BCM_IF_ERROR_RETURN(
   9692                    _bcm_tr3_cosq_child_node_at_input(node, cosq, &node));
   9693             port = node->gport;
   9694         }
   9695 
   9696         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
   9697             BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port)) {
   9698             BCM_IF_ERROR_RETURN
   9699                 (_bcm_tr3_cosq_index_resolve
   9700                  (unit, port, cosq, _BCM_TR3_COSQ_INDEX_STYLE_EGR_PERQ_UCAST,
   9701                   &local_port, &startq, NULL));
   9702             /* coverity[NEGATIVE_RETURNS: FALSE] */
   9703             BCM_IF_ERROR_RETURN
   9704                 (counter_get(unit, local_port,
   9705                                  SOC_COUNTER_NON_DMA_UC_QUEUE_CURRENT, startq,
   9706                                  value));
   9707             COMPILER_64_UMUL_32(*value, _BCM_TR3_BYTES_PER_CELL);
   9708         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
   9709             return BCM_E_PARAM;
   9710         } else {
   9711             BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_localport_resolve(unit, port, &local_port));
   9712             BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_port_has_ets(unit, port));
   9713 
   9714             if (IS_CPU_PORT(unit, local_port)) {
   9715                 return BCM_E_PARAM;
   9716             }
   9717             COMPILER_64_ZERO(sum);
   9718             if (cosq == BCM_COS_INVALID) {
   9719                 from_cos = 0;
   9720                 to_cos = (IS_CPU_PORT(unit, local_port)) ? 
   9721                             NUM_CPU_COSQ(unit) - 1 : _TR3_NUM_COS(unit) - 1;
   9722             } else {
   9723                 from_cos = to_cos = cosq;
   9724             }
   9725 
   9726             for (ci = from_cos; ci <= to_cos; ci++) {
   9727                 BCM_IF_ERROR_RETURN
   9728                         (_bcm_tr3_cosq_index_resolve
   9729                             (unit, port, ci, _BCM_TR3_COSQ_INDEX_STYLE_EGR_PERQ_UCAST,
   9730                              &local_port, &startq, &numq));
   9731                 for (i = 0; i < numq; i++) {
   9732                         /* coverity[NEGATIVE_RETURNS: FALSE] */
   9733                     BCM_IF_ERROR_RETURN
   9734                         (counter_get(unit, local_port,
   9735                                              SOC_COUNTER_NON_DMA_UC_QUEUE_CURRENT,
   9736                                              startq + i, &value64));
   9737                     COMPILER_64_ADD_64(sum, value64);
   9738                }
   9739             }
   9740             COMPILER_64_UMUL_32(sum, _BCM_TR3_BYTES_PER_CELL);
   9741             *value = sum;
   9742         }
   9743         break;
   9744 
   9745     case bcmCosqStatUCDroppedPackets:
   9746         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
   9747             BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port) ||
   9748             BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) ||
   9749             BCM_GPORT_IS_SCHEDULER(port)) {
   9750             return BCM_E_PARAM;
   9751         }
   9752         else {
   9753             BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_localport_resolve(unit, port, &local_port));
   9754             COMPILER_64_ZERO(sum);
   9755             if (cosq == BCM_COS_INVALID) {
   9756                 from_cos = 0;
   9757                 if (IS_CPU_PORT(unit, local_port)) {
   9758                     to_cos = NUM_CPU_COSQ(unit) - 1;
   9759                 } else if (IS_TR3_HSP_PORT(unit, local_port)) {
   9760                     to_cos = _TR3_NUM_HSP_COSQ - 1;
   9761                 } else {
   9762                     to_cos = _TR3_NUM_COS(unit) - 1;
   9763                 }
   9764             } else {
   9765                 from_cos = to_cos = cosq;
   9766             }
   9767             for (ci = from_cos; ci <= to_cos; ci++) {
   9768                 BCM_IF_ERROR_RETURN
   9769                     (_bcm_tr3_cosq_index_resolve
   9770                      (unit, port, ci, _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE,
   9771                       &local_port, &startq, &numq));
   9772                 for (i = 0; i < numq; i++) {
   9773                     /* coverity[NEGATIVE_RETURNS: FALSE] */
   9774                     BCM_IF_ERROR_RETURN
   9775                         (counter_get(unit, REG_PORT_ANY,
   9776                                      SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_UC,
   9777                                          startq + i, &value64));
   9778                     COMPILER_64_ADD_64(sum, value64);
   9779                 }
   9780             }
   9781             *value = sum;
   9782         }
   9783         break;
   9784         
   9785     case bcmCosqStatMCDroppedPackets:
   9786         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
   9787             BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port) ||
   9788             BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) ||
   9789             BCM_GPORT_IS_SCHEDULER(port)) {
   9790             return BCM_E_PARAM;
   9791         }
   9792         else {
   9793             BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_localport_resolve(unit, port, &local_port));
   9794             COMPILER_64_ZERO(sum);
   9795             if (cosq == BCM_COS_INVALID) {
   9796                 from_cos = 0;
   9797                 if (IS_CPU_PORT(unit, local_port)) {
   9798                     to_cos = NUM_CPU_COSQ(unit) - 1;
   9799                 } else if (IS_TR3_HSP_PORT(unit, local_port)) {
   9800                     to_cos = _TR3_NUM_HSP_COSQ - 1;
   9801                 } else {
   9802                     to_cos = _TR3_NUM_COS(unit) - 1;
   9803                 }
   9804             } else {
   9805                 from_cos = to_cos = cosq;
   9806             }
   9807             for (ci = from_cos; ci <= to_cos; ci++) {
   9808                 BCM_IF_ERROR_RETURN
   9809                     (_bcm_tr3_cosq_index_resolve
   9810                      (unit, port, ci, _BCM_TR3_COSQ_INDEX_STYLE_MCAST_QUEUE,
   9811                       &local_port, &startq, &numq));
   9812                 for (i = 0; i < numq; i++) {
   9813                     /* coverity[NEGATIVE_RETURNS: FALSE] */
   9814                     BCM_IF_ERROR_RETURN
   9815                         (counter_get(unit, REG_PORT_ANY,
   9816                                      SOC_COUNTER_NON_DMA_COSQ_DROP_PKT,
   9817                                          startq + i - 1024, &value64));
   9818                     COMPILER_64_ADD_64(sum, value64);
   9819                 }
   9820             }
   9821             *value = sum;
   9822         }
   9823         break;
   9824         
   9825     case bcmCosqStatUCDroppedBytes:
   9826         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
   9827             BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port) ||
   9828             BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) ||
   9829             BCM_GPORT_IS_SCHEDULER(port)) {
   9830             return BCM_E_PARAM;
   9831         }
   9832         else {
   9833             BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_localport_resolve(unit, port, &local_port));
   9834             COMPILER_64_ZERO(sum);
   9835             if (cosq == BCM_COS_INVALID) {
   9836                 from_cos = 0;
   9837                 if (IS_CPU_PORT(unit, local_port)) {
   9838                     to_cos = NUM_CPU_COSQ(unit) - 1;
   9839                 } else if (IS_TR3_HSP_PORT(unit, local_port)) {
   9840                     to_cos = _TR3_NUM_HSP_COSQ - 1;
   9841                 } else {
   9842                     to_cos = _TR3_NUM_COS(unit) - 1;
   9843                 }
   9844             } else {
   9845                 from_cos = to_cos = cosq;
   9846             }
   9847             for (ci = from_cos; ci <= to_cos; ci++) {
   9848                 BCM_IF_ERROR_RETURN
   9849                     (_bcm_tr3_cosq_index_resolve
   9850                      (unit, port, ci, _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE,
   9851                       &local_port, &startq, &numq));
   9852                 for (i = 0; i < numq; i++) {
   9853                     /* coverity[NEGATIVE_RETURNS: FALSE] */
   9854                     BCM_IF_ERROR_RETURN
   9855                         (counter_get(unit, REG_PORT_ANY,
   9856                                      SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE_UC,
   9857                                          startq + i, &value64));
   9858                     COMPILER_64_ADD_64(sum, value64);
   9859                 }
   9860             }
   9861             *value = sum;
   9862         }
   9863         break;
   9864         
   9865     case bcmCosqStatMCDroppedBytes:
   9866         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
   9867             BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port) ||
   9868             BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) ||
   9869             BCM_GPORT_IS_SCHEDULER(port)) {
   9870             return BCM_E_PARAM;
   9871         }
   9872         else {
   9873             BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_localport_resolve(unit, port, &local_port));
   9874             COMPILER_64_ZERO(sum);
   9875             if (cosq == BCM_COS_INVALID) {
   9876                 from_cos = 0;
   9877                 if (IS_CPU_PORT(unit, local_port)) {
   9878                     to_cos = NUM_CPU_COSQ(unit) - 1;
   9879                 } else if (IS_TR3_HSP_PORT(unit, local_port)) {
   9880                     to_cos = _TR3_NUM_HSP_COSQ - 1;
   9881                 } else {
   9882                     to_cos = _TR3_NUM_COS(unit) - 1;
   9883                 }
   9884             } else {
   9885                 from_cos = to_cos = cosq;
   9886             }
   9887             for (ci = from_cos; ci <= to_cos; ci++) {
   9888                 BCM_IF_ERROR_RETURN
   9889                     (_bcm_tr3_cosq_index_resolve
   9890                      (unit, port, ci, _BCM_TR3_COSQ_INDEX_STYLE_MCAST_QUEUE,
   9891                       &local_port, &startq, &numq));
   9892                 for (i = 0; i < numq; i++) {
   9893                     /* coverity[NEGATIVE_RETURNS: FALSE] */
   9894                     BCM_IF_ERROR_RETURN
   9895                         (counter_get(unit, REG_PORT_ANY,
   9896                                      SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE,
   9897                                          startq + i - 1024, &value64));
   9898                     COMPILER_64_ADD_64(sum, value64);
   9899                 }
   9900             }
   9901             *value = sum;
   9902         }
   9903         break;
   9904         
   9905     case bcmCosqStatUCOutPackets:
   9906         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
   9907             BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port) ||
   9908             BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) ||
   9909             BCM_GPORT_IS_SCHEDULER(port)) {
   9910             return BCM_E_PARAM;
   9911         }
   9912         else {
   9913             BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_localport_resolve(unit, port, &local_port));
   9914             COMPILER_64_ZERO(sum);
   9915             if (cosq == BCM_COS_INVALID) {
   9916                 from_cos = 0;
   9917                 if (IS_CPU_PORT(unit, local_port)) {
   9918                     to_cos = NUM_CPU_COSQ(unit) - 1;
   9919                 } else if (IS_TR3_HSP_PORT(unit, local_port)) {
   9920                     to_cos = _TR3_NUM_HSP_COSQ - 1;
   9921                 } else {
   9922                     to_cos = _TR3_NUM_COS(unit) - 1;
   9923                 }
   9924             } else {
   9925                 from_cos = to_cos = cosq;
   9926             }
   9927             for (ci = from_cos; ci <= to_cos; ci++) {
   9928                 BCM_IF_ERROR_RETURN
   9929                     (_bcm_tr3_cosq_index_resolve
   9930                      (unit, port, ci, _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE,
   9931                       &local_port, &startq, &numq));
   9932                 for (i = 0; i < numq; i++) {
   9933                     /* coverity[NEGATIVE_RETURNS: FALSE] */
   9934                     BCM_IF_ERROR_RETURN
   9935                         (counter_get(unit, REG_PORT_ANY,
   9936                                      SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT_UC,
   9937                                          startq + i, &value64));
   9938                     COMPILER_64_ADD_64(sum, value64);
   9939                 }
   9940             }
   9941             *value = sum;
   9942         }
   9943         break;
   9944         
   9945     case bcmCosqStatMCOutPackets:
   9946         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
   9947             BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port) ||
   9948             BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) ||
   9949             BCM_GPORT_IS_SCHEDULER(port)) {
   9950             return BCM_E_PARAM;
   9951         }
   9952         else {
   9953             BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_localport_resolve(unit, port, &local_port));
   9954             COMPILER_64_ZERO(sum);
   9955             if (cosq == BCM_COS_INVALID) {
   9956                 from_cos = 0;
   9957                 if (IS_CPU_PORT(unit, local_port)) {
   9958                     to_cos = NUM_CPU_COSQ(unit) - 1;
   9959                 } else if (IS_TR3_HSP_PORT(unit, local_port)) {
   9960                     to_cos = _TR3_NUM_HSP_COSQ - 1;
   9961                 } else {
   9962                     to_cos = _TR3_NUM_COS(unit) - 1;
   9963                 }
   9964             } else {
   9965                 from_cos = to_cos = cosq;
   9966             }
   9967             for (ci = from_cos; ci <= to_cos; ci++) {
   9968                 BCM_IF_ERROR_RETURN
   9969                     (_bcm_tr3_cosq_index_resolve
   9970                      (unit, port, ci, _BCM_TR3_COSQ_INDEX_STYLE_MCAST_QUEUE,
   9971                       &local_port, &startq, &numq));
   9972                 for (i = 0; i < numq; i++) {
   9973                     /* coverity[NEGATIVE_RETURNS: FALSE] */
   9974                     BCM_IF_ERROR_RETURN
   9975                         (counter_get(unit, REG_PORT_ANY,
   9976                                      SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT,
   9977                                          startq + i, &value64));
   9978                     COMPILER_64_ADD_64(sum, value64);
   9979                 }
   9980             }
   9981             *value = sum;
   9982         }
   9983         break;
   9984         
   9985     case bcmCosqStatUCOutBytes:
   9986         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
   9987             BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port) ||
   9988             BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) ||
   9989             BCM_GPORT_IS_SCHEDULER(port)) {
   9990             return BCM_E_PARAM;
   9991         }
   9992         else {
   9993             BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_localport_resolve(unit, port, &local_port));
   9994             COMPILER_64_ZERO(sum);
   9995             if (cosq == BCM_COS_INVALID) {
   9996                 from_cos = 0;
   9997                 if (IS_CPU_PORT(unit, local_port)) {
   9998                     to_cos = NUM_CPU_COSQ(unit) - 1;
   9999                 } else if (IS_TR3_HSP_PORT(unit, local_port)) {
  10000                     to_cos = _TR3_NUM_HSP_COSQ - 1;
  10001                 } else {
  10002                     to_cos = _TR3_NUM_COS(unit) - 1;
  10003                 }
  10004             } else {
  10005                 from_cos = to_cos = cosq;
  10006             }
  10007             for (ci = from_cos; ci <= to_cos; ci++) {
  10008                 BCM_IF_ERROR_RETURN
  10009                     (_bcm_tr3_cosq_index_resolve
  10010                      (unit, port, ci, _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE,
  10011                       &local_port, &startq, &numq));
  10012                 for (i = 0; i < numq; i++) {
  10013                     /* coverity[NEGATIVE_RETURNS: FALSE] */
  10014                     BCM_IF_ERROR_RETURN
  10015                         (counter_get(unit, REG_PORT_ANY,
  10016                                      SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE_UC,
  10017                                          startq + i, &value64));
  10018                     COMPILER_64_ADD_64(sum, value64);
  10019                 }
  10020             }
  10021             *value = sum;
  10022         }
  10023         break;
  10024         
  10025     case bcmCosqStatMCOutBytes:
  10026         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
  10027             BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(port) ||
  10028             BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) ||
  10029             BCM_GPORT_IS_SCHEDULER(port)) {
  10030             return BCM_E_PARAM;
  10031         }
  10032         else {
  10033             BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_localport_resolve(unit, port, &local_port));
  10034             COMPILER_64_ZERO(sum);
  10035             if (cosq == BCM_COS_INVALID) {
  10036                 from_cos = 0;
  10037                 if (IS_CPU_PORT(unit, local_port)) {
  10038                     to_cos = NUM_CPU_COSQ(unit) - 1;
  10039                 } else if (IS_TR3_HSP_PORT(unit, local_port)) {
  10040                     to_cos = _TR3_NUM_HSP_COSQ - 1;
  10041                 } else {
  10042                     to_cos = _TR3_NUM_COS(unit) - 1;
  10043                 }
  10044             } else {
  10045                 from_cos = to_cos = cosq;
  10046             }
  10047             for (ci = from_cos; ci <= to_cos; ci++) {
  10048                 BCM_IF_ERROR_RETURN
  10049                     (_bcm_tr3_cosq_index_resolve
  10050                      (unit, port, ci, _BCM_TR3_COSQ_INDEX_STYLE_MCAST_QUEUE,
  10051                       &local_port, &startq, &numq));
  10052                 for (i = 0; i < numq; i++) {
  10053                     /* coverity[NEGATIVE_RETURNS: FALSE] */
  10054                     BCM_IF_ERROR_RETURN
  10055                         (counter_get(unit, REG_PORT_ANY,
  10056                                      SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE,
  10057                                          startq + i, &value64));
  10058                     COMPILER_64_ADD_64(sum, value64);
  10059                 }
  10060             }
  10061             *value = sum;
  10062         }
  10063         break;
  10064 
  10065     default:
  10066         return BCM_E_PARAM;
  10067     }
  10068 
  10069     return BCM_E_NONE;
  10070 }
  10071 
  10072 /*
  10073  * Function:
  10074  *     _bcm_tr3_cosq_quantize_table_set
  10075  * Purpose:
  10076  *     Generate quantized feedback lookup table
  10077  * Parameters:
  10078  *     unit          - (IN) unit number
  10079  *     profile_index - (IN) profile index
  10080  *     weight_code   - (IN) weight encoding
  10081  *     set_point     - (IN) queue size set point
  10082  *     active_offset - (OUT) most significant non-zero bit position
  10083  * Returns:
  10084  *     BCM_E_XXX
  10085  * Notes:
  10086  *     The formular to quantize feedback value is:
  10087  *     quantized_feedbad = celling(feedback / max_feedback * 63)
  10088  *         where max_feedback = (2 * cpW + 1) * cpQsp
  10089  *         cpW is feedback weight
  10090  *         cpQsp is queue size set point
  10091  */
  10092 STATIC int
  10093 _bcm_tr3_cosq_quantize_table_set(int unit, int profile_index, int weight_code,
  10094                                 int set_point, int *active_offset)
  10095 {
  10096     int ref_count;
  10097     int weight_x_4, feedback, max_feedback, quantized_feedback, shift;
  10098     int base_index, index;
  10099 
  10100     /* weight = 2 ** (weight_code - 2) e.g. 0 for 1/4, 1 for 1/2, ...  */
  10101     weight_x_4 = 1 << weight_code;
  10102     max_feedback = ((2 * weight_x_4 + 4) * set_point + 3) / 4;
  10103     shift = 0;
  10104     while ((max_feedback >> shift) > 127) {
  10105         shift++;
  10106     }
  10107 
  10108     BCM_IF_ERROR_RETURN
  10109         (soc_profile_reg_ref_count_get(unit, _bcm_tr3_feedback_profile[unit],
  10110                                        profile_index, &ref_count));
  10111 
  10112     /*
  10113      * Hardware use lookup table to find quantized feedback in order to avoid
  10114      * division, use most significant 7-bit of feedback value as lookup table
  10115      * index to find quantized_feedback value
  10116      */
  10117     if (ref_count == 1) {
  10118         base_index = profile_index << 7;
  10119         for (index = 0; index < 128; index++) {
  10120             feedback = index << shift;
  10121             if (feedback > max_feedback) {
  10122                 quantized_feedback = 63;
  10123             } else {
  10124                 quantized_feedback = (feedback * 63 + max_feedback - 1) /
  10125                     max_feedback;
  10126             }
  10127             BCM_IF_ERROR_RETURN
  10128                 (soc_mem_field32_modify(unit, MMU_QCN_QFBTBm,
  10129                                         base_index  + index, CPQ_QNTZFBf,
  10130                                         quantized_feedback));
  10131         }
  10132     }
  10133 
  10134     *active_offset = shift + 6;
  10135 
  10136     return BCM_E_NONE;
  10137 }
  10138 
  10139 
  10140 STATIC int
  10141 _bcm_tr3_cosq_sample_int_table_set(int unit, int min, int max,
  10142                                   uint32 *profile_index)
  10143 {
  10144     mmu_qcn_sitb_entry_t sitb_entries[64];
  10145     void *entries[1];
  10146     int i, j, center, inc, value, index;
  10147 
  10148     sal_memset(sitb_entries, 0, sizeof(sitb_entries));
  10149     entries[0] = &sitb_entries;
  10150     for (i = 0; i < 8; i++) {
  10151         center = max - (max - min) * i / 7;
  10152         inc = (max - min) / 7 / 8;
  10153         for (j = 0; j < 8; j++, inc = -inc) {
  10154             index = i * 8 + j;
  10155             value = center + (j + 1) / 2 * inc;
  10156             if (value > 255) {
  10157                 value = 255;
  10158             } else if (value < 1) {
  10159                 value = 1;
  10160             }
  10161             soc_mem_field32_set(unit, MMU_QCN_SITBm, &sitb_entries[index],
  10162                                 CPQ_SIf, value);
  10163         }
  10164     }
  10165 
  10166     return soc_profile_mem_add(unit, _bcm_tr3_sample_int_profile[unit], entries,
  10167                                64, (uint32 *)profile_index);
  10168 }
  10169 
  10170 /*
  10171  * Function:
  10172  *     bcm_tr3_cosq_congestion_queue_set
  10173  * Purpose:
  10174  *     Enable/Disable a cos queue as congestion managed queue
  10175  * Parameters:
  10176  *     unit          - (IN) unit number
  10177  *     port          - (IN) port number or GPORT identifier
  10178  *     cosq          - (IN) COS queue number
  10179  *     index         - (IN) congestion managed queue index
  10180  * Returns:
  10181  *     BCM_E_XXX
  10182  */
  10183 int
  10184 bcm_tr3_cosq_congestion_queue_set(int unit, bcm_port_t port,
  10185                                  bcm_cos_queue_t cosq, int index)
  10186 {
  10187     bcm_port_t local_port;
  10188     uint32 rval;
  10189     uint64 rval64, *rval64s[1];
  10190     mmu_qcn_enable_entry_t enable_entry;
  10191     int active_offset, qindex;
  10192     uint32 profile_index, sample_profile_index;
  10193     int weight_code, set_point;
  10194 
  10195     if (cosq < 0 || cosq >= _TR3_NUM_COS(unit)) {
  10196         return BCM_E_PARAM;
  10197     }
  10198     if (index < -1 || index >= 512) {
  10199         return BCM_E_PARAM;
  10200     }
  10201 
  10202     BCM_IF_ERROR_RETURN
  10203         (_bcm_tr3_cosq_localport_resolve(unit, port, &local_port));
  10204 
  10205     BCM_IF_ERROR_RETURN
  10206         (_bcm_tr3_cosq_index_resolve(unit, port, cosq,
  10207                                     _BCM_TR3_COSQ_INDEX_STYLE_QCN,
  10208                                     &local_port, &qindex, NULL));
  10209 
  10210     BCM_IF_ERROR_RETURN(soc_mem_read(unit, MMU_QCN_ENABLEm,
  10211                                      MEM_BLOCK_ANY, qindex, &enable_entry));
  10212     if (index == -1) {
  10213         if (!soc_mem_field32_get(unit, MMU_QCN_ENABLEm, &enable_entry, CPQ_ENf)) {
  10214             return BCM_E_NONE;
  10215         }
  10216 
  10217         index = soc_mem_field32_get(unit, MMU_QCN_ENABLEm, &enable_entry,
  10218                                     CPQ_PROFILE_INDEXf);
  10219         soc_mem_field32_set(unit, MMU_QCN_ENABLEm, &enable_entry,
  10220                             CPQ_ENf, 0);
  10221         BCM_IF_ERROR_RETURN
  10222             (soc_mem_write(unit, MMU_QCN_ENABLEm, MEM_BLOCK_ANY, qindex,
  10223                            &enable_entry));
  10224 
  10225         profile_index =
  10226             soc_mem_field32_get(unit, MMU_QCN_ENABLEm, &enable_entry,
  10227                                  EQTB_INDEXf);
  10228 
  10229         BCM_IF_ERROR_RETURN
  10230             (soc_profile_reg_delete(unit, _bcm_tr3_feedback_profile[unit],
  10231                                     profile_index));
  10232 
  10233         profile_index =
  10234             soc_mem_field32_get(unit, MMU_QCN_ENABLEm, &enable_entry, SITB_SELf);
  10235 
  10236         BCM_IF_ERROR_RETURN
  10237             (soc_profile_mem_delete(unit, _bcm_tr3_sample_int_profile[unit],
  10238                                 profile_index * 64));
  10239     } else {
  10240         if (soc_mem_field32_get(unit, MMU_QCN_ENABLEm, 
  10241                                     &enable_entry, CPQ_ENf)) {
  10242             return BCM_E_BUSY;
  10243         }
  10244 
  10245         /* Use hardware reset value as default quantize setting */
  10246         weight_code = 2;
  10247         set_point = 0x96;
  10248         rval = 0;
  10249         soc_reg_field_set(unit, MMU_QCN_CPQ_SEQr, &rval, CPWf, weight_code);
  10250         soc_reg_field_set(unit, MMU_QCN_CPQ_SEQr, &rval, CPQEQf, set_point);
  10251         COMPILER_64_SET(rval64, 0, rval);
  10252         rval64s[0] = &rval64;
  10253         BCM_IF_ERROR_RETURN
  10254             (soc_profile_reg_add(unit, _bcm_tr3_feedback_profile[unit],
  10255                                  rval64s, 1, (uint32 *)&profile_index));
  10256 
  10257         /* Update quantized feedback calculation lookup table */
  10258         BCM_IF_ERROR_RETURN
  10259             (_bcm_tr3_cosq_quantize_table_set(unit, profile_index, weight_code,
  10260                                              set_point, &active_offset));
  10261 
  10262         /* Pick some sample interval */
  10263         BCM_IF_ERROR_RETURN
  10264             (_bcm_tr3_cosq_sample_int_table_set(unit, 13, 127,
  10265                                                &sample_profile_index));
  10266 
  10267         soc_mem_field32_set(unit, MMU_QCN_ENABLEm, &enable_entry,
  10268                             QNTZ_ACT_OFFSETf, active_offset);
  10269 
  10270         soc_mem_field32_set(unit, MMU_QCN_ENABLEm, &enable_entry,
  10271                             SITB_SELf, sample_profile_index/64);
  10272 
  10273         soc_mem_field32_set(unit, MMU_QCN_ENABLEm, &enable_entry,
  10274                             CPQ_INDEXf, index);
  10275 
  10276         soc_mem_field32_set(unit, MMU_QCN_ENABLEm, &enable_entry,
  10277                             CPQ_ENf, 1);
  10278 
  10279         BCM_IF_ERROR_RETURN
  10280             (soc_mem_write(unit, MMU_QCN_ENABLEm, MEM_BLOCK_ANY, qindex,
  10281                            &enable_entry));
  10282     }
  10283 
  10284     return BCM_E_NONE;
  10285 }
  10286 
  10287 /*
  10288  * Function:
  10289  *     bcm_tr3_cosq_congestion_queue_get
  10290  * Purpose:
  10291  *     Get congestion managed queue index of the specified cos queue
  10292  * Parameters:
  10293  *     unit          - (IN) unit number
  10294  *     port          - (IN) port number or GPORT identifier
  10295  *     cosq          - (IN) COS queue number
  10296  *     index         - (OUT) congestion managed queue index
  10297  * Returns:
  10298  *     BCM_E_XXX
  10299  */
  10300 int
  10301 bcm_tr3_cosq_congestion_queue_get(int unit, bcm_port_t port,
  10302                                  bcm_cos_queue_t cosq, int *index)
  10303 {
  10304     bcm_port_t local_port;
  10305     int qindex;
  10306     mmu_qcn_enable_entry_t entry;
  10307 
  10308     BCM_IF_ERROR_RETURN
  10309         (_bcm_tr3_cosq_localport_resolve(unit, port, &local_port));
  10310 
  10311     if (cosq < 0 || cosq >= _TR3_NUM_COS(unit)) {
  10312         return BCM_E_PARAM;
  10313     }
  10314     if (index == NULL) {
  10315         return BCM_E_PARAM;
  10316     }
  10317 
  10318     BCM_IF_ERROR_RETURN
  10319         (_bcm_tr3_cosq_index_resolve(unit, port, cosq,
  10320                                     _BCM_TR3_COSQ_INDEX_STYLE_QCN,
  10321                                     &local_port, &qindex, NULL));
  10322 
  10323     BCM_IF_ERROR_RETURN
  10324         (soc_mem_read(unit, MMU_QCN_ENABLEm, MEM_BLOCK_ANY, qindex, &entry));
  10325     if (soc_mem_field32_get(unit, MMU_QCN_ENABLEm, &entry, CPQ_ENf)) {
  10326         *index = soc_mem_field32_get(unit, MMU_QCN_ENABLEm, &entry,
  10327                                      CPQ_INDEXf);
  10328     } else {
  10329         *index = -1;
  10330     }
  10331 
  10332     return BCM_E_NONE;
  10333 }
  10334 
  10335 /*
  10336  * Function:
  10337  *     bcm_tr3_cosq_congestion_quantize_set
  10338  * Purpose:
  10339  *     Set quantized congestion feedback algorithm parameters
  10340  * Parameters:
  10341  *     unit          - (IN) unit number
  10342  *     port          - (IN) port number or GPORT identifier
  10343  *     cosq          - (IN) COS queue number
  10344  *     weight_code   - (IN) weight encoding (use -1 for unchange)
  10345  *     set_point     - (IN) queue size set point (use -1 for unchange)
  10346  * Returns:
  10347  *     BCM_E_XXX
  10348  */
  10349 int
  10350 bcm_tr3_cosq_congestion_quantize_set(int unit, bcm_port_t port,
  10351                                     bcm_cos_queue_t cosq, int weight_code,
  10352                                     int set_point)
  10353 {
  10354     bcm_port_t local_port;
  10355     uint32 rval;
  10356     uint64 rval64, *rval64s[1];
  10357     mmu_qcn_enable_entry_t enable_entry;
  10358     int cpq_index, active_offset, qindex;
  10359     uint32 profile_index, old_profile_index;
  10360 
  10361     BCM_IF_ERROR_RETURN
  10362         (_bcm_tr3_cosq_localport_resolve(unit, port, &local_port));
  10363 
  10364     BCM_IF_ERROR_RETURN
  10365         (bcm_tr3_cosq_congestion_queue_get(unit, port, cosq, &cpq_index));
  10366     if (cpq_index == -1) {
  10367         /* The cosq specified is not enabled as congestion managed queue */
  10368         return BCM_E_PARAM;
  10369     }
  10370 
  10371     BCM_IF_ERROR_RETURN
  10372         (_bcm_tr3_cosq_index_resolve(unit, port, cosq,
  10373                                     _BCM_TR3_COSQ_INDEX_STYLE_QCN,
  10374                                     &local_port, &qindex, NULL));
  10375 
  10376     BCM_IF_ERROR_RETURN(soc_mem_read(unit, MMU_QCN_ENABLEm,
  10377                                      MEM_BLOCK_ANY, qindex, &enable_entry));
  10378     old_profile_index =
  10379         soc_mem_field32_get(unit, MMU_QCN_ENABLEm, &enable_entry, CPQ_PROFILE_INDEXf);
  10380 
  10381     BCM_IF_ERROR_RETURN(READ_MMU_QCN_CPQ_SEQr(unit, old_profile_index, &rval));
  10382     if (weight_code == -1) {
  10383         weight_code = soc_reg_field_get(unit, MMU_QCN_CPQ_SEQr, rval, CPWf);
  10384     } else {
  10385         if (weight_code < 0 || weight_code > 7) {
  10386             return BCM_E_PARAM;
  10387         }
  10388         soc_reg_field_set(unit, MMU_QCN_CPQ_SEQr, &rval, CPWf, weight_code);
  10389     }
  10390     if (set_point == -1) {
  10391         set_point = soc_reg_field_get(unit, MMU_QCN_CPQ_SEQr, rval, CPQEQf);
  10392     } else {
  10393         if (set_point < 0 || set_point > 0xffff) {
  10394             return BCM_E_PARAM;
  10395         }
  10396         soc_reg_field_set(unit, MMU_QCN_CPQ_SEQr, &rval, CPQEQf, set_point);
  10397     }
  10398     COMPILER_64_SET(rval64, 0, rval);
  10399     rval64s[0] = &rval64;
  10400     /* Add new feedback parameter profile */
  10401     BCM_IF_ERROR_RETURN
  10402         (soc_profile_reg_add(unit, _bcm_tr3_feedback_profile[unit], rval64s,
  10403                              1, (uint32 *)&profile_index));
  10404     /* Delete original feedback parameter profile */
  10405     BCM_IF_ERROR_RETURN
  10406         (soc_profile_reg_delete(unit, _bcm_tr3_feedback_profile[unit],
  10407                                 old_profile_index));
  10408 
  10409     /* Update quantized feedback calculation lookup table */
  10410     BCM_IF_ERROR_RETURN
  10411         (_bcm_tr3_cosq_quantize_table_set(unit, profile_index, weight_code,
  10412                                          set_point, &active_offset));
  10413 
  10414     soc_mem_field32_set(unit, MMU_QCN_ENABLEm, &enable_entry,
  10415                             QNTZ_ACT_OFFSETf, active_offset);
  10416     soc_mem_field32_set(unit, MMU_QCN_ENABLEm, &enable_entry,
  10417                             CPQ_PROFILE_INDEXf, profile_index);
  10418     BCM_IF_ERROR_RETURN
  10419             (soc_mem_write(unit, MMU_QCN_ENABLEm, MEM_BLOCK_ANY, qindex,
  10420                            &enable_entry));
  10421 
  10422     return BCM_E_NONE;
  10423 }
  10424 
  10425 /*
  10426  * Function:
  10427  *     bcm_tr3_cosq_congestion_quantize_get
  10428  * Purpose:
  10429  *     Get quantized congestion feedback algorithm parameters
  10430  * Parameters:
  10431  *     unit          - (IN) unit number
  10432  *     port          - (IN) port number or GPORT identifier
  10433  *     cosq          - (IN) COS queue number
  10434  *     weight_code   - (OUT) weight encoding
  10435  *     set_point     - (OUT) queue size set point
  10436  * Returns:
  10437  *     BCM_E_XXX
  10438  */
  10439 int
  10440 bcm_tr3_cosq_congestion_quantize_get(int unit, bcm_port_t port,
  10441                                     bcm_cos_queue_t cosq, int *weight_code,
  10442                                     int *set_point)
  10443 {
  10444     bcm_port_t local_port;
  10445     int cpq_index, profile_index, qindex;
  10446     uint32 rval;
  10447     mmu_qcn_enable_entry_t enable_entry;
  10448 
  10449     BCM_IF_ERROR_RETURN
  10450         (_bcm_tr3_cosq_localport_resolve(unit, port, &local_port));
  10451 
  10452     BCM_IF_ERROR_RETURN
  10453         (bcm_tr3_cosq_congestion_queue_get(unit, port, cosq, &cpq_index));
  10454     if (cpq_index == -1) {
  10455         /* The cosq specified is not enabled as congestion managed queue */
  10456         return BCM_E_PARAM;
  10457     }
  10458 
  10459     BCM_IF_ERROR_RETURN
  10460         (_bcm_tr3_cosq_index_resolve(unit, port, cosq,
  10461                                     _BCM_TR3_COSQ_INDEX_STYLE_QCN,
  10462                                     &local_port, &qindex, NULL));
  10463     BCM_IF_ERROR_RETURN(soc_mem_read(unit, MMU_QCN_ENABLEm,
  10464                                      MEM_BLOCK_ANY, qindex, &enable_entry));
  10465 
  10466     profile_index =
  10467         soc_mem_field32_get(unit, MMU_QCN_ENABLEm, &enable_entry, CPQ_PROFILE_INDEXf);
  10468 
  10469     BCM_IF_ERROR_RETURN(READ_MMU_QCN_CPQ_SEQr(unit, profile_index, &rval));
  10470     if (weight_code != NULL) {
  10471         *weight_code = soc_reg_field_get(unit, MMU_QCN_CPQ_SEQr, rval, CPWf);
  10472     }
  10473     if (set_point != NULL) {
  10474         *set_point = soc_reg_field_get(unit, MMU_QCN_CPQ_SEQr, rval, CPQEQf);
  10475     }
  10476 
  10477     return BCM_E_NONE;
  10478 }
  10479 
  10480 int
  10481 bcm_tr3_cosq_congestion_sample_int_set(int unit, bcm_port_t port,
  10482                                       bcm_cos_queue_t cosq, int min, int max)
  10483 {
  10484     bcm_port_t local_port;
  10485     mmu_qcn_enable_entry_t entry;
  10486     mmu_qcn_sitb_entry_t sitb_entry;
  10487     int qindex;
  10488     uint32 profile_index, old_profile_index;
  10489 
  10490     BCM_IF_ERROR_RETURN
  10491         (_bcm_tr3_cosq_localport_resolve(unit, port, &local_port));
  10492 
  10493     BCM_IF_ERROR_RETURN
  10494         (_bcm_tr3_cosq_index_resolve(unit, port, cosq,
  10495                                     _BCM_TR3_COSQ_INDEX_STYLE_QCN,
  10496                                     &local_port, &qindex, NULL));
  10497 
  10498     BCM_IF_ERROR_RETURN
  10499         (soc_mem_read(unit, MMU_QCN_ENABLEm, MEM_BLOCK_ANY, qindex, &entry));
  10500 
  10501     if (!soc_mem_field32_get(unit, MMU_QCN_ENABLEm, &entry, CPQ_ENf)) {
  10502         return BCM_E_PARAM;
  10503     }
  10504 
  10505     old_profile_index =
  10506         soc_mem_field32_get(unit, MMU_QCN_ENABLEm, &entry, SITB_SELf);
  10507 
  10508     if (max == -1) {
  10509         BCM_IF_ERROR_RETURN(soc_mem_read(unit, MMU_QCN_SITBm, MEM_BLOCK_ANY,
  10510                                          old_profile_index * 64, &sitb_entry));
  10511         max = soc_mem_field32_get(unit, MMU_QCN_SITBm, &sitb_entry, CPQ_SIf);
  10512     } else {
  10513         if (max < 1 || max > 255) {
  10514             return BCM_E_PARAM;
  10515         }
  10516     }
  10517     if (min == -1) {
  10518         BCM_IF_ERROR_RETURN(soc_mem_read(unit, MMU_QCN_SITBm, MEM_BLOCK_ANY,
  10519                                          old_profile_index * 64 + 63,
  10520                                          &sitb_entry));
  10521         min = soc_mem_field32_get(unit, MMU_QCN_SITBm, &sitb_entry, CPQ_SIf);
  10522     } else {
  10523         if (min < 1 || min > 255) {
  10524             return BCM_E_PARAM;
  10525         }
  10526     }
  10527 
  10528     /* Add new sample interval profile */
  10529     BCM_IF_ERROR_RETURN
  10530         (_bcm_tr3_cosq_sample_int_table_set(unit, min, max, &profile_index));
  10531 
  10532     /* Delete original sample interval profile */
  10533     BCM_IF_ERROR_RETURN
  10534         (soc_profile_mem_delete(unit, _bcm_tr3_sample_int_profile[unit],
  10535                                 old_profile_index * 64));
  10536 
  10537     soc_mem_field32_set(unit, MMU_QCN_ENABLEm, &entry, SITB_SELf, 
  10538                         profile_index / 64);
  10539     BCM_IF_ERROR_RETURN(soc_mem_write(unit, MMU_QCN_ENABLEm, MEM_BLOCK_ANY,
  10540                                       qindex, &entry));
  10541     return BCM_E_NONE;
  10542 }
  10543 
  10544 int
  10545 bcm_tr3_cosq_congestion_sample_int_get(int unit, bcm_port_t port,
  10546                                       bcm_cos_queue_t cosq, int *min, int *max)
  10547 {
  10548     bcm_port_t local_port;
  10549     mmu_qcn_enable_entry_t entry;
  10550     mmu_qcn_sitb_entry_t sitb_entry;
  10551     int qindex;
  10552     uint32 old_profile_index;
  10553 
  10554     BCM_IF_ERROR_RETURN
  10555         (_bcm_tr3_cosq_localport_resolve(unit, port, &local_port));
  10556 
  10557     BCM_IF_ERROR_RETURN
  10558         (_bcm_tr3_cosq_index_resolve(unit, port, cosq,
  10559                                     _BCM_TR3_COSQ_INDEX_STYLE_QCN,
  10560                                     &local_port, &qindex, NULL));
  10561 
  10562     BCM_IF_ERROR_RETURN
  10563         (soc_mem_read(unit, MMU_QCN_ENABLEm, MEM_BLOCK_ANY, qindex, &entry));
  10564 
  10565     if (!soc_mem_field32_get(unit, MMU_QCN_ENABLEm, &entry, CPQ_ENf)) {
  10566         return BCM_E_PARAM;
  10567     }
  10568 
  10569     old_profile_index =
  10570     soc_mem_field32_get(unit, MMU_QCN_ENABLEm, &entry, SITB_SELf);
  10571 
  10572     if (max) {
  10573         BCM_IF_ERROR_RETURN(soc_mem_read(unit, MMU_QCN_SITBm, MEM_BLOCK_ANY,
  10574                                      old_profile_index * 64, &sitb_entry));
  10575         *max = soc_mem_field32_get(unit, MMU_QCN_SITBm, &sitb_entry, CPQ_SIf);
  10576     }
  10577 
  10578     if (min) {
  10579         BCM_IF_ERROR_RETURN(soc_mem_read(unit, MMU_QCN_SITBm, MEM_BLOCK_ANY,
  10580                                      old_profile_index * 64 + 63,
  10581                                      &sitb_entry));
  10582         *min = soc_mem_field32_get(unit, MMU_QCN_SITBm, &sitb_entry, CPQ_SIf);
  10583     }
  10584 
  10585     return BCM_E_NONE;
  10586 }
  10587 
  10588 STATIC int
  10589 _bcm_tr3_cosq_egr_pool_set(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
  10590                           bcm_cosq_control_t type, int arg)
  10591 {
  10592     bcm_port_t local_port;
  10593     int startq;
  10594     uint32 rval;
  10595     int num_cells;
  10596     uint32 entry[SOC_MAX_MEM_WORDS];
  10597 
  10598     num_cells = 0;
  10599 
  10600     if (type == bcmCosqControlUCEgressPool) {
  10601         BCM_IF_ERROR_RETURN
  10602             (_bcm_tr3_cosq_index_resolve(unit, gport, cosq,
  10603                                         _BCM_TR3_COSQ_INDEX_STYLE_UC_EGR_POOL,
  10604                                         &local_port, &startq, NULL));
  10605     } else {
  10606         BCM_IF_ERROR_RETURN
  10607             (_bcm_tr3_cosq_index_resolve(unit, gport, cosq,
  10608                                         _BCM_TR3_COSQ_INDEX_STYLE_EGR_POOL,
  10609                                         &local_port, &startq, NULL));
  10610     }
  10611 
  10612     if (type == bcmCosqControlEgressPoolLimitEnable) {
  10613         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
  10614             BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) {
  10615             BCM_IF_ERROR_RETURN(soc_reg32_get(unit, OP_PORT_CONFIG1_CELLr, 
  10616                                             local_port, 0, &rval));
  10617             soc_reg_field_set(unit, OP_PORT_CONFIG1_CELLr, &rval, 
  10618                           PORT_LIMIT_ENABLE_CELLf, arg ? 1 : 0);
  10619             BCM_IF_ERROR_RETURN(soc_reg32_set(unit, OP_PORT_CONFIG1_CELLr, 
  10620                                             local_port, 0, rval));
  10621         } else {
  10622             BCM_IF_ERROR_RETURN(soc_reg32_get(unit, OP_QUEUE_CONFIG1_CELLr, 
  10623                                             local_port, startq, &rval));
  10624             soc_reg_field_set(unit, OP_QUEUE_CONFIG1_CELLr, 
  10625                             &rval, Q_LIMIT_ENABLE_CELLf, arg ? 1 : 0);
  10626 
  10627             BCM_IF_ERROR_RETURN(soc_reg32_set(unit, OP_QUEUE_CONFIG1_CELLr, 
  10628                                                     local_port, startq, rval));
  10629         }
  10630         return BCM_E_NONE;
  10631     } else if (type == bcmCosqControlEgressPool || type == bcmCosqControlUCEgressPool ||
  10632                type == bcmCosqControlMCEgressPool) {
  10633         if (arg < 0 || arg > 3) {
  10634             return BCM_E_PARAM;
  10635         }
  10636     } else if (type == bcmCosqControlEgressPoolLimitBytes ||
  10637                type == bcmCosqControlEgressPoolYellowLimitBytes ||
  10638                type == bcmCosqControlEgressPoolRedLimitBytes) {
  10639         if (arg < 0) {
  10640             return BCM_E_PARAM;
  10641         }
  10642         num_cells = _BCM_TR3_BYTES_TO_CELLS(arg);
  10643         if (num_cells > _BCM_TR3_TOTAL_CELLS) {
  10644             return BCM_E_PARAM;
  10645         }
  10646     }
  10647 
  10648     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
  10649         BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) {
  10650         BCM_IF_ERROR_RETURN(
  10651                 soc_mem_read(unit, MMU_THDO_Q_TO_QGRP_MAPm, MEM_BLOCK_ALL,
  10652                              startq, entry));
  10653     } else {
  10654         BCM_IF_ERROR_RETURN(
  10655             soc_reg32_get(unit, OP_QUEUE_CONFIG1_CELLr, local_port, startq, &rval));
  10656     }
  10657 
  10658 
  10659     /* per service pool settings */
  10660     if (type == bcmCosqControlEgressPoolSharedLimitBytes ||
  10661         type == bcmCosqControlEgressPoolResumeLimitBytes ||
  10662         type == bcmCosqControlEgressPoolYellowSharedLimitBytes ||
  10663         type == bcmCosqControlEgressPoolYellowResumeLimitBytes ||
  10664         type == bcmCosqControlEgressPoolRedSharedLimitBytes ||
  10665         type == bcmCosqControlEgressPoolRedResumeLimitBytes) {
  10666         uint32 rval, max_val;
  10667         soc_reg_t reg;
  10668         soc_field_t fld_limit = INVALIDf;
  10669         int granularity = 1,pool;
  10670 
  10671         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
  10672             BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) {
  10673             pool = soc_mem_field32_get(unit, MMU_THDO_Q_TO_QGRP_MAPm, entry, Q_SPIDf);
  10674         } else {
  10675             pool = soc_reg_field_get(unit, OP_QUEUE_CONFIG1_CELLr, rval, Q_SPIDf);
  10676         }
  10677 
  10678         switch (type) {
  10679         case bcmCosqControlEgressPoolSharedLimitBytes:
  10680             reg = OP_BUFFER_SHARED_LIMIT_CELLr;
  10681             fld_limit = OP_BUFFER_SHARED_LIMIT_CELLf;
  10682             granularity = 1;
  10683             break;
  10684         case bcmCosqControlEgressPoolResumeLimitBytes:
  10685             reg = OP_BUFFER_SHARED_LIMIT_RESUME_CELLr;
  10686             fld_limit = OP_BUFFER_SHARED_LIMIT_RESUME_CELLf;
  10687             granularity = 1;
  10688             break;
  10689         case bcmCosqControlEgressPoolYellowSharedLimitBytes:
  10690             reg = OP_BUFFER_LIMIT_YELLOW_CELLr;
  10691             fld_limit = OP_BUFFER_LIMIT_YELLOW_CELLf;
  10692             granularity = 8;
  10693             break;
  10694         case bcmCosqControlEgressPoolYellowResumeLimitBytes:
  10695             reg = OP_BUFFER_LIMIT_RESUME_YELLOW_CELLr;
  10696             fld_limit = OP_BUFFER_LIMIT_RESUME_YELLOW_CELLf;
  10697             granularity = 8;
  10698             break;
  10699         case bcmCosqControlEgressPoolRedSharedLimitBytes:
  10700             reg = OP_BUFFER_LIMIT_RED_CELLr;
  10701             fld_limit = OP_BUFFER_LIMIT_RED_CELLf;
  10702             granularity = 8;
  10703             break;
  10704         case bcmCosqControlEgressPoolRedResumeLimitBytes:
  10705             reg = OP_BUFFER_LIMIT_RESUME_RED_CELLr;
  10706             fld_limit = OP_BUFFER_LIMIT_RESUME_RED_CELLf;
  10707             granularity = 8;
  10708             break;
  10709         /*
  10710          * COVERITY
  10711          *
  10712          * This default is unreachable but needed for some compiler.
  10713          */
  10714         /* coverity[dead_error_begin] */
  10715         default:
  10716             return BCM_E_UNAVAIL;
  10717         }
  10718 
  10719         num_cells = _BCM_TR3_BYTES_TO_CELLS(arg);
  10720         if (num_cells > _BCM_TR3_TOTAL_CELLS) {
  10721             return BCM_E_PARAM;
  10722         }
  10723 
  10724         BCM_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, pool, &rval));
  10725 
  10726         /* Check for min/max values */
  10727         max_val = (1 << soc_reg_field_length(unit, reg, fld_limit)) - 1;
  10728         if ((num_cells < 0) || ((num_cells/granularity) > max_val)) {
  10729             return BCM_E_PARAM;
  10730         } else {
  10731             soc_reg_field_set(unit, reg, &rval, fld_limit, (num_cells/granularity));
  10732         }
  10733 
  10734         BCM_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, pool, rval));
  10735 
  10736         return BCM_E_NONE;
  10737     }
  10738 
  10739     switch (type) {
  10740     case bcmCosqControlEgressPool:
  10741         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
  10742             BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) {
  10743             soc_mem_field32_set(unit, MMU_THDO_Q_TO_QGRP_MAPm, entry, Q_SPIDf, arg);
  10744             BCM_IF_ERROR_RETURN
  10745                 (soc_mem_write(unit, MMU_THDO_Q_TO_QGRP_MAPm, 
  10746                                         MEM_BLOCK_ALL, startq, entry));
  10747         } else {
  10748             soc_reg_field_set(unit, OP_QUEUE_CONFIG1_CELLr, &rval, Q_SPIDf, arg);
  10749             SOC_IF_ERROR_RETURN
  10750                 (WRITE_OP_QUEUE_CONFIG1_CELLr(unit, local_port, startq, rval));
  10751         }
  10752         break;
  10753 
  10754     case bcmCosqControlUCEgressPool:
  10755         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 
  10756             BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport) ||
  10757             BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  10758             return BCM_E_PARAM;
  10759         }
  10760         startq = SOC_INFO(unit).port_uc_cosq_base[local_port] + startq;
  10761         BCM_IF_ERROR_RETURN(
  10762                 soc_mem_read(unit, MMU_THDO_Q_TO_QGRP_MAPm, MEM_BLOCK_ALL,
  10763                              startq, entry));
  10764         soc_mem_field32_set(unit, MMU_THDO_Q_TO_QGRP_MAPm, entry, Q_SPIDf, arg);
  10765         BCM_IF_ERROR_RETURN
  10766             (soc_mem_write(unit, MMU_THDO_Q_TO_QGRP_MAPm,
  10767                                     MEM_BLOCK_ALL, startq, entry));
  10768         break; 
  10769 
  10770     case bcmCosqControlMCEgressPool:
  10771         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 
  10772             BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport) ||
  10773             BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  10774             return BCM_E_PARAM;
  10775         }
  10776         soc_reg_field_set(unit, OP_QUEUE_CONFIG1_CELLr, &rval, Q_SPIDf, arg);
  10777         SOC_IF_ERROR_RETURN
  10778             (WRITE_OP_QUEUE_CONFIG1_CELLr(unit, local_port, startq, rval));
  10779         break; 
  10780 
  10781     case bcmCosqControlEgressPoolLimitBytes:
  10782         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
  10783             BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) {
  10784             BCM_IF_ERROR_RETURN(
  10785                 soc_mem_read(unit, MMU_THDO_CONFIG_QUEUEm, MEM_BLOCK_ALL,
  10786                              startq, entry));
  10787             soc_mem_field32_set(unit, MMU_THDO_CONFIG_QUEUEm, entry,
  10788                                 Q_SHARED_LIMIT_CELLf, num_cells);
  10789             BCM_IF_ERROR_RETURN
  10790                 (soc_mem_write(unit, MMU_THDO_CONFIG_QUEUEm, 
  10791                                         MEM_BLOCK_ALL, startq, entry));
  10792         } else {
  10793             BCM_IF_ERROR_RETURN(
  10794              soc_reg32_get(unit, OP_QUEUE_CONFIG_CELLr, local_port, startq, &rval));
  10795             soc_reg_field_set(unit, OP_QUEUE_CONFIG_CELLr, &rval,
  10796                               Q_SHARED_LIMIT_CELLf, num_cells);
  10797             BCM_IF_ERROR_RETURN(soc_reg32_set(unit, OP_QUEUE_CONFIG_CELLr, 
  10798                                 local_port, startq, rval));
  10799         }
  10800 
  10801         break;
  10802     case bcmCosqControlEgressPoolYellowLimitBytes:
  10803         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
  10804             BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) {
  10805             BCM_IF_ERROR_RETURN(
  10806                 soc_mem_read(unit, MMU_THDO_CONFIG_QUEUEm, MEM_BLOCK_ALL,
  10807                              startq, entry));
  10808             soc_mem_field32_set(unit, MMU_THDO_CONFIG_QUEUEm, 
  10809                             entry, LIMIT_YELLOW_CELLf, num_cells / 8);
  10810             BCM_IF_ERROR_RETURN
  10811                 (soc_mem_write(unit, MMU_THDO_CONFIG_QUEUEm, 
  10812                                         MEM_BLOCK_ALL, startq, entry));
  10813         } else {
  10814             return BCM_E_UNAVAIL;
  10815         }
  10816         break;
  10817     case bcmCosqControlEgressPoolRedLimitBytes:
  10818         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
  10819             BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) {
  10820             BCM_IF_ERROR_RETURN(
  10821                 soc_mem_read(unit, MMU_THDO_CONFIG_QUEUEm, MEM_BLOCK_ALL,
  10822                              startq, entry));
  10823             soc_mem_field32_set(unit, MMU_THDO_CONFIG_QUEUEm, 
  10824                             entry, LIMIT_RED_CELLf, num_cells / 8);
  10825             BCM_IF_ERROR_RETURN
  10826                 (soc_mem_write(unit, MMU_THDO_CONFIG_QUEUEm, 
  10827                                         MEM_BLOCK_ALL, startq, entry));
  10828         } else {
  10829             BCM_IF_ERROR_RETURN(
  10830              soc_reg32_get(unit, OP_QUEUE_LIMIT_COLOR_CELLr, 
  10831                             local_port, startq, &rval));
  10832             soc_reg_field_set(unit, OP_QUEUE_LIMIT_COLOR_CELLr, &rval, REDf, num_cells/8);
  10833             BCM_IF_ERROR_RETURN(soc_reg32_set(unit, OP_QUEUE_LIMIT_COLOR_CELLr, 
  10834                                 local_port, startq, rval));
  10835         }
  10836         break;
  10837     default:
  10838         return BCM_E_UNAVAIL;
  10839     }
  10840     return BCM_E_NONE;
  10841 }
  10842 
  10843 STATIC int
  10844 _bcm_tr3_cosq_alpha_set(int unit, bcm_gport_t gport,
  10845                         bcm_cos_queue_t cosq, bcm_cosq_control_t type,
  10846                         bcm_cosq_control_drop_limit_alpha_value_t arg)
  10847 {
  10848     bcm_port_t local_port;
  10849     int startq;
  10850     int midx; 
  10851     uint32 rval;     
  10852     uint32 entry[SOC_MAX_MEM_WORDS];
  10853     soc_mem_t mem = INVALIDm;
  10854     int alpha;
  10855     int dynamic_thresh_mode;    
  10856     soc_reg_t reg = INVALIDr;
  10857     int phy_port, mmu_port, idx;
  10858     thdi_port_pg_config_entry_t pg_config_mem;
  10859     soc_info_t *si;
  10860     int type_uc = 0, type_mc = 0;
  10861 
  10862     if (type == bcmCosqControlDropLimitAlpha) {
  10863         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
  10864             BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) {
  10865             type_uc = 1;
  10866         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  10867             type_mc = 1;
  10868         }
  10869     } else if (type == bcmCosqControlUCDropLimitAlpha) {
  10870         if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  10871             return BCM_E_PARAM;
  10872         }
  10873         type_uc = 1;
  10874     } else if (type == bcmCosqControlMCDropLimitAlpha) {
  10875         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
  10876             BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) {
  10877             return BCM_E_PARAM;
  10878         }
  10879         type_mc = 1;
  10880     }
  10881 
  10882     si = &SOC_INFO(unit);
  10883     switch(arg) {
  10884     case bcmCosqControlDropLimitAlpha_1_64:
  10885         alpha = SOC_TR3_COSQ_DROP_LIMIT_ALPHA_1_64;
  10886         break;
  10887     case bcmCosqControlDropLimitAlpha_1_32:
  10888         alpha = SOC_TR3_COSQ_DROP_LIMIT_ALPHA_1_32;
  10889         break;
  10890     case bcmCosqControlDropLimitAlpha_1_16:
  10891         alpha = SOC_TR3_COSQ_DROP_LIMIT_ALPHA_1_16;
  10892         break;
  10893     case bcmCosqControlDropLimitAlpha_1_8:
  10894         alpha = SOC_TR3_COSQ_DROP_LIMIT_ALPHA_1_8;
  10895         break;
  10896     case bcmCosqControlDropLimitAlpha_1_4:
  10897         alpha = SOC_TR3_COSQ_DROP_LIMIT_ALPHA_1_4;
  10898         break;
  10899     case bcmCosqControlDropLimitAlpha_1_2:
  10900         alpha = SOC_TR3_COSQ_DROP_LIMIT_ALPHA_1_2;
  10901         break;
  10902     case bcmCosqControlDropLimitAlpha_1:
  10903         alpha = SOC_TR3_COSQ_DROP_LIMIT_ALPHA_1;
  10904         break;   
  10905     case bcmCosqControlDropLimitAlpha_2:
  10906         alpha = SOC_TR3_COSQ_DROP_LIMIT_ALPHA_2;
  10907         break;
  10908     case bcmCosqControlDropLimitAlpha_4:
  10909         alpha = SOC_TR3_COSQ_DROP_LIMIT_ALPHA_4;
  10910         break;
  10911     case bcmCosqControlDropLimitAlpha_8:
  10912         alpha = SOC_TR3_COSQ_DROP_LIMIT_ALPHA_8;
  10913         break;         
  10914     default:
  10915         return BCM_E_PARAM;          
  10916     }
  10917 
  10918     if (type_uc == 1) {
  10919         BCM_IF_ERROR_RETURN
  10920                 (_bcm_tr3_cosq_dynamic_thresh_enable_get(unit, gport, cosq, 
  10921                                    bcmCosqControlEgressUCSharedDynamicEnable, 
  10922                                    &dynamic_thresh_mode));
  10923         if (!dynamic_thresh_mode){
  10924             return BCM_E_CONFIG;
  10925         } 
  10926         
  10927         BCM_IF_ERROR_RETURN
  10928             (_bcm_tr3_cosq_index_resolve(unit, gport, cosq,
  10929                                      _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE,
  10930                                      &local_port, &startq, NULL));
  10931         
  10932         mem = MMU_THDO_CONFIG_QUEUEm;
  10933         BCM_IF_ERROR_RETURN
  10934             (soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  10935         soc_mem_field32_set(unit, mem, entry, 
  10936                             Q_SHARED_ALPHA_CELLf, alpha);
  10937         SOC_IF_ERROR_RETURN
  10938             (soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry));                 
  10939     } else if (type_mc == 1) {
  10940         BCM_IF_ERROR_RETURN
  10941                 (_bcm_tr3_cosq_dynamic_thresh_enable_get(unit, gport, cosq, 
  10942                                    bcmCosqControlEgressMCSharedDynamicEnable, 
  10943                                    &dynamic_thresh_mode));
  10944         if (!dynamic_thresh_mode){
  10945             return BCM_E_CONFIG;
  10946         }
  10947         if (cosq < 0) {
  10948             return BCM_E_PARAM;
  10949         }
  10950         
  10951         BCM_IF_ERROR_RETURN
  10952             (_bcm_tr3_cosq_index_resolve(unit, gport, cosq,
  10953                                      _BCM_TR3_COSQ_INDEX_STYLE_MCAST_QUEUE,
  10954                                      &local_port, &startq, NULL));
  10955         reg = OP_QUEUE_CONFIG_CELLr;
  10956         if (startq >= _BCM_TR3_NUM_L2_UC_LEAVES) {
  10957             startq -= (_BCM_TR3_NUM_L2_UC_LEAVES + si->port_cosq_base[local_port]);
  10958         }
  10959 
  10960         BCM_IF_ERROR_RETURN
  10961             (soc_reg32_get(unit, reg, local_port,
  10962                         startq, &rval));
  10963         soc_reg_field_set(unit, reg, &rval, Q_SHARED_ALPHA_CELLf, alpha);
  10964         BCM_IF_ERROR_RETURN
  10965             (soc_reg32_set(unit, reg, local_port,
  10966                         startq, rval));
  10967     } else {
  10968         BCM_IF_ERROR_RETURN
  10969             (_bcm_tr3_cosq_localport_resolve(unit, gport, &local_port));
  10970         if (local_port < 0) {
  10971             return BCM_E_PORT;
  10972         }
  10973         phy_port = si->port_l2p_mapping[local_port];
  10974         mmu_port = si->port_p2m_mapping[phy_port];
  10975 
  10976         /* Input port per port per priority group settings */
  10977         for (idx = 0; idx < _BCM_TR3_MMU_NUM_PG; idx++) {
  10978             midx = (mmu_port * 8) + idx;
  10979             mem = THDI_PORT_PG_CONFIGm;
  10980             sal_memset(&pg_config_mem, 0, sizeof(pg_config_mem));
  10981             BCM_IF_ERROR_RETURN
  10982                 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, &pg_config_mem));
  10983             soc_mem_field32_set(unit, mem, &pg_config_mem, 
  10984                                 PG_SHARED_LIMITf, alpha);
  10985             soc_mem_field32_set(unit, mem, &pg_config_mem, 
  10986                                 PG_SHARED_DYNAMICf, 1);
  10987             SOC_IF_ERROR_RETURN
  10988                 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, midx, &pg_config_mem));
  10989         }
  10990     } 
  10991     
  10992     return BCM_E_NONE;
  10993 }
  10994 
  10995 STATIC int
  10996 _bcm_tr3_cosq_alpha_get(int unit, bcm_gport_t gport, 
  10997                         bcm_cos_queue_t cosq, bcm_cosq_control_t type,
  10998                         bcm_cosq_control_drop_limit_alpha_value_t *arg)
  10999 {
  11000     bcm_port_t local_port;
  11001     int startq;
  11002     int midx; 
  11003     uint32 rval;     
  11004     uint32 entry[SOC_MAX_MEM_WORDS];
  11005     soc_mem_t mem = INVALIDm;
  11006     int dynamic_thresh_mode;    
  11007     soc_reg_t reg = INVALIDr;
  11008     int phy_port, mmu_port, idx;
  11009     thdi_port_pg_config_entry_t pg_config_mem;
  11010     soc_info_t *si;
  11011     int alpha = -1;
  11012     int type_uc = 0, type_mc = 0;
  11013 
  11014     if (!arg) {
  11015         return BCM_E_PARAM;
  11016     }
  11017 
  11018     if (type == bcmCosqControlDropLimitAlpha) {
  11019         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
  11020             BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) {
  11021             type_uc = 1;
  11022         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  11023             type_mc = 1;
  11024         }
  11025     } else if (type == bcmCosqControlUCDropLimitAlpha) {
  11026         if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  11027             return BCM_E_PARAM;
  11028         }
  11029         type_uc = 1;
  11030     } else if (type == bcmCosqControlMCDropLimitAlpha) {
  11031         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
  11032             BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) {
  11033             return BCM_E_PARAM;
  11034         }
  11035         type_mc = 1;
  11036     }
  11037 
  11038     si = &SOC_INFO(unit);
  11039 
  11040     if (type_uc == 1) {
  11041         BCM_IF_ERROR_RETURN
  11042                 (_bcm_tr3_cosq_dynamic_thresh_enable_get(unit, gport, cosq, 
  11043                                    bcmCosqControlEgressUCSharedDynamicEnable, 
  11044                                    &dynamic_thresh_mode));
  11045         if (!dynamic_thresh_mode){
  11046             return BCM_E_CONFIG;
  11047         } 
  11048         
  11049         BCM_IF_ERROR_RETURN
  11050             (_bcm_tr3_cosq_index_resolve(unit, gport, cosq,
  11051                                      _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE,
  11052                                      &local_port, &startq, NULL));
  11053         
  11054         mem = MMU_THDO_CONFIG_QUEUEm;
  11055         BCM_IF_ERROR_RETURN
  11056             (soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  11057         alpha = soc_mem_field32_get(unit, mem, entry, 
  11058                             Q_SHARED_ALPHA_CELLf);
  11059     } else if (type_mc == 1) {
  11060         BCM_IF_ERROR_RETURN
  11061                 (_bcm_tr3_cosq_dynamic_thresh_enable_get(unit, gport, cosq, 
  11062                                    bcmCosqControlEgressMCSharedDynamicEnable, 
  11063                                    &dynamic_thresh_mode));
  11064         if (!dynamic_thresh_mode){
  11065             return BCM_E_CONFIG;
  11066         }
  11067         if (cosq < 0) {
  11068             return BCM_E_PARAM;
  11069         }
  11070         
  11071         BCM_IF_ERROR_RETURN
  11072             (_bcm_tr3_cosq_index_resolve(unit, gport, cosq,
  11073                                      _BCM_TR3_COSQ_INDEX_STYLE_MCAST_QUEUE,
  11074                                      &local_port, &startq, NULL));
  11075         reg = OP_QUEUE_CONFIG_CELLr;
  11076         if (startq >= _BCM_TR3_NUM_L2_UC_LEAVES) {
  11077             startq -= (_BCM_TR3_NUM_L2_UC_LEAVES + si->port_cosq_base[local_port]);
  11078         }
  11079 
  11080         BCM_IF_ERROR_RETURN
  11081             (soc_reg32_get(unit, reg, local_port,
  11082                                     startq, &rval));
  11083         alpha = soc_reg_field_get(unit, reg, rval, Q_SHARED_ALPHA_CELLf);
  11084     } else {
  11085         BCM_IF_ERROR_RETURN
  11086             (_bcm_tr3_cosq_localport_resolve(unit, gport, &local_port));
  11087         if (local_port < 0) {
  11088             return BCM_E_PORT;
  11089         }
  11090         phy_port = si->port_l2p_mapping[local_port];
  11091         mmu_port = si->port_p2m_mapping[phy_port];
  11092 
  11093         /* Input port per port per priority group settings */
  11094         for (idx = 0; idx < _BCM_TR3_MMU_NUM_PG; idx++) {
  11095             midx = (mmu_port * 8) + idx;
  11096             mem = THDI_PORT_PG_CONFIGm;
  11097             sal_memset(&pg_config_mem, 0, sizeof(pg_config_mem));
  11098             BCM_IF_ERROR_RETURN
  11099                 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, &pg_config_mem));
  11100             if (soc_mem_field32_get(unit, mem, &pg_config_mem, PG_SHARED_DYNAMICf)) {
  11101                 alpha = soc_mem_field32_get(unit, mem, &pg_config_mem, 
  11102                                 PG_SHARED_LIMITf);
  11103                 break;
  11104             }
  11105         }
  11106     }
  11107 
  11108     switch(alpha) {
  11109     case SOC_TR3_COSQ_DROP_LIMIT_ALPHA_1_64:
  11110         *arg = bcmCosqControlDropLimitAlpha_1_64;
  11111         break;
  11112     case SOC_TR3_COSQ_DROP_LIMIT_ALPHA_1_32:
  11113         *arg = bcmCosqControlDropLimitAlpha_1_32;
  11114         break;
  11115     case SOC_TR3_COSQ_DROP_LIMIT_ALPHA_1_16:
  11116         *arg = bcmCosqControlDropLimitAlpha_1_16;
  11117         break;
  11118     case SOC_TR3_COSQ_DROP_LIMIT_ALPHA_1_8:
  11119         *arg = bcmCosqControlDropLimitAlpha_1_8;
  11120         break;
  11121     case SOC_TR3_COSQ_DROP_LIMIT_ALPHA_1_4:
  11122         *arg = bcmCosqControlDropLimitAlpha_1_4;
  11123         break;
  11124     case SOC_TR3_COSQ_DROP_LIMIT_ALPHA_1_2:
  11125         *arg = bcmCosqControlDropLimitAlpha_1_2;
  11126         break;
  11127     case SOC_TR3_COSQ_DROP_LIMIT_ALPHA_1:
  11128         *arg = bcmCosqControlDropLimitAlpha_1;
  11129         break;
  11130     case SOC_TR3_COSQ_DROP_LIMIT_ALPHA_2:
  11131         *arg = bcmCosqControlDropLimitAlpha_2;
  11132         break;
  11133     case SOC_TR3_COSQ_DROP_LIMIT_ALPHA_4:
  11134         *arg = bcmCosqControlDropLimitAlpha_4;
  11135         break;
  11136     case SOC_TR3_COSQ_DROP_LIMIT_ALPHA_8:
  11137         *arg = bcmCosqControlDropLimitAlpha_8;
  11138         break;
  11139     default:
  11140         return BCM_E_NONE;          
  11141     }
  11142     
  11143     return BCM_E_NONE;
  11144 }
  11145 
  11146 STATIC int
  11147 _bcm_tr3_cosq_egr_queue_set(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
  11148                             bcm_cosq_control_t type, int arg)
  11149 {
  11150     bcm_port_t local_port;
  11151     int startq;
  11152     uint32 max_val = 0;
  11153     uint32 entry[SOC_MAX_MEM_WORDS];
  11154     uint32 entry2[SOC_MAX_MEM_WORDS];
  11155     uint32 rval, rval2;
  11156     soc_mem_t mem = INVALIDm;
  11157     soc_mem_t mem2 = INVALIDm;
  11158     soc_reg_t reg = INVALIDr;
  11159     soc_reg_t reg2 = INVALIDr;
  11160     soc_field_t fld_limit = INVALIDf;
  11161     soc_field_t fld_limit2 = INVALIDf;
  11162     int granularity = 1;
  11163     int from_cos, to_cos, ci;
  11164     int shared_size, cur_val = 0, rv, post_update;
  11165     _bcm_tr3_mmu_info_t *mmu_info = _bcm_tr3_mmu_info[unit];
  11166     int delta = 0; /* In Cells */
  11167     int limit;
  11168     int spid = 0;
  11169 
  11170     if (arg < 0) {
  11171         return BCM_E_PARAM;
  11172     }
  11173 
  11174    arg = _BCM_TR3_BYTES_TO_CELLS(arg);
  11175 
  11176     if ((type == bcmCosqControlEgressUCQueueMinLimitBytes) ||
  11177         (type == bcmCosqControlEgressUCQueueSharedLimitBytes)) {
  11178         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
  11179             BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) {
  11180             BCM_IF_ERROR_RETURN
  11181                 (_bcm_tr3_cosq_index_resolve(unit, gport, cosq,
  11182                                              _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE,
  11183                                              &local_port, &startq, NULL));
  11184         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  11185             return BCM_E_PARAM;
  11186         }
  11187         else {
  11188             if (cosq == BCM_COS_INVALID) {
  11189                 from_cos = to_cos = 0;
  11190             } else {
  11191                 from_cos = to_cos = cosq;
  11192             }
  11193 
  11194             BCM_IF_ERROR_RETURN
  11195                 (_bcm_tr3_cosq_localport_resolve(unit, gport, &local_port));
  11196             if (local_port < 0) {
  11197                 return BCM_E_PORT;
  11198             }
  11199             for (ci = from_cos; ci <= to_cos; ci++) {
  11200                 BCM_IF_ERROR_RETURN
  11201                     (_bcm_tr3_cosq_index_resolve
  11202                      (unit, local_port, ci, _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE,
  11203                       NULL, &startq, NULL));
  11204             }
  11205         }
  11206         mem = MMU_THDO_CONFIG_QUEUEm;
  11207         mem2 = MMU_THDO_Q_TO_QGRP_MAPm;
  11208     } else if ((type == bcmCosqControlEgressMCQueueMinLimitBytes) ||
  11209                (type == bcmCosqControlEgressMCQueueSharedLimitBytes)) {
  11210         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
  11211             BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) {
  11212             return BCM_E_PARAM;
  11213         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  11214             BCM_IF_ERROR_RETURN
  11215                 (_bcm_tr3_cosq_index_resolve(unit, gport, cosq,
  11216                                              _BCM_TR3_COSQ_INDEX_STYLE_EGR_POOL,
  11217                                              &local_port, &startq, NULL));
  11218         }
  11219         else {
  11220             if (cosq == BCM_COS_INVALID) {
  11221                 from_cos = to_cos = 0;
  11222             } else {
  11223                 from_cos = to_cos = cosq;
  11224             }
  11225 
  11226             BCM_IF_ERROR_RETURN
  11227                 (_bcm_tr3_cosq_localport_resolve(unit, gport, &local_port));
  11228             if (local_port < 0) {
  11229                 return BCM_E_PORT;
  11230             }
  11231             for (ci = from_cos; ci <= to_cos; ci++) {
  11232                 BCM_IF_ERROR_RETURN
  11233                     (_bcm_tr3_cosq_index_resolve
  11234                      (unit, local_port, ci, _BCM_TR3_COSQ_INDEX_STYLE_EGR_POOL,
  11235                       NULL, &startq, NULL));
  11236             }
  11237             /* Here is just crash issue, there are some logical issue need to be fixed later */
  11238             if (cosq == BCM_COS_INVALID) {
  11239                 startq = 0;
  11240             }
  11241             else {
  11242                 startq = cosq;
  11243             }
  11244         }
  11245         reg = OP_QUEUE_CONFIG_CELLr;
  11246         reg2 = OP_QUEUE_CONFIG1_CELLr;
  11247     } else {
  11248         return BCM_E_PARAM;
  11249     }
  11250 
  11251     if (mem != INVALIDm) {
  11252         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  11253         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem2, MEM_BLOCK_ALL, startq, entry2));
  11254         spid = soc_mem_field32_get(unit, mem2, entry2, Q_SPIDf);
  11255     } else if (reg != INVALIDr) {
  11256         BCM_IF_ERROR_RETURN(soc_reg32_get(unit, reg,
  11257                         local_port, startq, &rval));
  11258         BCM_IF_ERROR_RETURN(soc_reg32_get(unit, reg2,
  11259                         local_port, startq, &rval2));
  11260         spid = soc_reg_field_get(unit, reg2, rval2, Q_SPIDf);
  11261     }
  11262 
  11263     switch (type) {
  11264     case bcmCosqControlEgressUCQueueSharedLimitBytes:
  11265         fld_limit = Q_SHARED_LIMIT_CELLf;
  11266         fld_limit2 = Q_LIMIT_ENABLE_CELLf;
  11267         break;
  11268     case bcmCosqControlEgressMCQueueSharedLimitBytes:
  11269         fld_limit = Q_SHARED_LIMIT_CELLf;
  11270         break;
  11271     case bcmCosqControlEgressUCQueueMinLimitBytes:
  11272         fld_limit = Q_MIN_LIMIT_CELLf;
  11273         break;
  11274     case bcmCosqControlEgressMCQueueMinLimitBytes:
  11275         fld_limit = Q_MIN_CELLf;
  11276         break;
  11277     default:
  11278         return BCM_E_UNAVAIL;
  11279     }
  11280 
  11281     /* Check for min/max values */
  11282     if (mem != INVALIDm) {
  11283         max_val = (1 << soc_mem_field_length(unit, mem, fld_limit)) - 1;
  11284     } else if (reg != INVALIDr) {
  11285         max_val = (1 << soc_reg_field_length(unit, reg, fld_limit)) - 1;
  11286     }
  11287     if ((arg < 0) || ((arg/granularity) > max_val)) {
  11288         return BCM_E_PARAM;
  11289     }
  11290 
  11291     /* Recalculate Shared Values if Min Changed */
  11292     shared_size = mmu_info->curr_shared_limit;
  11293     if (mem != INVALIDm) {
  11294         cur_val = soc_mem_field32_get(unit, mem, entry, fld_limit);
  11295     } else if (reg != INVALIDr) {
  11296         cur_val = soc_reg_field_get(unit, reg, rval, fld_limit);
  11297     }
  11298 
  11299     if ((arg / granularity) > cur_val) {
  11300         /* New Min Val > Cur Min Val
  11301          * So reduce the Shared values first and then 
  11302          * Increase the Min Value for given resource
  11303          */
  11304         post_update = 0;
  11305     } else if ((arg / granularity) < cur_val) {
  11306         /* New Min Val < Cur Min Val
  11307          * So reduce the Min values first and then 
  11308          * Increase Shared values everywhere
  11309          */
  11310         post_update = 1;
  11311     } else {
  11312         return BCM_E_NONE;
  11313     }
  11314  
  11315     if (!post_update &&
  11316         ((type == bcmCosqControlEgressUCQueueMinLimitBytes) ||
  11317          (type == bcmCosqControlEgressMCQueueMinLimitBytes))) {
  11318         delta = ((arg / granularity) - cur_val) * granularity;
  11319         if (delta > shared_size) {
  11320             return BCM_E_PARAM;
  11321         }
  11322         rv = soc_tr3_mmu_config_shared_buf_recalc(unit, spid,
  11323                                                   delta, 1);
  11324         if (rv < 0) { 
  11325             return rv;
  11326         }
  11327 
  11328         mmu_info->curr_shared_limit = shared_size - delta;
  11329 
  11330         /* Reading mem again as recalc would have updated the mem/reg. */
  11331         if (mem != INVALIDm) {
  11332             BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  11333             BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem2, MEM_BLOCK_ALL, startq, entry2));
  11334         } else if (reg != INVALIDr) {
  11335             BCM_IF_ERROR_RETURN(soc_reg32_get(unit, reg,
  11336                             local_port, startq, &rval));
  11337             BCM_IF_ERROR_RETURN(soc_reg32_get(unit, reg2,
  11338                             local_port, startq, &rval2));
  11339         }
  11340     }
  11341 
  11342         
  11343     switch (type) {
  11344     case bcmCosqControlEgressUCQueueSharedLimitBytes:
  11345 
  11346         soc_mem_field32_set(unit, mem, entry, fld_limit, (arg/granularity));
  11347         soc_mem_field32_set(unit, mem, entry, fld_limit2, 1);
  11348 
  11349         /* Set MMU_THDO_Q_TO_QGRP_MAP.DISABLE_QUEUING to 1 when both MIN
  11350          * and SHARED LIMIT are 0. Set it to 0 when either MIN or SHARED LIMIT
  11351          * is non-zero.
  11352          */
  11353         limit = soc_mem_field32_get(unit, mem, entry, Q_MIN_LIMIT_CELLf);
  11354         if ((arg == 0) && (limit == 0)) {
  11355             soc_mem_field32_set(unit, mem2, entry2, DISABLE_QUEUINGf, 1);
  11356         } else if ((arg != 0) || (limit != 0)) {
  11357             soc_mem_field32_set(unit, mem2, entry2, DISABLE_QUEUINGf, 0);
  11358         }
  11359         break;
  11360     case bcmCosqControlEgressMCQueueSharedLimitBytes:
  11361 
  11362         soc_reg_field_set(unit, reg, &rval, fld_limit, (arg/granularity));
  11363         soc_reg_field_set(unit, reg2, &rval2, Q_LIMIT_ENABLE_CELLf, 1);
  11364 
  11365         break;
  11366     case bcmCosqControlEgressUCQueueMinLimitBytes:
  11367 
  11368         soc_mem_field32_set(unit, mem, entry, fld_limit, (arg/granularity));
  11369         /* Set MMU_THDO_Q_TO_QGRP_MAP.DISABLE_QUEUING to 1 when both MIN
  11370          * and SHARED LIMIT are 0. Set it to 0 when either MIN or SHARED LIMIT is non-zero
  11371          */
  11372         limit = soc_mem_field32_get(unit, mem, entry, Q_SHARED_LIMIT_CELLf);
  11373         if ((arg == 0) && (limit == 0)) {
  11374             soc_mem_field32_set(unit, mem2, entry2, DISABLE_QUEUINGf, 1);
  11375         } else if ((arg != 0) || (limit != 0)) {
  11376             soc_mem_field32_set(unit, mem2, entry2, DISABLE_QUEUINGf, 0);
  11377         }
  11378         break;
  11379     case bcmCosqControlEgressMCQueueMinLimitBytes:
  11380 
  11381         soc_reg_field_set(unit, reg, &rval, fld_limit, (arg/granularity));
  11382         break;
  11383     /*
  11384      * COVERITY
  11385      *
  11386      * This default is unreachable but needed for some compiler. 
  11387      */ 
  11388     /* coverity[dead_error_begin] */
  11389     default:
  11390         return BCM_E_UNAVAIL;
  11391     }
  11392 
  11393 
  11394     if (mem != INVALIDm) {
  11395         BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry));
  11396         BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem2, MEM_BLOCK_ALL, startq, entry2));
  11397     } else if (reg != INVALIDr) {
  11398         BCM_IF_ERROR_RETURN(soc_reg32_set(unit, reg,
  11399                         local_port, startq, rval));
  11400         BCM_IF_ERROR_RETURN(soc_reg32_set(unit, reg2,
  11401                         local_port, startq, rval2));
  11402     }
  11403 
  11404     if (post_update && 
  11405         ((type == bcmCosqControlEgressUCQueueMinLimitBytes) ||
  11406          (type == bcmCosqControlEgressMCQueueMinLimitBytes))) {
  11407         int delta = 0;
  11408         delta = (cur_val - (arg / granularity)) * granularity;
  11409         if (delta > shared_size) {
  11410             return BCM_E_PARAM;
  11411         }
  11412         rv = soc_tr3_mmu_config_shared_buf_recalc(unit, spid,
  11413                                                   delta, 0);
  11414         if (rv < 0) { 
  11415             return rv;
  11416         }
  11417         mmu_info->curr_shared_limit = shared_size + delta;
  11418     }
  11419 
  11420     return BCM_E_NONE;
  11421 }
  11422 
  11423 STATIC int
  11424 _bcm_tr3_cosq_dynamic_thresh_enable_set(int unit, 
  11425                         bcm_gport_t gport, bcm_cos_queue_t cosq,
  11426                         bcm_cosq_control_t type, int arg)
  11427 {
  11428     bcm_port_t local_port;
  11429     int startq;
  11430     int from_cos, to_cos, ci;
  11431     uint32 entry[SOC_MAX_MEM_WORDS];
  11432     uint32 rval;
  11433     soc_mem_t mem = INVALIDm;
  11434     soc_reg_t reg = INVALIDr;
  11435     int port_pg;
  11436     int phy_port, mmu_port, midx;
  11437     static const soc_reg_t prigroup_reg[] = {
  11438         PORT_PRI_GRP0r, PORT_PRI_GRP1r
  11439     };
  11440     static const soc_field_t prigroup_field[] = {
  11441         PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf,
  11442         PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf,
  11443         PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf,
  11444         PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf
  11445     };
  11446     soc_info_t *si;
  11447 
  11448     if (type == bcmCosqControlIngressPortPGSharedDynamicEnable) {
  11449         BCM_IF_ERROR_RETURN
  11450             (_bcm_tr3_cosq_localport_resolve(unit, gport, &local_port));
  11451         if (local_port < 0) {
  11452             return BCM_E_PORT;
  11453         }
  11454         si = &SOC_INFO(unit);
  11455         phy_port = si->port_l2p_mapping[local_port];
  11456         mmu_port = si->port_p2m_mapping[phy_port];
  11457         /* get PG for port using Port+Cos */
  11458         if (cosq < 8) {
  11459             reg = prigroup_reg[0];
  11460         } else {
  11461             reg = prigroup_reg[1];
  11462         }
  11463 
  11464         SOC_IF_ERROR_RETURN
  11465             (soc_reg32_get(unit, reg, local_port, 0, &rval));
  11466         port_pg = soc_reg_field_get(unit, reg, rval, prigroup_field[cosq]);
  11467 
  11468         mem = THDI_PORT_PG_CONFIGm;
  11469         /* get index for Port-PG */
  11470         midx = (mmu_port * 8) + port_pg;
  11471         BCM_IF_ERROR_RETURN
  11472             (soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, entry));
  11473         soc_mem_field32_set(unit, mem, entry,
  11474                             PG_SHARED_DYNAMICf, arg ? 1 : 0);
  11475         SOC_IF_ERROR_RETURN
  11476             (soc_mem_write(unit, mem, MEM_BLOCK_ALL, midx, entry));
  11477 
  11478         if (arg) {
  11479             BCM_IF_ERROR_RETURN
  11480                 (_bcm_tr3_cosq_alpha_set(unit, gport, cosq, bcmCosqControlDropLimitAlpha,
  11481                                                       bcmCosqControlDropLimitAlpha_1_64));
  11482         }
  11483     } else if (type == bcmCosqControlEgressUCSharedDynamicEnable) {
  11484         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
  11485             BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) {
  11486             BCM_IF_ERROR_RETURN
  11487                 (_bcm_tr3_cosq_index_resolve(unit, gport, cosq,
  11488                                          _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE,
  11489                                          &local_port, &startq, NULL));
  11490         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  11491             return BCM_E_PARAM;
  11492         } else {
  11493             if (cosq == BCM_COS_INVALID) {
  11494                 from_cos = to_cos = 0;
  11495             } else {
  11496                 from_cos = to_cos = cosq;
  11497             }
  11498 
  11499             BCM_IF_ERROR_RETURN
  11500                 (_bcm_tr3_cosq_localport_resolve(unit, gport, &local_port));
  11501             if (local_port < 0) {
  11502                 return BCM_E_PORT;
  11503             }
  11504             for (ci = from_cos; ci <= to_cos; ci++) {
  11505                 BCM_IF_ERROR_RETURN
  11506                     (_bcm_tr3_cosq_index_resolve(unit, local_port, ci,
  11507                           _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE,
  11508                           NULL, &startq, NULL));
  11509                 
  11510             }
  11511         }
  11512         mem = MMU_THDO_CONFIG_QUEUEm;
  11513         
  11514         BCM_IF_ERROR_RETURN
  11515             (soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  11516         soc_mem_field32_set(unit, mem, entry, 
  11517                             Q_LIMIT_DYNAMIC_CELLf, arg ? 1 : 0);
  11518         SOC_IF_ERROR_RETURN
  11519             (soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry));
  11520 
  11521         if (arg) {
  11522             BCM_IF_ERROR_RETURN
  11523                 (_bcm_tr3_cosq_alpha_set(unit, gport, cosq, bcmCosqControlUCDropLimitAlpha,
  11524                                          bcmCosqControlDropLimitAlpha_1_64));
  11525         }
  11526     } else if (type == bcmCosqControlEgressMCSharedDynamicEnable) {
  11527         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
  11528             BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) {
  11529             return BCM_E_PARAM;
  11530         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  11531             BCM_IF_ERROR_RETURN
  11532                 (_bcm_tr3_cosq_index_resolve(unit, gport, cosq,
  11533                                          _BCM_TR3_COSQ_INDEX_STYLE_EGR_POOL,
  11534                                          &local_port, &startq, NULL));
  11535         }
  11536         else {
  11537             if (cosq == BCM_COS_INVALID) {
  11538                 from_cos = to_cos = 0;
  11539             } else {
  11540                 from_cos = to_cos = cosq;
  11541             }
  11542 
  11543             BCM_IF_ERROR_RETURN
  11544                 (_bcm_tr3_cosq_localport_resolve(unit, gport, &local_port));
  11545             if (local_port < 0) {
  11546                 return BCM_E_PORT;
  11547             }
  11548             for (ci = from_cos; ci <= to_cos; ci++) {
  11549                 BCM_IF_ERROR_RETURN
  11550                     (_bcm_tr3_cosq_index_resolve(unit, local_port, ci,
  11551                                          _BCM_TR3_COSQ_INDEX_STYLE_EGR_POOL,
  11552                                          NULL, &startq, NULL));
  11553               
  11554             }
  11555         }
  11556         if (cosq < 0) {
  11557             return BCM_E_PARAM;
  11558         }
  11559 
  11560         BCM_IF_ERROR_RETURN
  11561             (READ_OP_QUEUE_CONFIG1_CELLr(unit, local_port, startq, &rval));
  11562         soc_reg_field_set(unit, OP_QUEUE_CONFIG1_CELLr, &rval, Q_LIMIT_DYNAMIC_CELLf, arg);
  11563         WRITE_OP_QUEUE_CONFIG1_CELLr(unit, local_port, startq, rval);
  11564 
  11565         if (arg) {
  11566             BCM_IF_ERROR_RETURN
  11567                 (_bcm_tr3_cosq_alpha_set(unit, gport, cosq, bcmCosqControlMCDropLimitAlpha,
  11568                                                         bcmCosqControlDropLimitAlpha_1_64));
  11569         }
  11570     } else {
  11571         return BCM_E_PARAM;
  11572     }
  11573 
  11574     return BCM_E_NONE;
  11575 }
  11576 
  11577 STATIC int
  11578 _bcm_tr3_cosq_egr_queue_limit_enable_set(int unit, bcm_gport_t gport,
  11579                                                  bcm_cos_queue_t cosq,
  11580                                                  bcm_cosq_control_t type,
  11581                                                  int arg)
  11582 {
  11583     bcm_port_t local_port;
  11584     int startq;
  11585     uint32 entry[SOC_MAX_MEM_WORDS];
  11586     uint32 rval;
  11587     soc_mem_t mem = INVALIDm;
  11588     int enable;
  11589 
  11590     if (arg < 0) {
  11591         return BCM_E_PARAM;
  11592     }
  11593 
  11594     arg = arg ? 1 : 0;
  11595 
  11596     if (type == bcmCosqControlEgressUCQueueLimitEnable) {
  11597         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
  11598             BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) {
  11599             BCM_IF_ERROR_RETURN
  11600                 (_bcm_tr3_cosq_index_resolve(unit, gport, cosq,
  11601                                              _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE,
  11602                                              &local_port, &startq, NULL));
  11603         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  11604             return BCM_E_PARAM;
  11605         } else {
  11606             if (cosq < 0) {
  11607                 return BCM_E_PARAM;
  11608             }
  11609             BCM_IF_ERROR_RETURN
  11610                 (_bcm_tr3_cosq_localport_resolve(unit, gport, &local_port));
  11611             if (local_port < 0) {
  11612                 return BCM_E_PORT;
  11613             }
  11614             BCM_IF_ERROR_RETURN
  11615                 (_bcm_tr3_cosq_index_resolve
  11616                  (unit, local_port, cosq, _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE,
  11617                   NULL, &startq, NULL));
  11618         }
  11619 
  11620         mem = MMU_THDO_CONFIG_QUEUEm;
  11621         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  11622         enable = soc_mem_field32_get(unit, mem, entry, Q_LIMIT_ENABLE_CELLf);
  11623         if (enable != arg) {
  11624             soc_mem_field32_set(unit, mem, entry, Q_LIMIT_ENABLE_CELLf, arg);
  11625             BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry));
  11626         }
  11627     } else if (type == bcmCosqControlEgressMCQueueLimitEnable) {
  11628         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
  11629             BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) {
  11630             return BCM_E_PARAM;
  11631         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  11632             BCM_IF_ERROR_RETURN
  11633                 (_bcm_tr3_cosq_index_resolve(unit, gport, cosq,
  11634                                              _BCM_TR3_COSQ_INDEX_STYLE_MCAST_QUEUE,
  11635                                              &local_port, &startq, NULL));
  11636         } else {
  11637             if (cosq < 0) {
  11638                 return BCM_E_PARAM;
  11639             }
  11640             BCM_IF_ERROR_RETURN
  11641                 (_bcm_tr3_cosq_localport_resolve(unit, gport, &local_port));
  11642             if (local_port < 0) {
  11643                 return BCM_E_PORT;
  11644             }
  11645             BCM_IF_ERROR_RETURN
  11646                 (_bcm_tr3_cosq_index_resolve(unit, local_port, cosq,
  11647                                             _BCM_TR3_COSQ_INDEX_STYLE_MCAST_QUEUE,
  11648                                             NULL, &startq, NULL));
  11649         }
  11650         if (cosq < 0) {
  11651             return BCM_E_PARAM;
  11652         }
  11653 
  11654         BCM_IF_ERROR_RETURN
  11655             (READ_OP_QUEUE_CONFIG1_CELLr(unit, local_port, cosq, &rval));
  11656         enable = soc_reg_field_get(unit, OP_QUEUE_CONFIG1_CELLr, rval, Q_LIMIT_ENABLE_CELLf);
  11657         if (enable != arg) {
  11658             soc_reg_field_set(unit, OP_QUEUE_CONFIG1_CELLr, &rval, Q_LIMIT_ENABLE_CELLf, arg);
  11659             WRITE_OP_QUEUE_CONFIG1_CELLr(unit, local_port, cosq, rval);
  11660         }
  11661     } else {
  11662         return BCM_E_PARAM;
  11663     }
  11664 
  11665     return BCM_E_NONE;
  11666 }
  11667 
  11668 STATIC int
  11669 _bcm_tr3_cosq_egr_queue_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
  11670                             bcm_cosq_control_t type, int *arg)
  11671 {
  11672     bcm_port_t local_port;
  11673     int startq;
  11674     uint32 entry[SOC_MAX_MEM_WORDS];
  11675     uint32 rval;
  11676     soc_mem_t mem = INVALIDm;
  11677     soc_reg_t reg = INVALIDr;
  11678     soc_field_t fld_limit = INVALIDf;
  11679     int granularity = 1;
  11680     int from_cos, to_cos, ci;
  11681 
  11682     if (arg == NULL) {
  11683         return BCM_E_PARAM;
  11684     }
  11685 
  11686     if ((type == bcmCosqControlEgressUCQueueMinLimitBytes) ||
  11687         (type == bcmCosqControlEgressUCQueueSharedLimitBytes)) {
  11688         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
  11689             BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) {
  11690             BCM_IF_ERROR_RETURN
  11691                 (_bcm_tr3_cosq_index_resolve(unit, gport, cosq,
  11692                                              _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE,
  11693                                              &local_port, &startq, NULL));
  11694         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  11695             return BCM_E_PARAM;
  11696         }
  11697         else {
  11698             if (cosq == BCM_COS_INVALID) {
  11699                 from_cos = to_cos = 0;
  11700             } else {
  11701                 from_cos = to_cos = cosq;
  11702             }
  11703 
  11704             BCM_IF_ERROR_RETURN
  11705                 (_bcm_tr3_cosq_localport_resolve(unit, gport, &local_port));
  11706             if (local_port < 0) {
  11707                 return BCM_E_PORT;
  11708             }
  11709             for (ci = from_cos; ci <= to_cos; ci++) {
  11710                 BCM_IF_ERROR_RETURN
  11711                     (_bcm_tr3_cosq_index_resolve
  11712                      (unit, local_port, ci, _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE,
  11713                       NULL, &startq, NULL));
  11714             }
  11715         }
  11716         mem = MMU_THDO_CONFIG_QUEUEm;
  11717     } else if ((type == bcmCosqControlEgressMCQueueMinLimitBytes) ||
  11718                (type == bcmCosqControlEgressMCQueueSharedLimitBytes)) {
  11719         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
  11720             BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) {
  11721             return BCM_E_PARAM;
  11722         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  11723             BCM_IF_ERROR_RETURN
  11724                 (_bcm_tr3_cosq_index_resolve(unit, gport, cosq,
  11725                                              _BCM_TR3_COSQ_INDEX_STYLE_EGR_POOL,
  11726                                              &local_port, &startq, NULL));
  11727         }
  11728         else {
  11729             if (cosq == BCM_COS_INVALID) {
  11730                 from_cos = to_cos = 0;
  11731             } else {
  11732                 from_cos = to_cos = cosq;
  11733             }
  11734 
  11735             BCM_IF_ERROR_RETURN
  11736                 (_bcm_tr3_cosq_localport_resolve(unit, gport, &local_port));
  11737             if (local_port < 0) {
  11738                 return BCM_E_PORT;
  11739             }
  11740             for (ci = from_cos; ci <= to_cos; ci++) {
  11741                 BCM_IF_ERROR_RETURN
  11742                     (_bcm_tr3_cosq_index_resolve
  11743                      (unit, local_port, ci, _BCM_TR3_COSQ_INDEX_STYLE_EGR_POOL,
  11744                       NULL, &startq, NULL));
  11745             }
  11746         }
  11747         reg = OP_QUEUE_CONFIG_CELLr;
  11748     } else {
  11749         return BCM_E_PARAM;
  11750     }
  11751 
  11752     switch (type) {
  11753         case bcmCosqControlEgressUCQueueMinLimitBytes:
  11754             fld_limit = Q_MIN_LIMIT_CELLf;
  11755             break;
  11756         case bcmCosqControlEgressUCQueueSharedLimitBytes:
  11757             fld_limit = Q_SHARED_LIMIT_CELLf;
  11758             break;
  11759         case bcmCosqControlEgressMCQueueMinLimitBytes:
  11760             fld_limit = Q_MIN_CELLf;
  11761             break;
  11762         case bcmCosqControlEgressMCQueueSharedLimitBytes:
  11763             fld_limit = Q_SHARED_LIMIT_CELLf;
  11764             break;
  11765         default:
  11766             return BCM_E_PARAM;
  11767     }
  11768 
  11769     if (mem != INVALIDm) {
  11770         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  11771         *arg = soc_mem_field32_get(unit, mem, entry, fld_limit);
  11772     } else if (reg != INVALIDr) {
  11773         BCM_IF_ERROR_RETURN(soc_reg32_get(unit, reg,
  11774                         local_port, startq, &rval));
  11775         *arg = soc_reg_field_get(unit, reg, rval, fld_limit);
  11776     }
  11777     *arg = (*arg) * granularity * _BCM_TR3_BYTES_PER_CELL;
  11778     return BCM_E_NONE;
  11779 }
  11780 
  11781 STATIC int
  11782 _bcm_tr3_cosq_dynamic_thresh_enable_get(int unit, 
  11783                         bcm_gport_t gport, bcm_cos_queue_t cosq,
  11784                         bcm_cosq_control_t type, int *arg)
  11785 {
  11786     bcm_port_t local_port;
  11787     int startq;
  11788     int from_cos, to_cos, ci;
  11789     uint32 entry[SOC_MAX_MEM_WORDS];
  11790     uint32 rval;
  11791     soc_mem_t mem = INVALIDm;
  11792     soc_reg_t reg = INVALIDr;
  11793     int port_pg;
  11794     int phy_port, mmu_port, midx;
  11795     static const soc_reg_t prigroup_reg[] = {
  11796         PORT_PRI_GRP0r, PORT_PRI_GRP1r
  11797     };
  11798     static const soc_field_t prigroup_field[] = {
  11799         PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf,
  11800         PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf,
  11801         PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf,
  11802         PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf
  11803     };
  11804     soc_info_t *si;
  11805 
  11806     if (arg == NULL) {
  11807         return BCM_E_PARAM;
  11808     }
  11809 
  11810     if (type == bcmCosqControlIngressPortPGSharedDynamicEnable) {
  11811         BCM_IF_ERROR_RETURN
  11812             (_bcm_tr3_cosq_localport_resolve(unit, gport, &local_port));
  11813         if (local_port < 0) {
  11814             return BCM_E_PORT;
  11815         }
  11816         si = &SOC_INFO(unit);
  11817         phy_port = si->port_l2p_mapping[local_port];
  11818         mmu_port = si->port_p2m_mapping[phy_port];
  11819         /* get PG for port using Port+Cos */
  11820         if (cosq < 8) {
  11821             reg = prigroup_reg[0];
  11822         } else {
  11823             reg = prigroup_reg[1];
  11824         }
  11825 
  11826         SOC_IF_ERROR_RETURN
  11827             (soc_reg32_get(unit, reg, local_port, 0, &rval));
  11828         port_pg = soc_reg_field_get(unit, reg, rval, prigroup_field[cosq]);
  11829 
  11830         mem = THDI_PORT_PG_CONFIGm;
  11831         /* get index for Port-PG */
  11832         midx = (mmu_port * 8) + port_pg;
  11833         BCM_IF_ERROR_RETURN
  11834             (soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, entry));
  11835         *arg = soc_mem_field32_get(unit, mem, entry, PG_SHARED_DYNAMICf);
  11836 
  11837     } else if (type == bcmCosqControlEgressUCSharedDynamicEnable) {
  11838         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
  11839             BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) {
  11840             BCM_IF_ERROR_RETURN
  11841                 (_bcm_tr3_cosq_index_resolve(unit, gport, cosq,
  11842                                          _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE,
  11843                                          &local_port, &startq, NULL));
  11844         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  11845             return BCM_E_PARAM;
  11846         } else {
  11847             if (cosq == BCM_COS_INVALID) {
  11848                 from_cos = to_cos = 0;
  11849             } else {
  11850                 from_cos = to_cos = cosq;
  11851             }
  11852 
  11853             BCM_IF_ERROR_RETURN
  11854                 (_bcm_tr3_cosq_localport_resolve(unit, gport, &local_port));
  11855             if (local_port < 0) {
  11856                 return BCM_E_PORT;
  11857             }
  11858             for (ci = from_cos; ci <= to_cos; ci++) {
  11859                 BCM_IF_ERROR_RETURN
  11860                     (_bcm_tr3_cosq_index_resolve(unit, local_port, ci,
  11861                           _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE,
  11862                           NULL, &startq, NULL));
  11863                 
  11864             }
  11865         }
  11866         mem = MMU_THDO_CONFIG_QUEUEm;
  11867         
  11868         BCM_IF_ERROR_RETURN
  11869             (soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  11870         *arg = soc_mem_field32_get(unit, mem, entry, Q_LIMIT_DYNAMIC_CELLf);
  11871 
  11872     } else if (type == bcmCosqControlEgressMCSharedDynamicEnable) {
  11873         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
  11874             BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) {
  11875             return BCM_E_PARAM;
  11876         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  11877             BCM_IF_ERROR_RETURN
  11878                 (_bcm_tr3_cosq_index_resolve(unit, gport, cosq,
  11879                                          _BCM_TR3_COSQ_INDEX_STYLE_EGR_POOL,
  11880                                          &local_port, &startq, NULL));
  11881         }
  11882         else {
  11883             if (cosq == BCM_COS_INVALID) {
  11884                 from_cos = to_cos = 0;
  11885             } else {
  11886                 from_cos = to_cos = cosq;
  11887             }
  11888 
  11889             BCM_IF_ERROR_RETURN
  11890                 (_bcm_tr3_cosq_localport_resolve(unit, gport, &local_port));
  11891             if (local_port < 0) {
  11892                 return BCM_E_PORT;
  11893             }
  11894             for (ci = from_cos; ci <= to_cos; ci++) {
  11895                 BCM_IF_ERROR_RETURN
  11896                     (_bcm_tr3_cosq_index_resolve(unit, local_port, ci,
  11897                                          _BCM_TR3_COSQ_INDEX_STYLE_EGR_POOL,
  11898                                          NULL, &startq, NULL));
  11899               
  11900             }
  11901         }
  11902         if (cosq < 0) {
  11903             return BCM_E_PARAM;
  11904         }
  11905         
  11906         BCM_IF_ERROR_RETURN
  11907             (READ_OP_QUEUE_CONFIG1_CELLr(unit, local_port, startq, &rval));
  11908         *arg = soc_reg_field_get(unit, OP_QUEUE_CONFIG1_CELLr, rval, Q_LIMIT_DYNAMIC_CELLf);
  11909 
  11910     } else {
  11911         return BCM_E_PARAM;
  11912     }
  11913 
  11914     return BCM_E_NONE;
  11915 }
  11916 
  11917 /*
  11918  * Function:
  11919  *     _bcm_tr3_cosq_qgroup_limit_enable_set
  11920  * Purpose:
  11921  *     Enable/Disable COS queue Queue group
  11922  * Parameters:
  11923  *      unit   - (IN) unit number
  11924  *      gport  - (IN) GPORT identifier
  11925  *      cosq   - (IN) COS queue to configure
  11926  *      type   - (IN) Operation type
  11927  *      enable - (IN) Enable/Disable
  11928  * Returns:
  11929  *      BCM_E_XXX
  11930  */
  11931 STATIC int
  11932 _bcm_tr3_cosq_qgroup_limit_enable_set(int unit, bcm_gport_t gport,
  11933         bcm_cos_queue_t cosq, bcm_cosq_control_t type, int enable)
  11934 {
  11935     bcm_port_t  local_port;
  11936     soc_mem_t   mem = INVALIDm;
  11937     uint32      entry[SOC_MAX_MEM_WORDS];
  11938     int         startq;
  11939     int         qgroup_valid;
  11940 
  11941     if (!((enable == 0) || (enable == 1))) {
  11942         return BCM_E_PARAM;
  11943     }
  11944 
  11945     if (type == bcmCosqControlEgressUCQueueGroupMinEnable) {
  11946 
  11947         /* Resolve cosq for port or take from input argument */
  11948         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  11949             BCM_IF_ERROR_RETURN
  11950                 (_bcm_tr3_cosq_index_resolve(unit, gport, cosq,
  11951                                     _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE,
  11952                                     &local_port, &startq, NULL));
  11953         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  11954             /* Operation not valid for the multicast queue */
  11955             return BCM_E_PARAM;
  11956         } else {
  11957             if (cosq < -1) {
  11958                 return BCM_E_PARAM;
  11959             }
  11960             BCM_IF_ERROR_RETURN
  11961                 (_bcm_tr3_cosq_localport_resolve(unit, gport, &local_port));
  11962             if (local_port < 0) {
  11963                 return BCM_E_PORT;
  11964             }
  11965 
  11966             BCM_IF_ERROR_RETURN
  11967                 (_bcm_tr3_cosq_index_resolve(unit, local_port, cosq,
  11968                                 _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE,
  11969                                 NULL, &startq, NULL));
  11970         } /* if BCM_GPORT_IS_UCAST_QUEUE_GROUP */
  11971 
  11972         /* Update Table */
  11973         mem = MMU_THDO_Q_TO_QGRP_MAPm;
  11974         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL,
  11975                     startq, entry));
  11976         qgroup_valid = soc_mem_field32_get(unit, mem, entry, QGROUP_VALIDf);
  11977         if (enable != qgroup_valid) {
  11978             soc_mem_field32_set(unit, mem, entry, USE_QGROUP_MINf, enable);
  11979             soc_mem_field32_set(unit, mem, entry, QGROUP_VALIDf, enable);
  11980             BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL,
  11981                         startq, entry));
  11982         }
  11983     } else {
  11984         return BCM_E_PARAM;
  11985     } /* If type */
  11986 
  11987     return BCM_E_NONE;
  11988 }
  11989 
  11990 /*
  11991  * Function:
  11992  *     _bcm_tr3_cosq_qgroup_limit_enable_get
  11993  * Purpose:
  11994  *     Enable/Disable COS queue Queue group
  11995  * Parameters:
  11996  *      unit   - (IN) unit number
  11997  *      gport  - (IN) GPORT identifier
  11998  *      cosq   - (IN) COS queue to configure
  11999  *      type   - (IN) Operation type
  12000  *      enable - (OUT) Enable/Disable status
  12001  * Returns:
  12002  *      BCM_E_XXX
  12003  */
  12004 STATIC int
  12005 _bcm_tr3_cosq_qgroup_limit_enable_get(int unit, bcm_gport_t gport,
  12006         bcm_cos_queue_t cosq, bcm_cosq_control_t type, int *enable)
  12007 {
  12008     bcm_port_t  local_port;
  12009     soc_mem_t   mem = INVALIDm;
  12010     uint32      entry[SOC_MAX_MEM_WORDS];
  12011     int         startq;
  12012 
  12013     if (type == bcmCosqControlEgressUCQueueGroupMinEnable) {
  12014 
  12015         /* Resolve cosq for port or take from input argument */
  12016         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  12017             BCM_IF_ERROR_RETURN
  12018                 (_bcm_tr3_cosq_index_resolve(unit, gport, cosq,
  12019                                     _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE,
  12020                                     &local_port, &startq, NULL));
  12021         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  12022             /* Operation not valid for the multicast queue */
  12023             return BCM_E_PARAM;
  12024         } else {
  12025             if (cosq < -1) {
  12026                 return BCM_E_PARAM;
  12027             }
  12028             BCM_IF_ERROR_RETURN
  12029                 (_bcm_tr3_cosq_localport_resolve(unit, gport, &local_port));
  12030             if (local_port < 0) {
  12031                 return BCM_E_PORT;
  12032             }
  12033 
  12034             BCM_IF_ERROR_RETURN
  12035                 (_bcm_tr3_cosq_index_resolve(unit, local_port, cosq,
  12036                                 _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE,
  12037                                 NULL, &startq, NULL));
  12038         } /* if BCM_GPORT_IS_UCAST_QUEUE_GROUP */
  12039 
  12040         /* Retireve data from the table */
  12041         mem = MMU_THDO_Q_TO_QGRP_MAPm;
  12042         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL,
  12043                     startq, entry));
  12044         *enable = soc_mem_field32_get(unit, mem, entry, USE_QGROUP_MINf);
  12045     } else {
  12046         return BCM_E_PARAM;
  12047     } /* If type */
  12048 
  12049     return BCM_E_NONE;
  12050 }
  12051 
  12052 STATIC int
  12053 _bcm_tr3_cosq_egr_queue_limit_enable_get(int unit, bcm_gport_t gport,
  12054                                                  bcm_cos_queue_t cosq,
  12055                                                  bcm_cosq_control_t type,
  12056                                                  int *arg)
  12057 {
  12058     bcm_port_t local_port;
  12059     int startq;
  12060     uint32 entry[SOC_MAX_MEM_WORDS];
  12061     uint32 rval;
  12062     soc_mem_t mem = INVALIDm;
  12063 
  12064     if (arg == NULL) {
  12065         return BCM_E_PARAM;
  12066     }
  12067 
  12068     if (type == bcmCosqControlEgressUCQueueLimitEnable) {
  12069         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
  12070             BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) {
  12071             BCM_IF_ERROR_RETURN
  12072                 (_bcm_tr3_cosq_index_resolve(unit, gport, cosq,
  12073                                              _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE,
  12074                                              &local_port, &startq, NULL));
  12075         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  12076             return BCM_E_PARAM;
  12077         } else {
  12078             if (cosq < 0) {
  12079                 return BCM_E_PARAM;
  12080             }
  12081             BCM_IF_ERROR_RETURN
  12082                 (_bcm_tr3_cosq_localport_resolve(unit, gport, &local_port));
  12083             if (local_port < 0) {
  12084                 return BCM_E_PORT;
  12085             }
  12086             BCM_IF_ERROR_RETURN
  12087                 (_bcm_tr3_cosq_index_resolve
  12088                  (unit, local_port, cosq, _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE,
  12089                   NULL, &startq, NULL));
  12090         }
  12091 
  12092         mem = MMU_THDO_CONFIG_QUEUEm;
  12093         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  12094         *arg = soc_mem_field32_get(unit, mem, entry, Q_LIMIT_ENABLE_CELLf);
  12095     } else if (type == bcmCosqControlEgressMCQueueLimitEnable) {
  12096         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
  12097             BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) {
  12098             return BCM_E_PARAM;
  12099         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  12100             BCM_IF_ERROR_RETURN
  12101                 (_bcm_tr3_cosq_index_resolve(unit, gport, cosq,
  12102                                              _BCM_TR3_COSQ_INDEX_STYLE_MCAST_QUEUE,
  12103                                              &local_port, &startq, NULL));
  12104         } else {
  12105             if (cosq < 0) {
  12106                 return BCM_E_PARAM;
  12107             }
  12108             BCM_IF_ERROR_RETURN
  12109                 (_bcm_tr3_cosq_localport_resolve(unit, gport, &local_port));
  12110             if (local_port < 0) {
  12111                 return BCM_E_PORT;
  12112             }
  12113             BCM_IF_ERROR_RETURN
  12114                 (_bcm_tr3_cosq_index_resolve(unit, local_port, cosq,
  12115                                             _BCM_TR3_COSQ_INDEX_STYLE_MCAST_QUEUE,
  12116                                             NULL, &startq, NULL));
  12117         }
  12118         if (cosq < 0) {
  12119             return BCM_E_PARAM;
  12120         }
  12121 
  12122         BCM_IF_ERROR_RETURN
  12123             (READ_OP_QUEUE_CONFIG1_CELLr(unit, local_port, cosq, &rval));
  12124         *arg = soc_reg_field_get(unit, OP_QUEUE_CONFIG1_CELLr, rval, Q_LIMIT_ENABLE_CELLf);
  12125     } else {
  12126         return BCM_E_PARAM;
  12127     }
  12128 
  12129     return BCM_E_NONE;
  12130 }
  12131 
  12132 
  12133 STATIC int
  12134 _bcm_tr3_cosq_ing_pool_set(int unit, bcm_gport_t gport, bcm_cos_queue_t pri_grp,
  12135         bcm_cosq_control_t type, int arg)
  12136 {
  12137     int local_port;
  12138     uint32 rval;
  12139     static const soc_field_t prigroup_spid_field[] = {
  12140         PG0_SPIDf, PG1_SPIDf, PG2_SPIDf, PG3_SPIDf,
  12141         PG4_SPIDf, PG5_SPIDf, PG6_SPIDf, PG7_SPIDf
  12142     };
  12143     if(( arg < 0 ) || (arg > 3 )) {
  12144             return BCM_E_PARAM;
  12145     }
  12146 
  12147     BCM_IF_ERROR_RETURN
  12148             (_bcm_tr3_cosq_localport_resolve(unit, gport, &local_port));
  12149 
  12150     if (!SOC_PORT_VALID(unit, local_port)) {
  12151         return BCM_E_PORT;
  12152     }
  12153     /* coverity fix : pri_grp can take value from 0 to 7 */
  12154     if ((pri_grp < 0) || (pri_grp >= 8)) {
  12155         return BCM_E_PARAM;
  12156     }
  12157 
  12158     SOC_IF_ERROR_RETURN(READ_PORT_PG_SPIDr(unit, local_port, &rval));
  12159     soc_reg_field_set(unit, PORT_PG_SPIDr, &rval,
  12160                                 prigroup_spid_field[pri_grp],arg);
  12161     BCM_IF_ERROR_RETURN(WRITE_PORT_PG_SPIDr(unit, local_port, rval));
  12162     return BCM_E_NONE;
  12163 }
  12164 
  12165 STATIC int
  12166 _bcm_tr3_cosq_ing_pool_get(int unit, bcm_gport_t gport,
  12167         bcm_cos_queue_t pri_grp,
  12168         bcm_cosq_control_t type, int *arg)
  12169 {
  12170     int pool_start_idx = 0, pool_end_idx =0;
  12171     BCM_IF_ERROR_RETURN(
  12172             _bcm_tr3_cosq_ingress_sp_get(
  12173                 unit, gport, pri_grp, &pool_start_idx, &pool_end_idx));
  12174     *arg = pool_start_idx;
  12175     return BCM_E_NONE;
  12176 }
  12177 
  12178 
  12179 STATIC int
  12180 _bcm_tr3_cosq_ing_res_set(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
  12181                           bcm_cosq_control_t type, int arg)
  12182 {
  12183     bcm_port_t local_port;
  12184     int phy_port, mmu_port, midx;
  12185     uint32 max_val, rval;
  12186     uint32 entry[SOC_MAX_MEM_WORDS];
  12187     soc_mem_t mem = INVALIDm;
  12188     soc_field_t fld_limit = INVALIDf;
  12189     soc_reg_t reg = INVALIDr;
  12190     int port_pg, port_pg_pool, granularity = 1;
  12191     static const soc_reg_t prigroup_reg[] = {
  12192         PORT_PRI_GRP0r, PORT_PRI_GRP1r
  12193     };
  12194     static const soc_field_t prigroup_field[] = {
  12195         PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf,
  12196         PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf,
  12197         PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf,
  12198         PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf
  12199     };
  12200     static const soc_field_t prigroup_spid_field[] = {
  12201         PG0_SPIDf, PG1_SPIDf, PG2_SPIDf, PG3_SPIDf,
  12202         PG4_SPIDf, PG5_SPIDf, PG6_SPIDf, PG7_SPIDf
  12203     };
  12204     soc_info_t *si;
  12205 
  12206     if (cosq > 15 || cosq < 0) {
  12207         /* Error. Input pri > Max Pri_Grp */
  12208         return BCM_E_PARAM;
  12209     }
  12210 
  12211     if (arg < 0) {
  12212         return BCM_E_PARAM;
  12213     }
  12214 
  12215     arg = _BCM_TR3_BYTES_TO_CELLS(arg);
  12216     BCM_IF_ERROR_RETURN
  12217         (_bcm_tr3_cosq_localport_resolve(unit, gport, &local_port));
  12218     if (local_port < 0) {
  12219         return BCM_E_PORT;
  12220     }
  12221 
  12222     /* get PG for port using Port+Cos */
  12223     if (cosq < 8) {
  12224         reg = prigroup_reg[0];
  12225     } else {
  12226         reg = prigroup_reg[1];
  12227     }
  12228 
  12229     SOC_IF_ERROR_RETURN
  12230         (soc_reg32_get(unit, reg, local_port, 0, &rval));
  12231     port_pg = soc_reg_field_get(unit, reg, rval, prigroup_field[cosq]);
  12232 
  12233     si = &SOC_INFO(unit);
  12234     phy_port = si->port_l2p_mapping[local_port];
  12235     mmu_port = si->port_p2m_mapping[phy_port];
  12236 
  12237     if ((type == bcmCosqControlIngressPortPGSharedLimitBytes) ||
  12238         (type == bcmCosqControlIngressPortPGMinLimitBytes)||
  12239         (type == bcmCosqControlIngressPortPGHeadroomLimitBytes)||
  12240         (type == bcmCosqControlIngressPortPGResetFloorBytes)) {
  12241         mem = THDI_PORT_PG_CONFIGm;
  12242         /* get index for Port-PG */
  12243         midx = (mmu_port * 8) + port_pg;
  12244 
  12245     } else if ((type == bcmCosqControlIngressPortPoolMaxLimitBytes) ||
  12246                (type == bcmCosqControlIngressPortPoolMinLimitBytes)) {
  12247         reg = PORT_PG_SPIDr;
  12248 
  12249         SOC_IF_ERROR_RETURN
  12250             (soc_reg32_get(unit, reg, local_port, 0, &rval));
  12251         port_pg_pool = soc_reg_field_get(unit, reg, rval, prigroup_spid_field[port_pg]);
  12252 
  12253         mem = THDI_PORT_SP_CONFIGm;
  12254         /* get index for Port-SP */
  12255         midx = (mmu_port * 4) + port_pg_pool;;
  12256     } else {
  12257         return BCM_E_UNAVAIL;
  12258     }
  12259 
  12260     if (midx < 0) {
  12261         return BCM_E_PARAM;
  12262     }
  12263 
  12264     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, entry));
  12265 
  12266     switch (type) {
  12267     case bcmCosqControlIngressPortPGSharedLimitBytes:
  12268         fld_limit = PG_SHARED_LIMITf;
  12269         granularity = 1;
  12270         break;
  12271     case bcmCosqControlIngressPortPoolMaxLimitBytes:
  12272         fld_limit = PORT_SP_MAX_LIMITf;
  12273         granularity = 1;
  12274         break;
  12275     case bcmCosqControlIngressPortPGMinLimitBytes:
  12276         fld_limit = PG_MIN_LIMITf;
  12277         granularity = 1;
  12278         break;
  12279     case bcmCosqControlIngressPortPoolMinLimitBytes:
  12280         fld_limit = PORT_SP_MIN_LIMITf;
  12281         granularity = 1;
  12282         break;
  12283     case bcmCosqControlIngressPortPGHeadroomLimitBytes:
  12284         fld_limit = PG_HDRM_LIMITf;
  12285         granularity = 1;
  12286         break;
  12287     case bcmCosqControlIngressPortPGResetFloorBytes:
  12288         fld_limit = PG_RESET_FLOORf;
  12289         granularity = 1;
  12290         break;
  12291     /* coverity[dead_error_begin] */
  12292     default:
  12293         return BCM_E_UNAVAIL;
  12294     }
  12295 
  12296     /* Check for min/max values */
  12297     max_val = (1 << soc_mem_field_length(unit, mem, fld_limit)) - 1;
  12298     if ((arg < 0) || ((arg/granularity) > max_val)) {
  12299         return BCM_E_PARAM;
  12300     } else {
  12301         soc_mem_field32_set(unit, mem, entry, fld_limit, (arg/granularity));
  12302     }
  12303     BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, midx, entry));
  12304 
  12305     return BCM_E_NONE;
  12306 }
  12307 
  12308 STATIC int
  12309 _bcm_tr3_cosq_ing_res_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
  12310                           bcm_cosq_control_t type, int *arg)
  12311 {
  12312     bcm_port_t local_port;
  12313     int phy_port, mmu_port, midx;
  12314     uint32 rval;
  12315     uint32 entry[SOC_MAX_MEM_WORDS];
  12316     soc_mem_t mem = INVALIDm;
  12317     soc_field_t fld_limit = INVALIDf;
  12318     soc_reg_t reg = INVALIDr;
  12319     int port_pg, port_pg_pool, granularity = 1;
  12320     static const soc_reg_t prigroup_reg[] = {
  12321         PORT_PRI_GRP0r, PORT_PRI_GRP1r
  12322     };
  12323     static const soc_field_t prigroup_field[] = {
  12324         PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf,
  12325         PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf,
  12326         PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf,
  12327         PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf
  12328     };
  12329     static const soc_field_t prigroup_spid_field[] = {
  12330         PG0_SPIDf, PG1_SPIDf, PG2_SPIDf, PG3_SPIDf,
  12331         PG4_SPIDf, PG5_SPIDf, PG6_SPIDf, PG7_SPIDf
  12332     };
  12333     soc_info_t *si;
  12334 
  12335     if (cosq > 15 || cosq < 0) {
  12336         /* Error. Input pri > Max Pri_Grp */
  12337         return BCM_E_PARAM;
  12338     }
  12339 
  12340     if (!arg) {
  12341         return BCM_E_PARAM;
  12342     }
  12343 
  12344     BCM_IF_ERROR_RETURN
  12345         (_bcm_tr3_cosq_localport_resolve(unit, gport, &local_port));
  12346     if (local_port < 0) {
  12347         return BCM_E_PORT;
  12348     }
  12349 
  12350     /* get PG for port using Port+Cos */
  12351     if (cosq < 8) {
  12352         reg = prigroup_reg[0];
  12353     } else {
  12354         reg = prigroup_reg[1];
  12355     }
  12356 
  12357     SOC_IF_ERROR_RETURN
  12358         (soc_reg32_get(unit, reg, local_port, 0, &rval));
  12359     port_pg = soc_reg_field_get(unit, reg, rval, prigroup_field[cosq]);
  12360 
  12361     si = &SOC_INFO(unit);
  12362     phy_port = si->port_l2p_mapping[local_port];
  12363     mmu_port = si->port_p2m_mapping[phy_port];
  12364 
  12365     if ((type == bcmCosqControlIngressPortPGSharedLimitBytes) ||
  12366         (type == bcmCosqControlIngressPortPGMinLimitBytes)||
  12367         (type == bcmCosqControlIngressPortPGHeadroomLimitBytes)||
  12368         (type == bcmCosqControlIngressPortPGResetFloorBytes)) {
  12369         mem = THDI_PORT_PG_CONFIGm;
  12370         /* get index for Port-PG */
  12371         midx = (mmu_port * 8) + port_pg;
  12372 
  12373     } else if ((type == bcmCosqControlIngressPortPoolMaxLimitBytes) ||
  12374                (type == bcmCosqControlIngressPortPoolMinLimitBytes)) {
  12375         reg = PORT_PG_SPIDr;
  12376 
  12377         SOC_IF_ERROR_RETURN
  12378             (soc_reg32_get(unit, reg, local_port, 0, &rval));
  12379         port_pg_pool = soc_reg_field_get(unit, reg, rval, prigroup_spid_field[port_pg]);
  12380 
  12381         mem = THDI_PORT_SP_CONFIGm;
  12382         /* get index for Port-SP */
  12383         midx = (mmu_port * 4) + port_pg_pool;;
  12384     } else {
  12385         return BCM_E_UNAVAIL;
  12386     }
  12387 
  12388     if (midx < 0) {
  12389         return BCM_E_PARAM;
  12390     }
  12391 
  12392     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, entry));
  12393 
  12394     switch (type) {
  12395     case bcmCosqControlIngressPortPGSharedLimitBytes:
  12396         fld_limit = PG_SHARED_LIMITf;
  12397         granularity = 1;
  12398         break;
  12399     case bcmCosqControlIngressPortPoolMaxLimitBytes:
  12400         fld_limit = PORT_SP_MAX_LIMITf;
  12401         granularity = 1;
  12402         break;
  12403     case bcmCosqControlIngressPortPGMinLimitBytes:
  12404         fld_limit = PG_MIN_LIMITf;
  12405         granularity = 1;
  12406         break;
  12407     case bcmCosqControlIngressPortPoolMinLimitBytes:
  12408         fld_limit = PORT_SP_MIN_LIMITf;
  12409         granularity = 1;
  12410         break;
  12411     case bcmCosqControlIngressPortPGHeadroomLimitBytes:
  12412         fld_limit = PG_HDRM_LIMITf;
  12413         granularity = 1;
  12414         break;
  12415     case bcmCosqControlIngressPortPGResetFloorBytes:
  12416         fld_limit = PG_RESET_FLOORf;
  12417         granularity = 1;
  12418         break;
  12419     /* coverity[dead_error_begin] */
  12420     default:
  12421         return BCM_E_UNAVAIL;
  12422     }
  12423 
  12424     *arg = soc_mem_field32_get(unit, mem, entry, fld_limit);
  12425     *arg = (*arg) * granularity * _BCM_TR3_BYTES_PER_CELL;
  12426 
  12427     return BCM_E_NONE;
  12428 }
  12429 
  12430 /*
  12431  * This function is used to get ingress pool
  12432  * limit given Ingress [Port, Priority]
  12433  */
  12434 STATIC int
  12435 _bcm_tr3_cosq_ing_res_limit_get(int unit, bcm_gport_t gport, bcm_cos_t cosq,
  12436                                bcm_cosq_control_t type, int *arg)
  12437 {
  12438     bcm_port_t local_port;
  12439     uint32 rval;
  12440     soc_reg_t reg = INVALIDr;
  12441     int port_pg, port_pg_pool;
  12442     static const soc_reg_t prigroup_reg[] = {
  12443         PORT_PRI_GRP0r, PORT_PRI_GRP1r
  12444     };
  12445     static const soc_field_t prigroup_field[] = {
  12446        PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf,
  12447        PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf,
  12448        PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf,
  12449        PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf
  12450     };
  12451     static const soc_field_t prigroup_spid_field[] = {
  12452        PG0_SPIDf, PG1_SPIDf, PG2_SPIDf, PG3_SPIDf,
  12453        PG4_SPIDf, PG5_SPIDf, PG6_SPIDf, PG7_SPIDf
  12454     };
  12455 
  12456     if (cosq > 15 || cosq < 0) {
  12457        /* Error. Input pri > Max Pri_Grp */
  12458        return BCM_E_PARAM;
  12459     }
  12460     if (!arg) {
  12461        return BCM_E_PARAM;
  12462     }
  12463 
  12464     BCM_IF_ERROR_RETURN
  12465        (_bcm_tr3_cosq_localport_resolve(unit, gport, &local_port));
  12466     if (local_port < 0) {
  12467        return BCM_E_PORT;
  12468     }
  12469 
  12470     /* get PG for port using Port+Cos */
  12471     if (cosq < 8) {
  12472         reg = prigroup_reg[0];
  12473     } else {
  12474         reg = prigroup_reg[1];
  12475     }
  12476 
  12477     SOC_IF_ERROR_RETURN
  12478        (soc_reg32_get(unit, reg, local_port, 0, &rval));
  12479     port_pg = soc_reg_field_get(unit, reg, rval, prigroup_field[cosq]);
  12480 
  12481 
  12482     if (type == bcmCosqControlIngressPoolLimitBytes) {
  12483         reg = PORT_PG_SPIDr;
  12484 
  12485         SOC_IF_ERROR_RETURN
  12486             (soc_reg32_get(unit, reg, local_port, 0, &rval));
  12487         port_pg_pool = soc_reg_field_get(unit, reg, rval, prigroup_spid_field[port_pg]);
  12488 
  12489         SOC_IF_ERROR_RETURN
  12490             (READ_BUFFER_CELL_LIMIT_SPr(unit, port_pg_pool, &rval));
  12491         *arg = soc_reg_field_get(unit, BUFFER_CELL_LIMIT_SPr, rval, LIMITf);
  12492     } else {
  12493         return BCM_E_PARAM;
  12494     }
  12495 
  12496     *arg = (*arg) * _BCM_TR3_BYTES_PER_CELL;
  12497 
  12498     return BCM_E_NONE;
  12499 }
  12500 
  12501 /*
  12502  * This function is used to set ingress pool
  12503  * limit given Ingress [Port, Priority]
  12504  */
  12505 STATIC int
  12506 _bcm_tr3_cosq_ing_res_limit_set(int unit, bcm_gport_t gport, bcm_cos_t cosq,
  12507                                bcm_cosq_control_t type, int arg)
  12508 {
  12509     bcm_port_t local_port;
  12510     uint32 max_val, rval;
  12511     soc_reg_t reg = INVALIDr;
  12512     int port_pg, port_pg_pool;
  12513     static const soc_reg_t prigroup_reg[] = {
  12514         PORT_PRI_GRP0r, PORT_PRI_GRP1r
  12515     };
  12516     static const soc_field_t prigroup_field[] = {
  12517         PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf,
  12518         PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf,
  12519         PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf,
  12520         PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf
  12521     };
  12522     static const soc_field_t prigroup_spid_field[] = {
  12523         PG0_SPIDf, PG1_SPIDf, PG2_SPIDf, PG3_SPIDf,
  12524         PG4_SPIDf, PG5_SPIDf, PG6_SPIDf, PG7_SPIDf
  12525     };
  12526 
  12527     if (cosq > 15 || cosq < 0) {
  12528         /* Error. Input pri > Max Pri_Grp */
  12529         return BCM_E_PARAM;
  12530     }
  12531 
  12532     if (arg < 0) {
  12533         return BCM_E_PARAM;
  12534     }
  12535 
  12536     arg = _BCM_TR3_BYTES_TO_CELLS(arg);
  12537     BCM_IF_ERROR_RETURN
  12538         (_bcm_tr3_cosq_localport_resolve(unit, gport, &local_port));
  12539     if (local_port < 0) {
  12540         return BCM_E_PORT;
  12541     }
  12542 
  12543     /* get PG for port using Port+Cos */
  12544     if (cosq < 8) {
  12545         reg = prigroup_reg[0];
  12546     } else {
  12547         reg = prigroup_reg[1];
  12548     }
  12549 
  12550     SOC_IF_ERROR_RETURN
  12551         (soc_reg32_get(unit, reg, local_port, 0, &rval));
  12552     port_pg = soc_reg_field_get(unit, reg, rval, prigroup_field[cosq]);
  12553 
  12554     if (type == bcmCosqControlIngressPoolLimitBytes) {
  12555         reg = PORT_PG_SPIDr;
  12556 
  12557         SOC_IF_ERROR_RETURN
  12558             (soc_reg32_get(unit, reg, local_port, 0, &rval));
  12559         port_pg_pool = soc_reg_field_get(unit, reg, rval, prigroup_spid_field[port_pg]);
  12560 
  12561         rval = 0;
  12562         SOC_IF_ERROR_RETURN(READ_BUFFER_CELL_LIMIT_SPr(unit, port_pg_pool, &rval));
  12563         /* Check for min/max values */
  12564         max_val = (1 << soc_reg_field_length(unit, BUFFER_CELL_LIMIT_SPr, LIMITf)) - 1;
  12565         if ((arg < 0) || (arg > max_val)) {
  12566             return BCM_E_PARAM;
  12567         } else {
  12568             soc_reg_field_set(unit, BUFFER_CELL_LIMIT_SPr, &rval, LIMITf, arg);
  12569         }
  12570 
  12571         SOC_IF_ERROR_RETURN(WRITE_BUFFER_CELL_LIMIT_SPr(unit, port_pg_pool, rval));
  12572     } else {
  12573         return BCM_E_PARAM;
  12574     }
  12575 
  12576     return BCM_E_NONE;
  12577 }
  12578 
  12579 
  12580 STATIC int
  12581 _bcm_tr3_cosq_egr_pool_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
  12582                           bcm_cosq_control_t type, int *arg)
  12583 {
  12584     bcm_port_t local_port;
  12585     int startq, pool;
  12586     uint32 rval;
  12587     uint32 entry[SOC_MAX_MEM_WORDS];
  12588 
  12589     if (!arg) {
  12590         return BCM_E_PARAM;
  12591     }
  12592 
  12593     if (type == bcmCosqControlUCEgressPool) {
  12594         BCM_IF_ERROR_RETURN
  12595             (_bcm_tr3_cosq_index_resolve(unit, gport, cosq,
  12596                                         _BCM_TR3_COSQ_INDEX_STYLE_UC_EGR_POOL,
  12597                                         &local_port, &startq, NULL));
  12598     } else {
  12599         BCM_IF_ERROR_RETURN
  12600             (_bcm_tr3_cosq_index_resolve(unit, gport, cosq,
  12601                                         _BCM_TR3_COSQ_INDEX_STYLE_EGR_POOL,
  12602                                         &local_port, &startq, NULL));
  12603     }
  12604 
  12605     if (type == bcmCosqControlEgressPoolLimitEnable) {
  12606         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
  12607             BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) {
  12608             BCM_IF_ERROR_RETURN(soc_reg32_get(unit, OP_PORT_CONFIG1_CELLr, 
  12609                                             local_port, 0, &rval));
  12610             *arg = soc_reg_field_get(unit, OP_PORT_CONFIG1_CELLr, rval, 
  12611                                           PORT_LIMIT_ENABLE_CELLf);
  12612         } else {
  12613             BCM_IF_ERROR_RETURN(soc_reg32_get(unit, OP_QUEUE_CONFIG1_CELLr, 
  12614                                             local_port, startq, &rval));
  12615             *arg = soc_reg_field_get(unit, OP_QUEUE_CONFIG1_CELLr, 
  12616                                         rval, Q_LIMIT_ENABLE_CELLf);
  12617         }
  12618         return BCM_E_NONE;
  12619     }
  12620 
  12621     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
  12622         BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) {
  12623         BCM_IF_ERROR_RETURN(
  12624                 soc_mem_read(unit, MMU_THDO_Q_TO_QGRP_MAPm, MEM_BLOCK_ALL,
  12625                              startq, entry));
  12626         pool = soc_mem_field32_get(unit, MMU_THDO_Q_TO_QGRP_MAPm, entry, Q_SPIDf);
  12627     } else {
  12628         BCM_IF_ERROR_RETURN(
  12629             soc_reg32_get(unit, OP_QUEUE_CONFIG1_CELLr, local_port, startq, &rval));
  12630         pool = soc_reg_field_get(unit, OP_QUEUE_CONFIG1_CELLr, rval, Q_SPIDf);
  12631     }
  12632 
  12633     /* per service pool settings */
  12634     if (type == bcmCosqControlEgressPoolSharedLimitBytes ||
  12635         type == bcmCosqControlEgressPoolResumeLimitBytes ||
  12636         type == bcmCosqControlEgressPoolYellowSharedLimitBytes ||
  12637         type == bcmCosqControlEgressPoolYellowResumeLimitBytes ||
  12638         type == bcmCosqControlEgressPoolRedSharedLimitBytes ||
  12639         type == bcmCosqControlEgressPoolRedResumeLimitBytes) {
  12640         soc_reg_t reg;
  12641         soc_field_t fld_limit = INVALIDf;
  12642         int granularity = 1;
  12643 
  12644         switch (type) {
  12645         case bcmCosqControlEgressPoolSharedLimitBytes:
  12646             reg = OP_BUFFER_SHARED_LIMIT_CELLr;
  12647             fld_limit = OP_BUFFER_SHARED_LIMIT_CELLf;
  12648             granularity = 1;
  12649             break;
  12650         case bcmCosqControlEgressPoolResumeLimitBytes:
  12651             reg = OP_BUFFER_SHARED_LIMIT_RESUME_CELLr;
  12652             fld_limit = OP_BUFFER_SHARED_LIMIT_RESUME_CELLf;
  12653             granularity = 1;
  12654             break;
  12655         case bcmCosqControlEgressPoolYellowSharedLimitBytes:
  12656             reg = OP_BUFFER_LIMIT_YELLOW_CELLr;
  12657             fld_limit = OP_BUFFER_LIMIT_YELLOW_CELLf;
  12658             granularity = 8;
  12659             break;
  12660         case bcmCosqControlEgressPoolYellowResumeLimitBytes:
  12661             reg = OP_BUFFER_LIMIT_RESUME_YELLOW_CELLr;
  12662             fld_limit = OP_BUFFER_LIMIT_RESUME_YELLOW_CELLf;
  12663             granularity = 8;
  12664             break;
  12665         case bcmCosqControlEgressPoolRedSharedLimitBytes:
  12666             reg = OP_BUFFER_LIMIT_RED_CELLr;
  12667             fld_limit = OP_BUFFER_LIMIT_RED_CELLf;
  12668             granularity = 8;
  12669             break;
  12670         case bcmCosqControlEgressPoolRedResumeLimitBytes:
  12671             reg = OP_BUFFER_LIMIT_RESUME_RED_CELLr;
  12672             fld_limit = OP_BUFFER_LIMIT_RESUME_RED_CELLf;
  12673             granularity = 8;
  12674             break;
  12675         /*
  12676          * COVERITY
  12677          *
  12678          * This default is unreachable but needed for some compiler.
  12679          */
  12680         /* coverity[dead_error_begin] */
  12681         default:
  12682             return BCM_E_UNAVAIL;
  12683         }
  12684 
  12685         BCM_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, pool, &rval));
  12686 
  12687         *arg = soc_reg_field_get(unit, reg, rval, fld_limit);
  12688         *arg = (*arg) * granularity * _BCM_TR3_BYTES_PER_CELL;
  12689 
  12690         return BCM_E_NONE;
  12691     }
  12692 
  12693     switch (type) {
  12694     case bcmCosqControlEgressPool:
  12695         *arg = pool;
  12696         break;
  12697     case bcmCosqControlMCEgressPool:
  12698         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 
  12699             BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport) ||
  12700             BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  12701             return BCM_E_PARAM;
  12702         }
  12703         *arg = pool;
  12704         break;
  12705 
  12706     case bcmCosqControlUCEgressPool:
  12707         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 
  12708             BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport) ||
  12709             BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  12710             return BCM_E_PARAM;
  12711         }
  12712         startq = SOC_INFO(unit).port_uc_cosq_base[local_port] + startq;
  12713         BCM_IF_ERROR_RETURN(
  12714                 soc_mem_read(unit, MMU_THDO_Q_TO_QGRP_MAPm, MEM_BLOCK_ALL,
  12715                              startq, entry));
  12716         pool = soc_mem_field32_get(unit, MMU_THDO_Q_TO_QGRP_MAPm, entry, Q_SPIDf);
  12717         *arg = pool;
  12718         break;
  12719 
  12720     case bcmCosqControlEgressPoolLimitBytes:
  12721         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
  12722             BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) {
  12723             BCM_IF_ERROR_RETURN(
  12724                 soc_mem_read(unit, MMU_THDO_CONFIG_QUEUEm, MEM_BLOCK_ALL,
  12725                              startq, entry));
  12726             *arg = soc_mem_field32_get(unit, MMU_THDO_CONFIG_QUEUEm, entry,
  12727                                 Q_SHARED_LIMIT_CELLf);
  12728         } else {
  12729             BCM_IF_ERROR_RETURN(
  12730              soc_reg32_get(unit, OP_QUEUE_CONFIG_CELLr, local_port, startq, &rval));
  12731             *arg = soc_reg_field_get(unit, OP_QUEUE_CONFIG_CELLr, rval,
  12732                               Q_SHARED_LIMIT_CELLf) * 8;
  12733         }
  12734         break;
  12735     case bcmCosqControlEgressPoolYellowLimitBytes:
  12736         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
  12737             BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) {
  12738             BCM_IF_ERROR_RETURN(
  12739                 soc_mem_read(unit, MMU_THDO_CONFIG_QUEUEm, MEM_BLOCK_ALL,
  12740                              startq, entry));
  12741             *arg = soc_mem_field32_get(unit, MMU_THDO_CONFIG_QUEUEm, 
  12742                             entry, LIMIT_YELLOW_CELLf) * 8;
  12743         } else {
  12744             return BCM_E_UNAVAIL;
  12745         }
  12746         break;
  12747     case bcmCosqControlEgressPoolRedLimitBytes:
  12748         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
  12749             BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) {
  12750             BCM_IF_ERROR_RETURN(
  12751                 soc_mem_read(unit, MMU_THDO_CONFIG_QUEUEm, MEM_BLOCK_ALL,
  12752                              startq, entry));
  12753             *arg = soc_mem_field32_get(unit, MMU_THDO_CONFIG_QUEUEm, 
  12754                                         entry, LIMIT_RED_CELLf) * 8;
  12755         } else {
  12756             BCM_IF_ERROR_RETURN(
  12757              soc_reg32_get(unit, OP_QUEUE_LIMIT_COLOR_CELLr, 
  12758                             local_port, startq, &rval));
  12759             *arg = soc_reg_field_get(unit, OP_QUEUE_LIMIT_COLOR_CELLr, rval, REDf)*8;
  12760         }
  12761         break;
  12762     default:
  12763         return BCM_E_UNAVAIL;
  12764     }
  12765     return BCM_E_NONE;
  12766 }
  12767 
  12768 STATIC int
  12769 _bcm_tr3_cosq_ef_op_at_index(int unit, int hw_index, _bcm_cosq_op_t op, 
  12770                              int *ef_val)
  12771 {
  12772     lls_l2_parent_entry_t entry;
  12773 
  12774     SOC_IF_ERROR_RETURN
  12775         (soc_mem_read(unit, LLS_L2_PARENTm, MEM_BLOCK_ALL, hw_index, &entry));
  12776 
  12777     if (op == _BCM_COSQ_OP_GET) {
  12778         *ef_val = soc_mem_field32_get(unit, LLS_L2_PARENTm, &entry, C_EFf);
  12779     } else {
  12780         soc_mem_field32_set(unit, LLS_L2_PARENTm, &entry, C_EFf, *ef_val);
  12781         SOC_IF_ERROR_RETURN
  12782             (soc_mem_write(unit, LLS_L2_PARENTm, MEM_BLOCK_ALL, 
  12783                             hw_index, &entry));
  12784     }
  12785    
  12786     return BCM_E_NONE;
  12787 }
  12788 
  12789 STATIC int
  12790 _bcm_tr3_cosq_ef_op(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, int *arg,
  12791                     _bcm_cosq_op_t op)
  12792 {
  12793     _bcm_tr3_cosq_node_t *node;
  12794     bcm_port_t local_port;
  12795     int index, numq, from_cos, to_cos, ci;
  12796 
  12797     if (BCM_GPORT_IS_SCHEDULER(gport)) {
  12798         BCM_IF_ERROR_RETURN
  12799             (_bcm_tr3_cosq_node_get(unit, gport, 0, NULL, 
  12800                                     &local_port, NULL, &node));
  12801         BCM_IF_ERROR_RETURN(
  12802                _bcm_tr3_cosq_child_node_at_input(node, cosq, &node));
  12803         gport = node->gport;
  12804         cosq = 0;
  12805     }
  12806 
  12807     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
  12808         BCM_GPORT_IS_DESTMOD_QUEUE_GROUP(gport)) {
  12809         BCM_IF_ERROR_RETURN
  12810             (_bcm_tr3_cosq_index_resolve
  12811              (unit, gport, cosq, _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE,
  12812               &local_port, &index, NULL));
  12813         return _bcm_tr3_cosq_ef_op_at_index(unit, index, op, arg);
  12814     } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  12815         BCM_IF_ERROR_RETURN
  12816             (_bcm_tr3_cosq_index_resolve
  12817              (unit, gport, cosq, _BCM_TR3_COSQ_INDEX_STYLE_MCAST_QUEUE,
  12818               &local_port, &index, NULL));
  12819         return _bcm_tr3_cosq_ef_op_at_index(unit, index, op, arg);
  12820     } else if (BCM_GPORT_IS_SCHEDULER(gport)) {
  12821         return BCM_E_PARAM;
  12822     } else {
  12823         BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_port_has_ets(unit, local_port));
  12824         if (cosq == BCM_COS_INVALID) {
  12825             from_cos = 0;
  12826             to_cos = _TR3_NUM_COS(unit) - 1;
  12827         } else {
  12828             from_cos = to_cos = cosq;
  12829         }
  12830         for (ci = from_cos; ci <= to_cos; ci++) {
  12831             BCM_IF_ERROR_RETURN
  12832                 (_bcm_tr3_cosq_index_resolve
  12833                  (unit, gport, ci, _BCM_TR3_COSQ_INDEX_STYLE_UCAST_QUEUE,
  12834                   &local_port, &index, &numq));
  12835 
  12836             BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_ef_op_at_index(unit, 
  12837                                 index, op, arg));
  12838             if (op == _BCM_COSQ_OP_GET) {
  12839                 return BCM_E_NONE;
  12840             }
  12841 
  12842             BCM_IF_ERROR_RETURN
  12843                 (_bcm_tr3_cosq_index_resolve
  12844                  (unit, gport, ci, _BCM_TR3_COSQ_INDEX_STYLE_MCAST_QUEUE,
  12845                   &local_port, &index, &numq));
  12846 
  12847             BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_ef_op_at_index(unit, 
  12848                                 index, op, arg));
  12849         }
  12850     }
  12851     return BCM_E_NONE;
  12852 }
  12853 
  12854 STATIC int
  12855 _bcm_tr3_cosq_port_qnum_get(int unit, bcm_gport_t gport,
  12856         bcm_cos_queue_t cosq, bcm_cosq_control_t type, int *arg)
  12857 {
  12858     bcm_port_t local_port;
  12859     if (!arg) {
  12860         return BCM_E_PARAM;
  12861     }
  12862 
  12863     if (!BCM_COSQ_QUEUE_VALID(unit, cosq)) {
  12864         return BCM_E_PARAM;
  12865     }
  12866 
  12867     BCM_IF_ERROR_RETURN
  12868         (_bcm_tr3_cosq_localport_resolve(unit, gport, &local_port));
  12869     if (local_port < 0) {
  12870         return BCM_E_PORT;
  12871     }
  12872 
  12873     if (type == bcmCosqControlPortQueueUcast) {
  12874         *arg = SOC_INFO(unit).port_uc_cosq_base[local_port] + cosq;
  12875     } else {
  12876         *arg = SOC_INFO(unit).port_cosq_base[local_port] + cosq;
  12877     }
  12878 
  12879     return BCM_E_NONE;
  12880 }
  12881 
  12882 STATIC int
  12883 _bcm_tr3_cosq_qcn_proxy_set(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 
  12884                             bcm_cosq_control_t type, int arg)
  12885 {
  12886     int local_port;
  12887     uint32 rval;
  12888     
  12889     BCM_IF_ERROR_RETURN
  12890         (_bcm_tr3_cosq_localport_resolve(unit, gport, &local_port));
  12891     
  12892     BCM_IF_ERROR_RETURN(READ_QCN_CNM_PRP_CTRLr(unit, local_port, &rval));
  12893     soc_reg_field_set(unit, QCN_CNM_PRP_CTRLr, &rval, ENABLEf, !!arg);
  12894     soc_reg_field_set(unit, QCN_CNM_PRP_CTRLr, &rval, PRIORITY_BMAPf, 0xff);
  12895     BCM_IF_ERROR_RETURN(WRITE_QCN_CNM_PRP_CTRLr(unit, local_port, rval));
  12896     return BCM_E_NONE;
  12897 }
  12898 
  12899 int
  12900 bcm_tr3_cosq_control_set(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
  12901                         bcm_cosq_control_t type, int arg)
  12902 {
  12903     switch (type) {
  12904     case bcmCosqControlEgressPool:
  12905     case bcmCosqControlEgressPoolLimitBytes:
  12906     case bcmCosqControlEgressPoolYellowLimitBytes:
  12907     case bcmCosqControlEgressPoolRedLimitBytes:
  12908     case bcmCosqControlEgressPoolLimitEnable:
  12909     case bcmCosqControlUCEgressPool:
  12910     case bcmCosqControlMCEgressPool:
  12911     case bcmCosqControlEgressPoolSharedLimitBytes:
  12912     case bcmCosqControlEgressPoolResumeLimitBytes:
  12913     case bcmCosqControlEgressPoolYellowSharedLimitBytes:
  12914     case bcmCosqControlEgressPoolYellowResumeLimitBytes:
  12915     case bcmCosqControlEgressPoolRedSharedLimitBytes:
  12916     case bcmCosqControlEgressPoolRedResumeLimitBytes:
  12917         return _bcm_tr3_cosq_egr_pool_set(unit, gport, cosq, type, arg);
  12918     case bcmCosqControlEgressUCQueueSharedLimitBytes:
  12919     case bcmCosqControlEgressMCQueueSharedLimitBytes:
  12920     case bcmCosqControlEgressUCQueueMinLimitBytes:
  12921     case bcmCosqControlEgressMCQueueMinLimitBytes:
  12922         return _bcm_tr3_cosq_egr_queue_set(unit, gport, cosq, type, arg);
  12923     case bcmCosqControlIngressPortPGSharedLimitBytes:
  12924     case bcmCosqControlIngressPortPGMinLimitBytes:
  12925     case bcmCosqControlIngressPortPoolMaxLimitBytes:
  12926     case bcmCosqControlIngressPortPoolMinLimitBytes:
  12927     case bcmCosqControlIngressPortPGHeadroomLimitBytes:
  12928     case bcmCosqControlIngressPortPGResetFloorBytes:
  12929         return _bcm_tr3_cosq_ing_res_set(unit, gport, cosq, type, arg);
  12930     case bcmCosqControlIngressPoolLimitBytes:
  12931         return _bcm_tr3_cosq_ing_res_limit_set(unit, gport, cosq, type, arg);
  12932     case bcmCosqControlIngressPool:
  12933         return _bcm_tr3_cosq_ing_pool_set(unit, gport, cosq, type, arg);
  12934     case bcmCosqControlIngressPortPGSharedDynamicEnable:
  12935     case bcmCosqControlEgressUCSharedDynamicEnable:
  12936     case bcmCosqControlEgressMCSharedDynamicEnable:
  12937         return _bcm_tr3_cosq_dynamic_thresh_enable_set(unit, gport, cosq,
  12938                                                        type, arg);
  12939     case bcmCosqControlEgressUCQueueLimitEnable:
  12940     case bcmCosqControlEgressMCQueueLimitEnable:
  12941         return _bcm_tr3_cosq_egr_queue_limit_enable_set(unit, gport, cosq, type, arg);
  12942     case bcmCosqControlDropLimitAlpha:
  12943     case bcmCosqControlUCDropLimitAlpha:
  12944     case bcmCosqControlMCDropLimitAlpha:
  12945         return _bcm_tr3_cosq_alpha_set(unit, gport, cosq, type,
  12946                         (bcm_cosq_control_drop_limit_alpha_value_t)arg);
  12947     case bcmCosqControlEfPropagation:
  12948         return _bcm_tr3_cosq_ef_op(unit, gport, cosq, &arg, _BCM_COSQ_OP_SET);
  12949     case bcmCosqControlCongestionProxy:
  12950         return _bcm_tr3_cosq_qcn_proxy_set(unit, gport, cosq, type, arg);
  12951     case bcmCosqControlEgressUCQueueGroupMinEnable:
  12952         return _bcm_tr3_cosq_qgroup_limit_enable_set(unit, gport, cosq, type, arg);
  12953     default:
  12954         break;
  12955     }
  12956 
  12957     return BCM_E_UNAVAIL;
  12958 }
  12959 
  12960 int
  12961 bcm_tr3_cosq_control_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
  12962                         bcm_cosq_control_t type, int *arg)
  12963 {
  12964     switch (type) {
  12965     case bcmCosqControlEgressPool:
  12966     case bcmCosqControlEgressPoolLimitBytes:
  12967     case bcmCosqControlEgressPoolYellowLimitBytes:
  12968     case bcmCosqControlEgressPoolRedLimitBytes:
  12969     case bcmCosqControlEgressPoolLimitEnable:
  12970     case bcmCosqControlUCEgressPool:
  12971     case bcmCosqControlMCEgressPool:
  12972     case bcmCosqControlEgressPoolSharedLimitBytes:
  12973     case bcmCosqControlEgressPoolResumeLimitBytes:
  12974     case bcmCosqControlEgressPoolYellowSharedLimitBytes:
  12975     case bcmCosqControlEgressPoolYellowResumeLimitBytes:
  12976     case bcmCosqControlEgressPoolRedSharedLimitBytes:
  12977     case bcmCosqControlEgressPoolRedResumeLimitBytes:
  12978         return _bcm_tr3_cosq_egr_pool_get(unit, gport, cosq, type, arg);
  12979     case bcmCosqControlEgressUCQueueSharedLimitBytes:
  12980     case bcmCosqControlEgressMCQueueSharedLimitBytes:
  12981     case bcmCosqControlEgressUCQueueMinLimitBytes:
  12982     case bcmCosqControlEgressMCQueueMinLimitBytes:
  12983         return _bcm_tr3_cosq_egr_queue_get(unit, gport, cosq, type, arg);
  12984     case bcmCosqControlIngressPortPGSharedLimitBytes:
  12985     case bcmCosqControlIngressPortPGMinLimitBytes:
  12986     case bcmCosqControlIngressPortPoolMaxLimitBytes:
  12987     case bcmCosqControlIngressPortPoolMinLimitBytes:
  12988     case bcmCosqControlIngressPortPGHeadroomLimitBytes:
  12989     case bcmCosqControlIngressPortPGResetFloorBytes:
  12990         return _bcm_tr3_cosq_ing_res_get(unit, gport, cosq, type, arg);
  12991     case bcmCosqControlIngressPoolLimitBytes:
  12992         return _bcm_tr3_cosq_ing_res_limit_get(unit, gport, cosq, type, arg);
  12993     case bcmCosqControlIngressPool:
  12994         return _bcm_tr3_cosq_ing_pool_get(unit, gport, cosq, type, arg);
  12995     case bcmCosqControlIngressPortPGSharedDynamicEnable:
  12996     case bcmCosqControlEgressUCSharedDynamicEnable:
  12997     case bcmCosqControlEgressMCSharedDynamicEnable:
  12998         return _bcm_tr3_cosq_dynamic_thresh_enable_get(unit, gport, cosq,
  12999                                                        type, arg);
  13000     case bcmCosqControlEgressUCQueueLimitEnable:
  13001     case bcmCosqControlEgressMCQueueLimitEnable:
  13002         return _bcm_tr3_cosq_egr_queue_limit_enable_get(unit, gport, cosq, type, arg);
  13003     case bcmCosqControlDropLimitAlpha:
  13004     case bcmCosqControlUCDropLimitAlpha:
  13005     case bcmCosqControlMCDropLimitAlpha:
  13006         return _bcm_tr3_cosq_alpha_get(unit, gport, cosq, type,
  13007                         (bcm_cosq_control_drop_limit_alpha_value_t *)arg);
  13008     case bcmCosqControlEfPropagation:
  13009         return _bcm_tr3_cosq_ef_op(unit, gport, cosq, arg, _BCM_COSQ_OP_GET);
  13010     case bcmCosqControlPortQueueUcast:
  13011     case bcmCosqControlPortQueueMcast:
  13012         return _bcm_tr3_cosq_port_qnum_get(unit, gport, cosq, type, arg);
  13013     case bcmCosqControlEgressUCQueueGroupMinEnable:
  13014         return _bcm_tr3_cosq_qgroup_limit_enable_get(unit, gport, cosq, type, arg);
  13015     default:
  13016         break;
  13017     }
  13018 
  13019     return BCM_E_UNAVAIL;
  13020 }
  13021 
  13022 /*
  13023  * Function:
  13024  *     bcm_tr3_cosq_gport_bandwidth_set
  13025  * Purpose:
  13026  *     Configure COS queue bandwidth control
  13027  * Parameters:
  13028  *     unit   - (IN) unit number
  13029  *     gport  - (IN) GPORT identifier
  13030  *     cosq   - (IN) COS queue to configure, -1 for all COS queues
  13031  *     kbits_sec_min - (IN) minimum bandwidth, kbits/sec
  13032  *     kbits_sec_max - (IN) maximum bandwidth, kbits/sec
  13033  *     flags  - (IN) BCM_COSQ_BW_*
  13034  * Returns:
  13035  *     BCM_E_XXX
  13036  */
  13037 int
  13038 bcm_tr3_cosq_gport_bandwidth_set(int unit, bcm_gport_t gport,
  13039                                 bcm_cos_queue_t cosq, uint32 kbits_sec_min,
  13040                                 uint32 kbits_sec_max, uint32 flags)
  13041 {
  13042     int i, start_cos, end_cos, local_port;
  13043     _bcm_tr3_cosq_node_t *node;
  13044     uint32 burst_min, burst_max;
  13045 
  13046     if (cosq <= -1) {
  13047         if (BCM_GPORT_IS_SET(gport)) {
  13048             BCM_IF_ERROR_RETURN
  13049                 (_bcm_tr3_cosq_node_get(unit, gport, 0, NULL, 
  13050                                         NULL, NULL, &node));
  13051             start_cos = 0;
  13052             end_cos = node->numq - 1;
  13053         } else {
  13054             start_cos = 0;
  13055             end_cos = _TR3_NUM_COS(unit) - 1;
  13056         }
  13057     } else {
  13058         start_cos = end_cos = cosq;
  13059     }
  13060     
  13061     BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_localport_resolve(unit, gport, &local_port));
  13062 
  13063     burst_min = (kbits_sec_min > 0) ?
  13064           _bcm_td_default_burst_size(unit, local_port, kbits_sec_min) : 0;
  13065 
  13066     burst_max = (kbits_sec_max > 0) ?
  13067           _bcm_td_default_burst_size(unit, local_port, kbits_sec_max) : 0;
  13068 
  13069     for (i = start_cos; i <= end_cos; i++) {
  13070         BCM_IF_ERROR_RETURN
  13071             (_bcm_tr3_cosq_bucket_set(unit, gport, i, kbits_sec_min,
  13072                          kbits_sec_max, burst_min, burst_max, flags));
  13073     }
  13074 
  13075     return BCM_E_NONE;
  13076 }
  13077 
  13078 /*
  13079  * Function:
  13080  *     bcm_tr3_cosq_gport_bandwidth_get
  13081  * Purpose:
  13082  *     Get COS queue bandwidth control configuration
  13083  * Parameters:
  13084  *     unit   - (IN) unit number
  13085  *     gport  - (IN) GPORT identifier
  13086  *     cosq   - (IN) COS queue to get, -1 for any COS queue
  13087  *     kbits_sec_min - (OUT) minimum bandwidth, kbits/sec
  13088  *     kbits_sec_max - (OUT) maximum bandwidth, kbits/sec
  13089  *     flags  - (OUT) BCM_COSQ_BW_*
  13090  * Returns:
  13091  *     BCM_E_XXX
  13092  */
  13093 int
  13094 bcm_tr3_cosq_gport_bandwidth_get(int unit, bcm_gport_t gport,
  13095                                 bcm_cos_queue_t cosq, uint32 *kbits_sec_min,
  13096                                 uint32 *kbits_sec_max, uint32 *flags)
  13097 {
  13098     uint32 kbits_sec_burst;
  13099 
  13100     if (cosq == -1) {
  13101         return BCM_E_PARAM;
  13102     }
  13103 
  13104     BCM_IF_ERROR_RETURN
  13105         (_bcm_tr3_cosq_bucket_get(unit, gport, cosq,
  13106                                  kbits_sec_min, kbits_sec_max,
  13107                                  &kbits_sec_burst, &kbits_sec_burst, flags));
  13108     return BCM_E_NONE;
  13109 }
  13110 
  13111 /*
  13112  * Function:
  13113  *     bcm_tr3_cosq_gport_bandwidth_burst_set
  13114  * Purpose:
  13115  *     Configure COS queue bandwidth burst setting
  13116  * Parameters:
  13117  *      unit        - (IN) unit number
  13118  *      gport       - (IN) GPORT identifier
  13119  *      cosq        - (IN) COS queue to configure, -1 for all COS queues
  13120  *      kbits_burst - (IN) maximum burst, kbits
  13121  * Returns:
  13122  *      BCM_E_XXX
  13123  */
  13124 int
  13125 bcm_tr3_cosq_gport_bandwidth_burst_set(int unit, bcm_gport_t gport,
  13126                                       bcm_cos_queue_t cosq,
  13127                                       uint32 kbits_burst_min,
  13128                                       uint32 kbits_burst_max)
  13129 {
  13130     int i, start_cos, end_cos;
  13131     uint32 kbits_sec_min, kbits_sec_max, kbits_sec_burst, flags;
  13132     _bcm_tr3_cosq_node_t *node;
  13133 
  13134     if (cosq < -1) {
  13135         return BCM_E_PARAM;
  13136     }
  13137 
  13138     if (cosq == -1) {
  13139         if (BCM_GPORT_IS_SET(gport)) {
  13140             BCM_IF_ERROR_RETURN
  13141                 (_bcm_tr3_cosq_node_get(unit, gport, 0, NULL, 
  13142                                         NULL, NULL, &node));
  13143             start_cos = 0;
  13144             end_cos = node->numq - 1;
  13145         } else {
  13146             start_cos = 0;
  13147             end_cos = _TR3_NUM_COS(unit) - 1;
  13148         }
  13149     } else {
  13150         start_cos = end_cos = cosq;
  13151     }
  13152 
  13153     for (i = start_cos; i <= end_cos; i++) {
  13154         BCM_IF_ERROR_RETURN
  13155             (_bcm_tr3_cosq_bucket_get(unit, gport, i, &kbits_sec_min,
  13156                                      &kbits_sec_max, &kbits_sec_burst,
  13157                                      &kbits_sec_burst, &flags));
  13158         BCM_IF_ERROR_RETURN
  13159             (_bcm_tr3_cosq_bucket_set(unit, gport, i, kbits_sec_min,
  13160                                      kbits_sec_max, kbits_burst_min, 
  13161                                      kbits_burst_max, flags));
  13162     }
  13163 
  13164     return BCM_E_NONE;
  13165 }
  13166 
  13167 /*
  13168  * Function:
  13169  *     bcm_tr3_cosq_gport_bandwidth_burst_get
  13170  * Purpose:
  13171  *     Get COS queue bandwidth burst setting
  13172  * Parameters:
  13173  *     unit        - (IN) unit number
  13174  *     gport       - (IN) GPORT identifier
  13175  *     cosq        - (IN) COS queue to get, -1 for any queue
  13176  *     kbits_burst - (OUT) maximum burst, kbits
  13177  * Returns:
  13178  *     BCM_E_XXX
  13179  */
  13180 int
  13181 bcm_tr3_cosq_gport_bandwidth_burst_get(int unit, bcm_gport_t gport,
  13182                                        bcm_cos_queue_t cosq,
  13183                                        uint32 *kbits_burst_min,
  13184                                        uint32 *kbits_burst_max)
  13185 {
  13186     uint32 kbits_sec_min, kbits_sec_max, flags;
  13187 
  13188     if (cosq < -1) {
  13189         return BCM_E_PARAM;
  13190     }
  13191 
  13192     BCM_IF_ERROR_RETURN
  13193         (_bcm_tr3_cosq_bucket_get(unit, gport, cosq == -1 ? 0 : cosq,
  13194                                  &kbits_sec_min, &kbits_sec_max, kbits_burst_min,
  13195                                  kbits_burst_max, &flags));
  13196     return BCM_E_NONE;
  13197 }
  13198 
  13199 /*
  13200  * Function:
  13201  *     bcm_tr3_cosq_gport_sched_set
  13202  * Purpose:
  13203  *     Configure COS queue scheduler setting
  13204  * Parameters:
  13205  *      unit   - (IN) unit number
  13206  *      gport  - (IN) GPORT identifier
  13207  *      cosq   - (IN) COS queue to configure, -1 for all COS queues
  13208  *      mode   - (IN) Scheduling mode, one of BCM_COSQ_xxx
  13209  *      weight - (IN) queue weight
  13210  * Returns:
  13211  *      BCM_E_XXX
  13212  */
  13213 int
  13214 bcm_tr3_cosq_gport_sched_set(int unit, bcm_gport_t gport,
  13215                             bcm_cos_queue_t cosq, int mode, int weight)
  13216 {
  13217     int rv, numq, i, count;
  13218 
  13219     if (cosq == -1) {
  13220         BCM_IF_ERROR_RETURN
  13221             (_bcm_tr3_cosq_index_resolve(unit, gport, cosq,
  13222                                         _BCM_TR3_COSQ_INDEX_STYLE_SCHEDULER,
  13223                                         NULL, NULL, &numq));
  13224         cosq = 0;
  13225     } else {
  13226         numq = 1;
  13227     }
  13228 
  13229     count = 0;
  13230     for (i = 0; i < numq; i++) {
  13231         rv = _bcm_tr3_cosq_sched_set(unit, gport, cosq + i, mode, weight, 1);
  13232         if (rv == BCM_E_NOT_FOUND) {
  13233             continue;
  13234         } else if (BCM_FAILURE(rv)) {
  13235             return rv;
  13236         } else {
  13237             count++;
  13238         }
  13239     }
  13240 
  13241     return count > 0 ? BCM_E_NONE : BCM_E_NOT_FOUND;
  13242 }
  13243 
  13244 /*
  13245  * Function:
  13246  *     bcm_tr3_cosq_gport_sched_get
  13247  * Purpose:
  13248  *     Get COS queue scheduler setting
  13249  * Parameters:
  13250  *     unit   - (IN) unit number
  13251  *     gport  - (IN) GPORT identifier
  13252  *     cosq   - (IN) COS queue to get, -1 for any queue
  13253  *     mode   - (OUT) Scheduling mode, one of BCM_COSQ_xxx
  13254  *     weight - (OUT) queue weight
  13255  * Returns:
  13256  *     BCM_E_XXX
  13257  */
  13258 int
  13259 bcm_tr3_cosq_gport_sched_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
  13260                             int *mode, int *weight)
  13261 {
  13262     int rv, numq, i;
  13263 
  13264     if (cosq == -1) {
  13265         BCM_IF_ERROR_RETURN
  13266             (_bcm_tr3_cosq_index_resolve(unit, gport, 0,
  13267                                         _BCM_TR3_COSQ_INDEX_STYLE_SCHEDULER,
  13268                                         NULL, NULL, &numq));
  13269         cosq = 0;
  13270     } else {
  13271         numq = 1;
  13272     }
  13273 
  13274     for (i = 0; i < numq; i++) {
  13275         rv = _bcm_tr3_cosq_sched_get(unit, gport, cosq + i, mode, weight);
  13276         if (rv == BCM_E_NONE) {
  13277             continue;
  13278         } else {
  13279             return rv;
  13280         }
  13281     }
  13282 
  13283     return BCM_E_NONE;
  13284 }
  13285 
  13286 /*
  13287  * Function:
  13288  *     bcm_tr3_cosq_gport_discard_set
  13289  * Purpose:
  13290  *     Configure port WRED setting
  13291  * Parameters:
  13292  *     unit    - (IN) unit number
  13293  *     port    - (IN) GPORT identifier
  13294  *     cosq    - (IN) COS queue to configure, -1 for all COS queues
  13295  *     discard - (IN) discard settings
  13296  * Returns:
  13297  *     BCM_E_XXX
  13298  */
  13299 int
  13300 bcm_tr3_cosq_gport_discard_set(int unit, bcm_gport_t gport,
  13301                                bcm_cos_queue_t cosq,
  13302                                bcm_cosq_gport_discard_t *discard)
  13303 {
  13304     int numq, i;
  13305     uint32 min_thresh, max_thresh;
  13306     int cell_size, cell_field_max, flags = 0;
  13307 
  13308     if (discard == NULL ||
  13309         discard->gain < 0 || discard->gain > 15 ||
  13310         discard->drop_probability < 0 || discard->drop_probability > 100) {
  13311         return BCM_E_PARAM;
  13312     }
  13313 
  13314     cell_size = _BCM_TR3_BYTES_PER_CELL;
  13315     cell_field_max = TR3_CELL_FIELD_MAX;
  13316 
  13317     min_thresh = discard->min_thresh;
  13318     max_thresh = discard->max_thresh;
  13319     if (discard->flags & BCM_COSQ_DISCARD_BYTES) {
  13320         /* Convert bytes to cells */
  13321         min_thresh += (cell_size - 1);
  13322         min_thresh /= cell_size;
  13323 
  13324         max_thresh += (cell_size - 1);
  13325         max_thresh /= cell_size;
  13326 
  13327         if ((min_thresh > cell_field_max) ||
  13328             (max_thresh > cell_field_max)) {
  13329             return BCM_E_PARAM;
  13330         }
  13331     } else {
  13332         /* Packet mode not supported */
  13333         return BCM_E_PARAM;
  13334     }
  13335 
  13336     if (cosq == -1) {
  13337         if (gport == -1) {
  13338             numq= 1;
  13339         } else {
  13340             numq= _TR3_NUM_COS(unit);
  13341         }
  13342         cosq = 0;
  13343         flags = BCM_COSQ_DISCARD_PORT;
  13344     }
  13345     else {
  13346        numq = 1;
  13347     }
  13348 
  13349     for (i = 0; i < numq; i++) {
  13350         BCM_IF_ERROR_RETURN
  13351             (_bcm_tr3_cosq_wred_set(unit, gport, cosq + i, discard->flags,
  13352                                    min_thresh, max_thresh,
  13353                                    discard->drop_probability, discard->gain,
  13354                                    FALSE, flags));
  13355     }
  13356 
  13357     return BCM_E_NONE;
  13358 }
  13359 
  13360 /*
  13361  * Function:
  13362  *     bcm_tr3_cosq_gport_discard_get
  13363  * Purpose:
  13364  *     Get port WRED setting
  13365  * Parameters:
  13366  *     unit    - (IN) unit number
  13367  *     port    - (IN) GPORT identifier
  13368  *     cosq    - (IN) COS queue to get, -1 for any queue
  13369  *     discard - (OUT) discard settings
  13370  * Returns:
  13371  *     BCM_E_XXX
  13372  */
  13373 int
  13374 bcm_tr3_cosq_gport_discard_get(int unit, bcm_gport_t gport,
  13375                               bcm_cos_queue_t cosq,
  13376                               bcm_cosq_gport_discard_t *discard)
  13377 {
  13378     uint32 min_thresh, max_thresh;
  13379 
  13380     if (discard == NULL) {
  13381         return BCM_E_PARAM;
  13382     }
  13383 
  13384     BCM_IF_ERROR_RETURN
  13385         (_bcm_tr3_cosq_wred_get(unit, gport, cosq == -1 ? 0 : cosq,
  13386                                &discard->flags, &min_thresh, &max_thresh,
  13387                                &discard->drop_probability, &discard->gain, 0));
  13388 
  13389     /* Convert number of cells to number of bytes */
  13390     discard->min_thresh = min_thresh * _BCM_TR3_BYTES_PER_CELL;
  13391     discard->max_thresh = max_thresh * _BCM_TR3_BYTES_PER_CELL;
  13392 
  13393     return BCM_E_NONE;
  13394 }
  13395 
  13396 int
  13397 _bcm_tr3_cosq_pfc_class_resolve(bcm_switch_control_t sctype, int *type,
  13398                                int *class)
  13399 {
  13400     switch (sctype) {
  13401     case bcmSwitchPFCClass7Queue:
  13402     case bcmSwitchPFCClass6Queue:
  13403     case bcmSwitchPFCClass5Queue:
  13404     case bcmSwitchPFCClass4Queue:
  13405     case bcmSwitchPFCClass3Queue:
  13406     case bcmSwitchPFCClass2Queue:
  13407     case bcmSwitchPFCClass1Queue:
  13408     case bcmSwitchPFCClass0Queue:
  13409         *type = _BCM_TR3_COSQ_TYPE_UCAST;
  13410         break;
  13411     case bcmSwitchPFCClass7McastQueue:
  13412     case bcmSwitchPFCClass6McastQueue:
  13413     case bcmSwitchPFCClass5McastQueue:
  13414     case bcmSwitchPFCClass4McastQueue:
  13415     case bcmSwitchPFCClass3McastQueue:
  13416     case bcmSwitchPFCClass2McastQueue:
  13417     case bcmSwitchPFCClass1McastQueue:
  13418     case bcmSwitchPFCClass0McastQueue:
  13419         *type = _BCM_TR3_COSQ_TYPE_MCAST;
  13420         break;
  13421     case bcmSwitchPFCClass7DestmodQueue:
  13422     case bcmSwitchPFCClass6DestmodQueue:
  13423     case bcmSwitchPFCClass5DestmodQueue:
  13424     case bcmSwitchPFCClass4DestmodQueue:
  13425     case bcmSwitchPFCClass3DestmodQueue:
  13426     case bcmSwitchPFCClass2DestmodQueue:
  13427     case bcmSwitchPFCClass1DestmodQueue:
  13428     case bcmSwitchPFCClass0DestmodQueue:
  13429         *type = _BCM_TR3_COSQ_TYPE_EXT_UCAST;
  13430         break;
  13431     default:
  13432         return BCM_E_PARAM;
  13433     }
  13434 
  13435     switch (sctype) {
  13436     case bcmSwitchPFCClass7Queue:
  13437     case bcmSwitchPFCClass7McastQueue:
  13438     case bcmSwitchPFCClass7DestmodQueue:
  13439         *class = 7;
  13440         break;
  13441     case bcmSwitchPFCClass6Queue:
  13442     case bcmSwitchPFCClass6McastQueue:
  13443     case bcmSwitchPFCClass6DestmodQueue:
  13444         *class = 6;
  13445         break;
  13446     case bcmSwitchPFCClass5Queue:
  13447     case bcmSwitchPFCClass5McastQueue:
  13448     case bcmSwitchPFCClass5DestmodQueue:
  13449         *class = 5;
  13450         break;
  13451     case bcmSwitchPFCClass4Queue:
  13452     case bcmSwitchPFCClass4McastQueue:
  13453     case bcmSwitchPFCClass4DestmodQueue:
  13454         *class = 4;
  13455         break;
  13456     case bcmSwitchPFCClass3Queue:
  13457     case bcmSwitchPFCClass3McastQueue:
  13458     case bcmSwitchPFCClass3DestmodQueue:
  13459         *class = 3;
  13460         break;
  13461     case bcmSwitchPFCClass2Queue:
  13462     case bcmSwitchPFCClass2McastQueue:
  13463     case bcmSwitchPFCClass2DestmodQueue:
  13464         *class = 2;
  13465         break;
  13466     case bcmSwitchPFCClass1Queue:
  13467     case bcmSwitchPFCClass1McastQueue:
  13468     case bcmSwitchPFCClass1DestmodQueue:
  13469         *class = 1;
  13470         break;
  13471     case bcmSwitchPFCClass0Queue:
  13472     case bcmSwitchPFCClass0McastQueue:
  13473     case bcmSwitchPFCClass0DestmodQueue:
  13474         *class = 0;
  13475         break;
  13476     /*
  13477      * COVERITY
  13478      *
  13479      * This default is unreachable but needed for some compiler. 
  13480      */ 
  13481     /* coverity[dead_error_begin] */
  13482     default:
  13483         return BCM_E_INTERNAL;
  13484     }
  13485     return BCM_E_NONE;
  13486 }
  13487 
  13488 int
  13489 bcm_tr3_cosq_port_pfc_op(int unit, bcm_port_t port,
  13490                         bcm_switch_control_t sctype, _bcm_cosq_op_t op,
  13491                         bcm_gport_t *gport, int gport_count)
  13492 {
  13493     _bcm_tr3_cosq_node_t *node;
  13494     bcm_port_t local_port, resolved_port;
  13495     int type, class = -1, id, index, hw_cosq, hw_cosq1;
  13496     uint32 profile_index, old_profile_index;
  13497     uint64 rval64[16], tmp, *rval64s[1], rval, index_map;
  13498     uint32 fval, cos_bmp, tmp32;
  13499     int hw_index, hw_index1;
  13500     _bcm_tr3_mmu_info_t *mmu_info;
  13501     _bcm_tr3_cosq_port_info_t *port_info;
  13502     soc_reg_t   reg;
  13503     int phy_port, mmu_port, lvl;
  13504     soc_info_t *si;
  13505     static const soc_reg_t llfc_cfgr[] = {
  13506         PORT_PFC_CFG0r, PORT_PFC_CFG1r
  13507     };
  13508 
  13509     if (gport_count < 0) {
  13510         return BCM_E_PARAM;
  13511     }
  13512     
  13513     BCM_IF_ERROR_RETURN
  13514         (_bcm_tr3_cosq_localport_resolve(unit, port, &local_port));
  13515 
  13516     if (IS_CPU_PORT(unit, local_port)) {
  13517         return BCM_E_PARAM;
  13518     }
  13519 
  13520     BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_pfc_class_resolve(sctype, &type, &class));
  13521 
  13522     si = &SOC_INFO(unit);
  13523     phy_port = si->port_l2p_mapping[local_port];
  13524     mmu_port = si->port_p2m_mapping[phy_port];
  13525 
  13526     mmu_info = _bcm_tr3_mmu_info[unit];
  13527     port_info = &mmu_info->port_info[local_port];
  13528 
  13529     cos_bmp = 0;
  13530     for (index = 0; index < gport_count; index++) {
  13531         hw_index = hw_index1 = -1;
  13532         hw_cosq = hw_cosq1 = -1;
  13533         if (BCM_GPORT_IS_SET(gport[index])) {
  13534             BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_node_get(unit, gport[index], 
  13535                                 0, NULL, &resolved_port, &id, &node));
  13536             
  13537             if (!((node->type == _BCM_TR3_NODE_UCAST) ||
  13538                   (node->type == _BCM_TR3_NODE_MCAST) ||
  13539                   (node->type == _BCM_TR3_NODE_SCHEDULER))) {
  13540                 return BCM_E_PARAM;
  13541             }
  13542 
  13543             hw_index = node->hw_index;
  13544             hw_cosq = node->hw_cosq;
  13545             lvl = node->level;
  13546         } else {
  13547             if (_bcm_tr3_cosq_port_has_ets(unit, local_port)) {
  13548                 hw_cosq = gport[index];
  13549                 node = &mmu_info->queue_node[port_info->uc_base + hw_cosq];
  13550                 if ((!node->in_use) || (node->attached_to_input == -1)) {
  13551                     return BCM_E_PARAM;
  13552                 }
  13553                 hw_index = node->hw_index;
  13554                 node = &mmu_info->mc_queue_node[port_info->mc_base + hw_cosq];
  13555                 if ((!node->in_use) || (node->attached_to_input == -1)) {
  13556                     return BCM_E_PARAM;
  13557                 }
  13558                 hw_index1 = node->hw_index;
  13559                 hw_cosq1 = hw_cosq + 8;
  13560                 lvl = SOC_TR3_NODE_LVL_L2;
  13561             } else {
  13562                 hw_cosq = gport[index];
  13563                 if (IS_TR3_HSP_PORT(unit, local_port)) {
  13564                     /* HSP ports use Level-0 scheduler */
  13565                     lvl = SOC_TR3_NODE_LVL_L0;
  13566                     BCM_IF_ERROR_RETURN(soc_tr3_hsp_sched_hw_index_get(unit, local_port,
  13567                             SOC_TR3_NODE_LVL_L0, 0, hw_cosq, &hw_index));
  13568                 } else {
  13569                     lvl = SOC_TR3_NODE_LVL_L1;
  13570                     BCM_IF_ERROR_RETURN(soc_tr3_sched_hw_index_get(unit, local_port,
  13571                             SOC_TR3_NODE_LVL_L1, hw_cosq, &hw_index));
  13572                 }
  13573             }
  13574         }
  13575         if ((hw_cosq < 0) || (hw_cosq >= _TR3_NUM_COS(unit))) {
  13576             return BCM_E_PARAM;
  13577         }
  13578         BCM_IF_ERROR_RETURN(
  13579             _bcm_tr3_map_fc_status_to_node(unit, mmu_port*4, hw_cosq,
  13580                          hw_index, ((op == _BCM_COSQ_OP_CLEAR) ? 0 : 1), lvl));
  13581         cos_bmp |= 1 << hw_cosq;
  13582         if (hw_cosq1 >= 0) {
  13583             BCM_IF_ERROR_RETURN(
  13584                 _bcm_tr3_map_fc_status_to_node(unit, mmu_port*4, hw_cosq1,
  13585                          hw_index1, ((op == _BCM_COSQ_OP_CLEAR) ? 0 : 1), lvl));
  13586             cos_bmp |= 1 << hw_cosq1;
  13587         }
  13588     }
  13589 
  13590     if (op == _BCM_COSQ_OP_CLEAR) {
  13591         cos_bmp = (1 << NUM_COS(unit)) - 1;
  13592         cos_bmp |= (cos_bmp << 8);
  13593     }
  13594 
  13595     reg = llfc_cfgr[mmu_port/32];
  13596     rval64s[0] = rval64;
  13597     BCM_IF_ERROR_RETURN(soc_reg64_get(unit, reg, 0, 0, &rval));
  13598     if (op == _BCM_COSQ_OP_SET || cos_bmp != 0) {
  13599         index_map = soc_reg64_field_get(unit, reg, rval, PROFILE_INDEXf);
  13600         COMPILER_64_SHR(index_map, ((mmu_port % 32) * 2));
  13601         COMPILER_64_TO_32_LO(tmp32, index_map);
  13602         old_profile_index = (tmp32 & 3)*16;
  13603         BCM_IF_ERROR_RETURN
  13604             (soc_profile_reg_get(unit, _bcm_tr3_llfc_profile[unit],
  13605                                  old_profile_index, 16, rval64s));
  13606         if (op == _BCM_COSQ_OP_SET) {
  13607             soc_reg64_field32_set(unit, PRIO2COS_PROFILEr, &rval64[class],
  13608                                   COS_BMPf, cos_bmp);
  13609         } else if (cos_bmp != 0) {
  13610             fval = soc_reg64_field32_get(unit, PRIO2COS_PROFILEr, rval64[class],
  13611                                          COS_BMPf);
  13612             if (op == _BCM_COSQ_OP_ADD) {
  13613                 fval |= cos_bmp;
  13614             } else { /* _BCM_COSQ_OP_DELETE */
  13615                 fval &= ~cos_bmp;
  13616             }
  13617             soc_reg64_field32_set(unit, PRIO2COS_PROFILEr, &rval64[class],
  13618                                   COS_BMPf, fval);
  13619         }
  13620         BCM_IF_ERROR_RETURN
  13621             (soc_profile_reg_add(unit, _bcm_tr3_llfc_profile[unit], rval64s,
  13622                                  16, &profile_index));
  13623 
  13624 
  13625         index_map = soc_reg64_field_get(unit, reg, rval, PROFILE_INDEXf);
  13626 
  13627         COMPILER_64_SET(tmp, 0, 3);
  13628         COMPILER_64_SHL(tmp, (mmu_port % 32) * 2);
  13629         COMPILER_64_NOT(tmp);
  13630         COMPILER_64_AND(index_map, tmp);
  13631         COMPILER_64_SET(tmp, 0, profile_index/16);
  13632         COMPILER_64_SHL(tmp, (mmu_port % 32) * 2);
  13633         COMPILER_64_OR(index_map, tmp);
  13634         
  13635         soc_reg64_field_set(unit, reg, &rval, PROFILE_INDEXf,
  13636                             index_map);
  13637 
  13638         BCM_IF_ERROR_RETURN
  13639             (soc_profile_reg_delete(unit, _bcm_tr3_llfc_profile[unit],
  13640                                     old_profile_index));
  13641     }
  13642 
  13643     BCM_IF_ERROR_RETURN(soc_reg64_set(unit, reg, 0, 0, rval));
  13644 
  13645     return BCM_E_NONE;
  13646 }
  13647 
  13648 int
  13649 bcm_tr3_cosq_port_pfc_get(int unit, bcm_port_t port,
  13650                          bcm_switch_control_t sctype,
  13651                          bcm_gport_t *gport, int gport_count,
  13652                          int *actual_gport_count)
  13653 {
  13654     _bcm_tr3_cosq_node_t *node;
  13655     bcm_port_t local_port;
  13656     int type = -1, class = -1, hw_cosq, count = 0, j, inv_mapped, hw_index;
  13657     uint32 profile_index;
  13658     uint64 rval64[16], *rval64s[1], rval, index_map;
  13659     uint32 tmp32, bmp;
  13660     _bcm_tr3_mmu_info_t *mmu_info;
  13661     int phy_port, mmu_port;
  13662     int eindex;
  13663     soc_info_t *si;
  13664     soc_reg_t   reg;
  13665     soc_mem_t   mem;
  13666     static const soc_reg_t llfc_cfgr[] = {
  13667         PORT_PFC_CFG0r, PORT_PFC_CFG1r
  13668     };
  13669     static const soc_field_t self[] = {
  13670         SEL0f, SEL1f, SEL2f, SEL3f
  13671     };
  13672     uint32 map_entry[SOC_MAX_MEM_WORDS];
  13673 
  13674     if (IS_CPU_PORT(unit, port)) {
  13675         return BCM_E_PORT;
  13676     }
  13677 
  13678     if (gport == NULL || gport_count <= 0 || actual_gport_count == NULL) {
  13679         return BCM_E_PARAM;
  13680     }
  13681 
  13682     BCM_IF_ERROR_RETURN
  13683         (_bcm_tr3_cosq_localport_resolve(unit, port, &local_port));
  13684 
  13685     BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_pfc_class_resolve(sctype, &type, &class));
  13686 
  13687     si = &SOC_INFO(unit);
  13688     mmu_info = _bcm_tr3_mmu_info[unit];
  13689     phy_port = si->port_l2p_mapping[local_port];
  13690     mmu_port = si->port_p2m_mapping[phy_port];
  13691 
  13692     rval64s[0] = rval64;
  13693     reg = llfc_cfgr[mmu_port/32];
  13694     BCM_IF_ERROR_RETURN(soc_reg64_get(unit, reg, 0, 0, &rval));
  13695 
  13696     index_map = soc_reg64_field_get(unit, reg, rval, PROFILE_INDEXf);
  13697     COMPILER_64_SHR(index_map, ((mmu_port % 32) * 2));
  13698     COMPILER_64_TO_32_LO(tmp32, index_map);
  13699     profile_index = (tmp32 & 3)*16;
  13700 
  13701     BCM_IF_ERROR_RETURN
  13702         (soc_profile_reg_get(unit, _bcm_tr3_llfc_profile[unit],
  13703                              profile_index, 16, rval64s));
  13704 
  13705     bmp = soc_reg64_field32_get(unit, PRIO2COS_PROFILEr, rval64[class],
  13706                                 COS_BMPf);
  13707     for (hw_cosq = 0; hw_cosq < 16; hw_cosq++) {
  13708         if (!(bmp & (1 << hw_cosq))) {
  13709             continue;
  13710         }
  13711         if (_bcm_tr3_cosq_port_has_ets(unit, local_port)) {
  13712             inv_mapped = 0;
  13713             for (j = _BCM_TR3_NUM_PORT_SCHEDULERS; 
  13714                  j < _BCM_TR3_NUM_TOTAL_SCHEDULERS; j++) {
  13715                 node = &mmu_info->sched_node[j];
  13716                 if ((!node->in_use) || (node->local_port != local_port) ||
  13717                     (node->hw_cosq != hw_cosq)) {
  13718                     continue;
  13719                 }
  13720                 
  13721                 hw_index = (node->hw_index / 16);
  13722                 eindex = (node->hw_index % 16)/4;
  13723                 if (node->level == SOC_TR3_NODE_LVL_L0) {
  13724                     mem = MMU_INTFI_FC_MAP_TBL0m;
  13725                 } else if (node->level == SOC_TR3_NODE_LVL_L1) {
  13726                     mem = MMU_INTFI_FC_MAP_TBL1m;
  13727                 } else {
  13728                     continue;
  13729                 }
  13730 
  13731                 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, 
  13732                         MEM_BLOCK_ALL, hw_index, &map_entry));
  13733                 
  13734                 if (soc_mem_field32_get(unit, mem, &map_entry, self[eindex])) {
  13735                     inv_mapped = 1;
  13736                     gport[count++] = node->gport;
  13737                     break;
  13738                 }
  13739             }
  13740 
  13741             for (j = 0; inv_mapped==0 && j < _BCM_TR3_NUM_L2_UC_LEAVES; j++) {
  13742                 node = &mmu_info->queue_node[j];
  13743                 if ((!node->in_use) || (node->local_port != local_port) ||
  13744                     (node->hw_cosq != hw_cosq)) {
  13745                     continue;
  13746                 }
  13747                 
  13748                 mem = MMU_INTFI_FC_MAP_TBL2m;
  13749                 hw_index = (node->hw_index / 16);
  13750                 eindex = (node->hw_index % 16)/4;
  13751                 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, 
  13752                         MEM_BLOCK_ALL, hw_index, &map_entry));
  13753 
  13754                 if (soc_mem_field32_get(unit, mem, &map_entry, self[eindex])) {
  13755                     gport[count++] = node->gport;
  13756                 }
  13757                 break;
  13758             }
  13759         } else {
  13760             gport[count++] = hw_cosq;
  13761         }
  13762         if (count == gport_count) {
  13763             break;
  13764         }
  13765     }
  13766 
  13767     if (count == 0) {
  13768         return BCM_E_NOT_FOUND;
  13769     }
  13770     *actual_gport_count = count;
  13771 
  13772     return BCM_E_NONE;
  13773 }
  13774 
  13775 /*
  13776  * Function:
  13777  *     _bcm_tr3_fc_map_gport_check
  13778  * Purpose:
  13779  *     Validate if a gport can be mapped to a port's PFC/FC status.
  13780  * Parameters:
  13781  *     unit             - (IN) unit number
  13782  *     port             - (IN) port number
  13783  *     gport            - (IN) gport that will be mapped
  13784  * Returns:
  13785  *     BCM_E_XXX
  13786  */
  13787 STATIC int
  13788 _bcm_tr3_fc_map_gport_check(int unit,
  13789     bcm_gport_t port,
  13790     bcm_gport_t gport)
  13791 {
  13792     bcm_port_t local_port = -1, resolved_port;
  13793     int hw_cosq;
  13794     _bcm_tr3_cosq_port_info_t *port_info;
  13795     _bcm_tr3_mmu_info_t *mmu_info;
  13796     _bcm_tr3_cosq_node_t *node;
  13797 
  13798     BCM_IF_ERROR_RETURN
  13799         (_bcm_tr3_cosq_localport_resolve(unit, port, &local_port));
  13800 
  13801     if (local_port < 0) {
  13802         return BCM_E_PORT;
  13803     }
  13804 
  13805     mmu_info = _bcm_tr3_mmu_info[unit];
  13806     port_info = &mmu_info->port_info[local_port];
  13807     
  13808     hw_cosq = -1;
  13809     if (BCM_GPORT_IS_SET(gport)) {
  13810         BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_node_get(unit, gport, 
  13811                             0, NULL, &resolved_port, NULL, &node));
  13812         if (!((node->type == _BCM_TR3_NODE_UCAST) ||
  13813               (node->type == _BCM_TR3_NODE_MCAST) ||
  13814               (node->type == _BCM_TR3_NODE_SCHEDULER))) {
  13815             return BCM_E_PARAM;
  13816         }
  13817         if (resolved_port != local_port) {
  13818             return BCM_E_PARAM;
  13819         }
  13820         hw_cosq = node->hw_cosq;
  13821     } else {
  13822         hw_cosq = gport;
  13823         if (_bcm_tr3_cosq_port_has_ets(unit, local_port)) {
  13824             node = &mmu_info->queue_node[port_info->uc_base + hw_cosq];
  13825             if ((!node->in_use) || (node->attached_to_input == -1)) {
  13826                 return BCM_E_PARAM;
  13827             }
  13828             node = &mmu_info->mc_queue_node[port_info->mc_base + hw_cosq];
  13829             if ((!node->in_use) || (node->attached_to_input == -1)) {
  13830                 return BCM_E_PARAM;
  13831             }
  13832         }
  13833     }
  13834     if ((hw_cosq < 0) || (hw_cosq >= _TR3_NUM_INTERNAL_PRI)) {
  13835         return BCM_E_PARAM;
  13836     }
  13837 
  13838     return BCM_E_NONE;
  13839 }
  13840 
  13841 /*
  13842  * Function:
  13843  *     _bcm_tr3_pfc_class_mapping_check
  13844  * Purpose:
  13845  *     Validate param of bcm_cosq_pfc_class_mapping_t.
  13846  * Parameters:
  13847  *     unit             - (IN) unit number
  13848  *     port             - (IN) port number
  13849  *     array_count      - (IN) count of mapping array
  13850  *     mapping_array    - (IN) mapping array list
  13851  * Returns:
  13852  *     BCM_E_XXX
  13853  */
  13854 STATIC int
  13855 _bcm_tr3_pfc_class_mapping_check(int unit,
  13856     bcm_gport_t port,
  13857     int array_count,
  13858     bcm_cosq_pfc_class_mapping_t *mapping_array)
  13859 {
  13860     int count, index, cur_class;
  13861     bcm_gport_t cur_gport = 0;
  13862 
  13863     if (mapping_array == NULL) {
  13864         return BCM_E_PARAM;
  13865     }
  13866     
  13867     for (count = 0; count < array_count; count++) {
  13868         cur_class = mapping_array[count].class_id;
  13869         if ((cur_class < 0) || (cur_class >= _BCM_TR3_NUM_PFC_CLASS)) {
  13870             return BCM_E_PARAM;
  13871         }
  13872         
  13873         for (index = 0; index < BCM_COSQ_PFC_GPORT_COUNT; index++) {
  13874             cur_gport = mapping_array[count].gport_list[index];
  13875             if (cur_gport == BCM_GPORT_INVALID) {
  13876                 break;
  13877             }
  13878             BCM_IF_ERROR_RETURN(_bcm_tr3_fc_map_gport_check(unit,
  13879                                                             port, cur_gport));
  13880         }
  13881     }
  13882 
  13883     return BCM_E_NONE;
  13884 }
  13885 
  13886 /*
  13887  * Function:
  13888  *     _bcm_tr3_clear_fc_status_to_node
  13889  * Purpose:
  13890  *     Clear MMU_INTFI_PIPE_FC_MAP_TBL setting of a port.
  13891  * Parameters:
  13892  *     unit       - (IN) unit number
  13893  *     port       - (IN) port number
  13894  * Returns:
  13895  *     BCM_E_XXX
  13896  */
  13897 STATIC int
  13898 _bcm_tr3_clear_fc_status_to_node(int unit, int port)
  13899 {
  13900     uint32 map_entry[SOC_MAX_MEM_WORDS], i_value, s_value;
  13901     static const soc_field_t self[] = {
  13902         SEL0f, SEL1f, SEL2f, SEL3f
  13903     };
  13904     static const soc_field_t indexf[] = {
  13905         INDEX0f, INDEX1f, INDEX2f, INDEX3f
  13906     };
  13907     static const soc_mem_t mem[] = {
  13908         MMU_INTFI_FC_MAP_TBL0m,
  13909         MMU_INTFI_FC_MAP_TBL1m,
  13910         MMU_INTFI_FC_MAP_TBL2m
  13911     };
  13912     int base, table, index, count, field;
  13913     int mmu_port, phy_port, update;
  13914     bcm_port_t local_port;
  13915     soc_info_t *si;
  13916 
  13917     BCM_IF_ERROR_RETURN
  13918         (_bcm_tr3_cosq_localport_resolve(unit, port, &local_port));
  13919 
  13920     si = &SOC_INFO(unit);
  13921     phy_port = si->port_l2p_mapping[local_port];
  13922     mmu_port = si->port_p2m_mapping[phy_port];
  13923 
  13924     base = mmu_port * 4;
  13925     for (table = 0; table < COUNTOF(mem); table++) {
  13926         count = soc_mem_index_count(unit, mem[table]);
  13927         for (index = 0; index < count; index++) {
  13928             update = 0;
  13929             SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem[table],
  13930                 MEM_BLOCK_ALL, index, &map_entry));
  13931             for (field = 0; field < COUNTOF(indexf); field++) {
  13932                 s_value = soc_mem_field32_get(unit, mem[table],
  13933                                               &map_entry, self[field]);
  13934                 i_value = soc_mem_field32_get(unit, mem[table],
  13935                                               &map_entry, indexf[field]);
  13936                 if (s_value && (i_value >= base) && (i_value < (base + 4))) {
  13937                     soc_mem_field32_set(unit, mem[table],
  13938                                         &map_entry, self[field], 0);
  13939                     soc_mem_field32_set(unit, mem[table],
  13940                                         &map_entry, indexf[field], 0);
  13941                     update = 1;
  13942                 }
  13943             }
  13944             if (update) {
  13945                 SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem[table],
  13946                     MEM_BLOCK_ALL, index, &map_entry));
  13947             }
  13948         }
  13949     }
  13950 
  13951     return BCM_E_NONE;
  13952 }
  13953 
  13954 /*
  13955  * Function:
  13956  *     _bcm_tr3_fc_status_map_gport
  13957  * Purpose:
  13958  *     Set mapping in FC_MAP_TBL for gport, and update cos_bmp with gport cosq.
  13959  * Parameters:
  13960  *     unit       - (IN) unit number
  13961  *     port       - (IN) port number
  13962  *     gport      - (IN) gport to be mapped
  13963  *     cos_map    - (OUT) hw_cosq of gport
  13964  * Returns:
  13965  *     BCM_E_XXX
  13966  * Note:
  13967  *     This function assumes gport has been validated by
  13968  *     "_bcm_tr3_fc_map_gport_check".
  13969  */
  13970 STATIC int
  13971 _bcm_tr3_fc_status_map_gport(int unit, int port, 
  13972                 bcm_gport_t gport, uint32 *cos_bmp)
  13973 {
  13974     int hw_index, hw_index1;
  13975     int hw_cosq, hw_cosq1;
  13976     int id, lvl;
  13977     int mmu_port, phy_port;
  13978     bcm_port_t local_port, resolved_port;
  13979     _bcm_tr3_cosq_node_t *node;
  13980     _bcm_tr3_cosq_port_info_t *port_info;
  13981     soc_info_t *si;
  13982     _bcm_tr3_mmu_info_t *mmu_info;
  13983 
  13984     BCM_IF_ERROR_RETURN
  13985         (_bcm_tr3_cosq_localport_resolve(unit, port, &local_port));
  13986 
  13987     si = &SOC_INFO(unit);
  13988     phy_port = si->port_l2p_mapping[local_port];
  13989     mmu_port = si->port_p2m_mapping[phy_port];
  13990 
  13991     mmu_info = _bcm_tr3_mmu_info[unit];
  13992     port_info = &mmu_info->port_info[local_port];
  13993     
  13994     hw_index = hw_index1 = -1;
  13995     hw_cosq = hw_cosq1 = -1;
  13996     if (BCM_GPORT_IS_SET(gport)) {
  13997         BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_node_get(unit, gport, 
  13998                             0, NULL, &resolved_port, &id, &node));
  13999         hw_index = node->hw_index;
  14000         hw_cosq = node->hw_cosq;
  14001         lvl = node->level;
  14002     } else {
  14003         if (_bcm_tr3_cosq_port_has_ets(unit, local_port)) {
  14004             hw_cosq = gport;
  14005             node = &mmu_info->queue_node[port_info->uc_base + hw_cosq];
  14006             hw_index = node->hw_index;
  14007             
  14008             node = &mmu_info->mc_queue_node[port_info->mc_base + hw_cosq];
  14009             hw_index1 = node->hw_index;
  14010             hw_cosq1 = hw_cosq;
  14011             lvl = SOC_TR3_NODE_LVL_L2;
  14012         } else {
  14013             lvl = SOC_TR3_NODE_LVL_L1;
  14014             /* gport[] represnts the physical Cos value */
  14015             hw_cosq = gport;
  14016             BCM_IF_ERROR_RETURN(soc_tr3_sched_hw_index_get(unit, local_port, 
  14017             SOC_TR3_NODE_LVL_L1, hw_cosq, &hw_index));
  14018         }
  14019     }
  14020 
  14021     BCM_IF_ERROR_RETURN(
  14022         _bcm_tr3_map_fc_status_to_node(unit, mmu_port*4, hw_cosq,
  14023                                        hw_index, 1, lvl));
  14024     if (cos_bmp != NULL) {
  14025         *cos_bmp |= 1 << hw_cosq;
  14026     }
  14027     
  14028     if (hw_cosq1 >= 0) {
  14029         BCM_IF_ERROR_RETURN(
  14030             _bcm_tr3_map_fc_status_to_node(unit, mmu_port*4, hw_cosq1,
  14031                                         hw_index1, 1, lvl));
  14032         if (cos_bmp != NULL) {
  14033             *cos_bmp |= 1 << hw_cosq1;
  14034         }
  14035     }
  14036 
  14037     return BCM_E_NONE;
  14038 }
  14039 
  14040 /*
  14041  * Function:
  14042  *     _bcm_tr3_port_pfc_profile_set
  14043  * Purpose:
  14044  *     Set PFC mapping profile for port. Updates PRIO2COS_PROFILE & PORT_PFC_CFG.
  14045  * Parameters:
  14046  *     unit       - (IN) unit number
  14047  *     port       - (IN) port number
  14048  *     op         - (IN) operation type
  14049  *     entry_cnt  - (IN) count of bmp 
  14050  *     pfc_class  - (IN) class list
  14051  *     cos_bmp    - (IN) bmp list
  14052  * Returns:
  14053  *     BCM_E_XXX
  14054  */
  14055 STATIC int
  14056 _bcm_tr3_port_pfc_profile_set(int unit, int port, _bcm_cosq_op_t op,
  14057                               int entry_cnt, int *pfc_class, uint32 *cos_bmp)
  14058 {
  14059     soc_reg_t   reg;
  14060     bcm_port_t local_port;
  14061     int rv, entry, cur_class;
  14062     int mmu_port, phy_port;
  14063     uint32 profile_index, old_profile_index;
  14064     uint32 fval, tmp32, cur_bmp;
  14065     uint64 rval64[16], tmp, *rval64s[1], rval, index_map;
  14066     soc_info_t *si;
  14067     static const soc_reg_t llfc_cfgr[] = {
  14068         PORT_PFC_CFG0r, PORT_PFC_CFG1r
  14069     };
  14070 
  14071     if (pfc_class == NULL) {
  14072         return BCM_E_PARAM;
  14073     }
  14074     if (cos_bmp == NULL) {
  14075         return BCM_E_PARAM;
  14076     }
  14077     if ((entry_cnt < 0 ) || (entry_cnt > _BCM_TR3_NUM_PFC_CLASS)) {
  14078         return BCM_E_PARAM;
  14079     }
  14080     
  14081     BCM_IF_ERROR_RETURN(
  14082         _bcm_tr3_cosq_localport_resolve(unit, port, &local_port));
  14083 
  14084     si = &SOC_INFO(unit);
  14085     phy_port = si->port_l2p_mapping[local_port];
  14086     mmu_port = si->port_p2m_mapping[phy_port];
  14087     
  14088     reg = llfc_cfgr[mmu_port/32];
  14089     rval64s[0] = rval64;
  14090     BCM_IF_ERROR_RETURN(soc_reg64_get(unit, reg, 0, 0, &rval));
  14091     
  14092     index_map = soc_reg64_field_get(unit, reg, rval, PROFILE_INDEXf);
  14093     COMPILER_64_SHR(index_map, ((mmu_port % 32) * 2));
  14094     COMPILER_64_TO_32_LO(tmp32, index_map);
  14095     old_profile_index = (tmp32 & 3)*16;
  14096     BCM_IF_ERROR_RETURN
  14097         (soc_profile_reg_get(unit, _bcm_tr3_llfc_profile[unit],
  14098                              old_profile_index, 16, rval64s));
  14099 
  14100     for (entry = 0; entry < entry_cnt; entry++) {
  14101         cur_class = pfc_class[entry];
  14102         cur_bmp = cos_bmp[entry];
  14103         if (op == _BCM_COSQ_OP_SET) {
  14104             soc_reg64_field32_set(unit, PRIO2COS_PROFILEr, &rval64[cur_class],
  14105                                   COS_BMPf, cur_bmp);
  14106         } else {
  14107             if (cur_bmp != 0) {
  14108                 fval = soc_reg64_field32_get(unit, PRIO2COS_PROFILEr,
  14109                                              rval64[cur_class], COS_BMPf);
  14110                 if (op == _BCM_COSQ_OP_ADD) {
  14111                     fval |= cur_bmp;
  14112                 } else { /* _BCM_COSQ_OP_DELETE */
  14113                     fval &= ~cur_bmp;
  14114                 }
  14115                 soc_reg64_field32_set(unit, PRIO2COS_PROFILEr,
  14116                                       &rval64[cur_class], COS_BMPf, fval);
  14117             }
  14118         }
  14119     }
  14120     
  14121     BCM_IF_ERROR_RETURN
  14122         (soc_profile_reg_delete(unit, _bcm_tr3_llfc_profile[unit],
  14123                                 old_profile_index));
  14124 
  14125     rv = soc_profile_reg_add(unit, _bcm_tr3_llfc_profile[unit], rval64s,
  14126                              16, &profile_index);
  14127     if (SOC_FAILURE(rv)) {
  14128         BCM_IF_ERROR_RETURN
  14129             (soc_profile_reg_reference(unit, _bcm_tr3_llfc_profile[unit],
  14130                                        old_profile_index, 16));
  14131         return rv;
  14132     }
  14133 
  14134 
  14135     index_map = soc_reg64_field_get(unit, reg, rval, PROFILE_INDEXf);
  14136 
  14137     COMPILER_64_SET(tmp, 0, 3);
  14138     COMPILER_64_SHL(tmp, (mmu_port % 32) * 2);
  14139     COMPILER_64_NOT(tmp);
  14140     COMPILER_64_AND(index_map, tmp);
  14141     COMPILER_64_SET(tmp, 0, profile_index/16);
  14142     COMPILER_64_SHL(tmp, (mmu_port % 32) * 2);
  14143     COMPILER_64_OR(index_map, tmp);
  14144     
  14145     soc_reg64_field_set(unit, reg, &rval, PROFILE_INDEXf,
  14146                         index_map);
  14147 
  14148     BCM_IF_ERROR_RETURN(soc_reg64_set(unit, reg, 0, 0, rval));
  14149 
  14150     return BCM_E_NONE;
  14151 }
  14152 
  14153 /*
  14154  * Function:
  14155  *     bcm_tr3_cosq_pfc_class_mapping_set
  14156  * Purpose:
  14157  *     Set PFC mapping for port. PFC class is mapped to cosq or scheduler node gports.
  14158  * Parameters:
  14159  *     unit             - (IN) unit number
  14160  *     port             - (IN) port number
  14161  *     array_count      - (IN) count of mapping
  14162  *     mapping_array    - (IN) mappings 
  14163  * Returns:
  14164  *     BCM_E_XXX
  14165  */
  14166 int
  14167 bcm_tr3_cosq_pfc_class_mapping_set(int unit,
  14168     bcm_gport_t port,
  14169     int array_count,
  14170     bcm_cosq_pfc_class_mapping_t *mapping_array)
  14171 {
  14172     int index, count;
  14173     int cur_class = 0, pfc_class[_BCM_TR3_NUM_PFC_CLASS];
  14174     bcm_gport_t cur_gport = 0;
  14175     uint32 cos_bmp[_BCM_TR3_NUM_PFC_CLASS];
  14176 
  14177 
  14178     if ((array_count < 0) || (array_count > _BCM_TR3_NUM_PFC_CLASS)) {
  14179         return BCM_E_PARAM;
  14180     }
  14181     if (mapping_array == NULL) {
  14182         return BCM_E_PARAM;
  14183     }
  14184     BCM_IF_ERROR_RETURN(_bcm_tr3_pfc_class_mapping_check(unit, port,
  14185         array_count, mapping_array));
  14186 
  14187     (void) _bcm_tr3_clear_fc_status_to_node(unit, port);
  14188     sal_memset(cos_bmp, 0, sizeof(cos_bmp));
  14189     for (count = 0; count < array_count; count++) {
  14190         cur_class = mapping_array[count].class_id;
  14191         
  14192         for (index = 0; index < BCM_COSQ_PFC_GPORT_COUNT; index++) {
  14193             cur_gport = mapping_array[count].gport_list[index];
  14194             if (cur_gport == BCM_GPORT_INVALID) {
  14195                 break;
  14196             }
  14197             
  14198             BCM_IF_ERROR_RETURN(_bcm_tr3_fc_status_map_gport(unit, port, 
  14199                 cur_gport, &cos_bmp[cur_class]));
  14200         }
  14201     }
  14202 
  14203     for (index = 0; index < _BCM_TR3_NUM_PFC_CLASS; index++) {
  14204         pfc_class[index] = index;
  14205     }
  14206     BCM_IF_ERROR_RETURN(_bcm_tr3_port_pfc_profile_set(unit, port,
  14207         _BCM_COSQ_OP_SET, _BCM_TR3_NUM_PFC_CLASS, pfc_class, cos_bmp));
  14208     
  14209     return BCM_E_NONE;
  14210 }
  14211 
  14212 /*
  14213  * Function:
  14214  *     bcm_tr3_cosq_pfc_class_mapping_get
  14215  * Purpose:
  14216  *     Get PFC mapping for port.
  14217  *     Retrieves cosq or scheduler node gports
  14218  *     associated to PFC classes.
  14219  * Parameters:
  14220  *     unit             - (IN) unit number
  14221  *     port             - (IN) port number
  14222  *     array_max        - (IN) max retrieve count
  14223  *     mapping_array    - (OUT) mappings
  14224  *     array_count      - (OUT) retrieved mapping count
  14225  * Returns:
  14226  *     BCM_E_XXX
  14227  */
  14228 int
  14229 bcm_tr3_cosq_pfc_class_mapping_get(int unit,
  14230     bcm_gport_t port,
  14231     int array_max,
  14232     bcm_cosq_pfc_class_mapping_t *mapping_array,
  14233     int *array_count)
  14234 {
  14235     int rv = 0;
  14236     int cur_class = 0;
  14237     int actual_gport_count, class_count = 0;
  14238     bcm_switch_control_t sc[] = { bcmSwitchPFCClass0Queue,
  14239                                   bcmSwitchPFCClass1Queue,
  14240                                   bcmSwitchPFCClass2Queue,
  14241                                   bcmSwitchPFCClass3Queue,
  14242                                   bcmSwitchPFCClass4Queue,
  14243                                   bcmSwitchPFCClass5Queue,
  14244                                   bcmSwitchPFCClass6Queue,
  14245                                   bcmSwitchPFCClass7Queue
  14246                                 };
  14247 
  14248     if ((mapping_array == NULL) && (array_max > 0)) {
  14249         return BCM_E_PARAM;
  14250     }
  14251     if (array_count == NULL) {
  14252         return BCM_E_PARAM;
  14253     }
  14254 
  14255     for (cur_class = 0; cur_class < _BCM_TR3_NUM_PFC_CLASS; cur_class++) {
  14256         actual_gport_count = 0;
  14257         if (array_max > 0) {
  14258             rv = bcm_tr3_cosq_port_pfc_get(unit, port, sc[cur_class],
  14259                         mapping_array[class_count].gport_list,
  14260                         BCM_COSQ_PFC_GPORT_COUNT, &actual_gport_count);
  14261         } else {
  14262             rv = bcm_tr3_cosq_port_pfc_get(unit, port, sc[cur_class],
  14263                          NULL, -1, &actual_gport_count);
  14264         }
  14265         if (rv == BCM_E_NONE) {
  14266             if (array_max > 0) {
  14267                 mapping_array[class_count].class_id = cur_class;
  14268                 if (actual_gport_count < BCM_COSQ_PFC_GPORT_COUNT) {
  14269                     mapping_array[class_count].gport_list[actual_gport_count] = 
  14270                                                              BCM_GPORT_INVALID;
  14271                 }
  14272             }
  14273             class_count++;
  14274         } else if (rv != BCM_E_NOT_FOUND) {
  14275             return rv;
  14276         }
  14277 
  14278         if ((class_count == array_max) && (array_max > 0)) {
  14279             break;
  14280         }
  14281     }
  14282 
  14283     *array_count = class_count;
  14284     if (class_count == 0) {
  14285         return BCM_E_NOT_FOUND;
  14286     }
  14287     
  14288     return BCM_E_NONE;
  14289 }
  14290 
  14291 int
  14292 bcm_tr3_cosq_drop_status_enable_set(int unit, bcm_port_t port, int enable)
  14293 {
  14294     _bcm_tr3_mmu_info_t *mmu_info;
  14295     soc_info_t *si;
  14296     int base, count, idx;
  14297     uint32 rval;
  14298     _bcm_tr3_cosq_node_t *node;
  14299 
  14300     if ((mmu_info = _bcm_tr3_mmu_info[unit]) == NULL) {
  14301         return BCM_E_INIT;
  14302     }
  14303 
  14304     si = &SOC_INFO(unit);
  14305 
  14306     count = si->port_num_cosq[port];
  14307     for (idx = 0; idx < count; idx++) {
  14308         BCM_IF_ERROR_RETURN
  14309             (READ_OP_QUEUE_CONFIG1_CELLr(unit, port, idx, &rval));
  14310         soc_reg_field_set(unit,OP_QUEUE_CONFIG1_CELLr, &rval,
  14311                           Q_E2E_DS_EN_CELLf, enable ? 1 : 0);
  14312         BCM_IF_ERROR_RETURN
  14313             (WRITE_OP_QUEUE_CONFIG1_CELLr(unit, port, idx, rval));
  14314     }
  14315 
  14316     count = si->port_num_uc_cosq[port];
  14317     base = si->port_uc_cosq_base[port];
  14318     for (idx = 0; idx < count; idx++) {
  14319         BCM_IF_ERROR_RETURN
  14320             (soc_mem_field32_modify(unit, MMU_THDO_Q_TO_QGRP_MAPm, 
  14321                                     base + idx, Q_E2E_DS_EN_CELLf, !!enable));
  14322     }
  14323 
  14324     for (idx = mmu_info->num_base_queues; 
  14325                                 idx < _BCM_TR3_NUM_L2_UC_LEAVES; idx++) {
  14326         node = &mmu_info->queue_node[idx];
  14327         if ((node->in_use == FALSE) || (node->local_port != port)) {
  14328             BCM_IF_ERROR_RETURN
  14329                 (soc_mem_field32_modify(unit, MMU_THDO_Q_TO_QGRP_MAPm, 
  14330                                         idx, Q_E2E_DS_EN_CELLf, !!enable));
  14331         }
  14332     }
  14333 
  14334     BCM_IF_ERROR_RETURN(READ_OP_THR_CONFIGr(unit, &rval));
  14335     soc_reg_field_set(unit, OP_THR_CONFIGr, &rval, EARLY_E2E_SELECTf,
  14336                       enable ? 1 : 0);
  14337     BCM_IF_ERROR_RETURN(WRITE_OP_THR_CONFIGr(unit, rval));
  14338 
  14339     return BCM_E_NONE;
  14340 }
  14341 
  14342 
  14343 
  14344 int bcm_tr3_cosq_bst_profile_set(int unit, 
  14345                                  bcm_gport_t port, 
  14346                                  bcm_cos_queue_t cosq, 
  14347                                  bcm_bst_stat_id_t bid,
  14348                                  bcm_cosq_bst_profile_t *profile)
  14349 {
  14350     BCM_IF_ERROR_RETURN(_bcm_bst_cmn_profile_set
  14351         (unit, port, cosq, BCM_BST_DUP_XPE, bid, profile));
  14352     return BCM_E_NONE;
  14353 }
  14354 
  14355 int bcm_tr3_cosq_bst_profile_get(int unit, 
  14356                                  bcm_gport_t port, 
  14357                                  bcm_cos_queue_t cosq, 
  14358                                  bcm_bst_stat_id_t bid,
  14359                                  bcm_cosq_bst_profile_t *profile)
  14360 {
  14361     BCM_IF_ERROR_RETURN(_bcm_bst_cmn_profile_get
  14362         (unit, port, cosq, BCM_BST_DUP_XPE, bid, profile));
  14363     return BCM_E_NONE;
  14364 }
  14365 
  14366 int bcm_tr3_cosq_bst_stat_get(int unit, 
  14367                               bcm_gport_t port, 
  14368                               bcm_cos_queue_t cosq, 
  14369                               bcm_bst_stat_id_t bid,
  14370                               uint32 options,
  14371                               uint64 *value)
  14372 {
  14373     return _bcm_bst_cmn_stat_get(unit, port, cosq, -1, bid, options, value);
  14374 }
  14375 
  14376 int bcm_tr3_cosq_bst_stat_multi_get(int unit,
  14377                                 bcm_gport_t port,
  14378                                 bcm_cos_queue_t cosq,
  14379                                 uint32 options,
  14380                                 int max_values,
  14381                                 bcm_bst_stat_id_t *id_list,
  14382                                 uint64 *values)
  14383 {
  14384     return _bcm_bst_cmn_stat_multi_get(unit, port, cosq, options, max_values, 
  14385                                     id_list, values);
  14386 }
  14387 
  14388 int bcm_tr3_cosq_bst_stat_clear(int unit, 
  14389                             bcm_gport_t port, 
  14390                             bcm_cos_queue_t cosq, 
  14391                             bcm_bst_stat_id_t bid)
  14392 {
  14393     return _bcm_bst_cmn_stat_clear(unit, port, cosq, bid);
  14394 }
  14395 
  14396 int bcm_tr3_cosq_bst_stat_sync(int unit, bcm_bst_stat_id_t bid)
  14397 {
  14398     return _bcm_bst_cmn_stat_sync(unit, bid);
  14399 }
  14400 
  14401 /*
  14402  * Function:
  14403  *      bcm_tr3_cosq_field_classifier_id_create
  14404  * Purpose:
  14405  *      Create an endpoint.
  14406  * Parameters: 
  14407  *      unit          - (IN) Unit number.
  14408  *      classifier    - (IN) Classifier attributes
  14409  *      classifier_id - (OUT) Classifier ID
  14410  * Returns:
  14411  *      BCM_E_xxx
  14412  */     
  14413 int
  14414 bcm_tr3_cosq_field_classifier_id_create(
  14415     int unit,
  14416     bcm_cosq_classifier_t *classifier,
  14417     int *classifier_id)
  14418 {
  14419     int rv;
  14420     int ref_count = 0;
  14421     int ent_per_set = 16;
  14422     int i;
  14423 
  14424     if (NULL == classifier || NULL == classifier_id) {
  14425         return BCM_E_PARAM;
  14426     }
  14427 
  14428     for (i = 0; i < SOC_MEM_SIZE(unit, IFP_COS_MAPm);) {
  14429         rv = soc_profile_mem_ref_count_get
  14430                 (unit, _bcm_tr3_ifp_cos_map_profile[unit], i, &ref_count);
  14431         if (SOC_E_NONE != rv) {
  14432             return (rv);
  14433         }
  14434         if (0 == ref_count) {
  14435             break;
  14436         }
  14437         i = i + ent_per_set;
  14438     }
  14439 
  14440     if (i >= SOC_MEM_SIZE(unit, IFP_COS_MAPm) && ref_count != 0) {
  14441         *classifier_id = 0;
  14442         return (BCM_E_RESOURCE);
  14443     }
  14444 
  14445     _BCM_COSQ_CLASSIFIER_FIELD_SET(*classifier_id, (i / ent_per_set));
  14446 
  14447     return (BCM_E_NONE);
  14448 }
  14449 
  14450 /*
  14451  * Function:
  14452  *      bcm_tr3_cosq_field_classifier_get
  14453  * Purpose:
  14454  *      Get classifier type information.
  14455  * Parameters:
  14456  *      unit          - (IN) Unit number.
  14457  *      classifier_id - (IN) Classifier ID
  14458  *      classifier    - (OUT) Classifier info
  14459  * Returns:
  14460  *      BCM_E_xxx
  14461  */
  14462 int
  14463 bcm_tr3_cosq_field_classifier_get(
  14464     int unit,
  14465     int classifier_id,
  14466     bcm_cosq_classifier_t *classifier)
  14467 {
  14468     sal_memset(classifier, 0, sizeof(bcm_cosq_classifier_t));
  14469 
  14470     if (_BCM_COSQ_CLASSIFIER_IS_FIELD(classifier_id)) {
  14471         classifier->flags |= BCM_COSQ_CLASSIFIER_FIELD;
  14472     }
  14473 
  14474     return BCM_E_NONE;
  14475 }
  14476 
  14477 /*
  14478  * Function:
  14479  *      bcm_tr3_cosq_service_classifier_id_create
  14480  * Purpose:
  14481  *      Create an endpoint.
  14482  * Parameters: 
  14483  *      unit          - (IN) Unit number.
  14484  *      classifier    - (IN) Classifier attributes
  14485  *      classifier_id - (OUT) Classifier ID
  14486  * Returns:
  14487  *      BCM_E_xxx
  14488  */     
  14489 int
  14490 bcm_tr3_cosq_service_classifier_id_create(
  14491     int unit,
  14492     bcm_cosq_classifier_t *classifier,
  14493     int *classifier_id)
  14494 {
  14495     if (NULL == classifier || NULL == classifier_id) {
  14496         return BCM_E_PARAM;
  14497     }
  14498     /* XXX check classifier->vlan for valid vlan/vfi */
  14499     _BCM_COSQ_CLASSIFIER_SERVICE_SET(*classifier_id,classifier->vlan);
  14500     return BCM_E_NONE;
  14501 }
  14502 
  14503 /*
  14504  * Function:
  14505  *      bcm_tr3_cosq_service_classifier_id_destroy
  14506  * Purpose:
  14507  *      free resource associated with this service classifier id.
  14508  * Parameters:
  14509  *      unit          - (IN) Unit number.
  14510  *      classifier_id - (IN) Classifier ID
  14511  * Returns:
  14512  *      BCM_E_xxx
  14513  */     
  14514 int
  14515 bcm_tr3_cosq_service_classifier_id_destroy(
  14516     int unit,
  14517     int classifier_id)
  14518 {
  14519     return BCM_E_NONE;
  14520 }
  14521 
  14522 /*
  14523  * Function:
  14524  *      bcm_tr3_cosq_field_classifier_map_set
  14525  * Purpose:
  14526  *      Set internal priority to ingress field processor CoS queue
  14527  *      override mapping.
  14528  * Parameters:
  14529  *      unit           - (IN) Unit number.
  14530  *      classifier_id  - (IN) Classifier ID
  14531  *      count          - (IN) Number of elements in priority_array and
  14532  *                            cosq_array
  14533  *      priority_array - (IN) Array of internal priorities
  14534  *      cosq_array     - (IN) Array of COS queues
  14535  * Returns:
  14536  *      BCM_E_xxx
  14537  */
  14538 int
  14539 bcm_tr3_cosq_field_classifier_map_set(int unit,
  14540                                       int classifier_id,
  14541                                       int count,
  14542                                       bcm_cos_t *priority_array,
  14543                                       bcm_cos_queue_t *cosq_array)
  14544 {
  14545     int rv;
  14546     int i, update = 0;
  14547     int max_entries = 16;
  14548     uint32 index;
  14549     void *entries[1], *entries_out[2];
  14550     ifp_cos_map_entry_t *ent_buf, *ent_buf_out;
  14551     int field_width;
  14552     int ref_count = 0;
  14553     /* Input parameter check. */
  14554     if (!_BCM_COSQ_CLASSIFIER_IS_FIELD(classifier_id)) {
  14555         return (BCM_E_PARAM);
  14556     }
  14557 
  14558     if (count > max_entries) {
  14559         return (BCM_E_PARAM);
  14560     }
  14561 
  14562     ent_buf = sal_alloc(sizeof(ifp_cos_map_entry_t) * max_entries,
  14563             "IFP_COS_MAP entry");
  14564     if (ent_buf == NULL) {
  14565         return (BCM_E_MEMORY);
  14566     }
  14567 
  14568     field_width = soc_mem_field_length(unit, IFP_COS_MAPm, IFP_COSf);
  14569     sal_memset(ent_buf, 0, sizeof(ifp_cos_map_entry_t) * max_entries);
  14570     entries[0] = ent_buf;
  14571 
  14572     for (i = 0; i < count; i++) {
  14573         if (priority_array[i] < max_entries) {
  14574             if (cosq_array[i] >= (1 << field_width)) {
  14575                 return BCM_E_PARAM;
  14576             }
  14577             soc_mem_field32_set(unit, IFP_COS_MAPm, &ent_buf[priority_array[i]],
  14578                     IFP_COSf, cosq_array[i]);
  14579         }
  14580     }
  14581     index = _BCM_COSQ_CLASSIFIER_FIELD_GET(classifier_id);
  14582     rv = soc_profile_mem_ref_count_get
  14583         (unit, _bcm_tr3_ifp_cos_map_profile[unit],
  14584          index * max_entries, &ref_count);
  14585     if (SOC_E_NONE != rv) {
  14586         sal_free(ent_buf);
  14587         return (rv);
  14588     }
  14589     /*
  14590      *  UPDATE:
  14591      *  1. if ref count is 1 only then update can be called for since it is called 
  14592      *     per port and cosq group. Cannot be updated for all the ports in one go
  14593      *  2. then get the pre-configured profile for the classifier id
  14594      *  3. If profile varies then call an delete and then add the new one 
  14595      */
  14596 
  14597     if (ref_count == 1) {
  14598         ent_buf_out = sal_alloc(sizeof(ifp_cos_map_entry_t) * max_entries,
  14599                 "IFP_COS_MAP entry");
  14600         if (ent_buf_out == NULL) {
  14601             sal_free(ent_buf);
  14602             return (BCM_E_MEMORY);
  14603         }
  14604         sal_memset(ent_buf_out, 0, sizeof(ifp_cos_map_entry_t) * max_entries);
  14605         entries_out[0] = ent_buf_out;
  14606 
  14607         rv = soc_profile_mem_get(unit, _bcm_tr3_ifp_cos_map_profile[unit],
  14608                 index * max_entries, max_entries, entries_out);
  14609         if (rv < 0) {
  14610             sal_free(ent_buf);
  14611             sal_free(ent_buf_out);
  14612             return rv;
  14613         }
  14614 
  14615         /* check if both the profiles are same */
  14616         for (i = 0; i < count; i++) {
  14617             if (cosq_array[i] != soc_mem_field32_get(unit, IFP_COS_MAPm,
  14618                         &ent_buf_out[priority_array[i]],
  14619                         IFP_COSf)) {
  14620                 update = 1;
  14621                 break;
  14622             }
  14623         }
  14624         sal_free(ent_buf_out);
  14625         if (update) {
  14626             rv = soc_profile_mem_delete(unit,
  14627                     _bcm_tr3_ifp_cos_map_profile[unit],
  14628                     index * max_entries);
  14629             if (rv < 0) {
  14630                 sal_free(ent_buf);
  14631                 return rv; 
  14632             }
  14633         }
  14634     }
  14635     rv = soc_profile_mem_add(unit, _bcm_tr3_ifp_cos_map_profile[unit],
  14636             entries, max_entries, &index);
  14637 
  14638     sal_free(ent_buf);
  14639     return (rv);
  14640 }
  14641 
  14642 /*
  14643  * Function:
  14644  *      bcm_tr3_cosq_field_classifier_map_get
  14645  * Purpose:
  14646  *      Get internal priority to ingress field processor CoS queue
  14647  *      override mapping information.
  14648  * Parameters:
  14649  *      unit           - (IN) Unit number.
  14650  *      classifier_id  - (IN) Classifier ID
  14651  *      array_max      - (IN) Size of priority_array and cosq_array
  14652  *      priority_array - (IN) Array of internal priorities
  14653  *      cosq_array     - (OUT) Array of COS queues
  14654  *      array_count    - (OUT) Size of cosq_array
  14655  * Returns:
  14656  *      BCM_E_xxx
  14657  */
  14658 int
  14659 bcm_tr3_cosq_field_classifier_map_get(int unit,
  14660                                       int classifier_id,
  14661                                       int array_max,
  14662                                       bcm_cos_t *priority_array,
  14663                                       bcm_cos_queue_t *cosq_array,
  14664                                       int *array_count)
  14665 {
  14666     int rv;
  14667     int i;
  14668     int ent_per_set = 16;
  14669     uint32 index;
  14670     void *entries[1];
  14671     ifp_cos_map_entry_t *ent_buf;
  14672 
  14673     /* Input parameter check. */
  14674     if (NULL == priority_array || NULL == cosq_array || NULL == array_count) {
  14675         return (BCM_E_PARAM);
  14676     }
  14677 
  14678     /* Allocate entry buffer. */
  14679     ent_buf = sal_alloc(sizeof(ifp_cos_map_entry_t) * ent_per_set,
  14680                         "IFP_COS_MAP entry");
  14681     if (ent_buf == NULL) {
  14682         return (BCM_E_MEMORY);
  14683     }
  14684     sal_memset(ent_buf, 0, sizeof(ifp_cos_map_entry_t) * ent_per_set);
  14685     entries[0] = ent_buf;
  14686 
  14687     /* Get profile table entry set base index. */
  14688     index = _BCM_COSQ_CLASSIFIER_FIELD_GET(classifier_id);
  14689 
  14690     /* Read out entries from profile table into allocated buffer. */
  14691     rv = soc_profile_mem_get(unit, _bcm_tr3_ifp_cos_map_profile[unit],
  14692                              index * ent_per_set, ent_per_set, entries);
  14693     if (!(rv == SOC_E_NOT_FOUND || rv == SOC_E_NONE)) {
  14694         sal_free(ent_buf);
  14695         return rv;
  14696     }
  14697 
  14698     *array_count = array_max > ent_per_set ? ent_per_set : array_max;
  14699 
  14700     /* Copy values into API OUT parameters. */
  14701     for (i = 0; i < *array_count; i++) {
  14702         if (priority_array[i] >= 16) {
  14703             sal_free(ent_buf);
  14704             return BCM_E_PARAM;
  14705         }
  14706         cosq_array[i] = soc_mem_field32_get(unit, IFP_COS_MAPm,
  14707                                             &ent_buf[priority_array[i]],
  14708                                             IFP_COSf);
  14709     }
  14710 
  14711     sal_free(ent_buf);
  14712     return (BCM_E_NONE);
  14713 }
  14714 
  14715 /*
  14716  * Function:
  14717  *      bcm_tr3_cosq_field_classifier_map_clear
  14718  * Purpose:
  14719  *      Delete an internal priority to ingress field processor CoS queue
  14720  *      override mapping profile set.
  14721  * Parameters:
  14722  *      unit          - (IN) Unit number.
  14723  *      classifier_id - (IN) Classifier ID
  14724  * Returns:
  14725  *      BCM_E_xxx
  14726  */
  14727 int
  14728 bcm_tr3_cosq_field_classifier_map_clear(int unit, int classifier_id)
  14729 {
  14730     int ent_per_set = 16;
  14731     uint32 index;
  14732 
  14733     /* Get profile table entry set base index. */
  14734     index = _BCM_COSQ_CLASSIFIER_FIELD_GET(classifier_id);
  14735 
  14736     /* Delete the profile entries set. */
  14737     BCM_IF_ERROR_RETURN
  14738         (soc_profile_mem_delete(unit,
  14739                                 _bcm_tr3_ifp_cos_map_profile[unit],
  14740                                 index * ent_per_set));
  14741     return (BCM_E_NONE);
  14742 }
  14743 
  14744 /*
  14745  * Function:
  14746  *      bcm_tr3_cosq_field_classifier_id_destroy
  14747  * Purpose:
  14748  *      Free resource associated with this field classifier id.
  14749  * Parameters:
  14750  *      unit          - (IN) Unit number.
  14751  *      classifier_id - (IN) Classifier ID
  14752  * Returns:
  14753  *      BCM_E_xxx
  14754  */
  14755 int
  14756 bcm_tr3_cosq_field_classifier_id_destroy(int unit, int classifier_id)
  14757 {
  14758     return (BCM_E_NONE);
  14759 }
  14760 
  14761 /*
  14762  * Function:
  14763  *      bcm_tr3_cosq_service_map_set
  14764  * Purpose:
  14765  *      Set the mapping from port, classifier, and multiple internal priorities
  14766  *      to multiple COS queues in a queue group.
  14767  * Parameters:
  14768  *      unit           - (IN) Unit number.
  14769  *      port           - (IN) local port ID
  14770  *      classifier_id  - (IN) Classifier ID
  14771  *      queue_group    - (IN) Base queue ID
  14772  *      array_count    - (IN) Number of elements in priority_array and
  14773  *                            cosq_array
  14774  *      priority_array - (IN) Array of internal priorities
  14775  *      cosq_array     - (IN) Array of COS queues
  14776  * Returns:
  14777  *      BCM_E_xxx
  14778  */
  14779 int
  14780 bcm_tr3_cosq_service_map_set(
  14781     int unit,
  14782     bcm_port_t port,
  14783     int classifier_id,
  14784     bcm_gport_t queue_group,
  14785     int array_count,
  14786     bcm_cos_t *priority_array,
  14787     bcm_cos_queue_t *cosq_array)
  14788 {
  14789     int rv = BCM_E_NONE;
  14790     int i;
  14791     int j;
  14792     service_queue_map_entry_t sqm;
  14793     service_port_map_entry_t *spm;
  14794     service_cos_map_entry_t *scm;
  14795     void *spm_entries[1];
  14796     void *scm_entries[1];
  14797     int local_port,local_id;
  14798     int spm_entries_per_set = 128;
  14799     int scm_entries_per_set = 16;
  14800     int q_offset = 0;
  14801     uint32 spm_idx;
  14802     uint32 scm_idx;
  14803     int spm_old_index = 0;
  14804     int scm_old_index = 0;
  14805     int qptr;
  14806     int valid_cosq;
  14807     int vid;
  14808     int valid_entry;
  14809     _bcm_tr3_cosq_node_t *node, *cur_node;
  14810 
  14811     if (!_BCM_COSQ_CLASSIFIER_IS_SERVICE(classifier_id)) {
  14812         return BCM_E_PARAM;
  14813     }
  14814 
  14815     /* index above 4K is for VFI */
  14816     vid = _BCM_COSQ_CLASSIFIER_SERVICE_GET(classifier_id);
  14817     
  14818     /* validate the vlan id */
  14819     if (vid < 0 || vid >= SOC_MEM_SIZE(unit, SERVICE_QUEUE_MAPm)) {
  14820         return BCM_E_PARAM;
  14821     }
  14822 
  14823     BCM_IF_ERROR_RETURN(_bcm_tr3_cosq_node_get(unit, queue_group, 0, 
  14824                NULL, &local_port, &local_id, &node));
  14825 
  14826     if (node->attached_to_input < 0) {
  14827         return BCM_E_PARAM;
  14828     }
  14829 
  14830     /* Reading the parent numq so that , it will not exceed 
  14831        max number of inputs of the parent can have*/
  14832     local_id = node->hw_index; 
  14833     /* validate the user parameters */
  14834     if (array_count > scm_entries_per_set) {
  14835         return BCM_E_PARAM;
  14836     }
  14837 
  14838     /* queues allocated for this queue_group should be contiguous.*/
  14839     /* check if user's queue number is valid */
  14840     for (i = 0; i < array_count; i++) {
  14841          valid_cosq= 0;
  14842          for (cur_node = node->parent->child;
  14843               cur_node != NULL;
  14844               cur_node = cur_node->sibling) {
  14845               if (cosq_array[i] == cur_node->attached_to_input) {
  14846                   valid_cosq = 1;
  14847                   break;
  14848               }
  14849          }
  14850          if (valid_cosq == 0) {
  14851              return BCM_E_PARAM;
  14852          }
  14853     }
  14854 
  14855     BCM_IF_ERROR_RETURN(
  14856         soc_mem_read(unit, SERVICE_QUEUE_MAPm, MEM_BLOCK_ANY, (int)vid, &sqm));
  14857    
  14858     valid_entry = soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, &sqm, VALIDf);
  14859     if (!valid_entry) {
  14860     /* We need the offset to be atleast 1 to find if we have valid offset
  14861      *   for a given port.So reducing the base by 1 
  14862      */ 
  14863         qptr = local_id - 1 ;
  14864 
  14865         sal_memset(&sqm,0, sizeof(service_queue_map_entry_t));
  14866     } else {
  14867         qptr = soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, &sqm, SERVICE_QUEUE_PTRf);
  14868         spm_old_index = soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, &sqm,
  14869                                SERVICE_PORT_PROFILE_INDEXf);
  14870         scm_old_index = soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, &sqm,
  14871                                SERVICE_COS_PROFILE_INDEXf);
  14872     }
  14873 
  14874     /* allocate space for service port map profile */
  14875     spm = sal_alloc(sizeof(service_port_map_entry_t) *
  14876                     spm_entries_per_set,
  14877               "SERVICE_PORT_MAP temp Mem");
  14878     if (spm == NULL) {
  14879         return BCM_E_MEMORY;
  14880     }
  14881     sal_memset(spm,0,
  14882           sizeof(service_port_map_entry_t) * spm_entries_per_set);
  14883     spm_entries[0] = spm;
  14884 
  14885     /* allocate space for service cos map profile */
  14886     scm = sal_alloc(sizeof(service_cos_map_entry_t) *
  14887                     scm_entries_per_set,
  14888               "SERVICE_COS_MAP temp Mem");
  14889     if (scm == NULL) {
  14890         sal_free(spm);
  14891         return BCM_E_MEMORY;
  14892     }
  14893     sal_memset(scm,0,
  14894           sizeof(service_cos_map_entry_t) * scm_entries_per_set);
  14895     scm_entries[0] = scm;
  14896 
  14897   if (soc_property_get(unit, spn_SERVICE_QUEUE_DYNAMIC_CONFIG, FALSE) == FALSE) {
  14898     /* spn_SERVICE_QUEUE_DYNAMIC_CONFIG=FALSE, Default behavior */
  14899 
  14900     if (valid_entry) {
  14901         /* only one service_cos_map profile is allowed per vlan/vfi. The first one is
  14902          * used. If the subsequent profile doesn't match the existing one, 
  14903          * Then update the old profile, the new map may be added by other port.
  14904          */
  14905         rv = soc_profile_mem_get(unit, _bcm_tr3_service_cos_map_profile[unit],
  14906                              scm_old_index * scm_entries_per_set,
  14907                              scm_entries_per_set, scm_entries);
  14908         if (rv != SOC_E_NONE) {
  14909             goto cleanup;
  14910         }
  14911         scm_idx = scm_old_index * scm_entries_per_set;
  14912 
  14913         for (i = 0; i < array_count; i++) {
  14914             if (cosq_array[i] != soc_mem_field32_get(unit,SERVICE_COS_MAPm,
  14915                                &scm[priority_array[i]],SERVICE_COS_OFFSETf) ) {
  14916                 if (priority_array[i] < scm_entries_per_set) {
  14917                     soc_mem_field32_set(unit, SERVICE_COS_MAPm,
  14918                                         &scm[priority_array[i]],
  14919                                         SERVICE_COS_OFFSETf, cosq_array[i]);
  14920                 }
  14921             }
  14922         }
  14923 
  14924         rv = soc_profile_mem_add(unit, _bcm_tr3_service_cos_map_profile[unit],
  14925                                  scm_entries, scm_entries_per_set, &scm_idx);
  14926         if (rv != SOC_E_NONE) {
  14927             goto cleanup;
  14928         }
  14929 
  14930         if (scm_old_index != scm_idx) {
  14931             rv = soc_profile_mem_delete(unit, _bcm_tr3_service_cos_map_profile[unit],
  14932                                         scm_old_index);
  14933             if (rv != SOC_E_NONE) {
  14934                 goto cleanup;
  14935             }
  14936         }
  14937         sal_free(scm);
  14938  
  14939         rv = soc_profile_mem_get(unit, _bcm_tr3_service_port_map_profile[unit],
  14940                              spm_old_index * spm_entries_per_set,
  14941                              spm_entries_per_set, spm_entries);
  14942         if (!(rv == SOC_E_NOT_FOUND || rv == SOC_E_NONE)) {
  14943             sal_free(spm);
  14944             return rv;
  14945         }
  14946 
  14947         if (local_id < qptr) {
  14948             /* need to adjust the offset in service_port_map.
  14949              * The new base -> qptr, offset added to qptr-local_id
  14950              */
  14951             for (i = 0; i < spm_entries_per_set; i++) {
  14952                  q_offset = soc_mem_field32_get(unit,SERVICE_PORT_MAPm,&spm[i],
  14953                             SERVICE_PORT_OFFSETf);
  14954                  if (q_offset) { 
  14955                      soc_mem_field32_set(unit, SERVICE_PORT_MAPm,&spm[i],
  14956                                 SERVICE_PORT_OFFSETf,
  14957                                 (qptr - (local_id - 1)) + q_offset);
  14958                  }
  14959             }
  14960 
  14961             /* We need the offset to be atleast 1 to find if we have valid offset
  14962              * for a given port.So reducing the base by 1 
  14963              */ 
  14964             qptr =  local_id - 1  ;  
  14965             q_offset = 1;  /* use the new base queue */
  14966         } else {
  14967             q_offset = local_id - qptr  ;
  14968             /* no change in queue base */
  14969         }
  14970     } else {  /* first time setup */
  14971         q_offset = 1;  /* use the new base queue */
  14972 
  14973         /* add the cos profile if first time */
  14974         for (i = 0; i < array_count; i++) {
  14975             if (priority_array[i] < scm_entries_per_set) {
  14976                 soc_mem_field32_set(unit,SERVICE_COS_MAPm,&scm[priority_array[i]],
  14977                         SERVICE_COS_OFFSETf,
  14978                         cosq_array[i]);
  14979             }
  14980         }
  14981         /* add a new profile */
  14982         rv = soc_profile_mem_add(unit, _bcm_tr3_service_cos_map_profile[unit],
  14983                              scm_entries, scm_entries_per_set,
  14984                              &scm_idx);
  14985         sal_free(scm);
  14986         if (rv != SOC_E_NONE) {
  14987             sal_free(spm);
  14988             return rv;
  14989         }
  14990     }
  14991 
  14992     soc_mem_field32_set(unit, SERVICE_PORT_MAPm,
  14993                       &spm[local_port], SERVICE_PORT_OFFSETf,
  14994                            q_offset);
  14995     /* add a new profile */
  14996     rv = soc_profile_mem_add(unit, _bcm_tr3_service_port_map_profile[unit], spm_entries,
  14997                              spm_entries_per_set,
  14998                              &spm_idx);
  14999 
  15000     if (rv != SOC_E_NONE) {
  15001         if (valid_entry) {
  15002             /* delete the old spm porfile */
  15003             BCM_IF_ERROR_RETURN
  15004                 (soc_profile_mem_delete(unit, _bcm_tr3_service_port_map_profile[unit],
  15005                                         spm_old_index * spm_entries_per_set));
  15006         }
  15007         rv = soc_profile_mem_add(unit, _bcm_tr3_service_port_map_profile[unit], spm_entries,
  15008                 spm_entries_per_set,
  15009                 &spm_idx);
  15010         if (rv != SOC_E_NONE) {
  15011             sal_free(spm);
  15012             return rv;
  15013         }
  15014         valid_entry = 0;
  15015     }
  15016     sal_free(spm);
  15017   } else {
  15018     /* spn_SERVICE_QUEUE_DYNAMIC_CONFIG=TRUE, Behavior with dynamic configuration */
  15019     if (valid_entry) {
  15020         /* only one service_cos_map profile is allowed per vlan/vfi. The first one is
  15021          * used. If the subsequent profile doesn't match the existing one,
  15022          * it is treated as error. Should always use the xxx_multi_set instead of xxx_set.
  15023          */
  15024         rv = soc_profile_mem_get(unit, _bcm_tr3_service_cos_map_profile[unit],
  15025                              scm_old_index * scm_entries_per_set,
  15026                              scm_entries_per_set, scm_entries);
  15027         if (rv != SOC_E_NONE) {
  15028             goto cleanup;
  15029         }
  15030         scm_idx = scm_old_index * scm_entries_per_set;
  15031 
  15032         for (i = 0; i < array_count; i++) {
  15033             if (cosq_array[i] != soc_mem_field32_get(unit,SERVICE_COS_MAPm,
  15034                                &scm[priority_array[i]],SERVICE_COS_OFFSETf) ) {
  15035                 rv = BCM_E_PARAM;
  15036                 goto cleanup;
  15037             }
  15038         }
  15039 
  15040         for (i = 0; i < scm_entries_per_set; i++) {
  15041             for (j = 0; j < array_count; j++) {
  15042                 if (i == priority_array[j]) {
  15043                     break;
  15044                 }
  15045             }
  15046             /* for priorities not in priority_array, the cosq should be 0 */
  15047             if (j == array_count) {
  15048                 if (soc_mem_field32_get(unit,SERVICE_COS_MAPm,&scm[i],SERVICE_COS_OFFSETf)) {
  15049                     rv = BCM_E_PARAM;
  15050                     goto cleanup;
  15051                 }
  15052             }
  15053         }
  15054         sal_free(scm);
  15055 
  15056         rv = soc_profile_mem_get(unit, _bcm_tr3_service_port_map_profile[unit],
  15057                              spm_old_index * spm_entries_per_set,
  15058                              spm_entries_per_set, spm_entries);
  15059         if (!(rv == SOC_E_NOT_FOUND || rv == SOC_E_NONE)) {
  15060             sal_free(spm);
  15061             return rv;
  15062         }
  15063 
  15064         q_offset = (local_id - qptr) & 0x3ff; /* Might wrap here */
  15065 #ifdef DEBUG_TR3_COSQ
  15066 	    soc_cm_print("DEBUG %s[%d] COMPUTED q_offset = %u;\r\n", FUNCTION_NAME(),
  15067 		            __LINE__, q_offset);
  15068 #endif
  15069     } else {  /* first time setup */
  15070         q_offset = 1;  /* use the new base queue */
  15071 
  15072 #ifdef DEBUG_TR3_COSQ
  15073         soc_cm_print("DEBUG %s[%d] NEW q_offset = %u;\r\n", FUNCTION_NAME(),
  15074                     __LINE__, q_offset);
  15075 #endif
  15076 
  15077         /* add the cos profile if first time */
  15078         for (i = 0; i < array_count; i++) {
  15079             if (priority_array[i] < scm_entries_per_set) {
  15080                 soc_mem_field32_set(unit,SERVICE_COS_MAPm,&scm[priority_array[i]],
  15081                         SERVICE_COS_OFFSETf,
  15082                         cosq_array[i]);
  15083             }
  15084         }
  15085         /* add a new profile */
  15086         rv = soc_profile_mem_add(unit, _bcm_tr3_service_cos_map_profile[unit],
  15087                              scm_entries, scm_entries_per_set,
  15088                              &scm_idx);
  15089         sal_free(scm);
  15090         if (rv != SOC_E_NONE) {
  15091             return rv;
  15092         }
  15093 
  15094 	    /* Initialize all port service offsets to ensure that they map to diffServe */
  15095         PBMP_PORT_ITER(unit, i) {
  15096 	        int diffserv = (SOC_INFO(unit).port_uc_cosq_base[i] - qptr) & 0x3ff;
  15097             if (SOC_INFO(unit).port_uc_cosq_base[i] >= 0) {
  15098                 soc_mem_field32_set(unit, SERVICE_PORT_MAPm,
  15099                                     &spm[i], SERVICE_PORT_OFFSETf,
  15100                                     diffserv);
  15101             }
  15102         }
  15103     }
  15104 
  15105     soc_mem_field32_set(unit, SERVICE_PORT_MAPm,
  15106                       &spm[local_port], SERVICE_PORT_OFFSETf,
  15107                            q_offset);
  15108     /* add a new profile */
  15109     rv = soc_profile_mem_add(unit, _bcm_tr3_service_port_map_profile[unit], spm_entries,
  15110                              spm_entries_per_set,
  15111                              &spm_idx);
  15112     sal_free(spm);
  15113     if (rv != SOC_E_NONE) {
  15114         return rv;
  15115     }
  15116   } /* spn_SERVICE_QUEUE_DYNAMIC_CONFIG */
  15117 
  15118     /* program the vlan base queue */
  15119     soc_mem_field32_set(unit, SERVICE_QUEUE_MAPm, &sqm,
  15120                            SERVICE_QUEUE_PTRf, qptr );
  15121 
  15122     /* set the SERVICE_COS_MAP profile index
  15123      * scm_idx: hardware table base index for the set */
  15124     soc_mem_field32_set(unit, SERVICE_QUEUE_MAPm, &sqm,
  15125                 SERVICE_COS_PROFILE_INDEXf,
  15126                 scm_idx/scm_entries_per_set);
  15127 
  15128     /* set the SERVICE_PORT_MAP profile index
  15129      * spm_idx: hardware table base index for the set */
  15130     soc_mem_field32_set(unit, SERVICE_QUEUE_MAPm, &sqm,
  15131                 SERVICE_PORT_PROFILE_INDEXf,
  15132                 spm_idx/spm_entries_per_set);
  15133 
  15134     if (!valid_entry) {   /* first time */
  15135         /* use port indexed and cos indexed for this base queue */
  15136         soc_mem_field32_set(unit, SERVICE_QUEUE_MAPm, &sqm,
  15137                            SERVICE_QUEUE_MODELf, 3);
  15138         soc_mem_field32_set(unit, SERVICE_QUEUE_MAPm, &sqm,
  15139                            VALIDf, 1);
  15140     }
  15141 
  15142     /* Write back updated buffer. */
  15143     rv = soc_mem_write(unit, SERVICE_QUEUE_MAPm, MEM_BLOCK_ALL,
  15144                        (int)vid, &sqm);
  15145 
  15146     if (valid_entry) {
  15147         /* delete the old spm porfile */
  15148         if ((spm_old_index * spm_entries_per_set) != spm_idx) {
  15149             rv = soc_profile_mem_delete(unit, _bcm_tr3_service_port_map_profile[unit],
  15150                              spm_old_index * spm_entries_per_set);
  15151         }
  15152     }
  15153     return BCM_E_NONE;
  15154 
  15155 cleanup:
  15156     sal_free(spm);
  15157     sal_free(scm);
  15158     return rv;
  15159 }
  15160 
  15161 /*
  15162  * Function:
  15163  *      bcm_tr3_cosq_service_classifier_get
  15164  * Purpose:
  15165  *      Get info about an endpoint.
  15166  * Parameters:
  15167  *      unit          - (IN) Unit number.
  15168  *      classifier_id - (IN) Classifier ID
  15169  *      classifier    - (OUT) Classifier info
  15170  * Returns:
  15171  *      BCM_E_xxx
  15172  */
  15173 int
  15174 bcm_tr3_cosq_service_classifier_get(
  15175     int unit,
  15176     int classifier_id,
  15177     bcm_cosq_classifier_t *classifier)
  15178 {
  15179     sal_memset(classifier, 0, sizeof(bcm_cosq_classifier_t));
  15180     classifier->flags = BCM_COSQ_CLASSIFIER_VLAN;
  15181     classifier->vlan  = _BCM_COSQ_CLASSIFIER_SERVICE_GET(classifier_id);
  15182     return BCM_E_NONE;
  15183 }
  15184 
  15185 /*
  15186  * Function:
  15187  *      bcm_tr3_cosq_service_map_get
  15188  * Purpose:
  15189  *      Get the mapping from port, classifier, and multiple internal priorities
  15190  *      to multiple COS queues in a queue group.
  15191  * Parameters:
  15192  *      unit           - (IN) Unit number.
  15193  *      port           - (IN) Local port ID
  15194  *      classifier_id  - (IN) Classifier ID
  15195  *      queue_group    - (OUT) Queue group
  15196  *      array_max      - (IN) Size of priority_array and cosq_array
  15197  *      priority_array - (IN) Array of internal priorities
  15198  *      cosq_array     - (OUT) Array of COS queues
  15199  *      array_count    - (OUT) Size of cosq_array
  15200  * Returns:
  15201  *      BCM_E_xxx
  15202  */
  15203 int
  15204 bcm_tr3_cosq_service_map_get(
  15205     int unit,
  15206     bcm_port_t port,
  15207     int classifier_id,
  15208     bcm_gport_t *queue_group,
  15209     int array_max,
  15210     bcm_cos_t *priority_array,
  15211     bcm_cos_queue_t *cosq_array,
  15212     int *array_count)
  15213 {
  15214     service_queue_map_entry_t sqm;
  15215     service_port_map_entry_t *spm;
  15216     service_cos_map_entry_t *scm;
  15217     void *spm_entries[1];
  15218     void *scm_entries[1];
  15219     int spm_entries_per_set = 128;
  15220     int scm_entries_per_set = 16;
  15221     int q_offset;
  15222     int spm_index;
  15223     int scm_index;
  15224     int qptr;
  15225     int vid;
  15226     int valid_entry;
  15227     int rv;
  15228     int i;
  15229     _bcm_tr3_cosq_node_t *node;
  15230     _bcm_tr3_mmu_info_t *mmu_info;
  15231 
  15232     mmu_info = _bcm_tr3_mmu_info[unit];
  15233     node = &mmu_info->queue_node[0];
  15234 
  15235     vid = _BCM_COSQ_CLASSIFIER_SERVICE_GET(classifier_id);
  15236 
  15237     BCM_IF_ERROR_RETURN(
  15238         soc_mem_read(unit, SERVICE_QUEUE_MAPm, MEM_BLOCK_ANY, (int)vid, &sqm));
  15239 
  15240     valid_entry = soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, &sqm, VALIDf);
  15241     if (!valid_entry) {
  15242         return BCM_E_CONFIG;  /* service queue is configured */
  15243     }
  15244 
  15245     qptr = soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, &sqm, SERVICE_QUEUE_PTRf);
  15246     spm_index = soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, &sqm,
  15247                                SERVICE_PORT_PROFILE_INDEXf);
  15248     scm_index = soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, &sqm,
  15249                                SERVICE_COS_PROFILE_INDEXf);
  15250 
  15251     /* allocate space for service port map profile */
  15252     spm = sal_alloc(sizeof(service_port_map_entry_t) *
  15253                     spm_entries_per_set,
  15254               "SERVICE_PORT_MAP temp Mem");
  15255     if (spm == NULL) {
  15256         return BCM_E_MEMORY;
  15257     }
  15258     sal_memset(spm,0,
  15259           sizeof(service_port_map_entry_t) * spm_entries_per_set);
  15260     spm_entries[0] = spm;
  15261 
  15262     /* allocate space for service cos map profile */
  15263     scm = sal_alloc(sizeof(service_cos_map_entry_t) *
  15264                     scm_entries_per_set,
  15265               "SERVICE_COS_MAP temp Mem");
  15266     if (scm == NULL) {
  15267         sal_free(spm);
  15268         return BCM_E_MEMORY;
  15269     }
  15270     sal_memset(scm,0,
  15271           sizeof(service_cos_map_entry_t) * scm_entries_per_set);
  15272     scm_entries[0] = scm;
  15273 
  15274     rv = soc_profile_mem_get(unit, _bcm_tr3_service_port_map_profile[unit],
  15275                          spm_index * spm_entries_per_set,
  15276                          spm_entries_per_set, spm_entries);
  15277     if (!(rv == SOC_E_NOT_FOUND || rv == SOC_E_NONE)) {
  15278         sal_free(spm);
  15279         sal_free(scm);
  15280         return rv;
  15281     }
  15282 
  15283     rv = soc_profile_mem_get(unit, _bcm_tr3_service_cos_map_profile[unit],
  15284                          scm_index * scm_entries_per_set,
  15285                          scm_entries_per_set, scm_entries);
  15286     if (!(rv == SOC_E_NOT_FOUND || rv == SOC_E_NONE)) {
  15287         sal_free(spm);
  15288         sal_free(scm);
  15289         return rv;
  15290     }
  15291 
  15292     q_offset = soc_mem_field32_get(unit, SERVICE_PORT_MAPm,
  15293                       &spm[port], SERVICE_PORT_OFFSETf);
  15294     if (0 == q_offset) {
  15295         sal_free(spm);
  15296         sal_free(scm);
  15297         return BCM_E_NOT_FOUND;
  15298     }
  15299 
  15300     for (i = 0; i < _BCM_TR3_NUM_L2_UC_LEAVES; i++) {
  15301         if (node->in_use && (node->hw_index == (q_offset + qptr))) {
  15302             *queue_group = node->gport;
  15303             break;
  15304         }
  15305         node++;
  15306     }
  15307     if (i == _BCM_TR3_NUM_L2_UC_LEAVES) {
  15308         sal_free(spm);
  15309         sal_free(scm);
  15310         return BCM_E_NOT_FOUND;
  15311     }
  15312 
  15313     *array_count = array_max > scm_entries_per_set? scm_entries_per_set :
  15314                    array_max;
  15315     for (i = 0; i < *array_count; i++) {
  15316         if (priority_array[i] >= 16) {
  15317             sal_free(spm);
  15318             sal_free(scm);
  15319             return BCM_E_PARAM;
  15320         }
  15321         cosq_array[i]     = soc_mem_field32_get(unit,SERVICE_COS_MAPm,
  15322                                &scm[priority_array[i]],SERVICE_COS_OFFSETf);
  15323     }
  15324     sal_free(spm);
  15325     sal_free(scm);
  15326     return BCM_E_NONE;      
  15327 }
  15328 
  15329 /*
  15330  * Function:
  15331  *      bcm_tr3_cosq_service_map_clear
  15332  * Purpose:
  15333  *      Clear the mapping from port, classifier, and internal priorities
  15334  *      to COS queues in a queue group.
  15335  * Parameters:
  15336  *      unit          - (IN) Unit number.
  15337  *      port          - (IN) Local port ID
  15338  *      classifier_id - (IN) Classifier ID
  15339  * Returns:
  15340  *      BCM_E_xxx
  15341  */
  15342 int
  15343 bcm_tr3_cosq_service_map_clear(
  15344     int unit,
  15345     bcm_gport_t port,
  15346     int classifier_id)
  15347 {
  15348     service_queue_map_entry_t sqm;
  15349     int spm_entries_per_set = 128;
  15350     int scm_entries_per_set = 16;
  15351     int spm_index;
  15352     uint32  newspm_index;
  15353     int scm_index;
  15354     int vid;
  15355     int valid_entry;
  15356     int q_ptr = 0;
  15357     int oldq_ptr = 0;
  15358     service_port_map_entry_t *spm;
  15359     void *spm_entries[1];
  15360     int  i = 0;
  15361     int rv = 0; 
  15362     int offset_valid = 0;
  15363     int port_offset = 0 ;
  15364     int q_offset = 0;
  15365     int classifier_in_use;
  15366     int diffserv;
  15367 
  15368     vid = _BCM_COSQ_CLASSIFIER_SERVICE_GET(classifier_id);
  15369 
  15370     BCM_IF_ERROR_RETURN(soc_mem_read(unit, SERVICE_QUEUE_MAPm, MEM_BLOCK_ANY,
  15371                         (int)vid, &sqm));
  15372 
  15373     valid_entry = soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, &sqm, VALIDf);
  15374     if (!valid_entry) {
  15375         return BCM_E_NONE;  /* service queue is already cleared  */
  15376     }
  15377 
  15378   if (soc_property_get(unit, spn_SERVICE_QUEUE_DYNAMIC_CONFIG, FALSE) == FALSE) {
  15379     /* spn_SERVICE_QUEUE_DYNAMIC_CONFIG=FALSE, Default behavior */
  15380 #if 0
  15381     qptr = soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, &sqm, SERVICE_QUEUE_PTRf);
  15382 #endif
  15383     spm_index = soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, &sqm,
  15384                                SERVICE_PORT_PROFILE_INDEXf);
  15385     scm_index = soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, &sqm,
  15386                                SERVICE_COS_PROFILE_INDEXf);
  15387 
  15388      /* allocate space for service port map profile */
  15389     spm = sal_alloc(sizeof(service_port_map_entry_t) *
  15390                            spm_entries_per_set,
  15391                            "SERVICE_PORT_MAP temp Mem");
  15392     if (spm == NULL) {
  15393         return BCM_E_MEMORY;
  15394     }
  15395     sal_memset(spm, 0,
  15396         sizeof(service_port_map_entry_t) * spm_entries_per_set);
  15397         spm_entries[0] = spm;
  15398      
  15399     rv = soc_profile_mem_get(unit, _bcm_tr3_service_port_map_profile[unit],
  15400                              spm_index * spm_entries_per_set,
  15401                              spm_entries_per_set, spm_entries);
  15402     if (!(rv == SOC_E_NOT_FOUND || rv == SOC_E_NONE)) {
  15403           sal_free(spm);
  15404           return BCM_E_NOT_FOUND;
  15405     }
  15406 
  15407     soc_mem_field32_set(unit, SERVICE_PORT_MAPm,&spm[port],
  15408                                  SERVICE_PORT_OFFSETf, 0);
  15409 
  15410     classifier_in_use = 0;
  15411     for (i = 0; i < spm_entries_per_set; i++) {
  15412         if (soc_mem_field32_get(unit, SERVICE_PORT_MAPm,
  15413                                 &spm[i], SERVICE_PORT_OFFSETf)) {
  15414             classifier_in_use = 1;
  15415             break;
  15416         }
  15417     }
  15418 
  15419     /* delete the spm porfile */
  15420     rv = soc_profile_mem_delete(unit, 
  15421                          _bcm_tr3_service_port_map_profile[unit],
  15422                          spm_index * spm_entries_per_set);
  15423     if (rv != SOC_E_NONE) {
  15424         goto cleanup;
  15425     }
  15426 
  15427     if (classifier_in_use) {
  15428        rv = soc_profile_mem_add(unit, _bcm_tr3_service_port_map_profile[unit],
  15429                                 spm_entries,spm_entries_per_set,
  15430                                 &newspm_index);
  15431        if (rv != SOC_E_NONE) {
  15432            goto cleanup; 
  15433        }
  15434 
  15435        soc_mem_field32_set(unit, SERVICE_QUEUE_MAPm, &sqm,
  15436                            SERVICE_PORT_PROFILE_INDEXf,
  15437                            newspm_index / spm_entries_per_set);
  15438     }
  15439     else {
  15440         /* delete the scm profile */
  15441         rv = soc_profile_mem_delete(unit,
  15442                              _bcm_tr3_service_cos_map_profile[unit],
  15443                              scm_index * scm_entries_per_set);
  15444         if (rv != SOC_E_NONE) {
  15445             goto cleanup; 
  15446         }
  15447         sal_memset(&sqm, 0, sizeof(service_queue_map_entry_t));
  15448     }
  15449   } else {
  15450     /* spn_SERVICE_QUEUE_DYNAMIC_CONFIG=TRUE, Behavior with dynamic configuration */
  15451     spm_index = soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, &sqm,
  15452                                SERVICE_PORT_PROFILE_INDEXf);
  15453     newspm_index = spm_index;
  15454     scm_index = soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, &sqm,
  15455                                SERVICE_COS_PROFILE_INDEXf);
  15456 
  15457     oldq_ptr = soc_mem_field32_get(unit, SERVICE_QUEUE_MAPm, &sqm, SERVICE_QUEUE_PTRf);
  15458      /* allocate space for service port map profile */
  15459     spm = sal_alloc(sizeof(service_port_map_entry_t) *
  15460                            spm_entries_per_set,
  15461                            "SERVICE_PORT_MAP temp Mem");
  15462     if (spm == NULL) {
  15463         return BCM_E_MEMORY;
  15464     }
  15465     sal_memset(spm, 0,
  15466         sizeof(service_port_map_entry_t) * spm_entries_per_set);
  15467         spm_entries[0] = spm;
  15468 
  15469     rv = soc_profile_mem_get(unit, _bcm_tr3_service_port_map_profile[unit],
  15470                              spm_index * spm_entries_per_set,
  15471                              spm_entries_per_set, spm_entries);
  15472     if (!(rv == SOC_E_NOT_FOUND || rv == SOC_E_NONE)) {
  15473           sal_free(spm);
  15474           return BCM_E_NOT_FOUND;
  15475     }
  15476 
  15477     port_offset = soc_mem_field32_get(unit, SERVICE_PORT_MAPm, &spm[port],
  15478                                  SERVICE_PORT_OFFSETf);
  15479     if (SOC_INFO(unit).port_uc_cosq_base[port]>=0) {
  15480         diffserv = (SOC_INFO(unit).port_uc_cosq_base[port] - oldq_ptr) & 0x3ff;
  15481         soc_mem_field32_set(unit, SERVICE_PORT_MAPm, &spm[port],
  15482 	                        SERVICE_PORT_OFFSETf,
  15483                             diffserv);
  15484     } else {
  15485         soc_mem_field32_set(unit, SERVICE_PORT_MAPm,&spm[port],
  15486                             SERVICE_PORT_OFFSETf, 0);
  15487     }
  15488 #ifdef DEBUG_TR3_COSQ
  15489     soc_cm_print("%d:: old_offset=%d new_offset=0x%x  \r\n",
  15490                  __LINE__, port_offset,
  15491                  soc_mem_field32_get(unit, SERVICE_PORT_MAPm, &spm[port],
  15492                                  SERVICE_PORT_OFFSETf));
  15493 #endif
  15494     if (port_offset == 1) { /* Removing first entry ? */
  15495         int lowest_offset = spm_entries_per_set * 8;   /* Set to invalid range */
  15496         int found = 0;
  15497         for (i = 0; i < spm_entries_per_set; i++) {
  15498 
  15499             /* We need not iterate beyond Max Ports */
  15500             if ( i >=  ((SOC_MAX_NUM_PP_PORTS > SOC_MAX_NUM_PORTS ?
  15501                          SOC_MAX_NUM_PP_PORTS : SOC_MAX_NUM_PORTS)) ) {
  15502                 /* This check is reqd. for partial builds, as MAX_PORTS can be
  15503                    less than depth of SERVICE_PORT_MAPm (128) */
  15504                 /* coverity[dead_error_line] */
  15505                 break;
  15506             }
  15507 
  15508             q_offset = soc_mem_field32_get(unit, SERVICE_PORT_MAPm, &spm[i],
  15509                                            SERVICE_PORT_OFFSETf);
  15510             diffserv =
  15511                 (SOC_INFO(unit).port_uc_cosq_base[i] - oldq_ptr) & 0x3ff;
  15512 
  15513             if (q_offset && diffserv && (q_offset != diffserv)) {
  15514                if (q_offset < lowest_offset) {
  15515                   lowest_offset = q_offset;
  15516                   q_ptr = oldq_ptr + lowest_offset - port_offset;
  15517                   found = 1;
  15518                }
  15519             }
  15520         }
  15521 
  15522 
  15523 #ifdef DEBUG_TR3_COSQ
  15524         soc_cm_print("%d:: found=%d, lowest_os=%d, q_ptr=0x%x, old_ptr=0x%x\r\n",
  15525                     __LINE__, found, lowest_offset, q_ptr, oldq_ptr);
  15526 #endif
  15527         /* Found leftover port(s) ? */
  15528         if (found) {
  15529             lowest_offset--;   /* adjust by one */
  15530             offset_valid = 1;
  15531             for (i = 0; i < spm_entries_per_set; i++) {
  15532                 q_offset = soc_mem_field32_get(unit,
  15533 				                               SERVICE_PORT_MAPm, &spm[i],
  15534                                                SERVICE_PORT_OFFSETf);
  15535                 if (q_offset) {
  15536                     /* Adjust offsets */
  15537                     soc_mem_field32_set(unit, SERVICE_PORT_MAPm, &spm[i],
  15538                                         SERVICE_PORT_OFFSETf,
  15539                                         ((q_offset - lowest_offset) & 0x3FF));
  15540                 }
  15541             }
  15542         }
  15543 	    else {
  15544 	        /* No more ports ??? */
  15545 
  15546             /* Clear out SQM */
  15547             sal_memset(&sqm,0, sizeof(service_queue_map_entry_t));
  15548 
  15549             /* Write back updated buffer. */
  15550             rv =  soc_mem_write(unit, SERVICE_QUEUE_MAPm, MEM_BLOCK_ALL,
  15551                                (int)vid, &sqm);
  15552 
  15553 		    /* Remove SPM */
  15554             rv = soc_profile_mem_delete(unit,
  15555                          _bcm_tr3_service_port_map_profile[unit],
  15556                          spm_index * spm_entries_per_set);
  15557 
  15558             /* delete the scm profile (profile refcount is decremented and
  15559 			                           is deleted when refcount is 0) */
  15560             rv = soc_profile_mem_delete(unit,
  15561                                  _bcm_tr3_service_cos_map_profile[unit],
  15562                                  scm_index * scm_entries_per_set);
  15563 
  15564             goto cleanup;
  15565         }
  15566     }
  15567     else {
  15568         /* No need to adjust offsets since port w/base-q-pttr still exists ? */
  15569         for (i = 0; i < spm_entries_per_set; i++) {
  15570             q_offset = soc_mem_field32_get(unit, SERVICE_PORT_MAPm, &spm[i],
  15571                                            SERVICE_PORT_OFFSETf);
  15572             diffserv =
  15573                 (SOC_INFO(unit).port_uc_cosq_base[i] - oldq_ptr) & 0x3ff;
  15574 
  15575             if (q_offset && diffserv && (q_offset != diffserv)) {
  15576                 offset_valid = 1;
  15577                 break;
  15578             }
  15579         }
  15580     }
  15581 
  15582 #ifdef DEBUG_TR3_COSQ
  15583     soc_cm_print("%d:: offset_valid=%d, spm_index=%d \r\n", __LINE__, offset_valid, spm_index);
  15584 #endif
  15585     if(offset_valid) {
  15586 	   /*
  15587 	    *   Update sequence
  15588 	    *   a. Add new SPM.
  15589 	    *   b. Update SQM->SPM_Index to new SPM
  15590 	    *   c. Clear old SPM.
  15591 	    */
  15592        rv = soc_profile_mem_add(unit, _bcm_tr3_service_port_map_profile[unit],
  15593                                 spm_entries,spm_entries_per_set,
  15594                                 &newspm_index);
  15595        newspm_index = newspm_index / spm_entries_per_set;
  15596        if (rv != SOC_E_NONE) {
  15597            goto cleanup;
  15598        }
  15599        soc_mem_field32_set(unit, SERVICE_QUEUE_MAPm, &sqm,
  15600                            SERVICE_PORT_PROFILE_INDEXf,
  15601                            newspm_index);
  15602        if (port_offset == 1 ) {
  15603            soc_mem_field32_set(unit, SERVICE_QUEUE_MAPm, &sqm,
  15604                                SERVICE_QUEUE_PTRf, (q_ptr & 0x3FF));
  15605        }
  15606 
  15607        rv = soc_mem_write(unit, SERVICE_QUEUE_MAPm, MEM_BLOCK_ALL,
  15608                            (int)vid, &sqm);
  15609 	   if (!rv && (spm_index != newspm_index))
  15610 	   {
  15611            /* delete the spm porfile */
  15612            rv = soc_profile_mem_delete(unit,
  15613                       _bcm_tr3_service_port_map_profile[unit],
  15614                       spm_index * spm_entries_per_set);
  15615        }
  15616        goto cleanup;
  15617     }
  15618   } /* spn_SERVICE_QUEUE_DYNAMIC_CONFIG */
  15619     /* Write back updated buffer. */
  15620     rv =  soc_mem_write(unit, SERVICE_QUEUE_MAPm, MEM_BLOCK_ALL,
  15621                        (int)vid, &sqm);
  15622     
  15623 cleanup:
  15624     sal_free(spm);
  15625     return rv;
  15626 }
  15627 
  15628 #define IFP_COS_MAP_MAX_ENTRIES 16
  15629 int 
  15630 bcm_tr3_cosq_classifier_id_get(int unit, bcm_cosq_classifier_t *classifier,
  15631                 int array_count, 
  15632                 bcm_cos_t *priority_array, 
  15633                 bcm_cos_queue_t *cosq_array,
  15634                 int *classifier_id)
  15635 {
  15636     int rv = BCM_E_NONE;
  15637     ifp_cos_map_entry_t *ent_buf = NULL;    
  15638     int field_width;
  15639     uint32 index;
  15640     void *entries[1];
  15641 
  15642     if (array_count > IFP_COS_MAP_MAX_ENTRIES) {
  15643         return (BCM_E_PARAM);
  15644     }
  15645 
  15646     ent_buf = sal_alloc(sizeof(ifp_cos_map_entry_t) * IFP_COS_MAP_MAX_ENTRIES,
  15647             "IFP_COS_MAP entry");
  15648     if (ent_buf == NULL) {
  15649         return (BCM_E_MEMORY);
  15650     }
  15651 
  15652     field_width = soc_mem_field_length(unit, IFP_COS_MAPm, IFP_COSf);
  15653     sal_memset(ent_buf, 0, sizeof(ifp_cos_map_entry_t) * IFP_COS_MAP_MAX_ENTRIES);
  15654     entries[0] = ent_buf;
  15655 
  15656     for (index = 0; index < array_count; index++) {
  15657         if (priority_array[index] < IFP_COS_MAP_MAX_ENTRIES) {
  15658             if (cosq_array[index] >= (1 << field_width)) {
  15659                 sal_free(ent_buf);
  15660                 return BCM_E_PARAM;
  15661             }
  15662             soc_mem_field32_set(unit, IFP_COS_MAPm, &ent_buf[priority_array[index]],
  15663                     IFP_COSf, cosq_array[index]);
  15664         }
  15665     }
  15666 
  15667     rv = soc_profile_mem_search(unit, _bcm_tr3_ifp_cos_map_profile[unit],
  15668             entries, IFP_COS_MAP_MAX_ENTRIES, &index);
  15669     if (rv ==  SOC_E_EXISTS) {
  15670         _BCM_COSQ_CLASSIFIER_FIELD_SET(*classifier_id,index );
  15671         rv = BCM_E_NONE;
  15672     } else {
  15673         rv = BCM_E_NOT_FOUND;
  15674     }
  15675 
  15676     sal_free(ent_buf);
  15677     return rv;
  15678 }
  15679 /*
  15680  * Function:
  15681  *      bcm_td_cosq_cpu_cosq_enable_set
  15682  * Purpose:
  15683  *      To enable/disable Rx of packets on the specified CPU cosq.
  15684  * Parameters:
  15685  *      unit          - (IN) Unit number.
  15686  *      cosq          - (IN) CPU Cosq ID
  15687  *      enable        - (IN) Enable/Disable
  15688  * Returns:
  15689  *      BCM_E_xxx
  15690  */
  15691 int
  15692 bcm_tr3_cosq_cpu_cosq_enable_set(
  15693     int unit, 
  15694     bcm_cos_queue_t cosq, 
  15695     int enable)
  15696 {
  15697     return BCM_E_UNAVAIL;
  15698 }
  15699 
  15700 /*
  15701  * Function:
  15702  *      bcm_td_cosq_cpu_cosq_enable_get
  15703  * Purpose:
  15704  *      To get enable/disable status on Rx of packets on the specified CPU cosq.
  15705  * Parameters:
  15706  *      unit          - (IN) Unit number.
  15707  *      cosq          - (IN) CPU Cosq ID
  15708  *      enable        - (OUT) Enable/Disable
  15709  * Returns:
  15710  *      BCM_E_xxx
  15711  */
  15712 int
  15713 bcm_tr3_cosq_cpu_cosq_enable_get(
  15714     int unit, 
  15715     bcm_cos_queue_t cosq, 
  15716     int *enable)
  15717 {
  15718     return BCM_E_UNAVAIL;
  15719 }
  15720 
  15721 int
  15722 bcm_tr3_switch_qcn_mac_set(int unit, bcm_switch_control_t type,
  15723                       soc_mem_t mem,soc_field_t field, void* entry,
  15724                       uint32 mac_field)
  15725 {
  15726     bcm_mac_t   mac;
  15727     sal_memset(mac, 0, sizeof(bcm_mac_t));
  15728     soc_mem_mac_addr_get(unit, mem, entry,
  15729                         field, mac);
  15730     switch(type) {
  15731         case bcmSwitchCongestionCnmSrcMacNonOui:
  15732              mac[3] = (uint8) (mac_field >> 16 & 0xff);
  15733              mac[4] = (uint8) (mac_field >> 8 & 0xff);
  15734              mac[5] = (uint8) (mac_field & 0xff);
  15735              break;
  15736         case bcmSwitchCongestionCnmSrcMacOui:
  15737              mac[0] = (uint8) (mac_field >> 16 & 0xff);
  15738              mac[1] = (uint8) (mac_field >> 8 & 0xff);
  15739              mac[2] = (uint8) (mac_field & 0xff);
  15740              break;
  15741         default :
  15742              return BCM_E_PARAM;
  15743     }
  15744     soc_mem_mac_addr_set(unit, mem, entry,
  15745                         field, mac);
  15746     return BCM_E_NONE;
  15747 }
  15748 int
  15749 bcm_tr3_switch_qcn_mac_get(int unit, bcm_switch_control_t type,
  15750                       soc_mem_t mem,soc_field_t field, void* entry,
  15751                       uint32 *mac_field)
  15752 {
  15753      bcm_mac_t mac;
  15754      soc_mem_mac_addr_get(unit, mem, entry,
  15755                         field, mac);
  15756     switch (type) {
  15757         case bcmSwitchCongestionCnmSrcMacNonOui:
  15758              *mac_field = ((mac[3] << 16) | (mac[4] << 8)  | (mac[5] << 0));
  15759              break;
  15760         case bcmSwitchCongestionCnmSrcMacOui:
  15761              *mac_field = ((mac[0] << 16) | (mac[1] << 8)  | (mac[2] << 0));
  15762              break;
  15763         default :
  15764            return BCM_E_PARAM;
  15765     }
  15766     return BCM_E_NONE;
  15767 }
  15768 /*
  15769  * Function:
  15770  *     _bcm_tr3_port_enqueue_set
  15771  * Purpose:
  15772  *     Enable or Disable the enqueing the packets to the port
  15773  * Parameters:
  15774  *     unit       - (IN) unit number
  15775  *     gport      - (IN) gport of the port 
  15776  *     enable     - (IN) TRUE to enable
  15777  *                      FALSE to disable
  15778  * Returns:
  15779  *     BCM_E_XXX
  15780  */
  15781 
  15782 int
  15783 _bcm_tr3_port_enqueue_set(int unit, bcm_port_t gport,
  15784         int enable)
  15785 {
  15786     uint64 rval64, rval64_tmp;
  15787     int mmu_port, phy_port, i;
  15788     int rv = BCM_E_NONE;
  15789     bcm_port_t local_port;
  15790     soc_info_t *si;
  15791     soc_reg_t reg_tmp;
  15792     soc_reg_t reg[2] = {
  15793         OUTPUT_PORT_RX_ENABLE0_64r,
  15794         INPUT_PORT_RX_ENABLE_64r
  15795     };
  15796     int max_reg = 2;
  15797 
  15798     BCM_IF_ERROR_RETURN
  15799         (_bcm_tr3_cosq_localport_resolve(unit, gport, &local_port));
  15800 
  15801     si = &SOC_INFO(unit);
  15802 
  15803     phy_port = si->port_l2p_mapping[local_port];
  15804     mmu_port = si->port_p2m_mapping[phy_port];
  15805 
  15806     COMPILER_64_ZERO(rval64);
  15807     COMPILER_64_ZERO(rval64_tmp);
  15808 
  15809     /* Disable enqueue to the port */
  15810     for (i = 0; i < max_reg; i++) {
  15811         reg_tmp =  reg[i];
  15812 
  15813         SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg_tmp, REG_PORT_ANY, 0, &rval64));
  15814 
  15815         if (mmu_port < 32) {
  15816             COMPILER_64_SET(rval64_tmp, 0, 1 << mmu_port);
  15817         } else {
  15818             COMPILER_64_SET(rval64_tmp, 1 << (mmu_port - 32), 0);
  15819         }
  15820         if (!enable) {
  15821             COMPILER_64_NOT(rval64_tmp);
  15822             COMPILER_64_AND(rval64, rval64_tmp);
  15823         } else {
  15824             COMPILER_64_OR(rval64, rval64_tmp);
  15825         }
  15826         SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg_tmp, REG_PORT_ANY, 0, rval64));
  15827     }
  15828     return rv;
  15829 }
  15830 
  15831 /*
  15832  * Function:
  15833  *     _bcm_tr3_port_tx_set
  15834  * Purpose:
  15835  *     Enable or Disable the enqueing the packets to the port
  15836  * Parameters:
  15837  *     unit       - (IN) unit number
  15838  *     gport      - (IN) gport of the port
  15839  *     enable     - (IN) TRUE to enable
  15840  *                      FALSE to disable
  15841  * Returns:
  15842  *     BCM_E_XXX
  15843  */
  15844 int
  15845 _bcm_tr3_port_tx_set(int unit, bcm_port_t gport, int enable)
  15846 {
  15847     uint64 rval64, rval64_tmp;
  15848     int mmu_port, phy_port;
  15849     int rv = BCM_E_NONE;
  15850     bcm_port_t local_port;
  15851     soc_info_t *si;
  15852     soc_reg_t reg = OUTPUT_PORT_RX_ENABLE0_64r;
  15853 
  15854     BCM_IF_ERROR_RETURN
  15855         (_bcm_tr3_cosq_localport_resolve(unit, gport, &local_port));
  15856 
  15857     si = &SOC_INFO(unit);
  15858 
  15859     phy_port = si->port_l2p_mapping[local_port];
  15860     mmu_port = si->port_p2m_mapping[phy_port];
  15861 
  15862     COMPILER_64_ZERO(rval64);
  15863     COMPILER_64_ZERO(rval64_tmp);
  15864 
  15865     /* Disable enqueue to the port */
  15866 
  15867     SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, REG_PORT_ANY, 0, &rval64));
  15868 
  15869     if (mmu_port < 32) {
  15870         COMPILER_64_SET(rval64_tmp, 0, 1 << mmu_port);
  15871     } else {
  15872         COMPILER_64_SET(rval64_tmp, 1 << (mmu_port - 32), 0);
  15873     }
  15874     if (!enable) {
  15875         COMPILER_64_NOT(rval64_tmp);
  15876         COMPILER_64_AND(rval64, rval64_tmp);
  15877     } else {
  15878         COMPILER_64_OR(rval64, rval64_tmp);
  15879     }
  15880     SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, REG_PORT_ANY, 0, rval64));
  15881 
  15882     return rv;
  15883 }
  15884 
  15885 /*
  15886  * Function:
  15887  *     _bcm_tr3_port_enqueue_get
  15888  * Purpose:
  15889  *      Getting the enqueing state of the port 
  15890  * Parameters:
  15891  *     unit       - (IN) unit number
  15892  *     gport      - (IN) gport of the port 
  15893  *     enable     - (IN) TRUE to enable
  15894  *                      FALSE to disable
  15895  * Returns:
  15896  *     BCM_E_XXX
  15897  */
  15898 
  15899     int
  15900 _bcm_tr3_port_enqueue_get(int unit, bcm_port_t gport,
  15901                                   int *enable)
  15902 {
  15903     uint64 rval64;
  15904     int mmu_port, phy_port, i;
  15905     int rv = BCM_E_NONE;
  15906     bcm_port_t local_port;
  15907     soc_info_t *si;
  15908     soc_reg_t reg_tmp;
  15909     soc_reg_t reg[2] = {
  15910         OUTPUT_PORT_RX_ENABLE0_64r,
  15911         INPUT_PORT_RX_ENABLE_64r
  15912     };
  15913     int max_reg = 2;
  15914 
  15915     BCM_IF_ERROR_RETURN
  15916         (_bcm_tr3_cosq_localport_resolve(unit, gport, &local_port));
  15917 
  15918     si = &SOC_INFO(unit);
  15919 
  15920     phy_port = si->port_l2p_mapping[local_port];
  15921     mmu_port = si->port_p2m_mapping[phy_port];
  15922 
  15923     COMPILER_64_ZERO(rval64);
  15924 
  15925     /* Disable enqueue to the port */
  15926     for (i = 0; i < max_reg; i++) {
  15927         reg_tmp = reg[i];
  15928 
  15929         SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg_tmp, REG_PORT_ANY, 0, &rval64));
  15930 
  15931         if (COMPILER_64_BITTEST(rval64 , mmu_port)) {
  15932             *enable = TRUE;
  15933         } else {
  15934             *enable = FALSE;
  15935         }
  15936     }
  15937     return rv;
  15938 }
  15939 #endif  /* BCM_TRIUMPH3_SUPPORT */
  15940