aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/acpica/dsmethod.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/acpica/dsmethod.c')
-rw-r--r--drivers/acpi/acpica/dsmethod.c64
1 files changed, 48 insertions, 16 deletions
diff --git a/drivers/acpi/acpica/dsmethod.c b/drivers/acpi/acpica/dsmethod.c
index d94dd8974b55..5d797751e205 100644
--- a/drivers/acpi/acpica/dsmethod.c
+++ b/drivers/acpi/acpica/dsmethod.c
@@ -5,7 +5,7 @@
5 *****************************************************************************/ 5 *****************************************************************************/
6 6
7/* 7/*
8 * Copyright (C) 2000 - 2010, Intel Corp. 8 * Copyright (C) 2000 - 2011, Intel Corp.
9 * All rights reserved. 9 * All rights reserved.
10 * 10 *
11 * Redistribution and use in source and binary forms, with or without 11 * Redistribution and use in source and binary forms, with or without
@@ -43,7 +43,6 @@
43 43
44#include <acpi/acpi.h> 44#include <acpi/acpi.h>
45#include "accommon.h" 45#include "accommon.h"
46#include "amlcode.h"
47#include "acdispat.h" 46#include "acdispat.h"
48#include "acinterp.h" 47#include "acinterp.h"
49#include "acnamesp.h" 48#include "acnamesp.h"
@@ -201,7 +200,7 @@ acpi_ds_begin_method_execution(struct acpi_namespace_node *method_node,
201 /* 200 /*
202 * If this method is serialized, we need to acquire the method mutex. 201 * If this method is serialized, we need to acquire the method mutex.
203 */ 202 */
204 if (obj_desc->method.method_flags & AML_METHOD_SERIALIZED) { 203 if (obj_desc->method.info_flags & ACPI_METHOD_SERIALIZED) {
205 /* 204 /*
206 * Create a mutex for the method if it is defined to be Serialized 205 * Create a mutex for the method if it is defined to be Serialized
207 * and a mutex has not already been created. We defer the mutex creation 206 * and a mutex has not already been created. We defer the mutex creation
@@ -413,8 +412,9 @@ acpi_ds_call_control_method(struct acpi_thread_state *thread,
413 412
414 /* Invoke an internal method if necessary */ 413 /* Invoke an internal method if necessary */
415 414
416 if (obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY) { 415 if (obj_desc->method.info_flags & ACPI_METHOD_INTERNAL_ONLY) {
417 status = obj_desc->method.extra.implementation(next_walk_state); 416 status =
417 obj_desc->method.dispatch.implementation(next_walk_state);
418 if (status == AE_OK) { 418 if (status == AE_OK) {
419 status = AE_CTRL_TERMINATE; 419 status = AE_CTRL_TERMINATE;
420 } 420 }
@@ -579,11 +579,14 @@ acpi_ds_terminate_control_method(union acpi_operand_object *method_desc,
579 579
580 /* 580 /*
581 * Delete any namespace objects created anywhere within the 581 * Delete any namespace objects created anywhere within the
582 * namespace by the execution of this method. Unless this method 582 * namespace by the execution of this method. Unless:
583 * is a module-level executable code method, in which case we 583 * 1) This method is a module-level executable code method, in which
584 * want make the objects permanent. 584 * case we want make the objects permanent.
585 * 2) There are other threads executing the method, in which case we
586 * will wait until the last thread has completed.
585 */ 587 */
586 if (!(method_desc->method.flags & AOPOBJ_MODULE_LEVEL)) { 588 if (!(method_desc->method.info_flags & ACPI_METHOD_MODULE_LEVEL)
589 && (method_desc->method.thread_count == 1)) {
587 590
588 /* Delete any direct children of (created by) this method */ 591 /* Delete any direct children of (created by) this method */
589 592
@@ -593,12 +596,17 @@ acpi_ds_terminate_control_method(union acpi_operand_object *method_desc,
593 /* 596 /*
594 * Delete any objects that were created by this method 597 * Delete any objects that were created by this method
595 * elsewhere in the namespace (if any were created). 598 * elsewhere in the namespace (if any were created).
599 * Use of the ACPI_METHOD_MODIFIED_NAMESPACE optimizes the
600 * deletion such that we don't have to perform an entire
601 * namespace walk for every control method execution.
596 */ 602 */
597 if (method_desc->method. 603 if (method_desc->method.
598 flags & AOPOBJ_MODIFIED_NAMESPACE) { 604 info_flags & ACPI_METHOD_MODIFIED_NAMESPACE) {
599 acpi_ns_delete_namespace_by_owner(method_desc-> 605 acpi_ns_delete_namespace_by_owner(method_desc->
600 method. 606 method.
601 owner_id); 607 owner_id);
608 method_desc->method.info_flags &=
609 ~ACPI_METHOD_MODIFIED_NAMESPACE;
602 } 610 }
603 } 611 }
604 } 612 }
@@ -629,19 +637,43 @@ acpi_ds_terminate_control_method(union acpi_operand_object *method_desc,
629 * Serialized if it appears that the method is incorrectly written and 637 * Serialized if it appears that the method is incorrectly written and
630 * does not support multiple thread execution. The best example of this 638 * does not support multiple thread execution. The best example of this
631 * is if such a method creates namespace objects and blocks. A second 639 * is if such a method creates namespace objects and blocks. A second
632 * thread will fail with an AE_ALREADY_EXISTS exception 640 * thread will fail with an AE_ALREADY_EXISTS exception.
633 * 641 *
634 * This code is here because we must wait until the last thread exits 642 * This code is here because we must wait until the last thread exits
635 * before creating the synchronization semaphore. 643 * before marking the method as serialized.
636 */ 644 */
637 if ((method_desc->method.method_flags & AML_METHOD_SERIALIZED) 645 if (method_desc->method.
638 && (!method_desc->method.mutex)) { 646 info_flags & ACPI_METHOD_SERIALIZED_PENDING) {
639 (void)acpi_ds_create_method_mutex(method_desc); 647 if (walk_state) {
648 ACPI_INFO((AE_INFO,
649 "Marking method %4.4s as Serialized because of AE_ALREADY_EXISTS error",
650 walk_state->method_node->name.
651 ascii));
652 }
653
654 /*
655 * Method tried to create an object twice and was marked as
656 * "pending serialized". The probable cause is that the method
657 * cannot handle reentrancy.
658 *
659 * The method was created as not_serialized, but it tried to create
660 * a named object and then blocked, causing the second thread
661 * entrance to begin and then fail. Workaround this problem by
662 * marking the method permanently as Serialized when the last
663 * thread exits here.
664 */
665 method_desc->method.info_flags &=
666 ~ACPI_METHOD_SERIALIZED_PENDING;
667 method_desc->method.info_flags |=
668 ACPI_METHOD_SERIALIZED;
669 method_desc->method.sync_level = 0;
640 } 670 }
641 671
642 /* No more threads, we can free the owner_id */ 672 /* No more threads, we can free the owner_id */
643 673
644 if (!(method_desc->method.flags & AOPOBJ_MODULE_LEVEL)) { 674 if (!
675 (method_desc->method.
676 info_flags & ACPI_METHOD_MODULE_LEVEL)) {
645 acpi_ut_release_owner_id(&method_desc->method.owner_id); 677 acpi_ut_release_owner_id(&method_desc->method.owner_id);
646 } 678 }
647 } 679 }