diff options
Diffstat (limited to 'drivers/acpi/dispatcher/dsutils.c')
-rw-r--r-- | drivers/acpi/dispatcher/dsutils.c | 167 |
1 files changed, 149 insertions, 18 deletions
diff --git a/drivers/acpi/dispatcher/dsutils.c b/drivers/acpi/dispatcher/dsutils.c index 71503c036f7c..b398982f0d8b 100644 --- a/drivers/acpi/dispatcher/dsutils.c +++ b/drivers/acpi/dispatcher/dsutils.c | |||
@@ -5,7 +5,7 @@ | |||
5 | ******************************************************************************/ | 5 | ******************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | 8 | * Copyright (C) 2000 - 2008, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -278,7 +278,9 @@ acpi_ds_is_result_used(union acpi_parse_object * op, | |||
278 | AML_VAR_PACKAGE_OP) | 278 | AML_VAR_PACKAGE_OP) |
279 | || (op->common.parent->common.aml_opcode == AML_BUFFER_OP) | 279 | || (op->common.parent->common.aml_opcode == AML_BUFFER_OP) |
280 | || (op->common.parent->common.aml_opcode == | 280 | || (op->common.parent->common.aml_opcode == |
281 | AML_INT_EVAL_SUBTREE_OP)) { | 281 | AML_INT_EVAL_SUBTREE_OP) |
282 | || (op->common.parent->common.aml_opcode == | ||
283 | AML_BANK_FIELD_OP)) { | ||
282 | /* | 284 | /* |
283 | * These opcodes allow term_arg(s) as operands and therefore | 285 | * These opcodes allow term_arg(s) as operands and therefore |
284 | * the operands can be method calls. The result is used. | 286 | * the operands can be method calls. The result is used. |
@@ -472,7 +474,8 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state, | |||
472 | /* A valid name must be looked up in the namespace */ | 474 | /* A valid name must be looked up in the namespace */ |
473 | 475 | ||
474 | if ((arg->common.aml_opcode == AML_INT_NAMEPATH_OP) && | 476 | if ((arg->common.aml_opcode == AML_INT_NAMEPATH_OP) && |
475 | (arg->common.value.string)) { | 477 | (arg->common.value.string) && |
478 | !(arg->common.flags & ACPI_PARSEOP_IN_STACK)) { | ||
476 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Getting a name: Arg=%p\n", | 479 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Getting a name: Arg=%p\n", |
477 | arg)); | 480 | arg)); |
478 | 481 | ||
@@ -595,7 +598,8 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state, | |||
595 | } else { | 598 | } else { |
596 | /* Check for null name case */ | 599 | /* Check for null name case */ |
597 | 600 | ||
598 | if (arg->common.aml_opcode == AML_INT_NAMEPATH_OP) { | 601 | if ((arg->common.aml_opcode == AML_INT_NAMEPATH_OP) && |
602 | !(arg->common.flags & ACPI_PARSEOP_IN_STACK)) { | ||
599 | /* | 603 | /* |
600 | * If the name is null, this means that this is an | 604 | * If the name is null, this means that this is an |
601 | * optional result parameter that was not specified | 605 | * optional result parameter that was not specified |
@@ -617,7 +621,8 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state, | |||
617 | return_ACPI_STATUS(AE_NOT_IMPLEMENTED); | 621 | return_ACPI_STATUS(AE_NOT_IMPLEMENTED); |
618 | } | 622 | } |
619 | 623 | ||
620 | if (op_info->flags & AML_HAS_RETVAL) { | 624 | if ((op_info->flags & AML_HAS_RETVAL) |
625 | || (arg->common.flags & ACPI_PARSEOP_IN_STACK)) { | ||
621 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, | 626 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, |
622 | "Argument previously created, already stacked\n")); | 627 | "Argument previously created, already stacked\n")); |
623 | 628 | ||
@@ -630,9 +635,7 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state, | |||
630 | * Use value that was already previously returned | 635 | * Use value that was already previously returned |
631 | * by the evaluation of this argument | 636 | * by the evaluation of this argument |
632 | */ | 637 | */ |
633 | status = | 638 | status = acpi_ds_result_pop(&obj_desc, walk_state); |
634 | acpi_ds_result_pop_from_bottom(&obj_desc, | ||
635 | walk_state); | ||
636 | if (ACPI_FAILURE(status)) { | 639 | if (ACPI_FAILURE(status)) { |
637 | /* | 640 | /* |
638 | * Only error is underflow, and this indicates | 641 | * Only error is underflow, and this indicates |
@@ -698,27 +701,52 @@ acpi_ds_create_operands(struct acpi_walk_state *walk_state, | |||
698 | { | 701 | { |
699 | acpi_status status = AE_OK; | 702 | acpi_status status = AE_OK; |
700 | union acpi_parse_object *arg; | 703 | union acpi_parse_object *arg; |
704 | union acpi_parse_object *arguments[ACPI_OBJ_NUM_OPERANDS]; | ||
701 | u32 arg_count = 0; | 705 | u32 arg_count = 0; |
706 | u32 index = walk_state->num_operands; | ||
707 | u32 i; | ||
702 | 708 | ||
703 | ACPI_FUNCTION_TRACE_PTR(ds_create_operands, first_arg); | 709 | ACPI_FUNCTION_TRACE_PTR(ds_create_operands, first_arg); |
704 | 710 | ||
705 | /* For all arguments in the list... */ | 711 | /* Get all arguments in the list */ |
706 | 712 | ||
707 | arg = first_arg; | 713 | arg = first_arg; |
708 | while (arg) { | 714 | while (arg) { |
709 | status = acpi_ds_create_operand(walk_state, arg, arg_count); | 715 | if (index >= ACPI_OBJ_NUM_OPERANDS) { |
710 | if (ACPI_FAILURE(status)) { | 716 | return_ACPI_STATUS(AE_BAD_DATA); |
711 | goto cleanup; | ||
712 | } | 717 | } |
713 | 718 | ||
714 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, | 719 | arguments[index] = arg; |
715 | "Arg #%d (%p) done, Arg1=%p\n", arg_count, | 720 | walk_state->operands[index] = NULL; |
716 | arg, first_arg)); | ||
717 | 721 | ||
718 | /* Move on to next argument, if any */ | 722 | /* Move on to next argument, if any */ |
719 | 723 | ||
720 | arg = arg->common.next; | 724 | arg = arg->common.next; |
721 | arg_count++; | 725 | arg_count++; |
726 | index++; | ||
727 | } | ||
728 | |||
729 | index--; | ||
730 | |||
731 | /* It is the appropriate order to get objects from the Result stack */ | ||
732 | |||
733 | for (i = 0; i < arg_count; i++) { | ||
734 | arg = arguments[index]; | ||
735 | |||
736 | /* Force the filling of the operand stack in inverse order */ | ||
737 | |||
738 | walk_state->operand_index = (u8) index; | ||
739 | |||
740 | status = acpi_ds_create_operand(walk_state, arg, index); | ||
741 | if (ACPI_FAILURE(status)) { | ||
742 | goto cleanup; | ||
743 | } | ||
744 | |||
745 | index--; | ||
746 | |||
747 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, | ||
748 | "Arg #%d (%p) done, Arg1=%p\n", index, arg, | ||
749 | first_arg)); | ||
722 | } | 750 | } |
723 | 751 | ||
724 | return_ACPI_STATUS(status); | 752 | return_ACPI_STATUS(status); |
@@ -729,9 +757,112 @@ acpi_ds_create_operands(struct acpi_walk_state *walk_state, | |||
729 | * pop everything off of the operand stack and delete those | 757 | * pop everything off of the operand stack and delete those |
730 | * objects | 758 | * objects |
731 | */ | 759 | */ |
732 | (void)acpi_ds_obj_stack_pop_and_delete(arg_count, walk_state); | 760 | acpi_ds_obj_stack_pop_and_delete(arg_count, walk_state); |
761 | |||
762 | ACPI_EXCEPTION((AE_INFO, status, "While creating Arg %d", index)); | ||
763 | return_ACPI_STATUS(status); | ||
764 | } | ||
765 | |||
766 | /***************************************************************************** | ||
767 | * | ||
768 | * FUNCTION: acpi_ds_evaluate_name_path | ||
769 | * | ||
770 | * PARAMETERS: walk_state - Current state of the parse tree walk, | ||
771 | * the opcode of current operation should be | ||
772 | * AML_INT_NAMEPATH_OP | ||
773 | * | ||
774 | * RETURN: Status | ||
775 | * | ||
776 | * DESCRIPTION: Translate the -name_path- parse tree object to the equivalent | ||
777 | * interpreter object, convert it to value, if needed, duplicate | ||
778 | * it, if needed, and push it onto the current result stack. | ||
779 | * | ||
780 | ****************************************************************************/ | ||
781 | |||
782 | acpi_status acpi_ds_evaluate_name_path(struct acpi_walk_state *walk_state) | ||
783 | { | ||
784 | acpi_status status = AE_OK; | ||
785 | union acpi_parse_object *op = walk_state->op; | ||
786 | union acpi_operand_object **operand = &walk_state->operands[0]; | ||
787 | union acpi_operand_object *new_obj_desc; | ||
788 | u8 type; | ||
789 | |||
790 | ACPI_FUNCTION_TRACE_PTR(ds_evaluate_name_path, walk_state); | ||
791 | |||
792 | if (!op->common.parent) { | ||
793 | |||
794 | /* This happens after certain exception processing */ | ||
795 | |||
796 | goto exit; | ||
797 | } | ||
798 | |||
799 | if ((op->common.parent->common.aml_opcode == AML_PACKAGE_OP) || | ||
800 | (op->common.parent->common.aml_opcode == AML_VAR_PACKAGE_OP) || | ||
801 | (op->common.parent->common.aml_opcode == AML_REF_OF_OP)) { | ||
802 | |||
803 | /* TBD: Should we specify this feature as a bit of op_info->Flags of these opcodes? */ | ||
804 | |||
805 | goto exit; | ||
806 | } | ||
807 | |||
808 | status = acpi_ds_create_operand(walk_state, op, 0); | ||
809 | if (ACPI_FAILURE(status)) { | ||
810 | goto exit; | ||
811 | } | ||
812 | |||
813 | if (op->common.flags & ACPI_PARSEOP_TARGET) { | ||
814 | new_obj_desc = *operand; | ||
815 | goto push_result; | ||
816 | } | ||
817 | |||
818 | type = ACPI_GET_OBJECT_TYPE(*operand); | ||
819 | |||
820 | status = acpi_ex_resolve_to_value(operand, walk_state); | ||
821 | if (ACPI_FAILURE(status)) { | ||
822 | goto exit; | ||
823 | } | ||
824 | |||
825 | if (type == ACPI_TYPE_INTEGER) { | ||
826 | |||
827 | /* It was incremented by acpi_ex_resolve_to_value */ | ||
828 | |||
829 | acpi_ut_remove_reference(*operand); | ||
830 | |||
831 | status = | ||
832 | acpi_ut_copy_iobject_to_iobject(*operand, &new_obj_desc, | ||
833 | walk_state); | ||
834 | if (ACPI_FAILURE(status)) { | ||
835 | goto exit; | ||
836 | } | ||
837 | } else { | ||
838 | /* | ||
839 | * The object either was anew created or is | ||
840 | * a Namespace node - don't decrement it. | ||
841 | */ | ||
842 | new_obj_desc = *operand; | ||
843 | } | ||
844 | |||
845 | /* Cleanup for name-path operand */ | ||
846 | |||
847 | status = acpi_ds_obj_stack_pop(1, walk_state); | ||
848 | if (ACPI_FAILURE(status)) { | ||
849 | walk_state->result_obj = new_obj_desc; | ||
850 | goto exit; | ||
851 | } | ||
852 | |||
853 | push_result: | ||
854 | |||
855 | walk_state->result_obj = new_obj_desc; | ||
856 | |||
857 | status = acpi_ds_result_push(walk_state->result_obj, walk_state); | ||
858 | if (ACPI_SUCCESS(status)) { | ||
859 | |||
860 | /* Force to take it from stack */ | ||
861 | |||
862 | op->common.flags |= ACPI_PARSEOP_IN_STACK; | ||
863 | } | ||
864 | |||
865 | exit: | ||
733 | 866 | ||
734 | ACPI_EXCEPTION((AE_INFO, status, "While creating Arg %d", | ||
735 | (arg_count + 1))); | ||
736 | return_ACPI_STATUS(status); | 867 | return_ACPI_STATUS(status); |
737 | } | 868 | } |