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


      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:     XGS3 port function implementations
      9  *
     10  * int bcm_xgs3_port_cfg_init(int unit, bcm_port_t port, bcm_vlan_data_t *vd)
     11  * int bcm_xgs3_port_cfg_get(int unit, bcm_port_t port, bcm_port_cfg_t *cfg)
     12  * int bcm_xgs3_port_cfg_set(int unit, bcm_port_t port, bcm_port_cfg_t *cfg)
     13  */
     14 
     15 #include <soc/defs.h>
     16 
     17 #if defined(BCM_FIREBOLT_SUPPORT)
     18 
     19 #include <sal/core/libc.h>
     20 
     21 #include <soc/mem.h>
     22 #include <soc/debug.h>
     23 #include <soc/cm.h>
     24 #include <soc/drv.h>
     25 #include <soc/register.h>
     26 #include <soc/memory.h>
     27 #include <soc/ll.h>
     28 #include <soc/ptable.h>
     29 #include <soc/l2x.h>
     30 
     31 #include <bcm/port.h>
     32 #include <bcm/mirror.h>
     33 #include <bcm/error.h>
     34 
     35 #include <bcm_int/common/lock.h>
     36 #include <bcm_int/esw/mbcm.h>
     37 #include <bcm_int/esw/firebolt.h>
     38 #include <bcm_int/esw/triumph.h>
     39 #include <bcm_int/esw/mirror.h>
     40 #include <bcm_int/esw/stack.h>
     41 #include <bcm_int/esw/port.h>
     42 
     43 #ifdef BCM_TRIDENT_SUPPORT 
     44 #include <bcm_int/esw/trident.h>
     45 #endif /* BCM_TRIDENT_SUPPORT */
     46 
     47 #ifdef BCM_TRIDENT2_SUPPORT 
     48 #include <bcm_int/esw/trident2.h>
     49 #endif /* BCM_TRIDENT2_SUPPORT */
     50 
     51 #ifdef BCM_TRIDENT2PLUS_SUPPORT
     52 #include <bcm_int/esw/trident2plus.h>
     53 #endif /* BCM_TRIDENT2PLUS_SUPPORT */
     54 
     55 #ifdef BCM_HGPROXY_COE_SUPPORT
     56 #include <bcm_int/esw/subport.h>
     57 #include <bcm_int/esw/xgs5.h>
     58 #endif /* BCM_HGPROXY_COE_SUPPORT */
     59 
     60 #ifdef BCM_HURRICANE3_SUPPORT
     61 #include <bcm_int/esw/hurricane3.h>
     62 #endif /* BCM_HURRICANE3_SUPPORT */
     63 
     64 #ifdef BCM_TRX_SUPPORT
     65 #include <bcm_int/esw/trx.h>
     66 #endif /* BCM_TRX_SUPPORT */
     67 
     68 #include <bcm_int/esw_dispatch.h>
     69 
     70 
     71 /*
     72  * Function:
     73  *      _bcm_xgs3_port_table_read
     74  * Purpose:
     75  *      Read port table entry and parse it to a common 
     76  *      (bcm_port_cfg_t) structure.
     77  * Parameters:
     78  *      unit       - (IN)SOC unit number.
     79  *      port       - (IN)Port number.
     80  *      port_cfg   - (OUT)API port information structure.
     81  * Returns:
     82  *      BCM_E_XXX
     83  * Notes:
     84  *      The following port configuration settings
     85  *      do not apply to FB/ER ports:
     86  *
     87  *      port_cfg->pc_frame_type
     88  *      port_cfg->pc_ether_type
     89  *      port_cfg->pc_stp_state
     90  *      port_cfg->pc_cpu
     91  *      port_cfg->pc_ptype
     92  *      port_cfg->pc_pbm
     93  *      port_cfg->pc_ut_pbm
     94  *      port_cfg->pc_trunk
     95  *      port_cfg->pc_pfm
     96  *    The following port configuration do not apply to ER
     97  *       port_cfg->pc_nni_port
     98  */
     99 STATIC int
    100 _bcm_xgs3_port_table_read(int unit, bcm_port_t port,
    101                           bcm_port_cfg_t *port_cfg)
    102 {
    103     port_tab_entry_t ptab_entry;   /* Port table entry.             */
    104     int discard_tag;               /* Discard tagged packets bit.   */
    105     int discard_untag;             /* Discard untagged packets bit. */
    106     soc_mem_t mem = PORT_TABm;     /* Port table memory.            */
    107     int tbl_index = port;     /* Port table index.             */
    108     int rv;                        /* Operation return status.      */
    109 
    110     if (BCM_GPORT_IS_SET(port)) {
    111         BCM_IF_ERROR_RETURN(_bcm_esw_port_gport_validate(unit, port, &port));
    112     }
    113     tbl_index = port;
    114 
    115 #if defined(BCM_TRIDENT3_SUPPORT)
    116     if (SOC_MEM_IS_VALID(unit, ING_DEVICE_PORTm)) {
    117         mem = ING_DEVICE_PORTm;
    118     }
    119 #endif
    120 
    121     soc_mem_lock(unit, mem);
    122 
    123     /* Read port table entry from HW. */
    124     rv = BCM_XGS3_MEM_READ(unit, mem, tbl_index, &ptab_entry);
    125     if (BCM_FAILURE(rv)) {
    126        soc_mem_unlock(unit, mem);
    127        return (rv);
    128     }
    129 
    130     /* If port cpu managed learning is not frozen read it from port. */
    131     if (!soc_feature(unit, soc_feature_no_learning) && 
    132         soc_l2x_frozen_cml_get(unit, port, &port_cfg->pc_cml, &port_cfg->pc_cml_move) < 0) {
    133 #ifdef BCM_TRX_SUPPORT
    134         if (SOC_IS_TRX(unit)) {
    135             port_cfg->pc_cml = 
    136                 soc_mem_field32_get(unit, mem, &ptab_entry, CML_FLAGS_NEWf);
    137             port_cfg->pc_cml_move = 
    138                 soc_mem_field32_get(unit, mem, &ptab_entry, CML_FLAGS_MOVEf);
    139         } else
    140 #endif  /* BCM_TRX_SUPPORT */
    141         {
    142             port_cfg->pc_cml = soc_mem_field32_get(unit, mem, &ptab_entry, CMLf);
    143         }
    144     }
    145     soc_mem_unlock(unit, mem);
    146 
    147     /* Get drop all tagged packets flag. */
    148     discard_tag = soc_mem_field32_get(unit, mem,  &ptab_entry, PORT_DIS_TAGf);
    149 
    150     /* Get drop all untagged packets flag. */
    151     discard_untag = 
    152         soc_mem_field32_get(unit, mem,  &ptab_entry, PORT_DIS_UNTAGf);
    153 
    154     if (discard_tag && discard_untag) {
    155         port_cfg->pc_disc = BCM_PORT_DISCARD_ALL;
    156     } else if (discard_tag) {
    157         port_cfg->pc_disc = BCM_PORT_DISCARD_TAG;
    158     } else if (discard_untag) {
    159         port_cfg->pc_disc = BCM_PORT_DISCARD_UNTAG;
    160     } else {
    161         port_cfg->pc_disc = BCM_PORT_DISCARD_NONE;
    162     }
    163 
    164     /* Get drop bpdu's on ingress flag. */
    165     port_cfg->pc_bpdu_disable = 
    166         soc_mem_field32_get(unit, mem, &ptab_entry, DROP_BPDUf);
    167 
    168     /* Get enable mirroring flag. */
    169     if (soc_feature(unit, soc_feature_mirror_flexible)) {
    170         /* Multi-bit field */
    171         port_cfg->pc_mirror_ing =
    172             soc_mem_field32_get(unit, mem, &ptab_entry, MIRRORf);
    173     } else if (!soc_feature(unit, soc_feature_no_mirror) &&
    174                soc_mem_field32_get(unit, mem, &ptab_entry, MIRRORf)) {
    175         port_cfg->pc_mirror_ing |= BCM_MIRROR_MTP_ONE; 
    176     }
    177 
    178 
    179     /* Get port default vlan id (pvid). */
    180     port_cfg->pc_vlan = soc_mem_field32_get(unit, mem, &ptab_entry, PORT_VIDf);
    181 
    182 #ifdef BCM_TRX_SUPPORT
    183     if (SOC_IS_TRX(unit)) {
    184         if (SOC_MEM_FIELD_VALID(unit, mem, IVIDf)) {
    185             port_cfg->pc_ivlan = soc_mem_field32_get(unit, mem, &ptab_entry, IVIDf);
    186         }
    187         port_cfg->pc_vlan_action = soc_mem_field32_get(unit, mem, &ptab_entry, 
    188                                                        TAG_ACTION_PROFILE_PTRf);
    189     } else 
    190 #endif /* BCM_TRX_SUPPORT */
    191     {
    192         port_cfg->pc_ivlan = 0;
    193         port_cfg->pc_vlan_action = 0;
    194     }
    195 
    196     /* Get L3 IPv4 forwarding enable bit. */ 
    197     if (SOC_MEM_FIELD_VALID(unit, mem, V4L3_ENABLEf)) {
    198         if (soc_mem_field32_get(unit, mem, &ptab_entry, V4L3_ENABLEf)) { 
    199             port_cfg->pc_l3_flags |= BCM_PORT_L3_V4_ENABLE;
    200         }
    201     }
    202 
    203     /* Get L3 IPv6 forwarding enable bit. */ 
    204     if (SOC_MEM_FIELD_VALID(unit, mem, V6L3_ENABLEf)) {
    205         if (soc_mem_field32_get(unit, mem, &ptab_entry, V6L3_ENABLEf)) { 
    206             port_cfg->pc_l3_flags |= BCM_PORT_L3_V6_ENABLE;
    207         }
    208     }
    209 
    210     /* Get port default priority.*/ 
    211     if (soc_feature(unit, soc_feature_vlan_pri_cfi_action)) {
    212         port_cfg->pc_new_opri =
    213             soc_mem_field32_get(unit, mem, &ptab_entry, OPRIf);
    214         port_cfg->pc_new_ocfi =
    215             soc_mem_field32_get(unit, mem, &ptab_entry, OCFIf);
    216         if (SOC_MEM_FIELD_VALID(unit, mem, IPRIf)) {
    217             port_cfg->pc_new_ipri =
    218                 soc_mem_field32_get(unit, mem, &ptab_entry, IPRIf);
    219         }
    220         if (SOC_MEM_FIELD_VALID(unit, mem, ICFIf)) {
    221             port_cfg->pc_new_icfi =
    222                 soc_mem_field32_get(unit, mem, &ptab_entry, ICFIf);
    223         }
    224     } else {
    225         port_cfg->pc_new_opri = 
    226             soc_mem_field32_get(unit, mem, &ptab_entry, PORT_PRIf);
    227     }
    228 
    229     /* Get incoming packet overwrite/map priority. */
    230     if (SOC_MEM_FIELD_VALID(unit, mem, MAP_TAG_PKT_PRIORITYf)) {
    231         port_cfg->pc_remap_pri_en =
    232             soc_mem_field32_get(unit, mem, &ptab_entry, MAP_TAG_PKT_PRIORITYf);
    233     } else {
    234         port_cfg->pc_remap_pri_en = 0;
    235     }
    236 
    237     /* Get ingress port is trusted port, trust incoming IPv4 DSCP bit. */ 
    238     if (SOC_MEM_FIELD_VALID(unit, mem, TRUST_DSCP_V4f)) {
    239         port_cfg->pc_dse_mode =
    240             soc_mem_field32_get(unit, mem, &ptab_entry, TRUST_DSCP_V4f);
    241     }
    242 
    243     /* Get ingress port is trusted port, trust incoming IPv6 DSCP bit. */ 
    244     if (SOC_MEM_FIELD_VALID(unit, mem, TRUST_DSCP_V6f)) {
    245         port_cfg->pc_dse_mode_ipv6 =
    246             soc_mem_field32_get(unit, mem, &ptab_entry, TRUST_DSCP_V6f);
    247     }
    248 
    249     port_cfg->pc_dscp_prio = (port_cfg->pc_dse_mode |
    250             port_cfg->pc_dse_mode_ipv6);
    251     port_cfg->pc_dscp = -1;
    252 
    253     /* Get enable ingress filtering bit. */
    254     port_cfg->pc_en_ifilter =
    255         soc_mem_field32_get(unit, mem, &ptab_entry, EN_IFILTERf);
    256 
    257     /* Get enable L2 bridging on the incoming port. */
    258     if (SOC_MEM_FIELD_VALID(unit, mem, PORT_BRIDGEf)) {
    259         port_cfg->pc_bridge_port = 
    260             soc_mem_field32_get(unit, mem, &ptab_entry, PORT_BRIDGEf);
    261     }
    262 
    263     /* Get network to network port flag. (QinQ)  */
    264     if (SOC_MEM_FIELD_VALID(unit, mem, NNI_PORTf)) { 
    265         port_cfg->pc_nni_port = 
    266             soc_mem_field32_get(unit, mem, &ptab_entry, NNI_PORTf);
    267     }
    268 #if defined(BCM_TRX_SUPPORT) || defined(BCM_FIREBOLT2_SUPPORT)
    269     /* Unicast rpf mode. */
    270     if (SOC_MEM_FIELD_VALID(unit, mem, URPF_MODEf)) {
    271         port_cfg->pc_urpf_mode = soc_mem_field32_get(unit, mem, &ptab_entry,
    272                                                      URPF_MODEf);
    273     }
    274 
    275     /* Unicast rpf default gateway check. */
    276     if (SOC_MEM_FIELD_VALID(unit, mem, URPF_DEFAULTROUTECHECKf)) {
    277         port_cfg->pc_urpf_def_gw_check = 
    278             soc_mem_field32_get(unit, mem, &ptab_entry, URPF_DEFAULTROUTECHECKf);
    279     }
    280 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT */
    281 #if defined(BCM_TRX_SUPPORT)
    282     /* private VALN enable */
    283     if (SOC_MEM_FIELD_VALID(unit, mem, PVLAN_ENABLEf)) {
    284         port_cfg->pc_pvlan_enable = soc_mem_field32_get(unit, mem, &ptab_entry,
    285                                                         PVLAN_ENABLEf);
    286     }
    287 
    288     /* Get enable mirroring destination 2 flag. */
    289     if (SOC_MEM_FIELD_VALID(unit, mem, MIRROR1f)) {
    290         if (soc_mem_field32_get(unit, mem, &ptab_entry, MIRROR1f)) {
    291             port_cfg->pc_mirror_ing |= BCM_MIRROR_MTP_TWO; 
    292         }
    293     }
    294 #endif /* BCM_TRX_SUPPORT */
    295 
    296     return (BCM_E_NONE); 
    297 }
    298 
    299 /*
    300  * Function:
    301  *      _bcm_xgs3_port_table_write
    302  * Purpose:
    303  *      Prepare & write port table entry 
    304  * Parameters:
    305  *      unit       - (IN)SOC unit number.
    306  *      port       - (IN)Port number.
    307  *      port_cfg   - (IN)API port information structure.
    308  * Returns:
    309  *      BCM_E_XXX
    310  */
    311 STATIC int
    312 _bcm_xgs3_port_table_write(int unit, bcm_port_t port,
    313                            bcm_port_cfg_t *port_cfg)
    314 {
    315     int cml;                        /* CPU managed learning mode. */
    316     int repl_cml, repl_cml_move;    /* CPU managed learning mode. */
    317 #ifdef BCM_TRX_SUPPORT
    318     int cml_move;                   /* CPU managed learning mode. */
    319 #endif
    320 
    321     port_tab_entry_t ptab_entry;   /* Port table entry.          */
    322     soc_mem_t mem = PORT_TABm;     /* Port table memory.         */
    323     int tbl_index = port;          /* Port table index.          */
    324     int rv;
    325     int cpu_hg_index = 0;
    326 
    327     if (BCM_GPORT_IS_SET(port)) {
    328         BCM_IF_ERROR_RETURN(_bcm_esw_port_gport_validate(unit, port, &port));
    329     }
    330     tbl_index = port;
    331 
    332 #if defined(BCM_TRIDENT3_SUPPORT)
    333     if (SOC_MEM_IS_VALID(unit, ING_DEVICE_PORTm)) {
    334         mem = ING_DEVICE_PORTm;
    335     }
    336 #endif
    337 
    338     soc_mem_lock(unit, mem);    /* Lock port table */
    339 
    340     /* Read current port table entry from HW. */
    341     rv = BCM_XGS3_MEM_READ(unit, mem, tbl_index, &ptab_entry);
    342     if (BCM_FAILURE(rv)) {
    343         soc_mem_unlock(unit, mem);
    344         return rv;
    345     }
    346     /* Set drop all tagged/untagged packets flag. */
    347     switch (port_cfg->pc_disc) {
    348       case BCM_PORT_DISCARD_NONE:
    349           soc_mem_field32_set(unit, mem, &ptab_entry, PORT_DIS_TAGf, 0);
    350           soc_mem_field32_set(unit, mem, &ptab_entry, PORT_DIS_UNTAGf, 0);
    351           break;
    352       case BCM_PORT_DISCARD_ALL:
    353           soc_mem_field32_set(unit, mem, &ptab_entry, PORT_DIS_TAGf, 1);
    354           soc_mem_field32_set(unit, mem, &ptab_entry, PORT_DIS_UNTAGf, 1);
    355           break;
    356       case BCM_PORT_DISCARD_UNTAG:
    357           soc_mem_field32_set(unit, mem, &ptab_entry, PORT_DIS_TAGf, 0);
    358           soc_mem_field32_set(unit, mem, &ptab_entry, PORT_DIS_UNTAGf, 1);
    359           break;
    360       case BCM_PORT_DISCARD_TAG:
    361           soc_mem_field32_set(unit, mem, &ptab_entry, PORT_DIS_TAGf, 1);
    362           soc_mem_field32_set(unit, mem, &ptab_entry, PORT_DIS_UNTAGf, 0);
    363           break;
    364     }
    365 
    366     /* Set drop bpdu's on ingress flag. */
    367     soc_mem_field32_set(unit, mem, &ptab_entry, DROP_BPDUf,
    368                         port_cfg->pc_bpdu_disable);
    369 
    370     /* Set ingress mirroring flag. */
    371     if (soc_feature(unit, soc_feature_mirror_flexible)) {
    372         soc_mem_field32_set(unit, mem, &ptab_entry, MIRRORf, 
    373                 (port_cfg->pc_mirror_ing & BCM_TR2_MIRROR_MTP_MASK));
    374     } else if (!soc_feature(unit, soc_feature_no_mirror)) {
    375         soc_mem_field32_set(unit, mem, &ptab_entry, MIRRORf, 
    376                             (port_cfg->pc_mirror_ing & BCM_MIRROR_MTP_ONE));
    377     }
    378 
    379     /*
    380      * Set cpu managed learning (cml).
    381      * if unit is not frozen set the same value to port table.
    382      * else set port table (cml) to PVP_CML_FORWARD.
    383      */
    384     if (soc_l2x_frozen_cml_set(unit, port, port_cfg->pc_cml, 
    385                                port_cfg->pc_cml_move, &repl_cml, &repl_cml_move) < 0) {
    386         cml = port_cfg->pc_cml;
    387 #ifdef BCM_TRX_SUPPORT
    388         cml_move = port_cfg->pc_cml_move;
    389 #endif
    390     } else {
    391         cml = repl_cml;
    392 #ifdef BCM_TRX_SUPPORT
    393         cml_move = repl_cml_move;
    394 #endif
    395     }
    396 
    397 #ifdef BCM_TRX_SUPPORT
    398     if (SOC_IS_TRX(unit)) {
    399         if (SOC_MEM_FIELD_VALID(unit, mem, CML_FLAGS_NEWf)) {
    400             soc_mem_field32_set(unit, mem, &ptab_entry, CML_FLAGS_MOVEf, cml_move);
    401             soc_mem_field32_set(unit, mem, &ptab_entry, CML_FLAGS_NEWf, cml);
    402         }
    403         if (SOC_MEM_FIELD_VALID(unit, mem, IVIDf)) {
    404             soc_mem_field32_set(unit, mem, &ptab_entry, IVIDf, port_cfg->pc_ivlan);
    405         }
    406         soc_mem_field32_set(unit, mem, &ptab_entry, TAG_ACTION_PROFILE_PTRf,
    407                             port_cfg->pc_vlan_action);
    408     } else
    409 #endif  /* BCM_TRX_SUPPORT */
    410     {
    411         soc_mem_field32_set(unit, mem, &ptab_entry, CMLf, cml);
    412     }
    413 
    414     /* Set port default vlan id (pvid). */
    415     soc_mem_field32_set(unit, mem, &ptab_entry, PORT_VIDf, port_cfg->pc_vlan);
    416 
    417     /* Set L3 IPv4 forwarding enable bit. */ 
    418     if (SOC_MEM_FIELD_VALID(unit, mem, V4L3_ENABLEf)) {
    419         soc_mem_field32_set(unit, mem, &ptab_entry, V4L3_ENABLEf, 
    420             (port_cfg->pc_l3_flags & BCM_PORT_L3_V4_ENABLE) ? 1 : 0);
    421     }    
    422 
    423     /* Set L3 IPv6 forwarding enable bit. */ 
    424     if (SOC_MEM_FIELD_VALID(unit, mem, V6L3_ENABLEf)) {
    425         soc_mem_field32_set(unit, mem, &ptab_entry, V6L3_ENABLEf, 
    426             (port_cfg->pc_l3_flags & BCM_PORT_L3_V6_ENABLE) ? 1 : 0);
    427     }
    428 
    429     /* Set new port default priority.*/ 
    430     if (soc_feature(unit, soc_feature_vlan_pri_cfi_action)) {
    431         soc_mem_field32_set(unit, mem, &ptab_entry, PORT_PRIf, 
    432                         port_cfg->pc_new_opri);
    433         soc_mem_field32_set(unit, mem, &ptab_entry, OCFIf, 
    434                         port_cfg->pc_new_ocfi);
    435         if (SOC_MEM_FIELD_VALID(unit, mem, IPRIf)) {
    436             soc_mem_field32_set(unit, mem, &ptab_entry, IPRIf,
    437                             port_cfg->pc_new_ipri);
    438         }
    439         if (SOC_MEM_FIELD_VALID(unit, mem, ICFIf)) {
    440             soc_mem_field32_set(unit, mem, &ptab_entry, ICFIf,
    441                             port_cfg->pc_new_icfi);
    442         }
    443     } else {
    444         soc_mem_field32_set(unit, mem, &ptab_entry, PORT_PRIf, 
    445                         port_cfg->pc_new_opri);
    446     }
    447 
    448     /* Set incoming packet overwrite/map priority. */
    449     if (SOC_MEM_FIELD_VALID(unit, mem, MAP_TAG_PKT_PRIORITYf)) {
    450         soc_mem_field32_set(unit, mem, &ptab_entry, MAP_TAG_PKT_PRIORITYf, 
    451                             port_cfg->pc_remap_pri_en);
    452     }
    453 
    454     /* Set ingress port is trusted port, trust incoming IPv4 DSCP bit. */ 
    455     if (SOC_MEM_FIELD_VALID(unit, mem, TRUST_DSCP_V4f)) {
    456         soc_mem_field32_set(unit, mem, &ptab_entry, TRUST_DSCP_V4f, 
    457                         port_cfg->pc_dse_mode ? 1 : 0);
    458     }
    459 
    460     /* Set ingress port is trusted port, trust incoming IPv6 DSCP bit. */ 
    461     if (SOC_MEM_FIELD_VALID(unit, mem, TRUST_DSCP_V6f)) {
    462         soc_mem_field32_set(unit, mem, &ptab_entry, TRUST_DSCP_V6f, 
    463                         port_cfg->pc_dse_mode_ipv6 ? 1 : 0);
    464     }
    465 
    466     /* Set enable ingress filtering. */
    467     soc_mem_field32_set(unit, mem, &ptab_entry, EN_IFILTERf, 
    468                         port_cfg->pc_en_ifilter);
    469 
    470     /* Set enable ingress filtering. */
    471     if (SOC_MEM_FIELD_VALID(unit, mem, PORT_BRIDGEf)) {
    472         soc_mem_field32_set(unit, mem, &ptab_entry, PORT_BRIDGEf, 
    473                         port_cfg->pc_bridge_port);
    474     }
    475 
    476     if (SOC_MEM_FIELD_VALID(unit, mem, NNI_PORTf)) {
    477         /* Set network to network port flag. */
    478         soc_mem_field32_set(unit, mem, &ptab_entry, NNI_PORTf, 
    479                             port_cfg->pc_nni_port);
    480     }
    481 
    482 #if defined(BCM_TRX_SUPPORT) || defined(BCM_FIREBOLT2_SUPPORT)
    483     /* Unicast rpf mode. */
    484     if (SOC_MEM_FIELD_VALID(unit, mem, URPF_MODEf)) {
    485         soc_mem_field32_set(unit, mem, &ptab_entry, URPF_MODEf,
    486                             port_cfg->pc_urpf_mode);
    487     }
    488 
    489     /* Unicast rpf default gateway check. */
    490     if (SOC_MEM_FIELD_VALID(unit, mem, URPF_DEFAULTROUTECHECKf)) {
    491         soc_mem_field32_set(unit, mem, &ptab_entry, URPF_DEFAULTROUTECHECKf,
    492                             port_cfg->pc_urpf_def_gw_check);
    493     }
    494 #endif /* BCM_TRX_SUPPORT || BCM_FIREBOLT2_SUPPORT */
    495 #if defined(BCM_TRX_SUPPORT)
    496     /* private VALN enable */
    497     if (SOC_MEM_FIELD_VALID(unit, mem, PVLAN_ENABLEf)) {
    498         soc_mem_field32_set(unit, mem, &ptab_entry, PVLAN_ENABLEf,
    499                             port_cfg->pc_pvlan_enable);
    500     }
    501 
    502     /* Set ingress mirroring destination 2 enable flag. */
    503     if (SOC_MEM_FIELD_VALID(unit, mem, MIRROR1f)) {
    504         soc_mem_field32_set(unit, mem, &ptab_entry, MIRROR1f, 
    505                             ((port_cfg->pc_mirror_ing & BCM_MIRROR_MTP_TWO) ? 1 : 0));
    506 
    507     }
    508 #endif /* BCM_TRX_SUPPORT */
    509 
    510     /* Write entry to hw. */
    511     rv = BCM_XGS3_MEM_WRITE(unit, mem, tbl_index, &ptab_entry);
    512     if (BCM_FAILURE(rv)) {
    513         soc_mem_unlock(unit, mem);
    514         return rv;
    515     }
    516 
    517     /*
    518      * Set config to IPORT_TABLEm for the CPU port.
    519      * IPORT table's higig_packet field must be 1.
    520      */
    521     cpu_hg_index = SOC_IS_KATANA2(unit) ?
    522                    SOC_INFO(unit).cpu_hg_pp_port_index :
    523                    SOC_INFO(unit).cpu_hg_index;
    524     if (IS_CPU_PORT(unit, port)) {
    525         int value = 0;
    526         soc_mem_t cpu_hg_mem = INVALIDm;
    527         port_tab_entry_t iptab_entry; 
    528         if (SOC_MEM_FIELD_VALID(unit, mem, HIGIG_PACKETf)) {
    529             soc_mem_field32_set(unit, mem, &ptab_entry, HIGIG_PACKETf, 1);
    530         } else if (SOC_MEM_FIELD_VALID(unit, mem, PORT_TYPEf)) {
    531             soc_mem_field32_set(unit, mem, &ptab_entry, PORT_TYPEf, 1);
    532         }
    533 
    534         if (SOC_MEM_IS_VALID(unit, IPORT_TABLEm)) {
    535             cpu_hg_mem = IPORT_TABLEm;
    536             tbl_index = port;
    537         } else if (cpu_hg_index != -1) {
    538             cpu_hg_mem = mem;
    539             tbl_index = cpu_hg_index;
    540         }
    541 
    542         if(cpu_hg_mem != INVALIDm) {
    543             rv = soc_mem_read(unit, cpu_hg_mem, MEM_BLOCK_ANY, tbl_index, &iptab_entry);
    544             if (BCM_FAILURE(rv)) {
    545                 soc_mem_unlock(unit, mem);
    546                 return rv;
    547             }
    548             
    549             if (SOC_MEM_FIELD_VALID(unit, cpu_hg_mem, DISABLE_VLAN_CHECKSf)) {
    550                 value = soc_mem_field32_get(unit, cpu_hg_mem, &iptab_entry, DISABLE_VLAN_CHECKSf);
    551                 soc_mem_field32_set(unit, cpu_hg_mem, &ptab_entry, DISABLE_VLAN_CHECKSf, value);
    552             }
    553             
    554             /*
    555             * If other fields like DISABLE_VLAN_CHECKSf, add to here.
    556             */           
    557             rv = soc_mem_write(unit, cpu_hg_mem, MEM_BLOCK_ALL, tbl_index, &ptab_entry);
    558             if (BCM_FAILURE(rv)) {
    559                 soc_mem_unlock(unit, mem);
    560                 return rv;
    561             }
    562         }        
    563     }
    564     
    565     soc_mem_unlock(unit, mem); /* Unlock port table */
    566 
    567     return BCM_E_NONE;
    568 }
    569 
    570 /*
    571  * Function:
    572  *      _bcm_xgs3_trunk_table_read
    573  * Purpose:
    574  *      Read trunk table entry and parse it to common
    575  *      (bcm_port_cfg_t) structure.
    576  * Parameters:
    577  *      unit       - (IN)SOC unit number.
    578  *      port       - (IN)Port number.
    579  *      tid        - (OUT)Trunk group ID.
    580  * Returns:
    581  *      BCM_E_XXX
    582  */
    583 int
    584 _bcm_xgs3_trunk_table_read(int unit, bcm_port_t port, int *tid)
    585 {
    586     int    my_modid;
    587     int    src_trk_idx = 0; /*Source Trunk table index.*/
    588     source_trunk_map_table_entry_t trunk_map_entry;/*Trunk table entry buffer.*/
    589     soc_field_t tgid_fld = TGIDf;
    590 
    591     if (SOC_MEM_FIELD_VALID(unit, SOURCE_TRUNK_MAP_TABLEm, SRC_TGIDf)) {
    592         tgid_fld = SRC_TGIDf;
    593     }
    594 
    595     /* Get module id for unit. */
    596     BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_modid));
    597 
    598     /* Get index to source trunk map table */
    599     BCM_IF_ERROR_RETURN(_bcm_esw_src_mod_port_table_index_get(unit, my_modid,
    600                 port, &src_trk_idx));
    601 
    602     /* Read source trunk map table. */
    603     SOC_IF_ERROR_RETURN (BCM_XGS3_MEM_READ(unit, SOURCE_TRUNK_MAP_TABLEm, 
    604                                            src_trk_idx, &trunk_map_entry));
    605 
    606     /* Get trunk group id. */
    607     *tid = 0;
    608     if (1 == soc_mem_field32_get(unit, SOURCE_TRUNK_MAP_TABLEm,
    609                 &trunk_map_entry, PORT_TYPEf)) {
    610         *tid = soc_mem_field32_get(unit, SOURCE_TRUNK_MAP_TABLEm,
    611                 &trunk_map_entry, tgid_fld);
    612     }
    613 
    614     return (BCM_E_NONE); 
    615 }
    616 
    617 /*
    618  * Function:
    619  *      _bcm_xgs3_trunk_table_write
    620  * Purpose:
    621  *      Write trunk table entry.
    622  * Parameters:
    623  *      unit       - (IN)SOC unit number.
    624  *      port       - (IN)Port number.
    625  *      tid        - (IN)Trunk group ID. 
    626  * Returns:
    627  *      BCM_E_XXX
    628  */
    629 int
    630 _bcm_xgs3_trunk_table_write(int unit, bcm_port_t port, int tid)
    631 {
    632     int    rv;
    633     int    tgid;
    634     int    port_type;
    635     int    my_modid;
    636     int    src_trk_idx = 0; /*Source Trunk table index.*/
    637     source_trunk_map_table_entry_t trunk_map_entry;/*Trunk table entry buffer.*/
    638     soc_field_t tgid_fld = TGIDf;
    639 
    640     if (SOC_MEM_FIELD_VALID(unit, SOURCE_TRUNK_MAP_TABLEm, SRC_TGIDf)) {
    641         tgid_fld = SRC_TGIDf;
    642     }
    643 
    644     if (tid != BCM_TRUNK_INVALID) {
    645         tgid = tid;
    646         port_type = 1;
    647     } else {
    648         tgid = 0;
    649         port_type = 0;
    650     }
    651 
    652     /* Get module id for unit. */
    653     BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_modid));
    654 
    655     /* Get index to source trunk map table */
    656     BCM_IF_ERROR_RETURN(_bcm_esw_src_mod_port_table_index_get(unit, my_modid,
    657                 port, &src_trk_idx));
    658 
    659     soc_mem_lock(unit, SOURCE_TRUNK_MAP_TABLEm);
    660 
    661     /* Read source trunk map table. */
    662     rv = BCM_XGS3_MEM_READ(unit, SOURCE_TRUNK_MAP_TABLEm, 
    663             src_trk_idx, &trunk_map_entry);
    664     if (BCM_FAILURE(rv)) {
    665         soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm);
    666         return rv;
    667     }
    668 
    669     /* Set trunk group id. */ 
    670     soc_mem_field32_set(unit, SOURCE_TRUNK_MAP_TABLEm, &trunk_map_entry,
    671             tgid_fld, tgid);
    672 
    673     /* Set port is part of trunk flag. */
    674     soc_mem_field32_set(unit, SOURCE_TRUNK_MAP_TABLEm, &trunk_map_entry,
    675             PORT_TYPEf, port_type);
    676 
    677     /* Write entry to hw. */
    678     rv = BCM_XGS3_MEM_WRITE(unit, SOURCE_TRUNK_MAP_TABLEm,
    679             src_trk_idx, &trunk_map_entry);
    680 
    681     soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm);
    682 
    683     return rv; 
    684 }
    685 
    686 #ifdef  BCM_FIREBOLT_SUPPORT
    687 /*
    688  * Function:
    689  *      _bcm_fb_port_cfg_init
    690  * Purpose:
    691  *      Initialize port configuration according to Initial System
    692  *      Configuration (see init.c)
    693  * Parameters:
    694  *      unit       - (IN)StrataSwitch unit number.
    695  *      port       - (IN)Port number.
    696  *      vlan_data  - (IN)Initial VLAN data information
    697  * Returns:
    698  *      BCM_E_XXX
    699  */
    700 int
    701 _bcm_fb_port_cfg_init(int unit, bcm_port_t port, bcm_vlan_data_t *vlan_data)
    702 {
    703     port_tab_entry_t ptab;                 /* Port table entry. */
    704     soc_field_t field_ids[SOC_MAX_MEM_FIELD_WORDS], port_type_field;
    705     uint32 field_values[SOC_MAX_MEM_FIELD_WORDS], port_type;
    706     soc_field_t lp_field_ids[SOC_MAX_MEM_FIELD_WORDS];
    707     uint32 lp_field_values[SOC_MAX_MEM_FIELD_WORDS];
    708     soc_reg_t egr_port_reg = EGR_PORTr;
    709     soc_reg_t iegr_port_reg = IEGR_PORTr;
    710     int field_count;
    711     int lp_field_count = 0;
    712     int cpu_hg_index = 0;
    713 #if defined(BCM_TRIDENT2PLUS_SUPPORT) || defined(BCM_GREYHOUND2_SUPPORT)
    714     int rtag7_profile_idx = 0;
    715 #endif /* BCM_TRIDENT2PLUS_SUPPORT || BCM_GREYHOUND2_SUPPORT */
    716 #ifdef BCM_TRX_SUPPORT
    717     int key_type_value;
    718 #endif
    719     soc_mem_t mem = PORT_TABm;
    720     int rv = BCM_E_NONE;
    721 
    722 #ifdef BCM_TRIUMPH_SUPPORT
    723     int dual_modid = 0;
    724 
    725     if ((SOC_IS_TR_VL(unit)) && (NUM_MODID(unit) >= 2)) {
    726         dual_modid = 1;
    727     }
    728 
    729     if (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) || 
    730         SOC_IS_VALKYRIE2(unit) || SOC_IS_GREYHOUND(unit) ||
    731         SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) {
    732         egr_port_reg = EGR_PORT_64r;
    733         iegr_port_reg = IEGR_PORT_64r;
    734     }
    735 #endif
    736 
    737     if (SOC_MEM_IS_VALID(unit, ING_DEVICE_PORTm)) {
    738         mem = ING_DEVICE_PORTm;
    739     }
    740 
    741     if (SOC_MEM_FIELD_VALID(unit, mem, PORT_TYPEf)) {
    742         port_type_field = PORT_TYPEf;
    743     } else {
    744         port_type_field = HIGIG_PACKETf;
    745     }
    746 
    747     if (IS_ST_PORT(unit, port)) {
    748         port_type = 1;
    749     } else if (IS_LB_PORT(unit, port)) {
    750         port_type = 2;
    751     } else {
    752         port_type = 0;
    753     }
    754 
    755     field_ids[0] = port_type_field;
    756     field_values[0] = port_type;
    757     field_ids[1] = EN_EFILTERf;
    758     field_values[1] = 1;
    759     field_count = 2;
    760 
    761 #ifdef BCM_TRIUMPH_SUPPORT
    762     if (SOC_IS_TR_VL(unit)) {
    763         /* Enable/disable dual-modid */
    764         if (soc_reg_field_valid(unit, egr_port_reg, DUAL_MODID_ENABLEf)) {
    765             field_ids[field_count] = DUAL_MODID_ENABLEf;
    766             field_values[field_count] = dual_modid;
    767             field_count++;
    768         } else if (SOC_MEM_FIELD_VALID(unit, EGR_PORTm, DUAL_MODID_ENABLEf)) {
    769             BCM_IF_ERROR_RETURN
    770                 (soc_mem_field32_modify(unit, EGR_PORTm, port, DUAL_MODID_ENABLEf,
    771                                         dual_modid));
    772         }
    773         if (IS_XE_PORT(unit, port)) {
    774             if (soc_reg_field_valid(unit, XMODID_DUAL_ENr, DUAL_MODID_ENf)) {
    775                 BCM_IF_ERROR_RETURN
    776                     (soc_reg_field32_modify(unit, XMODID_DUAL_ENr, port,
    777                                             DUAL_MODID_ENf, dual_modid));
    778             } else if (soc_reg_field_valid(unit, XMODID_ENr, DUAL_MODID_ENf)) {
    779                 BCM_IF_ERROR_RETURN
    780                     (soc_reg_field32_modify(unit, XMODID_ENr, port,
    781                                             DUAL_MODID_ENf, dual_modid));
    782             }
    783         }
    784 
    785 #ifdef BCM_MONTEREY_SUPPORT
    786         if (SOC_IS_MONTEREY(unit)) {
    787             if (port < 67) {
    788                 BCM_IF_ERROR_RETURN
    789                    (soc_mem_field32_modify(unit, EGR_PORTm, port, MISC_PORT_PROFILE_INDEXf,
    790                                             port));
    791                 BCM_IF_ERROR_RETURN
    792                    (soc_mem_field32_modify(unit, EGR_LPORT_PROFILEm, port + 1,
    793                                            MISC_PORT_PROFILE_INDEXf, port));
    794                 BCM_IF_ERROR_RETURN
    795                    (soc_mem_field32_modify(unit, EGR_LPORT_PROFILEm, port + 1,
    796                                            EN_EFILTERf, 1));
    797             }
    798         }
    799 #endif
    800 
    801     }
    802 #endif
    803 #ifdef BCM_TRX_SUPPORT
    804     if (SOC_IS_TRX(unit) && !SOC_IS_TOMAHAWK3(unit)) {
    805         /* Initialize egress vlan translation port class with identity mapping */
    806         field_ids[field_count] = VT_PORT_GROUP_IDf;
    807         if (SOC_IS_TOMAHAWKX(unit) || SOC_IS_TRIDENT3X(unit)) {
    808             uint32 gid;
    809             uint32 max_gid;
    810 
    811             /* VT_PORT_GROUP_IDf cannot fit entire valid port number.
    812              * any port number greater than max group id
    813              * will be set as max group id.
    814              */
    815             max_gid = soc_mem_field_length(unit, EGR_PORTm, 
    816                       VT_PORT_GROUP_IDf);
    817             if (max_gid > 31) {
    818                 return BCM_E_INTERNAL;
    819             }
    820             max_gid = (1 << max_gid) - 1;
    821             if (port < max_gid) {
    822                 gid = port;
    823             } else {
    824                 gid = max_gid;
    825             } 
    826             field_values[field_count] = gid;
    827         } else {
    828             field_values[field_count] = port;
    829         }
    830         field_count++;
    831     }
    832 #endif
    833 
    834 #if defined(BCM_RAPTOR_SUPPORT) || defined(BCM_TRIDENT_SUPPORT)
    835     /* For some devices, directed mirroring will always be 1 */
    836     if (soc_feature(unit, soc_feature_directed_mirror_only)) {
    837         field_ids[field_count] = EM_SRCMOD_CHANGEf;
    838         field_values[field_count] = 1;
    839         field_count++;
    840     }
    841 #endif
    842 
    843 #ifdef BCM_SHADOW_SUPPORT
    844     /* EGR_PORT fields are Unsupported in shadow */
    845     if (SOC_IS_SHADOW(unit)) {
    846         field_count = 0;
    847     }
    848 #endif
    849 
    850     if (SOC_MEM_IS_VALID(unit, EGR_PORTm)) {
    851         BCM_IF_ERROR_RETURN 
    852             (soc_mem_fields32_modify(unit, EGR_PORTm, port, field_count,
    853                                      field_ids, field_values));
    854     } else {
    855         /*  Update EGR_PORTr register. */
    856         BCM_IF_ERROR_RETURN 
    857             (soc_reg_fields32_modify(unit, egr_port_reg, port, field_count,
    858                                      field_ids, field_values));
    859     }
    860 
    861 #define LPORT_TAB_SYNC(_u_, _p_, _fld_, _val_)                              \
    862     {                                                                       \
    863         if (!IS_CPU_PORT(_u_, _p_)) {                                       \
    864             if (SOC_IS_TOMAHAWKX(_u_) ||                                    \
    865                 SOC_IS_TD2P_TT2P(_u_)) {                                    \
    866                 if (SOC_MEM_IS_VALID(_u_, LPORT_TABm)) {                    \
    867                     lp_field_ids[lp_field_count] = _fld_;                   \
    868                     lp_field_values[lp_field_count] = _val_;                \
    869                     lp_field_count ++;                                      \
    870                 }                                                           \
    871             }                                                               \
    872         }                                                                   \
    873     }                                                                       \
    874 
    875     /* Write PORT_TABm memory */
    876     sal_memcpy(&ptab, soc_mem_entry_null(unit, mem), sizeof (ptab));
    877 
    878     /* Set default  vlan id(pvid) for port. */
    879     soc_mem_field32_set(unit, mem, &ptab, PORT_VIDf, vlan_data->vlan_tag);
    880     LPORT_TAB_SYNC(unit, port, PORT_VIDf, vlan_data->vlan_tag);
    881 
    882     /* Switching VLAN. */
    883     if (SOC_MEM_FIELD_VALID(unit, mem, OUTER_TPIDf)) {
    884         soc_mem_field32_set(unit, mem, &ptab, OUTER_TPIDf, 0x8100);
    885         LPORT_TAB_SYNC(unit, port, OUTER_TPIDf, 0x8100);
    886     }
    887 
    888     /* Enable mac based vlan classification. */
    889     if (SOC_MEM_FIELD_VALID(unit, mem, MAC_BASED_VID_ENABLEf)) {
    890         soc_mem_field32_set(unit, mem, &ptab, MAC_BASED_VID_ENABLEf, 1);
    891         LPORT_TAB_SYNC(unit, port, MAC_BASED_VID_ENABLEf, 1);
    892     }
    893 
    894     /* Enable subned based vlan classification. */
    895     if (SOC_MEM_FIELD_VALID(unit, mem, SUBNET_BASED_VID_ENABLEf)) {
    896         soc_mem_field32_set(unit, mem, &ptab, SUBNET_BASED_VID_ENABLEf, 1);
    897         LPORT_TAB_SYNC(unit, port, SUBNET_BASED_VID_ENABLEf, 1);
    898     }
    899 
    900     /* Set port type. */
    901     soc_mem_field32_set(unit, mem, &ptab, port_type_field, port_type);
    902     LPORT_TAB_SYNC(unit, port, port_type_field, port_type);
    903 
    904 #if defined(BCM_RAVEN_SUPPORT) || defined(BCM_TRX_SUPPORT)
    905     if (SOC_MEM_FIELD_VALID(unit, mem, TRUST_INCOMING_VIDf)) {
    906         soc_mem_field32_set(unit, mem, &ptab, TRUST_INCOMING_VIDf, 1);
    907         LPORT_TAB_SYNC(unit, port, TRUST_INCOMING_VIDf, 1);
    908     }
    909 #endif /* BCM_RAVEN_SUPPORT || BCM_TRX_SUPPORT */
    910 
    911 #ifdef BCM_TRX_SUPPORT
    912     /* Set identify mapping for pri/cfi re-mapping */
    913     if (SOC_MEM_FIELD_VALID(unit, mem, PRI_MAPPINGf)) {
    914         soc_mem_field32_set(unit, mem, &ptab, PRI_MAPPINGf, 0xfac688);
    915         LPORT_TAB_SYNC(unit, port, PRI_MAPPINGf, 0xfac688);
    916         soc_mem_field32_set(unit, mem, &ptab, CFI_0_MAPPINGf, 0);
    917         LPORT_TAB_SYNC(unit, port, CFI_0_MAPPINGf, 0);
    918         soc_mem_field32_set(unit, mem, &ptab, CFI_1_MAPPINGf, 1);
    919         LPORT_TAB_SYNC(unit, port, CFI_1_MAPPINGf, 1);
    920     }
    921 
    922 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
    923     /* Set identify mapping for ipri/icfi re-mapping */
    924     if (SOC_MEM_FIELD_VALID(unit, mem, IPRI_MAPPINGf)) {
    925         soc_mem_field32_set(unit, mem, &ptab, IPRI_MAPPINGf, 0xfac688);
    926         soc_mem_field32_set(unit, mem, &ptab, ICFI_0_MAPPINGf, 0);
    927         soc_mem_field32_set(unit, mem, &ptab, ICFI_1_MAPPINGf, 1);
    928     }
    929 #endif
    930 
    931     /* Set the CML to PVP_CML_SWITCH by default (hw learn and forward) */
    932     if (SOC_MEM_FIELD_VALID(unit, mem, CML_FLAGS_NEWf)) {
    933         soc_mem_field32_set(unit, mem, &ptab, CML_FLAGS_NEWf, 0x8);
    934         LPORT_TAB_SYNC(unit, port, CML_FLAGS_NEWf, 0x8);
    935         soc_mem_field32_set(unit, mem, &ptab, CML_FLAGS_MOVEf, 0x8);
    936         LPORT_TAB_SYNC(unit, port, CML_FLAGS_MOVEf, 0x8);
    937     }
    938 
    939     /* Set first VLAN_XLATE key-type to {outer,port}.
    940      * Set second VLAN_XLATE key-type to {inner,port}.
    941      */
    942     if (SOC_MEM_FIELD_VALID(unit, mem, VT_KEY_TYPEf)) {
    943         BCM_IF_ERROR_RETURN
    944             (_bcm_esw_pt_vtkey_type_value_get(unit,
    945                      VLXLT_HASH_KEY_TYPE_OVID,&key_type_value));
    946         soc_mem_field32_set(unit, mem, &ptab, VT_KEY_TYPEf,
    947                                   key_type_value);
    948 #if defined(BCM_GREYHOUND2_SUPPORT)
    949         if (soc_feature(unit, soc_feature_vxlan_lite_riot)) {
    950             if (!IS_CPU_PORT(unit, port)) {
    951                 lp_field_ids[lp_field_count] = VT_KEY_TYPEf;
    952                 lp_field_values[lp_field_count] = key_type_value;
    953                 lp_field_count++;
    954             }
    955         } else
    956 #endif /* BCM_GREYHOUND2_SUPPORT */
    957         {
    958             LPORT_TAB_SYNC(unit, port, VT_KEY_TYPEf, key_type_value);
    959         }
    960 
    961         if (SOC_IS_KATANA(unit)) {
    962             BCM_IF_ERROR_RETURN
    963             (_bcm_esw_port_tab_set(unit, port, _BCM_CPU_TABS_NONE,
    964                     VT_KEY_TYPEf, key_type_value));
    965 
    966         }
    967     }
    968     if (SOC_MEM_FIELD_VALID(unit, mem, VT_KEY_TYPE_USE_GLPf)) {
    969         soc_mem_field32_set(unit, mem, &ptab, VT_KEY_TYPE_USE_GLPf, 1);
    970 #if defined(BCM_GREYHOUND2_SUPPORT)
    971         if (soc_feature(unit, soc_feature_vxlan_lite_riot)) {
    972             if (!IS_CPU_PORT(unit, port)) {
    973                 lp_field_ids[lp_field_count] = VT_KEY_TYPE_USE_GLPf;
    974                 lp_field_values[lp_field_count] = 1;
    975                 lp_field_count++;
    976             }
    977         } else
    978 #endif /* BCM_GREYHOUND2_SUPPORT */
    979         {
    980             LPORT_TAB_SYNC(unit, port, VT_KEY_TYPE_USE_GLPf, 1);
    981         }
    982 
    983         if (SOC_IS_KATANA(unit)) {
    984             BCM_IF_ERROR_RETURN
    985             (_bcm_esw_port_tab_set(unit, port, _BCM_CPU_TABS_NONE,
    986                     VT_KEY_TYPE_USE_GLPf, 1));
    987         }
    988     }
    989     if (SOC_MEM_FIELD_VALID(unit, mem, VT_PORT_TYPE_SELECTf)) {
    990         soc_mem_field32_set(unit, mem, &ptab, VT_PORT_TYPE_SELECTf, 1);
    991         LPORT_TAB_SYNC(unit, port, VT_PORT_TYPE_SELECTf, 1);
    992     }
    993     if (SOC_MEM_FIELD_VALID(unit, mem, VT_KEY_TYPE_2f)) {
    994         BCM_IF_ERROR_RETURN
    995             (_bcm_esw_pt_vtkey_type_value_get(unit,
    996                      VLXLT_HASH_KEY_TYPE_IVID,&key_type_value));
    997         soc_mem_field32_set(unit, mem, &ptab, VT_KEY_TYPE_2f,
    998                                   key_type_value);
    999 #if defined(BCM_GREYHOUND2_SUPPORT)
   1000         if (soc_feature(unit, soc_feature_vxlan_lite_riot)) {
   1001             if (!IS_CPU_PORT(unit, port)) {
   1002                 lp_field_ids[lp_field_count] = VT_KEY_TYPE_2f;
   1003                 lp_field_values[lp_field_count] = key_type_value;
   1004                 lp_field_count++;
   1005             }
   1006         } else
   1007 #endif /* BCM_GREYHOUND2_SUPPORT */
   1008         {
   1009             LPORT_TAB_SYNC(unit, port, VT_KEY_TYPE_2f, key_type_value);
   1010         }
   1011 
   1012         if (SOC_IS_KATANA(unit)) {
   1013             BCM_IF_ERROR_RETURN
   1014             (_bcm_esw_port_tab_set(unit, port, _BCM_CPU_TABS_NONE,
   1015                     VT_KEY_TYPE_2f, key_type_value));
   1016         }
   1017     }
   1018     if (SOC_MEM_FIELD_VALID(unit, mem, VT_KEY_TYPE_2_USE_GLPf)) {
   1019         soc_mem_field32_set(unit, mem, &ptab, VT_KEY_TYPE_2_USE_GLPf, 1);
   1020 #if defined(BCM_GREYHOUND2_SUPPORT)
   1021         if (soc_feature(unit, soc_feature_vxlan_lite_riot)) {
   1022             if (!IS_CPU_PORT(unit, port)) {
   1023                 lp_field_ids[lp_field_count] = VT_KEY_TYPE_2_USE_GLPf;
   1024                 lp_field_values[lp_field_count] = 1;
   1025                 lp_field_count++;
   1026             }
   1027         } else
   1028 #endif /* BCM_GREYHOUND2_SUPPORT */
   1029         {
   1030             LPORT_TAB_SYNC(unit, port, VT_KEY_TYPE_2_USE_GLPf, 1);
   1031         }
   1032 
   1033         if (SOC_IS_KATANA(unit)) {
   1034             BCM_IF_ERROR_RETURN
   1035             (_bcm_esw_port_tab_set(unit, port, _BCM_CPU_TABS_NONE,
   1036                     VT_KEY_TYPE_2_USE_GLPf, 1));
   1037         }
   1038     }
   1039     if (SOC_MEM_FIELD_VALID(unit, mem, VT_PORT_TYPE_SELECT_2f)) {
   1040         soc_mem_field32_set(unit, mem, &ptab, VT_PORT_TYPE_SELECT_2f, 1);
   1041         LPORT_TAB_SYNC(unit, port, VT_PORT_TYPE_SELECT_2f, 1);
   1042     }
   1043 
   1044     /* Trust the outer tag pri/cfi (to be backwards compatible) */
   1045     if (SOC_MEM_FIELD_VALID(unit, mem, TRUST_OUTER_DOT1Pf)) {
   1046         soc_mem_field32_set(unit, mem, &ptab, TRUST_OUTER_DOT1Pf, 1);
   1047         LPORT_TAB_SYNC(unit, port, TRUST_OUTER_DOT1Pf, 1);
   1048     }
   1049 
   1050     if (SOC_MEM_FIELD_VALID(unit, mem, SRC_SYS_PORT_IDf)) {
   1051         soc_mem_field32_set(unit, mem, &ptab, SRC_SYS_PORT_IDf, port);
   1052         LPORT_TAB_SYNC(unit, port, SRC_SYS_PORT_IDf, port);
   1053     }
   1054 
   1055 #ifdef BCM_TRIUMPH_SUPPORT
   1056     if (SOC_IS_TR_VL(unit)) {
   1057         if (SOC_MEM_FIELD_VALID(unit, mem, DUAL_MODID_ENABLEf)) {
   1058             soc_mem_field32_set(unit, mem, &ptab, DUAL_MODID_ENABLEf, dual_modid);
   1059             LPORT_TAB_SYNC(unit, port, DUAL_MODID_ENABLEf, dual_modid);
   1060         }
   1061     }
   1062 #endif
   1063 #endif
   1064 
   1065 #ifdef BCM_RCPU_SUPPORT
   1066     if (SOC_IS_RCPU_ONLY(unit) &&
   1067         SOC_MEM_FIELD_VALID(unit, mem, OUTER_TPID_ENABLEf)) {
   1068         /* Required if rcpu vlan is not default vlan */
   1069         if (IS_CPU_PORT(unit,port) || IS_RCPU_PORT(unit,port)) {
   1070             soc_mem_field32_set(unit, mem, &ptab, OUTER_TPID_ENABLEf, 0x1);
   1071         }
   1072     }
   1073 #endif /* BCM_RCPU_SUPPORT */
   1074 
   1075 #ifdef BCM_MONTEREY_SUPPORT
   1076     if (SOC_IS_MONTEREY(unit)) {
   1077         if (port < 67) {
   1078             soc_PORT_TABm_field32_set(unit, &ptab, MISC_PORT_PROFILE_INDEXf, port);
   1079         }
   1080     }
   1081 #endif
   1082 
   1083 #if defined(BCM_TRIDENT2PLUS_SUPPORT) || defined(BCM_GREYHOUND2_SUPPORT)
   1084     if (soc_feature(unit, soc_feature_separate_ing_lport_rtag7_profile)) {
   1085         /* Last set of entries reserved for Front-Panel ports,
   1086          * hence adjusting the RTAG7 profile index.
   1087          */
   1088         rtag7_profile_idx =
   1089             ((soc_mem_index_max(unit, RTAG7_PORT_BASED_HASHm) -
   1090               soc_mem_index_max(unit, mem)) + port);
   1091         soc_mem_field32_set(unit, mem, &ptab, RTAG7_PORT_PROFILE_INDEXf, rtag7_profile_idx);
   1092 
   1093     }
   1094 #endif /* BCM_TRIDENT2PLUS_SUPPORT || BCM_GREYHOUND2_SUPPORT */
   1095 
   1096     BCM_IF_ERROR_RETURN(BCM_XGS3_MEM_WRITE(unit, mem, port, &ptab));
   1097     if (lp_field_count > 0) {
   1098         PORT_LOCK(unit);
   1099         rv = bcm_esw_port_lport_fields_set(unit, port, LPORT_PROFILE_LPORT_TAB,
   1100                                            lp_field_count, lp_field_ids,
   1101                                            lp_field_values);
   1102         PORT_UNLOCK(unit);
   1103         if (BCM_FAILURE(rv)) {
   1104             return rv;
   1105         }
   1106     }
   1107 #undef LPORT_TAB_SYNC
   1108 
   1109 #ifdef BCM_TRX_SUPPORT
   1110     if (SOC_MEM_FIELD_VALID(unit, SOURCE_TRUNK_MAP_TABLEm, OUTER_TPID_ENABLEf)) {
   1111         BCM_IF_ERROR_RETURN(
   1112             _bcm_trx_source_trunk_map_set(unit, port, OUTER_TPID_ENABLEf, 1));
   1113     }
   1114 #endif
   1115 
   1116     /* 
   1117      * Replicate port information to IPORT_TABLE and IEGR_PORT register
   1118      * for CPU port. 
   1119      */
   1120     cpu_hg_index = SOC_IS_KATANA2(unit) ?
   1121                    SOC_INFO(unit).cpu_hg_pp_port_index :
   1122                    SOC_INFO(unit).cpu_hg_index;
   1123     if (IS_CPU_PORT(unit,port)) {
   1124         soc_mem_field32_set(unit, mem, &ptab, port_type_field, 1);
   1125         if (SOC_MEM_IS_VALID(unit, IPORT_TABLEm)) {
   1126             /* IPORT and PORT have identical formats */
   1127             BCM_IF_ERROR_RETURN
   1128                 (soc_mem_write(unit, IPORT_TABLEm, MEM_BLOCK_ALL, port,
   1129                                &ptab));
   1130         } else if (cpu_hg_index != -1) {
   1131             BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL,
   1132                                 cpu_hg_index, &ptab));
   1133         }
   1134 
   1135         field_values[0] = 1;
   1136         if (SOC_REG_IS_VALID(unit, iegr_port_reg)) {
   1137             /* IEGR_PORT and EGR_PORT have identical formats */
   1138             BCM_IF_ERROR_RETURN 
   1139                 (soc_reg_fields32_modify(unit, iegr_port_reg, port,
   1140                                          field_count, field_ids,
   1141                                          field_values));
   1142         } else if (SOC_INFO(unit).cpu_hg_index != -1 &&
   1143                    soc_mem_index_max(unit, EGR_PORTm) ==
   1144                    SOC_INFO(unit).cpu_hg_index) {
   1145             BCM_IF_ERROR_RETURN 
   1146                 (soc_mem_fields32_modify(unit, EGR_PORTm,
   1147                                          SOC_INFO(unit).cpu_hg_index,
   1148                                          field_count, field_ids,
   1149                                          field_values));
   1150         }
   1151     }
   1152 
   1153     return (BCM_E_NONE);
   1154 }
   1155 
   1156 /*
   1157  * Function:
   1158  *      _bcm_fb_port_rate_ingress_set
   1159  * Purpose:
   1160  *      Set ingress rate limiting parameters
   1161  * Parameters:
   1162  *      unit        - (IN)SOC unit number.   
   1163  *      port        - (IN)Port number.
   1164  *      kbits_sec   - (IN)Rate in kilobits (1000 bits) per second.
   1165  *                        Rate of 0 disables rate limiting.
   1166  *      kbits_burst - (IN)Maximum burst size in kilobits (1000 bits).
   1167  * Returns:
   1168  *      BCM_E_XXX
   1169  * Notes:
   1170  *      Rate-based pause frames automatically will be enabled
   1171  *      whenever ingress rate metering is enabled. Since the
   1172  *      pause frame behavior also affects the discard/accept
   1173  *      behavior of the ingress meter, the pause frame behavior
   1174  *      is set such that the discard/accept hysteresis is as
   1175  *      small as possible.
   1176  */
   1177 
   1178 /* 
   1179  * Please consult the Programmer's Register Reference Guide for
   1180  * a description of the following settings and resultant values.
   1181  */
   1182 #define DISCARD_THD_BITS 3 
   1183 #define RESUME_THD_BITS  0
   1184 
   1185 STATIC int
   1186 _bcm_fb_port_rate_ingress_set(int unit, bcm_port_t port,
   1187                               uint32 kbits_sec, uint32 kbits_burst)
   1188 {
   1189     uint32 kbits_pause;     /* Pause frame rate.                     */  
   1190     uint32 regval = 0;      /* Register value.                       */
   1191     uint32 refresh_rate, bucketsize;
   1192 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_RAVEN_SUPPORT) || \
   1193     defined (BCM_SCORPION_SUPPORT) || defined(BCM_HURRICANE_SUPPORT) || \
   1194     defined (BCM_HURRICANE2_SUPPORT) || defined(BCM_GREYHOUND_SUPPORT)
   1195     uint32 granularity = 3; 
   1196 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_RAVEN_SUPPORT || BCM_SCORPION_SUPPORT */
   1197 #if defined (BCM_HURRICANE3_SUPPORT)
   1198     uint32 fval = 0;
   1199     soc_reg_t meter_ing_port_reg = INVALIDr;
   1200     soc_field_t meter_ing_port_field = INVALIDf;
   1201     bcm_port_t port_value;
   1202 #endif /* BCM_HURRICANE3_SUPPORT */
   1203 
   1204     /* Disable ingress metering and pause frames for this port */
   1205     BCM_IF_ERROR_RETURN(WRITE_BKPMETERINGCONFIGr(unit, port, regval));
   1206 
   1207     /*reset the BKPMETERING BUCKET Registers*/
   1208     BCM_IF_ERROR_RETURN(WRITE_BKPMETERINGBUCKETr(unit, port, regval));
   1209 
   1210 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_RAVEN_SUPPORT) || \
   1211     defined(BCM_HURRICANE_SUPPORT) || defined(BCM_GREYHOUND_SUPPORT)
   1212     if (SOC_IS_FIREBOLT2(unit) || SOC_IS_RAVEN(unit) || SOC_IS_HAWKEYE(unit) || 
   1213             SOC_IS_HURRICANEX(unit) || SOC_IS_GREYHOUND(unit) ||
   1214             SOC_IS_GREYHOUND2(unit)) {
   1215         BCM_IF_ERROR_RETURN(WRITE_BKPMETERINGCONFIG_EXTr(unit, port, regval));
   1216     }
   1217 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_RAVEN_SUPPORT */
   1218 
   1219     /* If metering is disabled on this ingress port we are done.*/
   1220     if (!kbits_sec || !kbits_burst) { 
   1221         return (BCM_E_NONE); 
   1222     }
   1223 
   1224 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_RAVEN_SUPPORT) || \
   1225     defined(BCM_HURRICANE_SUPPORT) || defined(BCM_GREYHOUND_SUPPORT)
   1226     if (SOC_IS_FIREBOLT2(unit) || SOC_IS_RAVEN(unit) || SOC_IS_HAWKEYE(unit) || 
   1227             SOC_IS_HURRICANEX(unit) || SOC_IS_GREYHOUND(unit) ||
   1228             SOC_IS_GREYHOUND2(unit)) {
   1229         uint32 regval_ext = 0;
   1230         BCM_IF_ERROR_RETURN
   1231             (READ_BKPMETERINGCONFIG_EXTr(unit, port, &regval_ext));
   1232         /* As below, but for in different register */
   1233         soc_reg_field_set(unit, BKPMETERINGCONFIG_EXTr, &regval_ext,
   1234                           BKPDISCARD_ENf, 1);
   1235 
   1236         /* Turn off backward compatability default */
   1237         soc_reg_field_set(unit, BKPMETERINGCONFIG_EXTr, &regval_ext,
   1238                           BKPDISCARD_ACCT_ENf, 0);
   1239 
   1240         soc_reg_field_set(unit, BKPMETERINGCONFIG_EXTr, &regval_ext,
   1241                           DISCARD_THDf, DISCARD_THD_BITS);
   1242         soc_reg_field_set(unit, BKPMETERINGCONFIG_EXTr, &regval_ext,
   1243                           RESUME_THDf, RESUME_THD_BITS);
   1244 
   1245         BCM_IF_ERROR_RETURN
   1246             (WRITE_BKPMETERINGCONFIG_EXTr(unit, port, regval_ext));
   1247     } else
   1248 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_RAVEN_SUPPORT */
   1249     {
   1250     /* Enable metering (rate-based discarding) */
   1251     soc_reg_field_set(unit, BKPMETERINGCONFIGr, &regval,
   1252                       BKPDISCARD_ENf, 1);
   1253 
   1254     /*
   1255      * BKPMETERINGCONFIGr.BKPDISCARD_ACCT_ENf was cleared when we wrote
   1256      * 0 to the BKPMETERINGCONFIGr register above, so we don't need
   1257      * to clear it here.
   1258      */
   1259 
   1260     /* 
   1261      * Set the "automatic" pause frame behavior. Because the 
   1262      * metering and pause frame behavior controls are intertwined, 
   1263      * truly independent control of both is not possible. Therefore,
   1264      * the pause frame behavior will be hardcoded so that the metering
   1265      * functionality (API) is preserved as much as possible.
   1266      * The smallest drop/resume hysteresis window should be used.
   1267      */ 
   1268     soc_reg_field_set(unit, BKPMETERINGCONFIGr, &regval,
   1269                       DISCARD_THDf, DISCARD_THD_BITS);
   1270     soc_reg_field_set(unit, BKPMETERINGCONFIGr, &regval,
   1271                       RESUME_THDf, RESUME_THD_BITS);
   1272     }
   1273 
   1274     /* Pre-check kbits_burst upper limit for upcoming math */
   1275     if (kbits_burst > (0xFFFFFFFF / 8)) {
   1276         kbits_burst = (0xFFFFFFFF / 8);
   1277     }
   1278     /* 
   1279      * Convert requested burst size into the appropriate
   1280      * PAUSE_THD field setting. Based on the above hysteresis
   1281      * window, convert the requested burst size to the 
   1282      * associated PAUSE_THD value.
   1283      */
   1284 #if (DISCARD_THD_BITS==0)
   1285     kbits_pause = (kbits_burst * 4) / 7;
   1286 #endif
   1287 #if (DISCARD_THD_BITS==1)
   1288     kbits_pause = (kbits_burst * 2) / 3;
   1289 #endif
   1290 #if (DISCARD_THD_BITS==2)
   1291     kbits_pause = (kbits_burst * 4) / 5;
   1292 #endif
   1293 #if (DISCARD_THD_BITS==3)
   1294     kbits_pause = (kbits_burst * 8) / 9;
   1295 #endif
   1296 
   1297 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_RAVEN_SUPPORT) || \
   1298     defined (BCM_SCORPION_SUPPORT)  || defined (BCM_HURRICANE_SUPPORT) || \
   1299     defined(BCM_GREYHOUND_SUPPORT)
   1300     if (SOC_IS_FIREBOLT2(unit) || SOC_IS_RAVEN(unit) || 
   1301             SOC_IS_HAWKEYE(unit) || SOC_IS_SC_CQ(unit) || 
   1302             SOC_IS_HURRICANEX(unit) || SOC_IS_GREYHOUND(unit) ||
   1303             SOC_IS_GREYHOUND2(unit)) {
   1304         uint32 miscval, flags = 0;
   1305         int    refresh_bitsize = 0;
   1306         int    bucket_bitsize = 0;
   1307         if (soc_reg_field_valid(unit, MISCCONFIGr, ITU_MODE_SELf)) {
   1308             BCM_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, &miscval));
   1309             if (soc_reg_field_get(unit, MISCCONFIGr,
   1310                                              miscval, ITU_MODE_SELf)) {
   1311                 flags |= _BCM_XGS_METER_FLAG_NON_LINEAR;
   1312             }
   1313         }
   1314         if (soc_reg_field_valid(unit, BKPMETERINGCONFIGr, METER_GRANf)) {
   1315             flags |= _BCM_XGS_METER_FLAG_GRANULARITY;
   1316         }
   1317 
   1318         if (SOC_IS_HURRICANE3(unit)  || SOC_IS_GREYHOUND2(unit)) {
   1319             flags |= _BCM_XGS_METER_FLAG_GRANULARITY_SELECTIVE;
   1320             flags |= _BCM_XGS_METER_FLAG_GRANULARITY_SELECT3;
   1321             flags |= _BCM_XGS_METER_FLAG_GRANULARITY_SELECT5;
   1322             flags |= _BCM_XGS_METER_FLAG_BUCKET_IN_8KB;
   1323         }
   1324 
   1325         if (soc_reg_field_valid(unit, BKPMETERINGCONFIGr, REFRESHCOUNTf)) {
   1326             refresh_bitsize = soc_reg_field_length(unit, BKPMETERINGCONFIGr,
   1327                                                    REFRESHCOUNTf);
   1328         } else 
   1329         /*coverity[result_independent_of_operands]*/
   1330         if (SOC_REG_IS_VALID(unit, BKPMETERINGCONFIG1r) &&
   1331                    soc_reg_field_valid(unit, BKPMETERINGCONFIG1r,
   1332                                        REFRESHCOUNTf)) {
   1333             refresh_bitsize = soc_reg_field_length(unit, BKPMETERINGCONFIG1r,
   1334                                                    REFRESHCOUNTf);
   1335         }
   1336         bucket_bitsize = soc_reg_field_length(unit, BKPMETERINGCONFIGr,
   1337                                                   PAUSE_THDf);
   1338         BCM_IF_ERROR_RETURN
   1339             (_bcm_xgs_kbits_to_bucket_encoding(kbits_sec, kbits_pause, flags,
   1340                             refresh_bitsize, bucket_bitsize,
   1341                             &refresh_rate, &bucketsize, &granularity));
   1342     } else
   1343 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_RAVEN_SUPPORT */
   1344     {
   1345         /* Calculate adj_rate rate. */
   1346         BCM_XGS3_PORT_RATE_64KBIT_QUANTUM(kbits_sec, refresh_rate);
   1347         bucketsize = _bcm_fb_kbits_to_bucketsize(kbits_pause);
   1348     }
   1349 
   1350     soc_reg_field_set(unit, BKPMETERINGCONFIGr, &regval,
   1351                       PAUSE_THDf, bucketsize);
   1352     /* Set adjasted rate to port config register. */
   1353     if (soc_reg_field_valid(unit,BKPMETERINGCONFIGr,REFRESHCOUNTf)) {
   1354         soc_reg_field_set(unit, BKPMETERINGCONFIGr, &regval,
   1355                           REFRESHCOUNTf, refresh_rate);
   1356     }
   1357 
   1358 #if defined(BCM_SCORPION_SUPPORT)
   1359     /*coverity[result_independent_of_operands]*/
   1360     if (SOC_REG_IS_VALID(unit, BKPMETERINGCONFIG1r)) {
   1361         if (soc_reg_field_valid(unit,BKPMETERINGCONFIG1r,REFRESHCOUNTf)) {
   1362             BCM_IF_ERROR_RETURN(
   1363                 soc_reg_field32_modify(unit, BKPMETERINGCONFIG1r, port,
   1364                                        REFRESHCOUNTf, refresh_rate));
   1365         }
   1366     }
   1367 
   1368     if (soc_reg_field_valid(unit, BKPMETERINGCONFIGr, METER_GRANf)) {
   1369         soc_reg_field_set(unit, BKPMETERINGCONFIGr, &regval, METER_GRANf,
   1370                           granularity);
   1371     }
   1372 #endif /* BCM_SCORPION_SUPPORT */
   1373 
   1374     /* Enable ingress metering and pause frames for this port */
   1375     BCM_IF_ERROR_RETURN(WRITE_BKPMETERINGCONFIGr(unit, port, regval));
   1376 
   1377 #if defined(BCM_HURRICANE3_SUPPORT)
   1378     meter_ing_port_reg = METER_ING_PORT_GRANr;
   1379     meter_ing_port_field = METER_ING_PORT_GRANf;
   1380     port_value = port;
   1381     if (SOC_IS_GREYHOUND2(unit)) {
   1382         int mmu_port;
   1383         int phy_port;
   1384         soc_info_t *si;
   1385 
   1386         /* For Greyhound2, program MMU port index */
   1387         si = &SOC_INFO(unit);
   1388         phy_port = si->port_l2p_mapping[port];
   1389         mmu_port = si->port_p2m_mapping[phy_port];
   1390 
   1391         if (mmu_port < 32) {
   1392             meter_ing_port_reg = METER_ING_PORT_GRAN_0r;
   1393             port_value = mmu_port;
   1394         } else if (mmu_port < 64) {
   1395             meter_ing_port_reg = METER_ING_PORT_GRAN_1r;
   1396             port_value = mmu_port - 32;
   1397         } else {
   1398             meter_ing_port_reg = METER_ING_PORT_GRAN_2r;
   1399             port_value = mmu_port - 64;
   1400         }
   1401     }
   1402 
   1403     if (soc_reg_field_valid(unit, meter_ing_port_reg, meter_ing_port_field)) {
   1404         BCM_IF_ERROR_RETURN(
   1405             soc_reg32_get(unit, meter_ing_port_reg, REG_PORT_ANY, 0, &regval));
   1406         fval = soc_reg_field_get(unit, meter_ing_port_reg,
   1407                                  regval, meter_ing_port_field);
   1408         if (granularity == 5) {
   1409             fval |= (1 << port_value);
   1410         } else {
   1411             fval &= ~(1 << port_value);
   1412         }
   1413         soc_reg_field_set(unit, meter_ing_port_reg, &regval,
   1414                           meter_ing_port_field, fval);
   1415         BCM_IF_ERROR_RETURN(
   1416             soc_reg32_set(unit, meter_ing_port_reg, REG_PORT_ANY, 0, regval));
   1417     }
   1418 #endif /* BCM_HURRICANE3_SUPPORT */
   1419 
   1420     /*  MISCCONFIG.METERING_CLK_EN is set by chip init */
   1421 
   1422     return (BCM_E_NONE);
   1423 }
   1424 
   1425 #ifdef BCM_TRIUMPH_SUPPORT
   1426 STATIC int
   1427 _bcm_tr_port_rate_ingress_set(int unit, bcm_port_t port,
   1428                               uint32 kbits_sec, uint32 kbits_burst)
   1429 {
   1430     uint32 miscval;
   1431     uint32 delta=0;
   1432     uint32 kbits_Rburst=0;  /* Adjusted burst value                  */
   1433     uint32 kbits_cburst=0;  /* Re computed burst value               */
   1434     uint32 kbits_pause;     /* Pause frame rate.                     */  
   1435     uint32 regval = 0;      /* Register value.                       */
   1436     uint64 regval_64;       /* 64-bit Register value.                */
   1437     uint32 refresh_rate, bucketsize, granularity = 3, flags = 0;
   1438     int    refresh_bitsize, bucket_bitsize;
   1439 
   1440     /* Disable ingress metering and pause frames for this port */
   1441     COMPILER_64_ZERO(regval_64);
   1442     BCM_IF_ERROR_RETURN(WRITE_BKPMETERINGCONFIG_64r(unit, port, regval_64));
   1443 
   1444     /*reset the BKPMETERING BUCKET Registers*/
   1445     BCM_IF_ERROR_RETURN(WRITE_BKPMETERINGBUCKETr(unit, port, regval));
   1446 
   1447     /* If metering is disabled on this ingress port we are done.*/
   1448     if (!kbits_sec || !kbits_burst) { 
   1449         return (BCM_E_NONE); 
   1450     }
   1451 
   1452     /* Enable metering (rate-based discarding) */
   1453     soc_reg64_field32_set(unit, BKPMETERINGCONFIG_64r, &regval_64,
   1454                           BKPDISCARD_ENf, 1);
   1455 
   1456     /*
   1457      * Set the "automatic" pause frame behavior. Because the
   1458      * metering and pause frame behavior controls are intertwined,
   1459      * truly independent control of both is not possible. Therefore,
   1460      * the pause frame behavior will be hardcoded so that the metering
   1461      * functionality (API) is preserved as much as possible.
   1462      * The smallest drop/resume hysteresis window should be used.
   1463      */
   1464     soc_reg64_field32_set(unit, BKPMETERINGCONFIG_64r, &regval_64,
   1465                           DISCARD_THDf, DISCARD_THD_BITS);
   1466     soc_reg64_field32_set(unit, BKPMETERINGCONFIG_64r, &regval_64,
   1467                           RESUME_THDf, RESUME_THD_BITS);
   1468 
   1469     /* Pre-check kbits_burst upper limit for upcoming math */
   1470     if (kbits_burst > (0xFFFFFFFF / 8)) {
   1471         kbits_burst = (0xFFFFFFFF / 8);
   1472     }
   1473 
   1474     /* 
   1475      * Convert requested burst size into the appropriate
   1476      * PAUSE_THD field setting. Based on the above hysteresis
   1477      * window, convert the requested burst size to the 
   1478      * associated PAUSE_THD value.
   1479      */
   1480 #if (DISCARD_THD_BITS==0)
   1481     kbits_pause = (kbits_burst * 4) / 7;
   1482     kbits_cburst = (kbits_pause * 7 ) / 4;
   1483 #endif
   1484 #if (DISCARD_THD_BITS==1)
   1485     kbits_pause = (kbits_burst * 2) / 3;
   1486     kbits_cburst = (kbits_pause * 3 ) / 2;
   1487 #endif
   1488 #if (DISCARD_THD_BITS==2)
   1489     kbits_pause = (kbits_burst * 4) / 5;
   1490     kbits_cburst = (kbits_pause * 5 ) / 4;
   1491 #endif
   1492 #if (DISCARD_THD_BITS==3)
   1493     kbits_pause = (kbits_burst * 8) / 9;
   1494     kbits_cburst = (kbits_pause * 9 ) / 8;
   1495 #endif
   1496     /*
   1497         compute back the burst.
   1498         Add (burst- computed burst) delta to org_burst to get new  burst and use it for kbits_pause.
   1499     */
   1500     delta = kbits_burst - kbits_cburst;
   1501     kbits_Rburst = kbits_burst + delta;
   1502 
   1503 #if (DISCARD_THD_BITS==0)
   1504     kbits_pause = (kbits_Rburst * 4) / 7;
   1505 #endif
   1506 #if (DISCARD_THD_BITS==1)
   1507     kbits_pause = (kbits_Rburst * 2) / 3;
   1508 #endif
   1509 #if (DISCARD_THD_BITS==2)
   1510     kbits_pause = (kbits_Rburst * 4) / 5;
   1511 #endif
   1512 #if (DISCARD_THD_BITS==3)
   1513     kbits_pause = (kbits_Rburst * 8) / 9;
   1514 #endif
   1515 
   1516     BCM_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, &miscval));
   1517     if (soc_reg_field_get(unit, MISCCONFIGr, miscval, ITU_MODE_SELf)) {
   1518         flags |= _BCM_XGS_METER_FLAG_NON_LINEAR;
   1519     }
   1520     flags |= _BCM_XGS_METER_FLAG_GRANULARITY;
   1521 
   1522     if (SOC_IS_TD_TT(unit) || SOC_IS_KATANAX(unit)) {
   1523         flags |= _BCM_XGS_METER_FLAG_DOUBLE_REFRESH_FREQ;
   1524     }
   1525     refresh_bitsize = soc_reg_field_length(unit, BKPMETERINGCONFIG_64r,
   1526                                            REFRESHCOUNTf);
   1527     bucket_bitsize = soc_reg_field_length(unit, BKPMETERINGCONFIG_64r,
   1528                                           PAUSE_THDf);
   1529     BCM_IF_ERROR_RETURN
   1530         (_bcm_xgs_kbits_to_bucket_encoding(kbits_sec, kbits_pause, flags,
   1531                             refresh_bitsize, bucket_bitsize,
   1532                             &refresh_rate, &bucketsize, &granularity));
   1533 
   1534     /* Commit values to fields */
   1535     soc_reg64_field32_set(unit, BKPMETERINGCONFIG_64r, &regval_64,
   1536                           PAUSE_THDf, bucketsize);
   1537     /* Set adjasted rate to port config register. */
   1538     soc_reg64_field32_set(unit, BKPMETERINGCONFIG_64r, &regval_64,
   1539                           REFRESHCOUNTf, refresh_rate);
   1540     soc_reg64_field32_set(unit, BKPMETERINGCONFIG_64r, &regval_64,
   1541                           METER_GRANULARITYf, granularity);
   1542 
   1543     /* Enable ingress metering and pause frames for this port */
   1544     BCM_IF_ERROR_RETURN(WRITE_BKPMETERINGCONFIG_64r(unit, port, regval_64));
   1545 
   1546     /*  MISCCONFIG.METERING_CLK_EN is set by chip init */
   1547 
   1548     return (BCM_E_NONE);
   1549 }
   1550 #endif
   1551 #undef DISCARD_THD_BITS 
   1552 #undef RESUME_THD_BITS
   1553 
   1554 /*
   1555  * Function:
   1556  *      _bcm_fb_port_rate_ingress_get
   1557  * Purpose:
   1558  *      Get ingress rate limiting parameters
   1559  * Parameters:
   1560  *      unit        - (IN)SOC unit number.
   1561  *      port        - (IN)Port number.
   1562  *      kbits_sec   - (OUT) Rate in kilobits (1000 bits) per second, or
   1563  *                        zero if rate limiting is disabled.
   1564  *      kbits_burst - (OUT) Maximum burst size in kilobits (1000 bits).
   1565  * Returns:
   1566  *      BCM_E_XXX
   1567  */
   1568 
   1569 int
   1570 _bcm_fb_port_rate_ingress_get(int unit, bcm_port_t port,
   1571                               uint32 *kbits_sec, uint32 *kbits_burst)
   1572 {
   1573     uint32 kbits_pause;     /* Pause frame rate.                     */  
   1574     uint32 regval;          /* Register value.                       */
   1575     int    bpkdiscard_en, discard_thd;
   1576     uint32 refresh_rate = 0, bucketsize = 0;
   1577 
   1578     /* Read ingress port metering configuration. */
   1579     BCM_IF_ERROR_RETURN(READ_BKPMETERINGCONFIGr(unit, port, &regval));
   1580 
   1581     /* Extract pause frame rate. */ 
   1582     bucketsize = soc_reg_field_get(unit, BKPMETERINGCONFIGr, 
   1583                                    regval, PAUSE_THDf);
   1584 
   1585 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_RAVEN_SUPPORT) || \
   1586     defined(BCM_HURRICANE_SUPPORT) || defined(BCM_GREYHOUND_SUPPORT)
   1587     if (SOC_IS_FIREBOLT2(unit) || SOC_IS_RAVEN(unit) || SOC_IS_HAWKEYE(unit) ||
   1588         SOC_IS_HURRICANEX(unit) || SOC_IS_GREYHOUND(unit) ||
   1589         SOC_IS_GREYHOUND2(unit)) {
   1590         uint32 regval_ext;
   1591         BCM_IF_ERROR_RETURN
   1592             (READ_BKPMETERINGCONFIG_EXTr(unit, port, &regval_ext));
   1593         bpkdiscard_en = soc_reg_field_get(unit, BKPMETERINGCONFIG_EXTr, 
   1594                                           regval_ext, BKPDISCARD_ENf);
   1595         discard_thd = soc_reg_field_get(unit, BKPMETERINGCONFIG_EXTr,
   1596                                         regval_ext, DISCARD_THDf);
   1597     } else
   1598 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_RAVEN_SUPPORT */
   1599     {
   1600         bpkdiscard_en = soc_reg_field_get(unit, BKPMETERINGCONFIGr, 
   1601                                           regval, BKPDISCARD_ENf);
   1602         discard_thd = soc_reg_field_get(unit, BKPMETERINGCONFIGr,
   1603                                         regval, DISCARD_THDf);
   1604     }
   1605 
   1606     if (!bpkdiscard_en || !bucketsize) {
   1607         *kbits_sec = *kbits_burst = 0;
   1608     } else {
   1609         if (soc_reg_field_valid(unit, BKPMETERINGCONFIGr, REFRESHCOUNTf)) {
   1610             refresh_rate = soc_reg_field_get(unit, BKPMETERINGCONFIGr, 
   1611                                                 regval, REFRESHCOUNTf);
   1612         }
   1613 #if defined(BCM_SCORPION_SUPPORT)
   1614         /*coverity[result_independent_of_operands]*/
   1615         if (SOC_REG_IS_VALID(unit, BKPMETERINGCONFIG1r)) {
   1616             uint32 val;
   1617             BCM_IF_ERROR_RETURN(READ_BKPMETERINGCONFIG1r(unit, port, &val));
   1618             if (soc_reg_field_valid(unit, BKPMETERINGCONFIG1r, REFRESHCOUNTf)) {
   1619                 refresh_rate = soc_reg_field_get(unit, BKPMETERINGCONFIG1r, 
   1620                                                     val, REFRESHCOUNTf);
   1621             }
   1622         }
   1623 #endif
   1624 
   1625 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_RAVEN_SUPPORT) || \
   1626     defined(BCM_SCORPION_SUPPORT) || defined (BCM_HURRICANE_SUPPORT) || \
   1627     defined(BCM_GREYHOUND_SUPPORT)
   1628         if (SOC_IS_FIREBOLT2(unit) || SOC_IS_RAVEN(unit) || 
   1629             SOC_IS_HAWKEYE(unit) || SOC_IS_SC_CQ(unit) || 
   1630             SOC_IS_HURRICANEX(unit) || SOC_IS_GREYHOUND(unit) ||
   1631             SOC_IS_GREYHOUND2(unit)) {
   1632             uint32 miscval, granularity = 3, flags = 0;
   1633 #if defined (BCM_HURRICANE3_SUPPORT)
   1634             uint32 fval = 0;
   1635             soc_reg_t meter_ing_port_reg = INVALIDr;
   1636             soc_field_t meter_ing_port_field = INVALIDf;
   1637             bcm_port_t port_value;
   1638 #endif /* BCM_HURRICANE3_SUPPORT */
   1639 
   1640             if (soc_reg_field_valid(unit, MISCCONFIGr, ITU_MODE_SELf)) {
   1641                 BCM_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, &miscval));
   1642                 if (soc_reg_field_get(unit, MISCCONFIGr,
   1643                                              miscval, ITU_MODE_SELf)) {
   1644                     flags |= _BCM_XGS_METER_FLAG_NON_LINEAR;
   1645                 }
   1646             }
   1647             if (soc_reg_field_valid(unit, BKPMETERINGCONFIGr, METER_GRANf)) {
   1648                 flags |= _BCM_XGS_METER_FLAG_GRANULARITY;
   1649                 granularity = soc_reg_field_get(unit, BKPMETERINGCONFIGr,
   1650                                                 regval, METER_GRANf);
   1651             }
   1652 
   1653 #if defined (BCM_HURRICANE3_SUPPORT)
   1654             meter_ing_port_reg = METER_ING_PORT_GRANr;
   1655             meter_ing_port_field = METER_ING_PORT_GRANf;
   1656             port_value = port;
   1657             if (SOC_IS_GREYHOUND2(unit)) {
   1658                 int mmu_port;
   1659                 int phy_port;
   1660                 soc_info_t *si;
   1661 
   1662                 /* For Greyhound2, program MMU port index */
   1663                 si = &SOC_INFO(unit);
   1664                 phy_port = si->port_l2p_mapping[port];
   1665                 mmu_port = si->port_p2m_mapping[phy_port];
   1666 
   1667                 if (mmu_port < 32) {
   1668                     meter_ing_port_reg = METER_ING_PORT_GRAN_0r;
   1669                     port_value = mmu_port;
   1670                 } else if (mmu_port < 64) {
   1671                     meter_ing_port_reg = METER_ING_PORT_GRAN_1r;
   1672                     port_value = mmu_port - 32;
   1673                 } else {
   1674                     meter_ing_port_reg = METER_ING_PORT_GRAN_2r;
   1675                     port_value = mmu_port - 64;
   1676                 }
   1677             }
   1678 
   1679             if (soc_reg_field_valid(unit, meter_ing_port_reg,
   1680                                     meter_ing_port_field)) {
   1681                 flags |= _BCM_XGS_METER_FLAG_GRANULARITY;
   1682 
   1683                 BCM_IF_ERROR_RETURN(
   1684                     soc_reg32_get(unit, meter_ing_port_reg,
   1685                                   REG_PORT_ANY, 0, &regval));
   1686                 fval = soc_reg_field_get(unit, meter_ing_port_reg,
   1687                                          regval, meter_ing_port_field);
   1688 
   1689                 if (fval & (1 << port_value)) {
   1690                     granularity = 5;
   1691                 }
   1692             }
   1693 #endif /* BCM_HURRICANE3_SUPPORT */
   1694             BCM_IF_ERROR_RETURN
   1695                 (_bcm_xgs_bucket_encoding_to_kbits(refresh_rate, bucketsize,
   1696                                                    granularity, flags,
   1697                                                    kbits_sec, &kbits_pause));
   1698         } else
   1699 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_RAVEN_SUPPORT */
   1700         {
   1701             if (soc_reg_field_valid(unit, BKPMETERINGCONFIGr, REFRESHCOUNTf)) {
   1702                         *kbits_sec = 64 * refresh_rate;
   1703             }
   1704             kbits_pause = _bcm_fb_bucketsize_to_kbits(bucketsize);
   1705         }
   1706 
   1707         switch (discard_thd) {
   1708           case 0:
   1709               *kbits_burst = (kbits_pause * 7) / 4;
   1710               break;
   1711           case 1:
   1712               *kbits_burst = (kbits_pause * 3) / 2;
   1713               break;
   1714           case 2:
   1715               *kbits_burst = (kbits_pause * 5) / 4;
   1716               break;
   1717           case 3:
   1718               *kbits_burst = (kbits_pause * 9) / 8;
   1719               break;
   1720           default:
   1721               /* Should never happen */
   1722               *kbits_burst = 0; 
   1723               break;
   1724         }
   1725     }
   1726     return (BCM_E_NONE); 
   1727 }
   1728 
   1729 #ifdef BCM_TRIUMPH_SUPPORT
   1730 int
   1731 _bcm_tr_port_rate_ingress_get(int unit, bcm_port_t port,
   1732                               uint32 *kbits_sec, uint32 *kbits_burst)
   1733 {
   1734     uint32 miscval;
   1735     uint32 kbits_pause;     /* Pause frame rate.                     */  
   1736     uint64 regval;          /* Register value.                       */
   1737     int    bpkdiscard_en, discard_thd;
   1738     uint32 refresh_rate = 0, bucketsize = 0, granularity = 3, flags = 0;
   1739 
   1740     /* Read ingress port metering configuration. */
   1741     BCM_IF_ERROR_RETURN(READ_BKPMETERINGCONFIG_64r(unit, port, &regval));
   1742 
   1743     /* Extract pause frame rate. */ 
   1744     bucketsize = soc_reg64_field32_get(unit, BKPMETERINGCONFIG_64r, 
   1745                                         regval, PAUSE_THDf);
   1746     bpkdiscard_en = soc_reg64_field32_get(unit, BKPMETERINGCONFIG_64r, 
   1747                                           regval, BKPDISCARD_ENf);
   1748     discard_thd = soc_reg64_field32_get(unit, BKPMETERINGCONFIG_64r,
   1749                                         regval, DISCARD_THDf);
   1750 
   1751     if (!bpkdiscard_en || !bucketsize) {
   1752         *kbits_sec = *kbits_burst = 0;
   1753     } else {
   1754         refresh_rate = soc_reg64_field32_get(unit, BKPMETERINGCONFIG_64r, 
   1755                                              regval, REFRESHCOUNTf);
   1756         BCM_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, &miscval));
   1757         if (soc_reg_field_get(unit, MISCCONFIGr, miscval, ITU_MODE_SELf)) {
   1758             flags |= _BCM_XGS_METER_FLAG_NON_LINEAR;
   1759         }
   1760         flags |= _BCM_XGS_METER_FLAG_GRANULARITY;
   1761         granularity = soc_reg64_field32_get(unit, BKPMETERINGCONFIG_64r,
   1762                                             regval, METER_GRANULARITYf);
   1763         if (SOC_IS_TD_TT(unit) || SOC_IS_KATANAX(unit)) {
   1764             flags |= _BCM_XGS_METER_FLAG_DOUBLE_REFRESH_FREQ;
   1765         }
   1766         BCM_IF_ERROR_RETURN
   1767             (_bcm_xgs_bucket_encoding_to_kbits(refresh_rate, bucketsize,
   1768                                                granularity, flags,
   1769                                                kbits_sec, &kbits_pause));
   1770 
   1771         switch (discard_thd) {
   1772           case 0:
   1773               *kbits_burst = (kbits_pause * 7) / 4;
   1774               break;
   1775           case 1:
   1776               *kbits_burst = (kbits_pause * 3) / 2;
   1777               break;
   1778           case 2:
   1779               *kbits_burst = (kbits_pause * 5) / 4;
   1780               break;
   1781           case 3:
   1782               *kbits_burst = (kbits_pause * 9) / 8;
   1783               break;
   1784           default:
   1785               /* Should never happen */
   1786               *kbits_burst = 0; 
   1787               break;
   1788         }
   1789     }
   1790     return (BCM_E_NONE); 
   1791 }
   1792 #endif
   1793 
   1794 /* 
   1795  * For Firebolt, there is no software support for bcm_port_rate_pause_set().
   1796  * However, there is support for bcm_port_rate_pause_get().
   1797  */
   1798 
   1799 /*
   1800  * Function:
   1801  *      bcm_fb_port_rate_pause_get
   1802  * Purpose:
   1803  *      Get ingress rate limiting pause frame control parameters
   1804  * Parameters:
   1805  *      unit         - (IN)SOC unit number.
   1806  *      port         - (IN)Port number.
   1807  *      kbits_pause  - (OUT) Pause threshold in kbits (1000 bits).
   1808  *              Zero indicates the pause/resume mechanism is disabled.
   1809  *      kbits_resume - (OUT) Resume threshold in kbits (1000 bits).
   1810  * Returns:
   1811  *      BCM_E_XXX
   1812  * Notes:
   1813  *      For Firebolt, these values are returned for informational
   1814  *      purposes only. In order to retain the ingress metering
   1815  *      behavior (as much as possible), the pause frame behavior
   1816  *      is hard-coded, and is not configurable.
   1817  *      Rate-based pause frames are automatically enabled whenever
   1818  *      ingress rate metering is enabled.
   1819  */
   1820 int
   1821 bcm_fb_port_rate_pause_get(int unit, bcm_port_t port,
   1822                            uint32 *kbits_pause, uint32 *kbits_resume)
   1823 {
   1824     uint32 regval = 0;
   1825     uint32 pause_thd_setting = 0;
   1826     uint32 pause = 0; 
   1827     uint32 bucket = 0; 
   1828     uint32 resume = 0;
   1829     soc_reg_t reg;
   1830 
   1831 
   1832     BCM_IF_ERROR_RETURN(READ_BKPMETERINGCONFIGr(unit, port, &regval));
   1833 
   1834     pause_thd_setting = soc_reg_field_get(unit, BKPMETERINGCONFIGr, 
   1835                                           regval, PAUSE_THDf);
   1836 
   1837     if (!pause_thd_setting) {
   1838         *kbits_pause = *kbits_resume = 0;
   1839         return (BCM_E_NONE);
   1840     }
   1841 
   1842 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_RAVEN_SUPPORT) || defined (BCM_SCORPION_SUPPORT) || defined (BCM_HURRICANE_SUPPORT)
   1843     if (SOC_IS_FIREBOLT2(unit) || SOC_IS_RAVEN(unit) || 
   1844         SOC_IS_HAWKEYE(unit) || SOC_IS_SC_CQ(unit) || 
   1845         SOC_IS_HURRICANEX(unit) || SOC_IS_GREYHOUND2(unit)) {
   1846         uint32 fval = 0;
   1847         uint32 miscval, rate, granularity = 3, flags = 0;
   1848         if (soc_reg_field_valid(unit, MISCCONFIGr, ITU_MODE_SELf)) {
   1849             BCM_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, &miscval));
   1850             if (soc_reg_field_get(unit, MISCCONFIGr,
   1851                                   miscval, ITU_MODE_SELf)) {
   1852                 flags |= _BCM_XGS_METER_FLAG_NON_LINEAR;
   1853             }
   1854         }
   1855         if (soc_reg_field_valid(unit, BKPMETERINGCONFIGr, METER_GRANf)) {
   1856             flags |= _BCM_XGS_METER_FLAG_GRANULARITY;
   1857             granularity = soc_reg_field_get(unit, BKPMETERINGCONFIGr,
   1858                                             regval, METER_GRANf);
   1859         }
   1860 
   1861         if (soc_reg_field_valid(unit, METER_ING_PORT_GRANr,
   1862                                 METER_ING_PORT_GRANf)) {
   1863             flags |= _BCM_XGS_METER_FLAG_GRANULARITY;
   1864 
   1865             SOC_IF_ERROR_RETURN(READ_METER_ING_PORT_GRANr(unit, &regval));
   1866             fval = soc_reg_field_get(unit, METER_ING_PORT_GRANr,
   1867                                      regval, METER_ING_PORT_GRANf);
   1868 
   1869             if (fval & (1 << port)) {
   1870                 granularity = 5;
   1871             }
   1872         }
   1873 
   1874         BCM_IF_ERROR_RETURN
   1875             (_bcm_xgs_bucket_encoding_to_kbits(0, pause_thd_setting,
   1876                                                granularity, flags,
   1877                                                &rate, &pause));
   1878     } else
   1879 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_RAVEN_SUPPORT */
   1880     {
   1881         pause = _bcm_fb_bucketsize_to_kbits(pause_thd_setting);
   1882     }
   1883 
   1884     reg = soc_reg_field_valid(unit, BKPMETERINGCONFIGr, DISCARD_THDf) ?
   1885                            BKPMETERINGCONFIGr : BKPMETERINGCONFIG_EXTr;
   1886 
   1887     SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, port, 0, &regval));
   1888 
   1889     switch (soc_reg_field_get(unit, reg,
   1890                               regval, DISCARD_THDf)) {
   1891       case 0:
   1892           bucket = (pause * 7) / 4;
   1893           break;
   1894       case 1:
   1895           bucket = (pause * 3) / 2;
   1896           break;
   1897       case 2:
   1898           bucket = (pause * 5) / 4;
   1899           break;
   1900       case 3:
   1901           bucket = (pause * 9) / 8;
   1902           break;
   1903       default:
   1904           /* Should never happen */
   1905           return (BCM_E_INTERNAL); 
   1906           break;
   1907     }
   1908 
   1909     switch (soc_reg_field_get(unit, reg,
   1910                               regval, RESUME_THDf)) {
   1911       case 0:
   1912           resume = (pause * 3) / 4;
   1913           break;
   1914       case 1:
   1915           resume = pause / 2;
   1916           break;
   1917       case 2:
   1918           resume = pause / 4;
   1919           break;
   1920       case 3:
   1921           resume = pause / 8;
   1922           break;
   1923       default:
   1924           /* Should never happen */
   1925           return (BCM_E_INTERNAL); 
   1926           break;
   1927     }
   1928 
   1929     /* 
   1930      * The API assumes a "token bucket", i.e. # tokens in the
   1931      * bucket is proportional to the available bandwidth. But
   1932      * Firebolt uses a "leaky bucket", where # tokens is
   1933      * inversely proportional to available bandwidth. 
   1934      * Convert "leaky bucket" thresholds to "token bucket"-like
   1935      * values.
   1936      */
   1937     *kbits_pause = bucket - pause;
   1938     *kbits_resume = bucket - resume;
   1939 
   1940     return (BCM_E_NONE); 
   1941 }
   1942 
   1943 #ifdef BCM_TRIUMPH_SUPPORT
   1944 int
   1945 bcm_tr_port_rate_pause_get(int unit, bcm_port_t port,
   1946                            uint32 *kbits_pause, uint32 *kbits_resume)
   1947 {
   1948     uint64 regval;
   1949     uint32 miscval, pause_thd_setting, pause, bucket, resume;
   1950     uint32 granularity = 3, rate, flags = 0;
   1951 
   1952     BCM_IF_ERROR_RETURN(READ_BKPMETERINGCONFIG_64r(unit, port, &regval));
   1953 
   1954     pause_thd_setting = soc_reg64_field32_get(unit, BKPMETERINGCONFIG_64r, 
   1955                                               regval, PAUSE_THDf);
   1956 
   1957     if (!pause_thd_setting) {
   1958         *kbits_pause = *kbits_resume = 0;
   1959         return (BCM_E_NONE);
   1960     }
   1961 
   1962     BCM_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, &miscval));
   1963     if (soc_reg_field_get(unit, MISCCONFIGr, miscval, ITU_MODE_SELf)) {
   1964         flags |= _BCM_XGS_METER_FLAG_NON_LINEAR;
   1965     }
   1966     flags |= _BCM_XGS_METER_FLAG_GRANULARITY;
   1967     if (soc_reg_field_valid(unit,BKPMETERINGCONFIG_64r, METER_GRANf)) {
   1968         granularity = soc_reg64_field32_get(unit, BKPMETERINGCONFIG_64r,
   1969                                         regval, METER_GRANf);
   1970     } else if (soc_reg_field_valid(unit, BKPMETERINGCONFIG_64r,
   1971                                 METER_GRANULARITYf)) {
   1972         granularity = soc_reg64_field32_get(unit, BKPMETERINGCONFIG_64r,
   1973                                         regval, METER_GRANULARITYf);
   1974     }
   1975     if (SOC_IS_TD_TT(unit) || SOC_IS_KATANAX(unit)) {
   1976         flags |= _BCM_XGS_METER_FLAG_DOUBLE_REFRESH_FREQ;
   1977     }
   1978     BCM_IF_ERROR_RETURN
   1979         (_bcm_xgs_bucket_encoding_to_kbits(0, pause_thd_setting,
   1980                                            granularity, flags,
   1981                                            &rate, &pause));
   1982 
   1983     switch (soc_reg64_field32_get(unit, BKPMETERINGCONFIG_64r,
   1984                                   regval, DISCARD_THDf)) {
   1985       case 0:
   1986           bucket = (pause * 7) / 4;
   1987           break;
   1988       case 1:
   1989           bucket = (pause * 3) / 2;
   1990           break;
   1991       case 2:
   1992           bucket = (pause * 5) / 4;
   1993           break;
   1994       case 3:
   1995           bucket = (pause * 9) / 8;
   1996           break;
   1997       default:
   1998           /* Should never happen */
   1999           return (BCM_E_INTERNAL); 
   2000           break;
   2001     }
   2002 
   2003     switch (soc_reg64_field32_get(unit, BKPMETERINGCONFIG_64r,
   2004                                   regval, RESUME_THDf)) {
   2005       case 0:
   2006           resume = (pause * 3) / 4;
   2007           break;
   2008       case 1:
   2009           resume = pause / 2;
   2010           break;
   2011       case 2:
   2012           resume = pause / 4;
   2013           break;
   2014       case 3:
   2015           resume = pause / 8;
   2016           break;
   2017       default:
   2018           /* Should never happen */
   2019           return (BCM_E_INTERNAL); 
   2020           break;
   2021     }
   2022 
   2023     /* 
   2024      * The API assumes a "token bucket", i.e. # tokens in the
   2025      * bucket is proportional to the available bandwidth. But
   2026      * Firebolt uses a "leaky bucket", where # tokens is
   2027      * inversely proportional to available bandwidth. 
   2028      * Convert "leaky bucket" thresholds to "token bucket"-like
   2029      * values.
   2030      */
   2031     *kbits_pause = bucket - pause;
   2032     *kbits_resume = bucket - resume;
   2033 
   2034     return (BCM_E_NONE); 
   2035 }
   2036 #endif
   2037 
   2038 /*
   2039  * Function:
   2040  *      bcm_fb_port_rate_egress_set
   2041  * Purpose:
   2042  *      Set egress rate limiting parameters for the Firebolt chip.
   2043  * Parameters:
   2044  *      unit       - (IN)SOC unit number
   2045  *      port       - (IN)Port number
   2046  *      kbits_sec  - (IN)Rate in kilobits (1000 bits) per second.
   2047  *                       Rate of 0 disables rate limiting.
   2048  *      kbits_burst -(IN)Maximum burst size in kilobits (1000 bits).
   2049  * Returns:
   2050  *      BCM_E_XXX
   2051  */
   2052 int
   2053 bcm_fb_port_rate_egress_set(int unit, bcm_port_t port,
   2054                             uint32 kbits_sec, uint32 kbits_burst, uint32 mode)
   2055 {
   2056     int rv = BCM_E_NONE;
   2057     uint32 refresh_rate, bucketsize;
   2058 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_RAVEN_SUPPORT) || \
   2059     defined(BCM_SCORPION_SUPPORT)  || defined(BCM_HURRICANE_SUPPORT) || \
   2060     defined(BCM_HURRICANE2_SUPPORT) || defined(BCM_GREYHOUND_SUPPORT)
   2061     uint32 granularity = 3, flags = 0;
   2062 #endif
   2063 
   2064 #if defined (BCM_HURRICANE3_SUPPORT)
   2065     uint32 fval = 0;
   2066     uint32 regval = 0;
   2067     soc_reg_t meter_egr_port_reg = INVALIDr;
   2068     soc_field_t meter_egr_port_field = INVALIDf;
   2069     bcm_port_t port_value;
   2070 #endif /* BCM_HURRICANE3_SUPPORT */
   2071     
   2072 #if defined(BCM_GREYHOUND_SUPPORT)
   2073     if (SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANE3(unit) ||
   2074         SOC_IS_GREYHOUND2(unit)) {
   2075         /* GH support Byte mode only */
   2076         if (mode != _BCM_PORT_RATE_BYTE_MODE) {
   2077             return BCM_E_UNAVAIL;
   2078         } 
   2079     }
   2080 #endif /* BCM_GREYHOUND_SUPPORT */
   2081     
   2082     /* Take lock if IPMC repl freeze is required */
   2083     if (soc_feature(unit, soc_feature_ipmc_repl_freeze)) {
   2084         SOC_EGRESS_METERING_LOCK(unit);
   2085     }
   2086 
   2087     /*
   2088      * The procedure followed is first disable the egress metering i.e.
   2089      * reset EGRMETERINGCONFIG, then clear the buckets and re-enable the
   2090      * egress metering. Finally enable the MISCCONFING,Metering clocking
   2091      *
   2092      * NOTE: During the period of disabling and re-enabling the Egress metering
   2093      * may be in-effective for couple of cycles
   2094      */
   2095 
   2096     /* Disable egress metering for this port */
   2097     if (soc_reg_field_valid(unit, EGRMETERINGCONFIGr, REFRESHf)) {
   2098         rv = soc_reg_field32_modify(unit, EGRMETERINGCONFIGr, port, 
   2099                                     REFRESHf, 0);
   2100     }
   2101 #if defined(BCM_SCORPION_SUPPORT)
   2102       else if (soc_reg_field_valid(unit, EGRMETERINGCONFIG1r, REFRESHf)) {
   2103         rv = soc_reg_field32_modify(unit, EGRMETERINGCONFIG1r, port, 
   2104                                     REFRESHf, 0);
   2105     }
   2106 #endif /* BCM_SCORPION_SUPPORT */
   2107 
   2108     if (BCM_FAILURE(rv)) {
   2109         if (soc_feature(unit, soc_feature_ipmc_repl_freeze)) {
   2110             SOC_EGRESS_METERING_UNLOCK(unit);
   2111         }
   2112         return rv;
   2113     }
   2114 
   2115     if (soc_reg_field_valid(unit, EGRMETERINGCONFIGr, THD_SELf)) {
   2116         rv = soc_reg_field32_modify(unit, EGRMETERINGCONFIGr, port, 
   2117                                     THD_SELf, 0);
   2118     } 
   2119 
   2120     if (BCM_FAILURE(rv)) {
   2121         if (soc_feature(unit, soc_feature_ipmc_repl_freeze)) {
   2122             SOC_EGRESS_METERING_UNLOCK(unit);
   2123         }
   2124         return rv;
   2125     }
   2126 
   2127     /* Reset metering bucket. */
   2128     rv = WRITE_EGRMETERINGBUCKETr(unit, port, 0);
   2129     if (BCM_FAILURE(rv)) {
   2130         if (soc_feature(unit, soc_feature_ipmc_repl_freeze)) {
   2131             SOC_EGRESS_METERING_UNLOCK(unit);
   2132         }
   2133         return rv;
   2134     }
   2135 
   2136     /* If kbits_sec=0, metering is disabled on this egress port */
   2137     if (kbits_sec) {
   2138         /* Enable metering for this port */
   2139 
   2140 
   2141 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_RAVEN_SUPPORT) || \
   2142     defined(BCM_SCORPION_SUPPORT) || defined(BCM_HURRICANE_SUPPORT) || \
   2143     defined(BCM_GREYHOUND_SUPPORT)
   2144         if (SOC_IS_FIREBOLT2(unit) || SOC_IS_RAVEN(unit) || 
   2145             SOC_IS_HAWKEYE(unit) || SOC_IS_SC_CQ(unit) || 
   2146             SOC_IS_HURRICANEX(unit) || SOC_IS_GREYHOUND(unit) ||
   2147             SOC_IS_GREYHOUND2(unit))  {
   2148             uint32 miscval = 0;
   2149             int    refresh_bitsize = 0;
   2150             int    bucket_bitsize = 0;
   2151 
   2152             rv = READ_MISCCONFIGr(unit, &miscval);
   2153             if (BCM_FAILURE(rv)) {
   2154                 if (soc_feature(unit, soc_feature_ipmc_repl_freeze)) {
   2155                     SOC_EGRESS_METERING_UNLOCK(unit);
   2156                 }
   2157                 return rv;
   2158             }
   2159             if (soc_reg_field_valid(unit, MISCCONFIGr, ITU_MODE_SELf)) {
   2160                 if (soc_reg_field_get(unit, MISCCONFIGr,
   2161                                       miscval, ITU_MODE_SELf)) {
   2162                     flags |= _BCM_XGS_METER_FLAG_NON_LINEAR;
   2163                 }
   2164             }
   2165 
   2166             if (soc_reg_field_valid(unit, EGRMETERINGCONFIGr, METER_GRANf)) {
   2167                 flags |= _BCM_XGS_METER_FLAG_GRANULARITY;
   2168             }
   2169 
   2170             if (SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) {
   2171                 flags |= _BCM_XGS_METER_FLAG_GRANULARITY_SELECTIVE;
   2172                 flags |= _BCM_XGS_METER_FLAG_GRANULARITY_SELECT3;
   2173                 flags |= _BCM_XGS_METER_FLAG_GRANULARITY_SELECT5;
   2174                 flags |= _BCM_XGS_METER_FLAG_BUCKET_IN_8KB;
   2175             }
   2176 
   2177             if (soc_reg_field_valid(unit, EGRMETERINGCONFIGr,
   2178                                     REFRESHf)) {
   2179                 refresh_bitsize = soc_reg_field_length(unit,
   2180                                       EGRMETERINGCONFIGr, REFRESHf);
   2181             } else if (SOC_REG_IS_VALID(unit, EGRMETERINGCONFIG1r) &&
   2182                        soc_reg_field_valid(unit, EGRMETERINGCONFIG1r,
   2183                                            REFRESHf)) {
   2184                 refresh_bitsize = soc_reg_field_length(unit,
   2185                                       EGRMETERINGCONFIG1r, REFRESHf);
   2186             }
   2187             bucket_bitsize = soc_reg_field_length(unit, EGRMETERINGCONFIGr,
   2188                                                   THD_SELf);
   2189             rv = _bcm_xgs_kbits_to_bucket_encoding(kbits_sec, kbits_burst,
   2190                           flags, refresh_bitsize, bucket_bitsize,
   2191                           &refresh_rate, &bucketsize, &granularity);
   2192             if (BCM_FAILURE(rv)) {
   2193                 if (soc_feature(unit, soc_feature_ipmc_repl_freeze)) {
   2194                     SOC_EGRESS_METERING_UNLOCK(unit);
   2195                 }
   2196                 return rv;
   2197             }
   2198         } else 
   2199 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_RAVEN_SUPPORT */
   2200         {
   2201             /* Calculate  kbits rate in 64bit quantum equivalent. */ 
   2202             BCM_XGS3_PORT_RATE_64KBIT_QUANTUM(kbits_sec, refresh_rate);
   2203             bucketsize = _bcm_fb_kbits_to_bucketsize(kbits_burst);
   2204         }
   2205 
   2206         if (soc_reg_field_valid(unit, EGRMETERINGCONFIGr, REFRESHf)) {
   2207             rv = soc_reg_field32_modify(unit, EGRMETERINGCONFIGr, port, 
   2208                                         REFRESHf, refresh_rate);
   2209         }
   2210 #if defined(BCM_SCORPION_SUPPORT)
   2211         else if (soc_reg_field_valid(unit, EGRMETERINGCONFIG1r, REFRESHf)) {
   2212             rv = soc_reg_field32_modify(unit, EGRMETERINGCONFIG1r, port, 
   2213                                         REFRESHf, refresh_rate);
   2214         }
   2215 
   2216         if (soc_reg_field_valid(unit, EGRMETERINGCONFIGr, METER_GRANf) &&
   2217             (BCM_SUCCESS(rv))) {
   2218             rv = soc_reg_field32_modify(unit, EGRMETERINGCONFIGr, port, 
   2219                                         METER_GRANf, granularity);
   2220         }
   2221 #endif /* BCM_SCORPION_SUPPORT */
   2222 
   2223         if (BCM_FAILURE(rv)) {
   2224             if (soc_feature(unit, soc_feature_ipmc_repl_freeze)) {
   2225                 SOC_EGRESS_METERING_UNLOCK(unit);
   2226             }
   2227             return rv;
   2228         }
   2229 
   2230         if (soc_reg_field_valid(unit, EGRMETERINGCONFIGr, THD_SELf)) {
   2231             rv = soc_reg_field32_modify(unit, EGRMETERINGCONFIGr, port, 
   2232                                         THD_SELf, bucketsize);
   2233         }
   2234 
   2235 #if defined(BCM_HURRICANE3_SUPPORT)
   2236         meter_egr_port_reg = METER_EGR_PORT_GRANr;
   2237         meter_egr_port_field = METER_EGR_PORT_GRANf;
   2238         port_value = port;
   2239         if (SOC_IS_GREYHOUND2(unit)) {
   2240             int mmu_port;
   2241             int phy_port;
   2242             soc_info_t *si;
   2243 
   2244             /* For Greyhound2, program MMU port index */
   2245             si = &SOC_INFO(unit);
   2246             phy_port = si->port_l2p_mapping[port];
   2247             mmu_port = si->port_p2m_mapping[phy_port];
   2248 
   2249             if (mmu_port < 32) {
   2250                 meter_egr_port_reg = METER_EGR_PORT_GRAN_0r;
   2251                 port_value = mmu_port;
   2252             } else if (mmu_port < 64) {
   2253                 meter_egr_port_reg = METER_EGR_PORT_GRAN_1r;
   2254                 port_value = mmu_port - 32;
   2255             } else {
   2256                 meter_egr_port_reg = METER_EGR_PORT_GRAN_2r;
   2257                 port_value = mmu_port - 64;
   2258             }
   2259         }
   2260 
   2261         if (soc_reg_field_valid(unit, meter_egr_port_reg,
   2262                                 meter_egr_port_field)) {
   2263             rv = soc_reg32_get(unit, meter_egr_port_reg,
   2264                                REG_PORT_ANY, 0, &regval);
   2265             if (BCM_FAILURE(rv)) {
   2266                 if (soc_feature(unit, soc_feature_ipmc_repl_freeze)) {
   2267                     SOC_EGRESS_METERING_UNLOCK(unit);
   2268                 }
   2269                 return rv;
   2270             }
   2271 
   2272             fval = soc_reg_field_get(unit, meter_egr_port_reg,
   2273                                      regval, meter_egr_port_field);
   2274             if (granularity == 5) {
   2275                 fval |= (1 << port_value);
   2276             } else {
   2277                 fval &= ~(1 << port_value);
   2278             }
   2279             soc_reg_field_set(unit, meter_egr_port_reg, &regval,
   2280                               meter_egr_port_field, fval);
   2281             rv = soc_reg32_set(unit, meter_egr_port_reg,
   2282                                REG_PORT_ANY, 0, regval);
   2283             if (BCM_FAILURE(rv)) {
   2284                 if (soc_feature(unit, soc_feature_ipmc_repl_freeze)) {
   2285                     SOC_EGRESS_METERING_UNLOCK(unit);
   2286                 }
   2287                 return rv;
   2288             }
   2289         }
   2290 #endif /* BCM_HURRICANE3_SUPPORT */
   2291     }
   2292 
   2293     /* MISCCONFIG.METERING_CLK_EN is set by chip init */
   2294 
   2295     /* Release lock if IPMC repl freeze is required */
   2296     if (soc_feature(unit, soc_feature_ipmc_repl_freeze)) {
   2297         SOC_EGRESS_METERING_UNLOCK(unit);
   2298     }
   2299 
   2300     return rv;
   2301 }
   2302 
   2303 /*
   2304  * Function:
   2305  *      bcm_fb_port_rate_egress_get
   2306  * Purpose:
   2307  *      Get egress rate limiting parameters from the Firebolt chip.
   2308  * Parameters:
   2309  *      unit       - (IN)SOC unit number.
   2310  *      port       - (IN)Port number.
   2311  *      kbits_sec -  (OUT)Rate in kilobits (1000 bits) per second, or
   2312  *                        zero if rate limiting is disabled.
   2313  *      kbits_burst -(OUT) Maximum burst size in kilobits (1000 bits).
   2314  * Returns:
   2315  *      BCM_E_XXX
   2316  */
   2317 int
   2318 bcm_fb_port_rate_egress_get(int unit, bcm_port_t port,
   2319                             uint32 *kbits_sec, uint32 *kbits_burst, uint32 *mode)
   2320 {
   2321     uint32 regval = 0;               /* EGRMETERINGCONFIGr register value. */
   2322     int rv = BCM_E_NONE;             /* Operation return status.           */
   2323     uint32 refresh_rate = 0, bucketsize = 0;
   2324 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_RAPTOR_SUPPORT) || \
   2325     defined(BCM_SCORPION_SUPPORT) || defined(BCM_HURRICANE_SUPPORT) || \
   2326     defined(BCM_HURRICANE2_SUPPORT) || defined(BCM_GREYHOUND_SUPPORT)
   2327     uint32 granularity = 3, flags = 0;
   2328 #endif
   2329 
   2330     /* Input parameters check. */
   2331     if (!kbits_sec || !kbits_burst) {
   2332         return (BCM_E_PARAM);
   2333     }
   2334 
   2335     /* Take lock if IPMC repl freeze is required */
   2336     if (soc_feature(unit, soc_feature_ipmc_repl_freeze)) {
   2337         SOC_EGRESS_METERING_LOCK(unit);
   2338     }
   2339 
   2340     rv = READ_EGRMETERINGCONFIGr(unit, port, &regval);
   2341 
   2342     /* Release lock if IPMC repl freeze is required */
   2343     if (soc_feature(unit, soc_feature_ipmc_repl_freeze)) {
   2344         SOC_EGRESS_METERING_UNLOCK(unit);
   2345     }
   2346 
   2347     if (rv < 0) {
   2348         return rv;
   2349     }
   2350 
   2351     if (!soc_reg_field_get(unit, EGRMETERINGCONFIGr, regval, THD_SELf)) {
   2352         *kbits_sec = *kbits_burst = 0;
   2353     } else {
   2354         /* Convert the REFRESH field to kbits/sec (1000 bits/sec). */
   2355         if (soc_reg_field_valid(unit, EGRMETERINGCONFIGr, REFRESHf)) {
   2356             refresh_rate =
   2357                 soc_reg_field_get(unit, EGRMETERINGCONFIGr, regval, REFRESHf);
   2358         }
   2359 #if defined(BCM_SCORPION_SUPPORT)
   2360         else if (soc_reg_field_valid(unit, EGRMETERINGCONFIG1r, REFRESHf)) {
   2361             uint32 val;
   2362             SOC_IF_ERROR_RETURN
   2363                 (READ_EGRMETERINGCONFIG1r(unit, port, &val));
   2364             refresh_rate =
   2365                 soc_reg_field_get(unit, EGRMETERINGCONFIG1r, val, REFRESHf);
   2366         }
   2367 #endif /* BCM_SCORPION_SUPPORT */
   2368         /* Convert the THD_SEL field to burst size in kbits. */
   2369 
   2370         if (soc_reg_field_valid(unit, EGRMETERINGCONFIGr, THD_SELf)) {
   2371             bucketsize =
   2372                 soc_reg_field_get(unit, EGRMETERINGCONFIGr, regval, THD_SELf);
   2373         }
   2374 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_RAPTOR_SUPPORT) || \
   2375     defined(BCM_SCORPION_SUPPORT) || defined(BCM_HURRICANE_SUPPORT) || \
   2376     defined(BCM_GREYHOUND_SUPPORT)
   2377         if (SOC_IS_FIREBOLT2(unit) || SOC_IS_RAVEN(unit) || 
   2378             SOC_IS_HAWKEYE(unit) || SOC_IS_SC_CQ(unit) || 
   2379             SOC_IS_HURRICANEX(unit) || SOC_IS_GREYHOUND(unit) ||
   2380             SOC_IS_GREYHOUND2(unit)) {
   2381             uint32 miscval;
   2382 #if defined(BCM_HURRICANE3_SUPPORT)
   2383             uint32 fval = 0;
   2384             soc_reg_t meter_egr_port_reg = INVALIDr;
   2385             soc_field_t meter_egr_port_field = INVALIDf;
   2386             bcm_port_t port_value;
   2387 #endif /* BCM_HURRICANE3_SUPPORT */
   2388             if (soc_reg_field_valid(unit, MISCCONFIGr, ITU_MODE_SELf)) { 
   2389                 BCM_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, &miscval));
   2390                 if (soc_reg_field_get(unit, MISCCONFIGr,
   2391                                              miscval, ITU_MODE_SELf)) {
   2392                     flags |= _BCM_XGS_METER_FLAG_NON_LINEAR;
   2393                 }
   2394             }
   2395             if (soc_reg_field_valid(unit, EGRMETERINGCONFIGr, METER_GRANf)) {
   2396                 flags |= _BCM_XGS_METER_FLAG_GRANULARITY;
   2397                 granularity = soc_reg_field_get(unit, EGRMETERINGCONFIGr,
   2398                                                 regval, METER_GRANf);
   2399             }
   2400 
   2401 #if defined(BCM_HURRICANE3_SUPPORT)
   2402             meter_egr_port_reg = METER_EGR_PORT_GRANr;
   2403             meter_egr_port_field = METER_EGR_PORT_GRANf;
   2404             port_value = port;
   2405 
   2406             if (SOC_IS_GREYHOUND2(unit)) {
   2407                 int mmu_port;
   2408                 int phy_port;
   2409                 soc_info_t *si;
   2410 
   2411                 /* For Greyhound2, program MMU port index */
   2412                 si = &SOC_INFO(unit);
   2413                 phy_port = si->port_l2p_mapping[port];
   2414                 mmu_port = si->port_p2m_mapping[phy_port];
   2415                 if (mmu_port < 32) {
   2416                     meter_egr_port_reg = METER_EGR_PORT_GRAN_0r;
   2417                     port_value = mmu_port;
   2418                 } else if (mmu_port < 64) {
   2419                     meter_egr_port_reg = METER_EGR_PORT_GRAN_1r;
   2420                     port_value = mmu_port - 32;
   2421                 } else {
   2422                     meter_egr_port_reg = METER_EGR_PORT_GRAN_2r;
   2423                     port_value = mmu_port - 64;
   2424                 }
   2425             }
   2426 
   2427             if (soc_reg_field_valid(unit, meter_egr_port_reg,
   2428                                     meter_egr_port_field)) {
   2429                 flags |= _BCM_XGS_METER_FLAG_GRANULARITY;
   2430 
   2431                 BCM_IF_ERROR_RETURN(soc_reg32_get(unit, meter_egr_port_reg,
   2432                                     REG_PORT_ANY, 0, &regval));
   2433                 fval = soc_reg_field_get(unit, meter_egr_port_reg,
   2434                                          regval, meter_egr_port_field);
   2435 
   2436                 if (fval & (1 << port_value)) {
   2437                     granularity = 5;
   2438                 }
   2439             }
   2440 #endif /* BCM_HURRICANE3_SUPPORT */
   2441             BCM_IF_ERROR_RETURN
   2442                 (_bcm_xgs_bucket_encoding_to_kbits(refresh_rate, bucketsize,
   2443                                                    granularity, flags,
   2444                                                    kbits_sec, kbits_burst));
   2445 #if defined(BCM_GREYHOUND_SUPPORT)
   2446             if (SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANE3(unit) ||
   2447                 SOC_IS_GREYHOUND2(unit)) {
   2448                 *mode = _BCM_PORT_RATE_BYTE_MODE;
   2449             }
   2450 #endif /* BCM_GREYHOUND_SUPPORT */
   2451         } else 
   2452 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_RAVEN_SUPPORT */
   2453         {
   2454             *kbits_sec = 64 * refresh_rate;
   2455             *kbits_burst = _bcm_fb_bucketsize_to_kbits(bucketsize);
   2456         }
   2457     }
   2458     return (BCM_E_NONE);
   2459 }
   2460 #endif /* BCM_FIREBOLT_SUPPORT */
   2461 
   2462 #ifdef BCM_TRIUMPH_SUPPORT
   2463 /*
   2464  * Function:
   2465  *      bcm_tr_port_rate_egress_set
   2466  * Purpose:
   2467  *      Set egress rate limiting parameters for the Triumph chip.
   2468  * Parameters:
   2469  *      unit       - (IN)SOC unit number
   2470  *      port       - (IN)Port number
   2471  *      kbits_sec  - (IN)Rate in kilobits (1000 bits) per second.
   2472  *                       Rate of 0 disables rate limiting.
   2473  *      kbits_burst -(IN)Maximum burst size in kilobits (1000 bits).
   2474  * Returns:
   2475  *      BCM_E_XXX
   2476  */
   2477 int
   2478 bcm_tr_port_rate_egress_set(int unit, bcm_port_t port,
   2479                             uint32 kbits_sec, uint32 kbits_burst, uint32 mode)
   2480 {
   2481     uint32 miscval;
   2482     uint64 regval;
   2483     uint32 refresh_rate, bucketsize, granularity = 3, flags = 0;
   2484     int    refresh_bitsize, bucket_bitsize;
   2485 
   2486     if (mode == _BCM_PORT_RATE_PPS_MODE) {
   2487         return bcm_tr_port_pps_rate_egress_set(
   2488                             unit, port, kbits_sec, kbits_burst);
   2489     }
   2490 
   2491     /*
   2492      * The procedure followed is first disable the egress metering i.e.
   2493      * reset EGRMETERINGCONFIG, then clear the buckets and re-enable the
   2494      * egress metering. Finally enable the MISCCONFING,Metering clocking
   2495      *
   2496      * NOTE: During the period of disabling and re-enabling the Egress metering
   2497      * may be in-effective for couple of cycles
   2498      */
   2499 
   2500     /* Disable egress metering for this port */
   2501     BCM_IF_ERROR_RETURN(READ_EGRMETERINGCONFIG_64r(unit, port, &regval));
   2502     soc_reg64_field32_set(unit, EGRMETERINGCONFIG_64r, &regval, REFRESHf, 0);
   2503     soc_reg64_field32_set(unit, EGRMETERINGCONFIG_64r, &regval, THD_SELf, 0);
   2504     if (soc_reg_field_valid(unit, EGRMETERINGCONFIG_64r, MODEf)) {
   2505         soc_reg64_field32_set(unit, EGRMETERINGCONFIG_64r, &regval, MODEf, 0);
   2506     }
   2507     BCM_IF_ERROR_RETURN(WRITE_EGRMETERINGCONFIG_64r(unit, port, regval));
   2508 
   2509     /* Reset metering bucket. */
   2510     BCM_IF_ERROR_RETURN(WRITE_EGRMETERINGBUCKETr(unit, port, 0));
   2511 
   2512     /* If kbits_sec=0, metering is disabled on this egress port*/
   2513     if (kbits_sec) {
   2514         /* Enable metering for this port */
   2515 
   2516         BCM_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, &miscval));
   2517         if (soc_reg_field_get(unit, MISCCONFIGr, miscval, ITU_MODE_SELf)) {
   2518             flags |= _BCM_XGS_METER_FLAG_NON_LINEAR;
   2519         }
   2520         flags |= _BCM_XGS_METER_FLAG_GRANULARITY;
   2521         if (SOC_IS_TD_TT(unit)) {
   2522             flags |= _BCM_XGS_METER_FLAG_DOUBLE_REFRESH_FREQ;
   2523         }
   2524         refresh_bitsize = soc_reg_field_length(unit, EGRMETERINGCONFIG_64r,
   2525                                                REFRESHf);
   2526         bucket_bitsize = soc_reg_field_length(unit, EGRMETERINGCONFIG_64r,
   2527                                               THD_SELf);
   2528         BCM_IF_ERROR_RETURN
   2529             (_bcm_xgs_kbits_to_bucket_encoding(kbits_sec, kbits_burst, flags,
   2530                                refresh_bitsize, bucket_bitsize,
   2531                                &refresh_rate, &bucketsize, &granularity));
   2532         if (soc_reg_field_valid(unit, EGRMETERINGCONFIG_64r, MODEf)) {
   2533             soc_reg64_field32_set(unit, EGRMETERINGCONFIG_64r, &regval,
   2534                             MODEf, 0);
   2535         }
   2536         if (soc_reg_field_valid(unit, EGRMETERINGCONFIG_64r, METER_GRANf)) {
   2537             soc_reg64_field32_set(unit, EGRMETERINGCONFIG_64r, &regval,
   2538                                   METER_GRANf, granularity);
   2539         }
   2540         soc_reg64_field32_set(unit, EGRMETERINGCONFIG_64r, &regval,
   2541                               REFRESHf, refresh_rate);
   2542         soc_reg64_field32_set(unit, EGRMETERINGCONFIG_64r, &regval,
   2543                               THD_SELf, bucketsize);
   2544         BCM_IF_ERROR_RETURN(WRITE_EGRMETERINGCONFIG_64r(unit, port, regval));
   2545     }
   2546 
   2547     /* MISCCONFIG.METERING_CLK_EN is set by chip init */
   2548 
   2549     return BCM_E_NONE;
   2550 }
   2551 
   2552 /*
   2553  * Function:
   2554  *      bcm_tr_port_rate_egress_get
   2555  * Purpose:
   2556  *      Get egress rate limiting parameters from the Triumph chip.
   2557  * Parameters:
   2558  *      unit       - (IN)SOC unit number.
   2559  *      port       - (IN)Port number.
   2560  *      kbits_sec -  (OUT)Rate in kilobits (1000 bits) per second, or
   2561  *                        zero if rate limiting is disabled.
   2562  *      kbits_burst -(OUT) Maximum burst size in kilobits (1000 bits).
   2563  * Returns:
   2564  *      BCM_E_XXX
   2565  */
   2566 int
   2567 bcm_tr_port_rate_egress_get(int unit, bcm_port_t port,
   2568                         uint32 *kbits_sec, uint32 *kbits_burst, uint32 *mode)
   2569 {
   2570     uint64 regval;                   /* EGRMETERINGCONFIGr register value. */
   2571     uint32 miscval;
   2572     uint32 refresh_rate = 0, bucketsize = 0, granularity = 3, flags = 0;
   2573 
   2574     COMPILER_64_ZERO(regval);
   2575 
   2576     /* Input parameters check. */
   2577     if (!kbits_sec || !kbits_burst) {
   2578         return (BCM_E_PARAM);
   2579     }
   2580 
   2581     BCM_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, &miscval));
   2582     if (soc_reg_field_get(unit, MISCCONFIGr, miscval, ITU_MODE_SELf)) {
   2583         flags |= _BCM_XGS_METER_FLAG_NON_LINEAR;
   2584     }
   2585 
   2586     BCM_IF_ERROR_RETURN(READ_EGRMETERINGCONFIG_64r(unit, port, &regval));
   2587 
   2588     if (soc_reg_field_valid(unit, EGRMETERINGCONFIG_64r, MODEf)) {
   2589         if (1 == soc_reg64_field32_get(unit, EGRMETERINGCONFIG_64r, 
   2590                                         regval, MODEf)) {
   2591             *mode = _BCM_PORT_RATE_PPS_MODE;
   2592             return bcm_tr_port_pps_rate_egress_get(unit, port, 
   2593                                                 kbits_sec, kbits_burst);
   2594         }
   2595     }
   2596 
   2597     bucketsize = soc_reg64_field32_get(unit, EGRMETERINGCONFIG_64r,
   2598                                        regval, THD_SELf);
   2599     refresh_rate = soc_reg64_field32_get(unit, EGRMETERINGCONFIG_64r, 
   2600                                          regval, REFRESHf);
   2601     flags |= _BCM_XGS_METER_FLAG_GRANULARITY;
   2602     if (SOC_IS_TD_TT(unit)) {
   2603         flags |= _BCM_XGS_METER_FLAG_DOUBLE_REFRESH_FREQ;
   2604     }
   2605 
   2606     if (soc_reg_field_valid(unit, EGRMETERINGCONFIG_64r, METER_GRANf)) {
   2607         granularity = soc_reg64_field32_get(unit, EGRMETERINGCONFIG_64r,
   2608                                             regval, METER_GRANf);
   2609     }
   2610     BCM_IF_ERROR_RETURN
   2611         (_bcm_xgs_bucket_encoding_to_kbits(refresh_rate, bucketsize,
   2612                                            granularity, flags,
   2613                                            kbits_sec, kbits_burst));
   2614 
   2615     return (BCM_E_NONE);
   2616 }
   2617 
   2618 int
   2619 bcm_tr_port_pps_rate_egress_set(int unit, bcm_port_t port,
   2620                                 uint32 pps, uint32 burst)
   2621 {
   2622     uint32 miscval;
   2623     uint64 regval;
   2624     uint32 refresh_rate, bucketsize, granularity = 3, flags = 0;
   2625     int    refresh_bitsize, bucket_bitsize;
   2626 
   2627     /*
   2628      * The procedure followed is first disable the egress metering i.e.
   2629      * reset EGRMETERINGCONFIG, then clear the buckets and re-enable the
   2630      * egress metering. Finally enable the MISCCONFING,Metering clocking
   2631      *
   2632      * NOTE: During the period of disabling and re-enabling the Egress metering
   2633      * may be in-effective for couple of cycles
   2634      */
   2635 
   2636     /* Disable egress metering for this port */
   2637     BCM_IF_ERROR_RETURN(READ_EGRMETERINGCONFIG_64r(unit, port, &regval));
   2638     soc_reg64_field32_set(unit, EGRMETERINGCONFIG_64r, &regval, REFRESHf, 0);
   2639     soc_reg64_field32_set(unit, EGRMETERINGCONFIG_64r, &regval, THD_SELf, 0);
   2640     if (soc_reg_field_valid(unit, EGRMETERINGCONFIG_64r, MODEf)) {
   2641         soc_reg64_field32_set(unit, EGRMETERINGCONFIG_64r, &regval, MODEf, 0);
   2642     }
   2643     BCM_IF_ERROR_RETURN(WRITE_EGRMETERINGCONFIG_64r(unit, port, regval));
   2644 
   2645     /* Reset metering bucket. */
   2646     BCM_IF_ERROR_RETURN(WRITE_EGRMETERINGBUCKETr(unit, port, 0));
   2647 
   2648     /* If pps=0, metering is disabled on this egress port*/
   2649     if (pps) {
   2650         /* Enable metering for this port */
   2651 
   2652         BCM_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, &miscval));
   2653         if (soc_reg_field_get(unit, MISCCONFIGr, miscval, ITU_MODE_SELf)) {
   2654             flags |= _BCM_XGS_METER_FLAG_NON_LINEAR;
   2655         }
   2656         flags |= _BCM_XGS_METER_FLAG_PACKET_MODE;
   2657         flags |= _BCM_XGS_METER_FLAG_GRANULARITY;
   2658         if (SOC_IS_TD_TT(unit)) {
   2659             flags |= _BCM_XGS_METER_FLAG_DOUBLE_REFRESH_FREQ;
   2660         }
   2661         refresh_bitsize = soc_reg_field_length(unit, EGRMETERINGCONFIG_64r,
   2662                                                REFRESHf);
   2663         bucket_bitsize = soc_reg_field_length(unit, EGRMETERINGCONFIG_64r,
   2664                                               THD_SELf);
   2665         BCM_IF_ERROR_RETURN
   2666             (_bcm_xgs_kbits_to_bucket_encoding(pps, burst, flags,
   2667                                refresh_bitsize, bucket_bitsize,
   2668                                &refresh_rate, &bucketsize, &granularity));
   2669 
   2670         if (soc_reg_field_valid(unit, EGRMETERINGCONFIG_64r, MODEf)) {
   2671             soc_reg64_field32_set(unit, EGRMETERINGCONFIG_64r, &regval,
   2672                                   MODEf, 1);
   2673         }
   2674         if (soc_reg_field_valid(unit, EGRMETERINGCONFIG_64r, METER_GRANf)) {
   2675             soc_reg64_field32_set(unit, EGRMETERINGCONFIG_64r, &regval,
   2676                                   METER_GRANf, granularity);
   2677         }
   2678         soc_reg64_field32_set(unit, EGRMETERINGCONFIG_64r, &regval,
   2679                               REFRESHf, refresh_rate);
   2680         soc_reg64_field32_set(unit, EGRMETERINGCONFIG_64r, &regval,
   2681                               THD_SELf, bucketsize);
   2682         BCM_IF_ERROR_RETURN(WRITE_EGRMETERINGCONFIG_64r(unit, port, regval));
   2683     }
   2684 
   2685     /* MISCCONFIG.METERING_CLK_EN is set by chip init */
   2686 
   2687     return BCM_E_NONE;
   2688 }
   2689 
   2690 int
   2691 bcm_tr_port_pps_rate_egress_get(int unit, bcm_port_t port,
   2692                                 uint32 *pps, uint32 *burst)
   2693 {
   2694     uint64 regval;                   /* EGRMETERINGCONFIGr register value. */
   2695     uint32 miscval;
   2696     uint32 refresh_rate = 0, bucketsize = 0, granularity = 3, flags = 0;
   2697 
   2698     COMPILER_64_ZERO(regval);
   2699 
   2700     /* Input parameters check. */
   2701     if (!pps || !burst) {
   2702         return (BCM_E_PARAM);
   2703     }
   2704 
   2705     BCM_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, &miscval));
   2706     if (soc_reg_field_get(unit, MISCCONFIGr, miscval, ITU_MODE_SELf)) {
   2707         flags |= _BCM_XGS_METER_FLAG_NON_LINEAR;
   2708     }
   2709 
   2710     BCM_IF_ERROR_RETURN(READ_EGRMETERINGCONFIG_64r(unit, port, &regval));
   2711 
   2712     bucketsize = soc_reg64_field32_get(unit, EGRMETERINGCONFIG_64r,
   2713                                        regval, THD_SELf);
   2714     refresh_rate = soc_reg64_field32_get(unit, EGRMETERINGCONFIG_64r, 
   2715                                          regval, REFRESHf);
   2716     flags |= _BCM_XGS_METER_FLAG_PACKET_MODE;
   2717     flags |= _BCM_XGS_METER_FLAG_GRANULARITY;
   2718     if (SOC_IS_TD_TT(unit)) {
   2719         flags |= _BCM_XGS_METER_FLAG_DOUBLE_REFRESH_FREQ;
   2720     }
   2721 
   2722     if (soc_reg_field_valid(unit, EGRMETERINGCONFIG_64r, METER_GRANf)) {
   2723         granularity = soc_reg64_field32_get(unit, EGRMETERINGCONFIG_64r,
   2724                                             regval, METER_GRANf);
   2725     }
   2726     BCM_IF_ERROR_RETURN
   2727         (_bcm_xgs_bucket_encoding_to_kbits(refresh_rate, bucketsize,
   2728                                            granularity, flags,
   2729                                            pps, burst));
   2730 
   2731     return (BCM_E_NONE);
   2732 }
   2733 
   2734 #endif /* BCM_TRIUMPH_SUPPORT */
   2735 
   2736 /*
   2737  * Function:
   2738  *      bcm_xgs3_port_cfg_get
   2739  * Purpose:
   2740  *      Get port configuration.
   2741  * Parameters:
   2742  *      unit       - (IN)SOC unit number.
   2743  *      port       - (IN)Port number.
   2744  *      port_cfg   - (OUT)API port information structure.
   2745  * Returns:
   2746  *      BCM_E_XXX
   2747  */
   2748 int
   2749 bcm_xgs3_port_cfg_get(int unit, bcm_port_t port, bcm_port_cfg_t *port_cfg)
   2750 {
   2751     /* Input parameters check.*/
   2752     if (NULL == port_cfg) {
   2753         return (BCM_E_PARAM);
   2754     }
   2755 
   2756     sal_memset(port_cfg, 0, sizeof(bcm_port_cfg_t));
   2757 
   2758     /* Read port table entry. */
   2759     BCM_IF_ERROR_RETURN(_bcm_xgs3_port_table_read(unit, port, port_cfg));
   2760 
   2761     return(BCM_E_NONE);
   2762 }
   2763 
   2764 /*
   2765  * Function:
   2766  *      bcm_xgs3_port_cfg_set
   2767  * Purpose:
   2768  *      Set port configuration. 
   2769  * Parameters:
   2770  *      unit       - (IN)SOC unit number.
   2771  *      port       - (IN)Port number.
   2772  *      port_cfg   - (IN)API port information structure.
   2773  * Returns:
   2774  *      BCM_E_XXX
   2775  */
   2776 int
   2777 bcm_xgs3_port_cfg_set(int unit, bcm_port_t port, bcm_port_cfg_t *port_cfg)
   2778 {
   2779     /* Input parameters check.*/
   2780     if (NULL == port_cfg) {
   2781         return (BCM_E_PARAM);
   2782     }
   2783 
   2784     /* Write port table entry. */
   2785     BCM_IF_ERROR_RETURN(_bcm_xgs3_port_table_write(unit, port, port_cfg));
   2786 
   2787     return (BCM_E_NONE);
   2788 }
   2789 
   2790 /*
   2791  * Function:
   2792  *      bcm_xgs3_port_cfg_init
   2793  * Purpose:
   2794  *      Initialize the port configuration according to Initial System
   2795  *      Configuration (see init.c)
   2796  * Parameters:
   2797  *      unit       - (IN)StrataSwitch unit number.
   2798  *      port       - (IN)Port number.
   2799  *      vlan_data  - (IN)Initial VLAN data information
   2800  * Returns:
   2801  *      BCM_E_XXX
   2802  */
   2803 int
   2804 bcm_xgs3_port_cfg_init(int unit, bcm_port_t port, bcm_vlan_data_t *vlan_data)
   2805 {
   2806 #ifdef BCM_FIREBOLT_SUPPORT
   2807     if(SOC_IS_FBX(unit)) {
   2808         return _bcm_fb_port_cfg_init(unit, port, vlan_data);
   2809     }
   2810 #endif /* BCM_FIREBOLT_SUPPORT */
   2811     return (BCM_E_NONE);
   2812 }
   2813 
   2814 /*
   2815  * Function:
   2816  *      bcm_xgs3_port_rate_ingress_set
   2817  * Purpose:
   2818  *      Set ingress rate limiting parameters
   2819  * Parameters:
   2820  *      unit        - (IN) SOC unit number.   
   2821  *      port        - (IN) Port number.
   2822  *      kbits_sec   - (IN) Rate in kilobits (1000 bits) per second.
   2823  *                         Rate of 0 disables rate limiting.
   2824  *      kbits_burst - (IN) Maximum burst size in kilobits (1000 bits).
   2825  * Returns:
   2826  *      BCM_E_XXX
   2827  * Notes:
   2828  *      Rate-based pause frames automatically will be enabled
   2829  *      whenever ingress rate metering is enabled. Since the
   2830  *      pause frame behavior also affects the discard/accept
   2831  *      behavior of the ingress meter, the pause frame behavior
   2832  *      is set such that the discard/accept hysteresis is as
   2833  *      small as possible.
   2834  */
   2835 int
   2836 bcm_xgs3_port_rate_ingress_set(int unit, bcm_port_t port,
   2837                                uint32 kbits_sec, uint32 kbits_burst)
   2838 {
   2839 #ifdef BCM_MONTEREY_SUPPORT
   2840     if (SOC_IS_MONTEREY(unit)) {
   2841         return BCM_E_UNAVAIL;
   2842     } else
   2843 #endif
   2844 #ifdef BCM_TOMAHAWK_SUPPORT
   2845     if (SOC_IS_TOMAHAWKX(unit) || SOC_IS_TRIDENT3X(unit)) {
   2846         return BCM_E_UNAVAIL;
   2847     } else
   2848 #endif
   2849 #ifdef BCM_TRIDENT2_SUPPORT
   2850     if (SOC_IS_TD2_TT2(unit)) {
   2851         return bcm_td2_port_rate_ingress_set(unit, port, kbits_sec,
   2852                                              kbits_burst);
   2853     } else
   2854 #endif
   2855 #ifdef BCM_TRIUMPH_SUPPORT
   2856     if(SOC_IS_TR_VL(unit) && !SOC_IS_HURRICANEX(unit) && 
   2857            !SOC_IS_GREYHOUND(unit) && !SOC_IS_GREYHOUND2(unit)) {
   2858         return _bcm_tr_port_rate_ingress_set(unit, port,
   2859                                              kbits_sec, kbits_burst);
   2860     } else
   2861 #endif
   2862 #ifdef BCM_FIREBOLT_SUPPORT
   2863     if(SOC_IS_FBX(unit)) {
   2864         return _bcm_fb_port_rate_ingress_set(unit, port,
   2865                                              kbits_sec, kbits_burst);
   2866     }
   2867 #endif /* BCM_FIREBOLT_SUPPORT */
   2868     return (BCM_E_UNAVAIL);
   2869 }
   2870 
   2871 /*
   2872  * Function:
   2873  *      bcm_xgs3_port_rate_ingress_get
   2874  * Purpose:
   2875  *      Get ingress rate limiting parameters
   2876  * Parameters:
   2877  *      unit        - (IN)SOC unit number.
   2878  *      port        - (IN)Port number.
   2879  *      kbits_sec   - (OUT) Rate in kilobits (1000 bits) per second, or
   2880  *                        zero if rate limiting is disabled.
   2881  *      kbits_burst - (OUT) Maximum burst size in kilobits (1000 bits).
   2882  * Returns:
   2883  *      BCM_E_XXX
   2884  */
   2885 int
   2886 bcm_xgs3_port_rate_ingress_get(int unit, bcm_port_t port,
   2887                                uint32 *kbits_sec, uint32 *kbits_burst)
   2888 {
   2889 
   2890 #ifdef BCM_MONTEREY_SUPPORT
   2891     if (SOC_IS_MONTEREY(unit)) {
   2892         return BCM_E_UNAVAIL; 
   2893     } else
   2894 #endif
   2895 #ifdef BCM_TOMAHAWK_SUPPORT
   2896     if (SOC_IS_TOMAHAWKX(unit) || SOC_IS_TRIDENT3X(unit)) {
   2897         return BCM_E_UNAVAIL; 
   2898     } else
   2899 #endif
   2900 #ifdef BCM_TRIDENT2_SUPPORT
   2901     if (SOC_IS_TD2_TT2(unit)) {
   2902         return bcm_td2_port_rate_ingress_get(unit, port, kbits_sec,
   2903                                              kbits_burst); 
   2904     } else
   2905 #endif
   2906 #ifdef BCM_TRIUMPH_SUPPORT
   2907     if(SOC_IS_TR_VL(unit) && !SOC_IS_HURRICANEX(unit) && 
   2908             !SOC_IS_GREYHOUND(unit) && !SOC_IS_GREYHOUND2(unit)) {
   2909         return _bcm_tr_port_rate_ingress_get(unit, port,
   2910                                              kbits_sec, kbits_burst); 
   2911     } else
   2912 #endif
   2913 #ifdef BCM_FIREBOLT_SUPPORT
   2914     if(SOC_IS_FBX(unit)) {
   2915         return _bcm_fb_port_rate_ingress_get(unit, port,
   2916                                              kbits_sec, kbits_burst); 
   2917     }
   2918 #endif /* BCM_FIREBOLT_SUPPORT */
   2919     return (BCM_E_UNAVAIL);
   2920 }
   2921 
   2922 /*
   2923  * MAX_SFLOW_RANGE is used for converting a sampling rate to a threshold
   2924  * value used for comparison with the sFlow random number for a port.
   2925  * If the random number is less than the threshold value, an sFlow
   2926  * sample record is sent to the CPU.
   2927  */
   2928 #define MAX_SFLOW_RANGE (1 << (SFLOW_RANGE_MAX(unit)))
   2929 
   2930 /*
   2931  * Function:
   2932  *    _bcm_xgs3_port_sample_rate_set
   2933  * Purpose:
   2934  *    Set rate sampling parameters for XGS3 family chip.
   2935  * Parameters:
   2936  *    unit         - (IN)SOC unit number.
   2937  *    port         - (IN)Port number.
   2938  *    rate         - (IN)Every 1/rate a packet will be sampled
   2939  *            1 indicating sample all.
   2940  *            0 indicating sample none.
   2941  *   rate_reg      - (IN)Ingress/Egress rate register. 
   2942  * Returns:
   2943  *    BCM_E_XXX
   2944  */
   2945 int
   2946 _bcm_xgs3_port_sample_rate_set(int unit, bcm_port_t port,
   2947                                int rate, soc_reg_t reg) 
   2948 {
   2949     soc_field_t fields[2] = {ENABLEf, THRESHOLDf};
   2950     uint32 values[2] = {0, 0};
   2951 #if defined(BCM_TOMAHAWK_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT)
   2952     sflow_ing_data_source_entry_t sflow_entry;
   2953     soc_counter_non_dma_t *non_dma = NULL;
   2954     soc_control_t *soc;
   2955     uint32 count = 0, subset_ct = 0;
   2956 #endif /* BCM_TOMAHAWK_SUPPORT || BCM_TRIDENT3_SUPPORT */
   2957 
   2958     /* Setup 'enable' and 'threshold' fields for register. */
   2959     if (rate > 0) {
   2960 
   2961         /* Enable sFlow */
   2962         values[0] = 1;
   2963 
   2964         /* Set sampling threshold */
   2965         if (rate == 1) {
   2966             /* Needs special handling to avoid register overflow */
   2967             values[1] = MAX_SFLOW_RANGE - 1;
   2968         } else {
   2969             /* Calculate threshold based on sampling rate */
   2970             values[1] = MAX_SFLOW_RANGE / rate;
   2971         }
   2972 
   2973         /* 
   2974          * For early sFlow implementations the 16-bit threshold value
   2975          * is compared to bits [23:8] of the sFlow random number.
   2976          */
   2977         if (soc_feature(unit, soc_feature_sample_offset8)) {
   2978             values[1] >>= 8;
   2979         }
   2980 
   2981         /* Cut the value in case 16 bit threshold can not accomodate it. */
   2982         if (soc_feature(unit, soc_feature_sample_thresh16)) {
   2983             if (values[1] >= (1 << 16)) {
   2984                 values[1] = (1 << 16) - 1;
   2985             }
   2986         }
   2987     }
   2988 
   2989 #if defined(BCM_TOMAHAWK_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT)
   2990     /* Update Ingress rate limiting data table. */
   2991     if((reg == SFLOW_ING_THRESHOLDr) &&
   2992         soc_feature(unit, soc_feature_sflow_ing_mem)) {
   2993         BCM_IF_ERROR_RETURN(
   2994         READ_SFLOW_ING_DATA_SOURCEm(unit, MEM_BLOCK_ANY, port,
   2995                                     &sflow_entry));
   2996         soc_SFLOW_ING_DATA_SOURCEm_field_set(unit, &sflow_entry, fields[0],
   2997                                              &values[0]);
   2998         soc_SFLOW_ING_DATA_SOURCEm_field_set(unit, &sflow_entry, fields[1],
   2999                                              &values[1]);
   3000         soc_SFLOW_ING_DATA_SOURCEm_field_set(unit, &sflow_entry, CPUf,
   3001                                              &values[0]);
   3002         BCM_IF_ERROR_RETURN(
   3003             WRITE_SFLOW_ING_DATA_SOURCEm(unit, MEM_BLOCK_ANY, port,
   3004                                          &sflow_entry));
   3005 
   3006         /* Enable counter thread for Ingress sFlow samplers */
   3007         if (values[0] == 1) {
   3008             soc = SOC_CONTROL(unit);
   3009             non_dma = &soc->counter_non_dma[SOC_COUNTER_NON_DMA_SFLOW_ING_PKT -
   3010                                             SOC_COUNTER_NON_DMA_START];
   3011             if (non_dma && !(non_dma->flags & _SOC_COUNTER_NON_DMA_VALID)) {
   3012                 /* Do PACKET_CTRf and BYTE_CTRf sequentially. Hence 2x loop */
   3013                 subset_ct = non_dma->extra_ctr_ct << 1;
   3014                 non_dma->flags |= _SOC_COUNTER_NON_DMA_VALID;
   3015                 non_dma = non_dma->extra_ctrs;
   3016 
   3017                 if (non_dma) {
   3018                 do {
   3019                     non_dma->flags |= _SOC_COUNTER_NON_DMA_VALID;
   3020                     /* BYTE_CTRf not currently supported */
   3021                     count += 2;
   3022                     non_dma += 2;
   3023                     } while (non_dma && (count < subset_ct));
   3024                 }
   3025             }
   3026         }
   3027         return BCM_E_NONE;
   3028     } else if (!SOC_REG_IS_VALID(unit, reg)) {
   3029         return BCM_E_UNAVAIL;
   3030     }
   3031 #endif /* BCM_TOMAHAWK_SUPPORT || BCM_TRIDENT3_SUPPORT */
   3032 
   3033     /* Update rate limiting regster values. */   
   3034     return soc_reg_fields32_modify(unit, reg, port,
   3035                                    sizeof(fields)/sizeof(uint32),
   3036                                    fields, values);
   3037 }
   3038 
   3039 /*
   3040  * Function:
   3041  *    bcm_xgs3_port_sample_rate_set
   3042  * Purpose:
   3043  *    Set rate sampling parameters for XGS3 family chip.
   3044  * Parameters:
   3045  *    unit         - (IN)SOC unit number.
   3046  *    port         - (IN)Port number.
   3047  *    ingress_rate - (IN)Every 1/ingress_rate a packet will be sampled
   3048  *            1 indicating sample all.
   3049  *            0 indicating sample none.
   3050  *    egress_rate  - (IN)Every 1/egress_rate a packet will be sampled
   3051  *            1 indicating sample all.
   3052  *            0 indicating sample none.
   3053  * Returns:
   3054  *    BCM_E_XXX
   3055  */
   3056 int
   3057 bcm_xgs3_port_sample_rate_set(int unit, bcm_port_t port,
   3058                               int ingress_rate, int egress_rate ) 
   3059 {
   3060     /* Set ingress rate limiting. */
   3061     BCM_IF_ERROR_RETURN
   3062         (_bcm_xgs3_port_sample_rate_set(unit, port, ingress_rate,
   3063                                         SFLOW_ING_THRESHOLDr)); 
   3064 
   3065     /* Set egress rate limiting. */
   3066     return _bcm_xgs3_port_sample_rate_set(unit, port, egress_rate,
   3067                                           SFLOW_EGR_THRESHOLDr); 
   3068 }
   3069 
   3070 /*
   3071  * Function:
   3072  *    bcm_xgs3_port_sample_rate_get
   3073  * Purpose:
   3074  *    Get rate sampling parameters from the hw.
   3075  * Parameters:
   3076  *    unit          - (IN)SOC unit number.
   3077  *    port          - (IN)Port number.
   3078  *    ingress_rate  - (OUT)Every 1/ingress_rate a packet will be sampled
   3079  *            1 indicating sample all.
   3080  *            0 indicating sample none.
   3081  *    egress_rate   - (OUT)Every 1/egress_rate a packet will be sampled
   3082  *            1 indicating sample all.
   3083  *            0 indicating sample none.
   3084  * Returns:
   3085  *    BCM_E_XXX
   3086  */
   3087 int
   3088 bcm_xgs3_port_sample_rate_get(int unit, bcm_port_t port,
   3089                               int *ingress_rate, int *egress_rate ) 
   3090 {
   3091     uint32 ingress_regval       = 0;
   3092     uint32 ingress_field_enable = 0;
   3093     uint32 ingress_field_thresh;
   3094     uint32 egress_regval;
   3095     uint32 egress_field_enable;
   3096     uint32 egress_field_thresh;
   3097 #ifdef BCM_TOMAHAWK_SUPPORT
   3098     sflow_ing_data_source_entry_t sflow_entry;
   3099 #endif /* BCM_TOMAHAWK_SUPPORT */
   3100 
   3101     /* Input parameters sanity. */
   3102     if ((NULL ==  ingress_rate) || (NULL == egress_rate)) {
   3103         return (BCM_E_PARAM);
   3104     }
   3105 
   3106 #if defined(BCM_TOMAHAWK_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT)
   3107     if (soc_feature(unit, soc_feature_sflow_ing_mem)) {
   3108         BCM_IF_ERROR_RETURN(
   3109             READ_SFLOW_ING_DATA_SOURCEm(unit, MEM_BLOCK_ANY, port,
   3110                                         &sflow_entry));
   3111     } else
   3112 #endif /* BCM_TOMAHAWK_SUPPORT || BCM_TRIDENT3_SUPPORT */
   3113 
   3114 #if defined(BCM_TOMAHAWK_SUPPORT)
   3115     if (SOC_REG_IS_VALID(unit,SFLOW_ING_THRESHOLDr)){
   3116         BCM_IF_ERROR_RETURN(READ_SFLOW_ING_THRESHOLDr(unit, port,
   3117                                                       &ingress_regval));
   3118     } else {
   3119         return BCM_E_UNAVAIL;
   3120     }
   3121 #else
   3122     BCM_IF_ERROR_RETURN(READ_SFLOW_ING_THRESHOLDr(unit, port, &ingress_regval));
   3123 #endif
   3124     BCM_IF_ERROR_RETURN(READ_SFLOW_EGR_THRESHOLDr(unit, port, &egress_regval));
   3125 
   3126     /* read 'enable' and 'threshold' fields for ingress and egress ports */
   3127 #if defined(BCM_TOMAHAWK_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT)
   3128     if (soc_feature(unit, soc_feature_sflow_ing_mem)) {
   3129         soc_SFLOW_ING_DATA_SOURCEm_field_get(unit, &sflow_entry, ENABLEf,
   3130                                              &ingress_field_enable);
   3131         soc_SFLOW_ING_DATA_SOURCEm_field_get(unit, &sflow_entry, THRESHOLDf,
   3132                                              &ingress_field_thresh);
   3133     } else
   3134 #endif /* BCM_TOMAHAWK_SUPPORT  || BCM_TRIDENT3_SUPPORT */
   3135     {
   3136         ingress_field_enable = soc_reg_field_get(unit, SFLOW_ING_THRESHOLDr,
   3137                                                  ingress_regval, ENABLEf);
   3138         ingress_field_thresh = soc_reg_field_get(unit, SFLOW_ING_THRESHOLDr,
   3139                                                  ingress_regval, THRESHOLDf);
   3140     }
   3141     egress_field_enable = soc_reg_field_get(unit, SFLOW_EGR_THRESHOLDr,
   3142                                             egress_regval, ENABLEf);
   3143     egress_field_thresh = soc_reg_field_get(unit, SFLOW_EGR_THRESHOLDr,
   3144                                             egress_regval, THRESHOLDf);
   3145 
   3146     /* 
   3147      * For early sFlow implementations the 16-bit threshold value
   3148      * is compared to bits [23:8] of the sFlow random number.
   3149      */
   3150     if (soc_feature(unit, soc_feature_sample_offset8)) {
   3151         ingress_field_thresh <<= 8;
   3152         egress_field_thresh <<= 8;
   3153     }
   3154 
   3155     /* Translate fields into ingress and egress rates */
   3156     if (ingress_field_enable) {
   3157         if (ingress_field_thresh) {
   3158             *ingress_rate = MAX_SFLOW_RANGE / ingress_field_thresh;
   3159         } else {
   3160             *ingress_rate = MAX_SFLOW_RANGE;
   3161         }
   3162     }
   3163     else {
   3164         *ingress_rate = 0;
   3165         if (ingress_field_thresh) {
   3166             return (BCM_E_INTERNAL);
   3167         }
   3168     }
   3169 
   3170     if (egress_field_enable) {
   3171         if (egress_field_thresh) { 
   3172             *egress_rate = MAX_SFLOW_RANGE / egress_field_thresh;
   3173         } else {
   3174             *egress_rate = MAX_SFLOW_RANGE;
   3175         }
   3176     }
   3177     else {
   3178         *egress_rate = 0;
   3179         if (egress_field_thresh) { 
   3180             return (BCM_E_INTERNAL);
   3181         }
   3182     }
   3183 
   3184     return (BCM_E_NONE);
   3185 }
   3186 #undef MAX_SFLOW_RANGE
   3187 /*
   3188  * Function:
   3189  *      _bcm_fb_port_protocol_vlan_add
   3190  * Purpose:
   3191  *      Adds a protocol based vlan to a port.  The protocol
   3192  *      is matched by frame type and ether type.  
   3193  * Parameters:
   3194  *      unit  - (IN) BCM device number
   3195  *      port  - (IN) Port number
   3196  *      frame - (IN) one of BCM_PORT_FRAMETYPE_{ETHER2,8023,LLC}
   3197  *      ether - (IN) 16 bit Ethernet type field
   3198  *      vid   - (IN)VLAN ID
   3199  * Returns:
   3200  *      BCM_E_XXX
   3201  */
   3202 int
   3203 _bcm_fb_port_protocol_vlan_add(int unit,
   3204                            bcm_port_t port,
   3205                            bcm_port_frametype_t frame,
   3206                            bcm_port_ethertype_t ether,
   3207                            bcm_vlan_t vid)
   3208 {
   3209     bcm_port_frametype_t         ft;
   3210     bcm_port_ethertype_t         et;
   3211     bcm_port_t                   p;
   3212     _bcm_port_info_t             *pinfo;
   3213     vlan_protocol_entry_t        vpe;
   3214     vlan_protocol_data_entry_t   vde;
   3215     int                          idxmin, idxmax;
   3216     int                          vlan_prot_entries;
   3217     int                          vpentry, vdentry;
   3218     bcm_pbmp_t                   switched_pbm;
   3219     int                          i;
   3220     int                          empty;
   3221 
   3222     idxmin = soc_mem_index_min(unit, VLAN_PROTOCOLm);
   3223     idxmax = soc_mem_index_max(unit, VLAN_PROTOCOLm);
   3224     vlan_prot_entries = idxmax + 1;
   3225     vpentry = empty = -1;
   3226     for (i = idxmin; i <= idxmax; i++) {
   3227         SOC_IF_ERROR_RETURN
   3228             (READ_VLAN_PROTOCOLm(unit, MEM_BLOCK_ANY, i, &vpe));
   3229         ft = 0;
   3230         if (soc_VLAN_PROTOCOLm_field32_get(unit, &vpe, ETHERIIf)) {
   3231             ft |= BCM_PORT_FRAMETYPE_ETHER2;
   3232         }
   3233         if (soc_VLAN_PROTOCOLm_field32_get(unit, &vpe, SNAPf)) {
   3234             ft |= BCM_PORT_FRAMETYPE_8023;
   3235         }
   3236         if (soc_VLAN_PROTOCOLm_field32_get(unit, &vpe, LLCf)) {
   3237             ft |= BCM_PORT_FRAMETYPE_LLC;
   3238         }
   3239         et = soc_VLAN_PROTOCOLm_field32_get(unit, &vpe, ETHERTYPEf);
   3240         if (empty < 0 && ft == 0) {
   3241             empty = i;
   3242         }
   3243         if (ft == frame && et == ether) {
   3244             vpentry = i;
   3245             break;
   3246         }
   3247     }
   3248     if (vpentry < 0 && empty < 0) {
   3249         return BCM_E_FULL;
   3250     }
   3251     if (vpentry < 0) {
   3252         sal_memset(&vpe, 0, sizeof(vpe));
   3253         soc_VLAN_PROTOCOLm_field32_set(unit, &vpe, ETHERTYPEf, ether);
   3254         if (frame & BCM_PORT_FRAMETYPE_ETHER2) {
   3255             soc_VLAN_PROTOCOLm_field32_set(unit, &vpe, ETHERIIf, 1);
   3256         }
   3257         if (frame & BCM_PORT_FRAMETYPE_8023) {
   3258             soc_VLAN_PROTOCOLm_field32_set(unit, &vpe, SNAPf, 1);
   3259         }
   3260         if (frame & BCM_PORT_FRAMETYPE_LLC) {
   3261             soc_VLAN_PROTOCOLm_field32_set(unit, &vpe, LLCf, 1);
   3262         }
   3263         soc_VLAN_PROTOCOLm_field32_set(unit, &vpe, MATCHUPPERf, 1);
   3264         soc_VLAN_PROTOCOLm_field32_set(unit, &vpe, MATCHLOWERf, 1);
   3265         SOC_IF_ERROR_RETURN
   3266             (WRITE_VLAN_PROTOCOLm(unit, MEM_BLOCK_ALL, empty, &vpe));
   3267         vpentry = empty;
   3268     }
   3269 
   3270     /*
   3271      * Set VLAN ID for target port. For all other ethernet ports,
   3272      * make sure entries indexed by the matched entry in VLAN_PROTOCOL
   3273      * have initialized values (either default or explicit VID).
   3274      */
   3275     switched_pbm = PBMP_E_ALL(unit);
   3276     if (soc_feature(unit, soc_feature_cpuport_switched)) {
   3277         BCM_PBMP_OR(switched_pbm, PBMP_CMIC(unit));
   3278     }
   3279 
   3280     BCM_PBMP_ITER(switched_pbm, p) {
   3281         bcm_vlan_t  cvid, defvid, wvid;
   3282         vdentry = (p * vlan_prot_entries)
   3283             + vpentry;
   3284         SOC_IF_ERROR_RETURN
   3285             (READ_VLAN_PROTOCOL_DATAm(unit, MEM_BLOCK_ANY,
   3286                                       vdentry, &vde));
   3287         wvid = vid;
   3288         cvid = soc_VLAN_PROTOCOL_DATAm_field32_get(unit, &vde, VLAN_IDf);
   3289         BCM_IF_ERROR_RETURN
   3290             (bcm_esw_port_untagged_vlan_get(unit, p, &defvid));
   3291 
   3292         BCM_IF_ERROR_RETURN(_bcm_port_info_get(unit, p, &pinfo));
   3293         if (p == port) {
   3294             if (_BCM_PORT_VD_PBVL_IS_SET(pinfo, vpentry)) {
   3295                 /* Already explicit VID; must remove first. */
   3296                 return BCM_E_EXISTS;
   3297             }
   3298             /* Set as explicit VID */
   3299             _BCM_PORT_VD_PBVL_SET(pinfo, vpentry);
   3300             if (cvid == vid) {
   3301                 /* Current (default) VID same as explicit VID */
   3302                 continue;
   3303             }
   3304         } else {
   3305             /*
   3306              * For all other ports, if no non-zero VID already set,
   3307              * set to default VLAN ID.
   3308              */
   3309             if (cvid != 0) {
   3310                 continue;
   3311             }
   3312             wvid = defvid;
   3313             _BCM_PORT_VD_PBVL_CLEAR(pinfo, vpentry);
   3314         }
   3315 
   3316         sal_memset(&vde, 0, sizeof(vde));
   3317         soc_VLAN_PROTOCOL_DATAm_field32_set(unit, &vde, VLAN_IDf, wvid);
   3318         soc_VLAN_PROTOCOL_DATAm_field32_set(unit, &vde, PRIf, pinfo->p_ut_prio);
   3319         SOC_IF_ERROR_RETURN
   3320             (WRITE_VLAN_PROTOCOL_DATAm(unit, MEM_BLOCK_ALL,
   3321                                        vdentry, &vde));
   3322     }
   3323     return BCM_E_NONE;
   3324 }
   3325 
   3326 /*
   3327  * Function:
   3328  *      _bcm_fb_port_protocol_vlan_delete
   3329  * Purpose:
   3330  *      Remove an already created proto protocol based vlan
   3331  *      on a port.
   3332  * Parameters:
   3333  *      unit - (IN) BCM device number
   3334  *      port - (IN) Port number
   3335  *      frame - (IN) one of BCM_PORT_FRAMETYPE_{ETHER2,8023,LLC}
   3336  *      ether - (IN) 16 bit Ethernet type field
   3337  * Returns:
   3338  *      BCM_E_XXX
   3339  */
   3340 
   3341 int
   3342 _bcm_fb_port_protocol_vlan_delete(int unit,
   3343                               bcm_port_t port,
   3344                               bcm_port_frametype_t frame,
   3345                               bcm_port_ethertype_t ether)
   3346 {
   3347     bcm_port_frametype_t         ft;
   3348     bcm_port_ethertype_t         et;
   3349     vlan_protocol_entry_t        vpe;
   3350     vlan_protocol_data_entry_t   vde;
   3351     bcm_vlan_t                   cvid, defvid;
   3352     int                          idxmin, idxmax;
   3353     int                          vlan_prot_entries;
   3354     int                          vpentry, vdentry, p, valid;
   3355     bcm_pbmp_t                   switched_pbm;
   3356     _bcm_port_info_t             *pinfo;
   3357     int                          i;
   3358 
   3359     idxmin = soc_mem_index_min(unit, VLAN_PROTOCOLm);
   3360     idxmax = soc_mem_index_max(unit, VLAN_PROTOCOLm);
   3361     vlan_prot_entries = idxmax + 1;
   3362     vpentry = -1;
   3363     for (i = idxmin; i <= idxmax; i++) {
   3364         SOC_IF_ERROR_RETURN
   3365             (READ_VLAN_PROTOCOLm(unit, MEM_BLOCK_ANY, i, &vpe));
   3366         ft = 0;
   3367         if (soc_VLAN_PROTOCOLm_field32_get(unit, &vpe, ETHERIIf)) {
   3368             ft |= BCM_PORT_FRAMETYPE_ETHER2;
   3369         }
   3370         if (soc_VLAN_PROTOCOLm_field32_get(unit, &vpe, SNAPf)) {
   3371             ft |= BCM_PORT_FRAMETYPE_8023;
   3372         }
   3373         if (soc_VLAN_PROTOCOLm_field32_get(unit, &vpe, LLCf)) {
   3374             ft |= BCM_PORT_FRAMETYPE_LLC;
   3375         }
   3376         et = soc_VLAN_PROTOCOLm_field32_get(unit, &vpe, ETHERTYPEf);
   3377         if (ft == frame && et == ether) {
   3378             vpentry = i;
   3379             break;
   3380         }
   3381     }
   3382     if (vpentry < 0) {
   3383         return BCM_E_NOT_FOUND;
   3384     }
   3385     vdentry = (port * vlan_prot_entries) + vpentry;
   3386     SOC_IF_ERROR_RETURN
   3387         (READ_VLAN_PROTOCOL_DATAm(unit, MEM_BLOCK_ANY, vdentry, &vde));
   3388     cvid = soc_VLAN_PROTOCOL_DATAm_field32_get(unit, &vde, VLAN_IDf);
   3389     BCM_IF_ERROR_RETURN
   3390         (bcm_esw_port_untagged_vlan_get(unit, port, &defvid));
   3391     /*
   3392      * Entry is initialized (undefined) if VLAN ID is 0.
   3393      * Otherwise, entry is a default VID entry if not programmed.
   3394      * Since we are attempting to remove an "explicit" VID entry,
   3395      * the indexed VLAN_PROTOCOL_DATA entry must be defined and
   3396      * not merely a default VID entry.
   3397      */
   3398     BCM_IF_ERROR_RETURN(_bcm_port_info_get(unit, port, &pinfo));
   3399     if (cvid == 0 ||
   3400         (cvid == defvid && (!_BCM_PORT_VD_PBVL_IS_SET(pinfo, vpentry)))) {
   3401         return BCM_E_NOT_FOUND;
   3402     }
   3403     sal_memset(&vde, 0, sizeof(vde));
   3404     /* set to default VLAN ID and mark it as not programmed   */
   3405     soc_VLAN_PROTOCOL_DATAm_field32_set(unit, &vde, VLAN_IDf, defvid);
   3406     _BCM_PORT_VD_PBVL_CLEAR(pinfo, vpentry);
   3407     SOC_IF_ERROR_RETURN
   3408         (WRITE_VLAN_PROTOCOL_DATAm(unit, MEM_BLOCK_ALL, vdentry, &vde));
   3409     /*
   3410      * See if any other port has an explicit vlan_protocol_data
   3411      * entry for the indicated protocol.
   3412      */
   3413     valid = 0;
   3414     switched_pbm = PBMP_E_ALL(unit);
   3415     if (soc_feature(unit, soc_feature_cpuport_switched)) {
   3416         BCM_PBMP_OR(switched_pbm, PBMP_CMIC(unit));
   3417     }
   3418 
   3419     BCM_PBMP_ITER(switched_pbm, p) {
   3420         if (p == port) {    /* skip the entry we just "defaulted" */
   3421             continue;
   3422         }
   3423         BCM_IF_ERROR_RETURN(_bcm_port_info_get(unit, p, &pinfo));
   3424         /* Check for explicit VID entry */
   3425         if (_BCM_PORT_VD_PBVL_IS_SET(pinfo, vpentry)) {
   3426             valid = 1;
   3427             break;
   3428         }
   3429     }
   3430     if (!valid) {
   3431         /*
   3432          * Clear all ports' VLAN_PROTOCOL_DATA entries
   3433          * associated with this protocol.
   3434          */
   3435         BCM_PBMP_ITER(switched_pbm, p) {
   3436             vdentry = (p * vlan_prot_entries) + vpentry;
   3437             sal_memset(&vde, 0, sizeof(vde));
   3438             SOC_IF_ERROR_RETURN
   3439                 (WRITE_VLAN_PROTOCOL_DATAm(unit, MEM_BLOCK_ALL,
   3440                                            vdentry, &vde));
   3441             BCM_IF_ERROR_RETURN(_bcm_port_info_get(unit, p, &pinfo));
   3442             _BCM_PORT_VD_PBVL_CLEAR(pinfo, vpentry);
   3443         }
   3444         /* clear VLAN_PROTOCOL entry */
   3445         sal_memset(&vpe, 0, sizeof(vpe));
   3446         SOC_IF_ERROR_RETURN
   3447             (WRITE_VLAN_PROTOCOLm(unit, MEM_BLOCK_ALL, vpentry, &vpe));
   3448     }
   3449     return BCM_E_NONE;
   3450 }
   3451 
   3452 /*
   3453  * Function:
   3454  *      _bcm_fb_port_untagged_vlan_data_update
   3455  * Purpose:
   3456  *      Update VLAN_PROTOCOL_DATA with new default VLAN ID for port
   3457  * Parameters:
   3458  *      unit - StrataSwitch unit number.
   3459  *      port - StrataSwitch port number of port to get info for
   3460  *      pdvid- Previous default VLAN ID
   3461  *      ndvid- New default VLAN ID
   3462  * Returns:
   3463  *      BCM_XX_NONE
   3464  */
   3465 int
   3466 _bcm_fb_port_untagged_vlan_data_update(int unit, bcm_port_t port,
   3467                                        bcm_vlan_t pdvid, bcm_vlan_t ndvid)
   3468 {
   3469     vlan_protocol_data_entry_t   vde;
   3470     _bcm_port_info_t             *pinfo;
   3471     int                          idx;
   3472     int                          vlan_prot_entries, vlan_data_prot_start;
   3473 
   3474     vlan_prot_entries = soc_mem_index_count(unit, VLAN_PROTOCOLm);
   3475     vlan_data_prot_start = (port * vlan_prot_entries);
   3476     for (idx = 0; idx < vlan_prot_entries; idx++) {
   3477         SOC_IF_ERROR_RETURN
   3478             (READ_VLAN_PROTOCOL_DATAm(unit, MEM_BLOCK_ANY,
   3479                                       vlan_data_prot_start + idx, &vde));
   3480         /*
   3481          * Update entry with new default VLAN ID if not a programmed
   3482          * VLAN ID and entry has previous default VLAN ID
   3483          */
   3484         BCM_IF_ERROR_RETURN(_bcm_port_info_get(unit, port, &pinfo));
   3485         if ( (!(_BCM_PORT_VD_PBVL_IS_SET(pinfo, idx))) &&
   3486              (soc_VLAN_PROTOCOL_DATAm_field32_get(unit, &vde, VLAN_IDf)
   3487               == pdvid) ) {
   3488             soc_VLAN_PROTOCOL_DATAm_field32_set(unit, &vde, VLAN_IDf, ndvid);
   3489             SOC_IF_ERROR_RETURN
   3490                 (WRITE_VLAN_PROTOCOL_DATAm(unit, MEM_BLOCK_ALL,
   3491                                            vlan_data_prot_start + idx, &vde));
   3492         }
   3493     }
   3494     return BCM_E_NONE;
   3495 }
   3496 
   3497 /*
   3498  * Function:
   3499  *      _bcm_fb_port_tpid_get
   3500  * Description:
   3501  *      Get the default Tag Protocol ID for a port.
   3502  * Parameters:
   3503  *      unit - Device number
   3504  *      port - Port number
   3505  *      tpid - Tag Protocol ID
   3506  * Return Value:
   3507  *      BCM_E_XXX
   3508  */
   3509 int
   3510 _bcm_fb_port_tpid_get(int unit, bcm_port_t port, uint16 *tpid)
   3511 {
   3512     port_tab_entry_t  ptab;
   3513     int rv; 
   3514 
   3515     rv = soc_mem_read(unit, PORT_TABm, MEM_BLOCK_ANY, port, &ptab);
   3516     BCM_IF_ERROR_RETURN(rv);
   3517 
   3518     *tpid = soc_PORT_TABm_field32_get(unit, &ptab, OUTER_TPIDf);
   3519     return (BCM_E_NONE);
   3520 }
   3521 
   3522 /*
   3523  * Function:
   3524  *      _bcm_fb_port_tpid_set
   3525  * Description:
   3526  *      Set the default Tag Protocol ID for a port.
   3527  * Parameters:
   3528  *      unit - Device number
   3529  *      port - Port number
   3530  *      tpid - Tag Protocol ID
   3531  * Return Value:
   3532  *      BCM_E_XXX
   3533  */
   3534 
   3535 int
   3536 _bcm_fb_port_tpid_set(int unit, bcm_port_t port, uint16 tpid)
   3537 {
   3538     port_tab_entry_t  ptab;
   3539     int               rv;
   3540 
   3541     rv = soc_mem_read(unit, PORT_TABm, MEM_BLOCK_ANY, port, &ptab);
   3542     BCM_IF_ERROR_RETURN(rv);
   3543 
   3544     soc_PORT_TABm_field32_set(unit, &ptab, OUTER_TPIDf, tpid);
   3545     rv = soc_mem_write(unit, PORT_TABm, MEM_BLOCK_ALL, port, &ptab);
   3546     BCM_IF_ERROR_RETURN(rv);
   3547 
   3548 #ifdef BCM_TRIDENT2PLUS_SUPPORT
   3549     if (soc_feature(unit, soc_feature_egr_vlan_control_is_memory)) {
   3550         if (soc_feature(unit, soc_feature_egr_all_profile)) {
   3551             BCM_IF_ERROR_RETURN(bcm_esw_port_egr_lport_field_set(unit,
   3552                 port, EGR_VLAN_CONTROL_1m, OUTER_TPIDf, tpid));
   3553         } else {
   3554             SOC_IF_ERROR_RETURN(soc_mem_field32_modify(unit,
   3555                 EGR_VLAN_CONTROL_1m, port, OUTER_TPIDf, tpid));
   3556         }
   3557     } else
   3558 #endif
   3559     {
   3560         rv = soc_reg_field32_modify(unit, EGR_VLAN_CONTROL_1r, port, 
   3561                                     OUTER_TPIDf, tpid);
   3562     }
   3563     return rv;
   3564 }
   3565 
   3566 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT) || \
   3567         defined(BCM_RAVEN_SUPPORT)
   3568 int
   3569 _bcm_fb2_port_tpid_enable_get(int unit, bcm_port_t port, uint32 *tpid_enable)
   3570 {
   3571 #ifdef BCM_TRIDENT2PLUS_SUPPORT
   3572     if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) &&
   3573         _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port)) {
   3574         int modid = _BCM_SUBPORT_COE_PORT_ID_MOD_GET(port);
   3575         int mod_port = _BCM_SUBPORT_COE_PORT_ID_PORT_GET(port);
   3576         BCM_IF_ERROR_RETURN(
   3577             _bcm_td_mod_port_tpid_enable_read(
   3578             unit, modid, mod_port, (int*)tpid_enable));
   3579     } else
   3580 #endif
   3581 #if defined(BCM_TRX_SUPPORT)
   3582     if (SOC_MEM_FIELD_VALID(unit, SOURCE_TRUNK_MAP_TABLEm, OUTER_TPID_ENABLEf)) {
   3583         BCM_IF_ERROR_RETURN(
   3584             _bcm_trx_source_trunk_map_get(unit, port, OUTER_TPID_ENABLEf,
   3585                                           tpid_enable));
   3586     } else
   3587 #endif
   3588     {
   3589         port_tab_entry_t ptab;
   3590         SOC_IF_ERROR_RETURN(
   3591             soc_mem_read(unit, PORT_TABm, MEM_BLOCK_ANY, port, &ptab));
   3592         *tpid_enable = soc_mem_field32_get(unit, PORT_TABm,
   3593                                            &ptab, OUTER_TPID_ENABLEf);
   3594     }
   3595 
   3596     return BCM_E_NONE;
   3597 }
   3598 
   3599 int
   3600 _bcm_fb2_port_tpid_enable_set(int unit, bcm_port_t port, uint32 tpid_enable)
   3601 {
   3602 #ifdef BCM_TRIDENT2PLUS_SUPPORT
   3603     if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) &&
   3604         _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port)) {
   3605         int modid = _BCM_SUBPORT_COE_PORT_ID_MOD_GET(port);
   3606         int mod_port = _BCM_SUBPORT_COE_PORT_ID_PORT_GET(port);
   3607         BCM_IF_ERROR_RETURN(
   3608             _bcm_td_mod_port_tpid_enable_write(
   3609             unit, modid, mod_port, tpid_enable));
   3610     } else
   3611 #endif
   3612 #ifdef BCM_TRX_SUPPORT
   3613     if (SOC_MEM_FIELD_VALID(unit, SOURCE_TRUNK_MAP_TABLEm, OUTER_TPID_ENABLEf)) {
   3614         BCM_IF_ERROR_RETURN(
   3615             _bcm_trx_source_trunk_map_set(unit, port, OUTER_TPID_ENABLEf, 
   3616                                           tpid_enable));
   3617     } else
   3618 #endif
   3619     {
   3620         port_tab_entry_t ptab;
   3621         SOC_IF_ERROR_RETURN(
   3622             soc_mem_read(unit, PORT_TABm, MEM_BLOCK_ANY, port, &ptab));
   3623         soc_PORT_TABm_field32_set(unit, &ptab, OUTER_TPID_ENABLEf, tpid_enable);
   3624         SOC_IF_ERROR_RETURN(
   3625             soc_mem_write(unit, PORT_TABm, MEM_BLOCK_ALL, port, &ptab));
   3626     }
   3627 
   3628     return BCM_E_NONE;
   3629 }
   3630 
   3631 int
   3632 _bcm_fb2_egr_vlan_control_field_get(int unit, bcm_port_t port, soc_field_t field, uint32 *value)
   3633 {
   3634 #ifdef BCM_TRIDENT2PLUS_SUPPORT
   3635     if (soc_feature(unit, soc_feature_egr_vlan_control_is_memory)) {
   3636         if (soc_feature(unit, soc_feature_egr_all_profile) ||
   3637             (soc_feature(unit, soc_feature_hgproxy_subtag_coe) &&
   3638             _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port))) {
   3639             BCM_IF_ERROR_RETURN(
   3640                 bcm_esw_port_egr_lport_field_get(
   3641                 unit, port, EGR_VLAN_CONTROL_1m,
   3642                 field, value));
   3643         } else {
   3644             egr_vlan_control_1_entry_t entry;
   3645             SOC_IF_ERROR_RETURN(
   3646                 READ_EGR_VLAN_CONTROL_1m(unit, MEM_BLOCK_ANY, port, &entry));
   3647             *value = soc_EGR_VLAN_CONTROL_1m_field32_get(unit, &entry, field);
   3648         }
   3649     } else
   3650 #endif
   3651     {
   3652         uint32 vctrl = 0;
   3653         SOC_IF_ERROR_RETURN(READ_EGR_VLAN_CONTROL_1r(unit, port, &vctrl));
   3654         *value = soc_reg_field_get(unit, EGR_VLAN_CONTROL_1r, vctrl, field);
   3655     }
   3656 
   3657     return BCM_E_NONE;
   3658 }
   3659 
   3660 int
   3661 _bcm_fb2_egr_vlan_control_field_set(int unit, bcm_port_t port, soc_field_t field, uint32 value)
   3662 {
   3663 #ifdef BCM_TRIDENT2PLUS_SUPPORT
   3664     if (soc_feature(unit, soc_feature_egr_vlan_control_is_memory)) {
   3665         if (soc_feature(unit, soc_feature_egr_all_profile) ||
   3666             (soc_feature(unit, soc_feature_hgproxy_subtag_coe) &&
   3667             _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port))) {
   3668             BCM_IF_ERROR_RETURN(
   3669                 bcm_esw_port_egr_lport_field_set(
   3670                 unit, port, EGR_VLAN_CONTROL_1m,
   3671                 field, value));
   3672         } else {
   3673             egr_vlan_control_1_entry_t entry;
   3674             SOC_IF_ERROR_RETURN(
   3675                 READ_EGR_VLAN_CONTROL_1m(unit, MEM_BLOCK_ANY, port, &entry));
   3676             soc_EGR_VLAN_CONTROL_1m_field32_set(unit, &entry, field, value);
   3677             SOC_IF_ERROR_RETURN(
   3678                 WRITE_EGR_VLAN_CONTROL_1m(unit, MEM_BLOCK_ANY, port, &entry));
   3679         }
   3680     } else
   3681 #endif
   3682     {
   3683         uint32 vctrl = 0;
   3684         SOC_IF_ERROR_RETURN(READ_EGR_VLAN_CONTROL_1r(unit, port, &vctrl));
   3685         soc_reg_field_set(unit, EGR_VLAN_CONTROL_1r, &vctrl, field, value);
   3686         SOC_IF_ERROR_RETURN(WRITE_EGR_VLAN_CONTROL_1r(unit, port, vctrl));
   3687     }
   3688 
   3689     return BCM_E_NONE;
   3690 }
   3691 
   3692 /*
   3693  * Function:
   3694  *      _bcm_fb2_port_tpid_get
   3695  * Description:
   3696  *      Get the default Tag Protocol ID for a port.
   3697  * Parameters:
   3698  *      unit - Device number
   3699  *      port - Port number
   3700  *      tpid - Tag Protocol ID
   3701  * Return Value:
   3702  *      BCM_E_XXX
   3703  */
   3704 int
   3705 _bcm_fb2_port_tpid_get(int unit, bcm_port_t port, uint16 *tpid)
   3706 {
   3707     int index = 0;
   3708     BCM_IF_ERROR_RETURN(
   3709         _bcm_fb2_egr_vlan_control_field_get(
   3710         unit, port, OUTER_TPID_INDEXf, (uint32*)&index));
   3711 
   3712     _bcm_fb2_outer_tpid_entry_get(unit, tpid, index);
   3713     return (BCM_E_NONE);
   3714 }
   3715 
   3716 #ifdef BCM_TRIUMPH2_SUPPORT
   3717 /*
   3718  * Function:
   3719  *      _bcm_fb2_mod_port_tpid_enable_write
   3720  * Description:
   3721  *      Write the Tag Protocol ID enables for a (module, port).
   3722  * Parameters:
   3723  *      unit - Device number
   3724  *      mod  - Module ID
   3725  *      port - Port number
   3726  *      tpid_enable - Tag Protocol ID enables
   3727  * Return Value:
   3728  *      BCM_E_XXX
   3729  */
   3730 STATIC int
   3731 _bcm_fb2_mod_port_tpid_enable_write(int unit, bcm_module_t mod,
   3732         bcm_port_t port, int tpid_enable)
   3733 {
   3734 #ifdef BCM_HURRICANE3_SUPPORT
   3735     if (SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) {
   3736         return _bcm_hr3_mod_port_tpid_enable_write(unit, mod, port,
   3737                 tpid_enable);
   3738     } else 
   3739 #endif /* BCM_HURRICANE3_SUPPORT */
   3740 #ifdef BCM_TRIDENT_SUPPORT
   3741     {
   3742         return _bcm_td_mod_port_tpid_enable_write(unit, mod, port,
   3743                 tpid_enable);
   3744     }
   3745 #endif /* BCM_TRIDENT_SUPPORT */
   3746     return BCM_E_UNAVAIL;
   3747 }
   3748 #endif /* BCM_TRIUMPH2_SUPPORT */
   3749 
   3750 /*
   3751  * Function:
   3752  *      _bcm_fb2_port_tpid_set
   3753  * Description:
   3754  *      Set the default Tag Protocol ID for a port.
   3755  * Parameters:
   3756  *      unit - Device number
   3757  *      port - Port number
   3758  *      tpid - Tag Protocol ID
   3759  * Return Value:
   3760  *      BCM_E_XXX
   3761  */
   3762 int
   3763 _bcm_fb2_port_tpid_set(int unit, bcm_port_t port, uint16 tpid, int *index)
   3764 {
   3765     int               old_tpid_index;
   3766     uint32            tpid_enable;
   3767     int               tpid_index;
   3768     uint16            old_tpid;
   3769     int               rv = BCM_E_NONE;
   3770 #ifdef BCM_TRIUMPH2_SUPPORT
   3771     bcm_module_t      modid = 0;
   3772     bcm_port_t        mod_port = port;
   3773 #endif
   3774 
   3775     _bcm_fb2_outer_tpid_tab_lock(unit);
   3776 
   3777 #ifdef BCM_TRIUMPH2_SUPPORT
   3778     rv = bcm_esw_stk_my_modid_get(unit, &modid);
   3779     if (BCM_FAILURE(rv)) {
   3780         _bcm_fb2_outer_tpid_tab_unlock(unit);
   3781         return (rv);
   3782     }
   3783 #endif
   3784 
   3785 #ifdef BCM_TRIDENT2PLUS_SUPPORT
   3786     if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) &&
   3787         _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port)) {
   3788         modid = _BCM_SUBPORT_COE_PORT_ID_MOD_GET(port);
   3789         mod_port = _BCM_SUBPORT_COE_PORT_ID_PORT_GET(port);
   3790     }
   3791 #endif
   3792 
   3793     /* Delete the TPID referenced by EGR_VLAN_CONTROL_1r */
   3794     rv = _bcm_fb2_egr_vlan_control_field_get(
   3795         unit, port, OUTER_TPID_INDEXf, (uint32*)&old_tpid_index);
   3796     if (BCM_FAILURE(rv)) {
   3797         _bcm_fb2_outer_tpid_tab_unlock(unit);
   3798         return (rv);
   3799     }
   3800 
   3801     rv = _bcm_fb2_outer_tpid_entry_get(unit, &old_tpid, old_tpid_index);
   3802     if (BCM_FAILURE(rv)) {
   3803         _bcm_fb2_outer_tpid_tab_unlock(unit);
   3804         return (rv);
   3805     }
   3806 
   3807     /* Add TPID reference for EGR_VLAN_CONTROL_1r. */
   3808     rv = _bcm_fb2_outer_tpid_entry_add(unit, tpid, &tpid_index);
   3809     if (BCM_FAILURE(rv)) {
   3810         _bcm_fb2_outer_tpid_tab_unlock(unit);
   3811         return (rv);
   3812     }
   3813 
   3814     /* Delete the TPID referenced by PORT and EGR_SRC_PORT
   3815      * tables. We keep only one reference for both table because
   3816      * the outer TPID enabled will be the same.
   3817      */
   3818 
   3819     rv = _bcm_fb2_port_tpid_enable_get(unit, port, &tpid_enable);
   3820     if (BCM_FAILURE(rv)) {
   3821         _bcm_fb2_outer_tpid_tab_unlock(unit);
   3822         return (rv);
   3823     }
   3824 
   3825     tpid_index = 0;
   3826     while (tpid_enable) {
   3827         if (tpid_enable & 1) {
   3828             rv = _bcm_fb2_outer_tpid_entry_delete(unit, tpid_index);
   3829             if (BCM_FAILURE(rv)) {
   3830                 _bcm_fb2_outer_tpid_tab_unlock(unit);
   3831                 return (rv);
   3832             }
   3833         }
   3834         tpid_enable = tpid_enable >> 1;
   3835         tpid_index++;
   3836     }
   3837 
   3838     /* Add TPID reference for EGR_SRC_PORT and PORT tables. 
   3839      * The first insertion and second insertion will return
   3840      * the same status because we are adding the same TPID value.
   3841      */
   3842     rv = _bcm_fb2_outer_tpid_entry_add(unit, tpid, &tpid_index);
   3843     if (BCM_FAILURE(rv)) {
   3844         _bcm_fb2_outer_tpid_entry_delete(unit, tpid_index);
   3845         _bcm_fb2_outer_tpid_tab_unlock(unit);
   3846         return (rv);
   3847     }
   3848 
   3849     /* Delete reference to old tpid entry after adding the new one */
   3850     rv = _bcm_fb2_outer_tpid_entry_delete(unit, old_tpid_index);
   3851     if (BCM_FAILURE(rv)) {
   3852         _bcm_fb2_outer_tpid_tab_unlock(unit);
   3853         return (rv);
   3854     }
   3855 
   3856     rv = _bcm_fb2_egr_vlan_control_field_set(
   3857         unit, port, OUTER_TPID_INDEXf, tpid_index);
   3858     if (BCM_FAILURE(rv)) {
   3859         _bcm_fb2_outer_tpid_entry_delete(unit, tpid_index);
   3860         _bcm_fb2_outer_tpid_entry_delete(unit, tpid_index);
   3861         _bcm_fb2_outer_tpid_tab_unlock(unit);
   3862         return (rv);
   3863     }
   3864 
   3865     tpid_enable = 1 << tpid_index;
   3866     rv = _bcm_fb2_port_tpid_enable_set(unit, port, tpid_enable);
   3867     if (BCM_FAILURE(rv)) {
   3868         _bcm_fb2_outer_tpid_entry_delete(unit, tpid_index);
   3869         _bcm_fb2_outer_tpid_entry_delete(unit, tpid_index);
   3870         _bcm_fb2_outer_tpid_tab_unlock(unit);
   3871         return (rv);
   3872     }
   3873     *index = tpid_index;
   3874 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   3875     if (soc_feature(unit, soc_feature_td2p_style_egr_outer_tpid)) {
   3876         if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) &&
   3877             _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port)) {
   3878             rv = bcm_esw_port_egr_lport_field_set(
   3879                 unit, port, EGR_PORT_1m,
   3880                 OUTER_TPID_ENABLEf, tpid_enable);
   3881         } else {
   3882             rv = soc_mem_field32_modify(unit, EGR_PORT_1m, port,
   3883                                         OUTER_TPID_ENABLEf, tpid_enable);
   3884         }
   3885     } else
   3886 #endif
   3887 #if defined(BCM_TRIUMPH2_SUPPORT) || defined(BCM_ENDURO_SUPPORT)
   3888     if (SOC_REG_FIELD_VALID(unit, EGR_PORT_1r, OUTER_TPID_ENABLEf)) {
   3889         rv = soc_reg_field32_modify(unit, EGR_PORT_1r, port,
   3890                                     OUTER_TPID_ENABLEf, tpid_enable);
   3891     } else
   3892 #endif 
   3893     if (SOC_REG_IS_VALID(unit, EGR_SRC_PORTr)) {
   3894         rv = soc_reg_field32_modify(unit, EGR_SRC_PORTr, port, 
   3895                                     OUTER_TPID_ENABLEf, tpid_enable);
   3896     } 
   3897 
   3898 #if defined(BCM_TRIUMPH2_SUPPORT)
   3899     /* For Triumph2 and Apollo, also need to program the SYSTEM_CONFIG_TABLE
   3900      * for second-pass packets. These are treated as Higig-lookup packets */
   3901     if (BCM_SUCCESS(rv) && !SOC_IS_TRIDENT3X(unit) &&
   3902         (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) ||
   3903         SOC_IS_VALKYRIE2(unit) || SOC_IS_ENDURO(unit) || 
   3904         SOC_IS_HURRICANEX(unit) || SOC_IS_TD_TT(unit) || 
   3905         SOC_IS_GREYHOUND(unit)|| SOC_IS_GREYHOUND2(unit))) {
   3906         if (soc_mem_is_valid(unit, SYSTEM_CONFIG_TABLE_MODBASEm)) {
   3907             rv = _bcm_fb2_mod_port_tpid_enable_write(unit, modid, mod_port,
   3908                     tpid_enable);
   3909         } else if (soc_mem_is_valid(unit, SYSTEM_CONFIG_TABLEm)) {
   3910             int sys_index = 0;
   3911             system_config_table_entry_t systab;
   3912 
   3913             sys_index = modid * 64 + mod_port;
   3914             rv = READ_SYSTEM_CONFIG_TABLEm(unit, MEM_BLOCK_ANY, sys_index,
   3915                     &systab);
   3916             if (BCM_SUCCESS(rv)) {
   3917                 soc_SYSTEM_CONFIG_TABLEm_field32_set(unit, &systab,
   3918                         OUTER_TPID_ENABLEf, tpid_enable);
   3919                 rv = WRITE_SYSTEM_CONFIG_TABLEm(unit, MEM_BLOCK_ALL,
   3920                         sys_index, &systab);
   3921             }
   3922         }
   3923     }
   3924 #endif /* BCM_TRIUMPH2_SUPPORT */
   3925 
   3926 #if defined(BCM_TRX_SUPPORT)
   3927     if (BCM_SUCCESS(rv) &&
   3928         soc_mem_field_valid(unit, SOURCE_TRUNK_MAP_TABLEm, OUTER_TPID_ENABLEf)) {
   3929         rv = _bcm_trx_source_trunk_map_set(unit, port, OUTER_TPID_ENABLEf,
   3930                                            tpid_enable);
   3931     }
   3932 #endif
   3933 
   3934     if (BCM_FAILURE(rv)) {
   3935         _bcm_fb2_outer_tpid_entry_delete(unit, tpid_index);
   3936         _bcm_fb2_outer_tpid_entry_delete(unit, tpid_index);
   3937         _bcm_fb2_outer_tpid_tab_unlock(unit);
   3938         return (rv);
   3939     }
   3940 
   3941 #if defined(BCM_HGPROXY_COE_SUPPORT)
   3942     if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) &&
   3943         BCM_GPORT_IS_SET(port) &&
   3944         _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port)) {
   3945         if(!_bcm_xgs5_subport_coe_gport_local(unit, port)) {
   3946             rv =  BCM_E_PORT;
   3947         } else {
   3948             rv = _bcmi_coe_subport_physical_port_get(unit, port, &port);
   3949         }
   3950         if (BCM_FAILURE(rv)) {
   3951             _bcm_fb2_outer_tpid_tab_unlock(unit);
   3952             return (rv);
   3953         }
   3954     }
   3955 #endif
   3956 
   3957     /* Set TPID to be used for untagged packets */
   3958     if (SOC_REG_IS_VALID(unit, EGR_INGRESS_PORT_TPID_SELECTr)) {
   3959         rv = WRITE_EGR_INGRESS_PORT_TPID_SELECTr(unit, port, tpid_index);
   3960     }
   3961     _bcm_fb2_outer_tpid_tab_unlock(unit);
   3962     return (rv);
   3963 }
   3964 
   3965 /*
   3966  * Function:
   3967  *      bcm_fb2_port_tpid_add
   3968  * Description:
   3969  *      Add allowed TPID for a port.
   3970  * Parameters:
   3971  *      unit         - (IN) Device number
   3972  *      port         - (IN) Port number
   3973  *      tpid         - (IN) Tag Protocol ID
   3974  *      color_select - (IN) Color mode for TPID
   3975  * Return Value:
   3976  *      BCM_E_XXX
   3977  */
   3978 int
   3979 _bcm_fb2_port_tpid_add(int unit, bcm_port_t port, 
   3980                       uint16 tpid, int color_select)
   3981 {
   3982     int      rv;
   3983     int      index;
   3984     uint32   tpid_enable;
   3985     uint32   cfi_cng;
   3986     uint32   tpid_mask;
   3987     uint8    remove_tpid;
   3988     port_tab_entry_t  ptab;
   3989     int      is_subport = 0;
   3990 #ifdef BCM_TRIUMPH2_SUPPORT
   3991     bcm_module_t    modid = 0;
   3992     bcm_port_t      mod_port = port;
   3993 #endif
   3994 
   3995 #if defined(BCM_TRX_SUPPORT)
   3996     /*
   3997      * TRX devices only support OUTER_CFI to be mapped to CNG
   3998      */
   3999     if (color_select == BCM_COLOR_INNER_CFI && SOC_IS_TRX(unit)) {
   4000         return BCM_E_UNAVAIL;
   4001     }
   4002 #endif
   4003 
   4004     remove_tpid = FALSE;
   4005     _bcm_fb2_outer_tpid_tab_lock(unit);
   4006 
   4007 #ifdef BCM_TRIUMPH2_SUPPORT
   4008     rv = bcm_esw_stk_my_modid_get(unit, &modid);
   4009     if (BCM_FAILURE(rv)) {
   4010         _bcm_fb2_outer_tpid_tab_unlock(unit);
   4011         return (rv);
   4012     }
   4013 #endif
   4014 
   4015 #ifdef BCM_TRIDENT2PLUS_SUPPORT
   4016     if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) &&
   4017         _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port)) {
   4018         is_subport = TRUE;
   4019         modid = _BCM_SUBPORT_COE_PORT_ID_MOD_GET(port);
   4020         mod_port = _BCM_SUBPORT_COE_PORT_ID_PORT_GET(port);
   4021     }
   4022 #endif
   4023 
   4024     rv = _bcm_fb2_port_tpid_enable_get(unit, port, &tpid_enable);
   4025     if (BCM_FAILURE(rv)) {
   4026         _bcm_fb2_outer_tpid_tab_unlock(unit);
   4027         return (rv);
   4028     }
   4029 
   4030     /* Add new TPID to cached table */
   4031     rv = _bcm_fb2_outer_tpid_lkup(unit, tpid, &index);
   4032 
   4033     /* If the new TPID is not allowed on the requested port,
   4034      * add the port.
   4035      */
   4036     if (rv == BCM_E_NOT_FOUND || !(tpid_enable & (1 << index))) {
   4037         rv = _bcm_fb2_outer_tpid_entry_add(unit, tpid, &index);
   4038         if (BCM_FAILURE(rv)) {
   4039             _bcm_fb2_outer_tpid_tab_unlock(unit);
   4040             return (rv);
   4041         }
   4042         remove_tpid = TRUE; 
   4043     }
   4044 
   4045     /* Update registers */
   4046 
   4047     tpid_mask = 1 << index;
   4048 
   4049     /* Updat allowed TPID per port */
   4050     tpid_enable |= tpid_mask;
   4051 
   4052     /* Update color selection per TPID per port */
   4053     rv = _bcm_fb2_egr_vlan_control_field_get(unit, port, CFI_AS_CNGf, &cfi_cng);
   4054     if (BCM_FAILURE(rv)) {
   4055         if (remove_tpid) {
   4056             _bcm_fb2_outer_tpid_entry_delete(unit, index);
   4057         }
   4058         _bcm_fb2_outer_tpid_tab_unlock(unit);
   4059         return (rv);
   4060     }
   4061 
   4062     switch (color_select) {
   4063       case BCM_COLOR_PRIORITY:
   4064           cfi_cng &= ~tpid_mask;
   4065           break;
   4066       case BCM_COLOR_INNER_CFI:
   4067           cfi_cng = 0x1;
   4068           break;
   4069       case BCM_COLOR_OUTER_CFI:
   4070           cfi_cng |= tpid_mask;
   4071           break;
   4072       default:
   4073           /* Already checked color_select param */
   4074           /* Should never get here              */ 
   4075           break;
   4076     }
   4077 
   4078     /* Update Registers */
   4079 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   4080     if (soc_feature(unit, soc_feature_td2p_style_egr_outer_tpid)) {
   4081         if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) &&
   4082             _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port)) {
   4083             rv = bcm_esw_port_egr_lport_field_set(
   4084                 unit, port, EGR_PORT_1m,
   4085                 OUTER_TPID_ENABLEf, tpid_enable);
   4086         } else {
   4087             rv = soc_mem_field32_modify(unit, EGR_PORT_1m, port,
   4088                                         OUTER_TPID_ENABLEf, tpid_enable);
   4089         }
   4090     } else 
   4091 #endif
   4092 #if defined(BCM_TRIUMPH2_SUPPORT) || defined(BCM_ENDURO_SUPPORT)
   4093     if (SOC_REG_FIELD_VALID(unit, EGR_PORT_1r, OUTER_TPID_ENABLEf)) {
   4094         rv = soc_reg_field32_modify(unit, EGR_PORT_1r, port,
   4095                                     OUTER_TPID_ENABLEf, tpid_enable);
   4096     } else
   4097 #endif 
   4098     if (SOC_REG_IS_VALID(unit, EGR_SRC_PORTr)) {
   4099         rv = soc_reg_field32_modify(unit, EGR_SRC_PORTr, port, 
   4100                                     OUTER_TPID_ENABLEf, tpid_enable);
   4101     } 
   4102     if (BCM_FAILURE(rv)) {
   4103         if (remove_tpid) {
   4104             _bcm_fb2_outer_tpid_entry_delete(unit, index);
   4105         }
   4106         _bcm_fb2_outer_tpid_tab_unlock(unit);
   4107         return (rv);
   4108     }
   4109 #if defined(BCM_TRIUMPH2_SUPPORT)
   4110     /* For Triumph2 and Apollo, also need to program the SYSTEM_CONFIG_TABLE
   4111      * for second-pass packets. These are treated as Higig-lookup packets */
   4112     if (!SOC_IS_TRIDENT3X(unit) &&
   4113         (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) ||
   4114         SOC_IS_VALKYRIE2(unit) || SOC_IS_ENDURO(unit) ||
   4115         SOC_IS_HURRICANEX(unit) || SOC_IS_TD_TT(unit) || 
   4116         SOC_IS_GREYHOUND(unit) || SOC_IS_GREYHOUND2(unit))) {
   4117         if (soc_mem_is_valid(unit, SYSTEM_CONFIG_TABLE_MODBASEm)) {
   4118             rv = _bcm_fb2_mod_port_tpid_enable_write(unit, modid, mod_port,
   4119                     tpid_enable);
   4120         } else if (soc_mem_is_valid(unit, SYSTEM_CONFIG_TABLEm)) {
   4121             int sys_index = 0;
   4122             system_config_table_entry_t systab;
   4123 
   4124             sys_index = modid * 64 + mod_port;
   4125             rv = READ_SYSTEM_CONFIG_TABLEm(unit, MEM_BLOCK_ANY, sys_index,
   4126                     &systab);
   4127             if (BCM_SUCCESS(rv)) {
   4128                 soc_SYSTEM_CONFIG_TABLEm_field32_set(unit, &systab,
   4129                         OUTER_TPID_ENABLEf, tpid_enable);
   4130                 rv = WRITE_SYSTEM_CONFIG_TABLEm(unit, MEM_BLOCK_ALL,
   4131                         sys_index, &systab);
   4132             }
   4133         }
   4134     }
   4135 #endif
   4136 
   4137 #if defined(BCM_TRX_SUPPORT)
   4138     if (BCM_SUCCESS(rv) &&
   4139         soc_mem_field_valid(unit, SOURCE_TRUNK_MAP_TABLEm, OUTER_TPID_ENABLEf)) {
   4140         rv = _bcm_trx_source_trunk_map_set(unit, port, OUTER_TPID_ENABLEf,
   4141                                            tpid_enable);
   4142     }
   4143 #endif
   4144 
   4145     if (BCM_FAILURE(rv)) {
   4146         if (remove_tpid) {
   4147             _bcm_fb2_outer_tpid_entry_delete(unit, index);
   4148         }
   4149         _bcm_fb2_outer_tpid_tab_unlock(unit);
   4150         return (rv);
   4151     }
   4152 
   4153     rv = _bcm_fb2_port_tpid_enable_set(unit, port, tpid_enable);
   4154     if (BCM_FAILURE(rv)) {
   4155         if (remove_tpid) {
   4156             _bcm_fb2_outer_tpid_entry_delete(unit, index);
   4157         }
   4158         _bcm_fb2_outer_tpid_tab_unlock(unit);
   4159         return (rv);
   4160     }
   4161 
   4162     rv = _bcm_fb2_egr_vlan_control_field_set(unit, port, CFI_AS_CNGf, cfi_cng);
   4163     if (BCM_FAILURE(rv)) {
   4164         if (remove_tpid) {
   4165             _bcm_fb2_outer_tpid_entry_delete(unit, index);
   4166         }
   4167         _bcm_fb2_outer_tpid_tab_unlock(unit);
   4168         return (rv);
   4169     }
   4170 
   4171     if (!is_subport) {
   4172         if (!(SOC_IS_TRIDENT3X(unit))) {
   4173         rv = soc_mem_read(unit, PORT_TABm, MEM_BLOCK_ANY, port, &ptab);
   4174             if (BCM_SUCCESS(rv)) {
   4175         soc_PORT_TABm_field32_set(unit, &ptab, CFI_AS_CNGf, cfi_cng);
   4176         rv = WRITE_PORT_TABm(unit, MEM_BLOCK_ALL, port, &ptab);
   4177             }
   4178         }
   4179         if (BCM_FAILURE(rv)) {
   4180             if (remove_tpid) {
   4181                 _bcm_fb2_outer_tpid_entry_delete(unit, index);
   4182             }
   4183         }
   4184     }
   4185 
   4186     _bcm_fb2_outer_tpid_tab_unlock(unit);
   4187     
   4188     return rv;
   4189 }
   4190 
   4191 /*
   4192  * Function:
   4193  *      _bcm_fb2_port_tpid_get_all
   4194  * Description:
   4195  *      Retrieve a list of TPIDs available for the port.
   4196  * Parameters:
   4197  *      unit         - (IN) Device number
   4198  *      port         - (IN) Port number
   4199  *      size         - (IN) size of the buffer arrays
   4200  *      tpid_array   - (OUT) tpid buffer array
   4201  *      color_array  - (OUT) color buffer array
   4202  *      count        - (OUT) actual number of tpids/colors retrieved
   4203  * Return Value:
   4204  *      BCM_E_XXX
   4205  */
   4206 int
   4207 _bcm_fb2_port_tpid_get_all(int unit, bcm_port_t port,
   4208                            int size, uint16 *tpid_array, 
   4209                            int *color_array, int *count)
   4210 {
   4211     int      rv;
   4212     int      index;
   4213     uint32   tpid_enable;  
   4214     uint32   cfi_cng;
   4215     int cnt;
   4216     uint32 tpid = 0;
   4217     int num_entries;
   4218 
   4219     cnt = 0;
   4220     rv = _bcm_fb2_port_tpid_enable_get(unit, port, &tpid_enable);
   4221     if (BCM_FAILURE(rv)) {
   4222         return (rv);
   4223     }
   4224 
   4225     /* max tpid entries limited by width of this field */
   4226     if (SOC_MEM_FIELD_VALID(unit, SOURCE_TRUNK_MAP_TABLEm, OUTER_TPID_ENABLEf)) {
   4227         num_entries = soc_mem_field_length(unit, SOURCE_TRUNK_MAP_TABLEm, 
   4228                                            OUTER_TPID_ENABLEf);
   4229     } else {
   4230     num_entries = soc_mem_field_length(unit,PORT_TABm,OUTER_TPID_ENABLEf);
   4231     }
   4232 
   4233     if (size == 0) {
   4234         for (index = 0; index < num_entries; index++) {
   4235             if (tpid_enable & (1 << index)) {
   4236                 cnt++;
   4237             }
   4238         }
   4239         *count = cnt;
   4240         return BCM_E_NONE;
   4241     }
   4242 
   4243     rv = _bcm_fb2_egr_vlan_control_field_get(unit, port, CFI_AS_CNGf, &cfi_cng);
   4244     if (BCM_FAILURE(rv)) {
   4245         return (rv);
   4246     }
   4247 
   4248     for (index = 0; index < num_entries; index++) {
   4249         if (cnt < size) {
   4250             if (tpid_enable & (1 << index)) {
   4251                 rv = READ_EGR_OUTER_TPIDr(unit, index, &tpid);
   4252                 if (BCM_FAILURE(rv)) {
   4253                     return (rv);
   4254                 }
   4255                 tpid_array[cnt] = (uint16)tpid;
   4256                 if (cfi_cng & (1 << index)) {
   4257                     color_array[cnt] = BCM_COLOR_OUTER_CFI;
   4258                 } else {
   4259                     color_array[cnt] = BCM_COLOR_PRIORITY;
   4260                 }
   4261                 cnt++;
   4262             }
   4263         }
   4264     }
   4265     *count = cnt;
   4266 
   4267     return rv;
   4268 }
   4269 
   4270 /*
   4271  * Function:
   4272  *      bcm_fb2_port_tpid_delete
   4273  * Description:
   4274  *      Delete allowed TPID for a port.
   4275  * Parameters:
   4276  *      unit - (IN) Device number
   4277  *      port - (IN) Port number
   4278  *      tpid - (IN) Tag Protocol ID
   4279  * Return Value:
   4280  *      BCM_E_XXX
   4281  */
   4282 int
   4283 _bcm_fb2_port_tpid_delete(int unit, bcm_port_t port, uint16 tpid)
   4284 {
   4285     int               rv;
   4286     int               index;
   4287     uint32            tpid_enable = 0;
   4288     uint16            default_tpid;
   4289     int               default_tpid_index;
   4290     _bcm_port_info_t  *pinfo;
   4291 #ifdef BCM_TRIUMPH2_SUPPORT
   4292     bcm_module_t      modid = 0;
   4293     bcm_port_t        mod_port = port;
   4294 #endif
   4295 
   4296     _bcm_fb2_outer_tpid_tab_lock(unit);
   4297 
   4298     rv = _bcm_fb2_outer_tpid_lkup(unit, tpid, &index);
   4299     if (BCM_FAILURE(rv)) {
   4300         _bcm_fb2_outer_tpid_tab_unlock(unit);
   4301         return (rv);
   4302     } 
   4303 
   4304 #ifdef BCM_TRIUMPH2_SUPPORT
   4305     rv = bcm_esw_stk_my_modid_get(unit, &modid);
   4306     if (BCM_FAILURE(rv)) {
   4307         _bcm_fb2_outer_tpid_tab_unlock(unit);
   4308         return (rv);
   4309     }
   4310 #endif
   4311 
   4312 #ifdef BCM_TRIDENT2PLUS_SUPPORT
   4313     if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) &&
   4314         _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port)) {
   4315         modid = _BCM_SUBPORT_COE_PORT_ID_MOD_GET(port);
   4316         mod_port = _BCM_SUBPORT_COE_PORT_ID_PORT_GET(port);
   4317     }
   4318 #endif
   4319 
   4320     rv = _bcm_fb2_port_tpid_enable_get(unit, port, &tpid_enable);
   4321     if (BCM_FAILURE(rv)) {
   4322         _bcm_fb2_outer_tpid_tab_unlock(unit);
   4323         return (rv);
   4324     }
   4325 
   4326     if (tpid_enable & (1 << index)) {
   4327         tpid_enable &= ~(1 << index);
   4328         rv = _bcm_fb2_port_tpid_enable_set(unit, port, tpid_enable);
   4329 #if defined(BCM_TRIUMPH2_SUPPORT)
   4330         /* For Triumph2 and Apollo, also need to program the SYSTEM_CONFIG_TABLE
   4331          * for second-pass packets. These are treated as Higig-lookup packets */
   4332         if (!SOC_IS_TRIDENT3X(unit) &&
   4333             (BCM_SUCCESS(rv) && (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) ||
   4334             SOC_IS_VALKYRIE2(unit) || SOC_IS_ENDURO(unit) ||
   4335             SOC_IS_HURRICANEX(unit) || SOC_IS_TD_TT(unit) ||
   4336             SOC_IS_GREYHOUND2(unit)))) {
   4337             if (soc_mem_is_valid(unit, SYSTEM_CONFIG_TABLE_MODBASEm)) {
   4338                 rv = _bcm_fb2_mod_port_tpid_enable_write(unit, modid, mod_port,
   4339                         tpid_enable);
   4340             } else if (soc_mem_is_valid(unit, SYSTEM_CONFIG_TABLEm)) {
   4341                 int sys_index = 0;
   4342                 system_config_table_entry_t systab;
   4343 
   4344                 sys_index = modid * 64 + mod_port;
   4345                 rv = READ_SYSTEM_CONFIG_TABLEm(unit, MEM_BLOCK_ANY, sys_index,
   4346                         &systab);
   4347                 if (BCM_SUCCESS(rv)) {
   4348                     soc_SYSTEM_CONFIG_TABLEm_field32_set(unit, &systab,
   4349                             OUTER_TPID_ENABLEf, tpid_enable);
   4350                     rv = WRITE_SYSTEM_CONFIG_TABLEm(unit, MEM_BLOCK_ALL,
   4351                             sys_index, &systab);
   4352                 }
   4353             }
   4354         }
   4355 #endif 
   4356 #if defined(BCM_TRX_SUPPORT)
   4357         if (BCM_SUCCESS(rv) &&
   4358             soc_mem_field_valid(unit, SOURCE_TRUNK_MAP_TABLEm,
   4359             OUTER_TPID_ENABLEf)) {
   4360             rv = _bcm_trx_source_trunk_map_set(unit, port, OUTER_TPID_ENABLEf,
   4361                                                tpid_enable);
   4362         }
   4363 #endif
   4364     } else {
   4365         rv = BCM_E_NOT_FOUND;
   4366     }
   4367     if (BCM_FAILURE(rv)) {
   4368         _bcm_fb2_outer_tpid_tab_unlock(unit);
   4369         return (rv);
   4370     } 
   4371  
   4372 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   4373     if (soc_feature(unit, soc_feature_td2p_style_egr_outer_tpid)) {
   4374         if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) &&
   4375             _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port)) {
   4376             rv = bcm_esw_port_egr_lport_field_set(
   4377                 unit, port, EGR_PORT_1m,
   4378                 OUTER_TPID_ENABLEf, tpid_enable);
   4379         } else {
   4380             rv = soc_mem_field32_modify(unit, EGR_PORT_1m, port,
   4381                                         OUTER_TPID_ENABLEf, tpid_enable);
   4382         }
   4383     } else 
   4384 #endif
   4385 #if defined(BCM_TRIUMPH2_SUPPORT) || defined(BCM_ENDURO_SUPPORT)
   4386     if (SOC_REG_FIELD_VALID(unit, EGR_PORT_1r, OUTER_TPID_ENABLEf)) {
   4387         rv = soc_reg_field32_modify(unit, EGR_PORT_1r, port,
   4388                                     OUTER_TPID_ENABLEf, tpid_enable);
   4389     } else
   4390 #endif
   4391     if (SOC_REG_IS_VALID(unit, EGR_SRC_PORTr)) {
   4392          rv = soc_reg_field32_modify(unit, EGR_SRC_PORTr, port,
   4393                                      OUTER_TPID_ENABLEf, tpid_enable);
   4394     }
   4395     if (BCM_FAILURE(rv)) {
   4396         _bcm_fb2_outer_tpid_tab_unlock(unit);
   4397         return (rv);
   4398     }
   4399 
   4400     rv = _bcm_fb2_egr_vlan_control_field_get(
   4401         unit, port, OUTER_TPID_INDEXf, (uint32*)&index);
   4402     if (BCM_FAILURE(rv)) {
   4403         _bcm_fb2_outer_tpid_tab_unlock(unit);
   4404         return (rv);
   4405     }
   4406 
   4407         /* If the current port tpid is not default tpid then
   4408          * add the default tpid to the port before deleting current port tpid */
   4409         default_tpid = _bcm_fb2_outer_tpid_default_get(unit);
   4410         rv = _bcm_fb2_outer_tpid_entry_add(unit, default_tpid,
   4411                                            &default_tpid_index);
   4412         if (BCM_FAILURE(rv)) {
   4413             _bcm_fb2_outer_tpid_tab_unlock(unit);
   4414             return (rv);
   4415         }
   4416 
   4417         rv = _bcm_fb2_egr_vlan_control_field_set(
   4418             unit, port, OUTER_TPID_INDEXf, default_tpid_index);
   4419         if (BCM_FAILURE(rv)) {
   4420             _bcm_fb2_outer_tpid_tab_unlock(unit);
   4421             return (rv);
   4422         }
   4423 
   4424     if (!(SOC_IS_APOLLO(unit) || SOC_IS_HURRICANE2(unit) ||
   4425         SOC_IS_SCORPION(unit) || SOC_IS_RAVEN(unit))) {
   4426         rv = _bcm_port_info_get(unit, port, &pinfo);
   4427         BCM_IF_ERROR_RETURN(rv);
   4428         if (pinfo->dtag_mode & BCM_PORT_DTAG_MODE_EXTERNAL) {
   4429             /*For DT mode external ports, don't enable outer TPIDs*/
   4430         } else {
   4431             /*Enable outer_tpid field for default tpid and add entry*/
   4432             tpid_enable =  1 << default_tpid_index;
   4433             rv = _bcm_fb2_port_tpid_enable_set(unit, port, tpid_enable);
   4434             if (BCM_FAILURE(rv)) {
   4435                 _bcm_fb2_outer_tpid_tab_unlock(unit);
   4436                 return (rv);
   4437             }
   4438             rv = _bcm_fb2_outer_tpid_entry_add(unit, default_tpid,
   4439                                                &default_tpid_index);
   4440             if (BCM_FAILURE(rv)) {
   4441                 _bcm_fb2_outer_tpid_tab_unlock(unit);
   4442                 return (rv);
   4443             }
   4444         }
   4445     }
   4446 
   4447     /* Delete function called twice to set it to the appropriate
   4448      * default value since the set function calls the entry_add 
   4449      * function twice resulting in the reference count to 
   4450      * to be incremented twice for EGR_VLAN_CONTROL_1r and PORT tables.
   4451      */
   4452     rv = _bcm_fb2_outer_tpid_entry_delete(unit, index);
   4453     if (BCM_FAILURE(rv)) {
   4454         _bcm_fb2_outer_tpid_tab_unlock(unit);
   4455         return (rv);
   4456     }    
   4457     /* Delete the cached entry only after the hardware is
   4458      * successfully updated.
   4459      */
   4460     rv = _bcm_fb2_outer_tpid_entry_delete(unit, index);
   4461     _bcm_fb2_outer_tpid_tab_unlock(unit);
   4462     return rv;
   4463 }
   4464 
   4465 /*
   4466  * Function:
   4467  *      bcm_fb2_port_tpid_delete_all
   4468  * Description:
   4469  *      Delete all allowed TPID for a port.
   4470  * Parameters:
   4471  *      unit - (IN) Device number
   4472  *      port - (IN) Port number
   4473  * Return Value:
   4474  *      BCM_E_XXX
   4475  */
   4476 int 
   4477 _bcm_fb2_port_tpid_delete_all(int unit, bcm_port_t port)
   4478 {
   4479     uint32            tpid_enable;
   4480     int               index = 0;
   4481     int               rv;
   4482     uint16            default_tpid;
   4483     int               default_tpid_index;
   4484     _bcm_port_info_t  *pinfo;
   4485 #ifdef BCM_TRIUMPH2_SUPPORT
   4486     bcm_module_t      modid = 0;
   4487     bcm_port_t        mod_port = port;
   4488 #endif
   4489 
   4490     _bcm_fb2_outer_tpid_tab_lock(unit);
   4491 
   4492 #ifdef BCM_TRIUMPH2_SUPPORT
   4493     rv = bcm_esw_stk_my_modid_get(unit, &modid);
   4494     if (BCM_FAILURE(rv)) {
   4495         _bcm_fb2_outer_tpid_tab_unlock(unit);
   4496         return (rv);
   4497     }
   4498 #endif
   4499 
   4500 #ifdef BCM_TRIDENT2PLUS_SUPPORT
   4501     if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) &&
   4502         _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port)) {
   4503         modid = _BCM_SUBPORT_COE_PORT_ID_MOD_GET(port);
   4504         mod_port = _BCM_SUBPORT_COE_PORT_ID_PORT_GET(port);
   4505     }
   4506 #endif
   4507 
   4508     rv = _bcm_fb2_port_tpid_enable_get(unit, port, &tpid_enable);
   4509     if (BCM_FAILURE(rv)) {
   4510         _bcm_fb2_outer_tpid_tab_unlock(unit);
   4511         return (rv);
   4512     }
   4513 
   4514     rv = _bcm_fb2_port_tpid_enable_set(unit, port, 0);
   4515     if (BCM_FAILURE(rv)) {
   4516         _bcm_fb2_outer_tpid_tab_unlock(unit);
   4517         return (rv);
   4518     }
   4519 
   4520 #if defined(BCM_TRIUMPH2_SUPPORT)
   4521     if (!SOC_IS_TRIDENT3X(unit) &&
   4522         (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) ||
   4523         SOC_IS_VALKYRIE2(unit) || SOC_IS_ENDURO(unit) ||
   4524         SOC_IS_HURRICANEX(unit) || SOC_IS_TD_TT(unit) ||
   4525         SOC_IS_GREYHOUND(unit) || SOC_IS_GREYHOUND2(unit))) {
   4526         if (soc_mem_is_valid(unit, SYSTEM_CONFIG_TABLE_MODBASEm)) {
   4527             rv = _bcm_fb2_mod_port_tpid_enable_write(unit, modid, mod_port, 0);
   4528         } else if (soc_mem_is_valid(unit, SYSTEM_CONFIG_TABLEm)) {
   4529             int sys_index = 0;
   4530             system_config_table_entry_t systab;
   4531 
   4532             sys_index = modid * 64 + mod_port;
   4533             rv = READ_SYSTEM_CONFIG_TABLEm(unit, MEM_BLOCK_ANY, sys_index,
   4534                     &systab);
   4535             if (BCM_SUCCESS(rv)) {
   4536                 soc_SYSTEM_CONFIG_TABLEm_field32_set(unit, &systab,
   4537                         OUTER_TPID_ENABLEf, 0);
   4538                 rv = WRITE_SYSTEM_CONFIG_TABLEm(unit, MEM_BLOCK_ALL,
   4539                         sys_index, &systab);
   4540             }
   4541         }
   4542 
   4543 #if defined(BCM_TRX_SUPPORT)
   4544         if (BCM_SUCCESS(rv) &&
   4545             soc_mem_field_valid(unit, SOURCE_TRUNK_MAP_TABLEm,
   4546             OUTER_TPID_ENABLEf)) {
   4547             rv = _bcm_trx_source_trunk_map_set(unit, port, OUTER_TPID_ENABLEf, 0);
   4548         }
   4549 #endif
   4550     }
   4551 #endif /* BCM_TRIUMPH2_SUPPORT */ 
   4552     if (BCM_FAILURE(rv)) {
   4553         _bcm_fb2_outer_tpid_tab_unlock(unit);
   4554         return (rv);
   4555     }
   4556 
   4557 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   4558     if (soc_feature(unit, soc_feature_td2p_style_egr_outer_tpid)) {
   4559         if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) &&
   4560             _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port)) {
   4561             rv = bcm_esw_port_egr_lport_field_set(
   4562                 unit, port, EGR_PORT_1m,
   4563                 OUTER_TPID_ENABLEf, 0);
   4564         } else {
   4565             rv = soc_mem_field32_modify(unit, EGR_PORT_1m, port,
   4566                                         OUTER_TPID_ENABLEf, 0);
   4567         }
   4568     } else 
   4569 #endif
   4570 #if defined(BCM_TRIUMPH2_SUPPORT) || defined(BCM_ENDURO_SUPPORT)
   4571     if (SOC_REG_FIELD_VALID(unit, EGR_PORT_1r, OUTER_TPID_ENABLEf)) {
   4572         rv = soc_reg_field32_modify(unit, EGR_PORT_1r, port,
   4573                                     OUTER_TPID_ENABLEf, 0);
   4574     } else
   4575 #endif
   4576     if (SOC_REG_IS_VALID(unit, EGR_SRC_PORTr)) {
   4577         rv = soc_reg_field32_modify(unit, EGR_SRC_PORTr, port,
   4578                                     OUTER_TPID_ENABLEf, tpid_enable);
   4579     }
   4580     if (BCM_FAILURE(rv)) {
   4581         _bcm_fb2_outer_tpid_tab_unlock(unit);
   4582         return (rv);
   4583     }
   4584 
   4585     rv = _bcm_fb2_egr_vlan_control_field_get(
   4586         unit, port, OUTER_TPID_INDEXf, (uint32*)&index);
   4587     if (BCM_FAILURE(rv)) {
   4588         _bcm_fb2_outer_tpid_tab_unlock(unit);
   4589         return (rv);
   4590     }
   4591 
   4592         /* If the current port tpid is not default tpid then
   4593          * add the default tpid to the port before deleting current port tpid */
   4594         default_tpid = _bcm_fb2_outer_tpid_default_get(unit);
   4595         rv = _bcm_fb2_outer_tpid_entry_add(unit, default_tpid,
   4596                                            &default_tpid_index);
   4597         if (BCM_FAILURE(rv)) {
   4598             _bcm_fb2_outer_tpid_tab_unlock(unit);
   4599             return (rv);
   4600         }
   4601 
   4602         rv = _bcm_fb2_egr_vlan_control_field_set(
   4603             unit, port, OUTER_TPID_INDEXf, default_tpid_index);
   4604 
   4605     if (BCM_FAILURE(rv)) {
   4606         _bcm_fb2_outer_tpid_tab_unlock(unit);
   4607         return (rv);
   4608     }
   4609 
   4610 
   4611     /* Delete the cached entries only after the hardware is 
   4612      * successfully updated.
   4613      */
   4614     rv = _bcm_fb2_outer_tpid_entry_delete(unit, index);
   4615     if (BCM_FAILURE(rv)) {
   4616         _bcm_fb2_outer_tpid_tab_unlock(unit);
   4617         return (rv);
   4618     }
   4619 
   4620     index = 0;
   4621     while (tpid_enable) {
   4622         if (tpid_enable & 1) {
   4623             rv = _bcm_fb2_outer_tpid_entry_delete(unit, index);
   4624             if (BCM_FAILURE(rv)) {
   4625                 _bcm_fb2_outer_tpid_tab_unlock(unit);
   4626                 return (rv);
   4627             }
   4628         }
   4629         tpid_enable = tpid_enable >> 1;
   4630         index++;
   4631     }
   4632 
   4633     /* After deleting all the TPID entries, enable the default TPID  *
   4634      * else reference count for even the default TPID will be cleared*/
   4635     if (!(SOC_IS_APOLLO(unit) || SOC_IS_HURRICANE2(unit) ||
   4636         SOC_IS_SCORPION(unit) || SOC_IS_RAVEN(unit))) {
   4637         rv = _bcm_port_info_get(unit, port, &pinfo);
   4638         BCM_IF_ERROR_RETURN(rv);
   4639         if (pinfo->dtag_mode & BCM_PORT_DTAG_MODE_EXTERNAL) {
   4640             /* For DT mode external ports, don't enable outer TPIDs */
   4641         } else {
   4642             /* Enable outer_tpid field for default tpid  and add entry*/
   4643             tpid_enable =  1 << default_tpid_index;
   4644             rv = _bcm_fb2_port_tpid_enable_set(unit, port, tpid_enable);
   4645             if (BCM_FAILURE(rv)) {
   4646                 _bcm_fb2_outer_tpid_tab_unlock(unit);
   4647                 return (rv);
   4648             }
   4649             rv = _bcm_fb2_outer_tpid_entry_add(unit, default_tpid,
   4650                                                &default_tpid_index);
   4651             if (BCM_FAILURE(rv)) {
   4652                 _bcm_fb2_outer_tpid_tab_unlock(unit);
   4653                 return (rv);
   4654             }
   4655         }
   4656     }
   4657 
   4658     _bcm_fb2_outer_tpid_tab_unlock(unit);
   4659     return (rv);
   4660 }
   4661 
   4662 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT || BCM_RAVEN_SUPPORT */
   4663 
   4664 /*
   4665  * Function:
   4666  *      _bcm_fb_port_dtag_mode_set
   4667  * Description:
   4668  *      Set the double-tagging mode of a port.
   4669  * Parameters:
   4670  *      unit - (IN) BCM device number
   4671  *      port - (IN) Port number
   4672  *      mode - (IN) Double-tagging mode, one of:
   4673  *              BCM_PORT_DTAG_MODE_NONE            No double tagging
   4674  *              BCM_PORT_DTAG_MODE_INTERNAL        Service Provider port
   4675  *              BCM_PORT_DTAG_MODE_EXTERNAL        Customer port
   4676  *              BCM_PORT_DTAG_REMOVE_EXTERNAL_TAG  Remove customer tag
   4677  *              BCM_PORT_DTAG_ADD_EXTERNAL_TAG     Add customer tag
   4678  *      dt_mode - (IN) True/False double tagged port.
   4679  *      ignore_tag - (IN) Ignore outer tag. 
   4680  * Return Value:
   4681  *      BCM_E_XXX
   4682  * Notes:
   4683  *      BCM_PORT_DTAG_MODE_INTERNAL is for service provider ports.
   4684  *              A tag will be added if the packet does not already
   4685  *              have the internal TPID (see bcm_port_tpid_set below).
   4686  *              Internally this sets DT_MODE and clears IGNORE_TAG.
   4687  *      BCM_PORT_DTAG_MODE_EXTERNAL is for customer ports.
   4688  *              The service provider TPID will always be added
   4689  *              (see bcm_port_tpid_set below).
   4690  *              Internally this sets DT_MODE and sets IGNORE_TAG.
   4691  */
   4692 int
   4693 _bcm_fb_port_dtag_mode_set(int unit, bcm_port_t port, int mode, 
   4694                            int dt_mode, int ignore_tag)
   4695 {
   4696     uint32           config, oconfig;
   4697     uint64           config64, oconfig64;
   4698     _bcm_port_info_t *pinfo;
   4699     bcm_port_cfg_t   pcfg;
   4700     int              rv;
   4701 
   4702     BCM_IF_ERROR_RETURN(_bcm_port_info_get(unit, port, &pinfo));
   4703 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_RAVEN_SUPPORT)
   4704     if (SOC_IS_FIREBOLT2(unit) || SOC_IS_RAVEN(unit) || SOC_IS_HAWKEYE(unit)) {
   4705         rv =  soc_reg_field32_modify(unit, EGR_SRC_PORTr, port, 
   4706                                      ADD_INNER_TAGf, 
   4707                                      (mode & BCM_PORT_DTAG_ADD_EXTERNAL_TAG)? 1 : 0);
   4708         BCM_IF_ERROR_RETURN(rv);
   4709 
   4710 #ifdef BCM_TRIDENT2PLUS_SUPPORT
   4711         if (soc_feature(unit, soc_feature_egr_vlan_control_is_memory)) {
   4712             if (soc_feature(unit, soc_feature_egr_all_profile)) {
   4713                 BCM_IF_ERROR_RETURN(
   4714                     bcm_esw_port_egr_lport_field_set(
   4715                     unit, port, EGR_VLAN_CONTROL_1m,
   4716                     REMOVE_INNER_TAGf,
   4717                     (mode & BCM_PORT_DTAG_REMOVE_EXTERNAL_TAG) ? 1 : 0));
   4718             } else {
   4719             rv = soc_mem_field32_modify(unit, EGR_VLAN_CONTROL_1m, port,
   4720                                         REMOVE_INNER_TAGf,
   4721                                         (mode & BCM_PORT_DTAG_REMOVE_EXTERNAL_TAG)? 1 : 0);
   4722             }
   4723         } else
   4724 #endif
   4725         {
   4726             rv = soc_reg_field32_modify(unit, EGR_VLAN_CONTROL_1r, port,
   4727                                         REMOVE_INNER_TAGf,
   4728                                         (mode & BCM_PORT_DTAG_REMOVE_EXTERNAL_TAG)? 1 : 0);
   4729         }
   4730         BCM_IF_ERROR_RETURN(rv);
   4731     }
   4732 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_RAVEN_SUPPORT */
   4733 
   4734 
   4735     SOC_IF_ERROR_RETURN(READ_ING_CONFIGr(unit, &config));
   4736     oconfig = config;
   4737     soc_reg_field_set(unit, ING_CONFIGr, &config,
   4738                       DT_MODEf, dt_mode);
   4739     if (config != oconfig) {
   4740         SOC_IF_ERROR_RETURN(WRITE_ING_CONFIGr(unit, config));
   4741     }
   4742 
   4743     SOC_IF_ERROR_RETURN(READ_EGR_CONFIGr(unit, &config));
   4744     oconfig = config;
   4745     soc_reg_field_set(unit, EGR_CONFIGr, &config, DT_MODEf, dt_mode);
   4746     if (config != oconfig) {
   4747         SOC_IF_ERROR_RETURN(WRITE_EGR_CONFIGr(unit, config));
   4748     }
   4749     /* Record double tag mode for use in DCBs */
   4750     SOC_DT_MODE(unit) = (dt_mode != 0);
   4751 
   4752     if (SOC_REG_IS_VALID(unit, EGR_PORT_64r)) {
   4753         SOC_IF_ERROR_RETURN(READ_EGR_PORT_64r(unit, port, &config64));
   4754         oconfig64 = config64;
   4755         soc_reg64_field32_set(unit, EGR_PORT_64r, &config64, NNI_PORTf, !ignore_tag); 
   4756         if (COMPILER_64_NE(config64, oconfig64)) {
   4757             SOC_IF_ERROR_RETURN(WRITE_EGR_PORT_64r(unit, port, config64));
   4758         }
   4759     } else {
   4760         SOC_IF_ERROR_RETURN(READ_EGR_PORTr(unit, port, &config));
   4761         oconfig = config;
   4762         soc_reg_field_set(unit, EGR_PORTr, &config, NNI_PORTf, !ignore_tag); 
   4763         if (config != oconfig) {
   4764             SOC_IF_ERROR_RETURN(WRITE_EGR_PORTr(unit, port, config));
   4765         }
   4766     }
   4767 
   4768     soc_mem_lock(unit, PORT_TABm);
   4769 
   4770     rv = mbcm_driver[unit]->mbcm_port_cfg_get(unit, port, &pcfg);
   4771     if (BCM_SUCCESS(rv) && (pcfg.pc_nni_port == ignore_tag)) {
   4772         pcfg.pc_nni_port = !ignore_tag;
   4773         rv = mbcm_driver[unit]->mbcm_port_cfg_set(unit, port, &pcfg);
   4774     }
   4775 
   4776     soc_mem_unlock(unit, PORT_TABm);
   4777     return rv;
   4778 }
   4779 
   4780 /*
   4781  * Function:
   4782  *      _bcm_fb_port_dtag_mode_get
   4783  * Description:
   4784  *      Return the current double-tagging mode of a port.
   4785  * Parameters:
   4786  *      unit - (IN) BCM device number
   4787  *      port - (IN) Port number
   4788  *      mode - (OUT) Double-tagging mode
   4789  * Return Value:
   4790  *      BCM_E_XXX
   4791  */
   4792 int
   4793 _bcm_fb_port_dtag_mode_get(int unit, bcm_port_t port, int *mode)
   4794 {
   4795     uint32           config;
   4796     bcm_port_cfg_t   pcfg;
   4797     int              rv;
   4798 
   4799     SOC_IF_ERROR_RETURN(READ_ING_CONFIGr(unit, &config));
   4800     if (soc_reg_field_get(unit, ING_CONFIGr, config, DT_MODEf) == 0) {
   4801         *mode = BCM_PORT_DTAG_MODE_NONE;
   4802     } else {
   4803         rv = mbcm_driver[unit]->mbcm_port_cfg_get(unit, port, &pcfg);
   4804         BCM_IF_ERROR_RETURN(rv);
   4805 
   4806         if (pcfg.pc_nni_port) {
   4807             *mode = BCM_PORT_DTAG_MODE_INTERNAL;
   4808         } else {
   4809             *mode = BCM_PORT_DTAG_MODE_EXTERNAL;
   4810         }
   4811     }
   4812 
   4813 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_RAVEN_SUPPORT)
   4814     if (SOC_REG_FIELD_VALID(unit, EGR_SRC_PORTr, ADD_INNER_TAGf)) {
   4815         uint32 value;
   4816 
   4817         SOC_IF_ERROR_RETURN(READ_EGR_SRC_PORTr(unit, port, &value));
   4818         if (soc_reg_field_get(unit, EGR_SRC_PORTr,
   4819                               value, ADD_INNER_TAGf)) {
   4820             *mode |= BCM_PORT_DTAG_ADD_EXTERNAL_TAG;
   4821         }
   4822 #ifdef BCM_TRIDENT2PLUS_SUPPORT
   4823         if (soc_feature(unit, soc_feature_egr_vlan_control_is_memory)) {
   4824             if (soc_feature(unit, soc_feature_egr_all_profile)) {
   4825                 uint32 val = 0;
   4826                 BCM_IF_ERROR_RETURN(bcm_esw_port_egr_lport_field_get(unit,
   4827                     port, EGR_VLAN_CONTROL_1m, REMOVE_INNER_TAGf, &val));
   4828                 if (val) {
   4829                     *mode |= BCM_PORT_DTAG_REMOVE_EXTERNAL_TAG;
   4830                 }
   4831             } else {
   4832             egr_vlan_control_1_entry_t entry;
   4833             SOC_IF_ERROR_RETURN(
   4834                 READ_EGR_VLAN_CONTROL_1m(unit, MEM_BLOCK_ANY, port, &entry));
   4835             if (soc_EGR_VLAN_CONTROL_1m_field32_get(unit, &entry,
   4836                                     REMOVE_INNER_TAGf)) {
   4837                 *mode |= BCM_PORT_DTAG_REMOVE_EXTERNAL_TAG;
   4838             }
   4839             }
   4840         } else
   4841 #endif
   4842         {
   4843             SOC_IF_ERROR_RETURN
   4844                 (READ_EGR_VLAN_CONTROL_1r(unit, port, &value));
   4845             if (soc_reg_field_get(unit, EGR_VLAN_CONTROL_1r, 
   4846                                   value, REMOVE_INNER_TAGf)) {
   4847                 *mode |= BCM_PORT_DTAG_REMOVE_EXTERNAL_TAG;
   4848             }
   4849         }
   4850     } 
   4851 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_RAVEN_SUPPORT */
   4852     return BCM_E_NONE;
   4853 }
   4854 
   4855 #endif  /* BCM_FIREBOLT_SUPPORT */