[v7,12/12] net/ice: support DCF new VLAN capabilities

Message ID 20220429091958.3103384-13-kevinx.liu@intel.com (mailing list archive)
State Accepted, archived
Delegated to: Qi Zhang
Headers
Series complete common VF features for DCF |

Checks

Context Check Description
ci/checkpatch success coding style OK
ci/Intel-compilation success Compilation OK
ci/intel-Testing success Testing PASS

Commit Message

Kevin Liu April 29, 2022, 9:19 a.m. UTC
  From: Alvin Zhang <alvinx.zhang@intel.com>

The new VLAN virtchnl opcodes introduce new capabilities like VLAN
filtering, stripping and insertion.

The DCF needs to query the VLAN capabilities based on current device
configuration firstly.

DCF is able to configure inner VLAN filter when port VLAN is enabled
base on negotiation; and DCF is able to configure outer VLAN (0x8100)
if port VLAN is disabled to be compatible with legacy mode.

When port VLAN is updated by DCF, the DCF needs to reset to query the
new VLAN capabilities.

Signed-off-by: Alvin Zhang <alvinx.zhang@intel.com>
Signed-off-by: Kevin Liu <kevinx.liu@intel.com>
---
 drivers/net/ice/ice_dcf.c        |  27 +++++
 drivers/net/ice/ice_dcf.h        |   1 +
 drivers/net/ice/ice_dcf_ethdev.c | 171 ++++++++++++++++++++++++++++---
 3 files changed, 182 insertions(+), 17 deletions(-)
  

Comments

Qi Zhang May 11, 2022, 12:06 a.m. UTC | #1
> -----Original Message-----
> From: Liu, KevinX <kevinx.liu@intel.com>
> Sent: Friday, April 29, 2022 5:20 PM
> To: dev@dpdk.org
> Cc: Yang, Qiming <qiming.yang@intel.com>; Zhang, Qi Z
> <qi.z.zhang@intel.com>; Yang, SteveX <stevex.yang@intel.com>; Alvin Zhang
> <alvinx.zhang@intel.com>; Liu, KevinX <kevinx.liu@intel.com>
> Subject: [PATCH v7 12/12] net/ice: support DCF new VLAN capabilities

Refine the title as " complete VLAN offload capability for DCF" in dpdk-next-net-intel.
As it does not introduce any new VLAN offload capability
  

Patch

diff --git a/drivers/net/ice/ice_dcf.c b/drivers/net/ice/ice_dcf.c
index 55ae68c456..885d58c0f4 100644
--- a/drivers/net/ice/ice_dcf.c
+++ b/drivers/net/ice/ice_dcf.c
@@ -587,6 +587,29 @@  ice_dcf_get_supported_rxdid(struct ice_dcf_hw *hw)
 	return 0;
 }
 
