summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/acpi/sleep.c2
-rw-r--r--drivers/pci/pci-acpi.c26
2 files changed, 25 insertions, 3 deletions
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c
index ab889becd3f3..feece693d773 100644
--- a/drivers/acpi/sleep.c
+++ b/drivers/acpi/sleep.c
@@ -691,7 +691,7 @@ int acpi_pm_device_sleep_wake(struct device *dev, bool enable)
struct acpi_device *adev;
int error;
- if (!device_may_wakeup(dev))
+ if (!device_can_wakeup(dev))
return -EINVAL;
handle = DEVICE_ACPI_HANDLE(dev);
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
index 0bddd787490d..33317df47699 100644
--- a/drivers/pci/pci-acpi.c
+++ b/drivers/pci/pci-acpi.c
@@ -109,10 +109,32 @@ static bool acpi_pci_can_wakeup(struct pci_dev *dev)
return handle ? acpi_bus_can_wakeup(handle) : false;
}
+static void acpi_pci_propagate_wakeup_enable(struct pci_bus *bus, bool enable)
+{
+ while (bus->parent) {
+ struct pci_dev *bridge = bus->self;
+ int ret;
+
+ ret = acpi_pm_device_sleep_wake(&bridge->dev, enable);
+ if (!ret || bridge->is_pcie)
+ return;
+ bus = bus->parent;
+ }
+
+ /* We have reached the root bus. */
+ if (bus->bridge)
+ acpi_pm_device_sleep_wake(bus->bridge, enable);
+}
+
static int acpi_pci_sleep_wake(struct pci_dev *dev, bool enable)
{
- return acpi_pci_can_wakeup(dev) ?
- acpi_pm_device_sleep_wake(&dev->dev, enable) : 0;
+ if (acpi_pci_can_wakeup(dev))
+ return acpi_pm_device_sleep_wake(&dev->dev, enable);
+
+ if (!dev->is_pcie)
+ acpi_pci_propagate_wakeup_enable(dev->bus, enable);
+
+ return 0;
}
static struct pci_platform_pm_ops acpi_pci_platform_pm = {