aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/acpi/Makefile3
-rw-r--r--drivers/acpi/device_pm.c91
-rw-r--r--drivers/pci/pci-acpi.c71
-rw-r--r--include/acpi/acpi_bus.h15
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 \
21acpi-y += osl.o utils.o reboot.o 21acpi-y += osl.o utils.o reboot.o
22acpi-y += nvs.o 22acpi-y += nvs.o
23 23
24# sleep related files 24# Power management related files
25acpi-y += wakeup.o 25acpi-y += wakeup.o
26acpi-y += sleep.o 26acpi-y += sleep.o
27acpi-$(CONFIG_PM) += device_pm.o
27acpi-$(CONFIG_ACPI_SLEEP) += proc.o 28acpi-$(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
31static 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 */
43acpi_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 */
70acpi_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
23static 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 */
81static 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 */
109static 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,
137acpi_status pci_acpi_add_bus_pm_notifier(struct acpi_device *dev, 74acpi_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 */
147acpi_status pci_acpi_remove_bus_pm_notifier(struct acpi_device *dev) 84acpi_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)
157acpi_status pci_acpi_add_pm_notifier(struct acpi_device *dev, 94acpi_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 */
167acpi_status pci_acpi_remove_pm_notifier(struct acpi_device *dev) 104acpi_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
172phys_addr_t acpi_pci_root_get_mcfg_addr(acpi_handle handle) 109phys_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);
416int acpi_disable_wakeup_device_power(struct acpi_device *dev); 416int acpi_disable_wakeup_device_power(struct acpi_device *dev);
417 417
418#ifdef CONFIG_PM 418#ifdef CONFIG_PM
419acpi_status acpi_add_pm_notifier(struct acpi_device *adev,
420 acpi_notify_handler handler, void *context);
421acpi_status acpi_remove_pm_notifier(struct acpi_device *adev,
422 acpi_notify_handler handler);
419int acpi_pm_device_sleep_state(struct device *, int *, int); 423int acpi_pm_device_sleep_state(struct device *, int *, int);
420#else 424#else
425static 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}
431static inline acpi_status acpi_remove_pm_notifier(struct acpi_device *adev,
432 acpi_notify_handler handler)
433{
434 return AE_SUPPORT;
435}
421static inline int acpi_pm_device_sleep_state(struct device *d, int *p, int m) 436static inline int acpi_pm_device_sleep_state(struct device *d, int *p, int m)
422{ 437{
423 if (p) 438 if (p)