Commit | Line | Data |
---|---|---|
ec2cd81c RW |
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 | } |