]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - drivers/acpi/acpica/dsmethod.c
Merge tag 'v2.6.38' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
[mv-sheeva.git] / drivers / acpi / acpica / dsmethod.c
index d94dd8974b55c5fb03845a52f64ec430c70a6ec1..5d797751e205b363a48e43b6484e2a9cc37fc317 100644 (file)
@@ -5,7 +5,7 @@
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2010, Intel Corp.
+ * Copyright (C) 2000 - 2011, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -43,7 +43,6 @@
 
 #include <acpi/acpi.h>
 #include "accommon.h"
-#include "amlcode.h"
 #include "acdispat.h"
 #include "acinterp.h"
 #include "acnamesp.h"
@@ -201,7 +200,7 @@ acpi_ds_begin_method_execution(struct acpi_namespace_node *method_node,
        /*
         * If this method is serialized, we need to acquire the method mutex.
         */
-       if (obj_desc->method.method_flags & AML_METHOD_SERIALIZED) {
+       if (obj_desc->method.info_flags & ACPI_METHOD_SERIALIZED) {
                /*
                 * Create a mutex for the method if it is defined to be Serialized
                 * 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,
 
        /* Invoke an internal method if necessary */
 
-       if (obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY) {
-               status = obj_desc->method.extra.implementation(next_walk_state);
+       if (obj_desc->method.info_flags & ACPI_METHOD_INTERNAL_ONLY) {
+               status =
+                   obj_desc->method.dispatch.implementation(next_walk_state);
                if (status == AE_OK) {
                        status = AE_CTRL_TERMINATE;
                }
@@ -579,11 +579,14 @@ acpi_ds_terminate_control_method(union acpi_operand_object *method_desc,
 
                /*
                 * Delete any namespace objects created anywhere within the
-                * namespace by the execution of this method. Unless this method
-                * is a module-level executable code method, in which case we
-                * want make the objects permanent.
+                * namespace by the execution of this method. Unless:
+                * 1) This method is a module-level executable code method, in which
+                *    case we want make the objects permanent.
+                * 2) There are other threads executing the method, in which case we
+                *    will wait until the last thread has completed.
                 */
-               if (!(method_desc->method.flags & AOPOBJ_MODULE_LEVEL)) {
+               if (!(method_desc->method.info_flags & ACPI_METHOD_MODULE_LEVEL)
+                   && (method_desc->method.thread_count == 1)) {
 
                        /* Delete any direct children of (created by) this method */
 
@@ -593,12 +596,17 @@ acpi_ds_terminate_control_method(union acpi_operand_object *method_desc,
                        /*
                         * Delete any objects that were created by this method
                         * elsewhere in the namespace (if any were created).
+                        * Use of the ACPI_METHOD_MODIFIED_NAMESPACE optimizes the
+                        * deletion such that we don't have to perform an entire
+                        * namespace walk for every control method execution.
                         */
                        if (method_desc->method.
-                           flags & AOPOBJ_MODIFIED_NAMESPACE) {
+                           info_flags & ACPI_METHOD_MODIFIED_NAMESPACE) {
                                acpi_ns_delete_namespace_by_owner(method_desc->
                                                                  method.
                                                                  owner_id);
+                               method_desc->method.info_flags &=
+                                   ~ACPI_METHOD_MODIFIED_NAMESPACE;
                        }
                }
        }
@@ -629,19 +637,43 @@ acpi_ds_terminate_control_method(union acpi_operand_object *method_desc,
                 * Serialized if it appears that the method is incorrectly written and
                 * does not support multiple thread execution. The best example of this
                 * is if such a method creates namespace objects and blocks. A second
-                * thread will fail with an AE_ALREADY_EXISTS exception
+                * thread will fail with an AE_ALREADY_EXISTS exception.
                 *
                 * This code is here because we must wait until the last thread exits
-                * before creating the synchronization semaphore.
+                * before marking the method as serialized.
                 */
-               if ((method_desc->method.method_flags & AML_METHOD_SERIALIZED)
-                   && (!method_desc->method.mutex)) {
-                       (void)acpi_ds_create_method_mutex(method_desc);
+               if (method_desc->method.
+                   info_flags & ACPI_METHOD_SERIALIZED_PENDING) {
+                       if (walk_state) {
+                               ACPI_INFO((AE_INFO,
+                                          "Marking method %4.4s as Serialized because of AE_ALREADY_EXISTS error",
+                                          walk_state->method_node->name.
+                                          ascii));
+                       }
+
+                       /*
+                        * Method tried to create an object twice and was marked as
+                        * "pending serialized". The probable cause is that the method
+                        * cannot handle reentrancy.
+                        *
+                        * The method was created as not_serialized, but it tried to create
+                        * a named object and then blocked, causing the second thread
+                        * entrance to begin and then fail. Workaround this problem by
+                        * marking the method permanently as Serialized when the last
+                        * thread exits here.
+                        */
+                       method_desc->method.info_flags &=
+                           ~ACPI_METHOD_SERIALIZED_PENDING;
+                       method_desc->method.info_flags |=
+                           ACPI_METHOD_SERIALIZED;
+                       method_desc->method.sync_level = 0;
                }
 
                /* No more threads, we can free the owner_id */
 
-               if (!(method_desc->method.flags & AOPOBJ_MODULE_LEVEL)) {
+               if (!
+                   (method_desc->method.
+                    info_flags & ACPI_METHOD_MODULE_LEVEL)) {
                        acpi_ut_release_owner_id(&method_desc->method.owner_id);
                }
        }