aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/acpica
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/acpica')
-rw-r--r--drivers/acpi/acpica/aclocal.h7
-rw-r--r--drivers/acpi/acpica/evgpe.c17
-rw-r--r--drivers/acpi/acpica/evxfgpe.c67
3 files changed, 66 insertions, 25 deletions
diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h
index 54784bb42cec..edc25867ad9d 100644
--- a/drivers/acpi/acpica/aclocal.h
+++ b/drivers/acpi/acpica/aclocal.h
@@ -416,10 +416,15 @@ struct acpi_gpe_handler_info {
416 u8 originally_enabled; /* True if GPE was originally enabled */ 416 u8 originally_enabled; /* True if GPE was originally enabled */
417}; 417};
418 418
419struct acpi_gpe_notify_object {
420 struct acpi_namespace_node *node;
421 struct acpi_gpe_notify_object *next;
422};
423
419union acpi_gpe_dispatch_info { 424union acpi_gpe_dispatch_info {
420 struct acpi_namespace_node *method_node; /* Method node for this GPE level */ 425 struct acpi_namespace_node *method_node; /* Method node for this GPE level */
421 struct acpi_gpe_handler_info *handler; /* Installed GPE handler */ 426 struct acpi_gpe_handler_info *handler; /* Installed GPE handler */
422 struct acpi_namespace_node *device_node; /* Parent _PRW device for implicit notify */ 427 struct acpi_gpe_notify_object device; /* List of _PRW devices for implicit notify */
423}; 428};
424 429
425/* 430/*
diff --git a/drivers/acpi/acpica/evgpe.c b/drivers/acpi/acpica/evgpe.c
index 14988a86066f..f4725212eb48 100644
--- a/drivers/acpi/acpica/evgpe.c
+++ b/drivers/acpi/acpica/evgpe.c
@@ -457,6 +457,7 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context)
457 acpi_status status; 457 acpi_status status;
458 struct acpi_gpe_event_info *local_gpe_event_info; 458 struct acpi_gpe_event_info *local_gpe_event_info;
459 struct acpi_evaluate_info *info; 459 struct acpi_evaluate_info *info;
460 struct acpi_gpe_notify_object *notify_object;
460 461
461 ACPI_FUNCTION_TRACE(ev_asynch_execute_gpe_method); 462 ACPI_FUNCTION_TRACE(ev_asynch_execute_gpe_method);
462 463
@@ -508,10 +509,18 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context)
508 * from this thread -- because handlers may in turn run other 509 * from this thread -- because handlers may in turn run other
509 * control methods. 510 * control methods.
510 */ 511 */
511 status = 512 status = acpi_ev_queue_notify_request(
512 acpi_ev_queue_notify_request(local_gpe_event_info->dispatch. 513 local_gpe_event_info->dispatch.device.node,
513 device_node, 514 ACPI_NOTIFY_DEVICE_WAKE);
514 ACPI_NOTIFY_DEVICE_WAKE); 515
516 notify_object = local_gpe_event_info->dispatch.device.next;
517 while (ACPI_SUCCESS(status) && notify_object) {
518 status = acpi_ev_queue_notify_request(
519 notify_object->node,
520 ACPI_NOTIFY_DEVICE_WAKE);
521 notify_object = notify_object->next;
522 }
523
515 break; 524 break;
516 525
517 case ACPI_GPE_DISPATCH_METHOD: 526 case ACPI_GPE_DISPATCH_METHOD:
diff --git a/drivers/acpi/acpica/evxfgpe.c b/drivers/acpi/acpica/evxfgpe.c
index e9562a7cb2f9..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
@@ -212,37 +214,62 @@ acpi_setup_gpe_for_wake(acpi_handle wake_device,
212 return_ACPI_STATUS(AE_BAD_PARAMETER); 214 return_ACPI_STATUS(AE_BAD_PARAMETER);
213 } 215 }
214 216
217 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
218
219 /* Ensure that we have a valid GPE number */
220
221 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
222 if (!gpe_event_info) {
223 goto unlock_and_exit;
224 }
225
226 if (wake_device == ACPI_ROOT_OBJECT) {
227 goto out;
228 }
229
230 /*
231 * If there is no method or handler for this GPE, then the
232 * wake_device will be notified whenever this GPE fires (aka
233 * "implicit notify") Note: The GPE is assumed to be
234 * level-triggered (for windows compatibility).
235 */
236 gpe_dispatch_mask = gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK;
237 if (gpe_dispatch_mask != ACPI_GPE_DISPATCH_NONE
238 && gpe_dispatch_mask != ACPI_GPE_DISPATCH_NOTIFY) {
239 goto out;
240 }
241
215 /* Validate wake_device is of type Device */ 242 /* Validate wake_device is of type Device */
216 243
217 device_node = ACPI_CAST_PTR(struct acpi_namespace_node, wake_device); 244 device_node = ACPI_CAST_PTR(struct acpi_namespace_node, wake_device);
218 if (device_node->type != ACPI_TYPE_DEVICE) { 245 if (device_node->type != ACPI_TYPE_DEVICE) {
219 return_ACPI_STATUS(AE_BAD_PARAMETER); 246 goto unlock_and_exit;
220 } 247 }
221 248
222 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); 249 if (gpe_dispatch_mask == ACPI_GPE_DISPATCH_NONE) {
250 gpe_event_info->flags = (ACPI_GPE_DISPATCH_NOTIFY |
251 ACPI_GPE_LEVEL_TRIGGERED);
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. */
223 256
224 /* Ensure that we have a valid GPE number */ 257 notify_object = ACPI_ALLOCATE_ZEROED(sizeof(*notify_object));
225 258 if (!notify_object) {
226 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); 259 status = AE_NO_MEMORY;
227 if (gpe_event_info) { 260 goto unlock_and_exit;
228 /*
229 * If there is no method or handler for this GPE, then the
230 * wake_device will be notified whenever this GPE fires (aka
231 * "implicit notify") Note: The GPE is assumed to be
232 * level-triggered (for windows compatibility).
233 */
234 if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) ==
235 ACPI_GPE_DISPATCH_NONE) {
236 gpe_event_info->flags =
237 (ACPI_GPE_DISPATCH_NOTIFY |
238 ACPI_GPE_LEVEL_TRIGGERED);
239 gpe_event_info->dispatch.device_node = device_node;
240 } 261 }
241 262
242 gpe_event_info->flags |= ACPI_GPE_CAN_WAKE; 263 notify_object->node = device_node;
243 status = AE_OK; 264 notify_object->next = gpe_event_info->dispatch.device.next;
265 gpe_event_info->dispatch.device.next = notify_object;
244 } 266 }
245 267
268 out:
269 gpe_event_info->flags |= ACPI_GPE_CAN_WAKE;
270 status = AE_OK;
271
272 unlock_and_exit:
246 acpi_os_release_lock(acpi_gbl_gpe_lock, flags); 273 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
247 return_ACPI_STATUS(status); 274 return_ACPI_STATUS(status);
248} 275}