.. | .. |
---|
12 | 12 | #include "internal.h" |
---|
13 | 13 | #include "sleep.h" |
---|
14 | 14 | |
---|
| 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 | + |
---|
15 | 24 | /* |
---|
16 | 25 | * We didn't lock acpi_device_lock in the file, because it invokes oops in |
---|
17 | 26 | * suspend/resume and isn't really required as this is called in S-state. At |
---|
18 | 27 | * that time, there is no device hotplug |
---|
19 | 28 | **/ |
---|
20 | | -#define _COMPONENT ACPI_SYSTEM_COMPONENT |
---|
21 | | -ACPI_MODULE_NAME("wakeup_devices") |
---|
22 | 29 | |
---|
23 | 30 | /** |
---|
24 | 31 | * acpi_enable_wakeup_devices - Enable wake-up device GPEs. |
---|
.. | .. |
---|
30 | 37 | */ |
---|
31 | 38 | void acpi_enable_wakeup_devices(u8 sleep_state) |
---|
32 | 39 | { |
---|
33 | | - struct list_head *node, *next; |
---|
| 40 | + struct acpi_device *dev, *tmp; |
---|
34 | 41 | |
---|
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) { |
---|
39 | 44 | if (!dev->wakeup.flags.valid |
---|
40 | 45 | || sleep_state > (u32) dev->wakeup.sleep_state |
---|
41 | 46 | || !(device_may_wakeup(&dev->dev) |
---|
42 | | - || dev->wakeup.prepare_count)) |
---|
| 47 | + || dev->wakeup.prepare_count)) |
---|
43 | 48 | continue; |
---|
44 | 49 | |
---|
45 | 50 | if (device_may_wakeup(&dev->dev)) |
---|
.. | .. |
---|
57 | 62 | */ |
---|
58 | 63 | void acpi_disable_wakeup_devices(u8 sleep_state) |
---|
59 | 64 | { |
---|
60 | | - struct list_head *node, *next; |
---|
| 65 | + struct acpi_device *dev, *tmp; |
---|
61 | 66 | |
---|
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) { |
---|
66 | 69 | if (!dev->wakeup.flags.valid |
---|
67 | 70 | || sleep_state > (u32) dev->wakeup.sleep_state |
---|
68 | 71 | || !(device_may_wakeup(&dev->dev) |
---|
69 | | - || dev->wakeup.prepare_count)) |
---|
| 72 | + || dev->wakeup.prepare_count)) |
---|
70 | 73 | continue; |
---|
71 | 74 | |
---|
72 | 75 | acpi_set_gpe_wake_mask(dev->wakeup.gpe_device, dev->wakeup.gpe_number, |
---|
.. | .. |
---|
79 | 82 | |
---|
80 | 83 | int __init acpi_wakeup_device_init(void) |
---|
81 | 84 | { |
---|
82 | | - struct list_head *node, *next; |
---|
| 85 | + struct acpi_device *dev, *tmp; |
---|
83 | 86 | |
---|
84 | 87 | 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) { |
---|
89 | 90 | if (device_can_wakeup(&dev->dev)) { |
---|
90 | 91 | /* Button GPEs are supposed to be always enabled. */ |
---|
91 | 92 | acpi_enable_gpe(dev->wakeup.gpe_device, |
---|
.. | .. |
---|
96 | 97 | mutex_unlock(&acpi_device_lock); |
---|
97 | 98 | return 0; |
---|
98 | 99 | } |
---|
| 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 | +} |
---|