diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/acpi/sleep.c | 2 | ||||
-rw-r--r-- | drivers/pci/pci-acpi.c | 26 |
2 files changed, 25 insertions, 3 deletions
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index ab889becd3f..feece693d77 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 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 = { |