Commit bc7a36ab authored by Lin Ming's avatar Lin Ming Committed by Len Brown

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=580Signed-off-by: default avatarBob Moore <robert.moore@intel.com>
Signed-off-by: default avatarAlexey Starikovskiy <astarikovskiy@suse.de>
Signed-off-by: default avatarLen Brown <len.brown@intel.com>
parent a6f4a451
...@@ -895,14 +895,25 @@ static void acpi_ex_dump_reference_obj(union acpi_operand_object *obj_desc) ...@@ -895,14 +895,25 @@ static void acpi_ex_dump_reference_obj(union acpi_operand_object *obj_desc)
} else if (obj_desc->reference.object) { } else if (obj_desc->reference.object) {
if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) == if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) ==
ACPI_DESC_TYPE_OPERAND) { ACPI_DESC_TYPE_OPERAND) {
acpi_os_printf(" Target: %p [%s]\n", acpi_os_printf(" Target: %p",
obj_desc->reference.object, 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_ut_get_type_name(((union
acpi_operand_object acpi_operand_object
*)obj_desc-> *)
obj_desc->
reference. reference.
object)->common. object)->
common.
type)); type));
}
} else { } else {
acpi_os_printf(" Target: %p\n", acpi_os_printf(" Target: %p\n",
obj_desc->reference.object); obj_desc->reference.object);
......
...@@ -382,10 +382,10 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state, ...@@ -382,10 +382,10 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state,
} }
/* /*
* For reference objects created via the ref_of or Index operators, * For reference objects created via the ref_of, Index, or Load/load_table
* we need to get to the base object (as per the ACPI specification * operators, we need to get to the base object (as per the ACPI
* of the object_type and size_of operators). This means traversing * specification of the object_type and size_of operators). This means
* the list of possibly many nested references. * traversing the list of possibly many nested references.
*/ */
while (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_REFERENCE) { while (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_REFERENCE) {
switch (obj_desc->reference.opcode) { switch (obj_desc->reference.opcode) {
...@@ -455,6 +455,11 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state, ...@@ -455,6 +455,11 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state,
} }
break; break;
case AML_LOAD_OP:
type = ACPI_TYPE_DDB_HANDLE;
goto exit;
case AML_LOCAL_OP: case AML_LOCAL_OP:
case AML_ARG_OP: case AML_ARG_OP:
......
...@@ -434,12 +434,25 @@ acpi_ex_store_object_to_index(union acpi_operand_object *source_desc, ...@@ -434,12 +434,25 @@ acpi_ex_store_object_to_index(union acpi_operand_object *source_desc,
*/ */
obj_desc = *(index_desc->reference.where); obj_desc = *(index_desc->reference.where);
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 = status =
acpi_ut_copy_iobject_to_iobject(source_desc, &new_desc, acpi_ut_copy_iobject_to_iobject(source_desc,
&new_desc,
walk_state); walk_state);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status); return_ACPI_STATUS(status);
} }
}
if (obj_desc) { if (obj_desc) {
......
...@@ -235,6 +235,7 @@ acpi_ps_get_next_namepath(struct acpi_walk_state *walk_state, ...@@ -235,6 +235,7 @@ acpi_ps_get_next_namepath(struct acpi_walk_state *walk_state,
union acpi_parse_object *name_op; union acpi_parse_object *name_op;
union acpi_operand_object *method_desc; union acpi_operand_object *method_desc;
struct acpi_namespace_node *node; struct acpi_namespace_node *node;
u8 *start = parser_state->aml;
ACPI_FUNCTION_TRACE(ps_get_next_namepath); ACPI_FUNCTION_TRACE(ps_get_next_namepath);
...@@ -267,6 +268,16 @@ acpi_ps_get_next_namepath(struct acpi_walk_state *walk_state, ...@@ -267,6 +268,16 @@ acpi_ps_get_next_namepath(struct acpi_walk_state *walk_state,
*/ */
if (ACPI_SUCCESS(status) && if (ACPI_SUCCESS(status) &&
possible_method_call && (node->type == ACPI_TYPE_METHOD)) { 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 */ /* This name is actually a control method invocation */
...@@ -678,9 +689,29 @@ acpi_ps_get_next_arg(struct acpi_walk_state *walk_state, ...@@ -678,9 +689,29 @@ acpi_ps_get_next_arg(struct acpi_walk_state *walk_state,
return_ACPI_STATUS(AE_NO_MEMORY); return_ACPI_STATUS(AE_NO_MEMORY);
} }
/* To support super_name arg of Unload */
if (walk_state->op->common.aml_opcode == AML_UNLOAD_OP) {
status = status =
acpi_ps_get_next_namepath(walk_state, parser_state, acpi_ps_get_next_namepath(walk_state,
arg, 0); 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 { } else {
/* Single complex argument, nothing returned */ /* Single complex argument, nothing returned */
......
...@@ -709,7 +709,15 @@ acpi_ut_copy_simple_object(union acpi_operand_object *source_desc, ...@@ -709,7 +709,15 @@ acpi_ut_copy_simple_object(union acpi_operand_object *source_desc,
/* /*
* We copied the reference object, so we now must add a reference * We copied the reference object, so we now must add a reference
* to the object pointed to by the 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); acpi_ut_add_reference(source_desc->reference.object);
break; break;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment