summaryrefslogtreecommitdiff
path: root/drivers/acpi/dispatcher
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/dispatcher')
-rw-r--r--drivers/acpi/dispatcher/dsmethod.c23
-rw-r--r--drivers/acpi/dispatcher/dsmthdat.c6
-rw-r--r--drivers/acpi/dispatcher/dswload.c41
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;
}