diff options
Diffstat (limited to 'drivers/acpi/acpica/evxfgpe.c')
-rw-r--r-- | drivers/acpi/acpica/evxfgpe.c | 42 |
1 files changed, 33 insertions, 9 deletions
diff --git a/drivers/acpi/acpica/evxfgpe.c b/drivers/acpi/acpica/evxfgpe.c index 3b20a3401b64..52aaff3df562 100644 --- a/drivers/acpi/acpica/evxfgpe.c +++ b/drivers/acpi/acpica/evxfgpe.c | |||
@@ -198,7 +198,9 @@ acpi_setup_gpe_for_wake(acpi_handle wake_device, | |||
198 | acpi_status status = AE_BAD_PARAMETER; | 198 | acpi_status status = AE_BAD_PARAMETER; |
199 | struct acpi_gpe_event_info *gpe_event_info; | 199 | struct acpi_gpe_event_info *gpe_event_info; |
200 | struct acpi_namespace_node *device_node; | 200 | struct acpi_namespace_node *device_node; |
201 | struct acpi_gpe_notify_object *notify_object; | ||
201 | acpi_cpu_flags flags; | 202 | acpi_cpu_flags flags; |
203 | u8 gpe_dispatch_mask; | ||
202 | 204 | ||
203 | ACPI_FUNCTION_TRACE(acpi_setup_gpe_for_wake); | 205 | ACPI_FUNCTION_TRACE(acpi_setup_gpe_for_wake); |
204 | 206 | ||
@@ -221,27 +223,49 @@ acpi_setup_gpe_for_wake(acpi_handle wake_device, | |||
221 | goto unlock_and_exit; | 223 | goto unlock_and_exit; |
222 | } | 224 | } |
223 | 225 | ||
226 | if (wake_device == ACPI_ROOT_OBJECT) { | ||
227 | goto out; | ||
228 | } | ||
229 | |||
224 | /* | 230 | /* |
225 | * If there is no method or handler for this GPE, then the | 231 | * If there is no method or handler for this GPE, then the |
226 | * wake_device will be notified whenever this GPE fires (aka | 232 | * wake_device will be notified whenever this GPE fires (aka |
227 | * "implicit notify") Note: The GPE is assumed to be | 233 | * "implicit notify") Note: The GPE is assumed to be |
228 | * level-triggered (for windows compatibility). | 234 | * level-triggered (for windows compatibility). |
229 | */ | 235 | */ |
230 | if (((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == | 236 | gpe_dispatch_mask = gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK; |
231 | ACPI_GPE_DISPATCH_NONE) && (wake_device != ACPI_ROOT_OBJECT)) { | 237 | if (gpe_dispatch_mask != ACPI_GPE_DISPATCH_NONE |
238 | && gpe_dispatch_mask != ACPI_GPE_DISPATCH_NOTIFY) { | ||
239 | goto out; | ||
240 | } | ||
232 | 241 | ||
233 | /* Validate wake_device is of type Device */ | 242 | /* Validate wake_device is of type Device */ |
234 | 243 | ||
235 | device_node = ACPI_CAST_PTR(struct acpi_namespace_node, | 244 | device_node = ACPI_CAST_PTR(struct acpi_namespace_node, wake_device); |
236 | wake_device); | 245 | if (device_node->type != ACPI_TYPE_DEVICE) { |
237 | if (device_node->type != ACPI_TYPE_DEVICE) { | 246 | goto unlock_and_exit; |
238 | goto unlock_and_exit; | 247 | } |
239 | } | 248 | |
249 | if (gpe_dispatch_mask == ACPI_GPE_DISPATCH_NONE) { | ||
240 | gpe_event_info->flags = (ACPI_GPE_DISPATCH_NOTIFY | | 250 | gpe_event_info->flags = (ACPI_GPE_DISPATCH_NOTIFY | |
241 | ACPI_GPE_LEVEL_TRIGGERED); | 251 | ACPI_GPE_LEVEL_TRIGGERED); |
242 | gpe_event_info->dispatch.device_node = device_node; | 252 | gpe_event_info->dispatch.device.node = device_node; |
253 | gpe_event_info->dispatch.device.next = NULL; | ||
254 | } else { | ||
255 | /* There are multiple devices to notify implicitly. */ | ||
256 | |||
257 | notify_object = ACPI_ALLOCATE_ZEROED(sizeof(*notify_object)); | ||
258 | if (!notify_object) { | ||
259 | status = AE_NO_MEMORY; | ||
260 | goto unlock_and_exit; | ||
261 | } | ||
262 | |||
263 | notify_object->node = device_node; | ||
264 | notify_object->next = gpe_event_info->dispatch.device.next; | ||
265 | gpe_event_info->dispatch.device.next = notify_object; | ||
243 | } | 266 | } |
244 | 267 | ||
268 | out: | ||
245 | gpe_event_info->flags |= ACPI_GPE_CAN_WAKE; | 269 | gpe_event_info->flags |= ACPI_GPE_CAN_WAKE; |
246 | status = AE_OK; | 270 | status = AE_OK; |
247 | 271 | ||