summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRafael J. Wysocki <rjw@sisk.pl>2009-01-14 00:40:38 +0100
committerGreg Kroah-Hartman <gregkh@suse.de>2009-01-18 10:35:46 -0800
commite1e04d6acc86af7ed9160e73bab9dc6bc9e0e5cf (patch)
tree1789ed38298cab24a74ed343f6c45e644b190cc6
parent939c599209d596d205cc44a7fb41b727f20fc459 (diff)
PCI PM: Split PCI Express port suspend-resume
commit a79d682f789730dfabaebbb507c87a90c0671a62 upstream 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> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--drivers/pci/pcie/portdrv_pci.c23
1 files changed, 17 insertions, 6 deletions
diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c
index 2f7bb3f50992..6abfafc50c63 100644
--- a/drivers/pci/pcie/portdrv_pci.c
+++ b/drivers/pci/pcie/portdrv_pci.c
@@ -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,
};