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


      1 /*
      2  * 
      3  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      4  * 
      5  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      6  *
      7  * MMU/Cosq soc routines
      8  */
      9 
     10 #include <sal/core/libc.h>
     11 
     12 #include <soc/debug.h>
     13 #include <soc/util.h>
     14 #include <soc/mem.h>
     15 #include <soc/trident2.h>
     16 #include <soc/tomahawk.h>
     17 #include <shared/bsl.h>
     18 #if defined(BCM_TOMAHAWK2_SUPPORT)
     19 #include <soc/tomahawk2.h>
     20 #endif
     21 #include <soc/mmu_config.h>
     22 #if defined(BCM_TOMAHAWK_SUPPORT)
     23 
     24 #define TH_MMU_PER_PIPE_PORT_OFFSET 64
     25 #define TH_MMU_GP_UCQ_NUM           320 /* Generl ports UC Queue Num in per Pipe Queue Number Space */
     26 #define TH_MMU_MGMT_UCQ_NUM         10  /* Management port UC Queues Num in Pipe Queue Number */
     27 #define TH_MMU_GP_MCQ_NUM           320 /* Generl ports MC Queue Num in per Pipe Queue Number Space */
     28 #define TH_MMU_LB_MCQ_NUM           10  /* Loopback port MC Queue Num in per Pipe Queue Number Space */
     29 #define TH_MMU_LB_MCQ_OFFSET       ((TH_MMU_GP_UCQ_NUM) + (TH_MMU_MGMT_UCQ_NUM) + \
     30                                      (TH_MMU_GP_MCQ_NUM))
     31 #define TH_MMU_CPU_MCQ_OFFSET      (TH_MMU_LB_MCQ_OFFSET + TH_MMU_LB_MCQ_NUM)
     32 #define TH_MMU_MGMT_UCQ_OFFSET     (TH_MMU_GP_UCQ_NUM)
     33 #define TH_MMU_MGMT_MCQ_OFFSET     (TH_MMU_LB_MCQ_OFFSET + TH_MMU_LB_MCQ_NUM)
     34 
     35 int
     36 soc_th_sched_weight_set(int unit, int port, int level,
     37                         int index, int weight, int mc)
     38 {
     39     soc_info_t *si;
     40     soc_mem_t mem = INVALIDm;
     41     uint32 entry[SOC_MAX_MEM_WORDS];
     42     int phy_port, mmu_port, pipe;
     43 
     44     si = &SOC_INFO(unit);
     45 
     46     pipe = si->port_pipe[port];
     47     phy_port = si->port_l2p_mapping[port];
     48     mmu_port = si->port_p2m_mapping[phy_port];
     49 
     50     if (level == SOC_TH_NODE_LVL_L0) {
     51         mem = Q_SCHED_L0_WEIGHT_MEMm;
     52         index = ((mmu_port % TH_MMU_PER_PIPE_PORT_OFFSET)  * 10) + index
     53                 + (mc ? SOC_TH_NUM_UC_QUEUES_PER_PIPE : 0);
     54     } else if (level == SOC_TH_NODE_LVL_L1) {
     55         mem = Q_SCHED_L1_WEIGHT_MEMm;
     56 
     57         if (IS_CPU_PORT(unit, port)) {
     58             index = TH_MMU_CPU_MCQ_OFFSET + index;
     59         } else if (IS_LB_PORT(unit, port)) {
     60             index = TH_MMU_LB_MCQ_OFFSET + index;
     61         } else if (SOC_PBMP_MEMBER(si->management_pbm, port)) {
     62             index = (mc ? TH_MMU_MGMT_MCQ_OFFSET : TH_MMU_MGMT_UCQ_OFFSET) + index;
     63         } else {
     64             index = ((mmu_port % TH_MMU_PER_PIPE_PORT_OFFSET)  * 10) + index
     65                     + (mc ? SOC_TH_NUM_UC_QUEUES_PER_PIPE : 0);
     66         }
     67     } else {
     68         return SOC_E_PARAM;
     69     }
     70 
     71     mem = SOC_MEM_UNIQUE_ACC(unit, mem)[pipe];
     72 
     73     SOC_IF_ERROR_RETURN
     74         (soc_mem_read(unit, mem, MEM_BLOCK_ALL, index, &entry));
     75     soc_mem_field32_set(unit, mem, &entry, WEIGHTf, weight);
     76     SOC_IF_ERROR_RETURN
     77         (soc_mem_write(unit, mem, MEM_BLOCK_ALL, index, &entry));
     78 
     79     return SOC_E_NONE;
     80 }
     81 
     82 int
     83 soc_th_sched_weight_get(int unit, int port, int level,
     84                         int index, int *weight, int mc)
     85 {
     86     soc_info_t *si;
     87     soc_mem_t mem = INVALIDm;
     88     uint32 entry[SOC_MAX_MEM_WORDS];
     89     int phy_port, mmu_port, pipe;
     90 
     91     si = &SOC_INFO(unit);
     92 
     93     pipe = si->port_pipe[port];
     94     phy_port = si->port_l2p_mapping[port];
     95     mmu_port = si->port_p2m_mapping[phy_port];
     96 
     97     if (level == SOC_TH_NODE_LVL_L0) {
     98         mem = Q_SCHED_L0_WEIGHT_MEMm;
     99         index = ((mmu_port % TH_MMU_PER_PIPE_PORT_OFFSET)  * 10) + index
    100                 + (mc ? SOC_TH_NUM_UC_QUEUES_PER_PIPE : 0);
    101     } else if (level == SOC_TH_NODE_LVL_L1) {
    102         mem = Q_SCHED_L1_WEIGHT_MEMm;
    103 
    104         if (IS_CPU_PORT(unit, port)) {
    105             index = TH_MMU_CPU_MCQ_OFFSET + index;
    106         } else if (IS_LB_PORT(unit, port)) {
    107             index = TH_MMU_LB_MCQ_OFFSET + index;
    108         } else if (SOC_PBMP_MEMBER(si->management_pbm, port)) {
    109             index = (mc ? TH_MMU_MGMT_MCQ_OFFSET : TH_MMU_MGMT_UCQ_OFFSET) + index;
    110         } else {
    111             index = ((mmu_port % TH_MMU_PER_PIPE_PORT_OFFSET)  * 10) + index
    112                     + (mc ? SOC_TH_NUM_UC_QUEUES_PER_PIPE : 0);
    113         }
    114     } else {
    115         return SOC_E_PARAM;
    116     }
    117 
    118     mem = SOC_MEM_UNIQUE_ACC(unit, mem)[pipe];
    119     SOC_IF_ERROR_RETURN
    120         (soc_mem_read(unit, mem, MEM_BLOCK_ALL, index, &entry));
    121     *weight = soc_mem_field32_get(unit, mem, &entry, WEIGHTf);
    122 
    123     return SOC_E_NONE;
    124 }
    125 
    126 int
    127 soc_th_cosq_sched_mode_set(int unit, soc_port_t port, int level, int index,
    128                            soc_th_sched_mode_e mode, int weight, int mc)
    129 {
    130     soc_reg_t reg, reg2 = INVALIDr;
    131     uint32 fval, rval, wrr_mask;
    132     soc_info_t *si = &SOC_INFO(unit);
    133 
    134     LOG_INFO(BSL_LS_SOC_COSQ,
    135              (BSL_META_U(unit,
    136                          "Port:%d L%s%d config : index=%d MODE=%d WT=%d\n"),
    137 			 port, (level == 0) ? "r" : "", level - 1,
    138              index, mode, weight));
    139 
    140     /* selection between SP and WxRR is based on weight property. */
    141     SOC_IF_ERROR_RETURN(soc_th_sched_weight_set(unit, port,
    142                                                 level, index, weight, mc));
    143 
    144     if (level == SOC_TH_NODE_LVL_L0) {
    145         if (IS_CPU_PORT(unit, port)) {
    146             reg = Q_SCHED_CPU_PORT_CONFIGr;
    147             reg2 = Q_SCHED_PORT_CONFIGr;
    148         } else {
    149             reg = Q_SCHED_PORT_CONFIGr;
    150         }
    151         index = 0;
    152     } else if (level == SOC_TH_NODE_LVL_L1) {
    153         if (IS_CPU_PORT(unit, port)) {
    154             int parent_index = 0;
    155             reg = Q_SCHED_CPU_L0_NODE_CONFIGr;
    156             reg2 = Q_SCHED_L0_NODE_CONFIGr;
    157             SOC_IF_ERROR_RETURN
    158                 (soc_th_cosq_cpu_parent_get(unit, index, SOC_TH_NODE_LVL_L1,
    159                                             &parent_index));
    160             index = parent_index;
    161         } else {
    162             reg = Q_SCHED_L0_NODE_CONFIGr;
    163             index %= si->port_num_cosq[port];
    164         }
    165     } else {
    166         return SOC_E_PARAM;
    167     }
    168 
    169     if (mode == SOC_TH_SCHED_MODE_WRR) {
    170         fval = 1;
    171     } else if (mode == SOC_TH_SCHED_MODE_WERR) {
    172         fval = 0;
    173     } else {
    174         return SOC_E_NONE;
    175     }
    176 
    177     SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, port, 0, &rval));
    178     wrr_mask = soc_reg_field_get(unit, reg, rval, ENABLE_WRRf);
    179     wrr_mask &= ~(1 << index);
    180     wrr_mask |= (fval << index);
    181     soc_reg_field_set(unit, reg, &rval, ENABLE_WRRf, wrr_mask);
    182     SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, port, 0, rval));
    183 
    184     /* WAR: set port 32 besides CPU reg, 
    185        as CPU WRED takes some info from port 32. */
    186     if (reg2 != INVALIDr) {
    187         SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg2, port, 0, &rval));
    188         wrr_mask = soc_reg_field_get(unit, reg2, rval, ENABLE_WRRf);
    189         wrr_mask &= ~(1 << index);
    190         wrr_mask |= (fval << index);
    191         soc_reg_field_set(unit, reg2, &rval, ENABLE_WRRf, wrr_mask);
    192         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg2, port, 0, rval));
    193     }
    194 
    195     return SOC_E_NONE;
    196 }
    197 
    198 int
    199 soc_th_cosq_sched_mode_get(int unit, soc_port_t port, int level, int index,
    200                            soc_th_sched_mode_e *mode, int *weight, int mc)
    201 {
    202     soc_reg_t reg;
    203     uint32 rval, wrr_mask;
    204     soc_info_t *si = &SOC_INFO(unit);
    205 
    206     /* selection between SP and WxRR is based on weight property. */
    207     SOC_IF_ERROR_RETURN(soc_th_sched_weight_get(unit, port,
    208                                                 level, index, weight, mc));
    209 
    210     if (level == SOC_TH_NODE_LVL_L0) {
    211         if (IS_CPU_PORT(unit, port)) {
    212             reg = Q_SCHED_CPU_PORT_CONFIGr;
    213         } else {
    214             reg = Q_SCHED_PORT_CONFIGr;
    215         }
    216         index = 0;
    217     } else if (level == SOC_TH_NODE_LVL_L1) {
    218         if (IS_CPU_PORT(unit, port)) {
    219             int parent_index = 0;
    220             reg = Q_SCHED_CPU_L0_NODE_CONFIGr;
    221             SOC_IF_ERROR_RETURN
    222                 (soc_th_cosq_cpu_parent_get(unit, index, SOC_TH_NODE_LVL_L1,
    223                                             &parent_index));
    224             index = parent_index;
    225         } else {
    226             reg = Q_SCHED_L0_NODE_CONFIGr;
    227             index %= si->port_num_cosq[port];
    228         }
    229     } else {
    230         return SOC_E_PARAM;
    231     }
    232 
    233     if (*weight == 0) {
    234         *mode = SOC_TH_SCHED_MODE_STRICT;
    235     } else {
    236         SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, port, 0, &rval));
    237         wrr_mask = soc_reg_field_get(unit, reg, rval, ENABLE_WRRf);
    238         if (wrr_mask & (1 << index)) {
    239             *mode = SOC_TH_SCHED_MODE_WRR;
    240         } else {
    241             *mode = SOC_TH_SCHED_MODE_WERR;
    242         }
    243     }
    244 
    245     return SOC_E_NONE;
    246 }
    247 
    248 /*
    249  * Function to Set Parent(L0) for a given L1 queue of the CPU port
    250  * Note: Only child @ L1 level is supported.
    251  * Because only L1 level queues can be attached to different parent (L0.0-L0.9)
    252  * of the CPU port.
    253  */
    254 int
    255 soc_th_cosq_cpu_parent_set(int unit, int child_index, int child_level,
    256                            int parent_index)
    257 {
    258     soc_reg_t reg = Q_SCHED_CPU_L1_MC_QUEUE_L0_MAPPINGr;
    259     uint32 rval = 0;
    260 
    261     if (child_level != SOC_TH_NODE_LVL_L1) {
    262         /* Only child at L1 are allowed to move */
    263         return SOC_E_PARAM;
    264     }
    265     /* Set the L1 queue's parent to the given L0 node */
    266     SOC_IF_ERROR_RETURN
    267         (soc_reg32_get(unit, reg, 0, child_index, &rval));
    268     soc_reg_field_set(unit, reg, &rval, SELECTf, parent_index);
    269     SOC_IF_ERROR_RETURN
    270         (soc_reg32_set(unit, reg, 0, child_index, rval));
    271 
    272     return SOC_E_NONE;
    273 }
    274 
    275 /*
    276  * Function to Get Parent(L0) for a given L1 queue of the CPU port
    277  * Note: Only child @ L1 level is supported.
    278  * Because only L1 level queues can be attached to different parent (L0.0-L0.9)
    279  * of the CPU port.
    280  */
    281 int
    282 soc_th_cosq_cpu_parent_get(int unit, int child_index, int child_level,
    283                            int *parent_index)
    284 {
    285     soc_reg_t reg = Q_SCHED_CPU_L1_MC_QUEUE_L0_MAPPINGr;
    286     uint32 rval = 0;
    287 
    288     if (child_level != SOC_TH_NODE_LVL_L1) {
    289         /* Only child at L1 are allowed to move */
    290         return SOC_E_PARAM;
    291     }
    292     /* Set the L1 queue's parent to the given L0 node */
    293     SOC_IF_ERROR_RETURN
    294         (soc_reg32_get(unit, reg, 0, child_index, &rval));
    295     *parent_index = soc_reg_field_get(unit, reg, rval, SELECTf);
    296 
    297     return SOC_E_NONE;
    298 }
    299 
    300 int
    301 soc_th_mmu_get_shared_size(int unit, int *thdi_shared,
    302                                int *thdo_db_shared, int *thdo_qe_shared)
    303 {
    304     int xpe, xpe_map;
    305     int granularity;
    306     uint32 rval = 0;
    307 
    308     xpe_map = SOC_INFO(unit).ipipe_xpe_map[0]|SOC_INFO(unit).ipipe_xpe_map[1];
    309 
    310     for (xpe = 0; xpe < NUM_XPE(unit); xpe ++) {
    311         /* unavailable XPEs */
    312         if (!(xpe_map & (1 << xpe))) {
    313             thdi_shared[xpe] = thdo_db_shared[xpe] = thdo_qe_shared[xpe] = -1;
    314             continue;
    315         }
    316 
    317         /* available XPEs */
    318         /* Read shared size from Service pool 0 */
    319         /* THDI */
    320         rval = 0;
    321         granularity = 1;
    322         SOC_IF_ERROR_RETURN
    323             (soc_tomahawk_xpe_reg32_get(unit, THDI_BUFFER_CELL_LIMIT_SPr,
    324                 xpe, -1, 0, &rval));
    325         thdi_shared[xpe] = soc_reg_field_get(unit, THDI_BUFFER_CELL_LIMIT_SPr,
    326                                         rval, LIMITf) * granularity;
    327         /* THDO - DB */
    328         rval = 0;
    329         granularity = 1;
    330         SOC_IF_ERROR_RETURN
    331             (soc_tomahawk_xpe_reg32_get(unit, MMU_THDM_DB_POOL_SHARED_LIMITr,
    332                 xpe, -1, 0, &rval));
    333         thdo_db_shared[xpe] = soc_reg_field_get(unit, MMU_THDM_DB_POOL_SHARED_LIMITr,
    334                                         rval, SHARED_LIMITf) * granularity;
    335         
    336         /* THDO - QE */
    337         rval = 0;
    338         granularity = 4;
    339         SOC_IF_ERROR_RETURN
    340             (soc_tomahawk_xpe_reg32_get(unit, MMU_THDM_MCQE_POOL_SHARED_LIMITr,
    341                 xpe, -1, 0, &rval));
    342         thdo_qe_shared[xpe] = soc_reg_field_get(unit, MMU_THDM_MCQE_POOL_SHARED_LIMITr,
    343                                         rval, SHARED_LIMITf) * granularity;
    344         
    345         LOG_VERBOSE(BSL_LS_SOC_MMU,
    346                     (BSL_META_U(unit,
    347                                 "XPE[%d] Shared cell allocation: ING: %d, "
    348                                 "EGR: DB %d, QE %d (unit of cells)\n"), xpe, 
    349                                 *thdi_shared, *thdo_db_shared, *thdo_qe_shared));
    350     }
    351     
    352     return SOC_E_NONE;
    353 }
    354 
    355 int soc_th_mmu_config_res_limits_update(int unit, int res, int *ing_shd,
    356                                         int *egr_db_shd, int *egr_qe_shd,
    357                                         int post_update)
    358 {
    359     if (SOC_IS_TOMAHAWK(unit)) {
    360         return soc_th_mmu_config_shared_buf_recalc(unit, res, ing_shd,
    361                                                    egr_db_shd, egr_qe_shd,
    362                                                    post_update);
    363     }
    364 #if defined(BCM_TOMAHAWK2_SUPPORT)
    365     else if (SOC_IS_TOMAHAWK2(unit)) {
    366         return soc_th2_mmu_config_shared_buf_set_hw(unit, res, ing_shd,
    367                                                    egr_db_shd, egr_qe_shd,
    368                                                    post_update);
    369     }
    370 #endif
    371     return SOC_E_INTERNAL;
    372 }
    373 
    374 /* 
    375  * Function to calculate reserved memory in Egress buffer
    376  */
    377 int
    378 soc_th_mmu_get_egr_rsvd (int unit, int pipe, int *egr_rsvd)
    379 {
    380     int port, phy_port, mmu_port, new_pipe, local_mmu_port;
    381     int startq, to_cos, cos, count;
    382     int qg_valid, use_qg_min;
    383     soc_mem_t mem1 = INVALIDm, base_mem1 = INVALIDm;
    384     soc_mem_t mem2 = INVALIDm, base_mem2 = INVALIDm;
    385     soc_mem_t mem3 = INVALIDm, base_mem3 = INVALIDm;
    386     soc_mem_t mem4 = INVALIDm, base_mem4 = INVALIDm;
    387     mmu_thdo_q_to_qgrp_map_entry_t entry1;
    388     mmu_thdu_config_qgroup_entry_t entry2;
    389     mmu_thdu_config_queue_entry_t entry3;
    390     mmu_thdm_db_queue_config_entry_t entry4;
    391     soc_info_t *si= &SOC_INFO(unit);
    392     soc_field_t qg_min_field = USE_QGROUP_MINf;
    393     *egr_rsvd = 0;
    394     if (pipe >= NUM_PIPE(unit)) {
    395         return SOC_E_PARAM;
    396     }
    397     base_mem1 = MMU_THDU_Q_TO_QGRP_MAPm;
    398     mem1 = SOC_MEM_UNIQUE_ACC(unit, base_mem1)[pipe];
    399     base_mem2 = MMU_THDU_CONFIG_QGROUPm;
    400     mem2 = SOC_MEM_UNIQUE_ACC(unit, base_mem2)[pipe];
    401     base_mem3 = MMU_THDU_CONFIG_QUEUEm;
    402     mem3 = SOC_MEM_UNIQUE_ACC(unit, base_mem3)[pipe];
    403     base_mem4 = MMU_THDM_DB_QUEUE_CONFIGm;
    404     mem4 = SOC_MEM_UNIQUE_ACC(unit, base_mem4)[pipe];
    405     /*Loop for UC queue/qgroup Mins, excluding CPU and LB ports*/
    406     PBMP_ALL_ITER(unit, port) {
    407         if (!(IS_CPU_PORT(unit, port)) && !(IS_LB_PORT(unit, port))) {
    408             new_pipe = si->port_pipe[port];
    409             if (pipe == new_pipe) {
    410                 /*Calculate qmin+qgroup_min for each port in the pipe*/
    411                 phy_port = si->port_l2p_mapping[port];
    412                 mmu_port = si->port_p2m_mapping[phy_port];
    413                 local_mmu_port = mmu_port & (SOC_TH_MMU_PORT_STRIDE - 1);
    414                 startq = si->port_uc_cosq_base[port];
    415                 count = si->port_num_cosq[port];
    416                 to_cos = startq + count;
    417                 /*Loop for qgroup min; add if atleast one queue uses
    418                  *qgroup min and break
    419                  */
    420                 for (cos = startq; cos < to_cos; cos++) {
    421                     SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem1,
    422                                 MEM_BLOCK_ALL, cos, &entry1));
    423                     qg_valid = soc_mem_field32_get(unit, mem1, &entry1,
    424                             QGROUP_VALIDf);
    425                     use_qg_min = soc_mem_field32_get(unit, mem1, &entry1,
    426                             qg_min_field);
    427                     if ((qg_valid == 1) && (use_qg_min ==1)) {
    428                         SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem2, MEM_BLOCK_ALL,
    429                                     local_mmu_port, &entry2));
    430                         *egr_rsvd += soc_mem_field32_get(unit, mem2, &entry2,
    431                                 Q_MIN_LIMIT_CELLf);
    432                         break;
    433                     }
    434                 }
    435                 /*loop for qmin; check all queues and add queue mins*/
    436                 for (cos = startq; cos < to_cos; cos++) {
    437                     SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem1, MEM_BLOCK_ALL,
    438                                 cos, &entry1));
    439                     qg_valid = soc_mem_field32_get(unit, mem1, &entry1,
    440                             QGROUP_VALIDf);
    441                     use_qg_min = soc_mem_field32_get(unit, mem1, &entry1,
    442                             qg_min_field);
    443                     if ((qg_valid == 0) || (use_qg_min ==0)) {
    444                         SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem3,
    445                                     MEM_BLOCK_ALL,cos, &entry3));
    446                         *egr_rsvd += soc_mem_field32_get(unit, mem3,
    447                                 &entry3, Q_MIN_LIMIT_CELLf);
    448                     }
    449                 }
    450             }
    451         }
    452     }
    453     /*Loop for MC queue Mins, including CPU and LB ports*/
    454     PBMP_ALL_ITER(unit, port) {
    455         new_pipe = si->port_pipe[port];
    456         if (pipe == new_pipe) {
    457             /*Calculate qmin+qgroup_min for each port in the pipe*/
    458             phy_port = si->port_l2p_mapping[port];
    459             mmu_port = si->port_p2m_mapping[phy_port];
    460             local_mmu_port = mmu_port & (SOC_TH_MMU_PORT_STRIDE - 1);
    461             startq = si->port_cosq_base[port];
    462             count = si->port_num_cosq[port];
    463             to_cos = startq + count;
    464             /*loop for MC qmin; check all queues and add queue mins*/
    465             for (cos = startq; cos < to_cos; cos++) {
    466                 SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem4, MEM_BLOCK_ALL,
    467                                 cos, &entry4));
    468                 *egr_rsvd += soc_mem_field32_get(unit, mem4, &entry4,
    469                             Q_MIN_LIMITf);
    470             }
    471         }
    472     }
    473     return SOC_E_NONE;
    474 }
    475 
    476 /*
    477  * Function to calculate the new value of egress shared limit
    478  */
    479 int
    480 soc_th_recalc_new_egress_shared_limit (int unit, int pipe,
    481         int *new_shared_limit)
    482 {
    483     soc_info_t *si;
    484     int  lossless, asf_profile;
    485     _soc_mmu_rsvd_buffer_t rsvd_buffer;
    486     int asf_rsvd1 = 0, asf_rsvd2 = 0;
    487     int egr_rsvd1 = 0, egr_rsvd2 = 0 ;
    488     int xpe, pipe2 = 0, count, temp_val;
    489     uint32 pipe_map;
    490     si = &SOC_INFO(unit);
    491     *new_shared_limit = 0;
    492    /*Getting the second egress pipe which is part of same xpe as this pipe*/
    493     for (xpe = 0; xpe < NUM_XPE(unit); xpe++) {
    494         pipe_map = si->xpe_epipe_map[xpe];
    495         if (pipe_map & (1 << pipe)) {
    496             count = 0;
    497             while(pipe_map) {
    498                 temp_val = (pipe_map >> 1);
    499                 if ((temp_val != 0) && (count != pipe)) {
    500                     pipe2=count;
    501                     break;
    502                 }
    503                 count++;
    504             }
    505         }
    506     }
    507 
    508     if (SOC_IS_TOMAHAWKPLUS(unit)) {
    509         lossless = soc_property_get(unit, spn_MMU_LOSSLESS, 
    510                                     SOC_TH_MMU_LOSSLESS_DEFAULT_DISABLE);
    511     } else {
    512         lossless = soc_property_get(unit, spn_MMU_LOSSLESS, 
    513                                     SOC_TH_MMU_LOSSLESS_DEFAULT_ENABLE);
    514     }
    515 
    516     asf_profile = soc_property_get(unit, spn_ASF_MEM_PROFILE,
    517                                    _SOC_TH_ASF_MEM_PROFILE_SIMILAR);
    518     soc_th_mmu_additional_buffer_reserve(unit, pipe, si->flex_eligible,
    519                                                 lossless, asf_profile,
    520                                                  &rsvd_buffer);
    521     asf_rsvd1 = rsvd_buffer.asf_rsvd_cells;
    522     soc_th_mmu_additional_buffer_reserve(unit, pipe2, si->flex_eligible,
    523                                                 lossless, asf_profile,
    524                                                  &rsvd_buffer);
    525     asf_rsvd2 = rsvd_buffer.asf_rsvd_cells;
    526     soc_th_mmu_get_egr_rsvd (unit, pipe, &egr_rsvd1);
    527     soc_th_mmu_get_egr_rsvd (unit, pipe2, &egr_rsvd2);
    528     *new_shared_limit = _TH_MMU_TOTAL_CELLS_PER_XPE - asf_rsvd1 -
    529         egr_rsvd1 -egr_rsvd2 - asf_rsvd2 - (_TH_MMU_NUM_RQE_QUEUES * 8);
    530     LOG_INFO(BSL_LS_SOC_MMU,
    531     (BSL_META_U(unit,
    532     "MMU buffer recal:  asf_rsvd1: %d egr_rsvd1: %d  new_shared_limit: %d\n"),
    533                asf_rsvd1, egr_rsvd1,  *new_shared_limit));
    534     return SOC_E_NONE;
    535 }
    536 
    537 #endif /* BCM_TOMAHAWK_SUPPORT */