aboutsummaryrefslogtreecommitdiff
path: root/drivers/pci/pci-acpi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci/pci-acpi.c')
-rw-r--r--drivers/pci/pci-acpi.c26
1 files changed, 24 insertions, 2 deletions
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
index 0bddd787490..33317df4769 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 = {