ACPICA: Add additional module-level code support
authorLin Ming <ming.m.lin@intel.com>
Thu, 12 Nov 2009 01:57:53 +0000 (09:57 +0800)
committerLen Brown <len.brown@intel.com>
Wed, 25 Nov 2009 02:31:11 +0000 (21:31 -0500)
This change will execute module-level code that is not at the
root of the namespace (under a Device object, etc.).
ACPICA BZ 762.

http://www.acpica.org/bugzilla/show_bug.cgi?id=762

Signed-off-by: Lin Ming <ming.m.lin@intel.com>
Signed-off-by: Bob Moore <robert.moore@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
drivers/acpi/acpica/nseval.c
drivers/acpi/acpica/psloop.c

index 846d1132feb1133faf08cbc8f65124d30f783308..f771e978c40396cc405e5484e29344dd5176d9f8 100644 (file)
@@ -366,33 +366,49 @@ static void
 acpi_ns_exec_module_code(union acpi_operand_object *method_obj,
                         struct acpi_evaluate_info *info)
 {
-       union acpi_operand_object *root_obj;
+       union acpi_operand_object *parent_obj;
+       struct acpi_namespace_node *parent_node;
+       acpi_object_type type;
        acpi_status status;
 
        ACPI_FUNCTION_TRACE(ns_exec_module_code);
 
+       /*
+        * Get the parent node. We cheat by using the next_object field
+        * of the method object descriptor.
+        */
+       parent_node = ACPI_CAST_PTR(struct acpi_namespace_node,
+                                   method_obj->method.next_object);
+       type = acpi_ns_get_type(parent_node);
+
+       /* Must clear next_object (acpi_ns_attach_object needs the field) */
+
+       method_obj->method.next_object = NULL;
+
        /* Initialize the evaluation information block */
 
        ACPI_MEMSET(info, 0, sizeof(struct acpi_evaluate_info));
-       info->prefix_node = acpi_gbl_root_node;
+       info->prefix_node = parent_node;
 
        /*
-        * Get the currently attached root object. Add a reference, because the
+        * Get the currently attached parent object. Add a reference, because the
         * ref count will be decreased when the method object is installed to
-        * the root node.
+        * the parent node.
         */
-       root_obj = acpi_ns_get_attached_object(acpi_gbl_root_node);
-       acpi_ut_add_reference(root_obj);
+       parent_obj = acpi_ns_get_attached_object(parent_node);
+       if (parent_obj) {
+               acpi_ut_add_reference(parent_obj);
+       }
 
-       /* Install the method (module-level code) in the root node */
+       /* Install the method (module-level code) in the parent node */
 
-       status = acpi_ns_attach_object(acpi_gbl_root_node, method_obj,
+       status = acpi_ns_attach_object(parent_node, method_obj,
                                       ACPI_TYPE_METHOD);
        if (ACPI_FAILURE(status)) {
                goto exit;
        }
 
-       /* Execute the root node as a control method */
+       /* Execute the parent node as a control method */
 
        status = acpi_ns_evaluate(info);
 
@@ -401,15 +417,19 @@ acpi_ns_exec_module_code(union acpi_operand_object *method_obj,
 
        /* Detach the temporary method object */
 
-       acpi_ns_detach_object(acpi_gbl_root_node);
+       acpi_ns_detach_object(parent_node);
 
-       /* Restore the original root object */
+       /* Restore the original parent object */
 
-       status =
-           acpi_ns_attach_object(acpi_gbl_root_node, root_obj,
-                                 ACPI_TYPE_DEVICE);
+       if (parent_obj) {
+               status = acpi_ns_attach_object(parent_node, parent_obj, type);
+       } else {
+               parent_node->type = (u8)type;
+       }
 
       exit:
-       acpi_ut_remove_reference(root_obj);
+       if (parent_obj) {
+               acpi_ut_remove_reference(parent_obj);
+       }
        return_VOID;
 }
index cd7995b3aed4a3c06096a4e2ae0d56f4a3a3c9c3..0988e4a8901da1c262230c79013be926f089c733 100644 (file)
@@ -87,7 +87,8 @@ acpi_ps_complete_final_op(struct acpi_walk_state *walk_state,
                          union acpi_parse_object *op, acpi_status status);
 
 static void
-acpi_ps_link_module_code(u8 *aml_start, u32 aml_length, acpi_owner_id owner_id);
+acpi_ps_link_module_code(union acpi_parse_object *parent_op,
+                        u8 *aml_start, u32 aml_length, acpi_owner_id owner_id);
 
 /*******************************************************************************
  *
@@ -479,11 +480,14 @@ acpi_ps_get_arguments(struct acpi_walk_state *walk_state,
                                 */
                                if (walk_state->pass_number ==
                                    ACPI_IMODE_LOAD_PASS1) {
-                                       acpi_ps_link_module_code(aml_op_start,
-                                                                walk_state->
+                                       acpi_ps_link_module_code(op->common.
+                                                                parent,
+                                                                aml_op_start,
+                                                                (u32)
+                                                                (walk_state->
                                                                 parser_state.
                                                                 pkg_end -
-                                                                aml_op_start,
+                                                                aml_op_start),
                                                                 walk_state->
                                                                 owner_id);
                                }
@@ -598,7 +602,8 @@ acpi_ps_get_arguments(struct acpi_walk_state *walk_state,
  *
  * FUNCTION:    acpi_ps_link_module_code
  *
- * PARAMETERS:  aml_start           - Pointer to the AML
+ * PARAMETERS:  parent_op           - Parent parser op
+ *              aml_start           - Pointer to the AML
  *              aml_length          - Length of executable AML
  *              owner_id            - owner_id of module level code
  *
@@ -611,11 +616,13 @@ acpi_ps_get_arguments(struct acpi_walk_state *walk_state,
  ******************************************************************************/
 
 static void
-acpi_ps_link_module_code(u8 *aml_start, u32 aml_length, acpi_owner_id owner_id)
+acpi_ps_link_module_code(union acpi_parse_object *parent_op,
+                        u8 *aml_start, u32 aml_length, acpi_owner_id owner_id)
 {
        union acpi_operand_object *prev;
        union acpi_operand_object *next;
        union acpi_operand_object *method_obj;
+       struct acpi_namespace_node *parent_node;
 
        /* Get the tail of the list */
 
@@ -639,11 +646,24 @@ acpi_ps_link_module_code(u8 *aml_start, u32 aml_length, acpi_owner_id owner_id)
                        return;
                }
 
+               if (parent_op->common.node) {
+                       parent_node = parent_op->common.node;
+               } else {
+                       parent_node = acpi_gbl_root_node;
+               }
+
                method_obj->method.aml_start = aml_start;
                method_obj->method.aml_length = aml_length;
                method_obj->method.owner_id = owner_id;
                method_obj->method.flags |= AOPOBJ_MODULE_LEVEL;
 
+               /*
+                * Save the parent node in next_object. This is cheating, but we
+                * don't want to expand the method object.
+                */
+               method_obj->method.next_object =
+                   ACPI_CAST_PTR(union acpi_operand_object, parent_node);
+
                if (!prev) {
                        acpi_gbl_module_code_list = method_obj;
                } else {