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


      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_TRIDENT_SUPPORT)
     16 #include <bcm/types.h>
     17 #include <bcm/pkt.h>
     18 #include <bcm/tx.h>
     19 #include <soc/drv.h>
     20 #include <soc/scache.h>
     21 #include <soc/profile_mem.h>
     22 #include <soc/trident.h>
     23 
     24 #include <bcm/error.h>
     25 #include <bcm/cosq.h>
     26 #include <bcm_int/esw/mbcm.h>
     27 #include <bcm_int/esw/trident.h>
     28 #include <bcm_int/esw/stack.h>
     29 #include <bcm_int/esw/cosq.h>
     30 
     31 #include <bcm_int/esw_dispatch.h>
     32 
     33 #ifdef BCM_WARM_BOOT_SUPPORT
     34 #include <bcm_int/esw/switch.h>
     35 #endif /* BCM_WARM_BOOT_SUPPORT */
     36 
     37 #define TD_CELL_FIELD_MAX       0xffff
     38 
     39 /* MMU cell size in bytes */
     40 #define _BCM_TD_PACKET_HEADER_BYTES       64    /* bytes */
     41 #define _BCM_TD_DEFAULT_MTU_BYTES         1536  /* bytes */
     42 #define _BCM_TD_TOTAL_CELLS               46080 /* 45k cells */
     43 #define _BCM_TD_BYTES_PER_CELL            208   /* bytes */
     44 #define _BCM_TD_BYTES_TO_CELLS(_byte_)  \
     45     (((_byte_) + _BCM_TD_BYTES_PER_CELL - 1) / _BCM_TD_BYTES_PER_CELL)
     46 
     47 #define _BCM_TD_NUM_UCAST_QUEUE_GROUP            10
     48 #define _BCM_TD_NUM_MCAST_QUEUE_GROUP            5
     49 #define _BCM_TD_NUM_EXT_UCAST_QUEUE_GROUP        16
     50 #define _BCM_TD_NUM_SCHEDULER                    9
     51 #define _BCM_TD_NUM_S2_SCHEDULER                 3
     52 #define _BCM_TD_NUM_S3_SCHEDULER                 4
     53 
     54 #define _BCM_TD_NUM_NON_SC_QM_UCAST_QUEUE        8
     55 #define _BCM_TD_NUM_NON_SC_QM_MCAST_QUEUE        4
     56 
     57 #define _BCM_TD_S1_SCHEDULER_NUM_INPUT           7
     58 #define _BCM_TD_S2_SCHEDULER_NUM_INPUT           9
     59 #define _BCM_TD_S3_SCHEDULER_NUM_INPUT           2
     60 #define _BCM_TD_EXT_S3_SCHEDULER_NUM_INPUT       18
     61 
     62 #define _BCM_TD_NUM_CPU_QUEUES                48
     63 #define _TD_NUM_COS    NUM_COS
     64 #define _BCM_TD_MAX_NUM_LLFC_EXTQ     4  /* At max, 4 EXTqs can be affected
     65                                             by a given LLFC priority. */
     66 #define _BCM_TD_NUM_PFC_CLASS         8  /* TD supports eight PFC priorities. */
     67 
     68 #define WRED_MIN_PKT_SIZE            148 /* Should be greater than one cell.*/
     69 #define SOC_WRED_WR_MAX_NUM_PORTS      4 /* 1 extended and 1 non-extended port
     70                                                          from each pipeline.*/
     71 
     72 #define PORT_IS_VALID(_u, _p)       \
     73         IS_XE_PORT(_u, _p) ? 1 :    \
     74         IS_HG_PORT(_u, _p) ? 1 : 0
     75 
     76 
     77 #define STG_BITS_PER_PORT       2
     78 #define STG_PORTS_PER_WORD      (32 / STG_BITS_PER_PORT)
     79 #define STG_WORD(port)          ((port) / STG_PORTS_PER_WORD)
     80 #define STG_BITS_SHIFT(port)    \
     81         (STG_BITS_PER_PORT * ((port) % STG_PORTS_PER_WORD))
     82 
     83 /* Shifts first LSB byte of the mac n times. */
     84 #define MAC_LSB_SHIFT(d, s, n)   \
     85             d[5] = s[5] << n;
     86 
     87 typedef enum {
     88     _BCM_TD_COSQ_TYPE_UCAST,
     89     _BCM_TD_COSQ_TYPE_MCAST,
     90     _BCM_TD_COSQ_TYPE_EXT_UCAST
     91 } _bcm_td_cosq_type_t;
     92 
     93 typedef struct _bcm_td_voq_profile_s {
     94     int         id;
     95     int         hw_index;
     96     int         int_prio2q[16];
     97 } _bcm_td_voq_profile_t;
     98 
     99 typedef struct _bcm_td_cosq_node_s {
    100     struct _bcm_td_cosq_node_s *parent;
    101     struct _bcm_td_cosq_node_s *sibling;
    102     struct _bcm_td_cosq_node_s *child;
    103     bcm_gport_t gport;
    104     int numq;
    105     int base;
    106     int cosq_attached_to;
    107     int hw_cosq_attached_to;
    108     int level;
    109     _bcm_td_voq_profile_t voq_profile;
    110 } _bcm_td_cosq_node_t;
    111 
    112 typedef struct _bcm_td_cosq_port_info_s {
    113     _bcm_td_cosq_node_t ucast[_BCM_TD_NUM_UCAST_QUEUE_GROUP];
    114     _bcm_td_cosq_node_t mcast[_BCM_TD_NUM_MCAST_QUEUE_GROUP];
    115     _bcm_td_cosq_node_t ext_ucast[_BCM_TD_NUM_EXT_UCAST_QUEUE_GROUP];
    116     _bcm_td_cosq_node_t sched[_BCM_TD_NUM_SCHEDULER];
    117 } _bcm_td_cosq_port_info_t;
    118 
    119 typedef struct _bcm_td_cosq_cpu_cosq_config_s {
    120     /* All MC queues have DB and MCQE space */
    121     int enable;
    122     int q_min_limit;
    123     int q_shared_limit;
    124     uint8 q_limit_dynamic;
    125     uint8 q_limit_enable;
    126 } _bcm_td_cosq_cpu_cosq_config_t;
    127 
    128 /* Structure to store bitmaps of PFC queue. */
    129 typedef struct _bcm_td_cosq_pfc_cos_bmp_s
    130 {
    131    uint32 uc_bmp;         /* Bitmap of unicast queue. */
    132    uint32 mc_bmp;         /* Bitmap of multicast queue. */
    133    int    ext_uc_count;   /* Number of extended queues. */
    134    int    ext_uc_qid[_BCM_TD_MAX_NUM_LLFC_EXTQ]; /* IDs of extended queues. */
    135 } _bcm_td_cosq_pfc_cos_bmp_t;
    136 
    137 /* Global structure to store default state of port and switch. */
    138 typedef struct _wred_war_ctrl_s
    139 {
    140    soc_port_t  port[SOC_WRED_WR_MAX_NUM_PORTS];
    141    int         port_mode[SOC_WRED_WR_MAX_NUM_PORTS];
    142    int         port_crc_mode[SOC_WRED_WR_MAX_NUM_PORTS];
    143    int         is_ge_port[SOC_WRED_WR_MAX_NUM_PORTS];
    144    port_tab_entry_t port_entry[SOC_WRED_WR_MAX_NUM_PORTS];
    145    epc_link_bmap_entry_t epc_entry;           /* EPC state. */
    146    uint32      stg_entry[SOC_MAX_MEM_WORDS];  /* STP group ports state map.   */
    147    int         parity_gen_en;
    148    int         parity_chk_en;
    149    int         enable[SOC_WRED_WR_MAX_NUM_PORTS];
    150    int         speed[SOC_WRED_WR_MAX_NUM_PORTS];
    151    int         duplex[SOC_WRED_WR_MAX_NUM_PORTS];
    152    bcm_port_abil_t advert[SOC_WRED_WR_MAX_NUM_PORTS];
    153    int         autoneg[SOC_WRED_WR_MAX_NUM_PORTS];
    154 }_wred_war_ctrl_t;
    155 
    156 _wred_war_ctrl_t war; /* Global control structure to store 
    157                        * WRED workaround configuration.
    158                        */
    159 
    160 STATIC _bcm_td_cosq_port_info_t *_bcm_td_cosq_port_info[BCM_MAX_NUM_UNITS];
    161 STATIC soc_profile_mem_t *_bcm_td_cos_map_profile[BCM_MAX_NUM_UNITS];
    162 STATIC soc_profile_mem_t *_bcm_td_voq_cos_map_profile[BCM_MAX_NUM_UNITS];
    163 STATIC soc_profile_mem_t *_bcm_td_wred_profile[BCM_MAX_NUM_UNITS];
    164 STATIC soc_profile_mem_t *_bcm_td_sample_int_profile[BCM_MAX_NUM_UNITS];
    165 STATIC soc_profile_reg_t *_bcm_td_feedback_profile[BCM_MAX_NUM_UNITS];
    166 STATIC soc_profile_reg_t *_bcm_td_llfc_profile[BCM_MAX_NUM_UNITS];
    167 STATIC soc_profile_reg_t *_bcm_td_ext_llfc_profile[BCM_MAX_NUM_UNITS];
    168 
    169 STATIC _bcm_td_cosq_cpu_cosq_config_t *_bcm_td_cosq_cpu_cosq_config[BCM_MAX_NUM_UNITS][_BCM_TD_NUM_CPU_QUEUES];
    170 
    171 STATIC const soc_field_t _bcm_td_cpq_en_field[] = {
    172     CPQ_EN0f, CPQ_EN1f,
    173     CPQ_EN2f, CPQ_EN3f,
    174     CPQ_EN4f, CPQ_EN5f,
    175     CPQ_EN6f, CPQ_EN7f,
    176     CPQ_EN8f, CPQ_EN9f
    177 };
    178 STATIC const soc_field_t _bcm_td_cpq_index_field[] = {
    179     CPQ_PROFILE_INDEX0f, CPQ_PROFILE_INDEX1f,
    180     CPQ_PROFILE_INDEX2f, CPQ_PROFILE_INDEX3f,
    181     CPQ_PROFILE_INDEX4f, CPQ_PROFILE_INDEX5f,
    182     CPQ_PROFILE_INDEX6f, CPQ_PROFILE_INDEX7f,
    183     CPQ_PROFILE_INDEX8f, CPQ_PROFILE_INDEX9f
    184 };
    185 STATIC const soc_field_t _bcm_td_eqtb_index_field[] = {
    186     EQTB_INDEX0f, EQTB_INDEX1f
    187 };
    188 STATIC const soc_field_t _bcm_td_act_offset_field[] = {
    189     QNTZ_ACT_OFFSET0f, QNTZ_ACT_OFFSET1f
    190 };
    191 STATIC const soc_field_t _bcm_td_sitb_sel_field[] = {
    192     SITB_SEL0f, SITB_SEL1f
    193 };
    194 static const soc_reg_t _bcm_td_ext_uc_spid_regs[] =
    195 {
    196     OP_EX_PORT_CONFIG_SPID_0r, OP_EX_PORT_CONFIG_SPID_1r,
    197     OP_EX_PORT_CONFIG_SPID_2r, OP_EX_PORT_CONFIG_SPID_3r,
    198     OP_EX_PORT_CONFIG_SPID_4r
    199 };
    200 static const soc_field_t _bcm_td_uc_spid_fields[] = {
    201     COS0_SPIDf, COS1_SPIDf, COS2_SPIDf, COS3_SPIDf,
    202     COS4_SPIDf, COS5_SPIDf, COS6_SPIDf, COS7_SPIDf,
    203     COS8_SPIDf, COS9_SPIDf
    204 };
    205 static const soc_field_t _bcm_td_ext_uc_spid_fields[] = {
    206     Q0_SPIDf, Q1_SPIDf, Q2_SPIDf, Q3_SPIDf,
    207     Q4_SPIDf, Q5_SPIDf, Q6_SPIDf, Q7_SPIDf,
    208     Q8_SPIDf, Q9_SPIDf, Q10_SPIDf, Q11_SPIDf,
    209     Q12_SPIDf, Q13_SPIDf, Q14_SPIDf, Q15_SPIDf,
    210     Q16_SPIDf, Q17_SPIDf, Q18_SPIDf, Q19_SPIDf,
    211     Q20_SPIDf, Q21_SPIDf, Q22_SPIDf, Q23_SPIDf,
    212     Q24_SPIDf, Q25_SPIDf, Q26_SPIDf, Q27_SPIDf,
    213     Q28_SPIDf, Q29_SPIDf, Q30_SPIDf, Q31_SPIDf,
    214     Q32_SPIDf, Q33_SPIDf, Q34_SPIDf, Q35_SPIDf,
    215     Q36_SPIDf, Q37_SPIDf, Q38_SPIDf, Q39_SPIDf,
    216     Q40_SPIDf, Q41_SPIDf, Q42_SPIDf, Q43_SPIDf,
    217     Q44_SPIDf, Q45_SPIDf, Q46_SPIDf, Q47_SPIDf,
    218     Q48_SPIDf, Q49_SPIDf, Q50_SPIDf, Q51_SPIDf,
    219     Q52_SPIDf, Q53_SPIDf, Q54_SPIDf, Q55_SPIDf,
    220     Q56_SPIDf, Q57_SPIDf, Q58_SPIDf, Q59_SPIDf,
    221     Q60_SPIDf, Q61_SPIDf, Q62_SPIDf, Q63_SPIDf,
    222     Q64_SPIDf, Q65_SPIDf, Q66_SPIDf, Q67_SPIDf,
    223     Q68_SPIDf, Q69_SPIDf, Q70_SPIDf, Q71_SPIDf,
    224     Q72_SPIDf, Q73_SPIDf
    225 };
    226 
    227 STATIC int _bcm_td_create_default_profile(int unit, bcm_port_t gport, int numq,
    228                                           _bcm_td_voq_profile_t *profile);
    229 
    230 STATIC int _bcm_td_voq_gport_mapping_set(int unit, bcm_port_t gport, 
    231                                          int int_prio, bcm_cos_t cos);
    232 
    233 /* Number of COSQs configured for this device */
    234 STATIC int _bcm_td_num_cosq[SOC_MAX_NUM_DEVICES];
    235 
    236 extern sal_mutex_t cosq_sync_lock[SOC_MAX_NUM_DEVICES];
    237 #define TD_COSQ_LOCK(unit)      do { \
    238                                     if (cosq_sync_lock[unit]) { \
    239                                         sal_mutex_take(cosq_sync_lock[unit], \
    240                                                        sal_mutex_FOREVER); \
    241                                     } \
    242                                 } while (0)
    243 #define TD_COSQ_UNLOCK(unit)    do { \
    244                                     if (cosq_sync_lock[unit]) { \
    245                                         sal_mutex_give(cosq_sync_lock[unit]); \
    246                                     } \
    247                                 } while (0)
    248 
    249 #define _BCM_TD_VOQ_QID_MIN_ID      (64)
    250 #define _BCM_TD_VOQ_QID_MAX_ID      (127)
    251 
    252 #define _BCM_TD_IS_VOQ_GPORT(unit, gport)     \
    253  ((BCM_GPORT_IS_UCAST_QUEUE_GROUP((gport))) &&  \
    254   ((BCM_GPORT_UCAST_QUEUE_GROUP_QID_GET((gport)) >= _BCM_TD_NUM_UCAST_QUEUE_GROUP) && \
    255    (BCM_GPORT_UCAST_QUEUE_GROUP_QID_GET((gport)) <  \
    256             (_BCM_TD_NUM_UCAST_QUEUE_GROUP + _BCM_TD_NUM_EXT_UCAST_QUEUE_GROUP))))
    257 
    258 
    259 #define _BCM_TD_NUM_COS_IN_QUEUE_GROUP(unit, gport) (4) 
    260 
    261 #define _BCM_TD_VOQ_GPORT_QUEUE_ID(unit, gport, offset)  \
    262     (_BCM_TD_VOQ_QID_MIN_ID +   (offset) +               \
    263      ((BCM_GPORT_UCAST_QUEUE_GROUP_QID_GET((gport)) - _BCM_TD_NUM_UCAST_QUEUE_GROUP) * 16)) 
    264         
    265 #define _BCM_TD_IS_PORT_DMVOQ_CAPABLE(u, p) \
    266             (((&SOC_INFO((u)))->port_num_ext_cosq[(p)]) ? 1 : 0)
    267 
    268 STATIC int _bcm_td_cosq_voq_init(int unit, bcm_port_t port);
    269 
    270 STATIC int
    271 _bcm_td_cosq_dynamic_thresh_enable_get(int unit, 
    272                         bcm_gport_t gport, bcm_cos_queue_t cosq, 
    273                         bcm_cosq_control_t type, int *arg);
    274 
    275 /*
    276  * queues on non-CPU ports:
    277  *     5 multicast queue group (1 queue per group)
    278  *         queue 0 - 3 can connected to input 0 of S3.0 - S3.3 scheduler
    279  *                                   or input 0 - 3 of MC group scheduler
    280  *         queue 4 (SC/QM queue) is fixed connected to input 4 of S1 scheduler
    281  *     10 unicast queue group (1 queue per group)
    282  *         queue 0 - 3 can connected to input 1 of S3.0 - S3.3 scheduler
    283  *                                   or input 4 - 7 of S2 scheduler
    284  *         queue 4 - 7 are fixed connected to input 8 - 11 of S2 scheduler
    285  *         queue 8 (SC queue) is fixed connected to input 5 of S1 scheduler
    286  *         queue 9 (QM queue) is fixed connected to input 6 of S1 scheduler
    287  *     16 extended unicast queue group (up to 4 queues per group)
    288  *         only exist in extended queue ports
    289  *         queue 0 - 15 are fixed connected to input 2 - 17 of S3.0 scheduler
    290  *         queue 16 - 31 are fixed connected to input 2 - 17 of S3.1 scheduler
    291  *         queue 32 - 47 are fixed connected to input 2 - 17 of S3.2 scheduler
    292  *         queue 48 - 63 are fixed connected to input 2 - 17 of S3.3 scheduler
    293  * schedulers on non-CPU ports:
    294  *     1 S1 scheduler (7 input)
    295  *     1 MC group scheduler (4 input)
    296  *         fixed connected to input 0 of S1 scheduler
    297  *     3 S2 schedulers (12 input)
    298  *         scheduler 0 - 2 are fixed connected to input 1 - 3 of S1 scheduler
    299  *     4 S3 schedulers (8 input for regular port, 72 input for extended port)
    300  *         scheduler 0 - 3 are fixed connected to input 0 - 3 of S2 scheduler
    301  *
    302  * Unicast queue group gport format:
    303  *   31       26 25                   14 13                        0
    304  *  +-------.---+---.-------.-------.---+---.-------.-------.-------+
    305  *  |0 0 1 0 0 1|   sysportid (port)    |            qid            |
    306  *  +-------.---+---.-------.-------.---+---.-------.-------.-------+
    307  * qid: 0 - 9 for unicast queue, 10 - 25 for extended unicast queue
    308  *
    309  * Multicast queue group gport format:
    310  *   31       26 25                   14 13                        0
    311  *  +-------.---+---.-------.-------.---+---.-------.-------.-------+
    312  *  |0 0 1 1 0 0|   sysportid (port)    |            qid            |
    313  *  +-------.---+---.-------.-------.---+---.-------.-------.-------+
    314  * qid: 0 - 4
    315  *
    316  * Scheduler gport format:
    317  *   31       26 25               16 15            8 7             0
    318  *  +-------.---+---.-------.-------+-------.-------+-------.-------+
    319  *  |0 0 1 1 0 1|    scheduler id   |    module     |     port      |
    320  *  +-------.---+---.-------.-------+-------.-------+-------.-------+
    321  * qid: 0 - 8
    322  */
    323 
    324 #ifndef BCM_SW_STATE_DUMP_DISABLE
    325 STATIC int
    326 _bcm_td_cosq_port_info_dump(int unit, bcm_port_t port)
    327 {
    328     _bcm_td_cosq_port_info_t *port_info;
    329     _bcm_td_cosq_node_t *node;
    330     int index, empty;
    331 
    332     if (!SOC_PORT_VALID(unit, port)) {
    333         return BCM_E_PORT;
    334     }
    335     port_info = &_bcm_td_cosq_port_info[unit][port];
    336 
    337     empty = TRUE;
    338     for (index = 0; index < _BCM_TD_NUM_SCHEDULER; index++) {
    339         if (port_info->sched[index].numq > 0) {
    340             empty = FALSE;
    341             break;
    342         }
    343     }
    344     if (empty) {
    345         for (index = 0; index < _BCM_TD_NUM_UCAST_QUEUE_GROUP; index++) {
    346             if (port_info->ucast[index].numq > 0) {
    347                 empty = FALSE;
    348                 break;
    349             }
    350         }
    351     }
    352     if (empty) {
    353         for (index = 0; index < _BCM_TD_NUM_MCAST_QUEUE_GROUP; index++) {
    354             if (port_info->mcast[index].numq > 0) {
    355                 empty = FALSE;
    356                 break;
    357             }
    358         }
    359     }
    360     if (empty) {
    361         for (index = 0; index < _BCM_TD_NUM_EXT_UCAST_QUEUE_GROUP; index++) {
    362             if (port_info->ext_ucast[index].numq > 0) {
    363                 empty = FALSE;
    364                 break;
    365             }
    366         }
    367     }
    368 
    369     if (empty == TRUE) {
    370         return BCM_E_NOT_FOUND;
    371     }
    372 
    373     LOG_CLI((BSL_META_U(unit,
    374                         "=== port %d\n"), port));
    375     for (index = 0; index < _BCM_TD_NUM_UCAST_QUEUE_GROUP; index++) {
    376         node = &port_info->ucast[index];
    377         LOG_CLI((BSL_META_U(unit,
    378                             "ucast[%d]: gport=%x numq=%d base=%d cosq_att=%d "
    379                  "hw_cosq_att=%d level=%d\n"),
    380                  index, node->gport, node->numq, node->base,
    381                  node->cosq_attached_to, node->hw_cosq_attached_to,
    382                  node->level));
    383         if (node->numq == 0) {
    384             continue;
    385         }
    386         if (node->parent != NULL) {
    387             LOG_CLI((BSL_META_U(unit,
    388                                 "  parent gport=%x\n"), node->parent->gport));
    389         }
    390         if (node->sibling != NULL) {
    391             LOG_CLI((BSL_META_U(unit,
    392                                 "  sibling gport=%x\n"), node->sibling->gport));
    393         }
    394         if (node->child != NULL) {
    395             LOG_CLI((BSL_META_U(unit,
    396                                 "  child  gport=%x\n"), node->child->gport));
    397         }
    398     }
    399 
    400     for (index = 0; index < _BCM_TD_NUM_MCAST_QUEUE_GROUP; index++) {
    401         node = &port_info->mcast[index];
    402         LOG_CLI((BSL_META_U(unit,
    403                             "mcast[%d]: gport=%x numq=%d base=%d cosq_att=%d "
    404                  "hw_cosq_att=%d level=%d\n"),
    405                  index, node->gport, node->numq, node->base,
    406                  node->cosq_attached_to, node->hw_cosq_attached_to,
    407                  node->level));
    408         if (node->numq == 0) {
    409             continue;
    410         }
    411         if (node->parent != NULL) {
    412             LOG_CLI((BSL_META_U(unit,
    413                                 "  parent gport=%x\n"), node->parent->gport));
    414         }
    415         if (node->sibling != NULL) {
    416             LOG_CLI((BSL_META_U(unit,
    417                                 "  sibling gport=%x\n"), node->sibling->gport));
    418         }
    419         if (node->child != NULL) {
    420             LOG_CLI((BSL_META_U(unit,
    421                                 "  child  gport=%x\n"), node->child->gport));
    422         }
    423     }
    424 
    425     for (index = 0; index < _BCM_TD_NUM_EXT_UCAST_QUEUE_GROUP; index++) {
    426         node = &port_info->ext_ucast[index];
    427         LOG_CLI((BSL_META_U(unit,
    428                             "ext_ucast[%d]: gport=%x numq=%d base=%d cosq_att=%d "
    429                  "hw_cosq_att=%d level=%d\n"),
    430                  index, node->gport, node->numq, node->base,
    431                  node->cosq_attached_to, node->hw_cosq_attached_to,
    432                  node->level));
    433         if (node->numq == 0) {
    434             continue;
    435         }
    436         if (node->parent != NULL) {
    437             LOG_CLI((BSL_META_U(unit,
    438                                 "  parent gport=%x\n"), node->parent->gport));
    439         }
    440         if (node->sibling != NULL) {
    441             LOG_CLI((BSL_META_U(unit,
    442                                 "  sibling gport=%x\n"), node->sibling->gport));
    443         }
    444         if (node->child != NULL) {
    445             LOG_CLI((BSL_META_U(unit,
    446                                 "  child  gport=%x\n"), node->child->gport));
    447         }
    448     }
    449 
    450     for (index = 0; index < _BCM_TD_NUM_SCHEDULER; index++) {
    451         node = &port_info->sched[index];
    452         LOG_CLI((BSL_META_U(unit,
    453                             "sched[%d]: gport=%x numq=%d base=%d cosq_att=%d "
    454                  "hw_cosq_att=%d level=%d\n"),
    455                  index, node->gport, node->numq, node->base,
    456                  node->cosq_attached_to, node->hw_cosq_attached_to,
    457                  node->level));
    458         if (node->numq == 0) {
    459             continue;
    460         }
    461         if (node->parent != NULL) {
    462             LOG_CLI((BSL_META_U(unit,
    463                                 "  parent gport=%x\n"), node->parent->gport));
    464         }
    465         if (node->sibling != NULL) {
    466             LOG_CLI((BSL_META_U(unit,
    467                                 "  sibling gport=%x\n"), node->sibling->gport));
    468         }
    469         if (node->child != NULL) {
    470             LOG_CLI((BSL_META_U(unit,
    471                                 "  child  gport=%x\n"), node->child->gport));
    472         }
    473     }
    474 
    475     return BCM_E_NONE;
    476 }
    477 #endif /* BCM_SW_STATE_DUMP_DISABLE */
    478 
    479 /*
    480  * Function:
    481  *     _bcm_td_cosq_node_get
    482  * Purpose:
    483  *     Get internal information of queue group or scheduler type GPORT
    484  * Parameters:
    485  *     unit       - (IN) unit number
    486  *     gport      - (IN) queue group/scheduler GPORT identifier
    487  *     modid      - (OUT) module identifier
    488  *     port       - (OUT) port number
    489  *     id         - (OUT) queue group or scheduler identifier
    490  *     node       - (OUT) node structure for the specified GPORT
    491  * Returns:
    492  *     BCM_E_XXX
    493  */
    494 STATIC int
    495 _bcm_td_cosq_node_get(int unit, bcm_gport_t gport, bcm_module_t *modid,
    496                       bcm_port_t *port, int *id, _bcm_td_cosq_node_t **node)
    497 {
    498     soc_info_t *si;
    499     _bcm_td_cosq_port_info_t *port_info;
    500     _bcm_td_cosq_node_t *node_base;
    501     bcm_module_t encap_modid, modid_out;
    502     bcm_port_t encap_port, port_out;
    503     uint32 encap_id;
    504     int result, index;
    505 
    506     si = &SOC_INFO(unit);
    507 
    508     if (_bcm_td_cosq_port_info[unit] == NULL) {
    509         return BCM_E_INIT;
    510     }
    511 
    512     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
    513         BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid_out));
    514         port_out = BCM_GPORT_UCAST_QUEUE_GROUP_SYSPORTID_GET(gport);
    515     } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
    516         BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid_out));
    517         port_out = BCM_GPORT_MCAST_QUEUE_GROUP_SYSPORTID_GET(gport);
    518     } else if (BCM_GPORT_IS_SCHEDULER(gport)) {
    519         encap_modid = (BCM_GPORT_SCHEDULER_GET(gport) >> 8) & 0xff;
    520         BCM_IF_ERROR_RETURN
    521             (_bcm_esw_modid_is_local(unit, encap_modid, &result));
    522         if (result != TRUE) {
    523             return BCM_E_PORT;
    524         }
    525         encap_port = BCM_GPORT_SCHEDULER_GET(gport) & 0xff;
    526         BCM_IF_ERROR_RETURN
    527             (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_SET, encap_modid,
    528                                      encap_port, &modid_out, &port_out));
    529     } else {
    530         return BCM_E_PORT;
    531     }
    532 
    533     if (!SOC_PORT_VALID(unit, port_out)) {
    534         return BCM_E_PORT;
    535     }
    536     port_info = &_bcm_td_cosq_port_info[unit][port_out];
    537 
    538     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
    539         encap_id = BCM_GPORT_UCAST_QUEUE_GROUP_QID_GET(gport);
    540         index = encap_id;
    541         if (index < _BCM_TD_NUM_UCAST_QUEUE_GROUP) {
    542             node_base = port_info->ucast;
    543         } else {
    544             index -= _BCM_TD_NUM_UCAST_QUEUE_GROUP;
    545             if (si->port_num_ext_cosq[port_out] == 0 ||
    546                 index >= _BCM_TD_NUM_EXT_UCAST_QUEUE_GROUP) {
    547                 return BCM_E_PORT;
    548             }
    549             node_base = port_info->ext_ucast;
    550         }
    551     } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
    552         encap_id = BCM_GPORT_MCAST_QUEUE_GROUP_QID_GET(gport);
    553         index = encap_id;
    554         if (index >= _BCM_TD_NUM_MCAST_QUEUE_GROUP) {
    555             return BCM_E_PORT;
    556         }
    557         node_base = port_info->mcast;
    558     } else { /* scheduler */
    559         encap_id = (BCM_GPORT_SCHEDULER_GET(gport) >> 16) & 0x3ff;
    560         index = encap_id;
    561         if (index >= _BCM_TD_NUM_SCHEDULER) {
    562             return BCM_E_PORT;
    563         }
    564         node_base = port_info->sched;
    565     }
    566 
    567     if (node_base[index].numq == 0) {
    568         return BCM_E_NOT_FOUND;
    569     }
    570 
    571     if (modid != NULL) {
    572         *modid = modid_out;
    573     }
    574     if (port != NULL) {
    575         *port = port_out;
    576     }
    577     if (id != NULL) {
    578         *id = encap_id;
    579     }
    580     if (node != NULL) {
    581         *node = &node_base[index];
    582     }
    583 
    584     return BCM_E_NONE;
    585 }
    586 
    587 /*
    588  * Function:
    589  *     _bcm_td_cosq_port_resolve
    590  * Purpose:
    591  *     Resolve following COS queue related GRPOT
    592  *         BCM_GPORT_TYPE_UCAST_QUEUE_GROUP
    593  *         BCM_GPORT_TYPE_MCAST_QUEUE_GROUP
    594  *         BCM_GPORT_TYPE SCHEDULER
    595  * Parameters:
    596  *     unit       - (IN) unit number
    597  *     gport      - (IN) queue group/scheduler GPORT identifier
    598  *     modid      - (OUT) module identifier
    599  *     port       - (OUT) port number
    600  *     trunk_id   - (OUT) trunk identifier
    601  *     id         - (OUT) queue group or scheduler identifier
    602  * Returns:
    603  *     BCM_E_XXX
    604  */
    605 int
    606 _bcm_td_cosq_port_resolve(int unit, bcm_gport_t gport, bcm_module_t *modid,
    607                           bcm_port_t *port, bcm_trunk_t *trunk_id, int *id)
    608 {
    609     BCM_IF_ERROR_RETURN
    610         (_bcm_td_cosq_node_get(unit, gport, modid, port, id, NULL));
    611 
    612 	if (trunk_id != NULL) {
    613         *trunk_id = -1;
    614     }
    615 
    616     return BCM_E_NONE;
    617 }
    618 
    619 /*
    620  * Function:
    621  *     _bcm_td_cosq_localport_resolve
    622  * Purpose:
    623  *     Resolve GRPOT if it is a local port
    624  * Parameters:
    625  *     unit       - (IN) unit number
    626  *     gport      - (IN) GPORT identifier
    627  *     local_port - (OUT) local port number
    628  * Returns:
    629  *     BCM_E_XXX
    630  */
    631 STATIC int
    632 _bcm_td_cosq_localport_resolve(int unit, bcm_gport_t gport,
    633                                bcm_port_t *local_port)
    634 {
    635     bcm_module_t module;
    636     bcm_port_t port;
    637     bcm_trunk_t trunk;
    638     int id, result;
    639 
    640     if (!BCM_GPORT_IS_SET(gport)) {
    641         if (!SOC_PORT_VALID(unit, gport)) {
    642             return BCM_E_PORT;
    643         }
    644         *local_port = gport;
    645         return BCM_E_NONE;
    646     } else if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
    647         BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) ||
    648         BCM_GPORT_IS_SCHEDULER(gport)) {
    649         return BCM_E_PORT;
    650     }
    651 
    652     BCM_IF_ERROR_RETURN
    653         (_bcm_esw_gport_resolve(unit, gport, &module, &port, &trunk, &id));
    654 
    655     BCM_IF_ERROR_RETURN(_bcm_esw_modid_is_local(unit, module, &result));
    656     if (result == FALSE) {
    657         return BCM_E_PORT;
    658     }
    659 
    660     *local_port = port;
    661 
    662     return BCM_E_NONE;
    663 }
    664 
    665 STATIC int
    666 _bcm_td_cosq_child_node_at_input(_bcm_td_cosq_node_t *node, int cosq,
    667                                   _bcm_td_cosq_node_t **child_node)
    668 {
    669     _bcm_td_cosq_node_t *cur_node;
    670 
    671     if (NULL == node) {
    672         return BCM_E_PARAM;
    673     }
    674 
    675     for (cur_node = node->child; cur_node; cur_node = cur_node->sibling) {
    676         if (cur_node->cosq_attached_to == cosq) {
    677             break;
    678         }
    679     }
    680     if (!cur_node) {
    681         return BCM_E_NOT_FOUND;
    682     }
    683 
    684     *child_node = cur_node;
    685 
    686     return BCM_E_NONE;
    687 }
    688 
    689 /*
    690  * Function:
    691  *     _bcm_td_cosq_index_resolve
    692  * Purpose:
    693  *     Find hardware index for the given port/cosq
    694  * Parameters:
    695  *     unit       - (IN) unit number
    696  *     port       - (IN) port number or GPORT identifier
    697  *     cosq       - (IN) COS queue number
    698  *     style      - (IN) index style (_BCM_TD_COSQ_INDEX_STYLE_XXX)
    699  *     local_port - (OUT) local port number
    700  *     index      - (OUT) result index
    701  *     count      - (OUT) number of index
    702  * Returns:
    703  *     BCM_E_XXX
    704  */
    705 int
    706 _bcm_td_cosq_index_resolve(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
    707                            _bcm_td_cosq_index_style_t style,
    708                            bcm_port_t *local_port, int *index, int *count)
    709 {
    710     soc_info_t *si;
    711     _bcm_td_cosq_node_t *node, *cur_node, *s3_node;
    712     bcm_port_t resolved_port, mmu_port;
    713     int resolved_index;
    714     int id, startq, numq, is_ext_cosq;
    715 
    716     si = &SOC_INFO(unit);
    717 
    718     if (cosq < -1) {
    719         return BCM_E_PARAM;
    720     } else if (cosq == -1) {
    721         startq = 0;
    722     } else {
    723         startq = cosq;
    724     }
    725 
    726     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
    727         BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) ||
    728         BCM_GPORT_IS_SCHEDULER(port)) {
    729         BCM_IF_ERROR_RETURN
    730             (_bcm_td_cosq_node_get(unit, port, NULL, &resolved_port, &id,
    731                                    &node));
    732         if (node->hw_cosq_attached_to < 0) { /* Not resolved yet */
    733             return BCM_E_NOT_FOUND;
    734         }
    735         numq = node->numq;
    736         if (startq >= numq) {
    737             return BCM_E_PARAM;
    738         }
    739     } else {
    740         /* optionally validate port */
    741         BCM_IF_ERROR_RETURN
    742             (_bcm_td_cosq_localport_resolve(unit, port, &resolved_port));
    743         if (resolved_port < 0) {
    744             return BCM_E_PORT;
    745         }
    746         node = NULL;
    747         numq = 0;
    748     }
    749 
    750     switch (style) {
    751     case _BCM_TD_COSQ_INDEX_STYLE_BUCKET:
    752         /*
    753          * hardware index for single queue bucket control:
    754          *     (MAXBUCKETCONFIG_64, MAXBUCKET,
    755          *      MINBUCKETCONFIG_64, MINBUCKET)
    756          *     cpu: index 0 - 47
    757          *     loopback port: index 0 - 4
    758          *     regular port:
    759          *         index 0 - 9 for unicast queue 0 - queue 9
    760          *         index 10 - 14 for multicast queue 0 - queue 4
    761          *     extended queue port:
    762          *         index 0 - 63 for extended unicast queue 0 - queue 63
    763          *         index 64 - 73 for unicast queue 0 - queue 9
    764          *         index 74 - 78 for multicast queue 0 - queue 4
    765          * hardware index for S3 schuduler bucket control:
    766          *     (S3_MAXBUCKETCONFIG_64, S3_MAXBUCKET,
    767          *      S3_MINBUCKETCONFIG_64, S3_MINBUCKET)
    768          *     (not for cpu port)
    769          *     index 0 - 3 for S3.0, S3.1, S3.2, S3.3 respectively
    770          * hardware index for S2 schuduler input bucket control:
    771          *     (S2_MAXBUCKETCONFIG_64, S2_MAXBUCKET,
    772          *      S2_MINBUCKETCONFIG_64, S2_MINBUCKET)
    773          *     (not for cpu port)
    774          *     index 0 for MC group
    775          *     input 1 - 3 for S2.0, S2.1, S2.2 respevtively
    776          * for non-gport:
    777          *     cpu port
    778          *         use cosq as hardware queue index
    779          *     port other than cpu:
    780          *         cosq 0 for the summary of unicast and multicast queue 0
    781          *         cosq 1 for the summary of unicast and multicast queue 1
    782          *         cosq 2 for the summary of unicast and multicast queue 2
    783          *         cosq 3 for the summary of unicast and multicast queue 3
    784          *         cosq 4 - 7 for unicast queue 4 - queue 7
    785          *         cosq 8 for unicast SC queue
    786          *         cosq 9 for unicast QM queue
    787          *         what do we want multicast SC/QM queue to be ??
    788          */
    789         if (node != NULL) {
    790             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) {
    791                 if (si->port_num_ext_cosq[resolved_port] == 0) {
    792                     resolved_index = node->base;
    793                 } else {
    794                     if (id < _BCM_TD_NUM_UCAST_QUEUE_GROUP) {
    795                         /* regular unicast queue */
    796                         resolved_index = 64 + node->base;
    797                     } else { /* extended unicast queue */
    798                         resolved_index = node->base + startq * 16;
    799                     }
    800                 }
    801             } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
    802                 if (si->port_num_ext_cosq[resolved_port] == 0) {
    803                     resolved_index = 10 + node->base;
    804                 } else {
    805                     resolved_index = 74 + node->base;
    806                 }
    807             } else { /* scheduler */
    808                 if (node->level == 2 || node->level == 3) {
    809                     numq = 1;
    810                     if (startq >= numq) {
    811                         return BCM_E_PARAM;
    812                     }
    813                     resolved_index = node->hw_cosq_attached_to;
    814                 } else {
    815                     return BCM_E_PARAM;
    816                 }
    817             }
    818         } else { /* node == NULL */
    819             if (IS_CPU_PORT(unit, resolved_port)) {
    820                 numq = si->port_num_cosq[resolved_port];
    821                 if (startq >= numq) {
    822                     return BCM_E_PARAM;
    823                 }
    824                 resolved_index = startq;
    825             } else {
    826                 numq = _BCM_TD_NUM_UCAST_QUEUE_GROUP;
    827                 if (startq >= numq) {
    828                     return BCM_E_PARAM;
    829                 }
    830                 if (startq < _BCM_TD_NUM_S3_SCHEDULER) {
    831                     /* use S3.0 - S3.3 for unicast and multicast queue 0 - 3 */
    832                     resolved_index = startq;
    833                 } else { /* unicast queue 4 - 7, SC queue, QM queue */
    834                     resolved_index = si->port_num_ext_cosq[resolved_port] +
    835                         startq;
    836                 }
    837             }
    838         }
    839         break;
    840     case _BCM_TD_COSQ_INDEX_STYLE_BUCKET_MODE:
    841         /*
    842          * hardware bit position for SHAPING_CONTROL
    843          *     cpu: bit 0 - 47
    844          *     regular port, extended queue port, and loopback port:
    845          *         bit 0 - 9 for unicast queue 0 - queue 9
    846          *         bit 10 - 14 for multicast queue 0 - queue 4
    847          *         bit 15 - 18 for S3.0, S3.1, S3.2, S3.3 respectively
    848          *         bit 19 for MC group scheduler bucket mode
    849          *         bit 20 - 22 for S2.0, S2.1, S2.2, respectively
    850          *     extended queue port:
    851          *         bit 23 - 86 for extended unicast queue 0 - queue 63
    852          *         bit 48 and up are actually in EXT1_SHAPING_CONTROL_PORTx
    853          *         for example bit 48 means bit 0 in EXT1_SHAPING_CONTROL_PORTx
    854          *         and bit 55 means bit 7 in EXT1_SHAPING_CONTROL_PORTx.
    855          * for non-gport:
    856          *     use the same interpretation as _BCM_TD_COSQ_INDEX_STYLE_BUCKET.
    857          */
    858         if (node != NULL) {
    859             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) {
    860                 if (id < _BCM_TD_NUM_UCAST_QUEUE_GROUP) {
    861                     /* regular unicast queue */
    862                     resolved_index = node->base;
    863                 } else { /* extended unicast queue */
    864                     resolved_index = 23 + node->base + startq * 16;
    865                 }
    866             } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
    867                 resolved_index = 10 + node->base;
    868             } else { /* scheduler */
    869                 numq = 1;
    870                 if (startq >= numq) {
    871                     return BCM_E_PARAM;
    872                 }
    873                 if (node->level == 2) {
    874                     resolved_index = 19 + node->hw_cosq_attached_to;
    875                 } else if (node->level == 3) {
    876                     resolved_index = 15 + node->hw_cosq_attached_to;
    877                 } else {
    878                     return BCM_E_PARAM;
    879                 }
    880             }
    881         } else { /* node == NULL */
    882             if (IS_CPU_PORT(unit, resolved_port)) {
    883                 numq = si->port_num_cosq[resolved_port];
    884                 if (startq >= numq) {
    885                     return BCM_E_PARAM;
    886                 }
    887                 resolved_index = startq;
    888             } else {
    889                 numq = _BCM_TD_NUM_UCAST_QUEUE_GROUP;
    890                 if (startq >= numq) {
    891                     return BCM_E_PARAM;
    892                 }
    893                 if (startq < _BCM_TD_NUM_S3_SCHEDULER) {
    894                     /* S3.0 - S3.3 for unicast queue 0 - 3 */
    895                     resolved_index = 15 + startq;
    896                 } else { /* unicast queue 4 - 7, SC queue, QM queue */
    897                     resolved_index = startq;
    898                 }
    899             }
    900         }
    901         break;
    902     case _BCM_TD_COSQ_INDEX_STYLE_WRED:
    903         /*
    904          * hardware index for regular port:
    905          *     (WRED_CONFIG, WRED_AVG_QSIZE)
    906          *     (not for cpu or loopback port)
    907          *     index 0 - 7 for unicast queue 0 - 7
    908          * hardware index for extended queue port:
    909          *     (DMVOQ_WRED_CONFIG, VOQ_WRED_AVG_QSIZE)
    910          *     index 0 - 63 for extended unicast queue 0 - 63
    911          *     index 64 - 71 for unicast queue 0 - 7
    912          *     (WRED_CONFIG, WRED_AVG_QSIZE)
    913          *     index 0: summary of unicast queue 0 and extended queue 0 - 15
    914          *     index 1: summary of unicast queue 1 and extended queue 16 - 31
    915          *     index 2: summary of unicast queue 2 and extended queue 32 - 47
    916          *     index 3: summary of unicast queue 3 and extended queue 48 - 63
    917          *     these summary does not need to equal to the sum of corresponding
    918          *     entries in DMVOQ_WRED_CONFIG
    919          * for non-gport:
    920          *     regular port:
    921          *         use cosq as hardware queue index
    922          *         cosq 0 - 7 for unicast queue 0 - queue 7
    923          *     extended queue port:
    924          *         cosq 0 - 7 for unicast queue 0 - queue 7
    925          *         cosq 8 - 71 for extended unicast queue 0 - 63
    926          *         instead of using hardwre queue index, adjust it to
    927          *         make the unicast queue has the same cosq number as regular
    928          *         port
    929          */
    930         if (node != NULL) {
    931             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) {
    932                 if (id < _BCM_TD_NUM_UCAST_QUEUE_GROUP) {
    933                     /* regular unicast queue */
    934                     if (node->base >= _BCM_TD_NUM_NON_SC_QM_UCAST_QUEUE) {
    935                         /* unicast SC or QM queue */
    936                         return BCM_E_PARAM;
    937                     }
    938                     if (si->port_num_ext_cosq[resolved_port] == 0) {
    939                         resolved_index = node->base;
    940                     } else {
    941                         resolved_index = 64 + node->base;
    942                     }
    943                 } else { /* extended unicast queue */
    944                     resolved_index = node->base + startq * 16;
    945                 }
    946             } else { /* multicast queue group or scheduler */
    947                 return BCM_E_PARAM;
    948             }
    949         } else { /* node == NULL */
    950             if (IS_CPU_PORT(unit, resolved_port) ||
    951                 IS_LB_PORT(unit, resolved_port)) {
    952                 return BCM_E_PORT;
    953             }
    954             /* regular ucast and extended ucast queues */
    955             numq = _BCM_TD_NUM_NON_SC_QM_UCAST_QUEUE +
    956                 si->port_num_ext_cosq[resolved_port];
    957             if (startq >= numq) {
    958                 return BCM_E_PARAM;
    959             }
    960             if (startq < _BCM_TD_NUM_NON_SC_QM_UCAST_QUEUE) {
    961                 resolved_index = si->port_num_ext_cosq[resolved_port] + startq;
    962             } else {
    963                 resolved_index = startq - _BCM_TD_NUM_NON_SC_QM_UCAST_QUEUE;
    964             }
    965         }
    966         break;
    967     case _BCM_TD_COSQ_INDEX_STYLE_WRED_DROP_THRESH:
    968         /*
    969          * hardware index:
    970          *     (WRED_DROP_THD_UC_ENQ0, WRED_DROP_THD_UC_ENQ1,
    971          *      WRED_DROP_THD_UC_DEQ0, WRED_DROP_THD_UC_DEQ1)
    972          *     (not for cpu or loopback port)
    973          *     regular port:
    974          *         index 0 - 63 for port 1 extended unicast queue 63 - 0
    975          *         index 64 - 127 for port 2 extended unicast queue 63 - 0
    976          *         index 128 - 191 for port 3 extended unicast queue 63 - 0
    977          *         index 192 - 255 for port 4 extended unicast queue 63 - 0
    978          *         index 256 - 319 for port 34 extended unicast queue 63 - 0
    979          *         index 320 - 383 for port 35 extended unicast queue 63 - 0
    980          *         index 384 - 447 for port 36 extended unicast queue 63 - 0
    981          *         index 448 - 511 for port 37 extended unicast queue 63 - 0
    982          *         index 512 - 519 for port 64 unicast queue 0 - 7
    983          *         index 520 - 775 for port 1 - 32 unicast queue 0 - 7
    984          *         index 776 - 783 for port 65 unicast queue 0 - 7
    985          *         index 784 - 1023 for port 34 - 63 unicast queue 0 - 7
    986          * for non-gport:
    987          *     regular port:
    988          *         use cosq as hardware queue index
    989          *         cosq 0 - 7 for unicast queue 0 - queue 7
    990          *     extended queue port:
    991          *         cosq 0 - 7 for unicast queue 0 - queue 7
    992          *         cosq 8 - 71 for extended unicast queue 0 - 63
    993          */
    994         is_ext_cosq = FALSE;
    995         if (node != NULL) {
    996             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) {
    997                 if (id < _BCM_TD_NUM_UCAST_QUEUE_GROUP) {
    998                     /* regular unicast queue */
    999                     if (node->base >= _BCM_TD_NUM_NON_SC_QM_UCAST_QUEUE) {
   1000                         /* unicast SC or QM queue */
   1001                         return BCM_E_PARAM;
   1002                     }
   1003                     resolved_index = node->base;
   1004                 } else { /* extended unicast queue */
   1005                     resolved_index = 63 - node->base + startq * 16;
   1006                     is_ext_cosq = TRUE;
   1007                 }
   1008             } else { /* multicast queue group or scheduler */
   1009                 return BCM_E_PARAM;
   1010             }
   1011         } else { /* node == NULL */
   1012             if (IS_CPU_PORT(unit, resolved_port) ||
   1013                 IS_LB_PORT(unit, resolved_port)) {
   1014                 return BCM_E_PORT;
   1015             }
   1016             /* regular ucast and extended ucast queues */
   1017             numq = _BCM_TD_NUM_NON_SC_QM_UCAST_QUEUE +
   1018                 si->port_num_ext_cosq[resolved_port];
   1019             if (startq >= numq) {
   1020                 return BCM_E_PARAM;
   1021             }
   1022             if (startq < _BCM_TD_NUM_NON_SC_QM_UCAST_QUEUE) {
   1023                 resolved_index = startq;
   1024             } else {
   1025                 resolved_index =
   1026                     63 - (startq - _BCM_TD_NUM_NON_SC_QM_UCAST_QUEUE);
   1027                 is_ext_cosq = TRUE;
   1028             }
   1029         }
   1030         /* Add port base offset */
   1031         mmu_port = si->port_p2m_mapping[si->port_l2p_mapping[resolved_port]];
   1032         if (is_ext_cosq) {
   1033             if (mmu_port < 33) {
   1034                 resolved_index += (mmu_port - 1) *
   1035                     si->port_num_ext_cosq[resolved_port];
   1036             } else {
   1037                 resolved_index += 256 + (mmu_port - 34) *
   1038                     si->port_num_ext_cosq[resolved_port];
   1039             }
   1040         } else {
   1041             if (mmu_port < 64) {
   1042                 resolved_index +=
   1043                     512 + mmu_port * _BCM_TD_NUM_NON_SC_QM_UCAST_QUEUE;
   1044             } else if (mmu_port == 64) {
   1045                 resolved_index += 512;
   1046             } else {
   1047                 resolved_index += 776;
   1048             }
   1049         }
   1050         break;
   1051     case _BCM_TD_COSQ_INDEX_STYLE_SCHEDULER:
   1052         /*
   1053          * hardware index for (S1) COSWEIGHTS:
   1054          *     cpu port
   1055          *         index 0 - 47 are for queue 0 - 47
   1056          *     regular port, extended queue port, and loopback port:
   1057          *         index 0 is for multicast group scheduler
   1058          *         index 1 - 3 are for S2.1, S2.2, S2.3 respectively
   1059          *         index 4 is for multicast SC and QM queue
   1060          *         index 5 is for unicast SC queue
   1061          *         index 6 is for unicast QM queue
   1062          * hardware index for S2_COSWEIGHTS:
   1063          *     (not for cpu port)
   1064          *     index 0 - 3 are for S3.0, S3.1, S3.2, S3.3 respectively
   1065          *     index 4 - 11 are for unicast queue 0 - 7
   1066          * hardware bit position for S2_COSMASK, S2_MINSPCONFIG:
   1067          *     (not for cpu port)
   1068          *     bit 0 - 3 are for S3.0, S3.1, S3.2, S3.3 respectively
   1069          *     bit 4 - 11 are for unicast queue 0 - 7
   1070          * hardware index for S3_COSWEIGHTS:
   1071          *     (not for cpu port)
   1072          *     regular port:
   1073          *         index 0, 2, 4, 6 are for multicast queue 0, 1, 2, 3
   1074          *             respectively
   1075          *         index 1, 3, 5, 7 are for unicast queue 0, 1, 2, 3
   1076          *             respectively
   1077          *     extended queue port:
   1078          *         index 0, 18, 36, 54 are for multicast queue 0, 1, 2, 3
   1079          *             respectively
   1080          *         index 1, 19, 37, 55 are for unicast queue 0, 1, 2, 3
   1081          *             respectively
   1082          *         index 2 - 17 are for extended unicast queue 0 - 15
   1083          *         index 20 - 35 are for extended unicast queue 16 - 31
   1084          *         index 38 - 53 are for extended unicast queue 32 - 47
   1085          *         index 56 - 71 are for extended unicast queue 48 - 63
   1086          * hardware bit position for S3_COSMASK, S3_MINSPCONFIG:
   1087          *     (not for cpu port)
   1088          *     there are 4 entries in each register
   1089          *         entry 0 is for input to S3.0
   1090          *         entry 1 is for input to S3.1
   1091          *         entry 2 is for input to S3.2
   1092          *         entry 3 is for input to S3.3
   1093          *     regular port and extended queue port:
   1094          *         bit 0 of entry 0 is for multicast queue 0
   1095          *         bit 0 of entry 1 is for multicast queue 1
   1096          *         bit 0 of entry 2 is for multicast queue 2
   1097          *         bit 0 of entry 3 is for multicast queue 3
   1098          *         bit 1 of entry 0 is for unicast queue 0
   1099          *         bit 1 of entry 1 is for unicast queue 1
   1100          *         bit 1 of entry 2 is for unicast queue 2
   1101          *         bit 1 of entry 3 is for unicast queue 3
   1102          *     extended queue port:
   1103          *         bit 2 - 17 of entry 0 are for extended unicast queue 0 - 15
   1104          *         bit 2 - 17 of entry 1 are for extended unicast queue 16 - 31
   1105          *         bit 2 - 17 of entry 2 are for extended unicast queue 32 - 47
   1106          *         bit 2 - 17 of entry 3 are for extended unicast queue 48 - 63
   1107          * hardware bit position for S3_COSMASK_MC, S3_MINSPCONFIG_MC:
   1108          *    bit 0 - 3 for multicast queue 0 - 3
   1109          */
   1110         if (node != NULL) {
   1111             if (BCM_GPORT_IS_SCHEDULER(port)) {
   1112                 for (cur_node = node->child; cur_node != NULL;
   1113                      cur_node = cur_node->sibling) {
   1114                     if (cur_node->cosq_attached_to == startq) {
   1115                         break;
   1116                     }
   1117                 }
   1118                 if (cur_node == NULL) {
   1119                     if (node->level == 3 &&
   1120                         si->port_num_ext_cosq[resolved_port] != 0) {
   1121                         /* search to see if it matches the extended unicast
   1122                          * queue index from the corresponding S3.0 node */
   1123                         for (s3_node = node->parent->child; s3_node != NULL;
   1124                              s3_node = s3_node->sibling) {
   1125                             if (s3_node->hw_cosq_attached_to == 0) { /* S3.0 */
   1126                                 break;
   1127                             }
   1128                         }
   1129                         if (s3_node != NULL) {
   1130                             for (cur_node = s3_node->child; cur_node != NULL;
   1131                                  cur_node = cur_node->sibling) {
   1132                                 if (cur_node->cosq_attached_to == startq) {
   1133                                     break;
   1134                                 }
   1135                             }
   1136                         }
   1137                     }
   1138                 }
   1139                 if (cur_node == NULL) {
   1140                     /* Nothing is attached to the specified cosq */
   1141                     resolved_index = -1;
   1142                 } else if (node->level == 3) { /* S3 scheduler */
   1143                     resolved_index = node->hw_cosq_attached_to *
   1144                         (si->port_num_ext_cosq[resolved_port] ? 18 : 2) +
   1145                         cur_node->hw_cosq_attached_to;
   1146                 } else if (node->level == 2 &&
   1147                            node->hw_cosq_attached_to == 0) {
   1148                     /* MC group scheduler */
   1149                     resolved_index = cur_node->hw_cosq_attached_to *
   1150                         (si->port_num_ext_cosq[resolved_port] ? 18 : 2);
   1151                 } else { /* S1 or S2 scheduler */
   1152                     resolved_index = cur_node->hw_cosq_attached_to;
   1153                 }
   1154             } else { /* unicast queue group or multicast queue group */
   1155                 return BCM_E_PARAM;
   1156             }
   1157         } else { /* node == NULL */
   1158             if (IS_CPU_PORT(unit, resolved_port)) {
   1159                 numq = si->num_cpu_cosq;
   1160                 if (startq >= numq) {
   1161                     return BCM_E_PARAM;
   1162                 }
   1163                 resolved_index = startq;
   1164             } else { /* S2.0 scheduler */
   1165                 numq = _BCM_TD_NUM_NON_SC_QM_UCAST_QUEUE;
   1166                 if (startq >= numq) {
   1167                     return BCM_E_PARAM;
   1168                 }
   1169                 /*
   1170                  * cosq 0 - 3 (via S3.0 - S3.3) map to index 0 - 3
   1171                  * cosq 4 - 7 map to index 8 - 11
   1172                  */
   1173                 resolved_index = startq >= 4 ? startq + 4 : startq;
   1174             }
   1175         }
   1176         break;
   1177     case _BCM_TD_COSQ_INDEX_STYLE_PERQ_XMT:
   1178         /*
   1179          * software assigned index for cpu port:
   1180          *     index 0 - 47
   1181          * software assigned index for loopback port:
   1182          *     index 0 - 8
   1183          * software assigned index for regular port:
   1184          *     index 0 - 9 for unicast queue 0 - 9
   1185          *     index 10 - 14 for multicast queue 0 - 4
   1186          * software assigned index for extended queue port:
   1187          *     index 0 - 9 for unicast queue 0 - 9
   1188          *     index 10 - 14 for multicast queue 0 - 4
   1189          *     index 15 - 78 for extended unicast queue 0 - 63
   1190          */
   1191         if (node != NULL) {
   1192             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) {
   1193                 if (id < _BCM_TD_NUM_UCAST_QUEUE_GROUP) {
   1194                     /* regular unicast queue */
   1195                     resolved_index = node->base;
   1196                 } else { /* extended unicast queue */
   1197                     resolved_index = si->port_num_uc_cosq[resolved_port] +
   1198                         si->port_num_cosq[resolved_port] +
   1199                         node->base + startq * 16;
   1200                 }
   1201             } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
   1202                 /* multicast queue */
   1203                 resolved_index = si->port_num_uc_cosq[resolved_port] +
   1204                     node->base;
   1205             } else { /* scheduler */
   1206                 return BCM_E_PARAM;
   1207             }
   1208         } else { /* node == NULL */
   1209             numq = si->port_num_uc_cosq[resolved_port] +
   1210                 si->port_num_cosq[resolved_port] +
   1211                 si->port_num_ext_cosq[resolved_port];
   1212             if (startq >= numq) {
   1213                 return BCM_E_PARAM;
   1214             }
   1215             resolved_index = startq;
   1216         }
   1217         break;
   1218     case _BCM_TD_COSQ_INDEX_STYLE_UCAST_DROP:
   1219         if (node != NULL) {
   1220             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) {
   1221                 if (id >= _BCM_TD_NUM_UCAST_QUEUE_GROUP) {
   1222                     /* extended unicast queue */
   1223                     return BCM_E_PARAM;
   1224                 }
   1225                 if (si->port_num_ext_cosq[resolved_port] == 0) {
   1226                     resolved_index = node->base;
   1227                 } else {
   1228                     resolved_index = 64 + node->base;
   1229                 }
   1230             } else { /* multicast queue group or scheduler */
   1231                 return BCM_E_PARAM;
   1232             }
   1233         } else { /* node == NULL */
   1234             numq = si->port_num_uc_cosq[resolved_port];
   1235             if (startq >= numq) {
   1236                 return BCM_E_PARAM;
   1237             }
   1238             if (si->port_num_ext_cosq[resolved_port] == 0) {
   1239                 resolved_index = startq;
   1240             } else {
   1241                 resolved_index = 64 + startq;
   1242             }
   1243         }
   1244         break;
   1245     case _BCM_TD_COSQ_INDEX_STYLE_UCAST_QUEUE:
   1246         if (node != NULL) {
   1247             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) {
   1248                 if (id >= _BCM_TD_NUM_UCAST_QUEUE_GROUP) {
   1249                     /* extended unicast queue */
   1250                     return BCM_E_PARAM;
   1251                 }
   1252                 resolved_index = node->base;
   1253             } else { /* multicast queue group or scheduler */
   1254                 return BCM_E_PARAM;
   1255             }
   1256         } else { /* node == NULL */
   1257             numq = si->port_num_uc_cosq[resolved_port];
   1258             if (startq >= numq) {
   1259                 return BCM_E_PARAM;
   1260             }
   1261             resolved_index = startq;
   1262         }
   1263         break;
   1264     case _BCM_TD_COSQ_INDEX_STYLE_MCAST_QUEUE:
   1265         if (node != NULL) {
   1266             if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
   1267                 resolved_index = node->base;
   1268             } else { /* unicast queue group or scheduler */
   1269                 return BCM_E_PARAM;
   1270             }
   1271         } else { /* node == NULL */
   1272             numq = si->port_num_cosq[resolved_port];
   1273             if (startq >= numq) {
   1274                 return BCM_E_PARAM;
   1275             }
   1276             resolved_index = startq;
   1277         }
   1278         break;
   1279     case _BCM_TD_COSQ_INDEX_STYLE_EXT_UCAST_QUEUE:
   1280         if (node != NULL) {
   1281             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) {
   1282                 if (id < _BCM_TD_NUM_UCAST_QUEUE_GROUP) {
   1283                     /* regular unicast queue */
   1284                     return BCM_E_PARAM;
   1285                 }
   1286                 resolved_index = node->base + startq * 16;
   1287             } else { /* multicast queue group or scheduler */
   1288                 return BCM_E_PARAM;
   1289             }
   1290         } else { /* node == NULL */
   1291             numq = si->port_num_ext_cosq[resolved_port];
   1292             if (startq >= numq) {
   1293                 return BCM_E_PARAM;
   1294             }
   1295             resolved_index = startq;
   1296         }
   1297         break;
   1298     case _BCM_TD_COSQ_INDEX_STYLE_EGR_POOL:
   1299         if (node != NULL) {
   1300             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) {
   1301                 if (id < _BCM_TD_NUM_UCAST_QUEUE_GROUP) {
   1302                     /* regular unicast queue */
   1303                     resolved_index = node->base;
   1304                 } else { /* extended unicast queue */
   1305                     resolved_index = node->base + startq * 16;
   1306                 }
   1307             } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
   1308                 resolved_index = node->base;
   1309             } else { /* scheduler */
   1310                 return BCM_E_PARAM;
   1311             }
   1312         } else { /* node == NULL */
   1313             numq = si->port_num_cosq[resolved_port];
   1314             if (startq >= numq) {
   1315                 return BCM_E_PARAM;
   1316             }
   1317             resolved_index = startq;
   1318         }
   1319         break;
   1320 
   1321     case _BCM_TD_COSQ_INDEX_STYLE_UC_EGR_POOL:
   1322         numq = si->port_num_uc_cosq[resolved_port];
   1323         if (startq >= numq) {
   1324                 return BCM_E_PARAM;
   1325         }
   1326         resolved_index = startq;
   1327         break;
   1328 
   1329     default:
   1330         return BCM_E_INTERNAL;
   1331     }
   1332 
   1333     if (index != NULL) {
   1334         if (resolved_index == -1) {
   1335             return BCM_E_NOT_FOUND;
   1336         }
   1337         *index = resolved_index;
   1338     }
   1339     if (local_port != NULL) {
   1340         *local_port = resolved_port;
   1341     }
   1342     if (count != NULL) {
   1343         *count = cosq == -1 ? numq : 1;
   1344     }
   1345 
   1346     return BCM_E_NONE;
   1347 }
   1348 
   1349 /*
   1350  * Function:
   1351  *     _bcm_td_cosq_node_resolve
   1352  * Purpose:
   1353  *     Resolve queue number in the specified scheduler tree and its subtree
   1354  * Parameters:
   1355  *     unit       - (IN) unit number
   1356  *     port       - (IN) port number
   1357  *     node       - (IN) node structure for the specified scheduler node
   1358  *     cosq       - (IN) COS queue to attach to
   1359  * Returns:
   1360  *     BCM_E_XXX
   1361  */
   1362 STATIC int
   1363 _bcm_td_cosq_node_resolve(int unit, bcm_port_t port, _bcm_td_cosq_node_t *node,
   1364                           bcm_cos_queue_t cosq)
   1365 {
   1366     soc_info_t *si;
   1367     _bcm_td_cosq_node_t *s1_node, *s2_node, *q_node, *cur_node;
   1368     uint32 map, s1_map, s2_map, mcg_map, s3_mc_map, s3_uc_map, s3_ext_uc_map;
   1369     int base, i;
   1370 
   1371     if (node->parent == NULL) {
   1372         /* Not attached, should never happen */
   1373         return BCM_E_NOT_FOUND;
   1374     }
   1375 
   1376     si = &SOC_INFO(unit);
   1377 
   1378     /* find the current cosq_attached_to usage */
   1379     map = 0;
   1380     for (cur_node = node->parent->child; cur_node != NULL;
   1381          cur_node = cur_node->sibling) {
   1382         if (cur_node->cosq_attached_to >= 0) {
   1383             map |= 1 << cur_node->cosq_attached_to;
   1384         }
   1385     }
   1386 
   1387     if (cosq < 0) {
   1388         for (i = 0; i < node->parent->numq; i++) {
   1389             if ((map & (1 << i)) == 0) {
   1390                 node->cosq_attached_to = i;
   1391                 break;
   1392             }
   1393         }
   1394         if (i == node->parent->numq) {
   1395             return BCM_E_PARAM;
   1396         }
   1397     } else {
   1398         if (map & (1 << cosq)) {
   1399             return BCM_E_EXISTS;
   1400         }
   1401         node->cosq_attached_to = cosq;
   1402     }
   1403     node->hw_cosq_attached_to = -1;
   1404 
   1405     /* find the current S3 to S2 mapping */
   1406     s3_mc_map = 0;
   1407     s3_uc_map = 0;
   1408     s3_ext_uc_map = 0;
   1409     s2_map = 0;
   1410     mcg_map = 0;
   1411     s1_map = 0;
   1412     for (s1_node = node->parent; s1_node->parent != NULL;
   1413          s1_node = s1_node->parent);
   1414     for (s2_node = s1_node->child; s2_node != NULL;
   1415          s2_node = s2_node->sibling) {
   1416         if (s2_node->hw_cosq_attached_to < 0) {
   1417             /* S2/MC group node may not be resolved yet */
   1418             continue;
   1419         }
   1420         s1_map |= 1 << s2_node->hw_cosq_attached_to;
   1421         if (s2_node->hw_cosq_attached_to == 0) { /* MC group node */
   1422             for (q_node = s2_node->child; q_node != NULL;
   1423                  q_node = q_node->sibling) {
   1424                 mcg_map |= 1 << q_node->hw_cosq_attached_to;
   1425             }
   1426         } else if (s2_node->hw_cosq_attached_to < 4) {
   1427             /* S2 node can be mapped to input 1, 2, or 3 of S1 node */
   1428             for (cur_node = s2_node->child; cur_node != NULL;
   1429                  cur_node = cur_node->sibling) {
   1430                 s2_map |= 1 << cur_node->hw_cosq_attached_to;
   1431                 if (cur_node->hw_cosq_attached_to < 4) {
   1432                     /* S3 node can be mapped to input 0, 1, 2, or 3 of S2
   1433                      * node */
   1434                     for (q_node = cur_node->child; q_node != NULL;
   1435                          q_node = q_node->sibling) {
   1436                         if (q_node->hw_cosq_attached_to < 0) {
   1437                             continue;
   1438                         } else if (q_node->hw_cosq_attached_to == 0) {
   1439                             /* multicast queue is always mapped to input 0 of
   1440                              * S3 node */
   1441                             s3_mc_map |= 1 << cur_node->hw_cosq_attached_to;
   1442                         } else if (q_node->hw_cosq_attached_to == 1) {
   1443                             /* unicast queue is always mapped to input 1 of
   1444                              * S3 node */
   1445                             s3_uc_map |= 1 << cur_node->hw_cosq_attached_to;
   1446                         } else {
   1447                             /* extended unicast queue can be mapped to input 2
   1448                              * to 17 of S3 node */
   1449                             s3_ext_uc_map |=
   1450                                 1 << (q_node->hw_cosq_attached_to - 2);
   1451                         }
   1452                     }
   1453                 }
   1454             }
   1455         }
   1456     }
   1457 
   1458     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(node->gport)) {
   1459         if (BCM_GPORT_UCAST_QUEUE_GROUP_QID_GET(node->gport) <
   1460             _BCM_TD_NUM_UCAST_QUEUE_GROUP) {
   1461             /* regular ucast queue */
   1462             if (node->parent->level == 1) {
   1463                 if ((s1_map & 0x60) == 0x60) {
   1464                     /* both SC queue and QM queue have been assigned */
   1465                     return BCM_E_FAIL;
   1466                 }
   1467             } else if (node->parent->level == 2) {
   1468                 if (node->parent->hw_cosq_attached_to == 0) {
   1469                     /* ucast queue can not attach to MC group */
   1470                     return BCM_E_FAIL;
   1471                 }
   1472                 if (((s2_map & 0xf00) == 0xf00) && s3_uc_map != 0) {
   1473                     /* ucast queue 4-7 have already been assigned,
   1474                      * but one or more of ucast queue 0-3 has attached to S3 */
   1475                     return BCM_E_FAIL;
   1476                 }
   1477             } else if (node->parent->level == 3) {
   1478                 if ((s2_map & 0x0f0) != 0) {
   1479                 /* One or more of ucast queue 0-3 has attached to S2 */
   1480                     return BCM_E_FAIL;
   1481                 }
   1482             } else {
   1483                 return BCM_E_FAIL;
   1484             }
   1485         } else {
   1486             /* extended ucast queue */
   1487             if (node->parent->level != 3) {
   1488                 return BCM_E_FAIL;
   1489             }
   1490         }
   1491     } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(node->gport)) {
   1492         if (node->parent->level == 1) {
   1493             if ((s1_map & 0x10) == 0x10) {
   1494                 /* multicast SC/QM queue has been assigned */
   1495                 return BCM_E_FAIL;
   1496             }
   1497         } else if (node->parent->level == 2) {
   1498             if (node->parent->hw_cosq_attached_to >= 1 &&
   1499                 node->parent->hw_cosq_attached_to <= 3) {
   1500                 /* mcast queue can not attach to S2 */
   1501                 return BCM_E_FAIL;
   1502             }
   1503             if (s3_mc_map != 0) {
   1504                 /* Some mcast queue has attached to S3 */
   1505                 return BCM_E_FAIL;
   1506             }
   1507         } else if (node->parent->level == 3) {
   1508             if (mcg_map != 0) {
   1509                 /* Some mcast queue has attached to MC group */
   1510                 return BCM_E_FAIL;
   1511             }
   1512         } else {
   1513             return BCM_E_FAIL;
   1514         }
   1515     } else if (BCM_GPORT_IS_SCHEDULER(node->gport)) {
   1516         if (node->parent->level == 1) {
   1517             if ((s1_map & 0x00f) == 0x00f) {
   1518                 /* There are only 3 S2 schedulers and 1 MC group scheduler */
   1519                 return BCM_E_FAIL;
   1520             }
   1521             if (node->numq > _BCM_TD_S2_SCHEDULER_NUM_INPUT) {
   1522                 /* hardware allows up to 9 input */
   1523                 return BCM_E_FAIL;
   1524             }
   1525         } else if (node->parent->level == 2) {
   1526             if ((s2_map & 0x00f) == 0x00f) {
   1527                 /* There are only 4 S3 schedulers */
   1528                 return BCM_E_FAIL;
   1529             }
   1530             if (si->port_num_ext_cosq[port] == 0) { /* regular port */
   1531                 if (node->numq > _BCM_TD_S3_SCHEDULER_NUM_INPUT) {
   1532                     /* possible input: 1 UC, 1 MC */
   1533                     return BCM_E_FAIL;
   1534                 }
   1535             } else { /* extended queue port */
   1536                 if (node->numq > _BCM_TD_EXT_S3_SCHEDULER_NUM_INPUT) {
   1537                     /* possible input: 1 UC, 1 MC, 16 EXT UC */
   1538                     return BCM_E_FAIL;
   1539                 }
   1540             }
   1541         } else {
   1542             return BCM_E_FAIL;
   1543         }
   1544     } else {
   1545         return BCM_E_INTERNAL;
   1546     }
   1547 
   1548     /* Resolve S2/MC group node if needed */
   1549     if (node->parent->level == 2 && node->parent->hw_cosq_attached_to < 0) {
   1550         s2_node = node->parent;
   1551         if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(node->gport)) {
   1552             /* MC group node is always mapped to input 0 of S1 node */
   1553             s2_node->hw_cosq_attached_to = 0;
   1554             s2_node->base = 0;
   1555         } else {
   1556             /* S2 node can be mapped to input 1, 2, or 3 of S1 node */
   1557             for (i = 1; i < 4; i++) {
   1558                 if ((s1_map & (1 << i)) == 0) {
   1559                     s2_node->hw_cosq_attached_to = i;
   1560                     s2_node->base = 0;
   1561                     break;
   1562                 }
   1563             }
   1564             if (s2_node->hw_cosq_attached_to < 0) {
   1565                 return BCM_E_FAIL;
   1566             }
   1567         }
   1568     }
   1569 
   1570     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(node->gport)) {
   1571         if (BCM_GPORT_UCAST_QUEUE_GROUP_QID_GET(node->gport) <
   1572             _BCM_TD_NUM_UCAST_QUEUE_GROUP) {
   1573             /* regular unicast queue */
   1574             if (node->parent->level == 1) {
   1575                 if (!(s1_map & 0x20)) { /* unicast SC queue */
   1576                     node->hw_cosq_attached_to = 5;
   1577                     node->base = 8;
   1578                 } else { /* unicast QM queue */
   1579                     node->hw_cosq_attached_to = 6;
   1580                     node->base = 9;
   1581                 }
   1582             } else if (node->parent->level == 2) {
   1583                 /* If regular unicast queue is attached to S2 scheduler,
   1584                  * queue 0 - 3 can be mapped to input 4 - 7 of S2 node,
   1585                  * queue 4 - 7 are fixed mapped to input 8 - 11 of S2 node */
   1586                 base = (s2_map & 0xf00) == 0xf00 ? 4 : 8;
   1587                 for (i = 0; i < 4; i++) {
   1588                     if ((s2_map & (1 << (base + i))) == 0) {
   1589                         node->hw_cosq_attached_to = base + i;
   1590                         node->base = node->hw_cosq_attached_to - 4;
   1591                         break;
   1592                     }
   1593                 }
   1594             } else if (node->parent->level == 3) {
   1595                 /* If regular unicast queue is attached to S3 scheduler,
   1596                  * queue 0 - 3 are fixed mapped to input 1 of S3 node 0 - 3,
   1597                  * S3 node 0 - 3 are mapped to input 0 - 3 of each S2 node */
   1598                 node->hw_cosq_attached_to = 1;
   1599                 node->base = node->parent->hw_cosq_attached_to;
   1600             } else {
   1601                 return BCM_E_FAIL;
   1602             }
   1603         } else { /* extended unicast queue */
   1604             if (node->parent->level == 3) {
   1605                 /* queue 0 - 15 are fixed mapped to input 2 - 17 of S3 node 0,
   1606                  * queue 16 - 31 are fixed mapped to input 2 - 17 of S3 node 1,
   1607                  * queue 32 - 47 are fixed mapped to input 2 - 17 of S3 node 2,
   1608                  * queue 48 - 63 are fixed mapped to input 2 - 17 of S3 node 3,
   1609                  * S3 node 0 - 3 are mapped to input 0 - 3 of each S2 node */
   1610                 for (i = 0; i < _BCM_TD_NUM_EXT_UCAST_QUEUE_GROUP; i++) {
   1611                     if ((s3_ext_uc_map & (1 << i)) == 0) {
   1612                         node->hw_cosq_attached_to = 2 + i;
   1613                         node->base = i;
   1614                         s3_ext_uc_map |= 1 << i;
   1615                         break;
   1616                     }
   1617                 }
   1618             }
   1619         }
   1620     } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(node->gport)) {
   1621         if (node->parent->level == 1) { /* multicast SC/QM queue */
   1622             node->hw_cosq_attached_to = 4;
   1623             node->base = 4;
   1624         } else if (node->parent->level == 2) {
   1625             /* If multicast queue is attached to MC group scheduler,
   1626              * queue 0 - 3 are mapped to input 0 - 3 of MC group node */
   1627             for (i = 0; i < _BCM_TD_NUM_MCAST_QUEUE_GROUP; i++) {
   1628                 if ((mcg_map & (1 << i)) == 0) {
   1629                     node->hw_cosq_attached_to = i;
   1630                     node->base = i;
   1631                     break;
   1632                 }
   1633             }
   1634         } else if (node->parent->level == 3) {
   1635             /* If multicast queue is attached to S3 scheduler,
   1636              * queue 0 - 3 are fixed mapped to input 0 of S3 node 0 - 3,
   1637              * S3 node 0 - 3 are mapped to input 0 - 3 of each S2 node */
   1638             node->hw_cosq_attached_to = 0;
   1639             node->base = node->parent->hw_cosq_attached_to;
   1640         }
   1641     } else if (BCM_GPORT_IS_SCHEDULER(node->gport)) {
   1642         if (node->parent->level == 1) {
   1643             /* We can not foresee if this node is S2.x or MC group yet */
   1644         } else if (node->parent->level == 2 ) {
   1645             for (i = 0; i < _BCM_TD_NUM_S3_SCHEDULER; i++) {
   1646                 /* S3 node can be mapped to input 0, 1, 2, or 3 of S2 node */
   1647                 if ((s2_map & (1 << i)) == 0) {
   1648                     node->hw_cosq_attached_to = i;
   1649                     node->base = 0;
   1650                     break;
   1651                 }
   1652             }
   1653         }
   1654         node->level = node->parent->level + 1;
   1655     }
   1656 
   1657     return BCM_E_NONE;
   1658 }
   1659 
   1660 STATIC int
   1661 _bcm_td_cosq_sched_node_set(int unit, bcm_port_t port)
   1662 {
   1663     uint64 rval64[3];
   1664     uint32 rval;
   1665     int uc_to_s2, use_mc_group, index;
   1666     _bcm_td_cosq_port_info_t *port_info;
   1667     _bcm_td_cosq_node_t *s1_node, *s2_node, *cur_node;
   1668     int i;
   1669     static const soc_field_t fields[] = {
   1670         S3_GROUP_NO_I0f, S3_GROUP_NO_I1f, S3_GROUP_NO_I2f, S3_GROUP_NO_I3f,
   1671         S3_GROUP_NO_I4f, S3_GROUP_NO_I5f, S3_GROUP_NO_I6f, S3_GROUP_NO_I7f,
   1672         S3_GROUP_NO_I8f
   1673     };
   1674 
   1675     COMPILER_64_ZERO(rval64[0]);
   1676     for (index = 0; index < 9; index++) {
   1677         soc_reg64_field32_set(unit, S2_S3_ROUTINGr, &rval64[0], fields[index],
   1678                               0x1f);
   1679     }
   1680     rval64[1] = rval64[0];
   1681     rval64[2] = rval64[0];
   1682 
   1683     port_info = &_bcm_td_cosq_port_info[unit][port];
   1684     s1_node = NULL;
   1685     for (i = 0; i < _BCM_TD_NUM_SCHEDULER; i++) {
   1686         if (port_info->sched[i].level == 1) {
   1687             s1_node = &port_info->sched[i];
   1688             break;
   1689         }
   1690     }
   1691     if (s1_node != NULL) {
   1692         use_mc_group = 0;
   1693         uc_to_s2 = 0;
   1694         for (s2_node = s1_node->child; s2_node != NULL;
   1695              s2_node = s2_node->sibling) {
   1696             if (s2_node->hw_cosq_attached_to < 0) {
   1697                 continue;
   1698             } else if (s2_node->hw_cosq_attached_to == 0) { /* MC group */
   1699                 if (s2_node->child != NULL) {
   1700                     use_mc_group = 1;
   1701                 }
   1702             } else if (s2_node->hw_cosq_attached_to < 4) { /* S2 */
   1703                 index = s2_node->hw_cosq_attached_to - 1;
   1704                 for (cur_node = s2_node->child; cur_node != NULL;
   1705                      cur_node = cur_node->sibling) {
   1706                     soc_reg64_field32_set(unit, S2_S3_ROUTINGr, &rval64[index],
   1707                                           fields[cur_node->cosq_attached_to],
   1708                                           cur_node->hw_cosq_attached_to);
   1709                     if (cur_node->hw_cosq_attached_to >= 4 &&
   1710                         cur_node->hw_cosq_attached_to < 8) {
   1711                         /* at least one of unicast queue 0 - 3 is directly
   1712                          * attached to S2 */
   1713                         uc_to_s2 = 1;
   1714                     }
   1715                 }
   1716             }
   1717         }
   1718 
   1719         BCM_IF_ERROR_RETURN(READ_S3_CONFIGr(unit, port, &rval));
   1720         soc_reg_field_set(unit, S3_CONFIGr, &rval, ROUTE_UC_TO_S2f, uc_to_s2);
   1721         BCM_IF_ERROR_RETURN(WRITE_S3_CONFIGr(unit, port, rval));
   1722 
   1723         BCM_IF_ERROR_RETURN(READ_S3_CONFIG_MCr(unit, port, &rval));
   1724         soc_reg_field_set(unit, S3_CONFIG_MCr, &rval, USE_MC_GROUPf,
   1725                           use_mc_group);
   1726         BCM_IF_ERROR_RETURN(WRITE_S3_CONFIG_MCr(unit, port, rval));
   1727     } else {
   1728         /* make it act like a non-ETS style scheduler
   1729          * unicast queue 0 and multicast queue 0 connect to S3.0
   1730          * unicast queue 1 and multicast queue 1 connect to S3.1
   1731          * unicast queue 2 and multicast queue 2 connect to S3.2
   1732          * unicast queue 3 and multicast queue 3 connect to S3.3
   1733          * S3.0 - S3.3 and unicast queue 4 - 7 connect to S2.0
   1734          * S2.1, S2.2, MC group are not used
   1735          */
   1736         /* S3.0 - S3.3 to S2.0 input 0 - 3 (S3 group number 0 - 3)*/
   1737         for (i = 0; i < _BCM_TD_NUM_S3_SCHEDULER; i++) {
   1738             soc_reg64_field32_set(unit, S2_S3_ROUTINGr, &rval64[0], fields[i],
   1739                                   i);
   1740         }
   1741         /* unicast queues 4 - 7 to S2.0 input 4 - 7 (S3 group number 8 - 11) */
   1742         for (i = _BCM_TD_NUM_S3_SCHEDULER;
   1743              i < _BCM_TD_NUM_NON_SC_QM_UCAST_QUEUE; i++) {
   1744             soc_reg64_field32_set(unit, S2_S3_ROUTINGr, &rval64[0], fields[i],
   1745                                   i + 4);
   1746         }
   1747 
   1748         rval = 0;
   1749         soc_reg_field_set(unit, S3_CONFIGr, &rval, SCHEDULING_SELECTf, 0x55);
   1750         BCM_IF_ERROR_RETURN(WRITE_S3_CONFIGr(unit, port, rval));
   1751 
   1752         BCM_IF_ERROR_RETURN(WRITE_S3_CONFIG_MCr(unit, port, 0));
   1753 
   1754         rval = 0;
   1755         soc_reg_field_set(unit, S2_CONFIGr, &rval, SCHEDULING_SELECTf, 0x15);
   1756         BCM_IF_ERROR_RETURN(WRITE_S2_CONFIGr(unit, port, rval));
   1757     }
   1758 
   1759     for (index = 0; index < _BCM_TD_NUM_S2_SCHEDULER; index++) {
   1760         BCM_IF_ERROR_RETURN
   1761             (WRITE_S2_S3_ROUTINGr(unit, port, index, rval64[index]));
   1762     }
   1763 
   1764     return BCM_E_NONE;
   1765 }
   1766 
   1767 /*
   1768  * Function:
   1769  *     _bcm_td_cosq_node_unresolve
   1770  * Purpose:
   1771  *     Unresolve queue number in the specified scheduler tree and its subtree
   1772  * Parameters:
   1773  *     unit       - (IN) unit number
   1774  *     node       - (IN) node structure for the specified scheduler node
   1775  * Returns:
   1776  *     BCM_E_XXX
   1777  */
   1778 STATIC int
   1779 _bcm_td_cosq_node_unresolve(int unit, _bcm_td_cosq_node_t *node)
   1780 {
   1781     if (node->cosq_attached_to < 0) {
   1782         /* Has been unresolved already */
   1783         return BCM_E_NONE;
   1784     }
   1785 
   1786     if (node->child != NULL) {
   1787         _bcm_td_cosq_node_unresolve(unit, node->child);
   1788     }
   1789 
   1790     if (node->sibling != NULL && node->sibling->cosq_attached_to >= 0) {
   1791         _bcm_td_cosq_node_unresolve(unit, node->sibling);
   1792     }
   1793 
   1794     node->cosq_attached_to = -1;
   1795     node->hw_cosq_attached_to = -1;
   1796     node->level = 0;
   1797     node->parent = NULL;
   1798     node->sibling = NULL;
   1799     node->child = NULL;
   1800 
   1801     return BCM_E_NONE;
   1802 }
   1803 
   1804 STATIC int
   1805 _bcm_td_cosq_config_set(int unit, int numq)
   1806 {
   1807     port_cos_map_entry_t cos_map_entries[16];
   1808     void *entries[1], *hg_entries[1];
   1809     uint32 index, hg_index;
   1810     int count, hg_count;
   1811     bcm_port_t port;
   1812     int cos, prio;
   1813     uint32 i;
   1814 #ifdef BCM_COSQ_HIGIG_MAP_DISABLE
   1815     port_cos_map_entry_t hg_cos_map_entries[16];
   1816 #endif
   1817 
   1818     if (numq < 1 || numq > 8) {
   1819         return BCM_E_PARAM;
   1820     }
   1821 
   1822     /* Distribute first 8 internal priority levels into the specified number
   1823      * of cosq, map remaining internal priority levels to highest priority
   1824      * cosq */
   1825     sal_memset(cos_map_entries, 0, sizeof(cos_map_entries));
   1826     entries[0] = &cos_map_entries;
   1827     hg_entries[0] = &cos_map_entries;
   1828     prio = 0;
   1829     for (cos = 0; cos < numq; cos++) {
   1830         for (i = 8 / numq + (cos < 8 % numq ? 1 : 0); i > 0; i--) {
   1831             soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio],
   1832                                 COSf, cos);
   1833             prio++;
   1834         }
   1835     }
   1836     for (prio = 8; prio < 16; prio++) {
   1837         soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[prio], COSf,
   1838                             numq - 1);
   1839     }
   1840 
   1841     /* Map internal priority levels to CPU CoS queues */
   1842     BCM_IF_ERROR_RETURN(_bcm_esw_cpu_cosq_mapping_default_set(unit, numq));
   1843 
   1844 #ifdef BCM_COSQ_HIGIG_MAP_DISABLE
   1845     /* Use identical mapping for Higig port */
   1846     sal_memset(hg_cos_map_entries, 0, sizeof(hg_cos_map_entries));
   1847     hg_entries[0] = &hg_cos_map_entries;
   1848     prio = 0;
   1849     for (prio = 0; prio < 8; prio++) {
   1850         soc_mem_field32_set(unit, PORT_COS_MAPm, &hg_cos_map_entries[prio],
   1851                             COSf, prio);
   1852     }
   1853     for (prio = 8; prio < 16; prio++) {
   1854         soc_mem_field32_set(unit, PORT_COS_MAPm, &hg_cos_map_entries[prio],
   1855                             COSf, 7);
   1856     }
   1857 #endif /* BCM_COSQ_HIGIG_MAP_DISABLE */
   1858 
   1859     BCM_IF_ERROR_RETURN
   1860         (soc_profile_mem_add(unit, _bcm_td_cos_map_profile[unit], entries, 16,
   1861                              &index));
   1862     BCM_IF_ERROR_RETURN
   1863         (soc_profile_mem_add(unit, _bcm_td_cos_map_profile[unit], hg_entries,
   1864                              16, &hg_index));
   1865     count = 0;
   1866     hg_count = 0;
   1867     PBMP_ALL_ITER(unit, port) {
   1868         if (IS_HG_PORT(unit, port)) {
   1869             BCM_IF_ERROR_RETURN
   1870                 (soc_mem_field32_modify(unit, COS_MAP_SELm, port, SELECTf,
   1871                                         hg_index / 16));
   1872             hg_count++;
   1873         } else {
   1874             BCM_IF_ERROR_RETURN
   1875                 (soc_mem_field32_modify(unit, COS_MAP_SELm, port, SELECTf,
   1876                                         index / 16));
   1877             count++;
   1878         }
   1879     }
   1880     if (SOC_INFO(unit).cpu_hg_index != -1) {
   1881         BCM_IF_ERROR_RETURN
   1882             (soc_mem_field32_modify(unit, COS_MAP_SELm,
   1883                                     SOC_INFO(unit).cpu_hg_index, SELECTf,
   1884                                     hg_index / 16));
   1885         hg_count++;
   1886     }
   1887     for (i = 1; i < count; i++) {
   1888         soc_profile_mem_reference(unit, _bcm_td_cos_map_profile[unit], index,
   1889                                   0);
   1890     }
   1891     for (i = 1; i < hg_count; i++) {
   1892         soc_profile_mem_reference(unit, _bcm_td_cos_map_profile[unit],
   1893                                   hg_index, 0);
   1894     }
   1895 
   1896     _bcm_td_num_cosq[unit] = numq;
   1897 
   1898     return BCM_E_NONE;
   1899 }
   1900 
   1901 /*
   1902  * Function:
   1903  *     _bcm_td_cosq_mapping_set
   1904  * Purpose:
   1905  *     Set COS queue for the specified priority of an ingress port
   1906  * Parameters:
   1907  *     unit     - (IN) unit number
   1908  *     ing_port - (IN) ingress port
   1909  *     gport    - (IN) queue group GPORT identifier
   1910  *     priority - (IN) priority value to map
   1911  *     flags    - (IN) BCM_COSQ_GPORT_XXX_QUEUE_GROUP
   1912  *     gport    - (IN) queue group GPORT identifier
   1913  *     cosq     - (IN) COS queue number
   1914  * Returns:
   1915  *     BCM_E_XXX
   1916  */
   1917 int
   1918 _bcm_td_cosq_mapping_set(int unit, bcm_port_t ing_port, bcm_cos_t priority,
   1919                          uint32 flags, bcm_gport_t gport, bcm_cos_queue_t cosq)
   1920 {
   1921     bcm_port_t local_port;
   1922     bcm_cos_queue_t hw_cosq, mc_hw_cosq = 0;
   1923     soc_field_t field, field2 = INVALIDf;
   1924     cos_map_sel_entry_t cos_map_sel_entry;
   1925     port_cos_map_entry_t cos_map_entries[16];
   1926     void *entries[1];
   1927     uint32 old_index, new_index;
   1928     int rv;
   1929 
   1930     if (priority < 0 || priority >= 16) {
   1931         return BCM_E_PARAM;
   1932     }
   1933 
   1934     BCM_IF_ERROR_RETURN
   1935         (_bcm_td_cosq_localport_resolve(unit, ing_port, &local_port));
   1936 
   1937     switch (flags) {
   1938     case BCM_COSQ_GPORT_UCAST_QUEUE_GROUP:
   1939         if (gport == -1) {
   1940 	    hw_cosq = cosq;
   1941 	} else {
   1942             BCM_IF_ERROR_RETURN
   1943                 (_bcm_td_cosq_index_resolve
   1944                  (unit, gport, cosq, _BCM_TD_COSQ_INDEX_STYLE_UCAST_QUEUE,
   1945                   NULL, &hw_cosq, NULL));
   1946         }
   1947         field = UC_COS1f;
   1948         break;
   1949     case BCM_COSQ_GPORT_MCAST_QUEUE_GROUP:
   1950         if (gport == -1) {
   1951 	    hw_cosq = cosq;
   1952 	} else {
   1953         BCM_IF_ERROR_RETURN
   1954             (_bcm_td_cosq_index_resolve
   1955              (unit, gport, cosq, _BCM_TD_COSQ_INDEX_STYLE_MCAST_QUEUE,
   1956               NULL, &hw_cosq, NULL));
   1957         }
   1958         field = MC_COS1f;
   1959         break;
   1960     case BCM_COSQ_GPORT_UCAST_QUEUE_GROUP | BCM_COSQ_GPORT_MCAST_QUEUE_GROUP:
   1961         if (gport == -1) {
   1962             hw_cosq = (cosq >> 16) & 0xffff;
   1963             mc_hw_cosq = cosq & 0xffff;
   1964         } else {
   1965             return BCM_E_PARAM;
   1966         }
   1967         field = UC_COS1f;
   1968         field2 = MC_COS1f;
   1969         break;    
   1970     case BCM_COSQ_GPORT_DESTMOD_UCAST_QUEUE_GROUP:
   1971         if (gport == -1) {
   1972 	    return BCM_E_UNAVAIL; 
   1973 	} else {
   1974         BCM_IF_ERROR_RETURN
   1975             (_bcm_td_cosq_index_resolve
   1976              (unit, gport, cosq, _BCM_TD_COSQ_INDEX_STYLE_EXT_UCAST_QUEUE,
   1977               NULL, &hw_cosq, NULL));
   1978         }
   1979         field = HG_COSf;
   1980         break;
   1981     default:
   1982         return BCM_E_PARAM;
   1983     }
   1984 
   1985     /* There are only 5 MC QUEUES [0,4] attached to a port. */
   1986     if (flags == BCM_COSQ_GPORT_MCAST_QUEUE_GROUP) {
   1987         if (hw_cosq > (_BCM_TD_NUM_MCAST_QUEUE_GROUP - 1)) {
   1988             return BCM_E_PARAM;
   1989         }
   1990     }
   1991 
   1992     entries[0] = &cos_map_entries;
   1993 
   1994     BCM_IF_ERROR_RETURN
   1995         (READ_COS_MAP_SELm(unit, MEM_BLOCK_ANY, local_port,
   1996                            &cos_map_sel_entry));
   1997     old_index = soc_mem_field32_get(unit, COS_MAP_SELm, &cos_map_sel_entry,
   1998                                     SELECTf);
   1999     old_index *= 16;
   2000 
   2001     BCM_IF_ERROR_RETURN
   2002         (soc_profile_mem_get(unit, _bcm_td_cos_map_profile[unit],
   2003                              old_index, 16, entries));
   2004     soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[priority], field,
   2005                         hw_cosq);
   2006     if (field2 != INVALIDf) {
   2007         soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[priority],
   2008                             field2,mc_hw_cosq);
   2009     }
   2010     
   2011     soc_mem_lock(unit, PORT_COS_MAPm);
   2012 
   2013     rv = soc_profile_mem_delete(unit, _bcm_td_cos_map_profile[unit],
   2014                                 old_index);
   2015 #ifndef BCM_COSQ_HIGIG_MAP_DISABLE
   2016     if (BCM_SUCCESS(rv) && IS_CPU_PORT(unit, local_port)) {
   2017         rv = soc_profile_mem_delete(unit, _bcm_td_cos_map_profile[unit],
   2018                                     old_index);
   2019     }
   2020 #endif /* BCM_COSQ_HIGIG_MAP_DISABLE */
   2021     if (BCM_FAILURE(rv)) {
   2022         soc_mem_unlock(unit, PORT_COS_MAPm);
   2023         return rv;
   2024     }
   2025 
   2026     rv = soc_profile_mem_add(unit, _bcm_td_cos_map_profile[unit], entries,
   2027                              16, &new_index);
   2028 #ifndef BCM_COSQ_HIGIG_MAP_DISABLE
   2029     if (BCM_SUCCESS(rv) && IS_CPU_PORT(unit, local_port)) {
   2030         rv = soc_profile_mem_reference(unit, _bcm_td_cos_map_profile[unit],
   2031                                        new_index, 16);
   2032     }
   2033 #endif /* BCM_COSQ_HIGIG_MAP_DISABLE */
   2034 
   2035     if (rv == SOC_E_RESOURCE) {
   2036         (void)soc_profile_mem_reference(unit, _bcm_td_cos_map_profile[unit],
   2037                                         old_index, 16);
   2038 #ifndef BCM_COSQ_HIGIG_MAP_DISABLE
   2039         if (IS_CPU_PORT(unit, local_port)) {
   2040             (void)soc_profile_mem_reference(unit,
   2041                                             _bcm_td_cos_map_profile[unit],
   2042                                             old_index, 16);
   2043         }
   2044 #endif /* BCM_COSQ_HIGIG_MAP_DISABLE */
   2045     }
   2046 
   2047     soc_mem_unlock(unit, PORT_COS_MAPm);
   2048 
   2049     if (BCM_FAILURE(rv)) {
   2050         return rv;
   2051     }
   2052 
   2053     soc_mem_field32_set(unit, COS_MAP_SELm, &cos_map_sel_entry, SELECTf,
   2054                         new_index / 16);
   2055     BCM_IF_ERROR_RETURN
   2056         (WRITE_COS_MAP_SELm(unit, MEM_BLOCK_ANY, local_port,
   2057                             &cos_map_sel_entry));
   2058 
   2059 #ifndef BCM_COSQ_HIGIG_MAP_DISABLE
   2060     if (IS_CPU_PORT(unit, local_port)) {
   2061         BCM_IF_ERROR_RETURN
   2062             (soc_mem_field32_modify(unit, COS_MAP_SELm,
   2063                                     SOC_INFO(unit).cpu_hg_index, SELECTf,
   2064                                     new_index / 16));
   2065     }
   2066 #endif /* BCM_COSQ_HIGIG_MAP_DISABLE */
   2067 
   2068     if (flags == BCM_COSQ_GPORT_DESTMOD_UCAST_QUEUE_GROUP) {
   2069         BCM_IF_ERROR_RETURN
   2070             (_bcm_td_voq_gport_mapping_set(unit, gport, priority, cosq));
   2071     }
   2072 
   2073     return BCM_E_NONE;
   2074 }
   2075 
   2076 /*
   2077  * Function:
   2078  *     _bcm_td_cosq_mapping_get
   2079  * Purpose:
   2080  *     Get COS queue for the specified priority of an ingress port
   2081  * Parameters:
   2082  *     unit     - (IN) unit number
   2083  *     ing_port - (IN) ingress port
   2084  *     gport    - (IN) queue group GPORT identifier
   2085  *     priority - (IN) priority value to map
   2086  *     flags    - (IN) BCM_COSQ_GPORT_XXX_QUEUE_GROUP
   2087  *     gport    - (OUT) queue group GPORT identifier
   2088  *     cosq     - (OUT) COS queue number
   2089  * Returns:
   2090  *     BCM_E_XXX
   2091  */
   2092 int
   2093 _bcm_td_cosq_mapping_get(int unit, bcm_port_t ing_port, bcm_cos_t priority,
   2094                          uint32 flags, bcm_gport_t *gport,
   2095                          bcm_cos_queue_t *cosq)
   2096 {
   2097     _bcm_td_cosq_port_info_t *port_info;
   2098     _bcm_td_cosq_node_t *node;
   2099     bcm_port_t local_port;
   2100     bcm_cos_queue_t hw_cosq;
   2101     int index, i;
   2102     cos_map_sel_entry_t cos_map_sel_entry;
   2103     void *entry_p;
   2104 
   2105     if (priority < 0 || priority >= 16) {
   2106         return BCM_E_PARAM;
   2107     }
   2108 
   2109     if (flags != BCM_COSQ_GPORT_UCAST_QUEUE_GROUP &&
   2110         flags != BCM_COSQ_GPORT_MCAST_QUEUE_GROUP &&
   2111         flags != BCM_COSQ_GPORT_DESTMOD_UCAST_QUEUE_GROUP) {
   2112         return BCM_E_PARAM;
   2113     }
   2114 
   2115     BCM_IF_ERROR_RETURN
   2116         (_bcm_td_cosq_localport_resolve(unit, ing_port, &local_port));
   2117 
   2118     BCM_IF_ERROR_RETURN
   2119         (READ_COS_MAP_SELm(unit, MEM_BLOCK_ANY, local_port,
   2120                            &cos_map_sel_entry));
   2121     index = soc_mem_field32_get(unit, COS_MAP_SELm, &cos_map_sel_entry,
   2122                                 SELECTf);
   2123     index *= 16;
   2124 
   2125     entry_p = SOC_PROFILE_MEM_ENTRY(unit, _bcm_td_cos_map_profile[unit],
   2126                                     port_cos_map_entry_t *,
   2127                                     index + priority);
   2128 
   2129     switch (flags) {
   2130     case BCM_COSQ_GPORT_UCAST_QUEUE_GROUP:
   2131         hw_cosq = soc_mem_field32_get(unit, PORT_COS_MAPm, entry_p, UC_COS1f);
   2132         if (IS_CPU_PORT(unit, local_port) || IS_LB_PORT(unit, local_port) ||
   2133             !gport) {
   2134             if (gport) {
   2135                 *gport = BCM_GPORT_INVALID;
   2136             }
   2137             *cosq = hw_cosq;
   2138         } else {
   2139             port_info = &_bcm_td_cosq_port_info[unit][local_port];
   2140             for (i = 0; i < _BCM_TD_NUM_UCAST_QUEUE_GROUP; i++) {
   2141                 node = &port_info->ucast[i];
   2142                 if (node->numq > 0 && node->base == hw_cosq) {
   2143                     *gport = node->gport;
   2144                     *cosq = 0;
   2145                     break;
   2146                 }
   2147             }
   2148             if (i == _BCM_TD_NUM_UCAST_QUEUE_GROUP) {
   2149                 return BCM_E_NOT_FOUND;
   2150             }
   2151         }
   2152         break;
   2153     case BCM_COSQ_GPORT_MCAST_QUEUE_GROUP:
   2154         hw_cosq = soc_mem_field32_get(unit, PORT_COS_MAPm, entry_p, MC_COS1f);
   2155         if (IS_CPU_PORT(unit, local_port) || IS_LB_PORT(unit, local_port) ||
   2156             !gport) {
   2157             if (gport) {
   2158                 *gport = BCM_GPORT_INVALID;
   2159             }
   2160             *cosq = hw_cosq;
   2161         } else {
   2162             port_info = &_bcm_td_cosq_port_info[unit][local_port];
   2163             for (i = 0; i < _BCM_TD_NUM_MCAST_QUEUE_GROUP; i++) {
   2164                 node = &port_info->mcast[i];
   2165                 if (node->numq > 0 && node->base == hw_cosq) {
   2166                     *gport = node->gport;
   2167                     *cosq = 0;
   2168                     break;
   2169                 }
   2170             }
   2171             if (i == _BCM_TD_NUM_MCAST_QUEUE_GROUP) {
   2172                 return BCM_E_NOT_FOUND;
   2173             }
   2174         }
   2175         break;
   2176     case BCM_COSQ_GPORT_DESTMOD_UCAST_QUEUE_GROUP:
   2177         hw_cosq = soc_mem_field32_get(unit, PORT_COS_MAPm, entry_p, HG_COSf);
   2178         if (IS_CPU_PORT(unit, local_port) || IS_LB_PORT(unit, local_port) ||
   2179             !gport) {
   2180             if (gport) {
   2181                 *gport = BCM_GPORT_INVALID;
   2182             }
   2183             *cosq = hw_cosq;
   2184         } else {
   2185             port_info = &_bcm_td_cosq_port_info[unit][local_port];
   2186             for (i = 0; i < _BCM_TD_NUM_EXT_UCAST_QUEUE_GROUP; i++) {
   2187                 node = &port_info->ext_ucast[i];
   2188                 if (node->numq > 0 && node->base == hw_cosq % 16) {
   2189                     *gport = node->gport;
   2190                     *cosq = hw_cosq / 16;
   2191                     break;
   2192                 }
   2193             }
   2194             if (i == _BCM_TD_NUM_EXT_UCAST_QUEUE_GROUP) {
   2195                 return BCM_E_NOT_FOUND;
   2196             }
   2197         }
   2198         break;
   2199     }
   2200 
   2201     return BCM_E_NONE;
   2202 }
   2203 
   2204 /*
   2205  *  Convert HW drop probability to percent value
   2206  */
   2207 STATIC int
   2208 _bcm_td_hw_drop_prob_to_percent[] = {
   2209     0,     /* 0  */
   2210     1,     /* 1  */
   2211     2,     /* 2  */
   2212     3,     /* 3  */
   2213     4,     /* 4  */
   2214     5,     /* 5  */
   2215     6,     /* 6  */
   2216     7,     /* 7  */
   2217     8,     /* 8  */
   2218     9,     /* 9  */
   2219     10,    /* 10 */
   2220     25,    /* 11 */
   2221     50,    /* 12 */
   2222     75,    /* 13 */
   2223     100,   /* 14 */
   2224     -1     /* 15 */
   2225 };
   2226 
   2227 STATIC int
   2228 _bcm_td_percent_to_drop_prob(int percent)
   2229 {
   2230    int i;
   2231 
   2232    for (i = 14; i > 0 ; i--) {
   2233       if (percent >= _bcm_td_hw_drop_prob_to_percent[i]) {
   2234           break;
   2235       }
   2236    }
   2237    return i;
   2238 }
   2239 
   2240 STATIC int
   2241 _bcm_td_drop_prob_to_percent(int drop_prob) {
   2242    return (_bcm_td_hw_drop_prob_to_percent[drop_prob]);
   2243 }
   2244 
   2245 /*
   2246  * index: degree, value: contangent(degree) * 100
   2247  * max value is 0xffff (16-bit) at 0 degree
   2248  */
   2249 STATIC int
   2250 _bcm_td_cotangent_lookup_table[] =
   2251 {
   2252     /*  0.. 5 */  65535, 5728, 2863, 1908, 1430, 1143,
   2253     /*  6..11 */    951,  814,  711,  631,  567,  514,
   2254     /* 12..17 */    470,  433,  401,  373,  348,  327,
   2255     /* 18..23 */    307,  290,  274,  260,  247,  235,
   2256     /* 24..29 */    224,  214,  205,  196,  188,  180,
   2257     /* 30..35 */    173,  166,  160,  153,  148,  142,
   2258     /* 36..41 */    137,  132,  127,  123,  119,  115,
   2259     /* 42..47 */    111,  107,  103,  100,   96,   93,
   2260     /* 48..53 */     90,   86,   83,   80,   78,   75,
   2261     /* 54..59 */     72,   70,   67,   64,   62,   60,
   2262     /* 60..65 */     57,   55,   53,   50,   48,   46,
   2263     /* 66..71 */     44,   42,   40,   38,   36,   34,
   2264     /* 72..77 */     32,   30,   28,   26,   24,   23,
   2265     /* 78..83 */     21,   19,   17,   15,   14,   12,
   2266     /* 84..89 */     10,    8,    6,    5,    3,    1,
   2267     /* 90     */      0
   2268 };
   2269 
   2270 /*
   2271  * Given a slope (angle in degrees) from 0 to 90, return the number of cells
   2272  * in the range from 0% drop probability to 100% drop probability.
   2273  */
   2274 STATIC int
   2275 _bcm_td_angle_to_cells(int angle)
   2276 {
   2277     return (_bcm_td_cotangent_lookup_table[angle]);
   2278 }
   2279 
   2280 /*
   2281  * Given a number of packets in the range from 0% drop probability
   2282  * to 100% drop probability, return the slope (angle in degrees).
   2283  */
   2284 STATIC int
   2285 _bcm_td_cells_to_angle(int packets)
   2286 {
   2287     int angle;
   2288 
   2289     for (angle = 90; angle >= 0 ; angle--) {
   2290         if (packets <= _bcm_td_cotangent_lookup_table[angle]) {
   2291             break;
   2292         }
   2293     }
   2294     return angle;
   2295 }
   2296 
   2297 STATIC int
   2298 _bcm_td_cosq_refresh_freeze(int unit)
   2299 {
   2300     uint32 reg;
   2301     int rv = BCM_E_NONE;
   2302 
   2303     if (soc_feature(unit, soc_feature_bucket_update_freeze)) {
   2304         TD_COSQ_LOCK(unit);
   2305 
   2306         rv = READ_MISCCONFIGr(unit, &reg);
   2307         if (BCM_FAILURE(rv)) {
   2308             TD_COSQ_UNLOCK(unit);
   2309             return rv;
   2310         }
   2311         soc_reg_field_set(unit, MISCCONFIGr, &reg, REFRESH_ENf, 0);
   2312         rv = WRITE_MISCCONFIGr(unit, reg);
   2313         if (BCM_FAILURE(rv)) {
   2314             TD_COSQ_UNLOCK(unit);
   2315             return rv;
   2316         }
   2317     }
   2318 
   2319     return rv;
   2320 }
   2321 
   2322 STATIC int
   2323 _bcm_td_cosq_refresh_thaw(int unit)
   2324 {
   2325     uint32 reg;
   2326     int rv = BCM_E_NONE;
   2327 
   2328     if (soc_feature(unit, soc_feature_bucket_update_freeze)) {
   2329         rv = READ_MISCCONFIGr(unit, &reg);
   2330         if (BCM_FAILURE(rv)) {
   2331             TD_COSQ_UNLOCK(unit);
   2332             return rv;
   2333         }
   2334         soc_reg_field_set(unit, MISCCONFIGr, &reg, REFRESH_ENf, 1);
   2335         rv = WRITE_MISCCONFIGr(unit, reg);
   2336         if (BCM_FAILURE(rv)) {
   2337             TD_COSQ_UNLOCK(unit);
   2338             return rv;
   2339         }
   2340 
   2341         TD_COSQ_UNLOCK(unit);
   2342     }
   2343 
   2344     return rv;
   2345 }
   2346 
   2347 /*
   2348  * Function:
   2349  *     _bcm_td_cosq_bucket_set
   2350  * Purpose:
   2351  *     Configure COS queue bandwidth control bucket
   2352  * Parameters:
   2353  *     unit          - (IN) unit number
   2354  *     port          - (IN) port number or GPORT identifier
   2355  *     cosq          - (IN) COS queue number
   2356  *     min_bandwidth - (IN) min bucket bandwidth (kbps or packet/second)
   2357  *     max_bandwidth - (IN) max bucket bandwidth (kbps or packet/second)
   2358  *     min_burst     - (IN) min bucket burst size (kbits or packets)
   2359  *     max_burst     - (IN) max bucket burst size (kbits or packets)
   2360  *     flags         - (IN) BCM_COSQ_BW_PACKET_MODE_XXX
   2361  * Returns:
   2362  *     BCM_E_XXX
   2363  * Notes:
   2364  *     If port is any form of local port, cosq is the hardware queue index.
   2365  */
   2366 STATIC int
   2367 _bcm_td_cosq_bucket_set(int unit, bcm_gport_t port, bcm_cos_queue_t cosq,
   2368                         uint32 min_bandwidth, uint32 max_bandwidth,
   2369                         uint32 min_burst, uint32 max_burst,
   2370                         uint32 flags)
   2371 {
   2372     soc_info_t *si;
   2373     _bcm_td_cosq_node_t *node;
   2374     bcm_port_t local_port, mmu_port, mmu_cmic_port, mmu_lb_port;
   2375     int rv, index;
   2376     soc_reg_t max_config_reg, max_reg, min_config_reg, min_reg, shaping_reg;
   2377     uint32 rval, fval;
   2378     uint32 orig_bandwidth, orig_burst;
   2379     uint64 rval64, orig_rval64, bucket_rval64, mode_rval64;
   2380     uint32 refresh_rate, bucketsize, granularity, meter_flags;
   2381     int refresh_bitsize, bucket_bitsize;
   2382     static const soc_reg_t ext_shaping_reg_x[] = {
   2383         EXT1_SHAPING_CONTROL_PORT1r, EXT1_SHAPING_CONTROL_PORT2r,
   2384         EXT1_SHAPING_CONTROL_PORT3r, EXT1_SHAPING_CONTROL_PORT4r
   2385     };
   2386     static const soc_reg_t ext_shaping_reg_y[] = {
   2387         EXT1_SHAPING_CONTROL_PORT34r, EXT1_SHAPING_CONTROL_PORT35r,
   2388         EXT1_SHAPING_CONTROL_PORT36r, EXT1_SHAPING_CONTROL_PORT37r
   2389     };
   2390 
   2391     if (cosq < 0) {
   2392         if (cosq == -1) {
   2393             /* caller needs to resolve the wild card value (-1) */
   2394             return BCM_E_INTERNAL;
   2395         } else { /* reject all other negative value */
   2396             return BCM_E_PARAM;
   2397         }
   2398     }
   2399 
   2400     BCM_IF_ERROR_RETURN
   2401         (_bcm_td_cosq_index_resolve(unit, port, cosq,
   2402                                     _BCM_TD_COSQ_INDEX_STYLE_BUCKET,
   2403                                     &local_port, &index, NULL));
   2404 
   2405     if (BCM_GPORT_IS_SCHEDULER(port)) {
   2406         BCM_IF_ERROR_RETURN
   2407             (_bcm_td_cosq_node_get(unit, port, NULL, NULL, NULL, &node));
   2408         if (node->level == 3) { /* S3 scheduler */
   2409             max_config_reg = S3_MAXBUCKETCONFIG_64r;
   2410             max_reg = S3_MAXBUCKETr;
   2411             min_config_reg = S3_MINBUCKETCONFIG_64r;
   2412             min_reg = S3_MINBUCKETr;
   2413         } else if (node->level == 2) { /* S2 scheduler */
   2414             max_config_reg = S2_MAXBUCKETCONFIG_64r;
   2415             max_reg = S2_MAXBUCKETr;
   2416             min_config_reg = S2_MINBUCKETCONFIG_64r;
   2417             min_reg = S2_MINBUCKETr;
   2418         } else {
   2419             return BCM_E_PARAM;
   2420         }
   2421     } else if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
   2422                BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
   2423         max_config_reg = MAXBUCKETCONFIG_64r;
   2424         max_reg = MAXBUCKETr;
   2425         min_config_reg = MINBUCKETCONFIG_64r;
   2426         min_reg = MINBUCKETr;
   2427     } else { /* local port */
   2428         if (cosq < _BCM_TD_NUM_S3_SCHEDULER &&
   2429             !IS_CPU_PORT(unit, local_port)) {
   2430             /* use S3.0 - S3.3 for unicast and multicast queue 0 - 3 */
   2431             max_config_reg = S3_MAXBUCKETCONFIG_64r;
   2432             max_reg = S3_MAXBUCKETr;
   2433             min_config_reg = S3_MINBUCKETCONFIG_64r;
   2434             min_reg = S3_MINBUCKETr;
   2435         } else { /* unicast queue 4 - 7 */
   2436             max_config_reg = MAXBUCKETCONFIG_64r;
   2437             max_reg = MAXBUCKETr;
   2438             min_config_reg = MINBUCKETCONFIG_64r;
   2439             min_reg = MINBUCKETr;
   2440         }
   2441     }
   2442 
   2443     meter_flags = flags & BCM_COSQ_BW_PACKET_MODE ?
   2444         _BCM_TD_METER_FLAG_PACKET_MODE : 0;
   2445     BCM_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, &rval));
   2446     if (soc_reg_field_get(unit, MISCCONFIGr, rval, ITU_MODE_SELf)) {
   2447         meter_flags |= _BCM_TD_METER_FLAG_NON_LINEAR;
   2448     }
   2449 
   2450     /* Retrieve MAXBUCKETCONFIG_64 and max bucket size */
   2451     BCM_IF_ERROR_RETURN(_bcm_td_cosq_refresh_freeze(unit));
   2452     BCM_IF_ERROR_RETURN
   2453         (soc_reg_get(unit, max_config_reg, local_port, index, &orig_rval64));
   2454     BCM_IF_ERROR_RETURN(_bcm_td_cosq_refresh_thaw(unit));
   2455     granularity =
   2456         soc_reg64_field32_get(unit, max_config_reg, orig_rval64, METER_GRANf);
   2457     refresh_rate =
   2458         soc_reg64_field32_get(unit, max_config_reg, orig_rval64, MAX_REFRESHf);
   2459     bucketsize =
   2460         soc_reg64_field32_get(unit, max_config_reg, orig_rval64, MAX_THDf);
   2461     BCM_IF_ERROR_RETURN
   2462         (_bcm_td_bucket_encoding_to_rate(unit, refresh_rate, bucketsize,
   2463                                          granularity, meter_flags,
   2464                                          &orig_bandwidth, &orig_burst));
   2465 
   2466     /* Construct MAXBUCKETCONFIG_64 */
   2467     refresh_bitsize = soc_reg_field_length(unit, max_config_reg, MAX_REFRESHf);
   2468     bucket_bitsize = soc_reg_field_length(unit, max_config_reg, MAX_THDf);
   2469     BCM_IF_ERROR_RETURN
   2470         (_bcm_td_rate_to_bucket_encoding(unit, max_bandwidth, max_burst,
   2471                                          meter_flags, refresh_bitsize,
   2472                                          bucket_bitsize, &refresh_rate,
   2473                                          &bucketsize, &granularity));
   2474     COMPILER_64_ZERO(rval64);
   2475     soc_reg64_field32_set(unit, max_config_reg, &rval64, METER_GRANf,
   2476                           granularity);
   2477     soc_reg64_field32_set(unit, max_config_reg, &rval64, MAX_REFRESHf,
   2478                           refresh_rate);
   2479     soc_reg64_field32_set(unit, max_config_reg, &rval64, MAX_THDf, bucketsize);
   2480 
   2481     if (COMPILER_64_NE(rval64, orig_rval64)) { /* value changed */
   2482         if (orig_burst != max_burst) {
   2483             /* Construct MAXBUCKET, pre-fill it to the current bucket size */
   2484             COMPILER_64_ZERO(bucket_rval64);
   2485             if (meter_flags & _BCM_TD_METER_FLAG_NON_LINEAR) {
   2486                 fval = ((bucketsize & 0xff) + 256) << ((bucketsize >> 8) + 8);
   2487             } else {
   2488                 fval = bucketsize << 16;
   2489             }
   2490             soc_reg64_field32_set(unit, max_reg, &bucket_rval64, MAX_BUCKETf,
   2491                                   fval);
   2492 
   2493             BCM_IF_ERROR_RETURN(_bcm_td_cosq_refresh_freeze(unit));
   2494             /* Write MAXBUCKETCONFIG */
   2495             rv = soc_reg_set(unit, max_config_reg, local_port, index, rval64);
   2496             if (BCM_SUCCESS(rv)) {
   2497                 /* Write MAXBUCKET */
   2498                 rv =soc_reg_set(unit, max_reg, local_port, index,
   2499                                 bucket_rval64);
   2500             }
   2501             BCM_IF_ERROR_RETURN(_bcm_td_cosq_refresh_thaw(unit));
   2502             if (BCM_FAILURE(rv)) {
   2503                 return rv;
   2504             }
   2505         } else {
   2506             /* Write the constructed value to hardware */
   2507             BCM_IF_ERROR_RETURN(soc_reg_set(unit, max_config_reg, local_port,
   2508                                             index, rval64));
   2509         }
   2510     }
   2511 
   2512     /* Retrieve MINBUCKETCONFIG_64 and min bucket size */
   2513     BCM_IF_ERROR_RETURN
   2514         (soc_reg_get(unit, min_config_reg, local_port, index, &orig_rval64));
   2515     granularity =
   2516         soc_reg64_field32_get(unit, min_config_reg, orig_rval64, METER_GRANf);
   2517     refresh_rate =
   2518         soc_reg64_field32_get(unit, min_config_reg, orig_rval64, MIN_REFRESHf);
   2519     bucketsize =
   2520         soc_reg64_field32_get(unit, min_config_reg, orig_rval64, MIN_THDf);
   2521     BCM_IF_ERROR_RETURN
   2522         (_bcm_td_bucket_encoding_to_rate(unit, refresh_rate, bucketsize,
   2523                                          granularity, meter_flags,
   2524                                          &orig_bandwidth, &orig_burst));
   2525 
   2526     /* Construct MINBUCKETCONFIG_64 */
   2527     refresh_bitsize = soc_reg_field_length(unit, min_config_reg, MIN_REFRESHf);
   2528     bucket_bitsize = soc_reg_field_length(unit, min_config_reg, MIN_THDf);
   2529     BCM_IF_ERROR_RETURN
   2530         (_bcm_td_rate_to_bucket_encoding(unit, min_bandwidth, min_burst,
   2531                                          meter_flags, refresh_bitsize,
   2532                                          bucket_bitsize, &refresh_rate,
   2533                                          &bucketsize, &granularity));
   2534     COMPILER_64_ZERO(rval64);
   2535     soc_reg64_field32_set(unit, min_config_reg, &rval64, METER_GRANf,
   2536                           granularity);
   2537     soc_reg64_field32_set(unit, min_config_reg, &rval64, MIN_REFRESHf,
   2538                           refresh_rate);
   2539     soc_reg64_field32_set(unit, min_config_reg, &rval64, MIN_THDf, bucketsize);
   2540 
   2541     if (COMPILER_64_NE(rval64, orig_rval64)) { /* value changed */
   2542         if (orig_burst != min_burst) {
   2543             /* Construct MINBUCKET, pre-fill it to the current bucket size */
   2544             COMPILER_64_ZERO(bucket_rval64);
   2545             if (meter_flags & _BCM_TD_METER_FLAG_NON_LINEAR) {
   2546                 fval = ((bucketsize & 0xff) + 256) << ((bucketsize >> 8) + 8);
   2547             } else {
   2548                 fval = bucketsize << 16;
   2549             }
   2550             soc_reg64_field32_set(unit, min_reg, &bucket_rval64, MIN_BUCKETf,
   2551                                   fval);
   2552 
   2553             BCM_IF_ERROR_RETURN(_bcm_td_cosq_refresh_freeze(unit));
   2554             /* Write MINBUCKETCONFIG */
   2555             rv = soc_reg_set(unit, min_config_reg, local_port, index, rval64);
   2556             if (BCM_SUCCESS(rv)) {
   2557                 /* Write MINBUCKET */
   2558                 rv =soc_reg_set(unit, min_reg, local_port, index,
   2559                                 bucket_rval64);
   2560             }
   2561             BCM_IF_ERROR_RETURN(_bcm_td_cosq_refresh_thaw(unit));
   2562             if (BCM_FAILURE(rv)) {
   2563                 return rv;
   2564             }
   2565         } else {
   2566             /* Write the constructed value to hardware */
   2567             BCM_IF_ERROR_RETURN(soc_reg_set(unit, min_config_reg, local_port,
   2568                                             index, rval64));
   2569         }
   2570     }
   2571 
   2572     /* resolve index into SHAPING_CONTROL register */
   2573     BCM_IF_ERROR_RETURN
   2574         (_bcm_td_cosq_index_resolve(unit, port, cosq,
   2575                                     _BCM_TD_COSQ_INDEX_STYLE_BUCKET_MODE,
   2576                                     NULL, &index, NULL));
   2577 
   2578     /* Configure SHAPING_CONTROL */
   2579     if (index < 48) { /* in SHAPING_CONTROL */
   2580         shaping_reg = SHAPING_CONTROLr;
   2581     } else { /* in EXT1_SHAPING_CONTROL_PORTx */
   2582         index -= 48;
   2583         si = &SOC_INFO(unit);
   2584         mmu_cmic_port =
   2585             si->port_p2m_mapping[si->port_l2p_mapping[si->cmic_port]];
   2586         mmu_lb_port = si->port_p2m_mapping[si->port_l2p_mapping[si->lb_port]];
   2587         mmu_port = si->port_p2m_mapping[si->port_l2p_mapping[local_port]];
   2588         if (mmu_port < mmu_lb_port) { /* X pipe */
   2589             shaping_reg = ext_shaping_reg_x[mmu_port - mmu_cmic_port - 1];
   2590         } else { /* Y pipe */
   2591             shaping_reg = ext_shaping_reg_y[mmu_port - mmu_lb_port - 1];
   2592         }
   2593     }
   2594 
   2595     /* Retrieve SHAPING_CONTROL */
   2596     BCM_IF_ERROR_RETURN
   2597         (soc_reg_get(unit, shaping_reg, local_port, 0, &orig_rval64));
   2598 
   2599     /* Construct SHAPING_CONTROL */
   2600     if (index < 32) {
   2601         COMPILER_64_SET(mode_rval64, 0, 1 << index);
   2602     } else {
   2603         COMPILER_64_SET(mode_rval64, 1 << (index - 32), 0);
   2604     }
   2605     rval64 = orig_rval64;
   2606     if (flags & BCM_COSQ_BW_PACKET_MODE) {
   2607         COMPILER_64_OR(rval64, mode_rval64);
   2608     } else {
   2609         COMPILER_64_NOT(mode_rval64);
   2610         COMPILER_64_AND(rval64, mode_rval64);
   2611     }
   2612 
   2613     /* Write the constructed value to SHAPING_CONTROL hardware */
   2614     if (COMPILER_64_NE(rval64, orig_rval64)) {
   2615         BCM_IF_ERROR_RETURN
   2616             (soc_reg_set(unit, shaping_reg, local_port, 0, rval64));
   2617     }
   2618 
   2619     return BCM_E_NONE;
   2620 }
   2621 
   2622 /*
   2623  * Function:
   2624  *     _bcm_td_cosq_bucket_get
   2625  * Purpose:
   2626  *     Get COS queue bandwidth control bucket setting
   2627  * Parameters:
   2628  *     unit          - (IN) unit number
   2629  *     port          - (IN) port number or GPORT identifier
   2630  *     cosq          - (IN) COS queue number
   2631  *     min_bandwidth - (OUT) min bucket bandwidth (kbps or packet/second)
   2632  *     max_bandwidth - (OUT) max bucket bandwidth (kbps or packet/second)
   2633  *     min_burst     - (OUT) min bucket burst size (kbits or packets)
   2634  *     max_burst     - (OUT) max bucket burst size (kbits or packets)
   2635  *     flags         - (OUT) BCM_COSQ_BW_PACKET_MODE_XXX
   2636  * Returns:
   2637  *     BCM_E_XXX
   2638  * Notes:
   2639  *     If port is any form of local port, cosq is the hardware queue index.
   2640  */
   2641 STATIC int
   2642 _bcm_td_cosq_bucket_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   2643                         uint32 *min_bandwidth, uint32 *max_bandwidth,
   2644                         uint32 *min_burst, uint32 *max_burst,
   2645                         uint32 *flags)
   2646 {
   2647     soc_info_t *si;
   2648     _bcm_td_cosq_node_t *node;
   2649     bcm_port_t local_port, mmu_port, mmu_cmic_port, mmu_lb_port;
   2650     int index, rv;
   2651     soc_reg_t max_config_reg, min_config_reg, shaping_reg;
   2652     uint32 rval;
   2653     uint64 rval64;
   2654     uint32 refresh_rate, bucketsize, granularity, meter_flags;
   2655     static const soc_reg_t ext_shaping_reg_x[] = {
   2656         EXT1_SHAPING_CONTROL_PORT1r, EXT1_SHAPING_CONTROL_PORT2r,
   2657         EXT1_SHAPING_CONTROL_PORT3r, EXT1_SHAPING_CONTROL_PORT4r
   2658     };
   2659     static const soc_reg_t ext_shaping_reg_y[] = {
   2660         EXT1_SHAPING_CONTROL_PORT34r, EXT1_SHAPING_CONTROL_PORT35r,
   2661         EXT1_SHAPING_CONTROL_PORT36r, EXT1_SHAPING_CONTROL_PORT37r
   2662     };
   2663 
   2664     if (cosq < 0) {
   2665         if (cosq == -1) {
   2666             /* caller needs to resolve the wild card value (-1) */
   2667             return BCM_E_INTERNAL;
   2668         } else { /* reject all other negative value */
   2669             return BCM_E_PARAM;
   2670         }
   2671     }
   2672 
   2673     if (min_bandwidth == NULL || max_bandwidth == NULL || 
   2674         min_burst == NULL || max_burst == NULL || flags == NULL) {
   2675         return BCM_E_PARAM;
   2676     }
   2677 
   2678     BCM_IF_ERROR_RETURN
   2679         (_bcm_td_cosq_index_resolve(unit, port, cosq,
   2680                                     _BCM_TD_COSQ_INDEX_STYLE_BUCKET_MODE,
   2681                                     &local_port, &index, NULL));
   2682 
   2683     if (index < 48) { /* in SHAPING_CONTROL */
   2684         shaping_reg = SHAPING_CONTROLr;
   2685     } else { /* in EXT1_SHAPING_CONTROL_PORTx */
   2686         index -= 48;
   2687         si = &SOC_INFO(unit);
   2688         mmu_cmic_port =
   2689             si->port_p2m_mapping[si->port_l2p_mapping[si->cmic_port]];
   2690         mmu_lb_port = si->port_p2m_mapping[si->port_l2p_mapping[si->lb_port]];
   2691         mmu_port = si->port_p2m_mapping[si->port_l2p_mapping[local_port]];
   2692         if (mmu_port < mmu_lb_port) { /* X pipe */
   2693             shaping_reg = ext_shaping_reg_x[mmu_port - mmu_cmic_port - 1];
   2694         } else { /* Y pipe */
   2695             shaping_reg = ext_shaping_reg_y[mmu_port - mmu_lb_port - 1];
   2696         }
   2697     }
   2698     BCM_IF_ERROR_RETURN
   2699         (soc_reg_get(unit, shaping_reg, local_port, 0, &rval64));
   2700     if (index < 32) {
   2701         *flags = COMPILER_64_LO(rval64) & (1 << index) ?
   2702             BCM_COSQ_BW_PACKET_MODE : 0;
   2703     } else {
   2704         *flags = COMPILER_64_HI(rval64) & (1 << (index - 32)) ?
   2705             BCM_COSQ_BW_PACKET_MODE : 0;
   2706     }
   2707 
   2708     BCM_IF_ERROR_RETURN
   2709         (_bcm_td_cosq_index_resolve(unit, port, cosq,
   2710                                     _BCM_TD_COSQ_INDEX_STYLE_BUCKET,
   2711                                     NULL, &index, NULL));
   2712 
   2713     if (BCM_GPORT_IS_SCHEDULER(port)) {
   2714         BCM_IF_ERROR_RETURN
   2715             (_bcm_td_cosq_node_get(unit, port, NULL, NULL, NULL, &node));
   2716         if (node->level == 3) { /* S3 scheduler */
   2717             max_config_reg = S3_MAXBUCKETCONFIG_64r;
   2718             min_config_reg = S3_MINBUCKETCONFIG_64r;
   2719         } else if (node->level == 2) { /* S2 scheduler */
   2720             max_config_reg = S2_MAXBUCKETCONFIG_64r;
   2721             min_config_reg = S2_MINBUCKETCONFIG_64r;
   2722         } else {
   2723             return BCM_E_PARAM;
   2724         }
   2725     } else if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
   2726                BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
   2727         max_config_reg = MAXBUCKETCONFIG_64r;
   2728         min_config_reg = MINBUCKETCONFIG_64r;
   2729     } else { /* local port */
   2730         if (cosq < _BCM_TD_NUM_S3_SCHEDULER &&
   2731             !IS_CPU_PORT(unit, local_port)) {
   2732             /* use S3.0 - S3.3 for unicast and multicast queue 0 - 3 */
   2733             max_config_reg = S3_MAXBUCKETCONFIG_64r;
   2734             min_config_reg = S3_MINBUCKETCONFIG_64r;
   2735         } else { /* unicast queue 4 - 7 */
   2736             max_config_reg = MAXBUCKETCONFIG_64r;
   2737             min_config_reg = MINBUCKETCONFIG_64r;
   2738         }
   2739     }
   2740 
   2741     meter_flags = *flags & BCM_COSQ_BW_PACKET_MODE ?
   2742         _BCM_TD_METER_FLAG_PACKET_MODE : 0;
   2743     BCM_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, &rval));
   2744     if (soc_reg_field_get(unit, MISCCONFIGr, rval, ITU_MODE_SELf)) {
   2745         meter_flags |= _BCM_TD_METER_FLAG_NON_LINEAR;
   2746     }
   2747 
   2748     BCM_IF_ERROR_RETURN(_bcm_td_cosq_refresh_freeze(unit));
   2749     rv = soc_reg_get(unit, max_config_reg, local_port, index, &rval64);
   2750     BCM_IF_ERROR_RETURN(_bcm_td_cosq_refresh_thaw(unit));
   2751     if (BCM_FAILURE(rv)) {
   2752         return rv;
   2753     }
   2754     granularity =
   2755         soc_reg64_field32_get(unit, max_config_reg, rval64, METER_GRANf);
   2756     refresh_rate =
   2757         soc_reg64_field32_get(unit, max_config_reg, rval64, MAX_REFRESHf);
   2758     bucketsize = soc_reg64_field32_get(unit, max_config_reg, rval64, MAX_THDf);
   2759     BCM_IF_ERROR_RETURN
   2760         (_bcm_td_bucket_encoding_to_rate(unit, refresh_rate, bucketsize,
   2761                                          granularity, meter_flags,
   2762                                          max_bandwidth, max_burst));
   2763 
   2764     BCM_IF_ERROR_RETURN(_bcm_td_cosq_refresh_freeze(unit));
   2765     rv = soc_reg_get(unit, min_config_reg, local_port, index, &rval64);
   2766     BCM_IF_ERROR_RETURN(_bcm_td_cosq_refresh_thaw(unit));
   2767     if (BCM_FAILURE(rv)) {
   2768         return rv;
   2769     }
   2770     granularity =
   2771         soc_reg64_field32_get(unit, min_config_reg, rval64, METER_GRANf);
   2772     refresh_rate =
   2773         soc_reg64_field32_get(unit, min_config_reg, rval64, MIN_REFRESHf);
   2774     bucketsize = soc_reg64_field32_get(unit, min_config_reg, rval64, MIN_THDf);
   2775     BCM_IF_ERROR_RETURN
   2776         (_bcm_td_bucket_encoding_to_rate(unit, refresh_rate, bucketsize,
   2777                                          granularity, meter_flags,
   2778                                          min_bandwidth, min_burst));
   2779 
   2780     return BCM_E_NONE;
   2781 }
   2782 
   2783 /*
   2784  * Function:
   2785  *     _bcm_td_cosq_wred_set
   2786  * Purpose:
   2787  *     Configure unicast queue WRED setting
   2788  * Parameters:
   2789  *     unit                - (IN) unit number
   2790  *     port                - (IN) port number or GPORT identifier
   2791  *     cosq                - (IN) COS queue number
   2792  *     flags               - (IN) BCM_COSQ_DISCARD_XXX
   2793  *     min_thresh          - (IN)
   2794  *     max_thresh          - (IN)
   2795  *     drop_probablity     - (IN)
   2796  *     gain                - (IN)
   2797  *     ignore_enable_flags - (IN)
   2798  * Returns:
   2799  *     BCM_E_XXX
   2800  * Notes:
   2801  *     If port is any form of local port, cosq is the hardware queue index.
   2802  */
   2803 STATIC int
   2804 _bcm_td_cosq_wred_set(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   2805                       uint32 flags, uint32 min_thresh, uint32 max_thresh,
   2806                       int drop_probability, int gain, int ignore_enable_flags)
   2807 {
   2808     soc_info_t *si;
   2809     soc_reg_t reg;
   2810     soc_field_t field;
   2811     uint32 rval;
   2812     bcm_port_t local_port;
   2813     int index;
   2814     uint32 profile_index, old_profile_index;
   2815     mmu_wred_drop_curve_profile_0_entry_t entry_tcp_green;
   2816     mmu_wred_drop_curve_profile_1_entry_t entry_tcp_yellow;
   2817     mmu_wred_drop_curve_profile_2_entry_t entry_tcp_red;
   2818     mmu_wred_drop_curve_profile_3_entry_t entry_nontcp_green;
   2819     mmu_wred_drop_curve_profile_4_entry_t entry_nontcp_yellow;
   2820     mmu_wred_drop_curve_profile_5_entry_t entry_nontcp_red;
   2821     void *entries[6];
   2822     soc_mem_t mems[6];
   2823     int rate, i, exists = 0;
   2824     static soc_mem_t wred_mems[6] = {
   2825         MMU_WRED_DROP_CURVE_PROFILE_0m,
   2826         MMU_WRED_DROP_CURVE_PROFILE_1m,
   2827         MMU_WRED_DROP_CURVE_PROFILE_2m,
   2828         MMU_WRED_DROP_CURVE_PROFILE_3m,
   2829         MMU_WRED_DROP_CURVE_PROFILE_4m,
   2830         MMU_WRED_DROP_CURVE_PROFILE_5m
   2831     };
   2832 
   2833     if ((port == -1) && (!(flags & BCM_COSQ_DISCARD_DEVICE))) {
   2834         return BCM_E_PORT;
   2835     }
   2836     entries[0] = &entry_tcp_green;
   2837     entries[1] = &entry_tcp_yellow;
   2838     entries[2] = &entry_tcp_red;
   2839     entries[3] = &entry_nontcp_green;
   2840     entries[4] = &entry_nontcp_yellow;
   2841     entries[5] = &entry_nontcp_red;
   2842     si = &SOC_INFO(unit);
   2843     /*
   2844      * if port == -1 and BCM_COSQ_DISCARD_DEVICE
   2845      *  set the all the service pools
   2846      */
   2847     if ((port == -1) && (flags & BCM_COSQ_DISCARD_DEVICE)) {
   2848         reg = GLOBAL_SP_WRED_CONFIGr;
   2849         field = WRED_ENABLEf;
   2850         local_port = 0;
   2851         index = 0;
   2852     } else {
   2853         /*
   2854          * For extended queue port:
   2855          * WRED_CONFIG:
   2856          *     index 0: summary of regular uc cosq 0 and extended uc queue 0-15
   2857          *     index 1: summary of regular uc cosq 1 and extended uc queue 16-31
   2858          *     index 2: summary of regular uc cosq 2 and extended uc queue 32-47
   2859          *     index 3: summary of regular uc cosq 3 and extended uc queue 48-63
   2860          *     these summary does not need to equal to the sum of corresponding
   2861          *     entries in DMVOQ_WRED_CONFIG
   2862          * DMVOQ_WRED_CONFIG:
   2863          *     index 0 - 63 for extended unicast queue 0 - queue 63
   2864          *     index 64 - 71 for unicast queue 0 - queue 7
   2865          */
   2866 
   2867         BCM_IF_ERROR_RETURN
   2868             (_bcm_td_cosq_index_resolve(unit, port, cosq,
   2869                                         _BCM_TD_COSQ_INDEX_STYLE_WRED,
   2870                                         &local_port, &index, NULL));
   2871         if (flags & (BCM_COSQ_DISCARD_DEVICE | BCM_COSQ_DISCARD_PORT)) {
   2872             /* Get the pool number for the queue */
   2873             if (si->port_num_ext_cosq[local_port] == 0) { /* regular port */
   2874                 reg = OP_UC_PORT_CONFIG1_CELLr;
   2875                 field = _bcm_td_uc_spid_fields[index];
   2876             } else { /* extended queue port */
   2877                 reg = _bcm_td_ext_uc_spid_regs[index / 16];
   2878                 field = _bcm_td_ext_uc_spid_fields[index];
   2879             }
   2880             BCM_IF_ERROR_RETURN(soc_reg32_get(unit, reg, local_port, 0, &rval));
   2881             index = soc_reg_field_get(unit, reg, rval, field);
   2882 
   2883             if (flags & BCM_COSQ_DISCARD_DEVICE) {
   2884                 reg = GLOBAL_SP_WRED_CONFIGr;
   2885                 field = WRED_ENABLEf;
   2886                 local_port = 0;
   2887             } else {
   2888                 reg = PORT_SP_WRED_CONFIGr;
   2889                 field = WRED_ENABLEf;
   2890             }
   2891         } else {
   2892             if (si->port_num_ext_cosq[local_port] == 0) { /* regular port */
   2893                 reg = WRED_CONFIGr;
   2894             } else { /* extended queue port */
   2895                 reg = DMVOQ_WRED_CONFIGr;
   2896             }
   2897             field = WRED_ENf;
   2898         }
   2899     }
   2900 
   2901     BCM_IF_ERROR_RETURN(soc_reg32_get(unit, reg, local_port, index, &rval));
   2902 
   2903     old_profile_index = 0xffffffff;
   2904     if (flags & (BCM_COSQ_DISCARD_NONTCP | BCM_COSQ_DISCARD_COLOR_ALL |
   2905                  BCM_COSQ_DISCARD_TCP)) {
   2906         old_profile_index = soc_reg_field_get(unit, reg, rval, PROFILE_INDEXf);
   2907         BCM_IF_ERROR_RETURN
   2908             (soc_profile_mem_get(unit, _bcm_td_wred_profile[unit],
   2909                                  old_profile_index, 1, entries));
   2910         for (i = 0; i < 6; i++) {
   2911             mems[i] = INVALIDm;
   2912         }
   2913         if (!(flags & (BCM_COSQ_DISCARD_COLOR_GREEN |
   2914                        BCM_COSQ_DISCARD_COLOR_YELLOW |
   2915                        BCM_COSQ_DISCARD_COLOR_RED))) {
   2916             flags |= BCM_COSQ_DISCARD_COLOR_ALL;
   2917         }
   2918         if (!(flags & BCM_COSQ_DISCARD_NONTCP) || (flags & BCM_COSQ_DISCARD_TCP)) {
   2919             if (flags & BCM_COSQ_DISCARD_COLOR_GREEN) {
   2920                 mems[0] = MMU_WRED_DROP_CURVE_PROFILE_0m;
   2921             }
   2922             if (flags & BCM_COSQ_DISCARD_COLOR_YELLOW) {
   2923                 mems[1] = MMU_WRED_DROP_CURVE_PROFILE_1m;
   2924             }
   2925             if (flags & BCM_COSQ_DISCARD_COLOR_RED) {
   2926                 mems[2] = MMU_WRED_DROP_CURVE_PROFILE_2m;
   2927             }
   2928         }
   2929         if (flags & BCM_COSQ_DISCARD_NONTCP) {                                                                  
   2930             if (flags & BCM_COSQ_DISCARD_COLOR_GREEN) {
   2931                 mems[3] = MMU_WRED_DROP_CURVE_PROFILE_3m;
   2932             }
   2933             if (flags & BCM_COSQ_DISCARD_COLOR_YELLOW) {
   2934                 mems[4] = MMU_WRED_DROP_CURVE_PROFILE_4m;
   2935             }
   2936             if (flags & BCM_COSQ_DISCARD_COLOR_RED) {
   2937                 mems[5] = MMU_WRED_DROP_CURVE_PROFILE_5m;
   2938             }
   2939         }
   2940         rate = _bcm_td_percent_to_drop_prob(drop_probability);
   2941         for (i = 0; i < 6; i++) {
   2942             exists = 0;
   2943             if ((soc_mem_field32_get(unit, wred_mems[i], entries[i],
   2944                                     MIN_THDf) != 0xffff) &&
   2945                                     (mems[i] == INVALIDm)) {
   2946                 mems[i] = wred_mems[i];
   2947                 exists = 1;
   2948             } else {
   2949                 soc_mem_field32_set(unit, wred_mems[i], entries[i], MIN_THDf,
   2950                                     (mems[i] == INVALIDm) ? 0xffff :
   2951                                     min_thresh);
   2952             }
   2953 
   2954             if ((soc_mem_field32_get(unit, wred_mems[i], entries[i],
   2955                                     MAX_THDf) != 0xffff) &&
   2956                                     ((mems[i] == INVALIDm) || exists)) {
   2957                 mems[i] = wred_mems[i];
   2958                 exists = 1;
   2959             } else {
   2960                 soc_mem_field32_set(unit, wred_mems[i], entries[i], MAX_THDf,
   2961                                     (mems[i] == INVALIDm) ? 0xffff :
   2962                                     max_thresh);
   2963             }
   2964 
   2965             if (!exists) {
   2966                 soc_mem_field32_set(unit, wred_mems[i], entries[i],
   2967                                     MAX_DROP_RATEf,
   2968                                     (mems[i] == INVALIDm) ? 0 : rate);
   2969             }
   2970         }
   2971         BCM_IF_ERROR_RETURN
   2972             (soc_profile_mem_add(unit, _bcm_td_wred_profile[unit], entries, 1,
   2973                                  &profile_index));
   2974 
   2975         soc_reg_field_set(unit, reg, &rval, PROFILE_INDEXf, profile_index);
   2976         soc_reg_field_set(unit, reg, &rval, WEIGHTf, gain);
   2977     }
   2978 
   2979     /* Some APIs only modify profiles */
   2980     if (!ignore_enable_flags) {
   2981         soc_reg_field_set(unit, reg, &rval, CAP_AVERAGEf,
   2982                           flags & BCM_COSQ_DISCARD_CAP_AVERAGE ? 1 : 0);
   2983         soc_reg_field_set(unit, reg, &rval, field,
   2984                           flags & BCM_COSQ_DISCARD_ENABLE ? 1 : 0);
   2985         if (reg == WRED_CONFIGr || reg == DMVOQ_WRED_CONFIGr) {
   2986             soc_reg_field_set(unit, reg, &rval, ECN_MARKING_ENf,
   2987                               flags & BCM_COSQ_DISCARD_MARK_CONGESTION ?
   2988                               1 : 0);
   2989         }
   2990     }
   2991     BCM_IF_ERROR_RETURN(soc_reg32_set(unit, reg, local_port, index, rval));
   2992     if ((port == -1) && (flags & BCM_COSQ_DISCARD_DEVICE)) {
   2993         for (i = 1; i< 4; i++) {
   2994             BCM_IF_ERROR_RETURN
   2995                 (soc_profile_mem_add(unit, _bcm_td_wred_profile[unit], entries, 1,
   2996                                      &profile_index));
   2997             BCM_IF_ERROR_RETURN(soc_reg32_set(unit, reg, local_port, i, rval));
   2998         }
   2999     }
   3000 
   3001     if (old_profile_index != 0xffffffff) {
   3002         BCM_IF_ERROR_RETURN
   3003             (soc_profile_mem_delete(unit, _bcm_td_wred_profile[unit],
   3004                                     old_profile_index));
   3005         if ((port == -1) &&(flags & BCM_COSQ_DISCARD_DEVICE)) {
   3006             for (i = 1; i< 4; i++) {
   3007                 BCM_IF_ERROR_RETURN
   3008                     (soc_profile_mem_delete(unit, _bcm_td_wred_profile[unit],
   3009                                             old_profile_index));
   3010             }
   3011         }
   3012     }
   3013 
   3014 
   3015        if (!((port == -1) && (flags & BCM_COSQ_DISCARD_DEVICE))) {
   3016            BCM_IF_ERROR_RETURN
   3017                (_bcm_td_cosq_index_resolve(unit, port, cosq,
   3018                                            _BCM_TD_COSQ_INDEX_STYLE_WRED_DROP_THRESH,
   3019                                            NULL, &index, NULL));
   3020            BCM_IF_ERROR_RETURN
   3021                (soc_mem_write(unit, MMU_WRED_DROP_THD_UC_ENQ0m, MEM_BLOCK_ALL, index,
   3022                               soc_mem_entry_null(unit, MMU_WRED_DROP_THD_UC_ENQ0m)));
   3023            BCM_IF_ERROR_RETURN
   3024                (soc_mem_write(unit, MMU_WRED_DROP_THD_UC_ENQ1m, MEM_BLOCK_ALL, index,
   3025                               soc_mem_entry_null(unit, MMU_WRED_DROP_THD_UC_ENQ1m)));
   3026            BCM_IF_ERROR_RETURN
   3027                (soc_mem_write(unit, MMU_WRED_DROP_THD_UC_DEQ0m, MEM_BLOCK_ALL, index,
   3028                               soc_mem_entry_null(unit, MMU_WRED_DROP_THD_UC_DEQ0m)));
   3029            BCM_IF_ERROR_RETURN
   3030                (soc_mem_write(unit, MMU_WRED_DROP_THD_UC_DEQ1m, MEM_BLOCK_ALL, index,
   3031                               soc_mem_entry_null(unit, MMU_WRED_DROP_THD_UC_DEQ1m)));
   3032        }
   3033     return BCM_E_NONE;
   3034 }
   3035 
   3036 /*
   3037  * Function:
   3038  *     _bcm_td_cosq_wred_get
   3039  * Purpose:
   3040  *     Get unicast queue WRED setting
   3041  * Parameters:
   3042  *     unit                - (IN) unit number
   3043  *     port                - (IN) port number or GPORT identifier
   3044  *     cosq                - (IN) COS queue number
   3045  *     flags               - (IN/OUT) BCM_COSQ_DISCARD_XXX
   3046  *     min_thresh          - (OUT)
   3047  *     max_thresh          - (OUT)
   3048  *     drop_probablity     - (OUT)
   3049  *     gain                - (OUT)
   3050  * Returns:
   3051  *     BCM_E_XXX
   3052  * Notes:
   3053  *     If port is any form of local port, cosq is the hardware queue index.
   3054  */
   3055 STATIC int
   3056 _bcm_td_cosq_wred_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   3057                       uint32 *flags, uint32 *min_thresh, uint32 *max_thresh,
   3058                       int *drop_probability, int *gain)
   3059 {
   3060     soc_info_t *si;
   3061     soc_reg_t reg;
   3062     soc_field_t field;
   3063     uint32 rval;
   3064     bcm_port_t local_port;
   3065     int index, profile_index;
   3066     mmu_wred_drop_curve_profile_0_entry_t entry_tcp_green;
   3067     mmu_wred_drop_curve_profile_1_entry_t entry_tcp_yellow;
   3068     mmu_wred_drop_curve_profile_2_entry_t entry_tcp_red;
   3069     mmu_wred_drop_curve_profile_3_entry_t entry_nontcp_green;
   3070     mmu_wred_drop_curve_profile_4_entry_t entry_nontcp_yellow;
   3071     mmu_wred_drop_curve_profile_5_entry_t entry_nontcp_red;
   3072     void *entries[6];
   3073     void *entry_p;
   3074     soc_mem_t mem;
   3075     int rate;
   3076     if ((port == -1) && (!(*flags & BCM_COSQ_DISCARD_DEVICE))) {
   3077         return BCM_E_PORT;
   3078     }
   3079 
   3080     si = &SOC_INFO(unit);
   3081     if ((port == -1 ) && (*flags & BCM_COSQ_DISCARD_DEVICE)) {
   3082         reg = GLOBAL_SP_WRED_CONFIGr;
   3083         field = WRED_ENABLEf;
   3084         local_port = 0;
   3085         index = 0;
   3086     } else {
   3087         BCM_IF_ERROR_RETURN
   3088             (_bcm_td_cosq_index_resolve(unit, port, cosq,
   3089                                         _BCM_TD_COSQ_INDEX_STYLE_WRED,
   3090                                         &local_port, &index, NULL));
   3091         if (*flags & (BCM_COSQ_DISCARD_DEVICE | BCM_COSQ_DISCARD_PORT)) {
   3092             /* Get the pool number for the queue */
   3093             if (si->port_num_ext_cosq[local_port] == 0) { /* regular port */
   3094                 reg = OP_UC_PORT_CONFIG1_CELLr;
   3095                 field = _bcm_td_uc_spid_fields[index];
   3096             } else { /* extended queue port */
   3097                 reg = _bcm_td_ext_uc_spid_regs[index / 16];
   3098                 field = _bcm_td_ext_uc_spid_fields[index];
   3099             }
   3100             BCM_IF_ERROR_RETURN(soc_reg32_get(unit, reg, local_port, 0, &rval));
   3101             index = soc_reg_field_get(unit, reg, rval, field);
   3102             if (*flags & BCM_COSQ_DISCARD_DEVICE) {
   3103                 reg = GLOBAL_SP_WRED_CONFIGr;
   3104                 field = WRED_ENABLEf;
   3105                 local_port = 0;
   3106             } else {
   3107                 reg = PORT_SP_WRED_CONFIGr;
   3108                 field = WRED_ENABLEf;
   3109             }
   3110         } else {
   3111             if (si->port_num_ext_cosq[local_port] == 0) { /* regular port */
   3112                 reg = WRED_CONFIGr;
   3113             } else { /* extended queue port */
   3114                 reg = DMVOQ_WRED_CONFIGr;
   3115             }
   3116             field = WRED_ENf;
   3117         }
   3118     }
   3119 
   3120     BCM_IF_ERROR_RETURN(soc_reg32_get(unit, reg, local_port, index, &rval));
   3121 
   3122     if (!(*flags & BCM_COSQ_DISCARD_NONTCP)) {
   3123         if (*flags & BCM_COSQ_DISCARD_COLOR_GREEN) {
   3124             mem = MMU_WRED_DROP_CURVE_PROFILE_0m;
   3125             entry_p = &entry_tcp_green;
   3126         } else if (*flags & BCM_COSQ_DISCARD_COLOR_YELLOW) {
   3127             mem = MMU_WRED_DROP_CURVE_PROFILE_1m;
   3128             entry_p = &entry_tcp_yellow;
   3129         } else if (*flags & BCM_COSQ_DISCARD_COLOR_RED) {
   3130             mem = MMU_WRED_DROP_CURVE_PROFILE_2m;
   3131             entry_p = &entry_tcp_red;
   3132         } else {
   3133            mem = MMU_WRED_DROP_CURVE_PROFILE_0m;
   3134            entry_p = &entry_tcp_green;
   3135         }
   3136     } else {
   3137         if (*flags & BCM_COSQ_DISCARD_COLOR_GREEN) {
   3138             mem = MMU_WRED_DROP_CURVE_PROFILE_3m;
   3139             entry_p = &entry_nontcp_green;
   3140         } else if (*flags & BCM_COSQ_DISCARD_COLOR_YELLOW) {
   3141             mem = MMU_WRED_DROP_CURVE_PROFILE_4m;
   3142             entry_p = &entry_nontcp_yellow;
   3143         } else if (*flags & BCM_COSQ_DISCARD_COLOR_RED) {
   3144             mem = MMU_WRED_DROP_CURVE_PROFILE_5m;
   3145             entry_p = &entry_nontcp_red;
   3146         } else {
   3147            mem = MMU_WRED_DROP_CURVE_PROFILE_3m;
   3148            entry_p = &entry_nontcp_green;
   3149         }
   3150     }
   3151     profile_index = soc_reg_field_get(unit, reg, rval, PROFILE_INDEXf);
   3152     entries[0] = &entry_tcp_green;
   3153     entries[1] = &entry_tcp_yellow;
   3154     entries[2] = &entry_tcp_red;
   3155     entries[3] = &entry_nontcp_green;
   3156     entries[4] = &entry_nontcp_yellow;
   3157     entries[5] = &entry_nontcp_red;
   3158     BCM_IF_ERROR_RETURN
   3159         (soc_profile_mem_get(unit, _bcm_td_wred_profile[unit],
   3160                              profile_index, 1, entries));
   3161     if (min_thresh != NULL) {
   3162         *min_thresh = soc_mem_field32_get(unit, mem, entry_p, MIN_THDf);
   3163     }
   3164     if (max_thresh != NULL) {
   3165         *max_thresh = soc_mem_field32_get(unit, mem, entry_p, MAX_THDf);
   3166     }
   3167     if (drop_probability != NULL) {
   3168         rate = soc_mem_field32_get(unit, mem, entry_p, MAX_DROP_RATEf);
   3169         *drop_probability = _bcm_td_drop_prob_to_percent(rate);
   3170     }
   3171 
   3172     if (gain != NULL) {
   3173         *gain = soc_reg_field_get(unit, reg, rval, WEIGHTf);
   3174     }
   3175 
   3176     *flags &= ~(BCM_COSQ_DISCARD_CAP_AVERAGE | BCM_COSQ_DISCARD_ENABLE);
   3177     if (soc_reg_field_get(unit, reg, rval, CAP_AVERAGEf)) {
   3178         *flags |= BCM_COSQ_DISCARD_CAP_AVERAGE;
   3179     }
   3180     if (soc_reg_field_get(unit, reg, rval, field)) {
   3181         *flags |= BCM_COSQ_DISCARD_ENABLE;
   3182     }
   3183     if (reg == WRED_CONFIGr || reg == DMVOQ_WRED_CONFIGr) {
   3184         if (soc_reg_field_get(unit, reg, rval, ECN_MARKING_ENf)) {
   3185             *flags |= BCM_COSQ_DISCARD_MARK_CONGESTION;
   3186         }
   3187     }
   3188 
   3189     return BCM_E_NONE;
   3190 }
   3191 
   3192 /*
   3193  * Function:
   3194  *     _bcm_td_cosq_sched_set
   3195  * Purpose:
   3196  *     Set scheduling mode
   3197  * Parameters:
   3198  *     unit                - (IN) unit number
   3199  *     port                - (IN) port number or GPORT identifier
   3200  *     cosq                - (IN) COS queue number
   3201  *     mode                - (IN) scheduling mode (BCM_COSQ_XXX)
   3202  *     num_weights         - (IN) number of entries in weights array
   3203  *     weights             - (IN) weights array
   3204  * Returns:
   3205  *     BCM_E_XXX
   3206  */
   3207 STATIC int
   3208 _bcm_td_cosq_sched_set(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   3209                        int mode, int num_weights, int *weights)
   3210 {
   3211     soc_info_t *si;
   3212     _bcm_td_cosq_port_info_t *port_info;
   3213     _bcm_td_cosq_node_t *node;
   3214     bcm_port_t local_port;
   3215     int index, minsp_index;
   3216     soc_reg_t config_reg, weight_reg, minsp_reg;
   3217     uint32 rval, fval, rval_hi, rval_lo;
   3218     uint64 rval64;
   3219     int mode_sel_shift, max_weight, minsp_width, mode_sel, i;
   3220 
   3221     if (cosq < 0) {
   3222         if (cosq == -1) {
   3223             /* caller needs to resolve the wild card value (-1) */
   3224             return BCM_E_INTERNAL;
   3225         } else { /* reject all other negative value */
   3226             return BCM_E_PARAM;
   3227         }
   3228     }
   3229 
   3230     si = &SOC_INFO(unit);
   3231 
   3232     mode_sel_shift = 0;
   3233     minsp_index = 0;
   3234     minsp_width = -1;
   3235 
   3236     if (BCM_GPORT_IS_SCHEDULER(port)) { /* ETS style scheduler */
   3237         BCM_IF_ERROR_RETURN
   3238             (_bcm_td_cosq_node_get(unit, port, NULL, &local_port, NULL,
   3239                                    &node));
   3240 
   3241         if (cosq + num_weights > node->numq) {
   3242             return BCM_E_PARAM;
   3243         }
   3244 
   3245         if (node->hw_cosq_attached_to < 0) { /* Not resolved yet */
   3246             return BCM_E_NOT_FOUND;
   3247         }
   3248 
   3249         switch (node->level) {
   3250         case 1: /* S1 scheduler */
   3251             config_reg = ESCONFIGr;
   3252             weight_reg = COSWEIGHTSr;
   3253             minsp_reg = MINSPCONFIGr;
   3254             break;
   3255         case 2:
   3256             if (node->hw_cosq_attached_to == 0) { /* MC group scheduler */
   3257                 config_reg = S3_CONFIG_MCr;
   3258                 weight_reg = S3_COSWEIGHTSr;
   3259                 minsp_reg = S3_MINSPCONFIG_MCr;
   3260             } else { /* S2 scheduler */
   3261                 config_reg = S2_CONFIGr;
   3262                 weight_reg = S2_COSWEIGHTSr;
   3263                 minsp_reg = S2_MINSPCONFIGr;
   3264                 mode_sel_shift = (node->hw_cosq_attached_to - 1) * 2;
   3265             }
   3266             break;
   3267         case 3: /* S3 scheduler */
   3268             config_reg = S3_CONFIGr;
   3269             weight_reg = S3_COSWEIGHTSr;
   3270             minsp_reg = S3_MINSPCONFIGr;
   3271             mode_sel_shift = node->hw_cosq_attached_to * 2;
   3272             minsp_index = node->hw_cosq_attached_to;
   3273             minsp_width = si->port_num_ext_cosq[local_port] ? 18 : 2;
   3274             break;
   3275         default:
   3276             return BCM_E_INTERNAL;
   3277         }
   3278     } else { /* non-ETS style scheduler */
   3279         BCM_IF_ERROR_RETURN
   3280             (_bcm_td_cosq_localport_resolve(unit, port, &local_port));
   3281         if (IS_CPU_PORT(unit, local_port)) {
   3282             if (cosq + num_weights > si->num_cpu_cosq) {
   3283                 return BCM_E_PARAM;
   3284             }
   3285             config_reg = ESCONFIGr;
   3286             weight_reg = COSWEIGHTSr;
   3287             minsp_reg = MINSPCONFIG_CPUr;
   3288         } else {
   3289             port_info = &_bcm_td_cosq_port_info[unit][local_port];
   3290             for (i = 0; i < _BCM_TD_NUM_SCHEDULER; i++) {
   3291                 if (port_info->sched[i].numq > 0 &&
   3292                     port_info->sched[i].cosq_attached_to != -1) {
   3293                     /* ETS style scheduling has been setup */
   3294                     return BCM_E_PORT;
   3295                 }
   3296             }
   3297             if (cosq + num_weights > _BCM_TD_NUM_NON_SC_QM_UCAST_QUEUE) {
   3298                 return BCM_E_PARAM;
   3299             }
   3300             config_reg = S2_CONFIGr;
   3301             weight_reg = S2_COSWEIGHTSr;
   3302             minsp_reg = S2_MINSPCONFIGr;
   3303             mode_sel_shift = 0; /* S2.0 */
   3304         }
   3305     }
   3306 
   3307     switch (mode) {
   3308     case BCM_COSQ_STRICT:
   3309         mode_sel = 0;
   3310         break;
   3311     case BCM_COSQ_ROUND_ROBIN:
   3312         mode_sel = 1;
   3313         break;
   3314     case BCM_COSQ_WEIGHTED_ROUND_ROBIN:
   3315         mode_sel = 2;
   3316         break;
   3317     case BCM_COSQ_DEFICIT_ROUND_ROBIN:
   3318         mode_sel = 3;
   3319         break;
   3320     default:
   3321         return BCM_E_PARAM;
   3322     }
   3323 
   3324     if (mode == BCM_COSQ_WEIGHTED_ROUND_ROBIN ||
   3325         mode == BCM_COSQ_DEFICIT_ROUND_ROBIN) {
   3326         max_weight =
   3327             (1 << soc_reg_field_length(unit, weight_reg, COSWEIGHTSf)) - 1;
   3328         for (i = 0; i < num_weights; i++) {
   3329             if (weights[i] < 0 || weights[i] > max_weight) {
   3330                 return BCM_E_PARAM;
   3331             }
   3332         }
   3333 
   3334         BCM_IF_ERROR_RETURN
   3335             (soc_reg_get(unit, minsp_reg, local_port, minsp_index, &rval64));
   3336         rval_hi = COMPILER_64_HI(rval64);
   3337         rval_lo = COMPILER_64_LO(rval64);
   3338         for (i = 0; i < num_weights; i++) {
   3339             BCM_IF_ERROR_RETURN
   3340                 (_bcm_td_cosq_index_resolve(unit, port, cosq + i,
   3341                                             _BCM_TD_COSQ_INDEX_STYLE_SCHEDULER,
   3342                                             NULL, &index, NULL));
   3343             BCM_IF_ERROR_RETURN
   3344                 (soc_reg32_get(unit, weight_reg, local_port, index, &rval));
   3345             soc_reg_field_set(unit, weight_reg, &rval, COSWEIGHTSf,
   3346                               weights[i]);
   3347             BCM_IF_ERROR_RETURN
   3348                 (soc_reg32_set(unit, weight_reg, local_port, index, rval));
   3349 
   3350             /* Set strict priority bit if weight is zero */
   3351             if (minsp_width != -1) {
   3352                 index %= minsp_width;
   3353             }
   3354             if (index < 32) {
   3355                 if (weights[i] != 0) {
   3356                     rval_lo &= ~(1 << index);
   3357                 } else {
   3358                     rval_lo |= 1 << index;
   3359                 }
   3360             } else {
   3361                 if (weights[i] != 0) {
   3362                     rval_hi &= ~(1 << (index - 32));
   3363                 } else {
   3364                     rval_hi |= 1 << (index - 32);
   3365                 }
   3366             }
   3367         }
   3368 
   3369         COMPILER_64_SET(rval64, rval_hi, rval_lo);
   3370         BCM_IF_ERROR_RETURN
   3371             (soc_reg_set(unit, minsp_reg, local_port, 0, rval64));
   3372     }
   3373 
   3374     /* Program the scheduling mode */
   3375     BCM_IF_ERROR_RETURN(soc_reg32_get(unit, config_reg, local_port, 0, &rval));
   3376     fval = soc_reg_field_get(unit, config_reg, rval, SCHEDULING_SELECTf);
   3377     fval &= ~(0x3 << mode_sel_shift);
   3378     fval |= mode_sel << mode_sel_shift;
   3379         soc_reg_field_set(unit, config_reg, &rval, SCHEDULING_SELECTf, fval);
   3380     BCM_IF_ERROR_RETURN(soc_reg32_set(unit, config_reg, local_port, 0, rval));
   3381 
   3382     return BCM_E_NONE;
   3383 }
   3384 
   3385 /*
   3386  * Function:
   3387  *     _bcm_td_cosq_sched_get
   3388  * Purpose:
   3389  *     Get scheduling mode setting
   3390  * Parameters:
   3391  *     unit                - (IN) unit number
   3392  *     port                - (IN) port number or GPORT identifier
   3393  *     cosq                - (IN) COS queue number
   3394  *     mode                - (OUT) scheduling mode (BCM_COSQ_XXX)
   3395  *     num_weights         - (IN) number of entries in weights array
   3396  *     weights             - (OUT) weights array
   3397  * Returns:
   3398  *     BCM_E_XXX
   3399  */
   3400 STATIC int
   3401 _bcm_td_cosq_sched_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   3402                        int *mode, int num_weights, int *weights)
   3403 {
   3404     soc_info_t *si;
   3405     _bcm_td_cosq_port_info_t *port_info;
   3406     _bcm_td_cosq_node_t *node;
   3407     bcm_port_t local_port;
   3408     int index;
   3409     soc_reg_t config_reg, weight_reg;
   3410     uint32 rval;
   3411     int mode_sel_shift, mode_sel, i;
   3412 
   3413     if (cosq < 0) {
   3414         if (cosq == -1) {
   3415             /* caller needs to resolve the wild card value (-1) */
   3416             return BCM_E_INTERNAL;
   3417         } else { /* reject all other negative value */
   3418             return BCM_E_PARAM;
   3419         }
   3420     }
   3421 
   3422     si = &SOC_INFO(unit);
   3423 
   3424     mode_sel_shift = 0;
   3425 
   3426     if (BCM_GPORT_IS_SCHEDULER(port)) { /* ETS style scheduler */
   3427         BCM_IF_ERROR_RETURN
   3428             (_bcm_td_cosq_node_get(unit, port, NULL, &local_port, NULL,
   3429                                    &node));
   3430 
   3431         if (cosq + num_weights > node->numq) {
   3432             return BCM_E_PARAM;
   3433         }
   3434 
   3435         if (node->hw_cosq_attached_to < 0) { /* Not resolved yet */
   3436             return BCM_E_NOT_FOUND;
   3437         }
   3438 
   3439         switch (node->level) {
   3440         case 1: /* S1 scheduler */
   3441             config_reg = ESCONFIGr;
   3442             weight_reg = COSWEIGHTSr;
   3443             break;
   3444         case 2:
   3445             if (node->hw_cosq_attached_to == 0) { /* MC group scheduler */
   3446                 config_reg = S3_CONFIG_MCr;
   3447                 weight_reg = S3_COSWEIGHTSr;
   3448             } else { /* S2 scheduler */
   3449                 config_reg = S2_CONFIGr;
   3450                 weight_reg = S2_COSWEIGHTSr;
   3451                 mode_sel_shift = (node->hw_cosq_attached_to - 1) * 2;
   3452             }
   3453             break;
   3454         case 3: /* S3 scheduler */
   3455             config_reg = S3_CONFIGr;
   3456             weight_reg = S3_COSWEIGHTSr;
   3457             mode_sel_shift = node->hw_cosq_attached_to * 2;
   3458             break;
   3459         default:
   3460             return BCM_E_INTERNAL;
   3461         }
   3462     } else { /* non-ETS style scheduler */
   3463         BCM_IF_ERROR_RETURN
   3464             (_bcm_td_cosq_localport_resolve(unit, port, &local_port));
   3465         if (IS_CPU_PORT(unit, local_port)) {
   3466             if (cosq + num_weights > si->num_cpu_cosq) {
   3467                 return BCM_E_PARAM;
   3468             }
   3469             config_reg = ESCONFIGr;
   3470             weight_reg = COSWEIGHTSr;
   3471         } else {
   3472             port_info = &_bcm_td_cosq_port_info[unit][local_port];
   3473             for (i = 0; i < _BCM_TD_NUM_SCHEDULER; i++) {
   3474                 if (port_info->sched[i].numq > 0 &&
   3475                     port_info->sched[i].cosq_attached_to != -1) {
   3476                     /* ETS style scheduling has been setup */
   3477                     return BCM_E_PORT;
   3478                 }
   3479             }
   3480             if (cosq + num_weights > _BCM_TD_NUM_NON_SC_QM_UCAST_QUEUE) {
   3481                 return BCM_E_PARAM;
   3482             }
   3483             config_reg = S2_CONFIGr;
   3484             weight_reg = S2_COSWEIGHTSr;
   3485             mode_sel_shift = 0; /* S2.0 */
   3486         }
   3487     }
   3488 
   3489     BCM_IF_ERROR_RETURN(soc_reg32_get(unit, config_reg, local_port, 0, &rval));
   3490     mode_sel = soc_reg_field_get(unit, config_reg, rval, SCHEDULING_SELECTf);
   3491 
   3492     switch ((mode_sel >> mode_sel_shift) & 0x03) {
   3493     case 0:
   3494         *mode = BCM_COSQ_STRICT;
   3495         break;
   3496     case 1:
   3497         *mode = BCM_COSQ_ROUND_ROBIN;
   3498         break;
   3499     case 2:
   3500         *mode = BCM_COSQ_WEIGHTED_ROUND_ROBIN;
   3501         break;
   3502     case 3:
   3503         *mode = BCM_COSQ_DEFICIT_ROUND_ROBIN;
   3504         break;
   3505     }
   3506 
   3507     if (*mode == BCM_COSQ_WEIGHTED_ROUND_ROBIN ||
   3508         *mode == BCM_COSQ_DEFICIT_ROUND_ROBIN) {
   3509         for (i = 0; i < num_weights; i++) {
   3510             BCM_IF_ERROR_RETURN
   3511                 (_bcm_td_cosq_index_resolve(unit, port, cosq + i,
   3512                                             _BCM_TD_COSQ_INDEX_STYLE_SCHEDULER,
   3513                                             NULL, &index, NULL));
   3514             BCM_IF_ERROR_RETURN(soc_reg32_get(unit, weight_reg, local_port, 
   3515                                 index, &rval));
   3516             weights[i] = soc_reg_field_get(unit, weight_reg, rval,
   3517                                            COSWEIGHTSf);
   3518         }
   3519     }
   3520 
   3521     return BCM_E_NONE;
   3522 }
   3523 
   3524 STATIC int
   3525 _bcm_td_cosq_ingress_sp_get(int unit, bcm_gport_t gport,
   3526                          bcm_cos_queue_t pri_grp, int *p_pool_start,
   3527                          int *p_pool_end)
   3528 {
   3529     int local_port;
   3530     uint32 rval, pool;
   3531     static const soc_field_t prigroup_spid_field[] = {
   3532         PG0_SPIDf, PG1_SPIDf, PG2_SPIDf, PG3_SPIDf,
   3533         PG4_SPIDf, PG5_SPIDf, PG6_SPIDf, PG7_SPIDf
   3534     };
   3535 
   3536     if (pri_grp == BCM_COS_INVALID) {
   3537         *p_pool_start = 0;
   3538         *p_pool_end = 3;
   3539         return BCM_E_NONE;
   3540     }
   3541 
   3542     BCM_IF_ERROR_RETURN
   3543             (_bcm_td_cosq_localport_resolve(unit, gport, &local_port));
   3544 
   3545     if (!SOC_PORT_VALID(unit, local_port)) {
   3546         return BCM_E_PORT;
   3547     }
   3548 
   3549     if (pri_grp >= 8) {
   3550         return BCM_E_PARAM;
   3551     }
   3552 
   3553     SOC_IF_ERROR_RETURN(READ_PORT_PG_SPIDr(unit, local_port, &rval));
   3554     pool = soc_reg_field_get(unit, PORT_PG_SPIDr, rval,
   3555                                 prigroup_spid_field[pri_grp]);
   3556 
   3557     *p_pool_start = *p_pool_end = pool;
   3558     return BCM_E_NONE;
   3559 }
   3560 
   3561 #ifdef BCM_WARM_BOOT_SUPPORT
   3562 
   3563 #define BCM_WB_VERSION_1_0                SOC_SCACHE_VERSION(1,0)
   3564 #define BCM_WB_VERSION_1_1                SOC_SCACHE_VERSION(1,1)
   3565 #define BCM_WB_DEFAULT_VERSION            BCM_WB_VERSION_1_1
   3566 
   3567 #define _BCM_TD_COSQ_WB_UCAST_COSQ_MASK        0x1f /* byte 0 bit 4-0 */
   3568 #define _BCM_TD_COSQ_WB_UCAST_COSQ_SHIFT       0
   3569 #define _BCM_TD_COSQ_WB_UCAST_BASE_MASK        0x07 /* byte 0 bit 7-5 */
   3570 #define _BCM_TD_COSQ_WB_UCAST_BASE_SHIFT       5
   3571 #define _BCM_TD_COSQ_WB_MCAST_COSQ_MASK        0x1f /* byte 0 bit 4-0 */
   3572 #define _BCM_TD_COSQ_WB_MCAST_COSQ_SHIFT       0
   3573 #define _BCM_TD_COSQ_WB_MCAST_BASE_MASK        0x07 /* byte 0 bit 7-5 */
   3574 #define _BCM_TD_COSQ_WB_MCAST_BASE_SHIFT       5
   3575 #define _BCM_TD_COSQ_WB_EXT_UCAST_COSQ_MASK    0x1f /* byte 0 bit 4-0 */
   3576 #define _BCM_TD_COSQ_WB_EXT_UCAST_COSQ_SHIFT   0
   3577 #define _BCM_TD_COSQ_WB_EXT_UCAST_NUMQ_MASK    0x07 /* byte 0 bit 7-5 */
   3578 #define _BCM_TD_COSQ_WB_EXT_UCAST_NUMQ_SHIFT   5
   3579 #define _BCM_TD_COSQ_WB_EXT_UCAST_BASE_MASK    0x0f /* byte 1 bit 3-0 */
   3580 #define _BCM_TD_COSQ_WB_EXT_UCAST_BASE_SHIFT   0
   3581 #define _BCM_TD_COSQ_WB_SCHED_LEVEL_MASK       0x03 /* byte 0 bit 1-0 */
   3582 #define _BCM_TD_COSQ_WB_SCHED_LEVEL_SHIFT      0
   3583 #define _BCM_TD_COSQ_WB_SCHED_NUMQ_MASK        0x1f /* byte 0 bit 6-2 */
   3584 #define _BCM_TD_COSQ_WB_SCHED_NUMQ_SHIFT       2
   3585 #define _BCM_TD_COSQ_WB_SCHED_COSQ_MASK        0x0f /* byte 1 bit 3-0 */
   3586 #define _BCM_TD_COSQ_WB_SCHED_COSQ_SHIFT       0
   3587 #define _BCM_TD_COSQ_WB_SCHED_HW_COSQ_MASK     0x07 /* byte 1 bit 6-4 */
   3588 #define _BCM_TD_COSQ_WB_SCHED_HW_COSQ_SHIFT    4
   3589 
   3590 #define SET_FIELD(_field, _value)                       \
   3591     (((_value) & _BCM_TD_COSQ_WB_## _field## _MASK) <<  \
   3592      _BCM_TD_COSQ_WB_## _field## _SHIFT)
   3593 #define GET_FIELD(_field, _byte)                        \
   3594     (((_byte) >> _BCM_TD_COSQ_WB_## _field## _SHIFT) &  \
   3595      _BCM_TD_COSQ_WB_## _field## _MASK)
   3596 
   3597 /*
   3598  * Function:
   3599  *     _bcm_td_cosq_wb_alloc_size_get
   3600  * Purpose:
   3601  *     Calculates the scache space required for a given warmboot version 
   3602  * Parameters:
   3603  *     unit - unit number
   3604  *     wb_ver - WarmBoot version
   3605  * Returns:
   3606  *     Size of scache size required
   3607  * Notes:
   3608  *    Handle scache allocation sizes for new versions
   3609  */
   3610 STATIC int
   3611 _bcm_td_cosq_wb_alloc_size_get(int unit, int wb_ver)
   3612 {
   3613     bcm_port_t port;
   3614     int alloc_size = 0;
   3615 
   3616     PBMP_ALL_ITER(unit, port) {
   3617         if (IS_CPU_PORT(unit, port)) {
   3618             continue;
   3619         }
   3620         if (SOC_INFO(unit).port_num_ext_cosq[port] != 0) {
   3621             alloc_size += 68;
   3622         } else {
   3623             alloc_size += 36;
   3624         }
   3625         /* Scache space to save ucast SC/QM queu info */
   3626         if (wb_ver >= BCM_WB_VERSION_1_1) {
   3627             alloc_size += 3;
   3628         }
   3629     }
   3630 
   3631     return alloc_size;
   3632 }
   3633 
   3634 /*
   3635  * Function:
   3636  *     _bcm_td_cosq_wb_alloc
   3637  * Purpose:
   3638  *     Allocates required scache space in Cold Boot
   3639  * Parameters:
   3640  *     unit - unit number
   3641  * Returns:
   3642  *     BCM_E_XXX
   3643  */
   3644 STATIC int
   3645 _bcm_td_cosq_wb_alloc(int unit)
   3646 {
   3647     soc_scache_handle_t scache_handle;
   3648     uint8 *scache_ptr;
   3649     int rv, alloc_size;
   3650 
   3651     alloc_size = _bcm_td_cosq_wb_alloc_size_get(unit, BCM_WB_DEFAULT_VERSION);
   3652 
   3653     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_COSQ, 0);
   3654     /* Allocate required scache size */
   3655     rv = _bcm_esw_scache_ptr_get(unit, scache_handle, TRUE, alloc_size,
   3656                                  &scache_ptr, BCM_WB_DEFAULT_VERSION, NULL);
   3657     if (rv == BCM_E_NOT_FOUND) {
   3658         rv = BCM_E_NONE;
   3659     }
   3660 
   3661     return rv;
   3662 }
   3663 
   3664 int
   3665 bcm_td_cosq_sync(int unit)
   3666 {
   3667     soc_scache_handle_t scache_handle;
   3668     uint8 *scache_ptr, *map;
   3669     uint8 *scache_ptr_2, *map_2;
   3670     _bcm_td_cosq_port_info_t *port_info;
   3671     _bcm_td_cosq_node_t *node;
   3672     bcm_port_t port;
   3673     int index;
   3674     uint32 num_cosq;
   3675 
   3676     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_COSQ, 0);
   3677     BCM_IF_ERROR_RETURN
   3678         (_bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 0,
   3679                                  &scache_ptr, BCM_WB_DEFAULT_VERSION, NULL));
   3680 
   3681     /* WB version 1.1 state starts at the end of scache for 1.0 version */
   3682     scache_ptr_2 = scache_ptr +
   3683                    _bcm_td_cosq_wb_alloc_size_get(unit, BCM_WB_VERSION_1_0);
   3684 
   3685     PBMP_ALL_ITER(unit, port) {
   3686         if (IS_CPU_PORT(unit, port)) {
   3687             continue;
   3688         }
   3689         port_info = &_bcm_td_cosq_port_info[unit][port];
   3690 
   3691         /* Store unicast queue info into scache */
   3692         map = scache_ptr;
   3693         *map = 0;
   3694         scache_ptr++;
   3695         for (index = 0; index < _BCM_TD_NUM_NON_SC_QM_UCAST_QUEUE; index++) {
   3696             node = &port_info->ucast[index];
   3697             if (node->numq == 0) {
   3698                 continue;
   3699             }
   3700             /*
   3701              * value range:
   3702              *     numq: 1, or 0 for unused entry
   3703              *     base: 0 - 7
   3704              *     cosq_attached_to: -1 for unattached node
   3705              *                       0 - 1 on regular port
   3706              *                       0 - 17 on extended queue port
   3707              */
   3708             *map |= 1 << index;
   3709             *scache_ptr = SET_FIELD(UCAST_COSQ, node->cosq_attached_to) |
   3710                           SET_FIELD(UCAST_BASE, node->base);
   3711             scache_ptr++;
   3712         }
   3713 
   3714         /* Store unicast SC/QM queue info into scache */
   3715         /* Note that scache_ptr_2 is used to recovered for level 1.2 */
   3716         map_2 = scache_ptr_2;
   3717         *map_2 = 0;
   3718         scache_ptr_2++;
   3719         for (index = _BCM_TD_NUM_NON_SC_QM_UCAST_QUEUE;
   3720              index < _BCM_TD_NUM_UCAST_QUEUE_GROUP;
   3721              index++) {
   3722             node = &port_info->ucast[index];
   3723             if (node->numq == 0) {
   3724                 continue;
   3725             }
   3726             /*
   3727              * value range for SC or QM queue (special encoding):
   3728              *     numq: 1, or 0 for unused entry
   3729              *     base : 8 - 9
   3730              *     cosq_attached_to: -1 for unattched node
   3731              *                       0 - 6
   3732              *     use magic number (base + 10) in UCAST_COSQ
   3733              *     use cosq_attached_to in UCAST_BASE
   3734              */
   3735             *map_2 |= 1 << (index - _BCM_TD_NUM_NON_SC_QM_UCAST_QUEUE);
   3736             *scache_ptr_2 = SET_FIELD(UCAST_COSQ, node->base + 10) |
   3737                             SET_FIELD(UCAST_BASE, node->cosq_attached_to);
   3738             scache_ptr_2++;
   3739         }
   3740 
   3741         /* Store multicast queue info into scache */
   3742         map = scache_ptr;
   3743         *map = 0;
   3744         scache_ptr++;
   3745         for (index = 0; index < _BCM_TD_NUM_MCAST_QUEUE_GROUP; index++) {
   3746             node = &port_info->mcast[index];
   3747             if (node->numq == 0) {
   3748                 continue;
   3749             }
   3750             /*
   3751              * value range:
   3752              *     numq: 1, or 0 for unused entry
   3753              *     base: 0 - 3
   3754              *     cosq_attached_to: -1 for unattached node
   3755              *                       0 - 1 on regular port
   3756              *                       0 - 17 on extended queue port
   3757              * value range for SC/QM queue:
   3758              *     numq: 1, or 0 for unused entry
   3759              *     base: 4
   3760              *     cosq_attached_to: -1 for unattached node
   3761              *                       0 - 6
   3762              */
   3763             *map |= 1 << index;
   3764             *scache_ptr = SET_FIELD(MCAST_COSQ, node->cosq_attached_to) |
   3765                 SET_FIELD(MCAST_BASE, node->base);
   3766             scache_ptr++;
   3767         }
   3768 
   3769         /* Store extended unicast queue info into scache */
   3770         if (SOC_INFO(unit).port_num_ext_cosq[port] != 0) {
   3771             map = scache_ptr;
   3772             *map = 0;
   3773             scache_ptr += 2;
   3774             for (index = 0; index < _BCM_TD_NUM_EXT_UCAST_QUEUE_GROUP;
   3775                  index++) {
   3776                 node = &port_info->ext_ucast[index];
   3777                 if (node->numq == 0) {
   3778                     continue;
   3779                 }
   3780                 /*
   3781                  * value range:
   3782                  *     numq: 1 - 4, or 0 for unused entry
   3783                  *     base: 0 - 15
   3784                  *     cosq_attached_to: 0 - 17, or -1 for unattached node
   3785                  */
   3786                 map[index >> 3] |= 1 << (index & 0x07);
   3787                 *scache_ptr =
   3788                     SET_FIELD(EXT_UCAST_COSQ, node->cosq_attached_to) |
   3789                     SET_FIELD(EXT_UCAST_NUMQ, node->numq);
   3790                 scache_ptr++;
   3791                 if (node->cosq_attached_to != -1) {
   3792                     *scache_ptr = SET_FIELD(EXT_UCAST_BASE, node->base);
   3793                     scache_ptr++;
   3794                 }
   3795             }
   3796         }
   3797 
   3798         /* Store scheduler info into scache */
   3799         map = scache_ptr;
   3800         *map = 0;
   3801         scache_ptr += 2;
   3802         for (index = 0; index < _BCM_TD_NUM_SCHEDULER; index++) {
   3803             node = &port_info->sched[index];
   3804             if (node->numq == 0) {
   3805                 continue;
   3806             }
   3807             /*
   3808              * value range:
   3809              *     numq: 0 for unused entry
   3810              *           1 - 4 for S1 scheduler
   3811              *           1 - 4 for MC group scheduler
   3812              *           1 - 9 for S2 scheduler
   3813              *           1 - 18 for S3 scheduler
   3814              *     cosq_attached_to: -1 for unattached node
   3815              *                       0 for S1 scheduler
   3816              *                       0 - 3 for MC group and S3 scheduler
   3817              *                       0 - 8 for S3 scheduler
   3818              *     hw_cosq_attached_to: -1 for unattached or unresolved node
   3819              *                          0 for S1 and MC group scheduler
   3820              *                          1 - 3 for S2 scheduler
   3821              *                          0 - 3 for S3 scheduler
   3822              *     level: 1 - 3, or 0 for unattached node
   3823              */
   3824             map[index >> 3] |= 1 << (index & 0x07);
   3825             *scache_ptr = SET_FIELD(SCHED_LEVEL, node->level) |
   3826                 SET_FIELD(SCHED_NUMQ, node->numq);
   3827             scache_ptr++;
   3828             if (node->level != 0) {
   3829                 *scache_ptr = SET_FIELD(SCHED_COSQ, node->cosq_attached_to) |
   3830                     SET_FIELD(SCHED_HW_COSQ, node->hw_cosq_attached_to);
   3831                 scache_ptr++;
   3832             }
   3833         }
   3834     }
   3835     /* Number COSQ */
   3836     num_cosq = _bcm_td_num_cosq[unit];
   3837     sal_memcpy(scache_ptr_2, &num_cosq, sizeof(num_cosq));
   3838 
   3839     return BCM_E_NONE;
   3840 }
   3841 
   3842 int
   3843 bcm_td_cosq_reinit(int unit)
   3844 {
   3845     soc_scache_handle_t scache_handle;
   3846     uint8 *scache_ptr, *map, value;
   3847     uint8 *scache_ptr_2, *map_2;
   3848     uint16 recovered_ver;
   3849     int additional_scache_size = 0;
   3850     soc_info_t *si;
   3851     _bcm_td_cosq_port_info_t *port_info;
   3852     _bcm_td_cosq_node_t *node, *s1_node, *s2_node[3], *s3_node[4], *mcg_node;
   3853     bcm_module_t local_modid, modid_out;
   3854     bcm_port_t port, port_out, phy_port, mmu_port;
   3855     uint64 rval64;
   3856     uint32 addr, rval, s2_input[3], sched_encap;
   3857     int rv, uc_to_s2, use_mc_group, index, s2_index, hw_cosq, stable_size = 0;
   3858     soc_profile_mem_t *profile_mem;
   3859     soc_profile_reg_t *profile_reg0, *profile_reg1;
   3860     soc_reg_t reg;
   3861     int set_index, cosq, numq;
   3862     uint32 entry[SOC_MAX_MEM_WORDS];
   3863     static const soc_field_t fields[] = {
   3864         S3_GROUP_NO_I0f, S3_GROUP_NO_I1f, S3_GROUP_NO_I2f, S3_GROUP_NO_I3f,
   3865         S3_GROUP_NO_I4f, S3_GROUP_NO_I5f, S3_GROUP_NO_I6f, S3_GROUP_NO_I7f,
   3866         S3_GROUP_NO_I8f
   3867     };
   3868     uint32 num_cosq;
   3869 
   3870     SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size));
   3871     if ((stable_size == 0) || (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit))) { 
   3872         /* COSQ warmboot requires extended scache support i.e. level2 warmboot*/  
   3873         return BCM_E_NONE;
   3874     }
   3875 
   3876     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_COSQ, 0);
   3877     rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 0, &scache_ptr,
   3878                                  BCM_WB_DEFAULT_VERSION, &recovered_ver);
   3879     if (BCM_FAILURE(rv)) {
   3880         return rv;
   3881     }
   3882 
   3883     si = &SOC_INFO(unit);
   3884 
   3885     /* WB version 1.1 state starts at the end of scache for 1.0 version */
   3886     scache_ptr_2 = scache_ptr +
   3887                    _bcm_td_cosq_wb_alloc_size_get(unit, BCM_WB_VERSION_1_0);
   3888 
   3889     PBMP_ALL_ITER(unit, port) {
   3890         if (IS_CPU_PORT(unit, port)) {
   3891             continue;
   3892         }
   3893         port_info = &_bcm_td_cosq_port_info[unit][port];
   3894 
   3895         /* Retrieve unicast queue info from scache */
   3896         map = scache_ptr;
   3897         scache_ptr++;
   3898         for (index = 0; index < _BCM_TD_NUM_NON_SC_QM_UCAST_QUEUE; index++) {
   3899             if ((*map & (1 << index)) == 0) {
   3900                 continue;
   3901             }
   3902             node = &port_info->ucast[index];
   3903             node->numq = 1;
   3904             value = GET_FIELD(UCAST_COSQ, *scache_ptr);
   3905             node->cosq_attached_to =
   3906                 value == _BCM_TD_COSQ_WB_UCAST_COSQ_MASK ? -1 : value;
   3907             node->base = GET_FIELD(UCAST_BASE, *scache_ptr);
   3908             scache_ptr++;
   3909         }
   3910 
   3911         /* Retrieve unicast SC/QM queue info from scache */
   3912         /* Note that scache_ptr_2 is used here for recovering this info */
   3913         if (recovered_ver >= BCM_WB_VERSION_1_1) {
   3914         map_2 = scache_ptr_2;
   3915         scache_ptr_2++;
   3916         for (index = _BCM_TD_NUM_NON_SC_QM_UCAST_QUEUE;
   3917              index < _BCM_TD_NUM_UCAST_QUEUE_GROUP;
   3918              index++) {
   3919 
   3920             if ((*map_2 &
   3921                 (1 << (index - _BCM_TD_NUM_NON_SC_QM_UCAST_QUEUE))) == 0) {
   3922                 continue;
   3923             }
   3924             node = &port_info->ucast[index];
   3925             node->numq = 1;
   3926             value = GET_FIELD(UCAST_COSQ, *scache_ptr_2);
   3927             node->cosq_attached_to = GET_FIELD(UCAST_BASE, *scache_ptr_2);
   3928             node->base = value - 10;
   3929             scache_ptr_2++;
   3930         }
   3931         }
   3932 
   3933         /* Retrieve multicast queue info from scache */
   3934         map = scache_ptr;
   3935         scache_ptr++;
   3936         for (index = 0; index < _BCM_TD_NUM_MCAST_QUEUE_GROUP; index++) {
   3937             if ((*map & (1 << index)) == 0) {
   3938                 continue;
   3939             }
   3940             node = &port_info->mcast[index];
   3941             node->numq = 1;
   3942             value = GET_FIELD(MCAST_COSQ, *scache_ptr);
   3943             node->cosq_attached_to =
   3944                 value == _BCM_TD_COSQ_WB_MCAST_COSQ_MASK ? -1 : value;
   3945             node->base = GET_FIELD(MCAST_BASE, *scache_ptr);
   3946             scache_ptr++;
   3947         }
   3948 
   3949         /* Retrieve extended unicast queue info from scache */
   3950         if (si->port_num_ext_cosq[port] != 0) {
   3951             map = scache_ptr;
   3952             scache_ptr += 2;
   3953             for (index = 0; index < _BCM_TD_NUM_EXT_UCAST_QUEUE_GROUP;
   3954                  index++) {
   3955                 if ((map[index >> 3] & (1 << (index & 0x07))) == 0) {
   3956                     continue;
   3957                 }
   3958                 node = &port_info->ext_ucast[index];
   3959                 value = GET_FIELD(EXT_UCAST_COSQ, *scache_ptr);
   3960                 node->cosq_attached_to =
   3961                     value == _BCM_TD_COSQ_WB_EXT_UCAST_COSQ_MASK ? -1 : value;
   3962                 node->numq = GET_FIELD(EXT_UCAST_NUMQ, *scache_ptr);
   3963                 scache_ptr++;
   3964                 if (node->cosq_attached_to != -1) {
   3965                     node->base = GET_FIELD(EXT_UCAST_BASE, *scache_ptr);
   3966                     scache_ptr++;
   3967                 }
   3968             }
   3969         }
   3970 
   3971         /* Retrieve scheduler info from scache */
   3972         map = scache_ptr;
   3973         scache_ptr += 2;
   3974         for (index = 0; index < _BCM_TD_NUM_SCHEDULER; index++) {
   3975             if ((map[index >> 3] & (1 << (index & 0x07))) == 0) {
   3976                 continue;
   3977             }
   3978             node = &port_info->sched[index];
   3979             node->level = GET_FIELD(SCHED_LEVEL, *scache_ptr);
   3980             node->numq = GET_FIELD(SCHED_NUMQ, *scache_ptr);
   3981             scache_ptr++;
   3982             if (node->level != 0) {
   3983                 value = GET_FIELD(SCHED_COSQ, *scache_ptr);
   3984                 node->cosq_attached_to =
   3985                     value == _BCM_TD_COSQ_WB_SCHED_COSQ_MASK ? -1 : value;
   3986                 value = GET_FIELD(SCHED_HW_COSQ, *scache_ptr);
   3987                 node->hw_cosq_attached_to =
   3988                     value == _BCM_TD_COSQ_WB_SCHED_HW_COSQ_MASK ? -1 : value;
   3989                 scache_ptr++;
   3990             } else {
   3991                 node->cosq_attached_to = -1;
   3992                 node->hw_cosq_attached_to = -1;
   3993             }
   3994         }
   3995     }
   3996     /* Number COSQ */
   3997     sal_memcpy(&num_cosq, scache_ptr_2, sizeof(num_cosq));
   3998     if (!num_cosq) {
   3999         /*sync didn't happen in the previous boot */
   4000         num_cosq = _bcm_esw_cosq_config_property_get(unit);
   4001     }
   4002     _bcm_td_num_cosq[unit] = num_cosq;
   4003 
   4004     /* Ideally this equation holds good for all incremental versions */
   4005     additional_scache_size =
   4006             _bcm_td_cosq_wb_alloc_size_get(unit, BCM_WB_DEFAULT_VERSION) -
   4007             _bcm_td_cosq_wb_alloc_size_get(unit, recovered_ver);
   4008 
   4009     /* Need to realloc unavailable space for subsequent syncs */
   4010     SOC_IF_ERROR_RETURN
   4011             (soc_scache_realloc(unit, scache_handle, additional_scache_size));
   4012 
   4013     PBMP_ALL_ITER(unit, port) {
   4014         if (IS_CPU_PORT(unit, port)) {
   4015             continue;
   4016         }
   4017         port_info = &_bcm_td_cosq_port_info[unit][port];
   4018 
   4019         /* Retrieve info from hardware */
   4020         for (s2_index = 0; s2_index < _BCM_TD_NUM_S2_SCHEDULER; s2_index++) {
   4021             s2_input[s2_index] = 0;
   4022             BCM_IF_ERROR_RETURN
   4023                 (READ_S2_S3_ROUTINGr(unit, port, s2_index, &rval64));
   4024             for (index = 0; index < _BCM_TD_S2_SCHEDULER_NUM_INPUT; index++) {
   4025                 hw_cosq = soc_reg64_field32_get(unit, S2_S3_ROUTINGr, rval64,
   4026                                                 fields[index]);
   4027                 if (hw_cosq != 0x1f) {
   4028                     s2_input[s2_index] |= 1 << hw_cosq;
   4029                 }
   4030             }
   4031         }
   4032         BCM_IF_ERROR_RETURN(READ_S3_CONFIGr(unit, port, &rval));
   4033         uc_to_s2 = soc_reg_field_get(unit, S3_CONFIGr, rval, ROUTE_UC_TO_S2f);
   4034         BCM_IF_ERROR_RETURN(READ_S3_CONFIG_MCr(unit, port, &rval));
   4035         use_mc_group = soc_reg_field_get(unit, S3_CONFIG_MCr, rval,
   4036                                          USE_MC_GROUPf);
   4037 
   4038         /* Get modid */
   4039         BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &local_modid));
   4040         BCM_IF_ERROR_RETURN
   4041             (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, local_modid,
   4042                                      port, &modid_out, &port_out));
   4043 
   4044         s1_node = NULL;
   4045         s2_node[0] = s2_node[1] = s2_node[2] = NULL;
   4046         s3_node[0] = s3_node[1] = s3_node[2] = s3_node[3] = NULL;
   4047         mcg_node = NULL;
   4048 
   4049         /* Recover software state of scheduler */
   4050         for (index = 0; index < _BCM_TD_NUM_SCHEDULER; index++) {
   4051             node = &port_info->sched[index];
   4052             if (node->numq == 0) {
   4053                 continue;
   4054             }
   4055             sched_encap = (index << 16) | (modid_out << 8) | port_out;
   4056             BCM_GPORT_SCHEDULER_SET(node->gport, sched_encap);
   4057             if (node->cosq_attached_to == -1) {
   4058                 continue;
   4059             }
   4060             if (node->level == 1) {
   4061                 s1_node = node;
   4062             } else if (node->level == 2) {
   4063                 if (node->hw_cosq_attached_to == 0) {
   4064                     mcg_node = node;
   4065                 } else if (node->hw_cosq_attached_to != -1) {
   4066                     s2_node[node->hw_cosq_attached_to - 1] = node;
   4067                 }
   4068             } else if (node->level == 3) {
   4069                 if (node->hw_cosq_attached_to != -1) {
   4070                     s3_node[node->hw_cosq_attached_to] = node;
   4071                 }
   4072             }
   4073         }
   4074 
   4075         if (s1_node == NULL)
   4076             continue;
   4077 
   4078         /* Recover software state of S2 scheduler */
   4079         for (index = 0; index < _BCM_TD_NUM_S2_SCHEDULER; index++) {
   4080             if (s2_node[index] == NULL) {
   4081                 continue;
   4082             }
   4083             s2_node[index]->parent = s1_node;
   4084             s2_node[index]->sibling = s1_node->child;
   4085             s1_node->child = s2_node[index];
   4086         }
   4087 
   4088         /* Recover software state of S3 scheduler */
   4089         for (index = 0; index < _BCM_TD_NUM_S3_SCHEDULER; index++) {
   4090             if (s3_node[index] == NULL) {
   4091                 continue;
   4092             }
   4093             hw_cosq = index;
   4094             for (s2_index = 0; s2_index < _BCM_TD_NUM_S2_SCHEDULER;
   4095                  s2_index++) {
   4096                 if (s2_input[s2_index] & (1 << hw_cosq)) {
   4097                     s3_node[index]->parent = s2_node[s2_index];
   4098                     s3_node[index]->sibling = s2_node[s2_index]->child;
   4099                     s2_node[s2_index]->child = s3_node[index];
   4100                     break;
   4101                 }
   4102             }
   4103         }
   4104 
   4105         /* Recover software state of unicast queue */
   4106         for (index = 0; index < _BCM_TD_NUM_UCAST_QUEUE_GROUP; index++) {
   4107             node = &port_info->ucast[index];
   4108             if (node->numq == 0) {
   4109                 continue;
   4110             }
   4111             BCM_GPORT_UCAST_QUEUE_GROUP_SYSQID_SET(node->gport, port, index);
   4112             if (node->cosq_attached_to == -1) {
   4113                 node->hw_cosq_attached_to = -1;
   4114                 continue;
   4115             }
   4116             if (node->base > 7) { /* unicast SC or QM queue */
   4117                 node->parent = s1_node;
   4118                 node->sibling = s1_node->child;
   4119                 s1_node->child = node;
   4120                 node->hw_cosq_attached_to = node->base - 3; /* 5 or 6 */
   4121             } else if (uc_to_s2 || node->base >= 4) {
   4122                 hw_cosq = node->base + 4;
   4123                 for (s2_index = 0; s2_index < _BCM_TD_NUM_S2_SCHEDULER;
   4124                      s2_index++) {
   4125                     if (s2_input[s2_index] & (1 << hw_cosq)) {
   4126                         node->parent = s2_node[s2_index];
   4127                         node->sibling = s2_node[s2_index]->child;
   4128                         s2_node[s2_index]->child = node;
   4129                         node->hw_cosq_attached_to = hw_cosq;
   4130                         break;
   4131                     }
   4132                 }
   4133             } else {
   4134                 node->parent = s3_node[node->base];
   4135                 node->sibling = s3_node[node->base]->child;
   4136                 s3_node[node->base]->child = node;
   4137                 node->hw_cosq_attached_to = 1;
   4138             }
   4139         }
   4140 
   4141         /* Recover software state of multicast queue */
   4142         for (index = 0; index < _BCM_TD_NUM_MCAST_QUEUE_GROUP; index++) {
   4143             node = &port_info->mcast[index];
   4144             if (node->numq == 0) {
   4145                 continue;
   4146             }
   4147             BCM_GPORT_MCAST_QUEUE_GROUP_SYSQID_SET(node->gport, port, index);
   4148             if (node->cosq_attached_to == -1) {
   4149                 node->hw_cosq_attached_to = -1;
   4150                 continue;
   4151             }
   4152             if (node->base > 3) { /* multicast SC/QM queue */
   4153                 node->parent = s1_node;
   4154                 node->sibling = s1_node->child;
   4155                 s1_node->child = node;
   4156                 node->hw_cosq_attached_to = 4;
   4157             } else if (use_mc_group) {
   4158                 node->parent = mcg_node;
   4159                 node->sibling = mcg_node->child;
   4160                 mcg_node->child = node;
   4161                 node->hw_cosq_attached_to = node->base;
   4162             } else {
   4163                 node->parent = s3_node[node->base];
   4164                 node->sibling = s3_node[node->base]->child;
   4165                 s3_node[node->base]->child = node;
   4166                 node->hw_cosq_attached_to = 0;
   4167             }
   4168         }
   4169 
   4170         /* Recover software state of extended unicast queue */
   4171         for (index = 0; index < _BCM_TD_NUM_EXT_UCAST_QUEUE_GROUP; index++) {
   4172             node = &port_info->ext_ucast[index];
   4173             if (node->numq == 0) {
   4174                 continue;
   4175             }
   4176             BCM_GPORT_UCAST_QUEUE_GROUP_SYSQID_SET
   4177                 (node->gport, port, _BCM_TD_NUM_UCAST_QUEUE_GROUP + index);
   4178             if (node->cosq_attached_to == -1) {
   4179                 node->hw_cosq_attached_to = -1;
   4180                 continue;
   4181             }
   4182             node->parent = s3_node[node->base];
   4183             node->sibling = s3_node[node->base]->child;
   4184             s3_node[node->base]->child = node;
   4185             node->hw_cosq_attached_to = node->base + 2;
   4186         }
   4187     }
   4188 
   4189     /* Update PORT_COS_MAP memory profile reference counter */
   4190     profile_mem = _bcm_td_cos_map_profile[unit];
   4191     PBMP_ALL_ITER(unit, port) {
   4192         SOC_IF_ERROR_RETURN
   4193             (soc_mem_read(unit, COS_MAP_SELm, MEM_BLOCK_ALL, port, &entry));
   4194         set_index = soc_mem_field32_get(unit, COS_MAP_SELm, &entry, SELECTf);
   4195         SOC_IF_ERROR_RETURN
   4196             (soc_profile_mem_reference(unit, profile_mem, set_index * 16, 16));
   4197     }
   4198     if (SOC_INFO(unit).cpu_hg_index != -1) {
   4199         SOC_IF_ERROR_RETURN(soc_mem_read(unit, COS_MAP_SELm, MEM_BLOCK_ALL,
   4200                                          SOC_INFO(unit).cpu_hg_index, &entry));
   4201         set_index = soc_mem_field32_get(unit, COS_MAP_SELm, &entry, SELECTf);
   4202         SOC_IF_ERROR_RETURN
   4203             (soc_profile_mem_reference(unit, profile_mem, set_index, 1));
   4204     }
   4205 
   4206     
   4207 
   4208     /* Update MMU_WRED_DROP_CURVE_PROFILE_x memory profile reference counter */
   4209     profile_mem = _bcm_td_wred_profile[unit];
   4210     PBMP_PORT_ITER(unit, port) {
   4211         if (SOC_INFO(unit).port_num_ext_cosq[port] == 0) { /* regular port */
   4212             reg = WRED_CONFIGr;
   4213         } else { /* extended queue port */
   4214             reg = DMVOQ_WRED_CONFIGr;
   4215         }
   4216         BCM_IF_ERROR_RETURN
   4217             (_bcm_td_cosq_index_resolve(unit, port, -1,
   4218                                         _BCM_TD_COSQ_INDEX_STYLE_WRED, NULL,
   4219                                         NULL, &numq));
   4220         for (cosq = 0; cosq < numq; cosq++) {
   4221             BCM_IF_ERROR_RETURN
   4222                 (_bcm_td_cosq_index_resolve(unit, port, cosq,
   4223                                             _BCM_TD_COSQ_INDEX_STYLE_WRED,
   4224                                             NULL, &index, NULL));
   4225             addr = soc_reg_addr(unit, reg, port, index);
   4226             SOC_IF_ERROR_RETURN(soc_reg32_read(unit, addr, &rval));
   4227             set_index = soc_reg_field_get(unit, reg, rval, PROFILE_INDEXf);
   4228             SOC_IF_ERROR_RETURN
   4229                 (soc_profile_mem_reference(unit, profile_mem, set_index, 1));
   4230         }
   4231     }
   4232 
   4233     /* Update MMU_QCN_SITB memory profile and MMU_QCN_CFP_SEQ register profile
   4234      * reference counter */
   4235     profile_mem = _bcm_td_sample_int_profile[unit];
   4236     profile_reg0 = _bcm_td_feedback_profile[unit];
   4237     numq = sizeof(_bcm_td_cpq_en_field) / sizeof(_bcm_td_cpq_en_field[0]);
   4238     PBMP_PORT_ITER(unit, port) {
   4239         phy_port = si->port_l2p_mapping[port];
   4240         mmu_port = si->port_p2m_mapping[phy_port];
   4241         SOC_IF_ERROR_RETURN(soc_mem_read(unit, MMU_QCN_ENABLEm, MEM_BLOCK_ANY,
   4242                                          mmu_port, &entry));
   4243         for (cosq = 0; cosq < numq; cosq++) {
   4244             if (!soc_mem_field32_get(unit, MMU_QCN_ENABLEm, &entry,
   4245                                      _bcm_td_cpq_en_field[cosq])) {
   4246                 continue;
   4247             }
   4248             index = soc_mem_field32_get(unit, MMU_QCN_ENABLEm, &entry,
   4249                                         _bcm_td_cpq_index_field[cosq]);
   4250             SOC_IF_ERROR_RETURN(soc_mem_read(unit, MMU_QCN_CPQCFGm,
   4251                                              MEM_BLOCK_ANY, mmu_port, &entry));
   4252             set_index = soc_mem_field32_get(unit, MMU_QCN_CPQCFGm, &entry,
   4253                                             _bcm_td_sitb_sel_field[index]);
   4254             SOC_IF_ERROR_RETURN
   4255                 (soc_profile_mem_reference(unit, profile_mem, set_index * 64,
   4256                                            64));
   4257             set_index = soc_mem_field32_get(unit, MMU_QCN_CPQCFGm, &entry,
   4258                                             _bcm_td_eqtb_index_field[index]);
   4259             SOC_IF_ERROR_RETURN
   4260                 (soc_profile_reg_reference(unit, profile_reg0, set_index, 1));
   4261         }
   4262     }
   4263 
   4264     /* Update PRIO2COS_LLFC and PRIO2EXTQ_LLFC register profile reference
   4265      * counter */
   4266     profile_reg0 = _bcm_td_llfc_profile[unit];
   4267     profile_reg1 = _bcm_td_ext_llfc_profile[unit];
   4268     PBMP_ALL_ITER(unit, port) {
   4269         if (IS_CPU_PORT(unit, port)) {
   4270             continue;
   4271         }
   4272         SOC_IF_ERROR_RETURN(READ_PORT_LLFC_CFGr(unit, port, &rval));
   4273         set_index = soc_reg_field_get(unit, PORT_LLFC_CFGr, rval,
   4274                                       PROFILE_INDEXf);
   4275         SOC_IF_ERROR_RETURN
   4276             (soc_profile_reg_reference(unit, profile_reg0, set_index * 16,
   4277                                        16));
   4278         set_index = soc_reg_field_get(unit, PORT_LLFC_CFGr, rval,
   4279                                       EXT_PER_Q_INDEXf);
   4280         SOC_IF_ERROR_RETURN
   4281             (soc_profile_reg_reference(unit, profile_reg1, set_index * 16,
   4282                                        16));
   4283     }
   4284 
   4285     return BCM_E_NONE;
   4286 }
   4287 #endif /* BCM_WARM_BOOT_SUPPORT */
   4288 
   4289 /*
   4290  * Function:
   4291  *     bcm_td_cosq_init
   4292  * Purpose:
   4293  *     Initialize (clear) all COS schedule/mapping state.
   4294  * Parameters:
   4295  *     unit - unit number
   4296  * Returns:
   4297  *     BCM_E_XXX
   4298  */
   4299 int
   4300 bcm_td_cosq_init(int unit)
   4301 {
   4302     STATIC int _td_max_cosq = -1;
   4303     int cosq, numq, alloc_size, i;
   4304     bcm_port_t port;
   4305     soc_reg_t reg;
   4306     soc_reg_t mem;
   4307     static soc_mem_t wred_mems[6] = {
   4308         MMU_WRED_DROP_CURVE_PROFILE_0m, MMU_WRED_DROP_CURVE_PROFILE_1m,
   4309         MMU_WRED_DROP_CURVE_PROFILE_2m, MMU_WRED_DROP_CURVE_PROFILE_3m,
   4310         MMU_WRED_DROP_CURVE_PROFILE_4m, MMU_WRED_DROP_CURVE_PROFILE_5m
   4311     };
   4312     int entry_words[6];
   4313     mmu_wred_drop_curve_profile_0_entry_t entry_tcp_green;
   4314     mmu_wred_drop_curve_profile_1_entry_t entry_tcp_yellow;
   4315     mmu_wred_drop_curve_profile_2_entry_t entry_tcp_red;
   4316     mmu_wred_drop_curve_profile_3_entry_t entry_nontcp_green;
   4317     mmu_wred_drop_curve_profile_4_entry_t entry_nontcp_yellow;
   4318     mmu_wred_drop_curve_profile_5_entry_t entry_nontcp_red;
   4319     void *entries[6];
   4320     uint64 rval64[16], *rval64s[1];
   4321     uint32 profile_index, rval;
   4322     soc_info_t *si;
   4323 
   4324     if (_td_max_cosq < 0) {
   4325         _td_max_cosq = NUM_COS(unit);
   4326         NUM_COS(unit) = 8;
   4327     }
   4328 
   4329     if (!SOC_WARM_BOOT(unit)) {    /* Cold Boot */
   4330         BCM_IF_ERROR_RETURN (bcm_td_cosq_detach(unit, 0));
   4331     }
   4332 
   4333     numq = soc_property_get(unit, spn_BCM_NUM_COS, BCM_COS_DEFAULT);
   4334 
   4335     if (numq < 1) {
   4336         numq = 1;
   4337     } else if (numq > 8) {
   4338         numq = 8;
   4339     }
   4340 
   4341     if (!cosq_sync_lock[unit]) {
   4342         cosq_sync_lock[unit] = sal_mutex_create("TD cosq sync lock");
   4343         if (cosq_sync_lock[unit] == NULL) {
   4344             return BCM_E_MEMORY;
   4345         }
   4346     }
   4347 
   4348     si = &SOC_INFO(unit);
   4349     /* Create ETS port information structures */
   4350     alloc_size = sizeof(_bcm_td_cosq_port_info_t) * 66;
   4351     if (_bcm_td_cosq_port_info[unit] == NULL) {
   4352         _bcm_td_cosq_port_info[unit] =
   4353             sal_alloc(alloc_size, "_bcm_td_cosq_port_info");
   4354     }
   4355     sal_memset(_bcm_td_cosq_port_info[unit], 0, alloc_size);
   4356 
   4357     /* Create profile for PORT_COS_MAP table */
   4358     if (_bcm_td_cos_map_profile[unit] == NULL) {
   4359         _bcm_td_cos_map_profile[unit] = sal_alloc(sizeof(soc_profile_mem_t),
   4360                                                   "COS_MAP Profile Mem");
   4361         if (_bcm_td_cos_map_profile[unit] == NULL) {
   4362             return BCM_E_MEMORY;
   4363         }
   4364         soc_profile_mem_t_init(_bcm_td_cos_map_profile[unit]);
   4365     }
   4366     mem = PORT_COS_MAPm;
   4367     entry_words[0] = sizeof(port_cos_map_entry_t) / sizeof(uint32);
   4368     BCM_IF_ERROR_RETURN(soc_profile_mem_create(unit, &mem, entry_words, 1,
   4369                                                _bcm_td_cos_map_profile[unit]));
   4370 
   4371     /* Create profile for VOQ_COS_MAP table */
   4372     if (_bcm_td_voq_cos_map_profile[unit] == NULL) {
   4373         _bcm_td_voq_cos_map_profile[unit] =
   4374             sal_alloc(sizeof(soc_profile_mem_t), "VOQ_COS_MAP Profile Mem");
   4375         if (_bcm_td_voq_cos_map_profile[unit] == NULL) {
   4376             return BCM_E_MEMORY;
   4377         }
   4378         soc_profile_mem_t_init(_bcm_td_voq_cos_map_profile[unit]);
   4379     }
   4380     mem = VOQ_COS_MAPm;
   4381     entry_words[0] = sizeof(voq_cos_map_entry_t) / sizeof(uint32);
   4382     BCM_IF_ERROR_RETURN
   4383         (soc_profile_mem_create(unit, &mem, entry_words, 1,
   4384                                 _bcm_td_voq_cos_map_profile[unit]));
   4385 
   4386     /* Create profile for MMU_WRED_DROP_CURVE_PROFILE_x tables */
   4387     if (_bcm_td_wred_profile[unit] == NULL) {
   4388         _bcm_td_wred_profile[unit] = sal_alloc(sizeof(soc_profile_mem_t),
   4389                                                "WRED Profile Mem");
   4390         if (_bcm_td_wred_profile[unit] == NULL) {
   4391             return BCM_E_MEMORY;
   4392         }
   4393         soc_profile_mem_t_init(_bcm_td_wred_profile[unit]);
   4394     }
   4395     entry_words[0] =
   4396         sizeof(mmu_wred_drop_curve_profile_0_entry_t) / sizeof(uint32);
   4397     entry_words[1] =
   4398         sizeof(mmu_wred_drop_curve_profile_1_entry_t) / sizeof(uint32);
   4399     entry_words[2] =
   4400         sizeof(mmu_wred_drop_curve_profile_2_entry_t) / sizeof(uint32);
   4401     entry_words[3] =
   4402         sizeof(mmu_wred_drop_curve_profile_3_entry_t) / sizeof(uint32);
   4403     entry_words[4] =
   4404         sizeof(mmu_wred_drop_curve_profile_4_entry_t) / sizeof(uint32);
   4405     entry_words[5] =
   4406         sizeof(mmu_wred_drop_curve_profile_5_entry_t) / sizeof(uint32);
   4407     BCM_IF_ERROR_RETURN
   4408         (soc_profile_mem_create(unit, wred_mems, entry_words, 6,
   4409                                 _bcm_td_wred_profile[unit]));
   4410 
   4411     /* Create profile for MMU_QCN_SITB table */
   4412     if (_bcm_td_sample_int_profile[unit] == NULL) {
   4413         _bcm_td_sample_int_profile[unit] =
   4414             sal_alloc(sizeof(soc_profile_mem_t), "QCN sample Int Profile Mem");
   4415         if (_bcm_td_sample_int_profile[unit] == NULL) {
   4416             return BCM_E_MEMORY;
   4417         }
   4418         soc_profile_mem_t_init(_bcm_td_sample_int_profile[unit]);
   4419     }
   4420     mem = MMU_QCN_SITBm;
   4421     entry_words[0] = sizeof(mmu_qcn_sitb_entry_t) / sizeof(uint32);
   4422     BCM_IF_ERROR_RETURN
   4423         (soc_profile_mem_create(unit, &mem, entry_words, 1,
   4424                                 _bcm_td_sample_int_profile[unit]));
   4425 
   4426     /* Create profile for MMU_QCN_CPQ_SEQ register */
   4427     if (_bcm_td_feedback_profile[unit] == NULL) {
   4428         _bcm_td_feedback_profile[unit] =
   4429             sal_alloc(sizeof(soc_profile_reg_t), "QCN Feedback Profile Reg");
   4430         if (_bcm_td_feedback_profile[unit] == NULL) {
   4431             return BCM_E_MEMORY;
   4432         }
   4433         soc_profile_reg_t_init(_bcm_td_feedback_profile[unit]);
   4434     }
   4435     reg = MMU_QCN_CPQ_SEQr;
   4436     BCM_IF_ERROR_RETURN
   4437         (soc_profile_reg_create(unit, &reg, 1,
   4438                                 _bcm_td_feedback_profile[unit]));
   4439 
   4440     /* Create profile for PRIO2COS_LLFC register */
   4441     if (_bcm_td_llfc_profile[unit] == NULL) {
   4442         _bcm_td_llfc_profile[unit] =
   4443             sal_alloc(sizeof(soc_profile_reg_t), "PRIO2COS_LLFC Profile Reg");
   4444         if (_bcm_td_llfc_profile[unit] == NULL) {
   4445             return BCM_E_MEMORY;
   4446         }
   4447         soc_profile_reg_t_init(_bcm_td_llfc_profile[unit]);
   4448     }
   4449     reg = PRIO2COS_LLFCr;
   4450     BCM_IF_ERROR_RETURN
   4451         (soc_profile_reg_create(unit, &reg, 1, _bcm_td_llfc_profile[unit]));
   4452 
   4453     /* Create profile for PRIO2EXTQ_LLFC register */
   4454     if (_bcm_td_ext_llfc_profile[unit] == NULL) {
   4455         _bcm_td_ext_llfc_profile[unit] =
   4456             sal_alloc(sizeof(soc_profile_reg_t), "PRIO2EXTQ_LLFC Profile Reg");
   4457         if (_bcm_td_ext_llfc_profile[unit] == NULL) {
   4458             return BCM_E_MEMORY;
   4459         }
   4460         soc_profile_reg_t_init(_bcm_td_ext_llfc_profile[unit]);
   4461     }
   4462     reg = PRIO2EXTQ_LLFCr;
   4463     BCM_IF_ERROR_RETURN
   4464         (soc_profile_reg_create(unit, &reg, 1,
   4465                                 _bcm_td_ext_llfc_profile[unit]));
   4466 
   4467     for (i = 0; i < si->num_cpu_cosq; i++) {
   4468         if (_bcm_td_cosq_cpu_cosq_config[unit][i] == NULL) {
   4469             _bcm_td_cosq_cpu_cosq_config[unit][i] =
   4470                 sal_alloc(sizeof(_bcm_td_cosq_cpu_cosq_config_t), "CPU Cosq Config");
   4471 
   4472             if (_bcm_td_cosq_cpu_cosq_config[unit][i] == NULL) {
   4473                 return BCM_E_MEMORY;
   4474             }
   4475             sal_memset(_bcm_td_cosq_cpu_cosq_config[unit][i], 0,
   4476                        sizeof(_bcm_td_cosq_cpu_cosq_config_t));
   4477             _bcm_td_cosq_cpu_cosq_config[unit][i]->enable = 1;
   4478         }
   4479     }
   4480 
   4481 #ifdef BCM_WARM_BOOT_SUPPORT
   4482     if (SOC_WARM_BOOT(unit)) {
   4483         return bcm_td_cosq_reinit(unit);
   4484     } else {
   4485         BCM_IF_ERROR_RETURN(_bcm_td_cosq_wb_alloc(unit));
   4486     }
   4487 #endif /* BCM_WARM_BOOT_SUPPORT */
   4488 
   4489     /* Add default entries for PORT_COS_MAP memory profile */
   4490     BCM_IF_ERROR_RETURN(_bcm_td_cosq_config_set(unit, numq));
   4491 
   4492     /* Add default entries for VOQ_COS_MAP memory profile */
   4493     PBMP_PORT_ITER(unit, port) {
   4494         if (!_BCM_TD_IS_PORT_DMVOQ_CAPABLE(unit, port)) {
   4495             continue;
   4496         }
   4497         BCM_IF_ERROR_RETURN(_bcm_td_cosq_voq_init(unit, port));
   4498     }
   4499 
   4500     /* Add default entries for MMU_WRED_DROP_CURVE_PROFILE_x memory profile */
   4501     sal_memset(&entry_tcp_green, 0, sizeof(entry_tcp_green));
   4502     sal_memset(&entry_tcp_yellow, 0, sizeof(entry_tcp_yellow));
   4503     sal_memset(&entry_tcp_red, 0, sizeof(entry_tcp_red));
   4504     sal_memset(&entry_nontcp_green, 0, sizeof(entry_nontcp_green));
   4505     sal_memset(&entry_nontcp_yellow, 0, sizeof(entry_nontcp_yellow));
   4506     sal_memset(&entry_nontcp_red, 0, sizeof(entry_nontcp_red));
   4507     entries[0] = &entry_tcp_green;
   4508     entries[1] = &entry_tcp_yellow;
   4509     entries[2] = &entry_tcp_red;
   4510     entries[3] = &entry_nontcp_green;
   4511     entries[4] = &entry_nontcp_yellow;
   4512     entries[5] = &entry_nontcp_red;
   4513     for (i = 0; i < 6; i++) {
   4514         soc_mem_field32_set(unit, wred_mems[i], entries[i],
   4515                             MIN_THDf, 0xffff);
   4516         soc_mem_field32_set(unit, wred_mems[i], entries[i],
   4517                             MAX_THDf, 0xffff);
   4518     }
   4519     profile_index = 0xffffffff;
   4520     PBMP_PORT_ITER(unit, port) {
   4521         BCM_IF_ERROR_RETURN
   4522             (_bcm_td_cosq_index_resolve(unit, port, -1,
   4523                                         _BCM_TD_COSQ_INDEX_STYLE_WRED, NULL,
   4524                                         NULL, &numq));
   4525         for (cosq = 0; cosq < numq; cosq++) {
   4526             if (profile_index == 0xffffffff) {
   4527                 BCM_IF_ERROR_RETURN
   4528                     (soc_profile_mem_add(unit, _bcm_td_wred_profile[unit],
   4529                                          entries, 1, &profile_index));
   4530             } else {
   4531                 BCM_IF_ERROR_RETURN
   4532                     (soc_profile_mem_reference(unit,
   4533                                                _bcm_td_wred_profile[unit],
   4534                                                profile_index, 0));
   4535             }
   4536         }
   4537     }
   4538 
   4539     /* Add default entries for PRIO2COS_LLFC register profile */
   4540     sal_memset(rval64, 0, sizeof(rval64));
   4541     rval64s[0] = rval64;
   4542     profile_index = 0xffffffff;
   4543     PBMP_PORT_ITER(unit, port) {
   4544         if (profile_index == 0xffffffff) {
   4545             BCM_IF_ERROR_RETURN
   4546                 (soc_profile_reg_add(unit, _bcm_td_llfc_profile[unit],
   4547                                      rval64s, 16, &profile_index));
   4548         } else {
   4549             BCM_IF_ERROR_RETURN
   4550                 (soc_profile_reg_reference(unit, _bcm_td_llfc_profile[unit],
   4551                                            profile_index, 0));
   4552         }
   4553     }
   4554 
   4555     /* Add default entries for PRIO2EXTQ_LLFC register profile */
   4556     profile_index = 0xffffffff;
   4557     PBMP_PORT_ITER(unit, port) {
   4558         if (profile_index == 0xffffffff) {
   4559             BCM_IF_ERROR_RETURN
   4560                 (soc_profile_reg_add(unit, _bcm_td_ext_llfc_profile[unit],
   4561                                      rval64s, 16, &profile_index));
   4562         } else {
   4563             BCM_IF_ERROR_RETURN
   4564                 (soc_profile_reg_reference(unit,
   4565                                            _bcm_td_ext_llfc_profile[unit],
   4566                                            profile_index, 0));
   4567         }
   4568     }
   4569 
   4570     /*
   4571      * Always strict priority for SC and QM COS queues
   4572      * S1 COS4 is for multicast SC and QM queue
   4573      * S1 COS5 is for unicast SC queue
   4574      * S1 COS6 is for unicast QM queue
   4575      */
   4576     PBMP_ALL_ITER(unit, port) {
   4577         if (IS_CPU_PORT(unit, port)) {
   4578             continue;
   4579         }
   4580         BCM_IF_ERROR_RETURN(READ_MINSPCONFIGr(unit, port, &rval));
   4581         soc_reg_field_set(unit, MINSPCONFIGr, &rval, COS4_IS_SPf, 1);
   4582         soc_reg_field_set(unit, MINSPCONFIGr, &rval, COS5_IS_SPf, 1);
   4583         soc_reg_field_set(unit, MINSPCONFIGr, &rval, COS6_IS_SPf, 1);
   4584         BCM_IF_ERROR_RETURN(WRITE_MINSPCONFIGr(unit, port, rval));
   4585     }
   4586 
   4587     return BCM_E_NONE;
   4588 }
   4589 
   4590 /*
   4591  * Function:
   4592  *     bcm_td_cosq_detach
   4593  * Purpose:
   4594  *     Discard all COS schedule/mapping state.
   4595  * Parameters:
   4596  *     unit - unit number
   4597  * Returns:
   4598  *     BCM_E_XXX
   4599  */
   4600 int
   4601 bcm_td_cosq_detach(int unit, int software_state_only)
   4602 {
   4603     int i;
   4604     soc_info_t *si;
   4605 
   4606     si = &SOC_INFO(unit);
   4607     /* Cleanup ETS port information structures */
   4608     if (_bcm_td_cosq_port_info[unit] != NULL) {
   4609         sal_free(_bcm_td_cosq_port_info[unit]);
   4610         _bcm_td_cosq_port_info[unit] = NULL;
   4611     }
   4612 
   4613     /* Cleanup profile for PORT_COS_MAP table */
   4614     if (_bcm_td_cos_map_profile[unit] != NULL) {
   4615         SOC_IF_ERROR_RETURN(soc_profile_mem_destroy(unit,
   4616                                 _bcm_td_cos_map_profile[unit]));
   4617         sal_free(_bcm_td_cos_map_profile[unit]);
   4618         _bcm_td_cos_map_profile[unit] = NULL;
   4619     }
   4620 
   4621     /* Cleanup profile for VOQ_COS_MAP table */
   4622     if (_bcm_td_voq_cos_map_profile[unit] != NULL) {
   4623         SOC_IF_ERROR_RETURN(soc_profile_mem_destroy(unit,
   4624                                 _bcm_td_voq_cos_map_profile[unit]));
   4625         sal_free(_bcm_td_voq_cos_map_profile[unit]);
   4626         _bcm_td_voq_cos_map_profile[unit] = NULL;
   4627     }
   4628 
   4629     /* Cleanup profile for MMU_WRED_DROP_CURVE_PROFILE_x tables */
   4630     if (_bcm_td_wred_profile[unit] != NULL) {
   4631         SOC_IF_ERROR_RETURN(soc_profile_mem_destroy(unit,
   4632                                 _bcm_td_wred_profile[unit]));
   4633         sal_free(_bcm_td_wred_profile[unit]);
   4634         _bcm_td_wred_profile[unit] = NULL;
   4635     }
   4636 
   4637     /* Cleanup profile for MMU_QCN_SITB table */
   4638     if (_bcm_td_sample_int_profile[unit] != NULL) {
   4639         SOC_IF_ERROR_RETURN(soc_profile_mem_destroy(unit,
   4640                                 _bcm_td_sample_int_profile[unit]));
   4641         sal_free(_bcm_td_sample_int_profile[unit]);
   4642         _bcm_td_sample_int_profile[unit] = NULL;
   4643     }
   4644 
   4645     /* Cleanup profile for MMU_QCN_CPQ_SEQ register */
   4646     if (_bcm_td_feedback_profile[unit] != NULL) {
   4647         SOC_IF_ERROR_RETURN(soc_profile_reg_destroy(unit,
   4648                                 _bcm_td_feedback_profile[unit]));
   4649         sal_free(_bcm_td_feedback_profile[unit]);
   4650         _bcm_td_feedback_profile[unit] = NULL;
   4651     }
   4652 
   4653     /* Cleanup profile for PRIO2COS_LLFC register */
   4654     if (_bcm_td_llfc_profile[unit] != NULL) {
   4655         SOC_IF_ERROR_RETURN(soc_profile_reg_destroy(unit,
   4656                                 _bcm_td_llfc_profile[unit]));
   4657         sal_free(_bcm_td_llfc_profile[unit]);
   4658         _bcm_td_llfc_profile[unit] = NULL;
   4659     }
   4660 
   4661     /* Cleanup profile for PRIO2EXTQ_LLFC register */
   4662     if (_bcm_td_ext_llfc_profile[unit] != NULL) {
   4663         SOC_IF_ERROR_RETURN(soc_profile_reg_destroy(unit,
   4664                                 _bcm_td_ext_llfc_profile[unit]));
   4665         sal_free(_bcm_td_ext_llfc_profile[unit]);
   4666         _bcm_td_ext_llfc_profile[unit] = NULL;
   4667     }
   4668 
   4669     for (i = 0; i < si->num_cpu_cosq; i++) {
   4670         if (_bcm_td_cosq_cpu_cosq_config[unit][i] != NULL) {
   4671             sal_free(_bcm_td_cosq_cpu_cosq_config[unit][i]);
   4672             _bcm_td_cosq_cpu_cosq_config[unit][i] = NULL;
   4673         }
   4674     }
   4675 
   4676     if (cosq_sync_lock[unit]) {
   4677         sal_mutex_destroy(cosq_sync_lock[unit]);
   4678         cosq_sync_lock[unit] = NULL;
   4679     }
   4680 
   4681     return BCM_E_NONE;
   4682 }
   4683 
   4684 /*
   4685  * Function:
   4686  *     bcm_td_cosq_config_set
   4687  * Purpose:
   4688  *     Set the number of COS queues
   4689  * Parameters:
   4690  *     unit - unit number
   4691  *     numq - number of COS queues (1-8).
   4692  * Returns:
   4693  *     BCM_E_XXX
   4694  */
   4695 int
   4696 bcm_td_cosq_config_set(int unit, int numq)
   4697 {
   4698     soc_mem_t mem;
   4699     int entry_words;
   4700 
   4701     mem = PORT_COS_MAPm;
   4702     entry_words = sizeof(port_cos_map_entry_t) / sizeof(uint32);
   4703     BCM_IF_ERROR_RETURN(soc_profile_mem_create(unit, &mem, &entry_words, 1,
   4704                                                _bcm_td_cos_map_profile[unit]));
   4705 
   4706     return _bcm_td_cosq_config_set(unit, numq);
   4707 }
   4708 
   4709 /*
   4710  * Function:
   4711  *     bcm_td_cosq_config_get
   4712  * Purpose:
   4713  *     Get the number of cos queues
   4714  * Parameters:
   4715  *     unit - unit number
   4716  *     numq - (Output) number of cosq
   4717  * Returns:
   4718  *     BCM_E_XXX
   4719  */
   4720 int
   4721 bcm_td_cosq_config_get(int unit, int *numq)
   4722 {
   4723     if (_bcm_td_num_cosq[unit] == 0) {
   4724         return BCM_E_INIT;
   4725     }
   4726 
   4727     if (numq != NULL) {
   4728         *numq = _bcm_td_num_cosq[unit];
   4729     }
   4730 
   4731     return BCM_E_NONE;
   4732 }
   4733 
   4734 /*
   4735  * Function:
   4736  *     bcm_td_cosq_mapping_set
   4737  * Purpose:
   4738  *     Set which cosq a given priority should fall into
   4739  * Parameters:
   4740  *     unit     - (IN) unit number
   4741  *     gport    - (IN) queue group GPORT identifier
   4742  *     priority - (IN) priority value to map
   4743  *     cosq     - (IN) COS queue to map to
   4744  * Returns:
   4745  *     BCM_E_XXX
   4746  */
   4747 int
   4748 bcm_td_cosq_mapping_set(int unit, bcm_port_t port, bcm_cos_t priority,
   4749                         bcm_cos_queue_t cosq)
   4750 {
   4751     bcm_pbmp_t pbmp;
   4752     bcm_port_t local_port;
   4753     bcm_cos_queue_t  mc_cosq_max, mc_cosq;
   4754 
   4755     mc_cosq_max = (_BCM_TD_NUM_MCAST_QUEUE_GROUP - 1);
   4756 
   4757     BCM_PBMP_CLEAR(pbmp);
   4758     if (port == -1) {
   4759         BCM_PBMP_ASSIGN(pbmp, PBMP_ALL(unit));
   4760     } else {
   4761         if (BCM_GPORT_IS_SET(port)) {
   4762             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
   4763                 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) ||
   4764                 BCM_GPORT_IS_SCHEDULER(port)) {
   4765                 return BCM_E_PARAM;
   4766             } else if (BCM_GPORT_IS_LOCAL(port)) {
   4767                 local_port = BCM_GPORT_LOCAL_GET(port);
   4768             } else {
   4769                 return BCM_E_PARAM;
   4770             }
   4771         } else {
   4772             local_port = port;
   4773         }
   4774         if (!SOC_PORT_VALID(unit, local_port)) {
   4775             return BCM_E_PORT;
   4776         }
   4777         BCM_PBMP_PORT_ADD(pbmp, local_port);
   4778     }
   4779 	  	
   4780     if ((cosq < 0) || (cosq >= _TD_NUM_COS(unit))) {
   4781         return BCM_E_PARAM;
   4782     }
   4783     PBMP_ITER(pbmp, local_port) {
   4784     if (IS_LB_PORT(unit, local_port)) {
   4785         continue;
   4786     }
   4787     /* If no gport, map the int prio symmetrically for ucast and
   4788     * mcast 
   4789     * There are only 5 MC QUEUES [0,4] attached to a port
   4790     */
   4791     mc_cosq = (cosq > mc_cosq_max) ? mc_cosq_max : cosq;
   4792     BCM_IF_ERROR_RETURN(_bcm_td_cosq_mapping_set(unit, local_port,
   4793         priority,
   4794         BCM_COSQ_GPORT_UCAST_QUEUE_GROUP | BCM_COSQ_GPORT_MCAST_QUEUE_GROUP,
   4795         -1, (cosq << 16 | (mc_cosq & 0xffff))));
   4796     }
   4797     return BCM_E_NONE;
   4798 
   4799 }
   4800 
   4801 /*
   4802  * Function:
   4803  *     bcm_td_cosq_mapping_get
   4804  * Purpose:
   4805  *     Determine which COS queue a given priority currently maps to.
   4806  * Parameters:
   4807  *     unit     - (IN) unit number
   4808  *     gport    - (IN) queue group GPORT identifier
   4809  *     priority - (IN) priority value to map
   4810  *     cosq     - (OUT) COS queue to map to
   4811  * Returns:
   4812  *     BCM_E_XXX
   4813  */
   4814 int
   4815 bcm_td_cosq_mapping_get(int unit, bcm_port_t port, bcm_cos_t priority,
   4816                         bcm_cos_queue_t *cosq)
   4817 {
   4818     bcm_port_t local_port;
   4819     bcm_pbmp_t pbmp;
   4820 
   4821     BCM_PBMP_CLEAR(pbmp);
   4822 
   4823     if (port == -1) {
   4824         BCM_PBMP_ASSIGN(pbmp, PBMP_ALL(unit));
   4825     } else {
   4826         if (BCM_GPORT_IS_SET(port)) {
   4827             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
   4828                 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) ||
   4829                 BCM_GPORT_IS_SCHEDULER(port)) {
   4830                 return BCM_E_PARAM;
   4831             } else if (BCM_GPORT_IS_LOCAL(port)) {
   4832                 local_port = BCM_GPORT_LOCAL_GET(port);
   4833             } else {
   4834                 return BCM_E_PARAM;
   4835             }
   4836         } else {
   4837             local_port = port;
   4838         }
   4839         if (!SOC_PORT_VALID(unit, local_port)) {
   4840             return BCM_E_PORT;
   4841         }
   4842         BCM_PBMP_PORT_ADD(pbmp, local_port);
   4843     }
   4844 
   4845     PBMP_ITER(pbmp, local_port) {
   4846         if (IS_LB_PORT(unit, local_port)) {
   4847             continue;
   4848         }
   4849         BCM_IF_ERROR_RETURN(_bcm_td_cosq_mapping_get(unit, local_port, 
   4850                priority, BCM_COSQ_GPORT_UCAST_QUEUE_GROUP, NULL, cosq));
   4851         break;
   4852     }
   4853     return BCM_E_NONE;
   4854 }
   4855 
   4856 /*
   4857  * Function:
   4858  *     bcm_td_cosq_port_sched_set
   4859  * Purpose:
   4860  *     Set up class-of-service policy and corresponding weights and delay
   4861  * Parameters:
   4862  *     unit    - (IN) unit number
   4863  *     pbm     - (IN) port bitmap
   4864  *     mode    - (IN) Scheduling mode (BCM_COSQ_xxx)
   4865  *     weights - (IN) Weights for each COS queue
   4866  *     delay   - This parameter is not used
   4867  * Returns:
   4868  *     BCM_E_XXX
   4869  */
   4870 int
   4871 bcm_td_cosq_port_sched_set(int unit, bcm_pbmp_t pbm,
   4872                            int mode, const int *weights, int delay)
   4873 {
   4874     bcm_port_t port;
   4875     int num_weights;
   4876 
   4877     BCM_PBMP_ITER(pbm, port) {
   4878         /* coverity[overrun-local : FALSE] */
   4879         num_weights = _TD_NUM_COS(unit);
   4880         BCM_IF_ERROR_RETURN
   4881             (_bcm_td_cosq_sched_set(unit, port, 0, mode, num_weights,
   4882                                     (int *)weights));
   4883     }
   4884 
   4885     return BCM_E_NONE;
   4886 }
   4887 
   4888 /*
   4889  * Function:
   4890  *     bcm_td_cosq_port_sched_get
   4891  * Purpose:
   4892  *     Retrieve class-of-service policy and corresponding weights and delay
   4893  * Parameters:
   4894  *     unit     - (IN) unit number
   4895  *     pbm      - (IN) port bitmap
   4896  *     mode     - (OUT) Scheduling mode (BCM_COSQ_XXX)
   4897  *     weights  - (OUT) Weights for each COS queue
   4898  *     delay    - This parameter is not used
   4899  * Returns:
   4900  *     BCM_E_XXX
   4901  */
   4902 int
   4903 bcm_td_cosq_port_sched_get(int unit, bcm_pbmp_t pbm,
   4904                            int *mode, int *weights, int *delay)
   4905 {
   4906     bcm_port_t port;
   4907 
   4908     BCM_PBMP_ITER(pbm, port) {
   4909         /* coverity[overrun-local : FALSE] */
   4910         /* coverity[illegal_address : FALSE] */
   4911         if (IS_CPU_PORT(unit, port) && SOC_PBMP_NEQ(pbm, PBMP_CMIC(unit))) {
   4912             continue;
   4913         }
   4914         return _bcm_td_cosq_sched_get(unit, port, 0, mode, 8, weights);
   4915     }
   4916 
   4917     return BCM_E_PORT;
   4918 }
   4919 
   4920 /*
   4921  * Function:
   4922  *     bcm_td_cosq_sched_weight_max_get
   4923  * Purpose:
   4924  *     Retrieve maximum weights for given COS policy
   4925  * Parameters:
   4926  *     unit    - (IN) unit number
   4927  *     mode    - (IN) Scheduling mode (BCM_COSQ_xxx)
   4928  *     weight_max - (OUT) Maximum weight for COS queue.
   4929  * Returns:
   4930  *     BCM_E_XXX
   4931  */
   4932 int
   4933 bcm_td_cosq_sched_weight_max_get(int unit, int mode, int *weight_max)
   4934 {
   4935     switch (mode) {
   4936     case BCM_COSQ_STRICT:
   4937         *weight_max = BCM_COSQ_WEIGHT_STRICT;
   4938         break;
   4939     case BCM_COSQ_ROUND_ROBIN:
   4940         *weight_max = BCM_COSQ_WEIGHT_MIN;
   4941         break;
   4942     case BCM_COSQ_WEIGHTED_ROUND_ROBIN:
   4943     case BCM_COSQ_DEFICIT_ROUND_ROBIN:
   4944         *weight_max =
   4945             (1 << soc_reg_field_length(unit, COSWEIGHTSr, COSWEIGHTSf)) - 1;
   4946         break;
   4947     default:
   4948         return BCM_E_PARAM;
   4949     }
   4950 
   4951     return BCM_E_NONE;
   4952 }
   4953 
   4954 /*
   4955  * Function:
   4956  *     bcm_td_cosq_bandwidth_set
   4957  * Purpose:
   4958  *     Configure COS queue bandwidth control
   4959  * Parameters:
   4960  *     unit          - (IN) unit number
   4961  *     port          - (IN) port number or GPORT identifier
   4962  *     cosq          - (IN) COS queue number
   4963  *     min_quantum   - (IN)
   4964  *     max_quantum   - (IN)
   4965  *     burst_quantum - (IN)
   4966  *     flags         - (IN)
   4967  * Returns:
   4968  *     BCM_E_XXX
   4969  * Notes:
   4970  *     If port is any form of local port, cosq is the hardware queue index.
   4971  */
   4972 int
   4973 bcm_td_cosq_port_bandwidth_set(int unit, bcm_port_t port,
   4974                                bcm_cos_queue_t cosq,
   4975                                uint32 min_quantum, uint32 max_quantum,
   4976                                uint32 burst_quantum, uint32 flags)
   4977 {
   4978     if (cosq < 0) {
   4979         return BCM_E_PARAM;
   4980     }
   4981 
   4982     return _bcm_td_cosq_bucket_set(unit, port, cosq, min_quantum,
   4983                                    max_quantum, min_quantum, max_quantum,
   4984                                    flags);
   4985 }
   4986 
   4987 /*
   4988  * Function:
   4989  *     bcm_td_cosq_bandwidth_get
   4990  * Purpose:
   4991  *     Get COS queue bandwidth control configuration
   4992  * Parameters:
   4993  *     unit          - (IN) unit number
   4994  *     port          - (IN) port number or GPORT identifier
   4995  *     cosq          - (IN) COS queue number
   4996  *     min_quantum   - (OUT)
   4997  *     max_quantum   - (OUT)
   4998  *     burst_quantum - (OUT)
   4999  *     flags         - (OUT)
   5000  * Returns:
   5001  *     BCM_E_XXX
   5002  * Notes:
   5003  *     If port is any form of local port, cosq is the hardware queue index.
   5004  */
   5005 int
   5006 bcm_td_cosq_port_bandwidth_get(int unit, bcm_port_t port,
   5007                                bcm_cos_queue_t cosq,
   5008                                uint32 *min_quantum, uint32 *max_quantum,
   5009                                uint32 *burst_quantum, uint32 *flags)
   5010 {
   5011     uint32 tmp;
   5012 
   5013     if (cosq < 0) {
   5014         return BCM_E_PARAM;
   5015     }
   5016 
   5017     BCM_IF_ERROR_RETURN(_bcm_td_cosq_bucket_get(unit, port, cosq, min_quantum,
   5018                                                 max_quantum, &tmp, 
   5019                                                 burst_quantum, flags));
   5020 
   5021     return BCM_E_NONE;
   5022 }
   5023 
   5024 int
   5025 bcm_td_cosq_port_pps_set(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   5026                          int pps)
   5027 {
   5028     uint32 min, max, burst, flags;
   5029     
   5030     if (!IS_CPU_PORT(unit, port)) {
   5031         return BCM_E_PORT;
   5032     } else if (cosq < 0 || cosq >= NUM_CPU_COSQ(unit)) {
   5033         return BCM_E_PARAM;
   5034     }
   5035 
   5036     /* Get the current PPS and BURST settings */
   5037     BCM_IF_ERROR_RETURN
   5038         (_bcm_td_cosq_bucket_get(unit, port, cosq, &min, &max, &burst, &burst,
   5039                                  &flags));
   5040 
   5041     
   5042 
   5043     /* Replace the current PPS setting, keep BURST the same */
   5044     return _bcm_td_cosq_bucket_set(unit, port, cosq, min, pps, burst, burst,
   5045                                    flags | BCM_COSQ_BW_PACKET_MODE);
   5046 }
   5047 
   5048 int
   5049 bcm_td_cosq_port_pps_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   5050                          int *pps)
   5051 {
   5052     uint32 min, max, burst, flags;
   5053 
   5054     if (!IS_CPU_PORT(unit, port)) {
   5055         return BCM_E_PORT;
   5056     } else if (cosq < 0 || cosq >= NUM_CPU_COSQ(unit)) {
   5057         return BCM_E_PARAM;
   5058     }
   5059 
   5060     BCM_IF_ERROR_RETURN
   5061         (_bcm_td_cosq_bucket_get(unit, port, cosq, &min, &max, &burst, &burst,
   5062                                  &flags));
   5063     *pps = max;
   5064 
   5065     return BCM_E_NONE;
   5066 }
   5067 
   5068 int
   5069 bcm_td_cosq_port_burst_set(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   5070                            int burst)
   5071 {
   5072     uint32 min, max, cur_burst, flags;
   5073 
   5074     if (!IS_CPU_PORT(unit, port)) {
   5075         return BCM_E_PORT;
   5076     } else if (cosq < 0 || cosq >= NUM_CPU_COSQ(unit)) {
   5077         return BCM_E_PARAM;
   5078     }
   5079 
   5080     /* Get the current PPS and BURST settings */
   5081     BCM_IF_ERROR_RETURN
   5082         (_bcm_td_cosq_bucket_get(unit, port, cosq, &min, &max, &cur_burst,
   5083                                  &cur_burst, &flags));
   5084 
   5085     
   5086 
   5087     /* Replace the current BURST setting, keep PPS the same */
   5088     return _bcm_td_cosq_bucket_set(unit, port, cosq, min, max, burst, burst,
   5089                                    flags | BCM_COSQ_BW_PACKET_MODE);
   5090 }
   5091 
   5092 int
   5093 bcm_td_cosq_port_burst_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   5094                            int *burst)
   5095 {
   5096     uint32 min, max, cur_burst, flags, tmp;
   5097 
   5098     if (!IS_CPU_PORT(unit, port)) {
   5099         return BCM_E_PORT;
   5100     } else if (cosq < 0 || cosq >= NUM_CPU_COSQ(unit)) {
   5101         return BCM_E_PARAM;
   5102     }
   5103 
   5104     BCM_IF_ERROR_RETURN
   5105         (_bcm_td_cosq_bucket_get(unit, port, cosq, &min, &max, &tmp, 
   5106                                  &cur_burst, &flags));
   5107     *burst = cur_burst;
   5108 
   5109     return BCM_E_NONE;
   5110 }
   5111 
   5112 int
   5113 bcm_td_cosq_discard_set(int unit, uint32 flags)
   5114 {
   5115     bcm_port_t port;
   5116     bcm_cos_queue_t cosq;
   5117     int numq;
   5118 
   5119     if (flags & ~(BCM_COSQ_DISCARD_DEVICE |
   5120                   BCM_COSQ_DISCARD_NONTCP |
   5121                   BCM_COSQ_DISCARD_COLOR_ALL |
   5122                   BCM_COSQ_DISCARD_PORT |
   5123                   BCM_COSQ_DISCARD_TCP |
   5124                   BCM_COSQ_DISCARD_COLOR_GREEN |
   5125                   BCM_COSQ_DISCARD_COLOR_YELLOW |
   5126                   BCM_COSQ_DISCARD_COLOR_RED |
   5127                   BCM_COSQ_DISCARD_CAP_AVERAGE |
   5128                   BCM_COSQ_DISCARD_ENABLE |
   5129                   BCM_COSQ_DISCARD_MARK_CONGESTION)) {
   5130         return BCM_E_PARAM;
   5131     }
   5132 
   5133     flags &= ~(BCM_COSQ_DISCARD_NONTCP | BCM_COSQ_DISCARD_COLOR_ALL);
   5134 
   5135     PBMP_PORT_ITER(unit, port) {
   5136         BCM_IF_ERROR_RETURN
   5137             (_bcm_td_cosq_index_resolve(unit, port, -1,
   5138                                         _BCM_TD_COSQ_INDEX_STYLE_WRED, NULL,
   5139                                         NULL, &numq));
   5140         for (cosq = 0; cosq < numq; cosq++) {
   5141             BCM_IF_ERROR_RETURN
   5142                 (_bcm_td_cosq_wred_set(unit, port, cosq, flags, 0, 0, 0, 0,
   5143                                        FALSE));
   5144         }
   5145     }
   5146 
   5147     return BCM_E_NONE;
   5148 }
   5149 
   5150 int
   5151 bcm_td_cosq_discard_get(int unit, uint32 *flags)
   5152 {
   5153     bcm_port_t port;
   5154 
   5155     PBMP_PORT_ITER(unit, port) {
   5156         *flags = 0;
   5157         /* use setting from hardware cosq index 0 of the first port */
   5158         return _bcm_td_cosq_wred_get(unit, port, 0, flags, NULL, NULL, NULL,
   5159                                      NULL);
   5160     }
   5161 
   5162     return BCM_E_NOT_FOUND;
   5163 }
   5164 
   5165 /*
   5166  * Function:
   5167  *     bcm_td_cosq_discard_port_set
   5168  * Purpose:
   5169  *     Configure port WRED setting
   5170  * Parameters:
   5171  *     unit          - (IN) unit number
   5172  *     port          - (IN) port number or GPORT identifier
   5173  *     cosq          - (IN) COS queue number
   5174  *     color         - (IN)
   5175  *     drop_start    - (IN)
   5176  *     drop_slot     - (IN)
   5177  *     average_time  - (IN)
   5178  * Returns:
   5179  *     BCM_E_XXX
   5180  * Notes:
   5181  *     If port is any form of local port, cosq is the hardware queue index.
   5182  */
   5183 int
   5184 bcm_td_cosq_discard_port_set(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   5185                              uint32 color, int drop_start, int drop_slope,
   5186                              int average_time)
   5187 {
   5188     bcm_port_t local_port;
   5189     bcm_pbmp_t pbmp;
   5190     int gain;
   5191     uint32 min_thresh, max_thresh, shared_limit;
   5192     uint32 rval, bits;
   5193     int numq, i;
   5194 
   5195     if (drop_start < 0 || drop_start > 100 ||
   5196         drop_slope < 0 || drop_slope > 90) {
   5197         return BCM_E_PARAM;
   5198     }
   5199 
   5200     /*
   5201      * average queue size is reculated every 4us, the formula is
   5202      * avg_qsize(t + 1) =
   5203      *     avg_qsize(t) + (cur_qsize - avg_qsize(t)) / (2 ** gain)
   5204      * gain = log2(average_time / 4)
   5205      */
   5206     bits = (average_time / 4) & 0xffff;
   5207     if (bits != 0) {
   5208         bits |= bits >> 1;
   5209         bits |= bits >> 2;
   5210         bits |= bits >> 4;
   5211         bits |= bits >> 8;
   5212         gain = _shr_popcount(bits) - 1;
   5213     } else {
   5214         gain = 0;
   5215     }
   5216 
   5217     /*
   5218      * per-port cell limit may be disabled.
   5219      * per-port per-cos cell limit may be set to use dynamic method.
   5220      * therefore drop_start percentage is based on per-device total shared
   5221      * cells.
   5222      */
   5223     BCM_IF_ERROR_RETURN(READ_OP_BUFFER_SHARED_LIMIT_CELLr(unit, &rval));
   5224     shared_limit = soc_reg_field_get(unit, OP_BUFFER_SHARED_LIMIT_CELLr,
   5225                                      rval, OP_BUFFER_SHARED_LIMIT_CELLf);
   5226     min_thresh = drop_start * shared_limit / 100;
   5227 
   5228     /* Calculate the max threshold. For a given slope (angle in
   5229      * degrees), determine how many packets are in the range from
   5230      * 0% drop probability to 100% drop probability. Add that
   5231      * number to the min_treshold to the the max_threshold.
   5232      */
   5233     max_thresh = min_thresh + _bcm_td_angle_to_cells(drop_slope);
   5234     if (max_thresh > TD_CELL_FIELD_MAX) {
   5235         max_thresh = TD_CELL_FIELD_MAX;
   5236     }
   5237 
   5238     if (BCM_GPORT_IS_SET(port)) {
   5239         if (cosq == -1) {
   5240             BCM_IF_ERROR_RETURN
   5241                 (_bcm_td_cosq_index_resolve(unit, port, cosq,
   5242                                             _BCM_TD_COSQ_INDEX_STYLE_WRED,
   5243                                             NULL, NULL, &numq));
   5244             cosq = 0;
   5245         } else {
   5246             numq = 1;
   5247         }
   5248         for (i = 0; i < numq; i++) {
   5249             BCM_IF_ERROR_RETURN
   5250                 (_bcm_td_cosq_wred_set(unit, port, cosq + i, color,
   5251                                        min_thresh, max_thresh, 100, gain,
   5252                                        TRUE));
   5253         }
   5254     } else {
   5255         if (port == -1) {
   5256             BCM_PBMP_ASSIGN(pbmp, PBMP_PORT_ALL(unit));
   5257         } else if (!SOC_PORT_VALID(unit, port)) {
   5258             return BCM_E_PORT;
   5259         } else {
   5260             BCM_PBMP_PORT_SET(pbmp, port);
   5261         }
   5262 
   5263         BCM_PBMP_ITER(pbmp, local_port) {
   5264             if (cosq == -1) {
   5265                 BCM_IF_ERROR_RETURN
   5266                     (_bcm_td_cosq_index_resolve(unit, local_port, cosq,
   5267                                                 _BCM_TD_COSQ_INDEX_STYLE_WRED,
   5268                                                 NULL, NULL, &numq));
   5269                 cosq = 0;
   5270             } else {
   5271                 numq = 1;
   5272             }
   5273             for (i = 0; i < numq; i++) {
   5274                 BCM_IF_ERROR_RETURN
   5275                     (_bcm_td_cosq_wred_set(unit, local_port, cosq + i,
   5276                                            color, min_thresh, max_thresh, 100,
   5277                                            gain, TRUE));
   5278             }
   5279         }
   5280     }
   5281 
   5282     return BCM_E_NONE;
   5283 }
   5284 
   5285 /*
   5286  * Function:
   5287  *     bcm_td_cosq_discard_port_get
   5288  * Purpose:
   5289  *     Get port WRED setting
   5290  * Parameters:
   5291  *     unit          - (IN) unit number
   5292  *     port          - (IN) port number or GPORT identifier
   5293  *     cosq          - (IN) COS queue number
   5294  *     color         - (OUT)
   5295  *     drop_start    - (OUT)
   5296  *     drop_slot     - (OUT)
   5297  *     average_time  - (OUT)
   5298  * Returns:
   5299  *     BCM_E_XXX
   5300  * Notes:
   5301  *     If port is any form of local port, cosq is the hardware queue index.
   5302  */
   5303 int
   5304 bcm_td_cosq_discard_port_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   5305                              uint32 color, int *drop_start, int *drop_slope,
   5306                              int *average_time)
   5307 {
   5308     bcm_port_t local_port;
   5309     bcm_pbmp_t pbmp;
   5310     int gain, drop_prob;
   5311     uint32 min_thresh, max_thresh, shared_limit;
   5312     uint32 rval;
   5313 
   5314     if (drop_start == NULL || drop_slope == NULL || average_time == NULL) {
   5315         return BCM_E_PARAM;
   5316     }
   5317 
   5318     if (BCM_GPORT_IS_SET(port)) {
   5319         local_port = port;
   5320     } else {
   5321         if (port == -1) {
   5322             BCM_PBMP_ASSIGN(pbmp, PBMP_PORT_ALL(unit));
   5323         } else if (!SOC_PORT_VALID(unit, port)) {
   5324             return BCM_E_PORT;
   5325         } else {
   5326             BCM_PBMP_PORT_SET(pbmp, port);
   5327         }
   5328         BCM_PBMP_ITER(pbmp, local_port) {
   5329             break;
   5330         }
   5331     }
   5332 
   5333     BCM_IF_ERROR_RETURN
   5334         (_bcm_td_cosq_wred_get(unit, local_port, cosq == -1 ? 0 : cosq,
   5335                                &color, &min_thresh, &max_thresh, &drop_prob,
   5336                                &gain));
   5337 
   5338     /*
   5339      * average queue size is reculated every 4us, the formula is
   5340      * avg_qsize(t + 1) =
   5341      *     avg_qsize(t) + (cur_qsize - avg_qsize(t)) / (2 ** gain)
   5342      */
   5343     *average_time = (1 << gain) * 4;
   5344 
   5345     /*
   5346      * per-port cell limit may be disabled.
   5347      * per-port per-cos cell limit may be set to use dynamic method.
   5348      * therefore drop_start percentage is based on per-device total shared
   5349      * cells.
   5350      */
   5351     BCM_IF_ERROR_RETURN(READ_OP_BUFFER_SHARED_LIMIT_CELLr(unit, &rval));
   5352     shared_limit = soc_reg_field_get(unit, OP_BUFFER_SHARED_LIMIT_CELLr,
   5353                                      rval, OP_BUFFER_SHARED_LIMIT_CELLf);
   5354     if (min_thresh > shared_limit) {
   5355         min_thresh = shared_limit;
   5356     }
   5357 
   5358     if (max_thresh > shared_limit) {
   5359         max_thresh = shared_limit;
   5360     }
   5361 
   5362     *drop_start = min_thresh * 100 / shared_limit;
   5363 
   5364     /* Calculate the slope using the min and max threshold.
   5365      * The angle is calculated knowing drop probability at min
   5366      * threshold is 0% and drop probability at max threshold is 100%.
   5367      */
   5368     *drop_slope = _bcm_td_cells_to_angle(max_thresh - min_thresh);
   5369 
   5370     return BCM_E_NONE;
   5371 }
   5372 
   5373 int
   5374 bcm_td_cosq_stat_set(int unit, bcm_gport_t port, bcm_cos_queue_t cosq,
   5375                      bcm_cosq_stat_t stat, uint64 value)
   5376 {
   5377     soc_info_t *si;
   5378     _bcm_td_cosq_node_t *node;
   5379     bcm_port_t local_port;
   5380     int startq, numq, i;
   5381 
   5382     si = &SOC_INFO(unit);
   5383 
   5384     switch (stat) {
   5385     case bcmCosqStatDroppedPackets:
   5386         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) {
   5387             BCM_IF_ERROR_RETURN
   5388                 (_bcm_td_cosq_index_resolve
   5389                  (unit, port, cosq, _BCM_TD_COSQ_INDEX_STYLE_UCAST_DROP,
   5390                   &local_port, &startq, NULL));
   5391             BCM_IF_ERROR_RETURN
   5392                 (soc_counter_set(unit, local_port,
   5393                                  SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_UC, startq,
   5394                                  value));
   5395         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
   5396             BCM_IF_ERROR_RETURN
   5397                 (_bcm_td_cosq_index_resolve
   5398                  (unit, port, cosq, _BCM_TD_COSQ_INDEX_STYLE_MCAST_QUEUE,
   5399                   &local_port, &startq, NULL));
   5400             BCM_IF_ERROR_RETURN
   5401                 (soc_counter_set(unit, local_port,
   5402                                  SOC_COUNTER_NON_DMA_COSQ_DROP_PKT, startq,
   5403                                  value));
   5404         } else {
   5405             BCM_IF_ERROR_RETURN
   5406                 (_bcm_td_cosq_index_resolve
   5407                  (unit, port, cosq, _BCM_TD_COSQ_INDEX_STYLE_MCAST_QUEUE,
   5408                   &local_port, &startq, &numq));
   5409             if (!IS_CPU_PORT(unit, local_port) && cosq != BCM_COS_INVALID) {
   5410                 return BCM_E_PARAM;
   5411             }
   5412             if (cosq == BCM_COS_INVALID) {
   5413                 numq = 1;
   5414             }
   5415             for (i = 0; i < numq; i++) {
   5416                 BCM_IF_ERROR_RETURN
   5417                     (soc_counter_set(unit, local_port,
   5418                                      SOC_COUNTER_NON_DMA_COSQ_DROP_PKT,
   5419                                      startq + i, value));
   5420             }
   5421             if (si->port_num_uc_cosq[local_port] > 0) {
   5422                 BCM_IF_ERROR_RETURN
   5423                     (_bcm_td_cosq_index_resolve
   5424                      (unit, port, cosq, _BCM_TD_COSQ_INDEX_STYLE_UCAST_DROP,
   5425                       &local_port, &startq, &numq));
   5426                 if (cosq == BCM_COS_INVALID) {
   5427                     numq = 1;
   5428                 }
   5429                 for (i = 0; i < numq; i++) {
   5430                     BCM_IF_ERROR_RETURN
   5431                         (soc_counter_set(unit, local_port,
   5432                                          SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_UC,
   5433                                          startq + i, value));
   5434                 }
   5435             }
   5436         }
   5437         break;
   5438     case bcmCosqStatDroppedBytes:
   5439         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) {
   5440             BCM_IF_ERROR_RETURN
   5441                 (_bcm_td_cosq_index_resolve
   5442                  (unit, port, cosq, _BCM_TD_COSQ_INDEX_STYLE_UCAST_DROP,
   5443                   &local_port, &startq, NULL));
   5444             BCM_IF_ERROR_RETURN
   5445                 (soc_counter_set(unit, local_port,
   5446                                  SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE_UC, startq,
   5447                                  value));
   5448         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
   5449             BCM_IF_ERROR_RETURN
   5450                 (_bcm_td_cosq_index_resolve
   5451                  (unit, port, cosq, _BCM_TD_COSQ_INDEX_STYLE_MCAST_QUEUE,
   5452                   &local_port, &startq, NULL));
   5453             BCM_IF_ERROR_RETURN
   5454                 (soc_counter_set(unit, local_port,
   5455                                  SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE, startq,
   5456                                  value));
   5457         } else {
   5458             BCM_IF_ERROR_RETURN
   5459                 (_bcm_td_cosq_index_resolve
   5460                  (unit, port, cosq, _BCM_TD_COSQ_INDEX_STYLE_MCAST_QUEUE,
   5461                   &local_port, &startq, &numq));
   5462             if (!IS_CPU_PORT(unit, local_port) && cosq != BCM_COS_INVALID) {
   5463                 return BCM_E_PARAM;
   5464             }
   5465             if (cosq == BCM_COS_INVALID) {
   5466                 numq = 1;
   5467             }
   5468             for (i = 0; i < numq; i++) {
   5469                 BCM_IF_ERROR_RETURN
   5470                     (soc_counter_set(unit, local_port,
   5471                                      SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE,
   5472                                      startq + i, value));
   5473             }
   5474             if (si->port_num_uc_cosq[local_port] > 0) {
   5475                 BCM_IF_ERROR_RETURN
   5476                     (_bcm_td_cosq_index_resolve
   5477                      (unit, port, cosq, _BCM_TD_COSQ_INDEX_STYLE_UCAST_DROP,
   5478                       &local_port, &startq, &numq));
   5479                 if (cosq == BCM_COS_INVALID) {
   5480                     numq = 1;
   5481                 }
   5482                 for (i = 0; i < numq; i++) {
   5483                     BCM_IF_ERROR_RETURN
   5484                         (soc_counter_set(unit, local_port,
   5485                                          SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE_UC,
   5486                                          startq + i, value));
   5487                 }
   5488             }
   5489         }
   5490         break;
   5491     case bcmCosqStatYellowCongestionDroppedPackets:
   5492         if (cosq != BCM_COS_INVALID) {
   5493             return BCM_E_UNAVAIL;
   5494         }
   5495         BCM_IF_ERROR_RETURN
   5496             (_bcm_td_cosq_localport_resolve(unit, port, &local_port));
   5497         BCM_IF_ERROR_RETURN
   5498             (soc_counter_set(unit, local_port,
   5499                              SOC_COUNTER_NON_DMA_PORT_DROP_PKT_YELLOW, 0,
   5500                              value));
   5501         break;
   5502     case bcmCosqStatRedCongestionDroppedPackets:
   5503         if (cosq != BCM_COS_INVALID) {
   5504             return BCM_E_UNAVAIL;
   5505         }
   5506         BCM_IF_ERROR_RETURN
   5507             (_bcm_td_cosq_localport_resolve(unit, port, &local_port));
   5508         BCM_IF_ERROR_RETURN
   5509             (soc_counter_set(unit, local_port,
   5510                              SOC_COUNTER_NON_DMA_PORT_DROP_PKT_RED, 0,
   5511                              value));
   5512         break;
   5513     case bcmCosqStatGreenDiscardDroppedPackets:
   5514         if (cosq != BCM_COS_INVALID) {
   5515             return BCM_E_UNAVAIL;
   5516         }
   5517         BCM_IF_ERROR_RETURN
   5518             (_bcm_td_cosq_localport_resolve(unit, port, &local_port));
   5519         BCM_IF_ERROR_RETURN
   5520             (soc_counter_set(unit, local_port,
   5521                              SOC_COUNTER_NON_DMA_PORT_WRED_PKT_GREEN, 0,
   5522                              value));
   5523         break;
   5524     case bcmCosqStatYellowDiscardDroppedPackets:
   5525         if (cosq != BCM_COS_INVALID) {
   5526             return BCM_E_UNAVAIL;
   5527         }
   5528         BCM_IF_ERROR_RETURN
   5529             (_bcm_td_cosq_localport_resolve(unit, port, &local_port));
   5530         BCM_IF_ERROR_RETURN
   5531             (soc_counter_set(unit, local_port,
   5532                              SOC_COUNTER_NON_DMA_PORT_WRED_PKT_YELLOW, 0,
   5533                              value));
   5534         break;
   5535     case bcmCosqStatRedDiscardDroppedPackets:
   5536         if (cosq != BCM_COS_INVALID) {
   5537             return BCM_E_UNAVAIL;
   5538         }
   5539         BCM_IF_ERROR_RETURN
   5540             (_bcm_td_cosq_localport_resolve(unit, port, &local_port));
   5541         BCM_IF_ERROR_RETURN
   5542             (soc_counter_set(unit, local_port,
   5543                              SOC_COUNTER_NON_DMA_PORT_WRED_PKT_RED, 0, value));
   5544         break;
   5545     case bcmCosqStatOutPackets:
   5546         if (BCM_GPORT_IS_SCHEDULER(port)) {
   5547             BCM_IF_ERROR_RETURN
   5548                 (_bcm_td_cosq_node_get(unit, port, NULL,
   5549                                         &local_port, NULL, &node));
   5550             BCM_IF_ERROR_RETURN
   5551                 (_bcm_td_cosq_child_node_at_input(node, cosq, &node));
   5552             port = node->gport;
   5553             if (BCM_GPORT_IS_SCHEDULER(port)) {
   5554                /* Not support more than one-layer scheduler node analysis*/
   5555                return BCM_E_PARAM;
   5556             }
   5557         }
   5558 
   5559         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) {
   5560             if (BCM_GPORT_UCAST_QUEUE_GROUP_QID_GET(port) <
   5561                 _BCM_TD_NUM_UCAST_QUEUE_GROUP) { /* regular ucast queue */
   5562                 BCM_IF_ERROR_RETURN
   5563                     (_bcm_td_cosq_index_resolve
   5564                      (unit, port, cosq, _BCM_TD_COSQ_INDEX_STYLE_UCAST_QUEUE,
   5565                       &local_port, &startq, NULL));
   5566                 BCM_IF_ERROR_RETURN
   5567                     (soc_counter_set(unit, local_port,
   5568                                      SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT_UC,
   5569                                      startq, value));
   5570             } else { /* extended ucast queue */
   5571                 BCM_IF_ERROR_RETURN
   5572                     (_bcm_td_cosq_index_resolve
   5573                      (unit, port, cosq,
   5574                       _BCM_TD_COSQ_INDEX_STYLE_EXT_UCAST_QUEUE,
   5575                       NULL, &startq, &numq));
   5576                 for (i = 0; i < numq; i++) {
   5577                     BCM_IF_ERROR_RETURN
   5578                         (_bcm_td_cosq_index_resolve
   5579                          (unit, port, cosq < 0 ? i : cosq,
   5580                           _BCM_TD_COSQ_INDEX_STYLE_EXT_UCAST_QUEUE,
   5581                           &local_port, &startq, NULL));
   5582                     BCM_IF_ERROR_RETURN
   5583                         (soc_counter_set
   5584                          (unit, local_port,
   5585                           SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT_EXT,
   5586                           startq, value));
   5587                 }
   5588             }
   5589         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
   5590             BCM_IF_ERROR_RETURN
   5591                 (_bcm_td_cosq_index_resolve
   5592                  (unit, port, cosq, _BCM_TD_COSQ_INDEX_STYLE_MCAST_QUEUE,
   5593                   &local_port, &startq, NULL));
   5594             BCM_IF_ERROR_RETURN
   5595                 (soc_counter_set(unit, local_port,
   5596                                  SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT, startq,
   5597                                  value));
   5598         } else {
   5599             if (cosq < BCM_COS_INVALID) {
   5600                 return BCM_E_PARAM;
   5601             }
   5602 
   5603             BCM_IF_ERROR_RETURN
   5604                 (_bcm_td_cosq_localport_resolve(unit, port, &local_port));
   5605             if (cosq == BCM_COS_INVALID) {
   5606                 /* UC queue */
   5607                 for (i = 0; i < si->port_num_uc_cosq[local_port]; i++) {
   5608                     BCM_IF_ERROR_RETURN
   5609                         (soc_counter_set(unit, local_port,
   5610                                          SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT_UC,
   5611                                          i, value));
   5612                 }
   5613                 /* MC queue */
   5614                 for (i = 0; i < si->port_num_cosq[local_port]; i++) {
   5615                     BCM_IF_ERROR_RETURN
   5616                         (soc_counter_set(unit, local_port,
   5617                                          SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT,
   5618                                          i, value));
   5619                 }
   5620             } else {
   5621                 /*
   5622                  * cosq=0 for ucast queue 0 + mcast queue 0
   5623                  * cosq=1 for ucast queue 1 + mcast queue 1
   5624                  * cosq=2 for ucast queue 2 + mcast queue 2
   5625                  * cosq=3 for ucast queue 3 + mcast queue 3
   5626                  * cosq=4 for ucast queue 4
   5627                  * cosq=5 for ucast queue 5
   5628                  * cosq=6 for ucast queue 6
   5629                  * cosq=7 for ucast queue 7
   5630                  * cosq=8 for unicast SC queue + multicast SC/QM queue
   5631                  * cosq=9 for unicast QM queue.
   5632                  */
   5633                 if (IS_CPU_PORT(unit, local_port) ||
   5634                     IS_LB_PORT(unit, local_port)) {
   5635                     if (cosq >= (si->port_num_cosq[local_port])) {
   5636                         return BCM_E_PARAM;
   5637                     }
   5638                 } else if (cosq >= (si->port_num_uc_cosq[local_port])){
   5639                     return BCM_E_PARAM;
   5640                 }
   5641 
   5642                 if (IS_CPU_PORT(unit, local_port) ||
   5643                     IS_LB_PORT(unit, local_port)) {
   5644                     BCM_IF_ERROR_RETURN
   5645                         (soc_counter_set(unit, local_port,
   5646                                      SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT,
   5647                                      cosq, value));
   5648                 } else {
   5649                     /* UC queue */
   5650                     BCM_IF_ERROR_RETURN
   5651                         (soc_counter_set(unit, local_port,
   5652                                      SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT_UC,
   5653                                      cosq, value));
   5654                     /* MC queue */
   5655                     if ((cosq < (si->port_num_cosq[local_port] - 1)) ||
   5656                         (cosq == 8)) {
   5657                         cosq = (cosq == 8) ? 4 : cosq;
   5658                         BCM_IF_ERROR_RETURN
   5659                             (soc_counter_set(unit, local_port,
   5660                                          SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT,
   5661                                          cosq, value));
   5662                     }
   5663                 }
   5664             }
   5665         }
   5666         break;
   5667     case bcmCosqStatOutBytes:
   5668         if (BCM_GPORT_IS_SCHEDULER(port)) {
   5669             BCM_IF_ERROR_RETURN
   5670                 (_bcm_td_cosq_node_get(unit, port, NULL,
   5671                                         &local_port, NULL, &node));
   5672             BCM_IF_ERROR_RETURN
   5673                 (_bcm_td_cosq_child_node_at_input(node, cosq, &node));
   5674             port = node->gport;
   5675             if (BCM_GPORT_IS_SCHEDULER(port)) {
   5676                /* Not support more than one-layer scheduler node analysis*/
   5677                return BCM_E_PARAM;
   5678             }
   5679         }
   5680 
   5681         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) {
   5682             if (BCM_GPORT_UCAST_QUEUE_GROUP_QID_GET(port) <
   5683                 _BCM_TD_NUM_UCAST_QUEUE_GROUP) { /* regular ucast queue */
   5684                 BCM_IF_ERROR_RETURN
   5685                     (_bcm_td_cosq_index_resolve
   5686                      (unit, port, cosq, _BCM_TD_COSQ_INDEX_STYLE_UCAST_QUEUE,
   5687                       &local_port, &startq, NULL));
   5688                 BCM_IF_ERROR_RETURN
   5689                     (soc_counter_set(unit, local_port,
   5690                                      SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE_UC,
   5691                                      startq, value));
   5692             } else { /* extended ucast queue */
   5693                 BCM_IF_ERROR_RETURN
   5694                     (_bcm_td_cosq_index_resolve
   5695                      (unit, port, cosq,
   5696                       _BCM_TD_COSQ_INDEX_STYLE_EXT_UCAST_QUEUE,
   5697                       NULL, NULL, &numq));
   5698                 for (i = 0; i < numq; i++) {
   5699                     BCM_IF_ERROR_RETURN
   5700                         (_bcm_td_cosq_index_resolve
   5701                          (unit, port, cosq < 0 ? i : cosq,
   5702                           _BCM_TD_COSQ_INDEX_STYLE_EXT_UCAST_QUEUE,
   5703                           &local_port, &startq, NULL));
   5704                     BCM_IF_ERROR_RETURN
   5705                         (soc_counter_set
   5706                          (unit, local_port,
   5707                           SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE_EXT,
   5708                           startq, value));
   5709                 }
   5710             }
   5711         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
   5712             BCM_IF_ERROR_RETURN
   5713                 (_bcm_td_cosq_index_resolve
   5714                  (unit, port, cosq, _BCM_TD_COSQ_INDEX_STYLE_MCAST_QUEUE,
   5715                   &local_port, &startq, NULL));
   5716             BCM_IF_ERROR_RETURN
   5717                 (soc_counter_set(unit, local_port,
   5718                                  SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE, startq,
   5719                                  value));
   5720         } else {
   5721             if (cosq < BCM_COS_INVALID) {
   5722                 return BCM_E_PARAM;
   5723             }
   5724 
   5725             BCM_IF_ERROR_RETURN
   5726                 (_bcm_td_cosq_localport_resolve(unit, port, &local_port));
   5727             if (cosq == BCM_COS_INVALID) {
   5728                 /* UC queue */
   5729                 for (i = 0; i < si->port_num_uc_cosq[local_port]; i++) {
   5730                     BCM_IF_ERROR_RETURN
   5731                         (soc_counter_set(unit, local_port,
   5732                                          SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE_UC,
   5733                                          i, value));
   5734                 }
   5735                 /* MC queue */
   5736                 for (i = 0; i < si->port_num_cosq[local_port]; i++) {
   5737                     BCM_IF_ERROR_RETURN
   5738                         (soc_counter_set(unit, local_port,
   5739                                          SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE,
   5740                                          i, value));
   5741                 }
   5742             } else {
   5743                 /*
   5744                  * cosq=0 for ucast queue 0 + mcast queue 0
   5745                  * cosq=1 for ucast queue 1 + mcast queue 1
   5746                  * cosq=2 for ucast queue 2 + mcast queue 2
   5747                  * cosq=3 for ucast queue 3 + mcast queue 3
   5748                  * cosq=4 for ucast queue 4
   5749                  * cosq=5 for ucast queue 5
   5750                  * cosq=6 for ucast queue 6
   5751                  * cosq=7 for ucast queue 7
   5752                  * cosq=8 for unicast SC queue + multicast SC/QM queue
   5753                  * cosq=9 for unicast QM queue.
   5754                  */
   5755                 if (IS_CPU_PORT(unit, local_port) ||
   5756                     IS_LB_PORT(unit, local_port)) {
   5757                     if (cosq >= (si->port_num_cosq[local_port])) {
   5758                         return BCM_E_PARAM;
   5759                     }
   5760                 } else if (cosq >= (si->port_num_uc_cosq[local_port])){
   5761                     return BCM_E_PARAM;
   5762                 }
   5763 
   5764                 if (IS_CPU_PORT(unit, local_port) ||
   5765                     IS_LB_PORT(unit, local_port)) {
   5766                     BCM_IF_ERROR_RETURN
   5767                         (soc_counter_set(unit, local_port,
   5768                                      SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE,
   5769                                      cosq, value));
   5770                 } else {
   5771                     /* UC queue */
   5772                     BCM_IF_ERROR_RETURN
   5773                         (soc_counter_set(unit, local_port,
   5774                                      SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE_UC,
   5775                                      cosq, value));
   5776                     /* MC queue */
   5777                     if ((cosq < (si->port_num_cosq[local_port] - 1)) ||
   5778                         (cosq == 8)) {
   5779                         cosq = (cosq == 8) ? 4 : cosq;
   5780                         BCM_IF_ERROR_RETURN
   5781                             (soc_counter_set(unit, local_port,
   5782                                          SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE,
   5783                                          cosq, value));
   5784                     }
   5785                 }
   5786             }
   5787         }
   5788         break;
   5789     case bcmCosqStatIeee8021CnCpTransmittedCnms:
   5790         BCM_IF_ERROR_RETURN
   5791             (_bcm_td_cosq_index_resolve
   5792                  (unit, port, cosq, _BCM_TD_COSQ_INDEX_STYLE_UCAST_QUEUE,
   5793                   &local_port, NULL, NULL));
   5794         BCM_IF_ERROR_RETURN
   5795             (bcm_td_cosq_congestion_queue_get(unit, port, cosq, &startq));
   5796                   
   5797         BCM_IF_ERROR_RETURN
   5798             (soc_counter_set(unit, local_port,
   5799                              SOC_COUNTER_NON_DMA_MMU_QCN_CNM, startq, value)); 
   5800         break;
   5801     default:
   5802         return BCM_E_PARAM;
   5803     }
   5804 
   5805     return BCM_E_NONE;
   5806 }
   5807 
   5808 int
   5809 bcm_td_cosq_stat_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   5810                      bcm_cosq_stat_t stat, int sync_mode, uint64 *value)
   5811 {
   5812     soc_info_t *si;
   5813     _bcm_td_cosq_node_t *node;
   5814     bcm_port_t local_port;
   5815     int startq, numq, i, start_hw_index, end_hw_index;
   5816     uint64 sum, value64;
   5817     int (*counter_get) (int , soc_port_t , soc_reg_t , int , uint64 *);
   5818 
   5819     if (value == NULL) {
   5820         return BCM_E_PARAM;
   5821     }
   5822 
   5823     /*
   5824      * if sync-mode is set, update the software cached counter value, 
   5825      * with the hardware count and then retrieve the count.
   5826      * else return the software cache counter value.
   5827      */
   5828     counter_get = (sync_mode == 1)? soc_counter_sync_get: soc_counter_get;
   5829 
   5830     si = &SOC_INFO(unit);
   5831 
   5832     switch (stat) {
   5833     case bcmCosqStatDroppedPackets:
   5834         COMPILER_64_ZERO(sum);
   5835         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) {
   5836             BCM_IF_ERROR_RETURN
   5837                 (_bcm_td_cosq_index_resolve
   5838                  (unit, port, cosq, _BCM_TD_COSQ_INDEX_STYLE_UCAST_DROP,
   5839                   &local_port, &startq, &numq));
   5840             for (i = 0; i < numq; i++) {
   5841                 BCM_IF_ERROR_RETURN
   5842                     (counter_get(unit, local_port,
   5843                                      SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_UC,
   5844                                      startq + i, &value64));
   5845                 COMPILER_64_ADD_64(sum, value64);
   5846             }
   5847         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
   5848             BCM_IF_ERROR_RETURN
   5849                 (_bcm_td_cosq_index_resolve
   5850                  (unit, port, cosq, _BCM_TD_COSQ_INDEX_STYLE_MCAST_QUEUE,
   5851                   &local_port, &startq, &numq));
   5852             for (i = 0; i < numq; i++) {
   5853                 BCM_IF_ERROR_RETURN
   5854                     (counter_get(unit, local_port,
   5855                                      SOC_COUNTER_NON_DMA_COSQ_DROP_PKT,
   5856                                      startq + i, &value64));
   5857                 COMPILER_64_ADD_64(sum, value64);
   5858             }
   5859         } else {
   5860             BCM_IF_ERROR_RETURN
   5861                 (_bcm_td_cosq_index_resolve
   5862                  (unit, port, cosq, _BCM_TD_COSQ_INDEX_STYLE_MCAST_QUEUE,
   5863                   &local_port, &startq, &numq));
   5864             if (!IS_CPU_PORT(unit, local_port) && cosq != BCM_COS_INVALID) {
   5865                 return BCM_E_PARAM;
   5866             }
   5867             for (i = 0; i < numq; i++) {
   5868                 BCM_IF_ERROR_RETURN
   5869                     (counter_get(unit, local_port,
   5870                                      SOC_COUNTER_NON_DMA_COSQ_DROP_PKT,
   5871                                      startq + i, &value64));
   5872                 COMPILER_64_ADD_64(sum, value64);
   5873             }
   5874             if (si->port_num_uc_cosq[local_port] > 0) {
   5875                 BCM_IF_ERROR_RETURN
   5876                     (_bcm_td_cosq_index_resolve
   5877                      (unit, port, cosq, _BCM_TD_COSQ_INDEX_STYLE_UCAST_DROP,
   5878                       &local_port, &startq, &numq));
   5879                 for (i = 0; i < numq; i++) {
   5880                     BCM_IF_ERROR_RETURN
   5881                         (counter_get(unit, local_port,
   5882                                          SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_UC,
   5883                                          startq + i, &value64));
   5884                     COMPILER_64_ADD_64(sum, value64);
   5885                 }
   5886             }
   5887         }
   5888         *value = sum;
   5889         break;
   5890     case bcmCosqStatDroppedBytes:
   5891         COMPILER_64_ZERO(sum);
   5892         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) {
   5893             BCM_IF_ERROR_RETURN
   5894                 (_bcm_td_cosq_index_resolve
   5895                  (unit, port, cosq, _BCM_TD_COSQ_INDEX_STYLE_UCAST_DROP,
   5896                   &local_port, &startq, &numq));
   5897             for (i = 0; i < numq; i++) {
   5898                 BCM_IF_ERROR_RETURN
   5899                     (counter_get(unit, local_port,
   5900                                      SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE_UC,
   5901                                      startq + i, &value64));
   5902                 COMPILER_64_ADD_64(sum, value64);
   5903             }
   5904         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
   5905             BCM_IF_ERROR_RETURN
   5906                 (_bcm_td_cosq_index_resolve
   5907                  (unit, port, cosq, _BCM_TD_COSQ_INDEX_STYLE_MCAST_QUEUE,
   5908                   &local_port, &startq, &numq));
   5909             for (i = 0; i < numq; i++) {
   5910                 BCM_IF_ERROR_RETURN
   5911                     (counter_get(unit, local_port,
   5912                                      SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE,
   5913                                      startq + i, &value64));
   5914                 COMPILER_64_ADD_64(sum, value64);
   5915             }
   5916         } else {
   5917             BCM_IF_ERROR_RETURN
   5918                 (_bcm_td_cosq_index_resolve
   5919                  (unit, port, cosq, _BCM_TD_COSQ_INDEX_STYLE_MCAST_QUEUE,
   5920                   &local_port, &startq, &numq));
   5921             if (!IS_CPU_PORT(unit, local_port) && cosq != BCM_COS_INVALID) {
   5922                 return BCM_E_PARAM;
   5923             }
   5924             for (i = 0; i < numq; i++) {
   5925                 BCM_IF_ERROR_RETURN
   5926                     (counter_get(unit, local_port,
   5927                                      SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE,
   5928                                      startq + i, &value64));
   5929                 COMPILER_64_ADD_64(sum, value64);
   5930             }
   5931             if (si->port_num_uc_cosq[local_port] > 0) {
   5932                 BCM_IF_ERROR_RETURN
   5933                     (_bcm_td_cosq_index_resolve
   5934                      (unit, port, cosq, _BCM_TD_COSQ_INDEX_STYLE_UCAST_DROP,
   5935                       &local_port, &startq, &numq));
   5936                 for (i = 0; i < numq; i++) {
   5937                     BCM_IF_ERROR_RETURN
   5938                         (counter_get(unit, local_port,
   5939                                          SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE_UC,
   5940                                          startq + i, &value64));
   5941                     COMPILER_64_ADD_64(sum, value64);
   5942                 }
   5943             }
   5944         }
   5945         *value = sum;
   5946         break;
   5947     case bcmCosqStatYellowCongestionDroppedPackets:
   5948         if (cosq != BCM_COS_INVALID) {
   5949             return BCM_E_UNAVAIL;
   5950         }
   5951         BCM_IF_ERROR_RETURN
   5952             (_bcm_td_cosq_localport_resolve(unit, port, &local_port));
   5953         BCM_IF_ERROR_RETURN
   5954             (counter_get(unit, local_port,
   5955                              SOC_COUNTER_NON_DMA_PORT_DROP_PKT_YELLOW, 0,
   5956                              value));
   5957         break;
   5958     case bcmCosqStatRedCongestionDroppedPackets:
   5959         if (cosq != BCM_COS_INVALID) {
   5960             return BCM_E_UNAVAIL;
   5961         }
   5962         BCM_IF_ERROR_RETURN
   5963             (_bcm_td_cosq_localport_resolve(unit, port, &local_port));
   5964         BCM_IF_ERROR_RETURN
   5965             (counter_get(unit, local_port,
   5966                              SOC_COUNTER_NON_DMA_PORT_DROP_PKT_RED, 0,
   5967                              value));
   5968         break;
   5969     case bcmCosqStatGreenDiscardDroppedPackets:
   5970         if (cosq != BCM_COS_INVALID) {
   5971             return BCM_E_UNAVAIL;
   5972         }
   5973         BCM_IF_ERROR_RETURN
   5974             (_bcm_td_cosq_localport_resolve(unit, port, &local_port));
   5975         BCM_IF_ERROR_RETURN
   5976             (counter_get(unit, local_port,
   5977                              SOC_COUNTER_NON_DMA_PORT_WRED_PKT_GREEN, 0,
   5978                              value));
   5979         break;
   5980     case bcmCosqStatYellowDiscardDroppedPackets:
   5981         if (cosq != BCM_COS_INVALID) {
   5982             return BCM_E_UNAVAIL;
   5983         }
   5984         BCM_IF_ERROR_RETURN
   5985             (_bcm_td_cosq_localport_resolve(unit, port, &local_port));
   5986         BCM_IF_ERROR_RETURN
   5987             (counter_get(unit, local_port,
   5988                              SOC_COUNTER_NON_DMA_PORT_WRED_PKT_YELLOW, 0,
   5989                              value));
   5990         break;
   5991     case bcmCosqStatRedDiscardDroppedPackets:
   5992         if (cosq != BCM_COS_INVALID) {
   5993             return BCM_E_UNAVAIL;
   5994         }
   5995         BCM_IF_ERROR_RETURN
   5996             (_bcm_td_cosq_localport_resolve(unit, port, &local_port));
   5997         BCM_IF_ERROR_RETURN
   5998             (counter_get(unit, local_port,
   5999                              SOC_COUNTER_NON_DMA_PORT_WRED_PKT_RED, 0, value));
   6000         break;
   6001     case bcmCosqStatOutPackets:
   6002         if (BCM_GPORT_IS_SCHEDULER(port)) {
   6003             BCM_IF_ERROR_RETURN
   6004                 (_bcm_td_cosq_node_get(unit, port, NULL,
   6005                                         &local_port, NULL, &node));
   6006             BCM_IF_ERROR_RETURN
   6007                 (_bcm_td_cosq_child_node_at_input(node, cosq, &node));
   6008             port = node->gport;
   6009             if (BCM_GPORT_IS_SCHEDULER(port)) {
   6010                /* Not support more than one-layer scheduler node analysis*/
   6011                return BCM_E_PARAM;
   6012             }
   6013         }
   6014 
   6015         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) {
   6016             if (BCM_GPORT_UCAST_QUEUE_GROUP_QID_GET(port) <
   6017                 _BCM_TD_NUM_UCAST_QUEUE_GROUP) { /* regular ucast queue */
   6018                 BCM_IF_ERROR_RETURN
   6019                     (_bcm_td_cosq_index_resolve
   6020                      (unit, port, cosq, _BCM_TD_COSQ_INDEX_STYLE_UCAST_QUEUE,
   6021                       &local_port, &startq, NULL));
   6022                 BCM_IF_ERROR_RETURN
   6023                     (counter_get(unit, local_port,
   6024                                      SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT_UC,
   6025                                      startq, value));
   6026             } else { /* extended ucast queue */
   6027                 BCM_IF_ERROR_RETURN
   6028                     (_bcm_td_cosq_index_resolve
   6029                      (unit, port, cosq,
   6030                       _BCM_TD_COSQ_INDEX_STYLE_EXT_UCAST_QUEUE,
   6031                       NULL, NULL, &numq));
   6032                 COMPILER_64_ZERO(sum);
   6033                 for (i = 0; i < numq; i++) {
   6034                     BCM_IF_ERROR_RETURN
   6035                         (_bcm_td_cosq_index_resolve
   6036                          (unit, port, cosq < 0 ? i : cosq,
   6037                           _BCM_TD_COSQ_INDEX_STYLE_EXT_UCAST_QUEUE,
   6038                           &local_port, &startq, NULL));
   6039                     BCM_IF_ERROR_RETURN
   6040                         (counter_get
   6041                          (unit, local_port,
   6042                           SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT_EXT,
   6043                           startq, &value64));
   6044                     COMPILER_64_ADD_64(sum, value64);
   6045                 }
   6046                 *value = sum;
   6047             }
   6048         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
   6049             BCM_IF_ERROR_RETURN
   6050                 (_bcm_td_cosq_index_resolve
   6051                  (unit, port, cosq, _BCM_TD_COSQ_INDEX_STYLE_MCAST_QUEUE,
   6052                   &local_port, &startq, NULL));
   6053             BCM_IF_ERROR_RETURN
   6054                 (counter_get(unit, local_port,
   6055                                  SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT, startq,
   6056                                  value));
   6057         } else {
   6058             if (cosq < BCM_COS_INVALID) {
   6059                 return BCM_E_PARAM;
   6060             }
   6061 
   6062             BCM_IF_ERROR_RETURN
   6063                 (_bcm_td_cosq_localport_resolve(unit, port, &local_port));
   6064             COMPILER_64_ZERO(sum);
   6065             if (cosq == BCM_COS_INVALID) {
   6066                 /* UC queue */
   6067                 for (i = 0; i < si->port_num_uc_cosq[local_port]; i++) {
   6068                     BCM_IF_ERROR_RETURN
   6069                         (counter_get(unit, local_port,
   6070                                      SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT_UC,
   6071                                      i, &value64));
   6072                     COMPILER_64_ADD_64(sum, value64);
   6073                 }
   6074                 /* MC queue */
   6075                 for (i = 0; i < si->port_num_cosq[local_port]; i++) {
   6076                     BCM_IF_ERROR_RETURN
   6077                         (counter_get(unit, local_port,
   6078                                          SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT,
   6079                                          i, &value64));
   6080                     COMPILER_64_ADD_64(sum, value64);
   6081                 }
   6082             } else {
   6083                 /*
   6084                  * cosq=0 for ucast queue 0 + mcast queue 0
   6085                  * cosq=1 for ucast queue 1 + mcast queue 1
   6086                  * cosq=2 for ucast queue 2 + mcast queue 2
   6087                  * cosq=3 for ucast queue 3 + mcast queue 3
   6088                  * cosq=4 for ucast queue 4
   6089                  * cosq=5 for ucast queue 5
   6090                  * cosq=6 for ucast queue 6
   6091                  * cosq=7 for ucast queue 7
   6092                  * cosq=8 for unicast SC queue + multicast SC/QM queue
   6093                  * cosq=9 for unicast QM queue.
   6094                  */
   6095                 if (IS_CPU_PORT(unit, local_port) ||
   6096                     IS_LB_PORT(unit, local_port)) {
   6097                     if (cosq >= (si->port_num_cosq[local_port])) {
   6098                         return BCM_E_PARAM;
   6099                     }
   6100                 } else if (cosq >= (si->port_num_uc_cosq[local_port])){
   6101                     return BCM_E_PARAM;
   6102                 }
   6103 
   6104                 if (IS_CPU_PORT(unit, local_port) ||
   6105                     IS_LB_PORT(unit, local_port)) {
   6106                     BCM_IF_ERROR_RETURN
   6107                         (counter_get(unit, local_port,
   6108                                      SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT,
   6109                                      cosq, &value64));
   6110                     COMPILER_64_ADD_64(sum, value64);
   6111                 } else {
   6112                     /* UC queue */
   6113                     BCM_IF_ERROR_RETURN
   6114                         (counter_get(unit, local_port,
   6115                                      SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT_UC,
   6116                                      cosq, &value64));
   6117                     COMPILER_64_ADD_64(sum, value64);
   6118                     /* MC queue */
   6119                     if ((cosq < (si->port_num_cosq[local_port] - 1)) ||
   6120                         (cosq == 8)){
   6121                         cosq = (cosq == 8) ? 4 : cosq;
   6122                         BCM_IF_ERROR_RETURN
   6123                             (counter_get(unit, local_port,
   6124                                          SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT,
   6125                                          cosq, &value64));
   6126                         COMPILER_64_ADD_64(sum, value64);
   6127                     }
   6128                 }
   6129             }
   6130             *value = sum;
   6131         }
   6132         break;
   6133     case bcmCosqStatOutBytes:
   6134         if (BCM_GPORT_IS_SCHEDULER(port)) {
   6135             BCM_IF_ERROR_RETURN
   6136                 (_bcm_td_cosq_node_get(unit, port, NULL,
   6137                                         &local_port, NULL, &node));
   6138             BCM_IF_ERROR_RETURN
   6139                 (_bcm_td_cosq_child_node_at_input(node, cosq, &node));
   6140             port = node->gport;
   6141             if (BCM_GPORT_IS_SCHEDULER(port)) {
   6142                /* Not support more than one-layer scheduler node analysis*/
   6143                return BCM_E_PARAM;
   6144             }
   6145         }
   6146 
   6147         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) {
   6148             if (BCM_GPORT_UCAST_QUEUE_GROUP_QID_GET(port) <
   6149                 _BCM_TD_NUM_UCAST_QUEUE_GROUP) { /* regular ucast queue */
   6150                 BCM_IF_ERROR_RETURN
   6151                     (_bcm_td_cosq_index_resolve
   6152                      (unit, port, cosq, _BCM_TD_COSQ_INDEX_STYLE_UCAST_QUEUE,
   6153                       &local_port, &startq, NULL));
   6154                 BCM_IF_ERROR_RETURN
   6155                     (counter_get(unit, local_port,
   6156                                      SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE_UC,
   6157                                      startq, value));
   6158             } else { /* extended ucast queue */
   6159                 BCM_IF_ERROR_RETURN
   6160                     (_bcm_td_cosq_index_resolve
   6161                      (unit, port, cosq,
   6162                       _BCM_TD_COSQ_INDEX_STYLE_EXT_UCAST_QUEUE,
   6163                       NULL, NULL, &numq));
   6164                 COMPILER_64_ZERO(sum);
   6165                 for (i = 0; i < numq; i++) {
   6166                     BCM_IF_ERROR_RETURN
   6167                         (_bcm_td_cosq_index_resolve
   6168                          (unit, port, cosq < 0 ? i : cosq,
   6169                           _BCM_TD_COSQ_INDEX_STYLE_EXT_UCAST_QUEUE,
   6170                           &local_port, &startq, NULL));
   6171                     BCM_IF_ERROR_RETURN
   6172                         (counter_get
   6173                          (unit, local_port,
   6174                           SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE_EXT,
   6175                           startq, &value64));
   6176                     COMPILER_64_ADD_64(sum, value64);
   6177                 }
   6178                 *value = sum;
   6179             }
   6180         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
   6181             BCM_IF_ERROR_RETURN
   6182                 (_bcm_td_cosq_index_resolve
   6183                  (unit, port, cosq, _BCM_TD_COSQ_INDEX_STYLE_MCAST_QUEUE,
   6184                   &local_port, &startq, NULL));
   6185             BCM_IF_ERROR_RETURN
   6186                 (counter_get(unit, local_port,
   6187                                  SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE, startq,
   6188                                  value));
   6189         } else {
   6190             if (cosq < BCM_COS_INVALID) {
   6191                 return BCM_E_PARAM;
   6192             }
   6193 
   6194             BCM_IF_ERROR_RETURN
   6195                 (_bcm_td_cosq_localport_resolve(unit, port, &local_port));
   6196             COMPILER_64_ZERO(sum);
   6197             if (cosq == BCM_COS_INVALID) {
   6198                 /* UC queue */
   6199                 for (i = 0; i < si->port_num_uc_cosq[local_port]; i++) {
   6200                     BCM_IF_ERROR_RETURN
   6201                         (counter_get(unit, local_port,
   6202                                      SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE_UC,
   6203                                      i, &value64));
   6204                     COMPILER_64_ADD_64(sum, value64);
   6205                 }
   6206                 /* MC queue */
   6207                 for (i = 0; i < si->port_num_cosq[local_port]; i++) {
   6208                     BCM_IF_ERROR_RETURN
   6209                         (counter_get(unit, local_port,
   6210                                          SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE,
   6211                                          i, &value64));
   6212                     COMPILER_64_ADD_64(sum, value64);
   6213                 }
   6214             } else {
   6215                 /*
   6216                  * cosq=0 for ucast queue 0 + mcast queue 0
   6217                  * cosq=1 for ucast queue 1 + mcast queue 1
   6218                  * cosq=2 for ucast queue 2 + mcast queue 2
   6219                  * cosq=3 for ucast queue 3 + mcast queue 3
   6220                  * cosq=4 for ucast queue 4
   6221                  * cosq=5 for ucast queue 5
   6222                  * cosq=6 for ucast queue 6
   6223                  * cosq=7 for ucast queue 7
   6224                  * cosq=8 for unicast SC queue + multicast SC/QM queue
   6225                  * cosq=9 for unicast QM queue.
   6226                  */
   6227                 if (IS_CPU_PORT(unit, local_port) ||
   6228                     IS_LB_PORT(unit, local_port)) {
   6229                     if (cosq >= (si->port_num_cosq[local_port])) {
   6230                         return BCM_E_PARAM;
   6231                     }
   6232                 } else if (cosq >= (si->port_num_uc_cosq[local_port])){
   6233                     return BCM_E_PARAM;
   6234                 }
   6235 
   6236                 if (IS_CPU_PORT(unit, local_port) ||
   6237                     IS_LB_PORT(unit, local_port)) {
   6238                     BCM_IF_ERROR_RETURN
   6239                         (counter_get(unit, local_port,
   6240                                      SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE,
   6241                                      cosq, &value64));
   6242                     COMPILER_64_ADD_64(sum, value64);
   6243                 } else {
   6244                     /* UC queue */
   6245                     BCM_IF_ERROR_RETURN
   6246                         (counter_get(unit, local_port,
   6247                                      SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE_UC,
   6248                                      cosq, &value64));
   6249                     COMPILER_64_ADD_64(sum, value64);
   6250                     /* MC queue */
   6251                     if ((cosq < (si->port_num_cosq[local_port] - 1)) ||
   6252                         (cosq == 8)){
   6253                         cosq = (cosq == 8) ? 4 : cosq;
   6254                         BCM_IF_ERROR_RETURN
   6255                             (counter_get(unit, local_port,
   6256                                          SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE,
   6257                                          cosq, &value64));
   6258                         COMPILER_64_ADD_64(sum, value64);
   6259                     }
   6260                 }
   6261             }
   6262             *value = sum;
   6263         }
   6264         break;
   6265     case bcmCosqStatIeee8021CnCpTransmittedCnms:
   6266         BCM_IF_ERROR_RETURN
   6267             (_bcm_td_cosq_index_resolve
   6268                  (unit, port, cosq, _BCM_TD_COSQ_INDEX_STYLE_UCAST_QUEUE,
   6269                   &local_port, NULL, NULL));
   6270         BCM_IF_ERROR_RETURN
   6271             (bcm_td_cosq_congestion_queue_get(unit, port, cosq, &startq));
   6272         BCM_IF_ERROR_RETURN
   6273             (counter_get(unit, local_port,
   6274                              SOC_COUNTER_NON_DMA_MMU_QCN_CNM,startq, value));
   6275         break;
   6276     case bcmCosqStatIngressPortPoolSharedBytesPeak:
   6277         COMPILER_64_ZERO(sum);
   6278         BCM_IF_ERROR_RETURN
   6279             (_bcm_td_cosq_ingress_sp_get(unit, port, cosq, &start_hw_index,
   6280                                          &end_hw_index));
   6281         BCM_IF_ERROR_RETURN(_bcm_td_cosq_localport_resolve(unit, port,
   6282                                                            &local_port));
   6283         for (i = start_hw_index; i <= end_hw_index; i++) {
   6284             /* coverity[NEGATIVE_RETURNS: FALSE] */
   6285             BCM_IF_ERROR_RETURN
   6286                 (counter_get(unit, local_port,
   6287                              SOC_COUNTER_NON_DMA_POOL_PEAK,
   6288                              i, &value64));
   6289             COMPILER_64_ADD_64(sum, value64);
   6290         }
   6291 
   6292         COMPILER_64_UMUL_32(sum, _BCM_TD_BYTES_PER_CELL);
   6293         *value = sum;
   6294         break;
   6295     case bcmCosqStatIngressPortPoolSharedBytesCurrent:
   6296         BCM_IF_ERROR_RETURN
   6297             (_bcm_td_cosq_ingress_sp_get(unit, port, cosq, &start_hw_index,
   6298                                          &end_hw_index));
   6299         BCM_IF_ERROR_RETURN(_bcm_td_cosq_localport_resolve(unit, port,
   6300                                                            &local_port));
   6301 
   6302         COMPILER_64_ZERO(sum);
   6303         for (i = start_hw_index; i <= end_hw_index; i++) {
   6304             /* coverity[NEGATIVE_RETURNS: FALSE] */
   6305             BCM_IF_ERROR_RETURN
   6306                 (counter_get(unit, local_port,
   6307                              SOC_COUNTER_NON_DMA_POOL_CURRENT,
   6308                              i, &value64));
   6309            COMPILER_64_ADD_64(sum, value64);
   6310         }
   6311 
   6312         COMPILER_64_UMUL_32(sum, _BCM_TD_BYTES_PER_CELL);
   6313         *value = sum;
   6314         break;
   6315 
   6316     default:
   6317         return BCM_E_PARAM;
   6318     }
   6319 
   6320     return BCM_E_NONE;
   6321 }
   6322 
   6323 /*
   6324  * Function:
   6325  *     _bcm_td_cosq_quantize_table_set
   6326  * Purpose:
   6327  *     Generate quantized feedback lookup table
   6328  * Parameters:
   6329  *     unit          - (IN) unit number
   6330  *     profile_index - (IN) profile index
   6331  *     weight_code   - (IN) weight encoding
   6332  *     set_point     - (IN) queue size set point
   6333  *     active_offset - (OUT) most significant non-zero bit position
   6334  * Returns:
   6335  *     BCM_E_XXX
   6336  * Notes:
   6337  *     The formular to quantize feedback value is:
   6338  *     quantized_feedbad = celling(feedback / max_feedback * 63)
   6339  *         where max_feedback = (2 * cpW + 1) * cpQsp
   6340  *         cpW is feedback weight
   6341  *         cpQsp is queue size set point
   6342  */
   6343 STATIC int
   6344 _bcm_td_cosq_quantize_table_set(int unit, int profile_index, int weight_code,
   6345                                 int set_point, int *active_offset)
   6346 {
   6347     int ref_count;
   6348     int weight_x_4, feedback, max_feedback, quantized_feedback, shift;
   6349     int base_index, index;
   6350 
   6351     /* weight = 2 ** (weight_code - 2) e.g. 0 for 1/4, 1 for 1/2, ...  */
   6352     weight_x_4 = 1 << weight_code;
   6353     max_feedback = ((2 * weight_x_4 + 4) * set_point + 3) / 4;
   6354     shift = 0;
   6355     while ((max_feedback >> shift) > 127) {
   6356         shift++;
   6357     }
   6358 
   6359     BCM_IF_ERROR_RETURN
   6360         (soc_profile_reg_ref_count_get(unit, _bcm_td_feedback_profile[unit],
   6361                                        profile_index, &ref_count));
   6362 
   6363     /*
   6364      * Hardware use lookup table to find quantized feedback in order to avoid
   6365      * division, use most significant 7-bit of feedback value as lookup table
   6366      * index to find quantized_feedback value
   6367      */
   6368     if (ref_count == 1) {
   6369         base_index = profile_index << 7;
   6370         for (index = 0; index < 128; index++) {
   6371             feedback = index << shift;
   6372             if (feedback > max_feedback) {
   6373                 quantized_feedback = 63;
   6374             } else {
   6375                 quantized_feedback = (feedback * 63 + max_feedback - 1) /
   6376                     max_feedback;
   6377             }
   6378             BCM_IF_ERROR_RETURN
   6379                 (soc_mem_field32_modify(unit, MMU_QCN_QFBTBm,
   6380                                         base_index  + index, CPQ_QNTZFBf,
   6381                                         quantized_feedback));
   6382         }
   6383     }
   6384 
   6385     *active_offset = shift + 6;
   6386 
   6387     return BCM_E_NONE;
   6388 }
   6389 
   6390 STATIC int
   6391 _bcm_td_cosq_sample_int_table_set(int unit, int min, int max,
   6392                                   uint32 *profile_index)
   6393 {
   6394     mmu_qcn_sitb_entry_t sitb_entries[64];
   6395     void *entries[1];
   6396     int i, j, center, inc, value, index;
   6397 
   6398     sal_memset(sitb_entries, 0, sizeof(sitb_entries));
   6399     entries[0] = &sitb_entries;
   6400     for (i = 0; i < 8; i++) {
   6401         center = max - (max - min) * i / 7;
   6402         inc = (max - min) / 7 / 8;
   6403         for (j = 0; j < 8; j++, inc = -inc) {
   6404             index = i * 8 + j;
   6405             value = center + (j + 1) / 2 * inc;
   6406             if (value > 255) {
   6407                 value = 255;
   6408             } else if (value < 1) {
   6409                 value = 1;
   6410             }
   6411             soc_mem_field32_set(unit, MMU_QCN_SITBm, &sitb_entries[index],
   6412                                 CPQ_SIf, value);
   6413         }
   6414     }
   6415 
   6416     return soc_profile_mem_add(unit, _bcm_td_sample_int_profile[unit], entries,
   6417                                64, (uint32 *)profile_index);
   6418 }
   6419 
   6420 /*
   6421  * Function:
   6422  *     bcm_td_cosq_congestion_queue_set
   6423  * Purpose:
   6424  *     Enable/Disable a cos queue as congestion managed queue
   6425  * Parameters:
   6426  *     unit          - (IN) unit number
   6427  *     port          - (IN) port number or GPORT identifier
   6428  *     cosq          - (IN) COS queue number
   6429  *     index         - (IN) congestion managed queue index
   6430  * Returns:
   6431  *     BCM_E_XXX
   6432  */
   6433 int
   6434 bcm_td_cosq_congestion_queue_set(int unit, bcm_port_t port,
   6435                                  bcm_cos_queue_t cosq, int index)
   6436 {
   6437     soc_info_t *si;
   6438     bcm_port_t local_port;
   6439     int phy_port, mmu_port;
   6440     uint32 rval;
   6441     uint64 rval64, *rval64s[1];
   6442     mmu_qcn_enable_entry_t enable_entry;
   6443     mmu_qcn_cpqcfg_entry_t cpqcfg_entry;
   6444     int cosq_index, active_offset, count;
   6445     uint32 profile_index, sample_profile_index;
   6446     int weight_code, set_point;
   6447 	int qindex;
   6448 	
   6449     si = &SOC_INFO(unit);
   6450 
   6451     if (cosq < 0 || cosq >= _bcm_td_num_cosq[unit]) {
   6452         return BCM_E_PARAM;
   6453     }
   6454 
   6455     if (index < -1 || index > 1) {
   6456         return BCM_E_PARAM;
   6457     }
   6458 
   6459 	BCM_IF_ERROR_RETURN
   6460         (_bcm_td_cosq_index_resolve(unit, port, cosq,
   6461                                     _BCM_TD_COSQ_INDEX_STYLE_UCAST_QUEUE,
   6462                                     &local_port, &qindex, NULL));
   6463 	
   6464     phy_port = si->port_l2p_mapping[local_port];
   6465     mmu_port = si->port_p2m_mapping[phy_port];
   6466     BCM_IF_ERROR_RETURN(soc_mem_read(unit, MMU_QCN_ENABLEm,
   6467                                      MEM_BLOCK_ANY, mmu_port, &enable_entry));
   6468     if (index == -1) {
   6469         if (!soc_mem_field32_get(unit, MMU_QCN_ENABLEm, &enable_entry,
   6470                                  _bcm_td_cpq_en_field[qindex])) {
   6471             return BCM_E_NONE;
   6472         }
   6473 
   6474         index = soc_mem_field32_get(unit, MMU_QCN_ENABLEm, &enable_entry,
   6475                                     _bcm_td_cpq_index_field[qindex]);
   6476         soc_mem_field32_set(unit, MMU_QCN_ENABLEm, &enable_entry,
   6477                             _bcm_td_cpq_en_field[qindex], 0);
   6478         BCM_IF_ERROR_RETURN
   6479             (soc_mem_write(unit, MMU_QCN_ENABLEm, MEM_BLOCK_ANY, mmu_port,
   6480                            &enable_entry));
   6481 
   6482         /* Delete feedback parameter profile */
   6483         BCM_IF_ERROR_RETURN(soc_mem_read(unit, MMU_QCN_CPQCFGm, MEM_BLOCK_ANY,
   6484                                          mmu_port, &cpqcfg_entry));
   6485         profile_index =
   6486             soc_mem_field32_get(unit, MMU_QCN_CPQCFGm, &cpqcfg_entry,
   6487                                 _bcm_td_eqtb_index_field[index]);
   6488         BCM_IF_ERROR_RETURN
   6489             (soc_profile_reg_delete(unit, _bcm_td_feedback_profile[unit],
   6490                                     profile_index));
   6491     } else {
   6492         count = sizeof(_bcm_td_cpq_en_field) / sizeof(_bcm_td_cpq_en_field[0]);
   6493         for (cosq_index = 0; cosq_index < count; cosq_index++) {
   6494             if (!soc_mem_field32_get(unit, MMU_QCN_ENABLEm, &enable_entry,
   6495                                      _bcm_td_cpq_en_field[cosq_index])) {
   6496                 continue;
   6497             }
   6498             if (soc_mem_field32_get(unit, MMU_QCN_ENABLEm, &enable_entry,
   6499                                     _bcm_td_cpq_index_field[cosq_index]) ==
   6500                 index) {
   6501                 if (cosq_index == qindex) {
   6502                     return BCM_E_NONE;
   6503                 } else {
   6504                     return BCM_E_EXISTS;
   6505                 }
   6506             }
   6507         }
   6508 
   6509         /* Use hardware reset value as default quantize setting */
   6510         weight_code = 3;
   6511         set_point = 0x96;
   6512         rval = 0;
   6513         soc_reg_field_set(unit, MMU_QCN_CPQ_SEQr, &rval, CPWf, weight_code);
   6514         soc_reg_field_set(unit, MMU_QCN_CPQ_SEQr, &rval, CPQEQf, set_point);
   6515         COMPILER_64_SET(rval64, 0, rval);
   6516         rval64s[0] = &rval64;
   6517         BCM_IF_ERROR_RETURN
   6518             (soc_profile_reg_add(unit, _bcm_td_feedback_profile[unit],
   6519                                  rval64s, 1, (uint32 *)&profile_index));
   6520 
   6521         /* Update quantized feedback calculation lookup table */
   6522         BCM_IF_ERROR_RETURN
   6523             (_bcm_td_cosq_quantize_table_set(unit, profile_index, weight_code,
   6524                                              set_point, &active_offset));
   6525 
   6526         /* Pick some sample interval */
   6527         BCM_IF_ERROR_RETURN
   6528             (_bcm_td_cosq_sample_int_table_set(unit, 13, 127,
   6529                                                &sample_profile_index));
   6530 
   6531         BCM_IF_ERROR_RETURN(soc_mem_read(unit, MMU_QCN_CPQCFGm, MEM_BLOCK_ANY,
   6532                                          mmu_port, &cpqcfg_entry));
   6533         soc_mem_field32_set(unit, MMU_QCN_CPQCFGm, &cpqcfg_entry,
   6534                             _bcm_td_act_offset_field[index], active_offset);
   6535         soc_mem_field32_set(unit, MMU_QCN_CPQCFGm, &cpqcfg_entry,
   6536                             _bcm_td_eqtb_index_field[index], profile_index);
   6537         soc_mem_field32_set(unit, MMU_QCN_CPQCFGm, &cpqcfg_entry,
   6538                             _bcm_td_sitb_sel_field[index],
   6539                             sample_profile_index);
   6540         BCM_IF_ERROR_RETURN(soc_mem_write(unit, MMU_QCN_CPQCFGm, MEM_BLOCK_ANY,
   6541                                           mmu_port, &cpqcfg_entry));
   6542 
   6543         soc_mem_field32_set(unit, MMU_QCN_ENABLEm, &enable_entry,
   6544                             _bcm_td_cpq_en_field[qindex], 1);
   6545         soc_mem_field32_set(unit, MMU_QCN_ENABLEm, &enable_entry,
   6546                             _bcm_td_cpq_index_field[qindex], index);
   6547         BCM_IF_ERROR_RETURN
   6548             (soc_mem_write(unit, MMU_QCN_ENABLEm, MEM_BLOCK_ANY, mmu_port,
   6549                            &enable_entry));
   6550     }
   6551 
   6552     /* Need to program ING_OUTER_DOT1P_MAPPING_TABLE to bypass the cosq */
   6553 
   6554     return BCM_E_NONE;
   6555 }
   6556 
   6557 /*
   6558  * Function:
   6559  *     bcm_td_cosq_congestion_queue_get
   6560  * Purpose:
   6561  *     Get congestion managed queue index of the specified cos queue
   6562  * Parameters:
   6563  *     unit          - (IN) unit number
   6564  *     port          - (IN) port number or GPORT identifier
   6565  *     cosq          - (IN) COS queue number
   6566  *     index         - (OUT) congestion managed queue index
   6567  * Returns:
   6568  *     BCM_E_XXX
   6569  */
   6570 int
   6571 bcm_td_cosq_congestion_queue_get(int unit, bcm_port_t port,
   6572                                  bcm_cos_queue_t cosq, int *index)
   6573 {
   6574     soc_info_t *si;
   6575     bcm_port_t local_port;
   6576     int phy_port, mmu_port;
   6577     mmu_qcn_enable_entry_t entry;
   6578 	int qindex;
   6579 
   6580     si = &SOC_INFO(unit);
   6581 
   6582     if (cosq < 0 || cosq >= _bcm_td_num_cosq[unit]) {
   6583         return BCM_E_PARAM;
   6584     }
   6585 
   6586     if (index == NULL) {
   6587         return BCM_E_PARAM;
   6588     }
   6589 
   6590 	BCM_IF_ERROR_RETURN
   6591         (_bcm_td_cosq_index_resolve(unit, port, cosq,
   6592                                     _BCM_TD_COSQ_INDEX_STYLE_UCAST_QUEUE,
   6593                                     &local_port, &qindex, NULL));
   6594 
   6595     phy_port = si->port_l2p_mapping[local_port];
   6596     mmu_port = si->port_p2m_mapping[phy_port];
   6597     BCM_IF_ERROR_RETURN
   6598         (soc_mem_read(unit, MMU_QCN_ENABLEm, MEM_BLOCK_ANY, mmu_port, &entry));
   6599     if (soc_mem_field32_get(unit, MMU_QCN_ENABLEm, &entry,
   6600                             _bcm_td_cpq_en_field[qindex])) {
   6601         *index = soc_mem_field32_get(unit, MMU_QCN_ENABLEm, &entry,
   6602                                      _bcm_td_cpq_index_field[qindex]);
   6603     } else {
   6604         *index = -1;
   6605     }
   6606 
   6607     return BCM_E_NONE;
   6608 }
   6609 
   6610 /*
   6611  * Function:
   6612  *     bcm_td_cosq_congestion_quantize_set
   6613  * Purpose:
   6614  *     Set quantized congestion feedback algorithm parameters
   6615  * Parameters:
   6616  *     unit          - (IN) unit number
   6617  *     port          - (IN) port number or GPORT identifier
   6618  *     cosq          - (IN) COS queue number
   6619  *     weight_code   - (IN) weight encoding (use -1 for unchange)
   6620  *     set_point     - (IN) queue size set point (use -1 for unchange)
   6621  * Returns:
   6622  *     BCM_E_XXX
   6623  */
   6624 int
   6625 bcm_td_cosq_congestion_quantize_set(int unit, bcm_port_t port,
   6626                                     bcm_cos_queue_t cosq, int weight_code,
   6627                                     int set_point)
   6628 {
   6629     soc_info_t *si;
   6630     bcm_port_t local_port;
   6631     int phy_port, mmu_port;
   6632     uint32 rval;
   6633     uint64 rval64, *rval64s[1];
   6634     mmu_qcn_cpqcfg_entry_t entry;
   6635     int cpq_index, active_offset;
   6636     uint32 profile_index, old_profile_index;
   6637 
   6638     si = &SOC_INFO(unit);
   6639 
   6640     BCM_IF_ERROR_RETURN
   6641         (_bcm_td_cosq_index_resolve(unit, port, cosq,
   6642                                     _BCM_TD_COSQ_INDEX_STYLE_UCAST_QUEUE,
   6643                                     &local_port, NULL, NULL));
   6644 
   6645     BCM_IF_ERROR_RETURN
   6646         (bcm_td_cosq_congestion_queue_get(unit, port, cosq, &cpq_index));
   6647     if (cpq_index == -1) {
   6648         /* The cosq specified is not enabled as congestion managed queue */
   6649         return BCM_E_PARAM;
   6650     }
   6651 
   6652     phy_port = si->port_l2p_mapping[local_port];
   6653     mmu_port = si->port_p2m_mapping[phy_port];
   6654 
   6655     BCM_IF_ERROR_RETURN
   6656         (soc_mem_read(unit, MMU_QCN_CPQCFGm, MEM_BLOCK_ANY, mmu_port, &entry));
   6657     old_profile_index =
   6658         soc_mem_field32_get(unit, MMU_QCN_CPQCFGm, &entry,
   6659                             _bcm_td_eqtb_index_field[cpq_index]);
   6660 
   6661     BCM_IF_ERROR_RETURN(READ_MMU_QCN_CPQ_SEQr(unit, old_profile_index, &rval));
   6662     if (weight_code == -1) {
   6663         weight_code = soc_reg_field_get(unit, MMU_QCN_CPQ_SEQr, rval, CPWf);
   6664     } else {
   6665         if (weight_code < 0 || weight_code > 7) {
   6666             return BCM_E_PARAM;
   6667         }
   6668         soc_reg_field_set(unit, MMU_QCN_CPQ_SEQr, &rval, CPWf, weight_code);
   6669     }
   6670     if (set_point == -1) {
   6671         set_point = soc_reg_field_get(unit, MMU_QCN_CPQ_SEQr, rval, CPQEQf);
   6672     } else {
   6673         if (set_point < 0 || set_point > 0xffff) {
   6674             return BCM_E_PARAM;
   6675         }
   6676         soc_reg_field_set(unit, MMU_QCN_CPQ_SEQr, &rval, CPQEQf, set_point);
   6677     }
   6678     COMPILER_64_SET(rval64, 0, rval);
   6679     rval64s[0] = &rval64;
   6680     /* Add new feedback parameter profile */
   6681     BCM_IF_ERROR_RETURN
   6682         (soc_profile_reg_add(unit, _bcm_td_feedback_profile[unit], rval64s,
   6683                              1, (uint32 *)&profile_index));
   6684     /* Delete original feedback parameter profile */
   6685     BCM_IF_ERROR_RETURN
   6686         (soc_profile_reg_delete(unit, _bcm_td_feedback_profile[unit],
   6687                                 old_profile_index));
   6688 
   6689     /* Update quantized feedback calculation lookup table */
   6690     BCM_IF_ERROR_RETURN
   6691         (_bcm_td_cosq_quantize_table_set(unit, profile_index, weight_code,
   6692                                          set_point, &active_offset));
   6693 
   6694     soc_mem_field32_set(unit, MMU_QCN_CPQCFGm, &entry,
   6695                         _bcm_td_act_offset_field[cpq_index], active_offset);
   6696     soc_mem_field32_set(unit, MMU_QCN_CPQCFGm, &entry,
   6697                         _bcm_td_eqtb_index_field[cpq_index], profile_index);
   6698     BCM_IF_ERROR_RETURN(soc_mem_write(unit, MMU_QCN_CPQCFGm, MEM_BLOCK_ANY,
   6699                                       mmu_port, &entry));
   6700 
   6701     return BCM_E_NONE;
   6702 }
   6703 
   6704 /*
   6705  * Function:
   6706  *     bcm_td_cosq_congestion_quantize_get
   6707  * Purpose:
   6708  *     Get quantized congestion feedback algorithm parameters
   6709  * Parameters:
   6710  *     unit          - (IN) unit number
   6711  *     port          - (IN) port number or GPORT identifier
   6712  *     cosq          - (IN) COS queue number
   6713  *     weight_code   - (OUT) weight encoding
   6714  *     set_point     - (OUT) queue size set point
   6715  * Returns:
   6716  *     BCM_E_XXX
   6717  */
   6718 int
   6719 bcm_td_cosq_congestion_quantize_get(int unit, bcm_port_t port,
   6720                                     bcm_cos_queue_t cosq, int *weight_code,
   6721                                     int *set_point)
   6722 {
   6723     soc_info_t *si;
   6724     bcm_port_t local_port;
   6725     int phy_port, mmu_port;
   6726     int cpq_index, profile_index;
   6727     uint32 rval;
   6728     mmu_qcn_cpqcfg_entry_t entry;
   6729 
   6730     si = &SOC_INFO(unit);
   6731 
   6732     BCM_IF_ERROR_RETURN
   6733         (_bcm_td_cosq_index_resolve(unit, port, cosq,
   6734                                     _BCM_TD_COSQ_INDEX_STYLE_UCAST_QUEUE,
   6735                                     &local_port, NULL, NULL));
   6736 
   6737     BCM_IF_ERROR_RETURN
   6738         (bcm_td_cosq_congestion_queue_get(unit, port, cosq, &cpq_index));
   6739     if (cpq_index == -1) {
   6740         /* The cosq specified is not enabled as congestion managed queue */
   6741         return BCM_E_PARAM;
   6742     }
   6743 
   6744     phy_port = si->port_l2p_mapping[local_port];
   6745     mmu_port = si->port_p2m_mapping[phy_port];
   6746 
   6747     BCM_IF_ERROR_RETURN
   6748         (soc_mem_read(unit, MMU_QCN_CPQCFGm, MEM_BLOCK_ANY, mmu_port, &entry));
   6749     profile_index = soc_mem_field32_get(unit, MMU_QCN_CPQCFGm, &entry,
   6750                                         _bcm_td_eqtb_index_field[cpq_index]);
   6751 
   6752     BCM_IF_ERROR_RETURN(READ_MMU_QCN_CPQ_SEQr(unit, profile_index, &rval));
   6753     if (weight_code != NULL) {
   6754         *weight_code = soc_reg_field_get(unit, MMU_QCN_CPQ_SEQr, rval, CPWf);
   6755     }
   6756     if (set_point != NULL) {
   6757         *set_point = soc_reg_field_get(unit, MMU_QCN_CPQ_SEQr, rval, CPQEQf);
   6758     }
   6759 
   6760     return BCM_E_NONE;
   6761 }
   6762 
   6763 int
   6764 bcm_td_cosq_congestion_sample_int_set(int unit, bcm_port_t port,
   6765                                       bcm_cos_queue_t cosq, int min, int max)
   6766 {
   6767     soc_info_t *si;
   6768     bcm_port_t local_port;
   6769     int phy_port, mmu_port;
   6770     mmu_qcn_cpqcfg_entry_t cpqcfg_entry;
   6771     mmu_qcn_sitb_entry_t sitb_entry;
   6772     int cpq_index;
   6773     uint32 profile_index, old_profile_index;
   6774 
   6775     si = &SOC_INFO(unit);
   6776 
   6777     BCM_IF_ERROR_RETURN
   6778         (_bcm_td_cosq_index_resolve(unit, port, cosq,
   6779                                     _BCM_TD_COSQ_INDEX_STYLE_UCAST_QUEUE,
   6780                                     &local_port, NULL, NULL));
   6781 
   6782     BCM_IF_ERROR_RETURN
   6783         (bcm_td_cosq_congestion_queue_get(unit, port, cosq, &cpq_index));
   6784     if (cpq_index == -1) {
   6785         /* The cosq specified is not enabled as congestion managed queue */
   6786         return BCM_E_PARAM;
   6787     }
   6788 
   6789     phy_port = si->port_l2p_mapping[local_port];
   6790     mmu_port = si->port_p2m_mapping[phy_port];
   6791 
   6792     BCM_IF_ERROR_RETURN(soc_mem_read(unit, MMU_QCN_CPQCFGm, MEM_BLOCK_ANY,
   6793                                      mmu_port, &cpqcfg_entry));
   6794     old_profile_index =
   6795         soc_mem_field32_get(unit, MMU_QCN_CPQCFGm, &cpqcfg_entry,
   6796                             _bcm_td_sitb_sel_field[cpq_index]);
   6797 
   6798     if (max == -1) {
   6799         BCM_IF_ERROR_RETURN(soc_mem_read(unit, MMU_QCN_SITBm, MEM_BLOCK_ANY,
   6800                                          old_profile_index * 64, &sitb_entry));
   6801         max = soc_mem_field32_get(unit, MMU_QCN_SITBm, &sitb_entry, CPQ_SIf);
   6802     } else {
   6803         if (max < 1 || max > 255) {
   6804             return BCM_E_PARAM;
   6805         }
   6806     }
   6807     if (min == -1) {
   6808         BCM_IF_ERROR_RETURN(soc_mem_read(unit, MMU_QCN_SITBm, MEM_BLOCK_ANY,
   6809                                          old_profile_index * 64 + 56,
   6810                                          &sitb_entry));
   6811         min = soc_mem_field32_get(unit, MMU_QCN_SITBm, &sitb_entry, CPQ_SIf);
   6812     } else {
   6813         if (min < 1 || min > 255) {
   6814             return BCM_E_PARAM;
   6815         }
   6816     }
   6817 
   6818     /* Add new sample interval profile */
   6819     BCM_IF_ERROR_RETURN
   6820         (_bcm_td_cosq_sample_int_table_set(unit, min, max, &profile_index));
   6821 
   6822     /* Delete original sample interval profile */
   6823     BCM_IF_ERROR_RETURN
   6824         (soc_profile_mem_delete(unit, _bcm_td_sample_int_profile[unit],
   6825                                 old_profile_index * 64));
   6826 
   6827     soc_mem_field32_set(unit, MMU_QCN_CPQCFGm, &cpqcfg_entry,
   6828                         _bcm_td_sitb_sel_field[cpq_index], profile_index / 64);
   6829     BCM_IF_ERROR_RETURN(soc_mem_write(unit, MMU_QCN_CPQCFGm, MEM_BLOCK_ANY,
   6830                                       mmu_port, &cpqcfg_entry));
   6831 
   6832     return BCM_E_NONE;
   6833 }
   6834 
   6835 int
   6836 bcm_td_cosq_congestion_sample_int_get(int unit, bcm_port_t port,
   6837                                       bcm_cos_queue_t cosq, int *min, int *max)
   6838 {
   6839     soc_info_t *si;
   6840     bcm_port_t local_port;
   6841     int phy_port, mmu_port;
   6842     mmu_qcn_cpqcfg_entry_t cpqcfg_entry;
   6843     mmu_qcn_sitb_entry_t sitb_entry;
   6844     int cpq_index, profile_index;
   6845 
   6846     si = &SOC_INFO(unit);
   6847 
   6848     BCM_IF_ERROR_RETURN
   6849         (_bcm_td_cosq_index_resolve(unit, port, cosq,
   6850                                     _BCM_TD_COSQ_INDEX_STYLE_UCAST_QUEUE,
   6851                                     &local_port, NULL, NULL));
   6852 
   6853     BCM_IF_ERROR_RETURN
   6854         (bcm_td_cosq_congestion_queue_get(unit, port, cosq, &cpq_index));
   6855     if (cpq_index == -1) {
   6856         /* The cosq specified is not enabled as congestion managed queue */
   6857         return BCM_E_PARAM;
   6858     }
   6859 
   6860     phy_port = si->port_l2p_mapping[local_port];
   6861     mmu_port = si->port_p2m_mapping[phy_port];
   6862 
   6863     BCM_IF_ERROR_RETURN(soc_mem_read(unit, MMU_QCN_CPQCFGm, MEM_BLOCK_ANY,
   6864                                      mmu_port, &cpqcfg_entry));
   6865     profile_index = soc_mem_field32_get(unit, MMU_QCN_CPQCFGm, &cpqcfg_entry,
   6866                                         _bcm_td_sitb_sel_field[cpq_index]);
   6867 
   6868     if (max != NULL) {
   6869         BCM_IF_ERROR_RETURN(soc_mem_read(unit, MMU_QCN_SITBm, MEM_BLOCK_ANY,
   6870                                          profile_index * 64, &sitb_entry));
   6871         *max = soc_mem_field32_get(unit, MMU_QCN_SITBm, &sitb_entry, CPQ_SIf);
   6872     }
   6873     if (min != NULL) {
   6874         BCM_IF_ERROR_RETURN(soc_mem_read(unit, MMU_QCN_SITBm, MEM_BLOCK_ANY,
   6875                                          profile_index * 64 + 56,
   6876                                          &sitb_entry));
   6877         *min = soc_mem_field32_get(unit, MMU_QCN_SITBm, &sitb_entry, CPQ_SIf);
   6878     }
   6879 
   6880     return BCM_E_NONE;
   6881 }
   6882 
   6883 int
   6884 bcm_td_cosq_drop_status_enable_set(int unit, bcm_port_t port, int enable)
   6885 {
   6886     soc_info_t *si;
   6887     soc_mem_t mem;
   6888     int phy_port, mmu_port, base, count, idx;
   6889     uint32 rval;
   6890 
   6891     si = &SOC_INFO(unit);
   6892 
   6893     /* Multicast queue */
   6894     count = IS_LB_PORT(unit, port) ? 5 : si->port_num_cosq[port];
   6895     for (idx = 0; idx < count; idx++) {
   6896         SOC_IF_ERROR_RETURN
   6897             (READ_OP_QUEUE_CONFIG1_CELLr(unit, port, idx, &rval));
   6898         soc_reg_field_set(unit,OP_QUEUE_CONFIG1_CELLr, &rval,
   6899                           Q_E2E_DS_EN_CELLf, enable ? 1 : 0);
   6900         SOC_IF_ERROR_RETURN
   6901             (WRITE_OP_QUEUE_CONFIG1_CELLr(unit, port, idx, rval));
   6902     }
   6903 
   6904     phy_port = si->port_l2p_mapping[port];
   6905     mmu_port = si->port_p2m_mapping[phy_port];
   6906     if (si->port_num_ext_cosq[port] == 0) { /* regular port */
   6907         /* Regular unicast queue */
   6908         if (SOC_PBMP_MEMBER(si->xpipe_pbm, port)) { /* X pipe */
   6909             mem = MMU_THDO_CONFIG_0m;
   6910             /* Index starts from mmu port 5, 10 entries per port */
   6911             base = (mmu_port - 5) * 10;
   6912         } else { /* Y pipe */
   6913             mem = MMU_THDO_CONFIG_1m;
   6914             /* Index starts from mmu port 38, 10 entries per port */
   6915             base = (mmu_port - 38) * 10;
   6916         }
   6917         for (idx = 0; idx < si->port_num_uc_cosq[port]; idx++) {
   6918             SOC_IF_ERROR_RETURN
   6919                 (soc_mem_field32_modify(unit, mem, base + idx,
   6920                                         Q_E2E_DS_EN_CELLf, 1));
   6921         }
   6922     } else { /* extended queue port */
   6923         /*
   6924          * Depends on OP_VOQ_PORT_CONFIG mode setting for the extended
   6925          * queue port:
   6926          * - cos mode
   6927          *     use MMU_THDO_CONFIG_SP_x table, 10 entries per port
   6928          * - queue mode
   6929          *     use MMU_THDO_CONFIG_EX_x table, 74 entries per port
   6930          *     extended unicast queue: index 0-63
   6931          *     regular unicast queue: index 64-73
   6932          */
   6933         /* Regular unicast queue in queue mode and extended unicast queue */
   6934         if (SOC_PBMP_MEMBER(si->xpipe_pbm, port)) { /* X pipe */
   6935             mem = MMU_THDO_CONFIG_EX_0m;
   6936             /* Index starts from mmu port 1, 74 entries per port */
   6937             base = (mmu_port - 1) * 74;
   6938         } else { /* Y pipe */
   6939             mem = MMU_THDO_CONFIG_EX_1m;
   6940             /* Index starts from mmu port 34, 74 entries per port */
   6941             base = (mmu_port - 34) * 74;
   6942         }
   6943         count = si->port_num_uc_cosq[port] + si->port_num_ext_cosq[port];
   6944         for (idx = 0; idx < count; idx++) {
   6945             SOC_IF_ERROR_RETURN
   6946                 (soc_mem_field32_modify(unit, mem, base + idx,
   6947                                         Q_E2E_DS_EN_CELLf, enable ? 1 : 0));
   6948         }
   6949 
   6950         /* Regular unicast queue in cos mode */
   6951         if (SOC_PBMP_MEMBER(si->xpipe_pbm, port)) { /* X pipe */
   6952             mem = MMU_THDO_CONFIG_SP_0m;
   6953             /* Index starts from mmu port 1, 10 entries per port */
   6954             base = (mmu_port - 1) * 10;
   6955         } else { /* Y pipe */
   6956             mem = MMU_THDO_CONFIG_SP_1m;
   6957             /* Index starts from mmu port 34, 10 entries per port */
   6958             base = (mmu_port - 34) * 10;
   6959         }
   6960         for (idx = 0; idx < si->port_num_uc_cosq[port]; idx++) {
   6961             SOC_IF_ERROR_RETURN
   6962                 (soc_mem_field32_modify(unit, mem, base + idx,
   6963                                         Q_E2E_DS_EN_CELLf, enable ? 1 : 0));
   6964         }
   6965     }
   6966 
   6967     /* Regular unicast queue */
   6968     SOC_IF_ERROR_RETURN(READ_OP_UC_PORT_CONFIG1_CELLr(unit, port, &rval));
   6969     soc_reg_field_set(unit,OP_UC_PORT_CONFIG1_CELLr, &rval,
   6970                       Q_E2E_DS_ENf, enable ? 0xff : 0);
   6971     SOC_IF_ERROR_RETURN(WRITE_OP_UC_PORT_CONFIG1_CELLr(unit, port, rval));
   6972 
   6973     SOC_IF_ERROR_RETURN(READ_OP_THR_CONFIGr(unit, &rval));
   6974     soc_reg_field_set(unit, OP_THR_CONFIGr, &rval, EARLY_E2E_SELECTf,
   6975                       enable ? 1 : 0);
   6976     SOC_IF_ERROR_RETURN(WRITE_OP_THR_CONFIGr(unit, rval));
   6977 
   6978     return BCM_E_NONE;
   6979 }
   6980 
   6981 STATIC int
   6982 _bcm_td_cosq_egr_pool_set(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
   6983                           bcm_cosq_control_t type, int arg)
   6984 {
   6985     bcm_port_t local_port;
   6986     int id, startq, pool;
   6987     soc_reg_t reg;
   6988     soc_field_t field;
   6989     uint32 rval;
   6990     int num_cells, default_mtu_cells;
   6991     soc_info_t *si;
   6992 
   6993     num_cells = 0;
   6994     default_mtu_cells = _BCM_TD_BYTES_TO_CELLS(_BCM_TD_DEFAULT_MTU_BYTES +
   6995                                                _BCM_TD_PACKET_HEADER_BYTES);
   6996     si = &SOC_INFO(unit);
   6997 
   6998     if (type == bcmCosqControlUCEgressPool) {
   6999         BCM_IF_ERROR_RETURN
   7000             (_bcm_td_cosq_index_resolve(unit, gport, cosq,
   7001                                         _BCM_TD_COSQ_INDEX_STYLE_UC_EGR_POOL,
   7002                                         &local_port, &startq, NULL));
   7003     } else {
   7004         BCM_IF_ERROR_RETURN
   7005             (_bcm_td_cosq_index_resolve(unit, gport, cosq,
   7006                                         _BCM_TD_COSQ_INDEX_STYLE_EGR_POOL,
   7007                                         &local_port, &startq, NULL));
   7008     }
   7009     if (type == bcmCosqControlEgressPoolLimitEnable) {
   7010         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   7011             reg = OP_UC_PORT_CONFIG1_CELLr;
   7012         } else {
   7013             reg = OP_PORT_CONFIG1_CELLr;
   7014         }
   7015         BCM_IF_ERROR_RETURN(soc_reg32_get(unit, reg, local_port, 0, &rval));
   7016         soc_reg_field_set(unit, reg, &rval, PORT_LIMIT_ENABLE_CELLf,
   7017                           arg ? 1 : 0);
   7018         BCM_IF_ERROR_RETURN(soc_reg32_set(unit, reg, local_port, 0, rval));
   7019         return BCM_E_NONE;
   7020     } else if (type == bcmCosqControlEgressPool) {
   7021         if (arg < 0 || arg > 3) {
   7022             return BCM_E_PARAM;
   7023         }
   7024     } else if (type ==  bcmCosqControlUCEgressPool || type == bcmCosqControlMCEgressPool) {
   7025         if (arg < 0 || arg > 3) {
   7026             return BCM_E_PARAM;
   7027         }
   7028         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   7029             return BCM_E_PARAM;
   7030         }
   7031     } else if (type == bcmCosqControlEgressPoolLimitBytes ||
   7032                type == bcmCosqControlEgressPoolYellowLimitBytes ||
   7033                type == bcmCosqControlEgressPoolRedLimitBytes) {
   7034         if (arg < 0) {
   7035             return BCM_E_PARAM;
   7036         }
   7037         num_cells = arg / _BCM_TD_BYTES_PER_CELL;
   7038         if (num_cells > _BCM_TD_TOTAL_CELLS) {
   7039             return BCM_E_PARAM;
   7040         }
   7041     }
   7042 
   7043     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   7044         BCM_IF_ERROR_RETURN
   7045             (_bcm_td_cosq_node_get(unit, gport, NULL, NULL, &id, NULL));
   7046         if (id < _BCM_TD_NUM_UCAST_QUEUE_GROUP) {
   7047             reg = OP_UC_PORT_CONFIG1_CELLr;
   7048             field = _bcm_td_uc_spid_fields[startq];
   7049             /* regular unicast queue */
   7050         } else {
   7051             /* extended unicast queue */
   7052             reg = _bcm_td_ext_uc_spid_regs[startq / 16];
   7053             field = _bcm_td_ext_uc_spid_fields[startq];
   7054         }
   7055         startq = 0;
   7056     } else if (type == bcmCosqControlUCEgressPool) {
   7057         if (si->port_num_ext_cosq[local_port] == 0) {
   7058             /* regular unicast queue */
   7059             reg = OP_UC_PORT_CONFIG1_CELLr;
   7060             field = _bcm_td_uc_spid_fields[startq];
   7061         } else { 
   7062             /* extended unicast queue */
   7063             reg = _bcm_td_ext_uc_spid_regs[(startq + 64) / 16]; 
   7064             field = _bcm_td_ext_uc_spid_fields[startq + 64];
   7065         }
   7066     } else { /* multicast queue group or local port */
   7067         reg = OP_QUEUE_CONFIG1_CELLr;
   7068         field = Q_SPIDf;
   7069     }
   7070 
   7071     BCM_IF_ERROR_RETURN(soc_reg32_get(unit, reg, local_port, startq, &rval));
   7072     if (type == bcmCosqControlEgressPool || type == bcmCosqControlUCEgressPool ||
   7073         type == bcmCosqControlMCEgressPool) {
   7074         soc_reg_field_set(unit, reg, &rval, field, arg);
   7075         BCM_IF_ERROR_RETURN
   7076             (soc_reg32_set(unit, reg, local_port, startq, rval));
   7077         return BCM_E_NONE;
   7078     }
   7079 
   7080     pool = soc_reg_field_get(unit, reg, rval, field);
   7081     switch (type) {
   7082     case bcmCosqControlEgressPoolLimitBytes:
   7083         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   7084             reg = OP_UC_PORT_CONFIG_CELLr;
   7085         } else {
   7086             reg = OP_PORT_CONFIG_CELLr;
   7087         }
   7088         BCM_IF_ERROR_RETURN(soc_reg32_get(unit, reg, local_port, pool, &rval));
   7089         soc_reg_field_set(unit, reg, &rval, OP_SHARED_LIMIT_CELLf, num_cells);
   7090         num_cells = num_cells > default_mtu_cells ?
   7091             num_cells - default_mtu_cells : 0;
   7092         soc_reg_field_set(unit, reg, &rval, OP_SHARED_RESET_VALUE_CELLf,
   7093                           num_cells);
   7094         BCM_IF_ERROR_RETURN(soc_reg32_set(unit, reg, local_port, pool, rval));
   7095         break;
   7096     case bcmCosqControlEgressPoolYellowLimitBytes:
   7097         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   7098             reg = OP_UC_PORT_LIMIT_COLOR_CELLr;
   7099         } else {
   7100             return BCM_E_PARAM;
   7101         }
   7102         BCM_IF_ERROR_RETURN(soc_reg32_get(unit, reg, local_port, pool, &rval));
   7103         /* granularity for color limit is 8 cells */
   7104         soc_reg_field_set(unit, reg, &rval, YELf, num_cells / 8);
   7105         BCM_IF_ERROR_RETURN(soc_reg32_set(unit, reg, local_port, pool, rval));
   7106         break;
   7107     case bcmCosqControlEgressPoolRedLimitBytes:
   7108         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   7109             reg = OP_UC_PORT_LIMIT_COLOR_CELLr;
   7110         } else {
   7111             reg = OP_PORT_LIMIT_COLOR_CELLr;
   7112         }
   7113         BCM_IF_ERROR_RETURN(soc_reg32_get(unit, reg, local_port, pool, &rval));
   7114         /* granularity for color limit is 8 cells */
   7115         soc_reg_field_set(unit, reg, &rval, REDf, num_cells / 8);
   7116         BCM_IF_ERROR_RETURN(soc_reg32_set(unit, reg, local_port, pool, rval));
   7117         break;
   7118     default:
   7119         return BCM_E_UNAVAIL;
   7120     }
   7121 
   7122     return BCM_E_NONE;
   7123 }
   7124 
   7125 STATIC int
   7126 _bcm_td_cosq_egr_pool_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
   7127                           bcm_cosq_control_t type, int *arg)
   7128 {
   7129     bcm_port_t local_port;
   7130     int id, startq, pool;
   7131     soc_reg_t reg;
   7132     soc_field_t field;
   7133     uint32 rval;
   7134     soc_info_t *si;
   7135     si = &SOC_INFO(unit);
   7136 
   7137     if (type == bcmCosqControlUCEgressPool) {
   7138         BCM_IF_ERROR_RETURN
   7139             (_bcm_td_cosq_index_resolve(unit, gport, cosq,
   7140                                         _BCM_TD_COSQ_INDEX_STYLE_UC_EGR_POOL,
   7141                                         &local_port, &startq, NULL));
   7142     } else {
   7143         BCM_IF_ERROR_RETURN
   7144             (_bcm_td_cosq_index_resolve(unit, gport, cosq,
   7145                                         _BCM_TD_COSQ_INDEX_STYLE_EGR_POOL,
   7146                                         &local_port, &startq, NULL));
   7147     }
   7148     if (type == bcmCosqControlEgressPoolLimitEnable) {
   7149         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   7150             reg = OP_UC_PORT_CONFIG1_CELLr;
   7151         } else {
   7152             reg = OP_PORT_CONFIG1_CELLr;
   7153         }
   7154         BCM_IF_ERROR_RETURN(soc_reg32_get(unit, reg, local_port, 0, &rval));
   7155         *arg = soc_reg_field_get(unit, reg, rval, PORT_LIMIT_ENABLE_CELLf);
   7156         return BCM_E_NONE;
   7157     }
   7158 
   7159     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   7160         BCM_IF_ERROR_RETURN
   7161             (_bcm_td_cosq_node_get(unit, gport, NULL, NULL, &id, NULL));
   7162         if (id < _BCM_TD_NUM_UCAST_QUEUE_GROUP) {
   7163             reg = OP_UC_PORT_CONFIG1_CELLr;
   7164             field = _bcm_td_uc_spid_fields[startq];
   7165             /* regular unicast queue */
   7166         } else {
   7167             /* extended unicast queue */
   7168             reg = _bcm_td_ext_uc_spid_regs[startq / 16];
   7169             field = _bcm_td_ext_uc_spid_fields[startq];
   7170         }
   7171         startq = 0;
   7172     } else if (type == bcmCosqControlUCEgressPool) {
   7173         if (si->port_num_ext_cosq[local_port] == 0) {
   7174             /* regular unicast queue */
   7175             reg = OP_UC_PORT_CONFIG1_CELLr;
   7176             field = _bcm_td_uc_spid_fields[startq];
   7177         } else { 
   7178             /* extended unicast queue */
   7179             reg = _bcm_td_ext_uc_spid_regs[(startq + 64)/16];
   7180             field = _bcm_td_ext_uc_spid_fields[startq + 64];
   7181         }
   7182     } else { /* multicast queue group or local port */
   7183         reg = OP_QUEUE_CONFIG1_CELLr;
   7184         field = Q_SPIDf;
   7185     }
   7186 
   7187     BCM_IF_ERROR_RETURN(soc_reg32_get(unit, reg, local_port, startq, &rval));
   7188     pool = soc_reg_field_get(unit, reg, rval, field);
   7189     if (type == bcmCosqControlEgressPool || type == bcmCosqControlUCEgressPool ||
   7190         type == bcmCosqControlMCEgressPool) {
   7191         *arg = pool;
   7192         return BCM_E_NONE;
   7193     }
   7194 
   7195     switch (type) {
   7196     case bcmCosqControlEgressPoolLimitBytes:
   7197         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   7198             reg = OP_UC_PORT_CONFIG_CELLr;
   7199         } else {
   7200             reg = OP_PORT_CONFIG_CELLr;
   7201         }
   7202         BCM_IF_ERROR_RETURN(soc_reg32_get(unit, reg, local_port, pool, &rval));
   7203         *arg = soc_reg_field_get(unit, reg, rval, OP_SHARED_LIMIT_CELLf) *
   7204             _BCM_TD_BYTES_PER_CELL;
   7205         break;
   7206     case bcmCosqControlEgressPoolYellowLimitBytes:
   7207         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   7208             reg = OP_UC_PORT_LIMIT_COLOR_CELLr;
   7209         } else {
   7210             return BCM_E_PARAM;
   7211         }
   7212         BCM_IF_ERROR_RETURN(soc_reg32_get(unit, reg, local_port, pool, &rval));
   7213         /* granularity for color limit is 8 cells */
   7214         *arg = soc_reg_field_get(unit, reg, rval, YELf) * 8 *
   7215             _BCM_TD_BYTES_PER_CELL;
   7216         break;
   7217     case bcmCosqControlEgressPoolRedLimitBytes:
   7218         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   7219             reg = OP_UC_PORT_LIMIT_COLOR_CELLr;
   7220         } else {
   7221             reg = OP_PORT_LIMIT_COLOR_CELLr;
   7222         }
   7223         BCM_IF_ERROR_RETURN(soc_reg32_get(unit, reg, local_port, pool, &rval));
   7224         /* granularity for color limit is 8 cells */
   7225         *arg = soc_reg_field_get(unit, reg, rval, REDf) * 8 *
   7226             _BCM_TD_BYTES_PER_CELL;
   7227         break;
   7228     default:
   7229         return BCM_E_UNAVAIL;
   7230     }
   7231 
   7232     return BCM_E_NONE;
   7233 }
   7234 
   7235 STATIC int
   7236 _bcm_td_cosq_alpha_set(int unit, 
   7237                         bcm_gport_t gport, bcm_cos_queue_t cosq,
   7238                         bcm_cosq_control_drop_limit_alpha_value_t arg)
   7239 {
   7240     bcm_port_t local_port;
   7241     int id,startq;
   7242     uint32 entry[SOC_MAX_MEM_WORDS];
   7243     soc_mem_t mem = INVALIDm;
   7244     soc_info_t *si;    
   7245     int alpha;
   7246     uint32 rval;  
   7247     int dynamic_thresh_mode;
   7248     int port_pg;
   7249     soc_reg_t reg = INVALIDr;    
   7250     static const soc_reg_t prigroup_reg[] = {
   7251         PORT_PRI_GRP0r, PORT_PRI_GRP1r
   7252     };
   7253     static const soc_field_t prigroup_field[] = {
   7254         PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf,
   7255         PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf,
   7256         PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf,
   7257         PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf
   7258     };     
   7259 
   7260     switch(arg) {
   7261     case bcmCosqControlDropLimitAlpha_1_64:
   7262         alpha = SOC_TD_COSQ_DROP_LIMIT_ALPHA_1_64;
   7263         break;
   7264     case bcmCosqControlDropLimitAlpha_1_32:
   7265         alpha = SOC_TD_COSQ_DROP_LIMIT_ALPHA_1_32;
   7266         break;
   7267     case bcmCosqControlDropLimitAlpha_1_16:
   7268         alpha = SOC_TD_COSQ_DROP_LIMIT_ALPHA_1_16;
   7269         break;
   7270     case bcmCosqControlDropLimitAlpha_1_8:
   7271         alpha = SOC_TD_COSQ_DROP_LIMIT_ALPHA_1_8;
   7272         break;
   7273     case bcmCosqControlDropLimitAlpha_1_4:
   7274         alpha = SOC_TD_COSQ_DROP_LIMIT_ALPHA_1_4;
   7275         break;
   7276     case bcmCosqControlDropLimitAlpha_1_2:
   7277         alpha = SOC_TD_COSQ_DROP_LIMIT_ALPHA_1_2;
   7278         break;
   7279     case bcmCosqControlDropLimitAlpha_1:
   7280         alpha = SOC_TD_COSQ_DROP_LIMIT_ALPHA_1;
   7281         break;   
   7282     case bcmCosqControlDropLimitAlpha_2:
   7283         alpha = SOC_TD_COSQ_DROP_LIMIT_ALPHA_2;
   7284         break;
   7285     case bcmCosqControlDropLimitAlpha_4:
   7286         alpha = SOC_TD_COSQ_DROP_LIMIT_ALPHA_4;
   7287         break;
   7288     case bcmCosqControlDropLimitAlpha_8:
   7289         alpha = SOC_TD_COSQ_DROP_LIMIT_ALPHA_8;
   7290         break;         
   7291     default:
   7292         return BCM_E_PARAM;          
   7293     }
   7294 
   7295     si = &SOC_INFO(unit);
   7296 
   7297     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   7298         BCM_IF_ERROR_RETURN
   7299                 (_bcm_td_cosq_dynamic_thresh_enable_get(unit, gport, cosq, 
   7300                                    bcmCosqControlEgressUCSharedDynamicEnable, 
   7301                                    &dynamic_thresh_mode));
   7302         if (!dynamic_thresh_mode){
   7303             return BCM_E_CONFIG;
   7304         }
   7305     
   7306         BCM_IF_ERROR_RETURN
   7307             (_bcm_td_cosq_index_resolve(unit, gport, cosq,
   7308                                      _BCM_TD_COSQ_INDEX_STYLE_UCAST_QUEUE,
   7309                                      &local_port, &startq, NULL));
   7310         BCM_IF_ERROR_RETURN
   7311             (_bcm_td_cosq_node_get(unit, gport, NULL, NULL, &id, NULL));
   7312         if (id < _BCM_TD_NUM_UCAST_QUEUE_GROUP) {
   7313              /* regular unicast queue */
   7314             if (SOC_PBMP_MEMBER(si->xpipe_pbm, local_port)) { /* X pipe */
   7315                 mem = MMU_THDO_CONFIG_0m;
   7316             } else { /* Y pipe */
   7317                 mem = MMU_THDO_CONFIG_1m;
   7318             }           
   7319         } else {
   7320             /* extended unicast queue */
   7321             if (SOC_PBMP_MEMBER(si->xpipe_pbm, local_port)) { /* X pipe */
   7322                 mem = MMU_THDO_CONFIG_EX_0m;
   7323             } else { /* Y pipe */
   7324                 mem = MMU_THDO_CONFIG_EX_1m;
   7325             }
   7326         } 
   7327         BCM_IF_ERROR_RETURN
   7328             (soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
   7329         soc_mem_field32_set(unit, mem, entry, 
   7330                             Q_SHARED_ALPHA_CELLf, alpha);
   7331         SOC_IF_ERROR_RETURN
   7332             (soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry));
   7333         
   7334     } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   7335         BCM_IF_ERROR_RETURN
   7336                 (_bcm_td_cosq_dynamic_thresh_enable_get(unit, gport, cosq, 
   7337                                    bcmCosqControlEgressMCSharedDynamicEnable, 
   7338                                    &dynamic_thresh_mode));
   7339         if (!dynamic_thresh_mode){
   7340             return BCM_E_CONFIG;
   7341         }
   7342         
   7343         BCM_IF_ERROR_RETURN
   7344             (_bcm_td_cosq_index_resolve(unit, gport, cosq,
   7345                                      _BCM_TD_COSQ_INDEX_STYLE_MCAST_QUEUE,
   7346                                      &local_port, &startq, NULL));
   7347         BCM_IF_ERROR_RETURN
   7348             (READ_OP_QUEUE_CONFIG_CELLr(unit, local_port, cosq, &rval));
   7349         soc_reg_field_set(unit, OP_QUEUE_CONFIG_CELLr, &rval,
   7350                           Q_SHARED_ALPHA_CELLf, alpha);
   7351         BCM_IF_ERROR_RETURN
   7352             (WRITE_OP_QUEUE_CONFIG_CELLr(unit, local_port, cosq, rval));  
   7353         
   7354     } else {
   7355         BCM_IF_ERROR_RETURN
   7356                 (_bcm_td_cosq_dynamic_thresh_enable_get(unit, gport, cosq, 
   7357                                bcmCosqControlIngressPortPGSharedDynamicEnable,
   7358                                &dynamic_thresh_mode));
   7359         if (!dynamic_thresh_mode){
   7360             return BCM_E_CONFIG;
   7361         }
   7362         
   7363         BCM_IF_ERROR_RETURN
   7364             (_bcm_td_cosq_localport_resolve(unit, gport, &local_port));
   7365         if (local_port < 0) {
   7366             return BCM_E_PORT;
   7367         }
   7368         
   7369         /* get PG for port using Port+Cos */
   7370         if (cosq < 8) {
   7371             reg = prigroup_reg[0];
   7372         } else {
   7373             reg = prigroup_reg[1];
   7374         }
   7375 
   7376         SOC_IF_ERROR_RETURN
   7377             (soc_reg32_get(unit, reg, local_port, 0, &rval));
   7378         port_pg = soc_reg_field_get(unit, reg, rval, prigroup_field[cosq]);
   7379         
   7380         SOC_IF_ERROR_RETURN
   7381             (READ_PG_SHARED_LIMIT_CELLr(unit, local_port, port_pg, &rval));
   7382         soc_reg_field_set(unit, PG_SHARED_LIMIT_CELLr, &rval,
   7383                           PG_SHARED_LIMITf, alpha);
   7384         SOC_IF_ERROR_RETURN
   7385             (WRITE_PG_SHARED_LIMIT_CELLr(unit, local_port, port_pg, rval));        
   7386     }   
   7387      
   7388     return BCM_E_NONE;
   7389 }
   7390 
   7391 STATIC int
   7392 _bcm_td_cosq_alpha_get(int unit, 
   7393                         bcm_gport_t gport, bcm_cos_queue_t cosq, 
   7394                         bcm_cosq_control_drop_limit_alpha_value_t *arg)
   7395 {
   7396     bcm_port_t local_port;
   7397     int id,startq;
   7398     uint32 entry[SOC_MAX_MEM_WORDS];
   7399     soc_mem_t mem = INVALIDm;
   7400     soc_info_t *si;  
   7401     int alpha;
   7402     uint32 rval;    
   7403     int dynamic_thresh_mode;
   7404     int port_pg;
   7405     soc_reg_t reg = INVALIDr;    
   7406     static const soc_reg_t prigroup_reg[] = {
   7407         PORT_PRI_GRP0r, PORT_PRI_GRP1r
   7408     };
   7409     static const soc_field_t prigroup_field[] = {
   7410         PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf,
   7411         PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf,
   7412         PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf,
   7413         PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf
   7414     };     
   7415 
   7416     si = &SOC_INFO(unit);
   7417 
   7418     if (!arg) {
   7419         return BCM_E_PARAM;
   7420     }
   7421 
   7422     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   7423         BCM_IF_ERROR_RETURN
   7424                 (_bcm_td_cosq_dynamic_thresh_enable_get(unit, gport, cosq, 
   7425                                    bcmCosqControlEgressUCSharedDynamicEnable, 
   7426                                    &dynamic_thresh_mode));
   7427         if (!dynamic_thresh_mode){
   7428             return BCM_E_CONFIG;
   7429         }
   7430         
   7431         BCM_IF_ERROR_RETURN
   7432             (_bcm_td_cosq_index_resolve(unit, gport, cosq,
   7433                                      _BCM_TD_COSQ_INDEX_STYLE_UCAST_QUEUE,
   7434                                      &local_port, &startq, NULL));
   7435         BCM_IF_ERROR_RETURN
   7436             (_bcm_td_cosq_node_get(unit, gport, NULL, NULL, &id, NULL));
   7437         if (id < _BCM_TD_NUM_UCAST_QUEUE_GROUP) {
   7438              /* regular unicast queue */
   7439             if (SOC_PBMP_MEMBER(si->xpipe_pbm, local_port)) { /* X pipe */
   7440                 mem = MMU_THDO_CONFIG_0m;
   7441             } else { /* Y pipe */
   7442                 mem = MMU_THDO_CONFIG_1m;
   7443             }           
   7444         } else {
   7445             /* extended unicast queue */
   7446             if (SOC_PBMP_MEMBER(si->xpipe_pbm, local_port)) { /* X pipe */
   7447                 mem = MMU_THDO_CONFIG_EX_0m;
   7448             } else { /* Y pipe */
   7449                 mem = MMU_THDO_CONFIG_EX_1m;
   7450             }
   7451         }      
   7452         BCM_IF_ERROR_RETURN
   7453             (soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
   7454         alpha = soc_mem_field32_get(unit, mem, entry, Q_SHARED_ALPHA_CELLf);
   7455         
   7456     } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   7457         BCM_IF_ERROR_RETURN
   7458                 (_bcm_td_cosq_dynamic_thresh_enable_get(unit, gport, cosq, 
   7459                                    bcmCosqControlEgressMCSharedDynamicEnable, 
   7460                                    &dynamic_thresh_mode));
   7461         if (!dynamic_thresh_mode){
   7462             return BCM_E_CONFIG;
   7463         }
   7464         
   7465         BCM_IF_ERROR_RETURN
   7466             (_bcm_td_cosq_index_resolve(unit, gport, cosq,
   7467                                      _BCM_TD_COSQ_INDEX_STYLE_MCAST_QUEUE,
   7468                                      &local_port, &startq, NULL));
   7469         BCM_IF_ERROR_RETURN
   7470             (READ_OP_QUEUE_CONFIG_CELLr(unit, local_port, cosq, &rval));
   7471         alpha = soc_reg_field_get(unit, OP_QUEUE_CONFIG_CELLr, rval,
   7472                                   Q_SHARED_ALPHA_CELLf);   
   7473         
   7474     } else {
   7475         BCM_IF_ERROR_RETURN
   7476                 (_bcm_td_cosq_dynamic_thresh_enable_get(unit, gport, cosq, 
   7477                                bcmCosqControlIngressPortPGSharedDynamicEnable,
   7478                                &dynamic_thresh_mode));
   7479         if (!dynamic_thresh_mode){
   7480             return BCM_E_CONFIG;
   7481         }
   7482         
   7483         BCM_IF_ERROR_RETURN
   7484             (_bcm_td_cosq_localport_resolve(unit, gport, &local_port));
   7485         if (local_port < 0) {
   7486             return BCM_E_PORT;
   7487         }
   7488         
   7489         /* get PG for port using Port+Cos */
   7490         if (cosq < 8) {
   7491             reg = prigroup_reg[0];
   7492         } else {
   7493             reg = prigroup_reg[1];
   7494         }
   7495 
   7496         SOC_IF_ERROR_RETURN
   7497             (soc_reg32_get(unit, reg, local_port, 0, &rval));
   7498         port_pg = soc_reg_field_get(unit, reg, rval, prigroup_field[cosq]);
   7499         
   7500         SOC_IF_ERROR_RETURN
   7501             (READ_PG_SHARED_LIMIT_CELLr(unit, local_port, port_pg, &rval));
   7502         alpha = soc_reg_field_get(unit, PG_SHARED_LIMIT_CELLr, rval,
   7503                                  PG_SHARED_LIMITf);         
   7504     } 
   7505     
   7506     switch(alpha) {
   7507     case SOC_TD_COSQ_DROP_LIMIT_ALPHA_1_64:
   7508         *arg = bcmCosqControlDropLimitAlpha_1_64;
   7509         break;
   7510     case SOC_TD_COSQ_DROP_LIMIT_ALPHA_1_32:
   7511         *arg = bcmCosqControlDropLimitAlpha_1_32;
   7512         break;
   7513     case SOC_TD_COSQ_DROP_LIMIT_ALPHA_1_16:
   7514         *arg = bcmCosqControlDropLimitAlpha_1_16;
   7515         break;
   7516     case SOC_TD_COSQ_DROP_LIMIT_ALPHA_1_8:
   7517         *arg = bcmCosqControlDropLimitAlpha_1_8;
   7518         break;
   7519     case SOC_TD_COSQ_DROP_LIMIT_ALPHA_1_4:
   7520         *arg = bcmCosqControlDropLimitAlpha_1_4;
   7521         break;
   7522     case SOC_TD_COSQ_DROP_LIMIT_ALPHA_1_2:
   7523         *arg = bcmCosqControlDropLimitAlpha_1_2;
   7524         break;
   7525     case SOC_TD_COSQ_DROP_LIMIT_ALPHA_1:
   7526         *arg = bcmCosqControlDropLimitAlpha_1;
   7527         break;   
   7528     case SOC_TD_COSQ_DROP_LIMIT_ALPHA_2:
   7529         *arg = bcmCosqControlDropLimitAlpha_2;
   7530         break;
   7531     case SOC_TD_COSQ_DROP_LIMIT_ALPHA_4:
   7532         *arg = bcmCosqControlDropLimitAlpha_4;
   7533         break;
   7534     case SOC_TD_COSQ_DROP_LIMIT_ALPHA_8:
   7535         *arg = bcmCosqControlDropLimitAlpha_8;
   7536         break;         
   7537     default:
   7538         return BCM_E_PARAM;          
   7539     }
   7540 
   7541     return BCM_E_NONE;
   7542 }
   7543 
   7544 STATIC int
   7545 _bcm_td_cosq_dynamic_thresh_enable_set(int unit, 
   7546                         bcm_gport_t gport, bcm_cos_queue_t cosq,
   7547                         bcm_cosq_control_t type, int arg)
   7548 {
   7549     bcm_port_t local_port;
   7550     int id,startq;
   7551     uint32 entry[SOC_MAX_MEM_WORDS];
   7552     soc_mem_t mem = INVALIDm;
   7553     soc_info_t *si;  
   7554     uint32 rval;
   7555     int port_pg;
   7556     soc_reg_t reg = INVALIDr;    
   7557     static const soc_reg_t prigroup_reg[] = {
   7558         PORT_PRI_GRP0r, PORT_PRI_GRP1r
   7559     };
   7560     static const soc_field_t prigroup_field[] = {
   7561         PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf,
   7562         PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf,
   7563         PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf,
   7564         PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf
   7565     };    
   7566 
   7567     si = &SOC_INFO(unit);
   7568 
   7569     if (type == bcmCosqControlIngressPortPGSharedDynamicEnable) {
   7570         BCM_IF_ERROR_RETURN
   7571             (_bcm_td_cosq_localport_resolve(unit, gport, &local_port));
   7572         if (local_port < 0) {
   7573             return BCM_E_PORT;
   7574         }
   7575         if ((cosq < 0) || (cosq >= 16)) {
   7576             return BCM_E_PARAM;
   7577         }
   7578         
   7579         /* get PG for port using Port+Cos */
   7580         if (cosq < 8) {
   7581             reg = prigroup_reg[0];
   7582         } else {
   7583             reg = prigroup_reg[1];
   7584         }
   7585 
   7586         SOC_IF_ERROR_RETURN
   7587             (soc_reg32_get(unit, reg, local_port, 0, &rval));
   7588         port_pg = soc_reg_field_get(unit, reg, rval, prigroup_field[cosq]);
   7589         
   7590         SOC_IF_ERROR_RETURN
   7591             (READ_PG_SHARED_LIMIT_CELLr(unit, local_port, port_pg, &rval));
   7592         soc_reg_field_set(unit, PG_SHARED_LIMIT_CELLr, &rval,
   7593                           PG_SHARED_DYNAMICf, arg ? 1 : 0);
   7594         SOC_IF_ERROR_RETURN
   7595             (WRITE_PG_SHARED_LIMIT_CELLr(unit, local_port, port_pg, rval));        
   7596     } else if (type == bcmCosqControlEgressUCSharedDynamicEnable) {
   7597         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   7598             BCM_IF_ERROR_RETURN
   7599                 (_bcm_td_cosq_index_resolve(unit, gport, cosq,
   7600                                          _BCM_TD_COSQ_INDEX_STYLE_UCAST_QUEUE,
   7601                                          &local_port, &startq, NULL));
   7602 
   7603             BCM_IF_ERROR_RETURN
   7604                 (_bcm_td_cosq_node_get(unit, gport, NULL, NULL, &id, NULL));
   7605             if (id < _BCM_TD_NUM_UCAST_QUEUE_GROUP) {
   7606                  /* regular unicast queue */
   7607                 if (SOC_PBMP_MEMBER(si->xpipe_pbm, local_port)) { /* X pipe */
   7608                     mem = MMU_THDO_CONFIG_0m;
   7609                 } else { /* Y pipe */
   7610                     mem = MMU_THDO_CONFIG_1m;
   7611                 }           
   7612             } else {
   7613                 /* extended unicast queue */
   7614                 if (SOC_PBMP_MEMBER(si->xpipe_pbm, local_port)) { /* X pipe */
   7615                     mem = MMU_THDO_CONFIG_EX_0m;
   7616                 } else { /* Y pipe */
   7617                     mem = MMU_THDO_CONFIG_EX_1m;
   7618                 }
   7619             }
   7620             BCM_IF_ERROR_RETURN
   7621                 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
   7622             soc_mem_field32_set(unit, mem, entry, 
   7623                                 Q_LIMIT_DYNAMIC_CELLf, arg ? 1 : 0);
   7624             SOC_IF_ERROR_RETURN
   7625                 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry));
   7626             
   7627         } else {
   7628             return BCM_E_PARAM;
   7629         }       
   7630     } else if (type == bcmCosqControlEgressMCSharedDynamicEnable) {
   7631         if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   7632             BCM_IF_ERROR_RETURN
   7633                 (_bcm_td_cosq_index_resolve(unit, gport, cosq,
   7634                                          _BCM_TD_COSQ_INDEX_STYLE_MCAST_QUEUE,
   7635                                          &local_port, &startq, NULL));
   7636             BCM_IF_ERROR_RETURN
   7637                 (READ_OP_QUEUE_CONFIG1_CELLr(unit, local_port, cosq, &rval));
   7638             soc_reg_field_set(unit, OP_QUEUE_CONFIG1_CELLr, &rval,
   7639                               Q_LIMIT_DYNAMIC_CELLf, arg ? 1 : 0);
   7640             BCM_IF_ERROR_RETURN
   7641                 (WRITE_OP_QUEUE_CONFIG1_CELLr(unit, local_port, cosq, rval));
   7642 
   7643         } else {
   7644             return BCM_E_PARAM;
   7645         }      
   7646        
   7647     } else {
   7648         return BCM_E_PARAM;
   7649     }
   7650 
   7651     /* Set default alpha value*/
   7652     if (arg) {
   7653         BCM_IF_ERROR_RETURN
   7654             (_bcm_td_cosq_alpha_set(unit, gport, cosq, 
   7655                                     bcmCosqControlDropLimitAlpha_1_64));
   7656     }
   7657     
   7658     return BCM_E_NONE;
   7659 }
   7660 
   7661 STATIC int
   7662 _bcm_td_cosq_dynamic_thresh_enable_get(int unit, 
   7663                         bcm_gport_t gport, bcm_cos_queue_t cosq, 
   7664                         bcm_cosq_control_t type, int *arg)
   7665 {
   7666     bcm_port_t local_port;
   7667     int id,startq;
   7668     uint32 entry[SOC_MAX_MEM_WORDS];
   7669     soc_mem_t mem = INVALIDm;
   7670     soc_info_t *si;
   7671     uint32 rval;
   7672     int port_pg;
   7673     soc_reg_t reg = INVALIDr;    
   7674     static const soc_reg_t prigroup_reg[] = {
   7675         PORT_PRI_GRP0r, PORT_PRI_GRP1r
   7676     };
   7677     static const soc_field_t prigroup_field[] = {
   7678         PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf,
   7679         PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf,
   7680         PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf,
   7681         PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf
   7682     };     
   7683     
   7684     si = &SOC_INFO(unit);
   7685 
   7686     if (type == bcmCosqControlIngressPortPGSharedDynamicEnable) {
   7687         BCM_IF_ERROR_RETURN
   7688             (_bcm_td_cosq_localport_resolve(unit, gport, &local_port));
   7689         if (local_port < 0) {
   7690             return BCM_E_PORT;
   7691         }
   7692         if ((cosq < 0) || (cosq >= 16)) {
   7693             return BCM_E_PARAM;
   7694         }
   7695         
   7696         /* get PG for port using Port+Cos */
   7697         if (cosq < 8) {
   7698             reg = prigroup_reg[0];
   7699         } else {
   7700             reg = prigroup_reg[1];
   7701         }
   7702 
   7703         SOC_IF_ERROR_RETURN
   7704             (soc_reg32_get(unit, reg, local_port, 0, &rval));
   7705         port_pg = soc_reg_field_get(unit, reg, rval, prigroup_field[cosq]);
   7706         
   7707         SOC_IF_ERROR_RETURN
   7708             (READ_PG_SHARED_LIMIT_CELLr(unit, local_port, port_pg, &rval));
   7709         *arg = soc_reg_field_get(unit, PG_SHARED_LIMIT_CELLr, rval,
   7710                                  PG_SHARED_DYNAMICf);         
   7711     } else if (type == bcmCosqControlEgressUCSharedDynamicEnable) {
   7712         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   7713             BCM_IF_ERROR_RETURN
   7714                 (_bcm_td_cosq_index_resolve(unit, gport, cosq,
   7715                                          _BCM_TD_COSQ_INDEX_STYLE_UCAST_QUEUE,
   7716                                          &local_port, &startq, NULL));
   7717 
   7718             BCM_IF_ERROR_RETURN
   7719                 (_bcm_td_cosq_node_get(unit, gport, NULL, NULL, &id, NULL));
   7720             if (id < _BCM_TD_NUM_UCAST_QUEUE_GROUP) {
   7721                  /* regular unicast queue */
   7722                 if (SOC_PBMP_MEMBER(si->xpipe_pbm, local_port)) { /* X pipe */
   7723                     mem = MMU_THDO_CONFIG_0m;
   7724                 } else { /* Y pipe */
   7725                     mem = MMU_THDO_CONFIG_1m;
   7726                 }           
   7727             } else {
   7728                 /* extended unicast queue */
   7729                 if (SOC_PBMP_MEMBER(si->xpipe_pbm, local_port)) { /* X pipe */
   7730                     mem = MMU_THDO_CONFIG_EX_0m;
   7731                 } else { /* Y pipe */
   7732                     mem = MMU_THDO_CONFIG_EX_1m;
   7733                 }
   7734             }
   7735             BCM_IF_ERROR_RETURN
   7736                 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
   7737             *arg = soc_mem_field32_get(unit, mem, entry, Q_LIMIT_DYNAMIC_CELLf);
   7738     
   7739         } else {
   7740             return BCM_E_PARAM;
   7741         }       
   7742     } else if (type == bcmCosqControlEgressMCSharedDynamicEnable) {
   7743         if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   7744             BCM_IF_ERROR_RETURN
   7745                 (_bcm_td_cosq_index_resolve(unit, gport, cosq,
   7746                                          _BCM_TD_COSQ_INDEX_STYLE_MCAST_QUEUE,
   7747                                          &local_port, &startq, NULL));
   7748             BCM_IF_ERROR_RETURN
   7749                 (READ_OP_QUEUE_CONFIG1_CELLr(unit, local_port, cosq, &rval));
   7750             *arg = soc_reg_field_get(unit, OP_QUEUE_CONFIG1_CELLr, rval,
   7751                                      Q_LIMIT_DYNAMIC_CELLf); 
   7752 
   7753         } else {
   7754             return BCM_E_PARAM;
   7755         }       
   7756     } else {
   7757         return BCM_E_PARAM;
   7758     }
   7759     
   7760     return BCM_E_NONE;
   7761 }
   7762 
   7763 STATIC int
   7764 _bcm_td_cosq_egr_queue_set(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
   7765                             bcm_cosq_control_t type, int arg)
   7766 {
   7767     bcm_port_t local_port;
   7768     int id, startq;
   7769     uint32 entry[SOC_MAX_MEM_WORDS];
   7770     soc_mem_t mem = INVALIDm;
   7771     soc_info_t *si;
   7772     int granularity = 1;
   7773     uint32 rval, rval2;
   7774     int phy_port, mmu_port;
   7775 
   7776     if (arg < 0) {
   7777         return BCM_E_PARAM;
   7778     }
   7779 
   7780     si = &SOC_INFO(unit);
   7781 
   7782     arg /= _BCM_TD_BYTES_PER_CELL;
   7783 
   7784     if ((type == bcmCosqControlEgressUCQueueMinLimitBytes) ||
   7785         (type == bcmCosqControlEgressUCQueueSharedLimitBytes)) {
   7786         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   7787             BCM_IF_ERROR_RETURN
   7788                 (_bcm_td_cosq_index_resolve(unit, gport, cosq,
   7789                                              _BCM_TD_COSQ_INDEX_STYLE_UCAST_QUEUE,
   7790                                              &local_port, NULL, NULL));
   7791             BCM_IF_ERROR_RETURN
   7792                 (_bcm_td_cosq_node_get(unit, gport, NULL, NULL, &id, NULL));
   7793         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   7794             return BCM_E_PARAM;
   7795         } else {
   7796             if (cosq == BCM_COS_INVALID) {
   7797                 return BCM_E_PARAM;
   7798             }
   7799             BCM_IF_ERROR_RETURN
   7800                 (_bcm_td_cosq_localport_resolve(unit, gport, &local_port));
   7801             if (local_port < 0) {
   7802                 return BCM_E_PORT;
   7803             }
   7804             id = cosq;
   7805         }
   7806 
   7807         phy_port = si->port_l2p_mapping[local_port];
   7808         mmu_port = si->port_p2m_mapping[phy_port];
   7809 
   7810         /* regular unicast queue */
   7811         if (si->port_num_ext_cosq[local_port] == 0) {
   7812             /* Front-panel ports */
   7813             if (SOC_PBMP_MEMBER(si->xpipe_pbm, local_port)) { /* X pipe */
   7814                 mem = MMU_THDO_CONFIG_0m;
   7815                 startq = (mmu_port - 5) * 10 + id;
   7816             } else { /* Y pipe */
   7817                 mem = MMU_THDO_CONFIG_1m;
   7818                 startq = (mmu_port - 38) * 10 + id;
   7819             }
   7820         } else {
   7821             /* extended queue ports:
   7822              *   use MMU_THDO_CONFIG_EX_x table, 74 entries per port
   7823              *   extended unicast queues: index 0-63
   7824              *   regular unicast queue: index 64-73
   7825              */
   7826             if (SOC_PBMP_MEMBER(si->xpipe_pbm, local_port)) { /* X pipe */
   7827                 mem = MMU_THDO_CONFIG_EX_0m;
   7828                 startq = (mmu_port - 1) * 74 + 64 + id;
   7829             } else { /* Y pipe */
   7830                 mem = MMU_THDO_CONFIG_EX_1m;
   7831                 startq = (mmu_port - 34) * 74 + 64 + id;
   7832             }
   7833         }
   7834 
   7835         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
   7836 
   7837         if (type == bcmCosqControlEgressUCQueueSharedLimitBytes) {
   7838             soc_mem_field32_set(unit, mem, entry, Q_SHARED_LIMIT_CELLf, (arg/granularity));
   7839             soc_mem_field32_set(unit, mem, entry, Q_LIMIT_ENABLE_CELLf, 1);
   7840             soc_mem_field32_set(unit, mem, entry, Q_LIMIT_DYNAMIC_CELLf, 0);
   7841         } else {
   7842             soc_mem_field32_set(unit, mem, entry, Q_MIN_CELLf, (arg/granularity));
   7843         }
   7844 
   7845         BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry));
   7846     } else if ((type == bcmCosqControlEgressMCQueueMinLimitBytes) ||
   7847                (type == bcmCosqControlEgressMCQueueSharedLimitBytes)) {
   7848         if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   7849             if (cosq != BCM_COS_INVALID) {
   7850                 return BCM_E_PARAM;
   7851             }
   7852             BCM_IF_ERROR_RETURN
   7853                 (_bcm_td_cosq_index_resolve(unit, gport, cosq,
   7854                                          _BCM_TD_COSQ_INDEX_STYLE_MCAST_QUEUE,
   7855                                          &local_port, &startq, NULL));
   7856         } else if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   7857             return BCM_E_PARAM;
   7858         } else {
   7859             if (cosq == BCM_COS_INVALID) {
   7860                 return BCM_E_PARAM;
   7861             }
   7862             BCM_IF_ERROR_RETURN
   7863                 (_bcm_td_cosq_localport_resolve(unit, gport, &local_port));
   7864             if (local_port < 0) {
   7865                 return BCM_E_PORT;
   7866             }
   7867             startq = cosq;
   7868         }
   7869         BCM_IF_ERROR_RETURN
   7870             (READ_OP_QUEUE_CONFIG_CELLr(unit, local_port, startq, &rval));
   7871         if (type == bcmCosqControlEgressMCQueueSharedLimitBytes) {
   7872             soc_reg_field_set(unit, OP_QUEUE_CONFIG_CELLr, &rval,
   7873                               Q_SHARED_LIMIT_CELLf, arg/granularity);
   7874 
   7875             /* enable the queue discard thresholds */
   7876             BCM_IF_ERROR_RETURN
   7877                 (READ_OP_QUEUE_CONFIG1_CELLr(unit, local_port, startq, &rval2));
   7878             soc_reg_field_set(unit,OP_QUEUE_CONFIG1_CELLr, &rval2,
   7879                                     Q_LIMIT_ENABLE_CELLf, 1);
   7880             soc_reg_field_set(unit,OP_QUEUE_CONFIG1_CELLr, &rval2,
   7881                                     Q_LIMIT_DYNAMIC_CELLf, 0);
   7882             BCM_IF_ERROR_RETURN
   7883                 (WRITE_OP_QUEUE_CONFIG1_CELLr(unit, local_port, startq, rval2));
   7884         } else {
   7885             soc_reg_field_set(unit, OP_QUEUE_CONFIG_CELLr, &rval,
   7886                               Q_MIN_CELLf, arg/granularity);
   7887         }
   7888         BCM_IF_ERROR_RETURN
   7889             (WRITE_OP_QUEUE_CONFIG_CELLr(unit, local_port, startq, rval));
   7890     }else {
   7891         return BCM_E_PARAM;
   7892     }
   7893     return BCM_E_NONE;
   7894 }
   7895 
   7896 STATIC int
   7897 _bcm_td_cosq_egr_queue_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
   7898                             bcm_cosq_control_t type, int *arg)
   7899 {
   7900     bcm_port_t local_port;
   7901     int id, startq;
   7902     uint32 entry[SOC_MAX_MEM_WORDS];
   7903     soc_mem_t mem = INVALIDm;
   7904     soc_info_t *si;
   7905     int granularity = 1;
   7906     uint32 rval;
   7907     int phy_port, mmu_port;
   7908 
   7909     if (arg == NULL) {
   7910         return BCM_E_PARAM;
   7911     }
   7912 
   7913     si = &SOC_INFO(unit);
   7914 
   7915     if ((type == bcmCosqControlEgressUCQueueMinLimitBytes) ||
   7916         (type == bcmCosqControlEgressUCQueueSharedLimitBytes)) {
   7917         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   7918             BCM_IF_ERROR_RETURN
   7919                 (_bcm_td_cosq_index_resolve(unit, gport, cosq,
   7920                                              _BCM_TD_COSQ_INDEX_STYLE_UCAST_QUEUE,
   7921                                              &local_port, NULL, NULL));
   7922             BCM_IF_ERROR_RETURN(_bcm_td_cosq_node_get(unit, gport, NULL, NULL, &id, NULL));
   7923         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   7924             return BCM_E_PARAM;
   7925         } else {
   7926             if (cosq == BCM_COS_INVALID) {
   7927                 return BCM_E_PARAM;
   7928             }
   7929             BCM_IF_ERROR_RETURN
   7930                 (_bcm_td_cosq_localport_resolve(unit, gport, &local_port));
   7931             if (local_port < 0) {
   7932                 return BCM_E_PORT;
   7933             }
   7934             id = cosq;
   7935         }
   7936 
   7937         phy_port = si->port_l2p_mapping[local_port];
   7938         mmu_port = si->port_p2m_mapping[phy_port];
   7939 
   7940         /* regular unicast queue */
   7941         if (si->port_num_ext_cosq[local_port] == 0) {
   7942             /* Front-panel ports */
   7943             if (SOC_PBMP_MEMBER(si->xpipe_pbm, local_port)) { /* X pipe */
   7944                 mem = MMU_THDO_CONFIG_0m;
   7945                 startq = (mmu_port - 5) * 10 + id;
   7946             } else { /* Y pipe */
   7947                 mem = MMU_THDO_CONFIG_1m;
   7948                 startq = (mmu_port - 38) * 10 + id;
   7949             }
   7950         } else {
   7951             /* extended queue ports
   7952              *     use MMU_THDO_CONFIG_EX_x table, 74 entries per port
   7953              *     extended unicast queues: index 0-63
   7954              *     regular unicast queue: index 64-73
   7955              */
   7956             if (SOC_PBMP_MEMBER(si->xpipe_pbm, local_port)) { /* X pipe */
   7957                 mem = MMU_THDO_CONFIG_EX_0m;
   7958                 startq = (mmu_port - 1) * 74 + 64 + id;
   7959             } else { /* Y pipe */
   7960                 mem = MMU_THDO_CONFIG_EX_1m;
   7961                 startq = (mmu_port - 34) * 74 + 64 + id;
   7962             }
   7963         }
   7964 
   7965         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
   7966         if (type == bcmCosqControlEgressUCQueueSharedLimitBytes) {
   7967             *arg = soc_mem_field32_get(unit, mem, entry, Q_SHARED_LIMIT_CELLf);
   7968         } else {
   7969             *arg = soc_mem_field32_get(unit, mem, entry, Q_MIN_CELLf);
   7970         }
   7971     } else if ((type == bcmCosqControlEgressMCQueueMinLimitBytes) ||
   7972                (type == bcmCosqControlEgressMCQueueSharedLimitBytes)) {
   7973         if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   7974             if (cosq != BCM_COS_INVALID) {
   7975                 return BCM_E_PARAM;
   7976             }
   7977             BCM_IF_ERROR_RETURN
   7978                 (_bcm_td_cosq_index_resolve(unit, gport, cosq,
   7979                                          _BCM_TD_COSQ_INDEX_STYLE_MCAST_QUEUE,
   7980                                          &local_port, &startq, NULL));
   7981         } else if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   7982             return BCM_E_PARAM;
   7983         } else {
   7984             if (cosq == BCM_COS_INVALID) {
   7985                 return BCM_E_PARAM;
   7986             }
   7987             BCM_IF_ERROR_RETURN
   7988                 (_bcm_td_cosq_localport_resolve(unit, gport, &local_port));
   7989             if (local_port < 0) {
   7990                 return BCM_E_PORT;
   7991             }
   7992             startq = cosq;
   7993         }
   7994         BCM_IF_ERROR_RETURN
   7995             (READ_OP_QUEUE_CONFIG_CELLr(unit, local_port, startq, &rval));
   7996         if (type == bcmCosqControlEgressMCQueueMinLimitBytes) {
   7997             *arg = soc_reg_field_get(unit, OP_QUEUE_CONFIG_CELLr, rval,
   7998                                      Q_MIN_CELLf);
   7999         } else {
   8000             *arg = soc_reg_field_get(unit, OP_QUEUE_CONFIG_CELLr, rval,
   8001                                      Q_SHARED_LIMIT_CELLf);
   8002         }
   8003     }else {
   8004         return BCM_E_PARAM;
   8005     }
   8006 
   8007     *arg = (*arg) * granularity * _BCM_TD_BYTES_PER_CELL;
   8008     return BCM_E_NONE;
   8009 }
   8010 
   8011 STATIC int
   8012 _bcm_td_cosq_egr_queue_limit_enable_set(int unit, bcm_gport_t gport,
   8013                                                 bcm_cos_queue_t cosq,
   8014                                                 bcm_cosq_control_t type,
   8015                                                 int arg)
   8016 {
   8017     bcm_port_t local_port;
   8018     int id, startq;
   8019     uint32 entry[SOC_MAX_MEM_WORDS];
   8020     soc_mem_t mem = INVALIDm;
   8021     soc_info_t *si;
   8022     uint32 rval;
   8023     int phy_port, mmu_port;
   8024 
   8025     if (arg < 0) {
   8026         return BCM_E_PARAM;
   8027     }
   8028 
   8029     si = &SOC_INFO(unit);
   8030     arg = arg ? 1 : 0;
   8031 
   8032     if (type == bcmCosqControlEgressUCQueueLimitEnable) {
   8033         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   8034             BCM_IF_ERROR_RETURN
   8035                 (_bcm_td_cosq_index_resolve(unit, gport, cosq,
   8036                                              _BCM_TD_COSQ_INDEX_STYLE_UCAST_QUEUE,
   8037                                              &local_port, NULL, NULL));
   8038             BCM_IF_ERROR_RETURN(_bcm_td_cosq_node_get(unit, gport, NULL, NULL, &id, NULL));
   8039         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   8040             return BCM_E_PARAM;
   8041         } else {
   8042             if (cosq == BCM_COS_INVALID) {
   8043                 return BCM_E_PARAM;
   8044             }
   8045             BCM_IF_ERROR_RETURN
   8046                 (_bcm_td_cosq_localport_resolve(unit, gport, &local_port));
   8047             if (local_port < 0) {
   8048                 return BCM_E_PORT;
   8049             }
   8050             id = cosq;
   8051         }
   8052 
   8053         phy_port = si->port_l2p_mapping[local_port];
   8054         mmu_port = si->port_p2m_mapping[phy_port];
   8055 
   8056         /* regular unicast queue */
   8057         if (si->port_num_ext_cosq[local_port] == 0) {
   8058             /* Front-panel ports */
   8059             if (SOC_PBMP_MEMBER(si->xpipe_pbm, local_port)) { /* X pipe */
   8060                 mem = MMU_THDO_CONFIG_0m;
   8061                 startq = (mmu_port - 5) * 10 + id;
   8062             } else { /* Y pipe */
   8063                 mem = MMU_THDO_CONFIG_1m;
   8064                 startq = (mmu_port - 38) * 10 + id;
   8065             }
   8066         } else {
   8067             /* extended queue ports
   8068              *     use MMU_THDO_CONFIG_EX_x table, 74 entries per port
   8069              *     extended unicast queues: index 0-63
   8070              *     regular unicast queue: index 64-73
   8071              */
   8072             if (SOC_PBMP_MEMBER(si->xpipe_pbm, local_port)) { /* X pipe */
   8073                 mem = MMU_THDO_CONFIG_EX_0m;
   8074                 startq = (mmu_port - 1) * 74 + 64 + id;
   8075             } else { /* Y pipe */
   8076                 mem = MMU_THDO_CONFIG_EX_1m;
   8077                 startq = (mmu_port - 34) * 74 + 64 + id;
   8078             }
   8079         }
   8080 
   8081         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
   8082         soc_mem_field32_set(unit, mem, entry, Q_LIMIT_ENABLE_CELLf, arg);
   8083         BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry));
   8084     } else if (type == bcmCosqControlEgressMCQueueLimitEnable) {
   8085         if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   8086             if (cosq != BCM_COS_INVALID) {
   8087                 return BCM_E_PARAM;
   8088             }
   8089             BCM_IF_ERROR_RETURN
   8090                 (_bcm_td_cosq_index_resolve(unit, gport, cosq,
   8091                                          _BCM_TD_COSQ_INDEX_STYLE_MCAST_QUEUE,
   8092                                          &local_port, &startq, NULL));
   8093         } else if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   8094             return BCM_E_PARAM;
   8095         } else {
   8096             if (cosq == BCM_COS_INVALID) {
   8097                 return BCM_E_PARAM;
   8098             }
   8099             BCM_IF_ERROR_RETURN
   8100                 (_bcm_td_cosq_localport_resolve(unit, gport, &local_port));
   8101             if (local_port < 0) {
   8102                 return BCM_E_PORT;
   8103             }
   8104             startq = cosq;
   8105         }
   8106         /* enable the queue discard thresholds */
   8107         BCM_IF_ERROR_RETURN
   8108             (READ_OP_QUEUE_CONFIG1_CELLr(unit, local_port, startq, &rval));
   8109         soc_reg_field_set(unit,OP_QUEUE_CONFIG1_CELLr, &rval,
   8110                                 Q_LIMIT_ENABLE_CELLf, arg);
   8111         BCM_IF_ERROR_RETURN
   8112             (WRITE_OP_QUEUE_CONFIG1_CELLr(unit, local_port, startq, rval));
   8113     }else {
   8114         return BCM_E_PARAM;
   8115     }
   8116     return BCM_E_NONE;
   8117 }
   8118 
   8119 STATIC int
   8120 _bcm_td_cosq_egr_queue_limit_enable_get(int unit, bcm_gport_t gport,
   8121                                                 bcm_cos_queue_t cosq,
   8122                                                 bcm_cosq_control_t type,
   8123                                                 int *arg)
   8124 {
   8125     bcm_port_t local_port;
   8126     int id, startq;
   8127     uint32 entry[SOC_MAX_MEM_WORDS];
   8128     soc_mem_t mem = INVALIDm;
   8129     soc_info_t *si;
   8130     uint32 rval;
   8131     int phy_port, mmu_port;
   8132 
   8133     if (arg == NULL) {
   8134         return BCM_E_PARAM;
   8135     }
   8136 
   8137     si = &SOC_INFO(unit);
   8138 
   8139     if (type == bcmCosqControlEgressUCQueueLimitEnable) {
   8140         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   8141             BCM_IF_ERROR_RETURN
   8142                 (_bcm_td_cosq_index_resolve(unit, gport, cosq,
   8143                                              _BCM_TD_COSQ_INDEX_STYLE_UCAST_QUEUE,
   8144                                              &local_port, NULL, NULL));
   8145             BCM_IF_ERROR_RETURN(_bcm_td_cosq_node_get(unit, gport, NULL, NULL, &id, NULL));
   8146         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   8147             return BCM_E_PARAM;
   8148         } else {
   8149             if (cosq == BCM_COS_INVALID) {
   8150                 return BCM_E_PARAM;
   8151             }
   8152             BCM_IF_ERROR_RETURN
   8153                 (_bcm_td_cosq_localport_resolve(unit, gport, &local_port));
   8154             if (local_port < 0) {
   8155                 return BCM_E_PORT;
   8156             }
   8157             id = cosq;
   8158         }
   8159 
   8160         phy_port = si->port_l2p_mapping[local_port];
   8161         mmu_port = si->port_p2m_mapping[phy_port];
   8162 
   8163         /* regular unicast queue */
   8164         if (si->port_num_ext_cosq[local_port] == 0) {
   8165             /* Front-panel ports */
   8166             if (SOC_PBMP_MEMBER(si->xpipe_pbm, local_port)) { /* X pipe */
   8167                 mem = MMU_THDO_CONFIG_0m;
   8168                 startq = (mmu_port - 5) * 10 + id;
   8169             } else { /* Y pipe */
   8170                 mem = MMU_THDO_CONFIG_1m;
   8171                 startq = (mmu_port - 38) * 10 + id;
   8172             }
   8173         } else {
   8174             /* extended queue ports
   8175              *     use MMU_THDO_CONFIG_EX_x table, 74 entries per port
   8176              *     extended unicast queues: index 0-63
   8177              *     regular unicast queue: index 64-73
   8178              */
   8179             if (SOC_PBMP_MEMBER(si->xpipe_pbm, local_port)) { /* X pipe */
   8180                 mem = MMU_THDO_CONFIG_EX_0m;
   8181                 startq = (mmu_port - 1) * 74 + 64 + id;
   8182             } else { /* Y pipe */
   8183                 mem = MMU_THDO_CONFIG_EX_1m;
   8184                 startq = (mmu_port - 34) * 74 + 64 + id;
   8185             }
   8186         }
   8187 
   8188         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
   8189         *arg = soc_mem_field32_get(unit, mem, entry, Q_LIMIT_ENABLE_CELLf);
   8190     } else if (type == bcmCosqControlEgressMCQueueLimitEnable) {
   8191         if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   8192             if (cosq != BCM_COS_INVALID) {
   8193                 return BCM_E_PARAM;
   8194             }
   8195             BCM_IF_ERROR_RETURN
   8196                 (_bcm_td_cosq_index_resolve(unit, gport, cosq,
   8197                                          _BCM_TD_COSQ_INDEX_STYLE_MCAST_QUEUE,
   8198                                          &local_port, &startq, NULL));
   8199         } else if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   8200             return BCM_E_PARAM;
   8201         } else {
   8202             if (cosq == BCM_COS_INVALID) {
   8203                 return BCM_E_PARAM;
   8204             }
   8205             BCM_IF_ERROR_RETURN
   8206                 (_bcm_td_cosq_localport_resolve(unit, gport, &local_port));
   8207             if (local_port < 0) {
   8208                 return BCM_E_PORT;
   8209             }
   8210             startq = cosq;
   8211         }
   8212 
   8213         BCM_IF_ERROR_RETURN
   8214             (READ_OP_QUEUE_CONFIG1_CELLr(unit, local_port, startq, &rval));
   8215         *arg = soc_reg_field_get(unit, OP_QUEUE_CONFIG1_CELLr, rval,
   8216                                      Q_LIMIT_ENABLE_CELLf);
   8217     }else {
   8218         return BCM_E_PARAM;
   8219     }
   8220     return BCM_E_NONE;
   8221 }
   8222 
   8223 int
   8224 bcm_td_cosq_control_set(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
   8225                         bcm_cosq_control_t type, int arg)
   8226 {
   8227     switch (type) {
   8228     case bcmCosqControlEgressPool:
   8229     case bcmCosqControlEgressPoolLimitBytes:
   8230     case bcmCosqControlEgressPoolYellowLimitBytes:
   8231     case bcmCosqControlEgressPoolRedLimitBytes:
   8232     case bcmCosqControlEgressPoolLimitEnable:
   8233     case bcmCosqControlUCEgressPool:
   8234     case bcmCosqControlMCEgressPool:
   8235         return _bcm_td_cosq_egr_pool_set(unit, gport, cosq, type, arg);
   8236     case bcmCosqControlDropLimitAlpha:
   8237         return _bcm_td_cosq_alpha_set(unit, gport, cosq, 
   8238                             (bcm_cosq_control_drop_limit_alpha_value_t)arg);
   8239     case bcmCosqControlIngressPortPGSharedDynamicEnable:        
   8240     case bcmCosqControlEgressUCSharedDynamicEnable:
   8241     case bcmCosqControlEgressMCSharedDynamicEnable:
   8242         return _bcm_td_cosq_dynamic_thresh_enable_set(unit, gport, cosq, 
   8243                                                        type, arg);        
   8244     case bcmCosqControlEgressUCQueueSharedLimitBytes:
   8245     case bcmCosqControlEgressMCQueueSharedLimitBytes:
   8246     case bcmCosqControlEgressUCQueueMinLimitBytes:
   8247     case bcmCosqControlEgressMCQueueMinLimitBytes:
   8248         return _bcm_td_cosq_egr_queue_set(unit, gport, cosq, type, arg);
   8249     case bcmCosqControlEgressUCQueueLimitEnable:
   8250     case bcmCosqControlEgressMCQueueLimitEnable:
   8251         return _bcm_td_cosq_egr_queue_limit_enable_set(unit, gport, cosq,
   8252                                                         type, arg);
   8253 
   8254     default:
   8255         break;
   8256     }
   8257 
   8258     return BCM_E_UNAVAIL;
   8259 }
   8260 
   8261 int
   8262 bcm_td_cosq_control_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
   8263                         bcm_cosq_control_t type, int *arg)
   8264 {
   8265     switch (type) {
   8266     case bcmCosqControlEgressPool:
   8267     case bcmCosqControlEgressPoolLimitBytes:
   8268     case bcmCosqControlEgressPoolYellowLimitBytes:
   8269     case bcmCosqControlEgressPoolRedLimitBytes:
   8270     case bcmCosqControlEgressPoolLimitEnable:
   8271     case bcmCosqControlUCEgressPool:
   8272     case bcmCosqControlMCEgressPool:
   8273         return _bcm_td_cosq_egr_pool_get(unit, gport, cosq, type, arg);
   8274     case bcmCosqControlDropLimitAlpha:
   8275         return _bcm_td_cosq_alpha_get(unit, gport, cosq,
   8276                             (bcm_cosq_control_drop_limit_alpha_value_t *)arg);
   8277     case bcmCosqControlIngressPortPGSharedDynamicEnable:        
   8278     case bcmCosqControlEgressUCSharedDynamicEnable:
   8279     case bcmCosqControlEgressMCSharedDynamicEnable:
   8280         return _bcm_td_cosq_dynamic_thresh_enable_get(unit, gport, cosq, 
   8281                                                        type, arg);        
   8282     case bcmCosqControlEgressUCQueueSharedLimitBytes:
   8283     case bcmCosqControlEgressMCQueueSharedLimitBytes:
   8284     case bcmCosqControlEgressUCQueueMinLimitBytes:
   8285     case bcmCosqControlEgressMCQueueMinLimitBytes:
   8286         return _bcm_td_cosq_egr_queue_get(unit, gport, cosq, type, arg);
   8287     case bcmCosqControlEgressUCQueueLimitEnable:
   8288     case bcmCosqControlEgressMCQueueLimitEnable:
   8289         return _bcm_td_cosq_egr_queue_limit_enable_get(unit, gport, cosq,
   8290                                                         type, arg);
   8291 
   8292     default:
   8293         break;
   8294     }
   8295 
   8296     return BCM_E_UNAVAIL;
   8297 }
   8298 
   8299 #if 0
   8300 STATIC int
   8301 _bcm_td_cosq_gport_detach(int unit, bcm_port_t port)
   8302 {
   8303     soc_info_t *si;
   8304     int phy_port, mmu_port;
   8305     int cosq, weights[16];
   8306     uint32 rval, fval_hi, fval_lo;
   8307     uint64 rval64, fval64;
   8308 
   8309     si = &SOC_INFO(unit);
   8310 
   8311     phy_port = si->port_l2p_mapping[port];
   8312     mmu_port = si->port_p2m_mapping[phy_port];
   8313 
   8314     /* Detach from physical port */
   8315     BCM_IF_ERROR_RETURN(READ_ING_COS_MODEr(unit, port, &rval));
   8316     soc_reg_field_set(unit, ING_COS_MODEr, &rval, QUEUE_MODEf, 0);
   8317     soc_reg_field_set(unit, ING_COS_MODEr, &rval, COS_MODEf, 0);
   8318     BCM_IF_ERROR_RETURN(WRITE_ING_COS_MODEr(unit, port, rval));
   8319 
   8320     if (si->port_group[port] < 2) {
   8321         /* X pipe COS_MODE_SEL has 32 ports (mmu port 1-32) */
   8322         BCM_IF_ERROR_RETURN(READ_COS_MODE_Xr(unit, &rval64));
   8323         fval_lo = soc_reg64_field32_get(unit, COS_MODE_Xr, rval64,
   8324                                         COS_MODE_SELf);
   8325         fval_lo &= ~(1 << (mmu_port - 1));
   8326         soc_reg64_field32_set(unit, COS_MODE_Xr, &rval64, COS_MODE_SELf,
   8327                               fval_lo);
   8328         BCM_IF_ERROR_RETURN(WRITE_COS_MODE_Xr(unit, rval64));
   8329     } else {
   8330         /* Y pipe COS_MODE_SEL has 33 ports (mmu port 33-65) */
   8331         BCM_IF_ERROR_RETURN(READ_COS_MODE_Yr(unit, &rval64));
   8332         fval64 = soc_reg64_field_get(unit, COS_MODE_Yr, rval64, COS_MODE_SELf);
   8333         fval_lo = COMPILER_64_LO(fval64);
   8334         fval_hi = COMPILER_64_HI(fval64);
   8335         if (mmu_port - 33 < 32) {
   8336             fval_lo &= ~(1 << (mmu_port - 33));
   8337         } else {
   8338             fval_hi &= ~(1 << (mmu_port - 33 - 32));
   8339         }
   8340         COMPILER_64_SET(fval64, fval_hi, fval_lo);
   8341         soc_reg64_field_set(unit, COS_MODE_Yr, &rval64, COS_MODE_SELf, fval64);
   8342         BCM_IF_ERROR_RETURN(WRITe_COS_MODE_Yr(unit, rval64));
   8343     }
   8344 
   8345     
   8346     /* Clear bandwidth of all Stage1 COSQs */
   8347     
   8348     for (cosq = 8; cosq < 24; cosq++) {
   8349         BCM_IF_ERROR_RETURN(bcm_td_cosq_bucket_set(unit, port, cosq, 0, 0, 0));
   8350     }
   8351 
   8352     /* Clear weights of all Stage1 COSQs */
   8353     for (cosq = 0; cosq < 16; cosq++) {
   8354         weights[cosq] = 0;
   8355     }
   8356     BCM_IF_ERROR_RETURN
   8357         (_bcm_td_cosq_sched_set(unit, port, 0, BCM_COSQ_WEIGHTED_ROUND_ROBIN,
   8358                                 16, weights));
   8359 
   8360     /* Clear weight for S1 output queue */
   8361     cosq = 8;
   8362     BCM_IF_ERROR_RETURN(READ_COSWEIGHTSr(unit, port, cosq, &val));
   8363     soc_reg_field_set(unit, COSWEIGHTSr, &val, COSWEIGHTSf, 0);
   8364     BCM_IF_ERROR_RETURN(WRITE_COSWEIGHTSr(unit, port, cosq, val));
   8365 
   8366     /* Clear discard settings for all Stage1 COSQs */
   8367     for (cosq = 8; cosq < 24; cosq++) {
   8368         BCM_IF_ERROR_RETURN
   8369             (_bcm_td_cosq_wred_set(unit, port, cosq,
   8370                                    BCM_COSQ_DISCARD_COLOR_ALL |
   8371                                    BCM_COSQ_DISCARD_NONTCP,
   8372                                    TD_CELL_FIELD_MAX,
   8373                                    TD_CELL_FIELD_MAX, 100, 0,
   8374                                    TRUE));
   8375     }
   8376 
   8377     _td_sched_num_cosq[unit][port] = 0;
   8378 
   8379     return BCM_E_NONE;
   8380 }
   8381 #endif
   8382 
   8383 /*
   8384  * Function:
   8385  *     bcm_td_cosq_gport_add
   8386  * Purpose:
   8387  *     Create a cosq gport structure
   8388  * Parameters:
   8389  *     unit  - (IN) unit number
   8390  *     port  - (IN) port number
   8391  *     numq  - (IN) number of COS queues
   8392  *     flags - (IN) flags (BCM_COSQ_GPORT_XXX)
   8393  *     gport - (OUT) GPORT identifier
   8394  * Returns:
   8395  *     BCM_E_XXX
   8396  */
   8397 int
   8398 bcm_td_cosq_gport_add(int unit, bcm_gport_t port, int numq, uint32 flags,
   8399                       bcm_gport_t *gport)
   8400 {
   8401     soc_info_t *si;
   8402     _bcm_td_cosq_port_info_t *port_info;
   8403     _bcm_td_cosq_node_t *node;
   8404     bcm_module_t local_modid, modid_out;
   8405     bcm_port_t local_port, port_out;
   8406     int id;
   8407     uint32 sched_encap;
   8408 
   8409     LOG_INFO(BSL_LS_BCM_COSQ,
   8410              (BSL_META_U(unit,
   8411                          "bcm_td_cosq_gport_add: unit=%d port=0x%x numq=%d flags=0x%x\n"),
   8412               unit, port, numq, flags));
   8413 
   8414     if (!soc_feature(unit, soc_feature_ets)) {
   8415         return BCM_E_UNAVAIL;
   8416     }    
   8417 
   8418     if (gport == NULL) {
   8419         return BCM_E_PARAM;
   8420     }
   8421 
   8422     si = &SOC_INFO(unit);
   8423 
   8424     if (_bcm_td_cosq_port_info[unit] == NULL) {
   8425         return BCM_E_INIT;
   8426     }
   8427 
   8428     BCM_IF_ERROR_RETURN
   8429         (_bcm_td_cosq_localport_resolve(unit, port, &local_port));
   8430 
   8431     if (local_port < 0 || IS_CPU_PORT(unit, local_port) ||
   8432         IS_LB_PORT(unit, local_port)) {
   8433         return BCM_E_PORT;
   8434     }
   8435 
   8436     port_info = &_bcm_td_cosq_port_info[unit][local_port];
   8437     switch (flags) {
   8438     case BCM_COSQ_GPORT_UCAST_QUEUE_GROUP:
   8439         if (numq != 1) {
   8440             return BCM_E_PARAM;
   8441         }
   8442         for (id = 0; id < _BCM_TD_NUM_UCAST_QUEUE_GROUP; id++) {
   8443             if (port_info->ucast[id].numq == 0) {
   8444                 break;
   8445             }
   8446         }
   8447         if (id == _BCM_TD_NUM_UCAST_QUEUE_GROUP) {
   8448             return BCM_E_RESOURCE;
   8449         }
   8450         BCM_GPORT_UCAST_QUEUE_GROUP_SYSQID_SET(*gport, local_port, id);
   8451         node = &port_info->ucast[id];
   8452         break;
   8453     case BCM_COSQ_GPORT_MCAST_QUEUE_GROUP:
   8454         if (numq != 1) {
   8455             return BCM_E_PARAM;
   8456         }
   8457         for (id = 0; id < _BCM_TD_NUM_MCAST_QUEUE_GROUP; id++) {
   8458             if (port_info->mcast[id].numq == 0) {
   8459                 break;
   8460             }
   8461         }
   8462         if (id == _BCM_TD_NUM_MCAST_QUEUE_GROUP) {
   8463             return BCM_E_RESOURCE;
   8464         }
   8465         BCM_GPORT_MCAST_QUEUE_GROUP_SYSQID_SET(*gport, local_port, id);
   8466         node = &port_info->mcast[id];
   8467         break;
   8468     case BCM_COSQ_GPORT_DESTMOD_UCAST_QUEUE_GROUP:
   8469         if (si->port_num_ext_cosq[local_port] == 0) { /* regular port */
   8470             return BCM_E_PARAM;
   8471         }
   8472         if (numq <= 0 || numq > 4) {
   8473             return BCM_E_PARAM;
   8474         }
   8475         for (id = 0; id < _BCM_TD_NUM_EXT_UCAST_QUEUE_GROUP; id++) {
   8476             if (port_info->ext_ucast[id].numq == 0) {
   8477                 break;
   8478             }
   8479         }
   8480         if (id == _BCM_TD_NUM_EXT_UCAST_QUEUE_GROUP) {
   8481             return BCM_E_RESOURCE;
   8482         }
   8483         BCM_GPORT_UCAST_QUEUE_GROUP_SYSQID_SET
   8484             (*gport, local_port, _BCM_TD_NUM_UCAST_QUEUE_GROUP + id);
   8485         node = &port_info->ext_ucast[id];
   8486 
   8487         /* create VOQ profile which maps internal priorities evenly to
   8488          * queues */
   8489         SOC_IF_ERROR_RETURN
   8490             (_bcm_td_create_default_profile(unit, *gport, numq, 
   8491                                             &node->voq_profile));
   8492 
   8493         break;
   8494     case BCM_COSQ_GPORT_SCHEDULER:
   8495     case 0:
   8496         /*
   8497          * Can not validate actual number of cosq until attach time.
   8498          * The max number of configurable input:
   8499          *   S1: 7 (S2.0, S2.1, S2.2, mcast group, multiast SC/QM queue,
   8500          *          unicast SC queue, unicast QM queue)
   8501          *   S2: 9 (hardware allows to select up to 9 of the possible 12 input)
   8502          *   S3: 18 (1 regular ucast queue, 1 mcast queue,
   8503          *           16 extended ucast queues)
   8504          */
   8505         if (si->port_num_ext_cosq[local_port] == 0) { /* regular port */
   8506             if (numq <= 0 || numq > _BCM_TD_S2_SCHEDULER_NUM_INPUT) {
   8507                 return BCM_E_PARAM;
   8508             }
   8509         } else { /* extended queue port */
   8510             if (numq <= 0 || numq > _BCM_TD_EXT_S3_SCHEDULER_NUM_INPUT) {
   8511                 return BCM_E_PARAM;
   8512             }
   8513         }
   8514         for (id = 0; id < _BCM_TD_NUM_SCHEDULER; id++) {
   8515             if (port_info->sched[id].numq == 0) {
   8516                 break;
   8517             }
   8518         }
   8519         if (id == _BCM_TD_NUM_SCHEDULER) {
   8520             return BCM_E_RESOURCE;
   8521         }
   8522 
   8523         BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &local_modid));
   8524         BCM_IF_ERROR_RETURN
   8525             (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, local_modid,
   8526                                      local_port, &modid_out, &port_out));
   8527         sched_encap = (id << 16) | (modid_out << 8) | port_out;
   8528         BCM_GPORT_SCHEDULER_SET(*gport, sched_encap);
   8529         node = &port_info->sched[id];
   8530         break;
   8531     default:
   8532         return BCM_E_PARAM;
   8533     }
   8534 
   8535     node->gport = *gport;
   8536     node->numq = numq;
   8537     node->cosq_attached_to = -1;
   8538     node->hw_cosq_attached_to = -1;
   8539     node->level = 0;
   8540     node->parent = NULL;
   8541     node->sibling = NULL;
   8542     node->child = NULL;
   8543 
   8544     LOG_INFO(BSL_LS_BCM_COSQ,
   8545              (BSL_META_U(unit,
   8546                          "                       gport=0x%x\n"),
   8547               *gport));
   8548 
   8549     return BCM_E_NONE;
   8550 }
   8551 
   8552 STATIC int
   8553 _bcm_td_cosq_gport_delete_all(int unit, bcm_gport_t gport)
   8554 {
   8555     _bcm_td_cosq_node_t *node;
   8556 
   8557     LOG_INFO(BSL_LS_BCM_COSQ,
   8558              (BSL_META_U(unit,
   8559                          "bcm_td_cosq_gport_delete: unit=%d gport=0x%x\n"),
   8560               unit, gport));
   8561 
   8562     if (!soc_feature(unit, soc_feature_ets)) {
   8563         return BCM_E_UNAVAIL;
   8564     }
   8565     
   8566     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 
   8567         BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) ||
   8568         BCM_GPORT_IS_SCHEDULER(gport)) {
   8569         BCM_IF_ERROR_RETURN
   8570             (_bcm_td_cosq_node_get(unit, gport, NULL, NULL, NULL, &node));
   8571         if (node->child != NULL) {
   8572             BCM_IF_ERROR_RETURN(
   8573                     _bcm_td_cosq_gport_delete_all(unit, node->child->gport));
   8574         }
   8575         if (node->sibling != NULL) {
   8576             BCM_IF_ERROR_RETURN(
   8577                     _bcm_td_cosq_gport_delete_all(unit, node->sibling->gport));
   8578         }   
   8579         if (node->cosq_attached_to >= 0) {
   8580             BCM_IF_ERROR_RETURN(
   8581                 bcm_td_cosq_gport_detach(unit, node->gport, BCM_GPORT_INVALID, -1));
   8582         }       
   8583         node->numq = 0;
   8584     } else {
   8585         return BCM_E_PORT;
   8586     }
   8587     
   8588     return BCM_E_NONE;
   8589 }
   8590 
   8591 /*
   8592  * Function:
   8593  *     bcm_td_cosq_gport_delete
   8594  * Purpose:
   8595  *     Destroy a cosq gport structure
   8596  * Parameters:
   8597  *     unit  - (IN) unit number
   8598  *     gport - (IN) GPORT identifier
   8599  * Returns:
   8600  *     BCM_E_XXX
   8601  */
   8602 int
   8603 bcm_td_cosq_gport_delete(int unit, bcm_gport_t gport)
   8604 {
   8605     _bcm_td_cosq_node_t *node = NULL, *tnode;
   8606     _bcm_td_cosq_port_info_t *port_info;
   8607     int ii, local_port;
   8608 
   8609     LOG_INFO(BSL_LS_BCM_COSQ,
   8610              (BSL_META_U(unit,
   8611                          "bcm_td_cosq_gport_delete: unit=%d gport=0x%x\n"),
   8612               unit, gport));
   8613 
   8614     if (!soc_feature(unit, soc_feature_ets)) {
   8615         return BCM_E_UNAVAIL;
   8616     }
   8617     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) || 
   8618         BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) ||
   8619         BCM_GPORT_IS_SCHEDULER(gport)) {
   8620         BCM_IF_ERROR_RETURN
   8621             (_bcm_td_cosq_node_get(unit, gport, NULL, NULL, NULL, &node));
   8622 
   8623         if (node->cosq_attached_to >= 0) {
   8624             BCM_IF_ERROR_RETURN
   8625                 (bcm_td_cosq_gport_detach(unit, node->gport, BCM_GPORT_INVALID, -1));
   8626         }
   8627 
   8628         node->numq = 0;
   8629     } else {
   8630         local_port = (BCM_GPORT_IS_LOCAL(gport)) ?
   8631            BCM_GPORT_LOCAL_GET(gport) : BCM_GPORT_MODPORT_PORT_GET(gport);
   8632 
   8633         if (!SOC_PORT_VALID(unit, local_port)) {
   8634             return BCM_E_PORT;
   8635         }
   8636 
   8637         port_info = &_bcm_td_cosq_port_info[unit][local_port];
   8638         for (ii = 0; ii < _BCM_TD_NUM_SCHEDULER; ii++) {
   8639             tnode = &port_info->sched[ii];
   8640             if (port_info->sched[ii].numq == 0) {
   8641                 continue;
   8642             }
   8643             /* s1 node */
   8644             if (tnode->level == 1) {   
   8645                 node = tnode;
   8646                 break;
   8647             }
   8648         }
   8649         if (node == NULL) {
   8650             return BCM_E_NONE;
   8651         }
   8652         BCM_IF_ERROR_RETURN(
   8653             _bcm_td_cosq_gport_delete_all(unit, node->gport));
   8654     }
   8655 
   8656     return BCM_E_NONE;
   8657 }
   8658 
   8659 /*
   8660  * Function:
   8661  *     bcm_td_cosq_gport_get
   8662  * Purpose:
   8663  *     Get a cosq gport structure
   8664  * Parameters:
   8665  *     unit  - (IN) unit number
   8666  *     gport - (IN) GPORT identifier
   8667  *     port  - (OUT) port number
   8668  *     numq  - (OUT) number of COS queues
   8669  *     flags - (OUT) flags (BCM_COSQ_GPORT_XXX)
   8670  * Returns:
   8671  *     BCM_E_XXX
   8672  */
   8673 int
   8674 bcm_td_cosq_gport_get(int unit, bcm_gport_t gport, bcm_gport_t *port,
   8675                       int *numq, uint32 *flags)
   8676 {
   8677     _bcm_td_cosq_node_t *node;
   8678     bcm_module_t modid;
   8679     bcm_port_t local_port;
   8680     int id;
   8681     _bcm_gport_dest_t dest;
   8682 
   8683     if (port == NULL || numq == NULL || flags == NULL) {
   8684         return BCM_E_PARAM;
   8685     }
   8686 
   8687     LOG_INFO(BSL_LS_BCM_COSQ,
   8688              (BSL_META_U(unit,
   8689                          "bcm_td_cosq_gport_get: unit=%d gport=0x%x\n"),
   8690               unit, gport));
   8691 
   8692     BCM_IF_ERROR_RETURN
   8693         (_bcm_td_cosq_node_get(unit, gport, NULL, &local_port, &id, &node));
   8694 
   8695     if (SOC_USE_GPORT(unit)) {
   8696         BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid));
   8697         dest.gport_type = _SHR_GPORT_TYPE_MODPORT;
   8698         dest.modid = modid;
   8699         dest.port = local_port;
   8700         BCM_IF_ERROR_RETURN(_bcm_esw_gport_construct(unit, &dest, port));
   8701     } else {
   8702         *port = local_port;
   8703     }
   8704 
   8705     *numq = node->numq;
   8706 
   8707     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   8708         if (id < _BCM_TD_NUM_UCAST_QUEUE_GROUP) {
   8709             *flags = BCM_COSQ_GPORT_UCAST_QUEUE_GROUP;
   8710         } else {
   8711             *flags = BCM_COSQ_GPORT_DESTMOD_UCAST_QUEUE_GROUP;
   8712         }
   8713     } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   8714         *flags = BCM_COSQ_GPORT_MCAST_QUEUE_GROUP;
   8715     } else if (BCM_GPORT_IS_SCHEDULER(gport)) {
   8716         *flags = BCM_COSQ_GPORT_SCHEDULER;
   8717     } else {
   8718         *flags = 0;
   8719     }
   8720 
   8721     LOG_INFO(BSL_LS_BCM_COSQ,
   8722              (BSL_META_U(unit,
   8723                          "                       port=0x%x numq=%d flags=0x%x\n"),
   8724               *port, *numq, *flags));
   8725 
   8726     return BCM_E_NONE;
   8727 }
   8728 
   8729 /*
   8730  * Function:
   8731  *     bcm_td_cosq_gport_traverse
   8732  * Purpose:
   8733  *     Walks through the valid COSQ GPORTs and calls
   8734  *     the user supplied callback function for each entry.
   8735  * Parameters:
   8736  *     unit       - (IN) unit number
   8737  *     trav_fn    - (IN) Callback function.
   8738  *     user_data  - (IN) User data to be passed to callback function
   8739  * Returns:
   8740  *     BCM_E_NONE - Success.
   8741  *     BCM_E_XXX
   8742  */
   8743 int
   8744 bcm_td_cosq_gport_traverse(int unit, bcm_cosq_gport_traverse_cb cb,
   8745                            void *user_data)
   8746 {
   8747     _bcm_td_cosq_port_info_t *port_info;
   8748     bcm_module_t my_modid, modid_out;
   8749     bcm_port_t port, port_out;
   8750     bcm_gport_t gport;
   8751     int id, rv = BCM_E_NONE;
   8752 
   8753     if (_bcm_td_cosq_port_info[unit] == NULL) {
   8754         return BCM_E_INIT;
   8755     }
   8756 
   8757     BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_modid));
   8758     PBMP_ALL_ITER(unit, port) {
   8759         BCM_IF_ERROR_RETURN
   8760             (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET,
   8761                                     my_modid, port, &modid_out, &port_out));
   8762         BCM_GPORT_MODPORT_SET(gport, modid_out, port_out);
   8763 
   8764         port_info = &_bcm_td_cosq_port_info[unit][port];
   8765         for (id = 0; id < _BCM_TD_NUM_UCAST_QUEUE_GROUP; id++) {
   8766             if (port_info->ucast[id].numq == 0) {
   8767                 continue;
   8768             }
   8769             /* coverity[value_overwrite] */
   8770             rv = cb(unit, gport, port_info->ucast[id].numq,
   8771                     BCM_COSQ_GPORT_UCAST_QUEUE_GROUP,
   8772                     port_info->ucast[id].gport, user_data);
   8773             if (BCM_FAILURE(rv)) {
   8774 #ifdef BCM_CB_ABORT_ON_ERR
   8775                 if (SOC_CB_ABORT_ON_ERR(unit)) {
   8776                     return rv;
   8777                 }
   8778 #endif
   8779             }
   8780         }
   8781         for (id = 0; id < _BCM_TD_NUM_MCAST_QUEUE_GROUP; id++) {
   8782             if (port_info->mcast[id].numq == 0) {
   8783                 continue;
   8784             }
   8785             /* coverity[value_overwrite] */
   8786             rv = cb(unit, gport, port_info->mcast[id].numq,
   8787                     BCM_COSQ_GPORT_MCAST_QUEUE_GROUP,
   8788                     port_info->mcast[id].gport, user_data);
   8789 #ifdef BCM_CB_ABORT_ON_ERR
   8790             if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) {
   8791                 return rv;
   8792             }
   8793 #endif
   8794         }
   8795         for (id = 0; id < _BCM_TD_NUM_EXT_UCAST_QUEUE_GROUP; id++) {
   8796             if (port_info->ext_ucast[id].numq == 0) {
   8797                 continue;
   8798             }
   8799             /* coverity[value_overwrite] */
   8800             rv = cb(unit, gport, port_info->ext_ucast[id].numq,
   8801                     BCM_COSQ_GPORT_UCAST_QUEUE_GROUP,
   8802                     port_info->ext_ucast[id].gport, user_data);
   8803 #ifdef BCM_CB_ABORT_ON_ERR
   8804             if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) {
   8805                 return rv;
   8806             }
   8807 #endif
   8808         }
   8809         for (id = 0; id < _BCM_TD_NUM_SCHEDULER; id++) {
   8810             if (port_info->sched[id].numq == 0) {
   8811                 continue;
   8812             }
   8813             /* coverity[value_overwrite] */
   8814             rv = cb(unit, gport, port_info->sched[id].numq,
   8815                     BCM_COSQ_GPORT_SCHEDULER,
   8816                     port_info->sched[id].gport, user_data);
   8817 #ifdef BCM_CB_ABORT_ON_ERR
   8818             if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) {
   8819                 return rv;
   8820             }
   8821 #endif
   8822         }
   8823     }
   8824 
   8825     return BCM_E_NONE;
   8826 }
   8827 
   8828 int
   8829 bcm_td_cosq_gport_mapping_set(int unit, bcm_port_t ing_port,
   8830                               bcm_cos_t int_pri, uint32 flags,
   8831                               bcm_gport_t gport, bcm_cos_queue_t cosq)
   8832 {
   8833     return _bcm_td_cosq_mapping_set(unit, ing_port, int_pri, flags, gport,
   8834                                     cosq);
   8835 }
   8836 
   8837 int
   8838 bcm_td_cosq_gport_mapping_get(int unit, bcm_port_t ing_port,
   8839                               bcm_cos_t int_pri, uint32 flags,
   8840                               bcm_gport_t *gport, bcm_cos_queue_t *cosq)
   8841 {
   8842     if (gport == NULL || cosq == NULL) {
   8843         return BCM_E_PARAM;
   8844     }
   8845 
   8846     return _bcm_td_cosq_mapping_get(unit, ing_port, int_pri, flags, gport,
   8847                                     cosq);
   8848 }
   8849 
   8850 /*
   8851  * Function:
   8852  *     bcm_td_cosq_gport_bandwidth_set
   8853  * Purpose:
   8854  *     Configure COS queue bandwidth control
   8855  * Parameters:
   8856  *     unit   - (IN) unit number
   8857  *     gport  - (IN) GPORT identifier
   8858  *     cosq   - (IN) COS queue to configure, -1 for all COS queues
   8859  *     kbits_sec_min - (IN) minimum bandwidth, kbits/sec
   8860  *     kbits_sec_max - (IN) maximum bandwidth, kbits/sec
   8861  *     flags  - (IN) BCM_COSQ_BW_*
   8862  * Returns:
   8863  *     BCM_E_XXX
   8864  */
   8865 int
   8866 bcm_td_cosq_gport_bandwidth_set(int unit, bcm_gport_t gport,
   8867                                 bcm_cos_queue_t cosq, uint32 kbits_sec_min,
   8868                                 uint32 kbits_sec_max, uint32 flags)
   8869 {
   8870     int numq, i;
   8871 
   8872     if (cosq == -1) {
   8873         BCM_IF_ERROR_RETURN
   8874             (_bcm_td_cosq_index_resolve(unit, gport, cosq,
   8875                                         _BCM_TD_COSQ_INDEX_STYLE_BUCKET,
   8876                                         NULL, NULL, &numq));
   8877         cosq = 0;
   8878     } else {
   8879         numq = 1;
   8880     }
   8881 
   8882     for (i = 0; i < numq; i++) {
   8883         BCM_IF_ERROR_RETURN
   8884             (_bcm_td_cosq_bucket_set(unit, gport, cosq + i, kbits_sec_min,
   8885                                      kbits_sec_max, kbits_sec_min, 
   8886                                      kbits_sec_max, flags));
   8887     }
   8888 
   8889     return BCM_E_NONE;
   8890 }
   8891 
   8892 /*
   8893  * Function:
   8894  *     bcm_td_cosq_gport_bandwidth_get
   8895  * Purpose:
   8896  *     Get COS queue bandwidth control configuration
   8897  * Parameters:
   8898  *     unit   - (IN) unit number
   8899  *     gport  - (IN) GPORT identifier
   8900  *     cosq   - (IN) COS queue to get, -1 for any COS queue
   8901  *     kbits_sec_min - (OUT) minimum bandwidth, kbits/sec
   8902  *     kbits_sec_max - (OUT) maximum bandwidth, kbits/sec
   8903  *     flags  - (OUT) BCM_COSQ_BW_*
   8904  * Returns:
   8905  *     BCM_E_XXX
   8906  */
   8907 int
   8908 bcm_td_cosq_gport_bandwidth_get(int unit, bcm_gport_t gport,
   8909                                 bcm_cos_queue_t cosq, uint32 *kbits_sec_min,
   8910                                 uint32 *kbits_sec_max, uint32 *flags)
   8911 {
   8912     uint32 kbits_sec_burst;
   8913 
   8914     BCM_IF_ERROR_RETURN
   8915         (_bcm_td_cosq_bucket_get(unit, gport, cosq == -1 ? 0 : cosq,
   8916                                  kbits_sec_min, kbits_sec_max,
   8917                                  &kbits_sec_burst, &kbits_sec_burst, flags));
   8918 
   8919     return BCM_E_NONE;
   8920 }
   8921 
   8922 /*
   8923  * Function:
   8924  *     bcm_td_cosq_gport_bandwidth_burst_set
   8925  * Purpose:
   8926  *     Configure COS queue bandwidth burst setting
   8927  * Parameters:
   8928  *      unit        - (IN) unit number
   8929  *      gport       - (IN) GPORT identifier
   8930  *      cosq        - (IN) COS queue to configure, -1 for all COS queues
   8931  *      kbits_burst - (IN) maximum burst, kbits
   8932  * Returns:
   8933  *      BCM_E_XXX
   8934  */
   8935 int
   8936 bcm_td_cosq_gport_bandwidth_burst_set(int unit, bcm_gport_t gport,
   8937                                       bcm_cos_queue_t cosq,
   8938                                       uint32 kbits_burst_min,
   8939                                       uint32 kbits_burst_max)
   8940 {
   8941     int numq, i;
   8942     uint32 kbits_sec_min, kbits_sec_max, kbits_sec_burst, flags = 0;
   8943 
   8944     if (cosq == -1) {
   8945         BCM_IF_ERROR_RETURN
   8946             (_bcm_td_cosq_index_resolve(unit, gport, cosq,
   8947                                         _BCM_TD_COSQ_INDEX_STYLE_BUCKET,
   8948                                         NULL, NULL, &numq));
   8949         cosq = 0;
   8950     } else {
   8951         numq = 1;
   8952     }
   8953 
   8954     for (i = 0; i < numq; i++) {
   8955         BCM_IF_ERROR_RETURN
   8956             (_bcm_td_cosq_bucket_get(unit, gport, cosq + i, &kbits_sec_min,
   8957                                      &kbits_sec_max, &kbits_sec_burst,
   8958                                      &kbits_sec_burst, &flags));
   8959         BCM_IF_ERROR_RETURN
   8960             (_bcm_td_cosq_bucket_set(unit, gport, cosq + i, kbits_sec_min,
   8961                                      kbits_sec_max, kbits_burst_min,
   8962                                      kbits_burst_max, flags));
   8963     }
   8964 
   8965     return BCM_E_NONE;
   8966 }
   8967 
   8968 /*
   8969  * Function:
   8970  *     bcm_td_cosq_gport_bandwidth_burst_get
   8971  * Purpose:
   8972  *     Get COS queue bandwidth burst setting
   8973  * Parameters:
   8974  *     unit        - (IN) unit number
   8975  *     gport       - (IN) GPORT identifier
   8976  *     cosq        - (IN) COS queue to get, -1 for any queue
   8977  *     kbits_burst - (OUT) maximum burst, kbits
   8978  * Returns:
   8979  *     BCM_E_XXX
   8980  */
   8981 int
   8982 bcm_td_cosq_gport_bandwidth_burst_get(int unit, bcm_gport_t gport,
   8983                                        bcm_cos_queue_t cosq,
   8984                                        uint32 *kbits_burst_min,
   8985                                        uint32 *kbits_burst_max)
   8986 {
   8987     uint32 kbits_sec_min, kbits_sec_max, flags;
   8988 
   8989     BCM_IF_ERROR_RETURN
   8990         (_bcm_td_cosq_bucket_get(unit, gport, cosq == -1 ? 0 : cosq,
   8991                                  &kbits_sec_min, &kbits_sec_max, 
   8992                                  kbits_burst_min, kbits_burst_max, &flags));
   8993 
   8994     return BCM_E_NONE;
   8995 }
   8996 
   8997 /*
   8998  * Function:
   8999  *     bcm_td_cosq_gport_sched_set
   9000  * Purpose:
   9001  *     Configure COS queue scheduler setting
   9002  * Parameters:
   9003  *      unit   - (IN) unit number
   9004  *      gport  - (IN) GPORT identifier
   9005  *      cosq   - (IN) COS queue to configure, -1 for all COS queues
   9006  *      mode   - (IN) Scheduling mode, one of BCM_COSQ_xxx
   9007  *      weight - (IN) queue weight
   9008  * Returns:
   9009  *      BCM_E_XXX
   9010  */
   9011 int
   9012 bcm_td_cosq_gport_sched_set(int unit, bcm_gport_t gport,
   9013                             bcm_cos_queue_t cosq, int mode, int weight)
   9014 {
   9015     int rv, numq, i, count;
   9016 
   9017     if (cosq == -1) {
   9018         BCM_IF_ERROR_RETURN
   9019             (_bcm_td_cosq_index_resolve(unit, gport, cosq,
   9020                                         _BCM_TD_COSQ_INDEX_STYLE_SCHEDULER,
   9021                                         NULL, NULL, &numq));
   9022         cosq = 0;
   9023     } else {
   9024         numq = 1;
   9025     }
   9026 
   9027     count = 0;
   9028     for (i = 0; i < numq; i++) {
   9029         rv = _bcm_td_cosq_sched_set(unit, gport, cosq + i, mode, 1, &weight);
   9030         if (rv == BCM_E_NOT_FOUND) {
   9031             continue;
   9032         } else if (BCM_FAILURE(rv)) {
   9033             return rv;
   9034         } else {
   9035             count++;
   9036         }
   9037     }
   9038 
   9039     return count > 0 ? BCM_E_NONE : BCM_E_NOT_FOUND;
   9040 }
   9041 
   9042 /*
   9043  * Function:
   9044  *     bcm_td_cosq_gport_sched_get
   9045  * Purpose:
   9046  *     Get COS queue scheduler setting
   9047  * Parameters:
   9048  *     unit   - (IN) unit number
   9049  *     gport  - (IN) GPORT identifier
   9050  *     cosq   - (IN) COS queue to get, -1 for any queue
   9051  *     mode   - (OUT) Scheduling mode, one of BCM_COSQ_xxx
   9052  *     weight - (OUT) queue weight
   9053  * Returns:
   9054  *     BCM_E_XXX
   9055  */
   9056 int
   9057 bcm_td_cosq_gport_sched_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
   9058                             int *mode, int *weight)
   9059 {
   9060     int rv, numq, i;
   9061 
   9062     if (cosq == -1) {
   9063         BCM_IF_ERROR_RETURN
   9064             (_bcm_td_cosq_index_resolve(unit, gport, cosq,
   9065                                         _BCM_TD_COSQ_INDEX_STYLE_SCHEDULER,
   9066                                         NULL, NULL, &numq));
   9067         cosq = 0;
   9068     } else {
   9069         numq = 1;
   9070     }
   9071 
   9072     for (i = 0; i < numq; i++) {
   9073         rv = _bcm_td_cosq_sched_get(unit, gport, cosq + i, mode, 1, weight);
   9074         if (rv == BCM_E_NOT_FOUND) {
   9075             continue;
   9076         } else {
   9077             return rv;
   9078         }
   9079     }
   9080 
   9081     return BCM_E_NOT_FOUND;
   9082 }
   9083 
   9084 /*
   9085  * Function:
   9086  *     bcm_td_cosq_gport_discard_set
   9087  * Purpose:
   9088  *     Configure port WRED setting
   9089  * Parameters:
   9090  *     unit    - (IN) unit number
   9091  *     port    - (IN) GPORT identifier
   9092  *     cosq    - (IN) COS queue to configure, -1 for all COS queues
   9093  *     discard - (IN) discard settings
   9094  * Returns:
   9095  *     BCM_E_XXX
   9096  */
   9097 int
   9098 bcm_td_cosq_gport_discard_set(int unit, bcm_gport_t gport,
   9099                                bcm_cos_queue_t cosq,
   9100                                bcm_cosq_gport_discard_t *discard)
   9101 {
   9102     int numq, i;
   9103     uint32 min_thresh, max_thresh;
   9104     int cell_size, cell_field_max;
   9105 
   9106     if (discard == NULL ||
   9107         discard->gain < 0 || discard->gain > 15 ||
   9108         discard->drop_probability < 0 || discard->drop_probability > 100 ||
   9109         (discard->min_thresh > discard->max_thresh) ||
   9110         (discard->min_thresh < 0)) {
   9111         return BCM_E_PARAM;
   9112     }
   9113 
   9114     cell_size = _BCM_TD_BYTES_PER_CELL;
   9115     cell_field_max = TD_CELL_FIELD_MAX;
   9116 
   9117     min_thresh = discard->min_thresh;
   9118     max_thresh = discard->max_thresh;
   9119     if (discard->flags & BCM_COSQ_DISCARD_BYTES) {
   9120         /* Convert bytes to cells */
   9121         min_thresh += (cell_size - 1);
   9122         min_thresh /= cell_size;
   9123 
   9124         max_thresh += (cell_size - 1);
   9125         max_thresh /= cell_size;
   9126 
   9127         if ((min_thresh > cell_field_max) ||
   9128             (max_thresh > cell_field_max)) {
   9129             return BCM_E_PARAM;
   9130         }
   9131     } else {
   9132         /* Packet mode not supported */
   9133         return BCM_E_PARAM;
   9134     }
   9135 
   9136     if (cosq == -1) {
   9137         BCM_IF_ERROR_RETURN
   9138             (_bcm_td_cosq_index_resolve(unit, gport, cosq,
   9139                                         _BCM_TD_COSQ_INDEX_STYLE_WRED,
   9140                                         NULL, NULL, &numq));
   9141         cosq = 0;
   9142     } else {
   9143         numq = 1;
   9144     }
   9145 
   9146     for (i = 0; i < numq; i++) {
   9147         BCM_IF_ERROR_RETURN
   9148             (_bcm_td_cosq_wred_set(unit, gport, cosq + i, discard->flags,
   9149                                    min_thresh, max_thresh,
   9150                                    discard->drop_probability, discard->gain,
   9151                                    FALSE));
   9152     }
   9153 
   9154     return BCM_E_NONE;
   9155 }
   9156 
   9157 /*
   9158  * Function:
   9159  *     bcm_td_cosq_gport_discard_get
   9160  * Purpose:
   9161  *     Get port WRED setting
   9162  * Parameters:
   9163  *     unit    - (IN) unit number
   9164  *     port    - (IN) GPORT identifier
   9165  *     cosq    - (IN) COS queue to get, -1 for any queue
   9166  *     discard - (OUT) discard settings
   9167  * Returns:
   9168  *     BCM_E_XXX
   9169  */
   9170 int
   9171 bcm_td_cosq_gport_discard_get(int unit, bcm_gport_t gport,
   9172                               bcm_cos_queue_t cosq,
   9173                               bcm_cosq_gport_discard_t *discard)
   9174 {
   9175     uint32 min_thresh, max_thresh;
   9176 
   9177     if (discard == NULL) {
   9178         return BCM_E_PARAM;
   9179     }
   9180 
   9181     BCM_IF_ERROR_RETURN
   9182         (_bcm_td_cosq_wred_get(unit, gport, cosq == -1 ? 0 : cosq,
   9183                                &discard->flags, &min_thresh, &max_thresh,
   9184                                &discard->drop_probability, &discard->gain));
   9185 
   9186     /* Convert number of cells to number of bytes */
   9187     discard->min_thresh = min_thresh * _BCM_TD_BYTES_PER_CELL;
   9188     discard->max_thresh = max_thresh * _BCM_TD_BYTES_PER_CELL;
   9189 
   9190     return BCM_E_NONE;
   9191 }
   9192 
   9193 STATIC int
   9194 _bcm_td_cosq_pfc_class_resolve(bcm_switch_control_t sctype, int *type,
   9195                                int *class)
   9196 {
   9197     switch (sctype) {
   9198     case bcmSwitchPFCClass7Queue:
   9199     case bcmSwitchPFCClass6Queue:
   9200     case bcmSwitchPFCClass5Queue:
   9201     case bcmSwitchPFCClass4Queue:
   9202     case bcmSwitchPFCClass3Queue:
   9203     case bcmSwitchPFCClass2Queue:
   9204     case bcmSwitchPFCClass1Queue:
   9205     case bcmSwitchPFCClass0Queue:
   9206         *type = _BCM_TD_COSQ_TYPE_UCAST;
   9207         break;
   9208     case bcmSwitchPFCClass7McastQueue:
   9209     case bcmSwitchPFCClass6McastQueue:
   9210     case bcmSwitchPFCClass5McastQueue:
   9211     case bcmSwitchPFCClass4McastQueue:
   9212     case bcmSwitchPFCClass3McastQueue:
   9213     case bcmSwitchPFCClass2McastQueue:
   9214     case bcmSwitchPFCClass1McastQueue:
   9215     case bcmSwitchPFCClass0McastQueue:
   9216         *type = _BCM_TD_COSQ_TYPE_MCAST;
   9217         break;
   9218     case bcmSwitchPFCClass7DestmodQueue:
   9219     case bcmSwitchPFCClass6DestmodQueue:
   9220     case bcmSwitchPFCClass5DestmodQueue:
   9221     case bcmSwitchPFCClass4DestmodQueue:
   9222     case bcmSwitchPFCClass3DestmodQueue:
   9223     case bcmSwitchPFCClass2DestmodQueue:
   9224     case bcmSwitchPFCClass1DestmodQueue:
   9225     case bcmSwitchPFCClass0DestmodQueue:
   9226         *type = _BCM_TD_COSQ_TYPE_EXT_UCAST;
   9227         break;
   9228     default:
   9229         return BCM_E_PARAM;
   9230     }
   9231 
   9232     switch (sctype) {
   9233     case bcmSwitchPFCClass7Queue:
   9234     case bcmSwitchPFCClass7McastQueue:
   9235     case bcmSwitchPFCClass7DestmodQueue:
   9236         *class = 7;
   9237         break;
   9238     case bcmSwitchPFCClass6Queue:
   9239     case bcmSwitchPFCClass6McastQueue:
   9240     case bcmSwitchPFCClass6DestmodQueue:
   9241         *class = 6;
   9242         break;
   9243     case bcmSwitchPFCClass5Queue:
   9244     case bcmSwitchPFCClass5McastQueue:
   9245     case bcmSwitchPFCClass5DestmodQueue:
   9246         *class = 5;
   9247         break;
   9248     case bcmSwitchPFCClass4Queue:
   9249     case bcmSwitchPFCClass4McastQueue:
   9250     case bcmSwitchPFCClass4DestmodQueue:
   9251         *class = 4;
   9252         break;
   9253     case bcmSwitchPFCClass3Queue:
   9254     case bcmSwitchPFCClass3McastQueue:
   9255     case bcmSwitchPFCClass3DestmodQueue:
   9256         *class = 3;
   9257         break;
   9258     case bcmSwitchPFCClass2Queue:
   9259     case bcmSwitchPFCClass2McastQueue:
   9260     case bcmSwitchPFCClass2DestmodQueue:
   9261         *class = 2;
   9262         break;
   9263     case bcmSwitchPFCClass1Queue:
   9264     case bcmSwitchPFCClass1McastQueue:
   9265     case bcmSwitchPFCClass1DestmodQueue:
   9266         *class = 1;
   9267         break;
   9268     case bcmSwitchPFCClass0Queue:
   9269     case bcmSwitchPFCClass0McastQueue:
   9270     case bcmSwitchPFCClass0DestmodQueue:
   9271         *class = 0;
   9272         break;
   9273     /*
   9274      * COVERITY
   9275      *
   9276      * This default is unreachable but needed for some compiler. 
   9277      */ 
   9278     /* coverity[dead_error_begin] */
   9279     default:
   9280         return BCM_E_INTERNAL;
   9281     }
   9282 
   9283     return BCM_E_NONE;
   9284 }
   9285 
   9286 /*
   9287  * Function:
   9288  *     _bcm_td_fc_status_map_gport
   9289  * Purpose:
   9290  *     Update cos_bmp with gport cosq.
   9291  * Parameters:
   9292  *     unit       - (IN) unit number
   9293  *     port       - (IN) port number
   9294  *     type       - (IN) cosq type
   9295  *     gport      - (IN) gport to be mapped
   9296  *     cos_map    - (OUT) hw_cosq of gport
   9297  * Returns:
   9298  *     BCM_E_XXX
   9299  */
   9300 STATIC int
   9301 _bcm_td_fc_status_map_gport(int unit, int port, int type, bcm_gport_t gport,
   9302                             _bcm_td_cosq_pfc_cos_bmp_t *cos_bmp)
   9303 {
   9304     bcm_port_t local_port;
   9305     bcm_port_t resolved_port;
   9306     _bcm_td_cosq_node_t *node;
   9307     uint32 uc_bmp, mc_bmp;
   9308     int id, cnt;
   9309     int ext_uc_count;
   9310     int *ext_uc_qid = NULL;
   9311 
   9312     if (NULL == cos_bmp) {
   9313         return BCM_E_PARAM;
   9314     }
   9315     
   9316     BCM_IF_ERROR_RETURN
   9317         (_bcm_td_cosq_localport_resolve(unit, port, &local_port));
   9318 
   9319     uc_bmp = cos_bmp->uc_bmp;
   9320     mc_bmp = cos_bmp->mc_bmp;
   9321     ext_uc_count = cos_bmp->ext_uc_count;
   9322     ext_uc_qid = &(cos_bmp->ext_uc_qid[0]);
   9323     if (BCM_GPORT_IS_SET(gport)) {
   9324         if (BCM_GPORT_IS_SCHEDULER(gport)) {
   9325             return BCM_E_PORT;
   9326         }
   9327 
   9328         BCM_IF_ERROR_RETURN(
   9329                 _bcm_td_cosq_node_get(unit, gport, NULL,
   9330                                       &resolved_port, &id, &node));
   9331         if (resolved_port != local_port) {
   9332             return BCM_E_PORT;
   9333         }
   9334         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   9335             if (id > _BCM_TD_NUM_UCAST_QUEUE_GROUP) {
   9336                 /* extended unicast queue */
   9337                 if (type != _BCM_TD_COSQ_TYPE_EXT_UCAST) {
   9338                     return BCM_E_PARAM;
   9339                 }
   9340                 if (ext_uc_count == _BCM_TD_MAX_NUM_LLFC_EXTQ) {
   9341                     return BCM_E_RESOURCE;
   9342                 }
   9343                 for (cnt = 0; cnt < ext_uc_count; cnt++) {
   9344                     if (ext_uc_qid[cnt] == node->base + 64) {
   9345                         break;
   9346                     }
   9347                 }
   9348                 if (cnt == ext_uc_count) {
   9349                     ext_uc_qid[ext_uc_count] = node->base + 64;
   9350                     ext_uc_count++;
   9351                 }
   9352             } else { /* unicast queue */
   9353                 if (type != _BCM_TD_COSQ_TYPE_UCAST) {
   9354                     return BCM_E_PARAM;
   9355                 }
   9356                 uc_bmp |= 1 << node->base;
   9357             }
   9358         } else { /* multicast queue */
   9359             if (type != _BCM_TD_COSQ_TYPE_MCAST) {
   9360                 return BCM_E_PARAM;
   9361             }
   9362             mc_bmp |= 1 << node->base;
   9363         }
   9364     } else {
   9365         if (type == _BCM_TD_COSQ_TYPE_UCAST) {
   9366             bcm_cos_queue_t mc_cosq_max; 
   9367             mc_cosq_max = (_BCM_TD_NUM_MCAST_QUEUE_GROUP - 1);
   9368             uc_bmp |= 1 << gport;
   9369             /* In the legacy mode, need to set both UC & MC queue */
   9370             if (gport > mc_cosq_max) {
   9371                 mc_bmp |= 1 << mc_cosq_max;
   9372             } else {
   9373                 mc_bmp |= 1 << gport;
   9374             }
   9375         } else {
   9376             return BCM_E_PARAM;
   9377         }
   9378     }
   9379 
   9380     cos_bmp->uc_bmp = uc_bmp;
   9381     cos_bmp->mc_bmp = mc_bmp;
   9382     cos_bmp->ext_uc_count = ext_uc_count;
   9383 
   9384     return BCM_E_NONE;
   9385 }
   9386 
   9387 /*
   9388  * Function:
   9389  *     _bcm_td_port_pfc_profile_set
   9390  * Purpose:
   9391  *     Set PFC mapping profile for port. Updates PRIO2COS_LLFC & PORT_LLFC_CFG.
   9392  * Parameters:
   9393  *     unit       - (IN) unit number
   9394  *     port       - (IN) port number
   9395  *     op         - (IN) operation type
   9396  *     entry_cnt  - (IN) count of pfc classes and according bitmaps
   9397  *     pfc_class  - (IN) class list
   9398  *     cos_bmp    - (IN) bmp list
   9399  * Returns:
   9400  *     BCM_E_XXX
   9401  */
   9402 STATIC int
   9403 _bcm_td_port_pfc_profile_set(int unit, int port, _bcm_cosq_op_t op,
   9404                              int entry_cnt, int *pfc_class,
   9405                              _bcm_td_cosq_pfc_cos_bmp_t *cos_bmp)
   9406 {
   9407     static const soc_field_t valid_field[] = {
   9408         Q_VLD0f, Q_VLD1f, Q_VLD2f, Q_VLD3f
   9409     };
   9410     static const soc_field_t num_field[] = {
   9411         Q_NUM0f, Q_NUM1f, Q_NUM2f, Q_NUM3f
   9412     };
   9413     uint32 profile_index, old_profile_index;
   9414     uint32 ext_profile_index, ext_old_profile_index;
   9415     uint64 rval64[16], *rval64s[1];
   9416     uint64 ext_rval64[16], *ext_rval64s[1];
   9417     uint32 rval, fval;
   9418     uint32 uc_bmp, mc_bmp;
   9419     int rv, index, id, ext_uc_count, free_index, cur_ext_uc_qid[4];
   9420     int *ext_uc_qid = NULL;
   9421     int entry, cur_class, uc_mc_update = 0, euc_update = 0;
   9422 
   9423     rval64s[0] = rval64;
   9424     ext_rval64s[0] = ext_rval64;
   9425     BCM_IF_ERROR_RETURN(READ_PORT_LLFC_CFGr(unit, port, &rval));
   9426     old_profile_index = soc_reg_field_get(unit, PORT_LLFC_CFGr, rval,
   9427                                           PROFILE_INDEXf) * 16;
   9428     BCM_IF_ERROR_RETURN(soc_profile_reg_get(unit, _bcm_td_llfc_profile[unit],
   9429                                             old_profile_index, 16, rval64s));
   9430     ext_old_profile_index = soc_reg_field_get(unit, PORT_LLFC_CFGr, rval,
   9431                                               EXT_PER_Q_INDEXf) * 16;
   9432     BCM_IF_ERROR_RETURN
   9433         (soc_profile_reg_get(unit, _bcm_td_ext_llfc_profile[unit],
   9434                              ext_old_profile_index, 16, ext_rval64s));
   9435     
   9436     for (entry = 0; entry < entry_cnt; entry++) {
   9437         cur_class = pfc_class[entry];
   9438         uc_bmp = cos_bmp[entry].uc_bmp;
   9439         mc_bmp = cos_bmp[entry].mc_bmp;
   9440         ext_uc_count = cos_bmp[entry].ext_uc_count;
   9441         ext_uc_qid = &(cos_bmp[entry].ext_uc_qid[0]);
   9442         
   9443         if (uc_bmp != 0 || mc_bmp != 0) {
   9444             if (uc_bmp != 0) {
   9445                 /* coverity[dead_error_condition : FALSE] */
   9446                 if (op == _BCM_COSQ_OP_SET) {
   9447                     fval = uc_bmp;
   9448                 } else {
   9449                     fval = soc_reg64_field32_get(unit, PRIO2COS_LLFCr,
   9450                                                  rval64[cur_class],
   9451                                                  UC_COS0_10_BMPf);
   9452                     if (op == _BCM_COSQ_OP_ADD) {
   9453                         fval |= uc_bmp;
   9454                     } else { /* _BCM_COSQ_OP_DELETE */
   9455                         fval &= ~uc_bmp;
   9456                     }
   9457                 }
   9458                 soc_reg64_field32_set(unit, PRIO2COS_LLFCr, &rval64[cur_class],
   9459                                       UC_COS0_10_BMPf, fval);
   9460             }
   9461             if (mc_bmp != 0) {
   9462                 if (op == _BCM_COSQ_OP_SET) {
   9463                     fval = mc_bmp;
   9464                 } else {
   9465                     fval = soc_reg64_field32_get(unit, PRIO2COS_LLFCr,
   9466                                                  rval64[cur_class],
   9467                                                  MC_COS0_5_BMPf);
   9468                     if (op == _BCM_COSQ_OP_ADD) {
   9469                         fval |= mc_bmp;
   9470                     } else { /* _BCM_COSQ_OP_DELETE */
   9471                         fval &= ~mc_bmp;
   9472                     }
   9473                 }
   9474                 soc_reg64_field32_set(unit, PRIO2COS_LLFCr, &rval64[cur_class],
   9475                                       MC_COS0_5_BMPf, fval);
   9476             }
   9477             uc_mc_update = 1;
   9478         }
   9479 
   9480         if (ext_uc_count != 0) {
   9481             if (op == _BCM_COSQ_OP_SET) {
   9482                 COMPILER_64_ZERO(ext_rval64[cur_class]);
   9483                 for (index = 0; index < ext_uc_count; index++) {
   9484                     soc_reg64_field32_set(unit, PRIO2EXTQ_LLFCr,
   9485                                           &ext_rval64[cur_class],
   9486                                           valid_field[index], 1);
   9487                     soc_reg64_field32_set(unit, PRIO2EXTQ_LLFCr,
   9488                                           &ext_rval64[cur_class],
   9489                                           num_field[index], ext_uc_qid[index]);
   9490                 }
   9491             } else {
   9492                 for (id = 0; id < sizeof(num_field) / sizeof(num_field[0]);
   9493                      id++) {
   9494                     cur_ext_uc_qid[id] = -1;
   9495                     if (soc_reg64_field32_get(unit, PRIO2EXTQ_LLFCr,
   9496                                               ext_rval64[cur_class],
   9497                                               valid_field[id])) {
   9498                         cur_ext_uc_qid[id] =
   9499                             soc_reg64_field32_get(unit, PRIO2EXTQ_LLFCr,
   9500                                                   ext_rval64[cur_class],
   9501                                                   num_field[id]);
   9502                     }
   9503                 }
   9504                 if (op == _BCM_COSQ_OP_ADD) {
   9505                     free_index = -1;
   9506                     for (index = 0; index < ext_uc_count; index++) {
   9507                         for (id = 0;
   9508                              id < sizeof(num_field) / sizeof(num_field[0]);
   9509                              id++) {
   9510                             if (ext_uc_qid[index] == cur_ext_uc_qid[id]) {
   9511                                 /* already exist */
   9512                                 break;
   9513                             }
   9514                             if (free_index == -1 && cur_ext_uc_qid[id] == -1) {
   9515                                 free_index = id;
   9516                             }
   9517                         }
   9518                         if (id < sizeof(num_field) / sizeof(num_field[0])) {
   9519                             continue;
   9520                         }
   9521                         soc_reg64_field32_set(unit, PRIO2EXTQ_LLFCr,
   9522                                               &ext_rval64[cur_class],
   9523                                               valid_field[free_index], 1);
   9524                         soc_reg64_field32_set(unit, PRIO2EXTQ_LLFCr,
   9525                                               &ext_rval64[cur_class],
   9526                                               num_field[free_index],
   9527                                               ext_uc_qid[index]);
   9528                     }
   9529                 } else { /* _BCM_COSQ_OP_DELETE */
   9530                     for (index = 0; index < ext_uc_count; index++) {
   9531                         for (id = 0;
   9532                              id < sizeof(num_field) / sizeof(num_field[0]);
   9533                              id++) {
   9534                             if (ext_uc_qid[index] == cur_ext_uc_qid[id]) {
   9535                                 soc_reg64_field32_set(unit, PRIO2EXTQ_LLFCr,
   9536                                                       &ext_rval64[cur_class],
   9537                                                       valid_field[id], 0);
   9538                                 break;
   9539                             }
   9540                         }
   9541                     }
   9542                 }
   9543             }
   9544             euc_update = 1;
   9545         }
   9546     }
   9547 
   9548     if (uc_mc_update) {
   9549         BCM_IF_ERROR_RETURN
   9550                 (soc_profile_reg_delete(unit, _bcm_td_llfc_profile[unit],
   9551                                         old_profile_index));
   9552         rv = soc_profile_reg_add(unit, _bcm_td_llfc_profile[unit], rval64s,
   9553                                  16, &profile_index);
   9554         if (SOC_FAILURE(rv)) {
   9555             BCM_IF_ERROR_RETURN
   9556                 (soc_profile_reg_reference(unit, _bcm_td_llfc_profile[unit],
   9557                                            old_profile_index, 16));
   9558             return rv;
   9559         }
   9560         soc_reg_field_set(unit, PORT_LLFC_CFGr, &rval, PROFILE_INDEXf,
   9561                           profile_index / 16);
   9562     }
   9563     if (euc_update) {
   9564         BCM_IF_ERROR_RETURN
   9565                 (soc_profile_reg_delete(unit, _bcm_td_ext_llfc_profile[unit],
   9566                                         ext_old_profile_index));
   9567         rv = soc_profile_reg_add(unit, _bcm_td_ext_llfc_profile[unit],
   9568                                  ext_rval64s, 16, &ext_profile_index);
   9569         if (SOC_FAILURE(rv)) {
   9570             BCM_IF_ERROR_RETURN
   9571                 (soc_profile_reg_reference(unit, _bcm_td_ext_llfc_profile[unit],
   9572                                            ext_old_profile_index, 16));
   9573             return rv;
   9574         }
   9575         soc_reg_field_set(unit, PORT_LLFC_CFGr, &rval, EXT_PER_Q_INDEXf,
   9576                           ext_profile_index / 16);
   9577     }
   9578     BCM_IF_ERROR_RETURN(WRITE_PORT_LLFC_CFGr(unit, port, rval));
   9579 
   9580     return BCM_E_NONE;
   9581 }
   9582 
   9583 int
   9584 bcm_td_cosq_port_pfc_op(int unit, bcm_port_t port,
   9585                         bcm_switch_control_t sctype, _bcm_cosq_op_t op,
   9586                         bcm_gport_t *gport, int gport_count)
   9587 {
   9588     _bcm_td_cosq_pfc_cos_bmp_t cos_bmp;
   9589     int type = -1, class = -1, index;    
   9590 
   9591     if (IS_CPU_PORT(unit, port)) {
   9592         return BCM_E_PORT;
   9593     }
   9594     if (gport_count < 0) {
   9595         return BCM_E_PARAM;
   9596     }
   9597 
   9598     BCM_IF_ERROR_RETURN(_bcm_td_cosq_pfc_class_resolve(sctype, &type, &class));
   9599 
   9600     sal_memset(&cos_bmp, 0, sizeof(cos_bmp));
   9601     for (index = 0; index < gport_count; index++) {
   9602         if (!BCM_GPORT_IS_SET(gport[index]) && (_BCM_COSQ_OP_CLEAR != op) && 
   9603             (gport[index] < 0 || gport[index] >= _BCM_TD_NUM_UCAST_QUEUE_GROUP)
   9604            ) {
   9605             return BCM_E_PARAM;
   9606         }
   9607         BCM_IF_ERROR_RETURN(
   9608             _bcm_td_fc_status_map_gport(unit, port, type, gport[index],
   9609                                         &cos_bmp));
   9610     }
   9611 
   9612     if (op == _BCM_COSQ_OP_CLEAR) {
   9613         cos_bmp.uc_bmp = (1 << _BCM_TD_NUM_UCAST_QUEUE_GROUP) - 1;
   9614         cos_bmp.mc_bmp = (1 << _BCM_TD_NUM_MCAST_QUEUE_GROUP) - 1;
   9615     }
   9616 
   9617     BCM_IF_ERROR_RETURN(_bcm_td_port_pfc_profile_set(unit, port, op,
   9618                                                      1, &class, &cos_bmp));
   9619 
   9620     return BCM_E_NONE;
   9621 }
   9622 
   9623 int
   9624 bcm_td_cosq_port_pfc_get(int unit, bcm_port_t port,
   9625                          bcm_switch_control_t sctype,
   9626                          bcm_gport_t *gport, int gport_count,
   9627                          int *actual_gport_count)
   9628 {
   9629     _bcm_td_cosq_port_info_t *port_info;
   9630     bcm_port_t local_port;
   9631     int type = -1, class = -1, id, hw_cosq, count, i;
   9632     static const soc_field_t valid_field[] = {
   9633         Q_VLD0f, Q_VLD1f, Q_VLD2f, Q_VLD3f
   9634     };
   9635     static const soc_field_t num_field[] = {
   9636         Q_NUM0f, Q_NUM1f, Q_NUM2f, Q_NUM3f
   9637     };
   9638     uint32 profile_index;
   9639     uint64 rval64[16], *rval64s[1];
   9640     uint32 rval, bmp;
   9641 
   9642     if (IS_CPU_PORT(unit, port)) {
   9643         return BCM_E_PORT;
   9644     }
   9645 
   9646     if ((gport == NULL) && (gport_count > 0)) {
   9647         return BCM_E_PARAM;
   9648     }
   9649     
   9650     if (actual_gport_count == NULL) {
   9651         return BCM_E_PARAM;
   9652     }
   9653 
   9654     BCM_IF_ERROR_RETURN
   9655         (_bcm_td_cosq_localport_resolve(unit, port, &local_port));
   9656 
   9657     BCM_IF_ERROR_RETURN(_bcm_td_cosq_pfc_class_resolve(sctype, &type, &class));
   9658 
   9659     port_info = &_bcm_td_cosq_port_info[unit][local_port];
   9660     count = 0;
   9661 
   9662     rval64s[0] = rval64;
   9663     BCM_IF_ERROR_RETURN(READ_PORT_LLFC_CFGr(unit, local_port, &rval));
   9664     if (type == _BCM_TD_COSQ_TYPE_UCAST || type == _BCM_TD_COSQ_TYPE_MCAST) {
   9665         profile_index = soc_reg_field_get(unit, PORT_LLFC_CFGr, rval,
   9666                                           PROFILE_INDEXf) * 16;
   9667         BCM_IF_ERROR_RETURN
   9668             (soc_profile_reg_get(unit, _bcm_td_llfc_profile[unit],
   9669                                  profile_index, 16, rval64s));
   9670         if (type == _BCM_TD_COSQ_TYPE_UCAST) {
   9671             bmp = soc_reg64_field32_get(unit, PRIO2COS_LLFCr, rval64[class],
   9672                                         UC_COS0_10_BMPf);
   9673             for (hw_cosq = 0; hw_cosq < _BCM_TD_NUM_UCAST_QUEUE_GROUP;
   9674                  hw_cosq++) {
   9675                 if (!(bmp & (1 << hw_cosq))) {
   9676                     continue;
   9677                 }
   9678                 for (id = 0; id < _BCM_TD_NUM_UCAST_QUEUE_GROUP; id++) {
   9679                     if (port_info->ucast[id].parent == NULL || 
   9680                         port_info->ucast[id].base != hw_cosq) {
   9681                         continue;
   9682                     }
   9683                     if (gport_count > 0) {
   9684                         gport[count] = port_info->ucast[id].gport;
   9685                     }
   9686                     count++;
   9687                     break;
   9688                 }
   9689                 if (id == _BCM_TD_NUM_UCAST_QUEUE_GROUP) {
   9690                     if (gport_count > 0) {
   9691                         gport[count] = hw_cosq;
   9692                     }
   9693                     count++;
   9694                 }
   9695                 if ((gport_count > 0) && (count == gport_count)) {
   9696                     break;
   9697                 }
   9698             }
   9699         } else {
   9700             bmp = soc_reg64_field32_get(unit, PRIO2COS_LLFCr, rval64[class],
   9701                                         MC_COS0_5_BMPf);
   9702             for (hw_cosq = 0; hw_cosq < _BCM_TD_NUM_MCAST_QUEUE_GROUP;
   9703                  hw_cosq++) {
   9704                 if (!(bmp & (1 << hw_cosq))) {
   9705                     continue;
   9706                 }
   9707                 for (id = 0; id < _BCM_TD_NUM_MCAST_QUEUE_GROUP; id++) {
   9708                     if (port_info->mcast[id].parent == NULL ||
   9709                         port_info->mcast[id].base != hw_cosq) {
   9710                         continue;
   9711                     }
   9712                     if (gport_count > 0) {
   9713                         gport[count] = port_info->mcast[id].gport;
   9714                     }
   9715                     count++;
   9716                     break;
   9717                 }
   9718                 if (id == _BCM_TD_NUM_MCAST_QUEUE_GROUP) {
   9719                     if (gport_count > 0) {
   9720                         gport[count] = hw_cosq;
   9721                     }
   9722                     count++;
   9723                 }
   9724                 if ((gport_count > 0) && (count == gport_count)) {
   9725                     break;
   9726                 }
   9727             }
   9728         }
   9729     } else {
   9730         profile_index = soc_reg_field_get(unit, PORT_LLFC_CFGr, rval,
   9731                                           EXT_PER_Q_INDEXf) * 16;
   9732         BCM_IF_ERROR_RETURN
   9733             (soc_profile_reg_get(unit, _bcm_td_ext_llfc_profile[unit],
   9734                                  profile_index, 16, rval64s));
   9735         for (i = 0; i < sizeof(num_field) / sizeof(num_field[0]); i++) {
   9736             if (!soc_reg64_field32_get(unit, PRIO2EXTQ_LLFCr,
   9737                                       rval64[class], valid_field[i])) {
   9738                 continue;
   9739             }
   9740             hw_cosq = soc_reg64_field32_get(unit, PRIO2EXTQ_LLFCr,
   9741                                             rval64[class], num_field[i]) - 64;
   9742             for (id = 0; id < _BCM_TD_NUM_EXT_UCAST_QUEUE_GROUP; id++) {
   9743                 if (port_info->ext_ucast[id].parent == NULL ||
   9744                     port_info->ext_ucast[id].base != hw_cosq) {
   9745                     continue;
   9746                 }
   9747                 if (gport_count > 0) {
   9748                     gport[count] = port_info->ext_ucast[id].gport;
   9749                 }
   9750                 count++;
   9751                 break;
   9752             }
   9753             if (id == _BCM_TD_NUM_EXT_UCAST_QUEUE_GROUP) {
   9754                 if (gport_count > 0) {
   9755                     gport[count] = hw_cosq;
   9756                 }
   9757                 count++;
   9758             }
   9759             if ((gport_count > 0) && (count == gport_count)) {
   9760                 break;
   9761             }
   9762         }
   9763     }
   9764 
   9765     if (count == 0) {
   9766         return BCM_E_NOT_FOUND;
   9767     }
   9768     *actual_gport_count = count;
   9769     return BCM_E_NONE;
   9770 }
   9771 
   9772 /*
   9773  * Function:
   9774  *     bcm_td_cosq_pfc_class_mapping_set
   9775  * Purpose:
   9776  *     Set PFC mapping for port. PFC class is mapped to cosq.
   9777  * Parameters:
   9778  *     unit             - (IN) unit number
   9779  *     port             - (IN) port number
   9780  *     array_count      - (IN) count of mapping
   9781  *     mapping_array    - (IN) mappings 
   9782  * Returns:
   9783  *     BCM_E_XXX
   9784  */
   9785 int
   9786 bcm_td_cosq_pfc_class_mapping_set(int unit,
   9787     bcm_gport_t port,
   9788     int array_count,
   9789     bcm_cosq_pfc_class_mapping_t *mapping_array)
   9790 {
   9791     int index, count;
   9792     int cosq, type;
   9793     int cur_class = 0, pfc_class[_BCM_TD_NUM_PFC_CLASS];
   9794     bcm_gport_t cur_gport = 0;
   9795     _bcm_td_cosq_pfc_cos_bmp_t cos_bmp[_BCM_TD_NUM_PFC_CLASS];
   9796 
   9797 
   9798     if ((array_count < 0) || (array_count > _BCM_TD_NUM_PFC_CLASS)) {
   9799         return BCM_E_PARAM;
   9800     }
   9801     if (mapping_array == NULL) {
   9802         return BCM_E_PARAM;
   9803     }
   9804 
   9805     sal_memset(cos_bmp, 0, sizeof(cos_bmp));
   9806     for (count = 0; count < array_count; count++) {
   9807         cur_class = mapping_array[count].class_id;
   9808         if ((cur_class < 0) || (cur_class >= _BCM_TD_NUM_PFC_CLASS)) {
   9809             return BCM_E_PARAM;
   9810         }
   9811         
   9812         for (index = 0; index < BCM_COSQ_PFC_GPORT_COUNT; index++) {
   9813             cur_gport = mapping_array[count].gport_list[index];
   9814             if (cur_gport == BCM_GPORT_INVALID) {
   9815                 break;
   9816             }
   9817 
   9818             if (BCM_GPORT_IS_SET(cur_gport)) {
   9819                 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(cur_gport)) {
   9820                     BCM_IF_ERROR_RETURN(
   9821                         _bcm_td_cosq_node_get(unit, cur_gport, NULL, NULL,
   9822                                               &cosq, NULL));
   9823                     
   9824                     if (cosq > _BCM_TD_NUM_UCAST_QUEUE_GROUP) {
   9825                         /* extended unicast queue */
   9826                         type = _BCM_TD_COSQ_TYPE_EXT_UCAST;
   9827                     } else {
   9828                         type = _BCM_TD_COSQ_TYPE_UCAST;
   9829                     }
   9830                 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(cur_gport)) {
   9831                     type = _BCM_TD_COSQ_TYPE_MCAST;
   9832                 } else {
   9833                     /* Scheduler and other types of gport are not supported. */
   9834                     return BCM_E_PARAM;                    
   9835                 }
   9836             } else {
   9837                 if (cur_gport > _BCM_TD_NUM_UCAST_QUEUE_GROUP) {
   9838                     return BCM_E_PARAM;
   9839                 } else {
   9840                     /* gport represents the physical Cos value. */
   9841                     type = _BCM_TD_COSQ_TYPE_UCAST;
   9842                 }
   9843             }
   9844             BCM_IF_ERROR_RETURN(
   9845                 _bcm_td_fc_status_map_gport(unit, port, type, cur_gport,
   9846                                             &cos_bmp[cur_class]));
   9847         }
   9848     }
   9849 
   9850     for (index = 0; index < _BCM_TD_NUM_PFC_CLASS; index++) {
   9851         pfc_class[index] = index;
   9852     }
   9853     BCM_IF_ERROR_RETURN(_bcm_td_port_pfc_profile_set(unit, port,
   9854         _BCM_COSQ_OP_SET, _BCM_TD_NUM_PFC_CLASS, pfc_class, cos_bmp));
   9855     
   9856     return BCM_E_NONE;
   9857 }
   9858 
   9859 /*
   9860  * Function:
   9861  *     bcm_td_cosq_pfc_class_mapping_get
   9862  * Purpose:
   9863  *     Get PFC mapping for port.
   9864  *     Retrieves cosq gport associated to PFC classes.
   9865  * Parameters:
   9866  *     unit             - (IN) unit number
   9867  *     port             - (IN) port number
   9868  *     array_max        - (IN) max retrieve count
   9869  *     mapping_array    - (OUT) mappings
   9870  *     array_count      - (OUT) retrieved mapping count
   9871  * Returns:
   9872  *     BCM_E_XXX
   9873  */
   9874 int
   9875 bcm_td_cosq_pfc_class_mapping_get(int unit,
   9876     bcm_gport_t port,
   9877     int array_max,
   9878     bcm_cosq_pfc_class_mapping_t *mapping_array,
   9879     int *array_count)
   9880 {
   9881     int rv = 0;
   9882     int cur_class = 0;
   9883     int actual_gport_count, class_count = 0;
   9884     bcm_switch_control_t sc[] = { bcmSwitchPFCClass0Queue,
   9885                                   bcmSwitchPFCClass1Queue,
   9886                                   bcmSwitchPFCClass2Queue,
   9887                                   bcmSwitchPFCClass3Queue,
   9888                                   bcmSwitchPFCClass4Queue,
   9889                                   bcmSwitchPFCClass5Queue,
   9890                                   bcmSwitchPFCClass6Queue,
   9891                                   bcmSwitchPFCClass7Queue
   9892                                 };
   9893 
   9894     if ((mapping_array == NULL) && (array_max > 0)) {
   9895         return BCM_E_PARAM;
   9896     }
   9897     if (array_count == NULL) {
   9898         return BCM_E_PARAM;
   9899     }
   9900 
   9901     for (cur_class = 0; cur_class < _BCM_TD_NUM_PFC_CLASS; cur_class++) {
   9902         actual_gport_count = 0;
   9903         if (array_max > 0) {
   9904             rv = bcm_td_cosq_port_pfc_get(unit, port, sc[cur_class],
   9905                         mapping_array[class_count].gport_list,
   9906                         BCM_COSQ_PFC_GPORT_COUNT, &actual_gport_count);
   9907         } else {
   9908             rv = bcm_td_cosq_port_pfc_get(unit, port, sc[cur_class],
   9909                          NULL, -1, &actual_gport_count);
   9910         }
   9911         if (rv == BCM_E_NONE) {
   9912             if (array_max > 0) {
   9913                 mapping_array[class_count].class_id = cur_class;
   9914                 if (actual_gport_count < BCM_COSQ_PFC_GPORT_COUNT) {
   9915                     mapping_array[class_count].gport_list[actual_gport_count] = 
   9916                                                              BCM_GPORT_INVALID;
   9917                 }
   9918             }
   9919             class_count++;
   9920         } else if (rv != BCM_E_NOT_FOUND) {
   9921             return rv;
   9922         }
   9923 
   9924         if ((class_count == array_max) && (array_max > 0)) {
   9925             break;
   9926         }
   9927     }
   9928 
   9929     *array_count = class_count;
   9930     if (class_count == 0) {
   9931         return BCM_E_NOT_FOUND;
   9932     }
   9933     
   9934     return BCM_E_NONE;
   9935 }
   9936 
   9937 /*
   9938  * Function:
   9939  *     bcm_td_cosq_gport_attach
   9940  * Purpose:
   9941  *     Attach sched_port to the specified index (cosq) of input_port
   9942  * Parameters:
   9943  *     unit       - (IN) unit number
   9944  *     sched_port - (IN) scheduler GPORT identifier
   9945  *     input_port - (IN) GPORT to attach to
   9946  *     cosq       - (IN) COS queue to attach to (-1 for first available cosq)
   9947  * Returns:
   9948  *     BCM_E_XXX
   9949  */
   9950 int
   9951 bcm_td_cosq_gport_attach(int unit, bcm_gport_t sched_gport,
   9952                          bcm_gport_t input_gport, bcm_cos_queue_t cosq)
   9953 {
   9954     _bcm_td_cosq_node_t *sched_node, *input_node;
   9955     bcm_port_t sched_port, input_port;
   9956     int rv;
   9957 
   9958     LOG_INFO(BSL_LS_BCM_COSQ,
   9959              (BSL_META_U(unit,
   9960                          "bcm_td_cosq_gport_attach: unit=%d sched_port=0x%x "
   9961                          "input_port=0x%x cosq=%d\n"),
   9962               unit, sched_gport, input_gport, cosq));
   9963 
   9964     BCM_IF_ERROR_RETURN
   9965         (_bcm_td_cosq_node_get(unit, sched_gport, NULL, &sched_port, NULL,
   9966                                &sched_node));
   9967 
   9968     if (sched_node->cosq_attached_to >= 0) {
   9969         /* Has already attached */
   9970         return BCM_E_EXISTS;
   9971     }
   9972 
   9973     if (BCM_GPORT_IS_SCHEDULER(input_gport)) {
   9974         BCM_IF_ERROR_RETURN
   9975             (_bcm_td_cosq_node_get(unit, input_gport, NULL, &input_port, NULL,
   9976                                    &input_node));
   9977     } else {
   9978         BCM_IF_ERROR_RETURN
   9979             (_bcm_td_cosq_localport_resolve(unit, input_gport, &input_port));
   9980         input_node = NULL;
   9981     }
   9982 
   9983     if (sched_port != input_port) {
   9984         return BCM_E_PORT;
   9985     }
   9986 
   9987     if (input_node != NULL) {  /* sched_gport is not an S1 scheduler */
   9988         if (input_node->cosq_attached_to < 0) {
   9989             /* Only allow to attach to a node that has already attached */
   9990             return BCM_E_PARAM;
   9991         }
   9992         if (cosq < -1 || cosq >= input_node->numq) {
   9993             return BCM_E_PARAM;
   9994         }
   9995         sched_node->parent = input_node;
   9996         sched_node->sibling = input_node->child;
   9997         input_node->child = sched_node;
   9998         rv = _bcm_td_cosq_node_resolve(unit, input_port, sched_node, cosq);
   9999         if (BCM_FAILURE(rv)) {
  10000             input_node->child = sched_node->sibling;
  10001             return rv;
  10002         }
  10003         BCM_IF_ERROR_RETURN(_bcm_td_cosq_sched_node_set(unit, sched_port));
  10004 
  10005         LOG_INFO(BSL_LS_BCM_COSQ,
  10006                  (BSL_META_U(unit,
  10007                              "                         hw_cosq=%d\n"),
  10008                   sched_node->hw_cosq_attached_to));
  10009     } else { /* sched_gport is an S1 scheduler */
  10010         if (!BCM_GPORT_IS_SCHEDULER(sched_gport)) {
  10011             return BCM_E_PORT;
  10012         }
  10013 
  10014         if (sched_node->numq > _BCM_TD_S1_SCHEDULER_NUM_INPUT) {
  10015             return BCM_E_FAIL;
  10016         }
  10017         sched_node->cosq_attached_to = 0;
  10018         sched_node->hw_cosq_attached_to = 0;
  10019         sched_node->level = 1;
  10020     }
  10021 
  10022 #if 0
  10023     BCM_IF_ERROR_RETURN
  10024         (soc_reg_field32_modify(unit, ING_COS_MODEr, input_port,
  10025                                 SELECTf, 0x3)); /* VLAN_COS */
  10026     BCM_IF_ERROR_RETURN
  10027         (soc_reg_field32_modify(unit, COS_MODEr, input_port,
  10028                                 SELECTf, 0x3)); /* VLAN_COS */
  10029 #endif
  10030 
  10031     return BCM_E_NONE;
  10032 }
  10033 
  10034 /*
  10035  * Function:
  10036  *     bcm_td_cosq_gport_detach
  10037  * Purpose:
  10038  *     Detach sched_port from the specified index (cosq) of input_port
  10039  * Parameters:
  10040  *     unit       - (IN) unit number
  10041  *     sched_port - (IN) scheduler GPORT identifier
  10042  *     input_port - (IN) GPORT to detach from
  10043  *     cosq       - (IN) COS queue to detach from
  10044  * Returns:
  10045  *     BCM_E_XXX
  10046  */
  10047 int
  10048 bcm_td_cosq_gport_detach(int unit, bcm_gport_t sched_gport,
  10049                          bcm_gport_t input_gport, bcm_cos_queue_t cosq)
  10050 {
  10051     _bcm_td_cosq_node_t *sched_node, *input_node, *prev_node;
  10052     bcm_port_t sched_port, input_port;
  10053 
  10054     LOG_INFO(BSL_LS_BCM_COSQ,
  10055              (BSL_META_U(unit,
  10056                          "bcm_td_cosq_gport_detach: unit=%d sched_port=0x%x "
  10057                          "input_port=0x%x cosq=%d\n"),
  10058               unit, sched_gport, input_gport, cosq));
  10059 
  10060     BCM_IF_ERROR_RETURN
  10061         (_bcm_td_cosq_node_get(unit, sched_gport, NULL, &sched_port, NULL,
  10062                                &sched_node));
  10063 
  10064     if (sched_node->cosq_attached_to < 0) {
  10065         /* Not attached yet */
  10066         return BCM_E_PORT;
  10067     }
  10068 
  10069     /* input_gport argument is redundant, check if it is specified */
  10070     if (input_gport != BCM_GPORT_INVALID) {
  10071         if (BCM_GPORT_IS_SCHEDULER(input_gport)) {
  10072             BCM_IF_ERROR_RETURN
  10073                 (_bcm_td_cosq_node_get(unit, input_gport, NULL, &input_port,
  10074                                        NULL, &input_node));
  10075         } else {
  10076             BCM_IF_ERROR_RETURN
  10077                 (_bcm_td_cosq_localport_resolve(unit, input_gport,
  10078                                                 &input_port));
  10079             input_node = NULL;
  10080         }
  10081         if (sched_port != input_port) {
  10082             return BCM_E_PORT;
  10083         }
  10084         if (sched_node->parent != input_node) {
  10085             return BCM_E_PORT;
  10086         }
  10087     }
  10088 
  10089     /* cosq argument is redundant, check if it is specified */
  10090     if (cosq != -1) {
  10091         if (sched_node->parent == NULL) {
  10092             /*schedule node is S1*/
  10093             if (sched_node->cosq_attached_to != 0) {
  10094                 return BCM_E_PARAM;
  10095             }
  10096         } else if (sched_node->cosq_attached_to != cosq) {
  10097             return BCM_E_PARAM;
  10098         }
  10099     }
  10100 
  10101     if (sched_node->parent != NULL) { /* sched_node is not an S1 scheduler */
  10102         if (sched_node->parent->child == sched_node) {
  10103             sched_node->parent->child = sched_node->sibling;
  10104         } else {
  10105             prev_node = sched_node->parent->child;
  10106             while (prev_node != NULL && prev_node->sibling != sched_node) {
  10107                 prev_node = prev_node->sibling;
  10108             }
  10109             if (prev_node == NULL) {
  10110                 return BCM_E_INTERNAL;
  10111             }
  10112             prev_node->sibling = sched_node->sibling;
  10113         }
  10114         sched_node->parent = NULL;
  10115         sched_node->sibling = NULL;
  10116     }
  10117 
  10118     BCM_IF_ERROR_RETURN(_bcm_td_cosq_node_unresolve(unit, sched_node));
  10119     BCM_IF_ERROR_RETURN(_bcm_td_cosq_sched_node_set(unit, sched_port));
  10120 
  10121 #if 0
  10122     BCM_IF_ERROR_RETURN
  10123         (soc_reg_field32_modify(unit, COS_MODEr, input_port, SELECTf, 0x0));
  10124     BCM_IF_ERROR_RETURN
  10125         (soc_reg_field32_modify(unit, ING_COS_MODEr, input_port, SELECTf, 0x0));
  10126 #endif
  10127 
  10128     return BCM_E_NONE;
  10129 }
  10130 
  10131 /*
  10132  * Function:
  10133  *     bcm_td_cosq_gport_attach_get
  10134  * Purpose:
  10135  *     Get attached status of a scheduler port
  10136  * Parameters:
  10137  *     unit       - (IN) unit number
  10138  *     sched_port - (IN) scheduler GPORT identifier
  10139  *     input_port - (OUT) GPORT to attach to
  10140  *     cosq       - (OUT) COS queue to attached to
  10141  * Returns:
  10142  *     BCM_E_XXX
  10143  * Notes:
  10144  */
  10145 int
  10146 bcm_td_cosq_gport_attach_get(int unit, bcm_gport_t sched_gport,
  10147                              bcm_gport_t *input_gport, bcm_cos_queue_t *cosq)
  10148 {
  10149     _bcm_td_cosq_node_t *sched_node;
  10150     bcm_module_t modid, modid_out;
  10151     bcm_port_t port, port_out;
  10152 
  10153     if (input_gport == NULL || cosq == NULL) {
  10154         return BCM_E_PARAM;
  10155     }
  10156 
  10157     BCM_IF_ERROR_RETURN
  10158         (_bcm_td_cosq_node_get(unit, sched_gport, &modid, &port, NULL,
  10159                                &sched_node));
  10160 
  10161     if (sched_node->cosq_attached_to < 0) {
  10162         /* Not attached yet */
  10163         return BCM_E_NOT_FOUND;
  10164     }
  10165 
  10166     if (sched_node->parent != NULL) { /* sched_node is not an S1 scheduler */
  10167         *input_gport = sched_node->parent->gport;
  10168     } else {  /* sched_node is an S1 scheduler */
  10169         BCM_IF_ERROR_RETURN
  10170             (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, modid, port,
  10171                                     &modid_out, &port_out));
  10172         BCM_GPORT_MODPORT_SET(*input_gport, modid_out, port_out);
  10173     }
  10174     *cosq = sched_node->cosq_attached_to;
  10175 
  10176     return BCM_E_NONE;
  10177 }
  10178 
  10179 STATIC const soc_reg_t hg_voqfc_msg_sel_reg[8] = {
  10180         VOQFC_MSG_PORT_SEL0r, 
  10181         VOQFC_MSG_PORT_SEL1r, 
  10182         VOQFC_MSG_PORT_SEL2r, 
  10183         VOQFC_MSG_PORT_SEL3r, 
  10184         VOQFC_MSG_PORT_SEL4r, 
  10185         VOQFC_MSG_PORT_SEL5r, 
  10186         VOQFC_MSG_PORT_SEL6r, 
  10187         VOQFC_MSG_PORT_SEL7r
  10188     };
  10189 
  10190 STATIC const soc_reg_t hg_voqfc_group_merge_reg[8] = {
  10191         VOQFC_STATE_MERGE_GRP0r, 
  10192         VOQFC_STATE_MERGE_GRP1r, 
  10193         VOQFC_STATE_MERGE_GRP2r, 
  10194         VOQFC_STATE_MERGE_GRP3r, 
  10195         VOQFC_STATE_MERGE_GRP4r, 
  10196         VOQFC_STATE_MERGE_GRP5r, 
  10197         VOQFC_STATE_MERGE_GRP6r, 
  10198         VOQFC_STATE_MERGE_GRP7r
  10199     };
  10200 
  10201 /*
  10202  * Returns index of the port for indexing into MSG_SEL.
  10203  */
  10204 STATIC int
  10205 _bcm_td_voq_port_index(int unit, bcm_port_t port)
  10206 {
  10207     soc_info_t *si;
  10208     int     ii, pipe, mmu_base[2], index = -1;
  10209     bcm_port_t phy_port, mmu_port;
  10210 
  10211     si = &SOC_INFO(unit);
  10212     
  10213     phy_port = si->port_l2p_mapping[port];
  10214 
  10215     if (phy_port < 0) {
  10216         return -1;
  10217     }
  10218 
  10219     mmu_base[0] = 1;
  10220     mmu_base[1] = 34;
  10221 
  10222     for (pipe = 0; pipe < 2; pipe++) {
  10223         for (ii = 0; ii < 4; ii++) {
  10224             mmu_port = mmu_base[pipe] + ii;
  10225             if (si->port_m2p_mapping[mmu_port] == phy_port) {
  10226                 index = (pipe * 4) + ii;
  10227             }
  10228         }
  10229     }
  10230 
  10231     return index;
  10232 }
  10233 
  10234 STATIC int
  10235 _bcm_cosq_voq_find_empty_msg_sel_entry(int unit, bcm_port_t port, 
  10236                                        bcm_port_t fab_egr_port,
  10237                                        int *msg_sel_index)
  10238 {
  10239     soc_reg_t merge_grp_reg, msg_sel_reg;
  10240     uint32    reg_addr, reg_data;
  10241     int       ii, pidx = -1;
  10242     uint16    used_bmp = 0, profile_bmp;
  10243     uint32    fabric_port[16];
  10244 
  10245     *msg_sel_index = -1;
  10246 
  10247     if ((pidx = _bcm_td_voq_port_index(unit, port)) < 0) {
  10248         return BCM_E_UNAVAIL;
  10249     }
  10250 
  10251     msg_sel_reg = hg_voqfc_msg_sel_reg[pidx];
  10252     merge_grp_reg = hg_voqfc_group_merge_reg[pidx];
  10253 
  10254     for (ii = 0; ii < 16; ii++) {
  10255         reg_addr = soc_reg_addr(unit, msg_sel_reg, REG_PORT_ANY, ii);
  10256         SOC_IF_ERROR_RETURN(soc_reg32_read(unit, reg_addr, &reg_data));
  10257         fabric_port[ii] = soc_reg_field_get(unit, msg_sel_reg, reg_data, MSG_PORTf);
  10258     }
  10259 
  10260     for (ii = 0; ii < 16; ii++) {
  10261         reg_addr = soc_reg_addr(unit, merge_grp_reg, REG_PORT_ANY, ii);
  10262         SOC_IF_ERROR_RETURN(soc_reg32_read(unit, reg_addr, &reg_data));
  10263         profile_bmp = soc_reg_field_get(unit, merge_grp_reg, 
  10264                                             reg_data, MERGE_ST_BMPf);
  10265         used_bmp |= profile_bmp;
  10266     }
  10267 
  10268     for (ii = 0; ii < 16; ii++) {
  10269         /* check already in use */
  10270         if ((used_bmp & (1 << ii)) && (fab_egr_port == fabric_port[ii])) {
  10271             *msg_sel_index = ii;
  10272             return BCM_E_NONE;
  10273         }
  10274     }
  10275     /* Not found, ok, get an first empty slot */
  10276     for (ii = 0; ii < 16; ii++) {
  10277         /* check already in use */
  10278         if ((used_bmp & (1 << ii)) == 0) {
  10279             *msg_sel_index = ii;
  10280             return BCM_E_NONE;
  10281         }
  10282     }
  10283 
  10284     return BCM_E_FULL;
  10285 }
  10286 
  10287 STATIC int
  10288 _bcm_cosq_voq_find_current_msg_sel_entry(int unit, bcm_port_t port, 
  10289                                        bcm_port_t fab_egr_port,
  10290                                        int q_group, int *msg_sel_index)
  10291 {
  10292     soc_reg_t merge_grp_reg, msg_sel_reg;
  10293     uint32    reg_addr, reg_data;
  10294     int       ii, pidx = -1;
  10295     uint16    used_bmp = 0, profile_bmp;
  10296     uint32    fabric_port[16];
  10297     int       from_q_grp, to_q_grp;
  10298 
  10299     *msg_sel_index = -1;
  10300 
  10301     if ((pidx = _bcm_td_voq_port_index(unit, port)) < 0) {
  10302         return BCM_E_UNAVAIL;
  10303     }
  10304 
  10305     msg_sel_reg = hg_voqfc_msg_sel_reg[pidx];
  10306     merge_grp_reg = hg_voqfc_group_merge_reg[pidx];
  10307 
  10308     for (ii = 0; ii < 16; ii++) {
  10309         reg_addr = soc_reg_addr(unit, msg_sel_reg, REG_PORT_ANY, ii);
  10310         SOC_IF_ERROR_RETURN(soc_reg32_read(unit, reg_addr, &reg_data));
  10311         fabric_port[ii] = soc_reg_field_get(unit, msg_sel_reg, reg_data, MSG_PORTf);
  10312     }
  10313 
  10314     if (q_group < 0) {
  10315         from_q_grp = 0;
  10316         to_q_grp = 15;
  10317     } else {
  10318         from_q_grp = to_q_grp = q_group;
  10319     }
  10320 
  10321     for (ii = from_q_grp; ii <= to_q_grp; ii++) {
  10322         reg_addr = soc_reg_addr(unit, merge_grp_reg, REG_PORT_ANY, ii);
  10323         SOC_IF_ERROR_RETURN(soc_reg32_read(unit, reg_addr, &reg_data));
  10324         profile_bmp = soc_reg_field_get(unit, merge_grp_reg, reg_data, MERGE_ST_BMPf);
  10325 
  10326         used_bmp |= profile_bmp;
  10327     }
  10328 
  10329     /* Not found, ok, get an first empty slot */
  10330     for (ii = 0; ii < 16; ii++) {
  10331         if ((used_bmp & (1 << ii)) && (fab_egr_port == fabric_port[ii])) {
  10332             *msg_sel_index = ii;
  10333             return BCM_E_NONE;
  10334         }
  10335     }
  10336 
  10337     return BCM_E_NOT_FOUND;
  10338 }
  10339 
  10340 STATIC int
  10341 _bcm_td_voq_fabric_port_set(int unit, bcm_port_t port, 
  10342                               bcm_port_t fab_egr_port,
  10343                               int msg_sel_index, int q_grp_idx)
  10344 {
  10345     soc_reg_t merge_grp_reg, msg_sel;
  10346     uint32    reg_data;
  10347     int       voq_pidx = -1;
  10348     uint16    bmp;
  10349 
  10350     if ((voq_pidx = _bcm_td_voq_port_index(unit, port)) < 0) {
  10351         return BCM_E_PARAM;
  10352     }
  10353 
  10354     msg_sel = hg_voqfc_msg_sel_reg[voq_pidx];
  10355     merge_grp_reg = hg_voqfc_group_merge_reg[voq_pidx];
  10356 
  10357     reg_data = 0;
  10358     soc_reg_field_set(unit, msg_sel, &reg_data, MSG_PORTf, fab_egr_port);
  10359     BCM_IF_ERROR_RETURN
  10360         (soc_reg32_set(unit, msg_sel, REG_PORT_ANY, msg_sel_index, reg_data));
  10361 
  10362     SOC_IF_ERROR_RETURN
  10363         (soc_reg32_get(unit, merge_grp_reg, REG_PORT_ANY, q_grp_idx,
  10364                        &reg_data));
  10365     bmp = soc_reg_field_get(unit, merge_grp_reg, reg_data, MERGE_ST_BMPf);
  10366     if ((bmp & (1 << q_grp_idx)) == 0) {
  10367         bmp |= (1 << q_grp_idx);
  10368         soc_reg_field_set(unit, merge_grp_reg, &reg_data, MERGE_ST_BMPf, bmp);
  10369 
  10370         BCM_IF_ERROR_RETURN
  10371             (soc_reg32_set(unit, merge_grp_reg, REG_PORT_ANY, q_grp_idx,
  10372                            reg_data));
  10373     }
  10374 
  10375     return BCM_E_NONE;
  10376 }
  10377 
  10378 STATIC int
  10379 _bcm_td_voq_fabric_port_unset(int unit, bcm_port_t port, 
  10380                               bcm_port_t fab_egr_port, int q_grp,
  10381                               uint32 *new_fabric_pbmp)
  10382 {
  10383     uint32    reg_data;
  10384     int       voq_pidx = -1;
  10385     uint16    profile_bmp, ii, jj;
  10386     uint32    fabric_port[16];
  10387     soc_reg_t merge_grp_reg, msg_sel_reg;
  10388 
  10389     if ((voq_pidx = _bcm_td_voq_port_index(unit, port)) < 0) {
  10390         return BCM_E_PARAM;
  10391     }
  10392 
  10393     msg_sel_reg = hg_voqfc_msg_sel_reg[voq_pidx];
  10394     merge_grp_reg = hg_voqfc_group_merge_reg[voq_pidx];
  10395 
  10396     for (ii = 0; ii < 16; ii++) {
  10397         SOC_IF_ERROR_RETURN
  10398             (soc_reg32_get(unit, msg_sel_reg, REG_PORT_ANY, ii, &reg_data));
  10399         fabric_port[ii] = soc_reg_field_get(unit, msg_sel_reg, reg_data, MSG_PORTf);
  10400     }
  10401 
  10402     SOC_IF_ERROR_RETURN
  10403         (soc_reg32_get(unit, merge_grp_reg, REG_PORT_ANY, q_grp, &reg_data));
  10404     profile_bmp = soc_reg_field_get(unit, merge_grp_reg, reg_data,
  10405                                     MERGE_ST_BMPf);
  10406 
  10407     for (jj = 0; jj < 16; jj++) {
  10408         if ((profile_bmp & (1 << jj)) && (fab_egr_port == fabric_port[jj])) {
  10409             profile_bmp &= ~(1 << jj);
  10410 
  10411             soc_reg_field_set(unit, merge_grp_reg, &reg_data, 
  10412                               MERGE_ST_BMPf, profile_bmp);
  10413             BCM_IF_ERROR_RETURN
  10414                 (soc_reg32_set(unit, merge_grp_reg, REG_PORT_ANY, q_grp,
  10415                                reg_data));
  10416             *new_fabric_pbmp = profile_bmp;
  10417             break;
  10418         }
  10419     }
  10420 
  10421     return BCM_E_NONE;
  10422 }
  10423 
  10424 STATIC int _bcm_td_cosq_voq_init(int unit, bcm_port_t port)
  10425 {
  10426     soc_reg_t merge_grp_reg;
  10427     uint32    reg_data = 0;
  10428     int       pidx = -1, ii;
  10429 
  10430     if ((pidx = _bcm_td_voq_port_index(unit, port)) < 0) {
  10431         return BCM_E_NONE;
  10432     }
  10433 
  10434     merge_grp_reg = hg_voqfc_group_merge_reg[pidx];
  10435 
  10436     /*
  10437      * clear out VOQFC_STATE_MERGE_GRPx registers.
  10438      */
  10439     for (ii = 0; ii < 16; ii++) {
  10440         soc_reg_field_set(unit, merge_grp_reg, &reg_data, MERGE_ST_BMPf, 0);
  10441         BCM_IF_ERROR_RETURN
  10442             (soc_reg32_set(unit, merge_grp_reg, REG_PORT_ANY, ii, reg_data));
  10443     }
  10444 
  10445     return BCM_E_NONE;
  10446 }
  10447 
  10448 STATIC int
  10449 _bcm_td_create_default_profile(int unit, bcm_port_t gport, int numq,
  10450                                 _bcm_td_voq_profile_t *profile)
  10451 {
  10452     int     ii;
  10453 
  10454     if ((numq <= 0) || (!profile)) {
  10455         return BCM_E_PARAM;
  10456     }
  10457 
  10458     profile->hw_index = -1;
  10459     profile->id = -1;
  10460 
  10461     for (ii = 0; ii < 16; ii++) {
  10462         profile->int_prio2q[ii] = 
  10463                         _BCM_TD_VOQ_GPORT_QUEUE_ID(unit, gport, (ii*numq/16));
  10464     }
  10465     return BCM_E_NONE;
  10466 }
  10467 
  10468 STATIC int
  10469 _bcm_td_add_voq_profile(int unit, _bcm_td_cosq_node_t *node)
  10470 {
  10471     uint32 new_index;
  10472     voq_cos_map_entry_t voq_cos_map_entries[16];
  10473     void *entries[1];
  10474     int ii;
  10475     _bcm_td_voq_profile_t *profile = &node->voq_profile;
  10476 
  10477     sal_memset(voq_cos_map_entries, 0, sizeof(voq_cos_map_entries));
  10478 
  10479     for (ii = 0; ii < 16; ii++) {
  10480         soc_mem_field32_set(unit, VOQ_COS_MAPm, 
  10481                    &voq_cos_map_entries[ii], VOQ_COSf, profile->int_prio2q[ii]);
  10482     }
  10483 
  10484     entries[0] = &voq_cos_map_entries;
  10485     BCM_IF_ERROR_RETURN
  10486         (soc_profile_mem_add(unit, _bcm_td_voq_cos_map_profile[unit], 
  10487                              entries, 16, &new_index));
  10488 
  10489     profile->hw_index = new_index;
  10490     profile->id = new_index/16;
  10491 
  10492     return BCM_E_NONE;
  10493 }
  10494 
  10495 
  10496 /* Map internal priority to voq cos */
  10497 STATIC int
  10498 _bcm_td_voq_gport_mapping_set(int unit, bcm_port_t gport, int int_prio, 
  10499                               bcm_cos_t cos)
  10500 {
  10501     _bcm_td_voq_profile_t *profile;
  10502     _bcm_td_cosq_node_t *node;
  10503     int qid, id, prev_profile_id = -1, profile_id, modid, rv;
  10504     bcm_port_t  local_port, port, dest_port;
  10505 
  10506     BCM_IF_ERROR_RETURN
  10507         (_bcm_td_cosq_node_get(unit, gport, NULL, &local_port, &id, &node));
  10508 
  10509     profile = &node->voq_profile;
  10510 
  10511     qid = _BCM_TD_VOQ_GPORT_QUEUE_ID(unit, gport, cos);
  10512     if (qid == profile->int_prio2q[int_prio]) {
  10513         return BCM_E_NONE;
  10514     }
  10515 
  10516     profile->int_prio2q[int_prio] = qid;
  10517 
  10518     if (profile->id < 0) {
  10519         return BCM_E_NONE;
  10520     }
  10521 
  10522     prev_profile_id = profile->id;
  10523 
  10524     /*
  10525      * Update modport_sw table for all the ingress ports that use this
  10526      * voq group to use new profile.
  10527      */
  10528     PBMP_PORT_ITER(unit, port) {
  10529         for (modid = 0; modid <= SOC_MODID_MAX(unit); modid++) {
  10530             rv = bcm_esw_stk_port_modport_get(unit, port,
  10531                                               modid, &dest_port);
  10532 
  10533             if ((!BCM_SUCCESS(rv)) || (dest_port != local_port)) {
  10534                 continue;
  10535             }
  10536 
  10537             rv = bcm_stk_modport_voq_cosq_profile_get(unit, port, 
  10538                                                       modid, &profile_id);
  10539             if ((!BCM_SUCCESS(rv)) || (prev_profile_id != profile_id)) {
  10540                 continue;
  10541             }
  10542 
  10543             /*
  10544              * Add VOQ profile to HW. and delete the previos VOQ profile
  10545              */
  10546             BCM_IF_ERROR_RETURN(_bcm_td_add_voq_profile(unit, node));
  10547 
  10548             BCM_IF_ERROR_RETURN
  10549                 (soc_profile_mem_delete(unit, _bcm_td_voq_cos_map_profile[unit], 
  10550                                         prev_profile_id * 16));
  10551 
  10552             BCM_IF_ERROR_RETURN
  10553                 (bcm_stk_modport_voq_cosq_profile_set(unit, port, 
  10554                                                       modid, profile->id));
  10555         }
  10556     }
  10557 
  10558     return BCM_E_NONE;
  10559 }
  10560 
  10561 /*
  10562  * Function:
  10563  *     bcm_td_cosq_gport_modid_attach
  10564  * Purpose:
  10565  *     Get attached status of a scheduler port
  10566  * Parameters:
  10567  *     unit       - (IN) unit number
  10568  *     sched_port - (IN) scheduler GPORT identifier
  10569  *     input_port - (OUT) GPORT to attach to
  10570  *     cosq       - (OUT) COS queue to attached to
  10571  * Returns:
  10572  *     BCM_E_XXX
  10573  * Notes:
  10574  */
  10575 int
  10576 bcm_td_cosq_gport_destmod_attach(int unit, bcm_gport_t gport,
  10577                                bcm_port_t ing_port,
  10578                                bcm_module_t dest_modid, 
  10579                                int fabric_egress_port)
  10580 {
  10581     int q_grp;
  10582     bcm_port_t local_port;
  10583     int msg_sel_index, cur_profile_id = -1;
  10584     _bcm_td_cosq_node_t *node;
  10585     _bcm_td_voq_profile_t *profile;
  10586 
  10587     BCM_IF_ERROR_RETURN
  10588         (bcm_stk_modport_voq_cosq_profile_get(unit, ing_port, 
  10589                                               dest_modid, &cur_profile_id));
  10590     if (cur_profile_id >= 0) {
  10591         return BCM_E_BUSY;
  10592     }
  10593 
  10594     if (!_BCM_TD_IS_VOQ_GPORT(unit, gport)) {
  10595         return BCM_E_PARAM;
  10596     }
  10597     
  10598     BCM_IF_ERROR_RETURN
  10599         (_bcm_td_cosq_node_get(unit, gport, NULL, &local_port, &q_grp, &node));
  10600     if (node == NULL) {
  10601         return BCM_E_PARAM;
  10602     }
  10603 
  10604     /*
  10605      * find an empty index to read VOQFC[port] state.
  10606      */
  10607     if (_bcm_cosq_voq_find_empty_msg_sel_entry(unit, local_port, 
  10608                                     fabric_egress_port, &msg_sel_index) < 0) {
  10609         LOG_ERROR(BSL_LS_BCM_COSQ,
  10610                   (BSL_META_U(unit,
  10611                               "Error: unit %d port %d MSG_SEL enteries full \n"),
  10612                               unit, local_port));
  10613         return BCM_E_FULL;
  10614     }
  10615 
  10616     q_grp = q_grp - _BCM_TD_NUM_UCAST_QUEUE_GROUP;
  10617     SOC_IF_ERROR_RETURN
  10618         (_bcm_td_voq_fabric_port_set(unit, local_port, 
  10619                                      fabric_egress_port, msg_sel_index, q_grp));
  10620 
  10621     BCM_IF_ERROR_RETURN(_bcm_td_add_voq_profile(unit, node));
  10622 
  10623     profile = &node->voq_profile;
  10624 
  10625     /* update modport table to new profile */
  10626     BCM_IF_ERROR_RETURN
  10627         (bcm_stk_modport_voq_cosq_profile_set(unit, ing_port, 
  10628                                               dest_modid, profile->id));
  10629     return BCM_E_NONE;
  10630 }
  10631 
  10632 /*
  10633  * Function:
  10634  *     bcm_td_cosq_gport_modid_detach
  10635  * Purpose:
  10636  *     Get attached status of a scheduler port
  10637  * Parameters:
  10638  *     unit       - (IN) unit number
  10639  *     sched_port - (IN) scheduler GPORT identifier
  10640  *     input_port - (OUT) GPORT to attach to
  10641  *     cosq       - (OUT) COS queue to attached to
  10642  * Returns:
  10643  *     BCM_E_XXX
  10644  * Notes:
  10645  */
  10646 int
  10647 bcm_td_cosq_gport_destmod_detach(int unit, bcm_gport_t gport,
  10648                                  bcm_port_t ing_port,
  10649                                  bcm_module_t dest_modid, 
  10650                                  int fabric_egress_port)
  10651 {
  10652     int qid, q_grp, id, rv;
  10653     _bcm_td_voq_profile_t *profile;
  10654     bcm_port_t local_port, port, m_dest_port;
  10655     int msg_sel_index, cur_profile_id = -1, use_cnt, profile_id;
  10656     uint32      new_fab_pbmp;
  10657     _bcm_td_cosq_node_t *node;
  10658 
  10659     if (!_BCM_TD_IS_VOQ_GPORT(unit, gport)) {
  10660         return BCM_E_PARAM;
  10661     }
  10662     
  10663     local_port = BCM_GPORT_UCAST_QUEUE_GROUP_SYSPORTID_GET(gport);
  10664     if (!_BCM_TD_IS_PORT_DMVOQ_CAPABLE(unit, local_port)) {
  10665         LOG_ERROR(BSL_LS_BCM_COSQ,
  10666                   (BSL_META_U(unit,
  10667                               "Error: unit %d port %d is not a DestMod flow-control capable \n"),
  10668                    unit, local_port));
  10669         return BCM_E_PARAM;
  10670     }
  10671 
  10672     BCM_IF_ERROR_RETURN
  10673         (bcm_stk_modport_voq_cosq_profile_get(unit, ing_port, 
  10674                                               dest_modid, &cur_profile_id));
  10675 
  10676     /*
  10677      * check if port really has a VOQ profile attached to it.
  10678      */
  10679     if (cur_profile_id < 0) {
  10680         return BCM_E_NONE;
  10681     }
  10682 
  10683     /*
  10684      * Get the cosmap profile and add to HW.
  10685      */
  10686     BCM_IF_ERROR_RETURN
  10687         (_bcm_td_cosq_node_get(unit, gport, NULL, &local_port, &id, &node));
  10688 
  10689     profile = &node->voq_profile;
  10690 
  10691     /*
  10692      * validate that the profile we are trying to detach is really 
  10693      * the one attached to this port.
  10694      */
  10695     if (cur_profile_id != profile->id) {
  10696         return BCM_E_PARAM;
  10697     }
  10698 
  10699     qid = _BCM_TD_VOQ_GPORT_QUEUE_ID(unit, gport, 0);
  10700     q_grp = (qid - _BCM_TD_VOQ_QID_MIN_ID) % 16;
  10701 
  10702     /*
  10703      * Disconnect VOQ profile for this ingress port.
  10704      */
  10705     BCM_IF_ERROR_RETURN
  10706         (bcm_stk_modport_voq_cosq_profile_set(unit, ing_port, dest_modid, -1));
  10707 
  10708 
  10709     BCM_IF_ERROR_RETURN
  10710         (soc_profile_mem_delete(unit, _bcm_td_voq_cos_map_profile[unit], 
  10711                                 profile->hw_index));
  10712 
  10713     /* 
  10714      * get the number of ports still using this profile. if none clear
  10715      * out msg_sel register.
  10716      */
  10717     use_cnt = 0;
  10718     PBMP_PORT_ITER(unit, port) {
  10719         rv = bcm_esw_stk_port_modport_get(unit, port,
  10720                                           dest_modid, &m_dest_port);
  10721 
  10722         if ((BCM_FAILURE(rv)) || (m_dest_port != local_port)) {
  10723             continue;
  10724         }
  10725 
  10726         rv = bcm_stk_modport_voq_cosq_profile_get(unit, port, 
  10727                                                   dest_modid, &profile_id);
  10728 
  10729         if ((BCM_FAILURE(rv)) || (profile->id != profile_id)) {
  10730             continue;
  10731         }
  10732         use_cnt++;
  10733     }
  10734 
  10735     if (use_cnt) {
  10736         return BCM_E_NONE;
  10737     }
  10738 
  10739     SOC_IF_ERROR_RETURN
  10740         (_bcm_cosq_voq_find_current_msg_sel_entry(unit, local_port, 
  10741                                     fabric_egress_port, q_grp, &msg_sel_index));
  10742 
  10743     if (msg_sel_index < 0) {
  10744         return BCM_E_NOT_FOUND;
  10745     }
  10746 
  10747     SOC_IF_ERROR_RETURN
  10748         (_bcm_td_voq_fabric_port_unset(unit, local_port, 
  10749                                        fabric_egress_port, q_grp, &new_fab_pbmp));
  10750     profile->id = -1;
  10751     profile->hw_index = -1;
  10752 
  10753     return BCM_E_NONE;
  10754 }
  10755 
  10756 /*
  10757  * Function:
  10758  *      bcm_td_cosq_cpu_cosq_enable_set
  10759  * Purpose:
  10760  *      To enable/disable Rx of packets on the specified CPU cosq.
  10761  * Parameters:
  10762  *      unit          - (IN) Unit number.
  10763  *      cosq          - (IN) CPU Cosq ID
  10764  *      enable        - (IN) Enable/Disable
  10765  * Returns:
  10766  *      BCM_E_xxx
  10767  */
  10768 int
  10769 bcm_td_cosq_cpu_cosq_enable_set(
  10770     int unit, 
  10771     bcm_cos_queue_t cosq, 
  10772     int enable)
  10773 {
  10774     uint32 rval, rval1;
  10775     int enable_status;
  10776     soc_info_t *si;
  10777     _bcm_td_cosq_cpu_cosq_config_t *cpu_cosq;
  10778 
  10779     si = &SOC_INFO(unit);
  10780 
  10781     if ((cosq < 0) || (cosq >= si->num_cpu_cosq)) {
  10782         return BCM_E_PARAM;
  10783     }
  10784 
  10785     cpu_cosq = _bcm_td_cosq_cpu_cosq_config[unit][cosq];
  10786 
  10787     if (!cpu_cosq) {
  10788         return BCM_E_INTERNAL;
  10789     }
  10790     if (enable) {
  10791         enable = 1;
  10792     }
  10793     BCM_IF_ERROR_RETURN(bcm_td_cosq_cpu_cosq_enable_get(unit, cosq,
  10794                                                         &enable_status));
  10795     if (enable == enable_status) {
  10796         return BCM_E_NONE;
  10797     }
  10798 
  10799     BCM_IF_ERROR_RETURN
  10800         (READ_OP_QUEUE_CONFIG_CELLr(unit, 0, cosq, &rval));
  10801     BCM_IF_ERROR_RETURN
  10802         (READ_OP_QUEUE_CONFIG1_CELLr(unit, 0, cosq, &rval1));
  10803 
  10804     if (enable) {
  10805         soc_reg_field_set(unit, OP_QUEUE_CONFIG_CELLr, &rval,
  10806                           Q_SHARED_LIMIT_CELLf, cpu_cosq->q_shared_limit);
  10807         soc_reg_field_set(unit, OP_QUEUE_CONFIG_CELLr, &rval,
  10808                           Q_MIN_CELLf, cpu_cosq->q_min_limit);
  10809     } else {
  10810         cpu_cosq->q_shared_limit = soc_reg_field_get(unit,
  10811                                                      OP_QUEUE_CONFIG_CELLr,
  10812                                                      rval,
  10813                                                      Q_SHARED_LIMIT_CELLf);
  10814         cpu_cosq->q_min_limit = soc_reg_field_get(unit,
  10815                                                   OP_QUEUE_CONFIG_CELLr,
  10816                                                   rval,
  10817                                                   Q_MIN_CELLf);
  10818         cpu_cosq->q_limit_dynamic = soc_reg_field_get(unit,
  10819                                                       OP_QUEUE_CONFIG1_CELLr,
  10820                                                       rval1,
  10821                                                       Q_LIMIT_DYNAMIC_CELLf);
  10822         cpu_cosq->q_limit_enable = soc_reg_field_get(unit,
  10823                                                      OP_QUEUE_CONFIG1_CELLr,
  10824                                                      rval1,
  10825                                                      Q_LIMIT_ENABLE_CELLf);
  10826     }
  10827 
  10828     cpu_cosq->enable = enable;
  10829     soc_reg_field_set(unit, OP_QUEUE_CONFIG1_CELLr, &rval1,
  10830                       Q_LIMIT_DYNAMIC_CELLf, 
  10831                       enable ? cpu_cosq->q_limit_dynamic : 0);
  10832     soc_reg_field_set(unit, OP_QUEUE_CONFIG1_CELLr, &rval1,
  10833                       Q_LIMIT_ENABLE_CELLf,
  10834                       enable ? cpu_cosq->q_limit_enable : 1);
  10835     BCM_IF_ERROR_RETURN
  10836         (WRITE_OP_QUEUE_CONFIG1_CELLr(unit, 0, cosq, rval1));
  10837     BCM_IF_ERROR_RETURN
  10838         (WRITE_OP_QUEUE_CONFIG_CELLr(unit, 0, cosq, enable ? rval : 0));
  10839 
  10840     return BCM_E_NONE;
  10841 }
  10842 
  10843 /*
  10844  * Function:
  10845  *      bcm_td_cosq_cpu_cosq_enable_get
  10846  * Purpose:
  10847  *      To get enable/disable status on Rx of packets on the specified CPU cosq.
  10848  * Parameters:
  10849  *      unit          - (IN) Unit number.
  10850  *      cosq          - (IN) CPU Cosq ID
  10851  *      enable        - (OUT) Enable/Disable
  10852  * Returns:
  10853  *      BCM_E_xxx
  10854  */
  10855 int
  10856 bcm_td_cosq_cpu_cosq_enable_get(
  10857     int unit, 
  10858     bcm_cos_queue_t cosq, 
  10859     int *enable)
  10860 {
  10861     _bcm_td_cosq_cpu_cosq_config_t *cpu_cosq;
  10862     soc_info_t *si;
  10863     uint32 rval, rval1;
  10864     uint32 min_limit, shared_limit, limit_enable, dynamic_enable;
  10865     int hw_enable;
  10866 
  10867     si = &SOC_INFO(unit);
  10868 
  10869     if ((cosq < 0) || (cosq >= si->num_cpu_cosq)) {
  10870         return BCM_E_PARAM;
  10871     }
  10872 
  10873     cpu_cosq = _bcm_td_cosq_cpu_cosq_config[unit][cosq];
  10874     if (!cpu_cosq) {
  10875         return BCM_E_INTERNAL;
  10876     }
  10877 
  10878     hw_enable = 1;
  10879     /* Sync up software record with hardware status. */
  10880     BCM_IF_ERROR_RETURN
  10881         (READ_OP_QUEUE_CONFIG_CELLr(unit, 0, cosq, &rval));
  10882     BCM_IF_ERROR_RETURN
  10883         (READ_OP_QUEUE_CONFIG1_CELLr(unit, 0, cosq, &rval1));
  10884     min_limit = soc_reg_field_get(unit, OP_QUEUE_CONFIG_CELLr,
  10885                                   rval, Q_MIN_CELLf);
  10886     shared_limit = soc_reg_field_get(unit, OP_QUEUE_CONFIG_CELLr,
  10887                                      rval, Q_SHARED_LIMIT_CELLf);
  10888     limit_enable = soc_reg_field_get(unit, OP_QUEUE_CONFIG1_CELLr,
  10889                                      rval1, Q_LIMIT_ENABLE_CELLf);
  10890     dynamic_enable = soc_reg_field_get(unit, OP_QUEUE_CONFIG1_CELLr,
  10891                                        rval1, Q_LIMIT_DYNAMIC_CELLf);
  10892     if (limit_enable && (dynamic_enable == 0) &&
  10893         (min_limit == 0) && (shared_limit == 0)) {
  10894         hw_enable = 0;
  10895     }
  10896     cpu_cosq->enable = hw_enable;
  10897 
  10898     *enable = cpu_cosq->enable;
  10899     return BCM_E_NONE;
  10900 }
  10901 
  10902 
  10903 #ifndef BCM_SW_STATE_DUMP_DISABLE
  10904 /*
  10905  * Function:
  10906  *     bcm_td_cosq_sw_dump
  10907  * Purpose:
  10908  *     Displays COS Queue information maintained by software.
  10909  * Parameters:
  10910  *     unit - Device unit number
  10911  * Returns:
  10912  *     None
  10913  */
  10914 void
  10915 bcm_td_cosq_sw_dump(int unit)
  10916 {
  10917     bcm_port_t port;
  10918 
  10919     LOG_CLI((BSL_META_U(unit,
  10920                         "\nSW Information COSQ - Unit %d\n"), unit));
  10921 
  10922     PBMP_ALL_ITER(unit, port) {
  10923         if (IS_CPU_PORT(unit, port)) {
  10924             continue;
  10925         }
  10926         (void)_bcm_td_cosq_port_info_dump(unit, port);
  10927     }
  10928 
  10929     return;
  10930 }
  10931 #endif /* BCM_SW_STATE_DUMP_DISABLE */
  10932 
  10933 /*
  10934  * Function:
  10935  *     _bcm_td_port_enqueue_set
  10936  * Purpose:
  10937  *     Enable or Disable the enqueing the packets to the port
  10938  * Parameters:
  10939  *     unit       - (IN) unit number
  10940  *     gport      - (IN) gport of the port 
  10941  *     enable     - (IN) TRUE to enable
  10942  *                      FALSE to disable
  10943  * Returns:
  10944  *     BCM_E_XXX
  10945  */
  10946 
  10947 int
  10948 _bcm_td_port_enqueue_set(int unit, bcm_port_t gport,
  10949                          int enable)
  10950 {
  10951     uint64 rval64 ,rval64_tmp ;
  10952     int mmu_port, phy_port;
  10953     int i;
  10954     int rv = BCM_E_NONE;
  10955     bcm_port_t local_port;
  10956     soc_info_t *si;
  10957     soc_reg_t reg_tmp;
  10958     soc_reg_t reg[2][2] = {
  10959         {
  10960             OUTPUT_PORT_RX_ENABLE0_64r,
  10961             OUTPUT_PORT_RX_ENABLE1_64r,
  10962         },
  10963         {
  10964             INPUT_PORT_RX_ENABLE0_64r,
  10965             INPUT_PORT_RX_ENABLE1_64r,
  10966         }
  10967     };
  10968 
  10969     COMPILER_64_ZERO(rval64);
  10970     COMPILER_64_ZERO(rval64_tmp);
  10971 
  10972 
  10973     BCM_IF_ERROR_RETURN
  10974         (_bcm_td_cosq_localport_resolve(unit, gport, &local_port));
  10975 
  10976     si = &SOC_INFO(unit);
  10977 
  10978     phy_port = si->port_l2p_mapping[local_port];
  10979     mmu_port = si->port_p2m_mapping[phy_port];
  10980 
  10981     for (i = 0; i < 2; i++) {
  10982 
  10983         if (SOC_PBMP_MEMBER(si->xpipe_pbm, local_port)) { /* X pipe */
  10984             reg_tmp = reg[i][0];
  10985         } else { /* Y pipe */
  10986             reg_tmp = reg[i][1];
  10987         }
  10988         SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg_tmp, REG_PORT_ANY, 0, &rval64));
  10989 
  10990         mmu_port &= 0x3f;
  10991  
  10992         /* OUTPUT_PORT_RX and INPUT_PORT_RX is organised as follows:
  10993            port 0 to port 32 in RX_ENABLE0 and port 33 to 63 in RX_ENABLE1
  10994            the following logic is to set 0-32 bits for port 33 to 63 in RX_ENABLE1 */
  10995 
  10996         if (mmu_port > 32) {
  10997             mmu_port = mmu_port - 33;
  10998         }
  10999 
  11000         if (mmu_port < 32) {
  11001             COMPILER_64_SET(rval64_tmp, 0, 1 << mmu_port);
  11002         } else {
  11003             COMPILER_64_SET(rval64_tmp, 1 << (mmu_port - 32), 0);
  11004         }
  11005 
  11006         if (!enable) {
  11007             COMPILER_64_NOT(rval64_tmp);
  11008             COMPILER_64_AND(rval64, rval64_tmp);
  11009         } else {
  11010             COMPILER_64_OR(rval64, rval64_tmp);
  11011         }
  11012         SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg_tmp, REG_PORT_ANY, 0, rval64));
  11013     }
  11014     return rv;
  11015 }
  11016 
  11017 /*
  11018  * Function:
  11019  *     _bcm_td_port_enqueue_get
  11020  * Purpose:
  11021  *     Getting the enqueing state of the port
  11022  * Parameters:
  11023  *     unit       - (IN) unit number
  11024  *     gport      - (IN) gport of the port 
  11025  *     enable     - (OUT) TRUE if enable
  11026  *                      FALSE if disable
  11027  * Returns:
  11028  *     BCM_E_XXX
  11029  */
  11030 
  11031 
  11032 int
  11033 _bcm_td_port_enqueue_get(int unit, bcm_port_t gport,
  11034                          int *enable)
  11035 {
  11036     uint64 rval64 ; 
  11037     int mmu_port, phy_port;
  11038     int rv = BCM_E_NONE;
  11039     bcm_port_t local_port;
  11040     soc_info_t *si;
  11041     soc_reg_t reg;
  11042 
  11043     COMPILER_64_ZERO(rval64);
  11044 
  11045     BCM_IF_ERROR_RETURN
  11046         (_bcm_td_cosq_localport_resolve(unit, gport, &local_port));
  11047 
  11048     si = &SOC_INFO(unit);
  11049 
  11050     phy_port = si->port_l2p_mapping[local_port];
  11051     mmu_port = si->port_p2m_mapping[phy_port];
  11052 
  11053 
  11054     if (SOC_PBMP_MEMBER(si->xpipe_pbm, local_port)) { /* X pipe */
  11055         reg = OUTPUT_PORT_RX_ENABLE0_64r;
  11056     } else { /* Y pipe */
  11057         reg = OUTPUT_PORT_RX_ENABLE1_64r;
  11058     }
  11059     SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, REG_PORT_ANY, 0, &rval64));
  11060 
  11061     mmu_port &= 0x3f;
  11062 
  11063     if (mmu_port > 32) {
  11064         mmu_port = mmu_port - 33;
  11065     }
  11066     if (COMPILER_64_BITTEST(rval64 , mmu_port)) {
  11067         *enable = TRUE;
  11068     } else {
  11069         *enable = FALSE;
  11070     }
  11071     return rv;
  11072 }
  11073 
  11074 /* 
  11075  * Function:    _bcm_td_wred_war_ports_select
  11076  *
  11077  * Purpose:     Selects one extended queue port and one 
  11078  *              regular port from each (X/Y)pipeline. 
  11079  */
  11080 STATIC int
  11081 _bcm_td_wred_war_ports_select(int unit)
  11082 {
  11083    
  11084    soc_info_t      *si;
  11085    soc_port_t local_port;
  11086    soc_port_t rcpu_port = 0xff; /* Invalid port number */
  11087    int local_port_mode;
  11088    _wred_war_ctrl_t *w;
  11089    int valid_port = 0;
  11090    mac_driver_t *mac = NULL;
  11091 
  11092    mac = &soc_mac_x;
  11093    w = &war;
  11094 
  11095    w->port[0] =  w->port[1] =  w->port[2] =  w->port[3] = -1;
  11096    
  11097    si = &SOC_INFO(unit);
  11098 
  11099    if (SOC_IS_RCPU_UNIT(unit)) {
  11100        rcpu_port = RCPU_PORT(unit);
  11101    }
  11102   
  11103    PBMP_ALL_ITER(unit, local_port) {
  11104       valid_port = PORT_IS_VALID(unit, local_port);
  11105       if (!valid_port || (rcpu_port == local_port)) {
  11106           continue;
  11107       }
  11108 	  
  11109       SOC_IF_ERROR_RETURN
  11110             (MAC_ENCAP_GET(mac, unit, local_port, &local_port_mode));
  11111       
  11112       if (SOC_PBMP_MEMBER(si->xpipe_pbm, local_port)) { /* X pipe */
  11113           if ((si->port_num_ext_cosq[local_port] == 0) && (w->port[0] == -1)) { 
  11114               w->port[0] = local_port;     /* regular port */
  11115               w->port_mode[0] = local_port_mode;
  11116           } else if ((si->port_num_ext_cosq[local_port] != 0) &&
  11117                      (w->port[1] == -1)) { /* extended queue port */
  11118 	      w->port[1] = local_port;
  11119 	      w->port_mode[1] = local_port_mode;
  11120 	  } else {
  11121 	      continue; 
  11122 	  }
  11123       } else { /* Y pipe */
  11124           if ((si->port_num_ext_cosq[local_port] == 0) && (w->port[2] == -1)) {
  11125               w->port[2] = local_port;     /* regular port */
  11126   	      w->port_mode[2] = local_port_mode;
  11127           } else if ((si->port_num_ext_cosq[local_port] != 0) &&
  11128                      (w->port[3] == -1)) { /* extended queue port */
  11129 	      w->port[3] = local_port;
  11130 	      w->port_mode[3] = local_port_mode;
  11131 	  } else {
  11132 	      continue;
  11133 	  }
  11134       }	  
  11135       if ((w->port[0] != -1) && (w->port[1] != -1) && 
  11136           (w->port[2] != -1) && (w->port[3] != -1)) {
  11137           break;
  11138       }
  11139    }
  11140   
  11141    return SOC_E_NONE;
  11142 }
  11143 
  11144 /*
  11145  * Function:     _bcm_td_wred_war_configure
  11146  *
  11147  * Purpose:      configures wred workaround on ports and switch.
  11148  *
  11149  * Description : This function function does below things:
  11150  *               -Stops live traffic by configuring EPC_LINK_BMAP.
  11151  *               -Converts higig ports into xe ports and removes higig
  11152  *                configuration that was on the ports.
  11153  *               -Configures MAC loopback mode on four ports. 
  11154  *               -Configures MAC CRC mode to 1 to generate CRC packetsi. 
  11155  *               -Enables CRC checks on the switch and configures ING_PRI_CNG
  11156  *                map table to mark ingress packets with red color. 
  11157  */
  11158 STATIC int
  11159 _bcm_td_wred_war_configure(int unit)
  11160 {
  11161    int     i;
  11162    uint32  rval;
  11163    uint64  tx_ctrl;
  11164    pbmp_t  pbm;
  11165    uint32  stg_entry[SOC_MAX_MEM_WORDS];
  11166    mac_driver_t            *mac = NULL;
  11167    _wred_war_ctrl_t        *w;
  11168    port_tab_entry_t        p_entry;
  11169    epc_link_bmap_entry_t   epc_entry;
  11170    uint32 pri_map[SOC_MAX_MEM_FIELD_WORDS];
  11171 
  11172    sal_memset(pri_map, 0, sizeof(pri_map));
  11173 
  11174 
  11175    mac = &soc_mac_x;
  11176    w = &war;
  11177 
  11178    SOC_PBMP_CLEAR(pbm);
  11179    /* Reads default link status.*/
  11180    SOC_IF_ERROR_RETURN(READ_EPC_LINK_BMAPm(unit, MEM_BLOCK_ALL,
  11181                                            0, &w->epc_entry));
  11182 
  11183    /* Reads default STG mode on switch.*/
  11184    SOC_IF_ERROR_RETURN(soc_mem_read(unit, STG_TABm, MEM_BLOCK_ANY, 1, w->stg_entry));
  11185 
  11186    sal_memset(&epc_entry, 0, sizeof(epc_entry));
  11187    sal_memset(&stg_entry, 0, sizeof(stg_entry));
  11188 
  11189    /* Removes all ports from EPC_LINK_BMAP table. */
  11190    if (SOC_IS_RCPU_UNIT(unit)) {
  11191        SOC_PBMP_PORT_ADD(pbm, RCPU_PORT(unit));
  11192    }
  11193    soc_mem_pbmp_field_set(unit, EPC_LINK_BMAPm, &epc_entry, PORT_BITMAPf, &pbm);
  11194    SOC_IF_ERROR_RETURN(WRITE_EPC_LINK_BMAPm(unit, MEM_BLOCK_ALL,
  11195                                             0, &epc_entry));
  11196 
  11197    for (i = 0; i < SOC_WRED_WR_MAX_NUM_PORTS; i++) {
  11198       if (w->port[i] == -1) {
  11199           continue;
  11200       }
  11201 
  11202       /*Get current settings of each port*/
  11203       BCM_IF_ERROR_RETURN(bcm_esw_port_enable_get(unit, w->port[i], &w->enable[i]));
  11204       BCM_IF_ERROR_RETURN(bcm_esw_port_speed_get(unit, w->port[i], &w->speed[i]));
  11205       BCM_IF_ERROR_RETURN(bcm_esw_port_duplex_get(unit, w->port[i], &w->duplex[i]));
  11206       BCM_IF_ERROR_RETURN(bcm_esw_port_advert_get(unit, w->port[i], &w->advert[i]));
  11207       BCM_IF_ERROR_RETURN(bcm_esw_port_autoneg_get(unit, w->port[i], &w->autoneg[i]));
  11208 
  11209       /* Configures IEEE mode on all non IEEE ports.*/
  11210       if ((w->port_mode[i] != SOC_ENCAP_IEEE) && SOC_IS_TRIDENT(unit)) {
  11211 	  SOC_IF_ERROR_RETURN(MAC_ENCAP_SET(mac, unit, w->port[i],
  11212                                                         SOC_ENCAP_IEEE));
  11213           SOC_IF_ERROR_RETURN(soc_mem_field32_modify(unit, EGR_PORTm,
  11214                                                  w->port[i], HIGIG2f, 0));
  11215           SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, XLPORT_CONFIGr,
  11216                                             w->port[i], HIGIG2_MODEf, 0));
  11217           SOC_IF_ERROR_RETURN(soc_mem_field32_modify(unit, EGR_ING_PORTm,
  11218                                                  w->port[i], HIGIG2f, 0));
  11219       }
  11220       
  11221       BCM_IF_ERROR_RETURN(bcm_esw_port_enable_set(unit, w->port[i], w->enable[i]));
  11222       /* Configures MAC loop back on port.*/ 
  11223       SOC_IF_ERROR_RETURN(bcm_esw_port_loopback_set(unit, w->port[i], BCM_PORT_LOOPBACK_MAC));
  11224 
  11225       /* Configures XMAC_TX_CTRL register to send FCS packets. */ 
  11226       SOC_IF_ERROR_RETURN(READ_XMAC_TX_CTRLr(unit, w->port[i], &tx_ctrl));
  11227       w->port_crc_mode[i] = soc_reg64_field32_get(unit, XMAC_TX_CTRLr, 
  11228                                                   tx_ctrl, CRC_MODEf);
  11229       soc_reg64_field32_set(unit, XMAC_TX_CTRLr, &tx_ctrl, CRC_MODEf, 1);
  11230       SOC_IF_ERROR_RETURN(WRITE_XMAC_TX_CTRLr(unit, w->port[i], tx_ctrl));
  11231   
  11232       /* Set PORT_BRIDGE bit on port.*/ 
  11233       SOC_IF_ERROR_RETURN(soc_mem_read(unit, PORT_TABm, MEM_BLOCK_ANY, 
  11234                                        w->port[i], &w->port_entry[i]));
  11235       sal_memcpy(&p_entry, &w->port_entry[i], sizeof(p_entry));
  11236       soc_mem_field32_set(unit, PORT_TABm, &p_entry, PORT_BRIDGEf, 1);
  11237       SOC_IF_ERROR_RETURN(soc_mem_write(unit, PORT_TABm, MEM_BLOCK_ALL,
  11238                                         w->port[i], &p_entry));
  11239 
  11240       SOC_PBMP_PORT_ADD(pbm, w->port[i]);
  11241 
  11242       stg_entry[STG_WORD(w->port[i])] |= (0x3 << STG_BITS_SHIFT(w->port[i]));
  11243    }
  11244 
  11245    /* Saves default configuration of MISCCONFIG register in global structure
  11246       and configures parity check and parity gen  fields. */
  11247    SOC_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, &rval));
  11248    w->parity_gen_en = soc_reg_field_get(unit, MISCCONFIGr, rval, PARITY_GEN_ENf);
  11249    w->parity_chk_en = soc_reg_field_get(unit, MISCCONFIGr, rval, PARITY_CHK_ENf);
  11250 
  11251    soc_reg_field_set(unit, MISCCONFIGr, &rval, PARITY_CHK_ENf, 1);
  11252    soc_reg_field_set(unit, MISCCONFIGr, &rval, PARITY_GEN_ENf, 1);
  11253    SOC_IF_ERROR_RETURN(WRITE_MISCCONFIGr(unit, rval));
  11254 
  11255    /* Write spanning tree group port state to hw. */
  11256    SOC_IF_ERROR_RETURN(soc_mem_write(unit, STG_TABm, MEM_BLOCK_ALL,
  11257                                      1, stg_entry));
  11258 
  11259    /* Write port status on switch. */
  11260    soc_mem_pbmp_field_set(unit, EPC_LINK_BMAPm, &epc_entry, PORT_BITMAPf, &pbm);
  11261    SOC_IF_ERROR_RETURN(WRITE_EPC_LINK_BMAPm(unit, MEM_BLOCK_ALL, 
  11262                                             0, &epc_entry));
  11263  
  11264    /* Mark priority 0 packets with red color. */ 
  11265    if (SOC_IS_TRIDENT3X(unit)) {
  11266        SOC_IF_ERROR_RETURN(READ_PHB_MAPPING_TBL_1m(unit, MEM_BLOCK_ANY,
  11267                                                  0, &pri_map));
  11268        soc_mem_field32_set(unit, PHB_MAPPING_TBL_1m, &pri_map, CNGf, 1);
  11269        SOC_IF_ERROR_RETURN(WRITE_PHB_MAPPING_TBL_1m(unit, MEM_BLOCK_ALL,
  11270                                                   0, &pri_map));
  11271    } else {
  11272        SOC_IF_ERROR_RETURN(READ_ING_PRI_CNG_MAPm(unit, MEM_BLOCK_ANY,
  11273                                                  0, &pri_map));
  11274        soc_mem_field32_set(unit, ING_PRI_CNG_MAPm, &pri_map, CNGf, 1);
  11275        SOC_IF_ERROR_RETURN(WRITE_ING_PRI_CNG_MAPm(unit, MEM_BLOCK_ALL,
  11276                                                   0, &pri_map));
  11277    }
  11278  
  11279    return SOC_E_NONE;
  11280 }
  11281 
  11282 /*
  11283  * Function: _bcm_td_wred_war_hw_state_restore
  11284  *
  11285  * Purpose:  Restores default state of ports and other reg/mem's.
  11286  */
  11287 
  11288 STATIC int
  11289 _bcm_td_wred_war_hw_state_restore(int unit)
  11290 {
  11291    int     i;
  11292    int     mode;
  11293    uint32  rval;
  11294    uint64  tx_ctrl;
  11295    soc_pbmp_t       pbmp;
  11296    mac_driver_t     *mac = NULL;
  11297    _wred_war_ctrl_t *w;
  11298    uint32 pri_map[SOC_MAX_MEM_FIELD_WORDS];
  11299 
  11300    int    adv, max_speed = 0;
  11301    mac = &soc_mac_x;
  11302    w   = &war;
  11303 
  11304    SOC_PBMP_CLEAR(pbmp);
  11305 
  11306    sal_memset(pri_map, 0, sizeof(pri_map));
  11307 
  11308    for (i = 0; i < SOC_WRED_WR_MAX_NUM_PORTS; i++) {
  11309       if (w->port[i] == -1) {
  11310           continue;
  11311       }
  11312 
  11313       if ((w->port_mode[i] != SOC_ENCAP_IEEE) && SOC_IS_TRIDENT(unit)) {
  11314           SOC_IF_ERROR_RETURN
  11315             (MAC_ENCAP_SET(mac, unit, w->port[i], w->port_mode[i]));
  11316 
  11317           mode = soc_property_port_get(unit, w->port[i], 
  11318                                        spn_HIGIG2_HDR_MODE, 0);
  11319           SOC_IF_ERROR_RETURN(soc_mem_field32_modify(unit, EGR_PORTm,
  11320                                               w->port[i], HIGIG2f, mode));
  11321           SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, XLPORT_CONFIGr,
  11322                                          w->port[i], HIGIG2_MODEf, mode));
  11323           SOC_IF_ERROR_RETURN(soc_mem_field32_modify(unit, EGR_ING_PORTm,
  11324                                               w->port[i], HIGIG2f, mode));
  11325       }
  11326       SOC_IF_ERROR_RETURN
  11327             (bcm_esw_port_loopback_set(unit, w->port[i], BCM_PORT_LOOPBACK_NONE));
  11328 
  11329       SOC_IF_ERROR_RETURN(bcm_esw_port_speed_max(unit, w->port[i], &max_speed));
  11330       BCM_IF_ERROR_RETURN(bcm_esw_port_autoneg_set(unit, w->port[i], w->autoneg[i]));
  11331       /* if speed is 0, set the port speed to max. if port autoneg is enable,
  11332       * port max speed may be 0. if port autoneg is enable and port max speed is 0,
  11333       * bcm_esw_port_speed_set will be return SOC_E_CONFIG(-15).
  11334       */
  11335       if (w->autoneg[i] == 0) {
  11336           BCM_IF_ERROR_RETURN(bcm_esw_port_duplex_set(unit, w->port[i], w->duplex[i]));
  11337           if (w->speed[i] != 0 || max_speed != 0) {
  11338               BCM_IF_ERROR_RETURN(bcm_esw_port_speed_set(unit, w->port[i], w->speed[i]));
  11339           }
  11340       }
  11341       adv = soc_property_port_get(unit, w->port[i], spn_PORT_INIT_ADV, -1);
  11342       if (adv != -1) {
  11343           BCM_IF_ERROR_RETURN(bcm_esw_port_advert_set(unit, w->port[i], w->advert[i]));      
  11344       }
  11345       BCM_IF_ERROR_RETURN(bcm_esw_port_enable_set(unit, w->port[i], w->enable[i]));
  11346 
  11347       SOC_IF_ERROR_RETURN(READ_XMAC_TX_CTRLr(unit, w->port[i], &tx_ctrl));
  11348       soc_reg64_field32_set(unit, XMAC_TX_CTRLr, &tx_ctrl, 
  11349                             CRC_MODEf, w->port_crc_mode[i]);
  11350       SOC_IF_ERROR_RETURN(WRITE_XMAC_TX_CTRLr(unit, w->port[i], tx_ctrl));
  11351 
  11352       /* Restore settings on port.*/
  11353       SOC_IF_ERROR_RETURN(soc_mem_write(unit, PORT_TABm, MEM_BLOCK_ALL, 
  11354                                         w->port[i], &w->port_entry[i]));
  11355 
  11356       BCM_IF_ERROR_RETURN(bcm_esw_stat_clear(unit, w->port[i]));
  11357       SOC_PBMP_PORT_ADD(pbmp, w->port[i]);
  11358    }
  11359 
  11360    SOC_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, &rval));
  11361    soc_reg_field_set(unit, MISCCONFIGr, &rval, 
  11362                      PARITY_CHK_ENf, w->parity_gen_en);
  11363    soc_reg_field_set(unit, MISCCONFIGr, &rval, 
  11364                      PARITY_GEN_ENf, w->parity_chk_en);
  11365    SOC_IF_ERROR_RETURN(WRITE_MISCCONFIGr(unit, rval));
  11366 
  11367    /* Write default spanning tree group port states to hw. */
  11368    SOC_IF_ERROR_RETURN(soc_mem_write(unit, STG_TABm, MEM_BLOCK_ALL, 
  11369                                      1, w->stg_entry));
  11370 
  11371    /* Restore default value in ING_PR_CNG_MAP_TABLE. */
  11372    if (SOC_IS_TRIDENT3X(unit)) {
  11373        SOC_IF_ERROR_RETURN(READ_PHB_MAPPING_TBL_1m(unit, MEM_BLOCK_ANY,
  11374                                                  0, &pri_map));
  11375        soc_mem_field32_set(unit, PHB_MAPPING_TBL_1m, &pri_map, CNGf, 0);
  11376        SOC_IF_ERROR_RETURN(WRITE_PHB_MAPPING_TBL_1m(unit, MEM_BLOCK_ALL,
  11377                                                         0, &pri_map));
  11378    } else {
  11379        SOC_IF_ERROR_RETURN(READ_ING_PRI_CNG_MAPm(unit, MEM_BLOCK_ANY,
  11380                                                  0, &pri_map));
  11381        soc_mem_field32_set(unit, ING_PRI_CNG_MAPm, &pri_map, CNGf, 0);
  11382        SOC_IF_ERROR_RETURN(WRITE_ING_PRI_CNG_MAPm(unit, MEM_BLOCK_ALL,
  11383                                                         0, &pri_map));
  11384    }
  11385 
  11386    /* Clear counters of war ports. */
  11387    SOC_IF_ERROR_RETURN(soc_counter_set32_by_port(unit, pbmp, 0));
  11388 
  11389    /* Write default port status to hw. */
  11390    SOC_IF_ERROR_RETURN(WRITE_EPC_LINK_BMAPm(unit, MEM_BLOCK_ALL,
  11391                                             0, &w->epc_entry));
  11392    
  11393    return SOC_E_NONE;
  11394 }
  11395 
  11396 /*
  11397  * Function:     _bcm_td_wred_mem_war
  11398  *
  11399  * Purpose:      Warkaound to recover WRED memories from 
  11400  *               corrupted state to good state.
  11401  *
  11402  * Description : This logic sends 8 unicast packets that are larger
  11403  *               than 1 cell and contain a bad crc from below ports
  11404  *               to put WRED memories in good state.
  11405  *
  11406  *               - Packet 1 ingresses on any port in the x-pipe and is supposed
  11407  *                 to be switched to a non-extended queuing port in the x-pipe 
  11408  *               - Packet 2 ingresses on any port in the x-pipe and is supposed 
  11409  *                 to be switched to a non-extended queuing port in the y-pipe
  11410  *               - Packet 3 ingresses on any port in the x-pipe and is supposed 
  11411  *                 to be switched to an extended queuing port in the x-pipe 
  11412  *               - Packet 4 ingresses on any port in the x-pipe and is supposed 
  11413  *                 to be switched to an extended queuing port in the y-pipe
  11414  *
  11415  *               - Packet 5 ingresses on any port in the y-pipe and is supposed 
  11416  *                 to be switched to a non-extended queuing port in the x-pipe
  11417  *               - Packet 6 ingresses on any port in the y-pipe and is supposed 
  11418  *                 to be switched to a non-extended queuing port in the y-pip
  11419  *               - Packet 7 ingresses on any port in the y-pipe and is supposed 
  11420  *                 to be switched to an extended queuing port in the x-pipe
  11421  *               - Packet 8 ingresses on any port in the y-pipe and is supposed 
  11422  *                 to be switched to an extended queuing port in the y-pipe
  11423  */
  11424 int 
  11425 _bcm_td_wred_mem_war(int unit)
  11426 {
  11427    int         rv = SOC_E_NONE;
  11428    int         i, j;
  11429    int         l2_flags;
  11430    int         pkt_flags;
  11431    bcm_pkt_t   *tx_pkt;
  11432    bcm_mac_t   mac = {0x00, 0x00, 0x00, 0x00, 0x00, 0x11};
  11433    bcm_mac_t   dstmac, srcmac; 
  11434    l2x_entry_t l2x_entry;
  11435    _wred_war_ctrl_t *w;
  11436 
  11437    w = &war;
  11438 
  11439    sal_memset(&l2x_entry, 0, sizeof (l2x_entry)); 
  11440    sal_memset(dstmac, 0, sizeof (dstmac));
  11441    sal_memset(srcmac, 0, sizeof (srcmac));
  11442 
  11443    /* Selects one regular port and one extented queue port from each pipeline
  11444     * and configures wred workaround settings on selected ports and on switch.
  11445     */
  11446    BCM_IF_ERROR_RETURN(_bcm_td_wred_war_ports_select(unit));
  11447    BCM_IF_ERROR_RETURN(_bcm_td_wred_war_configure(unit));
  11448 
  11449 
  11450    if (SOC_IS_TRIDENT(unit)) {
  11451        /* Clears stray entries. */
  11452        l2_flags = BCM_L2_REPLACE_DELETE | BCM_L2_REPLACE_MATCH_STATIC |
  11453                   BCM_L2_REPLACE_VLAN_AND_VPN_TYPE;
  11454        rv = bcm_esw_l2_replace(unit, l2_flags, NULL, -1, -1, -1);
  11455        if (rv != BCM_E_NONE) {
  11456            BCM_IF_ERROR_RETURN(_bcm_td_wred_war_hw_state_restore(unit));
  11457            return rv;
  11458        }
  11459 
  11460        /* Adds L2 entries in L2 table. */
  11461        soc_L2Xm_field32_set(unit, &l2x_entry, KEY_TYPEf, 0);
  11462        soc_L2Xm_field32_set(unit, &l2x_entry, STATIC_BITf, 1);
  11463        soc_L2Xm_field32_set(unit, &l2x_entry, VALIDf, 1);
  11464        soc_L2Xm_field32_set(unit, &l2x_entry, VLAN_IDf, 1);
  11465        for (i = 0; i < SOC_WRED_WR_MAX_NUM_PORTS; i++) {
  11466           if (w->port[i] == -1) {
  11467               continue;
  11468           }
  11469           MAC_LSB_SHIFT(dstmac, mac, i);
  11470           soc_L2Xm_mac_addr_set(unit,&l2x_entry, MAC_ADDRf, dstmac);
  11471           soc_L2Xm_field32_set(unit, &l2x_entry, PORT_NUMf, w->port[i]);
  11472           soc_mem_insert(unit, L2Xm, MEM_BLOCK_ALL, (void *)&l2x_entry);
  11473        }
  11474   } 
  11475 
  11476    /* Allocates memory for packet. */
  11477    pkt_flags = BCM_TX_CRC_APPEND | BCM_TX_NO_PAD;
  11478    rv = bcm_pkt_alloc(unit, WRED_MIN_PKT_SIZE, pkt_flags, &tx_pkt);
  11479    if (rv != BCM_E_NONE) {
  11480        BCM_IF_ERROR_RETURN(_bcm_td_wred_war_hw_state_restore(unit));
  11481        return rv;
  11482    }
  11483 
  11484    /* Configure packet parameters.*/
  11485    tx_pkt->unit = unit;
  11486    tx_pkt->call_back = 0;
  11487    tx_pkt->blk_count = 1;
  11488    tx_pkt->_vtag[0] = 0x81;
  11489    tx_pkt->_vtag[1] = 0x00;
  11490    tx_pkt->_vtag[2] = 0x00;
  11491    tx_pkt->_vtag[3] = 0x01;
  11492    tx_pkt->flags |= BCM_PKT_F_NO_VTAG;
  11493    tx_pkt->opcode = BCM_HG_OPCODE_UC;
  11494 	
  11495    /* This logic prepares 8 SOBMH packets with different src 
  11496     * and dst mac addresses and transmits packets from regular ports.
  11497     */			
  11498    for (i = 0; i < SOC_WRED_WR_MAX_NUM_PORTS; i++) {
  11499      if ((w->port[i] == -1) || (i == 1) || (i == 3)) {
  11500           /* Skip if the port is extended port.
  11501            * Send packets only from regular port.
  11502            */
  11503           continue;
  11504       }
  11505       MAC_LSB_SHIFT(srcmac, mac, i);
  11506       BCM_PKT_HDR_SMAC_SET(tx_pkt, srcmac);
  11507       BCM_PKT_PORT_SET(tx_pkt, w->port[i], FALSE, FALSE);
  11508       		
  11509       for (j = 0; j < SOC_WRED_WR_MAX_NUM_PORTS; j++) {
  11510          if ((w->port[j] == -1)) {
  11511              continue;
  11512          }
  11513 
  11514          MAC_LSB_SHIFT(dstmac, mac, j);
  11515          BCM_PKT_HDR_DMAC_SET(tx_pkt, dstmac);
  11516 
  11517          if (SOC_IS_TITAN(unit)) {
  11518              tx_pkt->flags |= BCM_PKT_F_HGHDR;
  11519              tx_pkt->flags |= BCM_TX_SRC_MOD;
  11520              tx_pkt->src_mod = 2; /* Some randum value. */
  11521              tx_pkt->src_port = 0;
  11522              tx_pkt->dest_port = w->port[j];
  11523              tx_pkt->dest_mod = (j > 1) ? 1 : 0; /* To handle DUAL_MODID's. */
  11524          }
  11525 
  11526          rv = bcm_esw_tx(unit, tx_pkt, NULL);
  11527          if (rv <= -1) {
  11528 	     goto cleanup;
  11529 	 }
  11530       }
  11531    }
  11532    
  11533 cleanup:
  11534     /* Frees packet pointer. */
  11535     rv = bcm_pkt_free(unit, tx_pkt);
  11536 
  11537     if (SOC_IS_TRIDENT(unit)) {
  11538         /* Delete L2 entries. */
  11539         for (i = 0; i < SOC_WRED_WR_MAX_NUM_PORTS; i++) {
  11540            if (w->port[i] == -1) {
  11541                continue;
  11542            }
  11543            MAC_LSB_SHIFT(dstmac, mac, i);
  11544            soc_L2Xm_mac_addr_set(unit,&l2x_entry, MAC_ADDRf, dstmac);
  11545            soc_L2Xm_field32_set(unit, &l2x_entry, PORT_NUMf, w->port[i]);
  11546            SOC_IF_ERROR_RETURN(soc_mem_delete(unit, L2Xm,
  11547                                MEM_BLOCK_ANY, (void *)&l2x_entry));
  11548         }
  11549     } 
  11550 
  11551     BCM_IF_ERROR_RETURN(_bcm_td_wred_war_hw_state_restore(unit));
  11552              
  11553     return rv;
  11554 }
  11555 #else /* BCM_TRIDENT_SUPPORT */
  11556 int _td_cosq_not_empty;
  11557 #endif  /* BCM_TRIDENT_SUPPORT */