ACPICA: Fixes for Unload and DDBHandles
Lin Ming [Thu, 10 Apr 2008 15:06:42 +0000 (19:06 +0400)]
Implemented support for the use of DDBHandles as an Indexed
Reference, as per the ACPI spec.

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

Implemented support for UserTerm (Method invocation) for the Unload operator
as per the ACPI spec.

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

Signed-off-by: Bob Moore <robert.moore@intel.com>
Signed-off-by: Alexey Starikovskiy <astarikovskiy@suse.de>
Signed-off-by: Len Brown <len.brown@intel.com>

drivers/acpi/executer/exdump.c
drivers/acpi/executer/exresolv.c
drivers/acpi/executer/exstore.c
drivers/acpi/parser/psargs.c
drivers/acpi/utilities/utcopy.c

index 251d84b..ed560e6 100644 (file)
@@ -895,14 +895,25 @@ static void acpi_ex_dump_reference_obj(union acpi_operand_object *obj_desc)
        } else if (obj_desc->reference.object) {
                if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) ==
                    ACPI_DESC_TYPE_OPERAND) {
-                       acpi_os_printf(" Target: %p [%s]\n",
-                                      obj_desc->reference.object,
-                                      acpi_ut_get_type_name(((union
-                                                              acpi_operand_object
-                                                              *)obj_desc->
-                                                             reference.
-                                                             object)->common.
-                                                            type));
+                       acpi_os_printf(" Target: %p",
+                                      obj_desc->reference.object);
+                       if (obj_desc->reference.opcode == AML_LOAD_OP) {
+                               /*
+                                * For DDBHandle reference,
+                                * obj_desc->Reference.Object is the table index
+                                */
+                               acpi_os_printf(" [DDBHandle]\n");
+                       } else {
+                               acpi_os_printf(" [%s]\n",
+                                              acpi_ut_get_type_name(((union
+                                                                      acpi_operand_object
+                                                                      *)
+                                                                     obj_desc->
+                                                                     reference.
+                                                                     object)->
+                                                                    common.
+                                                                    type));
+                       }
                } else {
                        acpi_os_printf(" Target: %p\n",
                                       obj_desc->reference.object);
index 9c3cdf6..5b5b2ff 100644 (file)
@@ -382,10 +382,10 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state,
        }
 
        /*
-        * For reference objects created via the ref_of or Index operators,
-        * we need to get to the base object (as per the ACPI specification
-        * of the object_type and size_of operators). This means traversing
-        * the list of possibly many nested references.
+        * For reference objects created via the ref_of, Index, or Load/load_table
+        * operators, we need to get to the base object (as per the ACPI
+        * specification of the object_type and size_of operators). This means
+        * traversing the list of possibly many nested references.
         */
        while (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_REFERENCE) {
                switch (obj_desc->reference.opcode) {
@@ -455,6 +455,11 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state,
                        }
                        break;
 
+               case AML_LOAD_OP:
+
+                       type = ACPI_TYPE_DDB_HANDLE;
+                       goto exit;
+
                case AML_LOCAL_OP:
                case AML_ARG_OP:
 
index 2408122..725614e 100644 (file)
@@ -434,11 +434,24 @@ acpi_ex_store_object_to_index(union acpi_operand_object *source_desc,
                 */
                obj_desc = *(index_desc->reference.where);
 
-               status =
-                   acpi_ut_copy_iobject_to_iobject(source_desc, &new_desc,
-                                                   walk_state);
-               if (ACPI_FAILURE(status)) {
-                       return_ACPI_STATUS(status);
+               if (ACPI_GET_OBJECT_TYPE(source_desc) ==
+                   ACPI_TYPE_LOCAL_REFERENCE
+                   && source_desc->reference.opcode == AML_LOAD_OP) {
+
+                       /* This is a DDBHandle, just add a reference to it */
+
+                       acpi_ut_add_reference(source_desc);
+                       new_desc = source_desc;
+               } else {
+                       /* Normal object, copy it */
+
+                       status =
+                           acpi_ut_copy_iobject_to_iobject(source_desc,
+                                                           &new_desc,
+                                                           walk_state);
+                       if (ACPI_FAILURE(status)) {
+                               return_ACPI_STATUS(status);
+                       }
                }
 
                if (obj_desc) {
index 442880f..2a3a948 100644 (file)
@@ -235,6 +235,7 @@ acpi_ps_get_next_namepath(struct acpi_walk_state *walk_state,
        union acpi_parse_object *name_op;
        union acpi_operand_object *method_desc;
        struct acpi_namespace_node *node;
+       u8 *start = parser_state->aml;
 
        ACPI_FUNCTION_TRACE(ps_get_next_namepath);
 
@@ -267,6 +268,16 @@ acpi_ps_get_next_namepath(struct acpi_walk_state *walk_state,
         */
        if (ACPI_SUCCESS(status) &&
            possible_method_call && (node->type == ACPI_TYPE_METHOD)) {
+               if (walk_state->op->common.aml_opcode == AML_UNLOAD_OP) {
+                       /*
+                        * acpi_ps_get_next_namestring has increased the AML pointer,
+                        * so we need to restore the saved AML pointer for method call.
+                        */
+                       walk_state->parser_state.aml = start;
+                       walk_state->arg_count = 1;
+                       acpi_ps_init_op(arg, AML_INT_METHODCALL_OP);
+                       return_ACPI_STATUS(AE_OK);
+               }
 
                /* This name is actually a control method invocation */
 
@@ -678,9 +689,29 @@ acpi_ps_get_next_arg(struct acpi_walk_state *walk_state,
                                return_ACPI_STATUS(AE_NO_MEMORY);
                        }
 
-                       status =
-                           acpi_ps_get_next_namepath(walk_state, parser_state,
-                                                     arg, 0);
+                       /* To support super_name arg of Unload */
+
+                       if (walk_state->op->common.aml_opcode == AML_UNLOAD_OP) {
+                               status =
+                                   acpi_ps_get_next_namepath(walk_state,
+                                                             parser_state, arg,
+                                                             1);
+
+                               /*
+                                * If the super_name arg of Unload is a method call,
+                                * we have restored the AML pointer, just free this Arg
+                                */
+                               if (arg->common.aml_opcode ==
+                                   AML_INT_METHODCALL_OP) {
+                                       acpi_ps_free_op(arg);
+                                       arg = NULL;
+                               }
+                       } else {
+                               status =
+                                   acpi_ps_get_next_namepath(walk_state,
+                                                             parser_state, arg,
+                                                             0);
+                       }
                } else {
                        /* Single complex argument, nothing returned */
 
index b56953d..ba89971 100644 (file)
@@ -709,7 +709,15 @@ acpi_ut_copy_simple_object(union acpi_operand_object *source_desc,
                /*
                 * We copied the reference object, so we now must add a reference
                 * to the object pointed to by the reference
+                *
+                * DDBHandle reference (from Load/load_table is a special reference,
+                * it's Reference.Object is the table index, so does not need to
+                * increase the reference count
                 */
+               if (source_desc->reference.opcode == AML_LOAD_OP) {
+                       break;
+               }
+
                acpi_ut_add_reference(source_desc->reference.object);
                break;