Port reset will call i40evf_uninit_vf() to release resource. It wants
to call i40evf_dev_close() to do some clean work. Before this patch,
port reset will never call i40evf_dev_close() to shutdown adminq. So
the i40evf_dev_init() will failed.

Fixs: 18599342024("net/i40e: fix VF add/del MAC")

Signed-off-by: Zhirun Yan <zhirun....@intel.com>
Signed-off-by: Haiyue Wang <haiyue.w...@intel.com>
---
 drivers/net/i40e/i40e_ethdev_vf.c | 28 ++++++++++++++++------------
 1 file changed, 16 insertions(+), 12 deletions(-)

diff --git a/drivers/net/i40e/i40e_ethdev_vf.c 
b/drivers/net/i40e/i40e_ethdev_vf.c
index ae55b9b18..cecedc91f 100644
--- a/drivers/net/i40e/i40e_ethdev_vf.c
+++ b/drivers/net/i40e/i40e_ethdev_vf.c
@@ -1924,15 +1924,12 @@ static int
 i40evf_dev_start(struct rte_eth_dev *dev)
 {
        struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
-       struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
        struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
        struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
        uint32_t intr_vector = 0;
 
        PMD_INIT_FUNC_TRACE();
 
-       hw->adapter_stopped = 0;
-
        vf->max_pkt_len = dev->data->dev_conf.rxmode.max_rx_pkt_len;
        vf->num_queue_pairs = RTE_MAX(dev->data->nb_rx_queues,
                                        dev->data->nb_tx_queues);
@@ -2004,7 +2001,6 @@ i40evf_dev_stop(struct rte_eth_dev *dev)
 {
        struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
        struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
-       struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
        struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
 
        PMD_INIT_FUNC_TRACE();
@@ -2012,8 +2008,6 @@ i40evf_dev_stop(struct rte_eth_dev *dev)
        if (dev->data->dev_conf.intr_conf.rxq != 0)
                rte_intr_disable(intr_handle);
 
-       if (hw->adapter_stopped == 1)
-               return;
        i40evf_stop_queues(dev);
        i40evf_disable_queues_intr(dev);
        i40e_dev_clear_queues(dev);
@@ -2029,7 +2023,6 @@ i40evf_dev_stop(struct rte_eth_dev *dev)
        /* remove all multicast addresses */
        i40evf_add_del_mc_addr_list(dev, vf->mc_addrs, vf->mc_addrs_num,
                                FALSE);
-       hw->adapter_stopped = 1;
 
 }
 
@@ -2245,21 +2238,32 @@ static void
 i40evf_dev_close(struct rte_eth_dev *dev)
 {
        struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+       struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
+
+       if (dev->data->dev_started != 0) {
+               dev->data->dev_started = 0;
+               i40evf_dev_stop(dev);
+       }
 
-       i40evf_dev_stop(dev);
        i40e_dev_free_queues(dev);
        /*
         * disable promiscuous mode before reset vf
         * it is a workaround solution when work with kernel driver
         * and it is not the normal way
+        *
+        * If VF is reset, AQTX: head overrun at 0xdeadbeef > 32
         */
-       i40evf_dev_promiscuous_disable(dev);
-       i40evf_dev_allmulticast_disable(dev);
+       if (!vf->vf_reset) {
+               i40evf_dev_promiscuous_disable(dev);
+               i40evf_dev_allmulticast_disable(dev);
+               i40evf_reset_vf(hw);
+       }
 
-       i40evf_reset_vf(hw);
+       rte_eal_alarm_cancel(i40evf_dev_alarm_handler, dev);
        i40e_shutdown_adminq(hw);
        i40evf_disable_irq0(hw);
-       rte_eal_alarm_cancel(i40evf_dev_alarm_handler, dev);
+
+       hw->adapter_stopped = 1;
 }
 
 /*
-- 
2.17.1

Reply via email to