aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/device_pm.c
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2012-11-01 20:40:36 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2012-11-14 18:15:17 -0500
commitdee8370cc87e505ef39567f0974e73d59e75d76b (patch)
treea8016fcb6edbdf2fbb01c6d50ded276eed626829 /drivers/acpi/device_pm.c
parentcd7bd02d319eb34fa33d1705cf63f64928643708 (diff)
ACPI / PM: Split device wakeup management routines
Two device wakeup management routines in device_pm.c and sleep.c, acpi_pm_device_run_wake() and acpi_pm_device_sleep_wake(), take a device pointer argument and use it to obtain the ACPI handle of the corresponding ACPI namespace node. That handle is then used to get the address of the struct acpi_device object corresponding to the struct device passed as the argument. Unfortunately, that last operation may be costly, because it involves taking the global ACPI namespace mutex, so it shouldn't be carried out too often. However, the callers of those routines usually call them in a row with acpi_pm_device_sleep_state() which also takes that mutex for the same reason, so it would be more efficient if they ran acpi_bus_get_device() themselves to obtain a pointer to the struct acpi_device object in question and then passed that pointer to the appropriate PM routines. To make that possible, split each of the PM routines mentioned above in two parts, one taking a struct acpi_device pointer argument and the other implementing the current interface for compatibility. Additionally, change acpi_pm_device_run_wake() to actually return an error code if there is an error while setting up runtime remote wakeup for the device. Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/acpi/device_pm.c')
-rw-r--r--drivers/acpi/device_pm.c74
1 files changed, 57 insertions, 17 deletions
diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c
index 81052981045e..b4f03f91b0b0 100644
--- a/drivers/acpi/device_pm.c
+++ b/drivers/acpi/device_pm.c
@@ -200,38 +200,78 @@ EXPORT_SYMBOL_GPL(acpi_device_power_state);
200 200
201#ifdef CONFIG_PM_RUNTIME 201#ifdef CONFIG_PM_RUNTIME
202/** 202/**
203 * acpi_pm_device_run_wake - Enable/disable remote wakeup for given device. 203 * __acpi_device_run_wake - Enable/disable runtime remote wakeup for device.
204 * @phys_dev: Device to enable/disable the platform to wake up. 204 * @adev: ACPI device to enable/disable the remote wakeup for.
205 * @enable: Whether to enable or disable the wakeup functionality. 205 * @enable: Whether to enable or disable the wakeup functionality.
206 * 206 *
207 * Find the ACPI device object corresponding to @phys_dev and try to 207 * Enable/disable the GPE associated with @adev so that it can generate
208 * enable/disable the GPE associated with it, so that it can generate 208 * wakeup signals for the device in response to external (remote) events and
209 * wakeup signals for the device in response to external (remote) events. 209 * enable/disable device wakeup power.
210 *
211 * Callers must ensure that @adev is a valid ACPI device node before executing
212 * this function.
213 */
214int __acpi_device_run_wake(struct acpi_device *adev, bool enable)
215{
216 struct acpi_device_wakeup *wakeup = &adev->wakeup;
217
218 if (enable) {
219 acpi_status res;
220 int error;
221
222 error = acpi_enable_wakeup_device_power(adev, ACPI_STATE_S0);
223 if (error)
224 return error;
225
226 res = acpi_enable_gpe(wakeup->gpe_device, wakeup->gpe_number);
227 if (ACPI_FAILURE(res)) {
228 acpi_disable_wakeup_device_power(adev);
229 return -EIO;
230 }
231 } else {
232 acpi_disable_gpe(wakeup->gpe_device, wakeup->gpe_number);
233 acpi_disable_wakeup_device_power(adev);
234 }
235 return 0;
236}
237
238/**
239 * acpi_pm_device_run_wake - Enable/disable remote wakeup for given device.
240 * @dev: Device to enable/disable the platform to wake up.
241 * @enable: Whether to enable or disable the wakeup functionality.
210 */ 242 */
211int acpi_pm_device_run_wake(struct device *phys_dev, bool enable) 243int acpi_pm_device_run_wake(struct device *phys_dev, bool enable)
212{ 244{
213 struct acpi_device *dev; 245 struct acpi_device *adev;
214 acpi_handle handle; 246 acpi_handle handle;
215 247
216 if (!device_run_wake(phys_dev)) 248 if (!device_run_wake(phys_dev))
217 return -EINVAL; 249 return -EINVAL;
218 250
219 handle = DEVICE_ACPI_HANDLE(phys_dev); 251 handle = DEVICE_ACPI_HANDLE(phys_dev);
220 if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &dev))) { 252 if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &adev))) {
221 dev_dbg(phys_dev, "ACPI handle has no context in %s!\n", 253 dev_dbg(phys_dev, "ACPI handle without context in %s!\n",
222 __func__); 254 __func__);
223 return -ENODEV; 255 return -ENODEV;
224 } 256 }
225 257
226 if (enable) { 258 return __acpi_device_run_wake(adev, enable);
227 acpi_enable_wakeup_device_power(dev, ACPI_STATE_S0);
228 acpi_enable_gpe(dev->wakeup.gpe_device, dev->wakeup.gpe_number);
229 } else {
230 acpi_disable_gpe(dev->wakeup.gpe_device, dev->wakeup.gpe_number);
231 acpi_disable_wakeup_device_power(dev);
232 }
233
234 return 0;
235} 259}
236EXPORT_SYMBOL(acpi_pm_device_run_wake); 260EXPORT_SYMBOL(acpi_pm_device_run_wake);
237#endif /* CONFIG_PM_RUNTIME */ 261#endif /* CONFIG_PM_RUNTIME */
262
263 #ifdef CONFIG_PM_SLEEP
264/**
265 * __acpi_device_sleep_wake - Enable or disable device to wake up the system.
266 * @dev: Device to enable/desible to wake up the system.
267 * @target_state: System state the device is supposed to wake up from.
268 * @enable: Whether to enable or disable @dev to wake up the system.
269 */
270int __acpi_device_sleep_wake(struct acpi_device *adev, u32 target_state,
271 bool enable)
272{
273 return enable ?
274 acpi_enable_wakeup_device_power(adev, target_state) :
275 acpi_disable_wakeup_device_power(adev);
276}
277#endif /* CONFIG_PM_SLEEP */