Commit 9a884ab6 authored by Lin Ming's avatar Lin Ming Committed by Len Brown

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=762Signed-off-by: default avatarLin Ming <ming.m.lin@intel.com>
Signed-off-by: default avatarBob Moore <robert.moore@intel.com>
Signed-off-by: default avatarLen Brown <len.brown@intel.com>
parent dc95a270
...@@ -366,33 +366,49 @@ static void ...@@ -366,33 +366,49 @@ static void
acpi_ns_exec_module_code(union acpi_operand_object *method_obj, acpi_ns_exec_module_code(union acpi_operand_object *method_obj,
struct acpi_evaluate_info *info) 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_status status;
ACPI_FUNCTION_TRACE(ns_exec_module_code); 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 */ /* Initialize the evaluation information block */
ACPI_MEMSET(info, 0, sizeof(struct acpi_evaluate_info)); 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 * 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); parent_obj = acpi_ns_get_attached_object(parent_node);
acpi_ut_add_reference(root_obj); 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); ACPI_TYPE_METHOD);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
goto exit; goto exit;
} }
/* Execute the root node as a control method */ /* Execute the parent node as a control method */
status = acpi_ns_evaluate(info); status = acpi_ns_evaluate(info);
...@@ -401,15 +417,19 @@ acpi_ns_exec_module_code(union acpi_operand_object *method_obj, ...@@ -401,15 +417,19 @@ acpi_ns_exec_module_code(union acpi_operand_object *method_obj,
/* Detach the temporary method object */ /* 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 = if (parent_obj) {
acpi_ns_attach_object(acpi_gbl_root_node, root_obj, status = acpi_ns_attach_object(parent_node, parent_obj, type);
ACPI_TYPE_DEVICE); } else {
parent_node->type = (u8)type;
}
exit: exit:
acpi_ut_remove_reference(root_obj); if (parent_obj) {
acpi_ut_remove_reference(parent_obj);
}
return_VOID; return_VOID;
} }
...@@ -87,7 +87,8 @@ acpi_ps_complete_final_op(struct acpi_walk_state *walk_state, ...@@ -87,7 +87,8 @@ acpi_ps_complete_final_op(struct acpi_walk_state *walk_state,
union acpi_parse_object *op, acpi_status status); union acpi_parse_object *op, acpi_status status);
static void 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, ...@@ -479,11 +480,14 @@ acpi_ps_get_arguments(struct acpi_walk_state *walk_state,
*/ */
if (walk_state->pass_number == if (walk_state->pass_number ==
ACPI_IMODE_LOAD_PASS1) { ACPI_IMODE_LOAD_PASS1) {
acpi_ps_link_module_code(aml_op_start, acpi_ps_link_module_code(op->common.
walk_state-> parent,
aml_op_start,
(u32)
(walk_state->
parser_state. parser_state.
pkg_end - pkg_end -
aml_op_start, aml_op_start),
walk_state-> walk_state->
owner_id); owner_id);
} }
...@@ -598,7 +602,8 @@ acpi_ps_get_arguments(struct acpi_walk_state *walk_state, ...@@ -598,7 +602,8 @@ acpi_ps_get_arguments(struct acpi_walk_state *walk_state,
* *
* FUNCTION: acpi_ps_link_module_code * 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 * aml_length - Length of executable AML
* owner_id - owner_id of module level code * owner_id - owner_id of module level code
* *
...@@ -611,11 +616,13 @@ acpi_ps_get_arguments(struct acpi_walk_state *walk_state, ...@@ -611,11 +616,13 @@ acpi_ps_get_arguments(struct acpi_walk_state *walk_state,
******************************************************************************/ ******************************************************************************/
static void 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 *prev;
union acpi_operand_object *next; union acpi_operand_object *next;
union acpi_operand_object *method_obj; union acpi_operand_object *method_obj;
struct acpi_namespace_node *parent_node;
/* Get the tail of the list */ /* 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) ...@@ -639,11 +646,24 @@ acpi_ps_link_module_code(u8 *aml_start, u32 aml_length, acpi_owner_id owner_id)
return; 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_start = aml_start;
method_obj->method.aml_length = aml_length; method_obj->method.aml_length = aml_length;
method_obj->method.owner_id = owner_id; method_obj->method.owner_id = owner_id;
method_obj->method.flags |= AOPOBJ_MODULE_LEVEL; 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) { if (!prev) {
acpi_gbl_module_code_list = method_obj; acpi_gbl_module_code_list = method_obj;
} else { } else {
......
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