Blob Blame History Raw
From: Brett Creeley <brett.creeley@intel.com>
Date: Thu, 2 Dec 2021 08:38:44 -0800
Subject: ice: Use the proto argument for VLAN ops
Patch-mainline: v5.18-rc1
Git-commit: 2bfefa2dab6bb4c8596778e3ccb011d1f0e13975
References: jsc#PED-376

Currently the proto argument is unused. This is because the driver only
supports 802.1Q VLAN filtering. This policy is enforced via netdev
features that the driver sets up when configuring the netdev, so the
proto argument won't ever be anything other than 802.1Q. However, this
will allow for future iterations of the driver to seemlessly support
802.1ad filtering. Begin using the proto argument and extend the related
structures to support its use.

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>
Acked-by: Thomas Bogendoerfer <tbogendoerfer@suse.de>
---
 drivers/net/ethernet/intel/ice/ice_fltr.c         |    2 
 drivers/net/ethernet/intel/ice/ice_lib.c          |    2 
 drivers/net/ethernet/intel/ice/ice_main.c         |   22 ++++------
 drivers/net/ethernet/intel/ice/ice_switch.c       |    5 ++
 drivers/net/ethernet/intel/ice/ice_switch.h       |    2 
 drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c  |   10 ++--
 drivers/net/ethernet/intel/ice/ice_virtchnl_pf.h  |    2 
 drivers/net/ethernet/intel/ice/ice_vlan.h         |    3 -
 drivers/net/ethernet/intel/ice/ice_vsi_vlan_lib.c |   48 +++++++++++++++++++++-
 drivers/net/ethernet/intel/ice/ice_vsi_vlan_lib.h |    4 -
 drivers/net/ethernet/intel/ice/ice_vsi_vlan_ops.h |    4 -
 11 files changed, 78 insertions(+), 26 deletions(-)

