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 { |
