aboutsummaryrefslogtreecommitdiff
path: root/drivers/pci/pci-driver.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-02-02 19:28:58 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2009-02-02 19:28:58 -0800
commitb1792e367053968f2ddb48bc911d314143ce6242 (patch)
tree31ac3fddb0b14a202e9ceaa9681c1335ba35210c /drivers/pci/pci-driver.c
parent859281ff370977f917ec2195f86a5bfccf1fc6d6 (diff)
parent71a082efc9fdc12068a3cee6cebb1330b00ebeee (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci-2.6: PCI hotplug: Change link order of pciehp & acpiphp PCI hotplug: fakephp: Allocate PCI resources before adding the device PCI MSI: Fix undefined shift by 32 PCI PM: Do not wait for buses in B2 or B3 during resume PCI PM: Power up devices before restoring their state PCI PM: Fix hibernation breakage on EeePC 701 PCI: irq and pci_ids patch for Intel Tigerpoint DeviceIDs PCI PM: Fix suspend error paths and testing facility breakage
Diffstat (limited to 'drivers/pci/pci-driver.c')
-rw-r--r--drivers/pci/pci-driver.c21
1 files changed, 20 insertions, 1 deletions
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index 9de07b75b99..ab1d615425a 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -370,6 +370,7 @@ static int pci_legacy_suspend(struct device *dev, pm_message_t state)
}
pci_save_state(pci_dev);
+ pci_dev->state_saved = true;
/*
* This is for compatibility with existing code with legacy PM support.
*/
@@ -419,6 +420,7 @@ static int pci_legacy_resume(struct device *dev)
static void pci_pm_default_resume_noirq(struct pci_dev *pci_dev)
{
pci_restore_standard_config(pci_dev);
+ pci_dev->state_saved = false;
pci_fixup_device(pci_fixup_resume_early, pci_dev);
}
@@ -555,6 +557,13 @@ static int pci_pm_resume(struct device *dev)
struct device_driver *drv = dev->driver;
int error = 0;
+ /*
+ * This is necessary for the suspend error path in which resume is
+ * called without restoring the standard config registers of the device.
+ */
+ if (pci_dev->state_saved)
+ pci_restore_standard_config(pci_dev);
+
if (pci_has_legacy_pm_support(pci_dev))
return pci_legacy_resume(dev);
@@ -660,7 +669,10 @@ static int pci_pm_poweroff(struct device *dev)
if (pci_has_legacy_pm_support(pci_dev))
return pci_legacy_suspend(dev, PMSG_HIBERNATE);
- if (drv && drv->pm && drv->pm->poweroff) {
+ if (!drv || !drv->pm)
+ return 0;
+
+ if (drv->pm->poweroff) {
error = drv->pm->poweroff(dev);
suspend_report_result(drv->pm->poweroff, error);
}
@@ -710,6 +722,13 @@ static int pci_pm_restore(struct device *dev)
struct device_driver *drv = dev->driver;
int error = 0;
+ /*
+ * This is necessary for the hibernation error path in which restore is
+ * called without restoring the standard config registers of the device.
+ */
+ if (pci_dev->state_saved)
+ pci_restore_standard_config(pci_dev);
+
if (pci_has_legacy_pm_support(pci_dev))
return pci_legacy_resume(dev);