diff mbox series

[v1] net/iavf: fix reset VF doesn't notify PF to reset

Message ID 20201105083216.38300-1-stevex.yang@intel.com (mailing list archive)
State Superseded, archived
Delegated to: Qi Zhang
Headers show
Series [v1] net/iavf: fix reset VF doesn't notify PF to reset | expand

Checks

Context Check Description
ci/iol-mellanox-Performance success Performance Testing PASS
ci/iol-intel-Performance success Performance Testing PASS
ci/iol-intel-Functional fail Functional Testing issues
ci/iol-broadcom-Functional fail Functional Testing issues
ci/iol-testing success Testing PASS
ci/travis-robot success Travis build: passed
ci/Intel-compilation success Compilation OK
ci/checkpatch success coding style OK

Commit Message

Steve Yang Nov. 5, 2020, 8:32 a.m. UTC
When VF closed, the VF should notify PF to close/reset relative
resources from PF side.

Check the VF RSS offload flag and ignore relative operation when
iavf hash uninit to avoid reset/close error.

Fixes: 22b123a36d07 ("net/avf: initialize PMD")

Signed-off-by: Steve Yang <stevex.yang@intel.com>
---
 drivers/common/iavf/iavf_prototype.h |  1 +
 drivers/common/iavf/version.map      |  1 +
 drivers/net/iavf/iavf_ethdev.c       | 48 +++++++++++++++++++++++++++-
 drivers/net/iavf/iavf_hash.c         |  9 ++++--
 4 files changed, 55 insertions(+), 4 deletions(-)

Comments

Xing, Beilei Nov. 6, 2020, 2:58 a.m. UTC | #1
> -----Original Message-----
> From: Steve Yang <stevex.yang@intel.com>
> Sent: Thursday, November 5, 2020 4:32 PM
> To: dev@dpdk.org
> Cc: Yang, Qiming <qiming.yang@intel.com>; Xing, Beilei
> <beilei.xing@intel.com>; Wu, Jingjing <jingjing.wu@intel.com>; Yang, SteveX
> <stevex.yang@intel.com>
> Subject: [PATCH v1] net/iavf: fix reset VF doesn't notify PF to reset
> 
> When VF closed, the VF should notify PF to close/reset relative resources from
> PF side.
> 
> Check the VF RSS offload flag and ignore relative operation when iavf hash
> uninit to avoid reset/close error.

Seems there're 2 bug fix in the patch, it's better to split.
Is the fix ported from i40evf?
For vf_reset, I think there's another patch needed backport: commit 0eaa1f8c75311b96d269a0195b80e80d6c27e83c

