hc
2023-12-11 d2ccde1c8e90d38cee87a1b0309ad2827f3fd30d
kernel/drivers/acpi/wakeup.c
....@@ -12,13 +12,20 @@
1212 #include "internal.h"
1313 #include "sleep.h"
1414
15
+struct acpi_wakeup_handler {
16
+ struct list_head list_node;
17
+ bool (*wakeup)(void *context);
18
+ void *context;
19
+};
20
+
21
+static LIST_HEAD(acpi_wakeup_handler_head);
22
+static DEFINE_MUTEX(acpi_wakeup_handler_mutex);
23
+
1524 /*
1625 * We didn't lock acpi_device_lock in the file, because it invokes oops in
1726 * suspend/resume and isn't really required as this is called in S-state. At
1827 * that time, there is no device hotplug
1928 **/
20
-#define _COMPONENT ACPI_SYSTEM_COMPONENT
21
-ACPI_MODULE_NAME("wakeup_devices")
2229
2330 /**
2431 * acpi_enable_wakeup_devices - Enable wake-up device GPEs.
....@@ -30,16 +37,14 @@
3037 */
3138 void acpi_enable_wakeup_devices(u8 sleep_state)
3239 {
33
- struct list_head *node, *next;
40
+ struct acpi_device *dev, *tmp;
3441
35
- list_for_each_safe(node, next, &acpi_wakeup_device_list) {
36
- struct acpi_device *dev =
37
- container_of(node, struct acpi_device, wakeup_list);
38
-
42
+ list_for_each_entry_safe(dev, tmp, &acpi_wakeup_device_list,
43
+ wakeup_list) {
3944 if (!dev->wakeup.flags.valid
4045 || sleep_state > (u32) dev->wakeup.sleep_state
4146 || !(device_may_wakeup(&dev->dev)
42
- || dev->wakeup.prepare_count))
47
+ || dev->wakeup.prepare_count))
4348 continue;
4449
4550 if (device_may_wakeup(&dev->dev))
....@@ -57,16 +62,14 @@
5762 */
5863 void acpi_disable_wakeup_devices(u8 sleep_state)
5964 {
60
- struct list_head *node, *next;
65
+ struct acpi_device *dev, *tmp;
6166
62
- list_for_each_safe(node, next, &acpi_wakeup_device_list) {
63
- struct acpi_device *dev =
64
- container_of(node, struct acpi_device, wakeup_list);
65
-
67
+ list_for_each_entry_safe(dev, tmp, &acpi_wakeup_device_list,
68
+ wakeup_list) {
6669 if (!dev->wakeup.flags.valid
6770 || sleep_state > (u32) dev->wakeup.sleep_state
6871 || !(device_may_wakeup(&dev->dev)
69
- || dev->wakeup.prepare_count))
72
+ || dev->wakeup.prepare_count))
7073 continue;
7174
7275 acpi_set_gpe_wake_mask(dev->wakeup.gpe_device, dev->wakeup.gpe_number,
....@@ -79,13 +82,11 @@
7982
8083 int __init acpi_wakeup_device_init(void)
8184 {
82
- struct list_head *node, *next;
85
+ struct acpi_device *dev, *tmp;
8386
8487 mutex_lock(&acpi_device_lock);
85
- list_for_each_safe(node, next, &acpi_wakeup_device_list) {
86
- struct acpi_device *dev = container_of(node,
87
- struct acpi_device,
88
- wakeup_list);
88
+ list_for_each_entry_safe(dev, tmp, &acpi_wakeup_device_list,
89
+ wakeup_list) {
8990 if (device_can_wakeup(&dev->dev)) {
9091 /* Button GPEs are supposed to be always enabled. */
9192 acpi_enable_gpe(dev->wakeup.gpe_device,
....@@ -96,3 +97,75 @@
9697 mutex_unlock(&acpi_device_lock);
9798 return 0;
9899 }
100
+
101
+/**
102
+ * acpi_register_wakeup_handler - Register wakeup handler
103
+ * @wake_irq: The IRQ through which the device may receive wakeups
104
+ * @wakeup: Wakeup-handler to call when the SCI has triggered a wakeup
105
+ * @context: Context to pass to the handler when calling it
106
+ *
107
+ * Drivers which may share an IRQ with the SCI can use this to register
108
+ * a handler which returns true when the device they are managing wants
109
+ * to trigger a wakeup.
110
+ */
111
+int acpi_register_wakeup_handler(int wake_irq, bool (*wakeup)(void *context),
112
+ void *context)
113
+{
114
+ struct acpi_wakeup_handler *handler;
115
+
116
+ /*
117
+ * If the device is not sharing its IRQ with the SCI, there is no
118
+ * need to register the handler.
119
+ */
120
+ if (!acpi_sci_irq_valid() || wake_irq != acpi_sci_irq)
121
+ return 0;
122
+
123
+ handler = kmalloc(sizeof(*handler), GFP_KERNEL);
124
+ if (!handler)
125
+ return -ENOMEM;
126
+
127
+ handler->wakeup = wakeup;
128
+ handler->context = context;
129
+
130
+ mutex_lock(&acpi_wakeup_handler_mutex);
131
+ list_add(&handler->list_node, &acpi_wakeup_handler_head);
132
+ mutex_unlock(&acpi_wakeup_handler_mutex);
133
+
134
+ return 0;
135
+}
136
+EXPORT_SYMBOL_GPL(acpi_register_wakeup_handler);
137
+
138
+/**
139
+ * acpi_unregister_wakeup_handler - Unregister wakeup handler
140
+ * @wakeup: Wakeup-handler passed to acpi_register_wakeup_handler()
141
+ * @context: Context passed to acpi_register_wakeup_handler()
142
+ */
143
+void acpi_unregister_wakeup_handler(bool (*wakeup)(void *context),
144
+ void *context)
145
+{
146
+ struct acpi_wakeup_handler *handler;
147
+
148
+ mutex_lock(&acpi_wakeup_handler_mutex);
149
+ list_for_each_entry(handler, &acpi_wakeup_handler_head, list_node) {
150
+ if (handler->wakeup == wakeup && handler->context == context) {
151
+ list_del(&handler->list_node);
152
+ kfree(handler);
153
+ break;
154
+ }
155
+ }
156
+ mutex_unlock(&acpi_wakeup_handler_mutex);
157
+}
158
+EXPORT_SYMBOL_GPL(acpi_unregister_wakeup_handler);
159
+
160
+bool acpi_check_wakeup_handlers(void)
161
+{
162
+ struct acpi_wakeup_handler *handler;
163
+
164
+ /* No need to lock, nothing else is running when we're called. */
165
+ list_for_each_entry(handler, &acpi_wakeup_handler_head, list_node) {
166
+ if (handler->wakeup(handler->context))
167
+ return true;
168
+ }
169
+
170
+ return false;
171
+}