From 0090def6c37c8ea29508a435e581f2ef26fea10f Mon Sep 17 00:00:00 2001 From: Lin Ming Date: Thu, 29 Mar 2012 14:09:39 +0800 Subject: ACPI: Add interface to register/unregister device to/from power resources Devices may share same list of power resources in _PR0, for example Device(Dev0) { Name (_PR0, Package (0x01) { P0PR, P1PR }) } Device(Dev1) { Name (_PR0, Package (0x01) { P0PR, P1PR } } Assume Dev0 and Dev1 were runtime suspended. Then Dev0 is resumed first and it goes into D0 state. But Dev1 is left in D0_Uninitialised state. This is wrong. In this case, Dev1 must be resumed too. In order to hand this case, each power resource maintains a list of devices which relies on it. When power resource is ON, it will check if the devices on its list can be resumed. The device can only be resumed when all the power resouces of its _PR0 are ON. Signed-off-by: Lin Ming Signed-off-by: Len Brown --- include/acpi/acpi_bus.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include/acpi') diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 6cd5b6403a7b..e168fffe1db5 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -323,6 +323,8 @@ int acpi_bus_set_power(acpi_handle handle, int state); int acpi_bus_update_power(acpi_handle handle, int *state_p); bool acpi_bus_power_manageable(acpi_handle handle); bool acpi_bus_can_wakeup(acpi_handle handle); +int acpi_power_resource_register_device(struct device *dev, acpi_handle handle); +void acpi_power_resource_unregister_device(struct device *dev, acpi_handle handle); #ifdef CONFIG_ACPI_PROC_EVENT int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data); int acpi_bus_generate_proc_event4(const char *class, const char *bid, u8 type, int data); -- cgit v1.2.3 From b24e5098853653554baf6ec975b9e855f3d6e5c0 Mon Sep 17 00:00:00 2001 From: Lin Ming Date: Tue, 27 Mar 2012 15:43:25 +0800 Subject: ACPI, PCI: Move acpi_dev_run_wake() to ACPI core acpi_dev_run_wake() is a generic function which can be used by other subsystem too. Rename it to acpi_pm_device_run_wake, to be consistent with acpi_pm_device_sleep_wake. Then move it to ACPI core. Acked-by: Rafael J. Wysocki Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/acpi/sleep.c | 35 +++++++++++++++++++++++++++++++++++ drivers/pci/pci-acpi.c | 40 +++------------------------------------- include/acpi/acpi_bus.h | 5 +++++ 3 files changed, 43 insertions(+), 37 deletions(-) (limited to 'include/acpi') diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index ca191ff97844..00fa664d5fd8 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -17,6 +17,7 @@ #include #include #include +#include #include @@ -729,6 +730,40 @@ int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p) #endif /* CONFIG_PM */ #ifdef CONFIG_PM_SLEEP +/** + * acpi_pm_device_run_wake - Enable/disable wake-up for given device. + * @phys_dev: Device to enable/disable the platform to wake-up the system for. + * @enable: Whether enable or disable the wake-up functionality. + * + * Find the ACPI device object corresponding to @pci_dev and try to + * enable/disable the GPE associated with it. + */ +int acpi_pm_device_run_wake(struct device *phys_dev, bool enable) +{ + struct acpi_device *dev; + acpi_handle handle; + + if (!device_run_wake(phys_dev)) + return -EINVAL; + + handle = DEVICE_ACPI_HANDLE(phys_dev); + if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &dev))) { + dev_dbg(phys_dev, "ACPI handle has no context in %s!\n", + __func__); + return -ENODEV; + } + + if (enable) { + acpi_enable_wakeup_device_power(dev, ACPI_STATE_S0); + acpi_enable_gpe(dev->wakeup.gpe_device, dev->wakeup.gpe_number); + } else { + acpi_disable_gpe(dev->wakeup.gpe_device, dev->wakeup.gpe_number); + acpi_disable_wakeup_device_power(dev); + } + + return 0; +} + /** * acpi_pm_device_sleep_wake - enable or disable the system wake-up * capability of given device diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index 060fd22a1103..0f150f271c2a 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c @@ -277,40 +277,6 @@ static int acpi_pci_sleep_wake(struct pci_dev *dev, bool enable) return 0; } -/** - * acpi_dev_run_wake - Enable/disable wake-up for given device. - * @phys_dev: Device to enable/disable the platform to wake-up the system for. - * @enable: Whether enable or disable the wake-up functionality. - * - * Find the ACPI device object corresponding to @pci_dev and try to - * enable/disable the GPE associated with it. - */ -static int acpi_dev_run_wake(struct device *phys_dev, bool enable) -{ - struct acpi_device *dev; - acpi_handle handle; - - if (!device_run_wake(phys_dev)) - return -EINVAL; - - handle = DEVICE_ACPI_HANDLE(phys_dev); - if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &dev))) { - dev_dbg(phys_dev, "ACPI handle has no context in %s!\n", - __func__); - return -ENODEV; - } - - if (enable) { - acpi_enable_wakeup_device_power(dev, ACPI_STATE_S0); - acpi_enable_gpe(dev->wakeup.gpe_device, dev->wakeup.gpe_number); - } else { - acpi_disable_gpe(dev->wakeup.gpe_device, dev->wakeup.gpe_number); - acpi_disable_wakeup_device_power(dev); - } - - return 0; -} - static void acpi_pci_propagate_run_wake(struct pci_bus *bus, bool enable) { while (bus->parent) { @@ -318,14 +284,14 @@ static void acpi_pci_propagate_run_wake(struct pci_bus *bus, bool enable) if (bridge->pme_interrupt) return; - if (!acpi_dev_run_wake(&bridge->dev, enable)) + if (!acpi_pm_device_run_wake(&bridge->dev, enable)) return; bus = bus->parent; } /* We have reached the root bus. */ if (bus->bridge) - acpi_dev_run_wake(bus->bridge, enable); + acpi_pm_device_run_wake(bus->bridge, enable); } static int acpi_pci_run_wake(struct pci_dev *dev, bool enable) @@ -333,7 +299,7 @@ static int acpi_pci_run_wake(struct pci_dev *dev, bool enable) if (dev->pme_interrupt) return 0; - if (!acpi_dev_run_wake(&dev->dev, enable)) + if (!acpi_pm_device_run_wake(&dev->dev, enable)) return 0; acpi_pci_propagate_run_wake(dev->bus, enable); diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index e168fffe1db5..f1c8ca60e824 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -394,8 +394,13 @@ static inline int acpi_pm_device_sleep_state(struct device *d, int *p) #endif #ifdef CONFIG_PM_SLEEP +int acpi_pm_device_run_wake(struct device *, bool); int acpi_pm_device_sleep_wake(struct device *, bool); #else +static inline int acpi_pm_device_run_wake(struct device *dev, bool enable) +{ + return -ENODEV; +} static inline int acpi_pm_device_sleep_wake(struct device *dev, bool enable) { return -ENODEV; -- cgit v1.2.3