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


      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  * MMU/Cosq soc routines
      8  */
      9 
     10 #include <sal/core/libc.h>
     11 #include <shared/bsl.h>
     12 #include <soc/debug.h>
     13 #include <soc/util.h>
     14 #include <soc/mem.h>
     15 #include <soc/trident2.h>
     16 #if defined(BCM_TRIDENT2_SUPPORT)
     17 #include <soc/td2_td2p.h>
     18 
     19 #define _TD2_XPIPE 0
     20 #define _TD2_YPIPE 1
     21 
     22 #define _TD2_HSP_PORT_MAX_L0    5
     23 #define _TD2_HSP_PORT_MAX_L1    10
     24 #define _TD2_HSP_PORT_MAX_COS   8
     25 
     26 #define _SOC_TD2_IS_HSP_PORT(u,p)   \
     27         ((IS_CE_PORT((u),(p))) ||   \
     28         ((IS_HG_PORT((u),(p))) && (SOC_INFO((u)).port_speed_max[(p)] >= 100000)))
     29 
     30 typedef enum {
     31     _SOC_TD2_LLS_OP_TEAR = 0,
     32     _SOC_TD2_LLS_OP_SETUP,
     33     _SOC_TD2_LLS_OP_TRAVERSE
     34 } _soc_td2p_lls_op_mode_t;
     35 
     36 /* number of registers in the set to support Dynamic Scheduling */
     37 #define _SOC_TD2PLUS_DYN_REGISTER_SET    4  
     38 
     39 typedef struct soc_td2_fc_map_shadow_memory_s {
     40     soc_mem_t mem;
     41     uint32  *mem_shadow;
     42 }soc_td2_fc_map_shadow_memory_t;
     43 
     44 typedef struct soc_td2_fc_map_shadow_s {
     45     soc_td2_fc_map_shadow_memory_t* shadow_array;
     46     int mem_count;
     47 }soc_td2_fc_map_shadow_t;
     48 
     49 
     50 static soc_mem_t fc_map_mems[] = {
     51     MMU_INTFI_XPIPE_FC_MAP_TBL0m,
     52     MMU_INTFI_XPIPE_FC_MAP_TBL1m,
     53     MMU_INTFI_YPIPE_FC_MAP_TBL0m,
     54     MMU_INTFI_YPIPE_FC_MAP_TBL1m
     55     };
     56 
     57 static soc_td2_fc_map_shadow_t soc_td2_fc_map_shadow[SOC_MAX_NUM_DEVICES];
     58 
     59 static int _td2_invalid_ptr[SOC_MAX_NUM_DEVICES][SOC_TD2_NODE_LVL_MAX];
     60 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
     61 static int _td2p_prev_invalid_ptr[SOC_MAX_NUM_DEVICES][SOC_TD2_NODE_LVL_MAX];
     62 #endif
     63 
     64 /* Structure to maintain the ports that are undergoing dyn sched*/
     65 typedef struct _soc_td2p_port_dyn_sched_s {
     66     sal_mutex_t     lock;
     67     int             port[_SOC_TD2PLUS_DYN_REGISTER_SET];
     68     int             _soc_td2plus_init_done[SOC_MAX_NUM_DEVICES];
     69 } _soc_td2p_port_dyn_sched_t;
     70 
     71 static _soc_td2p_port_dyn_sched_t _td2p_dyn_sched_unit_data[SOC_MAX_NUM_DEVICES];
     72 
     73 /*
     74  * Function:
     75  *     _soc_td2plus_alloc_dyn_set
     76  * Purpose:
     77  *     This function allocates the register available from
     78  *     the set of SP_WERR_DYN_CHANGEnA/nB/nC (n=0,1,2,3) to the port and 
     79  *     updates the structure _td2p_dyn_sched_unit_data to keep track 
     80  *     of the used registers from the set.
     81  * Parameters:
     82  *     unit       - (IN) unit number
     83  *     port       - (IN) local port number
     84  *     r_a        - (OUT) SP_WERR_DYN_CHANGEnA register
     85  *     r_b        - (OUT) SP_WERR_DYN_CHANGEnB register
     86  *     r_ctrl     - (OUT) SP_WERR_DYN_CHANGEnC register
     87  * Returns:
     88  *     SOC_E_XXX
     89  */
     90 STATIC int _soc_td2plus_alloc_dyn_set(int unit, int port, 
     91             soc_reg_t *r_a, soc_reg_t *r_b, soc_reg_t *r_ctrl)
     92 {
     93     _soc_td2p_port_dyn_sched_t *pcb;
     94     int i, empty_at = -1, rv = SOC_E_NONE, pipe;
     95     soc_info_t *si;
     96 
     97     soc_reg_t dyn_change_a_x[] = {
     98                                        ES_PIPE0_LLS_SP_WERR_DYN_CHANGE_0Ar,
     99                                        ES_PIPE0_LLS_SP_WERR_DYN_CHANGE_1Ar,
    100                                        ES_PIPE0_LLS_SP_WERR_DYN_CHANGE_2Ar,
    101                                        ES_PIPE0_LLS_SP_WERR_DYN_CHANGE_3Ar
    102                                  };
    103     soc_reg_t dyn_change_b_x[] = {
    104                                        ES_PIPE0_LLS_SP_WERR_DYN_CHANGE_0Br,
    105                                        ES_PIPE0_LLS_SP_WERR_DYN_CHANGE_1Br,
    106                                        ES_PIPE0_LLS_SP_WERR_DYN_CHANGE_2Br,
    107                                        ES_PIPE0_LLS_SP_WERR_DYN_CHANGE_3Br
    108                                  };
    109     
    110     soc_reg_t dyn_change_ctrl_x[] = {
    111                                        ES_PIPE0_LLS_SP_WERR_DYN_CHANGE_0Cr,
    112                                        ES_PIPE0_LLS_SP_WERR_DYN_CHANGE_1Cr,
    113                                        ES_PIPE0_LLS_SP_WERR_DYN_CHANGE_2Cr,
    114                                        ES_PIPE0_LLS_SP_WERR_DYN_CHANGE_3Cr
    115                                     };
    116         
    117     soc_reg_t dyn_change_a_y[] = {
    118                                        ES_PIPE1_LLS_SP_WERR_DYN_CHANGE_0Ar,
    119                                        ES_PIPE1_LLS_SP_WERR_DYN_CHANGE_1Ar,
    120                                        ES_PIPE1_LLS_SP_WERR_DYN_CHANGE_2Ar,
    121                                        ES_PIPE1_LLS_SP_WERR_DYN_CHANGE_3Ar
    122                                  };
    123     soc_reg_t dyn_change_b_y[] = {
    124                                        ES_PIPE1_LLS_SP_WERR_DYN_CHANGE_0Br,
    125                                        ES_PIPE1_LLS_SP_WERR_DYN_CHANGE_1Br,
    126                                        ES_PIPE1_LLS_SP_WERR_DYN_CHANGE_2Br,
    127                                        ES_PIPE1_LLS_SP_WERR_DYN_CHANGE_3Br
    128                                  };
    129     
    130     soc_reg_t dyn_change_ctrl_y[] = {
    131                                        ES_PIPE1_LLS_SP_WERR_DYN_CHANGE_0Cr,
    132                                        ES_PIPE1_LLS_SP_WERR_DYN_CHANGE_1Cr,
    133                                        ES_PIPE1_LLS_SP_WERR_DYN_CHANGE_2Cr,
    134                                        ES_PIPE1_LLS_SP_WERR_DYN_CHANGE_3Cr
    135                                     };
    136 
    137     si = &SOC_INFO(unit); 
    138     pipe = (SOC_PBMP_MEMBER(si->xpipe_pbm, port)) ? 0 : 1;
    139 
    140     pcb = &_td2p_dyn_sched_unit_data[unit];
    141     
    142     sal_mutex_take(pcb->lock, sal_sem_FOREVER);
    143     for (i = 0; i < _SOC_TD2PLUS_DYN_REGISTER_SET; i++) {
    144         if (pcb->port[i] == -1) {
    145             empty_at = i;
    146             break;
    147         } else if (pcb->port[i] == port) {
    148             rv = SOC_E_BUSY;
    149             break;
    150         }
    151     }
    152 
    153     if (!rv && (empty_at >= 0)) {
    154         pcb->port[empty_at] = port;
    155     }
    156     
    157     sal_mutex_give(pcb->lock);
    158 
    159     if (rv) {
    160         return rv;
    161     }
    162 
    163     if (empty_at == -1) {
    164         return SOC_E_BUSY;
    165     }
    166     if (!pipe) {
    167         *r_a = dyn_change_a_x[empty_at];
    168         *r_b = dyn_change_b_x[empty_at];
    169         *r_ctrl = dyn_change_ctrl_x[empty_at];
    170     } else {
    171         *r_a = dyn_change_a_y[empty_at];
    172         *r_b = dyn_change_b_y[empty_at];
    173         *r_ctrl = dyn_change_ctrl_y[empty_at];
    174     }
    175     return SOC_E_NONE;
    176 }
    177 
    178 /*
    179  * Function:
    180  *     _soc_td2plus_free_dyn_set
    181  * Purpose:
    182  *     This function is called after the switchover is done 
    183  *     to update the structure _td2p_dyn_sched_unit_data by  
    184  *     removing the port from it. This makes the register
    185  *     used for the request available for the next request.
    186  * Parameters:
    187  *     unit       - (IN) unit number
    188  *     port       - (IN) local port number
    189  * Returns:
    190  *     SOC_E_XXX
    191  */
    192 STATIC int _soc_td2plus_free_dyn_set(int unit, int port)
    193 {
    194     _soc_td2p_port_dyn_sched_t *pcb;
    195     int i;
    196 
    197     pcb = &_td2p_dyn_sched_unit_data[unit];
    198 
    199     sal_mutex_take(pcb->lock, sal_sem_FOREVER);
    200     for (i = 0; i < _SOC_TD2PLUS_DYN_REGISTER_SET; i++) {
    201         if (pcb->port[i] == port) {
    202             pcb->port[i] = -1;
    203         }
    204     }
    205     sal_mutex_give(pcb->lock);
    206     
    207     return SOC_E_NONE;
    208 }
    209 
    210 STATIC int
    211 soc_td2_init_invalid_pointers(int unit)
    212 {
    213     uint32 mmu_bmp[4];
    214     int ii, port;
    215     int phy_port, mmu_port;
    216     soc_info_t *si;
    217 
    218     si = &SOC_INFO(unit);
    219 
    220     sal_memset(mmu_bmp, 0, sizeof(uint32)*4);
    221     
    222     _td2_invalid_ptr[unit][SOC_TD2_NODE_LVL_ROOT] = -1;
    223     _td2_invalid_ptr[unit][SOC_TD2_NODE_LVL_L1] = 
    224                         soc_mem_index_max(unit, ES_PIPE0_LLS_L0_PARENTm);
    225     _td2_invalid_ptr[unit][SOC_TD2_NODE_LVL_L2] = 
    226                         soc_mem_index_max(unit, ES_PIPE0_LLS_L1_PARENTm);
    227 
    228     PBMP_ALL_ITER(unit, port) {
    229         phy_port = si->port_l2p_mapping[port];
    230         mmu_port = si->port_p2m_mapping[phy_port];
    231         mmu_bmp[mmu_port/32] |= 1 << (mmu_port % 32);
    232     }
    233 
    234     /*PIPE0 & PIPE1 use the same base*/
    235     mmu_bmp[0] |= mmu_bmp[2];
    236     mmu_bmp[1] |= mmu_bmp[3];
    237     for (ii = 0; ii < (4 * 32); ii++) {
    238         if ((mmu_bmp[ii/32] & (1 << (ii % 32))) == 0) {
    239             _td2_invalid_ptr[unit][SOC_TD2_NODE_LVL_L0] = ii;
    240             break;
    241         }
    242     }
    243 
    244     if (!soc_feature(unit, soc_feature_lls_port_mema_config_match)) {
    245         /*Change invalid_ptr to 0 when it is over 52, avoid parity error*/
    246         if (_td2_invalid_ptr[unit][SOC_TD2_NODE_LVL_L0] >
    247                 SOC_TD2_NUM_MMU_PORTS_PER_PIPE - 1) {
    248             _td2_invalid_ptr[unit][SOC_TD2_NODE_LVL_L0] = 0;
    249         }
    250     }
    251     return SOC_E_NONE;
    252 }
    253 
    254 int _soc_td2_invalid_parent_index(int unit, int level)
    255 {
    256     return _td2_invalid_ptr[unit][level];
    257 }
    258 
    259 #define INVALID_PARENT(unit, level)   _soc_td2_invalid_parent_index((unit),(level))
    260 
    261 #define _SOC_TD2_DEF_SCHED_NODE_BASE(u,p,cfg,t)   \
    262             (cfg)[(t)].base_factor * (p)
    263 
    264 /*
    265  * Function:
    266  *      _soc_trident2_port_sched_type_get
    267  * Purpose:
    268  *      Gets the scheduling type of a port.
    269  * Parameters:
    270  *      unit           - (IN) Device Number
    271  *      port           - (IN) logical port
    272  * Returns:
    273  *      SOC_TD2_SCHED_HSP if HSP, SOC_TD2_SCHED_LLS if LLS,
    274  *      SOC_TD2_SCHED_UNKNOWN else. 
    275  */
    276 soc_trident2_sched_type_t
    277 _soc_trident2_port_sched_type_get(int unit, soc_port_t port)
    278 {
    279     int  smode, speed;
    280     soc_info_t *si;
    281 
    282     si = &SOC_INFO(unit);
    283 
    284     speed = si->port_speed_max[port];
    285 #ifdef BCM_TRIDENT2PLUS_SUPPORT
    286     if (SOC_IS_TRIDENT2PLUS(unit) || SOC_IS_TITAN2PLUS(unit)) {
    287         SOC_IF_ERROR_RETURN(soc_td2p_port_speed_get(unit, port, &speed));
    288     }
    289 #endif
    290 
    291     if (speed >= 100000 ||
    292         (speed >= 40000 && si->frequency < 760) ||
    293         SOC_PBMP_MEMBER(si->eq_pbm, port)) {
    294         return SOC_TD2_SCHED_HSP;
    295     } else if (speed < 40000) {
    296         return SOC_TD2_SCHED_LLS;
    297     } else {
    298 #ifdef BCM_TRIDENT2PLUS_SUPPORT
    299         /* Get the current state of port_sched_hsp. Flexport overrides this
    300            since the config parameter is based on logical port so when
    301            we flex, the config parameter is no longer valid. */
    302         if (SOC_IS_TRIDENT2PLUS(unit)) {
    303             SOC_IF_ERROR_RETURN(soc_td2p_port_sched_hsp_get(unit, port, &smode));
    304         } else 
    305 #endif
    306         {
    307             smode = soc_property_port_get(unit, port, spn_PORT_SCHED_HSP, 0);
    308         }
    309         return (smode == 0) ? SOC_TD2_SCHED_LLS : SOC_TD2_SCHED_HSP;
    310     }
    311     return SOC_TD2_SCHED_UNKNOWN;
    312 }
    313 
    314 int soc_td2_port_common_attributes_get(int unit, int port, int *pipe,
    315                                        int *mmu_port, int *phy_port)
    316 {
    317     int lphy_port, lmmu_port;
    318     soc_info_t *si;
    319 
    320     si = &SOC_INFO(unit);
    321 
    322     if (pipe) {
    323         *pipe = (SOC_PBMP_MEMBER(si->xpipe_pbm, port)) ? 0 : 1;
    324     }
    325 
    326     lphy_port = si->port_l2p_mapping[port];
    327     /* lmmu_port = si->max_port_p2m_mapping[lphy_port]; */
    328     lmmu_port = si->port_p2m_mapping[lphy_port];
    329 
    330     if (phy_port) {
    331         *phy_port = lphy_port;
    332     }
    333 
    334     if (mmu_port) {
    335         *mmu_port = lmmu_port;
    336     }
    337     return 0;
    338 }
    339 
    340 int _soc_trident2_root_scheduler_index(int unit, int port)
    341 {
    342     int mmu_port, in_pipe;
    343 
    344     SOC_IF_ERROR_RETURN(
    345         soc_td2_port_common_attributes_get(unit, port, &in_pipe, &mmu_port, NULL));
    346     return (in_pipe == 0) ? mmu_port : mmu_port - 64;
    347 }
    348 STATIC int
    349 _soc_td2_flush_queue(int unit, int port, int queue_hw_index)
    350 {
    351     
    352     return 0;
    353 }
    354 
    355 int
    356 soc_td2_cosq_set_sched_parent(int unit, soc_port_t port,
    357                               int level, int hw_index,
    358                               int parent_hw_idx)
    359 {
    360     soc_trident2_sched_type_t sched_type;
    361     uint32 entry[SOC_MAX_MEM_WORDS], fval, fval1, rval;
    362     soc_mem_t mem;
    363     int l0off, l1off, idx;
    364     uint32 *bmap = NULL;
    365     int parent_index = 0;
    366 
    367     LOG_INFO(BSL_LS_SOC_COSQ,
    368              (BSL_META_U(unit,
    369                          "Port:%d L%d : %d parent:%d\n"),
    370                port, level - 1, hw_index, parent_hw_idx));
    371 
    372     sched_type = _soc_trident2_port_sched_type_get(unit, port);
    373 
    374     if (sched_type == SOC_TD2_SCHED_LLS) {
    375         mem = _SOC_TD2_NODE_PARENT_MEM(unit, port, level);
    376         if (mem == INVALIDm) {
    377             return SOC_E_INTERNAL;
    378         }
    379 
    380         SOC_IF_ERROR_RETURN
    381             (soc_mem_read(unit, mem, MEM_BLOCK_ALL, hw_index, &entry));
    382         if (soc_mem_field32_get(unit, mem, entry, C_PARENTf) == parent_hw_idx) {
    383             return SOC_E_NONE;
    384         }
    385 
    386         /* disconnecting the queue , flush it */
    387         if ((parent_hw_idx == INVALID_PARENT(unit, level)) && 
    388                                             (level == SOC_TD2_NODE_LVL_L2)) {
    389             SOC_IF_ERROR_RETURN(_soc_td2_flush_queue(unit, port, hw_index));
    390         }
    391         
    392         soc_mem_field32_set(unit, mem, entry, C_PARENTf, parent_hw_idx);
    393         SOC_IF_ERROR_RETURN
    394             (soc_mem_write(unit, mem, MEM_BLOCK_ALL, hw_index, &entry));
    395         if (level == SOC_TD2_NODE_LVL_L0) {
    396             bmap = SOC_CONTROL(unit)->port_lls_l0_bmap[port];
    397         } else if (level == SOC_TD2_NODE_LVL_L1) {
    398             bmap = SOC_CONTROL(unit)->port_lls_l1_bmap[port];
    399         } else if (level == SOC_TD2_NODE_LVL_L2) {
    400             bmap = SOC_CONTROL(unit)->port_lls_l2_bmap[port];
    401         }
    402         parent_index = _soc_td2_invalid_parent_index(unit, level);
    403         /* SDK has allocated memory space according to value of "bmap"
    404         * during process of "_soc_egress_metering_freeze".
    405         * If we set a new number during process of "_soc_egress_metering_freeze", the buffer
    406         * may overflow. So we add a lock at this.  We should add other actions
    407         *  between lock and unklock.
    408         */
    409         SOC_LLS_SCHEDULER_LOCK(unit);
    410         if (parent_hw_idx == parent_index) {
    411             SHR_BITCLR(bmap, hw_index);
    412         } else {
    413             SHR_BITSET(bmap, hw_index);
    414         }
    415         SOC_LLS_SCHEDULER_UNLOCK(unit);
    416     } else if (sched_type == SOC_TD2_SCHED_HSP) {
    417         if (level == SOC_TD2_NODE_LVL_L1) {
    418             l0off = parent_hw_idx % 5;
    419             l1off = hw_index % 10;
    420 
    421             /* disconnect from any existing node */
    422             for (idx = 0; idx < 5; idx++) {
    423                 if ((l0off == idx) &&
    424                     (parent_hw_idx != INVALID_PARENT(unit, level))) {
    425                     continue;
    426                 }
    427 
    428                 /*
    429                  * For L0.1, L0.2, and L0.3 nodes: 
    430                  *     The bitmap is organized as {L1.7, L1.6, ..., L1.0}, 
    431                  * For L0.4 node: 
    432                  *     The bit 7 selects L1.9 and bit6 selects L1.8. 
    433                  *     The rest bits are not used and should be set to 0.
    434                  */
    435                 if ((l1off >= 8) && (idx != 4)) {
    436                     continue;
    437                 } else if ((l1off < 8) && (idx == 4)) {
    438                     continue;
    439                 }
    440 
    441                 SOC_IF_ERROR_RETURN(READ_HSP_SCHED_L0_NODE_CONNECTION_CONFIGr(
    442                                                         unit, port, idx, &rval));
    443                 fval1 = fval = soc_reg_field_get(unit, 
    444                                       HSP_SCHED_L0_NODE_CONNECTION_CONFIGr, 
    445                                       rval, CHILDREN_CONNECTION_MAPf);
    446                 /* L1.8 & L1.9 need to adjust hw offset */
    447                 if (l1off >= 8) {
    448                     l1off -= 2;
    449                 }
    450                 fval &= ~(1 << l1off);
    451                 if (fval1 == fval) {
    452                     continue;
    453                 }
    454                 soc_reg_field_set(unit, 
    455                                   HSP_SCHED_L0_NODE_CONNECTION_CONFIGr, 
    456                                   &rval, CHILDREN_CONNECTION_MAPf, fval);
    457                 SOC_IF_ERROR_RETURN(
    458                     WRITE_HSP_SCHED_L0_NODE_CONNECTION_CONFIGr(unit, port,
    459                                                                 idx, rval));
    460                 break;
    461             }
    462 
    463             if (parent_hw_idx == INVALID_PARENT(unit, level)) {
    464                 SOC_IF_ERROR_RETURN(_soc_td2_flush_queue(unit, port, hw_index));
    465             } else {
    466                 SOC_IF_ERROR_RETURN(READ_HSP_SCHED_L0_NODE_CONNECTION_CONFIGr(
    467                                                 unit, port, l0off, &rval));
    468 
    469                 fval = soc_reg_field_get(unit, HSP_SCHED_L0_NODE_CONNECTION_CONFIGr, 
    470                                          rval, CHILDREN_CONNECTION_MAPf);
    471 
    472                 /* L1.8 & L1.9 need to adjust hw offset */
    473                 if (l1off >= 8) {
    474                     l1off -= 2;
    475                 }
    476                 fval |= 1 << l1off;
    477                 soc_reg_field_set(unit, HSP_SCHED_L0_NODE_CONNECTION_CONFIGr, 
    478                                   &rval, CHILDREN_CONNECTION_MAPf, fval);
    479 
    480                 SOC_IF_ERROR_RETURN(WRITE_HSP_SCHED_L0_NODE_CONNECTION_CONFIGr(
    481                                                         unit, port, l0off, rval));
    482             }
    483         }
    484     }
    485 
    486     return SOC_E_NONE;
    487 }
    488 
    489 int 
    490 soc_td2_sched_weight_set(int unit, int port, int level,
    491                          int hw_index, int weight)
    492 {
    493     soc_trident2_sched_type_t sched_type;
    494     uint32 entry[SOC_MAX_MEM_WORDS], rval;
    495     soc_mem_t mem = INVALIDm;
    496     soc_reg_t reg = INVALIDr;
    497 
    498     LOG_INFO(BSL_LS_SOC_COSQ,
    499              (BSL_META_U(unit,
    500                          "sched_weight_set L%d csch_index=%d wt=%d\n"),
    501               level, hw_index, weight));
    502 
    503     sched_type = _soc_trident2_port_sched_type_get(unit, port);
    504 
    505     if (weight > 0x7f) {
    506         return SOC_E_PARAM;
    507     }
    508     if (sched_type == SOC_TD2_SCHED_LLS) {
    509         mem = _SOC_TD2_NODE_WIEGHT_MEM(unit, port, level);
    510         if (mem == INVALIDm) {
    511             return SOC_E_INTERNAL;
    512         }
    513         SOC_IF_ERROR_RETURN
    514             (soc_mem_read(unit, mem, MEM_BLOCK_ALL, hw_index, &entry));
    515         soc_mem_field32_set(unit, mem, &entry, C_WEIGHTf, weight);
    516         SOC_IF_ERROR_RETURN
    517             (soc_mem_write(unit, mem, MEM_BLOCK_ALL, hw_index, &entry));
    518     } else if (sched_type == SOC_TD2_SCHED_HSP) {
    519         if ((level == SOC_TD2_NODE_LVL_L0) || (level == SOC_TD2_NODE_LVL_L1)) {
    520             if (level == SOC_TD2_NODE_LVL_L0) {
    521                 hw_index = hw_index % 5;
    522                 reg = HSP_SCHED_L0_NODE_WEIGHTr;
    523             } else if (level == SOC_TD2_NODE_LVL_L1) {
    524                 hw_index = hw_index % 10;
    525                 reg = HSP_SCHED_L1_NODE_WEIGHTr;
    526             }
    527 
    528             rval = 0;
    529             soc_reg_field_set(unit, reg, &rval, WEIGHTf, weight);
    530             SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, port, hw_index, rval));
    531         } else if (level == SOC_TD2_NODE_LVL_L2) {
    532             if (hw_index < 1480)
    533             {
    534                 reg = HSP_SCHED_L2_UC_QUEUE_WEIGHTr;
    535             } else {
    536                 reg = HSP_SCHED_L2_MC_QUEUE_WEIGHTr;
    537             }
    538 
    539             rval = 0;
    540             hw_index = hw_index % 10;
    541             soc_reg_field_set(unit, reg, &rval, WEIGHTf, weight);
    542             SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, port, hw_index, rval));
    543         }
    544     }
    545     return SOC_E_NONE;
    546 }
    547 
    548 int 
    549 soc_td2_sched_weight_get(int unit, int port, int level,
    550                          int hw_index, int *weight)
    551 {
    552     soc_trident2_sched_type_t sched_type;
    553     uint32 entry[SOC_MAX_MEM_WORDS], rval;
    554     soc_mem_t mem = INVALIDm;
    555     soc_reg_t reg = INVALIDr;
    556 
    557     sched_type = _soc_trident2_port_sched_type_get(unit, port);
    558 
    559     if (sched_type == SOC_TD2_SCHED_LLS) {
    560         mem = _SOC_TD2_NODE_WIEGHT_MEM(unit, port, level);
    561         if (mem == INVALIDm) {
    562             return SOC_E_INTERNAL;
    563         }
    564         SOC_IF_ERROR_RETURN
    565             (soc_mem_read(unit, mem, MEM_BLOCK_ALL, hw_index, &entry));
    566         *weight = soc_mem_field32_get(unit, mem, &entry, C_WEIGHTf);
    567     } else if (sched_type == SOC_TD2_SCHED_HSP) {
    568         if ((level == SOC_TD2_NODE_LVL_L0) || (level == SOC_TD2_NODE_LVL_L1)) {
    569             if (level == SOC_TD2_NODE_LVL_L0) {
    570                 hw_index = hw_index % 5;
    571                 reg = HSP_SCHED_L0_NODE_WEIGHTr;
    572             } else if (level == SOC_TD2_NODE_LVL_L1) {
    573                 hw_index = hw_index % 10;
    574                 reg = HSP_SCHED_L1_NODE_WEIGHTr;
    575             }
    576 
    577             SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, port, hw_index, &rval));
    578             *weight = soc_reg_field_get(unit, reg, rval, WEIGHTf);
    579         } else if (level == SOC_TD2_NODE_LVL_L2) {
    580             if (hw_index < 1480)
    581             {
    582                 reg = HSP_SCHED_L2_UC_QUEUE_WEIGHTr;
    583             } else {
    584                 reg = HSP_SCHED_L2_MC_QUEUE_WEIGHTr;
    585             }
    586 
    587             hw_index = hw_index % 10;
    588             SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, port, hw_index, &rval));
    589             *weight = soc_reg_field_get(unit, reg, rval, WEIGHTf);
    590         }
    591     }
    592 
    593     LOG_INFO(BSL_LS_SOC_COSQ,
    594              (BSL_META_U(unit,
    595                          "sched_weight_get L%d csch_index=%d wt=%d\n"),
    596               level, hw_index, *weight));
    597 
    598     return SOC_E_NONE;
    599 }
    600 
    601 /*
    602  * Function:
    603  *     soc_td2_cosq_set_sched_child_config_dynamic
    604  * Purpose:
    605  *     This function enables the spri_vect_mode by setting the 
    606  *     spri_vect_mode_enable field to 1 in the LLS_CONFIG0 reg, which changes 
    607  *     p_num_spri[3:0] to p_vect_spri[7:0]. It allocates the register from set
    608  *     of SP_WERR_DYN_CHNG_nA/nB/nC registers to the port. It then sets the 
    609  *     SP_WERR_DYN_CHNG_nB/nC reg with the new value for the node id's parent.
    610  *     It sets the fields in SP_WERR_DYN_CHNG_nA with the info about the node
    611  *     to be switched like node_id, node_level and parent_id along with in_use
    612  *     field to 1, which triggers the request in H/W. The H/W clears in_use
    613  *     field to 0 once the switchover is complete, so we keep polling its
    614  *     to know about the completion of the request. 
    615  * Parameters:
    616  *     unit       - (IN) unit number
    617  *     port       - (IN) local port number
    618  *     level      - (IN) level of the node
    619  *     index      - (IN) index of the node
    620  *     num_spri   - (IN) number of SPRI child nodes
    621  *     first_child - (IN) first child node
    622  *     first_mc_child - (IN) first multicast child node
    623  *     ucmap        - (IN) unicast map
    624  *     spmap        - (IN) spri map
    625  *     child_index     - (IN) index number of the child
    626  * Returns:
    627  *     SOC_E_XXX
    628  */
    629 int
    630 soc_td2_cosq_set_sched_child_config_dynamic(int unit, soc_port_t port,
    631                                             int level, int index, 
    632                                             int num_spri, int first_child,
    633                                             int first_mc_child, uint32 ucmap,
    634                                             uint32 spmap, int child_index)
    635 {
    636     uint32 entry[SOC_MAX_MEM_WORDS], rval, d32, timeout_val, old_spmap, f1, f2;
    637     soc_mem_t mem, mem2;
    638     int rv = SOC_E_NONE;
    639     soc_reg_t r_a = INVALIDr, r_b = INVALIDr, r_ctrl = INVALIDr;
    640     soc_timeout_t timeout;
    641     SOC_IF_ERROR_RETURN(READ_ES_PIPE0_LLS_CONFIG0r(unit, &rval));
    642      
    643     soc_reg_field_get(unit, ES_PIPE0_LLS_CONFIG0r, rval, SPRI_VECT_MODE_ENABLEf);
    644     if (!soc_reg_field_get(unit, ES_PIPE0_LLS_CONFIG0r, rval, SPRI_VECT_MODE_ENABLEf)) {
    645         soc_reg_field_set(unit, ES_PIPE0_LLS_CONFIG0r, &rval, SPRI_VECT_MODE_ENABLEf, 1);
    646         SOC_IF_ERROR_RETURN(WRITE_ES_PIPE0_LLS_CONFIG0r(unit, rval));
    647         SOC_IF_ERROR_RETURN(WRITE_ES_PIPE1_LLS_CONFIG0r(unit, rval)); 
    648     }
    649 
    650     SOC_IF_ERROR_RETURN(_soc_td2plus_alloc_dyn_set(unit, port, 
    651                                                &r_a, &r_b, &r_ctrl));
    652 
    653     mem = _SOC_TD2_NODE_CONFIG_MEM(unit, port, level);
    654     mem2 = _SOC_TD2_NODE_CONFIG_MEM2(unit, port, level);
    655     if (mem == INVALIDm || mem2 == INVALIDm) {
    656         return SOC_E_INTERNAL;
    657     }
    658 
    659     /* Getting the old spmap */    
    660     SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, index, &entry));
    661     f1 = soc_mem_field32_get(unit, mem, &entry, P_NUM_SPRIf);
    662     f2 = soc_mem_field32_get(unit, mem, &entry, P_VECT_SPRI_7_4f);
    663     old_spmap = f1 | (f2 << 4);
    664 
    665     LOG_INFO(BSL_LS_SOC_COSQ,
    666             (BSL_META_U(unit,
    667             "Port:%d L%s%d config : index=%d FC=%d FMC=%d UMAP=0x%x NUMSP=%d\n"), 
    668              port, (level==0) ? "r" : "", level - 1, 
    669              index, first_child, first_mc_child, ucmap, num_spri));
    670 
    671     /* Setting the memory fields based on the new spmap */
    672     soc_mem_field32_set(unit, mem, &entry, P_NUM_SPRIf, spmap & 0xf);
    673     soc_mem_field32_set(unit, mem, &entry, P_VECT_SPRI_7_4f, (spmap >> 4) & 0xf);
    674 
    675     if ((mem == ES_PIPE0_LLS_L1_MEMA_CONFIGm) ||
    676         (mem == ES_PIPE1_LLS_L1_MEMA_CONFIGm)) {
    677         soc_mem_field32_set(unit, mem, &entry, P_START_UC_SPRIf, first_child);
    678         soc_mem_field32_set(unit, mem, &entry, P_START_MC_SPRIf, first_mc_child);
    679         soc_mem_field32_set(unit, mem, &entry, P_SPRI_SELECTf, 
    680                             (num_spri > 0) ? ucmap : 0);
    681     } else {
    682         soc_mem_field32_set(unit, mem, &entry, P_START_SPRIf, first_child);
    683     }
    684 
    685     SOC_IF_ERROR_RETURN(
    686         soc_mem_write(unit, mem, MEM_BLOCK_ANY, index, &entry));
    687     SOC_IF_ERROR_RETURN(
    688         soc_mem_write(unit, mem2, MEM_BLOCK_ANY, index, &entry));
    689         
    690 
    691     rval = 0;
    692     soc_bits_get(entry, 0, 31, &d32);
    693     soc_reg_field_set(unit, r_ctrl, &rval, LLS_PARENT_CONFIGf, d32);
    694     SOC_IF_ERROR_RETURN(soc_reg32_set(unit, r_ctrl, REG_PORT_ANY, 0, rval));
    695 
    696     rval = 0;
    697     soc_bits_get(entry, 32, 40, &d32);
    698     soc_reg_field_set(unit, r_b, &rval, LLS_PARENT_CONFIGf, d32);
    699     soc_reg_field_set(unit, r_b, &rval, LLS_PARENT_CONFIG_ORIGINAL_SP_VECTORf,
    700                                             old_spmap);
    701     SOC_IF_ERROR_RETURN(soc_reg32_set(unit, r_b, REG_PORT_ANY, 0, rval));
    702 
    703     rval = 0;
    704     soc_reg_field_set(unit, r_a, &rval, NODE_LEVELf, level + 1);
    705     soc_reg_field_set(unit, r_a, &rval, NODE_IDf, child_index);
    706     soc_reg_field_set(unit, r_a, &rval, PARENT_IDf, index);
    707     soc_reg_field_set(unit, r_a, &rval, IN_USEf, 1);
    708     SOC_IF_ERROR_RETURN(soc_reg32_set(unit, r_a, REG_PORT_ANY, 0, rval));
    709 
    710     if (!SAL_BOOT_SIMULATION) {
    711         timeout_val = soc_property_get(unit, spn_MMU_QUEUE_FLUSH_TIMEOUT, 20000);
    712         soc_timeout_init(&timeout, timeout_val, 0);
    713 
    714         do {
    715             SOC_IF_ERROR_RETURN(
    716                 soc_reg32_get(unit, r_a, REG_PORT_ANY, 0, &rval));
    717                 
    718             if (soc_timeout_check(&timeout)) {
    719                 rv = SOC_E_TIMEOUT;
    720                 break;
    721             }
    722         } while (soc_reg_field_get(unit, r_a, rval, IN_USEf));
    723     }
    724 
    725     SOC_IF_ERROR_RETURN(_soc_td2plus_free_dyn_set(unit, port));
    726 
    727     return rv;
    728 }
    729 
    730 int
    731 soc_td2_cosq_set_sched_child_config(int unit, soc_port_t port,
    732                               int level, int index,
    733                               int num_spri, int first_sp_child, 
    734                               int first_sp_mc_child, uint32 ucmap, uint32 spmap)
    735 {
    736     soc_trident2_sched_type_t sched_type;
    737     uint32 entry[SOC_MAX_MEM_WORDS], rval;
    738     soc_mem_t mem, mem2;
    739 
    740     LOG_INFO(BSL_LS_SOC_COSQ,
    741              (BSL_META_U(unit,
    742                          "Port:%d L%s%d config : index=%d FC=%d FMC=%d UMAP=0x%x\n"),
    743               port, (level == 0) ? "r" : "", level - 1, 
    744               index, first_sp_child, first_sp_mc_child, ucmap));
    745 
    746     mem = INVALIDm;
    747 
    748     sched_type = _soc_trident2_port_sched_type_get(unit, port);
    749     if (sched_type == SOC_TD2_SCHED_HSP) {
    750         return SOC_E_PARAM;
    751     }
    752 
    753     if (soc_feature(unit, soc_feature_vector_based_spri)) {
    754         SOC_IF_ERROR_RETURN(READ_ES_PIPE0_LLS_CONFIG0r(unit, &rval));
    755         if (!soc_reg_field_get(unit, ES_PIPE0_LLS_CONFIG0r, rval, SPRI_VECT_MODE_ENABLEf)) {
    756             soc_reg_field_set(unit, ES_PIPE0_LLS_CONFIG0r, &rval,
    757                               SPRI_VECT_MODE_ENABLEf, 1);
    758             SOC_IF_ERROR_RETURN(WRITE_ES_PIPE0_LLS_CONFIG0r(unit, rval));
    759             SOC_IF_ERROR_RETURN(WRITE_ES_PIPE1_LLS_CONFIG0r(unit, rval));
    760         }
    761     }
    762 
    763     mem = _SOC_TD2_NODE_CONFIG_MEM(unit, port, level);
    764     mem2 = _SOC_TD2_NODE_CONFIG_MEM2(unit, port, level);
    765     /* coverity[negative_returns : FALSE] */
    766     SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, index, &entry));
    767     if (soc_feature(unit, soc_feature_vector_based_spri)) {
    768         /* Setting the memory fields based on the new spmap */
    769         soc_mem_field32_set(unit, mem, &entry, P_NUM_SPRIf, spmap & 0xf);
    770         soc_mem_field32_set(unit, mem, &entry, P_VECT_SPRI_7_4f,
    771                             (spmap >> 4) & 0xf);
    772     } else {
    773         soc_mem_field32_set(unit, mem, &entry, P_NUM_SPRIf, num_spri);
    774     }
    775 
    776     if ((mem == ES_PIPE0_LLS_L1_MEMA_CONFIGm) || 
    777         (mem == ES_PIPE1_LLS_L1_MEMA_CONFIGm)) {
    778         soc_mem_field32_set(unit, mem, &entry, P_START_UC_SPRIf, first_sp_child);
    779         soc_mem_field32_set(unit, mem, &entry, P_START_MC_SPRIf, 
    780                                                        first_sp_mc_child);
    781         soc_mem_field32_set(unit, mem, &entry, P_SPRI_SELECTf, 
    782                             (num_spri > 0) ? ucmap : 0);
    783     } else {
    784         soc_mem_field32_set(unit, mem, &entry, P_START_SPRIf, first_sp_child);
    785     }
    786 
    787     SOC_IF_ERROR_RETURN(soc_mem_write
    788                         (unit, mem, MEM_BLOCK_ANY, index, &entry));
    789     SOC_IF_ERROR_RETURN
    790         (soc_mem_write(unit, mem2, MEM_BLOCK_ANY, index, &entry));
    791 
    792     return SOC_E_NONE;
    793 }
    794 
    795 int
    796 soc_td2_cosq_set_sched_mode(int unit, soc_port_t port, int level, int index,
    797                             const soc_td2_sched_mode_e mode, int weight)
    798 {
    799     soc_trident2_sched_type_t sched_type;
    800     uint32 entry[SOC_MAX_MEM_WORDS], mfval = 0, rval, wrr_mask, sp_mask;
    801     soc_mem_t mem, mem2;
    802     soc_reg_t reg, reg2;
    803     int fval, idx, parent_idx = -1;
    804 
    805     LOG_INFO(BSL_LS_SOC_COSQ,
    806              (BSL_META_U(unit,
    807                          "Port:%d L%s%d config : index=%d MODE=%d WT=%d\n"),
    808               port, (level == 0) ? "r" : "", level - 1, 
    809               index, mode, weight));
    810 
    811     reg = INVALIDr;
    812     reg2 = INVALIDr;
    813     mem = INVALIDm;
    814     sched_type = _soc_trident2_port_sched_type_get(unit, port);
    815     if (sched_type == SOC_TD2_SCHED_HSP) {
    816         /* get the port relative index / offset */
    817         if (level == SOC_TD2_NODE_LVL_L0) {
    818             index = index % 5;
    819             reg = HSP_SCHED_PORT_CONFIGr;
    820             reg2 = HSP_SCHED_L0_NODE_CONFIGr;
    821             parent_idx = 0;
    822         } else if (level == SOC_TD2_NODE_LVL_L1) {
    823             index = index % 10;
    824             reg = HSP_SCHED_L0_NODE_CONFIGr;
    825             reg2 = HSP_SCHED_L1_NODE_CONFIGr;
    826             /* Find the Parent index for the current child */
    827             for (idx = 1; idx < 5; idx++) {
    828                 SOC_IF_ERROR_RETURN(READ_HSP_SCHED_L0_NODE_CONNECTION_CONFIGr(
    829                                                     unit, port, idx, &rval));
    830                 fval = soc_reg_field_get(unit,
    831                             HSP_SCHED_L0_NODE_CONNECTION_CONFIGr,
    832                             rval, CHILDREN_CONNECTION_MAPf);
    833                 if (idx == 4) {
    834                     if ((index >= 8) && (fval & (1 << (index - 2)))) {
    835                         parent_idx = idx;
    836                         break;
    837                     }
    838                 } else {
    839                     if (fval & (1 << index)) {
    840                         parent_idx = idx;
    841                         break;
    842                     }
    843                 }
    844             }
    845         } else if (level == SOC_TD2_NODE_LVL_L2) {
    846             uint32 rval = 0;
    847             uint32 mc_group_mode = 0;
    848             SOC_IF_ERROR_RETURN(
    849                 READ_HSP_SCHED_PORT_CONFIGr(unit, port, &rval));
    850             mc_group_mode  = soc_reg_field_get(unit, 
    851                                                HSP_SCHED_PORT_CONFIGr,
    852                                                rval, MC_GROUP_MODEf);
    853             reg = HSP_SCHED_L1_NODE_CONFIGr;
    854             if (index >= 1480) {
    855                 reg2 = HSP_SCHED_L2_MC_QUEUE_CONFIGr;
    856             } else {
    857                 reg2 = HSP_SCHED_L2_UC_QUEUE_CONFIGr;
    858             }
    859             parent_idx = index % 10;
    860             
    861             if (mc_group_mode && (index >= 1480)) {
    862                 if ((index % 10) < _TD2_HSP_PORT_MAX_COS) {
    863                     reg= HSP_SCHED_L0_NODE_CONFIGr;
    864                     parent_idx = 0;
    865                 }
    866             }
    867         } else {
    868             return SOC_E_PARAM;
    869         }
    870 
    871         if (parent_idx == -1) {
    872             return SOC_E_INTERNAL;
    873         }
    874 
    875         if (mode == SOC_TD2_SCHED_MODE_STRICT) {
    876             weight = 0;
    877         } else if (mode == SOC_TD2_SCHED_MODE_WRR) {
    878             mfval = 1;
    879         } else if (mode == SOC_TD2_SCHED_MODE_WDRR) {
    880             mfval = 0;
    881         } else {
    882             return SOC_E_PARAM;
    883         }
    884 
    885         /* selection between SP and WxRR is based on weight property. */
    886         SOC_IF_ERROR_RETURN(soc_td2_sched_weight_set(unit, port, 
    887                                                 level, index, weight));
    888 
    889         SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, port, 0, &rval));
    890         wrr_mask = soc_reg_field_get(unit, reg, rval, ENABLE_WRRf);
    891         wrr_mask &= ~(1 << parent_idx);
    892         wrr_mask |= (mfval << parent_idx);
    893         soc_reg_field_set(unit, reg, &rval, ENABLE_WRRf, wrr_mask);
    894         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, port, 0, rval));
    895 
    896         SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg2, port, 0, &rval));
    897         sp_mask = soc_reg_field_get(unit, reg2, rval, ENABLE_SP_IN_MINf);
    898         if (mode == SOC_TD2_SCHED_MODE_STRICT) {
    899             sp_mask |= (1 << (index % 10));
    900         } else {
    901             sp_mask &= ~(1 << (index % 10));
    902         }
    903         soc_reg_field_set(unit, reg2, &rval, ENABLE_SP_IN_MINf, sp_mask);
    904         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg2, port, 0, rval));
    905     } else {
    906         if (mode == SOC_TD2_SCHED_MODE_STRICT) {
    907             weight = 0;
    908         }
    909         
    910         SOC_IF_ERROR_RETURN(soc_td2_sched_weight_set(unit, port, 
    911                                                 level, index, weight));
    912 
    913         if (mode != SOC_TD2_SCHED_MODE_STRICT) {
    914             mem = _SOC_TD2_NODE_CONFIG_MEM(unit, port, SOC_TD2_NODE_LVL_ROOT);
    915             mem2 = _SOC_TD2_NODE_CONFIG_MEM2(unit, port, SOC_TD2_NODE_LVL_ROOT); 
    916             index = _soc_trident2_root_scheduler_index(unit, port);
    917             SOC_IF_ERROR_RETURN(
    918                     soc_mem_read(unit, mem, MEM_BLOCK_ALL, index, &entry));
    919             soc_mem_field32_set(unit, mem, entry, 
    920                     PACKET_MODE_WRR_ACCOUNTING_ENABLEf, 
    921                     (mode == SOC_TD2_SCHED_MODE_WRR) ? 1 : 0);
    922             SOC_IF_ERROR_RETURN(
    923                     soc_mem_write(unit, mem, MEM_BLOCK_ANY, index, &entry));
    924             SOC_IF_ERROR_RETURN
    925                 (soc_mem_write(unit, mem2, MEM_BLOCK_ANY, index, &entry));
    926         }
    927     }
    928     return SOC_E_NONE;
    929 }
    930 
    931 int
    932 soc_td2_cosq_set_sched_config(int unit, soc_port_t port,
    933                               int level, int index, int child_index,
    934                               int num_spri, int first_child, 
    935                               int first_mc_child, uint32 ucmap, uint32 spmap,
    936                               const soc_td2_sched_mode_e mode, int weight)
    937 {
    938     int child_level = -1, wt = 0;
    939     soc_td2_sched_mode_e cur_sched_mode = SOC_TD2_SCHED_MODE_UNKNOWN;
    940     int sp_vec = soc_feature(unit, soc_feature_vector_based_spri);
    941 
    942     if (level >= SOC_TD2_NODE_LVL_L2) {
    943         return SOC_E_PARAM;
    944     }
    945 
    946     if (child_index >= 0) {
    947         soc_td2_get_child_type(unit, port, level, &child_level);
    948         SOC_IF_ERROR_RETURN(soc_td2_cosq_get_sched_mode(unit, port, child_level,
    949                                 child_index, &cur_sched_mode, &wt));
    950     }
    951 
    952     /* If dynamice switchover feature is enabled, we configure the child
    953        based on the switchover request and trigger the switchover in  H/W */ 
    954     if (sp_vec && (cur_sched_mode != mode)) {
    955         SOC_IF_ERROR_RETURN(
    956             soc_td2_cosq_set_sched_child_config_dynamic(unit, port,
    957                                    level, index, num_spri, first_child, 
    958                                    first_mc_child, ucmap, spmap, child_index));
    959     } else {
    960         SOC_IF_ERROR_RETURN(soc_td2_cosq_set_sched_child_config(unit, port,
    961             level, index, num_spri, first_child, first_mc_child, ucmap, spmap));
    962 
    963     }
    964    
    965     if (child_index >= 0) {
    966         SOC_IF_ERROR_RETURN(soc_td2_cosq_set_sched_mode(unit, port, child_level, 
    967                                 child_index, mode, weight));
    968     }
    969 
    970     return SOC_E_NONE;
    971 }
    972 
    973 int
    974 soc_td2_cosq_get_sched_child_config(int unit, soc_port_t port,
    975                               int level, int index,
    976                               int *pnum_spri, int *pfirst_sp_child, 
    977                               int *pfirst_sp_mc_child, uint32 *pucmap,
    978                               uint32 *pspmap)
    979 {
    980     soc_trident2_sched_type_t sched_type;
    981     uint32 entry[SOC_MAX_MEM_WORDS];
    982    
    983     soc_mem_t mem;
    984     uint32 num_spri = 0, ucmap = 0, f1, f2;
    985     int first_sp_child = -1, first_sp_mc_child = -1, ii;
    986     int sp_vec = soc_feature(unit, soc_feature_vector_based_spri);
    987 
    988     *pspmap = 0;
    989 
    990     sched_type = _soc_trident2_port_sched_type_get(unit, port);
    991 
    992     mem = INVALIDm;
    993 
    994     if (sched_type == SOC_TD2_SCHED_HSP) {
    995         return SOC_E_PARAM;
    996     }
    997 
    998     mem = _SOC_TD2_NODE_CONFIG_MEM(unit, port, level);
    999     SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, index, &entry));
   1000     
   1001     /* If dynamic switchover feature is enabled, we calculate the spmap based 
   1002        on the 8 bit p_vect_spri[7:0] and also the number of SPRI nodes  */    
   1003     if (sp_vec) {
   1004         f1 = soc_mem_field32_get(unit, mem, &entry, P_NUM_SPRIf);
   1005         f2 = soc_mem_field32_get(unit, mem, &entry, P_VECT_SPRI_7_4f);
   1006         *pspmap = f1 | (f2 << 4);
   1007         if ( (f1 >> 1) == 0 && f1 > 0) {
   1008             num_spri = 1;
   1009         } else {
   1010     
   1011             for (ii = 0; ii < 8; ii++) {
   1012                 if ((1 << ii) & *pspmap) {
   1013                     num_spri++;
   1014                 }
   1015             }
   1016         }
   1017     } else {
   1018         num_spri = soc_mem_field32_get(unit, mem, &entry, P_NUM_SPRIf);
   1019     }
   1020  
   1021     if ((mem == ES_PIPE0_LLS_L1_MEMA_CONFIGm) || 
   1022         (mem == ES_PIPE1_LLS_L1_MEMA_CONFIGm)) {
   1023         first_sp_child = soc_mem_field32_get(unit, mem, &entry, P_START_UC_SPRIf);
   1024         first_sp_mc_child = soc_mem_field32_get(unit, mem, 
   1025                                          &entry, P_START_MC_SPRIf);
   1026         ucmap = soc_mem_field32_get(unit, mem, &entry, P_SPRI_SELECTf);
   1027     } else {
   1028         first_sp_child = soc_mem_field32_get(unit, mem, &entry, P_START_SPRIf);
   1029         first_sp_mc_child = 0;
   1030     }
   1031     
   1032     if (num_spri == 0) {
   1033         ucmap = 0;
   1034     }
   1035 
   1036     if (pnum_spri) {
   1037         *pnum_spri = num_spri;
   1038     }
   1039        
   1040     if (pucmap) {
   1041         *pucmap = ucmap;
   1042     }
   1043 
   1044     if (pfirst_sp_child) {
   1045         *pfirst_sp_child = first_sp_child;
   1046     }
   1047 
   1048     if (pfirst_sp_mc_child) {
   1049         *pfirst_sp_mc_child = first_sp_mc_child;
   1050     }
   1051 
   1052     LOG_INFO(BSL_LS_SOC_COSQ,
   1053              (BSL_META_U(unit,
   1054                          "Port:%d L%s%d config : index=%d FC=%d FMC=%d UMAP=0x%x\n"),
   1055               port, (level == 0) ? "r" : "", level - 1, 
   1056               index, first_sp_child, first_sp_mc_child, ucmap));
   1057 
   1058     return SOC_E_NONE;
   1059 }
   1060 
   1061 int
   1062 soc_td2_cosq_get_sched_mode(int unit, soc_port_t port, int level, 
   1063                             int index, soc_td2_sched_mode_e *pmode, int *weight)
   1064 {
   1065     soc_trident2_sched_type_t sched_type;
   1066     uint32 entry[SOC_MAX_MEM_WORDS], rval, wrr_mask;
   1067     soc_td2_sched_mode_e mode = SOC_TD2_SCHED_MODE_UNKNOWN;
   1068     soc_mem_t mem;
   1069     soc_reg_t reg;
   1070     int parent_idx  = 0;
   1071     int  idx, fval;    
   1072 
   1073     reg = INVALIDr;
   1074     mem = INVALIDm;
   1075     sched_type = _soc_trident2_port_sched_type_get(unit, port);
   1076 
   1077     if (sched_type == SOC_TD2_SCHED_HSP) {
   1078         /* get the port relative index / offset */
   1079         if (level == SOC_TD2_NODE_LVL_L0) {
   1080             index = index % 5;
   1081             reg = HSP_SCHED_PORT_CONFIGr;
   1082             parent_idx = 0;
   1083         } else if (level == SOC_TD2_NODE_LVL_L1) {
   1084             index = index % 10;
   1085             reg = HSP_SCHED_L0_NODE_CONFIGr;
   1086             /* Find the Parent index for the current child */
   1087             for (idx = 1; idx < 5; idx++) {
   1088                 SOC_IF_ERROR_RETURN(READ_HSP_SCHED_L0_NODE_CONNECTION_CONFIGr(
   1089                                                     unit, port, idx, &rval));
   1090                 fval = soc_reg_field_get(unit,
   1091                             HSP_SCHED_L0_NODE_CONNECTION_CONFIGr,
   1092                             rval, CHILDREN_CONNECTION_MAPf);
   1093                 if (idx == 4) {
   1094                     if ((index >= 8) && (fval & (1 << (index - 2)))) {
   1095                         parent_idx = idx;
   1096                         break;
   1097                     }
   1098                 } else {
   1099                     if (fval & (1 << index)) {
   1100                         parent_idx = idx;
   1101                         break;
   1102                     }
   1103                 }
   1104             }
   1105         } else if (level == SOC_TD2_NODE_LVL_L2) {
   1106             uint32 rval = 0;
   1107             uint32 mc_group_mode = 0;
   1108             SOC_IF_ERROR_RETURN(
   1109                 READ_HSP_SCHED_PORT_CONFIGr(unit, port, &rval));
   1110             mc_group_mode  = soc_reg_field_get(unit, 
   1111                                                HSP_SCHED_PORT_CONFIGr,
   1112                                                rval, MC_GROUP_MODEf);
   1113             reg = HSP_SCHED_L1_NODE_CONFIGr;
   1114             parent_idx = index % 10;
   1115 
   1116             if (mc_group_mode && (index >= 1480)) {
   1117                 if ((index % 10) < _TD2_HSP_PORT_MAX_COS) {
   1118                     reg= HSP_SCHED_L0_NODE_CONFIGr;
   1119                     parent_idx = 0;
   1120                 }
   1121             }
   1122         } else {
   1123             return SOC_E_PARAM;
   1124         }
   1125 
   1126         /* selection between SP and WxRR is based on weight property. */
   1127         SOC_IF_ERROR_RETURN(soc_td2_sched_weight_get(unit, port, 
   1128                                                 level, index, weight));
   1129         if (*weight == 0) {
   1130             mode = SOC_TD2_SCHED_MODE_STRICT;
   1131         } else {
   1132             SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, port, 0, &rval));
   1133             wrr_mask = soc_reg_field_get(unit, reg, rval, ENABLE_WRRf);
   1134             if (wrr_mask & (1 << parent_idx)) {
   1135                 mode = SOC_TD2_SCHED_MODE_WRR;
   1136             } else {
   1137                 mode = SOC_TD2_SCHED_MODE_WDRR;
   1138             }
   1139         }
   1140     } else {
   1141         SOC_IF_ERROR_RETURN(soc_td2_sched_weight_get(unit, port, 
   1142                                                 level, index, weight));
   1143 
   1144         if (*weight == 0) {
   1145             mode = SOC_TD2_SCHED_MODE_STRICT;
   1146         } else {
   1147             mem = _SOC_TD2_NODE_CONFIG_MEM(unit, port, SOC_TD2_NODE_LVL_ROOT);
   1148             index = _soc_trident2_root_scheduler_index(unit, port);
   1149             SOC_IF_ERROR_RETURN(
   1150                     soc_mem_read(unit, mem, MEM_BLOCK_ALL, index, &entry));
   1151             if (soc_mem_field32_get(unit, mem, 
   1152                                 entry, PACKET_MODE_WRR_ACCOUNTING_ENABLEf)) {
   1153                 mode = SOC_TD2_SCHED_MODE_WRR;
   1154             } else {
   1155                 mode = SOC_TD2_SCHED_MODE_WDRR;
   1156             }
   1157         }
   1158     }
   1159 
   1160     if (pmode) {
   1161         *pmode = mode;
   1162     }
   1163 
   1164     LOG_INFO(BSL_LS_SOC_COSQ,
   1165              (BSL_META_U(unit,
   1166                          "Port:%d L%s%d config : index=%d MODE=%d WT=%d\n"),
   1167               port, (level == 0) ? "r" : "", level - 1, index, mode, *weight));
   1168 
   1169     return SOC_E_NONE;
   1170 }
   1171 
   1172 int
   1173 soc_td2_cosq_get_sched_config(int unit, soc_port_t port,
   1174                               int level, int index, int child_index,
   1175                               int *pnum_spri, int *pfirst_child, 
   1176                               int *pfirst_mc_child, uint32 *pucmap, uint32 *pspmap,
   1177                               soc_td2_sched_mode_e *pmode, int *weight)
   1178 {
   1179     int child_level;
   1180 
   1181     if (level >= SOC_TD2_NODE_LVL_L2) {
   1182         return SOC_E_PARAM;
   1183     }
   1184 
   1185     SOC_IF_ERROR_RETURN(soc_td2_cosq_get_sched_child_config(unit, port, level,
   1186                         index, pnum_spri, pfirst_child, pfirst_mc_child, pucmap,
   1187                         pspmap));
   1188 
   1189     if (child_index >= 0) {
   1190         soc_td2_get_child_type(unit, port, level, &child_level);
   1191         
   1192         SOC_IF_ERROR_RETURN(
   1193                 soc_td2_cosq_get_sched_mode(unit, port, child_level, child_index,
   1194                                             pmode, weight));
   1195     }
   1196     
   1197     return SOC_E_NONE;
   1198 }
   1199 
   1200 int soc_td2_get_child_type(int unit, soc_port_t port, int level, 
   1201                                     int *child_type)
   1202 {
   1203     *child_type = -1;
   1204 
   1205     if (level == SOC_TD2_NODE_LVL_ROOT) {
   1206         *child_type = SOC_TD2_NODE_LVL_L0;
   1207     } else if (level == SOC_TD2_NODE_LVL_L0) {
   1208         *child_type = SOC_TD2_NODE_LVL_L1;
   1209     } else if (level == SOC_TD2_NODE_LVL_L1) {
   1210         *child_type = SOC_TD2_NODE_LVL_L2;
   1211     }
   1212     return SOC_E_NONE;
   1213 }
   1214 
   1215 typedef struct _soc_td2_lls_config_s {
   1216     int    level;
   1217     int    node_id;
   1218     int    num_children;
   1219     int    sched_mode;
   1220     int    weights[48];
   1221     uint32 uc_mc_map;
   1222 } _soc_td2_lls_config_t;
   1223 
   1224 /* CPU lls tree is dynamically generated */
   1225 static _soc_td2_lls_config_t *_td2_cpu_port_lls_config[SOC_MAX_NUM_DEVICES];
   1226 
   1227 static _soc_td2_lls_config_t _td2_port_lls_config[] = {
   1228     /* SOC_TD2_NODE_LVL_ROOT */
   1229     { SOC_TD2_NODE_LVL_ROOT, 0,
   1230       1, SOC_TD2_SCHED_MODE_WRR, 
   1231       { 1,1,1,1,1,1,1,1,
   1232         1,1,1,1,1,1,1,1,
   1233         1,1,1,1,1,1,1,1,
   1234         1,1,1,1,1,1,1,1,
   1235         1,1,1,1,1,1,1,1,
   1236         1,1,1,1,1,1,1,1 },
   1237       0},
   1238     /* SOC_TD2_NODE_LVL_L0 L0.0 */
   1239     { SOC_TD2_NODE_LVL_L0, 0,
   1240       10, SOC_TD2_SCHED_MODE_WRR, 
   1241       { 1,1,1,1,1,1,1,1,
   1242         1,1,1,1,1,1,1,1,
   1243         1,1,1,1,1,1,1,1,
   1244         1,1,1,1,1,1,1,1,
   1245         1,1,1,1,1,1,1,1,
   1246         1,1,1,1,1,1,1,1 },
   1247       0},
   1248     /* SOC_TD2_NODE_LVL_L1 L1.0 */
   1249     { SOC_TD2_NODE_LVL_L1, 0,
   1250       2, SOC_TD2_SCHED_MODE_WRR, 
   1251       { 1,1,1,1,1,1,1,1,
   1252         1,1,1,1,1,1,1,1,
   1253         1,1,1,1,1,1,1,1,
   1254         1,1,1,1,1,1,1,1,
   1255         1,1,1,1,1,1,1,1,
   1256         1,1,1,1,1,1,1,1 },
   1257       0x1 /* 1 UC nodes, 1 MC node */},
   1258     /* SOC_TD2_NODE_LVL_L1 L1.1 */
   1259     { SOC_TD2_NODE_LVL_L1, 1,
   1260       2, SOC_TD2_SCHED_MODE_WRR, 
   1261       { 1,1,1,1,1,1,1,1,
   1262         1,1,1,1,1,1,1,1,
   1263         1,1,1,1,1,1,1,1,
   1264         1,1,1,1,1,1,1,1,
   1265         1,1,1,1,1,1,1,1,
   1266         1,1,1,1,1,1,1,1 },
   1267       0x1 /* 1 UC nodes, 1 MC node */},
   1268     /* SOC_TD2_NODE_LVL_L1 L1.2 */
   1269     { SOC_TD2_NODE_LVL_L1, 2,
   1270       2, SOC_TD2_SCHED_MODE_WRR, 
   1271       { 1,1,1,1,1,1,1,1,
   1272         1,1,1,1,1,1,1,1,
   1273         1,1,1,1,1,1,1,1,
   1274         1,1,1,1,1,1,1,1,
   1275         1,1,1,1,1,1,1,1,
   1276         1,1,1,1,1,1,1,1 },
   1277       0x1 /* 1 UC nodes, 1 MC node */},
   1278     /* SOC_TD2_NODE_LVL_L1 L1.3 */
   1279     { SOC_TD2_NODE_LVL_L1, 3,
   1280       2, SOC_TD2_SCHED_MODE_WRR, 
   1281       { 1,1,1,1,1,1,1,1,
   1282         1,1,1,1,1,1,1,1,
   1283         1,1,1,1,1,1,1,1,
   1284         1,1,1,1,1,1,1,1,
   1285         1,1,1,1,1,1,1,1,
   1286         1,1,1,1,1,1,1,1 },
   1287       0x1 /* 1 UC nodes, 1 MC node */},
   1288     /* SOC_TD2_NODE_LVL_L1 L1.4 */
   1289     { SOC_TD2_NODE_LVL_L1, 4,
   1290       2, SOC_TD2_SCHED_MODE_WRR, 
   1291       { 1,1,1,1,1,1,1,1,
   1292         1,1,1,1,1,1,1,1,
   1293         1,1,1,1,1,1,1,1,
   1294         1,1,1,1,1,1,1,1,
   1295         1,1,1,1,1,1,1,1,
   1296         1,1,1,1,1,1,1,1 },
   1297       0x1 /* 1 UC nodes, 1 MC node */},
   1298     /* SOC_TD2_NODE_LVL_L1 L1.5 */
   1299     { SOC_TD2_NODE_LVL_L1, 5,
   1300       2, SOC_TD2_SCHED_MODE_WRR, 
   1301       { 1,1,1,1,1,1,1,1,
   1302         1,1,1,1,1,1,1,1,
   1303         1,1,1,1,1,1,1,1,
   1304         1,1,1,1,1,1,1,1,
   1305         1,1,1,1,1,1,1,1,
   1306         1,1,1,1,1,1,1,1 },
   1307       0x1 /* 1 UC nodes, 1 MC node */},
   1308     /* SOC_TD2_NODE_LVL_L1 L1.6 */
   1309     { SOC_TD2_NODE_LVL_L1, 6,
   1310       2, SOC_TD2_SCHED_MODE_WRR, 
   1311       { 1,1,1,1,1,1,1,1,
   1312         1,1,1,1,1,1,1,1,
   1313         1,1,1,1,1,1,1,1,
   1314         1,1,1,1,1,1,1,1,
   1315         1,1,1,1,1,1,1,1,
   1316         1,1,1,1,1,1,1,1 },
   1317       0x1 /* 1 UC nodes, 1 MC node */},
   1318     /* SOC_TD2_NODE_LVL_L1 L1.7 */
   1319     { SOC_TD2_NODE_LVL_L1, 7,
   1320       2, SOC_TD2_SCHED_MODE_WRR, 
   1321       { 1,1,1,1,1,1,1,1,
   1322         1,1,1,1,1,1,1,1,
   1323         1,1,1,1,1,1,1,1,
   1324         1,1,1,1,1,1,1,1,
   1325         1,1,1,1,1,1,1,1,
   1326         1,1,1,1,1,1,1,1 },
   1327       0x1 /* 1 UC nodes, 1 MC node */},
   1328     /* SOC_TD2_NODE_LVL_L1 L1.8 */
   1329     { SOC_TD2_NODE_LVL_L1, 8,
   1330       2, SOC_TD2_SCHED_MODE_WRR, 
   1331       { 1,1,1,1,1,1,1,1,
   1332         1,1,1,1,1,1,1,1,
   1333         1,1,1,1,1,1,1,1,
   1334         1,1,1,1,1,1,1,1,
   1335         1,1,1,1,1,1,1,1,
   1336         1,1,1,1,1,1,1,1 },
   1337       0x1 /* 1 UC nodes, 1 MC node */},
   1338     /* SOC_TD2_NODE_LVL_L1 L1.7 */
   1339     { SOC_TD2_NODE_LVL_L1, 9,
   1340       2, SOC_TD2_SCHED_MODE_WRR, 
   1341       { 1,1,1,1,1,1,1,1,
   1342         1,1,1,1,1,1,1,1,
   1343         1,1,1,1,1,1,1,1,
   1344         1,1,1,1,1,1,1,1,
   1345         1,1,1,1,1,1,1,1,
   1346         1,1,1,1,1,1,1,1 },
   1347       0x1 /* 1 UC nodes, 1 MC node */},
   1348     /* SOC_TD2_NODE_LVL_L2 */
   1349     { -1, 0, 0, -1,
   1350       { 1,1,1,1,1,1,1,1,
   1351         1,1,1,1,1,1,1,1,
   1352         1,1,1,1,1,1,1,1,
   1353         1,1,1,1,1,1,1,1,
   1354         1,1,1,1,1,1,1,1,
   1355         1,1,1,1,1,1,1,1 },
   1356       1 }
   1357 };
   1358 
   1359 static _soc_td2_lls_config_t _td2_lb_port_lls_config[] = {
   1360     /* SOC_TD2_NODE_LVL_ROOT */
   1361     { SOC_TD2_NODE_LVL_ROOT, 0,
   1362       1, SOC_TD2_SCHED_MODE_WRR,
   1363       { 1,1,1,1,1,1,1,1,
   1364         1,1,1,1,1,1,1,1,
   1365         1,1,1,1,1,1,1,1,
   1366         1,1,1,1,1,1,1,1,
   1367         1,1,1,1,1,1,1,1,
   1368         1,1,1,1,1,1,1,1 },
   1369       0},
   1370     /* SOC_TD2_NODE_LVL_L0 L0.0 */
   1371     { SOC_TD2_NODE_LVL_L0, 0,
   1372       9, SOC_TD2_SCHED_MODE_WRR,
   1373       { 1,1,1,1,1,1,1,1,
   1374         1,1,1,1,1,1,1,1,
   1375         1,1,1,1,1,1,1,1,
   1376         1,1,1,1,1,1,1,1,
   1377         1,1,1,1,1,1,1,1,
   1378         1,1,1,1,1,1,1,1 },
   1379       0},
   1380     /* SOC_TD2_NODE_LVL_L1 L1.0 */
   1381     { SOC_TD2_NODE_LVL_L1, 0,
   1382       1, SOC_TD2_SCHED_MODE_WRR,
   1383       { 1,1,1,1,1,1,1,1,
   1384         1,1,1,1,1,1,1,1,
   1385         1,1,1,1,1,1,1,1,
   1386         1,1,1,1,1,1,1,1,
   1387         1,1,1,1,1,1,1,1,
   1388         1,1,1,1,1,1,1,1 },
   1389       0 /* 1 MC node */},
   1390     /* SOC_TD2_NODE_LVL_L1 L1.1 */
   1391     { SOC_TD2_NODE_LVL_L1, 1,
   1392       1, SOC_TD2_SCHED_MODE_WRR,
   1393       { 1,1,1,1,1,1,1,1,
   1394         1,1,1,1,1,1,1,1,
   1395         1,1,1,1,1,1,1,1,
   1396         1,1,1,1,1,1,1,1,
   1397         1,1,1,1,1,1,1,1,
   1398         1,1,1,1,1,1,1,1 },
   1399       0 /* 1 MC node */},
   1400     /* SOC_TD2_NODE_LVL_L1 L1.2 */
   1401     { SOC_TD2_NODE_LVL_L1, 2,
   1402       1, SOC_TD2_SCHED_MODE_WRR,
   1403       { 1,1,1,1,1,1,1,1,
   1404         1,1,1,1,1,1,1,1,
   1405         1,1,1,1,1,1,1,1,
   1406         1,1,1,1,1,1,1,1,
   1407         1,1,1,1,1,1,1,1,
   1408         1,1,1,1,1,1,1,1 },
   1409       0 /* 1 MC node */},
   1410     /* SOC_TD2_NODE_LVL_L1 L1.3 */
   1411     { SOC_TD2_NODE_LVL_L1, 3,
   1412       1, SOC_TD2_SCHED_MODE_WRR,
   1413       { 1,1,1,1,1,1,1,1,
   1414         1,1,1,1,1,1,1,1,
   1415         1,1,1,1,1,1,1,1,
   1416         1,1,1,1,1,1,1,1,
   1417         1,1,1,1,1,1,1,1,
   1418         1,1,1,1,1,1,1,1 },
   1419       0 /* 1 MC node */},
   1420     /* SOC_TD2_NODE_LVL_L1 L1.4 */
   1421     { SOC_TD2_NODE_LVL_L1, 4,
   1422       1, SOC_TD2_SCHED_MODE_WRR,
   1423       { 1,1,1,1,1,1,1,1,
   1424         1,1,1,1,1,1,1,1,
   1425         1,1,1,1,1,1,1,1,
   1426         1,1,1,1,1,1,1,1,
   1427         1,1,1,1,1,1,1,1,
   1428         1,1,1,1,1,1,1,1 },
   1429       0 /* 1 MC node */},
   1430     /* SOC_TD2_NODE_LVL_L1 L1.5 */
   1431     { SOC_TD2_NODE_LVL_L1, 5,
   1432       1, SOC_TD2_SCHED_MODE_WRR,
   1433       { 1,1,1,1,1,1,1,1,
   1434         1,1,1,1,1,1,1,1,
   1435         1,1,1,1,1,1,1,1,
   1436         1,1,1,1,1,1,1,1,
   1437         1,1,1,1,1,1,1,1,
   1438         1,1,1,1,1,1,1,1 },
   1439       0 /* 1 MC node */},
   1440     /* SOC_TD2_NODE_LVL_L1 L1.6 */
   1441     { SOC_TD2_NODE_LVL_L1, 6,
   1442       1, SOC_TD2_SCHED_MODE_WRR,
   1443       { 1,1,1,1,1,1,1,1,
   1444         1,1,1,1,1,1,1,1,
   1445         1,1,1,1,1,1,1,1,
   1446         1,1,1,1,1,1,1,1,
   1447         1,1,1,1,1,1,1,1,
   1448         1,1,1,1,1,1,1,1 },
   1449       0 /* 1 MC node */},
   1450     /* SOC_TD2_NODE_LVL_L1 L1.7 */
   1451     { SOC_TD2_NODE_LVL_L1, 7,
   1452       1, SOC_TD2_SCHED_MODE_WRR,
   1453       { 1,1,1,1,1,1,1,1,
   1454         1,1,1,1,1,1,1,1,
   1455         1,1,1,1,1,1,1,1,
   1456         1,1,1,1,1,1,1,1,
   1457         1,1,1,1,1,1,1,1,
   1458         1,1,1,1,1,1,1,1 },
   1459       0 /* 1 MC node */},
   1460     /* SOC_TD2_NODE_LVL_L1 L1.8 */
   1461     { SOC_TD2_NODE_LVL_L1, 8,
   1462       1, SOC_TD2_SCHED_MODE_WRR,
   1463       { 1,1,1,1,1,1,1,1,
   1464         1,1,1,1,1,1,1,1,
   1465         1,1,1,1,1,1,1,1,
   1466         1,1,1,1,1,1,1,1,
   1467         1,1,1,1,1,1,1,1,
   1468         1,1,1,1,1,1,1,1 },
   1469       0 /* 1 QCN node */},
   1470     /* SOC_TD2_NODE_LVL_L2 */
   1471     { -1, 0, 0, -1,
   1472       { 1,1,1,1,1,1,1,1,
   1473         1,1,1,1,1,1,1,1,
   1474         1,1,1,1,1,1,1,1,
   1475         1,1,1,1,1,1,1,1,
   1476         1,1,1,1,1,1,1,1,
   1477         1,1,1,1,1,1,1,1 },
   1478       0 }
   1479 };
   1480 
   1481 STATIC _soc_td2_lls_config_t *
   1482 _soc_td2_get_config_for_level(_soc_td2_lls_config_t *cfg_tbl, int lvl, 
   1483                               int offset)
   1484 {
   1485     _soc_td2_lls_config_t *en = cfg_tbl;
   1486 
   1487     while (en->level != -1) {
   1488         if ((en->level == lvl) && (en->node_id == offset)) {
   1489             return en;
   1490         }
   1491         en++;
   1492     }
   1493 
   1494     return NULL;
   1495 }
   1496 
   1497 STATIC int
   1498 _soc_td2_get_sched_count(int unit, soc_port_t port, 
   1499                          _soc_td2_lls_config_t *cfgtbl, int lvl)
   1500 {
   1501     int cnt = 0;
   1502 
   1503     while (_soc_td2_get_config_for_level(cfgtbl, lvl, cnt)) {
   1504         cnt++;
   1505     }
   1506     return cnt;
   1507 }
   1508 
   1509 STATIC int
   1510 _soc_td2_alloc_sched(int unit, soc_port_t in_port, soc_td2_node_lvl_e lvl, 
   1511                      int offset, int *hw_index)
   1512 {
   1513 
   1514     int port, in_pipe, port_in_pipe, tlm = -1, cpu_tlm;
   1515     int mmu_port, empty, base, max = -1, jj;
   1516     soc_trident2_sched_type_t stype;
   1517     uint32  sched_bmap[32];
   1518     int base_hsp = 0;
   1519 
   1520     COMPILER_REFERENCE(base_hsp);
   1521     
   1522     sal_memset(sched_bmap, 0, sizeof(uint32)*32);
   1523 
   1524     SOC_IF_ERROR_RETURN(
   1525         soc_td2_port_common_attributes_get(unit, in_port, &in_pipe, &mmu_port, NULL));
   1526 
   1527     stype = _soc_trident2_port_sched_type_get(unit, in_port);
   1528 
   1529     if (lvl == SOC_TD2_NODE_LVL_ROOT) {
   1530         tlm = 1;
   1531         max = 106;
   1532     } else if (lvl == SOC_TD2_NODE_LVL_L0) {
   1533         tlm = 5; /* max 4 L0 under HSP */
   1534         max = 265;
   1535     } else if (lvl == SOC_TD2_NODE_LVL_L1) {
   1536         tlm = 10;
   1537         max = 1024;
   1538     }
   1539 
   1540     if ((max < 0) || (tlm < 0)) {
   1541         return SOC_E_PARAM;
   1542     }
   1543 
   1544     base = 0;
   1545     cpu_tlm = _soc_td2_get_sched_count(unit, in_port, _td2_cpu_port_lls_config[unit], lvl);
   1546     if (lvl == SOC_TD2_NODE_LVL_L0) {
   1547         if (cpu_tlm < SOC_TD2_COSQ_NUM_CPU_L0_NODES(unit)) {
   1548             cpu_tlm = SOC_TD2_COSQ_NUM_CPU_L0_NODES(unit);
   1549         }
   1550     }
   1551 
   1552     if (stype == SOC_TD2_SCHED_HSP) {
   1553         /* For HSP ports, the indexes of the scheduler and queues are fixed.*/
   1554         if (offset >= tlm) {
   1555             return SOC_E_PARAM;
   1556         }
   1557         mmu_port += (mmu_port >= 64) ? -64 : 0;
   1558         *hw_index = (mmu_port * tlm) + offset;
   1559         return SOC_E_NONE;
   1560     } else {
   1561         /* reserve all the scheduler and queus that are prefixed for hsp. */
   1562         PBMP_ALL_ITER(unit, port) {
   1563             SOC_IF_ERROR_RETURN(soc_td2_port_common_attributes_get(unit, port, 
   1564                                         &port_in_pipe, &mmu_port, NULL));
   1565             if (in_pipe != port_in_pipe) {
   1566                 continue;
   1567             }
   1568 
   1569             if (_soc_trident2_port_sched_type_get(unit, port) == SOC_TD2_SCHED_HSP) {
   1570                 mmu_port += (mmu_port >= 64) ? -64 : 0;
   1571                 base = mmu_port * tlm;
   1572                 for (jj = 0; jj < tlm; jj++) {
   1573                     sched_bmap[(base + jj)/32] |= 1 << ((base + jj) % 32);
   1574                 }
   1575                 if (base + tlm > base_hsp) {
   1576                     base_hsp = base + tlm;
   1577                 }
   1578             }
   1579         }
   1580         
   1581         if (lvl == SOC_TD2_NODE_LVL_L0) {
   1582             base = SOC_TD2_COSQ_CPU_RESERVED_L0_BASE(unit);
   1583             if (IS_CPU_PORT(unit, in_port)) {
   1584                 if (offset >= cpu_tlm) {
   1585                     return SOC_E_PARAM;
   1586                 }
   1587                 base += offset;
   1588                 sched_bmap[base/32] |= 1 << (base % 32);
   1589                 *hw_index = base;
   1590                 return SOC_E_NONE;
   1591             } else {
   1592                 /* reserve the CPU L0 nodes */
   1593                 for (jj = 0; jj < cpu_tlm; jj++) {
   1594                     sched_bmap[(base + jj)/32] |= 1 << ((base + jj) % 32);
   1595                 }
   1596             }
   1597             base = INVALID_PARENT(unit, lvl);
   1598             if (base == 0) {
   1599                 base = 53;
   1600             }
   1601             sched_bmap[base/32] |= (1 << (base % 32));
   1602         } else {
   1603             base = INVALID_PARENT(unit, lvl);
   1604             sched_bmap[base/32] |= (1 << (base % 32));
   1605         }
   1606 
   1607         cpu_tlm = (cpu_tlm + 3) & ~3;
   1608 
   1609         base = 0;
   1610         PBMP_ALL_ITER(unit, port) {
   1611             SOC_IF_ERROR_RETURN(
   1612                 soc_td2_port_common_attributes_get(unit, port, 
   1613                                                  &port_in_pipe, &mmu_port, NULL));
   1614             if ((in_pipe != port_in_pipe) || 
   1615                 (_soc_trident2_port_sched_type_get(unit, port) == SOC_TD2_SCHED_HSP)) {
   1616                 continue;
   1617             }
   1618             
   1619             tlm = _soc_td2_get_sched_count(unit, port, 
   1620                 ((IS_CPU_PORT(unit, port)) ? _td2_cpu_port_lls_config[unit] :
   1621                                              _td2_port_lls_config), lvl);
   1622             tlm = (tlm + 3) & ~3;
   1623 
   1624 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   1625             if (SOC_IS_TD2P_TT2P(unit)) {
   1626                 if (lvl == SOC_TD2_NODE_LVL_L1) {
   1627                     if (IS_CPU_PORT(unit, in_port)) {
   1628                         if (offset >= cpu_tlm) {
   1629                             return SOC_E_PARAM;
   1630                         }
   1631                         base = base_hsp;
   1632                         base += offset;
   1633                         sched_bmap[base/32] |= 1 << (base % 32);
   1634                         *hw_index = base;
   1635                         return SOC_E_NONE;
   1636                     }
   1637                 } 
   1638 
   1639                 mmu_port += (mmu_port >= 64) ? -64 : 0;
   1640                 if (lvl == SOC_TD2_NODE_LVL_L1) {
   1641                     base = cpu_tlm + (mmu_port * tlm);
   1642                 } else {
   1643                     base = mmu_port * tlm;
   1644                 }
   1645                 if (base >= max) {
   1646                     return SOC_E_RESOURCE;
   1647                 }
   1648                 if (port == in_port) {
   1649                     if (offset >= tlm) {
   1650                         return SOC_E_PARAM;
   1651                     }
   1652                     *hw_index = base + offset;
   1653                     return SOC_E_NONE;
   1654                 } else {
   1655                     for(jj = 0; jj < tlm; jj++) {
   1656                         sched_bmap[base/32] |= 1 << (base % 32);
   1657                         base += 1;
   1658                     }
   1659                 }
   1660             } else
   1661 #endif
   1662             {
   1663                 /* step to empty resources start. */
   1664                 empty = 0;
   1665                 while (base < max) {
   1666                     if ((sched_bmap[base/32] & (1 << (base % 32))) == 0) {
   1667                         empty += 1;
   1668                     } else {
   1669                         empty = 0;
   1670                     }
   1671 
   1672                     base += 1;
   1673                     if (empty == tlm) {
   1674                         base -= tlm;
   1675                         break;
   1676                     }
   1677                 }
   1678 
   1679                 if (base == max) {
   1680                     return SOC_E_RESOURCE;
   1681                 }
   1682 
   1683                 if (port == in_port) {
   1684                     if (offset >= tlm) {
   1685                         return SOC_E_PARAM;
   1686                     }
   1687                     *hw_index = base + offset;
   1688                     return SOC_E_NONE;
   1689                 } else {
   1690                     for(jj = 0; jj < tlm; jj++) {
   1691                         sched_bmap[base/32] |= 1 << (base % 32);
   1692                         base += 1;
   1693                     }
   1694                 }
   1695             }
   1696         }
   1697     }
   1698 
   1699     return SOC_E_RESOURCE;
   1700 }
   1701 
   1702 int soc_td2_l2_hw_index(int unit, int qnum, int uc)
   1703 {
   1704     if (uc) {
   1705         qnum -= (qnum >= 1480) ? 1480 : 0;
   1706     } else {
   1707         qnum -= (qnum >= 568) ? 568 : 0;
   1708         qnum += 1480;
   1709     }
   1710     return qnum;
   1711 }
   1712 
   1713 /*
   1714  * Function:
   1715  *     soc_td2_hw_index_logical_num
   1716  * Purpose:
   1717  *     Get the logical queue number according to hw index
   1718  * Parameters:
   1719  *     unit          - (IN) unit number
   1720  *     port          - (IN) local port number
   1721  *     index         -(IN) The index of Queue management related memory Tables
   1722  *     uc            - (IN) unicast indicator
   1723  * Returns:
   1724  *     logical queue number: queue number in logical view
   1725  *     In logical view,
   1726  *     the range of unicast queue number is:   pipeX[0,1480),pipeY[1480,2960)
   1727  *     the range of multicast queue number is: pipeX[0,568),pipeY[568,1136)
   1728  */
   1729 int
   1730 soc_td2_hw_index_logical_num(int unit,int port,int index,int uc)
   1731 {
   1732     int qnum;
   1733     uint32 pipe =  SOC_TD2_PORT_PIPE(unit, port);
   1734     if (uc) {
   1735         qnum = index + ( pipe ? 1480 : 0);
   1736     } else {
   1737         qnum =  index - 1480;
   1738         qnum += pipe ? 568 : 0;
   1739     }
   1740 
   1741     return qnum;
   1742 }
   1743 
   1744 STATIC int
   1745 soc_td2_port_lls_init(int unit, int port, _soc_td2_lls_config_t *cfg_tbl,
   1746                       int setup, _soc_td2_lls_traverse_cb cb, void *cookie)
   1747 {
   1748     _soc_td2_lls_config_t *pinfo, *cinfo;
   1749     struct _td2_sched_pending_setup_s {
   1750         int     parent;
   1751         int     level;
   1752         int     offset;
   1753         int     hw_index;
   1754         int     l2_uc;
   1755     } pending_list[64], *ppending;
   1756     int  list_size, lindex, child_lvl = 0, uc;
   1757     int  l2_lvl_offsets[2], rc, numq;
   1758     int spri, smcpri, num_spri, qnum, self_hw_index, c;
   1759     uint32 ucmap, rval;
   1760     int pipe, mmu_port;
   1761     int num_children, lvl_offsets[4];
   1762     int sp_vec = soc_feature(unit, soc_feature_vector_based_spri);
   1763 
   1764 
   1765     /* If the dynamic switchover feature is enabled, we need to enable the
   1766        spri_vect_mode by setting spri_vect_mode_enable in LLS_CONFIG0 reg */
   1767     if (sp_vec) {
   1768         
   1769         SOC_IF_ERROR_RETURN(READ_ES_PIPE0_LLS_CONFIG0r(unit, &rval));
   1770         if (!soc_reg_field_get(unit, ES_PIPE0_LLS_CONFIG0r, rval, 
   1771                                SPRI_VECT_MODE_ENABLEf)) {
   1772             soc_reg_field_set(unit, ES_PIPE0_LLS_CONFIG0r, &rval, 
   1773                               SPRI_VECT_MODE_ENABLEf, 1);
   1774             SOC_IF_ERROR_RETURN(WRITE_ES_PIPE0_LLS_CONFIG0r(unit, rval));
   1775             SOC_IF_ERROR_RETURN(WRITE_ES_PIPE1_LLS_CONFIG0r(unit, rval)); 
   1776         }
   1777     }
   1778 
   1779     l2_lvl_offsets[0] = l2_lvl_offsets[1] = 0;
   1780     lvl_offsets[0] = lvl_offsets[1] = lvl_offsets[2] = lvl_offsets[3] = 0;
   1781 
   1782     SOC_IF_ERROR_RETURN(
   1783         soc_td2_port_common_attributes_get(unit, port, &pipe, &mmu_port, NULL));
   1784 
   1785     /* setup port scheduler */
   1786     pending_list[0].parent = -1;
   1787     pending_list[0].level = SOC_TD2_NODE_LVL_ROOT;
   1788     pending_list[0].offset = 0;
   1789     pending_list[0].hw_index = (pipe) ? mmu_port - 64 : mmu_port;
   1790 
   1791     list_size = 1;
   1792     lindex = 0;
   1793     do {
   1794         ppending = &pending_list[lindex++];
   1795         self_hw_index = ppending->hw_index;
   1796         /* If we are just traversing the LLS heirarchy, just call the callback
   1797            function, which is passed as an argument to this func */
   1798         if (setup == _SOC_TD2_LLS_OP_TRAVERSE) {
   1799             if (cb != NULL) {
   1800                 cb(unit, port, ppending->level, ppending->hw_index, cookie);
   1801             }
   1802         } else if (ppending->parent != -1) {            
   1803             /* attach to parent */
   1804             SOC_IF_ERROR_RETURN(soc_td2_cosq_set_sched_parent(unit, port, 
   1805                                 ppending->level, self_hw_index, 
   1806             (setup) ? ppending->parent : INVALID_PARENT(unit, ppending->level)));
   1807         }
   1808 
   1809         if (ppending->level == SOC_TD2_NODE_LVL_L2) {
   1810             continue;
   1811         }
   1812         
   1813         pinfo = _soc_td2_get_config_for_level(cfg_tbl, 
   1814                                               ppending->level, 
   1815                                               ppending->offset);
   1816         if (!pinfo) {
   1817             return SOC_E_INTERNAL;
   1818         }
   1819             
   1820         soc_td2_get_child_type(unit, port, ppending->level, &child_lvl);
   1821         ucmap = 0;
   1822         spri = -1;
   1823         smcpri = -1;
   1824         num_spri = 0;
   1825 
   1826         num_children = pinfo->num_children;
   1827 
   1828         for (c = 0; c < num_children; c++) {
   1829             pending_list[list_size].parent = self_hw_index;
   1830             pending_list[list_size].level = child_lvl;
   1831             pending_list[list_size].offset = lvl_offsets[child_lvl];
   1832             lvl_offsets[child_lvl] += 1;
   1833             if (child_lvl == SOC_TD2_NODE_LVL_L2) {
   1834                 uc = 0; /* default MC queue */
   1835                 if (!IS_CPU_PORT(unit, port) && !IS_LB_PORT(unit,port)) {
   1836                     uc = (pinfo->uc_mc_map & (1 << c)) ? 1 : 0;
   1837                 }
   1838 
   1839                 rc = soc_td2_get_def_qbase(unit, port, 
   1840                                 (uc ? _SOC_TD2_INDEX_STYLE_UCAST_QUEUE : 
   1841                                 _SOC_TD2_INDEX_STYLE_MCAST_QUEUE), &qnum, &numq);
   1842 
   1843                 if (rc) {
   1844                     return rc;
   1845                 }
   1846 
   1847                 if ((numq == 0) || (qnum < 0) || l2_lvl_offsets[uc] >= numq) {
   1848                     continue;
   1849                 }
   1850                 qnum = soc_td2_l2_hw_index(unit, qnum, uc);
   1851                 pending_list[list_size].hw_index = qnum + l2_lvl_offsets[uc];
   1852                 l2_lvl_offsets[uc]++;
   1853                 if (uc) {
   1854                     if (spri == -1) {
   1855                         spri = pending_list[list_size].hw_index;
   1856                     }
   1857                 } else {
   1858                     if (smcpri == -1) {
   1859                         smcpri = pending_list[list_size].hw_index;
   1860                     }
   1861                 }
   1862                 if ((pinfo->sched_mode == SOC_TD2_SCHED_MODE_STRICT) &&
   1863                     (!IS_CPU_PORT(unit, port))) {
   1864                     ucmap |= (uc) ? 0 : (1 << c);
   1865                     num_spri++;
   1866                 }
   1867                 /* if we are traversing the LLS, there is no need to set
   1868                    the scheduler parent and mode as it is to be done only 
   1869                    during the init */
   1870                 if (setup == _SOC_TD2_LLS_OP_TRAVERSE) {
   1871                     list_size++;
   1872                 } else {
   1873                     SOC_IF_ERROR_RETURN(
   1874                             soc_td2_cosq_set_sched_parent(unit, port, 
   1875                                   SOC_TD2_NODE_LVL_L2, 
   1876                                   pending_list[list_size].hw_index, 
   1877                                   self_hw_index));
   1878 
   1879                     SOC_IF_ERROR_RETURN(
   1880                         soc_td2_cosq_set_sched_mode(unit, port, SOC_TD2_NODE_LVL_L2,
   1881                                 pending_list[list_size].hw_index,
   1882                                 pinfo->sched_mode, pinfo->weights[c]));
   1883                 }
   1884 
   1885             } else {
   1886                 cinfo = _soc_td2_get_config_for_level(cfg_tbl, child_lvl, 
   1887                                           pending_list[list_size].offset);
   1888                 if (!cinfo) {
   1889                     return SOC_E_INTERNAL;
   1890                 }
   1891                 if (soc_td2_sched_hw_index_get(unit, port, child_lvl, 
   1892                                             pending_list[list_size].offset, 
   1893                                          &pending_list[list_size].hw_index)) {
   1894                     return SOC_E_INTERNAL;
   1895                 }
   1896                 if (spri == -1) {
   1897                     spri = pending_list[list_size].hw_index;
   1898                 }
   1899                 if (cinfo->sched_mode == SOC_TD2_SCHED_MODE_STRICT) {
   1900                     num_spri++;
   1901                 }
   1902                 /* if we are traversing the LLS, there is no need to set
   1903                    the scheduler parent and mode as it is to be done only 
   1904                    during the init */
   1905                 if (setup != _SOC_TD2_LLS_OP_TRAVERSE) {
   1906                     SOC_IF_ERROR_RETURN(
   1907                             soc_td2_cosq_set_sched_parent(unit, port, child_lvl, 
   1908                                 pending_list[list_size].hw_index,
   1909                                 self_hw_index));
   1910 
   1911                     SOC_IF_ERROR_RETURN(
   1912                         soc_td2_cosq_set_sched_mode(unit, port, child_lvl,
   1913                                 pending_list[list_size].hw_index,
   1914                                 cinfo->sched_mode, pinfo->weights[c]));
   1915                 }
   1916                 list_size++;
   1917             }
   1918         }
   1919 
   1920         if (spri == -1) {
   1921             spri = 0;
   1922         }
   1923         if (smcpri == -1) {
   1924             smcpri = 1480;
   1925         }
   1926         /* if we are NOT traversing the LLS, we need to set the scheduler
   1927            configuration for the child  */
   1928         if (setup != _SOC_TD2_LLS_OP_TRAVERSE) {
   1929             SOC_IF_ERROR_RETURN(
   1930                 soc_td2_cosq_set_sched_child_config(unit, port, 
   1931                                     ppending->level, self_hw_index, 
   1932                                     num_spri, spri, smcpri, ucmap, 0));
   1933         }
   1934     } while (lindex < list_size);
   1935 
   1936     return SOC_E_NONE;
   1937 }
   1938 
   1939 /*
   1940  * Function:
   1941  *     soc_td2_hsp_sp_node_init
   1942  * Purpose:
   1943  *     This function initialises ENABLE_SP_IN_MIN setting in
   1944  *     HSP_SCHED_Lx_NODE_CONFIG.
   1945  *     Hardware default value for sched mode is SP. SP nodes
   1946  *     with min bandwidth set may be scheduled in WRR manner.
   1947  *     To schedule SP nodes with strict priority, ENABLE_SP_IN_MIN
   1948  *     must be set.
   1949  * Parameters:
   1950  *     unit       - (IN) unit number
   1951  *     port       - (IN) local port number
   1952  * Returns:
   1953  *     SOC_E_XXX
   1954  */
   1955 int
   1956 soc_td2_hsp_sp_node_init(int unit, soc_port_t port)
   1957 {
   1958     uint32 index, rval, fval;
   1959     soc_reg_t regs[4] = {
   1960             HSP_SCHED_L0_NODE_CONFIGr,
   1961             HSP_SCHED_L1_NODE_CONFIGr,
   1962             HSP_SCHED_L2_UC_QUEUE_CONFIGr,
   1963             HSP_SCHED_L2_MC_QUEUE_CONFIGr
   1964         };
   1965 
   1966     for (index = 0; index < COUNTOF(regs); index++) {
   1967         if (regs[index] == HSP_SCHED_L0_NODE_CONFIGr) {
   1968             fval = 0x1f;
   1969         } else {
   1970             fval = 0x3ff;
   1971         }
   1972         SOC_IF_ERROR_RETURN(soc_reg32_get(unit, regs[index], port, 0, &rval));
   1973         soc_reg_field_set(unit, regs[index], &rval, ENABLE_SP_IN_MINf, fval);
   1974         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, regs[index], port, 0, rval));
   1975     }
   1976 
   1977     return SOC_E_NONE;
   1978 }
   1979 
   1980 #define TD2_DFL_HSP_SCHED_MODE  SOC_TD2_SCHED_MODE_WDRR
   1981 
   1982 STATIC int
   1983 soc_td2_setup_hsp_port(int unit, int port)
   1984 {
   1985     uint32 rval, fval = 0, pbmf;
   1986     int mmu_port, pipe, l0_index, l1_index, l0_1, l0_4, hw_index;
   1987     int hsp_port_index;
   1988 
   1989     SOC_IF_ERROR_RETURN(
   1990         soc_td2_port_common_attributes_get(unit, port, &pipe, &mmu_port, NULL));
   1991 
   1992     rval = 0;
   1993     SOC_IF_ERROR_RETURN(WRITE_HSP_SCHED_PORT_CONFIGr(unit, port, rval));
   1994     SOC_IF_ERROR_RETURN(WRITE_HSP_SCHED_L0_NODE_CONFIGr(unit, port, rval));
   1995     SOC_IF_ERROR_RETURN(WRITE_HSP_SCHED_L1_NODE_CONFIGr(unit, port, rval));
   1996     SOC_IF_ERROR_RETURN(WRITE_HSP_SCHED_L2_UC_QUEUE_CONFIGr(unit, port, rval));
   1997 
   1998     SOC_IF_ERROR_RETURN(soc_td2_hsp_sp_node_init(unit, port));
   1999 
   2000     l0_1 = 0;
   2001     l0_4 = 0;
   2002     for (l0_index = 0; l0_index < 5; l0_index++) {
   2003         SOC_IF_ERROR_RETURN(soc_td2_sched_hw_index_get(unit, port, 
   2004                                     SOC_TD2_NODE_LVL_L0, l0_index, &hw_index));
   2005         SOC_IF_ERROR_RETURN(soc_td2_cosq_set_sched_parent(unit, port,
   2006                               SOC_TD2_NODE_LVL_L0, hw_index, mmu_port));
   2007 
   2008         if (l0_index == 1) {
   2009             l0_1 = hw_index;
   2010         } else if (l0_index == 4) {
   2011             l0_4 = hw_index;
   2012         }
   2013     }
   2014 
   2015     for (l1_index = 0; l1_index < 10; l1_index++) {
   2016         SOC_IF_ERROR_RETURN(soc_td2_sched_hw_index_get(unit, port, 
   2017                                     SOC_TD2_NODE_LVL_L1, l1_index, &hw_index));
   2018 
   2019         SOC_IF_ERROR_RETURN(soc_td2_cosq_set_sched_parent(unit, port,
   2020                    SOC_TD2_NODE_LVL_L1, hw_index, (l1_index < 8) ? l0_1 : l0_4));
   2021 
   2022         SOC_IF_ERROR_RETURN(soc_td2_cosq_set_sched_mode(unit, port, 
   2023                  SOC_TD2_NODE_LVL_L1, l1_index, SOC_TD2_SCHED_MODE_WDRR, 1));
   2024     }
   2025 
   2026     pbmf = pipe ? IS_HSP_PORT_IN_YPIPEf : IS_HSP_PORT_IN_XPIPEf;
   2027     SOC_IF_ERROR_RETURN(READ_HSP_SCHED_GLOBAL_CONFIGr(unit, &rval));
   2028     fval = soc_reg_field_get(unit, HSP_SCHED_GLOBAL_CONFIGr, rval, pbmf);
   2029     hsp_port_index = mmu_port - pipe * _TD2_PORTS_PER_PIPE;
   2030     fval |= (1 << hsp_port_index);
   2031     soc_reg_field_set(unit, HSP_SCHED_GLOBAL_CONFIGr, &rval, pbmf, fval);
   2032     SOC_IF_ERROR_RETURN(WRITE_HSP_SCHED_GLOBAL_CONFIGr(unit, rval));
   2033     return SOC_E_NONE;
   2034 }
   2035 
   2036 STATIC int
   2037 soc_td2_reset_hsp_port(int unit, int port)
   2038 {
   2039     int l1_index, hw_index;
   2040 
   2041     for (l1_index = 0; l1_index < _TD2_HSP_PORT_MAX_L1; l1_index++) {
   2042         SOC_IF_ERROR_RETURN(
   2043             soc_td2_sched_hw_index_get(unit, port, SOC_TD2_NODE_LVL_L1, 
   2044                                        l1_index, &hw_index));
   2045 
   2046         SOC_IF_ERROR_RETURN(
   2047             soc_td2_cosq_set_sched_parent(
   2048                 unit, port, SOC_TD2_NODE_LVL_L1, hw_index, 
   2049                 INVALID_PARENT(unit, SOC_TD2_NODE_LVL_L1)));
   2050     }
   2051 
   2052     return SOC_E_NONE;
   2053 }
   2054 
   2055 STATIC int
   2056 soc_td2_cpu_port_lls_init(int unit, int port, int setup, int reserve,
   2057                           _soc_td2_lls_traverse_cb cb, void *cookie)
   2058 
   2059 {
   2060     int num_l0, num_l1, l0_0, l0_1, l0_2, num_nodes, w, ii, jj;
   2061     int l1_cnt[3], l2_cnt[3], nc, cmc;
   2062     _soc_td2_lls_config_t *lnc, *pnode;
   2063     int max_q = 48, l1off;
   2064 
   2065     if (_td2_cpu_port_lls_config[unit] != NULL) {
   2066         sal_free(_td2_cpu_port_lls_config[unit]);
   2067         _td2_cpu_port_lls_config[unit] = NULL;
   2068     }
   2069 
   2070     max_q = (reserve==0) ? 48 : 48 - SOC_TD2_COSQ_CPU_RESERVED_L0_NUM(unit);
   2071 
   2072     /* alloc structure to hold lls node data, init it and kick off 
   2073      * soc_td2_port_lls_init */
   2074     
   2075     l2_cnt[1] = l0_1 = NUM_CPU_ARM_COSQ(unit, SOC_ARM_CMC(unit, 0));
   2076     l2_cnt[2] = l0_2 = NUM_CPU_ARM_COSQ(unit, SOC_ARM_CMC(unit, 1));
   2077     l2_cnt[0] = l0_0 = max_q - (l0_1 + l0_2);
   2078     
   2079     if (l0_0 <= 0) {
   2080         return SOC_E_PARAM;
   2081     }
   2082 
   2083     num_l0 = 1 + (l0_1 > 0 ? 1 : 0) + (l0_2 > 0 ? 1 : 0);
   2084 
   2085     /* keep a max of 8 nodes under each l1. */
   2086     l1_cnt[0] = l1_cnt[1] = l1_cnt[2] = 0;
   2087 
   2088     l1_cnt[0] = (l0_0 + 7)/8;
   2089     l1_cnt[1] = (l0_1 + 7)/8;
   2090     l1_cnt[2] = (l0_2 + 7)/8;
   2091 
   2092     num_l1  = l1_cnt[0] + l1_cnt[1] + l1_cnt[2];
   2093 
   2094     num_nodes = 1 /* root */ + num_l0 + num_l1 + 1 /* null last node */;
   2095 
   2096     for (cmc = 0, ii = 0; cmc < 3; cmc++) {
   2097         SHR_BITCLR_RANGE(CPU_ARM_QUEUE_BITMAP(unit, cmc), 0, 48);
   2098         SHR_BITCLR_RANGE(CPU_ARM_RSVD_QUEUE_BITMAP(unit, cmc), 0, 48);
   2099         for (jj = 0; jj < l2_cnt[cmc]; jj++, ii++) {
   2100             SHR_BITSET(CPU_ARM_QUEUE_BITMAP(unit, cmc), ii);
   2101         }
   2102         NUM_CPU_ARM_COSQ(unit, cmc) = l2_cnt[cmc];
   2103     }
   2104 
   2105     if (SOC_IS_TD2P_TT2P(unit)) {
   2106         /* TBD COSQ. The following should be chaneged after full solution for new queues */
   2107         /* CPU  is L0.0 - bit 58 */
   2108         /* ARM0 is L0.1 - bit 59 */
   2109         /* ARM1 is L0.2 - bit 60 */
   2110         SHR_BITSET(CPU_ARM_RSVD_QUEUE_BITMAP(unit, 0), 58);
   2111         if (l2_cnt[1]) {
   2112             SHR_BITSET(CPU_ARM_RSVD_QUEUE_BITMAP(unit, 1), 59);
   2113         }
   2114         if (l2_cnt[2]) {
   2115             SHR_BITSET(CPU_ARM_RSVD_QUEUE_BITMAP(unit, 2), 60);
   2116         }
   2117     } else {
   2118         for (ii = max_q; ii < 48; ii++) {
   2119             cmc = ii - max_q;
   2120             if (l1_cnt[cmc] > 0) {
   2121                 SHR_BITSET(CPU_ARM_RSVD_QUEUE_BITMAP(unit, cmc), ii);
   2122             }
   2123         }
   2124     }
   2125 
   2126     lnc = sal_alloc(sizeof(_soc_td2_lls_config_t)*num_nodes, "CPU LLS config");
   2127     if (lnc == NULL) {
   2128         /* No rollback needed */
   2129         return SOC_E_MEMORY;
   2130     }
   2131 
   2132     /* init root */
   2133     pnode = lnc;
   2134     pnode->level = SOC_TD2_NODE_LVL_ROOT;
   2135     pnode->node_id = 0;
   2136     pnode->sched_mode = SOC_TD2_SCHED_MODE_WRR;
   2137     pnode->num_children = num_l0;
   2138     pnode->uc_mc_map = 0;
   2139     for (w = 0; w < 48; w++) {
   2140         pnode->weights[w] = 1;
   2141     }
   2142     
   2143     pnode++;
   2144     l1off = 0;
   2145 
   2146     for (ii = 0; ii < num_l0; ii++) {
   2147         pnode->level = SOC_TD2_NODE_LVL_L0;
   2148         pnode->node_id = ii;
   2149         pnode->num_children = l1_cnt[ii];
   2150         pnode->sched_mode = SOC_TD2_SCHED_MODE_WRR;
   2151         pnode->uc_mc_map = 0;
   2152         for (w = 0; w < 48; w++) {
   2153             pnode->weights[w] = 1;
   2154         }
   2155         pnode++;
   2156 
   2157         for (nc = 0, jj = 0; jj < l1_cnt[ii]; jj++) {
   2158             pnode->level = SOC_TD2_NODE_LVL_L1;
   2159             pnode->node_id = l1off++;
   2160 
   2161             if ((l2_cnt[ii] - nc) >= 8) {
   2162                 pnode->num_children = 8;
   2163             } else {
   2164                 pnode->num_children = l2_cnt[ii] - nc;
   2165             }
   2166 
   2167             nc += pnode->num_children;
   2168 
   2169             pnode->sched_mode = SOC_TD2_SCHED_MODE_WRR;
   2170             pnode->uc_mc_map = 0;
   2171             for (w = 0; w < 48; w++) {
   2172                 pnode->weights[w] = 1;
   2173             }
   2174             pnode++;
   2175         }
   2176     }
   2177 
   2178     /* null node */
   2179     pnode->level = -1;
   2180     pnode->node_id = -1;
   2181     pnode->num_children = 0;
   2182     pnode->uc_mc_map = 0;
   2183 
   2184     _td2_cpu_port_lls_config[unit] = lnc;
   2185 
   2186     SOC_IF_ERROR_RETURN(soc_td2_port_lls_init(unit, port, 
   2187                                               _td2_cpu_port_lls_config[unit], setup,
   2188                                               cb, cookie));
   2189     return 0;
   2190 }
   2191 
   2192 int soc_td2_lls_reset(int unit)
   2193 {
   2194     int port, lvl, i;
   2195     uint32 clrmap = 0, pipe;
   2196     soc_info_t *si;
   2197     int phy_port, mmu_port, index;
   2198     soc_mem_t mem;
   2199     uint32 entry[SOC_MAX_MEM_WORDS];
   2200     uint32 *bmap = NULL;
   2201     int alloc_size;
   2202 
   2203     si = &SOC_INFO(unit);
   2204 
   2205     PBMP_ALL_ITER(unit, port) {
   2206         pipe = SOC_TD2_PORT_PIPE(unit, port);
   2207         for (lvl = SOC_TD2_NODE_LVL_L0; lvl <= SOC_TD2_NODE_LVL_L2; lvl++) {
   2208             mem = _SOC_TD2_NODE_PARENT_MEM(unit, port, lvl);
   2209             /* coverity[negative_returns : FALSE] */
   2210             alloc_size = SHR_BITALLOCSIZE(soc_mem_index_count(unit, mem));
   2211             if (lvl == SOC_TD2_NODE_LVL_L0) {
   2212                 if (SOC_CONTROL(unit)->port_lls_l0_bmap[port] == NULL) {
   2213                     SOC_CONTROL(unit)->port_lls_l0_bmap[port] = 
   2214                                         sal_alloc(alloc_size, "LLS_L0_BMAP");
   2215                 }
   2216                 bmap = SOC_CONTROL(unit)->port_lls_l0_bmap[port];
   2217             } else if (lvl == SOC_TD2_NODE_LVL_L1) {
   2218                 if (SOC_CONTROL(unit)->port_lls_l1_bmap[port] == NULL) {
   2219                     SOC_CONTROL(unit)->port_lls_l1_bmap[port] = 
   2220                                         sal_alloc(alloc_size, "LLS_L1_BMAP");
   2221                 }
   2222                 bmap = SOC_CONTROL(unit)->port_lls_l1_bmap[port];
   2223             } else if (lvl == SOC_TD2_NODE_LVL_L2) {
   2224                 if (SOC_CONTROL(unit)->port_lls_l2_bmap[port] == NULL) {
   2225                     SOC_CONTROL(unit)->port_lls_l2_bmap[port] = 
   2226                                         sal_alloc(alloc_size, "LLS_L2_BMAP");
   2227                 }
   2228                 bmap = SOC_CONTROL(unit)->port_lls_l2_bmap[port];
   2229             }
   2230         
   2231             sal_memset(bmap, 0, alloc_size);
   2232             
   2233             if ((clrmap & (1 << (pipe * SOC_TD2_NODE_LVL_MAX + lvl))) == 0) {
   2234                 sal_memset(entry, 0, sizeof(uint32)*SOC_MAX_MEM_WORDS);
   2235                 soc_mem_field32_set(unit, mem, entry, C_PARENTf, INVALID_PARENT(unit, lvl));
   2236 
   2237                 for (i = 0; i <= soc_mem_index_max(unit, mem); i++) {
   2238                     SOC_IF_ERROR_RETURN
   2239                         (soc_mem_write(unit, mem, MEM_BLOCK_ALL, i, &entry));
   2240                 }
   2241                 clrmap |= (1 << (pipe * SOC_TD2_NODE_LVL_MAX + lvl));
   2242             }
   2243         }
   2244 
   2245         if (SOC_PBMP_MEMBER(si->eq_pbm, port)) { /* VBS (HSP) port */
   2246             phy_port = si->port_l2p_mapping[port];
   2247             mmu_port = si->port_p2m_mapping[phy_port];
   2248             for (index = 0; index < 5; index++) {
   2249                 SHR_BITSET(SOC_CONTROL(unit)->port_lls_l0_bmap[port],
   2250                            (mmu_port & 0x3f) * 5 + index);
   2251             }
   2252             for (index = 0; index < 10; index++) {
   2253                 SHR_BITSET(SOC_CONTROL(unit)->port_lls_l1_bmap[port],
   2254                            (mmu_port & 0x3f) * 10 + index);
   2255             }
   2256             for (index = 0; index < 10; index++) {
   2257                 SHR_BITSET(SOC_CONTROL(unit)->port_lls_l2_bmap[port],
   2258                            (mmu_port & 0x3f) * 10 + index);
   2259             }
   2260         }
   2261     }
   2262 
   2263     return 0;
   2264 }
   2265 
   2266 int soc_td2_lls_reset_port(int unit, int port)
   2267 {
   2268     int lvl;
   2269     soc_mem_t mem;
   2270     uint32 *bmap = NULL;
   2271     int alloc_size;
   2272 
   2273     for (lvl = SOC_TD2_NODE_LVL_L0; lvl <= SOC_TD2_NODE_LVL_L2; lvl++) {
   2274         mem = _SOC_TD2_NODE_PARENT_MEM(unit, port, lvl);
   2275         alloc_size = SHR_BITALLOCSIZE(soc_mem_index_count(unit, mem));
   2276         if (lvl == SOC_TD2_NODE_LVL_L0) {
   2277             if (SOC_CONTROL(unit)->port_lls_l0_bmap[port] == NULL) {
   2278                 SOC_CONTROL(unit)->port_lls_l0_bmap[port] = 
   2279                                     sal_alloc(alloc_size, "LLS_L0_BMAP");
   2280             }
   2281             bmap = SOC_CONTROL(unit)->port_lls_l0_bmap[port];
   2282         } else if (lvl == SOC_TD2_NODE_LVL_L1) {
   2283             if (SOC_CONTROL(unit)->port_lls_l1_bmap[port] == NULL) {
   2284                 SOC_CONTROL(unit)->port_lls_l1_bmap[port] = 
   2285                                     sal_alloc(alloc_size, "LLS_L1_BMAP");
   2286             }
   2287             bmap = SOC_CONTROL(unit)->port_lls_l1_bmap[port];
   2288         } else if (lvl == SOC_TD2_NODE_LVL_L2) {
   2289             if (SOC_CONTROL(unit)->port_lls_l2_bmap[port] == NULL) {
   2290                 SOC_CONTROL(unit)->port_lls_l2_bmap[port] = 
   2291                                     sal_alloc(alloc_size, "LLS_L2_BMAP");
   2292             }
   2293             bmap = SOC_CONTROL(unit)->port_lls_l2_bmap[port];
   2294         }
   2295     
   2296         sal_memset(bmap, 0, alloc_size);
   2297     }
   2298 
   2299     return 0;
   2300 }
   2301 
   2302 /*
   2303  * Function:
   2304  *     _soc_td2plus_lls_init
   2305  * Purpose:
   2306  *     This function initialises the structure _td2p_dyn_sched_unit_data, which is
   2307  *     used later to allocate the register available from  the set of 
   2308  *     SP_WERR_DYN_CHANGEnA/nB/nC (n=0,1,2,3) to the port and  to keep track 
   2309  *     of the used registers from the set for the port 
   2310  * Parameters:
   2311  *     unit       - (IN) unit number
   2312  * Returns:
   2313  *     SOC_E_XXX
   2314  */
   2315 STATIC int _soc_td2plus_lls_init(int unit)
   2316 {
   2317     _soc_td2p_port_dyn_sched_t *pcb = NULL;
   2318     int i;
   2319     
   2320     if (soc_feature(unit, soc_feature_vector_based_spri)) {
   2321         pcb = &_td2p_dyn_sched_unit_data[unit];
   2322         
   2323         if (pcb->_soc_td2plus_init_done[unit] == 1) {
   2324             return SOC_E_NONE;
   2325         }
   2326 
   2327         pcb->lock = sal_mutex_create("td2plus_dyn_lock");
   2328         for (i = 0; i < _SOC_TD2PLUS_DYN_REGISTER_SET; i++) {
   2329             pcb->port[i] = -1;
   2330         }
   2331         pcb->_soc_td2plus_init_done[unit] = 1;
   2332     }
   2333 
   2334     return SOC_E_NONE;
   2335 }
   2336 
   2337 int soc_td2_lls_init(int unit)
   2338 {
   2339     int port, rv = SOC_E_NONE, reserve_queues, pipe;
   2340     soc_trident2_sched_type_t sched_type;
   2341     uint32 entry[SOC_MAX_MEM_WORDS];
   2342     uint32 rval;
   2343     soc_reg_t reg;
   2344     _soc_td2p_lls_op_mode_t op_mode;
   2345 
   2346     static const soc_reg_t llfc_cfgr[] = {
   2347         ES_PIPE0_LLS_FC_CONFIGr, ES_PIPE1_LLS_FC_CONFIGr };
   2348 
   2349     reserve_queues = soc_feature(unit, soc_feature_cmic_reserved_queues);
   2350 
   2351     SOC_IF_ERROR_RETURN(_soc_td2plus_lls_init(unit));
   2352 
   2353     /* do dummy read from L0 parent mem per TD2-3313. */
   2354     SOC_IF_ERROR_RETURN(soc_mem_read(unit, ES_PIPE0_LLS_L0_PARENTm, MEM_BLOCK_ALL, 0, &entry));
   2355     SOC_IF_ERROR_RETURN(soc_mem_read(unit, ES_PIPE1_LLS_L0_PARENTm, MEM_BLOCK_ALL, 0, &entry));
   2356 
   2357     SOC_IF_ERROR_RETURN(soc_td2_init_invalid_pointers(unit));
   2358 
   2359     SOC_IF_ERROR_RETURN(WRITE_HSP_SCHED_GLOBAL_CONFIGr(unit, 0));
   2360 
   2361     SOC_IF_ERROR_RETURN(soc_td2_lls_reset(unit));
   2362 
   2363     PBMP_ALL_ITER(unit, port) {
   2364         sched_type = _soc_trident2_port_sched_type_get(unit, port);
   2365 
   2366         if (sched_type == SOC_TD2_SCHED_HSP) {
   2367             rv = soc_td2_setup_hsp_port(unit, port);
   2368             if (soc_td2_is_skip_default_lls_creation(unit)) {
   2369                 SOC_IF_ERROR_RETURN(
   2370                     soc_td2_port_mmu_tx_enable_set(unit, port, 1));
   2371             }
   2372         } else if (IS_CPU_PORT(unit, port)) {
   2373             op_mode = _SOC_TD2_LLS_OP_SETUP;
   2374             rv = soc_td2_cpu_port_lls_init(unit, port, op_mode, reserve_queues, NULL, NULL);
   2375         } else if (IS_LB_PORT(unit, port)) {
   2376             if (!soc_td2_is_skip_default_lls_creation(unit)) {
   2377                 op_mode = _SOC_TD2_LLS_OP_SETUP;
   2378                 rv = soc_td2_port_lls_init(unit, port, _td2_lb_port_lls_config, op_mode, NULL, NULL);
   2379             }
   2380         } else {
   2381             if (!soc_td2_is_skip_default_lls_creation(unit)) {
   2382                 op_mode = _SOC_TD2_LLS_OP_SETUP;
   2383                 rv = soc_td2_port_lls_init(unit, port, _td2_port_lls_config, op_mode, NULL, NULL);
   2384             } else {
   2385                 SOC_IF_ERROR_RETURN(
   2386                     soc_td2_port_mmu_tx_enable_set(unit, port, 0));
   2387                 SOC_IF_ERROR_RETURN(
   2388                     soc_td2_mmu_rx_enable_set(unit, port, 0));
   2389             }
   2390         }
   2391         if (rv) {
   2392             return SOC_E_INTERNAL;
   2393         }
   2394     }
   2395 
   2396     for (pipe = _TD2_XPIPE; pipe <= _TD2_YPIPE; pipe++) {
   2397         reg = llfc_cfgr[pipe];
   2398         SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
   2399         soc_reg_field_set(unit, reg, &rval, FC_CFG_DISABLE_XOFFf, 0);
   2400         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval));
   2401     }
   2402 
   2403     return SOC_E_NONE;
   2404 }
   2405 
   2406 int soc_td2_lls_port_uninit(int unit, soc_port_t port)
   2407 {
   2408     soc_trident2_sched_type_t sched_type;
   2409     int rv = SOC_E_NONE;
   2410     _soc_td2p_lls_op_mode_t op_mode;
   2411 
   2412     sched_type = _soc_trident2_port_sched_type_get(unit, port);
   2413 
   2414     if (sched_type == SOC_TD2_SCHED_LLS) {
   2415         if (IS_CPU_PORT(unit, port)) {
   2416             op_mode = _SOC_TD2_LLS_OP_TEAR;
   2417             rv = soc_td2_cpu_port_lls_init(unit, port, op_mode, 0, NULL, NULL);
   2418         } else if (IS_LB_PORT(unit, port)) {
   2419             if (!soc_td2_is_skip_default_lls_creation(unit)) {
   2420                 op_mode = _SOC_TD2_LLS_OP_TEAR;
   2421                 rv = soc_td2_port_lls_init(unit, port, _td2_lb_port_lls_config, op_mode, NULL, NULL);
   2422             }
   2423         } else {
   2424             if (!soc_td2_is_skip_default_lls_creation(unit)) {
   2425                 op_mode = _SOC_TD2_LLS_OP_TEAR;
   2426                 rv = soc_td2_port_lls_init(unit, port, _td2_port_lls_config, op_mode, NULL, NULL);
   2427             }
   2428         }
   2429     } else {
   2430         rv = soc_td2_reset_hsp_port(unit, port);
   2431     }
   2432     return rv;
   2433 }
   2434 
   2435 /*
   2436  * Function:
   2437  *     soc_td2_port_lls_traverse
   2438  * Purpose:
   2439  *     This function initialises the structure _td2p_dyn_sched_unit_data, which is
   2440  *     used later to allocate the register available from  the set of 
   2441  *     SP_WERR_DYN_CHANGEnA/nB/nC (n=0,1,2,3) to the port and  to keep track 
   2442  *     of the used registers from the set for the port 
   2443  * Parameters:
   2444  *     unit       - (IN) unit number
   2445  *     port       - (IN) local port number
   2446  *     cb         - (IN) callback function / function pointer
   2447  *     cookie     - (OUT) previous state of LLS 
   2448  * Returns:
   2449  *     SOC_E_XXX
   2450  */
   2451 int soc_td2_port_lls_traverse(int unit, soc_port_t port, 
   2452                               _soc_td2_lls_traverse_cb cb, void *cookie)
   2453 {
   2454     int rv = SOC_E_INTERNAL;
   2455     _soc_td2p_lls_op_mode_t op_mode;
   2456  
   2457     if (_SOC_TD2_IS_HSP_PORT(unit, port)) {
   2458         rv = SOC_E_UNAVAIL;
   2459     } else if (IS_CPU_PORT(unit, port)) {
   2460         if (soc_feature(unit, soc_feature_cmic_reserved_queues)) {
   2461             op_mode = _SOC_TD2_LLS_OP_TRAVERSE;
   2462             rv = soc_td2_cpu_port_lls_init(unit, port, op_mode,
   2463                                            1, cb, cookie);
   2464         } else {
   2465             op_mode = _SOC_TD2_LLS_OP_TRAVERSE;
   2466             rv = soc_td2_cpu_port_lls_init(unit, port, op_mode,
   2467                                            0, cb, cookie);
   2468         }
   2469     } else {
   2470         op_mode = _SOC_TD2_LLS_OP_TRAVERSE;
   2471         rv = soc_td2_port_lls_init(unit, port, _td2_port_lls_config, 
   2472                                     op_mode, cb, cookie);
   2473     }
   2474      return rv;
   2475 }
   2476 
   2477 int
   2478 soc_td2_sched_hw_index_get(int unit, int port, int lvl, int offset, 
   2479                             int *hw_index)
   2480 {
   2481     int rv;
   2482 
   2483     rv = _soc_td2_alloc_sched(unit, port, lvl, offset, hw_index);
   2484 
   2485     LOG_INFO(BSL_LS_SOC_COSQ,
   2486              (BSL_META_U(unit,
   2487                          "Alloced : port=%d lvl=%d ofst=%d Index=%d\n"),
   2488               port, lvl, offset, *hw_index));
   2489     return rv;
   2490 }
   2491 
   2492 int
   2493 soc_td2_qcn_counter_hw_index_get(int unit, soc_port_t port,
   2494                                  int index, int *qindex)
   2495 {
   2496     soc_mem_t mem;
   2497     mmu_qcn_enable_entry_t entry;
   2498     int resolved_index = -1;    
   2499     
   2500     if (qindex == NULL) {
   2501         return SOC_E_PARAM;
   2502     }
   2503 
   2504     mem = SOC_TD2_PMEM(unit, port, MMU_QCN_ENABLE_0m, MMU_QCN_ENABLE_1m);    
   2505     
   2506     resolved_index = soc_td2_l2_hw_index(unit, index, 1);
   2507     SOC_IF_ERROR_RETURN
   2508         (soc_mem_read(unit, mem, MEM_BLOCK_ANY, resolved_index, &entry));
   2509     if (soc_mem_field32_get(unit, mem, &entry, CPQ_ENf)) {
   2510         *qindex = soc_mem_field32_get(unit, mem, &entry, CPQ_IDf);
   2511     } else {
   2512         *qindex = -1;
   2513     }
   2514 
   2515     return SOC_E_NONE;
   2516 }
   2517 
   2518 #define MMU_LB_PORT     116
   2519 #define MMU_CMIC_PORT   52
   2520 
   2521 int 
   2522 soc_td2_get_def_qbase(int unit, soc_port_t inport, int qtype, 
   2523                        int *pbase, int *pnumq)
   2524 {
   2525     soc_info_t *si;
   2526     int base, numq;
   2527 
   2528     si = &SOC_INFO(unit);
   2529 
   2530     if (qtype == _SOC_TD2_INDEX_STYLE_UCAST_QUEUE) {
   2531         base = si->port_uc_cosq_base[inport];
   2532         numq = si->port_num_uc_cosq[inport];
   2533     } else if (qtype == _SOC_TD2_INDEX_STYLE_MCAST_QUEUE) {
   2534         base = si->port_cosq_base[inport];
   2535         numq = si->port_num_cosq[inport];
   2536     } else {
   2537         return SOC_E_INTERNAL;
   2538     }
   2539 
   2540     if (pbase) {
   2541         *pbase = base;
   2542     }
   2543     if (pnumq) {
   2544         *pnumq = numq;
   2545     }
   2546     return SOC_E_NONE;
   2547 }
   2548 
   2549 STATIC int
   2550 _soc_td2_dump_hsp_sched_at(int unit, int port, int level, int offset, int index)
   2551 {
   2552     uint32     rval = 0;
   2553     uint32     conn_map;
   2554     uint32     l0_index, l1_index;
   2555     uint32     mc_group_mode = 0;
   2556     char       *lvl_name[] = { "Root", "L0", "L1", "UC", "MC" };
   2557     char       *sched_modes[] = {"X", "SP", "WRR", "WDRR"};
   2558     uint32     num_spri =0;
   2559     uint32     first_child =0;
   2560     uint32     first_mc_child =0;
   2561     uint32     ucmap =0;
   2562     uint32     sched_mode =0;
   2563     soc_info_t *si;
   2564     int        uc_cosq, mc_cosq;
   2565     int        uc_cosq_base, mc_cosq_base;
   2566     int        uc_hw_index, mc_hw_index;
   2567     int        hw_index;
   2568     int        wt =0;
   2569 
   2570     si = &SOC_INFO(unit);
   2571 
   2572     uc_cosq_base = si->port_uc_cosq_base[port];
   2573     mc_cosq_base = si->port_cosq_base[port];
   2574     uc_cosq = soc_td2_logical_qnum_hw_qnum(unit, port, uc_cosq_base, 1);
   2575     mc_cosq = soc_td2_logical_qnum_hw_qnum(unit, port, mc_cosq_base, 0);
   2576 
   2577     if (level != SOC_TD2_NODE_LVL_ROOT) {
   2578         return SOC_E_PARAM;
   2579     }
   2580     SOC_IF_ERROR_RETURN(READ_HSP_SCHED_PORT_CONFIGr(unit, port, &rval));
   2581     mc_group_mode = soc_reg_field_get(unit, HSP_SCHED_PORT_CONFIGr,
   2582                                       rval, MC_GROUP_MODEf);
   2583     /* Root Node */
   2584     LOG_CLI((BSL_META_U(unit,
   2585                         "  %s.%d : INDEX=%d NUM_SPRI=%d FC=%d MODE=%s Wt=%d\n"),
   2586              lvl_name[level], offset, index, num_spri, first_child,
   2587              sched_modes[sched_mode], wt));
   2588 
   2589     /* L0 Node */
   2590     for (l0_index = 0; l0_index < 5; l0_index++) {
   2591         /* print the L0 Nodes*/
   2592         level = SOC_TD2_NODE_LVL_L0;
   2593         SOC_IF_ERROR_RETURN(soc_td2_sched_hw_index_get(unit,
   2594                          port, level, l0_index, &hw_index));
   2595         soc_td2_cosq_get_sched_mode(unit, port, SOC_TD2_NODE_LVL_L0,
   2596                                      hw_index, &sched_mode, &wt);
   2597         LOG_CLI((BSL_META_U(unit,
   2598                             "  %s.%d : INDEX=%d NUM_SPRI=%d FC=%d MODE=%s Wt=%d\n"),
   2599                  lvl_name[level], l0_index, hw_index, num_spri, first_child,
   2600                  sched_modes[sched_mode], wt));
   2601 
   2602         /* read Connection map for the  L0.1, L0.2, L0.3, L0.4
   2603          * by default connection map should be set to all zeros for L0.0
   2604          */
   2605 
   2606         SOC_IF_ERROR_RETURN(READ_HSP_SCHED_L0_NODE_CONNECTION_CONFIGr(
   2607                                  unit, port, l0_index, &rval));
   2608         conn_map = soc_reg_field_get(unit,
   2609                             HSP_SCHED_L0_NODE_CONNECTION_CONFIGr,
   2610                             rval, CHILDREN_CONNECTION_MAPf);
   2611         if ((l0_index >= 1) && (l0_index <= 4)) {
   2612             for (l1_index = 0; l1_index < 8; l1_index++) {
   2613                 if (conn_map & (1U<<l1_index)) {
   2614                     if (l0_index == 4) {
   2615                         offset = l1_index + 2;
   2616                     } else {
   2617                         offset = l1_index;
   2618                     }
   2619                     /* print L1 node */
   2620                     level = SOC_TD2_NODE_LVL_L1;
   2621                     SOC_IF_ERROR_RETURN(soc_td2_sched_hw_index_get(unit,
   2622                         port, level, offset, &hw_index));
   2623                     soc_td2_cosq_get_sched_mode(unit, port, SOC_TD2_NODE_LVL_L1,
   2624                                                 hw_index, &sched_mode, &wt);
   2625                     LOG_CLI((BSL_META_U(unit,
   2626                                         "  %s.%d : INDEX=%d NUM_SP=%d FC=%d "
   2627                                         "FMC=%d UCMAP=0x%08x MODE=%s WT=%d\n"),
   2628                              lvl_name[level], offset, hw_index, num_spri,
   2629                              first_child, first_mc_child, ucmap,
   2630                              sched_modes[sched_mode], wt));
   2631 
   2632                     /* print L2 UC node attached to L1 */
   2633                     uc_hw_index = soc_td2_l2_hw_index(
   2634                                         unit, uc_cosq_base + offset, 1);
   2635                     soc_td2_cosq_get_sched_mode(unit, port,
   2636                                                     SOC_TD2_NODE_LVL_L2,
   2637                                                     uc_hw_index, &sched_mode, &wt);
   2638                     LOG_CLI((BSL_META_U(unit,
   2639                                         "    L2.uc : INDEX=%d Mode=%s WEIGHT=%d\n"),
   2640                              uc_cosq + offset, sched_modes[sched_mode], wt));
   2641 
   2642                     if (((mc_group_mode == 1) && (l0_index == 4)) ||
   2643                          (mc_group_mode == 0)) {
   2644                         /* print L2 MC node attached to L1 */
   2645                         /* MC_GROUP_MODE = 1 then  8 MC Cos queues are
   2646                          * grouped together and shared the parent (L0.0) bandwidth.
   2647                          * MC_QM and MC_SC queues are still paired with
   2648                          * UC_QM and UC_SC respectivly
   2649                          */
   2650                         mc_hw_index = soc_td2_l2_hw_index(
   2651                                             unit, mc_cosq_base + offset, 0);
   2652                         soc_td2_cosq_get_sched_mode(unit, port,
   2653                                                     SOC_TD2_NODE_LVL_L2,
   2654                                                     mc_hw_index, &sched_mode, &wt);
   2655                         LOG_CLI((BSL_META_U(unit,
   2656                                             "    L2.mc : INDEX=%d Mode=%s WEIGHT=%d\n"),
   2657                                  mc_cosq + offset, sched_modes[sched_mode], wt));
   2658                     }
   2659                 }
   2660             }
   2661         } else if (l0_index == 0) {
   2662             if (mc_group_mode) {
   2663                 offset = 0;
   2664                 for (l1_index = 0; l1_index < 8; l1_index++) {
   2665                     /* 8 MC Cos queues are grouped together and shared
   2666                      * the parent (L0.0) bandwidth.
   2667                      */
   2668                     mc_hw_index = soc_td2_l2_hw_index(unit,
   2669                                                       mc_cosq_base + offset, 0);
   2670                     soc_td2_cosq_get_sched_mode(unit, port,
   2671                                                     SOC_TD2_NODE_LVL_L2,
   2672                                                     mc_hw_index, &sched_mode, &wt);
   2673                     LOG_CLI((BSL_META_U(unit,
   2674                                         "    L2.mc : INDEX=%d Mode=%s WEIGHT=%d\n"),
   2675                              mc_cosq + offset, sched_modes[sched_mode], wt));
   2676                     offset++;
   2677                 }
   2678 
   2679             }
   2680         }
   2681     }
   2682 
   2683    return SOC_E_NONE;
   2684 }
   2685 
   2686 STATIC int
   2687 _soc_td2_child_num_get(int unit, int port, int level, int hw_index, int *count)
   2688 {
   2689     soc_mem_t mem;
   2690     int cindex, index_max, ii, child_level, num_child = 0;
   2691     uint32 entry[SOC_MAX_MEM_WORDS];
   2692 
   2693     soc_td2_get_child_type(unit, port, level, &child_level);
   2694     mem = _SOC_TD2_NODE_PARENT_MEM(unit, port, child_level);
   2695     
   2696     if (mem == INVALIDm) {
   2697         return SOC_E_INTERNAL;
   2698     }
   2699     index_max = soc_mem_index_max(unit, mem);
   2700 
   2701     for (ii = 0; ii <= index_max; ii++) {
   2702         SOC_IF_ERROR_RETURN( 
   2703                 soc_mem_read(unit, mem, MEM_BLOCK_ALL, ii, &entry));
   2704 
   2705         cindex = soc_mem_field32_get(unit, mem, entry, C_PARENTf);
   2706 
   2707         if (cindex == hw_index) {
   2708             num_child += 1;
   2709         }
   2710     }
   2711 
   2712     if (count != NULL) {
   2713         *count = num_child;
   2714     }
   2715 
   2716     return SOC_E_NONE;
   2717 }
   2718 
   2719 STATIC int 
   2720 _soc_td2_dump_sched_at(int unit, int port, int level, int offset, int hw_index)
   2721 {
   2722     int num_spri, first_child, first_mc_child, rv, cindex;
   2723     uint32 ucmap, spmap;
   2724     soc_td2_sched_mode_e sched_mode;
   2725     soc_mem_t mem;
   2726     int index_max, ii, ci, child_level, wt = 0, num_child, num_l1_children = 0;
   2727     uint32 entry[SOC_MAX_MEM_WORDS];
   2728     char *lvl_name[] = { "Root", "L0", "L1", "L2" };
   2729     char *sched_modes[] = {"X", "SP", "WRR", "WDRR"};
   2730 
   2731     if (level < SOC_TD2_NODE_LVL_L2) {
   2732         soc_td2_get_child_type(unit, port, level, &child_level);
   2733         if (hw_index == INVALID_PARENT(unit, child_level)) {
   2734             if (soc_feature(unit, soc_feature_lls_port_mema_config_match)) {
   2735                 return SOC_E_NONE;
   2736             }
   2737 
   2738             /* 
   2739              * INVALID_PARENT(L0) may be zero. 
   2740              * When this condition occurs, 
   2741              * we need to do further check instead of returning.
   2742              */
   2743             if (!((child_level == SOC_TD2_NODE_LVL_L0) &&
   2744                 (hw_index == 0))) {
   2745                 return SOC_E_NONE;
   2746             }
   2747         }
   2748     }
   2749 
   2750     /* get sched config */
   2751     SOC_IF_ERROR_RETURN(
   2752             soc_td2_cosq_get_sched_child_config(unit, port, level, hw_index, 
   2753                              &num_spri, &first_child, &first_mc_child, &ucmap,
   2754                              &spmap));
   2755     sched_mode = 0;
   2756     if (level != SOC_TD2_NODE_LVL_ROOT) {
   2757         SOC_IF_ERROR_RETURN(
   2758           soc_td2_cosq_get_sched_mode(unit, port, level, hw_index, &sched_mode, &wt));
   2759     }
   2760     
   2761     if (level == SOC_TD2_NODE_LVL_L1) {
   2762         LOG_CLI((BSL_META_U(unit,
   2763                             "  %s.%d : INDEX=%d NUM_SP=%d FC=%d "
   2764                             "FMC=%d UCMAP=0x%08x MODE=%s WT=%d\n"),
   2765                  lvl_name[level], offset, hw_index, num_spri, 
   2766                  first_child, first_mc_child, ucmap, 
   2767                  sched_modes[sched_mode], wt));
   2768     } else {
   2769         LOG_CLI((BSL_META_U(unit,
   2770                             "  %s.%d : INDEX=%d NUM_SPRI=%d FC=%d MODE=%s Wt=%d\n"),
   2771                  lvl_name[level], offset, hw_index, num_spri, first_child,
   2772                  sched_modes[sched_mode], wt));
   2773     }
   2774 
   2775     soc_td2_get_child_type(unit, port, level, &child_level);
   2776     mem = _SOC_TD2_NODE_PARENT_MEM(unit, port, child_level);
   2777     
   2778     if(mem == INVALIDm) {
   2779         return SOC_E_INTERNAL;
   2780     }
   2781     index_max = soc_mem_index_max(unit, mem);
   2782 
   2783     num_child = 0;
   2784     for (ii = 0, ci = 0; ii <= index_max; ii++) {
   2785         rv = soc_mem_read(unit, mem, MEM_BLOCK_ALL, ii, &entry);
   2786         if (rv) {
   2787             LOG_CLI((BSL_META_U(unit,
   2788                                 "Failed to read memory at index: %d\n"), ii));
   2789             break;
   2790         }
   2791         
   2792         cindex = soc_mem_field32_get(unit, mem, entry, C_PARENTf);
   2793         if (cindex == hw_index) {
   2794             if (!soc_feature(unit, soc_feature_lls_port_mema_config_match)) {
   2795                 /*
   2796                  * INVALID_PARENT(L0) may be zero.
   2797                  * When this condition occurs,
   2798                  * we should get the node`s child count to decide
   2799                  * if it is a valid node or not.
   2800                  */
   2801                 if ((cindex == 0) && (child_level == SOC_TD2_NODE_LVL_L0)) {
   2802                     _soc_td2_child_num_get(unit, port, child_level,
   2803                                                 ii, &num_l1_children);
   2804                     if (num_l1_children == 0) {
   2805                         continue;
   2806                     }
   2807                 }
   2808             }
   2809             if (child_level == SOC_TD2_NODE_LVL_L2) {
   2810                 SOC_IF_ERROR_RETURN(soc_td2_cosq_get_sched_mode(unit, port,
   2811                                     SOC_TD2_NODE_LVL_L2, ii, &sched_mode, &wt));
   2812                 LOG_CLI((BSL_META_U(unit,
   2813                                     "     L2.%s INDEX=%d Mode=%s WEIGHT=%d\n"), 
   2814                          ((ii < 1480) ? "uc" : "mc"),
   2815                          ii, sched_modes[sched_mode], wt));
   2816             } else {
   2817                 _soc_td2_dump_sched_at(unit, port, child_level, ci, ii);
   2818                 ci += 1;
   2819             }
   2820             num_child += 1;
   2821         }
   2822     }
   2823     if (num_child == 0) {
   2824         LOG_CLI((BSL_META_U(unit,
   2825                             "*** No children \n")));
   2826     }
   2827     return SOC_E_NONE;
   2828 }
   2829 
   2830 int soc_td2_dump_port_lls(int unit, int port)
   2831 {
   2832     int mmu_port, index;
   2833 
   2834     if (_soc_trident2_port_sched_type_get(unit, port) == SOC_TD2_SCHED_HSP) {
   2835         return SOC_E_NONE;
   2836     }
   2837 
   2838 
   2839     soc_td2_port_common_attributes_get(unit, port, NULL, &mmu_port, NULL);
   2840 
   2841     LOG_CLI((BSL_META_U(unit,
   2842                         "-------%s (LLS)------\n"), SOC_PORT_NAME(unit, (port))));
   2843     index = _soc_trident2_root_scheduler_index(unit, port);
   2844     LOG_INFO(BSL_LS_SOC_COSQ,
   2845             (BSL_META_U(unit, "Port:%d  mmu_port %d index %d\n"), port, mmu_port, index));
   2846     _soc_td2_dump_sched_at(unit, port, SOC_TD2_NODE_LVL_ROOT, 0, index);
   2847     return SOC_E_NONE;
   2848 }
   2849 int soc_td2_dump_port_hsp(int unit, int port)
   2850 {
   2851     int mmu_port, index;
   2852 
   2853     if (_soc_trident2_port_sched_type_get(unit, port) == SOC_TD2_SCHED_LLS) {
   2854         return SOC_E_NONE;
   2855     }
   2856 
   2857     soc_td2_port_common_attributes_get(unit, port, NULL, &mmu_port, NULL);
   2858 
   2859     LOG_CLI((BSL_META_U(unit,
   2860                         "-------%s (HSP)------\n"), SOC_PORT_NAME(unit, (port))));
   2861     index = _soc_trident2_root_scheduler_index(unit, port);
   2862     _soc_td2_dump_hsp_sched_at(unit, port, SOC_TD2_NODE_LVL_ROOT, 0, index);
   2863     return SOC_E_NONE;
   2864 }
   2865 int soc_td2_logical_qnum_hw_qnum(int unit, int port, int lqnum, int uc)
   2866 {
   2867     if (uc) {
   2868 	if (lqnum >= 1480) {
   2869 	    return (lqnum - 1480) + 2048;
   2870 	} else {
   2871 	    return lqnum;
   2872 	}
   2873     } else {
   2874 	if (lqnum >= 568) {
   2875 	    return (lqnum - 568) + 3528;
   2876 	} else {
   2877 	    return lqnum + 1480;
   2878 	}
   2879     }
   2880     return -1;
   2881 }
   2882 
   2883 int soc_td2_mmu_get_shared_size(int unit, int *shared_size)
   2884 {
   2885     uint32 entry0[SOC_MAX_MEM_WORDS];
   2886 
   2887     sal_memset(entry0, 0, sizeof(mmu_thdu_xpipe_config_queue_entry_t));
   2888     SOC_IF_ERROR_RETURN
   2889         (soc_mem_read(unit, MMU_THDU_XPIPE_CONFIG_QUEUEm, MEM_BLOCK_ALL, 0, entry0));
   2890     *shared_size = soc_mem_field32_get(unit, MMU_THDU_XPIPE_CONFIG_QUEUEm, entry0, Q_SHARED_LIMIT_CELLf);
   2891     return 1;
   2892 }
   2893 
   2894 int
   2895 soc_td2_mmu_config_res_limits_update(int unit,uint32 spid,
   2896                                      uint32 shared_size, int flags)
   2897 {
   2898     return soc_td2_mmu_config_shared_buf_recalc(unit, spid, shared_size, flags);
   2899 }
   2900 
   2901 void
   2902 soc_trident2_fc_map_shadow_free(int unit)
   2903 {
   2904     int mem_idx;
   2905     soc_td2_fc_map_shadow_memory_t * shadow_info;
   2906     soc_td2_fc_map_shadow_t* shadow_ctrl = &soc_td2_fc_map_shadow[unit];
   2907     
   2908     if (shadow_ctrl->shadow_array != NULL) {
   2909         for (mem_idx = 0; mem_idx < shadow_ctrl->mem_count; mem_idx++){
   2910             shadow_info = &(shadow_ctrl->shadow_array[mem_idx]);
   2911             if (shadow_info->mem_shadow != NULL){
   2912                 sal_free(shadow_info->mem_shadow);
   2913             }
   2914         }
   2915     sal_free(shadow_ctrl->shadow_array);
   2916     shadow_ctrl->shadow_array = NULL;
   2917     shadow_ctrl->mem_count = 0;
   2918     }
   2919 }
   2920 
   2921 int
   2922 soc_trident2_fc_map_shadow_create(int unit)
   2923 {
   2924 	  int mem_idx, alloc_size, num_entries, entry_size;
   2925 	  soc_td2_fc_map_shadow_memory_t* shadow_info = NULL;
   2926 	  uint32* shadow = NULL;
   2927     
   2928     if (soc_td2_fc_map_shadow[unit].shadow_array == NULL) {
   2929         alloc_size = sizeof(soc_td2_fc_map_shadow_memory_t) * 
   2930                      COUNTOF(fc_map_mems);
   2931         shadow_info = sal_alloc(alloc_size, "fc map shadow control");
   2932         if (shadow_info == NULL) {
   2933             return SOC_E_MEMORY;
   2934         }
   2935         
   2936         sal_memset(shadow_info, 0, alloc_size);
   2937         soc_td2_fc_map_shadow[unit].shadow_array = shadow_info;
   2938     
   2939         for (mem_idx = 0; mem_idx < COUNTOF(fc_map_mems); mem_idx++) {
   2940             num_entries = soc_mem_index_count(unit, fc_map_mems[mem_idx]);
   2941             entry_size = soc_mem_entry_words(unit, fc_map_mems[mem_idx]);
   2942             alloc_size = entry_size * num_entries * sizeof(uint32);
   2943             shadow = sal_alloc(alloc_size, "fc map shadow tbl");
   2944             if (shadow == NULL) {
   2945                 soc_trident2_fc_map_shadow_free(unit);
   2946                 return SOC_E_MEMORY;
   2947             }
   2948             sal_memset(shadow, 0, alloc_size);
   2949             soc_td2_fc_map_shadow[unit].shadow_array[mem_idx].mem_shadow = shadow;
   2950             soc_td2_fc_map_shadow[unit].shadow_array[mem_idx].mem = fc_map_mems[mem_idx];
   2951             soc_td2_fc_map_shadow[unit].mem_count++;
   2952         }
   2953     }
   2954     return SOC_E_NONE; 
   2955 }
   2956 
   2957 int
   2958 soc_trident2_fc_map_shadow_entry_get (int unit, soc_mem_t mem, int index, 
   2959                                       void* entry_data)
   2960 {
   2961     int mem_idx, entry_words;
   2962     uint32 * shadow = NULL;
   2963     
   2964     switch(mem){
   2965         case MMU_INTFI_XPIPE_FC_MAP_TBL0m:
   2966             mem_idx = 0;
   2967             break;
   2968         case MMU_INTFI_XPIPE_FC_MAP_TBL1m:
   2969             mem_idx = 1;
   2970             break;
   2971         case MMU_INTFI_YPIPE_FC_MAP_TBL0m:
   2972             mem_idx = 2;
   2973             break;
   2974         case MMU_INTFI_YPIPE_FC_MAP_TBL1m:
   2975             mem_idx = 3;
   2976             break;
   2977         default:
   2978             return SOC_E_NOT_FOUND;
   2979         
   2980     }
   2981     
   2982     shadow = soc_td2_fc_map_shadow[unit].shadow_array[mem_idx].mem_shadow;
   2983     entry_words = soc_mem_entry_words(unit, mem);
   2984     sal_memcpy(entry_data, shadow + index * entry_words, 
   2985                entry_words * sizeof(uint32));
   2986     return SOC_E_NONE;
   2987 }
   2988 
   2989 int
   2990 soc_trident2_fc_map_shadow_entry_set (int unit, soc_mem_t mem, int index, 
   2991                                       void* entry_data)
   2992 {
   2993     int mem_idx, entry_words;
   2994     uint32 * shadow = NULL;
   2995     
   2996     switch(mem){
   2997         case MMU_INTFI_XPIPE_FC_MAP_TBL0m:
   2998             mem_idx = 0;
   2999             break;
   3000         case MMU_INTFI_XPIPE_FC_MAP_TBL1m:
   3001             mem_idx = 1;
   3002             break;
   3003         case MMU_INTFI_YPIPE_FC_MAP_TBL0m:
   3004             mem_idx = 2;
   3005             break;
   3006         case MMU_INTFI_YPIPE_FC_MAP_TBL1m:
   3007             mem_idx = 3;
   3008             break;
   3009         default:
   3010             return SOC_E_NOT_FOUND;
   3011         
   3012     }
   3013     shadow = soc_td2_fc_map_shadow[unit].shadow_array[mem_idx].mem_shadow;
   3014     entry_words = soc_mem_entry_words(unit, mem);
   3015     sal_memcpy(shadow + index * entry_words, entry_data, 
   3016                entry_words * sizeof(uint32));
   3017     return SOC_E_NONE;
   3018 }
   3019 
   3020 int 
   3021 soc_trident2_fc_map_shadow_clear (int unit, soc_mem_t mem)
   3022 {
   3023     uint32 * shadow = NULL;
   3024     int entry_words, tbl_size, mem_idx, num_entries;
   3025     switch(mem){
   3026         case MMU_INTFI_XPIPE_FC_MAP_TBL0m:
   3027             mem_idx = 0;
   3028             break;
   3029         case MMU_INTFI_XPIPE_FC_MAP_TBL1m:
   3030             mem_idx = 1;
   3031             break;
   3032         case MMU_INTFI_YPIPE_FC_MAP_TBL0m:
   3033             mem_idx = 2;
   3034             break;
   3035         case MMU_INTFI_YPIPE_FC_MAP_TBL1m:
   3036             mem_idx = 3;
   3037             break;
   3038         default:
   3039             return SOC_E_NOT_FOUND;
   3040     }
   3041     entry_words = soc_mem_entry_words(unit, mem);
   3042     shadow = soc_td2_fc_map_shadow[unit].shadow_array[mem_idx].mem_shadow;
   3043     num_entries = soc_mem_index_count(unit, fc_map_mems[mem_idx]);
   3044     tbl_size = entry_words * num_entries;
   3045     if (shadow != NULL) {
   3046         sal_memset(shadow, 0, tbl_size * sizeof(uint32));
   3047     }
   3048     return SOC_E_NONE;
   3049 }
   3050 #ifdef BCM_WARM_BOOT_SUPPORT
   3051 int
   3052 soc_trident2_fc_map_shadow_size_get (int unit, uint32 * size)
   3053 {
   3054     int alloc_size = 0, mem_idx, num_entries, entry_size;
   3055     for (mem_idx = 0; mem_idx < COUNTOF(fc_map_mems); mem_idx++) {
   3056         num_entries = soc_mem_index_count(unit, fc_map_mems[mem_idx]);
   3057         entry_size = soc_mem_entry_words(unit, fc_map_mems[mem_idx]);
   3058         alloc_size += entry_size * num_entries * sizeof(uint32);
   3059     }
   3060     *size = alloc_size;
   3061     return SOC_E_NONE;
   3062 }
   3063 
   3064 int
   3065 soc_trident2_fc_map_shadow_sync (int unit, uint32 **sync_addr)
   3066 {
   3067     int mem_idx, num_entries, tbl_size, entry_size;
   3068 
   3069     for (mem_idx = 0; mem_idx < COUNTOF(fc_map_mems); mem_idx++) {
   3070         num_entries = soc_mem_index_count(unit, fc_map_mems[mem_idx]);
   3071         entry_size = soc_mem_entry_words(unit, fc_map_mems[mem_idx]);
   3072         tbl_size = entry_size * num_entries;
   3073         sal_memcpy(*sync_addr, soc_td2_fc_map_shadow[unit].shadow_array[mem_idx].mem_shadow, 
   3074                    tbl_size * sizeof(uint32));
   3075         *sync_addr += tbl_size;
   3076     }
   3077     return SOC_E_NONE;
   3078 }
   3079 
   3080 int
   3081 soc_trident2_fc_map_shadow_load (int unit, uint32 **load_addr)
   3082 {
   3083     int blk, mem_idx, num_entries;
   3084     int tbl_size, entry_size, vmap_size;
   3085     uint32 *cache;
   3086     uint32 *shadow;
   3087     uint8 *vmap;
   3088     int index_min;
   3089     soc_mem_t mem;
   3090     
   3091     for (mem_idx = 0; mem_idx < COUNTOF(fc_map_mems); mem_idx++) {
   3092         mem = fc_map_mems[mem_idx];
   3093         num_entries = soc_mem_index_count(unit, mem);
   3094         entry_size = soc_mem_entry_words(unit, mem);
   3095         index_min = soc_mem_index_min(unit, mem);
   3096         tbl_size = entry_size * num_entries;
   3097         sal_memcpy(soc_td2_fc_map_shadow[unit].shadow_array[mem_idx].mem_shadow, *load_addr,
   3098                    tbl_size * sizeof(uint32));
   3099         *load_addr += tbl_size;
   3100         /* restore memory cache */
   3101         vmap_size = (num_entries + 7) / 8;
   3102         SOC_MEM_BLOCK_ITER(unit, mem, blk) {
   3103             if (SOC_MEM_STATE(unit, mem).cache[blk] == NULL) {
   3104                 continue;
   3105             }
   3106             cache = SOC_MEM_STATE(unit, mem).cache[blk];
   3107             vmap = SOC_MEM_STATE(unit, mem).vmap[blk];
   3108             shadow = soc_td2_fc_map_shadow[unit].shadow_array[mem_idx].mem_shadow;
   3109             sal_memcpy(cache, shadow, tbl_size * sizeof(uint32));
   3110         
   3111             sal_memset(&vmap[index_min / 8], 0xff, 
   3112                       (num_entries + 7 - index_min) / 8);
   3113                 
   3114             /* Clear invalid bits at the left and right ends */
   3115             vmap[index_min / 8] &= 0xff00 >> (8 - index_min % 8);
   3116             vmap[vmap_size - 1] &= 0x00ff >> ((8 - num_entries % 8) % 8);
   3117         }
   3118     }
   3119     return SOC_E_NONE;
   3120 }
   3121 #endif
   3122 
   3123 /*
   3124 * Function:
   3125 * soc_trident2_port_sched_set
   3126 * Purpose:
   3127 * Update/Set Scheduling on the port
   3128 * Parameters:
   3129 * unit    - (IN) Unit number.
   3130 * port    - (IN) Logical SOC port number.
   3131 * Returns:
   3132 * SOC_E_XXX
   3133  */
   3134 int
   3135 soc_trident2_port_sched_set(int unit, soc_port_t port)
   3136 {
   3137     int rv = SOC_E_NONE;
   3138     soc_trident2_sched_type_t sched_type;
   3139     _soc_td2p_lls_op_mode_t op_mode;
   3140 
   3141      if (IS_CPU_PORT(unit, port) || (IS_LB_PORT(unit, port))) {
   3142          return rv;
   3143      }
   3144 
   3145     sched_type = _soc_trident2_port_sched_type_get(unit, port);
   3146 
   3147     if (sched_type == SOC_TD2_SCHED_HSP) {
   3148         rv = soc_td2_setup_hsp_port(unit, port);
   3149     } else {
   3150         if (!soc_td2_is_skip_default_lls_creation(unit)) {
   3151             op_mode = _SOC_TD2_LLS_OP_SETUP;
   3152             rv = soc_td2_port_lls_init(unit, port,
   3153                     _td2_port_lls_config, op_mode, NULL, NULL);
   3154         }
   3155     }
   3156     if (rv) {
   3157         return SOC_E_INTERNAL;
   3158     }
   3159     return SOC_E_NONE;
   3160 }
   3161 
   3162 
   3163 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   3164 /*
   3165 * Function:
   3166 *     soc_td2p_lls_reinit_invalid_pointers
   3167 * Purpose:
   3168 *     Makes a copy of _td2_invalid_ptr.
   3169 *     Reinitialize _td2_invalid_ptr
   3170 * Parameters:
   3171 *     unit          - (IN) unit number
   3172 * Returns:
   3173 * SOC_E_XXX
   3174 */
   3175 
   3176 int soc_td2p_lls_reinit_invalid_pointers(int unit)
   3177 {
   3178     int lvl;
   3179 
   3180     for (lvl = SOC_TD2_NODE_LVL_ROOT; lvl < SOC_TD2_NODE_LVL_MAX; lvl++) {
   3181         _td2p_prev_invalid_ptr[unit][lvl] = _td2_invalid_ptr[unit][lvl];
   3182     }
   3183 
   3184     SOC_IF_ERROR_RETURN(soc_td2_init_invalid_pointers(unit));
   3185 
   3186     return SOC_E_NONE;
   3187 }
   3188 
   3189 /*
   3190 * Function:
   3191 *     soc_td2p_lls_reset_flex
   3192 * Purpose:
   3193 *     updates LLS memories (_SOC_TD2_NODE_PARENT_MEM)
   3194 *     with INVALID PARENT
   3195 * Parameters:
   3196 *     unit          - (IN) unit number
   3197 * Returns:
   3198 * SOC_E_XXX
   3199 */
   3200 int soc_td2p_lls_reset_flex(int unit)
   3201 {
   3202     int lvl, i;
   3203     uint32 clrmap = 0, pipe;
   3204     soc_mem_t mem;
   3205     uint32 entry[SOC_MAX_MEM_WORDS];
   3206     int rv, cindex;
   3207 
   3208 
   3209     for (pipe = _TD2_XPIPE; pipe <= _TD2_YPIPE; pipe++) {
   3210         for (lvl = SOC_TD2_NODE_LVL_L0; lvl <= SOC_TD2_NODE_LVL_L2; lvl++) {
   3211             mem = _SOC_TD2_PIPED_NODE_PARENT_MEM(unit, pipe, lvl);
   3212 
   3213             if ((clrmap & (1 << (pipe * SOC_TD2_NODE_LVL_MAX + lvl))) == 0) {
   3214                 /* coverity[negative_returns : FALSE] */
   3215                 for (i = 0; i <= soc_mem_index_max(unit, mem); i++) {
   3216                     rv = soc_mem_read(unit, mem, MEM_BLOCK_ALL, i, &entry);
   3217                     if (rv) {
   3218                         LOG_ERROR(BSL_LS_SOC_COSQ,
   3219                                 (BSL_META_U(unit,
   3220                                             "Failed to read memory at index: %d\n"), i));
   3221                         break;
   3222                     }
   3223                     cindex = soc_mem_field32_get(unit, mem, entry, C_PARENTf);
   3224                     if ((cindex == _td2p_prev_invalid_ptr[unit][lvl]) &&
   3225                         (cindex != INVALID_PARENT(unit, lvl))) {
   3226                         sal_memset(entry, 0, sizeof(uint32)*SOC_MAX_MEM_WORDS);
   3227                         soc_mem_field32_set(unit, mem, entry, C_PARENTf, INVALID_PARENT(unit, lvl));
   3228                         SOC_IF_ERROR_RETURN
   3229                             (soc_mem_write(unit, mem, MEM_BLOCK_ALL, i, &entry));
   3230                     }
   3231                 }
   3232                 clrmap |= (1 << (pipe * SOC_TD2_NODE_LVL_MAX + lvl));
   3233             }
   3234         }
   3235     }
   3236 
   3237     return SOC_E_NONE;
   3238 }
   3239 #endif
   3240 
   3241 #endif /* BCM_TRIDENT2_SUPPORT */
   3242