| .. | .. |
|---|
| 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 | +} |
|---|