diff options
author | Brett Creeley <brett.creeley@intel.com> | 2021-12-02 08:38:46 -0800 |
---|---|---|
committer | Tony Nguyen <anthony.l.nguyen@intel.com> | 2022-02-09 09:24:45 -0800 |
commit | c31af68a1b94d003358c00f53ba3f06606c33336 (patch) | |
tree | 07b8efc3760c9f908a9410b6c9483dbeee0bbfc6 /drivers/net/ethernet/intel/ice/ice_main.c | |
parent | 7bd527aa174f80d3d9879d28073c2c944ec7df38 (diff) | |
download | lwn-c31af68a1b94d003358c00f53ba3f06606c33336.tar.gz lwn-c31af68a1b94d003358c00f53ba3f06606c33336.zip |
ice: Add outer_vlan_ops and VSI specific VLAN ops implementations
Add a new outer_vlan_ops member to the ice_vsi structure as outer VLAN
ops are only available when the device is in Double VLAN Mode (DVM).
Depending on the VSI type, the requirements for what operations to
use/allow differ.
By default all VSI's have unsupported inner and outer VSI VLAN ops. This
implementation was chosen to prevent unexpected crashes due to null
pointer dereferences. Instead, if a VSI calls an unsupported op, it will
just return -EOPNOTSUPP.
Add implementations to support modifying outer VLAN fields for VSI
context. This includes the ability to modify VLAN stripping, insertion,
and the port VLAN based on the outer VLAN handling fields of the VSI
context.
These functions should only ever be used if DVM is enabled because that
means the firmware supports the outer VLAN fields in the VSI context. If
the device is in DVM, then always use the outer_vlan_ops, else use the
vlan_ops since the device is in Single VLAN Mode (SVM).
Also, move adding the untagged VLAN 0 filter from ice_vsi_setup() to
ice_vsi_vlan_setup() as the latter function is specific to the PF and
all other VSI types that need an untagged VLAN 0 filter already do this
in their specific flows. Without this change, Flow Director is failing
to initialize because it does not implement any VSI VLAN ops.
Signed-off-by: Brett Creeley <brett.creeley@intel.com>
Tested-by: Gurucharan G <gurucharanx.g@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
Diffstat (limited to 'drivers/net/ethernet/intel/ice/ice_main.c')
-rw-r--r-- | drivers/net/ethernet/intel/ice/ice_main.c | 60 |
1 files changed, 37 insertions, 23 deletions
diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c index 9b85498067b9..a1497c809cf3 100644 --- a/drivers/net/ethernet/intel/ice/ice_main.c +++ b/drivers/net/ethernet/intel/ice/ice_main.c @@ -21,6 +21,7 @@ #include "ice_trace.h" #include "ice_eswitch.h" #include "ice_tc_lib.h" +#include "ice_vsi_vlan_ops.h" #define DRV_SUMMARY "Intel(R) Ethernet Connection E800 Series Linux Driver" static const char ice_driver_string[] = DRV_SUMMARY; @@ -244,7 +245,7 @@ static int ice_set_promisc(struct ice_vsi *vsi, u8 promisc_m) if (vsi->type != ICE_VSI_PF) return 0; - if (vsi->num_vlan > 1) + if (ice_vsi_has_non_zero_vlans(vsi)) status = ice_fltr_set_vlan_vsi_promisc(&vsi->back->hw, vsi, promisc_m); else status = ice_fltr_set_vsi_promisc(&vsi->back->hw, vsi->idx, promisc_m, 0); @@ -264,7 +265,7 @@ static int ice_clear_promisc(struct ice_vsi *vsi, u8 promisc_m) if (vsi->type != ICE_VSI_PF) return 0; - if (vsi->num_vlan > 1) + if (ice_vsi_has_non_zero_vlans(vsi)) status = ice_fltr_clear_vlan_vsi_promisc(&vsi->back->hw, vsi, promisc_m); else status = ice_fltr_clear_vsi_promisc(&vsi->back->hw, vsi->idx, promisc_m, 0); @@ -279,6 +280,7 @@ static int ice_clear_promisc(struct ice_vsi *vsi, u8 promisc_m) */ static int ice_vsi_sync_fltr(struct ice_vsi *vsi) { + struct ice_vsi_vlan_ops *vlan_ops = ice_get_compat_vsi_vlan_ops(vsi); struct device *dev = ice_pf_to_dev(vsi->back); struct net_device *netdev = vsi->netdev; bool promisc_forced_on = false; @@ -352,7 +354,7 @@ static int ice_vsi_sync_fltr(struct ice_vsi *vsi) /* check for changes in promiscuous modes */ if (changed_flags & IFF_ALLMULTI) { if (vsi->current_netdev_flags & IFF_ALLMULTI) { - if (vsi->num_vlan > 1) + if (ice_vsi_has_non_zero_vlans(vsi)) promisc_m = ICE_MCAST_VLAN_PROMISC_BITS; else promisc_m = ICE_MCAST_PROMISC_BITS; @@ -366,7 +368,7 @@ static int ice_vsi_sync_fltr(struct ice_vsi *vsi) } } else { /* !(vsi->current_netdev_flags & IFF_ALLMULTI) */ - if (vsi->num_vlan > 1) + if (ice_vsi_has_non_zero_vlans(vsi)) promisc_m = ICE_MCAST_VLAN_PROMISC_BITS; else promisc_m = ICE_MCAST_PROMISC_BITS; @@ -396,7 +398,7 @@ static int ice_vsi_sync_fltr(struct ice_vsi *vsi) goto out_promisc; } err = 0; - vsi->vlan_ops.dis_rx_filtering(vsi); + vlan_ops->dis_rx_filtering(vsi); } } else { /* Clear Rx filter to remove traffic from wire */ @@ -410,7 +412,7 @@ static int ice_vsi_sync_fltr(struct ice_vsi *vsi) goto out_promisc; } if (vsi->num_vlan > 1) - vsi->vlan_ops.ena_rx_filtering(vsi); + vlan_ops->ena_rx_filtering(vsi); } } } @@ -3411,6 +3413,7 @@ static int ice_vlan_rx_add_vid(struct net_device *netdev, __be16 proto, u16 vid) { struct ice_netdev_priv *np = netdev_priv(netdev); + struct ice_vsi_vlan_ops *vlan_ops; struct ice_vsi *vsi = np->vsi; struct ice_vlan vlan; int ret; @@ -3419,9 +3422,11 @@ ice_vlan_rx_add_vid(struct net_device *netdev, __be16 proto, u16 vid) if (!vid) return 0; + vlan_ops = ice_get_compat_vsi_vlan_ops(vsi); + /* Enable VLAN pruning when a VLAN other than 0 is added */ if (!ice_vsi_is_vlan_pruning_ena(vsi)) { - ret = vsi->vlan_ops.ena_rx_filtering(vsi); + ret = vlan_ops->ena_rx_filtering(vsi); if (ret) return ret; } @@ -3430,7 +3435,7 @@ ice_vlan_rx_add_vid(struct net_device *netdev, __be16 proto, u16 vid) * packets aren't pruned by the device's internal switch on Rx */ vlan = ICE_VLAN(be16_to_cpu(proto), vid, 0); - ret = vsi->vlan_ops.add_vlan(vsi, &vlan); + ret = vlan_ops->add_vlan(vsi, &vlan); if (!ret) set_bit(ICE_VSI_VLAN_FLTR_CHANGED, vsi->state); @@ -3449,6 +3454,7 @@ static int ice_vlan_rx_kill_vid(struct net_device *netdev, __be16 proto, u16 vid) { struct ice_netdev_priv *np = netdev_priv(netdev); + struct ice_vsi_vlan_ops *vlan_ops; struct ice_vsi *vsi = np->vsi; struct ice_vlan vlan; int ret; @@ -3457,17 +3463,19 @@ ice_vlan_rx_kill_vid(struct net_device *netdev, __be16 proto, u16 vid) if (!vid) return 0; + vlan_ops = ice_get_compat_vsi_vlan_ops(vsi); + /* Make sure VLAN delete is successful before updating VLAN * information */ vlan = ICE_VLAN(be16_to_cpu(proto), vid, 0); - ret = vsi->vlan_ops.del_vlan(vsi, &vlan); + ret = vlan_ops->del_vlan(vsi, &vlan); if (ret) return ret; /* Disable pruning when VLAN 0 is the only VLAN rule */ if (vsi->num_vlan == 1 && ice_vsi_is_vlan_pruning_ena(vsi)) - vsi->vlan_ops.dis_rx_filtering(vsi); + vlan_ops->dis_rx_filtering(vsi); set_bit(ICE_VSI_VLAN_FLTR_CHANGED, vsi->state); return ret; @@ -5579,6 +5587,7 @@ static int ice_set_features(struct net_device *netdev, netdev_features_t features) { struct ice_netdev_priv *np = netdev_priv(netdev); + struct ice_vsi_vlan_ops *vlan_ops; struct ice_vsi *vsi = np->vsi; struct ice_pf *pf = vsi->back; int ret = 0; @@ -5595,6 +5604,8 @@ ice_set_features(struct net_device *netdev, netdev_features_t features) return -EBUSY; } + vlan_ops = ice_get_compat_vsi_vlan_ops(vsi); + /* Multiple features can be changed in one call so keep features in * separate if/else statements to guarantee each feature is checked */ @@ -5606,24 +5617,24 @@ ice_set_features(struct net_device *netdev, netdev_features_t features) if ((features & NETIF_F_HW_VLAN_CTAG_RX) && !(netdev->features & NETIF_F_HW_VLAN_CTAG_RX)) - ret = vsi->vlan_ops.ena_stripping(vsi, ETH_P_8021Q); + ret = vlan_ops->ena_stripping(vsi, ETH_P_8021Q); else if (!(features & NETIF_F_HW_VLAN_CTAG_RX) && (netdev->features & NETIF_F_HW_VLAN_CTAG_RX)) - ret = vsi->vlan_ops.dis_stripping(vsi); + ret = vlan_ops->dis_stripping(vsi); if ((features & NETIF_F_HW_VLAN_CTAG_TX) && !(netdev->features & NETIF_F_HW_VLAN_CTAG_TX)) - ret = vsi->vlan_ops.ena_insertion(vsi, ETH_P_8021Q); + ret = vlan_ops->ena_insertion(vsi, ETH_P_8021Q); else if (!(features & NETIF_F_HW_VLAN_CTAG_TX) && (netdev->features & NETIF_F_HW_VLAN_CTAG_TX)) - ret = vsi->vlan_ops.dis_insertion(vsi); + ret = vlan_ops->dis_insertion(vsi); if ((features & NETIF_F_HW_VLAN_CTAG_FILTER) && !(netdev->features & NETIF_F_HW_VLAN_CTAG_FILTER)) - ret = vsi->vlan_ops.ena_rx_filtering(vsi); + ret = vlan_ops->ena_rx_filtering(vsi); else if (!(features & NETIF_F_HW_VLAN_CTAG_FILTER) && (netdev->features & NETIF_F_HW_VLAN_CTAG_FILTER)) - ret = vsi->vlan_ops.dis_rx_filtering(vsi); + ret = vlan_ops->dis_rx_filtering(vsi); if ((features & NETIF_F_NTUPLE) && !(netdev->features & NETIF_F_NTUPLE)) { @@ -5651,19 +5662,21 @@ ice_set_features(struct net_device *netdev, netdev_features_t features) } /** - * ice_vsi_vlan_setup - Setup VLAN offload properties on a VSI + * ice_vsi_vlan_setup - Setup VLAN offload properties on a PF VSI * @vsi: VSI to setup VLAN properties for */ static int ice_vsi_vlan_setup(struct ice_vsi *vsi) { - int ret = 0; + struct ice_vsi_vlan_ops *vlan_ops; + + vlan_ops = ice_get_compat_vsi_vlan_ops(vsi); if (vsi->netdev->features & NETIF_F_HW_VLAN_CTAG_RX) - ret = vsi->vlan_ops.ena_stripping(vsi, ETH_P_8021Q); + vlan_ops->ena_stripping(vsi, ETH_P_8021Q); if (vsi->netdev->features & NETIF_F_HW_VLAN_CTAG_TX) - ret = vsi->vlan_ops.ena_insertion(vsi, ETH_P_8021Q); + vlan_ops->ena_insertion(vsi, ETH_P_8021Q); - return ret; + return ice_vsi_add_vlan_zero(vsi); } /** @@ -6264,11 +6277,12 @@ static void ice_napi_disable_all(struct ice_vsi *vsi) */ int ice_down(struct ice_vsi *vsi) { - int i, tx_err, rx_err, link_err = 0; + int i, tx_err, rx_err, link_err = 0, vlan_err = 0; WARN_ON(!test_bit(ICE_VSI_DOWN, vsi->state)); if (vsi->netdev && vsi->type == ICE_VSI_PF) { + vlan_err = ice_vsi_del_vlan_zero(vsi); if (!ice_is_e810(&vsi->back->hw)) ice_ptp_link_change(vsi->back, vsi->back->hw.pf_id, false); netif_carrier_off(vsi->netdev); @@ -6310,7 +6324,7 @@ int ice_down(struct ice_vsi *vsi) ice_for_each_rxq(vsi, i) ice_clean_rx_ring(vsi->rx_rings[i]); - if (tx_err || rx_err || link_err) { + if (tx_err || rx_err || link_err || vlan_err) { netdev_err(vsi->netdev, "Failed to close VSI 0x%04X on switch 0x%04X\n", vsi->vsi_num, vsi->vsw->sw_id); return -EIO; |