summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/vmxnet3/vmxnet3_drv.c27
1 files changed, 27 insertions, 0 deletions
diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c
index 61c0840c448c..bb352106fc91 100644
--- a/drivers/net/vmxnet3/vmxnet3_drv.c
+++ b/drivers/net/vmxnet3/vmxnet3_drv.c
@@ -3184,6 +3184,32 @@ vmxnet3_remove_device(struct pci_dev *pdev)
free_netdev(netdev);
}
+static void vmxnet3_shutdown_device(struct pci_dev *pdev)
+{
+ struct net_device *netdev = pci_get_drvdata(pdev);
+ struct vmxnet3_adapter *adapter = netdev_priv(netdev);
+ unsigned long flags;
+
+ /* Reset_work may be in the middle of resetting the device, wait for its
+ * completion.
+ */
+ while (test_and_set_bit(VMXNET3_STATE_BIT_RESETTING, &adapter->state))
+ msleep(1);
+
+ if (test_and_set_bit(VMXNET3_STATE_BIT_QUIESCED,
+ &adapter->state)) {
+ clear_bit(VMXNET3_STATE_BIT_RESETTING, &adapter->state);
+ return;
+ }
+ spin_lock_irqsave(&adapter->cmd_lock, flags);
+ VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
+ VMXNET3_CMD_QUIESCE_DEV);
+ spin_unlock_irqrestore(&adapter->cmd_lock, flags);
+ vmxnet3_disable_all_intrs(adapter);
+
+ clear_bit(VMXNET3_STATE_BIT_RESETTING, &adapter->state);
+}
+
#ifdef CONFIG_PM
@@ -3360,6 +3386,7 @@ static struct pci_driver vmxnet3_driver = {
.id_table = vmxnet3_pciid_table,
.probe = vmxnet3_probe_device,
.remove = vmxnet3_remove_device,
+ .shutdown = vmxnet3_shutdown_device,
#ifdef CONFIG_PM
.driver.pm = &vmxnet3_pm_ops,
#endif