aboutsummaryrefslogtreecommitdiff
path: root/drivers/acpi/parser/psargs.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/parser/psargs.c')
-rw-r--r--drivers/acpi/parser/psargs.c37
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 */