diff options
-rw-r--r-- | drivers/net/vmxnet3/vmxnet3_drv.c | 27 |
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 |