diff options
Diffstat (limited to 'drivers/acpi/dispatcher/dswexec.c')
-rw-r--r-- | drivers/acpi/dispatcher/dswexec.c | 61 |
1 files changed, 46 insertions, 15 deletions
diff --git a/drivers/acpi/dispatcher/dswexec.c b/drivers/acpi/dispatcher/dswexec.c index b02322e213de9..2071a0d2bbbb9 100644 --- a/drivers/acpi/dispatcher/dswexec.c +++ b/drivers/acpi/dispatcher/dswexec.c @@ -91,6 +91,7 @@ acpi_ds_get_predicate_value ( union acpi_operand_object *result_obj) { acpi_status status = AE_OK; union acpi_operand_object *obj_desc; + union acpi_operand_object *local_obj_desc = NULL; ACPI_FUNCTION_TRACE_PTR ("ds_get_predicate_value", walk_state); @@ -130,12 +131,17 @@ acpi_ds_get_predicate_value ( } /* - * Result of predicate evaluation currently must - * be a number + * Result of predicate evaluation must be an Integer + * object. Implicitly convert the argument if necessary. */ - if (ACPI_GET_OBJECT_TYPE (obj_desc) != ACPI_TYPE_INTEGER) { + status = acpi_ex_convert_to_integer (obj_desc, &local_obj_desc, 16); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + + if (ACPI_GET_OBJECT_TYPE (local_obj_desc) != ACPI_TYPE_INTEGER) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, - "Bad predicate (not a number) obj_desc=%p State=%p Type=%X\n", + "Bad predicate (not an integer) obj_desc=%p State=%p Type=%X\n", obj_desc, walk_state, ACPI_GET_OBJECT_TYPE (obj_desc))); status = AE_AML_OPERAND_TYPE; @@ -144,13 +150,13 @@ acpi_ds_get_predicate_value ( /* Truncate the predicate to 32-bits if necessary */ - acpi_ex_truncate_for32bit_table (obj_desc); + acpi_ex_truncate_for32bit_table (local_obj_desc); /* * Save the result of the predicate evaluation on * the control stack */ - if (obj_desc->integer.value) { + if (local_obj_desc->integer.value) { walk_state->control_state->common.value = TRUE; } else { @@ -170,12 +176,15 @@ cleanup: /* Break to debugger to display result */ - ACPI_DEBUGGER_EXEC (acpi_db_display_result_object (obj_desc, walk_state)); + ACPI_DEBUGGER_EXEC (acpi_db_display_result_object (local_obj_desc, walk_state)); /* * Delete the predicate result object (we know that * we don't need it anymore) */ + if (local_obj_desc != obj_desc) { + acpi_ut_remove_reference (local_obj_desc); + } acpi_ut_remove_reference (obj_desc); walk_state->control_state->common.state = ACPI_CONTROL_NORMAL; @@ -306,9 +315,10 @@ acpi_ds_exec_begin_op ( case AML_CLASS_EXECUTE: case AML_CLASS_CREATE: - /* most operators with arguments */ - /* Start a new result/operand state */ - + /* + * Most operators with arguments. + * Start a new result/operand state + */ status = acpi_ds_result_stack_push (walk_state); break; @@ -471,20 +481,41 @@ acpi_ds_exec_end_op ( /* 1 Operand, 0 external_result, 0 internal_result */ status = acpi_ds_exec_end_control_op (walk_state, op); - if (ACPI_FAILURE (status)) { - break; - } - status = acpi_ds_result_stack_pop (walk_state); + /* Make sure to properly pop the result stack */ + + if (ACPI_SUCCESS (status)) { + status = acpi_ds_result_stack_pop (walk_state); + } + else if (status == AE_CTRL_PENDING) { + status = acpi_ds_result_stack_pop (walk_state); + if (ACPI_SUCCESS (status)) { + status = AE_CTRL_PENDING; + } + } break; case AML_TYPE_METHOD_CALL: + /* + * If the method is referenced from within a package + * declaration, it is not a invocation of the method, just + * a reference to it. + */ + if ((op->asl.parent) && + ((op->asl.parent->asl.aml_opcode == AML_PACKAGE_OP) || + (op->asl.parent->asl.aml_opcode == AML_VAR_PACKAGE_OP))) { + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Method Reference in a Package, Op=%p\n", op)); + op->common.node = (struct acpi_namespace_node *) op->asl.value.arg->asl.node->object; + acpi_ut_add_reference (op->asl.value.arg->asl.node->object); + return_ACPI_STATUS (AE_OK); + } + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Method invocation, Op=%p\n", op)); /* - * (AML_METHODCALL) Op->Value->Arg->Node contains + * (AML_METHODCALL) Op->Asl.Value.Arg->Asl.Node contains * the method Node pointer */ /* next_op points to the op that holds the method name */ |