aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/acpi/acpica/evgpe.c57
1 files changed, 45 insertions, 12 deletions
diff --git a/drivers/acpi/acpica/evgpe.c b/drivers/acpi/acpica/evgpe.c
index 3fb621eec2fa..c25999546c8c 100644
--- a/drivers/acpi/acpica/evgpe.c
+++ b/drivers/acpi/acpica/evgpe.c
@@ -52,6 +52,8 @@ ACPI_MODULE_NAME("evgpe")
52/* Local prototypes */ 52/* Local prototypes */
53static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context); 53static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context);
54 54
55static void ACPI_SYSTEM_XFACE acpi_ev_asynch_enable_gpe(void *context);
56
55/******************************************************************************* 57/*******************************************************************************
56 * 58 *
57 * FUNCTION: acpi_ev_update_gpe_enable_mask 59 * FUNCTION: acpi_ev_update_gpe_enable_mask
@@ -441,17 +443,25 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list)
441 * an interrupt handler. 443 * an interrupt handler.
442 * 444 *
443 ******************************************************************************/ 445 ******************************************************************************/
444static void acpi_ev_asynch_enable_gpe(void *context);
445 446
446static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context) 447static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context)
447{ 448{
448 struct acpi_gpe_event_info *gpe_event_info = (void *)context; 449 struct acpi_gpe_event_info *gpe_event_info = context;
449 acpi_status status; 450 acpi_status status;
450 struct acpi_gpe_event_info local_gpe_event_info; 451 struct acpi_gpe_event_info *local_gpe_event_info;
451 struct acpi_evaluate_info *info; 452 struct acpi_evaluate_info *info;
452 453
453 ACPI_FUNCTION_TRACE(ev_asynch_execute_gpe_method); 454 ACPI_FUNCTION_TRACE(ev_asynch_execute_gpe_method);
454 455
456 /* Allocate a local GPE block */
457
458 local_gpe_event_info =
459 ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_gpe_event_info));
460 if (!local_gpe_event_info) {
461 ACPI_EXCEPTION((AE_INFO, AE_NO_MEMORY, "while handling a GPE"));
462 return_VOID;
463 }
464
455 status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); 465 status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
456 if (ACPI_FAILURE(status)) { 466 if (ACPI_FAILURE(status)) {
457 return_VOID; 467 return_VOID;
@@ -468,7 +478,7 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context)
468 * Take a snapshot of the GPE info for this level - we copy the info to 478 * Take a snapshot of the GPE info for this level - we copy the info to
469 * prevent a race condition with remove_handler/remove_block. 479 * prevent a race condition with remove_handler/remove_block.
470 */ 480 */
471 ACPI_MEMCPY(&local_gpe_event_info, gpe_event_info, 481 ACPI_MEMCPY(local_gpe_event_info, gpe_event_info,
472 sizeof(struct acpi_gpe_event_info)); 482 sizeof(struct acpi_gpe_event_info));
473 483
474 status = acpi_ut_release_mutex(ACPI_MTX_EVENTS); 484 status = acpi_ut_release_mutex(ACPI_MTX_EVENTS);
@@ -480,7 +490,7 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context)
480 * Must check for control method type dispatch one more time to avoid a 490 * Must check for control method type dispatch one more time to avoid a
481 * race with ev_gpe_install_handler 491 * race with ev_gpe_install_handler
482 */ 492 */
483 if ((local_gpe_event_info.flags & ACPI_GPE_DISPATCH_MASK) == 493 if ((local_gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) ==
484 ACPI_GPE_DISPATCH_METHOD) { 494 ACPI_GPE_DISPATCH_METHOD) {
485 495
486 /* Allocate the evaluation information block */ 496 /* Allocate the evaluation information block */
@@ -494,7 +504,7 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context)
494 * control method that corresponds to this GPE 504 * control method that corresponds to this GPE
495 */ 505 */
496 info->prefix_node = 506 info->prefix_node =
497 local_gpe_event_info.dispatch.method_node; 507 local_gpe_event_info->dispatch.method_node;
498 info->flags = ACPI_IGNORE_RETURN_VALUE; 508 info->flags = ACPI_IGNORE_RETURN_VALUE;
499 509
500 status = acpi_ns_evaluate(info); 510 status = acpi_ns_evaluate(info);
@@ -505,20 +515,41 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context)
505 ACPI_EXCEPTION((AE_INFO, status, 515 ACPI_EXCEPTION((AE_INFO, status,
506 "while evaluating GPE method [%4.4s]", 516 "while evaluating GPE method [%4.4s]",
507 acpi_ut_get_node_name 517 acpi_ut_get_node_name
508 (local_gpe_event_info.dispatch. 518 (local_gpe_event_info->dispatch.
509 method_node))); 519 method_node)));
510 } 520 }
511 } 521 }
522
512 /* Defer enabling of GPE until all notify handlers are done */ 523 /* Defer enabling of GPE until all notify handlers are done */
513 acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_ev_asynch_enable_gpe, 524
514 gpe_event_info); 525 status = acpi_os_execute(OSL_NOTIFY_HANDLER,
526 acpi_ev_asynch_enable_gpe,
527 local_gpe_event_info);
528 if (ACPI_FAILURE(status)) {
529 ACPI_FREE(local_gpe_event_info);
530 }
515 return_VOID; 531 return_VOID;
516} 532}
517 533
518static void acpi_ev_asynch_enable_gpe(void *context) 534/*******************************************************************************
535 *
536 * FUNCTION: acpi_ev_asynch_enable_gpe
537 *
538 * PARAMETERS: Context (gpe_event_info) - Info for this GPE
539 * Callback from acpi_os_execute
540 *
541 * RETURN: None
542 *
543 * DESCRIPTION: Asynchronous clear/enable for GPE. This allows the GPE to
544 * complete.
545 *
546 ******************************************************************************/
547
548static void ACPI_SYSTEM_XFACE acpi_ev_asynch_enable_gpe(void *context)
519{ 549{
520 struct acpi_gpe_event_info *gpe_event_info = context; 550 struct acpi_gpe_event_info *gpe_event_info = context;
521 acpi_status status; 551 acpi_status status;
552
522 if ((gpe_event_info->flags & ACPI_GPE_XRUPT_TYPE_MASK) == 553 if ((gpe_event_info->flags & ACPI_GPE_XRUPT_TYPE_MASK) ==
523 ACPI_GPE_LEVEL_TRIGGERED) { 554 ACPI_GPE_LEVEL_TRIGGERED) {
524 /* 555 /*
@@ -527,7 +558,7 @@ static void acpi_ev_asynch_enable_gpe(void *context)
527 */ 558 */
528 status = acpi_hw_clear_gpe(gpe_event_info); 559 status = acpi_hw_clear_gpe(gpe_event_info);
529 if (ACPI_FAILURE(status)) { 560 if (ACPI_FAILURE(status)) {
530 return_VOID; 561 goto exit;
531 } 562 }
532 } 563 }
533 564
@@ -537,7 +568,9 @@ static void acpi_ev_asynch_enable_gpe(void *context)
537 */ 568 */
538 (void)acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_CONDITIONAL_ENABLE); 569 (void)acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_CONDITIONAL_ENABLE);
539 570
540 return_VOID; 571exit:
572 ACPI_FREE(gpe_event_info);
573 return;
541} 574}
542 575
543/******************************************************************************* 576/*******************************************************************************