vmxnet3: Register shutdown handler for device (fwd)
authorShreyas Bhatewara <sbhatewara@vmware.com>
Fri, 19 Jun 2015 20:36:02 +0000 (13:36 -0700)
committerDavid S. Miller <davem@davemloft.net>
Tue, 23 Jun 2015 13:25:59 +0000 (06:25 -0700)
Implement a handler for pci shutdown so that the driver has an
opportunity to make sure that device is quiesced before the PCI
switches to legacy IRQs. This way the possibility of
"screaming interrupt" is avoided.

Acked-by: Shrikrishna Khare <skhare@vmware.com>
Signed-off-by: Shreyas N Bhatewara <sbhatewara@vmware.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/vmxnet3/vmxnet3_drv.c

index 61c0840c448c05e3e7fc340e4b1d19370db3363c..bb352106fc91692270b0137d32a36b8797ca0255 100644 (file)
@@ -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