PCI PM: Split PCI Express port suspend-resume
authorRafael J. Wysocki <rjw@sisk.pl>
Sat, 27 Dec 2008 15:28:58 +0000 (16:28 +0100)
committerJesse Barnes <jbarnes@virtuousgeek.org>
Wed, 7 Jan 2009 19:13:08 +0000 (11:13 -0800)
Suspend-resume of PCI Express ports has recently been moved into
_suspend_late() and _resume_early() callbacks, but some functions
executed from there should not be called with interrupts disabled,
eg. pci_enable_device().  For this reason, split the suspend-resume
of PCI Express ports into parts to be executed with interrupts
disabled and with interrupts enabled.

Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
drivers/pci/pcie/portdrv_pci.c

index 0549fe2bdac9c53c82e359914ff8ec843e0bca71..99a914a027f8530dc3abe923d3edf33d46bd1a3b 100644 (file)
@@ -41,7 +41,6 @@ static int pcie_portdrv_restore_config(struct pci_dev *dev)
 {
        int retval;
 
-       pci_restore_state(dev);
        retval = pci_enable_device(dev);
        if (retval)
                return retval;
@@ -50,23 +49,32 @@ static int pcie_portdrv_restore_config(struct pci_dev *dev)
 }
 
 #ifdef CONFIG_PM
-static int pcie_portdrv_suspend_late(struct pci_dev *dev, pm_message_t state)
+static int pcie_portdrv_suspend(struct pci_dev *dev, pm_message_t state)
 {
-       int ret = pcie_port_device_suspend(dev, state);
+       return pcie_port_device_suspend(dev, state);
 
-       if (!ret)
-               ret = pcie_portdrv_save_config(dev);
-       return ret;
+}
+
+static int pcie_portdrv_suspend_late(struct pci_dev *dev, pm_message_t state)
+{
+       return pci_save_state(dev);
 }
 
 static int pcie_portdrv_resume_early(struct pci_dev *dev)
+{
+       return pci_restore_state(dev);
+}
+
+static int pcie_portdrv_resume(struct pci_dev *dev)
 {
        pcie_portdrv_restore_config(dev);
        return pcie_port_device_resume(dev);
 }
 #else
+#define pcie_portdrv_suspend NULL
 #define pcie_portdrv_suspend_late NULL
 #define pcie_portdrv_resume_early NULL
+#define pcie_portdrv_resume NULL
 #endif
 
 /*
@@ -221,6 +229,7 @@ static pci_ers_result_t pcie_portdrv_slot_reset(struct pci_dev *dev)
 
        /* If fatal, restore cfg space for possible link reset at upstream */
        if (dev->error_state == pci_channel_io_frozen) {
+               pci_restore_state(dev);
                pcie_portdrv_restore_config(dev);
                pci_enable_pcie_error_reporting(dev);
        }
@@ -282,8 +291,10 @@ static struct pci_driver pcie_portdriver = {
        .probe          = pcie_portdrv_probe,
        .remove         = pcie_portdrv_remove,
 
+       .suspend        = pcie_portdrv_suspend,
        .suspend_late   = pcie_portdrv_suspend_late,
        .resume_early   = pcie_portdrv_resume_early,
+       .resume         = pcie_portdrv_resume,
 
        .err_handler    = &pcie_portdrv_err_handler,
 };