--- a/drivers/net/ethernet/intel/ice/ice_fltr.c
+++ b/drivers/net/ethernet/intel/ice/ice_fltr.c
@@ -217,6 +217,8 @@ ice_fltr_add_vlan_to_list(struct ice_vsi
 	info.fltr_act = ICE_FWD_TO_VSI;
 	info.vsi_handle = vsi->idx;
 	info.l_data.vlan.vlan_id = vlan->vid;
+	info.l_data.vlan.tpid = vlan->tpid;
+	info.l_data.vlan.tpid_valid = true;
 
 	return ice_fltr_add_entry_to_list(ice_pf_to_dev(vsi->back), &info,
 					  list);
--- a/drivers/net/ethernet/intel/ice/ice_lib.c
+++ b/drivers/net/ethernet/intel/ice/ice_lib.c
@@ -3929,7 +3929,7 @@ int ice_vsi_add_vlan_zero(struct ice_vsi
 {
 	struct ice_vlan vlan;
 
-	vlan = ICE_VLAN(0, 0);
+	vlan = ICE_VLAN(0, 0, 0);
 	return vsi->vlan_ops.add_vlan(vsi, &vlan);
 }
 
--- a/drivers/net/ethernet/intel/ice/ice_main.c
+++ b/drivers/net/ethernet/intel/ice/ice_main.c
@@ -3428,14 +3428,13 @@ ice_lb_vsi_setup(struct ice_pf *pf, stru
 /**
  * ice_vlan_rx_add_vid - Add a VLAN ID filter to HW offload
  * @netdev: network interface to be adjusted
- * @proto: unused protocol
+ * @proto: VLAN TPID
  * @vid: VLAN ID to be added
  *
  * net_device_ops implementation for adding VLAN IDs
  */
 static int
-ice_vlan_rx_add_vid(struct net_device *netdev, __always_unused __be16 proto,
-		    u16 vid)
+ice_vlan_rx_add_vid(struct net_device *netdev, __be16 proto, u16 vid)
 {
 	struct ice_netdev_priv *np = netdev_priv(netdev);
 	struct ice_vsi *vsi = np->vsi;
@@ -3456,7 +3455,7 @@ ice_vlan_rx_add_vid(struct net_device *n
 	/* Add a switch rule for this VLAN ID so its corresponding VLAN tagged
 	 * packets aren't pruned by the device's internal switch on Rx
 	 */
-	vlan = ICE_VLAN(vid, 0);
+	vlan = ICE_VLAN(be16_to_cpu(proto), vid, 0);
 	ret = vsi->vlan_ops.add_vlan(vsi, &vlan);
 	if (!ret)
 		set_bit(ICE_VSI_VLAN_FLTR_CHANGED, vsi->state);
@@ -3467,14 +3466,13 @@ ice_vlan_rx_add_vid(struct net_device *n
 /**
  * ice_vlan_rx_kill_vid - Remove a VLAN ID filter from HW offload
  * @netdev: network interface to be adjusted
- * @proto: unused protocol
+ * @proto: VLAN TPID
  * @vid: VLAN ID to be removed
  *
  * net_device_ops implementation for removing VLAN IDs
  */
 static int
-ice_vlan_rx_kill_vid(struct net_device *netdev, __always_unused __be16 proto,
-		     u16 vid)
+ice_vlan_rx_kill_vid(struct net_device *netdev, __be16 proto, u16 vid)
 {
 	struct ice_netdev_priv *np = netdev_priv(netdev);
 	struct ice_vsi *vsi = np->vsi;
@@ -3488,7 +3486,7 @@ ice_vlan_rx_kill_vid(struct net_device *
 	/* Make sure VLAN delete is successful before updating VLAN
 	 * information
 	 */
-	vlan = ICE_VLAN(vid, 0);
+	vlan = ICE_VLAN(be16_to_cpu(proto), vid, 0);
 	ret = vsi->vlan_ops.del_vlan(vsi, &vlan);
 	if (ret)
 		return ret;
@@ -5634,14 +5632,14 @@ ice_set_features(struct net_device *netd
 
 	if ((features & NETIF_F_HW_VLAN_CTAG_RX) &&
 	    !(netdev->features & NETIF_F_HW_VLAN_CTAG_RX))
-		ret = vsi->vlan_ops.ena_stripping(vsi);
+		ret = vsi->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);
 
 	if ((features & NETIF_F_HW_VLAN_CTAG_TX) &&
 	    !(netdev->features & NETIF_F_HW_VLAN_CTAG_TX))
-		ret = vsi->vlan_ops.ena_insertion(vsi);
+		ret = vsi->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);
@@ -5687,9 +5685,9 @@ static int ice_vsi_vlan_setup(struct ice
 	int ret = 0;
 
 	if (vsi->netdev->features & NETIF_F_HW_VLAN_CTAG_RX)
-		ret = vsi->vlan_ops.ena_stripping(vsi);
+		ret = vsi->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);
+		ret = vsi->vlan_ops.ena_insertion(vsi, ETH_P_8021Q);
 
 	return ret;
 }
--- a/drivers/net/ethernet/intel/ice/ice_switch.c
+++ b/drivers/net/ethernet/intel/ice/ice_switch.c
@@ -1539,6 +1539,7 @@ ice_fill_sw_rule(struct ice_hw *hw, stru
 		 struct ice_aqc_sw_rules_elem *s_rule, enum ice_adminq_opc opc)
 {
 	u16 vlan_id = ICE_MAX_VLAN_ID + 1;
+	u16 vlan_tpid = ETH_P_8021Q;
 	void *daddr = NULL;
 	u16 eth_hdr_sz;
 	u8 *eth_hdr;
@@ -1611,6 +1612,8 @@ ice_fill_sw_rule(struct ice_hw *hw, stru
 		break;
 	case ICE_SW_LKUP_VLAN:
 		vlan_id = f_info->l_data.vlan.vlan_id;
+		if (f_info->l_data.vlan.tpid_valid)
+			vlan_tpid = f_info->l_data.vlan.tpid;
 		if (f_info->fltr_act == ICE_FWD_TO_VSI ||
 		    f_info->fltr_act == ICE_FWD_TO_VSI_LIST) {
 			act |= ICE_SINGLE_ACT_PRUNE;
@@ -1653,6 +1656,8 @@ ice_fill_sw_rule(struct ice_hw *hw, stru
 	if (!(vlan_id > ICE_MAX_VLAN_ID)) {
 		off = (__force __be16 *)(eth_hdr + ICE_ETH_VLAN_TCI_OFFSET);
 		*off = cpu_to_be16(vlan_id);
+		off = (__force __be16 *)(eth_hdr + ICE_ETH_ETHTYPE_OFFSET);
+		*off = cpu_to_be16(vlan_tpid);
 	}
 
 	/* Create the switch rule with the final dummy Ethernet header */
--- a/drivers/net/ethernet/intel/ice/ice_switch.h
+++ b/drivers/net/ethernet/intel/ice/ice_switch.h
@@ -77,6 +77,8 @@ struct ice_fltr_info {
 		} mac_vlan;
 		struct {
 			u16 vlan_id;
+			u16 tpid;
+			u8 tpid_valid;
 		} vlan;
 		/* Set lkup_type as ICE_SW_LKUP_ETHERTYPE
 		 * if just using ethertype as filter. Set lkup_type as
--- a/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c
+++ b/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c
@@ -4134,7 +4134,7 @@ ice_set_vf_port_vlan(struct net_device *
 
 	mutex_lock(&vf->cfg_lock);
 
-	vf->port_vlan_info = ICE_VLAN(vlan_id, qos);
+	vf->port_vlan_info = ICE_VLAN(ETH_P_8021Q, vlan_id, qos);
 	if (ice_vf_is_port_vlan_ena(vf))
 		dev_info(dev, "Setting VLAN %u, QoS %u on VF %d\n",
 			 vlan_id, qos, vf_id);
@@ -4255,7 +4255,7 @@ static int ice_vc_process_vlan_msg(struc
 			if (!vid)
 				continue;
 
-			vlan = ICE_VLAN(vid, 0);
+			vlan = ICE_VLAN(ETH_P_8021Q, vid, 0);
 			status = vsi->vlan_ops.add_vlan(vsi, &vlan);
 			if (status) {
 				v_ret = VIRTCHNL_STATUS_ERR_PARAM;
@@ -4308,7 +4308,7 @@ static int ice_vc_process_vlan_msg(struc
 			if (!vid)
 				continue;
 
-			vlan = ICE_VLAN(vid, 0);
+			vlan = ICE_VLAN(ETH_P_8021Q, vid, 0);
 			status = vsi->vlan_ops.del_vlan(vsi, &vlan);
 			if (status) {
 				v_ret = VIRTCHNL_STATUS_ERR_PARAM;
@@ -4387,7 +4387,7 @@ static int ice_vc_ena_vlan_stripping(str
 	}
 
 	vsi = ice_get_vf_vsi(vf);
-	if (vsi->vlan_ops.ena_stripping(vsi))
+	if (vsi->vlan_ops.ena_stripping(vsi, ETH_P_8021Q))
 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
 
 error_param:
@@ -4452,7 +4452,7 @@ static int ice_vf_init_vlan_stripping(st
 		return 0;
 
 	if (ice_vf_vlan_offload_ena(vf->driver_caps))
-		return vsi->vlan_ops.ena_stripping(vsi);
+		return vsi->vlan_ops.ena_stripping(vsi, ETH_P_8021Q);
 	else
 		return vsi->vlan_ops.dis_stripping(vsi);
 }
--- a/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.h
+++ b/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.h
@@ -119,7 +119,7 @@ struct ice_vf {
 	struct ice_time_mac legacy_last_added_umac;
 	DECLARE_BITMAP(txq_ena, ICE_MAX_RSS_QS_PER_VF);
 	DECLARE_BITMAP(rxq_ena, ICE_MAX_RSS_QS_PER_VF);
-	struct ice_vlan port_vlan_info;	/* Port VLAN ID and QoS */
+	struct ice_vlan port_vlan_info;	/* Port VLAN ID, QoS, and TPID */
 	u8 pf_set_mac:1;		/* VF MAC address set by VMM admin */
 	u8 trusted:1;
 	u8 spoofchk:1;
--- a/drivers/net/ethernet/intel/ice/ice_vlan.h
+++ b/drivers/net/ethernet/intel/ice/ice_vlan.h
@@ -8,10 +8,11 @@
 #include "ice_type.h"
 
 struct ice_vlan {
+	u16 tpid;
 	u16 vid;
 	u8 prio;
 };
 
-#define ICE_VLAN(vid, prio) ((struct ice_vlan){ vid, prio })
+#define ICE_VLAN(tpid, vid, prio) ((struct ice_vlan){ tpid, vid, prio })
 
 #endif /* _ICE_VLAN_H_ */
--- a/drivers/net/ethernet/intel/ice/ice_vsi_vlan_lib.c
+++ b/drivers/net/ethernet/intel/ice/ice_vsi_vlan_lib.c
@@ -6,6 +6,31 @@
 #include "ice_fltr.h"
 #include "ice.h"
 
+static void print_invalid_tpid(struct ice_vsi *vsi, u16 tpid)
+{
+	dev_err(ice_pf_to_dev(vsi->back), "%s %d specified invalid VLAN tpid 0x%04x\n",
+		ice_vsi_type_str(vsi->type), vsi->idx, tpid);
+}
+
+/**
+ * validate_vlan - check if the ice_vlan passed in is valid
+ * @vsi: VSI used for printing error message
+ * @vlan: ice_vlan structure to validate
+ *
+ * Return true if the VLAN TPID is valid or if the VLAN TPID is 0 and the VLAN
+ * VID is 0, which allows for non-zero VLAN filters with the specified VLAN TPID
+ * and untagged VLAN 0 filters to be added to the prune list respectively.
+ */
+static bool validate_vlan(struct ice_vsi *vsi, struct ice_vlan *vlan)
+{
+	if (vlan->tpid != ETH_P_8021Q && (vlan->tpid || vlan->vid)) {
+		print_invalid_tpid(vsi, vlan->tpid);
+		return false;
+	}
+
+	return true;
+}
+
 /**
  * ice_vsi_add_vlan - default add VLAN implementation for all VSI types
  * @vsi: VSI being configured
@@ -15,6 +40,9 @@ int ice_vsi_add_vlan(struct ice_vsi *vsi
 {
 	int err = 0;
 
+	if (!validate_vlan(vsi, vlan))
+		return -EINVAL;
+
 	if (!ice_fltr_add_vlan(vsi, vlan)) {
 		vsi->num_vlan++;
 	} else {
@@ -37,6 +65,9 @@ int ice_vsi_del_vlan(struct ice_vsi *vsi
 	struct device *dev;
 	int err;
 
+	if (!validate_vlan(vsi, vlan))
+		return -EINVAL;
+
 	dev = ice_pf_to_dev(pf);
 
 	err = ice_fltr_remove_vlan(vsi, vlan);
@@ -143,8 +174,13 @@ out:
 	return err;
 }
 
-int ice_vsi_ena_stripping(struct ice_vsi *vsi)
+int ice_vsi_ena_stripping(struct ice_vsi *vsi, const u16 tpid)
 {
+	if (tpid != ETH_P_8021Q) {
+		print_invalid_tpid(vsi, tpid);
+		return -EINVAL;
+	}
+
 	return ice_vsi_manage_vlan_stripping(vsi, true);
 }
 
@@ -153,8 +189,13 @@ int ice_vsi_dis_stripping(struct ice_vsi
 	return ice_vsi_manage_vlan_stripping(vsi, false);
 }
 
-int ice_vsi_ena_insertion(struct ice_vsi *vsi)
+int ice_vsi_ena_insertion(struct ice_vsi *vsi, const u16 tpid)
 {
+	if (tpid != ETH_P_8021Q) {
+		print_invalid_tpid(vsi, tpid);
+		return -EINVAL;
+	}
+
 	return ice_vsi_manage_vlan_insertion(vsi);
 }
 
@@ -216,6 +257,9 @@ int ice_vsi_set_port_vlan(struct ice_vsi
 {
 	u16 port_vlan_info;
 
+	if (vlan->tpid != ETH_P_8021Q)
+		return -EINVAL;
+
 	if (vlan->prio > 7)
 		return -EINVAL;
 
--- a/drivers/net/ethernet/intel/ice/ice_vsi_vlan_lib.h
+++ b/drivers/net/ethernet/intel/ice/ice_vsi_vlan_lib.h
@@ -12,9 +12,9 @@ struct ice_vsi;
 int ice_vsi_add_vlan(struct ice_vsi *vsi, struct ice_vlan *vlan);
 int ice_vsi_del_vlan(struct ice_vsi *vsi, struct ice_vlan *vlan);
 
-int ice_vsi_ena_stripping(struct ice_vsi *vsi);
+int ice_vsi_ena_stripping(struct ice_vsi *vsi, u16 tpid);
 int ice_vsi_dis_stripping(struct ice_vsi *vsi);
-int ice_vsi_ena_insertion(struct ice_vsi *vsi);
+int ice_vsi_ena_insertion(struct ice_vsi *vsi, u16 tpid);
 int ice_vsi_dis_insertion(struct ice_vsi *vsi);
 int ice_vsi_set_port_vlan(struct ice_vsi *vsi, struct ice_vlan *vlan);
 
--- a/drivers/net/ethernet/intel/ice/ice_vsi_vlan_ops.h
+++ b/drivers/net/ethernet/intel/ice/ice_vsi_vlan_ops.h
@@ -12,9 +12,9 @@ struct ice_vsi;
 struct ice_vsi_vlan_ops {
 	int (*add_vlan)(struct ice_vsi *vsi, struct ice_vlan *vlan);
 	int (*del_vlan)(struct ice_vsi *vsi, struct ice_vlan *vlan);
-	int (*ena_stripping)(struct ice_vsi *vsi);
+	int (*ena_stripping)(struct ice_vsi *vsi, const u16 tpid);
 	int (*dis_stripping)(struct ice_vsi *vsi);
-	int (*ena_insertion)(struct ice_vsi *vsi);
+	int (*ena_insertion)(struct ice_vsi *vsi, const u16 tpid);
 	int (*dis_insertion)(struct ice_vsi *vsi);
 	int (*ena_rx_filtering)(struct ice_vsi *vsi);
 	int (*dis_rx_filtering)(struct ice_vsi *vsi);