aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/device_pm.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/device_pm.c')
-rw-r--r--drivers/acpi/device_pm.c136
1 files changed, 70 insertions, 66 deletions
diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c
index 96de787e6104..318fa32a141e 100644
--- a/drivers/acpi/device_pm.c
+++ b/drivers/acpi/device_pm.c
@@ -37,68 +37,6 @@
37#define _COMPONENT ACPI_POWER_COMPONENT 37#define _COMPONENT ACPI_POWER_COMPONENT
38ACPI_MODULE_NAME("device_pm"); 38ACPI_MODULE_NAME("device_pm");
39 39
40static DEFINE_MUTEX(acpi_pm_notifier_lock);
41
42/**
43 * acpi_add_pm_notifier - Register PM notifier for given ACPI device.
44 * @adev: ACPI device to add the notifier for.
45 * @context: Context information to pass to the notifier routine.
46 *
47 * NOTE: @adev need not be a run-wake or wakeup device to be a valid source of
48 * PM wakeup events. For example, wakeup events may be generated for bridges
49 * if one of the devices below the bridge is signaling wakeup, even if the
50 * bridge itself doesn't have a wakeup GPE associated with it.
51 */
52acpi_status acpi_add_pm_notifier(struct acpi_device *adev,
53 acpi_notify_handler handler, void *context)
54{
55 acpi_status status = AE_ALREADY_EXISTS;
56
57 mutex_lock(&acpi_pm_notifier_lock);
58
59 if (adev->wakeup.flags.notifier_present)
60 goto out;
61
62 status = acpi_install_notify_handler(adev->handle,
63 ACPI_SYSTEM_NOTIFY,
64 handler, context);
65 if (ACPI_FAILURE(status))
66 goto out;
67
68 adev->wakeup.flags.notifier_present = true;
69
70 out:
71 mutex_unlock(&acpi_pm_notifier_lock);
72 return status;
73}
74
75/**
76 * acpi_remove_pm_notifier - Unregister PM notifier from given ACPI device.
77 * @adev: ACPI device to remove the notifier from.
78 */
79acpi_status acpi_remove_pm_notifier(struct acpi_device *adev,
80 acpi_notify_handler handler)
81{
82 acpi_status status = AE_BAD_PARAMETER;
83
84 mutex_lock(&acpi_pm_notifier_lock);
85
86 if (!adev->wakeup.flags.notifier_present)
87 goto out;
88
89 status = acpi_remove_notify_handler(adev->handle,
90 ACPI_SYSTEM_NOTIFY,
91 handler);
92 if (ACPI_FAILURE(status))
93 goto out;
94
95 adev->wakeup.flags.notifier_present = false;
96
97 out:
98 mutex_unlock(&acpi_pm_notifier_lock);
99 return status;
100}
101
102/** 40/**
103 * acpi_power_state_string - String representation of ACPI device power state. 41 * acpi_power_state_string - String representation of ACPI device power state.
104 * @state: ACPI device power state to return the string representation of. 42 * @state: ACPI device power state to return the string representation of.
@@ -340,11 +278,13 @@ int acpi_bus_init_power(struct acpi_device *device)
340 if (result) 278 if (result)
341 return result; 279 return result;
342 } else if (state == ACPI_STATE_UNKNOWN) { 280 } else if (state == ACPI_STATE_UNKNOWN) {
343 /* No power resources and missing _PSC? Try to force D0. */ 281 /*
282 * No power resources and missing _PSC? Cross fingers and make
283 * it D0 in hope that this is what the BIOS put the device into.
284 * [We tried to force D0 here by executing _PS0, but that broke
285 * Toshiba P870-303 in a nasty way.]
286 */
344 state = ACPI_STATE_D0; 287 state = ACPI_STATE_D0;
345 result = acpi_dev_pm_explicit_set(device, state);
346 if (result)
347 return result;
348 } 288 }
349 device->power.state = state; 289 device->power.state = state;
350 return 0; 290 return 0;
@@ -385,6 +325,69 @@ bool acpi_bus_power_manageable(acpi_handle handle)
385} 325}
386EXPORT_SYMBOL(acpi_bus_power_manageable); 326EXPORT_SYMBOL(acpi_bus_power_manageable);
387 327
328#ifdef CONFIG_PM
329static DEFINE_MUTEX(acpi_pm_notifier_lock);
330
331/**
332 * acpi_add_pm_notifier - Register PM notifier for given ACPI device.
333 * @adev: ACPI device to add the notifier for.
334 * @context: Context information to pass to the notifier routine.
335 *
336 * NOTE: @adev need not be a run-wake or wakeup device to be a valid source of
337 * PM wakeup events. For example, wakeup events may be generated for bridges
338 * if one of the devices below the bridge is signaling wakeup, even if the
339 * bridge itself doesn't have a wakeup GPE associated with it.
340 */
341acpi_status acpi_add_pm_notifier(struct acpi_device *adev,
342 acpi_notify_handler handler, void *context)
343{
344 acpi_status status = AE_ALREADY_EXISTS;
345
346 mutex_lock(&acpi_pm_notifier_lock);
347
348 if (adev->wakeup.flags.notifier_present)
349 goto out;
350
351 status = acpi_install_notify_handler(adev->handle,
352 ACPI_SYSTEM_NOTIFY,
353 handler, context);
354 if (ACPI_FAILURE(status))
355 goto out;
356
357 adev->wakeup.flags.notifier_present = true;
358
359 out:
360 mutex_unlock(&acpi_pm_notifier_lock);
361 return status;
362}
363
364/**
365 * acpi_remove_pm_notifier - Unregister PM notifier from given ACPI device.
366 * @adev: ACPI device to remove the notifier from.
367 */
368acpi_status acpi_remove_pm_notifier(struct acpi_device *adev,
369 acpi_notify_handler handler)
370{
371 acpi_status status = AE_BAD_PARAMETER;
372
373 mutex_lock(&acpi_pm_notifier_lock);
374
375 if (!adev->wakeup.flags.notifier_present)
376 goto out;
377
378 status = acpi_remove_notify_handler(adev->handle,
379 ACPI_SYSTEM_NOTIFY,
380 handler);
381 if (ACPI_FAILURE(status))
382 goto out;
383
384 adev->wakeup.flags.notifier_present = false;
385
386 out:
387 mutex_unlock(&acpi_pm_notifier_lock);
388 return status;
389}
390
388bool acpi_bus_can_wakeup(acpi_handle handle) 391bool acpi_bus_can_wakeup(acpi_handle handle)
389{ 392{
390 struct acpi_device *device; 393 struct acpi_device *device;
@@ -1023,3 +1026,4 @@ void acpi_dev_pm_remove_dependent(acpi_handle handle, struct device *depdev)
1023 mutex_unlock(&adev->physical_node_lock); 1026 mutex_unlock(&adev->physical_node_lock);
1024} 1027}
1025EXPORT_SYMBOL_GPL(acpi_dev_pm_remove_dependent); 1028EXPORT_SYMBOL_GPL(acpi_dev_pm_remove_dependent);
1029#endif /* CONFIG_PM */