diff options
author | Lin Ming <ming.m.lin@intel.com> | 2009-11-11 20:57:53 -0500 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2009-11-24 21:31:11 -0500 |
commit | 9a884ab64a4d092b4c3bf24fd9a30f7fbd4591e7 (patch) | |
tree | 6b9fae885e7c6fc46e732db201a52a5c49260947 | |
parent | dc95a270c684e771b25dce0b60559cc80c033f22 (diff) |
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>
-rw-r--r-- | drivers/acpi/acpica/nseval.c | 50 | ||||
-rw-r--r-- | drivers/acpi/acpica/psloop.c | 32 |
2 files changed, 61 insertions, 21 deletions
diff --git a/drivers/acpi/acpica/nseval.c b/drivers/acpi/acpica/nseval.c index 846d1132feb1..f771e978c403 100644 --- a/drivers/acpi/acpica/nseval.c +++ b/drivers/acpi/acpica/nseval.c | |||
@@ -366,33 +366,49 @@ static void | |||
366 | acpi_ns_exec_module_code(union acpi_operand_object *method_obj, | 366 | acpi_ns_exec_module_code(union acpi_operand_object *method_obj, |
367 | struct acpi_evaluate_info *info) | 367 | struct acpi_evaluate_info *info) |
368 | { | 368 | { |
369 | union acpi_operand_object *root_obj; | 369 | union acpi_operand_object *parent_obj; |
370 | struct acpi_namespace_node *parent_node; | ||
371 | acpi_object_type type; | ||
370 | acpi_status status; | 372 | acpi_status status; |
371 | 373 | ||
372 | ACPI_FUNCTION_TRACE(ns_exec_module_code); | 374 | ACPI_FUNCTION_TRACE(ns_exec_module_code); |
373 | 375 | ||
376 | /* | ||
377 | * Get the parent node. We cheat by using the next_object field | ||
378 | * of the method object descriptor. | ||
379 | */ | ||
380 | parent_node = ACPI_CAST_PTR(struct acpi_namespace_node, | ||
381 | method_obj->method.next_object); | ||
382 | type = acpi_ns_get_type(parent_node); | ||
383 | |||
384 | /* Must clear next_object (acpi_ns_attach_object needs the field) */ | ||
385 | |||
386 | method_obj->method.next_object = NULL; | ||
387 | |||
374 | /* Initialize the evaluation information block */ | 388 | /* Initialize the evaluation information block */ |
375 | 389 | ||
376 | ACPI_MEMSET(info, 0, sizeof(struct acpi_evaluate_info)); | 390 | ACPI_MEMSET(info, 0, sizeof(struct acpi_evaluate_info)); |
377 | info->prefix_node = acpi_gbl_root_node; | 391 | info->prefix_node = parent_node; |
378 | 392 | ||
379 | /* | 393 | /* |
380 | * Get the currently attached root object. Add a reference, because the | 394 | * Get the currently attached parent object. Add a reference, because the |
381 | * ref count will be decreased when the method object is installed to | 395 | * ref count will be decreased when the method object is installed to |
382 | * the root node. | 396 | * the parent node. |
383 | */ | 397 | */ |
384 | root_obj = acpi_ns_get_attached_object(acpi_gbl_root_node); | 398 | parent_obj = acpi_ns_get_attached_object(parent_node); |
385 | acpi_ut_add_reference(root_obj); | 399 | if (parent_obj) { |
400 | acpi_ut_add_reference(parent_obj); | ||
401 | } | ||
386 | 402 | ||
387 | /* Install the method (module-level code) in the root node */ | 403 | /* Install the method (module-level code) in the parent node */ |
388 | 404 | ||
389 | status = acpi_ns_attach_object(acpi_gbl_root_node, method_obj, | 405 | status = acpi_ns_attach_object(parent_node, method_obj, |
390 | ACPI_TYPE_METHOD); | 406 | ACPI_TYPE_METHOD); |
391 | if (ACPI_FAILURE(status)) { | 407 | if (ACPI_FAILURE(status)) { |
392 | goto exit; | 408 | goto exit; |
393 | } | 409 | } |
394 | 410 | ||
395 | /* Execute the root node as a control method */ | 411 | /* Execute the parent node as a control method */ |
396 | 412 | ||
397 | status = acpi_ns_evaluate(info); | 413 | status = acpi_ns_evaluate(info); |
398 | 414 | ||
@@ -401,15 +417,19 @@ acpi_ns_exec_module_code(union acpi_operand_object *method_obj, | |||
401 | 417 | ||
402 | /* Detach the temporary method object */ | 418 | /* Detach the temporary method object */ |
403 | 419 | ||
404 | acpi_ns_detach_object(acpi_gbl_root_node); | 420 | acpi_ns_detach_object(parent_node); |
405 | 421 | ||
406 | /* Restore the original root object */ | 422 | /* Restore the original parent object */ |
407 | 423 | ||
408 | status = | 424 | if (parent_obj) { |
409 | acpi_ns_attach_object(acpi_gbl_root_node, root_obj, | 425 | status = acpi_ns_attach_object(parent_node, parent_obj, type); |
410 | ACPI_TYPE_DEVICE); | 426 | } else { |
427 | parent_node->type = (u8)type; | ||
428 | } | ||
411 | 429 | ||
412 | exit: | 430 | exit: |
413 | acpi_ut_remove_reference(root_obj); | 431 | if (parent_obj) { |
432 | acpi_ut_remove_reference(parent_obj); | ||
433 | } | ||
414 | return_VOID; | 434 | return_VOID; |
415 | } | 435 | } |
diff --git a/drivers/acpi/acpica/psloop.c b/drivers/acpi/acpica/psloop.c index cd7995b3aed4..0988e4a8901d 100644 --- a/drivers/acpi/acpica/psloop.c +++ b/drivers/acpi/acpica/psloop.c | |||
@@ -87,7 +87,8 @@ acpi_ps_complete_final_op(struct acpi_walk_state *walk_state, | |||
87 | union acpi_parse_object *op, acpi_status status); | 87 | union acpi_parse_object *op, acpi_status status); |
88 | 88 | ||
89 | static void | 89 | static void |
90 | acpi_ps_link_module_code(u8 *aml_start, u32 aml_length, acpi_owner_id owner_id); | 90 | acpi_ps_link_module_code(union acpi_parse_object *parent_op, |
91 | u8 *aml_start, u32 aml_length, acpi_owner_id owner_id); | ||
91 | 92 | ||
92 | /******************************************************************************* | 93 | /******************************************************************************* |
93 | * | 94 | * |
@@ -479,11 +480,14 @@ acpi_ps_get_arguments(struct acpi_walk_state *walk_state, | |||
479 | */ | 480 | */ |
480 | if (walk_state->pass_number == | 481 | if (walk_state->pass_number == |
481 | ACPI_IMODE_LOAD_PASS1) { | 482 | ACPI_IMODE_LOAD_PASS1) { |
482 | acpi_ps_link_module_code(aml_op_start, | 483 | acpi_ps_link_module_code(op->common. |
483 | walk_state-> | 484 | parent, |
485 | aml_op_start, | ||
486 | (u32) | ||
487 | (walk_state-> | ||
484 | parser_state. | 488 | parser_state. |
485 | pkg_end - | 489 | pkg_end - |
486 | aml_op_start, | 490 | aml_op_start), |
487 | walk_state-> | 491 | walk_state-> |
488 | owner_id); | 492 | owner_id); |
489 | } | 493 | } |
@@ -598,7 +602,8 @@ acpi_ps_get_arguments(struct acpi_walk_state *walk_state, | |||
598 | * | 602 | * |
599 | * FUNCTION: acpi_ps_link_module_code | 603 | * FUNCTION: acpi_ps_link_module_code |
600 | * | 604 | * |
601 | * PARAMETERS: aml_start - Pointer to the AML | 605 | * PARAMETERS: parent_op - Parent parser op |
606 | * aml_start - Pointer to the AML | ||
602 | * aml_length - Length of executable AML | 607 | * aml_length - Length of executable AML |
603 | * owner_id - owner_id of module level code | 608 | * owner_id - owner_id of module level code |
604 | * | 609 | * |
@@ -611,11 +616,13 @@ acpi_ps_get_arguments(struct acpi_walk_state *walk_state, | |||
611 | ******************************************************************************/ | 616 | ******************************************************************************/ |
612 | 617 | ||
613 | static void | 618 | static void |
614 | acpi_ps_link_module_code(u8 *aml_start, u32 aml_length, acpi_owner_id owner_id) | 619 | acpi_ps_link_module_code(union acpi_parse_object *parent_op, |
620 | u8 *aml_start, u32 aml_length, acpi_owner_id owner_id) | ||
615 | { | 621 | { |
616 | union acpi_operand_object *prev; | 622 | union acpi_operand_object *prev; |
617 | union acpi_operand_object *next; | 623 | union acpi_operand_object *next; |
618 | union acpi_operand_object *method_obj; | 624 | union acpi_operand_object *method_obj; |
625 | struct acpi_namespace_node *parent_node; | ||
619 | 626 | ||
620 | /* Get the tail of the list */ | 627 | /* Get the tail of the list */ |
621 | 628 | ||
@@ -639,11 +646,24 @@ acpi_ps_link_module_code(u8 *aml_start, u32 aml_length, acpi_owner_id owner_id) | |||
639 | return; | 646 | return; |
640 | } | 647 | } |
641 | 648 | ||
649 | if (parent_op->common.node) { | ||
650 | parent_node = parent_op->common.node; | ||
651 | } else { | ||
652 | parent_node = acpi_gbl_root_node; | ||
653 | } | ||
654 | |||
642 | method_obj->method.aml_start = aml_start; | 655 | method_obj->method.aml_start = aml_start; |
643 | method_obj->method.aml_length = aml_length; | 656 | method_obj->method.aml_length = aml_length; |
644 | method_obj->method.owner_id = owner_id; | 657 | method_obj->method.owner_id = owner_id; |
645 | method_obj->method.flags |= AOPOBJ_MODULE_LEVEL; | 658 | method_obj->method.flags |= AOPOBJ_MODULE_LEVEL; |
646 | 659 | ||
660 | /* | ||
661 | * Save the parent node in next_object. This is cheating, but we | ||
662 | * don't want to expand the method object. | ||
663 | */ | ||
664 | method_obj->method.next_object = | ||
665 | ACPI_CAST_PTR(union acpi_operand_object, parent_node); | ||
666 | |||
647 | if (!prev) { | 667 | if (!prev) { |
648 | acpi_gbl_module_code_list = method_obj; | 668 | acpi_gbl_module_code_list = method_obj; |
649 | } else { | 669 | } else { |