diff options
Diffstat (limited to 'drivers/acpi/dispatcher/dsutils.c')
-rw-r--r-- | drivers/acpi/dispatcher/dsutils.c | 113 |
1 files changed, 110 insertions, 3 deletions
diff --git a/drivers/acpi/dispatcher/dsutils.c b/drivers/acpi/dispatcher/dsutils.c index d2a8cfdaec22..36518b4a79c2 100644 --- a/drivers/acpi/dispatcher/dsutils.c +++ b/drivers/acpi/dispatcher/dsutils.c | |||
@@ -472,7 +472,8 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state, | |||
472 | /* A valid name must be looked up in the namespace */ | 472 | /* A valid name must be looked up in the namespace */ |
473 | 473 | ||
474 | if ((arg->common.aml_opcode == AML_INT_NAMEPATH_OP) && | 474 | if ((arg->common.aml_opcode == AML_INT_NAMEPATH_OP) && |
475 | (arg->common.value.string)) { | 475 | (arg->common.value.string) && |
476 | !(arg->common.flags & ACPI_PARSEOP_IN_STACK)) { | ||
476 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Getting a name: Arg=%p\n", | 477 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Getting a name: Arg=%p\n", |
477 | arg)); | 478 | arg)); |
478 | 479 | ||
@@ -595,7 +596,8 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state, | |||
595 | } else { | 596 | } else { |
596 | /* Check for null name case */ | 597 | /* Check for null name case */ |
597 | 598 | ||
598 | if (arg->common.aml_opcode == AML_INT_NAMEPATH_OP) { | 599 | if ((arg->common.aml_opcode == AML_INT_NAMEPATH_OP) && |
600 | !(arg->common.flags & ACPI_PARSEOP_IN_STACK)) { | ||
599 | /* | 601 | /* |
600 | * If the name is null, this means that this is an | 602 | * If the name is null, this means that this is an |
601 | * optional result parameter that was not specified | 603 | * optional result parameter that was not specified |
@@ -617,7 +619,8 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state, | |||
617 | return_ACPI_STATUS(AE_NOT_IMPLEMENTED); | 619 | return_ACPI_STATUS(AE_NOT_IMPLEMENTED); |
618 | } | 620 | } |
619 | 621 | ||
620 | if (op_info->flags & AML_HAS_RETVAL) { | 622 | if ((op_info->flags & AML_HAS_RETVAL) |
623 | || (arg->common.flags & ACPI_PARSEOP_IN_STACK)) { | ||
621 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, | 624 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, |
622 | "Argument previously created, already stacked\n")); | 625 | "Argument previously created, already stacked\n")); |
623 | 626 | ||
@@ -759,3 +762,107 @@ acpi_ds_create_operands(struct acpi_walk_state *walk_state, | |||
759 | ACPI_EXCEPTION((AE_INFO, status, "While creating Arg %d", index)); | 762 | ACPI_EXCEPTION((AE_INFO, status, "While creating Arg %d", index)); |
760 | return_ACPI_STATUS(status); | 763 | return_ACPI_STATUS(status); |
761 | } | 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: | ||
866 | |||
867 | return_ACPI_STATUS(status); | ||
868 | } | ||