ACPICA: Fixes for Unload and DDBHandles
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>
diff --git a/drivers/acpi/executer/exdump.c b/drivers/acpi/executer/exdump.c
index 251d84b..ed560e6 100644
--- a/drivers/acpi/executer/exdump.c
+++ b/drivers/acpi/executer/exdump.c
@@ -895,14 +895,25 @@
} 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);
diff --git a/drivers/acpi/executer/exresolv.c b/drivers/acpi/executer/exresolv.c
index 9c3cdf6..5b5b2ff 100644
--- a/drivers/acpi/executer/exresolv.c
+++ b/drivers/acpi/executer/exresolv.c
@@ -382,10 +382,10 @@
}
/*
- * 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 @@
}
break;
+ case AML_LOAD_OP:
+
+ type = ACPI_TYPE_DDB_HANDLE;
+ goto exit;
+
case AML_LOCAL_OP:
case AML_ARG_OP:
diff --git a/drivers/acpi/executer/exstore.c b/drivers/acpi/executer/exstore.c
index 2408122..725614e 100644
--- a/drivers/acpi/executer/exstore.c
+++ b/drivers/acpi/executer/exstore.c
@@ -434,11 +434,24 @@
*/
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) {
diff --git a/drivers/acpi/parser/psargs.c b/drivers/acpi/parser/psargs.c
index 442880f..2a3a948 100644
--- a/drivers/acpi/parser/psargs.c
+++ b/drivers/acpi/parser/psargs.c
@@ -235,6 +235,7 @@
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 @@
*/
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 @@
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 */
diff --git a/drivers/acpi/utilities/utcopy.c b/drivers/acpi/utilities/utcopy.c
index b56953d2..ba89971 100644
--- a/drivers/acpi/utilities/utcopy.c
+++ b/drivers/acpi/utilities/utcopy.c
@@ -709,7 +709,15 @@
/*
* 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;