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

port.c (33368B)


      1 /* 
      2  * 
      3  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      4  * 
      5  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      6  *
      7  * File:        port.c
      8  * Purpose:     TH2 SOC Port driver.
      9  */
     10 
     11 #include <shared/bsl.h>
     12 #include <soc/error.h>
     13 #include <soc/defs.h>
     14 #include <soc/tdm/core/tdm_top.h>
     15 
     16 #if defined(BCM_TOMAHAWK2_SUPPORT)
     17 #include <soc/tomahawk2_tdm.h>
     18 #include <soc/tomahawk2.h>
     19 #include <soc/scache.h>
     20 
     21 #ifdef BCM_WARM_BOOT_SUPPORT
     22 
     23 #define SOC_FLEXPORT_WB_VERSION_1_0                SOC_SCACHE_VERSION(1,0)
     24 #define SOC_FLEXPORT_WB_VERSION_1_1                SOC_SCACHE_VERSION(1,1)
     25 #define SOC_FLEXPORT_WB_DEFAULT_VERSION            SOC_FLEXPORT_WB_VERSION_1_1
     26 
     27 extern int
     28 _soc_th2_port_speed_cap[SOC_MAX_NUM_DEVICES][_TH2_DEV_PORTS_PER_DEV];
     29 #endif
     30 
     31 /*
     32  * Function:
     33  *      soc_th2_port_schedule_tdm_init
     34  * Purpose:
     35  *      Initialize TDM information in port_schedule_state that will be passed
     36  *      to DV FlexPort API
     37  * Parameters:
     38  *      unit                 - (IN)  Unit number.
     39  *      port_schedule_state  - (OUT) Port resource state.
     40  * Returns:
     41  *      BCM_E_xxx
     42  * Notes:
     43  *      If called during Scheduler Initialization, only below values need to be
     44  *      properly set:
     45  *        soc_tdm_schedule_pipe_t::num_slices
     46  *        soc_tdm_schedule_t:: cal_len
     47  *        soc_tdm_schedule_t:: num_ovs_groups
     48  *        soc_tdm_schedule_t:: ovs_group_len
     49  *        soc_tdm_schedule_t:: num_pkt_sch_or_ovs_space
     50  *        soc_tdm_schedule_t:: pkt_sch_or_ovs_space_len 
     51  */
     52 int
     53 soc_th2_port_schedule_tdm_init(int unit,
     54                             soc_port_schedule_state_t *port_schedule_state)
     55 {
     56     soc_control_t *soc = SOC_CONTROL(unit);
     57     _soc_tomahawk2_tdm_t *tdm = soc->tdm_info;
     58     soc_info_t *si = &SOC_INFO(unit);
     59     soc_tdm_schedule_pipe_t *tdm_ischd, *tdm_eschd;
     60     soc_tdm_schedule_t *sched;
     61     int pipe, hpipe, phy_port, is_flexport, group, slot;
     62     int *port_p2PBLK_inst_mapping;
     63 
     64     if (tdm == NULL) {
     65         /*XGSSIM will skip tdm configuration on TH2*/
     66         if (SAL_BOOT_XGSSIM) {
     67             return SOC_E_NONE;
     68         }
     69         return SOC_E_INIT;
     70     }
     71 
     72     is_flexport = port_schedule_state->is_flexport;
     73 
     74     port_schedule_state->calendar_type = si->fabric_port_enable ?
     75                                         _TH2_TDM_CALENDAR_UNIVERSAL :
     76                                         _TH2_TDM_CALENDAR_ETHERNET_OPTIMIZED;
     77 
     78     /* Construct tdm_ingress_schedule_pipe and tdm_egress_schedule_pipe */
     79     for (pipe = 0; pipe <  _TH2_PIPES_PER_DEV; pipe++) {
     80         tdm_ischd = &port_schedule_state->tdm_ingress_schedule_pipe[pipe];
     81         tdm_eschd = &port_schedule_state->tdm_egress_schedule_pipe[pipe];
     82 
     83         tdm_ischd->num_slices = _TH2_OVS_HPIPE_COUNT_PER_PIPE;
     84         tdm_eschd->num_slices = _TH2_OVS_HPIPE_COUNT_PER_PIPE;
     85 
     86         if (is_flexport) {
     87             /* TDM Calendar is always in slice 0 */
     88             sal_memcpy(tdm_ischd->tdm_schedule_slice[0].linerate_schedule,
     89                         tdm->tdm_pipe[pipe].idb_tdm,
     90                         sizeof(int)*_TH2_TDM_LENGTH);
     91             sal_memcpy(tdm_eschd->tdm_schedule_slice[0].linerate_schedule,
     92                         tdm->tdm_pipe[pipe].mmu_tdm,
     93                         sizeof(int)*_TH2_TDM_LENGTH);
     94         }
     95 
     96         /* OVS */
     97         for (hpipe = 0; hpipe < _TH2_OVS_HPIPE_COUNT_PER_PIPE; hpipe++) {
     98             /* IDB OVERSUB*/
     99             sched = &tdm_ischd->tdm_schedule_slice[hpipe];
    100             sched->cal_len = _TH2_TDM_LENGTH;
    101             sched->num_ovs_groups = _TH2_OVS_GROUP_COUNT_PER_HPIPE;
    102             sched->ovs_group_len = _TH2_OVS_GROUP_TDM_LENGTH;
    103             sched->num_pkt_sch_or_ovs_space = 1;
    104             sched->pkt_sch_or_ovs_space_len = _TH2_PKT_SCH_LENGTH;
    105 
    106             if (is_flexport) {
    107                 for (group = 0; group < _TH2_OVS_GROUP_COUNT_PER_HPIPE; group++) {
    108                     for (slot = 0; slot < _TH2_OVS_GROUP_TDM_LENGTH; slot++) {
    109                         sched->oversub_schedule[group][slot] =
    110                             tdm->tdm_pipe[pipe].ovs_tdm[hpipe][group][slot];
    111                     }
    112                 }
    113                 for (slot = 0; slot < _TH2_PKT_SCH_LENGTH; slot++) {
    114                     sched->pkt_sch_or_ovs_space[0][slot] = 
    115                         tdm->tdm_pipe[pipe].pkt_shaper_tdm[hpipe][slot];
    116                 }
    117             }
    118 
    119             /* MMU OVERSUB */
    120             sched = &tdm_eschd->tdm_schedule_slice[hpipe];
    121             sched->cal_len = _TH2_TDM_LENGTH;
    122             sched->num_ovs_groups = _TH2_OVS_GROUP_COUNT_PER_HPIPE;
    123             sched->ovs_group_len = _TH2_OVS_GROUP_TDM_LENGTH;
    124             sched->num_pkt_sch_or_ovs_space = 1;
    125             sched->pkt_sch_or_ovs_space_len = _TH2_PKT_SCH_LENGTH;
    126 
    127             if (is_flexport) {
    128                 for (group = 0; group < _TH2_OVS_GROUP_COUNT_PER_HPIPE; group++) {
    129                     for (slot = 0; slot < _TH2_OVS_GROUP_TDM_LENGTH; slot++) {
    130                         sched->oversub_schedule[group][slot] =
    131                             tdm->tdm_pipe[pipe].ovs_tdm[hpipe][group][slot];
    132                         }
    133                     }
    134                 for (slot = 0; slot < _TH2_PKT_SCH_LENGTH; slot++) {
    135                     sched->pkt_sch_or_ovs_space[0][slot] = 
    136                         tdm->tdm_pipe[pipe].pkt_shaper_tdm[hpipe][slot];
    137                 }
    138             }
    139         }
    140     }
    141 
    142     if (is_flexport) {
    143         port_p2PBLK_inst_mapping =
    144             port_schedule_state->in_port_map.port_p2PBLK_inst_mapping;
    145         /* pblk info for phy_port */
    146         for (phy_port = 1; phy_port < SOC_MAX_NUM_PORTS; phy_port++) {
    147             if (phy_port < TH2_NUM_EXT_PORTS) {
    148                 port_p2PBLK_inst_mapping[phy_port] =
    149                                         tdm->pblk_info[phy_port].pblk_cal_idx;
    150             } else {
    151                 port_p2PBLK_inst_mapping[phy_port] = -1;
    152             }
    153         }
    154         sal_memcpy(&port_schedule_state->in_port_map.physical_pbm,
    155                    &si->pbm_25g_use_50g_tdm, sizeof(pbmp_t));
    156     }
    157     return SOC_E_NONE;
    158 }
    159 
    160 /*
    161  * Function:
    162  *      soc_th2_soc_tdm_update
    163  * Purpose:
    164  *      Update TDM information in SOC with TDM state return from DV FlexPort API
    165  * Parameters:
    166  *      unit                 - (IN)  Unit number.
    167  *      port_schedule_state  - (OUT) Port resource state.
    168  * Returns:
    169  *      BCM_E_xxx
    170  * Notes:
    171  */
    172 int
    173 soc_th2_soc_tdm_update(int unit,
    174                             soc_port_schedule_state_t *port_schedule_state)
    175 {
    176     soc_control_t *soc = SOC_CONTROL(unit);
    177     soc_info_t *si = &SOC_INFO(unit);
    178     _soc_tomahawk2_tdm_t *tdm = soc->tdm_info;
    179     soc_tdm_schedule_pipe_t *tdm_ischd, *tdm_eschd;
    180     soc_tdm_schedule_t *sched;
    181     int pipe, hpipe, port, phy_port, clport, slot;
    182     int length, ovs_core_slot_count, ovs_io_slot_count, port_slot_count;
    183     int index, group;
    184 
    185     if (tdm == NULL) {
    186         /*XGSSIM will skip tdm configuration on TH2*/
    187         if (SAL_BOOT_XGSSIM) {
    188             return SOC_E_NONE;
    189         }
    190         return SOC_E_INIT;
    191     }
    192 
    193     /* Copy info from soc_port_schedule_state_t to _soc_tomahawk2_tdm_t */
    194     for (pipe = 0; pipe <  _TH2_PIPES_PER_DEV; pipe++) {
    195         tdm_ischd = &port_schedule_state->tdm_ingress_schedule_pipe[pipe];
    196         tdm_eschd = &port_schedule_state->tdm_egress_schedule_pipe[pipe];
    197 
    198         /* TDM Calendar is always in slice 0 */
    199         sal_memcpy(tdm->tdm_pipe[pipe].idb_tdm,
    200                     tdm_ischd->tdm_schedule_slice[0].linerate_schedule,
    201                     sizeof(int)*_TH2_TDM_LENGTH);
    202         sal_memcpy(tdm->tdm_pipe[pipe].mmu_tdm,
    203                     tdm_eschd->tdm_schedule_slice[0].linerate_schedule,
    204                     sizeof(int)*_TH2_TDM_LENGTH);
    205 
    206         for (hpipe = 0; hpipe < _TH2_OVS_HPIPE_COUNT_PER_PIPE; hpipe++) {
    207             sched = &tdm_ischd->tdm_schedule_slice[hpipe];
    208             for (group = 0; group < _TH2_OVS_GROUP_COUNT_PER_HPIPE; group++) {
    209                 for (slot = 0; slot < _TH2_OVS_GROUP_TDM_LENGTH; slot++) {
    210                     tdm->tdm_pipe[pipe].ovs_tdm[hpipe][group][slot] =
    211                         sched->oversub_schedule[group][slot];
    212                 }
    213             }
    214             for (slot = 0; slot < _TH2_PKT_SCH_LENGTH; slot++) {
    215                 tdm->tdm_pipe[pipe].pkt_shaper_tdm[hpipe][slot] =
    216                     sched->pkt_sch_or_ovs_space[0][slot];
    217 
    218             }
    219         }
    220     }
    221 
    222     /* pblk info init  */
    223     for (phy_port = 1; phy_port < TH2_NUM_EXT_PORTS; phy_port++) {
    224         tdm->pblk_info[phy_port].pblk_cal_idx = -1;
    225         tdm->pblk_info[phy_port].pblk_hpipe_num = -1;
    226     }
    227 
    228     /* pblk info for phy_port */
    229     for (pipe = 0; pipe < _TH2_PIPES_PER_DEV; pipe++) {
    230         tdm_ischd = &port_schedule_state->tdm_ingress_schedule_pipe[pipe];
    231         for (hpipe = 0; hpipe < _TH2_OVS_HPIPE_COUNT_PER_PIPE; hpipe++) {
    232             for (group = 0; group < _TH2_OVS_GROUP_COUNT_PER_HPIPE; group++) {
    233                 for (index = 0; index < _TH2_OVS_GROUP_TDM_LENGTH; index++) {
    234                     phy_port =
    235                         tdm_ischd->tdm_schedule_slice[hpipe].oversub_schedule[group][index];
    236                     if (phy_port < TH2_NUM_EXT_PORTS) {
    237                         tdm->pblk_info[phy_port].pblk_hpipe_num = hpipe;
    238                     }
    239                 }
    240             }
    241         }
    242     }
    243 
    244     for (phy_port = 0; phy_port < TH2_NUM_EXT_PORTS; phy_port++) {
    245         tdm->pblk_info[phy_port].pblk_cal_idx =
    246             port_schedule_state->out_port_map.port_p2PBLK_inst_mapping[phy_port];
    247     }
    248 
    249     /* CLPORT port ratio */
    250     for (clport = 0; clport < _TH2_PBLKS_PER_DEV; clport++) {
    251         soc_tomahawk2_port_ratio_get(unit, port_schedule_state, clport,
    252             &tdm->port_ratio[clport], 1);
    253     }
    254 
    255     /* Calculate the oversub ratio */
    256     for (pipe = 0; pipe < _TH2_PIPES_PER_DEV; pipe++) {
    257         /* At MAX Frequency OVS is always 3:2 */
    258         if (si->frequency == 1700) {
    259             for (hpipe = 0; hpipe < _TH2_OVS_HPIPE_COUNT_PER_PIPE; hpipe++) {
    260                 tdm->ovs_ratio_x1000[pipe][hpipe] = 1500;
    261             }
    262             continue;
    263         }
    264 
    265         tdm_ischd = &port_schedule_state->tdm_ingress_schedule_pipe[pipe];
    266         /* Count number of OVSB_TOKEN assigned by the TDM code */
    267         for (length = _TH2_TDM_LENGTH; length > 0; length--) {
    268             if (tdm_ischd->tdm_schedule_slice[0].linerate_schedule[length - 1]
    269                     != TH2_NUM_EXT_PORTS) {
    270                 break;
    271             }
    272         }
    273         ovs_core_slot_count = 0;
    274         for (index = 0; index < length; index++) {
    275             if (tdm_ischd->tdm_schedule_slice[0].linerate_schedule[index]
    276                     == TH2_OVSB_TOKEN) {
    277                 ovs_core_slot_count++;
    278             }
    279         }
    280 
    281         /* At line-rate with less than max frequency, OVS picks the 2:1 */
    282         if (ovs_core_slot_count == 0) {
    283             for (hpipe = 0; hpipe < _TH2_OVS_HPIPE_COUNT_PER_PIPE; hpipe++) {
    284                 tdm->ovs_ratio_x1000[pipe][hpipe] = 2000;
    285             }
    286         }
    287 
    288         /* Count number of slot needed for half-pipe's oversub I/O bandwidth */
    289         for (hpipe = 0; hpipe < _TH2_OVS_HPIPE_COUNT_PER_PIPE; hpipe++) {
    290             ovs_io_slot_count = 0;
    291             for (group = 0; group < _TH2_OVS_GROUP_COUNT_PER_HPIPE; group++) {
    292                 for (index = 0; index < _TH2_OVS_GROUP_TDM_LENGTH; index++) {
    293                     phy_port = tdm_ischd->tdm_schedule_slice[hpipe].oversub_schedule[group][index];
    294                     if (phy_port == TH2_NUM_EXT_PORTS) {
    295                         continue;
    296                     }
    297                     port = si->port_p2l_mapping[phy_port];
    298                     if ((port == -1) || IS_CPU_PORT(unit, port) ||
    299                         IS_LB_PORT(unit, port) ||
    300                         IS_MANAGEMENT_PORT(unit, port)) {
    301                         LOG_ERROR(BSL_LS_SOC_PORT,
    302                                   (BSL_META_U(unit,
    303                                               "Flexport: Invalid physical "
    304                                               "port %d in OverSub table.\n"),
    305                                    phy_port));
    306                         continue;
    307                     }
    308                     port_slot_count = si->port_init_speed[port] / 2500;
    309                     ovs_io_slot_count += port_slot_count;
    310                 }
    311             }
    312             if (ovs_core_slot_count != 0) {
    313                 tdm->ovs_ratio_x1000[pipe][hpipe] =
    314                     ovs_io_slot_count * 1000 / (ovs_core_slot_count / 2);
    315             }
    316         }
    317     }
    318 
    319     sal_memcpy(&si->pbm_25g_use_50g_tdm,
    320                &port_schedule_state->in_port_map.physical_pbm, sizeof(pbmp_t));
    321 
    322     return SOC_E_NONE;
    323 }
    324 
    325 /*
    326  * Function:
    327  *      soc_th2_max_lr_bandwidth
    328  * Purpose:
    329  *      Get the max line rate bandwidth per pipeline
    330  * Parameters:
    331  *      unit                 - (IN)  Unit number.
    332  *      max_lr_bw            - (OUT) Max line rate bandwidth (Gbps).
    333  * Returns:
    334  *      BCM_E_xxx
    335  * Notes:
    336  */
    337 int
    338 soc_th2_max_lr_bandwidth(int unit, uint32 *max_lr_bw)
    339 {
    340     soc_info_t *si = &SOC_INFO(unit);
    341     int cal_universal;
    342     int rv = SOC_E_NONE;
    343 
    344     cal_universal = si->fabric_port_enable ? 1 : 0;
    345 
    346     switch (si->frequency) {
    347     case 1700:
    348         *max_lr_bw = cal_universal ? 1050 : 1095;
    349         break;
    350     case 1625:
    351         *max_lr_bw = cal_universal ? 1002 : 1047;
    352         break;
    353     case 1525:
    354         *max_lr_bw = cal_universal ? 940 : 980;
    355         break;
    356     case 1425:
    357         *max_lr_bw = cal_universal ? 877 : 915;
    358         break;
    359     case 1325:
    360         *max_lr_bw = cal_universal ? 812 : 847;
    361         break;
    362     case 1275:
    363         *max_lr_bw = cal_universal ? 782 : 815;
    364         break;
    365     case 1225:
    366         *max_lr_bw = cal_universal ? 750 : 782;
    367         break;
    368     case 1125:
    369         *max_lr_bw = cal_universal ? 687 : 717;
    370         break;
    371     case 1050:
    372         *max_lr_bw = cal_universal ? 640 : 667;
    373         break;
    374     case 950:
    375         *max_lr_bw = cal_universal ? 575 : 600;
    376         break;
    377     case 850:
    378         *max_lr_bw = cal_universal ? 512 : 535;
    379         break;
    380     default:
    381         *max_lr_bw = 0;
    382         rv = SOC_E_INTERNAL;
    383         break;
    384     }
    385 
    386     return rv;
    387 }
    388 
    389 /*
    390  * Function:
    391  *      soc_th2_support_speeds
    392  * Purpose:
    393  *      Get the supported speed of port for specified lanes
    394  * Parameters:
    395  *      unit                 - (IN)  Unit number.
    396  *      lanes                - (IN)  Number of Lanes for the port.
    397  *      speed_mask           - (IN)  Bitmap for supported speed.
    398  * Returns:
    399  *      BCM_E_xxx
    400  * Notes:
    401  */
    402 int
    403 soc_th2_support_speeds(int unit, int lanes, uint32 *speed_mask)
    404 {
    405     soc_info_t *si = &SOC_INFO(unit);
    406     uint32 speed_valid;
    407 
    408     switch(lanes) {
    409     case 1:
    410         /* Single Lane Port Speeds */
    411         speed_valid = SOC_PA_SPEED_1000MB | SOC_PA_SPEED_10GB |
    412                       SOC_PA_SPEED_25GB;
    413         if(soc_feature(unit, soc_feature_higig2)) {
    414             speed_valid |= SOC_PA_SPEED_11GB  | SOC_PA_SPEED_27GB;
    415         }
    416         break;
    417     case 2:
    418         /* Dual Lane Port Speeds */
    419         speed_valid = SOC_PA_SPEED_20GB | SOC_PA_SPEED_40GB | SOC_PA_SPEED_50GB;
    420         if(soc_feature(unit, soc_feature_higig2)) {
    421             speed_valid |= SOC_PA_SPEED_21GB | SOC_PA_SPEED_42GB |
    422                            SOC_PA_SPEED_53GB;
    423         }
    424         break;
    425     case 4:
    426         /* Quad Lane Port Speeds */
    427         speed_valid = SOC_PA_SPEED_40GB | SOC_PA_SPEED_100GB;
    428         if(soc_feature(unit, soc_feature_higig2)) {
    429             speed_valid |= SOC_PA_SPEED_42GB | SOC_PA_SPEED_106GB;
    430         }
    431         break;
    432     default:
    433         return SOC_E_PARAM;
    434     }
    435 
    436     if (FALSE == si->fabric_port_enable) {
    437         /* Ethernet-optimized Calendar doesn't support any HG speed */
    438         speed_valid &= ~(SOC_PA_SPEED_11GB | SOC_PA_SPEED_21GB |
    439                             SOC_PA_SPEED_27GB | SOC_PA_SPEED_42GB |
    440                             SOC_PA_SPEED_53GB | SOC_PA_SPEED_106GB);
    441     } else if (si->frequency < 1125) {
    442         speed_valid &= ~(SOC_PA_SPEED_27GB | SOC_PA_SPEED_53GB |
    443                             SOC_PA_SPEED_106GB);
    444     }
    445 
    446     if (si->frequency < 1050) {
    447         speed_valid &= ~(SOC_PA_SPEED_25GB | SOC_PA_SPEED_50GB |
    448                             SOC_PA_SPEED_100GB);
    449     }
    450 
    451     *speed_mask = speed_valid;
    452 
    453     return SOC_E_NONE;
    454 }
    455 
    456 #ifdef BCM_WARM_BOOT_SUPPORT
    457 int soc_th2_flexport_scache_allocate(int unit)
    458 {
    459     int rv = SOC_E_NONE;
    460     uint8 *flexport_scache_ptr;
    461     soc_scache_handle_t scache_handle;
    462     uint32 alloc_get = 0;
    463     uint32 alloc_size = 0;
    464     int stable_size;
    465     int default_ver = SOC_FLEXPORT_WB_DEFAULT_VERSION;
    466 
    467     alloc_size =  (sizeof(int) * _TH2_PHY_PORTS_PER_DEV)  + /* phy to logical*/
    468                    (sizeof(int) * _TH2_DEV_PORTS_PER_DEV) + /* logical to phy */
    469                    (sizeof(int) * _TH2_DEV_PORTS_PER_DEV) + /* max port speed */
    470                    (sizeof(int) * _TH2_DEV_PORTS_PER_DEV) + /* init port speed */
    471                    (sizeof(int) * _TH2_DEV_PORTS_PER_DEV) + /* num of lanes */
    472                    (sizeof(pbmp_t))                       + /* HG bitmap */
    473                    (sizeof(pbmp_t))                       + /* Disabled bitmap */
    474                    (sizeof(pbmp_t));                        /* pbm_25g_use_50g_tdm */
    475     alloc_get = alloc_size;
    476 
    477     SOC_SCACHE_HANDLE_SET(scache_handle, unit, SOC_SCACHE_FLEXIO_HANDLE, 0);
    478     /* check to see if an scache table has been configured */
    479     rv = soc_stable_size_get(unit, &stable_size);
    480     if (SOC_FAILURE(rv) || stable_size <= 0) {
    481         return rv;
    482     }
    483 
    484     rv = soc_versioned_scache_ptr_get(unit, scache_handle,
    485                                           TRUE, &alloc_get,
    486                                           &flexport_scache_ptr,
    487                                           default_ver,
    488                                           NULL);
    489 
    490     if (rv  == SOC_E_CONFIG) {
    491         /* Probably Level1 */
    492         return SOC_E_NONE;
    493     }
    494     /* NotRequired but just to confirm Get the pointer for the Level 2 cache */
    495     if (alloc_get != alloc_size) {
    496         /* Expected size doesn't match retrieved size */
    497         LOG_ERROR(BSL_LS_SOC_COMMON,
    498                 (BSL_META_U(unit,
    499                  "ERROR: scache memory for flexport size mismatch"
    500                  "%s()[LINE:%d] DONE \n"),FUNCTION_NAME(),  __LINE__));
    501         return SOC_E_INTERNAL;
    502     }
    503 
    504     if (NULL == flexport_scache_ptr) {
    505         LOG_ERROR(BSL_LS_SOC_COMMON,
    506                 (BSL_META_U(unit,
    507                  "ERROR: scache memory not allocated for flexport"
    508                  "%s()[LINE:%d] DONE \n"),FUNCTION_NAME(),  __LINE__));
    509         return SOC_E_MEMORY;
    510     }
    511     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    512                 (BSL_META_U(unit,
    513                 "%s()[LINE:%d] DONE \n"),FUNCTION_NAME(),  __LINE__));
    514     return SOC_E_NONE;
    515 
    516 }
    517 
    518 /*
    519  * Function:
    520  *      soc_th2_flexport_scache_sync
    521  * Purpose:
    522  *      Record Port info that maybe changed during flexport for Level 2 WB
    523  *
    524  * Warm Boot Version Map:
    525  *
    526  *  BCM_WB_VERSION_1_0
    527  *    port_p2l_mapping
    528  *    port_l2p_mapping
    529  *    port_speed_max
    530  *    port_init_speed
    531  *    port_num_lanes
    532  *    disabled_bitmap
    533  *
    534  * Parameters:
    535  *      unit - StrataSwitch unit number.
    536  * Returns:
    537  *      SOC_E_XXX
    538  */
    539 int soc_th2_flexport_scache_sync(int unit)
    540 {
    541     uint8 *flexport_scache_ptr;
    542     soc_scache_handle_t scache_handle;
    543     uint32 alloc_get = 0;
    544     uint32 alloc_size = 0;
    545     uint32 var_size = 0;
    546     soc_info_t *si = &SOC_INFO(unit);
    547     uint32 scache_offset=0;
    548     int rv = 0;
    549 
    550     alloc_size =  (sizeof(int) * _TH2_PHY_PORTS_PER_DEV)  + /* phy to logical*/
    551                    (sizeof(int) * _TH2_DEV_PORTS_PER_DEV) + /* logical to phy */
    552                    (sizeof(int) * _TH2_DEV_PORTS_PER_DEV) + /* max port speed */
    553                    (sizeof(int) * _TH2_DEV_PORTS_PER_DEV) + /* init port speed */
    554                    (sizeof(int) * _TH2_DEV_PORTS_PER_DEV) + /* num of lanes */
    555                    (sizeof(pbmp_t))                       + /* HG bitmap */
    556                    (sizeof(pbmp_t))                       + /* Disabled bitmap */
    557                    (sizeof(pbmp_t));                        /* pbm_25g_use_50g_tdm */
    558 
    559     alloc_get = alloc_size;
    560 
    561     SOC_SCACHE_HANDLE_SET(scache_handle, unit, SOC_SCACHE_FLEXIO_HANDLE, 0);
    562     rv = soc_versioned_scache_ptr_get(unit, scache_handle,
    563                         FALSE, &alloc_get,
    564                         &flexport_scache_ptr,
    565                         SOC_FLEXPORT_WB_DEFAULT_VERSION,
    566                         NULL);
    567     if (rv == SOC_E_NOT_FOUND) {
    568         /* Probably Level1 */
    569         return SOC_E_NONE;
    570     }
    571     if (alloc_get != alloc_size) {
    572         /* Expected size doesn't match retrieved size */
    573         LOG_ERROR(BSL_LS_SOC_COMMON,
    574                 (BSL_META_U(unit,
    575                  "ERROR: scache memory for flexport size mismatch"
    576                  "%s()[LINE:%d] DONE \n"),FUNCTION_NAME(),  __LINE__));
    577         return SOC_E_INTERNAL;
    578     }
    579     if (NULL == flexport_scache_ptr) {
    580         LOG_ERROR(BSL_LS_SOC_COMMON,
    581                 (BSL_META_U(unit,
    582                  "ERROR: scache memory not allocated for flexport"
    583                  "%s()[LINE:%d] DONE \n"),FUNCTION_NAME(),  __LINE__));
    584         return SOC_E_MEMORY;
    585     }
    586 
    587     /* Physical to logical port mapping */
    588     var_size = sizeof(int) * _TH2_PHY_PORTS_PER_DEV;
    589     sal_memcpy(&flexport_scache_ptr[scache_offset],
    590                si->port_p2l_mapping, var_size);
    591     scache_offset += var_size;
    592 
    593     var_size = sizeof(int) * _TH2_DEV_PORTS_PER_DEV;
    594 
    595     /* Logical to Physical port mapping */
    596     sal_memcpy(&flexport_scache_ptr[scache_offset],
    597                si->port_l2p_mapping, var_size);
    598     scache_offset += var_size;
    599 
    600     /* Max port speed */
    601     sal_memcpy(&flexport_scache_ptr[scache_offset],
    602                si->port_speed_max, var_size);
    603     scache_offset += var_size;
    604 
    605     /* Init port speed */
    606     sal_memcpy(&flexport_scache_ptr[scache_offset],
    607                si->port_init_speed, var_size);
    608     scache_offset += var_size;
    609 
    610     /* Num of lanes */
    611     sal_memcpy(&flexport_scache_ptr[scache_offset],
    612                si->port_num_lanes, var_size);
    613     scache_offset += var_size;
    614 
    615 
    616     /* HG Bitmap */
    617     sal_memcpy(&flexport_scache_ptr[scache_offset],
    618                &si->hg.bitmap,
    619                sizeof(pbmp_t));
    620     scache_offset += sizeof(pbmp_t);
    621 
    622     /* Disabled Port Bitmap */
    623     sal_memcpy(&flexport_scache_ptr[scache_offset],
    624                &si->all.disabled_bitmap,
    625                sizeof(pbmp_t));
    626     scache_offset += sizeof(pbmp_t);
    627 
    628     /* Bitmap of 25G port use 50G tdm */
    629     sal_memcpy(&flexport_scache_ptr[scache_offset],
    630                &si->pbm_25g_use_50g_tdm,
    631                sizeof(pbmp_t));
    632     scache_offset += sizeof(pbmp_t);
    633 
    634     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    635                 (BSL_META_U(unit,
    636                  "%s()[LINE:%d] \n"),FUNCTION_NAME(),  __LINE__));
    637 
    638     return SOC_E_NONE;
    639 }
    640 
    641 /*
    642  * Function:
    643  *      soc_th2_flexport_scache_recovery
    644  * Purpose:
    645  *      Recover Port info that maybe changed during flexport for Level 2 WB
    646  *
    647  * Warm Boot Version Map:
    648  *
    649  *  BCM_WB_VERSION_1_0
    650  *    port_p2l_mapping
    651  *    port_l2p_mapping
    652  *    port_speed_max
    653  *    port_init_speed
    654  *    port_num_lanes
    655  *    disabled_bitmap
    656  *
    657  * Parameters:
    658  *      unit - StrataSwitch unit number.
    659  * Returns:
    660  *      SOC_E_XXX
    661  */
    662 int soc_th2_flexport_scache_recovery(int unit)
    663 {
    664     uint32 alloc_get = 0;
    665     uint32 alloc_size = 0;
    666     int rv = SOC_E_NONE;
    667     uint8 *flexport_scache_ptr = NULL;
    668     soc_scache_handle_t scache_handle;
    669     uint32 scache_offset=0;
    670     uint32 var_size = 0;
    671     uint16 recovered_ver = 0;
    672     int realloc_size = 0;
    673     soc_info_t *si = &SOC_INFO(unit);
    674 
    675     alloc_size =  (sizeof(int) * _TH2_PHY_PORTS_PER_DEV)  + /* phy to logical*/
    676                    (sizeof(int) * _TH2_DEV_PORTS_PER_DEV) + /* logical to phy */
    677                    (sizeof(int) * _TH2_DEV_PORTS_PER_DEV) + /* max port speed */
    678                    (sizeof(int) * _TH2_DEV_PORTS_PER_DEV) + /* init port speed */
    679                    (sizeof(int) * _TH2_DEV_PORTS_PER_DEV) + /* num of lanes */
    680                    (sizeof(pbmp_t))                       + /* HG bitmap */
    681                    (sizeof(pbmp_t))                       + /* Disabled bitmap */
    682                    (sizeof(pbmp_t));                        /* pbm_25g_use_50g_tdm */
    683 
    684     alloc_get = alloc_size;
    685 
    686     SOC_SCACHE_HANDLE_SET(scache_handle, unit, SOC_SCACHE_FLEXIO_HANDLE, 0);
    687     rv = soc_versioned_scache_ptr_get(unit, scache_handle,
    688                         FALSE, &alloc_get,
    689                         &flexport_scache_ptr,
    690                         SOC_FLEXPORT_WB_DEFAULT_VERSION,
    691                         &recovered_ver);
    692     if (SOC_FAILURE(rv)) {
    693         if ((rv == SOC_E_CONFIG) ||
    694             (rv == SOC_E_NOT_FOUND)) {
    695             /* warmboot file does not contain this
    696             * module, or the warmboot state does not exist.
    697             * in this case return SOC_E_NOT_FOUND
    698             */
    699             return SOC_E_NOT_FOUND;
    700         } else {
    701             /* Only Level2 - flexport treat this as a error */
    702             LOG_ERROR(BSL_LS_SOC_COMMON,
    703                      (BSL_META_U(unit,
    704                      "Failed to recover scache data - %s\n"),soc_errmsg(rv)));
    705             return rv;
    706         }
    707     }
    708     if (alloc_get != alloc_size) {
    709         /* Expected size doesn't match retrieved size */
    710         LOG_ERROR(BSL_LS_SOC_COMMON,
    711                 (BSL_META_U(unit,
    712                  "ERROR: scache recovery for flexport"
    713                  "%s()[LINE:%d] DONE \n"),
    714                   FUNCTION_NAME(),  __LINE__));
    715         return SOC_E_INTERNAL;
    716     }
    717 
    718     if (NULL == flexport_scache_ptr) {
    719         LOG_ERROR(BSL_LS_SOC_COMMON,
    720                 (BSL_META_U(unit,
    721                  "ERROR: scache recovery for flexport"
    722                  "%s()[LINE:%d] DONE \n"),
    723                   FUNCTION_NAME(),  __LINE__));
    724         return SOC_E_MEMORY;
    725     }
    726 
    727     /*Physical to logical port mapping */
    728     var_size = (sizeof(int) * _TH2_PHY_PORTS_PER_DEV);
    729     sal_memcpy(si->port_p2l_mapping,
    730                &flexport_scache_ptr[scache_offset],
    731                var_size);
    732     scache_offset += var_size;
    733 
    734     var_size = (sizeof(int) * _TH2_DEV_PORTS_PER_DEV);
    735 
    736     /*Logical to Physical port mapping*/
    737     sal_memcpy(si->port_l2p_mapping,
    738                &flexport_scache_ptr[scache_offset],
    739                var_size);
    740     scache_offset += var_size;
    741 
    742     /* Max port speed */
    743     sal_memcpy(_soc_th2_port_speed_cap[unit],
    744                &flexport_scache_ptr[scache_offset],
    745                var_size);
    746     scache_offset += var_size;
    747 
    748     /* Init port speed */
    749     sal_memcpy(si->port_speed_max,
    750                &flexport_scache_ptr[scache_offset],
    751                var_size);
    752     scache_offset += var_size;
    753 
    754     /* Num of lanes */
    755     sal_memcpy(si->port_num_lanes,
    756                &flexport_scache_ptr[scache_offset],
    757                var_size);
    758     scache_offset += var_size;
    759 
    760     /* HG Bitmap */
    761     sal_memcpy(&si->hg.bitmap,
    762            &flexport_scache_ptr[scache_offset],
    763            sizeof(pbmp_t));
    764     scache_offset += sizeof(pbmp_t);
    765 
    766     /* Disabled Port Bitmap */
    767     sal_memcpy(&si->all.disabled_bitmap,
    768            &flexport_scache_ptr[scache_offset],
    769            sizeof(pbmp_t));
    770     scache_offset += sizeof(pbmp_t);
    771 
    772     /* Bitmap of 25G port use 50G tdm */
    773     if (recovered_ver >= SOC_FLEXPORT_WB_VERSION_1_1) {
    774         sal_memcpy(&si->pbm_25g_use_50g_tdm,
    775                    &flexport_scache_ptr[scache_offset],
    776                    sizeof(pbmp_t));
    777         scache_offset += sizeof(pbmp_t);
    778     } else {
    779         realloc_size += sizeof(pbmp_t);
    780     }
    781 
    782     if (realloc_size > 0) {
    783         SOC_IF_ERROR_RETURN
    784             (soc_scache_realloc(unit, scache_handle, realloc_size));
    785     }
    786 
    787     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    788                 (BSL_META_U(unit,
    789                  "%s()[LINE:%d] \n"),FUNCTION_NAME(),  __LINE__));
    790 
    791     return SOC_E_NONE;
    792 }
    793 #endif /* BCM_WARM_BOOT_SUPPORT */
    794 
    795 #ifndef BCM_SW_STATE_DUMP_DISABLE
    796 void
    797 soc_th2_flexport_sw_dump(int unit)
    798 {
    799     int port, phy_port, mmu_port, pipe, pm, cosq, numq, uc_cosq, uc_numq;
    800     int max_speed, init_speed, num_lanes;
    801     char  pfmt[SOC_PBMP_FMT_LEN];
    802 
    803     LOG_CLI((BSL_META_U(unit,
    804                             "  port(log/phy/mmu)  pipe  pm  lanes    "
    805                             "speed(Max)    uc_Qbase/Numq mc_Qbase/Numq\n")));
    806     PBMP_ALL_ITER(unit, port) {
    807         pipe = SOC_INFO(unit).port_pipe[port];
    808         phy_port = SOC_INFO(unit).port_l2p_mapping[port];
    809         mmu_port = SOC_INFO(unit).port_p2m_mapping[phy_port];
    810         num_lanes = SOC_INFO(unit).port_num_lanes[port];
    811         pm = SOC_INFO(unit).port_serdes[port];
    812         max_speed = SOC_INFO(unit).port_speed_max[port];
    813         init_speed = SOC_INFO(unit).port_init_speed[port];
    814         cosq = SOC_INFO(unit).port_cosq_base[port];
    815         numq = SOC_INFO(unit).port_num_cosq[port];
    816         uc_cosq = SOC_INFO(unit).port_uc_cosq_base[port];
    817         uc_numq = SOC_INFO(unit).port_num_uc_cosq[port];
    818 
    819         LOG_CLI((BSL_META_U(unit,
    820                             "  %4s(%3d/%3d/%3d)  %4d  %2d  %5d %7d(%7d) "
    821                             "%6d/%-6d  %6d/%-6d\n"),
    822                 SOC_INFO(unit).port_name[port], port, phy_port, mmu_port,
    823                 pipe, pm, num_lanes, init_speed, max_speed,
    824                 uc_cosq, uc_numq, cosq, numq));
    825     }
    826 
    827     LOG_CLI((BSL_META_U(unit,
    828                         "\n    Oversub Bitmap: %s"),
    829        SOC_PBMP_FMT(SOC_INFO(unit).oversub_pbm, pfmt)));
    830     LOG_CLI((BSL_META_U(unit,
    831                         "\n    Disabled Bitmap: %s \n"),
    832        SOC_PBMP_FMT(SOC_INFO(unit).all.disabled_bitmap, pfmt)));
    833 }
    834 #endif /* BCM_SW_STATE_DUMP_DISABLE */
    835 
    836 /*
    837  * Function:
    838  *      soc_th2_port_mode_get
    839  * Description:
    840  *      Get port mode by giving any logical port of TSC4
    841  * Parameters:
    842  *      unit          - Device number
    843  *      port          - Logical port
    844  *      int*          - Port Mode
    845  *
    846  * Each TSC4 can be configured into following 5 mode:
    847  *   Lane number    0    1    2    3
    848  *   ------------  ---  ---  ---  ---
    849  *      quad port  25G  25G  25G  25G
    850  *   tri_012 port  25G  25G  50G   x
    851  *   tri_023 port  50G   x   25G  25G
    852  *      dual port  50G   x   50G   x
    853  *    single port  100G  x    x    x
    854  */
    855 int
    856 soc_th2_port_mode_get(int unit, int logical_port, int *mode)
    857 {
    858     soc_info_t *si;
    859     int lane;
    860     int port, first_phyport, phy_port;
    861     int num_lanes[_TH2_PORTS_PER_PBLK];
    862 
    863     si = &SOC_INFO(unit);
    864     first_phyport = PORT_BLOCK_BASE_PORT(logical_port);
    865 
    866     for (lane = 0; lane < _TH2_PORTS_PER_PBLK; lane++) {
    867         phy_port = first_phyport + lane;
    868         port = si->port_p2l_mapping[phy_port];
    869         if (port == -1 || SOC_PBMP_MEMBER(si->all.disabled_bitmap, port)) {
    870             num_lanes[lane] = -1;
    871         } else {
    872             num_lanes[lane] = si->port_num_lanes[port];
    873         }
    874     }
    875 
    876     if (num_lanes[0] == 4) {
    877         *mode = SOC_TH2_PORT_MODE_QUAD;
    878     } else if (num_lanes[0] == 2 && num_lanes[2] == 2) {
    879         *mode = SOC_TH2_PORT_MODE_DUAL;
    880     } else if (num_lanes[0] == 2 && (num_lanes[2] == 1 || num_lanes[3] == 1)) {
    881         *mode = SOC_TH2_PORT_MODE_TRI_023;
    882     } else if ((num_lanes[0] == 1 || num_lanes[1] == 1) && num_lanes[2] == 2) {
    883         *mode = SOC_TH2_PORT_MODE_TRI_012;
    884     } else {
    885         *mode = SOC_TH2_PORT_MODE_SINGLE;
    886     }
    887 
    888     return SOC_E_NONE;
    889 }
    890 
    891 
    892 /*
    893  * Function:
    894  *      soc_th2_speed_mix_validate
    895  * Purpose:
    896  *      Check if the mix of all ports speed is valid
    897  * Parameters:
    898  *      unit       - Unit.
    899  *      speed_mask - Bitmap of speed on all ports
    900  * Returns:
    901  *      SOC_E_NONE
    902  *      SOC_E_CONFIG
    903  */
    904 int
    905 soc_th2_speed_mix_validate(int unit, uint32 speed_mask)
    906 {
    907     uint32 count;
    908     soc_info_t *si;
    909 
    910     si = &SOC_INFO(unit);
    911 
    912     count = _shr_popcount(speed_mask);
    913 
    914     /* OverSub mode supports 10/25/40/50/100G and 10/20/40/100G , 
    915        * while LineRate mode only supports 10/25/50/100G and 10/20/40/100G.
    916        */
    917     if ((count == 4) &&
    918          (((!si->oversub_mode) &&
    919           ((speed_mask & SOC_PA_SPEED_20GB) || (speed_mask & SOC_PA_SPEED_40GB))) 
    920           ||
    921           ((si->oversub_mode) && (speed_mask & SOC_PA_SPEED_20GB)))
    922          &&
    923          ((speed_mask & SOC_PA_SPEED_25GB) ||
    924           (speed_mask & SOC_PA_SPEED_50GB))) {
    925         LOG_ERROR(BSL_LS_BCM_COMMON,
    926                   (BSL_META_U(unit,
    927                               "Port configurations that contain 4 speed class "
    928                               "and both 20G/40G and 25G/50G port speed "
    929                               "are not supported.\n")));
    930         return SOC_E_PARAM;
    931     }
    932 
    933     if ((count < 4) &&
    934         ((speed_mask & SOC_PA_SPEED_20GB) && (speed_mask & SOC_PA_SPEED_25GB))) {
    935         LOG_ERROR(BSL_LS_BCM_COMMON,
    936                   (BSL_META_U(unit,
    937                               "Port configurations that contain both 20G "
    938                               "and 25G port speed are not supported.\n")));
    939         return SOC_E_PARAM;
    940     }
    941 
    942     if ((count == _TH2_TDM_OS_SPEED_CLASS_MAX) &&
    943          (speed_mask & SOC_PA_SPEED_20GB)) {
    944         LOG_ERROR(BSL_LS_BCM_COMMON,
    945                   (BSL_META_U(unit,
    946                               "When contain %d speed class, only combination "
    947                               "10/25/40/50/100G is supported under oversub "
    948                               "mode.\n"), _TH2_TDM_OS_SPEED_CLASS_MAX));
    949         return SOC_E_PARAM;
    950     }
    951 
    952     return SOC_E_NONE;
    953 }
    954 
    955 #endif /* BCM_TOMAHAWK2_SUPPORT */