diff options
-rw-r--r-- | drivers/acpi/Makefile | 3 | ||||
-rw-r--r-- | drivers/acpi/device_pm.c | 91 | ||||
-rw-r--r-- | drivers/pci/pci-acpi.c | 71 | ||||
-rw-r--r-- | include/acpi/acpi_bus.h | 15 |
4 files changed, 112 insertions, 68 deletions
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index 82422fe90f8..a2711fae62d 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -21,9 +21,10 @@ obj-y += acpi.o \ acpi-y += osl.o utils.o reboot.o acpi-y += nvs.o -# sleep related files +# Power management related files acpi-y += wakeup.o acpi-y += sleep.o +acpi-$(CONFIG_PM) += device_pm.o acpi-$(CONFIG_ACPI_SLEEP) += proc.o diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c new file mode 100644 index 00000000000..2d2e0bc8891 --- /dev/null +++ b/drivers/acpi/device_pm.c @@ -0,0 +1,91 @@ +/* + * drivers/acpi/device_pm.c - ACPI device power management routines. + * + * Copyright (C) 2012, Intel Corp. + * Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com> + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + */ + +#include <linux/device.h> +#include <linux/mutex.h> + +#include <acpi/acpi.h> +#include <acpi/acpi_bus.h> + +static DEFINE_MUTEX(acpi_pm_notifier_lock); + +/** + * acpi_add_pm_notifier - Register PM notifier for given ACPI device. + * @adev: ACPI device to add the notifier for. + * @context: Context information to pass to the notifier routine. + * + * NOTE: @adev need not be a run-wake or wakeup device to be a valid source of + * PM wakeup events. For example, wakeup events may be generated for bridges + * if one of the devices below the bridge is signaling wakeup, even if the + * bridge itself doesn't have a wakeup GPE associated with it. + */ +acpi_status acpi_add_pm_notifier(struct acpi_device *adev, + acpi_notify_handler handler, void *context) +{ + acpi_status status = AE_ALREADY_EXISTS; + + mutex_lock(&acpi_pm_notifier_lock); + + if (adev->wakeup.flags.notifier_present) + goto out; + + status = acpi_install_notify_handler(adev->handle, + ACPI_SYSTEM_NOTIFY, + handler, context); + if (ACPI_FAILURE(status)) + goto out; + + adev->wakeup.flags.notifier_present = true; + + out: + mutex_unlock(&acpi_pm_notifier_lock); + return status; +} + +/** + * acpi_remove_pm_notifier - Unregister PM notifier from given ACPI device. + * @adev: ACPI device to remove the notifier from. + */ +acpi_status acpi_remove_pm_notifier(struct acpi_device *adev, + acpi_notify_handler handler) +{ + acpi_status status = AE_BAD_PARAMETER; + + mutex_lock(&acpi_pm_notifier_lock); + + if (!adev->wakeup.flags.notifier_present) + goto out; + + status = acpi_remove_notify_handler(adev->handle, + ACPI_SYSTEM_NOTIFY, + handler); + if (ACPI_FAILURE(status)) + goto out; + + adev->wakeup.flags.notifier_present = false; + + out: + mutex_unlock(&acpi_pm_notifier_lock); + return status; +} diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index 63d6618a480..1af4008182f 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c @@ -20,8 +20,6 @@ #include <linux/pm_qos.h> #include "pci.h" -static DEFINE_MUTEX(pci_acpi_pm_notify_mtx); - /** * pci_acpi_wake_bus - Wake-up notification handler for root buses. * @handle: ACPI handle of a device the notification is for. @@ -69,67 +67,6 @@ static void pci_acpi_wake_dev(acpi_handle handle, u32 event, void *context) } /** - * add_pm_notifier - Register PM notifier for given ACPI device. - * @dev: ACPI device to add the notifier for. - * @context: PCI device or bus to check for PME status if an event is signaled. - * - * NOTE: @dev need not be a run-wake or wake-up device to be a valid source of - * PM wake-up events. For example, wake-up events may be generated for bridges - * if one of the devices below the bridge is signaling PME, even if the bridge - * itself doesn't have a wake-up GPE associated with it. - */ -static acpi_status add_pm_notifier(struct acpi_device *dev, - acpi_notify_handler handler, - void *context) -{ - acpi_status status = AE_ALREADY_EXISTS; - - mutex_lock(&pci_acpi_pm_notify_mtx); - - if (dev->wakeup.flags.notifier_present) - goto out; - - status = acpi_install_notify_handler(dev->handle, - ACPI_SYSTEM_NOTIFY, - handler, context); - if (ACPI_FAILURE(status)) - goto out; - - dev->wakeup.flags.notifier_present = true; - - out: - mutex_unlock(&pci_acpi_pm_notify_mtx); - return status; -} - -/** - * remove_pm_notifier - Unregister PM notifier from given ACPI device. - * @dev: ACPI device to remove the notifier from. - */ -static acpi_status remove_pm_notifier(struct acpi_device *dev, - acpi_notify_handler handler) -{ - acpi_status status = AE_BAD_PARAMETER; - - mutex_lock(&pci_acpi_pm_notify_mtx); - - if (!dev->wakeup.flags.notifier_present) - goto out; - - status = acpi_remove_notify_handler(dev->handle, - ACPI_SYSTEM_NOTIFY, - handler); - if (ACPI_FAILURE(status)) - goto out; - - dev->wakeup.flags.notifier_present = false; - - out: - mutex_unlock(&pci_acpi_pm_notify_mtx); - return status; -} - -/** * pci_acpi_add_bus_pm_notifier - Register PM notifier for given PCI bus. * @dev: ACPI device to add the notifier for. * @pci_bus: PCI bus to walk checking for PME status if an event is signaled. @@ -137,7 +74,7 @@ static acpi_status remove_pm_notifier(struct acpi_device *dev, acpi_status pci_acpi_add_bus_pm_notifier(struct acpi_device *dev, struct pci_bus *pci_bus) { - return add_pm_notifier(dev, pci_acpi_wake_bus, pci_bus); + return acpi_add_pm_notifier(dev, pci_acpi_wake_bus, pci_bus); } /** @@ -146,7 +83,7 @@ acpi_status pci_acpi_add_bus_pm_notifier(struct acpi_device *dev, */ acpi_status pci_acpi_remove_bus_pm_notifier(struct acpi_device *dev) { - return remove_pm_notifier(dev, pci_acpi_wake_bus); + return acpi_remove_pm_notifier(dev, pci_acpi_wake_bus); } /** @@ -157,7 +94,7 @@ acpi_status pci_acpi_remove_bus_pm_notifier(struct acpi_device *dev) acpi_status pci_acpi_add_pm_notifier(struct acpi_device *dev, struct pci_dev *pci_dev) { - return add_pm_notifier(dev, pci_acpi_wake_dev, pci_dev); + return acpi_add_pm_notifier(dev, pci_acpi_wake_dev, pci_dev); } /** @@ -166,7 +103,7 @@ acpi_status pci_acpi_add_pm_notifier(struct acpi_device *dev, */ acpi_status pci_acpi_remove_pm_notifier(struct acpi_device *dev) { - return remove_pm_notifier(dev, pci_acpi_wake_dev); + return acpi_remove_pm_notifier(dev, pci_acpi_wake_dev); } phys_addr_t acpi_pci_root_get_mcfg_addr(acpi_handle handle) diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 72053db9c2e..6983272f9d0 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -416,8 +416,23 @@ int acpi_enable_wakeup_device_power(struct acpi_device *dev, int state); int acpi_disable_wakeup_device_power(struct acpi_device *dev); #ifdef CONFIG_PM +acpi_status acpi_add_pm_notifier(struct acpi_device *adev, + acpi_notify_handler handler, void *context); +acpi_status acpi_remove_pm_notifier(struct acpi_device *adev, + acpi_notify_handler handler); int acpi_pm_device_sleep_state(struct device *, int *, int); #else +static inline acpi_status acpi_add_pm_notifier(struct acpi_device *adev, + acpi_notify_handler handler, + void *context) +{ + return AE_SUPPORT; +} +static inline acpi_status acpi_remove_pm_notifier(struct acpi_device *adev, + acpi_notify_handler handler) +{ + return AE_SUPPORT; +} static inline int acpi_pm_device_sleep_state(struct device *d, int *p, int m) { if (p) |