> 
> Fixes: 22b123a36d07 ("net/avf: initialize PMD")
> 
> Signed-off-by: Steve Yang <stevex.yang@intel.com>
> ---
>  drivers/common/iavf/iavf_prototype.h |  1 +
>  drivers/common/iavf/version.map      |  1 +
>  drivers/net/iavf/iavf_ethdev.c       | 48 +++++++++++++++++++++++++++-
>  drivers/net/iavf/iavf_hash.c         |  9 ++++--
>  4 files changed, 55 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/common/iavf/iavf_prototype.h
> b/drivers/common/iavf/iavf_prototype.h
> index f34e77db0f..3998d26dc0 100644
> --- a/drivers/common/iavf/iavf_prototype.h
> +++ b/drivers/common/iavf/iavf_prototype.h
> @@ -83,6 +83,7 @@ void iavf_destroy_spinlock(struct iavf_spinlock *sp);
> __rte_internal  void iavf_vf_parse_hw_config(struct iavf_hw *hw,
>  			     struct virtchnl_vf_resource *msg);
> +__rte_internal
>  enum iavf_status iavf_vf_reset(struct iavf_hw *hw);  __rte_internal  enum
> iavf_status iavf_aq_send_msg_to_pf(struct iavf_hw *hw, diff --git
> a/drivers/common/iavf/version.map b/drivers/common/iavf/version.map
> index e0f117197c..6c1427cca4 100644
> --- a/drivers/common/iavf/version.map
> +++ b/drivers/common/iavf/version.map
> @@ -7,6 +7,7 @@ INTERNAL {
>  	iavf_set_mac_type;
>  	iavf_shutdown_adminq;
>  	iavf_vf_parse_hw_config;
> +	iavf_vf_reset;
> 
>  	local: *;
>  };
> diff --git a/drivers/net/iavf/iavf_ethdev.c b/drivers/net/iavf/iavf_ethdev.c
> index 7e3c26a94e..e2498a184e 100644
> --- a/drivers/net/iavf/iavf_ethdev.c
> +++ b/drivers/net/iavf/iavf_ethdev.c
> @@ -1780,6 +1780,34 @@ iavf_init_proto_xtr(struct rte_eth_dev *dev)
>  	}
>  }
> 
> +static int
> +iavf_reset_vf(struct iavf_hw *hw)
> +{
> +	int ret;
> +	if (iavf_vf_reset(hw) != IAVF_SUCCESS) {
> +		PMD_INIT_LOG(ERR, "Reset VF NIC failed");
> +		return -1;
> +	}
> +	/**
> +	 * After issuing vf reset command to pf, pf won't necessarily
> +	 * reset vf, it depends on what state it exactly is. If it's not
> +	 * initialized yet, it won't have vf reset since it's in a certain
> +	 * state. If not, it will try to reset. Even vf is reset, pf will
> +	 * set I40E_VFGEN_RSTAT to COMPLETE first, then wait 10ms and set
> +	 * it to ACTIVE. In this duration, vf may not catch the moment that
> +	 * COMPLETE is set. So, for vf, we'll try to wait a long time.
> +	 */
> +	rte_delay_ms(200);
> +
> +	ret = iavf_check_vf_reset_done(hw);
> +	if (ret) {
> +		PMD_INIT_LOG(ERR, "VF is still resetting");
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
>  static int
>  iavf_init_vf(struct rte_eth_dev *dev)
>  {
> @@ -1814,6 +1842,24 @@ iavf_init_vf(struct rte_eth_dev *dev)
>  		goto err;
>  	}
> 
> +	/* Reset VF and wait until it's complete */
> +	if (iavf_reset_vf(hw)) {
> +		PMD_INIT_LOG(ERR, "reset NIC failed");
> +		goto err_aq;
> +	}
> +
> +	/* VF reset, shutdown admin queue and initialize again */
> +	if (iavf_shutdown_adminq(hw) != IAVF_SUCCESS) {
> +		PMD_INIT_LOG(ERR, "iavf_shutdown_adminq failed");
> +		goto err;
> +	}
> +
> +	iavf_init_adminq_parameter(hw);
> +	if (iavf_init_adminq(hw) != IAVF_SUCCESS) {
> +		PMD_INIT_LOG(ERR, "init_adminq failed");
> +		goto err;
> +	}
> +
>  	vf->aq_resp = rte_zmalloc("vf_aq_resp", IAVF_AQ_BUF_SZ, 0);
>  	if (!vf->aq_resp) {
>  		PMD_INIT_LOG(ERR, "unable to allocate vf_aq_resp memory");
> @@ -2050,7 +2096,7 @@ iavf_dev_close(struct rte_eth_dev *dev)
> 
>  	iavf_flow_flush(dev, NULL);
>  	iavf_flow_uninit(adapter);
> -
> +	iavf_reset_vf(hw);
>  	/*
>  	 * disable promiscuous mode before reset vf
>  	 * it is a workaround solution when work with kernel driver diff --git
> a/drivers/net/iavf/iavf_hash.c b/drivers/net/iavf/iavf_hash.c index
> 8a5a6bb5a4..d3e9218f75 100644
> --- a/drivers/net/iavf/iavf_hash.c
> +++ b/drivers/net/iavf/iavf_hash.c
> @@ -1093,10 +1093,13 @@ iavf_hash_uninit(struct iavf_adapter *ad)
>  	if (vf->vf_reset)
>  		return;
> 
> -	if (iavf_hash_default_set(ad, false))
> -		PMD_DRV_LOG(ERR, "fail to delete default RSS");
> +	if (vf->vf_res &&
> +	    vf->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_ADV_RSS_PF) {
> +		if (iavf_hash_default_set(ad, false))
> +			PMD_DRV_LOG(ERR, "fail to delete default RSS");
> 
> -	iavf_unregister_parser(&iavf_hash_parser, ad);
> +		iavf_unregister_parser(&iavf_hash_parser, ad);
> +	}
>  }
> 
>  static void
> --
> 2.17.1
diff mbox series

Patch

diff --git a/drivers/common/iavf/iavf_prototype.h b/drivers/common/iavf/iavf_prototype.h
index f34e77db0f..3998d26dc0 100644
--- a/drivers/common/iavf/iavf_prototype.h
+++ b/drivers/common/iavf/iavf_prototype.h
@@ -83,6 +83,7 @@  void iavf_destroy_spinlock(struct iavf_spinlock *sp);
 __rte_internal
 void iavf_vf_parse_hw_config(struct iavf_hw *hw,
 			     struct virtchnl_vf_resource *msg);
+__rte_internal
 enum iavf_status iavf_vf_reset(struct iavf_hw *hw);
 __rte_internal
 enum iavf_status iavf_aq_send_msg_to_pf(struct iavf_hw *hw,
diff --git a/drivers/common/iavf/version.map b/drivers/common/iavf/version.map
index e0f117197c..6c1427cca4 100644
--- a/drivers/common/iavf/version.map
+++ b/drivers/common/iavf/version.map
@@ -7,6 +7,7 @@  INTERNAL {
 	iavf_set_mac_type;
 	iavf_shutdown_adminq;
 	iavf_vf_parse_hw_config;
+	iavf_vf_reset;
 
 	local: *;
 };
diff --git a/drivers/net/iavf/iavf_ethdev.c b/drivers/net/iavf/iavf_ethdev.c
index 7e3c26a94e..e2498a184e 100644
--- a/drivers/net/iavf/iavf_ethdev.c
+++ b/drivers/net/iavf/iavf_ethdev.c
@@ -1780,6 +1780,34 @@  iavf_init_proto_xtr(struct rte_eth_dev *dev)
 	}
 }
 
+static int
+iavf_reset_vf(struct iavf_hw *hw)
+{
+	int ret;
+	if (iavf_vf_reset(hw) != IAVF_SUCCESS) {
+		PMD_INIT_LOG(ERR, "Reset VF NIC failed");
+		return -1;
+	}
+	/**
+	 * After issuing vf reset command to pf, pf won't necessarily
+	 * reset vf, it depends on what state it exactly is. If it's not
+	 * initialized yet, it won't have vf reset since it's in a certain
+	 * state. If not, it will try to reset. Even vf is reset, pf will
+	 * set I40E_VFGEN_RSTAT to COMPLETE first, then wait 10ms and set
+	 * it to ACTIVE. In this duration, vf may not catch the moment that
+	 * COMPLETE is set. So, for vf, we'll try to wait a long time.
+	 */
+	rte_delay_ms(200);
+
+	ret = iavf_check_vf_reset_done(hw);
+	if (ret) {
+		PMD_INIT_LOG(ERR, "VF is still resetting");
+		return ret;
+	}
+
+	return 0;
+}
+
 static int
 iavf_init_vf(struct rte_eth_dev *dev)
 {
@@ -1814,6 +1842,24 @@  iavf_init_vf(struct rte_eth_dev *dev)
 		goto err;
 	}
 
+	/* Reset VF and wait until it's complete */
+	if (iavf_reset_vf(hw)) {
+		PMD_INIT_LOG(ERR, "reset NIC failed");
+		goto err_aq;
+	}
+
+	/* VF reset, shutdown admin queue and initialize again */
+	if (iavf_shutdown_adminq(hw) != IAVF_SUCCESS) {
+		PMD_INIT_LOG(ERR, "iavf_shutdown_adminq failed");
+		goto err;
+	}
+
+	iavf_init_adminq_parameter(hw);
+	if (iavf_init_adminq(hw) != IAVF_SUCCESS) {
+		PMD_INIT_LOG(ERR, "init_adminq failed");
+		goto err;
+	}
+
 	vf->aq_resp = rte_zmalloc("vf_aq_resp", IAVF_AQ_BUF_SZ, 0);
 	if (!vf->aq_resp) {
 		PMD_INIT_LOG(ERR, "unable to allocate vf_aq_resp memory");
@@ -2050,7 +2096,7 @@  iavf_dev_close(struct rte_eth_dev *dev)
 
 	iavf_flow_flush(dev, NULL);
 	iavf_flow_uninit(adapter);
-
+	iavf_reset_vf(hw);
 	/*
 	 * disable promiscuous mode before reset vf
 	 * it is a workaround solution when work with kernel driver
diff --git a/drivers/net/iavf/iavf_hash.c b/drivers/net/iavf/iavf_hash.c
index 8a5a6bb5a4..d3e9218f75 100644
--- a/drivers/net/iavf/iavf_hash.c
+++ b/drivers/net/iavf/iavf_hash.c
@@ -1093,10 +1093,13 @@  iavf_hash_uninit(struct iavf_adapter *ad)
 	if (vf->vf_reset)
 		return;
 
-	if (iavf_hash_default_set(ad, false))
-		PMD_DRV_LOG(ERR, "fail to delete default RSS");
+	if (vf->vf_res &&
+	    vf->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_ADV_RSS_PF) {
+		if (iavf_hash_default_set(ad, false))
+			PMD_DRV_LOG(ERR, "fail to delete default RSS");
 
-	iavf_unregister_parser(&iavf_hash_parser, ad);
+		iavf_unregister_parser(&iavf_hash_parser, ad);
+	}
 }
 
 static void