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

trident2p.c (236377B)


      1 /*
      2 
      3  * 
      4  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      5  * 
      6  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      7  *
      8  * File:        trident2p.c
      9  * Purpose:
     10  * Requires:
     11  */
     12 #include <shared/bsl.h>
     13 #include <sal/core/boot.h>
     14 
     15 #include <soc/bradley.h>
     16 #include <soc/drv.h>
     17 #include <soc/error.h>
     18 #include <soc/debug.h>
     19 #include <soc/mem.h>
     20 #include <soc/mspi.h>
     21 #include <soc/l2x.h>
     22 #include <soc/soc_ser_log.h>
     23 #include <soc/devids.h>
     24 
     25 
     26 #ifdef BCM_TRIDENT2PLUS_SUPPORT
     27 #include <soc/trident2.h>
     28 #include <soc/td2_td2p.h>
     29 #include <soc/tdm/core/tdm_top.h>
     30 #include <soc/esw/portctrl.h>
     31 #include <soc/scache.h>
     32 
     33 #define IS_OVERSUB_PORT(unit,port)           \
     34         (SOC_PBMP_MEMBER(PBMP_OVERSUB(unit), port))
     35 
     36 
     37 #define BCM_TD2P_MAX_BANK_SIZE      128
     38 #define BCM_TD2P_SMALL_BANK_SIZE    64
     39 
     40 
     41 #define _TD2P_PROB_DROP_SOP_XOFF          80
     42 #define _TD2P_PROB_DROP_SOP_XON_ABOVE_THR 65
     43 #define _TD2P_PROB_DROP_SOP_XON_BELOW_THR 0
     44 
     45 
     46 #define _SOC_TRIDENT2P_UPDATE_TDM_PRE  (0)
     47 #define _SOC_TRIDENT2P_UPDATE_TDM_POST (1)
     48 
     49 static const soc_reg_t pvtmon_result_reg[] = {
     50     TOP_PVTMON_RESULT_0r, TOP_PVTMON_RESULT_1r,
     51     TOP_PVTMON_RESULT_2r, TOP_PVTMON_RESULT_3r,
     52     TOP_PVTMON_RESULT_4r, TOP_PVTMON_RESULT_5r,
     53     TOP_PVTMON_RESULT_6r, TOP_PVTMON_RESULT_7r,
     54     TOP_PVTMON_RESULT_8r
     55 };
     56 
     57 STATIC soc_reg_t mmu_ovs_group_wt_regs_td2p_local[2][_MMU_OVS_WT_GROUP_COUNT] = {
     58     {
     59         ES_PIPE0_OVR_SUB_GRP_WT0r, ES_PIPE0_OVR_SUB_GRP_WT1r,
     60         ES_PIPE0_OVR_SUB_GRP_WT2r, ES_PIPE0_OVR_SUB_GRP_WT3r
     61     },
     62     {
     63         ES_PIPE1_OVR_SUB_GRP_WT0r, ES_PIPE1_OVR_SUB_GRP_WT1r,
     64         ES_PIPE1_OVR_SUB_GRP_WT2r, ES_PIPE1_OVR_SUB_GRP_WT3r
     65     }
     66 };
     67 
     68 STATIC soc_reg_t mmu_3dbg_c_regs[2] = {
     69     ES_PIPE0_MMU_3DBG_Cr,
     70     ES_PIPE1_MMU_3DBG_Cr
     71 };
     72 
     73 STATIC const soc_field_t mmu_ovr_group_wt_select_fields[] = {
     74     GRP0f, GRP1f, GRP2f, GRP3f,
     75     GRP4f, GRP5f, GRP6f, GRP7f
     76 };
     77 
     78 typedef struct _soc_td2p_ovr_sub_mmu_tdm_s {
     79     int grp_wt_sel[TD2P_PIPES_PER_DEV][MAX_MMU_OVS_GROUP_COUNT];
     80     int tdm_update[TD2P_PIPES_PER_DEV][MAX_MMU_OVS_GROUP_COUNT]
     81                                     [_MMU_OVS_GROUP_TDM_LENGTH];
     82     int grp_wt[TD2P_PIPES_PER_DEV][MAX_MMU_OVS_GROUP_COUNT]
     83                                     [_MMU_OVS_GROUP_TDM_LENGTH];
     84     int mmu_port[TD2P_PIPES_PER_DEV][MAX_MMU_OVS_GROUP_COUNT]
     85                                     [_MMU_OVS_GROUP_TDM_LENGTH];
     86 } _soc_td2p_ovr_sub_mmu_tdm_t;
     87 
     88 typedef struct _soc_td2p_ovr_sub_tdm_s {
     89     _soc_td2p_ovr_sub_mmu_tdm_t mmu_tdm;
     90 } _soc_td2p_ovr_sub_tdm_t;
     91 
     92 enum _td2p_ovs_wt_speed_group {
     93     td2p_ovs_wt_group_speed_10G,
     94     td2p_ovs_wt_group_speed_20G,
     95     td2p_ovs_wt_group_speed_40G,
     96     td2p_ovs_wt_group_speed_NA
     97 };
     98 
     99 static _soc_td2p_flexport_port_q_cb td2p_flexport_cb;
    100 static _soc_td2p_ets_mode_q_cb      td2p_ets_mode_cb;
    101 
    102 
    103 #define NUM_TSC4_PORT_MACRO 32
    104 static int 
    105 soc_td2p_pm_to_1st_port_tsc12[NUM_TSC4_PORT_MACRO] = 
    106                                         {1 , 1 , 1 , 13, /* X Pipe */
    107                                          17, 21, 21, 21,
    108                                          33, 33, 33, 45,
    109                                          49, 53, 53, 53, 
    110                                          65, 65, 65, 77, /* Y Pipe */
    111                                          81, 85, 85, 85, 
    112                                          97, 97, 97, 109, 
    113                                          113,117, 117, 117};
    114 
    115 static int 
    116 soc_td2p_pm_to_1st_port_tsc4[NUM_TSC4_PORT_MACRO] = 
    117                                         {1 , 5 , 9 , 13, /* X Pipe */
    118                                          17, 21, 25, 29, 
    119                                          33, 37, 41, 45, 
    120                                          49, 53, 57, 61, 
    121                                          65, 69, 73, 77, /* Y Pipe */
    122                                          81, 85, 89, 93, 
    123                                          97, 101, 105, 109, 
    124                                          113,117, 121, 125};
    125 
    126 /* index 0 is for X pipe, index 1 is for Y pipe */
    127 static int num_hsp_to_reserve[_TD2_PIPES_PER_DEV] = {0, 0};     
    128 
    129 /* defines for Reserved Buffer for Flex Port Macro when new Flex Port is
    130    enabled */
    131 /* lossless defines */
    132 #define _TD2P_RSVD_BUF_FLEX_HDRM_LOSSLESS 182
    133 
    134 #define _TD2P_RSVD_BUF_FLEX_QGRP 16
    135 #define _TD2P_RSVD_BUF_FLEX_ASF 4
    136 
    137 /* defines for Reserved Buffer for Ports when Flex Port for the macro is NOT
    138    enabled*/
    139 #define _TD2P_RSVD_BUF_NON_FLEX_100G_HDRM_LOSSLESS 558
    140 #define _TD2P_RSVD_BUF_NON_FLEX_40G_HDRM_LOSSLESS 461
    141 #define _TD2P_RSVD_BUF_NON_FLEX_20G_HDRM_LOSSLESS 262
    142 #define _TD2P_RSVD_BUF_NON_FLEX_10G_HDRM_LOSSLESS 182
    143 
    144 #define _TD2P_RSVD_BUF_NON_FLEX_PGMIN 8
    145 #define _TD2P_RSVD_BUF_NON_FLEX_QGRP 16
    146 #define _TD2P_RSVD_BUF_NON_FLEX_ASF 16
    147 
    148 #define _TD2P_RSVD_BUF_NON_FLEX_10G_ASF 4
    149 
    150 #define _TD2P_NUM_TSC4_PER_PIPE 16
    151 #define _TD2P_NUM_PORTS_PER_TSC4 4
    152 
    153 int get_mmu_mode (int unit)
    154 {
    155     int is16Mmode = 0;
    156     char *str, *str_end;
    157     int mmu_size = 0;
    158 
    159     if (SAL_BOOT_QUICKTURN) {
    160         if ((str = soc_property_get_str(unit, "mmu_mem_size")) != NULL) {
    161             mmu_size = sal_ctoi(str, &str_end);
    162             if (str != str_end) {
    163                 if ( mmu_size == 16 ) {
    164                     is16Mmode = 1;
    165                 }
    166             } 
    167         }
    168     } else {
    169         is16Mmode = 1;
    170     }
    171 
    172     return is16Mmode;
    173 }
    174 
    175 mmu_ovs_group_wt_regs_t 
    176 get_mmu_ovs_group_wt_regs (int unit, mmu_ovs_group_wt_regs_t old)
    177 {
    178     if (SOC_IS_TD2P_TT2P(unit)) {
    179         return mmu_ovs_group_wt_regs_td2p_local;
    180     }
    181     return old;
    182 }
    183 
    184 int soc_td2p_if_full_chip (int unit)
    185 {
    186     int full_chip = 1;
    187 
    188     return full_chip;
    189 }
    190 
    191 int soc_td2p_show_voltage(int unit)
    192 {
    193     soc_reg_t reg;
    194     int index;
    195     uint32 rval, fval, avg;
    196 
    197     SOC_IF_ERROR_RETURN(READ_TOP_PVTMON_CTRL_1r(unit, &rval));
    198     soc_reg_field_set(unit, TOP_PVTMON_CTRL_1r, &rval, PVTMON_ADC_RESETBf, 0);
    199     SOC_IF_ERROR_RETURN(WRITE_TOP_PVTMON_CTRL_1r(unit, rval)); 
    200     soc_reg_field_set(unit, TOP_PVTMON_CTRL_1r, &rval, PVTMON_ADC_RESETBf, 1);
    201     soc_reg_field_set(unit, TOP_PVTMON_CTRL_1r, &rval, PVTMON_SELECTf, 4);
    202     SOC_IF_ERROR_RETURN(WRITE_TOP_PVTMON_CTRL_1r(unit, rval));
    203     SOC_IF_ERROR_RETURN(READ_TOP_SOFT_RESET_REG_2r(unit, &rval));
    204     soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_AVS_PVTMON_RST_Lf, 0);
    205     SOC_IF_ERROR_RETURN(WRITE_TOP_SOFT_RESET_REG_2r(unit, rval));
    206     soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_AVS_PVTMON_RST_Lf, 1);
    207     SOC_IF_ERROR_RETURN(WRITE_TOP_SOFT_RESET_REG_2r(unit, rval));
    208 
    209     sal_sleep(1);
    210     avg = 0;
    211 
    212     /* Read Voltages. Ignores result of PVTMON8 */
    213     for (index = 0; index < COUNTOF(pvtmon_result_reg) - 1; index++) {
    214         reg = pvtmon_result_reg[index];
    215         SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
    216         fval = soc_reg_field_get(unit, reg, rval, PVT_DATAf);
    217         /* (PVT_DATA * 880) / 1024 * 0.7 */
    218         fval = (fval * 880 * 10) / (1024 * 7);
    219         avg += fval;
    220         LOG_CLI((BSL_META_U(unit,
    221                             "Voltage monitor %d: voltage = %d.%03dV\n"),
    222                  index, (fval/1000), (fval %1000)));
    223     }
    224 
    225     avg /= (COUNTOF(pvtmon_result_reg) - 1);
    226     LOG_CLI((BSL_META_U(unit,
    227                         "Average voltage is = %d.%03dV\n"),
    228              (avg/1000), (avg %1000)));
    229 
    230     return SOC_E_NONE;
    231 }
    232 
    233 int soc_td2p_set_obm_registers (int unit, soc_reg_t reg, int speed, int index,
    234                 int obm_inst,  int lossless , int default_flag)
    235 {
    236     int xon, xoff;
    237     uint64 ctrl_rval64;
    238     int maxt, mint = 0;
    239     int lowprit;
    240     int div;
    241 
    242     if (PGW_OBM_INIT_HW_DEFAULT == default_flag) {
    243         maxt = 0;
    244         xoff = 0;
    245         xon  = 0;
    246         lowprit = 0;
    247     } else {
    248         if ( speed > 20000) {
    249             div = 1;
    250             xoff = 0x2C3;
    251             xon  = 0x2AB;
    252             lowprit = 0x2AE;
    253         } else if (speed > 10000) {
    254             div = 2;
    255             xoff = 0x13B;
    256             xon  = 0x12F;
    257             lowprit = 0x132;
    258         } else {
    259             div = 4;
    260             xoff = 0x4F;
    261             xon  = 0x49;
    262             lowprit = 0x4c;
    263         }
    264         maxt = GET_NUM_CELLS_PER_OBM(unit) / div;
    265 
    266         if ( !lossless ) {
    267             xon = xoff = 0x7FF;
    268             lowprit = maxt;
    269         }
    270     }
    271 
    272     SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, obm_inst, index,
    273                                     &ctrl_rval64));
    274     soc_reg64_field32_set(unit, reg, &ctrl_rval64,
    275                           MIN_THRESHOLDf, mint);
    276     soc_reg64_field32_set(unit, reg, &ctrl_rval64,
    277                           LOW_PRI_THRESHOLDf, lowprit);
    278     soc_reg64_field32_set(unit, reg, &ctrl_rval64,
    279                           MAX_THRESHOLDf, maxt);
    280     soc_reg64_field32_set(unit, reg, &ctrl_rval64,
    281                           FLOW_CTRL_XONf, xon);
    282     soc_reg64_field32_set(unit, reg, &ctrl_rval64,
    283                           FLOW_CTRL_XOFFf, xoff);
    284 
    285     SOC_IF_ERROR_RETURN
    286         (soc_reg_set(unit, reg, obm_inst, index, ctrl_rval64));
    287 
    288 
    289     return SOC_E_NONE;
    290 }
    291 
    292 /* Probablistic Drop configuration for TD2PLUS:
    293  * These settings cannot be changed dynamically, According to Architecture team
    294  * these settings are optimized for all the OverSubscription ratios. Hence not
    295  * giving any configuration options for these fields. 
    296  * OverSub feature is enabled by default for TD2PLUS.
    297  */
    298 int soc_td2p_obm_prob_drop_default_set (int unit, int xlp, int index,
    299                                          int obm_inst, int default_flag)
    300 {
    301     static const soc_reg_t pgw_obm_prob_drop_regs[] = {
    302                 PGW_OBM0_LOW_PRI_DROP_PROBr, PGW_OBM1_LOW_PRI_DROP_PROBr,
    303                 PGW_OBM2_LOW_PRI_DROP_PROBr, PGW_OBM3_LOW_PRI_DROP_PROBr
    304     };
    305     soc_reg_t reg;
    306     uint64 ctrl_rval64;
    307 
    308     reg = pgw_obm_prob_drop_regs[xlp];
    309     SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, obm_inst, index,
    310                                     &ctrl_rval64));
    311     if (PGW_OBM_INIT_HW_DEFAULT == default_flag) {
    312         soc_reg64_field32_set(unit, reg, &ctrl_rval64, EN_DROP_PROBf, 0);
    313         soc_reg64_field32_set(unit, reg, &ctrl_rval64, SOP_XOFFf, 0);
    314         soc_reg64_field32_set(unit, reg, &ctrl_rval64, SOP_XON_ABOVE_THRf, 0);
    315         soc_reg64_field32_set(unit, reg, &ctrl_rval64, SOP_XON_BELOW_THRf, 0);
    316     } else {
    317         /* By default enable Probabilistic dropping */
    318         soc_reg64_field32_set(unit, reg, &ctrl_rval64, EN_DROP_PROBf, 1);
    319         soc_reg64_field32_set(unit, reg, &ctrl_rval64, SOP_XOFFf,
    320                               _TD2P_PROB_DROP_SOP_XOFF);
    321         soc_reg64_field32_set(unit, reg, &ctrl_rval64, SOP_XON_ABOVE_THRf,
    322                               _TD2P_PROB_DROP_SOP_XON_ABOVE_THR);
    323         soc_reg64_field32_set(unit, reg, &ctrl_rval64, SOP_XON_BELOW_THRf,
    324                               _TD2P_PROB_DROP_SOP_XON_BELOW_THR);
    325     }
    326     SOC_IF_ERROR_RETURN
    327         (soc_reg_set(unit, reg, obm_inst, index, ctrl_rval64));
    328 
    329     return SOC_E_NONE;
    330 }
    331 
    332 /* Cut through is allowed if usage is less than or equal to
    333  * CUT_THROUGH_OKf threshold.  Granularity is 16B cell.
    334  */
    335 int soc_td2p_obm_cut_through_threshold_set (int unit, int xlp, int index,
    336                                             int obm_inst, int default_flag)
    337 {
    338     static const soc_reg_t pgw_obm_threshold2_regs[] = {
    339         PGW_OBM0_THRESHOLD2r, PGW_OBM1_THRESHOLD2r,
    340         PGW_OBM2_THRESHOLD2r, PGW_OBM3_THRESHOLD2r
    341     };
    342     soc_reg_t reg;
    343     uint64 ctrl_rval64;
    344 
    345     reg = pgw_obm_threshold2_regs[xlp];
    346     SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, obm_inst, index,
    347                                     &ctrl_rval64));
    348     if ( PGW_OBM_INIT_HW_DEFAULT == default_flag ) {
    349         soc_reg64_field32_set(unit, reg, &ctrl_rval64,
    350                               CUT_THROUGH_OKf, 0);
    351     } else {
    352         soc_reg64_field32_set(unit, reg, &ctrl_rval64,
    353                               CUT_THROUGH_OKf, 2);
    354     }
    355     SOC_IF_ERROR_RETURN
    356         (soc_reg_set(unit, reg, obm_inst, index, ctrl_rval64));
    357     return SOC_E_NONE;
    358 }
    359 
    360 STATIC int
    361 soc_td2p_pgw_mib_reset_reg_default_set(int unit, int xlp, int port_index,
    362                                        int obm_inst)
    363 {
    364     const soc_reg_t reg = PGW_MIB_RESETr;
    365     const soc_field_t field = CLR_CNTf;
    366     int port_index_pgw;
    367     uint64 ctrl_rval64;
    368     uint32 reg_val;
    369 
    370     port_index_pgw = xlp * 4 + port_index;
    371 
    372     SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, obm_inst, port_index,
    373                                     &ctrl_rval64));
    374     reg_val = soc_reg64_field32_get(unit, reg, ctrl_rval64, field);
    375     /* coverity[ptr_arith] */
    376     SHR_BITSET(&reg_val, port_index_pgw);
    377     soc_reg64_field32_set(unit, reg, &ctrl_rval64,
    378                           field, reg_val);
    379     SOC_IF_ERROR_RETURN
    380         (soc_reg_set(unit, reg, obm_inst, port_index, ctrl_rval64));
    381 
    382     /* coverity[ptr_arith] */
    383     SHR_BITCLR(&reg_val, port_index_pgw);
    384     soc_reg64_field32_set(unit, reg, &ctrl_rval64,
    385                           field, reg_val);
    386     SOC_IF_ERROR_RETURN
    387         (soc_reg_set(unit, reg, obm_inst, port_index, ctrl_rval64));
    388 
    389     return SOC_E_NONE;
    390 }
    391 
    392 STATIC int
    393 soc_td2p_obm_high_pri_byte_drop_default_set (int unit, int xlp, int index,
    394                                              int obm_inst)
    395 {
    396     static const soc_reg_t pgw_obm_high_pri_byte_drop_regs[] = {
    397                 PGW_OBM0_HIGH_PRI_BYTE_DROPr, PGW_OBM1_HIGH_PRI_BYTE_DROPr,
    398                 PGW_OBM2_HIGH_PRI_BYTE_DROPr, PGW_OBM3_HIGH_PRI_BYTE_DROPr
    399     };
    400     soc_reg_t reg;
    401     uint64 ctrl_rval64;
    402     reg = pgw_obm_high_pri_byte_drop_regs[xlp];
    403     SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, obm_inst, index,
    404                                     &ctrl_rval64));
    405     soc_reg64_field32_set(unit, reg, &ctrl_rval64, COUNTERf, 0);
    406     SOC_IF_ERROR_RETURN
    407         (soc_reg_set(unit, reg, obm_inst, index, ctrl_rval64));
    408 
    409     return SOC_E_NONE;
    410 }
    411 
    412 STATIC int
    413 soc_td2p_obm_high_pri_pkt_drop_default_set (int unit, int xlp, int index,
    414                                             int obm_inst)
    415 {
    416     static const soc_reg_t pgw_obm_high_pri_pkt_drop_regs[] = {
    417                 PGW_OBM0_HIGH_PRI_PKT_DROPr, PGW_OBM1_HIGH_PRI_PKT_DROPr,
    418                 PGW_OBM2_HIGH_PRI_PKT_DROPr, PGW_OBM3_HIGH_PRI_PKT_DROPr
    419     };
    420     soc_reg_t reg;
    421     uint64 ctrl_rval64;
    422     reg = pgw_obm_high_pri_pkt_drop_regs[xlp];
    423     SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, obm_inst, index,
    424                                     &ctrl_rval64));
    425     soc_reg64_field32_set(unit, reg, &ctrl_rval64, COUNTERf, 0);
    426     SOC_IF_ERROR_RETURN
    427         (soc_reg_set(unit, reg, obm_inst, index, ctrl_rval64));
    428 
    429     return SOC_E_NONE;
    430 }
    431 
    432 STATIC int
    433 soc_td2p_obm_low_pri_byte_drop_default_set (int unit, int xlp, int index,
    434                                             int obm_inst)
    435 {
    436     static const soc_reg_t pgw_obm_low_pri_byte_drop_regs[] = {
    437                 PGW_OBM0_LOW_PRI_BYTE_DROPr, PGW_OBM1_LOW_PRI_BYTE_DROPr,
    438                 PGW_OBM2_LOW_PRI_BYTE_DROPr, PGW_OBM3_LOW_PRI_BYTE_DROPr
    439     };
    440     soc_reg_t reg;
    441     uint64 ctrl_rval64;
    442     reg = pgw_obm_low_pri_byte_drop_regs[xlp];
    443     SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, obm_inst, index,
    444                                     &ctrl_rval64));
    445     soc_reg64_field32_set(unit, reg, &ctrl_rval64, COUNTERf, 0);
    446     SOC_IF_ERROR_RETURN
    447         (soc_reg_set(unit, reg, obm_inst, index, ctrl_rval64));
    448 
    449     return SOC_E_NONE;
    450 }
    451 
    452 STATIC int
    453 soc_td2p_obm_low_pri_pkt_drop_default_set (int unit, int xlp, int index,
    454                                            int obm_inst)
    455 {
    456     static const soc_reg_t pgw_obm_low_pri_pkt_drop_regs[] = {
    457                 PGW_OBM0_LOW_PRI_PKT_DROPr, PGW_OBM1_LOW_PRI_PKT_DROPr,
    458                 PGW_OBM2_LOW_PRI_PKT_DROPr, PGW_OBM3_LOW_PRI_PKT_DROPr
    459     };
    460     soc_reg_t reg;
    461     uint64 ctrl_rval64;
    462     reg = pgw_obm_low_pri_pkt_drop_regs[xlp];
    463     SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, obm_inst, index,
    464                                     &ctrl_rval64));
    465     soc_reg64_field32_set(unit, reg, &ctrl_rval64, COUNTERf, 0);
    466     SOC_IF_ERROR_RETURN
    467         (soc_reg_set(unit, reg, obm_inst, index, ctrl_rval64));
    468 
    469     return SOC_E_NONE;
    470 }
    471 
    472 
    473 int soc_td2p_mmu_delay_insertion_set (int unit, int port, int speed)
    474 {
    475     int phy_port, mmu_port;    
    476     int pipe;
    477     int val = 0;
    478     uint32 rval;
    479     soc_info_t *si;
    480 
    481     si = &SOC_INFO(unit);      
    482 
    483     phy_port = si->port_l2p_mapping[port];
    484     mmu_port = si->port_p2m_mapping[phy_port] & 0x3F;
    485 
    486     if ( mmu_port < SOC_TD2P_MAX_MMU_PORTS_PER_PIPE ) {
    487         pipe = SOC_PBMP_MEMBER(si->ypipe_pbm, port) ? 1 : 0;
    488 
    489         SOC_IF_ERROR_RETURN(soc_reg32_get(unit, 
    490                     mmu_3dbg_c_regs [ pipe ], REG_PORT_ANY, mmu_port, &rval));
    491         /* register format is the same for PIPE0 and PIPE1 */
    492         if (IS_OVERSUB_PORT(unit, port )) {
    493             if ( speed <= 10000 ) {
    494                 val = 15;
    495             } else if ( speed <= 20000 ) {
    496                 val = 30;
    497             } else if ( speed <= 25000 ) {
    498                 val = 40;
    499             } else if ( speed <= 40000 ) {
    500                 val = 60;
    501             } else {
    502             }
    503         } else {
    504             /* linerate port */
    505         }
    506         soc_reg_field_set(unit, ES_PIPE0_MMU_3DBG_Cr, &rval, FIELD_Af, val);
    507 
    508         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, 
    509                     mmu_3dbg_c_regs [ pipe ], REG_PORT_ANY, mmu_port, rval));
    510     }
    511 
    512     return SOC_E_NONE;
    513 }
    514 
    515 /*
    516  * Function:
    517  *      soc_td2p_subport_init
    518  * Purpose:
    519  *      Setup the pbm fields from config variables for the COE application
    520  * Parameters:
    521  *      unit    -  (IN) Device number.
    522  * Returns:
    523  *      NONE
    524  */
    525 void soc_td2p_subport_init(int unit)
    526 {
    527     soc_port_t  port;
    528     soc_info_t *si=&SOC_INFO(unit);
    529     soc_pbmp_t  pbmp_subport;
    530     int         num_subport = 0;
    531 
    532     SOC_PBMP_CLEAR(si->subtag_pbm);
    533     SOC_PBMP_CLEAR(si->subtag_allowed_pbm);
    534     SOC_PBMP_CLEAR(si->subtag.bitmap);
    535 
    536     for (port = 0; port < SOC_MAX_NUM_PORTS; port++) {
    537         si->port_num_subport[port] = 0;
    538     }
    539 
    540     pbmp_subport = soc_property_get_pbmp(unit, spn_PBMP_SUBPORT, 0);
    541 
    542     SOC_PBMP_ASSIGN(si->subtag_allowed_pbm, pbmp_subport);
    543 
    544     if (SOC_PBMP_NOT_NULL(si->subtag_allowed_pbm)) {
    545         /* Iterate through SubTag ports and reserve subport indices */
    546         SOC_PBMP_ITER(si->subtag_allowed_pbm, port) {
    547 
    548             
    549             num_subport =
    550                 soc_property_port_get(unit, port, spn_NUM_SUBPORTS, 0);
    551 
    552             if (num_subport > TD2P_MAX_SUBPORT_COE_PORT_PER_CASPORT) {
    553                 LOG_ERROR(BSL_LS_SOC_COMMON,
    554                           (BSL_META_U(unit,
    555                               "\nCONFIG ERROR\n"
    556                               "num_subports_%d on port %d exceed max value,"
    557                               "setting it to the max allowed value %d\n\n"), 
    558                               num_subport, port,
    559                               TD2P_MAX_SUBPORT_COE_PORT_PER_CASPORT));
    560                 num_subport = TD2P_MAX_SUBPORT_COE_PORT_PER_CASPORT;
    561             }
    562 
    563             if (port < SOC_MAX_NUM_PORTS) {
    564                 si->port_num_subport[port] = num_subport;
    565 
    566             }
    567         }
    568     }
    569 
    570     /* Initialize the number of COE modules */
    571     si->num_coe_modules = TD2P_MAX_COE_MODULES;
    572 }
    573 
    574 int
    575 soc_td2p_mem_config(int unit, uint16 dev_id, uint8 rev_id)
    576 {
    577     soc_persist_t *sop;
    578     sop_memstate_t *memState;
    579 
    580     int         index_max;
    581     int         ipmc_tbl [] = { L3_IPMC_1m, L3_IPMC_REMAPm, L3_IPMCm, 
    582                                 EGR_IPMCm};
    583     int         ipmc_tindex;
    584             
    585     
    586     sop = SOC_PERSIST(unit);
    587     memState = sop->memState;
    588 
    589     switch ( dev_id ) {
    590         case BCM56832_DEVICE_ID :
    591             index_max = 8 * 1024;
    592             break;
    593         default :
    594             index_max = 16 * 1024;
    595             break;
    596     }
    597     index_max--; /* index is a last element so = size - 1 */
    598 
    599     for (ipmc_tindex = 0; ipmc_tindex < sizeof(ipmc_tbl)/sizeof(ipmc_tbl[0]); 
    600                           ipmc_tindex++ ) {
    601         memState[ipmc_tbl[ipmc_tindex]].index_max = index_max;
    602     }
    603 
    604     if (dev_id == BCM56832_DEVICE_ID) { 
    605         index_max = 8 * 1024;
    606     } else {
    607         index_max = 12 * 1024;
    608     }
    609     index_max--;
    610     memState[L3_IIFm].index_max = index_max;
    611 
    612     /* Disable CoE related memories for appr. SKUs */
    613     if ((dev_id != BCM56866_DEVICE_ID) && (dev_id != BCM56867_DEVICE_ID)) {
    614         memState[SUBPORT_TAG_SGPP_MAPm].index_max = -1;
    615         memState[SUBPORT_TAG_SGPP_MAP_ONLYm].index_max = -1;
    616         memState[SUBPORT_TAG_SGPP_MAP_DATA_ONLYm].index_max = -1;
    617         memState[EGR_LPORT_PROFILEm].index_max = -1;
    618         memState[EGR_SUBPORT_TAG_DOT1P_MAPm].index_max = -1;
    619     }
    620 
    621     switch (dev_id) {
    622        case BCM56868_DEVICE_ID:
    623             /* L3 Forwarding disabled */
    624             memState[L3_ECMPm].index_max = -1;
    625             memState[L3_ECMP_COUNTm].index_max = -1;
    626             memState[ING_L3_NEXT_HOPm].index_max = -1;
    627             memState[INITIAL_L3_ECMPm].index_max = -1;
    628             memState[INITIAL_L3_ECMP_GROUPm].index_max = -1;
    629             memState[INITIAL_ING_L3_NEXT_HOPm].index_max = -1;
    630             memState[L3_DEFIP_AUX_HITBIT_UPDATEm].index_max = -1;
    631             memState[L3_DEFIP_AUX_SCRATCHm].index_max = -1;
    632             memState[L3_DEFIP_AUX_TABLEm].index_max = -1;
    633             memState[L3_TUNNELm].index_max = -1;
    634             memState[L3_TUNNEL_DATA_ONLYm].index_max = -1;
    635             memState[L3_TUNNEL_ONLYm].index_max = -1;
    636 
    637             /* MPLS related memories */
    638             memState[ING_MPLS_EXP_MAPPINGm].index_max = -1;
    639             memState[EGR_MPLS_EXP_PRI_MAPPINGm].index_max = -1;
    640             memState[EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm].index_max = -1;
    641             memState[EGR_MPLS_EXP_PRI_MAPPINGm].index_max = -1;
    642             memState[EGR_IP_TUNNEL_MPLSm].index_max = -1;
    643             memState[MPLS_ENTROPY_LABEL_DATAm].index_max = -1;
    644             memState[MPLS_ENTRYm].index_max = -1;
    645 
    646             /* coverity[fallthrough:FALSE] */
    647         case BCM56832_DEVICE_ID:
    648         case BCM56833_DEVICE_ID:
    649         case BCM56836_DEVICE_ID:
    650         case BCM56867_DEVICE_ID:
    651             /* FCoE */
    652             memState[ING_FC_HEADER_TYPEm].index_max = -1;
    653             memState[ING_VFT_PRI_MAPm].index_max = -1;
    654             memState[ING_VSANm].index_max = -1;
    655             memState[FC_MAP_PROFILEm].index_max = -1;
    656             memState[FCOE_HOP_COUNT_FNm].index_max = -1;
    657             memState[EGR_VSAN_INTPRI_MAPm].index_max = -1;
    658             memState[EGR_FCOE_CONTROL_1m].index_max = -1;
    659             memState[EGR_VFT_FIELDS_PROFILEm].index_max = -1;
    660             memState[EGR_VFT_PRI_MAPm].index_max = -1;
    661             memState[EGR_FC_HEADER_TYPEm].index_max = -1;
    662 
    663             /* NAT */
    664             memState[ING_SNATm].index_max = -1;
    665             memState[ING_SNAT_DATA_ONLYm].index_max = -1;
    666             memState[ING_SNAT_HIT_ONLYm].index_max = -1;
    667             memState[ING_SNAT_HIT_ONLY_Xm].index_max = -1;
    668             memState[ING_SNAT_HIT_ONLY_Ym].index_max = -1;
    669             memState[ING_SNAT_ONLYm].index_max = -1;
    670             memState[ING_DNAT_ADDRESS_TYPEm].index_max = -1;
    671             memState[EGR_NAT_PACKET_EDIT_INFOm].index_max = -1;
    672 
    673             /* TRILL */
    674             memState[ING_TRILL_PARSE_CONTROLm].index_max = -1;
    675             memState[ING_TRILL_PAYLOAD_PARSE_CONTROLm].index_max = -1;
    676             memState[EGR_TRILL_PARSE_CONTROLm].index_max = -1;
    677             memState[EGR_TRILL_PARSE_CONTROL_2m].index_max = -1;
    678             memState[EGR_TRILL_RBRIDGE_NICKNAMESm].index_max = -1;
    679             memState[EGR_TRILL_TREE_PROFILEm].index_max = -1;
    680             break;
    681         case BCM56860_DEVICE_ID:
    682             if (SOC_SWITCH_BYPASS_MODE(unit) != SOC_SWITCH_BYPASS_MODE_NONE) {
    683                 if (SOC_SWITCH_BYPASS_MODE(unit) ==
    684                         SOC_SWITCH_BYPASS_MODE_L3_AND_FP) {
    685     
    686                     /* IFP */
    687                     memState[FP_RANGE_CHECKm].index_max = -1;
    688                     memState[FP_GLOBAL_MASK_TCAMm].index_max = -1;
    689                     memState[FP_GM_FIELDSm].index_max = -1;
    690                     memState[FP_TCAMm].index_max = -1;
    691                     memState[FP_SLICE_MAPm].index_max = -1;
    692                     memState[FP_POLICY_TABLEm].index_max = -1;
    693                     memState[FP_METER_TABLEm].index_max = -1;
    694                     memState[FP_COUNTER_TABLEm].index_max = -1;
    695                     memState[FP_COUNTER_TABLE_Xm].index_max = -1;
    696                     memState[FP_COUNTER_TABLE_Ym].index_max = -1;
    697                     memState[FP_STORM_CONTROL_METERSm].index_max = -1;
    698                     memState[FP_SLICE_KEY_CONTROLm].index_max = -1;
    699                     memState[FP_PORT_METER_MAPm].index_max = -1;
    700                     memState[FP_I2E_CLASSID_SELECTm].index_max = -1;
    701                     memState[FP_HG_CLASSID_SELECTm].index_max = -1;
    702                      
    703                     /* EFP */
    704                     memState[EFP_TCAMm].index_max = -1;
    705                     memState[EFP_POLICY_TABLEm].index_max = -1;
    706                     memState[EFP_METER_TABLEm].index_max = -1;
    707                     memState[EGR_PW_INIT_COUNTERSm].index_max = -1;
    708 
    709                     /* IVXLT */
    710                     memState[VLAN_PROTOCOLm].index_max = -1;
    711                     memState[VLAN_PROTOCOL_DATAm].index_max = -1;
    712                     memState[VLAN_SUBNETm].index_max = -1;
    713                     memState[VLAN_SUBNET_ONLYm].index_max = -1;
    714                     memState[VLAN_SUBNET_DATA_ONLYm].index_max = -1;
    715                     memState[VLAN_MACm].index_max = -1;
    716                     memState[VLAN_XLATEm].index_max = -1;
    717                     memState[VFP_TCAMm].index_max = -1;
    718                     memState[VFP_POLICY_TABLEm].index_max = -1;
    719                     memState[ING_VLAN_TAG_ACTION_PROFILEm].index_max = -1;
    720                     memState[MPLS_ENTRYm].index_max = -1;
    721                     memState[UDF_CONDITIONAL_CHECK_TABLE_CAMm].index_max = -1;
    722                     memState[UDF_CONDITIONAL_CHECK_TABLE_RAMm].index_max = -1;
    723                     memState[ING_ETAG_PCP_MAPPINGm].index_max = -1;
    724                     memState[VLAN_XLATE_ECCm].index_max = -1;
    725                     memState[MPLS_ENTROPY_LABEL_DATAm].index_max = -1;
    726                     memState[ING_ETAG_PCP_MAPPINGm].index_max = -1;
    727                 }
    728             }
    729             break;
    730         default:
    731             ;
    732 
    733     }
    734 
    735     return SOC_E_NONE;
    736 }
    737 
    738 int
    739 soc_td2p_get_shared_bank_size(int unit, uint16 dev_id, uint8 rev_id)
    740 {
    741     int bank_size = BCM_TD2P_SMALL_BANK_SIZE;
    742 
    743 
    744     switch ( dev_id ) {
    745     case BCM56867_DEVICE_ID :
    746         bank_size = BCM_TD2P_MAX_BANK_SIZE;
    747         break;
    748     }
    749 
    750     return bank_size;
    751 }
    752 
    753 uint32* soc_td2p_mmu_params_arr_get (uint16 dev_id, uint8 rev_id)
    754 {
    755     switch (dev_id) {
    756         case BCM56860_DEVICE_ID:
    757         case BCM56861_DEVICE_ID:
    758         case BCM56862_DEVICE_ID:
    759         case BCM56864_DEVICE_ID:
    760         case BCM56865_DEVICE_ID:
    761         case BCM56866_DEVICE_ID:
    762         case BCM56867_DEVICE_ID:
    763         case BCM56868_DEVICE_ID:
    764         case BCM56836_DEVICE_ID:
    765             return soc_mmu_pkt_buf_size_arr[_MMU_PKT_BUF_SIZE_16MB];
    766             break;
    767         case BCM56832_DEVICE_ID:
    768             return soc_mmu_pkt_buf_size_arr[_MMU_PKT_BUF_SIZE_9MB];
    769             break;
    770         case BCM56833_DEVICE_ID:
    771             return soc_mmu_pkt_buf_size_arr[_MMU_PKT_BUF_SIZE_12MB];
    772             break;
    773     }
    774 
    775     return NULL;
    776 }
    777 
    778 STATIC uint32 trident2p_write_data[] = {
    779     0x1fffffc0, 0xbffffbfe, 0x1dfcbe80, 0xbffffbfe, 0x40000000, 0x40000200,
    780     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 
    781     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    782     0x80000180, 0x1dfcfe80, 0xbffffbfe, 0x40000000, 0x40000200, 0x40000000,
    783     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    784     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x80000180,
    785     0x1dfc7e80, 0xbffffbfe, 0x40000000, 0x40080000, 0x40000000, 0x40000000,
    786     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    787     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    788     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    789     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    790     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    791     0x40000000, 0x80000180, 0x1dfc3e80, 0xbffffbfe, 0x40000000, 0x40080000,
    792     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    793     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    794     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    795     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    796     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    797     0x40000000, 0x40000000, 0x40000000, 0x80000180, 0x1dfcde80, 0xbffffbfe,
    798     0x44000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    799     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    800     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    801     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    802     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    803     0x40000000, 0x80000180, 0x1dfc9e80, 0xbffffbfe, 0x44000000, 0x40000000,
    804     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    805     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    806     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    807     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    808     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x80000180,
    809     0xbfcbe80, 0xbffffbfe, 0x40000000, 0x40001000, 0x40000000, 0x40000000,
    810     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    811     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    812     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    813     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    814     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    815     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    816     0x40000000, 0x80000180, 0xbfc7e80, 0xbffffbfe, 0x40000000, 0x40001000,
    817     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    818     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    819     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    820     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    821     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    822     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    823     0x40000000, 0x40000000, 0x40000000, 0x80000180, 0xbfc3e80, 0xbffffbfe,
    824     0x40000000, 0x40080000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    825     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    826     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    827     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x80000180,
    828     0xbfcde80, 0xbffffbfe, 0x40000000, 0x41000000, 0x40000000, 0x40000000,
    829     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    830     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    831     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    832     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    833     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x80000180, 0x1bfc3e80,
    834     0xbffffbfe, 0x40000000, 0x40000008, 0x40000000, 0x40000000, 0x40000000,
    835     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    836     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    837     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    838     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x80000180, 0x1bfcde80,
    839     0xbffffbfe, 0x40000000, 0x40000008, 0x40000000, 0x40000000, 0x40000000,
    840     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    841     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    842     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    843     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x80000180, 0x17fc7e80,
    844     0xbffffbfe, 0x40000000, 0x40000008, 0x40000000, 0x40000000, 0x40000000,
    845     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    846     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    847     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    848     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x80000180, 0x17fc3e80,
    849     0xbffffbfe, 0x40000000, 0x40000008, 0x40000000, 0x40000000, 0x40000000,
    850     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    851     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    852     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    853     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x80000180, 0x13fcbe80,
    854     0xbffffbfe, 0x40000000, 0x40000008, 0x40000000, 0x40000000, 0x40000000,
    855     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    856     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    857     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    858     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x80000180, 0x13fc7e80,
    859     0xbffffbfe, 0x40000000, 0x40000008, 0x40000000, 0x40000000, 0x40000000,
    860     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    861     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    862     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    863     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x80000180, 0xffcfe80,
    864     0xbffffbfe, 0x40000000, 0x40000008, 0x40000000, 0x40000000, 0x40000000,
    865     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    866     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    867     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    868     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x80000180, 0xffcbe80,
    869     0xbffffbfe, 0x40000000, 0x40000008, 0x40000000, 0x40000000, 0x40000000,
    870     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    871     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    872     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    873     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x80000180, 0x1ffc5e80,
    874     0xbffffbfe, 0x44000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    875     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    876     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    877     0x40000000, 0x40000000, 0x40000000, 0x80000180, 0x1ffc1e80, 0xbffffbfe,
    878     0x44000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    879     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    880     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    881     0x40000000, 0x40000000, 0x80000180, 0x1dfc5e80, 0xbffffbfe, 0x40000000,
    882     0x40000002, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    883     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    884     0x40000000, 0x40000000, 0x80000180, 0x1dfc1e80, 0xbffffbfe, 0x40000000,
    885     0x40000002, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    886     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    887     0x40000000, 0x40000000, 0x80000180, 0x1bfcfe80, 0xbffffbfe, 0x40000000,
    888     0x48000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    889     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x80000180, 0x1bfcbe80,
    890     0xbffffbfe, 0x40000000, 0x48000000, 0x40000000, 0x40000000, 0x40000000,
    891     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    892     0x80000180, 0xdfc5e80, 0xbffffbfe, 0x40000000, 0x40000002, 0x40000000,
    893     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x80000180,
    894     0xdfc1e80, 0xbffffbfe, 0x40000000, 0x40200000, 0x40000000, 0x40000000,
    895     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    896     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    897     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    898     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    899     0x40000000, 0x40000000, 0x80000180, 0xbfcfe80, 0xbffffbfe, 0x40000000,
    900     0x40200000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    901     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    902     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    903     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    904     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x80000180,
    905     0xbfc9e80, 0xbffffbfe, 0x40000000, 0x40000008, 0x40000000, 0x40000000,
    906     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    907     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    908     0x80000180, 0x1dfcbe80, 0xbffffbfe, 0x40000000, 0x40000200, 0x40000000,
    909     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    910     0x40000000, 0x41000000, 0x40000000, 0x40000000, 0x40000000, 0x80000180,
    911     0x1dfcbe80, 0xbffffbfe, 0x40000000, 0x40000200, 0x40000000, 0x40000000,
    912     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    913     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x80000180, 0x1dfcfe80,
    914     0xbffffbfe, 0x40000000, 0x40000200, 0x40000000, 0x40000000, 0x40000000,
    915     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x41000000,
    916     0x40000000, 0x40000000, 0x40000000, 0x80000180, 0x1dfcfe80, 0xbffffbfe,
    917     0x40000000, 0x40000200, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    918     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    919     0x40000000, 0x40000000, 0x80000180, 0x1dfc7e80, 0xbffffbfe, 0x40000000,
    920     0x40080000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    921     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    922     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    923     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    924     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    925     0x41000000, 0x40000000, 0x40000000, 0x40000000, 0x80000180, 0x1dfc7e80,
    926     0xbffffbfe, 0x40000000, 0x40080000, 0x40000000, 0x40000000, 0x40000000,
    927     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    928     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    929     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    930     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    931     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    932     0x80000180, 0x1dfc3e80, 0xbffffbfe, 0x40000000, 0x40080000, 0x40000000,
    933     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    934     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    935     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    936     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    937     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x41000000, 0x40000000,
    938     0x40000000, 0x40000000, 0x80000180, 0x1dfc3e80, 0xbffffbfe, 0x40000000,
    939     0x40080000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    940     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    941     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    942     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    943     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    944     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x80000180, 0x1dfcde80,
    945     0xbffffbfe, 0x44000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    946     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    947     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    948     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    949     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x41000000, 0x40000000,
    950     0x40000000, 0x40000000, 0x80000180, 0x1dfcde80, 0xbffffbfe, 0x44000000,
    951     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    952     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    953     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    954     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    955     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    956     0x80000180, 0x1dfc9e80, 0xbffffbfe, 0x44000000, 0x40000000, 0x40000000,
    957     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    958     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    959     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    960     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    961     0x41000000, 0x40000000, 0x40000000, 0x40000000, 0x80000180, 0x1dfc9e80,
    962     0xbffffbfe, 0x44000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    963     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    964     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    965     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    966     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    967     0x40000000, 0x40000000, 0x80000180, 0xbfcbe80, 0xbffffbfe, 0x40000000,
    968     0x40001000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    969     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    970     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    971     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    972     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    973     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    974     0x41000000, 0x40000000, 0x40000000, 0x40000000, 0x80000180, 0xbfcbe80,
    975     0xbffffbfe, 0x40000000, 0x40001000, 0x40000000, 0x40000000, 0x40000000,
    976     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    977     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    978     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    979     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    980     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    981     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    982     0x80000180, 0xbfc7e80, 0xbffffbfe, 0x40000000, 0x40001000, 0x40000000,
    983     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    984     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    985     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    986     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    987     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    988     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x41000000, 0x40000000,
    989     0x40000000, 0x40000000, 0x80000180, 0xbfc7e80, 0xbffffbfe, 0x40000000,
    990     0x40001000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    991     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    992     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    993     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    994     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    995     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    996     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x80000180, 0xbfc3e80,
    997     0xbffffbfe, 0x40000000, 0x40080000, 0x40000000, 0x40000000, 0x40000000,
    998     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
    999     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1000     0x40000000, 0x40000000, 0x41000000, 0x40000000, 0x40000000, 0x40000000,
   1001     0x80000180, 0xbfc3e80, 0xbffffbfe, 0x40000000, 0x40080000, 0x40000000,
   1002     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1003     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1004     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1005     0x40000000, 0x40000000, 0x80000180, 0xbfcde80, 0xbffffbfe, 0x40000000,
   1006     0x41000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1007     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1008     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1009     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1010     0x40000000, 0x40000000, 0x40000000, 0x41000000, 0x40000000, 0x40000000,
   1011     0x40000000, 0x80000180, 0xbfcde80, 0xbffffbfe, 0x40000000, 0x41000000,
   1012     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1013     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1014     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1015     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1016     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1017     0x80000180, 0x1bfc3e80, 0xbffffbfe, 0x40000000, 0x40000008, 0x40000000,
   1018     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1019     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1020     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1021     0x40000000, 0x40000000, 0x41000000, 0x40000000, 0x40000000, 0x40000000,
   1022     0x80000180, 0x1bfc3e80, 0xbffffbfe, 0x40000000, 0x40000008, 0x40000000,
   1023     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1024     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1025     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1026     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1027     0x80000180, 0x1bfcde80, 0xbffffbfe, 0x40000000, 0x40000008, 0x40000000,
   1028     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1029     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1030     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1031     0x40000000, 0x40000000, 0x41000000, 0x40000000, 0x40000000, 0x40000000,
   1032     0x80000180, 0x1bfcde80, 0xbffffbfe, 0x40000000, 0x40000008, 0x40000000,
   1033     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1034     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1035     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1036     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1037     0x80000180, 0x17fc7e80, 0xbffffbfe, 0x40000000, 0x40000008, 0x40000000,
   1038     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1039     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1040     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1041     0x40000000, 0x40000000, 0x41000000, 0x40000000, 0x40000000, 0x40000000,
   1042     0x80000180, 0x17fc7e80, 0xbffffbfe, 0x40000000, 0x40000008, 0x40000000,
   1043     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1044     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1045     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1046     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1047     0x80000180, 0x17fc3e80, 0xbffffbfe, 0x40000000, 0x40000008, 0x40000000,
   1048     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1049     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1050     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1051     0x40000000, 0x40000000, 0x41000000, 0x40000000, 0x40000000, 0x40000000,
   1052     0x80000180, 0x17fc3e80, 0xbffffbfe, 0x40000000, 0x40000008, 0x40000000,
   1053     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1054     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1055     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1056     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1057     0x80000180, 0x13fcbe80, 0xbffffbfe, 0x40000000, 0x40000008, 0x40000000,
   1058     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1059     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1060     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1061     0x40000000, 0x40000000, 0x41000000, 0x40000000, 0x40000000, 0x40000000,
   1062     0x80000180, 0x13fcbe80, 0xbffffbfe, 0x40000000, 0x40000008, 0x40000000,
   1063     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1064     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1065     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1066     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1067     0x80000180, 0x13fc7e80, 0xbffffbfe, 0x40000000, 0x40000008, 0x40000000,
   1068     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1069     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1070     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1071     0x40000000, 0x40000000, 0x41000000, 0x40000000, 0x40000000, 0x40000000,
   1072     0x80000180, 0x13fc7e80, 0xbffffbfe, 0x40000000, 0x40000008, 0x40000000,
   1073     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1074     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1075     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1076     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1077     0x80000180, 0xffcfe80, 0xbffffbfe, 0x40000000, 0x40000008, 0x40000000,
   1078     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1079     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1080     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1081     0x40000000, 0x40000000, 0x41000000, 0x40000000, 0x40000000, 0x40000000,
   1082     0x80000180, 0xffcfe80, 0xbffffbfe, 0x40000000, 0x40000008, 0x40000000,
   1083     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1084     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1085     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1086     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1087     0x80000180, 0xffcbe80, 0xbffffbfe, 0x40000000, 0x40000008, 0x40000000,
   1088     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1089     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1090     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1091     0x40000000, 0x40000000, 0x41000000, 0x40000000, 0x40000000, 0x40000000,
   1092     0x80000180, 0xffcbe80, 0xbffffbfe, 0x40000000, 0x40000008, 0x40000000,
   1093     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1094     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1095     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1096     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1097     0x80000180, 0x1ffc5e80, 0xbffffbfe, 0x44000000, 0x40000000, 0x40000000,
   1098     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1099     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1100     0x40000000, 0x41000000, 0x40000000, 0x40000000, 0x40000000, 0x80000180,
   1101     0x1ffc5e80, 0xbffffbfe, 0x44000000, 0x40000000, 0x40000000, 0x40000000,
   1102     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1103     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1104     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x80000180, 0x1ffc1e80,
   1105     0xbffffbfe, 0x44000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1106     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1107     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x41000000,
   1108     0x40000000, 0x40000000, 0x40000000, 0x80000180, 0x1ffc1e80, 0xbffffbfe,
   1109     0x44000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1110     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1111     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1112     0x40000000, 0x40000000, 0x80000180, 0x1dfc5e80, 0xbffffbfe, 0x40000000,
   1113     0x40000002, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1114     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x41000000, 0x40000000,
   1115     0x40000000, 0x40000000, 0x80000180, 0x1dfc5e80, 0xbffffbfe, 0x40000000,
   1116     0x40000002, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1117     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1118     0x40000000, 0x40000000, 0x80000180, 0x1dfc1e80, 0xbffffbfe, 0x40000000,
   1119     0x40000002, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1120     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x41000000, 0x40000000,
   1121     0x40000000, 0x40000000, 0x80000180, 0x1dfc1e80, 0xbffffbfe, 0x40000000,
   1122     0x40000002, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1123     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1124     0x40000000, 0x40000000, 0x80000180, 0x1bfcfe80, 0xbffffbfe, 0x40000000,
   1125     0x48000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1126     0x41000000, 0x40000000, 0x40000000, 0x40000000, 0x80000180, 0x1bfcfe80,
   1127     0xbffffbfe, 0x40000000, 0x48000000, 0x40000000, 0x40000000, 0x40000000,
   1128     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1129     0x80000180, 0x1bfcbe80, 0xbffffbfe, 0x40000000, 0x48000000, 0x40000000,
   1130     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x41000000, 0x40000000,
   1131     0x40000000, 0x40000000, 0x80000180, 0x1bfcbe80, 0xbffffbfe, 0x40000000,
   1132     0x48000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1133     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x80000180, 0xdfc5e80,
   1134     0xbffffbfe, 0x40000000, 0x40000002, 0x40000000, 0x40000000, 0x41000000,
   1135     0x40000000, 0x40000000, 0x40000000, 0x80000180, 0xdfc5e80, 0xbffffbfe,
   1136     0x40000000, 0x40000002, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1137     0x40000000, 0x40000000, 0x80000180, 0xdfc1e80, 0xbffffbfe, 0x40000000,
   1138     0x40200000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1139     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1140     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1141     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1142     0x40000000, 0x41000000, 0x40000000, 0x40000000, 0x40000000, 0x80000180,
   1143     0xdfc1e80, 0xbffffbfe, 0x40000000, 0x40200000, 0x40000000, 0x40000000,
   1144     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1145     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1146     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1147     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1148     0x40000000, 0x40000000, 0x80000180, 0xbfcfe80, 0xbffffbfe, 0x40000000,
   1149     0x40200000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1150     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1151     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1152     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1153     0x40000000, 0x41000000, 0x40000000, 0x40000000, 0x40000000, 0x80000180,
   1154     0xbfcfe80, 0xbffffbfe, 0x40000000, 0x40200000, 0x40000000, 0x40000000,
   1155     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1156     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1157     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1158     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1159     0x40000000, 0x40000000, 0x80000180, 0xbfc9e80, 0xbffffbfe, 0x40000000,
   1160     0x40000008, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1161     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x41000000,
   1162     0x40000000, 0x40000000, 0x40000000, 0x80000180, 0xbfc9e80, 0xbffffbfe,
   1163     0x40000000, 0x40000008, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1164     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000,
   1165     0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x80000180
   1166 };
   1167 
   1168 /*
   1169  * Function:
   1170  *      trident2p_ovstb_toggle
   1171  * Purpose:
   1172  *      Execute the OVST sequence for Trident2Plus_A0 devices
   1173  * Parameters:
   1174  *      unit - StrataSwitch unit #
   1175 */
   1176 void
   1177 trident2p_ovstb_toggle(int unit)
   1178 {
   1179     int i = 0;
   1180     int array_length = 0;
   1181     int write_data_count = 0;
   1182     uint32 read_data = 0;
   1183       
   1184     array_length = sizeof(trident2p_write_data) / sizeof(uint32); 
   1185     WRITE_TOP_UC_TAP_CONTROLr(unit, 0x2e);
   1186     WRITE_TOP_UC_TAP_CONTROLr(unit, 0x2e);
   1187     WRITE_TOP_UC_TAP_CONTROLr(unit, 0x2f);
   1188     READ_TOP_UC_TAP_CONTROLr(unit, &read_data);
   1189 
   1190     for ( i=0; i < array_length; i++)
   1191     {
   1192         WRITE_TOP_UC_TAP_WRITE_DATAr(unit, trident2p_write_data[write_data_count]);
   1193         WRITE_TOP_UC_TAP_CONTROLr(unit, 0x2f);
   1194         READ_TOP_UC_TAP_READ_DATAr(unit, &read_data);
   1195         write_data_count++;
   1196     
   1197     }
   1198       
   1199     WRITE_TOP_UC_TAP_CONTROLr(unit, 0x2f);
   1200     WRITE_TOP_UC_TAP_CONTROLr(unit, 0x2e);
   1201     WRITE_TOP_UC_TAP_CONTROLr(unit, 0x2c);
   1202 
   1203     return;    
   1204 }
   1205 
   1206 
   1207 /*
   1208  * Function:
   1209  *      soc_td2p_idb_buf_reset
   1210  * Purpose:
   1211  *      Poll until Cell Assembly and OBM buffers are empty.
   1212  * Parameters:
   1213  *      unit    - (IN) Unit number.
   1214  *      port    - (IN) Logical SOC port number.
   1215  *      reset   - (IN) Reset.
   1216  * Returns:
   1217  *      SOC_E_XXX
   1218  */
   1219 int
   1220 soc_td2p_idb_buf_reset(int unit, soc_port_t port, int reset)
   1221 {
   1222     soc_info_t *si = &SOC_INFO(unit);
   1223     soc_reg_t reg;
   1224     soc_field_t field;
   1225     uint64 rval64;
   1226     int phy_port;
   1227     int pgw;
   1228     int xlp;
   1229     int port_index;
   1230     int obm;
   1231     soc_timeout_t to;
   1232     int use_count;
   1233     int fifo_empty;
   1234     static const soc_reg_t pgw_obm_use_counter_regs[] = {
   1235         PGW_OBM0_USE_COUNTERr, PGW_OBM1_USE_COUNTERr,
   1236         PGW_OBM2_USE_COUNTERr, PGW_OBM3_USE_COUNTERr
   1237     };
   1238     static const soc_field_t pgw_obm_use_counter_fields[] = {
   1239         PORT0_USE_COUNTf, PORT1_USE_COUNTf,
   1240         PORT2_USE_COUNTf, PORT3_USE_COUNTf
   1241     };
   1242 
   1243     /* If not reset, nothing to do */
   1244     if (!reset) {
   1245         return SOC_E_NONE;
   1246     }
   1247 
   1248     /* Get physical port PGW information */
   1249     phy_port = si->port_l2p_mapping[port];
   1250     SOC_IF_ERROR_RETURN
   1251         (soc_td2p_phy_port_pgw_info_get(unit, phy_port,
   1252                                         &pgw, &xlp, &port_index));
   1253 
   1254     /* Assume values returned above are valid */
   1255     reg = pgw_obm_use_counter_regs[xlp];
   1256     field = pgw_obm_use_counter_fields[port_index];
   1257     obm = pgw | SOC_REG_ADDR_INSTANCE_MASK;
   1258 
   1259     if (!SAL_BOOT_SIMULATION) {
   1260         /* Poll until Cell Assembly and OBM buffers are empty */
   1261         soc_timeout_init(&to, 250000, 0);
   1262         for (;;) {
   1263             /* Get PGW use counter */
   1264             SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, obm, port_index,
   1265                                             &rval64));
   1266             use_count = soc_reg64_field32_get(unit, reg, rval64, field);
   1267 
   1268             /* Get PGW fifo empty flag */
   1269             SOC_IF_ERROR_RETURN(READ_PGW_BOD_STATUS1r(unit, port, &rval64));
   1270             fifo_empty = soc_reg64_field32_get(unit, PGW_BOD_STATUS1r,
   1271                                                rval64, PGW_BOD_FIFO_EMPTYf);
   1272 
   1273             if ((use_count == 0) && (fifo_empty == 1)) {
   1274                 break;
   1275             }
   1276 
   1277             if (soc_timeout_check(&to)) {
   1278                 LOG_ERROR(BSL_LS_SOC_COMMON,
   1279                           (BSL_META_U(unit,
   1280                                       "PGW buffer reset timeout: port %d, %s, "
   1281                                       "timeout (use_count: %d) "
   1282                                       "(pgw_bod_fifo_emty:%d)\n"),
   1283                            port, SOC_PORT_NAME(unit, port),
   1284                            use_count, fifo_empty));
   1285                 return SOC_E_INTERNAL;
   1286             }
   1287         }
   1288     }
   1289 
   1290     return SOC_E_NONE;
   1291 }
   1292 
   1293 STATIC int
   1294 _soc_td2p_port_credit_size_get(int unit, soc_port_t port, int *ep_credit_size)
   1295 {
   1296     int speed_max;
   1297 
   1298     if (ep_credit_size == NULL) {
   1299         return SOC_E_INTERNAL;
   1300     }
   1301 
   1302     SOC_IF_ERROR_RETURN(
   1303         soc_td2p_port_speed_get(unit, port, &speed_max));
   1304 
   1305     if (IS_OVERSUB_PORT(unit, port)) {
   1306       if (speed_max >= 100000) {
   1307          return SOC_E_PARAM;
   1308       } else if (speed_max >= 40000) {
   1309          *ep_credit_size = _TD2P_MMU_EGR_MMU_CREDIT_LIMIT_OVERSUB(40G);
   1310       } else if (speed_max >= 20000) {
   1311          *ep_credit_size = _TD2P_MMU_EGR_MMU_CREDIT_LIMIT_OVERSUB(20G);
   1312       } else {
   1313          *ep_credit_size = _TD2P_MMU_EGR_MMU_CREDIT_LIMIT_OVERSUB(10G);
   1314       }
   1315     } else {
   1316        if (speed_max >= 100000) {
   1317           *ep_credit_size = _TD2P_MMU_EGR_MMU_CREDIT_LIMIT_LINERATE(100G);
   1318        } else if (speed_max >= 40000) {
   1319           *ep_credit_size = _TD2P_MMU_EGR_MMU_CREDIT_LIMIT_LINERATE(40G);
   1320        } else if (speed_max >= 20000) {
   1321           *ep_credit_size = _TD2P_MMU_EGR_MMU_CREDIT_LIMIT_LINERATE(20G);
   1322        } else {
   1323           *ep_credit_size = _TD2P_MMU_EGR_MMU_CREDIT_LIMIT_LINERATE(10G);
   1324        }
   1325     }
   1326 
   1327     return SOC_E_NONE;
   1328 }
   1329 
   1330 /*
   1331  * Function:
   1332  *      _soc_td2p_mmu_ep_credit_set
   1333  * Purpose:
   1334  *      Initalize EP credits in MMU so EP is in charge
   1335  *      of distributing the correct number of credits.
   1336  * Parameters:
   1337  *      unit    - (IN) Unit number.
   1338  *      port    - (IN) Logical SOC port number.
   1339  * Returns:
   1340  *      SOC_E_XXX
   1341  */
   1342 STATIC int
   1343 _soc_td2p_mmu_ep_credit_set(int unit, soc_port_t port)
   1344 {
   1345     soc_info_t *si = &SOC_INFO(unit);
   1346     int phy_port;
   1347     int mmu_port;
   1348     int ep_credit_size = 0;
   1349     soc_reg_t reg;
   1350     uint32 rval;
   1351 
   1352     /* Get physical port */
   1353     phy_port = si->port_l2p_mapping[port];
   1354     if (phy_port == -1) {
   1355         return SOC_E_INTERNAL;
   1356     }
   1357 
   1358     /* Get MMU port */
   1359     mmu_port = si->port_p2m_mapping[phy_port];
   1360     if (mmu_port == -1) {
   1361         return SOC_E_INTERNAL;
   1362     }
   1363     mmu_port &= 0x3F;    /* Convert mmu port number for pipe */
   1364 
   1365     /* Wait until credits are initialised at non-optimum value
   1366      * EP passes MMU 1 credit per cycle, so worse case delay is 95 cycles after EGR_ENABLE is set.
   1367      * @793.75MHz, this is ~120ns.
   1368      */
   1369     sal_usleep(1);
   1370 
   1371     if (SOC_PBMP_MEMBER(si->xpipe_pbm, port)) {
   1372         reg = ES_PIPE0_MMU_PORT_CREDITr;
   1373     } else {
   1374         reg = ES_PIPE1_MMU_PORT_CREDITr;
   1375     }
   1376 
   1377     SOC_IF_ERROR_RETURN(_soc_td2p_port_credit_size_get(unit, port, &ep_credit_size));
   1378     SOC_IF_ERROR_RETURN
   1379         (soc_reg32_get(unit, reg, REG_PORT_ANY, mmu_port, &rval));
   1380     soc_reg_field_set(unit, reg, &rval, INIT_CREDITf, ep_credit_size);
   1381     SOC_IF_ERROR_RETURN
   1382         (soc_reg32_set(unit, reg, REG_PORT_ANY, mmu_port, rval));
   1383 
   1384     return SOC_E_NONE;
   1385 }
   1386 
   1387 /*
   1388  * Function:
   1389  *      _soc_td2p_mmu_ep_credit_reset
   1390  * Purpose:
   1391  *      Reset EP credits
   1392  * Parameters:
   1393  *      unit    - (IN) Unit number.
   1394  *      port    - (IN) Logical SOC port number.
   1395  * Returns:
   1396  *      SOC_E_XXX
   1397  */
   1398 STATIC int
   1399 _soc_td2p_mmu_ep_credit_reset(int unit, soc_port_t port)
   1400 {
   1401     soc_info_t *si = &SOC_INFO(unit);
   1402     int phy_port;
   1403     int mmu_port;
   1404     soc_reg_t reg;
   1405     uint32 rval;
   1406 
   1407     /* Get physical port */
   1408     phy_port = si->port_l2p_mapping[port];
   1409     if (phy_port == -1) {
   1410         return SOC_E_INTERNAL;
   1411     }
   1412 
   1413     /* Get MMU port */
   1414     mmu_port = si->port_p2m_mapping[phy_port];
   1415     if (mmu_port == -1) {
   1416         return SOC_E_INTERNAL;
   1417     }
   1418     mmu_port &= 0x3F;    /* Convert mmu port number for pipe */
   1419 
   1420     if (SOC_PBMP_MEMBER(si->xpipe_pbm, port)) {
   1421         reg = ES_PIPE0_MMU_PORT_CREDITr;
   1422     } else {
   1423         reg = ES_PIPE1_MMU_PORT_CREDITr;
   1424     }
   1425 
   1426     SOC_IF_ERROR_RETURN
   1427         (soc_reg32_get(unit, reg, REG_PORT_ANY, mmu_port, &rval));
   1428     soc_reg_field_set(unit, reg, &rval, INIT_CREDITf, 0);
   1429     SOC_IF_ERROR_RETURN
   1430         (soc_reg32_set(unit, reg, REG_PORT_ANY, mmu_port, rval));
   1431 
   1432     return SOC_E_NONE;
   1433 }
   1434 
   1435 /*
   1436  * Function:
   1437  *      soc_td2p_edb_buf_reset
   1438  * Purpose:
   1439  *      Initialize EP credits in MMU, release EDB port buffer and
   1440  *      enable cell request in EP.
   1441  * Parameters:
   1442  *      unit    - (IN) Unit number.
   1443  *      port    - (IN) Logical SOC port number.
   1444  *      reset   - (IN) Reset.
   1445  * Returns:
   1446  *      SOC_E_XXX
   1447  */
   1448 int
   1449 soc_td2p_edb_buf_reset(int unit, soc_port_t port, int reset)
   1450 {
   1451     soc_info_t *si = &SOC_INFO(unit);
   1452     uint32 entry[SOC_MAX_MEM_WORDS];
   1453     int phy_port;
   1454     int use_pfc_optimized_settings = FALSE;
   1455 
   1456     /* Get physical port */
   1457     phy_port = si->port_l2p_mapping[port];
   1458     if (phy_port == -1) {
   1459         return SOC_E_INTERNAL;
   1460     }
   1461 
   1462     if (reset) {
   1463         /*
   1464          * Hold EDB port buffer in reset state and disable cell
   1465          * request generation in EP.
   1466          */
   1467         SOC_IF_ERROR_RETURN
   1468             (READ_EGR_ENABLEm(unit, MEM_BLOCK_ALL, phy_port, entry));
   1469         soc_mem_field32_set(unit, EGR_ENABLEm, entry, PRT_ENABLEf, 0);
   1470         SOC_IF_ERROR_RETURN
   1471             (WRITE_EGR_ENABLEm(unit, MEM_BLOCK_ALL, phy_port, entry));
   1472 
   1473         SOC_IF_ERROR_RETURN
   1474             (READ_EGR_PER_PORT_BUFFER_SFT_RESETm(unit, MEM_BLOCK_ALL,
   1475                                                  phy_port, entry));
   1476         soc_mem_field32_set(unit, EGR_PER_PORT_BUFFER_SFT_RESETm,
   1477                             entry, ENABLEf, 1);
   1478         SOC_IF_ERROR_RETURN
   1479             (WRITE_EGR_PER_PORT_BUFFER_SFT_RESETm(unit, MEM_BLOCK_ALL,
   1480                                                   phy_port, entry));
   1481     } else {
   1482 
   1483         /* Initialize EP credits in MMU */
   1484         SOC_IF_ERROR_RETURN(_soc_td2p_mmu_ep_credit_reset(unit, port));
   1485 
   1486         /* If system is able to use optimized settings, set
   1487            credit limit accordingly, else use default */
   1488         use_pfc_optimized_settings = soc_td2p_use_pfc_optimized_settings(unit);
   1489         if (use_pfc_optimized_settings) {
   1490            SOC_IF_ERROR_RETURN(soc_td2p_set_mmu_credit_limit(unit, port));
   1491         }
   1492 
   1493         /*
   1494          * Release EDB port buffer reset and
   1495          * enable cell request generation in EP.
   1496          */
   1497         SOC_IF_ERROR_RETURN
   1498             (READ_EGR_PER_PORT_BUFFER_SFT_RESETm(unit, MEM_BLOCK_ALL,
   1499                                                  phy_port, entry));
   1500         soc_mem_field32_set(unit, EGR_PER_PORT_BUFFER_SFT_RESETm,
   1501                             entry, ENABLEf, 0);
   1502         SOC_IF_ERROR_RETURN
   1503             (WRITE_EGR_PER_PORT_BUFFER_SFT_RESETm(unit, MEM_BLOCK_ALL,
   1504                                                   phy_port, entry));
   1505 
   1506         SOC_IF_ERROR_RETURN
   1507             (READ_EGR_ENABLEm(unit, MEM_BLOCK_ALL, phy_port, entry));
   1508         soc_mem_field32_set(unit, EGR_ENABLEm, entry, PRT_ENABLEf, 1);
   1509         SOC_IF_ERROR_RETURN
   1510             (WRITE_EGR_ENABLEm(unit, MEM_BLOCK_ALL, phy_port, entry));
   1511 
   1512         /* If system is able to use optimized settings, set
   1513            watermark thresh accordingly, else use default */
   1514         if (use_pfc_optimized_settings) {
   1515            SOC_IF_ERROR_RETURN(_soc_td2p_mmu_ep_credit_set(unit, port));
   1516            SOC_IF_ERROR_RETURN(
   1517            soc_td2p_set_edb_pfc_watermark_threshold(unit, port));
   1518         }
   1519     }
   1520 
   1521     return SOC_E_NONE;
   1522 }
   1523 
   1524 
   1525 STATIC int
   1526 _soc_td2p_resource_data_check(int unit, int num_res, soc_port_resource_t *res)
   1527 {
   1528     int i, j;
   1529     /* null check for all resource data before accessing register */
   1530     for (i = 0 ; i < num_res ; ++i) {
   1531         soc_port_resource_t *p = &res[i];
   1532         if (NULL == p) {
   1533             /* 
   1534             * COVERITY 
   1535             * It is kept intentionally as a defensive check. 
   1536             */
   1537             /* coverity[dead_error_line] */
   1538             return SOC_E_PARAM;
   1539         }
   1540         for (j = 0; j < p->num_lanes ; ++j) {
   1541             soc_port_lane_info_t *p_lane_info = p->lane_info[j];
   1542             if (NULL == p_lane_info) {
   1543                 return SOC_E_PARAM;
   1544             }
   1545         }
   1546     }
   1547     return SOC_E_NONE;
   1548 }
   1549 
   1550 
   1551 /*
   1552  * Function:
   1553  *      soc_td2p_pgw_obm_default_set
   1554  * Purpose:
   1555  *      Reconfigure PGW registers in flex port sequence
   1556  *      In this function following registers will be initialized.
   1557  *          PGW_OBM[0-3]_CONTROL
   1558  *          PGW_OBM[0-3]_HIGH_PRI_BYTE_DROP[]
   1559  *          PGW_OBM[0-3]_HIGH_PRI_PKT_DROP[]
   1560  *          PGW_OBM[0-3]_LOW_PRI_BYTE_DROP[]
   1561  *          PGW_OBM[0-3]_LOW_PRI_DROP_PROB[]
   1562  *          PGW_OBM[0-3]_LOW_PRI_PKT_DROP[]
   1563  *          PGW_OBM[0-3]_USE_COUNTER
   1564  *          PGW_OBM[0-3]_SHARED_CONFIG
   1565  *      If default_flag is PGW_OBM_INIT_HW_DEFAULT,
   1566  *      register will be intialized by HW reset value
   1567  *      If default_flag is PGW_OBM_INIT_SW_DEFAULT,
   1568  *      register will be intialized by SW reset value
   1569  *
   1570  * Parameters:
   1571  *      unit         - (IN) Unit number.
   1572  *      num_res      - (IN) Number of resource
   1573  *      res          - (IN) Resource data structure
   1574  *      default_flag - (IN) PGW_OBM_INIT_HW_DEFAULT
   1575  *                          Use HW reset value for register value
   1576  *                   - (IN) PGW_OBM_INIT_SW_DEFAULT
   1577  *                          Use SW default value
   1578  *
   1579  * Assumption:
   1580  *      This function cannot access SOC_INFO data structure.
   1581  *      So assume followings condition should be checked
   1582  *      before calling this function.
   1583  *
   1584  *      1. master/slave pgw block is valid
   1585  *             si->block_valid[PGW_CL_BLOCK(unit, pgw)] is true
   1586  *             si->block_valid[PGW_CL_BLOCK(unit, pgw+1)] is true
   1587  *      2. port block is used
   1588  *             block = PGW_CL_BLOCK(unit, pgw);
   1589  *             SOC_BLOCK_PORT(unit, block) < 0
   1590  *      3. num_res should be correct number of resource data structure.
   1591  *         all resource data structure should be accessed by using
   1592  *         pointer offset by res_num. If the pointer of resource data is NULL,
   1593  *         returns SOC_E_PARAM.
   1594  *
   1595  * Returns:
   1596  *      SOC_E_XXX
   1597  */
   1598 STATIC int
   1599 soc_td2p_pgw_obm_default_set(int unit, int num_res, soc_port_resource_t *res,
   1600                              int default_flag)
   1601 {
   1602     int obm_inst;
   1603     int xlp, port_index;
   1604     int i, j;
   1605 
   1606     for (i = 0 ; i < num_res ; ++i) {
   1607         soc_port_resource_t *p = &res[i];
   1608 
   1609         for (j = 0; j < p->num_lanes ; ++j) {
   1610             soc_port_lane_info_t *p_lane_info = p->lane_info[j];
   1611 
   1612             xlp = p_lane_info->xlp;
   1613             port_index = p_lane_info->port_index;
   1614             obm_inst = p_lane_info->pgw | SOC_REG_ADDR_INSTANCE_MASK;
   1615 
   1616             /* PGW_OBM[0-3]_CONTROL */
   1617             SOC_IF_ERROR_RETURN
   1618                 (soc_td2_obm_ctrl_reg_default_set(unit, xlp,
   1619                                port_index, obm_inst, p->oversub, default_flag));
   1620             /* PGW_OBM[0-3]_LOW_PRI_DROP_PROB[] */
   1621             SOC_IF_ERROR_RETURN
   1622                 (soc_td2p_obm_prob_drop_default_set (unit, xlp,
   1623                                port_index, obm_inst, default_flag));
   1624             /* PGW_OBM[0-3]_HIGH_PRI_BYTE_DROP[] */
   1625             SOC_IF_ERROR_RETURN
   1626                 (soc_td2p_obm_high_pri_byte_drop_default_set(unit, xlp,
   1627                                port_index, obm_inst));
   1628             /* PGW_OBM[0-3]_HIGH_PRI_PKT_DROP[] */
   1629             SOC_IF_ERROR_RETURN
   1630                 (soc_td2p_obm_high_pri_pkt_drop_default_set(unit, xlp,
   1631                                port_index, obm_inst));
   1632             /* PGW_OBM[0-3]_LOW_PRI_BYTE_DROP[] */
   1633             SOC_IF_ERROR_RETURN
   1634                 (soc_td2p_obm_low_pri_byte_drop_default_set(unit, xlp,
   1635                                port_index, obm_inst));
   1636             /* PGW_OBM[0-3]_LOW_PRI_PKT_DROP[] */
   1637             SOC_IF_ERROR_RETURN
   1638                 (soc_td2p_obm_low_pri_pkt_drop_default_set(unit, xlp,
   1639                                port_index, obm_inst));
   1640             /* PGW_OBM[0-3]_USE_COUNTER */
   1641             SOC_IF_ERROR_RETURN
   1642                 (soc_td2_obm_use_counter_reg_default_set(unit, xlp,
   1643                                port_index, obm_inst));
   1644             /* PGW_OBM[0-3]_SHARED_CONFIG */
   1645             SOC_IF_ERROR_RETURN
   1646                 (soc_td2_obm_shared_config_reg_default_set(unit, xlp,
   1647                                port_index, obm_inst, default_flag));
   1648         }
   1649     }
   1650     return SOC_E_NONE;
   1651 }
   1652 
   1653 STATIC int
   1654 soc_td2p_pgw_obm_hw_default_set(int unit, int num_res, soc_port_resource_t *res)
   1655 {
   1656     int rv;
   1657     rv = soc_td2p_pgw_obm_default_set(unit, num_res, res,
   1658                                       PGW_OBM_INIT_HW_DEFAULT);
   1659     return rv;
   1660 }
   1661 
   1662 STATIC int
   1663 soc_td2p_pgw_obm_sw_default_set(int unit, int num_res, soc_port_resource_t *res)
   1664 {
   1665     int rv;
   1666     rv = soc_td2p_pgw_obm_default_set(unit, num_res, res,
   1667                                       PGW_OBM_INIT_SW_DEFAULT);
   1668     return rv;
   1669 }
   1670 
   1671 /*
   1672  * Function:
   1673  *      soc_td2p_pgw_obm_set
   1674  * Purpose:
   1675  *      Reconfigure PGW_OBM registers in flex port sequence
   1676  *      This function will do two things,
   1677  *      1. clear all registers for old ports which exists in pre-Flex status
   1678  *      2. initialize all registers for new ports which exists in post-Flex status
   1679  *
   1680  * Parameters:
   1681  *      unit         - (IN) Unit number.
   1682  *      pre_num_res  - (IN) Number of resource data which exist in pre-Flex status
   1683  *      post_num_res - (IN) Number of resource data which exist in post-Flex status
   1684  *      pre_res      - (IN) Resource data structure pointer in pre-Flex status
   1685  *      post_res     - (IN) Resource data structure pointer in post-Flex status
   1686  *
   1687  * Returns:
   1688  *      SOC_E_XXX
   1689  */
   1690 int
   1691 soc_td2p_pgw_obm_set(int unit,
   1692                      int pre_num_res,  soc_port_resource_t *pre_res,
   1693                      int post_num_res, soc_port_resource_t *post_res)
   1694 {
   1695     SOC_IF_ERROR_RETURN(
   1696         _soc_td2p_resource_data_check(unit, pre_num_res, pre_res));
   1697     SOC_IF_ERROR_RETURN(
   1698         _soc_td2p_resource_data_check(unit, post_num_res, post_res));
   1699 
   1700     SOC_IF_ERROR_RETURN(soc_td2p_pgw_obm_hw_default_set(unit,
   1701                                                         pre_num_res, pre_res));
   1702     SOC_IF_ERROR_RETURN(soc_td2p_pgw_obm_sw_default_set(unit,
   1703                                                         post_num_res, post_res));
   1704     return SOC_E_NONE;
   1705 }
   1706 
   1707 
   1708 /*
   1709  * Function:
   1710  *      soc_td2p_obm_threshold_default_set
   1711  * Purpose:
   1712  *      Reconfigure PGW Threshold in flex port sequence
   1713  *      In this function following registers will be initialized.
   1714  *          PGW_OBM[0-3]_THRESHOLD
   1715  *          PGW_OBM[0-3]_THRESHOLD2
   1716  *      If default_flag is PGW_OBM_INIT_HW_DEFAULT,
   1717  *      register will be intialized by HW reset value
   1718  *      If default_flag is PGW_OBM_INIT_SW_DEFAULT,
   1719  *      register will be intialized by SW reset value
   1720  *
   1721  * Parameters:
   1722  *      unit         - (IN) Unit number
   1723  *      num_res      - (IN) Number of resource
   1724  *      res          - (IN) Resource data structure
   1725  *      lossless     - (IN) Lossless configuration of device
   1726  *      default_flag - (IN) PGW_OBM_INIT_HW_DEFAULT
   1727  *                          Use HW reset value for register value
   1728  *                   - (IN) PGW_OBM_INIT_SW_DEFAULT
   1729  *                          Use SW default value
   1730  *
   1731  * Assumption:
   1732  *      This function cannot access SOC_INFO data structure.
   1733  *      So assume followings condition should be checked
   1734  *      before calling this function.
   1735  *
   1736  *      1. master/slave pgw block is valid
   1737  *             si->block_valid[PGW_CL_BLOCK(unit, pgw)] is true
   1738  *             si->block_valid[PGW_CL_BLOCK(unit, pgw+1)] is true
   1739  *      2. port block is used
   1740  *             block = PGW_CL_BLOCK(unit, pgw);
   1741  *             SOC_BLOCK_PORT(unit, block) < 0
   1742  *      3. num_res should be correct number of resource data structure.
   1743  *         all resource data structure should be accessed by using
   1744  *         pointer offset by res_num. If the pointer of resource data is NULL,
   1745  *         returns SOC_E_PARAM.
   1746  *
   1747  * Returns:
   1748  *      SOC_E_XXX
   1749  */
   1750 STATIC
   1751 soc_error_t soc_td2p_obm_threshold_default_set(int unit,
   1752                                                int num_res,
   1753                                                soc_port_resource_t *res,
   1754                                                int lossless,
   1755                                                int default_flag)
   1756 {
   1757     pgw_obm_threshold_regs_t pgw_obm_threshold_regs =
   1758                              soc_trident2_pgw_obm_threshold_regs_get(unit);
   1759     soc_reg_t  reg;
   1760     int obm_inst;
   1761     int xlp, port_index, speed;
   1762     int i, j;
   1763 
   1764     for (i = 0 ; i < num_res ; ++i) {
   1765         soc_port_resource_t *p = &res[i];
   1766 
   1767         speed = p->speed;
   1768         for (j = 0; j < p->num_lanes ; ++j) {
   1769             soc_port_lane_info_t *p_lane_info = p->lane_info[j];
   1770 
   1771             xlp        = p_lane_info->xlp;
   1772             port_index = p_lane_info->port_index;
   1773             obm_inst   = p_lane_info->pgw | SOC_REG_ADDR_INSTANCE_MASK;
   1774 
   1775             reg = pgw_obm_threshold_regs[xlp];
   1776             /* PGW_OBM[0-3]_THRESHOLD */
   1777             SOC_IF_ERROR_RETURN
   1778                 (soc_td2p_set_obm_registers(unit, reg, speed, port_index,
   1779                                             obm_inst, lossless, default_flag));
   1780 
   1781             /* PGW_OBM[0-3]_THRESHOLD2 */
   1782             SOC_IF_ERROR_RETURN
   1783                 (soc_td2p_obm_cut_through_threshold_set(unit, xlp, port_index,
   1784                                                      obm_inst, default_flag));
   1785         }
   1786     }
   1787 
   1788     return SOC_E_NONE;
   1789 }
   1790 
   1791 STATIC int
   1792 soc_td2p_obm_threshold_hw_default_set(int unit, int num_res,
   1793                                       soc_port_resource_t *res,
   1794                                       int lossless)
   1795 {
   1796 
   1797     SOC_IF_ERROR_RETURN(soc_td2p_obm_threshold_default_set(unit, num_res, res,
   1798                                                lossless,
   1799                                                PGW_OBM_INIT_HW_DEFAULT));
   1800     return SOC_E_NONE;
   1801 }
   1802 
   1803 STATIC int
   1804 soc_td2p_obm_threshold_sw_default_set(int unit, int num_res,
   1805                                       soc_port_resource_t *res,
   1806                                       int lossless)
   1807 {
   1808     SOC_IF_ERROR_RETURN(soc_td2p_obm_threshold_default_set(unit, num_res, res,
   1809                                                lossless,
   1810                                                PGW_OBM_INIT_SW_DEFAULT));
   1811     return SOC_E_NONE;
   1812 }
   1813 
   1814 /*
   1815  * Function:
   1816  *      soc_td2p_obm_threshold_set
   1817  * Purpose:
   1818  *  Reconfigure PGW registers in flex port sequence
   1819  *  In this function PGW OBM threshold registers will be initialized.
   1820  *  This function will do two things,
   1821  *  1. clear all registers for old ports which exists in pre-Flex status
   1822  *  2. initialize all registers for new ports which exists in post-Flex status
   1823  *
   1824  * Parameters:
   1825  *  unit         - (IN) Unit number.
   1826  *  pre_num_res  - (IN) Number of resource data which exist in pre-Flex status
   1827  *  post_num_res - (IN) Number of resource data which exist in post-Flex status
   1828  *  pre_res      - (IN) Resource data structure pointer in pre-Flex status
   1829  *  post_res     - (IN) Resource data structure pointer in post-Flex status
   1830  *  lossless     - (IN) mmu lossless information
   1831  *
   1832  * Returns:
   1833  *  SOC_E_XXX
   1834  *
   1835  * Note : For 100G port, this functions expects the ovsersub field to be
   1836  * disabled.
   1837  */
   1838 soc_error_t soc_td2p_obm_threshold_set(int unit,
   1839                          int pre_num_res, soc_port_resource_t *pre_res,
   1840                          int post_num_res, soc_port_resource_t *post_res,
   1841                          int lossless)
   1842 {
   1843     
   1844     SOC_IF_ERROR_RETURN(_soc_td2p_resource_data_check(unit, pre_num_res,
   1845                                                       pre_res));
   1846     SOC_IF_ERROR_RETURN(_soc_td2p_resource_data_check(unit, post_num_res,
   1847                                                       post_res));
   1848     SOC_IF_ERROR_RETURN(soc_td2p_obm_threshold_hw_default_set(unit,
   1849                         pre_num_res, pre_res, lossless));
   1850 
   1851     SOC_IF_ERROR_RETURN(soc_td2p_obm_threshold_sw_default_set(unit, 
   1852                         post_num_res, post_res, lossless));
   1853 
   1854     return SOC_E_NONE;
   1855 }
   1856 
   1857 
   1858 /*
   1859  * Function:
   1860  *      soc_td2p_pgw_port_default_set
   1861  * Purpose:
   1862  *      Reconfigure PGW registers in flex port sequence
   1863  *      In this function following registers will be initialized.
   1864  *          PGW_OBM[0-3]_MAX_USAGE:
   1865  *          PGW_OBM_PORT[0-15]_FC_CONFIG
   1866  *          PGW_OBM[0-3]_PRIORITY_MAP[]
   1867  *      If default_flag is PGW_OBM_INIT_HW_DEFAULT,
   1868  *      register will be intialized by HW reset value
   1869  *      If default_flag is PGW_OBM_FLEXPORT_INIT_SW_DEFAULT,
   1870  *      register will be intialized by SW reset value
   1871  *
   1872  * Parameters:
   1873  *      unit         - (IN) Unit number.
   1874  *      num_res      - (IN) Number of resource
   1875  *      res          - (IN) Resource data structure
   1876  *      default_flag - (IN) PGW_OBM_INIT_HW_DEFAULT
   1877  *                          Use HW reset value for register value
   1878  *                   - (IN) PGW_OBM_FLEXPORT_INIT_SW_DEFAULT
   1879  *                          Use SW default value
   1880  *      lossless     - (IN) mmu lossless information
   1881  *
   1882  * Assumption:
   1883  *      This function cannot access SOC_INFO data structure.
   1884  *      So assume followings condition should be checked
   1885  *      before calling this function.
   1886  *
   1887  *      1. master/slave pgw block is valid
   1888  *             si->block_valid[PGW_CL_BLOCK(unit, pgw)] is true
   1889  *             si->block_valid[PGW_CL_BLOCK(unit, pgw+1)] is true
   1890  *      2. port block is used
   1891  *             block = PGW_CL_BLOCK(unit, pgw);
   1892  *             SOC_BLOCK_PORT(unit, block) < 0
   1893  *      3. num_res should be correct number of resource data structure.
   1894  *         all resource data structure should be accessed by using
   1895  *         pointer offset by res_num. If the pointer of resource data is NULL,
   1896  *         returns SOC_E_PARAM.
   1897  *
   1898  * Returns:
   1899  *      SOC_E_XXX
   1900  */
   1901 STATIC int
   1902 soc_td2p_pgw_port_default_set(int unit, int num_res, soc_port_resource_t *res,
   1903                               int lossless, int default_flag)
   1904 {
   1905     int obm_inst;
   1906     int xlp, port_index;
   1907     int i, j;
   1908 
   1909     for (i = 0 ; i < num_res ; ++i) {
   1910         soc_port_resource_t *p = &res[i];
   1911 
   1912         for (j = 0; j < p->num_lanes ; ++j) {
   1913             soc_port_lane_info_t *p_lane_info = p->lane_info[j];
   1914 
   1915             xlp = p_lane_info->xlp;
   1916             port_index = p_lane_info->port_index;
   1917 
   1918             obm_inst = p_lane_info->pgw | SOC_REG_ADDR_INSTANCE_MASK;
   1919 
   1920             /* PGW_MIB_RESET */
   1921             SOC_IF_ERROR_RETURN(soc_td2p_pgw_mib_reset_reg_default_set(
   1922                                     unit, xlp, port_index, obm_inst));
   1923 
   1924             /* PGW_OBM[0-3]_MAX_USAGE */
   1925             SOC_IF_ERROR_RETURN
   1926                 (soc_td2_obm_max_usage_reg_default_set(unit, xlp,
   1927                                        port_index, obm_inst));
   1928 
   1929             if (!lossless) {
   1930                 continue;
   1931             }
   1932 
   1933             /* PGW_OBM_PORT[0-15]_FC_CONFIG */
   1934             SOC_IF_ERROR_RETURN
   1935                 (soc_td2_obm_fc_config_reg_default_set(unit, xlp, port_index,
   1936                                        obm_inst, p->logical_port, p->oversub,
   1937                                        default_flag));
   1938         }
   1939     }
   1940 
   1941     return SOC_E_NONE;
   1942 }
   1943 
   1944 STATIC int
   1945 soc_td2p_pgw_port_hw_default_set(int unit, int num_res, soc_port_resource_t *res,
   1946                                  int lossless)
   1947 {
   1948     int rv;
   1949     rv = soc_td2p_pgw_port_default_set(unit, num_res, res,
   1950                                        lossless, PGW_OBM_INIT_HW_DEFAULT);
   1951     return rv;
   1952 }
   1953 
   1954 STATIC int
   1955 soc_td2p_pgw_port_sw_default_set(int unit, int num_res, soc_port_resource_t *res,
   1956                                  int lossless)
   1957 {
   1958     int rv;
   1959     rv = soc_td2p_pgw_port_default_set(unit, num_res, res,
   1960                                        lossless, PGW_OBM_INIT_SW_DEFAULT);
   1961     return rv;
   1962 }
   1963 
   1964 
   1965 STATIC
   1966 int soc_td2p_ovr_sub_tdm_config_get(int unit,
   1967                                     _soc_td2p_ovr_sub_tdm_t *ovs_tdm)
   1968 {
   1969     int pipe;
   1970     int group;
   1971     int slot;
   1972     uint32 wt_group_select;
   1973     soc_reg_t reg;
   1974     uint32 rval;
   1975     int index;
   1976     mmu_ovs_group_wt_regs_t mmu_ovs_group_wt_regs =
   1977                                         mmu_ovs_group_wt_regs_td2p_local;
   1978     _soc_td2p_ovr_sub_mmu_tdm_t *mmu_tdm = &ovs_tdm->mmu_tdm;
   1979     mmu_ovs_group_regs_t mmu_ovs_group_regs =
   1980                            soc_trident2_mmu_ovs_group_regs_get(unit);
   1981     mmu_ovs_group_wt_select_regs_t mmu_ovs_group_wt_select_regs =
   1982                            soc_trident2_mmu_ovs_group_wt_select_regs_get(unit);
   1983 
   1984     /* Initialize MMU OverSub TDM Ports Database */
   1985     for (pipe = 0; pipe < TD2P_PIPES_PER_DEV; pipe++) {
   1986         for (group = 0; group < GET_MMU_OVS_GCOUNT(unit); group++) {
   1987             for (slot = 0; slot < _MMU_OVS_GROUP_TDM_LENGTH; slot++) {
   1988                 /* Invalid MMU Port 0x3f */
   1989                 mmu_tdm->mmu_port[pipe][group][slot] = 0x3f;
   1990             }
   1991         }
   1992     }
   1993 
   1994     /* Extract MMU Over Subscription TDM */
   1995     for (pipe = 0; pipe < TD2P_PIPES_PER_DEV; pipe++) {
   1996         wt_group_select = 0;
   1997         SOC_IF_ERROR_RETURN
   1998             (soc_reg32_get(unit, mmu_ovs_group_wt_select_regs[pipe],
   1999                                REG_PORT_ANY, 0, &wt_group_select));
   2000 
   2001         for (group = 0; group < GET_MMU_OVS_GCOUNT(unit); group++) {
   2002             reg = mmu_ovs_group_regs[pipe][group];
   2003             for (slot = 0; slot < _MMU_OVS_GROUP_TDM_LENGTH; slot++) {
   2004                 SOC_IF_ERROR_RETURN
   2005                     (soc_reg32_get(unit, reg, REG_PORT_ANY, slot, &rval));
   2006                 mmu_tdm->mmu_port[pipe][group][slot] =
   2007                                 soc_reg_field_get(unit, reg, rval, MMU_PORTf);
   2008             }
   2009         }
   2010         /* TD2P supports 4 oversub speeds only 10/20 and 40*/
   2011         for (group = 0; group < _MMU_OVS_WT_GROUP_COUNT; group++) {
   2012             reg = mmu_ovs_group_wt_regs[pipe][group];
   2013             for (index = 0; index < _MMU_OVS_GROUP_TDM_LENGTH; index++) {
   2014                 SOC_IF_ERROR_RETURN
   2015                     (soc_reg32_get(unit, reg, REG_PORT_ANY, index, &rval));
   2016                 mmu_tdm->grp_wt[pipe][group][index] =
   2017                      soc_reg_field_get(unit, reg, rval, WEIGHTf);
   2018             }
   2019         }
   2020             /*Read the Group Weight Sel fields, Used later while
   2021              * configuring the MMU TDM.
   2022              */
   2023         for (group = 0; group < MAX_MMU_OVS_GROUP_COUNT; group++) {
   2024             mmu_tdm->grp_wt_sel[pipe][group] =
   2025                 soc_reg_field_get(unit,  mmu_ovs_group_wt_select_regs[pipe],
   2026                                   wt_group_select,
   2027                                   mmu_ovr_group_wt_select_fields[group]);
   2028         }
   2029     }
   2030 
   2031     return SOC_E_NONE;
   2032 }
   2033 
   2034 
   2035 /* TD2P OverSub Scheduler */
   2036 /* For Egress MMU OvrSub schedular configuration, we need to create weight
   2037  * group for each port speed.
   2038  * If we didn't have a Port speed setup in the config file and during flex
   2039  * operation, if we want to setup a port with new speed(Eg:40) we need to
   2040  * create a new group. This functions sets up the Weight configuration.
   2041  */
   2042 STATIC
   2043 int soc_td2p_ovr_sub_tdm_mmu_group_create(int unit, int pipe, int speed_max,
   2044                                           _soc_td2p_ovr_sub_tdm_t *ovs_tdm,
   2045                                           int *group_new)
   2046 {
   2047     mmu_ovs_group_regs_t mmu_ovs_group_regs =
   2048                           soc_trident2_mmu_ovs_group_regs_get(unit);
   2049     mmu_ovs_group_wt_select_regs_t mmu_ovs_group_wt_select_regs =
   2050                            soc_trident2_mmu_ovs_group_wt_select_regs_get(unit);
   2051     mmu_ovs_group_wt_regs_t mmu_ovs_group_wt_regs =
   2052                                         mmu_ovs_group_wt_regs_td2p_local;
   2053     _soc_td2p_ovr_sub_mmu_tdm_t *mmu_tdm = &ovs_tdm->mmu_tdm;
   2054     int index;
   2055     int group; 
   2056     int slot;
   2057     int wt_group = 0;
   2058     soc_reg_t reg;
   2059     uint32 rval;
   2060     int weight;
   2061 
   2062     for (group = 0; group < GET_MMU_OVS_GCOUNT(unit); group++) {
   2063         if (mmu_tdm->grp_wt_sel[pipe][group] == td2p_ovs_wt_group_speed_NA) {
   2064             /* This is an empty group, Initialize the group */
   2065             break;
   2066         }
   2067     }
   2068 
   2069     if (group == GET_MMU_OVS_GCOUNT(unit)) {
   2070         /* No Groups Available, Hence return SOC_E_RESOURCE */
   2071         return SOC_E_RESOURCE;
   2072     }
   2073     reg = mmu_ovs_group_regs[pipe][group];
   2074 
   2075     /* Initialize the MMU port to 0x3f for all the slots */
   2076     for (slot = 0; slot < _MMU_OVS_GROUP_TDM_LENGTH; slot++) {
   2077         rval = 0;
   2078         soc_reg_field_set(unit, reg, &rval, MMU_PORTf, 0x3f);
   2079         SOC_IF_ERROR_RETURN
   2080             (soc_reg32_set(unit, reg, REG_PORT_ANY, slot, rval));
   2081     }
   2082     
   2083     if ( speed_max <= 11000 ) {
   2084         wt_group = td2p_ovs_wt_group_speed_10G;
   2085     } else if ( speed_max <= 21000 ) {
   2086         wt_group = td2p_ovs_wt_group_speed_20G;
   2087     } else if ( speed_max <= 42000 ) {
   2088         wt_group = td2p_ovs_wt_group_speed_40G;
   2089     } else {
   2090         wt_group = td2p_ovs_wt_group_speed_NA; /* "not" valid group */
   2091     }
   2092     /* use 2500M as weight unit */
   2093     weight = (speed_max > 2500 ? speed_max : 2500) / 2500;
   2094 
   2095     /* Read the Current OverSub Group Select Register per pipe, and assign the
   2096      * group_weight for this group*/
   2097     rval = 0;   
   2098     SOC_IF_ERROR_RETURN
   2099         (soc_reg32_get(unit, mmu_ovs_group_wt_select_regs [pipe], 
   2100                        REG_PORT_ANY, 0, &rval));
   2101     /* Clear the Existing Weight, and append the new weight */
   2102     soc_reg_field_set(unit, mmu_ovs_group_wt_select_regs [pipe],
   2103                       &rval, mmu_ovr_group_wt_select_fields[group], wt_group);
   2104     SOC_IF_ERROR_RETURN
   2105         (soc_reg32_set(unit, mmu_ovs_group_wt_select_regs [pipe], 
   2106                        REG_PORT_ANY, 0, rval));
   2107 
   2108     /* For the new Group, set the weight for all it's entries */
   2109     rval = 0;   
   2110     reg = mmu_ovs_group_wt_regs[pipe][wt_group];
   2111     for (index = 0; index < _MMU_OVS_GROUP_TDM_LENGTH; index++) {
   2112         soc_reg_field_set(unit, reg, &rval, WEIGHTf,
   2113                           weight * (index + 1));
   2114         SOC_IF_ERROR_RETURN
   2115             (soc_reg32_set(unit, reg, REG_PORT_ANY, index, rval));
   2116     }
   2117     *group_new = group;
   2118     return SOC_E_NONE;
   2119 }
   2120 
   2121 
   2122 
   2123 
   2124 /* TD2P OverSub Scheduler */
   2125 /* This function expects the oversub field in port_resource_t structure to be 0
   2126  * for 100G ports. Since oversub on 100G ports is not supported for TD2Plus.
   2127  *
   2128  * This function Updates the Over Sub TDM calender.
   2129  */
   2130 STATIC
   2131 int soc_td2p_ovr_sub_tdm_db_update(int unit, int num_port_res,
   2132                                    soc_port_resource_t *port_res,
   2133                                    _soc_td2p_ovr_sub_tdm_t *ovs_tdm,
   2134                                    int db_type)
   2135 {
   2136     int pipe, res_count;
   2137     int group;
   2138     int slot = 0;
   2139     int count;
   2140     int speed_max;
   2141     int group_wt;
   2142     int mmu_port, mmu_port_update;
   2143     _soc_td2p_ovr_sub_mmu_tdm_t *mmu_tdm = &ovs_tdm->mmu_tdm;
   2144 
   2145     for ( res_count = 0; res_count < num_port_res; res_count++) {
   2146         soc_port_resource_t *p = &port_res[res_count];
   2147 
   2148         /* If OBM is not enabled then continue */
   2149         if (!p->oversub) {
   2150             continue;
   2151         }
   2152 
   2153         if (p->flags & SOC_PORT_RESOURCE_INACTIVE) {
   2154             continue;
   2155         }
   2156 
   2157         speed_max   = p->speed;
   2158         pipe        = p->pipe;
   2159 
   2160         if (_SOC_TRIDENT2P_UPDATE_TDM_PRE  == db_type) {
   2161             mmu_port        = p->mmu_port & 0x3f;
   2162             mmu_port_update = 0x3f; /* Invalid MMU Port */
   2163         } else {
   2164             mmu_port        = 0x3f;
   2165             mmu_port_update = p->mmu_port & 0x3f;      /* Valid MMU Port */
   2166         }
   2167 
   2168         if ( speed_max <= 11000 ) {
   2169             group_wt = td2p_ovs_wt_group_speed_10G;
   2170         } else if ( speed_max <= 21000 ) {
   2171             group_wt = td2p_ovs_wt_group_speed_20G;
   2172         } else if ( speed_max <= 42000 ) {
   2173             group_wt = td2p_ovs_wt_group_speed_40G;
   2174         } else {
   2175             group_wt = td2p_ovs_wt_group_speed_NA; /* "not" valid group */
   2176         }
   2177 
   2178         /* Update MMU OverSub TDM Ports Database */
   2179         count = 0;
   2180         for (group = 0; group < GET_MMU_OVS_GCOUNT(unit); group++) {
   2181             /* Identify the group that needs to be updated */
   2182             if (mmu_tdm->grp_wt_sel[pipe][group] != group_wt) {
   2183                 continue;
   2184             }
   2185             /* Update MMU OverSub TDM Ports Database */
   2186             for (slot = 0; slot < _MMU_OVS_GROUP_TDM_LENGTH; slot++) {
   2187                 /* Invalid MMU Port 0x3f */
   2188                 if (mmu_tdm->mmu_port[pipe][group][slot] == mmu_port) {
   2189                     count++;
   2190                     break;
   2191                 }
   2192             }
   2193             if (count) {
   2194                 break;
   2195             }
   2196         }
   2197 
   2198         if (group ==  GET_MMU_OVS_GCOUNT(unit) && 
   2199             (_SOC_TRIDENT2P_UPDATE_TDM_PRE  != db_type)) {
   2200             /* Group (or) Free slot not found.
   2201              * Need to allocate a new group if available */
   2202 
   2203             SOC_IF_ERROR_RETURN(
   2204                          soc_td2p_ovr_sub_tdm_mmu_group_create(unit, pipe,
   2205                                               speed_max, ovs_tdm, &group));
   2206 
   2207             /* Start from the begining slot */
   2208             mmu_tdm->grp_wt_sel[pipe][group] = group_wt;
   2209             slot = 0;
   2210             count = 1;
   2211 
   2212             /* MMU Port should be configured only once */
   2213             if (1 != count) {
   2214                 LOG_ERROR(BSL_LS_SOC_PORT,
   2215                           (BSL_META_U(unit,
   2216                            "MMU port %d cannot be found in MMU OVS GROUP TABLE: "
   2217                            "ES_PIPE_OVR_SUB_GRP_TBL\n"),
   2218                            mmu_port));
   2219                 return SOC_E_PARAM;
   2220             }
   2221         }
   2222 
   2223         /* Update the MMU_PORT */
   2224         mmu_tdm->tdm_update[pipe][group][slot] = 1;
   2225         mmu_tdm->mmu_port[pipe][group][slot] = mmu_port_update;
   2226     }
   2227     return SOC_E_NONE;
   2228 }
   2229 
   2230 STATIC
   2231 int soc_td2p_ovr_sub_tdm_hw_update(int unit,
   2232                                    _soc_td2p_ovr_sub_tdm_t *ovs_tdm)
   2233 {
   2234     int pgw_master;
   2235     int pipe;
   2236     int group;
   2237     int slot;
   2238     int index = 0;
   2239     int pgw;
   2240     int base;
   2241     soc_reg_t reg;
   2242     uint32 rval;
   2243     uint64 rval64, ctrl_rval64;
   2244     int obm_inst;
   2245     int phy_port;
   2246     int count = 0;
   2247     _soc_td2p_ovr_sub_mmu_tdm_t *mmu_tdm = &ovs_tdm->mmu_tdm;
   2248     mmu_ovs_group_regs_t mmu_ovs_group_regs =
   2249                            soc_trident2_mmu_ovs_group_regs_get(unit);
   2250     pgw_ovs_tdm_regs_t pgw_ovs_tdm_regs =
   2251                            soc_trident2_pgw_ovs_tdm_regs_get(unit);
   2252     pgw_tdm_fields_t pgw_tdm_fields =
   2253                            soc_trident2_pgw_tdm_fields_get(unit);
   2254     pgw_ovs_spacing_regs_t pgw_ovs_spacing_regs =
   2255                            soc_trident2_pgw_ovs_spacing_regs_get(unit);
   2256     pgw_spacing_fields_t pgw_spacing_fields =
   2257                            soc_trident2_pgw_spacing_fields_get(unit);
   2258     _soc_trident2_tdm_t *tdm;
   2259 
   2260     tdm = soc_td2_td2p_tdm_sched_info_get(unit, 0);
   2261     if (tdm == NULL) {
   2262         return SOC_E_INIT;
   2263     }
   2264     
   2265 
   2266     /* Initialize MMU OverSub TDM Ports Database */
   2267     for (pipe = 0; pipe < TD2P_PIPES_PER_DEV; pipe++) {
   2268         for (group = 0; group < GET_MMU_OVS_GCOUNT(unit); group++) {
   2269             for (slot = 0; slot < _MMU_OVS_GROUP_TDM_LENGTH; slot++) {
   2270                 if (mmu_tdm->tdm_update[pipe][group][slot]) {
   2271                     /* Invalid MMU Port 0x3f */
   2272                     reg = mmu_ovs_group_regs[pipe][group];
   2273 
   2274                     SOC_IF_ERROR_RETURN
   2275                      (soc_reg32_get(unit, reg, REG_PORT_ANY, slot, &rval));
   2276 
   2277                     soc_reg_field_set(unit, reg, &rval, MMU_PORTf,
   2278                              mmu_tdm->mmu_port[pipe][group][slot] & 0x3f);
   2279                     SOC_IF_ERROR_RETURN
   2280                         (soc_reg32_set(unit, reg, REG_PORT_ANY, slot, rval));
   2281                 }
   2282             }
   2283         }
   2284     }
   2285 
   2286     /* Extract PGW Over Subscription TDM */
   2287     for (pgw = 0; pgw < TD2P_PGWS_PER_DEV; pgw += TD2P_PGWS_PER_QUAD) {
   2288         pgw_master = pgw;
   2289 
   2290         if (( pgw == 2 ) || ( pgw == 6 )) {
   2291             pgw_master = pgw + 1;
   2292         }
   2293 
   2294         obm_inst = pgw_master | SOC_REG_ADDR_INSTANCE_MASK;
   2295 
   2296         /* Update PGW oversubscription ports TDM */
   2297         count = 0;
   2298         SOC_IF_ERROR_RETURN(soc_reg_get(unit, PGW_TDM_CONTROLr, obm_inst, 0,
   2299                                         &ctrl_rval64));
   2300         for (base = 0; base < _PGW_TDM_OVS_SIZE;
   2301                        base += _PGW_TDM_SLOTS_PER_REG) {
   2302             reg = pgw_ovs_tdm_regs[base / _PGW_TDM_SLOTS_PER_REG];
   2303             COMPILER_64_ZERO(rval64);
   2304             for (index = 0; index < _PGW_TDM_SLOTS_PER_REG; index++) {
   2305                 slot = base + index;
   2306                 phy_port = tdm->pgw_ovs_tdm[pgw_master / 2][slot];
   2307                 if (phy_port == NUM_EXT_PORTS) {
   2308                     phy_port = 0xff;
   2309                 } else {
   2310                     count++;
   2311                 }
   2312                 soc_reg64_field32_set(unit, reg, &rval64, pgw_tdm_fields[slot],
   2313                                       phy_port);
   2314             }
   2315             SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, obm_inst, 0,
   2316                                                             rval64));
   2317         }
   2318         soc_reg64_field32_set(unit, PGW_TDM_CONTROLr, &ctrl_rval64,
   2319                               OS_TDM_ENABLEf, count ? 1 : 0);
   2320         SOC_IF_ERROR_RETURN
   2321             (soc_reg_set(unit, PGW_TDM_CONTROLr, obm_inst, 0, ctrl_rval64));
   2322 
   2323         /* Configure PGW oversubscription port spacing */
   2324         for (base = 0; base < _PGW_TDM_OVS_SIZE;
   2325              base += _PGW_TDM_SLOTS_PER_REG) {
   2326             reg = pgw_ovs_spacing_regs[base / _PGW_TDM_SLOTS_PER_REG];
   2327             COMPILER_64_ZERO(rval64);
   2328             for (index = 0; index < _PGW_TDM_SLOTS_PER_REG; index++) {
   2329                 slot = base + index;
   2330                 phy_port = tdm->pgw_ovs_spacing[pgw_master / 2][slot];
   2331                 soc_reg64_field32_set(unit, reg, &rval64,
   2332                                       pgw_spacing_fields[slot], phy_port);
   2333             }
   2334             SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, obm_inst, 0, rval64));
   2335         }
   2336     }
   2337     return SOC_E_NONE;
   2338 }
   2339 
   2340 /*
   2341  * Function:
   2342  *      soc_td2p_ovr_sub_tdm_update
   2343  * Description:
   2344  *      Update PGW and MMU TDM Over subscription programming for flex port
   2345  * Parameters:
   2346  *      unit          - Device number
   2347  *      pre_num_res   - Number of Previous resources
   2348  *      pre_res       - Previous resource information.
   2349  *      post_num_res  - Number of Current resource configured
   2350  *      post_res      - Current port resource information.
   2351  */
   2352 int
   2353 soc_td2p_ovr_sub_tdm_update(int unit, 
   2354                          int pre_num_res, soc_port_resource_t *pre_res,
   2355                          int post_num_res, soc_port_resource_t *post_res)
   2356 {
   2357     _soc_td2p_ovr_sub_tdm_t *ovr_sub_tdm;
   2358     int rv;
   2359 
   2360     
   2361     SOC_IF_ERROR_RETURN(_soc_td2p_resource_data_check(unit, pre_num_res,
   2362                                                       pre_res));
   2363     SOC_IF_ERROR_RETURN(_soc_td2p_resource_data_check(unit, post_num_res,
   2364                                                       post_res));
   2365 
   2366     ovr_sub_tdm = sal_alloc(sizeof(_soc_td2p_ovr_sub_tdm_t), "ovr_sub_tdm");
   2367     if (ovr_sub_tdm == NULL) {
   2368         return SOC_E_MEMORY;
   2369     }
   2370     sal_memset(ovr_sub_tdm, 0, sizeof(_soc_td2p_ovr_sub_tdm_t));
   2371 
   2372     /* Recover the Over_Sub PGW and MMU TDM configuration from registers.
   2373      * Construct software database.
   2374      */
   2375     rv = soc_td2p_ovr_sub_tdm_config_get(unit, ovr_sub_tdm);
   2376     if (SOC_FAILURE(rv)) {
   2377         sal_free(ovr_sub_tdm);
   2378         return rv;
   2379     }
   2380 
   2381     /* Update the Pre OBM TDM configuration
   2382      * Free's the pre-occupied slots*/
   2383     rv = soc_td2p_ovr_sub_tdm_db_update(unit, pre_num_res, pre_res, ovr_sub_tdm,
   2384                                               _SOC_TRIDENT2P_UPDATE_TDM_PRE);
   2385     if (SOC_FAILURE(rv)) {
   2386         sal_free(ovr_sub_tdm);
   2387         return rv;
   2388     }
   2389 
   2390     /* Update the Post OBM TDM configuration
   2391      * Updates the Empty slots*/
   2392     rv = soc_td2p_ovr_sub_tdm_db_update(unit, post_num_res, post_res, ovr_sub_tdm,
   2393                                               _SOC_TRIDENT2P_UPDATE_TDM_POST);
   2394     if (SOC_FAILURE(rv)) {
   2395         sal_free(ovr_sub_tdm);
   2396         return rv;
   2397     }
   2398 
   2399     /* Updates the OBM TDM configuration in the Hardware */
   2400     rv = soc_td2p_ovr_sub_tdm_hw_update(unit, ovr_sub_tdm);
   2401     if (SOC_FAILURE(rv)) {
   2402         sal_free(ovr_sub_tdm);
   2403         return rv;
   2404     }
   2405 
   2406     sal_free(ovr_sub_tdm);
   2407     return SOC_E_NONE;
   2408 }
   2409 
   2410 
   2411 /*
   2412  * Function:
   2413  *      soc_td2p_egr_edb_xmit_ctrl_set
   2414  *
   2415  * Description:
   2416  *      Program EGR_EDB_XMIT_CTRL memory by considering
   2417  *      Oversub/Linerate mode and Cut-Through/SAF mode
   2418  *
   2419  * Parameters:
   2420  *      unit            - Device number
   2421  *      phy_port        - Physical port
   2422  *      speed           - Port speed
   2423  *      oversub         - Oversub is enabled or not
   2424  *      cut_thru_enable - Cut through mode is enabled or not
   2425  */
   2426 int soc_td2p_egr_edb_xmit_ctrl_set(int unit, int phy_port, int speed,
   2427                                    int oversub, int cut_thru_enable)
   2428 {
   2429     soc_info_t *si;
   2430     uint32 entry[SOC_MAX_MEM_WORDS];
   2431     soc_field_t reg_field;
   2432     int         start_cnt_val = 0;
   2433 
   2434     si = &SOC_INFO(unit);
   2435     sal_memset(entry, 0, sizeof(egr_edb_xmit_ctrl_entry_t));
   2436     SOC_IF_ERROR_RETURN(soc_mem_read(unit, EGR_EDB_XMIT_CTRLm, MEM_BLOCK_ALL,
   2437                                      phy_port, &entry));
   2438     if (!cut_thru_enable) {
   2439         if (oversub) {
   2440             reg_field = WAIT_FOR_2ND_MOPf;
   2441         } else {
   2442             reg_field = WAIT_FOR_MOPf;
   2443         }
   2444         soc_mem_field32_set(unit, EGR_EDB_XMIT_CTRLm, entry, START_CNTf, 0);
   2445         soc_mem_field32_set(unit, EGR_EDB_XMIT_CTRLm, entry, reg_field, 1);
   2446     } else {
   2447         if (oversub) {
   2448             start_cnt_val = _TD2_MMU_XMIT_START_CNT_OVERSUB;
   2449         } else {
   2450             start_cnt_val = _TD2_MMU_XMIT_START_CNT_LINERATE(speed);
   2451         }
   2452         soc_mem_field32_set(unit, EGR_EDB_XMIT_CTRLm, entry, START_CNTf,
   2453                             start_cnt_val);
   2454         soc_mem_field32_set(unit, EGR_EDB_XMIT_CTRLm, entry, WAIT_FOR_MOPf, 0);
   2455         soc_mem_field32_set(unit, EGR_EDB_XMIT_CTRLm, entry, WAIT_FOR_2ND_MOPf,
   2456                             0);
   2457     }
   2458     SOC_IF_ERROR_RETURN(soc_mem_write(unit, EGR_EDB_XMIT_CTRLm,
   2459                                       MEM_BLOCK_ALL,
   2460                                       phy_port, &entry));
   2461     return SOC_E_NONE;
   2462 }
   2463 
   2464 /*
   2465  * This function is used to enable or disable cut through when a port is 
   2466  * operating in store and forward mode. 
   2467  * Caller must pass the correct port_info pointer, corresponding to the port
   2468  * being configured (and sent by the BCM layer)
   2469  * To enable cut-through, pass enable = 1
   2470  * To disable cut-through, pass enable = 0
   2471  */
   2472 STATIC int 
   2473 soc_td2p_cut_thru_enable_disable(int unit,
   2474                                             soc_port_resource_t *port_info,
   2475                                             int enable)
   2476 {
   2477     uint32 rval;
   2478     uint32 speed;
   2479     int use_pfc_optimized_settings = FALSE;
   2480     egr_pfc_control_entry_t pfc_control;
   2481 
   2482     /* Mask unnecessary bits */
   2483     enable &= 0x1;
   2484 
   2485     SOC_IF_ERROR_RETURN(READ_ASF_PORT_CFGr(unit, port_info->logical_port,
   2486                         &rval));
   2487 
   2488     speed = soc_reg_field_get(unit, ASF_PORT_CFGr, rval, ASF_PORT_SPEEDf);
   2489 
   2490     /* Set port speed to 0 */
   2491     soc_reg_field_set(unit, ASF_PORT_CFGr, &rval, ASF_PORT_SPEEDf, 0);
   2492     SOC_IF_ERROR_RETURN(WRITE_ASF_PORT_CFGr(unit, port_info->logical_port,
   2493                         rval));
   2494 
   2495     if (!enable) {
   2496         /* Wait 8ms for draining all cells */
   2497         sal_usleep(8000);
   2498     }
   2499 
   2500     SOC_IF_ERROR_RETURN(soc_td2p_egr_edb_xmit_ctrl_set(
   2501                             unit, port_info->physical_port, port_info->speed,
   2502                             port_info->oversub, enable));
   2503 
   2504     /* Set UC_ASF_ENABLE, MC_ASF_ENABLE bits to 1 */
   2505     soc_reg_field_set(unit, ASF_PORT_CFGr, &rval, UC_ASF_ENABLEf, enable);
   2506     soc_reg_field_set(unit, ASF_PORT_CFGr, &rval, MC_ASF_ENABLEf, enable);
   2507     SOC_IF_ERROR_RETURN(WRITE_ASF_PORT_CFGr(unit, port_info->logical_port,
   2508                                             rval));
   2509 
   2510     if (enable) {
   2511         /* Wait 1 micro-sec */
   2512         sal_usleep(1);
   2513     }
   2514 
   2515     soc_reg_field_set(unit, ASF_PORT_CFGr, &rval, ASF_PORT_SPEEDf, speed);
   2516     SOC_IF_ERROR_RETURN(WRITE_ASF_PORT_CFGr(unit, port_info->logical_port,
   2517                                             rval));
   2518 
   2519     /* If system is able to use optimized settings,
   2520        disable EDB watermark to avoid credit underrun.
   2521        MMU mechanism will be used to optimize PFC response. */
   2522     use_pfc_optimized_settings = soc_td2p_use_pfc_optimized_settings(unit);
   2523     if (use_pfc_optimized_settings) {
   2524         SOC_IF_ERROR_RETURN(READ_EGR_PFC_CONTROLm(unit, MEM_BLOCK_ALL,
   2525             port_info->physical_port, &pfc_control));
   2526         soc_mem_field32_set(unit, EGR_PFC_CONTROLm, &pfc_control,
   2527             ENABLEf, enable ? 0 : 1);
   2528         SOC_IF_ERROR_RETURN(WRITE_EGR_PFC_CONTROLm(unit, MEM_BLOCK_ALL,
   2529             port_info->physical_port, &pfc_control));
   2530     }
   2531 
   2532     return SOC_E_NONE;
   2533 }
   2534 
   2535 int soc_td2p_max_speed_port_find(int phy_port, 
   2536                                         soc_port_resource_t *port_info,
   2537                                         int port_info_arr_size) 
   2538 {
   2539     int idx, index, speed;
   2540   
   2541     index = 0;
   2542     speed = port_info[index].speed;
   2543 
   2544     for (idx = 1; idx < port_info_arr_size; idx++) {
   2545         /* If all speeds are equal, '>' will return the 1st index,
   2546          * '>=' will return the last index
   2547          */
   2548         if (port_info[idx].speed > speed) {
   2549             speed = port_info[idx].speed;
   2550             index = idx;
   2551         }
   2552     }
   2553 
   2554     return index;
   2555 }
   2556 
   2557 /* This function fetches the current egress scheduler's TDM table number being
   2558  * used by the hardware. This function will be used during flexing, but its use
   2559  * is not restricted to flexing operations.
   2560  */
   2561 STATIC int soc_td2p_curr_egr_tdm_table_get(int unit, int pipe,
   2562                                            uint32 *table_num)
   2563 {
   2564     soc_reg_t reg;
   2565     uint32 rval;
   2566 
   2567     /* Return value of CURR_CALf in table_num */
   2568 
   2569     reg = (pipe == 0) ? ES_PIPE0_TDM_CONFIGr : ES_PIPE1_TDM_CONFIGr;
   2570 
   2571     SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
   2572 
   2573     *table_num = soc_reg_field_get(unit, reg, rval, CURR_CALf);
   2574 
   2575     return SOC_E_NONE;
   2576 }
   2577 
   2578 /* This function fetches the current ingress scheduler's TDM table number being
   2579  * used by the hardware. This function will be used during flexing, but its use
   2580  * is not restricted to flexing operations.
   2581  */
   2582 STATIC int soc_td2p_curr_ingr_tdm_table_get(int unit, int pgw_inst,
   2583                                             uint32 *table_num)
   2584 {
   2585     uint64 rval64;
   2586 
   2587     SOC_IF_ERROR_RETURN(soc_reg_get(unit, PGW_TDM_CONTROLr, pgw_inst, 0,
   2588                                     &rval64));
   2589 
   2590     /* Return value of LR_TDM_SEL in table_num */
   2591     *table_num = soc_reg64_field32_get(unit, PGW_TDM_CONTROLr, rval64, 
   2592                                        LR_TDM_SELf);
   2593 
   2594     return SOC_E_NONE;
   2595 }
   2596 
   2597 /* This function sets the new egress scheduler's TDM table number which will be
   2598  * used by the hardware. This function will be used during flexing, but its use
   2599  * is not restricted to flexing operations.
   2600  */
   2601 STATIC int soc_td2p_curr_egr_tdm_table_set(int unit, int pipe, 
   2602                                             uint32 table_num)
   2603 {
   2604     uint32 rval;
   2605     soc_reg_t reg;
   2606 
   2607     reg = (pipe == 0) ? ES_PIPE0_TDM_CONFIGr : ES_PIPE1_TDM_CONFIGr;
   2608 
   2609     SOC_IF_ERROR_RETURN (soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
   2610 
   2611     /* Mask unwanted bits */
   2612     table_num &= 0x1;
   2613 
   2614     /* Set CURR_CALf */
   2615     soc_reg_field_set(unit, reg, &rval, CURR_CALf, table_num);
   2616 
   2617     SOC_IF_ERROR_RETURN (soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval));
   2618 
   2619     return SOC_E_NONE;
   2620 }
   2621 
   2622 /* This function fetches the current ingress scheduler's TDM table number being
   2623  * used by the hardware.  This function will be used during flexing, but its use
   2624  * is not restricted to flexing operations.
   2625  */
   2626 STATIC int soc_td2p_curr_ingr_tdm_table_set(int unit, int pgw_inst,
   2627                                             int table_num)
   2628 {
   2629     uint64 rval64;
   2630 
   2631     SOC_IF_ERROR_RETURN(soc_reg_get(unit, PGW_TDM_CONTROLr, pgw_inst, 0,
   2632                                     &rval64));
   2633 
   2634     /* Mask unwanted bits */
   2635     table_num &= 0x1;
   2636 
   2637     /* Set LR_TDM_SEL */
   2638     soc_reg64_field32_set(unit, PGW_TDM_CONTROLr, &rval64, LR_TDM_SELf,
   2639                           table_num);
   2640 
   2641     SOC_IF_ERROR_RETURN (soc_reg_set(unit, PGW_TDM_CONTROLr, pgw_inst, 0,
   2642                          rval64));
   2643 
   2644     return SOC_E_NONE;
   2645 }
   2646 
   2647 /*
   2648  * This function checks if cut-through is enabled for a given port.
   2649  * If either unicast or multicast cut-through is enabled, the function
   2650  * returns TRUE else FALSE is returned
   2651  */
   2652 int soc_td2p_is_cut_thru_enabled(int unit, soc_port_t port, int *enable)
   2653 {
   2654     uint32 rval;
   2655     uint32 uc_enable, mc_enable;
   2656 
   2657     SOC_IF_ERROR_RETURN(READ_ASF_PORT_CFGr(unit, port, &rval));
   2658 
   2659     uc_enable = soc_reg_field_get(unit, ASF_PORT_CFGr, rval, UC_ASF_ENABLEf);
   2660     mc_enable = soc_reg_field_get(unit, ASF_PORT_CFGr, rval, MC_ASF_ENABLEf);
   2661 
   2662     /* This is for ensuring that the behavior of cut-through setting get is
   2663      * same as in _bcm_td2_port_asf_enable_get called by application
   2664      * (upper layer software), through bcm_esw_switch_control_port_get()
   2665      */
   2666     if (uc_enable & mc_enable) {
   2667         *enable = TRUE;
   2668     } else {
   2669         *enable = FALSE;
   2670     }
   2671 
   2672     return SOC_E_NONE;
   2673 }
   2674 
   2675 /*
   2676  * This function is used to clear various counters in EP block. The 
   2677  * counters to clear are mentioned in 'Reconfigure EP' section of TD2+ Flexport
   2678  */
   2679 STATIC int soc_td2p_ep_counters_clear(int unit, soc_port_resource_t *port_info)
   2680 {
   2681     uint64 val64;
   2682     uint32 val = 0;
   2683 
   2684     COMPILER_64_ZERO(val64);
   2685     SOC_IF_ERROR_RETURN(WRITE_EGR_TRILL_TX_PKTSr(unit, port_info->logical_port,
   2686                         val));
   2687     SOC_IF_ERROR_RETURN(WRITE_EGR_TRILL_TX_ACCESS_PORT_TRILL_PKTS_DISCARDEDr(unit, port_info->logical_port, val));
   2688     SOC_IF_ERROR_RETURN(WRITE_EGR_FCOE_DELIMITER_ERROR_FRAMESr(unit,
   2689                         port_info->logical_port, val));
   2690     SOC_IF_ERROR_RETURN(WRITE_EGR_FCOE_INVALID_CRC_FRAMESr(unit, 
   2691                         port_info->logical_port, val));
   2692 
   2693     SOC_IF_ERROR_RETURN(WRITE_TPCEr(unit, port_info->logical_port, val64));
   2694 
   2695     SOC_IF_ERROR_RETURN(WRITE_TDBGC0r(unit, port_info->logical_port, val64));
   2696     SOC_IF_ERROR_RETURN(WRITE_TDBGC1r(unit, port_info->logical_port, val64));
   2697     SOC_IF_ERROR_RETURN(WRITE_TDBGC2r(unit, port_info->logical_port, val64));
   2698     SOC_IF_ERROR_RETURN(WRITE_TDBGC3r(unit, port_info->logical_port, val64));
   2699     SOC_IF_ERROR_RETURN(WRITE_TDBGC4r(unit, port_info->logical_port, val64));
   2700     SOC_IF_ERROR_RETURN(WRITE_TDBGC5r(unit, port_info->logical_port, val64));
   2701     SOC_IF_ERROR_RETURN(WRITE_TDBGC6r(unit, port_info->logical_port, val64));
   2702     SOC_IF_ERROR_RETURN(WRITE_TDBGC7r(unit, port_info->logical_port, val64));
   2703     SOC_IF_ERROR_RETURN(WRITE_TDBGC8r(unit, port_info->logical_port, val64));
   2704     SOC_IF_ERROR_RETURN(WRITE_TDBGC9r(unit, port_info->logical_port, val64));
   2705     SOC_IF_ERROR_RETURN(WRITE_TDBGC10r(unit, port_info->logical_port, val64));
   2706     SOC_IF_ERROR_RETURN(WRITE_TDBGC11r(unit, port_info->logical_port, val64));
   2707 
   2708     return SOC_E_NONE;
   2709 }
   2710 
   2711 STATIC int soc_td2p_port_resource_tdm_calculate(int unit, 
   2712                                             int curr_port_info_size,
   2713                                             soc_port_resource_t *curr_port_info,
   2714                                             int new_port_info_size,
   2715                                             soc_port_resource_t *new_port_info,
   2716                                             soc_td2p_info_t *si_info)
   2717 {
   2718 #ifdef BCM_56860_A0
   2719     int rv, i;
   2720     int num_of_subport;
   2721     soc_info_t *si;
   2722     _soc_trident2_tdm_t *tdm;
   2723     tdm_soc_t _chip_pkg;
   2724     tdm_mod_t *_tdm_pkg;
   2725     int phy_port;
   2726     int port;
   2727     int speed_max, index, slot;
   2728     soc_pbmp_t pbmp;
   2729 
   2730     /* soc info has new values */
   2731     si = &SOC_INFO(unit);
   2732 
   2733     tdm = soc_td2_td2p_tdm_sched_info_get(unit, 1);
   2734     if (tdm == NULL) {
   2735         return SOC_E_MEMORY;
   2736     }
   2737 
   2738     PBMP_PORT_ITER(unit, port) {
   2739         if (SOC_PBMP_MEMBER(si->all.disabled_bitmap, port)) {
   2740             continue;
   2741         }
   2742 
   2743         /* Since soc info structure has been updated before this function is
   2744          * called, we use the information provided by it
   2745          */
   2746         phy_port = si->port_l2p_mapping[port];
   2747 
   2748         tdm->speed[phy_port] = si->port_speed_max[port];
   2749         if (si->port_speed_max[port] < 1000) {
   2750             tdm->speed[phy_port] = 1000;
   2751         }
   2752         tdm->port_state[phy_port] = SOC_PBMP_MEMBER(si->oversub_pbm, port) ?
   2753                                                     PORT_STATE_OVERSUB : 
   2754                                                     PORT_STATE_LINERATE;
   2755 
   2756         num_of_subport = 0;
   2757         if (tdm->speed[phy_port] >= 120000) {
   2758             num_of_subport = 11;
   2759         } else if (tdm->speed[phy_port] >= 100000) {
   2760             num_of_subport = 9;
   2761         } else if (tdm->speed[phy_port] >= 40000) {
   2762             num_of_subport = 3;
   2763         } else if (tdm->speed[phy_port] >= 20000) {
   2764             num_of_subport = 1;
   2765         }
   2766         for (i = 0; i < num_of_subport; i++) {
   2767             tdm->port_state[phy_port + i + 1] = PORT_STATE_SUBPORT;
   2768         }
   2769     }
   2770 
   2771     tdm->speed[0] = 1000;
   2772     tdm->speed[129] = 1000;
   2773     tdm->tdm_bw = si->bandwidth / 1000;
   2774 
   2775     SOC_PBMP_ASSIGN(pbmp, si->oversub_pbm);
   2776     SOC_PBMP_AND(pbmp, si->xpipe_pbm);
   2777     if (tdm->tdm_bw == 720) { /* 720g special handling */
   2778         /* tell tdm code the pipe is oversub only if all ports are oversub */
   2779         SOC_PBMP_PORT_ADD(pbmp, 0); /* cpu port */
   2780         tdm->pipe_ovs_state[0] = SOC_PBMP_EQ(pbmp, si->xpipe_pbm);
   2781     } else {
   2782         /* tell tdm code the pipe is oversub if any ports is oversub */
   2783         tdm->pipe_ovs_state[0] = SOC_PBMP_NOT_NULL(pbmp);
   2784     }
   2785     SOC_PBMP_ASSIGN(pbmp, si->oversub_pbm);
   2786     SOC_PBMP_AND(pbmp, si->ypipe_pbm);
   2787     if (tdm->tdm_bw == 720) { /* 720g special handling */
   2788         /* tell tdm code the pipe is oversub only if all ports are oversub */
   2789         SOC_PBMP_PORT_ADD(pbmp, 105); /* loopback port */
   2790         tdm->pipe_ovs_state[1] = SOC_PBMP_EQ(pbmp, si->ypipe_pbm);
   2791     } else {
   2792         /* tell tdm code the pipe is oversub if any ports is oversub */
   2793         tdm->pipe_ovs_state[1] = SOC_PBMP_NOT_NULL(pbmp);
   2794     }
   2795 
   2796     tdm->manage_port_type = 0;
   2797     if (SOC_PBMP_NOT_NULL(si->management_pbm)) {
   2798         speed_max = 0;
   2799         for (phy_port = 13; phy_port <= 16; phy_port++) {
   2800             port = si->port_p2l_mapping[phy_port];
   2801             if (port == -1) {
   2802                 continue;
   2803             }
   2804             if (speed_max < si->port_speed_max[port]) {
   2805                 speed_max = si->port_speed_max[port];
   2806             }
   2807         }
   2808         if (speed_max <= 1000) {
   2809             tdm->manage_port_type = 1; /* 4 x 1g */
   2810         } else if (speed_max <= 2500) {
   2811             tdm->manage_port_type = 2; /* 4 * 2.5g */
   2812         } else {
   2813             tdm->manage_port_type = 3; /* 1 x 10g */
   2814         }
   2815         if (tdm->manage_port_type > 0) {
   2816             tdm->pgw_tdm[0][0] = 1234; /* magic number used by tdm code */
   2817         }
   2818     }
   2819     if (tdm->manage_port_type != 0) {
   2820         _chip_pkg.soc_vars.td2p.tdm_mgmt_en = 1;
   2821     } else {
   2822         _chip_pkg.soc_vars.td2p.tdm_mgmt_en = 0;
   2823     }
   2824 
   2825     for (slot = 0; slot <= _MMU_TDM_LENGTH; slot++) {
   2826         tdm->mmu_tdm[0][slot] = NUM_EXT_PORTS;
   2827         tdm->mmu_tdm[1][slot] = NUM_EXT_PORTS;
   2828     }
   2829 
   2830     /* Configure ingress scheduler back up calendar */
   2831     _chip_pkg.unit = unit;
   2832     _chip_pkg.num_ext_ports = TD2P_NUM_EXT_PORTS;
   2833     _chip_pkg.state=sal_alloc((_chip_pkg.num_ext_ports)*sizeof(int *), "port state list");
   2834     _chip_pkg.speed=sal_alloc((_chip_pkg.num_ext_ports)*sizeof(int *), "port speed list");
   2835     for (index=1; index<(_chip_pkg.num_ext_ports); index++) {
   2836         _chip_pkg.state[index] = tdm->port_state[index];
   2837     }
   2838     _chip_pkg.state[0]=1; /* enable cpu port */
   2839     _chip_pkg.state[_chip_pkg.num_ext_ports-1]=1; /* enable loopback port */
   2840 
   2841     /* This pointer is used internally by set tdm table API, and is
   2842      * initialized in tdm_td2p_init (src/soc/esw/tdm/set_tdm.c).
   2843      * _soc_set_tdm_tbl calls functions in the array of function pointers
   2844      * (_chip_exec)
   2845      * This pointer is not used by SDK code.
   2846      */
   2847     /* coverity[uninit_use_in_call] */
   2848     _chip_pkg.pmap = NULL;
   2849     for (index=0; index<(_chip_pkg.num_ext_ports); index++) {
   2850         _chip_pkg.speed[index] = tdm->speed[index];
   2851     }
   2852 
   2853     /*
   2854      * Map detected core clk frequency to TDM algorithm internal code
   2855      * value.
   2856      */
   2857     switch (si->frequency) {
   2858            case 790:
   2859            case 760:
   2860                _chip_pkg.clk_freq = 760;
   2861                break;
   2862            case 635:
   2863                _chip_pkg.clk_freq = 608;
   2864                break;
   2865            case 537:
   2866                _chip_pkg.clk_freq = 518;
   2867                break;
   2868            case 421:
   2869                _chip_pkg.clk_freq = 415;
   2870                break;
   2871            default:
   2872                _chip_pkg.clk_freq = (si->frequency > 760) ? (760)
   2873                                        : si->frequency;
   2874     }
   2875 
   2876     /* This function initializes only the fields which the caller of
   2877      * _soc_set_tdm_tbl should fill. The remaining fields of _chip_pkg
   2878      * structure are initialized and used internally within _soc_set_tdm_tbl
   2879      * (and other tdm library functions)
   2880      */
   2881     /* coverity[uninit_use_in_call] */
   2882     _tdm_pkg = _soc_set_tdm_tbl(SOC_SEL_TDM(&_chip_pkg));
   2883     if (!_tdm_pkg) {
   2884         LOG_CLI((BSL_META_U(unit,
   2885                 "Unsupported config for TDM calendar generation\n")));
   2886         return SOC_E_FAIL;
   2887     }
   2888 
   2889     sal_memcpy(tdm->pgw_tdm[0], _tdm_pkg->_chip_data.cal_0.cal_main, sizeof(int)*MAX_PGW_TDM_LENGTH);
   2890     sal_memcpy(tdm->pgw_ovs_tdm[0], _tdm_pkg->_chip_data.cal_0.cal_grp[0], sizeof(int)*_PGW_TDM_OVS_SIZE);
   2891     sal_memcpy(tdm->pgw_ovs_spacing[0], _tdm_pkg->_chip_data.cal_0.cal_grp[1], sizeof(int)*_PGW_TDM_OVS_SIZE);
   2892     sal_memcpy(tdm->pgw_tdm[1], _tdm_pkg->_chip_data.cal_1.cal_main, sizeof(int)*MAX_PGW_TDM_LENGTH);
   2893     sal_memcpy(tdm->pgw_ovs_tdm[1], _tdm_pkg->_chip_data.cal_1.cal_grp[0], sizeof(int)*_PGW_TDM_OVS_SIZE);
   2894     sal_memcpy(tdm->pgw_ovs_spacing[1], _tdm_pkg->_chip_data.cal_1.cal_grp[1], sizeof(int)*_PGW_TDM_OVS_SIZE);
   2895     sal_memcpy(tdm->pgw_tdm[2], _tdm_pkg->_chip_data.cal_2.cal_main, sizeof(int)*MAX_PGW_TDM_LENGTH);
   2896     sal_memcpy(tdm->pgw_ovs_tdm[2], _tdm_pkg->_chip_data.cal_2.cal_grp[0], sizeof(int)*_PGW_TDM_OVS_SIZE);
   2897     sal_memcpy(tdm->pgw_ovs_spacing[2], _tdm_pkg->_chip_data.cal_2.cal_grp[1], sizeof(int)*_PGW_TDM_OVS_SIZE);
   2898     sal_memcpy(tdm->pgw_tdm[3], _tdm_pkg->_chip_data.cal_3.cal_main, sizeof(int)*MAX_PGW_TDM_LENGTH);
   2899     sal_memcpy(tdm->pgw_ovs_tdm[3], _tdm_pkg->_chip_data.cal_3.cal_grp[0], sizeof(int)*_PGW_TDM_OVS_SIZE);
   2900     sal_memcpy(tdm->pgw_ovs_spacing[3], _tdm_pkg->_chip_data.cal_3.cal_grp[1], sizeof(int)*_PGW_TDM_OVS_SIZE);
   2901     sal_memcpy(tdm->mmu_tdm[0], _tdm_pkg->_chip_data.cal_4.cal_main, sizeof(int)*_MMU_TDM_LENGTH);
   2902     sal_memcpy(tdm->mmu_ovs_group_tdm[0][0], _tdm_pkg->_chip_data.cal_4.cal_grp[0], sizeof(int)*_MMU_OVS_GROUP_TDM_LENGTH);
   2903     sal_memcpy(tdm->mmu_ovs_group_tdm[0][1], _tdm_pkg->_chip_data.cal_4.cal_grp[1], sizeof(int)*_MMU_OVS_GROUP_TDM_LENGTH);
   2904     sal_memcpy(tdm->mmu_ovs_group_tdm[0][2], _tdm_pkg->_chip_data.cal_4.cal_grp[2], sizeof(int)*_MMU_OVS_GROUP_TDM_LENGTH);
   2905     sal_memcpy(tdm->mmu_ovs_group_tdm[0][3], _tdm_pkg->_chip_data.cal_4.cal_grp[3], sizeof(int)*_MMU_OVS_GROUP_TDM_LENGTH);
   2906     sal_memcpy(tdm->mmu_ovs_group_tdm[0][4], _tdm_pkg->_chip_data.cal_4.cal_grp[4], sizeof(int)*_MMU_OVS_GROUP_TDM_LENGTH);
   2907     sal_memcpy(tdm->mmu_ovs_group_tdm[0][5], _tdm_pkg->_chip_data.cal_4.cal_grp[5], sizeof(int)*_MMU_OVS_GROUP_TDM_LENGTH);
   2908     sal_memcpy(tdm->mmu_ovs_group_tdm[0][6], _tdm_pkg->_chip_data.cal_4.cal_grp[6], sizeof(int)*_MMU_OVS_GROUP_TDM_LENGTH);
   2909     sal_memcpy(tdm->mmu_ovs_group_tdm[0][7], _tdm_pkg->_chip_data.cal_4.cal_grp[7], sizeof(int)*_MMU_OVS_GROUP_TDM_LENGTH);
   2910     sal_memcpy(tdm->mmu_tdm[1], _tdm_pkg->_chip_data.cal_5.cal_main, sizeof(int)*_MMU_TDM_LENGTH);
   2911     sal_memcpy(tdm->mmu_ovs_group_tdm[1][0], _tdm_pkg->_chip_data.cal_5.cal_grp[0], sizeof(int)*_MMU_OVS_GROUP_TDM_LENGTH);
   2912     sal_memcpy(tdm->mmu_ovs_group_tdm[1][1], _tdm_pkg->_chip_data.cal_5.cal_grp[1], sizeof(int)*_MMU_OVS_GROUP_TDM_LENGTH);
   2913     sal_memcpy(tdm->mmu_ovs_group_tdm[1][2], _tdm_pkg->_chip_data.cal_5.cal_grp[2], sizeof(int)*_MMU_OVS_GROUP_TDM_LENGTH);
   2914     sal_memcpy(tdm->mmu_ovs_group_tdm[1][3], _tdm_pkg->_chip_data.cal_5.cal_grp[3], sizeof(int)*_MMU_OVS_GROUP_TDM_LENGTH);
   2915     sal_memcpy(tdm->mmu_ovs_group_tdm[1][4], _tdm_pkg->_chip_data.cal_5.cal_grp[4], sizeof(int)*_MMU_OVS_GROUP_TDM_LENGTH);
   2916     sal_memcpy(tdm->mmu_ovs_group_tdm[1][5], _tdm_pkg->_chip_data.cal_5.cal_grp[5], sizeof(int)*_MMU_OVS_GROUP_TDM_LENGTH);
   2917     sal_memcpy(tdm->mmu_ovs_group_tdm[1][6], _tdm_pkg->_chip_data.cal_5.cal_grp[6], sizeof(int)*_MMU_OVS_GROUP_TDM_LENGTH);
   2918     sal_memcpy(tdm->mmu_ovs_group_tdm[1][7], _tdm_pkg->_chip_data.cal_5.cal_grp[7], sizeof(int)*_MMU_OVS_GROUP_TDM_LENGTH);
   2919     sal_free(_chip_pkg.state);
   2920     sal_free(_chip_pkg.speed);
   2921     _tdm_pkg->_chip_exec[TDM_CHIP_EXEC__FREE](_tdm_pkg);
   2922     sal_free(_tdm_pkg);
   2923 
   2924     rv = tdm_td2p_set_iarb_tdm_table(tdm->tdm_bw,
   2925                                      tdm->pipe_ovs_state[0],
   2926                                      tdm->pipe_ovs_state[1],
   2927                                      tdm->manage_port_type == 1,
   2928                                      tdm->manage_port_type == 2,
   2929                                      tdm->manage_port_type == 3,
   2930                                      &tdm->iarb_tdm_wrap_ptr[0],
   2931                                      &tdm->iarb_tdm_wrap_ptr[1],
   2932                                      tdm->iarb_tdm[0],
   2933                                      tdm->iarb_tdm[1]);
   2934 
   2935     if (rv == 0) {
   2936         LOG_CLI((BSL_META_U(unit,
   2937                             "Unsupported config for TDM calendar generation\n")));
   2938         return SOC_E_FAIL;
   2939     }
   2940 #endif
   2941     return SOC_E_NONE;
   2942 }
   2943 
   2944 /*
   2945  * Function:
   2946  *      soc_td2p_use_pfc_optimized_settings
   2947  * Purpose:
   2948  *      Determines whether to use pfc optimized settings or not.
   2949  *      PFC Optimized Settings can only be used at max clock frequency,
   2950  *      which enables bandwidth of 960G. Its use is also dependent on
   2951  *      the oversub ratio, which must be < 1.5. Configurations that are
   2952  *      all linerate or all oversub do not exceed this threshold. However,
   2953  *      mixed configurations of linerate and oversubbed ports can exceed
   2954  *      1.5, so the oversub ratio is calculated at the bottom of the
   2955  *      function.
   2956  *  
   2957  * Parameters:
   2958  *      unit     - (IN) Unit number.
   2959  *  
   2960  * Returns:
   2961  *      TRUE or FALSE
   2962  */
   2963 int
   2964 soc_td2p_use_pfc_optimized_settings(int unit)
   2965 {
   2966    soc_info_t *si;
   2967    soc_pbmp_t pbmp;
   2968 
   2969    int x_denominator = 0, y_denominator = 0;
   2970 
   2971    int all_x_oversub = 0, any_x_oversub = 0;
   2972    int all_y_oversub = 0, any_y_oversub = 0;
   2973 
   2974    int x_linerate_bw = 0, x_oversub_bw = 0;
   2975    int y_linerate_bw = 0, y_oversub_bw = 0;
   2976    int x_core_bw = 0, y_core_bw = 0;
   2977    int max_quad_core_bandwidth, quad_linerate_bandwidth, quad_oversub_bandwidth;
   2978 
   2979    /* soc info has new values */
   2980    si = &SOC_INFO(unit);
   2981    /* if not max frequency, use non-optimized settings */
   2982    if (si->bandwidth < 960000) {
   2983       return FALSE;
   2984    }
   2985 
   2986    SOC_PBMP_CLEAR(pbmp);
   2987    SOC_PBMP_ASSIGN(pbmp, si->oversub_pbm);
   2988    SOC_PBMP_AND(pbmp, si->xpipe_pbm);
   2989 
   2990    /* find if any X ports are oversub */
   2991    any_x_oversub = SOC_PBMP_NOT_NULL(pbmp);
   2992 
   2993    /* find if all X ports are oversub */
   2994    SOC_PBMP_PORT_ADD(pbmp, 0); /* cpu port */
   2995    all_x_oversub = SOC_PBMP_EQ(pbmp, si->xpipe_pbm);
   2996 
   2997 
   2998 
   2999    SOC_PBMP_CLEAR(pbmp);
   3000    SOC_PBMP_ASSIGN(pbmp, si->oversub_pbm);
   3001    SOC_PBMP_AND(pbmp, si->ypipe_pbm);
   3002 
   3003    /* find if any Y ports are oversub */
   3004    any_y_oversub = SOC_PBMP_NOT_NULL(pbmp);
   3005 
   3006    /* find if all Y ports are oversub */
   3007    SOC_PBMP_PORT_ADD(pbmp, 105); /* loopback port */
   3008    all_y_oversub = SOC_PBMP_EQ(pbmp, si->ypipe_pbm);
   3009 
   3010    /* if all ports are oversub, use pfc optimized settings;
   3011       oversub ratio < 1.5 */
   3012    if (all_x_oversub == 1 && all_y_oversub == 1) {
   3013       return TRUE;
   3014    }
   3015 
   3016    /* if all the ports are linerate, use pfc optimized settings;
   3017       oversub ratio < 1.5 */
   3018    if (any_x_oversub == 0 && any_y_oversub == 0) {
   3019       return TRUE;
   3020    }
   3021 
   3022    /* in the mixed line rate/oversub case, we need to calculate
   3023       the oversub ratio:
   3024     
   3025       oversubbed port bandwidth / remaining bw after guaranteed linerate
   3026     
   3027       Example: if 2 100G line rate ports, subtract 200 from core bandwidth
   3028       of 480 (per pipe) because that's guaranteed, so you're left with 280.
   3029     
   3030       Now if you have 8 40G ports, that's 320G of bandwidth, so you MUST
   3031       use oversub for those since you only have 280G left.
   3032     
   3033       Thus your Oversub ratio is 320/280.  This value MUST be < 1.5 in order
   3034       to use PFC Optimized Settings.
   3035       */
   3036 
   3037    /* Calculate total linerate and oversub bandwidth for X Pipe */
   3038    _soc_trident2_quad_bandwidth_calculate(unit, 0, &max_quad_core_bandwidth, 
   3039                                       &quad_linerate_bandwidth,
   3040                                       &quad_oversub_bandwidth);
   3041    x_core_bw     += max_quad_core_bandwidth;
   3042    x_linerate_bw += quad_linerate_bandwidth;
   3043    x_oversub_bw  += quad_oversub_bandwidth;
   3044 
   3045    _soc_trident2_quad_bandwidth_calculate(unit, 1, &max_quad_core_bandwidth, 
   3046                                       &quad_linerate_bandwidth,
   3047                                       &quad_oversub_bandwidth);
   3048    x_core_bw     += max_quad_core_bandwidth;
   3049    x_linerate_bw += quad_linerate_bandwidth;
   3050    x_oversub_bw  += quad_oversub_bandwidth;
   3051 
   3052    /* Calculate total linerate and oversub bandwidth for Y Pipe */
   3053    _soc_trident2_quad_bandwidth_calculate(unit, 2, &max_quad_core_bandwidth, 
   3054                                       &quad_linerate_bandwidth, 
   3055                                       &quad_oversub_bandwidth);
   3056    y_core_bw     += max_quad_core_bandwidth;
   3057    y_linerate_bw += quad_linerate_bandwidth;
   3058    y_oversub_bw  += quad_oversub_bandwidth;
   3059 
   3060    _soc_trident2_quad_bandwidth_calculate(unit, 3, &max_quad_core_bandwidth,
   3061                                       &quad_linerate_bandwidth,
   3062                                       &quad_oversub_bandwidth);
   3063    y_core_bw     += max_quad_core_bandwidth;
   3064    y_linerate_bw += quad_linerate_bandwidth;
   3065    y_oversub_bw  += quad_oversub_bandwidth;
   3066 
   3067    /* Calculate Oversub Ratio per pipe. Oversub ratio must be < 1.5.
   3068       Since we can't use floats, the math
   3069       used here is to multiply the numerator by 2 and the denominator by 3
   3070       and compare the results.
   3071       numerator = oversub bandwidth
   3072       denominator = core bandwidth - linerate bandwidth
   3073       */
   3074    x_denominator = (x_core_bw - x_linerate_bw);
   3075    y_denominator = (y_core_bw - y_linerate_bw);
   3076 
   3077    /* If either pipe has an oversub ratio > 1.5, use normal settings. */
   3078    if  ((2 * x_oversub_bw) >= (3 * x_denominator) ||
   3079         (2 * y_oversub_bw) >= (3 * y_denominator)) {
   3080       return FALSE;
   3081    }
   3082 
   3083    /* Use PFC Optimized Settings */
   3084    return TRUE;
   3085 }
   3086 
   3087 
   3088 
   3089 /*
   3090  * Function:
   3091  *      soc_td2p_set_mmu_credit_limit
   3092  * Purpose:
   3093  *      Programs egress port credit size depending on port speed and whether
   3094  *      oversub is enabled.  Programs it for the worst case scenario.
   3095  *  
   3096  *      EP credit sizing is used to reduce the usable size of Edatabuf (EDB)
   3097  *      to limit accumulation.
   3098  *  
   3099  * Parameters:
   3100  *      unit     - (IN) Unit number.
   3101  *      port     - (IN) Logical Port
   3102  *  
   3103  * Returns:
   3104  *      SOC_E_XXX
   3105  */
   3106 int 
   3107 soc_td2p_set_mmu_credit_limit(int unit, soc_port_t port)
   3108 {
   3109    uint32 enable = 1;
   3110    uint32 credit_limit = 0;
   3111    uint32 entry[SOC_MAX_MEM_WORDS];
   3112    int phy_port, speed_max, hw_index;
   3113    soc_mem_t mem;
   3114    soc_info_t *si = &SOC_INFO(unit);
   3115 
   3116    phy_port = si->port_l2p_mapping[port];
   3117    if (phy_port == -1) {
   3118        return SOC_E_INTERNAL;
   3119    }
   3120 
   3121    SOC_IF_ERROR_RETURN(
   3122       READ_EGR_MMU_CREDIT_LIMITm(unit, MEM_BLOCK_ALL, phy_port, entry));
   3123 
   3124    /* Get the maximum speed of the port */
   3125    speed_max = si->port_speed_max[port];
   3126 
   3127    /* There are different credit limits depending on if
   3128       oversub is enabled, and the port speed. */
   3129    if (IS_OVERSUB_PORT(unit, port)) {
   3130       if (speed_max >= 100000) {
   3131          return SOC_E_PARAM;
   3132       } else if (speed_max >= 40000) {
   3133          credit_limit = _TD2P_MMU_EGR_MMU_CREDIT_LIMIT_OVERSUB(40G);
   3134       } else if (speed_max >= 20000) {
   3135          credit_limit = _TD2P_MMU_EGR_MMU_CREDIT_LIMIT_OVERSUB(20G);
   3136       } else if (speed_max >= 10000) {
   3137          credit_limit = _TD2P_MMU_EGR_MMU_CREDIT_LIMIT_OVERSUB(10G);
   3138       } else {
   3139          return SOC_E_NONE;
   3140       }
   3141    } else {
   3142       if (speed_max >= 100000) {
   3143          credit_limit = _TD2P_MMU_EGR_MMU_CREDIT_LIMIT_LINERATE(100G);
   3144       } else if (speed_max >= 40000) {
   3145          credit_limit = _TD2P_MMU_EGR_MMU_CREDIT_LIMIT_LINERATE(40G);
   3146       } else if (speed_max >= 20000) {
   3147          credit_limit = _TD2P_MMU_EGR_MMU_CREDIT_LIMIT_LINERATE(20G);
   3148       } else if (speed_max >= 10000) {
   3149          credit_limit = _TD2P_MMU_EGR_MMU_CREDIT_LIMIT_LINERATE(10G);
   3150       } else {
   3151          return SOC_E_NONE;
   3152       }
   3153    }
   3154 
   3155     mem = SOC_TD2_PMEM(unit, port, EGR_MMU_CREDIT_LIMIT_Xm, EGR_MMU_CREDIT_LIMIT_Ym);
   3156     if (mem == INVALIDm) {
   3157         return SOC_E_INTERNAL;
   3158     }
   3159 
   3160     hw_index = phy_port;
   3161     SOC_IF_ERROR_RETURN
   3162              (soc_mem_read(unit, mem, MEM_BLOCK_ALL, hw_index, &entry));
   3163 
   3164     soc_mem_field32_set(unit, mem, entry, ENABLEf, enable);
   3165     soc_mem_field32_set(unit, mem, entry, CELL_COUNTSf, credit_limit);
   3166 
   3167     SOC_IF_ERROR_RETURN
   3168              (soc_mem_write(unit, mem, MEM_BLOCK_ALL, hw_index, entry));
   3169 
   3170 
   3171    return SOC_E_NONE;
   3172 }
   3173 
   3174 /*
   3175  * Function:
   3176  *      soc_td2p_set_edb_pfc_watermark_threshold
   3177  * Purpose:
   3178  *      Programs EDB PFC Watermark Threshold depending on port speed and whether
   3179  *      oversub is enabled. Programs it for the worst case scenario.
   3180  *  
   3181  *      PFC Watermark in EDB stalls EP credit return to the MMU in order
   3182  *      to limit outstanding credits.
   3183  *  
   3184  * Parameters:
   3185  *      unit     - (IN) Unit number.
   3186  *      port     - (IN) Logical Port
   3187  *  
   3188  * Returns:
   3189  *      SOC_E_XXX
   3190  */
   3191 int
   3192 soc_td2p_set_edb_pfc_watermark_threshold(int unit, soc_port_t port)
   3193 {
   3194 
   3195    uint32 enable = 1;
   3196    uint32 pfc_watermark_thresh = 0;
   3197    uint32 entry[SOC_MAX_MEM_WORDS];
   3198    int phy_port, speed_max, ct_enable = 0;
   3199    soc_info_t *si = &SOC_INFO(unit);
   3200 
   3201    phy_port = si->port_l2p_mapping[port];
   3202    if (phy_port == -1) {
   3203        return SOC_E_INTERNAL;
   3204    }
   3205 
   3206    SOC_IF_ERROR_RETURN(
   3207       READ_EGR_PFC_CONTROLm(unit, MEM_BLOCK_ALL, phy_port, entry));
   3208 
   3209    /* Get the maximum speed of the port */
   3210    speed_max = si->port_speed_max[port];
   3211 
   3212    /* There are different watermarks depending on if
   3213       oversub is enabled, and the port speed. */
   3214       /* cut through is not supported */
   3215    if (IS_OVERSUB_PORT(unit, port)) {
   3216       if (speed_max >= 100000) {
   3217          return SOC_E_PARAM;
   3218       } else if (speed_max >= 40000) {
   3219          pfc_watermark_thresh = _TD2P_EGR_PFC_WATERMARK_THRESH_OVERSUB(40G);
   3220       } else if (speed_max >= 20000) {
   3221          pfc_watermark_thresh = _TD2P_EGR_PFC_WATERMARK_THRESH_OVERSUB(20G);
   3222       } else if (speed_max >= 10000) {
   3223          pfc_watermark_thresh = _TD2P_EGR_PFC_WATERMARK_THRESH_OVERSUB(10G);
   3224       } else {
   3225          return SOC_E_NONE;
   3226       }
   3227    } else {
   3228       if (speed_max >= 100000) {
   3229          pfc_watermark_thresh = _TD2P_EGR_PFC_WATERMARK_THRESH_LINERATE(100G);
   3230       } else if (speed_max >= 40000) {
   3231          pfc_watermark_thresh = _TD2P_EGR_PFC_WATERMARK_THRESH_LINERATE(40G);
   3232       } else if (speed_max >= 20000) {
   3233          pfc_watermark_thresh = _TD2P_EGR_PFC_WATERMARK_THRESH_LINERATE(20G);
   3234       } else if (speed_max >= 10000) {
   3235          pfc_watermark_thresh = _TD2P_EGR_PFC_WATERMARK_THRESH_LINERATE(10G);
   3236       } else {
   3237          return SOC_E_NONE;
   3238       }
   3239    }
   3240 
   3241    SOC_IF_ERROR_RETURN(
   3242       soc_td2p_is_cut_thru_enabled(unit, port, &ct_enable));
   3243    if (ct_enable) {
   3244       enable = 0;
   3245    }
   3246    /* modify ENABLE and CELL_COUNTS in the EGR_MMU_CREDIT_LIMIT */
   3247    soc_EGR_PFC_CONTROLm_field_set(unit, entry, ENABLEf, &enable);
   3248    soc_EGR_PFC_CONTROLm_field_set(unit, entry, WATERMARKf, &pfc_watermark_thresh);   
   3249 
   3250    SOC_IF_ERROR_RETURN(
   3251       WRITE_EGR_PFC_CONTROLm(unit, MEM_BLOCK_ALL, phy_port, entry));
   3252 
   3253    return SOC_E_NONE;
   3254 }
   3255 
   3256 /*
   3257  * Function:
   3258  *      soc_td2p_port_resource_tdm_set
   3259  * Purpose:
   3260  *      Reconfigure the ingress and egress schedulers for
   3261  *      the new port configuration.
   3262  *
   3263  *      This includes reconfiguration of:
   3264  *      - OBM Thresholds
   3265  *      - EDB Prebuffer
   3266  *      - Ingress Oversub Scheduler
   3267  *      - Egress Oversub Scheduler
   3268  *      - Line-Rate Scheduler
   3269  * Parameters:
   3270  *      unit                 - (IN) Unit number.
   3271  *      curr_port_info_size  - (IN) Size of current port information array
   3272  *      curr_port_info       - (IN) Per-port array with current flexing info
   3273  *      new_port_info_size   - (IN) Size of new port information array
   3274  *      new_port_info        - (IN) Per-port array with new flexing info
   3275  *      si_info              - (IN) Contains subset of fields from
   3276  *                             soc_info_t structure
   3277  *                             prior to the flexing operation
   3278  *      lossless             - (IN) MMU lossless information
   3279  * Returns:
   3280  *      SOC_E_XXX
   3281  * Note:
   3282  *      Assumptions
   3283  *      - soc info structure members have been updated to reflect the latest
   3284  *        flexing operation
   3285  *      - There is no overlapping between logical or physical ports in the 
   3286  *        arrays passed, that is, operations like 4x10->1x40->4x10 on the same
   3287  *        set of ports have been rejected at bcm layer itself, and do not reach
   3288  *        this function
   3289  *      - Pre-FlexPort array
   3290  *        Contains current information on ports to be modified after
   3291  *        the FlexPort operation.  This should include ports whose
   3292  *        mappings are either deleted or remapped.
   3293  *      - Post-FlexPort array
   3294  *        Contains information on new configuration for
   3295  *        ports that are active (present) after the FlexPort operation.
   3296  *        This should include ports whose mappings that are remapped or new.
   3297  */
   3298 int soc_td2p_port_resource_tdm_set(int unit, int curr_port_info_size,
   3299                                    soc_port_resource_t *curr_port_info,
   3300                                    int new_port_info_size,
   3301                                    soc_port_resource_t *new_port_info,
   3302                                    soc_td2p_info_t *si_info,
   3303                                    int lossless)
   3304 {
   3305     soc_info_t *si;
   3306     _soc_trident2_tdm_t *tdm;
   3307     int pipe;
   3308     int phy_port;
   3309     int count;
   3310     uint32 table_num = 0;
   3311     uint64 rval64, ctrl_rval64;
   3312     uint32 rval;
   3313     int idx, mmu_port, length, profile_x, profile_y, port;
   3314     int  index, pgw, pgw_master, pgw_slave, obm_inst, base, slot;
   3315     soc_mem_t mem;
   3316     uint32 entry[SOC_MAX_MEM_WORDS];
   3317     soc_reg_t reg;
   3318     soc_field_t fields[4];
   3319     uint32 values[4];
   3320     soc_pbmp_t pbmp;
   3321     /* Used to store per-port cut-through setting */
   3322     int cut_thru_en[SOC_MAX_NUM_PORTS];
   3323     soc_port_resource_t res;
   3324 
   3325     /* Egress scheduler calendar memories */
   3326     static const soc_mem_t mmu_tdm_mems_0[2] ={
   3327         ES_PIPE0_TDM_TABLE_0m, ES_PIPE1_TDM_TABLE_0m
   3328     };
   3329 
   3330     static const soc_mem_t mmu_tdm_mems_1[2] ={
   3331         ES_PIPE0_TDM_TABLE_1m, ES_PIPE1_TDM_TABLE_1m
   3332     };
   3333 
   3334     static const soc_mem_t mmu_tdm_regs[2] ={
   3335         ES_PIPE0_TDM_CONFIGr, ES_PIPE1_TDM_CONFIGr
   3336     };
   3337 
   3338     static const soc_mem_t iarb_tdm_mems[2] ={
   3339         IARB_MAIN_TDM_Xm, IARB_MAIN_TDM_Ym
   3340     };
   3341 
   3342     static soc_reg_t pgw_tdm_regs[] = {
   3343         PGW_LR_TDM_REG_0r, PGW_LR_TDM_REG_1r,
   3344         PGW_LR_TDM_REG_2r, PGW_LR_TDM_REG_3r,
   3345         PGW_LR_TDM_REG_4r, PGW_LR_TDM_REG_5r,
   3346         PGW_LR_TDM_REG_6r, PGW_LR_TDM_REG_7r,
   3347         PGW_LR_TDM_REG_8r,  PGW_LR_TDM_REG_9r,
   3348         PGW_LR_TDM_REG_10r, PGW_LR_TDM_REG_11r,
   3349         PGW_LR_TDM_REG_12r, PGW_LR_TDM_REG_13r,
   3350         PGW_LR_TDM_REG_14r, PGW_LR_TDM_REG_15r
   3351     };
   3352 
   3353     /* Used for programming back up calender */
   3354     static soc_reg_t pgw_tdm2_regs[] = {
   3355         PGW_LR_TDM2_REG_0r, PGW_LR_TDM2_REG_1r,
   3356         PGW_LR_TDM2_REG_2r, PGW_LR_TDM2_REG_3r,
   3357         PGW_LR_TDM2_REG_4r, PGW_LR_TDM2_REG_5r,
   3358         PGW_LR_TDM2_REG_6r, PGW_LR_TDM2_REG_7r,
   3359         PGW_LR_TDM2_REG_8r,  PGW_LR_TDM2_REG_9r,
   3360         PGW_LR_TDM2_REG_10r, PGW_LR_TDM2_REG_11r,
   3361         PGW_LR_TDM2_REG_12r, PGW_LR_TDM2_REG_13r,
   3362         PGW_LR_TDM2_REG_14r, PGW_LR_TDM2_REG_15r
   3363     };
   3364 
   3365     static const soc_field_t pgw_tdm_fields[] = {
   3366         TDM_ENTRY0_PORT_IDf, TDM_ENTRY1_PORT_IDf,
   3367         TDM_ENTRY2_PORT_IDf, TDM_ENTRY3_PORT_IDf,
   3368         TDM_ENTRY4_PORT_IDf, TDM_ENTRY5_PORT_IDf,
   3369         TDM_ENTRY6_PORT_IDf, TDM_ENTRY7_PORT_IDf,
   3370         TDM_ENTRY8_PORT_IDf, TDM_ENTRY9_PORT_IDf,
   3371         TDM_ENTRY10_PORT_IDf, TDM_ENTRY11_PORT_IDf,
   3372         TDM_ENTRY12_PORT_IDf, TDM_ENTRY13_PORT_IDf,
   3373         TDM_ENTRY14_PORT_IDf, TDM_ENTRY15_PORT_IDf,
   3374         TDM_ENTRY16_PORT_IDf, TDM_ENTRY17_PORT_IDf,
   3375         TDM_ENTRY18_PORT_IDf, TDM_ENTRY19_PORT_IDf,
   3376         TDM_ENTRY20_PORT_IDf, TDM_ENTRY21_PORT_IDf,
   3377         TDM_ENTRY22_PORT_IDf, TDM_ENTRY23_PORT_IDf,
   3378         TDM_ENTRY24_PORT_IDf, TDM_ENTRY25_PORT_IDf,
   3379         TDM_ENTRY26_PORT_IDf, TDM_ENTRY27_PORT_IDf,
   3380         TDM_ENTRY28_PORT_IDf, TDM_ENTRY29_PORT_IDf,
   3381         TDM_ENTRY30_PORT_IDf, TDM_ENTRY31_PORT_IDf,
   3382         TDM_ENTRY32_PORT_IDf, TDM_ENTRY33_PORT_IDf,
   3383         TDM_ENTRY34_PORT_IDf, TDM_ENTRY35_PORT_IDf,
   3384         TDM_ENTRY36_PORT_IDf, TDM_ENTRY37_PORT_IDf,
   3385         TDM_ENTRY38_PORT_IDf, TDM_ENTRY39_PORT_IDf,
   3386         TDM_ENTRY40_PORT_IDf, TDM_ENTRY41_PORT_IDf,
   3387         TDM_ENTRY42_PORT_IDf, TDM_ENTRY43_PORT_IDf,
   3388         TDM_ENTRY44_PORT_IDf, TDM_ENTRY45_PORT_IDf,
   3389         TDM_ENTRY46_PORT_IDf, TDM_ENTRY47_PORT_IDf,
   3390         TDM_ENTRY48_PORT_IDf, TDM_ENTRY49_PORT_IDf,
   3391         TDM_ENTRY50_PORT_IDf, TDM_ENTRY51_PORT_IDf,
   3392         TDM_ENTRY52_PORT_IDf, TDM_ENTRY53_PORT_IDf,
   3393         TDM_ENTRY54_PORT_IDf, TDM_ENTRY55_PORT_IDf,
   3394         TDM_ENTRY56_PORT_IDf, TDM_ENTRY57_PORT_IDf,
   3395         TDM_ENTRY58_PORT_IDf, TDM_ENTRY59_PORT_IDf,
   3396         TDM_ENTRY60_PORT_IDf, TDM_ENTRY61_PORT_IDf,
   3397         TDM_ENTRY62_PORT_IDf, TDM_ENTRY63_PORT_IDf
   3398     };
   3399 
   3400     if ((!SOC_IS_TRIDENT2PLUS(unit) && !SOC_IS_TITAN2PLUS(unit))) {
   3401         /* Do nothing */
   3402         return SOC_E_NONE;
   3403     }
   3404 
   3405     /* Reconfigure EDB prebuffer */
   3406 
   3407     /* Note both pipelines' registers are written by hardware internally */
   3408     SOC_IF_ERROR_RETURN(READ_EGR_FLEXPORT_EXTRA_HOLDINGr(unit, &rval));
   3409     soc_reg_field_set(unit, EGR_FLEXPORT_EXTRA_HOLDINGr, &rval,
   3410                       CLPORT_CELL_COUNTSf, 0x1);
   3411     soc_reg_field_set(unit, EGR_FLEXPORT_EXTRA_HOLDINGr, &rval,
   3412                       XLPORT_CELL_COUNTSf, 0x3);
   3413     soc_reg_field_set(unit, EGR_FLEXPORT_EXTRA_HOLDINGr, &rval,
   3414                       ENABLEf, 0x1);
   3415     SOC_IF_ERROR_RETURN(WRITE_EGR_FLEXPORT_EXTRA_HOLDINGr(unit, rval));
   3416 
   3417     /* Reconfigure EDB prebuffer back up calendar, for line rate
   3418      * TDM calendar. Oversub related portion will be added later
   3419      */
   3420     SOC_IF_ERROR_RETURN(soc_td2p_port_resource_tdm_calculate(unit,
   3421                         curr_port_info_size, curr_port_info,
   3422                         new_port_info_size, new_port_info, si_info));
   3423 
   3424     /* Reconfigure oversub scheduler.
   3425      * Function internally determines if oversub is enabled/disabled
   3426      */
   3427     SOC_IF_ERROR_RETURN(soc_td2p_ovr_sub_tdm_update(unit, 
   3428                         curr_port_info_size, curr_port_info,
   3429                         new_port_info_size, new_port_info));
   3430 
   3431     tdm = soc_td2_td2p_tdm_sched_info_get(unit, 0);
   3432     if (tdm == NULL) {
   3433         return SOC_E_INIT;
   3434     }
   3435 
   3436     /* soc info has new values */
   3437     si = &SOC_INFO(unit);
   3438 
   3439     
   3440     /* Configure ingress scheduler back up calendar */
   3441     for (pgw = 0; pgw < _TD2_PGWS_PER_DEV; pgw += _TD2_PGWS_PER_QUAD) {
   3442         pgw_master = pgw;
   3443         pgw_slave  = pgw + 1;
   3444         if ((pgw == 2) || (pgw == 6)) {
   3445             pgw_master = pgw + 1;
   3446             pgw_slave  = pgw;
   3447         }
   3448 
   3449         /* coverity[negative_returns : FALSE] */
   3450         if (!si->block_valid[PGW_CL_BLOCK(unit, pgw_master)] &&
   3451             !si->block_valid[PGW_CL_BLOCK(unit, pgw_slave)]) {
   3452             /* Both master and slave are not in use */
   3453             continue;
   3454         }
   3455 
   3456         obm_inst = pgw_master | SOC_REG_ADDR_INSTANCE_MASK;
   3457 
   3458         SOC_IF_ERROR_RETURN(soc_reg_get(unit, PGW_TDM_CONTROLr, obm_inst, 0,
   3459                                         &ctrl_rval64));
   3460 
   3461         SOC_IF_ERROR_RETURN(soc_td2p_curr_ingr_tdm_table_get(unit,
   3462                                                             obm_inst,
   3463                                                             &table_num)); 
   3464         /* Configure PGW line rate TDM backup calendar */
   3465         count = 0;
   3466         for (base = 0; base < GET_PGW_TDM_LENGTH(unit);
   3467             base += _PGW_TDM_SLOTS_PER_REG) {
   3468 
   3469             /* Point to back up calendar */
   3470             if (table_num == 0) {
   3471                 reg = pgw_tdm2_regs[base / _PGW_TDM_SLOTS_PER_REG];
   3472             } else {
   3473                 reg = pgw_tdm_regs[base / _PGW_TDM_SLOTS_PER_REG];
   3474             }
   3475 
   3476             COMPILER_64_ZERO(rval64);
   3477             for (index = 0; index < _PGW_TDM_SLOTS_PER_REG; index++) {
   3478                 slot = base + index;
   3479                 phy_port = tdm->pgw_tdm[pgw_master / 2][slot];
   3480                 if (phy_port == NUM_EXT_PORTS) {
   3481                     break;
   3482                 }
   3483                 soc_reg64_field32_set(unit, reg, &rval64, pgw_tdm_fields[slot],
   3484                                       phy_port);
   3485                 count++;
   3486             }
   3487 
   3488             if (index != 0) {
   3489                 SOC_IF_ERROR_RETURN
   3490                     (soc_reg_set(unit, reg, obm_inst, 0, rval64));
   3491             }
   3492             if (index != _PGW_TDM_SLOTS_PER_REG) {
   3493                 /* Due to hardware limitation, line-rate TDM wrap pointer
   3494                  * must be larger than 0
   3495                  */
   3496                 if (count == 1) {
   3497 
   3498                     count = 2;
   3499 
   3500                     soc_reg64_field32_set(unit, reg, &rval64,
   3501                                           pgw_tdm_fields[slot],
   3502                                           PGW_LR_UNUSED_SLOT);
   3503 
   3504                     SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, obm_inst, 0,
   3505                                                     rval64));
   3506                 }
   3507                 break;
   3508             }
   3509         }
   3510 
   3511         LOG_VERBOSE(BSL_LS_SOC_PORT,
   3512                        (BSL_META_U(unit,
   3513                        "pgw_master %d, count %d\n"), pgw_master, count));
   3514 
   3515         /*
   3516          * When switching from current calendar to new calendar, there is an
   3517          * intermediate state where hardware waits until end of current calendar
   3518          * to switch to the new celandar. This happens when a moving table
   3519          * pointer (ptr) inside the hardware reaches the value LR_TDMx_WRAP_PTR.
   3520          * In the case where was no port on this pgw before flexing,
   3521          * the hardware pointer will not increment to reach LR_TDMx_WRAP_PTR
   3522          * value. In this case we set the value of wrap pointer to 0, so that,
   3523          * inside hardware, calendar switching happens.
   3524          */
   3525         if (table_num == 0) {
   3526             /* Program new calendar bits */
   3527             soc_reg64_field32_set(unit, PGW_TDM_CONTROLr, &ctrl_rval64,
   3528                                   LR_TDM2_WRAP_PTRf, count ? (count - 1) : 0);
   3529 
   3530             soc_reg64_field32_set(unit, PGW_TDM_CONTROLr, &ctrl_rval64,
   3531                                   LR_TDM2_ENABLEf, count ? 1 : 0);
   3532         } else {
   3533             /* Program new calendar bits */
   3534             soc_reg64_field32_set(unit, PGW_TDM_CONTROLr, &ctrl_rval64,
   3535                                   LR_TDM_WRAP_PTRf, count ? (count - 1) : 0);
   3536 
   3537             soc_reg64_field32_set(unit, PGW_TDM_CONTROLr, &ctrl_rval64,
   3538                                   LR_TDM_ENABLEf, count ? 1 : 0);
   3539         }
   3540 
   3541         SOC_IF_ERROR_RETURN
   3542             (soc_reg_set(unit, PGW_TDM_CONTROLr, obm_inst, 0, ctrl_rval64));
   3543     }
   3544 
   3545     /* Configure ingress scheduler back up calendar */
   3546     for (pipe = 0; pipe < _TD2_PIPES_PER_DEV; pipe++) {
   3547 
   3548         SOC_IF_ERROR_RETURN(soc_td2p_curr_egr_tdm_table_get(unit, pipe,
   3549                                                             &table_num)); 
   3550 
   3551         reg = mmu_tdm_regs[pipe];
   3552 
   3553         /* Program the _other_ (back up) TDM table (not the one in use)*/
   3554         if (table_num == 0) {
   3555             mem = mmu_tdm_mems_1[pipe];
   3556         } else {
   3557             mem = mmu_tdm_mems_0[pipe];
   3558         }
   3559 
   3560         length = _MMU_TDM_LENGTH;
   3561         for (slot = _MMU_TDM_LENGTH - 1; slot >= 0; slot--) {
   3562             if (tdm->mmu_tdm[pipe][slot] != NUM_EXT_PORTS) {
   3563                 length = slot + 1;
   3564                 break;
   3565             }
   3566         }
   3567         
   3568         SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
   3569         sal_memset(entry, 0, soc_mem_entry_words(unit, mem) * sizeof(uint32));
   3570         for (slot = 0; slot < length; slot += 2) {
   3571             phy_port = tdm->mmu_tdm[pipe][slot];
   3572             if (phy_port == GET_OVS_TOKEN(unit)) {
   3573                 mmu_port = 57; /* oppurtunist port */
   3574             } else if (phy_port == GET_IDL_TOKEN(unit)) {
   3575                 mmu_port = 58; /* scheduler will not pick anything */
   3576             } else if (phy_port >= NUM_EXT_PORTS) {
   3577                 mmu_port = 0x3f;
   3578             } else {
   3579                 /* The BCM layer has updated the p2m mapping before calling
   3580                  * tdm_set, so we use it. Other way may be to find mmu_port
   3581                  * from the subset of new ports in new_port_info.
   3582                  * For other ports, updated p2m mapping may be used 
   3583                  */
   3584                 mmu_port = si->port_p2m_mapping[phy_port];
   3585             }
   3586 
   3587             soc_mem_field32_set(unit, mem, entry, PORT_NUM_EVENf,
   3588                                 mmu_port & 0x3F);
   3589 
   3590             phy_port = tdm->mmu_tdm[pipe][slot + 1];
   3591             if (phy_port == GET_OVS_TOKEN(unit)) {
   3592                 mmu_port = 57; /* oppurtunist port */
   3593             } else if (phy_port == GET_IDL_TOKEN(unit)) {
   3594                 mmu_port = 58; /* scheduler will not pick anything */
   3595             } else if (phy_port >= NUM_EXT_PORTS) {
   3596                 mmu_port = 0x3f;
   3597             } else {
   3598                 /* See comment above for EVENf slots */
   3599                 mmu_port = si->port_p2m_mapping[phy_port];
   3600             }
   3601             soc_mem_field32_set(unit, mem, entry, PORT_NUM_ODDf,
   3602                                 mmu_port & 0x3f);
   3603             SOC_IF_ERROR_RETURN
   3604                 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, slot / 2, entry));
   3605         }
   3606 
   3607         /* We are programming the back up table, so we set it's
   3608          * 'end' field (that is, not the current table's end field)
   3609          */
   3610         if (table_num == 0) {
   3611             soc_reg_field_set(unit, reg, &rval, CAL1_ENDf, slot / 2);
   3612 
   3613             if (length & 1) {
   3614                 soc_reg_field_set(unit, reg, &rval, CAL1_END_SINGLEf, 1);
   3615             }
   3616         } else {
   3617             soc_reg_field_set(unit, reg, &rval, CAL0_ENDf, slot / 2);
   3618 
   3619             if (length & 1) {
   3620                 soc_reg_field_set(unit, reg, &rval, CAL0_END_SINGLEf, 1);
   3621             }
   3622         }
   3623 
   3624         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval));
   3625     }
   3626 
   3627     /* Configure IARB TDM */
   3628     for (pipe = 0; pipe < _TD2_PIPES_PER_DEV; pipe++) {
   3629         mem = iarb_tdm_mems[pipe];
   3630         sal_memset(entry, 0, soc_mem_entry_words(unit, mem) * sizeof(uint32));
   3631         for (slot = 0; slot < _IARB_TDM_LENGTH; slot++) {
   3632             if (slot > tdm->iarb_tdm_wrap_ptr[pipe]) {
   3633                 break;
   3634             }
   3635             soc_mem_field32_set(unit, mem, entry, TDM_SLOTf,
   3636                                 tdm->iarb_tdm[pipe][slot]);
   3637             SOC_IF_ERROR_RETURN
   3638                 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, slot, entry));
   3639         }
   3640     }
   3641 
   3642     /* Both pipe are expected to have same IARB TDM table length */
   3643     fields[0] = TDM_WRAP_PTRf;
   3644     values[0] = tdm->iarb_tdm_wrap_ptr[0];
   3645     fields[1] = DISABLEf;
   3646     values[1] = 0;
   3647     fields[2] = AUX_CMICM_SLOT_ENf;
   3648     values[2] = 1;
   3649     fields[3] = AUX_EP_LB_SLOT_ENf;
   3650     values[3] = 1;
   3651     SOC_IF_ERROR_RETURN
   3652         (soc_reg_fields32_modify(unit, IARB_TDM_CONTROLr, REG_PORT_ANY, 4,
   3653                                  fields, values));
   3654 
   3655     /* Find ports with speeds >= 100G in any or both of the pipes */ 
   3656     /* In the new flex config, check if we are adding >= 100G speeds in a pipe,
   3657      * or removing >=100G speeds from a pipe. If we are removing, profile_ will 
   3658      * set to '1'. If we are adding, profile_ will be set to '0' in the code
   3659      * below. If there's no change in the pipe as far as speeds >= 100G is
   3660      * concerned, we will set the same value of profile_ again.
   3661      */
   3662 
   3663     profile_x = 1; /* For enforcing a minimum of 11 cycle same-port spacing */
   3664     profile_y = 1; /* For enforcing a minimum of 11 cycle same-port spacing */
   3665 
   3666     for (idx = 0; idx < new_port_info_size; idx++) {
   3667         if (new_port_info[idx].speed >= 100000) {
   3668             /* Set profile_* value for enforcing a minimum of 4 cycle
   3669              * same-port spacing for speeds >= 100G
   3670              */
   3671             if (new_port_info[idx].pipe == 0) {
   3672                 /* Port belongs to x-pipe */
   3673                 profile_x = 0;
   3674             } else {
   3675                 /* Port belongs to y-pipe */
   3676                 profile_y = 0;
   3677             }
   3678         }
   3679     }
   3680 
   3681     /* If there was any port >= 100G configured during a past flexing within a 
   3682      * pipe, then we need to retain the same-port spacing value for 100G (0)
   3683      * Search in the bigger (whole) set of ports
   3684      */
   3685     for (pipe = 0; pipe < _TD2_PIPES_PER_DEV; pipe++) {
   3686         pbmp = pipe ? si->ypipe_pbm : si->xpipe_pbm;
   3687         SOC_PBMP_ITER(pbmp, port) {
   3688             
   3689             if (si->port_l2p_mapping[port] == -1) {
   3690                 continue;
   3691             }
   3692 
   3693             if (si->port_speed_max[port] >= 100000) {
   3694                 if (pipe == 0) {
   3695                     profile_x = 0;
   3696                 } else {
   3697                     profile_y = 0;
   3698                 }
   3699             }
   3700         }
   3701     }
   3702 
   3703     /* X-pipe */
   3704     SOC_IF_ERROR_RETURN(soc_reg32_get(unit, ES_PIPE0_MIN_SPACINGr,
   3705                         REG_PORT_ANY, 0, &rval));
   3706     soc_reg_field_set(unit, ES_PIPE0_MIN_SPACINGr, &rval, PROFILEf, profile_x);
   3707     SOC_IF_ERROR_RETURN(soc_reg32_set(unit, ES_PIPE0_MIN_SPACINGr,
   3708                                       REG_PORT_ANY, 0, rval));
   3709 
   3710     /* Y-pipe */
   3711     SOC_IF_ERROR_RETURN(soc_reg32_get(unit, ES_PIPE1_MIN_SPACINGr,
   3712                         REG_PORT_ANY, 0, &rval));
   3713     soc_reg_field_set(unit, ES_PIPE1_MIN_SPACINGr, &rval, PROFILEf, profile_y);
   3714     SOC_IF_ERROR_RETURN(soc_reg32_set(unit, ES_PIPE1_MIN_SPACINGr,
   3715                                       REG_PORT_ANY, 0, rval));
   3716 
   3717     /* Configure ingress scheduler back up calendar */
   3718 
   3719     /* Safety check to make sure the array bounds are not crossed. If the input
   3720      * array size exceeds, then we can increase size of cut_thru_en[]
   3721      */
   3722     if (new_port_info_size > SOC_MAX_NUM_PORTS) {
   3723         LOG_ERROR(BSL_LS_SOC_PORT,
   3724                   (BSL_META_U(unit,
   3725                    "Input array size %d (new_port_info_size) exceeds"
   3726                    " SOC_MAX_NUM_PORTS\n"),
   3727                    new_port_info_size));
   3728         return SOC_E_INTERNAL;
   3729     }
   3730 
   3731     /* Initialize cut-through settings array */
   3732     sal_memset(cut_thru_en, 0, sizeof(cut_thru_en));
   3733 
   3734     sal_memset(&res, 0, sizeof(soc_port_resource_t));
   3735     PBMP_PORT_ITER(unit, port) {
   3736 
   3737         if (IS_LB_PORT(unit, port) || IS_CPU_PORT (unit, port)) {
   3738             continue;
   3739         }
   3740 
   3741         /* Skip inactive ports, and ports with no mapping */
   3742         if ((SOC_PBMP_MEMBER(si->all.disabled_bitmap, port)) ||
   3743             (si->port_l2p_mapping[port] == -1)) {
   3744             continue;
   3745         }
   3746 
   3747         /* Cut-through setting should be manipulated for line rate ports only.
   3748          * Also, only speeds <= 21000 need to be considered
   3749          */
   3750         if ((SOC_PBMP_MEMBER(si->oversub_pbm, port)) ||
   3751             (si->port_speed_max[port] > 21000)) {
   3752             continue;
   3753         }
   3754 
   3755         /* Manipulate cut-through settings for the ports */
   3756         SOC_IF_ERROR_RETURN(soc_td2p_is_cut_thru_enabled(unit,
   3757                             port, &cut_thru_en[port]));
   3758 
   3759         /* If cut-through is enabled, then we disable it here and re-enable
   3760          * it again later in this function. If cut-through is disabled,
   3761          * we don't program anything related to cut-through, here
   3762          */
   3763         if (cut_thru_en[port] == TRUE) {
   3764             res.logical_port = port;
   3765             res.physical_port = si->port_l2p_mapping[port];
   3766             res.speed = si->port_speed_max[port];
   3767             res.oversub = 0;
   3768             /* Disable cut-through for this port */
   3769             SOC_IF_ERROR_RETURN(soc_td2p_cut_thru_enable_disable(unit, &res,
   3770                                                                  0));
   3771         }
   3772 
   3773     }
   3774 
   3775     /* Configure ingress scheduler back up calendar */
   3776     /* Note we are providing 80Usec delay only once, not twice
   3777      */
   3778     sal_usleep(80);
   3779     idx = 0;
   3780 
   3781     for (pipe = 0; pipe < _TD2_PIPES_PER_DEV; pipe++) {
   3782         int masters[_TD2_PGWS_PER_DEV / 2] = {0, 3, 4, 7}; /* pgw masters */
   3783         int masters_per_pipe = (sizeof(masters) / sizeof(int)) /
   3784                                 _TD2_PIPES_PER_DEV;
   3785          int pgw_num;
   3786 
   3787         /* Switch over egress calendar */
   3788         SOC_IF_ERROR_RETURN(soc_td2p_curr_egr_tdm_table_get(unit, pipe,
   3789                                                             &table_num));
   3790         table_num ^= 0x1;
   3791         
   3792         SOC_IF_ERROR_RETURN(soc_td2p_curr_egr_tdm_table_set(unit, pipe,
   3793                                                             table_num));
   3794 
   3795         for (pgw_num = 0; pgw_num  < masters_per_pipe; pgw_num++, idx++) { 
   3796             obm_inst = masters[idx] | SOC_REG_ADDR_INSTANCE_MASK;
   3797 
   3798             /* Switch over ingress calendar */
   3799 
   3800             SOC_IF_ERROR_RETURN(soc_td2p_curr_ingr_tdm_table_get(unit,
   3801                                 obm_inst, &table_num));
   3802             table_num ^= 0x1;
   3803 
   3804             SOC_IF_ERROR_RETURN(soc_td2p_curr_ingr_tdm_table_set(unit,
   3805                                 obm_inst, table_num));
   3806             }
   3807     }
   3808 
   3809     /* Configure ingress scheduler back up calendar */
   3810     sal_memset(&res, 0, sizeof(soc_port_resource_t));
   3811     PBMP_PORT_ITER(unit, port) {
   3812 
   3813         if (IS_LB_PORT(unit, port) || IS_CPU_PORT(unit, port)) {
   3814             continue;
   3815         }
   3816 
   3817         /* Skip inactive ports, and ports with no mapping */
   3818         if ((SOC_PBMP_MEMBER(si->all.disabled_bitmap, port)) ||
   3819             (si->port_l2p_mapping[port] == -1)) {
   3820             continue;
   3821         }
   3822 
   3823         /* Cut-through setting should be manipulated for line rate ports only.
   3824          * Also, only speeds <= 21000 need to be considered
   3825          */
   3826         if ((SOC_PBMP_MEMBER(si->oversub_pbm, port)) ||
   3827             (si->port_speed_max[port] > 21000)) {
   3828             continue;
   3829         }
   3830 
   3831         /* Cut-through was enabled before entering this function, so we
   3832          * restore it. If cut-through was disabled before entering this
   3833          * function, we don't perform any programming related to it.
   3834          */
   3835         if (cut_thru_en[port] == TRUE) {
   3836             res.logical_port = port;
   3837             res.physical_port = si->port_l2p_mapping[port];
   3838             res.speed = si->port_speed_max[port];
   3839             res.oversub = 0;
   3840             /* Re-enable cut-through for this port */
   3841             SOC_IF_ERROR_RETURN(soc_td2p_cut_thru_enable_disable(unit, &res,
   3842                                                                  1));
   3843         }
   3844 
   3845     }
   3846 
   3847     /* Reconfigure OBM thresholds */
   3848     SOC_IF_ERROR_RETURN(soc_td2p_obm_threshold_set(unit,
   3849                         curr_port_info_size, curr_port_info,
   3850                         new_port_info_size, new_port_info,
   3851                         lossless));
   3852 
   3853     /* Reconfigure EDB prebuffer */
   3854 
   3855     sal_usleep(1);
   3856 
   3857     /* Note both pipelines' registers are written by hardware internally */
   3858     SOC_IF_ERROR_RETURN(READ_EGR_FLEXPORT_EXTRA_HOLDINGr(unit, &rval));
   3859     soc_reg_field_set(unit, EGR_FLEXPORT_EXTRA_HOLDINGr, &rval,
   3860                       CLPORT_CELL_COUNTSf, 0x1);
   3861     soc_reg_field_set(unit, EGR_FLEXPORT_EXTRA_HOLDINGr, &rval,
   3862                       XLPORT_CELL_COUNTSf, 0x3);
   3863     soc_reg_field_set(unit, EGR_FLEXPORT_EXTRA_HOLDINGr, &rval,
   3864                       ENABLEf, 0x0);
   3865     SOC_IF_ERROR_RETURN(WRITE_EGR_FLEXPORT_EXTRA_HOLDINGr(unit, rval));
   3866 
   3867 
   3868     return SOC_E_NONE;
   3869 }
   3870 
   3871 /*
   3872  * Function:
   3873  *      soc_td2p_port_resource_pgw_set
   3874  * Purpose:
   3875  *      Reconfigure PGW registers in flex port sequence
   3876  *      In this function following registers will be initialized.
   3877  *      This function will do two things,
   3878  *      1. clear all registers for old ports which exists in pre-Flex status
   3879  *      2. initialize all registers for new ports which exists in post-Flex
   3880  *         status
   3881  *
   3882  * Parameters:
   3883  *      unit         - (IN) Unit number.
   3884  *      pre_num_res  - (IN) Number of resource data which exist in pre-Flex
   3885  *                          status
   3886  *      post_num_res - (IN) Number of resource data which exist in post-Flex
   3887  *                          status
   3888  *      pre_res      - (IN) Resource data structure pointer in pre-Flex status
   3889  *      post_res     - (IN) Resource data structure pointer in post-Flex status
   3890  *      lossless     - (IN) MMU lossless information
   3891  *
   3892  * Returns:
   3893  *      SOC_E_XXX
   3894  * Note: 
   3895  *      - Assumes FlexPort cases are valid.
   3896  *      - Pre-FlexPort array
   3897  *        Contains current information on ports to be modified after
   3898  *        the FlexPort operation.  This should include ports whose
   3899  *        mappings are either deleted or remapped.
   3900  *      - Post-FlexPort array
   3901  *        Contains information on new configuration for
   3902  *        ports that are active (present) after the FlexPort operation.
   3903  *        This should include ports whose mappings that are remapped or new.
   3904  */
   3905 int
   3906 soc_td2p_port_resource_pgw_set(int unit,
   3907                       int pre_num_res,  soc_port_resource_t *pre_res,
   3908                       int post_num_res, soc_port_resource_t *post_res,
   3909                       int lossless)
   3910 {
   3911     soc_esw_portctrl_pgw_t data;
   3912     int i;
   3913 
   3914     SOC_IF_ERROR_RETURN(
   3915         _soc_td2p_resource_data_check(unit, pre_num_res, pre_res));
   3916     SOC_IF_ERROR_RETURN(
   3917         _soc_td2p_resource_data_check(unit, post_num_res, post_res));
   3918 
   3919     /*
   3920      * NOTE: Mode is set in a per-XLPORT register, so
   3921      *       we only need to update the mode in a port.
   3922      */
   3923     for (i = 0; i < post_num_res; i++) {
   3924         data.mode       = post_res[i].mode;
   3925         data.lanes      = post_res[i].num_lanes;
   3926         data.port_index = post_res[i].lane_info[0]->port_index;
   3927         data.flags      = 0x0;
   3928 
   3929         SOC_IF_ERROR_RETURN(soc_esw_portctrl_pgw_reconfigure(unit,
   3930                             post_res[i].logical_port,
   3931                             post_res[i].physical_port, &data));
   3932     }
   3933 
   3934 
   3935     SOC_IF_ERROR_RETURN
   3936         (soc_td2p_pgw_obm_set(unit,
   3937                                         pre_num_res, pre_res,
   3938                                         post_num_res, post_res));
   3939 
   3940     SOC_IF_ERROR_RETURN(soc_td2p_pgw_port_hw_default_set(unit,
   3941                                                          pre_num_res, pre_res,
   3942                                                          lossless));
   3943     SOC_IF_ERROR_RETURN(soc_td2p_pgw_port_sw_default_set(unit,
   3944                                                          post_num_res, post_res,
   3945                                                          lossless));
   3946     return SOC_E_NONE;
   3947 }
   3948 
   3949 /*
   3950  * Function:
   3951  *      soc_td2p_port_resource_ip_set
   3952  * Purpose:
   3953  *      Reconfigure IP.
   3954  * Parameters:
   3955  *      unit     - (IN) Unit number.
   3956  *      curr_port_info_size - (IN) Size of current port information array
   3957  *      curr_port_info - (IN) Per-port array with current flexing info
   3958  *      new_port_info_size - (IN) Size of new port information array
   3959  *      new_port_info - (IN) Per-port array with new flexing info
   3960  *      si_info - (IN) Contains subset of fields from soc_info_t structure
   3961  *                     prior to the flexing operation
   3962  * Returns:
   3963  *      SOC_E_XXX
   3964  * Note:
   3965  *      Assumptions
   3966  *      - soc info structure members have been updated to reflect the latest
   3967  *        flexing operation
   3968  *      - There is no overlapping between logical or physical ports in the 
   3969  *        arrays passed, example, operations like 4x10->1x40->4x10 on the same
   3970  *        set of ports have been rejected at bcm layer itself, and do not reach
   3971  *        this function
   3972  *      - Pre-FlexPort array
   3973  *        Contains current information on ports to be modified after
   3974  *        the FlexPort operation.  This should include ports whose
   3975  *        mappings are either deleted or remapped.
   3976  *      - Post-FlexPort array
   3977  *        Contains information on new configuration for
   3978  *        ports that are active (present) after the FlexPort operation.
   3979  *        This should include ports whose mappings that are remapped or new.
   3980  */
   3981 int soc_td2p_port_resource_ip_set(int unit, int curr_port_info_size,
   3982                                   soc_port_resource_t *curr_port_info,
   3983                                   int new_port_info_size,
   3984                                   soc_port_resource_t *new_port_info,
   3985                                   soc_td2p_info_t *si_info)
   3986 {
   3987     soc_info_t *si;
   3988     soc_mem_t mem;
   3989     ing_physical_to_logical_port_number_mapping_table_entry_t entry;
   3990     int port, phy_port;
   3991     int num_phy_port;
   3992 
   3993     si = &SOC_INFO(unit);
   3994 
   3995     /* Ingress physical to logical port mapping */
   3996     mem = ING_PHYSICAL_TO_LOGICAL_PORT_NUMBER_MAPPING_TABLEm;
   3997     num_phy_port = soc_mem_index_count(unit, mem);
   3998 
   3999     for (phy_port = 0; phy_port < num_phy_port; phy_port++) {
   4000         sal_memset(&entry, 0, sizeof(entry));
   4001 
   4002         /* The p2l mapping has been updated before this function is called */
   4003         port = si->port_p2l_mapping[phy_port];
   4004 
   4005         soc_mem_field32_set(unit, mem, &entry, LOGICAL_PORT_NUMBERf,
   4006                             port == -1 ? 0x7F : port);
   4007         SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, phy_port,
   4008                                           &entry));
   4009     }
   4010 
   4011     return SOC_E_NONE;
   4012 }
   4013 
   4014 /*
   4015  * Function:
   4016  *      soc_td2p_port_resource_ep_set
   4017  * Purpose:
   4018  *      Reconfigure EP.
   4019  * Parameters:
   4020  *      unit     - (IN) Unit number.
   4021  *      curr_port_info_size - (IN) Size of current port information array
   4022  *      curr_port_info - (IN) Per-port array with current flexing info
   4023  *      new_port_info_size - (IN) Size of new port information array
   4024  *      new_port_info - (IN) Per-port array with new flexing info
   4025  *      si_info - (IN) Contains subset of fields from soc_info_t structure
   4026  *                     prior to the flexing operation
   4027  * Returns:
   4028  *      SOC_E_XXX
   4029  * Note:
   4030  *      Assumptions
   4031  *      - soc info structure members have been updated to reflect the latest
   4032  *        flexing operation
   4033  *      - There is no overlapping between logical or physical ports in the 
   4034  *        arrays passed, example, operations like 4x10->1x40->4x10 on the same
   4035  *        set of ports have been rejected at bcm layer itself, and do not reach
   4036  *        this function
   4037  *      - Pre-FlexPort array
   4038  *        Contains current information on ports to be modified after
   4039  *        the FlexPort operation.  This should include ports whose
   4040  *        mappings are either deleted or remapped.
   4041  *      - Post-FlexPort array
   4042  *        Contains information on new configuration for
   4043  *        ports that are active (present) after the FlexPort operation.
   4044  *        This should include ports whose mappings that are remapped or new.
   4045  */
   4046 int soc_td2p_port_resource_ep_set(int unit, int curr_port_info_size,
   4047                                   soc_port_resource_t *curr_port_info,
   4048                                   int new_port_info_size,
   4049                                   soc_port_resource_t *new_port_info,
   4050                                   soc_td2p_info_t *si_info)
   4051 {
   4052     soc_info_t *si;
   4053     uint32 rval;
   4054     int num_port, port, idx, phy_port;
   4055 
   4056     si = &SOC_INFO(unit);
   4057 
   4058     /* Ingress logical to physical port mapping */
   4059     num_port = soc_mem_index_count(unit, PORT_TABm) - 1;
   4060 
   4061     /* Egress logical to physical port mapping */
   4062     for (port = 0; port < num_port; port++) {
   4063         /*
   4064          * Use logical to physical number mapping from soc info structure
   4065          * since it has been updated before this function is called
   4066          */
   4067         phy_port = si->port_l2p_mapping[port];
   4068 
   4069         rval = 0;
   4070         soc_reg_field_set(unit, EGR_LOGICAL_TO_PHYSICAL_PORT_NUMBER_MAPPINGr,
   4071                           &rval, PHYSICAL_PORT_NUMBERf,
   4072                           phy_port == -1 ? 0xFF : phy_port);
   4073         SOC_IF_ERROR_RETURN
   4074             (WRITE_EGR_LOGICAL_TO_PHYSICAL_PORT_NUMBER_MAPPINGr(unit, port,
   4075                                                                 rval));
   4076     }
   4077 
   4078     /* Clear counters for the newly added ports */
   4079     for (idx = 0; idx < new_port_info_size; idx++) {
   4080         SOC_IF_ERROR_RETURN(soc_td2p_ep_counters_clear(unit,
   4081                                                        &new_port_info[idx]));
   4082     }
   4083 
   4084     return SOC_E_NONE;
   4085 }
   4086 
   4087 /*
   4088  * Function: 
   4089  *      soc_td2p_port_resource_mmu_mapping_set
   4090  * Purpose:
   4091  *      Set the HW MMU Port mappings.
   4092  * Parameters:
   4093  *      unit      - (IN) Unit number.
   4094  *      nport     - (IN) Number of elements in array resource.
   4095  *      resource  - (IN) Port Resource FlexPort configuration.
   4096  * Returns:
   4097  *      SOC_E_XXX
   4098  * Note:
   4099  *      Assumes FlexPort cases are valid.
   4100  *      Assumes SOC INFO data structure has been updated.
   4101  */
   4102 int
   4103 soc_td2p_port_resource_mmu_mapping_set(int unit, int nport,
   4104                                        soc_port_resource_t *resource)
   4105 {
   4106     soc_info_t *si = &SOC_INFO(unit);
   4107     soc_port_resource_t *pr;
   4108     int i;
   4109     int logic_port;
   4110     int phy_port;
   4111     uint32 rval;
   4112 
   4113     LOG_VERBOSE(BSL_LS_SOC_PORT,
   4114                 (BSL_META_U(unit,
   4115                             "SOC MMU Port Mappings Set\n")));
   4116 
   4117     for (i = 0, pr = &resource[0]; i < nport; i++, pr++) {
   4118         if (pr->physical_port == -1) {
   4119             logic_port = 0x7F;
   4120             phy_port = 0xFF;
   4121 
   4122             /* Clear MMU port info */
   4123             SOC_IF_ERROR_RETURN(
   4124             soc_td2p_mmu_port_resource_clear(unit, 
   4125                                              pr->logical_port));
   4126         } else {
   4127             logic_port = pr->logical_port;
   4128             phy_port = pr->physical_port;
   4129         }
   4130 
   4131         /*
   4132          * Skip for legacy inactive configurations since
   4133          * MMU mappings are kept the same.
   4134          */
   4135         if (pr->flags & SOC_PORT_RESOURCE_I_MAP) {
   4136             LOG_VERBOSE(BSL_LS_SOC_PORT,
   4137                         (BSL_META_U(unit,
   4138                                     "  Skip port with inactive configuration, "
   4139                                     "mappings are kept the same, "
   4140                                     "mmu=%d logical=%d physical=%d\n"),
   4141                          si->port_p2m_mapping
   4142                          [si->port_l2p_mapping[pr->logical_port]],
   4143                          pr->logical_port,
   4144                          si->port_l2p_mapping[pr->logical_port]));
   4145             continue;
   4146         }
   4147 
   4148 
   4149         rval = 0;
   4150         soc_reg_field_set(unit, MMU_PORT_TO_PHY_PORT_MAPPINGr, &rval,
   4151                           PHY_PORTf, phy_port);
   4152         SOC_IF_ERROR_RETURN
   4153             (soc_reg32_set(unit, MMU_PORT_TO_PHY_PORT_MAPPINGr,
   4154                            pr->logical_port, 0, rval));
   4155 
   4156         rval = 0;
   4157         soc_reg_field_set(unit, MMU_PORT_TO_LOGIC_PORT_MAPPINGr, &rval,
   4158                           LOGIC_PORTf, logic_port);
   4159         SOC_IF_ERROR_RETURN
   4160             (soc_reg32_set(unit, MMU_PORT_TO_LOGIC_PORT_MAPPINGr,
   4161                            pr->logical_port, 0, rval));
   4162 
   4163         LOG_VERBOSE(BSL_LS_SOC_PORT,
   4164                     (BSL_META_U(unit,
   4165                                 "  MMU port mappings: "
   4166                                 "mmu=%d logical=%d physical=%d\n"),
   4167                      si->port_p2m_mapping
   4168                      [si->port_l2p_mapping[pr->logical_port]],
   4169                      logic_port, phy_port));
   4170     }
   4171 
   4172     return SOC_E_NONE;
   4173 }
   4174 
   4175 
   4176 /*
   4177  * Function:
   4178  *      soc_td2p_port_resource_mmu_set
   4179  * Purpose:
   4180  *      Called to reconfigure the MMU hardware.
   4181  * Parameters:
   4182  *      unit           - (IN) Device Number
   4183  *      nport          - (IN) The number of port modifications in flexport_data
   4184  *      flexport_data  - (IN) An array of port changes that are being done
   4185  * Returns:
   4186  *      SOC_E_NONE if parameters are valid, an error otherwise. 
   4187  * Note:
   4188  *      Assumes FlexPort cases are valid.
   4189  *      Assumes SOC INFO data structure has been updated.
   4190  */
   4191 int
   4192 soc_td2p_port_resource_mmu_set(int unit, int nport,
   4193                                soc_port_resource_t *flexport_data)
   4194 {
   4195     int i, rv = SOC_E_NONE;
   4196     int * ports;
   4197 
   4198     /* Before we initialize LLS for the newly flexed ports,
   4199      * let's take a moment to update _td2_invalid_ptr since
   4200      * flex operation could have added new mmu ports.
   4201      * And also update the LLS memories with INVALID PARENT
   4202      * values
   4203  */
   4204     SOC_IF_ERROR_RETURN(soc_td2p_lls_reinit_invalid_pointers(unit));
   4205     SOC_IF_ERROR_RETURN(soc_td2p_lls_reset_flex(unit));
   4206 
   4207     /* Update MMU Port Mappings */
   4208     SOC_IF_ERROR_RETURN
   4209         (soc_td2p_port_resource_mmu_mapping_set(unit, nport,
   4210                                                 flexport_data));
   4211 
   4212     /* Configure all MMU registers for new ports */
   4213     for (i = 0; i < nport; i++) {
   4214         if (flexport_data[i].physical_port != -1) {
   4215             /* a physical port of -1 indicates it's being deleted, so here
   4216                we're adding */
   4217             SOC_IF_ERROR_RETURN(
   4218             soc_td2p_mmu_port_resource_set(unit, flexport_data[i].logical_port,
   4219                                            flexport_data[i].speed,
   4220                           (flexport_data[i].flags & SOC_PORT_RESOURCE_I_MAP)));
   4221         } 
   4222     }
   4223 
   4224     /* Copy the logical ports into a bcm_ports_t array because
   4225        bcm_td2p_update_base_queue_num in src/bcm/esw/trident2/cosq.c has no
   4226        concept of what a soc_port_resource_t is. */
   4227     ports = sal_alloc(sizeof(int) * nport, "flexport_ports");
   4228     if (ports == NULL) {
   4229         return SOC_E_MEMORY;
   4230     }
   4231     for (i = 0; i < nport; i++) {
   4232         ports[i] = flexport_data[i].logical_port;
   4233     }
   4234 
   4235     /* Update the logical port and queue mappings in memory and registers */
   4236     if (td2p_flexport_cb) {
   4237         rv = td2p_flexport_cb(unit, nport, ports);
   4238     }
   4239 
   4240     /* free up the ports array */
   4241     sal_free(ports);
   4242 
   4243     return rv;
   4244 }
   4245 
   4246 void
   4247 soc_td2p_num_hsp_reserved_reset(int unit)
   4248 {
   4249     num_hsp_to_reserve[0] = 0;
   4250     num_hsp_to_reserve[1] = 0;
   4251     return;
   4252 }
   4253 
   4254 /*
   4255  * Function:
   4256  *      soc_td2p_num_hsp_reserved_per_pipe
   4257  * Purpose:
   4258  *   This function calculates the number of HSP ports to reserve per pipe.
   4259  *   It does by using the following algorithm:
   4260  *   - device speed
   4261  *   - for High clock frequency systems ( > 760), it takes into consideration
   4262  *      the number of TSC-12's that are flex enabled
   4263  *   - for Lower clock frequency systems, it looks at the number of port macros
   4264  *      (TSC-4's) that are flex enabled * Parameters:
   4265  * Parameters 
   4266  *      unit           - (IN) Device Number
   4267  *      pipe           - (IN) The pipe that will be checked to see how many
   4268  *                            HSP need to be reserved.
   4269  *      num_hsp        - (OUT) The number of HSP that need to be reserved
   4270  *                             for the specified pipe.
   4271  * Returns:
   4272  *      SOC_E_NONE if parameters are valid, an error otherwise. 
   4273  * Note:
   4274  */
   4275 int 
   4276 soc_td2p_num_hsp_reserved_per_pipe(int unit, int pipe, int *num_hsp)
   4277 {
   4278     int port_macro, pm_flex_enabled = 0, temp_num_hsp = 0, port = 0;
   4279     int i, phy_port, skip_port;
   4280     soc_info_t *si;
   4281     soc_pbmp_t pbmp;
   4282     int phy_ports_x[] = {1, 21, 33, 53};
   4283     int phy_ports_y[] = {65, 85, 97, 117};
   4284     int * phy_ports = NULL;
   4285 
   4286     si = &SOC_INFO(unit);
   4287 
   4288     if (num_hsp == NULL) {
   4289         return SOC_E_PARAM;
   4290     }
   4291 
   4292     *num_hsp = 0;
   4293 
   4294     /* If we're at a sufficiently high frequency,
   4295        only check the first physical port of every TSC-12 PM:
   4296        physical ports 1, 21, 33, 53, 65, 85, 97, 117.
   4297        This is because only 100G+ ports are considered HSP. */
   4298     if (si->frequency >= 760) {
   4299         if (pipe == 0) {
   4300             phy_ports = phy_ports_x;
   4301         } else {
   4302             phy_ports = phy_ports_y;
   4303         }
   4304         /* If a PGW is flexport capable or if it's 100G but not flex capable,
   4305            a HSP MMU Port needs to be saved for it; it may not be given
   4306            to a non-hsp port. */
   4307         for(i = 0; i < _TD2_PGWS_PER_PIPE; i++) {
   4308             if(soc_td2p_is_port_flex_enable(unit, phy_ports[i])) {
   4309                 port = si->port_p2l_mapping[phy_ports[i]];
   4310                 temp_num_hsp++;
   4311             } else {
   4312                 port = si->port_p2l_mapping[phy_ports[i]];
   4313                 /* the PGW is NOT port flex enabled, but still requires a HSP
   4314                    so mark it as reserved. */
   4315                 if (si->port_speed_max[port] >= 100000 ||
   4316                     soc_property_port_get(unit, port, spn_PORT_SCHED_HSP, 0)) {
   4317                     temp_num_hsp++;
   4318                 }
   4319             }
   4320         }
   4321         /* Go through all the logical ports, skipping the ones mapped to
   4322            the first of the PGWs
   4323            since they were checked above, and see if they are port_sched_hsp */
   4324         pbmp = pipe ? si->ypipe_pbm : si->xpipe_pbm;
   4325         SOC_PBMP_ITER(pbmp, port) {
   4326             phy_port = si->port_l2p_mapping[port];
   4327             skip_port = 0;
   4328 
   4329             /* skip the port if it was already counted above */
   4330             for(i = 0; i < _TD2_PGWS_PER_PIPE; i++) {
   4331                 if(phy_port == phy_ports[i]) {
   4332                     skip_port = 1;
   4333                     break;
   4334                 }
   4335             }
   4336             if(skip_port == 0) {
   4337                 /* if the logical port was declared port_sched_hsp,
   4338                    reserve HSP */
   4339                 if(soc_property_port_get(unit, port, spn_PORT_SCHED_HSP, 0)) {
   4340                     temp_num_hsp++;
   4341                 }
   4342             }
   4343         }
   4344     } else {
   4345         /* Otherwise, check each PM on the specified pipe because
   4346            we'll need to at least reserve 1 HSP port per port macro.
   4347            This function does NOT determine if a T2OQ needs to be
   4348            reserved too. */
   4349         for (port_macro = pipe * _TD2P_NUM_TSC4_PER_PIPE; 
   4350              port_macro < (pipe * _TD2P_NUM_TSC4_PER_PIPE) + 
   4351                   _TD2P_NUM_TSC4_PER_PIPE; port_macro++) {
   4352             SOC_IF_ERROR_RETURN(
   4353                soc_td2p_port_macro_flex_enabled(unit, port_macro, &pm_flex_enabled));
   4354 
   4355             /* If a PM is flexport capable or if it's 40G but not flex capable,
   4356                a HSP MMU Port needs to be saved for it; it may not be given
   4357                to a non-hsp port. */
   4358             if (pm_flex_enabled == 1) {
   4359                 temp_num_hsp++;
   4360             } else {
   4361                 phy_port = soc_td2p_pm_to_1st_port_tsc4[port_macro];
   4362                 port = si->port_p2l_mapping[phy_port];
   4363                 /* the PM is NOT port flex enabled, but still requires a HSP
   4364                    so mark it as reserved. */
   4365                 if (si->port_speed_max[port] >= 40000 ||
   4366                     soc_property_port_get(unit, port, spn_PORT_SCHED_HSP, 0)) {
   4367                     temp_num_hsp++;
   4368                 }
   4369             }
   4370         }
   4371 
   4372         /* Go through all the logical ports, skipping the ones mapped to
   4373            the port macros
   4374            since they were checked above, and see if they are port_sched_hsp */
   4375         pbmp = pipe ? si->ypipe_pbm : si->xpipe_pbm;
   4376         SOC_PBMP_ITER(pbmp, port) {
   4377             phy_port = si->port_l2p_mapping[port];
   4378             skip_port = 0;
   4379 
   4380             /* skip the port if it was already counted above */
   4381             for (port_macro = pipe * _TD2P_NUM_TSC4_PER_PIPE; 
   4382                  port_macro < (pipe * _TD2P_NUM_TSC4_PER_PIPE) + 
   4383                       _TD2P_NUM_TSC4_PER_PIPE; port_macro++) {
   4384                 if(phy_port == 
   4385                    soc_td2p_pm_to_1st_port_tsc4[port_macro]) {
   4386                     skip_port = 1;
   4387                     break;
   4388                 }
   4389             }
   4390             if(skip_port == 0) {
   4391                 /* if the logical port was declared port_sched_hsp,
   4392                    reserve HSP */
   4393                 if(soc_property_port_get(unit, port, spn_PORT_SCHED_HSP, 0)) {
   4394                     temp_num_hsp++;
   4395                 }
   4396             }
   4397         }
   4398     }
   4399     /* Only allow 16 HSP maximum per pipe */
   4400     if(temp_num_hsp > SOC_TD2_NUM_HSP_MMU_PORTS_PER_PIPE) {
   4401         *num_hsp = SOC_TD2_NUM_HSP_MMU_PORTS_PER_PIPE;
   4402     } else {
   4403         *num_hsp = temp_num_hsp;
   4404     }
   4405 
   4406     return SOC_E_NONE;
   4407 }
   4408 
   4409 
   4410 
   4411 /* Tells if a port macro (indexed by TSC4, not TSC12) is flex port enabled.
   4412  *  
   4413  * Port macro flex on or off is determined by the first port in that macro. 
   4414  * For TSC12 it's the first port in the first TSC4. For a TSC4 that is NOT 
   4415  * part of a TSC12, it's also the first port of that port macro.  For a TSC4 
   4416  * that is a part of a TSC12, refer to the first port of the first port macro 
   4417  * for that TSC12. 
   4418  *  
   4419  * Parameters:
   4420  *      unit          - (IN) Unit number.
   4421  *      port_macro    - (IN) port macro desired
   4422  *      flex_enabled  - (OUT) whether the port macro is enabled or disabled
   4423  *  
   4424  *  Returns: 
   4425  *      SOC_E_xxx
   4426  */
   4427 int
   4428 soc_td2p_port_macro_flex_enabled(int unit, int port_macro, int * flex_enabled)
   4429 {
   4430     soc_info_t *si;
   4431     int port_num = -1;
   4432 
   4433     si = &SOC_INFO(unit);
   4434 
   4435     if ((port_macro < 0) || (port_macro > 31)) {
   4436         return SOC_E_PARAM;
   4437     }
   4438 
   4439     /* If SKU is max frequency, check flexport for TSC-12 and then
   4440             individual TSC-4.
   4441        Else, check each individual TSC-4 (not grouped as TSC-12). */
   4442     if (si->frequency >= 760) {
   4443         port_num = soc_td2p_pm_to_1st_port_tsc12[port_macro];
   4444     } else {
   4445         port_num = soc_td2p_pm_to_1st_port_tsc4[port_macro];
   4446     }
   4447 
   4448     *flex_enabled = soc_td2p_is_port_flex_enable(unit, port_num);
   4449 
   4450     return SOC_E_NONE;
   4451 }
   4452 
   4453 /* Function to reserve cells for CutThru(CT) and Flex ports
   4454  * Parameters:
   4455  *      unit          - (IN) Unit number.
   4456  *      pipe          - (IN) Pipe number
   4457  *      flex          - (IN) Config has Flex ports or Not
   4458  *      rsvd_buffer   - (OUT) Buffers reserved per resource (Ing/Egr/ASF)
   4459  * Returns:
   4460  *      SOC_E_xxx
   4461  */
   4462 int
   4463 soc_td2p_mmu_additional_buffer_reserve(int unit, int pipe, int flex,
   4464                                      _soc_mmu_rsvd_buffer_t *rsvd_buffer)
   4465 {
   4466     soc_info_t *si;
   4467     int pg_min_cells = 0, qgrp_min_cells = 0, hdrm_cells = 0, asf_cells = 0;
   4468     int total_reserve = 0;
   4469     int lossless = 0;
   4470     int mcq_entry = 0;
   4471 
   4472     int i, j, start_port, logical_port, start_pm, end_pm;
   4473     int pm_flex_enabled = 0;
   4474 
   4475     COMPILER_REFERENCE(si);
   4476     si = &SOC_INFO(unit);
   4477 
   4478     if ((pipe >= NUM_PIPE(unit)) || (!rsvd_buffer)) {
   4479         return SOC_E_PARAM;
   4480     }
   4481 
   4482     /* returning if flex is true.  flex true indicates the legacy flexport ':i' case is
   4483        enabled */
   4484     if (flex) {
   4485         return SOC_E_NONE;
   4486     }
   4487 
   4488     lossless = soc_property_get(unit, spn_MMU_LOSSLESS, 1);
   4489 
   4490     /* if we're on pipe 1, start at the 2nd half of the macros.  Otherwise,
   4491        start at the 1st half */
   4492     if(pipe) {
   4493         start_pm = _TD2P_NUM_TSC4_PER_PIPE;
   4494         end_pm = 2*_TD2P_NUM_TSC4_PER_PIPE;
   4495     } else {
   4496         start_pm = 0;
   4497         end_pm = _TD2P_NUM_TSC4_PER_PIPE;
   4498     }
   4499     
   4500     /* Per pipe, calculate the memory required on a per port macro (TSC4) basis */    
   4501     for (i = start_pm; i < end_pm; i++) {
   4502         SOC_IF_ERROR_RETURN(
   4503             soc_td2p_port_macro_flex_enabled(unit, i, &pm_flex_enabled));
   4504 
   4505         /* if this port macro is flex enabled, allocate memory for it accordingly */
   4506         if (pm_flex_enabled == 1) {
   4507             /* Reserved Buffer for Flex Port Macro when Flex Port is enabled in
   4508                device */
   4509             if (lossless) {
   4510                 hdrm_cells      = (_TD2P_RSVD_BUF_FLEX_HDRM_LOSSLESS 
   4511                                    * _TD2P_NUM_PORTS_PER_TSC4);
   4512                 pg_min_cells    = (_TD2P_MMU_RSVD_BUF_FLEX_PGMIN_LOSSLESS
   4513                                    * _TD2P_NUM_PORTS_PER_TSC4);
   4514                 qgrp_min_cells  = 0;
   4515                 asf_cells       = (_TD2P_RSVD_BUF_FLEX_ASF
   4516                                    * _TD2P_NUM_PORTS_PER_TSC4);
   4517             } else {
   4518                 hdrm_cells      = 0;
   4519                 pg_min_cells    = 0;
   4520                 qgrp_min_cells  = (_TD2P_RSVD_BUF_FLEX_QGRP 
   4521                                    * _TD2P_NUM_PORTS_PER_TSC4);
   4522 
   4523                 asf_cells       = (_TD2P_RSVD_BUF_FLEX_ASF
   4524                                    * _TD2P_NUM_PORTS_PER_TSC4);
   4525             }
   4526             mcq_entry = _TD2P_MMU_NUM_MCQ_PORT_MACRO * 
   4527                 _TD2P_MMU_PER_COSQ_EGRESS_QENTRY_RSVD *
   4528                 _TD2P_NUM_PORTS_PER_TSC4;
   4529         } else {
   4530             /*For port modules that are in non-flex mode, buffer is reserved 
   4531               per port (not port macro).
   4532              
   4533               Here we are calculating the buffer requirements for this TSC4 on
   4534               a per port basis. */
   4535             hdrm_cells = 0;
   4536             pg_min_cells = 0;
   4537             qgrp_min_cells = 0;
   4538             asf_cells = 0;
   4539             mcq_entry = 0;
   4540 
   4541             start_port = (i * _TD2P_NUM_PORTS_PER_TSC4) + 1;
   4542             for (j = start_port; j < start_port + _TD2P_NUM_PORTS_PER_TSC4; j++) {
   4543                 /* figure out from the logical port what the speed of this port is */
   4544                 logical_port = si->port_p2l_mapping[j];
   4545                 if (logical_port == -1) {
   4546                     continue;
   4547                 }
   4548 
   4549                 if (si->port_speed_max[logical_port] >= 100000) {
   4550                     if (lossless) {
   4551                         hdrm_cells      += _TD2P_RSVD_BUF_NON_FLEX_100G_HDRM_LOSSLESS;
   4552                         pg_min_cells    += _TD2P_RSVD_BUF_NON_FLEX_PGMIN;
   4553                         qgrp_min_cells  += _TD2P_RSVD_BUF_NON_FLEX_QGRP;
   4554                         asf_cells       += _TD2P_RSVD_BUF_NON_FLEX_ASF;
   4555                     } else {
   4556                         qgrp_min_cells  += _TD2P_RSVD_BUF_NON_FLEX_QGRP;
   4557                         asf_cells       += _TD2P_RSVD_BUF_NON_FLEX_ASF;
   4558                     }
   4559                 } else if (si->port_speed_max[logical_port] >= 40000) {
   4560                     if (lossless) {
   4561                         hdrm_cells      += _TD2P_RSVD_BUF_NON_FLEX_40G_HDRM_LOSSLESS;
   4562                         pg_min_cells    += _TD2P_RSVD_BUF_NON_FLEX_PGMIN;
   4563                         qgrp_min_cells  += _TD2P_RSVD_BUF_NON_FLEX_QGRP;
   4564                         asf_cells       += _TD2P_RSVD_BUF_NON_FLEX_ASF;
   4565                     } else {
   4566                         qgrp_min_cells  += _TD2P_RSVD_BUF_NON_FLEX_QGRP;
   4567                         asf_cells       += _TD2P_RSVD_BUF_NON_FLEX_ASF;
   4568                     }
   4569                 } else if (si->port_speed_max[logical_port] >= 20000) {
   4570                     if (lossless) {
   4571                         hdrm_cells      += _TD2P_RSVD_BUF_NON_FLEX_20G_HDRM_LOSSLESS;
   4572                         pg_min_cells    += _TD2P_RSVD_BUF_NON_FLEX_PGMIN;
   4573                         qgrp_min_cells  += _TD2P_RSVD_BUF_NON_FLEX_QGRP;
   4574                         asf_cells       += _TD2P_RSVD_BUF_NON_FLEX_ASF;
   4575                     } else {
   4576                         qgrp_min_cells  += _TD2P_RSVD_BUF_NON_FLEX_QGRP;
   4577                         asf_cells       += _TD2P_RSVD_BUF_NON_FLEX_ASF;
   4578                     }
   4579                 } else {
   4580                     if (lossless) {
   4581                         hdrm_cells      += _TD2P_RSVD_BUF_NON_FLEX_10G_HDRM_LOSSLESS;
   4582                         pg_min_cells    += _TD2P_RSVD_BUF_NON_FLEX_PGMIN;
   4583                         qgrp_min_cells  += _TD2P_RSVD_BUF_NON_FLEX_QGRP;
   4584                         asf_cells       += _TD2P_RSVD_BUF_NON_FLEX_10G_ASF;
   4585                     } else {
   4586                         qgrp_min_cells  += _TD2P_RSVD_BUF_NON_FLEX_QGRP;
   4587                         asf_cells       += _TD2P_RSVD_BUF_NON_FLEX_10G_ASF;
   4588                     }
   4589                 }
   4590                 mcq_entry += soc_td2p_mcq_entries_rsvd_port(unit, logical_port);
   4591             }
   4592         }
   4593 
   4594         /* Add what was calculated for the port macro to the total */
   4595         rsvd_buffer->ing_rsvd_cells += (hdrm_cells + pg_min_cells);
   4596         rsvd_buffer->egr_rsvd_cells += qgrp_min_cells;
   4597         rsvd_buffer->asf_rsvd_cells += asf_cells;
   4598         rsvd_buffer->mcq_entry_rsvd += mcq_entry;
   4599     }
   4600 
   4601     total_reserve = rsvd_buffer->ing_rsvd_cells;
   4602     total_reserve += rsvd_buffer->egr_rsvd_cells;
   4603     total_reserve += rsvd_buffer->asf_rsvd_cells;
   4604 
   4605     LOG_VERBOSE(BSL_LS_SOC_MMU,
   4606                 (BSL_META_U(unit,
   4607                             "MMU config: Cells rsvd for Pipe %d,"
   4608                             " Flex/ASF per pipe: %d, Ing: %d,"
   4609                             " Egr: %d, ASF: %d MCQ %d\n"),
   4610                             pipe, total_reserve, rsvd_buffer->ing_rsvd_cells,
   4611                             rsvd_buffer->egr_rsvd_cells,
   4612                             rsvd_buffer->asf_rsvd_cells,
   4613                             rsvd_buffer->mcq_entry_rsvd));
   4614 
   4615     return SOC_E_NONE;
   4616 }
   4617 
   4618 STATIC int
   4619 soc_td2p_mmu_config_init_port(int unit, int port)
   4620 {
   4621     int rv;
   4622     int lossless;
   4623     _soc_mmu_cfg_buf_t *buf;
   4624     _soc_mmu_device_info_t devcfg;
   4625 
   4626     buf = soc_mmu_cfg_alloc(unit);
   4627     if (!buf) {
   4628         return SOC_E_MEMORY;
   4629     }
   4630 
   4631     lossless = soc_property_get(unit, spn_MMU_LOSSLESS, 1);
   4632 
   4633     _soc_td2_mmu_init_dev_config(unit, &devcfg, lossless);
   4634     /* Calculate the buf - global as well as per port
   4635      * but _soc_td2_mmu_config_buf_set_hw_port is only made
   4636      * for that port - since it is flex operation - we don't
   4637      * touch any other port */
   4638     _soc_td2_mmu_config_buf_default(unit, buf, &devcfg, lossless);
   4639     if (soc_property_get(unit, spn_MMU_CONFIG_OVERRIDE, 1) == 0) {
   4640         _soc_mmu_cfg_buf_read(unit, buf, &devcfg);
   4641     }
   4642     rv = _soc_mmu_cfg_buf_check(unit, buf, &devcfg);
   4643     if (SOC_FAILURE(rv)) {
   4644         LOG_VERBOSE(BSL_LS_SOC_COMMON,
   4645                 (BSL_META_U(unit,
   4646                             "MMU config: Use default setting\n")));
   4647         _soc_td2_mmu_config_buf_default_global(unit, buf, &devcfg, lossless);
   4648         _soc_td2_mmu_config_buf_default_port(unit, port, buf, &devcfg, lossless);
   4649         _soc_mmu_cfg_buf_calculate(unit, buf, &devcfg);
   4650     }
   4651     rv = _soc_td2_mmu_config_buf_set_hw_port(unit, port, buf, &devcfg, lossless);
   4652 
   4653     soc_mmu_cfg_free(unit, buf);
   4654 
   4655     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   4656                 (BSL_META_U(unit,
   4657                             "MMU THDI/THDO init done\n")));
   4658     return rv;
   4659 }
   4660 
   4661 
   4662 /*
   4663  * Function:
   4664  *      soc_td2p_mmu_flexport_map_validate
   4665  * Purpose:
   4666  *      Validate and allocate/deallocate MMU port assignments.
   4667  *      New MMU port assignments are returned in argument.
   4668  * Parameters:
   4669  *      unit           - (IN) Device Number
   4670  *      nport          - (IN) The number of port modifications in flexport_data
   4671  *      flexport_data  - (IN/OUT) An array of port changes that are being done.
   4672  *                       Returns MMU ports assignment.
   4673  * Returns:
   4674  *      SOC_E_NONE if parameters are valid, an error otherwise. 
   4675  */
   4676 int
   4677 soc_td2p_mmu_flexport_map_validate(int unit, int nport, 
   4678                                    soc_port_resource_t * flexport_data)
   4679 {
   4680     return soc_td2p_mmu_flexport_allocate_deallocate_ports(unit, nport, 
   4681                                                            flexport_data);
   4682 }
   4683 
   4684 /*
   4685  * Function:
   4686  *      soc_td2p_mmu_flexport_allocate_deallocate_ports
   4687  * Purpose:
   4688  *      Allocate or deallocate ports in software.  This function frees up
   4689  *      mmu ports or allocates them in software.  When apply is 0,
   4690  *      flexport_data[x].mmu_port needs to be filled in.  When apply is 1,
   4691  *      flexport_data[x].mmu_port is valid and needs to be assigned in the
   4692  *      port_p2m_mapping[].
   4693  * Parameters:
   4694  *      unit           - (IN) Device Number
   4695  *      nport          - (IN) The number of port modifications in flexport_data
   4696  *      flexport_data  - (IN/OUT) An array of port changes that are being done
   4697  * Returns:
   4698  *      SOC_E_NONE if parameters are valid, an error otherwise. 
   4699  */
   4700 int
   4701 soc_td2p_mmu_flexport_allocate_deallocate_ports(int unit, int nport, 
   4702                              soc_port_resource_t * flexport_data)
   4703 {
   4704     int i, j;
   4705     int phy_port;
   4706     int mmu_port;
   4707     int pipe;
   4708     int start_mmu_port;
   4709     int end_mmu_port;
   4710     int port_max_speed = 0;
   4711     int mmu_ports_used[TD2P_PIPES_PER_DEV * _TD2_PORTS_PER_PIPE];
   4712     int flexport_max_speed = -1;
   4713     int flexport_max_speed_pipe[_TD2_PIPES_PER_DEV];
   4714     int t2oq_reserved[2];
   4715     int port_sched_hsp_exists = 0;
   4716 
   4717     soc_info_t *si = &SOC_INFO(unit);
   4718 
   4719     t2oq_reserved[0] = 0;
   4720     t2oq_reserved[1] = 0;
   4721 
   4722     sal_memset(mmu_ports_used, 0, sizeof(int) * COUNTOF(mmu_ports_used));
   4723 
   4724     /* Iterate through all logical ports and see if any of them are marked
   4725        with port_sched_hsp */
   4726     PBMP_ALL_ITER(unit, i) {
   4727         if(soc_property_port_get(unit, i, spn_PORT_SCHED_HSP, 0)) {
   4728             port_sched_hsp_exists = 1;
   4729         }
   4730     }
   4731 
   4732     /* Iterate through all the MMU ports and mark the used mmu ports */
   4733     for (j = 1; j <= TD2P_PIPES_PER_DEV * _TD2_PORTS_PER_PIPE; j++) {
   4734 
   4735         mmu_port = si->port_p2m_mapping[j];
   4736 
   4737         /* if the mmu port is assigned, mark it as used */
   4738         if(mmu_port != -1) {
   4739             mmu_ports_used[mmu_port] = 1;
   4740         }
   4741     }
   4742 
   4743     /* Find out how many port macros are capable of flexing per pipe. Only
   4744        really needs to be called and set once. */
   4745     if(num_hsp_to_reserve[0] == 0 && num_hsp_to_reserve[1] == 0) {
   4746         SOC_IF_ERROR_RETURN(
   4747            soc_td2p_num_hsp_reserved_per_pipe(unit, 0, &num_hsp_to_reserve[0]));
   4748         SOC_IF_ERROR_RETURN(
   4749            soc_td2p_num_hsp_reserved_per_pipe(unit, 1, &num_hsp_to_reserve[1]));
   4750     }
   4751 
   4752     /* Iterate through the array to deallocate and allocate ports */
   4753     for (i = 0; i < nport; i++) {
   4754         if ((flexport_data[i].flags & SOC_PORT_RESOURCE_I_MAP) ||
   4755             (flexport_data[i].physical_port == -1)) {
   4756 
   4757             /*
   4758              * Get the current physical port and MMU Port associated
   4759              * with the logical port passed in */
   4760             phy_port = si->port_l2p_mapping[flexport_data[i].logical_port];
   4761 
   4762             if (phy_port == -1) { 
   4763                 LOG_VERBOSE(BSL_LS_SOC_MMU,
   4764                     (BSL_META_U(unit,
   4765                                 "MMU port deallocation failure: logical "
   4766                                 "port %d is not mapped to a physical port\n"), 
   4767                                 flexport_data[i].logical_port));
   4768 
   4769                 return SOC_E_PARAM;
   4770             }
   4771 
   4772             mmu_port = si->port_p2m_mapping[phy_port];
   4773 
   4774             /* Use current MMU port assignments for inactive mapping */
   4775             if (flexport_data[i].flags & SOC_PORT_RESOURCE_I_MAP) {
   4776                 if (mmu_port == -1) { 
   4777                     LOG_ERROR(BSL_LS_SOC_MMU,
   4778                               (BSL_META_U(unit,
   4779                                           "Invalid MMU port on inactive "
   4780                                           "port configuration: "
   4781                                           "port=%d mmu=%d\n"),
   4782                                flexport_data[i].logical_port, mmu_port));
   4783                     return SOC_E_INTERNAL;
   4784                 }
   4785 
   4786                 flexport_data[i].mmu_port = mmu_port;
   4787                 LOG_VERBOSE(BSL_LS_SOC_MMU,
   4788                             (BSL_META_U(unit,
   4789                                         "Inactive port configuration, "
   4790                                         "keep same mapping: port=%d mmu=%d\n"),
   4791                              flexport_data[i].logical_port, mmu_port));
   4792                 continue;
   4793             }
   4794 
   4795             /*
   4796              * Continue with next case.
   4797              * If the phy_port == -1, we're deallocating if we're told to
   4798              */
   4799 
   4800             /* Check to make sure we aren't indexing into mmu_ports_used with
   4801                a negative mmu port number. Skip this if p2m returns negative. */
   4802             if (mmu_port < 0) {
   4803                 continue;
   4804             }
   4805             /* Mark the MMU port unused so that it can be allocated again
   4806                in this routine */
   4807             mmu_ports_used[si->port_p2m_mapping[phy_port]] = 0;
   4808 
   4809 
   4810         } else {
   4811             /* We're allocating a port.
   4812                1. Find out if we need to allocate a HSP given the port speed
   4813                and the clock frequency
   4814                2. Assign a free MMU port appropriate to the pipe the physical
   4815                port is on.  A phy port on X
   4816                   pipe must have an MMU port on X pipe, Y on Y.  */
   4817 
   4818             SOC_IF_ERROR_RETURN(soc_td2p_port_resource_speed_max_get(unit, &flexport_max_speed));
   4819 
   4820 
   4821             /* Find out what pipe we're going to assign to */
   4822             if (flexport_data[i].physical_port < si->phy_port_base[1]) { /* X-pipe */
   4823                 pipe = 0;
   4824             } else {
   4825                 pipe = 1;
   4826             }
   4827 
   4828             /* If a per pipe flex speed has been defined, use that instead.
   4829                Must have been defined for both X and Y Pipe. */
   4830             flexport_max_speed_pipe[0] = 0;
   4831             flexport_max_speed_pipe[1] = 0;
   4832 
   4833             SOC_IF_ERROR_RETURN(soc_td2p_port_resource_speed_max_x_get(unit, &flexport_max_speed_pipe[0]));
   4834             SOC_IF_ERROR_RETURN(soc_td2p_port_resource_speed_max_y_get(unit, &flexport_max_speed_pipe[1]));
   4835 
   4836             /* If both X and Y pipes have had their flex speed specified, select
   4837                the one from the appropriate pipe; it takes priority over the
   4838                global flex speed. */
   4839             if ((flexport_max_speed_pipe[0] > 0) && (flexport_max_speed_pipe[1] > 0)) {
   4840                 flexport_max_speed = flexport_max_speed_pipe[pipe];
   4841             }
   4842 
   4843             /* 1. Find the first unused mmu port and map it to our phy
   4844                port.  If we aren't allocating a HSP, skip MMU Ports 0-15
   4845                (start at 16). If we are, start at 0 and end at 15.
   4846              
   4847                We use SOC_TD2_NUM_MMU_PORTS_PER_PIPE instead of
   4848                _TD2_PORTS_PER_PIPE because
   4849                the last 11 MMU ports in each pipe are not used.
   4850              
   4851                **** THIS IS PER PIPE!!! ****
   4852              
   4853                */
   4854             if (si->bandwidth >= 960000) {
   4855                 if(flexport_data[i].speed >= 100000) {
   4856                     start_mmu_port = 0;
   4857                     end_mmu_port = num_hsp_to_reserve[pipe];
   4858                 } else {
   4859                     /* If any port is capable of flexing above HG[42],
   4860                        then we've reserved HSP and T2OQ */
   4861                     if(flexport_max_speed > 42000 || port_sched_hsp_exists == 1) {
   4862                         start_mmu_port = num_hsp_to_reserve[pipe];
   4863                         /* 53 MMU ports per pipe, MMU port 52 is CPU port,
   4864                            MMU port 116 is Loopback port*/
   4865                         end_mmu_port = SOC_TD2_NUM_MMU_PORTS_PER_PIPE - 1;
   4866 
   4867                         /* Reserving T2OQ per pipe to match with HSP */
   4868                         t2oq_reserved[pipe] = num_hsp_to_reserve[pipe];
   4869                     } else {
   4870                         /* No HSP.  All ports are treated as normal */
   4871                         start_mmu_port = 0;
   4872                         end_mmu_port = SOC_TD2_NUM_MMU_PORTS_PER_PIPE - 1;
   4873                     }
   4874                 }
   4875             } else if (si->bandwidth >= 480000) {
   4876                 /* both 480G and 720G SKU need a HSP at 40Gb and above */
   4877                 if (flexport_data[i].speed >= 40000) {
   4878                     start_mmu_port = 0;
   4879                     end_mmu_port = num_hsp_to_reserve[pipe];
   4880                 } else {
   4881                     /* If any port is capable of flexing above 40G,
   4882                        then we've reserved HSP and T2OQ */
   4883                     if(flexport_max_speed >= 40000 || port_sched_hsp_exists == 1) {
   4884                         start_mmu_port = num_hsp_to_reserve[pipe];
   4885                         /* 53 MMU ports per pipe, MMU port 52 is CPU port,
   4886                            MMU port 116 is Loopback port */
   4887                         end_mmu_port = SOC_TD2_NUM_MMU_PORTS_PER_PIPE - 1;
   4888 
   4889                         /* Reserving T2OQ per pipe to match with HSP */
   4890                         t2oq_reserved[pipe] = num_hsp_to_reserve[pipe];
   4891                     } else {
   4892                         start_mmu_port = 0;
   4893                         end_mmu_port = SOC_TD2_NUM_MMU_PORTS_PER_PIPE - 1;
   4894                     }
   4895                 }
   4896             } else {
   4897                 LOG_VERBOSE(BSL_LS_SOC_MMU,
   4898                     (BSL_META_U(unit,
   4899                                 "MMU port allocation failure: "
   4900                                 "SKU %d is not supported\n"), 
   4901                                 si->bandwidth));
   4902                 return SOC_E_INTERNAL;
   4903             }
   4904 
   4905             /* 2. check pipe for a free mmu port */
   4906             /* Add the necessary offset for the pipe we're in */
   4907             start_mmu_port += (pipe * _TD2_PORTS_PER_PIPE);
   4908             end_mmu_port += (pipe * _TD2_PORTS_PER_PIPE);
   4909 
   4910             /* loop from start mmu port to end mmu port to find
   4911                a free mmu port
   4912                0-51 is range for X Pipe
   4913                52 is CPU port
   4914                53-63 are NOT used
   4915                64-115 is range for Y Pipe
   4916                116 is Loopback port */
   4917             for(j = start_mmu_port; j < end_mmu_port; j++) {
   4918                 /* Case where SKU == 720G and
   4919                    40 Gig <= max flexed speed < 100 Gig doesn't
   4920                    require T2OQ to be reserved, so we
   4921                    can use mmu ports 36 - 51 in that case,
   4922                    but MUST skip for all others */
   4923                 SOC_IF_ERROR_RETURN
   4924                     (soc_td2p_port_resource_speed_max_get(unit,
   4925                                                           &port_max_speed));
   4926 
   4927                 /* Only want to skip the amount of T2OQ needed to match with
   4928                    HSP. If we reserved 4 HSP, need to reserve 4 T2OQ max.
   4929                    If we reserved 16 HSP, need to reserve 16 T2OQ.
   4930                    j < (36 + t2oq_reserved + (pipe * _TD2_PORTS_PER_PIPE)).
   4931                    sets the upper limit of T2OQ we reserve since j >= 36...  .
   4932                    is the base. */
   4933                 if (!((si->bandwidth == 720000) &&
   4934                       (port_max_speed >= 40000) &&
   4935                       (port_max_speed < 100000))){
   4936                     if ((j >= 36 + (pipe * _TD2_PORTS_PER_PIPE)) &&
   4937                         j < (36 + t2oq_reserved[pipe] + (pipe * _TD2_PORTS_PER_PIPE))) {
   4938                         continue;
   4939                     }
   4940                 }
   4941 
   4942                 /* We found an unused MMU port! Let's assign it to
   4943                    a phy port! */
   4944                 if (mmu_ports_used[j] == 0) {
   4945                     /* Mark the port as used. This is done in case
   4946                        we're passed multiple ports
   4947                        to allocate to make sure we have enough ports. */
   4948                     mmu_ports_used[j] = 1;
   4949                     flexport_data[i].mmu_port = j;
   4950                     break;
   4951                 }
   4952             }
   4953 
   4954             /* if we didn't find a free mmu port, return error. */
   4955             if (j == end_mmu_port) {
   4956                 return SOC_E_RESOURCE;
   4957             }
   4958         }
   4959     }
   4960     return SOC_E_NONE;
   4961 }
   4962 
   4963 /*
   4964 * Function:
   4965 *     soc_td2p_port_asf_set
   4966 * Purpose:
   4967 *     Enable/Disable CT/ASF sequence
   4968 * Parameters:
   4969 *     unit    - (IN) Unit number.
   4970 *     port    - (IN) Logical SOC port number.
   4971 *     enable  - (IN) Enable or Disable.
   4972 * Returns:
   4973 *     SOC_E_XXX
   4974  */
   4975 int
   4976 soc_td2p_port_asf_set (int unit, soc_port_t port, int enable)
   4977 {
   4978     soc_port_resource_t res;
   4979     soc_info_t *si;
   4980     si = &SOC_INFO(unit);
   4981 
   4982     sal_memset(&res, 0, sizeof(soc_port_resource_t));
   4983     res.logical_port = port;
   4984     res.physical_port = si->port_l2p_mapping[port];
   4985     res.speed = si->port_speed_max[port];
   4986     res.oversub = IS_OVERSUB_PORT(unit, port);
   4987 
   4988     /* Enable/disable cut-through for this port */
   4989     return soc_td2p_cut_thru_enable_disable(unit, &res, enable);
   4990 }
   4991 
   4992 /*
   4993 * Function:
   4994 *     soc_td2p_port_icc_width_set
   4995 * Purpose:
   4996 *     Program PORT_INITIAL_COPY_COUNT_WIDTHr
   4997 * Parameters:
   4998 *     unit    - (IN) Unit number.
   4999 *     port    - (IN) Logical SOC port number.
   5000 * Returns:
   5001 *     SOC_E_XXX
   5002  */
   5003 STATIC int
   5004 soc_td2p_port_icc_width_set(int unit, soc_port_t port)
   5005 {
   5006     int num_lanes;
   5007     int count_width = 0;
   5008 
   5009     if (SOC_REG_IS_VALID(unit, PORT_INITIAL_COPY_COUNT_WIDTHr)) {
   5010         num_lanes = SOC_INFO(unit).port_num_lanes[port];
   5011         switch (num_lanes) {
   5012             case 1: count_width = 1;
   5013                     break;
   5014             case 2: count_width = 2;
   5015                     break;
   5016             case 4: count_width = 3;
   5017                     break;
   5018             default: count_width = 0;
   5019                      break;
   5020         }
   5021         if (SOC_REG_FIELD_VALID(unit, PORT_INITIAL_COPY_COUNT_WIDTHr, 
   5022                     BIT_WIDTHf)) {
   5023             SOC_IF_ERROR_RETURN(
   5024                     soc_reg_field32_modify(unit, PORT_INITIAL_COPY_COUNT_WIDTHr,
   5025                         port, BIT_WIDTHf, count_width ? (count_width - 1) : 0));                    
   5026         }
   5027     }
   5028 
   5029     return SOC_E_NONE;
   5030 }
   5031 
   5032 /*
   5033  * Function:
   5034  *     soc_td2p_repl_port_agg_map_init
   5035  * Purpose:
   5036  *     Initialize L3MC Port Agg Map.
   5037  * Parameters:
   5038  *     unit    - (IN) Unit number.
   5039  *     port    - (IN) Logical SOC port number.
   5040  * Returns:
   5041  *     SOC_E_xxx
   5042  */
   5043 STATIC int
   5044 soc_td2p_repl_port_agg_map_init(int unit, soc_port_t port)
   5045 {
   5046     soc_info_t *si;
   5047     int phy_port, mmu_port;
   5048     uint32 regval;
   5049 
   5050     si = &SOC_INFO(unit);
   5051     phy_port = si->port_l2p_mapping[port];
   5052     mmu_port = si->port_p2m_mapping[phy_port];
   5053 
   5054     /* configure mmu port to repl aggregateId map */
   5055     regval = 0;
   5056     soc_reg_field_set(unit, MMU_TOQ_REPL_PORT_AGG_MAPr, &regval,
   5057             L3MC_PORT_AGG_IDf, mmu_port % 64);
   5058     SOC_IF_ERROR_RETURN(soc_reg32_set(unit, MMU_TOQ_REPL_PORT_AGG_MAPr,
   5059                 port,0,regval));
   5060 
   5061     regval = 0;
   5062     soc_reg_field_set(unit, MMU_ENQ_REPL_PORT_AGG_MAPr, &regval,
   5063                       L3MC_PORT_AGG_IDf, mmu_port);
   5064     SOC_IF_ERROR_RETURN(
   5065         soc_reg32_set(unit, MMU_ENQ_REPL_PORT_AGG_MAPr, port, 0, regval));
   5066 
   5067     regval = 0;
   5068     soc_reg_field_set(unit, MMU_ENQ_LOGICAL_PORT_TO_PORT_AGG_MAPr, &regval,
   5069                       L3MC_PORT_AGG_IDf, mmu_port);
   5070     SOC_IF_ERROR_RETURN(WRITE_MMU_ENQ_LOGICAL_PORT_TO_PORT_AGG_MAPr(unit,
   5071                         port, regval));
   5072 
   5073     return SOC_E_NONE;
   5074 }
   5075 
   5076 /*
   5077 * Function:
   5078 *     soc_td2p_ipmc_repl_init
   5079 * Purpose:
   5080 *     Initialize IPMC Replication settings
   5081 * Parameters:
   5082 *     unit    - (IN) Unit number.
   5083 *     port    - (IN) Logical SOC port number.
   5084 * Returns:
   5085 *     SOC_E_XXX
   5086  */
   5087 STATIC int
   5088 soc_td2p_ipmc_repl_init(int unit, soc_port_t port)
   5089 {
   5090     /* Program MMU_TOQ_REPL_PORT_AGG_MAP
   5091  */
   5092     SOC_IF_ERROR_RETURN(soc_td2p_repl_port_agg_map_init(unit, port));
   5093 
   5094     return SOC_E_NONE;
   5095 }
   5096 /*
   5097 * Function:
   5098 *     soc_trident2p_num_cosq_init_port
   5099 * Purpose:
   5100 *     Assign the base queues and number of queues for the
   5101 *     specified port.  These are based upon MMU Port number to avoid
   5102 *     reallocation or running into other queues during post device init
   5103 *     port init.  This is modeled after soc_trident2_num_cosq_init
   5104 *     but only for individual ports.
   5105 * Parameters:
   5106 *     unit         - (IN) Unit number.
   5107 *     logical_port - (IN) logical port num
   5108 * Returns:
   5109 *     SOC_E_XXX
   5110 *
   5111 *
   5112 * cpu port (mmu port 0): 48 queues (2000-2047)
   5113 * loopback port (mmu port 116): 8 queues (4048-4055)
   5114 */
   5115 STATIC int
   5116 soc_trident2p_num_cosq_init_port(int unit, int logical_port)
   5117 {
   5118     soc_info_t *si;
   5119     int port, phy_port, mmu_port, mmu_port_offset, pipe;
   5120     int uc_cosq_base, mc_cosq_base, uc_cosq_per_port;
   5121     int apply = 0;
   5122 
   5123     si = &SOC_INFO(unit);
   5124 /*
   5125     if (soc_feature(unit, soc_feature_cmic_reserved_queues)) {
   5126         si->port_num_cosq[CMIC_PORT(unit)] = 44;
   5127     } else {
   5128         si->port_num_cosq[CMIC_PORT(unit)] = 48;
   5129     }
   5130     si->port_cosq_base[CMIC_PORT(unit)] = 520; */
   5131 /*
   5132     si->port_num_cosq[LB_PORT(unit)] = 9;
   5133     si->port_cosq_base[LB_PORT(unit)] = 1088;*/
   5134 
   5135     for (pipe = 0; pipe < _TD2_PIPES_PER_DEV; pipe++) {
   5136         if (pipe) { /* Y-pipe */
   5137             uc_cosq_base = 1480;
   5138             mc_cosq_base = 568;
   5139         } else { /* X-pipe */
   5140             uc_cosq_base = 0;
   5141             mc_cosq_base = 0;
   5142         }
   5143         for (mmu_port_offset = 0; mmu_port_offset < _TD2_MMU_PORTS_PER_PIPE;
   5144              mmu_port_offset++) {
   5145             mmu_port = si->mmu_port_base[pipe] + mmu_port_offset;
   5146             phy_port = si->port_m2p_mapping[mmu_port];
   5147             if (phy_port == -1) {
   5148                 continue;
   5149             }
   5150             port = si->port_p2l_mapping[phy_port];
   5151 
   5152             if(port == logical_port) {
   5153                 apply = 1;
   5154             }
   5155 
   5156             if (IS_CPU_PORT(unit, port) || IS_LB_PORT(unit, port)) {
   5157                 continue;
   5158             }
   5159 
   5160             if (SOC_PBMP_MEMBER(si->eq_pbm, port)) { /* VBS (HSP) port */
   5161                 if(apply == 1) {
   5162                     si->port_num_cosq[port] = 10;
   5163                     si->port_cosq_base[port] = mc_cosq_base + (mmu_port_offset * si->port_num_cosq[port]);
   5164                     si->port_num_uc_cosq[port] = 10;
   5165                     /* Made port_uc_cosq_base a function of mmu_port number
   5166                      * rather than a running number (as calculated by
   5167                      * uc_cosq_base before). If it is a running number, &
   5168                      * the port numbers come & go dynamically (as in flex port)
   5169                      * uc_cosq_base overlap. With port_uc_cosq_base a function
   5170                      * of mmu_port, each port has a fixed offset
   5171  */
   5172                     si->port_uc_cosq_base[port] = uc_cosq_base + (mmu_port_offset * 10);
   5173                 }
   5174             } else {
   5175                 uc_cosq_per_port =
   5176                     soc_property_port_get(unit, port, spn_LLS_NUM_L2UC, 10);
   5177                 if (uc_cosq_per_port < 10 || uc_cosq_per_port > 16) {
   5178                     uc_cosq_per_port = 10;
   5179                 }
   5180                 uc_cosq_per_port = (uc_cosq_per_port + 3) & ~3;
   5181 
   5182                 if (apply == 1) {
   5183                     si->port_num_cosq[port] = 10;
   5184                     si->port_cosq_base[port] = mc_cosq_base + (mmu_port_offset * si->port_num_cosq[port]);
   5185                     si->port_num_uc_cosq[port] = uc_cosq_per_port;
   5186                 }
   5187                 /* uc_cosq_base for LLS port must be
   5188                  * divisible by 4 for PFC to work */
   5189                 uc_cosq_base = (uc_cosq_base + 3) & (~3);
   5190 
   5191                 if (apply == 1) {
   5192                     /* Made port_uc_cosq_base a function of mmu_port number
   5193                      * rather than a running number (as calculated by
   5194                      * uc_cosq_base before). If it is a running number, &
   5195                      * the port numbers come & go dynamically (as in flex port)
   5196                      * uc_cosq_base overlap. With port_uc_cosq_base a function
   5197                      * of mmu_port, each port has a fixed offset
   5198  */
   5199                     si->port_uc_cosq_base[port] = uc_cosq_base + (mmu_port_offset * uc_cosq_per_port);
   5200 
   5201                     return SOC_E_NONE;
   5202                 }
   5203             }
   5204         }
   5205     }
   5206 
   5207     return SOC_E_NONE;
   5208 }
   5209 
   5210 /*
   5211  * Function:
   5212  * soc_td2p_hsp_sched_global_config_set
   5213  * Purpose:
   5214  * Set HSP_SCHED_GLOBAL_CONFIG for the given port
   5215  * Parameters:
   5216  * unit     - (IN) Unit number.
   5217  * port     - (IN) Logical SOC port number.
   5218  * Returns:
   5219  * SOC_E_XXX
   5220  */
   5221 STATIC int soc_td2p_hsp_sched_global_config_set(int unit, soc_port_t port)
   5222 {
   5223     uint32 rval, fval;
   5224     uint32 field;
   5225     int mmu_port, pipe;
   5226     int hsp_port_index;
   5227 
   5228     /* Only set this register for the port if the port is HSP */
   5229     if(_soc_trident2_port_sched_type_get(unit, port)
   5230                 != SOC_TD2_SCHED_HSP) {
   5231         return SOC_E_NONE;
   5232     }
   5233 
   5234     rval = fval = 0;
   5235 
   5236     SOC_IF_ERROR_RETURN(
   5237             soc_td2_port_common_attributes_get(unit, port, &pipe, &mmu_port, NULL));
   5238 
   5239     field = pipe ? IS_HSP_PORT_IN_YPIPEf : IS_HSP_PORT_IN_XPIPEf;
   5240     SOC_IF_ERROR_RETURN(READ_HSP_SCHED_GLOBAL_CONFIGr(unit, &rval));
   5241     fval = soc_reg_field_get(unit, HSP_SCHED_GLOBAL_CONFIGr, rval, field);
   5242     hsp_port_index = mmu_port - pipe * _TD2_PORTS_PER_PIPE;
   5243     fval |= (1 << hsp_port_index);
   5244     soc_reg_field_set(unit, HSP_SCHED_GLOBAL_CONFIGr, &rval, field, fval);
   5245     SOC_IF_ERROR_RETURN(WRITE_HSP_SCHED_GLOBAL_CONFIGr(unit, rval));
   5246 
   5247     return SOC_E_NONE;
   5248 }
   5249 
   5250 /*
   5251 * Function:
   5252 * soc_td2p_hsp_sched_global_config_clear
   5253 * Purpose:
   5254 * Clear HSP_SCHED_GLOBAL_CONFIG for the given port
   5255 * Parameters:
   5256 * unit    - (IN) Unit number.
   5257 * port    - (IN) Logical SOC port number.
   5258 * Returns:
   5259 * SOC_E_XXX
   5260  */
   5261 STATIC int soc_td2p_hsp_sched_global_config_clear(int unit, soc_port_t port)
   5262 {
   5263     uint32 rval, fval;
   5264     uint32 field;
   5265     int mmu_port, pipe;
   5266     int hsp_port_index;
   5267 
   5268     rval = fval = 0;
   5269 
   5270     SOC_IF_ERROR_RETURN(
   5271             soc_td2_port_common_attributes_get(unit, port, &pipe, &mmu_port, NULL));
   5272 
   5273     field = pipe ? IS_HSP_PORT_IN_YPIPEf : IS_HSP_PORT_IN_XPIPEf;
   5274     SOC_IF_ERROR_RETURN(READ_HSP_SCHED_GLOBAL_CONFIGr(unit, &rval));
   5275     fval = soc_reg_field_get(unit, HSP_SCHED_GLOBAL_CONFIGr, rval, field);
   5276     hsp_port_index = mmu_port - pipe * _TD2_PORTS_PER_PIPE;
   5277     fval &= ~(1 << hsp_port_index);
   5278     soc_reg_field_set(unit, HSP_SCHED_GLOBAL_CONFIGr, &rval, field, fval);
   5279     SOC_IF_ERROR_RETURN(WRITE_HSP_SCHED_GLOBAL_CONFIGr(unit, rval));
   5280 
   5281     return SOC_E_NONE;
   5282 }
   5283 
   5284 /*
   5285 * Function:
   5286 * soc_td2p_mmu_port_resource_set
   5287 * Purpose:
   5288 * Reconfigure MMU for flexport operation
   5289 * Parameters:
   5290 * unit       - (IN) Unit number.
   5291 * port       - (IN) Logical SOC port number.
   5292 * speed      - (IN) port speed. 
   5293 * legacyFlex - (IN) Whether this is a legacy flex or new flex 
   5294 * Returns:
   5295 * SOC_E_XXX
   5296  */
   5297 int soc_td2p_mmu_port_resource_set(int unit, soc_port_t port, int speed, int legacyFlex)
   5298 {
   5299     int ets_mode = 0;
   5300     /* Flex port operation not allowed on CPU or loopback port
   5301  */
   5302      if (IS_CPU_PORT(unit, port) || IS_LB_PORT(unit, port)) {
   5303          return SOC_E_PARAM;
   5304      }
   5305 
   5306     /* Update the logical port and queue mappings in memory and registers */
   5307     if (td2p_ets_mode_cb) {
   5308         ets_mode = td2p_ets_mode_cb(unit, port);
   5309     }
   5310 
   5311     /* Alloc the bitmaps for L0, L1, L2 nodes for this port */
   5312     SOC_IF_ERROR_RETURN(soc_trident2_lls_bmap_alloc_port(unit, port, ets_mode));
   5313 
   5314     SOC_IF_ERROR_RETURN(soc_trident2p_num_cosq_init_port(unit, port));
   5315 
   5316     /* Configure all MMU registers for new ports whose setting is
   5317      * based on port speed.
   5318  */
   5319     SOC_IF_ERROR_RETURN(soc_trident2_port_speed_update(unit, port, speed));
   5320 
   5321     /* Program PORT_INITIAL_COPY_COUNT_WIDTH
   5322  */
   5323     SOC_IF_ERROR_RETURN(soc_td2p_port_icc_width_set(unit, port));
   5324     
   5325 
   5326     if (!ets_mode) {
   5327         /* Default Scheduling on the port.  The function
   5328          * below also sets HSP_SCHED_GLOBAL_CONFIG for high speed ports.
   5329          * This needs to be done regardless of if it's default or
   5330          * custom scheduling. Custom scheduling is handled below.
   5331  */
   5332         SOC_IF_ERROR_RETURN(soc_trident2_port_sched_set(unit, port));
   5333     } else {
   5334         /* Custom scheduling on the port.
   5335          * If the port is HSP, set HSP_SCHED_GLOBAL_CONFIG so the 
   5336          * device knows to use HSP scheduling for that port. The
   5337          * function below checks if the port is HSP internally.
   5338  */
   5339          SOC_IF_ERROR_RETURN(
   5340              soc_td2p_hsp_sched_global_config_set(unit, port));
   5341     }
   5342 
   5343     /* Reconfigure IPMC replication
   5344  */
   5345     SOC_IF_ERROR_RETURN(soc_td2p_ipmc_repl_init(unit, port));
   5346 
   5347     /* Reconfigure THDI, THDO settings
   5348  */
   5349     /* legacy flex has already set up these pg and queue settings for the port
   5350        on device init. Calling this will overwrite any settings with
   5351        default settings. */
   5352     if(legacyFlex == 0) {
   5353         SOC_IF_ERROR_RETURN(soc_td2p_mmu_config_init_port(unit, port));
   5354     }
   5355 
   5356     return SOC_E_NONE;
   5357 }
   5358 
   5359 /*
   5360 * Function:
   5361 * soc_td2p_mmu_port_resource_clear
   5362 * Purpose:
   5363 * Reconfigure MMU for flexport operation
   5364 * Parameters:
   5365 * unit    - (IN) Unit number.
   5366 * port    - (IN) Logical SOC port number.
   5367 * Returns:
   5368 * SOC_E_XXX
   5369  */
   5370 int soc_td2p_mmu_port_resource_clear(int unit, soc_port_t port)
   5371 {
   5372     int ets_mode = 0;
   5373     soc_trident2_sched_type_t sched_type;
   5374 
   5375     if (td2p_ets_mode_cb) {
   5376         ets_mode = td2p_ets_mode_cb(unit, port);
   5377     }
   5378 
   5379     sched_type = _soc_trident2_port_sched_type_get(unit, port);
   5380     if (sched_type == SOC_TD2_SCHED_HSP) {
   5381         SOC_IF_ERROR_RETURN(soc_td2p_hsp_sched_global_config_clear(unit, port));
   5382     }
   5383 
   5384     /* In ETS mode, SDK does not initialize or deletes the default LLS hierarchy */
   5385     if (!ets_mode) {
   5386         SOC_IF_ERROR_RETURN(soc_td2_lls_port_uninit(unit, port));
   5387     }
   5388     SOC_IF_ERROR_RETURN(soc_td2_lls_reset_port(unit, port));
   5389 
   5390     SOC_IF_ERROR_RETURN(soc_td2p_port_sched_hsp_set(unit, port, 0));
   5391     return SOC_E_NONE;
   5392 }
   5393 
   5394 /*
   5395 * Function:
   5396 *     soc_td2p_is_any_port_flex_enable
   5397 * Purpose:
   5398 *     Find out if
   5399 *     port_flex_enable=1 OR
   5400 *     port_flex_enable{physical port num}=1
   5401 *     config is present in config.bcm
   5402 * Parameters:
   5403 *     unit    - (IN) Unit number.
   5404 * Returns:
   5405 *     TRUE or FALSE
   5406 *     If such a config is present, this function
   5407 *     returns 1 - implying that flex is enable on
   5408 *     at least 1 port (port macro) in the system
   5409 *     This function returns 0, if flex is not enabled
   5410 *     on any port (port macro) in the system
   5411  */
   5412 int soc_td2p_is_any_port_flex_enable(int unit)
   5413 {
   5414     int phy_port, num_phy_port;
   5415 
   5416     num_phy_port = 130;
   5417 
   5418     for (phy_port = 0; phy_port < num_phy_port; phy_port++) {
   5419         if (soc_property_phys_port_get(unit,
   5420                                        phy_port,
   5421                                        spn_PORT_FLEX_ENABLE, 0)) {
   5422             return TRUE;
   5423         }
   5424     }
   5425 
   5426     return FALSE;
   5427 }
   5428 
   5429 /*
   5430 * Function:
   5431 *     soc_td2p_is_port_flex_enable
   5432 * Purpose:
   5433 *     Find out if port_flex_enable{physical port num} config
   5434 *     is present on the given physical port in config.bcm
   5435 * Parameters:
   5436 *     unit    - (IN) Unit number.
   5437 *     phy_port - (IN) physical port num
   5438 * Returns:
   5439 *     TRUE or FALSE
   5440  */
   5441 int soc_td2p_is_port_flex_enable(int unit, int phy_port)
   5442 {
   5443     int enable = 0;
   5444 
   5445     /* This property does not apply to cpu port &
   5446      * loopback port
   5447  */
   5448 
   5449     if (phy_port > 0 && phy_port < 129) {
   5450         enable = soc_property_phys_port_get(unit,
   5451                                             phy_port,
   5452                                             spn_PORT_FLEX_ENABLE, 0);
   5453     }
   5454 
   5455     return enable;
   5456 }
   5457 
   5458 /*
   5459 * Function:
   5460 *     soc_td2p_set_flexport_port_q_callback
   5461 * Purpose:
   5462 *     Register a callback for the bcm layer so that the soc layer can call it
   5463 *     to update logical port and queue associations
   5464 * Parameters:
   5465 *     unit    - (IN) Unit number.
   5466 *     cb      - (IN) Function callback
   5467 * Returns:
   5468 *     SOC_E_XXX
   5469  */
   5470 int soc_td2p_set_flexport_port_q_callback(int unit, 
   5471                                           _soc_td2p_flexport_port_q_cb cb)
   5472 {
   5473    td2p_flexport_cb = cb;
   5474    return SOC_E_NONE;
   5475 }
   5476 
   5477 /*
   5478 * Function:
   5479 *     soc_td2p_set_ets_mode_q_callback
   5480 * Purpose:
   5481 *     Register a callback for the bcm layer so that the soc layer can call it
   5482 *     and check if ets mode is enabled or not
   5483 * Parameters:
   5484 *     unit    - (IN) Unit number.
   5485 *     cb      - (IN) Function callback
   5486 * Returns:
   5487 *     SOC_E_XXX
   5488  */
   5489 int soc_td2p_set_ets_mode_q_callback(int unit, 
   5490                                           _soc_td2p_ets_mode_q_cb cb)
   5491 {
   5492    td2p_ets_mode_cb = cb;
   5493    return SOC_E_NONE;
   5494 }
   5495 
   5496 /*
   5497  * Function:
   5498  *      soc_td2p_port_mode_get
   5499  * Description:
   5500  *      Get port mode by giving first logical port of TSC4
   5501  * Parameters:
   5502  *      unit          - Device number
   5503  *      port          - Logical port
   5504  *      int*          - Port Mode
   5505  *
   5506  * Each TSC4 can be configured into following 5 mode:
   5507  *   Lane number    0    1    2    3
   5508  *   ------------  ---  ---  ---  ---
   5509  *      quad port  10G  10G  10G  10G
   5510  *   tri_012 port  10G  10G  20G   x
   5511  *   tri_023 port  20G   x   10G  10G
   5512  *      dual port  20G   x   20G   x
   5513  *    single port  40G   x    x    x
   5514  */
   5515 int
   5516 soc_td2p_port_mode_get(int unit, int logical_port, int *mode)
   5517 {
   5518     soc_info_t *si;
   5519     int lane;
   5520     int port, first_phyport, phy_port;
   5521     int num_lanes[_TD2_PORTS_PER_XLP];
   5522 
   5523     si = &SOC_INFO(unit);
   5524     first_phyport = si->port_l2p_mapping[logical_port];
   5525 
   5526     for (lane = 0; lane < _TD2_PORTS_PER_XLP; lane++) {
   5527         phy_port = first_phyport + lane;
   5528         port = si->port_p2l_mapping[phy_port];
   5529         if (port == -1 || SOC_PBMP_MEMBER(si->all.disabled_bitmap, port)) {
   5530             num_lanes[lane] = -1;
   5531         } else {
   5532             num_lanes[lane] = si->port_num_lanes[port];
   5533         }
   5534     }
   5535 
   5536     if (num_lanes[0] == 4) {
   5537         *mode = SOC_TD2_PORT_MODE_QUAD;
   5538     } else if (num_lanes[0] == 2 && num_lanes[2] == 2) {
   5539         *mode = SOC_TD2_PORT_MODE_DUAL;
   5540     } else if (num_lanes[0] == 2 && num_lanes[2] == 1 && num_lanes[3] == 1) {
   5541         *mode = SOC_TD2_PORT_MODE_TRI_023;
   5542     } else if (num_lanes[0] == 1 && num_lanes[1] == 1 && num_lanes[2] == 2) {
   5543         *mode = SOC_TD2_PORT_MODE_TRI_012;
   5544     } else {
   5545         *mode = SOC_TD2_PORT_MODE_SINGLE;
   5546     }
   5547 
   5548     return SOC_E_NONE;
   5549 }
   5550 
   5551 /*
   5552 * Function:
   5553 *     soc_td2p_mcq_entries_rsvd_port
   5554 * Purpose:
   5555 *     For a given port, soc_td2p_mcq_entries_rsvd_port calculates
   5556 *     the number of MC q entries (Reserved Egress Queue Entries).
   5557 *     This function only gives MC q entries for
   5558 *     for flex disabled ports.
   5559 *     For flex enabled port macros, this function is not used.
   5560 * Parameters:
   5561 *     unit    - (IN) Unit number.
   5562 *     port    - (IN) logical port num
   5563 * Returns:
   5564 *     Reserved Egress Queue Entries for a given port
   5565  */
   5566 int soc_td2p_mcq_entries_rsvd_port(int unit, int port)
   5567 {
   5568     int port_num_cosq;
   5569     soc_info_t *si;
   5570     int mcq_entry = 0;
   5571 
   5572     si = &SOC_INFO(unit);
   5573     port_num_cosq = si->port_num_cosq[port];
   5574 
   5575     if (IS_LB_PORT(unit, port)) {
   5576         /* Loopback port has 9 queues (including QCN)
   5577          * For calculation of Egress queue entries,
   5578          * loopback port is considered having 8 queues
   5579          * (Why? :- ask Architecture)
   5580  */
   5581         port_num_cosq = si->port_num_cosq[port] - 1;
   5582     }
   5583 
   5584     mcq_entry = port_num_cosq * _TD2P_MMU_PER_COSQ_EGRESS_QENTRY_RSVD;
   5585     return mcq_entry;
   5586 }
   5587 
   5588 /*
   5589 * Function:
   5590 *     soc_td2p_egr_buf_rsvd_port
   5591 * Purpose:
   5592 *     For Cpu port or loopback port,
   5593 *     soc_td2p_egr_buf_rsvd_port calculates
   5594 *     the reserved queue min/guarantee. 
   5595 *     This function only gives cumulative (for all queues)
   5596 *     queue guarantee for CPU port or Loopback port.
   5597 * Parameters:
   5598 *     unit    - (IN) Unit number.
   5599 *     port    - (IN) logical port num for CPU port or LB port
   5600 * Returns:
   5601 *     Reserved Cumulative (total for all queues) Queue Min/Guarantee value
   5602  */
   5603 int soc_td2p_egr_buf_rsvd_port(int unit, int port, int default_mtu_cells)
   5604 {
   5605     int port_num_cosq;
   5606     soc_info_t *si;
   5607     int egr_rsvd = 0;
   5608     int min_cell_per_mcq;
   5609 
   5610     if (!IS_CPU_PORT(unit, port) && !IS_LB_PORT(unit, port)) {
   5611         return 0;
   5612     }
   5613 
   5614     si = &SOC_INFO(unit);
   5615 
   5616     port_num_cosq = si->port_num_cosq[port];
   5617 
   5618     if (IS_LB_PORT(unit, port)) {
   5619         /* Loopback port has 9 queues (including QCN)
   5620          * For calculation of Egress queue entries,
   5621          * loopback port is considered having 8 queues
   5622          * (Why? :- ask Architecture)
   5623  */
   5624         port_num_cosq = si->port_num_cosq[port] - 1;
   5625     }
   5626 
   5627     if (soc_feature(unit, soc_feature_min_cell_per_queue)) {
   5628         min_cell_per_mcq = _soc_td2_min_cell_rsvd_per_mcq(unit, port, default_mtu_cells);
   5629     } else {
   5630         min_cell_per_mcq = default_mtu_cells;
   5631     }
   5632 
   5633     egr_rsvd = port_num_cosq * min_cell_per_mcq;
   5634     return egr_rsvd;
   5635 }
   5636 
   5637 /*
   5638  * Function:
   5639  *      _soc_td2p_lb_port_flush
   5640  * Purpose:
   5641  *      Poll until LB port gets back all the credits from EP
   5642  * Parameters:
   5643  *      unit           - (IN) Unit number.
   5644  * Returns:
   5645  *      SOC_E_XXX
   5646  */
   5647 STATIC int
   5648 _soc_td2p_lb_port_flush(int unit)
   5649 {
   5650 #define MMU_LB_PORT_BOOT_TIME_CREDITS 36
   5651 
   5652     soc_info_t *si = &SOC_INFO(unit);
   5653     soc_timeout_t to;
   5654     int lb_port_credits;
   5655     uint32 lbval;
   5656     int mmu_lb_port;
   5657 
   5658     mmu_lb_port = si->port_p2m_mapping[si->port_l2p_mapping[si->lb_port]];
   5659     /* Adjust for pipe */
   5660     mmu_lb_port = mmu_lb_port &0x3f;
   5661 
   5662     soc_timeout_init(&to, 250000, 0);
   5663 
   5664     /* Poll until EDB buffer is empty */
   5665     for (;;) {
   5666         SOC_IF_ERROR_RETURN
   5667             (READ_ES_PIPE1_MMU_PORT_CURRENT_CREDITr(unit, mmu_lb_port, &lbval));
   5668         lb_port_credits = soc_reg_field_get(unit, ES_PIPE1_MMU_PORT_CURRENT_CREDITr,
   5669                 lbval, CREDITf);
   5670         if (lb_port_credits >= MMU_LB_PORT_BOOT_TIME_CREDITS) {
   5671             break;
   5672         }
   5673         if (soc_timeout_check(&to)) {
   5674             LOG_ERROR(BSL_LS_SOC_COMMON,
   5675                     (BSL_META_U(unit,
   5676                                 "EDB buffer drain timeout: "
   5677                                 "port %d, %s, "
   5678                                 "timeout port %d credit %d\n"),
   5679                      unit, SOC_PORT_NAME(unit, si->lb_port), mmu_lb_port, lb_port_credits));
   5680             return SOC_E_INTERNAL;
   5681         }
   5682     }
   5683 
   5684     return SOC_E_NONE;
   5685 }
   5686 
   5687 #define _TD2P_XPIPE (0)
   5688 #define _TD2P_YPIPE (1)
   5689 /*
   5690  * Function:
   5691  *      _soc_td2p_tdm_cpulb_port_indices_get
   5692  * Purpose:
   5693  *      This function finds & returns the slot number (location of) 
   5694  *      loopback port in the active TDM calendar
   5695  * Parameters:
   5696  *      unit           - (IN) Unit number.
   5697  *      pipe           - (IN) pipe number. 0 - xpipe, 1 - ypipe.
   5698  *      table_num      - (IN) Active TDM Table number - 0 or 1
   5699  *      slot_len       - (IN) Current length of the Active TDM table
   5700  *      *arr           - (OUT) contains location (slot num) of lb port in TDM Cal
   5701  *      count          - (OUT) number(count) of locations of LB port in TDM Cal
   5702  *                             - valid number of entries in *arr
   5703  * Returns:
   5704  *      SOC_E_XXX
   5705  * Note:
   5706  *     This function assumes that the output array (arr) being passed
   5707  *     is initialized & has sufficient memory (_MMU_TDM_LENGTH) to store all possible
   5708  *     locations of loopback port in the TDM Calendar. In short,
   5709  *     before calling this function, please allocate the memory
   5710  *     (uint32 * _MMU_TDM_LENGTH) for arr
   5711  */
   5712 STATIC int
   5713 _soc_td2p_tdm_cpulb_port_indices_get(int unit, int pipe, int table_num,
   5714                                   int slot_len, uint32 *arr, uint32 *count)
   5715 {
   5716     static const soc_mem_t mmu_tdm_mems[2][2] = {
   5717         {ES_PIPE0_TDM_TABLE_0m, ES_PIPE0_TDM_TABLE_1m},
   5718         {ES_PIPE1_TDM_TABLE_0m, ES_PIPE1_TDM_TABLE_1m}
   5719     };
   5720     static const soc_mem_t mmu_tdm_fields[2] = {
   5721         PORT_NUM_EVENf, PORT_NUM_ODDf};
   5722 
   5723     soc_info_t *si;
   5724     uint32 entry[SOC_MAX_MEM_WORDS];
   5725     soc_field_t field;
   5726     soc_mem_t mem;
   5727     uint32 fval;
   5728     int phy_port, log_port, mmu_port;
   5729     int slot, index;
   5730     int temp_count;
   5731 
   5732     si = &SOC_INFO(unit);
   5733 
   5734     if (!arr || !count) {
   5735         return SOC_E_NONE;
   5736     }
   5737     if ((pipe != _TD2P_XPIPE) && (pipe != _TD2P_YPIPE)) {
   5738         return SOC_E_PARAM;
   5739     }
   5740 
   5741     temp_count = 0;
   5742     mem = mmu_tdm_mems[pipe][table_num];
   5743     LOG_VERBOSE(BSL_LS_SOC_MMU,
   5744             (BSL_META_U(unit,
   5745                         "Cal GET Pipe %d table_num %d slot_len %d mem %d \n"),
   5746              pipe, table_num, slot_len, mem));
   5747 
   5748     for (slot = 0; slot < slot_len; slot += 2) {
   5749         SOC_IF_ERROR_RETURN
   5750             (soc_mem_read(unit, mem, MEM_BLOCK_ALL, slot / 2, entry));
   5751         for (index = 0; index < 2; index++) {
   5752             if (slot + index >= slot_len){
   5753                 break;
   5754             }
   5755             field = mmu_tdm_fields[index];
   5756             fval = soc_mem_field32_get(unit, mem, entry, field);
   5757             mmu_port = fval + si->mmu_port_base[pipe];
   5758             phy_port = si->port_m2p_mapping[mmu_port];
   5759             if (phy_port != -1) {
   5760                 log_port = si->port_p2l_mapping[phy_port];
   5761                 if (((pipe == _TD2P_XPIPE) && IS_CPU_PORT(unit, log_port)) ||
   5762                     ((pipe == _TD2P_YPIPE) && IS_LB_PORT(unit, log_port))) {
   5763                     LOG_VERBOSE(BSL_LS_SOC_MMU,
   5764                             (BSL_META_U(unit,
   5765                                         "Pipe %d TDM Calendar %d slot %d"
   5766                                         " mmu %d phy %d log %d fval 0x%x\n"),
   5767                              pipe, table_num,
   5768                              slot+index,
   5769                              mmu_port,
   5770                              phy_port, log_port, fval));
   5771                     arr[temp_count] = slot+index;
   5772                     temp_count++;
   5773                 }
   5774             }
   5775         }
   5776     }
   5777     *count = temp_count;
   5778 
   5779     return SOC_E_NONE;
   5780 }
   5781 
   5782 /*
   5783  * Function:
   5784  *      _soc_td2p_tdm_cpulb_port_indices_set
   5785  * Purpose:
   5786  *      This function sets the given slot number (locations)
   5787  *      in active TDM calendar with the value passed in the arguments.
   5788  * Parameters:
   5789  *      unit           - (IN) Unit number.
   5790  *      pipe           - (IN) pipe number. 0 - xpipe, 1 - ypipe.
   5791  *      table_num      - (IN) Active TDM Table number - 0 or 1
   5792  *      slot_len       - (IN) Current length of the Active TDM table
   5793  *      *arr           - (IN) contains location (slot num) of TDM Cal
   5794  *      count          - (IN) number(count) of valid locations of TDM Cal
   5795  *                             - valid number of entries in *arr
   5796  *      value          - (IN) value to be set
   5797  * Returns:
   5798  *      SOC_E_XXX
   5799  */
   5800 STATIC int
   5801 _soc_td2p_tdm_cpulb_port_indices_set(int unit, int pipe, int table_num, int slot_len,
   5802                                   uint32 *arr, uint32 count, int value)
   5803 {
   5804 
   5805     static const soc_mem_t mmu_tdm_mems[2][2] = {
   5806         {ES_PIPE0_TDM_TABLE_0m, ES_PIPE0_TDM_TABLE_1m},
   5807         {ES_PIPE1_TDM_TABLE_0m, ES_PIPE1_TDM_TABLE_1m}
   5808     };
   5809     static const soc_mem_t mmu_tdm_fields[2] ={
   5810         PORT_NUM_EVENf, PORT_NUM_ODDf
   5811     };
   5812 
   5813     int i, offset;
   5814     uint32 entry[SOC_MAX_MEM_WORDS];
   5815     soc_field_t field;
   5816     soc_mem_t mem;
   5817     int slot, index;
   5818 
   5819     if (!arr) {
   5820         return SOC_E_NONE;
   5821     }
   5822     if ((pipe != _TD2P_XPIPE) && (pipe != _TD2P_YPIPE)) {
   5823         return SOC_E_PARAM;
   5824     }
   5825 
   5826     mem = mmu_tdm_mems[pipe][table_num];
   5827     LOG_VERBOSE(BSL_LS_SOC_MMU,
   5828             (BSL_META_U(unit,
   5829                         "Cal SET Pipe %d table_num %d slot_len %d mem %d \n"),
   5830              pipe, table_num, slot_len, mem));
   5831 
   5832     for (i = 0; i < count; i++) {
   5833         if (arr[i] >= slot_len){
   5834             break;
   5835         }
   5836         index = arr[i];
   5837         offset = index % 2;
   5838         slot = index - offset;
   5839         LOG_VERBOSE(BSL_LS_SOC_MMU,
   5840                 (BSL_META_U(unit,
   5841                             "Writing TDM Cal %d slot %d value 0x%x\n"),
   5842                  table_num, slot+offset, value));
   5843         SOC_IF_ERROR_RETURN
   5844             (soc_mem_read(unit, mem, MEM_BLOCK_ALL, slot/2, entry));
   5845         field = mmu_tdm_fields[offset];
   5846         soc_mem_field32_set(unit, mem, entry, field, value);
   5847         SOC_IF_ERROR_RETURN
   5848             (soc_mem_write(unit, mem, MEM_BLOCK_ALL, slot / 2, entry));
   5849     }
   5850 
   5851     return SOC_E_NONE;
   5852 }
   5853 
   5854 /*
   5855  * Function:
   5856  *      _soc_td2p_mmu_map_phy_port_to_cpulb
   5857  * Purpose:
   5858  *      This function temporarily maps old physical port to
   5859  *      CPU/loopback port in the mmu port mapping registers
   5860  * Parameters:
   5861  *      unit           - (IN) Unit number.
   5862  *      pipe           - (IN) Pipe number.
   5863  *      count          - (IN) Number of ports to map.
   5864  *      pport          - (IN) Physical port number list.
   5865  * Returns:
   5866  *      SOC_E_XXX
   5867  */
   5868 STATIC int
   5869 _soc_td2p_mmu_map_phy_port_to_cpulb(int unit, int pipe,
   5870                                  int count, int *pport)
   5871 {
   5872     int i;
   5873     uint32 rval;
   5874     int old_phy_port;
   5875     int cpulb_port;
   5876     soc_info_t *si = &SOC_INFO(unit);
   5877 
   5878     cpulb_port = (pipe == _TD2P_XPIPE)? si->cmic_port : si->lb_port;
   5879     for (i = 0; i < count; i++) {
   5880         LOG_VERBOSE(BSL_LS_SOC_MMU,
   5881                 (BSL_META_U(unit,
   5882                             "MMU RQE Phy port remapping "
   5883                             "old physical_port=%d\n"),
   5884                             pport[i]));
   5885 
   5886         /* MMU_PORT_TO_PHY_PORT_MAPPING [MMU CPU/LB port number]
   5887          * = old physical port number
   5888  */
   5889         old_phy_port = pport[i];
   5890 
   5891         rval = 0;
   5892         soc_reg_field_set(unit, MMU_PORT_TO_PHY_PORT_MAPPINGr, &rval,
   5893                 PHY_PORTf, old_phy_port);
   5894         SOC_IF_ERROR_RETURN
   5895             (soc_reg32_set(unit, MMU_PORT_TO_PHY_PORT_MAPPINGr,
   5896                            cpulb_port, 0, rval));
   5897 
   5898     }
   5899 
   5900     /* MMU_PORT_TO_PHY_PORT_MAPPING [MMU CPU/LB port number]
   5901      * = physical CPU/LB port number */
   5902     rval = 0;
   5903     soc_reg_field_set(unit, MMU_PORT_TO_PHY_PORT_MAPPINGr, &rval,
   5904             PHY_PORTf, si->port_l2p_mapping[cpulb_port]);
   5905     SOC_IF_ERROR_RETURN
   5906         (soc_reg32_set(unit, MMU_PORT_TO_PHY_PORT_MAPPINGr,
   5907                        cpulb_port, 0, rval));
   5908 
   5909     return SOC_E_NONE;
   5910 }
   5911 
   5912 /*
   5913  * Function:
   5914  *      soc_td2p_mmu_rqe_phy_port_mapping_update
   5915  * Purpose:
   5916  *      This function maps the old physical ports
   5917  *      temporarily to the CPU/Loopback port
   5918  * Parameters:
   5919  *      unit           - (IN) Unit number.
   5920  *      pipe           - (IN) pipe number of the ports. 0 - xpipe, 1 - ypipe.
   5921  *      count          - (IN) number of ports.
   5922  *      phy_port       - (IN) list of physical port number.
   5923  * Returns:
   5924  *      SOC_E_XXX
   5925  * Note:
   5926  *      - Ports in the list should be in the same pipe.
   5927  *      - The goal of this function is to minimize the time CPU/loopback port
   5928  *        is down. Hence, minimal operations are done between
   5929  *        Turning off Opportunistic Scheduling for the CPU/Loopback port
   5930  *        and
   5931  *        Turning ON Opportunistic Scheduling for the CPU/Loopback port
   5932  */
   5933 STATIC int
   5934 soc_td2p_mmu_rqe_phy_port_mapping_update(int unit, int pipe,
   5935                                          int count, int *phy_port)
   5936 {
   5937     static const soc_reg_t mmu_tdm_regs[2] = {
   5938         ES_PIPE0_TDM_CONFIGr, ES_PIPE1_TDM_CONFIGr};
   5939     static const soc_mem_t cal_end_field[2] = {
   5940         CAL0_ENDf, CAL1_ENDf };
   5941     static const soc_mem_t cal_end_single_field[2] = {
   5942         CAL0_END_SINGLEf, CAL1_END_SINGLEf};
   5943     soc_reg_t mmu_tdm_reg;
   5944     uint32 cpulb_port_tdm_indices[_MMU_TDM_LENGTH];
   5945     uint32 mmu_tdm_reg_rval;
   5946     soc_info_t *si;
   5947     uint32 cnt = 0;
   5948     int cpulb_lport;
   5949     int mmu_cpulb_port;
   5950     int table_num;
   5951     int slot_len;
   5952 
   5953 
   5954     LOG_VERBOSE(BSL_LS_SOC_MMU,
   5955             (BSL_META_U(unit,
   5956                         "Start MMU RQE phy port remapping\n")));
   5957 
   5958     if ((pipe != _TD2P_XPIPE) && (pipe != _TD2P_YPIPE)) {
   5959         return SOC_E_PARAM;
   5960     }
   5961     /* Get all the fields here from Pipe TDM CONFIG
   5962      * to avoid SBUS access in every
   5963      * subsequent function to essentially
   5964      * get the same information */
   5965     mmu_tdm_reg = mmu_tdm_regs[pipe];
   5966     mmu_tdm_reg_rval = 0;
   5967     SOC_IF_ERROR_RETURN(
   5968             soc_reg32_get(unit, mmu_tdm_reg, REG_PORT_ANY, 0, &mmu_tdm_reg_rval));
   5969     table_num = soc_reg_field_get(
   5970                 unit, mmu_tdm_reg, mmu_tdm_reg_rval, CURR_CALf);
   5971     slot_len = (soc_reg_field_get(
   5972                 unit, mmu_tdm_reg,
   5973                 mmu_tdm_reg_rval, cal_end_field[table_num]) + 1) * 2;
   5974     slot_len -= soc_reg_field_get(
   5975                 unit, mmu_tdm_reg,
   5976                 mmu_tdm_reg_rval, cal_end_single_field[table_num]);
   5977 
   5978     si = &SOC_INFO(unit);
   5979     cpulb_lport = (pipe == _TD2P_XPIPE)? si->cmic_port : si->lb_port;
   5980     mmu_cpulb_port = si->port_p2m_mapping[si->port_l2p_mapping[cpulb_lport]];
   5981     /* Adjust for pipe */
   5982     mmu_cpulb_port = mmu_cpulb_port &0x3f;
   5983 
   5984     /* Get the location of (slot numbers) CPU/loopback port in the active TDM calendar */
   5985     SOC_IF_ERROR_RETURN(
   5986             _soc_td2p_tdm_cpulb_port_indices_get(unit, pipe, table_num,
   5987                 slot_len, cpulb_port_tdm_indices,
   5988                 &cnt));
   5989 
   5990     /* Turn off Opportunistic Scheduling for the CPU/Loopback port */
   5991     soc_reg_field_set(unit, mmu_tdm_reg, &mmu_tdm_reg_rval, OPP_CPULB_ENf, 0);
   5992     SOC_IF_ERROR_RETURN(
   5993             soc_reg32_set(unit, mmu_tdm_reg,
   5994                           REG_PORT_ANY, 0, mmu_tdm_reg_rval));
   5995 
   5996     LOG_VERBOSE(BSL_LS_SOC_MMU,
   5997             (BSL_META_U(unit,
   5998                         "Writing 0x3f to CPU/LB port locations\n")));
   5999 
   6000     /* Write to the active TDM calendar table,
   6001      * changing all instances of the CPU/LB port to 0x3f */
   6002     SOC_IF_ERROR_RETURN(
   6003             _soc_td2p_tdm_cpulb_port_indices_set(unit, pipe, table_num, slot_len,
   6004                 cpulb_port_tdm_indices, cnt, 0x3f));
   6005 
   6006     if (pipe == _TD2P_XPIPE) {
   6007         /* Stop EDB drain to the CMIC */
   6008         (void) WRITE_CMIC_RXBUF_BLOCK_DATABUF_ALLOCr(unit, 1);
   6009     } else {
   6010         /* Waiting for LB port to be empty */
   6011         SOC_IF_ERROR_RETURN(
   6012                 _soc_td2p_lb_port_flush(unit));
   6013     }
   6014 
   6015     /* Temporarily map each old physical port number to the CPU/Loopback Port MMU port */
   6016     SOC_IF_ERROR_RETURN(
   6017             _soc_td2p_mmu_map_phy_port_to_cpulb(unit, pipe, count, phy_port));
   6018 
   6019     if (pipe == _TD2P_XPIPE) {
   6020         /* Resume EDB drain to the CMIC */
   6021         (void) WRITE_CMIC_RXBUF_BLOCK_DATABUF_ALLOCr(unit, 0);
   6022     }
   6023 
   6024     LOG_VERBOSE(BSL_LS_SOC_MMU,
   6025             (BSL_META_U(unit,
   6026                         "Restoring TDM Cal to original\n\n")));
   6027     /* Write to the active TDM calendar table,
   6028      * changing all instances of the LB port to mmu port for LB port */
   6029     SOC_IF_ERROR_RETURN(
   6030             _soc_td2p_tdm_cpulb_port_indices_set(unit, pipe, table_num, slot_len,
   6031                 cpulb_port_tdm_indices, cnt, mmu_cpulb_port));
   6032 
   6033 
   6034     /* Turn ON Opportunistic Scheduling for the Loopback port */
   6035     soc_reg_field_set(unit, mmu_tdm_reg, &mmu_tdm_reg_rval, OPP_CPULB_ENf, 1);
   6036     SOC_IF_ERROR_RETURN(
   6037             soc_reg32_set(unit,
   6038                           mmu_tdm_reg, REG_PORT_ANY, 0, mmu_tdm_reg_rval));
   6039 
   6040 
   6041     LOG_VERBOSE(BSL_LS_SOC_MMU,
   6042             (BSL_META_U(unit,
   6043                         "End MMU RQE phy port remapping\n")));
   6044 
   6045     return SOC_E_NONE;
   6046 }
   6047 
   6048 /*
   6049  * Function:
   6050  *      soc_td2p_mmu_rqe_phy_port_mapping_set
   6051  * Purpose:
   6052  *      This function maps the old physical ports
   6053  *      (that are either being deleted or remapped
   6054  *      in the flexport sequence)
   6055  *      temporarily to the CPU/Loopback port
   6056  * Parameters:
   6057  *      unit           - (IN) Unit number.
   6058  *      pre_count      - (IN) Array size for pre-FlexPort array.
   6059  *      pre_resource   - (IN) Pre-FlexPort configuration array.
   6060  * Returns:
   6061  *      SOC_E_XXX
   6062  * Note:
   6063  *      - Assumes all data is Port Resource arrays has been validated.
   6064  *      - The goal of this function is to minimize the time loopback port
   6065  *        is down. Hence, minimal operations are done between
   6066  *        Turning off Opportunistic Scheduling for the CPU/Loopback port
   6067  *        and
   6068  *        Turning ON Opportunistic Scheduling for the CPU/Loopback port
   6069  */
   6070 int
   6071 soc_td2p_mmu_rqe_phy_port_mapping_set(int unit,
   6072                                   int pre_count,
   6073                                   soc_port_resource_t *pre_resource)
   6074 {
   6075     int *pport;
   6076     int i, px_cnt = 0, py_cnt = 0;
   6077     soc_port_resource_t *pr;
   6078     int rv = SOC_E_NONE;
   6079 
   6080     LOG_VERBOSE(BSL_LS_SOC_MMU,
   6081             (BSL_META_U(unit,
   6082                         "Start MMU RQE phy port remapping\n")));
   6083     if (pre_count <= 0) {
   6084         return SOC_E_NONE;
   6085     }
   6086     /* sort pre_resource based on port pipe. */
   6087     pport = sal_alloc(pre_count * sizeof(int), "phy port list");
   6088     if (!pport) {
   6089         return SOC_E_MEMORY;
   6090     }
   6091     for (i = 0, pr = &pre_resource[0]; i < pre_count; i++, pr++) {
   6092         if (pr->physical_port > _TD2_PORTS_PER_PIPE) {
   6093             py_cnt++;
   6094             pport[pre_count - py_cnt] = pr->physical_port;
   6095         } else {
   6096             pport[px_cnt] = pr->physical_port;
   6097             px_cnt++;
   6098         }
   6099     }
   6100 
   6101     /* Do remapping for ports in x-pipe and y-pipe respectively. */
   6102     if (px_cnt > 0) {
   6103         rv = soc_td2p_mmu_rqe_phy_port_mapping_update(unit, _TD2P_XPIPE,
   6104                                                      px_cnt, pport);
   6105     }
   6106     if (SOC_FAILURE(rv)) {
   6107         goto cleanup;
   6108     }
   6109 
   6110     if (py_cnt > 0) {
   6111         rv = soc_td2p_mmu_rqe_phy_port_mapping_update(unit, _TD2P_YPIPE,
   6112                                                      py_cnt, pport + px_cnt);
   6113     }
   6114 
   6115 cleanup:
   6116     sal_free(pport);
   6117 
   6118     if (SOC_FAILURE(rv)) {
   6119         LOG_VERBOSE(BSL_LS_SOC_MMU,
   6120                 (BSL_META_U(unit,
   6121                             "Error happen during MMU RQE phy port remapping\n")));
   6122     } else {
   6123         LOG_VERBOSE(BSL_LS_SOC_MMU,
   6124                 (BSL_META_U(unit,
   6125                             "End MMU RQE phy port remapping\n")));
   6126     }
   6127 
   6128     return rv;
   6129 }
   6130 
   6131 #endif /* BCM_TRIDENT2PLUS_SUPPORT */