|
@@ -1143,6 +1143,7 @@ void i40evf_down(struct i40evf_adapter *adapter)
|
|
|
}
|
|
|
|
|
|
clear_bit(__I40EVF_IN_CRITICAL_TASK, &adapter->crit_section);
|
|
|
+ mod_timer_pending(&adapter->watchdog_timer, jiffies + 1);
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -1794,6 +1795,7 @@ static void i40evf_disable_vf(struct i40evf_adapter *adapter)
|
|
|
clear_bit(__I40EVF_IN_CRITICAL_TASK, &adapter->crit_section);
|
|
|
adapter->flags &= ~I40EVF_FLAG_RESET_PENDING;
|
|
|
adapter->state = __I40EVF_DOWN;
|
|
|
+ wake_up(&adapter->down_waitqueue);
|
|
|
dev_info(&adapter->pdev->dev, "Reset task did not complete, VF disabled\n");
|
|
|
}
|
|
|
|
|
@@ -1939,6 +1941,7 @@ continue_reset:
|
|
|
i40evf_irq_enable(adapter, true);
|
|
|
} else {
|
|
|
adapter->state = __I40EVF_DOWN;
|
|
|
+ wake_up(&adapter->down_waitqueue);
|
|
|
}
|
|
|
|
|
|
return;
|
|
@@ -2238,6 +2241,7 @@ err_setup_tx:
|
|
|
static int i40evf_close(struct net_device *netdev)
|
|
|
{
|
|
|
struct i40evf_adapter *adapter = netdev_priv(netdev);
|
|
|
+ int status;
|
|
|
|
|
|
if (adapter->state <= __I40EVF_DOWN_PENDING)
|
|
|
return 0;
|
|
@@ -2255,7 +2259,18 @@ static int i40evf_close(struct net_device *netdev)
|
|
|
* still active and can DMA into memory. Resources are cleared in
|
|
|
* i40evf_virtchnl_completion() after we get confirmation from the PF
|
|
|
* driver that the rings have been stopped.
|
|
|
+ *
|
|
|
+ * Also, we wait for state to transition to __I40EVF_DOWN before
|
|
|
+ * returning. State change occurs in i40evf_virtchnl_completion() after
|
|
|
+ * VF resources are released (which occurs after PF driver processes and
|
|
|
+ * responds to admin queue commands).
|
|
|
*/
|
|
|
+
|
|
|
+ status = wait_event_timeout(adapter->down_waitqueue,
|
|
|
+ adapter->state == __I40EVF_DOWN,
|
|
|
+ msecs_to_jiffies(200));
|
|
|
+ if (!status)
|
|
|
+ netdev_warn(netdev, "Device resources not yet released\n");
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -2683,6 +2698,7 @@ static void i40evf_init_task(struct work_struct *work)
|
|
|
adapter->state = __I40EVF_DOWN;
|
|
|
set_bit(__I40E_VSI_DOWN, adapter->vsi.state);
|
|
|
i40evf_misc_irq_enable(adapter);
|
|
|
+ wake_up(&adapter->down_waitqueue);
|
|
|
|
|
|
adapter->rss_key = kzalloc(adapter->rss_key_size, GFP_KERNEL);
|
|
|
adapter->rss_lut = kzalloc(adapter->rss_lut_size, GFP_KERNEL);
|
|
@@ -2844,6 +2860,9 @@ static int i40evf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|
|
schedule_delayed_work(&adapter->init_task,
|
|
|
msecs_to_jiffies(5 * (pdev->devfn & 0x07)));
|
|
|
|
|
|
+ /* Setup the wait queue for indicating transition to down status */
|
|
|
+ init_waitqueue_head(&adapter->down_waitqueue);
|
|
|
+
|
|
|
return 0;
|
|
|
|
|
|
err_ioremap:
|