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


      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 <sal/core/libc.h>
     14 #include <soc/defs.h>
     15 #if defined(BCM_KATANA_SUPPORT)
     16 #include <soc/drv.h>
     17 #include <soc/scache.h>
     18 #include <soc/katana.h>
     19 #include <soc/macutil.h>
     20 #include <soc/profile_mem.h>
     21 #ifdef BCM_CMICM_SUPPORT
     22 #include <soc/cmicm.h>
     23 #endif
     24 #include <bcm/error.h>
     25 #include <bcm/cosq.h>
     26 #include <bcm_int/esw/mbcm.h>
     27 #include <bcm_int/esw/firebolt.h>
     28 #include <bcm_int/esw/katana.h>
     29 #include <bcm_int/esw/stack.h>
     30 #include <bcm_int/esw/cosq.h>
     31 #include <bcm_int/esw/multicast.h>
     32 
     33 #include <bcm_int/esw_dispatch.h>
     34 
     35 #include <bcm/types.h>
     36 
     37 #ifdef BCM_WARM_BOOT_SUPPORT
     38 #include <bcm_int/esw/switch.h>
     39 #endif /* BCM_WARM_BOOT_SUPPORT */
     40 
     41 #if defined(BCM_KATANA_SUPPORT)
     42 #include <soc/katana2.h>
     43 #endif
     44 
     45 #define _BCM_COSQ_PARENT_BMAP_SET(bmap, bit)          \
     46     if (bmap != NULL) {                               \
     47         SHR_BITSET(bmap, bit);                        \
     48     } 
     49 
     50 #define _BCM_COSQ_PARENT_BMAP_CLR(bmap, bit)          \
     51     if (bmap != NULL) {                               \
     52         SHR_BITCLR(bmap, bit);                        \
     53     }                                                       
     54 
     55 #define _BCM_KT_IS_UC_QUEUE(mmu_info,qid)   \
     56          (((qid) < mmu_info->num_base_queues) ? 1 : 0)
     57     
     58 
     59 #define KT_CELL_FIELD_MAX       0x3ffff
     60 
     61 #define KT_QUEUE_FLUSH_BURST_MANTISSA   124
     62 #define KT_QUEUE_FLUSH_BURST_EXP        14
     63 #define KT_QUEUE_FLUSH_CYCLE_SEL        0
     64 
     65 /* Sum of all of max bandwidth configured on all children
     66  * nodes should be less than or equal to the parent node's
     67  * max bandwidth. Hence using 90% of parent's node BW and dividing
     68  * it by the num of children nodes when configuring the children nodes
     69  * shpaer config.
     70  */
     71 #define KT_COSQ_SHAPER_PERC             90
     72 
     73 /* MMU cell size in bytes */
     74 #define _BCM_KT_COSQ_CELLSIZE   192
     75 #define _BCM_KT_COSQ_EXT_CELLSIZE   768
     76 
     77 #define _BCM_KT_NUM_UCAST_QUEUE_GROUP            8
     78 #define _BCM_KT_NUM_VLAN_UCAST_QUEUE_GROUP       16
     79 
     80 /* ==========Separate file for KT2 is surely required now ===== */
     81 /* For KT: #define _BCM_KT_NUM_PORT_SCHEDULERS              36  */
     82 /* For KT2: #define _BCM_KT_NUM_PORT_SCHEDULERS              42 */
     83 /* ============================================================ */
     84 #define _BCM_KT_NUM_PORT_SCHEDULERS              42
     85 #define _BCM_KT_NUM_L0_SCHEDULER                 256
     86 #define _BCM_KT_NUM_L1_SCHEDULER                 1024
     87 #define _BCM_KT_NUM_L2_QUEUES                    4096
     88 #define _BCM_KT_NUM_TOTAL_SCHEDULERS             (_BCM_KT_NUM_PORT_SCHEDULERS + \
     89                                                   _BCM_KT_NUM_L0_SCHEDULER +    \
     90                                                   _BCM_KT_NUM_L1_SCHEDULER)
     91 
     92 #define _BCM_KT_COSQ_LIST_NODE_INIT(list, node)         \
     93     list[node].in_use            = FALSE;               \
     94     list[node].wrr_in_use        = 0;                   \
     95     list[node].gport             = -1;                  \
     96     list[node].base_index        = -1;                  \
     97     list[node].numq              = 0;                   \
     98     list[node].hw_index          = -1;                  \
     99     list[node].level             = -1;                  \
    100     list[node].cosq_attached_to  = -1;                  \
    101     list[node].num_child         = 0;                   \
    102     list[node].first_child       = 4095;                \
    103     list[node].cosq_map          = NULL;                \
    104     list[node].parent            = NULL;                \
    105     list[node].sibling           = NULL;                \
    106     list[node].child             = NULL;
    107 
    108 #define _BCM_KT_COSQ_NODE_INIT(node)                    \
    109     node->in_use            = FALSE;                    \
    110     node->wrr_in_use        = 0;                        \
    111     node->gport             = -1;                       \
    112     node->base_index        = -1;                       \
    113     node->numq              = 0;                        \
    114     node->hw_index          = -1;                       \
    115     node->level             = -1;                       \
    116     node->cosq_attached_to  = -1;                       \
    117     node->num_child         = 0;                        \
    118     node->first_child       = 4095;                     \
    119     node->cosq_map          = NULL;                     \
    120     node->parent            = NULL;                     \
    121     node->sibling           = NULL;                     \
    122     node->child             = NULL;
    123 
    124 typedef enum {
    125     _BCM_KT_COSQ_STATE_NO_CHANGE,
    126     _BCM_KT_COSQ_STATE_DISABLE,
    127     _BCM_KT_COSQ_STATE_ENABLE,
    128     _BCM_KT_COSQ_STATE_SPRI_TO_WRR,
    129     _BCM_KT_COSQ_STATE_WRR_TO_SPRI,
    130     _BCM_KT_COSQ_STATE_MAX
    131 }_bcm_kt_cosq_state_t;
    132 
    133 typedef struct _bcm_kt_cosq_list_s {
    134     int count;
    135     SHR_BITDCL *bits;
    136 }_bcm_kt_cosq_list_t;
    137 
    138 typedef struct _bcm_kt_cosq_port_info {
    139     int q_offset;
    140     int q_limit;
    141 }_bcm_kt_cosq_port_info_t;
    142 
    143 typedef struct _bcm_kt_mmu_info_s {
    144     int num_base_queues;   /* Number of classical queues */
    145     int num_ext_queues;    /* Number of extended queues */
    146     int num_sub_queues;    /* Number of subscriber queues */
    147     int base_sub_queue;    /* Base Subscriber queue */
    148     int qset_size;         /* subscriber queue set size */
    149     uint32 num_queues;     /* total number of queues */
    150     uint32 num_nodes;      /* max number of sched nodes */
    151     uint32 max_nodes[_BCM_KT_COSQ_NODE_LEVEL_MAX]; /* max nodes in each level */
    152     bcm_gport_t *l1_gport_pair;         /* L1 gport mapping for dynamic update */
    153     _bcm_kt_cosq_port_info_t *port;     /* port information */
    154     _bcm_kt_cosq_list_t ext_qlist;      /* list of extended queues */
    155     _bcm_kt_cosq_list_t sub_qlist;      /* list of subscriber queues */
    156     _bcm_kt_cosq_list_t sched_list;     /* list of sched nodes */
    157     _bcm_kt_cosq_list_t l0_sched_list;  /* list of l0 sched nodes */
    158     _bcm_kt_cosq_list_t l1_sched_list;  /* list of l1 sched nodes */
    159     _bcm_kt_cosq_list_t l2_base_qlist;  /* list of l2  base queue index list */
    160     _bcm_kt_cosq_list_t l2_ext_qlist;   /* list of l2  base queue index list */
    161     _bcm_kt_cosq_list_t l2_sub_qlist;   /* list of l2  subscriber queue index list */
    162 
    163     _bcm_kt_cosq_node_t sched_node[_BCM_KT_NUM_TOTAL_SCHEDULERS];     /* sched nodes */
    164     _bcm_kt_cosq_node_t queue_node[_BCM_KT_NUM_L2_QUEUES];            /* queue nodes */
    165     uint32  intf_ref_cnt[BCM_MULTICAST_PORT_MAX]; /* Interface reference count
    166                                                      for queues */
    167 }_bcm_kt_mmu_info_t;
    168 
    169 STATIC _bcm_kt_mmu_info_t *_bcm_kt_mmu_info[BCM_MAX_NUM_UNITS];  /* MMU info */
    170 
    171 STATIC soc_profile_mem_t *_bcm_kt_cos_map_profile[BCM_MAX_NUM_UNITS];
    172 STATIC soc_profile_mem_t *_bcm_kt_wred_profile[BCM_MAX_NUM_UNITS];
    173 
    174 STATIC int 
    175 _bcm_kt_cosq_child_node_at_input(_bcm_kt_cosq_node_t *node, int cosq,
    176                                   _bcm_kt_cosq_node_t **child_node);
    177 /* Number of COSQs configured for this device */
    178 STATIC int _bcm_kt_num_cosq[SOC_MAX_NUM_DEVICES];
    179 
    180 extern sal_mutex_t cosq_sync_lock[SOC_MAX_NUM_DEVICES];
    181 
    182 /*
    183  * Function:
    184  *     _bcm_kt_cosq_localport_resolve
    185  * Purpose:
    186  *     Resolve GRPOT if it is a local port
    187  * Parameters:
    188  *     unit       - (IN) unit number
    189  *     gport      - (IN) GPORT identifier
    190  *     local_port - (OUT) local port number
    191  * Returns:
    192  *     BCM_E_XXX
    193  */
    194 STATIC int
    195 _bcm_kt_cosq_localport_resolve(int unit, bcm_gport_t gport,
    196                                bcm_port_t *local_port)
    197 {
    198     bcm_module_t module;
    199     bcm_port_t port;
    200     bcm_trunk_t trunk;
    201     int id, result;
    202 
    203     if (!BCM_GPORT_IS_SET(gport)) {
    204         /* Below SOC check is used for time-being for KT2 */
    205         if (SOC_IS_KATANA(unit)) {
    206             if (!SOC_PORT_VALID(unit, gport)) {
    207                 return BCM_E_PORT;
    208             }
    209         }
    210         *local_port = gport;
    211         return BCM_E_NONE;
    212     } else if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
    213                BCM_GPORT_IS_SCHEDULER(gport) ||
    214                BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport)) {
    215         return BCM_E_PORT;
    216     }
    217 
    218     BCM_IF_ERROR_RETURN
    219         (_bcm_esw_gport_resolve(unit, gport, &module, &port, &trunk, &id));
    220 
    221     BCM_IF_ERROR_RETURN(_bcm_esw_modid_is_local(unit, module, &result));
    222     if (result == FALSE) {
    223         return BCM_E_PORT;
    224     }
    225 
    226     *local_port = port;
    227 
    228     return BCM_E_NONE;
    229 }
    230 
    231 /*
    232  * Function:
    233  *     _bcm_kt_node_index_get
    234  * Purpose:
    235  *     Allocate free index from the given list
    236  * Parameters:
    237  *     unit       - (IN) unit number
    238  *     list       - (IN) bit list
    239  *     start      - (IN) start index
    240  *     end        - (IN) end index
    241  *     qset       - (IN) size of queue set
    242  *     range      - (IN) range bits
    243  *     id         - (OUT) start index
    244  * Returns:
    245  *     BCM_E_XXX
    246  */
    247 STATIC int
    248 _bcm_kt_node_index_get(int unit, SHR_BITDCL *list, int start, int end,
    249                        int qset, int range, int *id)
    250 {
    251     int i, j, inc;
    252     _bcm_kt_mmu_info_t *mmu_info;
    253 
    254     if (_bcm_kt_mmu_info[unit] == NULL) {
    255         return BCM_E_INIT;
    256     }
    257     mmu_info = _bcm_kt_mmu_info[unit];
    258 
    259     *id = -1;
    260 
    261     if (range != qset) {
    262         inc = 1;
    263         for (i = start; i < end; i = (i + inc)) {
    264              inc = 1;
    265             for (j = i; j < (i + range); j++, inc++) {
    266                 if (SHR_BITGET(list, j) != 0) {
    267                     break;
    268                 }
    269             }
    270 
    271             if (j == (i + range) && (mmu_info->intf_ref_cnt[i] == 0)) {
    272                 *id = i;
    273                 return BCM_E_NONE;
    274             }
    275         }
    276         if (i == end) {
    277             return BCM_E_RESOURCE;
    278          }
    279     }
    280 
    281     for (i = start; i < end;  i = i + range) {
    282         for (j = i; j < (i + range); j++) {
    283             if (SHR_BITGET(list, j) != 0) {
    284                 break;
    285             }
    286         }
    287 
    288         if (j == (i + range) && (mmu_info->intf_ref_cnt[i] == 0)) {
    289             *id  =  i;
    290             return BCM_E_NONE;
    291            }
    292     }
    293 
    294     if (i == end) {
    295         return BCM_E_RESOURCE;
    296       }
    297 
    298     return BCM_E_NONE;
    299 }
    300 
    301 /*
    302  * Function:
    303  *     _bcm_kt_node_index_set
    304  * Purpose:
    305  *     Mark indices as allocated
    306  * Parameters:
    307  *     list       - (IN) bit list
    308  *     start      - (IN) start index
    309  *     range      - (IN) range bits
    310  * Returns:
    311  *     BCM_E_XXX
    312  */
    313 STATIC int
    314 _bcm_kt_node_index_set(_bcm_kt_cosq_list_t *list, int start, int range)
    315 {
    316     list->count += range;
    317     SHR_BITSET_RANGE(list->bits, start, range);
    318 
    319     return BCM_E_NONE;
    320 }
    321 
    322 /*
    323  * Function:
    324  *     _bcm_kt_node_index_clear
    325  * Purpose:
    326  *     Mark indices as free
    327  * Parameters:
    328  *     list       - (IN) bit list
    329  *     start      - (IN) start index
    330  *     range      - (IN) range bits
    331  * Returns:
    332  *     BCM_E_XXX
    333  */
    334 STATIC int
    335 _bcm_kt_node_index_clear(_bcm_kt_cosq_list_t *list, int start, int range)
    336 {
    337     list->count -= range;
    338     SHR_BITCLR_RANGE(list->bits, start, range);
    339 
    340     return BCM_E_NONE;
    341 }
    342 
    343 /*
    344  * Function:
    345  *     _bcm_kt_cosq_map_index_get
    346  * Purpose:
    347  *     Allocate free index from the given list
    348  * Parameters:
    349  *     list       - (IN) bit list
    350  *     start      - (IN) start index
    351  *     end        - (IN) end index
    352  *     id         - (OUT) start index
    353  * Returns:
    354  *     BCM_E_XXX
    355  */
    356 STATIC int
    357 _bcm_kt_cosq_map_index_get(SHR_BITDCL *list, int start, int end, int *id)
    358 {
    359     int i;
    360 
    361     for (i = start; i < end; i++) {
    362         if (SHR_BITGET(list, i) != 0) {
    363             continue;
    364         }
    365         *id  =  i;
    366         return BCM_E_NONE;
    367     }
    368 
    369     return BCM_E_RESOURCE;
    370 }
    371 
    372 /*
    373  * Function:
    374  *     _bcm_kt_cosq_map_index_set
    375  * Purpose:
    376  *     Mark indices as allocated
    377  * Parameters:
    378  *     list       - (IN) bit list
    379  *     start      - (IN) start index
    380  *     range      - (IN) range bits
    381  * Returns:
    382  *     BCM_E_XXX
    383  */
    384 STATIC int
    385 _bcm_kt_cosq_map_index_set(SHR_BITDCL *list, int start, int range)
    386 {
    387     SHR_BITSET_RANGE(list, start, range);
    388     return BCM_E_NONE;
    389 }
    390 
    391 /*
    392  * Function:
    393  *     _bcm_kt_cosq_map_index_clear
    394  * Purpose:
    395  *     Mark indices as free
    396  * Parameters:
    397  *     list       - (IN) bit list
    398  *     start      - (IN) start index
    399  *     range      - (IN) range bits
    400  * Returns:
    401  *     BCM_E_XXX
    402  */
    403 STATIC int
    404 _bcm_kt_cosq_map_index_clear(SHR_BITDCL *list, int start, int range)
    405 {
    406     SHR_BITCLR_RANGE(list, start, range);
    407     return BCM_E_NONE;
    408 }
    409 
    410 /*
    411  * Function:
    412  *     _bcm_kt_cosq_map_index_is_set
    413  * Purpose:
    414  *     Check index is allocated
    415  * Parameters:
    416  *     list       - (IN) bit list
    417  *     index      - (IN) index
    418  * Returns:
    419  *     BCM_E_XXX
    420  */
    421 STATIC int
    422 _bcm_kt_cosq_map_index_is_set(SHR_BITDCL *list, int index)
    423 {
    424     if (SHR_BITGET(list, index) != 0) {
    425         return TRUE;
    426     } 
    427     
    428     return FALSE;
    429 }
    430 
    431 STATIC int 
    432 _bcm_kt_cosq_max_nodes_get(int unit, _bcm_kt_cosq_node_level_t level,
    433                            int *id)
    434 {
    435     _bcm_kt_mmu_info_t *mmu_info;
    436 
    437     if (level < _BCM_KT_COSQ_NODE_LEVEL_ROOT ||
    438         level >= _BCM_KT_COSQ_NODE_LEVEL_MAX) {
    439         return BCM_E_PARAM;
    440     }
    441     mmu_info = _bcm_kt_mmu_info[unit];
    442     *id = mmu_info->max_nodes[level];
    443 
    444     return BCM_E_NONE;
    445 }
    446 
    447 /*
    448  * Function:
    449  *     _bcm_kt_cosq_alloc_clear
    450  * Purpose:
    451  *     Allocate cosq memory and clear
    452  * Parameters:
    453  *     size       - (IN) size of memory required
    454  *     description- (IN) description about the structure
    455  * Returns:
    456  *     BCM_E_XXX
    457  */
    458 STATIC void *
    459 _bcm_kt_cosq_alloc_clear(unsigned int size, char *description)
    460 {
    461     void *block_p;
    462 
    463     block_p = sal_alloc(size, description);
    464 
    465     if (block_p != NULL) {
    466         sal_memset(block_p, 0, size);
    467     }
    468 
    469     return block_p;
    470 }
    471 
    472 /*
    473  * Function:
    474  *     _bcm_kt_cosq_free_memory
    475  * Purpose:
    476  *     Free memory allocated for mmu info members
    477  * Parameters:
    478  *     mmu_info_p       - (IN) MMU info pointer
    479  * Returns:
    480  *     BCM_E_XXX
    481  */
    482 STATIC void
    483 _bcm_kt_cosq_free_memory(_bcm_kt_mmu_info_t *mmu_info_p)
    484 {
    485     sal_free(mmu_info_p->port);
    486     sal_free(mmu_info_p->l1_gport_pair);
    487     sal_free(mmu_info_p->ext_qlist.bits);
    488     sal_free(mmu_info_p->sched_list.bits);
    489     sal_free(mmu_info_p->l0_sched_list.bits);
    490     sal_free(mmu_info_p->l1_sched_list.bits);
    491     sal_free(mmu_info_p->l2_base_qlist.bits);
    492     sal_free(mmu_info_p->l2_ext_qlist.bits);
    493 
    494     if (mmu_info_p->sub_qlist.bits != NULL) {
    495         sal_free(mmu_info_p->sub_qlist.bits);
    496     }
    497     if (mmu_info_p->l2_sub_qlist.bits != NULL) {
    498         sal_free(mmu_info_p->l2_sub_qlist.bits);
    499     }
    500 }
    501 
    502 /*
    503  * Function:
    504  *     _bcm_kt_cosq_node_get
    505  * Purpose:
    506  *     Get internal information of queue group or scheduler type GPORT
    507  * Parameters:
    508  *     unit       - (IN) unit number
    509  *     gport      - (IN) queue group/scheduler GPORT identifier
    510  *     modid      - (OUT) module identifier
    511  *     port       - (OUT) port number
    512  *     id         - (OUT) queue group or scheduler identifier
    513  *     node       - (OUT) node structure for the specified GPORT
    514  * Returns:
    515  *     BCM_E_XXX
    516  */
    517 STATIC int
    518 _bcm_kt_cosq_node_get(int unit, bcm_gport_t gport, bcm_module_t *modid,
    519                       bcm_port_t *port, int *id, _bcm_kt_cosq_node_t **node)
    520 {
    521     soc_info_t *si;
    522     _bcm_kt_mmu_info_t *mmu_info;
    523     _bcm_kt_cosq_node_t *node_base;
    524     bcm_module_t modid_out = 0;
    525     bcm_port_t port_out = 0;
    526     uint32 encap_id = 0;
    527     int index;
    528 
    529     si = &SOC_INFO(unit);
    530 
    531     if (_bcm_kt_mmu_info[unit] == NULL) {
    532         return BCM_E_INIT;
    533     }
    534 
    535     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
    536         BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid_out));
    537         port_out = BCM_GPORT_UCAST_QUEUE_GROUP_SYSPORTID_GET(gport);
    538     } else if (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport)) {
    539         BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid_out));
    540         port_out = BCM_GPORT_UCAST_SUBSCRIBER_QUEUE_GROUP_SYSPORTID_GET(gport);
    541     } else if (BCM_GPORT_IS_SCHEDULER(gport)) {
    542         BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid_out));
    543         port_out = BCM_GPORT_SCHEDULER_GET(gport) & 0xff;
    544     } else if (BCM_GPORT_IS_LOCAL(gport)) {
    545         encap_id = BCM_GPORT_LOCAL_GET(gport);
    546         port_out = encap_id;
    547     } else if (BCM_GPORT_IS_MODPORT(gport)) {
    548         /* get the local_port */
    549         BCM_IF_ERROR_RETURN(
    550            _bcm_kt_cosq_localport_resolve(unit, gport, &port_out));
    551         encap_id = port_out;
    552     } else {
    553         return BCM_E_PORT;
    554     }
    555 
    556     /* Below SOC check is used for time-being for KT2 */
    557     if (SOC_IS_KATANA(unit)) {
    558         if (!SOC_PORT_VALID(unit, port_out)) {
    559             return BCM_E_PORT;
    560         }
    561     }
    562 
    563     mmu_info = _bcm_kt_mmu_info[unit];
    564 
    565     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
    566         encap_id = BCM_GPORT_UCAST_QUEUE_GROUP_QID_GET(gport);
    567         index = encap_id;
    568         if (index < mmu_info->num_base_queues) {
    569             node_base = mmu_info->queue_node;
    570         } else {
    571             if (si->port_num_ext_cosq[port_out] == 0) {
    572                 return BCM_E_PORT;
    573             }
    574             node_base = mmu_info->queue_node;
    575         }
    576     } else if (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport)) {
    577         encap_id = BCM_GPORT_UCAST_SUBSCRIBER_QUEUE_GROUP_QID_GET(gport);
    578         index = encap_id;
    579         if (mmu_info->num_sub_queues > 0) {
    580             index += mmu_info->base_sub_queue;
    581         } else {
    582             index += mmu_info->num_base_queues;
    583         }
    584         node_base = mmu_info->queue_node;
    585     }
    586     else { 
    587         if (BCM_GPORT_IS_SCHEDULER(gport)) {
    588             /* scheduler */
    589             encap_id = (BCM_GPORT_SCHEDULER_GET(gport) >> 8) & 0x7ff;
    590             if (encap_id == 0) {
    591                 encap_id = (BCM_GPORT_SCHEDULER_GET(gport) & 0xff);
    592             }
    593         }
    594         index = encap_id;
    595         if (index >= _BCM_KT_NUM_TOTAL_SCHEDULERS) {
    596             return BCM_E_PORT;
    597         }
    598         node_base = mmu_info->sched_node;
    599     }
    600 
    601     if (!(BCM_GPORT_IS_LOCAL(gport) || BCM_GPORT_IS_MODPORT(gport)) &&
    602          node_base[index].numq == 0) {
    603         return BCM_E_NOT_FOUND;
    604     }
    605 
    606     if (modid != NULL) {
    607         *modid = modid_out;
    608     }
    609     if (port != NULL) {
    610         *port = port_out;
    611     }
    612     if (id != NULL) {
    613         *id = encap_id;
    614     }
    615     if (node != NULL) {
    616         *node = &node_base[index];
    617     }
    618 
    619     return BCM_E_NONE;
    620 }
    621 
    622 int
    623 _bcm_kt_cosq_port_resolve(int unit, bcm_gport_t gport, bcm_module_t *modid,
    624                           bcm_port_t *port, bcm_trunk_t *trunk_id, int *id,
    625                           int *qnum)
    626 {
    627     _bcm_kt_cosq_node_t *node;
    628 
    629     BCM_IF_ERROR_RETURN
    630         (_bcm_kt_cosq_node_get(unit, gport, modid, port, NULL, &node));
    631     *trunk_id = -1;
    632 
    633     if (qnum) {
    634         if (node->hw_index == -1) {
    635             return BCM_E_PARAM;
    636         }
    637         *qnum = node->hw_index;
    638     }
    639 
    640     return BCM_E_NONE;
    641 }
    642 
    643 /*
    644  * Function:
    645  *     _bcm_kt_cosq_gport_traverse
    646  * Purpose:
    647  *     Walks through the valid COSQ GPORTs and calls
    648  *     the user supplied callback function for each entry.
    649  * Parameters:
    650  *     unit       - (IN) unit number
    651  *     gport      - (IN)
    652  *     cb         - (IN) Callback function.
    653  *     user_data  - (IN) User data to be passed to callback function
    654  * Returns:
    655  *     BCM_E_NONE - Success.
    656  *     BCM_E_XXX
    657  */
    658 int
    659 _bcm_kt_cosq_gport_traverse(int unit, bcm_gport_t gport,
    660                             bcm_cosq_gport_traverse_cb cb,
    661                             void *user_data)
    662 {
    663     _bcm_kt_cosq_node_t *node;
    664     uint32 flags = BCM_COSQ_GPORT_SCHEDULER;
    665     int rv = BCM_E_NONE;
    666 
    667     BCM_IF_ERROR_RETURN
    668         (_bcm_kt_cosq_node_get(unit, gport, NULL, NULL, NULL, &node));
    669 
    670     if (node != NULL) {
    671        if (node->level == _BCM_KT_COSQ_NODE_LEVEL_L2) {
    672           flags = BCM_GPORT_IS_UCAST_QUEUE_GROUP(node->gport) ?
    673                   BCM_COSQ_GPORT_UCAST_QUEUE_GROUP :
    674                   BCM_COSQ_GPORT_SUBSCRIBER;
    675        }
    676        rv = cb(unit, gport, node->numq, flags,
    677                   node->gport, user_data);
    678        if (BCM_FAILURE(rv)) {
    679 #ifdef BCM_CB_ABORT_ON_ERR
    680            if (SOC_CB_ABORT_ON_ERR(unit)) {
    681                return rv;
    682            }
    683 #endif
    684        }
    685     } else {
    686             return BCM_E_NONE;
    687     }
    688 
    689     if (node->sibling != NULL) {
    690         _bcm_kt_cosq_gport_traverse(unit, node->sibling->gport, cb, user_data);
    691     }
    692 
    693     if (node->child != NULL) {
    694         _bcm_kt_cosq_gport_traverse(unit, node->child->gport, cb, user_data);
    695     }
    696 
    697     return BCM_E_NONE;
    698 }
    699 
    700 /*
    701  * Function:
    702  *     _bcm_kt_cosq_index_resolve
    703  * Purpose:
    704  *     Find hardware index for the given port/cosq
    705  * Parameters:
    706  *     unit       - (IN) unit number
    707  *     port       - (IN) port number or GPORT identifier
    708  *     cosq       - (IN) COS queue number
    709  *     style      - (IN) index style (_BCM_KA_COSQ_INDEX_STYLE_XXX)
    710  *     local_port - (OUT) local port number
    711  *     index      - (OUT) result index
    712  *     count      - (OUT) number of index
    713  * Returns:
    714  *     BCM_E_XXX
    715  */
    716 int
    717 _bcm_kt_cosq_index_resolve(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
    718                            _bcm_kt_cosq_index_style_t style,
    719                            bcm_port_t *local_port, int *index, int *count)
    720 {
    721     _bcm_kt_cosq_node_t *node, *cur_node;
    722     bcm_port_t resolved_port;
    723     int resolved_index;
    724     int id, startq, numq = 0;
    725     _bcm_kt_mmu_info_t *mmu_info;
    726 
    727     if (cosq < -1) {
    728         return BCM_E_PARAM;
    729     } else if (cosq == -1) {
    730         startq = 0;
    731     } else {
    732         startq = cosq;
    733     }
    734 
    735     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
    736         BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port) || 
    737         BCM_GPORT_IS_SCHEDULER(port)) {
    738         BCM_IF_ERROR_RETURN
    739             (_bcm_kt_cosq_node_get(unit, port, NULL, &resolved_port, &id,
    740                                    &node));
    741         if ((node->cosq_attached_to < 0) || (node->hw_index == -1)) {
    742             /* Not resolved yet */
    743             return BCM_E_NOT_FOUND;
    744         }
    745         if (BCM_GPORT_IS_SCHEDULER(port) && 
    746              (style != _BCM_KT_COSQ_INDEX_STYLE_BUCKET)) {
    747             numq = node->numq;
    748             if (startq >= numq) {
    749                 return BCM_E_PARAM;
    750             }
    751         } 
    752         else {
    753              numq=node->numq;
    754         }    
    755     } else {
    756         /* optionally validate port */
    757         BCM_IF_ERROR_RETURN
    758             (_bcm_kt_cosq_localport_resolve(unit, port, &resolved_port));
    759         if (resolved_port < 0) {
    760             return BCM_E_PORT;
    761         }
    762         node = NULL;
    763         numq = 0;
    764     }
    765 
    766     switch (style) {
    767     case _BCM_KT_COSQ_INDEX_STYLE_BUCKET:
    768         if (node != NULL) {
    769             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
    770                 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port)) {
    771                 resolved_index = node->hw_index;
    772             } else if (BCM_GPORT_IS_SCHEDULER(port)) {
    773                 if (node->level > _BCM_KT_COSQ_NODE_LEVEL_L1) {
    774                     return BCM_E_PARAM;
    775                 }
    776                 resolved_index = node->hw_index;
    777             } else {
    778                     return BCM_E_PARAM;
    779             }
    780         } else { /* node == NULL */
    781             mmu_info = _bcm_kt_mmu_info[unit];
    782             numq = mmu_info->port[resolved_port].q_limit - 
    783                     mmu_info->port[resolved_port].q_offset;
    784             
    785             if (cosq >= numq) {
    786                 return BCM_E_PARAM;
    787             }
    788             resolved_index = mmu_info->port[resolved_port].q_offset + startq;
    789         }
    790         break;
    791 
    792     case _BCM_KT_COSQ_INDEX_STYLE_WRED:
    793         if (node != NULL) {
    794             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
    795                 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port)) {
    796                 resolved_index = node->hw_index;
    797             } else if (BCM_GPORT_IS_SCHEDULER(port)) {
    798                 if (node->level != _BCM_KT_COSQ_NODE_LEVEL_L1) {
    799                     return BCM_E_PARAM;
    800                 }
    801                 resolved_index = node->hw_index;
    802             } else {
    803                     return BCM_E_PARAM;
    804             }
    805         } else { /* node == NULL */
    806             mmu_info = _bcm_kt_mmu_info[unit];
    807             numq = mmu_info->port[resolved_port].q_limit - 
    808                    mmu_info->port[resolved_port].q_offset;
    809 
    810             if (cosq >= numq) {
    811                 return BCM_E_PARAM;
    812             }
    813             resolved_index = mmu_info->port[resolved_port].q_offset + startq;
    814         }
    815         break;
    816 
    817     case _BCM_KT_COSQ_INDEX_STYLE_SCHEDULER:
    818         if (node != NULL) {
    819             if (BCM_GPORT_IS_SCHEDULER(port)) {
    820                 for (cur_node = node->child; cur_node != NULL;
    821                     cur_node = cur_node->sibling) {
    822                     if (cur_node->cosq_attached_to == startq) {
    823                         break;
    824                     }
    825                 }
    826 
    827                 if (cur_node == NULL) {
    828                     /* this cosq is not yet attached */
    829                     return BCM_E_INTERNAL;
    830                 }
    831 
    832                 if (node->numq <= 8) {
    833                     resolved_index = node->base_index + startq;
    834                 } else {
    835                     resolved_index = cur_node->hw_index;
    836                 } 
    837             } else { /* unicast queue group or multicast queue group */
    838                 return BCM_E_PARAM;
    839             }
    840         } else { /* node == NULL */
    841             mmu_info = _bcm_kt_mmu_info[unit];
    842             numq = mmu_info->port[resolved_port].q_limit -
    843                    mmu_info->port[resolved_port].q_offset;
    844 
    845             if (cosq >= numq) {
    846                 return BCM_E_PARAM;
    847             }
    848             resolved_index = mmu_info->port[resolved_port].q_offset + startq;
    849         }
    850         break;
    851     case _BCM_KT_COSQ_INDEX_STYLE_UCAST_QUEUE:
    852         mmu_info = _bcm_kt_mmu_info[unit];
    853         if (node != NULL) {
    854             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
    855                 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port)) {
    856                 resolved_index = node->hw_index;
    857             } else if (BCM_GPORT_IS_SCHEDULER(port)) {
    858                 if (node->level != _BCM_KT_COSQ_NODE_LEVEL_L1) {
    859                     return BCM_E_PARAM;
    860                 }
    861                 resolved_index = node->base_index;
    862             } else {
    863                 return BCM_E_PARAM;
    864             }
    865             
    866             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) {
    867                 resolved_index -= mmu_info->port[resolved_port].q_offset;
    868             }
    869         } else { /* node == NULL */
    870             mmu_info = _bcm_kt_mmu_info[unit];
    871             numq = mmu_info->port[resolved_port].q_limit -
    872                    mmu_info->port[resolved_port].q_offset;
    873 
    874             if (startq >= numq) {
    875                 return BCM_E_PARAM;
    876             }
    877             resolved_index = startq;        
    878         }
    879         break;
    880     case _BCM_KT_COSQ_INDEX_STYLE_QUEUE_REPLICATION:
    881             mmu_info = _bcm_kt_mmu_info[unit];
    882             if (node != NULL) {
    883                 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
    884                     BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port)) {
    885                     resolved_index = node->hw_index;
    886                 } else {
    887                     return BCM_E_PARAM;
    888                 }
    889                 
    890             } else { /* node == NULL */
    891                 mmu_info = _bcm_kt_mmu_info[unit];
    892                 numq = mmu_info->port[resolved_port].q_limit -
    893                        mmu_info->port[resolved_port].q_offset;
    894    
    895                if (startq >= numq) {
    896                    return BCM_E_PARAM;
    897                }
    898                resolved_index = startq + mmu_info->port
    899                                         [resolved_port].q_offset;        
    900            }
    901             break;
    902     default:
    903         return BCM_E_INTERNAL;
    904     }
    905 
    906     if (local_port != NULL) {
    907         *local_port = resolved_port;
    908     }
    909     if (index != NULL) {
    910         *index = resolved_index;
    911     }
    912     if (count != NULL) {
    913         *count = (cosq == -1) ? numq : 1;
    914     }
    915 
    916     return BCM_E_NONE;
    917 }
    918 
    919 int 
    920 bcm_kt_sw_hw_queue(int unit, int *queue_array)
    921 {
    922     _bcm_kt_mmu_info_t *mmu_info;
    923     int index = 0;
    924     mmu_info = _bcm_kt_mmu_info[unit];
    925     
    926     for (index = 0; index < mmu_info->num_queues; index++){
    927         if (mmu_info->queue_node[index].hw_index == *queue_array){
    928             *queue_array = index;
    929             return BCM_E_NONE;
    930         }        
    931     }
    932     index = -1;
    933     return BCM_E_PARAM;
    934 }
    935 
    936 int
    937 bcm_kt_is_uc_queue(int unit,int queue_id,int *is_ucq)
    938 {
    939     _bcm_kt_mmu_info_t *mmu_info;
    940     mmu_info = _bcm_kt_mmu_info[unit];
    941    
    942     if(_BCM_KT_IS_UC_QUEUE(mmu_info, queue_id)) 
    943     {
    944       *is_ucq = TRUE;
    945     }
    946     else 
    947     {
    948       *is_ucq = FALSE  ;
    949     }
    950     return BCM_E_NONE;
    951 }
    952 /*
    953  * Function:
    954  *     _bcm_kt_cosq_node_resolve
    955  * Purpose:
    956  *     Resolve queue number in the specified scheduler tree and its subtree
    957  * Parameters:
    958  *     unit       - (IN) unit number
    959  *     node       - (IN) node structure for the specified scheduler node
    960  *     cosq       - (IN) COS queue to attach to
    961  * Returns:
    962  *     BCM_E_XXX
    963  */
    964 STATIC int
    965 _bcm_kt_cosq_node_resolve(int unit, _bcm_kt_cosq_node_t *node,
    966                           bcm_cos_queue_t cosq)
    967 {
    968     _bcm_kt_cosq_node_t *parent;
    969     _bcm_kt_mmu_info_t *mmu_info;
    970     _bcm_kt_cosq_list_t *list;
    971     bcm_port_t local_port;
    972     int alloc_size;
    973     int numq, id = 0;
    974     int offset, limit;
    975 
    976     parent = node->parent;
    977     if (parent == NULL) {
    978         /* Not attached, should never happen */
    979         return BCM_E_NOT_FOUND;
    980     }
    981 
    982     if (parent->numq == 0 || parent->numq < -1) {
    983         return BCM_E_PARAM;
    984     }
    985 
    986     if (parent->cosq_map == NULL) {
    987         alloc_size = SHR_BITALLOCSIZE(parent->numq);
    988         parent->cosq_map = _bcm_kt_cosq_alloc_clear(alloc_size,
    989                                            "cosq_map");
    990         if (parent->cosq_map == NULL) {
    991             return BCM_E_MEMORY;
    992         }
    993     }
    994 
    995     if (cosq < 0) {
    996         BCM_IF_ERROR_RETURN
    997             (_bcm_kt_cosq_map_index_get(parent->cosq_map,
    998                                         0, parent->numq, &id));    
    999         BCM_IF_ERROR_RETURN
   1000             (_bcm_kt_cosq_map_index_set(parent->cosq_map, id, 1));
   1001         node->cosq_attached_to = id;
   1002     } else {
   1003         if (_bcm_kt_cosq_map_index_is_set(parent->cosq_map, 
   1004                                   cosq) == TRUE) {
   1005             return BCM_E_EXISTS;
   1006         }
   1007         BCM_IF_ERROR_RETURN
   1008             (_bcm_kt_cosq_map_index_set(parent->cosq_map,cosq, 1));
   1009         node->cosq_attached_to = cosq;
   1010     }   
   1011  
   1012     mmu_info = _bcm_kt_mmu_info[unit];
   1013     numq = (parent->numq > 8) ? 8 : parent->numq;
   1014 
   1015     switch (parent->level) {
   1016         case _BCM_KT_COSQ_NODE_LEVEL_ROOT:
   1017             list = &mmu_info->l0_sched_list;
   1018             if (parent->base_index < 0) {
   1019                 BCM_IF_ERROR_RETURN
   1020                     (_bcm_kt_node_index_get(unit, list->bits, 0, mmu_info->max_nodes[node->level],
   1021                                     mmu_info->qset_size, numq, &id));
   1022                 _bcm_kt_node_index_set(list, id, numq);
   1023                 parent->base_index = id;
   1024                 
   1025             } else if (node->cosq_attached_to >= 8) {
   1026                 BCM_IF_ERROR_RETURN
   1027                     (_bcm_kt_node_index_get(unit, list->bits, 0, mmu_info->max_nodes[node->level],
   1028                                     mmu_info->qset_size, 1, &id));
   1029                 _bcm_kt_node_index_set(list, id, 1);
   1030 
   1031             }    
   1032             break;
   1033 
   1034         case _BCM_KT_COSQ_NODE_LEVEL_L0:
   1035             list = &mmu_info->l1_sched_list;
   1036             if (parent->base_index < 0) {
   1037                 BCM_IF_ERROR_RETURN
   1038                     (_bcm_kt_node_index_get(unit, list->bits, 0, mmu_info->max_nodes[node->level],
   1039                                     mmu_info->qset_size, numq, &id));
   1040                 _bcm_kt_node_index_set(list, id, numq);
   1041                 parent->base_index = id;
   1042             } else if (node->cosq_attached_to >= 8) {
   1043                 BCM_IF_ERROR_RETURN
   1044                     (_bcm_kt_node_index_get(unit, list->bits, 0, mmu_info->max_nodes[node->level],
   1045                                     mmu_info->qset_size, 1, &id));
   1046                 _bcm_kt_node_index_set(list, id, 1);
   1047 
   1048             }            
   1049             break;
   1050 
   1051         case _BCM_KT_COSQ_NODE_LEVEL_L1:
   1052             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(node->gport)) {
   1053                 list = &mmu_info->l2_base_qlist;
   1054                 local_port = BCM_GPORT_UCAST_QUEUE_GROUP_SYSPORTID_GET(node->gport);
   1055                 offset = mmu_info->port[local_port].q_offset;
   1056                 limit =  mmu_info->port[local_port].q_limit;
   1057             }  else if (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(node->gport)) {
   1058                 local_port = BCM_GPORT_UCAST_SUBSCRIBER_QUEUE_GROUP_SYSPORTID_GET
   1059                                                          (node->gport);
   1060                 offset = 0;
   1061                 if (mmu_info->num_sub_queues > 0) {
   1062                     list = &mmu_info->l2_sub_qlist;
   1063                     limit = mmu_info->num_sub_queues;
   1064                 } else {
   1065                     list = &mmu_info->l2_ext_qlist;
   1066                     limit = mmu_info->num_ext_queues;
   1067                 }
   1068             } else {
   1069                 list = &mmu_info->l2_ext_qlist;
   1070                 offset = 0;
   1071                 limit = mmu_info->num_ext_queues;
   1072             }
   1073             if (node->cosq_attached_to >= 8) {
   1074                 numq = 1;
   1075             }    
   1076 
   1077             if (node->hw_index < 0) {
   1078                 if ((BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(node->gport)) &&
   1079                            (parent->base_index < 0) &&
   1080                            (node->cosq_attached_to < 8)) {
   1081                     BCM_IF_ERROR_RETURN
   1082                         (_bcm_kt_node_index_get(unit, list->bits, offset, limit,
   1083                                                  mmu_info->qset_size, numq, &id));
   1084 
   1085                     _bcm_kt_node_index_set(list, id, numq);
   1086                     if (mmu_info->num_sub_queues > 0) {
   1087                         parent->base_index = id + mmu_info->base_sub_queue ;
   1088                     } else {
   1089                         parent->base_index = id + mmu_info->num_base_queues ;
   1090                     }
   1091                     node->base_index = parent->base_index;
   1092                 } else if((parent->base_index < 0) && (node->cosq_attached_to < 8)) {
   1093                     BCM_IF_ERROR_RETURN
   1094                         (_bcm_kt_node_index_get(unit, list->bits, offset, limit,
   1095                                                 mmu_info->qset_size, numq, &id));
   1096                     _bcm_kt_node_index_set(list, id, numq);
   1097                     parent->base_index = (BCM_GPORT_IS_UCAST_QUEUE_GROUP(node->gport)) ? id :
   1098                                          (id + mmu_info->num_base_queues);
   1099                     node->base_index = parent->base_index;  
   1100                 } else if (node->cosq_attached_to >= 8) {
   1101                     BCM_IF_ERROR_RETURN
   1102                         (_bcm_kt_node_index_get(unit, list->bits, offset, limit,
   1103                                                 mmu_info->qset_size, numq, &id));
   1104                     _bcm_kt_node_index_set(list, id, numq);
   1105                 }
   1106                 if (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(node->gport)) {
   1107                     if (mmu_info->num_sub_queues > 0) {
   1108                         id += mmu_info->base_sub_queue ;
   1109                     } else {
   1110                         id += mmu_info->num_base_queues;
   1111                     }
   1112                 } else {
   1113                     id += (BCM_GPORT_IS_UCAST_QUEUE_GROUP(node->gport)) ?
   1114                        0 : mmu_info->num_base_queues;    
   1115                 }
   1116             } else {
   1117                 if (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(node->gport)) {
   1118                     /* Input 0 should be atttached
   1119                      * first to get the correct base
   1120                      */
   1121                     if (node->cosq_attached_to < 8) {
   1122                         if ((BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(node->gport)) &&
   1123                             parent->base_index < 0) {
   1124                             parent->base_index = node->hw_index;
   1125                         }
   1126                     }
   1127                 }
   1128             }
   1129             break;
   1130 
   1131         case _BCM_KT_COSQ_NODE_LEVEL_L2:
   1132             /* passthru */
   1133         default:
   1134             return BCM_E_PARAM;
   1135 
   1136     }
   1137 
   1138     if (parent->numq <= 8) {
   1139         if (parent->level <= _BCM_KT_COSQ_NODE_LEVEL_L1) {
   1140             if (node->hw_index < 0) {
   1141                 node->hw_index = parent->base_index + node->cosq_attached_to;
   1142             }    
   1143         }
   1144 
   1145         parent->num_child++;
   1146         /* get the lowest cosq as a first child */
   1147         if (node->hw_index < parent->first_child) {
   1148             parent->first_child = node->hw_index;
   1149         }
   1150     } else {
   1151         if (parent->level <= _BCM_KT_COSQ_NODE_LEVEL_L1) {
   1152             if (node->hw_index < 0) {
   1153                 node->hw_index = (node->cosq_attached_to < 8) ? 
   1154                     (parent->base_index + node->cosq_attached_to) : id;
   1155             }
   1156             if (node->cosq_attached_to >= 8) {
   1157                 node->wrr_in_use = 1;
   1158             }    
   1159         }
   1160         parent->num_child++;
   1161     }
   1162 
   1163     return BCM_E_NONE;
   1164 }
   1165 
   1166 /*
   1167  * Function:
   1168  *     _bcm_kt_cosq_node_unresolve
   1169  * Purpose:
   1170  *     Unresolve queue number in the specified scheduler tree and its subtree
   1171  * Parameters:
   1172  *     unit       - (IN) unit number
   1173  *     node       - (IN) node structure for the specified scheduler node
   1174  *     cosq       - (IN) COS queue to attach to
   1175  * Returns:
   1176  *     BCM_E_XXX
   1177  */
   1178 STATIC int
   1179 _bcm_kt_cosq_node_unresolve(int unit, _bcm_kt_cosq_node_t *node, bcm_cos_queue_t cosq)
   1180 {
   1181     _bcm_kt_cosq_node_t *cur_node, *parent;
   1182     _bcm_kt_mmu_info_t *mmu_info;
   1183     _bcm_kt_cosq_list_t *list;
   1184     uint32 map;
   1185     int min_index;
   1186     int id, offset, numq;
   1187     int min_flag = 0;
   1188 
   1189     if (node->cosq_attached_to < 0) {
   1190         /* Has been unresolved already */
   1191         return BCM_E_NONE;
   1192     }
   1193 
   1194     parent = node->parent;
   1195 
   1196     if (parent->numq == 0 || parent->numq < -1) {
   1197         return BCM_E_PARAM;
   1198     }
   1199 
   1200     if (parent->numq <= 8) {
   1201          /* find the current cosq_attached_to usage */
   1202         map = 0;
   1203         if (parent->first_child == node->hw_index && node->wrr_in_use == 0) {
   1204             min_flag = 1;
   1205             min_index = (node->level == _BCM_KT_COSQ_NODE_LEVEL_L2) ? 4095 :
   1206                         ((node->level == _BCM_KT_COSQ_NODE_LEVEL_L1) ? 1023 : 255);
   1207         } else {
   1208             min_index = parent->first_child;
   1209         }
   1210 
   1211         for (cur_node = parent->child; cur_node != NULL;
   1212             cur_node = cur_node->sibling) {
   1213             if (cur_node->cosq_attached_to >= 0) {
   1214                 map |= 1 << cur_node->cosq_attached_to;
   1215                 /* dont update the min node is not this node */
   1216                 if (min_flag && cur_node->hw_index != node->hw_index) {
   1217                 if (cur_node->hw_index < min_index) {
   1218                     min_index = cur_node->hw_index;
   1219                 }
   1220                }
   1221             }
   1222         }
   1223 
   1224         if (!(map & (1 << node->cosq_attached_to))) {
   1225             return BCM_E_PARAM;
   1226         }
   1227 
   1228         BCM_IF_ERROR_RETURN
   1229             (_bcm_kt_cosq_map_index_clear(parent->cosq_map, 
   1230              node->cosq_attached_to, 1));
   1231         parent->first_child = min_index;
   1232 
   1233     } else {
   1234 
   1235         /* check whether the entry is available */
   1236         for (cur_node = parent->child; cur_node != NULL;
   1237             cur_node = cur_node->sibling) {
   1238             if (cur_node->gport == node->gport) {
   1239                 break;
   1240             }
   1241         }
   1242 
   1243         if (cur_node == NULL) {
   1244             return BCM_E_PARAM;
   1245         }
   1246         BCM_IF_ERROR_RETURN
   1247             (_bcm_kt_cosq_map_index_clear(parent->cosq_map, 
   1248              cur_node->cosq_attached_to, 1));
   1249     }
   1250 
   1251     mmu_info = _bcm_kt_mmu_info[unit];
   1252     numq = (parent->numq > 8) ? 8 : parent->numq;
   1253 
   1254     switch (parent->level) {
   1255         case _BCM_KT_COSQ_NODE_LEVEL_ROOT:
   1256             list = &mmu_info->l0_sched_list;
   1257             parent->num_child--;
   1258             if (parent->num_child >= 0) {
   1259                 if (node->cosq_attached_to >= 8) {
   1260                     _bcm_kt_node_index_clear(list, node->hw_index, 1);
   1261                 } 
   1262                 if (parent->num_child == 0 &&
   1263                     parent->base_index >= 0) {
   1264                     /* release contiguous queue ids */
   1265                     _bcm_kt_node_index_clear(list, parent->base_index, numq);
   1266                     parent->base_index = -1;
   1267                 }
   1268             } 
   1269             break;
   1270 
   1271         case _BCM_KT_COSQ_NODE_LEVEL_L0:
   1272             list = &mmu_info->l1_sched_list;
   1273             parent->num_child--;
   1274             if (parent->num_child >= 0) {
   1275                 if (node->cosq_attached_to >= 8) {
   1276                     _bcm_kt_node_index_clear(list, node->hw_index, 1);
   1277                 } 
   1278                 if (parent->num_child == 0 &&
   1279                     parent->base_index >= 0) {
   1280                     /* release contiguous queue ids */
   1281                     _bcm_kt_node_index_clear(list, parent->base_index, numq);
   1282                     parent->base_index = -1;
   1283                 }
   1284             } 
   1285             break;
   1286 
   1287         case _BCM_KT_COSQ_NODE_LEVEL_L1:
   1288             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(node->gport)) {
   1289                 list = &mmu_info->l2_base_qlist;
   1290                 offset = 0;
   1291             } else if (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(node->gport)
   1292                        && (mmu_info->num_sub_queues > 0)) {
   1293                 list = &mmu_info->l2_sub_qlist;
   1294                 offset = mmu_info->base_sub_queue;
   1295             } else {
   1296                 list = &mmu_info->l2_ext_qlist;
   1297                 offset = mmu_info->num_base_queues;
   1298             }
   1299             parent->num_child--;
   1300             id = node->hw_index - offset;
   1301             if (parent->num_child >= 0) {
   1302                 if (node->cosq_attached_to >= 8) {
   1303                     _bcm_kt_node_index_clear(list, id, 1);
   1304                 } 
   1305                 if (parent->num_child == 0 &&
   1306                     parent->base_index >= 0) {
   1307                     /* release contiguous queue ids */
   1308                     id = parent->base_index - offset;
   1309                     _bcm_kt_node_index_clear(list, id, numq);
   1310                     parent->base_index = -1;
   1311                 }
   1312             } 
   1313             break;
   1314 
   1315         case _BCM_KT_COSQ_NODE_LEVEL_L2:
   1316             /* passthru */
   1317         default:
   1318             return BCM_E_PARAM;
   1319 
   1320     }
   1321 
   1322     return BCM_E_NONE;
   1323 }
   1324 
   1325 STATIC int
   1326 _bcm_kt_cosq_valid_werr_node(int unit, _bcm_kt_cosq_node_t *node, 
   1327                                     int cosq, int spri)
   1328 {
   1329     _bcm_kt_cosq_node_t *cur_node;
   1330     uint8 spri_vector = 0;
   1331     uint8 mask, mask_lower, mask_upper;
   1332 
   1333     if (cosq >= 8) {
   1334         return 1;
   1335     }    
   1336     for (cur_node = node->child; cur_node != NULL;
   1337          cur_node = cur_node->sibling) {
   1338          if ((cur_node->cosq_attached_to < 8) && (cur_node->wrr_in_use == 0)) {
   1339              spri_vector |= (1 << cur_node->cosq_attached_to);   
   1340          }
   1341     }
   1342     mask_lower = ~(0xFF << cosq);
   1343     mask_upper =  0xFF << (cosq + 1);
   1344 
   1345     if ((spri_vector & mask_lower) && (spri_vector & mask_upper)) {
   1346         /* if queues are not contiguous return invalid */
   1347         return 0;
   1348     }    
   1349    
   1350     if (((spri_vector & mask_lower) == 0) && ((spri_vector & mask_upper) != 0)) {
   1351         mask = spri_vector & mask_upper; 
   1352         if ((spri == 0) || (mask & (1 << (cosq + 1)))) {
   1353             /* check the next queue also in spri if cosq is spri */
   1354             return 1;    
   1355         }
   1356     } else if (((spri_vector & mask_lower) != 0) && ((spri_vector & mask_upper) == 0)) {
   1357         mask = spri_vector & mask_lower;
   1358         if ((spri == 0) || (mask & (1 << (cosq - 1)))) {
   1359             /* check previous queue also in spri if cosq is spri */
   1360             return 1;
   1361         }    
   1362    } else {
   1363        /* this is the first queue */
   1364        return 1; 
   1365    }
   1366           
   1367    return 0;
   1368 }
   1369 
   1370 STATIC int 
   1371 _bcm_kt_cosq_dynamic_bw_update(int unit, soc_mem_t config_mem, 
   1372                                int index, int hw_index, 
   1373                                lls_l2_shaper_config_lower_entry_t l2_shaper_entry)
   1374 {
   1375     soc_mem_t bucket_mem;
   1376     lls_l2_shaper_bucket_lower_entry_t l2_bucket_max_entry;
   1377     lls_l2_shaper_config_lower_entry_t l2_temp_entry;
   1378     uint32 i;
   1379     int rv = BCM_E_NONE;
   1380     static const soc_field_t rate_exp_fields[] = {
   1381        C_MAX_REF_RATE_EXP_0f, C_MAX_REF_RATE_EXP_1f,
   1382        C_MAX_REF_RATE_EXP_2f, C_MAX_REF_RATE_EXP_3f
   1383     };
   1384     static const soc_field_t rate_mant_fields[] = {
   1385        C_MAX_REF_RATE_MANT_0f, C_MAX_REF_RATE_MANT_1f,
   1386        C_MAX_REF_RATE_MANT_2f, C_MAX_REF_RATE_MANT_3f
   1387     };    
   1388     static const soc_field_t not_active_fields[] = {
   1389        NOT_ACTIVE_IN_LLS_0f, NOT_ACTIVE_IN_LLS_1f,
   1390        NOT_ACTIVE_IN_LLS_2f, NOT_ACTIVE_IN_LLS_3f    
   1391     };      
   1392     
   1393     /* Change L2 max shaper configuration back to original setting. */
   1394     bucket_mem = (config_mem == LLS_L2_SHAPER_CONFIG_LOWERm) ?
   1395                   LLS_L2_SHAPER_BUCKET_LOWERm :
   1396                   LLS_L2_SHAPER_BUCKET_UPPERm;
   1397     sal_memset(&l2_bucket_max_entry, 0, sizeof(lls_l2_shaper_bucket_lower_entry_t));
   1398     sal_memcpy(&l2_temp_entry, &l2_shaper_entry, 
   1399                sizeof(lls_l2_shaper_config_lower_entry_t));    
   1400     for (i = 0; i < 4; i++) {
   1401         soc_mem_field32_set(unit, config_mem, &l2_temp_entry,
   1402                         rate_exp_fields[i], 0);
   1403         soc_mem_field32_set(unit, config_mem, &l2_temp_entry,
   1404                         rate_mant_fields[i], 0);
   1405         soc_mem_field32_set(unit, bucket_mem, &l2_bucket_max_entry,
   1406                         not_active_fields[i], 1);
   1407     }    
   1408     SOC_EGRESS_METERING_LOCK(unit);
   1409     rv = soc_mem_write(unit, config_mem, MEM_BLOCK_ALL,
   1410                        index/8, &l2_temp_entry);
   1411     if (rv < 0) {
   1412         SOC_EGRESS_METERING_UNLOCK(unit);
   1413         return rv;
   1414     }
   1415 
   1416     rv = soc_mem_write(unit, bucket_mem, MEM_BLOCK_ALL,
   1417                        index/8, &l2_bucket_max_entry);
   1418     if (rv < 0) {
   1419         SOC_EGRESS_METERING_UNLOCK(unit);
   1420         return rv;
   1421     }
   1422 
   1423     rv = soc_mem_write(unit, config_mem, MEM_BLOCK_ALL,
   1424                        index/8, &l2_shaper_entry);
   1425     SOC_EGRESS_METERING_UNLOCK(unit);
   1426     return rv;
   1427 }
   1428  STATIC int
   1429  _bcm_kt_cosq_inject_max_shaper_update(int unit,_bcm_kt_cosq_node_t *node)
   1430 {
   1431 
   1432      _bcm_kt_cosq_node_t *parentl0_node = NULL;
   1433      _bcm_kt_cosq_node_t *cur_node = NULL;
   1434      uint32 rval = 0;
   1435      if((!node) || !(node->parent) ||
   1436                (node->level != _BCM_KT_COSQ_NODE_LEVEL_L2)) 
   1437      {
   1438          return BCM_E_INTERNAL; 
   1439      }
   1440      parentl0_node = node->parent->parent;
   1441      for(cur_node = parentl0_node->child ;cur_node;cur_node=cur_node->sibling) {
   1442          if(cur_node->child){
   1443             /* Inject max shaper enqueue. */
   1444             SOC_IF_ERROR_RETURN(READ_LLS_DEBUG_INJECT_ACTIVATIONr(unit, &rval));
   1445             soc_reg_field_set(unit, LLS_DEBUG_INJECT_ACTIVATIONr, &rval, INJECTf, 1);
   1446             soc_reg_field_set(unit, LLS_DEBUG_INJECT_ACTIVATIONr, &rval, ENTITY_TYPEf, 1);
   1447             soc_reg_field_set(unit, LLS_DEBUG_INJECT_ACTIVATIONr, &rval, ENTITY_LEVELf, 3);
   1448             soc_reg_field_set(unit, LLS_DEBUG_INJECT_ACTIVATIONr, &rval, ENTITY_IDENTIFIERf,
   1449                              cur_node->child->hw_index);
   1450             SOC_IF_ERROR_RETURN(WRITE_LLS_DEBUG_INJECT_ACTIVATIONr(unit, rval));
   1451          }
   1452      }
   1453      return BCM_E_NONE;
   1454  }
   1455 
   1456     
   1457 STATIC int
   1458 _bcm_kt_cosq_dynamic_sched_update(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   1459                                   int mode, _bcm_kt_cosq_node_t *node)
   1460 {
   1461     soc_timeout_t timeout;
   1462     uint32 timeout_val;
   1463     lls_l2_child_state1_entry_t l2_child_state;
   1464     lls_l1_parent_state_entry_t l1_parent_state;
   1465     lls_l2_shaper_config_lower_entry_t l2_shaper_entry_upper;
   1466     lls_l2_shaper_config_lower_entry_t l2_shaper_entry_lower;
   1467     lls_l2_shaper_config_lower_entry_t l2_temp_entry_upper; 
   1468     lls_l2_shaper_config_lower_entry_t l2_temp_entry_lower; 
   1469     lls_l2_shaper_config_lower_entry_t *entry; 
   1470     uint32 wrr0_not_empty, wrr1_not_empty;
   1471     uint32 poll_active = 1;
   1472     int parent_id, old_l1_index;
   1473     bcm_gport_t remap_gport;
   1474     _bcm_kt_mmu_info_t *mmu_info;
   1475     _bcm_kt_cosq_node_t *prev_node, *l1_node;
   1476     uint32 spare, min_list, ef_list;
   1477     bcm_port_t local_port;
   1478     int index;
   1479     int num_cos = 0;
   1480     int cos = 0;
   1481     int rv = BCM_E_NONE;
   1482     soc_mem_t config_mem, config_mem1, config_mem2;
   1483     static const soc_field_t rate_exp_fields[] = {
   1484        C_MAX_REF_RATE_EXP_0f, C_MAX_REF_RATE_EXP_1f,
   1485        C_MAX_REF_RATE_EXP_2f, C_MAX_REF_RATE_EXP_3f
   1486     };
   1487     static const soc_field_t rate_mant_fields[] = {
   1488        C_MAX_REF_RATE_MANT_0f, C_MAX_REF_RATE_MANT_1f,
   1489        C_MAX_REF_RATE_MANT_2f, C_MAX_REF_RATE_MANT_3f
   1490     };
   1491     static const soc_field_t burst_exp_fields[] = {
   1492        C_MAX_THLD_EXP_0f, C_MAX_THLD_EXP_1f,
   1493        C_MAX_THLD_EXP_2f, C_MAX_THLD_EXP_3f
   1494     };
   1495  
   1496     if (node == NULL) {
   1497         return BCM_E_INTERNAL;
   1498     }
   1499     bcm_kt_cosq_config_get(unit,&num_cos);
   1500     /* Change the max shaper configuration for the queue to minimum threshold (64B) and
   1501      * minimum rate (2kbps) 
   1502      */
   1503     BCM_IF_ERROR_RETURN
   1504         (_bcm_kt_cosq_index_resolve(unit, port, cosq,
   1505                                     _BCM_KT_COSQ_INDEX_STYLE_BUCKET,
   1506                                     &local_port, &index, NULL));
   1507     SOC_EGRESS_METERING_LOCK(unit);
   1508     config_mem1 =  LLS_L2_SHAPER_CONFIG_LOWERm;
   1509     config_mem2 =  LLS_L2_SHAPER_CONFIG_UPPERm;        
   1510     rv = soc_mem_read(unit, config_mem1, MEM_BLOCK_ALL,
   1511                       index/8, &l2_shaper_entry_lower);
   1512     if ( rv < 0 ){
   1513         SOC_EGRESS_METERING_UNLOCK(unit);
   1514         return rv;
   1515     }
   1516     rv = soc_mem_read(unit, config_mem2, MEM_BLOCK_ALL,
   1517                       index/8, &l2_shaper_entry_upper);
   1518     if ( rv < 0 ){
   1519         SOC_EGRESS_METERING_UNLOCK(unit);
   1520         return rv;
   1521     }
   1522     sal_memcpy(&l2_temp_entry_lower, &l2_shaper_entry_lower, 
   1523                sizeof(lls_l2_shaper_config_lower_entry_t)); 
   1524     sal_memcpy(&l2_temp_entry_upper, &l2_shaper_entry_upper, 
   1525                sizeof(lls_l2_shaper_config_lower_entry_t));
   1526     for(cos = 0; cos<num_cos; cos++) {
   1527         config_mem = ((cos < 4) ? LLS_L2_SHAPER_CONFIG_LOWERm :
   1528                       LLS_L2_SHAPER_CONFIG_UPPERm);
   1529         entry = ((cos < 4) ? (&l2_temp_entry_lower) : (&l2_temp_entry_upper));
   1530         soc_mem_field32_set(unit, config_mem, entry, 
   1531                                     rate_exp_fields[cos % 4], 0);
   1532         soc_mem_field32_set(unit, config_mem, entry ,
   1533                                     rate_mant_fields[cos % 4], 1); 
   1534         soc_mem_field32_set(unit, config_mem, entry, 
   1535                                     burst_exp_fields[cos % 4], 5);
   1536     }
   1537 
   1538     rv = soc_mem_write(unit, config_mem1, MEM_BLOCK_ALL,
   1539                        index/8, &l2_temp_entry_lower);
   1540     if ( rv < 0 ){
   1541         SOC_EGRESS_METERING_UNLOCK(unit);
   1542         return rv;
   1543     }
   1544     rv = soc_mem_write(unit, config_mem2, MEM_BLOCK_ALL,
   1545                        index/8, &l2_temp_entry_upper);
   1546     if ( rv < 0 ){
   1547         SOC_EGRESS_METERING_UNLOCK(unit);
   1548         return rv;
   1549     }
   1550     SOC_EGRESS_METERING_UNLOCK(unit);
   1551     /* Poll L2 child state until observe node is not active within the scheduler hierarchy.*/
   1552     timeout_val = soc_property_get(unit, spn_MMU_QUEUE_FLUSH_TIMEOUT, 20000);
   1553     soc_timeout_init(&timeout, timeout_val, 0);
   1554 
   1555     while (poll_active) {
   1556         SOC_IF_ERROR_RETURN
   1557             (READ_LLS_L2_CHILD_STATE1m(unit, MEM_BLOCK_ALL, node->hw_index,
   1558                                                   &l2_child_state));
   1559          if (SOC_MEM_FIELD_VALID(unit, LLS_L2_CHILD_STATE1m, SPAREf)) {
   1560              soc_mem_field_get(unit, LLS_L2_CHILD_STATE1m, (uint32 *)&l2_child_state,
   1561                                SPAREf, &spare);
   1562          } else {
   1563              soc_mem_field_get(unit, LLS_L2_CHILD_STATE1m, (uint32 *)&l2_child_state,
   1564                                C_ON_WERR_LISTf, &spare);
   1565          }
   1566          soc_mem_field_get(unit, LLS_L2_CHILD_STATE1m, (uint32 *)&l2_child_state, 
   1567                                         C_ON_MIN_LIST_0f, &min_list);
   1568          soc_mem_field_get(unit, LLS_L2_CHILD_STATE1m, (uint32 *)&l2_child_state, 
   1569                                         C_ON_EF_LIST_0f, &ef_list);
   1570          if (!spare && !min_list && !ef_list) {
   1571              poll_active = 0;
   1572          }
   1573          if (soc_timeout_check(&timeout)) {
   1574              BCM_IF_ERROR_RETURN
   1575              (_bcm_kt_cosq_dynamic_bw_update(unit, config_mem1, index, node->hw_index,
   1576                                                      l2_shaper_entry_lower));
   1577              BCM_IF_ERROR_RETURN
   1578              (_bcm_kt_cosq_dynamic_bw_update(unit, config_mem1, index, node->hw_index,
   1579                                                      l2_shaper_entry_upper));
   1580              BCM_IF_ERROR_RETURN
   1581              (_bcm_kt_cosq_inject_max_shaper_update(unit,node));
   1582 
   1583              LOG_ERROR(BSL_LS_BCM_COMMON,
   1584                        (BSL_META_U(unit,
   1585                                    "ERROR: Queue %d L2 child state timeout: spare %d min_list %d ef_list %d\n"), 
   1586                         node->hw_index, spare, min_list, ef_list));
   1587              return BCM_E_TIMEOUT; 
   1588          }         
   1589     }
   1590 
   1591     /* Change L2 parent to point to new L1 */
   1592     mmu_info = _bcm_kt_mmu_info[unit];
   1593     if (node->parent == NULL) {
   1594         return BCM_E_INTERNAL;
   1595     }
   1596     parent_id = (BCM_GPORT_SCHEDULER_GET(node->parent->gport) >> 8) & 0x7ff;
   1597     remap_gport = mmu_info->l1_gport_pair[parent_id];
   1598 
   1599     BCM_IF_ERROR_RETURN
   1600         (_bcm_kt_cosq_node_get(unit, node->parent->gport, NULL, NULL, NULL,
   1601                                &l1_node));
   1602     old_l1_index = l1_node->hw_index;
   1603 
   1604     /* unresolve the node - delete this node from parent's child list */
   1605     BCM_IF_ERROR_RETURN
   1606         (_bcm_kt_cosq_node_unresolve(unit, node, 0));
   1607 
   1608     /* now remove from the sw tree */
   1609     if (node->parent != NULL) {
   1610         if (node->parent->child == node) {
   1611             node->parent->child = node->sibling;
   1612         } else {
   1613             prev_node = node->parent->child;
   1614             while (prev_node != NULL && prev_node->sibling != node) {
   1615                 prev_node = prev_node->sibling;
   1616             }
   1617             if (prev_node == NULL) {
   1618                 return BCM_E_INTERNAL;
   1619             }
   1620             prev_node->sibling = node->sibling;
   1621        }
   1622         node->parent = NULL;
   1623         node->sibling = NULL;
   1624         node->hw_index = -1;
   1625         node->wrr_in_use = 0;
   1626         node->cosq_attached_to = -1;
   1627      }
   1628 
   1629     node->wrr_in_use = (mode != BCM_COSQ_STRICT) ? 1 : 0;
   1630     BCM_IF_ERROR_RETURN
   1631          (bcm_kt_cosq_gport_attach(unit, node->gport, remap_gport, 0));
   1632 
   1633     /* Read L2 child state to check L2 is not active in the scheduler. */
   1634     SOC_IF_ERROR_RETURN
   1635         (READ_LLS_L2_CHILD_STATE1m(unit, MEM_BLOCK_ALL, node->hw_index,
   1636                                    &l2_child_state));  
   1637     if (SOC_MEM_FIELD_VALID(unit, LLS_L2_CHILD_STATE1m, SPAREf)) {
   1638         soc_mem_field_get(unit, LLS_L2_CHILD_STATE1m, (uint32 *)&l2_child_state,
   1639                           SPAREf, &spare);
   1640     } else {
   1641         soc_mem_field_get(unit, LLS_L2_CHILD_STATE1m, (uint32 *)&l2_child_state,
   1642                           C_ON_WERR_LISTf, &spare);
   1643     }
   1644 
   1645     /* if(spare == 1) check whether L2 is on old L1. */
   1646     if (spare == 1) {
   1647         SOC_IF_ERROR_RETURN
   1648             (READ_LLS_L1_PARENT_STATEm(unit, MEM_BLOCK_ALL, old_l1_index,
   1649                                              &l1_parent_state)); 
   1650         soc_mem_field_get(unit, LLS_L1_PARENT_STATEm, (uint32 *)&l1_parent_state, 
   1651                                 P_WRR_0_NOT_EMPTYf, &wrr0_not_empty);
   1652         soc_mem_field_get(unit, LLS_L1_PARENT_STATEm, (uint32 *)&l1_parent_state, 
   1653                                 P_WRR_1_NOT_EMPTYf, &wrr1_not_empty);
   1654         if (wrr0_not_empty || wrr1_not_empty) {
   1655             timeout_val = soc_property_get(unit, spn_MMU_QUEUE_FLUSH_TIMEOUT, 20000);
   1656             soc_timeout_init(&timeout, timeout_val, 0);
   1657            
   1658             poll_active = 1; 
   1659             while (poll_active) {
   1660                 SOC_IF_ERROR_RETURN
   1661                     (READ_LLS_L2_CHILD_STATE1m(unit, MEM_BLOCK_ALL, node->hw_index,
   1662                                                       &l2_child_state));
   1663                 if (SOC_MEM_FIELD_VALID(unit, LLS_L2_CHILD_STATE1m, SPAREf)) {
   1664                     soc_mem_field_get(unit, LLS_L2_CHILD_STATE1m, (uint32 *)&l2_child_state,
   1665                                             SPAREf, &spare);
   1666                 } else {
   1667                     soc_mem_field_get(unit, LLS_L2_CHILD_STATE1m, (uint32 *)&l2_child_state,
   1668                                             C_ON_WERR_LISTf, &spare);
   1669                 }
   1670                 soc_mem_field_get(unit, LLS_L2_CHILD_STATE1m, (uint32 *)&l2_child_state, 
   1671                                         C_ON_MIN_LIST_0f, &min_list);
   1672                 soc_mem_field_get(unit, LLS_L2_CHILD_STATE1m, (uint32 *)&l2_child_state, 
   1673                                         C_ON_EF_LIST_0f, &ef_list);
   1674                 if (!spare && !min_list && !ef_list) {
   1675                     poll_active = 0;
   1676                 }
   1677                 if (soc_timeout_check(&timeout)) {
   1678                     (_bcm_kt_cosq_dynamic_bw_update(unit, config_mem1, index, node->hw_index,
   1679                                               l2_shaper_entry_lower));
   1680                     BCM_IF_ERROR_RETURN
   1681                     (_bcm_kt_cosq_dynamic_bw_update(unit, config_mem2, index, node->hw_index,
   1682                                                 l2_shaper_entry_upper));
   1683                     BCM_IF_ERROR_RETURN
   1684                     (_bcm_kt_cosq_inject_max_shaper_update(unit,node));
   1685 
   1686                     LOG_ERROR(BSL_LS_BCM_COMMON,
   1687                               (BSL_META_U(unit,
   1688                                           "ERROR: Queue %d old L1 index %d wrr0/1_not_empty %d %d\n"), 
   1689                                node->hw_index, old_l1_index, wrr0_not_empty, 
   1690                                wrr1_not_empty));
   1691                     LOG_ERROR(BSL_LS_BCM_COMMON,
   1692                               (BSL_META_U(unit,
   1693                                           "spare %d min_list %d ef_list %d\n"),
   1694                                spare, min_list, 
   1695                                ef_list)); 
   1696                     return BCM_E_TIMEOUT; 
   1697                  }                    
   1698             }    
   1699         }                            
   1700     }    
   1701      BCM_IF_ERROR_RETURN
   1702      (_bcm_kt_cosq_dynamic_bw_update(unit, config_mem1, index, node->hw_index,
   1703                                            l2_shaper_entry_lower));
   1704      BCM_IF_ERROR_RETURN
   1705      (_bcm_kt_cosq_dynamic_bw_update(unit, config_mem2, index, node->hw_index,
   1706                                             l2_shaper_entry_upper));
   1707      BCM_IF_ERROR_RETURN
   1708      (_bcm_kt_cosq_inject_max_shaper_update(unit,node));
   1709 
   1710     return rv;
   1711 }
   1712 
   1713 /*
   1714  * Function:
   1715  *     _bcm_kt_cosq_valid_dynamic_request
   1716  * Purpose:
   1717  *     Validate the new dynamic request
   1718  * Parameters:
   1719  *     unit       - (IN) unit number
   1720  *     port      - (IN) port
   1721  *     level      - (IN) scheduler level
   1722  *     node_id    - (IN) node index
   1723  *     parent_id  - (IN) parent index
   1724  *     rval        - (IN) dynamic reg value
   1725  * Returns:
   1726  *     BCM_E_XXX
   1727  */
   1728 
   1729 STATIC int
   1730 _bcm_kt_cosq_valid_dynamic_request(int unit, bcm_port_t port, int node_level, 
   1731                                    int node_id, int parent_id, uint32 rval) 
   1732 {
   1733     soc_reg_t dyn_reg = LLS_SP_WERR_DYN_CHANGE_0Ar;
   1734     lls_l0_parent_entry_t l0_parent;
   1735     lls_l1_parent_entry_t l1_parent;
   1736     bcm_port_t req_port, req_parent;
   1737 
   1738     /* dont allow more than one req per parent  */
   1739     req_parent = soc_reg_field_get(unit, dyn_reg, rval, PARENT_IDf);
   1740     if ((node_level == soc_reg_field_get(unit, dyn_reg, rval, NODE_LEVELf)) &&
   1741         (parent_id == req_parent)) {
   1742         return FALSE;
   1743     }
   1744 
   1745     switch (node_level) {
   1746         case _BCM_KT_COSQ_NODE_LEVEL_L0:
   1747             req_port = parent_id;
   1748             break;
   1749         case _BCM_KT_COSQ_NODE_LEVEL_L1:
   1750             SOC_IF_ERROR_RETURN
   1751                 (READ_LLS_L0_PARENTm(unit, MEM_BLOCK_ALL, req_parent,
   1752                                      &l0_parent));
   1753             req_port = soc_mem_field32_get(unit, LLS_L0_PARENTm, &l0_parent, 
   1754                                            C_PARENTf); 
   1755             break;
   1756         case _BCM_KT_COSQ_NODE_LEVEL_L2:
   1757             SOC_IF_ERROR_RETURN
   1758                 (READ_LLS_L1_PARENTm(unit, MEM_BLOCK_ALL, req_parent,
   1759                                      &l1_parent));
   1760             req_port = soc_mem_field32_get(unit, LLS_L1_PARENTm, &l1_parent, 
   1761                                            C_PARENTf); 
   1762             SOC_IF_ERROR_RETURN
   1763                 (READ_LLS_L0_PARENTm(unit, MEM_BLOCK_ALL, req_port,
   1764                                      &l0_parent));
   1765             req_port = soc_mem_field32_get(unit, LLS_L0_PARENTm, &l0_parent, 
   1766                                            C_PARENTf);    
   1767             break;
   1768         default:
   1769             return FALSE;
   1770     }
   1771 
   1772     /* dont allow more than one req per port */
   1773     if (port == req_port) {
   1774         return FALSE;
   1775     }    
   1776     return TRUE;
   1777 }
   1778 
   1779 /*
   1780  * Function:
   1781  *     _bcm_kt_cosq_dynamic_sp_werr_change
   1782  * Purpose:
   1783  *     Set LLS dynamic scheduler registers based on level and hw index
   1784  * Parameters:
   1785  *     unit       - (IN) unit number
   1786  *     level      - (IN) scheduler level
   1787  *     node_id    - (IN) node index
   1788  *     parent_id  - (IN) parent index
   1789  *     config       - (IN) config details
   1790  * Returns:
   1791  *     BCM_E_XXX
   1792  */
   1793 STATIC int
   1794 _bcm_kt_cosq_dynamic_sp_werr_change(int unit, bcm_port_t port, int node_level, 
   1795                                     int node_id, int parent_id, uint32 config,
   1796                                     _bcm_kt_cosq_state_t state)
   1797 {
   1798     soc_timeout_t timeout;
   1799     uint32 timeout_val, rval;
   1800     int i, in_use;
   1801     soc_reg_t dyn_reg_a, dyn_reg_b;
   1802     lls_l0_xoff_entry_t l0_xoff;
   1803     soc_reg_t dyn_change_a[] = 
   1804         {
   1805         LLS_SP_WERR_DYN_CHANGE_0Ar,
   1806         LLS_SP_WERR_DYN_CHANGE_1Ar,
   1807         LLS_SP_WERR_DYN_CHANGE_2Ar,
   1808         LLS_SP_WERR_DYN_CHANGE_3Ar
   1809         };
   1810     soc_reg_t dyn_change_b[] = 
   1811         {
   1812         LLS_SP_WERR_DYN_CHANGE_0Br,
   1813         LLS_SP_WERR_DYN_CHANGE_1Br,
   1814         LLS_SP_WERR_DYN_CHANGE_2Br,
   1815         LLS_SP_WERR_DYN_CHANGE_3Br
   1816         };
   1817 
   1818     /* Get one of the free register to place the request */    
   1819     for (i = 0; i < 4; i++) {
   1820         dyn_reg_a =  dyn_change_a[i];
   1821         dyn_reg_b =  dyn_change_b[i];
   1822         SOC_IF_ERROR_RETURN(soc_reg32_get(unit, dyn_reg_a, REG_PORT_ANY, 
   1823                                           0, &rval));
   1824         if (SAL_BOOT_SIMULATION) {
   1825             break;
   1826         }    
   1827         
   1828         if (soc_reg_field_get(unit, dyn_reg_a, rval, IN_USEf) == 0) {
   1829             break;
   1830         } else {
   1831         /* verify any other req pending from this port or same parent */
   1832             if (_bcm_kt_cosq_valid_dynamic_request(unit, port, node_level, 
   1833                      node_id, parent_id, rval) == FALSE) {
   1834                 return BCM_E_UNAVAIL;     
   1835             }                                                     
   1836         }
   1837     }    
   1838 
   1839     if (i == 4) {
   1840         /* None of the registers are available */
   1841         return BCM_E_UNAVAIL;
   1842     }    
   1843 
   1844     rval = 0;
   1845     soc_reg_field_set(unit, dyn_reg_a, &rval, NODE_LEVELf, node_level);
   1846     soc_reg_field_set(unit, dyn_reg_a, &rval, NODE_IDf, node_id);
   1847     soc_reg_field_set(unit, dyn_reg_a, &rval, PARENT_IDf, parent_id);
   1848     soc_reg_field_set(unit, dyn_reg_a, &rval, IN_USEf, 1);
   1849 
   1850     /* Write DYN_CHANGE_XB register first */
   1851     SOC_IF_ERROR_RETURN(soc_reg32_set(unit, dyn_reg_b, REG_PORT_ANY, 
   1852                                       0, config));
   1853     /* Write DYN_CHANGE_XA register next. this triggers the request */
   1854     SOC_IF_ERROR_RETURN(soc_reg32_set(unit, dyn_reg_a, REG_PORT_ANY, 
   1855                                       0, rval));
   1856     if (SAL_BOOT_SIMULATION) {
   1857         return BCM_E_NONE;
   1858     }
   1859     
   1860     in_use = 1;
   1861     timeout_val = soc_property_get(unit, spn_MMU_QUEUE_FLUSH_TIMEOUT, 
   1862                                    _BCM_COSQ_QUEUE_FLUSH_TIMEOUT_DEFAULT);
   1863     soc_timeout_init(&timeout, timeout_val, 0);
   1864 
   1865     while (in_use) {                              
   1866         SOC_IF_ERROR_RETURN
   1867             (soc_reg32_get(unit, dyn_reg_a, REG_PORT_ANY, 0, &rval)); 
   1868         in_use = soc_reg_field_get(unit, dyn_reg_a, rval, IN_USEf);
   1869         if (in_use && soc_timeout_check(&timeout)) {
   1870             LOG_ERROR(BSL_LS_BCM_COMMON,
   1871                       (BSL_META_U(unit,
   1872                                   "ERROR: dynamic sp <-> werr change operation failed \n")));
   1873             LOG_ERROR(BSL_LS_BCM_COMMON,
   1874                       (BSL_META_U(unit,
   1875                                   " node_level %d node_id %d parent_id %d \n"), 
   1876                        node_level, node_id, parent_id));
   1877             soc_reg_field_set(unit, dyn_reg_a, &rval, IN_USEf, 0);
   1878             SOC_IF_ERROR_RETURN(soc_reg32_set(unit, dyn_reg_a, REG_PORT_ANY, 
   1879                                 0, rval));
   1880             return BCM_E_TIMEOUT;
   1881          }
   1882     }
   1883 
   1884     if (node_level == _BCM_KT_COSQ_NODE_LEVEL_L1 && 
   1885         state == _BCM_KT_COSQ_STATE_WRR_TO_SPRI) {
   1886         sal_memset(&l0_xoff, 0, sizeof(lls_l0_xoff_entry_t));
   1887         soc_mem_field32_set(unit, LLS_L0_XOFFm, &l0_xoff, C_XOFFf,
   1888                             (1 << (parent_id & 0xf)));     
   1889         SOC_IF_ERROR_RETURN
   1890             (WRITE_LLS_L0_XOFFm(unit, MEM_BLOCK_ALL, ((parent_id >> 4) & 0xf),
   1891                                 &l0_xoff));
   1892         /* Add single lls register read delay */
   1893         SOC_IF_ERROR_RETURN(soc_reg32_get(unit, dyn_reg_a, REG_PORT_ANY, 
   1894                                           0, &rval));
   1895         soc_mem_field32_set(unit, LLS_L0_XOFFm, &l0_xoff, C_XOFFf, 0);     
   1896         SOC_IF_ERROR_RETURN
   1897             (WRITE_LLS_L0_XOFFm(unit, MEM_BLOCK_ALL, ((parent_id >> 4) & 0xf),
   1898                                 &l0_xoff));
   1899         SOC_IF_ERROR_RETURN(READ_LLS_DEBUG_INJECT_ACTIVATIONr(unit, &rval));
   1900         soc_reg_field_set(unit, LLS_DEBUG_INJECT_ACTIVATIONr, &rval, 
   1901                           INJECTf, 1);
   1902         soc_reg_field_set(unit, LLS_DEBUG_INJECT_ACTIVATIONr, &rval, 
   1903                           ENTITY_TYPEf, 2);
   1904         soc_reg_field_set(unit, LLS_DEBUG_INJECT_ACTIVATIONr, &rval, 
   1905                           ENTITY_LEVELf, 1);
   1906         soc_reg_field_set(unit, LLS_DEBUG_INJECT_ACTIVATIONr, &rval, 
   1907                           ENTITY_IDENTIFIERf, parent_id);
   1908         SOC_IF_ERROR_RETURN(WRITE_LLS_DEBUG_INJECT_ACTIVATIONr(unit, rval));
   1909     }
   1910 
   1911     return BCM_E_NONE;
   1912 }
   1913 
   1914 STATIC int
   1915 _bcm_kt_cosq_shaper_value_get(int unit, int port, int max_speed,
   1916                               uint32 lvl, int *node_count,
   1917                               uint32 *exp, uint32 *mant)
   1918 {
   1919     int speed;
   1920     int rv;
   1921     int l0_speed = 0, l1_speed = 0;
   1922 
   1923     if (NULL == exp || NULL == mant) {
   1924         return BCM_E_PARAM;
   1925     }
   1926 
   1927     speed = max_speed * 1000;
   1928 
   1929 
   1930     if (lvl == _SOC_KT_COSQ_NODE_LEVEL_L0) {
   1931         speed = (( KT_COSQ_SHAPER_PERC * speed) / 100);
   1932         if (node_count[_SOC_KT_COSQ_NODE_LEVEL_L1]) {
   1933             speed /= node_count[_SOC_KT_COSQ_NODE_LEVEL_L1];
   1934         }
   1935     } else if (lvl == _SOC_KT_COSQ_NODE_LEVEL_L1) {
   1936         l0_speed = (( KT_COSQ_SHAPER_PERC * speed) / 100);
   1937         if(node_count[_SOC_KT_COSQ_NODE_LEVEL_L1]) {
   1938             l0_speed /= node_count[_SOC_KT_COSQ_NODE_LEVEL_L0];
   1939         }
   1940         speed = (( KT_COSQ_SHAPER_PERC * l0_speed) / 100);
   1941         if (node_count[_SOC_KT_COSQ_NODE_LEVEL_L1]) {
   1942             speed /= node_count[_SOC_KT_COSQ_NODE_LEVEL_L1];
   1943         }
   1944     } else if (lvl == _SOC_KT_COSQ_NODE_LEVEL_L2) {
   1945         l0_speed = (( KT_COSQ_SHAPER_PERC * speed) / 100);
   1946         if (node_count[_SOC_KT_COSQ_NODE_LEVEL_L0]) {
   1947             l0_speed /= node_count[_SOC_KT_COSQ_NODE_LEVEL_L0];
   1948         }
   1949         l1_speed = (( KT_COSQ_SHAPER_PERC * l0_speed) / 100);
   1950         if (node_count[_SOC_KT_COSQ_NODE_LEVEL_L1]) {
   1951             l1_speed /= node_count[_SOC_KT_COSQ_NODE_LEVEL_L1];
   1952         }
   1953         speed = (( KT_COSQ_SHAPER_PERC * l1_speed) / 100);
   1954         if (node_count[_SOC_KT_COSQ_NODE_LEVEL_L2]) {
   1955             speed /= node_count[_SOC_KT_COSQ_NODE_LEVEL_L2];
   1956         }
   1957     } else {
   1958         speed = (( KT_COSQ_SHAPER_PERC * speed) / 100);
   1959     }
   1960 
   1961     rv = soc_katana_get_shaper_rate_info(unit, speed, mant, exp);
   1962     if (BCM_FAILURE(rv)) {
   1963         return(rv);
   1964     }
   1965     return BCM_E_NONE;
   1966 }
   1967 
   1968 STATIC int
   1969 _bcm_kt_cosq_sched_bucket_set(int unit, int port,
   1970                         int index, uint32 level, int *node_count, int max_speed)
   1971 {
   1972     uint32 idx = 0;
   1973     uint32 i = 0;
   1974     lls_port_shaper_config_c_entry_t port_entry;
   1975     lls_l0_shaper_config_c_entry_t  l0_entry;
   1976     lls_l1_shaper_config_c_entry_t  l1_entry;
   1977     lls_l2_shaper_config_lower_entry_t l2_entry;
   1978     uint32 exp = 0, mant = 0;
   1979     soc_mem_t config_mem[2];
   1980     static const soc_field_t rate_exp_fields[] = {
   1981        C_MAX_REF_RATE_EXP_0f, C_MAX_REF_RATE_EXP_1f,
   1982        C_MAX_REF_RATE_EXP_2f, C_MAX_REF_RATE_EXP_3f,
   1983        C_MIN_REF_RATE_EXP_0f, C_MIN_REF_RATE_EXP_1f,
   1984        C_MIN_REF_RATE_EXP_2f, C_MIN_REF_RATE_EXP_3f
   1985     };
   1986     static const soc_field_t rate_mant_fields[] = {
   1987        C_MAX_REF_RATE_MANT_0f, C_MAX_REF_RATE_MANT_1f,
   1988        C_MAX_REF_RATE_MANT_2f, C_MAX_REF_RATE_MANT_3f,
   1989        C_MIN_REF_RATE_MANT_0f, C_MIN_REF_RATE_MANT_1f,
   1990        C_MIN_REF_RATE_MANT_2f, C_MIN_REF_RATE_MANT_3f
   1991     };
   1992     static const soc_field_t burst_exp_fields[] = {
   1993        C_MAX_THLD_EXP_0f, C_MAX_THLD_EXP_1f,
   1994        C_MAX_THLD_EXP_2f, C_MAX_THLD_EXP_3f,
   1995        C_MIN_THLD_EXP_0f, C_MIN_THLD_EXP_1f,
   1996        C_MIN_THLD_EXP_2f, C_MIN_THLD_EXP_3f
   1997     };
   1998     static const soc_field_t burst_mant_fields[] = {
   1999        C_MAX_THLD_MANT_0f, C_MAX_THLD_MANT_1f,
   2000        C_MAX_THLD_MANT_2f, C_MAX_THLD_MANT_3f,
   2001        C_MIN_THLD_MANT_0f, C_MIN_THLD_MANT_1f,
   2002        C_MIN_THLD_MANT_2f, C_MIN_THLD_MANT_3f
   2003     };
   2004     static const soc_field_t cycle_sel_fields[] = {
   2005         C_MAX_CYCLE_SEL_0f, C_MAX_CYCLE_SEL_1f,
   2006         C_MAX_CYCLE_SEL_2f, C_MAX_CYCLE_SEL_3f,
   2007         C_MIN_CYCLE_SEL_0f, C_MIN_CYCLE_SEL_1f,
   2008         C_MIN_CYCLE_SEL_2f, C_MIN_CYCLE_SEL_3f
   2009     };
   2010 
   2011     soc_field_t rate_exp_f[] = {
   2012         C_MAX_REF_RATE_EXPf, C_MIN_REF_RATE_EXPf
   2013     };
   2014     soc_field_t rate_mant_f[] = {
   2015         C_MAX_REF_RATE_MANTf, C_MIN_REF_RATE_MANTf
   2016     };
   2017     soc_field_t burst_exp_f[] = {
   2018         C_MAX_THLD_EXPf, C_MIN_THLD_EXPf
   2019     };
   2020     soc_field_t burst_mant_f[] = {
   2021         C_MAX_THLD_MANTf, C_MIN_THLD_MANTf
   2022     };
   2023     soc_field_t cycle_sel_f[] = {
   2024         C_MAX_CYCLE_SELf, C_MIN_CYCLE_SELf
   2025     };
   2026 
   2027 
   2028     SOC_IF_ERROR_RETURN
   2029            (_bcm_kt_cosq_shaper_value_get(unit, port, max_speed, level, node_count, &exp, &mant));
   2030     switch (level)  {
   2031         case _SOC_KT_COSQ_NODE_LEVEL_ROOT:
   2032             config_mem[0] = LLS_PORT_SHAPER_CONFIG_Cm;
   2033 
   2034             sal_memset(&port_entry, 0,
   2035                        sizeof(lls_port_shaper_config_c_entry_t));
   2036             SOC_IF_ERROR_RETURN
   2037                (soc_mem_read(unit, config_mem[0], MEM_BLOCK_ALL,
   2038                              index, &port_entry));
   2039             soc_mem_field32_set(unit, config_mem[0], &port_entry,
   2040                                 rate_exp_f[0], exp);
   2041             soc_mem_field32_set(unit, config_mem[0], &port_entry,
   2042                                 rate_mant_f[0], mant);
   2043             soc_mem_field32_set(unit, config_mem[0], &port_entry,
   2044                                 burst_exp_f[0], KT_QUEUE_FLUSH_BURST_EXP);
   2045             soc_mem_field32_set(unit, config_mem[0], &port_entry,
   2046                                 burst_mant_f[0], KT_QUEUE_FLUSH_BURST_MANTISSA);
   2047             soc_mem_field32_set(unit, config_mem[0], &port_entry,
   2048                                 cycle_sel_f[0], KT_QUEUE_FLUSH_CYCLE_SEL);
   2049             SOC_IF_ERROR_RETURN
   2050                    (soc_mem_write(unit, config_mem[0],
   2051                                        MEM_BLOCK_ALL, index, &port_entry));
   2052            break;
   2053         case _SOC_KT_COSQ_NODE_LEVEL_L0:
   2054             config_mem[0] = LLS_L0_SHAPER_CONFIG_Cm;
   2055             config_mem[1] = LLS_L0_MIN_CONFIG_Cm;
   2056 
   2057             for (i = 0; i < 2; i++) {
   2058                 sal_memset(&l0_entry, 0,
   2059                              sizeof(lls_l0_shaper_config_c_entry_t));
   2060                 SOC_IF_ERROR_RETURN
   2061                        (soc_mem_read(unit, config_mem[i], MEM_BLOCK_ALL,
   2062                                      index, &l0_entry));
   2063                 soc_mem_field32_set(unit, config_mem[i], &l0_entry,
   2064                                     rate_exp_f[i], exp);
   2065                 soc_mem_field32_set(unit, config_mem[i], &l0_entry,
   2066                                     rate_mant_f[i], mant);
   2067                 soc_mem_field32_set(unit, config_mem[i], &l0_entry,
   2068                                     burst_exp_f[i], KT_QUEUE_FLUSH_BURST_EXP);
   2069                 soc_mem_field32_set(unit, config_mem[i], &l0_entry,
   2070                                     burst_mant_f[i], KT_QUEUE_FLUSH_BURST_MANTISSA);
   2071                 soc_mem_field32_set(unit, config_mem[i], &l0_entry,
   2072                                     cycle_sel_f[i], KT_QUEUE_FLUSH_CYCLE_SEL);
   2073                 SOC_IF_ERROR_RETURN
   2074                          (soc_mem_write(unit, config_mem[i],
   2075                                     MEM_BLOCK_ALL, index, &l0_entry));
   2076             }
   2077             break;
   2078         case _SOC_KT_COSQ_NODE_LEVEL_L1:
   2079             config_mem[0] = LLS_L1_SHAPER_CONFIG_Cm;
   2080             config_mem[1] = LLS_L1_MIN_CONFIG_Cm;
   2081 
   2082             for (i = 0; i < 2; i++) {
   2083                 sal_memset(&l1_entry, 0,
   2084                             sizeof(lls_l1_shaper_config_c_entry_t));
   2085                 idx = (i * 4) + (index % 4);
   2086                 SOC_IF_ERROR_RETURN
   2087                        (soc_mem_read(unit, config_mem[i], MEM_BLOCK_ALL,
   2088                                    index/4, &l1_entry));
   2089                 soc_mem_field32_set(unit, config_mem[i], &l1_entry,
   2090                                     rate_exp_fields[idx], exp);
   2091                 soc_mem_field32_set(unit, config_mem[i], &l1_entry,
   2092                                     rate_mant_fields[idx], mant);
   2093                 soc_mem_field32_set(unit, config_mem[i], &l1_entry,
   2094                                     burst_exp_fields[idx], KT_QUEUE_FLUSH_BURST_EXP);
   2095                 soc_mem_field32_set(unit, config_mem[i], &l1_entry,
   2096                                     burst_mant_fields[idx], KT_QUEUE_FLUSH_BURST_MANTISSA);
   2097                 soc_mem_field32_set(unit, config_mem[i], &l1_entry,
   2098                                     cycle_sel_fields[idx], KT_QUEUE_FLUSH_CYCLE_SEL);
   2099                 SOC_IF_ERROR_RETURN
   2100                      (soc_mem_write(unit, config_mem[i],
   2101                                     MEM_BLOCK_ALL, index/4, &l1_entry));
   2102             }
   2103             break;
   2104         case _SOC_KT_COSQ_NODE_LEVEL_L2:
   2105             if ((index % 8) < 4) {
   2106                 config_mem[0] = LLS_L2_SHAPER_CONFIG_LOWERm;
   2107                 config_mem[1] = LLS_L2_MIN_CONFIG_LOWER_Cm;
   2108             } else {
   2109                 config_mem[0] = LLS_L2_SHAPER_CONFIG_UPPERm;
   2110                 config_mem[1] = LLS_L2_MIN_CONFIG_UPPER_Cm;
   2111             }
   2112 
   2113             for ( i = 0; i < 2; i++) {
   2114                 idx = (i * 4) + (index % 4);
   2115 
   2116                 sal_memset(&l2_entry, 0,
   2117                            sizeof(lls_l2_shaper_config_lower_entry_t));
   2118                 SOC_IF_ERROR_RETURN
   2119                     (soc_mem_read(unit, config_mem[i], MEM_BLOCK_ALL,
   2120                                   index/8, &l2_entry));
   2121                 soc_mem_field32_set(unit, config_mem[i], &l2_entry,
   2122                                     rate_exp_fields[idx], exp);
   2123                 soc_mem_field32_set(unit, config_mem[i], &l2_entry,
   2124                                     rate_mant_fields[idx], mant);
   2125                 soc_mem_field32_set(unit, config_mem[i], &l2_entry,
   2126                                     burst_exp_fields[idx], KT_QUEUE_FLUSH_BURST_EXP );
   2127                 soc_mem_field32_set(unit, config_mem[i], &l2_entry,
   2128                                     burst_mant_fields[idx], KT_QUEUE_FLUSH_BURST_MANTISSA );
   2129                 soc_mem_field32_set(unit, config_mem[i], &l2_entry,
   2130                                     cycle_sel_fields[idx], KT_QUEUE_FLUSH_CYCLE_SEL);
   2131                 SOC_IF_ERROR_RETURN
   2132                     (soc_mem_write(unit, config_mem[i],
   2133                                    MEM_BLOCK_ALL, index/8, &l2_entry));
   2134             }
   2135             break;
   2136         default:
   2137             return SOC_E_NONE;
   2138 
   2139     }
   2140 
   2141     return SOC_E_NONE;
   2142 }
   2143 
   2144 
   2145 STATIC int
   2146 _bcm_kt_egress_metering_freeze(int unit, soc_port_t port, void **setting)
   2147 {
   2148     int rv = BCM_E_NONE;
   2149     soc_mem_t mem;
   2150     uint32 *bmap, *bmap_list[5];
   2151     int word_count, wdc[5], blk_size=0;
   2152     int lvl, j, index, word, bit, index_count, count;
   2153     int idx, upper_flag = 0;
   2154     int prev_idx, prev_upper_flag;
   2155     int node_count[4], speed = 0;
   2156     mem_entry_t *buffer;
   2157     soc_info_t *si;
   2158     static const soc_mem_t cfg_mems[][2] = {
   2159         { LLS_PORT_SHAPER_CONFIG_Cm, INVALIDm },
   2160         { LLS_L0_SHAPER_CONFIG_Cm, LLS_L0_MIN_CONFIG_Cm },
   2161         { LLS_L1_SHAPER_CONFIG_Cm, LLS_L1_MIN_CONFIG_Cm },
   2162         { LLS_L2_SHAPER_CONFIG_LOWERm, LLS_L2_MIN_CONFIG_LOWER_Cm },
   2163         { LLS_L2_SHAPER_CONFIG_UPPERm, LLS_L2_MIN_CONFIG_UPPER_Cm },
   2164     };
   2165 
   2166     SOC_EGRESS_METERING_LOCK(unit);
   2167 
   2168     si = &SOC_INFO(unit);
   2169     bmap_list[1] = SOC_CONTROL(unit)->port_lls_l0_bmap[port];
   2170     bmap_list[2] = SOC_CONTROL(unit)->port_lls_l1_bmap[port];
   2171     bmap_list[3] = SOC_CONTROL(unit)->port_lls_l2_bmap[port];
   2172     count = 0; /* One entry for port level */
   2173 
   2174     for (lvl = _BCM_KT_COSQ_NODE_LEVEL_L0;
   2175           lvl < _BCM_KT_COSQ_NODE_LEVEL_MAX; lvl++) {
   2176         node_count[lvl] = 0;
   2177     }
   2178 
   2179     if (IS_LB_PORT(unit, port) || IS_CPU_PORT(unit, port)) {
   2180         speed = si->port_speed_max[port];
   2181     } else {
   2182         rv =  bcm_esw_port_speed_get(unit, port, &speed);
   2183         if (BCM_FAILURE(rv)) {
   2184             goto _ka_freeze_abort;
   2185         }
   2186         if (speed == 0) {
   2187             rv =  bcm_esw_port_speed_max(unit, port, &speed);
   2188             if (BCM_FAILURE(rv)) {
   2189                 goto _ka_freeze_abort;
   2190             }
   2191         }
   2192     }
   2193 
   2194     for (lvl = _BCM_KT_COSQ_NODE_LEVEL_L0;
   2195           lvl < _BCM_KT_COSQ_NODE_LEVEL_MAX; lvl++) {
   2196         bmap = bmap_list[lvl];
   2197         mem = cfg_mems[lvl][0];
   2198         index_count = soc_mem_index_count(unit, mem);
   2199         /*
   2200          * Allocation done using LLS_LX_PARENT
   2201          * reading also done using same memories
   2202          */
   2203         if (lvl == _BCM_KT_COSQ_NODE_LEVEL_L0) {
   2204             index_count = soc_mem_index_count(unit, LLS_L0_PARENTm);
   2205         } else if (lvl == _BCM_KT_COSQ_NODE_LEVEL_L1) {
   2206             index_count = soc_mem_index_count(unit, LLS_L1_PARENTm);
   2207         } else if (lvl == _BCM_KT_COSQ_NODE_LEVEL_L2) {
   2208             index_count = soc_mem_index_count(unit, LLS_L2_PARENTm);
   2209         }
   2210         wdc[lvl] = _SHR_BITDCLSIZE(index_count);
   2211         word_count = wdc[lvl];
   2212         for (word = 0; word < word_count; word++) {
   2213             if (bmap[word] != 0) {
   2214                 if (lvl == _BCM_KT_COSQ_NODE_LEVEL_L0) {
   2215                     node_count[_BCM_KT_COSQ_NODE_LEVEL_L0] += _shr_popcount(bmap[word]);
   2216                 } else if (lvl == _BCM_KT_COSQ_NODE_LEVEL_L1) {
   2217                     node_count[_BCM_KT_COSQ_NODE_LEVEL_L1] += _shr_popcount(bmap[word]);
   2218                 } else if (lvl == _BCM_KT_COSQ_NODE_LEVEL_L2) {
   2219                     node_count[_BCM_KT_COSQ_NODE_LEVEL_L2] += _shr_popcount(bmap[word]);
   2220                 }
   2221             }
   2222         }
   2223     }
   2224 
   2225     for (lvl = _BCM_KT_COSQ_NODE_LEVEL_L0;
   2226          lvl < _BCM_KT_COSQ_NODE_LEVEL_MAX; lvl++) {
   2227         count += node_count[lvl];
   2228     }
   2229     count = (count * 8) + 1;
   2230     node_count[_BCM_KT_COSQ_NODE_LEVEL_ROOT] = 1;
   2231 
   2232     buffer = sal_alloc((count + 1) * sizeof(mem_entry_t),
   2233             "shaper buffer");
   2234 
   2235     if (buffer == NULL) {
   2236         rv = BCM_E_MEMORY;
   2237         goto _ka_freeze_abort;
   2238     }
   2239 
   2240     count = 0;
   2241     /* port */
   2242     mem = LLS_PORT_SHAPER_CONFIG_Cm;
   2243     index = port & 0x3f;
   2244     /* Save the entry */
   2245     rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, index,
   2246             &buffer[count].entry);
   2247 
   2248     if (BCM_FAILURE(rv)) {
   2249         sal_free(buffer);
   2250         goto _ka_freeze_abort;
   2251     }
   2252     buffer[count].mem = mem;
   2253     buffer[count].index = index;
   2254     count++;
   2255     /* Set the threshold for the port to max shaper rate */
   2256     rv = _bcm_kt_cosq_sched_bucket_set(unit, port, index,
   2257             _SOC_KT_COSQ_NODE_LEVEL_ROOT, node_count, speed);
   2258     if (BCM_FAILURE(rv)) {
   2259         sal_free(buffer);
   2260         goto _ka_freeze_abort;
   2261     }
   2262 
   2263     /* L0, L1, L2 meter */
   2264     for (lvl = _BCM_KT_COSQ_NODE_LEVEL_L0;
   2265          lvl < _BCM_KT_COSQ_NODE_LEVEL_MAX; lvl++) {
   2266         idx = upper_flag = 0;
   2267         prev_idx = prev_upper_flag = -1;
   2268         blk_size = (lvl == _BCM_KT_COSQ_NODE_LEVEL_L2) ? 8:
   2269                     ((lvl == _BCM_KT_COSQ_NODE_LEVEL_L1)? 4:1);
   2270         bmap = bmap_list[lvl];
   2271         word_count = wdc[lvl];
   2272         for (word = 0; word < word_count; word++) {
   2273             if (bmap[word] == 0) {
   2274                 continue;
   2275             }
   2276             for (bit = 0; bit < SHR_BITWID; bit++) {
   2277                 if (!(bmap[word] & (1 << bit))) {
   2278                     continue;
   2279                 }
   2280                 index = word * SHR_BITWID + bit;
   2281                 idx = index / blk_size;
   2282                 for (j = 0; j < 2; j++) {
   2283                     mem = cfg_mems[lvl][j];
   2284                     if (lvl == _BCM_KT_COSQ_NODE_LEVEL_L2) {
   2285                         if ((index % 8) >= 4) {
   2286                             mem = cfg_mems[lvl][j];
   2287                             upper_flag = 1;
   2288                         } else {
   2289                             upper_flag = 0;
   2290                         }
   2291                     }
   2292 
   2293                     /* Store the Threshold MIN/MAX table entries only
   2294                      * once per table index as for the
   2295                      * next consecutive L1/L2 indices falling on
   2296                      * to the same table index need not be stored
   2297                      */
   2298                     if ((prev_idx != idx) ||
   2299                             ((lvl == _BCM_KT_COSQ_NODE_LEVEL_L2) && (prev_upper_flag != upper_flag))) {
   2300                         rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, idx,
   2301                                 &buffer[count].entry);
   2302                         if (BCM_FAILURE(rv)) {
   2303                             sal_free(buffer);
   2304                             goto _ka_freeze_abort;
   2305                         }
   2306                         buffer[count].mem = mem;
   2307                         buffer[count].index = idx;
   2308                         count++;
   2309                     }
   2310 
   2311                     if (lvl == _BCM_KT_COSQ_NODE_LEVEL_L2){
   2312                         rv = _bcm_kt_cosq_sched_bucket_set(unit, port,
   2313                                 index, lvl, node_count, speed);
   2314                     } else if ((lvl != _BCM_KT_COSQ_NODE_LEVEL_L2) && (j == 1)) {
   2315                         rv = _bcm_kt_cosq_sched_bucket_set(unit, port,
   2316                                 index, lvl, node_count, speed);
   2317                     }
   2318                     if (BCM_FAILURE(rv)) {
   2319                         sal_free(buffer);
   2320                         goto _ka_freeze_abort;
   2321                     }
   2322                 }/*END of for j */
   2323                 prev_idx = idx;
   2324                 prev_upper_flag = upper_flag;
   2325             } /* END of the valid bit */
   2326         } /* END of the word */
   2327     } /* END of lvl */
   2328 
   2329     buffer[count].mem = INVALIDm;
   2330     *setting = buffer;
   2331 _ka_freeze_abort:
   2332     return rv;
   2333 }
   2334 
   2335 STATIC int
   2336 _bcm_kt_egress_metering_thaw(int unit, soc_port_t port, void *setting)
   2337 {
   2338     int       rv;
   2339     int index;
   2340     mem_entry_t *buffer;
   2341     if (setting == NULL) {
   2342         SOC_EGRESS_METERING_UNLOCK(unit);
   2343         return SOC_E_NONE;
   2344     }
   2345     rv = SOC_E_NONE;
   2346 
   2347     buffer = setting;
   2348     for (index = 0; buffer[index].mem != INVALIDm ;index++) {
   2349          rv = soc_mem_write(unit, buffer[index].mem, MEM_BLOCK_ANY,
   2350          buffer[index].index, &buffer[index].entry);
   2351          if (BCM_FAILURE(rv)) {
   2352              break;
   2353          }
   2354     }
   2355     sal_free(setting);
   2356     SOC_EGRESS_METERING_UNLOCK(unit);
   2357     return rv;
   2358 }
   2359 
   2360 /*
   2361  * Function:
   2362  *     _bcm_kt_cosq_sched_config_set
   2363  * Purpose:
   2364  *     Set LLS scheduler registers based on GPORT
   2365  * Parameters:
   2366  *     unit       - (IN) unit number
   2367  *     gport     - (IN) queue group/scheduler GPORT identifier
   2368  *     state     - (IN) sched state change
   2369  * Returns:
   2370  *     BCM_E_XXX
   2371  */
   2372 STATIC int
   2373 _bcm_kt_cosq_sched_config_set(int unit, bcm_gport_t gport, 
   2374                               _bcm_kt_cosq_state_t state)
   2375 {
   2376     _bcm_kt_mmu_info_t *mmu_info;
   2377     _bcm_kt_cosq_node_t *node, *parent;
   2378     mmu_rqe_queue_op_node_map_entry_t rqe_op_node;
   2379     mmu_wred_queue_op_node_map_entry_t wred_op_node;
   2380     lls_l2_child_state1_entry_t l2_child_state;
   2381     uint32 entry_c[SOC_MAX_MEM_WORDS];
   2382     uint32 entry_p[SOC_MAX_MEM_WORDS];
   2383     int port, start_spri = 0;
   2384     int flush_active = 0;
   2385     int update_spri_vector = 0;
   2386     uint8 spri_vector = 0;
   2387     int parent_index;
   2388     uint8 vec_3_0, vec_7_4;
   2389     uint32 rval = 0, timeout_val;
   2390     int retval_temp = 0;
   2391     uint32 spare, min_list, ef_list, not_empty;
   2392     soc_timeout_t timeout;
   2393     soc_mem_t config_mem, parent_mem;
   2394     uint32 *bmap = NULL;
   2395     soc_mem_t mem_c[] = { 
   2396                         LLS_PORT_CONFIGm, 
   2397                         LLS_L0_CONFIGm,
   2398                         LLS_L1_CONFIGm
   2399                       };
   2400     soc_mem_t mem_p[] = { 
   2401                         LLS_L0_PARENTm, 
   2402                         LLS_L1_PARENTm,
   2403                         LLS_L2_PARENTm
   2404                       };
   2405     
   2406     void *setting = NULL;
   2407     BCM_IF_ERROR_RETURN
   2408         (_bcm_kt_cosq_node_get(unit, gport, NULL, &port, NULL,
   2409                                &node));
   2410     parent = node->parent;
   2411 
   2412     if (node->cosq_attached_to < 0 || (node->cosq_attached_to < 8 && 
   2413         parent->base_index < 0)) {
   2414         return BCM_E_PARAM;
   2415     }
   2416 
   2417     config_mem = mem_c[parent->level];    
   2418     if ((node->cosq_attached_to < 8) && (parent->hw_index != -1)) {
   2419         start_spri = parent->base_index; 
   2420         spri_vector = 1 << (node->hw_index - start_spri);
   2421         update_spri_vector =  1;
   2422 
   2423         sal_memset(entry_c, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS);    
   2424         SOC_IF_ERROR_RETURN
   2425             (soc_mem_read(unit, config_mem, MEM_BLOCK_ALL, parent->hw_index, 
   2426                           &entry_c));
   2427         vec_3_0 = soc_mem_field32_get(unit, config_mem, &entry_c, 
   2428                                       P_NUM_SPRIf);
   2429         vec_7_4 = soc_mem_field32_get(unit, config_mem, &entry_c, 
   2430                                       P_VECT_SPRI_7_4f);
   2431         if (state == _BCM_KT_COSQ_STATE_ENABLE || 
   2432             state == _BCM_KT_COSQ_STATE_WRR_TO_SPRI) {
   2433             vec_3_0 |= (spri_vector & 0xF);
   2434             vec_7_4 |= (spri_vector >> 4); 
   2435         } else if (state == _BCM_KT_COSQ_STATE_DISABLE ||
   2436                    state == _BCM_KT_COSQ_STATE_SPRI_TO_WRR) {
   2437             vec_3_0 &= ~(spri_vector & 0xF);
   2438             vec_7_4 &= ~(spri_vector >> 4);
   2439         } 
   2440 
   2441         /* update LLS_CONFIG with the updated vector */ 
   2442         soc_mem_field32_set(unit, config_mem, &entry_c, P_START_SPRIf, 
   2443                             start_spri);
   2444         soc_mem_field32_set(unit, config_mem, &entry_c, P_NUM_SPRIf, 
   2445                             vec_3_0);
   2446         soc_mem_field32_set(unit, config_mem, &entry_c, P_VECT_SPRI_7_4f, 
   2447                             vec_7_4);    
   2448     }
   2449 
   2450     parent_mem = mem_p[parent->level]; 
   2451     sal_memset(entry_p, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS);
   2452     sal_memset(&rqe_op_node, 0, sizeof(mmu_rqe_queue_op_node_map_entry_t));
   2453     sal_memset(&wred_op_node, 0, sizeof(mmu_wred_queue_op_node_map_entry_t));
   2454 
   2455     if (parent->level == _BCM_KT_COSQ_NODE_LEVEL_ROOT) {
   2456         bmap = SOC_CONTROL(unit)->port_lls_l0_bmap[port];
   2457     } else if (parent->level == _BCM_KT_COSQ_NODE_LEVEL_L0) {
   2458         bmap = SOC_CONTROL(unit)->port_lls_l1_bmap[port];
   2459     } else if (parent->level == _BCM_KT_COSQ_NODE_LEVEL_L1) {
   2460         bmap = SOC_CONTROL(unit)->port_lls_l2_bmap[port];
   2461     }
   2462     switch (state) {
   2463         case _BCM_KT_COSQ_STATE_ENABLE:
   2464             if ((parent_mem == LLS_L0_PARENTm) &&
   2465                 SOC_MEM_FIELD_VALID(unit, LLS_L0_PARENTm, C_TYPEf)) {
   2466                 soc_mem_field32_set(unit, parent_mem, &entry_p, C_TYPEf, 1); 
   2467             }
   2468             soc_mem_field32_set(unit, parent_mem, &entry_p, C_PARENTf, parent->hw_index);
   2469             SOC_IF_ERROR_RETURN
   2470                 (soc_mem_write(unit, parent_mem, MEM_BLOCK_ANY, node->hw_index, &entry_p));
   2471             if (update_spri_vector) {
   2472                 SOC_IF_ERROR_RETURN
   2473                     (soc_mem_write(unit, config_mem, MEM_BLOCK_ANY, parent->hw_index, 
   2474                                    &entry_c));
   2475             }
   2476             
   2477             if (parent->level == _BCM_KT_COSQ_NODE_LEVEL_L1) {
   2478                 /* Read the entry from the RQE map in order to preserve the E_TYPE field */
   2479                 SOC_IF_ERROR_RETURN
   2480                     (READ_MMU_RQE_QUEUE_OP_NODE_MAPm(unit, MEM_BLOCK_ALL, node->hw_index,
   2481                                                      &rqe_op_node));
   2482                 soc_mem_field32_set(unit, MMU_RQE_QUEUE_OP_NODE_MAPm, &rqe_op_node,
   2483                                     OP_NODEf, parent->hw_index);           
   2484                 soc_mem_field32_set(unit, MMU_WRED_QUEUE_OP_NODE_MAPm, &wred_op_node,
   2485                                     OP_NODEf, parent->hw_index);    
   2486                 SOC_IF_ERROR_RETURN
   2487                     (WRITE_MMU_RQE_QUEUE_OP_NODE_MAPm(unit, MEM_BLOCK_ALL, node->hw_index,
   2488                                                       &rqe_op_node));
   2489                 SOC_IF_ERROR_RETURN
   2490                     (WRITE_MMU_WRED_QUEUE_OP_NODE_MAPm(unit, MEM_BLOCK_ALL, node->hw_index,
   2491                                                        &wred_op_node));            
   2492                 _soc_kt_cosq_end_port_flush(unit,node->hw_index);
   2493             }
   2494             _BCM_COSQ_PARENT_BMAP_SET(bmap, node->hw_index);
   2495             break;
   2496         case _BCM_KT_COSQ_STATE_DISABLE:
   2497             mmu_info = _bcm_kt_mmu_info[unit];
   2498             if (parent->level == _BCM_KT_COSQ_NODE_LEVEL_ROOT) {
   2499                 parent_index = (1 << soc_mem_field_length(unit, parent_mem, C_PARENTf)) - 1;
   2500             } else {    
   2501                 parent_index = mmu_info->max_nodes[parent->level] - 1;
   2502             }    
   2503             soc_mem_field32_set(unit, parent_mem, &entry_p, C_PARENTf, parent_index); 
   2504                                         
   2505             if (parent->level == _BCM_KT_COSQ_NODE_LEVEL_L1) {
   2506                 /* flush the queue  */
   2507                 if (!(SAL_BOOT_SIMULATION)) {
   2508                     BCM_IF_ERROR_RETURN(READ_TOQ_QUEUE_FLUSH0r(unit, &rval)); 
   2509                     flush_active = soc_reg_field_get(unit, TOQ_QUEUE_FLUSH0r, rval, 
   2510                                                      Q_FLUSH_ACTIVEf);
   2511                     if (flush_active == 1) {
   2512                         /* some other queue is in flush state, return failure */
   2513                         LOG_ERROR(BSL_LS_BCM_COMMON,
   2514                                   (BSL_META_U(unit,
   2515                                               "ERROR: Queue %d is already in flush state \n"),
   2516                                    (soc_reg_field_get(unit, TOQ_QUEUE_FLUSH0r, rval, 
   2517                                    Q_FLUSH_ID0f))));
   2518                         return BCM_E_BUSY;  
   2519                     }
   2520 
   2521                     soc_reg_field_set(unit, TOQ_QUEUE_FLUSH0r, &rval, Q_FLUSH_ID0f, 
   2522                                        node->hw_index);
   2523                     soc_reg_field_set(unit, TOQ_QUEUE_FLUSH0r, &rval, Q_FLUSH_NUMf, 1);
   2524                     soc_reg_field_set(unit, TOQ_QUEUE_FLUSH0r, &rval, Q_FLUSH_ACTIVEf, 1);
   2525                     soc_reg_field_set(unit, TOQ_QUEUE_FLUSH0r, &rval,
   2526                                       Q_FLUSH_EXTERNALf,
   2527                                       (IS_EXT_MEM_PORT(unit, port) ? 1: 0));
   2528                     BCM_IF_ERROR_RETURN(WRITE_TOQ_QUEUE_FLUSH0r(unit, rval)); 
   2529                     flush_active = 1;
   2530                     timeout_val = soc_property_get(unit, spn_MMU_QUEUE_FLUSH_TIMEOUT, 20000);
   2531                     soc_timeout_init(&timeout, timeout_val, 0);
   2532 
   2533                     while (flush_active) {                              
   2534                         BCM_IF_ERROR_RETURN(READ_TOQ_QUEUE_FLUSH0r(unit, &rval)); 
   2535                         flush_active = soc_reg_field_get(unit, TOQ_QUEUE_FLUSH0r, rval, 
   2536                                                      Q_FLUSH_ACTIVEf);
   2537                         if (soc_timeout_check(&timeout)) {
   2538                             LOG_ERROR(BSL_LS_BCM_COMMON,
   2539                                       (BSL_META_U(unit,
   2540                                                   "ERROR: Queue %d flush operation failed \n"), 
   2541                                        node->hw_index));
   2542                             return (BCM_E_TIMEOUT);
   2543                         }
   2544                     }
   2545                 }
   2546                 SOC_IF_ERROR_RETURN
   2547                     (READ_LLS_L2_CHILD_STATE1m(unit, MEM_BLOCK_ALL,
   2548                                                node->hw_index,
   2549                                                &l2_child_state));
   2550                 if (SOC_MEM_FIELD_VALID(unit, LLS_L2_CHILD_STATE1m, SPAREf)) {
   2551                     soc_mem_field_get(unit, LLS_L2_CHILD_STATE1m,
   2552                                       (uint32 *)&l2_child_state, SPAREf,
   2553                                       &spare);
   2554                 } else {
   2555                     soc_mem_field_get(unit, LLS_L2_CHILD_STATE1m,
   2556                                       (uint32 *)&l2_child_state, C_ON_WERR_LISTf,
   2557                                       &spare);
   2558                 }
   2559                 soc_mem_field_get(unit, LLS_L2_CHILD_STATE1m,
   2560                                   (uint32 *)&l2_child_state,
   2561                                   C_ON_MIN_LIST_0f, &min_list);
   2562                 soc_mem_field_get(unit, LLS_L2_CHILD_STATE1m,
   2563                                   (uint32 *)&l2_child_state,
   2564                                   C_ON_EF_LIST_0f, &ef_list);
   2565                 soc_mem_field_get(unit, LLS_L2_CHILD_STATE1m,
   2566                                   (uint32 *)&l2_child_state,
   2567                                   C_NOT_EMPTY_0f, &not_empty);
   2568                 /* check LLS_L2_CHILD_STATE[7:4] == 4'b0000 to confirm
   2569                  * that the node is empty */
   2570                 if (spare || min_list || ef_list || not_empty) {
   2571                     return BCM_E_BUSY;
   2572                 }
   2573                 SOC_IF_ERROR_RETURN
   2574                     (READ_LLS_L2_CHILD_STATE1m(unit, MEM_BLOCK_ALL, 
   2575                                                node->hw_index,
   2576                                                &l2_child_state));
   2577                 if (SOC_MEM_FIELD_VALID(unit, LLS_L2_CHILD_STATE1m, SPAREf)) {
   2578                     soc_mem_field_get(unit, LLS_L2_CHILD_STATE1m,
   2579                                       (uint32 *)&l2_child_state, SPAREf,
   2580                                       &spare);
   2581                 } else {
   2582                     soc_mem_field_get(unit, LLS_L2_CHILD_STATE1m,
   2583                                       (uint32 *)&l2_child_state, C_ON_WERR_LISTf,
   2584                                       &spare);
   2585                 }
   2586                 soc_mem_field_get(unit, LLS_L2_CHILD_STATE1m, 
   2587                                   (uint32 *)&l2_child_state, 
   2588                                   C_ON_MIN_LIST_0f, &min_list);
   2589                 soc_mem_field_get(unit, LLS_L2_CHILD_STATE1m, 
   2590                                   (uint32 *)&l2_child_state, 
   2591                                   C_ON_EF_LIST_0f, &ef_list);
   2592                 soc_mem_field_get(unit, LLS_L2_CHILD_STATE1m, 
   2593                                   (uint32 *)&l2_child_state, 
   2594                                   C_NOT_EMPTY_0f, &not_empty);
   2595                 /* check LLS_L2_CHILD_STATE[7:4] == 4'b0000 to confirm 
   2596                  * that the node is empty */
   2597                 if (spare || min_list || ef_list || not_empty) {
   2598                     return BCM_E_BUSY;  
   2599                 }    
   2600                 SOC_IF_ERROR_RETURN
   2601                     (READ_MMU_RQE_QUEUE_OP_NODE_MAPm(unit, MEM_BLOCK_ALL, node->hw_index,
   2602                                                  &rqe_op_node));
   2603                 soc_mem_field32_set(unit, MMU_RQE_QUEUE_OP_NODE_MAPm, &rqe_op_node,
   2604                                 OP_NODEf, parent_index);
   2605                 soc_mem_field32_set(unit, MMU_WRED_QUEUE_OP_NODE_MAPm, &wred_op_node,
   2606                                 OP_NODEf, parent_index);
   2607                 SOC_IF_ERROR_RETURN
   2608                     (soc_mem_write(unit, parent_mem, MEM_BLOCK_ANY, node->hw_index, &entry_p));
   2609                 SOC_IF_ERROR_RETURN
   2610                     (WRITE_MMU_RQE_QUEUE_OP_NODE_MAPm(unit, MEM_BLOCK_ALL, node->hw_index,
   2611                                                       &rqe_op_node));
   2612                 SOC_IF_ERROR_RETURN
   2613                     (WRITE_MMU_WRED_QUEUE_OP_NODE_MAPm(unit, MEM_BLOCK_ALL, node->hw_index,
   2614                                                        &wred_op_node));                                            
   2615             } else {
   2616                 SOC_IF_ERROR_RETURN
   2617                     (soc_mem_write(unit, parent_mem, MEM_BLOCK_ANY, node->hw_index, &entry_p));
   2618             }
   2619             if (update_spri_vector) {
   2620                 SOC_IF_ERROR_RETURN
   2621                     (soc_mem_write(unit, config_mem, MEM_BLOCK_ANY, parent->hw_index, 
   2622                                    &entry_c));
   2623             }
   2624             _BCM_COSQ_PARENT_BMAP_CLR(bmap, node->hw_index);
   2625             break;
   2626         case _BCM_KT_COSQ_STATE_WRR_TO_SPRI:
   2627         case _BCM_KT_COSQ_STATE_SPRI_TO_WRR:
   2628             if (update_spri_vector) {
   2629                 SOC_IF_ERROR_RETURN(_bcm_kt_egress_metering_freeze(unit,
   2630                             port, &setting));
   2631                 retval_temp = _bcm_kt_cosq_dynamic_sp_werr_change(unit, port, node->level, 
   2632                                 node->hw_index, parent->hw_index, entry_c[0], state);
   2633                 SOC_IF_ERROR_RETURN(_bcm_kt_egress_metering_thaw(unit, port, setting));
   2634                 if (BCM_FAILURE(retval_temp)) {
   2635                     return retval_temp;
   2636                 }
   2637             }
   2638             break;
   2639         default:
   2640             break;
   2641     }            
   2642 
   2643     return BCM_E_NONE;
   2644 }
   2645 
   2646 /*
   2647  * Function:
   2648  *     _bcm_kt_cosq_sched_node_set
   2649  * Purpose:
   2650  *     Set LLS scheduler registers based on GPORT
   2651  * Parameters:
   2652  *     unit       - (IN) unit number
   2653  *     gport      - (IN) queue group/scheduler GPORT identifier
   2654  * Returns:
   2655  *     BCM_E_XXX
   2656  */
   2657 STATIC int
   2658 _bcm_kt_cosq_sched_node_set(int unit, bcm_gport_t gport, 
   2659                                     _bcm_kt_cosq_state_t state)
   2660 {
   2661     _bcm_kt_cosq_node_t *node, *parent;
   2662     _bcm_kt_cosq_node_t *cur_node;
   2663     lls_port_config_entry_t port_cfg;
   2664     lls_l0_parent_entry_t l0_parent;
   2665     lls_l0_config_entry_t l0_cfg;
   2666     lls_l1_config_entry_t l1_cfg;
   2667     lls_l1_parent_entry_t l1_parent;
   2668     lls_l2_parent_entry_t l2_parent;
   2669     mmu_rqe_queue_op_node_map_entry_t rqe_op_node;
   2670     mmu_wred_queue_op_node_map_entry_t wred_op_node;
   2671     uint32 num_pri = 0, wrr_use = 0, start_pri = 0;
   2672     int port;
   2673     uint32 rval = 0;
   2674     int spri_nodes =0;
   2675     int set_wrr = 0;
   2676     int update_mem = 0;
   2677     int flush_active = 0;
   2678     int min_index;
   2679     soc_timeout_t timeout;
   2680     uint32 timeout_val;
   2681     uint32 *bmap = NULL;
   2682 
   2683     if (soc_feature(unit, soc_feature_vector_based_spri)) {
   2684         return _bcm_kt_cosq_sched_config_set(unit, gport, state);
   2685     }    
   2686     
   2687     /*  parent ->level == root
   2688       * config LLS_PORT_CONFIG, LLS_L0_PARENT points to port.
   2689 
   2690       * parent->level == L0
   2691       * config LLS_L0_CONFIG and LLS_L1_PARENT points to L0 queue
   2692 
   2693       * parent->level == L1
   2694       * config LLS_L1_CONFIG and LLS_L2_PARENT points to L1 queue
   2695      */
   2696 
   2697     BCM_IF_ERROR_RETURN
   2698         (_bcm_kt_cosq_node_get(unit, gport, NULL, &port, NULL,
   2699                                &node));
   2700 
   2701    /* read lls_config[level], if num_pri and num_child is diffent reprogram
   2702      * write lls_parent[level with node->parent->hw_index indexed on node_hw_index
   2703      */
   2704 
   2705     parent = node->parent;
   2706 
   2707     min_index = (node->level == _BCM_KT_COSQ_NODE_LEVEL_L2) ? 4095 :
   2708                 ((node->level == _BCM_KT_COSQ_NODE_LEVEL_L1) ? 1023 : 255);
   2709                     
   2710     if (parent->numq <= 8) {
   2711         for (cur_node = parent->child; cur_node != NULL;
   2712              cur_node = cur_node->sibling) {
   2713             if (cur_node->wrr_in_use == 0) {
   2714                 spri_nodes++;
   2715                 if (cur_node->hw_index < min_index) {
   2716                     min_index = cur_node->hw_index;
   2717                  }                     
   2718             } else {
   2719                set_wrr = 1;
   2720             }
   2721         }
   2722         if (spri_nodes == 1 && state == _BCM_KT_COSQ_STATE_DISABLE) {
   2723             /* this is the last spri node which gets deleted */
   2724             spri_nodes = 0;
   2725             min_index = (node->level == _BCM_KT_COSQ_NODE_LEVEL_L2) ? 4095 :
   2726                         ((node->level == _BCM_KT_COSQ_NODE_LEVEL_L1) ? 1023 : 255);     
   2727         } 
   2728         
   2729         parent->first_child = min_index;     
   2730     }
   2731 
   2732     if (parent->level == _BCM_KT_COSQ_NODE_LEVEL_ROOT) {
   2733         bmap = SOC_CONTROL(unit)->port_lls_l0_bmap[port];
   2734         SOC_IF_ERROR_RETURN
   2735             (READ_LLS_PORT_CONFIGm(unit, MEM_BLOCK_ALL, parent->hw_index, &port_cfg));
   2736 
   2737         wrr_use = soc_mem_field32_get(unit, LLS_PORT_CONFIGm, &port_cfg, P_WRR_IN_USEf);
   2738         num_pri = soc_mem_field32_get(unit, LLS_PORT_CONFIGm, &port_cfg, P_NUM_SPRIf);
   2739         start_pri = soc_mem_field32_get(unit, LLS_PORT_CONFIGm, &port_cfg, P_START_SPRIf);
   2740 
   2741         if (wrr_use != set_wrr) {
   2742             soc_mem_field32_set(unit, LLS_PORT_CONFIGm, &port_cfg, P_WRR_IN_USEf, set_wrr);
   2743             update_mem = 1;
   2744         }    
   2745         if (num_pri != spri_nodes) {
   2746             soc_mem_field32_set(unit, LLS_PORT_CONFIGm, &port_cfg, P_NUM_SPRIf, spri_nodes);
   2747             update_mem = 1;     
   2748         }    
   2749         if (start_pri != min_index) {
   2750             soc_mem_field32_set(unit, LLS_PORT_CONFIGm, &port_cfg, P_START_SPRIf, min_index);
   2751             update_mem = 1;
   2752         }    
   2753         
   2754         if (update_mem == 1) {
   2755             SOC_IF_ERROR_RETURN
   2756                 (WRITE_LLS_PORT_CONFIGm(unit, MEM_BLOCK_ALL, parent->hw_index, &port_cfg));
   2757         }    
   2758 
   2759         sal_memset(&l0_parent, 0, sizeof(lls_l0_parent_entry_t));  
   2760         if (state == _BCM_KT_COSQ_STATE_ENABLE) {  
   2761             soc_mem_field32_set(unit, LLS_L0_PARENTm, &l0_parent, C_PARENTf, parent->hw_index);
   2762             SOC_IF_ERROR_RETURN
   2763                 (WRITE_LLS_L0_PARENTm(unit, MEM_BLOCK_ALL, node->hw_index, &l0_parent));
   2764             _BCM_COSQ_PARENT_BMAP_SET(bmap, node->hw_index);
   2765         } 
   2766         if (state == _BCM_KT_COSQ_STATE_DISABLE) {  
   2767             soc_mem_field32_set(unit, LLS_L0_PARENTm, &l0_parent, C_PARENTf, 0x3f);
   2768             SOC_IF_ERROR_RETURN
   2769                 (WRITE_LLS_L0_PARENTm(unit, MEM_BLOCK_ALL, node->hw_index, &l0_parent));
   2770             _BCM_COSQ_PARENT_BMAP_CLR(bmap, node->hw_index);
   2771         }
   2772     } else if (parent->level == _BCM_KT_COSQ_NODE_LEVEL_L0) {
   2773         bmap = SOC_CONTROL(unit)->port_lls_l1_bmap[port];
   2774         SOC_IF_ERROR_RETURN
   2775             (READ_LLS_L0_CONFIGm(unit, MEM_BLOCK_ALL, parent->hw_index, &l0_cfg));
   2776 
   2777         wrr_use = soc_mem_field32_get(unit, LLS_L0_CONFIGm, &l0_cfg, P_WRR_IN_USEf);
   2778         num_pri = soc_mem_field32_get(unit, LLS_L0_CONFIGm, &l0_cfg, P_NUM_SPRIf);
   2779         start_pri = soc_mem_field32_get(unit, LLS_L0_CONFIGm, &l0_cfg, P_START_SPRIf);
   2780 
   2781         if (wrr_use != set_wrr) {
   2782             soc_mem_field32_set(unit, LLS_L0_CONFIGm, &l0_cfg, P_WRR_IN_USEf, set_wrr);
   2783             update_mem = 1;
   2784         }    
   2785         if (num_pri != spri_nodes) {
   2786             soc_mem_field32_set(unit, LLS_L0_CONFIGm, &l0_cfg, P_NUM_SPRIf, spri_nodes);
   2787             update_mem = 1;     
   2788         }    
   2789         if (start_pri != min_index) {
   2790             soc_mem_field32_set(unit, LLS_L0_CONFIGm, &l0_cfg, P_START_SPRIf, min_index);
   2791             update_mem = 1;
   2792         }    
   2793         
   2794         if (update_mem == 1) {
   2795             SOC_IF_ERROR_RETURN
   2796                 (WRITE_LLS_L0_CONFIGm(unit, MEM_BLOCK_ALL, parent->hw_index, &l0_cfg));
   2797         }    
   2798 
   2799         sal_memset(&l1_parent, 0, sizeof(lls_l1_parent_entry_t));
   2800         if (state == _BCM_KT_COSQ_STATE_ENABLE) {
   2801             soc_mem_field32_set(unit, LLS_L1_PARENTm, &l1_parent, C_PARENTf, parent->hw_index);
   2802             SOC_IF_ERROR_RETURN
   2803                 (WRITE_LLS_L1_PARENTm(unit, MEM_BLOCK_ALL, node->hw_index, &l1_parent));
   2804             _BCM_COSQ_PARENT_BMAP_SET(bmap, node->hw_index);
   2805         }
   2806         if (state == _BCM_KT_COSQ_STATE_DISABLE) {
   2807             soc_mem_field32_set(unit, LLS_L1_PARENTm, &l1_parent, C_PARENTf, 0xff);
   2808             SOC_IF_ERROR_RETURN
   2809                 (WRITE_LLS_L1_PARENTm(unit, MEM_BLOCK_ALL, node->hw_index, &l1_parent));
   2810             _BCM_COSQ_PARENT_BMAP_CLR(bmap, node->hw_index);
   2811         }
   2812     } else if (parent->level == _BCM_KT_COSQ_NODE_LEVEL_L1) {
   2813         bmap = SOC_CONTROL(unit)->port_lls_l2_bmap[port];
   2814         if (soc_feature(unit, soc_feature_dynamic_sched_update)) {
   2815             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   2816                 set_wrr = 0;  
   2817                 spri_nodes = 0;
   2818                 min_index = 0;
   2819             }
   2820         } else {
   2821             SOC_IF_ERROR_RETURN
   2822                 (READ_LLS_L1_CONFIGm(unit, MEM_BLOCK_ALL, parent->hw_index, &l1_cfg));
   2823             num_pri = soc_mem_field32_get(unit, LLS_L1_CONFIGm, &l1_cfg, P_NUM_SPRIf);
   2824             wrr_use = soc_mem_field32_get(unit, LLS_L1_CONFIGm, &l1_cfg, P_WRR_IN_USEf);
   2825             if (SOC_IS_KATANA2(unit)) {
   2826                 /* Changed in the latest QT Regfile. MMU Implementor to revisit / reconfirm */
   2827                 start_pri = soc_mem_field32_get(unit, LLS_L1_CONFIGm, &l1_cfg, P_START_UC_SPRIf);
   2828             } else {
   2829                 start_pri = soc_mem_field32_get(unit, LLS_L1_CONFIGm, &l1_cfg, P_START_SPRIf);
   2830             }
   2831         }    
   2832 
   2833         if (wrr_use != set_wrr) {
   2834             soc_mem_field32_set(unit, LLS_L1_CONFIGm, &l1_cfg, P_WRR_IN_USEf, set_wrr);
   2835             update_mem = 1;
   2836         }    
   2837         if (num_pri != spri_nodes) {
   2838             soc_mem_field32_set(unit, LLS_L1_CONFIGm, &l1_cfg, P_NUM_SPRIf, spri_nodes);
   2839             update_mem = 1;     
   2840         }    
   2841         if (start_pri != min_index) {
   2842             if (SOC_IS_KATANA2(unit)) {
   2843                 soc_mem_field32_set(unit, LLS_L1_CONFIGm, &l1_cfg, P_START_UC_SPRIf, min_index);
   2844             } else {
   2845                 soc_mem_field32_set(unit, LLS_L1_CONFIGm, &l1_cfg, P_START_SPRIf, min_index);
   2846             }
   2847             update_mem = 1;
   2848         }
   2849         if (state != _BCM_KT_COSQ_STATE_DISABLE && update_mem == 1) {
   2850             SOC_IF_ERROR_RETURN
   2851                 (WRITE_LLS_L1_CONFIGm(unit, MEM_BLOCK_ALL, parent->hw_index, &l1_cfg));
   2852         }
   2853 
   2854         sal_memset(&l2_parent, 0, sizeof(lls_l2_parent_entry_t));
   2855         sal_memset(&rqe_op_node, 0, sizeof(mmu_rqe_queue_op_node_map_entry_t));
   2856         sal_memset(&wred_op_node, 0, sizeof(mmu_wred_queue_op_node_map_entry_t));
   2857         
   2858         if (state == _BCM_KT_COSQ_STATE_ENABLE) {            
   2859             soc_mem_field32_set(unit, LLS_L2_PARENTm, &l2_parent, 
   2860                                 C_PARENTf, parent->hw_index);
   2861             SOC_IF_ERROR_RETURN
   2862                 (WRITE_LLS_L2_PARENTm(unit, MEM_BLOCK_ALL, node->hw_index, 
   2863                                       &l2_parent));
   2864             /* Read the entry from the RQE map in order to preserve the E_TYPE field */
   2865             SOC_IF_ERROR_RETURN
   2866                 (READ_MMU_RQE_QUEUE_OP_NODE_MAPm(unit, MEM_BLOCK_ALL, node->hw_index,
   2867                                                  &rqe_op_node));
   2868             soc_mem_field32_set(unit, MMU_RQE_QUEUE_OP_NODE_MAPm, &rqe_op_node,
   2869                                 OP_NODEf, parent->hw_index);           
   2870             soc_mem_field32_set(unit, MMU_WRED_QUEUE_OP_NODE_MAPm, &wred_op_node,
   2871                                 OP_NODEf, parent->hw_index);    
   2872             SOC_IF_ERROR_RETURN
   2873                 (WRITE_MMU_RQE_QUEUE_OP_NODE_MAPm(unit, MEM_BLOCK_ALL, node->hw_index,
   2874                                                   &rqe_op_node));
   2875             SOC_IF_ERROR_RETURN
   2876                 (WRITE_MMU_WRED_QUEUE_OP_NODE_MAPm(unit, MEM_BLOCK_ALL, node->hw_index,
   2877                                                    &wred_op_node));            
   2878             _soc_kt_cosq_end_port_flush(unit,node->hw_index);
   2879             _BCM_COSQ_PARENT_BMAP_SET(bmap, node->hw_index);
   2880         } else if (state == _BCM_KT_COSQ_STATE_DISABLE) {
   2881             /* deletion case , flush the queue  */
   2882             BCM_IF_ERROR_RETURN(READ_TOQ_QUEUE_FLUSH0r(unit, &rval)); 
   2883             flush_active = soc_reg_field_get(unit, TOQ_QUEUE_FLUSH0r, rval, 
   2884                                              Q_FLUSH_ACTIVEf);
   2885             if (flush_active == 1) {
   2886                 /* some other queue is in flush state, return failure */
   2887                 LOG_ERROR(BSL_LS_BCM_COMMON,
   2888                           (BSL_META_U(unit,
   2889                                       "ERROR: Queue %d is already in flush state \n"),
   2890                            (soc_reg_field_get(unit, TOQ_QUEUE_FLUSH0r, rval, 
   2891                            Q_FLUSH_ID0f))));
   2892                 return BCM_E_BUSY;  
   2893             }
   2894 
   2895             if (!(SAL_BOOT_SIMULATION)) {
   2896                 soc_reg_field_set(unit, TOQ_QUEUE_FLUSH0r, &rval, Q_FLUSH_ID0f, 
   2897                                   node->hw_index);
   2898                 soc_reg_field_set(unit, TOQ_QUEUE_FLUSH0r, &rval, Q_FLUSH_NUMf, 1);
   2899                 soc_reg_field_set(unit, TOQ_QUEUE_FLUSH0r, &rval, Q_FLUSH_ACTIVEf, 1);
   2900                 soc_reg_field_set(unit, TOQ_QUEUE_FLUSH0r, &rval,
   2901                                   Q_FLUSH_EXTERNALf,
   2902                                   (IS_EXT_MEM_PORT(unit, port) ? 1: 0));
   2903 
   2904                 BCM_IF_ERROR_RETURN(WRITE_TOQ_QUEUE_FLUSH0r(unit, rval)); 
   2905             }
   2906             flush_active = 1;
   2907             timeout_val = soc_property_get(unit, spn_MMU_QUEUE_FLUSH_TIMEOUT, 20000);
   2908             soc_timeout_init(&timeout, timeout_val, 0);
   2909 
   2910             while (flush_active) {                              
   2911                 BCM_IF_ERROR_RETURN(READ_TOQ_QUEUE_FLUSH0r(unit, &rval)); 
   2912                 flush_active = soc_reg_field_get(unit, TOQ_QUEUE_FLUSH0r, rval, 
   2913                                              Q_FLUSH_ACTIVEf);
   2914                 if (soc_timeout_check(&timeout)) {
   2915                     LOG_ERROR(BSL_LS_BCM_COMMON,
   2916                               (BSL_META_U(unit,
   2917                                           "ERROR: Queue %d flush operation failed \n"), 
   2918                                node->hw_index));
   2919                     return (BCM_E_TIMEOUT);
   2920                 }
   2921             }
   2922 
   2923             soc_mem_field32_set(unit, LLS_L2_PARENTm, &l2_parent, 
   2924                                 C_PARENTf, 0x3ff);
   2925             soc_mem_field32_set(unit, MMU_RQE_QUEUE_OP_NODE_MAPm, &rqe_op_node,
   2926                                 OP_NODEf, 0x3ff);
   2927             soc_mem_field32_set(unit, MMU_WRED_QUEUE_OP_NODE_MAPm, &wred_op_node,
   2928                                 OP_NODEf, 0x3ff);
   2929             SOC_IF_ERROR_RETURN
   2930                 (WRITE_LLS_L2_PARENTm(unit, MEM_BLOCK_ALL, node->hw_index, 
   2931                                       &l2_parent));
   2932             SOC_IF_ERROR_RETURN
   2933                 (WRITE_MMU_RQE_QUEUE_OP_NODE_MAPm(unit, MEM_BLOCK_ALL, node->hw_index,
   2934                                                   &rqe_op_node));
   2935             SOC_IF_ERROR_RETURN
   2936                 (WRITE_MMU_WRED_QUEUE_OP_NODE_MAPm(unit, MEM_BLOCK_ALL, node->hw_index,
   2937                                                    &wred_op_node));   
   2938             if (update_mem == 1) {
   2939                 SOC_IF_ERROR_RETURN
   2940                     (WRITE_LLS_L1_CONFIGm(unit, MEM_BLOCK_ALL, parent->hw_index, &l1_cfg));
   2941             }
   2942             _BCM_COSQ_PARENT_BMAP_CLR(bmap, node->hw_index);
   2943         }
   2944     } else {
   2945         return BCM_E_PARAM;
   2946     }
   2947 
   2948     return BCM_E_NONE;
   2949 }
   2950 
   2951 /*
   2952  * Function:
   2953  *     _bcm_kt_cosq_sched_set
   2954  * Purpose:
   2955  *     Set scheduling mode
   2956  * Parameters:
   2957  *     unit                - (IN) unit number
   2958  *     port                - (IN) port number or GPORT identifier
   2959  *     cosq                - (IN) COS queue number
   2960  *     mode                - (IN) scheduling mode (BCM_COSQ_XXX)
   2961  *     num_weights         - (IN) number of entries in weights array
   2962  *     weights             - (IN) weights array
   2963  * Returns:
   2964  *     BCM_E_XXX
   2965  */
   2966 STATIC int
   2967 _bcm_kt_cosq_sched_set(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   2968                        int mode, int num_weights, const int weights[])
   2969 {
   2970     _bcm_kt_mmu_info_t *mmu_info;
   2971     _bcm_kt_cosq_node_t *node, *cur_node, *l0_node;
   2972     bcm_port_t local_port;
   2973     int index;
   2974     int i;
   2975     int max_weight;
   2976     lls_l0_child_weight_cfg_cnt_entry_t l0_weight_cfg;
   2977     lls_l1_child_weight_cfg_cnt_entry_t l1_weight_cfg; 
   2978     lls_l2_child_weight_cfg_cnt_entry_t l2_weight_cfg;
   2979     lls_l2_parent_entry_t l2_parent;
   2980     _bcm_kt_cosq_state_t state = _BCM_KT_COSQ_STATE_NO_CHANGE;
   2981     int parent_id;
   2982     bcm_gport_t remap_gport;
   2983     int numq;
   2984     uint32 fval;
   2985     uint32 entry[SOC_MAX_MEM_WORDS];
   2986     soc_mem_t mem;
   2987     int rv;
   2988 
   2989     if (cosq < 0) { 
   2990         if (cosq == -1) {
   2991             /* caller needs to resolve the wild card value */
   2992             return BCM_E_INTERNAL;
   2993         } else {
   2994             /* reject all other negative value */
   2995             return BCM_E_PARAM;
   2996         } 
   2997     }
   2998     
   2999     /* Validate weight values */
   3000     if (mode == BCM_COSQ_ROUND_ROBIN ||
   3001         mode == BCM_COSQ_WEIGHTED_ROUND_ROBIN ||
   3002         mode == BCM_COSQ_DEFICIT_ROUND_ROBIN ||
   3003         mode == BCM_COSQ_STRICT) {
   3004         max_weight =
   3005             (1 << soc_mem_field_length(unit, LLS_L0_CHILD_WEIGHT_CFG_CNTm, C_WEIGHTf)) - 1;
   3006         for (i = 0; i < num_weights; i++) {
   3007             if (weights[i] < 0 || weights[i] > max_weight) {
   3008                 return BCM_E_PARAM;
   3009             }
   3010         }
   3011     } else {
   3012         return BCM_E_PARAM;
   3013     }
   3014 
   3015     /* To support legacy device compatibility to configure STRICT
   3016        mode if weight is "0".
   3017      */
   3018     if ((num_weights == 1) && (weights[0] == BCM_COSQ_WEIGHT_STRICT)) {
   3019         mode =  BCM_COSQ_STRICT;
   3020     }
   3021 
   3022     mmu_info = _bcm_kt_mmu_info[unit];
   3023     
   3024     if (BCM_GPORT_IS_SCHEDULER(port)) { /* ETS style scheduler */
   3025         BCM_IF_ERROR_RETURN
   3026             (_bcm_kt_cosq_node_get(unit, port, NULL, &local_port, NULL,
   3027                                    &node));        
   3028     }else {
   3029         BCM_IF_ERROR_RETURN
   3030             (_bcm_kt_cosq_localport_resolve(unit, port, &local_port));
   3031 
   3032         node = &mmu_info->sched_node[local_port];
   3033         
   3034         if (node->gport < 0) {
   3035             return BCM_E_PARAM;
   3036         }
   3037 
   3038         if ((l0_node = node->child) == NULL) {
   3039             return BCM_E_PARAM;
   3040         }
   3041         if (!soc_feature(unit, soc_feature_dynamic_sched_update)) {   
   3042             if ((node = l0_node->child) == NULL) {
   3043                 return BCM_E_PARAM;
   3044             }    
   3045         } else {
   3046             node = l0_node;
   3047         } 
   3048         if (IS_CPU_PORT(unit, local_port)) {
   3049             /*
   3050             * In case when number of cpu queues are not multiples of 8
   3051             * there is chance last siblings gets numq < 8,
   3052             * which may result in failure , So node is moved to the
   3053             * first sibling, which guarantee to have numq = 8
   3054             */
   3055             for (cur_node = l0_node; cur_node->sibling != NULL;
   3056                     cur_node = cur_node->sibling) {
   3057                   if (cur_node->numq == 5) {
   3058                      break;
   3059                   }
   3060                }
   3061             for (cur_node = cur_node->child; cur_node->sibling != NULL;
   3062                     cur_node = cur_node->sibling);
   3063             node = cur_node;
   3064         }
   3065 
   3066     }
   3067 
   3068     if ((mode != BCM_COSQ_STRICT) && 
   3069         (node->numq > 0 && (cosq + num_weights) > node->numq)) {
   3070         return BCM_E_PARAM;
   3071     }
   3072 
   3073     
   3074     if (node->cosq_attached_to < 0) { /* Not resolved yet */
   3075         return BCM_E_NOT_FOUND;
   3076     }
   3077 
   3078     if (!soc_feature(unit, soc_feature_dynamic_sched_update) ||
   3079         BCM_GPORT_IS_SCHEDULER(port)) { 
   3080         for (cur_node = node->child; cur_node != NULL;
   3081             cur_node = cur_node->sibling) {
   3082             if (cur_node->cosq_attached_to == cosq) {
   3083                 break;
   3084             }
   3085         }
   3086     } else {        
   3087         numq = soc_property_get(unit, spn_BCM_NUM_COS, BCM_COS_DEFAULT);
   3088         for (cur_node = node->child; cur_node != NULL;
   3089             cur_node = cur_node->sibling) {
   3090             if (cur_node->child != NULL && (cur_node->cosq_attached_to == cosq ||
   3091                 cur_node->cosq_attached_to == (cosq + numq))) {
   3092                 break;
   3093             }
   3094         } 
   3095 
   3096         if (cur_node != NULL) {
   3097             cur_node = cur_node->child;
   3098         }
   3099     }
   3100     
   3101     if (cur_node == NULL) {
   3102         /* this cosq is not yet attached */
   3103         return BCM_E_INTERNAL;
   3104     }
   3105 
   3106     if (cur_node->wrr_in_use == 1 && mode == BCM_COSQ_STRICT) {
   3107         if (cur_node->cosq_attached_to >= 8) {
   3108             return BCM_E_PARAM;
   3109         }  
   3110         if (!soc_feature(unit, soc_feature_dynamic_sched_update) &&
   3111             !soc_feature(unit, soc_feature_vector_based_spri) &&
   3112             _bcm_kt_cosq_valid_werr_node(unit, node, cur_node->cosq_attached_to, 1) == 0)
   3113             {
   3114             return BCM_E_PARAM;
   3115         }        
   3116         state = _BCM_KT_COSQ_STATE_WRR_TO_SPRI;        
   3117     }    
   3118 
   3119     if (cur_node->wrr_in_use == 0 && mode != BCM_COSQ_STRICT) {
   3120         if (!soc_feature(unit, soc_feature_dynamic_sched_update) &&
   3121             !soc_feature(unit, soc_feature_vector_based_spri) &&
   3122             _bcm_kt_cosq_valid_werr_node(unit, node, cur_node->cosq_attached_to, 0) == 0)
   3123             {
   3124             return BCM_E_PARAM;
   3125         }
   3126         state = _BCM_KT_COSQ_STATE_SPRI_TO_WRR;
   3127     }    
   3128 
   3129     if (state == _BCM_KT_COSQ_STATE_SPRI_TO_WRR && 
   3130         cur_node->level == _BCM_KT_COSQ_NODE_LEVEL_L2) {
   3131         SOC_IF_ERROR_RETURN
   3132             (READ_LLS_L2_PARENTm(unit, MEM_BLOCK_ALL, cur_node->hw_index, 
   3133                                  &l2_parent));
   3134         if (soc_mem_field32_get(unit, LLS_L2_PARENTm, 
   3135                                 &l2_parent, C_EFf) == 1) {
   3136             return BCM_E_PARAM;
   3137         }
   3138     }
   3139 
   3140     if (soc_feature(unit, soc_feature_dynamic_sched_update) &&
   3141         !BCM_GPORT_IS_SCHEDULER(port)) {
   3142         if (state == _BCM_KT_COSQ_STATE_WRR_TO_SPRI ||
   3143             state == _BCM_KT_COSQ_STATE_SPRI_TO_WRR) {
   3144         parent_id = (BCM_GPORT_SCHEDULER_GET(cur_node->parent->gport) >> 8) & 0x7ff;
   3145         remap_gport = mmu_info->l1_gport_pair[parent_id];
   3146         BCM_IF_ERROR_RETURN
   3147             (_bcm_kt_cosq_dynamic_sched_update(unit, port, cosq, mode, cur_node));
   3148         BCM_IF_ERROR_RETURN
   3149             (_bcm_kt_cosq_node_get(unit, remap_gport, NULL, &local_port, NULL,
   3150                                    &node));
   3151         } else {
   3152             BCM_IF_ERROR_RETURN
   3153                 (_bcm_kt_cosq_node_get(unit, cur_node->parent->gport, 
   3154                                        NULL, &local_port, NULL,
   3155                                        &node));
   3156         }
   3157         port = node->parent->gport;
   3158         cosq = node->cosq_attached_to;   
   3159         BCM_IF_ERROR_RETURN
   3160             (_bcm_kt_cosq_node_get(unit, port, NULL, &local_port, NULL,
   3161                                    &node));        
   3162     } else {
   3163         cur_node->wrr_in_use = (mode != BCM_COSQ_STRICT) ? 1 : 0;
   3164         rv = _bcm_kt_cosq_sched_node_set(unit, cur_node->gport, state);
   3165         if (BCM_FAILURE(rv)) {
   3166             if (state == _BCM_KT_COSQ_STATE_SPRI_TO_WRR) {
   3167                 cur_node->wrr_in_use = 0;
   3168             } else if (state == _BCM_KT_COSQ_STATE_WRR_TO_SPRI) {
   3169                 cur_node->wrr_in_use = 1;
   3170             }
   3171         }
   3172     }
   3173 
   3174     if (mode != BCM_COSQ_STRICT) {
   3175         mem = LLS_PORT_CONFIGm;
   3176         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, 
   3177                                          local_port, &entry));
   3178         fval = ((mode == BCM_COSQ_WEIGHTED_ROUND_ROBIN) ||
   3179                 (mode == BCM_COSQ_ROUND_ROBIN)) ? 1 : 0;
   3180         if (soc_mem_field32_get(unit, mem, entry, 
   3181                                 PACKET_MODE_WRR_ACCOUNTING_ENABLEf) != fval) {
   3182             soc_mem_field32_set(unit, mem, entry,
   3183                                 PACKET_MODE_WRR_ACCOUNTING_ENABLEf, fval);
   3184             BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ANY,
   3185                                 local_port, &entry)); 
   3186         } 
   3187     }
   3188 
   3189     switch (node->level) {
   3190     case _BCM_KT_COSQ_NODE_LEVEL_ROOT: /* port scheduler */
   3191         for (i = 0; i < num_weights; i++) {
   3192             BCM_IF_ERROR_RETURN
   3193                    (_bcm_kt_cosq_index_resolve(unit, port, cosq + i,
   3194                                        _BCM_KT_COSQ_INDEX_STYLE_SCHEDULER,
   3195                                        NULL, &index, NULL));
   3196             SOC_IF_ERROR_RETURN
   3197                    (READ_LLS_L0_CHILD_WEIGHT_CFG_CNTm(unit, MEM_BLOCK_ALL, index, &l0_weight_cfg));
   3198             soc_mem_field32_set(unit, LLS_L0_CHILD_WEIGHT_CFG_CNTm, (uint32 *)&l0_weight_cfg, 
   3199                                 C_WEIGHTf, (mode == BCM_COSQ_ROUND_ROBIN) ? 1: weights[i]); 
   3200             soc_mem_field32_set(unit, LLS_L0_CHILD_WEIGHT_CFG_CNTm, (uint32 *)&l0_weight_cfg, 
   3201                                 C_WEIGHT_SURPLUS_COUNTf, 0);
   3202             soc_mem_field32_set(unit, LLS_L0_CHILD_WEIGHT_CFG_CNTm, (uint32 *)&l0_weight_cfg, 
   3203                                 C_WEIGHT_COUNTf, 0);
   3204             SOC_IF_ERROR_RETURN
   3205                    (WRITE_LLS_L0_CHILD_WEIGHT_CFG_CNTm(unit, MEM_BLOCK_ALL, index, &l0_weight_cfg));
   3206 
   3207         }
   3208         break;
   3209 
   3210     case _BCM_KT_COSQ_NODE_LEVEL_L0: /* L0 scheduler */
   3211         for (i = 0; i < num_weights; i++) {
   3212             BCM_IF_ERROR_RETURN
   3213                    (_bcm_kt_cosq_index_resolve(unit, port, cosq + i,
   3214                                        _BCM_KT_COSQ_INDEX_STYLE_SCHEDULER,
   3215                                         NULL, &index, NULL));
   3216             SOC_IF_ERROR_RETURN
   3217                    (READ_LLS_L1_CHILD_WEIGHT_CFG_CNTm(unit, MEM_BLOCK_ALL, index, &l1_weight_cfg));
   3218             soc_mem_field32_set(unit, LLS_L1_CHILD_WEIGHT_CFG_CNTm, (uint32 *)&l1_weight_cfg, 
   3219                                 C_WEIGHTf, (mode == BCM_COSQ_ROUND_ROBIN) ? 1: weights[i]); 
   3220             soc_mem_field32_set(unit, LLS_L1_CHILD_WEIGHT_CFG_CNTm, (uint32 *)&l1_weight_cfg, 
   3221                                 C_WEIGHT_SURPLUS_COUNTf, 0);
   3222             soc_mem_field32_set(unit, LLS_L1_CHILD_WEIGHT_CFG_CNTm, (uint32 *)&l1_weight_cfg, 
   3223                                 C_WEIGHT_COUNTf, 0);
   3224             SOC_IF_ERROR_RETURN
   3225                    (WRITE_LLS_L1_CHILD_WEIGHT_CFG_CNTm(unit, MEM_BLOCK_ALL, index, &l1_weight_cfg));
   3226 
   3227         }
   3228         break;
   3229 
   3230     case _BCM_KT_COSQ_NODE_LEVEL_L1: /* L1 scheduler */
   3231         for (i = 0; i < num_weights; i++) {
   3232             BCM_IF_ERROR_RETURN
   3233                    (_bcm_kt_cosq_index_resolve(unit, port, cosq + i,
   3234                                        _BCM_KT_COSQ_INDEX_STYLE_SCHEDULER,
   3235                                         NULL, &index, NULL));
   3236             SOC_IF_ERROR_RETURN
   3237                    (READ_LLS_L2_CHILD_WEIGHT_CFG_CNTm(unit, MEM_BLOCK_ALL, index, &l2_weight_cfg));
   3238             soc_mem_field32_set(unit, LLS_L2_CHILD_WEIGHT_CFG_CNTm, (uint32 *)&l2_weight_cfg, 
   3239                                 C_WEIGHTf, (mode == BCM_COSQ_ROUND_ROBIN) ? 1: weights[i]); 
   3240             soc_mem_field32_set(unit, LLS_L2_CHILD_WEIGHT_CFG_CNTm, (uint32 *)&l2_weight_cfg, 
   3241                                 C_WEIGHT_SURPLUS_COUNTf, 0);
   3242             soc_mem_field32_set(unit, LLS_L2_CHILD_WEIGHT_CFG_CNTm, (uint32 *)&l2_weight_cfg, 
   3243                                 C_WEIGHT_COUNTf, 0);
   3244             SOC_IF_ERROR_RETURN
   3245                    (WRITE_LLS_L2_CHILD_WEIGHT_CFG_CNTm(unit, MEM_BLOCK_ALL, index, &l2_weight_cfg));
   3246 
   3247         }
   3248         break;
   3249 
   3250     default:
   3251         return BCM_E_INTERNAL;
   3252     }
   3253 
   3254     return BCM_E_NONE;
   3255 }
   3256 
   3257 /*
   3258  * Function:
   3259  *     _bcm_kt_cosq_sched_get
   3260  * Purpose:
   3261  *     Get scheduling mode setting
   3262  * Parameters:
   3263  *     unit                - (IN) unit number
   3264  *     port                - (IN) port number or GPORT identifier
   3265  *     cosq                - (IN) COS queue number
   3266  *     mode                - (OUT) scheduling mode (BCM_COSQ_XXX)
   3267  *     num_weights         - (IN) number of entries in weights array
   3268  *     weights             - (OUT) weights array
   3269  * Returns:
   3270  *     BCM_E_XXX
   3271  */
   3272 STATIC int
   3273 _bcm_kt_cosq_sched_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   3274                        int *mode, int num_weights, int weights[])
   3275 {
   3276     _bcm_kt_mmu_info_t *mmu_info; 
   3277     _bcm_kt_cosq_node_t *node, *l0_node = NULL;
   3278     _bcm_kt_cosq_node_t *cur_node;
   3279     bcm_port_t local_port;
   3280     int index;
   3281     int i;
   3282     lls_l0_child_weight_cfg_cnt_entry_t l0_weight_cfg;
   3283     lls_l1_child_weight_cfg_cnt_entry_t l1_weight_cfg;
   3284     lls_l2_child_weight_cfg_cnt_entry_t l2_weight_cfg;
   3285     int numq;
   3286     soc_mem_t mem;
   3287     uint32 entry[SOC_MAX_MEM_WORDS];
   3288 
   3289     if (cosq < 0) {
   3290         if (cosq == -1) {
   3291             /* caller needs to resolve the wild card value */
   3292             return BCM_E_INTERNAL;
   3293         } else {
   3294             /* reject all other negative value */
   3295             return BCM_E_PARAM;
   3296         } 
   3297     }
   3298 
   3299     if (BCM_GPORT_IS_SCHEDULER(port)) { /* ETS style scheduler */
   3300            BCM_IF_ERROR_RETURN
   3301                (_bcm_kt_cosq_node_get(unit, port, NULL, &local_port, NULL,
   3302                                       &node));
   3303     } else {
   3304         BCM_IF_ERROR_RETURN
   3305             (_bcm_kt_cosq_localport_resolve(unit, port, &local_port));
   3306         mmu_info = _bcm_kt_mmu_info[unit];
   3307 
   3308         node = &mmu_info->sched_node[local_port];
   3309         
   3310         if (node->gport < 0) {
   3311             return BCM_E_PARAM;
   3312         }
   3313 
   3314         if ((l0_node = node->child) == NULL) {
   3315             return BCM_E_PARAM;
   3316         }
   3317         if (!soc_feature(unit, soc_feature_dynamic_sched_update)) {
   3318             if ((node = l0_node->child) == NULL) {
   3319                 return BCM_E_PARAM;
   3320             }    
   3321         } else {
   3322             node = l0_node;
   3323         }
   3324         if (IS_CPU_PORT(unit, local_port)) {
   3325             /*
   3326             * In case when number of cpu queues are not multiples of 8
   3327             * there is chance last siblings gets numq < 8,
   3328             * which may result in failure , So node is moved to the
   3329             * first sibling, which guarantee to have numq = 8
   3330             */
   3331             for (cur_node = l0_node; cur_node->sibling != NULL;
   3332                     cur_node = cur_node->sibling) {
   3333                 /* After warm boot first sibling will have numq = 4
   3334                  * check for the parent node in which all childs will have the numq = 8
   3335                  * so we wont see failure 
   3336                  */
   3337                 if (cur_node->numq == 5) {
   3338                     break;
   3339                 }
   3340             }
   3341             for (cur_node = cur_node->child; cur_node->sibling != NULL;
   3342                     cur_node = cur_node->sibling);
   3343             node = cur_node;
   3344         }
   3345     }
   3346 
   3347     if (node->numq > 0 && (cosq + num_weights) > node->numq) {
   3348         return BCM_E_PARAM;
   3349     }
   3350 
   3351     if (node->cosq_attached_to < 0) { /* Not resolved yet */
   3352         return BCM_E_NOT_FOUND;
   3353     }
   3354 
   3355     if (!soc_feature(unit, soc_feature_dynamic_sched_update)) {
   3356         for (cur_node = node->child; cur_node != NULL;
   3357             cur_node = cur_node->sibling) {
   3358             if (cur_node->cosq_attached_to == cosq) {
   3359                 break;
   3360             }
   3361         }
   3362     } else {    
   3363         numq = soc_property_get(unit, spn_BCM_NUM_COS, BCM_COS_DEFAULT);
   3364         for (cur_node = node->child; cur_node != NULL;
   3365             cur_node = cur_node->sibling) {
   3366             if (cur_node->child != NULL && (cur_node->cosq_attached_to == cosq ||
   3367                 cur_node->cosq_attached_to == (cosq + numq))) {
   3368                 break;
   3369             }
   3370         } 
   3371 
   3372         if (cur_node != NULL) {
   3373             port = l0_node->gport;
   3374             cosq = cur_node->cosq_attached_to;
   3375         }
   3376     }
   3377     
   3378     switch (node->level) {
   3379     case _BCM_KT_COSQ_NODE_LEVEL_ROOT: /* port scheduler */
   3380         for (i = 0; i < num_weights; i++) {
   3381             BCM_IF_ERROR_RETURN
   3382                 (_bcm_kt_cosq_index_resolve(unit, port, cosq + i,
   3383                                         _BCM_KT_COSQ_INDEX_STYLE_SCHEDULER,
   3384                                         NULL, &index, NULL));
   3385             SOC_IF_ERROR_RETURN
   3386                 (READ_LLS_L0_CHILD_WEIGHT_CFG_CNTm(unit, MEM_BLOCK_ALL, index, &l0_weight_cfg));
   3387             weights[i] = soc_mem_field32_get(unit, LLS_L0_CHILD_WEIGHT_CFG_CNTm, (uint32 *)&l0_weight_cfg, C_WEIGHTf);
   3388         }
   3389         break;
   3390 
   3391     case _BCM_KT_COSQ_NODE_LEVEL_L0: /* L0 scheduler */
   3392         for (i = 0; i < num_weights; i++) {
   3393             BCM_IF_ERROR_RETURN
   3394                 (_bcm_kt_cosq_index_resolve(unit, port, cosq + i,
   3395                                         _BCM_KT_COSQ_INDEX_STYLE_SCHEDULER,
   3396                                         NULL, &index, NULL));
   3397             SOC_IF_ERROR_RETURN
   3398                 (READ_LLS_L1_CHILD_WEIGHT_CFG_CNTm(unit, MEM_BLOCK_ALL, index, &l1_weight_cfg));
   3399             weights[i] = soc_mem_field32_get(unit, LLS_L1_CHILD_WEIGHT_CFG_CNTm, (uint32 *)&l1_weight_cfg, C_WEIGHTf);
   3400 
   3401         }
   3402         break;
   3403 
   3404     case _BCM_KT_COSQ_NODE_LEVEL_L1: /* L1 scheduler */
   3405         for (i = 0; i < num_weights; i++) {
   3406             BCM_IF_ERROR_RETURN
   3407                 (_bcm_kt_cosq_index_resolve(unit, port, cosq + i,
   3408                                         _BCM_KT_COSQ_INDEX_STYLE_SCHEDULER,
   3409                                         NULL, &index, NULL));
   3410             SOC_IF_ERROR_RETURN
   3411                 (READ_LLS_L2_CHILD_WEIGHT_CFG_CNTm(unit, MEM_BLOCK_ALL, index, &l2_weight_cfg));
   3412             weights[i] = soc_mem_field32_get(unit, LLS_L2_CHILD_WEIGHT_CFG_CNTm, (uint32 *)&l2_weight_cfg, C_WEIGHTf);
   3413 
   3414         }
   3415         break;
   3416 
   3417     default:
   3418         return BCM_E_INTERNAL;
   3419     }
   3420 
   3421     if (cur_node->wrr_in_use == 0) {
   3422         *mode = BCM_COSQ_STRICT;   
   3423     } else {   
   3424         mem = LLS_PORT_CONFIGm;
   3425         BCM_IF_ERROR_RETURN(
   3426                 soc_mem_read(unit, mem, MEM_BLOCK_ALL, local_port, &entry));
   3427         if (soc_mem_field32_get(unit, mem, entry,
   3428                    PACKET_MODE_WRR_ACCOUNTING_ENABLEf)) {
   3429             *mode = BCM_COSQ_WEIGHTED_ROUND_ROBIN;
   3430         } else {
   3431             *mode = BCM_COSQ_DEFICIT_ROUND_ROBIN;
   3432         }
   3433 
   3434     }
   3435     
   3436     return BCM_E_NONE;
   3437 }
   3438 
   3439 /*
   3440  * Function:
   3441  *     _bcm_kt_cosq_port_sched_set
   3442  * Purpose:
   3443  *     Set scheduling mode setting for a port
   3444  * Parameters:
   3445  *     unit                - (IN) unit number
   3446  *     port                - (IN) port number or GPORT identifier
   3447  *     cosq                - (IN) COS queue number
   3448  *     mode                - (IN) scheduling mode (BCM_COSQ_XXX)
   3449  *     num_weights         - (IN) number of entries in weights array
   3450  *     weights             - (IN) weights array
   3451  * Returns:
   3452  *     BCM_E_XXX
   3453  */
   3454 STATIC int
   3455 _bcm_kt_cosq_port_sched_set(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   3456                                    int mode, int num_weights, int *weights)
   3457 {
   3458     int i;
   3459 
   3460     for (i = 0; i < num_weights; i++) {
   3461         BCM_IF_ERROR_RETURN
   3462             (_bcm_kt_cosq_sched_set(unit, port, (cosq + i), mode, 1, &weights[i])); 
   3463                                      
   3464     }
   3465 
   3466     return BCM_E_NONE;
   3467 }
   3468 
   3469 /*
   3470  * Function:
   3471  *     _bcm_kt_cosq_port_sched_get
   3472  * Purpose:
   3473  *     Set scheduling mode setting for a port
   3474  * Parameters:
   3475  *     unit                - (IN) unit number
   3476  *     port                - (IN) port number or GPORT identifier
   3477  *     cosq                - (IN) COS queue number
   3478  *     mode                - (OUT) scheduling mode (BCM_COSQ_XXX)
   3479  *     num_weights         - (IN) number of entries in weights array
   3480  *     weights             - (OUT) weights array
   3481  * Returns:
   3482  *     BCM_E_XXX
   3483  */
   3484 STATIC int
   3485 _bcm_kt_cosq_port_sched_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   3486                                    int *mode, int num_weights, int *weights)
   3487 {
   3488     int i;
   3489 
   3490     for (i = 0; i < num_weights; i++) {
   3491         BCM_IF_ERROR_RETURN
   3492             (_bcm_kt_cosq_sched_get(unit, port, (cosq + i), mode, 1, &weights[i])); 
   3493                                      
   3494     }
   3495     
   3496     return BCM_E_NONE;
   3497 }
   3498 
   3499 /*
   3500  * Function:
   3501  *     _bcm_kt_cosq_mapping_set_regular
   3502  * Purpose:
   3503  *     Determine which COS queue a given priority currently maps to.
   3504  * Parameters:
   3505  *     unit     - (IN) unit number
   3506  *     gport    - (IN) queue group GPORT identifier
   3507  *     priority - (IN) priority value to map
   3508  *     cosq     - (IN) COS queue to map to
   3509  * Returns:
   3510  *     BCM_E_XXX
   3511  */
   3512 STATIC int
   3513 _bcm_kt_cosq_mapping_set_regular(int unit, bcm_port_t gport, bcm_cos_t priority,
   3514                         bcm_cos_queue_t cosq)
   3515 {
   3516     _bcm_kt_mmu_info_t *mmu_info;
   3517     bcm_port_t port;
   3518     int numq;
   3519     bcm_cos_queue_t hw_cosq;
   3520     soc_field_t field = COSf;
   3521     cos_map_sel_entry_t cos_map_sel_entry;
   3522     port_cos_map_entry_t cos_map_entries[16];
   3523     void *entries[1];     
   3524     uint32 old_index, new_index;
   3525     int rv;
   3526 #ifndef BCM_COSQ_HIGIG_MAP_DISABLE
   3527     int cpu_hg_index = 0;
   3528 #endif
   3529     
   3530     if (priority < 0 || priority >= 16) {
   3531         return BCM_E_PARAM;
   3532     }
   3533 
   3534     hw_cosq = cosq;
   3535     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   3536         BCM_IF_ERROR_RETURN
   3537             (_bcm_kt_cosq_index_resolve
   3538             (unit, gport, cosq, _BCM_KT_COSQ_INDEX_STYLE_UCAST_QUEUE,
   3539              &port, &hw_cosq, NULL));
   3540     } else {
   3541         if (BCM_GPORT_IS_SET(gport)) {
   3542             BCM_IF_ERROR_RETURN(
   3543                 bcm_esw_port_local_get(unit, gport, &port));
   3544         } else {
   3545             port = gport;
   3546         }
   3547 
   3548         if (!SOC_PORT_VALID(unit, port) || !IS_ALL_PORT(unit, port)) {
   3549             return BCM_E_PORT;
   3550         }
   3551     }
   3552 
   3553     mmu_info = _bcm_kt_mmu_info[unit];
   3554     numq = mmu_info->port[port].q_limit - 
   3555            mmu_info->port[port].q_offset;
   3556 
   3557     if (cosq >= numq) {
   3558         return BCM_E_PARAM;
   3559     }
   3560     
   3561     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   3562         field = (numq <= 8) ? COSf : HG_COSf;
   3563     }
   3564 
   3565     entries[0] = &cos_map_entries;
   3566 
   3567     BCM_IF_ERROR_RETURN
   3568         (READ_COS_MAP_SELm(unit, MEM_BLOCK_ANY, port, &cos_map_sel_entry));
   3569     old_index = soc_mem_field32_get(unit, COS_MAP_SELm, &cos_map_sel_entry,
   3570                                     SELECTf);
   3571     old_index *= 16;
   3572 
   3573     BCM_IF_ERROR_RETURN
   3574         (soc_profile_mem_get(unit, _bcm_kt_cos_map_profile[unit],
   3575                              old_index, 16, entries));
   3576     soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[priority], field,
   3577                         hw_cosq);
   3578 
   3579     soc_mem_lock(unit, PORT_COS_MAPm);
   3580 
   3581     rv = soc_profile_mem_delete(unit, _bcm_kt_cos_map_profile[unit],
   3582                                 old_index);
   3583 #ifndef BCM_COSQ_HIGIG_MAP_DISABLE
   3584     if (BCM_SUCCESS(rv) && IS_CPU_PORT(unit, port)) {
   3585         rv = soc_profile_mem_delete(unit, _bcm_kt_cos_map_profile[unit],
   3586                                     old_index);
   3587     }
   3588 #endif /* BCM_COSQ_HIGIG_MAP_DISABLE */
   3589     if (BCM_FAILURE(rv)) {
   3590         soc_mem_unlock(unit, PORT_COS_MAPm);
   3591         return rv;
   3592     }
   3593 
   3594     rv = soc_profile_mem_add(unit, _bcm_kt_cos_map_profile[unit], entries,
   3595                              16, &new_index);
   3596 #ifndef BCM_COSQ_HIGIG_MAP_DISABLE
   3597     if (BCM_SUCCESS(rv) && IS_CPU_PORT(unit, port)) {
   3598         rv = soc_profile_mem_reference(unit, _bcm_kt_cos_map_profile[unit],
   3599                                        new_index, 16);
   3600     }
   3601 #endif /* BCM_COSQ_HIGIG_MAP_DISABLE */
   3602 
   3603     if (rv == SOC_E_RESOURCE) {
   3604         (void)soc_profile_mem_reference(unit, _bcm_kt_cos_map_profile[unit],
   3605                                         old_index, 16);
   3606 #ifndef BCM_COSQ_HIGIG_MAP_DISABLE
   3607         if (IS_CPU_PORT(unit, port)) {
   3608             (void)soc_profile_mem_reference(unit,
   3609                                             _bcm_kt_cos_map_profile[unit],
   3610                                             old_index, 16);
   3611         }
   3612 #endif /* BCM_COSQ_HIGIG_MAP_DISABLE */
   3613     }
   3614 
   3615     soc_mem_unlock(unit, PORT_COS_MAPm);
   3616 
   3617     if (BCM_FAILURE(rv)) {
   3618         return rv;
   3619     }
   3620 
   3621     soc_mem_field32_set(unit, COS_MAP_SELm, &cos_map_sel_entry, SELECTf,
   3622                         new_index / 16);
   3623     BCM_IF_ERROR_RETURN
   3624         (WRITE_COS_MAP_SELm(unit, MEM_BLOCK_ANY, port, &cos_map_sel_entry));
   3625 
   3626 #ifndef BCM_COSQ_HIGIG_MAP_DISABLE
   3627     if (IS_CPU_PORT(unit, port)) {
   3628         cpu_hg_index = SOC_IS_KATANA2(unit) ?
   3629                        SOC_INFO(unit).cpu_hg_pp_port_index :
   3630                        SOC_INFO(unit).cpu_hg_index;
   3631         BCM_IF_ERROR_RETURN
   3632             (soc_mem_field32_modify(unit, COS_MAP_SELm,
   3633                                     cpu_hg_index, SELECTf,
   3634                                     new_index / 16));
   3635     }
   3636 #endif /* BCM_COSQ_HIGIG_MAP_DISABLE */
   3637 
   3638     return BCM_E_NONE;
   3639 }
   3640 
   3641 /*
   3642  * Function:
   3643  *     _bcm_kt_cosq_bucket_set
   3644  * Purpose:
   3645  *     Configure COS queue bandwidth control bucket
   3646  * Parameters:
   3647  *     unit          - (IN) unit number
   3648  *     port          - (IN) port number or GPORT identifier
   3649  *     cosq          - (IN) COS queue number
   3650  *     min_quantum   - (IN) kbps or packet/second
   3651  *     max_quantum   - (IN) kbps or packet/second
   3652  *     burst_quantum - (IN) kbps or packet/second
   3653  *     flags         - (IN)
   3654  * Returns:
   3655  *     BCM_E_XXX
   3656  * Notes:
   3657  *     If port is any form of local port, cosq is the hardware queue index.
   3658  */
   3659 STATIC int
   3660 _bcm_kt_cosq_bucket_set(int unit, bcm_gport_t port, bcm_cos_queue_t cosq,
   3661                         uint32 min_quantum, uint32 max_quantum,
   3662                         uint32 burst_min_quantum, uint32 burst_max_quantum,
   3663                         uint32 flags)
   3664 {
   3665     int rv;
   3666     _bcm_kt_cosq_node_t *node;
   3667     bcm_port_t local_port;
   3668     int index;
   3669     soc_mem_t config_mem[2];
   3670     soc_mem_t bucket_mem;
   3671     lls_port_shaper_config_c_entry_t port_entry;
   3672     lls_port_shaper_config_c_entry_t port_null_entry;
   3673     lls_port_shaper_bucket_c_entry_t port_bucket_entry;
   3674     lls_l0_shaper_config_c_entry_t  l0_entry;
   3675     lls_l1_shaper_config_c_entry_t  l1_entry;
   3676     lls_l2_shaper_config_lower_entry_t l2_entry;
   3677     lls_l0_min_config_c_entry_t  l0_null_entry;
   3678     lls_l0_min_bucket_c_entry_t  l0_bucket_entry; 
   3679     lls_l1_min_config_c_entry_t  l1_null_entry;
   3680     lls_l1_min_bucket_c_entry_t  l1_bucket_entry;
   3681     lls_l2_min_config_lower_c_entry_t l2_null_entry; 
   3682     lls_l2_min_bucket_lower_c_entry_t l2_bucket_entry;
   3683     lls_l2_shaper_config_lower_entry_t l2_null_max_entry; 
   3684     lls_l2_shaper_bucket_lower_entry_t l2_bucket_max_entry;    
   3685     uint32 rate_exp[2], rate_mantissa[2];
   3686     uint32 burst_exp[2], burst_mantissa[2];
   3687     uint32 cycle_sel[2];
   3688     uint32 burst_min, burst_max;
   3689     int i, idx;
   3690     int level = _BCM_KT_COSQ_NODE_LEVEL_L2;
   3691     soc_field_t rate_exp_f[] = {
   3692         C_MAX_REF_RATE_EXPf, C_MIN_REF_RATE_EXPf
   3693     };
   3694     soc_field_t rate_mant_f[] = {
   3695         C_MAX_REF_RATE_MANTf, C_MIN_REF_RATE_MANTf
   3696     };
   3697     soc_field_t burst_exp_f[] = {
   3698         C_MAX_THLD_EXPf, C_MIN_THLD_EXPf
   3699     };
   3700     soc_field_t burst_mant_f[] = {
   3701         C_MAX_THLD_MANTf, C_MIN_THLD_MANTf
   3702     };
   3703     soc_field_t cycle_sel_f[] = {
   3704         C_MAX_CYCLE_SELf, C_MIN_CYCLE_SELf
   3705     };
   3706     static const soc_field_t rate_exp_fields[] = {
   3707        C_MAX_REF_RATE_EXP_0f, C_MAX_REF_RATE_EXP_1f,
   3708        C_MAX_REF_RATE_EXP_2f, C_MAX_REF_RATE_EXP_3f,
   3709        C_MIN_REF_RATE_EXP_0f, C_MIN_REF_RATE_EXP_1f,
   3710        C_MIN_REF_RATE_EXP_2f, C_MIN_REF_RATE_EXP_3f
   3711     };
   3712     static const soc_field_t rate_mant_fields[] = {
   3713        C_MAX_REF_RATE_MANT_0f, C_MAX_REF_RATE_MANT_1f,
   3714        C_MAX_REF_RATE_MANT_2f, C_MAX_REF_RATE_MANT_3f,
   3715        C_MIN_REF_RATE_MANT_0f, C_MIN_REF_RATE_MANT_1f,
   3716        C_MIN_REF_RATE_MANT_2f, C_MIN_REF_RATE_MANT_3f
   3717     };
   3718     static const soc_field_t burst_exp_fields[] = {
   3719        C_MAX_THLD_EXP_0f, C_MAX_THLD_EXP_1f,
   3720        C_MAX_THLD_EXP_2f, C_MAX_THLD_EXP_3f,
   3721        C_MIN_THLD_EXP_0f, C_MIN_THLD_EXP_1f,
   3722        C_MIN_THLD_EXP_2f, C_MIN_THLD_EXP_3f
   3723     };
   3724     static const soc_field_t burst_mant_fields[] = {
   3725        C_MAX_THLD_MANT_0f, C_MAX_THLD_MANT_1f,
   3726        C_MAX_THLD_MANT_2f, C_MAX_THLD_MANT_3f,
   3727        C_MIN_THLD_MANT_0f, C_MIN_THLD_MANT_1f,
   3728        C_MIN_THLD_MANT_2f, C_MIN_THLD_MANT_3f
   3729     };
   3730     soc_field_t cycle_sel_fields[] = {
   3731         C_MAX_CYCLE_SEL_0f, C_MAX_CYCLE_SEL_1f,
   3732         C_MAX_CYCLE_SEL_2f, C_MAX_CYCLE_SEL_3f,    
   3733         C_MIN_CYCLE_SEL_0f, C_MIN_CYCLE_SEL_1f,
   3734         C_MIN_CYCLE_SEL_2f, C_MIN_CYCLE_SEL_3f
   3735     };
   3736 
   3737     if (cosq < 0) {
   3738         if (cosq == -1) {
   3739             /* caller needs to resolve the wild card value (-1) */
   3740             return BCM_E_INTERNAL;
   3741         } else { /* reject all other negative value */
   3742             return BCM_E_PARAM;
   3743         }
   3744     }
   3745 
   3746 
   3747     BCM_IF_ERROR_RETURN
   3748         (_bcm_kt_cosq_index_resolve(unit, port, cosq,
   3749                                     _BCM_KT_COSQ_INDEX_STYLE_BUCKET,
   3750                                     &local_port, &index, NULL));
   3751 
   3752     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
   3753         BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port) ||
   3754         BCM_GPORT_IS_SCHEDULER(port)) {
   3755         BCM_IF_ERROR_RETURN
   3756             (_bcm_kt_cosq_node_get(unit, port, NULL, NULL, NULL, &node));
   3757         level = node->level;   
   3758         if ((level== _BCM_KT_COSQ_NODE_LEVEL_ROOT) &&
   3759             (min_quantum > 0)) {
   3760             /* min shaper is not supported */
   3761             return BCM_E_PARAM;
   3762         } 
   3763     }     
   3764 
   3765     /* compute exp and mantissa and program the registers */
   3766     rv = soc_katana_get_shaper_rate_info(unit, max_quantum,
   3767                                          &rate_mantissa[0], &rate_exp[0]);
   3768     if (BCM_FAILURE(rv)) {
   3769         return(rv);
   3770     }
   3771 
   3772     rv = soc_katana_get_shaper_rate_info(unit, min_quantum,
   3773                                          &rate_mantissa[1], &rate_exp[1]);
   3774     if (BCM_FAILURE(rv)) {
   3775         return(rv);
   3776     }
   3777 
   3778     burst_max = burst_max_quantum;
   3779     burst_min = burst_min_quantum;
   3780     rv = soc_katana_get_shaper_burst_info(unit, burst_max, &burst_mantissa[0], 
   3781                                           &burst_exp[0], flags);
   3782     if (BCM_FAILURE(rv)) {
   3783         return(rv);
   3784     }
   3785     
   3786     rv = soc_katana_get_shaper_burst_info(unit, burst_min, &burst_mantissa[1], 
   3787                                           &burst_exp[1], flags);
   3788     if (BCM_FAILURE(rv)) {
   3789         return(rv);
   3790     }    
   3791 
   3792     if (!(flags & _BCM_XGS_METER_FLAG_NON_BURST_CORRECTION)) {
   3793         /* set recommended burst settings */
   3794         for (i = 0; i < 2; i++) {
   3795             if (rate_exp[i] != 0) {
   3796                 if (rate_exp[i] < 10) {
   3797                     burst_exp[i] = 5;
   3798                     burst_mantissa[i] = 0;
   3799                 } else {
   3800                     burst_exp[i] = rate_exp[i] - 4;
   3801                     burst_mantissa[i] = (rate_mantissa[i] >> 3);
   3802                 }
   3803             }
   3804         }
   3805         /* set recommended refresh rate/cycle_sel settings */
   3806         for (i = 0; i < 2; i++) {
   3807             if (rate_exp[i] > 4) {
   3808                 cycle_sel[i] = 0;
   3809             } else if (rate_exp[i] > 1) {
   3810                 cycle_sel[i] = 5 - rate_exp[i];
   3811             } else {
   3812                  cycle_sel[i] = 4;
   3813             }
   3814         }
   3815     } else {
   3816         for (i = 0; i < 2; i++) {
   3817             if ((burst_exp[i] >= 14) && (burst_mantissa[i] >= 124)) {
   3818                 /* maximum supported is 2064384 byte */
   3819                 burst_exp[i] = 14;
   3820                 burst_mantissa[i] = 124;
   3821             }
   3822             rv =  soc_katana_compute_refresh_rate(unit, rate_exp[i],
   3823                                                   rate_mantissa[i], burst_exp[i],
   3824                                                   burst_mantissa[i], &cycle_sel[i]);
   3825             if (BCM_FAILURE(rv)) {
   3826                 return(rv);
   3827             }
   3828         }
   3829     }
   3830    
   3831     if (soc_feature(unit, soc_feature_dynamic_shaper_update) && 
   3832         (level > _BCM_KT_COSQ_NODE_LEVEL_L0)) { 
   3833         /* set cycle_sel = 0 for L1 and L2 in A0 */
   3834         for (i = 0; i < 2; i++) {
   3835             cycle_sel[i] = 0;
   3836         }
   3837     }    
   3838 
   3839     SOC_EGRESS_METERING_LOCK(unit);
   3840     switch (level) {
   3841         case _BCM_KT_COSQ_NODE_LEVEL_ROOT:
   3842             config_mem[0] = LLS_PORT_SHAPER_CONFIG_Cm;
   3843             sal_memset(&port_null_entry, 0, sizeof(lls_port_shaper_config_c_entry_t));
   3844             sal_memset(&port_bucket_entry, 0, sizeof(lls_port_shaper_bucket_c_entry_t));
   3845             
   3846             rv = soc_mem_read(unit, config_mem[0], MEM_BLOCK_ALL,
   3847                              index, &port_entry);
   3848             if (BCM_FAILURE(rv)) {
   3849                 SOC_EGRESS_METERING_UNLOCK(unit);
   3850                 return(rv);
   3851             }
   3852             soc_mem_field32_set(unit, config_mem[0], &port_entry,
   3853                                 rate_exp_f[0], rate_exp[0]);
   3854             soc_mem_field32_set(unit, config_mem[0], &port_entry,
   3855                                 rate_mant_f[0], rate_mantissa[0]);
   3856             soc_mem_field32_set(unit, config_mem[0], &port_entry,
   3857                                 burst_exp_f[0], burst_exp[0]);
   3858             soc_mem_field32_set(unit, config_mem[0], &port_entry,
   3859                                 burst_mant_f[0], burst_mantissa[0]);
   3860             soc_mem_field32_set(unit, config_mem[0], &port_entry,
   3861                                 cycle_sel_f[0], cycle_sel[0]); 
   3862             if (soc_feature(unit, soc_feature_dynamic_shaper_update)) {
   3863                 bucket_mem = LLS_PORT_SHAPER_BUCKET_Cm;
   3864                 rv = soc_mem_write(unit, config_mem[0],
   3865                                    MEM_BLOCK_ALL, index, &port_null_entry);
   3866                 if (BCM_FAILURE(rv)) {
   3867                     SOC_EGRESS_METERING_UNLOCK(unit);
   3868                     return(rv);
   3869                 }
   3870                 soc_mem_field32_set(unit, bucket_mem, &port_bucket_entry,
   3871                                     NOT_ACTIVE_IN_LLSf, 1);   
   3872                 rv = soc_mem_write(unit, bucket_mem,
   3873                                        MEM_BLOCK_ALL, index, &port_bucket_entry);   
   3874                 if (BCM_FAILURE(rv)) {
   3875                     SOC_EGRESS_METERING_UNLOCK(unit);
   3876                     return(rv);
   3877                 }
   3878             }
   3879             rv = soc_mem_write(unit, config_mem[0],
   3880                                MEM_BLOCK_ALL, index, &port_entry);
   3881             if (BCM_FAILURE(rv)) {
   3882                 SOC_EGRESS_METERING_UNLOCK(unit);
   3883                 return(rv);
   3884             }
   3885             break;
   3886 
   3887         case _BCM_KT_COSQ_NODE_LEVEL_L0:
   3888             config_mem[0] = LLS_L0_SHAPER_CONFIG_Cm;
   3889             config_mem[1] = LLS_L0_MIN_CONFIG_Cm;
   3890             sal_memset(&l0_null_entry, 0, sizeof(lls_l0_min_config_c_entry_t));
   3891             sal_memset(&l0_bucket_entry, 0, sizeof(lls_l0_min_bucket_c_entry_t));
   3892             
   3893             for (i = 0; i < 2; i++) {
   3894                 rv = soc_mem_read(unit, config_mem[i], MEM_BLOCK_ALL,
   3895                                    index, &l0_entry);
   3896                 if (BCM_FAILURE(rv)) {
   3897                     SOC_EGRESS_METERING_UNLOCK(unit);
   3898                     return(rv);
   3899                 }
   3900                 soc_mem_field32_set(unit, config_mem[i], &l0_entry,
   3901                                     rate_exp_f[i], rate_exp[i]);
   3902                 soc_mem_field32_set(unit, config_mem[i], &l0_entry,
   3903                                     rate_mant_f[i], rate_mantissa[i]);
   3904                 soc_mem_field32_set(unit, config_mem[i], &l0_entry,
   3905                                     burst_exp_f[i], burst_exp[i]);
   3906                 soc_mem_field32_set(unit, config_mem[i], &l0_entry,
   3907                                     burst_mant_f[i], burst_mantissa[i]);
   3908                 soc_mem_field32_set(unit, config_mem[i], &l0_entry,
   3909                                     cycle_sel_f[i], cycle_sel[i]);   
   3910                 if (soc_feature(unit, soc_feature_dynamic_shaper_update)) {
   3911                     bucket_mem = (config_mem[i] == LLS_L0_MIN_CONFIG_Cm) ?
   3912                                  LLS_L0_MIN_BUCKET_Cm :
   3913                                  LLS_L0_SHAPER_BUCKET_Cm;
   3914                     rv = soc_mem_write(unit, config_mem[i],
   3915                                        MEM_BLOCK_ALL, index, &l0_null_entry);
   3916                     if (BCM_FAILURE(rv)) {
   3917                         SOC_EGRESS_METERING_UNLOCK(unit);
   3918                         return(rv);
   3919                     }
   3920                     soc_mem_field32_set(unit, bucket_mem, &l0_bucket_entry,
   3921                                         NOT_ACTIVE_IN_LLSf, 1);        
   3922                     rv = soc_mem_write(unit, bucket_mem,
   3923                                        MEM_BLOCK_ALL, index, &l0_bucket_entry);                    
   3924                     if (BCM_FAILURE(rv)) {
   3925                         SOC_EGRESS_METERING_UNLOCK(unit);
   3926                         return(rv);
   3927                     }
   3928                 }    
   3929                 rv = soc_mem_write(unit, config_mem[i],
   3930                                      MEM_BLOCK_ALL, index, &l0_entry);
   3931                 if (BCM_FAILURE(rv)) {
   3932                     SOC_EGRESS_METERING_UNLOCK(unit);
   3933                     return(rv);
   3934                 }
   3935              }
   3936             break;
   3937 
   3938         case _BCM_KT_COSQ_NODE_LEVEL_L1:
   3939             config_mem[0] = LLS_L1_SHAPER_CONFIG_Cm;
   3940             config_mem[1] = LLS_L1_MIN_CONFIG_Cm;
   3941             sal_memset(&l1_null_entry, 0, sizeof(lls_l1_min_config_c_entry_t));
   3942             sal_memset(&l1_bucket_entry, 0, sizeof(lls_l1_min_bucket_c_entry_t));
   3943             
   3944             for (i = 0; i < 2; i++) {
   3945                 idx = (i * 4) + (index % 4);
   3946                 rv = soc_mem_read(unit, config_mem[i], MEM_BLOCK_ALL,
   3947                                    index/4, &l1_entry);
   3948                 if (BCM_FAILURE(rv)) {
   3949                     SOC_EGRESS_METERING_UNLOCK(unit);
   3950                     return(rv);
   3951                 }
   3952                 soc_mem_field32_set(unit, config_mem[i], &l1_entry,
   3953                                     rate_exp_fields[idx], rate_exp[i]);
   3954                 soc_mem_field32_set(unit, config_mem[i], &l1_entry,
   3955                                     rate_mant_fields[idx], rate_mantissa[i]);
   3956                 soc_mem_field32_set(unit, config_mem[i], &l1_entry,
   3957                                     burst_exp_fields[idx], burst_exp[i]);
   3958                 soc_mem_field32_set(unit, config_mem[i], &l1_entry,
   3959                                     burst_mant_fields[idx], burst_mantissa[i]);
   3960                 soc_mem_field32_set(unit, config_mem[i], &l1_entry,
   3961                                     cycle_sel_fields[idx], cycle_sel[i]);               
   3962                 if (soc_feature(unit, soc_feature_dynamic_shaper_update)) {
   3963                     bucket_mem = (config_mem[i] == LLS_L1_MIN_CONFIG_Cm) ?
   3964                                  LLS_L1_MIN_BUCKET_Cm :
   3965                                  LLS_L1_SHAPER_BUCKET_Cm;            
   3966                     rv = soc_mem_write(unit, config_mem[i],
   3967                                           MEM_BLOCK_ALL, index/4, &l1_null_entry);
   3968                     if (BCM_FAILURE(rv)) {
   3969                         SOC_EGRESS_METERING_UNLOCK(unit);
   3970                         return(rv);
   3971                     }
   3972                     soc_mem_field32_set(unit, bucket_mem, &l1_bucket_entry,
   3973                                         NOT_ACTIVE_IN_LLS_0f, 1);
   3974                     soc_mem_field32_set(unit, bucket_mem, &l1_bucket_entry,
   3975                                         NOT_ACTIVE_IN_LLS_1f, 1);
   3976                     soc_mem_field32_set(unit, bucket_mem, &l1_bucket_entry,
   3977                                         NOT_ACTIVE_IN_LLS_2f, 1);
   3978                     soc_mem_field32_set(unit, bucket_mem, &l1_bucket_entry,
   3979                                         NOT_ACTIVE_IN_LLS_3f, 1);                    
   3980                     rv = soc_mem_write(unit, bucket_mem,
   3981                                           MEM_BLOCK_ALL, index/4, &l1_bucket_entry);                    
   3982                     if (BCM_FAILURE(rv)) {
   3983                         SOC_EGRESS_METERING_UNLOCK(unit);
   3984                         return(rv);
   3985                     }
   3986                 }    
   3987 
   3988                 rv = soc_mem_write(unit, config_mem[i],
   3989                                    MEM_BLOCK_ALL, index/4, &l1_entry);
   3990                 if (BCM_FAILURE(rv)) {
   3991                     SOC_EGRESS_METERING_UNLOCK(unit);
   3992                     return(rv);
   3993                 }
   3994             }
   3995             break;
   3996 
   3997         case _BCM_KT_COSQ_NODE_LEVEL_L2:
   3998             if ((index % 8) < 4) {
   3999                 config_mem[0] = LLS_L2_SHAPER_CONFIG_LOWERm;
   4000                 config_mem[1] = LLS_L2_MIN_CONFIG_LOWER_Cm;
   4001             } else {
   4002                 config_mem[0] = LLS_L2_SHAPER_CONFIG_UPPERm;
   4003                 config_mem[1] = LLS_L2_MIN_CONFIG_UPPER_Cm;
   4004             }
   4005             sal_memset(&l2_null_entry, 0, sizeof(lls_l2_min_config_lower_c_entry_t));
   4006             sal_memset(&l2_bucket_entry, 0, sizeof(lls_l2_min_bucket_lower_c_entry_t));
   4007             sal_memset(&l2_null_max_entry, 0, sizeof(lls_l2_shaper_config_lower_entry_t));
   4008             sal_memset(&l2_bucket_max_entry, 0, sizeof(lls_l2_shaper_bucket_lower_entry_t));
   4009 
   4010             for (i = 0; i < 2; i++) {
   4011                 idx = (i * 4) + (index % 4);
   4012                 rv = soc_mem_read(unit, config_mem[i], MEM_BLOCK_ALL,
   4013                                  index/8, &l2_entry);
   4014                 if (BCM_FAILURE(rv)) {
   4015                     SOC_EGRESS_METERING_UNLOCK(unit);
   4016                     return(rv);
   4017                 }
   4018                 soc_mem_field32_set(unit, config_mem[i], &l2_entry,
   4019                                     rate_exp_fields[idx], rate_exp[i]);
   4020                 soc_mem_field32_set(unit, config_mem[i], &l2_entry,
   4021                                     rate_mant_fields[idx], rate_mantissa[i]);
   4022                 soc_mem_field32_set(unit, config_mem[i], &l2_entry,
   4023                                     burst_exp_fields[idx], burst_exp[i]);
   4024                 soc_mem_field32_set(unit, config_mem[i], &l2_entry,
   4025                                     burst_mant_fields[idx], burst_mantissa[i]);
   4026                 soc_mem_field32_set(unit, config_mem[i], &l2_entry,
   4027                                     cycle_sel_fields[idx], cycle_sel[i]);      
   4028                 if (soc_feature(unit, soc_feature_dynamic_shaper_update) &&
   4029                     (config_mem[i] == LLS_L2_MIN_CONFIG_LOWER_Cm ||
   4030                      config_mem[i] == LLS_L2_MIN_CONFIG_UPPER_Cm)) {
   4031                     bucket_mem = (config_mem[i] == LLS_L2_MIN_CONFIG_LOWER_Cm) ?
   4032                                  LLS_L2_MIN_BUCKET_LOWER_Cm :
   4033                                  LLS_L2_MIN_BUCKET_UPPER_Cm;
   4034                     rv = soc_mem_write(unit, config_mem[i],
   4035                                           MEM_BLOCK_ALL, index/8, &l2_null_entry);
   4036                     if (BCM_FAILURE(rv)) {
   4037                         SOC_EGRESS_METERING_UNLOCK(unit);
   4038                         return(rv);
   4039                     }
   4040                     soc_mem_field32_set(unit, bucket_mem, &l2_bucket_entry,
   4041                                         NOT_ACTIVE_IN_LLS_0f, 1);
   4042                     soc_mem_field32_set(unit, bucket_mem, &l2_bucket_entry,
   4043                                         NOT_ACTIVE_IN_LLS_1f, 1);
   4044                     soc_mem_field32_set(unit, bucket_mem, &l2_bucket_entry,
   4045                                         NOT_ACTIVE_IN_LLS_2f, 1);
   4046                     soc_mem_field32_set(unit, bucket_mem, &l2_bucket_entry,
   4047                                         NOT_ACTIVE_IN_LLS_3f, 1);                    
   4048                     rv = soc_mem_write(unit, bucket_mem,
   4049                                           MEM_BLOCK_ALL, index/8, &l2_bucket_entry);                       
   4050                     if (BCM_FAILURE(rv)) {
   4051                         SOC_EGRESS_METERING_UNLOCK(unit);
   4052                         return(rv);
   4053                     }
   4054                 }    
   4055                 if (soc_feature(unit, soc_feature_dynamic_shaper_update) &&
   4056                     (config_mem[i] == LLS_L2_SHAPER_CONFIG_LOWERm ||
   4057                      config_mem[i] == LLS_L2_SHAPER_CONFIG_UPPERm)) {
   4058                     bucket_mem = (config_mem[i] == LLS_L2_SHAPER_CONFIG_LOWERm) ?
   4059                                  LLS_L2_SHAPER_BUCKET_LOWERm :
   4060                                  LLS_L2_SHAPER_BUCKET_UPPERm;
   4061                     rv = soc_mem_write(unit, config_mem[i],
   4062                                           MEM_BLOCK_ALL, index/8, &l2_null_max_entry);
   4063                     if (BCM_FAILURE(rv)) {
   4064                         SOC_EGRESS_METERING_UNLOCK(unit);
   4065                         return(rv);
   4066                     }
   4067                     soc_mem_field32_set(unit, bucket_mem, &l2_bucket_max_entry,
   4068                                         NOT_ACTIVE_IN_LLS_0f, 1);
   4069                     soc_mem_field32_set(unit, bucket_mem, &l2_bucket_max_entry,
   4070                                         NOT_ACTIVE_IN_LLS_1f, 1);
   4071                     soc_mem_field32_set(unit, bucket_mem, &l2_bucket_max_entry,
   4072                                         NOT_ACTIVE_IN_LLS_2f, 1);
   4073                     soc_mem_field32_set(unit, bucket_mem, &l2_bucket_max_entry,
   4074                                         NOT_ACTIVE_IN_LLS_3f, 1);                    
   4075                     rv = soc_mem_write(unit, bucket_mem,
   4076                                           MEM_BLOCK_ALL, index/8, &l2_bucket_max_entry);                       
   4077                     if (BCM_FAILURE(rv)) {
   4078                         SOC_EGRESS_METERING_UNLOCK(unit);
   4079                         return(rv);
   4080                     }
   4081                 }  
   4082                 rv = soc_mem_write(unit, config_mem[i],
   4083                                    MEM_BLOCK_ALL, index/8, &l2_entry);
   4084                 if (BCM_FAILURE(rv)) {
   4085                     SOC_EGRESS_METERING_UNLOCK(unit);
   4086                     return(rv);
   4087                 }
   4088             }
   4089             break;
   4090 
   4091         default:
   4092             SOC_EGRESS_METERING_UNLOCK(unit);
   4093             return BCM_E_PARAM;
   4094     }
   4095         
   4096     SOC_EGRESS_METERING_UNLOCK(unit);
   4097     return BCM_E_NONE;
   4098 }
   4099 
   4100 /*
   4101  * Function:
   4102  *     _bcm_kt_cosq_bucket_get
   4103  * Purpose:
   4104  *     Get COS queue bandwidth control bucket setting
   4105  * Parameters:
   4106  *     unit          - (IN) unit number
   4107  *     port          - (IN) port number or GPORT identifier
   4108  *     cosq          - (IN) COS queue number
   4109  *     min_quantum   - (OUT) kbps or packet/second
   4110  *     max_quantum   - (OUT) kbps or packet/second
   4111  *     burst_quantum - (OUT) kbps or packet/second
   4112  *     flags         - (IN)
   4113  * Returns:
   4114  *     BCM_E_XXX
   4115  * Notes:
   4116  *     If port is any form of local port, cosq is the hardware queue index.
   4117  */
   4118 STATIC int
   4119 _bcm_kt_cosq_bucket_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   4120                         uint32 *min_quantum, uint32 *max_quantum,
   4121                         uint32 *burst_min_quantum, uint32 *burst_max_quantum,
   4122                         uint32 flags)
   4123 {
   4124     int rv;
   4125     _bcm_kt_cosq_node_t *node;
   4126     bcm_port_t local_port;
   4127     int index;
   4128     soc_mem_t config_mem[2];
   4129     lls_port_shaper_config_c_entry_t port_entry;
   4130     lls_l0_shaper_config_c_entry_t  l0_entry;
   4131     lls_l1_shaper_config_c_entry_t  l1_entry;
   4132     lls_l2_shaper_config_lower_entry_t l2_entry;
   4133     uint32 rate_exp[2], rate_mantissa[2];
   4134     uint32 burst_exp[2], burst_mantissa[2];
   4135     int i, idx;
   4136     int level = _BCM_KT_COSQ_NODE_LEVEL_L2;
   4137     soc_field_t rate_exp_f[] = {
   4138         C_MAX_REF_RATE_EXPf, C_MIN_REF_RATE_EXPf
   4139     };
   4140     soc_field_t rate_mant_f[] = {
   4141         C_MAX_REF_RATE_MANTf, C_MIN_REF_RATE_MANTf
   4142     };
   4143     soc_field_t burst_exp_f[] = {
   4144         C_MAX_THLD_EXPf, C_MIN_THLD_EXPf
   4145     };
   4146     soc_field_t burst_mant_f[] = {
   4147         C_MAX_THLD_MANTf, C_MIN_THLD_MANTf
   4148     };
   4149     static const soc_field_t rate_exp_fields[] = {
   4150        C_MAX_REF_RATE_EXP_0f, C_MAX_REF_RATE_EXP_1f,
   4151        C_MAX_REF_RATE_EXP_2f, C_MAX_REF_RATE_EXP_3f,
   4152        C_MIN_REF_RATE_EXP_0f, C_MIN_REF_RATE_EXP_1f,
   4153        C_MIN_REF_RATE_EXP_2f, C_MIN_REF_RATE_EXP_3f
   4154     };
   4155     static const soc_field_t rate_mant_fields[] = {
   4156        C_MAX_REF_RATE_MANT_0f, C_MAX_REF_RATE_MANT_1f,
   4157        C_MAX_REF_RATE_MANT_2f, C_MAX_REF_RATE_MANT_3f,
   4158        C_MIN_REF_RATE_MANT_0f, C_MIN_REF_RATE_MANT_1f,
   4159        C_MIN_REF_RATE_MANT_2f, C_MIN_REF_RATE_MANT_3f
   4160     };
   4161     static const soc_field_t burst_exp_fields[] = {
   4162        C_MAX_THLD_EXP_0f, C_MAX_THLD_EXP_1f,
   4163        C_MAX_THLD_EXP_2f, C_MAX_THLD_EXP_3f,
   4164        C_MIN_THLD_EXP_0f, C_MIN_THLD_EXP_1f,
   4165        C_MIN_THLD_EXP_2f, C_MIN_THLD_EXP_3f       
   4166     };
   4167     static const soc_field_t burst_mant_fields[] = {
   4168        C_MAX_THLD_MANT_0f, C_MAX_THLD_MANT_1f,
   4169        C_MAX_THLD_MANT_2f, C_MAX_THLD_MANT_3f,
   4170        C_MIN_THLD_MANT_0f, C_MIN_THLD_MANT_1f,
   4171        C_MIN_THLD_MANT_2f, C_MIN_THLD_MANT_3f
   4172     };
   4173 
   4174     if (cosq < 0) {
   4175         if (cosq == -1) {
   4176             /* caller needs to resolve the wild card value (-1) */
   4177             return BCM_E_INTERNAL;
   4178         } else { /* reject all other negative value */
   4179             return BCM_E_PARAM;
   4180         }
   4181     }
   4182 
   4183     if (min_quantum == NULL || max_quantum == NULL || 
   4184         burst_min_quantum == NULL || burst_max_quantum == NULL) {
   4185         return BCM_E_PARAM;
   4186     }
   4187 
   4188     BCM_IF_ERROR_RETURN
   4189         (_bcm_kt_cosq_index_resolve(unit, port, cosq,
   4190                                     _BCM_KT_COSQ_INDEX_STYLE_BUCKET,
   4191                                     &local_port, &index, NULL));
   4192     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
   4193         BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port) ||
   4194         BCM_GPORT_IS_SCHEDULER(port)) {
   4195         BCM_IF_ERROR_RETURN
   4196             (_bcm_kt_cosq_node_get(unit, port, NULL, NULL, NULL, &node));
   4197         level = node->level;    
   4198     } 
   4199 
   4200     SOC_EGRESS_METERING_LOCK(unit);
   4201     switch (level) {
   4202         case _BCM_KT_COSQ_NODE_LEVEL_ROOT:
   4203             config_mem[0] = LLS_PORT_SHAPER_CONFIG_Cm;
   4204             rv = soc_mem_read(unit, config_mem[0], MEM_BLOCK_ALL,
   4205                              index, &port_entry);
   4206             if (BCM_FAILURE(rv)) {
   4207                 SOC_EGRESS_METERING_UNLOCK(unit);
   4208                 return(rv);
   4209             }
   4210             rate_exp[0] = soc_mem_field32_get(unit, config_mem[0], &port_entry,
   4211                                 rate_exp_f[0]);
   4212             rate_mantissa[0] = soc_mem_field32_get(unit, config_mem[0], &port_entry,
   4213                                 rate_mant_f[0]);
   4214             rate_exp[1] = rate_exp[0];
   4215             rate_mantissa[1] = rate_mantissa[0];
   4216             burst_exp[0] = soc_mem_field32_get(unit, config_mem[0], &port_entry,
   4217                                 burst_exp_f[0]);
   4218             burst_mantissa[0] = soc_mem_field32_get(unit, config_mem[0], &port_entry,
   4219                                 burst_mant_f[0]);
   4220             burst_exp[1] = burst_exp[0];
   4221             burst_mantissa[1] = burst_mantissa[0];
   4222             break;
   4223 
   4224         case _BCM_KT_COSQ_NODE_LEVEL_L0:
   4225             config_mem[0] = LLS_L0_SHAPER_CONFIG_Cm;
   4226             config_mem[1] = LLS_L0_MIN_CONFIG_Cm;
   4227 
   4228             for (i = 0; i < 2; i++) {
   4229                 rv = soc_mem_read(unit, config_mem[i], MEM_BLOCK_ALL,
   4230                                  index, &l0_entry);
   4231                 if (BCM_FAILURE(rv)) {
   4232                     SOC_EGRESS_METERING_UNLOCK(unit);
   4233                     return(rv);
   4234                 }
   4235                 rate_exp[i] = soc_mem_field32_get(unit, config_mem[i], &l0_entry,
   4236                                     rate_exp_f[i]);
   4237                 rate_mantissa[i] = soc_mem_field32_get(unit, config_mem[i], &l0_entry,
   4238                                     rate_mant_f[i]);
   4239                 burst_exp[i] = soc_mem_field32_get(unit, config_mem[i], &l0_entry,
   4240                                     burst_exp_f[i]);
   4241                 burst_mantissa[i] = soc_mem_field32_get(unit, config_mem[i], &l0_entry,
   4242                                     burst_mant_f[i]);
   4243             }
   4244             break;
   4245 
   4246         case _BCM_KT_COSQ_NODE_LEVEL_L1:
   4247             config_mem[0] = LLS_L1_SHAPER_CONFIG_Cm;
   4248             config_mem[1] = LLS_L1_MIN_CONFIG_Cm;
   4249 
   4250             for (i = 0; i < 2; i++) {
   4251                 idx = (i * 4) + (index % 4);
   4252                 rv = soc_mem_read(unit, config_mem[i], MEM_BLOCK_ALL,
   4253                                      index/4, &l1_entry);
   4254                 if (BCM_FAILURE(rv)) {
   4255                     SOC_EGRESS_METERING_UNLOCK(unit);
   4256                     return(rv);
   4257                 }
   4258                 rate_exp[i] = soc_mem_field32_get(unit, config_mem[i], &l1_entry,
   4259                                     rate_exp_fields[idx]);
   4260                 rate_mantissa[i] = soc_mem_field32_get(unit, config_mem[i], &l1_entry,
   4261                                     rate_mant_fields[idx]);
   4262                 burst_exp[i] = soc_mem_field32_get(unit, config_mem[i], &l1_entry,
   4263                                     burst_exp_fields[idx]);
   4264                 burst_mantissa[i] = soc_mem_field32_get(unit, config_mem[i], &l1_entry,
   4265                                     burst_mant_fields[idx]);
   4266              }
   4267             break;
   4268 
   4269         case _BCM_KT_COSQ_NODE_LEVEL_L2:
   4270             if ((index % 8) < 4) {
   4271                 config_mem[0] = LLS_L2_SHAPER_CONFIG_LOWERm;
   4272                 config_mem[1] = LLS_L2_MIN_CONFIG_LOWER_Cm;
   4273             } else {
   4274                 config_mem[0] = LLS_L2_SHAPER_CONFIG_UPPERm;
   4275                 config_mem[1] = LLS_L2_MIN_CONFIG_UPPER_Cm;
   4276             }
   4277 
   4278             for (i = 0; i < 2; i++) {
   4279                 idx = (i * 4) + (index % 4);
   4280                 rv = soc_mem_read(unit, config_mem[i], MEM_BLOCK_ALL,
   4281                                  index/8, &l2_entry);
   4282                 if (BCM_FAILURE(rv)) {
   4283                     SOC_EGRESS_METERING_UNLOCK(unit);
   4284                     return(rv);
   4285                 }
   4286                 rate_exp[i] = soc_mem_field32_get(unit, config_mem[i], &l2_entry,
   4287                                     rate_exp_fields[idx]);
   4288                 rate_mantissa[i] = soc_mem_field32_get(unit, config_mem[i], &l2_entry,
   4289                                     rate_mant_fields[idx]);
   4290                 burst_exp[i] = soc_mem_field32_get(unit, config_mem[i], &l2_entry,
   4291                                     burst_exp_fields[idx]);
   4292                 burst_mantissa[i] = soc_mem_field32_get(unit, config_mem[i], &l2_entry,
   4293                                     burst_mant_fields[idx]);
   4294             }
   4295             break;
   4296 
   4297         default:
   4298             SOC_EGRESS_METERING_UNLOCK(unit);
   4299             return BCM_E_PARAM;
   4300     }
   4301  
   4302     SOC_EGRESS_METERING_UNLOCK(unit);
   4303     /* convert exp and mantissa to bps */
   4304     rv = soc_katana_compute_shaper_rate(unit, rate_mantissa[0], rate_exp[0],
   4305                                         max_quantum);
   4306     if (BCM_FAILURE(rv)) {
   4307         return(rv);
   4308     }
   4309 
   4310     rv = soc_katana_compute_shaper_rate(unit, rate_mantissa[1], rate_exp[1],
   4311                                         min_quantum);
   4312     if (BCM_FAILURE(rv)) {
   4313         return(rv);
   4314     }
   4315 
   4316     /* Reset min shaping rate for port */
   4317     if(level == _BCM_KT_COSQ_NODE_LEVEL_ROOT) {
   4318        *min_quantum = 0;
   4319     }
   4320 
   4321     rv = soc_katana_compute_shaper_burst(unit, burst_mantissa[0], burst_exp[0],
   4322                                          burst_max_quantum);
   4323     if (BCM_FAILURE(rv)) {
   4324         return(rv);
   4325     }
   4326 
   4327     rv = soc_katana_compute_shaper_burst(unit, burst_mantissa[1], burst_exp[1],
   4328                                          burst_min_quantum);
   4329     if (BCM_FAILURE(rv)) {
   4330         return(rv);
   4331     }    
   4332 
   4333     return BCM_E_NONE;
   4334 }
   4335 
   4336 STATIC int
   4337 _bcm_kt_cosq_dynamic_bucket_set(int unit, bcm_gport_t port, bcm_cos_queue_t cosq,
   4338                                         uint32 min_quantum, uint32 max_quantum,
   4339                                         uint32 burst_min_quantum, uint32 burst_max_quantum,
   4340                                         uint32 flags)
   4341 {
   4342     _bcm_kt_mmu_info_t *mmu_info;
   4343     _bcm_kt_cosq_node_t *node, *cur_node, *l0_node;
   4344     bcm_port_t local_port;
   4345     int numq;
   4346 
   4347     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
   4348         BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port) ||
   4349         BCM_GPORT_IS_SCHEDULER(port)) {
   4350         BCM_IF_ERROR_RETURN
   4351             (_bcm_kt_cosq_bucket_set(unit, port, cosq, min_quantum,
   4352                                      max_quantum, burst_min_quantum,
   4353                                      burst_max_quantum, flags));  
   4354     } else {
   4355         BCM_IF_ERROR_RETURN
   4356             (_bcm_kt_cosq_localport_resolve(unit, port, &local_port));
   4357         mmu_info = _bcm_kt_mmu_info[unit];
   4358 
   4359         node = &mmu_info->sched_node[local_port];
   4360         
   4361         if (node->gport < 0) {
   4362             return BCM_E_PARAM;
   4363         }
   4364 
   4365         if ((l0_node = node->child) == NULL) {
   4366             return BCM_E_PARAM;
   4367         }
   4368         BCM_IF_ERROR_RETURN
   4369             (_bcm_kt_cosq_bucket_set(unit, port, cosq, 0,
   4370                                      max_quantum, 0,
   4371                                      burst_max_quantum, flags));  
   4372         
   4373         numq = soc_property_get(unit, spn_BCM_NUM_COS, BCM_COS_DEFAULT);
   4374         for (cur_node = l0_node->child; cur_node != NULL;
   4375             cur_node = cur_node->sibling) {
   4376             if (cur_node->cosq_attached_to == cosq ||
   4377                 cur_node->cosq_attached_to == (cosq + numq)) {
   4378                 BCM_IF_ERROR_RETURN
   4379                     (_bcm_kt_cosq_bucket_set(unit, cur_node->gport, 0, 
   4380                                              min_quantum,
   4381                                              0, burst_min_quantum,
   4382                                              0, flags));  
   4383                 continue;
   4384             }
   4385         } 
   4386 
   4387     }
   4388 
   4389     return BCM_E_NONE;
   4390 }
   4391 
   4392 STATIC int
   4393 _bcm_kt_cosq_dynamic_bucket_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   4394                         uint32 *min_quantum, uint32 *max_quantum,
   4395                         uint32 *burst_min_quantum, uint32 *burst_max_quantum,
   4396                         uint32 flags)
   4397 {
   4398     _bcm_kt_mmu_info_t *mmu_info;
   4399     _bcm_kt_cosq_node_t *node, *cur_node, *l0_node;
   4400     bcm_port_t local_port;
   4401     int numq;
   4402     uint32 temp_val;
   4403 
   4404     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
   4405         BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port) ||
   4406         BCM_GPORT_IS_SCHEDULER(port)) {
   4407         BCM_IF_ERROR_RETURN
   4408             (_bcm_kt_cosq_bucket_get(unit, port, cosq,
   4409                                      min_quantum, max_quantum,
   4410                                      burst_min_quantum, burst_max_quantum, 
   4411                                      flags)); 
   4412     } else {
   4413         BCM_IF_ERROR_RETURN
   4414             (_bcm_kt_cosq_localport_resolve(unit, port, &local_port));
   4415         mmu_info = _bcm_kt_mmu_info[unit];
   4416 
   4417         node = &mmu_info->sched_node[local_port];
   4418         
   4419         if (node->gport < 0) {
   4420             return BCM_E_PARAM;
   4421         }
   4422 
   4423         if ((l0_node = node->child) == NULL) {
   4424             return BCM_E_PARAM;
   4425         }
   4426 
   4427         BCM_IF_ERROR_RETURN
   4428             (_bcm_kt_cosq_bucket_get(unit, port, cosq, &temp_val,
   4429                                      max_quantum, &temp_val,
   4430                                      burst_max_quantum, flags));  
   4431         
   4432         numq = soc_property_get(unit, spn_BCM_NUM_COS, BCM_COS_DEFAULT);
   4433         for (cur_node = l0_node->child; cur_node != NULL;
   4434             cur_node = cur_node->sibling) {
   4435             if (cur_node->child != NULL && (cur_node->cosq_attached_to == cosq ||
   4436                 cur_node->cosq_attached_to == (cosq + numq))) {
   4437                 BCM_IF_ERROR_RETURN
   4438                     (_bcm_kt_cosq_bucket_get(unit, cur_node->gport, 0,
   4439                                              min_quantum,
   4440                                              &temp_val, burst_min_quantum,
   4441                                              &temp_val, flags));  
   4442                 break;
   4443             }
   4444         } 
   4445 
   4446     }
   4447 
   4448     return BCM_E_NONE;
   4449 }
   4450 
   4451 /*
   4452  *  Convert HW drop probability to percent value
   4453  */
   4454 STATIC int
   4455 _bcm_kt_hw_drop_prob_to_percent[] = {
   4456     0,     /* 0  */
   4457     1,     /* 1  */
   4458     2,     /* 2  */
   4459     3,     /* 3  */
   4460     4,     /* 4  */
   4461     5,     /* 5  */
   4462     6,     /* 6  */
   4463     7,     /* 7  */
   4464     8,     /* 8  */
   4465     9,     /* 9  */
   4466     10,    /* 10 */
   4467     25,    /* 11 */
   4468     50,    /* 12 */
   4469     75,    /* 13 */
   4470     100,   /* 14 */
   4471     -1     /* 15 */
   4472 };
   4473 
   4474 STATIC int
   4475 _bcm_kt_percent_to_drop_prob(int percent)
   4476 {
   4477    int i;
   4478 
   4479    for (i = 14; i > 0 ; i--) {
   4480       if (percent >= _bcm_kt_hw_drop_prob_to_percent[i]) {
   4481           break;
   4482       }
   4483    }
   4484    return i;
   4485 }
   4486 
   4487 STATIC int
   4488 _bcm_kt_drop_prob_to_percent(int drop_prob) {
   4489    return (_bcm_kt_hw_drop_prob_to_percent[drop_prob]);
   4490 }
   4491 
   4492 /*
   4493  * Function:
   4494  *     _bcm_kt_cosq_wred_set
   4495  * Purpose:
   4496  *     Configure unicast queue WRED setting
   4497  * Parameters:
   4498  *     unit                - (IN) unit number
   4499  *     port                - (IN) port number or GPORT identifier
   4500  *     cosq                - (IN) COS queue number
   4501  *     flags               - (IN) BCM_COSQ_DISCARD_XXX
   4502  *     min_thresh          - (IN)
   4503  *     max_thresh          - (IN)
   4504  *     drop_probablity     - (IN)
   4505  *     gain                - (IN)
   4506  *     ignore_enable_flags - (IN)
   4507  * Returns:
   4508  *     BCM_E_XXX
   4509  * Notes:
   4510  *     If port is any form of local port, cosq is the hardware queue index.
   4511  */
   4512 STATIC int
   4513 _bcm_kt_cosq_wred_set(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   4514                       uint32 flags, uint32 min_thresh, uint32 max_thresh,
   4515                       int drop_probability, int gain, int ignore_enable_flags)
   4516 {
   4517     soc_reg_t reg = 0;
   4518     soc_field_t field;
   4519     uint32 rval = 0;
   4520     bcm_port_t local_port;
   4521     int index;
   4522     uint32 profile_index, old_profile_index, partner_index;
   4523     mmu_wred_drop_curve_profile_0_entry_t entry_tcp_green;
   4524     mmu_wred_drop_curve_profile_1_entry_t entry_tcp_yellow;
   4525     mmu_wred_drop_curve_profile_2_entry_t entry_tcp_red;
   4526     mmu_wred_drop_curve_profile_3_entry_t entry_nontcp_green;
   4527     mmu_wred_drop_curve_profile_4_entry_t entry_nontcp_yellow;
   4528     mmu_wred_drop_curve_profile_5_entry_t entry_nontcp_red;
   4529     void *entries[6];
   4530     soc_mem_t mems[6];
   4531     _bcm_kt_cosq_node_t *node;
   4532     soc_mem_t wred_mem = MMU_WRED_QUEUE_CONFIG_BUFFERm;
   4533     soc_mem_t partner_mem = MMU_WRED_QUEUE_CONFIG_QENTRYm;
   4534     mmu_wred_queue_config_buffer_entry_t qentry, entry;
   4535     int rate, i;
   4536     int wred_enabled = 0;
   4537     int ext_mem_port_count = 0;
   4538 
   4539     reg = WRED_CONFIGr;
   4540     if (flags & BCM_COSQ_DISCARD_DEVICE) {
   4541 /* For port -1 , set global wred discard profile for all ports */
   4542         if ((port == -1) || (flags & BCM_COSQ_DISCARD_PACKETS)) {
   4543             reg = GLOBAL_WRED_CONFIG_QENTRYr;
   4544             field = WRED_ENABLEf;
   4545             local_port = 0;
   4546             index = 0; /* mmu init code uses service pool 0 only */
   4547         } else {
   4548             return BCM_E_PARAM;
   4549         }
   4550     } else {
   4551         if (cosq == -1) {
   4552            return BCM_E_PARAM;
   4553         }
   4554         BCM_IF_ERROR_RETURN
   4555             (_bcm_kt_cosq_index_resolve(unit, port, cosq,
   4556                                         _BCM_KT_COSQ_INDEX_STYLE_WRED,
   4557                                         &local_port, &index, NULL));
   4558         /* WRED doesn't work on CPU/LB Ports */
   4559         if (IS_LB_PORT(unit, local_port) || IS_CPU_PORT(unit, local_port)) {
   4560             return BCM_E_PORT;
   4561         }
   4562 
   4563         if (flags & BCM_COSQ_DISCARD_PACKETS) {
   4564             wred_mem = MMU_WRED_QUEUE_CONFIG_QENTRYm;
   4565             partner_mem = MMU_WRED_QUEUE_CONFIG_BUFFERm;
   4566         }
   4567         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
   4568             BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port) ||
   4569             BCM_GPORT_IS_SCHEDULER(port)) {
   4570                 BCM_IF_ERROR_RETURN
   4571                     (_bcm_kt_cosq_node_get(unit, port, NULL, &local_port, NULL,
   4572                                        &node));
   4573  
   4574                 if (node->level == _BCM_KT_COSQ_NODE_LEVEL_L1) {
   4575                     wred_mem = (flags & BCM_COSQ_DISCARD_PACKETS) ? 
   4576                                 MMU_WRED_OPN_CONFIG_QENTRYm : 
   4577                                 MMU_WRED_OPN_CONFIG_BUFFERm;
   4578                     partner_mem = (flags & BCM_COSQ_DISCARD_PACKETS) ? 
   4579                                 MMU_WRED_OPN_CONFIG_BUFFERm : 
   4580                                 MMU_WRED_OPN_CONFIG_QENTRYm;                                
   4581                 }
   4582             }
   4583         field = WRED_ENf;
   4584     }
   4585 
   4586     old_profile_index = 0xffffffff;
   4587     profile_index = 0xffffffff;
   4588     if (reg == GLOBAL_WRED_CONFIG_QENTRYr) {
   4589         BCM_IF_ERROR_RETURN(soc_reg32_get(unit, reg, local_port, index, &rval));
   4590     } else {
   4591         SOC_IF_ERROR_RETURN
   4592            (soc_mem_read(unit, wred_mem, MEM_BLOCK_ALL,
   4593                          index, &qentry));
   4594     }
   4595     if (flags & (BCM_COSQ_DISCARD_NONTCP | BCM_COSQ_DISCARD_COLOR_ALL)) {
   4596         if (reg == GLOBAL_WRED_CONFIG_QENTRYr) {
   4597             old_profile_index = soc_reg_field_get(unit, reg, rval, PROFILE_INDEXf);
   4598         } else {
   4599             old_profile_index = soc_mem_field32_get(unit, wred_mem,
   4600                                                     &qentry, PROFILE_INDEXf);
   4601         } 
   4602         entries[0] = &entry_tcp_green;
   4603         entries[1] = &entry_tcp_yellow;
   4604         entries[2] = &entry_tcp_red;
   4605         entries[3] = &entry_nontcp_green;
   4606         entries[4] = &entry_nontcp_yellow;
   4607         entries[5] = &entry_nontcp_red;
   4608         BCM_IF_ERROR_RETURN
   4609             (soc_profile_mem_get(unit, _bcm_kt_wred_profile[unit],
   4610                                  old_profile_index, 1, entries));
   4611         for (i = 0; i < 6; i++) {
   4612             mems[i] = INVALIDm;
   4613         }
   4614         if (!(flags & BCM_COSQ_DISCARD_NONTCP)) {
   4615             if (flags & BCM_COSQ_DISCARD_COLOR_GREEN) {
   4616                 mems[0] = MMU_WRED_DROP_CURVE_PROFILE_0m;
   4617             }
   4618             if (flags & BCM_COSQ_DISCARD_COLOR_YELLOW) {
   4619                 mems[1] = MMU_WRED_DROP_CURVE_PROFILE_1m;
   4620             }
   4621             if (flags & BCM_COSQ_DISCARD_COLOR_RED) {
   4622                 mems[2] = MMU_WRED_DROP_CURVE_PROFILE_2m;
   4623             }
   4624         } else if (!(flags & (BCM_COSQ_DISCARD_COLOR_GREEN |
   4625                               BCM_COSQ_DISCARD_COLOR_YELLOW |
   4626                               BCM_COSQ_DISCARD_COLOR_RED))) {
   4627             mems[3] = MMU_WRED_DROP_CURVE_PROFILE_3m;
   4628             mems[4] = MMU_WRED_DROP_CURVE_PROFILE_4m;
   4629             mems[5] = MMU_WRED_DROP_CURVE_PROFILE_5m;
   4630 
   4631         } else {
   4632             if (flags & BCM_COSQ_DISCARD_COLOR_GREEN) {
   4633                 mems[3] = MMU_WRED_DROP_CURVE_PROFILE_3m;
   4634             }
   4635             if (flags & BCM_COSQ_DISCARD_COLOR_YELLOW) {
   4636                 mems[4] = MMU_WRED_DROP_CURVE_PROFILE_4m;
   4637             }
   4638             if (flags & BCM_COSQ_DISCARD_COLOR_RED) {
   4639                 mems[5] = MMU_WRED_DROP_CURVE_PROFILE_5m;
   4640             }
   4641         }
   4642         rate = _bcm_kt_percent_to_drop_prob(drop_probability);
   4643         for (i = 0; i < 6; i++) {
   4644             if (mems[i] == INVALIDm) {
   4645                 continue;
   4646             }
   4647             soc_mem_field32_set(unit, mems[i], entries[i], MIN_THDf,
   4648                                 min_thresh);
   4649             soc_mem_field32_set(unit, mems[i], entries[i], MAX_THDf,
   4650                                 max_thresh);
   4651             soc_mem_field32_set(unit, mems[i], entries[i], MAX_DROP_RATEf,
   4652                                 rate);
   4653         }
   4654         BCM_IF_ERROR_RETURN
   4655             (soc_profile_mem_add(unit, _bcm_kt_wred_profile[unit], entries, 1,
   4656                                  &profile_index));
   4657         if (reg == GLOBAL_WRED_CONFIG_QENTRYr) {
   4658             soc_reg_field_set(unit, reg, &rval, PROFILE_INDEXf, profile_index);
   4659             soc_reg_field_set(unit, reg, &rval, WEIGHTf, gain);
   4660         } else {
   4661             soc_mem_field32_set(unit, wred_mem, &qentry, PROFILE_INDEXf, profile_index);
   4662             soc_mem_field32_set(unit, wred_mem, &qentry, WEIGHTf, gain);
   4663         }
   4664     }
   4665 
   4666     /* Some APIs only modify profiles */
   4667     if (!ignore_enable_flags) {
   4668         if ( reg == GLOBAL_WRED_CONFIG_QENTRYr) {
   4669             soc_reg_field_set(unit, reg, &rval, CAP_AVERAGEf,
   4670                               flags & BCM_COSQ_DISCARD_CAP_AVERAGE ? 1 : 0);
   4671             soc_reg_field_set(unit, reg, &rval, field,
   4672                               flags & BCM_COSQ_DISCARD_ENABLE ? 1 : 0);
   4673         } else {
   4674             soc_mem_field32_set(unit, wred_mem, &qentry, CAP_AVERAGEf,
   4675                               flags & BCM_COSQ_DISCARD_CAP_AVERAGE ? 1 : 0);
   4676             soc_mem_field32_set(unit, wred_mem, &qentry, field,
   4677                               flags & BCM_COSQ_DISCARD_ENABLE ? 1 : 0);
   4678             if (wred_mem == MMU_WRED_QUEUE_CONFIG_BUFFERm || 
   4679                 wred_mem == MMU_WRED_QUEUE_CONFIG_QENTRYm) {
   4680                 /* ECN marking is applicable only for queues */
   4681                 soc_mem_field32_set(unit, wred_mem, &qentry, ECN_MARKING_ENf,
   4682                                     flags & BCM_COSQ_DISCARD_MARK_CONGESTION ?
   4683                                     1 : 0);
   4684                 if (wred_mem == MMU_WRED_QUEUE_CONFIG_QENTRYm) {
   4685                     /* ECN marking needs to be enabled in BUFFER entry */
   4686                     SOC_IF_ERROR_RETURN
   4687                            (soc_mem_read(unit, MMU_WRED_QUEUE_CONFIG_BUFFERm, 
   4688                                          MEM_BLOCK_ALL, index, &entry));
   4689                     soc_mem_field32_set(unit, MMU_WRED_QUEUE_CONFIG_BUFFERm, 
   4690                                        &entry, ECN_MARKING_ENf,
   4691                                        flags & BCM_COSQ_DISCARD_MARK_CONGESTION ?
   4692                                        1 : 0);
   4693                     SOC_IF_ERROR_RETURN
   4694                         (soc_mem_write(unit, MMU_WRED_QUEUE_CONFIG_BUFFERm, 
   4695                                        MEM_BLOCK_ALL, index, &entry));
   4696                 }    
   4697             }
   4698         }
   4699     }
   4700 
   4701     partner_index = 0xffffffff;
   4702     if (reg == GLOBAL_WRED_CONFIG_QENTRYr) {
   4703         BCM_IF_ERROR_RETURN(soc_reg32_set(unit, reg, local_port, index, rval));
   4704 
   4705         /* update interna/external buffer entries based on port configuration */
   4706         BCM_IF_ERROR_RETURN(soc_reg32_get(unit, GLOBAL_WRED_CONFIG_BUFFERIr,
   4707                                           local_port, index, &rval));
   4708         soc_reg_field_set(unit, GLOBAL_WRED_CONFIG_BUFFERIr, &rval, field,
   4709                           flags & BCM_COSQ_DISCARD_ENABLE ? 1 : 0);
   4710         soc_reg_field_set(unit, GLOBAL_WRED_CONFIG_BUFFERIr, &rval,
   4711                           PROFILE_INDEXf, 0);
   4712         BCM_IF_ERROR_RETURN(soc_reg32_set(unit, GLOBAL_WRED_CONFIG_BUFFERIr,
   4713                             local_port, index, rval));
   4714         BCM_PBMP_COUNT(PBMP_EXT_MEM (unit), ext_mem_port_count);
   4715         if (ext_mem_port_count > 0) {
   4716             BCM_IF_ERROR_RETURN(soc_reg32_get(unit, GLOBAL_WRED_CONFIG_BUFFEREr,
   4717                                               local_port, index, &rval));
   4718             soc_reg_field_set(unit, GLOBAL_WRED_CONFIG_BUFFEREr, &rval, field,
   4719                               flags & BCM_COSQ_DISCARD_ENABLE ? 1 : 0);
   4720             soc_reg_field_set(unit, GLOBAL_WRED_CONFIG_BUFFEREr, &rval,
   4721                               PROFILE_INDEXf, 0);
   4722             BCM_IF_ERROR_RETURN(soc_reg32_set(unit, GLOBAL_WRED_CONFIG_BUFFEREr,
   4723                                 local_port, index, rval));
   4724         }
   4725     } else {
   4726         SOC_IF_ERROR_RETURN
   4727             (soc_mem_write(unit, wred_mem, MEM_BLOCK_ALL,
   4728                            index, &qentry));
   4729         SOC_IF_ERROR_RETURN
   4730             (soc_mem_read(unit, partner_mem, MEM_BLOCK_ALL,
   4731                               index, &qentry));
   4732         wred_enabled = soc_mem_field32_get(unit, partner_mem,
   4733                                            &qentry, WRED_ENf);
   4734         
   4735         /* if buffer/qentry_mem WRED enabled, make sure the partner_mem (qentry/buffer_mem) 
   4736          * also WRED enabled.
   4737          * if buffer/qentry_mem WRED disabled, make sure the partner_mem (qentry/buffer_mem) 
   4738          * also WRED disabled. 
   4739          */
   4740         if (((flags & BCM_COSQ_DISCARD_ENABLE) && (wred_enabled == 0)) ||
   4741             (!(flags & BCM_COSQ_DISCARD_ENABLE) && (wred_enabled == 1))) {
   4742             partner_index = soc_mem_field32_get(unit, partner_mem,
   4743                                                 &qentry, PROFILE_INDEXf);                     
   4744             soc_mem_field32_set(unit, partner_mem, &qentry, PROFILE_INDEXf, 0);
   4745             soc_mem_field32_set(unit, partner_mem, &qentry, WRED_ENf, 
   4746                                 flags & BCM_COSQ_DISCARD_ENABLE ? 1 : 0);
   4747             SOC_IF_ERROR_RETURN
   4748                 (soc_mem_write(unit, partner_mem, MEM_BLOCK_ALL,
   4749                                index, &qentry));    
   4750         }    
   4751     }
   4752 
   4753 /* Replacing old profiles with new global profiles when wred discard 
   4754    profile is set for all ports */
   4755 
   4756     if ((port == -1) && (flags & BCM_COSQ_DISCARD_DEVICE) &&
   4757                         (profile_index != 0xffffffff)) {
   4758         for (i = 1; i < SOC_REG_NUMELS(unit, reg); i++) {
   4759             BCM_IF_ERROR_RETURN(soc_profile_mem_add(unit, 
   4760                         _bcm_kt_wred_profile[unit], entries, 1, 
   4761                         &profile_index));
   4762             BCM_IF_ERROR_RETURN(soc_reg32_set(unit, reg, local_port, i, rval));
   4763         }
   4764     }
   4765 
   4766     if (old_profile_index != 0xffffffff && old_profile_index > 0) {
   4767         BCM_IF_ERROR_RETURN
   4768             (soc_profile_mem_delete(unit, _bcm_kt_wred_profile[unit],
   4769                                     old_profile_index));
   4770         if((port==-1) && (flags & BCM_COSQ_DISCARD_DEVICE)) {
   4771             for(i = 1; i < SOC_REG_NUMELS(unit, reg); i++) {
   4772                 BCM_IF_ERROR_RETURN(soc_profile_mem_delete(unit,
   4773                              _bcm_kt_wred_profile[unit], 
   4774                              old_profile_index));
   4775             }
   4776         }
   4777     }
   4778     
   4779     if (partner_index != 0xffffffff && partner_index > 0) {
   4780         BCM_IF_ERROR_RETURN
   4781             (soc_profile_mem_delete(unit, _bcm_kt_wred_profile[unit],
   4782                                     partner_index));
   4783     }    
   4784 
   4785     return BCM_E_NONE;
   4786 }
   4787 
   4788 /*
   4789  * Function:
   4790  *     _bcm_kt_cosq_wred_get
   4791  * Purpose:
   4792  *     Get unicast queue WRED setting
   4793  * Parameters:
   4794  *     unit                - (IN) unit number
   4795  *     port                - (IN) port number or GPORT identifier
   4796  *     cosq                - (IN) COS queue number
   4797  *     flags               - (IN/OUT) BCM_COSQ_DISCARD_XXX
   4798  *     min_thresh          - (OUT)
   4799  *     max_thresh          - (OUT)
   4800  *     drop_probablity     - (OUT)
   4801  *     gain                - (OUT)
   4802  * Returns:
   4803  *     BCM_E_XXX
   4804  * Notes:
   4805  *     If port is any form of local port, cosq is the hardware queue index.
   4806  */
   4807 STATIC int
   4808 _bcm_kt_cosq_wred_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   4809                       uint32 *flags, uint32 *min_thresh, uint32 *max_thresh,
   4810                       int *drop_probability, int *gain)
   4811 {
   4812     soc_reg_t reg = 0;
   4813     soc_field_t field;
   4814     uint32 rval;
   4815     bcm_port_t local_port;
   4816     int index, profile_index;
   4817     mmu_wred_drop_curve_profile_0_entry_t entry_tcp_green;
   4818     mmu_wred_drop_curve_profile_1_entry_t entry_tcp_yellow;
   4819     mmu_wred_drop_curve_profile_2_entry_t entry_tcp_red;
   4820     mmu_wred_drop_curve_profile_3_entry_t entry_nontcp_green;
   4821     mmu_wred_drop_curve_profile_4_entry_t entry_nontcp_yellow;
   4822     mmu_wred_drop_curve_profile_5_entry_t entry_nontcp_red;
   4823     void *entries[6];
   4824     void *entry_p;
   4825     soc_mem_t mem;
   4826     _bcm_kt_cosq_node_t *node;
   4827     soc_mem_t wred_mem = MMU_WRED_QUEUE_CONFIG_BUFFERm;
   4828     mmu_wred_queue_config_buffer_entry_t qentry;
   4829     int rate;
   4830 
   4831     if (*flags & BCM_COSQ_DISCARD_DEVICE) {
   4832         if ((port == -1) || (*flags & BCM_COSQ_DISCARD_PACKETS)) {
   4833             reg = GLOBAL_WRED_CONFIG_QENTRYr;
   4834             field = WRED_ENABLEf;
   4835             local_port = 0;
   4836             index = 0; /* mmu init code uses service pool 0 only */
   4837             wred_mem = 0;
   4838         } else {
   4839             return BCM_E_PARAM;
   4840         }
   4841     } else {
   4842         if (cosq == -1) {
   4843            return BCM_E_PARAM;
   4844         }
   4845         BCM_IF_ERROR_RETURN
   4846             (_bcm_kt_cosq_index_resolve(unit, port, cosq,
   4847                                         _BCM_KT_COSQ_INDEX_STYLE_WRED,
   4848                                         &local_port, &index, NULL));
   4849         /* WRED doesn't work on CPU/LB Ports */
   4850         if (IS_LB_PORT(unit, local_port) || IS_CPU_PORT(unit, local_port)) {
   4851             return BCM_E_PORT;
   4852         }
   4853         if (*flags & BCM_COSQ_DISCARD_PACKETS) {
   4854             wred_mem = MMU_WRED_QUEUE_CONFIG_QENTRYm;
   4855         }
   4856         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
   4857             BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port) ||
   4858             BCM_GPORT_IS_SCHEDULER(port)) {        
   4859                 BCM_IF_ERROR_RETURN
   4860                     (_bcm_kt_cosq_node_get(unit, port, NULL, &local_port, NULL,
   4861                                        &node));
   4862                 if (node->level == _BCM_KT_COSQ_NODE_LEVEL_L1) {
   4863                     wred_mem = (*flags & BCM_COSQ_DISCARD_PACKETS) ? 
   4864                                 MMU_WRED_OPN_CONFIG_QENTRYm : 
   4865                                 MMU_WRED_OPN_CONFIG_BUFFERm;
   4866                 }
   4867             }
   4868          
   4869         field = WRED_ENf;
   4870     }
   4871 
   4872     if (reg == GLOBAL_WRED_CONFIG_QENTRYr) {
   4873         BCM_IF_ERROR_RETURN(soc_reg32_get(unit, reg, local_port, index, &rval));
   4874         profile_index = soc_reg_field_get(unit, reg, rval, PROFILE_INDEXf);
   4875     } else {
   4876             SOC_IF_ERROR_RETURN
   4877                (soc_mem_read(unit, wred_mem, MEM_BLOCK_ALL,
   4878                              index, &qentry));
   4879             profile_index = soc_mem_field32_get(unit, wred_mem,
   4880                                                 &qentry, PROFILE_INDEXf);
   4881     }
   4882 
   4883     if (!(*flags & BCM_COSQ_DISCARD_NONTCP)) {
   4884         if (*flags & BCM_COSQ_DISCARD_COLOR_GREEN) {
   4885             mem = MMU_WRED_DROP_CURVE_PROFILE_0m;
   4886             entry_p = &entry_tcp_green;
   4887         } else if (*flags & BCM_COSQ_DISCARD_COLOR_YELLOW) {
   4888             mem = MMU_WRED_DROP_CURVE_PROFILE_1m;
   4889             entry_p = &entry_tcp_yellow;
   4890         } else if (*flags & BCM_COSQ_DISCARD_COLOR_RED) {
   4891             mem = MMU_WRED_DROP_CURVE_PROFILE_2m;
   4892             entry_p = &entry_tcp_red;
   4893         } else {
   4894            mem = MMU_WRED_DROP_CURVE_PROFILE_0m;
   4895            entry_p = &entry_tcp_green;
   4896         }
   4897     } else {
   4898         if (*flags & BCM_COSQ_DISCARD_COLOR_GREEN) {
   4899             mem = MMU_WRED_DROP_CURVE_PROFILE_3m;
   4900             entry_p = &entry_nontcp_green;
   4901         } else if (*flags & BCM_COSQ_DISCARD_COLOR_YELLOW) {
   4902             mem = MMU_WRED_DROP_CURVE_PROFILE_4m;
   4903             entry_p = &entry_nontcp_yellow;
   4904         } else if (*flags & BCM_COSQ_DISCARD_COLOR_RED) {
   4905             mem = MMU_WRED_DROP_CURVE_PROFILE_5m;
   4906             entry_p = &entry_nontcp_red;
   4907         } else {
   4908            mem = MMU_WRED_DROP_CURVE_PROFILE_3m;
   4909            entry_p = &entry_nontcp_green;
   4910         }
   4911     }
   4912     entries[0] = &entry_tcp_green;
   4913     entries[1] = &entry_tcp_yellow;
   4914     entries[2] = &entry_tcp_red;
   4915     entries[3] = &entry_nontcp_green;
   4916     entries[4] = &entry_nontcp_yellow;
   4917     entries[5] = &entry_nontcp_red;
   4918     BCM_IF_ERROR_RETURN
   4919         (soc_profile_mem_get(unit, _bcm_kt_wred_profile[unit],
   4920                              profile_index, 1, entries));
   4921     if (min_thresh != NULL) {
   4922         *min_thresh = soc_mem_field32_get(unit, mem, entry_p, MIN_THDf);
   4923     }
   4924     if (max_thresh != NULL) {
   4925         *max_thresh = soc_mem_field32_get(unit, mem, entry_p, MAX_THDf);
   4926     }
   4927     if (drop_probability != NULL) {
   4928         rate = soc_mem_field32_get(unit, mem, entry_p, MAX_DROP_RATEf);
   4929         *drop_probability = _bcm_kt_drop_prob_to_percent(rate);
   4930     }
   4931 
   4932     if (gain != NULL && reg == GLOBAL_WRED_CONFIG_QENTRYr) {
   4933         *gain = soc_reg_field_get(unit, reg, rval, WEIGHTf);
   4934     }
   4935     if (gain != NULL && wred_mem != 0) {
   4936         *gain = soc_mem_field32_get(unit, wred_mem, &qentry, WEIGHTf);
   4937     }
   4938 
   4939     *flags &= ~(BCM_COSQ_DISCARD_CAP_AVERAGE | BCM_COSQ_DISCARD_ENABLE);
   4940     if ((reg == GLOBAL_WRED_CONFIG_QENTRYr) &&
   4941         soc_reg_field_get(unit, reg, rval, CAP_AVERAGEf)) {
   4942         *flags |= BCM_COSQ_DISCARD_CAP_AVERAGE;
   4943     }
   4944     if ((wred_mem != 0) &&
   4945          soc_mem_field32_get(unit, wred_mem, &qentry, CAP_AVERAGEf)) {
   4946         *flags |= BCM_COSQ_DISCARD_CAP_AVERAGE;
   4947     }
   4948 
   4949     if ((reg == GLOBAL_WRED_CONFIG_QENTRYr) &&
   4950         soc_reg_field_get(unit, reg, rval, field)) {
   4951         *flags |= BCM_COSQ_DISCARD_ENABLE;
   4952     }
   4953     if ((wred_mem != 0) &&
   4954          soc_mem_field32_get(unit, wred_mem, &qentry, field)) {
   4955         *flags |= BCM_COSQ_DISCARD_ENABLE;
   4956     }
   4957 
   4958     if (wred_mem == MMU_WRED_QUEUE_CONFIG_BUFFERm || 
   4959         wred_mem == MMU_WRED_QUEUE_CONFIG_QENTRYm) {
   4960         if (soc_mem_field32_get(unit, wred_mem, &qentry, ECN_MARKING_ENf)) {
   4961             *flags |= BCM_COSQ_DISCARD_MARK_CONGESTION;
   4962         }
   4963     }
   4964 
   4965     return BCM_E_NONE;
   4966 }
   4967     
   4968 STATIC int
   4969 _bcm_kt_cosq_dynamic_hierarchy_create(int unit, bcm_gport_t port, int numq)
   4970 {
   4971     bcm_gport_t port_sched, l0_sched, l1_sched[16];
   4972     bcm_gport_t queue;
   4973     int i, encap_id;
   4974     _bcm_kt_mmu_info_t *mmu_info;
   4975 
   4976     BCM_IF_ERROR_RETURN
   4977         (bcm_kt_cosq_gport_add(unit, port, 1, 0, &port_sched));
   4978 
   4979     /* coverity[uninit_use_in_call] */
   4980     BCM_IF_ERROR_RETURN
   4981         (bcm_kt_cosq_gport_add(unit, port, 16, BCM_COSQ_GPORT_SCHEDULER, 
   4982                                &l0_sched));
   4983     BCM_IF_ERROR_RETURN
   4984         (bcm_kt_cosq_gport_attach(unit, l0_sched, port_sched, 0));
   4985 
   4986     for (i = 0; i < (2 * numq); i++) {
   4987         BCM_IF_ERROR_RETURN
   4988             (bcm_kt_cosq_gport_add(unit, port, 1, BCM_COSQ_GPORT_SCHEDULER, 
   4989                                    &l1_sched[i]));
   4990         BCM_IF_ERROR_RETURN
   4991             (bcm_kt_cosq_gport_attach(unit, l1_sched[i], l0_sched, i));         
   4992     }
   4993 
   4994     mmu_info = _bcm_kt_mmu_info[unit];
   4995     
   4996     for (i = 0; i < numq; i++) {
   4997         BCM_IF_ERROR_RETURN
   4998             (bcm_kt_cosq_gport_add(unit, port, 1,
   4999                                    BCM_COSQ_GPORT_UCAST_QUEUE_GROUP, &queue));
   5000         BCM_IF_ERROR_RETURN
   5001             (bcm_kt_cosq_gport_attach(unit, queue, l1_sched[i], 0));  
   5002         encap_id = (BCM_GPORT_SCHEDULER_GET(l1_sched[i]) >> 8) & 0x7ff;
   5003         mmu_info->l1_gport_pair[encap_id] = l1_sched[i + numq];
   5004         encap_id = (BCM_GPORT_SCHEDULER_GET(l1_sched[i + numq]) >> 8) & 0x7ff;
   5005         mmu_info->l1_gport_pair[encap_id] = l1_sched[i];        
   5006     }    
   5007     
   5008     return 0;
   5009 }
   5010 
   5011 STATIC int
   5012 _bcm_kt_cosq_gport_delete_all(int unit, bcm_gport_t gport, int *rv)
   5013 {
   5014     _bcm_kt_cosq_node_t *node;
   5015     _bcm_kt_mmu_info_t *mmu_info;
   5016     int encap_id;    
   5017     int local_port;
   5018     
   5019     BCM_IF_ERROR_RETURN
   5020         (_bcm_kt_cosq_node_get(unit, gport, NULL, NULL, NULL, &node));
   5021 
   5022     if (node->child != NULL) {
   5023         _bcm_kt_cosq_gport_delete_all(unit, node->child->gport, rv);
   5024         BCM_IF_ERROR_RETURN(*rv);
   5025     }
   5026 
   5027     if (node->sibling != NULL) {
   5028         _bcm_kt_cosq_gport_delete_all(unit, node->sibling->gport, rv);
   5029         BCM_IF_ERROR_RETURN(*rv);
   5030     }
   5031 
   5032     if (node->level != _BCM_KT_COSQ_NODE_LEVEL_ROOT && node->cosq_attached_to >= 0) {
   5033         *rv = bcm_kt_cosq_gport_detach(unit, node->gport, node->parent->gport, 
   5034                                        node->cosq_attached_to);
   5035         BCM_IF_ERROR_RETURN(*rv);
   5036     }
   5037 
   5038     mmu_info = _bcm_kt_mmu_info[unit];
   5039 
   5040     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) { /* unicast queue group */
   5041         encap_id = BCM_GPORT_UCAST_QUEUE_GROUP_QID_GET(gport);
   5042     } else if (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport)) {
   5043         /* subscriber queue group */
   5044         encap_id = BCM_GPORT_UCAST_SUBSCRIBER_QUEUE_GROUP_QID_GET(gport);
   5045         if (mmu_info->num_sub_queues > 0) {
   5046             _bcm_kt_node_index_clear(&mmu_info->sub_qlist,
   5047                     encap_id , 1);
   5048         } else {
   5049 
   5050             _bcm_kt_node_index_clear(&mmu_info->ext_qlist,
   5051                                 encap_id, 1);
   5052         }
   5053     } else {
   5054         if (BCM_GPORT_IS_SCHEDULER(gport)) {
   5055             /* scheduler node */
   5056             encap_id = (BCM_GPORT_SCHEDULER_GET(gport) >> 8) & 0x7ff;
   5057 
   5058             if (encap_id == 0) {
   5059                 encap_id = (BCM_GPORT_SCHEDULER_GET(gport) & 0xff);
   5060             }
   5061         } else if ((BCM_GPORT_IS_LOCAL(gport)) || (BCM_GPORT_IS_MODPORT(gport))) {
   5062             BCM_IF_ERROR_RETURN
   5063                (_bcm_kt_cosq_localport_resolve(unit, gport, &local_port));
   5064             if (local_port < 0) {
   5065                 return BCM_E_PORT;
   5066             }
   5067             encap_id = local_port;
   5068         } else {
   5069             return BCM_E_PARAM;
   5070         }
   5071 
   5072         _bcm_kt_node_index_clear(&mmu_info->sched_list, encap_id, 1);
   5073 
   5074    }
   5075    
   5076    if (node->cosq_map != NULL) {
   5077        sal_free(node->cosq_map);
   5078    } 
   5079 
   5080    _BCM_KT_COSQ_NODE_INIT(node);
   5081 
   5082     return BCM_E_NONE;
   5083 }
   5084 
   5085 /*
   5086  * Function:
   5087  *     _bcm_kt_intf_ref_cnt_increment
   5088  * Purpose:
   5089  *     Increase interface reference count for queue id
   5090  * Parameters:
   5091  *     unit  - (IN) unit number
   5092  *     queue_id - (IN) HW queue id
   5093  *     count  - (IN) Interface count
   5094  * Returns:
   5095  *     BCM_E_XXX
   5096  */
   5097 
   5098 int
   5099 _bcm_kt_intf_ref_cnt_increment(int unit, uint32 queue_id, int count)
   5100 {
   5101     _bcm_kt_mmu_info_t *mmu_info;
   5102 
   5103     if (_bcm_kt_mmu_info[unit] == NULL) {
   5104         return BCM_E_INIT;
   5105     }
   5106 
   5107     mmu_info = _bcm_kt_mmu_info[unit];
   5108     mmu_info->intf_ref_cnt[queue_id] = mmu_info->intf_ref_cnt[queue_id]
   5109                                        + count;
   5110     return BCM_E_NONE;
   5111 }
   5112 
   5113 /*
   5114  * Function:
   5115  *     _bcm_kt_intf_ref_cnt_decrement
   5116  * Purpose:
   5117  *     Decrease interface reference count for queue id
   5118  * Parameters:
   5119  *     unit  - (IN) unit number
   5120  *     queue_id - (IN) HW queue id
   5121  *     count  - (IN) Interface count
   5122  * Returns:
   5123  *     BCM_E_XXX
   5124  */
   5125 
   5126 int
   5127 _bcm_kt_intf_ref_cnt_decrement(int unit, uint32 queue_id, int count)
   5128 {
   5129     _bcm_kt_mmu_info_t *mmu_info;
   5130 
   5131     if (_bcm_kt_mmu_info[unit] == NULL) {
   5132         return BCM_E_INIT;
   5133     }
   5134 
   5135     mmu_info = _bcm_kt_mmu_info[unit];
   5136     if (mmu_info->intf_ref_cnt[queue_id] > 0) {
   5137         mmu_info->intf_ref_cnt[queue_id] = mmu_info->intf_ref_cnt[queue_id]
   5138                                            - count;
   5139     } else {
   5140         return BCM_E_PARAM;
   5141     }
   5142     return BCM_E_NONE;
   5143 }
   5144 
   5145 /*
   5146  * Function:
   5147  *     bcm_kt_cosq_gport_add
   5148  * Purpose:
   5149  *     Create a cosq gport structure
   5150  * Parameters:
   5151  *     unit  - (IN) unit number
   5152  *     port  - (IN) port number
   5153  *     numq  - (IN) number of COS queues
   5154  *     flags - (IN) flags (BCM_COSQ_GPORT_XXX)
   5155  *     gport - (OUT) GPORT identifier
   5156  * Returns:
   5157  *     BCM_E_XXX
   5158  */
   5159 int
   5160 bcm_kt_cosq_gport_add(int unit, bcm_gport_t port, int numq, uint32 flags,
   5161                       bcm_gport_t *gport)
   5162 {
   5163     soc_info_t *si;
   5164     _bcm_kt_mmu_info_t *mmu_info;
   5165     _bcm_kt_cosq_port_info_t *port_info;
   5166     _bcm_kt_cosq_node_t *node = NULL;
   5167     bcm_port_t local_port;
   5168     int id, max_nodes;
   5169     uint32 sched_encap;
   5170     _bcm_kt_cosq_list_t *list;
   5171     int max_queues;
   5172 
   5173     LOG_INFO(BSL_LS_BCM_COSQ,
   5174              (BSL_META_U(unit,
   5175                          "bcm_kt_cosq_gport_add: unit=%d port=0x%x numq=%d flags=0x%x\n"),
   5176               unit, port, numq, flags));
   5177 
   5178     if (gport == NULL) {
   5179         return BCM_E_PARAM;
   5180     }
   5181 
   5182     si = &SOC_INFO(unit);
   5183 
   5184     if (_bcm_kt_mmu_info[unit] == NULL) {
   5185         return BCM_E_INIT;
   5186     }
   5187 
   5188     BCM_IF_ERROR_RETURN
   5189         (_bcm_kt_cosq_localport_resolve(unit, port, &local_port));
   5190 
   5191     if (local_port < 0) {
   5192         return BCM_E_PORT;
   5193     }
   5194 
   5195     mmu_info = _bcm_kt_mmu_info[unit];
   5196     switch (flags) {
   5197     case BCM_COSQ_GPORT_UCAST_QUEUE_GROUP:
   5198     case BCM_COSQ_GPORT_VLAN_UCAST_QUEUE_GROUP:
   5199         if (numq != 1) {
   5200             return BCM_E_PARAM;
   5201         }
   5202 
   5203         if ((flags ==  BCM_COSQ_GPORT_VLAN_UCAST_QUEUE_GROUP) &&
   5204             (si->port_num_ext_cosq[local_port] == 0)) {
   5205             return BCM_E_PARAM;
   5206         }    
   5207 
   5208         port_info = &mmu_info->port[local_port];
   5209         
   5210         for (id = port_info->q_offset; id < port_info->q_limit; id++) {
   5211             if (mmu_info->queue_node[id].numq == 0) {
   5212                 break;
   5213             }
   5214         }
   5215         
   5216         if (id == port_info->q_limit) {
   5217             return BCM_E_RESOURCE;
   5218         }            
   5219 
   5220         BCM_GPORT_UCAST_QUEUE_GROUP_SYSQID_SET(*gport, local_port, id);
   5221         node = &mmu_info->queue_node[id];
   5222         node->gport = *gport;
   5223         node->numq = numq;
   5224         break;
   5225 
   5226     case BCM_COSQ_GPORT_SUBSCRIBER:
   5227         if (numq != 1) {
   5228             return BCM_E_PARAM;
   5229         }
   5230         /* chcek for pre allocated subscriber queues */
   5231         if (mmu_info->num_sub_queues == 0) {
   5232             list = &mmu_info->ext_qlist;
   5233             max_queues = mmu_info->num_ext_queues;
   5234         } else {
   5235             list = &mmu_info->sub_qlist;
   5236             max_queues = mmu_info->num_sub_queues;
   5237         }
   5238         BCM_IF_ERROR_RETURN
   5239             (_bcm_kt_node_index_get(unit, list->bits, 0, max_queues,
   5240                                 mmu_info->qset_size, 1, &id));
   5241         _bcm_kt_node_index_set(list, id, 1);
   5242         BCM_GPORT_UCAST_SUBSCRIBER_QUEUE_GROUP_SYSQID_SET(*gport,
   5243                                                  local_port, id);
   5244         if (mmu_info->num_sub_queues == 0) {
   5245             id += mmu_info->num_base_queues;
   5246         } else {
   5247             id += mmu_info->base_sub_queue;
   5248         }
   5249         node = &mmu_info->queue_node[id];
   5250         node->gport = *gport;
   5251         node->numq = numq;
   5252         break;
   5253 
   5254     case (BCM_COSQ_GPORT_WITH_ID |  BCM_COSQ_GPORT_SUBSCRIBER):
   5255         if (numq != 1) {
   5256             return BCM_E_PARAM;
   5257         }
   5258 
   5259         if (BCM_GPORT_UCAST_SUBSCRIBER_QUEUE_GROUP_SYSPORTID_GET(*gport)
   5260               != local_port) {
   5261             return BCM_E_PARAM;
   5262         }
   5263 
   5264         id = BCM_GPORT_UCAST_SUBSCRIBER_QUEUE_GROUP_QID_GET(*gport);
   5265         if ((id >= mmu_info->num_sub_queues) ||
   5266              (mmu_info->num_sub_queues == 0) ||
   5267              (mmu_info->intf_ref_cnt[id] != 0)) {
   5268             return BCM_E_PARAM;
   5269         }
   5270         max_queues = mmu_info->num_sub_queues;
   5271 
   5272         node = &mmu_info->queue_node[id + mmu_info->base_sub_queue];
   5273         if(node->numq != 0) {
   5274             return BCM_E_EXISTS;
   5275         }
   5276         _bcm_kt_node_index_set(&mmu_info->sub_qlist, id, 1);
   5277         _bcm_kt_node_index_set(&mmu_info->l2_sub_qlist, id, 1);
   5278 
   5279         id += mmu_info->base_sub_queue;
   5280         node->hw_index  = id;
   5281         node->gport = *gport;
   5282         node->numq = numq;
   5283         node->level = _BCM_KT_COSQ_NODE_LEVEL_L2;
   5284         node->type = _BCM_KT_NODE_SUBSCRIBER_GPORT_ID;
   5285         break;
   5286 
   5287     case BCM_COSQ_GPORT_SCHEDULER:
   5288         /* passthru */
   5289     case 0:  
   5290         /*
   5291          * Can not validate actual number of cosq until attach time.
   5292          * Maximum number of input is 8 for SP or WRR node
   5293          * expect -1 if number of inputs are unknown at this stage(WRR only)
   5294          */
   5295         if (numq == 0 || numq < -1) {
   5296             return BCM_E_PARAM;
   5297         }
   5298         
   5299         if (flags == BCM_COSQ_GPORT_SCHEDULER) {
   5300             BCM_IF_ERROR_RETURN
   5301                 (_bcm_kt_cosq_max_nodes_get(unit, _BCM_KT_COSQ_NODE_LEVEL_L2, 
   5302                                             &max_nodes));
   5303         } else {
   5304             BCM_IF_ERROR_RETURN
   5305                 (_bcm_kt_cosq_max_nodes_get(unit, _BCM_KT_COSQ_NODE_LEVEL_L0, 
   5306                                             &max_nodes));
   5307         }
   5308         if (numq > max_nodes) {
   5309             return BCM_E_PARAM;
   5310         }
   5311 
   5312         if ( flags == 0) {
   5313             /* this is a port level scheduler */
   5314             id = local_port;
   5315 
   5316             if ( id < 0 || id >= _BCM_KT_NUM_PORT_SCHEDULERS) {
   5317                 return BCM_E_PARAM;
   5318             }
   5319 
   5320             _bcm_kt_node_index_set(&mmu_info->sched_list, id, 1);
   5321             node = &mmu_info->sched_node[id];
   5322             sched_encap = (id << 8) | local_port;
   5323             BCM_GPORT_SCHEDULER_SET(*gport, sched_encap);
   5324             node->gport = *gport;
   5325             node->level = _BCM_KT_COSQ_NODE_LEVEL_ROOT;
   5326             node->hw_index = id;
   5327             node->numq = numq;
   5328             node->cosq_attached_to = 0;
   5329         } else {
   5330              /* allocate from sched_list, index will start from 36,
   5331               * 0-35 is used for port(root) schedulers. */
   5332             BCM_IF_ERROR_RETURN
   5333                 (_bcm_kt_node_index_get(unit, mmu_info->sched_list.bits,
   5334                                 _BCM_KT_NUM_PORT_SCHEDULERS,
   5335                                 mmu_info->num_nodes, 1, 1, &id));
   5336             _bcm_kt_node_index_set(&mmu_info->sched_list, id, 1);
   5337             node = &mmu_info->sched_node[id];
   5338             sched_encap = (id << 8) | local_port;
   5339             BCM_GPORT_SCHEDULER_SET(*gport, sched_encap);
   5340             node->gport = *gport;
   5341             node->numq = numq;
   5342             node->cosq_attached_to = -1;
   5343        }
   5344         break;
   5345         
   5346     case BCM_COSQ_GPORT_WITH_ID:
   5347         if (BCM_GPORT_IS_SCHEDULER(*gport)) {
   5348             if (numq == 0 || numq < -1 || numq > 8) {
   5349                 return BCM_E_PARAM;
   5350             }
   5351             id = BCM_GPORT_SCHEDULER_GET(*gport);
   5352 
   5353             if (id != local_port) {
   5354                 return BCM_E_PARAM;
   5355             }    
   5356             
   5357             /* allow only port level scheduler with id */
   5358             if ( id < 0 || id >= _BCM_KT_NUM_PORT_SCHEDULERS) {
   5359                 return BCM_E_PARAM;
   5360             }
   5361 
   5362             _bcm_kt_node_index_set(&mmu_info->sched_list, id, 1);
   5363             node = &mmu_info->sched_node[id];
   5364             node->gport = *gport;
   5365             node->level = _BCM_KT_COSQ_NODE_LEVEL_ROOT;
   5366             node->hw_index = id;
   5367             node->numq = numq;
   5368             node->cosq_attached_to = 0;
   5369         } else if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(*gport)) {
   5370             if (numq != 1) {
   5371                 return BCM_E_PARAM;
   5372             }
   5373 
   5374             if (BCM_GPORT_UCAST_QUEUE_GROUP_SYSPORTID_GET(*gport) != local_port) {
   5375                 return BCM_E_PARAM;
   5376             }    
   5377             
   5378             id = BCM_GPORT_UCAST_QUEUE_GROUP_QID_GET(*gport);
   5379             port_info = &mmu_info->port[local_port];
   5380             /* allow only base queues */
   5381             if (id < port_info->q_offset || id >= port_info->q_limit) {
   5382                 return BCM_E_PARAM;
   5383             }
   5384 
   5385             list = &mmu_info->l2_base_qlist; 
   5386             if (SHR_BITGET(list->bits, id) != 0) {
   5387                 return BCM_E_RESOURCE;
   5388             }    
   5389 
   5390             node = &mmu_info->queue_node[id];
   5391             if (node->numq != 0) {
   5392                 return BCM_E_EXISTS;
   5393             }
   5394             
   5395             _bcm_kt_node_index_set(&mmu_info->l2_base_qlist, id, 1);
   5396             node->hw_index  = id;  
   5397             node->gport = *gport;
   5398             node->numq = numq;          
   5399         } else {
   5400             return BCM_E_PARAM;
   5401         }
   5402         break;
   5403         
   5404     default:
   5405         return BCM_E_PARAM;
   5406     }
   5407 
   5408     LOG_INFO(BSL_LS_BCM_COSQ,
   5409              (BSL_META_U(unit,
   5410                          "                       gport=0x%x\n"),
   5411               *gport));
   5412 
   5413     return BCM_E_NONE;
   5414 }
   5415 
   5416 /*
   5417  * Function:
   5418  *     bcm_kt_cosq_gport_delete
   5419  * Purpose:
   5420  *     Destroy a cosq gport structure
   5421  * Parameters:
   5422  *     unit  - (IN) unit number
   5423  *     gport - (IN) GPORT identifier
   5424  * Returns:
   5425  *     BCM_E_XXX
   5426  */
   5427 int
   5428 bcm_kt_cosq_gport_delete(int unit, bcm_gport_t gport)
   5429 {
   5430     _bcm_kt_cosq_node_t *node;
   5431     _bcm_kt_mmu_info_t *mmu_info;
   5432     int encap_id;
   5433     int rv = BCM_E_NONE;
   5434     _bcm_kt_cosq_list_t *list;
   5435 
   5436     LOG_INFO(BSL_LS_BCM_COSQ,
   5437              (BSL_META_U(unit,
   5438                          "bcm_kt_cosq_gport_delete: unit=%d gport=0x%x\n"),
   5439               unit, gport));
   5440 
   5441     if (_bcm_kt_mmu_info[unit] == NULL) {
   5442         return BCM_E_INIT;
   5443     }
   5444     mmu_info = _bcm_kt_mmu_info[unit];
   5445     
   5446     BCM_IF_ERROR_RETURN
   5447         (_bcm_kt_cosq_node_get(unit, gport, NULL, NULL, NULL, &node));
   5448 
   5449     if (node->gport < 0) {
   5450         return BCM_E_NOT_FOUND;
   5451     }    
   5452     
   5453     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
   5454         BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport)) {
   5455         if (node->cosq_attached_to >= 0) {
   5456             BCM_IF_ERROR_RETURN
   5457                 (bcm_kt_cosq_gport_detach(unit, gport, node->parent->gport, 
   5458                                           node->cosq_attached_to));
   5459         }
   5460         if (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport)) {
   5461             encap_id = BCM_GPORT_UCAST_SUBSCRIBER_QUEUE_GROUP_QID_GET(gport);
   5462             if (mmu_info->num_sub_queues == 0) {
   5463                 list = &mmu_info->ext_qlist;
   5464             } else {
   5465                 list = &mmu_info->sub_qlist;
   5466             }
   5467             _bcm_kt_node_index_clear(list, encap_id, 1);
   5468         }    
   5469         _BCM_KT_COSQ_NODE_INIT(node);
   5470     } else {
   5471         BCM_IF_ERROR_RETURN
   5472             (_bcm_kt_cosq_gport_delete_all(unit, gport, &rv));
   5473     }
   5474 
   5475     return rv;
   5476 }
   5477 
   5478 /*
   5479  * Function:
   5480  *     bcm_kt_cosq_gport_get
   5481  * Purpose:
   5482  *     Get a cosq gport structure
   5483  * Parameters:
   5484  *     unit  - (IN) unit number
   5485  *     gport - (IN) GPORT identifier
   5486  *     port  - (OUT) port number
   5487  *     numq  - (OUT) number of COS queues
   5488  *     flags - (OUT) flags (BCM_COSQ_GPORT_XXX)
   5489  * Returns:
   5490  *     BCM_E_XXX
   5491  */
   5492 int
   5493 bcm_kt_cosq_gport_get(int unit, bcm_gport_t gport, bcm_gport_t *port,
   5494                       int *numq, uint32 *flags)
   5495 {
   5496     _bcm_kt_cosq_node_t *node;
   5497     bcm_module_t modid;
   5498     bcm_port_t local_port;
   5499     int id;
   5500     _bcm_gport_dest_t dest;
   5501 
   5502     if (port == NULL || numq == NULL || flags == NULL) {
   5503         return BCM_E_PARAM;
   5504     }
   5505 
   5506     LOG_INFO(BSL_LS_BCM_COSQ,
   5507              (BSL_META_U(unit,
   5508                          "bcm_kt_cosq_gport_get: unit=%d gport=0x%x\n"),
   5509               unit, gport));
   5510 
   5511     BCM_IF_ERROR_RETURN
   5512         (_bcm_kt_cosq_node_get(unit, gport, NULL, &local_port, &id, &node));
   5513 
   5514     if (SOC_USE_GPORT(unit)) {
   5515         BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid));
   5516         dest.gport_type = _SHR_GPORT_TYPE_MODPORT;
   5517         dest.modid = modid;
   5518         dest.port = local_port;
   5519         BCM_IF_ERROR_RETURN(_bcm_esw_gport_construct(unit, &dest, port));
   5520     } else {
   5521         *port = local_port;
   5522     }
   5523 
   5524     *numq = node->numq;
   5525 
   5526     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   5527         *flags = BCM_COSQ_GPORT_UCAST_QUEUE_GROUP;
   5528             
   5529     } else if (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport)) {
   5530         *flags = BCM_COSQ_GPORT_SUBSCRIBER;
   5531     } else if (BCM_GPORT_IS_SCHEDULER(gport)) {
   5532         *flags = BCM_COSQ_GPORT_SCHEDULER;
   5533     } else {
   5534         *flags = 0;
   5535     }
   5536 
   5537     LOG_INFO(BSL_LS_BCM_COSQ,
   5538              (BSL_META_U(unit,
   5539                          "                       port=0x%x numq=%d flags=0x%x\n"),
   5540               *port, *numq, *flags));
   5541 
   5542     return BCM_E_NONE;
   5543 }
   5544 
   5545 /*
   5546  * Function:
   5547  *     bcm_kt_cosq_gport_traverse
   5548  * Purpose:
   5549  *     Walks through the valid COSQ GPORTs and calls
   5550  *     the user supplied callback function for each entry.
   5551  * Parameters:
   5552  *     unit       - (IN) unit number
   5553  *     trav_fn    - (IN) Callback function.
   5554  *     user_data  - (IN) User data to be passed to callback function
   5555  * Returns:
   5556  *     BCM_E_NONE - Success.
   5557  *     BCM_E_XXX
   5558  */
   5559 int
   5560 bcm_kt_cosq_gport_traverse(int unit, bcm_cosq_gport_traverse_cb cb,
   5561                            void *user_data)
   5562 {
   5563     _bcm_kt_cosq_node_t *port_info;
   5564     _bcm_kt_mmu_info_t *mmu_info;
   5565     bcm_port_t local_port;
   5566     bcm_port_t port;
   5567 
   5568     if (_bcm_kt_mmu_info[unit] == NULL) {
   5569         return BCM_E_INIT;
   5570     }
   5571     mmu_info = _bcm_kt_mmu_info[unit];
   5572 
   5573     PBMP_ALL_ITER(unit, port) {
   5574         BCM_IF_ERROR_RETURN
   5575             (_bcm_kt_cosq_localport_resolve(unit, port, &local_port));
   5576 
   5577         if (local_port < 0) {
   5578             return BCM_E_PORT;
   5579         }
   5580         /* root node */
   5581         port_info = &mmu_info->sched_node[local_port];
   5582 
   5583         if (port_info->gport >= 0) {
   5584             _bcm_kt_cosq_gport_traverse(unit, port_info->gport, cb, user_data);
   5585         }
   5586       }
   5587 
   5588     return BCM_E_NONE;
   5589 }
   5590 
   5591 /*
   5592  * Function:
   5593  *     bcm_kt_cosq_mapping_set
   5594  * Purpose:
   5595  *     Determine which COS queue a given priority currently maps to.
   5596  * Parameters:
   5597  *     unit     - (IN) unit number
   5598  *     gport    - (IN) queue group GPORT identifier
   5599  *     priority - (IN) priority value to map
   5600  *     cosq     - (IN) COS queue to map to
   5601  * Returns:
   5602  *     BCM_E_XXX
   5603  */
   5604 int
   5605 bcm_kt_cosq_mapping_set(int unit, bcm_port_t gport, bcm_cos_t priority,
   5606                         bcm_cos_queue_t cosq)
   5607 { 
   5608     bcm_pbmp_t ports;
   5609     bcm_port_t local_port;
   5610 
   5611     if (gport == -1) {    /* all ports */
   5612         BCM_PBMP_ASSIGN(ports, PBMP_ALL(unit));
   5613     } else {
   5614         return _bcm_kt_cosq_mapping_set_regular(unit, gport, priority, cosq);
   5615     }
   5616 
   5617     PBMP_ITER(ports, local_port) {
   5618         BCM_IF_ERROR_RETURN
   5619             (_bcm_kt_cosq_mapping_set_regular(unit, local_port, priority, cosq));
   5620 
   5621     }    
   5622 
   5623     return BCM_E_NONE;
   5624 }
   5625 
   5626 
   5627 /*
   5628  * Function:
   5629  *     bcm_kt_cosq_mapping_get
   5630  * Purpose:
   5631  *     Determine which COS queue a given priority currently maps to.
   5632  * Parameters:
   5633  *     unit     - (IN) unit number
   5634  *     gport    - (IN) queue group GPORT identifier
   5635  *     priority - (IN) priority value to map
   5636  *     cosq     - (OUT) COS queue to map to
   5637  * Returns:
   5638  *     BCM_E_XXX
   5639  */
   5640 int
   5641 bcm_kt_cosq_mapping_get(int unit, bcm_port_t gport, bcm_cos_t priority,
   5642                         bcm_cos_queue_t *cosq)
   5643 {
   5644     _bcm_kt_mmu_info_t *mmu_info;
   5645     bcm_port_t port;
   5646     int numq;
   5647     bcm_cos_queue_t hw_cosq;
   5648     soc_field_t field = COSf;
   5649     int index;
   5650     cos_map_sel_entry_t cos_map_sel_entry;
   5651     void *entry_p;
   5652     bcm_pbmp_t ports;
   5653 
   5654     if (priority < 0 || priority >= 16) {
   5655         return BCM_E_PARAM;
   5656     }
   5657 
   5658     if (gport == -1) {
   5659         BCM_PBMP_ASSIGN(ports, PBMP_ALL(unit));
   5660         PBMP_ITER(ports, port) {
   5661             BCM_IF_ERROR_RETURN
   5662                 (READ_COS_MAP_SELm(unit, MEM_BLOCK_ANY, port, &cos_map_sel_entry));
   5663             index = soc_mem_field32_get(unit, COS_MAP_SELm, &cos_map_sel_entry,
   5664                                         SELECTf);
   5665             index *= 16;
   5666 
   5667             entry_p = SOC_PROFILE_MEM_ENTRY(unit, _bcm_kt_cos_map_profile[unit],
   5668                                             port_cos_map_entry_t *,
   5669                                             index + priority);
   5670             *cosq = soc_mem_field32_get(unit, PORT_COS_MAPm, entry_p, field);
   5671 
   5672             return BCM_E_NONE;
   5673         }
   5674     }
   5675 
   5676     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   5677         BCM_IF_ERROR_RETURN
   5678             (_bcm_kt_cosq_index_resolve
   5679             (unit, gport, -1, _BCM_KT_COSQ_INDEX_STYLE_UCAST_QUEUE,
   5680              &port, NULL, NULL));
   5681     } else {
   5682         if (BCM_GPORT_IS_SET(gport)) {
   5683             BCM_IF_ERROR_RETURN(
   5684                 bcm_esw_port_local_get(unit, gport, &port));
   5685         } else {
   5686             port = gport;
   5687         }
   5688 
   5689         if (!SOC_PORT_VALID(unit, port) || !IS_ALL_PORT(unit, port)) {
   5690             return BCM_E_PORT;
   5691         }
   5692     }
   5693 
   5694     mmu_info = _bcm_kt_mmu_info[unit];
   5695     numq = mmu_info->port[port].q_limit - 
   5696            mmu_info->port[port].q_offset;
   5697     
   5698     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   5699         field = (numq <= 8) ? COSf : HG_COSf;
   5700     }
   5701 
   5702     BCM_IF_ERROR_RETURN
   5703         (READ_COS_MAP_SELm(unit, MEM_BLOCK_ANY, port, &cos_map_sel_entry));
   5704     index = soc_mem_field32_get(unit, COS_MAP_SELm, &cos_map_sel_entry,
   5705                                 SELECTf);
   5706     index *= 16;
   5707 
   5708     entry_p = SOC_PROFILE_MEM_ENTRY(unit, _bcm_kt_cos_map_profile[unit],
   5709                                     port_cos_map_entry_t *,
   5710                                     index + priority);
   5711     hw_cosq = soc_mem_field32_get(unit, PORT_COS_MAPm, entry_p, field);
   5712 
   5713     if (hw_cosq >= numq) {
   5714         return BCM_E_NOT_FOUND;
   5715     }
   5716     *cosq = hw_cosq;
   5717 
   5718     return BCM_E_NONE;
   5719 }
   5720 
   5721 /*
   5722  * Function:
   5723  *     bcm_kt_cosq_port_sched_set
   5724  * Purpose:
   5725  *     Set up class-of-service policy and corresponding weights and delay
   5726  * Parameters:
   5727  *     unit    - (IN) unit number
   5728  *     pbm     - (IN) port bitmap
   5729  *     mode    - (IN) Scheduling mode (BCM_COSQ_xxx)
   5730  *     weights - (IN) Weights for each COS queue
   5731  *     delay   - This parameter is not used
   5732  * Returns:
   5733  *     BCM_E_XXX
   5734  * Notes:
   5735  *     For non-ETS style scheduler (CPU port) only.
   5736  */
   5737 int
   5738 bcm_kt_cosq_port_sched_set(int unit, bcm_pbmp_t pbm,
   5739                            int mode, const int *weights, int delay)
   5740 {
   5741     bcm_port_t port;
   5742     int num_cos;
   5743     int num_weights;
   5744 
   5745     num_cos = soc_property_get(unit, spn_BCM_NUM_COS, BCM_COS_DEFAULT);
   5746     
   5747     BCM_PBMP_ITER(pbm, port) {
   5748         num_weights = IS_CPU_PORT(unit, port) ? BCM_COS_COUNT : num_cos;
   5749             
   5750         BCM_IF_ERROR_RETURN
   5751             (_bcm_kt_cosq_port_sched_set(unit, port, 0, mode, num_weights,
   5752                                          (int *)weights));
   5753     }
   5754 
   5755     return BCM_E_NONE;
   5756 }
   5757 
   5758 /*
   5759  * Function:
   5760  *     bcm_kt_cosq_port_sched_get
   5761  * Purpose:
   5762  *     Retrieve class-of-service policy and corresponding weights and delay
   5763  * Parameters:
   5764  *     unit     - (IN) unit number
   5765  *     pbm      - (IN) port bitmap
   5766  *     mode     - (OUT) Scheduling mode (BCM_COSQ_XXX)
   5767  *     weights  - (OUT) Weights for each COS queue
   5768  *     delay    - This parameter is not used
   5769  * Returns:
   5770  *     BCM_E_XXX
   5771  * Notes:
   5772  *     For non-ETS style scheduler (CPU port) only.
   5773  */
   5774 int
   5775 bcm_kt_cosq_port_sched_get(int unit, bcm_pbmp_t pbm,
   5776                            int *mode, int *weights, int *delay)
   5777 {
   5778     bcm_port_t port;
   5779     int num_cos;
   5780     int num_weights;
   5781     
   5782     num_cos = soc_property_get(unit, spn_BCM_NUM_COS, BCM_COS_DEFAULT);
   5783     
   5784     BCM_PBMP_ITER(pbm, port) {
   5785         num_weights = IS_CPU_PORT(unit, port) ? BCM_COS_COUNT : num_cos;
   5786         
   5787         BCM_IF_ERROR_RETURN
   5788             (_bcm_kt_cosq_port_sched_get(unit, port, 0, mode, num_weights, 
   5789                                          weights));        
   5790     }
   5791 
   5792     return BCM_E_NONE;
   5793 }
   5794 
   5795 /*
   5796  * Function:
   5797  *     bcm_kt_cosq_sched_weight_max_get
   5798  * Purpose:
   5799  *     Retrieve maximum weights for given COS policy
   5800  * Parameters:
   5801  *     unit    - (IN) unit number
   5802  *     mode    - (IN) Scheduling mode (BCM_COSQ_xxx)
   5803  *     weight_max - (OUT) Maximum weight for COS queue.
   5804  * Returns:
   5805  *     BCM_E_XXX
   5806  */
   5807 int
   5808 bcm_kt_cosq_sched_weight_max_get(int unit, int mode, int *weight_max)
   5809 {
   5810     switch (mode) {
   5811     case BCM_COSQ_STRICT:
   5812         *weight_max = BCM_COSQ_WEIGHT_STRICT;
   5813         break;
   5814     case BCM_COSQ_ROUND_ROBIN:
   5815         *weight_max = BCM_COSQ_WEIGHT_MIN;
   5816         break;
   5817     case BCM_COSQ_WEIGHTED_ROUND_ROBIN:
   5818     case BCM_COSQ_DEFICIT_ROUND_ROBIN:
   5819         *weight_max =
   5820             (1 << soc_mem_field_length(unit, LLS_L0_CHILD_WEIGHT_CFG_CNTm, C_WEIGHTf)) - 1;
   5821         break;
   5822     default:
   5823         return BCM_E_PARAM;
   5824     }
   5825 
   5826     return BCM_E_NONE;
   5827 }
   5828 
   5829 /*
   5830  * Function:
   5831  *     bcm_kt_cosq_bandwidth_set
   5832  * Purpose:
   5833  *     Configure COS queue bandwidth control
   5834  * Parameters:
   5835  *     unit          - (IN) unit number
   5836  *     port          - (IN) port number or GPORT identifier
   5837  *     cosq          - (IN) COS queue number
   5838  *     min_quantum   - (IN)
   5839  *     max_quantum   - (IN)
   5840  *     burst_quantum - (IN)
   5841  *     flags         - (IN)
   5842  * Returns:
   5843  *     BCM_E_XXX
   5844  * Notes:
   5845  *     If port is any form of local port, cosq is the hardware queue index.
   5846  */
   5847 int
   5848 bcm_kt_cosq_port_bandwidth_set(int unit, bcm_port_t port,
   5849                                bcm_cos_queue_t cosq,
   5850                                uint32 min_quantum, uint32 max_quantum,
   5851                                uint32 burst_quantum, uint32 flags)
   5852 {
   5853     if (cosq < 0) {
   5854         return BCM_E_PARAM;
   5855     }
   5856 
   5857     return _bcm_kt_cosq_bucket_set(unit, port, cosq, min_quantum,
   5858                                    max_quantum, min_quantum, 
   5859                                    burst_quantum, flags);
   5860 }
   5861 
   5862 /*
   5863  * Function:
   5864  *     bcm_kt_cosq_bandwidth_get
   5865  * Purpose:
   5866  *     Get COS queue bandwidth control configuration
   5867  * Parameters:
   5868  *     unit          - (IN) unit number
   5869  *     port          - (IN) port number or GPORT identifier
   5870  *     cosq          - (IN) COS queue number
   5871  *     min_quantum   - (OUT)
   5872  *     max_quantum   - (OUT)
   5873  *     burst_quantum - (OUT)
   5874  *     flags         - (OUT)
   5875  * Returns:
   5876  *     BCM_E_XXX
   5877  * Notes:
   5878  *     If port is any form of local port, cosq is the hardware queue index.
   5879  */
   5880 int
   5881 bcm_kt_cosq_port_bandwidth_get(int unit, bcm_port_t port,
   5882                                bcm_cos_queue_t cosq,
   5883                                uint32 *min_quantum, uint32 *max_quantum,
   5884                                uint32 *burst_quantum, uint32 *flags)
   5885 {
   5886 
   5887     if (cosq < 0) {
   5888         return BCM_E_PARAM;
   5889     }
   5890 
   5891     BCM_IF_ERROR_RETURN(_bcm_kt_cosq_bucket_get(unit, port, cosq, min_quantum,
   5892                                                 max_quantum, burst_quantum,
   5893                                                 burst_quantum, *flags));
   5894     *flags = 0;
   5895 
   5896     return BCM_E_NONE;
   5897 }
   5898 
   5899 int
   5900 bcm_kt_cosq_port_pps_set(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   5901                          int pps)
   5902 {
   5903     uint32 min, max, burst_min, burst_max;
   5904 
   5905     if (!IS_CPU_PORT(unit, port)) {
   5906         return BCM_E_PORT;
   5907     } else if (cosq < 0 || cosq >= NUM_CPU_COSQ(unit)) {
   5908         return BCM_E_PARAM;
   5909     }
   5910 
   5911     BCM_IF_ERROR_RETURN
   5912         (_bcm_kt_cosq_bucket_get(unit, port, cosq, &min, &max, &burst_min,
   5913                                  &burst_max, _BCM_XGS_METER_FLAG_PACKET_MODE));
   5914 
   5915     return _bcm_kt_cosq_bucket_set(unit, port, cosq, min, pps, burst_min,
   5916                                    burst_max, _BCM_XGS_METER_FLAG_PACKET_MODE);
   5917 }
   5918 
   5919 int
   5920 bcm_kt_cosq_port_pps_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   5921                          int *pps)
   5922 {
   5923     uint32 min, max, burst_min, burst_max;
   5924 
   5925     if (!IS_CPU_PORT(unit, port)) {
   5926         return BCM_E_PORT;
   5927     } else if (cosq < 0 || cosq >= NUM_CPU_COSQ(unit)) {
   5928         return BCM_E_PARAM;
   5929     }
   5930 
   5931     BCM_IF_ERROR_RETURN
   5932         (_bcm_kt_cosq_bucket_get(unit, port, cosq, &min, &max, &burst_min,
   5933                                  &burst_max, _BCM_XGS_METER_FLAG_PACKET_MODE));
   5934     *pps = max;
   5935 
   5936     return BCM_E_NONE;
   5937 }
   5938 
   5939 int
   5940 bcm_kt_cosq_port_burst_set(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   5941                            int burst)
   5942 {
   5943     uint32 min, max, cur_burst_min, cur_burst_max;
   5944 
   5945     if (!IS_CPU_PORT(unit, port)) {
   5946         return BCM_E_PORT;
   5947     } else if (cosq < 0 || cosq >= NUM_CPU_COSQ(unit)) {
   5948         return BCM_E_PARAM;
   5949     }
   5950 
   5951     /* Get the current PPS and BURST settings */
   5952     BCM_IF_ERROR_RETURN
   5953         (_bcm_kt_cosq_bucket_get(unit, port, cosq, &min, &max, &cur_burst_min,
   5954                                  &cur_burst_max, _BCM_XGS_METER_FLAG_PACKET_MODE));
   5955 
   5956     /* Replace the current BURST setting, keep PPS the same */
   5957     return _bcm_kt_cosq_bucket_set(unit, port, cosq, min, max, cur_burst_min, burst,
   5958                                    _BCM_XGS_METER_FLAG_PACKET_MODE);
   5959 }
   5960 
   5961 int
   5962 bcm_kt_cosq_port_burst_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   5963                            int *burst)
   5964 {
   5965     uint32 min, max, cur_burst_min, cur_burst_max;
   5966 
   5967     if (!IS_CPU_PORT(unit, port)) {
   5968         return BCM_E_PORT;
   5969     } else if (cosq < 0 || cosq >= NUM_CPU_COSQ(unit)) {
   5970         return BCM_E_PARAM;
   5971     }
   5972 
   5973     BCM_IF_ERROR_RETURN
   5974         (_bcm_kt_cosq_bucket_get(unit, port, cosq, &min, &max, &cur_burst_min,
   5975                                  &cur_burst_max, _BCM_XGS_METER_FLAG_PACKET_MODE));
   5976     *burst = cur_burst_max;
   5977 
   5978     return BCM_E_NONE;
   5979 }
   5980 
   5981 /*
   5982  * Function:
   5983  *     bcm_kt_cosq_gport_sched_set
   5984  * Purpose:
   5985  *     Configure COS queue scheduler setting
   5986  * Parameters:
   5987  *      unit   - (IN) unit number
   5988  *      gport  - (IN) GPORT identifier
   5989  *      cosq   - (IN) COS queue to configure, -1 for all COS queues
   5990  *      mode   - (IN) Scheduling mode, one of BCM_COSQ_xxx
   5991  *      weight - (IN) queue weight
   5992  * Returns:
   5993  *      BCM_E_XXX
   5994  */
   5995 int
   5996 bcm_kt_cosq_gport_sched_set(int unit, bcm_gport_t gport,
   5997                             bcm_cos_queue_t cosq, int mode, int weight)
   5998 {
   5999     int rv, numq, i, count;
   6000 
   6001     if (cosq == -1) {
   6002         BCM_IF_ERROR_RETURN
   6003             (_bcm_kt_cosq_index_resolve(unit, gport, cosq,
   6004                                         _BCM_KT_COSQ_INDEX_STYLE_SCHEDULER,
   6005                                         NULL, NULL, &numq));
   6006         cosq = 0;
   6007     } else {
   6008         numq = 1;
   6009     }
   6010 
   6011     count = 0;
   6012     for (i = 0; i < numq; i++) {
   6013         rv = _bcm_kt_cosq_sched_set(unit, gport, cosq + i, mode, 1, &weight);
   6014         if (rv == BCM_E_NOT_FOUND) {
   6015             continue;
   6016         } else if (BCM_FAILURE(rv)) {
   6017             return rv;
   6018         } else {
   6019             count++;
   6020         }
   6021     }
   6022 
   6023     return count > 0 ? BCM_E_NONE : BCM_E_NOT_FOUND;
   6024 }
   6025 
   6026 /*
   6027  * Function:
   6028  *     bcm_kt_cosq_gport_sched_get
   6029  * Purpose:
   6030  *     Get COS queue scheduler setting
   6031  * Parameters:
   6032  *     unit   - (IN) unit number
   6033  *     gport  - (IN) GPORT identifier
   6034  *     cosq   - (IN) COS queue to get, -1 for any queue
   6035  *     mode   - (OUT) Scheduling mode, one of BCM_COSQ_xxx
   6036  *     weight - (OUT) queue weight
   6037  * Returns:
   6038  *     BCM_E_XXX
   6039  */
   6040 int
   6041 bcm_kt_cosq_gport_sched_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
   6042                             int *mode, int *weight)
   6043 {
   6044     int rv, numq, i;
   6045 
   6046     if (cosq == -1) {
   6047         BCM_IF_ERROR_RETURN
   6048             (_bcm_kt_cosq_index_resolve(unit, gport, cosq,
   6049                                         _BCM_KT_COSQ_INDEX_STYLE_SCHEDULER,
   6050                                         NULL, NULL, &numq));
   6051         cosq = 0;
   6052     } else {
   6053         numq = 1;
   6054     }
   6055 
   6056     for (i = 0; i < numq; i++) {
   6057         rv = _bcm_kt_cosq_sched_get(unit, gport, cosq + i, mode, 1, weight);
   6058         if (rv == BCM_E_NOT_FOUND) {
   6059             continue;
   6060         } else {
   6061             return rv;
   6062         }
   6063     }
   6064 
   6065     return BCM_E_NOT_FOUND;
   6066 }
   6067 
   6068 /*
   6069  * Function:
   6070  *     bcm_kt_cosq_gport_bandwidth_set
   6071  * Purpose:
   6072  *     Configure COS queue bandwidth control
   6073  * Parameters:
   6074  *     unit   - (IN) unit number
   6075  *     gport  - (IN) GPORT identifier
   6076  *     cosq   - (IN) COS queue to configure, -1 for all COS queues
   6077  *     kbits_sec_min - (IN) minimum bandwidth, kbits/sec
   6078  *     kbits_sec_max - (IN) maximum bandwidth, kbits/sec
   6079  *     flags  - (IN) BCM_COSQ_BW_*
   6080  * Returns:
   6081  *     BCM_E_XXX
   6082  */
   6083 int
   6084 bcm_kt_cosq_gport_bandwidth_set(int unit, bcm_gport_t gport,
   6085                                 bcm_cos_queue_t cosq, uint32 kbits_sec_min,
   6086                                 uint32 kbits_sec_max, uint32 flags)
   6087 {
   6088     int numq, i;
   6089 
   6090     if (cosq == -1) {
   6091         BCM_IF_ERROR_RETURN
   6092             (_bcm_kt_cosq_index_resolve(unit, gport, cosq,
   6093                                         _BCM_KT_COSQ_INDEX_STYLE_BUCKET,
   6094                                         NULL, NULL, &numq));
   6095         cosq = 0;
   6096     } else {
   6097         numq = 1;
   6098     }
   6099 
   6100     for (i = 0; i < numq; i++) {
   6101         if (!soc_feature(unit, soc_feature_dynamic_sched_update)) {  
   6102             BCM_IF_ERROR_RETURN
   6103                 (_bcm_kt_cosq_bucket_set(unit, gport, cosq + i, kbits_sec_min,
   6104                                           kbits_sec_max, kbits_sec_min,
   6105                                           kbits_sec_max, flags));
   6106         } else {
   6107             BCM_IF_ERROR_RETURN
   6108                 (_bcm_kt_cosq_dynamic_bucket_set(unit, gport, cosq + i, 
   6109                                           kbits_sec_min,
   6110                                           kbits_sec_max, kbits_sec_min,
   6111                                           kbits_sec_max, flags));
   6112         }
   6113     }
   6114 
   6115     return BCM_E_NONE;
   6116 }
   6117 
   6118 /*
   6119  * Function:
   6120  *     bcm_kt_cosq_gport_bandwidth_get
   6121  * Purpose:
   6122  *     Get COS queue bandwidth control configuration
   6123  * Parameters:
   6124  *     unit   - (IN) unit number
   6125  *     gport  - (IN) GPORT identifier
   6126  *     cosq   - (IN) COS queue to get, -1 for any COS queue
   6127  *     kbits_sec_min - (OUT) minimum bandwidth, kbits/sec
   6128  *     kbits_sec_max - (OUT) maximum bandwidth, kbits/sec
   6129  *     flags  - (OUT) BCM_COSQ_BW_*
   6130  * Returns:
   6131  *     BCM_E_XXX
   6132  */
   6133 int
   6134 bcm_kt_cosq_gport_bandwidth_get(int unit, bcm_gport_t gport,
   6135                                 bcm_cos_queue_t cosq, uint32 *kbits_sec_min,
   6136                                 uint32 *kbits_sec_max, uint32 *flags)
   6137 {
   6138     uint32 burst_min, burst_max;
   6139 
   6140     if (!soc_feature(unit, soc_feature_dynamic_sched_update)) {
   6141         BCM_IF_ERROR_RETURN
   6142             (_bcm_kt_cosq_bucket_get(unit, gport, cosq == -1 ? 0 : cosq,
   6143                                      kbits_sec_min, kbits_sec_max,
   6144                                     &burst_min, &burst_max, *flags));
   6145     } else {
   6146         BCM_IF_ERROR_RETURN
   6147             (_bcm_kt_cosq_dynamic_bucket_get(unit, gport, cosq == -1 ? 0 : cosq,
   6148                                      kbits_sec_min, kbits_sec_max,
   6149                                     &burst_min, &burst_max, *flags));    
   6150     }
   6151     
   6152     *flags = 0;
   6153 
   6154     return BCM_E_NONE;
   6155 }
   6156 
   6157 /*
   6158  * Function:
   6159  *     bcm_kt_cosq_gport_child_node_bandwidth_set
   6160  * Purpose:
   6161  *     Configure COS queue bandwidth control
   6162  * Parameters:
   6163  *     unit   - (IN) unit number
   6164  *     gport  - (IN) GPORT identifier
   6165  *     cosq   - (IN) COS queue to configure, -1 for all COS queues
   6166  *     kbits_sec_min - (IN) minimum bandwidth, kbits/sec
   6167  *     kbits_sec_max - (IN) maximum bandwidth, kbits/sec
   6168  *     flags  - (IN) BCM_COSQ_BW_*
   6169  * Returns:
   6170  *     BCM_E_XXX
   6171  */
   6172 int
   6173 bcm_kt_cosq_gport_child_node_bandwidth_set(int unit,
   6174                                 bcm_gport_t gport, bcm_cos_queue_t cosq,
   6175                                 uint32 kbits_sec_min, uint32 kbits_sec_max,
   6176                                 uint32 flags)
   6177 {
   6178     _bcm_kt_cosq_node_t *node = NULL;
   6179     _bcm_kt_cosq_node_t *cur_node = NULL;
   6180     bcm_gport_t cur_gport;
   6181     int start_cos;
   6182     int end_cos;
   6183     int numq, i;
   6184     uint32 temp_kbits_sec_min = 0;
   6185     uint32 temp_kbits_sec_max = 0;
   6186     uint32 kbits_sec_burst_min = 0;
   6187     uint32 kbits_sec_burst_max = 0;
   6188 
   6189     cur_gport = gport;
   6190     if (cosq == -1) {
   6191         BCM_IF_ERROR_RETURN
   6192             (_bcm_kt_cosq_index_resolve(unit, gport, cosq,
   6193                                         _BCM_KT_COSQ_INDEX_STYLE_BUCKET,
   6194                                         NULL, NULL, &numq));
   6195         start_cos = 0;
   6196         end_cos = numq - 1;
   6197 
   6198     } else {
   6199         start_cos = end_cos = cosq;
   6200     }
   6201 
   6202     if ((BCM_GPORT_IS_SET(gport)) &&
   6203         (BCM_GPORT_IS_SCHEDULER(gport))) {
   6204         BCM_IF_ERROR_RETURN
   6205             (_bcm_kt_cosq_node_get(unit, gport, NULL, NULL, NULL, &node));
   6206     }
   6207 
   6208     if (node) {
   6209         /* For Port gport, L0, L1 scheduler nodes */
   6210         if (cosq >= node->numq) {
   6211             return BCM_E_PARAM;
   6212         }
   6213         for (i = 0, cur_node = node->child; cur_node; 
   6214              cur_node = cur_node->sibling, i++) {
   6215             
   6216              /* get the child node at cosq */
   6217              if ((cosq != -1) && (cur_node->cosq_attached_to != cosq)) {
   6218                  continue;
   6219              }
   6220              cur_gport = cur_node->gport;
   6221              BCM_IF_ERROR_RETURN
   6222                 (_bcm_kt_cosq_bucket_get(unit, cur_gport,
   6223                                      cur_node->cosq_attached_to,
   6224                                      &temp_kbits_sec_min,
   6225                                      &temp_kbits_sec_max,
   6226                                      &kbits_sec_burst_min,
   6227                                      &kbits_sec_burst_max, 0));
   6228              if (kbits_sec_burst_min || kbits_sec_burst_max) {
   6229                  flags = _BCM_XGS_METER_FLAG_NON_BURST_CORRECTION;
   6230              }
   6231              BCM_IF_ERROR_RETURN
   6232               (_bcm_kt_cosq_bucket_set(unit, cur_gport,
   6233                             cur_node->cosq_attached_to, kbits_sec_min,
   6234                             kbits_sec_max, kbits_sec_burst_min,
   6235                             kbits_sec_burst_max, flags));
   6236         }
   6237     } else {
   6238         /* For Port and L2 queues */
   6239         for (i = start_cos; i <= end_cos; i++) {
   6240              BCM_IF_ERROR_RETURN
   6241                 (_bcm_kt_cosq_bucket_get(unit, cur_gport, i,
   6242                                      &temp_kbits_sec_min,
   6243                                      &temp_kbits_sec_max,
   6244                                      &kbits_sec_burst_min,
   6245                                      &kbits_sec_burst_max, 0));
   6246 
   6247             if (kbits_sec_burst_min || kbits_sec_burst_max) {
   6248                 flags = _BCM_XGS_METER_FLAG_NON_BURST_CORRECTION;
   6249             }
   6250             BCM_IF_ERROR_RETURN
   6251                 (_bcm_kt_cosq_bucket_set(unit, cur_gport,
   6252                                           i, kbits_sec_min,
   6253                                           kbits_sec_max,
   6254                                           kbits_sec_burst_min,
   6255                                           kbits_sec_burst_max, flags));
   6256         }
   6257     }
   6258 
   6259     return BCM_E_NONE;
   6260 }
   6261 
   6262 /*
   6263  * Function:
   6264  *     bcm_kt_cosq_gport_child_node_bandwidth_get
   6265  * Purpose:
   6266  *     Get COS queue bandwidth control configuration
   6267  * Parameters:
   6268  *     unit   - (IN) unit number
   6269  *     gport  - (IN) GPORT identifier
   6270  *     cosq   - (IN) COS queue to get, -1 for any COS queue
   6271  *     kbits_sec_min - (OUT) minimum bandwidth, kbits/sec
   6272  *     kbits_sec_max - (OUT) maximum bandwidth, kbits/sec
   6273  *     flags  - (OUT) BCM_COSQ_BW_*
   6274  * Returns:
   6275  *     BCM_E_XXX
   6276  */
   6277 int
   6278 bcm_kt_cosq_gport_child_node_bandwidth_get(int unit, bcm_gport_t gport,
   6279                                 bcm_cos_queue_t cosq, uint32 *kbits_sec_min,
   6280                                 uint32 *kbits_sec_max, uint32 *flags)
   6281 {
   6282     uint32 burst_min, burst_max;
   6283     _bcm_kt_cosq_node_t *node = NULL;
   6284     _bcm_kt_cosq_node_t *cur_node = NULL;
   6285     bcm_gport_t cur_gport;
   6286     int i;
   6287 
   6288     i = (cosq == -1) ? 0 : cosq;
   6289     cur_gport = gport;
   6290     if ((BCM_GPORT_IS_SET(gport)) &&
   6291         (BCM_GPORT_IS_SCHEDULER(gport))) {
   6292         /* get the child node at cosq*/
   6293         BCM_IF_ERROR_RETURN
   6294             (_bcm_kt_cosq_node_get(unit, gport, NULL, NULL, NULL, &node));
   6295         if (node != NULL) {
   6296             if (cosq >= node->numq) { 
   6297                 return BCM_E_PARAM; 
   6298             }
   6299             /* resolve the child attached to input cosq */
   6300             BCM_IF_ERROR_RETURN(
   6301                _bcm_kt_cosq_child_node_at_input(node, i, &cur_node));
   6302             cur_gport = cur_node->gport;
   6303 
   6304         } else {
   6305             return BCM_E_PARAM;
   6306         }
   6307     }
   6308     BCM_IF_ERROR_RETURN
   6309         (_bcm_kt_cosq_bucket_get(unit, cur_gport, i,
   6310                                   kbits_sec_min, kbits_sec_max,
   6311                                   &burst_min, &burst_max, *flags));
   6312     *flags = 0;
   6313     return BCM_E_NONE;
   6314 }
   6315 
   6316 /*
   6317  * Function:
   6318  *     bcm_kt_cosq_gport_bandwidth_burst_set
   6319  * Purpose:
   6320  *     Configure COS queue bandwidth burst setting
   6321  * Parameters:
   6322  *      unit        - (IN) unit number
   6323  *      gport       - (IN) GPORT identifier
   6324  *      cosq        - (IN) COS queue to configure, -1 for all COS queues
   6325  *      kbits_burst - (IN) maximum burst, kbits
   6326  * Returns:
   6327  *      BCM_E_XXX
   6328  */
   6329 int
   6330 bcm_kt_cosq_gport_bandwidth_burst_set(int unit, bcm_gport_t gport,
   6331                                       bcm_cos_queue_t cosq,
   6332                                       uint32 kbits_burst_min,
   6333                                       uint32 kbits_burst_max)
   6334 {
   6335     int numq, i;
   6336     uint32 kbits_sec_min, kbits_sec_max;
   6337     uint32 kbits_sec_burst_min, kbits_sec_burst_max;
   6338 
   6339     if (cosq == -1) {
   6340         BCM_IF_ERROR_RETURN
   6341             (_bcm_kt_cosq_index_resolve(unit, gport, cosq,
   6342                                         _BCM_KT_COSQ_INDEX_STYLE_BUCKET,
   6343                                         NULL, NULL, &numq));
   6344         cosq = 0;
   6345     } else {
   6346         numq = 1;
   6347     }
   6348 
   6349     for (i = 0; i < numq; i++) {
   6350         BCM_IF_ERROR_RETURN
   6351             (_bcm_kt_cosq_bucket_get(unit, gport, cosq + i, &kbits_sec_min,
   6352                                      &kbits_sec_max, &kbits_sec_burst_min, 
   6353                                      &kbits_sec_burst_max, 0));
   6354         BCM_IF_ERROR_RETURN
   6355             (_bcm_kt_cosq_bucket_set(unit, gport, cosq + i, kbits_sec_min,
   6356                                      kbits_sec_max, kbits_burst_min, 
   6357                                      kbits_burst_max, 
   6358                                      _BCM_XGS_METER_FLAG_NON_BURST_CORRECTION));
   6359     }
   6360 
   6361     return BCM_E_NONE;
   6362 }
   6363 
   6364 /*
   6365  * Function:
   6366  *     bcm_kt_cosq_gport_bandwidth_burst_get
   6367  * Purpose:
   6368  *     Get COS queue bandwidth burst setting
   6369  * Parameters:
   6370  *     unit        - (IN) unit number
   6371  *     gport       - (IN) GPORT identifier
   6372  *     cosq        - (IN) COS queue to get, -1 for any queue
   6373  *     kbits_burst - (OUT) maximum burst, kbits
   6374  * Returns:
   6375  *     BCM_E_XXX
   6376  */
   6377 int
   6378 bcm_kt_cosq_gport_bandwidth_burst_get(int unit, bcm_gport_t gport,
   6379                                        bcm_cos_queue_t cosq,
   6380                                        uint32 *kbits_burst_min,
   6381                                        uint32 *kbits_burst_max)
   6382 {
   6383     uint32 kbits_sec_min, kbits_sec_max;
   6384 
   6385     BCM_IF_ERROR_RETURN
   6386         (_bcm_kt_cosq_bucket_get(unit, gport, cosq == -1 ? 0 : cosq,
   6387                                  &kbits_sec_min, &kbits_sec_max, 
   6388                                  kbits_burst_min, kbits_burst_max, 0));
   6389 
   6390     return BCM_E_NONE;
   6391 }
   6392 
   6393 /*
   6394  * Function:
   6395  *     bcm_kt_cosq_gport_discard_set
   6396  * Purpose:
   6397  *     Configure gport WRED setting
   6398  * Parameters:
   6399  *     unit    - (IN) unit number
   6400  *     port    - (IN) GPORT identifier
   6401  *     cosq    - (IN) COS queue to configure, -1 for all COS queues
   6402  *     discard - (IN) discard settings
   6403  * Returns:
   6404  *     BCM_E_XXX
   6405  */
   6406 int
   6407 bcm_kt_cosq_gport_discard_set(int unit, bcm_gport_t gport,
   6408                                bcm_cos_queue_t cosq,
   6409                                bcm_cosq_gport_discard_t *discard)
   6410 {
   6411     int numq, i;
   6412     uint32 min_thresh, max_thresh;
   6413     int cell_size, cell_field_max;
   6414     bcm_port_t local_port;
   6415 
   6416     if (discard == NULL ||
   6417         discard->gain < 0 || discard->gain > 15 ||
   6418         discard->drop_probability < 0 || discard->drop_probability > 100) {
   6419         return BCM_E_PARAM;
   6420     }
   6421 
   6422     if (cosq < -1) {
   6423         return BCM_E_PARAM;
   6424     }
   6425 
   6426     cell_size = _BCM_KT_COSQ_CELLSIZE;
   6427     if (gport != -1) {
   6428         
   6429     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
   6430         BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport) || 
   6431         BCM_GPORT_IS_SCHEDULER(gport)) {
   6432         BCM_IF_ERROR_RETURN
   6433             (_bcm_kt_cosq_node_get(unit, gport, NULL, &local_port,NULL,
   6434                                    NULL));
   6435     } else {
   6436         BCM_IF_ERROR_RETURN
   6437             (_bcm_kt_cosq_localport_resolve(unit, gport, &local_port));
   6438     }
   6439     if (IS_EXT_MEM_PORT(unit, local_port)) {
   6440         cell_size = _BCM_KT_COSQ_EXT_CELLSIZE;
   6441     }    
   6442    }
   6443  
   6444 
   6445     cell_field_max = KT_CELL_FIELD_MAX;
   6446 
   6447     min_thresh = discard->min_thresh;
   6448     max_thresh = discard->max_thresh;
   6449     if (discard->flags & BCM_COSQ_DISCARD_BYTES) {
   6450         /* Convert bytes to cells */
   6451         min_thresh += (cell_size - 1);
   6452         min_thresh /= cell_size;
   6453 
   6454         max_thresh += (cell_size - 1);
   6455         max_thresh /= cell_size;
   6456 
   6457         if ((min_thresh > cell_field_max) ||
   6458             (max_thresh > cell_field_max)) {
   6459             return BCM_E_PARAM;
   6460         }
   6461     } else { /* BCM_COSQ_DISCARD_PACKETS */
   6462         if ((min_thresh > KT_CELL_FIELD_MAX) ||
   6463             (max_thresh > KT_CELL_FIELD_MAX)) {
   6464             return BCM_E_PARAM;
   6465         }
   6466     }
   6467 
   6468     if (cosq == -1) {
   6469         BCM_IF_ERROR_RETURN
   6470             (_bcm_kt_cosq_index_resolve(unit, gport, cosq,
   6471                                         _BCM_KT_COSQ_INDEX_STYLE_WRED,
   6472                                         NULL, NULL, &numq));
   6473         cosq = 0;
   6474     } else {
   6475         numq = 1;
   6476     }
   6477 
   6478     for (i = 0; i < numq; i++) {
   6479         BCM_IF_ERROR_RETURN
   6480             (_bcm_kt_cosq_wred_set(unit, gport, cosq + i, discard->flags,
   6481                                    min_thresh, max_thresh,
   6482                                    discard->drop_probability, discard->gain,
   6483                                    FALSE));
   6484     }
   6485 
   6486     return BCM_E_NONE;
   6487 }
   6488 
   6489 /*
   6490  * Function:
   6491  *     bcm_kt_cosq_gport_discard_get
   6492  * Purpose:
   6493  *     Get port WRED setting
   6494  * Parameters:
   6495  *     unit    - (IN) unit number
   6496  *     port    - (IN) GPORT identifier
   6497  *     cosq    - (IN) COS queue to get, -1 for any queue
   6498  *     discard - (OUT) discard settings
   6499  * Returns:
   6500  *     BCM_E_XXX
   6501  */
   6502 int
   6503 bcm_kt_cosq_gport_discard_get(int unit, bcm_gport_t gport,
   6504                               bcm_cos_queue_t cosq,
   6505                               bcm_cosq_gport_discard_t *discard)
   6506 {
   6507     uint32 min_thresh, max_thresh;
   6508     int cell_size;
   6509     bcm_port_t local_port;
   6510     
   6511     if (discard == NULL) {
   6512         return BCM_E_PARAM;
   6513     }
   6514 
   6515     if (cosq < -1) {
   6516         return BCM_E_PARAM;
   6517     }
   6518 
   6519     BCM_IF_ERROR_RETURN
   6520         (_bcm_kt_cosq_wred_get(unit, gport, cosq == -1 ? 0 : cosq,
   6521                                &discard->flags, &min_thresh, &max_thresh,
   6522                                &discard->drop_probability, &discard->gain));
   6523     
   6524     cell_size = _BCM_KT_COSQ_CELLSIZE;
   6525     if (gport != -1) {
   6526         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
   6527             BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport) ||
   6528             BCM_GPORT_IS_SCHEDULER(gport)) {
   6529                 BCM_IF_ERROR_RETURN
   6530                 (_bcm_kt_cosq_node_get(unit, gport, NULL, &local_port,NULL,
   6531                                    NULL));
   6532     } else {
   6533 
   6534         BCM_IF_ERROR_RETURN
   6535             (_bcm_kt_cosq_localport_resolve(unit, gport, &local_port));
   6536     }
   6537     if (IS_EXT_MEM_PORT(unit, local_port)) {
   6538         cell_size = _BCM_KT_COSQ_EXT_CELLSIZE;
   6539     }   
   6540     }
   6541     /* Convert number of cells to number of bytes */
   6542     if (discard->flags & BCM_COSQ_DISCARD_BYTES) {
   6543         discard->min_thresh = min_thresh * cell_size;
   6544         discard->max_thresh = max_thresh * cell_size;
   6545     } else {
   6546         discard->min_thresh = min_thresh;
   6547         discard->max_thresh = max_thresh;
   6548     }
   6549 
   6550     return BCM_E_NONE;
   6551 }
   6552 
   6553 /*
   6554  * Function:
   6555  *     bcm_kt_cosq_discard_set
   6556  * Purpose:
   6557  *     Get port WRED setting
   6558  * Parameters:
   6559  *     unit    - (IN) unit number
   6560  *     flags   - (IN) flags
   6561  * Returns:
   6562  *     BCM_E_XXX
   6563  */
   6564 int
   6565 bcm_kt_cosq_discard_set(int unit, uint32 flags)
   6566 {
   6567     bcm_port_t port;
   6568     bcm_cos_queue_t cosq;
   6569     int numq;
   6570 
   6571     if (flags & ~(BCM_COSQ_DISCARD_DEVICE |
   6572                   BCM_COSQ_DISCARD_NONTCP |
   6573                   BCM_COSQ_DISCARD_COLOR_ALL |
   6574                   BCM_COSQ_DISCARD_PACKETS |
   6575                   BCM_COSQ_DISCARD_CAP_AVERAGE |
   6576                   BCM_COSQ_DISCARD_ENABLE |
   6577                   BCM_COSQ_DISCARD_MARK_CONGESTION)) {
   6578         return BCM_E_PARAM;
   6579     }
   6580 
   6581     flags &= ~(BCM_COSQ_DISCARD_NONTCP | BCM_COSQ_DISCARD_COLOR_ALL);
   6582 
   6583     PBMP_PORT_ITER(unit, port) {
   6584         BCM_IF_ERROR_RETURN
   6585             (_bcm_kt_cosq_index_resolve(unit, port, -1,
   6586                                         _BCM_KT_COSQ_INDEX_STYLE_WRED, NULL,
   6587                                         NULL, &numq));
   6588         for (cosq = 0; cosq < numq; cosq++) {
   6589             BCM_IF_ERROR_RETURN
   6590                 (_bcm_kt_cosq_wred_set(unit, port, cosq, flags, 0, 0, 0, 0,
   6591                                        FALSE));
   6592         }
   6593     }
   6594 
   6595     return BCM_E_NONE;
   6596 
   6597 }
   6598 
   6599 /*
   6600  * Function:
   6601  *     bcm_kt_cosq_discard_get
   6602  * Purpose:
   6603  *     Get port WRED setting
   6604  * Parameters:
   6605  *     unit    - (IN) unit number
   6606  *     flags   - (OUT) flags
   6607  * Returns:
   6608  *     BCM_E_XXX
   6609  */
   6610 int
   6611 bcm_kt_cosq_discard_get(int unit, uint32 *flags)
   6612 {
   6613     bcm_port_t port;
   6614 
   6615     PBMP_PORT_ITER(unit, port) {
   6616         *flags = 0;
   6617         /* use setting from hardware cosq index 0 of the first port */
   6618         return _bcm_kt_cosq_wred_get(unit, port, 0, flags, NULL, NULL, NULL,
   6619                                      NULL);
   6620     }
   6621 
   6622     return BCM_E_NOT_FOUND;
   6623 
   6624 }
   6625 
   6626 /*
   6627  * Function:
   6628  *     bcm_kt_cosq_discard_port_set
   6629  * Purpose:
   6630  *     Configure port WRED setting
   6631  * Parameters:
   6632  *     unit          - (IN) unit number
   6633  *     port          - (IN) port number or GPORT identifier
   6634  *     cosq          - (IN) COS queue number
   6635  *     color         - (IN)
   6636  *     drop_start    - (IN)
   6637  *     drop_slot     - (IN)
   6638  *     average_time  - (IN)
   6639  * Returns:
   6640  *     BCM_E_XXX
   6641  * Notes:
   6642  *     If port is any form of local port, cosq is the hardware queue index.
   6643  */
   6644 int
   6645 bcm_kt_cosq_discard_port_set(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   6646                              uint32 color, int drop_start, int drop_slope,
   6647                              int average_time)
   6648 {
   6649     return SOC_E_UNAVAIL;
   6650 }
   6651 
   6652 /*
   6653  * Function:
   6654  *     bcm_kt_cosq_discard_port_get
   6655  * Purpose:
   6656  *     Get port WRED setting
   6657  * Parameters:
   6658  *     unit          - (IN) unit number
   6659  *     port          - (IN) port number or GPORT identifier
   6660  *     cosq          - (IN) COS queue number
   6661  *     color         - (OUT)
   6662  *     drop_start    - (OUT)
   6663  *     drop_slot     - (OUT)
   6664  *     average_time  - (OUT)
   6665  * Returns:
   6666  *     BCM_E_XXX
   6667  * Notes:
   6668  *     If port is any form of local port, cosq is the hardware queue index.
   6669  */
   6670 int
   6671 bcm_kt_cosq_discard_port_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   6672                              uint32 color, int *drop_start, int *drop_slope,
   6673                              int *average_time)
   6674 {
   6675     return SOC_E_UNAVAIL;
   6676 }
   6677 
   6678 int
   6679 bcm_kt_cosq_stat_set(int unit, bcm_gport_t port, bcm_cos_queue_t cosq,
   6680                      bcm_cosq_stat_t stat, uint64 value)
   6681 {
   6682     bcm_port_t local_port;
   6683     int startq, numq, i;
   6684     _bcm_kt_mmu_info_t *mmu_info;
   6685     soc_counter_non_dma_id_t dma_id;
   6686     _bcm_kt_cosq_node_t *node = NULL;
   6687     _bcm_kt_cosq_node_t *child_node = NULL;
   6688     int first_child = 1; 
   6689     uint64  value64;
   6690     uint64 zero;
   6691 
   6692     BCM_IF_ERROR_RETURN
   6693         (_bcm_kt_cosq_index_resolve
   6694         (unit, port, cosq, _BCM_KT_COSQ_INDEX_STYLE_UCAST_QUEUE,
   6695          &local_port, &startq, &numq));
   6696 
   6697     mmu_info = _bcm_kt_mmu_info[unit];
   6698     if (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port) ||
   6699         startq >= mmu_info->num_base_queues) {
   6700         /* pass port as queue number */
   6701         local_port = startq;
   6702         startq = 0;
   6703     }
   6704 
   6705     switch (stat) {
   6706     case bcmCosqStatDroppedPackets:
   6707         dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_PKT;
   6708         break;
   6709     case bcmCosqStatDroppedBytes:
   6710         dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE;
   6711         break;
   6712     case bcmCosqStatRedCongestionDroppedPackets:
   6713         dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_RED;
   6714         break;
   6715     case bcmCosqStatOutPackets:
   6716         dma_id = SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT;
   6717         break;
   6718     case bcmCosqStatOutBytes:
   6719         dma_id = SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE; 
   6720         break;
   6721     default:
   6722         return BCM_E_PARAM;
   6723     }
   6724 
   6725     if (!BCM_GPORT_IS_SCHEDULER(port)) {
   6726         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
   6727             BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port) ||
   6728             BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) ||
   6729             BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(port) ||
   6730             (cosq != BCM_COS_INVALID)) {
   6731             BCM_IF_ERROR_RETURN
   6732                 (soc_counter_set(unit, local_port, dma_id, startq, value));
   6733         } else {
   6734             numq = soc_property_get(unit, spn_BCM_NUM_COS, BCM_COS_DEFAULT);
   6735             if (numq < 1) {
   6736                 numq = 1;
   6737             } else if (numq > 8) {
   6738                 numq = 8;
   6739             }
   6740             for (i = 0; i < numq; i++) {
   6741                 COMPILER_64_ZERO(zero);
   6742                 SOC_IF_ERROR_RETURN
   6743                     (soc_counter_set(unit, local_port, dma_id, i, i == 0 ? value : zero));
   6744             }
   6745         }
   6746     } else {
   6747        BCM_IF_ERROR_RETURN
   6748                (_bcm_kt_cosq_node_get(unit, port, 0,
   6749                               &local_port, NULL, &node));
   6750              if (cosq == -1) {  
   6751                  for (i = 0; i < node->numq; i++) {
   6752                       if ((_bcm_kt_cosq_child_node_at_input(node, i, &child_node))
   6753                                                            == BCM_E_NOT_FOUND) {
   6754                            continue;
   6755                        }
   6756                        port = child_node->gport;
   6757                        BCM_IF_ERROR_RETURN
   6758                        (_bcm_kt_cosq_index_resolve
   6759                        (unit, port, 0, _BCM_KT_COSQ_INDEX_STYLE_UCAST_QUEUE,
   6760                         &local_port, &startq, &numq));
   6761        
   6762                         if (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port) ||
   6763                             startq >= mmu_info->num_base_queues) {
   6764                             /* pass port as queue number */
   6765                             local_port = startq;
   6766                             startq = 0;
   6767                         }
   6768                         if (first_child) {
   6769                         /*
   6770                          *According to api guide only first child should be set with given value
   6771                          *all other are set to 0
   6772                          */
   6773                           BCM_IF_ERROR_RETURN
   6774                           (soc_counter_set(unit, local_port, dma_id,
   6775                                      startq , value));
   6776                            first_child = 0;
   6777                          }
   6778                         else {
   6779                           COMPILER_64_ZERO(value64);
   6780                           BCM_IF_ERROR_RETURN
   6781                           (soc_counter_set(unit, local_port, dma_id,
   6782                                       startq , value64));
   6783                          }
   6784                    }
   6785               }
   6786               else { 
   6787                     if ((_bcm_kt_cosq_child_node_at_input(node, cosq, &child_node))
   6788                                                           == BCM_E_NOT_FOUND) {
   6789                         return BCM_E_NOT_FOUND;  
   6790                     }
   6791                     port = child_node->gport;
   6792                     BCM_IF_ERROR_RETURN
   6793                     (_bcm_kt_cosq_index_resolve
   6794                       (unit, port, 0, _BCM_KT_COSQ_INDEX_STYLE_UCAST_QUEUE,
   6795                        &local_port, &startq, &numq));
   6796        
   6797                     if (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port) ||
   6798                         startq >= mmu_info->num_base_queues) {
   6799                          /* pass port as queue number */
   6800                          local_port = startq;
   6801                          startq = 0;
   6802                     }
   6803                     BCM_IF_ERROR_RETURN
   6804                     (soc_counter_set(unit, local_port, dma_id,
   6805                             startq , value));
   6806 
   6807              }
   6808        }
   6809 
   6810     return BCM_E_NONE;
   6811 }
   6812 
   6813 int
   6814 bcm_kt_cosq_stat_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   6815                      bcm_cosq_stat_t stat, int sync_mode, uint64 *value)
   6816 {
   6817     bcm_port_t local_port;
   6818     int startq, numq, i;
   6819     uint64 sum, value64;
   6820     _bcm_kt_mmu_info_t *mmu_info;
   6821     soc_counter_non_dma_id_t dma_id;
   6822      _bcm_kt_cosq_node_t *node = NULL;
   6823      _bcm_kt_cosq_node_t *child_node = NULL;
   6824     int (*counter_get) (int , soc_port_t , soc_reg_t , int , uint64 *);
   6825 
   6826     if (value == NULL) {
   6827         return BCM_E_PARAM;
   6828     }
   6829 
   6830     /*
   6831      * if sync-mode is set, update the software cached counter value, 
   6832      * with the hardware count and then retrieve the count.
   6833      * else return the software cache counter value.
   6834      */
   6835     counter_get = (sync_mode == 1)? soc_counter_sync_get: soc_counter_get;
   6836 
   6837 
   6838     BCM_IF_ERROR_RETURN
   6839         (_bcm_kt_cosq_index_resolve
   6840         (unit, port, cosq, _BCM_KT_COSQ_INDEX_STYLE_UCAST_QUEUE,
   6841          &local_port, &startq, &numq));
   6842 
   6843     mmu_info = _bcm_kt_mmu_info[unit];
   6844     if (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port) ||
   6845         startq >= mmu_info->num_base_queues) {
   6846         /* pass port as queue number */
   6847         local_port = startq;
   6848         startq = 0;
   6849     }
   6850 
   6851     switch (stat) {
   6852     case bcmCosqStatDroppedPackets:
   6853         dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_PKT;
   6854         break;
   6855     case bcmCosqStatDroppedBytes:
   6856         dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE;
   6857         break;
   6858     case bcmCosqStatRedCongestionDroppedPackets:
   6859         dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_RED;
   6860         break;
   6861     case bcmCosqStatOutPackets:
   6862         dma_id = SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT;
   6863         break;
   6864     case bcmCosqStatOutBytes:
   6865         dma_id = SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE;
   6866         break;
   6867     default:
   6868         return BCM_E_PARAM;
   6869     }
   6870 
   6871     if (!BCM_GPORT_IS_SCHEDULER(port)) {
   6872         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
   6873             BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port) ||
   6874             BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) ||
   6875             BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(port) ||
   6876             (cosq != BCM_COS_INVALID)) {
   6877             BCM_IF_ERROR_RETURN
   6878                 (counter_get(unit, local_port, dma_id, startq, value));
   6879         } else {
   6880             numq = soc_property_get(unit, spn_BCM_NUM_COS, BCM_COS_DEFAULT);
   6881             if (numq < 1) {
   6882                 numq = 1;
   6883             } else if (numq > 8) {
   6884                 numq = 8;
   6885             }
   6886             COMPILER_64_ZERO(sum);
   6887             COMPILER_64_ZERO(value64);
   6888             for (i = 0; i < numq; i++) {
   6889                 BCM_IF_ERROR_RETURN
   6890                     (counter_get(unit, local_port, dma_id, i, &value64));
   6891                 COMPILER_64_ADD_64(sum, value64);
   6892             }
   6893             *value = sum;
   6894         }
   6895     } else {
   6896         BCM_IF_ERROR_RETURN
   6897           (_bcm_kt_cosq_node_get(unit, port, 0,
   6898                     &local_port, NULL, &node));
   6899         COMPILER_64_ZERO(sum);
   6900         if (cosq ==-1) {  
   6901             for (i = 0; i < node->numq; i++) {
   6902                  if ((_bcm_kt_cosq_child_node_at_input(node, i, &child_node))
   6903                                                         == BCM_E_NOT_FOUND) {
   6904                       continue;
   6905                  }
   6906                  port = child_node->gport;
   6907      
   6908                  BCM_IF_ERROR_RETURN
   6909                    (_bcm_kt_cosq_index_resolve
   6910                    (unit, port, 0, _BCM_KT_COSQ_INDEX_STYLE_UCAST_QUEUE,
   6911                     &local_port, &startq, &numq));
   6912        
   6913                 if (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port) ||
   6914                     startq >= mmu_info->num_base_queues) {
   6915                     /* pass port as queue number */
   6916                     local_port = startq;
   6917                     startq = 0;
   6918                 }
   6919                 BCM_IF_ERROR_RETURN
   6920                 (counter_get(unit, local_port, dma_id,
   6921                             startq , &value64));
   6922                 COMPILER_64_ADD_64(sum, value64);
   6923 
   6924            }
   6925         }
   6926         else { 
   6927           if ((_bcm_kt_cosq_child_node_at_input(node, cosq, &child_node))
   6928                                                  == BCM_E_NOT_FOUND) {
   6929                return BCM_E_NOT_FOUND; 
   6930           }
   6931           port = child_node->gport;
   6932    
   6933           BCM_IF_ERROR_RETURN
   6934           (_bcm_kt_cosq_index_resolve
   6935               (unit, port, 0, _BCM_KT_COSQ_INDEX_STYLE_UCAST_QUEUE,
   6936                &local_port, &startq, &numq));
   6937       
   6938           if (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port) ||
   6939               startq >= mmu_info->num_base_queues) {
   6940               /* pass port as queue number */
   6941               local_port = startq;
   6942               startq = 0;
   6943           }
   6944           BCM_IF_ERROR_RETURN
   6945           (counter_get(unit, local_port, dma_id,
   6946                        startq , &value64));
   6947           COMPILER_64_ADD_64(sum, value64);
   6948         }
   6949 
   6950         *value = sum;
   6951     }
   6952 
   6953     return BCM_E_NONE;
   6954 }
   6955 
   6956 int
   6957 bcm_kt_cosq_gport_stat_set(int unit, bcm_gport_t port, bcm_cos_queue_t cosq,
   6958                                  bcm_cosq_gport_stats_t stat, uint64 value)
   6959 {
   6960     bcm_port_t local_port;
   6961     int startq, numq, i;
   6962     uint64  value64;
   6963     _bcm_kt_mmu_info_t *mmu_info;
   6964     soc_counter_non_dma_id_t dma_id;
   6965 
   6966     if (BCM_GPORT_IS_SCHEDULER(port) && cosq != BCM_COS_INVALID) {
   6967         return BCM_E_PARAM;
   6968     }
   6969 
   6970     BCM_IF_ERROR_RETURN
   6971         (_bcm_kt_cosq_index_resolve
   6972         (unit, port, cosq, _BCM_KT_COSQ_INDEX_STYLE_UCAST_QUEUE,
   6973          &local_port, &startq, &numq));
   6974 
   6975     mmu_info = _bcm_kt_mmu_info[unit];
   6976     if (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port) ||
   6977         startq >= mmu_info->num_base_queues) {
   6978         /* pass port as queue number */
   6979         local_port = startq;
   6980         startq = 0;
   6981     }
   6982 
   6983     switch (stat) {
   6984     case bcmCosqGportGreenAcceptedPkts:
   6985         dma_id = SOC_COUNTER_NON_DMA_COSQ_ACCEPT_PKT_GREEN;
   6986         break;
   6987     case bcmCosqGportGreenAcceptedBytes:
   6988         dma_id = SOC_COUNTER_NON_DMA_COSQ_ACCEPT_BYTE_GREEN;
   6989         break;
   6990     case bcmCosqGportYellowAcceptedPkts:
   6991         dma_id = SOC_COUNTER_NON_DMA_COSQ_ACCEPT_PKT_YELLOW;
   6992         break;
   6993     case bcmCosqGportYellowAcceptedBytes:
   6994         dma_id = SOC_COUNTER_NON_DMA_COSQ_ACCEPT_BYTE_YELLOW;
   6995         break;    
   6996     case bcmCosqGportRedAcceptedPkts:
   6997         dma_id = SOC_COUNTER_NON_DMA_COSQ_ACCEPT_PKT_RED;
   6998         break;
   6999     case bcmCosqGportRedAcceptedBytes:
   7000         dma_id = SOC_COUNTER_NON_DMA_COSQ_ACCEPT_BYTE_RED;
   7001         break;        
   7002     case bcmCosqGportReceivedPkts:
   7003         dma_id = SOC_COUNTER_NON_DMA_COSQ_ACCEPT_PKT;
   7004         break;
   7005     case bcmCosqGportReceivedBytes:
   7006         dma_id = SOC_COUNTER_NON_DMA_COSQ_ACCEPT_BYTE;
   7007         break;
   7008     case bcmCosqGportGreenDroppedPkts:
   7009         dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_GREEN;
   7010         break;
   7011     case bcmCosqGportGreenDroppedBytes:
   7012         dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE_GREEN;
   7013         break;    
   7014     case bcmCosqGportYellowDroppedPkts:
   7015         dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_YELLOW;
   7016         break;
   7017     case bcmCosqGportYellowDroppedBytes:
   7018         dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE_YELLOW;
   7019         break;    
   7020     case bcmCosqGportRedDroppedPkts:
   7021         dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_RED;
   7022         break;
   7023     case bcmCosqGportRedDroppedBytes:
   7024         dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE_RED;
   7025         break;    
   7026     case bcmCosqGportDroppedPkts:
   7027         dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_PKT;
   7028         break;
   7029     case bcmCosqGportDroppedBytes:
   7030         dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE;
   7031         break;
   7032     case bcmCosqGportOutPkts:
   7033         dma_id = SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT;
   7034         break;
   7035     case bcmCosqGportOutBytes:
   7036         dma_id = SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE;
   7037         break;    
   7038     default:
   7039         return BCM_E_PARAM;
   7040     }
   7041 
   7042     if (!BCM_GPORT_IS_SCHEDULER(port)) {      
   7043         BCM_IF_ERROR_RETURN
   7044              (soc_counter_set(unit, local_port, dma_id, startq, value));
   7045     } else {
   7046         COMPILER_64_ZERO(value64);
   7047         for (i = 0; i < numq; i++) {
   7048             BCM_IF_ERROR_RETURN
   7049                 (soc_counter_set(unit, local_port, dma_id, startq + i, 
   7050                                  value64));
   7051         }
   7052     }    
   7053 
   7054     return BCM_E_NONE;
   7055 }
   7056 
   7057 int
   7058 bcm_kt_cosq_gport_stat_get(int unit, int sync_mode, bcm_port_t port, 
   7059                            bcm_cos_queue_t cosq, bcm_cosq_gport_stats_t stat, 
   7060                            uint64 *value)
   7061 {
   7062     bcm_port_t local_port;
   7063     int startq, numq, i;
   7064     uint64 sum, value64;
   7065     _bcm_kt_mmu_info_t *mmu_info;
   7066     soc_counter_non_dma_id_t dma_id;
   7067     int (*counter_get) (int , soc_port_t , soc_reg_t , int , uint64 *);
   7068     
   7069     if (value == NULL) {
   7070         return BCM_E_PARAM;
   7071     }
   7072 
   7073     if (BCM_GPORT_IS_SCHEDULER(port) && cosq != BCM_COS_INVALID) {
   7074         return BCM_E_PARAM;
   7075     }    
   7076 
   7077     BCM_IF_ERROR_RETURN
   7078         (_bcm_kt_cosq_index_resolve
   7079         (unit, port, cosq, _BCM_KT_COSQ_INDEX_STYLE_UCAST_QUEUE,
   7080          &local_port, &startq, &numq));
   7081 
   7082     mmu_info = _bcm_kt_mmu_info[unit];
   7083     if (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port) ||
   7084         startq >= mmu_info->num_base_queues) {
   7085         /* pass port as queue number */
   7086         local_port = startq;
   7087         startq = 0;
   7088     }
   7089 
   7090     switch (stat) {
   7091     case bcmCosqGportGreenAcceptedPkts:
   7092         dma_id = SOC_COUNTER_NON_DMA_COSQ_ACCEPT_PKT_GREEN;
   7093         break;
   7094     case bcmCosqGportGreenAcceptedBytes:
   7095         dma_id = SOC_COUNTER_NON_DMA_COSQ_ACCEPT_BYTE_GREEN;
   7096         break;
   7097     case bcmCosqGportYellowAcceptedPkts:
   7098         dma_id = SOC_COUNTER_NON_DMA_COSQ_ACCEPT_PKT_YELLOW;
   7099         break;
   7100     case bcmCosqGportYellowAcceptedBytes:
   7101         dma_id = SOC_COUNTER_NON_DMA_COSQ_ACCEPT_BYTE_YELLOW;
   7102         break;    
   7103     case bcmCosqGportRedAcceptedPkts:
   7104         dma_id = SOC_COUNTER_NON_DMA_COSQ_ACCEPT_PKT_RED;
   7105         break;
   7106     case bcmCosqGportRedAcceptedBytes:
   7107         dma_id = SOC_COUNTER_NON_DMA_COSQ_ACCEPT_BYTE_RED;
   7108         break;        
   7109     case bcmCosqGportReceivedPkts:
   7110         dma_id = SOC_COUNTER_NON_DMA_COSQ_ACCEPT_PKT;
   7111         break;
   7112     case bcmCosqGportReceivedBytes:
   7113         dma_id = SOC_COUNTER_NON_DMA_COSQ_ACCEPT_BYTE;
   7114         break;
   7115     case bcmCosqGportGreenDroppedPkts:
   7116         dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_GREEN;
   7117         break;
   7118     case bcmCosqGportGreenDroppedBytes:
   7119         dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE_GREEN;
   7120         break;    
   7121     case bcmCosqGportYellowDroppedPkts:
   7122         dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_YELLOW;
   7123         break;
   7124     case bcmCosqGportYellowDroppedBytes:
   7125         dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE_YELLOW;
   7126         break;    
   7127     case bcmCosqGportRedDroppedPkts:
   7128         dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_RED;
   7129         break;
   7130     case bcmCosqGportRedDroppedBytes:
   7131         dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE_RED;
   7132         break;    
   7133     case bcmCosqGportDroppedPkts:
   7134         dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_PKT;
   7135         break;
   7136     case bcmCosqGportDroppedBytes:
   7137         dma_id = SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE;
   7138         break;
   7139     case bcmCosqGportOutPkts:
   7140         dma_id = SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT;
   7141         break;
   7142     case bcmCosqGportOutBytes:
   7143         dma_id = SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE;
   7144         break;    
   7145     default:
   7146         return BCM_E_PARAM;
   7147     }
   7148 
   7149     /* if sync-mode is set, update the software cached counter value, 
   7150      * with the hardware count and then retrieve the count.
   7151      * else return the software cache counter value.
   7152      */
   7153     counter_get = (sync_mode == 1)? soc_counter_sync_get: soc_counter_get;
   7154 
   7155     if (!BCM_GPORT_IS_SCHEDULER(port)) { 
   7156         BCM_IF_ERROR_RETURN
   7157              (counter_get(unit, local_port, dma_id, startq, value)); 
   7158     } else {
   7159         COMPILER_64_ZERO(sum);
   7160         for (i = 0; i < numq; i++) {
   7161             BCM_IF_ERROR_RETURN
   7162                 (counter_get(unit, local_port, dma_id, startq + i, &value64));
   7163             COMPILER_64_ADD_64(sum, value64);
   7164         }
   7165         *value = sum;
   7166     }
   7167 
   7168     return BCM_E_NONE;
   7169 }
   7170 
   7171 int bcm_kt_cosq_port_get(int unit, int queue_id, bcm_port_t *port) 
   7172 {
   7173     _bcm_kt_mmu_info_t *mmu_info;
   7174     lls_l0_parent_entry_t l0_parent;
   7175     lls_l1_parent_entry_t l1_parent;
   7176     lls_l2_parent_entry_t l2_parent;
   7177     int index;
   7178 
   7179     if (_bcm_kt_mmu_info[unit] == NULL) {
   7180         return BCM_E_INIT;
   7181     }
   7182 
   7183     mmu_info = _bcm_kt_mmu_info[unit];
   7184     
   7185     if (queue_id >= mmu_info->num_queues) {
   7186         return BCM_E_PARAM;
   7187     }
   7188 
   7189     SOC_IF_ERROR_RETURN
   7190             (READ_LLS_L2_PARENTm(unit, MEM_BLOCK_ALL, queue_id, &l2_parent));
   7191     index = soc_mem_field32_get(unit, LLS_L2_PARENTm, &l2_parent, C_PARENTf);
   7192 
   7193     SOC_IF_ERROR_RETURN
   7194             (READ_LLS_L1_PARENTm(unit, MEM_BLOCK_ALL, index, &l1_parent));
   7195     index = soc_mem_field32_get(unit, LLS_L1_PARENTm, &l1_parent, C_PARENTf);
   7196 
   7197     SOC_IF_ERROR_RETURN
   7198             (READ_LLS_L0_PARENTm(unit, MEM_BLOCK_ALL, index, &l0_parent));
   7199     
   7200     *port = soc_mem_field32_get(unit, LLS_L0_PARENTm, &l0_parent, C_PARENTf);;
   7201 
   7202     return BCM_E_NONE;
   7203 }
   7204 
   7205 #ifdef BCM_WARM_BOOT_SUPPORT
   7206 
   7207 #define BCM_WB_VERSION_1_0                     SOC_SCACHE_VERSION(1,0)
   7208 #define BCM_WB_VERSION_1_1                     SOC_SCACHE_VERSION(1,1)
   7209 #define BCM_WB_VERSION_1_2                     SOC_SCACHE_VERSION(1,2)
   7210 #define BCM_WB_DEFAULT_VERSION                 BCM_WB_VERSION_1_2
   7211 
   7212 #define _BCM_KT_COSQ_WB_END_NODE_VALUE         0xffffffff
   7213 
   7214 #define _BCM_KT_COSQ_WB_NODE_COSQ_MASK         0x3f    /* LW-1 [5:0] */
   7215 #define _BCM_KT_COSQ_WB_NODE_COSQ_SHIFT        0
   7216 #define _BCM_KT_COSQ_WB_NODE_NUMQ_MASK         0x3f    /* LW-1 [11:6] */
   7217 #define _BCM_KT_COSQ_WB_NODE_NUMQ_SHIFT        6
   7218 #define _BCM_KT_COSQ_WB_NODE_HW_INDEX_MASK     0xfff   /* LW-1 [23:12] */
   7219 #define _BCM_KT_COSQ_WB_NODE_HW_INDEX_SHIFT    12
   7220 #define _BCM_KT_COSQ_WB_NODE_LEVEL_MASK        0x3     /* LW-1 [25:24 */
   7221 #define _BCM_KT_COSQ_WB_NODE_LEVEL_SHIFT       24
   7222 #define _BCM_KT_COSQ_WB_NODE_WRR_MASK          0x1     /* LW-1 [27] */
   7223 #define _BCM_KT_COSQ_WB_NODE_WRR_SHIFT         27
   7224 
   7225 #define _BCM_KT_COSQ_WB_NUM_COS_MASK         0xf    /* [3:0] */
   7226 #define _BCM_KT_COSQ_WB_NUM_COS_SHIFT        0
   7227 
   7228 #define SET_FIELD(_field, _value)                       \
   7229     (((_value) & _BCM_KT_COSQ_WB_## _field## _MASK) <<  \
   7230      _BCM_KT_COSQ_WB_## _field## _SHIFT)
   7231 #define GET_FIELD(_field, _byte)                        \
   7232     (((_byte) >> _BCM_KT_COSQ_WB_## _field## _SHIFT) &  \
   7233      _BCM_KT_COSQ_WB_## _field## _MASK)
   7234 
   7235 STATIC int
   7236 _bcm_kt_cosq_wb_alloc(int unit)
   7237 {
   7238     soc_scache_handle_t scache_handle;
   7239     uint8 *scache_ptr;
   7240     _bcm_kt_mmu_info_t *mmu_info;
   7241     int rv, alloc_size;
   7242 
   7243     mmu_info = _bcm_kt_mmu_info[unit];
   7244 
   7245     alloc_size = 0;
   7246     alloc_size += sizeof(mmu_info->num_base_queues);
   7247     alloc_size += sizeof(mmu_info->num_ext_queues);
   7248     alloc_size += sizeof(mmu_info->qset_size);
   7249     alloc_size += sizeof(mmu_info->num_queues);
   7250     alloc_size += sizeof(mmu_info->num_nodes);
   7251     alloc_size += sizeof(mmu_info->max_nodes);
   7252     alloc_size += (_BCM_KT_NUM_TOTAL_SCHEDULERS * sizeof(uint32) * 3);
   7253     alloc_size += (_BCM_KT_NUM_L2_QUEUES * sizeof(uint32) * 2);
   7254     alloc_size += sizeof(uint32);
   7255     /* Storing NUM_COS */
   7256     alloc_size += sizeof(uint8);
   7257     /* Storing interface reference count for all queues */
   7258     alloc_size += (BCM_MULTICAST_PORT_MAX * sizeof(uint32));
   7259 
   7260     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_COSQ, 0);
   7261     rv = _bcm_esw_scache_ptr_get(unit, scache_handle, TRUE, alloc_size,
   7262                                  &scache_ptr, BCM_WB_DEFAULT_VERSION, NULL);
   7263     if (rv == BCM_E_NOT_FOUND) {
   7264         rv = BCM_E_NONE;
   7265     }
   7266 
   7267     return rv;
   7268 }
   7269 
   7270 /*
   7271  * This funtion encodes the 1 byte of the common  data to be written in to
   7272  * scache.Currently only last 4 bits of the byte are used for storing
   7273  * num cos value rest can be used if necessary later.
   7274  */
   7275 STATIC void
   7276 _bcm_kt_cosq_wb_encode_data(int unit, uint8 *scache_ptr)
   7277  {
   7278      uint8 data = 0;
   7279      int   numq = 0;
   7280      bcm_kt_cosq_config_get(unit, &numq);
   7281      data  = SET_FIELD(NUM_COS, numq);
   7282      *scache_ptr = data;
   7283 }
   7284 
   7285 STATIC uint32
   7286 _bcm_kt_cosq_wb_encode_node(int unit, _bcm_kt_cosq_node_t *node)
   7287 {
   7288     uint32 data = 0;
   7289 
   7290     data  = SET_FIELD(NODE_COSQ, node->cosq_attached_to);
   7291     data |= SET_FIELD(NODE_NUMQ, node->numq);
   7292     data |= SET_FIELD(NODE_LEVEL, node->level);
   7293     data |= SET_FIELD(NODE_HW_INDEX, node->hw_index);
   7294     data |= SET_FIELD(NODE_WRR, node->wrr_in_use);
   7295 
   7296     return data;
   7297 }
   7298 
   7299 int
   7300 bcm_kt_cosq_sync(int unit)
   7301 {
   7302     soc_scache_handle_t scache_handle;
   7303     uint8 *scache_ptr, *ptr;
   7304     _bcm_kt_mmu_info_t *mmu_info;
   7305     _bcm_kt_cosq_node_t *port_node, *l0_node, *l1_node, *l2_node;
   7306     bcm_port_t port;
   7307     int i;
   7308     uint32 node_data;
   7309 
   7310     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_COSQ, 0);
   7311     BCM_IF_ERROR_RETURN
   7312         (_bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 0,
   7313                                  &scache_ptr, BCM_WB_DEFAULT_VERSION, NULL));
   7314 
   7315     if (_bcm_kt_mmu_info[unit] == NULL) {
   7316         return BCM_E_INIT;
   7317     }
   7318 
   7319     mmu_info = _bcm_kt_mmu_info[unit];
   7320 
   7321     ptr = scache_ptr;
   7322 
   7323     *(((uint32 *)ptr)) = mmu_info->num_base_queues;
   7324     ptr += sizeof(uint32);
   7325 
   7326     *(((uint32 *)ptr)) = mmu_info->num_ext_queues;
   7327     ptr += sizeof(uint32);
   7328 
   7329     *(((uint32 *)ptr)) = mmu_info->qset_size;
   7330     ptr += sizeof(uint32);
   7331 
   7332     *(((uint32 *)ptr)) = mmu_info->num_queues;
   7333     ptr += sizeof(uint32);
   7334 
   7335     *(((uint32 *)ptr)) = mmu_info->num_nodes;
   7336     ptr += sizeof(uint32);
   7337 
   7338     for (i = 0; i < _BCM_KT_COSQ_NODE_LEVEL_MAX; i++) {
   7339         *(((uint32 *)ptr)) = mmu_info->max_nodes[i];
   7340         ptr += sizeof(uint32);
   7341     }
   7342 
   7343     PBMP_ALL_ITER(unit, port) {
   7344         port_node = &mmu_info->sched_node[port];
   7345 
   7346         if (port_node->cosq_attached_to < 0) {
   7347             continue;
   7348         }
   7349 
   7350         if (port_node->child != NULL) {
   7351             *(((uint32 *)ptr)) = port_node->gport;
   7352             ptr += sizeof(uint32);
   7353             
   7354             node_data = _bcm_kt_cosq_wb_encode_node(unit, port_node);
   7355             *(((uint32 *)ptr)) = node_data;
   7356             ptr += sizeof(uint32);
   7357 
   7358             *(((uint32 *)ptr)) = port_node->base_index;
   7359             ptr += sizeof(uint32);
   7360         }
   7361 
   7362         for (l0_node = port_node->child; l0_node != NULL;
   7363              l0_node = l0_node->sibling) {
   7364             *(((uint32 *)ptr)) = l0_node->gport;
   7365             ptr += sizeof(uint32);
   7366             
   7367             node_data = _bcm_kt_cosq_wb_encode_node(unit, l0_node);
   7368             *(((uint32 *)ptr)) = node_data;
   7369             ptr += sizeof(uint32);
   7370 
   7371             *(((uint32 *)ptr)) = l0_node->base_index;
   7372             ptr += sizeof(uint32);
   7373 
   7374             for (l1_node = l0_node->child; l1_node != NULL;
   7375                  l1_node = l1_node->sibling) {
   7376                 *(((uint32 *)ptr)) = l1_node->gport;
   7377                 ptr += sizeof(uint32);
   7378 
   7379                 node_data = _bcm_kt_cosq_wb_encode_node(unit, l1_node);
   7380                 *(((uint32 *)ptr)) = node_data;
   7381                 ptr += sizeof(uint32);
   7382 
   7383                 *(((uint32 *)ptr)) = l1_node->base_index;
   7384                 ptr += sizeof(uint32);
   7385                 
   7386                 for (l2_node = l1_node->child; l2_node != NULL;
   7387                      l2_node = l2_node->sibling) {
   7388                     *(((uint32 *)ptr)) = l2_node->gport;
   7389                     ptr += sizeof(uint32);
   7390                      
   7391                     node_data = _bcm_kt_cosq_wb_encode_node(unit, l2_node);
   7392                     *(((uint32 *)ptr)) = node_data;
   7393                     ptr += sizeof(uint32);
   7394 
   7395                 }
   7396             }
   7397 
   7398         }
   7399 
   7400     }
   7401 
   7402     *(((uint32 *)ptr)) = _BCM_KT_COSQ_WB_END_NODE_VALUE;
   7403     ptr += sizeof(uint32);
   7404 
   7405     /* add NUM_COS to the scache */
   7406     _bcm_kt_cosq_wb_encode_data(unit, (uint8 *)ptr);
   7407     ptr += sizeof(uint8);
   7408 
   7409     /* copy interface reference count values for all queues into scache ptr */
   7410     sal_memcpy(ptr, mmu_info->intf_ref_cnt,
   7411                (sizeof(uint32) * BCM_MULTICAST_PORT_MAX));
   7412     ptr += (sizeof(uint32) * BCM_MULTICAST_PORT_MAX);
   7413 
   7414     return BCM_E_NONE; 
   7415 }
   7416 /*
   7417  * Function:
   7418  *     _bcm_kt_cosq_map_alloc_set
   7419  * Purpose:
   7420  *     Allocate the cosq_map bitmap and 
   7421  *     restore  
   7422  * Parameters:
   7423  *     node       - (IN) cosq_node 
   7424  * Returns:
   7425  *     BCM_E_XXX
   7426  */
   7427 STATIC int
   7428 _bcm_kt_cosq_map_alloc_set(_bcm_kt_cosq_node_t *node)
   7429 {
   7430     _bcm_kt_cosq_node_t *child;
   7431     int alloc_size;
   7432     if (node->cosq_map == NULL) {
   7433         alloc_size = SHR_BITALLOCSIZE(node->numq);
   7434         node->cosq_map = _bcm_kt_cosq_alloc_clear(alloc_size,
   7435                                            "cosq_map");
   7436         if (node->cosq_map == NULL) {
   7437             return BCM_E_MEMORY;
   7438         }
   7439     }
   7440     child = node->child;
   7441     while (child != NULL) {
   7442            BCM_IF_ERROR_RETURN
   7443              (_bcm_kt_cosq_map_index_set(node->cosq_map, 
   7444                                   child->cosq_attached_to, 1));
   7445         child = child->sibling;
   7446     }
   7447 
   7448     return BCM_E_NONE;
   7449 }
   7450 
   7451 /*
   7452  * Function:
   7453  *     _bcm_kt_cosq_map_recover_next_level_node  
   7454  * Purpose:
   7455  *     Used to recover cos_map for S0,S1,L0,L1 levels   
   7456  * Parameters:
   7457  *     node       - (IN) cosq_node 
   7458  * Returns:
   7459  *     BCM_E_XXX
   7460  */
   7461 
   7462 
   7463 STATIC int
   7464 _bcm_kt_cosq_map_recover_next_level_node(_bcm_kt_cosq_node_t *node) 
   7465 {
   7466     if (!node) {
   7467         return BCM_E_NONE;
   7468     }
   7469     if (node->level == _BCM_KT_COSQ_NODE_LEVEL_L2) {
   7470         return BCM_E_NONE;
   7471     }
   7472     BCM_IF_ERROR_RETURN(_bcm_kt_cosq_map_alloc_set(node));
   7473     BCM_IF_ERROR_RETURN(_bcm_kt_cosq_map_recover_next_level_node(node->sibling));
   7474     BCM_IF_ERROR_RETURN(_bcm_kt_cosq_map_recover_next_level_node(node->child));
   7475     return BCM_E_NONE;
   7476 }
   7477 
   7478 STATIC int
   7479 _bcm_set_gport_pair(int unit,_bcm_kt_cosq_node_t *node) 
   7480 {
   7481 
   7482     _bcm_kt_cosq_node_t *parent = NULL;
   7483     _bcm_kt_cosq_node_t *curnode = NULL;
   7484     _bcm_kt_mmu_info_t *mmu_info = NULL;
   7485     int cosq = 0;
   7486     int paircosq = 0;
   7487     int numcos = 0;
   7488     uint32 encap_id;
   7489    
   7490     BCM_IF_ERROR_RETURN(
   7491        bcm_kt_cosq_config_get(unit, &numcos));
   7492     parent = node->parent;
   7493     if(!parent) 
   7494     {
   7495        return BCM_E_INTERNAL; 
   7496     }
   7497     cosq = node->cosq_attached_to;
   7498     paircosq = (cosq + numcos) % (numcos * 2);
   7499     mmu_info = _bcm_kt_mmu_info[unit];
   7500 
   7501     for(curnode = parent->child; curnode; curnode = curnode->sibling)
   7502     {
   7503         if (curnode->cosq_attached_to == paircosq) { 
   7504             encap_id = (BCM_GPORT_SCHEDULER_GET(node->gport) >> 8) & 0x7ff; 
   7505             mmu_info->l1_gport_pair[encap_id] = curnode->gport; 
   7506             break; 
   7507        }
   7508     }
   7509     return BCM_E_NONE;
   7510 }
   7511 int
   7512 bcm_kt_cosq_reinit(int unit)
   7513 {
   7514     soc_scache_handle_t scache_handle;
   7515     uint8 *scache_ptr, *ptr;
   7516     _bcm_kt_cosq_node_t *port_info;
   7517     _bcm_kt_mmu_info_t *mmu_info;
   7518     _bcm_kt_cosq_node_t *port_node = NULL;
   7519     _bcm_kt_cosq_node_t *queue_node = NULL;
   7520     _bcm_kt_cosq_node_t *node = NULL;
   7521     _bcm_kt_cosq_node_t *l0_node = NULL;
   7522     _bcm_kt_cosq_node_t *l1_node = NULL;
   7523     _bcm_kt_cosq_node_t *l2_node = NULL;
   7524     _bcm_kt_cosq_node_t *curnode = NULL;
   7525     _bcm_kt_cosq_node_t *l0node = NULL;
   7526     int rv, stable_size = 0;
   7527     bcm_port_t port = 0;
   7528     bcm_gport_t gport;
   7529     int i, index, numq;
   7530     uint32 node_data;
   7531     uint32 encap_id;
   7532     int set_index, cosq;
   7533     uint32 entry[SOC_MAX_MEM_WORDS];
   7534     soc_profile_mem_t *profile_mem;
   7535     _bcm_kt_cosq_list_t *list;
   7536     soc_mem_t mem;
   7537     mmu_wred_queue_config_buffer_entry_t qentry;
   7538     mmu_wred_queue_config_qentry_entry_t qentry1;
   7539     int cpu_hg_index = 0;
   7540     uint8 data;
   7541     int num_cos = 0;
   7542     uint16 recovered_ver = 0;
   7543     int additional_scache_size = 0;
   7544     uint32 *l0_bmap = NULL;
   7545     uint32 *l1_bmap = NULL;
   7546     uint32 *l2_bmap = NULL;
   7547 
   7548 
   7549     SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size));
   7550     if ((stable_size == 0) || (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit))) {
   7551         /* COSQ warmboot requires extended scache support i.e. level2 warmboot*/
   7552         return BCM_E_NONE;
   7553     }
   7554 
   7555     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_COSQ, 0);
   7556     rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 0, &scache_ptr,
   7557                                  BCM_WB_DEFAULT_VERSION, &recovered_ver);
   7558     if (BCM_FAILURE(rv)) {
   7559         return rv;
   7560     }
   7561 
   7562     if (_bcm_kt_mmu_info[unit] == NULL) {
   7563         return BCM_E_INIT;
   7564     }
   7565 
   7566     mmu_info = _bcm_kt_mmu_info[unit];
   7567 
   7568     ptr = scache_ptr;
   7569 
   7570     mmu_info->num_base_queues = *(((uint32 *)ptr));
   7571     ptr += sizeof(uint32);
   7572 
   7573     mmu_info->num_ext_queues = *(((uint32 *)ptr));
   7574     ptr += sizeof(uint32);
   7575 
   7576     mmu_info->qset_size = *(((uint32 *)ptr));
   7577     ptr += sizeof(uint32);
   7578 
   7579     mmu_info->num_queues = *(((uint32 *)ptr));
   7580     ptr += sizeof(uint32);
   7581 
   7582     mmu_info->num_nodes = *(((uint32 *)ptr));
   7583     ptr += sizeof(uint32);
   7584 
   7585     for (i = 0; i < _BCM_KT_COSQ_NODE_LEVEL_MAX; i++) {
   7586         mmu_info->max_nodes[i] = *(((uint32 *)ptr));
   7587         ptr += sizeof(uint32);
   7588     }
   7589 
   7590     while (*(((uint32 *)ptr)) != _BCM_KT_COSQ_WB_END_NODE_VALUE) {
   7591         gport = *(((uint32 *)ptr));
   7592         ptr += sizeof(uint32);
   7593         node_data = *(((uint32 *)ptr));
   7594         ptr += sizeof(uint32);
   7595                      
   7596         if (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport)) {
   7597             list = &mmu_info->ext_qlist;
   7598             encap_id = BCM_GPORT_UCAST_SUBSCRIBER_QUEUE_GROUP_QID_GET(gport);
   7599             node = &mmu_info->queue_node[encap_id];
   7600             encap_id -= mmu_info->num_base_queues;
   7601             _bcm_kt_node_index_set(list, encap_id, 1);
   7602         } else if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   7603             encap_id = BCM_GPORT_UCAST_QUEUE_GROUP_QID_GET(gport);
   7604             node = &mmu_info->queue_node[encap_id];
   7605         } else {
   7606             encap_id = (BCM_GPORT_SCHEDULER_GET(gport) >> 8) & 0x7ff;
   7607             if (encap_id == 0) {
   7608                 encap_id = (BCM_GPORT_SCHEDULER_GET(gport) & 0xff);
   7609             }
   7610             list = &mmu_info->sched_list;
   7611             _bcm_kt_node_index_set(list, encap_id, 1);
   7612             node = &mmu_info->sched_node[encap_id]; 
   7613             node->first_child = 4095;
   7614             node->base_index = *(((uint32 *)ptr));
   7615             ptr += sizeof(uint32);
   7616         }
   7617 
   7618         node->gport = gport;
   7619         node->numq  = GET_FIELD(NODE_NUMQ, node_data);
   7620         node->cosq_attached_to = GET_FIELD(NODE_COSQ, node_data);
   7621         node->level = GET_FIELD(NODE_LEVEL, node_data);
   7622         node->hw_index = GET_FIELD(NODE_HW_INDEX, node_data);
   7623         node->wrr_in_use = GET_FIELD(NODE_WRR, node_data);
   7624 
   7625         switch (node->level) {
   7626             case _BCM_KT_COSQ_NODE_LEVEL_ROOT:
   7627                 port_node = node;
   7628                 port_node->parent = NULL;
   7629                 port_node->sibling = NULL;
   7630                 port_node->child = NULL;
   7631                 break;
   7632 
   7633             case _BCM_KT_COSQ_NODE_LEVEL_L0:
   7634                 l0_node = node;
   7635                 list = &mmu_info->l0_sched_list;
   7636                 
   7637                 if (port_node != NULL) {
   7638                     l0_node->parent = port_node;
   7639                     l0_node->sibling = port_node->child;
   7640                     
   7641                     port_node->child = l0_node;
   7642                     port_node->num_child++;
   7643                     
   7644                     if (port_node->numq > 0) {
   7645                         if (l0_node->hw_index < port_node->first_child) {
   7646                             port_node->first_child = l0_node->hw_index;
   7647                         }
   7648                         if (port_node->num_child == 1) {
   7649                             _bcm_kt_node_index_set(list, port_node->base_index, port_node->numq);
   7650                         }
   7651                     } else {
   7652                         _bcm_kt_node_index_set(list, l0_node->hw_index, 1);
   7653                     }
   7654                 }
   7655                 break;
   7656 
   7657             case _BCM_KT_COSQ_NODE_LEVEL_L1:
   7658                 l1_node = node;
   7659                 list = &mmu_info->l1_sched_list;
   7660                 if (l0_node != NULL) {
   7661                     l1_node->parent = l0_node;
   7662                     l1_node->sibling = l0_node->child;
   7663                     
   7664                     l0_node->child = l1_node;
   7665                     l0_node->num_child++;
   7666 
   7667                     if (l0_node->numq > 0) {
   7668                         if (l1_node->hw_index < l0_node->first_child) {
   7669                             l0_node->first_child = l1_node->hw_index;
   7670                         }
   7671                         if (l0_node->num_child == 1) {
   7672                             _bcm_kt_node_index_set(list, l0_node->base_index, l0_node->numq);
   7673                         }
   7674                     } else {
   7675                         _bcm_kt_node_index_set(list, l1_node->hw_index, 1);
   7676                     }
   7677                 }
   7678                 break;
   7679 
   7680             case _BCM_KT_COSQ_NODE_LEVEL_L2:
   7681                 queue_node = node;
   7682                 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   7683                     list = &mmu_info->l2_base_qlist;
   7684                 } else {
   7685                     list = &mmu_info->l2_ext_qlist;
   7686                 }
   7687                 if (l1_node != NULL) {
   7688                     queue_node->parent = l1_node;
   7689                     queue_node->sibling = l1_node->child;
   7690                     queue_node->hw_index = GET_FIELD(NODE_HW_INDEX, node_data);
   7691                     l1_node->child = queue_node;
   7692                     l1_node->num_child++;
   7693 
   7694                     if (l1_node->numq > 0) {    
   7695                         if (queue_node->hw_index < l1_node->first_child) {
   7696                             l1_node->first_child = queue_node->hw_index;
   7697                         }
   7698                         if (l1_node->num_child == 1) {
   7699                             _bcm_kt_node_index_set(list, l1_node->base_index, l1_node->numq);
   7700                         }    
   7701                     } else {
   7702                         _bcm_kt_node_index_set(list, queue_node->hw_index, 1);
   7703                     }
   7704                 }
   7705                 break;
   7706 
   7707             default:
   7708                break;
   7709         }
   7710     }
   7711 
   7712     /* Update PORT_COS_MAP memory profile reference counter */
   7713     profile_mem = _bcm_kt_cos_map_profile[unit];
   7714     PBMP_ALL_ITER(unit, port) {
   7715         SOC_IF_ERROR_RETURN
   7716             (soc_mem_read(unit, COS_MAP_SELm, MEM_BLOCK_ALL, port, &entry));
   7717         set_index = soc_mem_field32_get(unit, COS_MAP_SELm, &entry, SELECTf);
   7718         SOC_IF_ERROR_RETURN
   7719             (soc_profile_mem_reference(unit, profile_mem, set_index * 16, 16));
   7720     }
   7721 
   7722     cpu_hg_index = SOC_IS_KATANA2(unit) ?
   7723                    SOC_INFO(unit).cpu_hg_pp_port_index :
   7724                    SOC_INFO(unit).cpu_hg_index;
   7725     if (cpu_hg_index != -1) {
   7726         SOC_IF_ERROR_RETURN(soc_mem_read(unit, COS_MAP_SELm, MEM_BLOCK_ALL,
   7727                                          cpu_hg_index, &entry));
   7728         set_index = soc_mem_field32_get(unit, COS_MAP_SELm, &entry, SELECTf);
   7729         SOC_IF_ERROR_RETURN
   7730             (soc_profile_mem_reference(unit, profile_mem, set_index, 1));
   7731     }
   7732 
   7733     /* Update MMU_WRED_DROP_CURVE_PROFILE_x memory profile reference counter */
   7734     profile_mem = _bcm_kt_wred_profile[unit];
   7735     PBMP_PORT_ITER(unit, port) {
   7736     /* 
   7737      * Wred data can be in two tables depending on packet based or byte bases
   7738      * we scan both and update the software profile
   7739      */
   7740         BCM_IF_ERROR_RETURN
   7741             (_bcm_kt_cosq_index_resolve(unit, port, -1,
   7742                                         _BCM_KT_COSQ_INDEX_STYLE_WRED, NULL,
   7743                                         NULL, &numq));
   7744         for (cosq = 0; cosq < numq; cosq++) {
   7745             BCM_IF_ERROR_RETURN
   7746                 (_bcm_kt_cosq_index_resolve(unit, port, cosq,
   7747                                             _BCM_KT_COSQ_INDEX_STYLE_WRED,
   7748                                             NULL, &index, NULL));
   7749             /* scan byte based wred table */ 
   7750             mem = MMU_WRED_QUEUE_CONFIG_BUFFERm;
   7751             SOC_IF_ERROR_RETURN
   7752             (soc_mem_read(unit, mem, MEM_BLOCK_ALL, index, &qentry));
   7753             set_index = soc_mem_field32_get(unit, mem, &qentry, PROFILE_INDEXf);
   7754             SOC_IF_ERROR_RETURN
   7755                 (soc_profile_mem_reference(unit, profile_mem, set_index, 1));
   7756             
   7757             /* scan packet based wred table */ 
   7758             mem = MMU_WRED_QUEUE_CONFIG_QENTRYm;
   7759             set_index = 0; 
   7760             memset(&qentry1, 0, sizeof(mmu_wred_queue_config_qentry_entry_t));
   7761 
   7762             SOC_IF_ERROR_RETURN
   7763             (soc_mem_read(unit, mem, MEM_BLOCK_ALL, index, &qentry1));
   7764             set_index = soc_mem_field32_get(unit, mem, &qentry1, PROFILE_INDEXf);
   7765             SOC_IF_ERROR_RETURN
   7766                 (soc_profile_mem_reference(unit, profile_mem, set_index, 1));
   7767         }
   7768     }
   7769     /* Restoring the cosq_map */ 
   7770     PBMP_ALL_ITER(unit, port) {
   7771     /* root node */
   7772        port_info = &mmu_info->sched_node[port];
   7773        node = NULL;
   7774        if (port_info->gport >= 0) {
   7775            BCM_IF_ERROR_RETURN(
   7776               _bcm_kt_cosq_node_get(unit, port_info->gport, 
   7777                                NULL, NULL, NULL, &node));
   7778            if (node != NULL) {
   7779                   BCM_IF_ERROR_RETURN(
   7780                           _bcm_kt_cosq_map_recover_next_level_node(node));
   7781                    }
   7782         }
   7783      }
   7784 /*
   7785  * The following will recover the L1 gport pair 
   7786  * if the dynamic sched update feature is enabled 
   7787  */
   7788     if (soc_feature(unit, soc_feature_dynamic_sched_update)) 
   7789     { 
   7790         PBMP_ALL_ITER(unit, port) {
   7791           port_info = &mmu_info->sched_node[port];
   7792           if (port_info->gport >= 0) {
   7793                BCM_IF_ERROR_RETURN(
   7794               _bcm_kt_cosq_node_get(unit, port_info->gport, 
   7795                                   NULL, NULL, NULL, &node));
   7796               if (node->child) {
   7797                   l0node = node->child; 
   7798 /*The curnode is always L1 here*/
   7799                   for (curnode = l0node->child; curnode; 
   7800                                       curnode = curnode->sibling ) { 
   7801                        _bcm_set_gport_pair(unit, curnode); 
   7802                   }      
   7803               }
   7804           } 
   7805        }
   7806     }
   7807     /* Recover NUM_COS */
   7808     if (recovered_ver >= BCM_WB_VERSION_1_1) {
   7809         ptr += sizeof(uint32);
   7810         data = *((uint8 *) ptr);
   7811         num_cos = GET_FIELD(NUM_COS, data);
   7812         if (_bcm_kt_num_cosq[unit] == 0) {
   7813             return BCM_E_INIT;
   7814         }
   7815         _bcm_kt_num_cosq[unit] = num_cos;
   7816     } else {
   7817         additional_scache_size += sizeof(uint8);
   7818     }
   7819 
   7820     if (recovered_ver >= BCM_WB_VERSION_1_2) {
   7821         ptr += sizeof(uint8);
   7822         /* Update interface reference count values for all queues */
   7823         sal_memcpy(mmu_info->intf_ref_cnt, ptr,
   7824                    (sizeof(uint32) * BCM_MULTICAST_PORT_MAX));
   7825         ptr += (sizeof(uint32) * BCM_MULTICAST_PORT_MAX);
   7826     } else {
   7827         /* Extra memory to store interface ref count of queues */
   7828         additional_scache_size += (sizeof(uint32) * BCM_MULTICAST_PORT_MAX);
   7829     }
   7830 
   7831     if (additional_scache_size > 0) {
   7832         BCM_IF_ERROR_RETURN(
   7833                 soc_scache_realloc(unit, scache_handle, additional_scache_size));
   7834     }
   7835 
   7836     for (port = CMIC_PORT(unit); port < (LB_PORT(unit)+1); port++) {
   7837         l0_bmap = SOC_CONTROL(unit)->port_lls_l0_bmap[port];
   7838         l1_bmap = SOC_CONTROL(unit)->port_lls_l1_bmap[port];
   7839         l2_bmap = SOC_CONTROL(unit)->port_lls_l2_bmap[port];
   7840         port_node = &mmu_info->sched_node[port];
   7841 
   7842         if (port_node->cosq_attached_to < 0) {
   7843             continue;
   7844         }
   7845 
   7846 
   7847         for (l0_node = port_node->child; l0_node != NULL;
   7848                 l0_node = l0_node->sibling) {
   7849             _BCM_COSQ_PARENT_BMAP_SET(l0_bmap, l0_node->hw_index);
   7850             for (l1_node = l0_node->child; l1_node != NULL;
   7851                     l1_node = l1_node->sibling) {
   7852                 _BCM_COSQ_PARENT_BMAP_SET(l1_bmap, l1_node->hw_index);
   7853                 for (l2_node = l1_node->child; l2_node != NULL;
   7854                         l2_node = l2_node->sibling) {
   7855                     _BCM_COSQ_PARENT_BMAP_SET(l2_bmap, l2_node->hw_index);
   7856                 }
   7857             }
   7858         }
   7859     }
   7860 
   7861 
   7862     return BCM_E_NONE;
   7863 }
   7864 
   7865 #endif /* BCM_WARM_BOOT_SUPPORT */
   7866 
   7867 /*
   7868  * Function:
   7869  *     bcm_kt_cosq_init
   7870  * Purpose:
   7871  *     Initialize (clear) all COS schedule/mapping state.
   7872  * Parameters:
   7873  *     unit - unit number
   7874  * Returns:
   7875  *     BCM_E_XXX
   7876  */
   7877 int
   7878 bcm_kt_cosq_init(int unit)
   7879 {
   7880     soc_info_t *si;
   7881     STATIC int _kt_max_cosq = -1;
   7882     int cosq, numq, alloc_size;
   7883     bcm_port_t port;
   7884     soc_reg_t mem;
   7885     STATIC soc_mem_t wred_mems[6] = {
   7886         MMU_WRED_DROP_CURVE_PROFILE_0m, MMU_WRED_DROP_CURVE_PROFILE_1m,
   7887         MMU_WRED_DROP_CURVE_PROFILE_2m, MMU_WRED_DROP_CURVE_PROFILE_3m,
   7888         MMU_WRED_DROP_CURVE_PROFILE_4m, MMU_WRED_DROP_CURVE_PROFILE_5m
   7889     };
   7890     int entry_words[6];
   7891     mmu_wred_drop_curve_profile_0_entry_t entry_tcp_green;
   7892     mmu_wred_drop_curve_profile_1_entry_t entry_tcp_yellow;
   7893     mmu_wred_drop_curve_profile_2_entry_t entry_tcp_red;
   7894     mmu_wred_drop_curve_profile_3_entry_t entry_nontcp_green;
   7895     mmu_wred_drop_curve_profile_4_entry_t entry_nontcp_yellow;
   7896     mmu_wred_drop_curve_profile_5_entry_t entry_nontcp_red;
   7897     void *entries[6];
   7898     uint32 profile_index, rval;
   7899     _bcm_kt_mmu_info_t *mmu_info_p;
   7900     int i, cmc;
   7901     bcm_gport_t port_sched, l0_sched, l1_sched, queue;
   7902     uint32 max_threshold, min_threshold;
   7903     int num_queues, num_inputs;
   7904     int num_base_queues = 0;
   7905 
   7906     if (_kt_max_cosq < 0) {
   7907         _kt_max_cosq = NUM_COS(unit);
   7908         NUM_COS(unit) = 8;
   7909     }
   7910 
   7911     if (!SOC_WARM_BOOT(unit)) {    /* Cold Boot */
   7912         BCM_IF_ERROR_RETURN (bcm_kt_cosq_detach(unit, 0));
   7913     }
   7914 
   7915     numq = soc_property_get(unit, spn_BCM_NUM_COS, BCM_COS_DEFAULT);
   7916 
   7917     if (numq < 1) {
   7918         numq = 1;
   7919     } else if (numq > 8) {
   7920         numq = 8;
   7921     }
   7922 
   7923     /* Create profile for PORT_COS_MAP table */
   7924     if (_bcm_kt_cos_map_profile[unit] == NULL) {
   7925         _bcm_kt_cos_map_profile[unit] = sal_alloc(sizeof(soc_profile_mem_t),
   7926                                                   "COS_MAP Profile Mem");
   7927         if (_bcm_kt_cos_map_profile[unit] == NULL) {
   7928             return BCM_E_MEMORY;
   7929         }
   7930         soc_profile_mem_t_init(_bcm_kt_cos_map_profile[unit]);
   7931     }
   7932     mem = PORT_COS_MAPm;
   7933     entry_words[0] = sizeof(port_cos_map_entry_t) / sizeof(uint32);
   7934     BCM_IF_ERROR_RETURN(soc_profile_mem_create(unit, &mem, entry_words, 1,
   7935                                                _bcm_kt_cos_map_profile[unit]));
   7936 
   7937     /* Create profile for MMU_WRED_DROP_CURVE_PROFILE_x tables */
   7938     if (_bcm_kt_wred_profile[unit] == NULL) {
   7939         _bcm_kt_wred_profile[unit] = sal_alloc(sizeof(soc_profile_mem_t),
   7940                                                "WRED Profile Mem");
   7941         if (_bcm_kt_wred_profile[unit] == NULL) {
   7942             return BCM_E_MEMORY;
   7943         }
   7944         soc_profile_mem_t_init(_bcm_kt_wred_profile[unit]);
   7945     }
   7946     entry_words[0] =
   7947         sizeof(mmu_wred_drop_curve_profile_0_entry_t) / sizeof(uint32);
   7948     entry_words[1] =
   7949         sizeof(mmu_wred_drop_curve_profile_1_entry_t) / sizeof(uint32);
   7950     entry_words[2] =
   7951         sizeof(mmu_wred_drop_curve_profile_2_entry_t) / sizeof(uint32);
   7952     entry_words[3] =
   7953         sizeof(mmu_wred_drop_curve_profile_3_entry_t) / sizeof(uint32);
   7954     entry_words[4] =
   7955         sizeof(mmu_wred_drop_curve_profile_4_entry_t) / sizeof(uint32);
   7956     entry_words[5] =
   7957         sizeof(mmu_wred_drop_curve_profile_5_entry_t) / sizeof(uint32);
   7958     BCM_IF_ERROR_RETURN(soc_profile_mem_create(unit, wred_mems, entry_words, 6,
   7959                                                _bcm_kt_wred_profile[unit]));
   7960 
   7961     alloc_size = sizeof(_bcm_kt_mmu_info_t) * 1;
   7962     if (_bcm_kt_mmu_info[unit] == NULL) {
   7963         _bcm_kt_mmu_info[unit] =
   7964             sal_alloc(alloc_size, "_bcm_kt_mmu_info");
   7965 
   7966         if (_bcm_kt_mmu_info[unit] == NULL) {
   7967             return BCM_E_MEMORY;
   7968         }
   7969     } else {
   7970         _bcm_kt_cosq_free_memory(_bcm_kt_mmu_info[unit]);
   7971     }
   7972 
   7973     sal_memset(_bcm_kt_mmu_info[unit], 0, alloc_size);
   7974 
   7975     mmu_info_p = _bcm_kt_mmu_info[unit];
   7976     if (soc_feature(unit, soc_feature_ddr3)) {
   7977         mmu_info_p->num_queues = soc_mem_index_count(unit, LLS_L2_PARENTm);
   7978     } else {
   7979         /* restrict to maximum 1K queues */
   7980         mmu_info_p->num_queues = 1024;
   7981     }
   7982     
   7983     mmu_info_p->max_nodes[_BCM_KT_COSQ_NODE_LEVEL_ROOT] = soc_mem_index_count(unit, LLS_PORT_CONFIGm);
   7984     mmu_info_p->max_nodes[_BCM_KT_COSQ_NODE_LEVEL_L0]   = soc_mem_index_count(unit, LLS_L0_CONFIGm);
   7985     mmu_info_p->max_nodes[_BCM_KT_COSQ_NODE_LEVEL_L1]   = soc_mem_index_count(unit, LLS_L1_CONFIGm);
   7986     mmu_info_p->max_nodes[_BCM_KT_COSQ_NODE_LEVEL_L2]   = mmu_info_p->num_queues;
   7987 
   7988     mmu_info_p->num_nodes = 0;
   7989 
   7990     if (!soc_feature(unit, soc_feature_ddr3)) {
   7991         mmu_info_p->max_nodes[_BCM_KT_COSQ_NODE_LEVEL_L0] /= 2; /* 512 */
   7992         mmu_info_p->max_nodes[_BCM_KT_COSQ_NODE_LEVEL_L1] /= 2; /* 128 */
   7993     }    
   7994 
   7995     for (i=0; i<_BCM_KT_COSQ_NODE_LEVEL_L2; i++) {
   7996         mmu_info_p->num_nodes += mmu_info_p->max_nodes[i];
   7997     }
   7998 
   7999     mmu_info_p->port = _bcm_kt_cosq_alloc_clear((_BCM_KT_NUM_PORT_SCHEDULERS * 
   8000                                               sizeof(_bcm_kt_cosq_port_info_t)),
   8001                                               "port_info");
   8002     if (mmu_info_p->port == NULL) {
   8003         _bcm_kt_cosq_free_memory(mmu_info_p);
   8004         return BCM_E_MEMORY;
   8005     }
   8006 
   8007     si = &SOC_INFO(unit);
   8008     
   8009     for (port=0;port < (si->lb_port+1);port++) {  
   8010         if (!SOC_PBMP_MEMBER((PBMP_ALL(unit)), port)) {
   8011             if (SOC_IS_KATANA(unit)) {
   8012                 continue;
   8013             }
   8014         }
   8015         mmu_info_p->port[port].q_offset = si->port_cosq_base[port];
   8016         mmu_info_p->port[port].q_limit = si->port_cosq_base[port] + 
   8017                                          si->port_num_uc_cosq[port];
   8018 
   8019         SOC_IF_ERROR_RETURN(READ_ING_COS_MODEr(unit, port, &rval));
   8020         soc_reg_field_set(unit, ING_COS_MODEr, &rval, BASE_QUEUE_NUMf,
   8021                       mmu_info_p->port[port].q_offset);
   8022         if (IS_HG_PORT(unit, port)) {
   8023             soc_reg_field_set(unit, ING_COS_MODEr, &rval, COS_MODEf, 2);  
   8024         }
   8025         SOC_IF_ERROR_RETURN(WRITE_ING_COS_MODEr(unit, port, rval));
   8026 
   8027         if (SOC_IS_KATANA(unit)) {
   8028             SOC_IF_ERROR_RETURN(READ_RQE_PORT_CONFIGr(unit, port, &rval));
   8029             soc_reg_field_set(unit, RQE_PORT_CONFIGr, &rval, BASE_QUEUEf,
   8030                               mmu_info_p->port[port].q_offset);
   8031             if (IS_EXT_MEM_PORT(unit, port)) {
   8032                 soc_reg_field_set(unit, RQE_PORT_CONFIGr, &rval, BUFF_TYPEf, 1);
   8033             }    
   8034             if (IS_HG_PORT(unit, port)) {
   8035                 soc_reg_field_set(unit, RQE_PORT_CONFIGr, &rval, COS_MODEf, 2);
   8036             }   
   8037             SOC_IF_ERROR_RETURN(WRITE_RQE_PORT_CONFIGr(unit, port, rval));
   8038 
   8039             rval = 0;
   8040             soc_reg_field_set(unit, OP_E2ECC_PORT_CONFIGr, &rval, BASE_QUEUEf,
   8041                               mmu_info_p->port[port].q_offset);
   8042             if (IS_EXT_MEM_PORT(unit, port)) {
   8043                 soc_reg_field_set(unit, OP_E2ECC_PORT_CONFIGr, &rval, 
   8044                                   BUFF_TYPEf, 1);  
   8045             }    
   8046             SOC_IF_ERROR_RETURN(WRITE_OP_E2ECC_PORT_CONFIGr(unit, port, rval));
   8047         }
   8048 
   8049 #if defined (BCM_KATANA2_SUPPORT)
   8050         if (SOC_IS_KATANA2(unit)) {
   8051             SOC_IF_ERROR_RETURN(READ_RQE_PP_PORT_CONFIGr(unit, port, &rval));
   8052             soc_reg_field_set(unit, RQE_PP_PORT_CONFIGr, &rval, BASE_QUEUEf,
   8053                               mmu_info_p->port[port].q_offset);
   8054             if (IS_EXT_MEM_PORT(unit, port)) {
   8055                 soc_reg_field_set(unit, RQE_PP_PORT_CONFIGr,
   8056                     &rval, BUFF_TYPEf, 1);
   8057             }    
   8058             if (IS_HG_PORT(unit, port)) {
   8059                 soc_reg_field_set(unit, RQE_PP_PORT_CONFIGr,
   8060                     &rval, COS_MODEf, 2);
   8061             }   
   8062             SOC_IF_ERROR_RETURN(WRITE_RQE_PP_PORT_CONFIGr(unit, port, rval));
   8063      
   8064             for (i = mmu_info_p->port[port].q_offset;
   8065                  i <= (mmu_info_p->port[port].q_offset +
   8066                        mmu_info_p->port[port].q_limit); i++) {
   8067                 SOC_IF_ERROR_RETURN (soc_mem_field32_modify(unit,
   8068                     EGR_QUEUE_TO_PP_PORT_MAPm, i, PP_PORTf,port));
   8069             }
   8070         }
   8071 #endif
   8072         num_base_queues = mmu_info_p->port[port].q_limit;
   8073     }
   8074 
   8075     mmu_info_p->num_base_queues = soc_property_get(unit, spn_MMU_MAX_CLASSIC_QUEUES, 
   8076                                                    num_base_queues);
   8077     mmu_info_p->num_ext_queues    = mmu_info_p->num_queues - mmu_info_p->num_base_queues;
   8078     mmu_info_p->qset_size         = soc_property_get(unit, spn_MMU_SUBSCRIBER_NUM_COS_LEVEL, 1);
   8079 
   8080     /* Config variable defining
   8081      * the number of pre reserved subscriber queues
   8082      * spn_MMU_NUM_SUBSCRIBER_QUEUES
   8083      */
   8084     mmu_info_p->num_sub_queues = soc_property_get(unit,
   8085                                                    spn_MMU_NUM_SUBSCRIBER_QUEUES,
   8086                                                    0);
   8087     mmu_info_p->l1_gport_pair = _bcm_kt_cosq_alloc_clear((mmu_info_p->num_nodes * 
   8088                                               sizeof(bcm_gport_t)),
   8089                                               "l1_pair_info");
   8090     if (mmu_info_p->l1_gport_pair == NULL) {
   8091         _bcm_kt_cosq_free_memory(mmu_info_p);
   8092         return BCM_E_MEMORY;
   8093     }
   8094 
   8095     mmu_info_p->ext_qlist.bits  = _bcm_kt_cosq_alloc_clear(SHR_BITALLOCSIZE(mmu_info_p->num_ext_queues),
   8096                                               "ext_qlist");
   8097     if (mmu_info_p->ext_qlist.bits == NULL) {
   8098         _bcm_kt_cosq_free_memory(mmu_info_p);
   8099         return BCM_E_MEMORY;
   8100     }
   8101 
   8102     mmu_info_p->sched_list.bits = _bcm_kt_cosq_alloc_clear(SHR_BITALLOCSIZE(mmu_info_p->num_nodes),
   8103                                               "sched_list");
   8104     if (mmu_info_p->sched_list.bits == NULL) {
   8105         _bcm_kt_cosq_free_memory(mmu_info_p);
   8106         return BCM_E_MEMORY;
   8107     }
   8108 
   8109     mmu_info_p->l0_sched_list.bits = _bcm_kt_cosq_alloc_clear(SHR_BITALLOCSIZE
   8110                                             (mmu_info_p->max_nodes[_BCM_KT_COSQ_NODE_LEVEL_L0]),
   8111                                             "l0_sched_list");
   8112     if (mmu_info_p->l0_sched_list.bits == NULL) {
   8113         _bcm_kt_cosq_free_memory(mmu_info_p);
   8114         return BCM_E_MEMORY;
   8115     }
   8116 
   8117     mmu_info_p->l1_sched_list.bits = _bcm_kt_cosq_alloc_clear(SHR_BITALLOCSIZE
   8118                                              (mmu_info_p->max_nodes[_BCM_KT_COSQ_NODE_LEVEL_L1]),
   8119                                              "l1_sched_list");
   8120     if (mmu_info_p->l1_sched_list.bits == NULL) {
   8121         _bcm_kt_cosq_free_memory(mmu_info_p);
   8122         return BCM_E_MEMORY;
   8123     }
   8124 
   8125     mmu_info_p->l2_base_qlist.bits = _bcm_kt_cosq_alloc_clear(SHR_BITALLOCSIZE(mmu_info_p->num_base_queues),
   8126                                              "l2_base_qlist");
   8127     if (mmu_info_p->l2_base_qlist.bits == NULL) {
   8128         _bcm_kt_cosq_free_memory(mmu_info_p);
   8129         return BCM_E_MEMORY;
   8130     }
   8131 
   8132     mmu_info_p->l2_ext_qlist.bits = _bcm_kt_cosq_alloc_clear(SHR_BITALLOCSIZE(mmu_info_p->num_ext_queues),
   8133                                              "l2_ext_qlist");
   8134     if (mmu_info_p->l2_ext_qlist.bits == NULL) {
   8135         _bcm_kt_cosq_free_memory(mmu_info_p);
   8136         return BCM_E_MEMORY;
   8137     }
   8138 
   8139     for (i = 0; i < _BCM_KT_NUM_TOTAL_SCHEDULERS; i++) {
   8140         _BCM_KT_COSQ_LIST_NODE_INIT(mmu_info_p->sched_node, i);
   8141     }
   8142 
   8143     for (i = 0; i < _BCM_KT_NUM_L2_QUEUES; i++) {
   8144         _BCM_KT_COSQ_LIST_NODE_INIT(mmu_info_p->queue_node, i);
   8145     }
   8146 
   8147     /* reserve last entry of L0 and L1 nodes */
   8148     BCM_IF_ERROR_RETURN
   8149         (_bcm_kt_node_index_set(&mmu_info_p->l0_sched_list, 
   8150         (mmu_info_p->max_nodes[_BCM_KT_COSQ_NODE_LEVEL_L0] - 1), 1));
   8151     BCM_IF_ERROR_RETURN
   8152         (_bcm_kt_node_index_set(&mmu_info_p->l1_sched_list, 
   8153         (mmu_info_p->max_nodes[_BCM_KT_COSQ_NODE_LEVEL_L1] - 1), 1));    
   8154 
   8155     if (mmu_info_p->num_sub_queues) {
   8156         mmu_info_p->base_sub_queue = mmu_info_p->num_base_queues;
   8157         mmu_info_p->sub_qlist.bits  = _bcm_kt_cosq_alloc_clear(
   8158              SHR_BITALLOCSIZE(mmu_info_p->num_sub_queues),
   8159              "sub_qlist");
   8160         if (mmu_info_p->sub_qlist.bits == NULL) {
   8161             _bcm_kt_cosq_free_memory(mmu_info_p);
   8162             return BCM_E_MEMORY;
   8163         }
   8164 
   8165         mmu_info_p->l2_sub_qlist.bits = _bcm_kt_cosq_alloc_clear(
   8166                  SHR_BITALLOCSIZE
   8167                  (mmu_info_p->num_sub_queues),
   8168                  "l2_sub_qlist");
   8169 
   8170         if (mmu_info_p->l2_sub_qlist.bits == NULL) {
   8171              _bcm_kt_cosq_free_memory(mmu_info_p);
   8172              return BCM_E_MEMORY;
   8173         }
   8174 
   8175         BCM_IF_ERROR_RETURN
   8176          (_bcm_kt_node_index_set(&mmu_info_p->l2_ext_qlist,
   8177                                   mmu_info_p->base_sub_queue,
   8178                                   mmu_info_p->num_sub_queues));
   8179         BCM_IF_ERROR_RETURN
   8180          (_bcm_kt_node_index_set(&mmu_info_p->ext_qlist,
   8181                                   mmu_info_p->base_sub_queue,
   8182                                   mmu_info_p->num_sub_queues));
   8183 
   8184     } else {
   8185        mmu_info_p->base_sub_queue = 0;
   8186     }
   8187 
   8188     
   8189     if (!SOC_WARM_BOOT(unit)) {    /* Cold Boot */
   8190         
   8191      for (port=0;port < (si->lb_port+1);port++) {  
   8192          if (!SOC_PBMP_MEMBER((PBMP_ALL(unit)), port)) {
   8193              if (SOC_IS_KATANA(unit)) {
   8194                  continue;
   8195              }
   8196          }
   8197         if (IS_CPU_PORT(unit, port)) {
   8198             BCM_IF_ERROR_RETURN
   8199                 (bcm_kt_cosq_gport_add(unit, port, SOC_CMCS_NUM(unit), 
   8200                                0, &port_sched));
   8201             for (cmc = 0; cmc < SOC_CMCS_NUM(unit); cmc++) {
   8202                 if (NUM_CPU_ARM_COSQ(unit, cmc) == 0) {
   8203                     continue;
   8204                 } 
   8205                 cosq = (NUM_CPU_ARM_COSQ(unit, cmc) + 7) / 8;
   8206                 /* coverity[uninit_use_in_call] */
   8207                 BCM_IF_ERROR_RETURN
   8208                     (bcm_kt_cosq_gport_add(unit, port, cosq, 
   8209                                    BCM_COSQ_GPORT_SCHEDULER, &l0_sched));
   8210                 BCM_IF_ERROR_RETURN
   8211                     (bcm_kt_cosq_gport_attach(unit, l0_sched, port_sched, cmc));  
   8212                 cosq = 0;
   8213                 num_queues = NUM_CPU_ARM_COSQ(unit, cmc);
   8214                 for (i = 0; i < NUM_CPU_ARM_COSQ(unit, cmc); i++) {
   8215                     if (i % 8 == 0) {
   8216                         num_inputs = (num_queues >= 8) ? 8 : num_queues;
   8217                         BCM_IF_ERROR_RETURN
   8218                             (bcm_kt_cosq_gport_add(unit, port, num_inputs, 
   8219                                            BCM_COSQ_GPORT_SCHEDULER, &l1_sched));
   8220                         BCM_IF_ERROR_RETURN
   8221                              (bcm_kt_cosq_gport_attach(unit, l1_sched, l0_sched, cosq));  
   8222                         cosq++;
   8223                         num_queues -= num_inputs;
   8224                     } 
   8225                     BCM_IF_ERROR_RETURN
   8226                         (bcm_kt_cosq_gport_add(unit, port, 1,
   8227                                        BCM_COSQ_GPORT_UCAST_QUEUE_GROUP, &queue));
   8228                     BCM_IF_ERROR_RETURN
   8229                         (bcm_kt_cosq_gport_attach(unit, queue, l1_sched, (i % 8)));  
   8230 
   8231                 }
   8232             } 
   8233         } else {
   8234             if (!soc_feature(unit, soc_feature_dynamic_sched_update)) {
   8235                 BCM_IF_ERROR_RETURN
   8236                     (bcm_kt_cosq_gport_add(unit, port, 1, 0, &port_sched));
   8237                 /* coverity[uninit_use_in_call] */
   8238                 BCM_IF_ERROR_RETURN
   8239                     (bcm_kt_cosq_gport_add(unit, port, 1, BCM_COSQ_GPORT_SCHEDULER, 
   8240                                               &l0_sched));
   8241                 BCM_IF_ERROR_RETURN
   8242                     (bcm_kt_cosq_gport_attach(unit, l0_sched, port_sched, 0));  
   8243                 BCM_IF_ERROR_RETURN
   8244                     (bcm_kt_cosq_gport_add(unit, port, numq, BCM_COSQ_GPORT_SCHEDULER, 
   8245                                               &l1_sched));
   8246                 BCM_IF_ERROR_RETURN
   8247                     (bcm_kt_cosq_gport_attach(unit, l1_sched, l0_sched, 0));  
   8248                 for (cosq = 0; cosq < numq; cosq++) {
   8249                     BCM_IF_ERROR_RETURN
   8250                         (bcm_kt_cosq_gport_add(unit, port, 1,
   8251                                        BCM_COSQ_GPORT_UCAST_QUEUE_GROUP, &queue));
   8252                     BCM_IF_ERROR_RETURN
   8253                          (bcm_kt_cosq_gport_attach(unit, queue, l1_sched, cosq));  
   8254 
   8255                 }
   8256            } else {    
   8257                BCM_IF_ERROR_RETURN
   8258                    (_bcm_kt_cosq_dynamic_hierarchy_create(unit, port, numq));
   8259            }
   8260         }
   8261     }
   8262     
   8263    }
   8264 
   8265    if (!cosq_sync_lock[unit]) {
   8266         cosq_sync_lock[unit] = sal_mutex_create("KT cosq sync lock");
   8267         if (cosq_sync_lock[unit] == NULL) {
   8268             return BCM_E_MEMORY;
   8269         }
   8270     }
   8271 
   8272     /* Add default entries for PORT_COS_MAP memory profile */
   8273     BCM_IF_ERROR_RETURN(bcm_kt_cosq_config_set(unit, numq));
   8274 
   8275 #ifdef BCM_WARM_BOOT_SUPPORT
   8276     if (SOC_WARM_BOOT(unit)) {
   8277         return bcm_kt_cosq_reinit(unit);
   8278     } else {
   8279         BCM_IF_ERROR_RETURN(_bcm_kt_cosq_wb_alloc(unit));
   8280     }
   8281 #endif /* BCM_WARM_BOOT_SUPPORT */
   8282 
   8283     
   8284     sal_memset(&entry_tcp_green, 0, sizeof(entry_tcp_green));
   8285     sal_memset(&entry_tcp_yellow, 0, sizeof(entry_tcp_yellow));
   8286     sal_memset(&entry_tcp_red, 0, sizeof(entry_tcp_red));
   8287     sal_memset(&entry_nontcp_green, 0, sizeof(entry_nontcp_green));
   8288     sal_memset(&entry_nontcp_yellow, 0, sizeof(entry_nontcp_yellow));
   8289     sal_memset(&entry_nontcp_red, 0, sizeof(entry_nontcp_red));
   8290     entries[0] = &entry_tcp_green;
   8291     entries[1] = &entry_tcp_yellow;
   8292     entries[2] = &entry_tcp_red;
   8293     entries[3] = &entry_nontcp_green;
   8294     entries[4] = &entry_nontcp_yellow;
   8295     entries[5] = &entry_nontcp_red;
   8296     max_threshold = (1 << soc_mem_field_length(unit, MMU_WRED_DROP_CURVE_PROFILE_0m, 
   8297                      MAX_THDf)) - 1;
   8298     min_threshold = (1 << soc_mem_field_length(unit, MMU_WRED_DROP_CURVE_PROFILE_0m, 
   8299                      MIN_THDf)) - 1;    
   8300     for (i = 0; i < 6; i++) {
   8301         soc_mem_field32_set(unit, wred_mems[i], entries[i], MIN_THDf,
   8302                             max_threshold);
   8303         soc_mem_field32_set(unit, wred_mems[i], entries[i], MAX_THDf,
   8304                             min_threshold);
   8305     }    
   8306     profile_index = 0xffffffff;
   8307     for (port=0;port < (si->lb_port+1);port++) {  
   8308         if (!SOC_PBMP_MEMBER((PBMP_ALL(unit)), port)) {
   8309             if (SOC_IS_KATANA(unit)) {
   8310                 continue;
   8311             }
   8312         }
   8313         BCM_IF_ERROR_RETURN
   8314             (_bcm_kt_cosq_index_resolve(unit, port, -1,
   8315                                         _BCM_KT_COSQ_INDEX_STYLE_WRED, NULL,
   8316                                         NULL, &numq));
   8317         for (cosq = 0; cosq < numq; cosq++) {
   8318             if (profile_index == 0xffffffff) {
   8319                 BCM_IF_ERROR_RETURN
   8320                     (soc_profile_mem_add(unit, _bcm_kt_wred_profile[unit],
   8321                                          entries, 1, &profile_index));
   8322             } else {
   8323                 BCM_IF_ERROR_RETURN
   8324                     (soc_profile_mem_reference(unit,
   8325                                                _bcm_kt_wred_profile[unit],
   8326                                                profile_index, 0));
   8327             }
   8328         }
   8329     }
   8330     /*
   8331      * Set all CPU queues to disable enqueue.  Enqueue will be enabled when
   8332      * RX DMA is enabled. This is to prevent packets from getting wedged in
   8333      * the CMIC when they don't have a means of egressing from the CMIC.
   8334      */
   8335     if (!(SAL_BOOT_SIMULATION) && !SOC_IS_RCPU_ONLY(unit)) {
   8336         for (i = 0; i < NUM_CPU_COSQ(unit); i++) {
   8337             rval = 0;
   8338             soc_reg_field_set(unit, TOQ_QUEUE_FLUSH0r, &rval, Q_FLUSH_ID0f, i);
   8339             soc_reg_field_set(unit, TOQ_QUEUE_FLUSH0r, &rval, Q_FLUSH_NUMf, 1);
   8340             if (SOC_PBMP_MEMBER (PBMP_EXT_MEM (unit), CMIC_PORT(unit))) {
   8341                 soc_reg_field_set(unit, TOQ_QUEUE_FLUSH0r, &rval, Q_FLUSH_EXTERNALf, 1);
   8342             }
   8343             soc_reg_field_set(unit,
   8344                 TOQ_QUEUE_FLUSH0r, &rval, Q_FLUSH_ACTIVEf, 1);
   8345             SOC_IF_ERROR_RETURN(WRITE_TOQ_QUEUE_FLUSH0r(unit, rval));
   8346             while (rval) {
   8347                 SOC_IF_ERROR_RETURN(READ_TOQ_QUEUE_FLUSH0r(unit, &rval));
   8348                 rval = soc_reg_field_get(unit,
   8349                            TOQ_QUEUE_FLUSH0r, rval, Q_FLUSH_ACTIVEf);
   8350             }
   8351             rval = 0;
   8352             soc_reg_field_set(unit, TOQ_ERRORr, &rval, FLUSH_COMPLETEf, 1); /* w1tc */
   8353             SOC_IF_ERROR_RETURN(WRITE_TOQ_ERRORr(unit, rval));
   8354         }
   8355     }
   8356     return BCM_E_NONE;
   8357 }
   8358 
   8359 /*
   8360  * Function:
   8361  *     bcm_kt_cosq_detach
   8362  * Purpose:
   8363  *     Discard all COS schedule/mapping state.
   8364  * Parameters:
   8365  *     unit - unit number
   8366  * Returns:
   8367  *     BCM_E_XXX
   8368  */
   8369 int
   8370 bcm_kt_cosq_detach(int unit, int software_state_only)
   8371 {
   8372    if (cosq_sync_lock[unit]) {
   8373         sal_mutex_destroy(cosq_sync_lock[unit]);
   8374         cosq_sync_lock[unit] = NULL;
   8375     }
   8376 
   8377     return BCM_E_NONE;
   8378 }
   8379 
   8380 /*
   8381  * Function:
   8382  *     bcm_kt_cosq_config_set
   8383  * Purpose:
   8384  *     Set the number of COS queues
   8385  * Parameters:
   8386  *     unit - unit number
   8387  *     numq - number of COS queues (1-8).
   8388  * Returns:
   8389  *     BCM_E_XXX
   8390  */
   8391 int
   8392 bcm_kt_cosq_config_set(int unit, int numq)
   8393 {
   8394     port_cos_map_entry_t cos_map_entries[16];
   8395     void *entries[1], *hg_entries[1];
   8396     uint32 index, hg_index;
   8397     int count, hg_count;
   8398     bcm_port_t port;
   8399     int cos, prio;
   8400     uint32 i;
   8401     int cpu_hg_index = 0, ref_count;
   8402 #ifdef BCM_COSQ_HIGIG_MAP_DISABLE
   8403     port_cos_map_entry_t hg_cos_map_entries[16];
   8404 #endif
   8405 
   8406     if (numq < 1 || numq > 8) {
   8407         return BCM_E_PARAM;
   8408     }
   8409 
   8410     /* clear out old profiles. */
   8411     index = 0;
   8412     while (index < soc_mem_index_count(unit, PORT_COS_MAPm)) {
   8413         BCM_IF_ERROR_RETURN(soc_profile_mem_ref_count_get(unit,
   8414                                       _bcm_kt_cos_map_profile[unit],
   8415                                       index, &ref_count));
   8416         if (ref_count > 0) {
   8417             while (ref_count) {
   8418                 BCM_IF_ERROR_RETURN(soc_profile_mem_delete(unit,
   8419                                         _bcm_kt_cos_map_profile[unit], index));
   8420                 ref_count -= 1;
   8421             }
   8422         }
   8423         index += 16;
   8424     }
   8425 
   8426     /* Distribute first 8 internal priority levels into the specified number
   8427      * of cosq, map remaining internal priority levels to highest priority
   8428      * cosq */
   8429     sal_memset(cos_map_entries, 0, sizeof(cos_map_entries));
   8430     entries[0] = &cos_map_entries;
   8431     hg_entries[0] = &cos_map_entries;
   8432     prio = 0;
   8433     for (cos = 0; cos < numq; cos++) {
   8434         for (i = 8 / numq + (cos < 8 % numq ? 1 : 0); i > 0; i--) {
   8435             soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio],
   8436                                 COSf, cos);
   8437             prio++;
   8438         }
   8439     }
   8440     for (prio = 8; prio < 16; prio++) {
   8441         soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio], COSf,
   8442                             numq - 1);
   8443     }
   8444 
   8445     /* Map internal priority levels to CPU CoS queues */
   8446     BCM_IF_ERROR_RETURN(_bcm_esw_cpu_cosq_mapping_default_set(unit, numq));
   8447 
   8448 #ifdef BCM_COSQ_HIGIG_MAP_DISABLE
   8449     /* Use identical mapping for Higig port */
   8450     sal_memset(hg_cos_map_entries, 0, sizeof(hg_cos_map_entries));
   8451     hg_entries[0] = &hg_cos_map_entries;
   8452     prio = 0;
   8453     for (prio = 0; prio < 8; prio++) {
   8454         soc_mem_field32_set(unit, PORT_COS_MAPm, &hg_cos_map_entries[prio],
   8455                             COSf, prio);
   8456     }
   8457     for (prio = 8; prio < 16; prio++) {
   8458         soc_mem_field32_set(unit, PORT_COS_MAPm, &hg_cos_map_entries[prio],
   8459                             COSf, 7);
   8460     }
   8461 
   8462 #endif /* BCM_COSQ_HIGIG_MAP_DISABLE */
   8463 
   8464     BCM_IF_ERROR_RETURN
   8465         (soc_profile_mem_add(unit, _bcm_kt_cos_map_profile[unit], entries, 16,
   8466                              &index));
   8467     BCM_IF_ERROR_RETURN
   8468         (soc_profile_mem_add(unit, _bcm_kt_cos_map_profile[unit], hg_entries,
   8469                              16, &hg_index));
   8470     count = 0;
   8471     hg_count = 0;
   8472     PBMP_ALL_ITER(unit, port) {
   8473         if (IS_HG_PORT(unit, port)) {
   8474             BCM_IF_ERROR_RETURN
   8475                 (soc_mem_field32_modify(unit, COS_MAP_SELm, port, SELECTf,
   8476                                         hg_index / 16));
   8477             hg_count++;
   8478         } else {
   8479             BCM_IF_ERROR_RETURN
   8480                 (soc_mem_field32_modify(unit, COS_MAP_SELm, port, SELECTf,
   8481                                         index / 16));
   8482             count++;
   8483         }
   8484     }
   8485 
   8486     cpu_hg_index = SOC_IS_KATANA2(unit) ?
   8487                    SOC_INFO(unit).cpu_hg_pp_port_index :
   8488                    SOC_INFO(unit).cpu_hg_index;
   8489     if (cpu_hg_index != -1) {
   8490         BCM_IF_ERROR_RETURN
   8491             (soc_mem_field32_modify(unit, COS_MAP_SELm,
   8492                                     cpu_hg_index, SELECTf,
   8493                                     hg_index / 16));
   8494         hg_count++;
   8495     }
   8496 
   8497 
   8498     for (i = 1; i < count; i++) {
   8499         soc_profile_mem_reference(unit, _bcm_kt_cos_map_profile[unit], index,
   8500                                   0);
   8501     }
   8502     for (i = 1; i < hg_count; i++) {
   8503         soc_profile_mem_reference(unit, _bcm_kt_cos_map_profile[unit],
   8504                                   hg_index, 0);
   8505     }
   8506 
   8507     _bcm_kt_num_cosq[unit] = numq;
   8508 
   8509     return BCM_E_NONE;
   8510 }
   8511 
   8512 
   8513 /*
   8514  * Function:
   8515  *     bcm_kt_cosq_config_get
   8516  * Purpose:
   8517  *     Get the number of cos queues
   8518  * Parameters:
   8519  *     unit - unit number
   8520  *     numq - (Output) number of cosq
   8521  * Returns:
   8522  *     BCM_E_XXX
   8523  */
   8524 int
   8525 bcm_kt_cosq_config_get(int unit, int *numq)
   8526 {
   8527     if (_bcm_kt_num_cosq[unit] == 0) {
   8528         return BCM_E_INIT;
   8529     }
   8530 
   8531     if (numq != NULL) {
   8532         *numq = _bcm_kt_num_cosq[unit];
   8533     }
   8534 
   8535     return BCM_E_NONE;
   8536 }
   8537 
   8538 /*
   8539  * Function:
   8540  *     bcm_kt_cosq_gport_attach
   8541  * Purpose:
   8542  *     Attach sched_port to the specified index (cosq) of input_port
   8543  * Parameters:
   8544  *     unit       - (IN) unit number
   8545  *     sched_port - (IN) scheduler GPORT identifier
   8546  *     input_port - (IN) GPORT to attach to
   8547  *     cosq       - (IN) COS queue to attach to (-1 for first available cosq)
   8548  * Returns:
   8549  *     BCM_E_XXX
   8550  */
   8551 int
   8552 bcm_kt_cosq_gport_attach(int unit, bcm_gport_t sched_gport,
   8553                          bcm_gport_t input_gport, bcm_cos_queue_t cosq)
   8554 {
   8555     _bcm_kt_cosq_node_t *sched_node, *input_node, *temp_parent, *temp_sibling;
   8556     bcm_port_t sched_port, input_port, local_port;
   8557     int rv, max_nodes;
   8558     int status = 0;
   8559 
   8560     if (_bcm_kt_mmu_info[unit] == NULL) {
   8561         return BCM_E_INIT;
   8562     }
   8563 
   8564     if ((BCM_GPORT_IS_UCAST_QUEUE_GROUP(input_gport)) ||
   8565         (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(input_gport))) {
   8566         return BCM_E_PORT;
   8567     }
   8568 
   8569     if(!(BCM_GPORT_IS_UCAST_QUEUE_GROUP(sched_gport) ||
   8570          BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(sched_gport) ||
   8571          BCM_GPORT_IS_SCHEDULER(sched_gport))) {
   8572         return BCM_E_PORT;
   8573      }
   8574 
   8575     if (cosq < -1) {
   8576         return BCM_E_PARAM;
   8577     }
   8578 
   8579     BCM_IF_ERROR_RETURN
   8580         (_bcm_kt_cosq_node_get(unit, sched_gport, NULL, &sched_port, NULL,
   8581                                &sched_node));
   8582 
   8583     if (sched_node->cosq_attached_to >= 0) {
   8584         /* Has already attached */
   8585         return BCM_E_EXISTS;
   8586     }
   8587 
   8588     if (BCM_GPORT_IS_SCHEDULER(input_gport) ||
   8589         BCM_GPORT_IS_LOCAL(input_gport) ||
   8590         BCM_GPORT_IS_MODPORT(input_gport)) {
   8591         BCM_IF_ERROR_RETURN
   8592             (_bcm_kt_cosq_node_get(unit, input_gport, NULL, &input_port, NULL,
   8593                                    &input_node));
   8594     } else {
   8595         BCM_IF_ERROR_RETURN
   8596             (_bcm_kt_cosq_localport_resolve(unit, input_gport, &input_port));
   8597         input_node = NULL;
   8598     }
   8599 
   8600     if (sched_port != input_port) {
   8601         return BCM_E_PORT;
   8602     }
   8603 
   8604       /* Identify the levels of schedulers
   8605        * input_port == phy_port && sched_gport == scheduler => sched_gport = L0
   8606        * input_port == schduler && sched_gport == scheduler => input_port = L0 and sched_port = L1
   8607        * input_port == scheduler && sched_port == queue_group => input_port = L1 and sched_port = L2
   8608        */
   8609     if (input_node != NULL) {
   8610         if (!BCM_GPORT_IS_SCHEDULER(input_gport)) {
   8611             if (input_node->numq == 0) {
   8612                 local_port = (BCM_GPORT_IS_LOCAL(input_gport)) ?
   8613                               BCM_GPORT_LOCAL_GET(input_gport) :
   8614                               BCM_GPORT_MODPORT_PORT_GET(input_gport);
   8615                 input_node->gport = input_gport;
   8616                 input_node->hw_index = local_port;
   8617                 input_node->level = _BCM_KT_COSQ_NODE_LEVEL_ROOT;
   8618                 input_node->cosq_attached_to = 0;
   8619                 input_node->numq = 4; /* Assign max of 4 L0 nodes */
   8620                 input_node->base_index = -1;
   8621             }
   8622 
   8623             if (!BCM_GPORT_IS_SCHEDULER(sched_gport)) {
   8624                 return BCM_E_PARAM;
   8625             }
   8626 
   8627             sched_node->level = _BCM_KT_COSQ_NODE_LEVEL_L0;
   8628         } else {
   8629              if (input_node->level == _BCM_KT_COSQ_NODE_LEVEL_ROOT) {
   8630                  /* Don't allow non-scheduler node (queues) to be attached to port */ 
   8631                  if (!BCM_GPORT_IS_SCHEDULER(sched_gport)) {
   8632                      return BCM_E_PARAM;
   8633                  }
   8634                  sched_node->level = _BCM_KT_COSQ_NODE_LEVEL_L0;
   8635                  BCM_IF_ERROR_RETURN
   8636                      (_bcm_kt_cosq_max_nodes_get(unit, sched_node->level, &max_nodes));
   8637                  if (input_node->numq == -1) {
   8638                      input_node->numq = max_nodes;
   8639                  } else {
   8640                      if (input_node->numq > max_nodes) {
   8641                          return BCM_E_PARAM;
   8642                      }
   8643                  }
   8644              }
   8645              if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(sched_gport) ||
   8646                 BCM_GPORT_IS_MCAST_QUEUE_GROUP(sched_gport) ||
   8647                 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(sched_gport) ||
   8648                 BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(sched_gport)) {
   8649                 if (!BCM_GPORT_IS_SCHEDULER(input_gport)) {
   8650                     return BCM_E_PARAM;
   8651                 }
   8652                 if (input_node->level != _BCM_KT_COSQ_NODE_LEVEL_L1) {
   8653                     return BCM_E_PARAM;
   8654                 }
   8655             }
   8656 
   8657              if ((input_node->level == -1)) {
   8658                 input_node->level = (BCM_GPORT_IS_SCHEDULER(sched_gport)) ?
   8659                                      _BCM_KT_COSQ_NODE_LEVEL_L0 : _BCM_KT_COSQ_NODE_LEVEL_L1;
   8660              }
   8661 
   8662              if (sched_node->level == -1) {
   8663                  sched_node->level = (BCM_GPORT_IS_UCAST_QUEUE_GROUP(sched_gport) ||
   8664                                       BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(sched_gport)) ?
   8665                                       _BCM_KT_COSQ_NODE_LEVEL_L2 : _BCM_KT_COSQ_NODE_LEVEL_L1;
   8666                  BCM_IF_ERROR_RETURN
   8667                      (_bcm_kt_cosq_max_nodes_get(unit, sched_node->level, &max_nodes));
   8668                  if (input_node->numq == -1) {
   8669                      input_node->numq = max_nodes;
   8670                  } else {
   8671                      if (input_node->numq > max_nodes) {
   8672                          return BCM_E_PARAM;
   8673                      }
   8674                  }
   8675              }
   8676         }
   8677 
   8678         if (input_node->cosq_attached_to < 0) {
   8679             /* Only allow to attach to a node that has already attached */
   8680             return BCM_E_PARAM;
   8681         }
   8682         if (cosq < -1 || (input_node->numq != -1 && cosq >= input_node->numq)) {
   8683             return BCM_E_PARAM;
   8684         }
   8685     }
   8686 
   8687     if (BCM_GPORT_IS_SCHEDULER(input_gport) || BCM_GPORT_IS_LOCAL(input_gport) ||
   8688         BCM_GPORT_IS_MODPORT(input_gport)) {
   8689         if (input_node->cosq_attached_to < 0) {
   8690             /* dont allow to attach to a node that has already attached */
   8691             return BCM_E_PARAM;
   8692         }
   8693         temp_parent = sched_node->parent;
   8694         temp_sibling = sched_node->sibling;
   8695 
   8696         sched_node->parent = input_node;
   8697         sched_node->sibling = input_node->child;
   8698         input_node->child = sched_node;
   8699         /* resolve the nodes */
   8700         rv = _bcm_kt_cosq_node_resolve(unit, sched_node, cosq);
   8701         if (BCM_FAILURE(rv)) {
   8702             input_node->child = sched_node->sibling;
   8703             sched_node->parent = temp_parent;
   8704             sched_node->sibling = temp_sibling;
   8705             sched_node->cosq_attached_to = -1;
   8706             return rv;
   8707         }
   8708         /* Protect LLS hierachy change as
   8709          * port flush on link flap might be effected
   8710          * when there is changed in the LLS hierarchy
   8711          */
   8712         SOC_LLS_SCHEDULER_LOCK(unit);
   8713         soc_kt_port_flush_state_get(unit, input_port, &status); 
   8714         if (status) {
   8715             LOG_ERROR(BSL_LS_BCM_COSQ,
   8716              (BSL_META_U(unit,
   8717              "Unit %d Port %d is in flush state, Cannot change LLS hierarchy."
   8718              "\n Attach of Cosq hw_cosq=%d failed.\n"),
   8719             unit, input_port, sched_node->cosq_attached_to));
   8720             input_node->child = sched_node->sibling;
   8721             SOC_LLS_SCHEDULER_UNLOCK(unit);  
   8722             return BCM_E_RESOURCE;
   8723         }
   8724         rv = _bcm_kt_cosq_sched_node_set(unit, sched_gport, 
   8725                             _BCM_KT_COSQ_STATE_ENABLE);
   8726         SOC_LLS_SCHEDULER_UNLOCK(unit);
   8727         if (BCM_FAILURE(rv)) {
   8728             return rv;
   8729         }
   8730         LOG_INFO(BSL_LS_BCM_COSQ,
   8731                  (BSL_META_U(unit,
   8732                              "                         hw_cosq=%d\n"),
   8733                   sched_node->cosq_attached_to));
   8734     } else {
   8735             return BCM_E_PORT;
   8736     }
   8737 
   8738     return BCM_E_NONE;
   8739 }
   8740 
   8741 /*
   8742  * Function:
   8743  *     bcm_kt_cosq_gport_detach
   8744  * Purpose:
   8745  *     Detach sched_port to the specified index (cosq) of input_port
   8746  * Parameters:
   8747  *     unit       - (IN) unit number
   8748  *     sched_port - (IN) scheduler GPORT identifier
   8749  *     input_port - (IN) GPORT to attach to
   8750  *     cosq       - (IN) COS queue to attach to (-1 for first available cosq)
   8751  * Returns:
   8752  *     BCM_E_XXX
   8753  */
   8754 int
   8755 bcm_kt_cosq_gport_detach(int unit, bcm_gport_t sched_gport,
   8756                          bcm_gport_t input_gport, bcm_cos_queue_t cosq)
   8757 {
   8758     _bcm_kt_cosq_node_t *sched_node, *input_node, *prev_node;
   8759     bcm_port_t sched_port, input_port;
   8760     int rv; 
   8761     int status = 0; 
   8762 
   8763     if (_bcm_kt_mmu_info[unit] == NULL) {
   8764         return BCM_E_INIT;
   8765     }
   8766 
   8767     if ((BCM_GPORT_IS_UCAST_QUEUE_GROUP(input_gport)) ||
   8768         (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(input_gport))) {
   8769         return BCM_E_PORT;
   8770     }
   8771 
   8772     BCM_IF_ERROR_RETURN
   8773         (_bcm_kt_cosq_node_get(unit, sched_gport, NULL, &sched_port, NULL,
   8774                                &sched_node));
   8775 
   8776     if (sched_node->cosq_attached_to < 0) {
   8777         /* Not attached yet */
   8778         return BCM_E_PORT;
   8779     }
   8780 
   8781     if (input_gport != BCM_GPORT_INVALID) {
   8782 
   8783         if (BCM_GPORT_IS_SCHEDULER(input_gport) ||
   8784             BCM_GPORT_IS_LOCAL(input_gport) ||
   8785             BCM_GPORT_IS_MODPORT(input_gport)) {
   8786                BCM_IF_ERROR_RETURN
   8787                 (_bcm_kt_cosq_node_get(unit, input_gport, NULL, &input_port, NULL,
   8788                                        &input_node));
   8789 
   8790         }
   8791         else {
   8792 
   8793             if (!(BCM_GPORT_IS_SCHEDULER(sched_gport) ||
   8794                   BCM_GPORT_IS_UCAST_QUEUE_GROUP(sched_gport) ||
   8795                   BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(sched_gport))) {
   8796                 return BCM_E_PARAM;
   8797             }
   8798             else {
   8799                 BCM_IF_ERROR_RETURN
   8800                 (_bcm_kt_cosq_localport_resolve(unit, input_gport,
   8801                                                 &input_port));
   8802                 input_node = NULL;
   8803             }
   8804         }
   8805     }
   8806 
   8807     if (sched_port != input_port) {
   8808         return BCM_E_PORT;
   8809     }
   8810 
   8811     if (sched_node->parent != input_node) {
   8812         return BCM_E_PORT;
   8813     }
   8814 
   8815     if (cosq < -1 || (input_node->numq != -1 && cosq >= input_node->numq)) {
   8816         return BCM_E_PARAM;
   8817     }    
   8818 
   8819     if (cosq != -1) {
   8820         if (sched_node->cosq_attached_to != cosq) {
   8821             return BCM_E_PARAM;
   8822         }
   8823     }
   8824     /* Update the hw accordingly
   8825      * Protect LLS hierachy change as
   8826      * port flush on link flap might be effected
   8827      * when there is a change in the LLS hierarchy
   8828      */
   8829     SOC_LLS_SCHEDULER_LOCK(unit);
   8830     soc_kt_port_flush_state_get(unit, input_port, &status);
   8831     if (status) {
   8832         LOG_ERROR(BSL_LS_BCM_COSQ,
   8833              (BSL_META_U(unit,
   8834         " Unit %d Port %d is in flush state, Cannot change LLS hierarchy."
   8835          "\n Detach of Cosq hw_cosq=%d failed.\n"),
   8836             unit, input_port, sched_node->cosq_attached_to));  
   8837         SOC_LLS_SCHEDULER_UNLOCK(unit);
   8838         return BCM_E_RESOURCE;
   8839     }
   8840 
   8841     rv = _bcm_kt_cosq_sched_node_set(unit, sched_gport,
   8842                                      _BCM_KT_COSQ_STATE_DISABLE);
   8843     SOC_LLS_SCHEDULER_UNLOCK(unit);
   8844     if (BCM_FAILURE(rv)) {
   8845        return rv;
   8846     }
   8847     /* unresolve the node - delete this node from parent's child list */
   8848     BCM_IF_ERROR_RETURN
   8849         (_bcm_kt_cosq_node_unresolve(unit, sched_node, cosq));
   8850 
   8851     /* now remove from the sw tree */
   8852     if (sched_node->parent != NULL) {
   8853         if (sched_node->parent->child == sched_node) {
   8854             sched_node->parent->child = sched_node->sibling;
   8855         } else {
   8856             prev_node = sched_node->parent->child;
   8857             while (prev_node != NULL && prev_node->sibling != sched_node) {
   8858                 prev_node = prev_node->sibling;
   8859             }
   8860             if (prev_node == NULL) {
   8861                 return BCM_E_INTERNAL;
   8862             }
   8863             prev_node->sibling = sched_node->sibling;
   8864        }
   8865         sched_node->parent = NULL;
   8866         sched_node->sibling = NULL;
   8867         sched_node->wrr_in_use = 0;
   8868         sched_node->cosq_attached_to = -1;
   8869         if (sched_node->type !=
   8870              _BCM_KT_NODE_SUBSCRIBER_GPORT_ID) {
   8871             sched_node->hw_index = -1;
   8872         }
   8873      }
   8874 
   8875       LOG_INFO(BSL_LS_BCM_COSQ,
   8876                (BSL_META_U(unit,
   8877                            "                         hw_cosq=%d\n"),
   8878                 sched_node->cosq_attached_to));
   8879 
   8880     return BCM_E_NONE;
   8881 }
   8882 
   8883 /*
   8884  * Function:
   8885  *     bcm_kt_cosq_gport_attach_get
   8886  * Purpose:
   8887  *     Get attached status of a scheduler port
   8888  * Parameters:
   8889  *     unit       - (IN) unit number
   8890  *     sched_port - (IN) scheduler GPORT identifier
   8891  *     input_port - (OUT) GPORT to attach to
   8892  *     cosq       - (OUT) COS queue to attached to
   8893  * Returns:
   8894  *     BCM_E_XXX
   8895  * Notes:
   8896  */
   8897 int
   8898 bcm_kt_cosq_gport_attach_get(int unit, bcm_gport_t sched_gport,
   8899                              bcm_gport_t *input_gport, bcm_cos_queue_t *cosq)
   8900 {
   8901     _bcm_kt_cosq_node_t *sched_node;
   8902     bcm_module_t modid, modid_out;
   8903     bcm_port_t port, port_out;
   8904 
   8905     if (input_gport == NULL || cosq == NULL) {
   8906         return BCM_E_PARAM;
   8907     }
   8908 
   8909     BCM_IF_ERROR_RETURN
   8910         (_bcm_kt_cosq_node_get(unit, sched_gport, &modid, &port, NULL,
   8911                                &sched_node));
   8912 
   8913     if (sched_node->level == _BCM_KT_COSQ_NODE_LEVEL_ROOT) {
   8914         return BCM_E_PARAM;
   8915     }    
   8916     
   8917     if (sched_node->cosq_attached_to < 0) {
   8918         /* Not attached yet */
   8919         return BCM_E_NOT_FOUND;
   8920     }
   8921 
   8922     if (sched_node->parent != NULL) { 
   8923         *input_gport = sched_node->parent->gport;
   8924     } else {  /* sched_node is in L2 level */
   8925         BCM_IF_ERROR_RETURN
   8926             (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, modid, port,
   8927                                     &modid_out, &port_out));
   8928         BCM_GPORT_MODPORT_SET(*input_gport, modid_out, port_out);
   8929     }
   8930     *cosq = sched_node->cosq_attached_to;
   8931 
   8932     return BCM_E_NONE;
   8933 }
   8934 
   8935 STATIC int
   8936 _bcm_kt_cosq_ef_update_war(int unit, bcm_gport_t gport,  bcm_cos_queue_t cosq,
   8937                            int hw_index, lls_l2_parent_entry_t *entry)
   8938 {
   8939     lls_l1_config_entry_t l1_config;
   8940     uint32 min_bw, max_bw, min_burst, max_burst, flags = 0;
   8941     int parent_index, spri_vector;
   8942     uint32 start_pri, vec_3_0 =0, vec_7_4 = 0;
   8943     uint32 rval = 0, bit_offset;
   8944 
   8945     LOG_INFO(BSL_LS_BCM_COSQ,
   8946              (BSL_META_U(unit,
   8947                          "_bcm_kt_cosq_ef_update_war:unit=%d gport=0x%x cosq=%d idx=%d\n"),
   8948               unit, gport, cosq, hw_index));
   8949    
   8950     BCM_IF_ERROR_RETURN
   8951         (_bcm_kt_cosq_bucket_get(unit, gport, cosq, &min_bw, &max_bw,
   8952                                  &min_burst, &max_burst, flags)); 
   8953 
   8954     if ((min_bw == 0) && (max_bw == 0)) {
   8955         SOC_IF_ERROR_RETURN
   8956             (soc_mem_write(unit, LLS_L2_PARENTm, MEM_BLOCK_ALL,
   8957                            hw_index, entry));
   8958     } else {
   8959         parent_index = soc_mem_field32_get(unit, LLS_L2_PARENTm, entry, 
   8960                                            C_PARENTf); 
   8961         SOC_IF_ERROR_RETURN
   8962             (soc_mem_read(unit, LLS_L1_CONFIGm, MEM_BLOCK_ALL, parent_index, 
   8963                           &l1_config));
   8964         if (SOC_IS_KATANA2(unit)) {
   8965             start_pri = soc_mem_field32_get(unit, LLS_L1_CONFIGm, &l1_config, 
   8966                                             P_START_UC_SPRIf); 
   8967         } else {
   8968             start_pri = soc_mem_field32_get(unit, LLS_L1_CONFIGm, &l1_config, 
   8969                                             P_START_SPRIf); 
   8970         }
   8971         vec_3_0 = soc_mem_field32_get(unit, LLS_L1_CONFIGm, &l1_config, 
   8972                                       P_NUM_SPRIf);
   8973         vec_7_4 = soc_mem_field32_get(unit, LLS_L1_CONFIGm, &l1_config, 
   8974                                       P_VECT_SPRI_7_4f);
   8975         spri_vector = vec_3_0 | (vec_7_4 << 4);
   8976         bit_offset = hw_index - start_pri;
   8977         if (bit_offset >= 8) {
   8978             return BCM_E_PARAM;
   8979         }
   8980         LOG_INFO(BSL_LS_BCM_COSQ,
   8981                  (BSL_META_U(unit,
   8982                              "parent=%d spri_vector=0x%x bit_offset=%d\n"),
   8983                   parent_index, spri_vector, bit_offset));
   8984         spri_vector &= ~(1 << bit_offset);
   8985         soc_mem_field32_set(unit, LLS_L1_CONFIGm, &l1_config, P_NUM_SPRIf, 
   8986                             (spri_vector & 0xF));
   8987         soc_mem_field32_set(unit, LLS_L1_CONFIGm, &l1_config, P_VECT_SPRI_7_4f, 
   8988                             ((spri_vector >> 4) & 0xF));
   8989         BCM_IF_ERROR_RETURN
   8990             (_bcm_kt_cosq_bucket_set(unit, gport, cosq, 0, 0,
   8991                                      min_burst, max_burst, flags)); 
   8992         SOC_IF_ERROR_RETURN
   8993             (soc_mem_write(unit, LLS_L2_PARENTm, MEM_BLOCK_ALL,
   8994                            hw_index, entry));
   8995         SOC_IF_ERROR_RETURN
   8996             (soc_mem_write(unit, LLS_L1_CONFIGm, MEM_BLOCK_ALL,
   8997                            parent_index, &l1_config));
   8998 
   8999         soc_reg_field_set(unit, LLS_DEBUG_INJECT_ACTIVATIONr, &rval, 
   9000                           INJECTf, 1);
   9001         /* 0 = enqueue event,1 = shaper event,2 = xon event,3 = xoff event */ 
   9002         soc_reg_field_set(unit, LLS_DEBUG_INJECT_ACTIVATIONr, &rval, 
   9003                           ENTITY_TYPEf, 1);
   9004         /* 0 = port, 1 = level 0, 2 = level 1, 3 = level 2 */
   9005         soc_reg_field_set(unit, LLS_DEBUG_INJECT_ACTIVATIONr, &rval, 
   9006                           ENTITY_LEVELf, 3);
   9007         soc_reg_field_set(unit, LLS_DEBUG_INJECT_ACTIVATIONr, &rval, 
   9008                           ENTITY_IDENTIFIERf, hw_index); 
   9009         SOC_IF_ERROR_RETURN(WRITE_LLS_DEBUG_INJECT_ACTIVATIONr(unit, rval)); 
   9010         spri_vector |= (1 << bit_offset);
   9011         soc_mem_field32_set(unit, LLS_L1_CONFIGm, &l1_config, P_NUM_SPRIf, 
   9012                             (spri_vector & 0xF));
   9013         soc_mem_field32_set(unit, LLS_L1_CONFIGm, &l1_config, P_VECT_SPRI_7_4f, 
   9014                             ((spri_vector >> 4) & 0xF));
   9015         SOC_IF_ERROR_RETURN
   9016             (soc_mem_write(unit, LLS_L1_CONFIGm, MEM_BLOCK_ALL,
   9017                            parent_index, &l1_config));
   9018         BCM_IF_ERROR_RETURN
   9019             (_bcm_kt_cosq_bucket_set(unit, gport, cosq, min_bw, max_bw,
   9020                                      min_burst, max_burst, flags)); 
   9021     }
   9022 
   9023     return BCM_E_NONE;
   9024 }
   9025 
   9026 STATIC int
   9027 _bcm_kt_cosq_valid_ef_node(int unit, lls_l1_config_entry_t *entry, 
   9028                            int hw_index)
   9029 {
   9030     lls_l2_parent_entry_t l2_parent;
   9031     int index, start_pri, spri_vector, num_spri, vec_7_4;
   9032     uint32 bit_offset;
   9033     int i;
   9034 
   9035     if (SOC_IS_KATANA2(unit)) {
   9036         start_pri = soc_mem_field32_get(unit, LLS_L1_CONFIGm, entry, 
   9037                                         P_START_UC_SPRIf); 
   9038     } else {
   9039         start_pri = soc_mem_field32_get(unit, LLS_L1_CONFIGm, entry, 
   9040                                         P_START_SPRIf); 
   9041     }
   9042     num_spri = soc_mem_field32_get(unit, LLS_L1_CONFIGm, entry, 
   9043                                    P_NUM_SPRIf);
   9044     if (soc_feature(unit, soc_feature_vector_based_spri)) {
   9045         vec_7_4 = soc_mem_field32_get(unit, LLS_L1_CONFIGm, entry, 
   9046                                       P_VECT_SPRI_7_4f);
   9047         spri_vector = num_spri | (vec_7_4 << 4);
   9048         bit_offset = hw_index - start_pri;
   9049         if (bit_offset >= 8) {
   9050             return BCM_E_PARAM;
   9051         }
   9052         if (!(spri_vector & (1 << bit_offset))) {
   9053             /* werr node cannot be EF */
   9054             return BCM_E_PARAM;
   9055         }
   9056         for (i = 0; i < 8; i++) {
   9057             if (spri_vector & (1 << i)) {
   9058                 index = start_pri + i;
   9059                 SOC_IF_ERROR_RETURN
   9060                      (soc_mem_read(unit, LLS_L2_PARENTm, MEM_BLOCK_ALL,
   9061                                    index, &l2_parent));
   9062                 if (soc_mem_field32_get(unit, LLS_L2_PARENTm, 
   9063                                         &l2_parent, C_EFf) == 1) {
   9064                     /* maximum of 1 EF node is supported */
   9065                     return FALSE;
   9066                 }
   9067             }
   9068         }
   9069     } else {
   9070         if ((hw_index < start_pri) || (hw_index >= (start_pri + num_spri))) {
   9071             /* werr node cannot be EF */
   9072             return BCM_E_PARAM;
   9073         } 
   9074         for (i = start_pri; i < (start_pri + num_spri); i++) {
   9075             SOC_IF_ERROR_RETURN
   9076                 (soc_mem_read(unit, LLS_L2_PARENTm, MEM_BLOCK_ALL,
   9077                               i, &l2_parent));
   9078             if (soc_mem_field32_get(unit, LLS_L2_PARENTm,
   9079                                     &l2_parent, C_EFf) == 1) {
   9080                 /* maximum of 1 EF node is supported */
   9081                 return FALSE;
   9082             }
   9083         }
   9084     }
   9085    
   9086     return TRUE;
   9087 }
   9088 
   9089 STATIC int
   9090 _bcm_kt_cosq_ef_op_at_index(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
   9091                             int hw_index, _bcm_cosq_op_t op, int *ef_val)
   9092 {
   9093     lls_l2_parent_entry_t entry;
   9094     lls_l1_parent_entry_t l1_entry;
   9095     lls_l1_config_entry_t l1_config;
   9096     lls_l0_config_entry_t l0_config;
   9097     uint32 current_ef = 0, set_ef = 0;
   9098     uint32 index;
   9099 
   9100     SOC_IF_ERROR_RETURN
   9101         (soc_mem_read(unit, LLS_L2_PARENTm, MEM_BLOCK_ALL, hw_index, &entry));
   9102 
   9103     if (op == _BCM_COSQ_OP_GET) {
   9104         *ef_val = soc_mem_field32_get(unit, LLS_L2_PARENTm, &entry, C_EFf);
   9105     } else {
   9106         current_ef = soc_mem_field32_get(unit, LLS_L2_PARENTm, &entry, C_EFf);
   9107         set_ef = (*ef_val != 0) ? 1 : 0;
   9108         soc_mem_field32_set(unit, LLS_L2_PARENTm, &entry, C_EFf, set_ef);
   9109         if ((current_ef == 0) && (set_ef == 1)) {
   9110             index = soc_mem_field32_get(unit, LLS_L2_PARENTm, &entry, 
   9111                                         C_PARENTf); 
   9112             SOC_IF_ERROR_RETURN
   9113                 (soc_mem_read(unit, LLS_L1_CONFIGm, MEM_BLOCK_ALL, 
   9114                               index, &l1_config));
   9115             if (_bcm_kt_cosq_valid_ef_node(unit, &l1_config, 
   9116                                            hw_index) != TRUE) {
   9117                  return BCM_E_PARAM;
   9118             }  
   9119             soc_mem_field32_set(unit, LLS_L1_CONFIGm, &l1_config, 
   9120                                 P_CFG_EF_PROPAGATEf, set_ef);
   9121             SOC_IF_ERROR_RETURN
   9122                 (soc_mem_write(unit, LLS_L1_CONFIGm, MEM_BLOCK_ALL,
   9123                                index, &l1_config));
   9124             SOC_IF_ERROR_RETURN
   9125                 (soc_mem_read(unit, LLS_L1_PARENTm, MEM_BLOCK_ALL, 
   9126                               index, &l1_entry));
   9127             index = soc_mem_field32_get(unit, LLS_L1_PARENTm, &l1_entry, 
   9128                                         C_PARENTf); 
   9129             SOC_IF_ERROR_RETURN
   9130                 (soc_mem_read(unit, LLS_L0_CONFIGm, MEM_BLOCK_ALL, 
   9131                               index, &l0_config));
   9132             soc_mem_field32_set(unit, LLS_L0_CONFIGm, &l0_config, 
   9133                                 P_CFG_EF_PROPAGATEf, set_ef);
   9134             SOC_IF_ERROR_RETURN
   9135                 (soc_mem_write(unit, LLS_L0_CONFIGm, MEM_BLOCK_ALL,
   9136                                index, &l0_config));
   9137             SOC_IF_ERROR_RETURN
   9138                 (soc_mem_write(unit, LLS_L2_PARENTm, MEM_BLOCK_ALL,
   9139                                hw_index, &entry));
   9140         } else if ((current_ef == 1) && (set_ef == 0)) {
   9141             if (soc_feature(unit, soc_feature_vector_based_spri)) {
   9142                 return _bcm_kt_cosq_ef_update_war(unit, gport, cosq, 
   9143                                                   hw_index, &entry);
   9144             }  
   9145             SOC_IF_ERROR_RETURN
   9146                 (soc_mem_write(unit, LLS_L2_PARENTm, MEM_BLOCK_ALL,
   9147                                hw_index, &entry));
   9148         } else {
   9149             return BCM_E_NONE;     
   9150         }
   9151     }
   9152 
   9153     return BCM_E_NONE;
   9154 }
   9155 
   9156 STATIC int
   9157 _bcm_kt_cosq_ef_op(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, int *arg,
   9158                    _bcm_cosq_op_t op)
   9159 {
   9160     bcm_port_t local_port;
   9161     int index, numq, from_cos, to_cos, ci;
   9162 
   9163     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
   9164         BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport)) {
   9165         BCM_IF_ERROR_RETURN
   9166             (_bcm_kt_cosq_index_resolve
   9167              (unit, gport, cosq, _BCM_KT_COSQ_INDEX_STYLE_BUCKET,
   9168               &local_port, &index, NULL));
   9169         return _bcm_kt_cosq_ef_op_at_index(unit, gport, cosq, 
   9170                                            index, op, arg);
   9171     } else if (BCM_GPORT_IS_SCHEDULER(gport)) {
   9172         return BCM_E_PARAM;
   9173     } else {
   9174         BCM_IF_ERROR_RETURN
   9175             (_bcm_kt_cosq_index_resolve
   9176              (unit, gport, cosq, _BCM_KT_COSQ_INDEX_STYLE_BUCKET,
   9177               &local_port, &index, &numq));
   9178         if (cosq == BCM_COS_INVALID) {
   9179             /* Maximum 1 spri can be EF enabled */
   9180             from_cos = to_cos = 0;
   9181         } else {
   9182             from_cos = to_cos = cosq;
   9183         }
   9184         for (ci = from_cos; ci <= to_cos; ci++) {
   9185             BCM_IF_ERROR_RETURN
   9186                 (_bcm_kt_cosq_index_resolve
   9187                  (unit, gport, ci, _BCM_KT_COSQ_INDEX_STYLE_BUCKET,
   9188                   &local_port, &index, NULL));
   9189 
   9190             BCM_IF_ERROR_RETURN(_bcm_kt_cosq_ef_op_at_index(unit,
   9191                                 gport, ci, index, op, arg));
   9192             if (op == _BCM_COSQ_OP_GET) {
   9193                 return BCM_E_NONE;
   9194             }
   9195         }
   9196     }
   9197     return BCM_E_NONE;
   9198 }
   9199 
   9200 STATIC int
   9201 _bcm_kt_cosq_port_qnum_get(int unit, bcm_gport_t gport,
   9202         bcm_cos_queue_t cosq, bcm_cosq_control_t type, int *arg)
   9203 {
   9204     bcm_port_t local_port;
   9205     if (!arg) {
   9206         return BCM_E_PARAM;
   9207     }
   9208 
   9209     if (!BCM_COSQ_QUEUE_VALID(unit, cosq)) {
   9210         return BCM_E_PARAM;
   9211     }
   9212 
   9213     BCM_IF_ERROR_RETURN
   9214         (_bcm_kt_cosq_localport_resolve(unit, gport, &local_port));
   9215     if (local_port < 0) {
   9216         return BCM_E_PORT;
   9217     }
   9218 
   9219     if (type == bcmCosqControlPortQueueUcast) {
   9220         *arg = SOC_INFO(unit).port_uc_cosq_base[local_port] + cosq;
   9221     } else {
   9222         *arg = SOC_INFO(unit).port_cosq_base[local_port] + cosq;
   9223     }
   9224 
   9225     return BCM_E_NONE;
   9226 }
   9227 
   9228 int
   9229 bcm_kt_cosq_control_set(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
   9230                         bcm_cosq_control_t type, int arg)
   9231 {
   9232     LOG_INFO(BSL_LS_BCM_COSQ,
   9233              (BSL_META_U(unit,
   9234                          "bcm_kt_cosq_control_set: unit=%d gport=0x%x cosq=%d \
   9235                          type=%d arg=%d\n"),
   9236               unit, gport, cosq, type, arg));
   9237     switch (type) {
   9238     case bcmCosqControlEfPropagation:
   9239         return _bcm_kt_cosq_ef_op(unit, gport, cosq, &arg, _BCM_COSQ_OP_SET);
   9240     default:
   9241         break;
   9242     }
   9243 
   9244     return BCM_E_UNAVAIL;
   9245 }
   9246 
   9247 int
   9248 bcm_kt_cosq_control_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
   9249                         bcm_cosq_control_t type, int *arg)
   9250 {
   9251     LOG_INFO(BSL_LS_BCM_COSQ,
   9252              (BSL_META_U(unit,
   9253                          "bcm_kt_cosq_control_get: unit=%d gport=0x%x cosq=%d type=%d\n"),
   9254               unit, gport, cosq, type));
   9255     switch (type) {
   9256     case bcmCosqControlEfPropagation:
   9257         return _bcm_kt_cosq_ef_op(unit, gport, cosq, arg, _BCM_COSQ_OP_GET);
   9258     case bcmCosqControlPortQueueUcast:
   9259     case bcmCosqControlPortQueueMcast:
   9260         return _bcm_kt_cosq_port_qnum_get(unit, gport, cosq, type, arg);
   9261     default:
   9262         break;
   9263     }
   9264 
   9265     return BCM_E_UNAVAIL;
   9266 }
   9267 
   9268 int
   9269 bcm_kt_cosq_drop_status_enable_set(int unit, bcm_port_t port, int enable)
   9270 {
   9271     uint32 rval;
   9272 
   9273     BCM_IF_ERROR_RETURN(READ_OP_E2ECC_PORT_CONFIGr(unit, port, &rval));
   9274     soc_reg_field_set(unit, OP_E2ECC_PORT_CONFIGr, &rval, 
   9275                       COS_MASKf,  enable ? 0xFF : 0x0);
   9276     soc_reg_field_set(unit, OP_E2ECC_PORT_CONFIGr, &rval, 
   9277                       E2ECC_RPT_ENf, enable ? 1 : 0);
   9278     BCM_IF_ERROR_RETURN(WRITE_OP_E2ECC_PORT_CONFIGr(unit, port, rval));
   9279     
   9280 
   9281     BCM_IF_ERROR_RETURN(READ_OP_THR_CONFIGr(unit, &rval));
   9282     soc_reg_field_set(unit, OP_THR_CONFIGr, &rval, EARLY_E2E_SELECTf,
   9283                       enable ? 1 : 0);
   9284     BCM_IF_ERROR_RETURN(WRITE_OP_THR_CONFIGr(unit, rval));
   9285 
   9286     return BCM_E_NONE;
   9287 }
   9288 
   9289 STATIC int
   9290 _bcm_kt_dump_config(int unit, bcm_port_t port,
   9291                        _bcm_kt_cosq_node_t *node)
   9292 {
   9293     int num_spri, first_child;
   9294     uint32 spmap;
   9295     soc_kt_sched_mode_e sched_mode = SOC_KT_SCHED_MODE_UNKNOWN;
   9296     int wt = 0;
   9297     char *lvl_name[] = { "Root", "L0", "L1", "L2" };
   9298     char *sched_modes[] = {"X", "SP", "WRR", "WDRR"};
   9299     int sp_vec = soc_feature(unit, soc_feature_vector_based_spri);
   9300 
   9301 
   9302     /* get sched config */
   9303     if (node->level != _BCM_KT_COSQ_NODE_LEVEL_L2) {
   9304         SOC_IF_ERROR_RETURN(
   9305             soc_kt_sched_get_node_config(unit, port, node->level,
   9306                                          node->hw_index, &num_spri,
   9307                                          &first_child, &spmap));
   9308     }
   9309     sched_mode = 0;
   9310     if (node->level != _BCM_KT_COSQ_NODE_LEVEL_ROOT) {
   9311         SOC_IF_ERROR_RETURN(
   9312          soc_kt_cosq_get_sched_mode(unit, port, node->level, node->hw_index,
   9313                                                &sched_mode, &wt));
   9314     }
   9315     switch (node->level) {
   9316         case _BCM_KT_COSQ_NODE_LEVEL_ROOT:
   9317         case _BCM_KT_COSQ_NODE_LEVEL_L0:
   9318         case _BCM_KT_COSQ_NODE_LEVEL_L1:
   9319             if (sp_vec) {
   9320                 LOG_CLI((BSL_META_U(unit,
   9321                 "  %s.%d : INDEX=%d NUM_SPRI=%d FC=%d SPMAP=0x%08x MODE=%s Wt=%d\n"),
   9322                       lvl_name[node->level], node->cosq_attached_to,
   9323                       node->hw_index, num_spri, first_child,
   9324                       spmap, sched_modes[sched_mode], wt));
   9325             } else {
   9326                 LOG_CLI((BSL_META_U(unit,
   9327                 "  %s.%d : INDEX=%d NUM_SPRI=%d FC=%d MODE=%s Wt=%d\n"),
   9328                       lvl_name[node->level], node->cosq_attached_to,
   9329                       node->hw_index, num_spri, first_child,
   9330                       sched_modes[sched_mode], wt));
   9331             }
   9332         break;
   9333         case _BCM_KT_COSQ_NODE_LEVEL_L2:
   9334                 LOG_CLI((BSL_META_U(unit,
   9335                               "     L2.%d INDEX=%d Mode=%s WEIGHT=%d\n"),
   9336                                    node->cosq_attached_to, node->hw_index,
   9337                                    sched_modes[sched_mode], wt));
   9338         break;
   9339         default:
   9340              return BCM_E_INTERNAL;
   9341 
   9342     }
   9343     return BCM_E_NONE;
   9344 }
   9345 
   9346 STATIC int
   9347 _bcm_kt_cosq_child_node_at_input(_bcm_kt_cosq_node_t *node, int cosq,
   9348                                   _bcm_kt_cosq_node_t **child_node)
   9349 {
   9350     _bcm_kt_cosq_node_t *cur_node;
   9351 
   9352     for (cur_node = node->child; cur_node; cur_node = cur_node->sibling) {
   9353         if (cur_node->cosq_attached_to == cosq) {
   9354             break;
   9355         }
   9356     }
   9357     if (!cur_node) {
   9358         return BCM_E_NOT_FOUND;
   9359     }
   9360 
   9361     *child_node = cur_node;
   9362 
   9363     return BCM_E_NONE;
   9364 }
   9365 
   9366 STATIC int
   9367 _bcm_kt_dump_sched(int unit, bcm_port_t port, bcm_gport_t gport)
   9368 {
   9369     _bcm_kt_cosq_node_t *node;
   9370     _bcm_kt_cosq_node_t *cur_node;
   9371     int i = 0;
   9372     int start_cos = 0;
   9373     int end_cos = 0;
   9374 
   9375     BCM_IF_ERROR_RETURN
   9376         (_bcm_kt_cosq_node_get(unit, gport, NULL, NULL, NULL, &node));
   9377 
   9378     if (node != NULL) {
   9379         if (node->level == _BCM_KT_COSQ_NODE_LEVEL_L2) {
   9380             return BCM_E_INTERNAL;
   9381         }
   9382 
   9383         start_cos = 0;
   9384         end_cos = node->numq;
   9385         _bcm_kt_dump_config(unit, port, node);
   9386 
   9387         for (i = start_cos; i < end_cos; i++)
   9388         {
   9389             if(_bcm_kt_cosq_child_node_at_input(node, i, &cur_node)
   9390                        == BCM_E_NOT_FOUND) {
   9391                 continue;
   9392             }
   9393             if (cur_node->level == _BCM_KT_COSQ_NODE_LEVEL_L2) {
   9394                  BCM_IF_ERROR_RETURN
   9395                    (_bcm_kt_dump_config(unit, port, cur_node));
   9396             } else {
   9397                 BCM_IF_ERROR_RETURN
   9398                    (_bcm_kt_dump_sched(unit, port, cur_node->gport));
   9399             }
   9400         }
   9401     }
   9402     return BCM_E_NONE;
   9403 
   9404 }
   9405 
   9406 STATIC int
   9407 _bcm_kt_dump_port_lls(int unit, bcm_port_t port)
   9408 {
   9409     _bcm_kt_cosq_node_t *port_info;
   9410     _bcm_kt_mmu_info_t *mmu_info;
   9411     bcm_port_t port_out;
   9412 
   9413     if (_bcm_kt_mmu_info[unit] == NULL) {
   9414         return BCM_E_INIT;
   9415     }
   9416     mmu_info = _bcm_kt_mmu_info[unit];
   9417 
   9418     BCM_IF_ERROR_RETURN
   9419         (_bcm_kt_cosq_localport_resolve(unit, port, &port_out));
   9420 
   9421     /* root node */
   9422     port_info = &mmu_info->sched_node[port_out];
   9423 
   9424     if (port_info->gport >= 0) {
   9425        _bcm_kt_dump_sched(unit, port, port_info->gport);
   9426     }
   9427     return BCM_E_NONE;
   9428 }
   9429 
   9430 int bcm_kt_dump_port_lls(int unit, bcm_port_t port)
   9431 {
   9432 
   9433     LOG_CLI((BSL_META_U(unit,
   9434       "-------%s (LLS)------\n"), SOC_PORT_NAME(unit, (port))));
   9435     _bcm_kt_dump_port_lls(unit, port);
   9436     return SOC_E_NONE;
   9437 }
   9438 
   9439 int
   9440 bcm_kt_cosq_subscriber_qid_set(int unit,
   9441       bcm_gport_t *gport,
   9442        int queue_id)
   9443 {
   9444    _bcm_kt_mmu_info_t *mmu_info;
   9445    mmu_info = _bcm_kt_mmu_info[unit];
   9446    if (mmu_info == NULL) {
   9447        return BCM_E_INIT;
   9448    }
   9449    if (queue_id >= mmu_info->num_base_queues) {
   9450        queue_id -= mmu_info->num_base_queues;
   9451    }
   9452    BCM_GPORT_UCAST_SUBSCRIBER_QUEUE_GROUP_QID_SET
   9453                             (*gport,queue_id);
   9454    return SOC_E_NONE;
   9455 }
   9456 
   9457 
   9458 #ifndef BCM_SW_STATE_DUMP_DISABLE
   9459 
   9460 STATIC int
   9461 _bcm_kt_cosq_port_info_dump(int unit, bcm_port_t port) 
   9462 {
   9463     _bcm_kt_mmu_info_t *mmu_info;
   9464     _bcm_kt_cosq_node_t *port_node = NULL;
   9465     _bcm_kt_cosq_node_t *queue_node = NULL;
   9466     _bcm_kt_cosq_node_t *l0_node = NULL;
   9467     _bcm_kt_cosq_node_t *l1_node = NULL;
   9468 
   9469     if (!SOC_PORT_VALID(unit, port)) {
   9470         return BCM_E_PORT;
   9471     }
   9472 
   9473     mmu_info = _bcm_kt_mmu_info[unit];
   9474 
   9475     /* get the root node */
   9476     port_node = &mmu_info->sched_node[port];
   9477 
   9478     if (port_node && port_node->cosq_attached_to < 0) {
   9479         return BCM_E_NONE;
   9480     }    
   9481 
   9482     LOG_CLI((BSL_META_U(unit,
   9483                         "=== port %d\n"), port));
   9484     LOG_CLI((BSL_META_U(unit,
   9485                         "base = %d numq = %d hw_index = %d level = %d cosq_attach = %d \n"),
   9486              port_node->base_index, port_node->numq, port_node->hw_index,
   9487              port_node->level, port_node->cosq_attached_to));
   9488     LOG_CLI((BSL_META_U(unit,
   9489                         "num_child = %d first_child = %d \n"), port_node->num_child,
   9490              port_node->first_child));
   9491     if (port_node->parent != NULL) {
   9492         LOG_CLI((BSL_META_U(unit,
   9493                             "  parent gport = 0x%08x\n"), port_node->parent->gport));
   9494     }
   9495     if (port_node->sibling != NULL) {
   9496         LOG_CLI((BSL_META_U(unit,
   9497                             "  sibling gport = 0x%08x\n"), port_node->sibling->gport));
   9498     }
   9499     if (port_node->child != NULL) {
   9500         LOG_CLI((BSL_META_U(unit,
   9501                             "  child  gport = 0x%08x\n"), port_node->child->gport));
   9502     }
   9503 
   9504     for (l0_node = port_node->child; l0_node != NULL;
   9505          l0_node = l0_node->sibling) {
   9506 
   9507          if (l0_node->cosq_attached_to < 0) {
   9508             return BCM_E_NONE;
   9509          }    
   9510          LOG_CLI((BSL_META_U(unit,
   9511                              "=== L0 gport 0x%08x\n"), l0_node->gport));
   9512          LOG_CLI((BSL_META_U(unit,
   9513                              "base = %d numq = %d hw_index = %d level = %d cosq_attach = %d \n"),
   9514                   l0_node->base_index, l0_node->numq, l0_node->hw_index,
   9515                   l0_node->level, l0_node->cosq_attached_to));
   9516          LOG_CLI((BSL_META_U(unit,
   9517                              "num_child = %d first_child = %d \n"), l0_node->num_child,
   9518                   l0_node->first_child));
   9519          if (l0_node->parent != NULL) {
   9520              LOG_CLI((BSL_META_U(unit,
   9521                                  "  parent gport = 0x%08x\n"), l0_node->parent->gport));
   9522          }
   9523          if (l0_node->sibling != NULL) {
   9524              LOG_CLI((BSL_META_U(unit,
   9525                                  "  sibling gport = 0x%08x\n"), l0_node->sibling->gport));
   9526          }
   9527          if (l0_node->child != NULL) {
   9528              LOG_CLI((BSL_META_U(unit,
   9529                                  "  child    gport = 0x%08x\n"), l0_node->child->gport));
   9530          }
   9531 
   9532          for (l1_node = l0_node->child; l1_node != NULL;
   9533               l1_node = l1_node->sibling) {
   9534               if (l1_node->cosq_attached_to < 0) {
   9535                   return BCM_E_NONE;
   9536               }
   9537               LOG_CLI((BSL_META_U(unit,
   9538                                   "=== L1 gport 0x%08x\n"), l1_node->gport));
   9539               LOG_CLI((BSL_META_U(unit,
   9540                                   "base = %d numq = %d hw_index = %d level = %d cosq_attach = %d \n"),
   9541                        l1_node->base_index, l1_node->numq, l1_node->hw_index,
   9542                        l1_node->level, l1_node->cosq_attached_to));
   9543               LOG_CLI((BSL_META_U(unit,
   9544                                   "num_child = %d first_child = %d \n"), l1_node->num_child,
   9545                        l1_node->first_child));
   9546               if (l1_node->parent != NULL) {
   9547                   LOG_CLI((BSL_META_U(unit,
   9548                                       "  parent gport = 0x%08x\n"), l1_node->parent->gport));
   9549               }
   9550               if (l1_node->sibling != NULL) {
   9551                   LOG_CLI((BSL_META_U(unit,
   9552                                       "  sibling gport = 0x%08x\n"), l1_node->sibling->gport));
   9553               }
   9554               if (l1_node->child != NULL) {
   9555                   LOG_CLI((BSL_META_U(unit,
   9556                                       "  child  gport = 0x%08x\n"), l1_node->child->gport));
   9557               }
   9558 
   9559               for (queue_node = l1_node->child; queue_node != NULL;
   9560                    queue_node = queue_node->sibling) {
   9561                    if (queue_node->cosq_attached_to < 0) {
   9562                        return BCM_E_NONE;
   9563                    }
   9564                    LOG_CLI((BSL_META_U(unit,
   9565                                        "=== L2 gport 0x%08x\n"), queue_node->gport));
   9566                    LOG_CLI((BSL_META_U(unit,
   9567                                        "base = %d numq = %d hw_index = %d level = %d cosq_attach = %d \n"),
   9568                             queue_node->base_index, queue_node->numq, queue_node->hw_index,
   9569                             queue_node->level, queue_node->cosq_attached_to));
   9570                    LOG_CLI((BSL_META_U(unit,
   9571                                        "num_child = %d first_child = %d \n"), queue_node->num_child,
   9572                             queue_node->first_child));
   9573                    if (queue_node->parent != NULL) {
   9574                        LOG_CLI((BSL_META_U(unit,
   9575                                            "  parent gport = 0x%08x\n"), queue_node->parent->gport));
   9576                    }
   9577                    if (queue_node->sibling != NULL) {
   9578                        LOG_CLI((BSL_META_U(unit,
   9579                                            "  sibling gport = 0x%08x\n"), queue_node->sibling->gport));
   9580                    }
   9581                    if (queue_node->child != NULL) {
   9582                        LOG_CLI((BSL_META_U(unit,
   9583                                            "  child  gport = 0x%08x\n"), queue_node->child->gport));
   9584                    }
   9585               }        
   9586 
   9587          }        
   9588     }        
   9589 
   9590     return BCM_E_NONE;
   9591 }
   9592 
   9593 /*
   9594  * Function:
   9595  *     bcm_kt_cosq_sw_dump
   9596  * Purpose:
   9597  *     Displays COS Queue information maintained by software.
   9598  * Parameters:
   9599  *     unit - Device unit number
   9600  * Returns:
   9601  *     None
   9602  */
   9603 void
   9604 bcm_kt_cosq_sw_dump(int unit)
   9605 {
   9606     _bcm_kt_mmu_info_t *mmu_info;
   9607     bcm_port_t port;
   9608 
   9609     mmu_info = _bcm_kt_mmu_info[unit];
   9610 
   9611     LOG_CLI((BSL_META_U(unit,
   9612                         "\nSW Information COSQ - Unit %d\n"), unit));
   9613 
   9614     PBMP_ALL_ITER(unit, port) {
   9615         (void)_bcm_kt_cosq_port_info_dump(unit, port);
   9616     }
   9617 
   9618     LOG_CLI((BSL_META_U(unit,
   9619                         "ext_qlist = %d \n"), mmu_info->ext_qlist.count));
   9620     LOG_CLI((BSL_META_U(unit,
   9621                         "sched_list = %d \n"), mmu_info->sched_list.count));
   9622     LOG_CLI((BSL_META_U(unit,
   9623                         "l0_sched_list = %d \n"), mmu_info->l0_sched_list.count));
   9624     LOG_CLI((BSL_META_U(unit,
   9625                         "l1_sched_list = %d \n"), mmu_info->l1_sched_list.count));
   9626     LOG_CLI((BSL_META_U(unit,
   9627                         "l2_base_qlist = %d \n"), mmu_info->l2_base_qlist.count));
   9628     LOG_CLI((BSL_META_U(unit,
   9629                         "l2_ext_qlist = %d \n"), mmu_info->l2_ext_qlist.count));
   9630     
   9631     return;
   9632 }
   9633 #endif /* BCM_SW_STATE_DUMP_DISABLE */
   9634 
   9635 #else /* BCM_KATANA_SUPPORT */
   9636 int _kt_cosq_not_empty;
   9637 #endif  /* BCM_KATANA_SUPPORT */