aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi
diff options
context:
space:
mode:
authorLin Ming <ming.m.lin@intel.com>2009-11-11 20:57:53 -0500
committerLen Brown <len.brown@intel.com>2009-11-24 21:31:11 -0500
commit9a884ab64a4d092b4c3bf24fd9a30f7fbd4591e7 (patch)
tree6b9fae885e7c6fc46e732db201a52a5c49260947 /drivers/acpi
parentdc95a270c684e771b25dce0b60559cc80c033f22 (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>
Diffstat (limited to 'drivers/acpi')
-rw-r--r--drivers/acpi/acpica/nseval.c50
-rw-r--r--drivers/acpi/acpica/psloop.c32
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
366acpi_ns_exec_module_code(union acpi_operand_object *method_obj, 366acpi_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
89static void 89static void
90acpi_ps_link_module_code(u8 *aml_start, u32 aml_length, acpi_owner_id owner_id); 90acpi_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
613static void 618static void
614acpi_ps_link_module_code(u8 *aml_start, u32 aml_length, acpi_owner_id owner_id) 619acpi_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 {