Commit 53d0b3ae authored by Mitch A Williams's avatar Mitch A Williams Committed by Jeff Kirsher

i40evf: refactor shutdown code

If the VF driver is running in the host, the shutdown code is completely
broken. We cannot wait in our down routine for the PF to respond to our
requests, as its admin queue task will never run while we hold the lock.

Instead, we schedule operations, then let the watchdog take care of
shutting things down. If the driver is being removed, then wait in the
remove routine until the watchdog is done before continuing.

Change-ID: I93a58d17389e8d6b58f21e430b56ed7b4590b2c5
Signed-off-by: default avatarMitch Williams <mitch.a.williams@intel.com>
Acked-by: default avatarShannon Nelson <shannon.nelson@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
parent d4f82fd3
......@@ -958,6 +958,12 @@ void i40evf_down(struct i40evf_adapter *adapter)
if (adapter->state == __I40EVF_DOWN)
return;
while (test_and_set_bit(__I40EVF_IN_CRITICAL_TASK,
&adapter->crit_section))
usleep_range(500, 1000);
i40evf_irq_disable(adapter);
/* remove all MAC filters */
list_for_each_entry(f, &adapter->mac_filter_list, list) {
f->remove = true;
......@@ -968,22 +974,27 @@ void i40evf_down(struct i40evf_adapter *adapter)
}
if (!(adapter->flags & I40EVF_FLAG_PF_COMMS_FAILED) &&
adapter->state != __I40EVF_RESETTING) {
adapter->aq_required |= I40EVF_FLAG_AQ_DEL_MAC_FILTER;
/* cancel any current operation */
adapter->current_op = I40E_VIRTCHNL_OP_UNKNOWN;
adapter->aq_pending = 0;
/* Schedule operations to close down the HW. Don't wait
* here for this to complete. The watchdog is still running
* and it will take care of this.
*/
adapter->aq_required = I40EVF_FLAG_AQ_DEL_MAC_FILTER;
adapter->aq_required |= I40EVF_FLAG_AQ_DEL_VLAN_FILTER;
/* disable receives */
adapter->aq_required |= I40EVF_FLAG_AQ_DISABLE_QUEUES;
mod_timer_pending(&adapter->watchdog_timer, jiffies + 1);
msleep(20);
}
netif_tx_disable(netdev);
netif_tx_stop_all_queues(netdev);
i40evf_irq_disable(adapter);
i40evf_napi_disable_all(adapter);
msleep(20);
netif_carrier_off(netdev);
clear_bit(__I40EVF_IN_CRITICAL_TASK, &adapter->crit_section);
}
/**
......@@ -2408,6 +2419,7 @@ static void i40evf_remove(struct pci_dev *pdev)
struct i40evf_adapter *adapter = netdev_priv(netdev);
struct i40evf_mac_filter *f, *ftmp;
struct i40e_hw *hw = &adapter->hw;
int count = 50;
cancel_delayed_work_sync(&adapter->init_task);
cancel_work_sync(&adapter->reset_task);
......@@ -2416,6 +2428,11 @@ static void i40evf_remove(struct pci_dev *pdev)
unregister_netdev(netdev);
adapter->netdev_registered = false;
}
while (count-- && adapter->aq_required)
msleep(50);
if (count < 0)
dev_err(&pdev->dev, "Timed out waiting for PF driver.\n");
adapter->state = __I40EVF_REMOVE;
if (adapter->msix_entries) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment