diff options
Diffstat (limited to 'drivers/acpi/parser')
-rw-r--r-- | drivers/acpi/parser/psargs.c | 37 |
1 files changed, 34 insertions, 3 deletions
diff --git a/drivers/acpi/parser/psargs.c b/drivers/acpi/parser/psargs.c index 442880f5600..2a3a948dd11 100644 --- a/drivers/acpi/parser/psargs.c +++ b/drivers/acpi/parser/psargs.c @@ -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 */ |