diff options
Diffstat (limited to 'drivers/acpi/dispatcher')
-rw-r--r-- | drivers/acpi/dispatcher/dsmethod.c | 23 | ||||
-rw-r--r-- | drivers/acpi/dispatcher/dsmthdat.c | 6 | ||||
-rw-r--r-- | drivers/acpi/dispatcher/dswload.c | 41 |
3 files changed, 56 insertions, 14 deletions
diff --git a/drivers/acpi/dispatcher/dsmethod.c b/drivers/acpi/dispatcher/dsmethod.c index 651f2b68531b..e348db0e541e 100644 --- a/drivers/acpi/dispatcher/dsmethod.c +++ b/drivers/acpi/dispatcher/dsmethod.c @@ -385,6 +385,7 @@ acpi_ds_restart_control_method(struct acpi_walk_state *walk_state, union acpi_operand_object *return_desc) { acpi_status status; + int same_as_implicit_return; ACPI_FUNCTION_TRACE_PTR(ds_restart_control_method, walk_state); @@ -402,6 +403,11 @@ acpi_ds_restart_control_method(struct acpi_walk_state *walk_state, if (return_desc) { + /* Is the implicit return object the same as the return desc? */ + + same_as_implicit_return = + (walk_state->implicit_return_obj == return_desc); + /* Are we actually going to use the return value? */ if (walk_state->return_used) { @@ -422,18 +428,23 @@ acpi_ds_restart_control_method(struct acpi_walk_state *walk_state, } /* - * The following code is the - * optional support for a so-called "implicit return". Some AML code - * assumes that the last value of the method is "implicitly" returned - * to the caller. Just save the last result as the return value. + * The following code is the optional support for the so-called + * "implicit return". Some AML code assumes that the last value of the + * method is "implicitly" returned to the caller, in the absence of an + * explicit return value. + * + * Just save the last result of the method as the return value. + * * NOTE: this is optional because the ASL language does not actually * support this behavior. */ else if (!acpi_ds_do_implicit_return - (return_desc, walk_state, FALSE)) { + (return_desc, walk_state, FALSE) + || same_as_implicit_return) { /* * Delete the return value if it will not be used by the - * calling method + * calling method or remove one reference if the explicit return + * is the same as the implicit return value. */ acpi_ut_remove_reference(return_desc); } diff --git a/drivers/acpi/dispatcher/dsmthdat.c b/drivers/acpi/dispatcher/dsmthdat.c index b47c54fad86d..459160ff9058 100644 --- a/drivers/acpi/dispatcher/dsmthdat.c +++ b/drivers/acpi/dispatcher/dsmthdat.c @@ -336,7 +336,7 @@ acpi_ds_method_data_set_value(u16 opcode, * Increment ref count so object can't be deleted while installed. * NOTE: We do not copy the object in order to preserve the call by * reference semantics of ACPI Control Method invocation. - * (See ACPI specification 2.0_c) + * (See ACPI Specification 2.0_c) */ acpi_ut_add_reference(object); @@ -351,7 +351,7 @@ acpi_ds_method_data_set_value(u16 opcode, * FUNCTION: acpi_ds_method_data_get_value * * PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP - * Index - which local_var or argument to get + * Index - Which local_var or argument to get * walk_state - Current walk state object * dest_desc - Where Arg or Local value is returned * @@ -459,7 +459,7 @@ acpi_ds_method_data_get_value(u16 opcode, * FUNCTION: acpi_ds_method_data_delete_value * * PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP - * Index - which local_var or argument to delete + * Index - Which local_var or argument to delete * walk_state - Current walk state object * * RETURN: None diff --git a/drivers/acpi/dispatcher/dswload.c b/drivers/acpi/dispatcher/dswload.c index a8deb700cf33..35074399c617 100644 --- a/drivers/acpi/dispatcher/dswload.c +++ b/drivers/acpi/dispatcher/dswload.c @@ -178,12 +178,12 @@ acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state, * Target of Scope() not found. Generate an External for it, and * insert the name into the namespace. */ - acpi_dm_add_to_external_list(path); + acpi_dm_add_to_external_list(path, ACPI_TYPE_DEVICE, 0); status = acpi_ns_lookup(walk_state->scope_info, path, object_type, ACPI_IMODE_LOAD_PASS1, ACPI_NS_SEARCH_PARENT, walk_state, - &(node)); + &node); } #endif if (ACPI_FAILURE(status)) { @@ -301,10 +301,41 @@ acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state, status = acpi_ns_lookup(walk_state->scope_info, path, object_type, ACPI_IMODE_LOAD_PASS1, flags, walk_state, - &(node)); + &node); if (ACPI_FAILURE(status)) { - ACPI_ERROR_NAMESPACE(path, status); - return_ACPI_STATUS(status); + if (status == AE_ALREADY_EXISTS) { + + /* The name already exists in this scope */ + + if (node->flags & ANOBJ_IS_EXTERNAL) { + /* + * Allow one create on an object or segment that was + * previously declared External + */ + node->flags &= ~ANOBJ_IS_EXTERNAL; + node->type = (u8) object_type; + + /* Just retyped a node, probably will need to open a scope */ + + if (acpi_ns_opens_scope(object_type)) { + status = + acpi_ds_scope_stack_push + (node, object_type, + walk_state); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS + (status); + } + } + status = AE_OK; + } + } + + if (ACPI_FAILURE(status)) { + + ACPI_ERROR_NAMESPACE(path, status); + return_ACPI_STATUS(status); + } } break; } |