aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLv Zheng <lv.zheng@intel.com>2015-02-05 02:20:01 -0500
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2015-02-05 09:31:37 -0500
commitb18da580343b88fa33bbba8a7f48392447bc6cbf (patch)
treee2978df7f802a21e5df6c871aeccefbda9ce2f35
parent833bb9316a3b4644b2671317ec4889e343ae5d42 (diff)
ACPICA: Events: Remove acpi_ev_valid_gpe_event() due to current restriction
ACPICA commit 8823b44ff53859ab24ecfcfd3fba8cc56b17d223 Currently we rely on the logic that GPE blocks will never be deleted, otherwise we can be broken by the race between acpi_ev_create_gpe_block(), acpi_ev_delete_gpe_block() and acpi_ev_gpe_detect(). On the other hand, if we want to protect GPE block creation/deletion, we need to use a different synchronization facility to protect the period between acpi_ev_gpe_dispatch() and acpi_ev_asynch_enable_gpe(). Which leaves us no choice but abandoning the ACPI_MTX_EVENTS used during this period. This patch removes ACPI_MTX_EVENTS used during this period and the acpi_ev_valid_gpe_event() to reflect current restriction. Lv Zheng. Link: https://github.com/acpica/acpica/commit/8823b44f Signed-off-by: Lv Zheng <lv.zheng@intel.com> Signed-off-by: David E. Box <david.e.box@linux.intel.com> Signed-off-by: Bob Moore <robert.moore@intel.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
-rw-r--r--drivers/acpi/acpica/acevents.h2
-rw-r--r--drivers/acpi/acpica/evgpe.c62
-rw-r--r--drivers/acpi/acpica/evgpeutil.c51
3 files changed, 15 insertions, 100 deletions
diff --git a/drivers/acpi/acpica/acevents.h b/drivers/acpi/acpica/acevents.h
index 7a7811a9fc26..38b94a1a5cf8 100644
--- a/drivers/acpi/acpica/acevents.h
+++ b/drivers/acpi/acpica/acevents.h
@@ -143,8 +143,6 @@ acpi_ev_match_gpe_method(acpi_handle obj_handle,
143acpi_status 143acpi_status
144acpi_ev_walk_gpe_list(acpi_gpe_callback gpe_walk_callback, void *context); 144acpi_ev_walk_gpe_list(acpi_gpe_callback gpe_walk_callback, void *context);
145 145
146u8 acpi_ev_valid_gpe_event(struct acpi_gpe_event_info *gpe_event_info);
147
148acpi_status 146acpi_status
149acpi_ev_get_gpe_device(struct acpi_gpe_xrupt_info *gpe_xrupt_info, 147acpi_ev_get_gpe_device(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
150 struct acpi_gpe_block_info *gpe_block, void *context); 148 struct acpi_gpe_block_info *gpe_block, void *context);
diff --git a/drivers/acpi/acpica/evgpe.c b/drivers/acpi/acpica/evgpe.c
index b2e63e785719..ddee96733403 100644
--- a/drivers/acpi/acpica/evgpe.c
+++ b/drivers/acpi/acpica/evgpe.c
@@ -474,51 +474,14 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context)
474{ 474{
475 struct acpi_gpe_event_info *gpe_event_info = context; 475 struct acpi_gpe_event_info *gpe_event_info = context;
476 acpi_status status; 476 acpi_status status;
477 struct acpi_gpe_event_info *local_gpe_event_info;
478 struct acpi_evaluate_info *info; 477 struct acpi_evaluate_info *info;
479 struct acpi_gpe_notify_info *notify; 478 struct acpi_gpe_notify_info *notify;
480 479
481 ACPI_FUNCTION_TRACE(ev_asynch_execute_gpe_method); 480 ACPI_FUNCTION_TRACE(ev_asynch_execute_gpe_method);
482 481
483 /* Allocate a local GPE block */
484
485 local_gpe_event_info =
486 ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_gpe_event_info));
487 if (!local_gpe_event_info) {
488 ACPI_EXCEPTION((AE_INFO, AE_NO_MEMORY, "while handling a GPE"));
489 return_VOID;
490 }
491
492 status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
493 if (ACPI_FAILURE(status)) {
494 ACPI_FREE(local_gpe_event_info);
495 return_VOID;
496 }
497
498 /* Must revalidate the gpe_number/gpe_block */
499
500 if (!acpi_ev_valid_gpe_event(gpe_event_info)) {
501 status = acpi_ut_release_mutex(ACPI_MTX_EVENTS);
502 ACPI_FREE(local_gpe_event_info);
503 return_VOID;
504 }
505
506 /*
507 * Take a snapshot of the GPE info for this level - we copy the info to
508 * prevent a race condition with remove_handler/remove_block.
509 */
510 ACPI_MEMCPY(local_gpe_event_info, gpe_event_info,
511 sizeof(struct acpi_gpe_event_info));
512
513 status = acpi_ut_release_mutex(ACPI_MTX_EVENTS);
514 if (ACPI_FAILURE(status)) {
515 ACPI_FREE(local_gpe_event_info);
516 return_VOID;
517 }
518
519 /* Do the correct dispatch - normal method or implicit notify */ 482 /* Do the correct dispatch - normal method or implicit notify */
520 483
521 switch (local_gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) { 484 switch (gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) {
522 case ACPI_GPE_DISPATCH_NOTIFY: 485 case ACPI_GPE_DISPATCH_NOTIFY:
523 /* 486 /*
524 * Implicit notify. 487 * Implicit notify.
@@ -531,7 +494,7 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context)
531 * June 2012: Expand implicit notify mechanism to support 494 * June 2012: Expand implicit notify mechanism to support
532 * notifies on multiple device objects. 495 * notifies on multiple device objects.
533 */ 496 */
534 notify = local_gpe_event_info->dispatch.notify_list; 497 notify = gpe_event_info->dispatch.notify_list;
535 while (ACPI_SUCCESS(status) && notify) { 498 while (ACPI_SUCCESS(status) && notify) {
536 status = 499 status =
537 acpi_ev_queue_notify_request(notify->device_node, 500 acpi_ev_queue_notify_request(notify->device_node,
@@ -555,7 +518,7 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context)
555 * _Lxx/_Exx control method that corresponds to this GPE 518 * _Lxx/_Exx control method that corresponds to this GPE
556 */ 519 */
557 info->prefix_node = 520 info->prefix_node =
558 local_gpe_event_info->dispatch.method_node; 521 gpe_event_info->dispatch.method_node;
559 info->flags = ACPI_IGNORE_RETURN_VALUE; 522 info->flags = ACPI_IGNORE_RETURN_VALUE;
560 523
561 status = acpi_ns_evaluate(info); 524 status = acpi_ns_evaluate(info);
@@ -565,25 +528,27 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context)
565 if (ACPI_FAILURE(status)) { 528 if (ACPI_FAILURE(status)) {
566 ACPI_EXCEPTION((AE_INFO, status, 529 ACPI_EXCEPTION((AE_INFO, status,
567 "while evaluating GPE method [%4.4s]", 530 "while evaluating GPE method [%4.4s]",
568 acpi_ut_get_node_name 531 acpi_ut_get_node_name(gpe_event_info->
569 (local_gpe_event_info->dispatch. 532 dispatch.
570 method_node))); 533 method_node)));
571 } 534 }
572 break; 535 break;
573 536
574 default: 537 default:
575 538
576 return_VOID; /* Should never happen */ 539 goto error_exit; /* Should never happen */
577 } 540 }
578 541
579 /* Defer enabling of GPE until all notify handlers are done */ 542 /* Defer enabling of GPE until all notify handlers are done */
580 543
581 status = acpi_os_execute(OSL_NOTIFY_HANDLER, 544 status = acpi_os_execute(OSL_NOTIFY_HANDLER,
582 acpi_ev_asynch_enable_gpe, 545 acpi_ev_asynch_enable_gpe, gpe_event_info);
583 local_gpe_event_info); 546 if (ACPI_SUCCESS(status)) {
584 if (ACPI_FAILURE(status)) { 547 return_VOID;
585 ACPI_FREE(local_gpe_event_info);
586 } 548 }
549
550error_exit:
551 acpi_ev_asynch_enable_gpe(gpe_event_info);
587 return_VOID; 552 return_VOID;
588} 553}
589 554
@@ -611,7 +576,6 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_enable_gpe(void *context)
611 (void)acpi_ev_finish_gpe(gpe_event_info); 576 (void)acpi_ev_finish_gpe(gpe_event_info);
612 acpi_os_release_lock(acpi_gbl_gpe_lock, flags); 577 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
613 578
614 ACPI_FREE(gpe_event_info);
615 return; 579 return;
616} 580}
617 581
diff --git a/drivers/acpi/acpica/evgpeutil.c b/drivers/acpi/acpica/evgpeutil.c
index 9e2b94c8f7c4..3f1c5aa682a5 100644
--- a/drivers/acpi/acpica/evgpeutil.c
+++ b/drivers/acpi/acpica/evgpeutil.c
@@ -108,53 +108,6 @@ unlock_and_exit:
108 108
109/******************************************************************************* 109/*******************************************************************************
110 * 110 *
111 * FUNCTION: acpi_ev_valid_gpe_event
112 *
113 * PARAMETERS: gpe_event_info - Info for this GPE
114 *
115 * RETURN: TRUE if the gpe_event is valid
116 *
117 * DESCRIPTION: Validate a GPE event. DO NOT CALL FROM INTERRUPT LEVEL.
118 * Should be called only when the GPE lists are semaphore locked
119 * and not subject to change.
120 *
121 ******************************************************************************/
122
123u8 acpi_ev_valid_gpe_event(struct acpi_gpe_event_info *gpe_event_info)
124{
125 struct acpi_gpe_xrupt_info *gpe_xrupt_block;
126 struct acpi_gpe_block_info *gpe_block;
127
128 ACPI_FUNCTION_ENTRY();
129
130 /* No need for spin lock since we are not changing any list elements */
131
132 /* Walk the GPE interrupt levels */
133
134 gpe_xrupt_block = acpi_gbl_gpe_xrupt_list_head;
135 while (gpe_xrupt_block) {
136 gpe_block = gpe_xrupt_block->gpe_block_list_head;
137
138 /* Walk the GPE blocks on this interrupt level */
139
140 while (gpe_block) {
141 if ((&gpe_block->event_info[0] <= gpe_event_info) &&
142 (&gpe_block->event_info[gpe_block->gpe_count] >
143 gpe_event_info)) {
144 return (TRUE);
145 }
146
147 gpe_block = gpe_block->next;
148 }
149
150 gpe_xrupt_block = gpe_xrupt_block->next;
151 }
152
153 return (FALSE);
154}
155
156/*******************************************************************************
157 *
158 * FUNCTION: acpi_ev_get_gpe_device 111 * FUNCTION: acpi_ev_get_gpe_device
159 * 112 *
160 * PARAMETERS: GPE_WALK_CALLBACK 113 * PARAMETERS: GPE_WALK_CALLBACK
@@ -167,8 +120,8 @@ u8 acpi_ev_valid_gpe_event(struct acpi_gpe_event_info *gpe_event_info)
167 ******************************************************************************/ 120 ******************************************************************************/
168 121
169acpi_status 122acpi_status
170acpi_ev_get_gpe_device(struct acpi_gpe_xrupt_info * gpe_xrupt_info, 123acpi_ev_get_gpe_device(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
171 struct acpi_gpe_block_info * gpe_block, void *context) 124 struct acpi_gpe_block_info *gpe_block, void *context)
172{ 125{
173 struct acpi_gpe_device_info *info = context; 126 struct acpi_gpe_device_info *info = context;
174 127