Commit 1428895ad417 ("net/iavf: fix disabling of promiscuous modes on
close") added a synchronous VIRTCHNL round-trip on the close path
before the reset request is sent. This delays the reset just long
enough that `IAVF_VFGEN_RSTAT` still reads `VIRTCHNL_VFR_VFACTIVE`
when the re-init path polls it for reset completion. The driver
interprets this as the reset being complete, when in fact it has not
yet started, and proceeds to issue VIRTCHNL commands before the PF
has disabled the VF mailbox.

Fix by polling `IAVF_VF_ARQLEN1.ARQENABLE` immediately after the reset
request and before shutting down the admin queue, when the close is
triggered by a reset. The PF clears this bit as its first reset action,
providing an unambiguous signal that the reset is in progress.

Fixes: 1428895ad4 ("net/iavf: fix disabling of promiscuous modes on close")
Cc: [email protected]

Reported-by: Talluri Chaitanyababu <[email protected]>
Signed-off-by: Ciara Loftus <[email protected]>
---
 drivers/net/intel/iavf/iavf.h        |  1 +
 drivers/net/intel/iavf/iavf_ethdev.c | 12 ++++++++++++
 2 files changed, 13 insertions(+)

diff --git a/drivers/net/intel/iavf/iavf.h b/drivers/net/intel/iavf/iavf.h
index 2615b6f034..4444602a30 100644
--- a/drivers/net/intel/iavf/iavf.h
+++ b/drivers/net/intel/iavf/iavf.h
@@ -291,6 +291,7 @@ struct iavf_info {
        struct rte_eth_dev *eth_dev;
 
        bool in_reset_recovery;
+       bool reset_pending;
 
        uint32_t ptp_caps;
        rte_spinlock_t phc_time_aq_lock;
diff --git a/drivers/net/intel/iavf/iavf_ethdev.c 
b/drivers/net/intel/iavf/iavf_ethdev.c
index a8031e23a5..a38132e80e 100644
--- a/drivers/net/intel/iavf/iavf_ethdev.c
+++ b/drivers/net/intel/iavf/iavf_ethdev.c
@@ -106,6 +106,7 @@ static int iavf_dev_start(struct rte_eth_dev *dev);
 static int iavf_dev_stop(struct rte_eth_dev *dev);
 static int iavf_dev_close(struct rte_eth_dev *dev);
 static int iavf_dev_reset(struct rte_eth_dev *dev);
+static bool iavf_is_reset_detected(struct iavf_adapter *adapter);
 static int iavf_dev_info_get(struct rte_eth_dev *dev,
                             struct rte_eth_dev_info *dev_info);
 static const uint32_t *iavf_dev_supported_ptypes_get(struct rte_eth_dev *dev,
@@ -3196,6 +3197,14 @@ iavf_dev_close(struct rte_eth_dev *dev)
        iavf_flow_uninit(adapter);
 
        iavf_vf_reset(hw);
+       /*
+        * If a reset is pending, wait for the PF to disable the VF's admin
+        * receive queue (its first reset action) before we shut it down
+        * ourselves.  This ensures iavf_check_vf_reset_done() does not see
+        * a stale VFACTIVE value on the re-init path.
+        */
+       if (vf->reset_pending)
+               iavf_is_reset_detected(adapter);
        vf->aq_intr_enabled = false;
        iavf_shutdown_adminq(hw);
        if (vf->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_WB_ON_ITR) {
@@ -3273,6 +3282,7 @@ iavf_dev_reset(struct rte_eth_dev *dev)
        struct iavf_adapter *adapter =
                IAVF_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
        struct iavf_hw *hw = IAVF_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+       struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
        /*
         * Check whether the VF reset has been done and inform application,
         * to avoid calling the virtual channel command, which may cause
@@ -3285,8 +3295,10 @@ iavf_dev_reset(struct rte_eth_dev *dev)
        }
        iavf_set_no_poll(adapter, false);
 
+       vf->reset_pending = true;
        PMD_DRV_LOG(DEBUG, "Start dev_reset ...");
        ret = iavf_dev_uninit(dev);
+       vf->reset_pending = false;
        if (ret)
                return ret;
 
-- 
2.43.0

Reply via email to