ACPICA: Add additional module-level code support

This change will execute module-level code that is not at the
root of the namespace (under a Device object, etc.).
ACPICA BZ 762.

http://www.acpica.org/bugzilla/show_bug.cgi?id=762

Signed-off-by: Lin Ming <ming.m.lin@intel.com>
Signed-off-by: Bob Moore <robert.moore@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
This commit is contained in:
Lin Ming 2009-11-12 09:57:53 +08:00 committed by Len Brown
parent dc95a270c6
commit 9a884ab64a
2 changed files with 61 additions and 21 deletions

View File

@ -366,33 +366,49 @@ static void
acpi_ns_exec_module_code(union acpi_operand_object *method_obj,
struct acpi_evaluate_info *info)
{
union acpi_operand_object *root_obj;
union acpi_operand_object *parent_obj;
struct acpi_namespace_node *parent_node;
acpi_object_type type;
acpi_status status;
ACPI_FUNCTION_TRACE(ns_exec_module_code);
/*
* Get the parent node. We cheat by using the next_object field
* of the method object descriptor.
*/
parent_node = ACPI_CAST_PTR(struct acpi_namespace_node,
method_obj->method.next_object);
type = acpi_ns_get_type(parent_node);
/* Must clear next_object (acpi_ns_attach_object needs the field) */
method_obj->method.next_object = NULL;
/* Initialize the evaluation information block */
ACPI_MEMSET(info, 0, sizeof(struct acpi_evaluate_info));
info->prefix_node = acpi_gbl_root_node;
info->prefix_node = parent_node;
/*
* Get the currently attached root object. Add a reference, because the
* Get the currently attached parent object. Add a reference, because the
* ref count will be decreased when the method object is installed to
* the root node.
* the parent node.
*/
root_obj = acpi_ns_get_attached_object(acpi_gbl_root_node);
acpi_ut_add_reference(root_obj);
parent_obj = acpi_ns_get_attached_object(parent_node);
if (parent_obj) {
acpi_ut_add_reference(parent_obj);
}
/* Install the method (module-level code) in the root node */
/* Install the method (module-level code) in the parent node */
status = acpi_ns_attach_object(acpi_gbl_root_node, method_obj,
status = acpi_ns_attach_object(parent_node, method_obj,
ACPI_TYPE_METHOD);
if (ACPI_FAILURE(status)) {
goto exit;
}
/* Execute the root node as a control method */
/* Execute the parent node as a control method */
status = acpi_ns_evaluate(info);
@ -401,15 +417,19 @@ acpi_ns_exec_module_code(union acpi_operand_object *method_obj,
/* Detach the temporary method object */
acpi_ns_detach_object(acpi_gbl_root_node);
acpi_ns_detach_object(parent_node);
/* Restore the original root object */
/* Restore the original parent object */
status =
acpi_ns_attach_object(acpi_gbl_root_node, root_obj,
ACPI_TYPE_DEVICE);
if (parent_obj) {
status = acpi_ns_attach_object(parent_node, parent_obj, type);
} else {
parent_node->type = (u8)type;
}
exit:
acpi_ut_remove_reference(root_obj);
if (parent_obj) {
acpi_ut_remove_reference(parent_obj);
}
return_VOID;
}

View File

@ -87,7 +87,8 @@ acpi_ps_complete_final_op(struct acpi_walk_state *walk_state,
union acpi_parse_object *op, acpi_status status);
static void
acpi_ps_link_module_code(u8 *aml_start, u32 aml_length, acpi_owner_id owner_id);
acpi_ps_link_module_code(union acpi_parse_object *parent_op,
u8 *aml_start, u32 aml_length, acpi_owner_id owner_id);
/*******************************************************************************
*
@ -479,11 +480,14 @@ acpi_ps_get_arguments(struct acpi_walk_state *walk_state,
*/
if (walk_state->pass_number ==
ACPI_IMODE_LOAD_PASS1) {
acpi_ps_link_module_code(aml_op_start,
walk_state->
acpi_ps_link_module_code(op->common.
parent,
aml_op_start,
(u32)
(walk_state->
parser_state.
pkg_end -
aml_op_start,
aml_op_start),
walk_state->
owner_id);
}
@ -598,7 +602,8 @@ acpi_ps_get_arguments(struct acpi_walk_state *walk_state,
*
* FUNCTION: acpi_ps_link_module_code
*
* PARAMETERS: aml_start - Pointer to the AML
* PARAMETERS: parent_op - Parent parser op
* aml_start - Pointer to the AML
* aml_length - Length of executable AML
* owner_id - owner_id of module level code
*
@ -611,11 +616,13 @@ acpi_ps_get_arguments(struct acpi_walk_state *walk_state,
******************************************************************************/
static void
acpi_ps_link_module_code(u8 *aml_start, u32 aml_length, acpi_owner_id owner_id)
acpi_ps_link_module_code(union acpi_parse_object *parent_op,
u8 *aml_start, u32 aml_length, acpi_owner_id owner_id)
{
union acpi_operand_object *prev;
union acpi_operand_object *next;
union acpi_operand_object *method_obj;
struct acpi_namespace_node *parent_node;
/* Get the tail of the list */
@ -639,11 +646,24 @@ acpi_ps_link_module_code(u8 *aml_start, u32 aml_length, acpi_owner_id owner_id)
return;
}
if (parent_op->common.node) {
parent_node = parent_op->common.node;
} else {
parent_node = acpi_gbl_root_node;
}
method_obj->method.aml_start = aml_start;
method_obj->method.aml_length = aml_length;
method_obj->method.owner_id = owner_id;
method_obj->method.flags |= AOPOBJ_MODULE_LEVEL;
/*
* Save the parent node in next_object. This is cheating, but we
* don't want to expand the method object.
*/
method_obj->method.next_object =
ACPI_CAST_PTR(union acpi_operand_object, parent_node);
if (!prev) {
acpi_gbl_module_code_list = method_obj;
} else {