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 82422fe90f81..a2711fae62d8 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile | |||
@@ -21,9 +21,10 @@ obj-y += acpi.o \ | |||
21 | acpi-y += osl.o utils.o reboot.o | 21 | acpi-y += osl.o utils.o reboot.o |
22 | acpi-y += nvs.o | 22 | acpi-y += nvs.o |
23 | 23 | ||
24 | # sleep related files | 24 | # Power management related files |
25 | acpi-y += wakeup.o | 25 | acpi-y += wakeup.o |
26 | acpi-y += sleep.o | 26 | acpi-y += sleep.o |
27 | acpi-$(CONFIG_PM) += device_pm.o | ||
27 | acpi-$(CONFIG_ACPI_SLEEP) += proc.o | 28 | acpi-$(CONFIG_ACPI_SLEEP) += proc.o |
28 | 29 | ||
29 | 30 | ||
diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c new file mode 100644 index 000000000000..2d2e0bc8891b --- /dev/null +++ b/drivers/acpi/device_pm.c | |||
@@ -0,0 +1,91 @@ | |||
1 | /* | ||
2 | * drivers/acpi/device_pm.c - ACPI device power management routines. | ||
3 | * | ||
4 | * Copyright (C) 2012, Intel Corp. | ||
5 | * Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com> | ||
6 | * | ||
7 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as published | ||
11 | * by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License along | ||
19 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
20 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. | ||
21 | * | ||
22 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
23 | */ | ||
24 | |||
25 | #include <linux/device.h> | ||
26 | #include <linux/mutex.h> | ||
27 | |||
28 | #include <acpi/acpi.h> | ||
29 | #include <acpi/acpi_bus.h> | ||
30 | |||
31 | static DEFINE_MUTEX(acpi_pm_notifier_lock); | ||
32 | |||
33 | /** | ||
34 | * acpi_add_pm_notifier - Register PM notifier for given ACPI device. | ||
35 | * @adev: ACPI device to add the notifier for. | ||
36 | * @context: Context information to pass to the notifier routine. | ||
37 | * | ||
38 | * NOTE: @adev need not be a run-wake or wakeup device to be a valid source of | ||
39 | * PM wakeup events. For example, wakeup events may be generated for bridges | ||
40 | * if one of the devices below the bridge is signaling wakeup, even if the | ||
41 | * bridge itself doesn't have a wakeup GPE associated with it. | ||
42 | */ | ||
43 | acpi_status acpi_add_pm_notifier(struct acpi_device *adev, | ||
44 | acpi_notify_handler handler, void *context) | ||
45 | { | ||
46 | acpi_status status = AE_ALREADY_EXISTS; | ||
47 | |||
48 | mutex_lock(&acpi_pm_notifier_lock); | ||
49 | |||
50 | if (adev->wakeup.flags.notifier_present) | ||
51 | goto out; | ||
52 | |||
53 | status = acpi_install_notify_handler(adev->handle, | ||
54 | ACPI_SYSTEM_NOTIFY, | ||
55 | handler, context); | ||
56 | if (ACPI_FAILURE(status)) | ||
57 | goto out; | ||
58 | |||
59 | adev->wakeup.flags.notifier_present = true; | ||
60 | |||
61 | out: | ||
62 | mutex_unlock(&acpi_pm_notifier_lock); | ||
63 | return status; | ||
64 | } | ||
65 | |||
66 | /** | ||
67 | * acpi_remove_pm_notifier - Unregister PM notifier from given ACPI device. | ||
68 | * @adev: ACPI device to remove the notifier from. | ||
69 | */ | ||
70 | acpi_status acpi_remove_pm_notifier(struct acpi_device *adev, | ||
71 | acpi_notify_handler handler) | ||
72 | { | ||
73 | acpi_status status = AE_BAD_PARAMETER; | ||
74 | |||
75 | mutex_lock(&acpi_pm_notifier_lock); | ||
76 | |||
77 | if (!adev->wakeup.flags.notifier_present) | ||
78 | goto out; | ||
79 | |||
80 | status = acpi_remove_notify_handler(adev->handle, | ||
81 | ACPI_SYSTEM_NOTIFY, | ||
82 | handler); | ||
83 | if (ACPI_FAILURE(status)) | ||
84 | goto out; | ||
85 | |||
86 | adev->wakeup.flags.notifier_present = false; | ||
87 | |||
88 | out: | ||
89 | mutex_unlock(&acpi_pm_notifier_lock); | ||
90 | return status; | ||
91 | } | ||
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index 63d6618a4804..1af4008182fd 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c | |||
@@ -20,8 +20,6 @@ | |||
20 | #include <linux/pm_qos.h> | 20 | #include <linux/pm_qos.h> |
21 | #include "pci.h" | 21 | #include "pci.h" |
22 | 22 | ||
23 | static DEFINE_MUTEX(pci_acpi_pm_notify_mtx); | ||
24 | |||
25 | /** | 23 | /** |
26 | * pci_acpi_wake_bus - Wake-up notification handler for root buses. | 24 | * pci_acpi_wake_bus - Wake-up notification handler for root buses. |
27 | * @handle: ACPI handle of a device the notification is for. | 25 | * @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) | |||
69 | } | 67 | } |
70 | 68 | ||
71 | /** | 69 | /** |
72 | * add_pm_notifier - Register PM notifier for given ACPI device. | ||
73 | * @dev: ACPI device to add the notifier for. | ||
74 | * @context: PCI device or bus to check for PME status if an event is signaled. | ||
75 | * | ||
76 | * NOTE: @dev need not be a run-wake or wake-up device to be a valid source of | ||
77 | * PM wake-up events. For example, wake-up events may be generated for bridges | ||
78 | * if one of the devices below the bridge is signaling PME, even if the bridge | ||
79 | * itself doesn't have a wake-up GPE associated with it. | ||
80 | */ | ||
81 | static acpi_status add_pm_notifier(struct acpi_device *dev, | ||
82 | acpi_notify_handler handler, | ||
83 | void *context) | ||
84 | { | ||
85 | acpi_status status = AE_ALREADY_EXISTS; | ||
86 | |||
87 | mutex_lock(&pci_acpi_pm_notify_mtx); | ||
88 | |||
89 | if (dev->wakeup.flags.notifier_present) | ||
90 | goto out; | ||
91 | |||
92 | status = acpi_install_notify_handler(dev->handle, | ||
93 | ACPI_SYSTEM_NOTIFY, | ||
94 | handler, context); | ||
95 | if (ACPI_FAILURE(status)) | ||
96 | goto out; | ||
97 | |||
98 | dev->wakeup.flags.notifier_present = true; | ||
99 | |||
100 | out: | ||
101 | mutex_unlock(&pci_acpi_pm_notify_mtx); | ||
102 | return status; | ||
103 | } | ||
104 | |||
105 | /** | ||
106 | * remove_pm_notifier - Unregister PM notifier from given ACPI device. | ||
107 | * @dev: ACPI device to remove the notifier from. | ||
108 | */ | ||
109 | static acpi_status remove_pm_notifier(struct acpi_device *dev, | ||
110 | acpi_notify_handler handler) | ||
111 | { | ||
112 | acpi_status status = AE_BAD_PARAMETER; | ||
113 | |||
114 | mutex_lock(&pci_acpi_pm_notify_mtx); | ||
115 | |||
116 | if (!dev->wakeup.flags.notifier_present) | ||
117 | goto out; | ||
118 | |||
119 | status = acpi_remove_notify_handler(dev->handle, | ||
120 | ACPI_SYSTEM_NOTIFY, | ||
121 | handler); | ||
122 | if (ACPI_FAILURE(status)) | ||
123 | goto out; | ||
124 | |||
125 | dev->wakeup.flags.notifier_present = false; | ||
126 | |||
127 | out: | ||
128 | mutex_unlock(&pci_acpi_pm_notify_mtx); | ||
129 | return status; | ||
130 | } | ||
131 | |||
132 | /** | ||
133 | * pci_acpi_add_bus_pm_notifier - Register PM notifier for given PCI bus. | 70 | * pci_acpi_add_bus_pm_notifier - Register PM notifier for given PCI bus. |
134 | * @dev: ACPI device to add the notifier for. | 71 | * @dev: ACPI device to add the notifier for. |
135 | * @pci_bus: PCI bus to walk checking for PME status if an event is signaled. | 72 | * @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, | |||
137 | acpi_status pci_acpi_add_bus_pm_notifier(struct acpi_device *dev, | 74 | acpi_status pci_acpi_add_bus_pm_notifier(struct acpi_device *dev, |
138 | struct pci_bus *pci_bus) | 75 | struct pci_bus *pci_bus) |
139 | { | 76 | { |
140 | return add_pm_notifier(dev, pci_acpi_wake_bus, pci_bus); | 77 | return acpi_add_pm_notifier(dev, pci_acpi_wake_bus, pci_bus); |
141 | } | 78 | } |
142 | 79 | ||
143 | /** | 80 | /** |
@@ -146,7 +83,7 @@ acpi_status pci_acpi_add_bus_pm_notifier(struct acpi_device *dev, | |||
146 | */ | 83 | */ |
147 | acpi_status pci_acpi_remove_bus_pm_notifier(struct acpi_device *dev) | 84 | acpi_status pci_acpi_remove_bus_pm_notifier(struct acpi_device *dev) |
148 | { | 85 | { |
149 | return remove_pm_notifier(dev, pci_acpi_wake_bus); | 86 | return acpi_remove_pm_notifier(dev, pci_acpi_wake_bus); |
150 | } | 87 | } |
151 | 88 | ||
152 | /** | 89 | /** |
@@ -157,7 +94,7 @@ acpi_status pci_acpi_remove_bus_pm_notifier(struct acpi_device *dev) | |||
157 | acpi_status pci_acpi_add_pm_notifier(struct acpi_device *dev, | 94 | acpi_status pci_acpi_add_pm_notifier(struct acpi_device *dev, |
158 | struct pci_dev *pci_dev) | 95 | struct pci_dev *pci_dev) |
159 | { | 96 | { |
160 | return add_pm_notifier(dev, pci_acpi_wake_dev, pci_dev); | 97 | return acpi_add_pm_notifier(dev, pci_acpi_wake_dev, pci_dev); |
161 | } | 98 | } |
162 | 99 | ||
163 | /** | 100 | /** |
@@ -166,7 +103,7 @@ acpi_status pci_acpi_add_pm_notifier(struct acpi_device *dev, | |||
166 | */ | 103 | */ |
167 | acpi_status pci_acpi_remove_pm_notifier(struct acpi_device *dev) | 104 | acpi_status pci_acpi_remove_pm_notifier(struct acpi_device *dev) |
168 | { | 105 | { |
169 | return remove_pm_notifier(dev, pci_acpi_wake_dev); | 106 | return acpi_remove_pm_notifier(dev, pci_acpi_wake_dev); |
170 | } | 107 | } |
171 | 108 | ||
172 | phys_addr_t acpi_pci_root_get_mcfg_addr(acpi_handle handle) | 109 | 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 72053db9c2ec..6983272f9d02 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); | |||
416 | int acpi_disable_wakeup_device_power(struct acpi_device *dev); | 416 | int acpi_disable_wakeup_device_power(struct acpi_device *dev); |
417 | 417 | ||
418 | #ifdef CONFIG_PM | 418 | #ifdef CONFIG_PM |
419 | acpi_status acpi_add_pm_notifier(struct acpi_device *adev, | ||
420 | acpi_notify_handler handler, void *context); | ||
421 | acpi_status acpi_remove_pm_notifier(struct acpi_device *adev, | ||
422 | acpi_notify_handler handler); | ||
419 | int acpi_pm_device_sleep_state(struct device *, int *, int); | 423 | int acpi_pm_device_sleep_state(struct device *, int *, int); |
420 | #else | 424 | #else |
425 | static inline acpi_status acpi_add_pm_notifier(struct acpi_device *adev, | ||
426 | acpi_notify_handler handler, | ||
427 | void *context) | ||
428 | { | ||
429 | return AE_SUPPORT; | ||
430 | } | ||
431 | static inline acpi_status acpi_remove_pm_notifier(struct acpi_device *adev, | ||
432 | acpi_notify_handler handler) | ||
433 | { | ||
434 | return AE_SUPPORT; | ||
435 | } | ||
421 | static inline int acpi_pm_device_sleep_state(struct device *d, int *p, int m) | 436 | static inline int acpi_pm_device_sleep_state(struct device *d, int *p, int m) |
422 | { | 437 | { |
423 | if (p) | 438 | if (p) |