summaryrefslogtreecommitdiff
path: root/drivers/pci
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci')
-rw-r--r--drivers/pci/pci-acpi.c3
-rw-r--r--drivers/pci/pci-driver.c17
2 files changed, 18 insertions, 2 deletions
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
index c5e1a097d7e3..1897847ceb0c 100644
--- a/drivers/pci/pci-acpi.c
+++ b/drivers/pci/pci-acpi.c
@@ -733,7 +733,8 @@ static bool acpi_pci_need_resume(struct pci_dev *dev)
if (!adev || !acpi_device_power_manageable(adev))
return false;
- if (device_may_wakeup(&dev->dev) != !!adev->wakeup.prepare_count)
+ if (adev->wakeup.flags.valid &&
+ device_may_wakeup(&dev->dev) != !!adev->wakeup.prepare_count)
return true;
if (acpi_target_system_state() == ACPI_STATE_S0)
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index cae630fe6387..5eadbc3d0969 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -734,6 +734,8 @@ static int pci_pm_suspend(struct device *dev)
struct pci_dev *pci_dev = to_pci_dev(dev);
const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+ pci_dev->skip_bus_pm = false;
+
if (pci_has_legacy_pm_support(pci_dev))
return pci_legacy_suspend(dev, PMSG_SUSPEND);
@@ -827,7 +829,20 @@ static int pci_pm_suspend_noirq(struct device *dev)
}
}
- if (!pci_dev->state_saved) {
+ if (pci_dev->skip_bus_pm) {
+ /*
+ * The function is running for the second time in a row without
+ * going through full resume, which is possible only during
+ * suspend-to-idle in a spurious wakeup case. Moreover, the
+ * device was originally left in D0, so its power state should
+ * not be changed here and the device register values saved
+ * originally should be restored on resume again.
+ */
+ pci_dev->state_saved = true;
+ } else if (pci_dev->state_saved) {
+ if (pci_dev->current_state == PCI_D0)
+ pci_dev->skip_bus_pm = true;
+ } else {
pci_save_state(pci_dev);
if (pci_power_manageable(pci_dev))
pci_prepare_to_sleep(pci_dev);