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


      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:     Port Management for Trident 3
      9  *
     10  *              The purpose is to set port management implementation specified
     11  *              to Trident 3 in this file.
     12  */
     13 
     14 #include <soc/defs.h>
     15 
     16 #if defined(BCM_TRIDENT3_SUPPORT)
     17 #include <sal/core/libc.h>
     18 #include <soc/drv.h>
     19 #include <soc/hash.h>
     20 #include <soc/l2x.h>
     21 #include <soc/trident3.h>
     22 #include <soc/tomahawk.h>
     23 #include <soc/esw/cancun.h>
     24 #include <bcm/port.h>
     25 #include <bcm/error.h>
     26 
     27 #include <bcm_int/esw/port.h>
     28 #include <bcm_int/esw/xgs3.h>
     29 #include <bcm_int/esw/trx.h>
     30 #include <bcm_int/esw/mirror.h>
     31 #include <bcm_int/esw/firebolt.h>
     32 #include <bcm_int/esw/trident3.h>
     33 #if defined(BCM_HELIX5_SUPPORT)
     34 #include <bcm_int/esw/helix5.h>
     35 #endif
     36 #include <bcm_int/esw/trident.h>
     37 #include <bcm_int/esw/tomahawk.h>
     38 
     39 #include <bcm_int/esw/xgs5.h>
     40 #include <bcm_int/esw/portctrl.h>
     41 #include <soc/flexport/trident3/trident3_flexport.h>
     42 #include <soc/flexport/trident3/trident3_flexport_defines.h>
     43 #include <include/bcm_int/esw/triumph3.h>
     44 #include <bcm_int/esw/trident2plus.h>
     45 /*
     46  * Function Vector
     47  */
     48 static bcm_esw_port_drv_t bcm_td3_port_drv = {
     49     /* fn_drv_init                   */ bcmi_td3_port_fn_drv_init,
     50     /* resource_set                  */ bcmi_xgs5_port_resource_set,
     51     /* resource_get                  */ bcmi_xgs5_port_resource_get,
     52     /* resource_multi_set            */ bcmi_xgs5_port_resource_multi_set,
     53     /* resource_speed_set            */ bcmi_xgs5_port_speed_set,
     54     /* resource_traverse             */ bcmi_xgs5_port_resource_traverse,
     55     /* port_redirect_set             */ NULL,
     56     /* port_redirect_get             */ NULL,
     57     /* port_enable_set               */ bcmi_xgs5_port_enable_set,
     58     /* encap_speed_check             */ bcmi_xgs5_port_encap_speed_check,
     59     /* force_lb_set                  */ NULL,
     60     /* force_lb_check                */ NULL,
     61     /* resource_status_update        */ bcmi_xgs5_port_resource_status_update,
     62     /* port_resource_speed_multi_set */ bcmi_xgs5_port_resource_speed_multi_set,
     63     /* device_speed_check            */ NULL,
     64 };
     65 
     66 /* Device programming routines */
     67 static bcmi_xgs5_port_func_t bcmi_td3_port_calls = {
     68     /* reconfigure_ports        */ soc_trident3_reconfigure_ports,
     69     /* soc_resource_init        */ bcmi_td3_port_soc_resource_init,
     70     /* port_resource_validate   */ bcmi_td3_port_resource_validate,
     71     /* pre_flexport_tdm         */ bcmi_td3_pre_flexport_tdm,
     72     /* post_flexport_tdm        */ bcmi_td3_post_flexport_tdm,
     73     /* port_macro_update        */ bcmi_td3_clport_update,
     74     /* port_enable              */ bcmi_td3_port_enable,
     75     /* port_disable             */ bcmi_td3_port_disable,
     76     /* no_tdm_speed_update      */ bcmi_td3_port_speed_1g_update,
     77     /* speed_ability_get        */ bcmi_td3_speed_ability_get,
     78     /* speed_mix_validate       */ bcmi_td3_speed_mix_validate,
     79     /* cos_map_update           */ bcmi_td3_port_cosmap_update,
     80 };
     81 
     82 static bcmi_xgs5_dev_info_t  *bcmi_td3_dev_info[SOC_MAX_NUM_DEVICES];
     83 
     84 /* HW Definitions */
     85 static bcmi_xgs5_port_drv_t    bcmi_td3_port_drv;
     86 
     87 static
     88 int (*td3_port_attach_exec[PORT_ATTACH_EXEC__MAX])(int unit, bcm_port_t port) = {
     89     /* MMU config init */
     90     &bcmi_td3_port_attach_mmu,
     91 
     92     /* PORT module (bcm_esw_port_init) */
     93     &bcmi_xgs5_port_attach_dscp,
     94     &bcmi_xgs5_port_attach_software,
     95     &bcmi_xgs5_port_attach_egr_vlan_action,
     96     &bcmi_xgs5_port_cfg_init,
     97     &bcmi_xgs5_port_attach_port_probe,
     98     &bcmi_xgs5_port_attach_frame_length_check,
     99     &bcmi_xgs5_port_attach_rcpu_mtu,
    100     &bcmi_xgs5_port_attach_outer_tpid,
    101     &bcmi_xgs5_port_egr_block_profile_init,
    102     &bcmi_xgs5_port_attach_vlan_protocol,
    103     &bcmi_xgs5_port_attach_eee,
    104     &bcmi_xgs5_port_attach_higig,
    105     &bcmi_xgs5_port_attach_port_info_cfg,
    106     &bcmi_xgs5_port_attach_egr_link_delay,
    107 
    108     /* Other modules related to port */
    109     &bcmi_xgs5_port_attach_stg,
    110     &bcmi_xgs5_port_attach_vlan,
    111     &bcmi_xgs5_port_attach_trunk,
    112     &bcm_td3_cosq_port_attach,
    113     &bcmi_xgs5_port_attach_linkscan,
    114     &bcmi_xgs5_port_attach_stat,
    115     &bcmi_td3_port_attach_stack,
    116     &bcmi_xgs5_port_attach_rate,
    117     &bcmi_xgs5_port_attach_field,
    118     &bcmi_xgs5_port_attach_mirror,
    119     &bcmi_td3_port_attach_l3,
    120     &bcmi_xgs5_port_attach_ipmc,
    121 #if defined(INCLUDE_L3)
    122     &bcm_th_ipmc_repl_port_attach,
    123 #else
    124     NULL,
    125 #endif
    126     &bcmi_xgs5_port_attach_mpls,
    127     &bcmi_xgs5_port_attach_mim,
    128 };
    129 
    130 static
    131 int (*td3_port_detach_exec[PORT_DETACH_EXEC__MAX])(int unit, bcm_port_t port) = {
    132     /* Other modules related to port */
    133 #if defined(INCLUDE_L3)
    134     &bcm_th_ipmc_repl_port_detach,
    135 #else
    136     NULL,
    137 #endif
    138     &bcmi_xgs5_port_detach_ipmc,
    139     &bcmi_xgs5_port_detach_mpls,
    140     &bcmi_xgs5_port_detach_mim,
    141     &bcmi_td3_port_detach_l3,
    142     &bcmi_xgs5_port_detach_mirror,
    143     &bcmi_xgs5_port_detach_field,
    144     &bcmi_xgs5_port_detach_rate,
    145     &bcmi_td3_port_detach_stack,
    146     &bcm_td3_cosq_port_detach,
    147     &bcmi_xgs5_port_detach_trunk,
    148     &bcmi_xgs5_port_detach_vlan,
    149     &bcmi_xgs5_port_detach_stg,
    150 
    151     /* PORT module (_bcm_esw_port_deinit) */
    152     &bcmi_td3_port_detach_asf,
    153     &bcmi_xgs5_port_detach_egr_link_delay,
    154     &bcmi_xgs5_port_detach_higig,
    155     &bcmi_xgs5_port_detach_eee,
    156     &bcmi_xgs5_port_detach_vlan_protocol,
    157     &bcmi_xgs5_port_egr_block_profile_init,
    158     &bcmi_xgs5_port_detach_phy,
    159     &bcmi_xgs5_port_detach_dscp,
    160     &bcmi_xgs5_port_cfg_init,
    161     &bcmi_xgs5_port_detach_egr_vlan_action,
    162     &bcmi_xgs5_port_detach_software,
    163 };
    164 
    165 /*
    166  * Function:
    167  *      bcmi_td3_init_condition_set
    168  * Purpose:
    169  *      Set the info of skiped modules during initialization in dev_info.
    170  * Parameters:
    171  *      unit - (IN) Unit number.
    172  *      dev_info - (OUT) Device info used during flexport
    173  * Returns:
    174  *      None
    175  * Notes:
    176  *      Must follow the _bcm_modules_init()
    177  */
    178 void
    179 _bcmi_td3_init_condition_set(int unit, bcmi_xgs5_dev_info_t *dev_info)
    180 {
    181     int init_all;
    182 
    183     init_all = soc_property_get(unit, "init_all_modules",
    184                                 (SAL_BOOT_BCMSIM) || (!SAL_BOOT_SIMULATION));
    185 
    186     if (soc_feature(unit, soc_feature_virtual_switching) ||
    187         soc_feature(unit, soc_feature_gport_service_counters) ||
    188         soc_feature(unit, soc_feature_fast_init) ||
    189         soc_feature(unit, soc_feature_int_common_init)){
    190         SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_COMMON);
    191     }
    192 
    193     SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_PORT);
    194 
    195     if (!(SAL_BOOT_SIMULATION &&
    196           soc_property_get(unit, spn_SKIP_L2_VLAN_INIT, 0))) {
    197         SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_L2);
    198         SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_VLAN);
    199     }
    200 
    201     SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_STG);
    202 
    203     if (init_all ||
    204         (soc_property_get(unit, "skip_cosq_init", 0) ? FALSE : TRUE)) {
    205         SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_COSQ);
    206     }
    207     if (init_all ||
    208         (soc_property_get(unit, "skip_stack_init", 0) ? FALSE : TRUE)) {
    209         SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_STK);
    210     }
    211     if (init_all ||
    212         (soc_property_get(unit, "skip_mirror_init", 0) ? FALSE : TRUE)) {
    213         SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_MIRROR);
    214     }
    215     if (init_all) {
    216         SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_TRUNK);
    217         SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_MCAST);
    218         SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_RATE);
    219 
    220         if (SOC_MEM_IS_VALID(unit, FP_UDF_TCAMm)) {
    221             SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_UDF);
    222         }
    223 
    224 #ifdef BCM_FIELD_SUPPORT
    225         if (SOC_MEM_IS_VALID(unit, IFP_RANGE_CHECKm)) {
    226             SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_RANGE);
    227         }
    228         if (soc_feature(unit, soc_feature_field)) {
    229             SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_FIELD);
    230             SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_AUTH);
    231         }
    232 #endif
    233 
    234 #ifdef INCLUDE_L3
    235         if (soc_feature(unit, soc_feature_failover)) {
    236             SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_FAILOVER);
    237         }
    238 
    239         if (soc_feature(unit, soc_feature_l3) &&
    240             soc_property_get(unit, spn_L3_ENABLE, 1)) {
    241             SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_L3);
    242         }
    243         if (soc_feature(unit, soc_feature_ip_mcast)) {
    244             SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_IPMC);
    245         }
    246 
    247 #ifdef BCM_MPLS_SUPPORT
    248         if (soc_feature(unit, soc_feature_mpls)) {
    249             SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_MPLS);
    250         }
    251 #endif
    252         if (soc_feature(unit, soc_feature_mim)) {
    253             SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_MIM);
    254         }
    255         if (soc_feature(unit, soc_feature_wlan)) {
    256             SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_WLAN);
    257         }
    258         SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_PROXY);
    259 
    260         if (soc_feature(unit, soc_feature_subport) ||
    261             soc_feature(unit, soc_feature_linkphy_coe) ||
    262             soc_feature(unit, soc_feature_subtag_coe) ||
    263             soc_feature(unit, soc_feature_hgproxy_subtag_coe)) {
    264             SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_SUBPORT);
    265         }
    266         if (soc_feature(unit, soc_feature_trill)) {
    267             SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_TRILL);
    268         }
    269         if (soc_feature(unit, soc_feature_niv)) {
    270             SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_NIV);
    271         }
    272         if (soc_feature(unit, soc_feature_l2gre)) {
    273             SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_L2GRE);
    274         }
    275         if (soc_feature(unit, soc_feature_vxlan)) {
    276             SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_VXLAN);
    277         }
    278         if (soc_feature(unit, soc_feature_port_extension)) {
    279             SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_EXTENDER);
    280         }
    281         SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_MULTICAST);
    282 #endif
    283         if (soc_feature(unit, soc_feature_qos_profile)) {
    284             SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_QOS);
    285         }
    286         if (soc_feature(unit, soc_feature_oam) ||
    287             soc_feature(unit, soc_feature_fp_based_oam)) {
    288             SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_OAM);
    289         }
    290 #ifdef INCLUDE_PTP
    291         if (soc_feature(unit, soc_feature_ptp)) {
    292             SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_PTP);
    293         }
    294 #endif
    295 #ifdef INCLUDE_BFD
    296         if (soc_feature(unit, soc_feature_bfd)) {
    297             SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_BFD);
    298         }
    299 #endif
    300         if (soc_feature(unit, soc_feature_fcoe)) {
    301             SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_FCOE);
    302         }
    303     }
    304 
    305     SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_LINKSCAN);
    306     SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_STAT);
    307 #ifdef INCLUDE_KNET
    308     SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_KNET);
    309 #endif
    310     SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_TX);
    311     SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_RX);
    312 #ifdef INCLUDE_REGEX
    313     if (soc_feature(unit, soc_feature_regex)) {
    314         SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_REGEX);
    315     }
    316 #endif
    317     if (soc_feature(unit, soc_feature_time_support)) {
    318         SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_TIME);
    319     }
    320     /* Service meter */
    321     if (soc_feature(unit, soc_feature_global_meter)) {
    322         SHR_BITSET(dev_info->init_cond, SHR_BPROF_BCM_GLB_METER);
    323     }
    324     if (soc_property_get(unit, "skip_ipmc_init", 0)) {
    325         SHR_BITCLR(dev_info->init_cond, SHR_BPROF_BCM_IPMC);
    326     }
    327 
    328     if (soc_property_get(unit, "skip_mpls_init", 0)) {
    329         SHR_BITCLR(dev_info->init_cond, SHR_BPROF_BCM_MPLS);
    330     }
    331 
    332     if (soc_property_get(unit, "skip_mim_init", 0)) {
    333         SHR_BITCLR(dev_info->init_cond, SHR_BPROF_BCM_MIM);
    334     }
    335     if (soc_property_get(unit, "skip_trunk_init", 0)) {
    336         SHR_BITCLR(dev_info->init_cond, SHR_BPROF_BCM_TRUNK);
    337     }
    338     if (soc_property_get(unit, "skip_mirror_init", 0)) {
    339         SHR_BITCLR(dev_info->init_cond, SHR_BPROF_BCM_MIRROR);
    340     }
    341     return;
    342 
    343 }
    344 
    345 
    346 /*
    347  * Function:
    348  *      bcmi_td3_port_dev_info_init
    349  * Purpose:
    350  *      Initialize the device info.
    351  * Parameters:
    352  *      unit - (IN) Unit number.
    353  * Returns:
    354  *      BCM_E_xxx
    355  * Notes:
    356  */
    357 int
    358 bcmi_td3_port_dev_info_init(int unit)
    359 {
    360     bcmi_xgs5_dev_info_t *dev_info;
    361     soc_info_t *si = &SOC_INFO(unit);
    362     uint32 pipe_lr_bw;
    363     int alloc_size;
    364     int pipe, phy_port, blk, bindex;
    365     int i, cntmaxsize;
    366 
    367     /* Free bcmi_td3_dev_info[unit] if already allocated */
    368     if (bcmi_td3_dev_info[unit]) {
    369         sal_free(bcmi_td3_dev_info[unit]);
    370         bcmi_td3_dev_info[unit] = NULL;
    371     }
    372 
    373     /* Allocate memory for main SW data structure */
    374     alloc_size = sizeof(bcmi_xgs5_dev_info_t) +
    375                  (sizeof(bcmi_xgs5_phy_port_t) * TRIDENT3_PHY_PORTS_PER_DEV);
    376     dev_info = sal_alloc(alloc_size, "bcmi_td3_dev_info");
    377     if (dev_info == NULL) {
    378         return BCM_E_MEMORY;
    379     }
    380     sal_memset(dev_info, 0, alloc_size);
    381     dev_info->phy_port_info = (bcmi_xgs5_phy_port_t *)&dev_info[1];
    382     bcmi_td3_dev_info[unit] = dev_info;
    383 
    384     /* Clear data structure */
    385 
    386     /* Device information init */
    387     dev_info = bcmi_td3_dev_info[unit];
    388     dev_info->num_pipe = _TD3_PIPES_PER_DEV;
    389     dev_info->num_tsc = _TD3_PBLKS_PER_DEV(unit);
    390     dev_info->phy_ports_max = TRIDENT3_PHY_PORTS_PER_DEV;
    391     dev_info->mmu_lossless = 0;
    392     dev_info->asf_prof_default = _SOC_ASF_MEM_PROFILE_SIMILAR;
    393     dev_info->pipe_bound = 1;
    394     for (pipe = 0; pipe < _TD3_PIPES_PER_DEV; pipe++) {
    395         /* First logical port in pipe   */
    396         dev_info->pipe_log_port_base[pipe] = TRIDENT3_PHY_PORTS_PER_PIPE * pipe;
    397 
    398         /* First physical port in pipe  */
    399         dev_info->pipe_phy_port_base[pipe] = TRIDENT3_GPHY_PORTS_PER_PIPE * pipe +
    400                                              (pipe ? 1 : 0);
    401 
    402         dev_info->ports_pipe_max[pipe] = TRIDENT3_PHY_PORTS_PER_PIPE;
    403     }
    404     /* 10G is the min speed in TDM calendar program.
    405      * TDM eventually sets minimum speed to 10G in TDM calendar.
    406      */
    407     dev_info->tdm_speed_min = SPEED_1G;
    408 
    409     /* 10G is the min speed in TDM calculations */
    410     dev_info->tdm_pipe_lr_bw_limit_checker_speed_min = SPEED_10G;
    411 
    412     cntmaxsize = soc_property_get(unit, spn_BCM_STAT_JUMBO, 1518);
    413     if (cntmaxsize > si->max_mtu) {
    414         cntmaxsize = si->max_mtu;
    415     }
    416     dev_info->cntmaxsize_xl = cntmaxsize;
    417     dev_info->cntmaxsize_cl = cntmaxsize;
    418 
    419     dev_info->restriction_mask = BCMI_XGS5_FLEXPORT_RESTRICTION_PIPE_BANDWIDTH |
    420                             BCMI_XGS5_FLEXPORT_RESTRICTION_MIX_LR_OVS_DEV |
    421                             BCMI_XGS5_FLEXPORT_RESTRICTION_SPEED_CLASS |
    422                             BCMI_XGS5_FLEXPORT_RESTRICTION_PM_OVS_MIX_SISTER |
    423                             BCMI_XGS5_FLEXPORT_RESTRICTION_PM_MIX_ETH_HIGIG |
    424                             BCMI_XGS5_FLEXPORT_RESTRICTION_PM_LR_MIX_SISTER |
    425                             BCMI_XGS5_FLEXPORT_RESTRICTION_PM_HG_MIX_SPEED |
    426                             BCMI_XGS5_FLEXPORT_RESTRICTION_PM_SINGLE_PLL;
    427 
    428     dev_info->encap_mask = BCM_PA_ENCAP_IEEE | BCM_PA_ENCAP_HIGIG2;
    429 
    430     /*
    431      * Restriction 13:No port configurations with more than 4 port speed
    432      *                classes are supported in LR.
    433      * Restriction 15:All port configurations with 1-3 port speed classes are
    434      *                supported, except configurations that contain both 20G
    435      *                and 25G port speeds.
    436      * OS speed class exception: 5 speed classes (10/25/40/50/100) are supported
    437      *                           in oversub mode only.
    438      */
    439     dev_info->speed_class.speed_class_num = si->oversub_mode ?
    440                         _TD3_TDM_OS_SPEED_CLASS_MAX : _TD3_TDM_LR_SPEED_CLASS_MAX;
    441     
    442     dev_info->speed_class.no_mix_speed_mask = SOC_PA_SPEED_20GB
    443                                                 | SOC_PA_SPEED_25GB;
    444 
    445     dev_info->port_ratio_mask = BCMI_XGS5_PORT_RATIO_SINGLE |
    446                                     BCMI_XGS5_PORT_RATIO_DUAL_1_1 |
    447                                     BCMI_XGS5_PORT_RATIO_DUAL_2_1 |
    448                                     BCMI_XGS5_PORT_RATIO_DUAL_1_2 |
    449                                     BCMI_XGS5_PORT_RATIO_TRI_023_2_1_1 |
    450                                     BCMI_XGS5_PORT_RATIO_TRI_023_4_1_1 |
    451                                     BCMI_XGS5_PORT_RATIO_TRI_012_1_1_2 |
    452                                     BCMI_XGS5_PORT_RATIO_TRI_012_1_1_4 |
    453                                     BCMI_XGS5_PORT_RATIO_QUAD;
    454 
    455     /* Set max line rate bandwidth per pipeline */
    456     BCM_IF_ERROR_RETURN
    457         (soc_td3_max_lr_bandwidth(unit, &pipe_lr_bw));
    458     dev_info->pipe_lr_bw = pipe_lr_bw * 1000;
    459 
    460     /* Set valid speeds for 1/2/4 Lanes */
    461     BCM_IF_ERROR_RETURN
    462         (soc_td3_support_speeds(unit, 1, &dev_info->speed_valid[1]));
    463     BCM_IF_ERROR_RETURN
    464         (soc_td3_support_speeds(unit, 2, &dev_info->speed_valid[2]));
    465     BCM_IF_ERROR_RETURN
    466         (soc_td3_support_speeds(unit, 4, &dev_info->speed_valid[4]));
    467 
    468     /*
    469      * Set physical port info:
    470      *  - Port lane capability
    471      *  - Port is enabled for flexport
    472      *  - pipe
    473      */
    474     for (phy_port = 0; phy_port < TRIDENT3_PHY_PORTS_PER_DEV; phy_port++) {
    475         /* Set information to invalid */
    476         dev_info->phy_port_info[phy_port].pipe = -1;
    477     }
    478 
    479     /* Flexport is not supported for CPU/LB/MNG ports, so skip CPU/LB/MNG */
    480     for (phy_port = 1; phy_port <= TRIDENT3_PHY_PORTS_PER_DEV; phy_port++) {
    481         /* Check for end of port list */
    482         if (SOC_PORT_BLOCK(unit, phy_port) < 0 &&
    483             SOC_PORT_BINDEX(unit, phy_port) < 0) {
    484             break;
    485         }
    486         /* Set pipe information */
    487         dev_info->phy_port_info[phy_port].pipe =
    488                                     (phy_port - 1) / TRIDENT3_GPHY_PORTS_PER_PIPE;
    489 
    490         for (i = 0; i < SOC_DRIVER(unit)->port_num_blktype; i++) {
    491             blk = SOC_PORT_IDX_BLOCK(unit, phy_port, i);
    492             bindex = SOC_PORT_IDX_BINDEX(unit, phy_port, i);
    493 
    494             if ((blk < 0) || (bindex < 0)) {
    495                 continue;
    496             }
    497 
    498             if (SOC_BLOCK_TYPE(unit, blk) == SOC_BLK_CLPORT) {
    499                 /* Set port lane capabilites */
    500                 dev_info->phy_port_info[phy_port].lanes_valid =
    501                                                 BCMI_XGS5_PORT_LANES_1;
    502                 if (bindex == 0) {
    503                     dev_info->phy_port_info[phy_port].lanes_valid |=
    504                         BCMI_XGS5_PORT_LANES_2 | BCMI_XGS5_PORT_LANES_4;
    505                 } else if (bindex == 2) {
    506                     dev_info->phy_port_info[phy_port].lanes_valid |=
    507                                                 BCMI_XGS5_PORT_LANES_2;
    508                 }
    509 
    510                 if (SHR_BITGET(si->flexible_pm_bitmap,blk)) {
    511                     dev_info->phy_port_info[phy_port].flex = 1;
    512                 }
    513             }
    514         } /* for port_num_blktype */
    515         dev_info->phy_port_info[phy_port].max_lane_speed = 27000;
    516     }
    517 
    518     /* For TD3 encap type change (i.e calendar type from Ethernet type to
    519      * HiGig type, or vice versa)  should also be detected as a
    520      * flexport trigger condition
    521      */
    522     dev_info->encap_change_flex = 1;
    523 
    524     /* Init condition */
    525     _bcmi_td3_init_condition_set(unit, dev_info);
    526 
    527     return BCM_E_NONE;
    528 }
    529 
    530 
    531 
    532 /*
    533  * Function:
    534  *      bcmi_td3_port_fn_drv_init
    535  * Purpose:
    536  *      Initialize the Port function driver.
    537  * Parameters:
    538  *      unit - (IN) Unit number.
    539  * Returns:
    540  *      BCM_E_xxx
    541  * Notes:
    542  */
    543 int
    544 bcmi_td3_port_fn_drv_init(int unit)
    545 {
    546    int phase_pos, present;
    547 
    548     BCM_IF_ERROR_RETURN
    549         (bcmi_td3_port_dev_info_init(unit));
    550 
    551     /* BCMI Driver init */
    552     bcmi_td3_port_drv.port_calls = &bcmi_td3_port_calls;
    553     bcmi_td3_port_drv.dev_info[unit] = bcmi_td3_dev_info[unit];
    554 
    555 
    556     sal_memcpy(bcmi_td3_port_drv.port_calls->port_attach_exec,
    557                td3_port_attach_exec,
    558                sizeof(bcmi_td3_port_drv.port_calls->port_attach_exec));
    559 
    560     sal_memcpy(bcmi_td3_port_drv.port_calls->port_detach_exec,
    561                td3_port_detach_exec,
    562                sizeof(bcmi_td3_port_drv.port_calls->port_detach_exec));
    563 
    564     /* Initialize Common XGS5 Port module */
    565     BCM_IF_ERROR_RETURN
    566         (bcmi_xgs5_port_fn_drv_init(unit,
    567                                     &bcm_td3_port_drv,
    568                                     &bcmi_td3_port_drv,
    569                                     NULL));
    570 
    571     BCM_IF_ERROR_RETURN(soc_check_flex_phase(unit, td3_flexport_phases,
    572                                              soc_trident3_flex_top_port_down,
    573                                              &present));
    574     /* Detach port enable/disable in DV Flexport */
    575     if (present) {
    576         BCM_IF_ERROR_RETURN
    577             (soc_detach_flex_phase(unit, td3_flexport_phases,
    578                                    soc_trident3_flex_top_port_down,
    579                                    &phase_pos));
    580     }
    581     BCM_IF_ERROR_RETURN(soc_check_flex_phase(unit, td3_flexport_phases,
    582                                              soc_trident3_flex_top_port_up,
    583                                              &present));
    584     if (present) {
    585         BCM_IF_ERROR_RETURN
    586             (soc_detach_flex_phase(unit, td3_flexport_phases,
    587                                    soc_trident3_flex_top_port_up,
    588                                    &phase_pos));
    589     }
    590     return BCM_E_NONE;
    591 }
    592 
    593 /*
    594  * Function:
    595  *      bcmi_td3_port_soc_resource_init
    596  * Purpose:
    597  *      Initialize SOC Port Structure.
    598  *      This includes:
    599  *          Copy Port information from BCM port resource array.
    600  *          Set correct pipe, MMU port, IDB port for new logical port.
    601  * Parameters:
    602  *      unit         - (IN)  Unit number.
    603  *      nport        - (IN)  Number of elements in array resource.
    604  *      resource     - (IN)  BCM Port resource configuration array.
    605  *      soc_resource - (OUT) SOC Port resource array.
    606  * Returns:
    607  *      BCM_E_xxx
    608  * Notes:
    609  */
    610 int
    611 bcmi_td3_port_soc_resource_init(int unit, int nport,
    612                                  bcm_port_resource_t *resource,
    613                                  soc_port_resource_t *soc_resource)
    614 {
    615     int i;
    616     int logic_port, idb_port, mmu_port, pipe;
    617     soc_info_t *si = &SOC_INFO(unit);
    618 
    619     /*
    620      * SOC Port Structure initialization
    621      */
    622 
    623     /* Clear data structure */
    624     sal_memset(soc_resource, 0, sizeof(soc_port_resource_t) * nport);
    625 
    626     /* Copy initial information */
    627     for (i = 0; i < nport; i++) {
    628         logic_port = resource[i].port;
    629 
    630         pipe = logic_port / TRIDENT3_PHY_PORTS_PER_PIPE;
    631         idb_port = (logic_port % TRIDENT3_PHY_PORTS_PER_PIPE) - 1;
    632         mmu_port = (pipe << 7) | idb_port;
    633 
    634         soc_resource[i].flags = resource[i].flags;
    635         soc_resource[i].logical_port = logic_port;
    636         soc_resource[i].physical_port = resource[i].physical_port;
    637         soc_resource[i].speed = resource[i].speed;
    638         soc_resource[i].num_lanes = resource[i].lanes;
    639         soc_resource[i].encap = resource[i].encap;
    640         soc_resource[i].pipe = pipe;
    641         soc_resource[i].idb_port = idb_port;
    642         soc_resource[i].mmu_port = mmu_port;
    643         /* TD3 does NOT support port configuration with a mix of line-rate ports
    644          * and oversubscribed ports. */
    645         soc_resource[i].oversub = SOC_PBMP_IS_NULL(si->oversub_pbm) ? 0 : 1;
    646 
    647         if (resource[i].speed >= 40000) {
    648             soc_resource[i].hsp = 1;
    649 	    }
    650     }
    651 
    652     return BCM_E_NONE;
    653 }
    654 
    655 /* Function:
    656  *      bcmi_td3_port_resource_validate
    657  * Purpose:
    658  *      Validate that the given FlexPort operations is valid.
    659  * Parameters:
    660  *      unit                 - (IN)  Unit number.
    661  *      port_schedule_state  - (OUT) Port resource state.
    662  * Returns:
    663  *      BCM_E_xxx
    664  * Notes:
    665  */
    666 int
    667 bcmi_td3_port_resource_validate(int unit,
    668                             soc_port_schedule_state_t *port_schedule_state)
    669 {
    670     soc_port_resource_t *pr;
    671     int nport = port_schedule_state->nport;
    672     int i, pmap_err = 0;
    673     int port;       /* Logical port associated to physical port */
    674     int phy_port;   /* Physical port associated logical port */
    675 
    676     /* Allow only correct logical port to physical port association. */
    677     for (i = 0, pr = port_schedule_state->resource; i < nport; i++, pr++) {
    678         if (pr->physical_port == -1) {
    679             continue;
    680         }
    681         port = pr->logical_port;
    682         phy_port = pr->physical_port;
    683         if ((port >= 0) && (port <= 64)) {
    684             if (port != phy_port) {
    685                 pmap_err = 1;
    686                 break;
    687             }
    688         } else if((port == 65) && (phy_port != 130)) {
    689             pmap_err = 1;
    690             break;
    691         } else if ((port == 66) && (phy_port != 129)) {
    692             pmap_err = 1;
    693             break;
    694         } else if((port >= 67) && (port <= 130)) {
    695             if (port != phy_port + 2) {
    696                 pmap_err = 1;
    697                 break;
    698            }
    699         } else if((port == 131) && (phy_port != 131)) {
    700             pmap_err = 1;
    701             break;
    702         }
    703     }
    704     if (pmap_err) {
    705         LOG_CLI((BSL_META_U(unit,
    706                             "Port %d: Invalid logical port to physical port mapping.\n"),
    707                             port));
    708         return BCM_E_PORT;
    709     }
    710     return BCM_E_NONE;
    711 }
    712 
    713 /*
    714  * Function:
    715  *      bcmi_td3_pre_flexport_tdm
    716  * Purpose:
    717  *      Pass TDM information pre FlexPort to DV FlexPort API
    718  * Parameters:
    719  *      unit                 - (IN)  Unit number.
    720  *      port_schedule_state  - (OUT) Port resource state.
    721  * Returns:
    722  *      BCM_E_xxx
    723  * Notes:
    724  */
    725 int
    726 bcmi_td3_pre_flexport_tdm(int unit,
    727                             soc_port_schedule_state_t *port_schedule_state)
    728 {
    729     port_schedule_state->is_flexport = 1;
    730 
    731     BCM_IF_ERROR_RETURN
    732         (soc_td3_port_schedule_tdm_init(unit, port_schedule_state));
    733     return BCM_E_NONE;
    734 }
    735 
    736 /*
    737  * Function:
    738  *      bcmi_td3_post_flexport_tdm
    739  * Purpose:
    740  *      Update TDM information in SOC with post FlexPort TDM state return from
    741  *      DV FlexPort API.
    742  * Parameters:
    743  *      unit                 - (IN)  Unit number.
    744  *      port_schedule_state  - (IN) Port resource state.
    745  * Returns:
    746  *      BCM_E_xxx
    747  * Notes:
    748  */
    749 int
    750 bcmi_td3_post_flexport_tdm(int unit,
    751                             soc_port_schedule_state_t *port_schedule_state)
    752 {
    753     BCM_IF_ERROR_RETURN
    754         (soc_td3_soc_tdm_update(unit, port_schedule_state));
    755     return BCM_E_NONE;
    756 }
    757 
    758 /*
    759  * Function:
    760  *      bcmi_td3_clport_update
    761  * Purpose:
    762  *      Update CLPORT.
    763  * Parameters:
    764  *      unit                 - (IN)  Unit number.
    765  *      port_schedule_state  - (IN) Port resource state.
    766  * Returns:
    767  *      BCM_E_xxx
    768  * Notes:
    769  */
    770 int
    771 bcmi_td3_clport_update(int unit,
    772                             soc_port_schedule_state_t *port_schedule_state)
    773 {
    774     soc_info_t *si = &SOC_INFO(unit);
    775     soc_port_resource_t *pr;
    776     int i, nport;
    777     int phy_port, logic_port, phy_port_base;
    778     int blk;
    779     int clport, lane, mode;
    780     SHR_BITDCL  pm_bmp[_SHR_BITDCLSIZE(SOC_MAX_NUM_BLKS)];
    781     soc_port_map_type_t *in_port_map;
    782     uint32 rval;
    783     static soc_field_t port_fields[TRIDENT3_PORTS_PER_PBLK] = {
    784         PORT0f, PORT1f, PORT2f, PORT3f
    785     };
    786     static const int mode_encodings[SOC_TD3_PORT_RATIO_COUNT] = {
    787         4, 3, 3, 3, 2, 2, 1, 1, 0
    788     };
    789 
    790     SHR_BITCLR_RANGE(pm_bmp, 0, SOC_MAX_NUM_BLKS);
    791 
    792     nport = port_schedule_state->nport;
    793     in_port_map = &port_schedule_state->in_port_map;
    794 
    795     for (i = 0, pr = port_schedule_state->resource; i < nport; i++, pr++) {
    796         if (!(pr->op & ~(BCMI_XGS5_PORT_RESOURCE_OP_SPEED|
    797                       BCMI_XGS5_PORT_RESOURCE_OP_ENCAP))) {
    798             continue;
    799         }
    800 
    801         logic_port = pr->logical_port;
    802         phy_port = pr->physical_port == -1 ?
    803                     in_port_map->port_l2p_mapping[logic_port] :
    804                     pr->physical_port;
    805         blk = SOC_PORT_IDX_BLOCK(unit, phy_port, 0);
    806         SHR_BITSET(pm_bmp, blk);
    807     }
    808 
    809     SHR_BIT_ITER(pm_bmp, SOC_MAX_NUM_BLKS, blk) {
    810         if (!SOC_INFO(unit).block_valid[blk]) {
    811             continue;
    812         }
    813         logic_port = SOC_BLOCK_PORT(unit, blk);
    814         clport = SOC_BLOCK_NUMBER(unit, blk);
    815         phy_port_base = PORT_BLOCK_BASE_PORT(logic_port);
    816 
    817         /* Assert CLPORT soft reset */
    818         rval = 0;
    819         for (lane = 0; lane < TRIDENT3_PORTS_PER_PBLK; lane++) {
    820             if (si->port_p2l_mapping[phy_port_base + lane] != -1) {
    821                 soc_reg_field_set(unit, CLPORT_SOFT_RESETr, &rval,
    822                                   port_fields[lane], 1);
    823             }
    824         }
    825         SOC_IF_ERROR_RETURN(WRITE_CLPORT_SOFT_RESETr(unit, logic_port, rval));
    826 
    827         /* Set port mode */
    828         soc_td3_tdm_get_port_ratio(unit, port_schedule_state, clport,
    829                                          &mode,
    830                                          0);
    831         SOC_IF_ERROR_RETURN(soc_reg32_get(unit, CLPORT_MODE_REGr,
    832                                                   logic_port, 0, &rval));
    833         soc_reg_field_set(unit, CLPORT_MODE_REGr, &rval, XPORT0_CORE_PORT_MODEf,
    834                           mode_encodings[mode]);
    835         soc_reg_field_set(unit, CLPORT_MODE_REGr, &rval, XPORT0_PHY_PORT_MODEf,
    836                           mode_encodings[mode]);
    837         SOC_IF_ERROR_RETURN(WRITE_CLPORT_MODE_REGr(unit, logic_port, rval));
    838 
    839         /* De-assert XLPORT soft reset */
    840         SOC_IF_ERROR_RETURN(WRITE_CLPORT_SOFT_RESETr(unit, logic_port, 0));
    841     }
    842     return BCM_E_NONE;
    843 }
    844 
    845 int
    846 bcmi_td3_port_attach_mmu(int unit, int port)
    847 {
    848     if (IS_CPU_PORT(unit, port) || IS_LB_PORT(unit, port) ||
    849         IS_MANAGEMENT_PORT(unit, port)) {
    850         return BCM_E_PARAM;
    851     }
    852 
    853     /* Assign the base queues and number of queues for the specified port. */
    854     BCM_IF_ERROR_RETURN
    855         (soc_trident3_num_cosq_init_port(unit, port));
    856 
    857     /* Enable enqueing packets to the port */
    858     SOC_IF_ERROR_RETURN(
    859         soc_td3_port_mmu_tx_enable_set(unit, port, 1));
    860     SOC_IF_ERROR_RETURN(
    861         soc_td3_port_mmu_rx_enable_set(unit, port, 1));
    862 
    863     /* Reconfigure THDI, THDO settings */
    864     BCM_IF_ERROR_RETURN
    865         (soc_td3_mmu_config_init_port(unit, port));
    866 
    867     return BCM_E_NONE;
    868 }
    869 
    870 int
    871 bcmi_td3_port_attach_stack(int unit, int port)
    872 {
    873     modport_map_subport_entry_t subport_entry;
    874     modport_map_subport_mirror_entry_t subport_m_entry;
    875 
    876     /* Configure logical subport numbers */
    877     sal_memset(&subport_entry, 0, sizeof(subport_entry));
    878     soc_MODPORT_MAP_SUBPORTm_field32_set(unit, &subport_entry, ENABLEf, 1);
    879     soc_MODPORT_MAP_SUBPORTm_field32_set(unit, &subport_entry, DESTf, port);
    880     SOC_IF_ERROR_RETURN
    881         (WRITE_MODPORT_MAP_SUBPORTm(unit, MEM_BLOCK_ALL, port, &subport_entry));
    882 
    883     /* Configure logical subport mirror numbers */
    884     sal_memset(&subport_m_entry, 0, sizeof(subport_m_entry));
    885     soc_MODPORT_MAP_SUBPORT_M0m_field32_set(unit, &subport_m_entry, ENABLEf, 1);
    886     soc_MODPORT_MAP_SUBPORT_M0m_field32_set(unit,
    887                                             &subport_m_entry, DESTf, port);
    888     SOC_IF_ERROR_RETURN
    889         (WRITE_MODPORT_MAP_SUBPORT_MIRRORm(
    890             unit, MEM_BLOCK_ALL, port, &subport_m_entry));
    891 
    892     BCM_IF_ERROR_RETURN
    893             (bcmi_xgs5_port_attach_stack(unit, port));
    894 
    895     return BCM_E_NONE;
    896 }
    897 
    898 int
    899 bcmi_td3_port_detach_stack(int unit, int port)
    900 {
    901     modport_map_subport_entry_t subport_entry;
    902     modport_map_subport_mirror_entry_t subport_m_entry;
    903 
    904     /* Clear logical subport numbers */
    905     sal_memset(&subport_entry, 0, sizeof(subport_entry));
    906     SOC_IF_ERROR_RETURN
    907         (WRITE_MODPORT_MAP_SUBPORTm(unit, MEM_BLOCK_ALL, port, &subport_entry));
    908 
    909     /* Clear logical subport mirror numbers */
    910     sal_memset(&subport_m_entry, 0, sizeof(subport_m_entry));
    911     SOC_IF_ERROR_RETURN
    912         (WRITE_MODPORT_MAP_SUBPORT_MIRRORm(
    913             unit, MEM_BLOCK_ALL, port, &subport_m_entry));
    914 
    915     BCM_IF_ERROR_RETURN
    916             (bcmi_xgs5_port_detach_stack(unit, port));
    917 
    918     return BCM_E_NONE;
    919 }
    920 
    921 /*
    922  * Function:
    923  *      bcmi_td3_port_attach_l3
    924  * Purpose:
    925  *      Enable IPv4, IPv6 on port, add to default vfi membership profile
    926  * Parameters:
    927  *      unit    - (IN) Unit number.
    928  *      port    - (IN) Logical port.
    929  * Returns:
    930  *      SOC_E_XXX
    931  */
    932 int
    933 bcmi_td3_port_attach_l3(int unit, bcm_port_t port)
    934 {
    935 #ifdef INCLUDE_L3
    936     int rv = BCM_E_NONE;
    937     /* L3 */
    938     if (soc_feature(unit, soc_feature_l3) &&
    939         soc_property_get(unit, spn_L3_ENABLE, 1) &&
    940         !IS_ST_PORT(unit, port)) {
    941 
    942         BCM_IF_ERROR_RETURN
    943             (bcm_esw_port_control_set(unit, port, bcmPortControlIP4, 1));
    944         BCM_IF_ERROR_RETURN
    945             (bcm_esw_port_control_set(unit, port, bcmPortControlIP6, 1));
    946     }
    947     if (soc_feature(unit, soc_feature_l3) &&
    948         soc_property_get(unit, spn_L3_ENABLE, 1)) {
    949    /* VFI */
    950         rv = _bcm_td2p_vfi_membership_port_attach(unit, port);
    951         if (BCM_FAILURE(rv)) {
    952             LOG_ERROR(BSL_LS_BCM_PORT,
    953                      (BSL_META_U(unit,
    954                                  "Unable to add port to default VFI membership "
    955                                  "unit=%d port=%d rv=%d\n"),
    956                       unit, port, rv));
    957             return rv;
    958         }
    959     }
    960 #endif /* INCLUDE_L3 */
    961     return BCM_E_NONE;
    962 }
    963 
    964 /*
    965  * Function:
    966  *      bcmi_td3_port_detach_l3
    967  * Purpose:
    968  *      Disable IPv4, IPv6 on port,
    969  *      remove port from default  vfi membership profile
    970  * Parameters:
    971  *      unit    - (IN) Unit number.
    972  *      port    - (IN) Logical port.
    973  * Returns:
    974  *      SOC_E_XXX
    975  */
    976 int
    977 bcmi_td3_port_detach_l3(int unit, bcm_port_t port)
    978 {
    979 #ifdef INCLUDE_L3
    980     int rv = BCM_E_NONE;
    981     /* L3 */
    982     if (soc_feature(unit, soc_feature_l3) &&
    983         soc_property_get(unit, spn_L3_ENABLE, 1) &&
    984         !IS_ST_PORT(unit, port)) {
    985 
    986         BCM_IF_ERROR_RETURN
    987             (bcm_esw_port_control_set(unit, port, bcmPortControlIP4, 0));
    988         BCM_IF_ERROR_RETURN
    989             (bcm_esw_port_control_set(unit, port, bcmPortControlIP6, 0));
    990     }
    991     if (soc_feature(unit, soc_feature_l3) &&
    992         soc_property_get(unit, spn_L3_ENABLE, 1)) {
    993     /* VFI */
    994        rv = _bcm_td2p_vfi_membership_port_detach(unit, port);
    995        if (BCM_FAILURE(rv)) {
    996            LOG_ERROR(BSL_LS_BCM_PORT,
    997                      (BSL_META_U(unit,
    998                                  "Unable to clear port in default VFI membership "
    999                                  "unit=%d port=%d rv=%d\n"),
   1000                       unit, port, rv));
   1001            return rv;
   1002        }
   1003     }
   1004 #endif /* INCLUDE_L3 */
   1005     return BCM_E_NONE;
   1006 }
   1007 
   1008 /*
   1009  * Function:
   1010  *      bcmi_td3_port_detach_asf
   1011  * Purpose:
   1012  *      Update ASF when port deleted during Flexport operations.
   1013  * Parameters:
   1014  *      unit                 - (IN)  Unit number.
   1015  *      port                 - (IN)  Logical port number.
   1016  * Returns:
   1017  *      BCM_E_xxx
   1018  * Notes:
   1019  */
   1020 int
   1021 bcmi_td3_port_detach_asf(int unit, bcm_port_t port)
   1022 {
   1023     BCM_IF_ERROR_RETURN
   1024         (soc_td3_port_asf_detach(unit, port));
   1025 
   1026     return BCM_E_NONE;
   1027 }
   1028 
   1029 /*
   1030  * Function:
   1031  *      bcmi_td3_port_enable
   1032  * Purpose:
   1033  *      Enable port.
   1034  * Parameters:
   1035  *      unit                 - (IN)  Unit number.
   1036  *      port_schedule_state  - (IN) Port resource state.
   1037  * Returns:
   1038  *      BCM_E_xxx
   1039  * Notes:
   1040  *      This function should only be called with PORTMOD enabled
   1041  */
   1042 int
   1043 bcmi_td3_port_enable(int unit,
   1044                              soc_port_schedule_state_t *port_schedule_state)
   1045 {
   1046     int i, nport, rv = BCM_E_NONE;
   1047     bcm_port_t *port;
   1048 
   1049     nport = port_schedule_state->nport;
   1050 
   1051     port = sal_alloc(nport * sizeof(bcm_port_t), "port array");
   1052     if (port == NULL) {
   1053         return BCM_E_MEMORY;
   1054     }
   1055     for (i = 0; i < nport; i++) {
   1056         port[i] = port_schedule_state->resource[i].logical_port;
   1057     }
   1058 
   1059     if (BCM_SUCCESS(rv) && (!(SAL_BOOT_XGSSIM || SAL_BOOT_BCMSIM))) {
   1060         rv = soc_trident3_flex_mmu_port_up(unit, port_schedule_state);
   1061     }
   1062     if (BCM_SUCCESS(rv)) {
   1063         rv = soc_trident3_flex_ep_port_up(unit, port_schedule_state);
   1064     }
   1065     if (BCM_SUCCESS(rv)) {
   1066         rv = soc_trident3_flex_idb_port_up(unit, port_schedule_state);
   1067     }
   1068     if (BCM_SUCCESS(rv)) {
   1069         rv = bcmi_esw_portctrl_mac_up(unit, nport, port);
   1070     }
   1071     sal_free(port);
   1072     return rv;
   1073 }
   1074 
   1075 /*
   1076  * Function:
   1077  *      bcmi_td3_port_disable
   1078  * Purpose:
   1079  *      Disable port.
   1080  * Parameters:
   1081  *      unit                 - (IN)  Unit number.
   1082  *      port_schedule_state  - (IN) Port resource state.
   1083  * Returns:
   1084  *      BCM_E_xxx
   1085  * Notes:
   1086  *      This function should only be called with PORTMOD enabled
   1087  */
   1088 int
   1089 bcmi_td3_port_disable(int unit,
   1090                                 soc_port_schedule_state_t *port_schedule_state)
   1091 {
   1092     int i, nport, rv = BCM_E_NONE;
   1093     bcm_port_t *port;
   1094 
   1095     nport = port_schedule_state->nport;
   1096 
   1097     port = sal_alloc(nport * sizeof(bcm_port_t), "port array");
   1098     if (port == NULL) {
   1099         return BCM_E_MEMORY;
   1100     }
   1101     for (i = 0; i < nport; i++) {
   1102         port[i] = port_schedule_state->resource[i].logical_port;
   1103     }
   1104     rv = bcmi_esw_portctrl_mac_rx_down(unit, nport, port);
   1105     if (BCM_SUCCESS(rv)) {
   1106         rv = soc_trident3_flex_idb_port_down(unit, port_schedule_state);
   1107     }
   1108     if (BCM_SUCCESS(rv) && (!(SAL_BOOT_XGSSIM || SAL_BOOT_BCMSIM))) {
   1109         rv = soc_trident3_flex_mmu_port_down(unit, port_schedule_state);
   1110     }
   1111     if (BCM_SUCCESS(rv)) {
   1112         rv = soc_trident3_flex_ep_port_down(unit, port_schedule_state);
   1113     }
   1114     if (BCM_SUCCESS(rv)) {
   1115         rv = bcmi_esw_portctrl_mac_tx_down(unit, nport, port);
   1116     }
   1117 
   1118     sal_free(port);
   1119 
   1120     return rv;
   1121 }
   1122 
   1123 /*
   1124  * Function:
   1125  *      bcmi_td3_port_speed_1g_update
   1126  * Purpose:
   1127  *      Special operations for 1G speed.
   1128  * Parameters:
   1129  *      unit                 - (IN) Unit number.
   1130  *      port                 - (IN) Logical port number.
   1131  *      speed                - (IN) port speed (Mbps).
   1132  * Returns:
   1133  *      BCM_E_xxx
   1134  * Notes:
   1135  *      In the PRD, nothing below 10G is officially supported.
   1136  *      We enable customers with limited 1G support in Trident 3.
   1137  *      1G is not a support speed class in TDM calculation, thus treated same as
   1138  *      10G in TDM calculation. 1G port does NOT support cut through, flow
   1139  *      control.
   1140  */
   1141 int
   1142 bcmi_td3_port_speed_1g_update(int unit, bcm_port_t port, int speed)
   1143 {
   1144     if (speed != SPEED_1G) {
   1145         return BCM_E_NONE;
   1146     }
   1147 
   1148     /* Update port speed info in soc_info */
   1149     SOC_INFO(unit).port_init_speed[port] = speed;
   1150 
   1151     /* Set asf mode to SAF */
   1152     if (soc_feature(unit, soc_feature_asf_multimode)) {
   1153         BCM_IF_ERROR_RETURN
   1154             (soc_td3_port_asf_mode_set(unit, port, speed,
   1155                                     _SOC_TD3_ASF_MODE_SAF));
   1156     }
   1157 
   1158     /* Disable Pause */
   1159     BCM_IF_ERROR_RETURN
   1160         (bcm_esw_port_pause_set(unit, port, 0, 0));
   1161 
   1162     /* Disable PFC */
   1163     if (soc_feature(unit, soc_feature_priority_flow_control)) {
   1164         BCM_IF_ERROR_RETURN
   1165             (bcm_esw_port_control_set(unit, port,
   1166                                       bcmPortControlPFCReceive, 0));
   1167         BCM_IF_ERROR_RETURN
   1168             (bcm_esw_port_control_set(unit, port,
   1169                                       bcmPortControlPFCTransmit, 0));
   1170     }
   1171 
   1172     return BCM_E_NONE;
   1173 }
   1174 /*
   1175  * Function:
   1176  *      bcmi_td3_speed_ability_get
   1177  * Purpose:
   1178  *      Retrieve the local port abilities.
   1179  * Parameters:
   1180  *      unit - Unit.
   1181  *      port - Logical port num.
   1182  *      mask - (OUT) Mask of BCM_PORT_ABILITY_ values indicating the
   1183  *              supported speeds of the port.
   1184  * Returns:
   1185  *      BCM_E_NONE
   1186  *      BCM_E_XXX
   1187  */
   1188 int
   1189 bcmi_td3_speed_ability_get(int unit, bcm_port_t port, bcm_port_abil_t *mask)
   1190 {
   1191     if (IS_MANAGEMENT_PORT(unit, port)) {
   1192         /* TD3 Port Rates for Management ports:
   1193          * 10M 100M, 1G, 2.5G, 10G, HG[11G] */
   1194         *mask = BCM_PORT_ABILITY_10MB | BCM_PORT_ABILITY_100MB |
   1195                 BCM_PORT_ABILITY_1000MB | BCM_PORT_ABILITY_2500MB |
   1196                 BCM_PORT_ABILITY_10GB | BCM_PORT_ABILITY_11GB;
   1197     } else {
   1198         BCM_IF_ERROR_RETURN
   1199             (soc_td3_support_speeds(unit,
   1200                                     SOC_INFO(unit).port_num_lanes[port],
   1201                                     mask));
   1202     }
   1203     return BCM_E_NONE;
   1204 }
   1205 
   1206 int _bcm_td3_port_phb_map_tab1_default_entry_add(int unit,
   1207                                                soc_profile_mem_t *prof)
   1208 {
   1209     phb_mapping_tbl_1_entry_t pri_map[_BCM_TD3_PHB_MAP_TAB1_ENTRIES_PER_PROFILE];
   1210     ing_untagged_phb_entry_t phb;
   1211     int index, pkt_pri, cfi, base = 0;
   1212     int phb_map_tab1_entry;
   1213     void *entries[2];
   1214 
   1215     sal_memset(pri_map, 0, sizeof(phb_mapping_tbl_1_entry_t) *
   1216                                      _BCM_TD3_PHB_MAP_TAB1_ENTRIES_PER_PROFILE);
   1217     sal_memset(&phb, 0, sizeof(phb));
   1218 
   1219     for (cfi = 0; cfi <= 1; cfi++) {
   1220         for (pkt_pri = 0; pkt_pri <= 7; pkt_pri++) {
   1221             index = (pkt_pri << 1) | cfi;
   1222             soc_mem_field32_set(unit, PHB_MAPPING_TBL_1m,  &pri_map[index],
   1223                                 INT_PRIf, pkt_pri);
   1224             soc_mem_field32_set(unit, PHB_MAPPING_TBL_1m,  &pri_map[index],
   1225                                 CNGf, cfi);
   1226         }
   1227     }
   1228     entries[0] = &pri_map;
   1229     entries[1] = &phb;
   1230 
   1231 #if defined(BCM_HELIX5_SUPPORT)
   1232     if (SOC_IS_HELIX5(unit)) {
   1233         phb_map_tab1_entry = _BCM_HX5_PHB_MAP_TAB1_ENTRIES_PER_PROFILE;
   1234     } else
   1235 #endif
   1236     {
   1237         phb_map_tab1_entry = _BCM_TD3_PHB_MAP_TAB1_ENTRIES_PER_PROFILE;
   1238     }
   1239 
   1240     BCM_IF_ERROR_RETURN
   1241         (soc_profile_mem_add(unit, prof, entries, phb_map_tab1_entry,
   1242                              (uint32 *)&base));
   1243     if (base != soc_mem_index_min(unit, PHB_MAPPING_TBL_1m)) {
   1244         return BCM_E_INTERNAL;
   1245     }
   1246     return BCM_E_NONE;
   1247 }
   1248 
   1249 /*
   1250  * Function:
   1251  *      _bcm_td3_port_cfg_init
   1252  * Purpose:
   1253  *      Initialize port configuration according to Initial System
   1254  *      Configuration (see init.c)
   1255  * Parameters:
   1256  *      unit       - (IN)StrataSwitch unit number.
   1257  *      port       - (IN)Port number.
   1258  *      vlan_data  - (IN)Initial VLAN data information
   1259  * Returns:
   1260  *      BCM_E_XXX
   1261  */
   1262 int
   1263 _bcm_td3_port_cfg_init(int unit, bcm_port_t port, bcm_vlan_data_t *vlan_data)
   1264 {
   1265     soc_mem_t egr_port_mem = EGR_LPORT_PROFILEm;
   1266     soc_field_t field;
   1267     soc_field_t egr_port_field_ids[SOC_MAX_MEM_FIELD_WORDS];
   1268     uint32 egt_port_field_values[SOC_MAX_MEM_FIELD_WORDS];
   1269     int egr_port_field_count = 0;
   1270     soc_field_t port_field_ids[SOC_MAX_MEM_FIELD_WORDS];
   1271     uint32 port_field_values[SOC_MAX_MEM_FIELD_WORDS];
   1272     int port_field_count = 0;
   1273 
   1274     uint32 port_type;
   1275     uint32 egr_port_type = 0;
   1276     int dual_modid = 0;
   1277     int key_type_value;
   1278     int cpu_hg_index = -1;
   1279     uint32 max_gid, gid;
   1280     uint32 cancun_ver;
   1281     
   1282     SOC_IF_ERROR_RETURN(soc_cancun_version_get(unit, &cancun_ver));
   1283 
   1284     if ((SOC_IS_TR_VL(unit)) && (NUM_MODID(unit) >= 2)) {
   1285         dual_modid = 1;
   1286     }
   1287 
   1288     if (IS_CPU_PORT(unit,port)) {
   1289         cpu_hg_index = SOC_INFO(unit).cpu_hg_index;
   1290         port_type = 0; /* Same as Ethernet port */
   1291         egr_port_type = 1; /* CPU port needs to be HG port in EGR_PORT table */
   1292     } else if (IS_ST_PORT(unit, port)) {
   1293         port_type = 1;
   1294         egr_port_type = 1;
   1295     } else if (IS_LB_PORT(unit, port)) {
   1296         port_type = 2;
   1297         egr_port_type = 2;
   1298     } else {
   1299         port_type = 0;
   1300     }
   1301 
   1302     /* EGR_LPORT_TABLE config init */
   1303 #ifdef BCM_SHADOW_SUPPORT
   1304     /* EGR_PORT fields are Unsupported in shadow */
   1305     if (!SOC_IS_SHADOW(unit))
   1306 #endif
   1307     {
   1308         /* CPU port type is HG for CANCUN version >= B870.5.2.3 on TD3 */
   1309         if ((SOC_IS_TRIDENT3(unit)) && (cancun_ver <= SOC_CANCUN_VERSION_DEF_5_2_3)) {
   1310             soc_mem_set_field_value_array(egr_port_field_ids, PORT_TYPEf,
   1311                                       egt_port_field_values, port_type,
   1312                                       egr_port_field_count);
   1313         } else {
   1314             soc_mem_set_field_value_array(egr_port_field_ids, PORT_TYPEf,
   1315                                       egt_port_field_values, egr_port_type,
   1316                                       egr_port_field_count);
   1317         }
   1318         soc_mem_set_field_value_array(egr_port_field_ids, EN_EFILTERf,
   1319                                       egt_port_field_values, 1,
   1320                                       egr_port_field_count);
   1321         if (SOC_IS_TR_VL(unit)) {
   1322             soc_mem_set_field_value_array(egr_port_field_ids, DUAL_MODID_ENABLEf,
   1323                                           egt_port_field_values, dual_modid,
   1324                                           egr_port_field_count);
   1325         }
   1326 
   1327         field = VT_PORT_GROUP_IDf;
   1328         BCM_IF_ERROR_RETURN
   1329             (_bcm_td3_egr_port_tab_conv(unit, &field, &egr_port_mem));
   1330 
   1331         max_gid = soc_mem_field_length(unit, egr_port_mem, field);
   1332         if(max_gid > 31) {
   1333             return BCM_E_INTERNAL;
   1334         }
   1335         max_gid = (1 << max_gid) - 1;
   1336         gid = (port < max_gid) ? port : max_gid;
   1337         soc_mem_set_field_value_array(egr_port_field_ids, field,
   1338                                       egt_port_field_values, gid,
   1339                                       egr_port_field_count);
   1340 
   1341         if (soc_feature(unit, soc_feature_directed_mirror_only)) {
   1342             soc_mem_set_field_value_array(egr_port_field_ids, EM_SRCMOD_CHANGEf,
   1343                                           egt_port_field_values, 1,
   1344                                           egr_port_field_count);
   1345         }
   1346 
   1347         _bcm_esw_egr_port_tab_multi_set(unit, port, egr_port_field_count,
   1348                                         egr_port_field_ids,
   1349                                         egt_port_field_values);
   1350 
   1351 #if defined(CANCUN_SUPPORT)
   1352         if (soc_feature(unit, soc_feature_cancun)) {
   1353             /* initialize the Cancun tag profile entry setup
   1354              * for VT_MISS_UNTAG action. Should be done in Cancun
   1355              */
   1356             if (soc_cancun_cmh_check(unit, EGR_VLAN_CONTROL_1m,
   1357                 VT_MISS_UNTAGf) == SOC_E_NONE) {
   1358                 int rv = SOC_E_NONE;
   1359                 rv = soc_cancun_cmh_mem_set(unit,
   1360                         EGR_VLAN_CONTROL_1m, port,
   1361                                 VT_MISS_UNTAGf, 1);
   1362                 if (BCM_FAILURE(rv) && rv != SOC_E_PARAM) {
   1363                     return rv;
   1364                 }
   1365             }
   1366         }
   1367 #endif
   1368 
   1369         /* Copy EGR port information to CPU Higig port if applied */
   1370         if (cpu_hg_index != -1 &&
   1371             soc_mem_index_max(unit, EGR_PORTm) == cpu_hg_index) {
   1372             BCM_IF_ERROR_RETURN(_bcm_esw_egr_port_tab_multi_set(unit, cpu_hg_index,
   1373                                     egr_port_field_count, egr_port_field_ids,
   1374                                     egt_port_field_values));
   1375         }
   1376 
   1377     }
   1378 
   1379     /* PORT_TABLE config init */
   1380     soc_mem_set_field_value_array(port_field_ids, PORT_VIDf,
   1381                                   port_field_values, vlan_data->vlan_tag,
   1382                                   port_field_count);
   1383 #if 0
   1384     soc_mem_set_field_value_array(port_field_ids, OUTER_TPIDf,
   1385                                   port_field_values, 0x8100,
   1386                                   port_field_count);
   1387 #endif
   1388     soc_mem_set_field_value_array(port_field_ids, MAC_BASED_VID_ENABLEf,
   1389                                   port_field_values, 1,
   1390                                   port_field_count);
   1391     soc_mem_set_field_value_array(port_field_ids, SUBNET_BASED_VID_ENABLEf,
   1392                                   port_field_values, 1,
   1393                                   port_field_count);
   1394 #if 0
   1395     soc_mem_set_field_value_array(port_field_ids, TRUST_INCOMING_VIDf,
   1396                                   port_field_values, 1,
   1397                                   port_field_count);
   1398 #endif
   1399     soc_mem_set_field_value_array(port_field_ids, PRI_MAPPINGf,
   1400                                   port_field_values, 0xfac688,
   1401                                   port_field_count);
   1402     soc_mem_set_field_value_array(port_field_ids, CFI_0_MAPPINGf,
   1403                                   port_field_values, 0,
   1404                                   port_field_count);
   1405     soc_mem_set_field_value_array(port_field_ids, CFI_1_MAPPINGf,
   1406                                   port_field_values, 1,
   1407                                   port_field_count);
   1408     soc_mem_set_field_value_array(port_field_ids, IPRI_MAPPINGf,
   1409                                   port_field_values, 0xfac688,
   1410                                   port_field_count);
   1411     soc_mem_set_field_value_array(port_field_ids, ICFI_0_MAPPINGf,
   1412                                   port_field_values, 0,
   1413                                   port_field_count);
   1414     soc_mem_set_field_value_array(port_field_ids, ICFI_1_MAPPINGf,
   1415                                   port_field_values, 1,
   1416                                   port_field_count);
   1417     soc_mem_set_field_value_array(port_field_ids, CML_FLAGS_NEWf,
   1418                                   port_field_values, 0x8,
   1419                                   port_field_count);
   1420     soc_mem_set_field_value_array(port_field_ids, CML_FLAGS_MOVEf,
   1421                                   port_field_values, 0x8,
   1422                                   port_field_count);
   1423     BCM_IF_ERROR_RETURN
   1424         (_bcm_esw_pt_vtkey_type_value_get(unit, VLXLT_HASH_KEY_TYPE_OVID,
   1425                                           &key_type_value));
   1426     soc_mem_set_field_value_array(port_field_ids, VT_KEY_TYPEf,
   1427                                   port_field_values, key_type_value,
   1428                                   port_field_count);
   1429     soc_mem_set_field_value_array(port_field_ids, VT_PORT_TYPE_SELECT_1f,
   1430                                   port_field_values, 1,
   1431                                   port_field_count);
   1432     BCM_IF_ERROR_RETURN
   1433         (_bcm_esw_pt_vtkey_type_value_get(unit, VLXLT_HASH_KEY_TYPE_IVID,
   1434                                           &key_type_value));
   1435     soc_mem_set_field_value_array(port_field_ids, VT_KEY_TYPE_2f,
   1436                                   port_field_values, key_type_value,
   1437                                   port_field_count);
   1438     soc_mem_set_field_value_array(port_field_ids, VT_PORT_TYPE_SELECT_2f,
   1439                                   port_field_values, 1,
   1440                                   port_field_count);
   1441     soc_mem_set_field_value_array(port_field_ids, PORT_TYPEf,
   1442                                   port_field_values, port_type,
   1443                                   port_field_count);
   1444     soc_mem_set_field_value_array(port_field_ids, SRC_SYS_PORT_IDf,
   1445                                   port_field_values, port,
   1446                                   port_field_count);
   1447     /* TD3TBD SYS_PORT_ID and PP_PORT_NUM should be covered by CIH, 
   1448      * will remove it after CIH is ready. */
   1449     soc_mem_set_field_value_array(port_field_ids, SYS_PORT_IDf,
   1450                                   port_field_values, port,
   1451                                   port_field_count);
   1452     soc_mem_set_field_value_array(port_field_ids, PP_PORT_NUMf,
   1453                                   port_field_values, port,
   1454                                   port_field_count);
   1455     soc_mem_set_field_value_array(port_field_ids, DUAL_MODID_ENABLEf,
   1456                                   port_field_values, dual_modid,
   1457                                   port_field_count);
   1458     soc_mem_set_field_value_array(port_field_ids, TAG_ACTION_PROFILE_PTRf,
   1459                                   port_field_values, 1,
   1460                                   port_field_count);
   1461 
   1462     BCM_IF_ERROR_RETURN(_bcm_esw_port_tab_multi_set(unit, port, _BCM_CPU_TABS_BOTH,
   1463                             port_field_count, port_field_ids,
   1464                             port_field_values));
   1465 
   1466     if (cpu_hg_index != -1) {
   1467         soc_cancun_cmh_mem_set(unit, PORT_TABm, cpu_hg_index, PORT_TYPEf, 1);
   1468         /* TD3TBD should be covered by CMH, will remove it after CMH
   1469          * is ready. */
   1470         BCM_IF_ERROR_RETURN(soc_mem_field32_modify(unit, ING_DEVICE_PORTm,
   1471                             cpu_hg_index, PORT_TYPEf, 1));
   1472     }
   1473 #ifdef BCM_RCPU_SUPPORT
   1474     if (SOC_IS_RCPU_ONLY(unit)) {
   1475         soc_cancun_cmh_mem_set(unit, PORT_TABm, port, OUTER_TPID_ENABLEf, 0x1);
   1476     }
   1477 #endif /* BCM_RCPU_SUPPORT */
   1478 
   1479     return (BCM_E_NONE);
   1480 }
   1481 
   1482 /*
   1483  * Function:
   1484  *      bcm_td3_port_cfg_init
   1485  * Purpose:
   1486  *      Initialize the port configuration according to Initial System
   1487  *      Configuration (see init.c)
   1488  * Parameters:
   1489  *      unit       - (IN)StrataSwitch unit number.
   1490  *      port       - (IN)Port number.
   1491  *      vlan_data  - (IN)Initial VLAN data information
   1492  * Returns:
   1493  *      BCM_E_XXX
   1494  */
   1495 int
   1496 bcm_td3_port_cfg_init(int unit, bcm_port_t port, bcm_vlan_data_t *vlan_data)
   1497 {
   1498     if (SOC_IS_TRIDENT3X(unit)) {
   1499         return _bcm_td3_port_cfg_init(unit, port, vlan_data);
   1500     }
   1501 
   1502     return (BCM_E_NONE);
   1503 }
   1504 
   1505 /*
   1506  * Function:
   1507  *      _bcm_td3_port_table_read
   1508  * Purpose:
   1509  *      Read port table entry and parse it to a common
   1510  *      (bcm_port_cfg_t) structure.
   1511  * Parameters:
   1512  *      unit       - (IN)SOC unit number.
   1513  *      port       - (IN)Port number.
   1514  *      port_cfg   - (OUT)API port information structure.
   1515  * Returns:
   1516  *      BCM_E_XXX
   1517  * Notes:
   1518  *      The following port configuration settings
   1519  *      do not apply to FB/ER ports:
   1520  *
   1521  *      port_cfg->pc_frame_type
   1522  *      port_cfg->pc_ether_type
   1523  *      port_cfg->pc_stp_state
   1524  *      port_cfg->pc_cpu
   1525  *      port_cfg->pc_ptype
   1526  *      port_cfg->pc_pbm
   1527  *      port_cfg->pc_ut_pbm
   1528  *      port_cfg->pc_trunk
   1529  *      port_cfg->pc_pfm
   1530  *    The following port configuration do not apply to ER
   1531  *       port_cfg->pc_nni_port
   1532  */
   1533 STATIC int
   1534 _bcm_td3_port_table_read(int unit, bcm_port_t port,
   1535                          bcm_port_cfg_t *port_cfg)
   1536 {
   1537 #define LPORT_FIELDS    22
   1538     int discard_tag = 0;            /* Discard tagged packets bit.   */
   1539     int discard_untag = 0;          /* Discard untagged packets bit. */
   1540     uint32 values[LPORT_FIELDS];
   1541     int i, value = 0;
   1542 
   1543     soc_field_t fields[LPORT_FIELDS] = {
   1544         PORT_DIS_TAGf,
   1545         PORT_DIS_UNTAGf,
   1546         DROP_BPDUf,
   1547         MIRRORf,
   1548         PORT_VIDf,
   1549         IVIDf,
   1550         TAG_ACTION_PROFILE_PTRf,
   1551         V4L3_ENABLEf,
   1552         V6L3_ENABLEf,
   1553         OPRIf,
   1554         OCFIf,
   1555         IPRIf,
   1556         ICFIf,
   1557         TRUST_DSCP_V4f,
   1558         TRUST_DSCP_V6f,
   1559         EN_IFILTERf,
   1560         PORT_BRIDGEf,
   1561         URPF_MODEf,
   1562         URPF_DEFAULTROUTECHECKf,
   1563         PVLAN_ENABLEf,
   1564         CML_FLAGS_NEWf,
   1565         CML_FLAGS_MOVEf
   1566     };
   1567 
   1568 #define _GET_FIELD_VALUE(_f, _v)                \
   1569     do {                                        \
   1570         for (i = 0; i < LPORT_FIELDS; i++) {    \
   1571             if (fields[i] == (_f)) {            \
   1572                 (_v) = values[i];               \
   1573                 break;                          \
   1574             }                                   \
   1575         }                                       \
   1576     } while (0)
   1577 
   1578     BCM_IF_ERROR_RETURN(
   1579         bcm_esw_port_lport_fields_get(
   1580             unit, port, LPORT_PROFILE_LPORT_TAB, LPORT_FIELDS, 
   1581             fields, values));
   1582 
   1583     /* Get drop all tagged packets flag. */
   1584     _GET_FIELD_VALUE(PORT_DIS_TAGf, discard_tag);
   1585 
   1586     /* Get drop all untagged packets flag. */
   1587     _GET_FIELD_VALUE(PORT_DIS_UNTAGf, discard_untag);
   1588 
   1589     if (discard_tag && discard_untag) {
   1590         port_cfg->pc_disc = BCM_PORT_DISCARD_ALL;
   1591     } else if (discard_tag) {
   1592         port_cfg->pc_disc = BCM_PORT_DISCARD_TAG;
   1593     } else if (discard_untag) {
   1594         port_cfg->pc_disc = BCM_PORT_DISCARD_UNTAG;
   1595     } else {
   1596         port_cfg->pc_disc = BCM_PORT_DISCARD_NONE;
   1597     }
   1598 
   1599     /* Get drop bpdu's on ingress flag. */
   1600     _GET_FIELD_VALUE(DROP_BPDUf, port_cfg->pc_bpdu_disable);
   1601 
   1602     /* Get enable mirroring flag. */
   1603     _GET_FIELD_VALUE(MIRRORf, value);
   1604     if (soc_feature(unit, soc_feature_mirror_flexible)) {
   1605         /* Multi-bit field */
   1606         port_cfg->pc_mirror_ing = value;
   1607     } else if (!soc_feature(unit, soc_feature_no_mirror) && value) {
   1608         port_cfg->pc_mirror_ing |= BCM_MIRROR_MTP_ONE;
   1609     }
   1610 
   1611     /* Get port default vlan id (pvid). */
   1612     _GET_FIELD_VALUE(PORT_VIDf, port_cfg->pc_vlan);
   1613 
   1614     _GET_FIELD_VALUE(IVIDf, port_cfg->pc_ivlan);
   1615     _GET_FIELD_VALUE(TAG_ACTION_PROFILE_PTRf, port_cfg->pc_vlan_action);
   1616 
   1617     /* Get L3 IPv4 forwarding enable bit. */
   1618     _GET_FIELD_VALUE(V4L3_ENABLEf, value);
   1619     if (value) {
   1620         port_cfg->pc_l3_flags |= BCM_PORT_L3_V4_ENABLE;
   1621     }
   1622 
   1623     /* Get L3 IPv6 forwarding enable bit. */
   1624     _GET_FIELD_VALUE(V6L3_ENABLEf, value);
   1625     if (value) {
   1626         port_cfg->pc_l3_flags |= BCM_PORT_L3_V6_ENABLE;
   1627     }
   1628 
   1629     /* Get port default priority.*/
   1630     _GET_FIELD_VALUE(OPRIf, port_cfg->pc_new_opri);
   1631     _GET_FIELD_VALUE(OCFIf, port_cfg->pc_new_ocfi);
   1632     _GET_FIELD_VALUE(IPRIf, port_cfg->pc_new_ipri);
   1633     _GET_FIELD_VALUE(ICFIf, port_cfg->pc_new_icfi);
   1634 
   1635     /* Get ingress port is trusted port, trust incoming IPv4 DSCP bit. */
   1636     _GET_FIELD_VALUE(TRUST_DSCP_V4f, port_cfg->pc_dse_mode);
   1637 
   1638     /* Get ingress port is trusted port, trust incoming IPv6 DSCP bit. */
   1639     _GET_FIELD_VALUE(TRUST_DSCP_V6f, port_cfg->pc_dse_mode_ipv6);
   1640     port_cfg->pc_dscp_prio = port_cfg->pc_dse_mode;
   1641     port_cfg->pc_dscp = -1;
   1642 
   1643     /* Get enable ingress filtering bit. */
   1644     _GET_FIELD_VALUE(EN_IFILTERf, port_cfg->pc_en_ifilter);
   1645 
   1646     /* Get enable L2 bridging on the incoming port. */
   1647     _GET_FIELD_VALUE(PORT_BRIDGEf, port_cfg->pc_bridge_port);
   1648 
   1649     /* Unicast rpf mode. */
   1650     _GET_FIELD_VALUE(URPF_MODEf, port_cfg->pc_urpf_mode);
   1651 
   1652     /* Unicast rpf default gateway check. */
   1653     _GET_FIELD_VALUE(URPF_DEFAULTROUTECHECKf, port_cfg->pc_urpf_def_gw_check);
   1654 
   1655     /* private VALN enable */
   1656     _GET_FIELD_VALUE(PVLAN_ENABLEf, port_cfg->pc_pvlan_enable);
   1657 
   1658     /* If port cpu managed learning is not frozen read it from port. */
   1659     if (!soc_feature(unit, soc_feature_no_learning) && 
   1660         soc_l2x_frozen_cml_get(unit, port, &port_cfg->pc_cml, 
   1661                                &port_cfg->pc_cml_move) < 0) {
   1662         _GET_FIELD_VALUE(CML_FLAGS_NEWf, port_cfg->pc_cml);
   1663         _GET_FIELD_VALUE(CML_FLAGS_MOVEf, port_cfg->pc_cml_move);
   1664     }
   1665 
   1666     return (BCM_E_NONE);
   1667 }
   1668 
   1669 /*
   1670  * Function:
   1671  *      _bcm_td3_port_table_write
   1672  * Purpose:
   1673  *      Prepare & write port table entry 
   1674  * Parameters:
   1675  *      unit       - (IN)SOC unit number.
   1676  *      port       - (IN)Port number.
   1677  *      port_cfg   - (IN)API port information structure.
   1678  * Returns:
   1679  *      BCM_E_XXX
   1680  */
   1681 STATIC int
   1682 _bcm_td3_port_table_write(int unit, bcm_port_t port,
   1683                           bcm_port_cfg_t *port_cfg)
   1684 {
   1685     soc_field_t port_field_ids[SOC_MAX_MEM_FIELD_WORDS];
   1686     uint32 port_field_values[SOC_MAX_MEM_FIELD_WORDS];
   1687     int port_field_count = 0;
   1688     int repl_cml, repl_cml_move;
   1689     int cml, cml_move;
   1690 
   1691     /* Set drop all tagged/untagged packets flag. */
   1692     switch (port_cfg->pc_disc) {
   1693         case BCM_PORT_DISCARD_NONE:
   1694             soc_mem_set_field_value_array(port_field_ids, PORT_DIS_TAGf,
   1695                                           port_field_values, 0,
   1696                                           port_field_count);
   1697             soc_mem_set_field_value_array(port_field_ids, PORT_DIS_UNTAGf,
   1698                                           port_field_values, 0,
   1699                                           port_field_count);
   1700             break;
   1701         case BCM_PORT_DISCARD_ALL:
   1702             soc_mem_set_field_value_array(port_field_ids, PORT_DIS_TAGf,
   1703                                           port_field_values, 1,
   1704                                           port_field_count);
   1705             soc_mem_set_field_value_array(port_field_ids, PORT_DIS_UNTAGf,
   1706                                           port_field_values, 1,
   1707                                           port_field_count);
   1708             break;
   1709         case BCM_PORT_DISCARD_UNTAG:
   1710             soc_mem_set_field_value_array(port_field_ids, PORT_DIS_TAGf,
   1711                                           port_field_values, 0,
   1712                                           port_field_count);
   1713             soc_mem_set_field_value_array(port_field_ids, PORT_DIS_UNTAGf,
   1714                                           port_field_values, 1,
   1715                                           port_field_count);
   1716             break;
   1717         case BCM_PORT_DISCARD_TAG:
   1718             soc_mem_set_field_value_array(port_field_ids, PORT_DIS_TAGf,
   1719                                           port_field_values, 1,
   1720                                           port_field_count);
   1721             soc_mem_set_field_value_array(port_field_ids, PORT_DIS_UNTAGf,
   1722                                           port_field_values, 0,
   1723                                           port_field_count);
   1724             break;
   1725     }
   1726 
   1727     /* Set drop bpdu's on ingress flag. */
   1728     soc_mem_set_field_value_array(port_field_ids, DROP_BPDUf,
   1729                                   port_field_values, port_cfg->pc_bpdu_disable,
   1730                                   port_field_count);
   1731 
   1732     /* Set ingress mirroring flag. */
   1733     if (soc_feature(unit, soc_feature_mirror_flexible)) {
   1734         soc_mem_set_field_value_array(port_field_ids, MIRRORf,
   1735             port_field_values, (port_cfg->pc_mirror_ing & BCM_TR2_MIRROR_MTP_MASK),
   1736             port_field_count);
   1737     } else if (!soc_feature(unit, soc_feature_no_mirror)) {
   1738         soc_mem_set_field_value_array(port_field_ids, MIRRORf,
   1739             port_field_values, (port_cfg->pc_mirror_ing & BCM_MIRROR_MTP_ONE),
   1740             port_field_count);
   1741     }
   1742 
   1743     /*
   1744      * Set cpu managed learning (cml).
   1745      * if unit is not frozen set the same value to port table.
   1746      * else set port table (cml) to PVP_CML_FORWARD.
   1747      */
   1748     if (soc_l2x_frozen_cml_set(unit, port, port_cfg->pc_cml, 
   1749                                port_cfg->pc_cml_move, &repl_cml, 
   1750                                &repl_cml_move) < 0) {
   1751         cml = port_cfg->pc_cml;
   1752         cml_move = port_cfg->pc_cml_move;
   1753     } else {
   1754         cml = repl_cml;
   1755         cml_move = repl_cml_move;
   1756     }
   1757 
   1758     if (SOC_IS_TRX(unit)) {
   1759         soc_mem_set_field_value_array(port_field_ids, CML_FLAGS_MOVEf,
   1760             port_field_values, cml_move, port_field_count);
   1761         soc_mem_set_field_value_array(port_field_ids, CML_FLAGS_NEWf,
   1762             port_field_values, cml, port_field_count);
   1763 
   1764         soc_mem_set_field_value_array(port_field_ids, IVIDf,
   1765             port_field_values, port_cfg->pc_ivlan, port_field_count);
   1766         soc_mem_set_field_value_array(port_field_ids, TAG_ACTION_PROFILE_PTRf,
   1767             port_field_values, port_cfg->pc_vlan_action, port_field_count);
   1768     }
   1769 
   1770     /* Set port default vlan id (pvid). */
   1771     soc_mem_set_field_value_array(port_field_ids, PORT_VIDf,
   1772         port_field_values, port_cfg->pc_vlan, port_field_count);
   1773 
   1774     /* Set L3 IPv4 forwarding enable bit. */ 
   1775     soc_mem_set_field_value_array(port_field_ids, V4L3_ENABLEf,
   1776         port_field_values, 
   1777         (port_cfg->pc_l3_flags & BCM_PORT_L3_V4_ENABLE) ? 1 : 0,
   1778         port_field_count);
   1779 
   1780     /* Set L3 IPv6 forwarding enable bit. */ 
   1781     soc_mem_set_field_value_array(port_field_ids, V6L3_ENABLEf,
   1782         port_field_values, 
   1783         (port_cfg->pc_l3_flags & BCM_PORT_L3_V6_ENABLE) ? 1 : 0,
   1784         port_field_count);
   1785 
   1786     /* Set new port default priority.*/
   1787     soc_mem_set_field_value_array(port_field_ids, PORT_PRIf,
   1788         port_field_values, port_cfg->pc_new_opri, port_field_count);
   1789     soc_mem_set_field_value_array(port_field_ids, OCFIf,
   1790         port_field_values, port_cfg->pc_new_ocfi, port_field_count);
   1791     soc_mem_set_field_value_array(port_field_ids, IPRIf,
   1792         port_field_values, port_cfg->pc_new_ipri, port_field_count);
   1793     soc_mem_set_field_value_array(port_field_ids, ICFIf,
   1794         port_field_values, port_cfg->pc_new_icfi, port_field_count);
   1795 
   1796     /* Set ingress port is trusted port, trust incoming IPv4 DSCP bit. */ 
   1797     soc_mem_set_field_value_array(port_field_ids, TRUST_DSCP_V4f,
   1798         port_field_values, port_cfg->pc_dse_mode ? 1 : 0, port_field_count);
   1799 
   1800     /* Set ingress port is trusted port, trust incoming IPv6 DSCP bit. */
   1801     soc_mem_set_field_value_array(port_field_ids, TRUST_DSCP_V6f,
   1802         port_field_values, port_cfg->pc_dse_mode_ipv6 ? 1 : 0, port_field_count);
   1803 
   1804     /* Set enable ingress filtering. */
   1805     soc_mem_set_field_value_array(port_field_ids, EN_IFILTERf,
   1806         port_field_values, port_cfg->pc_en_ifilter, port_field_count);
   1807 
   1808     /* Set enable ingress filtering. */
   1809     soc_mem_set_field_value_array(port_field_ids, PORT_BRIDGEf,
   1810         port_field_values, port_cfg->pc_bridge_port, port_field_count);
   1811 
   1812     /* Unicast rpf mode. */
   1813     soc_mem_set_field_value_array(port_field_ids, URPF_MODEf,
   1814         port_field_values, port_cfg->pc_urpf_mode, port_field_count);
   1815 
   1816     /* Unicast rpf default gateway check. */
   1817     soc_mem_set_field_value_array(port_field_ids, URPF_DEFAULTROUTECHECKf,
   1818         port_field_values, port_cfg->pc_urpf_def_gw_check, port_field_count);
   1819 
   1820     /* private VALN enable */
   1821     soc_mem_set_field_value_array(port_field_ids, PVLAN_ENABLEf,
   1822         port_field_values, port_cfg->pc_pvlan_enable, port_field_count);
   1823 
   1824     _bcm_esw_port_tab_multi_set(unit, port, _BCM_CPU_TABS_BOTH,
   1825                                 port_field_count, port_field_ids,
   1826                                 port_field_values);
   1827 
   1828     return BCM_E_NONE;
   1829 }
   1830 
   1831 /*
   1832  * Function:
   1833  *      bcm_td3_port_cfg_get
   1834  * Purpose:
   1835  *      Get port configuration.
   1836  * Parameters:
   1837  *      unit       - (IN)SOC unit number.
   1838  *      port       - (IN)Port number.
   1839  *      port_cfg   - (OUT)API port information structure.
   1840  * Returns:
   1841  *      BCM_E_XXX
   1842  */
   1843 int
   1844 bcm_td3_port_cfg_get(int unit, bcm_port_t port, bcm_port_cfg_t *port_cfg)
   1845 {
   1846     /* Input parameters check.*/
   1847     if (NULL == port_cfg) {
   1848         return (BCM_E_PARAM);
   1849     }
   1850 
   1851     sal_memset(port_cfg, 0, sizeof(bcm_port_cfg_t));
   1852 
   1853     /* Read port table entry. */
   1854     BCM_IF_ERROR_RETURN(_bcm_td3_port_table_read(unit, port, port_cfg));
   1855 
   1856     return(BCM_E_NONE);
   1857 }
   1858 
   1859 /*
   1860  * Function:
   1861  *      bcm_td3_port_cfg_set
   1862  * Purpose:
   1863  *      Set port configuration.
   1864  * Parameters:
   1865  *      unit       - (IN)SOC unit number.
   1866  *      port       - (IN)Port number.
   1867  *      port_cfg   - (OUT)API port information structure.
   1868  * Returns:
   1869  *      BCM_E_XXX
   1870  */
   1871 int
   1872 bcm_td3_port_cfg_set(int unit, bcm_port_t port, bcm_port_cfg_t *port_cfg)
   1873 {
   1874     /* Input parameters check.*/
   1875     if (NULL == port_cfg) {
   1876         return (BCM_E_PARAM);
   1877     }
   1878 
   1879     /* Write port table entry. */
   1880     BCM_IF_ERROR_RETURN(_bcm_td3_port_table_write(unit, port, port_cfg));
   1881 
   1882     return (BCM_E_NONE);
   1883 }
   1884 
   1885 int
   1886 _bcm_td3_egr_port_tab_conv(int unit, soc_field_t *field, soc_mem_t* mem) {
   1887 
   1888     soc_mem_t m = EGR_LPORT_PROFILEm;
   1889     soc_field_t f = *field;
   1890 
   1891     switch(*field) {
   1892         case QOS_CTRL_IDf:
   1893         case PORT_TYPEf:
   1894         case MY_MODIDf:
   1895         case EGR_PORT_CTRL_IDf:
   1896         case EGR_LPORT_PROFILE_IDXf:
   1897             m = EGR_PORTm;
   1898             break;
   1899         case VT_PORT_GROUP_IDf:
   1900             m = EGR_GPP_ATTRIBUTESm;
   1901             break;
   1902         default:
   1903             break;
   1904     }
   1905 
   1906     if (SOC_MEM_FIELD_VALID(unit, m, f)) {
   1907         *mem = m;
   1908         *field = f;
   1909         return BCM_E_NONE;
   1910     }
   1911 
   1912     return BCM_E_NOT_FOUND;
   1913 }
   1914 
   1915 int
   1916 _bcm_td3_port_tab_conv(int unit, soc_field_t *field, soc_mem_t *mem) {
   1917 
   1918     soc_mem_t m = LPORT_TABm;
   1919     soc_field_t f = *field;
   1920 
   1921     switch (*field) {
   1922         case ECCPf:
   1923         case PARITYf:
   1924         case ECCf:
   1925         case ECC_DATAf:
   1926         case SRC_SYS_PORT_IDf:
   1927         case FROM_REMOTE_CPU_ENf:
   1928         case REMOTE_CPU_ENf:
   1929         case DUAL_MODID_ENABLEf:
   1930         case HIGIG_TRUNK_IDf:
   1931         case HIGIG_TRUNKf:
   1932         case MY_MODIDf:
   1933         case POINTERf:
   1934         case HG_TYPEf:
   1935         case HDR_TYPE_0f:
   1936         /*case HDR_TYPE_NAMESPACE_0f:*/
   1937         case INITIAL_SHIFT_AMOUNT_0f:
   1938         case PARSE_CONTEXT_ID_0f:
   1939         case PARSE_CTRL_ID_0f:
   1940         case PKT_FLOW_SELECT_CTRL_ID_0f:
   1941         case SUBPORT_ID_NAMESPACEf:
   1942         case PP_PORT_NUMf:
   1943         case SYS_PORT_IDf:
   1944         case LPORT_PROFILE_IDXf:
   1945         case PORT_TYPEf:
   1946         case PORT_IPBM_INDEXf:
   1947         case INSERT_RX_TIMESTAMPf:
   1948         case DISABLE_TIMESTAMPINGf:
   1949             m = ING_DEVICE_PORTm;
   1950             break;
   1951         case VT_PORT_TYPE_SELECTf:
   1952             f = VT_PORT_TYPE_SELECT_1f;
   1953             break;
   1954         case SUBPORT_TAG_NAMESPACEf:
   1955             m = ING_DEVICE_PORTm;
   1956             f = SUBPORT_ID_NAMESPACEf;
   1957             break;
   1958         case OUTER_TPID_ENABLEf:
   1959             m = SOURCE_TRUNK_MAP_TABLEm;
   1960             break;
   1961         default:
   1962             break;
   1963     }
   1964 
   1965     if (SOC_MEM_FIELD_VALID(unit, m, f)) {
   1966         *mem = m;
   1967         *field = f;
   1968         return BCM_E_NONE;
   1969     }
   1970 
   1971     return BCM_E_NOT_FOUND;
   1972 }
   1973 
   1974 /*
   1975  * Function:
   1976  *      bcm_td3_port_ing_pri_cng_set
   1977  * Description:
   1978  *      Set packet priority and cfi to internal priority and color mapping
   1979  * Parameters:
   1980  *      unit         - (IN) Device number
   1981  *      port         - (IN) Port number
   1982  *      untagged     - (IN) For untagged packet (ignore pkt_pri, cfi argumnet)
   1983  *      pkt_pri      - (IN) Packet priority (802.1p cos)
   1984  *      cfi          - (IN) Packet CFI
   1985  *      int_pri      - (IN) Internal priority
   1986  *      color        - (IN) Color
   1987  * Return Value:
   1988  *      BCM_E_XXX
   1989  * Note:
   1990  *      When both pkt_pri and cfi are -1, the setting is for untagged packet
   1991  */
   1992 #define MAP_SIZE    64
   1993 int
   1994 bcm_td3_port_ing_pri_cng_set(int unit, bcm_port_t port, int untagged,
   1995                              int pkt_pri, int cfi,
   1996                              int int_pri, bcm_color_t color)
   1997 {
   1998     ing_pri_cng_map_entry_t  map[MAP_SIZE];
   1999     void                     *entries[1];
   2000     uint32                   prof_index, old_prof_index;
   2001     int                      index;
   2002     int                      pkt_pri_cur, pkt_pri_min, pkt_pri_max;
   2003     int                      cfi_cur, cfi_min, cfi_max;
   2004     int                      rv = BCM_E_NONE;
   2005     soc_mem_t                mem = ING_DEVICE_PORTm;
   2006 
   2007     if (pkt_pri < 0) {
   2008         pkt_pri_min = 0;
   2009         pkt_pri_max = 7;
   2010     } else {
   2011         pkt_pri_min = pkt_pri;
   2012         pkt_pri_max = pkt_pri;
   2013     }
   2014 
   2015     if (cfi < 0) {
   2016         cfi_min = 0;
   2017         cfi_max = 1;
   2018     } else {
   2019         cfi_min = cfi;
   2020         cfi_max = cfi;
   2021     }
   2022 
   2023     /* Lock the port table */
   2024     soc_mem_lock(unit, mem);
   2025 
   2026     rv = _bcm_esw_port_tab_get(unit, port, TRUST_DOT1P_PTRf,
   2027                                (void *)&old_prof_index);
   2028     if (BCM_FAILURE(rv)) {
   2029         goto __cleanup;
   2030     }
   2031 
   2032     old_prof_index = old_prof_index * MAP_SIZE;
   2033 
   2034     entries[0] = map;
   2035 
   2036     rv = _bcm_ing_pri_cng_map_entry_get(unit, old_prof_index, MAP_SIZE, entries);
   2037     if (BCM_FAILURE(rv)) {
   2038         goto __cleanup;
   2039     }
   2040 
   2041     for (pkt_pri_cur = pkt_pri_min; pkt_pri_cur <= pkt_pri_max;
   2042          pkt_pri_cur++) {
   2043         for (cfi_cur = cfi_min; cfi_cur <= cfi_max; cfi_cur++) {
   2044             index = ((untagged != 0) << 4) |
   2045                     ((pkt_pri_cur << 1) & 0xe) |
   2046                     (cfi_cur & 0x1);
   2047             if (int_pri >= 0) {
   2048                 soc_mem_field32_set(unit, PHB_MAPPING_TBL_1m, &map[index],
   2049                                     INT_PRIf, int_pri);
   2050             }
   2051             if (color >= 0) {
   2052                 soc_mem_field32_set(unit, PHB_MAPPING_TBL_1m, &map[index],
   2053                                     CNGf,
   2054                                     _BCM_COLOR_ENCODING(unit, color));
   2055             }
   2056         }
   2057     }
   2058 
   2059     rv = _bcm_ing_pri_cng_map_entry_add(unit, entries, MAP_SIZE, &prof_index);
   2060     if (BCM_FAILURE(rv)) {
   2061         goto __cleanup;
   2062     }
   2063 
   2064     if (prof_index != old_prof_index) {
   2065         rv = _bcm_esw_port_tab_set(unit, port, _BCM_CPU_TABS_BOTH,
   2066                                    TRUST_DOT1P_PTRf, prof_index / MAP_SIZE);
   2067         if (BCM_FAILURE(rv)) {
   2068             goto __cleanup;
   2069         }
   2070     }
   2071 
   2072     if (old_prof_index != 0) {
   2073         rv = _bcm_ing_pri_cng_map_entry_delete(unit, old_prof_index);
   2074         if (BCM_FAILURE(rv)) {
   2075             goto __cleanup;
   2076         }
   2077     }
   2078 __cleanup:
   2079     /* Release port table lock */
   2080     soc_mem_unlock(unit, mem);
   2081     return rv;
   2082 }
   2083 
   2084 /*
   2085  * Function:
   2086  *      bcm_td3_port_ing_pri_cng_get
   2087  * Description:
   2088  *      Get packet priority and cfi to internal priority and color mapping
   2089  * Parameters:
   2090  *      unit         - (IN) Device number
   2091  *      port         - (IN) Port number
   2092  *      untagged     - (IN) For untagged packet (ignore pkt_pri, cfi argumnet)
   2093  *      pkt_pri      - (IN) Packet priority (802.1p cos)
   2094  *      cfi          - (IN) Packet CFI
   2095  *      int_pri      - (OUT) Internal priority
   2096  *      color        - (OUT) Color
   2097  * Return Value:
   2098  *      BCM_E_XXX
   2099  * Note:
   2100  *      When both pkt_pri and cfi are -1, the setting is for untagged packet
   2101  */
   2102 int
   2103 bcm_td3_port_ing_pri_cng_get(int unit, bcm_port_t port, int untagged,
   2104                              int pkt_pri, int cfi,
   2105                              int *int_pri, bcm_color_t *color)
   2106 {
   2107     ing_pri_cng_map_entry_t  map[MAP_SIZE];
   2108     void                     *entries[1];
   2109     uint32                   profile_index;
   2110     int                      index;
   2111     int                      hw_color;
   2112 
   2113     BCM_IF_ERROR_RETURN(_bcm_esw_port_tab_get(unit, port, TRUST_DOT1P_PTRf,
   2114                                (void *)&profile_index));
   2115     profile_index = profile_index * MAP_SIZE;
   2116 
   2117     entries[0] = map;
   2118 
   2119     BCM_IF_ERROR_RETURN
   2120         (_bcm_ing_pri_cng_map_entry_get(unit, profile_index, MAP_SIZE, entries));
   2121 
   2122     index = ((untagged != 0) << 4) | ((pkt_pri << 1) & 0xe) | (cfi & 0x1);
   2123 
   2124     if (int_pri != NULL) {
   2125         *int_pri = soc_mem_field32_get(unit, PHB_MAPPING_TBL_1m, &map[index],
   2126                                        INT_PRIf);
   2127     }
   2128     if (color != NULL) {
   2129         hw_color = soc_mem_field32_get(unit, PHB_MAPPING_TBL_1m, &map[index],
   2130                                        CNGf);
   2131         *color = _BCM_COLOR_DECODING(unit, hw_color);
   2132     }
   2133 
   2134     return BCM_E_NONE;
   2135 }
   2136 
   2137 /*
   2138  * Function:
   2139  *      bcm_td3_port_rate_egress_set
   2140  * Purpose:
   2141  *      Set egress metering information
   2142  * Parameters:
   2143  *      unit       - (IN) Unit number
   2144  *      port       - (IN) Port number
   2145  *      bandwidth  - (IN) Kilobits per second or packets per second
   2146  *                        zero if rate limiting is disabled
   2147  *      burst      - (IN) Maximum burst size in kilobits or packets
   2148  *      mode       - (IN) _BCM_PORT_RATE_BYTE_MODE or _BCM_PORT_RATE_PPS_MODE
   2149  * Returns:
   2150  *      BCM_E_XXX
   2151  */
   2152 int
   2153 bcm_td3_port_rate_egress_set(int unit, bcm_port_t port, uint32 bandwidth,
   2154                              uint32 burst, uint32 mode)
   2155 {
   2156     int phy_port, mmu_port, index;
   2157     soc_mem_t mem = MMU_MTRO_EGRMETERINGCONFIG_MEMm;
   2158     uint32 rval, itu_mode_sel;
   2159     mmu_mtro_egrmeteringconfig_mem_0_entry_t entry;
   2160     uint32 refresh_rate, bucketsize, granularity, flags;
   2161     int refresh_bitsize, bucket_bitsize;
   2162 
   2163     phy_port = SOC_INFO(unit).port_l2p_mapping[port];
   2164     mmu_port = SOC_INFO(unit).port_p2m_mapping[phy_port];
   2165 
   2166     sal_memset(&entry, 0, sizeof(entry));
   2167 
   2168     index = mmu_port % SOC_TD3_MMU_PORT_PER_PIPE;
   2169     mem = SOC_TD3_PMEM(unit, port, MMU_MTRO_EGRMETERINGCONFIG_MEM_PIPE0m,
   2170             MMU_MTRO_EGRMETERINGCONFIG_MEM_PIPE1m);
   2171 
   2172     /* If metering is disabled on this ingress port we are done. */
   2173     if (!bandwidth || !burst) {
   2174         SOC_IF_ERROR_RETURN
   2175             (soc_mem_write(unit, mem, MEM_BLOCK_ANY, index, &entry));
   2176         return BCM_E_NONE;
   2177     }
   2178 
   2179     if((bandwidth < _BCM_PORT_RATE_MIN_KILOBITS ||
   2180         bandwidth > _BCM_PORT_RATE_MAX_KILOBITS) ||
   2181         (burst < _BCM_PORT_BURST_MIN_KILOBITS ||
   2182         burst > _BCM_PORT_BURST_MAX_KILOBITS)) {
   2183         return BCM_E_PARAM;
   2184     }
   2185 
   2186     flags = mode == _BCM_PORT_RATE_PPS_MODE ?
   2187                         _BCM_TD_METER_FLAG_PACKET_MODE : 0;
   2188 
   2189     BCM_IF_ERROR_RETURN(READ_MMU_SEDCFG_MISCCONFIGr(unit, &rval));
   2190     itu_mode_sel = soc_reg_field_get(unit, MMU_SEDCFG_MISCCONFIGr, rval,
   2191                                      ITU_MODE_SELf);
   2192 
   2193     if (itu_mode_sel) {
   2194         flags |= _BCM_TD_METER_FLAG_NON_LINEAR;
   2195     }
   2196 
   2197     refresh_bitsize = soc_mem_field_length(unit, mem, REFRESHf);
   2198     bucket_bitsize = soc_mem_field_length(unit, mem, THD_SELf);
   2199     BCM_IF_ERROR_RETURN
   2200         (_bcm_td_rate_to_bucket_encoding(unit, bandwidth, burst, flags,
   2201                                          refresh_bitsize, bucket_bitsize,
   2202                                          &refresh_rate, &bucketsize,
   2203                                          &granularity));
   2204     soc_mem_field32_set(unit, mem, &entry, MODEf,
   2205                         mode == _BCM_PORT_RATE_PPS_MODE ? 1 : 0);
   2206     soc_mem_field32_set(unit, mem, &entry, METER_GRANf, granularity);
   2207     soc_mem_field32_set(unit, mem, &entry, REFRESHf, refresh_rate);
   2208     soc_mem_field32_set(unit, mem, &entry, THD_SELf, bucketsize);
   2209 
   2210     SOC_IF_ERROR_RETURN
   2211         (soc_mem_write(unit, mem, MEM_BLOCK_ANY, index, &entry));
   2212 
   2213     return BCM_E_NONE;
   2214 }
   2215 
   2216 /*
   2217  * Function:
   2218  *      bcm_td3_port_ipbm_opaque_set
   2219  * Purpose:
   2220  *      Set egress metering information
   2221  * Parameters:
   2222  *      unit       - (IN) Unit number
   2223  *      stm_idx    - (IN) SOURCE_TRUNK_MAP table index
   2224  *      class      - (IN) port class value(range 0-131)
   2225  * Returns:
   2226  *      BCM_E_XXX
   2227  */
   2228 int
   2229 bcm_td3_port_ipbm_opaque_set(int unit, int stm_idx, uint32 class)
   2230 {
   2231     int rv;
   2232     int temp_p;
   2233     uint32 pipe_port;
   2234     int max_port = 0;
   2235     uint32 ipbm_val = 0;
   2236     uint32 opq_obj_val = 0;
   2237     uint8 opaque_3 = _BCM_TD3_OPAQUE3_ID;
   2238     uint8 opaque_4 = _BCM_TD3_OPAQUE4_ID;
   2239     soc_mem_t mem = SOURCE_TRUNK_MAP_TABLEm;
   2240     soc_field_t ipbm_fld = IPBM_INDEXf;
   2241     soc_field_t opq_obj_fld = OPAQUE_OBJECTf;
   2242     source_trunk_map_table_entry_t stm_entry;
   2243 
   2244     if (!(SOC_MEM_FIELD_VALID(unit, mem, ipbm_fld) &&
   2245           SOC_MEM_FIELD_VALID(unit, mem, opq_obj_fld))) {
   2246         return BCM_E_UNAVAIL;
   2247     }
   2248 
   2249     max_port = _BCM_TD3_NUM_PIPE_PORTS;
   2250 
   2251     if(class >= max_port) {
   2252         return BCM_E_PARAM;
   2253     }
   2254 
   2255    /* Read source trunk map table. */
   2256     rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, stm_idx, &stm_entry);
   2257     BCM_IF_ERROR_RETURN(rv);
   2258 
   2259     pipe_port = class;
   2260 
   2261     /* Set IPBM_INDEX */
   2262     ipbm_val = (pipe_port < _FP_TD3_TCAM_IPBMP_SIZE) ? pipe_port : _FP_TD3_TCAM_IPBMP_SIZE+1;
   2263     soc_mem_field32_set(unit, mem, &stm_entry, ipbm_fld, ipbm_val);
   2264 
   2265     /* Set OPAQUE_OBJECT */
   2266     if (pipe_port >= _FP_TD3_TCAM_IPBMP_SIZE) {
   2267         if (pipe_port >= (_FP_TD3_TCAM_IPBMP_SIZE + _FP_FLEX_PBMP_SIZE)) {
   2268             opq_obj_val = opaque_4;
   2269             temp_p = pipe_port - (_FP_TD3_TCAM_IPBMP_SIZE + _FP_FLEX_PBMP_SIZE);
   2270         } else {
   2271             opq_obj_val = opaque_3;
   2272             temp_p = pipe_port - _FP_TD3_TCAM_IPBMP_SIZE;
   2273         }
   2274         opq_obj_val = ((1 << temp_p) << 3) | opq_obj_val;
   2275         soc_mem_field32_set(unit, mem, &stm_entry, opq_obj_fld, opq_obj_val);
   2276     }
   2277 
   2278     /* Write source trunk map table */
   2279     rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, stm_idx, &stm_entry);
   2280     BCM_IF_ERROR_RETURN(rv);
   2281 
   2282     return BCM_E_NONE;
   2283 }
   2284 
   2285 /*
   2286  * Function:
   2287  *      bcm_td3_port_ipbm_opaque_get
   2288  * Purpose:
   2289  *      Set egress metering information
   2290  * Parameters:
   2291  *      unit       - (IN) Unit number
   2292  *      stm_idx    - (IN) SOURCE_TRUNK_MAP table index
   2293  *      class      - (OUT) pointer of class
   2294  * Returns:
   2295  *      BCM_E_XXX
   2296  */
   2297 int
   2298 bcm_td3_port_ipbm_opaque_get(int unit, int stm_idx, uint32* class)
   2299 {
   2300     int rv;
   2301     uint32 temp_p;
   2302     uint32 ipbm_val = 0;
   2303     uint32 opq_obj_val = 0;
   2304     uint8 opaque_3 = _BCM_TD3_OPAQUE3_ID;
   2305     uint8 opaque_4 = _BCM_TD3_OPAQUE4_ID;
   2306     soc_mem_t mem = SOURCE_TRUNK_MAP_TABLEm;
   2307     soc_field_t ipbm_fld = IPBM_INDEXf;
   2308     soc_field_t opq_obj_fld = OPAQUE_OBJECTf;
   2309     source_trunk_map_table_entry_t stm_entry;
   2310     uint32 temp_cnt = 0;
   2311 
   2312     if (!(SOC_MEM_FIELD_VALID(unit, mem, ipbm_fld) &&
   2313           SOC_MEM_FIELD_VALID(unit, mem, opq_obj_fld))) {
   2314         return BCM_E_UNAVAIL;
   2315     }
   2316 
   2317    /* Read source trunk map table. */
   2318     rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, stm_idx, &stm_entry);
   2319     BCM_IF_ERROR_RETURN(rv);
   2320 
   2321     ipbm_val = soc_mem_field32_get(unit, mem, &stm_entry, ipbm_fld);
   2322 
   2323     if (ipbm_val < _FP_TD3_TCAM_IPBMP_SIZE) {
   2324         *class = ipbm_val;
   2325         return BCM_E_NONE;
   2326     } else {
   2327         temp_p = soc_mem_field32_get(unit, mem, &stm_entry, opq_obj_fld);
   2328         opq_obj_val = temp_p & _BCM_TD3_OPAQUE_ID_MASK;
   2329         temp_p = temp_p >> 3;
   2330         while ((temp_p = temp_p >> 1) > 0) {
   2331             temp_cnt++;
   2332         }
   2333         if (opq_obj_val == opaque_3) {
   2334             *class = temp_cnt + _FP_TD3_TCAM_IPBMP_SIZE;
   2335         } else if (opq_obj_val == opaque_4) {
   2336             *class = temp_cnt + _FP_TD3_TCAM_IPBMP_SIZE
   2337                                                  + _FP_FLEX_PBMP_SIZE;
   2338         } else {
   2339             return BCM_E_INTERNAL;
   2340         }
   2341 
   2342         return BCM_E_NONE;
   2343     }
   2344 }
   2345 
   2346 /*
   2347  * Function:
   2348  *      bcm_td3_port_rate_egress_get
   2349  * Purpose:
   2350  *      Get egress metering information
   2351  * Parameters:
   2352  *      unit       - (IN) Unit number
   2353  *      port       - (IN) Port number
   2354  *      bandwidth  - (OUT) Kilobits per second or packets per second
   2355  *                        zero if rate limiting is disabled
   2356  *      burst      - (OUT) Maximum burst size in kilobits or packets
   2357  *      mode       - (OUT) _BCM_PORT_RATE_BYTE_MODE or _BCM_PORT_RATE_PPS_MODE
   2358  * Returns:
   2359  *      BCM_E_XXX
   2360  */
   2361 int
   2362 bcm_td3_port_rate_egress_get(int unit, bcm_port_t port, uint32 *bandwidth,
   2363                              uint32 *burst, uint32 *mode)
   2364 {
   2365     int phy_port, mmu_port, index;
   2366     soc_mem_t mem = MMU_MTRO_EGRMETERINGCONFIG_MEMm;
   2367     uint32 rval, itu_mode_sel;
   2368     mmu_mtri_bkpmeteringconfig_mem_0_entry_t entry;
   2369     uint32 refresh_rate, bucketsize, granularity, flags;
   2370 
   2371     if (bandwidth == NULL || burst == NULL) {
   2372         return BCM_E_PARAM;
   2373     }
   2374 
   2375     phy_port = SOC_INFO(unit).port_l2p_mapping[port];
   2376     mmu_port = SOC_INFO(unit).port_p2m_mapping[phy_port];
   2377 
   2378     index = mmu_port % SOC_TD3_MMU_PORT_PER_PIPE;
   2379     mem = SOC_TD3_PMEM(unit, port, MMU_MTRO_EGRMETERINGCONFIG_MEM_PIPE0m,
   2380             MMU_MTRO_EGRMETERINGCONFIG_MEM_PIPE1m);
   2381 
   2382     SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ANY, index, &entry));
   2383 
   2384     refresh_rate = soc_mem_field32_get(unit, mem, &entry, REFRESHf);
   2385     bucketsize = soc_mem_field32_get(unit, mem, &entry, THD_SELf);
   2386     granularity = soc_mem_field32_get(unit, mem, &entry, METER_GRANf);
   2387 
   2388     flags = soc_mem_field32_get(unit, mem, &entry, MODEf) ?
   2389                 _BCM_TD_METER_FLAG_PACKET_MODE : 0;
   2390 
   2391     BCM_IF_ERROR_RETURN(READ_MMU_SEDCFG_MISCCONFIGr(unit, &rval));
   2392     itu_mode_sel = soc_reg_field_get(unit, MMU_SEDCFG_MISCCONFIGr, rval,
   2393                                      ITU_MODE_SELf);
   2394 
   2395     if (itu_mode_sel) {
   2396         flags |= _BCM_TD_METER_FLAG_NON_LINEAR;
   2397     }
   2398 
   2399     BCM_IF_ERROR_RETURN
   2400         (_bcm_td_bucket_encoding_to_rate(unit, refresh_rate, bucketsize,
   2401                                          granularity, flags, bandwidth, burst));
   2402 
   2403     *mode = flags & _BCM_TD_METER_FLAG_PACKET_MODE ?
   2404                 _BCM_PORT_RATE_PPS_MODE : _BCM_PORT_RATE_BYTE_MODE;
   2405 
   2406     return BCM_E_NONE;
   2407 
   2408 }
   2409 
   2410 int bcm_td3_port_drain_cells(int unit, int port)
   2411 {
   2412     mac_driver_t *macd;
   2413     int rv = BCM_E_NONE;
   2414 
   2415     if (IS_CPU_PORT(unit, port)) {
   2416         return BCM_E_PORT;
   2417     }
   2418 
   2419     /* Call Port Control module */
   2420     if (SOC_USE_PORTCTRL(unit)) {
   2421         return bcmi_esw_portctrl_egress_queue_drain(unit, port);
   2422     }
   2423 
   2424     PORT_LOCK(unit);
   2425     rv = soc_mac_probe(unit, port, &macd);
   2426 
   2427     if (BCM_SUCCESS(rv)) {
   2428         rv = MAC_CONTROL_SET(macd, unit, port, SOC_MAC_CONTROL_EGRESS_DRAIN, 1);
   2429 
   2430     }
   2431     PORT_UNLOCK(unit);
   2432     return rv;
   2433 }
   2434 
   2435 int
   2436 bcm_td3_port_init(int unit)
   2437 {
   2438     int rv = BCM_E_NONE;
   2439     int port;
   2440     /* VLAN control TBA in FlexPP (SDK-66866) */
   2441     /* Add default entries for SYSTEM_CONFIG_TABLE profile */
   2442 #if 0
   2443     /* TD3TBD */
   2444     int port, index;
   2445     uint16 tpid;
   2446 
   2447     tpid = _bcm_fb2_outer_tpid_default_get(unit);
   2448     BCM_IF_ERROR_RETURN(_bcm_fb2_outer_tpid_lkup(unit, tpid, &index));
   2449 
   2450     for (port = 0; port <= SOC_PORT_ADDR_MAX(unit); port++) {
   2451         BCM_IF_ERROR_RETURN(
   2452             _bcm_trx_source_trunk_map_set(unit, port,
   2453             OUTER_TPID_ENABLEf, 1 << index));
   2454     }
   2455     BCM_IF_ERROR_RETURN(_bcm_fb2_outer_tpid_tab_ref_count_add(unit, index, 1));
   2456 #endif
   2457 
   2458     /* Move from _soc_trident3_misc_init */
   2459     if (soc_feature(unit, soc_feature_egr_all_profile)) {
   2460         PBMP_ALL_ITER(unit, port) {
   2461             soc_field_t flds[3] = {
   2462                 VT_MISS_UNTAGf,
   2463                 REMARK_OUTER_DOT1Pf,
   2464                 OUTER_TPID_VALIDf
   2465             };
   2466             uint32 vals[3] = {0, 1, 1};
   2467             BCM_IF_ERROR_RETURN(bcm_esw_port_egr_lport_fields_set(unit,
   2468                 port, EGR_VLAN_CONTROL_1m, 3, flds, vals));
   2469         }
   2470     }
   2471 
   2472     return rv;
   2473 }
   2474 
   2475 int
   2476 bcmi_td3_speed_mix_validate(int unit, uint32 speed_mask)
   2477 {
   2478     return soc_td3_speed_mix_validate(unit, speed_mask);
   2479 }
   2480 
   2481 #define  FIELD_IDS_NUM   4
   2482 /*
   2483  * Function:
   2484  *      bcmi_td3_port_internal_loopback_set
   2485  * Purpose:
   2486  *      Put the port in the internal loopback mode 
   2487  *
   2488  * Parameters:
   2489  *      unit       - (IN) Unit number
   2490  *      port       - (IN) Port number
   2491  *      enable     - (IN) TRUE or FALSE
   2492  * Returns:
   2493  *      BCM_E_XXX
   2494  */
   2495 int bcmi_td3_port_internal_loopback_set(int unit, bcm_port_t port, int enable)
   2496 {
   2497     soc_field_t fld_ids[FIELD_IDS_NUM];
   2498     uint32 fld_values[FIELD_IDS_NUM];
   2499 
   2500     fld_ids[0]    = PORT_TYPEf;
   2501     fld_ids[1]    = PARSE_CONTEXT_ID_0f;
   2502     if (enable) { /* enable */
   2503         fld_values[0] = 2;
   2504         fld_values[1] = 4;
   2505     } else {
   2506         fld_values[0] = 0;
   2507         fld_values[1] = 6;
   2508     }
   2509 
   2510     BCM_IF_ERROR_RETURN(_bcm_esw_port_tab_multi_set(unit, port, 
   2511         _BCM_CPU_TABS_BOTH, 2, fld_ids, fld_values));
   2512     fld_ids[0]    = PORT_TYPEf;
   2513     fld_ids[1]    = EGR_PORT_CTRL_IDf;
   2514     fld_ids[2]    = EDIT_CTRL_IDf;
   2515     fld_ids[3]    = EM_SRCMOD_CHANGEf;
   2516     if (enable) { /* enable */
   2517         fld_values[0] = 2;
   2518         fld_values[1] = 2;
   2519         fld_values[2] = 3;
   2520         fld_values[3] = 0;
   2521     } else {
   2522         fld_values[0] = 0;
   2523         fld_values[1] = 1;
   2524         fld_values[2] = 0;
   2525         fld_values[3] = 1;
   2526     }
   2527     BCM_IF_ERROR_RETURN(_bcm_esw_egr_port_tab_multi_set(unit, port, 
   2528                      FIELD_IDS_NUM, fld_ids, fld_values));
   2529     if (enable) {
   2530         /* enable IPv4 L3 on loopback port. The CPU masquerade packet
   2531          * will reference the LPORT profile from source_trunk_map with
   2532          * port number set in the loopback header. The default LPORT
   2533          * profile index is 0 for all these masquerade ports.
   2534          */
   2535         SOC_IF_ERROR_RETURN(soc_mem_field32_modify(unit, LPORT_TABm, 0,
   2536                         V4L3_ENABLEf, 1));
   2537 
   2538     }
   2539     PORT_LOCK(unit);
   2540     if (enable) {
   2541         SOC_PBMP_PORT_ADD(SOC_INFO(unit).lb_pbm, port);
   2542     } else {
   2543         SOC_PBMP_PORT_REMOVE(SOC_INFO(unit).lb_pbm, port);
   2544     }
   2545     PORT_UNLOCK(unit);
   2546 
   2547     return BCM_E_NONE;
   2548 }
   2549 
   2550 #else /* BCM_TRIDENT3_SUPPORT */
   2551 int _td3_port_not_empty;
   2552 
   2553 #endif  /* BCM_TRIDENT3_SUPPORT */