+static int
+dcf_get_vlan_offload_caps_v2(struct ice_dcf_hw *hw)
+{
+	struct virtchnl_vlan_caps vlan_v2_caps;
+	struct dcf_virtchnl_cmd args;
+	int ret;
+
+	memset(&args, 0, sizeof(args));
+	args.v_op = VIRTCHNL_OP_GET_OFFLOAD_VLAN_V2_CAPS;
+	args.rsp_msgbuf = (uint8_t *)&vlan_v2_caps;
+	args.rsp_buflen = sizeof(vlan_v2_caps);
+
+	ret = ice_dcf_execute_virtchnl_cmd(hw, &args);
+	if (ret) {
+		PMD_DRV_LOG(ERR,
+			    "Failed to execute command of VIRTCHNL_OP_GET_OFFLOAD_VLAN_V2_CAPS");
+		return ret;
+	}
+
+	rte_memcpy(&hw->vlan_v2_caps, &vlan_v2_caps, sizeof(vlan_v2_caps));
+	return 0;
+}
+
 int
 ice_dcf_init_hw(struct rte_eth_dev *eth_dev, struct ice_dcf_hw *hw)
 {
@@ -701,6 +724,10 @@  ice_dcf_init_hw(struct rte_eth_dev *eth_dev, struct ice_dcf_hw *hw)
 	rte_intr_enable(pci_dev->intr_handle);
 	ice_dcf_enable_irq0(hw);
 
+	if ((hw->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_VLAN_V2) &&
+	    dcf_get_vlan_offload_caps_v2(hw))
+		goto err_rss;
+
 	return 0;
 
 err_rss:
diff --git a/drivers/net/ice/ice_dcf.h b/drivers/net/ice/ice_dcf.h
index 44a61404c3..7f42ebabe9 100644
--- a/drivers/net/ice/ice_dcf.h
+++ b/drivers/net/ice/ice_dcf.h
@@ -129,6 +129,7 @@  struct ice_dcf_hw {
 	uint16_t nb_msix;
 	uint16_t rxq_map[16];
 	struct virtchnl_eth_stats eth_stats_offset;
+	struct virtchnl_vlan_caps vlan_v2_caps;
 
 	/* Link status */
 	bool link_up;
diff --git a/drivers/net/ice/ice_dcf_ethdev.c b/drivers/net/ice/ice_dcf_ethdev.c
index 236c0395e0..8005eb2ab8 100644
--- a/drivers/net/ice/ice_dcf_ethdev.c
+++ b/drivers/net/ice/ice_dcf_ethdev.c
@@ -1050,6 +1050,46 @@  dcf_dev_set_default_mac_addr(struct rte_eth_dev *dev,
 	return 0;
 }
 
+static int
+dcf_add_del_vlan_v2(struct ice_dcf_hw *hw, uint16_t vlanid, bool add)
+{
+	struct virtchnl_vlan_supported_caps *supported_caps =
+			&hw->vlan_v2_caps.filtering.filtering_support;
+	struct virtchnl_vlan *vlan_setting;
+	struct virtchnl_vlan_filter_list_v2 vlan_filter;
+	struct dcf_virtchnl_cmd args;
+	uint32_t filtering_caps;
+	int err;
+
+	if (supported_caps->outer) {
+		filtering_caps = supported_caps->outer;
+		vlan_setting = &vlan_filter.filters[0].outer;
+	} else {
+		filtering_caps = supported_caps->inner;
+		vlan_setting = &vlan_filter.filters[0].inner;
+	}
+
+	if (!(filtering_caps & VIRTCHNL_VLAN_ETHERTYPE_8100))
+		return -ENOTSUP;
+
+	memset(&vlan_filter, 0, sizeof(vlan_filter));
+	vlan_filter.vport_id = hw->vsi_res->vsi_id;
+	vlan_filter.num_elements = 1;
+	vlan_setting->tpid = RTE_ETHER_TYPE_VLAN;
+	vlan_setting->tci = vlanid;
+
+	memset(&args, 0, sizeof(args));
+	args.v_op = add ? VIRTCHNL_OP_ADD_VLAN_V2 : VIRTCHNL_OP_DEL_VLAN_V2;
+	args.req_msg = (uint8_t *)&vlan_filter;
+	args.req_msglen = sizeof(vlan_filter);
+	err = ice_dcf_execute_virtchnl_cmd(hw, &args);
+	if (err)
+		PMD_DRV_LOG(ERR, "fail to execute command %s",
+			    add ? "OP_ADD_VLAN_V2" :  "OP_DEL_VLAN_V2");
+
+	return err;
+}
+
 static int
 dcf_add_del_vlan(struct ice_dcf_hw *hw, uint16_t vlanid, bool add)
 {
@@ -1076,6 +1116,116 @@  dcf_add_del_vlan(struct ice_dcf_hw *hw, uint16_t vlanid, bool add)
 	return err;
 }
 
+static int
+dcf_dev_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on)
+{
+	struct ice_dcf_adapter *adapter = dev->data->dev_private;
+	struct ice_dcf_hw *hw = &adapter->real_hw;
+	int err;
+
+	if (hw->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_VLAN_V2) {
+		err = dcf_add_del_vlan_v2(hw, vlan_id, on);
+		if (err)
+			return -EIO;
+		return 0;
+	}
+
+	if (!(hw->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_VLAN))
+		return -ENOTSUP;
+
+	err = dcf_add_del_vlan(hw, vlan_id, on);
+	if (err)
+		return -EIO;
+	return 0;
+}
+
+static void
+dcf_iterate_vlan_filters_v2(struct rte_eth_dev *dev, bool enable)
+{
+	struct rte_vlan_filter_conf *vfc = &dev->data->vlan_filter_conf;
+	struct ice_dcf_adapter *adapter = dev->data->dev_private;
+	struct ice_dcf_hw *hw = &adapter->real_hw;
+	uint32_t i, j;
+	uint64_t ids;
+
+	for (i = 0; i < RTE_DIM(vfc->ids); i++) {
+		if (vfc->ids[i] == 0)
+			continue;
+
+		ids = vfc->ids[i];
+		for (j = 0; ids != 0 && j < 64; j++, ids >>= 1) {
+			if (ids & 1)
+				dcf_add_del_vlan_v2(hw, 64 * i + j, enable);
+		}
+	}
+}
+
+static int
+dcf_config_vlan_strip_v2(struct ice_dcf_hw *hw, bool enable)
+{
+	struct virtchnl_vlan_supported_caps *stripping_caps =
+			&hw->vlan_v2_caps.offloads.stripping_support;
+	struct virtchnl_vlan_setting vlan_strip;
+	struct dcf_virtchnl_cmd args;
+	uint32_t *ethertype;
+	int ret;
+
+	if ((stripping_caps->outer & VIRTCHNL_VLAN_ETHERTYPE_8100) &&
+	    (stripping_caps->outer & VIRTCHNL_VLAN_TOGGLE))
+		ethertype = &vlan_strip.outer_ethertype_setting;
+	else if ((stripping_caps->inner & VIRTCHNL_VLAN_ETHERTYPE_8100) &&
+		 (stripping_caps->inner & VIRTCHNL_VLAN_TOGGLE))
+		ethertype = &vlan_strip.inner_ethertype_setting;
+	else
+		return -ENOTSUP;
+
+	memset(&vlan_strip, 0, sizeof(vlan_strip));
+	vlan_strip.vport_id = hw->vsi_res->vsi_id;
+	*ethertype = VIRTCHNL_VLAN_ETHERTYPE_8100;
+
+	memset(&args, 0, sizeof(args));
+	args.v_op = enable ? VIRTCHNL_OP_ENABLE_VLAN_STRIPPING_V2 :
+			    VIRTCHNL_OP_DISABLE_VLAN_STRIPPING_V2;
+	args.req_msg = (uint8_t *)&vlan_strip;
+	args.req_msglen = sizeof(vlan_strip);
+	ret = ice_dcf_execute_virtchnl_cmd(hw, &args);
+	if (ret)
+		PMD_DRV_LOG(ERR, "fail to execute command %s",
+			    enable ? "VIRTCHNL_OP_ENABLE_VLAN_STRIPPING_V2" :
+				     "VIRTCHNL_OP_DISABLE_VLAN_STRIPPING_V2");
+
+	return ret;
+}
+
+static int
+dcf_dev_vlan_offload_set_v2(struct rte_eth_dev *dev, int mask)
+{
+	struct rte_eth_rxmode *rxmode = &dev->data->dev_conf.rxmode;
+	struct ice_dcf_adapter *adapter = dev->data->dev_private;
+	struct ice_dcf_hw *hw = &adapter->real_hw;
+	bool enable;
+	int err;
+
+	if (mask & RTE_ETH_VLAN_FILTER_MASK) {
+		enable = !!(rxmode->offloads & RTE_ETH_RX_OFFLOAD_VLAN_FILTER);
+
+		dcf_iterate_vlan_filters_v2(dev, enable);
+	}
+
+	if (mask & RTE_ETH_VLAN_STRIP_MASK) {
+		enable = !!(rxmode->offloads & RTE_ETH_RX_OFFLOAD_VLAN_STRIP);
+
+		err = dcf_config_vlan_strip_v2(hw, enable);
+		/* If not support, the stripping is already disabled by PF */
+		if (err == -ENOTSUP && !enable)
+			err = 0;
+		if (err)
+			return -EIO;
+	}
+
+	return 0;
+}
+
 static int
 dcf_enable_vlan_strip(struct ice_dcf_hw *hw)
 {
@@ -1108,30 +1258,17 @@  dcf_disable_vlan_strip(struct ice_dcf_hw *hw)
 	return ret;
 }
 
-static int
-dcf_dev_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on)
-{
-	struct ice_dcf_adapter *adapter = dev->data->dev_private;
-	struct ice_dcf_hw *hw = &adapter->real_hw;
-	int err;
-
-	if (!(hw->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_VLAN))
-		return -ENOTSUP;
-
-	err = dcf_add_del_vlan(hw, vlan_id, on);
-	if (err)
-		return -EIO;
-	return 0;
-}
-
 static int
 dcf_dev_vlan_offload_set(struct rte_eth_dev *dev, int mask)
 {
+	struct rte_eth_conf *dev_conf = &dev->data->dev_conf;
 	struct ice_dcf_adapter *adapter = dev->data->dev_private;
 	struct ice_dcf_hw *hw = &adapter->real_hw;
-	struct rte_eth_conf *dev_conf = &dev->data->dev_conf;
 	int err;
 
+	if (hw->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_VLAN_V2)
+		return dcf_dev_vlan_offload_set_v2(dev, mask);
+
 	if (!(hw->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_VLAN))
 		return -ENOTSUP;