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

vlan.c (64907B)


      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:       vlan.c
      8  * Purpose:    Broadcom StrataSwitch VLAN switch API for TH3.
      9  */
     10 #include <soc/drv.h>
     11 #include <soc/rcpu.h>
     12 #include <bcm/error.h>
     13 #include <bcm_int/common/lock.h>
     14 #include <bcm_int/esw/vlan.h>
     15 #include <bcm_int/esw/mbcm.h>
     16 #include <bcm_int/esw/firebolt.h>
     17 
     18 #ifdef BCM_TOMAHAWK3_SUPPORT
     19 #include <bcm_int/tomahawk3_dispatch.h>
     20 #include <bcm_int/esw/tomahawk3.h>
     21 
     22 #define CHECK_INIT(unit)                                    \
     23         do {                                                \
     24             if (!vlan_info[unit].init) {                    \
     25                 return BCM_E_INIT;                          \
     26             }                                               \
     27         } while(0)                                          \
     28 
     29 #define CHECK_INIT_AND_VLAN_ID(unit, vlan)                  \
     30         do {                                                \
     31             CHECK_INIT(unit);                               \
     32             VLAN_CHK_ID(unit, vlan);                        \
     33         } while(0)
     34 
     35 #define BCM_TH3_VLAN_CONTROL_VLAN_ALL_VALID_MASK            \
     36     (BCM_VLAN_CONTROL_VLAN_VRF_MASK |                       \
     37      BCM_VLAN_CONTROL_VLAN_FORWARDING_VLAN_MASK |           \
     38      BCM_VLAN_CONTROL_VLAN_INGRESS_IF_MASK |                \
     39      BCM_VLAN_CONTROL_VLAN_OUTER_TPID_MASK |                \
     40      BCM_VLAN_CONTROL_VLAN_IP6_MCAST_FLOOD_MODE_MASK |      \
     41      BCM_VLAN_CONTROL_VLAN_IP4_MCAST_FLOOD_MODE_MASK |      \
     42      BCM_VLAN_CONTROL_VLAN_L2_MCAST_FLOOD_MODE_MASK |       \
     43      BCM_VLAN_CONTROL_VLAN_IF_CLASS_MASK |                  \
     44      BCM_VLAN_CONTROL_VLAN_FORWARDING_MODE_MASK |           \
     45      BCM_VLAN_CONTROL_VLAN_BROADCAST_GROUP_MASK |           \
     46      BCM_VLAN_CONTROL_VLAN_UNKNOWN_MULTICAST_GROUP_MASK |   \
     47      BCM_VLAN_CONTROL_VLAN_UNKNOWN_UNICAST_GROUP_MASK |     \
     48      BCM_VLAN_CONTROL_VLAN_PROTOCOL_PKT_MASK |              \
     49      BCM_VLAN_CONTROL_VLAN_L3_IF_CLASS_MASK)
     50 
     51 #define BCM_TH3_VLAN_CONTROL_VLAN_SUPPORTED_CTRL_FLAGS      \
     52     (BCM_VLAN_LEARN_DISABLE |                               \
     53      BCM_VLAN_ICMP_REDIRECT_TOCPU |                         \
     54      BCM_VLAN_IGMP_SNOOP_DISABLE |                          \
     55      BCM_VLAN_IP4_DISABLE |                                 \
     56      BCM_VLAN_IP4_MCAST_DISABLE |                           \
     57      BCM_VLAN_IP4_MCAST_L2_DISABLE |                        \
     58      BCM_VLAN_IP6_DISABLE |                                 \
     59      BCM_VLAN_IP6_MCAST_DISABLE |                           \
     60      BCM_VLAN_IP6_MCAST_L2_DISABLE |                        \
     61      BCM_VLAN_IPMC_DO_VLAN_DISABLE |                        \
     62      BCM_VLAN_L2_CLASS_ID_ONLY |                            \
     63      BCM_VLAN_L3_CLASS_ID |                                 \
     64      BCM_VLAN_L3_VRF_GLOBAL_DISABLE |                       \
     65      BCM_VLAN_MPLS_DISABLE |                                \
     66      BCM_VLAN_NON_UCAST_DROP |                              \
     67      BCM_VLAN_NON_UCAST_TOCPU |                             \
     68      BCM_VLAN_UNKNOWN_IP4_MCAST_TOCPU |                     \
     69      BCM_VLAN_UNKNOWN_IP6_MCAST_TOCPU |                     \
     70      BCM_VLAN_UNKNOWN_UCAST_DROP |                          \
     71      BCM_VLAN_UNKNOWN_UCAST_TOCPU)
     72 
     73 #define BCM_TH3_VLAN_GPORT_ADD_SUPPORTED_FLAGS              \
     74     (BCM_VLAN_GPORT_ADD_UNTAGGED |                          \
     75      BCM_VLAN_GPORT_ADD_INGRESS_ONLY |                      \
     76      BCM_VLAN_GPORT_ADD_EGRESS_ONLY |                       \
     77      BCM_VLAN_GPORT_ADD_EGRESS_L3_ONLY)
     78 
     79 typedef enum bcm_th3_cmd_e {
     80     BCM_TH3_GET,
     81     BCM_TH3_SET,
     82     BCM_TH3_DEL
     83 } bcm_th3_cmd_t;
     84 
     85 #if defined(BCM_WARM_BOOT_SUPPORT)
     86 #include <soc/scache.h>
     87 #include <bcm/module.h>
     88 #include <bcm_int/esw/switch.h>
     89 
     90 #define BCM_WB_VERSION_1_0          SOC_SCACHE_VERSION(1,0)
     91 #define BCM_WB_DEFAULT_VERSION      BCM_WB_VERSION_1_0
     92 
     93 /*
     94  * Function:
     95  *      _bcm_th3_vlan_reinit
     96  *
     97  * Purpose:
     98  *      Recover VLAN state from hardware (reload)
     99  *
    100  * Parameters:
    101  *      unit - (IN) StrataSwitch PCI device unit number (driver internal).
    102  *
    103  * Returns:
    104  *      BCM_E_NONE - Success.
    105  *      BCM_E_XXX - Other failures.
    106  *
    107  * Note:
    108  */
    109 STATIC int
    110 _bcm_th3_vlan_reinit(int unit)
    111 {
    112     bcm_vlan_info_t *vi = &vlan_info[unit];
    113     int rv;
    114     soc_scache_handle_t scache_handle;
    115     uint8 *vlan_scache_ptr;
    116     uint8  flood_mode;
    117     uint16 recovered_ver = BCM_WB_VERSION_1_0;
    118 
    119     /* Clean up existing vlan_info */
    120     vi->init = TRUE;
    121     BCM_IF_ERROR_RETURN(_bcm_vlan_cleanup(unit));
    122 
    123 #ifdef BCM_MCAST_FLOOD_DEFAULT
    124     BCM_IF_ERROR_RETURN
    125         (_bcm_esw_vlan_flood_default_set(unit, BCM_MCAST_FLOOD_DEFAULT));
    126 #else
    127     BCM_IF_ERROR_RETURN
    128         (_bcm_esw_vlan_flood_default_set(unit, BCM_VLAN_MCAST_FLOOD_UNKNOWN));
    129 #endif
    130 
    131     /*
    132      * Initialize software structures
    133      */
    134     vi->defl = BCM_VLAN_DEFAULT;
    135     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_VLAN, 0);
    136     rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE,
    137                                  0, &vlan_scache_ptr,
    138                                  BCM_WB_DEFAULT_VERSION, &recovered_ver);
    139     if (rv == SOC_E_NOT_FOUND) {
    140         /* Use non-Level 2 case */
    141     } else if (SOC_FAILURE(rv)) {
    142         return rv;
    143     } else {
    144         /* Success, recover default VLAN */
    145         sal_memcpy(&vi->defl, vlan_scache_ptr, sizeof(vi->defl));
    146         vlan_scache_ptr += sizeof(vi->defl);
    147 
    148         /* Flood mode */
    149         /* Type for 'flood_mode' is an enum, which values fit in uint8 */
    150         sal_memcpy(&flood_mode, vlan_scache_ptr, sizeof(flood_mode));
    151         vi->flood_mode = flood_mode;
    152         vlan_scache_ptr += sizeof(flood_mode);
    153     }
    154 
    155     vi->count = 0;
    156 
    157     /* Reinit the VLAN Cross Connect Internal Database */
    158     BCM_IF_ERROR_RETURN(_bcm_th3_vlan_xconnect_db_reinit(unit));
    159 
    160     vi->init = TRUE;
    161 
    162     BCM_IF_ERROR_RETURN(_bcm_vbmp_init(&vi->bmp));
    163     BCM_IF_ERROR_RETURN(_bcm_vbmp_init(&vi->pre_cfg_bmp));
    164 
    165     BCM_IF_ERROR_RETURN
    166         (mbcm_driver[unit]->mbcm_vlan_reload(unit, &vi->bmp, &vi->count));
    167 
    168     if (0 == _BCM_VBMP_LOOKUP(vi->bmp, vi->defl)) {
    169         LOG_WARN(BSL_LS_BCM_VLAN,
    170                  (BSL_META_U(unit,
    171                              "Warm Reboot: Default VLAN %4d does not exist!\n"),
    172                   vi->defl));
    173     }
    174 
    175     return BCM_E_NONE;
    176 }
    177 
    178 /*
    179  * Function:
    180  *      _bcm_th3_esw_vlan_sync
    181  *
    182  * Purpose:
    183  *      Record VLAN module persisitent info for Level 2 Warm Boot
    184  *
    185  * Parameters:
    186  *      unit - StrataSwitch unit number.
    187  *
    188  * Returns:
    189  *      BCM_E_XXX
    190  *
    191  * Note:
    192  */
    193 int
    194 _bcm_th3_vlan_sync(int unit)
    195 {
    196     bcm_vlan_info_t     *vi = &vlan_info[unit];
    197     soc_scache_handle_t scache_handle;
    198     uint8 *vlan_scache_ptr;
    199     uint8  flood_mode;
    200 
    201     CHECK_INIT(unit);
    202 
    203     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_VLAN, 0);
    204     BCM_IF_ERROR_RETURN
    205         (_bcm_esw_scache_ptr_get(unit, scache_handle, FALSE,
    206                                  0, &vlan_scache_ptr,
    207                                  BCM_WB_DEFAULT_VERSION, NULL));
    208     /* Default VLAN */
    209     sal_memcpy(vlan_scache_ptr, &vi->defl, sizeof(vi->defl));
    210     vlan_scache_ptr += sizeof(vi->defl);
    211 
    212     /* Flood mode */
    213     /* Type for 'flood_mode' is an enum, which values fit in uint8 */
    214     flood_mode = vlan_info[unit].flood_mode;
    215     sal_memcpy(vlan_scache_ptr, &flood_mode, sizeof(flood_mode));
    216     vlan_scache_ptr += sizeof(flood_mode);
    217 
    218     return BCM_E_NONE;
    219 }
    220 #endif /* BCM_WARM_BOOT_SUPPORT */
    221 
    222 /*
    223  * Function:
    224  *      _bcm_th3_vlan_port_add
    225  *
    226  * Purpose:
    227  *      Main part of bcm_vlan_port_add; assumes locking already done.
    228  *
    229  * Parameters:
    230  *      unit - (IN) StrataSwitch PCI device unit number (driver internal).
    231  *      vid - (IN) VLAN ID to add port to as a member.
    232  *      pbmp - (IN) egress port bitmap for members of VLAN
    233  *      ubmp - (IN) untagged members of VLAN
    234  *      ing_pbmp - (IN) ingress port bitmap for members of VLAN
    235  *      flags - (IN) VLAN_PORT flags qualifying the member ports.
    236  *
    237  * Returns:
    238  *      BCM_E_NONE - Success.
    239  *      BCM_E_XXX - Other failures.
    240  *
    241  * Note:
    242  */
    243 STATIC int
    244 _bcm_th3_vlan_port_add(int unit, bcm_vlan_t vid, pbmp_t pbmp, pbmp_t ubmp,
    245                    pbmp_t ing_pbmp, int flags)
    246 {
    247     pbmp_t  vlan_pbmp, vlan_ubmp, vlan_ing_pbmp, orig_pbmp;
    248 
    249     /* No such thing as untagged CPU */
    250     SOC_PBMP_REMOVE(ubmp, PBMP_CMIC(unit));
    251 
    252     /* Remove internal loopback port from vlan port bitmaps. Hardware does not
    253      * perform ingress/egress VLAN membership checks on internal loopback port.
    254      */
    255     SOC_PBMP_REMOVE(pbmp, PBMP_LB(unit));
    256     SOC_PBMP_REMOVE(ubmp, PBMP_LB(unit));
    257     SOC_PBMP_REMOVE(ing_pbmp, PBMP_LB(unit));
    258 
    259     /* Don't add ports that are already there */
    260     BCM_IF_ERROR_RETURN
    261         (mbcm_driver[unit]->mbcm_vlan_port_get(
    262             unit, vid, &vlan_pbmp, &vlan_ubmp, &vlan_ing_pbmp));
    263 
    264     SOC_PBMP_ASSIGN(orig_pbmp, pbmp);
    265     COMPILER_REFERENCE(orig_pbmp);
    266     /* But do allow for making the port tagged/
    267      * untagged if its already added to the vlan
    268      */
    269     SOC_PBMP_XOR(vlan_ubmp, ubmp);
    270     SOC_PBMP_REMOVE(vlan_pbmp, vlan_ubmp);
    271     SOC_PBMP_REMOVE(pbmp, vlan_pbmp);
    272     SOC_PBMP_REMOVE(ubmp, vlan_pbmp);
    273     SOC_PBMP_REMOVE(ing_pbmp, vlan_ing_pbmp);
    274 
    275     if (SOC_PBMP_NOT_NULL(pbmp) ||
    276         SOC_PBMP_NOT_NULL(ubmp) || SOC_PBMP_NOT_NULL(ing_pbmp)) {
    277         BCM_IF_ERROR_RETURN(
    278             mbcm_driver[unit]->mbcm_vlan_port_add(
    279                     unit, vid, pbmp, ubmp, ing_pbmp));
    280     }
    281     if (soc_feature(unit, soc_feature_vlan_egress_membership_l3_only) &&
    282         (flags & BCM_VLAN_GPORT_ADD_EGRESS_L3_ONLY)) {
    283         if (SOC_PBMP_NOT_NULL(pbmp)) {
    284             SOC_PBMP_CLEAR(ing_pbmp);
    285             SOC_PBMP_CLEAR(ubmp);
    286             BCM_IF_ERROR_RETURN
    287                 (_bcm_xgs3_vlan_table_port_remove(unit, vid, pbmp, ubmp,
    288                                                   ing_pbmp, VLAN_2_TABm));
    289         }
    290     }
    291 
    292     return BCM_E_NONE;
    293 }
    294 
    295 /*
    296  * Function:
    297  *     _bcm_th3_vlan_control_port_resolve
    298  *
    299  * Purpose:
    300  *     Internal function to validate the given port to be a valid port or
    301  *     supported GPORT. Once validation successfully completes, resolve the
    302  *     given port to its local port representation.
    303  *
    304  * Parameters:
    305  *     unit - (IN) StrataSwitch PCI device unit number (driver internal).
    306  *     in_port - (IN) port/gport to be validated and resolved.
    307  *     only_allow_gport - (IN) in_port has to be a gport.
    308  *     out_port - (OUT) local port. If NULL then the function would only
    309  *                      validate the given port.
    310  *
    311  * Returns:
    312  *     BCM_E_NONE - Success
    313  *     BCM_E_PORT - If the given port is not supported for TH3 VLAN operation
    314  *                  or in_port is not a gport and only_allow_gport is nonzero
    315  *
    316  * Note:
    317  */
    318 STATIC INLINE int
    319 _bcm_th3_vlan_control_port_resolve(
    320     int unit, bcm_port_t in_port, uint8 only_allow_gport, bcm_port_t *out_port)
    321 {
    322     int rv;
    323     int local_modid;
    324     bcm_port_t local_port;
    325 
    326     /* Check for TH3 supported port/gports */
    327     if (BCM_GPORT_IS_SET(in_port)) {
    328         if (BCM_GPORT_IS_LOCAL(in_port)) {
    329             local_port = BCM_GPORT_LOCAL_GET(in_port);
    330         } else if (BCM_GPORT_IS_LOCAL_CPU(in_port)) {
    331             local_port = CMIC_PORT(unit);
    332         } else if (BCM_GPORT_IS_DEVPORT(in_port)) {
    333             local_port = BCM_GPORT_DEVPORT_PORT_GET(in_port);
    334             if (unit != BCM_GPORT_DEVPORT_DEVID_GET(in_port)) {
    335                 return BCM_E_PORT;
    336             }
    337         } else if (BCM_GPORT_IS_MODPORT(in_port)) {
    338             rv = bcm_esw_stk_my_modid_get(unit, &local_modid);
    339             if (BCM_FAILURE(rv) ||
    340                 (local_modid != BCM_GPORT_MODPORT_MODID_GET(in_port))) {
    341                 return BCM_E_PORT;
    342             }
    343             local_port = BCM_GPORT_MODPORT_PORT_GET(in_port);
    344         } else {
    345             /* All other GPORTS are not supported for the VLAN operations */
    346             return BCM_E_PORT;
    347         }
    348     } else if (TRUE == only_allow_gport) {
    349         return BCM_E_PORT;
    350     } else {
    351         local_port = in_port;
    352     }
    353 
    354     /* Check validity of deduced local port */
    355     if (!SOC_PORT_VALID(unit, local_port)) {
    356         return BCM_E_PORT;
    357     }
    358 
    359     /* If caller wants the port resolution then provide */
    360     if (out_port) {
    361         *out_port = local_port;
    362     }
    363     return BCM_E_NONE;
    364 }
    365 
    366 /*
    367  * Function:
    368  *     _bcm_th3_vlan_control_port_config_command
    369  *
    370  * Purpose:
    371  *     Internal function to get/set port based VLAN configuration
    372  *
    373  * Parameters:
    374  *     unit - (IN) StrataSwitch PCI device unit number (driver internal).
    375  *     localport - (IN) port on which the VLAN configuration has to be applied
    376  *     type - (IN) value from bcm_vlan_control_port_t enumeration list
    377  *     cmd - (IN) If BCM_TH3_SET then SET the setting else GET it
    378  *     arg - (INOUT) value to be set or to be retrieved is stored
    379  *
    380  * Returns:
    381  *     BCM_E_NONE - Success
    382  *     BCM_E_PARAM - Given arg is NULL or type is not supported
    383  *     BCM_E_XXX - Other failures
    384  *
    385  * Note:
    386  *     It is assumed that localport parameter is a valid port and hence no
    387  *     further checks performed.
    388  */
    389 STATIC int
    390 _bcm_th3_vlan_control_port_config_command(int unit,
    391     bcm_port_t localport, bcm_vlan_control_port_t type, uint8 cmd, int *arg)
    392 {
    393     uint32 data, evc;
    394 
    395     if (NULL == arg) {
    396         return BCM_E_PARAM;
    397     }
    398 
    399     switch (type) {
    400         case bcmVlanPortVerifyOuterTpid:
    401             /* Call the appr. port module interface */
    402             if (BCM_TH3_SET == cmd) {
    403                 return (_bcm_esw_port_config_set(
    404                             unit, localport, _bcmPortVerifyOuterTpid, !!*arg));
    405             } else {
    406                 return (_bcm_esw_port_config_get(
    407                             unit, localport, _bcmPortVerifyOuterTpid, arg));
    408             }
    409 
    410         case bcmVlanPortOuterTpidSelect:
    411             /*
    412              * Access and/or Modify the OUTER_TPID_SEL field in the register
    413              * EGR_VLAN_CONTROL_1 which is indexed by the given port parameter
    414              */
    415             if (BCM_TH3_SET == cmd) {
    416                 if (*arg != BCM_PORT_OUTER_TPID &&
    417                     *arg != BCM_VLAN_OUTER_TPID) {
    418                     return BCM_E_PARAM;
    419                 }
    420                 SOC_IF_ERROR_RETURN(
    421                     READ_EGR_VLAN_CONTROL_1r(unit, localport, &evc));
    422                 data = evc;
    423                 soc_reg_field_set(
    424                         unit, EGR_VLAN_CONTROL_1r, &evc, OUTER_TPID_SELf, *arg);
    425                 if (evc != data) {
    426                     SOC_IF_ERROR_RETURN(
    427                         WRITE_EGR_VLAN_CONTROL_1r(unit, localport, evc));
    428                 }
    429             } else {
    430                 SOC_IF_ERROR_RETURN(READ_EGR_VLAN_CONTROL_1r(unit, localport, &evc));
    431                 *arg = soc_reg_field_get(
    432                            unit, EGR_VLAN_CONTROL_1r, evc, OUTER_TPID_SELf);
    433             }
    434             return BCM_E_NONE;
    435 
    436         default:
    437             return BCM_E_UNAVAIL;
    438     }
    439 }
    440 
    441 /*
    442  * Function:
    443  *     _bcm_th3_vlan_port_get
    444  *
    445  * Purpose:
    446  *     Helper routine to retrieve the list of
    447  *     the member ports of an existing VLAN.
    448  *
    449  * Parameters:
    450  *     unit - (IN) StrataSwitch PCI device unit number (driver internal).
    451  *     vlan - (IN) VLAN ID to retrieve the gport from.
    452  *     pbmp - (OUT) EGRESS port bitmap
    453  *     ubmp - (OUT) Untagged EGRESS port bitmap
    454  *     ing_pbmp - (OUT) INGRESS port bitmap
    455  *
    456  * Returns:
    457  *     BCM_E_NONE - Success
    458  *     BCM_E_NOT_FOUND - VLAN ID not existing
    459  *     BCM_E_PARAM
    460  *     BCM_E_UNAVAIL - Feature unavailable
    461  *     BCM_E_FAIL - Other failures
    462  *
    463  * Note:
    464  */
    465 STATIC INLINE int
    466 _bcm_th3_vlan_port_get(
    467     int unit, bcm_vlan_t vid, pbmp_t *pbmp, pbmp_t *ubmp, pbmp_t *ing_pbmp)
    468 {
    469     int rv;
    470 
    471     /* Check if the given VLAN ID is an existing vlan */
    472     if (0 == _BCM_VBMP_LOOKUP(vlan_info[unit].bmp, vid)) {
    473         return BCM_E_NOT_FOUND;
    474     }
    475 
    476     /* Init all given port bitmaps */
    477     if (pbmp) {
    478         BCM_PBMP_CLEAR(*pbmp);
    479     }
    480     if (ubmp) {
    481         BCM_PBMP_CLEAR(*ubmp);
    482     }
    483     if (ing_pbmp) {
    484         BCM_PBMP_CLEAR(*ing_pbmp);
    485     }
    486 
    487     /* Call lower level routine to retrieve bounded ports */
    488     BCM_LOCK(unit);
    489     rv = mbcm_driver[unit]->
    490         mbcm_vlan_port_get(unit, vid, pbmp, ubmp, ing_pbmp);
    491     BCM_UNLOCK(unit);
    492 
    493     return rv;
    494 }
    495 
    496 /*
    497  * Function:
    498  *      _bcm_th3_ing_vlan_tag_action_command
    499  *
    500  * Purpose:
    501  *      Generic function to get/set/delete the port's ingress vlan tag actions
    502  *
    503  * Parameters:
    504  *      unit    - (IN) BCM unit.
    505  *      port    - (IN) Port number.
    506  *      cmd     - (IN) One of the values from ENUM bcm_th3_cmd_t.
    507  *      action  - (IN/OUT) Vlan tag actions
    508  *
    509  * Returns:
    510  *      BCM_E_XXX
    511  *
    512  * Note:
    513  *      Based on the value of 'cmd', the parameter 'action' changes its behavior
    514  *      .It is dont care if cmd is BCM_TH3_DEL. If BCM_TH3_GET then 'action' is
    515  *      OUT direction, else if BCM_TH3_SET then it is IN direction.
    516  */
    517 STATIC int
    518 _bcm_th3_ing_vlan_tag_action_command (
    519     int unit, bcm_port_t port, uint8 cmd, bcm_vlan_action_set_t *action) {
    520 
    521     int rv = BCM_E_UNAVAIL;
    522     bcm_port_t  local_port;
    523 
    524     if (soc_feature(unit, soc_feature_vlan_action)) {
    525 
    526         /* Validate and resolve the given gport parameter */
    527         BCM_IF_ERROR_RETURN(
    528             _bcm_th3_vlan_control_port_resolve(unit, port, FALSE, &local_port));
    529 
    530         /* Lock the PORT TABLE as the operation on
    531          * VLAN table and Port table has to be atomic
    532          */
    533         soc_mem_lock(unit, PORT_TABm);
    534         /* Based on the type of API, call appropriate internal functions */
    535         if (BCM_TH3_GET == cmd) {
    536             rv =
    537                 _bcm_th3_vlan_port_default_action_get(unit, local_port, action);
    538         } else if (BCM_TH3_SET == cmd) {
    539             rv =
    540                 _bcm_th3_vlan_port_default_action_set(unit, local_port, action);
    541         } else  if (BCM_TH3_DEL == cmd) {
    542             rv = _bcm_th3_vlan_port_default_action_delete(unit, local_port);
    543         }
    544         /* Unlock the PORT Table */
    545         soc_mem_unlock(unit, PORT_TABm);
    546     }
    547 
    548     return rv;
    549 }
    550 
    551 /*
    552  * Function:
    553  *      _bcm_th3_egr_vlan_tag_action_command
    554  *
    555  * Purpose:
    556  *      Generic function to get/set/delete the port's egress vlan tag actions
    557  *
    558  * Parameters:
    559  *      unit    - (IN) BCM unit.
    560  *      port    - (IN) Port number.
    561  *      cmd     - (IN) One of the values from ENUM bcm_th3_cmd_t.
    562  *      action  - (IN/OUT) Vlan tag actions
    563  *
    564  * Returns:
    565  *      BCM_E_XXX
    566  *
    567  * Note:
    568  *      Based on the value of 'cmd', the parameter 'action' changes its behavior
    569  *      .It is dont care if cmd is BCM_TH3_DEL. If BCM_TH3_GET then 'action' is
    570  *      OUT direction, else if BCM_TH3_SET then it is IN direction.
    571  */
    572 STATIC int
    573 _bcm_th3_egr_vlan_tag_action_command (
    574     int unit, bcm_port_t port, uint8 cmd, bcm_vlan_action_set_t *action) {
    575 
    576     int rv = BCM_E_UNAVAIL;
    577     bcm_port_t  local_port;
    578 
    579     if (soc_feature(unit, soc_feature_vlan_action)) {
    580 
    581         /* Validate and resolve the given gport parameter */
    582         BCM_IF_ERROR_RETURN(
    583             _bcm_th3_vlan_control_port_resolve(unit, port, FALSE, &local_port));
    584 
    585         /* Based on the type of API, call appropriate internal functions */
    586         if (BCM_TH3_GET == cmd) {
    587             rv = _bcm_th3_vlan_port_egress_default_action_get(unit,
    588                                                               local_port,
    589                                                               action);
    590         } else if (BCM_TH3_SET == cmd) {
    591             rv = _bcm_th3_vlan_port_egress_default_action_set(unit,
    592                                                               local_port,
    593                                                               action);
    594         } else  if (BCM_TH3_DEL == cmd) {
    595             rv =
    596               _bcm_th3_vlan_port_egress_default_action_delete(unit, local_port);
    597             if (BCM_SUCCESS(rv)) {
    598                 _bcm_th3_egr_vlan_action_profile_entry_increment(
    599                                     unit, BCM_TH3_EGR_ACTION_PROFILE_DEFAULT);
    600             }
    601         }
    602     }
    603 
    604     return rv;
    605 }
    606 
    607 /*
    608  * Function:
    609  *      bcm_vlan_init
    610  *
    611  * Purpose:
    612  *      Initialize the VLAN module.
    613  *
    614  * Parameters:
    615  *      unit - StrataSwitch PCI device unit number (driver internal).
    616  *
    617  * Returns:
    618  *      BCM_E_NONE - Success.
    619  *      BCM_E_INTERNAL - Chip access failure.
    620  *
    621  * Note:
    622  */
    623 int
    624 bcm_tomahawk3_vlan_init(int unit)
    625 {
    626     bcm_vlan_info_t *vi = &vlan_info[unit];
    627     int rv = BCM_E_NONE;
    628 #ifdef BCM_WARM_BOOT_SUPPORT
    629     soc_scache_handle_t scache_handle;
    630     uint8 *vlan_scache_ptr;
    631     uint32 vlan_scache_size;
    632 #endif /* BCM_WARM_BOOT_SUPPORT */
    633 
    634     /* Set the auto stack as 0 as stacking not supported on TH3 */
    635     vi->vlan_auto_stack = 0;
    636 
    637 #ifdef BCM_WARM_BOOT_SUPPORT
    638     if (SOC_WARM_BOOT(unit)) {
    639         return(_bcm_th3_vlan_reinit(unit));
    640     } else
    641 #endif /* BCM_WARM_BOOT_SUPPORT */
    642     {
    643         bcm_vlan_data_t vd;
    644         bcm_pbmp_t      temp_pbmp;
    645 
    646         /*
    647          * Initialize hardware tables
    648          */
    649         BCM_PBMP_CLEAR(temp_pbmp);
    650         BCM_PBMP_ASSIGN(temp_pbmp, PBMP_ALL(unit));
    651 
    652         vd.vlan_tag = BCM_VLAN_DEFAULT;
    653         BCM_PBMP_ASSIGN(vd.port_bitmap, temp_pbmp);
    654         BCM_PBMP_REMOVE(vd.port_bitmap, PBMP_LB(unit));
    655         BCM_PBMP_ASSIGN(vd.ut_port_bitmap, temp_pbmp);
    656         BCM_PBMP_REMOVE(vd.ut_port_bitmap, PBMP_CMIC(unit));
    657         BCM_PBMP_REMOVE(vd.ut_port_bitmap, PBMP_LB(unit));
    658 
    659         /*
    660          * A compile-time application policy may prefer to not add
    661          * Ethernet or CPU ports to the default VLAN.
    662          */
    663 #ifdef  BCM_VLAN_NO_DEFAULT_ETHER
    664         BCM_PBMP_REMOVE(vd.port_bitmap, PBMP_E_ALL(unit));
    665         BCM_PBMP_REMOVE(vd.ut_port_bitmap, PBMP_E_ALL(unit));
    666 #endif  /* BCM_VLAN_NO_DEFAULT_ETHER */
    667 #ifdef  BCM_VLAN_NO_DEFAULT_CPU
    668         BCM_PBMP_REMOVE(vd.port_bitmap, PBMP_CMIC(unit));
    669 #endif  /* BCM_VLAN_NO_DEFAULT_CPU */
    670 
    671 #if defined(BCM_RCPU_SUPPORT)
    672         if (SOC_IS_RCPU_ONLY(unit) && vlan_info[unit].init) {
    673             bcm_vlan_t idx;
    674             soc_rcpu_cfg_t cfg;
    675 
    676             if (SOC_E_NONE != soc_cm_get_rcpu_cfg(unit, &cfg)) {
    677                 cfg.vlan = BCM_VLAN_INVALID;
    678             }
    679 
    680             /* Destroy previous VLANs */
    681             for (idx = BCM_VLAN_MIN; idx < BCM_VLAN_COUNT; idx++) {
    682                 if ((idx != vlan_info[unit].defl) &&
    683                     (idx != cfg.vlan) &&
    684                     (_BCM_VBMP_LOOKUP(vlan_info[unit].bmp, idx))) {
    685                     BCM_IF_ERROR_RETURN
    686                         (mbcm_driver[unit]->mbcm_vlan_destroy(unit, idx));
    687                 }
    688             }
    689         }
    690 #endif  /* BCM_RCPU_SUPPORT */
    691 
    692 #ifdef BCM_MCAST_FLOOD_DEFAULT
    693         BCM_IF_ERROR_RETURN
    694             (_bcm_esw_vlan_flood_default_set(unit, BCM_MCAST_FLOOD_DEFAULT));
    695 #else
    696         BCM_IF_ERROR_RETURN
    697             (_bcm_esw_vlan_flood_default_set(unit,
    698                                              BCM_VLAN_MCAST_FLOOD_UNKNOWN));
    699 #endif
    700 
    701         BCM_IF_ERROR_RETURN
    702             (mbcm_driver[unit]->mbcm_vlan_init(unit, &vd));
    703 
    704         /*
    705          * Initialize software structures
    706          */
    707         vi->defl = BCM_VLAN_DEFAULT;
    708 
    709 #ifdef BCM_WARM_BOOT_SUPPORT
    710         /* Warm boot level 2 cache size */
    711         /* Type for 'flood_mode' is an enum, which values fit in uint8 */
    712         vlan_scache_size = sizeof(vi->defl);/* Default VLAN */
    713         vlan_scache_size += sizeof(uint8);  /* Flood mode */
    714 
    715         SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_VLAN, 0);
    716         rv = _bcm_esw_scache_ptr_get(unit, scache_handle, TRUE,
    717                                      vlan_scache_size,
    718                                      &vlan_scache_ptr,
    719                                      BCM_WB_DEFAULT_VERSION, NULL);
    720         if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) {
    721             return rv;
    722         }
    723         rv = BCM_E_NONE;
    724 #endif /* BCM_WARM_BOOT_SUPPORT */
    725 
    726         /* In case bcm_vlan_init is called more than once */
    727         BCM_IF_ERROR_RETURN(_bcm_vbmp_init(&vi->bmp));
    728         _BCM_VBMP_INSERT(vi->bmp, vd.vlan_tag);
    729 
    730         BCM_IF_ERROR_RETURN(_bcm_vbmp_init(&vi->pre_cfg_bmp));
    731 
    732         /* Free vlan translation arrays if any as not supported. */
    733         if (NULL != vi->egr_trans) {
    734             sal_free(vi->egr_trans);
    735             vi->egr_trans = NULL;
    736         }
    737         if (NULL != vi->ing_trans) {
    738             sal_free(vi->ing_trans);
    739             vi->ing_trans = NULL;
    740         }
    741         vi->count = 1;
    742     }
    743 
    744     /*
    745      * Initialize Cross Connect Internal Database
    746      */
    747     BCM_IF_ERROR_RETURN(_bcm_th3_vlan_xconnect_db_init(unit));
    748 
    749     vi->init = TRUE;
    750 
    751 #if defined(BCM_RCPU_SUPPORT)
    752     if (SOC_IS_RCPU_ONLY(unit)) {
    753         soc_rcpu_cfg_t cfg;
    754         if (SOC_E_NONE == soc_cm_get_rcpu_cfg(unit, &cfg) &&
    755             BCM_VLAN_DEFAULT != cfg.vlan) {
    756             /*
    757              * RCPU vlan should have been created in remote device, sync
    758              * software status.
    759              */
    760             _BCM_VBMP_INSERT(vlan_info[unit].bmp, cfg.vlan);
    761             vlan_info[unit].count++;
    762         }
    763     }
    764 #endif  /* BCM_RCPU_SUPPORT */
    765 
    766     return rv;
    767 }
    768 
    769 /*
    770  * Function:
    771  *      bcm_vlan_detach
    772  *
    773  * Purpose:
    774  *      De-initialize the VLAN module.
    775  *
    776  * Parameters:
    777  *      unit - StrataSwitch PCI device unit number (driver internal).
    778  *
    779  * Returns:
    780  *      BCM_E_XXX
    781  *
    782  * Note:
    783  */
    784 int
    785 bcm_tomahawk3_vlan_detach(int unit)
    786 {
    787     bcm_vlan_info_t *vi = &vlan_info[unit];
    788     int rv = BCM_E_NONE;
    789 
    790     BCM_LOCK(unit);
    791 
    792     _bcm_vbmp_destroy(&vi->bmp);
    793     BCM_IF_ERROR_RETURN(_bcm_vbmp_destroy(&vi->pre_cfg_bmp));
    794 
    795     if (vi->egr_trans != NULL) {
    796         sal_free(vi->egr_trans);
    797         vi->egr_trans = NULL;
    798     }
    799     if (vi->ing_trans != NULL) {
    800         sal_free(vi->ing_trans);
    801         vi->ing_trans = NULL;
    802     }
    803 
    804     vi->init = 0;
    805 
    806 #if defined(BCM_FIREBOLT2_SUPPORT)
    807     if (soc_feature(unit, soc_feature_vlan_ctrl)) {
    808         rv = _bcm_xgs3_vlan_profile_detach(unit);
    809     }
    810 #endif /* BCM_FIREBOLT2_SUPPORT */
    811 
    812     BCM_IF_ERROR_RETURN(_bcm_th3_vlan_xconnect_db_destroy(unit));
    813 
    814     BCM_UNLOCK(unit);
    815     return rv;
    816 }
    817 
    818 /*
    819  * Function:
    820  *      bcm_vlan_port_add
    821  *
    822  * Purpose:
    823  *      Add ports to the specified vlan.
    824  *
    825  * Parameters:
    826  *      unit - StrataSwitch PCI device unit number (driver internal).
    827  *      vid - VLAN ID to add port to as a member.
    828  *      pbmp - port bitmap for members of VLAN
    829  *      ubmp - untagged members of VLAN
    830  *
    831  * Returns:
    832  *      BCM_E_NONE - Success.
    833  *      BCM_E_INTERNAL - Chip access failure.
    834  *      BCM_E_NOT_FOUND - VLAN ID not in use.
    835  *
    836  * Note:
    837  */
    838 int
    839 bcm_tomahawk3_vlan_port_add(int unit, bcm_vlan_t vid, pbmp_t pbmp, pbmp_t ubmp)
    840 {
    841     int                 rv = BCM_E_NONE;
    842     bcm_pbmp_t          pbm, ubm;
    843 
    844     CHECK_INIT_AND_VLAN_ID(unit, vid);
    845 
    846     BCM_PBMP_CLEAR(pbm);
    847     BCM_PBMP_CLEAR(ubm);
    848 
    849     /* we need to check if pbmp and ubmp are valid as well */
    850     BCM_PBMP_ASSIGN(pbm,PBMP_ALL(unit));
    851     BCM_PBMP_ASSIGN(ubm,PBMP_ALL(unit));
    852     BCM_PBMP_AND(pbm,pbmp);
    853     BCM_PBMP_AND(ubm,ubmp);
    854 
    855     if(!(BCM_PBMP_EQ(pbm, pbmp) && BCM_PBMP_EQ(ubm, ubmp))) {
    856         return BCM_E_PARAM;
    857     }
    858 
    859     LOG_VERBOSE(BSL_LS_BCM_VLAN,
    860                 (BSL_META_U(unit,
    861                             "VLAN %d: port add: vid %d. pbm 0x%x. upbm 0x%x\n"),
    862                  unit, vid, SOC_PBMP_WORD_GET(pbmp, 0),
    863                  SOC_PBMP_WORD_GET(ubmp, 0)));
    864 
    865     BCM_LOCK(unit);
    866     rv = _bcm_th3_vlan_port_add(unit, vid, pbmp, ubmp, pbmp, 0);
    867     BCM_UNLOCK(unit);
    868 
    869     return rv;
    870 }
    871 
    872 /*
    873  * Function:
    874  *      bcm_vlan_port_remove
    875  *
    876  * Purpose:
    877  *      Remove ports from a specified vlan.
    878  *
    879  * Parameters:
    880  *      unit - StrataSwitch PCI device unit number (driver internal).
    881  *      vid - VLAN ID to remove port(s) from.
    882  *      pbmp - port bitmap for ports to remove.
    883  *
    884  * Returns:
    885  *      BCM_E_NONE - Success.
    886  *      BCM_E_INTERNAL - Chip access failure.
    887  *      BCM_E_NOT_FOUND - VLAN ID not in use.
    888  *
    889  * Note:
    890  */
    891 int
    892 bcm_tomahawk3_vlan_port_remove(int unit, bcm_vlan_t vid, pbmp_t pbmp)
    893 {
    894     int rv = BCM_E_NONE;
    895 
    896     LOG_VERBOSE(BSL_LS_BCM_VLAN,
    897                 (BSL_META_U(unit,
    898                             "VLAN %d: port remove: vid %d. pbm 0x%x.\n"),
    899                  unit, vid, SOC_PBMP_WORD_GET(pbmp, 0)));
    900 
    901     CHECK_INIT_AND_VLAN_ID(unit, vid);
    902     /* As we are passing only one pbmp parameter to API bcm_vlan_port_remove,
    903      * the expected result is to remove same pbmp from PORT_BITMAPf, UT_BITMAPf
    904      * and ING_PORT_BITMAPf. Hence, same pbmp is passed as argument for ubmp
    905      * and ing_pbmp
    906      */
    907     BCM_LOCK(unit);
    908     rv = mbcm_driver[unit]->mbcm_vlan_port_remove(
    909                                 unit, vid, pbmp, pbmp, pbmp);
    910     BCM_UNLOCK(unit);
    911 
    912     return rv;
    913 }
    914 
    915 /*
    916  * Function:
    917  *      bcm_vlan_control_vlan_selective_get
    918  *
    919  * Purpose:
    920  *      Get per VLAN configuration.
    921  *
    922  * Parameters:
    923  *      unit     - (IN) StrataSwitch PCI device unit number (driver internal).
    924  *      vid      - (IN) VLAN to get the setting for.
    925  *      valid_fields - (IN) Valid fields for VLAN control
    926  *                          structure, BCM_VLAN_CONTROL_VLAN_XXX_MASK.
    927  *      control  - (OUT) VLAN control structure
    928  *
    929  * Returns:
    930  *      BCM_E_NONE - Success.
    931  *      BCM_E_XXX
    932  *
    933  * Note:
    934  */
    935 int
    936 bcm_tomahawk3_vlan_control_vlan_selective_get(int unit, bcm_vlan_t vlan,
    937                     uint32 valid_fields, bcm_vlan_control_vlan_t *control)
    938 {
    939     int rv = BCM_E_UNAVAIL;
    940 
    941     CHECK_INIT_AND_VLAN_ID(unit, vlan);
    942     if (NULL == control) {
    943         return (BCM_E_PARAM);
    944     }
    945 
    946     if (soc_feature(unit, soc_feature_vlan_ctrl)) {
    947 
    948         /* Check incoming fields validity for TH3 specific support */
    949         if (valid_fields & ~BCM_TH3_VLAN_CONTROL_VLAN_ALL_VALID_MASK) {
    950             return (BCM_E_PARAM);
    951         }
    952 
    953         BCM_LOCK(unit);
    954         rv = _bcm_xgs3_vlan_control_vlan_get(unit, vlan, valid_fields, control);
    955         BCM_UNLOCK(unit);
    956         /*
    957          * Clean the flag BCM_VLAN_L3_URPF_DEFAULT_ROUTE_CHECK_DISABLE from the
    958          * control->flags as URPF is not supported by TH3, but underlying layer
    959          * would check for the URPF support and if it does not find it, the
    960          * default outcome is chosen i.e. l3_urpf_default_route_check_disable.
    961          * However, for TH3 we do not want to provide this default flag to Appl.
    962          */
    963         control->flags &= ~BCM_VLAN_L3_URPF_DEFAULT_ROUTE_CHECK_DISABLE;
    964 
    965         /* Check for TH3 specific output validity */
    966         if (control->flags & ~BCM_TH3_VLAN_CONTROL_VLAN_SUPPORTED_CTRL_FLAGS) {
    967             return BCM_E_CONFIG;
    968         }
    969 
    970         if (valid_fields & BCM_VLAN_CONTROL_VLAN_FORWARDING_MODE_MASK) {
    971             if (control->forwarding_mode != bcmVlanForwardBridging &&
    972                 control->forwarding_mode != bcmVlanForwardSingleCrossConnect) {
    973 
    974                 return BCM_E_CONFIG;
    975             }
    976         }
    977     }
    978 
    979     return rv;
    980 }
    981 
    982 /*
    983  * Function:
    984  *      bcm_vlan_control_vlan_selective_set
    985  *
    986  * Purpose:
    987  *      Set per VLAN configuration.
    988  *
    989  * Parameters:
    990  *      unit    - (IN) StrataSwitch PCI device unit number (driver internal).
    991  *      vid     - (IN) VLAN to set the configuration for.
    992  *      valid_fields - (IN) Valid fields for VLAN control structure,
    993  *                           BCM_VLAN_CONTROL_VLAN_XXX_MASK.
    994  *      control - (IN) VLAN control structure
    995  *
    996  * Returns:
    997  *      BCM_E_NONE - Success.
    998  *      BCM_E_XXX
    999  *
   1000  * Note:
   1001  */
   1002 int
   1003 bcm_tomahawk3_vlan_control_vlan_selective_set(int unit, bcm_vlan_t vlan,
   1004                         uint32 valid_fields, bcm_vlan_control_vlan_t *control)
   1005 {
   1006     int rv = BCM_E_UNAVAIL;
   1007 
   1008     CHECK_INIT_AND_VLAN_ID(unit, vlan);
   1009 
   1010     /* Perform incoming parameter validity for TH3 device chip */
   1011     if (NULL == control) {
   1012         return (BCM_E_PARAM);
   1013     }
   1014 
   1015     if (valid_fields & ~BCM_TH3_VLAN_CONTROL_VLAN_ALL_VALID_MASK) {
   1016         return (BCM_E_PARAM);
   1017     }
   1018     if (control->flags & ~BCM_TH3_VLAN_CONTROL_VLAN_SUPPORTED_CTRL_FLAGS) {
   1019         return (BCM_E_PARAM);
   1020     }
   1021     if ((0 != control->learn_flags) || (0 != control->sr_flags)) {
   1022         return (BCM_E_PARAM);
   1023     }
   1024     if ((control->vrf > SOC_VRF_MAX(unit))) {
   1025         return (BCM_E_PARAM);
   1026     }
   1027     if (bcmVlanUrpfDisable != control->urpf_mode) {
   1028         return (BCM_E_PARAM);
   1029     }
   1030     if (valid_fields & BCM_VLAN_CONTROL_VLAN_FORWARDING_MODE_MASK) {
   1031         if ((control->forwarding_mode != bcmVlanForwardBridging) &&
   1032             (control->forwarding_mode != bcmVlanForwardSingleCrossConnect)) {
   1033             return (BCM_E_PARAM);
   1034         }
   1035     }
   1036 
   1037     if (soc_feature(unit, soc_feature_vlan_ctrl)) {
   1038         BCM_LOCK(unit);
   1039         rv = _bcm_xgs3_vlan_control_vlan_set(unit, vlan, valid_fields, control);
   1040         BCM_UNLOCK(unit);
   1041     }
   1042 
   1043     return rv;
   1044 }
   1045 
   1046 /*
   1047  * Function:
   1048  *      bcm_vlan_control_vlan_get
   1049  *
   1050  * Purpose:
   1051  *      Get all supported per VLAN configurations.
   1052  *
   1053  * Parameters:
   1054  *      unit    - (IN) StrataSwitch PCI device unit number (driver internal).
   1055  *      vid     - (IN) VLAN to get the setting for.
   1056  *      control - (OUT) VLAN control structure
   1057  *
   1058  * Returns:
   1059  *      BCM_E_NONE - Success.
   1060  *      BCM_E_XXX
   1061  *
   1062  * Note:
   1063  *      No checks are performed here as the callee function will do all checks
   1064  */
   1065 int
   1066 bcm_tomahawk3_vlan_control_vlan_get(int unit, bcm_vlan_t vid,
   1067                                     bcm_vlan_control_vlan_t *control)
   1068 {
   1069     return(
   1070         bcm_tomahawk3_vlan_control_vlan_selective_get(unit, vid,
   1071             (uint32)BCM_TH3_VLAN_CONTROL_VLAN_ALL_VALID_MASK, control));
   1072 }
   1073 
   1074 /*
   1075  * Function:
   1076  *      bcm_vlan_control_vlan_set
   1077  *
   1078  * Purpose:
   1079  *      Set per VLAN configuration.
   1080  *
   1081  * Parameters:
   1082  *      unit    - (IN) StrataSwitch PCI device unit number (driver internal).
   1083  *      vid     - (IN) VLAN to get the flood setting for.
   1084  *      control - (IN) VLAN control structure
   1085  *
   1086  * Returns:
   1087  *      BCM_E_NONE - Success.
   1088  *      BCM_E_XXX
   1089  *
   1090  * Note:
   1091  *      No checks are performed here as the callee function will do all checks
   1092  */
   1093 int
   1094 bcm_tomahawk3_vlan_control_vlan_set(int unit, bcm_vlan_t vid,
   1095                               /* coverity[pass_by_value] */
   1096                               bcm_vlan_control_vlan_t control)
   1097 {
   1098     return (
   1099         bcm_tomahawk3_vlan_control_vlan_selective_set(unit, vid,
   1100             (uint32)BCM_TH3_VLAN_CONTROL_VLAN_ALL_VALID_MASK, &control));
   1101 }
   1102 
   1103 /*
   1104  *   Function
   1105  *      bcm_vlan_vector_flags_set
   1106  *   Purpose
   1107  *      Set a one or more VLAN control vlan flags on a vlan_vector on this unit
   1108  *
   1109  *   Parameters
   1110  *      (in) int unit = unit number
   1111  *      (in) bcm_vlan_vector_t vlan_vector = Vlan vector for values to be set
   1112  *      (in) uint32 flags_mask
   1113  *      (in) uint32 flags_value
   1114  *
   1115  *   Returns
   1116  *      bcm_error_t = BCM_E_NONE if successful
   1117  *                    BCM_E_* appropriately if not
   1118  *
   1119  *   Note
   1120  */
   1121 int
   1122 bcm_tomahawk3_vlan_vector_flags_set(int unit,
   1123                               bcm_vlan_vector_t vlan_vector,
   1124                               uint32 flags_mask,
   1125                               uint32 flags_value)
   1126 {
   1127     int rv;
   1128 
   1129     bcm_vlan_t              vid;
   1130     bcm_vlan_control_vlan_t control;
   1131 
   1132     /* non-supported vector fields */
   1133     if (flags_mask & ~BCM_TH3_VLAN_CONTROL_VLAN_SUPPORTED_CTRL_FLAGS) {
   1134         return BCM_E_PARAM;
   1135     }
   1136 
   1137     /* Optimistically assume success from here */
   1138     rv = BCM_E_NONE;
   1139 
   1140     for (vid = BCM_VLAN_MIN + 1; vid < BCM_VLAN_MAX; vid++) {
   1141 
   1142         if (BCM_VLAN_VEC_GET(vlan_vector, vid)) {
   1143 
   1144             bcm_vlan_control_vlan_t_init(&control);
   1145 
   1146             rv = bcm_tomahawk3_vlan_control_vlan_selective_get(unit, vid,
   1147                     (uint32)BCM_TH3_VLAN_CONTROL_VLAN_ALL_VALID_MASK, &control);
   1148 
   1149             if (BCM_SUCCESS(rv)) {
   1150                 control.flags =
   1151                     (~flags_mask & control.flags) | (flags_mask & flags_value);
   1152 
   1153                 rv = bcm_tomahawk3_vlan_control_vlan_selective_set(
   1154                             unit,
   1155                             vid,
   1156                             (uint32)BCM_TH3_VLAN_CONTROL_VLAN_ALL_VALID_MASK,
   1157                             &control);
   1158                 if (BCM_FAILURE(rv)) {
   1159                     break;
   1160                 }
   1161             }
   1162         }
   1163     }
   1164     return rv;
   1165 }
   1166 
   1167 /*
   1168  * Function:
   1169  *     bcm_vlan_control_set
   1170  *
   1171  * Purpose:
   1172  *     Set miscellaneous VLAN-specific chip options
   1173  *
   1174  * Parameters:
   1175  *     unit - StrataSwitch PCI device unit number (driver internal).
   1176  *     type - A value from bcm_vlan_control_t enumeration list
   1177  *     arg  - state whose meaning is dependent on 'type'
   1178  *
   1179  * Returns:
   1180  *     BCM_E_NONE     - Success
   1181  *     BCM_E_INTERNAL - Chip access failure.
   1182  *     BCM_E_UNAVAIL  - type not supported on unit
   1183  *
   1184  * Note:
   1185  */
   1186 int
   1187 bcm_tomahawk3_vlan_control_set(int unit, bcm_vlan_control_t type, int arg)
   1188 {
   1189     uint32  data;
   1190     uint32  vlan_ctrl;
   1191 
   1192     LOG_VERBOSE(BSL_LS_BCM_VLAN,
   1193                 (BSL_META_U(unit,
   1194                             "VLAN %d: control set: type %d, arg %d\n"),
   1195                  unit, type, arg));
   1196 
   1197     if (SOC_IS_XGS3_FABRIC(unit)) {
   1198         return BCM_E_UNAVAIL;
   1199     }
   1200 
   1201     switch (type) {
   1202         case bcmVlanDropUnknown:
   1203             return bcm_esw_switch_control_port_set(unit,
   1204                                                    CMIC_PORT(unit),
   1205                                                    bcmSwitchUnknownVlanToCpu,
   1206                                                    !arg);
   1207         case bcmVlanShared:
   1208             arg = (arg ? 1 : 0);
   1209             SOC_IF_ERROR_RETURN(READ_VLAN_CTRLr(unit, &vlan_ctrl));
   1210             data = vlan_ctrl;
   1211             soc_reg_field_set(unit, VLAN_CTRLr, &vlan_ctrl,
   1212                               USE_LEARN_VIDf, arg);
   1213             if (data != vlan_ctrl) {
   1214                 SOC_IF_ERROR_RETURN(WRITE_VLAN_CTRLr(unit, vlan_ctrl));
   1215                 SOC_IF_ERROR_RETURN(
   1216                     soc_reg_field32_modify(unit,
   1217                         EGR_CONFIGr, CMIC_PORT(unit), USE_LEARN_VIDf, arg));
   1218             }
   1219             break;
   1220 
   1221         case bcmVlanSharedID:
   1222             VLAN_CHK_ID(unit, arg);
   1223             SOC_IF_ERROR_RETURN(READ_VLAN_CTRLr(unit, &vlan_ctrl));
   1224             data = vlan_ctrl;
   1225             soc_reg_field_set(unit, VLAN_CTRLr, &vlan_ctrl,
   1226                               LEARN_VIDf, arg);
   1227             if (data != vlan_ctrl) {
   1228                 SOC_IF_ERROR_RETURN(WRITE_VLAN_CTRLr(unit, vlan_ctrl));
   1229                 SOC_IF_ERROR_RETURN(
   1230                     soc_reg_field32_modify(unit,
   1231                         EGR_CONFIGr, CMIC_PORT(unit), LEARN_VIDf, arg));
   1232             }
   1233             break;
   1234 
   1235         default:
   1236             return BCM_E_UNAVAIL;
   1237     }
   1238 
   1239     return BCM_E_NONE;
   1240 }
   1241 
   1242 /*
   1243  * Function:
   1244  *     bcm_vlan_control_get
   1245  *
   1246  * Purpose:
   1247  *     Get miscellaneous VLAN-specific chip options
   1248  *
   1249  * Parameters:
   1250  *     unit - StrataSwitch PCI device unit number (driver internal).
   1251  *     type - A value from bcm_vlan_control_t enumeration list
   1252  *     arg  - (OUT) state whose meaning is dependent on 'type'
   1253  *
   1254  * Returns:
   1255  *     BCM_E_NONE     - Success
   1256  *     BCM_E_PARAM    - arg points to NULL
   1257  *     BCM_E_INTERNAL - Chip access failure.
   1258  *     BCM_E_UNAVAIL  - type not supported on unit
   1259  *
   1260  * Note:
   1261  */
   1262 int
   1263 bcm_tomahawk3_vlan_control_get(int unit, bcm_vlan_control_t type, int *arg)
   1264 {
   1265     int     rv = BCM_E_NONE;
   1266     uint32  vlan_ctrl;
   1267 
   1268     if (NULL == arg) {
   1269         return BCM_E_PARAM;
   1270     }
   1271 
   1272     if (SOC_IS_XGS3_FABRIC(unit)) {
   1273         return BCM_E_UNAVAIL;
   1274     }
   1275 
   1276     switch (type) {
   1277         case bcmVlanDropUnknown:
   1278             rv = bcm_esw_switch_control_port_get(unit,
   1279                                                  CMIC_PORT(unit),
   1280                                                  bcmSwitchUnknownVlanToCpu,
   1281                                                  arg);
   1282             if (BCM_SUCCESS(rv)) {
   1283                 *arg = !(*arg);
   1284             }
   1285             break;
   1286 
   1287         case bcmVlanShared:
   1288             SOC_IF_ERROR_RETURN(READ_VLAN_CTRLr(unit, &vlan_ctrl));
   1289             *arg = soc_reg_field_get(unit, VLAN_CTRLr,
   1290                                      vlan_ctrl, USE_LEARN_VIDf);
   1291             break;
   1292 
   1293         case bcmVlanSharedID:
   1294             SOC_IF_ERROR_RETURN(READ_VLAN_CTRLr(unit, &vlan_ctrl));
   1295             *arg = soc_reg_field_get(unit, VLAN_CTRLr,
   1296                                      vlan_ctrl, LEARN_VIDf);
   1297             break;
   1298 
   1299         default:
   1300             rv = BCM_E_UNAVAIL;
   1301             break;
   1302     }
   1303 
   1304     return rv;
   1305 }
   1306 
   1307 /*
   1308  * Function:
   1309  *     bcm_tomahawk3_vlan_control_port_set
   1310  *
   1311  * Purpose:
   1312  *     BCM dispatched API to set port based VLAN configuration.
   1313  *
   1314  * Parameters:
   1315  *     unit - (IN) StrataSwitch PCI device unit number (driver internal).
   1316  *     port - (IN) port/gport on which the VLAN configuration has to be applied
   1317  *     type - (IN) value from bcm_vlan_control_port_t enumeration list
   1318  *     arg - (IN) value to be set for the given type
   1319  *
   1320  * Returns:
   1321  *     BCM_E_NONE - Success
   1322  *     BCM_E_PORT - If the given port/gport is not supported for TH3 VLAN module
   1323  *     BCM_E_PARAM - Given arg or type is not supported for TH3
   1324  *     BCM_E_XXX - Other failures
   1325  *
   1326  * Note:
   1327  *     If the given port is -1 then apply the setting to all the local ports.
   1328  */
   1329 int
   1330 bcm_tomahawk3_vlan_control_port_set(int unit, bcm_port_t port,
   1331                               bcm_vlan_control_port_t type, int arg)
   1332 {
   1333     int rv = BCM_E_NONE;
   1334     bcm_pbmp_t temp_pbmp;
   1335 
   1336     if (-1 == port) {
   1337         BCM_PBMP_CLEAR(temp_pbmp);
   1338         BCM_PBMP_ASSIGN(temp_pbmp, PBMP_E_ALL(unit));
   1339 
   1340         /* Iterate through all local ports and apply the VLAN configuration */
   1341         PBMP_ITER(temp_pbmp, port) {
   1342             BCM_IF_ERROR_RETURN(
   1343                 _bcm_th3_vlan_control_port_config_command(
   1344                                 unit, port, type, BCM_TH3_SET, &arg));
   1345         }
   1346     } else {
   1347         /* Validate and resolve the given port parameter */
   1348         BCM_IF_ERROR_RETURN(
   1349                 _bcm_th3_vlan_control_port_resolve(unit, port, FALSE, &port));
   1350         rv =  _bcm_th3_vlan_control_port_config_command(
   1351                         unit, port, type, BCM_TH3_SET, &arg);
   1352     }
   1353     return rv;
   1354 }
   1355 
   1356 
   1357 /*
   1358  * Function:
   1359  *     bcm_tomahawk3_vlan_control_port_get
   1360  *
   1361  * Purpose:
   1362  *     BCM dispatched API to get port based VLAN configuration.
   1363  *
   1364  * Parameters:
   1365  *     unit - (IN) StrataSwitch PCI device unit number (driver internal).
   1366  *     port - (IN) port/gport for which the VLAN config has to be retrieved
   1367  *     type - (IN) value from bcm_vlan_control_port_t enumeration list
   1368  *     arg - (OUT) retrieved config value is to be stored in here
   1369  *
   1370  * Returns:
   1371  *     BCM_E_NONE - Success
   1372  *     BCM_E_PORT - If the given port/gport is not supported for TH3 VLAN module
   1373  *     BCM_E_PARAM - Given arg is NULL or type is not supported for TH3
   1374  *     BCM_E_XXX - Other failures
   1375  *
   1376  * Note:
   1377  */
   1378 int
   1379 bcm_tomahawk3_vlan_control_port_get(int unit, bcm_port_t port,
   1380                               bcm_vlan_control_port_t type, int *arg)
   1381 {
   1382     /* Validate and resolve the given port parameter */
   1383     BCM_IF_ERROR_RETURN(
   1384                 _bcm_th3_vlan_control_port_resolve(unit, port, FALSE, &port));
   1385 
   1386     return (_bcm_th3_vlan_control_port_config_command(
   1387                         unit, port, type, BCM_TH3_GET, arg));
   1388 }
   1389 
   1390 /*
   1391  * Function:
   1392  *      bcm_vlan_gport_add
   1393  *
   1394  * Purpose:
   1395  *      Add a Gport to the specified vlan.
   1396  *
   1397  * Parameters:
   1398  *      unit - (IN) StrataSwitch PCI device unit number (driver internal).
   1399  *      vlan - (IN) VLAN ID to retrieve the gport from.
   1400  *      gport - (IN) Gport to be deleted from the VLAN.
   1401  *      flags - (IN) VLAN_PORT flags qualifying the GPORT.
   1402  *
   1403  * Returns:
   1404  *      BCM_E_NONE - Success.
   1405  *      BCM_E_INIT - VLAN module is not initialized.
   1406  *      BCM_E_PARAM - Given parameter validation failed.
   1407  *      BCM_E_PORT - Given GPORT not supported.
   1408  *      BCM_E_NOT_FOUND - VLAN ID not in use.
   1409  *      BCM_E_XXX - Other failures
   1410  *
   1411  * Note:
   1412  */
   1413 int
   1414 bcm_tomahawk3_vlan_gport_add(
   1415     int unit, bcm_vlan_t vlan, bcm_gport_t gport, int flags)
   1416 {
   1417     int         rv;
   1418     bcm_pbmp_t  pbmp;
   1419     bcm_pbmp_t  ubmp;
   1420     bcm_pbmp_t  ing_pbmp;
   1421     bcm_port_t  local_port;
   1422 
   1423     /* Validate given VLAN ID */
   1424     CHECK_INIT_AND_VLAN_ID(unit, vlan);
   1425 
   1426     /* Validate and resolve the given gport parameter */
   1427     BCM_IF_ERROR_RETURN(
   1428         _bcm_th3_vlan_control_port_resolve(unit, gport, TRUE, &local_port));
   1429 
   1430     /* Validate the given flags */
   1431     if (flags & ~BCM_TH3_VLAN_GPORT_ADD_SUPPORTED_FLAGS) {
   1432         return BCM_E_PARAM;
   1433     }
   1434 
   1435     /* If EGRESS_L3_ONLY is set then check if it is supported */
   1436     if ((flags & BCM_VLAN_GPORT_ADD_EGRESS_L3_ONLY) &&
   1437         !soc_feature(unit, soc_feature_vlan_egress_membership_l3_only)) {
   1438         return BCM_E_UNAVAIL;
   1439     }
   1440 
   1441     /* Both EGRESS_ONLY and EGREE_L3_ONLY cannot be set */
   1442     if ((flags & BCM_VLAN_GPORT_ADD_EGRESS_ONLY) &&
   1443         (flags & BCM_VLAN_GPORT_ADD_EGRESS_L3_ONLY)) {
   1444         return BCM_E_PARAM;
   1445     }
   1446 
   1447     /* With INGRESS flag EGRESS_(L3)_ONLY or UNTAGGED flags cannot be set */
   1448     if (flags & BCM_VLAN_GPORT_ADD_INGRESS_ONLY) {
   1449         if (flags & BCM_VLAN_GPORT_ADD_UNTAGGED) {
   1450             return BCM_E_PARAM;
   1451         }
   1452 
   1453         if ((flags & BCM_VLAN_GPORT_ADD_EGRESS_ONLY) ||
   1454             (flags & BCM_VLAN_GPORT_ADD_EGRESS_L3_ONLY)) {
   1455             return BCM_E_PARAM;
   1456         }
   1457     }
   1458 
   1459     /* Based on the VLAN_GPORT_ADD flags form the port bitmaps appropriately */
   1460     if (flags &
   1461         (BCM_VLAN_GPORT_ADD_EGRESS_ONLY | BCM_VLAN_GPORT_ADD_EGRESS_L3_ONLY)) {
   1462         BCM_PBMP_CLEAR(ing_pbmp);
   1463     } else {
   1464         BCM_PBMP_PORT_SET(ing_pbmp, local_port);
   1465     }
   1466     if (flags & BCM_VLAN_GPORT_ADD_INGRESS_ONLY) {
   1467         BCM_PBMP_CLEAR(pbmp);
   1468     } else {
   1469         BCM_PBMP_PORT_SET(pbmp, local_port);
   1470     }
   1471     if (flags & BCM_VLAN_GPORT_ADD_UNTAGGED) {
   1472         BCM_PBMP_PORT_SET(ubmp, local_port);
   1473     } else {
   1474         BCM_PBMP_CLEAR(ubmp);
   1475     }
   1476 
   1477     /* Call low level routine to add the local physical port to the VLAN */
   1478     BCM_LOCK(unit);
   1479     rv = _bcm_th3_vlan_port_add(unit, vlan, pbmp, ubmp, ing_pbmp, flags);
   1480     BCM_UNLOCK(unit);
   1481 
   1482     return rv;
   1483 }
   1484 
   1485 /*
   1486  * Function:
   1487  *      bcm_vlan_gport_delete
   1488  *
   1489  * Purpose:
   1490  *      Delete a given Gport from the specified vlan.
   1491  *
   1492  * Parameters:
   1493  *      unit - (IN) StrataSwitch PCI device unit number (driver internal).
   1494  *      vlan - (IN) VLAN ID to retrieve the gport from.
   1495  *      gport - (IN) Gport to be deleted from the VLAN
   1496  *
   1497  * Returns:
   1498  *      BCM_E_NONE - Success.
   1499  *      BCM_E_INIT - VLAN module is not initialized.
   1500  *      BCM_E_PARAM - Given parameter validation failed.
   1501  *      BCM_E_PORT - Given GPORT not supported.
   1502  *      BCM_E_NOT_FOUND - VLAN ID not in use.
   1503  *      BCM_E_XXX - Other failures
   1504  *
   1505  * Note:
   1506  */
   1507 int
   1508 bcm_tomahawk3_vlan_gport_delete(int unit, bcm_vlan_t vlan, bcm_gport_t gport)
   1509 {
   1510     int         rv;
   1511     bcm_pbmp_t  pbmp;
   1512     bcm_port_t  local_port;
   1513 
   1514     /* Validate given VLAN ID */
   1515     CHECK_INIT_AND_VLAN_ID(unit, vlan);
   1516 
   1517     /* Validate and resolve the given gport parameter */
   1518     BCM_IF_ERROR_RETURN(
   1519         _bcm_th3_vlan_control_port_resolve(unit, gport, TRUE, &local_port));
   1520 
   1521     /* Create a port bitmap from the retrieved local physical port */
   1522     BCM_PBMP_CLEAR(pbmp);
   1523     BCM_PBMP_PORT_ADD(pbmp, local_port);
   1524 
   1525     /* Call low level routine to remove the retrieved local phys port */
   1526     BCM_LOCK(unit);
   1527     /* As we are passing only one pbmp parameter to API bcm_vlan_port_remove,
   1528      * the expected result is to remove same pbmp from PORT_BITMAPf, UT_BITMAPf
   1529      * and ING_PORT_BITMAPf. Hence, same pbmp is passed as argument for ubmp
   1530      * and ing_pbmp
   1531      */
   1532     rv = mbcm_driver[unit]->mbcm_vlan_port_remove(
   1533                                 unit, vlan, pbmp, pbmp, pbmp);
   1534     BCM_UNLOCK(unit);
   1535 
   1536     return rv;
   1537 }
   1538 
   1539 /*
   1540  * Function:
   1541  *      bcm_vlan_gport_extended_delete
   1542  *
   1543  * Purpose:
   1544  *      Delete the Gport qualified by the given VLAN_PORT
   1545  *      flags from the specified vlan.
   1546  *
   1547  * Parameters:
   1548  *      unit - (IN) StrataSwitch PCI device unit number (driver internal).
   1549  *      vlan - (IN) VLAN ID to retrieve the gport from.
   1550  *      gport - (IN) Gport to be deleted from the VLAN
   1551  *      flags - (IN) VLAN_PORT flags qualifying the GPORT.
   1552  *
   1553  * Returns:
   1554  *      BCM_E_NONE - Success.
   1555  *      BCM_E_INIT - VLAN module is not initialized.
   1556  *      BCM_E_PARAM - Given parameter validation failed.
   1557  *      BCM_E_PORT - Given GPORT not supported.
   1558  *      BCM_E_NOT_FOUND - VLAN ID not in use.
   1559  *      BCM_E_XXX - Other failures
   1560  *
   1561  * Note:
   1562  */
   1563 int
   1564 bcm_tomahawk3_vlan_gport_extended_delete(
   1565     int unit, bcm_vlan_t vlan, bcm_gport_t gport, int flags)
   1566 {
   1567     int         rv;
   1568     bcm_pbmp_t  pbmp;
   1569     bcm_pbmp_t  ubmp;
   1570     bcm_pbmp_t  ing_pbmp;
   1571     bcm_port_t  local_port;
   1572 
   1573     /* Validate given VLAN ID */
   1574     CHECK_INIT_AND_VLAN_ID(unit, vlan);
   1575 
   1576     /* Validate and resolve the given gport parameter */
   1577     BCM_IF_ERROR_RETURN(
   1578         _bcm_th3_vlan_control_port_resolve(unit, gport, TRUE, &local_port));
   1579 
   1580     /* Validate the given flags */
   1581     if (flags & ~BCM_TH3_VLAN_GPORT_ADD_SUPPORTED_FLAGS) {
   1582         return BCM_E_PARAM;
   1583     }
   1584 
   1585     if (flags & BCM_VLAN_GPORT_ADD_EGRESS_L3_ONLY) {
   1586         if (!soc_feature(unit, soc_feature_vlan_egress_membership_l3_only)) {
   1587             return BCM_E_PARAM;
   1588         }
   1589     }
   1590 
   1591     if (flags &
   1592         (BCM_VLAN_PORT_EGRESS_ONLY | BCM_VLAN_GPORT_ADD_EGRESS_L3_ONLY)) {
   1593         BCM_PBMP_CLEAR(ing_pbmp);
   1594     } else {
   1595         BCM_PBMP_PORT_SET(ing_pbmp, local_port);
   1596     }
   1597     if (flags & BCM_VLAN_PORT_INGRESS_ONLY) {
   1598         BCM_PBMP_CLEAR(pbmp);
   1599     } else {
   1600         BCM_PBMP_PORT_SET(pbmp, local_port);
   1601     }
   1602     if (flags & BCM_VLAN_PORT_UNTAGGED) {
   1603         BCM_PBMP_PORT_SET(ubmp, local_port);
   1604     } else {
   1605         BCM_PBMP_CLEAR(ubmp);
   1606     }
   1607 
   1608     /* Call low level routine to remove the retrieved local phys port */
   1609     BCM_LOCK(unit);
   1610     rv = mbcm_driver[unit]->mbcm_vlan_port_remove(
   1611                                 unit, vlan, pbmp, ubmp, ing_pbmp);
   1612     BCM_UNLOCK(unit);
   1613 
   1614     return rv;
   1615 }
   1616 
   1617 /*
   1618  * Function:
   1619  *      bcm_vlan_gport_delete_all
   1620  *
   1621  * Purpose:
   1622  *      Delete all Gports from the specified vlan.
   1623  *
   1624  * Parameters:
   1625  *      unit - (IN) StrataSwitch PCI device unit number (driver internal).
   1626  *      vlan - (IN) VLAN ID to retrieve the gport from.
   1627  *
   1628  * Returns:
   1629  *      BCM_E_NONE - Success.
   1630  *      BCM_E_INIT - VLAN module is not initialized.
   1631  *      BCM_E_PARAM - Given parameter validation failed.
   1632  *      BCM_E_NOT_FOUND - VLAN ID not in use.
   1633  *      BCM_E_XXX - Other failures
   1634  *
   1635  * Note:
   1636  */
   1637 int
   1638 bcm_tomahawk3_vlan_gport_delete_all(int unit, bcm_vlan_t vlan)
   1639 {
   1640     int         rv;
   1641     bcm_pbmp_t  pbmp;
   1642     bcm_pbmp_t  ubmp;
   1643     bcm_pbmp_t  ing_pbmp;
   1644 
   1645     /* Validate given VLAN ID */
   1646     CHECK_INIT_AND_VLAN_ID(unit, vlan);
   1647 
   1648     /* Retrieve all local physical ports bound to the given VLAN */
   1649     BCM_IF_ERROR_RETURN(
   1650         _bcm_th3_vlan_port_get(unit, vlan, &pbmp, &ubmp, &ing_pbmp));
   1651 
   1652     LOG_VERBOSE(BSL_LS_BCM_VLAN,
   1653                 (BSL_META_U(unit,
   1654                  "Vlan %d: gport rem all: pbm 0x%x, upbm 0x%x.\n"), vlan,
   1655                  SOC_PBMP_WORD_GET(pbmp, 0), SOC_PBMP_WORD_GET(ubmp, 0)));
   1656 
   1657     /* Call low level routine to remove all local physical ports */
   1658     BCM_LOCK(unit);
   1659     rv = mbcm_driver[unit]->
   1660             mbcm_vlan_port_remove(unit, vlan, pbmp, ubmp, ing_pbmp);
   1661     BCM_UNLOCK(unit);
   1662 
   1663     return rv;
   1664 }
   1665 
   1666 /*
   1667  * Function:
   1668  *      bcm_vlan_gport_get
   1669  *
   1670  * Purpose:
   1671  *      Retrieve VLAN_PORT flags for the given Gport on the specified vlan.
   1672  *
   1673  * Parameters:
   1674  *      unit - (IN) StrataSwitch PCI device unit number (driver internal).
   1675  *      vlan - (IN) VLAN ID to retrieve the gport and its flags from.
   1676  *      port - (IN) Gport for which the flags are to be retrieved.
   1677  *      flags - (OUT) VLAN_PORT flags to be stored here.
   1678  *
   1679  * Returns:
   1680  *      BCM_E_NONE - Success.
   1681  *      BCM_E_INIT - VLAN module is not initialized.
   1682  *      BCM_E_PARAM - Given parameter validation failed.
   1683  *      BCM_E_PORT - Not supported Gport.
   1684  *      BCM_E_NOT_FOUND - VLAN ID not in use or invalid flags on the VLAN.
   1685  *      BCM_E_XXX - Other failures
   1686  *
   1687  * Note:
   1688  */
   1689 int
   1690 bcm_tomahawk3_vlan_gport_get(
   1691     int unit, bcm_vlan_t vlan, bcm_gport_t gport, int *flags)
   1692 {
   1693     uint32      local_flags = 0;
   1694     bcm_pbmp_t  pbmp;
   1695     bcm_pbmp_t  ubmp;
   1696     bcm_pbmp_t  ing_pbmp;
   1697     bcm_port_t  local_port;
   1698 
   1699     /* Validate given VLAN ID */
   1700     CHECK_INIT_AND_VLAN_ID(unit, vlan);
   1701 
   1702     /* Validate other input parameters */
   1703     if (NULL == flags) {
   1704         return BCM_E_PARAM;
   1705     }
   1706 
   1707     /* Validate and resolve the given gport parameter */
   1708     BCM_IF_ERROR_RETURN(
   1709         _bcm_th3_vlan_control_port_resolve(unit, gport, TRUE, &local_port));
   1710 
   1711     /* Retrieve all local physical ports bound to the given VLAN */
   1712     BCM_IF_ERROR_RETURN(
   1713         _bcm_th3_vlan_port_get(unit, vlan, &pbmp, &ubmp, &ing_pbmp));
   1714 
   1715     /* Deduce the VLAN_PORT flags */
   1716     if (!BCM_PBMP_MEMBER(pbmp, local_port)) {
   1717         local_flags |= BCM_VLAN_PORT_INGRESS_ONLY;
   1718     }
   1719     if (!BCM_PBMP_MEMBER(ing_pbmp, local_port)) {
   1720         local_flags |= BCM_VLAN_PORT_EGRESS_ONLY;
   1721     }
   1722     if (local_flags ==
   1723         (BCM_VLAN_PORT_INGRESS_ONLY | BCM_VLAN_PORT_EGRESS_ONLY)) {
   1724         return BCM_E_NOT_FOUND;
   1725     }
   1726     if (BCM_PBMP_MEMBER(ubmp, local_port)) {
   1727         local_flags |= BCM_VLAN_PORT_UNTAGGED;
   1728     }
   1729     if ((local_flags & BCM_VLAN_PORT_EGRESS_ONLY) &&
   1730         soc_feature(unit, soc_feature_vlan_egress_membership_l3_only)) {
   1731 
   1732         BCM_PBMP_CLEAR(pbmp);
   1733         BCM_IF_ERROR_RETURN(
   1734             _bcm_xgs3_vlan_table_port_get(
   1735                 unit, vlan, &pbmp, NULL, NULL, VLAN_2_TABm));
   1736 
   1737         if (!BCM_PBMP_MEMBER(pbmp, local_port)) {
   1738             local_flags &= ~BCM_VLAN_PORT_EGRESS_ONLY;
   1739             local_flags |= BCM_VLAN_GPORT_ADD_EGRESS_L3_ONLY;
   1740         }
   1741     }
   1742 
   1743     /* Store the scrutinized Flags value */
   1744     *flags = local_flags;
   1745     return BCM_E_NONE;
   1746 }
   1747 
   1748 /*
   1749  * Function:
   1750  *      bcm_vlan_gport_get_all
   1751  *
   1752  * Purpose:
   1753  *      Retrieve VLAN_PORT flags for all Gports from the specified vlan.
   1754  *
   1755  * Parameters:
   1756  *      unit - (IN) StrataSwitch PCI device unit number (driver internal).
   1757  *      vlan - (IN) VLAN ID to retrieve all gports from.
   1758  *      array_max - (IN) Max slize for the provided arrays.
   1759  *      gport_array - (OUT) Array to be stored with the gports.
   1760  *      flags_array - (OUT) Array to be stored with VLAN_PORT flags.
   1761  *      array_size - (OUT) Number of retrieved gports.
   1762  *
   1763  * Returns:
   1764  *      BCM_E_NONE - Success.
   1765  *      BCM_E_INIT - VLAN module is not initialized.
   1766  *      BCM_E_PARAM - Given parameter validation failed.
   1767  *      BCM_E_NOT_FOUND - VLAN ID not in use or no gports on the VLAN.
   1768  *      BCM_E_XXX - Other failures
   1769  *
   1770  * Note:
   1771  *     1)  Parameter 'array_max' should be passed with positive value.
   1772  *     2)  Paremeter 'gport_array' and 'flags_array' are optional. If not
   1773  *          given then API would just return number of gports atatched to
   1774  *          the given VLAN. If either of the parameter is given then that
   1775  *          information is filled in by the API.
   1776  */
   1777 int
   1778 bcm_tomahawk3_vlan_gport_get_all(int unit, bcm_vlan_t vlan,
   1779     int array_max, bcm_gport_t *gport_array, int *flags_array, int* array_size)
   1780 {
   1781     int                 rv = BCM_E_NONE;
   1782     int                 local_modid;
   1783     int                 port_cnt = 0;
   1784     uint32              local_flags = 0;
   1785     bcm_pbmp_t          bmp;
   1786     bcm_pbmp_t          pbmp;
   1787     bcm_pbmp_t          ubmp;
   1788     bcm_pbmp_t          ing_pbmp;
   1789     bcm_port_t          port;
   1790     bcm_gport_t         gport;
   1791     _bcm_gport_dest_t   gport_dest;
   1792 
   1793     /* Validate given VLAN ID */
   1794     CHECK_INIT_AND_VLAN_ID(unit, vlan);
   1795 
   1796     /* Validate other incoming parameters */
   1797     if ((NULL == array_size) || (array_max <= 0)) {
   1798         return BCM_E_PARAM;
   1799     }
   1800 
   1801     /* Retrieve the local mod id */
   1802     BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &local_modid));
   1803 
   1804     /* Retrieve the local physical ports bound to the given VLAN */
   1805     BCM_IF_ERROR_RETURN(
   1806         _bcm_th3_vlan_port_get(unit, vlan, &pbmp, &ubmp, &ing_pbmp));
   1807 
   1808     /* Prepare a superset of bitmaps to iterate over */
   1809     BCM_PBMP_ASSIGN(bmp, pbmp);
   1810     BCM_PBMP_OR(bmp, ubmp);
   1811     BCM_PBMP_OR(bmp, ing_pbmp);
   1812 
   1813     /* Iterate through the list of ports from superset */
   1814     BCM_PBMP_ITER(bmp, port) {
   1815 
   1816         /* Check for boundary conditions */
   1817         if ((port_cnt == array_max) && gport_array) {
   1818             break;
   1819         }
   1820 
   1821         /* Formulate the MODPORT gport from the chosen local port */
   1822         gport_dest.port = port;
   1823         gport_dest.modid = local_modid;
   1824         gport_dest.gport_type = _SHR_GPORT_TYPE_MODPORT;
   1825         BCM_IF_ERROR_RETURN(
   1826             _bcm_esw_gport_construct(unit, &gport_dest, &gport));
   1827 
   1828         /* Deduce the VLAN_PORT flags */
   1829         local_flags = 0;
   1830         if (!BCM_PBMP_MEMBER(pbmp, port)) {
   1831             local_flags |= BCM_VLAN_PORT_INGRESS_ONLY;
   1832         }
   1833         if (!BCM_PBMP_MEMBER(ing_pbmp, port)) {
   1834             local_flags |= BCM_VLAN_PORT_EGRESS_ONLY;
   1835         }
   1836         if (local_flags ==
   1837             (BCM_VLAN_PORT_INGRESS_ONLY | BCM_VLAN_PORT_EGRESS_ONLY)) {
   1838             continue;
   1839         }
   1840 
   1841         /* Fill in the flags for the chosen port, if the flags_array given */
   1842         if (flags_array) {
   1843             if (BCM_PBMP_MEMBER(ubmp, port)) {
   1844                 local_flags |= BCM_VLAN_PORT_UNTAGGED;
   1845             }
   1846             flags_array[port_cnt] = local_flags;
   1847         }
   1848 
   1849         /* Fill in the gport for the chosen port, if the gport_array given */
   1850         if (gport_array) {
   1851             gport_array[port_cnt] = gport;
   1852         }
   1853 
   1854         port_cnt++;
   1855     }
   1856 
   1857     /* If all attempts found nothing return not found */
   1858     if (port_cnt) {
   1859         *array_size = port_cnt;
   1860     } else {
   1861         rv = BCM_E_NOT_FOUND;
   1862     }
   1863 
   1864     return rv;
   1865 }
   1866 
   1867 /*
   1868  * Function:
   1869  *      bcm_vlan_port_default_action_set
   1870  *
   1871  * Purpose:
   1872  *      Set the port's default vlan tag actions
   1873  *
   1874  * Parameters:
   1875  *      unit    - (IN) BCM unit.
   1876  *      port    - (IN) Port number (Gport or Local).
   1877  *      action  - (IN) Vlan tag actions
   1878  *
   1879  * Returns:
   1880  *      BCM_E_XXX
   1881  *
   1882  * Note:
   1883  */
   1884 int
   1885 bcm_tomahawk3_vlan_port_default_action_set(
   1886     int unit, bcm_port_t port, bcm_vlan_action_set_t *action)
   1887 {
   1888     return(
   1889         _bcm_th3_ing_vlan_tag_action_command(unit, port, BCM_TH3_SET, action));
   1890 }
   1891 
   1892 /*
   1893  * Function:
   1894  *      bcm_vlan_port_default_action_get
   1895  *
   1896  * Purpose:
   1897  *      Get the port's default vlan tag actions
   1898  *
   1899  * Parameters:
   1900  *      unit    - (IN) BCM unit.
   1901  *      port    - (IN) Port number.
   1902  *      action  - (OUT) Vlan tag actions
   1903  *
   1904  * Returns:
   1905  *      BCM_E_XXX
   1906  *
   1907  * Note:
   1908  */
   1909 int
   1910 bcm_tomahawk3_vlan_port_default_action_get(
   1911     int unit, bcm_port_t port, bcm_vlan_action_set_t *action)
   1912 {
   1913     return(
   1914         _bcm_th3_ing_vlan_tag_action_command(unit, port, BCM_TH3_GET, action));
   1915 }
   1916 
   1917 /*
   1918  * Function:
   1919  *      bcm_vlan_port_default_action_delete
   1920  *
   1921  * Purpose:
   1922  *      Delete the port's default vlan tag actions
   1923  *
   1924  * Parameters:
   1925  *      unit    - (IN) BCM unit.
   1926  *      port    - (IN) Port number.
   1927  *
   1928  * Returns:
   1929  *      BCM_E_XXX
   1930  *
   1931  * Note:
   1932  */
   1933 int
   1934 bcm_tomahawk3_vlan_port_default_action_delete(int unit, bcm_port_t port)
   1935 {
   1936     return(_bcm_th3_ing_vlan_tag_action_command(unit, port, BCM_TH3_DEL, NULL));
   1937 }
   1938 
   1939 /*
   1940  * Function:
   1941  *      bcm_vlan_port_egress_default_action_set
   1942  *
   1943  * Purpose:
   1944  *      Set the egress port's default vlan tag actions
   1945  *
   1946  * Parameters:
   1947  *      unit    - (IN) BCM unit.
   1948  *      port    - (IN) Port number (Gport or Local).
   1949  *      action  - (IN) Vlan tag actions
   1950  *
   1951  * Returns:
   1952  *      BCM_E_XXX
   1953  *
   1954  * Note:
   1955  */
   1956 int
   1957 bcm_tomahawk3_vlan_port_egress_default_action_set(
   1958     int unit, bcm_port_t port, bcm_vlan_action_set_t *action)
   1959 {
   1960     return(
   1961         _bcm_th3_egr_vlan_tag_action_command(unit, port, BCM_TH3_SET, action));
   1962 }
   1963 
   1964 /*
   1965  * Function:
   1966  *      bcm_vlan_port_egress_default_action_get
   1967  *
   1968  * Purpose:
   1969  *      Get the port's egress default vlan tag actions
   1970  *
   1971  * Parameters:
   1972  *      unit    - (IN) BCM unit.
   1973  *      port    - (IN) Port number.
   1974  *      action  - (OUT) Vlan tag actions
   1975  *
   1976  * Returns:
   1977  *      BCM_E_XXX
   1978  *
   1979  * Note:
   1980  */
   1981 int
   1982 bcm_tomahawk3_vlan_port_egress_default_action_get(
   1983     int unit, bcm_port_t port, bcm_vlan_action_set_t *action)
   1984 {
   1985     return(
   1986         _bcm_th3_egr_vlan_tag_action_command(unit, port, BCM_TH3_GET, action));
   1987 }
   1988 
   1989 /*
   1990  * Function:
   1991  *      bcm_vlan_port_egress_default_action_delete
   1992  *
   1993  * Purpose:
   1994  *      Delete the port's egress default vlan tag actions
   1995  *
   1996  * Parameters:
   1997  *      unit    - (IN) BCM unit.
   1998  *      port    - (IN) Port number.
   1999  *
   2000  * Returns:
   2001  *      BCM_E_XXX
   2002  *
   2003  * Note:
   2004  */
   2005 int
   2006 bcm_tomahawk3_vlan_port_egress_default_action_delete(int unit, bcm_port_t port)
   2007 {
   2008     return _bcm_th3_egr_vlan_tag_action_command(unit, port, BCM_TH3_DEL, NULL);
   2009 }
   2010 
   2011 /*
   2012  * Function:
   2013  *      bcm_vlan_cross_connect_add
   2014  *
   2015  * Purpose:
   2016  *      Add a VLAN cross connect entry
   2017  *
   2018  * Parameters:
   2019  *      unit       - (IN) BCM unit.
   2020  *      outer_vlan - (IN) Outer vlan ID
   2021  *      inner_vlan - (IN) Inner vlan ID
   2022  *      port_1     - (IN) First port in the cross-connect
   2023  *      port_2     - (IN) Second port in the cross-connect
   2024  *
   2025  * Returns:
   2026  *      BCM_E_NONE - Success.
   2027  *      BCM_E_PARAM - Vlan IDs are invalid
   2028  *      BCM_E_PORT - Given gports are invalid or not supported
   2029  *      BCM_E_XXX - Other failures
   2030  *
   2031  * Note:
   2032  */
   2033 int
   2034 bcm_tomahawk3_vlan_cross_connect_add(int unit, bcm_vlan_t outer_vlan,
   2035         bcm_vlan_t inner_vlan, bcm_gport_t port_1, bcm_gport_t port_2)
   2036 {
   2037     int     rv;
   2038     int     dest_val[2];
   2039     uint8   is_trunk_gport[2] = {0, 0};
   2040 
   2041     /* Validate if the VLAN module has been initialized */
   2042     CHECK_INIT(unit);
   2043 
   2044     /* Validate the outer and inner VLAN ID values */
   2045     if (BCM_VLAN_INVALID != inner_vlan) {
   2046         return BCM_E_UNAVAIL;
   2047     }
   2048 
   2049     if ((outer_vlan < BCM_VLAN_DEFAULT) || (outer_vlan > BCM_VLAN_MAX)) {
   2050         return BCM_E_PARAM;
   2051     }
   2052 
   2053     /* Validate and resolve the given gport parameters */
   2054     rv = _bcm_th3_vlan_control_port_resolve(unit, port_1, TRUE, &dest_val[0]);
   2055 
   2056     if (BCM_E_NONE != rv) {
   2057         /* _bcm_th3_vlan_control_port_resolve does not check for Trunk
   2058          * GPORT. Check for it explicitly and retrieve the trunk ID
   2059          */
   2060         if (BCM_GPORT_IS_TRUNK(port_1)) {
   2061             is_trunk_gport[0] = 1;
   2062             dest_val[0] = BCM_GPORT_TRUNK_GET(port_1);
   2063         } else {
   2064             return rv;
   2065         }
   2066     }
   2067 
   2068     rv =  _bcm_th3_vlan_control_port_resolve(unit, port_2, TRUE, &dest_val[1]);
   2069     if (BCM_E_NONE != rv) {
   2070         /* _bcm_th3_vlan_control_port_resolve does not check for Trunk
   2071          * GPORT. Check for it explicitly and retrieve the trunk ID
   2072          */
   2073         if (BCM_GPORT_IS_TRUNK(port_2)) {
   2074             is_trunk_gport[1] = 1;
   2075             dest_val[1] = BCM_GPORT_TRUNK_GET(port_2);
   2076         } else {
   2077             return rv;
   2078         }
   2079     }
   2080 
   2081     return _bcm_th3_vlan_xconnect_db_entry_add(
   2082                 unit, outer_vlan, is_trunk_gport, dest_val);
   2083 }
   2084 
   2085 /*
   2086  * Function:
   2087  *      bcm_vlan_cross_connect_delete
   2088  *
   2089  * Purpose:
   2090  *      Delete a VLAN cross connect entry
   2091  *
   2092  * Parameters:
   2093  *      unit       - (IN) BCM unit.
   2094  *      outer_vlan - (IN) Outer vlan ID
   2095  *      inner_vlan - (IN) Inner vlan ID
   2096  *
   2097  * Returns:
   2098  *      BCM_E_NONE - Success.
   2099  *      BCM_E_PARAM - Vlan IDs are invalid
   2100  *      BCM_E_XXX - Other failures
   2101  *
   2102  * Note:
   2103  */
   2104 int
   2105 bcm_tomahawk3_vlan_cross_connect_delete(
   2106         int unit, bcm_vlan_t outer_vlan, bcm_vlan_t inner_vlan)
   2107 {
   2108     /* Validate if the VLAN module has been initialized */
   2109     CHECK_INIT(unit);
   2110 
   2111     /* Validate the inner VLAN ID value */
   2112     if (BCM_VLAN_INVALID != inner_vlan) {
   2113         return BCM_E_UNAVAIL;
   2114     }
   2115 
   2116     return _bcm_th3_vlan_xconnect_db_entry_delete(unit, outer_vlan);
   2117 }
   2118 
   2119 /*
   2120  * Function:
   2121  *      bcm_vlan_cross_connect_delete_all
   2122  *
   2123  * Purpose:
   2124  *      Delete all VLAN cross connect entries
   2125  *
   2126  * Parameters:
   2127  *      unit       - (IN) BCM unit.
   2128  *
   2129  * Returns:
   2130  *      BCM_E_NONE - Success.
   2131  *      BCM_E_XXX - Other failures
   2132  *
   2133  * Note:
   2134  */
   2135 int
   2136 bcm_tomahawk3_vlan_cross_connect_delete_all(int unit)
   2137 {
   2138     /* Validate if the VLAN module has been initialized */
   2139     CHECK_INIT(unit);
   2140 
   2141     return _bcm_th3_vlan_xconnect_db_entry_delete_all(unit);
   2142 }
   2143 
   2144 /*
   2145  * Function:
   2146  *      bcm_vlan_cross_connect_traverse
   2147  *
   2148  * Purpose:
   2149  *      Walks through the valid cross connect entries and calls
   2150  *      the user supplied callback function for each entry.
   2151  *
   2152  * Parameters:
   2153  *      unit       - (IN) BCM unit.
   2154  *      cb         - (IN) Callback function.
   2155  *      user_data  - (IN) User data to be passed to callback function.
   2156  *
   2157  * Returns:
   2158  *      BCM_E_NONE - Success.
   2159  *      BCM_E_PARAM - Call back function not provided
   2160  *      BCM_E_XXX - Other failures
   2161  *
   2162  * Note:
   2163  */
   2164 int
   2165 bcm_tomahawk3_vlan_cross_connect_traverse(int unit,
   2166                                     bcm_vlan_cross_connect_traverse_cb cb,
   2167                                     void *user_data)
   2168 {
   2169     /* Validate if the VLAN module has been initialized */
   2170     CHECK_INIT(unit);
   2171 
   2172     if (NULL == cb) {
   2173         return BCM_E_PARAM;
   2174     }
   2175 
   2176     return _bcm_th3_vlan_xconnect_traverse(unit, cb, user_data);
   2177 }
   2178 
   2179 #endif /* BCM_TOMAHAWK3_SUPPORT */