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


      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  * APACHE 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 #include <soc/monterey.h>
     17 
     18 #if defined(BCM_MONTEREY_SUPPORT)
     19 
     20 #define _MN_COSQ_CPU_RESERVED_L0_BASE 261
     21 #define _MN_COSQ_CPU_RESERVED_L0_NUM  4
     22 
     23 #define _MN_HSP_PORT_MAX_COS 8
     24 #define _MN_MAX_NUM_UC_QUEUE(u) (SOC_IS_MONTEREY(unit) ? 640 :16384)
     25 
     26 typedef struct soc_monterey_shadow_memory_s {
     27     soc_mem_t mem;
     28     uint32  *mem_shadow;
     29 }soc_monterey_shadow_memory_t;
     30 
     31 typedef struct soc_monterey_shadow_s {
     32     soc_monterey_shadow_memory_t* shadow_array;
     33     int mem_count;
     34 }soc_monterey_shadow_t;
     35 typedef struct soc_monterey_obm_cb_entry_s {
     36     bcm_obm_callback_fn          cb;
     37     void                        *user_data;
     38 }soc_monterey_obm_cb_entry_t;
     39 soc_monterey_obm_cb_entry_t soc_monterey_obm_cb[SOC_MAX_NUM_DEVICES];
     40 
     41 
     42 
     43 static soc_mem_t shadow_mems[] = {
     44     MMU_INTFI_XPIPE_FC_MAP_TBL0m,
     45     MMU_INTFI_XPIPE_FC_MAP_TBL1m,
     46     /* Followings OBM classifier tables would have two instances for two pgws */
     47     IDB_OBM0_DSCP_MAP_PORT0m,
     48     IDB_OBM0_DSCP_MAP_PORT1m,
     49     IDB_OBM0_DSCP_MAP_PORT2m,
     50     IDB_OBM0_DSCP_MAP_PORT3m,
     51     IDB_OBM1_DSCP_MAP_PORT0m,
     52     IDB_OBM1_DSCP_MAP_PORT1m,
     53     IDB_OBM1_DSCP_MAP_PORT2m,
     54     IDB_OBM1_DSCP_MAP_PORT3m,
     55     IDB_OBM2_DSCP_MAP_PORT0m,
     56     IDB_OBM2_DSCP_MAP_PORT1m,
     57     IDB_OBM2_DSCP_MAP_PORT2m,
     58     IDB_OBM2_DSCP_MAP_PORT3m,
     59     IDB_OBM3_DSCP_MAP_PORT0m,
     60     IDB_OBM3_DSCP_MAP_PORT1m,
     61     IDB_OBM3_DSCP_MAP_PORT2m,
     62     IDB_OBM3_DSCP_MAP_PORT3m,
     63     IDB_OBM4_DSCP_MAP_PORT0m,
     64     IDB_OBM4_DSCP_MAP_PORT1m,
     65     IDB_OBM4_DSCP_MAP_PORT2m,
     66     IDB_OBM4_DSCP_MAP_PORT3m,
     67     IDB_OBM5_DSCP_MAP_PORT0m,
     68     IDB_OBM5_DSCP_MAP_PORT1m,
     69     IDB_OBM5_DSCP_MAP_PORT2m,
     70     IDB_OBM5_DSCP_MAP_PORT3m,
     71     IDB_OBM6_DSCP_MAP_PORT0m,
     72     IDB_OBM6_DSCP_MAP_PORT1m,
     73     IDB_OBM6_DSCP_MAP_PORT2m,
     74     IDB_OBM6_DSCP_MAP_PORT3m,
     75     IDB_OBM7_DSCP_MAP_PORT0m,
     76     IDB_OBM7_DSCP_MAP_PORT1m,
     77     IDB_OBM7_DSCP_MAP_PORT2m,
     78     IDB_OBM7_DSCP_MAP_PORT3m,
     79     IDB_OBM0_PRI_MAP_PORT0m,
     80     IDB_OBM0_PRI_MAP_PORT1m,
     81     IDB_OBM0_PRI_MAP_PORT2m,
     82     IDB_OBM0_PRI_MAP_PORT3m,
     83     IDB_OBM1_PRI_MAP_PORT0m,
     84     IDB_OBM1_PRI_MAP_PORT1m,
     85     IDB_OBM1_PRI_MAP_PORT2m,
     86     IDB_OBM1_PRI_MAP_PORT3m,
     87     IDB_OBM2_PRI_MAP_PORT0m,
     88     IDB_OBM2_PRI_MAP_PORT1m,
     89     IDB_OBM2_PRI_MAP_PORT2m,
     90     IDB_OBM2_PRI_MAP_PORT3m,
     91     IDB_OBM3_PRI_MAP_PORT0m,
     92     IDB_OBM3_PRI_MAP_PORT1m,
     93     IDB_OBM3_PRI_MAP_PORT2m,
     94     IDB_OBM3_PRI_MAP_PORT3m,
     95     IDB_OBM4_PRI_MAP_PORT0m,
     96     IDB_OBM4_PRI_MAP_PORT1m,
     97     IDB_OBM4_PRI_MAP_PORT2m,
     98     IDB_OBM4_PRI_MAP_PORT3m,
     99     IDB_OBM5_PRI_MAP_PORT0m,
    100     IDB_OBM5_PRI_MAP_PORT1m,
    101     IDB_OBM5_PRI_MAP_PORT2m,
    102     IDB_OBM5_PRI_MAP_PORT3m,
    103     IDB_OBM6_PRI_MAP_PORT0m,
    104     IDB_OBM6_PRI_MAP_PORT1m,
    105     IDB_OBM6_PRI_MAP_PORT2m,
    106     IDB_OBM6_PRI_MAP_PORT3m,
    107     IDB_OBM7_PRI_MAP_PORT0m,
    108     IDB_OBM7_PRI_MAP_PORT1m,
    109     IDB_OBM7_PRI_MAP_PORT2m,
    110     IDB_OBM7_PRI_MAP_PORT3m
    111    };
    112 
    113 static soc_monterey_shadow_t soc_monterey_shadow[SOC_MAX_NUM_DEVICES];
    114 
    115 int
    116 _soc_monterey_obm_cb_register(int unit , bcm_obm_callback_fn fn , void *fn_data)
    117 {
    118     if ( soc_monterey_obm_cb[unit].user_data != NULL) {
    119         return SOC_E_EXISTS;
    120     }
    121     soc_monterey_obm_cb[unit].cb = fn;
    122     soc_monterey_obm_cb[unit].user_data = fn_data;
    123     return SOC_E_NONE;
    124 }
    125 
    126 int
    127 _soc_monterey_obm_cb_unregister(int unit , bcm_obm_callback_fn fn , void *fn_data)
    128 {
    129     if ( soc_monterey_obm_cb[unit].user_data  == NULL ) {
    130         return SOC_E_NOT_FOUND;
    131     }
    132     soc_monterey_obm_cb[unit].cb = NULL;
    133     soc_monterey_obm_cb[unit].user_data = NULL;
    134     return SOC_E_NONE;
    135 }
    136 
    137 STATIC int
    138 soc_monterey_shadow_get_mem_idx(int unit, soc_mem_t mem, int *mem_idx)
    139 {
    140     if (mem_idx == NULL) {
    141         return SOC_E_PARAM;
    142     }
    143     switch(mem){
    144         case MMU_INTFI_XPIPE_FC_MAP_TBL0m:
    145             *mem_idx = 0;
    146             break;
    147         case MMU_INTFI_XPIPE_FC_MAP_TBL1m:
    148             *mem_idx = 1;
    149             break;
    150         case IDB_OBM0_DSCP_MAP_PORT0m:
    151             *mem_idx = 2;
    152             break;
    153         case IDB_OBM0_DSCP_MAP_PORT1m:
    154             *mem_idx = 3;
    155             break;
    156         case IDB_OBM0_DSCP_MAP_PORT2m:
    157             *mem_idx = 4;
    158             break;
    159         case IDB_OBM0_DSCP_MAP_PORT3m:
    160             *mem_idx = 5;
    161             break;
    162         case IDB_OBM1_DSCP_MAP_PORT0m:
    163             *mem_idx = 6;
    164             break;
    165         case IDB_OBM1_DSCP_MAP_PORT1m:
    166             *mem_idx = 7;
    167             break;
    168         case IDB_OBM1_DSCP_MAP_PORT2m:
    169             *mem_idx = 8;
    170             break;
    171         case IDB_OBM1_DSCP_MAP_PORT3m:
    172             *mem_idx = 9;
    173             break;
    174         case IDB_OBM2_DSCP_MAP_PORT0m:
    175             *mem_idx = 10;
    176             break;
    177         case IDB_OBM2_DSCP_MAP_PORT1m:
    178             *mem_idx = 11;
    179             break;
    180         case IDB_OBM2_DSCP_MAP_PORT2m:
    181             *mem_idx = 12;
    182             break;
    183         case IDB_OBM2_DSCP_MAP_PORT3m:
    184             *mem_idx = 13;
    185             break;
    186         case IDB_OBM3_DSCP_MAP_PORT0m:
    187             *mem_idx = 14;
    188             break;
    189         case IDB_OBM3_DSCP_MAP_PORT1m:
    190             *mem_idx = 15;
    191             break;
    192         case IDB_OBM3_DSCP_MAP_PORT2m:
    193             *mem_idx = 16;
    194             break;
    195         case IDB_OBM3_DSCP_MAP_PORT3m:
    196             *mem_idx = 17;
    197             break;
    198         case IDB_OBM4_DSCP_MAP_PORT0m:
    199             *mem_idx = 18;
    200             break;
    201         case IDB_OBM4_DSCP_MAP_PORT1m:
    202             *mem_idx = 19;
    203             break;
    204         case IDB_OBM4_DSCP_MAP_PORT2m:
    205             *mem_idx = 20;
    206             break;
    207         case IDB_OBM4_DSCP_MAP_PORT3m:
    208             *mem_idx = 21;
    209             break;
    210         case IDB_OBM5_DSCP_MAP_PORT0m:
    211             *mem_idx = 22;
    212             break;
    213         case IDB_OBM5_DSCP_MAP_PORT1m:
    214             *mem_idx = 23;
    215             break;
    216         case IDB_OBM5_DSCP_MAP_PORT2m:
    217             *mem_idx = 24;
    218             break;
    219         case IDB_OBM5_DSCP_MAP_PORT3m:
    220             *mem_idx = 25;
    221             break;
    222         case IDB_OBM6_DSCP_MAP_PORT0m:
    223             *mem_idx = 26;
    224             break;
    225         case IDB_OBM6_DSCP_MAP_PORT1m:
    226             *mem_idx = 27;
    227             break;
    228         case IDB_OBM6_DSCP_MAP_PORT2m:
    229             *mem_idx = 28;
    230             break;
    231         case IDB_OBM6_DSCP_MAP_PORT3m:
    232             *mem_idx = 29;
    233             break;
    234         case IDB_OBM7_DSCP_MAP_PORT0m:
    235             *mem_idx = 30;
    236             break;
    237         case IDB_OBM7_DSCP_MAP_PORT1m:
    238             *mem_idx = 31;
    239             break;
    240         case IDB_OBM7_DSCP_MAP_PORT2m:
    241             *mem_idx = 32;
    242             break;
    243         case IDB_OBM7_DSCP_MAP_PORT3m:
    244             *mem_idx = 33;
    245             break;
    246         case IDB_OBM0_PRI_MAP_PORT0m:
    247             *mem_idx = 34;
    248             break;
    249         case IDB_OBM0_PRI_MAP_PORT1m:
    250             *mem_idx = 35;
    251             break;
    252         case IDB_OBM0_PRI_MAP_PORT2m:
    253             *mem_idx = 36;
    254             break;
    255         case IDB_OBM0_PRI_MAP_PORT3m:
    256             *mem_idx = 37;
    257             break;
    258         case IDB_OBM1_PRI_MAP_PORT0m:
    259             *mem_idx = 38;
    260             break;
    261         case IDB_OBM1_PRI_MAP_PORT1m:
    262             *mem_idx = 39;
    263             break;
    264         case IDB_OBM1_PRI_MAP_PORT2m:
    265             *mem_idx = 40;
    266             break;
    267         case IDB_OBM1_PRI_MAP_PORT3m:
    268             *mem_idx = 41;
    269             break;
    270         case IDB_OBM2_PRI_MAP_PORT0m:
    271             *mem_idx = 42;
    272             break;
    273         case IDB_OBM2_PRI_MAP_PORT1m:
    274             *mem_idx = 43;
    275             break;
    276         case IDB_OBM2_PRI_MAP_PORT2m:
    277             *mem_idx = 44;
    278             break;
    279         case IDB_OBM2_PRI_MAP_PORT3m:
    280             *mem_idx = 45;
    281             break;
    282         case IDB_OBM3_PRI_MAP_PORT0m:
    283             *mem_idx = 46;
    284             break;
    285         case IDB_OBM3_PRI_MAP_PORT1m:
    286             *mem_idx = 47;
    287             break;
    288         case IDB_OBM3_PRI_MAP_PORT2m:
    289             *mem_idx = 48;
    290             break;
    291         case IDB_OBM3_PRI_MAP_PORT3m:
    292             *mem_idx = 49;
    293             break;
    294         case IDB_OBM4_PRI_MAP_PORT0m:
    295             *mem_idx = 50;
    296             break;
    297         case IDB_OBM4_PRI_MAP_PORT1m:
    298             *mem_idx = 51;
    299             break;
    300         case IDB_OBM4_PRI_MAP_PORT2m:
    301             *mem_idx = 52;
    302             break;
    303         case IDB_OBM4_PRI_MAP_PORT3m:
    304             *mem_idx = 53;
    305             break;
    306         case IDB_OBM5_PRI_MAP_PORT0m:
    307             *mem_idx = 54;
    308             break;
    309         case IDB_OBM5_PRI_MAP_PORT1m:
    310             *mem_idx = 55;
    311             break;
    312         case IDB_OBM5_PRI_MAP_PORT2m:
    313             *mem_idx = 56;
    314             break;
    315         case IDB_OBM5_PRI_MAP_PORT3m:
    316             *mem_idx = 57;
    317             break;
    318         case IDB_OBM6_PRI_MAP_PORT0m:
    319             *mem_idx = 58;
    320             break;
    321         case IDB_OBM6_PRI_MAP_PORT1m:
    322             *mem_idx = 59;
    323             break;
    324         case IDB_OBM6_PRI_MAP_PORT2m:
    325             *mem_idx = 60;
    326             break;
    327         case IDB_OBM6_PRI_MAP_PORT3m:
    328             *mem_idx = 61;
    329             break;
    330         case IDB_OBM7_PRI_MAP_PORT0m:
    331             *mem_idx = 62;
    332             break;
    333         case IDB_OBM7_PRI_MAP_PORT1m:
    334             *mem_idx = 63;
    335             break;
    336         case IDB_OBM7_PRI_MAP_PORT2m:
    337             *mem_idx = 64;
    338             break;
    339         case IDB_OBM7_PRI_MAP_PORT3m:
    340             *mem_idx = 65;
    341             break;
    342         default:
    343             return SOC_E_NOT_FOUND;
    344 
    345     }
    346     return SOC_E_NONE;
    347 }
    348 static int _ap_invalid_ptr[SOC_MAX_NUM_DEVICES][SOC_MONTEREY_NODE_LVL_MAX];
    349 #define INVALID_PARENT(unit, level)   _soc_monterey_invalid_parent_index((unit),(level))
    350 
    351 STATIC int
    352 soc_monterey_init_invalid_parents(int unit)
    353 {
    354 
    355     
    356     _ap_invalid_ptr[unit][SOC_MONTEREY_NODE_LVL_ROOT] = -1;
    357     _ap_invalid_ptr[unit][SOC_MONTEREY_NODE_LVL_S1] = 0x7f ;
    358     _ap_invalid_ptr[unit][SOC_MONTEREY_NODE_LVL_L0] =
    359         soc_mem_index_max(unit, LLS_S1_PARENTm);
    360     _ap_invalid_ptr[unit][SOC_MONTEREY_NODE_LVL_L1] =
    361         soc_mem_index_max(unit, LLS_L0_PARENTm);
    362     _ap_invalid_ptr[unit][SOC_MONTEREY_NODE_LVL_L2] =
    363         soc_mem_index_max(unit, LLS_L1_PARENTm);
    364     return SOC_E_NONE;
    365 }
    366 
    367 int _soc_monterey_invalid_parent_index(int unit, int level)
    368 {
    369     return _ap_invalid_ptr[unit][level];
    370 }
    371 
    372 #define _SOC_MONTEREY_DEF_SCHED_NODE_BASE(u,p,cfg,t)   \
    373             (cfg)[(t)].base_factor * (p)
    374 
    375 soc_monterey_sched_type_t
    376 _soc_monterey_port_sched_type_get(int unit, soc_port_t port)
    377 {
    378     soc_info_t *si;
    379 
    380     si = &SOC_INFO(unit);
    381     /* On Monterey everything is HSP */
    382     return (SOC_PBMP_MEMBER(si->eq_pbm, port) || SOC_IS_MONTEREY(unit)) ?
    383         SOC_MONTEREY_SCHED_HSP : SOC_MONTEREY_SCHED_LLS;
    384 }
    385 
    386 int soc_monterey_port_common_attributes_get(int unit, int port, int *pipe,
    387                                        int *mmu_port, int *phy_port)
    388 {
    389     int lphy_port, lmmu_port;
    390     soc_info_t *si;
    391 
    392     si = &SOC_INFO(unit);
    393 
    394     if (pipe) {
    395         *pipe = 0;
    396     }
    397 
    398     lphy_port = si->port_l2p_mapping[port];
    399     lmmu_port = si->port_p2m_mapping[lphy_port];
    400 
    401     if (phy_port) {
    402         *phy_port = lphy_port;
    403     }
    404 
    405     if (mmu_port) {
    406         *mmu_port = lmmu_port;
    407     }
    408     return 0;
    409 }
    410 
    411 int _soc_monterey_root_scheduler_index(int unit, int port)
    412 {
    413     int mmu_port, in_pipe;
    414 
    415     SOC_IF_ERROR_RETURN(
    416         soc_monterey_port_common_attributes_get(unit, port, &in_pipe, &mmu_port, NULL));
    417 
    418     return mmu_port;
    419 }
    420 
    421 int _soc_monterey_s1_scheduler_index(int unit, int port, int level, int hw_index)
    422 {
    423     soc_mem_t mem;
    424     int c_parent;
    425     uint32 entry[SOC_MAX_MEM_WORDS];
    426     if(level == SOC_MONTEREY_NODE_LVL_S1) {
    427         return hw_index;
    428     } else if (level >= SOC_MONTEREY_NODE_LVL_L0) {
    429         mem = _SOC_MONTEREY_NODE_PARENT_MEM(unit, port, level);
    430         SOC_IF_ERROR_RETURN
    431             (soc_mem_read(unit, mem, MEM_BLOCK_ALL, hw_index, &entry));
    432         c_parent = soc_mem_field32_get(unit, mem, entry, 
    433                 C_PARENTf);
    434         if(level == SOC_MONTEREY_NODE_LVL_L0) {
    435             return c_parent;
    436         }
    437         mem = _SOC_MONTEREY_NODE_PARENT_MEM(unit, port, level - 1);
    438         SOC_IF_ERROR_RETURN
    439             (soc_mem_read(unit, mem, MEM_BLOCK_ALL, c_parent, &entry));
    440         c_parent = soc_mem_field32_get(unit, mem, entry, 
    441                 C_PARENTf);
    442         if(level == SOC_MONTEREY_NODE_LVL_L1) {
    443             return c_parent;
    444         }
    445         mem = _SOC_MONTEREY_NODE_PARENT_MEM(unit, port, level - 2);
    446         SOC_IF_ERROR_RETURN
    447             (soc_mem_read(unit, mem, MEM_BLOCK_ALL, c_parent, &entry));
    448         c_parent = soc_mem_field32_get(unit, mem, entry, 
    449                 C_PARENTf);
    450         if(level == SOC_MONTEREY_NODE_LVL_L2) {
    451             return c_parent;
    452         }
    453 
    454     }
    455     return -1;
    456 }
    457 
    458 STATIC int
    459 _soc_monterey_flush_queue(int unit, int port, int queue_hw_index)
    460 {
    461     return 0;
    462 }
    463 
    464 soc_error_t
    465 soc_monterey_cosq_disable_hsp_sched(int unit, soc_port_t in_port)
    466 {
    467     int mmu_port;
    468     uint32 fval, rval;
    469 
    470     SOC_IF_ERROR_RETURN
    471         (soc_monterey_port_common_attributes_get(unit, in_port, NULL, &mmu_port, NULL));
    472     SOC_IF_ERROR_RETURN(READ_HSP_SCHED_GLOBAL_CONFIGr(unit, &rval));
    473     fval = soc_reg_field_get(unit, HSP_SCHED_GLOBAL_CONFIGr, rval, IS_HSP_PORT_IN_XPIPEf);
    474     fval &= ~(1 << mmu_port);
    475     soc_reg_field_set(unit, HSP_SCHED_GLOBAL_CONFIGr, &rval, IS_HSP_PORT_IN_XPIPEf, fval);
    476     SOC_IF_ERROR_RETURN(WRITE_HSP_SCHED_GLOBAL_CONFIGr(unit, rval));
    477     return SOC_E_NONE;
    478 }
    479 
    480 int
    481 soc_monterey_cosq_enable_hsp_sched(int unit, soc_port_t in_port)
    482 {
    483     int mmu_port;
    484     uint32 fval, rval;
    485 
    486     SOC_IF_ERROR_RETURN(
    487         soc_monterey_port_common_attributes_get(unit, in_port, NULL, &mmu_port, NULL));
    488     SOC_IF_ERROR_RETURN(READ_HSP_SCHED_GLOBAL_CONFIGr(unit, &rval));
    489     fval = soc_reg_field_get(unit, HSP_SCHED_GLOBAL_CONFIGr, rval, 
    490             IS_HSP_PORT_IN_XPIPEf);
    491     fval |= (1 << mmu_port);
    492     soc_reg_field_set(unit, HSP_SCHED_GLOBAL_CONFIGr, &rval, 
    493             IS_HSP_PORT_IN_XPIPEf, fval);
    494     SOC_IF_ERROR_RETURN(WRITE_HSP_SCHED_GLOBAL_CONFIGr(unit, rval));
    495     return SOC_E_NONE;
    496 }
    497 
    498 
    499 int
    500 soc_monterey_cosq_set_sched_parent(int unit, soc_port_t port,
    501                               int level, int hw_index,
    502                               int parent_hw_idx, int add)
    503 {
    504     soc_monterey_sched_type_t sched_type;
    505     uint32 entry[SOC_MAX_MEM_WORDS], fval, rval;
    506     soc_mem_t mem;
    507     int l0off, l1off;
    508     uint32 *bmap = NULL;
    509     soc_port_t mmu_port;
    510     LOG_INFO(BSL_LS_SOC_COSQ,
    511              (BSL_META_U(unit,
    512                          "Port:%d L%d : %d parent:%d\n"),
    513                port, level - 1, hw_index, parent_hw_idx));
    514 
    515     sched_type = _soc_monterey_port_sched_type_get(unit, port);
    516 
    517     if (sched_type == SOC_MONTEREY_SCHED_LLS) {
    518         mem = _SOC_MONTEREY_NODE_PARENT_MEM(unit, port, level);
    519         if (mem == INVALIDm) {
    520             return SOC_E_INTERNAL;
    521         }
    522 
    523         SOC_IF_ERROR_RETURN
    524             (soc_mem_read(unit, mem, MEM_BLOCK_ALL, hw_index, &entry));
    525 #if 0
    526         /* disconnecting the queue , flush it */
    527         if ((parent_hw_idx == INVALID_PARENT(unit, level)) && 
    528                 (level == SOC_MONTEREY_NODE_LVL_L2)) {
    529             SOC_IF_ERROR_RETURN(_soc_monterey_flush_queue(unit, port, hw_index));
    530         }
    531 #endif
    532 
    533         soc_mem_field32_set(unit, mem, entry,
    534                 level == SOC_MONTEREY_NODE_LVL_S1 ? P_PORTf : 
    535                 C_PARENTf, add ? parent_hw_idx: INVALID_PARENT(unit, level));
    536         SOC_IF_ERROR_RETURN
    537             (soc_mem_write(unit, mem, MEM_BLOCK_ALL, hw_index, &entry));
    538     } else if (sched_type == SOC_MONTEREY_SCHED_HSP) {
    539         if (level == SOC_MONTEREY_NODE_LVL_L1) {
    540             l0off = parent_hw_idx % 5;
    541             l1off = hw_index % 10;
    542             SOC_IF_ERROR_RETURN(
    543                     soc_monterey_port_common_attributes_get(unit, port, 
    544                         NULL, &mmu_port, NULL));
    545 
    546 
    547             if (parent_hw_idx == INVALID_PARENT(unit, level)) {
    548                 SOC_IF_ERROR_RETURN(_soc_monterey_flush_queue(unit,mmu_port, hw_index));
    549             }
    550             if (l0off == 4) {
    551                 SOC_IF_ERROR_RETURN(READ_HSP_SCHED_L0_NODE_4_CONNECTION_CONFIGr(
    552                         unit, port, &rval));
    553 
    554                 fval = soc_reg_field_get(unit, HSP_SCHED_L0_NODE_4_CONNECTION_CONFIGr,
    555                         rval, CHILDREN_CONNECTION_MAP_4f);
    556             } else {
    557                 
    558                 SOC_IF_ERROR_RETURN(READ_HSP_SCHED_L0_NODE_CONNECTION_CONFIGr(
    559                         unit, port, l0off - 1, &rval));
    560 
    561                 fval = soc_reg_field_get(unit, HSP_SCHED_L0_NODE_CONNECTION_CONFIGr, 
    562                        rval, CHILDREN_CONNECTION_MAPf);
    563             }
    564             if (l1off >= 8) {
    565                 l1off -= 8;
    566             }
    567 
    568             if (!add) {
    569                 fval &= ~(1 << l1off);
    570             } else {
    571                 fval |= 1 << l1off;
    572             }
    573             if (l0off == 4) {
    574                 soc_reg_field_set(unit, HSP_SCHED_L0_NODE_4_CONNECTION_CONFIGr,
    575                         &rval, CHILDREN_CONNECTION_MAP_4f, fval);
    576 
    577                 SOC_IF_ERROR_RETURN(WRITE_HSP_SCHED_L0_NODE_4_CONNECTION_CONFIGr(
    578                             unit, port, rval));
    579             } else {
    580                 soc_reg_field_set(unit, HSP_SCHED_L0_NODE_CONNECTION_CONFIGr, 
    581                         &rval, CHILDREN_CONNECTION_MAPf, fval);
    582 
    583                 SOC_IF_ERROR_RETURN(WRITE_HSP_SCHED_L0_NODE_CONNECTION_CONFIGr(
    584                             unit, port, l0off - 1, rval));
    585             }
    586         }
    587         if (SOC_IS_MONTEREY(unit)) {
    588             return SOC_E_NONE;
    589         }
    590     }
    591     if (level == SOC_MONTEREY_NODE_LVL_S1) {
    592         bmap = SOC_CONTROL(unit)->port_lls_s1_bmap[port];
    593     } else if (level == SOC_MONTEREY_NODE_LVL_L0) {
    594         bmap = SOC_CONTROL(unit)->port_lls_l0_bmap[port];
    595     } else if (level == SOC_MONTEREY_NODE_LVL_L1) {
    596         bmap = SOC_CONTROL(unit)->port_lls_l1_bmap[port];
    597     } else if (level == SOC_MONTEREY_NODE_LVL_L2) {
    598         bmap = SOC_CONTROL(unit)->port_lls_l2_bmap[port];
    599     } else {
    600         return SOC_E_PARAM;
    601     }
    602     
    603     SOC_LLS_SCHEDULER_LOCK(unit);
    604     if (!add) {
    605         SHR_BITCLR(bmap, hw_index);
    606     } else {
    607         SHR_BITSET(bmap, hw_index);
    608     }
    609     SOC_LLS_SCHEDULER_UNLOCK(unit);
    610 
    611     return SOC_E_NONE;
    612 }
    613 STATIC int
    614 soc_monterey_sched_weight_set(int unit, int port, int level,
    615                               int hw_index, int weight)
    616 {
    617     uint32 entry[SOC_MAX_MEM_WORDS];
    618    soc_mem_t mem = INVALIDm;
    619     soc_field_t field = INVALIDf;
    620 
    621     if (level == SOC_MONTEREY_NODE_LVL_L0) {
    622        hw_index = hw_index;
    623         mem = HSP_SCHED_L0_NODE_WEIGHTm;
    624         field = L0_NODE_WEIGHTf;
    625     } else if (level == SOC_MONTEREY_NODE_LVL_L1) {
    626         hw_index = hw_index;
    627         mem = HSP_SCHED_L1_NODE_WEIGHTm;
    628         field  = L1_NODE_WEIGHTf;
    629     } else if (level == SOC_MONTEREY_NODE_LVL_L2) {
    630         if (hw_index < 640) {
    631             mem = HSP_SCHED_L2_UC_QUEUE_WEIGHTm;
    632             hw_index = hw_index;
    633             field = L2_UC_QUEUE_WEIGHTf;
    634         } else {
    635             mem = HSP_SCHED_L2_MC_QUEUE_WEIGHTm;
    636             hw_index = (hw_index - 640);
    637             field = L2_MC_QUEUE_WEIGHTf;
    638         }
    639    } else {
    640         /*Wrong level */
    641         return SOC_E_PARAM;
    642     }
    643     SOC_IF_ERROR_RETURN
    644            (soc_mem_read(unit, mem, MEM_BLOCK_ALL, hw_index, &entry));
    645     soc_mem_field32_set(unit, mem, &entry, field, weight);
    646     SOC_IF_ERROR_RETURN
    647            (soc_mem_write(unit, mem, MEM_BLOCK_ALL, hw_index, &entry));
    648     return SOC_E_NONE;
    649 }
    650 
    651 STATIC int
    652 soc_monterey_sched_weight_get(int unit, int port, int level,
    653                               int hw_index, int *weight)
    654 {
    655     uint32 entry[SOC_MAX_MEM_WORDS];
    656     soc_mem_t mem = INVALIDm;
    657     soc_field_t field = INVALIDf;
    658 
    659     if (level == SOC_MONTEREY_NODE_LVL_L0) {
    660         hw_index = hw_index;
    661         mem = HSP_SCHED_L0_NODE_WEIGHTm;
    662         field = L0_NODE_WEIGHTf;
    663     } else if (level == SOC_MONTEREY_NODE_LVL_L1) {
    664         hw_index = hw_index;
    665         mem = HSP_SCHED_L1_NODE_WEIGHTm;
    666         field = L1_NODE_WEIGHTf;
    667     } else if (level == SOC_MONTEREY_NODE_LVL_L2) {
    668         if (hw_index < 640) {
    669             mem = HSP_SCHED_L2_UC_QUEUE_WEIGHTm;
    670             hw_index = hw_index;
    671             field = L2_UC_QUEUE_WEIGHTf;
    672         } else {
    673             mem = HSP_SCHED_L2_MC_QUEUE_WEIGHTm;
    674             hw_index = (hw_index - 640);
    675             field = L2_MC_QUEUE_WEIGHTf;
    676         }
    677     } else {
    678         /*Wrong level */
    679         return SOC_E_PARAM;
    680     }
    681     SOC_IF_ERROR_RETURN
    682            (soc_mem_read(unit, mem, MEM_BLOCK_ALL, hw_index, &entry));
    683     *weight = soc_mem_field32_get(unit, mem, &entry, field);
    684     return SOC_E_NONE;
    685 }
    686 
    687 int
    688 soc_monterey_cosq_set_sched_mode(int unit, soc_port_t port, int level, int index,
    689                             soc_monterey_sched_mode_e mode, int weight)
    690 {
    691     soc_monterey_sched_type_t sched_type;
    692     uint32 entry[SOC_MAX_MEM_WORDS], mfval = 0, rval = 0, wrr_mask;
    693     soc_mem_t mem;
    694     soc_reg_t reg;
    695     uint32 mc_group_mode;
    696     int fval, idx, parent_idx = -1, index_save = index;
    697 
    698     LOG_INFO(BSL_LS_SOC_COSQ,
    699              (BSL_META_U(unit,
    700                          "Port:%d L%s%d config : index=%d MODE=%d WT=%d\n"),
    701                port, (level == 0) ? "r" : "", level - 1, 
    702                index, mode, weight));
    703 
    704     reg = INVALIDr;
    705     mem = INVALIDm;
    706     sched_type = _soc_monterey_port_sched_type_get(unit, port);
    707     if (sched_type == SOC_MONTEREY_SCHED_HSP) {
    708         /* get the port relative index / offset */
    709         if (level == SOC_MONTEREY_NODE_LVL_L0) {
    710             index = index % 5;
    711             reg = HSP_SCHED_PORT_CONFIGr;
    712             parent_idx = 0;
    713         } else if (level == SOC_MONTEREY_NODE_LVL_L1) {
    714             index = index % 10;
    715             reg = HSP_SCHED_L0_NODE_CONFIGr;
    716             /* Find the Parent index for the current child */
    717             for (idx = 1; idx < 5; idx++) {
    718                  if (idx == 4) {
    719                      SOC_IF_ERROR_RETURN(READ_HSP_SCHED_L0_NODE_4_CONNECTION_CONFIGr(
    720                                                          unit, port, &rval));
    721                      fval = soc_reg_field_get(unit,
    722                                  HSP_SCHED_L0_NODE_4_CONNECTION_CONFIGr,
    723                                  rval, CHILDREN_CONNECTION_MAP_4f);
    724                 } else { 
    725                     SOC_IF_ERROR_RETURN(READ_HSP_SCHED_L0_NODE_CONNECTION_CONFIGr(
    726                                                        unit, port, idx - 1, &rval));
    727                     fval = soc_reg_field_get(unit,
    728                                 HSP_SCHED_L0_NODE_CONNECTION_CONFIGr,
    729                                rval, CHILDREN_CONNECTION_MAPf);
    730                 }
    731                 if (idx == 4) {
    732                     if ((index >= 8) && (fval & (1 << (index - 8)))) {
    733                         parent_idx = idx;
    734                         break;
    735                     }
    736                 } else {
    737                     if (fval & (1 << index)) {
    738                         parent_idx = idx;
    739                         break;
    740                     }
    741                 }
    742             }
    743         } else if (level == SOC_MONTEREY_NODE_LVL_L2) {
    744             mc_group_mode = soc_reg_field_get( unit,
    745                     HSP_SCHED_PORT_CONFIGr, rval,
    746                     MC_GROUP_MODEf);
    747             reg = HSP_SCHED_L1_NODE_CONFIGr;
    748             if (mc_group_mode && (index >= _MN_MAX_NUM_UC_QUEUE(unit))) {
    749                 parent_idx = (index - _MN_MAX_NUM_UC_QUEUE(unit))  % 10;
    750                 if ( parent_idx  < _MN_HSP_PORT_MAX_COS) {
    751                     reg = HSP_SCHED_L0_NODE_CONFIGr;
    752                     parent_idx = 0;
    753                 }
    754             }else {
    755                 parent_idx = index  % 10;
    756             }  
    757         } else {
    758             return SOC_E_PARAM;
    759         }
    760 
    761         if (parent_idx == -1) {
    762             return SOC_E_INTERNAL;
    763         }
    764 
    765         if (mode == SOC_MONTEREY_SCHED_MODE_STRICT) {
    766             weight = 0;
    767         } else if (mode == SOC_MONTEREY_SCHED_MODE_WRR) {
    768             mfval = 1;
    769         } else if (mode == SOC_MONTEREY_SCHED_MODE_WDRR) {
    770             mfval = 0;
    771         } else {
    772             return SOC_E_PARAM;
    773         }
    774 
    775         /* selection between SP and WxRR is based on weight property. */
    776         SOC_IF_ERROR_RETURN(soc_monterey_sched_weight_set(unit, port, 
    777                                                 level, index_save, weight));
    778         if (mode != SOC_MONTEREY_SCHED_MODE_STRICT) {
    779             SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, port, 0, &rval));
    780             wrr_mask = soc_reg_field_get(unit, reg, rval, ENABLE_WRRf);
    781             wrr_mask &= ~(1 << parent_idx);
    782             wrr_mask |= (mfval << parent_idx);
    783             soc_reg_field_set(unit, reg, &rval, ENABLE_WRRf, wrr_mask);
    784             SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, port, 0, rval));
    785         }
    786     } else {
    787         if (mode == SOC_MONTEREY_SCHED_MODE_STRICT) {
    788             weight = 0;
    789         }
    790         
    791         SOC_IF_ERROR_RETURN(soc_monterey_sched_weight_set(unit, port, 
    792                                                 level, index, weight));
    793 
    794         if (mode != SOC_MONTEREY_SCHED_MODE_STRICT) { 
    795             mem = _SOC_MONTEREY_NODE_CONFIG_MEM(unit, port, SOC_MONTEREY_NODE_LVL_S1);
    796             index = _soc_monterey_s1_scheduler_index(unit, port,  level, index);
    797             if (index == -1) {
    798                 return SOC_E_INTERNAL;
    799             }
    800             SOC_IF_ERROR_RETURN(
    801                     soc_mem_read(unit, mem, MEM_BLOCK_ALL, index, &entry));
    802             soc_mem_field32_set(unit, mem, entry, 
    803                     PACKET_MODE_WRR_ACCOUNTING_ENABLEf, 
    804                     (mode == SOC_MONTEREY_SCHED_MODE_WRR) ? 1 : 0);
    805             SOC_IF_ERROR_RETURN(
    806                     soc_mem_write(unit, mem, MEM_BLOCK_ANY, index, &entry));
    807         }
    808     }
    809     return SOC_E_NONE;
    810 }
    811 
    812 /* number of registers in the set to support Dynamic Scheduling */
    813 #define _SOC_MONTEREY_DYN_REGISTER_SET    4  
    814 
    815 /* Structure to maintain the ports that are undergoing dyn sched*/
    816 typedef struct _soc_monterey_port_dyn_sched_s {
    817     sal_mutex_t     lock;
    818     int             port[_SOC_MONTEREY_DYN_REGISTER_SET];
    819     int             _soc_monterey_init_done[SOC_MAX_NUM_DEVICES];
    820 } _soc_monterey_port_dyn_sched_t;
    821 
    822 static _soc_monterey_port_dyn_sched_t _monterey_dyn_sched_unit_data[SOC_MAX_NUM_DEVICES];
    823 
    824 /*
    825  * Function:
    826  *     _soc_monterey_alloc_dyn_set
    827  * Purpose:
    828  *     This function allocates the register available from
    829  *     the set of SP_WERR_DYN_CHANGEnA/nB/nC (n=0,1,2,3) to the port and 
    830  *     updates the structure _monterey_dyn_sched_unit_data to keep track 
    831  *     of the used registers from the set.
    832  * Parameters:
    833  *     unit       - (IN) unit number
    834  *     port       - (IN) local port number
    835  *     r_a        - (OUT) SP_WERR_DYN_CHANGEnA register
    836  *     r_b        - (OUT) SP_WERR_DYN_CHANGEnB register
    837  *     r_ctrl     - (OUT) SP_WERR_DYN_CHANGEnC register
    838  * Returns:
    839  *     SOC_E_XXX
    840  */
    841 STATIC int _soc_monterey_alloc_dyn_set(int unit, int port, 
    842             soc_reg_t *r_a, soc_reg_t *r_b, soc_reg_t *r_ctrl)
    843 {
    844     _soc_monterey_port_dyn_sched_t *pcb;
    845     int i, empty_at = -1, rv = SOC_E_NONE;
    846 
    847     soc_reg_t dyn_change_a_x[] = {
    848                                        LLS_SP_WERR_DYN_CHANGE_0Ar,
    849                                        LLS_SP_WERR_DYN_CHANGE_1Ar,
    850                                        LLS_SP_WERR_DYN_CHANGE_2Ar,
    851                                        LLS_SP_WERR_DYN_CHANGE_3Ar
    852                                  };
    853     soc_reg_t dyn_change_b_x[] = {
    854                                        LLS_SP_WERR_DYN_CHANGE_0Br,
    855                                        LLS_SP_WERR_DYN_CHANGE_1Br,
    856                                        LLS_SP_WERR_DYN_CHANGE_2Br,
    857                                        LLS_SP_WERR_DYN_CHANGE_3Br
    858                                  };
    859     
    860     soc_reg_t dyn_change_ctrl_x[] = {
    861                                        LLS_SP_WERR_DYN_CHANGE_0Cr,
    862                                        LLS_SP_WERR_DYN_CHANGE_1Cr,
    863                                        LLS_SP_WERR_DYN_CHANGE_2Cr,
    864                                        LLS_SP_WERR_DYN_CHANGE_3Cr
    865                                     };
    866 
    867     pcb = &_monterey_dyn_sched_unit_data[unit];
    868     
    869     sal_mutex_take(pcb->lock, sal_sem_FOREVER);
    870     for (i = 0; i < _SOC_MONTEREY_DYN_REGISTER_SET; i++) {
    871         if (pcb->port[i] == -1) {
    872             empty_at = i;
    873             break;
    874         } else if (pcb->port[i] == port) {
    875             rv = SOC_E_BUSY;
    876             break;
    877         }
    878     }
    879 
    880     if (!rv && (empty_at >= 0)) {
    881         pcb->port[empty_at] = port;
    882     }
    883     
    884     sal_mutex_give(pcb->lock);
    885 
    886     if (rv) {
    887         return rv;
    888     }
    889 
    890     if (empty_at == -1) {
    891         return SOC_E_BUSY;
    892     }
    893     *r_a = dyn_change_a_x[empty_at];
    894     *r_b = dyn_change_b_x[empty_at];
    895     *r_ctrl = dyn_change_ctrl_x[empty_at];
    896     return SOC_E_NONE;
    897 }
    898 
    899 /*
    900  * Function:
    901  *     _soc_monterey_free_dyn_set
    902  * Purpose:
    903  *     This function is called after the switchover is done 
    904  *     to update the structure _monterey_dyn_sched_unit_data by  
    905  *     removing the port from it. This makes the register
    906  *     used for the request available for the next request.
    907  * Parameters:
    908  *     unit       - (IN) unit number
    909  *     port       - (IN) local port number
    910  * Returns:
    911  *     SOC_E_XXX
    912  */
    913 STATIC int _soc_monterey_free_dyn_set(int unit, int port)
    914 {
    915     _soc_monterey_port_dyn_sched_t *pcb;
    916     int i;
    917 
    918     pcb = &_monterey_dyn_sched_unit_data[unit];
    919 
    920     sal_mutex_take(pcb->lock, sal_sem_FOREVER);
    921     for (i = 0; i < _SOC_MONTEREY_DYN_REGISTER_SET; i++) {
    922         if (pcb->port[i] == port) {
    923             pcb->port[i] = -1;
    924         }
    925     }
    926     sal_mutex_give(pcb->lock);
    927     
    928     return SOC_E_NONE;
    929 }
    930 
    931 /*
    932  * Function:
    933  *     soc_monterey_cosq_set_sched_child_config_dynamic
    934  * Purpose:
    935  *     This function enables the spri_vect_mode by setting the 
    936  *     spri_vect_mode_enable field to 1 in the LLS_CONFIG0 reg, which changes 
    937  *     p_num_spri[3:0] to p_vect_spri[7:0]. It allocates the register from set
    938  *     of SP_WERR_DYN_CHNG_nA/nB/nC registers to the port. It then sets the 
    939  *     SP_WERR_DYN_CHNG_nB/nC reg with the new value for the node id's parent.
    940  *     It sets the fields in SP_WERR_DYN_CHNG_nA with the info about the node
    941  *     to be switched like node_id, node_level and parent_id along with in_use
    942  *     field to 1, which triggers the request in H/W. The H/W clears in_use
    943  *     field to 0 once the switchover is complete, so we keep polling its
    944  *     to know about the completion of the request. 
    945  * Parameters:
    946  *     unit       - (IN) unit number
    947  *     port       - (IN) local port number
    948  *     level      - (IN) level of the node
    949  *     index      - (IN) index of the node
    950  *     num_spri   - (IN) number of SPRI child nodes
    951  *     first_child - (IN) first child node
    952  *     first_mc_child - (IN) first multicast child node
    953  *     ucmap        - (IN) unicast map
    954  *     spmap        - (IN) spri map
    955  *     child_index     - (IN) index number of the child
    956  * Returns:
    957  *     SOC_E_XXX
    958  */
    959 int
    960 soc_monterey_cosq_set_sched_child_config_dynamic(int unit, soc_port_t port,
    961                                             int level, int index, 
    962                                             int num_spri, int first_child,
    963                                             int first_mc_child, uint32 ucmap,
    964                                             uint32 spmap, int child_index)
    965 {
    966     uint32 entry[SOC_MAX_MEM_WORDS], rval, d32, timeout_val, old_spmap, f1, f2;
    967     soc_mem_t mem;
    968     int rv = SOC_E_NONE;
    969     soc_reg_t r_a = INVALIDr, r_b = INVALIDr, r_ctrl = INVALIDr;
    970     soc_timeout_t timeout;
    971 
    972     if (level == SOC_MONTEREY_NODE_LVL_ROOT) {
    973         return SOC_E_NONE;
    974     }
    975 
    976     SOC_IF_ERROR_RETURN(_soc_monterey_alloc_dyn_set(unit, port, 
    977                                                &r_a, &r_b, &r_ctrl));
    978 
    979     mem = _SOC_MONTEREY_NODE_CONFIG_MEM(unit, port, level);
    980     if (mem == INVALIDm) {
    981         return SOC_E_INTERNAL;
    982     }
    983 
    984     level -= 1;
    985     /* Getting the old spmap */    
    986     SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, index, &entry));
    987     f1 = soc_mem_field32_get(unit, mem, &entry, P_NUM_SPRIf);
    988     f2 = soc_mem_field32_get(unit, mem, &entry, P_VECT_SPRI_7_4f);
    989     old_spmap = f1 | (f2 << 4);
    990 
    991     LOG_INFO(BSL_LS_SOC_COSQ,
    992             (BSL_META_U(unit,
    993             "Port:%d L%s%d config : index=%d FC=%d FMC=%d UMAP=0x%x NUMSP=%d\n"), 
    994              port, (level==0) ? "r" : "", level, 
    995              index, first_child, first_mc_child, ucmap, num_spri));
    996 
    997     /* Setting the memory fields based on the new spmap */
    998     soc_mem_field32_set(unit, mem, &entry, P_NUM_SPRIf, spmap & 0xf);
    999     soc_mem_field32_set(unit, mem, &entry, P_VECT_SPRI_7_4f, (spmap >> 4) & 0xf);
   1000 
   1001     if (mem == LLS_L1_CONFIGm) {
   1002         soc_mem_field32_set(unit, mem, &entry, P_START_UC_SPRIf, first_child);
   1003         soc_mem_field32_set(unit, mem, &entry, P_START_MC_SPRIf, first_mc_child);
   1004         soc_mem_field32_set(unit, mem, &entry, P_SPRI_SELECTf, 
   1005                             (num_spri > 0) ? ucmap : 0);
   1006     } else {
   1007         soc_mem_field32_set(unit, mem, &entry, P_START_SPRIf, first_child);
   1008     }
   1009 
   1010     SOC_IF_ERROR_RETURN(
   1011         soc_mem_write(unit, mem, MEM_BLOCK_ANY, index, &entry));
   1012 
   1013     rval = 0;
   1014     soc_bits_get(entry, 0, 31, &d32);
   1015     soc_reg_field_set(unit, r_ctrl, &rval, LLS_PARENT_CONFIGf, d32);
   1016     SOC_IF_ERROR_RETURN(soc_reg32_set(unit, r_ctrl, REG_PORT_ANY, 0, rval));
   1017 
   1018     rval = 0;
   1019     soc_bits_get(entry, 32, 45, &d32);
   1020     soc_reg_field_set(unit, r_b, &rval, LLS_PARENT_CONFIGf, d32);
   1021     soc_reg_field_set(unit, r_b, &rval, LLS_PARENT_CONFIG_ORIGINAL_SP_VECTORf,
   1022                                             old_spmap);
   1023     SOC_IF_ERROR_RETURN(soc_reg32_set(unit, r_b, REG_PORT_ANY, 0, rval));
   1024 
   1025     rval = 0;
   1026     soc_reg_field_set(unit, r_a, &rval, NODE_LEVELf, level + 1);
   1027     soc_reg_field_set(unit, r_a, &rval, NODE_IDf, child_index);
   1028     soc_reg_field_set(unit, r_a, &rval, PARENT_IDf, index);
   1029     soc_reg_field_set(unit, r_a, &rval, IN_USEf, 1);
   1030     SOC_IF_ERROR_RETURN(soc_reg32_set(unit, r_a, REG_PORT_ANY, 0, rval));
   1031 
   1032     if (!SAL_BOOT_SIMULATION) {
   1033         timeout_val = soc_property_get(unit, spn_MMU_QUEUE_FLUSH_TIMEOUT, 20000);
   1034         soc_timeout_init(&timeout, timeout_val, 0);
   1035 
   1036         do {
   1037             SOC_IF_ERROR_RETURN(
   1038                 soc_reg32_get(unit, r_a, REG_PORT_ANY, 0, &rval));
   1039                 
   1040             if (soc_timeout_check(&timeout)) {
   1041                 rv = SOC_E_TIMEOUT;
   1042                 break;
   1043             }
   1044         } while (soc_reg_field_get(unit, r_a, rval, IN_USEf));
   1045     }
   1046 
   1047     SOC_IF_ERROR_RETURN(_soc_monterey_free_dyn_set(unit, port));
   1048 
   1049     return rv;
   1050 }
   1051 
   1052 int
   1053 soc_monterey_cosq_set_sched_config(int unit, soc_port_t port,
   1054                               int level, int index, int child_index,
   1055                               int num_spri, int first_child, 
   1056                               int first_mc_child, uint32 ucmap, uint32 spmap,
   1057                               soc_monterey_sched_mode_e mode, int weight)
   1058 {
   1059     int child_level;
   1060 
   1061     if (level >= SOC_MONTEREY_NODE_LVL_L2) {
   1062         return SOC_E_PARAM;
   1063     }
   1064 
   1065     SOC_IF_ERROR_RETURN(
   1066         soc_monterey_cosq_set_sched_child_config_dynamic(unit, port,
   1067                                 level, index, num_spri, first_child, 
   1068                                 first_mc_child, ucmap, spmap, child_index));
   1069     if (child_index >= 0) {
   1070         soc_monterey_get_child_type(unit, port, level, &child_level);
   1071         SOC_IF_ERROR_RETURN(soc_monterey_cosq_set_sched_mode(unit, port, 
   1072                     child_level, 
   1073                     child_index, mode, weight));
   1074     }
   1075 
   1076     return SOC_E_NONE;
   1077 }
   1078 
   1079 int
   1080 soc_monterey_cosq_get_sched_child_config(int unit, soc_port_t port,
   1081                               int level, int index,
   1082                               int *pnum_spri, int *pfirst_sp_child, 
   1083                               int *pfirst_sp_mc_child, uint32 *pucmap, uint32 *pspmap)
   1084 {
   1085     soc_monterey_sched_type_t sched_type;
   1086     uint32 entry[SOC_MAX_MEM_WORDS];
   1087     uint32 num_spri = 0, ucmap = 0, f1, f2;
   1088     int first_sp_child = -1, first_sp_mc_child = -1,ii;
   1089     soc_mem_t mem;
   1090 
   1091     sched_type = _soc_monterey_port_sched_type_get(unit, port);
   1092 
   1093     mem = INVALIDm;
   1094 
   1095     if (sched_type == SOC_MONTEREY_SCHED_HSP) {
   1096         return SOC_E_PARAM;
   1097     }
   1098 
   1099     mem = _SOC_MONTEREY_NODE_CONFIG_MEM(unit, port, level);
   1100     SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, index, &entry));
   1101     num_spri = soc_mem_field32_get(unit, mem, &entry, P_NUM_SPRIf);
   1102 
   1103     f1 = soc_mem_field32_get(unit, mem, &entry, P_NUM_SPRIf);
   1104     f2 = soc_mem_field32_get(unit, mem, &entry, P_VECT_SPRI_7_4f);
   1105     *pspmap = f1 | (f2 << 4);
   1106     for (ii = 0; ii < 8; ii++) {
   1107         if ((1 << ii) & *pspmap) {
   1108             num_spri++;
   1109         }
   1110     }
   1111     if (mem == LLS_L1_CONFIGm) { 
   1112         first_sp_child = soc_mem_field32_get(unit, mem, &entry, P_START_UC_SPRIf);
   1113         first_sp_mc_child = soc_mem_field32_get(unit, mem, 
   1114                                          &entry, P_START_MC_SPRIf);
   1115         ucmap = soc_mem_field32_get(unit, mem, &entry, P_SPRI_SELECTf);
   1116     } else {
   1117         first_sp_child = soc_mem_field32_get(unit, mem, &entry, P_START_SPRIf);
   1118         first_sp_mc_child = 0;
   1119     }
   1120     
   1121     if (num_spri == 0) {
   1122         ucmap = 0;
   1123     }
   1124 
   1125     if (pnum_spri) {
   1126         *pnum_spri = num_spri;
   1127     }
   1128        
   1129     if (pucmap) {
   1130         *pucmap = ucmap;
   1131     }
   1132 
   1133     if (pfirst_sp_child) {
   1134         *pfirst_sp_child = first_sp_child;
   1135     }
   1136 
   1137     if (pfirst_sp_mc_child) {
   1138         *pfirst_sp_mc_child = first_sp_mc_child;
   1139     }
   1140 
   1141     LOG_INFO(BSL_LS_SOC_COSQ,
   1142              (BSL_META_U(unit,
   1143                          "Port:%d L%s%d config : index=%d FC=%d FMC=%d UMAP=0x%x\n"),
   1144                port, (level == 0) ? "r" : "", level - 1, 
   1145                index, first_sp_child, first_sp_mc_child, ucmap));
   1146 
   1147     return SOC_E_NONE;
   1148 }
   1149 
   1150 int
   1151 soc_monterey_cosq_get_sched_mode(int unit, soc_port_t port, int level, 
   1152                             int index, soc_monterey_sched_mode_e *pmode, int *weight)
   1153 {
   1154     soc_monterey_sched_type_t sched_type;
   1155     uint32 entry[SOC_MAX_MEM_WORDS], rval, wrr_mask;
   1156     soc_monterey_sched_mode_e mode = SOC_MONTEREY_SCHED_MODE_UNKNOWN;
   1157     soc_mem_t mem;
   1158     soc_reg_t reg;
   1159     int parent_idx  = 0;
   1160     int  idx, fval, index_save = index;   
   1161     uint32 mc_group_mode = 0;
   1162     reg = INVALIDr;
   1163     mem = INVALIDm;
   1164     sched_type = _soc_monterey_port_sched_type_get(unit, port);
   1165 
   1166     if (sched_type == SOC_MONTEREY_SCHED_HSP) {
   1167         /* get the port relative index / offset */
   1168         if (level == SOC_MONTEREY_NODE_LVL_L0) {
   1169             index = index % 5;
   1170             reg = HSP_SCHED_PORT_CONFIGr;
   1171             parent_idx = 0;
   1172         } else if (level == SOC_MONTEREY_NODE_LVL_L1) {
   1173             index = index % 10;
   1174             reg = HSP_SCHED_L0_NODE_CONFIGr;
   1175             /* Find the Parent index for the current child */
   1176             for (idx = 1; idx < 5; idx++) {
   1177                  if (idx == 4) {
   1178                      SOC_IF_ERROR_RETURN(READ_HSP_SCHED_L0_NODE_4_CONNECTION_CONFIGr(
   1179                                                          unit, port, &rval));
   1180                      fval = soc_reg_field_get(unit,
   1181                                  HSP_SCHED_L0_NODE_4_CONNECTION_CONFIGr,
   1182                                  rval, CHILDREN_CONNECTION_MAP_4f);
   1183                 } else {
   1184                     SOC_IF_ERROR_RETURN(READ_HSP_SCHED_L0_NODE_CONNECTION_CONFIGr(
   1185                                                         unit, port, idx - 1, &rval));
   1186                     fval = soc_reg_field_get(unit,
   1187                                 HSP_SCHED_L0_NODE_CONNECTION_CONFIGr,
   1188                                 rval, CHILDREN_CONNECTION_MAPf);
   1189                 }
   1190                 if (idx == 4) {
   1191                     if ((index >= 8) && (fval & (1 << (index - 8)))) {
   1192                         parent_idx = idx;
   1193                         break;
   1194                     }
   1195                 } else {
   1196                     if (fval & (1 << index)) {
   1197                         parent_idx = idx;
   1198                         break;
   1199                     }
   1200                 }
   1201             }
   1202         } else if (level == SOC_MONTEREY_NODE_LVL_L2) {
   1203             SOC_IF_ERROR_RETURN(
   1204                     READ_HSP_SCHED_PORT_CONFIGr( unit, port, &rval));
   1205             mc_group_mode = soc_reg_field_get( unit,
   1206                                                HSP_SCHED_PORT_CONFIGr, rval,
   1207                                                MC_GROUP_MODEf);
   1208             reg = HSP_SCHED_L1_NODE_CONFIGr;
   1209 
   1210             if (mc_group_mode && (index >= _MN_MAX_NUM_UC_QUEUE(unit))) {
   1211                 parent_idx = (index - _MN_MAX_NUM_UC_QUEUE(unit))  % 10;
   1212                 if ( parent_idx  < _MN_HSP_PORT_MAX_COS) {
   1213                     reg = HSP_SCHED_L0_NODE_CONFIGr;
   1214                     parent_idx = 0;
   1215                 }
   1216             }else {
   1217                 parent_idx = index  % 10;
   1218             }
   1219 
   1220         } else {
   1221             return SOC_E_PARAM;
   1222         }
   1223 
   1224         /* selection between SP and WxRR is based on weight property. */
   1225         SOC_IF_ERROR_RETURN(soc_monterey_sched_weight_get(unit, port, 
   1226                                                 level, index_save, weight));
   1227         if (*weight == 0) {
   1228             mode = SOC_MONTEREY_SCHED_MODE_STRICT;
   1229         } else {
   1230             SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, port, 0, &rval));
   1231             wrr_mask = soc_reg_field_get(unit, reg, rval, ENABLE_WRRf);
   1232             if (wrr_mask & (1 << parent_idx)) {
   1233                 mode = SOC_MONTEREY_SCHED_MODE_WRR;
   1234             } else {
   1235                 mode = SOC_MONTEREY_SCHED_MODE_WDRR;
   1236             }
   1237         }
   1238     } else {
   1239         SOC_IF_ERROR_RETURN(soc_monterey_sched_weight_get(unit, port, 
   1240                         level, index, weight));
   1241         if (*weight == 0) {
   1242             mode = SOC_MONTEREY_SCHED_MODE_STRICT;
   1243         } else {
   1244             mem = _SOC_MONTEREY_NODE_CONFIG_MEM(unit, port, SOC_MONTEREY_NODE_LVL_S1);
   1245             index = _soc_monterey_s1_scheduler_index(unit, port,  level, index);
   1246             if (index == -1) {
   1247                 return SOC_E_INTERNAL;
   1248             }
   1249             SOC_IF_ERROR_RETURN(
   1250                     soc_mem_read(unit, mem, MEM_BLOCK_ALL, index, &entry));
   1251             if (soc_mem_field32_get(unit, mem, 
   1252                                 entry, PACKET_MODE_WRR_ACCOUNTING_ENABLEf)) {
   1253                 mode = SOC_MONTEREY_SCHED_MODE_WRR;
   1254             } else {
   1255                 mode = SOC_MONTEREY_SCHED_MODE_WDRR;
   1256             }
   1257         }
   1258     }
   1259 
   1260     if (pmode) {
   1261         *pmode = mode;
   1262     }
   1263 
   1264     LOG_INFO(BSL_LS_SOC_COSQ,
   1265              (BSL_META_U(unit,
   1266                          "Port:%d L%s%d config : index=%d MODE=%d WT=%d\n"),
   1267                port, (level == 0) ? "r" : "", level - 1, index, mode, *weight));
   1268 
   1269     return SOC_E_NONE;
   1270 }
   1271 
   1272 int
   1273 soc_monterey_cosq_get_sched_config(int unit, soc_port_t port,
   1274                               int level, int index, int child_index,
   1275                               int *pnum_spri, int *pfirst_child, 
   1276                               int *pfirst_mc_child, uint32 *pucmap, uint32 *pspmap,
   1277                               soc_monterey_sched_mode_e *pmode, int *weight)
   1278 {
   1279     int child_level;
   1280 
   1281     if (level >= SOC_MONTEREY_NODE_LVL_L2) {
   1282         return SOC_E_PARAM;
   1283     }
   1284 
   1285     if (level != SOC_MONTEREY_NODE_LVL_ROOT) {
   1286         SOC_IF_ERROR_RETURN(soc_monterey_cosq_get_sched_child_config(unit, port, level,
   1287                     index, pnum_spri, pfirst_child, pfirst_mc_child, pucmap, pspmap));
   1288     }
   1289 
   1290     if (child_index >= 0) {
   1291         soc_monterey_get_child_type(unit, port, level, &child_level);
   1292         SOC_IF_ERROR_RETURN(
   1293                 soc_monterey_cosq_get_sched_mode(unit, port, child_level, child_index,
   1294                                             pmode, weight));
   1295     }
   1296     
   1297     return SOC_E_NONE;
   1298 }
   1299 
   1300 int soc_monterey_get_child_type(int unit, soc_port_t port, int level, 
   1301                                     int *child_type)
   1302 {
   1303     *child_type = -1;
   1304     if (level == SOC_MONTEREY_NODE_LVL_ROOT) {
   1305         *child_type = SOC_MONTEREY_NODE_LVL_S1;
   1306     } else if (level == SOC_MONTEREY_NODE_LVL_S1) {
   1307             *child_type = SOC_MONTEREY_NODE_LVL_L0;
   1308     } else if (level == SOC_MONTEREY_NODE_LVL_L0) {
   1309         *child_type = SOC_MONTEREY_NODE_LVL_L1;
   1310     } else if (level == SOC_MONTEREY_NODE_LVL_L1) {
   1311         *child_type = SOC_MONTEREY_NODE_LVL_L2;
   1312     }
   1313     return SOC_E_NONE;
   1314 }
   1315 STATIC int
   1316 _soc_monterey_alloc_sched(int unit, soc_port_t in_port, soc_monterey_node_lvl_e lvl, 
   1317                      int offset, int *hw_index)
   1318 {
   1319     int in_pipe, tlm = -1;
   1320     int mmu_port, max = -1;
   1321     soc_monterey_sched_type_t stype;
   1322     uint32  sched_bmap[32];
   1323     
   1324     sal_memset(sched_bmap, 0, sizeof(uint32)*32);
   1325 
   1326     SOC_IF_ERROR_RETURN(
   1327         soc_monterey_port_common_attributes_get(unit, in_port, &in_pipe, &mmu_port, NULL));
   1328     stype = _soc_monterey_port_sched_type_get(unit, in_port);
   1329     if (SOC_IS_MONTEREY(unit)) {
   1330         if (IS_CPU_PORT(unit, in_port)) {
   1331             mmu_port++;
   1332         } else if (IS_LB_PORT(unit, in_port)) {
   1333             mmu_port--;
   1334         }
   1335     }
   1336     if (lvl == SOC_MONTEREY_NODE_LVL_ROOT) {
   1337         tlm = 1;
   1338         max = 106;
   1339     } else if (lvl == SOC_MONTEREY_NODE_LVL_L0) {
   1340         tlm = 5; /* max 4 L0 under HSP */
   1341         max = 272;
   1342     } else if (lvl == SOC_MONTEREY_NODE_LVL_L1) {
   1343         tlm = 10;
   1344         max = 1024;
   1345     }
   1346 
   1347     if ((max < 0) || (tlm < 0)) {
   1348         return SOC_E_PARAM;
   1349     }
   1350         
   1351     if (stype == SOC_MONTEREY_SCHED_HSP) {
   1352         /* For HSP ports, the indexes of the scheduler and queues are fixed.*/
   1353         if (offset >= tlm) {
   1354             return SOC_E_PARAM;
   1355         }
   1356         mmu_port += (mmu_port >= 74) ? -74 : 0;
   1357         *hw_index = (mmu_port * tlm) + offset;
   1358         return SOC_E_NONE;
   1359     }  
   1360 
   1361     return SOC_E_RESOURCE;
   1362 }
   1363 
   1364 int soc_monterey_l2_hw_index(int unit, int qnum, int uc)
   1365 {
   1366     if (uc) {
   1367         qnum -= (qnum >= 640) ? 640 : 0;
   1368     } else {
   1369         qnum += 640;
   1370     }
   1371     return qnum;
   1372 }
   1373 
   1374 /*
   1375  * Function:
   1376  *     soc_monterey_hw_index_logical_num
   1377  * Purpose:
   1378  *     Get the logical queue number according to hw index
   1379  * Parameters:
   1380  *     unit          - (IN) unit number
   1381  *     port          - (IN) local port number
   1382  *     index         -(IN) The index of Queue management related memory Tables
   1383  *     uc            - (IN) unicast indicator
   1384  * Returns:
   1385  *     logical queue number: queue number in logical view
   1386  *     In logical view,
   1387  *     the range of unicast queue number is:   [0,16384)
   1388  *     the range of multicast queue number is: [0,778)
   1389  */
   1390 int
   1391 soc_monterey_hw_index_logical_num(int unit,int port,int index,int uc)
   1392 {
   1393     int qnum;
   1394     if (uc) {
   1395         qnum = index;
   1396     } else {
   1397         
   1398         if (SOC_IS_MONTEREY(unit)) {
   1399             qnum =  index - 640;
   1400         } else { 
   1401             qnum =  index - 16384;
   1402         }
   1403     }
   1404 
   1405     return qnum;
   1406 }
   1407 
   1408 
   1409 #define AP_DFL_HSP_SCHED_MODE  SOC_MONTEREY_SCHED_MODE_WDRR
   1410 
   1411 int
   1412 soc_monterey_setup_hsp_port(int unit, int port)
   1413 {
   1414     uint32 rval, fval = 0, pbmf;
   1415     int mmu_port, pipe, l0_index, l1_index, l0_1, l0_4, hw_index, index;
   1416 
   1417    
   1418     SOC_IF_ERROR_RETURN(
   1419         soc_monterey_port_common_attributes_get(unit, port, &pipe, &mmu_port, NULL));
   1420 
   1421     for (index = 0; index < 5; index++) {
   1422         SHR_BITSET(SOC_CONTROL(unit)->port_lls_l0_bmap[port],
   1423                 (mmu_port & 0x3f) * 5 + index);
   1424     }
   1425     for (index = 0; index < 10; index++) {
   1426         SHR_BITSET(SOC_CONTROL(unit)->port_lls_l1_bmap[port],
   1427                 (mmu_port & 0x3f) * 10 + index);
   1428     }
   1429     for (index = 0; index < 10; index++) {
   1430         SHR_BITSET(SOC_CONTROL(unit)->port_lls_l2_bmap[port],
   1431                 (mmu_port & 0x3f) * 10 + index);
   1432     }
   1433 
   1434     rval = 0;
   1435     SOC_IF_ERROR_RETURN(WRITE_HSP_SCHED_PORT_CONFIGr(unit, port, rval));
   1436     SOC_IF_ERROR_RETURN(WRITE_HSP_SCHED_L0_NODE_CONFIGr(unit, port, rval));
   1437     SOC_IF_ERROR_RETURN(WRITE_HSP_SCHED_L1_NODE_CONFIGr(unit, port, rval));
   1438     SOC_IF_ERROR_RETURN(WRITE_HSP_SCHED_L2_UC_QUEUE_CONFIGr(unit, port, rval));
   1439 
   1440     l0_1 = 0;
   1441     l0_4 = 0;
   1442     for (l0_index = 0; l0_index < 5; l0_index++) {
   1443         SOC_IF_ERROR_RETURN(soc_monterey_sched_hw_index_get(unit, port, 
   1444                                     SOC_MONTEREY_NODE_LVL_L0, l0_index, &hw_index));
   1445         SOC_IF_ERROR_RETURN(soc_monterey_cosq_set_sched_parent(unit, port,
   1446                               SOC_MONTEREY_NODE_LVL_L0, hw_index, mmu_port, 1));
   1447 
   1448         if (l0_index == 1) {
   1449             l0_1 = hw_index;
   1450         } else if (l0_index == 4) {
   1451             l0_4 = hw_index;
   1452         }
   1453     }
   1454 
   1455     for (l1_index = 0; l1_index < 10; l1_index++) {
   1456         SOC_IF_ERROR_RETURN(soc_monterey_sched_hw_index_get(unit, port, 
   1457                                     SOC_MONTEREY_NODE_LVL_L1, l1_index, &hw_index));
   1458 
   1459         SOC_IF_ERROR_RETURN(soc_monterey_cosq_set_sched_parent(unit, port,
   1460                    SOC_MONTEREY_NODE_LVL_L1, hw_index, (l1_index < 8) ? l0_1 : l0_4, 1));
   1461 
   1462         SOC_IF_ERROR_RETURN(soc_monterey_cosq_set_sched_mode(unit, port, 
   1463                  SOC_MONTEREY_NODE_LVL_L1, l1_index, SOC_MONTEREY_SCHED_MODE_WDRR, 1));
   1464     }
   1465 
   1466     pbmf = IS_HSP_PORT_IN_XPIPEf;
   1467     SOC_IF_ERROR_RETURN(READ_HSP_SCHED_GLOBAL_CONFIGr(unit, &rval));
   1468     fval = soc_reg_field_get(unit, HSP_SCHED_GLOBAL_CONFIGr, rval, pbmf);
   1469     fval |= (1 << mmu_port);
   1470     soc_reg_field_set(unit, HSP_SCHED_GLOBAL_CONFIGr, &rval, pbmf, fval);
   1471     SOC_IF_ERROR_RETURN(WRITE_HSP_SCHED_GLOBAL_CONFIGr(unit, rval));
   1472     return SOC_E_NONE;
   1473 }
   1474 
   1475 int
   1476 soc_monterey_delete_hsp_port(int unit, int port)
   1477 {
   1478     uint32 rval, fval = 0, pbmf;
   1479     int mmu_port, pipe, l0_index, index;
   1480 
   1481     SOC_IF_ERROR_RETURN(
   1482             soc_monterey_port_common_attributes_get(unit, port, &pipe, &mmu_port, NULL));
   1483 
   1484     for (index = 0; index < 5; index++) {
   1485         SHR_BITCLR(SOC_CONTROL(unit)->port_lls_l0_bmap[port],
   1486                 (mmu_port & 0x3f) * 5 + index);
   1487     }
   1488     for (index = 0; index < 10; index++) {
   1489         SHR_BITCLR(SOC_CONTROL(unit)->port_lls_l1_bmap[port],
   1490                 (mmu_port & 0x3f) * 10 + index);
   1491     }
   1492     for (index = 0; index < 10; index++) {
   1493         SHR_BITCLR(SOC_CONTROL(unit)->port_lls_l2_bmap[port],
   1494                 (mmu_port & 0x3f) * 10 + index);
   1495     }
   1496   
   1497     rval = 0;
   1498     SOC_IF_ERROR_RETURN(WRITE_HSP_SCHED_PORT_CONFIGr(unit, port, rval));
   1499     SOC_IF_ERROR_RETURN(WRITE_HSP_SCHED_L0_NODE_CONFIGr(unit, port, rval));
   1500     SOC_IF_ERROR_RETURN(WRITE_HSP_SCHED_L1_NODE_CONFIGr(unit, port, rval));
   1501     SOC_IF_ERROR_RETURN(WRITE_HSP_SCHED_L2_UC_QUEUE_CONFIGr(unit, port, rval));
   1502 
   1503     for (l0_index = 1; l0_index < 5; l0_index++) {
   1504         if (l0_index == 4) {
   1505             SOC_IF_ERROR_RETURN(
   1506                     WRITE_HSP_SCHED_L0_NODE_4_CONNECTION_CONFIGr(unit, port,
   1507                         rval));
   1508         } else { 
   1509             SOC_IF_ERROR_RETURN(
   1510                     WRITE_HSP_SCHED_L0_NODE_CONNECTION_CONFIGr(unit, port,
   1511                         l0_index - 1, rval));
   1512         }
   1513     }
   1514 
   1515     pbmf = IS_HSP_PORT_IN_XPIPEf;
   1516     SOC_IF_ERROR_RETURN(READ_HSP_SCHED_GLOBAL_CONFIGr(unit, &rval));
   1517     fval = soc_reg_field_get(unit, HSP_SCHED_GLOBAL_CONFIGr, rval, pbmf);
   1518     fval &= (~(1 << mmu_port));
   1519     soc_reg_field_set(unit, HSP_SCHED_GLOBAL_CONFIGr, &rval, pbmf, fval);
   1520     SOC_IF_ERROR_RETURN(WRITE_HSP_SCHED_GLOBAL_CONFIGr(unit, rval));
   1521     return SOC_E_NONE;
   1522 }
   1523 
   1524 /*
   1525  * Function:
   1526  *     _soc_monterey_lls_init
   1527  * Purpose:
   1528  *     This function initialises the structure _monterey_dyn_sched_unit_data, which is
   1529  *     used later to allocate the register available from  the set of 
   1530  *     SP_WERR_DYN_CHANGEnA/nB/nC (n=0,1,2,3) to the port and  to keep track 
   1531  *     of the used registers from the set for the port 
   1532  * Parameters:
   1533  *     unit       - (IN) unit number
   1534  * Returns:
   1535  *     SOC_E_XXX
   1536  */
   1537 STATIC int _soc_monterey_lls_init(int unit)
   1538 {
   1539     _soc_monterey_port_dyn_sched_t *pcb = NULL;
   1540     int i;
   1541     
   1542     if (soc_feature(unit, soc_feature_vector_based_spri)) {
   1543         pcb = &_monterey_dyn_sched_unit_data[unit];
   1544         
   1545         if (pcb->_soc_monterey_init_done[unit] == 1) {
   1546             return SOC_E_NONE;
   1547         }
   1548 
   1549         pcb->lock = sal_mutex_create("apache_dyn_lock");
   1550         for (i = 0; i < _SOC_MONTEREY_DYN_REGISTER_SET; i++) {
   1551             pcb->port[i] = -1;
   1552         }
   1553         pcb->_soc_monterey_init_done[unit] = 1;
   1554     }
   1555 
   1556     return SOC_E_NONE;
   1557 }
   1558 
   1559 int soc_monterey_lls_init(int unit)
   1560 {
   1561 
   1562     SOC_IF_ERROR_RETURN(_soc_monterey_lls_init(unit));
   1563 
   1564 
   1565     SOC_IF_ERROR_RETURN(soc_monterey_init_invalid_parents(unit));
   1566     
   1567     return SOC_E_NONE;
   1568 }
   1569 
   1570 int
   1571 soc_monterey_sched_hw_index_get(int unit, int port, int lvl, int offset, 
   1572                             int *hw_index)
   1573 {
   1574     int rv;
   1575 
   1576     rv = _soc_monterey_alloc_sched(unit, port, lvl, offset, hw_index);
   1577 
   1578     LOG_INFO(BSL_LS_SOC_COSQ,
   1579              (BSL_META_U(unit,
   1580                          "Alloced : port=%d lvl=%d ofst=%d Index=%d\n"),
   1581                                 port, lvl, offset, *hw_index));
   1582     return rv;
   1583 }
   1584 
   1585 int
   1586 soc_monterey_qcn_counter_hw_index_get(int unit, soc_port_t port,
   1587                                  int index, int *qindex)
   1588 {
   1589     soc_mem_t mem;
   1590     mmu_qcn_enable_entry_t entry;
   1591     int resolved_index = -1;    
   1592     
   1593     if (qindex == NULL) {
   1594         return SOC_E_PARAM;
   1595     }
   1596 
   1597     mem = MMU_QCN_ENABLE_0m;
   1598 
   1599     resolved_index = soc_monterey_l2_hw_index(unit, index, 1);
   1600     SOC_IF_ERROR_RETURN
   1601         (soc_mem_read(unit, mem, MEM_BLOCK_ANY, resolved_index, &entry));
   1602     if (soc_mem_field32_get(unit, mem, &entry, CPQ_ENf)) {
   1603         *qindex = soc_mem_field32_get(unit, mem, &entry, CPQ_IDf);
   1604     } else {
   1605         *qindex = -1;
   1606     }
   1607 
   1608     return SOC_E_NONE;
   1609 }
   1610 
   1611 
   1612 int 
   1613 soc_monterey_get_def_qbase(int unit, soc_port_t inport, int qtype, 
   1614                        int *pbase, int *pnumq)
   1615 {
   1616     soc_info_t *si;
   1617     int base, numq;
   1618 
   1619     si = &SOC_INFO(unit);
   1620 
   1621     if (qtype == _SOC_TD2_INDEX_STYLE_UCAST_QUEUE) {
   1622         base = si->port_uc_cosq_base[inport];
   1623         numq = si->port_num_uc_cosq[inport];
   1624     } else if (qtype == _SOC_TD2_INDEX_STYLE_MCAST_QUEUE) {
   1625         base = si->port_cosq_base[inport];
   1626         numq = si->port_num_cosq[inport];
   1627     } else {
   1628         return SOC_E_INTERNAL;
   1629     }
   1630 
   1631     if (pbase) {
   1632         *pbase = base;
   1633     }
   1634     if (pnumq) {
   1635         *pnumq = numq;
   1636     }
   1637     return SOC_E_NONE;
   1638 }
   1639 
   1640 STATIC int
   1641 _soc_monterey_dump_hsp_sched_at(int unit, int port, int level, int offset, int index)
   1642 {
   1643     uint32     rval = 0;
   1644     uint32     conn_map = 0;
   1645     uint32     l0_index, l1_index;
   1646     uint32     mc_group_mode = 0;
   1647     char       *lvl_name[] = { "Root","S1","L0", "L1", "UC", "MC" };
   1648     char       *sched_modes[] = {"X", "SP", "WRR", "WERR"};
   1649     uint32     num_spri =0;
   1650     uint32     first_child =0;
   1651     uint32     first_mc_child =0;
   1652     uint32     ucmap =0;
   1653     uint32     sched_mode =0;
   1654     int        uc_cosq, mc_cosq;
   1655     int        uc_cosq_base, mc_cosq_base;
   1656     int        uc_hw_index, mc_hw_index;
   1657     int        hw_index;
   1658     int        wt =0;
   1659     int        l2_index, l2_max_num = 1;
   1660     int mmu_port;
   1661 
   1662 
   1663     SOC_IF_ERROR_RETURN(soc_monterey_sched_hw_index_get(unit,
   1664                 port, SOC_MONTEREY_NODE_LVL_L1, 0, &uc_cosq_base));
   1665     mc_cosq_base = uc_cosq_base;
   1666 
   1667     uc_cosq = soc_monterey_logical_qnum_hw_qnum(unit, port, uc_cosq_base, 1);
   1668     mc_cosq = soc_monterey_logical_qnum_hw_qnum(unit, port, mc_cosq_base, 0);
   1669 
   1670     if (level != SOC_MONTEREY_NODE_LVL_ROOT) {
   1671         return SOC_E_PARAM;
   1672     }
   1673     if (IS_CPU_PORT(unit, port)) {
   1674         l2_max_num = 8; 
   1675     }
   1676     soc_monterey_port_common_attributes_get(unit, port, NULL, &mmu_port, NULL);
   1677     /* Root Node */
   1678     LOG_CLI((BSL_META_U(unit,
   1679                         "  %s.%d : INDEX=%d NUM_SPRI=%d FC=%d MODE=%s Wt=%d\n"),
   1680                         lvl_name[level], offset, index, num_spri, first_child,
   1681                         sched_modes[sched_mode], wt));
   1682 
   1683     SOC_IF_ERROR_RETURN(READ_HSP_SCHED_PORT_CONFIGr(unit, port, &rval));
   1684     mc_group_mode = soc_reg_field_get(unit, HSP_SCHED_PORT_CONFIGr,
   1685                                       rval, MC_GROUP_MODEf);
   1686     /* L0 Node */
   1687     for (l0_index = 0; l0_index < 5; l0_index++) {
   1688         /* print the L0 Nodes*/
   1689         level = SOC_MONTEREY_NODE_LVL_L0;
   1690         SOC_IF_ERROR_RETURN(soc_monterey_sched_hw_index_get(unit,
   1691                          port, level, l0_index, &hw_index));
   1692         soc_monterey_cosq_get_sched_mode(unit, port, SOC_MONTEREY_NODE_LVL_L0,
   1693                                      hw_index, &sched_mode, &wt);
   1694         LOG_CLI((BSL_META_U(unit,
   1695                             "  %s.%d : INDEX=%d NUM_SPRI=%d FC=%d MODE=%s Wt=%d\n"),
   1696                             lvl_name[level], l0_index, hw_index, num_spri, first_child,
   1697                             sched_modes[sched_mode], wt));
   1698 
   1699         /* read Connection map for the  L0.1, L0.2, L0.3, L0.4, L0.5
   1700          * by default connection map should be set to all zeros for L0.0
   1701          */
   1702         if (l0_index == 4) {
   1703             SOC_IF_ERROR_RETURN(READ_HSP_SCHED_L0_NODE_4_CONNECTION_CONFIGr(
   1704                                      unit, port, &rval));
   1705             conn_map = soc_reg_field_get(unit,
   1706                                 HSP_SCHED_L0_NODE_4_CONNECTION_CONFIGr,
   1707                                 rval, CHILDREN_CONNECTION_MAP_4f);
   1708         } else if (l0_index > 0) { 
   1709             SOC_IF_ERROR_RETURN(READ_HSP_SCHED_L0_NODE_CONNECTION_CONFIGr(
   1710                                      unit, port, l0_index - 1, &rval));
   1711             conn_map = soc_reg_field_get(unit,
   1712                                 HSP_SCHED_L0_NODE_CONNECTION_CONFIGr,
   1713                                 rval, CHILDREN_CONNECTION_MAPf);
   1714         }
   1715         if ((l0_index >= 1) && (l0_index <= 4)) {
   1716             for (l1_index = 0; l1_index < 8; l1_index++) {
   1717                 if (conn_map & (1U<<l1_index)) {
   1718                     if (l0_index == 4) {
   1719                         offset = l1_index + 8;
   1720                     } else {
   1721                         offset = l1_index;
   1722                     }
   1723                     /* print L1 node */
   1724                     level = SOC_MONTEREY_NODE_LVL_L1;
   1725                     SOC_IF_ERROR_RETURN(soc_monterey_sched_hw_index_get(unit,
   1726                         port, level, offset, &hw_index));
   1727                     soc_monterey_cosq_get_sched_mode(unit, port, SOC_MONTEREY_NODE_LVL_L1,
   1728                                                 hw_index, &sched_mode, &wt);
   1729                     if (IS_CPU_PORT(unit, port)) {
   1730                         num_spri = 0;
   1731                         for (l2_index = 0; l2_index < l2_max_num; l2_index++) {
   1732                              mc_hw_index = soc_monterey_l2_hw_index(unit, mc_cosq_base + l2_index, 0);
   1733                              soc_monterey_cosq_get_sched_mode(unit, port, SOC_MONTEREY_NODE_LVL_L2,
   1734                                                               mc_hw_index, &sched_mode, &wt);
   1735                              if (wt == 0) {
   1736                                  num_spri++;
   1737                              }
   1738                         }
   1739                     }
   1740                     LOG_CLI((BSL_META_U(unit,
   1741                                         "  %s.%d : INDEX=%d NUM_SP=%d FC=%d "
   1742                                         "FMC=%d UCMAP=0x%08x MODE=%s WT=%d\n"),
   1743                                         lvl_name[level], offset, hw_index, num_spri,
   1744                                         first_child, first_mc_child, ucmap,
   1745                                         sched_modes[sched_mode], wt));
   1746                     for (l2_index = 0; l2_index < l2_max_num; l2_index++) {
   1747                          /* print L2 UC node attached to L1 */
   1748                          uc_hw_index = soc_monterey_l2_hw_index(unit, uc_cosq_base, 1);
   1749                          soc_monterey_cosq_get_sched_mode(unit, port,
   1750                                                     SOC_MONTEREY_NODE_LVL_L2,
   1751                                                     uc_hw_index, &sched_mode, &wt);
   1752                          if (uc_cosq < 640) {
   1753                              LOG_CLI((BSL_META_U(unit,
   1754                                                  "    L2.uc : INDEX=%d Mode=%s WEIGHT=%d\n"),
   1755                                                  uc_cosq, sched_modes[sched_mode], wt));
   1756                          }
   1757                          uc_cosq_base++;
   1758                          uc_cosq++;
   1759 
   1760                          if (((mc_group_mode == 1) && (l0_index == 4)) ||
   1761                              (mc_group_mode == 0)) {
   1762                              /* print L2 MC node attached to L1 */
   1763                              /* MC_GROUP_MODE = 1 then  8 MC Cos queues are
   1764                               * grouped together and shared the parent (L0.0) bandwidth.
   1765                               * MC_QM and MC_SC queues are still paired with
   1766                               * UC_QM and UC_SC respectivly
   1767                               */
   1768                              mc_hw_index = soc_monterey_l2_hw_index(unit, mc_cosq_base, 0);
   1769                              soc_monterey_cosq_get_sched_mode(unit, port,
   1770                                                         SOC_MONTEREY_NODE_LVL_L2,
   1771                                                         mc_hw_index, &sched_mode, &wt);
   1772                              LOG_CLI((BSL_META_U(unit,
   1773                                                  "    L2.mc : INDEX=%d Mode=%s WEIGHT=%d\n"),
   1774                                                  mc_cosq, sched_modes[sched_mode], wt));
   1775                              mc_cosq_base++;
   1776                              mc_cosq++;
   1777                           }
   1778                       }
   1779                    }
   1780             }
   1781         } else if (l0_index == 0) {
   1782             if (mc_group_mode) {
   1783                 offset = 0;
   1784                 for (l1_index = 0; l1_index < 8; l1_index++) {
   1785                     /* 8 MC Cos queues are grouped together and shared
   1786                      * the parent (L0.0) bandwidth.
   1787                      */
   1788                     mc_hw_index = soc_monterey_l2_hw_index(unit, mc_cosq_base + offset, 0);
   1789                     soc_monterey_cosq_get_sched_mode(unit, port,
   1790                                                     SOC_MONTEREY_NODE_LVL_L2,
   1791                                                     mc_hw_index, &sched_mode, &wt);
   1792                     LOG_CLI((BSL_META_U(unit,
   1793                                         "    L2.mc : INDEX=%d Mode=%s WEIGHT=%d\n"),
   1794                                         mc_cosq + offset, sched_modes[sched_mode], wt));
   1795                     offset++;
   1796                 }
   1797 
   1798             }
   1799         }
   1800     }
   1801 
   1802    return SOC_E_NONE;
   1803 }
   1804 
   1805 STATIC int
   1806 _soc_monterey_child_num_get(int unit, int port, int level, int hw_index, int *count)
   1807 {
   1808     soc_mem_t mem;
   1809     int cindex, index_max, ii, child_level, num_child = 0;
   1810     uint32 entry[SOC_MAX_MEM_WORDS];
   1811 
   1812     soc_monterey_get_child_type(unit, port, level, &child_level);
   1813     mem = _SOC_MONTEREY_NODE_PARENT_MEM(unit, port, child_level);
   1814 
   1815     if (mem == INVALIDm) {
   1816         return SOC_E_INTERNAL;
   1817     }
   1818     index_max = soc_mem_index_max(unit, mem);
   1819 
   1820     for (ii = 0; ii <= index_max; ii++) {
   1821         SOC_IF_ERROR_RETURN(
   1822                 soc_mem_read(unit, mem, MEM_BLOCK_ALL, ii, &entry));
   1823 
   1824         cindex = soc_mem_field32_get(unit, mem, entry, C_PARENTf);
   1825 
   1826         if (cindex == hw_index) {
   1827             num_child += 1;
   1828         }
   1829     }
   1830 
   1831     if (count != NULL) {
   1832         *count = num_child;
   1833     }
   1834 
   1835     return SOC_E_NONE;
   1836 }
   1837 
   1838 
   1839 STATIC int 
   1840 _soc_monterey_dump_sched_at(int unit, int port, int level, int offset, int hw_index)
   1841 {
   1842     int num_spri = 0, first_child = 0, first_mc_child, rv, cindex;
   1843     uint32 ucmap, spmap;
   1844     soc_monterey_sched_mode_e sched_mode;
   1845     soc_mem_t mem;
   1846     int index_max, ii, ci, child_level, wt = 0, num_child;
   1847     uint32 entry[SOC_MAX_MEM_WORDS];
   1848     char *lvl_name[] = { "Root", "S1",  "L0", "L1", "L2" };
   1849     char *sched_modes[] = {"X", "SP", "WRR", "WDRR"};
   1850     int num_s1_children = 0;
   1851 
   1852     if (level < SOC_MONTEREY_NODE_LVL_L2) {
   1853         soc_monterey_get_child_type(unit, port, level, &child_level);
   1854         if (hw_index == INVALID_PARENT(unit, child_level)) {
   1855             /* 
   1856              * INVALID_PARENT(L0) may be zero. 
   1857              * When this condition occurs, 
   1858              * we need to do further check instead of returning.
   1859              */
   1860             if (!((child_level == SOC_MONTEREY_NODE_LVL_S1) &&
   1861                 (hw_index == 0))) {
   1862                 return SOC_E_NONE;
   1863             }
   1864         }
   1865     }
   1866 
   1867     if (level != SOC_MONTEREY_NODE_LVL_ROOT) { 
   1868         /* get sched config */
   1869         SOC_IF_ERROR_RETURN(
   1870                 soc_monterey_cosq_get_sched_child_config(unit, port, level, hw_index, 
   1871                     &num_spri, &first_child, &first_mc_child, &ucmap, &spmap));
   1872     } 
   1873 
   1874     sched_mode = 0;
   1875     if (level != SOC_MONTEREY_NODE_LVL_ROOT) { 
   1876         SOC_IF_ERROR_RETURN(
   1877           soc_monterey_cosq_get_sched_mode(unit, port, level, hw_index, &sched_mode, &wt));
   1878     }
   1879     
   1880     if (level == SOC_MONTEREY_NODE_LVL_L1) {
   1881         LOG_CLI((BSL_META_U(unit,
   1882                             "  %s.%d : INDEX=%d NUM_SP=%d FC=%d "
   1883                             "FMC=%d UCMAP=0x%08x MODE=%s WT=%d\n"),
   1884                             lvl_name[level], offset, hw_index, num_spri, 
   1885                             first_child, first_mc_child, ucmap, 
   1886                             sched_modes[sched_mode], wt));
   1887     } else {
   1888         if (soc_feature(unit, soc_feature_mmu_hqos_four_level))
   1889         {
   1890             LOG_CLI((BSL_META_U(unit,
   1891                                 "  %s.%d : INDEX=%d NUM_SPRI=%d FC=%d MODE=%s Wt=%d\n"),
   1892                                 lvl_name[level], offset, hw_index, num_spri, first_child,
   1893                                 sched_modes[sched_mode],
   1894                                 wt));
   1895         } else 
   1896         {    
   1897             if (level != SOC_MONTEREY_NODE_LVL_ROOT)  
   1898             {
   1899                 if (level == SOC_MONTEREY_NODE_LVL_S1) { 
   1900                     LOG_CLI((BSL_META_U(unit,
   1901                                      "  %s.%d : INDEX=%d NUM_SPRI=%d FC=%d MODE=%s Wt=%d\n"),
   1902                                      lvl_name[level-1 ], offset, hw_index, num_spri, first_child,
   1903                                      sched_modes[sched_mode],
   1904                                      wt));
   1905                 }
   1906                 else 
   1907                 {
   1908                     LOG_CLI((BSL_META_U(unit,
   1909                                      "  %s.%d : INDEX=%d NUM_SPRI=%d FC=%d MODE=%s Wt=%d\n"),
   1910                                      lvl_name[level], offset, hw_index, num_spri, first_child,
   1911                                      sched_modes[sched_mode],
   1912                                      wt));
   1913 
   1914                }
   1915             }             
   1916         }
   1917     }
   1918 
   1919     soc_monterey_get_child_type(unit, port, level, &child_level);
   1920     mem = _SOC_MONTEREY_NODE_PARENT_MEM(unit, port, child_level);
   1921     
   1922     if(mem == INVALIDm) {
   1923         return SOC_E_INTERNAL;
   1924     }
   1925     index_max = soc_mem_index_max(unit, mem);
   1926 
   1927     num_child = 0;
   1928     for (ii = 0, ci = 0; ii <= index_max; ii++) {
   1929         rv = soc_mem_read(unit, mem, MEM_BLOCK_ALL, ii, &entry);
   1930         if (rv) {
   1931             LOG_CLI((BSL_META_U(unit,
   1932                                 "Failed to read memory at index: %d\n"), ii));
   1933             break;
   1934         }
   1935         
   1936         cindex = soc_mem_field32_get(unit, mem, entry,
   1937                 child_level == SOC_MONTEREY_NODE_LVL_S1 ? P_PORTf : 
   1938                 C_PARENTf);
   1939 
   1940         /*
   1941          * INVALID_PARENT(L0) may be zero.
   1942          * When this condition occurs,
   1943          * we should get the node`s child count to decide
   1944          * if it is a valid node or not.
   1945          */
   1946         if ((cindex == 0) && (child_level == SOC_MONTEREY_NODE_LVL_S1)) {
   1947             _soc_monterey_child_num_get(unit, port, child_level,
   1948                                         ii, &num_s1_children);
   1949             if (num_s1_children == 0) {
   1950                 continue;
   1951             }
   1952         }
   1953 
   1954         if (cindex == hw_index) {
   1955             if (child_level == SOC_MONTEREY_NODE_LVL_L2) {
   1956                 SOC_IF_ERROR_RETURN(soc_monterey_cosq_get_sched_mode(unit, port,
   1957                                     SOC_MONTEREY_NODE_LVL_L2, ii, &sched_mode, &wt));
   1958                 LOG_CLI((BSL_META_U(unit,
   1959                                     "     L2.%s INDEX=%d Mode=%s WEIGHT=%d\n"), 
   1960                                     ((ii < _MN_MAX_NUM_UC_QUEUE(unit)) ? "uc" : "mc"),
   1961                                     ii, sched_modes[sched_mode], wt));
   1962             } else {
   1963                 _soc_monterey_dump_sched_at(unit, port, child_level, ci, ii);
   1964                 ci += 1;
   1965             }
   1966             num_child += 1;
   1967         }
   1968     }
   1969     if (num_child == 0) {
   1970         LOG_CLI((BSL_META_U(unit,
   1971                             "*** No children \n")));
   1972     }
   1973     return SOC_E_NONE;
   1974 }
   1975 
   1976 int soc_monterey_dump_port_lls(int unit, int port)
   1977 {
   1978     int mmu_port, index;
   1979 
   1980     if (_soc_monterey_port_sched_type_get(unit, port) == SOC_MONTEREY_SCHED_HSP) {
   1981         return SOC_E_NONE;
   1982     }
   1983 
   1984     soc_monterey_port_common_attributes_get(unit, port, NULL, &mmu_port, NULL);
   1985 
   1986     LOG_CLI((BSL_META_U(unit,
   1987                         "-------%s (LLS)------\n"), SOC_PORT_NAME(unit, (port))));
   1988     index = _soc_monterey_root_scheduler_index(unit, port);
   1989     _soc_monterey_dump_sched_at(unit, port, SOC_MONTEREY_NODE_LVL_ROOT, 0, index);
   1990     return SOC_E_NONE;
   1991 }
   1992 int soc_monterey_dump_port_hsp(int unit, int port)
   1993 {
   1994     int mmu_port, index;
   1995 
   1996     if (_soc_monterey_port_sched_type_get(unit, port) == SOC_MONTEREY_SCHED_LLS) {
   1997         return SOC_E_NONE;
   1998     }
   1999 
   2000     soc_monterey_port_common_attributes_get(unit, port, NULL, &mmu_port, NULL);
   2001 
   2002     LOG_CLI((BSL_META_U(unit,
   2003                         "-------%s (HSP)------\n"), SOC_PORT_NAME(unit, (port))));
   2004     index = _soc_monterey_root_scheduler_index(unit, port);
   2005     _soc_monterey_dump_hsp_sched_at(unit, port, SOC_MONTEREY_NODE_LVL_ROOT, 0, index);
   2006     return SOC_E_NONE;
   2007 }
   2008 
   2009 int soc_monterey_logical_qnum_hw_qnum(int unit, int port, int lqnum, int uc)
   2010 {
   2011     if (uc) {
   2012         return lqnum;
   2013     } else {
   2014         return lqnum + 640;
   2015     }
   2016     return -1;
   2017 }
   2018 
   2019 int soc_monterey_mmu_get_shared_size(int unit, int *shared_size)
   2020 {
   2021     uint32 entry0[SOC_MAX_MEM_WORDS];
   2022 
   2023     sal_memset(entry0, 0, sizeof(mmu_thdu_xpipe_config_queue_entry_t));
   2024     SOC_IF_ERROR_RETURN
   2025         (soc_mem_read(unit, MMU_THDU_XPIPE_CONFIG_QUEUEm, MEM_BLOCK_ALL, 0, entry0));
   2026     *shared_size = soc_mem_field32_get(unit, MMU_THDU_XPIPE_CONFIG_QUEUEm, entry0, Q_SHARED_LIMIT_CELLf);
   2027     return 1;
   2028 }
   2029 
   2030 int soc_monterey_mmu_config_res_limits_update(int unit, uint32 spid, 
   2031                                                       uint32 shared_size, int flags)
   2032 {
   2033     return soc_monterey_mmu_config_shared_buf_recalc(unit, spid, shared_size, flags);
   2034 }
   2035 
   2036 void
   2037 soc_monterey_shadow_free(int unit)
   2038 {
   2039     int mem_idx;
   2040     soc_monterey_shadow_memory_t * shadow_info;
   2041     soc_monterey_shadow_t* shadow_ctrl = &soc_monterey_shadow[unit];
   2042     
   2043     if (shadow_ctrl->shadow_array != NULL) {
   2044         for (mem_idx = 0; mem_idx < shadow_ctrl->mem_count; mem_idx++){
   2045             shadow_info = &(shadow_ctrl->shadow_array[mem_idx]);
   2046             if (shadow_info->mem_shadow != NULL){
   2047                 sal_free(shadow_info->mem_shadow);
   2048             }
   2049         }
   2050     sal_free(shadow_ctrl->shadow_array);
   2051     shadow_ctrl->shadow_array = NULL;
   2052     shadow_ctrl->mem_count = 0;
   2053     }
   2054 }
   2055 
   2056 int
   2057 soc_monterey_shadow_create(int unit)
   2058 {
   2059 	  int mem_idx, alloc_size, num_entries, entry_size;
   2060 	  soc_monterey_shadow_memory_t* shadow_info = NULL;
   2061 	  uint32* shadow = NULL;
   2062     
   2063           if (soc_monterey_shadow[unit].shadow_array) {
   2064               soc_monterey_shadow_free(unit); 
   2065           } 
   2066           alloc_size = sizeof(soc_monterey_shadow_memory_t) *
   2067                       COUNTOF(shadow_mems);
   2068           shadow_info = sal_alloc(alloc_size, "fc map shadow control");
   2069           if (shadow_info == NULL) {
   2070               return SOC_E_MEMORY;
   2071           }
   2072         
   2073           sal_memset(shadow_info, 0, alloc_size);
   2074           soc_monterey_shadow[unit].shadow_array = shadow_info;
   2075     
   2076           for (mem_idx = 0; mem_idx < COUNTOF(shadow_mems); mem_idx++) {
   2077                num_entries = soc_mem_index_count(unit, shadow_mems[mem_idx]);
   2078                /* for OBM classifier tables we need space for two pgws */
   2079                if (mem_idx >= 2) {
   2080                num_entries = num_entries * 2;
   2081                }
   2082                entry_size = soc_mem_entry_words(unit, shadow_mems[mem_idx]);
   2083                alloc_size = entry_size * num_entries * sizeof(uint32);
   2084                shadow = sal_alloc(alloc_size, "fc map shadow tbl");
   2085                if (shadow == NULL) {
   2086                    soc_monterey_shadow_free(unit);
   2087                    return SOC_E_MEMORY;
   2088                }
   2089                sal_memset(shadow, 0, alloc_size);
   2090                soc_monterey_shadow[unit].shadow_array[mem_idx].mem_shadow = shadow;
   2091                soc_monterey_shadow[unit].shadow_array[mem_idx].mem = shadow_mems[mem_idx];
   2092                soc_monterey_shadow[unit].mem_count++;
   2093           }
   2094     return SOC_E_NONE; 
   2095 }
   2096 
   2097 int
   2098 soc_monterey_shadow_entry_get (int unit, soc_mem_t mem, int index,
   2099                                       void* entry_data)
   2100 {
   2101     int mem_idx, entry_words;
   2102     uint32 * shadow = NULL;
   2103     
   2104     SOC_IF_ERROR_RETURN(soc_monterey_shadow_get_mem_idx(unit, mem, &mem_idx));
   2105     shadow = soc_monterey_shadow[unit].shadow_array[mem_idx].mem_shadow;
   2106     entry_words = soc_mem_entry_words(unit, mem);
   2107     sal_memcpy(entry_data, shadow + index * entry_words, 
   2108                entry_words * sizeof(uint32));
   2109     return SOC_E_NONE;
   2110 }
   2111 
   2112 int
   2113 soc_monterey_shadow_entry_set (int unit, soc_mem_t mem, int index,
   2114                                       void* entry_data)
   2115 {
   2116     int mem_idx, entry_words;
   2117     uint32 * shadow = NULL;
   2118     
   2119     SOC_IF_ERROR_RETURN(soc_monterey_shadow_get_mem_idx(unit, mem, &mem_idx));
   2120     shadow = soc_monterey_shadow[unit].shadow_array[mem_idx].mem_shadow;
   2121     entry_words = soc_mem_entry_words(unit, mem);
   2122     sal_memcpy(shadow + index * entry_words, entry_data, 
   2123                entry_words * sizeof(uint32));
   2124     return SOC_E_NONE;
   2125 }
   2126 
   2127 int 
   2128 soc_monterey_shadow_clear (int unit, soc_mem_t mem)
   2129 {
   2130     uint32 * shadow = NULL;
   2131     int entry_words, tbl_size, mem_idx, num_entries;
   2132 
   2133     SOC_IF_ERROR_RETURN(soc_monterey_shadow_get_mem_idx(unit, mem, &mem_idx));
   2134     entry_words = soc_mem_entry_words(unit, mem);
   2135     shadow = soc_monterey_shadow[unit].shadow_array[mem_idx].mem_shadow;
   2136     num_entries = soc_mem_index_count(unit, shadow_mems[mem_idx]);
   2137     tbl_size = entry_words * num_entries;
   2138     if (shadow != NULL) {
   2139         sal_memset(shadow, 0, tbl_size * sizeof(uint32));
   2140     }
   2141     return SOC_E_NONE;
   2142 }
   2143 
   2144 int _soc_monterey_obm_interrupt_cb(int unit) {
   2145 
   2146      bcm_obm_interrupt_info_t obm_info;
   2147      int pgw = 0  ;
   2148      bcm_obm_callback_fn cb;
   2149      soc_info_t *si;
   2150      soc_reg_t  reg;
   2151      int pgw_inst = 0 ;
   2152      uint64 rval64; 
   2153      soc_field_t field;
   2154      int port = 0,phy_port = 0  ;
   2155      int temp =0 ;
   2156      void *user_data =soc_monterey_obm_cb[unit].user_data;  
   2157      si = &SOC_INFO(unit);
   2158     for (pgw = 0; pgw < MONTEREY_PGWS_PER_DEV ;pgw++)
   2159     {
   2160          pgw_inst = (pgw | SOC_REG_ADDR_INSTANCE_MASK);
   2161          reg = PGW_CA_OVERFLOW_STATUSr;
   2162          field = CA_PREEMPT_OVERFLOWf;
   2163          SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, pgw_inst ,0, &rval64));
   2164          temp = soc_reg64_field32_get(unit, reg, rval64, field);
   2165          if(temp ) {
   2166             obm_info.interrupt_type = bcmObmInterruptTypePreemptOverflow;
   2167             break;
   2168          }
   2169          field = CA_EXP_OVERFLOWf;
   2170          temp = soc_reg64_field32_get(unit, reg, rval64, field);
   2171          if(temp ) {
   2172             obm_info.interrupt_type = bcmObmInterruptTypeExpressOverflow;
   2173             break;
   2174          }
   2175 
   2176          reg = PGW_OBM_DROP_STATUSr;
   2177          field = EXP_DROP_ERRf ;
   2178          SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, pgw_inst,0, &rval64));
   2179          temp = soc_reg64_field32_get(unit, reg, rval64, field);
   2180          if(temp ) {
   2181             obm_info.interrupt_type  = bcmObmInterruptTypeExpressDrop ;
   2182             break;
   2183          }
   2184          field = PREEMPT_DROP_ERRf;
   2185          temp = soc_reg64_field32_get(unit, reg, rval64, field);
   2186          if(temp ) {
   2187             obm_info.interrupt_type = bcmObmInterruptTypePreemptDrop;
   2188             break;
   2189          }
   2190      }
   2191      if (!temp) {
   2192          return SOC_E_NONE;
   2193      }
   2194      PBMP_ALL_ITER(unit, port) {
   2195         if (port == 0  ) {
   2196             continue; 
   2197         } 
   2198         phy_port = si->port_l2p_mapping[port];
   2199         if ((pgw == 1) && (phy_port <= 32)) 
   2200         {
   2201              continue; 
   2202         }   
   2203         if (phy_port > 32) {
   2204             phy_port = phy_port - 32;
   2205         }
   2206         if (temp & (1 << (phy_port-1))) {
   2207             obm_info.port = port;
   2208             break;
   2209         }
   2210      }
   2211      cb=soc_monterey_obm_cb[unit].cb;
   2212      if (cb) {
   2213             (void)(*cb)(unit ,&obm_info, user_data);
   2214      }
   2215      return SOC_E_NONE;
   2216 
   2217 }
   2218 
   2219 #ifdef BCM_WARM_BOOT_SUPPORT
   2220 int
   2221 soc_monterey_shadow_size_get (int unit, uint32 * size)
   2222 {
   2223     int alloc_size = 0, mem_idx, num_entries, entry_size;
   2224     for (mem_idx = 0; mem_idx < COUNTOF(shadow_mems); mem_idx++) {
   2225         num_entries = soc_mem_index_count(unit, shadow_mems[mem_idx]);
   2226         entry_size = soc_mem_entry_words(unit, shadow_mems[mem_idx]);
   2227         if (mem_idx >= 2) {
   2228             num_entries = num_entries * 2;
   2229         }
   2230         alloc_size += entry_size * num_entries * sizeof(uint32);
   2231     }
   2232     *size = alloc_size;
   2233     return SOC_E_NONE;
   2234 }
   2235 
   2236 int
   2237 soc_monterey_shadow_sync (int unit, uint32 **sync_addr)
   2238 {
   2239     int mem_idx, num_entries, tbl_size, entry_size;
   2240 
   2241     for (mem_idx = 0; mem_idx < COUNTOF(shadow_mems); mem_idx++) {
   2242         num_entries = soc_mem_index_count(unit, shadow_mems[mem_idx]);
   2243         if (mem_idx >= 2) {
   2244             num_entries = num_entries * 2;
   2245         }
   2246         entry_size = soc_mem_entry_words(unit, shadow_mems[mem_idx]);
   2247         tbl_size = entry_size * num_entries;
   2248         sal_memcpy(*sync_addr, soc_monterey_shadow[unit].shadow_array[mem_idx].mem_shadow,
   2249                    tbl_size * sizeof(uint32));
   2250         *sync_addr += tbl_size;
   2251     }
   2252     return SOC_E_NONE;
   2253 }
   2254 
   2255 int
   2256 soc_monterey_shadow_load (int unit, uint32 **load_addr)
   2257 {
   2258     int blk, mem_idx, num_entries;
   2259     int tbl_size, entry_size, vmap_size;
   2260     uint32 *cache;
   2261     uint32 *shadow;
   2262     uint8 *vmap;
   2263     int index_min;
   2264     soc_mem_t mem;
   2265     
   2266     for (mem_idx = 0; mem_idx < COUNTOF(shadow_mems); mem_idx++) {
   2267         mem = shadow_mems[mem_idx];
   2268         num_entries = soc_mem_index_count(unit, mem);
   2269         if (mem_idx >= 2) {
   2270             num_entries = num_entries * 2;
   2271         }
   2272         entry_size = soc_mem_entry_words(unit, mem);
   2273         index_min = soc_mem_index_min(unit, mem);
   2274         tbl_size = entry_size * num_entries;
   2275         sal_memcpy(soc_monterey_shadow[unit].shadow_array[mem_idx].mem_shadow, *load_addr,
   2276                    tbl_size * sizeof(uint32));
   2277         *load_addr += tbl_size;
   2278         /* restore memory cache */
   2279         vmap_size = (num_entries + 7) / 8;
   2280         SOC_MEM_BLOCK_ITER(unit, mem, blk) {
   2281             if (SOC_MEM_STATE(unit, mem).cache[blk] == NULL) {
   2282                 continue;
   2283             }
   2284             cache = SOC_MEM_STATE(unit, mem).cache[blk];
   2285             vmap = SOC_MEM_STATE(unit, mem).vmap[blk];
   2286             shadow = soc_monterey_shadow[unit].shadow_array[mem_idx].mem_shadow;
   2287             sal_memcpy(cache, shadow, tbl_size * sizeof(uint32));
   2288         
   2289             sal_memset(&vmap[index_min / 8], 0xff, 
   2290                       (num_entries + 7 - index_min) / 8);
   2291                 
   2292             /* Clear invalid bits at the left and right ends */
   2293             vmap[index_min / 8] &= 0xff00 >> (8 - index_min % 8);
   2294             vmap[vmap_size - 1] &= 0x00ff >> ((8 - num_entries % 8) % 8);
   2295         }
   2296     }
   2297     return SOC_E_NONE;
   2298 }
   2299 #endif
   2300 
   2301 #undef _ERR_MSG_MODULE_NAME /* debug */
   2302 
   2303 #endif /* BCM_MONTEREY_SUPPORT */
   2304