ACPICA: Namespace: Fix dynamic table loading issues
[cascardo/linux.git] / drivers / acpi / acpica / nsparse.c
index f631a47..4f14e92 100644 (file)
 #include "acparser.h"
 #include "acdispat.h"
 #include "actables.h"
+#include "acinterp.h"
 
 #define _COMPONENT          ACPI_NAMESPACE
 ACPI_MODULE_NAME("nsparse")
 
+/*******************************************************************************
+ *
+ * FUNCTION:    ns_execute_table
+ *
+ * PARAMETERS:  table_desc      - An ACPI table descriptor for table to parse
+ *              start_node      - Where to enter the table into the namespace
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Load ACPI/AML table by executing the entire table as a
+ *              term_list.
+ *
+ ******************************************************************************/
+acpi_status
+acpi_ns_execute_table(u32 table_index, struct acpi_namespace_node *start_node)
+{
+       acpi_status status;
+       struct acpi_table_header *table;
+       acpi_owner_id owner_id;
+       struct acpi_evaluate_info *info = NULL;
+       u32 aml_length;
+       u8 *aml_start;
+       union acpi_operand_object *method_obj = NULL;
+
+       ACPI_FUNCTION_TRACE(ns_execute_table);
+
+       status = acpi_get_table_by_index(table_index, &table);
+       if (ACPI_FAILURE(status)) {
+               return_ACPI_STATUS(status);
+       }
+
+       /* Table must consist of at least a complete header */
+
+       if (table->length < sizeof(struct acpi_table_header)) {
+               return_ACPI_STATUS(AE_BAD_HEADER);
+       }
+
+       aml_start = (u8 *)table + sizeof(struct acpi_table_header);
+       aml_length = table->length - sizeof(struct acpi_table_header);
+
+       status = acpi_tb_get_owner_id(table_index, &owner_id);
+       if (ACPI_FAILURE(status)) {
+               return_ACPI_STATUS(status);
+       }
+
+       /* Create, initialize, and link a new temporary method object */
+
+       method_obj = acpi_ut_create_internal_object(ACPI_TYPE_METHOD);
+       if (!method_obj) {
+               return_ACPI_STATUS(AE_NO_MEMORY);
+       }
+
+       /* Allocate the evaluation information block */
+
+       info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info));
+       if (!info) {
+               status = AE_NO_MEMORY;
+               goto cleanup;
+       }
+
+       ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
+                         "Create table code block: %p\n", method_obj));
+
+       method_obj->method.aml_start = aml_start;
+       method_obj->method.aml_length = aml_length;
+       method_obj->method.owner_id = owner_id;
+       method_obj->method.info_flags |= ACPI_METHOD_MODULE_LEVEL;
+
+       info->pass_number = ACPI_IMODE_EXECUTE;
+       info->node = start_node;
+       info->obj_desc = method_obj;
+       info->node_flags = info->node->flags;
+       info->full_pathname = acpi_ns_get_normalized_pathname(info->node, TRUE);
+       if (!info->full_pathname) {
+               status = AE_NO_MEMORY;
+               goto cleanup;
+       }
+
+       status = acpi_ps_execute_table(info);
+
+cleanup:
+       if (info) {
+               ACPI_FREE(info->full_pathname);
+               info->full_pathname = NULL;
+       }
+       ACPI_FREE(info);
+       acpi_ut_remove_reference(method_obj);
+       return_ACPI_STATUS(status);
+}
+
 /*******************************************************************************
  *
  * FUNCTION:    ns_one_complete_parse
@@ -63,6 +154,7 @@ ACPI_MODULE_NAME("nsparse")
  * DESCRIPTION: Perform one complete parse of an ACPI/AML table.
  *
  ******************************************************************************/
+
 acpi_status
 acpi_ns_one_complete_parse(u32 pass_number,
                           u32 table_index,
@@ -143,7 +235,9 @@ acpi_ns_one_complete_parse(u32 pass_number,
 
        ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
                          "*PARSE* pass %u parse\n", pass_number));
+       acpi_ex_enter_interpreter();
        status = acpi_ps_parse_aml(walk_state);
+       acpi_ex_exit_interpreter();
 
 cleanup:
        acpi_ps_delete_parse_tree(parse_root);
@@ -170,38 +264,47 @@ acpi_ns_parse_table(u32 table_index, struct acpi_namespace_node *start_node)
 
        ACPI_FUNCTION_TRACE(ns_parse_table);
 
-       /*
-        * AML Parse, pass 1
-        *
-        * In this pass, we load most of the namespace. Control methods
-        * are not parsed until later. A parse tree is not created. Instead,
-        * each Parser Op subtree is deleted when it is finished. This saves
-        * a great deal of memory, and allows a small cache of parse objects
-        * to service the entire parse. The second pass of the parse then
-        * performs another complete parse of the AML.
-        */
-       ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "**** Start pass 1\n"));
-
-       status = acpi_ns_one_complete_parse(ACPI_IMODE_LOAD_PASS1,
-                                           table_index, start_node);
-       if (ACPI_FAILURE(status)) {
-               return_ACPI_STATUS(status);
-       }
+       if (acpi_gbl_parse_table_as_term_list) {
+               ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "**** Start load pass\n"));
 
-       /*
-        * AML Parse, pass 2
-        *
-        * In this pass, we resolve forward references and other things
-        * that could not be completed during the first pass.
-        * Another complete parse of the AML is performed, but the
-        * overhead of this is compensated for by the fact that the
-        * parse objects are all cached.
-        */
-       ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "**** Start pass 2\n"));
-       status = acpi_ns_one_complete_parse(ACPI_IMODE_LOAD_PASS2,
-                                           table_index, start_node);
-       if (ACPI_FAILURE(status)) {
-               return_ACPI_STATUS(status);
+               status = acpi_ns_execute_table(table_index, start_node);
+               if (ACPI_FAILURE(status)) {
+                       return_ACPI_STATUS(status);
+               }
+       } else {
+               /*
+                * AML Parse, pass 1
+                *
+                * In this pass, we load most of the namespace. Control methods
+                * are not parsed until later. A parse tree is not created.
+                * Instead, each Parser Op subtree is deleted when it is finished.
+                * This saves a great deal of memory, and allows a small cache of
+                * parse objects to service the entire parse. The second pass of
+                * the parse then performs another complete parse of the AML.
+                */
+               ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "**** Start pass 1\n"));
+
+               status = acpi_ns_one_complete_parse(ACPI_IMODE_LOAD_PASS1,
+                                                   table_index, start_node);
+               if (ACPI_FAILURE(status)) {
+                       return_ACPI_STATUS(status);
+               }
+
+               /*
+                * AML Parse, pass 2
+                *
+                * In this pass, we resolve forward references and other things
+                * that could not be completed during the first pass.
+                * Another complete parse of the AML is performed, but the
+                * overhead of this is compensated for by the fact that the
+                * parse objects are all cached.
+                */
+               ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "**** Start pass 2\n"));
+               status = acpi_ns_one_complete_parse(ACPI_IMODE_LOAD_PASS2,
+                                                   table_index, start_node);
+               if (ACPI_FAILURE(status)) {
+                       return_ACPI_STATUS(status);
+               }
        }
 
        return_ACPI_STATUS(status);